@selvajs/server 1.0.0-beta.9 → 1.0.1
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 +2 -2
- package/dist/definitions/index.d.ts.map +1 -1
- package/dist/definitions/index.js +1 -5
- 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 +55 -41
- package/dist/definitions/load-for-render.js.map +1 -1
- package/dist/definitions/schema-extraction.d.ts +36 -16
- package/dist/definitions/schema-extraction.d.ts.map +1 -1
- package/dist/definitions/schema-extraction.js +65 -28
- 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 +5 -5
package/dist/compute/safe-url.js
CHANGED
|
@@ -2,31 +2,29 @@ import { lookup } from 'node:dns/promises';
|
|
|
2
2
|
import { isIP } from 'node:net';
|
|
3
3
|
import { NoopLogger } from '@selvajs/platform';
|
|
4
4
|
/**
|
|
5
|
-
* SSRF guard for
|
|
6
|
-
* submit `http://169.254.169.254/...` (cloud metadata) or any intranet
|
|
7
|
-
* and the server would fetch it on their behalf.
|
|
5
|
+
* SSRF guard for the remote-definition fetch. Without it an authenticated user
|
|
6
|
+
* could submit `http://169.254.169.254/...` (cloud metadata) or any intranet
|
|
7
|
+
* endpoint and the server would fetch it on their behalf.
|
|
8
8
|
*
|
|
9
9
|
* Two layers:
|
|
10
10
|
*
|
|
11
|
-
* 1. `isSafeRemoteDefinitionUrl` — synchronous literal
|
|
12
|
-
* protocol, hostname literals, and every IP *encoding* that
|
|
13
|
-
* blocked address
|
|
14
|
-
* IPv4-mapped IPv6
|
|
11
|
+
* 1. `isSafeRemoteDefinitionUrl` — synchronous, DNS-free literal filter.
|
|
12
|
+
* Rejects the protocol, hostname literals, and every IP *encoding* that
|
|
13
|
+
* maps to a blocked address: dotted-decimal, integer, octal, hex,
|
|
14
|
+
* short-form, IPv4-mapped IPv6.
|
|
15
|
+
* 2. `assertSafeRemoteDefinitionUrl` — resolves the hostname and re-checks the
|
|
16
|
+
* *resolved* IP, catching a public name that points at a private one.
|
|
15
17
|
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
* connect to the resolved IP directly. Connecting by IP is a larger change
|
|
22
|
-
* — this closes the practical bypasses (literal encodings + a DNS record
|
|
23
|
-
* that points inward) which is what an attacker actually reaches for.
|
|
18
|
+
* Neither is bulletproof against DNS rebinding — the IP can change between our
|
|
19
|
+
* lookup and fetch's own. Closing that needs the caller to connect to the
|
|
20
|
+
* resolved IP directly, a much larger change; these two layers close the
|
|
21
|
+
* bypasses an attacker actually reaches for (literal encodings, and a public
|
|
22
|
+
* name whose record points inward).
|
|
24
23
|
*/
|
|
25
24
|
/**
|
|
26
25
|
* True when `ip` (a normalized IPv4 or IPv6 literal from `isIP`/`dns.lookup`)
|
|
27
26
|
* is loopback, private, link-local, or otherwise must-not-fetch. IPv4-mapped
|
|
28
|
-
* IPv6 (`::ffff:a.b.c.d`) is unwrapped
|
|
29
|
-
* rules apply.
|
|
27
|
+
* IPv6 (`::ffff:a.b.c.d`) is unwrapped first so the v4 rules apply.
|
|
30
28
|
*/
|
|
31
29
|
function isBlockedIp(ip) {
|
|
32
30
|
let addr = ip.toLowerCase();
|
|
@@ -76,9 +74,10 @@ function isBlockedIp(ip) {
|
|
|
76
74
|
/**
|
|
77
75
|
* Parse a bare-IPv4 hostname in any encoding browsers/glibc accept — integer
|
|
78
76
|
* (`2130706433`), octal (`0177.0.0.1`), hex (`0x7f000001`), and short forms
|
|
79
|
-
* (`127.1`) — into
|
|
80
|
-
* host is not a numeric IPv4 literal
|
|
81
|
-
*
|
|
77
|
+
* (`127.1`) — into canonical dotted-decimal. An already-valid dotted-quad comes
|
|
78
|
+
* back unchanged. Returns null only when the host is not a numeric IPv4 literal
|
|
79
|
+
* at all, i.e. it's a real name — which is what callers use to decide whether
|
|
80
|
+
* DNS resolution is needed.
|
|
82
81
|
*/
|
|
83
82
|
function canonicalizeNumericIpv4(host) {
|
|
84
83
|
// Already a clean dotted-quad — let isIP handle it directly.
|
|
@@ -133,10 +132,10 @@ function canonicalizeNumericIpv4(host) {
|
|
|
133
132
|
return [(value >>> 24) & 0xff, (value >>> 16) & 0xff, (value >>> 8) & 0xff, value & 0xff].join('.');
|
|
134
133
|
}
|
|
135
134
|
/**
|
|
136
|
-
* Synchronous literal pre-filter
|
|
137
|
-
* any IP literal (in any encoding) that
|
|
135
|
+
* Synchronous literal pre-filter: rejects bad schemes, loopback hostnames, and
|
|
136
|
+
* any IP literal (in any encoding) that maps to a blocked address. Does NOT
|
|
138
137
|
* perform DNS — a public *name* that points at a private IP passes here and is
|
|
139
|
-
* caught by `assertSafeRemoteDefinitionUrl`.
|
|
138
|
+
* caught only by `assertSafeRemoteDefinitionUrl`.
|
|
140
139
|
*/
|
|
141
140
|
export function isSafeRemoteDefinitionUrl(raw) {
|
|
142
141
|
let parsed;
|
|
@@ -170,13 +169,12 @@ export function isSafeRemoteDefinitionUrl(raw) {
|
|
|
170
169
|
/**
|
|
171
170
|
* Full SSRF check: literal pre-filter, then resolve every A/AAAA record and
|
|
172
171
|
* reject if *any* resolved IP is blocked. Returns the original URL on success
|
|
173
|
-
* so callers can `await assertSafeRemoteDefinitionUrl(url)` inline.
|
|
174
|
-
*
|
|
172
|
+
* so callers can `await assertSafeRemoteDefinitionUrl(url)` inline.
|
|
173
|
+
*
|
|
174
|
+
* Every rejection throws the same generic message so the caller gets no oracle;
|
|
175
|
+
* which host was blocked and by which layer is logged server-side instead.
|
|
175
176
|
*/
|
|
176
177
|
export async function assertSafeRemoteDefinitionUrl(raw, logger = new NoopLogger()) {
|
|
177
|
-
// Security-relevant event: the thrown message is deliberately generic (no
|
|
178
|
-
// oracle for the caller), so log the specifics server-side instead — which
|
|
179
|
-
// host was blocked and by which layer.
|
|
180
178
|
if (!isSafeRemoteDefinitionUrl(raw)) {
|
|
181
179
|
logger.warn('Blocked remote definition URL', {
|
|
182
180
|
component: 'Compute/ssrf',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"safe-url.js","sourceRoot":"","sources":["../../src/compute/safe-url.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAC3C,OAAO,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,UAAU,EAAgB,MAAM,mBAAmB,CAAC;AAE7D
|
|
1
|
+
{"version":3,"file":"safe-url.js","sourceRoot":"","sources":["../../src/compute/safe-url.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,8 @@
|
|
|
1
1
|
import type { IDataProvider, IStorageProvider, RequestContext, DefinitionRecord, DefinitionFileExt, DefinitionVersion, UpdateMetadataInput, UISchema } from '@selvajs/platform';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* Distinct from `CreateDefinitionInputSchema` exported by
|
|
7
|
-
* `@selvajs/platform/definitions`, which validates the user-facing
|
|
8
|
-
* HTTP body (no guid/ownerId — those are derived server-side).
|
|
3
|
+
* Not the HTTP body — that's `CreateDefinitionInputSchema` in
|
|
4
|
+
* `@selvajs/platform/definitions`, which has no guid/ownerId because those are
|
|
5
|
+
* derived server-side.
|
|
9
6
|
*/
|
|
10
7
|
export interface CreateDefinitionRecord {
|
|
11
8
|
guid: string;
|
|
@@ -21,33 +18,13 @@ export interface CreateDefinitionRecord {
|
|
|
21
18
|
computeServerId?: string;
|
|
22
19
|
}
|
|
23
20
|
/**
|
|
24
|
-
* Orchestrates writes
|
|
25
|
-
*
|
|
26
|
-
* because it is application orchestration, not platform contract.
|
|
27
|
-
*
|
|
28
|
-
* Ordering rules:
|
|
29
|
-
*
|
|
30
|
-
* create — metadata-first, then v1:
|
|
31
|
-
* 1. Write record with status='pending', both pointers null
|
|
32
|
-
* 2. Upload v1 blob to versions/v1.{ext}
|
|
33
|
-
* 3. Insert DefinitionVersion row v1
|
|
34
|
-
* 4. `attachInitialVersion` — atomically set live + draft pointers and
|
|
35
|
-
* flip status to 'draft' in a single store operation.
|
|
36
|
-
* Step 4 is one round-trip so a mid-flight failure can't leave a partial
|
|
37
|
-
* state (status='draft' with null pointers, or status='pending' with
|
|
38
|
-
* pointers set). If step 2 fails the record stays 'pending' with no
|
|
39
|
-
* blob and is filtered out of list endpoints by default.
|
|
40
|
-
*
|
|
41
|
-
* uploadVersion — append-only:
|
|
42
|
-
* 1. Reserve next versionNumber from the record's monotonic counter
|
|
43
|
-
* 2. Upload blob to versions/v{N}.{ext}
|
|
44
|
-
* 3. Insert DefinitionVersion row
|
|
45
|
-
* 4. Advance draft pointer (live unchanged)
|
|
46
|
-
*
|
|
47
|
-
* publish — pointer flip only, no blob writes.
|
|
21
|
+
* Orchestrates writes spanning IDataProvider + IStorageProvider. Application
|
|
22
|
+
* orchestration, not platform contract — hence not in @selvajs/platform.
|
|
48
23
|
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
24
|
+
* Methods that write both metadata and blobs order the two so a mid-flight
|
|
25
|
+
* failure leaves a state the API can still serve; those reasons sit inline at
|
|
26
|
+
* each write. `publish` and `updateMeta` flip pointers/metadata only and touch
|
|
27
|
+
* storage not at all.
|
|
51
28
|
*/
|
|
52
29
|
export declare class DefinitionService {
|
|
53
30
|
private data;
|
|
@@ -58,15 +35,13 @@ export declare class DefinitionService {
|
|
|
58
35
|
version: DefinitionVersion;
|
|
59
36
|
}>;
|
|
60
37
|
/**
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
* use `publish` to promote.
|
|
38
|
+
* Advances the draft pointer only — `live` is unchanged. Use `publish` to
|
|
39
|
+
* promote.
|
|
64
40
|
*/
|
|
65
41
|
uploadVersion(ctx: RequestContext, guid: string, file: Uint8Array, ext: DefinitionFileExt, originalName: string, schema: UISchema, changeNote?: string): Promise<DefinitionVersion>;
|
|
66
42
|
/**
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
* spec §6 makes rollback a first-class operation.
|
|
43
|
+
* Moves the live channel to `versionId`, or to the current draft if omitted.
|
|
44
|
+
* Any version id is accepted, so this rolls backward as well as forward.
|
|
70
45
|
*/
|
|
71
46
|
publish(ctx: RequestContext, guid: string, versionId?: string): Promise<DefinitionVersion>;
|
|
72
47
|
deleteVersion(ctx: RequestContext, guid: string, versionId: string): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definition-service.d.ts","sourceRoot":"","sources":["../../src/definitions/definition-service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACX,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,mBAAmB,EACnB,QAAQ,EACR,MAAM,mBAAmB,CAAC;AAG3B
|
|
1
|
+
{"version":3,"file":"definition-service.d.ts","sourceRoot":"","sources":["../../src/definitions/definition-service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACX,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,mBAAmB,EACnB,QAAQ,EACR,MAAM,mBAAmB,CAAC;AAG3B;;;;GAIG;AACH,MAAM,WAAW,sBAAsB;IACtC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,iBAAiB,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;;;;;;;GAQG;AACH,qBAAa,iBAAiB;IAE5B,OAAO,CAAC,IAAI;IACZ,OAAO,CAAC,OAAO;gBADP,IAAI,EAAE,aAAa,EACnB,OAAO,EAAE,gBAAgB;IAG5B,MAAM,CACX,GAAG,EAAE,cAAc,EACnB,KAAK,EAAE,sBAAsB,EAC7B,IAAI,EAAE,UAAU,EAChB,MAAM,EAAE,QAAQ,GACd,OAAO,CAAC;QAAE,MAAM,EAAE,gBAAgB,CAAC;QAAC,OAAO,EAAE,iBAAiB,CAAA;KAAE,CAAC;IA4DpE;;;OAGG;IACG,aAAa,CAClB,GAAG,EAAE,cAAc,EACnB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,UAAU,EAChB,GAAG,EAAE,iBAAiB,EACtB,YAAY,EAAE,MAAM,EACpB,MAAM,EAAE,QAAQ,EAChB,UAAU,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,iBAAiB,CAAC;IAkC7B;;;OAGG;IACG,OAAO,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC;IAoB1F,aAAa,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUlF,UAAU,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,mBAAmB,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxF,cAAc,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC;IAQzF,MAAM,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAW9D"}
|
|
@@ -1,33 +1,13 @@
|
|
|
1
1
|
import { randomUUID } from 'node:crypto';
|
|
2
2
|
import { ProviderError, definitionPaths } from '@selvajs/platform';
|
|
3
3
|
/**
|
|
4
|
-
* Orchestrates writes
|
|
5
|
-
*
|
|
6
|
-
* because it is application orchestration, not platform contract.
|
|
4
|
+
* Orchestrates writes spanning IDataProvider + IStorageProvider. Application
|
|
5
|
+
* orchestration, not platform contract — hence not in @selvajs/platform.
|
|
7
6
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
* 2. Upload v1 blob to versions/v1.{ext}
|
|
13
|
-
* 3. Insert DefinitionVersion row v1
|
|
14
|
-
* 4. `attachInitialVersion` — atomically set live + draft pointers and
|
|
15
|
-
* flip status to 'draft' in a single store operation.
|
|
16
|
-
* Step 4 is one round-trip so a mid-flight failure can't leave a partial
|
|
17
|
-
* state (status='draft' with null pointers, or status='pending' with
|
|
18
|
-
* pointers set). If step 2 fails the record stays 'pending' with no
|
|
19
|
-
* blob and is filtered out of list endpoints by default.
|
|
20
|
-
*
|
|
21
|
-
* uploadVersion — append-only:
|
|
22
|
-
* 1. Reserve next versionNumber from the record's monotonic counter
|
|
23
|
-
* 2. Upload blob to versions/v{N}.{ext}
|
|
24
|
-
* 3. Insert DefinitionVersion row
|
|
25
|
-
* 4. Advance draft pointer (live unchanged)
|
|
26
|
-
*
|
|
27
|
-
* publish — pointer flip only, no blob writes.
|
|
28
|
-
*
|
|
29
|
-
* deleteVersion — store enforces "not referenced by live/draft"; on
|
|
30
|
-
* success, delete the underlying blob.
|
|
7
|
+
* Methods that write both metadata and blobs order the two so a mid-flight
|
|
8
|
+
* failure leaves a state the API can still serve; those reasons sit inline at
|
|
9
|
+
* each write. `publish` and `updateMeta` flip pointers/metadata only and touch
|
|
10
|
+
* storage not at all.
|
|
31
11
|
*/
|
|
32
12
|
export class DefinitionService {
|
|
33
13
|
data;
|
|
@@ -61,14 +41,13 @@ export class DefinitionService {
|
|
|
61
41
|
updatedAt: now,
|
|
62
42
|
deletedAt: null
|
|
63
43
|
};
|
|
64
|
-
//
|
|
44
|
+
// Metadata first — if this fails there's nothing to clean up.
|
|
65
45
|
await this.data.definitions.create(ctx, record);
|
|
66
|
-
//
|
|
67
|
-
//
|
|
46
|
+
// If the blob write fails, the record stays 'pending' and is hidden from
|
|
47
|
+
// default list queries.
|
|
68
48
|
const versionId = randomUUID();
|
|
69
49
|
const fileKey = definitionPaths.version(input.guid, 1, input.fileExt);
|
|
70
50
|
await this.storage.put(fileKey, file, 'application/octet-stream');
|
|
71
|
-
// 3. Version row.
|
|
72
51
|
const version = {
|
|
73
52
|
id: versionId,
|
|
74
53
|
definitionId: input.guid,
|
|
@@ -82,10 +61,9 @@ export class DefinitionService {
|
|
|
82
61
|
schemaExtractedAt: now
|
|
83
62
|
};
|
|
84
63
|
await this.data.definitions.createVersion(ctx, version);
|
|
85
|
-
//
|
|
86
|
-
//
|
|
87
|
-
//
|
|
88
|
-
// header for why ordering matters here.
|
|
64
|
+
// Points both channels at v1 and flips status='draft' in ONE store
|
|
65
|
+
// operation. Doing it as three writes leaves a partial state on failure:
|
|
66
|
+
// status='draft' with null pointers, or 'pending' with pointers set.
|
|
89
67
|
await this.data.definitions.attachInitialVersion(ctx, input.guid, versionId);
|
|
90
68
|
return {
|
|
91
69
|
record: { ...record, status: 'draft', liveVersionId: versionId, draftVersionId: versionId },
|
|
@@ -93,18 +71,16 @@ export class DefinitionService {
|
|
|
93
71
|
};
|
|
94
72
|
}
|
|
95
73
|
/**
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
* use `publish` to promote.
|
|
74
|
+
* Advances the draft pointer only — `live` is unchanged. Use `publish` to
|
|
75
|
+
* promote.
|
|
99
76
|
*/
|
|
100
77
|
async uploadVersion(ctx, guid, file, ext, originalName, schema, changeNote) {
|
|
101
78
|
const existing = await this.data.definitions.get(ctx, guid);
|
|
102
79
|
if (!existing)
|
|
103
80
|
throw new ProviderError(`Definition not found: ${guid}`, 404);
|
|
104
|
-
//
|
|
105
|
-
//
|
|
106
|
-
//
|
|
107
|
-
// advances, so a delete-then-reupload gets a fresh number and fresh key.
|
|
81
|
+
// Monotonic counter, NOT max(existing)+1 — the latter reuses a number after
|
|
82
|
+
// delete-latest and collides the `fileKey`, serving a stale blob for new
|
|
83
|
+
// content.
|
|
108
84
|
const next = await this.data.definitions.reserveNextVersionNumber(ctx, guid);
|
|
109
85
|
const versionId = randomUUID();
|
|
110
86
|
const fileKey = definitionPaths.version(guid, next, ext);
|
|
@@ -129,9 +105,8 @@ export class DefinitionService {
|
|
|
129
105
|
return version;
|
|
130
106
|
}
|
|
131
107
|
/**
|
|
132
|
-
*
|
|
133
|
-
*
|
|
134
|
-
* spec §6 makes rollback a first-class operation.
|
|
108
|
+
* Moves the live channel to `versionId`, or to the current draft if omitted.
|
|
109
|
+
* Any version id is accepted, so this rolls backward as well as forward.
|
|
135
110
|
*/
|
|
136
111
|
async publish(ctx, guid, versionId) {
|
|
137
112
|
const existing = await this.data.definitions.get(ctx, guid);
|
|
@@ -171,16 +146,13 @@ export class DefinitionService {
|
|
|
171
146
|
return url;
|
|
172
147
|
}
|
|
173
148
|
async delete(ctx, guid) {
|
|
174
|
-
//
|
|
175
|
-
//
|
|
176
|
-
// record is the audit trail; the blobs are storage cost.
|
|
149
|
+
// Metadata is soft-deleted (audit trail, restorable by clearing
|
|
150
|
+
// `deleted_at`); blobs are HARD-deleted.
|
|
177
151
|
//
|
|
178
|
-
//
|
|
179
|
-
//
|
|
180
|
-
//
|
|
181
|
-
//
|
|
182
|
-
// window where the record is still alive but its blobs are gone — a
|
|
183
|
-
// 404 source for any in-flight reader.
|
|
152
|
+
// Metadata first, so the API hides the record immediately. A failed blob
|
|
153
|
+
// wipe then leaves orphan storage that no reader can reach, for a
|
|
154
|
+
// retention sweep to collect. The reverse order leaves the record alive
|
|
155
|
+
// with its blobs gone — a 404 for any in-flight reader.
|
|
184
156
|
await this.data.definitions.delete(ctx, guid);
|
|
185
157
|
await this.storage.deletePrefix(definitionPaths.prefix(guid));
|
|
186
158
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"definition-service.js","sourceRoot":"","sources":["../../src/definitions/definition-service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAWzC,OAAO,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"definition-service.js","sourceRoot":"","sources":["../../src/definitions/definition-service.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export { DefinitionService, type CreateDefinitionRecord } from './definition-service.js';
|
|
2
|
-
export { fetchSchemaFromCompute, postSchemaFormData, assertSupportedSchemaVersion, readSchemaResults, SchemaExtractionError } from './schema-extraction.js';
|
|
2
|
+
export { fetchSchemaFromCompute, postSchemaFormData, assertSupportedSchemaVersion, assertCamelCaseSchema, readSchemaResults, SchemaExtractionError } from './schema-extraction.js';
|
|
3
3
|
export type { SchemaExtractionResult } from './schema-extraction.js';
|
|
4
|
-
export { createDefinitionLoader, DefinitionLoadError, type DefinitionChannel, type DefinitionLoader, type DefinitionLoaderDeps, type DefinitionLoadErrorKind, type LoadedDefinition } from './load-for-render.js';
|
|
4
|
+
export { createDefinitionLoader, DefinitionLoadError, type DefinitionChannel, type DefinitionLoader, type DefinitionLoaderDeps, type DefinitionLoadErrorKind, type DefinitionLoadOptions, type LoadedDefinition } from './load-for-render.js';
|
|
5
5
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/definitions/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/definitions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,KAAK,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAEzF,OAAO,EACN,sBAAsB,EACtB,kBAAkB,EAClB,4BAA4B,EAC5B,qBAAqB,EACrB,iBAAiB,EACjB,qBAAqB,EACrB,MAAM,wBAAwB,CAAC;AAChC,YAAY,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AAErE,OAAO,EACN,sBAAsB,EACtB,mBAAmB,EACnB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC5B,KAAK,qBAAqB,EAC1B,KAAK,gBAAgB,EACrB,MAAM,sBAAsB,CAAC"}
|
|
@@ -1,8 +1,4 @@
|
|
|
1
|
-
// Definitions server slice — the write orchestration (DefinitionService), the
|
|
2
|
-
// compute-schema extraction/validation gate, and the render loader. All
|
|
3
|
-
// composition-root wiring (stores, warm-client cache, server resolution) is
|
|
4
|
-
// injected; access gating stays with the calling app.
|
|
5
1
|
export { DefinitionService } from './definition-service.js';
|
|
6
|
-
export { fetchSchemaFromCompute, postSchemaFormData, assertSupportedSchemaVersion, readSchemaResults, SchemaExtractionError } from './schema-extraction.js';
|
|
2
|
+
export { fetchSchemaFromCompute, postSchemaFormData, assertSupportedSchemaVersion, assertCamelCaseSchema, readSchemaResults, SchemaExtractionError } from './schema-extraction.js';
|
|
7
3
|
export { createDefinitionLoader, DefinitionLoadError } from './load-for-render.js';
|
|
8
4
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/definitions/index.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/definitions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAA+B,MAAM,yBAAyB,CAAC;AAEzF,OAAO,EACN,sBAAsB,EACtB,kBAAkB,EAClB,4BAA4B,EAC5B,qBAAqB,EACrB,iBAAiB,EACjB,qBAAqB,EACrB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EACN,sBAAsB,EACtB,mBAAmB,EAOnB,MAAM,sBAAsB,CAAC"}
|
|
@@ -26,11 +26,11 @@ export interface DefinitionLoaderDeps {
|
|
|
26
26
|
storage: Pick<IStorageProvider, 'get'>;
|
|
27
27
|
definitions: Pick<IDefinitionStore, 'getVersion' | 'setVersionSchema'>;
|
|
28
28
|
projects: Pick<IProjectStore, 'getProject'>;
|
|
29
|
-
/**
|
|
29
|
+
/** Resolution order: definition pin → org default override → global default. */
|
|
30
30
|
resolveServer: (ctx: RequestContext, orgId: string | null, opts: {
|
|
31
31
|
definitionPin: string | null;
|
|
32
32
|
}) => Promise<ComputeServerConfig>;
|
|
33
|
-
/** Shared warm-client cache
|
|
33
|
+
/** Shared warm-client cache, keyed by server id with a definition-guid affinity header. */
|
|
34
34
|
getClient: (server: ComputeServerConfig, opts: {
|
|
35
35
|
definitionGuid: string;
|
|
36
36
|
}) => Promise<{
|
|
@@ -39,32 +39,35 @@ export interface DefinitionLoaderDeps {
|
|
|
39
39
|
/** Schema extraction; defaults to `fetchSchemaFromCompute`. Injectable for tests. */
|
|
40
40
|
fetchSchema?: (bytes: Uint8Array, server: ComputeServerConfig) => Promise<UISchema>;
|
|
41
41
|
/**
|
|
42
|
-
*
|
|
43
|
-
*
|
|
44
|
-
* casing/serialization mismatches are visible.
|
|
42
|
+
* When set, an unhealthy IO result also dumps the raw /io wire shape, making
|
|
43
|
+
* casing/serialization mismatches visible.
|
|
45
44
|
*/
|
|
46
45
|
computeDebug?: boolean;
|
|
47
|
-
/**
|
|
48
|
-
* Legacy diagnostic sink, kept for callers that already pass one. When set it
|
|
49
|
-
* receives the rendered strings and `logger` is not used for these warnings.
|
|
50
|
-
*/
|
|
46
|
+
/** Legacy diagnostic sink. When set it takes the warnings below instead of `logger`. */
|
|
51
47
|
onWarn?: (message: string, detail?: string) => void;
|
|
52
48
|
/**
|
|
53
|
-
*
|
|
54
|
-
*
|
|
49
|
+
* Defaults to `NoopLogger`, so a consumer that wires nothing gets silence
|
|
50
|
+
* rather than unsolicited stdout.
|
|
55
51
|
*/
|
|
56
52
|
logger?: ILogger;
|
|
57
53
|
}
|
|
58
|
-
export
|
|
54
|
+
export interface DefinitionLoadOptions {
|
|
55
|
+
/**
|
|
56
|
+
* For callers that read only schema STRUCTURE (input ids, `source.key`,
|
|
57
|
+
* widget types — anything persisted at upload). A fresh cached schema then
|
|
58
|
+
* returns without touching compute, whose multi-second connect otherwise
|
|
59
|
+
* dominates a page resolving several definitions.
|
|
60
|
+
*
|
|
61
|
+
* Leave unset (the default) for anything that RENDERS a form — without
|
|
62
|
+
* compute defaults the form shows the wrong initial values.
|
|
63
|
+
*/
|
|
64
|
+
skipComputeDefaults?: boolean;
|
|
65
|
+
}
|
|
66
|
+
export type DefinitionLoader = (ctx: RequestContext, record: DefinitionRecord, channel: DefinitionChannel, explicitVersionId?: string | null, options?: DefinitionLoadOptions) => Promise<LoadedDefinition>;
|
|
59
67
|
/**
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
* merged compute defaults). By default it resolves the `channel` pointer
|
|
64
|
-
* (live/draft); pass `explicitVersionId` to render an arbitrary historical
|
|
65
|
-
* version instead — the caller must gate that behind edit permission
|
|
66
|
-
* (editor-only, like the draft channel). Throws `DefinitionLoadError` for
|
|
67
|
-
* classified failures so the caller can translate to HTTP status codes.
|
|
68
|
+
* The returned loader resolves the `channel` pointer (live/draft) by default.
|
|
69
|
+
* `explicitVersionId` renders an arbitrary historical version instead — the
|
|
70
|
+
* caller MUST gate that behind edit permission, as with the draft channel.
|
|
68
71
|
*/
|
|
69
72
|
export declare function createDefinitionLoader(deps: DefinitionLoaderDeps): DefinitionLoader;
|
|
70
73
|
//# sourceMappingURL=load-for-render.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"load-for-render.d.ts","sourceRoot":"","sources":["../../src/definitions/load-for-render.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"load-for-render.d.ts","sourceRoot":"","sources":["../../src/definitions/load-for-render.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACtE,OAAO,EAAqB,KAAK,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,KAAK,EACX,mBAAmB,EACnB,gBAAgB,EAChB,iBAAiB,EACjB,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAc,KAAK,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAG7D,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,OAAO,CAAC;AAEjD,MAAM,WAAW,gBAAgB;IAChC,OAAO,EAAE,iBAAiB,CAAC;IAC3B,gBAAgB,EAAE,UAAU,CAAC;IAC7B,aAAa,EAAE,mBAAmB,CAAC;IACnC,MAAM,EAAE,QAAQ,CAAC;CACjB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,uBAAuB,GAAG,MAAM,GAAG,gBAAgB,GAAG,SAAS,GAAG,QAAQ,CAAC;AAEvF,qBAAa,mBAAoB,SAAQ,KAAK;aAE5B,IAAI,EAAE,uBAAuB;aAE7B,KAAK,CAAC,EAAE,OAAO;gBAFf,IAAI,EAAE,uBAAuB,EAC7C,OAAO,EAAE,MAAM,EACC,KAAK,CAAC,EAAE,OAAO,YAAA;CAKhC;AAED,MAAM,WAAW,oBAAoB;IACpC,OAAO,EAAE,IAAI,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;IACvC,WAAW,EAAE,IAAI,CAAC,gBAAgB,EAAE,YAAY,GAAG,kBAAkB,CAAC,CAAC;IACvE,QAAQ,EAAE,IAAI,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC;IAC5C,gFAAgF;IAChF,aAAa,EAAE,CACd,GAAG,EAAE,cAAc,EACnB,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,IAAI,EAAE;QAAE,aAAa,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,KAClC,OAAO,CAAC,mBAAmB,CAAC,CAAC;IAClC,2FAA2F;IAC3F,SAAS,EAAE,CACV,MAAM,EAAE,mBAAmB,EAC3B,IAAI,EAAE;QAAE,cAAc,EAAE,MAAM,CAAA;KAAE,KAC5B,OAAO,CAAC;QAAE,MAAM,EAAE,iBAAiB,CAAA;KAAE,CAAC,CAAC;IAC5C,qFAAqF;IACrF,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,EAAE,mBAAmB,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;IACpF;;;OAGG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,wFAAwF;IACxF,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD;;;OAGG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,qBAAqB;IACrC;;;;;;;;OAQG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,MAAM,gBAAgB,GAAG,CAC9B,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,gBAAgB,EACxB,OAAO,EAAE,iBAAiB,EAC1B,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,EACjC,OAAO,CAAC,EAAE,qBAAqB,KAC3B,OAAO,CAAC,gBAAgB,CAAC,CAAC;AAE/B;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,oBAAoB,GAAG,gBAAgB,CAqKnF"}
|