@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.
- package/AGENTS.md +39 -0
- package/agents/generators.md +19 -5
- package/agents/system-diagnostics.md +43 -0
- package/dist/browser.js +2 -1
- package/dist/change-feed.d.ts +8 -0
- package/dist/change-feed.d.ts.map +1 -1
- package/dist/change-feed.js +1 -1
- package/dist/change-feed.js.map +1 -1
- package/dist/decorators/compatibility.d.ts +46 -0
- package/dist/decorators/compatibility.d.ts.map +1 -1
- package/dist/decorators/compatibility.js +48 -5
- package/dist/decorators/compatibility.js.map +1 -1
- package/dist/decorators/index.d.ts +119 -1
- package/dist/decorators/index.d.ts.map +1 -1
- package/dist/decorators/index.js +52 -8
- package/dist/decorators/index.js.map +1 -1
- package/dist/generators/custom-action.d.ts +379 -2
- package/dist/generators/custom-action.d.ts.map +1 -1
- package/dist/generators/custom-action.js +694 -17
- package/dist/generators/custom-action.js.map +1 -1
- package/dist/generators/index.d.ts +1 -1
- package/dist/generators/index.d.ts.map +1 -1
- package/dist/generators/index.js +2 -2
- package/dist/generators/preflight-route.d.ts +12 -10
- package/dist/generators/preflight-route.d.ts.map +1 -1
- package/dist/generators/preflight-route.js +46 -14
- package/dist/generators/preflight-route.js.map +1 -1
- package/dist/generators/rest.d.ts +44 -0
- package/dist/generators/rest.d.ts.map +1 -1
- package/dist/generators/rest.js +84 -9
- package/dist/generators/rest.js.map +1 -1
- package/dist/generators.js +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -4
- package/dist/knowledge.d.ts.map +1 -1
- package/dist/knowledge.js +59 -15
- package/dist/knowledge.js.map +1 -1
- package/dist/manifest/static-manifest.d.ts.map +1 -1
- package/dist/manifest/static-manifest.js +125 -53
- package/dist/manifest/static-manifest.js.map +1 -1
- package/dist/manifest/store.js +1 -1
- package/dist/manifest/store.js.map +1 -1
- package/dist/manifest.json +184 -53
- package/dist/postgres-permissions.d.ts +9 -1
- package/dist/postgres-permissions.d.ts.map +1 -1
- package/dist/postgres-permissions.js +127 -13
- package/dist/postgres-permissions.js.map +1 -1
- package/dist/registry/index.d.ts +1 -1
- package/dist/registry/index.d.ts.map +1 -1
- package/dist/registry/shared-state.d.ts +19 -0
- package/dist/registry/shared-state.d.ts.map +1 -1
- package/dist/registry/shared-state.js +16 -1
- package/dist/registry/shared-state.js.map +1 -1
- package/dist/registry.d.ts +136 -1
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +231 -1
- package/dist/registry.js.map +1 -1
- package/dist/scanner/manifest-generator.d.ts.map +1 -1
- package/dist/scanner/manifest-generator.js +18 -16
- package/dist/scanner/manifest-generator.js.map +1 -1
- package/dist/scanner/types.d.ts +59 -6
- package/dist/scanner/types.d.ts.map +1 -1
- package/dist/scanner/types.js.map +1 -1
- package/dist/smrt-knowledge.json +42 -35
- package/dist/system/diagnostics.d.ts +299 -0
- package/dist/system/diagnostics.d.ts.map +1 -0
- package/dist/system/diagnostics.js +530 -0
- package/dist/system/diagnostics.js.map +1 -0
- package/dist/system/index.d.ts +1 -0
- package/dist/system/index.d.ts.map +1 -1
- package/dist/system/index.js +2 -1
- package/dist/utils/scanner-module.d.ts +16 -0
- package/dist/utils/scanner-module.d.ts.map +1 -1
- package/dist/vite-plugin/api-client-entries.d.ts.map +1 -1
- package/dist/vite-plugin/api-client-entries.js +10 -8
- package/dist/vite-plugin/api-client-entries.js.map +1 -1
- package/dist/vite-plugin/index.d.ts +34 -1
- package/dist/vite-plugin/index.d.ts.map +1 -1
- package/dist/vite-plugin/index.js +82 -3
- package/dist/vite-plugin/index.js.map +1 -1
- package/dist/vite-plugin/sveltekit-generator.d.ts +28 -2
- package/dist/vite-plugin/sveltekit-generator.d.ts.map +1 -1
- package/dist/vite-plugin/sveltekit-generator.js +121 -51
- package/dist/vite-plugin/sveltekit-generator.js.map +1 -1
- package/dist/vite-plugin/web-collections.d.ts.map +1 -1
- package/dist/vite-plugin/web-collections.js +1 -1
- package/dist/vite-plugin/web-collections.js.map +1 -1
- package/dist/vite-plugin.js +2 -2
- package/package.json +16 -11
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { MAX_LIST_LIMIT, buildDefaultListOrderBy } from "../query-bounds.js";
|
|
2
|
-
import { CRUD_OPERATIONS, isCrudOperation, resolveCustomActionMetadata, resolveCustomActionNames } from "../generators/custom-action.js";
|
|
2
|
+
import { CRUD_OPERATIONS, createManifestClassNamePredicate, declaredTypeAcceptsDate, isCrudOperation, queryStringDecoderFor, resolveApiMethodExposure, resolveCustomActionMetadata, resolveCustomActionNames, resolveDeclaredScopeMismatch, resolveEffectiveActionMetadata } from "../generators/custom-action.js";
|
|
3
3
|
import { isFrameworkBaseClass } from "../registry/framework-base-classes.js";
|
|
4
4
|
import { generateConditionalGetRouteHelper } from "../generators/conditional-get.js";
|
|
5
5
|
import { AUTO_GENERATED_ROUTE_HEADER } from "./route-header.js";
|
|
@@ -596,8 +596,12 @@ function extractRoutePathParamNames(pathSegments) {
|
|
|
596
596
|
return pathSegments.filter((segment) => /^\[[^\]]+\]$/.test(segment)).map((segment) => segment.slice(1, -1)).filter(Boolean);
|
|
597
597
|
}
|
|
598
598
|
function resolveApiActionRouteConfig(actionName, actionDef, apiConfig, routeOptions = {}, defaultScope = actionDef.isStatic ? "collection" : "item") {
|
|
599
|
-
const
|
|
600
|
-
|
|
599
|
+
const effective = resolveEffectiveActionMetadata({
|
|
600
|
+
actionName,
|
|
601
|
+
method: actionDef,
|
|
602
|
+
apiConfig
|
|
603
|
+
});
|
|
604
|
+
const pathSegments = normalizeCustomRoutePath(actionName, effective.path, routeOptions);
|
|
601
605
|
return {
|
|
602
606
|
scope: resolveCustomActionMetadata({
|
|
603
607
|
actionName,
|
|
@@ -605,7 +609,7 @@ function resolveApiActionRouteConfig(actionName, actionDef, apiConfig, routeOpti
|
|
|
605
609
|
apiConfig,
|
|
606
610
|
defaultScope
|
|
607
611
|
}).scope,
|
|
608
|
-
method: normalizeApiHttpMethod(
|
|
612
|
+
method: normalizeApiHttpMethod(effective.httpMethod),
|
|
609
613
|
pathSegments,
|
|
610
614
|
pathParamNames: extractRoutePathParamNames(pathSegments)
|
|
611
615
|
};
|
|
@@ -626,11 +630,15 @@ function hasSingleOptionsParameter(actionDef) {
|
|
|
626
630
|
const parameters = Array.isArray(actionDef.parameters) ? actionDef.parameters : [];
|
|
627
631
|
return parameters.length === 1 && parameters[0]?.name === "options";
|
|
628
632
|
}
|
|
629
|
-
function buildActionInvocationArgs(actionDef, optionsIdentifier = "options") {
|
|
633
|
+
function buildActionInvocationArgs(actionDef, optionsIdentifier = "options", httpMethod) {
|
|
630
634
|
const parameters = Array.isArray(actionDef.parameters) ? actionDef.parameters : [];
|
|
631
635
|
if (parameters.length === 0) return [];
|
|
632
636
|
if (hasSingleOptionsParameter(actionDef)) return [optionsIdentifier];
|
|
633
|
-
return parameters.map((parameter) =>
|
|
637
|
+
return parameters.map((parameter, index) => {
|
|
638
|
+
const access = buildOptionsPropertyAccess(parameter.name);
|
|
639
|
+
const decoder = httpMethod === "GET" ? queryStringDecoderFor(parameter.type) : declaredTypeAcceptsDate(parameter.type) ? "toCustomActionDate" : void 0;
|
|
640
|
+
return decoder ? `${decoder}(${access}) as ActionArgs[${index}]` : access;
|
|
641
|
+
});
|
|
634
642
|
}
|
|
635
643
|
function buildObjectTypeProperty(propertyName) {
|
|
636
644
|
if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(propertyName)) return propertyName;
|
|
@@ -1162,14 +1170,12 @@ async function generateRoutesForObject(projectRoot, className, objectDef, manife
|
|
|
1162
1170
|
const itemRoute = generateItemRouteTemplate(projectRoot, className, objectDef, manifest, includedActions, options, join(routeDir, "[id]"));
|
|
1163
1171
|
generatedRoutePaths.push(writeRoute(join(routeDir, "[id]"), "+server.ts", itemRoute));
|
|
1164
1172
|
}
|
|
1165
|
-
const
|
|
1173
|
+
const { exposed: customActions, rejected } = resolveApiCustomActions(objectDef, manifest, false);
|
|
1174
|
+
warnUnhostedActions(className, rejected);
|
|
1166
1175
|
const actionSpecs = [];
|
|
1167
1176
|
for (const [actionName, actionDef] of customActions) {
|
|
1168
1177
|
const routeConfig = resolveApiActionRouteConfig(actionName, actionDef, apiConfig, { kebabRoutes: options.kebabRoutes });
|
|
1169
|
-
|
|
1170
|
-
console.warn(`[smrt] Skipping ${className}.${actionName} - collection API routes require a static method`);
|
|
1171
|
-
continue;
|
|
1172
|
-
}
|
|
1178
|
+
warnDeclaredScopeMismatch(className, actionName, actionDef, apiConfig, routeConfig.scope);
|
|
1173
1179
|
const actionBaseDir = routeConfig.scope === "collection" ? routeDir : join(routeDir, "[id]");
|
|
1174
1180
|
actionSpecs.push({
|
|
1175
1181
|
routeDir: join(actionBaseDir, ...routeConfig.pathSegments),
|
|
@@ -1200,15 +1206,13 @@ async function generateCollectionRoutesForObject(projectRoot, className, objectD
|
|
|
1200
1206
|
const routeDir = join(projectRoot, options.routesDir, objectDef.collection);
|
|
1201
1207
|
const lookupClassName = findItemClassRegistryKey(className, objectDef, manifest);
|
|
1202
1208
|
const lookupObjectDef = findObjectDefByRegistryKey(manifest, lookupClassName);
|
|
1203
|
-
const
|
|
1209
|
+
const { exposed: customActions, rejected } = resolveApiCustomActions(objectDef, manifest, true);
|
|
1210
|
+
warnUnhostedActions(className, rejected);
|
|
1204
1211
|
if (customActions.length === 0) return generatedRoutePaths;
|
|
1205
1212
|
const actionSpecs = [];
|
|
1206
1213
|
for (const [actionName, actionDef] of customActions) {
|
|
1207
1214
|
const routeConfig = resolveApiActionRouteConfig(actionName, actionDef, apiConfig, { kebabRoutes: options.kebabRoutes }, "collection");
|
|
1208
|
-
|
|
1209
|
-
console.warn(`[smrt] Skipping ${className}.${actionName} - collection class methods only support collection-scoped API routes`);
|
|
1210
|
-
continue;
|
|
1211
|
-
}
|
|
1215
|
+
warnDeclaredScopeMismatch(className, actionName, actionDef, apiConfig, routeConfig.scope);
|
|
1212
1216
|
actionSpecs.push({
|
|
1213
1217
|
routeDir: join(routeDir, ...routeConfig.pathSegments),
|
|
1214
1218
|
spec: {
|
|
@@ -1246,49 +1250,103 @@ function resolveStandardCrudActions(apiConfig) {
|
|
|
1246
1250
|
return crud;
|
|
1247
1251
|
}
|
|
1248
1252
|
/**
|
|
1249
|
-
*
|
|
1253
|
+
* Partition an object's custom (non-CRUD) methods into the ones the API
|
|
1254
|
+
* exposes and the ones it withholds, with a reason for each rejection.
|
|
1250
1255
|
*
|
|
1251
|
-
*
|
|
1252
|
-
*
|
|
1253
|
-
*
|
|
1256
|
+
* The ONE place route generation, `resolveApiActionSet`, and the knowledge
|
|
1257
|
+
* artifact's API projection agree, by all three reading
|
|
1258
|
+
* {@link resolveApiMethodExposure}. Before #2686 each re-derived a subset and
|
|
1259
|
+
* could disagree — most damagingly, a gate applied only to the coherence
|
|
1260
|
+
* resolver would report a method unreachable while the emitter next door still
|
|
1261
|
+
* wrote its route file.
|
|
1254
1262
|
*/
|
|
1255
|
-
function
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
const
|
|
1262
|
-
|
|
1263
|
+
function resolveApiCustomActions(objectDef, manifest, objectIsCollectionClass, wireability = {}) {
|
|
1264
|
+
const apiConfig = objectDef.decoratorConfig?.api;
|
|
1265
|
+
const isModelClassName = wireability.isModelClassName ?? createManifestClassNamePredicate(manifest);
|
|
1266
|
+
const exposed = [];
|
|
1267
|
+
const rejected = [];
|
|
1268
|
+
for (const [name, method] of Object.entries(objectDef.methods || {})) {
|
|
1269
|
+
const decision = resolveApiMethodExposure({
|
|
1270
|
+
actionName: name,
|
|
1271
|
+
method,
|
|
1272
|
+
apiConfig,
|
|
1273
|
+
isCollectionClass: objectIsCollectionClass,
|
|
1274
|
+
...isModelClassName ? { isModelClassName } : {}
|
|
1275
|
+
});
|
|
1276
|
+
if (decision.exposed) {
|
|
1277
|
+
exposed.push([name, method]);
|
|
1278
|
+
continue;
|
|
1279
|
+
}
|
|
1280
|
+
if (decision.code === "crud-reserved" || decision.code === "not-public") continue;
|
|
1281
|
+
rejected.push([name, decision]);
|
|
1263
1282
|
}
|
|
1264
|
-
return
|
|
1283
|
+
return {
|
|
1284
|
+
exposed,
|
|
1285
|
+
rejected
|
|
1286
|
+
};
|
|
1287
|
+
}
|
|
1288
|
+
/**
|
|
1289
|
+
* Warn about the one rejection class that would be a structural failure rather
|
|
1290
|
+
* than a configuration choice: an action whose declared scope has no receiver
|
|
1291
|
+
* to bind. Both emitters carried this warning before #2686 moved the check into
|
|
1292
|
+
* the shared resolver, and the message text is preserved.
|
|
1293
|
+
*
|
|
1294
|
+
* It cannot currently fire — `resolveCustomActionMetadata` collapses a
|
|
1295
|
+
* contradicting scope back to the receiver-derived one, as it did before this
|
|
1296
|
+
* change; see `resolveActionReceiver` in `generators/custom-action.ts`. The
|
|
1297
|
+
* warning a developer actually sees for a contradicting declaration is
|
|
1298
|
+
* `warnDeclaredScopeMismatch` below.
|
|
1299
|
+
*
|
|
1300
|
+
* Every other rejection is silent here and reported with its reason through
|
|
1301
|
+
* the knowledge artifact instead, so a normal build is not buried in output
|
|
1302
|
+
* for the 2% of methods the heuristic legitimately withholds.
|
|
1303
|
+
*/
|
|
1304
|
+
function warnUnhostedActions(className, rejected) {
|
|
1305
|
+
for (const [actionName, decision] of rejected) {
|
|
1306
|
+
if (decision.code !== "no-receiver") continue;
|
|
1307
|
+
console.warn(`[smrt] Skipping ${className}.${actionName} - ${decision.reason}`);
|
|
1308
|
+
}
|
|
1309
|
+
}
|
|
1310
|
+
/**
|
|
1311
|
+
* Report a declared `scope` that contradicts the method's actual receiver.
|
|
1312
|
+
*
|
|
1313
|
+
* The declaration is honored only where it AGREES; nothing in config can move
|
|
1314
|
+
* an instance method onto the class. Warning is the whole remedy — the route
|
|
1315
|
+
* is still emitted at the receiver-derived URL, so an author who expected the
|
|
1316
|
+
* other one learns why it is missing instead of silently getting nothing at
|
|
1317
|
+
* either address (#2686).
|
|
1318
|
+
*/
|
|
1319
|
+
function warnDeclaredScopeMismatch(className, actionName, actionDef, apiConfig, effectiveScope) {
|
|
1320
|
+
const declared = resolveDeclaredScopeMismatch({
|
|
1321
|
+
actionName,
|
|
1322
|
+
method: actionDef,
|
|
1323
|
+
apiConfig,
|
|
1324
|
+
effectiveScope
|
|
1325
|
+
});
|
|
1326
|
+
if (!declared) return;
|
|
1327
|
+
console.warn(`[smrt] ${className}.${actionName} declares scope '${declared}' but its receiver is ${effectiveScope}-scoped, so the declared scope is ignored. A scope describes where a method already lives; it cannot move it. Make ${actionName} static to reach it on the collection, or drop the scope option.`);
|
|
1265
1328
|
}
|
|
1266
1329
|
/**
|
|
1267
1330
|
* Compute the set of action names (standard CRUD + custom methods) that the
|
|
1268
1331
|
* API exposes for a given object definition. This is the same resolution used
|
|
1269
1332
|
* to drive route generation, exposed so coherence checks (e.g. CLI vs API)
|
|
1270
1333
|
* can ask "what does the API expose?" without re-implementing the logic.
|
|
1334
|
+
*
|
|
1335
|
+
* Pass a class inventory: without one the wire-ability heuristic cannot tell a
|
|
1336
|
+
* model class from an options interface and therefore accepts both, so the
|
|
1337
|
+
* caller silently disagrees with the emitters on the LARGEST group of withheld
|
|
1338
|
+
* methods (see `WireabilityOptions.isModelClassName`). Supply either
|
|
1339
|
+
* `manifest`, or `wireability.isModelClassName` when the caller's inventory is
|
|
1340
|
+
* the live registry rather than a manifest — `@happyvertical/smrt-users`' CLI
|
|
1341
|
+
* resource listing is the second kind. Both stay optional only because this is
|
|
1342
|
+
* public API.
|
|
1271
1343
|
*/
|
|
1272
|
-
function resolveApiActionSet(objectDef, manifest) {
|
|
1344
|
+
function resolveApiActionSet(objectDef, manifest, wireability = {}) {
|
|
1273
1345
|
const apiConfig = objectDef.decoratorConfig?.api;
|
|
1274
1346
|
if (apiConfig === false) return /* @__PURE__ */ new Set();
|
|
1275
1347
|
const objectIsCollectionClass = manifest ? isCollectionManifestClass(manifest, objectDef) : isCollectionClass(objectDef);
|
|
1276
1348
|
const actions = objectIsCollectionClass ? /* @__PURE__ */ new Set() : new Set(resolveStandardCrudActions(apiConfig));
|
|
1277
|
-
for (const [name
|
|
1278
|
-
if (isCrudOperation(name)) continue;
|
|
1279
|
-
if (!method.isPublic) continue;
|
|
1280
|
-
if (!shouldIncludeInApi(name, apiConfig)) continue;
|
|
1281
|
-
const scope = resolveCustomActionMetadata({
|
|
1282
|
-
actionName: name,
|
|
1283
|
-
method,
|
|
1284
|
-
apiConfig,
|
|
1285
|
-
defaultScope: objectIsCollectionClass ? "collection" : method.isStatic ? "collection" : "item"
|
|
1286
|
-
}).scope;
|
|
1287
|
-
if (objectIsCollectionClass) {
|
|
1288
|
-
if (scope !== "collection") continue;
|
|
1289
|
-
} else if (scope === "collection" && !method.isStatic) continue;
|
|
1290
|
-
actions.add(name);
|
|
1291
|
-
}
|
|
1349
|
+
for (const [name] of resolveApiCustomActions(objectDef, manifest, objectIsCollectionClass, wireability).exposed) actions.add(name);
|
|
1292
1350
|
return actions;
|
|
1293
1351
|
}
|
|
1294
1352
|
/**
|
|
@@ -1399,7 +1457,7 @@ function validateCliIncludeAgainstApi(manifest) {
|
|
|
1399
1457
|
return typeof cliConfig === "object" && cliConfig !== null && Array.isArray(cliConfig.include) && cliConfig.include.length > 0;
|
|
1400
1458
|
});
|
|
1401
1459
|
if (violations.length === 0) return;
|
|
1402
|
-
const messages = violations.flatMap(({ className, unreachable }) => unreachable.map((action) => `[smrt] ${className}.${action} is exposed as a CLI command but is not exposed via the api.\n Either:\n - Add '${action}' to api.include, or\n - Remove '${action}' from cli.include / add it to cli.exclude.\n The CLI invokes methods over HTTP; methods without API routes are unreachable.\n If this CLI is intentionally invoked in-process (no HTTP), set\n \`cli: { skipApiCheck: true }\` on the @smrt() decorator to acknowledge.`));
|
|
1460
|
+
const messages = violations.flatMap(({ className, unreachable }) => unreachable.map((action) => `[smrt] ${className}.${action} is exposed as a CLI command but is not exposed via the api.\n Either:\n - Decorate '${action}' with @method({ expose: true }) to route it, or\n - Add '${action}' to api.include, or\n - Remove '${action}' from cli.include / add it to cli.exclude.\n The CLI invokes methods over HTTP; methods without API routes are unreachable.\n A public method is routed by default only when every parameter can be\n built from JSON; @method({ expose: true }) overrides that for one method\n without widening api.include. See withheldSurfaces in the knowledge\n artifact for the reason this one was withheld (#2686).\n If this CLI is intentionally invoked in-process (no HTTP), set\n \`cli: { skipApiCheck: true }\` on the @smrt() decorator to acknowledge.`));
|
|
1403
1461
|
throw new Error(messages.join("\n\n"));
|
|
1404
1462
|
}
|
|
1405
1463
|
/**
|
|
@@ -1687,9 +1745,21 @@ function generateActionRouteTemplate(projectRoot, routeDir, routeSpecs, objectDe
|
|
|
1687
1745
|
const hostModelType = resolveObjectTypeReference(projectRoot, firstSpec.hostClassName, objectDef, options, routeDir);
|
|
1688
1746
|
const typeImports = mergeImportStatements([lookupModelType.importStatement, hostModelType.importStatement]);
|
|
1689
1747
|
if (routeSpecs.some((spec) => spec.hostType !== hostType || spec.lookupClassName !== lookupClassName || spec.routeConfig.scope !== routeConfig.scope)) throw new Error(`Cannot generate mixed custom route handlers for ${lookupClassName}. All handlers sharing a route path must target the same host type and scope.`);
|
|
1748
|
+
const decoderImports = /* @__PURE__ */ new Set();
|
|
1749
|
+
for (const spec of routeSpecs) {
|
|
1750
|
+
if (hasSingleOptionsParameter(spec.actionDef)) continue;
|
|
1751
|
+
for (const parameter of spec.actionDef.parameters ?? []) {
|
|
1752
|
+
const decoder = spec.routeConfig?.method === "GET" ? queryStringDecoderFor(parameter.type) : declaredTypeAcceptsDate(parameter.type) ? "toCustomActionDate" : void 0;
|
|
1753
|
+
if (decoder) decoderImports.add(decoder);
|
|
1754
|
+
}
|
|
1755
|
+
}
|
|
1690
1756
|
const importBlock = [
|
|
1691
1757
|
"import { error, json } from '@sveltejs/kit';",
|
|
1692
|
-
|
|
1758
|
+
`import { ${[
|
|
1759
|
+
"normalizeCustomActionFailure",
|
|
1760
|
+
"normalizeTypedHttpError",
|
|
1761
|
+
...[...decoderImports].sort()
|
|
1762
|
+
].join(", ")} } from '@happyvertical/smrt-core';`,
|
|
1693
1763
|
hostType === "collection" || routeConfig.scope !== "collection" ? "import { getCollection } from '$lib/server/smrt';" : "import { ObjectRegistry } from '@happyvertical/smrt-core';",
|
|
1694
1764
|
typeImports,
|
|
1695
1765
|
"import type { RequestHandler } from './$types';"
|
|
@@ -1719,7 +1789,7 @@ function generateActionRouteHandler(lookupClassName, actionName, actionDef, rout
|
|
|
1719
1789
|
const receiverExpression = actionDef.isStatic ? "CollectionClass" : "typedCollection";
|
|
1720
1790
|
const staticTargetLoad = actionDef.isStatic ? ` const CollectionClass = typedCollection.constructor as typeof ${hostTypeName};\n` : "";
|
|
1721
1791
|
const scopedOptions = buildScopedOptionsForTenantRead(actionDef, routeConfig, tenantScoped);
|
|
1722
|
-
const invocationArgs = buildActionInvocationArgs(actionDef, scopedOptions.optionsIdentifier);
|
|
1792
|
+
const invocationArgs = buildActionInvocationArgs(actionDef, scopedOptions.optionsIdentifier, routeConfig.method);
|
|
1723
1793
|
return `// Custom collection method: ${actionName}
|
|
1724
1794
|
export const ${handlerName}: RequestHandler = async (${collectionHandlerArgs}) => {
|
|
1725
1795
|
${authGuardLine}
|
|
@@ -1751,7 +1821,7 @@ ${optionsLoad}${scopedOptions.source} let result: unknown;
|
|
|
1751
1821
|
if (routeConfig.scope === "collection") {
|
|
1752
1822
|
const optionsLoad = buildActionOptionsLoad(actionName, actionDef, routeConfig, hostTypeName, true);
|
|
1753
1823
|
const scopedOptions = buildScopedOptionsForTenantRead(actionDef, routeConfig, tenantScoped);
|
|
1754
|
-
const invocationArgs = buildActionInvocationArgs(actionDef, scopedOptions.optionsIdentifier);
|
|
1824
|
+
const invocationArgs = buildActionInvocationArgs(actionDef, scopedOptions.optionsIdentifier, routeConfig.method);
|
|
1755
1825
|
return `// Custom collection action: ${actionName}
|
|
1756
1826
|
export const ${handlerName}: RequestHandler = async (${collectionHandlerArgs}) => {
|
|
1757
1827
|
${authGuardLine}
|
|
@@ -1784,7 +1854,7 @@ ${optionsLoad}${scopedOptions.source} const ClassRef = registered.constructor a
|
|
|
1784
1854
|
const item = await collection.get(
|
|
1785
1855
|
readScope ? { id: params.id, ...readScope } : params.id,
|
|
1786
1856
|
);` : " const item = await collection.get(params.id);";
|
|
1787
|
-
const invocationArgs = buildActionInvocationArgs(actionDef);
|
|
1857
|
+
const invocationArgs = buildActionInvocationArgs(actionDef, "options", routeConfig.method);
|
|
1788
1858
|
return `// Custom action: ${actionName}
|
|
1789
1859
|
export const ${handlerName}: RequestHandler = async (${itemHandlerArgs}) => {
|
|
1790
1860
|
${authGuardLine}
|
|
@@ -1992,6 +2062,6 @@ function updateGeneratedRouteIgnoreBlock(gitignoreContent, generatedPaths) {
|
|
|
1992
2062
|
return `${updatedContent}${managedBlock.join("\n")}\n`;
|
|
1993
2063
|
}
|
|
1994
2064
|
//#endregion
|
|
1995
|
-
export { findCliApiCoherenceViolations, generateSvelteKitRoutes, methodNameToKebab, resolveApiActionRouteConfig, resolveApiActionSet, validateCliIncludeAgainstApi };
|
|
2065
|
+
export { findCliApiCoherenceViolations, generateSvelteKitRoutes, methodNameToKebab, resolveApiActionRouteConfig, resolveApiActionSet, resolveApiCustomActions, validateCliIncludeAgainstApi };
|
|
1996
2066
|
|
|
1997
2067
|
//# sourceMappingURL=sveltekit-generator.js.map
|