@happyvertical/smrt-core 0.36.0 → 0.36.2
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/dist/manifest/static-manifest.js +2 -2
- package/dist/manifest/static-manifest.js.map +1 -1
- package/dist/manifest/store.js +2 -2
- package/dist/manifest/test-manifest-stub.js +27605 -27605
- package/dist/manifest/test-manifest-stub.js.map +1 -1
- package/dist/manifest.json +2 -2
- package/dist/smrt-knowledge.json +4 -4
- package/dist/vite-plugin/sveltekit-generator.d.ts.map +1 -1
- package/dist/vite-plugin/sveltekit-generator.js +304 -80
- package/dist/vite-plugin/sveltekit-generator.js.map +1 -1
- package/package.json +4 -4
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sveltekit-generator.js","sources":["../../src/vite-plugin/sveltekit-generator.ts"],"sourcesContent":["/**\n * SvelteKit route auto-generation from SMRT objects\n * Generates real TypeScript files in src/routes/api/ based on discovered SMRT objects\n */\n\nimport {\n existsSync,\n mkdirSync,\n readdirSync,\n readFileSync,\n unlinkSync,\n writeFileSync,\n} from 'node:fs';\nimport { join, relative } from 'node:path';\nimport type { DomainKnowledgeConfig } from '@happyvertical/smrt-types';\nimport type {\n ApiConfig,\n ApiCustomRouteConfig,\n ApiHttpMethod,\n ApiSerializerReference,\n} from '../registry/types.js';\nimport type {\n SmartObjectDefinition,\n SmartObjectManifest,\n} from '../scanner/types';\n\nexport interface SvelteKitOptions {\n enabled: boolean;\n routesDir: string;\n objectsDir: string;\n configPath?: string; // default: 'src/lib/server'\n configFileName?: string; // default: 'smrt.ts'\n /**\n * Apply kebab-case to custom-method URL segments (e.g. `discoverFromUrl`\n * becomes `/discover-from-url`). Opt-in for one minor; default flips in the\n * next major. An explicit `api.routes[name].path` always wins over this.\n */\n kebabRoutes?: boolean;\n /** Domain knowledge API route generation. Disabled unless explicitly enabled. */\n knowledge?: DomainKnowledgeConfig;\n}\n\n// Keep this aligned with biome.json formatter.lineWidth.\nconst BIOME_LINE_WIDTH = 80;\nconst AUTO_GENERATED_ROUTE_HEADER =\n '// Auto-generated by @smrt/core vite plugin';\nconst STANDARD_API_ACTIONS = ['list', 'get', 'create', 'update', 'delete'];\n\ninterface ResolvedApiActionRouteConfig {\n scope: 'item' | 'collection';\n method: ApiHttpMethod;\n pathSegments: string[];\n pathParamNames: string[];\n}\n\ninterface GeneratedActionRouteSpec {\n lookupClassName: string;\n actionName: string;\n actionDef: any;\n routeConfig: ResolvedApiActionRouteConfig;\n hostType: 'item' | 'collection';\n}\n\ninterface ResolvedStandardRouteSerializers {\n importStatements: string[];\n itemSerializerName?: string;\n listItemSerializerName?: string;\n}\n\n/**\n * Extract simple class name from potentially qualified name.\n * Qualified names follow the pattern: @scope/package:ClassName\n *\n * Issue #870: Manifests may contain qualified names which generate invalid\n * import statements like: import { @pkg:Class } from '@pkg'\n *\n * @param qualifiedName - Class name that may be qualified (e.g., \"@pkg:Class\" or \"Class\")\n * @returns Simple class name (e.g., \"Class\")\n */\nfunction extractSimpleClassName(qualifiedName: string): string {\n const colonIndex = qualifiedName.indexOf(':');\n if (colonIndex !== -1) {\n return qualifiedName.substring(colonIndex + 1);\n }\n return qualifiedName;\n}\n\n/**\n * Check if an object definition represents a SmrtCollection class.\n * Collection classes share route paths with their item class (via inherited `collection` field),\n * so generating routes for both would cause file collisions.\n */\nfunction isCollectionClass(objectDef: SmartObjectDefinition): boolean {\n return objectDef.extends === 'SmrtCollection' || !!objectDef.extendsTypeArg;\n}\n\nfunction getRegistrationPackageName(\n manifest: SmartObjectManifest,\n objectDef: SmartObjectDefinition,\n isLocal: boolean,\n): string | undefined {\n if (isLocal) {\n return manifest.packageName ?? objectDef.packageName;\n }\n\n return objectDef.packageName;\n}\n\nfunction toSingleQuotedStringLiteral(value: string): string {\n const jsonLiteral = JSON.stringify(value);\n const jsonContent = jsonLiteral.slice(1, -1).replaceAll(\"'\", \"\\\\'\");\n return `'${jsonContent}'`;\n}\n\nfunction getApiConfigObject(apiConfig: unknown): ApiConfig | null {\n if (!apiConfig || typeof apiConfig !== 'object') {\n return null;\n }\n\n return apiConfig as ApiConfig;\n}\n\nfunction isSameSerializerReference(\n left?: ApiSerializerReference,\n right?: ApiSerializerReference,\n): boolean {\n return (\n !!left &&\n !!right &&\n left.importPath === right.importPath &&\n left.exportName === right.exportName\n );\n}\n\nfunction resolveStandardRouteSerializers(\n apiConfig: unknown,\n): ResolvedStandardRouteSerializers {\n const config = getApiConfigObject(apiConfig);\n const itemSerializer = config?.serializers?.item;\n const listItemSerializer =\n config?.serializers?.listItem || config?.serializers?.item;\n\n const importStatements: string[] = [];\n let itemSerializerName: string | undefined;\n let listItemSerializerName: string | undefined;\n\n if (itemSerializer) {\n itemSerializerName = 'serializeItemResponse';\n importStatements.push(\n `import { ${itemSerializer.exportName} as ${itemSerializerName} } from '${itemSerializer.importPath}';`,\n );\n }\n\n if (listItemSerializer) {\n if (isSameSerializerReference(listItemSerializer, itemSerializer)) {\n listItemSerializerName = itemSerializerName;\n } else {\n listItemSerializerName = 'serializeListItemResponse';\n importStatements.push(\n `import { ${listItemSerializer.exportName} as ${listItemSerializerName} } from '${listItemSerializer.importPath}';`,\n );\n }\n }\n\n return {\n importStatements,\n itemSerializerName,\n listItemSerializerName,\n };\n}\n\n/**\n * Collect property names marked `@field({ readonly: true })` for an object, so\n * the generated write surfaces can strip them from request bodies (#1540, 2b).\n */\nfunction collectReadonlyFieldNames(objectDef: SmartObjectDefinition): string[] {\n const fields = objectDef.fields || {};\n const names: string[] = [];\n for (const [name, def] of Object.entries(fields)) {\n const meta = (def as { _meta?: Record<string, unknown> })._meta;\n if (\n (def as { readonly?: boolean }).readonly === true ||\n meta?.readonly === true\n ) {\n names.push(name);\n }\n }\n return names;\n}\n\n/**\n * Resolve the optional `@smrt({ api: { writable: [...] } })` allowlist. When\n * present, only these fields may be set from a create/update request body.\n */\nfunction getApiWritableAllowlist(apiConfig: unknown): string[] | null {\n const config = getApiConfigObject(apiConfig);\n return Array.isArray(config?.writable) ? config.writable : null;\n}\n\n/**\n * Emit the mass-assignment guard helper injected into generated route files\n * (#1540, 2b). It strips framework/server-managed (`id`, `tenantId`,\n * timestamps, `_`-prefixed) and `@field({ readonly: true })` fields from\n * request bodies, and — when a `writable` allowlist is configured — intersects\n * with it. Applied to every generated `create`/`update` handler.\n */\nfunction generateWritablePolicyHelper(\n objectDef: SmartObjectDefinition,\n): string {\n const readonly = collectReadonlyFieldNames(objectDef);\n const writable = getApiWritableAllowlist(objectDef.decoratorConfig?.api);\n\n return `\n// Mass-assignment guard (#1540): strip framework/server-managed + read-only\n// fields from create/update request bodies before they reach the model.\nconst WRITABLE_ALLOWLIST: string[] | null = ${\n writable ? JSON.stringify(writable) : 'null'\n };\nconst READONLY_FIELDS: string[] = ${JSON.stringify(readonly)};\nconst SERVER_MANAGED_FIELDS = [\n 'id',\n 'tenantId',\n 'tenant_id',\n 'createdAt',\n 'created_at',\n 'updatedAt',\n 'updated_at',\n];\n\nfunction applyWritablePolicy(data: unknown): Record<string, unknown> {\n if (!data || typeof data !== 'object') return {};\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data as Record<string, unknown>)) {\n if (key.startsWith('_')) continue;\n if (SERVER_MANAGED_FIELDS.includes(key)) continue;\n if (READONLY_FIELDS.includes(key)) continue;\n if (WRITABLE_ALLOWLIST && !WRITABLE_ALLOWLIST.includes(key)) continue;\n result[key] = value;\n }\n return result;\n}\n`;\n}\n\n/**\n * Resolve the `@smrt({ api: { public } })` posture (fail-closed default).\n * - `false`/unset → all routes require an authenticated principal.\n * - `true` → all routes are public.\n * - `'read'` → reads are public, mutations still require auth.\n */\nfunction getApiPublicAccess(apiConfig: unknown): boolean | 'read' {\n const config = getApiConfigObject(apiConfig);\n const value = config?.public;\n if (value === true || value === 'read') {\n return value;\n }\n return false;\n}\n\n/**\n * Emit the fail-closed authorization guard injected into generated route files\n * (#1540, 2c). Every generated CRUD/action handler calls `requireRouteAuth`,\n * which throws 401 unless the route is `public` or `locals` carries an\n * authenticated principal. Mirrors the knowledge-route `isKnowledgeAdmin`\n * precedent. Mutating verbs require auth even when reads are public.\n */\nfunction generateAuthGuardHelper(objectDef: SmartObjectDefinition): string {\n const publicAccess = getApiPublicAccess(objectDef.decoratorConfig?.api);\n\n return `\n// Fail-closed authorization (#1540): generated routes require an authenticated\n// principal on \\`locals\\` unless explicitly marked \\`@smrt({ api: { public } })\\`.\nconst PUBLIC_ACCESS: boolean | 'read' = ${JSON.stringify(publicAccess)};\n\nfunction hasAuthenticatedPrincipal(locals: unknown): boolean {\n if (!locals || typeof locals !== 'object') return false;\n const l = locals as Record<string, unknown>;\n // Only a resolved, object-shaped principal counts. We intentionally do NOT\n // treat \\`locals.auth\\` as a signal: Auth.js/SvelteKit put a callable\n // \\`auth()\\` helper on every request (including anonymous ones), so honoring\n // it would fail OPEN. Booleans don't count either (no convention sets\n // \\`locals.user = true\\`); the only boolean accepted is the explicit\n // \\`smrtAuth\\` opt-in marker.\n const isResolvedPrincipal = (v: unknown) =>\n typeof v === 'object' && v !== null;\n return (\n isResolvedPrincipal(l.user) ||\n isResolvedPrincipal(l.session) ||\n l.smrtAuth === true\n );\n}\n\nfunction requireRouteAuth(locals: unknown, mutating: boolean): void {\n if (PUBLIC_ACCESS === true) return;\n if (PUBLIC_ACCESS === 'read' && !mutating) return;\n if (!hasAuthenticatedPrincipal(locals)) {\n throw error(401, 'Authentication required');\n }\n}\n\n// Sensitive-field-safe serialization for custom-action results (#1540): a\n// custom method may return a SmrtObject (or one nested in an array/plain\n// object), so recurse and route each through toPublicJSON() rather than letting\n// JSON.stringify call toJSON(). Non-plain instances (Date, etc.) and primitives\n// pass through; a cycle guard prevents infinite loops.\nfunction toPublicResult(value: any, seen: WeakSet<object> = new WeakSet()): any {\n if (value === null || typeof value !== 'object') return value;\n if (typeof value.toPublicJSON === 'function') return value.toPublicJSON();\n if (Array.isArray(value)) {\n if (seen.has(value)) return value;\n seen.add(value);\n return value.map((entry: any) => toPublicResult(entry, seen));\n }\n const proto = Object.getPrototypeOf(value);\n if (proto !== Object.prototype && proto !== null) return value;\n if (seen.has(value)) return value;\n seen.add(value);\n const out: Record<string, any> = {};\n for (const [key, entry] of Object.entries(value)) {\n out[key] = toPublicResult(entry, seen);\n }\n return out;\n}\n`;\n}\n\n/**\n * Whether an object is `@TenantScoped` (carries a `tenantScoped` config in its\n * `@smrt()`/`@TenantScoped()` decorator). Drives tenant-context establishment in\n * generated routes (#1540, facet 2).\n */\nfunction isTenantScoped(objectDef: SmartObjectDefinition): boolean {\n return !!objectDef.decoratorConfig?.tenantScoped;\n}\n\n/**\n * Emit the tenant-context establishment helper for `@TenantScoped` objects\n * (#1540, facet 2). Generated handlers call `establishTenantContext(locals)`\n * after the auth guard so every collection query runs inside the tenant context\n * derived from the authenticated principal — engaging the `@TenantScoped`\n * interceptors that auto-filter by tenant.\n *\n * Without this, an `optional`-mode scoped object queried over a generated route\n * with no active context returns rows from ALL tenants (the interceptor only\n * hard-fails `required` mode). We read the canonical `locals.tenantId` set by\n * the smrt-users auth hook (with `user`/`session` fallbacks). It is a no-op when\n * a context is already active (e.g. an upstream tenancy handle) or when the\n * principal carries no tenant (global/admin — preserving optional-mode global\n * access). Imported only for tenant-scoped routes, which already depend on\n * `@happyvertical/smrt-tenancy`.\n */\nfunction generateTenantContextHelper(): string {\n return `\nimport { enterTenantContext, hasTenantContext } from '@happyvertical/smrt-tenancy';\n\nfunction establishTenantContext(locals: unknown): void {\n if (hasTenantContext()) return;\n if (!locals || typeof locals !== 'object') return;\n const l = locals as Record<string, any>;\n const tenantId = l.tenantId ?? l.user?.tenantId ?? l.session?.tenantId;\n if (typeof tenantId === 'string' && tenantId) {\n enterTenantContext({ tenantId });\n }\n}\n`;\n}\n\n/**\n * The per-handler guard preamble: the fail-closed auth check (#1540 2c) plus, for\n * tenant-scoped objects, tenant-context establishment (#1540 facet 2).\n */\nfunction routeGuardPreamble(\n objectDef: SmartObjectDefinition,\n mutating: boolean,\n): string {\n const lines = [` requireRouteAuth(locals, ${mutating});`];\n if (isTenantScoped(objectDef)) {\n lines.push(' establishTenantContext(locals);');\n }\n return lines.join('\\n');\n}\n\nfunction normalizeApiHttpMethod(method?: string): ApiHttpMethod {\n switch (method?.toUpperCase()) {\n case 'GET':\n case 'POST':\n case 'PUT':\n case 'PATCH':\n case 'DELETE':\n return method.toUpperCase() as ApiHttpMethod;\n default:\n return 'POST';\n }\n}\n\n/**\n * Convert a camelCase / PascalCase method name to a kebab-case URL segment.\n * Examples:\n * discoverFromUrl -> discover-from-url\n * XMLExport -> xml-export\n * URL -> url\n * a1B2c3 -> a1-b2c3\n *\n * Known limitation: consecutive uppercase acronyms aren't split apart, e.g.\n * `HTMLAPIExport` becomes `htmlapi-export` rather than `html-api-export`.\n * Override with an explicit `api.routes[name].path` if you need a specific\n * segmentation.\n */\nexport function methodNameToKebab(name: string): string {\n return name\n .replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n .replace(/([A-Z]+)([A-Z][a-z])/g, '$1-$2')\n .toLowerCase();\n}\n\nfunction normalizeCustomRoutePath(\n actionName: string,\n path?: string,\n options: { kebabRoutes?: boolean } = {},\n): string[] {\n // Explicit path override always wins, and is used verbatim (split on /).\n if (path) {\n const segments = path\n .split('/')\n .map((segment) => segment.trim())\n .filter(Boolean);\n if (segments.length > 0) {\n return segments;\n }\n }\n\n const segment = options.kebabRoutes\n ? methodNameToKebab(actionName)\n : actionName;\n return [segment];\n}\n\nfunction extractRoutePathParamNames(pathSegments: string[]): string[] {\n return pathSegments\n .filter((segment) => /^\\[[^\\]]+\\]$/.test(segment))\n .map((segment) => segment.slice(1, -1))\n .filter(Boolean);\n}\n\nfunction resolveApiActionRouteConfig(\n actionName: string,\n actionDef: { isStatic?: boolean },\n apiConfig: unknown,\n routeOptions: { kebabRoutes?: boolean } = {},\n defaultScope: 'item' | 'collection' = actionDef.isStatic\n ? 'collection'\n : 'item',\n): ResolvedApiActionRouteConfig {\n const config = getApiConfigObject(apiConfig);\n const routeConfig: ApiCustomRouteConfig | undefined =\n config?.routes?.[actionName];\n\n const pathSegments = normalizeCustomRoutePath(\n actionName,\n routeConfig?.path,\n routeOptions,\n );\n\n return {\n scope: routeConfig?.scope || defaultScope,\n method: normalizeApiHttpMethod(routeConfig?.method),\n pathSegments,\n pathParamNames: extractRoutePathParamNames(pathSegments),\n };\n}\n\nfunction buildRouteHandlerArgs(\n includeParams: boolean,\n includeRequest: boolean,\n): string {\n // `locals` is always destructured so the fail-closed auth guard (#1540) can\n // inspect the authenticated principal.\n const args: string[] = ['locals'];\n\n if (includeParams) {\n args.push('params');\n }\n\n if (includeRequest) {\n args.push('request');\n }\n\n return `{ ${args.join(', ')} }`;\n}\n\nfunction buildPathParamsObjectLiteral(pathParamNames: string[]): string {\n if (pathParamNames.length === 0) {\n return '{}';\n }\n\n return `{\n${pathParamNames\n .map(\n (paramName) =>\n ` ${JSON.stringify(paramName)}: params[${JSON.stringify(paramName)}],`,\n )\n .join('\\n')}\n }`;\n}\n\nfunction buildActionInvocationArgs(actionDef: any): string[] {\n const parameters = Array.isArray(actionDef.parameters)\n ? actionDef.parameters\n : [];\n\n if (parameters.length === 0) {\n return [];\n }\n\n if (parameters.length === 1 && parameters[0]?.name === 'options') {\n return ['options'];\n }\n\n return parameters.map((parameter: any) =>\n buildOptionsPropertyAccess(parameter.name),\n );\n}\n\nfunction buildOptionsPropertyAccess(propertyName: string): string {\n if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(propertyName)) {\n return `options.${propertyName}`;\n }\n\n const escapedPropertyName = propertyName\n .replaceAll('\\\\', '\\\\\\\\')\n .replaceAll(\"'\", \"\\\\'\");\n\n return `options['${escapedPropertyName}']`;\n}\n\nfunction buildActionInvocationExpression(\n receiverExpression: string,\n actionName: string,\n invocationArgs: string[],\n): string {\n const singleLineInvocation = `await ${receiverExpression}.${actionName}(${invocationArgs.join(', ')})`;\n const singleLineResultAssignment = ` const result = ${singleLineInvocation};`;\n\n if (singleLineResultAssignment.length <= 100) {\n return singleLineInvocation;\n }\n\n return [\n `await ${receiverExpression}.${actionName}(`,\n ...invocationArgs.map((argument) => ` ${argument},`),\n ' )',\n ].join('\\n');\n}\n\nfunction findItemClassRegistryKey(\n className: string,\n objectDef: SmartObjectDefinition,\n manifest: SmartObjectManifest,\n): string {\n const itemClassName =\n objectDef.extendsTypeArg ||\n (className.endsWith('Collection')\n ? className.slice(0, -'Collection'.length)\n : undefined);\n\n if (!itemClassName) {\n return className;\n }\n\n const manifestMatch = Object.entries(manifest.objects).find(\n ([manifestKey, candidate]) =>\n manifestKey === itemClassName || candidate.className === itemClassName,\n );\n\n return manifestMatch?.[0] || itemClassName;\n}\n\nfunction groupCustomActionRoutes(\n actionSpecs: Array<{\n routeDir: string;\n spec: GeneratedActionRouteSpec;\n }>,\n): Map<string, GeneratedActionRouteSpec[]> {\n const groupedRoutes = new Map<string, GeneratedActionRouteSpec[]>();\n\n for (const { routeDir, spec } of actionSpecs) {\n const existing = groupedRoutes.get(routeDir) || [];\n const duplicateMethod = existing.find(\n (candidate) => candidate.routeConfig.method === spec.routeConfig.method,\n );\n\n if (duplicateMethod) {\n throw new Error(\n `Duplicate custom API route handler for ${routeDir} (${spec.routeConfig.method}). ` +\n `Methods ${duplicateMethod.actionName} and ${spec.actionName} resolve to the same generated route.`,\n );\n }\n\n existing.push(spec);\n groupedRoutes.set(routeDir, existing);\n }\n\n return groupedRoutes;\n}\n\n/**\n * Generates SvelteKit API routes from manifest\n */\nexport async function generateSvelteKitRoutes(\n projectRoot: string,\n manifest: SmartObjectManifest,\n options: SvelteKitOptions,\n): Promise<void> {\n if (!options.enabled) return;\n\n console.log('[smrt] Generating SvelteKit routes...');\n\n clearGeneratedRouteFiles(join(projectRoot, options.routesDir));\n clearGeneratedKnowledgeRoute(projectRoot, options);\n\n // Generate centralized configuration file first (if it doesn't exist)\n await generateSmrtConfigFile(projectRoot, manifest, options);\n\n let generatedCount = 0;\n let skippedCollections = 0;\n for (const [className, objectDef] of Object.entries(manifest.objects)) {\n if (isCollectionClass(objectDef)) {\n const generatedCollectionRoutes = await generateCollectionRoutesForObject(\n projectRoot,\n className,\n objectDef,\n manifest,\n options,\n );\n if (generatedCollectionRoutes) {\n generatedCount++;\n } else {\n console.log(\n `[smrt] Skipping ${className} - no collection API routes to generate`,\n );\n skippedCollections++;\n }\n continue;\n }\n await generateRoutesForObject(projectRoot, className, objectDef, options);\n generatedCount++;\n }\n\n if (options.knowledge?.api?.enabled) {\n generateKnowledgeRoute(projectRoot, options);\n }\n\n // Update .gitignore to exclude generated routes\n updateGitignore(projectRoot, options);\n\n const skippedMsg =\n skippedCollections > 0\n ? ` (skipped ${skippedCollections} collection classes)`\n : '';\n console.log(\n `[smrt] Generated routes for ${generatedCount} SMRT objects${skippedMsg}`,\n );\n}\n\nfunction clearGeneratedRouteFiles(routesRoot: string): void {\n if (!existsSync(routesRoot)) {\n return;\n }\n\n for (const entry of readdirSync(routesRoot, { withFileTypes: true })) {\n const entryPath = join(routesRoot, entry.name);\n\n if (entry.isDirectory()) {\n clearGeneratedRouteFiles(entryPath);\n continue;\n }\n\n if (!entry.isFile() || entry.name !== '+server.ts') {\n continue;\n }\n\n const fileContent = readFileSync(entryPath, 'utf-8');\n if (fileContent.startsWith(AUTO_GENERATED_ROUTE_HEADER)) {\n unlinkSync(entryPath);\n }\n }\n}\n\nfunction knowledgeRouteDir(projectRoot: string, options: SvelteKitOptions) {\n const basePath = options.knowledge?.api?.basePath || '/__smrt/knowledge';\n const routeRoot = svelteKitRouteRoot(options.routesDir);\n const segments = basePath\n .split('/')\n .map((segment) => segment.trim())\n .filter(Boolean);\n\n return join(projectRoot, routeRoot, ...segments);\n}\n\nfunction svelteKitRouteRoot(routesDir: string): string {\n const normalized = routesDir.replaceAll('\\\\', '/').replace(/\\/+$/, '');\n const marker = '/routes';\n const markerIndex = normalized.indexOf(marker);\n\n if (normalized === 'src/routes' || normalized.endsWith('/routes')) {\n return normalized;\n }\n if (markerIndex !== -1) {\n return normalized.slice(0, markerIndex + marker.length);\n }\n return 'src/routes';\n}\n\nfunction clearGeneratedKnowledgeRoute(\n projectRoot: string,\n options: SvelteKitOptions,\n): void {\n const routeDir = knowledgeRouteDir(projectRoot, options);\n const routePath = join(routeDir, '+server.ts');\n if (!existsSync(routePath)) return;\n\n const content = readFileSync(routePath, 'utf-8');\n if (content.startsWith(AUTO_GENERATED_ROUTE_HEADER)) {\n unlinkSync(routePath);\n }\n}\n\nfunction generateKnowledgeRoute(\n projectRoot: string,\n options: SvelteKitOptions,\n): void {\n const routeDir = knowledgeRouteDir(projectRoot, options);\n const route = generateKnowledgeRouteTemplate(\n options.knowledge ?? {},\n readKnowledgeRouteArtifact(projectRoot),\n );\n writeRoute(routeDir, '+server.ts', route);\n}\n\nfunction readKnowledgeRouteArtifact(\n projectRoot: string,\n): Record<string, any> | null {\n for (const relativePath of [\n '.smrt/smrt-knowledge.json',\n 'dist/smrt-knowledge.json',\n ]) {\n const fullPath = join(projectRoot, relativePath);\n if (!existsSync(fullPath)) continue;\n try {\n return JSON.parse(readFileSync(fullPath, 'utf-8'));\n } catch {\n return null;\n }\n }\n\n return null;\n}\n\n/**\n * Generates SMRT object registration file\n * This file imports all SMRT objects to trigger their @smrt() decorators\n */\nasync function generateRegistrationFile(\n projectRoot: string,\n manifest: SmartObjectManifest,\n options: SvelteKitOptions,\n): Promise<void> {\n const configPath = options.configPath || 'src/lib/server';\n const configDir = join(projectRoot, configPath);\n const registrationFilePath = join(configDir, 'smrt-register.ts');\n\n // Group objects by package for efficient imports\n const localObjects: Array<[string, (typeof manifest.objects)[string]]> = [];\n const packageObjects = new Map<\n string,\n { classNames: string[]; hasCollectionImport: boolean }\n >();\n\n for (const [className, objectDef] of Object.entries(manifest.objects)) {\n if (isLocalObject(projectRoot, objectDef)) {\n // Local object (source in project, not node_modules) - use $lib path\n localObjects.push([className, objectDef]);\n } else if (objectDef.packageName) {\n // External package - group by package name\n const packageEntry = packageObjects.get(objectDef.packageName) || {\n classNames: [],\n hasCollectionImport: false,\n };\n\n if (isCollectionClass(objectDef)) {\n packageEntry.hasCollectionImport = true;\n } else {\n packageEntry.classNames.push(className);\n }\n\n packageObjects.set(objectDef.packageName, packageEntry);\n } else {\n // No package name and not local - treat as local fallback\n localObjects.push([className, objectDef]);\n }\n }\n\n // Generate imports for local objects\n // Issue #870: Extract simple class names from qualified names\n const localNamedImports = new Map<string, string[]>();\n const localSideEffectImports = new Set<string>();\n\n for (const [className, objectDef] of localObjects) {\n const simpleClassName = extractSimpleClassName(className);\n\n // Calculate direct relative path from the configDir where smrt-register.ts lives\n // to the actual source file of the object.\n let importPath = '';\n if (objectDef.filePath) {\n const relativeToConfig = relative(configDir, objectDef.filePath);\n const normalized = relativeToConfig\n .replace(/\\\\/g, '/')\n .replace(/\\.(ts|js|tsx|jsx)$/, '');\n importPath = normalized.startsWith('.') ? normalized : `./${normalized}`;\n } else {\n // Fallback for missing file paths\n importPath = getSvelteKitImportPath(\n projectRoot,\n undefined,\n options.objectsDir,\n simpleClassName,\n );\n }\n\n if (isCollectionClass(objectDef)) {\n localSideEffectImports.add(importPath);\n continue;\n }\n\n const existing = localNamedImports.get(importPath) ?? [];\n existing.push(simpleClassName);\n localNamedImports.set(importPath, existing);\n }\n\n const localImports = [\n ...Array.from(localNamedImports.entries())\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([importPath, simpleNames]) => {\n const sortedNames = simpleNames.sort((a, b) => a.localeCompare(b));\n return `import { ${sortedNames.join(', ')} } from '${importPath}';`;\n }),\n ...Array.from(localSideEffectImports.values())\n .sort((a, b) => a.localeCompare(b))\n .map((importPath) => `import '${importPath}';`),\n ].join('\\n');\n\n // Generate imports for external packages\n // Issue #870: Extract simple class names from qualified names\n const packageImports = Array.from(packageObjects.entries())\n .sort(([left], [right]) => left.localeCompare(right))\n .flatMap(([packageName, packageEntry]) => {\n const imports: string[] = [];\n\n if (packageEntry.hasCollectionImport) {\n imports.push(`import '${packageName}';`);\n }\n\n if (packageEntry.classNames.length > 0) {\n // Extract simple class names for valid import syntax\n const simpleNames = packageEntry.classNames\n .map(extractSimpleClassName)\n .sort((a, b) => a.localeCompare(b));\n imports.push(\n `import { ${simpleNames.join(', ')} } from '${packageName}';`,\n );\n }\n\n return imports;\n })\n .join('\\n');\n\n const imports = [packageImports, localImports].filter(Boolean).join('\\n');\n const registrations = Object.entries(manifest.objects)\n .map(([className, objectDef]) => {\n if (isCollectionClass(objectDef)) {\n // Importing the collection class is enough to trigger its decorator.\n // Explicit package-qualified re-registration only applies to object\n // classes, because ObjectRegistry.register() is object-only.\n return null;\n }\n\n const simpleClassName = extractSimpleClassName(className);\n const localObject = isLocalObject(projectRoot, objectDef);\n const packageName = getRegistrationPackageName(\n manifest,\n objectDef,\n localObject,\n );\n\n if (!packageName) {\n return null;\n }\n\n const packageNameLiteral = toSingleQuotedStringLiteral(packageName);\n const singleLineRegistration = `ObjectRegistry.register(${simpleClassName}, { name: '${simpleClassName}', packageName: ${packageNameLiteral} });`;\n\n if (singleLineRegistration.length <= BIOME_LINE_WIDTH) {\n return singleLineRegistration;\n }\n\n return [\n `ObjectRegistry.register(${simpleClassName}, {`,\n ` name: '${simpleClassName}',`,\n ` packageName: ${packageNameLiteral},`,\n `});`,\n ].join('\\n');\n })\n .filter((registration): registration is string => registration !== null)\n .join('\\n');\n\n const registrationContent = `/**\n * Auto-generated SMRT object registration\n * DO NOT EDIT - changes will be overwritten\n *\n * Importing these modules triggers their @smrt() decorators, which perform\n * the initial registration. The explicit re-registration below is intentional:\n * it upgrades bundled runtimes to deterministic qualified registrations.\n */\n\nimport { ObjectRegistry } from '@happyvertical/smrt-core';\n\n${imports}\n\n// Re-register imported objects with explicit package names for bundled runtimes\n${registrations}\n`;\n\n // Create directory if it doesn't exist\n if (!existsSync(configDir)) {\n mkdirSync(configDir, { recursive: true });\n }\n\n writeFileSync(registrationFilePath, registrationContent, 'utf-8');\n console.log(`[smrt] Generated registration file: ${registrationFilePath}`);\n}\n\n/**\n * Generates centralized SMRT configuration file\n * Only creates if file doesn't exist (preserves user customizations)\n */\nasync function generateSmrtConfigFile(\n projectRoot: string,\n manifest: SmartObjectManifest,\n options: SvelteKitOptions,\n): Promise<void> {\n const configPath = options.configPath || 'src/lib/server';\n const configFileName = options.configFileName || 'smrt.ts';\n const configDir = join(projectRoot, configPath);\n const configFilePath = join(configDir, configFileName);\n\n // Always generate registration file (it gets overwritten)\n await generateRegistrationFile(projectRoot, manifest, options);\n\n // Don't overwrite existing config file\n if (existsSync(configFilePath)) {\n console.log('[smrt] Config file already exists, skipping generation');\n return;\n }\n\n const configContent = `/**\n * Centralized SMRT configuration with per-object overrides\n * Generated by @smrt/core vite plugin\n *\n * Most objects will use the default configuration.\n * Add entries to \\`objectOverrides\\` for objects that need different backends.\n */\n\n// Import SMRT objects to register them via @smrt() decorators\nimport './smrt-register.js';\n\nimport { ObjectRegistry } from '@happyvertical/smrt-core';\nimport type { SmrtClassOptions } from '@happyvertical/smrt-core';\n\ndeclare global {\n // eslint-disable-next-line no-var\n var __smrtGetRequestScopedDatabase:\n | (() => SmrtClassOptions['db'] | undefined)\n | undefined;\n}\n\n/**\n * Per-object configuration overrides\n * Define specific backends for objects that differ from project defaults\n *\n * @example\n * const objectOverrides: Record<string, Partial<SmrtClassOptions>> = {\n * // Analytics uses a separate PostgreSQL database\n * Analytics: {\n * db: {\n * url: process.env.ANALYTICS_DATABASE_URL!,\n * type: 'postgres'\n * }\n * },\n *\n * // AuditLog uses dedicated database with no AI\n * AuditLog: {\n * db: {\n * url: process.env.AUDIT_DATABASE_URL!,\n * type: 'postgres'\n * },\n * ai: undefined\n * },\n *\n * // Cache uses REST adapter (e.g., Redis)\n * Cache: {\n * persistence: {\n * type: 'rest',\n * baseUrl: process.env.REDIS_URL!\n * }\n * }\n * };\n */\nconst objectOverrides: Record<string, Partial<SmrtClassOptions>> = {\n // Add your per-object configuration overrides here\n};\n\n/**\n * Default configuration for most SMRT objects\n * Customize this to change project-wide defaults\n */\nfunction getDefaultConfig(): SmrtClassOptions {\n return {\n db: {\n url: process.env.DATABASE_URL || ':memory:',\n type: (process.env.DATABASE_TYPE as 'sqlite' | 'postgres') || 'sqlite'\n },\n ai: process.env.OPENAI_API_KEY ? {\n type: 'openai',\n apiKey: process.env.OPENAI_API_KEY\n } : process.env.ANTHROPIC_API_KEY ? {\n type: 'anthropic',\n apiKey: process.env.ANTHROPIC_API_KEY\n } : undefined\n };\n}\n\nfunction getRequestScopedDatabase(): SmrtClassOptions['db'] | undefined {\n const getter = globalThis.__smrtGetRequestScopedDatabase;\n return typeof getter === 'function' ? getter() : undefined;\n}\n\n/**\n * Get configuration for a specific SMRT object\n * Merges project defaults with per-object overrides if defined\n */\nexport function getSmrtConfig(className: string): SmrtClassOptions {\n const defaults = getDefaultConfig();\n const override = objectOverrides[className];\n\n if (override) {\n // Deep merge: override specific properties while keeping defaults\n return {\n ...defaults,\n ...override,\n // Ensure nested objects are merged properly\n db: override.db\n ? { ...(defaults.db as any), ...(override.db as any) }\n : defaults.db,\n ai: override.ai !== undefined ? override.ai : defaults.ai\n };\n }\n\n return defaults;\n}\n\n/**\n * Helper to get a collection with centralized configuration\n * Automatically applies project defaults or object-specific overrides\n */\nexport async function getCollection<\n T extends import('@happyvertical/smrt-core').SmrtObject,\n>(className: string, overrides: Partial<SmrtClassOptions> = {}) {\n const config = getSmrtConfig(className);\n const objectOverride = objectOverrides[className];\n const requestScopedDb =\n !overrides.db && !objectOverride?.db\n ? getRequestScopedDatabase()\n : undefined;\n\n return await ObjectRegistry.getCollection<T>(\n className,\n {\n ...config,\n ...overrides,\n db: overrides.db\n ? { ...(config.db as any), ...(overrides.db as any) }\n : requestScopedDb ?? config.db,\n ai: overrides.ai !== undefined ? overrides.ai : config.ai\n }\n );\n}\n`;\n\n // Create directory if it doesn't exist\n if (!existsSync(configDir)) {\n mkdirSync(configDir, { recursive: true });\n }\n\n writeFileSync(configFilePath, configContent, 'utf-8');\n console.log(`[smrt] Generated configuration file: ${configFilePath}`);\n}\n\n/**\n * Generates route files for a single SMRT object\n */\nasync function generateRoutesForObject(\n projectRoot: string,\n className: string,\n objectDef: SmartObjectDefinition,\n options: SvelteKitOptions,\n): Promise<void> {\n const collectionName = objectDef.collection;\n const routeDir = join(projectRoot, options.routesDir, collectionName);\n\n // Check if API is enabled for this object\n const apiConfig = objectDef.decoratorConfig?.api;\n if (apiConfig === false) {\n console.log(`[smrt] Skipping ${className} - API disabled`);\n return;\n }\n\n // Determine which CRUD actions to include via the shared resolver.\n const includedActions = resolveStandardCrudActions(apiConfig);\n\n // Generate collection route (list, create)\n if (includedActions.includes('list') || includedActions.includes('create')) {\n const collectionRoute = generateCollectionRouteTemplate(\n projectRoot,\n className,\n objectDef,\n includedActions,\n options,\n );\n writeRoute(routeDir, '+server.ts', collectionRoute);\n }\n\n // Generate item route (get, update, delete)\n if (\n includedActions.includes('get') ||\n includedActions.includes('update') ||\n includedActions.includes('delete')\n ) {\n const itemRoute = generateItemRouteTemplate(\n projectRoot,\n className,\n objectDef,\n includedActions,\n options,\n );\n writeRoute(join(routeDir, '[id]'), '+server.ts', itemRoute);\n }\n\n // Generate custom action routes\n const customActions = Object.entries(objectDef.methods).filter(\n ([name, method]) =>\n !STANDARD_API_ACTIONS.includes(name) &&\n method.isPublic &&\n shouldIncludeInApi(name, apiConfig),\n );\n\n const actionSpecs: Array<{\n routeDir: string;\n spec: GeneratedActionRouteSpec;\n }> = [];\n\n for (const [actionName, actionDef] of customActions) {\n const routeConfig = resolveApiActionRouteConfig(\n actionName,\n actionDef,\n apiConfig,\n { kebabRoutes: options.kebabRoutes },\n );\n\n if (routeConfig.scope === 'collection' && !actionDef.isStatic) {\n console.warn(\n `[smrt] Skipping ${className}.${actionName} - collection API routes require a static method`,\n );\n continue;\n }\n\n const actionBaseDir =\n routeConfig.scope === 'collection' ? routeDir : join(routeDir, '[id]');\n actionSpecs.push({\n routeDir: join(actionBaseDir, ...routeConfig.pathSegments),\n spec: {\n lookupClassName: className,\n actionName,\n actionDef,\n routeConfig,\n hostType: 'item',\n },\n });\n }\n\n for (const [actionRouteDir, routeSpecs] of groupCustomActionRoutes(\n actionSpecs,\n )) {\n const actionRoute = generateActionRouteTemplate(\n projectRoot,\n routeSpecs,\n objectDef,\n options,\n );\n writeRoute(actionRouteDir, '+server.ts', actionRoute);\n }\n}\n\nasync function generateCollectionRoutesForObject(\n projectRoot: string,\n className: string,\n objectDef: SmartObjectDefinition,\n manifest: SmartObjectManifest,\n options: SvelteKitOptions,\n): Promise<boolean> {\n const apiConfig = objectDef.decoratorConfig?.api;\n if (apiConfig === false) {\n console.log(`[smrt] Skipping ${className} - API disabled`);\n return false;\n }\n\n const routeDir = join(projectRoot, options.routesDir, objectDef.collection);\n const lookupClassName = findItemClassRegistryKey(\n className,\n objectDef,\n manifest,\n );\n\n const customActions = Object.entries(objectDef.methods).filter(\n ([name, method]) =>\n !STANDARD_API_ACTIONS.includes(name) &&\n method.isPublic &&\n shouldIncludeInApi(name, apiConfig),\n );\n\n if (customActions.length === 0) {\n return false;\n }\n\n let generatedAnyRoutes = false;\n const actionSpecs: Array<{\n routeDir: string;\n spec: GeneratedActionRouteSpec;\n }> = [];\n\n for (const [actionName, actionDef] of customActions) {\n const routeConfig = resolveApiActionRouteConfig(\n actionName,\n actionDef,\n apiConfig,\n { kebabRoutes: options.kebabRoutes },\n 'collection',\n );\n\n if (routeConfig.scope !== 'collection') {\n console.warn(\n `[smrt] Skipping ${className}.${actionName} - collection class methods only support collection-scoped API routes`,\n );\n continue;\n }\n\n actionSpecs.push({\n routeDir: join(routeDir, ...routeConfig.pathSegments),\n spec: {\n lookupClassName,\n actionName,\n actionDef,\n routeConfig,\n hostType: 'collection',\n },\n });\n }\n\n for (const [actionRouteDir, routeSpecs] of groupCustomActionRoutes(\n actionSpecs,\n )) {\n const actionRoute = generateActionRouteTemplate(\n projectRoot,\n routeSpecs,\n objectDef,\n options,\n );\n writeRoute(actionRouteDir, '+server.ts', actionRoute);\n generatedAnyRoutes = true;\n }\n\n return generatedAnyRoutes;\n}\n\n/**\n * Resolve the list of standard CRUD actions exposed by the API for a given\n * apiConfig. Single source of truth for both the route generator and the\n * cli↔api coherence lint.\n */\nfunction resolveStandardCrudActions(apiConfig: unknown): string[] {\n if (apiConfig === false) return [];\n if (apiConfig === true || apiConfig === undefined) {\n return [...STANDARD_API_ACTIONS];\n }\n if (typeof apiConfig !== 'object') return [...STANDARD_API_ACTIONS];\n\n const config = apiConfig as { include?: string[]; exclude?: string[] };\n let crud: string[] = config.include\n ? config.include.filter((a) => STANDARD_API_ACTIONS.includes(a))\n : [...STANDARD_API_ACTIONS];\n if (Array.isArray(config.exclude)) {\n const exclude = config.exclude;\n crud = crud.filter((a) => !exclude.includes(a));\n }\n return crud;\n}\n\n/**\n * Check if a custom action should be included in API.\n *\n * Mirrors the CRUD inclusion path: intersect with `include` (when set), then\n * subtract `exclude`. Both filters apply together, matching principle of least\n * surprise for users supplying both lists.\n */\nfunction shouldIncludeInApi(actionName: string, apiConfig: any): boolean {\n if (apiConfig === false) return false;\n if (apiConfig === true || apiConfig === undefined) return true;\n\n if (typeof apiConfig === 'object') {\n const included = apiConfig.include\n ? apiConfig.include.includes(actionName)\n : true;\n const excluded = apiConfig.exclude\n ? apiConfig.exclude.includes(actionName)\n : false;\n return included && !excluded;\n }\n\n return true;\n}\n\n/**\n * Compute the set of action names (standard CRUD + custom methods) that the\n * API exposes for a given object definition. This is the same resolution used\n * to drive route generation, exposed so coherence checks (e.g. CLI vs API)\n * can ask \"what does the API expose?\" without re-implementing the logic.\n */\nexport function resolveApiActionSet(\n objectDef: SmartObjectDefinition,\n): Set<string> {\n const apiConfig = objectDef.decoratorConfig?.api;\n if (apiConfig === false) return new Set();\n\n const actions = new Set<string>(resolveStandardCrudActions(apiConfig));\n const objectIsCollectionClass = isCollectionClass(objectDef);\n const config = getApiConfigObject(apiConfig);\n\n // Custom (non-CRUD, public) methods. We mirror BOTH the include/exclude\n // filter AND the scope/static skip rules that the route generators apply\n // (sveltekit-generator.ts generateRoutesForObject and\n // generateCollectionRoutesForObject). Otherwise the cli↔api coherence lint\n // would claim \"reachable via API\" for methods that produce no HTTP route.\n for (const [name, method] of Object.entries(objectDef.methods || {})) {\n if (STANDARD_API_ACTIONS.includes(name)) continue;\n if (!method.isPublic) continue;\n if (!shouldIncludeInApi(name, apiConfig)) continue;\n\n const routeConfig: ApiCustomRouteConfig | undefined =\n config?.routes?.[name];\n const defaultScope: 'item' | 'collection' = objectIsCollectionClass\n ? 'collection'\n : method.isStatic\n ? 'collection'\n : 'item';\n const scope = routeConfig?.scope || defaultScope;\n\n if (objectIsCollectionClass) {\n // Collection classes only emit collection-scoped custom routes.\n if (scope !== 'collection') continue;\n } else {\n // Non-collection classes skip collection-scoped non-static methods\n // (the generator emits a console warning in this case).\n if (scope === 'collection' && !method.isStatic) continue;\n }\n\n actions.add(name);\n }\n\n return actions;\n}\n\n/**\n * Detail for a single cli-vs-api coherence violation.\n */\nexport interface CliApiCoherenceViolation {\n className: string;\n unreachable: string[];\n}\n\n/**\n * Inspect a manifest and return classes whose `cli.include` references\n * methods not exposed via the API. Classes that opt out via\n * `cli: { skipApiCheck: true }` are skipped.\n *\n * Throws nothing; returns the violation list so callers can choose to throw\n * or warn.\n */\nexport function findCliApiCoherenceViolations(\n manifest: SmartObjectManifest,\n): CliApiCoherenceViolation[] {\n const violations: CliApiCoherenceViolation[] = [];\n\n for (const [className, objectDef] of Object.entries(manifest.objects)) {\n const cliConfig = objectDef.decoratorConfig?.cli;\n if (!cliConfig || typeof cliConfig !== 'object') continue;\n if (cliConfig.skipApiCheck) continue;\n if (!cliConfig.include || cliConfig.include.length === 0) continue;\n\n // Match generateCLIModule's effective command set: include − exclude.\n // A command in both lists is not actually registered, so the lint must\n // not flag it as unreachable.\n const cliExclude = Array.isArray(cliConfig.exclude)\n ? cliConfig.exclude\n : [];\n const effectiveCliCommands = cliConfig.include.filter(\n (cmd: string) => !cliExclude.includes(cmd),\n );\n if (effectiveCliCommands.length === 0) continue;\n\n const apiActionSet = resolveApiActionSet(objectDef);\n const unreachable = effectiveCliCommands.filter(\n (action: string) => !apiActionSet.has(action),\n );\n\n if (unreachable.length > 0) {\n violations.push({ className, unreachable });\n }\n }\n\n return violations;\n}\n\n/**\n * Throw if any class in the manifest has `cli.include` methods that aren't\n * reachable via the API. Default build-time gate; opt-out per-class via\n * `cli: { skipApiCheck: true }` (or globally via the vite plugin option\n * `validateCliApiCoherence: false`).\n */\nexport function validateCliIncludeAgainstApi(\n manifest: SmartObjectManifest,\n): void {\n const violations = findCliApiCoherenceViolations(manifest);\n if (violations.length === 0) return;\n\n const messages = violations.flatMap(({ className, unreachable }) =>\n unreachable.map(\n (action) =>\n `[smrt] ${className}.${action} is declared in cli.include but is not exposed via the api.\\n` +\n ` Either:\\n` +\n ` - Add '${action}' to api.include, or\\n` +\n ` - Remove '${action}' from cli.include.\\n` +\n ` The CLI invokes methods over HTTP; methods without API routes are unreachable.\\n` +\n ` If this CLI is intentionally invoked in-process (no HTTP), set\\n` +\n ` \\`cli: { skipApiCheck: true }\\` on the @smrt() decorator to acknowledge.`,\n ),\n );\n\n throw new Error(messages.join('\\n\\n'));\n}\n\n/**\n * Writes a route file, creating directories as needed\n */\nfunction writeRoute(dir: string, filename: string, content: string): void {\n try {\n // Create directory if needed\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n // Write the file (writeFileSync is synchronous and will throw on failure)\n const filePath = join(dir, filename);\n writeFileSync(filePath, content, 'utf-8');\n console.log(`[smrt] Generated: ${filePath}`);\n } catch (error) {\n console.error(`[smrt] [ERROR] Failed to write route file:`);\n console.error(`[smrt] [ERROR] Directory: ${dir}`);\n console.error(`[smrt] [ERROR] Filename: ${filename}`);\n console.error(`[smrt] [ERROR] Error:`, error);\n throw error;\n }\n}\n\n/**\n * Converts absolute file path to SvelteKit $lib alias import\n * For SvelteKit projects, uses $lib alias for better module resolution\n */\nfunction getSvelteKitImportPath(\n projectRoot: string,\n objectFilePath: string | undefined,\n objectsDir: string,\n className?: string,\n): string {\n // Handle undefined filePath by generating a default path\n // This allows tests to work without providing explicit file paths\n const filePath =\n objectFilePath ||\n join(projectRoot, objectsDir, `${className || 'Object'}.ts`);\n\n // Convert objectsDir to absolute path if it's relative\n const absoluteObjectsDir = objectsDir.startsWith('/')\n ? objectsDir\n : join(projectRoot, objectsDir);\n\n // Get the relative path from objectsDir to the file\n const relativePath = relative(absoluteObjectsDir, filePath);\n\n // Convert to forward slashes and remove extension\n const normalizedPath = relativePath.replace(/\\\\/g, '/');\n const withoutExtension = normalizedPath.replace(/\\.(ts|js|tsx|jsx)$/, '');\n\n // If objectsDir is under src/lib, use $lib alias\n if (objectsDir.includes('src/lib')) {\n const libSubpath = objectsDir.split('src/lib')[1] || '';\n const fullPath = libSubpath\n ? `${libSubpath}/${withoutExtension}`\n : withoutExtension;\n return `$lib${fullPath}`.replace(/\\/+/g, '/'); // Clean up double slashes\n }\n\n // Otherwise use relative path (fallback for non-standard layouts)\n return withoutExtension.startsWith('.')\n ? withoutExtension\n : `./${withoutExtension}`;\n}\n\n/**\n * Check if an object's source file is local to the project (not in node_modules).\n * The scanner sets packageName for all objects (including local ones from the\n * project's own package.json), so we check the filePath to distinguish.\n */\nfunction isLocalObject(\n projectRoot: string,\n objectDef: SmartObjectDefinition,\n): boolean {\n if (!objectDef.filePath) return false;\n return (\n objectDef.filePath.startsWith(projectRoot) &&\n !objectDef.filePath.includes('/node_modules/')\n );\n}\n\n/**\n * Generates collection route template (GET list, POST create)\n */\nfunction generateCollectionRouteTemplate(\n _projectRoot: string,\n className: string,\n objectDef: SmartObjectDefinition,\n includedActions: string[],\n _options: SvelteKitOptions,\n): string {\n const hasGet = includedActions.includes('list');\n const hasPost = includedActions.includes('create');\n const serializers = resolveStandardRouteSerializers(\n objectDef.decoratorConfig?.api,\n );\n const serializerImports = serializers.importStatements.join('\\n');\n\n const imports = `${AUTO_GENERATED_ROUTE_HEADER}\n// DO NOT EDIT - changes will be overwritten\n\nimport { error, json } from '@sveltejs/kit';\n${\n serializerImports ? `${serializerImports}\\n` : ''\n}import { getCollection } from '$lib/server/smrt';\nimport type { RequestHandler } from './$types';\n// Note: ${className} is auto-registered by the Vite plugin scanner\n${generateAuthGuardHelper(objectDef)}${isTenantScoped(objectDef) ? generateTenantContextHelper() : ''}${hasPost ? generateWritablePolicyHelper(objectDef) : ''}`;\n\n const getHandler = hasGet\n ? `\n// List all ${className.toLowerCase()}s\nexport const GET: RequestHandler = async ({ locals, url }) => {\n${routeGuardPreamble(objectDef, false)}\n const limit = Number(url.searchParams.get('limit')) || 50;\n const offset = Number(url.searchParams.get('offset')) || 0;\n\n${generateCollectionLoad(className)}\n const items = await collection.list({ limit, offset });\n const count = await collection.count();\n${\n serializers.listItemSerializerName\n ? `\n const serializedItems = await Promise.all(\n items.map((item) => ${serializers.listItemSerializerName}(item)),\n );\n\n return json({ items: serializedItems, count, limit, offset });`\n : `\n const items_public = items.map((item) => item.toPublicJSON());\n return json({ items: items_public, count, limit, offset });`\n}\n};\n`\n : '';\n\n const postHandler = hasPost\n ? `\n// Create new ${className.toLowerCase()}\nexport const POST: RequestHandler = async ({ locals, request }) => {\n${routeGuardPreamble(objectDef, true)}\n const data = applyWritablePolicy(await request.json());\n\n${generateCollectionLoad(className)}\n const item = await collection.create(data);\n await item.save();\n${\n serializers.itemSerializerName\n ? `\n const serializedItem = await ${serializers.itemSerializerName}(item);\n\n return json(serializedItem, { status: 201 });`\n : `\n return json(item.toPublicJSON(), { status: 201 });`\n}\n};\n`\n : '';\n\n return imports + getHandler + postHandler;\n}\n\nfunction generateCollectionLoad(\n className: string,\n options: { generic?: boolean } = {},\n): string {\n const genericSuffix = options.generic ? '<any>' : '';\n\n return [\n ` const collection = await getCollection${genericSuffix}(`,\n ` '${className}',`,\n ' );',\n ].join('\\n');\n}\n\nfunction generateNotFoundError(className: string): string {\n const singleLineNotFoundError = ` if (!item) throw error(404, '${className} not found');`;\n\n if (singleLineNotFoundError.length <= 100) {\n return singleLineNotFoundError;\n }\n\n return [\n ' if (!item)',\n ' throw error(',\n ' 404,',\n ` '${className} not found',`,\n ' );',\n ].join('\\n');\n}\n\nfunction generateCollectionNotRegisteredError(className: string): string {\n return [\n ' if (!collection)',\n ' throw error(',\n ' 500,',\n ` '${className} collection is not registered',`,\n ' );',\n ].join('\\n');\n}\n\nfunction generateClassNotRegisteredError(className: string): string {\n return [\n ' if (!registered)',\n ' throw error(',\n ' 500,',\n ` '${className} is not registered',`,\n ' );',\n ].join('\\n');\n}\n\n/**\n * Generates item route template (GET, PUT, DELETE)\n */\nfunction generateItemRouteTemplate(\n _projectRoot: string,\n className: string,\n objectDef: SmartObjectDefinition,\n includedActions: string[],\n _options: SvelteKitOptions,\n): string {\n const hasGet = includedActions.includes('get');\n const hasPut = includedActions.includes('update');\n const hasDelete = includedActions.includes('delete');\n const simpleClassName = extractSimpleClassName(className);\n const serializers = resolveStandardRouteSerializers(\n objectDef.decoratorConfig?.api,\n );\n const serializerImports = serializers.importStatements.join('\\n');\n\n const imports = `${AUTO_GENERATED_ROUTE_HEADER}\n// DO NOT EDIT - changes will be overwritten\n\nimport { error, json } from '@sveltejs/kit';\n${serializerImports ? `${serializerImports}\\n` : ''}import { getCollection } from '$lib/server/smrt';\nimport type { RequestHandler } from './$types';\n${generateAuthGuardHelper(objectDef)}${isTenantScoped(objectDef) ? generateTenantContextHelper() : ''}${hasPut ? generateWritablePolicyHelper(objectDef) : ''}`;\n\n const getHandler = hasGet\n ? `\n// Get single ${simpleClassName.toLowerCase()}\nexport const GET: RequestHandler = async ({ locals, params }) => {\n${routeGuardPreamble(objectDef, false)}\n${generateCollectionLoad(className, { generic: true })}\n const item = await collection.get(params.id);\n${generateNotFoundError(className)}\n${\n serializers.itemSerializerName\n ? `\n const serializedItem = await ${serializers.itemSerializerName}(item);\n\n return json(serializedItem);`\n : `\n return json(item.toPublicJSON());`\n}\n};\n`\n : '';\n\n const putHandler = hasPut\n ? `\n// Update ${simpleClassName.toLowerCase()}\nexport const PUT: RequestHandler = async ({ locals, params, request }) => {\n${routeGuardPreamble(objectDef, true)}\n${generateCollectionLoad(className, { generic: true })}\n const item = await collection.get(params.id);\n${generateNotFoundError(className)}\n\n const data = applyWritablePolicy(await request.json());\n Object.assign(item, data);\n await item.save();\n${\n serializers.itemSerializerName\n ? `\n const serializedItem = await ${serializers.itemSerializerName}(item);\n\n return json(serializedItem);`\n : `\n return json(item.toPublicJSON());`\n}\n};\n`\n : '';\n\n const deleteHandler = hasDelete\n ? `\n// Delete ${simpleClassName.toLowerCase()}\nexport const DELETE: RequestHandler = async ({ locals, params }) => {\n${routeGuardPreamble(objectDef, true)}\n${generateCollectionLoad(className, { generic: true })}\n const item = await collection.get(params.id);\n${generateNotFoundError(className)}\n\n await item.delete();\n return json({ success: true });\n};\n`\n : '';\n\n return imports + getHandler + putHandler + deleteHandler;\n}\n\n/**\n * Generates custom action route template\n */\nfunction generateActionRouteTemplate(\n _projectRoot: string,\n routeSpecs: GeneratedActionRouteSpec[],\n objectDef: SmartObjectDefinition,\n _options: SvelteKitOptions,\n): string {\n if (routeSpecs.length === 0) {\n throw new Error('Cannot generate a custom action route without handlers');\n }\n\n const [firstSpec] = routeSpecs;\n const { lookupClassName, routeConfig, hostType } = firstSpec;\n\n const hasMixedHosts = routeSpecs.some(\n (spec) =>\n spec.hostType !== hostType ||\n spec.lookupClassName !== lookupClassName ||\n spec.routeConfig.scope !== routeConfig.scope,\n );\n\n if (hasMixedHosts) {\n throw new Error(\n `Cannot generate mixed custom route handlers for ${lookupClassName}. ` +\n 'All handlers sharing a route path must target the same host type and scope.',\n );\n }\n\n const importBlock =\n hostType === 'collection'\n ? `import { error, json } from '@sveltejs/kit';\nimport { getCollection } from '$lib/server/smrt';\nimport type { RequestHandler } from './$types';`\n : routeConfig.scope === 'collection'\n ? `import { error, json } from '@sveltejs/kit';\nimport { ObjectRegistry } from '@happyvertical/smrt-core';\nimport type { RequestHandler } from './$types';`\n : `import { error, json } from '@sveltejs/kit';\nimport { getCollection } from '$lib/server/smrt';\nimport type { RequestHandler } from './$types';`;\n\n const tenantScoped = isTenantScoped(objectDef);\n const handlers = routeSpecs\n .map((spec) =>\n generateActionRouteHandler(\n spec.lookupClassName,\n spec.actionName,\n spec.actionDef,\n spec.routeConfig,\n spec.hostType,\n tenantScoped,\n ),\n )\n .join('\\n');\n\n return `${AUTO_GENERATED_ROUTE_HEADER}\n// DO NOT EDIT - changes will be overwritten\n\n${importBlock}\n${generateAuthGuardHelper(objectDef)}${tenantScoped ? generateTenantContextHelper() : ''}\n${handlers}`;\n}\n\nfunction generateActionRouteHandler(\n lookupClassName: string,\n actionName: string,\n actionDef: any,\n routeConfig: ResolvedApiActionRouteConfig,\n hostType: 'item' | 'collection',\n tenantScoped: boolean,\n): string {\n const handlerName = routeConfig.method;\n // Mutating verbs require auth even when reads are public (#1540). Tenant-scoped\n // objects also establish tenant context so the action runs filtered.\n const guardLines = [\n ` requireRouteAuth(locals, ${routeConfig.method !== 'GET'});`,\n ];\n if (tenantScoped) {\n guardLines.push(' establishTenantContext(locals);');\n }\n const authGuardLine = guardLines.join('\\n');\n const hasInput = actionDef.parameters.length > 0;\n const needsRequest = hasInput;\n const invocationArgs = buildActionInvocationArgs(actionDef);\n const hasPathParams = routeConfig.pathParamNames.length > 0;\n const pathParamsObjectLiteral = buildPathParamsObjectLiteral(\n routeConfig.pathParamNames,\n );\n const optionsLoad =\n hasInput && routeConfig.method === 'GET'\n ? hasPathParams\n ? [\n ` const pathParams = ${pathParamsObjectLiteral};`,\n ' const options = {',\n ' ...Object.fromEntries(new URL(request.url).searchParams.entries()),',\n ' ...pathParams,',\n ' };',\n '',\n ].join('\\n')\n : [\n ' const options = Object.fromEntries(',\n ' new URL(request.url).searchParams.entries(),',\n ' );',\n '',\n ].join('\\n')\n : hasInput\n ? hasPathParams\n ? [\n ` const pathParams = ${pathParamsObjectLiteral};`,\n ' const options = {',\n ' ...(await request.json()),',\n ' ...pathParams,',\n ' };',\n '',\n ].join('\\n')\n : ' const options = await request.json();\\n'\n : '';\n const collectionHandlerArgs = buildRouteHandlerArgs(\n hasPathParams,\n needsRequest,\n );\n const itemHandlerArgs = buildRouteHandlerArgs(true, needsRequest);\n\n if (hostType === 'collection') {\n return `// Custom collection method: ${actionName}\nexport const ${handlerName}: RequestHandler = async (${collectionHandlerArgs}) => {\n${authGuardLine}\n${generateCollectionLoad(lookupClassName, { generic: true })}\n const typedCollection = collection as any;\n${generateCollectionNotRegisteredError(lookupClassName)}\n\n${optionsLoad} const result = ${buildActionInvocationExpression(\n actionDef.isStatic\n ? '(typedCollection.constructor as any)'\n : 'typedCollection',\n actionName,\n invocationArgs,\n )};\n\n return json({ action: '${actionName}', result: toPublicResult(result) });\n};\n`;\n }\n\n if (routeConfig.scope === 'collection') {\n return `// Custom collection action: ${actionName}\nexport const ${handlerName}: RequestHandler = async (${collectionHandlerArgs}) => {\n${authGuardLine}\n const registered = ObjectRegistry.getClass('${lookupClassName}');\n${generateClassNotRegisteredError(lookupClassName)}\n\n${optionsLoad} const ClassRef = registered.constructor as any;\n const result = ${buildActionInvocationExpression(\n 'ClassRef',\n actionName,\n invocationArgs,\n )};\n\n return json({ action: '${actionName}', result: toPublicResult(result) });\n};\n`;\n }\n\n return `// Custom action: ${actionName}\nexport const ${handlerName}: RequestHandler = async (${itemHandlerArgs}) => {\n${authGuardLine}\n${generateCollectionLoad(lookupClassName, { generic: true })}\n const item = await collection.get(params.id);\n${generateNotFoundError(lookupClassName)}\n\n${optionsLoad} const result = ${buildActionInvocationExpression(\n 'item',\n actionName,\n invocationArgs,\n )};\n\n return json({ action: '${actionName}', result: toPublicResult(result) });\n};\n`;\n}\n\nfunction generateKnowledgeRouteTemplate(\n knowledge: DomainKnowledgeConfig,\n artifact: Record<string, any> | null,\n): string {\n const api = knowledge.api ?? {};\n const includeDocs = api.includeDocs === true;\n const includePrompts = api.includePrompts === true;\n const requireAdmin = api.requireAdmin !== false;\n const artifactLiteral = artifact ? JSON.stringify(artifact) : 'null';\n\n return `${AUTO_GENERATED_ROUTE_HEADER}\n// DO NOT EDIT - changes will be overwritten\n\nimport { dev } from '$app/environment';\nimport { error, json } from '@sveltejs/kit';\nimport type { RequestHandler } from './$types';\n\nconst INCLUDE_DOCS_BY_DEFAULT = ${JSON.stringify(includeDocs)};\nconst INCLUDE_PROMPTS_BY_DEFAULT = ${JSON.stringify(includePrompts)};\nconst REQUIRE_ADMIN = ${JSON.stringify(requireAdmin)};\nconst KNOWLEDGE_ARTIFACT: Record<string, any> | null = ${artifactLiteral};\n\nif (!dev && !REQUIRE_ADMIN) {\n console.warn('[smrt] PUBLIC knowledge API route enabled; unauthenticated responses are sanitized.');\n}\n\nexport const GET: RequestHandler = async ({ locals, url, setHeaders }) => {\n setHeaders({ 'cache-control': 'private, no-store' });\n\n if (!dev && REQUIRE_ADMIN && !isKnowledgeAdmin(locals as Record<string, any>)) {\n throw error(403, 'SMRT knowledge requires dev mode or admin access');\n }\n\n const artifact = readKnowledgeArtifact();\n const includeDocs = queryBoolean(url, 'includeDocs', INCLUDE_DOCS_BY_DEFAULT);\n const includePrompts = queryBoolean(\n url,\n 'includePrompts',\n INCLUDE_PROMPTS_BY_DEFAULT,\n );\n\n return json(sanitizeKnowledgeArtifact(artifact, {\n includeDocs,\n includePrompts,\n publicAccess: !REQUIRE_ADMIN,\n }));\n};\n\nfunction readKnowledgeArtifact(): Record<string, any> {\n if (!KNOWLEDGE_ARTIFACT) throw error(404, 'SMRT knowledge artifact not found');\n return KNOWLEDGE_ARTIFACT;\n}\n\nfunction queryBoolean(url: URL, name: string, defaultValue: boolean): boolean {\n const value = url.searchParams.get(name);\n if (value === null) return defaultValue;\n return value === 'true';\n}\n\nfunction sanitizeKnowledgeArtifact(\n artifact: Record<string, any>,\n options: { includeDocs: boolean; includePrompts: boolean; publicAccess: boolean },\n): Record<string, any> {\n const sanitized = { ...artifact };\n\n if (!options.includeDocs) {\n delete sanitized.agentDoc;\n }\n\n if (!options.includePrompts) {\n sanitized.prompts = [];\n }\n\n if (options.publicAccess) {\n delete sanitized.dependencies;\n delete sanitized.sourceHashes;\n delete sanitized.sourceManifestPath;\n delete sanitized.agentDocPath;\n }\n\n return sanitized;\n}\n\nfunction isKnowledgeAdmin(locals: Record<string, any>): boolean {\n if (locals.smrtKnowledgeAdmin === true || locals.smrtAdmin === true) {\n return true;\n }\n\n const userRoles = rolesFrom(locals.user);\n const sessionRoles = rolesFrom(locals.session?.user);\n return [...userRoles, ...sessionRoles].some((role) =>\n ['admin', 'owner', 'superadmin'].includes(role),\n );\n}\n\nfunction rolesFrom(value: any): string[] {\n if (!value || typeof value !== 'object') return [];\n const roles = Array.isArray(value.roles) ? value.roles : [value.role];\n return roles\n .filter((role): role is string => typeof role === 'string')\n .map((role) => role.toLowerCase());\n}\n`;\n}\n\n/**\n * Updates .gitignore to exclude auto-generated routes\n */\nfunction updateGitignore(projectRoot: string, options: SvelteKitOptions): void {\n const gitignorePath = join(projectRoot, '.gitignore');\n\n // Patterns to add\n const patternsToAdd = [\n '# SMRT auto-generated routes (from Vite plugin)',\n `${options.routesDir}/**/+server.ts`,\n ];\n if (options.knowledge?.api?.enabled) {\n const knowledgeRoute = relative(\n projectRoot,\n join(knowledgeRouteDir(projectRoot, options), '+server.ts'),\n ).replaceAll('\\\\', '/');\n patternsToAdd.push(knowledgeRoute);\n }\n\n // Read existing .gitignore or create empty string\n let gitignoreContent = '';\n if (existsSync(gitignorePath)) {\n gitignoreContent = readFileSync(gitignorePath, 'utf-8');\n }\n\n // Check if patterns already exist\n let needsUpdate = false;\n const linesToAdd: string[] = [];\n\n for (const pattern of patternsToAdd) {\n // Skip if pattern already exists (check for exact match or similar)\n if (!gitignoreContent.includes(pattern)) {\n linesToAdd.push(pattern);\n needsUpdate = true;\n }\n }\n\n if (needsUpdate) {\n // Ensure file ends with newline before adding\n if (gitignoreContent.length > 0 && !gitignoreContent.endsWith('\\n')) {\n gitignoreContent += '\\n';\n }\n\n // Add a blank line before our section if file has content\n if (gitignoreContent.length > 0 && !gitignoreContent.endsWith('\\n\\n')) {\n gitignoreContent += '\\n';\n }\n\n // Add our patterns\n gitignoreContent += `${linesToAdd.join('\\n')}\\n`;\n\n writeFileSync(gitignorePath, gitignoreContent, 'utf-8');\n console.log('[smrt] Updated .gitignore with generated route patterns');\n }\n}\n"],"names":["segment","imports"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"sveltekit-generator.js","sources":["../../src/vite-plugin/sveltekit-generator.ts"],"sourcesContent":["/**\n * SvelteKit route auto-generation from SMRT objects\n * Generates real TypeScript files in src/routes/api/ based on discovered SMRT objects\n */\n\nimport {\n existsSync,\n mkdirSync,\n readdirSync,\n readFileSync,\n unlinkSync,\n writeFileSync,\n} from 'node:fs';\nimport { join, relative } from 'node:path';\nimport type { DomainKnowledgeConfig } from '@happyvertical/smrt-types';\nimport type {\n ApiConfig,\n ApiCustomRouteConfig,\n ApiHttpMethod,\n ApiSerializerReference,\n} from '../registry/types.js';\nimport type {\n SmartObjectDefinition,\n SmartObjectManifest,\n} from '../scanner/types';\n\nexport interface SvelteKitOptions {\n enabled: boolean;\n routesDir: string;\n objectsDir: string;\n configPath?: string; // default: 'src/lib/server'\n configFileName?: string; // default: 'smrt.ts'\n /**\n * Apply kebab-case to custom-method URL segments (e.g. `discoverFromUrl`\n * becomes `/discover-from-url`). Opt-in for one minor; default flips in the\n * next major. An explicit `api.routes[name].path` always wins over this.\n */\n kebabRoutes?: boolean;\n /** Domain knowledge API route generation. Disabled unless explicitly enabled. */\n knowledge?: DomainKnowledgeConfig;\n}\n\n// Keep this aligned with biome.json formatter.lineWidth.\nconst BIOME_LINE_WIDTH = 80;\nconst AUTO_GENERATED_ROUTE_HEADER =\n '// Auto-generated by @smrt/core vite plugin';\nconst STANDARD_API_ACTIONS = ['list', 'get', 'create', 'update', 'delete'];\n\ninterface ResolvedApiActionRouteConfig {\n scope: 'item' | 'collection';\n method: ApiHttpMethod;\n pathSegments: string[];\n pathParamNames: string[];\n}\n\ninterface GeneratedActionRouteSpec {\n lookupClassName: string;\n lookupObjectDef?: SmartObjectDefinition;\n hostClassName: string;\n actionName: string;\n actionDef: any;\n routeConfig: ResolvedApiActionRouteConfig;\n hostType: 'item' | 'collection';\n}\n\ninterface ResolvedStandardRouteSerializers {\n importStatements: string[];\n itemSerializerName?: string;\n listItemSerializerName?: string;\n}\n\ninterface GeneratedTypeReference {\n typeName: string;\n importStatement?: string;\n}\n\n/**\n * Extract simple class name from potentially qualified name.\n * Qualified names follow the pattern: @scope/package:ClassName\n *\n * Issue #870: Manifests may contain qualified names which generate invalid\n * import statements like: import { @pkg:Class } from '@pkg'\n *\n * @param qualifiedName - Class name that may be qualified (e.g., \"@pkg:Class\" or \"Class\")\n * @returns Simple class name (e.g., \"Class\")\n */\nfunction extractSimpleClassName(qualifiedName: string): string {\n const colonIndex = qualifiedName.indexOf(':');\n if (colonIndex !== -1) {\n return qualifiedName.substring(colonIndex + 1);\n }\n return qualifiedName;\n}\n\n/**\n * Check if an object definition represents a SmrtCollection class.\n * Collection classes share route paths with their item class (via inherited `collection` field),\n * so generating routes for both would cause file collisions.\n */\nfunction isCollectionClass(objectDef: SmartObjectDefinition): boolean {\n return objectDef.extends === 'SmrtCollection' || !!objectDef.extendsTypeArg;\n}\n\nfunction getRegistrationPackageName(\n manifest: SmartObjectManifest,\n objectDef: SmartObjectDefinition,\n isLocal: boolean,\n): string | undefined {\n if (isLocal) {\n return manifest.packageName ?? objectDef.packageName;\n }\n\n return objectDef.packageName;\n}\n\nfunction toSingleQuotedStringLiteral(value: string): string {\n const jsonLiteral = JSON.stringify(value);\n const jsonContent = jsonLiteral.slice(1, -1).replaceAll(\"'\", \"\\\\'\");\n return `'${jsonContent}'`;\n}\n\nfunction getApiConfigObject(apiConfig: unknown): ApiConfig | null {\n if (!apiConfig || typeof apiConfig !== 'object') {\n return null;\n }\n\n return apiConfig as ApiConfig;\n}\n\nfunction isSameSerializerReference(\n left?: ApiSerializerReference,\n right?: ApiSerializerReference,\n): boolean {\n return (\n !!left &&\n !!right &&\n left.importPath === right.importPath &&\n left.exportName === right.exportName\n );\n}\n\nfunction resolveStandardRouteSerializers(\n apiConfig: unknown,\n): ResolvedStandardRouteSerializers {\n const config = getApiConfigObject(apiConfig);\n const itemSerializer = config?.serializers?.item;\n const listItemSerializer =\n config?.serializers?.listItem || config?.serializers?.item;\n\n const importStatements: string[] = [];\n let itemSerializerName: string | undefined;\n let listItemSerializerName: string | undefined;\n\n if (itemSerializer) {\n itemSerializerName = 'serializeItemResponse';\n importStatements.push(\n `import { ${itemSerializer.exportName} as ${itemSerializerName} } from '${itemSerializer.importPath}';`,\n );\n }\n\n if (listItemSerializer) {\n if (isSameSerializerReference(listItemSerializer, itemSerializer)) {\n listItemSerializerName = itemSerializerName;\n } else {\n listItemSerializerName = 'serializeListItemResponse';\n importStatements.push(\n `import { ${listItemSerializer.exportName} as ${listItemSerializerName} } from '${listItemSerializer.importPath}';`,\n );\n }\n }\n\n return {\n importStatements,\n itemSerializerName,\n listItemSerializerName,\n };\n}\n\nfunction isValidTypeIdentifier(name: string): boolean {\n return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name);\n}\n\nfunction resolveObjectTypeReference(\n projectRoot: string,\n className: string,\n objectDef: SmartObjectDefinition | undefined,\n options: SvelteKitOptions,\n routeDir?: string,\n): GeneratedTypeReference {\n const simpleClassName = extractSimpleClassName(className);\n\n if (!objectDef || !isValidTypeIdentifier(simpleClassName)) {\n return { typeName: \"import('@happyvertical/smrt-core').SmrtObject\" };\n }\n\n const importPath =\n isLocalObject(projectRoot, objectDef) || !objectDef.packageName\n ? getRouteTypeImportPath(\n projectRoot,\n objectDef,\n options,\n simpleClassName,\n routeDir,\n )\n : objectDef.packageName;\n\n return {\n typeName: simpleClassName,\n importStatement: `import type { ${simpleClassName} } from '${importPath}';`,\n };\n}\n\nfunction getRouteTypeImportPath(\n projectRoot: string,\n objectDef: SmartObjectDefinition,\n options: SvelteKitOptions,\n simpleClassName: string,\n routeDir?: string,\n): string {\n if (objectDef.filePath) {\n const srcLibDir = join(projectRoot, 'src/lib');\n if (objectDef.filePath.startsWith(`${srcLibDir}/`)) {\n const libRelative = relative(srcLibDir, objectDef.filePath)\n .replace(/\\\\/g, '/')\n .replace(/\\.(ts|js|tsx|jsx)$/, '');\n return `$lib/${libRelative}`.replace(/\\/+/g, '/');\n }\n\n if (routeDir) {\n const routeRelative = relative(routeDir, objectDef.filePath)\n .replace(/\\\\/g, '/')\n .replace(/\\.(ts|js|tsx|jsx)$/, '');\n return routeRelative.startsWith('.')\n ? routeRelative\n : `./${routeRelative}`;\n }\n }\n\n return getSvelteKitImportPath(\n projectRoot,\n objectDef.filePath,\n options.objectsDir,\n simpleClassName,\n );\n}\n\nfunction mergeImportStatements(\n importStatements: Array<string | undefined>,\n): string {\n return Array.from(new Set(importStatements.filter(Boolean))).join('\\n');\n}\n\nfunction findObjectDefByRegistryKey(\n manifest: SmartObjectManifest,\n className: string,\n): SmartObjectDefinition | undefined {\n return (\n manifest.objects[className] ??\n Object.values(manifest.objects).find(\n (objectDef) => objectDef.className === extractSimpleClassName(className),\n )\n );\n}\n\n/**\n * Collect property names marked `@field({ readonly: true })` for an object, so\n * the generated write surfaces can strip them from request bodies (#1540, 2b).\n */\nfunction collectReadonlyFieldNames(objectDef: SmartObjectDefinition): string[] {\n const fields = objectDef.fields || {};\n const names: string[] = [];\n for (const [name, def] of Object.entries(fields)) {\n const meta = (def as { _meta?: Record<string, unknown> })._meta;\n if (\n (def as { readonly?: boolean }).readonly === true ||\n meta?.readonly === true\n ) {\n names.push(name);\n }\n }\n return names;\n}\n\n/**\n * Resolve the optional `@smrt({ api: { writable: [...] } })` allowlist. When\n * present, only these fields may be set from a create/update request body.\n */\nfunction getApiWritableAllowlist(apiConfig: unknown): string[] | null {\n const config = getApiConfigObject(apiConfig);\n return Array.isArray(config?.writable) ? config.writable : null;\n}\n\n/**\n * Emit the mass-assignment guard helper injected into generated route files\n * (#1540, 2b). It strips framework/server-managed (`id`, `tenantId`,\n * timestamps, `_`-prefixed) and `@field({ readonly: true })` fields from\n * request bodies, and — when a `writable` allowlist is configured — intersects\n * with it. Applied to every generated `create`/`update` handler.\n */\nfunction generateWritablePolicyHelper(\n objectDef: SmartObjectDefinition,\n): string {\n const readonly = collectReadonlyFieldNames(objectDef);\n const writable = getApiWritableAllowlist(objectDef.decoratorConfig?.api);\n\n return `\n// Mass-assignment guard (#1540): strip framework/server-managed + read-only\n// fields from create/update request bodies before they reach the model.\nconst WRITABLE_ALLOWLIST: string[] | null = ${\n writable ? JSON.stringify(writable) : 'null'\n };\nconst READONLY_FIELDS: string[] = ${JSON.stringify(readonly)};\nconst SERVER_MANAGED_FIELDS = [\n 'id',\n 'tenantId',\n 'tenant_id',\n 'createdAt',\n 'created_at',\n 'updatedAt',\n 'updated_at',\n];\n\nfunction applyWritablePolicy(data: unknown): Record<string, unknown> {\n if (!data || typeof data !== 'object') return {};\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data as Record<string, unknown>)) {\n if (key.startsWith('_')) continue;\n if (SERVER_MANAGED_FIELDS.includes(key)) continue;\n if (READONLY_FIELDS.includes(key)) continue;\n if (WRITABLE_ALLOWLIST && !WRITABLE_ALLOWLIST.includes(key)) continue;\n result[key] = value;\n }\n return result;\n}\n`;\n}\n\n/**\n * Resolve the `@smrt({ api: { public } })` posture (fail-closed default).\n * - `false`/unset → all routes require an authenticated principal.\n * - `true` → all routes are public.\n * - `'read'` → reads are public, mutations still require auth.\n */\nfunction getApiPublicAccess(apiConfig: unknown): boolean | 'read' {\n const config = getApiConfigObject(apiConfig);\n const value = config?.public;\n if (value === true || value === 'read') {\n return value;\n }\n return false;\n}\n\n/**\n * Emit the fail-closed authorization guard injected into generated route files\n * (#1540, 2c). Every generated CRUD/action handler calls `requireRouteAuth`,\n * which throws 401 unless the route is `public` or `locals` carries an\n * authenticated principal. Mirrors the knowledge-route `isKnowledgeAdmin`\n * precedent. Mutating verbs require auth even when reads are public.\n */\nfunction generateAuthGuardHelper(objectDef: SmartObjectDefinition): string {\n const publicAccess = getApiPublicAccess(objectDef.decoratorConfig?.api);\n\n return `\n// Fail-closed authorization (#1540): generated routes require an authenticated\n// principal on \\`locals\\` unless explicitly marked \\`@smrt({ api: { public } })\\`.\nconst PUBLIC_ACCESS: boolean | 'read' = ${JSON.stringify(publicAccess)};\n\nfunction hasAuthenticatedPrincipal(locals: unknown): boolean {\n if (!locals || typeof locals !== 'object') return false;\n const l = locals as Record<string, unknown>;\n // Only a resolved, object-shaped principal counts. We intentionally do NOT\n // treat \\`locals.auth\\` as a signal: Auth.js/SvelteKit put a callable\n // \\`auth()\\` helper on every request (including anonymous ones), so honoring\n // it would fail OPEN. Booleans don't count either (no convention sets\n // \\`locals.user = true\\`); the only boolean accepted is the explicit\n // \\`smrtAuth\\` opt-in marker.\n const isResolvedPrincipal = (v: unknown) =>\n typeof v === 'object' && v !== null;\n return (\n isResolvedPrincipal(l.user) ||\n isResolvedPrincipal(l.session) ||\n l.smrtAuth === true\n );\n}\n\nfunction requireRouteAuth(locals: unknown, mutating: boolean): void {\n if (PUBLIC_ACCESS === true) return;\n if (PUBLIC_ACCESS === 'read' && !mutating) return;\n if (!hasAuthenticatedPrincipal(locals)) {\n throw error(401, 'Authentication required');\n }\n}\n\n// Sensitive-field-safe serialization for custom-action results (#1540): a\n// custom method may return a SmrtObject (or one nested in an array/plain\n// object), so recurse and route each through toPublicJSON() rather than letting\n// JSON.stringify call toJSON(). Non-plain instances (Date, etc.) and primitives\n// pass through; a cycle guard prevents infinite loops.\ninterface PublicJsonSource {\n toPublicJSON(): unknown;\n}\n\nfunction hasPublicJson(value: object): value is PublicJsonSource {\n return (\n 'toPublicJSON' in value &&\n typeof (value as { toPublicJSON?: unknown }).toPublicJSON === 'function'\n );\n}\n\nfunction readJsonRecord(value: unknown): Record<string, unknown> {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return {};\n return value as Record<string, unknown>;\n}\n\nfunction toPublicResult(\n value: unknown,\n seen: WeakSet<object> = new WeakSet(),\n): unknown {\n if (value === null || typeof value !== 'object') return value;\n if (seen.has(value)) return null;\n if (hasPublicJson(value)) {\n seen.add(value);\n return toPublicResult(value.toPublicJSON(), seen);\n }\n if (Array.isArray(value)) {\n seen.add(value);\n return value.map((entry) => toPublicResult(entry, seen));\n }\n const proto = Object.getPrototypeOf(value);\n if (proto !== Object.prototype && proto !== null) return value;\n seen.add(value);\n const out: Record<string, unknown> = {};\n for (const [key, entry] of Object.entries(\n value as Record<string, unknown>,\n )) {\n out[key] = toPublicResult(entry, seen);\n }\n return out;\n}\n`;\n}\n\n/**\n * Whether an object is `@TenantScoped` (carries a `tenantScoped` config in its\n * `@smrt()`/`@TenantScoped()` decorator). Drives tenant-context establishment in\n * generated routes (#1540, facet 2).\n */\nfunction isTenantScoped(objectDef: SmartObjectDefinition): boolean {\n return !!objectDef.decoratorConfig?.tenantScoped;\n}\n\n/**\n * Emit the tenant-context establishment helper for `@TenantScoped` objects\n * (#1540, facet 2). Generated handlers call `establishTenantContext(locals)`\n * after the auth guard so every collection query runs inside the tenant context\n * derived from the authenticated principal — engaging the `@TenantScoped`\n * interceptors that auto-filter by tenant.\n *\n * Without this, an `optional`-mode scoped object queried over a generated route\n * with no active context returns rows from ALL tenants (the interceptor only\n * hard-fails `required` mode). We read the canonical `locals.tenantId` set by\n * the smrt-users auth hook (with `user`/`session` fallbacks). It is a no-op when\n * a context is already active (e.g. an upstream tenancy handle) or when the\n * principal carries no tenant (global/admin — preserving optional-mode global\n * access). Imported only for tenant-scoped routes, which already depend on\n * `@happyvertical/smrt-tenancy`.\n */\nfunction generateTenantContextHelper(): string {\n return `\nimport { enterTenantContext, hasTenantContext } from '@happyvertical/smrt-tenancy';\n\nfunction establishTenantContext(locals: unknown): void {\n if (hasTenantContext()) return;\n if (!locals || typeof locals !== 'object') return;\n const l = locals as Record<string, unknown>;\n const user = l.user as Record<string, unknown> | undefined;\n const session = l.session as Record<string, unknown> | undefined;\n const tenantId = l.tenantId ?? user?.tenantId ?? session?.tenantId;\n if (typeof tenantId === 'string' && tenantId) {\n enterTenantContext({ tenantId });\n }\n}\n`;\n}\n\n/**\n * The per-handler guard preamble: the fail-closed auth check (#1540 2c) plus, for\n * tenant-scoped objects, tenant-context establishment (#1540 facet 2).\n */\nfunction routeGuardPreamble(\n objectDef: SmartObjectDefinition,\n mutating: boolean,\n): string {\n const lines = [` requireRouteAuth(locals, ${mutating});`];\n if (isTenantScoped(objectDef)) {\n lines.push(' establishTenantContext(locals);');\n }\n return lines.join('\\n');\n}\n\nfunction normalizeApiHttpMethod(method?: string): ApiHttpMethod {\n switch (method?.toUpperCase()) {\n case 'GET':\n case 'POST':\n case 'PUT':\n case 'PATCH':\n case 'DELETE':\n return method.toUpperCase() as ApiHttpMethod;\n default:\n return 'POST';\n }\n}\n\n/**\n * Convert a camelCase / PascalCase method name to a kebab-case URL segment.\n * Examples:\n * discoverFromUrl -> discover-from-url\n * XMLExport -> xml-export\n * URL -> url\n * a1B2c3 -> a1-b2c3\n *\n * Known limitation: consecutive uppercase acronyms aren't split apart, e.g.\n * `HTMLAPIExport` becomes `htmlapi-export` rather than `html-api-export`.\n * Override with an explicit `api.routes[name].path` if you need a specific\n * segmentation.\n */\nexport function methodNameToKebab(name: string): string {\n return name\n .replace(/([a-z0-9])([A-Z])/g, '$1-$2')\n .replace(/([A-Z]+)([A-Z][a-z])/g, '$1-$2')\n .toLowerCase();\n}\n\nfunction normalizeCustomRoutePath(\n actionName: string,\n path?: string,\n options: { kebabRoutes?: boolean } = {},\n): string[] {\n // Explicit path override always wins, and is used verbatim (split on /).\n if (path) {\n const segments = path\n .split('/')\n .map((segment) => segment.trim())\n .filter(Boolean);\n if (segments.length > 0) {\n return segments;\n }\n }\n\n const segment = options.kebabRoutes\n ? methodNameToKebab(actionName)\n : actionName;\n return [segment];\n}\n\nfunction extractRoutePathParamNames(pathSegments: string[]): string[] {\n return pathSegments\n .filter((segment) => /^\\[[^\\]]+\\]$/.test(segment))\n .map((segment) => segment.slice(1, -1))\n .filter(Boolean);\n}\n\nfunction resolveApiActionRouteConfig(\n actionName: string,\n actionDef: { isStatic?: boolean },\n apiConfig: unknown,\n routeOptions: { kebabRoutes?: boolean } = {},\n defaultScope: 'item' | 'collection' = actionDef.isStatic\n ? 'collection'\n : 'item',\n): ResolvedApiActionRouteConfig {\n const config = getApiConfigObject(apiConfig);\n const routeConfig: ApiCustomRouteConfig | undefined =\n config?.routes?.[actionName];\n\n const pathSegments = normalizeCustomRoutePath(\n actionName,\n routeConfig?.path,\n routeOptions,\n );\n\n return {\n scope: routeConfig?.scope || defaultScope,\n method: normalizeApiHttpMethod(routeConfig?.method),\n pathSegments,\n pathParamNames: extractRoutePathParamNames(pathSegments),\n };\n}\n\nfunction buildRouteHandlerArgs(\n includeParams: boolean,\n includeRequest: boolean,\n): string {\n // `locals` is always destructured so the fail-closed auth guard (#1540) can\n // inspect the authenticated principal.\n const args: string[] = ['locals'];\n\n if (includeParams) {\n args.push('params');\n }\n\n if (includeRequest) {\n args.push('request');\n }\n\n return `{ ${args.join(', ')} }`;\n}\n\nfunction buildPathParamsObjectLiteral(pathParamNames: string[]): string {\n if (pathParamNames.length === 0) {\n return '{}';\n }\n\n return `{\n${pathParamNames\n .map(\n (paramName) =>\n ` ${JSON.stringify(paramName)}: params[${JSON.stringify(paramName)}],`,\n )\n .join('\\n')}\n }`;\n}\n\nfunction buildActionInvocationArgs(actionDef: any): string[] {\n const parameters = Array.isArray(actionDef.parameters)\n ? actionDef.parameters\n : [];\n\n if (parameters.length === 0) {\n return [];\n }\n\n if (parameters.length === 1 && parameters[0]?.name === 'options') {\n return ['options'];\n }\n\n return parameters.map((parameter: any) =>\n buildOptionsPropertyAccess(parameter.name),\n );\n}\n\nfunction buildObjectTypeProperty(propertyName: string): string {\n if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(propertyName)) {\n return propertyName;\n }\n\n return JSON.stringify(propertyName);\n}\n\nfunction buildActionTargetTypeExpression(\n targetTypeName: string,\n isStatic: boolean,\n): string {\n return isStatic ? `(typeof ${targetTypeName})` : targetTypeName;\n}\n\nfunction buildActionArgsTypeAlias(\n actionName: string,\n targetTypeName: string,\n isStatic: boolean,\n): string {\n const targetTypeExpression = buildActionTargetTypeExpression(\n targetTypeName,\n isStatic,\n );\n return ` type ActionArgs = Parameters<${targetTypeExpression}[${JSON.stringify(actionName)}]>;`;\n}\n\nfunction buildActionOptionsTypeAlias(actionDef: any): string {\n const parameters = Array.isArray(actionDef.parameters)\n ? actionDef.parameters\n : [];\n\n if (parameters.length <= 1 && parameters[0]?.name === 'options') {\n return '';\n }\n\n return [\n ' type ActionOptions = {',\n ...parameters.map(\n (parameter: any, index: number) =>\n ` ${buildObjectTypeProperty(parameter.name)}: ActionArgs[${index}];`,\n ),\n ' };',\n ].join('\\n');\n}\n\nfunction buildActionOptionsLoad(\n actionName: string,\n actionDef: any,\n routeConfig: ResolvedApiActionRouteConfig,\n targetTypeName: string,\n isStatic: boolean,\n): string {\n const parameters = Array.isArray(actionDef.parameters)\n ? actionDef.parameters\n : [];\n if (parameters.length === 0) {\n return '';\n }\n\n const hasPathParams = routeConfig.pathParamNames.length > 0;\n const pathParamsObjectLiteral = buildPathParamsObjectLiteral(\n routeConfig.pathParamNames,\n );\n const isSingleOptionsParameter =\n parameters.length === 1 && parameters[0]?.name === 'options';\n const lines = [\n buildActionArgsTypeAlias(actionName, targetTypeName, isStatic),\n ];\n const optionsTypeAlias = buildActionOptionsTypeAlias(actionDef);\n if (optionsTypeAlias) {\n lines.push(optionsTypeAlias);\n }\n\n if (routeConfig.method === 'GET') {\n if (hasPathParams) {\n lines.push(\n ` const pathParams = ${pathParamsObjectLiteral};`,\n ' const options = {',\n ' ...Object.fromEntries(new URL(request.url).searchParams.entries()),',\n ' ...pathParams,',\n ` } as ${isSingleOptionsParameter ? 'ActionArgs[0]' : 'ActionOptions'};`,\n '',\n );\n } else {\n lines.push(\n ' const options = Object.fromEntries(',\n ' new URL(request.url).searchParams.entries(),',\n ` ) as ${isSingleOptionsParameter ? 'ActionArgs[0]' : 'ActionOptions'};`,\n '',\n );\n }\n return lines.join('\\n');\n }\n\n if (hasPathParams) {\n lines.push(\n ` const pathParams = ${pathParamsObjectLiteral};`,\n ' const body: unknown = await request.json();',\n ' const options = {',\n ' ...readJsonRecord(body),',\n ' ...pathParams,',\n ` } as ${isSingleOptionsParameter ? 'ActionArgs[0]' : 'ActionOptions'};`,\n '',\n );\n return lines.join('\\n');\n }\n\n lines.push(' const body: unknown = await request.json();');\n if (isSingleOptionsParameter) {\n lines.push(' const options = body as ActionArgs[0];', '');\n } else {\n lines.push(' const options = readJsonRecord(body) as ActionOptions;', '');\n }\n return lines.join('\\n');\n}\n\nfunction buildOptionsPropertyAccess(propertyName: string): string {\n if (/^[A-Za-z_$][A-Za-z0-9_$]*$/.test(propertyName)) {\n return `options.${propertyName}`;\n }\n\n const escapedPropertyName = propertyName\n .replaceAll('\\\\', '\\\\\\\\')\n .replaceAll(\"'\", \"\\\\'\");\n\n return `options['${escapedPropertyName}']`;\n}\n\nfunction buildActionInvocationExpression(\n receiverExpression: string,\n actionName: string,\n invocationArgs: string[],\n): string {\n const singleLineInvocation = `await ${receiverExpression}.${actionName}(${invocationArgs.join(', ')})`;\n const singleLineResultAssignment = ` const result = ${singleLineInvocation};`;\n\n if (singleLineResultAssignment.length <= 100) {\n return singleLineInvocation;\n }\n\n return [\n `await ${receiverExpression}.${actionName}(`,\n ...invocationArgs.map((argument) => ` ${argument},`),\n ' )',\n ].join('\\n');\n}\n\nfunction findItemClassRegistryKey(\n className: string,\n objectDef: SmartObjectDefinition,\n manifest: SmartObjectManifest,\n): string {\n const itemClassName =\n objectDef.extendsTypeArg ||\n (className.endsWith('Collection')\n ? className.slice(0, -'Collection'.length)\n : undefined);\n\n if (!itemClassName) {\n return className;\n }\n\n const manifestMatch = Object.entries(manifest.objects).find(\n ([manifestKey, candidate]) =>\n manifestKey === itemClassName || candidate.className === itemClassName,\n );\n\n return manifestMatch?.[0] || itemClassName;\n}\n\nfunction groupCustomActionRoutes(\n actionSpecs: Array<{\n routeDir: string;\n spec: GeneratedActionRouteSpec;\n }>,\n): Map<string, GeneratedActionRouteSpec[]> {\n const groupedRoutes = new Map<string, GeneratedActionRouteSpec[]>();\n\n for (const { routeDir, spec } of actionSpecs) {\n const existing = groupedRoutes.get(routeDir) || [];\n const duplicateMethod = existing.find(\n (candidate) => candidate.routeConfig.method === spec.routeConfig.method,\n );\n\n if (duplicateMethod) {\n throw new Error(\n `Duplicate custom API route handler for ${routeDir} (${spec.routeConfig.method}). ` +\n `Methods ${duplicateMethod.actionName} and ${spec.actionName} resolve to the same generated route.`,\n );\n }\n\n existing.push(spec);\n groupedRoutes.set(routeDir, existing);\n }\n\n return groupedRoutes;\n}\n\n/**\n * Generates SvelteKit API routes from manifest\n */\nexport async function generateSvelteKitRoutes(\n projectRoot: string,\n manifest: SmartObjectManifest,\n options: SvelteKitOptions,\n): Promise<void> {\n if (!options.enabled) return;\n\n console.log('[smrt] Generating SvelteKit routes...');\n\n clearGeneratedRouteFiles(join(projectRoot, options.routesDir));\n clearGeneratedKnowledgeRoute(projectRoot, options);\n\n // Generate centralized configuration file first (if it doesn't exist)\n await generateSmrtConfigFile(projectRoot, manifest, options);\n\n let generatedCount = 0;\n let skippedCollections = 0;\n for (const [className, objectDef] of Object.entries(manifest.objects)) {\n if (isCollectionClass(objectDef)) {\n const generatedCollectionRoutes = await generateCollectionRoutesForObject(\n projectRoot,\n className,\n objectDef,\n manifest,\n options,\n );\n if (generatedCollectionRoutes) {\n generatedCount++;\n } else {\n console.log(\n `[smrt] Skipping ${className} - no collection API routes to generate`,\n );\n skippedCollections++;\n }\n continue;\n }\n await generateRoutesForObject(projectRoot, className, objectDef, options);\n generatedCount++;\n }\n\n if (options.knowledge?.api?.enabled) {\n generateKnowledgeRoute(projectRoot, options);\n }\n\n // Update .gitignore to exclude generated routes\n updateGitignore(projectRoot, options);\n\n const skippedMsg =\n skippedCollections > 0\n ? ` (skipped ${skippedCollections} collection classes)`\n : '';\n console.log(\n `[smrt] Generated routes for ${generatedCount} SMRT objects${skippedMsg}`,\n );\n}\n\nfunction clearGeneratedRouteFiles(routesRoot: string): void {\n if (!existsSync(routesRoot)) {\n return;\n }\n\n for (const entry of readdirSync(routesRoot, { withFileTypes: true })) {\n const entryPath = join(routesRoot, entry.name);\n\n if (entry.isDirectory()) {\n clearGeneratedRouteFiles(entryPath);\n continue;\n }\n\n if (!entry.isFile() || entry.name !== '+server.ts') {\n continue;\n }\n\n const fileContent = readFileSync(entryPath, 'utf-8');\n if (fileContent.startsWith(AUTO_GENERATED_ROUTE_HEADER)) {\n unlinkSync(entryPath);\n }\n }\n}\n\nfunction knowledgeRouteDir(projectRoot: string, options: SvelteKitOptions) {\n const basePath = String(\n options.knowledge?.api?.basePath || '/__smrt/knowledge',\n );\n const routeRoot = svelteKitRouteRoot(options.routesDir);\n const segments = basePath\n .split('/')\n .map((segment) => segment.trim())\n .filter(Boolean);\n\n return join(projectRoot, routeRoot, ...segments);\n}\n\nfunction svelteKitRouteRoot(routesDir: string): string {\n const normalized = routesDir.replaceAll('\\\\', '/').replace(/\\/+$/, '');\n const marker = '/routes';\n const markerIndex = normalized.indexOf(marker);\n\n if (normalized === 'src/routes' || normalized.endsWith('/routes')) {\n return normalized;\n }\n if (markerIndex !== -1) {\n return normalized.slice(0, markerIndex + marker.length);\n }\n return 'src/routes';\n}\n\nfunction clearGeneratedKnowledgeRoute(\n projectRoot: string,\n options: SvelteKitOptions,\n): void {\n const routeDir = knowledgeRouteDir(projectRoot, options);\n const routePath = join(routeDir, '+server.ts');\n if (!existsSync(routePath)) return;\n\n const content = readFileSync(routePath, 'utf-8');\n if (content.startsWith(AUTO_GENERATED_ROUTE_HEADER)) {\n unlinkSync(routePath);\n }\n}\n\nfunction generateKnowledgeRoute(\n projectRoot: string,\n options: SvelteKitOptions,\n): void {\n const routeDir = knowledgeRouteDir(projectRoot, options);\n const route = generateKnowledgeRouteTemplate(\n options.knowledge ?? {},\n readKnowledgeRouteArtifact(projectRoot),\n );\n writeRoute(routeDir, '+server.ts', route);\n}\n\nfunction readKnowledgeRouteArtifact(\n projectRoot: string,\n): Record<string, unknown> | null {\n for (const relativePath of [\n '.smrt/smrt-knowledge.json',\n 'dist/smrt-knowledge.json',\n ]) {\n const fullPath = join(projectRoot, relativePath);\n if (!existsSync(fullPath)) continue;\n try {\n return JSON.parse(readFileSync(fullPath, 'utf-8'));\n } catch {\n return null;\n }\n }\n\n return null;\n}\n\n/**\n * Generates SMRT object registration file\n * This file imports all SMRT objects to trigger their @smrt() decorators\n */\nasync function generateRegistrationFile(\n projectRoot: string,\n manifest: SmartObjectManifest,\n options: SvelteKitOptions,\n): Promise<void> {\n const configPath = options.configPath || 'src/lib/server';\n const configDir = join(projectRoot, configPath);\n const registrationFilePath = join(configDir, 'smrt-register.ts');\n\n // Group objects by package for efficient imports\n const localObjects: Array<[string, (typeof manifest.objects)[string]]> = [];\n const packageObjects = new Map<\n string,\n { classNames: string[]; hasCollectionImport: boolean }\n >();\n\n for (const [className, objectDef] of Object.entries(manifest.objects)) {\n if (isLocalObject(projectRoot, objectDef)) {\n // Local object (source in project, not node_modules) - use $lib path\n localObjects.push([className, objectDef]);\n } else if (objectDef.packageName) {\n // External package - group by package name\n const packageEntry = packageObjects.get(objectDef.packageName) || {\n classNames: [],\n hasCollectionImport: false,\n };\n\n if (isCollectionClass(objectDef)) {\n packageEntry.hasCollectionImport = true;\n } else {\n packageEntry.classNames.push(className);\n }\n\n packageObjects.set(objectDef.packageName, packageEntry);\n } else {\n // No package name and not local - treat as local fallback\n localObjects.push([className, objectDef]);\n }\n }\n\n // Generate imports for local objects\n // Issue #870: Extract simple class names from qualified names\n const localNamedImports = new Map<string, string[]>();\n const localSideEffectImports = new Set<string>();\n\n for (const [className, objectDef] of localObjects) {\n const simpleClassName = extractSimpleClassName(className);\n\n // Calculate direct relative path from the configDir where smrt-register.ts lives\n // to the actual source file of the object.\n let importPath = '';\n if (objectDef.filePath) {\n const relativeToConfig = relative(configDir, objectDef.filePath);\n const normalized = relativeToConfig\n .replace(/\\\\/g, '/')\n .replace(/\\.(ts|js|tsx|jsx)$/, '');\n importPath = normalized.startsWith('.') ? normalized : `./${normalized}`;\n } else {\n // Fallback for missing file paths\n importPath = getSvelteKitImportPath(\n projectRoot,\n undefined,\n options.objectsDir,\n simpleClassName,\n );\n }\n\n if (isCollectionClass(objectDef)) {\n localSideEffectImports.add(importPath);\n continue;\n }\n\n const existing = localNamedImports.get(importPath) ?? [];\n existing.push(simpleClassName);\n localNamedImports.set(importPath, existing);\n }\n\n const localImports = [\n ...Array.from(localNamedImports.entries())\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([importPath, simpleNames]) => {\n const sortedNames = simpleNames.sort((a, b) => a.localeCompare(b));\n return `import { ${sortedNames.join(', ')} } from '${importPath}';`;\n }),\n ...Array.from(localSideEffectImports.values())\n .sort((a, b) => a.localeCompare(b))\n .map((importPath) => `import '${importPath}';`),\n ].join('\\n');\n\n // Generate imports for external packages\n // Issue #870: Extract simple class names from qualified names\n const packageImports = Array.from(packageObjects.entries())\n .sort(([left], [right]) => left.localeCompare(right))\n .flatMap(([packageName, packageEntry]) => {\n const imports: string[] = [];\n\n if (packageEntry.hasCollectionImport) {\n imports.push(`import '${packageName}';`);\n }\n\n if (packageEntry.classNames.length > 0) {\n // Extract simple class names for valid import syntax\n const simpleNames = packageEntry.classNames\n .map(extractSimpleClassName)\n .sort((a, b) => a.localeCompare(b));\n imports.push(\n `import { ${simpleNames.join(', ')} } from '${packageName}';`,\n );\n }\n\n return imports;\n })\n .join('\\n');\n\n const imports = [packageImports, localImports].filter(Boolean).join('\\n');\n const registrations = Object.entries(manifest.objects)\n .map(([className, objectDef]) => {\n if (isCollectionClass(objectDef)) {\n // Importing the collection class is enough to trigger its decorator.\n // Explicit package-qualified re-registration only applies to object\n // classes, because ObjectRegistry.register() is object-only.\n return null;\n }\n\n const simpleClassName = extractSimpleClassName(className);\n const localObject = isLocalObject(projectRoot, objectDef);\n const packageName = getRegistrationPackageName(\n manifest,\n objectDef,\n localObject,\n );\n\n if (!packageName) {\n return null;\n }\n\n const packageNameLiteral = toSingleQuotedStringLiteral(packageName);\n const singleLineRegistration = `ObjectRegistry.register(${simpleClassName}, { name: '${simpleClassName}', packageName: ${packageNameLiteral} });`;\n\n if (singleLineRegistration.length <= BIOME_LINE_WIDTH) {\n return singleLineRegistration;\n }\n\n return [\n `ObjectRegistry.register(${simpleClassName}, {`,\n ` name: '${simpleClassName}',`,\n ` packageName: ${packageNameLiteral},`,\n `});`,\n ].join('\\n');\n })\n .filter((registration): registration is string => registration !== null)\n .join('\\n');\n\n const registrationContent = `/**\n * Auto-generated SMRT object registration\n * DO NOT EDIT - changes will be overwritten\n *\n * Importing these modules triggers their @smrt() decorators, which perform\n * the initial registration. The explicit re-registration below is intentional:\n * it upgrades bundled runtimes to deterministic qualified registrations.\n */\n\nimport { ObjectRegistry } from '@happyvertical/smrt-core';\n\n${imports}\n\n// Re-register imported objects with explicit package names for bundled runtimes\n${registrations}\n`;\n\n // Create directory if it doesn't exist\n if (!existsSync(configDir)) {\n mkdirSync(configDir, { recursive: true });\n }\n\n writeFileSync(registrationFilePath, registrationContent, 'utf-8');\n console.log(`[smrt] Generated registration file: ${registrationFilePath}`);\n}\n\n/**\n * Generates centralized SMRT configuration file\n * Only creates if file doesn't exist (preserves user customizations)\n */\nasync function generateSmrtConfigFile(\n projectRoot: string,\n manifest: SmartObjectManifest,\n options: SvelteKitOptions,\n): Promise<void> {\n const configPath = options.configPath || 'src/lib/server';\n const configFileName = options.configFileName || 'smrt.ts';\n const configDir = join(projectRoot, configPath);\n const configFilePath = join(configDir, configFileName);\n\n // Always generate registration file (it gets overwritten)\n await generateRegistrationFile(projectRoot, manifest, options);\n\n // Don't overwrite existing config file\n if (existsSync(configFilePath)) {\n console.log('[smrt] Config file already exists, skipping generation');\n return;\n }\n\n const configContent = `/**\n * Centralized SMRT configuration with per-object overrides\n * Generated by @smrt/core vite plugin\n *\n * Most objects will use the default configuration.\n * Add entries to \\`objectOverrides\\` for objects that need different backends.\n */\n\n// Import SMRT objects to register them via @smrt() decorators\nimport './smrt-register.js';\n\nimport { ObjectRegistry } from '@happyvertical/smrt-core';\nimport type { SmrtClassOptions } from '@happyvertical/smrt-core';\n\ndeclare global {\n // eslint-disable-next-line no-var\n var __smrtGetRequestScopedDatabase:\n | (() => SmrtClassOptions['db'] | undefined)\n | undefined;\n}\n\n/**\n * Per-object configuration overrides\n * Define specific backends for objects that differ from project defaults\n *\n * @example\n * const objectOverrides: Record<string, Partial<SmrtClassOptions>> = {\n * // Analytics uses a separate PostgreSQL database\n * Analytics: {\n * db: {\n * url: process.env.ANALYTICS_DATABASE_URL!,\n * type: 'postgres'\n * }\n * },\n *\n * // AuditLog uses dedicated database with no AI\n * AuditLog: {\n * db: {\n * url: process.env.AUDIT_DATABASE_URL!,\n * type: 'postgres'\n * },\n * ai: undefined\n * },\n *\n * // Cache uses REST adapter (e.g., Redis)\n * Cache: {\n * persistence: {\n * type: 'rest',\n * baseUrl: process.env.REDIS_URL!\n * }\n * }\n * };\n */\nconst objectOverrides: Record<string, Partial<SmrtClassOptions>> = {\n // Add your per-object configuration overrides here\n};\n\n/**\n * Default configuration for most SMRT objects\n * Customize this to change project-wide defaults\n */\nfunction getDefaultConfig(): SmrtClassOptions {\n return {\n db: {\n url: process.env.DATABASE_URL || ':memory:',\n type: (process.env.DATABASE_TYPE as 'sqlite' | 'postgres') || 'sqlite'\n },\n ai: process.env.OPENAI_API_KEY ? {\n type: 'openai',\n apiKey: process.env.OPENAI_API_KEY\n } : process.env.ANTHROPIC_API_KEY ? {\n type: 'anthropic',\n apiKey: process.env.ANTHROPIC_API_KEY\n } : undefined\n };\n}\n\nfunction getRequestScopedDatabase(): SmrtClassOptions['db'] | undefined {\n const getter = globalThis.__smrtGetRequestScopedDatabase;\n return typeof getter === 'function' ? getter() : undefined;\n}\n\n/**\n * Get configuration for a specific SMRT object\n * Merges project defaults with per-object overrides if defined\n */\nexport function getSmrtConfig(className: string): SmrtClassOptions {\n const defaults = getDefaultConfig();\n const override = objectOverrides[className];\n\n if (override) {\n // Deep merge: override specific properties while keeping defaults\n return {\n ...defaults,\n ...override,\n // Ensure nested objects are merged properly\n db: override.db\n ? { ...(defaults.db as any), ...(override.db as any) }\n : defaults.db,\n ai: override.ai !== undefined ? override.ai : defaults.ai\n };\n }\n\n return defaults;\n}\n\n/**\n * Helper to get a collection with centralized configuration\n * Automatically applies project defaults or object-specific overrides\n */\nexport async function getCollection<\n T extends import('@happyvertical/smrt-core').SmrtObject,\n>(className: string, overrides: Partial<SmrtClassOptions> = {}) {\n const config = getSmrtConfig(className);\n const objectOverride = objectOverrides[className];\n const requestScopedDb =\n !overrides.db && !objectOverride?.db\n ? getRequestScopedDatabase()\n : undefined;\n\n return await ObjectRegistry.getCollection<T>(\n className,\n {\n ...config,\n ...overrides,\n db: overrides.db\n ? { ...(config.db as any), ...(overrides.db as any) }\n : requestScopedDb ?? config.db,\n ai: overrides.ai !== undefined ? overrides.ai : config.ai\n }\n );\n}\n`;\n\n // Create directory if it doesn't exist\n if (!existsSync(configDir)) {\n mkdirSync(configDir, { recursive: true });\n }\n\n writeFileSync(configFilePath, configContent, 'utf-8');\n console.log(`[smrt] Generated configuration file: ${configFilePath}`);\n}\n\n/**\n * Generates route files for a single SMRT object\n */\nasync function generateRoutesForObject(\n projectRoot: string,\n className: string,\n objectDef: SmartObjectDefinition,\n options: SvelteKitOptions,\n): Promise<void> {\n const collectionName = objectDef.collection;\n const routeDir = join(projectRoot, options.routesDir, collectionName);\n\n // Check if API is enabled for this object\n const apiConfig = objectDef.decoratorConfig?.api;\n if (apiConfig === false) {\n console.log(`[smrt] Skipping ${className} - API disabled`);\n return;\n }\n\n // Determine which CRUD actions to include via the shared resolver.\n const includedActions = resolveStandardCrudActions(apiConfig);\n\n // Generate collection route (list, create)\n if (includedActions.includes('list') || includedActions.includes('create')) {\n const collectionRoute = generateCollectionRouteTemplate(\n projectRoot,\n className,\n objectDef,\n includedActions,\n options,\n routeDir,\n );\n writeRoute(routeDir, '+server.ts', collectionRoute);\n }\n\n // Generate item route (get, update, delete)\n if (\n includedActions.includes('get') ||\n includedActions.includes('update') ||\n includedActions.includes('delete')\n ) {\n const itemRoute = generateItemRouteTemplate(\n projectRoot,\n className,\n objectDef,\n includedActions,\n options,\n join(routeDir, '[id]'),\n );\n writeRoute(join(routeDir, '[id]'), '+server.ts', itemRoute);\n }\n\n // Generate custom action routes\n const customActions = Object.entries(objectDef.methods).filter(\n ([name, method]) =>\n !STANDARD_API_ACTIONS.includes(name) &&\n method.isPublic &&\n shouldIncludeInApi(name, apiConfig),\n );\n\n const actionSpecs: Array<{\n routeDir: string;\n spec: GeneratedActionRouteSpec;\n }> = [];\n\n for (const [actionName, actionDef] of customActions) {\n const routeConfig = resolveApiActionRouteConfig(\n actionName,\n actionDef,\n apiConfig,\n { kebabRoutes: options.kebabRoutes },\n );\n\n if (routeConfig.scope === 'collection' && !actionDef.isStatic) {\n console.warn(\n `[smrt] Skipping ${className}.${actionName} - collection API routes require a static method`,\n );\n continue;\n }\n\n const actionBaseDir =\n routeConfig.scope === 'collection' ? routeDir : join(routeDir, '[id]');\n actionSpecs.push({\n routeDir: join(actionBaseDir, ...routeConfig.pathSegments),\n spec: {\n lookupClassName: className,\n lookupObjectDef: objectDef,\n hostClassName: className,\n actionName,\n actionDef,\n routeConfig,\n hostType: 'item',\n },\n });\n }\n\n for (const [actionRouteDir, routeSpecs] of groupCustomActionRoutes(\n actionSpecs,\n )) {\n const actionRoute = generateActionRouteTemplate(\n projectRoot,\n actionRouteDir,\n routeSpecs,\n objectDef,\n options,\n );\n writeRoute(actionRouteDir, '+server.ts', actionRoute);\n }\n}\n\nasync function generateCollectionRoutesForObject(\n projectRoot: string,\n className: string,\n objectDef: SmartObjectDefinition,\n manifest: SmartObjectManifest,\n options: SvelteKitOptions,\n): Promise<boolean> {\n const apiConfig = objectDef.decoratorConfig?.api;\n if (apiConfig === false) {\n console.log(`[smrt] Skipping ${className} - API disabled`);\n return false;\n }\n\n const routeDir = join(projectRoot, options.routesDir, objectDef.collection);\n const lookupClassName = findItemClassRegistryKey(\n className,\n objectDef,\n manifest,\n );\n const lookupObjectDef = findObjectDefByRegistryKey(manifest, lookupClassName);\n\n const customActions = Object.entries(objectDef.methods).filter(\n ([name, method]) =>\n !STANDARD_API_ACTIONS.includes(name) &&\n method.isPublic &&\n shouldIncludeInApi(name, apiConfig),\n );\n\n if (customActions.length === 0) {\n return false;\n }\n\n let generatedAnyRoutes = false;\n const actionSpecs: Array<{\n routeDir: string;\n spec: GeneratedActionRouteSpec;\n }> = [];\n\n for (const [actionName, actionDef] of customActions) {\n const routeConfig = resolveApiActionRouteConfig(\n actionName,\n actionDef,\n apiConfig,\n { kebabRoutes: options.kebabRoutes },\n 'collection',\n );\n\n if (routeConfig.scope !== 'collection') {\n console.warn(\n `[smrt] Skipping ${className}.${actionName} - collection class methods only support collection-scoped API routes`,\n );\n continue;\n }\n\n actionSpecs.push({\n routeDir: join(routeDir, ...routeConfig.pathSegments),\n spec: {\n lookupClassName,\n lookupObjectDef,\n hostClassName: className,\n actionName,\n actionDef,\n routeConfig,\n hostType: 'collection',\n },\n });\n }\n\n for (const [actionRouteDir, routeSpecs] of groupCustomActionRoutes(\n actionSpecs,\n )) {\n const actionRoute = generateActionRouteTemplate(\n projectRoot,\n actionRouteDir,\n routeSpecs,\n objectDef,\n options,\n );\n writeRoute(actionRouteDir, '+server.ts', actionRoute);\n generatedAnyRoutes = true;\n }\n\n return generatedAnyRoutes;\n}\n\n/**\n * Resolve the list of standard CRUD actions exposed by the API for a given\n * apiConfig. Single source of truth for both the route generator and the\n * cli↔api coherence lint.\n */\nfunction resolveStandardCrudActions(apiConfig: unknown): string[] {\n if (apiConfig === false) return [];\n if (apiConfig === true || apiConfig === undefined) {\n return [...STANDARD_API_ACTIONS];\n }\n if (typeof apiConfig !== 'object') return [...STANDARD_API_ACTIONS];\n\n const config = apiConfig as { include?: string[]; exclude?: string[] };\n let crud: string[] = config.include\n ? config.include.filter((a) => STANDARD_API_ACTIONS.includes(a))\n : [...STANDARD_API_ACTIONS];\n if (Array.isArray(config.exclude)) {\n const exclude = config.exclude;\n crud = crud.filter((a) => !exclude.includes(a));\n }\n return crud;\n}\n\n/**\n * Check if a custom action should be included in API.\n *\n * Mirrors the CRUD inclusion path: intersect with `include` (when set), then\n * subtract `exclude`. Both filters apply together, matching principle of least\n * surprise for users supplying both lists.\n */\nfunction shouldIncludeInApi(actionName: string, apiConfig: any): boolean {\n if (apiConfig === false) return false;\n if (apiConfig === true || apiConfig === undefined) return true;\n\n if (typeof apiConfig === 'object') {\n const included = apiConfig.include\n ? apiConfig.include.includes(actionName)\n : true;\n const excluded = apiConfig.exclude\n ? apiConfig.exclude.includes(actionName)\n : false;\n return included && !excluded;\n }\n\n return true;\n}\n\n/**\n * Compute the set of action names (standard CRUD + custom methods) that the\n * API exposes for a given object definition. This is the same resolution used\n * to drive route generation, exposed so coherence checks (e.g. CLI vs API)\n * can ask \"what does the API expose?\" without re-implementing the logic.\n */\nexport function resolveApiActionSet(\n objectDef: SmartObjectDefinition,\n): Set<string> {\n const apiConfig = objectDef.decoratorConfig?.api;\n if (apiConfig === false) return new Set();\n\n const actions = new Set<string>(resolveStandardCrudActions(apiConfig));\n const objectIsCollectionClass = isCollectionClass(objectDef);\n const config = getApiConfigObject(apiConfig);\n\n // Custom (non-CRUD, public) methods. We mirror BOTH the include/exclude\n // filter AND the scope/static skip rules that the route generators apply\n // (sveltekit-generator.ts generateRoutesForObject and\n // generateCollectionRoutesForObject). Otherwise the cli↔api coherence lint\n // would claim \"reachable via API\" for methods that produce no HTTP route.\n for (const [name, method] of Object.entries(objectDef.methods || {})) {\n if (STANDARD_API_ACTIONS.includes(name)) continue;\n if (!method.isPublic) continue;\n if (!shouldIncludeInApi(name, apiConfig)) continue;\n\n const routeConfig: ApiCustomRouteConfig | undefined =\n config?.routes?.[name];\n const defaultScope: 'item' | 'collection' = objectIsCollectionClass\n ? 'collection'\n : method.isStatic\n ? 'collection'\n : 'item';\n const scope = routeConfig?.scope || defaultScope;\n\n if (objectIsCollectionClass) {\n // Collection classes only emit collection-scoped custom routes.\n if (scope !== 'collection') continue;\n } else {\n // Non-collection classes skip collection-scoped non-static methods\n // (the generator emits a console warning in this case).\n if (scope === 'collection' && !method.isStatic) continue;\n }\n\n actions.add(name);\n }\n\n return actions;\n}\n\n/**\n * Detail for a single cli-vs-api coherence violation.\n */\nexport interface CliApiCoherenceViolation {\n className: string;\n unreachable: string[];\n}\n\n/**\n * Inspect a manifest and return classes whose `cli.include` references\n * methods not exposed via the API. Classes that opt out via\n * `cli: { skipApiCheck: true }` are skipped.\n *\n * Throws nothing; returns the violation list so callers can choose to throw\n * or warn.\n */\nexport function findCliApiCoherenceViolations(\n manifest: SmartObjectManifest,\n): CliApiCoherenceViolation[] {\n const violations: CliApiCoherenceViolation[] = [];\n\n for (const [className, objectDef] of Object.entries(manifest.objects)) {\n const cliConfig = objectDef.decoratorConfig?.cli;\n if (!cliConfig || typeof cliConfig !== 'object') continue;\n if (cliConfig.skipApiCheck) continue;\n if (!cliConfig.include || cliConfig.include.length === 0) continue;\n\n // Match generateCLIModule's effective command set: include − exclude.\n // A command in both lists is not actually registered, so the lint must\n // not flag it as unreachable.\n const cliExclude = Array.isArray(cliConfig.exclude)\n ? cliConfig.exclude\n : [];\n const effectiveCliCommands = cliConfig.include.filter(\n (cmd: string) => !cliExclude.includes(cmd),\n );\n if (effectiveCliCommands.length === 0) continue;\n\n const apiActionSet = resolveApiActionSet(objectDef);\n const unreachable = effectiveCliCommands.filter(\n (action: string) => !apiActionSet.has(action),\n );\n\n if (unreachable.length > 0) {\n violations.push({ className, unreachable });\n }\n }\n\n return violations;\n}\n\n/**\n * Throw if any class in the manifest has `cli.include` methods that aren't\n * reachable via the API. Default build-time gate; opt-out per-class via\n * `cli: { skipApiCheck: true }` (or globally via the vite plugin option\n * `validateCliApiCoherence: false`).\n */\nexport function validateCliIncludeAgainstApi(\n manifest: SmartObjectManifest,\n): void {\n const violations = findCliApiCoherenceViolations(manifest);\n if (violations.length === 0) return;\n\n const messages = violations.flatMap(({ className, unreachable }) =>\n unreachable.map(\n (action) =>\n `[smrt] ${className}.${action} is declared in cli.include but is not exposed via the api.\\n` +\n ` Either:\\n` +\n ` - Add '${action}' to api.include, or\\n` +\n ` - Remove '${action}' from cli.include.\\n` +\n ` The CLI invokes methods over HTTP; methods without API routes are unreachable.\\n` +\n ` If this CLI is intentionally invoked in-process (no HTTP), set\\n` +\n ` \\`cli: { skipApiCheck: true }\\` on the @smrt() decorator to acknowledge.`,\n ),\n );\n\n throw new Error(messages.join('\\n\\n'));\n}\n\n/**\n * Writes a route file, creating directories as needed\n */\nfunction writeRoute(dir: string, filename: string, content: string): void {\n try {\n // Create directory if needed\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n\n // Write the file (writeFileSync is synchronous and will throw on failure)\n const filePath = join(dir, filename);\n writeFileSync(filePath, content, 'utf-8');\n console.log(`[smrt] Generated: ${filePath}`);\n } catch (error) {\n console.error(`[smrt] [ERROR] Failed to write route file:`);\n console.error(`[smrt] [ERROR] Directory: ${dir}`);\n console.error(`[smrt] [ERROR] Filename: ${filename}`);\n console.error(`[smrt] [ERROR] Error:`, error);\n throw error;\n }\n}\n\n/**\n * Converts absolute file path to SvelteKit $lib alias import\n * For SvelteKit projects, uses $lib alias for better module resolution\n */\nfunction getSvelteKitImportPath(\n projectRoot: string,\n objectFilePath: string | undefined,\n objectsDir: string,\n className?: string,\n): string {\n // Handle undefined filePath by generating a default path\n // This allows tests to work without providing explicit file paths\n const filePath =\n objectFilePath ||\n join(projectRoot, objectsDir, `${className || 'Object'}.ts`);\n\n // Convert objectsDir to absolute path if it's relative\n const absoluteObjectsDir = objectsDir.startsWith('/')\n ? objectsDir\n : join(projectRoot, objectsDir);\n\n // Get the relative path from objectsDir to the file\n const relativePath = relative(absoluteObjectsDir, filePath);\n\n // Convert to forward slashes and remove extension\n const normalizedPath = relativePath.replace(/\\\\/g, '/');\n const withoutExtension = normalizedPath.replace(/\\.(ts|js|tsx|jsx)$/, '');\n\n // If objectsDir is under src/lib, use $lib alias\n if (objectsDir.includes('src/lib')) {\n const libSubpath = objectsDir.split('src/lib')[1] || '';\n const fullPath = libSubpath\n ? `${libSubpath}/${withoutExtension}`\n : withoutExtension;\n return `$lib${fullPath}`.replace(/\\/+/g, '/'); // Clean up double slashes\n }\n\n // Otherwise use relative path (fallback for non-standard layouts)\n return withoutExtension.startsWith('.')\n ? withoutExtension\n : `./${withoutExtension}`;\n}\n\n/**\n * Check if an object's source file is local to the project (not in node_modules).\n * The scanner sets packageName for all objects (including local ones from the\n * project's own package.json), so we check the filePath to distinguish.\n */\nfunction isLocalObject(\n projectRoot: string,\n objectDef: SmartObjectDefinition,\n): boolean {\n if (!objectDef.filePath) return false;\n return (\n objectDef.filePath.startsWith(projectRoot) &&\n !objectDef.filePath.includes('/node_modules/')\n );\n}\n\n/**\n * Generates collection route template (GET list, POST create)\n */\nfunction generateCollectionRouteTemplate(\n projectRoot: string,\n className: string,\n objectDef: SmartObjectDefinition,\n includedActions: string[],\n options: SvelteKitOptions,\n routeDir: string,\n): string {\n const hasGet = includedActions.includes('list');\n const hasPost = includedActions.includes('create');\n const modelType = resolveObjectTypeReference(\n projectRoot,\n className,\n objectDef,\n options,\n routeDir,\n );\n const serializers = resolveStandardRouteSerializers(\n objectDef.decoratorConfig?.api,\n );\n const serializerImports = serializers.importStatements.join('\\n');\n\n const imports = `${AUTO_GENERATED_ROUTE_HEADER}\n// DO NOT EDIT - changes will be overwritten\n\nimport { error, json } from '@sveltejs/kit';\n${\n serializerImports ? `${serializerImports}\\n` : ''\n}import { getCollection } from '$lib/server/smrt';\n${modelType.importStatement ? `${modelType.importStatement}\\n` : ''}import type { RequestHandler } from './$types';\n// Note: ${className} is auto-registered by the Vite plugin scanner\n${generateAuthGuardHelper(objectDef)}${isTenantScoped(objectDef) ? generateTenantContextHelper() : ''}${hasPost ? generateWritablePolicyHelper(objectDef) : ''}`;\n\n const getHandler = hasGet\n ? `\n// List all ${className.toLowerCase()}s\nexport const GET: RequestHandler = async ({ locals, url }) => {\n${routeGuardPreamble(objectDef, false)}\n const limit = Number(url.searchParams.get('limit')) || 50;\n const offset = Number(url.searchParams.get('offset')) || 0;\n\n${generateCollectionLoad(className, { typeName: modelType.typeName })}\n const items = await collection.list({ limit, offset });\n const count = await collection.count();\n${\n serializers.listItemSerializerName\n ? `\n const serializedItems = await Promise.all(\n items.map((item) => ${serializers.listItemSerializerName}(item)),\n );\n\n return json({ items: serializedItems, count, limit, offset });`\n : `\n const items_public = items.map((item) => item.toPublicJSON());\n return json({ items: items_public, count, limit, offset });`\n}\n};\n`\n : '';\n\n const postHandler = hasPost\n ? `\n// Create new ${className.toLowerCase()}\nexport const POST: RequestHandler = async ({ locals, request }) => {\n${routeGuardPreamble(objectDef, true)}\n const body: unknown = await request.json();\n const data = applyWritablePolicy(body);\n\n${generateCollectionLoad(className, { typeName: modelType.typeName })}\n const item = await collection.create(data);\n await item.save();\n${\n serializers.itemSerializerName\n ? `\n const serializedItem = await ${serializers.itemSerializerName}(item);\n\n return json(serializedItem, { status: 201 });`\n : `\n return json(item.toPublicJSON(), { status: 201 });`\n}\n};\n`\n : '';\n\n return imports + getHandler + postHandler;\n}\n\nfunction generateCollectionLoad(\n className: string,\n options: { typeName?: string } = {},\n): string {\n const genericSuffix = options.typeName ? `<${options.typeName}>` : '';\n\n return [\n ` const collection = await getCollection${genericSuffix}(`,\n ` '${className}',`,\n ' );',\n ].join('\\n');\n}\n\nfunction generateNotFoundError(className: string): string {\n const singleLineNotFoundError = ` if (!item) throw error(404, '${className} not found');`;\n\n if (singleLineNotFoundError.length <= 100) {\n return singleLineNotFoundError;\n }\n\n return [\n ' if (!item)',\n ' throw error(',\n ' 404,',\n ` '${className} not found',`,\n ' );',\n ].join('\\n');\n}\n\nfunction generateCollectionNotRegisteredError(className: string): string {\n return [\n ' if (!collection)',\n ' throw error(',\n ' 500,',\n ` '${className} collection is not registered',`,\n ' );',\n ].join('\\n');\n}\n\nfunction generateClassNotRegisteredError(className: string): string {\n return [\n ' if (!registered)',\n ' throw error(',\n ' 500,',\n ` '${className} is not registered',`,\n ' );',\n ].join('\\n');\n}\n\n/**\n * Generates item route template (GET, PUT, DELETE)\n */\nfunction generateItemRouteTemplate(\n projectRoot: string,\n className: string,\n objectDef: SmartObjectDefinition,\n includedActions: string[],\n options: SvelteKitOptions,\n routeDir: string,\n): string {\n const hasGet = includedActions.includes('get');\n const hasPut = includedActions.includes('update');\n const hasDelete = includedActions.includes('delete');\n const simpleClassName = extractSimpleClassName(className);\n const modelType = resolveObjectTypeReference(\n projectRoot,\n className,\n objectDef,\n options,\n routeDir,\n );\n const serializers = resolveStandardRouteSerializers(\n objectDef.decoratorConfig?.api,\n );\n const serializerImports = serializers.importStatements.join('\\n');\n\n const imports = `${AUTO_GENERATED_ROUTE_HEADER}\n// DO NOT EDIT - changes will be overwritten\n\nimport { error, json } from '@sveltejs/kit';\n${serializerImports ? `${serializerImports}\\n` : ''}import { getCollection } from '$lib/server/smrt';\n${modelType.importStatement ? `${modelType.importStatement}\\n` : ''}import type { RequestHandler } from './$types';\n${generateAuthGuardHelper(objectDef)}${isTenantScoped(objectDef) ? generateTenantContextHelper() : ''}${hasPut ? generateWritablePolicyHelper(objectDef) : ''}`;\n\n const getHandler = hasGet\n ? `\n// Get single ${simpleClassName.toLowerCase()}\nexport const GET: RequestHandler = async ({ locals, params }) => {\n${routeGuardPreamble(objectDef, false)}\n${generateCollectionLoad(className, { typeName: modelType.typeName })}\n const item = await collection.get(params.id);\n${generateNotFoundError(className)}\n${\n serializers.itemSerializerName\n ? `\n const serializedItem = await ${serializers.itemSerializerName}(item);\n\n return json(serializedItem);`\n : `\n return json(item.toPublicJSON());`\n}\n};\n`\n : '';\n\n const putHandler = hasPut\n ? `\n// Update ${simpleClassName.toLowerCase()}\nexport const PUT: RequestHandler = async ({ locals, params, request }) => {\n${routeGuardPreamble(objectDef, true)}\n${generateCollectionLoad(className, { typeName: modelType.typeName })}\n const item = await collection.get(params.id);\n${generateNotFoundError(className)}\n\n const body: unknown = await request.json();\n const data = applyWritablePolicy(body);\n Object.assign(item, data);\n await item.save();\n${\n serializers.itemSerializerName\n ? `\n const serializedItem = await ${serializers.itemSerializerName}(item);\n\n return json(serializedItem);`\n : `\n return json(item.toPublicJSON());`\n}\n};\n`\n : '';\n\n const deleteHandler = hasDelete\n ? `\n// Delete ${simpleClassName.toLowerCase()}\nexport const DELETE: RequestHandler = async ({ locals, params }) => {\n${routeGuardPreamble(objectDef, true)}\n${generateCollectionLoad(className, { typeName: modelType.typeName })}\n const item = await collection.get(params.id);\n${generateNotFoundError(className)}\n\n await item.delete();\n return json({ success: true });\n};\n`\n : '';\n\n return imports + getHandler + putHandler + deleteHandler;\n}\n\n/**\n * Generates custom action route template\n */\nfunction generateActionRouteTemplate(\n projectRoot: string,\n routeDir: string,\n routeSpecs: GeneratedActionRouteSpec[],\n objectDef: SmartObjectDefinition,\n options: SvelteKitOptions,\n): string {\n if (routeSpecs.length === 0) {\n throw new Error('Cannot generate a custom action route without handlers');\n }\n\n const [firstSpec] = routeSpecs;\n const { lookupClassName, routeConfig, hostType } = firstSpec;\n const lookupModelType = resolveObjectTypeReference(\n projectRoot,\n lookupClassName,\n firstSpec.lookupObjectDef,\n options,\n routeDir,\n );\n const hostModelType = resolveObjectTypeReference(\n projectRoot,\n firstSpec.hostClassName,\n objectDef,\n options,\n routeDir,\n );\n const typeImports = mergeImportStatements([\n lookupModelType.importStatement,\n hostModelType.importStatement,\n ]);\n\n const hasMixedHosts = routeSpecs.some(\n (spec) =>\n spec.hostType !== hostType ||\n spec.lookupClassName !== lookupClassName ||\n spec.routeConfig.scope !== routeConfig.scope,\n );\n\n if (hasMixedHosts) {\n throw new Error(\n `Cannot generate mixed custom route handlers for ${lookupClassName}. ` +\n 'All handlers sharing a route path must target the same host type and scope.',\n );\n }\n\n const importBlock = [\n \"import { error, json } from '@sveltejs/kit';\",\n hostType === 'collection' || routeConfig.scope !== 'collection'\n ? \"import { getCollection } from '$lib/server/smrt';\"\n : \"import { ObjectRegistry } from '@happyvertical/smrt-core';\",\n typeImports,\n \"import type { RequestHandler } from './$types';\",\n ]\n .filter(Boolean)\n .join('\\n');\n\n const tenantScoped =\n isTenantScoped(objectDef) ||\n routeSpecs.some(\n (spec) => !!spec.lookupObjectDef && isTenantScoped(spec.lookupObjectDef),\n );\n const handlers = routeSpecs\n .map((spec) =>\n generateActionRouteHandler(\n spec.lookupClassName,\n spec.actionName,\n spec.actionDef,\n spec.routeConfig,\n spec.hostType,\n tenantScoped,\n lookupModelType.typeName,\n hostModelType.typeName,\n ),\n )\n .join('\\n');\n\n return `${AUTO_GENERATED_ROUTE_HEADER}\n// DO NOT EDIT - changes will be overwritten\n\n${importBlock}\n${generateAuthGuardHelper(objectDef)}${tenantScoped ? generateTenantContextHelper() : ''}\n${handlers}`;\n}\n\nfunction generateActionRouteHandler(\n lookupClassName: string,\n actionName: string,\n actionDef: any,\n routeConfig: ResolvedApiActionRouteConfig,\n hostType: 'item' | 'collection',\n tenantScoped: boolean,\n lookupTypeName: string,\n hostTypeName: string,\n): string {\n const handlerName = routeConfig.method;\n // Mutating verbs require auth even when reads are public (#1540). Tenant-scoped\n // objects also establish tenant context so the action runs filtered.\n const guardLines = [\n ` requireRouteAuth(locals, ${routeConfig.method !== 'GET'});`,\n ];\n if (tenantScoped) {\n guardLines.push(' establishTenantContext(locals);');\n }\n const authGuardLine = guardLines.join('\\n');\n const hasInput = actionDef.parameters.length > 0;\n const needsRequest = hasInput;\n const invocationArgs = buildActionInvocationArgs(actionDef);\n const collectionHandlerArgs = buildRouteHandlerArgs(\n routeConfig.pathParamNames.length > 0,\n needsRequest,\n );\n const itemHandlerArgs = buildRouteHandlerArgs(true, needsRequest);\n\n if (hostType === 'collection') {\n const optionsLoad = buildActionOptionsLoad(\n actionName,\n actionDef,\n routeConfig,\n hostTypeName,\n actionDef.isStatic,\n );\n const receiverExpression = actionDef.isStatic\n ? 'CollectionClass'\n : 'typedCollection';\n const staticTargetLoad = actionDef.isStatic\n ? ` const CollectionClass = typedCollection.constructor as typeof ${hostTypeName};\\n`\n : '';\n\n return `// Custom collection method: ${actionName}\nexport const ${handlerName}: RequestHandler = async (${collectionHandlerArgs}) => {\n${authGuardLine}\n${generateCollectionLoad(lookupClassName, { typeName: lookupTypeName })}\n const typedCollection = collection as unknown as ${hostTypeName};\n${generateCollectionNotRegisteredError(lookupClassName)}\n${staticTargetLoad}\n\n${optionsLoad} const result = ${buildActionInvocationExpression(\n receiverExpression,\n actionName,\n invocationArgs,\n )};\n\n return json({ action: '${actionName}', result: toPublicResult(result) });\n};\n`;\n }\n\n if (routeConfig.scope === 'collection') {\n const optionsLoad = buildActionOptionsLoad(\n actionName,\n actionDef,\n routeConfig,\n hostTypeName,\n true,\n );\n return `// Custom collection action: ${actionName}\nexport const ${handlerName}: RequestHandler = async (${collectionHandlerArgs}) => {\n${authGuardLine}\n const registered = ObjectRegistry.getClass('${lookupClassName}');\n${generateClassNotRegisteredError(lookupClassName)}\n\n${optionsLoad} const ClassRef = registered.constructor as typeof ${hostTypeName};\n const result = ${buildActionInvocationExpression(\n 'ClassRef',\n actionName,\n invocationArgs,\n )};\n\n return json({ action: '${actionName}', result: toPublicResult(result) });\n};\n`;\n }\n\n const optionsLoad = buildActionOptionsLoad(\n actionName,\n actionDef,\n routeConfig,\n hostTypeName,\n false,\n );\n return `// Custom action: ${actionName}\nexport const ${handlerName}: RequestHandler = async (${itemHandlerArgs}) => {\n${authGuardLine}\n${generateCollectionLoad(lookupClassName, { typeName: lookupTypeName })}\n const item = await collection.get(params.id);\n${generateNotFoundError(lookupClassName)}\n\n${optionsLoad} const result = ${buildActionInvocationExpression(\n 'item',\n actionName,\n invocationArgs,\n )};\n\n return json({ action: '${actionName}', result: toPublicResult(result) });\n};\n`;\n}\n\nfunction generateKnowledgeRouteTemplate(\n knowledge: DomainKnowledgeConfig,\n artifact: Record<string, unknown> | null,\n): string {\n const api = knowledge.api ?? {};\n const includeDocs = api.includeDocs === true;\n const includePrompts = api.includePrompts === true;\n const requireAdmin = api.requireAdmin !== false;\n const artifactLiteral = artifact ? JSON.stringify(artifact) : 'null';\n\n return `${AUTO_GENERATED_ROUTE_HEADER}\n// DO NOT EDIT - changes will be overwritten\n\nimport { dev } from '$app/environment';\nimport { error, json } from '@sveltejs/kit';\nimport type { RequestHandler } from './$types';\n\nconst INCLUDE_DOCS_BY_DEFAULT = ${JSON.stringify(includeDocs)};\nconst INCLUDE_PROMPTS_BY_DEFAULT = ${JSON.stringify(includePrompts)};\nconst REQUIRE_ADMIN = ${JSON.stringify(requireAdmin)};\nconst KNOWLEDGE_ARTIFACT: Record<string, unknown> | null = ${artifactLiteral};\n\nif (!dev && !REQUIRE_ADMIN) {\n console.warn('[smrt] PUBLIC knowledge API route enabled; unauthenticated responses are sanitized.');\n}\n\nexport const GET: RequestHandler = async ({ locals, url, setHeaders }) => {\n setHeaders({ 'cache-control': 'private, no-store' });\n\n if (!dev && REQUIRE_ADMIN && !isKnowledgeAdmin(locals)) {\n throw error(403, 'SMRT knowledge requires dev mode or admin access');\n }\n\n const artifact = readKnowledgeArtifact();\n const includeDocs = queryBoolean(url, 'includeDocs', INCLUDE_DOCS_BY_DEFAULT);\n const includePrompts = queryBoolean(\n url,\n 'includePrompts',\n INCLUDE_PROMPTS_BY_DEFAULT,\n );\n\n return json(sanitizeKnowledgeArtifact(artifact, {\n includeDocs,\n includePrompts,\n publicAccess: !REQUIRE_ADMIN,\n }));\n};\n\nfunction readKnowledgeArtifact(): Record<string, unknown> {\n if (!KNOWLEDGE_ARTIFACT) throw error(404, 'SMRT knowledge artifact not found');\n return KNOWLEDGE_ARTIFACT;\n}\n\nfunction queryBoolean(url: URL, name: string, defaultValue: boolean): boolean {\n const value = url.searchParams.get(name);\n if (value === null) return defaultValue;\n return value === 'true';\n}\n\nfunction sanitizeKnowledgeArtifact(\n artifact: Record<string, unknown>,\n options: { includeDocs: boolean; includePrompts: boolean; publicAccess: boolean },\n): Record<string, unknown> {\n const sanitized = { ...artifact };\n\n if (!options.includeDocs) {\n delete sanitized.agentDoc;\n }\n\n if (!options.includePrompts) {\n sanitized.prompts = [];\n }\n\n if (options.publicAccess) {\n delete sanitized.dependencies;\n delete sanitized.sourceHashes;\n delete sanitized.sourceManifestPath;\n delete sanitized.agentDocPath;\n }\n\n return sanitized;\n}\n\nfunction recordValue(value: unknown, key: string): unknown {\n if (!value || typeof value !== 'object') return undefined;\n return (value as Record<string, unknown>)[key];\n}\n\nfunction isKnowledgeAdmin(locals: unknown): boolean {\n if (!locals || typeof locals !== 'object') return false;\n const localRecord = locals as Record<string, unknown>;\n if (\n localRecord.smrtKnowledgeAdmin === true ||\n localRecord.smrtAdmin === true\n ) {\n return true;\n }\n\n const userRoles = rolesFrom(localRecord.user);\n const sessionRoles = rolesFrom(recordValue(localRecord.session, 'user'));\n return [...userRoles, ...sessionRoles].some((role) =>\n ['admin', 'owner', 'superadmin'].includes(role),\n );\n}\n\nfunction rolesFrom(value: unknown): string[] {\n if (!value || typeof value !== 'object') return [];\n const roleList = recordValue(value, 'roles');\n const roles = Array.isArray(roleList) ? roleList : [recordValue(value, 'role')];\n return roles\n .filter((role): role is string => typeof role === 'string')\n .map((role) => role.toLowerCase());\n}\n`;\n}\n\n/**\n * Updates .gitignore to exclude auto-generated routes\n */\nfunction updateGitignore(projectRoot: string, options: SvelteKitOptions): void {\n const gitignorePath = join(projectRoot, '.gitignore');\n\n // Patterns to add\n const patternsToAdd = [\n '# SMRT auto-generated routes (from Vite plugin)',\n `${options.routesDir}/**/+server.ts`,\n ];\n if (options.knowledge?.api?.enabled) {\n const knowledgeRoute = relative(\n projectRoot,\n join(knowledgeRouteDir(projectRoot, options), '+server.ts'),\n ).replaceAll('\\\\', '/');\n patternsToAdd.push(knowledgeRoute);\n }\n\n // Read existing .gitignore or create empty string\n let gitignoreContent = '';\n if (existsSync(gitignorePath)) {\n gitignoreContent = readFileSync(gitignorePath, 'utf-8');\n }\n\n // Check if patterns already exist\n let needsUpdate = false;\n const linesToAdd: string[] = [];\n\n for (const pattern of patternsToAdd) {\n // Skip if pattern already exists (check for exact match or similar)\n if (!gitignoreContent.includes(pattern)) {\n linesToAdd.push(pattern);\n needsUpdate = true;\n }\n }\n\n if (needsUpdate) {\n // Ensure file ends with newline before adding\n if (gitignoreContent.length > 0 && !gitignoreContent.endsWith('\\n')) {\n gitignoreContent += '\\n';\n }\n\n // Add a blank line before our section if file has content\n if (gitignoreContent.length > 0 && !gitignoreContent.endsWith('\\n\\n')) {\n gitignoreContent += '\\n';\n }\n\n // Add our patterns\n gitignoreContent += `${linesToAdd.join('\\n')}\\n`;\n\n writeFileSync(gitignorePath, gitignoreContent, 'utf-8');\n console.log('[smrt] Updated .gitignore with generated route patterns');\n }\n}\n"],"names":["segment","imports","optionsLoad"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@happyvertical/smrt-core",
|
|
3
|
-
"version": "0.36.
|
|
3
|
+
"version": "0.36.2",
|
|
4
4
|
"description": "Core AI agent framework with standardized collections, object-relational mapping, and code generators",
|
|
5
5
|
"author": "HappyVertical",
|
|
6
6
|
"type": "module",
|
|
@@ -153,9 +153,9 @@
|
|
|
153
153
|
"tsx": "^4.21.0",
|
|
154
154
|
"typescript": "^5.9.3",
|
|
155
155
|
"yaml": "^2.8.2",
|
|
156
|
-
"@happyvertical/smrt-config": "0.36.
|
|
157
|
-
"@happyvertical/smrt-
|
|
158
|
-
"@happyvertical/smrt-
|
|
156
|
+
"@happyvertical/smrt-config": "0.36.2",
|
|
157
|
+
"@happyvertical/smrt-types": "0.36.2",
|
|
158
|
+
"@happyvertical/smrt-scanner": "0.36.2"
|
|
159
159
|
},
|
|
160
160
|
"peerDependencies": {
|
|
161
161
|
"@huggingface/transformers": ">=3.0.0 <4.0.0",
|