@selvajs/server 1.2.0 → 1.3.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.
Files changed (217) hide show
  1. package/dist/access/guards.d.ts +213 -0
  2. package/dist/access/guards.d.ts.map +1 -0
  3. package/dist/access/guards.js +417 -0
  4. package/dist/access/guards.js.map +1 -0
  5. package/dist/access/index.d.ts +2 -0
  6. package/dist/access/index.d.ts.map +1 -1
  7. package/dist/access/index.js +6 -0
  8. package/dist/access/index.js.map +1 -1
  9. package/dist/access/permissions-scope.d.ts +15 -0
  10. package/dist/access/permissions-scope.d.ts.map +1 -0
  11. package/dist/access/permissions-scope.js +23 -0
  12. package/dist/access/permissions-scope.js.map +1 -0
  13. package/dist/api/bodies.d.ts +104 -0
  14. package/dist/api/bodies.d.ts.map +1 -0
  15. package/dist/api/bodies.js +87 -0
  16. package/dist/api/bodies.js.map +1 -0
  17. package/dist/api/deps.d.ts +135 -0
  18. package/dist/api/deps.d.ts.map +1 -0
  19. package/dist/api/deps.js +55 -0
  20. package/dist/api/deps.js.map +1 -0
  21. package/dist/api/errors.d.ts +35 -0
  22. package/dist/api/errors.d.ts.map +1 -0
  23. package/dist/api/errors.js +63 -0
  24. package/dist/api/errors.js.map +1 -0
  25. package/dist/api/index.d.ts +12 -0
  26. package/dist/api/index.d.ts.map +1 -0
  27. package/dist/api/index.js +15 -0
  28. package/dist/api/index.js.map +1 -0
  29. package/dist/api/map-core-error.d.ts +19 -0
  30. package/dist/api/map-core-error.d.ts.map +1 -0
  31. package/dist/api/map-core-error.js +49 -0
  32. package/dist/api/map-core-error.js.map +1 -0
  33. package/dist/api/pagination.d.ts +19 -0
  34. package/dist/api/pagination.d.ts.map +1 -0
  35. package/dist/api/pagination.js +40 -0
  36. package/dist/api/pagination.js.map +1 -0
  37. package/dist/api/request.d.ts +93 -0
  38. package/dist/api/request.d.ts.map +1 -0
  39. package/dist/api/request.js +150 -0
  40. package/dist/api/request.js.map +1 -0
  41. package/dist/api/respond.d.ts +29 -0
  42. package/dist/api/respond.d.ts.map +1 -0
  43. package/dist/api/respond.js +59 -0
  44. package/dist/api/respond.js.map +1 -0
  45. package/dist/api/responses-schema.d.ts +158 -0
  46. package/dist/api/responses-schema.d.ts.map +1 -0
  47. package/dist/api/responses-schema.js +104 -0
  48. package/dist/api/responses-schema.js.map +1 -0
  49. package/dist/api/responses.d.ts +19 -0
  50. package/dist/api/responses.d.ts.map +1 -0
  51. package/dist/api/responses.js +21 -0
  52. package/dist/api/responses.js.map +1 -0
  53. package/dist/api/shaped.d.ts +23 -0
  54. package/dist/api/shaped.d.ts.map +1 -0
  55. package/dist/api/shaped.js +29 -0
  56. package/dist/api/shaped.js.map +1 -0
  57. package/dist/api/types.d.ts +41 -0
  58. package/dist/api/types.d.ts.map +1 -0
  59. package/dist/api/types.js +12 -0
  60. package/dist/api/types.js.map +1 -0
  61. package/dist/compute/errors.d.ts +18 -0
  62. package/dist/compute/errors.d.ts.map +1 -0
  63. package/dist/compute/errors.js +21 -0
  64. package/dist/compute/errors.js.map +1 -0
  65. package/dist/compute/evict-changed-servers.d.ts +22 -0
  66. package/dist/compute/evict-changed-servers.d.ts.map +1 -0
  67. package/dist/compute/evict-changed-servers.js +31 -0
  68. package/dist/compute/evict-changed-servers.js.map +1 -0
  69. package/dist/compute/idempotency-http.d.ts +47 -0
  70. package/dist/compute/idempotency-http.d.ts.map +1 -0
  71. package/dist/compute/idempotency-http.js +51 -0
  72. package/dist/compute/idempotency-http.js.map +1 -0
  73. package/dist/compute/index.d.ts +5 -0
  74. package/dist/compute/index.d.ts.map +1 -1
  75. package/dist/compute/index.js +5 -0
  76. package/dist/compute/index.js.map +1 -1
  77. package/dist/compute/resolve-server.d.ts +25 -0
  78. package/dist/compute/resolve-server.d.ts.map +1 -0
  79. package/dist/compute/resolve-server.js +35 -0
  80. package/dist/compute/resolve-server.js.map +1 -0
  81. package/dist/compute/server-config-write.d.ts +52 -0
  82. package/dist/compute/server-config-write.d.ts.map +1 -0
  83. package/dist/compute/server-config-write.js +100 -0
  84. package/dist/compute/server-config-write.js.map +1 -0
  85. package/dist/definitions/index.d.ts +1 -0
  86. package/dist/definitions/index.d.ts.map +1 -1
  87. package/dist/definitions/index.js +1 -0
  88. package/dist/definitions/index.js.map +1 -1
  89. package/dist/definitions/visibility.d.ts +74 -0
  90. package/dist/definitions/visibility.d.ts.map +1 -0
  91. package/dist/definitions/visibility.js +117 -0
  92. package/dist/definitions/visibility.js.map +1 -0
  93. package/dist/handlers/definitionVersions.d.ts +30 -0
  94. package/dist/handlers/definitionVersions.d.ts.map +1 -0
  95. package/dist/handlers/definitionVersions.js +93 -0
  96. package/dist/handlers/definitionVersions.js.map +1 -0
  97. package/dist/handlers/definitions.d.ts +35 -0
  98. package/dist/handlers/definitions.d.ts.map +1 -0
  99. package/dist/handlers/definitions.js +207 -0
  100. package/dist/handlers/definitions.js.map +1 -0
  101. package/dist/handlers/index.d.ts +27 -0
  102. package/dist/handlers/index.d.ts.map +1 -0
  103. package/dist/handlers/index.js +29 -0
  104. package/dist/handlers/index.js.map +1 -0
  105. package/dist/handlers/invite-lookup.d.ts +11 -0
  106. package/dist/handlers/invite-lookup.d.ts.map +1 -0
  107. package/dist/handlers/invite-lookup.js +20 -0
  108. package/dist/handlers/invite-lookup.js.map +1 -0
  109. package/dist/handlers/invites.d.ts +31 -0
  110. package/dist/handlers/invites.d.ts.map +1 -0
  111. package/dist/handlers/invites.js +148 -0
  112. package/dist/handlers/invites.js.map +1 -0
  113. package/dist/handlers/me.d.ts +8 -0
  114. package/dist/handlers/me.d.ts.map +1 -0
  115. package/dist/handlers/me.js +21 -0
  116. package/dist/handlers/me.js.map +1 -0
  117. package/dist/handlers/me.starred.d.ts +11 -0
  118. package/dist/handlers/me.starred.d.ts.map +1 -0
  119. package/dist/handlers/me.starred.js +21 -0
  120. package/dist/handlers/me.starred.js.map +1 -0
  121. package/dist/handlers/orgAssets.d.ts +13 -0
  122. package/dist/handlers/orgAssets.d.ts.map +1 -0
  123. package/dist/handlers/orgAssets.js +54 -0
  124. package/dist/handlers/orgAssets.js.map +1 -0
  125. package/dist/handlers/orgCompute.d.ts +16 -0
  126. package/dist/handlers/orgCompute.d.ts.map +1 -0
  127. package/dist/handlers/orgCompute.js +96 -0
  128. package/dist/handlers/orgCompute.js.map +1 -0
  129. package/dist/handlers/orgMembers.d.ts +29 -0
  130. package/dist/handlers/orgMembers.d.ts.map +1 -0
  131. package/dist/handlers/orgMembers.js +200 -0
  132. package/dist/handlers/orgMembers.js.map +1 -0
  133. package/dist/handlers/orgs.d.ts +16 -0
  134. package/dist/handlers/orgs.d.ts.map +1 -0
  135. package/dist/handlers/orgs.js +26 -0
  136. package/dist/handlers/orgs.js.map +1 -0
  137. package/dist/handlers/projectMembers.d.ts +15 -0
  138. package/dist/handlers/projectMembers.d.ts.map +1 -0
  139. package/dist/handlers/projectMembers.js +95 -0
  140. package/dist/handlers/projectMembers.js.map +1 -0
  141. package/dist/handlers/projects.d.ts +21 -0
  142. package/dist/handlers/projects.d.ts.map +1 -0
  143. package/dist/handlers/projects.js +164 -0
  144. package/dist/handlers/projects.js.map +1 -0
  145. package/dist/handlers/reclaim.d.ts +10 -0
  146. package/dist/handlers/reclaim.d.ts.map +1 -0
  147. package/dist/handlers/reclaim.js +38 -0
  148. package/dist/handlers/reclaim.js.map +1 -0
  149. package/dist/handlers/services.d.ts +22 -0
  150. package/dist/handlers/services.d.ts.map +1 -0
  151. package/dist/handlers/services.js +37 -0
  152. package/dist/handlers/services.js.map +1 -0
  153. package/dist/handlers/shareLinks.d.ts +23 -0
  154. package/dist/handlers/shareLinks.d.ts.map +1 -0
  155. package/dist/handlers/shareLinks.js +85 -0
  156. package/dist/handlers/shareLinks.js.map +1 -0
  157. package/dist/http/index.d.ts +1 -0
  158. package/dist/http/index.d.ts.map +1 -1
  159. package/dist/http/index.js +1 -0
  160. package/dist/http/index.js.map +1 -1
  161. package/dist/http/login-rate-limit.d.ts +72 -0
  162. package/dist/http/login-rate-limit.d.ts.map +1 -0
  163. package/dist/http/login-rate-limit.js +84 -0
  164. package/dist/http/login-rate-limit.js.map +1 -0
  165. package/dist/notifications/deliver-invite.d.ts +27 -0
  166. package/dist/notifications/deliver-invite.d.ts.map +1 -0
  167. package/dist/notifications/deliver-invite.js +32 -0
  168. package/dist/notifications/deliver-invite.js.map +1 -0
  169. package/dist/notifications/index.d.ts +1 -0
  170. package/dist/notifications/index.d.ts.map +1 -1
  171. package/dist/notifications/index.js +1 -0
  172. package/dist/notifications/index.js.map +1 -1
  173. package/dist/organizations/index.d.ts +3 -0
  174. package/dist/organizations/index.d.ts.map +1 -0
  175. package/dist/organizations/index.js +5 -0
  176. package/dist/organizations/index.js.map +1 -0
  177. package/dist/organizations/list-all-members.d.ts +10 -0
  178. package/dist/organizations/list-all-members.d.ts.map +1 -0
  179. package/dist/organizations/list-all-members.js +36 -0
  180. package/dist/organizations/list-all-members.js.map +1 -0
  181. package/dist/organizations/org-asset-service.d.ts +39 -0
  182. package/dist/organizations/org-asset-service.d.ts.map +1 -0
  183. package/dist/organizations/org-asset-service.js +71 -0
  184. package/dist/organizations/org-asset-service.js.map +1 -0
  185. package/dist/projects/create-project.d.ts +30 -0
  186. package/dist/projects/create-project.d.ts.map +1 -0
  187. package/dist/projects/create-project.js +56 -0
  188. package/dist/projects/create-project.js.map +1 -0
  189. package/dist/projects/index.d.ts +2 -0
  190. package/dist/projects/index.d.ts.map +1 -0
  191. package/dist/projects/index.js +3 -0
  192. package/dist/projects/index.js.map +1 -0
  193. package/dist/providers/auth-lookup.d.ts +14 -0
  194. package/dist/providers/auth-lookup.d.ts.map +1 -0
  195. package/dist/providers/auth-lookup.js +34 -0
  196. package/dist/providers/auth-lookup.js.map +1 -0
  197. package/dist/providers/index.d.ts +1 -0
  198. package/dist/providers/index.d.ts.map +1 -1
  199. package/dist/providers/index.js +1 -0
  200. package/dist/providers/index.js.map +1 -1
  201. package/dist/testing/harness.d.ts +168 -0
  202. package/dist/testing/harness.d.ts.map +1 -0
  203. package/dist/testing/harness.js +314 -0
  204. package/dist/testing/harness.js.map +1 -0
  205. package/dist/testing/index.d.ts +18 -0
  206. package/dist/testing/index.d.ts.map +1 -0
  207. package/dist/testing/index.js +15 -0
  208. package/dist/testing/index.js.map +1 -0
  209. package/dist/testing/scenarios.d.ts +67 -0
  210. package/dist/testing/scenarios.d.ts.map +1 -0
  211. package/dist/testing/scenarios.js +104 -0
  212. package/dist/testing/scenarios.js.map +1 -0
  213. package/dist/testing/seed-adapter.d.ts +31 -0
  214. package/dist/testing/seed-adapter.d.ts.map +1 -0
  215. package/dist/testing/seed-adapter.js +19 -0
  216. package/dist/testing/seed-adapter.js.map +1 -0
  217. package/package.json +30 -2
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Version handlers: list, upload, read, delete, and a version's cached schema.
3
+ *
4
+ * Reads resolve through `getVisibleDefinition` / `loadVisibleVersion`, which
5
+ * return `null` rather than throwing, so an invisible definition answers 404.
6
+ * A 403 anywhere here would confirm a guid exists across a tenant boundary.
7
+ */
8
+ import { apiError, ApiErrorCode, collection, created, formText, noContent, parseListOptions, parseParam, requireCaller, requireUpload } from '../api/index.js';
9
+ import { GuidSchema } from '@selvajs/platform/definitions';
10
+ import { requireEditableDefinition } from '../access/index.js';
11
+ import { GH_EXTENSIONS } from '@selvajs/platform';
12
+ import { resolveServerForOrg } from '../compute/index.js';
13
+ import { fetchSchemaFromCompute, getVisibleDefinition, loadVisibleVersion } from '../definitions/index.js';
14
+ import { definitionService } from './services.js';
15
+ export const listVersions = async (req) => {
16
+ const guid = parseParam(req.params.guid, GuidSchema, 'GUID');
17
+ const { ctx } = requireCaller(req);
18
+ // Resolve through `getVisibleDefinition` like the sibling routes, which
19
+ // answers 404 for a guid the caller cannot see. A 403 here would confirm
20
+ // the definition exists and turn this into a cross-tenant existence oracle.
21
+ const def = await getVisibleDefinition(ctx, guid, req.deps);
22
+ if (!def)
23
+ apiError(404, ApiErrorCode.NOT_FOUND, 'Definition not found');
24
+ return collection(await req.deps.definitionMeta.listVersions(ctx, guid, parseListOptions(req.url)));
25
+ };
26
+ /** Upload a new version. Advances `draft`; `live` is unchanged until publish. */
27
+ export const uploadVersion = async (req) => {
28
+ const guid = parseParam(req.params.guid, GuidSchema, 'GUID');
29
+ const form = await req.request.formData();
30
+ const { file, extension } = requireUpload(form, 'file', {
31
+ maxBytes: req.deps.uploadLimits.maxDefinitionFileSize,
32
+ extensions: GH_EXTENSIONS,
33
+ label: 'Grasshopper (.gh or .ghx) file'
34
+ });
35
+ const changeNote = formText(form, 'changeNote', { maxLength: 1000 });
36
+ const { ctx, record, project } = await requireEditableDefinition(req, guid);
37
+ const data = new Uint8Array(await file.arrayBuffer());
38
+ // Validate-and-cache gate: extract the schema from compute BEFORE any
39
+ // write, so a failure rejects the upload with nothing persisted.
40
+ // `project` comes from the guard — no re-fetch.
41
+ const server = await resolveServerForOrg(ctx, project?.orgId ?? null, req.deps.computeServer, {
42
+ definitionPin: record.computeServerId ?? null
43
+ });
44
+ const schema = await fetchSchemaFromCompute(data, server);
45
+ const version = await definitionService(req.deps).uploadVersion(ctx, guid, data, extension.slice(1), file.name, schema, changeNote);
46
+ return created({ version });
47
+ };
48
+ /**
49
+ * Version metadata. `schema` is excluded and served by the `/schema`
50
+ * sub-resource, so a version read never carries a several-hundred-KB blob.
51
+ */
52
+ export const getVersion = async (req) => {
53
+ const guid = parseParam(req.params.guid, GuidSchema, 'GUID');
54
+ const versionId = parseParam(req.params.versionId, GuidSchema, 'version ID');
55
+ const { ctx } = requireCaller(req);
56
+ const version = await loadVisibleVersion(ctx, guid, versionId, req.deps);
57
+ if (!version)
58
+ apiError(404, ApiErrorCode.NOT_FOUND, 'Version not found');
59
+ const { schema: _schema, ...rest } = version;
60
+ return { body: rest };
61
+ };
62
+ /**
63
+ * Delete an old version. The store throws 409 if the version is currently
64
+ * referenced by `liveVersionId` or `draftVersionId` — repoint first.
65
+ */
66
+ export const deleteVersion = async (req) => {
67
+ const guid = parseParam(req.params.guid, GuidSchema, 'GUID');
68
+ const versionId = parseParam(req.params.versionId, GuidSchema, 'version ID');
69
+ const { ctx } = await requireEditableDefinition(req, guid);
70
+ await definitionService(req.deps).deleteVersion(ctx, guid, versionId);
71
+ return noContent();
72
+ };
73
+ /**
74
+ * The UI schema cached on this version at upload. Reads what is stored — no
75
+ * Rhino.Compute round-trip, unlike the pre-upload `POST /api/v1/compute/schema`.
76
+ *
77
+ * Schemas belong to a version, so this is the canonical location;
78
+ * `/definitions/{guid}/schema` is an alias for the live one.
79
+ */
80
+ export const getVersionSchema = async (req) => {
81
+ const guid = parseParam(req.params.guid, GuidSchema, 'GUID');
82
+ const versionId = parseParam(req.params.versionId, GuidSchema, 'version ID');
83
+ const { ctx } = requireCaller(req);
84
+ const version = await loadVisibleVersion(ctx, guid, versionId, req.deps);
85
+ if (!version)
86
+ apiError(404, ApiErrorCode.NOT_FOUND, 'Version not found');
87
+ // A pre-caching version can still lack a schema (lazy backfill bridge) —
88
+ // that is a missing sub-resource, not an error.
89
+ if (!version.schema)
90
+ apiError(404, ApiErrorCode.NOT_FOUND, 'No schema cached for this version');
91
+ return { body: version.schema };
92
+ };
93
+ //# sourceMappingURL=definitionVersions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"definitionVersions.js","sourceRoot":"","sources":["../../src/handlers/definitionVersions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Definition handlers: the collection, one definition's detail and metadata,
3
+ * its live schema, cover image, and the publish channel.
4
+ *
5
+ * Solve and the two compute routes stay unwrapped deliberately — they stream
6
+ * and mark their own metrics, which the `ApiResponse` envelope does not model.
7
+ */
8
+ import type { ApiHandler } from '../api/index.js';
9
+ /**
10
+ * Definitions the caller can view. Visibility is resolved into the query via
11
+ * `projectIds`, so `limit`/`nextCursor` describe the filtered set.
12
+ */
13
+ export declare const listDefinitions: ApiHandler;
14
+ /** Create a definition — metadata and the Grasshopper file in one request. */
15
+ export declare const createDefinition: ApiHandler;
16
+ /** The record plus its live and draft version summaries. */
17
+ export declare const getDefinition: ApiHandler;
18
+ /** Soft-delete the definition; versions and blobs are wiped with it. */
19
+ export declare const deleteDefinition: ApiHandler;
20
+ /** Metadata only. New versions POST to `/versions`. */
21
+ export declare const updateDefinition: ApiHandler;
22
+ /**
23
+ * Convenience alias for the live version's schema — the call a client makes
24
+ * before solving. The canonical location is `/versions/{versionId}/schema`;
25
+ * this resolves the `live` pointer for you.
26
+ */
27
+ export declare const getDefinitionSchema: ApiHandler;
28
+ /**
29
+ * Advance the live channel. Body `{ versionId? }` targets a specific version
30
+ * (rollback or forward-roll); omit it to promote the current draft.
31
+ */
32
+ export declare const publishDefinition: ApiHandler;
33
+ /** Upload a cover image. */
34
+ export declare const uploadDefinitionImage: ApiHandler;
35
+ //# sourceMappingURL=definitions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"definitions.d.ts","sourceRoot":"","sources":["../../src/handlers/definitions.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAiBH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAuBlD;;;GAGG;AACH,eAAO,MAAM,eAAe,EAAE,UAsB7B,CAAC;AAWF,8EAA8E;AAC9E,eAAO,MAAM,gBAAgB,EAAE,UA0F9B,CAAC;AAaF,4DAA4D;AAC5D,eAAO,MAAM,aAAa,EAAE,UAoB3B,CAAC;AAEF,wEAAwE;AACxE,eAAO,MAAM,gBAAgB,EAAE,UAM9B,CAAC;AAEF,uDAAuD;AACvD,eAAO,MAAM,gBAAgB,EAAE,UAO9B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,EAAE,UAejC,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,UAM/B,CAAC;AAEF,4BAA4B;AAC5B,eAAO,MAAM,qBAAqB,EAAE,UAanC,CAAC"}
@@ -0,0 +1,207 @@
1
+ /**
2
+ * Definition handlers: the collection, one definition's detail and metadata,
3
+ * its live schema, cover image, and the publish channel.
4
+ *
5
+ * Solve and the two compute routes stay unwrapped deliberately — they stream
6
+ * and mark their own metrics, which the `ApiResponse` envelope does not model.
7
+ */
8
+ import { randomUUID } from 'node:crypto';
9
+ import { apiError, ApiErrorCode, collection, created, formText, noContent, parseBody, parseDefinitionListOptions, parseParam, requireCaller, requireUpload, throwZodError } from '../api/index.js';
10
+ import { toDefinitionListItem } from '@selvajs/platform';
11
+ import { CreateDefinitionInputSchema, GuidSchema, PublishVersionInputSchema, UpdateMetadataInputSchema } from '@selvajs/platform/definitions';
12
+ import { requireCanCreateDefinition, requireEditableDefinition } from '../access/index.js';
13
+ import { GH_EXTENSIONS } from '@selvajs/platform';
14
+ import { resolveServerForOrg } from '../compute/index.js';
15
+ import { fetchSchemaFromCompute, getVisibleDefinition, listVisibleDefinitions, loadVisibleVersion, resolveAccessibleProjects } from '../definitions/index.js';
16
+ import { definitionService } from './services.js';
17
+ const LISTABLE_STATUSES = ['draft', 'published', 'archived'];
18
+ /**
19
+ * Definitions the caller can view. Visibility is resolved into the query via
20
+ * `projectIds`, so `limit`/`nextCursor` describe the filtered set.
21
+ */
22
+ export const listDefinitions = async (req) => {
23
+ const { ctx } = requireCaller(req);
24
+ const statusParam = req.url.searchParams.get('status');
25
+ if (statusParam && !LISTABLE_STATUSES.includes(statusParam)) {
26
+ apiError(400, ApiErrorCode.VALIDATION_FAILED, `status must be one of: ${LISTABLE_STATUSES.join(', ')}`);
27
+ }
28
+ const page = await listVisibleDefinitions(ctx, {
29
+ ...parseDefinitionListOptions(req.url),
30
+ projectId: req.url.searchParams.get('projectId') ?? undefined,
31
+ statuses: statusParam ? [statusParam] : undefined
32
+ }, req.deps);
33
+ return collection({ items: page.items.map(toDefinitionListItem), nextCursor: page.nextCursor });
34
+ };
35
+ function parseTags(raw) {
36
+ if (!raw)
37
+ return undefined;
38
+ const tags = raw
39
+ .split(',')
40
+ .map((t) => t.trim())
41
+ .filter(Boolean);
42
+ return tags.length ? tags : undefined;
43
+ }
44
+ /** Create a definition — metadata and the Grasshopper file in one request. */
45
+ export const createDefinition = async (req) => {
46
+ const { ctx, user } = requireCaller(req);
47
+ const form = await req.request.formData();
48
+ const { file, extension } = requireUpload(form, 'file', {
49
+ maxBytes: req.deps.uploadLimits.maxDefinitionFileSize,
50
+ extensions: GH_EXTENSIONS,
51
+ label: 'Grasshopper (.gh or .ghx) file'
52
+ });
53
+ const imageFile = form.get('image');
54
+ const maxImageBytes = req.deps.uploadLimits.maxImageFileSize;
55
+ if (imageFile instanceof File && imageFile.size > maxImageBytes) {
56
+ apiError(400, ApiErrorCode.VALIDATION_FAILED, `Image too large. Max size: ${maxImageBytes / (1024 * 1024)} MB`);
57
+ }
58
+ let projectId = formText(form, 'projectId');
59
+ if (!projectId) {
60
+ // The fallback picks a project on the caller's behalf, so it must pick
61
+ // from what the caller can already see. `listProjects` ignores its ctx on
62
+ // the local provider, which would let the pick land on a `private`
63
+ // project the caller is not a member of — and on an `autoJoinOnUpload`
64
+ // project `requireCanCreateDefinition` then allows the write, so the
65
+ // upload succeeds into a project the caller never named.
66
+ if (!ctx.actingOrgId)
67
+ apiError(400, ApiErrorCode.VALIDATION_FAILED, 'No active organization');
68
+ const { projects } = await resolveAccessibleProjects(ctx, req.deps);
69
+ const fallback = projects.find((p) => p.orgId === ctx.actingOrgId);
70
+ if (!fallback) {
71
+ apiError(400, ApiErrorCode.VALIDATION_FAILED, 'No accessible project — pass projectId.');
72
+ }
73
+ projectId = fallback.id;
74
+ }
75
+ const { project } = await requireCanCreateDefinition(req, projectId);
76
+ // Not `parseBody` — the fields arrive as multipart, not JSON, so they are
77
+ // assembled here and validated by the same schema.
78
+ const parsed = CreateDefinitionInputSchema.safeParse({
79
+ displayName: formText(form, 'displayName'),
80
+ description: formText(form, 'description'),
81
+ category: formText(form, 'category'),
82
+ coverImage: formText(form, 'coverImage'),
83
+ tags: parseTags(formText(form, 'tags')),
84
+ projectId,
85
+ computeServerId: formText(form, 'computeServerId')
86
+ });
87
+ if (!parsed.success)
88
+ throwZodError(parsed.error);
89
+ const guid = randomUUID();
90
+ const fileData = new Uint8Array(await file.arrayBuffer());
91
+ // Validate-and-cache gate: extract the schema from compute BEFORE any
92
+ // write, so compute being down or the file having no Schema output rejects
93
+ // the upload with nothing persisted.
94
+ const server = await resolveServerForOrg(ctx, project.orgId, req.deps.computeServer, {
95
+ definitionPin: parsed.data.computeServerId ?? null
96
+ });
97
+ const schema = await fetchSchemaFromCompute(fileData, server);
98
+ const service = definitionService(req.deps);
99
+ const { record, version } = await service.create(ctx, {
100
+ guid,
101
+ projectId: parsed.data.projectId,
102
+ ownerId: user.id,
103
+ fileExt: extension.slice(1),
104
+ originalFilename: file.name,
105
+ computeServerId: parsed.data.computeServerId,
106
+ displayName: parsed.data.displayName.trim(),
107
+ description: parsed.data.description,
108
+ category: parsed.data.category,
109
+ tags: parsed.data.tags,
110
+ coverImage: parsed.data.coverImage
111
+ }, fileData, schema);
112
+ let coverImage = record.coverImage;
113
+ if (imageFile instanceof File && imageFile.size > 0) {
114
+ const imageData = new Uint8Array(await imageFile.arrayBuffer());
115
+ coverImage = await service.saveCoverImage(ctx, guid, imageData);
116
+ }
117
+ return created({ guid, version, coverImage });
118
+ };
119
+ /** `schema` is a large blob, served on demand by `/versions/{versionId}/schema`. */
120
+ function versionSummary(v) {
121
+ return {
122
+ id: v.id,
123
+ versionNumber: v.versionNumber,
124
+ uploadedAt: v.uploadedAt,
125
+ uploadedBy: v.uploadedBy,
126
+ changeNote: v.changeNote
127
+ };
128
+ }
129
+ /** The record plus its live and draft version summaries. */
130
+ export const getDefinition = async (req) => {
131
+ const guid = parseParam(req.params.guid, GuidSchema, 'GUID');
132
+ const { ctx } = requireCaller(req);
133
+ const record = await getVisibleDefinition(ctx, guid, req.deps);
134
+ if (!record)
135
+ apiError(404, ApiErrorCode.NOT_FOUND, 'Definition not found');
136
+ const meta = req.deps.definitionMeta;
137
+ const [liveVersion, draftVersion] = await Promise.all([
138
+ record.liveVersionId ? meta.getVersion(ctx, record.liveVersionId) : null,
139
+ record.draftVersionId ? meta.getVersion(ctx, record.draftVersionId) : null
140
+ ]);
141
+ return {
142
+ body: {
143
+ ...record,
144
+ liveVersion: liveVersion ? versionSummary(liveVersion) : null,
145
+ draftVersion: draftVersion ? versionSummary(draftVersion) : null
146
+ }
147
+ };
148
+ };
149
+ /** Soft-delete the definition; versions and blobs are wiped with it. */
150
+ export const deleteDefinition = async (req) => {
151
+ const guid = parseParam(req.params.guid, GuidSchema, 'GUID');
152
+ const { ctx } = await requireEditableDefinition(req, guid);
153
+ await definitionService(req.deps).delete(ctx, guid);
154
+ return noContent();
155
+ };
156
+ /** Metadata only. New versions POST to `/versions`. */
157
+ export const updateDefinition = async (req) => {
158
+ const guid = parseParam(req.params.guid, GuidSchema, 'GUID');
159
+ const { ctx } = await requireEditableDefinition(req, guid);
160
+ const patch = await parseBody(req.request, UpdateMetadataInputSchema);
161
+ await definitionService(req.deps).updateMeta(ctx, guid, patch);
162
+ return noContent();
163
+ };
164
+ /**
165
+ * Convenience alias for the live version's schema — the call a client makes
166
+ * before solving. The canonical location is `/versions/{versionId}/schema`;
167
+ * this resolves the `live` pointer for you.
168
+ */
169
+ export const getDefinitionSchema = async (req) => {
170
+ const guid = parseParam(req.params.guid, GuidSchema, 'GUID');
171
+ const { ctx } = requireCaller(req);
172
+ const record = await getVisibleDefinition(ctx, guid, req.deps);
173
+ if (!record)
174
+ apiError(404, ApiErrorCode.NOT_FOUND, 'Definition not found');
175
+ if (!record.liveVersionId) {
176
+ apiError(404, ApiErrorCode.NOT_FOUND, 'This definition has no published version');
177
+ }
178
+ const version = await loadVisibleVersion(ctx, guid, record.liveVersionId, req.deps);
179
+ if (!version?.schema) {
180
+ apiError(404, ApiErrorCode.NOT_FOUND, 'No schema cached for the live version');
181
+ }
182
+ return { body: version.schema };
183
+ };
184
+ /**
185
+ * Advance the live channel. Body `{ versionId? }` targets a specific version
186
+ * (rollback or forward-roll); omit it to promote the current draft.
187
+ */
188
+ export const publishDefinition = async (req) => {
189
+ const guid = parseParam(req.params.guid, GuidSchema, 'GUID');
190
+ const { versionId } = await parseBody(req.request, PublishVersionInputSchema, { missingAs: {} });
191
+ const { ctx } = await requireEditableDefinition(req, guid);
192
+ return { body: { version: await definitionService(req.deps).publish(ctx, guid, versionId) } };
193
+ };
194
+ /** Upload a cover image. */
195
+ export const uploadDefinitionImage = async (req) => {
196
+ const guid = parseParam(req.params.guid, GuidSchema, 'GUID');
197
+ const { ctx } = await requireEditableDefinition(req, guid);
198
+ const { file } = requireUpload(await req.request.formData(), 'image', {
199
+ maxBytes: req.deps.uploadLimits.maxImageFileSize,
200
+ label: 'Image'
201
+ });
202
+ const data = new Uint8Array(await file.arrayBuffer());
203
+ return {
204
+ body: { coverImage: await definitionService(req.deps).saveCoverImage(ctx, guid, data) }
205
+ };
206
+ };
207
+ //# sourceMappingURL=definitions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"definitions.js","sourceRoot":"","sources":["../../src/handlers/definitions.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * The API handlers themselves — the business logic behind each endpoint.
3
+ *
4
+ * A handler is `(req: ApiRequest) => Promise<ApiResponse | Response>` and names
5
+ * no web framework: it reads params and body off `req`, reaches stores through
6
+ * `req.deps`, and fails by throwing `ApiError`. A host binds one to a route by
7
+ * building an `ApiRequest` and calling `runHandler` — see `api/README.md`.
8
+ *
9
+ * Handlers live here rather than in a host app so a second host implements the
10
+ * same API by mounting these, not by reimplementing them and re-deriving the
11
+ * gates, invariants, and status codes each one enforces.
12
+ */
13
+ export { definitionService, orgAssetService, tokenCodec } from './services.js';
14
+ export { getMe } from './me.js';
15
+ export { starDefinition, unstarDefinition } from './me.starred.js';
16
+ export { getOrg, listOrgMembers } from './orgs.js';
17
+ export { updateOrgMember, removeOrgMember } from './orgMembers.js';
18
+ export { reclaimProject } from './reclaim.js';
19
+ export { uploadOrgAsset, removeOrgAsset } from './orgAssets.js';
20
+ export { listShareLinks, createShareLink, revokeShareLink } from './shareLinks.js';
21
+ export { listDefinitions, createDefinition, getDefinition, deleteDefinition, updateDefinition, getDefinitionSchema, publishDefinition, uploadDefinitionImage } from './definitions.js';
22
+ export { listVersions, uploadVersion, getVersion, deleteVersion, getVersionSchema } from './definitionVersions.js';
23
+ export { listProjects, createProject, getProject, updateProject, deleteProject } from './projects.js';
24
+ export { listProjectMembers, addProjectMember, updateProjectMemberRole, removeProjectMember } from './projectMembers.js';
25
+ export { getOrgCompute, updateOrgCompute } from './orgCompute.js';
26
+ export { listInvites, createInvite, revokeInvite, resendInvite } from './invites.js';
27
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/handlers/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE/E,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACnF,OAAO,EACN,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,iBAAiB,EACjB,qBAAqB,EACrB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACN,YAAY,EACZ,aAAa,EACb,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACN,YAAY,EACZ,aAAa,EACb,UAAU,EACV,aAAa,EACb,aAAa,EACb,MAAM,eAAe,CAAC;AACvB,OAAO,EACN,kBAAkB,EAClB,gBAAgB,EAChB,uBAAuB,EACvB,mBAAmB,EACnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,29 @@
1
+ /**
2
+ * The API handlers themselves — the business logic behind each endpoint.
3
+ *
4
+ * A handler is `(req: ApiRequest) => Promise<ApiResponse | Response>` and names
5
+ * no web framework: it reads params and body off `req`, reaches stores through
6
+ * `req.deps`, and fails by throwing `ApiError`. A host binds one to a route by
7
+ * building an `ApiRequest` and calling `runHandler` — see `api/README.md`.
8
+ *
9
+ * Handlers live here rather than in a host app so a second host implements the
10
+ * same API by mounting these, not by reimplementing them and re-deriving the
11
+ * gates, invariants, and status codes each one enforces.
12
+ */
13
+ // Accessors for the host-composed services on `SelvaDeps`. Exported because a
14
+ // host's own handlers reach the same services through the same named failure.
15
+ export { definitionService, orgAssetService, tokenCodec } from './services.js';
16
+ export { getMe } from './me.js';
17
+ export { starDefinition, unstarDefinition } from './me.starred.js';
18
+ export { getOrg, listOrgMembers } from './orgs.js';
19
+ export { updateOrgMember, removeOrgMember } from './orgMembers.js';
20
+ export { reclaimProject } from './reclaim.js';
21
+ export { uploadOrgAsset, removeOrgAsset } from './orgAssets.js';
22
+ export { listShareLinks, createShareLink, revokeShareLink } from './shareLinks.js';
23
+ export { listDefinitions, createDefinition, getDefinition, deleteDefinition, updateDefinition, getDefinitionSchema, publishDefinition, uploadDefinitionImage } from './definitions.js';
24
+ export { listVersions, uploadVersion, getVersion, deleteVersion, getVersionSchema } from './definitionVersions.js';
25
+ export { listProjects, createProject, getProject, updateProject, deleteProject } from './projects.js';
26
+ export { listProjectMembers, addProjectMember, updateProjectMemberRole, removeProjectMember } from './projectMembers.js';
27
+ export { getOrgCompute, updateOrgCompute } from './orgCompute.js';
28
+ export { listInvites, createInvite, revokeInvite, resendInvite } from './invites.js';
29
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/handlers/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,8EAA8E;AAC9E,8EAA8E;AAC9E,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE/E,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAChC,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACnE,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AACnF,OAAO,EACN,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EAChB,gBAAgB,EAChB,mBAAmB,EACnB,iBAAiB,EACjB,qBAAqB,EACrB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACN,YAAY,EACZ,aAAa,EACb,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACN,YAAY,EACZ,aAAa,EACb,UAAU,EACV,aAAa,EACb,aAAa,EACb,MAAM,eAAe,CAAC;AACvB,OAAO,EACN,kBAAkB,EAClB,gBAAgB,EAChB,uBAAuB,EACvB,mBAAmB,EACnB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { IDataProvider, Invite, RequestContext } from '@selvajs/platform';
2
+ /**
3
+ * Find an invite by id, confirming it belongs to `orgId`.
4
+ *
5
+ * `manage_org_members` is org-scoped, so a permitted caller must not reach an
6
+ * invite in another org. Neither store scopes `revoke()` by acting org, so
7
+ * every route that mutates an invite by id has to establish ownership first —
8
+ * hence one shared paged scan rather than a copy per route.
9
+ */
10
+ export declare function findPendingInviteInOrg(ctx: RequestContext, orgId: string, id: string, store: IDataProvider['invites']): Promise<Invite | null>;
11
+ //# sourceMappingURL=invite-lookup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invite-lookup.d.ts","sourceRoot":"","sources":["../../src/handlers/invite-lookup.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AAE/E;;;;;;;GAOG;AACH,wBAAsB,sBAAsB,CAC3C,GAAG,EAAE,cAAc,EACnB,KAAK,EAAE,MAAM,EACb,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,aAAa,CAAC,SAAS,CAAC,GAC7B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CASxB"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Find an invite by id, confirming it belongs to `orgId`.
3
+ *
4
+ * `manage_org_members` is org-scoped, so a permitted caller must not reach an
5
+ * invite in another org. Neither store scopes `revoke()` by acting org, so
6
+ * every route that mutates an invite by id has to establish ownership first —
7
+ * hence one shared paged scan rather than a copy per route.
8
+ */
9
+ export async function findPendingInviteInOrg(ctx, orgId, id, store) {
10
+ let cursor;
11
+ do {
12
+ const page = await store.listByOrg(ctx, orgId, { limit: 200, cursor });
13
+ const match = page.items.find((i) => i.id === id);
14
+ if (match)
15
+ return match;
16
+ cursor = page.nextCursor ?? undefined;
17
+ } while (cursor);
18
+ return null;
19
+ }
20
+ //# sourceMappingURL=invite-lookup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invite-lookup.js","sourceRoot":"","sources":["../../src/handlers/invite-lookup.ts"],"names":[],"mappings":"AAEA;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC3C,GAAmB,EACnB,KAAa,EACb,EAAU,EACV,KAA+B;IAE/B,IAAI,MAA0B,CAAC;IAC/B,GAAG,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,CAAC,CAAC;QACvE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;QAClD,IAAI,KAAK;YAAE,OAAO,KAAK,CAAC;QACxB,MAAM,GAAG,IAAI,CAAC,UAAU,IAAI,SAAS,CAAC;IACvC,CAAC,QAAQ,MAAM,EAAE;IACjB,OAAO,IAAI,CAAC;AACb,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Org invites: list, mint, revoke, resend.
3
+ *
4
+ * **The raw token exists only in the response.** The store sees an HMAC digest,
5
+ * so a leak of the `invites` table cannot be replayed without the instance
6
+ * secret — and `tokenHash` is dropped by the response schema, which is why
7
+ * every response here goes through `shaped`/`shapedCollection` rather than
8
+ * `{ body }`.
9
+ */
10
+ import type { ApiHandler } from '../api/index.js';
11
+ /** Pending and recently accepted invites for the acting org. */
12
+ export declare const listInvites: ApiHandler;
13
+ /** Create an invite and return the accept URL. */
14
+ export declare const createInvite: ApiHandler;
15
+ /** Revoke a pending invite. Consumed invites are preserved for audit. */
16
+ export declare const revokeInvite: ApiHandler;
17
+ /**
18
+ * Re-send an invite: mint a replacement and revoke the original.
19
+ *
20
+ * A resend cannot reuse the original link. The raw token is never stored — only
21
+ * its HMAC digest is — so there is nothing to re-read, and rather than weaken
22
+ * that, this issues a fresh token and revokes the row it replaces. The old link
23
+ * stops working the moment this returns, which is also what an admin wants
24
+ * after mailing an invite to the wrong address.
25
+ *
26
+ * Grants are copied verbatim from the original. The role and permission gates
27
+ * ran when it was minted; re-deriving them here would let a since-demoted admin
28
+ * silently change what the invite carries.
29
+ */
30
+ export declare const resendInvite: ApiHandler;
31
+ //# sourceMappingURL=invites.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"invites.d.ts","sourceRoot":"","sources":["../../src/handlers/invites.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAiBH,OAAO,KAAK,EAAE,UAAU,EAAc,MAAM,iBAAiB,CAAC;AA+C9D,gEAAgE;AAChE,eAAO,MAAM,WAAW,EAAE,UASzB,CAAC;AAEF,kDAAkD;AAClD,eAAO,MAAM,YAAY,EAAE,UA2D1B,CAAC;AAEF,yEAAyE;AACzE,eAAO,MAAM,YAAY,EAAE,UAU1B,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,YAAY,EAAE,UA+B1B,CAAC"}