@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
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/access/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACN,+BAA+B,EAC/B,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,sBAAsB,EAC3B,MAAM,2BAA2B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/access/index.ts"],"names":[],"mappings":"AAGA,OAAO,EACN,+BAA+B,EAC/B,KAAK,kBAAkB,EACvB,KAAK,yBAAyB,EAC9B,KAAK,sBAAsB,EAC3B,MAAM,2BAA2B,CAAC;AAInC,cAAc,aAAa,CAAC;AAI5B,OAAO,EAAE,oBAAoB,EAAE,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC"}
@@ -1,4 +1,10 @@
1
1
  // Access-rule input assembly — marshals providers + flags into what
2
2
  // platform's pure canView/canEdit/… rules consume.
3
3
  export { createProjectAccessInputBuilder } from './project-access-input.js';
4
+ // Framework-free permission guards. Redirecting guards stay with the host —
5
+ // see the module header in ./guards.ts.
6
+ export * from './guards.js';
7
+ // Wire-format adapter: the v1 invite body accepts one flat `permissions` array,
8
+ // while the stores keep platform and org scope apart.
9
+ export { splitFlatPermissions } from './permissions-scope.js';
4
10
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/access/index.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,mDAAmD;AAEnD,OAAO,EACN,+BAA+B,EAI/B,MAAM,2BAA2B,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/access/index.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,mDAAmD;AAEnD,OAAO,EACN,+BAA+B,EAI/B,MAAM,2BAA2B,CAAC;AAEnC,4EAA4E;AAC5E,wCAAwC;AACxC,cAAc,aAAa,CAAC;AAE5B,gFAAgF;AAChF,sDAAsD;AACtD,OAAO,EAAE,oBAAoB,EAAyB,MAAM,wBAAwB,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Bridges the flat `permissions` array the v1 invite body accepts to the
3
+ * two-scope model adapters expect. One invite legitimately carries both scopes,
4
+ * so this is a wire-format adapter, not a migration shim — retire it only when
5
+ * the invite body grows separate `platformPermissions` + `orgPermissions`
6
+ * fields.
7
+ */
8
+ import type { OrgPermission, PlatformPermission } from '@selvajs/platform';
9
+ export interface SplitPermissions {
10
+ platform: PlatformPermission[];
11
+ org: OrgPermission[];
12
+ }
13
+ /** Split a flat array into platform + org scope buckets, dropping unknowns. */
14
+ export declare function splitFlatPermissions(flat: readonly string[]): SplitPermissions;
15
+ //# sourceMappingURL=permissions-scope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions-scope.d.ts","sourceRoot":"","sources":["../../src/access/permissions-scope.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAM3E,MAAM,WAAW,gBAAgB;IAChC,QAAQ,EAAE,kBAAkB,EAAE,CAAC;IAC/B,GAAG,EAAE,aAAa,EAAE,CAAC;CACrB;AAED,+EAA+E;AAC/E,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,gBAAgB,CAQ9E"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Bridges the flat `permissions` array the v1 invite body accepts to the
3
+ * two-scope model adapters expect. One invite legitimately carries both scopes,
4
+ * so this is a wire-format adapter, not a migration shim — retire it only when
5
+ * the invite body grows separate `platformPermissions` + `orgPermissions`
6
+ * fields.
7
+ */
8
+ import { ALL_ORG_PERMISSIONS, ALL_PLATFORM_PERMISSIONS } from '@selvajs/platform';
9
+ const PLATFORM_SET = new Set(ALL_PLATFORM_PERMISSIONS);
10
+ const ORG_SET = new Set(ALL_ORG_PERMISSIONS);
11
+ /** Split a flat array into platform + org scope buckets, dropping unknowns. */
12
+ export function splitFlatPermissions(flat) {
13
+ const platform = [];
14
+ const org = [];
15
+ for (const p of flat) {
16
+ if (PLATFORM_SET.has(p))
17
+ platform.push(p);
18
+ else if (ORG_SET.has(p))
19
+ org.push(p);
20
+ }
21
+ return { platform, org };
22
+ }
23
+ //# sourceMappingURL=permissions-scope.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"permissions-scope.js","sourceRoot":"","sources":["../../src/access/permissions-scope.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,MAAM,mBAAmB,CAAC;AAElF,MAAM,YAAY,GAAwB,IAAI,GAAG,CAAC,wBAAwB,CAAC,CAAC;AAC5E,MAAM,OAAO,GAAwB,IAAI,GAAG,CAAC,mBAAmB,CAAC,CAAC;AAOlE,+EAA+E;AAC/E,MAAM,UAAU,oBAAoB,CAAC,IAAuB;IAC3D,MAAM,QAAQ,GAAyB,EAAE,CAAC;IAC1C,MAAM,GAAG,GAAoB,EAAE,CAAC;IAChC,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;QACtB,IAAI,YAAY,CAAC,GAAG,CAAC,CAAC,CAAC;YAAE,QAAQ,CAAC,IAAI,CAAC,CAAuB,CAAC,CAAC;aAC3D,IAAI,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;YAAE,GAAG,CAAC,IAAI,CAAC,CAAkB,CAAC,CAAC;IACvD,CAAC;IACD,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;AAC1B,CAAC"}
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Request-body validators for the API routes that take JSON.
3
+ *
4
+ * They live apart from their handlers so a spec generator can import them
5
+ * without loading a host's route module — in Selva's case a `+server.ts` imports
6
+ * `./$types`, which only resolves inside a SvelteKit build.
7
+ *
8
+ * **A JSON body accepted by an API route belongs in this file.** Adding one
9
+ * inline is invisible to the generator, so the endpoint documents an empty body.
10
+ * Multipart handlers are the exception — `FormData` has no Zod schema to derive
11
+ * from, so their fields are described in the spec directly.
12
+ */
13
+ import { z } from 'zod';
14
+ export declare const SolveBodySchema: z.ZodObject<{
15
+ inputs: z.ZodDefault<z.ZodArray<z.ZodUnknown>>;
16
+ values: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
17
+ channel: z.ZodDefault<z.ZodEnum<{
18
+ draft: "draft";
19
+ live: "live";
20
+ }>>;
21
+ versionId: z.ZodOptional<z.ZodString>;
22
+ definitionUrl: z.ZodOptional<z.ZodString>;
23
+ }, z.core.$strip>;
24
+ export declare const CreateProjectBodySchema: z.ZodObject<{
25
+ name: z.ZodString;
26
+ description: z.ZodOptional<z.ZodString>;
27
+ visibility: z.ZodDefault<z.ZodEnum<{
28
+ public: "public";
29
+ org: "org";
30
+ private: "private";
31
+ platform: "platform";
32
+ }>>;
33
+ autoJoinOnUpload: z.ZodOptional<z.ZodBoolean>;
34
+ }, z.core.$strip>;
35
+ export declare const UpdateProjectBodySchema: z.ZodObject<{
36
+ name: z.ZodOptional<z.ZodString>;
37
+ description: z.ZodOptional<z.ZodOptional<z.ZodNullable<z.ZodString>>>;
38
+ visibility: z.ZodOptional<z.ZodEnum<{
39
+ public: "public";
40
+ org: "org";
41
+ private: "private";
42
+ platform: "platform";
43
+ }>>;
44
+ autoJoinOnUpload: z.ZodOptional<z.ZodBoolean>;
45
+ }, z.core.$strip>;
46
+ export declare const AddProjectMemberBodySchema: z.ZodObject<{
47
+ userId: z.ZodString;
48
+ role: z.ZodEnum<{
49
+ owner: "owner";
50
+ editor: "editor";
51
+ viewer: "viewer";
52
+ }>;
53
+ }, z.core.$strip>;
54
+ export declare const UpdateProjectMemberBodySchema: z.ZodObject<{
55
+ role: z.ZodEnum<{
56
+ owner: "owner";
57
+ editor: "editor";
58
+ viewer: "viewer";
59
+ }>;
60
+ }, z.core.$strip>;
61
+ export declare const CreateInviteBodySchema: z.ZodObject<{
62
+ email: z.ZodPipe<z.ZodEmail, z.ZodTransform<string, string>>;
63
+ orgRole: z.ZodDefault<z.ZodEnum<{
64
+ admin: "admin";
65
+ owner: "owner";
66
+ member: "member";
67
+ }>>;
68
+ permissions: z.ZodDefault<z.ZodArray<z.ZodUnion<readonly [z.ZodEnum<{
69
+ instance_admin: "instance_admin";
70
+ manage_compute: "manage_compute";
71
+ manage_instance_users: "manage_instance_users";
72
+ manage_updates: "manage_updates";
73
+ }>, z.ZodEnum<{
74
+ manage_org_members: "manage_org_members";
75
+ manage_org_compute: "manage_org_compute";
76
+ manage_definitions: "manage_definitions";
77
+ manage_projects: "manage_projects";
78
+ }>]>>>;
79
+ }, z.core.$strip>;
80
+ export declare const OrgComputePatchBodySchema: z.ZodObject<{
81
+ servers: z.ZodArray<z.ZodObject<{
82
+ id: z.ZodString;
83
+ label: z.ZodString;
84
+ serverUrl: z.ZodString;
85
+ apiKey: z.ZodOptional<z.ZodNullable<z.ZodString>>;
86
+ timeoutMs: z.ZodOptional<z.ZodNumber>;
87
+ retryCount: z.ZodOptional<z.ZodNumber>;
88
+ }, z.core.$strip>>;
89
+ defaultServerId: z.ZodOptional<z.ZodNullable<z.ZodString>>;
90
+ }, z.core.$strip>;
91
+ export declare const UpdateOrgMemberBodySchema: z.ZodObject<{
92
+ role: z.ZodOptional<z.ZodEnum<{
93
+ admin: "admin";
94
+ owner: "owner";
95
+ member: "member";
96
+ }>>;
97
+ permissions: z.ZodOptional<z.ZodArray<z.ZodEnum<{
98
+ manage_org_members: "manage_org_members";
99
+ manage_org_compute: "manage_org_compute";
100
+ manage_definitions: "manage_definitions";
101
+ manage_projects: "manage_projects";
102
+ }>>>;
103
+ }, z.core.$strip>;
104
+ //# sourceMappingURL=bodies.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bodies.d.ts","sourceRoot":"","sources":["../../src/api/bodies.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAexB,eAAO,MAAM,eAAe;;;;;;;;;iBAO1B,CAAC;AAMH,eAAO,MAAM,uBAAuB;;;;;;;;;;iBAKlC,CAAC;AAEH,eAAO,MAAM,uBAAuB;;;;;;;;;;iBAOzB,CAAC;AAEZ,eAAO,MAAM,0BAA0B;;;;;;;iBAGrC,CAAC;AAEH,eAAO,MAAM,6BAA6B;;;;;;iBAAwC,CAAC;AASnF,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;;;;;iBAIjC,CAAC;AAiBH,eAAO,MAAM,yBAAyB;;;;;;;;;;iBAIpC,CAAC;AAEH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;iBASnC,CAAC"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * Request-body validators for the API routes that take JSON.
3
+ *
4
+ * They live apart from their handlers so a spec generator can import them
5
+ * without loading a host's route module — in Selva's case a `+server.ts` imports
6
+ * `./$types`, which only resolves inside a SvelteKit build.
7
+ *
8
+ * **A JSON body accepted by an API route belongs in this file.** Adding one
9
+ * inline is invisible to the generator, so the endpoint documents an empty body.
10
+ * Multipart handlers are the exception — `FormData` has no Zod schema to derive
11
+ * from, so their fields are described in the spec directly.
12
+ */
13
+ import { z } from 'zod';
14
+ import { ProjectVisibilitySchema, ProjectRoleSchema, OrgRoleSchema, OrgPermissionSchema, PlatformPermissionSchema, ALL_ORG_PERMISSIONS } from '@selvajs/platform';
15
+ // ============================================================================
16
+ // Definitions
17
+ // ============================================================================
18
+ export const SolveBodySchema = z.object({
19
+ inputs: z.array(z.unknown()).default([]),
20
+ values: z.record(z.string(), z.unknown()).default({}),
21
+ channel: z.enum(['live', 'draft']).default('live'),
22
+ versionId: z.string().optional(),
23
+ /** Must name this same definition, or the route 400s instead of solving a different one. */
24
+ definitionUrl: z.string().optional()
25
+ });
26
+ // ============================================================================
27
+ // Projects
28
+ // ============================================================================
29
+ export const CreateProjectBodySchema = z.object({
30
+ name: z.string().min(1, 'Project name is required').max(128).trim(),
31
+ description: z.string().max(2000).optional(),
32
+ visibility: ProjectVisibilitySchema.default('private'),
33
+ autoJoinOnUpload: z.boolean().optional()
34
+ });
35
+ export const UpdateProjectBodySchema = z
36
+ .object({
37
+ name: z.string().min(1).max(128).trim(),
38
+ description: z.string().max(2000).nullish(),
39
+ visibility: ProjectVisibilitySchema,
40
+ autoJoinOnUpload: z.boolean()
41
+ })
42
+ .partial();
43
+ export const AddProjectMemberBodySchema = z.object({
44
+ userId: z.string().min(1, 'userId is required'),
45
+ role: ProjectRoleSchema
46
+ });
47
+ export const UpdateProjectMemberBodySchema = z.object({ role: ProjectRoleSchema });
48
+ // ============================================================================
49
+ // Orgs
50
+ // ============================================================================
51
+ /** Platform-scope entries are dropped downstream — an invite only grants org rights. */
52
+ const FlatPermissionSchema = z.union([PlatformPermissionSchema, OrgPermissionSchema]);
53
+ export const CreateInviteBodySchema = z.object({
54
+ email: z.email('Valid email is required').transform((s) => s.toLowerCase().trim()),
55
+ orgRole: OrgRoleSchema.default('member'),
56
+ permissions: z.array(FlatPermissionSchema).default([])
57
+ });
58
+ /**
59
+ * `apiKey` is tri-state: **omitted** keeps the stored key, **null** clears it, a
60
+ * string replaces it. `.optional().nullable()` — not `.nullish()` — because the
61
+ * two must stay distinguishable after parsing, or a request that just omits the
62
+ * field would silently wipe the stored credential.
63
+ */
64
+ const IncomingComputeServerSchema = z.object({
65
+ id: z.string().min(1),
66
+ label: z.string().min(1),
67
+ serverUrl: z.string().min(1),
68
+ apiKey: z.string().nullable().optional(),
69
+ timeoutMs: z.number().optional(),
70
+ retryCount: z.number().optional()
71
+ });
72
+ export const OrgComputePatchBodySchema = z.object({
73
+ servers: z.array(IncomingComputeServerSchema),
74
+ /** May name any server visible to the org. `null` clears the override; omitted leaves it untouched. */
75
+ defaultServerId: z.string().nullable().optional()
76
+ });
77
+ export const UpdateOrgMemberBodySchema = z
78
+ .object({
79
+ role: OrgRoleSchema.optional(),
80
+ permissions: z
81
+ .array(z.enum(ALL_ORG_PERMISSIONS))
82
+ .optional()
83
+ })
84
+ .refine((b) => b.role !== undefined || b.permissions !== undefined, {
85
+ message: 'Provide at least one of role, permissions'
86
+ });
87
+ //# sourceMappingURL=bodies.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bodies.js","sourceRoot":"","sources":["../../src/api/bodies.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Everything an API handler talks to, as one injected value.
3
+ *
4
+ * Handlers used to reach module-global getters (`getProjectProvider()`,
5
+ * `getDefinitionService()`, …) from the Selva app's composition root — 77 call
6
+ * sites across the v1 routes. That welded them to one app's boot: a second app
7
+ * on a different provider set (parafa, on Supabase) could not call them at all.
8
+ *
9
+ * Most fields are sub-stores of `IDataProvider`, so a host that already built a
10
+ * `SelvaConfig` gets them via `depsFromConfig`. `services` stays host-defined:
11
+ * `DefinitionService` and friends are composed rather than resolved, and a host
12
+ * may supply its own.
13
+ */
14
+ import type { DefinitionService } from '../definitions/definition-service.js';
15
+ import type { OrgAssetService } from '../organizations/org-asset-service.js';
16
+ import type { TokenCodec } from '../tokens/token-codec.js';
17
+ import type { IAuthProvider, IDataProvider, IEventSink, INotificationProvider, IStorageProvider, SelvaConfig, SelvaFlags } from '@selvajs/platform';
18
+ export interface SelvaDeps {
19
+ auth: IAuthProvider;
20
+ storage: IStorageProvider;
21
+ data: IDataProvider;
22
+ /** `data.orgs` — hoisted because 18 v1 call sites read it directly. */
23
+ orgs: IDataProvider['orgs'];
24
+ /** `data.projects` — 18 call sites. */
25
+ projects: IDataProvider['projects'];
26
+ /** `data.definitions` — the definition metadata store. */
27
+ definitionMeta: IDataProvider['definitions'];
28
+ computeServer: IDataProvider['computeServer'];
29
+ userProfile: IDataProvider['userProfile'];
30
+ shareLinks: IDataProvider['shareLinks'];
31
+ invites: IDataProvider['invites'];
32
+ permissions: IDataProvider['permissions'];
33
+ platformProjectGrants: IDataProvider['platformProjectGrants'];
34
+ /**
35
+ * Audit sink. Never optional here even though `SelvaConfig.events` is:
36
+ * handlers emit escalation events (`project.reclaimed`,
37
+ * `org_member.removed_orphaning_projects`) that the audit trail depends on,
38
+ * and a handler deciding for itself what a missing sink means is how one of
39
+ * them ends up silently unlogged. `depsFromConfig` substitutes
40
+ * `NoopEventSink`, which discards explicitly.
41
+ */
42
+ events: IEventSink;
43
+ /**
44
+ * Feature flags, as a predicate rather than a record: an omitted flag must
45
+ * read as false, and keeping that in `isFlagEnabled` stops each caller from
46
+ * re-deciding what a missing flag means.
47
+ */
48
+ flag: (name: keyof SelvaFlags) => boolean;
49
+ /**
50
+ * Token codecs, one per family, keyed by what they mint.
51
+ *
52
+ * Injected rather than resolved because the codec is built from an
53
+ * instance-wide HMAC secret, and reading that secret is the host's job — a
54
+ * package that reached for `process.env.SELVA_HMAC_KEY` itself would pin
55
+ * every host to one env var name and one way of loading it. Rotating a
56
+ * secret invalidates that family's outstanding tokens, so the two families
57
+ * are separate values rather than one shared codec.
58
+ *
59
+ * Optional: a host with no sharing and no invites wires neither. The
60
+ * handlers that need one fail loudly if it is absent rather than minting a
61
+ * token nobody can verify.
62
+ */
63
+ tokens: {
64
+ shareLinks?: TokenCodec;
65
+ invites?: TokenCodec;
66
+ };
67
+ /**
68
+ * Upload caps, in bytes.
69
+ *
70
+ * Deployment config, so the host resolves them — a package reading its own
71
+ * env would pin every host to one variable name. Defaults apply when the
72
+ * host says nothing, because a missing cap must not read as "unlimited":
73
+ * `requireUpload` compares against this number, and `undefined` would let
74
+ * any size through.
75
+ */
76
+ uploadLimits: {
77
+ maxDefinitionFileSize: number;
78
+ maxImageFileSize: number;
79
+ };
80
+ /**
81
+ * Outbound mail, and the instance name to fall back to when a record has no
82
+ * name of its own.
83
+ *
84
+ * Optional because mail is best-effort by design: an invite row is committed
85
+ * before delivery is attempted, and the caller still holds the accept URL to
86
+ * share by hand. A host with no mail configured wires nothing and the
87
+ * handlers report `not-configured` rather than failing the write.
88
+ */
89
+ notifications?: INotificationProvider;
90
+ /** Instance display name, used where a record has none. */
91
+ instanceName: string;
92
+ /**
93
+ * Drop the host's warm compute client for one server id.
94
+ *
95
+ * A warm client caches on server `id`, so a rotated URL or key keeps the
96
+ * same cache key with stale connection details and never ages out. The
97
+ * config-write handlers evict through this rather than importing a cache:
98
+ * which cache holds them is the host's decision, and importing one would
99
+ * pull a whole solve engine into every consumer.
100
+ *
101
+ * Defaults to a no-op — a host with no client cache has nothing to evict,
102
+ * and the handler must not have to know which kind of host it is running on.
103
+ */
104
+ evictComputeClient: (id: string) => void;
105
+ /**
106
+ * Composed services the host supplies.
107
+ *
108
+ * The named ones are typed because handlers call them — leaving a service
109
+ * `unknown` pushes a cast into every call site, and a cast is exactly where
110
+ * a second host's differently-shaped service would slip through unnoticed.
111
+ * The index signature keeps host-specific extras possible without naming
112
+ * them here.
113
+ */
114
+ services: {
115
+ definitions?: DefinitionService;
116
+ orgAssets?: OrgAssetService;
117
+ } & Record<string, unknown>;
118
+ }
119
+ /**
120
+ * Build deps from a resolved `SelvaConfig`, plus whatever services and token
121
+ * codecs the host composed on top. The hoisted fields are aliases into `data`,
122
+ * not copies.
123
+ *
124
+ * `services` stays positional — every existing caller passes it there — and
125
+ * `tokens` arrives in an options object rather than as a third positional, so
126
+ * the two composed bags cannot be swapped at a call site.
127
+ */
128
+ export declare function depsFromConfig(config: SelvaConfig, services?: SelvaDeps['services'], { tokens, uploadLimits, evictComputeClient, notifications, instanceName }?: {
129
+ tokens?: SelvaDeps['tokens'];
130
+ uploadLimits?: Partial<SelvaDeps['uploadLimits']>;
131
+ evictComputeClient?: SelvaDeps['evictComputeClient'];
132
+ notifications?: INotificationProvider;
133
+ instanceName?: string;
134
+ }): SelvaDeps;
135
+ //# sourceMappingURL=deps.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deps.d.ts","sourceRoot":"","sources":["../../src/api/deps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAGH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,sCAAsC,CAAC;AAC9E,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uCAAuC,CAAC;AAC7E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,KAAK,EACX,aAAa,EACb,aAAa,EACb,UAAU,EACV,qBAAqB,EACrB,gBAAgB,EAChB,WAAW,EACX,UAAU,EACV,MAAM,mBAAmB,CAAC;AAE3B,MAAM,WAAW,SAAS;IACzB,IAAI,EAAE,aAAa,CAAC;IACpB,OAAO,EAAE,gBAAgB,CAAC;IAC1B,IAAI,EAAE,aAAa,CAAC;IACpB,uEAAuE;IACvE,IAAI,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC5B,uCAAuC;IACvC,QAAQ,EAAE,aAAa,CAAC,UAAU,CAAC,CAAC;IACpC,0DAA0D;IAC1D,cAAc,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;IAC7C,aAAa,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;IAC9C,WAAW,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;IAC1C,UAAU,EAAE,aAAa,CAAC,YAAY,CAAC,CAAC;IACxC,OAAO,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;IAClC,WAAW,EAAE,aAAa,CAAC,aAAa,CAAC,CAAC;IAC1C,qBAAqB,EAAE,aAAa,CAAC,uBAAuB,CAAC,CAAC;IAC9D;;;;;;;OAOG;IACH,MAAM,EAAE,UAAU,CAAC;IACnB;;;;OAIG;IACH,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,UAAU,KAAK,OAAO,CAAC;IAC1C;;;;;;;;;;;;;OAaG;IACH,MAAM,EAAE;QACP,UAAU,CAAC,EAAE,UAAU,CAAC;QACxB,OAAO,CAAC,EAAE,UAAU,CAAC;KACrB,CAAC;IACF;;;;;;;;OAQG;IACH,YAAY,EAAE;QACb,qBAAqB,EAAE,MAAM,CAAC;QAC9B,gBAAgB,EAAE,MAAM,CAAC;KACzB,CAAC;IACF;;;;;;;;OAQG;IACH,aAAa,CAAC,EAAE,qBAAqB,CAAC;IACtC,2DAA2D;IAC3D,YAAY,EAAE,MAAM,CAAC;IACrB;;;;;;;;;;;OAWG;IACH,kBAAkB,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC;;;;;;;;OAQG;IACH,QAAQ,EAAE;QACT,WAAW,CAAC,EAAE,iBAAiB,CAAC;QAChC,SAAS,CAAC,EAAE,eAAe,CAAC;KAC5B,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC5B;AAED;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAC7B,MAAM,EAAE,WAAW,EACnB,QAAQ,GAAE,SAAS,CAAC,UAAU,CAAM,EACpC,EACC,MAAW,EACX,YAAY,EACZ,kBAA6B,EAC7B,aAAa,EACb,YAAsB,EACtB,GAAE;IACF,MAAM,CAAC,EAAE,SAAS,CAAC,QAAQ,CAAC,CAAC;IAC7B,YAAY,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,cAAc,CAAC,CAAC,CAAC;IAClD,kBAAkB,CAAC,EAAE,SAAS,CAAC,oBAAoB,CAAC,CAAC;IACrD,aAAa,CAAC,EAAE,qBAAqB,CAAC;IACtC,YAAY,CAAC,EAAE,MAAM,CAAC;CACjB,GACJ,SAAS,CA8BX"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * Everything an API handler talks to, as one injected value.
3
+ *
4
+ * Handlers used to reach module-global getters (`getProjectProvider()`,
5
+ * `getDefinitionService()`, …) from the Selva app's composition root — 77 call
6
+ * sites across the v1 routes. That welded them to one app's boot: a second app
7
+ * on a different provider set (parafa, on Supabase) could not call them at all.
8
+ *
9
+ * Most fields are sub-stores of `IDataProvider`, so a host that already built a
10
+ * `SelvaConfig` gets them via `depsFromConfig`. `services` stays host-defined:
11
+ * `DefinitionService` and friends are composed rather than resolved, and a host
12
+ * may supply its own.
13
+ */
14
+ import { isFlagEnabled, NoopEventSink } from '@selvajs/platform';
15
+ /**
16
+ * Build deps from a resolved `SelvaConfig`, plus whatever services and token
17
+ * codecs the host composed on top. The hoisted fields are aliases into `data`,
18
+ * not copies.
19
+ *
20
+ * `services` stays positional — every existing caller passes it there — and
21
+ * `tokens` arrives in an options object rather than as a third positional, so
22
+ * the two composed bags cannot be swapped at a call site.
23
+ */
24
+ export function depsFromConfig(config, services = {}, { tokens = {}, uploadLimits, evictComputeClient = () => { }, notifications, instanceName = 'Selva' } = {}) {
25
+ const { data } = config;
26
+ return {
27
+ auth: config.auth,
28
+ storage: config.storage,
29
+ data,
30
+ orgs: data.orgs,
31
+ projects: data.projects,
32
+ definitionMeta: data.definitions,
33
+ computeServer: data.computeServer,
34
+ userProfile: data.userProfile,
35
+ shareLinks: data.shareLinks,
36
+ invites: data.invites,
37
+ permissions: data.permissions,
38
+ platformProjectGrants: data.platformProjectGrants,
39
+ events: config.events ?? new NoopEventSink(),
40
+ flag: (name) => isFlagEnabled(config, name),
41
+ tokens,
42
+ // Same defaults `resolveComputeLimits` applies, repeated rather than
43
+ // imported: pulling that in would make every host resolving deps also
44
+ // resolve compute limits from env, which is the coupling this avoids.
45
+ uploadLimits: {
46
+ maxDefinitionFileSize: uploadLimits?.maxDefinitionFileSize ?? 50 * 1024 * 1024,
47
+ maxImageFileSize: uploadLimits?.maxImageFileSize ?? 10 * 1024 * 1024
48
+ },
49
+ evictComputeClient,
50
+ notifications,
51
+ instanceName,
52
+ services
53
+ };
54
+ }
55
+ //# sourceMappingURL=deps.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deps.js","sourceRoot":"","sources":["../../src/api/deps.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAoHjE;;;;;;;;GAQG;AACH,MAAM,UAAU,cAAc,CAC7B,MAAmB,EACnB,WAAkC,EAAE,EACpC,EACC,MAAM,GAAG,EAAE,EACX,YAAY,EACZ,kBAAkB,GAAG,GAAG,EAAE,GAAE,CAAC,EAC7B,aAAa,EACb,YAAY,GAAG,OAAO,KAOnB,EAAE;IAEN,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC;IACxB,OAAO;QACN,IAAI,EAAE,MAAM,CAAC,IAAI;QACjB,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,IAAI;QACJ,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,QAAQ,EAAE,IAAI,CAAC,QAAQ;QACvB,cAAc,EAAE,IAAI,CAAC,WAAW;QAChC,aAAa,EAAE,IAAI,CAAC,aAAa;QACjC,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,qBAAqB,EAAE,IAAI,CAAC,qBAAqB;QACjD,MAAM,EAAE,MAAM,CAAC,MAAM,IAAI,IAAI,aAAa,EAAE;QAC5C,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,CAAC,MAAM,EAAE,IAAI,CAAC;QAC3C,MAAM;QACN,qEAAqE;QACrE,sEAAsE;QACtE,sEAAsE;QACtE,YAAY,EAAE;YACb,qBAAqB,EAAE,YAAY,EAAE,qBAAqB,IAAI,EAAE,GAAG,IAAI,GAAG,IAAI;YAC9E,gBAAgB,EAAE,YAAY,EAAE,gBAAgB,IAAI,EAAE,GAAG,IAAI,GAAG,IAAI;SACpE;QACD,kBAAkB;QAClB,aAAa;QACb,YAAY;QACZ,QAAQ;KACR,CAAC;AACH,CAAC"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * The transport-free error type every API handler raises.
3
+ *
4
+ * `apiError` used to throw SvelteKit's `error()` directly, which welded all 151
5
+ * of its call sites to one framework. `ApiError` carries the same envelope as a
6
+ * plain exception; the host adapter converts it to whatever its framework
7
+ * expects (see `toApiResponse`). Call sites are unchanged — only the throw
8
+ * site and the boundary know the difference.
9
+ */
10
+ /** Stable, machine-readable error codes. Append-only — never renumber/rename. */
11
+ export declare const ApiErrorCode: {
12
+ readonly VALIDATION_FAILED: "VALIDATION_FAILED";
13
+ readonly UNAUTHORIZED: "UNAUTHORIZED";
14
+ readonly FORBIDDEN: "FORBIDDEN";
15
+ readonly NOT_FOUND: "NOT_FOUND";
16
+ readonly CONFLICT: "CONFLICT";
17
+ readonly UNPROCESSABLE: "UNPROCESSABLE";
18
+ readonly COMPUTE_UNAVAILABLE: "COMPUTE_UNAVAILABLE";
19
+ readonly SETUP_REQUIRED: "SETUP_REQUIRED";
20
+ readonly INTERNAL: "INTERNAL";
21
+ };
22
+ export type ApiErrorCode = (typeof ApiErrorCode)[keyof typeof ApiErrorCode];
23
+ export declare class ApiError extends Error {
24
+ readonly status: number;
25
+ readonly code: ApiErrorCode;
26
+ /** Per-field validation messages, keyed by dotted path. Only on VALIDATION_FAILED. */
27
+ readonly fields?: Record<string, string>;
28
+ constructor(status: number, code: ApiErrorCode, message: string, fields?: Record<string, string>);
29
+ }
30
+ export declare function isApiError(err: unknown): err is ApiError;
31
+ /** Raise a structured API error. The only way handlers should fail. */
32
+ export declare function apiError(status: number, code: ApiErrorCode, message: string, fields?: Record<string, string>): never;
33
+ /** Default code for a status, for mapping errors that carry no code of their own. */
34
+ export declare function codeForStatus(status: number): ApiErrorCode;
35
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/api/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,iFAAiF;AACjF,eAAO,MAAM,YAAY;;;;;;;;;;CAUf,CAAC;AAEX,MAAM,MAAM,YAAY,GAAG,CAAC,OAAO,YAAY,CAAC,CAAC,MAAM,OAAO,YAAY,CAAC,CAAC;AAE5E,qBAAa,QAAS,SAAQ,KAAK;IAClC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,sFAAsF;IACtF,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;gBAGxC,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,YAAY,EAClB,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC;CAQhC;AAED,wBAAgB,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,IAAI,QAAQ,CAExD;AAED,uEAAuE;AACvE,wBAAgB,QAAQ,CACvB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,YAAY,EAClB,OAAO,EAAE,MAAM,EACf,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC7B,KAAK,CAEP;AAED,qFAAqF;AACrF,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAmB1D"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * The transport-free error type every API handler raises.
3
+ *
4
+ * `apiError` used to throw SvelteKit's `error()` directly, which welded all 151
5
+ * of its call sites to one framework. `ApiError` carries the same envelope as a
6
+ * plain exception; the host adapter converts it to whatever its framework
7
+ * expects (see `toApiResponse`). Call sites are unchanged — only the throw
8
+ * site and the boundary know the difference.
9
+ */
10
+ /** Stable, machine-readable error codes. Append-only — never renumber/rename. */
11
+ export const ApiErrorCode = {
12
+ VALIDATION_FAILED: 'VALIDATION_FAILED',
13
+ UNAUTHORIZED: 'UNAUTHORIZED',
14
+ FORBIDDEN: 'FORBIDDEN',
15
+ NOT_FOUND: 'NOT_FOUND',
16
+ CONFLICT: 'CONFLICT',
17
+ UNPROCESSABLE: 'UNPROCESSABLE',
18
+ COMPUTE_UNAVAILABLE: 'COMPUTE_UNAVAILABLE',
19
+ SETUP_REQUIRED: 'SETUP_REQUIRED',
20
+ INTERNAL: 'INTERNAL'
21
+ };
22
+ export class ApiError extends Error {
23
+ status;
24
+ code;
25
+ /** Per-field validation messages, keyed by dotted path. Only on VALIDATION_FAILED. */
26
+ fields;
27
+ constructor(status, code, message, fields) {
28
+ super(message);
29
+ this.name = 'ApiError';
30
+ this.status = status;
31
+ this.code = code;
32
+ this.fields = fields;
33
+ }
34
+ }
35
+ export function isApiError(err) {
36
+ return err instanceof ApiError;
37
+ }
38
+ /** Raise a structured API error. The only way handlers should fail. */
39
+ export function apiError(status, code, message, fields) {
40
+ throw new ApiError(status, code, message, fields);
41
+ }
42
+ /** Default code for a status, for mapping errors that carry no code of their own. */
43
+ export function codeForStatus(status) {
44
+ switch (status) {
45
+ case 400:
46
+ return ApiErrorCode.VALIDATION_FAILED;
47
+ case 401:
48
+ return ApiErrorCode.UNAUTHORIZED;
49
+ case 403:
50
+ return ApiErrorCode.FORBIDDEN;
51
+ case 404:
52
+ return ApiErrorCode.NOT_FOUND;
53
+ case 409:
54
+ return ApiErrorCode.CONFLICT;
55
+ case 422:
56
+ return ApiErrorCode.UNPROCESSABLE;
57
+ case 503:
58
+ return ApiErrorCode.COMPUTE_UNAVAILABLE;
59
+ default:
60
+ return ApiErrorCode.INTERNAL;
61
+ }
62
+ }
63
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/api/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,iFAAiF;AACjF,MAAM,CAAC,MAAM,YAAY,GAAG;IAC3B,iBAAiB,EAAE,mBAAmB;IACtC,YAAY,EAAE,cAAc;IAC5B,SAAS,EAAE,WAAW;IACtB,SAAS,EAAE,WAAW;IACtB,QAAQ,EAAE,UAAU;IACpB,aAAa,EAAE,eAAe;IAC9B,mBAAmB,EAAE,qBAAqB;IAC1C,cAAc,EAAE,gBAAgB;IAChC,QAAQ,EAAE,UAAU;CACX,CAAC;AAIX,MAAM,OAAO,QAAS,SAAQ,KAAK;IACzB,MAAM,CAAS;IACf,IAAI,CAAe;IAC5B,sFAAsF;IAC7E,MAAM,CAA0B;IAEzC,YACC,MAAc,EACd,IAAkB,EAClB,OAAe,EACf,MAA+B;QAE/B,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACtB,CAAC;CACD;AAED,MAAM,UAAU,UAAU,CAAC,GAAY;IACtC,OAAO,GAAG,YAAY,QAAQ,CAAC;AAChC,CAAC;AAED,uEAAuE;AACvE,MAAM,UAAU,QAAQ,CACvB,MAAc,EACd,IAAkB,EAClB,OAAe,EACf,MAA+B;IAE/B,MAAM,IAAI,QAAQ,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;AACnD,CAAC;AAED,qFAAqF;AACrF,MAAM,UAAU,aAAa,CAAC,MAAc;IAC3C,QAAQ,MAAM,EAAE,CAAC;QAChB,KAAK,GAAG;YACP,OAAO,YAAY,CAAC,iBAAiB,CAAC;QACvC,KAAK,GAAG;YACP,OAAO,YAAY,CAAC,YAAY,CAAC;QAClC,KAAK,GAAG;YACP,OAAO,YAAY,CAAC,SAAS,CAAC;QAC/B,KAAK,GAAG;YACP,OAAO,YAAY,CAAC,SAAS,CAAC;QAC/B,KAAK,GAAG;YACP,OAAO,YAAY,CAAC,QAAQ,CAAC;QAC9B,KAAK,GAAG;YACP,OAAO,YAAY,CAAC,aAAa,CAAC;QACnC,KAAK,GAAG;YACP,OAAO,YAAY,CAAC,mBAAmB,CAAC;QACzC;YACC,OAAO,YAAY,CAAC,QAAQ,CAAC;IAC/B,CAAC;AACF,CAAC"}
@@ -0,0 +1,12 @@
1
+ export { ApiError, ApiErrorCode, apiError, codeForStatus, isApiError } from './errors.js';
2
+ export type { ApiHandler, ApiRequest, ApiResponse } from './types.js';
3
+ export { depsFromConfig, type SelvaDeps } from './deps.js';
4
+ export { collection, created, noContent } from './responses.js';
5
+ export { shaped, shapedCollection } from './shaped.js';
6
+ export { formText, parseBody, parseParam, requireCaller, requireParams, requireUpload, throwZodError } from './request.js';
7
+ export { runHandler, toErrorBody, type ApiErrorBody } from './respond.js';
8
+ export { mapCoreError } from './map-core-error.js';
9
+ export { parseListOptions, parseDefinitionListOptions } from './pagination.js';
10
+ export { SolveBodySchema, CreateProjectBodySchema, UpdateProjectBodySchema, AddProjectMemberBodySchema, UpdateProjectMemberBodySchema, CreateInviteBodySchema, OrgComputePatchBodySchema, UpdateOrgMemberBodySchema } from './bodies.js';
11
+ export { ShareLinkResponseSchema, CreatedShareLinkResponseSchema, InviteResponseSchema, CreatedInviteResponseSchema, OrgComputeServerResponseSchema, ComputeCatalogEntrySchema, OrgComputeResponseSchema, type ShareLinkResponse } from './responses-schema.js';
12
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAC1F,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AACtE,OAAO,EAAE,cAAc,EAAE,KAAK,SAAS,EAAE,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EACN,QAAQ,EACR,SAAS,EACT,UAAU,EACV,aAAa,EACb,aAAa,EACb,aAAa,EACb,aAAa,EACb,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAC1E,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAC/E,OAAO,EACN,eAAe,EACf,uBAAuB,EACvB,uBAAuB,EACvB,0BAA0B,EAC1B,6BAA6B,EAC7B,sBAAsB,EACtB,yBAAyB,EACzB,yBAAyB,EACzB,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,uBAAuB,EACvB,8BAA8B,EAC9B,oBAAoB,EACpB,2BAA2B,EAC3B,8BAA8B,EAC9B,yBAAyB,EACzB,wBAAwB,EACxB,KAAK,iBAAiB,EACtB,MAAM,uBAAuB,CAAC"}
@@ -0,0 +1,15 @@
1
+ // Transport-free API core — handler contract, injected deps, error envelope.
2
+ //
3
+ // A host binds this by building an `ApiRequest` and calling `runHandler`; the
4
+ // handlers themselves name no web framework. See `api/README.md`.
5
+ export { ApiError, ApiErrorCode, apiError, codeForStatus, isApiError } from './errors.js';
6
+ export { depsFromConfig } from './deps.js';
7
+ export { collection, created, noContent } from './responses.js';
8
+ export { shaped, shapedCollection } from './shaped.js';
9
+ export { formText, parseBody, parseParam, requireCaller, requireParams, requireUpload, throwZodError } from './request.js';
10
+ export { runHandler, toErrorBody } from './respond.js';
11
+ export { mapCoreError } from './map-core-error.js';
12
+ export { parseListOptions, parseDefinitionListOptions } from './pagination.js';
13
+ export { SolveBodySchema, CreateProjectBodySchema, UpdateProjectBodySchema, AddProjectMemberBodySchema, UpdateProjectMemberBodySchema, CreateInviteBodySchema, OrgComputePatchBodySchema, UpdateOrgMemberBodySchema } from './bodies.js';
14
+ export { ShareLinkResponseSchema, CreatedShareLinkResponseSchema, InviteResponseSchema, CreatedInviteResponseSchema, OrgComputeServerResponseSchema, ComputeCatalogEntrySchema, OrgComputeResponseSchema } from './responses-schema.js';
15
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,EAAE;AACF,8EAA8E;AAC9E,kEAAkE;AAElE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAE1F,OAAO,EAAE,cAAc,EAAkB,MAAM,WAAW,CAAC;AAC3D,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChE,OAAO,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACvD,OAAO,EACN,QAAQ,EACR,SAAS,EACT,UAAU,EACV,aAAa,EACb,aAAa,EACb,aAAa,EACb,aAAa,EACb,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,UAAU,EAAE,WAAW,EAAqB,MAAM,cAAc,CAAC;AAC1E,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAC/E,OAAO,EACN,eAAe,EACf,uBAAuB,EACvB,uBAAuB,EACvB,0BAA0B,EAC1B,6BAA6B,EAC7B,sBAAsB,EACtB,yBAAyB,EACzB,yBAAyB,EACzB,MAAM,aAAa,CAAC;AACrB,OAAO,EACN,uBAAuB,EACvB,8BAA8B,EAC9B,oBAAoB,EACpB,2BAA2B,EAC3B,8BAA8B,EAC9B,yBAAyB,EACzB,wBAAwB,EAExB,MAAM,uBAAuB,CAAC"}