diff --git a/packages/async/webda.module.json b/packages/async/webda.module.json index f171536e9..d1f6da5f4 100644 --- a/packages/async/webda.module.json +++ b/packages/async/webda.module.json @@ -380,7 +380,7 @@ "properties": { "writable": { "type": "boolean", - "description": "Is `true` if it is safe to call `writable.write()`, which means the stream has not been destroyed, errored or ended." + "description": "Is `true` if it is safe to call `writable.write()`, which means the stream has not been destroyed, errored, or ended." }, "writableEnded": { "type": "boolean", @@ -412,7 +412,7 @@ }, "closed": { "type": "boolean", - "description": "Is true after 'close' has been emitted." + "description": "Is `true` after `'close'` has been emitted." }, "errored": { "anyOf": [ @@ -442,7 +442,7 @@ }, "writableNeedDrain": { "type": "boolean", - "description": "Is `true` if the stream's buffer has been full and stream will emit 'drain'." + "description": "Is `true` if the stream's buffer has been full and stream will emit `'drain'`." } }, "required": [ @@ -756,7 +756,7 @@ }, "hostname": { "type": "string", - "description": "Gets and sets the host name portion of the URL. The key difference between`url.host` and `url.hostname` is that `url.hostname` does _not_ include the port.\n\n```js const myURL = new URL('https://example.org:81/foo'); console.log(myURL.hostname); // Prints example.org\n\n// Setting the hostname does not change the port myURL.hostname = 'example.com:82'; console.log(myURL.href); // Prints https://example.com:81/foo\n\n// Use myURL.host to change the hostname and port myURL.host = 'example.org:82'; console.log(myURL.href); // Prints https://example.org:82/foo ```\n\nInvalid host name values assigned to the `hostname` property are ignored." + "description": "Gets and sets the host name portion of the URL. The key difference between`url.host` and `url.hostname` is that `url.hostname` does _not_ include the port.\n\n```js const myURL = new URL('https://example.org:81/foo'); console.log(myURL.hostname); // Prints example.org\n\n// Setting the hostname does not change the port myURL.hostname = 'example.com'; console.log(myURL.href); // Prints https://example.com:81/foo\n\n// Use myURL.host to change the hostname and port myURL.host = 'example.org:82'; console.log(myURL.href); // Prints https://example.org:82/foo ```\n\nInvalid host name values assigned to the `hostname` property are ignored." }, "href": { "type": "string", @@ -768,7 +768,7 @@ }, "password": { "type": "string", - "description": "Gets and sets the password portion of the URL.\n\n```js const myURL = new URL('https://abc:xyz@example.com'); console.log(myURL.password); // Prints xyz\n\nmyURL.password = '123'; console.log(myURL.href); // Prints https://abc:123@example.com ```\n\nInvalid URL characters included in the value assigned to the `password` property are `percent-encoded`. The selection of which characters to percent-encode may vary somewhat from what the {@link parse } and {@link format } methods would produce." + "description": "Gets and sets the password portion of the URL.\n\n```js const myURL = new URL('https://abc:xyz@example.com'); console.log(myURL.password); // Prints xyz\n\nmyURL.password = '123'; console.log(myURL.href); // Prints https://abc:123@example.com/ ```\n\nInvalid URL characters included in the value assigned to the `password` property are `percent-encoded`. The selection of which characters to percent-encode may vary somewhat from what the {@link parse } and {@link format } methods would produce." }, "pathname": { "type": "string", @@ -797,7 +797,7 @@ "required": [ "size" ], - "description": "Gets the `URLSearchParams` object representing the query parameters of the URL. This property is read-only but the `URLSearchParams` object it provides can be used to mutate the URL instance; to replace the entirety of query parameters of the URL, use the {@link search } setter. See `URLSearchParams` documentation for details.\n\nUse care when using `.searchParams` to modify the `URL` because, per the WHATWG specification, the `URLSearchParams` object uses different rules to determine which characters to percent-encode. For instance, the `URL` object will not percent encode the ASCII tilde (`~`) character, while `URLSearchParams` will always encode it:\n\n```js const myUrl = new URL('https://example.org/abc?foo=~bar');\n\nconsole.log(myUrl.search); // prints ?foo=~bar\n\n// Modify the URL via searchParams... myUrl.searchParams.sort();\n\nconsole.log(myUrl.search); // prints ?foo=%7Ebar ```" + "description": "Gets the `URLSearchParams` object representing the query parameters of the URL. This property is read-only but the `URLSearchParams` object it provides can be used to mutate the URL instance; to replace the entirety of query parameters of the URL, use the {@link search } setter. See `URLSearchParams` documentation for details.\n\nUse care when using `.searchParams` to modify the `URL` because, per the WHATWG specification, the `URLSearchParams` object uses different rules to determine which characters to percent-encode. For instance, the `URL` object will not percent encode the ASCII tilde (`~`) character, while `URLSearchParams` will always encode it:\n\n```js const myURL = new URL('https://example.org/abc?foo=~bar');\n\nconsole.log(myURL.search); // prints ?foo=~bar\n\n// Modify the URL via searchParams... myURL.searchParams.sort();\n\nconsole.log(myURL.search); // prints ?foo=%7Ebar ```" }, "username": { "type": "string", @@ -839,9 +839,7 @@ "type": "string" }, "stdio": { - "$ref": "#/definitions/StdioOptions", - "description": "Can be set to 'pipe', 'inherit', 'overlapped', or 'ignore', or an array of these strings. If passed as an array, the first element is used for `stdin`, the second for `stdout`, and the third for `stderr`. A fourth element can be used to specify the `stdio` behavior beyond the standard streams. See {@link ChildProcess.stdio } for more information.", - "default": "pipe" + "$ref": "#/definitions/StdioOptions" }, "shell": { "type": [ diff --git a/packages/aws/package.json b/packages/aws/package.json index c4326544b..cd7e5416d 100644 --- a/packages/aws/package.json +++ b/packages/aws/package.json @@ -56,7 +56,7 @@ "@webda/workout": "^4.0.0-beta.1", "bluebird": "^3.7.2", "commitlint": "^19.2.1", - "cookie": "^0.6.0", + "cookie": "^1.0.1", "glob": "^10.0.0", "iam-policy-optimizer": "^1.2.0", "mime-types": "^2.1.35", diff --git a/packages/core/package.json b/packages/core/package.json index 9955df432..e4b166d07 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -33,9 +33,9 @@ "ajv-formats": "^3.0.1", "antlr4ts": "^0.5.0-alpha.4", "bcryptjs": "^2.4.3", - "cookie": "^0.6.0", + "cookie": "^1.0.1", "dateformat": "^5.0.3", - "deepmerge-ts": "^5.1.0", + "deepmerge-ts": "^7.1.3", "email-templates": "^12.0.1", "glob": "^10.0.0", "global": "^4.4.0", diff --git a/packages/core/src/rest/restdomainservice.ts b/packages/core/src/rest/restdomainservice.ts index 856c32431..d09f2a815 100644 --- a/packages/core/src/rest/restdomainservice.ts +++ b/packages/core/src/rest/restdomainservice.ts @@ -1,8 +1,10 @@ +import { QueryValidator } from "@webda/ql"; import { CoreModelDefinition, ModelAction } from "../models/coremodel"; import { DomainServiceParameters, ModelsOperationsService } from "../services/domainservice"; import { DeepPartial } from "../services/service"; import { WebContext } from "../utils/context"; import { OpenAPIWebdaDefinition } from "./router"; +import { WebdaError } from "../index"; /** * Swagger static html @@ -203,23 +205,26 @@ export class RESTDomainService< `${prefix}${this.parameters.queryMethod === "GET" ? "{?q?}" : ""}`, [this.parameters.queryMethod], async (context: WebContext) => { - let query = ""; + let queryString = ""; const parentId = `pid.${depth - 1}`; if (context.getHttpContext().getMethod() === "PUT") { - query = (await context.getInput()).q ?? ""; + queryString = (await context.getInput()).q ?? ""; context.clearInput(); } else { - query = context.parameter("q", ""); + queryString = context.parameter("q", ""); } + let query: QueryValidator; + try { + query = new QueryValidator(queryString); + } catch (err) { + throw new WebdaError.BadRequest(`Invalid query ${queryString}`); + } + // Inject parent attribute if (injectAttribute) { - if (query.trim() === "") { - query = `${injectAttribute} = '${context.parameter(parentId)}'`; - } else { - query = `${injectAttribute} = '${context.parameter(parentId)}' AND (${query})`; - } + query.merge(`${injectAttribute} = '${context.parameter(parentId)}'`); } - context.getParameters().query = query; + context.getParameters().query = query.toString(); return this._webda.callOperation(context, `${plurial}.Query`); }, openapi diff --git a/packages/core/src/services/domainservice.spec.ts b/packages/core/src/services/domainservice.spec.ts index 225853dcc..6b66fafd0 100644 --- a/packages/core/src/services/domainservice.spec.ts +++ b/packages/core/src/services/domainservice.spec.ts @@ -232,10 +232,37 @@ class DomainServiceTest extends WebdaTest { }, context }); + // We have 5 items so 5+4+3+2+1=15 assert.strictEqual( result.results.reduce((total, u) => parseInt(u.name.substring(5)) + total, 0), 15 ); + result = await this.http({ + method: "PUT", + url: `/companies/${companies[0].uuid}/users`, + body: { + q: "LIMIT 3" + }, + context + }); + // We have 3 items so 3+2+1=6 + assert.strictEqual( + result.results.reduce((total, u) => parseInt(u.name.substring(5)) + total, 0), + 6 + ); + result = await this.http({ + method: "PUT", + url: `/companies/${companies[0].uuid}/users`, + body: { + q: `LIMIT 2 OFFSET "${result.continuationToken}"` + }, + context + }); + // We should only have 2 items starting from 4 + assert.strictEqual( + result.results.reduce((total, u) => parseInt(u.name.substring(5)) + total, 0), + 9 + ); result = await this.http({ method: "PUT", url: `/companies/${companies[1].uuid}/users`, @@ -244,6 +271,18 @@ class DomainServiceTest extends WebdaTest { }, context }); + await assert.rejects( + () => + this.http({ + method: "PUT", + url: `/companies/${companies[1].uuid}/users`, + body: { + q: "invalid query" + }, + context + }), + WebdaError.BadRequest + ); assert.strictEqual( result.results.reduce((total, u) => parseInt(u.name.substring(5)) + total, 0), 40 diff --git a/packages/core/src/unpackedapplication.ts b/packages/core/src/unpackedapplication.ts index 69635c3df..d649b47e2 100644 --- a/packages/core/src/unpackedapplication.ts +++ b/packages/core/src/unpackedapplication.ts @@ -12,6 +12,7 @@ import { UnpackedConfiguration } from "./application"; import { FileUtils } from "./utils/serializers"; +import { join } from "path"; /** * Empty git information @@ -218,6 +219,53 @@ export class UnpackedApplication extends Application { return cacheModules; } + /** + * Search the node_modules structure for webda.module.json files + * + * @param path + * @returns + */ + static findModulesFiles(path: string): string[] { + if (!path.endsWith("node_modules") || !fs.existsSync(path)) { + return []; + } + const files = new Set(); + const checkFolder = (filepath: string) => { + if (fs.existsSync(join(filepath, "webda.module.json"))) { + files.add(join(filepath, "webda.module.json")); + } + if (fs.existsSync(join(filepath, "node_modules"))) { + this.findModulesFiles(join(filepath, "node_modules")).forEach(f => files.add(f)); + } + }; + const recursiveSearch = (dirpath: string, depth: number = 0) => { + fs.readdirSync(dirpath, { withFileTypes: true }).forEach(file => { + if (file.name.startsWith(".")) { + return; + } + const filepath = join(dirpath, file.name); + if (file.isDirectory() && file.name.startsWith("@") && depth === 0) { + // One recursion + recursiveSearch(filepath, depth + 1); + } else if (file.isDirectory()) { + checkFolder(filepath); + } else if (file.isSymbolicLink()) { + // We want to follow symbolic links w/o increasing depth + let realPath; + try { + // realpathSync will throw if the symlink is broken + realPath = fs.realpathSync(filepath); + } catch (err) { + return; + } + checkFolder(realPath); + } + }); + }; + recursiveSearch(path, 0); + return [...files]; + } + /** * Load all imported modules and current module * It will compile module @@ -239,27 +287,12 @@ export class UnpackedApplication extends Application { files.push(currentModule); } - const findModuleFiles = (nodeModules: string): void => { - if (!fs.existsSync(nodeModules)) { - return; - } - FileUtils.walkSync( - nodeModules, - filepath => { - // We filter out the cache of nx - // If it is inside a node_modules/. we consider it should not be checked - if (filepath.endsWith("webda.module.json") && !filepath.includes("node_modules/.")) { - files.push(filepath); - } - }, - { followSymlinks: true } - ); - }; - - findModuleFiles(this.getAppPath("node_modules")); + UnpackedApplication.findModulesFiles(this.getAppPath("node_modules")).forEach(f => files.push(f)); // Search workspace for webda.module.json if (module.project.webda.workspaces && module.project.webda.workspaces.path !== "") { - findModuleFiles(path.join(module.project.webda.workspaces.path, "node_modules")); + UnpackedApplication.findModulesFiles(path.join(module.project.webda.workspaces.path, "node_modules")).forEach(f => + files.push(f) + ); } // Ensure we are not adding many times the same modules diff --git a/packages/core/src/utils/context.spec.ts b/packages/core/src/utils/context.spec.ts index 0a472bc85..1165aba19 100644 --- a/packages/core/src/utils/context.spec.ts +++ b/packages/core/src/utils/context.spec.ts @@ -232,10 +232,14 @@ class ContextTest extends WebdaTest { cookie: "PHPSESSID=298zf09hf012fh2; csrftoken=u32t4o3tb3gg43; _gat=1" }); assert.strictEqual(ctx.getAbsoluteUrl("/test"), "http://test.webda.io/test"); - assert.deepStrictEqual(ctx.getCookies(), { + const cookies = ctx.getCookies(); + const valid = { PHPSESSID: "298zf09hf012fh2", csrftoken: "u32t4o3tb3gg43", _gat: "1" + }; + Object.keys(cookies).forEach(key => { + assert.deepEqual(cookies[key], valid[key]); }); ctx = new HttpContext("test.webda.io", "GET", "/uritemplate/plop", "https", 80); assert.strictEqual(ctx.getAbsoluteUrl(), "https://test.webda.io:80/uritemplate/plop"); diff --git a/packages/core/src/utils/cookie.ts b/packages/core/src/utils/cookie.ts index 9d5fdbbf2..e5ed254a8 100644 --- a/packages/core/src/utils/cookie.ts +++ b/packages/core/src/utils/cookie.ts @@ -1,4 +1,4 @@ -import { CookieSerializeOptions, serialize as cookieSerialize } from "cookie"; +import { type SerializeOptions, serialize as cookieSerialize } from "cookie"; import { JWTOptions } from "../services/cryptoservice"; import { WebContext } from "./context"; import { HttpContext } from "./httpcontext"; @@ -12,7 +12,7 @@ const SPLIT = 4096; /** * Cookie Options */ -export class CookieOptions implements Omit { +export class CookieOptions implements Omit { /** * @default lax */ @@ -164,7 +164,7 @@ export class SecureCookie { name ??= "webda"; let cookieName = name; let limit; - const mapLength = cookieSerialize(name, "", params).length; + const mapLength = cookieSerialize(name, "", params).length; for (let i = 0; i < value.length; ) { limit = SPLIT - mapLength; if (j > 1) { diff --git a/packages/core/webda.module.json b/packages/core/webda.module.json index 4112bc9cb..c8fabc69e 100644 --- a/packages/core/webda.module.json +++ b/packages/core/webda.module.json @@ -844,39 +844,64 @@ "cookie": { "type": "object", "properties": { - "sameSite": { - "type": "string", - "enum": [ - "none", - "strict", - "lax" - ], - "default": "lax" - }, - "domain": { - "type": "boolean", - "enum": [ - true - ], - "description": "if true domain will be set to the request hostname if undefined no domain will be output (browser will use the current domain and only this one) if a string is provided it will be used as the domain\n\nWhen provided a domain is setting the cookie to be available to all subdomains" + "encode": { + "description": "Specifies a function that will be used to encode a [cookie-value](https://datatracker.ietf.org/doc/html/rfc6265#section-4.1.1). Since value of a cookie has a limited character set (and must be a simple string), this function can be used to encode a value into a string suited for a cookie's value, and should mirror `decode` when parsing.", + "default": "encodeURIComponent" }, "maxAge": { "type": "number", + "description": "Specifies the `number` (in seconds) to be the value for the [`Max-Age` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.2).\n\nThe [cookie storage model specification](https://tools.ietf.org/html/rfc6265#section-5.3) states that if both `expires` and `maxAge` are set, then `maxAge` takes precedence, but it is possible not all clients by obey this, so if both are set, they should point to the same date and time.", "minimum": 1, "default": "86400 * 7" }, + "expires": { + "type": "string", + "description": "Specifies the `Date` object to be the value for the [`Expires` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.1). When no expiration is set clients consider this a \"non-persistent cookie\" and delete it the current session is over.\n\nThe [cookie storage model specification](https://tools.ietf.org/html/rfc6265#section-5.3) states that if both `expires` and `maxAge` are set, then `maxAge` takes precedence, but it is possible not all clients by obey this, so if both are set, they should point to the same date and time." + }, "path": { "type": "string", + "description": "Specifies the value for the [`Path` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.4). When no path is set, the path is considered the [\"default path\"](https://tools.ietf.org/html/rfc6265#section-5.1.4).", "default": "/" }, "httpOnly": { "type": "boolean", + "description": "Enables the [`HttpOnly` `Set-Cookie` attribute](https://tools.ietf.org/html/rfc6265#section-5.2.6). When enabled, clients will not allow client-side JavaScript to see the cookie in `document.cookie`.", "default": true }, "secure": { "type": "boolean", "description": "If not set will be true if https request and false otherwise If defined it will be set to the value" }, + "partitioned": { + "type": "boolean", + "description": "Enables the [`Partitioned` `Set-Cookie` attribute](https://tools.ietf.org/html/draft-cutler-httpbis-partitioned-cookies/). When enabled, clients will only send the cookie back when the current domain _and_ top-level domain matches.\n\nThis is an attribute that has not yet been fully standardized, and may change in the future. This also means clients may ignore this attribute until they understand it. More information about can be found in [the proposal](https://github.com/privacycg/CHIPS)." + }, + "priority": { + "type": "string", + "enum": [ + "low", + "medium", + "high" + ], + "description": "Specifies the value for the [`Priority` `Set-Cookie` attribute](https://tools.ietf.org/html/draft-west-cookie-priority-00#section-4.1).\n\n- `'low'` will set the `Priority` attribute to `Low`.\n- `'medium'` will set the `Priority` attribute to `Medium`, the default priority when not set.\n- `'high'` will set the `Priority` attribute to `High`.\n\nMore information about priority levels can be found in [the specification](https://tools.ietf.org/html/draft-west-cookie-priority-00#section-4.1)." + }, + "sameSite": { + "type": "string", + "enum": [ + "none", + "strict", + "lax" + ], + "description": "Specifies the value for the [`SameSite` `Set-Cookie` attribute](https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-09#section-5.4.7).\n\n- `true` will set the `SameSite` attribute to `Strict` for strict same site enforcement.\n- `'lax'` will set the `SameSite` attribute to `Lax` for lax same site enforcement.\n- `'none'` will set the `SameSite` attribute to `None` for an explicit cross-site cookie.\n- `'strict'` will set the `SameSite` attribute to `Strict` for strict same site enforcement.\n\nMore information about enforcement levels can be found in [the specification](https://tools.ietf.org/html/draft-ietf-httpbis-rfc6265bis-09#section-5.4.7).", + "default": "lax" + }, + "domain": { + "type": "boolean", + "enum": [ + true + ], + "description": "if true domain will be set to the request hostname if undefined no domain will be output (browser will use the current domain and only this one) if a string is provided it will be used as the domain\n\nWhen provided a domain is setting the cookie to be available to all subdomains" + }, "name": { "type": "string", "description": "Name of the cookie" @@ -2384,6 +2409,16 @@ "description": "Cache control header to set", "default": "public, max-age=31536000" }, + "indexCacheControl": { + "type": "string", + "description": "Cache control for index file SPA usually do not cache the index file", + "default": "no-cache, no-store, must-revalidate" + }, + "allowHiddenFiles": { + "type": "boolean", + "description": "Serve also . prefixed files . files usually have some secrets and should not be served", + "default": false + }, "openapi": { "type": "object", "additionalProperties": true diff --git a/packages/graphql/src/graphql.ts b/packages/graphql/src/graphql.ts index 411b34bda..8dccab765 100644 --- a/packages/graphql/src/graphql.ts +++ b/packages/graphql/src/graphql.ts @@ -469,7 +469,7 @@ export class GraphQLService ext } }); } - if ((await modelInstance.canAct(context, "get")) !== true) { + if ((await modelInstance?.canAct(context, "get")) !== true) { throw new GraphQLError("Permission denied", { extensions: { code: "PERMISSION_DENIED" @@ -560,7 +560,7 @@ export class GraphQLService ext resolve: async (_, args, context) => { const object = new model().load(args[name]); this.log("INFO", "Create", object, context.getCurrentUserId()); - if ((await object.canAct(context, "create")) !== true) { + if ((await object?.canAct(context, "create")) !== true) { throw new GraphQLError("Permission denied", { extensions: { code: "PERMISSION_DENIED" @@ -912,7 +912,7 @@ export class GraphQLService ext }, "Store.Saved": async evt => { // If object match the query and is not in the result and can be read by the user - if (queryInfo.eval(evt.object) && !queryInfo.getOffset() && evt.object.canAct(context, "get")) { + if (queryInfo.eval(evt.object) && !queryInfo.getOffset() && evt.object?.canAct(context, "get")) { // Should check with the order by of the query to see if we need to recompute result = await model.query(query, true, context); return result; diff --git a/packages/postgres/webda.module.json b/packages/postgres/webda.module.json index cd0b08436..bd2cf8627 100644 --- a/packages/postgres/webda.module.json +++ b/packages/postgres/webda.module.json @@ -161,7 +161,7 @@ "properties": { "writable": { "type": "boolean", - "description": "Is `true` if it is safe to call `writable.write()`, which means the stream has not been destroyed, errored or ended." + "description": "Is `true` if it is safe to call `writable.write()`, which means the stream has not been destroyed, errored, or ended." }, "writableEnded": { "type": "boolean", @@ -193,7 +193,7 @@ }, "closed": { "type": "boolean", - "description": "Is true after 'close' has been emitted." + "description": "Is `true` after `'close'` has been emitted." }, "errored": { "anyOf": [ @@ -223,7 +223,7 @@ }, "writableNeedDrain": { "type": "boolean", - "description": "Is `true` if the stream's buffer has been full and stream will emit 'drain'." + "description": "Is `true` if the stream's buffer has been full and stream will emit `'drain'`." }, "readable": { "type": "boolean", @@ -273,7 +273,7 @@ }, "allowHalfOpen": { "type": "boolean", - "description": "If `false` then the stream will automatically end the writable side when the readable side ends. Set initially by the `allowHalfOpen` constructor option, which defaults to `false`.\n\nThis can be changed manually to change the half-open behavior of an existing`Duplex` stream instance, but must be changed before the `'end'` event is emitted." + "description": "If `false` then the stream will automatically end the writable side when the readable side ends. Set initially by the `allowHalfOpen` constructor option, which defaults to `true`.\n\nThis can be changed manually to change the half-open behavior of an existing`Duplex` stream instance, but must be changed before the `'end'` event is emitted." } }, "required": [ @@ -424,9 +424,6 @@ "description": "If true the server will reject any connection which is not authorized with the list of supplied CAs. This option only has an effect if requestCert is true.", "default": true }, - "ALPNCallback": { - "description": "If set, this will be called when a client opens a connection using the ALPN extension. One argument will be passed to the callback: an object containing `servername` and `protocols` fields, respectively containing the server name from the SNI extension (if any) and an array of ALPN protocol name strings. The callback must return either one of the strings listed in `protocols`, which will be returned to the client as the selected ALPN protocol, or `undefined`, to reject the connection with a fatal alert. If a string is returned that does not match one of the client's ALPN protocols, an error will be thrown. This option cannot be used with the `ALPNProtocols` option, and setting both options will throw an error." - }, "ca": { "anyOf": [ { @@ -1014,7 +1011,7 @@ "properties": { "writable": { "type": "boolean", - "description": "Is `true` if it is safe to call `writable.write()`, which means the stream has not been destroyed, errored or ended." + "description": "Is `true` if it is safe to call `writable.write()`, which means the stream has not been destroyed, errored, or ended." }, "writableEnded": { "type": "boolean", @@ -1046,7 +1043,7 @@ }, "closed": { "type": "boolean", - "description": "Is true after 'close' has been emitted." + "description": "Is `true` after `'close'` has been emitted." }, "errored": { "anyOf": [ @@ -1076,7 +1073,7 @@ }, "writableNeedDrain": { "type": "boolean", - "description": "Is `true` if the stream's buffer has been full and stream will emit 'drain'." + "description": "Is `true` if the stream's buffer has been full and stream will emit `'drain'`." }, "readable": { "type": "boolean", @@ -1126,7 +1123,7 @@ }, "allowHalfOpen": { "type": "boolean", - "description": "If `false` then the stream will automatically end the writable side when the readable side ends. Set initially by the `allowHalfOpen` constructor option, which defaults to `false`.\n\nThis can be changed manually to change the half-open behavior of an existing`Duplex` stream instance, but must be changed before the `'end'` event is emitted." + "description": "If `false` then the stream will automatically end the writable side when the readable side ends. Set initially by the `allowHalfOpen` constructor option, which defaults to `true`.\n\nThis can be changed manually to change the half-open behavior of an existing`Duplex` stream instance, but must be changed before the `'end'` event is emitted." } }, "required": [ @@ -1260,7 +1257,7 @@ "properties": { "writable": { "type": "boolean", - "description": "Is `true` if it is safe to call `writable.write()`, which means the stream has not been destroyed, errored or ended." + "description": "Is `true` if it is safe to call `writable.write()`, which means the stream has not been destroyed, errored, or ended." }, "writableEnded": { "type": "boolean", @@ -1292,7 +1289,7 @@ }, "closed": { "type": "boolean", - "description": "Is true after 'close' has been emitted." + "description": "Is `true` after `'close'` has been emitted." }, "errored": { "anyOf": [ @@ -1322,7 +1319,7 @@ }, "writableNeedDrain": { "type": "boolean", - "description": "Is `true` if the stream's buffer has been full and stream will emit 'drain'." + "description": "Is `true` if the stream's buffer has been full and stream will emit `'drain'`." }, "readable": { "type": "boolean", @@ -1372,7 +1369,7 @@ }, "allowHalfOpen": { "type": "boolean", - "description": "If `false` then the stream will automatically end the writable side when the readable side ends. Set initially by the `allowHalfOpen` constructor option, which defaults to `false`.\n\nThis can be changed manually to change the half-open behavior of an existing`Duplex` stream instance, but must be changed before the `'end'` event is emitted." + "description": "If `false` then the stream will automatically end the writable side when the readable side ends. Set initially by the `allowHalfOpen` constructor option, which defaults to `true`.\n\nThis can be changed manually to change the half-open behavior of an existing`Duplex` stream instance, but must be changed before the `'end'` event is emitted." } }, "required": [ @@ -1523,9 +1520,6 @@ "description": "If true the server will reject any connection which is not authorized with the list of supplied CAs. This option only has an effect if requestCert is true.", "default": true }, - "ALPNCallback": { - "description": "If set, this will be called when a client opens a connection using the ALPN extension. One argument will be passed to the callback: an object containing `servername` and `protocols` fields, respectively containing the server name from the SNI extension (if any) and an array of ALPN protocol name strings. The callback must return either one of the strings listed in `protocols`, which will be returned to the client as the selected ALPN protocol, or `undefined`, to reject the connection with a fatal alert. If a string is returned that does not match one of the client's ALPN protocols, an error will be thrown. This option cannot be used with the `ALPNProtocols` option, and setting both options will throw an error." - }, "ca": { "anyOf": [ { @@ -2113,7 +2107,7 @@ "properties": { "writable": { "type": "boolean", - "description": "Is `true` if it is safe to call `writable.write()`, which means the stream has not been destroyed, errored or ended." + "description": "Is `true` if it is safe to call `writable.write()`, which means the stream has not been destroyed, errored, or ended." }, "writableEnded": { "type": "boolean", @@ -2145,7 +2139,7 @@ }, "closed": { "type": "boolean", - "description": "Is true after 'close' has been emitted." + "description": "Is `true` after `'close'` has been emitted." }, "errored": { "anyOf": [ @@ -2175,7 +2169,7 @@ }, "writableNeedDrain": { "type": "boolean", - "description": "Is `true` if the stream's buffer has been full and stream will emit 'drain'." + "description": "Is `true` if the stream's buffer has been full and stream will emit `'drain'`." }, "readable": { "type": "boolean", @@ -2225,7 +2219,7 @@ }, "allowHalfOpen": { "type": "boolean", - "description": "If `false` then the stream will automatically end the writable side when the readable side ends. Set initially by the `allowHalfOpen` constructor option, which defaults to `false`.\n\nThis can be changed manually to change the half-open behavior of an existing`Duplex` stream instance, but must be changed before the `'end'` event is emitted." + "description": "If `false` then the stream will automatically end the writable side when the readable side ends. Set initially by the `allowHalfOpen` constructor option, which defaults to `true`.\n\nThis can be changed manually to change the half-open behavior of an existing`Duplex` stream instance, but must be changed before the `'end'` event is emitted." } }, "required": [ diff --git a/packages/runtime/package.json b/packages/runtime/package.json index 7f29768cf..6592877a9 100644 --- a/packages/runtime/package.json +++ b/packages/runtime/package.json @@ -28,9 +28,9 @@ "ajv-formats": "^3.0.1", "antlr4ts": "^0.5.0-alpha.4", "bcryptjs": "^2.4.3", - "cookie": "^0.6.0", + "cookie": "^1.0.1", "dateformat": "^5.0.3", - "deepmerge-ts": "^5.1.0", + "deepmerge-ts": "^7.1.3", "email-templates": "^12.0.1", "glob": "^10.0.0", "global": "^4.4.0", diff --git a/packages/shell/package.json b/packages/shell/package.json index d827d4b8c..c13054838 100644 --- a/packages/shell/package.json +++ b/packages/shell/package.json @@ -42,7 +42,7 @@ "@webda/workout": "^4.0.0-beta.1", "archiver": "^7.0.1", "chalk": "^5.0.1", - "cookie": "^0.6.0", + "cookie": "^1.0.1", "dateformat": "^5.0.3", "fs-extra": "^11.0.0", "generator-webda": "^1.2.0", diff --git a/sample-app/webda.module.json b/sample-app/webda.module.json index ff83f2631..b019ff52c 100644 --- a/sample-app/webda.module.json +++ b/sample-app/webda.module.json @@ -704,7 +704,7 @@ "type": "string" }, "interfaceParam": { - "$ref": "#/definitions/Partial%3Cinterface-829200435-246-294-829200435-0-1238%3E", + "$ref": "#/definitions/Partial%3Cinterface-1076421816-246-294-1076421816-0-1238%3E", "description": "The Partial will generate a new $ref" }, "openapi": { @@ -719,7 +719,7 @@ ], "$schema": "http://json-schema.org/draft-07/schema#", "definitions": { - "Partial": { + "Partial": { "type": "object", "properties": { "test": { @@ -1325,7 +1325,7 @@ "description": "URL on which to serve the content" }, "introspection": { - "$ref": "#/definitions/Partial%3Cclass-1131383939-2740-3224-1131383939-0-9466976353190%3E" + "$ref": "#/definitions/Partial%3Cclass-178760925-2740-3224-178760925-0-9466976353190%3E" }, "openapi": { "type": "object", @@ -1338,7 +1338,7 @@ ], "$schema": "http://json-schema.org/draft-07/schema#", "definitions": { - "Partial": { + "Partial": { "type": "object", "properties": { "type": { @@ -1369,7 +1369,7 @@ "type": "string" }, "interfaceParam": { - "$ref": "#/definitions/Partial%3Cinterface-829200435-246-294-829200435-0-1238%3E", + "$ref": "#/definitions/Partial%3Cinterface-1076421816-246-294-1076421816-0-1238%3E", "description": "The Partial will generate a new $ref" }, "fourthParameter": { @@ -1390,7 +1390,7 @@ ], "$schema": "http://json-schema.org/draft-07/schema#", "definitions": { - "Partial": { + "Partial": { "type": "object", "properties": { "test": { @@ -1601,7 +1601,7 @@ "type": "string" }, "interfaceParam": { - "$ref": "#/definitions/Partial%3Cinterface-829200435-246-294-829200435-0-1238%3E", + "$ref": "#/definitions/Partial%3Cinterface-1076421816-246-294-1076421816-0-1238%3E", "description": "The Partial will generate a new $ref" }, "openapi": { @@ -1616,7 +1616,7 @@ ], "$schema": "http://json-schema.org/draft-07/schema#", "definitions": { - "Partial": { + "Partial": { "type": "object", "properties": { "test": {