@selvajs/server 1.0.0-beta.8 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +18 -20
- package/dist/access/project-access-input.d.ts +13 -16
- package/dist/access/project-access-input.d.ts.map +1 -1
- package/dist/access/project-access-input.js +2 -2
- package/dist/access/project-access-input.js.map +1 -1
- package/dist/compute/idempotency.d.ts +18 -22
- package/dist/compute/idempotency.d.ts.map +1 -1
- package/dist/compute/idempotency.js +10 -14
- package/dist/compute/idempotency.js.map +1 -1
- package/dist/compute/index.d.ts.map +1 -1
- package/dist/compute/index.js +3 -5
- package/dist/compute/index.js.map +1 -1
- package/dist/compute/limits.d.ts +70 -86
- package/dist/compute/limits.d.ts.map +1 -1
- package/dist/compute/limits.js +27 -56
- package/dist/compute/limits.js.map +1 -1
- package/dist/compute/rate-limit.d.ts +41 -53
- package/dist/compute/rate-limit.d.ts.map +1 -1
- package/dist/compute/rate-limit.js +27 -35
- package/dist/compute/rate-limit.js.map +1 -1
- package/dist/compute/remote-definition.d.ts +8 -22
- package/dist/compute/remote-definition.d.ts.map +1 -1
- package/dist/compute/remote-definition.js +9 -19
- package/dist/compute/remote-definition.js.map +1 -1
- package/dist/compute/safe-url.d.ts +7 -5
- package/dist/compute/safe-url.d.ts.map +1 -1
- package/dist/compute/safe-url.js +26 -28
- package/dist/compute/safe-url.js.map +1 -1
- package/dist/definitions/definition-service.d.ts +13 -38
- package/dist/definitions/definition-service.d.ts.map +1 -1
- package/dist/definitions/definition-service.js +25 -53
- package/dist/definitions/definition-service.js.map +1 -1
- package/dist/definitions/index.d.ts +1 -1
- package/dist/definitions/index.d.ts.map +1 -1
- package/dist/definitions/index.js +0 -4
- package/dist/definitions/index.js.map +1 -1
- package/dist/definitions/load-for-render.d.ts +23 -20
- package/dist/definitions/load-for-render.d.ts.map +1 -1
- package/dist/definitions/load-for-render.js +37 -40
- package/dist/definitions/load-for-render.js.map +1 -1
- package/dist/definitions/schema-extraction.d.ts +11 -14
- package/dist/definitions/schema-extraction.d.ts.map +1 -1
- package/dist/definitions/schema-extraction.js +17 -26
- package/dist/definitions/schema-extraction.js.map +1 -1
- package/dist/errors/SentryErrorReporter.d.ts +2 -3
- package/dist/errors/SentryErrorReporter.d.ts.map +1 -1
- package/dist/errors/SentryErrorReporter.js +10 -14
- package/dist/errors/SentryErrorReporter.js.map +1 -1
- package/dist/http/body-size.d.ts +8 -11
- package/dist/http/body-size.d.ts.map +1 -1
- package/dist/http/body-size.js +8 -11
- package/dist/http/body-size.js.map +1 -1
- package/dist/http/redirect.d.ts +3 -7
- package/dist/http/redirect.d.ts.map +1 -1
- package/dist/http/redirect.js +8 -8
- package/dist/http/redirect.js.map +1 -1
- package/dist/http/route-classifier.d.ts +20 -24
- package/dist/http/route-classifier.d.ts.map +1 -1
- package/dist/http/route-classifier.js +6 -7
- package/dist/http/route-classifier.js.map +1 -1
- package/dist/http/security-headers.d.ts +13 -15
- package/dist/http/security-headers.d.ts.map +1 -1
- package/dist/http/security-headers.js +10 -12
- package/dist/http/security-headers.js.map +1 -1
- package/dist/logging/PinoLogger.d.ts +8 -14
- package/dist/logging/PinoLogger.d.ts.map +1 -1
- package/dist/logging/PinoLogger.js +29 -35
- package/dist/logging/PinoLogger.js.map +1 -1
- package/dist/logging/requestId.d.ts +20 -28
- package/dist/logging/requestId.d.ts.map +1 -1
- package/dist/logging/requestId.js +29 -37
- package/dist/logging/requestId.js.map +1 -1
- package/dist/ops/index.d.ts.map +1 -1
- package/dist/ops/index.js +2 -1
- package/dist/ops/index.js.map +1 -1
- package/dist/ops/semver.d.ts +22 -24
- package/dist/ops/semver.d.ts.map +1 -1
- package/dist/ops/semver.js +22 -25
- package/dist/ops/semver.js.map +1 -1
- package/dist/providers/create-selva-providers.d.ts +19 -27
- package/dist/providers/create-selva-providers.d.ts.map +1 -1
- package/dist/providers/create-selva-providers.js +28 -34
- package/dist/providers/create-selva-providers.js.map +1 -1
- package/dist/providers/index.d.ts.map +1 -1
- package/dist/providers/index.js +2 -4
- package/dist/providers/index.js.map +1 -1
- package/dist/tokens/token-codec.d.ts +24 -27
- package/dist/tokens/token-codec.d.ts.map +1 -1
- package/dist/tokens/token-codec.js +18 -21
- package/dist/tokens/token-codec.js.map +1 -1
- package/package.json +6 -6
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route-classifier.d.ts","sourceRoot":"","sources":["../../src/http/route-classifier.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"route-classifier.d.ts","sourceRoot":"","sources":["../../src/http/route-classifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,MAAM,WAAW,qBAAqB;IACrC,iEAAiE;IACjE,WAAW,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC/B,2FAA2F;IAC3F,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC;;;;OAIG;IACH,UAAU,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC9B;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,yEAAyE;IACzE,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,qEAAqE;IACrE,WAAW,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,eAAe;IAC/B,iFAAiF;IACjF,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IACzC,yFAAyF;IACzF,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;IAChD,4EAA4E;IAC5E,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC;CACzC;AAED,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,qBAAqB,GAAG,eAAe,CAyBpF"}
|
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Deny-by-default route classification.
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
* loud 401/redirect), not silently public.
|
|
2
|
+
* Deny-by-default route classification. A request is gated unless its path
|
|
3
|
+
* matches one of the allowlists supplied here, so forgetting to list a new
|
|
4
|
+
* route makes it gated — a loud 401/redirect, not silently public.
|
|
6
5
|
*
|
|
7
|
-
* The
|
|
8
|
-
*
|
|
9
|
-
*
|
|
6
|
+
* The pattern is reusable; the values are app policy, supplied by the consuming
|
|
7
|
+
* app. Matching is plain exact/prefix string comparison: cheap enough for the
|
|
8
|
+
* hooks hot path, and no regex to get wrong.
|
|
10
9
|
*/
|
|
11
10
|
export function createRouteClassifier(config) {
|
|
12
11
|
const publicPages = new Set(config.publicPages ?? []);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route-classifier.js","sourceRoot":"","sources":["../../src/http/route-classifier.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"route-classifier.js","sourceRoot":"","sources":["../../src/http/route-classifier.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAoCH,MAAM,UAAU,qBAAqB,CAAC,MAA6B;IAClE,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;IACtD,MAAM,cAAc,GAAG,MAAM,CAAC,cAAc,IAAI,EAAE,CAAC;IACnD,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC;IACpD,MAAM,gBAAgB,GAAG,MAAM,CAAC,gBAAgB,CAAC;IACjD,MAAM,cAAc,GAAG,MAAM,CAAC,cAAc,IAAI,EAAE,CAAC;IACnD,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;IAEtD,SAAS,aAAa,CAAC,QAAgB;QACtC,IAAI,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC;YAAE,OAAO,IAAI,CAAC;QAC3C,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3D,CAAC;IAED,SAAS,oBAAoB,CAAC,QAAgB;QAC7C,OAAO,gBAAgB,KAAK,SAAS,IAAI,QAAQ,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC;IAChF,CAAC;IAED,SAAS,aAAa,CAAC,QAAgB;QACtC,IAAI,WAAW,CAAC,GAAG,CAAC,QAAQ,CAAC;YAAE,OAAO,IAAI,CAAC;QAC3C,IAAI,UAAU,CAAC,GAAG,CAAC,QAAQ,CAAC;YAAE,OAAO,IAAI,CAAC;QAC1C,IAAI,oBAAoB,CAAC,QAAQ,CAAC;YAAE,OAAO,IAAI,CAAC;QAChD,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3D,CAAC;IAED,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,aAAa,EAAE,CAAC;AAC/D,CAAC"}
|
|
@@ -1,31 +1,29 @@
|
|
|
1
1
|
export interface SecurityHeaderOptions {
|
|
2
2
|
/**
|
|
3
|
-
* Set `Strict-Transport-Security
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* Set `Strict-Transport-Security`. Production only — pinning
|
|
4
|
+
* http://localhost to HTTPS bricks local development. The caller decides
|
|
5
|
+
* what "production" means (e.g. `NODE_ENV`).
|
|
6
6
|
*/
|
|
7
7
|
hsts: boolean;
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
10
|
-
* Apply baseline browser-hardening headers to a response
|
|
11
|
-
*
|
|
10
|
+
* Apply baseline browser-hardening headers to a response and return it for
|
|
11
|
+
* chaining. Each is a cheap win that needs no UI verification:
|
|
12
12
|
*
|
|
13
13
|
* - X-Content-Type-Options: nosniff — disables MIME sniffing.
|
|
14
|
-
* - Referrer-Policy: strict-origin-when-cross-origin — strips
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* - Permissions-Policy:
|
|
18
|
-
*
|
|
19
|
-
* - HSTS when `opts.hsts
|
|
14
|
+
* - Referrer-Policy: strict-origin-when-cross-origin — strips path and query
|
|
15
|
+
* from cross-origin Referer headers. Matches modern browser defaults, but
|
|
16
|
+
* pins the behavior in case a default drifts.
|
|
17
|
+
* - Permissions-Policy: opts out of browser APIs Selva-engine apps don't use,
|
|
18
|
+
* so XSS can't enable them.
|
|
19
|
+
* - HSTS when `opts.hsts`.
|
|
20
20
|
*
|
|
21
21
|
* **Intentionally NOT set here:**
|
|
22
22
|
* - Content-Security-Policy + frame-ancestors. Selva-engine apps are built
|
|
23
|
-
* for iframe embedding, so a strict CSP needs
|
|
24
|
-
*
|
|
23
|
+
* for iframe embedding, so a strict CSP needs validating against real
|
|
24
|
+
* consumer sites before it can ship.
|
|
25
25
|
* - X-Frame-Options. Same iframe-embedding constraint.
|
|
26
26
|
* - Cache-Control. Asset-path layout is app policy; set it in the caller.
|
|
27
|
-
*
|
|
28
|
-
* Returns the same response for chaining.
|
|
29
27
|
*/
|
|
30
28
|
export declare function applySecurityHeaders(response: Response, opts: SecurityHeaderOptions): Response;
|
|
31
29
|
//# sourceMappingURL=security-headers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"security-headers.d.ts","sourceRoot":"","sources":["../../src/http/security-headers.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,qBAAqB;IACrC;;;;OAIG;IACH,IAAI,EAAE,OAAO,CAAC;CACd;AAED
|
|
1
|
+
{"version":3,"file":"security-headers.d.ts","sourceRoot":"","sources":["../../src/http/security-headers.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,qBAAqB;IACrC;;;;OAIG;IACH,IAAI,EAAE,OAAO,CAAC;CACd;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,qBAAqB,GAAG,QAAQ,CAW9F"}
|
|
@@ -1,23 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Apply baseline browser-hardening headers to a response
|
|
3
|
-
*
|
|
2
|
+
* Apply baseline browser-hardening headers to a response and return it for
|
|
3
|
+
* chaining. Each is a cheap win that needs no UI verification:
|
|
4
4
|
*
|
|
5
5
|
* - X-Content-Type-Options: nosniff — disables MIME sniffing.
|
|
6
|
-
* - Referrer-Policy: strict-origin-when-cross-origin — strips
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
* - Permissions-Policy:
|
|
10
|
-
*
|
|
11
|
-
* - HSTS when `opts.hsts
|
|
6
|
+
* - Referrer-Policy: strict-origin-when-cross-origin — strips path and query
|
|
7
|
+
* from cross-origin Referer headers. Matches modern browser defaults, but
|
|
8
|
+
* pins the behavior in case a default drifts.
|
|
9
|
+
* - Permissions-Policy: opts out of browser APIs Selva-engine apps don't use,
|
|
10
|
+
* so XSS can't enable them.
|
|
11
|
+
* - HSTS when `opts.hsts`.
|
|
12
12
|
*
|
|
13
13
|
* **Intentionally NOT set here:**
|
|
14
14
|
* - Content-Security-Policy + frame-ancestors. Selva-engine apps are built
|
|
15
|
-
* for iframe embedding, so a strict CSP needs
|
|
16
|
-
*
|
|
15
|
+
* for iframe embedding, so a strict CSP needs validating against real
|
|
16
|
+
* consumer sites before it can ship.
|
|
17
17
|
* - X-Frame-Options. Same iframe-embedding constraint.
|
|
18
18
|
* - Cache-Control. Asset-path layout is app policy; set it in the caller.
|
|
19
|
-
*
|
|
20
|
-
* Returns the same response for chaining.
|
|
21
19
|
*/
|
|
22
20
|
export function applySecurityHeaders(response, opts) {
|
|
23
21
|
response.headers.set('X-Content-Type-Options', 'nosniff');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"security-headers.js","sourceRoot":"","sources":["../../src/http/security-headers.ts"],"names":[],"mappings":"AASA
|
|
1
|
+
{"version":3,"file":"security-headers.js","sourceRoot":"","sources":["../../src/http/security-headers.ts"],"names":[],"mappings":"AASA;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,oBAAoB,CAAC,QAAkB,EAAE,IAA2B;IACnF,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,wBAAwB,EAAE,SAAS,CAAC,CAAC;IAC1D,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,iCAAiC,CAAC,CAAC;IAC3E,QAAQ,CAAC,OAAO,CAAC,GAAG,CACnB,oBAAoB,EACpB,+GAA+G,CAC/G,CAAC;IACF,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACf,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,2BAA2B,EAAE,qCAAqC,CAAC,CAAC;IAC1F,CAAC;IACD,OAAO,QAAQ,CAAC;AACjB,CAAC"}
|
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import type { ILogger, LogFields, LogLevel } from '@selvajs/platform';
|
|
2
2
|
/**
|
|
3
|
-
* Minimal `ILogger` over `console.*`, used when pino isn't installed.
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* honest about not being machine-parseable. `child` fields are merged eagerly
|
|
7
|
-
* so correlation still works without pino.
|
|
3
|
+
* Minimal `ILogger` over `console.*`, used when pino isn't installed. Renders
|
|
4
|
+
* as `LEVEL message {fields}` — greppable, and honest about not being
|
|
5
|
+
* machine-parseable. `child` fields merge eagerly so correlation still works.
|
|
8
6
|
*/
|
|
9
7
|
export declare class ConsoleLogger implements ILogger {
|
|
10
8
|
private readonly bound;
|
|
@@ -19,21 +17,17 @@ export declare class ConsoleLogger implements ILogger {
|
|
|
19
17
|
child(fields: LogFields): ILogger;
|
|
20
18
|
}
|
|
21
19
|
export interface CreateLoggerOptions {
|
|
22
|
-
/** Minimum level written
|
|
20
|
+
/** Minimum level written; records below it are dropped. Defaults to `info`. */
|
|
23
21
|
level?: LogLevel;
|
|
24
22
|
/**
|
|
25
|
-
* Pretty-print via `pino-pretty`
|
|
26
|
-
*
|
|
27
|
-
*
|
|
23
|
+
* Pretty-print via `pino-pretty` instead of JSON — for local development;
|
|
24
|
+
* production wants JSON for the collector. Asking for this without
|
|
25
|
+
* `pino-pretty` installed drops the whole logger to {@link ConsoleLogger}.
|
|
28
26
|
*/
|
|
29
27
|
pretty?: boolean;
|
|
30
28
|
/** Fields stamped on every record (e.g. service name, release). */
|
|
31
29
|
base?: LogFields;
|
|
32
30
|
}
|
|
33
|
-
/**
|
|
34
|
-
* Build the app's root logger. Never throws and never returns `null`: a
|
|
35
|
-
* deployment with no pino installed gets {@link ConsoleLogger}, because losing
|
|
36
|
-
* warnings and errors is a worse outcome than losing JSON formatting.
|
|
37
|
-
*/
|
|
31
|
+
/** Build the app's root logger. Never throws, never returns `null`. */
|
|
38
32
|
export declare function createLogger(opts?: CreateLoggerOptions): Promise<ILogger>;
|
|
39
33
|
//# sourceMappingURL=PinoLogger.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PinoLogger.d.ts","sourceRoot":"","sources":["../../src/logging/PinoLogger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"PinoLogger.d.ts","sourceRoot":"","sources":["../../src/logging/PinoLogger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AA2DtE;;;;GAIG;AACH,qBAAa,aAAc,YAAW,OAAO;IAE3C,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,QAAQ;gBADR,KAAK,GAAE,SAAc,EACrB,QAAQ,GAAE,QAAiB;IAG7C,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAK3B;IAEF,OAAO,CAAC,KAAK;IAYb,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,GAAG,IAAI;IAGhD,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,GAAG,IAAI;IAG/C,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,GAAG,IAAI;IAG/C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,SAAS,GAAG,IAAI;IAGhD,KAAK,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO;CAGjC;AAqDD,MAAM,WAAW,mBAAmB;IACnC,+EAA+E;IAC/E,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB;;;;OAIG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,mEAAmE;IACnE,IAAI,CAAC,EAAE,SAAS,CAAC;CACjB;AAED,uEAAuE;AACvE,wBAAsB,YAAY,CAAC,IAAI,GAAE,mBAAwB,GAAG,OAAO,CAAC,OAAO,CAAC,CAuBnF"}
|
|
@@ -1,8 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Field paths scrubbed before a record is written.
|
|
3
|
-
* sites are required not to log secrets in
|
|
4
|
-
* This catches the
|
|
5
|
-
*
|
|
2
|
+
* Field paths scrubbed before a record is written. A backstop for accidents,
|
|
3
|
+
* NOT a licence to log objects: call sites are required not to log secrets in
|
|
4
|
+
* the first place (see `LogFields`). This catches the case where a whole object
|
|
5
|
+
* is spread into fields and happens to carry a credential.
|
|
6
|
+
*
|
|
7
|
+
* It matches by FIELD NAME, and only at the top level or one level deep (the
|
|
8
|
+
* `*.` entries). It will not catch personal data — an email nested in a payload
|
|
9
|
+
* sails straight through, and a log line reaches a collector that erasure can
|
|
10
|
+
* never reach. Note the nested `*.` set covers only five of the eight names.
|
|
6
11
|
*/
|
|
7
12
|
const REDACTED_PATHS = [
|
|
8
13
|
'token',
|
|
@@ -20,11 +25,9 @@ const REDACTED_PATHS = [
|
|
|
20
25
|
'*.password'
|
|
21
26
|
];
|
|
22
27
|
/**
|
|
23
|
-
* Minimal `ILogger` over `console.*`, used when pino isn't installed.
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
* honest about not being machine-parseable. `child` fields are merged eagerly
|
|
27
|
-
* so correlation still works without pino.
|
|
28
|
+
* Minimal `ILogger` over `console.*`, used when pino isn't installed. Renders
|
|
29
|
+
* as `LEVEL message {fields}` — greppable, and honest about not being
|
|
30
|
+
* machine-parseable. `child` fields merge eagerly so correlation still works.
|
|
28
31
|
*/
|
|
29
32
|
export class ConsoleLogger {
|
|
30
33
|
bound;
|
|
@@ -45,9 +48,8 @@ export class ConsoleLogger {
|
|
|
45
48
|
const merged = { ...this.bound, ...fields };
|
|
46
49
|
const suffix = Object.keys(merged).length > 0 ? ` ${safeStringify(merged)}` : '';
|
|
47
50
|
const line = `${level.toUpperCase()} ${message}${suffix}`;
|
|
48
|
-
//
|
|
49
|
-
//
|
|
50
|
-
// is already spelled out in the line's own prefix.
|
|
51
|
+
// Split stderr/stdout the way an operator expects. `info` carries debug
|
|
52
|
+
// too — both land on stdout, and the line already spells out its level.
|
|
51
53
|
if (level === 'error')
|
|
52
54
|
console.error(line);
|
|
53
55
|
else if (level === 'warn')
|
|
@@ -85,8 +87,8 @@ class PinoLogger {
|
|
|
85
87
|
constructor(pino) {
|
|
86
88
|
this.pino = pino;
|
|
87
89
|
}
|
|
88
|
-
// pino takes (fields, message); ILogger takes (message, fields)
|
|
89
|
-
// deliberate
|
|
90
|
+
// pino takes (fields, message); ILogger takes (message, fields). The flip is
|
|
91
|
+
// deliberate — the message is what a human scans for first.
|
|
90
92
|
debug(message, fields) {
|
|
91
93
|
try {
|
|
92
94
|
this.pino.debug(fields ?? {}, message);
|
|
@@ -128,11 +130,7 @@ class PinoLogger {
|
|
|
128
130
|
}
|
|
129
131
|
}
|
|
130
132
|
}
|
|
131
|
-
/**
|
|
132
|
-
* Build the app's root logger. Never throws and never returns `null`: a
|
|
133
|
-
* deployment with no pino installed gets {@link ConsoleLogger}, because losing
|
|
134
|
-
* warnings and errors is a worse outcome than losing JSON formatting.
|
|
135
|
-
*/
|
|
133
|
+
/** Build the app's root logger. Never throws, never returns `null`. */
|
|
136
134
|
export async function createLogger(opts = {}) {
|
|
137
135
|
const level = opts.level ?? 'info';
|
|
138
136
|
try {
|
|
@@ -150,10 +148,9 @@ export async function createLogger(opts = {}) {
|
|
|
150
148
|
return new PinoLogger(pino);
|
|
151
149
|
}
|
|
152
150
|
catch (err) {
|
|
153
|
-
// pino resolved but
|
|
154
|
-
//
|
|
155
|
-
//
|
|
156
|
-
// something they didn't get. Fall back rather than go quiet.
|
|
151
|
+
// pino resolved but wouldn't construct — a real misconfiguration (e.g.
|
|
152
|
+
// `pretty: true` with pino-pretty absent). Worth complaining about, unlike
|
|
153
|
+
// a merely absent package: the operator asked for something they didn't get.
|
|
157
154
|
console.warn(`[Logger] pino was found but could not be initialized; falling back to console logging. ${String(err)}`);
|
|
158
155
|
return new ConsoleLogger(opts.base ?? {}, level);
|
|
159
156
|
}
|
|
@@ -161,16 +158,13 @@ export async function createLogger(opts = {}) {
|
|
|
161
158
|
/**
|
|
162
159
|
* Load pino's factory, or `null` when it isn't installed.
|
|
163
160
|
*
|
|
164
|
-
*
|
|
165
|
-
*
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
*
|
|
171
|
-
*
|
|
172
|
-
* `@vite-ignore` alone was NOT sufficient — it suppressed the warning while the
|
|
173
|
-
* rewrite happened anyway.
|
|
161
|
+
* Don't inline the specifier. A literal `import('pino')` is statically
|
|
162
|
+
* analyzable, so Vite applied browser-field mapping to this server build and
|
|
163
|
+
* resolved it to pino's `server_false` browser shim — a stub whose factory
|
|
164
|
+
* throws, turning "use pino" into a silent fall back to the console. Computing
|
|
165
|
+
* the specifier defeats that and leaves the import to Node at runtime.
|
|
166
|
+
* `@vite-ignore` alone was NOT enough: it silenced the warning and the rewrite
|
|
167
|
+
* still happened.
|
|
174
168
|
*/
|
|
175
169
|
async function loadPinoFactory() {
|
|
176
170
|
const specifier = 'pino';
|
|
@@ -181,8 +175,8 @@ async function loadPinoFactory() {
|
|
|
181
175
|
}
|
|
182
176
|
catch {
|
|
183
177
|
// Not installed — the expected path on a base install, where the console
|
|
184
|
-
// fallback is
|
|
185
|
-
//
|
|
178
|
+
// fallback is intended. Quiet on purpose: complaining at boot about an
|
|
179
|
+
// optional package nobody asked for is noise.
|
|
186
180
|
return null;
|
|
187
181
|
}
|
|
188
182
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PinoLogger.js","sourceRoot":"","sources":["../../src/logging/PinoLogger.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"PinoLogger.js","sourceRoot":"","sources":["../../src/logging/PinoLogger.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,45 +1,37 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Request-id resolution for log correlation.
|
|
2
|
+
* Request-id resolution for log correlation. Every record on a request path
|
|
3
|
+
* carries the same `requestId`, so an operator handed one id can reconstruct
|
|
4
|
+
* that request's whole story.
|
|
3
5
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
6
|
+
* Inbound ids are TRUSTED when present. Selva runs behind a reverse proxy
|
|
7
|
+
* (Caddy/nginx) that mints a request id for its own access logs; minting a
|
|
8
|
+
* second one here would split one request across two ids and kill cross-tier
|
|
9
|
+
* correlation. The trade — a direct caller picks their own id — is fine, because
|
|
10
|
+
* the id is only ever a log field and an echoed response header, never an
|
|
11
|
+
* authorization or uniqueness input.
|
|
7
12
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* two ids and make cross-tier correlation impossible. The trade is that a direct
|
|
12
|
-
* caller can choose their own id — acceptable, because a request id is a
|
|
13
|
-
* correlation hint, never an authorization or uniqueness input. It is used only
|
|
14
|
-
* as a log field and an echoed response header.
|
|
15
|
-
*
|
|
16
|
-
* That trust is exactly why {@link sanitizeRequestId} exists: an attacker-chosen
|
|
17
|
-
* id is untrusted *content*. Unbounded or newline-carrying values would let a
|
|
18
|
-
* caller forge log lines (log injection) or bloat every record on the request.
|
|
13
|
+
* That trust is why {@link sanitizeRequestId} exists: an attacker-chosen id is
|
|
14
|
+
* untrusted content. Unbounded or newline-carrying values would let a caller
|
|
15
|
+
* forge log lines (log injection) or bloat every record on the request.
|
|
19
16
|
*/
|
|
20
17
|
/** Header carrying a caller/proxy-supplied id. The de-facto standard spelling. */
|
|
21
18
|
export declare const REQUEST_ID_HEADER = "x-request-id";
|
|
22
|
-
/**
|
|
23
|
-
* Reduce an untrusted inbound id to something safe to stamp on every record.
|
|
24
|
-
* Returns `null` when nothing usable survives, so the caller generates instead.
|
|
25
|
-
*/
|
|
19
|
+
/** Returns `null` when nothing usable survives, so the caller generates instead. */
|
|
26
20
|
export declare function sanitizeRequestId(raw: string | null | undefined): string | null;
|
|
27
21
|
/**
|
|
28
|
-
*
|
|
29
|
-
* sanitization, otherwise mint a fresh UUID.
|
|
22
|
+
* Reuse the proxy's id when it survives sanitization, otherwise mint a UUID.
|
|
30
23
|
*
|
|
31
|
-
* @param
|
|
32
|
-
* @param generate id source; injectable so tests get deterministic ids
|
|
24
|
+
* @param generate injectable so tests get deterministic ids
|
|
33
25
|
*/
|
|
34
26
|
export declare function resolveRequestId(headers: Headers, generate?: () => string): string;
|
|
35
27
|
/**
|
|
36
28
|
* Render a thrown value into a log field.
|
|
37
29
|
*
|
|
38
|
-
* Not every rejection is an `Error` — provider adapters
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
*
|
|
30
|
+
* Not every rejection is an `Error` — provider adapters sometimes reject with a
|
|
31
|
+
* plain `{ message, status }`, which would stringify to a useless
|
|
32
|
+
* `[object Object]` and destroy the only record of the failure. Errors keep
|
|
33
|
+
* their stack; anything else is JSON-serialized, with `String()` as the last
|
|
34
|
+
* resort for cycles and exotic values.
|
|
43
35
|
*/
|
|
44
36
|
export declare function renderThrown(error: unknown): string;
|
|
45
37
|
//# sourceMappingURL=requestId.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"requestId.d.ts","sourceRoot":"","sources":["../../src/logging/requestId.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"requestId.d.ts","sourceRoot":"","sources":["../../src/logging/requestId.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,kFAAkF;AAClF,eAAO,MAAM,iBAAiB,iBAAiB,CAAC;AAahD,oFAAoF;AACpF,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAI/E;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,GAAE,MAAM,MAAiB,GAAG,MAAM,CAE5F;AAED;;;;;;;;GAQG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAOnD"}
|
|
@@ -1,37 +1,31 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Request-id resolution for log correlation.
|
|
2
|
+
* Request-id resolution for log correlation. Every record on a request path
|
|
3
|
+
* carries the same `requestId`, so an operator handed one id can reconstruct
|
|
4
|
+
* that request's whole story.
|
|
3
5
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
6
|
+
* Inbound ids are TRUSTED when present. Selva runs behind a reverse proxy
|
|
7
|
+
* (Caddy/nginx) that mints a request id for its own access logs; minting a
|
|
8
|
+
* second one here would split one request across two ids and kill cross-tier
|
|
9
|
+
* correlation. The trade — a direct caller picks their own id — is fine, because
|
|
10
|
+
* the id is only ever a log field and an echoed response header, never an
|
|
11
|
+
* authorization or uniqueness input.
|
|
7
12
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* two ids and make cross-tier correlation impossible. The trade is that a direct
|
|
12
|
-
* caller can choose their own id — acceptable, because a request id is a
|
|
13
|
-
* correlation hint, never an authorization or uniqueness input. It is used only
|
|
14
|
-
* as a log field and an echoed response header.
|
|
15
|
-
*
|
|
16
|
-
* That trust is exactly why {@link sanitizeRequestId} exists: an attacker-chosen
|
|
17
|
-
* id is untrusted *content*. Unbounded or newline-carrying values would let a
|
|
18
|
-
* caller forge log lines (log injection) or bloat every record on the request.
|
|
13
|
+
* That trust is why {@link sanitizeRequestId} exists: an attacker-chosen id is
|
|
14
|
+
* untrusted content. Unbounded or newline-carrying values would let a caller
|
|
15
|
+
* forge log lines (log injection) or bloat every record on the request.
|
|
19
16
|
*/
|
|
20
17
|
/** Header carrying a caller/proxy-supplied id. The de-facto standard spelling. */
|
|
21
18
|
export const REQUEST_ID_HEADER = 'x-request-id';
|
|
22
|
-
/**
|
|
19
|
+
/** Long enough for a UUID or a W3C trace-id, short enough to bound a record. */
|
|
23
20
|
const MAX_REQUEST_ID_LENGTH = 128;
|
|
24
21
|
/**
|
|
25
|
-
* Characters allowed through verbatim.
|
|
26
|
-
* trace-ids and nginx's `$request_id` all fit.
|
|
27
|
-
* control chars, quotes, CR/LF
|
|
28
|
-
* legitimate id
|
|
22
|
+
* Characters allowed through verbatim. Strict on purpose: UUIDs, ULIDs, hex
|
|
23
|
+
* trace-ids and nginx's `$request_id` all fit. Everything else — whitespace,
|
|
24
|
+
* control chars, quotes, CR/LF — is dropped rather than escaped, since no
|
|
25
|
+
* legitimate id needs them and dropping can't be un-escaped downstream.
|
|
29
26
|
*/
|
|
30
27
|
const UNSAFE_REQUEST_ID_CHARS = /[^A-Za-z0-9._:-]/g;
|
|
31
|
-
/**
|
|
32
|
-
* Reduce an untrusted inbound id to something safe to stamp on every record.
|
|
33
|
-
* Returns `null` when nothing usable survives, so the caller generates instead.
|
|
34
|
-
*/
|
|
28
|
+
/** Returns `null` when nothing usable survives, so the caller generates instead. */
|
|
35
29
|
export function sanitizeRequestId(raw) {
|
|
36
30
|
if (!raw)
|
|
37
31
|
return null;
|
|
@@ -39,11 +33,9 @@ export function sanitizeRequestId(raw) {
|
|
|
39
33
|
return cleaned.length > 0 ? cleaned : null;
|
|
40
34
|
}
|
|
41
35
|
/**
|
|
42
|
-
*
|
|
43
|
-
* sanitization, otherwise mint a fresh UUID.
|
|
36
|
+
* Reuse the proxy's id when it survives sanitization, otherwise mint a UUID.
|
|
44
37
|
*
|
|
45
|
-
* @param
|
|
46
|
-
* @param generate id source; injectable so tests get deterministic ids
|
|
38
|
+
* @param generate injectable so tests get deterministic ids
|
|
47
39
|
*/
|
|
48
40
|
export function resolveRequestId(headers, generate = randomId) {
|
|
49
41
|
return sanitizeRequestId(headers.get(REQUEST_ID_HEADER)) ?? generate();
|
|
@@ -51,11 +43,11 @@ export function resolveRequestId(headers, generate = randomId) {
|
|
|
51
43
|
/**
|
|
52
44
|
* Render a thrown value into a log field.
|
|
53
45
|
*
|
|
54
|
-
* Not every rejection is an `Error` — provider adapters
|
|
55
|
-
*
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
46
|
+
* Not every rejection is an `Error` — provider adapters sometimes reject with a
|
|
47
|
+
* plain `{ message, status }`, which would stringify to a useless
|
|
48
|
+
* `[object Object]` and destroy the only record of the failure. Errors keep
|
|
49
|
+
* their stack; anything else is JSON-serialized, with `String()` as the last
|
|
50
|
+
* resort for cycles and exotic values.
|
|
59
51
|
*/
|
|
60
52
|
export function renderThrown(error) {
|
|
61
53
|
if (error instanceof Error)
|
|
@@ -68,10 +60,10 @@ export function renderThrown(error) {
|
|
|
68
60
|
}
|
|
69
61
|
}
|
|
70
62
|
/**
|
|
71
|
-
* `crypto.randomUUID`
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
* correlate logs, never unguessable.
|
|
63
|
+
* `crypto.randomUUID` exists in every runtime Selva targets (Node 22+, workers,
|
|
64
|
+
* modern browsers); the `Math.random` branch only covers non-secure contexts
|
|
65
|
+
* where it is missing. Not a weakness: these ids need to be collision-free
|
|
66
|
+
* enough to correlate logs, never unguessable.
|
|
75
67
|
*/
|
|
76
68
|
function randomId() {
|
|
77
69
|
const c = globalThis.crypto;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"requestId.js","sourceRoot":"","sources":["../../src/logging/requestId.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"requestId.js","sourceRoot":"","sources":["../../src/logging/requestId.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,kFAAkF;AAClF,MAAM,CAAC,MAAM,iBAAiB,GAAG,cAAc,CAAC;AAEhD,gFAAgF;AAChF,MAAM,qBAAqB,GAAG,GAAG,CAAC;AAElC;;;;;GAKG;AACH,MAAM,uBAAuB,GAAG,mBAAmB,CAAC;AAEpD,oFAAoF;AACpF,MAAM,UAAU,iBAAiB,CAAC,GAA8B;IAC/D,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,uBAAuB,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,qBAAqB,CAAC,CAAC;IACzF,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC;AAC5C,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAgB,EAAE,WAAyB,QAAQ;IACnF,OAAO,iBAAiB,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,IAAI,QAAQ,EAAE,CAAC;AACxE,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAAC,KAAc;IAC1C,IAAI,KAAK,YAAY,KAAK;QAAE,OAAO,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,OAAO,CAAC;IAChE,IAAI,CAAC;QACJ,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;IAC/C,CAAC;IAAC,MAAM,CAAC;QACR,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;AACF,CAAC;AAED;;;;;GAKG;AACH,SAAS,QAAQ;IAChB,MAAM,CAAC,GAAuB,UAAU,CAAC,MAAM,CAAC;IAChD,IAAI,CAAC,IAAI,OAAO,CAAC,CAAC,UAAU,KAAK,UAAU;QAAE,OAAO,CAAC,CAAC,UAAU,EAAE,CAAC;IACnE,OAAO,OAAO,IAAI,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,EAAE,CAAC;AACpF,CAAC"}
|
package/dist/ops/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ops/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ops/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACN,WAAW,EACX,OAAO,EACP,WAAW,EACX,cAAc,EACd,KAAK,cAAc,EACnB,MAAM,aAAa,CAAC"}
|
package/dist/ops/index.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
// Deployment/ops helpers — channel-aware semver comparison.
|
|
1
|
+
// Deployment/ops helpers — channel-aware semver comparison and engines.node
|
|
2
|
+
// range checks.
|
|
2
3
|
export { parseSemver, isNewer, compareCore, satisfiesRange } from './semver.js';
|
|
3
4
|
//# sourceMappingURL=index.js.map
|
package/dist/ops/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ops/index.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ops/index.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,gBAAgB;AAEhB,OAAO,EACN,WAAW,EACX,OAAO,EACP,WAAW,EACX,cAAc,EAEd,MAAM,aAAa,CAAC"}
|
package/dist/ops/semver.d.ts
CHANGED
|
@@ -1,53 +1,51 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Channel-aware semver comparison for update checks. Understands exactly the
|
|
3
|
-
* two
|
|
4
|
-
* (`x.y.z`, npm `
|
|
5
|
-
*
|
|
6
|
-
* arbitrary pre-release identifiers.
|
|
3
|
+
* two lines Selva publishes under: stable (`x.y.z`, npm `latest`) and beta
|
|
4
|
+
* (`x.y.z-beta.N`, npm `beta`). Deliberately not general semver — no build
|
|
5
|
+
* metadata, no arbitrary pre-release identifiers.
|
|
7
6
|
*/
|
|
8
7
|
/** Which published line a deployment tracks. */
|
|
9
8
|
export type ReleaseChannel = 'stable' | 'beta';
|
|
10
9
|
/**
|
|
11
|
-
* Parse `x.y.z` plus an optional `-beta.N`
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* that doesn't lead with a numeric core.
|
|
10
|
+
* Parse `x.y.z` plus an optional `-beta.N` counter. `beta` comes back separate
|
|
11
|
+
* from the core so beta-channel comparisons can order successive betas of one
|
|
12
|
+
* core. Null when the string doesn't lead with a numeric core.
|
|
15
13
|
*/
|
|
16
14
|
export declare function parseSemver(v: string): {
|
|
17
15
|
core: [number, number, number];
|
|
18
16
|
beta: number | null;
|
|
19
17
|
} | null;
|
|
20
18
|
/**
|
|
21
|
-
* Compare two `x.y.z` cores
|
|
22
|
-
* about
|
|
19
|
+
* Compare two `x.y.z` cores, ignoring pre-release tails. Callers that care
|
|
20
|
+
* about those want `isNewer`, which layers the channel rules on top.
|
|
23
21
|
*/
|
|
24
22
|
export declare function compareCore(a: string, b: string): number;
|
|
25
23
|
/**
|
|
26
24
|
* Does `version` satisfy an `engines.node` range?
|
|
27
25
|
*
|
|
28
|
-
* Deliberately narrow: handles the
|
|
29
|
-
* forms Selva and its dependencies
|
|
30
|
-
* space-separated conjunctions (`>=18 <21`). Anything it
|
|
31
|
-
* `null`
|
|
32
|
-
* strand an operator
|
|
26
|
+
* Deliberately narrow: handles the `>=`, `>`, `<=`, `<`, `^`, `~`, `=` and
|
|
27
|
+
* bare-version forms Selva and its dependencies publish, plus `||` alternatives
|
|
28
|
+
* and space-separated conjunctions (`>=18 <21`). Anything it can't parse
|
|
29
|
+
* returns `null` for "unknown", never a false "incompatible" — a wrong block
|
|
30
|
+
* would strand an operator with no way to override the bad parse.
|
|
33
31
|
*
|
|
34
|
-
* A full `semver` dependency would subsume this
|
|
35
|
-
* handful of range forms in play
|
|
32
|
+
* A full `semver` dependency would subsume this, but isn't warranted for the
|
|
33
|
+
* handful of range forms in play.
|
|
36
34
|
*/
|
|
37
35
|
export declare function satisfiesRange(version: string, range: string): boolean | null;
|
|
38
36
|
/**
|
|
39
|
-
* True when `latest` is strictly newer than `current
|
|
37
|
+
* True when `latest` is strictly newer than `current`.
|
|
40
38
|
*
|
|
41
|
-
* Stable channel (default): pre-release suffixes are ignored
|
|
39
|
+
* Stable channel (default): pre-release suffixes are ignored, so only stable
|
|
42
40
|
* core bumps surface.
|
|
43
41
|
*
|
|
44
|
-
* Beta channel: pre-releases participate. A higher core wins; on an equal
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
*
|
|
42
|
+
* Beta channel: pre-releases participate. A higher core wins; on an equal core
|
|
43
|
+
* a higher `-beta.N` wins, and a stable (no suffix) outranks any -beta of that
|
|
44
|
+
* core (4.6.0 > 4.6.0-beta.9). An update UI can then show both "beta.1 →
|
|
45
|
+
* beta.2" and the promotion of a beta line to stable.
|
|
48
46
|
*
|
|
49
47
|
* Unparseable versions fall back to inequality: different strings count as
|
|
50
|
-
*
|
|
48
|
+
* newer, so an odd published version still surfaces; identical ones don't.
|
|
51
49
|
*/
|
|
52
50
|
export declare function isNewer(latest: string, current: string, channel?: ReleaseChannel): boolean;
|
|
53
51
|
//# sourceMappingURL=semver.d.ts.map
|