@happyvertical/smrt-core 0.46.0 → 0.47.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 (90) hide show
  1. package/AGENTS.md +39 -0
  2. package/agents/generators.md +19 -5
  3. package/agents/system-diagnostics.md +43 -0
  4. package/dist/browser.js +2 -1
  5. package/dist/change-feed.d.ts +8 -0
  6. package/dist/change-feed.d.ts.map +1 -1
  7. package/dist/change-feed.js +1 -1
  8. package/dist/change-feed.js.map +1 -1
  9. package/dist/decorators/compatibility.d.ts +46 -0
  10. package/dist/decorators/compatibility.d.ts.map +1 -1
  11. package/dist/decorators/compatibility.js +48 -5
  12. package/dist/decorators/compatibility.js.map +1 -1
  13. package/dist/decorators/index.d.ts +119 -1
  14. package/dist/decorators/index.d.ts.map +1 -1
  15. package/dist/decorators/index.js +52 -8
  16. package/dist/decorators/index.js.map +1 -1
  17. package/dist/generators/custom-action.d.ts +379 -2
  18. package/dist/generators/custom-action.d.ts.map +1 -1
  19. package/dist/generators/custom-action.js +694 -17
  20. package/dist/generators/custom-action.js.map +1 -1
  21. package/dist/generators/index.d.ts +1 -1
  22. package/dist/generators/index.d.ts.map +1 -1
  23. package/dist/generators/index.js +2 -2
  24. package/dist/generators/preflight-route.d.ts +12 -10
  25. package/dist/generators/preflight-route.d.ts.map +1 -1
  26. package/dist/generators/preflight-route.js +46 -14
  27. package/dist/generators/preflight-route.js.map +1 -1
  28. package/dist/generators/rest.d.ts +44 -0
  29. package/dist/generators/rest.d.ts.map +1 -1
  30. package/dist/generators/rest.js +84 -9
  31. package/dist/generators/rest.js.map +1 -1
  32. package/dist/generators.js +2 -2
  33. package/dist/index.d.ts +2 -2
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +5 -4
  36. package/dist/knowledge.d.ts.map +1 -1
  37. package/dist/knowledge.js +59 -15
  38. package/dist/knowledge.js.map +1 -1
  39. package/dist/manifest/static-manifest.d.ts.map +1 -1
  40. package/dist/manifest/static-manifest.js +125 -53
  41. package/dist/manifest/static-manifest.js.map +1 -1
  42. package/dist/manifest/store.js +1 -1
  43. package/dist/manifest/store.js.map +1 -1
  44. package/dist/manifest.json +184 -53
  45. package/dist/postgres-permissions.d.ts +9 -1
  46. package/dist/postgres-permissions.d.ts.map +1 -1
  47. package/dist/postgres-permissions.js +127 -13
  48. package/dist/postgres-permissions.js.map +1 -1
  49. package/dist/registry/index.d.ts +1 -1
  50. package/dist/registry/index.d.ts.map +1 -1
  51. package/dist/registry/shared-state.d.ts +19 -0
  52. package/dist/registry/shared-state.d.ts.map +1 -1
  53. package/dist/registry/shared-state.js +16 -1
  54. package/dist/registry/shared-state.js.map +1 -1
  55. package/dist/registry.d.ts +136 -1
  56. package/dist/registry.d.ts.map +1 -1
  57. package/dist/registry.js +231 -1
  58. package/dist/registry.js.map +1 -1
  59. package/dist/scanner/manifest-generator.d.ts.map +1 -1
  60. package/dist/scanner/manifest-generator.js +18 -16
  61. package/dist/scanner/manifest-generator.js.map +1 -1
  62. package/dist/scanner/types.d.ts +59 -6
  63. package/dist/scanner/types.d.ts.map +1 -1
  64. package/dist/scanner/types.js.map +1 -1
  65. package/dist/smrt-knowledge.json +42 -35
  66. package/dist/system/diagnostics.d.ts +299 -0
  67. package/dist/system/diagnostics.d.ts.map +1 -0
  68. package/dist/system/diagnostics.js +530 -0
  69. package/dist/system/diagnostics.js.map +1 -0
  70. package/dist/system/index.d.ts +1 -0
  71. package/dist/system/index.d.ts.map +1 -1
  72. package/dist/system/index.js +2 -1
  73. package/dist/utils/scanner-module.d.ts +16 -0
  74. package/dist/utils/scanner-module.d.ts.map +1 -1
  75. package/dist/vite-plugin/api-client-entries.d.ts.map +1 -1
  76. package/dist/vite-plugin/api-client-entries.js +10 -8
  77. package/dist/vite-plugin/api-client-entries.js.map +1 -1
  78. package/dist/vite-plugin/index.d.ts +34 -1
  79. package/dist/vite-plugin/index.d.ts.map +1 -1
  80. package/dist/vite-plugin/index.js +82 -3
  81. package/dist/vite-plugin/index.js.map +1 -1
  82. package/dist/vite-plugin/sveltekit-generator.d.ts +28 -2
  83. package/dist/vite-plugin/sveltekit-generator.d.ts.map +1 -1
  84. package/dist/vite-plugin/sveltekit-generator.js +121 -51
  85. package/dist/vite-plugin/sveltekit-generator.js.map +1 -1
  86. package/dist/vite-plugin/web-collections.d.ts.map +1 -1
  87. package/dist/vite-plugin/web-collections.js +1 -1
  88. package/dist/vite-plugin/web-collections.js.map +1 -1
  89. package/dist/vite-plugin.js +2 -2
  90. package/package.json +16 -11
@@ -179,6 +179,50 @@ export declare class APIGenerator {
179
179
  * a returned `{ ok: false, ... }` failure becomes its requested non-2xx
180
180
  * status with a redacted payload, and success wraps as `{ action, result }`.
181
181
  */
182
+ /**
183
+ * Every action this transport treats as DECLARED for a collection route,
184
+ * paired with its manifest method definition when one is known.
185
+ *
186
+ * The union of two declaration sources, so migrating a route entry onto its
187
+ * method does not silently drop the route here (#2686):
188
+ *
189
+ * - a `api.routes[action]` entry, this transport's only source before;
190
+ * - a method whose `@method()` supplies route-shaping metadata
191
+ * (`httpMethod`, `path`, or `scope`).
192
+ *
193
+ * Deliberately still DECLARATION-gated rather than adopting the generated
194
+ * transport's default-route heuristic: this router's URL shape supports only
195
+ * single-segment collection paths, and widening it to every wire-able public
196
+ * method would publish endpoints that have never existed here. That is a
197
+ * separate contract change, not a compatibility fix.
198
+ *
199
+ * `declaresRuntimeRestRoute` is shared with `isRestActionRoutable`, the
200
+ * browser-plane preflight prediction of this same dispatch, so the route and
201
+ * the prediction of the route cannot drift.
202
+ */
203
+ private declaredCollectionActions;
204
+ /**
205
+ * The method view a RUNTIME transport should read for one action: the
206
+ * manifest entry when the project was scanned, with its `@method()` config
207
+ * backfilled from the live decorator store when it is not.
208
+ */
209
+ private runtimeMethod;
210
+ /**
211
+ * Refuse a request that matched a DECLARED action's own path and verb but
212
+ * whose action is withheld — or return `null` to let it fall through.
213
+ *
214
+ * Only `POST` is refused, and the asymmetry is the whole point.
215
+ * `getCrudAction` maps `POST` to `create` and DISCARDS the path segment, so
216
+ * falling through writes a row and answers 201 for a request aimed at an
217
+ * operation the author withheld: silent, mutating, and the opposite of what
218
+ * the generated SvelteKit surface does for the same URL, which 404s because
219
+ * it wrote no route file. Every other verb carries the segment into a by-id
220
+ * operation that 404s on its own when the segment is not an id — and that
221
+ * fall-through is load-bearing, because an object's id may legitimately equal
222
+ * a declared action's path, and `GET /<collection>/<id>` must keep resolving
223
+ * to that object (#2686).
224
+ */
225
+ private refuseWithheldAction;
182
226
  private dispatchCustomCollectionAction;
183
227
  /**
184
228
  * Public-safe projection for custom-action results, mirroring the generated
@@ -1 +1 @@
1
- {"version":3,"file":"rest.d.ts","sourceRoot":"","sources":["../../src/generators/rest.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"rest.d.ts","sourceRoot":"","sources":["../../src/generators/rest.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAKpD,OAAO,KAAK,EAAqB,UAAU,EAAE,MAAM,WAAW,CAAC;AAQ/D,OAAO,KAAK,EAEV,eAAe,EAGhB,MAAM,mBAAmB,CAAC;AAoC3B,OAAO,EAKL,KAAK,yBAAyB,EAC/B,MAAM,mBAAmB,CAAC;AAG3B,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;IAC1B;;;;;;;;;;OAUG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;IACnE,cAAc,CAAC,EAAE,CACf,UAAU,EAAE,MAAM,EAClB,MAAM,EAAE,MAAM,KACX,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,OAAO,GAAG,QAAQ,CAAC,CAAC;IACnD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,WAAW,CAAC,EAAE;QACZ,cAAc,CAAC,EAAE,MAAM,CAAC;KACzB,CAAC;IACF;;;;;;;;;OASG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;;;;;;OASG;IACH,iBAAiB,CAAC,EAAE,yBAAyB,CAAC;CAC/C;AAED,MAAM,WAAW,UAAU;IACzB,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,IAAI,CAAC,EAAE;QACL,EAAE,EAAE,MAAM,CAAC;QACX,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;KAClB,CAAC;IACF,oDAAoD;IACpD,WAAW,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;CAChC;AAiED;;;;GAIG;AACH,wBAAgB,6BAA6B,CAC3C,OAAO,GAAE,QAAQ,CAAC,CAAC,MAAM,EAAE,eAAe,CAAC,CAAkC,GAC5E,MAAM,CAcR;AAED;;GAEG;AACH,qBAAa,YAAY;IACvB,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,WAAW,CAAiD;IACpE,OAAO,CAAC,OAAO,CAAa;IAC5B,OAAO,CAAC,mBAAmB,CAAqB;gBAEpC,MAAM,GAAE,SAAc,EAAE,OAAO,GAAE,UAAe;IAa5D;;;;;OAKG;IACH,kBAAkB,CAChB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,cAAc,CAAC,UAAU,CAAC,GACrC,IAAI;IAKP;;;;;;;;;OASG;IACH,OAAO,CAAC,gBAAgB;IAMxB;;OAEG;IACH,YAAY,IAAI;QAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE;IAoBpD;;OAEG;YACW,cAAc;IAQ5B;;OAEG;YACW,uBAAuB;IAyBrC;;OAEG;YACW,yBAAyB;IAkEvC;;OAEG;IACH,eAAe,IAAI,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC;IAItD;;OAEG;YACW,aAAa;IA4E3B;;OAEG;YACW,iBAAiB;IAmG/B;;OAEG;YACW,oBAAoB;IAiFlC,OAAO,CAAC,aAAa;IAmBrB;;;;;;OAMG;IACH,OAAO,CAAC,aAAa;IASrB,OAAO,CAAC,kBAAkB;IAO1B,OAAO,CAAC,uBAAuB;IAuB/B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IACH;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,OAAO,CAAC,yBAAyB;IAsBjC;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAOrB;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,oBAAoB;YAYd,8BAA8B;IA2N5C;;;;;;OAMG;IACH,OAAO,CAAC,oBAAoB;IAoC5B;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,OAAO,CAAC,sBAAsB;IAmB9B;;;;;;OAMG;IACH,OAAO,CAAC,oBAAoB;IAsB5B;;OAEG;YACW,SAAS;IAkEvB;;OAEG;YACW,UAAU;IAwFxB;;OAEG;YACW,WAAW;IA8CzB;;OAEG;YACW,YAAY;IAW1B;;OAEG;YACW,YAAY;IAoB1B;;OAEG;YACW,YAAY;IAc1B;;;;;OAKG;YACW,eAAe;IAqB7B;;;;OAIG;YACW,sBAAsB;IA+DpC;;OAEG;YACW,aAAa;IA6B3B;;;;OAIG;IACH,OAAO,CAAC,mBAAmB;IAiD3B;;;OAGG;IACH,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,oBAAoB;IAI5B;;;;;;;OAOG;IACH,OAAO,CAAC,sBAAsB;IA2B9B;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,OAAO,CAAC,yBAAyB;IAejC,OAAO,CAAC,uBAAuB;IAe/B,OAAO,CAAC,2BAA2B;IAyBnC;;;;;;;;;;OAUG;YACW,eAAe;IAqB7B,OAAO,CAAC,mBAAmB;IAQ3B;;;;;OAKG;IACH,OAAO,CAAC,uBAAuB;IAY/B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAS1B;;OAEG;IACH,OAAO,CAAC,mBAAmB;IAS3B;;;;OAIG;IACH,OAAO,CAAC,oBAAoB;IAQ5B;;;;;OAKG;IACH,OAAO,CAAC,sBAAsB;IAI9B;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAsB1B;;OAEG;IACH,OAAO,CAAC,cAAc;IA+BtB;;;;;;;;;;;;;;;OAeG;IACH,OAAO,CAAC,4BAA4B;IA0BpC;;OAEG;IACH,OAAO,CAAC,SAAS;CASlB;AAID,MAAM,WAAW,gBAAiB,SAAQ,SAAS;IACjD,WAAW,CAAC,EAAE;QACZ,OAAO,CAAC,EAAE,OAAO,CAAC;QAClB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,YAAY,CAAC,EAAE,CAAC,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;KAC3C,CAAC;CACH;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,CAAC,OAAO,UAAU,CAAC,EAAE,EAC9B,OAAO,GAAE,UAAe,EACxB,MAAM,GAAE,gBAAqB,GAC5B;IAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CActC;AAED;;GAEG;AACH,wBAAgB,eAAe,CAC7B,OAAO,EAAE,CAAC,OAAO,UAAU,CAAC,EAAE,EAC9B,OAAO,GAAE,UAAe,EACxB,MAAM,GAAE,gBAAqB,GAC5B,OAAO,CAAC,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC,CAwB9B"}
@@ -1,7 +1,7 @@
1
1
  import { isTenantScopedClassResolved, resolveDispatchTenantScope } from "../dispatch/tenant-resolver.js";
2
2
  import { getTableVersion } from "../change-feed.js";
3
3
  import { buildDefaultListOrderBy, resolveListLimit, resolveListOffset } from "../query-bounds.js";
4
- import { buildCustomActionInvocationArgs, normalizeCustomActionFailure, resolveCustomActionMetadata } from "./custom-action.js";
4
+ import { buildCustomActionInvocationArgs, declaresRuntimeRestRouteShape, normalizeCustomActionFailure, readMethodDecoratorConfig, resolveCustomActionMetadata, resolveEffectiveActionMetadata } from "./custom-action.js";
5
5
  import { isFrameworkBaseClass } from "../registry/framework-base-classes.js";
6
6
  import { ObjectRegistry } from "../registry.js";
7
7
  import "../dispatch/index.js";
@@ -385,28 +385,103 @@ var APIGenerator = class {
385
385
  * a returned `{ ok: false, ... }` failure becomes its requested non-2xx
386
386
  * status with a redacted payload, and success wraps as `{ action, result }`.
387
387
  */
388
+ /**
389
+ * Every action this transport treats as DECLARED for a collection route,
390
+ * paired with its manifest method definition when one is known.
391
+ *
392
+ * The union of two declaration sources, so migrating a route entry onto its
393
+ * method does not silently drop the route here (#2686):
394
+ *
395
+ * - a `api.routes[action]` entry, this transport's only source before;
396
+ * - a method whose `@method()` supplies route-shaping metadata
397
+ * (`httpMethod`, `path`, or `scope`).
398
+ *
399
+ * Deliberately still DECLARATION-gated rather than adopting the generated
400
+ * transport's default-route heuristic: this router's URL shape supports only
401
+ * single-segment collection paths, and widening it to every wire-able public
402
+ * method would publish endpoints that have never existed here. That is a
403
+ * separate contract change, not a compatibility fix.
404
+ *
405
+ * `declaresRuntimeRestRoute` is shared with `isRestActionRoutable`, the
406
+ * browser-plane preflight prediction of this same dispatch, so the route and
407
+ * the prediction of the route cannot drift.
408
+ */
409
+ declaredCollectionActions(objectName, apiConfig) {
410
+ const names = new Set(Object.keys(apiConfig.routes ?? {}));
411
+ for (const name of ObjectRegistry.listDecoratedMethodNames(objectName)) if (declaresRuntimeRestRouteShape(this.runtimeMethod(objectName, name))) names.add(name);
412
+ return [...names].map((name) => [name, this.runtimeMethod(objectName, name)]);
413
+ }
414
+ /**
415
+ * The method view a RUNTIME transport should read for one action: the
416
+ * manifest entry when the project was scanned, with its `@method()` config
417
+ * backfilled from the live decorator store when it is not.
418
+ */
419
+ runtimeMethod(objectName, methodName) {
420
+ return ObjectRegistry.resolveRuntimeMethod(objectName, methodName).method;
421
+ }
422
+ /**
423
+ * Refuse a request that matched a DECLARED action's own path and verb but
424
+ * whose action is withheld — or return `null` to let it fall through.
425
+ *
426
+ * Only `POST` is refused, and the asymmetry is the whole point.
427
+ * `getCrudAction` maps `POST` to `create` and DISCARDS the path segment, so
428
+ * falling through writes a row and answers 201 for a request aimed at an
429
+ * operation the author withheld: silent, mutating, and the opposite of what
430
+ * the generated SvelteKit surface does for the same URL, which 404s because
431
+ * it wrote no route file. Every other verb carries the segment into a by-id
432
+ * operation that 404s on its own when the segment is not an id — and that
433
+ * fall-through is load-bearing, because an object's id may legitimately equal
434
+ * a declared action's path, and `GET /<collection>/<id>` must keep resolving
435
+ * to that object (#2686).
436
+ */
437
+ refuseWithheldAction(req, actionName, withheldBy) {
438
+ if (req.method.toUpperCase() !== "POST") return null;
439
+ return this.createErrorResponse(404, `Custom action '${actionName}' is not exposed (${withheldBy})`);
440
+ }
388
441
  async dispatchCustomCollectionAction(req, collection, pathSegment, url, objectName) {
389
442
  const apiConfig = ObjectRegistry.getConfig(objectName)?.api;
390
- if (!apiConfig || typeof apiConfig !== "object" || !apiConfig.routes) return null;
391
- for (const [actionName, routeConfig] of Object.entries(apiConfig.routes)) {
392
- const routePath = routeConfig?.path || actionName;
443
+ if (!apiConfig || typeof apiConfig !== "object") return null;
444
+ const declaredActions = this.declaredCollectionActions(objectName, apiConfig);
445
+ if (declaredActions.length === 0) return null;
446
+ for (const [actionName, declaredMethod] of declaredActions) {
447
+ const effective = resolveEffectiveActionMetadata({
448
+ actionName,
449
+ ...declaredMethod ? { method: declaredMethod } : {},
450
+ apiConfig
451
+ });
452
+ const routePath = effective.path || actionName;
393
453
  if (routePath.includes("/") || routePath !== pathSegment) continue;
394
- const routeMethod = (routeConfig?.method || "POST").toUpperCase();
454
+ const routeMethod = (effective.httpMethod || "POST").toUpperCase();
395
455
  if (routeMethod !== req.method.toUpperCase()) continue;
396
- if (apiConfig.include && !apiConfig.include.includes(actionName)) continue;
397
- if (apiConfig.exclude?.includes(actionName)) continue;
456
+ if (apiConfig.include && !apiConfig.include.includes(actionName)) {
457
+ const refusal = this.refuseWithheldAction(req, actionName, "api.include");
458
+ if (refusal) return refusal;
459
+ continue;
460
+ }
461
+ if (apiConfig.exclude?.includes(actionName)) {
462
+ const refusal = this.refuseWithheldAction(req, actionName, "api.exclude");
463
+ if (refusal) return refusal;
464
+ continue;
465
+ }
466
+ if (readMethodDecoratorConfig(declaredMethod)?.expose === false) {
467
+ const refusal = this.refuseWithheldAction(req, actionName, "@method({ expose: false })");
468
+ if (refusal) return refusal;
469
+ continue;
470
+ }
398
471
  const collectionMethod = collection[actionName];
399
472
  const itemConstructor = ObjectRegistry.getClass(objectName)?.constructor;
400
473
  const staticMethod = itemConstructor?.[actionName];
401
474
  const isCollectionHosted = typeof collectionMethod === "function";
402
475
  if (!isCollectionHosted && !(!isCollectionHosted && typeof staticMethod === "function")) {
403
- if (routeConfig?.scope === "collection") return this.createErrorResponse(501, `Custom action '${actionName}' is declared but not implemented`);
476
+ if (effective.scope === "collection") return this.createErrorResponse(501, `Custom action '${actionName}' is declared but not implemented`);
477
+ const refusal = this.refuseWithheldAction(req, actionName, "an item-scoped declaration, which this transport does not serve");
478
+ if (refusal) return refusal;
404
479
  continue;
405
480
  }
406
481
  const metadata = resolveCustomActionMetadata({
407
482
  actionName,
408
483
  apiConfig,
409
- method: ObjectRegistry.getMethods(objectName)?.get(actionName),
484
+ ...declaredMethod ? { method: declaredMethod } : {},
410
485
  defaultScope: "collection"
411
486
  });
412
487
  if (metadata.scope !== "collection") continue;