@selvajs/server 0.2.0-beta.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.
Files changed (123) hide show
  1. package/LICENSE +21 -0
  2. package/dist/compute/__tests__/client-cache.test.d.ts +11 -0
  3. package/dist/compute/__tests__/client-cache.test.d.ts.map +1 -0
  4. package/dist/compute/__tests__/client-cache.test.js +149 -0
  5. package/dist/compute/__tests__/client-cache.test.js.map +1 -0
  6. package/dist/compute/__tests__/rate-limit.test.d.ts +2 -0
  7. package/dist/compute/__tests__/rate-limit.test.d.ts.map +1 -0
  8. package/dist/compute/__tests__/rate-limit.test.js +62 -0
  9. package/dist/compute/__tests__/rate-limit.test.js.map +1 -0
  10. package/dist/compute/__tests__/remote-definition.test.d.ts +11 -0
  11. package/dist/compute/__tests__/remote-definition.test.d.ts.map +1 -0
  12. package/dist/compute/__tests__/remote-definition.test.js +114 -0
  13. package/dist/compute/__tests__/remote-definition.test.js.map +1 -0
  14. package/dist/compute/__tests__/safe-url.test.d.ts +2 -0
  15. package/dist/compute/__tests__/safe-url.test.d.ts.map +1 -0
  16. package/dist/compute/__tests__/safe-url.test.js +71 -0
  17. package/dist/compute/__tests__/safe-url.test.js.map +1 -0
  18. package/dist/compute/__tests__/solve-pipeline.test.d.ts +11 -0
  19. package/dist/compute/__tests__/solve-pipeline.test.d.ts.map +1 -0
  20. package/dist/compute/__tests__/solve-pipeline.test.js +245 -0
  21. package/dist/compute/__tests__/solve-pipeline.test.js.map +1 -0
  22. package/dist/compute/__tests__/transform-input.test.d.ts +14 -0
  23. package/dist/compute/__tests__/transform-input.test.d.ts.map +1 -0
  24. package/dist/compute/__tests__/transform-input.test.js +114 -0
  25. package/dist/compute/__tests__/transform-input.test.js.map +1 -0
  26. package/dist/compute/client-cache.d.ts +104 -0
  27. package/dist/compute/client-cache.d.ts.map +1 -0
  28. package/dist/compute/client-cache.js +147 -0
  29. package/dist/compute/client-cache.js.map +1 -0
  30. package/dist/compute/index.d.ts +8 -0
  31. package/dist/compute/index.d.ts.map +1 -0
  32. package/dist/compute/index.js +9 -0
  33. package/dist/compute/index.js.map +1 -0
  34. package/dist/compute/limits.d.ts +102 -0
  35. package/dist/compute/limits.d.ts.map +1 -0
  36. package/dist/compute/limits.js +76 -0
  37. package/dist/compute/limits.js.map +1 -0
  38. package/dist/compute/rate-limit.d.ts +49 -0
  39. package/dist/compute/rate-limit.d.ts.map +1 -0
  40. package/dist/compute/rate-limit.js +49 -0
  41. package/dist/compute/rate-limit.js.map +1 -0
  42. package/dist/compute/remote-definition.d.ts +53 -0
  43. package/dist/compute/remote-definition.d.ts.map +1 -0
  44. package/dist/compute/remote-definition.js +110 -0
  45. package/dist/compute/remote-definition.js.map +1 -0
  46. package/dist/compute/safe-url.d.ts +15 -0
  47. package/dist/compute/safe-url.d.ts.map +1 -0
  48. package/dist/compute/safe-url.js +195 -0
  49. package/dist/compute/safe-url.js.map +1 -0
  50. package/dist/compute/solve-pipeline.d.ts +127 -0
  51. package/dist/compute/solve-pipeline.d.ts.map +1 -0
  52. package/dist/compute/solve-pipeline.js +195 -0
  53. package/dist/compute/solve-pipeline.js.map +1 -0
  54. package/dist/compute/transform-input.d.ts +20 -0
  55. package/dist/compute/transform-input.d.ts.map +1 -0
  56. package/dist/compute/transform-input.js +47 -0
  57. package/dist/compute/transform-input.js.map +1 -0
  58. package/dist/definitions/__tests__/load-for-render.test.d.ts +8 -0
  59. package/dist/definitions/__tests__/load-for-render.test.d.ts.map +1 -0
  60. package/dist/definitions/__tests__/load-for-render.test.js +196 -0
  61. package/dist/definitions/__tests__/load-for-render.test.js.map +1 -0
  62. package/dist/definitions/__tests__/schema-extraction.test.d.ts +11 -0
  63. package/dist/definitions/__tests__/schema-extraction.test.d.ts.map +1 -0
  64. package/dist/definitions/__tests__/schema-extraction.test.js +115 -0
  65. package/dist/definitions/__tests__/schema-extraction.test.js.map +1 -0
  66. package/dist/definitions/definition-service.d.ts +77 -0
  67. package/dist/definitions/definition-service.d.ts.map +1 -0
  68. package/dist/definitions/definition-service.js +184 -0
  69. package/dist/definitions/definition-service.js.map +1 -0
  70. package/dist/definitions/index.d.ts +4 -0
  71. package/dist/definitions/index.d.ts.map +1 -0
  72. package/dist/definitions/index.js +8 -0
  73. package/dist/definitions/index.js.map +1 -0
  74. package/dist/definitions/load-for-render.d.ts +61 -0
  75. package/dist/definitions/load-for-render.d.ts.map +1 -0
  76. package/dist/definitions/load-for-render.js +165 -0
  77. package/dist/definitions/load-for-render.js.map +1 -0
  78. package/dist/definitions/schema-extraction.d.ts +22 -0
  79. package/dist/definitions/schema-extraction.d.ts.map +1 -0
  80. package/dist/definitions/schema-extraction.js +89 -0
  81. package/dist/definitions/schema-extraction.js.map +1 -0
  82. package/dist/index.d.ts +18 -0
  83. package/dist/index.d.ts.map +1 -0
  84. package/dist/index.js +18 -0
  85. package/dist/index.js.map +1 -0
  86. package/dist/providers/__tests__/create-selva-providers.test.d.ts +7 -0
  87. package/dist/providers/__tests__/create-selva-providers.test.d.ts.map +1 -0
  88. package/dist/providers/__tests__/create-selva-providers.test.js +135 -0
  89. package/dist/providers/__tests__/create-selva-providers.test.js.map +1 -0
  90. package/dist/providers/create-selva-providers.d.ts +53 -0
  91. package/dist/providers/create-selva-providers.d.ts.map +1 -0
  92. package/dist/providers/create-selva-providers.js +152 -0
  93. package/dist/providers/create-selva-providers.js.map +1 -0
  94. package/dist/providers/index.d.ts +2 -0
  95. package/dist/providers/index.d.ts.map +1 -0
  96. package/dist/providers/index.js +6 -0
  97. package/dist/providers/index.js.map +1 -0
  98. package/package.json +60 -0
  99. package/src/compute/__tests__/client-cache.test.ts +164 -0
  100. package/src/compute/__tests__/rate-limit.test.ts +69 -0
  101. package/src/compute/__tests__/remote-definition.test.ts +140 -0
  102. package/src/compute/__tests__/safe-url.test.ts +72 -0
  103. package/src/compute/__tests__/solve-pipeline.test.ts +294 -0
  104. package/src/compute/__tests__/transform-input.test.ts +155 -0
  105. package/src/compute/client-cache.ts +278 -0
  106. package/src/compute/index.ts +48 -0
  107. package/src/compute/limits.ts +147 -0
  108. package/src/compute/rate-limit.ts +83 -0
  109. package/src/compute/remote-definition.ts +149 -0
  110. package/src/compute/safe-url.ts +186 -0
  111. package/src/compute/solve-pipeline.ts +324 -0
  112. package/src/compute/transform-input.ts +52 -0
  113. package/src/definitions/__tests__/load-for-render.test.ts +244 -0
  114. package/src/definitions/__tests__/schema-extraction.test.ts +137 -0
  115. package/src/definitions/definition-service.ts +243 -0
  116. package/src/definitions/index.ts +22 -0
  117. package/src/definitions/load-for-render.ts +272 -0
  118. package/src/definitions/schema-extraction.ts +117 -0
  119. package/src/index.ts +18 -0
  120. package/src/providers/__tests__/create-selva-providers.test.ts +172 -0
  121. package/src/providers/__tests__/fixtures/override-config.mjs +8 -0
  122. package/src/providers/create-selva-providers.ts +241 -0
  123. package/src/providers/index.ts +12 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-extraction.test.js","sourceRoot":"","sources":["../../../src/definitions/__tests__/schema-extraction.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ import type { IDataProvider, IStorageProvider, RequestContext, DefinitionRecord, DefinitionFileExt, DefinitionVersion, UpdateMetadataInput, UISchema } from '@selvajs/platform';
2
+ /**
3
+ * Input passed to `DefinitionService.create`. Carries everything the service
4
+ * needs to assemble a `DefinitionRecord` plus orchestrate the v1 upload.
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).
9
+ */
10
+ export interface CreateDefinitionRecord {
11
+ guid: string;
12
+ projectId: string;
13
+ ownerId: string;
14
+ fileExt: DefinitionFileExt;
15
+ originalFilename?: string;
16
+ displayName: string;
17
+ description?: string;
18
+ category?: string;
19
+ tags?: string[];
20
+ coverImage?: string;
21
+ computeServerId?: string;
22
+ }
23
+ /**
24
+ * Orchestrates writes that span IDataProvider + IStorageProvider for the
25
+ * spec §6 versioning model. Lives in @selvajs/selva (not @selvajs/platform)
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. Resolve next versionNumber from the version list
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.
48
+ *
49
+ * deleteVersion — store enforces "not referenced by live/draft"; on
50
+ * success, delete the underlying blob.
51
+ */
52
+ export declare class DefinitionService {
53
+ private data;
54
+ private storage;
55
+ constructor(data: IDataProvider, storage: IStorageProvider);
56
+ create(ctx: RequestContext, input: CreateDefinitionRecord, file: Uint8Array, schema: UISchema): Promise<{
57
+ record: DefinitionRecord;
58
+ version: DefinitionVersion;
59
+ }>;
60
+ /**
61
+ * Upload a new version of an existing definition. Writes the blob, inserts
62
+ * the version row, and advances the draft pointer. `live` is unchanged —
63
+ * use `publish` to promote.
64
+ */
65
+ uploadVersion(ctx: RequestContext, guid: string, file: Uint8Array, ext: DefinitionFileExt, originalName: string, schema: UISchema, changeNote?: string): Promise<DefinitionVersion>;
66
+ /**
67
+ * Advance the live channel. If `versionId` is omitted, promotes the
68
+ * current draft. Pass an arbitrary version id to roll forward/back —
69
+ * spec §6 makes rollback a first-class operation.
70
+ */
71
+ publish(ctx: RequestContext, guid: string, versionId?: string): Promise<DefinitionVersion>;
72
+ deleteVersion(ctx: RequestContext, guid: string, versionId: string): Promise<void>;
73
+ updateMeta(ctx: RequestContext, guid: string, patch: UpdateMetadataInput): Promise<void>;
74
+ saveCoverImage(ctx: RequestContext, guid: string, imageData: Uint8Array): Promise<string>;
75
+ delete(ctx: RequestContext, guid: string): Promise<void>;
76
+ }
77
+ //# sourceMappingURL=definition-service.d.ts.map
@@ -0,0 +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;;;;;;;GAOG;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;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;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;;;;OAIG;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;IAiC7B;;;;OAIG;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;CAc9D"}
@@ -0,0 +1,184 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { ProviderError, definitionPaths } from '@selvajs/platform';
3
+ /**
4
+ * Orchestrates writes that span IDataProvider + IStorageProvider for the
5
+ * spec §6 versioning model. Lives in @selvajs/selva (not @selvajs/platform)
6
+ * because it is application orchestration, not platform contract.
7
+ *
8
+ * Ordering rules:
9
+ *
10
+ * create — metadata-first, then v1:
11
+ * 1. Write record with status='pending', both pointers null
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. Resolve next versionNumber from the version list
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.
31
+ */
32
+ export class DefinitionService {
33
+ data;
34
+ storage;
35
+ constructor(data, storage) {
36
+ this.data = data;
37
+ this.storage = storage;
38
+ }
39
+ async create(ctx, input, file, schema) {
40
+ const now = new Date().toISOString();
41
+ const actor = ctx.userId || input.ownerId;
42
+ const record = {
43
+ guid: input.guid,
44
+ projectId: input.projectId,
45
+ ownerId: input.ownerId,
46
+ createdBy: actor,
47
+ updatedBy: actor,
48
+ displayName: input.displayName,
49
+ description: input.description,
50
+ category: input.category,
51
+ tags: input.tags,
52
+ coverImage: input.coverImage,
53
+ computeServerId: input.computeServerId,
54
+ status: 'pending',
55
+ solveCount: 0,
56
+ liveVersionId: null,
57
+ draftVersionId: null,
58
+ createdAt: now,
59
+ updatedAt: now,
60
+ deletedAt: null
61
+ };
62
+ // 1. Metadata first — if this fails there's nothing to clean up.
63
+ await this.data.definitions.create(ctx, record);
64
+ // 2. v1 blob — if this fails the record stays 'pending' and is hidden
65
+ // from default list queries.
66
+ const versionId = randomUUID();
67
+ const fileKey = definitionPaths.version(input.guid, 1, input.fileExt);
68
+ await this.storage.put(fileKey, file, 'application/octet-stream');
69
+ // 3. Version row.
70
+ const version = {
71
+ id: versionId,
72
+ definitionId: input.guid,
73
+ versionNumber: 1,
74
+ fileExt: input.fileExt,
75
+ fileKey,
76
+ originalFilename: input.originalFilename,
77
+ uploadedBy: actor,
78
+ uploadedAt: now,
79
+ schema,
80
+ schemaExtractedAt: now
81
+ };
82
+ await this.data.definitions.createVersion(ctx, version);
83
+ // 4. Atomically point both channels at v1 and flip status='draft' in a
84
+ // single store operation. Replaces three separate writes
85
+ // (setLiveVersion + setDraftVersion + update) — see the class
86
+ // header for why ordering matters here.
87
+ await this.data.definitions.attachInitialVersion(ctx, input.guid, versionId);
88
+ return {
89
+ record: { ...record, status: 'draft', liveVersionId: versionId, draftVersionId: versionId },
90
+ version
91
+ };
92
+ }
93
+ /**
94
+ * Upload a new version of an existing definition. Writes the blob, inserts
95
+ * the version row, and advances the draft pointer. `live` is unchanged —
96
+ * use `publish` to promote.
97
+ */
98
+ async uploadVersion(ctx, guid, file, ext, originalName, schema, changeNote) {
99
+ const existing = await this.data.definitions.get(ctx, guid);
100
+ if (!existing)
101
+ throw new ProviderError(`Definition not found: ${guid}`, 404);
102
+ // Highest existing versionNumber + 1; covers gaps from deletions.
103
+ const versions = await this.data.definitions.listVersions(ctx, guid, { limit: 1 });
104
+ const next = (versions.items[0]?.versionNumber ?? 0) + 1;
105
+ const versionId = randomUUID();
106
+ const fileKey = definitionPaths.version(guid, next, ext);
107
+ await this.storage.put(fileKey, file, 'application/octet-stream');
108
+ const now = new Date().toISOString();
109
+ const actor = ctx.userId || existing.ownerId;
110
+ const version = {
111
+ id: versionId,
112
+ definitionId: guid,
113
+ versionNumber: next,
114
+ fileExt: ext,
115
+ fileKey,
116
+ originalFilename: originalName,
117
+ uploadedBy: actor,
118
+ uploadedAt: now,
119
+ changeNote: changeNote?.trim() || undefined,
120
+ schema,
121
+ schemaExtractedAt: now
122
+ };
123
+ await this.data.definitions.createVersion(ctx, version);
124
+ await this.data.definitions.setDraftVersion(ctx, guid, versionId);
125
+ return version;
126
+ }
127
+ /**
128
+ * Advance the live channel. If `versionId` is omitted, promotes the
129
+ * current draft. Pass an arbitrary version id to roll forward/back —
130
+ * spec §6 makes rollback a first-class operation.
131
+ */
132
+ async publish(ctx, guid, versionId) {
133
+ const existing = await this.data.definitions.get(ctx, guid);
134
+ if (!existing)
135
+ throw new ProviderError(`Definition not found: ${guid}`, 404);
136
+ const target = versionId ?? existing.draftVersionId;
137
+ if (!target)
138
+ throw new ProviderError('No version to publish', 400);
139
+ const version = await this.data.definitions.getVersion(ctx, target);
140
+ if (!version || version.definitionId !== guid) {
141
+ throw new ProviderError(`Version '${target}' not found for this definition`, 404);
142
+ }
143
+ await this.data.definitions.setLiveVersion(ctx, guid, target);
144
+ // Flip status to 'published' the first time live moves off pending/draft.
145
+ if (existing.status === 'draft' || existing.status === 'pending') {
146
+ await this.data.definitions.update(ctx, guid, { status: 'published' });
147
+ }
148
+ return version;
149
+ }
150
+ async deleteVersion(ctx, guid, versionId) {
151
+ const version = await this.data.definitions.getVersion(ctx, versionId);
152
+ if (!version || version.definitionId !== guid) {
153
+ throw new ProviderError(`Version '${versionId}' not found for this definition`, 404);
154
+ }
155
+ // Store enforces the live/draft reference check; if it throws, blob stays.
156
+ await this.data.definitions.deleteVersion(ctx, versionId);
157
+ await this.storage.delete(version.fileKey);
158
+ }
159
+ async updateMeta(ctx, guid, patch) {
160
+ await this.data.definitions.update(ctx, guid, patch);
161
+ }
162
+ async saveCoverImage(ctx, guid, imageData) {
163
+ const path = definitionPaths.image(guid);
164
+ await this.storage.put(path, imageData, 'image/webp');
165
+ const url = this.storage.getPublicUrl(path);
166
+ await this.data.definitions.update(ctx, guid, { coverImage: url });
167
+ return url;
168
+ }
169
+ async delete(ctx, guid) {
170
+ // CONTRACT (spec §9): metadata is soft-deleted (preserved for audit,
171
+ // restorable by clearing `deleted_at`); blobs are HARD-deleted. The
172
+ // record is the audit trail; the blobs are storage cost.
173
+ //
174
+ // Order matters. Metadata first so the API immediately hides the
175
+ // record (RLS / `deleted_at IS NULL` filter). If the blob wipe then
176
+ // fails, the orphan storage is unreachable through the API — a
177
+ // retention sweep can clean it up later. The reverse order leaves a
178
+ // window where the record is still alive but its blobs are gone — a
179
+ // 404 source for any in-flight reader.
180
+ await this.data.definitions.delete(ctx, guid);
181
+ await this.storage.deletePrefix(definitionPaths.prefix(guid));
182
+ }
183
+ }
184
+ //# sourceMappingURL=definition-service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"definition-service.js","sourceRoot":"","sources":["../../src/definitions/definition-service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { DefinitionService, type CreateDefinitionRecord } from './definition-service.js';
2
+ export { fetchSchemaFromCompute, assertSupportedSchemaVersion, SchemaExtractionError } from './schema-extraction.js';
3
+ export { createDefinitionLoader, DefinitionLoadError, type DefinitionChannel, type DefinitionLoader, type DefinitionLoaderDeps, type DefinitionLoadErrorKind, type LoadedDefinition } from './load-for-render.js';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/definitions/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,iBAAiB,EAAE,KAAK,sBAAsB,EAAE,MAAM,yBAAyB,CAAC;AAEzF,OAAO,EACN,sBAAsB,EACtB,4BAA4B,EAC5B,qBAAqB,EACrB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACN,sBAAsB,EACtB,mBAAmB,EACnB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,oBAAoB,EACzB,KAAK,uBAAuB,EAC5B,KAAK,gBAAgB,EACrB,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,8 @@
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
+ export { DefinitionService } from './definition-service.js';
6
+ export { fetchSchemaFromCompute, assertSupportedSchemaVersion, SchemaExtractionError } from './schema-extraction.js';
7
+ export { createDefinitionLoader, DefinitionLoadError } from './load-for-render.js';
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/definitions/index.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,wEAAwE;AACxE,4EAA4E;AAC5E,sDAAsD;AAEtD,OAAO,EAAE,iBAAiB,EAA+B,MAAM,yBAAyB,CAAC;AAEzF,OAAO,EACN,sBAAsB,EACtB,4BAA4B,EAC5B,qBAAqB,EACrB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACN,sBAAsB,EACtB,mBAAmB,EAMnB,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,61 @@
1
+ import type { GrasshopperClient } from '@selvajs/compute/grasshopper';
2
+ import { type UISchema } from '@selvajs/schemas';
3
+ import type { ComputeServerConfig, DefinitionRecord, DefinitionVersion, IDefinitionStore, IProjectStore, IStorageProvider, RequestContext } from '@selvajs/platform';
4
+ export type DefinitionChannel = 'live' | 'draft';
5
+ export interface LoadedDefinition {
6
+ version: DefinitionVersion;
7
+ definitionSource: Uint8Array;
8
+ computeServer: ComputeServerConfig;
9
+ schema: UISchema;
10
+ }
11
+ /**
12
+ * Classified failure modes so callers can map to appropriate HTTP status:
13
+ * - 'data': record references a version/blob that isn't there. (400)
14
+ * - 'missing-config': no compute server resolvable for this org/definition. (503)
15
+ * - 'connect': compute server is configured but unreachable. (503)
16
+ * - 'schema': compute responded but IO/schema phase failed. (500)
17
+ */
18
+ export type DefinitionLoadErrorKind = 'data' | 'missing-config' | 'connect' | 'schema';
19
+ export declare class DefinitionLoadError extends Error {
20
+ readonly kind: DefinitionLoadErrorKind;
21
+ readonly cause?: unknown | undefined;
22
+ constructor(kind: DefinitionLoadErrorKind, message: string, cause?: unknown | undefined);
23
+ }
24
+ export interface DefinitionLoaderDeps {
25
+ storage: Pick<IStorageProvider, 'get'>;
26
+ definitions: Pick<IDefinitionStore, 'getVersion' | 'setVersionSchema'>;
27
+ projects: Pick<IProjectStore, 'getProject'>;
28
+ /** §3 resolution order: definition pin → org default override → global default. */
29
+ resolveServer: (ctx: RequestContext, orgId: string | null, opts: {
30
+ definitionPin: string | null;
31
+ }) => Promise<ComputeServerConfig>;
32
+ /** Shared warm-client cache (ADR 0004: keyed by server id, definition-guid affinity header). */
33
+ getClient: (server: ComputeServerConfig, opts: {
34
+ definitionGuid: string;
35
+ }) => Promise<{
36
+ client: GrasshopperClient;
37
+ }>;
38
+ /** Schema extraction; defaults to `fetchSchemaFromCompute`. Injectable for tests. */
39
+ fetchSchema?: (bytes: Uint8Array, server: ComputeServerConfig) => Promise<UISchema>;
40
+ /**
41
+ * Verbose IO diagnostics — when set, an unhealthy IO result (empty inputs /
42
+ * parse / load errors) also dumps the raw /io wire shape so
43
+ * casing/serialization mismatches are visible.
44
+ */
45
+ computeDebug?: boolean;
46
+ /** Diagnostic sink; defaults to `console.warn`. */
47
+ onWarn?: (message: string, detail?: string) => void;
48
+ }
49
+ export type DefinitionLoader = (ctx: RequestContext, record: DefinitionRecord, channel: DefinitionChannel, explicitVersionId?: string | null) => Promise<LoadedDefinition>;
50
+ /**
51
+ * Build a definition loader over the injected stores/compute wiring.
52
+ *
53
+ * The returned function loads a definition's version blob + schema (with
54
+ * merged compute defaults). By default it resolves the `channel` pointer
55
+ * (live/draft); pass `explicitVersionId` to render an arbitrary historical
56
+ * version instead — the caller must gate that behind edit permission
57
+ * (editor-only, like the draft channel). Throws `DefinitionLoadError` for
58
+ * classified failures so the caller can translate to HTTP status codes.
59
+ */
60
+ export declare function createDefinitionLoader(deps: DefinitionLoaderDeps): DefinitionLoader;
61
+ //# sourceMappingURL=load-for-render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-for-render.d.ts","sourceRoot":"","sources":["../../src/definitions/load-for-render.ts"],"names":[],"mappings":"AAYA,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;AAG3B,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,mFAAmF;IACnF,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,gGAAgG;IAChG,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;;;;OAIG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,mDAAmD;IACnD,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CACpD;AAED,MAAM,MAAM,gBAAgB,GAAG,CAC9B,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,gBAAgB,EACxB,OAAO,EAAE,iBAAiB,EAC1B,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,KAC7B,OAAO,CAAC,gBAAgB,CAAC,CAAC;AAE/B;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,IAAI,EAAE,oBAAoB,GAAG,gBAAgB,CA0InF"}
@@ -0,0 +1,165 @@
1
+ // Loader for "given a definition record, produce everything the client needs to
2
+ // render its form and solve it": version resolution, blob fetch, compute-server
3
+ // resolution, schema fetch (with the ADR 0005 staleness check), default merging.
4
+ //
5
+ // Access gating is intentionally NOT done here — the calling route decides
6
+ // whether `ctx` is allowed to load this definition, since gates differ across
7
+ // routes (project membership, segment ownership, share-token, admin override).
8
+ //
9
+ // Everything stateful is injected (`DefinitionLoaderDeps`): stores, server
10
+ // resolution, the warm-client cache, and the schema fetcher — so any app built
11
+ // on the engine can wire its own composition root.
12
+ import { UI_SCHEMA_VERSION } from '@selvajs/schemas';
13
+ import { fetchSchemaFromCompute } from './schema-extraction.js';
14
+ export class DefinitionLoadError extends Error {
15
+ kind;
16
+ cause;
17
+ constructor(kind, message, cause) {
18
+ super(message);
19
+ this.kind = kind;
20
+ this.cause = cause;
21
+ this.name = 'DefinitionLoadError';
22
+ }
23
+ }
24
+ /**
25
+ * Build a definition loader over the injected stores/compute wiring.
26
+ *
27
+ * The returned function loads a definition's version blob + schema (with
28
+ * merged compute defaults). By default it resolves the `channel` pointer
29
+ * (live/draft); pass `explicitVersionId` to render an arbitrary historical
30
+ * version instead — the caller must gate that behind edit permission
31
+ * (editor-only, like the draft channel). Throws `DefinitionLoadError` for
32
+ * classified failures so the caller can translate to HTTP status codes.
33
+ */
34
+ export function createDefinitionLoader(deps) {
35
+ const { storage, definitions, projects, resolveServer, getClient, fetchSchema = fetchSchemaFromCompute, computeDebug = false, onWarn = (message, detail) => (detail ? console.warn(message, detail) : console.warn(message)) } = deps;
36
+ return async function loadDefinitionForRender(ctx, record, channel, explicitVersionId) {
37
+ const versionId = explicitVersionId ?? (channel === 'draft' ? record.draftVersionId : record.liveVersionId);
38
+ if (!versionId)
39
+ throw new DefinitionLoadError('data', `Definition '${record.guid}' has no ${channel} version`);
40
+ const version = await definitions.getVersion(ctx, versionId);
41
+ if (!version)
42
+ throw new DefinitionLoadError('data', `version missing for '${record.guid}'`);
43
+ // An explicitly requested version must belong to this definition.
44
+ if (version.definitionId !== record.guid)
45
+ throw new DefinitionLoadError('data', `version does not belong to '${record.guid}'`);
46
+ const definitionSource = await storage.get(version.fileKey);
47
+ if (!definitionSource)
48
+ throw new DefinitionLoadError('data', `Definition file for '${record.guid}' not found on disk`);
49
+ const project = await projects.getProject(ctx, record.projectId);
50
+ let computeServer;
51
+ try {
52
+ computeServer = await resolveServer(ctx, project?.orgId ?? null, {
53
+ definitionPin: record.computeServerId ?? null
54
+ });
55
+ }
56
+ catch (err) {
57
+ throw new DefinitionLoadError('missing-config', 'No compute server configured for this definition', err);
58
+ }
59
+ // Only the client is used here (getIO); the entry's solve scheduler rides
60
+ // along unused.
61
+ let client;
62
+ try {
63
+ client = (await getClient(computeServer, { definitionGuid: record.guid })).client;
64
+ }
65
+ catch (err) {
66
+ const message = err instanceof Error ? err.message : String(err);
67
+ throw new DefinitionLoadError('connect', `Failed to connect to Rhino Compute server: ${message}`, err);
68
+ }
69
+ try {
70
+ // Prefer the schema cached on the version row (extracted + validated at
71
+ // upload) — but ONLY when its format version matches the app's. The
72
+ // stored schema is a disposable cache (ADR 0005): on a version mismatch
73
+ // (or a pre-caching row with no schema at all) re-extract from compute,
74
+ // whose C# SchemaMigrator emits the current format — the web side never
75
+ // migrates schemas itself. `getIO` is always needed to merge compute
76
+ // default values into the schema, cached or not.
77
+ const cachedSchema = version.schema;
78
+ const freshCache = cachedSchema && cachedSchema.schemaVersion === UI_SCHEMA_VERSION ? cachedSchema : null;
79
+ const [definition, fetchedSchema] = await Promise.all([
80
+ client.getIO(definitionSource),
81
+ freshCache ? Promise.resolve(freshCache) : fetchSchema(definitionSource, computeServer)
82
+ ]);
83
+ // Persist the refreshed schema back onto the version row (best-effort —
84
+ // a viewer context may lack write access; the next editor render or the
85
+ // solve-time backfill will land it). Only when the re-extracted schema
86
+ // is at the app's current version: persisting an older format (compute
87
+ // plugin behind the app) would just go stale again next render.
88
+ if (!freshCache && fetchedSchema.schemaVersion === UI_SCHEMA_VERSION) {
89
+ definitions.setVersionSchema(ctx, version.id, fetchedSchema).catch((err) => {
90
+ onWarn(`[loadForRender] schema cache refresh failed for version ${version.id}: ` +
91
+ `${err instanceof Error ? err.message : String(err)}`);
92
+ });
93
+ }
94
+ if (!definition) {
95
+ throw new Error(`Failed to get definition IO — server returned undefined`);
96
+ }
97
+ // Surface IO health when something looks off: zero inputs, or the compute
98
+ // layer reported parse/load problems (e.g. an empty ValueList because its
99
+ // backing GH component didn't resolve → "Missing Definition Objects", or a
100
+ // PascalCase /io response the parser silently dropped to []). On a problem
101
+ // we also fetch the raw IO so the un-parsed wire shape is in the logs.
102
+ // Always-on warn (cheap, only fires on the unhappy path); the verbose raw
103
+ // dump is gated on `computeDebug`.
104
+ const ioParseErrors = definition.parseErrors ?? [];
105
+ const ioLoadErrors = definition.loadErrors ?? [];
106
+ const ioLooksBroken = definition.inputs.length === 0 || ioParseErrors.length > 0 || ioLoadErrors.length > 0;
107
+ if (ioLooksBroken) {
108
+ onWarn(`[loadForRender] IO health for '${record.guid}':`, JSON.stringify({
109
+ inputCount: definition.inputs.length,
110
+ outputCount: definition.outputs?.length,
111
+ parseErrors: ioParseErrors,
112
+ loadErrors: ioLoadErrors,
113
+ loadWarnings: definition.loadWarnings
114
+ }));
115
+ if (computeDebug) {
116
+ const rawIO = await client
117
+ .getRawIO(definitionSource)
118
+ .catch((e) => ({ error: String(e) }));
119
+ onWarn('[loadForRender] raw /io:', JSON.stringify(rawIO).slice(0, 3000));
120
+ }
121
+ }
122
+ return {
123
+ version,
124
+ definitionSource,
125
+ computeServer,
126
+ schema: mergeComputeDefaults(fetchedSchema, definition.inputs)
127
+ };
128
+ }
129
+ catch (err) {
130
+ if (err instanceof DefinitionLoadError)
131
+ throw err;
132
+ const message = err instanceof Error ? err.message : String(err);
133
+ throw new DefinitionLoadError('schema', message, err);
134
+ }
135
+ };
136
+ }
137
+ // Merge default values from Compute definition into schema inputs.
138
+ // Colors come back as "r,g,b" or "a,r,g,b" strings — convert to hex so the
139
+ // color picker can consume them directly.
140
+ function mergeComputeDefaults(schema, computeInputs) {
141
+ const byParamId = new Map(computeInputs.map((input) => [input.id, input]));
142
+ return {
143
+ ...schema,
144
+ inputs: schema.inputs.map((schemaInput) => {
145
+ const computeInput = byParamId.get(schemaInput.id);
146
+ if (computeInput?.paramType === 'Color' && computeInput.default !== undefined) {
147
+ const toHex = (value) => value.toString(16).padStart(2, '0');
148
+ const parts = String(computeInput.default)
149
+ .split(',')
150
+ .map((s) => parseInt(s.trim(), 10));
151
+ if (parts.length === 3) {
152
+ computeInput.default = `#${toHex(parts[0])}${toHex(parts[1])}${toHex(parts[2])}`;
153
+ }
154
+ else if (parts.length === 4) {
155
+ computeInput.default = `#${toHex(parts[1])}${toHex(parts[2])}${toHex(parts[3])}`;
156
+ }
157
+ }
158
+ if (computeInput && computeInput.default !== undefined) {
159
+ return { ...schemaInput, default: computeInput.default };
160
+ }
161
+ return schemaInput;
162
+ })
163
+ };
164
+ }
165
+ //# sourceMappingURL=load-for-render.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"load-for-render.js","sourceRoot":"","sources":["../../src/definitions/load-for-render.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import { type UISchema } from '@selvajs/schemas';
2
+ import type { ComputeServerConfig } from '@selvajs/platform';
3
+ /** Thrown when compute is reachable but the definition yields no usable schema. */
4
+ export declare class SchemaExtractionError extends Error {
5
+ readonly kind: 'unreachable' | 'invalid' | 'unsupported';
6
+ constructor(kind: 'unreachable' | 'invalid' | 'unsupported', message: string);
7
+ }
8
+ /**
9
+ * Plugin↔app compat gate: reject a schema emitted by a NEWER plugin than this
10
+ * app was built against — its shape may contain constructs the renderer does
11
+ * not know. Older (or missing) versions pass: the compute-side C# migrator
12
+ * always emits its own current version, and an older shape only lacks
13
+ * optional additions.
14
+ */
15
+ export declare function assertSupportedSchemaVersion(schema: UISchema): void;
16
+ /**
17
+ * Fetch the UI schema from Rhino Compute's `/grasshopper/schema` endpoint (no
18
+ * solve required). Throws `SchemaExtractionError` so callers can map to the
19
+ * right HTTP status (503 unreachable / 422 invalid or unsupported).
20
+ */
21
+ export declare function fetchSchemaFromCompute(definitionBytes: Uint8Array, server: ComputeServerConfig): Promise<UISchema>;
22
+ //# sourceMappingURL=schema-extraction.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema-extraction.d.ts","sourceRoot":"","sources":["../../src/definitions/schema-extraction.ts"],"names":[],"mappings":"AAUA,OAAO,EAAqB,KAAK,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACpE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAE7D,mFAAmF;AACnF,qBAAa,qBAAsB,SAAQ,KAAK;aAE9B,IAAI,EAAE,aAAa,GAAG,SAAS,GAAG,aAAa;gBAA/C,IAAI,EAAE,aAAa,GAAG,SAAS,GAAG,aAAa,EAC/D,OAAO,EAAE,MAAM;CAKhB;AAOD;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,QAAQ,GAAG,IAAI,CAmBnE;AAED;;;;GAIG;AACH,wBAAsB,sBAAsB,CAC3C,eAAe,EAAE,UAAU,EAC3B,MAAM,EAAE,mBAAmB,GACzB,OAAO,CAAC,QAAQ,CAAC,CAmDnB"}