@happyvertical/smrt-core 0.53.4 → 0.53.6
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 +4 -0
- package/README.md +11 -0
- package/agents/build-knowledge.md +7 -0
- package/agents/generators.md +24 -1
- package/dist/generated-collection-access.d.ts +43 -0
- package/dist/generated-collection-access.d.ts.map +1 -0
- package/dist/generated-collection-access.js +71 -0
- package/dist/generated-collection-access.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/manifest/static-manifest.js +1 -1
- package/dist/manifest/static-manifest.js.map +1 -1
- package/dist/manifest/store.js +1 -1
- package/dist/manifest.json +1 -1
- package/dist/scanner/manifest-generator.d.ts.map +1 -1
- package/dist/scanner/manifest-generator.js +3 -1
- package/dist/scanner/manifest-generator.js.map +1 -1
- package/dist/smrt-knowledge.json +9 -9
- package/dist/utils/qualified-names.d.ts +15 -0
- package/dist/utils/qualified-names.d.ts.map +1 -1
- package/dist/utils/qualified-names.js +31 -1
- package/dist/utils/qualified-names.js.map +1 -1
- package/dist/vite-plugin/changes-route.d.ts +4 -3
- package/dist/vite-plugin/changes-route.d.ts.map +1 -1
- package/dist/vite-plugin/changes-route.js +8 -7
- package/dist/vite-plugin/changes-route.js.map +1 -1
- package/dist/vite-plugin/dev-plane-route.d.ts.map +1 -1
- package/dist/vite-plugin/dev-plane-route.js +4 -4
- package/dist/vite-plugin/dev-plane-route.js.map +1 -1
- package/dist/vite-plugin/events-route.d.ts.map +1 -1
- package/dist/vite-plugin/events-route.js +4 -4
- package/dist/vite-plugin/events-route.js.map +1 -1
- package/dist/vite-plugin/index.d.ts.map +1 -1
- package/dist/vite-plugin/index.js +13 -1
- package/dist/vite-plugin/index.js.map +1 -1
- package/dist/vite-plugin/resources-route.d.ts.map +1 -1
- package/dist/vite-plugin/resources-route.js +9 -4
- package/dist/vite-plugin/resources-route.js.map +1 -1
- package/dist/vite-plugin/sveltekit-config-import.d.ts +22 -0
- package/dist/vite-plugin/sveltekit-config-import.d.ts.map +1 -1
- package/dist/vite-plugin/sveltekit-config-import.js +44 -2
- package/dist/vite-plugin/sveltekit-config-import.js.map +1 -1
- package/dist/vite-plugin/sveltekit-generator.d.ts.map +1 -1
- package/dist/vite-plugin/sveltekit-generator.js +59 -9
- package/dist/vite-plugin/sveltekit-generator.js.map +1 -1
- package/dist/vite-plugin/sveltekit-register-injection.d.ts +26 -0
- package/dist/vite-plugin/sveltekit-register-injection.d.ts.map +1 -0
- package/dist/vite-plugin/sveltekit-register-injection.js +37 -0
- package/dist/vite-plugin/sveltekit-register-injection.js.map +1 -0
- package/dist/vite-plugin/sync-apply-route.d.ts +1 -1
- package/dist/vite-plugin/sync-apply-route.d.ts.map +1 -1
- package/dist/vite-plugin/sync-apply-route.js +4 -4
- package/dist/vite-plugin/sync-apply-route.js.map +1 -1
- package/package.json +10 -10
|
@@ -144,11 +144,14 @@ function generateResourcesRoute(projectRoot, options) {
|
|
|
144
144
|
return false;
|
|
145
145
|
}
|
|
146
146
|
if (!existsSync(routeDir)) mkdirSync(routeDir, { recursive: true });
|
|
147
|
-
writeFileSync(filePath, generateResourcesRouteTemplate(resolveSvelteKitConfigImport(projectRoot, routeDir, options),
|
|
147
|
+
writeFileSync(filePath, generateResourcesRouteTemplate(resolveSvelteKitConfigImport(projectRoot, routeDir, options), resolveSvelteKitConfigImport(projectRoot, routeDir, {
|
|
148
|
+
configPath: options.configPath,
|
|
149
|
+
configFileName: "smrt-register.ts"
|
|
150
|
+
}), options), "utf-8");
|
|
148
151
|
console.log(`[smrt] Generated: ${filePath}`);
|
|
149
152
|
return true;
|
|
150
153
|
}
|
|
151
|
-
function generateResourcesRouteTemplate(configImport, options) {
|
|
154
|
+
function generateResourcesRouteTemplate(configImport, registerImport, options) {
|
|
152
155
|
return `${AUTO_GENERATED_ROUTE_HEADER}
|
|
153
156
|
// DO NOT EDIT - changes will be overwritten
|
|
154
157
|
//
|
|
@@ -160,12 +163,14 @@ function generateResourcesRouteTemplate(configImport, options) {
|
|
|
160
163
|
|
|
161
164
|
import { createResourceListHandler } from '@happyvertical/smrt-users/sveltekit';
|
|
162
165
|
// Side effect: registers @smrt() classes in ObjectRegistry before the
|
|
163
|
-
// handler walks it (
|
|
164
|
-
//
|
|
166
|
+
// handler walks it (the generated registration, then the app's SMRT config
|
|
167
|
+
// module, as the CRUD/changes/events routes import them).
|
|
168
|
+
import '${registerImport}';
|
|
165
169
|
import '${configImport}';
|
|
166
170
|
|
|
167
171
|
export const GET = createResourceListHandler({
|
|
168
172
|
ensureRegistry: async () => {
|
|
173
|
+
await import('${registerImport}');
|
|
169
174
|
await import('${configImport}');
|
|
170
175
|
},${options.kebabRoutes ? "\n kebabRoutes: true," : ""}
|
|
171
176
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resources-route.js","names":[],"sources":["../../src/vite-plugin/resources-route.ts"],"sourcesContent":["/**\n * SvelteKit `_resources` route generation — CLI discovery endpoint (#2663;\n * parent epic #2655).\n *\n * Emits `{routesDir}/_resources/+server.ts`: `GET /api/_resources`, the\n * endpoint the distributable CLI (`@happyvertical/smrt-app-cli`) reads to\n * learn which resources and commands it can invoke. Every other generated\n * route lives in `sveltekit-generator.ts` or a sibling emitter; this one is\n * kept in its own module for the same reason `changes-route.ts` and\n * `events-route.ts` are — a one-line registration hook in the shared\n * generator file.\n *\n * ## The dependency constraint\n *\n * The handler this route delegates to, `createResourceListHandler`, lives in\n * `@happyvertical/smrt-users` — and `smrt-users` depends on `smrt-core`, not\n * the reverse, so core cannot import it directly. That is not a problem for\n * *emitting* the import: the generated file is written into the consumer's\n * own `src/routes/`, where `@happyvertical/smrt-users` resolves through the\n * consumer's own dependency graph, exactly like the `@happyvertical/smrt-tenancy`\n * import `sveltekit-generator.ts`'s `generateTenantContextHelper` already\n * emits into tenant-scoped routes (see the comment above that function). The\n * only question is *when* it is safe to emit — a consumer that never took a\n * dependency on `smrt-users` must never receive a route whose import cannot\n * resolve, or a working build turns red.\n *\n * ## Detection mechanism\n *\n * Unlike the tenancy guard — which reads a semantic signal already present in\n * the manifest (whether any object is `@TenantScoped`, which itself implies\n * the app depends on `smrt-tenancy`) — nothing in the manifest indicates\n * whether a consumer has taken on `smrt-users`. Objects don't declare an\n * auth dependency; the app does, at the package level.\n *\n * So this route uses a **resolvable-dependency check**: does the exact\n * subpath the generated file imports — `@happyvertical/smrt-users/sveltekit`\n * — resolve from the consumer's `projectRoot`, via a `createRequire` rooted\n * at the consumer's own `package.json`? That is stronger than reading\n * `package.json`'s `dependencies` block (which can list a package that was\n * never installed) and, unlike a single hardcoded\n * `node_modules/@happyvertical/smrt-users/package.json` path, it uses\n * Node's real module resolution — so it also finds the package when a\n * workspace hoists shared dependencies to an ancestor `node_modules` (npm/\n * yarn workspaces, or pnpm with `node-linker=hoisted`) rather than\n * installing them directly under the consumer's own `projectRoot`.\n * Resolving the `/sveltekit` subpath specifically, rather than the\n * package's bare `package.json`, matters too: `smrt-users`'s `exports` map\n * does not list `./package.json`, so resolving that path would throw\n * `ERR_PACKAGE_PATH_NOT_EXPORTED` even when the package is genuinely\n * installed — resolving the subpath the route actually imports sidesteps\n * that and checks precisely the thing that must succeed at build time.\n *\n * An explicit `sveltekit: { resourcesRoute: { enabled: false } }` escape\n * hatch is also available, matching `changesRoute`/`eventsRoute`, for a\n * consumer that has `smrt-users` installed but wants to keep hand-writing\n * (or omit) `_resources`.\n *\n * ## Preserving a hand-written route\n *\n * Every consumer today hand-writes this route (the reference implementation\n * in the issue). `clearGeneratedRouteFiles` (in `sveltekit-generator.ts`)\n * already only deletes `+server.ts` files that start with\n * {@link AUTO_GENERATED_ROUTE_HEADER}, so a hand-written `_resources` route —\n * which never carries that header — survives the pre-generation sweep\n * untouched. This emitter additionally checks `existsSync` on the target\n * path before writing: by the time it runs, anything still there is\n * necessarily hand-written (a generator-owned copy would already have been\n * swept), so its mere presence is sufficient to skip generation and leave it\n * alone.\n *\n * Once a consumer's `_resources` route IS generator-owned (no hand-written\n * file present, `smrt-users` resolvable), its path is generator-owned for\n * `.gitignore` purposes too — it is included in `generatedRoutePaths` like\n * any other emitted route, so `updateGitignore` puts it in the managed\n * block. A project that migrated from a hand-written route to a fully\n * generated one may still carry a stale `# Application-owned rule` comment\n * above the same literal path from before the migration; `updateGitignore`\n * only ever touches its own managed block, so that stale comment is left as\n * project history for the consumer to clean up — the same way any other\n * manual `.gitignore` edit outside the managed block is preserved.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport { join } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { AUTO_GENERATED_ROUTE_HEADER } from './route-header.js';\nimport { resolveSvelteKitConfigImport } from './sveltekit-config-import.js';\nimport type { SvelteKitOptions } from './sveltekit-generator.js';\n\n/**\n * Whether `@happyvertical/smrt-users/sveltekit` — the exact subpath the\n * generated route imports — is resolvable from the consumer at\n * `projectRoot`. See the module doc for why this check (rather than reading\n * `package.json`'s declared `dependencies`, or checking one hardcoded\n * physical path) is the chosen signal.\n */\nexport function consumerHasSmrtUsers(projectRoot: string): boolean {\n try {\n const consumerRequire = createRequire(\n pathToFileURL(join(projectRoot, 'package.json')).href,\n );\n consumerRequire.resolve('@happyvertical/smrt-users/sveltekit');\n return true;\n } catch {\n return false;\n }\n}\n\n/** Whether this invocation will own the `_resources` output file. */\nexport function willGenerateResourcesRoute(\n projectRoot: string,\n options: SvelteKitOptions,\n): boolean {\n if (\n options.resourcesRoute?.enabled === false ||\n !consumerHasSmrtUsers(projectRoot)\n ) {\n return false;\n }\n const routeDir = join(projectRoot, options.routesDir, '_resources');\n for (const name of ['+server.ts', '+server.js']) {\n const file = join(routeDir, name);\n if (!existsSync(file)) continue;\n if (!readFileSync(file, 'utf-8').startsWith(AUTO_GENERATED_ROUTE_HEADER)) {\n return false;\n }\n }\n return true;\n}\n\n/** Whether `_resources` is occupied by its generated utility or a preserved\n * handwritten SvelteKit server module. This is used only by route collision\n * preflight: the emitter remains file-aware and never overwrites handwriting. */\nexport function reservesResourcesRoute(\n projectRoot: string,\n options: SvelteKitOptions,\n): boolean {\n if (willGenerateResourcesRoute(projectRoot, options)) return true;\n const routeDir = join(projectRoot, options.routesDir, '_resources');\n return ['+server.ts', '+server.js'].some((name) => {\n const file = join(routeDir, name);\n return (\n existsSync(file) &&\n !readFileSync(file, 'utf-8').startsWith(AUTO_GENERATED_ROUTE_HEADER)\n );\n });\n}\n\n/**\n * Generate the `_resources/+server.ts` route. Returns true when a route was\n * written. Disabled with `sveltekit: { resourcesRoute: { enabled: false } }`;\n * skipped (with a log line) when `@happyvertical/smrt-users` is not\n * resolvable from the consumer, or when a hand-written route already\n * occupies the path.\n */\nexport function generateResourcesRoute(\n projectRoot: string,\n options: SvelteKitOptions,\n): boolean {\n if (options.resourcesRoute?.enabled === false) {\n return false;\n }\n\n if (!consumerHasSmrtUsers(projectRoot)) {\n console.log(\n '[smrt] Skipping _resources route - @happyvertical/smrt-users is not ' +\n 'resolvable; createResourceListHandler would not resolve in the ' +\n 'consumer build',\n );\n return false;\n }\n\n const routeDir = join(projectRoot, options.routesDir, '_resources');\n const filePath = join(routeDir, '+server.ts');\n\n // By this point in generation, clearGeneratedRouteFiles has already swept\n // any previously generator-owned copy at this path — anything still here\n // is necessarily hand-written. Preserve it rather than clobbering a\n // consumer's customized discovery route. Check every server-module\n // extension SvelteKit resolves by default (`.js` and `.ts` — see\n // https://svelte.dev/docs/kit/configuration#moduleExtensions), not only\n // `.ts`: a hand-written `+server.js` is invisible to a `.ts`-only check,\n // so the generator would write `+server.ts` alongside it and SvelteKit\n // would then refuse the route with \"Multiple endpoint files found\".\n const existingServerFile = ['+server.ts', '+server.js'].find((name) =>\n existsSync(join(routeDir, name)),\n );\n if (existingServerFile) {\n console.log(\n `[smrt] Preserving hand-written _resources route (${existingServerFile}, not generator-owned)`,\n );\n return false;\n }\n\n if (!existsSync(routeDir)) {\n mkdirSync(routeDir, { recursive: true });\n }\n writeFileSync(\n filePath,\n generateResourcesRouteTemplate(\n resolveSvelteKitConfigImport(projectRoot, routeDir, options),\n options,\n ),\n 'utf-8',\n );\n console.log(`[smrt] Generated: ${filePath}`);\n return true;\n}\n\nfunction generateResourcesRouteTemplate(\n configImport: string,\n options: SvelteKitOptions,\n): string {\n const kebabRoutesOption = options.kebabRoutes ? '\\n kebabRoutes: true,' : '';\n\n return `${AUTO_GENERATED_ROUTE_HEADER}\n// DO NOT EDIT - changes will be overwritten\n//\n// GET /api/_resources — CLI discovery endpoint (#2663). Returns the auth-aware\n// list of resources and commands the distributable CLI\n// (@happyvertical/smrt-app-cli) can invoke, derived from ObjectRegistry by\n// createResourceListHandler. Subsumes the route every consumer previously\n// hand-wrote (see the issue for the reference implementation this replaces).\n\nimport { createResourceListHandler } from '@happyvertical/smrt-users/sveltekit';\n// Side effect: registers @smrt() classes in ObjectRegistry before the\n// handler walks it (mirrors the generated CRUD/changes/events routes'\n// configured SMRT config import).\nimport '${configImport}';\n\nexport const GET = createResourceListHandler({\n ensureRegistry: async () => {\n await import('${configImport}');\n },${kebabRoutesOption}\n});\n`;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiGA,SAAgB,qBAAqB,aAA8B;CACjE,IAAI;EAIF,cAFE,cAAc,KAAK,aAAa,cAAc,CAAC,CAAC,CAAC,IAEnD,CAAA,CAAgB,QAAQ,qCAAqC;EAC7D,OAAO;CACT,QAAQ;EACN,OAAO;CACT;AACF;;AAGA,SAAgB,2BACd,aACA,SACS;CACT,IACE,QAAQ,gBAAgB,YAAY,SACpC,CAAC,qBAAqB,WAAW,GAEjC,OAAO;CAET,MAAM,WAAW,KAAK,aAAa,QAAQ,WAAW,YAAY;CAClE,KAAK,MAAM,QAAQ,CAAC,cAAc,YAAY,GAAG;EAC/C,MAAM,OAAO,KAAK,UAAU,IAAI;EAChC,IAAI,CAAC,WAAW,IAAI,GAAG;EACvB,IAAI,CAAC,aAAa,MAAM,OAAO,CAAC,CAAC,WAAA,6CAAsC,GACrE,OAAO;CAEX;CACA,OAAO;AACT;;;;AAKA,SAAgB,uBACd,aACA,SACS;CACT,IAAI,2BAA2B,aAAa,OAAO,GAAG,OAAO;CAC7D,MAAM,WAAW,KAAK,aAAa,QAAQ,WAAW,YAAY;CAClE,OAAO,CAAC,cAAc,YAAY,CAAC,CAAC,MAAM,SAAS;EACjD,MAAM,OAAO,KAAK,UAAU,IAAI;EAChC,OACE,WAAW,IAAI,KACf,CAAC,aAAa,MAAM,OAAO,CAAC,CAAC,WAAA,6CAAsC;CAEvE,CAAC;AACH;;;;;;;;AASA,SAAgB,uBACd,aACA,SACS;CACT,IAAI,QAAQ,gBAAgB,YAAY,OACtC,OAAO;CAGT,IAAI,CAAC,qBAAqB,WAAW,GAAG;EACtC,QAAQ,IACN,mJAGF;EACA,OAAO;CACT;CAEA,MAAM,WAAW,KAAK,aAAa,QAAQ,WAAW,YAAY;CAClE,MAAM,WAAW,KAAK,UAAU,YAAY;CAW5C,MAAM,qBAAqB,CAAC,cAAc,YAAY,CAAC,CAAC,MAAM,SAC5D,WAAW,KAAK,UAAU,IAAI,CAAC,CACjC;CACA,IAAI,oBAAoB;EACtB,QAAQ,IACN,oDAAoD,mBAAmB,uBACzE;EACA,OAAO;CACT;CAEA,IAAI,CAAC,WAAW,QAAQ,GACtB,UAAU,UAAU,EAAE,WAAW,KAAK,CAAC;CAEzC,cACE,UACA,+BACE,6BAA6B,aAAa,UAAU,OAAO,GAC3D,OACF,GACA,OACF;CACA,QAAQ,IAAI,qBAAqB,UAAU;CAC3C,OAAO;AACT;AAEA,SAAS,+BACP,cACA,SACQ;CAGR,OAAO,GAAG,4BAA4B;;;;;;;;;;;;;UAa9B,aAAa;;;;oBAIH,aAAa;MAnBL,QAAQ,cAAc,2BAA2B,GAoBrD;;;AAGxB"}
|
|
1
|
+
{"version":3,"file":"resources-route.js","names":[],"sources":["../../src/vite-plugin/resources-route.ts"],"sourcesContent":["/**\n * SvelteKit `_resources` route generation — CLI discovery endpoint (#2663;\n * parent epic #2655).\n *\n * Emits `{routesDir}/_resources/+server.ts`: `GET /api/_resources`, the\n * endpoint the distributable CLI (`@happyvertical/smrt-app-cli`) reads to\n * learn which resources and commands it can invoke. Every other generated\n * route lives in `sveltekit-generator.ts` or a sibling emitter; this one is\n * kept in its own module for the same reason `changes-route.ts` and\n * `events-route.ts` are — a one-line registration hook in the shared\n * generator file.\n *\n * ## The dependency constraint\n *\n * The handler this route delegates to, `createResourceListHandler`, lives in\n * `@happyvertical/smrt-users` — and `smrt-users` depends on `smrt-core`, not\n * the reverse, so core cannot import it directly. That is not a problem for\n * *emitting* the import: the generated file is written into the consumer's\n * own `src/routes/`, where `@happyvertical/smrt-users` resolves through the\n * consumer's own dependency graph, exactly like the `@happyvertical/smrt-tenancy`\n * import `sveltekit-generator.ts`'s `generateTenantContextHelper` already\n * emits into tenant-scoped routes (see the comment above that function). The\n * only question is *when* it is safe to emit — a consumer that never took a\n * dependency on `smrt-users` must never receive a route whose import cannot\n * resolve, or a working build turns red.\n *\n * ## Detection mechanism\n *\n * Unlike the tenancy guard — which reads a semantic signal already present in\n * the manifest (whether any object is `@TenantScoped`, which itself implies\n * the app depends on `smrt-tenancy`) — nothing in the manifest indicates\n * whether a consumer has taken on `smrt-users`. Objects don't declare an\n * auth dependency; the app does, at the package level.\n *\n * So this route uses a **resolvable-dependency check**: does the exact\n * subpath the generated file imports — `@happyvertical/smrt-users/sveltekit`\n * — resolve from the consumer's `projectRoot`, via a `createRequire` rooted\n * at the consumer's own `package.json`? That is stronger than reading\n * `package.json`'s `dependencies` block (which can list a package that was\n * never installed) and, unlike a single hardcoded\n * `node_modules/@happyvertical/smrt-users/package.json` path, it uses\n * Node's real module resolution — so it also finds the package when a\n * workspace hoists shared dependencies to an ancestor `node_modules` (npm/\n * yarn workspaces, or pnpm with `node-linker=hoisted`) rather than\n * installing them directly under the consumer's own `projectRoot`.\n * Resolving the `/sveltekit` subpath specifically, rather than the\n * package's bare `package.json`, matters too: `smrt-users`'s `exports` map\n * does not list `./package.json`, so resolving that path would throw\n * `ERR_PACKAGE_PATH_NOT_EXPORTED` even when the package is genuinely\n * installed — resolving the subpath the route actually imports sidesteps\n * that and checks precisely the thing that must succeed at build time.\n *\n * An explicit `sveltekit: { resourcesRoute: { enabled: false } }` escape\n * hatch is also available, matching `changesRoute`/`eventsRoute`, for a\n * consumer that has `smrt-users` installed but wants to keep hand-writing\n * (or omit) `_resources`.\n *\n * ## Preserving a hand-written route\n *\n * Every consumer today hand-writes this route (the reference implementation\n * in the issue). `clearGeneratedRouteFiles` (in `sveltekit-generator.ts`)\n * already only deletes `+server.ts` files that start with\n * {@link AUTO_GENERATED_ROUTE_HEADER}, so a hand-written `_resources` route —\n * which never carries that header — survives the pre-generation sweep\n * untouched. This emitter additionally checks `existsSync` on the target\n * path before writing: by the time it runs, anything still there is\n * necessarily hand-written (a generator-owned copy would already have been\n * swept), so its mere presence is sufficient to skip generation and leave it\n * alone.\n *\n * Once a consumer's `_resources` route IS generator-owned (no hand-written\n * file present, `smrt-users` resolvable), its path is generator-owned for\n * `.gitignore` purposes too — it is included in `generatedRoutePaths` like\n * any other emitted route, so `updateGitignore` puts it in the managed\n * block. A project that migrated from a hand-written route to a fully\n * generated one may still carry a stale `# Application-owned rule` comment\n * above the same literal path from before the migration; `updateGitignore`\n * only ever touches its own managed block, so that stale comment is left as\n * project history for the consumer to clean up — the same way any other\n * manual `.gitignore` edit outside the managed block is preserved.\n */\n\nimport { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';\nimport { createRequire } from 'node:module';\nimport { join } from 'node:path';\nimport { pathToFileURL } from 'node:url';\nimport { AUTO_GENERATED_ROUTE_HEADER } from './route-header.js';\nimport { resolveSvelteKitConfigImport } from './sveltekit-config-import.js';\nimport type { SvelteKitOptions } from './sveltekit-generator.js';\n\n/**\n * Whether `@happyvertical/smrt-users/sveltekit` — the exact subpath the\n * generated route imports — is resolvable from the consumer at\n * `projectRoot`. See the module doc for why this check (rather than reading\n * `package.json`'s declared `dependencies`, or checking one hardcoded\n * physical path) is the chosen signal.\n */\nexport function consumerHasSmrtUsers(projectRoot: string): boolean {\n try {\n const consumerRequire = createRequire(\n pathToFileURL(join(projectRoot, 'package.json')).href,\n );\n consumerRequire.resolve('@happyvertical/smrt-users/sveltekit');\n return true;\n } catch {\n return false;\n }\n}\n\n/** Whether this invocation will own the `_resources` output file. */\nexport function willGenerateResourcesRoute(\n projectRoot: string,\n options: SvelteKitOptions,\n): boolean {\n if (\n options.resourcesRoute?.enabled === false ||\n !consumerHasSmrtUsers(projectRoot)\n ) {\n return false;\n }\n const routeDir = join(projectRoot, options.routesDir, '_resources');\n for (const name of ['+server.ts', '+server.js']) {\n const file = join(routeDir, name);\n if (!existsSync(file)) continue;\n if (!readFileSync(file, 'utf-8').startsWith(AUTO_GENERATED_ROUTE_HEADER)) {\n return false;\n }\n }\n return true;\n}\n\n/** Whether `_resources` is occupied by its generated utility or a preserved\n * handwritten SvelteKit server module. This is used only by route collision\n * preflight: the emitter remains file-aware and never overwrites handwriting. */\nexport function reservesResourcesRoute(\n projectRoot: string,\n options: SvelteKitOptions,\n): boolean {\n if (willGenerateResourcesRoute(projectRoot, options)) return true;\n const routeDir = join(projectRoot, options.routesDir, '_resources');\n return ['+server.ts', '+server.js'].some((name) => {\n const file = join(routeDir, name);\n return (\n existsSync(file) &&\n !readFileSync(file, 'utf-8').startsWith(AUTO_GENERATED_ROUTE_HEADER)\n );\n });\n}\n\n/**\n * Generate the `_resources/+server.ts` route. Returns true when a route was\n * written. Disabled with `sveltekit: { resourcesRoute: { enabled: false } }`;\n * skipped (with a log line) when `@happyvertical/smrt-users` is not\n * resolvable from the consumer, or when a hand-written route already\n * occupies the path.\n */\nexport function generateResourcesRoute(\n projectRoot: string,\n options: SvelteKitOptions,\n): boolean {\n if (options.resourcesRoute?.enabled === false) {\n return false;\n }\n\n if (!consumerHasSmrtUsers(projectRoot)) {\n console.log(\n '[smrt] Skipping _resources route - @happyvertical/smrt-users is not ' +\n 'resolvable; createResourceListHandler would not resolve in the ' +\n 'consumer build',\n );\n return false;\n }\n\n const routeDir = join(projectRoot, options.routesDir, '_resources');\n const filePath = join(routeDir, '+server.ts');\n\n // By this point in generation, clearGeneratedRouteFiles has already swept\n // any previously generator-owned copy at this path — anything still here\n // is necessarily hand-written. Preserve it rather than clobbering a\n // consumer's customized discovery route. Check every server-module\n // extension SvelteKit resolves by default (`.js` and `.ts` — see\n // https://svelte.dev/docs/kit/configuration#moduleExtensions), not only\n // `.ts`: a hand-written `+server.js` is invisible to a `.ts`-only check,\n // so the generator would write `+server.ts` alongside it and SvelteKit\n // would then refuse the route with \"Multiple endpoint files found\".\n const existingServerFile = ['+server.ts', '+server.js'].find((name) =>\n existsSync(join(routeDir, name)),\n );\n if (existingServerFile) {\n console.log(\n `[smrt] Preserving hand-written _resources route (${existingServerFile}, not generator-owned)`,\n );\n return false;\n }\n\n if (!existsSync(routeDir)) {\n mkdirSync(routeDir, { recursive: true });\n }\n writeFileSync(\n filePath,\n generateResourcesRouteTemplate(\n resolveSvelteKitConfigImport(projectRoot, routeDir, options),\n resolveSvelteKitConfigImport(projectRoot, routeDir, {\n configPath: options.configPath,\n configFileName: 'smrt-register.ts',\n }),\n options,\n ),\n 'utf-8',\n );\n console.log(`[smrt] Generated: ${filePath}`);\n return true;\n}\n\nfunction generateResourcesRouteTemplate(\n configImport: string,\n registerImport: string,\n options: SvelteKitOptions,\n): string {\n const kebabRoutesOption = options.kebabRoutes ? '\\n kebabRoutes: true,' : '';\n\n return `${AUTO_GENERATED_ROUTE_HEADER}\n// DO NOT EDIT - changes will be overwritten\n//\n// GET /api/_resources — CLI discovery endpoint (#2663). Returns the auth-aware\n// list of resources and commands the distributable CLI\n// (@happyvertical/smrt-app-cli) can invoke, derived from ObjectRegistry by\n// createResourceListHandler. Subsumes the route every consumer previously\n// hand-wrote (see the issue for the reference implementation this replaces).\n\nimport { createResourceListHandler } from '@happyvertical/smrt-users/sveltekit';\n// Side effect: registers @smrt() classes in ObjectRegistry before the\n// handler walks it (the generated registration, then the app's SMRT config\n// module, as the CRUD/changes/events routes import them).\nimport '${registerImport}';\nimport '${configImport}';\n\nexport const GET = createResourceListHandler({\n ensureRegistry: async () => {\n await import('${registerImport}');\n await import('${configImport}');\n },${kebabRoutesOption}\n});\n`;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAiGA,SAAgB,qBAAqB,aAA8B;CACjE,IAAI;EAIF,cAFE,cAAc,KAAK,aAAa,cAAc,CAAC,CAAC,CAAC,IAEnD,CAAA,CAAgB,QAAQ,qCAAqC;EAC7D,OAAO;CACT,QAAQ;EACN,OAAO;CACT;AACF;;AAGA,SAAgB,2BACd,aACA,SACS;CACT,IACE,QAAQ,gBAAgB,YAAY,SACpC,CAAC,qBAAqB,WAAW,GAEjC,OAAO;CAET,MAAM,WAAW,KAAK,aAAa,QAAQ,WAAW,YAAY;CAClE,KAAK,MAAM,QAAQ,CAAC,cAAc,YAAY,GAAG;EAC/C,MAAM,OAAO,KAAK,UAAU,IAAI;EAChC,IAAI,CAAC,WAAW,IAAI,GAAG;EACvB,IAAI,CAAC,aAAa,MAAM,OAAO,CAAC,CAAC,WAAA,6CAAsC,GACrE,OAAO;CAEX;CACA,OAAO;AACT;;;;AAKA,SAAgB,uBACd,aACA,SACS;CACT,IAAI,2BAA2B,aAAa,OAAO,GAAG,OAAO;CAC7D,MAAM,WAAW,KAAK,aAAa,QAAQ,WAAW,YAAY;CAClE,OAAO,CAAC,cAAc,YAAY,CAAC,CAAC,MAAM,SAAS;EACjD,MAAM,OAAO,KAAK,UAAU,IAAI;EAChC,OACE,WAAW,IAAI,KACf,CAAC,aAAa,MAAM,OAAO,CAAC,CAAC,WAAA,6CAAsC;CAEvE,CAAC;AACH;;;;;;;;AASA,SAAgB,uBACd,aACA,SACS;CACT,IAAI,QAAQ,gBAAgB,YAAY,OACtC,OAAO;CAGT,IAAI,CAAC,qBAAqB,WAAW,GAAG;EACtC,QAAQ,IACN,mJAGF;EACA,OAAO;CACT;CAEA,MAAM,WAAW,KAAK,aAAa,QAAQ,WAAW,YAAY;CAClE,MAAM,WAAW,KAAK,UAAU,YAAY;CAW5C,MAAM,qBAAqB,CAAC,cAAc,YAAY,CAAC,CAAC,MAAM,SAC5D,WAAW,KAAK,UAAU,IAAI,CAAC,CACjC;CACA,IAAI,oBAAoB;EACtB,QAAQ,IACN,oDAAoD,mBAAmB,uBACzE;EACA,OAAO;CACT;CAEA,IAAI,CAAC,WAAW,QAAQ,GACtB,UAAU,UAAU,EAAE,WAAW,KAAK,CAAC;CAEzC,cACE,UACA,+BACE,6BAA6B,aAAa,UAAU,OAAO,GAC3D,6BAA6B,aAAa,UAAU;EAClD,YAAY,QAAQ;EACpB,gBAAgB;CAClB,CAAC,GACD,OACF,GACA,OACF;CACA,QAAQ,IAAI,qBAAqB,UAAU;CAC3C,OAAO;AACT;AAEA,SAAS,+BACP,cACA,gBACA,SACQ;CAGR,OAAO,GAAG,4BAA4B;;;;;;;;;;;;;UAa9B,eAAe;UACf,aAAa;;;;oBAIH,eAAe;oBACf,aAAa;MArBL,QAAQ,cAAc,2BAA2B,GAsBrD;;;AAGxB"}
|
|
@@ -16,4 +16,26 @@ export interface SvelteKitConfigImportOptions {
|
|
|
16
16
|
* directory which will contain the generated `+server.ts` file.
|
|
17
17
|
*/
|
|
18
18
|
export declare function resolveSvelteKitConfigImport(projectRoot: string, routeDir: string, options: SvelteKitConfigImportOptions): string;
|
|
19
|
+
/** Collection accessors a generated route can take from the access prelude. */
|
|
20
|
+
export type GeneratedCollectionAccessor = 'getCollection' | 'getSmrtConfig';
|
|
21
|
+
/**
|
|
22
|
+
* Import block giving a generated route its collection accessors (#3416).
|
|
23
|
+
*
|
|
24
|
+
* The route imports the generated registration module (written beside the
|
|
25
|
+
* config module in the same generation pass, so it always exists), then
|
|
26
|
+
* resolves `getCollection`/`getSmrtConfig` through
|
|
27
|
+
* `createGeneratedCollectionAccess()` over the application's config module:
|
|
28
|
+
* its exported `runtime` (`runtime.getCollection()`, request-scoped), or a
|
|
29
|
+
* deprecated `getCollection`/`getSmrtConfig` export. The application no longer
|
|
30
|
+
* hand-writes the accessors generated routes need.
|
|
31
|
+
*/
|
|
32
|
+
export declare function generateCollectionAccessImports(projectRoot: string, routeDir: string, options: SvelteKitConfigImportOptions, accessors: readonly GeneratedCollectionAccessor[]): string;
|
|
33
|
+
/**
|
|
34
|
+
* Fail generation, before anything is written, when the configured config
|
|
35
|
+
* module would resolve to the generated registration module (any script
|
|
36
|
+
* extension or case). Generation overwrites `smrt-register.ts`, and generated
|
|
37
|
+
* routes import the config module as the application's runtime, so such a
|
|
38
|
+
* name would destroy the authored file and leave routes without a runtime.
|
|
39
|
+
*/
|
|
40
|
+
export declare function assertSvelteKitConfigModuleNotReserved(options: SvelteKitConfigImportOptions): void;
|
|
19
41
|
//# sourceMappingURL=sveltekit-config-import.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sveltekit-config-import.d.ts","sourceRoot":"","sources":["../../src/vite-plugin/sveltekit-config-import.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,MAAM,WAAW,4BAA4B;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAeD;;;;GAIG;AACH,wBAAgB,4BAA4B,CAC1C,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,4BAA4B,GACpC,MAAM,CAYR"}
|
|
1
|
+
{"version":3,"file":"sveltekit-config-import.d.ts","sourceRoot":"","sources":["../../src/vite-plugin/sveltekit-config-import.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,MAAM,WAAW,4BAA4B;IAC3C,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAeD;;;;GAIG;AACH,wBAAgB,4BAA4B,CAC1C,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,4BAA4B,GACpC,MAAM,CAYR;AAED,+EAA+E;AAC/E,MAAM,MAAM,2BAA2B,GAAG,eAAe,GAAG,eAAe,CAAC;AAE5E;;;;;;;;;;GAUG;AACH,wBAAgB,+BAA+B,CAC7C,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,4BAA4B,EACrC,SAAS,EAAE,SAAS,2BAA2B,EAAE,GAChD,MAAM,CAuBR;AAKD;;;;;;GAMG;AACH,wBAAgB,sCAAsC,CACpD,OAAO,EAAE,4BAA4B,GACpC,IAAI,CASN"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { join, relative } from "node:path";
|
|
1
|
+
import { basename, join, relative } from "node:path";
|
|
2
2
|
//#region src/vite-plugin/sveltekit-config-import.ts
|
|
3
3
|
/**
|
|
4
4
|
* Resolve the import specifier for the generated application's SMRT config.
|
|
@@ -30,7 +30,49 @@ function resolveSvelteKitConfigImport(projectRoot, routeDir, options) {
|
|
|
30
30
|
const routeRelative = relative(routeDir, join(projectRoot, configPath, configModule)).replace(/\\/g, "/");
|
|
31
31
|
return routeRelative.startsWith(".") ? routeRelative : `./${routeRelative}`;
|
|
32
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Import block giving a generated route its collection accessors (#3416).
|
|
35
|
+
*
|
|
36
|
+
* The route imports the generated registration module (written beside the
|
|
37
|
+
* config module in the same generation pass, so it always exists), then
|
|
38
|
+
* resolves `getCollection`/`getSmrtConfig` through
|
|
39
|
+
* `createGeneratedCollectionAccess()` over the application's config module:
|
|
40
|
+
* its exported `runtime` (`runtime.getCollection()`, request-scoped), or a
|
|
41
|
+
* deprecated `getCollection`/`getSmrtConfig` export. The application no longer
|
|
42
|
+
* hand-writes the accessors generated routes need.
|
|
43
|
+
*/
|
|
44
|
+
function generateCollectionAccessImports(projectRoot, routeDir, options, accessors) {
|
|
45
|
+
const configImport = resolveSvelteKitConfigImport(projectRoot, routeDir, options);
|
|
46
|
+
const registerImport = resolveSvelteKitConfigImport(projectRoot, routeDir, {
|
|
47
|
+
configPath: options.configPath,
|
|
48
|
+
configFileName: "smrt-register.ts"
|
|
49
|
+
});
|
|
50
|
+
const source = `${normalizePath(options.configPath || "src/lib/server")}/${options.configFileName || "smrt.ts"}`;
|
|
51
|
+
return [
|
|
52
|
+
`import '${registerImport}';`,
|
|
53
|
+
"import { createGeneratedCollectionAccess } from '@happyvertical/smrt-core';",
|
|
54
|
+
`import * as smrtApplication from '${configImport}';`,
|
|
55
|
+
"",
|
|
56
|
+
`const { ${accessors.join(", ")} } = createGeneratedCollectionAccess(`,
|
|
57
|
+
" smrtApplication,",
|
|
58
|
+
` '${source.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}',`,
|
|
59
|
+
");"
|
|
60
|
+
].join("\n");
|
|
61
|
+
}
|
|
62
|
+
/** Base name of the generated registration module beside the config module. */
|
|
63
|
+
var REGISTRATION_MODULE_NAME = /^smrt-register(?:\.[cm]?[jt]sx?)?$/i;
|
|
64
|
+
/**
|
|
65
|
+
* Fail generation, before anything is written, when the configured config
|
|
66
|
+
* module would resolve to the generated registration module (any script
|
|
67
|
+
* extension or case). Generation overwrites `smrt-register.ts`, and generated
|
|
68
|
+
* routes import the config module as the application's runtime, so such a
|
|
69
|
+
* name would destroy the authored file and leave routes without a runtime.
|
|
70
|
+
*/
|
|
71
|
+
function assertSvelteKitConfigModuleNotReserved(options) {
|
|
72
|
+
const configFileName = options.configFileName || "smrt.ts";
|
|
73
|
+
if (REGISTRATION_MODULE_NAME.test(basename(normalizePath(configFileName)))) throw new Error(`[smrt] svelteKit.configFileName '${configFileName}' is reserved for the generated registration module (smrt-register.ts). Name the application's SMRT config module something else, for example smrt.ts.`);
|
|
74
|
+
}
|
|
33
75
|
//#endregion
|
|
34
|
-
export { resolveSvelteKitConfigImport };
|
|
76
|
+
export { assertSvelteKitConfigModuleNotReserved, generateCollectionAccessImports, resolveSvelteKitConfigImport };
|
|
35
77
|
|
|
36
78
|
//# sourceMappingURL=sveltekit-config-import.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sveltekit-config-import.js","names":[],"sources":["../../src/vite-plugin/sveltekit-config-import.ts"],"sourcesContent":["/**\n * Resolve the import specifier for the generated application's SMRT config.\n *\n * SvelteKit maps `src/lib` to `$lib`; preserve that concise public convention\n * where possible. Configurations outside `src/lib` remain supported through a\n * route-relative import so generated server routes do not assume an alias the\n * consumer did not configure.\n */\n\nimport { join, relative } from 'node:path';\n\nexport interface SvelteKitConfigImportOptions {\n configPath?: string;\n configFileName?: string;\n}\n\n// Generated config files have historically imported TypeScript files without\n// their `.ts` suffix. Keep every other supplied extension intact: it may carry\n// a consumer-selected module format (for example `.mts`).\nconst TYPESCRIPT_EXTENSION = /\\.ts$/i;\n\nfunction normalizePath(path: string): string {\n return path.replace(/\\\\/g, '/').replace(/^\\.\\//, '').replace(/\\/+$/, '');\n}\n\nfunction moduleSpecifierPath(fileName: string): string {\n return fileName.replace(TYPESCRIPT_EXTENSION, '');\n}\n\n/**\n * Return an extensionless specifier because Vite resolves generated route\n * imports through its source-module resolver. `routeDir` is the absolute\n * directory which will contain the generated `+server.ts` file.\n */\nexport function resolveSvelteKitConfigImport(\n projectRoot: string,\n routeDir: string,\n options: SvelteKitConfigImportOptions,\n): string {\n const configPath = normalizePath(options.configPath || 'src/lib/server');\n const configModule = moduleSpecifierPath(options.configFileName || 'smrt.ts');\n\n if (configPath === 'src/lib' || configPath.startsWith('src/lib/')) {\n const libPath = configPath.slice('src/lib'.length).replace(/^\\//, '');\n return libPath ? `$lib/${libPath}/${configModule}` : `$lib/${configModule}`;\n }\n\n const configFile = join(projectRoot, configPath, configModule);\n const routeRelative = relative(routeDir, configFile).replace(/\\\\/g, '/');\n return routeRelative.startsWith('.') ? routeRelative : `./${routeRelative}`;\n}\n"],"mappings":";;;;;;;;;;AAmBA,IAAM,uBAAuB;AAE7B,SAAS,cAAc,MAAsB;CAC3C,OAAO,KAAK,QAAQ,OAAO,GAAG,CAAC,CAAC,QAAQ,SAAS,EAAE,CAAC,CAAC,QAAQ,QAAQ,EAAE;AACzE;AAEA,SAAS,oBAAoB,UAA0B;CACrD,OAAO,SAAS,QAAQ,sBAAsB,EAAE;AAClD;;;;;;AAOA,SAAgB,6BACd,aACA,UACA,SACQ;CACR,MAAM,aAAa,cAAc,QAAQ,cAAc,gBAAgB;CACvE,MAAM,eAAe,oBAAoB,QAAQ,kBAAkB,SAAS;CAE5E,IAAI,eAAe,aAAa,WAAW,WAAW,UAAU,GAAG;EACjE,MAAM,UAAU,WAAW,MAAM,CAAgB,CAAC,CAAC,QAAQ,OAAO,EAAE;EACpE,OAAO,UAAU,QAAQ,QAAQ,GAAG,iBAAiB,QAAQ;CAC/D;CAGA,MAAM,gBAAgB,SAAS,UADZ,KAAK,aAAa,YAAY,YACR,CAAU,CAAC,CAAC,QAAQ,OAAO,GAAG;CACvE,OAAO,cAAc,WAAW,GAAG,IAAI,gBAAgB,KAAK;AAC9D"}
|
|
1
|
+
{"version":3,"file":"sveltekit-config-import.js","names":[],"sources":["../../src/vite-plugin/sveltekit-config-import.ts"],"sourcesContent":["/**\n * Resolve the import specifier for the generated application's SMRT config.\n *\n * SvelteKit maps `src/lib` to `$lib`; preserve that concise public convention\n * where possible. Configurations outside `src/lib` remain supported through a\n * route-relative import so generated server routes do not assume an alias the\n * consumer did not configure.\n */\n\nimport { basename, join, relative } from 'node:path';\n\nexport interface SvelteKitConfigImportOptions {\n configPath?: string;\n configFileName?: string;\n}\n\n// Generated config files have historically imported TypeScript files without\n// their `.ts` suffix. Keep every other supplied extension intact: it may carry\n// a consumer-selected module format (for example `.mts`).\nconst TYPESCRIPT_EXTENSION = /\\.ts$/i;\n\nfunction normalizePath(path: string): string {\n return path.replace(/\\\\/g, '/').replace(/^\\.\\//, '').replace(/\\/+$/, '');\n}\n\nfunction moduleSpecifierPath(fileName: string): string {\n return fileName.replace(TYPESCRIPT_EXTENSION, '');\n}\n\n/**\n * Return an extensionless specifier because Vite resolves generated route\n * imports through its source-module resolver. `routeDir` is the absolute\n * directory which will contain the generated `+server.ts` file.\n */\nexport function resolveSvelteKitConfigImport(\n projectRoot: string,\n routeDir: string,\n options: SvelteKitConfigImportOptions,\n): string {\n const configPath = normalizePath(options.configPath || 'src/lib/server');\n const configModule = moduleSpecifierPath(options.configFileName || 'smrt.ts');\n\n if (configPath === 'src/lib' || configPath.startsWith('src/lib/')) {\n const libPath = configPath.slice('src/lib'.length).replace(/^\\//, '');\n return libPath ? `$lib/${libPath}/${configModule}` : `$lib/${configModule}`;\n }\n\n const configFile = join(projectRoot, configPath, configModule);\n const routeRelative = relative(routeDir, configFile).replace(/\\\\/g, '/');\n return routeRelative.startsWith('.') ? routeRelative : `./${routeRelative}`;\n}\n\n/** Collection accessors a generated route can take from the access prelude. */\nexport type GeneratedCollectionAccessor = 'getCollection' | 'getSmrtConfig';\n\n/**\n * Import block giving a generated route its collection accessors (#3416).\n *\n * The route imports the generated registration module (written beside the\n * config module in the same generation pass, so it always exists), then\n * resolves `getCollection`/`getSmrtConfig` through\n * `createGeneratedCollectionAccess()` over the application's config module:\n * its exported `runtime` (`runtime.getCollection()`, request-scoped), or a\n * deprecated `getCollection`/`getSmrtConfig` export. The application no longer\n * hand-writes the accessors generated routes need.\n */\nexport function generateCollectionAccessImports(\n projectRoot: string,\n routeDir: string,\n options: SvelteKitConfigImportOptions,\n accessors: readonly GeneratedCollectionAccessor[],\n): string {\n const configImport = resolveSvelteKitConfigImport(\n projectRoot,\n routeDir,\n options,\n );\n const registerImport = resolveSvelteKitConfigImport(projectRoot, routeDir, {\n configPath: options.configPath,\n configFileName: 'smrt-register.ts',\n });\n const source = `${normalizePath(options.configPath || 'src/lib/server')}/${\n options.configFileName || 'smrt.ts'\n }`;\n return [\n `import '${registerImport}';`,\n \"import { createGeneratedCollectionAccess } from '@happyvertical/smrt-core';\",\n `import * as smrtApplication from '${configImport}';`,\n '',\n `const { ${accessors.join(', ')} } = createGeneratedCollectionAccess(`,\n ' smrtApplication,',\n ` '${source.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\")}',`,\n ');',\n ].join('\\n');\n}\n\n/** Base name of the generated registration module beside the config module. */\nconst REGISTRATION_MODULE_NAME = /^smrt-register(?:\\.[cm]?[jt]sx?)?$/i;\n\n/**\n * Fail generation, before anything is written, when the configured config\n * module would resolve to the generated registration module (any script\n * extension or case). Generation overwrites `smrt-register.ts`, and generated\n * routes import the config module as the application's runtime, so such a\n * name would destroy the authored file and leave routes without a runtime.\n */\nexport function assertSvelteKitConfigModuleNotReserved(\n options: SvelteKitConfigImportOptions,\n): void {\n const configFileName = options.configFileName || 'smrt.ts';\n if (REGISTRATION_MODULE_NAME.test(basename(normalizePath(configFileName)))) {\n throw new Error(\n `[smrt] svelteKit.configFileName '${configFileName}' is reserved for the ` +\n 'generated registration module (smrt-register.ts). Name the ' +\n \"application's SMRT config module something else, for example smrt.ts.\",\n );\n }\n}\n"],"mappings":";;;;;;;;;;AAmBA,IAAM,uBAAuB;AAE7B,SAAS,cAAc,MAAsB;CAC3C,OAAO,KAAK,QAAQ,OAAO,GAAG,CAAC,CAAC,QAAQ,SAAS,EAAE,CAAC,CAAC,QAAQ,QAAQ,EAAE;AACzE;AAEA,SAAS,oBAAoB,UAA0B;CACrD,OAAO,SAAS,QAAQ,sBAAsB,EAAE;AAClD;;;;;;AAOA,SAAgB,6BACd,aACA,UACA,SACQ;CACR,MAAM,aAAa,cAAc,QAAQ,cAAc,gBAAgB;CACvE,MAAM,eAAe,oBAAoB,QAAQ,kBAAkB,SAAS;CAE5E,IAAI,eAAe,aAAa,WAAW,WAAW,UAAU,GAAG;EACjE,MAAM,UAAU,WAAW,MAAM,CAAgB,CAAC,CAAC,QAAQ,OAAO,EAAE;EACpE,OAAO,UAAU,QAAQ,QAAQ,GAAG,iBAAiB,QAAQ;CAC/D;CAGA,MAAM,gBAAgB,SAAS,UADZ,KAAK,aAAa,YAAY,YACR,CAAU,CAAC,CAAC,QAAQ,OAAO,GAAG;CACvE,OAAO,cAAc,WAAW,GAAG,IAAI,gBAAgB,KAAK;AAC9D;;;;;;;;;;;;AAgBA,SAAgB,gCACd,aACA,UACA,SACA,WACQ;CACR,MAAM,eAAe,6BACnB,aACA,UACA,OACF;CACA,MAAM,iBAAiB,6BAA6B,aAAa,UAAU;EACzE,YAAY,QAAQ;EACpB,gBAAgB;CAClB,CAAC;CACD,MAAM,SAAS,GAAG,cAAc,QAAQ,cAAc,gBAAgB,EAAE,GACtE,QAAQ,kBAAkB;CAE5B,OAAO;EACL,WAAW,eAAe;EAC1B;EACA,qCAAqC,aAAa;EAClD;EACA,WAAW,UAAU,KAAK,IAAI,EAAE;EAChC;EACA,MAAM,OAAO,QAAQ,OAAO,MAAM,CAAC,CAAC,QAAQ,MAAM,KAAK,EAAE;EACzD;CACF,CAAC,CAAC,KAAK,IAAI;AACb;;AAGA,IAAM,2BAA2B;;;;;;;;AASjC,SAAgB,uCACd,SACM;CACN,MAAM,iBAAiB,QAAQ,kBAAkB;CACjD,IAAI,yBAAyB,KAAK,SAAS,cAAc,cAAc,CAAC,CAAC,GACvE,MAAM,IAAI,MACR,oCAAoC,eAAe,uJAGrD;AAEJ"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sveltekit-generator.d.ts","sourceRoot":"","sources":["../../src/vite-plugin/sveltekit-generator.ts"],"names":[],"mappings":"AAAA;;;GAGG;
|
|
1
|
+
{"version":3,"file":"sveltekit-generator.d.ts","sourceRoot":"","sources":["../../src/vite-plugin/sveltekit-generator.ts"],"names":[],"mappings":"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"}
|
|
@@ -3,7 +3,7 @@ import { CRUD_OPERATIONS, createManifestClassNamePredicate, declaredTypeAcceptsD
|
|
|
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";
|
|
6
|
-
import { resolveSvelteKitConfigImport } from "./sveltekit-config-import.js";
|
|
6
|
+
import { assertSvelteKitConfigModuleNotReserved, generateCollectionAccessImports, resolveSvelteKitConfigImport } from "./sveltekit-config-import.js";
|
|
7
7
|
import { generateChangesRoute } from "./changes-route.js";
|
|
8
8
|
import { generateDevPlaneRoute, willGenerateDevPlaneRoute } from "./dev-plane-route.js";
|
|
9
9
|
import { generateEventsRoute } from "./events-route.js";
|
|
@@ -12,7 +12,9 @@ import { canonicalSvelteKitPath } from "./sveltekit-path.js";
|
|
|
12
12
|
import { collectSyncApplyTargets, generateSyncApplyRoute } from "./sync-apply-route.js";
|
|
13
13
|
import { computeWebManifestHash, isCollectionManifestClass, orderedManifestObjectEntries, resolveCollectionItemObject, resolveCollectionItemTypeName } from "./web-collections.js";
|
|
14
14
|
import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
15
|
+
import { createRequire } from "node:module";
|
|
15
16
|
import { isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
17
|
+
import { pathToFileURL } from "node:url";
|
|
16
18
|
//#region src/vite-plugin/sveltekit-generator.ts
|
|
17
19
|
/**
|
|
18
20
|
* SvelteKit route auto-generation from SMRT objects
|
|
@@ -881,6 +883,7 @@ async function generateSvelteKitRoutes(projectRoot, routeManifest, options, sema
|
|
|
881
883
|
clearKnowledgeRoute: true
|
|
882
884
|
}, registrationManifest = routeManifest, hooks = {}) {
|
|
883
885
|
if (!options.enabled) return;
|
|
886
|
+
assertSvelteKitConfigModuleNotReserved(options);
|
|
884
887
|
console.log("[smrt] Generating SvelteKit routes...");
|
|
885
888
|
if (options.rejectRouteCollisions) assertNoCrossObjectRouteCollisions(projectRoot, routeManifest, options, semanticManifest, utilityManifests.protectedRoutePaths);
|
|
886
889
|
await hooks.beforeCleanup?.();
|
|
@@ -1150,6 +1153,37 @@ function formatRegistrationImport(importedObject) {
|
|
|
1150
1153
|
return importedObject.simpleName === importedObject.bindingName ? importedObject.simpleName : `${importedObject.simpleName} as ${importedObject.bindingName}`;
|
|
1151
1154
|
}
|
|
1152
1155
|
/**
|
|
1156
|
+
* Whether `@happyvertical/smrt-app-runtime/sveltekit` resolves from the
|
|
1157
|
+
* consumer at `projectRoot` (same signal as `consumerHasSmrtUsers`).
|
|
1158
|
+
*/
|
|
1159
|
+
function consumerHasSmrtAppRuntime(projectRoot) {
|
|
1160
|
+
try {
|
|
1161
|
+
createRequire(pathToFileURL(join(projectRoot, "package.json")).href).resolve("@happyvertical/smrt-app-runtime/sveltekit");
|
|
1162
|
+
return true;
|
|
1163
|
+
} catch {
|
|
1164
|
+
return false;
|
|
1165
|
+
}
|
|
1166
|
+
}
|
|
1167
|
+
/** Default config module for apps that install the application runtime. */
|
|
1168
|
+
var RUNTIME_CONFIG_FILE_CONTENT = `/**
|
|
1169
|
+
* The application's SMRT runtime (\`@happyvertical/smrt-app-runtime\`).
|
|
1170
|
+
* Generated once by the smrt() Vite plugin because this file was missing; it
|
|
1171
|
+
* is never overwritten, so add application options here.
|
|
1172
|
+
*
|
|
1173
|
+
* The plugin registers the generated objects before this module runs, and
|
|
1174
|
+
* generated API routes resolve collections through \`runtime.getCollection()\`
|
|
1175
|
+
* (request-scoped). In the local profile the runtime holds the single-writer
|
|
1176
|
+
* lease; pass \`acquireWriterLease: false\` to opt out.
|
|
1177
|
+
*/
|
|
1178
|
+
|
|
1179
|
+
import { createProviderReadinessProbe } from '@happyvertical/smrt-app-runtime';
|
|
1180
|
+
import { createSmrtSvelteKitRuntime } from '@happyvertical/smrt-app-runtime/sveltekit';
|
|
1181
|
+
|
|
1182
|
+
export const runtime = createSmrtSvelteKitRuntime({
|
|
1183
|
+
providerReadiness: createProviderReadinessProbe,
|
|
1184
|
+
});
|
|
1185
|
+
`;
|
|
1186
|
+
/**
|
|
1153
1187
|
* Generates centralized SMRT configuration file
|
|
1154
1188
|
* Only creates if file doesn't exist (preserves user customizations)
|
|
1155
1189
|
*/
|
|
@@ -1163,6 +1197,12 @@ async function generateSmrtConfigFile(projectRoot, manifest, options) {
|
|
|
1163
1197
|
console.log("[smrt] Config file already exists, skipping generation");
|
|
1164
1198
|
return;
|
|
1165
1199
|
}
|
|
1200
|
+
if (!existsSync(configDir)) mkdirSync(configDir, { recursive: true });
|
|
1201
|
+
if (consumerHasSmrtAppRuntime(projectRoot)) {
|
|
1202
|
+
writeFileSync(configFilePath, RUNTIME_CONFIG_FILE_CONTENT, "utf-8");
|
|
1203
|
+
console.log(`[smrt] Generated configuration file: ${configFilePath}`);
|
|
1204
|
+
return;
|
|
1205
|
+
}
|
|
1166
1206
|
const configContent = `/**
|
|
1167
1207
|
* Centralized SMRT configuration with per-object overrides
|
|
1168
1208
|
* Generated by @smrt/core vite plugin
|
|
@@ -1705,14 +1745,14 @@ function generateCollectionRouteTemplate(projectRoot, className, objectDef, sema
|
|
|
1705
1745
|
const listUsesPermissionScopedBody = collectReadPermissionFields(objectDef, semanticManifest).length > 0;
|
|
1706
1746
|
const listUsesBodyHash = listUsesSerializer || listUsesPermissionScopedBody;
|
|
1707
1747
|
const webManifestHash = computeWebManifestHash(semanticManifest);
|
|
1708
|
-
const
|
|
1748
|
+
const collectionAccessImports = generateCollectionAccessImports(projectRoot, routeDir, options, ["getCollection"]);
|
|
1709
1749
|
const imports = `${AUTO_GENERATED_ROUTE_HEADER}
|
|
1710
1750
|
// DO NOT EDIT - changes will be overwritten
|
|
1711
1751
|
|
|
1712
1752
|
import { error${hasPost ? ", json" : ""} } from '@sveltejs/kit';
|
|
1713
|
-
${serializerImports ? `${serializerImports}\n` : ""}import {
|
|
1714
|
-
${hasPost ? "import { normalizeTypedHttpError } from '@happyvertical/smrt-core';\n" : ""}
|
|
1753
|
+
${serializerImports ? `${serializerImports}\n` : ""}${hasPost ? "import { normalizeTypedHttpError } from '@happyvertical/smrt-core';\n" : ""}
|
|
1715
1754
|
${modelType.importStatement ? `${modelType.importStatement}\n` : ""}import type { RequestHandler } from './$types';
|
|
1755
|
+
${collectionAccessImports}
|
|
1716
1756
|
// Note: ${className} is auto-registered by the Vite plugin scanner
|
|
1717
1757
|
${generateAuthGuardHelper(objectDef, semanticManifest)}${needsRouteTenantContext(objectDef) ? generateTenantContextHelper(usesPrincipalContext(objectDef), isTenantScoped(objectDef)) : ""}${hasPost ? generateWritablePolicyHelper(objectDef) : ""}${hasPost ? generateTypedRouteErrorHelper() : ""}${hasGet ? generateListBoundsHelper(objectDef) : ""}${hasGet ? generateConditionalGetRouteHelper(objectDef.decoratorConfig?.api, {
|
|
1718
1758
|
tenantScoped: isTenantScoped(objectDef),
|
|
@@ -1832,14 +1872,14 @@ function generateItemRouteTemplate(projectRoot, className, objectDef, semanticMa
|
|
|
1832
1872
|
const getUsesPermissionScopedBody = collectReadPermissionFields(objectDef, semanticManifest).length > 0;
|
|
1833
1873
|
const getUsesBodyHash = getUsesSerializer || getUsesPermissionScopedBody;
|
|
1834
1874
|
const webManifestHash = computeWebManifestHash(semanticManifest);
|
|
1835
|
-
const
|
|
1875
|
+
const collectionAccessImports = generateCollectionAccessImports(projectRoot, routeDir, options, ["getCollection"]);
|
|
1836
1876
|
const imports = `${AUTO_GENERATED_ROUTE_HEADER}
|
|
1837
1877
|
// DO NOT EDIT - changes will be overwritten
|
|
1838
1878
|
|
|
1839
1879
|
import { error${hasPut || hasDelete ? ", json" : ""} } from '@sveltejs/kit';
|
|
1840
|
-
${serializerImports ? `${serializerImports}\n` : ""}import {
|
|
1841
|
-
${hasPut || hasDelete ? "import { normalizeTypedHttpError } from '@happyvertical/smrt-core';\n" : ""}
|
|
1880
|
+
${serializerImports ? `${serializerImports}\n` : ""}${hasPut || hasDelete ? "import { normalizeTypedHttpError } from '@happyvertical/smrt-core';\n" : ""}
|
|
1842
1881
|
${modelType.importStatement ? `${modelType.importStatement}\n` : ""}import type { RequestHandler } from './$types';
|
|
1882
|
+
${collectionAccessImports}
|
|
1843
1883
|
${generateAuthGuardHelper(objectDef, semanticManifest)}${needsRouteTenantContext(objectDef) ? generateTenantContextHelper(usesPrincipalContext(objectDef), isTenantScoped(objectDef)) : ""}${hasPut ? generateWritablePolicyHelper(objectDef) : ""}${hasPut || hasDelete ? generateTypedRouteErrorHelper() : ""}${hasGet ? generateConditionalGetRouteHelper(objectDef.decoratorConfig?.api, {
|
|
1844
1884
|
tenantScoped: isTenantScoped(objectDef),
|
|
1845
1885
|
permissionScoped: getUsesPermissionScopedBody,
|
|
@@ -1943,13 +1983,23 @@ function generateActionRouteTemplate(projectRoot, routeDir, routeSpecs, objectDe
|
|
|
1943
1983
|
"normalizeTypedHttpError",
|
|
1944
1984
|
...[...decoderImports].sort()
|
|
1945
1985
|
].join(", ");
|
|
1986
|
+
const usesCollection = hostType === "collection" || routeConfig.scope !== "collection";
|
|
1946
1987
|
const configImport = resolveSvelteKitConfigImport(projectRoot, routeDir, options);
|
|
1988
|
+
const registerImport = resolveSvelteKitConfigImport(projectRoot, routeDir, {
|
|
1989
|
+
configPath: options.configPath,
|
|
1990
|
+
configFileName: "smrt-register.ts"
|
|
1991
|
+
});
|
|
1947
1992
|
const importBlock = [
|
|
1948
1993
|
"import { error, json } from '@sveltejs/kit';",
|
|
1949
1994
|
`import { ${coreImports} } from '@happyvertical/smrt-core';`,
|
|
1950
|
-
|
|
1995
|
+
usesCollection ? null : [
|
|
1996
|
+
`import '${registerImport}';`,
|
|
1997
|
+
`import '${configImport}';`,
|
|
1998
|
+
"import { ObjectRegistry } from '@happyvertical/smrt-core';"
|
|
1999
|
+
].join("\n"),
|
|
1951
2000
|
typeImports,
|
|
1952
|
-
"import type { RequestHandler } from './$types';"
|
|
2001
|
+
"import type { RequestHandler } from './$types';",
|
|
2002
|
+
usesCollection ? generateCollectionAccessImports(projectRoot, routeDir, options, ["getCollection"]) : null
|
|
1953
2003
|
].filter(Boolean).join("\n");
|
|
1954
2004
|
const tenantScoped = isTenantScoped(objectDef) || routeSpecs.some((spec) => !!spec.lookupObjectDef && isTenantScoped(spec.lookupObjectDef));
|
|
1955
2005
|
const principalContext = usesPrincipalContext(objectDef) || routeSpecs.some((spec) => !!spec.lookupObjectDef && usesPrincipalContext(spec.lookupObjectDef));
|