@stratal/inertia 0.0.1 → 0.0.18

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.
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.mjs","names":[],"sources":["../src/augment/router-context.ts","../src/vite/create-vite-config.ts","../src/commands/inertia-build.command.ts","../src/commands/inertia-dev.command.ts","../src/commands/inertia-install.command.ts","../src/commands/inertia-types.command.ts","../src/inertia.tokens.ts","../src/middleware/inertia.middleware.ts","../src/types.ts","../src/services/inertia.service.ts","../src/services/manifest.service.ts","../src/services/ssr-renderer.service.ts","../src/services/template.service.ts","../src/inertia.module.ts","../src/decorators/inertia-route.decorator.ts"],"sourcesContent":["import type { RedirectStatusCode } from 'hono/utils/http-status'\nimport { RouterContext } from 'stratal/router'\nimport type { InertiaService } from '../services/inertia.service'\nimport type {\n InertiaDeferredProp,\n InertiaMergeProp,\n InertiaOptionalProp,\n InertiaPageComponent,\n InertiaPageRegistry,\n InertiaRenderOptions,\n ResolvedInertiaPageProps,\n} from '../types'\n\ndeclare module 'stratal/router' {\n interface RouterContext {\n inertia<C extends InertiaPageComponent>(\n component: C,\n ...args: keyof InertiaPageRegistry extends never\n ? [props?: Record<string, unknown>, options?: InertiaRenderOptions]\n : Record<string, never> extends ResolvedInertiaPageProps<C>\n ? [props?: ResolvedInertiaPageProps<C>, options?: InertiaRenderOptions]\n : [props: ResolvedInertiaPageProps<C>, options?: InertiaRenderOptions]\n ): Promise<Response>\n defer(callback: () => unknown, group?: string): InertiaDeferredProp\n optional(callback: () => unknown): InertiaOptionalProp\n merge(callback: () => unknown): InertiaMergeProp\n withoutSsr(): void\n }\n}\n\nexport function augmentRouterContext(resolveService: (ctx: RouterContext) => InertiaService): void {\n const proto = RouterContext.prototype\n\n // Override redirect to auto-convert 302 → 303 for non-GET/HEAD requests\n // so the browser follows with GET instead of preserving the original method\n // eslint-disable-next-line @typescript-eslint/unbound-method -- intentionally saving reference, called with .call(this)\n const originalRedirect = proto.redirect\n proto.redirect = function (this: RouterContext, url: string, status?: RedirectStatusCode) {\n if (!status || status === 302) {\n const method = this.c.req.method\n if (method !== 'GET' && method !== 'HEAD') {\n return originalRedirect.call(this, url, 303)\n }\n }\n return originalRedirect.call(this, url, status)\n }\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n proto.inertia = function (this: RouterContext, component: string, props?: any, options?: InertiaRenderOptions) {\n const service = resolveService(this)\n return service.render(this, component, props as Record<string, unknown>, options)\n }\n\n proto.defer = function (this: RouterContext, callback: () => unknown, group?: string) {\n const service = resolveService(this)\n return service.defer(callback, group)\n }\n\n proto.optional = function (this: RouterContext, callback: () => unknown) {\n const service = resolveService(this)\n return service.optional(callback)\n }\n\n proto.merge = function (this: RouterContext, callback: () => unknown) {\n const service = resolveService(this)\n return service.merge(callback)\n }\n\n proto.withoutSsr = function (this: RouterContext) {\n this.c.set('withoutSsr', true)\n }\n}\n","import { existsSync } from 'node:fs'\nimport { join } from 'node:path'\nimport type { EnvironmentOptions, Plugin, UserConfig } from 'vite'\n\nexport interface InertiaViteConfigOptions {\n cwd: string\n entryPath: string\n outDir?: string\n server?: { port?: number; host?: boolean }\n}\n\nexport async function createInertiaViteConfig(options: InertiaViteConfigOptions): Promise<UserConfig> {\n const { mergeConfig } = await import('vite')\n\n let userConfig = {}\n const viteConfigPath = join(options.cwd, 'vite.config.ts')\n if (existsSync(viteConfigPath)) {\n const loaded = await import(/* @vite-ignore */ viteConfigPath) as Record<string, unknown>\n userConfig = loaded.default ?? loaded\n }\n\n const { cloudflare } = await import('@cloudflare/vite-plugin') as unknown as { cloudflare: () => Plugin }\n\n const { stratalInertiaDevCss } = await import('./inertia-dev-css-plugin')\n const { stratalInertiaTypes } = await import('./inertia-types-plugin')\n\n // Check if user's config already includes the @inertiajs/vite plugin\n const userPlugins = Array.isArray((userConfig as UserConfig).plugins)\n ? (userConfig as UserConfig).plugins!.flat()\n : []\n const hasInertiaPlugin = userPlugins.some(\n (p) => p && typeof p === 'object' && 'name' in p && (p as Plugin).name === 'inertia',\n )\n\n const inertiaPlugins: Plugin[] = []\n if (!hasInertiaPlugin) {\n try {\n const { default: inertia } = await import('@inertiajs/vite') as { default: (opts?: Record<string, unknown>) => Plugin }\n inertiaPlugins.push(inertia({\n pages: { path: './src/inertia/pages', extension: '.tsx' },\n }))\n } catch {\n // @inertiajs/vite not installed — skip\n }\n }\n\n const optimizeDepsExclude = ['@cloudflare/vite-plugin', 'wrangler', 'blake3-wasm']\n\n const baseConfig: UserConfig = {\n plugins: [\n cloudflare(),\n ...inertiaPlugins,\n stratalInertiaDevCss({ entries: ['/' + options.entryPath] }),\n stratalInertiaTypes(),\n {\n name: 'stratal:optimize-deps-fix',\n configEnvironment(_name: string, env: EnvironmentOptions) {\n const existing = env.optimizeDeps?.exclude ?? []\n env.optimizeDeps = {\n ...env.optimizeDeps,\n exclude: [...existing, ...optimizeDepsExclude],\n }\n },\n },\n ],\n publicDir: join(options.cwd, 'src', 'inertia', 'public'),\n build: {\n ...(options.outDir ? { outDir: options.outDir } : {}),\n rolldownOptions: {\n input: options.entryPath,\n },\n },\n ...(options.server ? {\n server: {\n port: options.server.port,\n host: options.server.host ?? undefined,\n },\n } : {}),\n }\n\n return mergeConfig(baseConfig, userConfig)\n}\n","import { existsSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { Command } from 'stratal/quarry'\nimport { createInertiaViteConfig } from '../vite/create-vite-config'\n\nexport class InertiaBuildCommand extends Command {\n static command = 'inertia:build {--outDir=dist : Output directory} {--ssr : Also build SSR bundle}'\n static description = 'Build Inertia.js frontend for production'\n\n async handle(): Promise<number | undefined> {\n const outDir = this.string('outDir') || 'dist'\n const shouldBuildSsr = this.boolean('ssr')\n const cwd = process.cwd()\n\n const entryPath = 'src/inertia/app.tsx'\n if (!existsSync(join(cwd, entryPath))) {\n this.fail('src/inertia/app.tsx not found. Run `quarry inertia:install` first.')\n return 1\n }\n\n this.info('Building Inertia.js frontend for production...')\n\n try {\n const { build } = await import('vite')\n\n const config = await createInertiaViteConfig({\n cwd,\n entryPath,\n outDir,\n })\n\n await build(config)\n this.success('Client build complete!')\n\n if (shouldBuildSsr) {\n this.info('Building SSR bundle...')\n await build({\n ...config,\n build: {\n ...config.build,\n ssr: true,\n },\n })\n this.success('SSR build complete!')\n }\n\n this.success(`Output in ${outDir}/`)\n } catch (err) {\n this.fail(`Build failed: ${(err as Error).message}`)\n return 1\n }\n\n return 0\n }\n}\n","import { existsSync } from 'node:fs'\nimport { join } from 'node:path'\nimport { Command } from 'stratal/quarry'\nimport { createInertiaViteConfig } from '../vite/create-vite-config'\n\nexport class InertiaDevCommand extends Command {\n static command = 'inertia:dev {--port=5173 : Dev server port} {--host : Expose to network}'\n static description = 'Start Inertia.js Vite development server'\n\n async handle(): Promise<number | undefined> {\n const port = this.number('port') || 5173\n const host = this.boolean('host')\n const cwd = process.cwd()\n\n const entryPath = 'src/inertia/app.tsx'\n if (!existsSync(join(cwd, entryPath))) {\n this.fail('src/inertia/app.tsx not found. Run `quarry inertia:install` first.')\n return 1\n }\n\n this.info('Starting Vite dev server...')\n\n try {\n const { createServer } = await import('vite')\n\n const config = await createInertiaViteConfig({\n cwd,\n entryPath,\n server: { port, host },\n })\n\n const server = await createServer(config)\n await server.listen()\n server.printUrls()\n } catch (err) {\n this.fail(`Failed to start dev server: ${(err as Error).message}`)\n return 1\n }\n\n return 0\n }\n}\n","import { existsSync, mkdirSync, writeFileSync } from 'node:fs'\nimport { join, relative } from 'node:path'\nimport { Command } from 'stratal/quarry'\nimport { runTypeGeneration } from '../generator/type-generator'\n\nconst ROOT_HTML = `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\" />\n @viteHead\n @inertiaHead\n</head>\n<body>\n @inertia\n @viteScripts\n</body>\n</html>`\n\nconst APP_TSX = `import { createInertiaApp } from '@inertiajs/react'\n\ncreateInertiaApp()`\n\nconst HOME_TSX = `export default function Home({ message }: { message: string }) {\n return (\n <div>\n <h1>{message}</h1>\n <p>This page is rendered with Inertia.js and Stratal.</p>\n </div>\n )\n}`\n\nexport class InertiaInstallCommand extends Command {\n static command = 'inertia:install {--skip-deps : Skip installing npm dependencies}'\n static description = 'Scaffold Inertia.js files for a Stratal project'\n\n async handle(): Promise<number | undefined> {\n const skipDeps = this.boolean('skip-deps')\n const cwd = process.cwd()\n const inertiaDir = join(cwd, 'src', 'inertia')\n const pagesDir = join(inertiaDir, 'pages')\n\n // Create directories\n this.info('Creating src/inertia/ directory...')\n mkdirSync(pagesDir, { recursive: true })\n\n const publicDir = join(inertiaDir, 'public')\n mkdirSync(publicDir, { recursive: true })\n const gitkeepPath = join(publicDir, '.gitkeep')\n if (!existsSync(gitkeepPath)) {\n writeFileSync(gitkeepPath, '', 'utf-8')\n }\n this.success('Created src/inertia/public/')\n\n // Write template files\n const files = [\n { path: join(inertiaDir, 'root.html'), content: ROOT_HTML, name: 'root.html' },\n { path: join(inertiaDir, 'app.tsx'), content: APP_TSX, name: 'app.tsx' },\n { path: join(pagesDir, 'Home.tsx'), content: HOME_TSX, name: 'pages/Home.tsx' },\n ]\n\n for (const file of files) {\n if (existsSync(file.path)) {\n this.warn(`Skipping ${file.name} (already exists)`)\n } else {\n writeFileSync(file.path, file.content, 'utf-8')\n this.success(`Created src/inertia/${file.name}`)\n }\n }\n\n // Modify app.module.ts\n const appModulePath = join(cwd, 'src', 'app.module.ts')\n if (existsSync(appModulePath)) {\n this.info('Updating src/app.module.ts...')\n try {\n const updated = await this.updateAppModule(appModulePath)\n if (updated) {\n this.success('Updated src/app.module.ts with InertiaModule')\n } else {\n this.info('InertiaModule already configured in app.module.ts')\n }\n } catch (err) {\n this.warn(`Could not auto-update app.module.ts: ${(err as Error).message}`)\n this.info('Please manually add InertiaModule.forRoot() to your module imports')\n }\n } else {\n this.info('No src/app.module.ts found — please manually configure InertiaModule')\n }\n\n // Generate initial type definitions\n try {\n const { outputPath, pageCount } = await runTypeGeneration(cwd)\n const relPath = relative(cwd, outputPath)\n this.success(`Generated ${relPath} (${pageCount} page${pageCount !== 1 ? 's' : ''})`)\n } catch {\n this.warn('Could not generate initial type definitions. Run `quarry inertia:types` manually.')\n }\n\n if (!skipDeps) {\n this.newLine()\n this.info('Install the following dependencies:')\n this.line(' npm install @stratal/inertia @inertiajs/react @inertiajs/vite react react-dom')\n this.line(' npm install -D @types/react @types/react-dom vite @cloudflare/vite-plugin')\n }\n\n this.newLine()\n this.success('Inertia.js scaffolding complete!')\n this.info('Run `quarry inertia:dev` to start the dev server')\n\n return 0\n }\n\n private async updateAppModule(modulePath: string): Promise<boolean> {\n const { Project, SyntaxKind } = await import('ts-morph')\n\n const project = new Project({ useInMemoryFileSystem: false })\n const sourceFile = project.addSourceFileAtPath(modulePath)\n\n // Check if InertiaModule is already imported\n const existingImport = sourceFile.getImportDeclaration((decl) =>\n decl.getModuleSpecifierValue() === '@stratal/inertia',\n )\n if (existingImport) {\n return false\n }\n\n // Add rootView import\n sourceFile.addImportDeclaration({\n defaultImport: 'rootView',\n moduleSpecifier: './inertia/root.html?raw',\n })\n\n // Add InertiaModule import\n sourceFile.addImportDeclaration({\n namedImports: ['InertiaModule'],\n moduleSpecifier: '@stratal/inertia',\n })\n\n // Find the @Module decorator and add InertiaModule to imports\n const classes = sourceFile.getClasses()\n for (const cls of classes) {\n const moduleDecorator = cls.getDecorator('Module')\n if (!moduleDecorator) continue\n\n const args = moduleDecorator.getArguments()\n if (args.length === 0) continue\n\n const objLiteral = args[0].asKind(SyntaxKind.ObjectLiteralExpression)\n if (!objLiteral) continue\n\n const importsProp = objLiteral.getProperty('imports')\n if (importsProp) {\n // Add to existing imports array\n const initializer = importsProp.asKind(SyntaxKind.PropertyAssignment)?.getInitializer()\n const arrayLiteral = initializer?.asKind(SyntaxKind.ArrayLiteralExpression)\n if (arrayLiteral) {\n arrayLiteral.addElement(`InertiaModule.forRoot({\\n rootView,\\n })`)\n }\n } else {\n // Add imports property\n objLiteral.addPropertyAssignment({\n name: 'imports',\n initializer: `[\\n InertiaModule.forRoot({\\n rootView,\\n }),\\n ]`,\n })\n }\n\n break\n }\n\n await sourceFile.save()\n return true\n }\n}\n","import { existsSync } from 'node:fs'\nimport { watch } from 'node:fs/promises'\nimport { relative } from 'node:path'\nimport { Command } from 'stratal/quarry'\nimport { findPagesDir, runTypeGeneration } from '../generator/type-generator'\n\nexport class InertiaTypesCommand extends Command {\n static command = 'inertia:types {--watch : Watch for changes and regenerate}'\n static description = 'Generate Inertia.js page type definitions'\n\n async handle(): Promise<number | undefined> {\n const cwd = process.cwd()\n const pagesDir = findPagesDir(cwd)\n\n if (!existsSync(pagesDir)) {\n this.fail('src/inertia/pages/ not found. Run `quarry inertia:install` first.')\n return 1\n }\n\n const result = await this.generate(cwd)\n if (!result) return 1\n\n if (this.boolean('watch')) {\n this.info('Watching for changes...')\n await this.watchForChanges(cwd, pagesDir)\n }\n\n return 0\n }\n\n private async generate(cwd: string): Promise<boolean> {\n try {\n const { outputPath, pageCount } = await runTypeGeneration(cwd)\n const relPath = relative(cwd, outputPath)\n this.success(`Generated ${relPath} (${pageCount} page${pageCount !== 1 ? 's' : ''})`)\n return true\n } catch (err) {\n this.fail(`Type generation failed: ${(err as Error).message}`)\n return false\n }\n }\n\n private async watchForChanges(cwd: string, pagesDir: string): Promise<void> {\n try {\n const watcher = watch(pagesDir, { recursive: true })\n for await (const event of watcher) {\n if (event.filename && /\\.(tsx|ts)$/.test(event.filename)) {\n this.info(`Change detected: ${event.filename}`)\n await this.generate(cwd)\n }\n }\n } catch (err) {\n this.fail(`Watch failed: ${(err as Error).message}`)\n }\n }\n}\n","export const INERTIA_TOKENS = {\n Options: Symbol.for('stratal:inertia:options'),\n InertiaService: Symbol.for('stratal:inertia:service'),\n TemplateService: Symbol.for('stratal:inertia:template'),\n ManifestService: Symbol.for('stratal:inertia:manifest'),\n SsrRenderer: Symbol.for('stratal:inertia:ssr-renderer'),\n} as const\n","import { Transient, inject } from 'stratal/di'\nimport type { Middleware, RouterContext } from 'stratal/router'\nimport type { InertiaModuleOptions } from '../inertia.options'\nimport { INERTIA_TOKENS } from '../inertia.tokens'\n\n@Transient()\nexport class InertiaMiddleware implements Middleware {\n constructor(\n @inject(INERTIA_TOKENS.Options) private readonly options: InertiaModuleOptions,\n ) { }\n\n async handle(ctx: RouterContext, next: () => Promise<void>): Promise<void> {\n const isInertia = ctx.header('x-inertia') === 'true'\n const isPrefetch = ctx.header('purpose') === 'prefetch'\n\n // Store Inertia state on context for services to access\n ctx.c.set('inertia', isInertia)\n ctx.c.set('inertiaPrefetch', isPrefetch)\n ctx.c.set('withoutSsr', false)\n\n // Version mismatch check on GET requests\n if (isInertia && ctx.c.req.method === 'GET') {\n const clientVersion = ctx.header('x-inertia-version')\n const serverVersion = this.options.version ?? ''\n\n if (clientVersion && serverVersion && clientVersion !== serverVersion) {\n ctx.c.header('X-Inertia-Location', ctx.c.req.url)\n ctx.c.status(409)\n return\n }\n }\n\n await next()\n\n // Add Vary header to all responses\n ctx.c.header('Vary', 'X-Inertia')\n\n // Convert 302 to 303 for non-GET/HEAD Inertia requests\n if (isInertia) {\n const method = ctx.c.req.method\n const status = ctx.c.res.status\n\n if (status === 302 && method !== 'GET' && method !== 'HEAD') {\n ctx.c.status(303)\n }\n }\n }\n}\n","import type { SharedPageProps } from '@inertiajs/core'\nimport type { RouterContext } from 'stratal/router'\n\n\nexport interface InertiaPageRegistry {}\n\n// Derive shared props from @inertiajs/core's InertiaConfig.sharedPageProps.\n// Users augment InertiaConfig in their global.d.ts — this type stays in sync automatically.\nexport type InertiaSharedProps = SharedPageProps\n\nexport type InertiaPageComponent = keyof InertiaPageRegistry extends never\n ? string\n : Extract<keyof InertiaPageRegistry, string>\n\n// Allows each prop value to be wrapped with defer/merge/optional\ntype AllowInertiaWrappers<T> = {\n [K in keyof T]: T[K] | InertiaDeferredProp | InertiaMergeProp | InertiaOptionalProp\n}\n\n// Props the controller passes to ctx.inertia() — page-specific only, shared props are auto-injected\n// Each prop can be the raw value OR a deferred/merge/optional wrapper\nexport type ResolvedInertiaPageProps<C extends InertiaPageComponent> =\n C extends keyof InertiaPageRegistry ? AllowInertiaWrappers<InertiaPageRegistry[C]> : Record<string, unknown>\n\n// Full props the React page component receives — page-specific + shared (auto-injected), no wrappers\nexport type InertiaFullPageProps<C extends InertiaPageComponent> =\n (C extends keyof InertiaPageRegistry ? InertiaPageRegistry[C] : Record<string, unknown>) & InertiaSharedProps\n\nexport interface InertiaPage {\n component: string\n props: Record<string, unknown>\n url: string\n version: string\n mergeProps: string[]\n deferredProps: Record<string, string[]>\n encryptHistory?: boolean\n clearHistory?: boolean\n}\n\nexport interface InertiaRenderOptions {\n encryptHistory?: boolean\n clearHistory?: boolean\n}\n\nexport interface InertiaSsrResult {\n head: string[]\n body: string\n}\n\nexport interface InertiaSsrBundle {\n render(page: InertiaPage): Promise<InertiaSsrResult>\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport type SharedDataResolver = (ctx: RouterContext) => any\n\nexport interface ViteManifestEntry {\n file: string\n css?: string[]\n isEntry?: boolean\n imports?: string[]\n dynamicImports?: string[]\n src?: string\n}\n\nexport type ViteManifest = Record<string, ViteManifestEntry>\n\nexport const INERTIA_PROP_OPTIONAL = Symbol.for('stratal:inertia:prop:optional')\nexport const INERTIA_PROP_DEFERRED = Symbol.for('stratal:inertia:prop:deferred')\nexport const INERTIA_PROP_MERGE = Symbol.for('stratal:inertia:prop:merge')\n\nexport interface InertiaOptionalProp {\n [INERTIA_PROP_OPTIONAL]: true\n callback: () => unknown\n}\n\nexport interface InertiaDeferredProp {\n [INERTIA_PROP_DEFERRED]: true\n callback: () => unknown\n group: string\n}\n\nexport interface InertiaMergeProp {\n [INERTIA_PROP_MERGE]: true\n callback: () => unknown\n}\n","import { Transient, inject } from 'stratal/di'\nimport type { RouterContext } from 'stratal/router'\nimport type { InertiaModuleOptions } from '../inertia.options'\nimport { INERTIA_TOKENS } from '../inertia.tokens'\nimport type {\n InertiaDeferredProp,\n InertiaMergeProp,\n InertiaOptionalProp,\n InertiaPage,\n InertiaRenderOptions,\n SharedDataResolver,\n} from '../types'\nimport {\n INERTIA_PROP_DEFERRED,\n INERTIA_PROP_MERGE,\n INERTIA_PROP_OPTIONAL,\n} from '../types'\nimport type { SsrRendererService } from './ssr-renderer.service'\nimport type { TemplateService } from './template.service'\n\n@Transient()\nexport class InertiaService {\n private sharedData: Record<string, unknown> = {}\n\n constructor(\n @inject(INERTIA_TOKENS.Options) private readonly options: InertiaModuleOptions,\n @inject(INERTIA_TOKENS.TemplateService) private readonly template: TemplateService,\n @inject(INERTIA_TOKENS.SsrRenderer) private readonly ssr: SsrRendererService,\n ) { }\n\n share(key: string, value: unknown): void {\n this.sharedData[key] = value\n }\n\n location(url: string): Response {\n return new Response('', {\n status: 409,\n headers: { 'X-Inertia-Location': url },\n })\n }\n\n optional(callback: () => unknown): InertiaOptionalProp {\n return { [INERTIA_PROP_OPTIONAL]: true, callback }\n }\n\n defer(callback: () => unknown, group = 'default'): InertiaDeferredProp {\n return { [INERTIA_PROP_DEFERRED]: true, callback, group }\n }\n\n merge(callback: () => unknown): InertiaMergeProp {\n return { [INERTIA_PROP_MERGE]: true, callback }\n }\n\n async render(\n ctx: RouterContext,\n component: string,\n props: Record<string, unknown> = {},\n renderOptions: InertiaRenderOptions = {},\n ): Promise<Response> {\n const url = new URL(ctx.c.req.url).pathname\n const isInertia = ctx.c.get('inertia')\n\n // Resolve shared data from module options\n const resolvedShared = await this.resolveSharedData(ctx)\n\n // Merge shared data with route props\n const allProps = { ...resolvedShared, ...this.sharedData, ...props }\n\n // Process props: handle optional, deferred, merge\n const { resolvedProps, mergeProps, deferredProps } = await this.processProps(\n allProps,\n ctx,\n component,\n isInertia,\n )\n\n const page: InertiaPage = {\n component,\n props: resolvedProps,\n url,\n version: this.options.version ?? '',\n mergeProps,\n deferredProps,\n ...(renderOptions.encryptHistory ? { encryptHistory: true } : {}),\n ...(renderOptions.clearHistory ? { clearHistory: true } : {}),\n }\n\n if (isInertia) {\n return new Response(JSON.stringify(page), {\n status: 200,\n headers: {\n 'Content-Type': 'application/json',\n 'X-Inertia': 'true',\n 'Vary': 'X-Inertia',\n },\n })\n }\n\n // Full page render — skip SSR if disabled for this route\n const ssrDisabled = ctx.c.get('withoutSsr') || this.isSsrDisabled(url)\n const ssrResult = ssrDisabled\n ? { head: [] as string[], body: '' }\n : await this.ssr.render(page)\n const html = this.template.render(page, ssrResult.head, ssrResult.body)\n\n return new Response(html, {\n status: 200,\n headers: {\n 'Content-Type': 'text/html; charset=utf-8',\n },\n })\n }\n\n private async resolveSharedData(ctx: RouterContext): Promise<Record<string, unknown>> {\n const shared: Record<string, unknown> = {}\n const configShared = this.options.sharedData\n\n if (!configShared) return shared\n\n for (const [key, value] of Object.entries(configShared)) {\n if (typeof value === 'function') {\n shared[key] = await (value as SharedDataResolver)(ctx)\n } else {\n shared[key] = value\n }\n }\n\n return shared\n }\n\n private async processProps(\n allProps: Record<string, unknown>,\n ctx: RouterContext,\n component: string,\n isInertia: boolean,\n ): Promise<{\n resolvedProps: Record<string, unknown>\n mergeProps: string[]\n deferredProps: Record<string, string[]>\n }> {\n const resolvedProps: Record<string, unknown> = {}\n const mergeProps: string[] = []\n const deferredProps: Record<string, string[]> = {}\n\n const partialComponent = ctx.header('x-inertia-partial-component')\n const partialDataHeader = ctx.header('x-inertia-partial-data')\n const isPartialReload = isInertia && partialComponent === component && partialDataHeader\n\n const requestedProps = partialDataHeader?.split(',').map((s) => s.trim()) ?? []\n\n for (const [key, value] of Object.entries(allProps)) {\n // Handle deferred props\n if (this.isDeferredProp(value)) {\n if (isPartialReload && this.isRequested(key, requestedProps)) {\n resolvedProps[key] = await value.callback()\n } else if (!isPartialReload) {\n deferredProps[value.group] ??= []\n deferredProps[value.group].push(key)\n }\n continue\n }\n\n // Handle merge props\n if (this.isMergeProp(value)) {\n if (isPartialReload && !this.isRequested(key, requestedProps)) {\n continue\n }\n mergeProps.push(key)\n resolvedProps[key] = await value.callback()\n continue\n }\n\n // Handle optional props\n if (this.isOptionalProp(value)) {\n // Only include on partial reloads when explicitly requested\n if (isPartialReload && this.isRequested(key, requestedProps)) {\n resolvedProps[key] = await value.callback()\n }\n continue\n }\n\n // Regular props\n if (isPartialReload) {\n // On partial reload, only include requested props\n if (this.isRequested(key, requestedProps)) {\n resolvedProps[key] = value\n }\n } else {\n resolvedProps[key] = value\n }\n }\n\n return { resolvedProps, mergeProps, deferredProps }\n }\n\n /**\n * Check if a prop key is requested — supports dot-notation (e.g., `user.permissions`\n * matches the top-level `user` key).\n */\n private isRequested(key: string, requestedProps: string[]): boolean {\n return requestedProps.some((prop) => prop === key || prop.startsWith(`${key}.`))\n }\n\n private isOptionalProp(value: unknown): value is InertiaOptionalProp {\n return typeof value === 'object' && value !== null && INERTIA_PROP_OPTIONAL in value\n }\n\n private isDeferredProp(value: unknown): value is InertiaDeferredProp {\n return typeof value === 'object' && value !== null && INERTIA_PROP_DEFERRED in value\n }\n\n private isMergeProp(value: unknown): value is InertiaMergeProp {\n return typeof value === 'object' && value !== null && INERTIA_PROP_MERGE in value\n }\n\n private isSsrDisabled(pathname: string): boolean {\n const patterns = this.options.ssr?.disabled\n if (!patterns || patterns.length === 0) return false\n\n return patterns.some((pattern) => {\n const escaped = pattern.replace(/[.+?^${}()|[\\]\\\\]/g, '\\\\$&')\n const regex = new RegExp(`^/${escaped.replace(/\\*/g, '[^/]*')}$`)\n return regex.test(pathname)\n })\n }\n}\n","import { Transient, inject } from 'stratal/di'\nimport type { InertiaModuleOptions } from '../inertia.options'\nimport { INERTIA_TOKENS } from '../inertia.tokens'\nimport type { ViteManifest } from '../types'\n\nconst DEFAULT_ENTRY_CLIENT_PATH = 'src/inertia/app.tsx'\n\n@Transient()\nexport class ManifestService {\n private readonly manifest: ViteManifest | null\n private readonly entryClientPath: string\n\n constructor(\n @inject(INERTIA_TOKENS.Options) options: InertiaModuleOptions,\n ) {\n this.manifest = options.manifest ?? null\n this.entryClientPath = (options.entryClientPath ?? DEFAULT_ENTRY_CLIENT_PATH).replace(/^\\/+/, '')\n }\n\n private get isDev(): boolean {\n return this.manifest === null\n }\n\n getHeadTags(): string {\n if (this.isDev) {\n return '<link rel=\"stylesheet\" href=\"/__inertia/ssr-css\" data-ssr-css />'\n }\n\n const tags: string[] = []\n const seen = new Set<string>()\n for (const entry of Object.values(this.manifest!)) {\n if (entry.css) {\n for (const cssFile of entry.css) {\n if (seen.has(cssFile)) continue\n seen.add(cssFile)\n tags.push(`<link rel=\"stylesheet\" href=\"/${cssFile}\" />`)\n }\n }\n }\n\n return tags.join('\\n')\n }\n\n getScriptTags(): string {\n if (this.isDev) {\n return [\n '<script type=\"module\" src=\"/@vite/client\"></script>',\n `<script type=\"module\">\nimport { createHotContext } from \"/@vite/client\";\nconst hot = createHotContext(\"/__ssr_css\");\nhot.on(\"vite:afterUpdate\", () => {\n document.querySelectorAll(\"[data-ssr-css]\").forEach(el => el.remove());\n});\n</script>`,\n `<script type=\"module\" src=\"/${this.entryClientPath}\"></script>`,\n ].join('\\n')\n }\n\n const tags: string[] = []\n for (const entry of Object.values(this.manifest!)) {\n if (entry.isEntry) {\n tags.push(`<script type=\"module\" src=\"/${entry.file}\"></script>`)\n }\n }\n\n return tags.join('\\n')\n }\n}\n","import { Transient, inject } from 'stratal/di'\nimport type { InertiaModuleOptions } from '../inertia.options'\nimport { INERTIA_TOKENS } from '../inertia.tokens'\nimport type { InertiaPage, InertiaSsrResult } from '../types'\n\ninterface LoadedSsrBundle {\n render(page: InertiaPage): Promise<InertiaSsrResult>\n}\n\n@Transient()\nexport class SsrRendererService {\n private bundle: LoadedSsrBundle | null = null\n private loadPromise: Promise<void> | null = null\n\n constructor(\n @inject(INERTIA_TOKENS.Options) private readonly options: InertiaModuleOptions,\n ) { }\n\n async render(page: InertiaPage): Promise<InertiaSsrResult> {\n if (!this.options.ssr) {\n return { head: [], body: '' }\n }\n\n await this.ensureBundle()\n\n if (!this.bundle) {\n return { head: [], body: '' }\n }\n\n return this.bundle.render(page)\n }\n\n private async ensureBundle(): Promise<void> {\n if (this.bundle) return\n\n this.loadPromise ??= this.loadBundle()\n\n try {\n await this.loadPromise\n } catch {\n // loadBundle already clears loadPromise on failure\n }\n }\n\n private async loadBundle(): Promise<void> {\n if (!this.options.ssr) return\n\n try {\n const mod = await this.options.ssr.bundle()\n const resolved = ('default' in mod ? mod.default : mod) as LoadedSsrBundle\n this.bundle = resolved\n } catch {\n this.loadPromise = null\n }\n }\n}\n","import { Transient, inject } from 'stratal/di'\nimport type { InertiaModuleOptions } from '../inertia.options'\nimport { INERTIA_TOKENS } from '../inertia.tokens'\nimport type { InertiaPage } from '../types'\nimport type { ManifestService } from './manifest.service'\n\n@Transient()\nexport class TemplateService {\n constructor(\n @inject(INERTIA_TOKENS.Options) private readonly options: InertiaModuleOptions,\n @inject(INERTIA_TOKENS.ManifestService) private readonly manifest: ManifestService,\n ) { }\n\n render(page: InertiaPage, ssrHead: string[], ssrBody: string): string {\n // When SSR body is present, Inertia's buildSSRBody already returns the\n // <script data-page=\"app\"> tag + <div id=\"app\" data-server-rendered=\"true\">.\n // Without SSR, we generate both elements ourselves for client-side hydration.\n const appHtml = ssrBody || this.buildClientOnlyBody(page)\n\n const headTags = ssrHead.length > 0 ? ssrHead.join('\\n') : ''\n const viteHead = this.manifest.getHeadTags()\n const viteScripts = this.manifest.getScriptTags()\n\n let html = this.options.rootView\n html = html.replace('@inertiaHead', headTags)\n html = html.replace('@inertia', appHtml)\n html = html.replace('@viteHead', viteHead)\n html = html.replace('@viteScripts', viteScripts)\n\n return html\n }\n\n private buildClientOnlyBody(page: InertiaPage): string {\n const json = JSON.stringify(page).replace(/\\//g, '\\\\/')\n return `<script data-page=\"app\" type=\"application/json\">${json}</script><div id=\"app\"></div>`\n }\n}\n","import type { MiddlewareConfigurable, MiddlewareConsumer } from 'stratal/middleware'\nimport type { AsyncModuleOptions, DynamicModule, OnInitialize } from 'stratal/module'\nimport { Module } from 'stratal/module'\nimport { augmentRouterContext } from './augment/router-context'\nimport { InertiaBuildCommand } from './commands/inertia-build.command'\nimport { InertiaDevCommand } from './commands/inertia-dev.command'\nimport { InertiaInstallCommand } from './commands/inertia-install.command'\nimport { InertiaTypesCommand } from './commands/inertia-types.command'\nimport type { InertiaModuleOptions } from './inertia.options'\nimport { INERTIA_TOKENS } from './inertia.tokens'\nimport { InertiaMiddleware } from './middleware/inertia.middleware'\nimport { InertiaService } from './services/inertia.service'\nimport { ManifestService } from './services/manifest.service'\nimport { SsrRendererService } from './services/ssr-renderer.service'\nimport { TemplateService } from './services/template.service'\n\n@Module({\n providers: [\n { provide: INERTIA_TOKENS.InertiaService, useClass: InertiaService },\n { provide: INERTIA_TOKENS.TemplateService, useClass: TemplateService },\n { provide: INERTIA_TOKENS.ManifestService, useClass: ManifestService },\n { provide: INERTIA_TOKENS.SsrRenderer, useClass: SsrRendererService },\n InertiaInstallCommand,\n InertiaTypesCommand,\n InertiaDevCommand,\n InertiaBuildCommand,\n ],\n})\nexport class InertiaModule implements MiddlewareConfigurable, OnInitialize {\n static forRoot(options: InertiaModuleOptions): DynamicModule {\n return {\n module: InertiaModule,\n providers: [\n { provide: INERTIA_TOKENS.Options, useValue: options },\n ],\n }\n }\n\n static forRootAsync(options: AsyncModuleOptions<InertiaModuleOptions>): DynamicModule {\n return {\n module: InertiaModule,\n providers: [\n {\n provide: INERTIA_TOKENS.Options,\n useFactory: options.useFactory,\n inject: options.inject,\n },\n ],\n }\n }\n\n configure(consumer: MiddlewareConsumer): void {\n consumer.apply(InertiaMiddleware).forRoutes('*')\n }\n\n onInitialize(): void {\n augmentRouterContext((ctx) => {\n const requestContainer = ctx.getContainer()\n return requestContainer.resolve<InertiaService>(INERTIA_TOKENS.InertiaService)\n })\n }\n}\n","import type { RouteConfig } from 'stratal/router'\nimport { Route } from 'stratal/router'\nimport { z } from 'stratal/validation'\n\n/**\n * Zod schema for the Inertia page JSON response (returned for X-Inertia XHR requests)\n */\nexport const inertiaPageSchema = z.object({\n component: z.string(),\n props: z.record(z.string(), z.unknown()),\n url: z.string(),\n version: z.string(),\n mergeProps: z.array(z.string()),\n deferredProps: z.record(z.string(), z.array(z.string())),\n encryptHistory: z.boolean(),\n clearHistory: z.boolean(),\n})\n\nexport type InertiaRouteConfig = Omit<RouteConfig, 'response' | 'statusCode' | 'hideFromDocs'> & {\n hideFromDocs?: boolean\n}\n\n/**\n * Decorator for Inertia page routes.\n *\n * Wraps `@Route()` with:\n * - Auto-applied Inertia page response schema\n * - `hideFromDocs: true` by default (overridable)\n *\n * Accepts `query`, `params`, `body`, `tags`, `summary`, `description`, `security`.\n *\n * @example\n * ```typescript\n * @Controller('/notes')\n * export class NotesController implements IController {\n * @InertiaRoute({ query: z.object({ page: z.string().optional() }) })\n * async index(ctx: RouterContext) {\n * return ctx.inertia('notes/Index', { notes: [] })\n * }\n * }\n * ```\n */\nexport function InertiaRoute(config: InertiaRouteConfig = {}) {\n const { hideFromDocs = true, ...rest } = config\n\n return Route({\n ...rest,\n response: {\n schema: inertiaPageSchema,\n description: 'Inertia page response',\n contentType: 'text/html',\n },\n hideFromDocs,\n })\n}\n"],"mappings":"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"}
@@ -1,70 +0,0 @@
1
- import { t as __exportAll } from "./rolldown-runtime-wcPFST8Q.mjs";
2
- //#region src/vite/inertia-dev-css-plugin.ts
3
- var inertia_dev_css_plugin_exports = /* @__PURE__ */ __exportAll({ stratalInertiaDevCss: () => stratalInertiaDevCss });
4
- const CSS_LANGS_RE = /\.(css|scss|sass|less|styl|stylus|pcss|postcss)(?:$|\?)/;
5
- const VIRTUAL_MODULE_ID = "virtual:inertia-ssr.css";
6
- const RESOLVED_VIRTUAL_MODULE_ID = "\0" + VIRTUAL_MODULE_ID;
7
- function collectStyleUrls(server, entries) {
8
- const urls = [];
9
- const visited = /* @__PURE__ */ new Set();
10
- function traverse(mod) {
11
- if (visited.has(mod.url)) return;
12
- visited.add(mod.url);
13
- if (CSS_LANGS_RE.test(mod.url)) urls.push(mod.url);
14
- for (const imported of mod.importedModules) traverse(imported);
15
- }
16
- for (const entry of entries) {
17
- const mod = server.moduleGraph.getModulesByFile(entry.startsWith("/") ? entry.slice(1) : entry);
18
- if (mod) for (const m of mod) traverse(m);
19
- const urlMod = server.moduleGraph.urlToModuleMap.get(entry);
20
- if (urlMod) traverse(urlMod);
21
- }
22
- return urls;
23
- }
24
- async function collectStyle(server, entries) {
25
- for (const entry of entries) try {
26
- await server.transformRequest(entry);
27
- } catch {}
28
- const urls = collectStyleUrls(server, entries);
29
- const styles = [];
30
- for (const url of urls) try {
31
- const separator = url.includes("?") ? "&" : "?";
32
- const result = await server.transformRequest(url + separator + "direct");
33
- if (result?.code) styles.push(result.code);
34
- } catch {}
35
- return styles.join("\n");
36
- }
37
- function stratalInertiaDevCss(options) {
38
- let server;
39
- return {
40
- name: "stratal:inertia-dev-css",
41
- apply: "serve",
42
- resolveId(id) {
43
- if (id === VIRTUAL_MODULE_ID) return RESOLVED_VIRTUAL_MODULE_ID;
44
- },
45
- async load(id) {
46
- if (id === RESOLVED_VIRTUAL_MODULE_ID) return await collectStyle(server, options.entries);
47
- },
48
- configureServer(devServer) {
49
- server = devServer;
50
- server.middlewares.use((req, res, next) => {
51
- if (new URL(req.url ?? "", "http://localhost").pathname !== "/__inertia/ssr-css") {
52
- next();
53
- return;
54
- }
55
- collectStyle(server, options.entries).then((css) => {
56
- res.setHeader("Content-Type", "text/css");
57
- res.setHeader("Cache-Control", "no-store");
58
- res.end(css);
59
- }).catch(() => {
60
- res.statusCode = 500;
61
- res.end("");
62
- });
63
- });
64
- }
65
- };
66
- }
67
- //#endregion
68
- export { stratalInertiaDevCss as n, inertia_dev_css_plugin_exports as t };
69
-
70
- //# sourceMappingURL=inertia-dev-css-plugin-BYromyO_.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"inertia-dev-css-plugin-BYromyO_.mjs","names":[],"sources":["../src/vite/inertia-dev-css-plugin.ts"],"sourcesContent":["import type { ModuleNode, Plugin, ViteDevServer } from 'vite'\n\nconst CSS_LANGS_RE = /\\.(css|scss|sass|less|styl|stylus|pcss|postcss)(?:$|\\?)/\nconst VIRTUAL_MODULE_ID = 'virtual:inertia-ssr.css'\nconst RESOLVED_VIRTUAL_MODULE_ID = '\\0' + VIRTUAL_MODULE_ID\n\nexport interface InertiaDevCssOptions {\n entries: string[]\n}\n\nfunction collectStyleUrls(server: ViteDevServer, entries: string[]): string[] {\n const urls: string[] = []\n const visited = new Set<string>()\n\n function traverse(mod: ModuleNode) {\n if (visited.has(mod.url)) return\n visited.add(mod.url)\n\n if (CSS_LANGS_RE.test(mod.url)) {\n urls.push(mod.url)\n }\n\n for (const imported of mod.importedModules) {\n traverse(imported)\n }\n }\n\n for (const entry of entries) {\n const mod = server.moduleGraph.getModulesByFile(\n entry.startsWith('/') ? entry.slice(1) : entry,\n )\n\n if (mod) {\n for (const m of mod) {\n traverse(m)\n }\n }\n\n const urlMod = server.moduleGraph.urlToModuleMap.get(entry)\n if (urlMod) {\n traverse(urlMod)\n }\n }\n\n return urls\n}\n\nasync function collectStyle(server: ViteDevServer, entries: string[]): Promise<string> {\n for (const entry of entries) {\n try {\n await server.transformRequest(entry)\n }\n catch {\n //\n }\n }\n\n const urls = collectStyleUrls(server, entries)\n const styles: string[] = []\n\n for (const url of urls) {\n try {\n const separator = url.includes('?') ? '&' : '?'\n const result = await server.transformRequest(url + separator + 'direct')\n if (result?.code) {\n styles.push(result.code)\n }\n }\n catch {\n //\n }\n }\n\n return styles.join('\\n')\n}\n\nexport function stratalInertiaDevCss(options: InertiaDevCssOptions): Plugin {\n let server: ViteDevServer\n\n return {\n name: 'stratal:inertia-dev-css',\n apply: 'serve',\n\n resolveId(id) {\n if (id === VIRTUAL_MODULE_ID) {\n return RESOLVED_VIRTUAL_MODULE_ID\n }\n },\n\n async load(id) {\n if (id === RESOLVED_VIRTUAL_MODULE_ID) {\n return await collectStyle(server, options.entries)\n }\n },\n\n configureServer(devServer) {\n server = devServer\n\n server.middlewares.use((req, res, next) => {\n const pathname = new URL(req.url ?? '', 'http://localhost').pathname\n if (pathname !== '/__inertia/ssr-css') { next(); return; }\n\n collectStyle(server, options.entries).then((css) => {\n res.setHeader('Content-Type', 'text/css')\n res.setHeader('Cache-Control', 'no-store')\n res.end(css)\n }).catch(() => {\n res.statusCode = 500\n res.end('')\n })\n })\n },\n }\n}\n"],"mappings":";;;AAEA,MAAM,eAAe;AACrB,MAAM,oBAAoB;AAC1B,MAAM,6BAA6B,OAAO;AAM1C,SAAS,iBAAiB,QAAuB,SAA6B;CAC5E,MAAM,OAAiB,EAAE;CACzB,MAAM,0BAAU,IAAI,KAAa;CAEjC,SAAS,SAAS,KAAiB;AACjC,MAAI,QAAQ,IAAI,IAAI,IAAI,CAAE;AAC1B,UAAQ,IAAI,IAAI,IAAI;AAEpB,MAAI,aAAa,KAAK,IAAI,IAAI,CAC5B,MAAK,KAAK,IAAI,IAAI;AAGpB,OAAK,MAAM,YAAY,IAAI,gBACzB,UAAS,SAAS;;AAItB,MAAK,MAAM,SAAS,SAAS;EAC3B,MAAM,MAAM,OAAO,YAAY,iBAC7B,MAAM,WAAW,IAAI,GAAG,MAAM,MAAM,EAAE,GAAG,MAC1C;AAED,MAAI,IACF,MAAK,MAAM,KAAK,IACd,UAAS,EAAE;EAIf,MAAM,SAAS,OAAO,YAAY,eAAe,IAAI,MAAM;AAC3D,MAAI,OACF,UAAS,OAAO;;AAIpB,QAAO;;AAGT,eAAe,aAAa,QAAuB,SAAoC;AACrF,MAAK,MAAM,SAAS,QAClB,KAAI;AACF,QAAM,OAAO,iBAAiB,MAAM;SAEhC;CAKR,MAAM,OAAO,iBAAiB,QAAQ,QAAQ;CAC9C,MAAM,SAAmB,EAAE;AAE3B,MAAK,MAAM,OAAO,KAChB,KAAI;EACF,MAAM,YAAY,IAAI,SAAS,IAAI,GAAG,MAAM;EAC5C,MAAM,SAAS,MAAM,OAAO,iBAAiB,MAAM,YAAY,SAAS;AACxE,MAAI,QAAQ,KACV,QAAO,KAAK,OAAO,KAAK;SAGtB;AAKR,QAAO,OAAO,KAAK,KAAK;;AAG1B,SAAgB,qBAAqB,SAAuC;CAC1E,IAAI;AAEJ,QAAO;EACL,MAAM;EACN,OAAO;EAEP,UAAU,IAAI;AACZ,OAAI,OAAO,kBACT,QAAO;;EAIX,MAAM,KAAK,IAAI;AACb,OAAI,OAAO,2BACT,QAAO,MAAM,aAAa,QAAQ,QAAQ,QAAQ;;EAItD,gBAAgB,WAAW;AACzB,YAAS;AAET,UAAO,YAAY,KAAK,KAAK,KAAK,SAAS;AAEzC,QADiB,IAAI,IAAI,IAAI,OAAO,IAAI,mBAAmB,CAAC,aAC3C,sBAAsB;AAAE,WAAM;AAAE;;AAEjD,iBAAa,QAAQ,QAAQ,QAAQ,CAAC,MAAM,QAAQ;AAClD,SAAI,UAAU,gBAAgB,WAAW;AACzC,SAAI,UAAU,iBAAiB,WAAW;AAC1C,SAAI,IAAI,IAAI;MACZ,CAAC,YAAY;AACb,SAAI,aAAa;AACjB,SAAI,IAAI,GAAG;MACX;KACF;;EAEL"}
@@ -1,39 +0,0 @@
1
- import { t as __exportAll } from "./rolldown-runtime-wcPFST8Q.mjs";
2
- import { n as runTypeGeneration, t as findPagesDir } from "./type-generator-DlXIc6e2.mjs";
3
- import { existsSync } from "node:fs";
4
- import { isAbsolute, relative } from "node:path";
5
- //#region src/vite/inertia-types-plugin.ts
6
- var inertia_types_plugin_exports = /* @__PURE__ */ __exportAll({ stratalInertiaTypes: () => stratalInertiaTypes });
7
- function stratalInertiaTypes() {
8
- let cwd;
9
- let pagesDir;
10
- return {
11
- name: "stratal:inertia-types",
12
- configResolved(config) {
13
- cwd = config.root;
14
- pagesDir = findPagesDir(cwd) + "/";
15
- },
16
- async buildStart() {
17
- if (!existsSync(pagesDir)) return;
18
- try {
19
- await runTypeGeneration(cwd);
20
- } catch (error) {
21
- console.warn("[stratal:inertia-types] Type generation failed during build:", error);
22
- }
23
- },
24
- async handleHotUpdate({ file }) {
25
- const rel = relative(pagesDir, file);
26
- if (rel.startsWith("..") || isAbsolute(rel)) return;
27
- if (!/\.(tsx|ts)$/.test(file)) return;
28
- try {
29
- await runTypeGeneration(cwd);
30
- } catch (error) {
31
- console.warn("[stratal:inertia-types] Type generation failed during HMR:", error);
32
- }
33
- }
34
- };
35
- }
36
- //#endregion
37
- export { stratalInertiaTypes as n, inertia_types_plugin_exports as t };
38
-
39
- //# sourceMappingURL=inertia-types-plugin-NO_uxhxQ.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"inertia-types-plugin-NO_uxhxQ.mjs","names":[],"sources":["../src/vite/inertia-types-plugin.ts"],"sourcesContent":["import { existsSync } from 'node:fs'\nimport { isAbsolute, relative } from 'node:path'\nimport type { Plugin } from 'vite'\nimport { findPagesDir, runTypeGeneration } from '../generator/type-generator'\n\nexport function stratalInertiaTypes(): Plugin {\n let cwd: string\n let pagesDir: string\n\n return {\n name: 'stratal:inertia-types',\n\n configResolved(config) {\n cwd = config.root\n pagesDir = findPagesDir(cwd) + '/'\n },\n\n async buildStart() {\n if (!existsSync(pagesDir)) return\n try {\n await runTypeGeneration(cwd)\n } catch (error) {\n console.warn('[stratal:inertia-types] Type generation failed during build:', error)\n }\n },\n\n async handleHotUpdate({ file }) {\n const rel = relative(pagesDir, file)\n if (rel.startsWith('..') || isAbsolute(rel)) return\n if (!/\\.(tsx|ts)$/.test(file)) return\n\n try {\n await runTypeGeneration(cwd)\n } catch (error) {\n console.warn('[stratal:inertia-types] Type generation failed during HMR:', error)\n }\n },\n }\n}\n"],"mappings":";;;;;;AAKA,SAAgB,sBAA8B;CAC5C,IAAI;CACJ,IAAI;AAEJ,QAAO;EACL,MAAM;EAEN,eAAe,QAAQ;AACrB,SAAM,OAAO;AACb,cAAW,aAAa,IAAI,GAAG;;EAGjC,MAAM,aAAa;AACjB,OAAI,CAAC,WAAW,SAAS,CAAE;AAC3B,OAAI;AACF,UAAM,kBAAkB,IAAI;YACrB,OAAO;AACd,YAAQ,KAAK,gEAAgE,MAAM;;;EAIvF,MAAM,gBAAgB,EAAE,QAAQ;GAC9B,MAAM,MAAM,SAAS,UAAU,KAAK;AACpC,OAAI,IAAI,WAAW,KAAK,IAAI,WAAW,IAAI,CAAE;AAC7C,OAAI,CAAC,cAAc,KAAK,KAAK,CAAE;AAE/B,OAAI;AACF,UAAM,kBAAkB,IAAI;YACrB,OAAO;AACd,YAAQ,KAAK,8DAA8D,MAAM;;;EAGtF"}
@@ -1,13 +0,0 @@
1
- //#region \0rolldown/runtime.js
2
- var __defProp = Object.defineProperty;
3
- var __exportAll = (all, no_symbols) => {
4
- let target = {};
5
- for (var name in all) __defProp(target, name, {
6
- get: all[name],
7
- enumerable: true
8
- });
9
- if (!no_symbols) __defProp(target, Symbol.toStringTag, { value: "Module" });
10
- return target;
11
- };
12
- //#endregion
13
- export { __exportAll as t };
@@ -1,193 +0,0 @@
1
- import { existsSync, mkdirSync, writeFileSync } from "node:fs";
2
- import { dirname, join, relative } from "node:path";
3
- //#region src/generator/type-generator.ts
4
- async function loadTsMorph() {
5
- return import("ts-morph");
6
- }
7
- async function extractPageTypes(pagesDir, tsConfigPath) {
8
- if (!existsSync(pagesDir)) return [];
9
- const { Project, SyntaxKind, ts } = await loadTsMorph();
10
- const project = new Project({
11
- tsConfigFilePath: tsConfigPath,
12
- skipAddingFilesFromTsConfig: true,
13
- compilerOptions: tsConfigPath ? void 0 : {
14
- jsx: ts.JsxEmit.ReactJSX,
15
- esModuleInterop: true,
16
- moduleResolution: ts.ModuleResolutionKind.Bundler,
17
- module: ts.ModuleKind.ESNext,
18
- target: ts.ScriptTarget.ESNext
19
- }
20
- });
21
- project.addSourceFilesAtPaths(join(pagesDir, "**/*.{tsx,ts}"));
22
- const pages = [];
23
- for (const sourceFile of project.getSourceFiles()) {
24
- const relPath = relative(pagesDir, sourceFile.getFilePath());
25
- if (relPath.includes("__tests__") || relPath.includes(".spec.") || relPath.includes(".test.")) continue;
26
- const fileName = relPath.split("/").pop();
27
- if (fileName.startsWith("_") || /^Layout\.(tsx|ts)$/.test(fileName)) continue;
28
- const componentName = relPath.replace(/\.(tsx|ts)$/, "").replace(/\\/g, "/");
29
- const propsType = extractDefaultExportPropsType(sourceFile, SyntaxKind, ts);
30
- if (propsType !== null) pages.push({
31
- componentName,
32
- propsType
33
- });
34
- }
35
- return pages.sort((a, b) => a.componentName.localeCompare(b.componentName));
36
- }
37
- function extractDefaultExportPropsType(sourceFile, SK, tsObj) {
38
- const defaultExportSymbol = sourceFile.getDefaultExportSymbol();
39
- if (!defaultExportSymbol) return null;
40
- const declarations = defaultExportSymbol.getDeclarations();
41
- for (const decl of declarations) {
42
- if (decl.isKind(SK.FunctionDeclaration)) return extractPropsFromFunction(decl, tsObj);
43
- if (decl.isKind(SK.ExportAssignment)) {
44
- const expr = decl.getExpression();
45
- if (!expr) continue;
46
- if (expr.isKind(SK.FunctionExpression)) return extractPropsFromParams(expr.getParameters(), tsObj);
47
- if (expr.isKind(SK.Identifier)) return resolveIdentifierPropsType(expr, SK, tsObj);
48
- if (expr.isKind(SK.ArrowFunction)) return extractPropsFromParams(expr.getParameters(), tsObj);
49
- }
50
- }
51
- return null;
52
- }
53
- function extractPropsFromFunction(fn, tsObj) {
54
- return extractPropsFromParams(fn.getParameters(), tsObj);
55
- }
56
- function extractPropsFromParams(params, tsObj) {
57
- if (params.length === 0) return "Record<string, never>";
58
- return typeToString(params[0].getType(), tsObj);
59
- }
60
- function resolveIdentifierPropsType(identifier, SK, tsObj) {
61
- const symbol = identifier.getSymbol();
62
- if (!symbol) return null;
63
- for (const decl of symbol.getDeclarations()) {
64
- if (decl.isKind(SK.FunctionDeclaration)) return extractPropsFromFunction(decl, tsObj);
65
- if (decl.isKind(SK.VariableDeclaration)) {
66
- const init = decl.getInitializer();
67
- if (init?.isKind(SK.ArrowFunction) || init?.isKind(SK.FunctionExpression)) return extractPropsFromParams(init.getParameters(), tsObj);
68
- }
69
- }
70
- return null;
71
- }
72
- function typeToString(type, tsObj) {
73
- const text = type.getText(void 0, tsObj.TypeFormatFlags.NoTruncation | tsObj.TypeFormatFlags.UseFullyQualifiedType);
74
- if (text.includes("import(")) return expandTypeToInline(type, tsObj);
75
- return text;
76
- }
77
- function expandTypeToInline(type, tsObj, visited = /* @__PURE__ */ new Set()) {
78
- if (visited.has(type)) return "Record<string, unknown>";
79
- visited.add(type);
80
- if (type.isObject() && !type.isArray()) {
81
- const properties = type.getProperties();
82
- if (properties.length === 0) return "Record<string, never>";
83
- return `{ ${properties.map((prop) => {
84
- const decl = prop.getDeclarations()[0] ?? prop.getValueDeclaration();
85
- const isOptional = prop.isOptional();
86
- if (!decl) return `${prop.getName()}${isOptional ? "?" : ""}: unknown`;
87
- const propTypeStr = expandTypeToInline(prop.getTypeAtLocation(decl), tsObj, visited);
88
- return `${prop.getName()}${isOptional ? "?" : ""}: ${propTypeStr}`;
89
- }).join("; ")} }`;
90
- }
91
- if (type.isArray()) {
92
- const elementType = type.getArrayElementType();
93
- if (elementType) return `Array<${expandTypeToInline(elementType, tsObj, visited)}>`;
94
- }
95
- if (type.isUnion()) return type.getUnionTypes().map((t) => expandTypeToInline(t, tsObj, visited)).join(" | ");
96
- if (type.isIntersection()) return type.getIntersectionTypes().map((t) => expandTypeToInline(t, tsObj, visited)).join(" & ");
97
- const text = type.getText(void 0, tsObj.TypeFormatFlags.NoTruncation);
98
- if (text.includes("import(")) return "Record<string, unknown>";
99
- return text;
100
- }
101
- async function extractSharedDataType(moduleFilePath, tsConfigPath) {
102
- if (!existsSync(moduleFilePath)) return null;
103
- const { Project, SyntaxKind, ts } = await loadTsMorph();
104
- const callExpressions = new Project({
105
- tsConfigFilePath: tsConfigPath,
106
- skipAddingFilesFromTsConfig: true,
107
- compilerOptions: tsConfigPath ? void 0 : {
108
- moduleResolution: ts.ModuleResolutionKind.Bundler,
109
- module: ts.ModuleKind.ESNext,
110
- target: ts.ScriptTarget.ESNext
111
- }
112
- }).addSourceFileAtPath(moduleFilePath).getDescendantsOfKind(SyntaxKind.CallExpression);
113
- for (const call of callExpressions) {
114
- const expr = call.getExpression();
115
- if (!expr.isKind(SyntaxKind.PropertyAccessExpression)) continue;
116
- const propName = expr.getName();
117
- if (propName !== "forRoot" && propName !== "forRootAsync") continue;
118
- const objExpr = expr.getExpression();
119
- if (!objExpr.isKind(SyntaxKind.Identifier) || objExpr.getText() !== "InertiaModule") continue;
120
- const args = call.getArguments();
121
- if (args.length === 0) continue;
122
- const optionsArg = args[0];
123
- if (!optionsArg.isKind(SyntaxKind.ObjectLiteralExpression)) continue;
124
- const sharedDataProp = optionsArg.getProperty("sharedData");
125
- if (!sharedDataProp) continue;
126
- if (!sharedDataProp.isKind(SyntaxKind.PropertyAssignment)) continue;
127
- const initializer = sharedDataProp.getInitializer();
128
- if (!initializer?.isKind(SyntaxKind.ObjectLiteralExpression)) continue;
129
- const members = [];
130
- for (const prop of initializer.getProperties()) {
131
- if (!prop.isKind(SyntaxKind.PropertyAssignment)) continue;
132
- const name = prop.getName();
133
- const value = prop.getInitializer();
134
- if (!value) continue;
135
- let valueType;
136
- if (value.isKind(SyntaxKind.ArrowFunction) || value.isKind(SyntaxKind.FunctionExpression)) valueType = typeToString(value.getReturnType(), ts);
137
- else valueType = typeToString(value.getType(), ts);
138
- members.push(`${name}: ${valueType}`);
139
- }
140
- if (members.length > 0) return { propsType: `{ ${members.join("; ")} }` };
141
- }
142
- return null;
143
- }
144
- function generateInertiaTypes(pages, sharedData) {
145
- const lines = ["// Auto-generated by @stratal/inertia. Do not edit.", "declare module '@stratal/inertia' {"];
146
- lines.push(" interface InertiaPageRegistry {");
147
- for (const page of pages) lines.push(` '${page.componentName}': ${page.propsType}`);
148
- lines.push(" }");
149
- lines.push("}");
150
- if (sharedData) {
151
- lines.push("");
152
- lines.push("declare module '@inertiajs/core' {");
153
- lines.push(" interface InertiaConfig {");
154
- lines.push(` sharedPageProps: ${sharedData.propsType}`);
155
- lines.push(" }");
156
- lines.push("}");
157
- }
158
- lines.push("", "export {}", "");
159
- return lines.join("\n");
160
- }
161
- function writeInertiaTypes(outputPath, content) {
162
- mkdirSync(dirname(outputPath), { recursive: true });
163
- writeFileSync(outputPath, content, "utf-8");
164
- }
165
- function findAppModulePath(cwd) {
166
- return [join(cwd, "src", "app.module.ts"), join(cwd, "src", "app.module.tsx")].find(existsSync);
167
- }
168
- function findPagesDir(cwd) {
169
- return join(cwd, "src", "inertia", "pages");
170
- }
171
- function findOutputPath(cwd) {
172
- return join(cwd, "src", "inertia", "inertia.d.ts");
173
- }
174
- function findTsConfigPath(cwd) {
175
- const candidate = join(cwd, "tsconfig.json");
176
- return existsSync(candidate) ? candidate : void 0;
177
- }
178
- async function runTypeGeneration(cwd) {
179
- const pagesDir = findPagesDir(cwd);
180
- const outputPath = findOutputPath(cwd);
181
- const moduleFilePath = findAppModulePath(cwd);
182
- const tsConfigPath = findTsConfigPath(cwd);
183
- const pages = await extractPageTypes(pagesDir, tsConfigPath);
184
- writeInertiaTypes(outputPath, generateInertiaTypes(pages, moduleFilePath ? await extractSharedDataType(moduleFilePath, tsConfigPath) : null));
185
- return {
186
- outputPath,
187
- pageCount: pages.length
188
- };
189
- }
190
- //#endregion
191
- export { runTypeGeneration as n, findPagesDir as t };
192
-
193
- //# sourceMappingURL=type-generator-DlXIc6e2.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"type-generator-DlXIc6e2.mjs","names":[],"sources":["../src/generator/type-generator.ts"],"sourcesContent":["import { existsSync, mkdirSync, writeFileSync } from 'node:fs'\nimport { dirname, join, relative } from 'node:path'\n\nexport interface PageTypeInfo {\n componentName: string\n propsType: string\n}\n\nexport interface SharedDataTypeInfo {\n propsType: string\n}\n\nasync function loadTsMorph() {\n return import('ts-morph')\n}\n\ntype TsMorphModule = Awaited<ReturnType<typeof loadTsMorph>>\ntype TsObj = TsMorphModule['ts']\ntype SourceFile = InstanceType<TsMorphModule['Project']> extends { getSourceFiles(): (infer S)[] } ? S : never\ntype FunctionDeclaration = ReturnType<SourceFile['getFunctions']>[number]\ntype Node = ReturnType<SourceFile['getDescendants']>[number]\ntype Type = ReturnType<Node['getType']>\n\nexport async function extractPageTypes(pagesDir: string, tsConfigPath?: string): Promise<PageTypeInfo[]> {\n if (!existsSync(pagesDir)) return []\n\n const { Project, SyntaxKind, ts } = await loadTsMorph()\n\n const project = new Project({\n tsConfigFilePath: tsConfigPath,\n skipAddingFilesFromTsConfig: true,\n compilerOptions: tsConfigPath ? undefined : {\n jsx: ts.JsxEmit.ReactJSX,\n esModuleInterop: true,\n moduleResolution: ts.ModuleResolutionKind.Bundler,\n module: ts.ModuleKind.ESNext,\n target: ts.ScriptTarget.ESNext,\n },\n })\n\n project.addSourceFilesAtPaths(join(pagesDir, '**/*.{tsx,ts}'))\n\n const pages: PageTypeInfo[] = []\n\n for (const sourceFile of project.getSourceFiles()) {\n const filePath = sourceFile.getFilePath()\n const relPath = relative(pagesDir, filePath)\n\n if (relPath.includes('__tests__') || relPath.includes('.spec.') || relPath.includes('.test.')) continue\n\n const fileName = relPath.split('/').pop()!\n if (fileName.startsWith(\"_\") || /^Layout\\.(tsx|ts)$/.test(fileName)) continue\n\n const componentName = relPath\n .replace(/\\.(tsx|ts)$/, '')\n .replace(/\\\\/g, '/')\n\n const propsType = extractDefaultExportPropsType(sourceFile, SyntaxKind, ts)\n if (propsType !== null) {\n pages.push({ componentName, propsType })\n }\n }\n\n return pages.sort((a, b) => a.componentName.localeCompare(b.componentName))\n}\n\nfunction extractDefaultExportPropsType(sourceFile: SourceFile, SK: TsMorphModule['SyntaxKind'], tsObj: TsObj): string | null {\n const defaultExportSymbol = sourceFile.getDefaultExportSymbol()\n if (!defaultExportSymbol) return null\n\n const declarations = defaultExportSymbol.getDeclarations()\n for (const decl of declarations) {\n if (decl.isKind(SK.FunctionDeclaration)) {\n return extractPropsFromFunction(decl, tsObj)\n }\n\n if (decl.isKind(SK.ExportAssignment)) {\n const expr = decl.getExpression()\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (!expr) continue\n\n if (expr.isKind(SK.FunctionExpression)) {\n return extractPropsFromParams(expr.getParameters(), tsObj)\n }\n\n if (expr.isKind(SK.Identifier)) {\n return resolveIdentifierPropsType(expr, SK, tsObj)\n }\n\n if (expr.isKind(SK.ArrowFunction)) {\n return extractPropsFromParams(expr.getParameters(), tsObj)\n }\n }\n }\n\n return null\n}\n\nfunction extractPropsFromFunction(fn: FunctionDeclaration, tsObj: TsObj): string {\n return extractPropsFromParams(fn.getParameters(), tsObj)\n}\n\nfunction extractPropsFromParams(params: ReturnType<FunctionDeclaration['getParameters']>, tsObj: TsObj): string {\n if (params.length === 0) return 'Record<string, never>'\n\n const firstParam = params[0]\n const paramType = firstParam.getType()\n\n return typeToString(paramType, tsObj)\n}\n\nfunction resolveIdentifierPropsType(identifier: Node, SK: TsMorphModule['SyntaxKind'], tsObj: TsObj): string | null {\n const symbol = identifier.getSymbol()\n if (!symbol) return null\n\n for (const decl of symbol.getDeclarations()) {\n if (decl.isKind(SK.FunctionDeclaration)) {\n return extractPropsFromFunction(decl, tsObj)\n }\n\n if (decl.isKind(SK.VariableDeclaration)) {\n const init = decl.getInitializer()\n if (init?.isKind(SK.ArrowFunction) || init?.isKind(SK.FunctionExpression)) {\n const fn = init as { getParameters(): ReturnType<FunctionDeclaration['getParameters']> }\n return extractPropsFromParams(fn.getParameters(), tsObj)\n }\n }\n }\n\n return null\n}\n\nfunction typeToString(type: Type, tsObj: TsObj): string {\n const text = type.getText(undefined, tsObj.TypeFormatFlags.NoTruncation | tsObj.TypeFormatFlags.UseFullyQualifiedType)\n\n if (text.includes('import(')) {\n return expandTypeToInline(type, tsObj)\n }\n\n return text\n}\n\nfunction expandTypeToInline(type: Type, tsObj: TsObj, visited = new Set<Type>()): string {\n if (visited.has(type)) return 'Record<string, unknown>'\n visited.add(type)\n\n if (type.isObject() && !type.isArray()) {\n const properties = type.getProperties()\n if (properties.length === 0) return 'Record<string, never>'\n\n const members = properties.map((prop) => {\n const decl = prop.getDeclarations()[0] ?? prop.getValueDeclaration()\n const isOptional = prop.isOptional()\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- defensive: ambient/synthetic symbols may lack declarations at runtime\n if (!decl) return `${prop.getName()}${isOptional ? '?' : ''}: unknown`\n const propType = prop.getTypeAtLocation(decl)\n const propTypeStr = expandTypeToInline(propType, tsObj, visited)\n return `${prop.getName()}${isOptional ? '?' : ''}: ${propTypeStr}`\n })\n\n return `{ ${members.join('; ')} }`\n }\n\n if (type.isArray()) {\n const elementType = type.getArrayElementType()\n if (elementType) {\n return `Array<${expandTypeToInline(elementType, tsObj, visited)}>`\n }\n }\n\n if (type.isUnion()) {\n return type.getUnionTypes().map((t) => expandTypeToInline(t, tsObj, visited)).join(' | ')\n }\n\n if (type.isIntersection()) {\n return type.getIntersectionTypes().map((t) => expandTypeToInline(t, tsObj, visited)).join(' & ')\n }\n\n const text = type.getText(undefined, tsObj.TypeFormatFlags.NoTruncation)\n if (text.includes('import(')) {\n return 'Record<string, unknown>'\n }\n return text\n}\n\nexport async function extractSharedDataType(moduleFilePath: string, tsConfigPath?: string): Promise<SharedDataTypeInfo | null> {\n if (!existsSync(moduleFilePath)) return null\n\n const { Project, SyntaxKind, ts } = await loadTsMorph()\n\n const project = new Project({\n tsConfigFilePath: tsConfigPath,\n skipAddingFilesFromTsConfig: true,\n compilerOptions: tsConfigPath ? undefined : {\n moduleResolution: ts.ModuleResolutionKind.Bundler,\n module: ts.ModuleKind.ESNext,\n target: ts.ScriptTarget.ESNext,\n },\n })\n\n const sourceFile = project.addSourceFileAtPath(moduleFilePath)\n\n const callExpressions = sourceFile.getDescendantsOfKind(SyntaxKind.CallExpression)\n\n for (const call of callExpressions) {\n const expr = call.getExpression()\n if (!expr.isKind(SyntaxKind.PropertyAccessExpression)) continue\n\n const propName = expr.getName()\n if (propName !== 'forRoot' && propName !== 'forRootAsync') continue\n\n const objExpr = expr.getExpression()\n if (!objExpr.isKind(SyntaxKind.Identifier) || objExpr.getText() !== 'InertiaModule') continue\n\n const args = call.getArguments()\n if (args.length === 0) continue\n\n const optionsArg = args[0]\n if (!optionsArg.isKind(SyntaxKind.ObjectLiteralExpression)) continue\n\n const sharedDataProp = optionsArg.getProperty('sharedData')\n if (!sharedDataProp) continue\n\n if (!sharedDataProp.isKind(SyntaxKind.PropertyAssignment)) continue\n\n const initializer = sharedDataProp.getInitializer()\n if (!initializer?.isKind(SyntaxKind.ObjectLiteralExpression)) continue\n\n const members: string[] = []\n for (const prop of initializer.getProperties()) {\n if (!prop.isKind(SyntaxKind.PropertyAssignment)) continue\n\n const name = prop.getName()\n const value = prop.getInitializer()\n if (!value) continue\n\n let valueType: string\n\n if (value.isKind(SyntaxKind.ArrowFunction) || value.isKind(SyntaxKind.FunctionExpression)) {\n const returnType = value.getReturnType()\n valueType = typeToString(returnType, ts)\n } else {\n valueType = typeToString(value.getType(), ts)\n }\n\n members.push(`${name}: ${valueType}`)\n }\n\n if (members.length > 0) {\n return { propsType: `{ ${members.join('; ')} }` }\n }\n }\n\n return null\n}\n\nexport function generateInertiaTypes(pages: PageTypeInfo[], sharedData?: SharedDataTypeInfo | null): string {\n const lines: string[] = [\n '// Auto-generated by @stratal/inertia. Do not edit.',\n \"declare module '@stratal/inertia' {\",\n ]\n\n lines.push(' interface InertiaPageRegistry {')\n for (const page of pages) {\n lines.push(` '${page.componentName}': ${page.propsType}`)\n }\n lines.push(' }')\n\n lines.push('}')\n\n if (sharedData) {\n lines.push('')\n lines.push(\"declare module '@inertiajs/core' {\")\n lines.push(' interface InertiaConfig {')\n lines.push(` sharedPageProps: ${sharedData.propsType}`)\n lines.push(' }')\n lines.push('}')\n }\n\n lines.push('', 'export {}', '')\n\n return lines.join('\\n')\n}\n\nexport function writeInertiaTypes(outputPath: string, content: string): void {\n mkdirSync(dirname(outputPath), { recursive: true })\n writeFileSync(outputPath, content, 'utf-8')\n}\n\nexport function findAppModulePath(cwd: string): string | undefined {\n const candidates = [\n join(cwd, 'src', 'app.module.ts'),\n join(cwd, 'src', 'app.module.tsx'),\n ]\n\n return candidates.find(existsSync)\n}\n\nexport function findPagesDir(cwd: string): string {\n return join(cwd, 'src', 'inertia', 'pages')\n}\n\nexport function findOutputPath(cwd: string): string {\n return join(cwd, 'src', 'inertia', 'inertia.d.ts')\n}\n\nexport function findTsConfigPath(cwd: string): string | undefined {\n const candidate = join(cwd, 'tsconfig.json')\n return existsSync(candidate) ? candidate : undefined\n}\n\nexport async function runTypeGeneration(cwd: string): Promise<{ outputPath: string; pageCount: number }> {\n const pagesDir = findPagesDir(cwd)\n const outputPath = findOutputPath(cwd)\n const moduleFilePath = findAppModulePath(cwd)\n const tsConfigPath = findTsConfigPath(cwd)\n\n const pages = await extractPageTypes(pagesDir, tsConfigPath)\n const sharedData = moduleFilePath\n ? await extractSharedDataType(moduleFilePath, tsConfigPath)\n : null\n\n const content = generateInertiaTypes(pages, sharedData)\n writeInertiaTypes(outputPath, content)\n\n return { outputPath, pageCount: pages.length }\n}\n"],"mappings":"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"}
package/dist/vite.d.mts DELETED
@@ -1,14 +0,0 @@
1
- /// <reference path="../global.d.ts" />
2
- import { Plugin } from "vite";
3
-
4
- //#region src/vite/inertia-dev-css-plugin.d.ts
5
- interface InertiaDevCssOptions {
6
- entries: string[];
7
- }
8
- declare function stratalInertiaDevCss(options: InertiaDevCssOptions): Plugin;
9
- //#endregion
10
- //#region src/vite/inertia-types-plugin.d.ts
11
- declare function stratalInertiaTypes(): Plugin;
12
- //#endregion
13
- export { stratalInertiaDevCss, stratalInertiaTypes };
14
- //# sourceMappingURL=vite.d.mts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"vite.d.mts","names":[],"sources":["../src/vite/inertia-dev-css-plugin.ts","../src/vite/inertia-types-plugin.ts"],"mappings":";;;UAMiB,oBAAA;EACf,OAAA;AAAA;AAAA,iBAqEc,oBAAA,CAAqB,OAAA,EAAS,oBAAA,GAAuB,MAAA;;;iBCvErD,mBAAA,CAAA,GAAuB,MAAA"}
package/dist/vite.mjs DELETED
@@ -1,4 +0,0 @@
1
- import "./type-generator-DlXIc6e2.mjs";
2
- import { n as stratalInertiaDevCss } from "./inertia-dev-css-plugin-BYromyO_.mjs";
3
- import { n as stratalInertiaTypes } from "./inertia-types-plugin-NO_uxhxQ.mjs";
4
- export { stratalInertiaDevCss, stratalInertiaTypes };