@stratal/inertia 0.0.22 → 0.0.24
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/README.md +33 -1
- package/dist/build-seo-tags-DBsHKxX9.mjs +123 -0
- package/dist/build-seo-tags-DBsHKxX9.mjs.map +1 -0
- package/dist/{decorate-CzXVx7ZH.mjs → decorate-B7nr7eBl.mjs} +1 -1
- package/dist/generator/type-generator.worker.mjs +1 -1
- package/dist/generator/type-generator.worker.mjs.map +1 -1
- package/dist/index.d.mts +209 -78
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +274 -60
- package/dist/index.mjs.map +1 -1
- package/dist/quarry.d.mts +9 -0
- package/dist/quarry.d.mts.map +1 -1
- package/dist/quarry.mjs +56 -9
- package/dist/quarry.mjs.map +1 -1
- package/dist/react.d.mts +15 -3
- package/dist/react.d.mts.map +1 -1
- package/dist/react.mjs +21 -8
- package/dist/react.mjs.map +1 -1
- package/dist/seo-runtime.d.mts +1 -0
- package/dist/seo-runtime.mjs +56 -0
- package/dist/seo-runtime.mjs.map +1 -0
- package/dist/ssr.d.mts +65 -0
- package/dist/ssr.d.mts.map +1 -0
- package/dist/ssr.mjs +56 -0
- package/dist/ssr.mjs.map +1 -0
- package/dist/testing.d.mts +1 -1
- package/dist/testing.mjs.map +1 -1
- package/dist/{type-generator-bfo14BJI.mjs → type-generator-DFpha_Fp.mjs} +178 -28
- package/dist/type-generator-DFpha_Fp.mjs.map +1 -0
- package/dist/types-BhgXhWx6.d.mts +82 -0
- package/dist/types-BhgXhWx6.d.mts.map +1 -0
- package/dist/types-DzE1pdZs.d.mts +76 -0
- package/dist/types-DzE1pdZs.d.mts.map +1 -0
- package/dist/vite.d.mts.map +1 -1
- package/dist/vite.mjs +22 -2
- package/dist/vite.mjs.map +1 -1
- package/package.json +27 -18
- package/dist/type-generator-bfo14BJI.mjs.map +0 -1
|
@@ -189,24 +189,163 @@ function unwrapAs(node, SK) {
|
|
|
189
189
|
if (node.isKind(SK.SatisfiesExpression)) return node.getExpression();
|
|
190
190
|
return node;
|
|
191
191
|
}
|
|
192
|
-
function detectI18nConfig(project, SK,
|
|
193
|
-
const
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
const
|
|
200
|
-
if (
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
const
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
192
|
+
function detectI18nConfig(project, SK, srcDir) {
|
|
193
|
+
const none = {
|
|
194
|
+
enabled: false,
|
|
195
|
+
only: []
|
|
196
|
+
};
|
|
197
|
+
const normalizedSrcDir = srcDir.replace(/\\/g, "/");
|
|
198
|
+
for (const sourceFile of project.getSourceFiles()) {
|
|
199
|
+
const filePath = sourceFile.getFilePath();
|
|
200
|
+
if (!filePath.startsWith(normalizedSrcDir)) continue;
|
|
201
|
+
if (filePath.includes("__tests__") || filePath.includes(".spec.") || filePath.includes(".test.")) continue;
|
|
202
|
+
const callExpressions = sourceFile.getDescendantsOfKind(SK.CallExpression);
|
|
203
|
+
for (const call of callExpressions) {
|
|
204
|
+
const expr = call.getExpression();
|
|
205
|
+
if (!expr.isKind(SK.PropertyAccessExpression)) continue;
|
|
206
|
+
const propName = expr.getName();
|
|
207
|
+
if (propName !== "forRoot" && propName !== "forRootAsync") continue;
|
|
208
|
+
const objExpr = expr.getExpression();
|
|
209
|
+
if (!objExpr.isKind(SK.Identifier) || objExpr.getText() !== "InertiaModule") continue;
|
|
210
|
+
const args = call.getArguments();
|
|
211
|
+
if (args.length === 0) continue;
|
|
212
|
+
const optionsLiteral = resolveModuleOptionsLiteral(args[0], SK);
|
|
213
|
+
if (optionsLiteral?.isKind(SK.ObjectLiteralExpression)) {
|
|
214
|
+
const i18nProp = optionsLiteral.getProperty("i18n");
|
|
215
|
+
if (!i18nProp) continue;
|
|
216
|
+
return {
|
|
217
|
+
enabled: true,
|
|
218
|
+
only: extractOnlyFromLiteral(i18nProp, SK)
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
const configLiteral = resolveConfigLiteralFromAsProvider(args[0], SK);
|
|
222
|
+
if (configLiteral?.isKind(SK.ObjectLiteralExpression)) {
|
|
223
|
+
const i18nProp = configLiteral.getProperty("i18n");
|
|
224
|
+
if (i18nProp) return {
|
|
225
|
+
enabled: true,
|
|
226
|
+
only: extractOnlyFromLiteral(i18nProp, SK)
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
const optionsType = resolveOptionsType(args[0], propName);
|
|
230
|
+
if (optionsType?.getProperty("i18n")) return {
|
|
231
|
+
enabled: true,
|
|
232
|
+
only: extractOnlyFromType(optionsType, args[0])
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
return none;
|
|
237
|
+
}
|
|
238
|
+
function resolveConfigLiteralFromAsProvider(arg, SK) {
|
|
239
|
+
if (!arg.isKind(SK.CallExpression)) return null;
|
|
240
|
+
const callExpr = arg.getExpression();
|
|
241
|
+
if (!callExpr.isKind(SK.PropertyAccessExpression)) return null;
|
|
242
|
+
if (callExpr.getName() !== "asProvider") return null;
|
|
243
|
+
const configIdentifier = callExpr.getExpression();
|
|
244
|
+
if (!configIdentifier.isKind(SK.Identifier)) return null;
|
|
245
|
+
const varDecl = resolveToVariableDeclaration(configIdentifier, SK);
|
|
246
|
+
if (!varDecl) return null;
|
|
247
|
+
return extractLiteralFromRegisterAs(varDecl, SK);
|
|
248
|
+
}
|
|
249
|
+
function resolveToVariableDeclaration(identifier, SK) {
|
|
250
|
+
const symbol = identifier.getSymbol();
|
|
251
|
+
if (!symbol) return null;
|
|
252
|
+
for (const decl of symbol.getDeclarations()) {
|
|
253
|
+
if (decl.isKind(SK.VariableDeclaration)) return decl;
|
|
254
|
+
if (decl.isKind(SK.ImportSpecifier)) {
|
|
255
|
+
const sourceFile = decl.getImportDeclaration().getModuleSpecifierSourceFile();
|
|
256
|
+
if (!sourceFile) continue;
|
|
257
|
+
const exportName = decl.getName();
|
|
258
|
+
const exported = sourceFile.getExportedDeclarations().get(exportName);
|
|
259
|
+
if (!exported) continue;
|
|
260
|
+
for (const exportDecl of exported) if (exportDecl.isKind(SK.VariableDeclaration)) return exportDecl;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return null;
|
|
264
|
+
}
|
|
265
|
+
function extractLiteralFromRegisterAs(varDecl, SK) {
|
|
266
|
+
if (!varDecl.isKind(SK.VariableDeclaration)) return null;
|
|
267
|
+
const init = varDecl.getInitializer();
|
|
268
|
+
if (!init?.isKind(SK.CallExpression)) return null;
|
|
269
|
+
const factoryArgs = init.getArguments();
|
|
270
|
+
if (factoryArgs.length < 2) return null;
|
|
271
|
+
const factory = factoryArgs[1];
|
|
272
|
+
if (!factory.isKind(SK.ArrowFunction) && !factory.isKind(SK.FunctionExpression)) return null;
|
|
273
|
+
const body = factory.getBody();
|
|
274
|
+
if (body.isKind(SK.ParenthesizedExpression)) {
|
|
275
|
+
const inner = unwrapAs(body.getExpression(), SK);
|
|
276
|
+
if (inner?.isKind(SK.ObjectLiteralExpression)) return inner;
|
|
277
|
+
}
|
|
278
|
+
const unwrapped = unwrapAs(body, SK);
|
|
279
|
+
if (unwrapped?.isKind(SK.ObjectLiteralExpression)) return unwrapped;
|
|
280
|
+
if (body.isKind(SK.Block)) {
|
|
281
|
+
const returnStatements = body.getDescendantsOfKind(SK.ReturnStatement);
|
|
282
|
+
for (let i = returnStatements.length - 1; i >= 0; i--) {
|
|
283
|
+
const retExpr = returnStatements[i].getExpression();
|
|
284
|
+
if (!retExpr) continue;
|
|
285
|
+
if (retExpr.isKind(SK.ParenthesizedExpression)) {
|
|
286
|
+
const inner = unwrapAs(retExpr.getExpression(), SK);
|
|
287
|
+
if (inner?.isKind(SK.ObjectLiteralExpression)) return inner;
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
const direct = unwrapAs(retExpr, SK);
|
|
291
|
+
if (direct?.isKind(SK.ObjectLiteralExpression)) return direct;
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
return null;
|
|
295
|
+
}
|
|
296
|
+
function extractOnlyFromLiteral(i18nProp, SK) {
|
|
297
|
+
const only = [];
|
|
298
|
+
if (!i18nProp.isKind(SK.PropertyAssignment)) return only;
|
|
299
|
+
const init = i18nProp.getInitializer();
|
|
300
|
+
if (!init?.isKind(SK.ObjectLiteralExpression)) return only;
|
|
301
|
+
const onlyProp = init.getProperty("only");
|
|
302
|
+
if (!onlyProp?.isKind(SK.PropertyAssignment)) return only;
|
|
303
|
+
const onlyInit = onlyProp.getInitializer();
|
|
304
|
+
if (!onlyInit?.isKind(SK.ArrayLiteralExpression)) return only;
|
|
305
|
+
for (const el of onlyInit.getElements()) if (el.isKind(SK.StringLiteral)) only.push(el.getLiteralValue());
|
|
306
|
+
return only;
|
|
307
|
+
}
|
|
308
|
+
function resolveOptionsType(arg, methodName) {
|
|
309
|
+
const argType = arg.getType();
|
|
310
|
+
if (methodName === "forRoot") return argType;
|
|
311
|
+
const useFactorySymbol = argType.getProperty("useFactory");
|
|
312
|
+
if (!useFactorySymbol) return null;
|
|
313
|
+
const signatures = useFactorySymbol.getTypeAtLocation(arg).getCallSignatures();
|
|
314
|
+
if (signatures.length === 0) return null;
|
|
315
|
+
const returnType = signatures[0].getReturnType();
|
|
316
|
+
if (returnType.isUnion()) {
|
|
317
|
+
for (const member of returnType.getUnionTypes()) if (member.getProperty("i18n")) return member;
|
|
318
|
+
return null;
|
|
208
319
|
}
|
|
209
|
-
return
|
|
320
|
+
return returnType;
|
|
321
|
+
}
|
|
322
|
+
function extractOnlyFromType(optionsType, locationNode) {
|
|
323
|
+
const i18nSymbol = optionsType.getProperty("i18n");
|
|
324
|
+
if (!i18nSymbol) return [];
|
|
325
|
+
const onlySymbol = i18nSymbol.getTypeAtLocation(locationNode).getProperty("only");
|
|
326
|
+
if (!onlySymbol) return [];
|
|
327
|
+
const elementType = onlySymbol.getTypeAtLocation(locationNode).getNumberIndexType();
|
|
328
|
+
if (!elementType) return [];
|
|
329
|
+
const result = [];
|
|
330
|
+
if (elementType.isUnion()) {
|
|
331
|
+
for (const member of elementType.getUnionTypes()) if (member.isStringLiteral()) result.push(member.getLiteralValue());
|
|
332
|
+
} else if (elementType.isStringLiteral()) result.push(elementType.getLiteralValue());
|
|
333
|
+
return result;
|
|
334
|
+
}
|
|
335
|
+
/**
|
|
336
|
+
* Collect every string-literal value a flash-key argument can resolve to.
|
|
337
|
+
*
|
|
338
|
+
* A direct string literal yields a single key. A conditional expression
|
|
339
|
+
* (`cond ? 'a' : 'b'`, including nested ternaries) contributes the literals
|
|
340
|
+
* from each branch. Non-literal keys (variables, template strings) yield
|
|
341
|
+
* nothing — they can't be statically known.
|
|
342
|
+
*/
|
|
343
|
+
function collectFlashKeyLiterals(node, SK) {
|
|
344
|
+
const stringLiteral = node.asKind(SK.StringLiteral);
|
|
345
|
+
if (stringLiteral) return [stringLiteral.getLiteralValue()];
|
|
346
|
+
const conditional = node.asKind(SK.ConditionalExpression);
|
|
347
|
+
if (conditional) return [...collectFlashKeyLiterals(conditional.getWhenTrue(), SK), ...collectFlashKeyLiterals(conditional.getWhenFalse(), SK)];
|
|
348
|
+
return [];
|
|
210
349
|
}
|
|
211
350
|
function extractFlashTypes(project, SK, tsObj, srcDir) {
|
|
212
351
|
const flashMembers = /* @__PURE__ */ new Map();
|
|
@@ -221,12 +360,13 @@ function extractFlashTypes(project, SK, tsObj, srcDir) {
|
|
|
221
360
|
if (expr.getName() !== "flash") continue;
|
|
222
361
|
const args = call.getArguments();
|
|
223
362
|
if (args.length < 2) continue;
|
|
224
|
-
const
|
|
225
|
-
if (
|
|
226
|
-
const key = keyArg.getLiteralValue();
|
|
227
|
-
if (flashMembers.has(key)) continue;
|
|
363
|
+
const keys = collectFlashKeyLiterals(args[0], SK);
|
|
364
|
+
if (keys.length === 0) continue;
|
|
228
365
|
const valueType = widenLiteralType(args[1].getType(), tsObj);
|
|
229
|
-
|
|
366
|
+
for (const key of keys) {
|
|
367
|
+
if (flashMembers.has(key)) continue;
|
|
368
|
+
flashMembers.set(key, valueType);
|
|
369
|
+
}
|
|
230
370
|
}
|
|
231
371
|
}
|
|
232
372
|
if (flashMembers.size === 0) return null;
|
|
@@ -295,7 +435,7 @@ function resolvePagePropsTypeNames(pages) {
|
|
|
295
435
|
return result;
|
|
296
436
|
}
|
|
297
437
|
function generateInertiaTypes(input) {
|
|
298
|
-
const { pages, sharedData, shareCallTypes,
|
|
438
|
+
const { pages, sharedData, shareCallTypes, i18n, flashTypes } = input;
|
|
299
439
|
const typeNames = resolvePagePropsTypeNames(pages);
|
|
300
440
|
const lines = ["// Auto-generated by @stratal/inertia. Do not edit."];
|
|
301
441
|
if (pages.length > 0) {
|
|
@@ -314,6 +454,12 @@ function generateInertiaTypes(input) {
|
|
|
314
454
|
lines.push(` '${page.componentName}': ${typeName}`);
|
|
315
455
|
}
|
|
316
456
|
lines.push(" }");
|
|
457
|
+
if (i18n.enabled && i18n.only.length > 0) {
|
|
458
|
+
const prefixUnion = i18n.only.map((p) => `'${p}'`).join(" | ");
|
|
459
|
+
lines.push(" interface InertiaI18nConfig {");
|
|
460
|
+
lines.push(` translationKeys: import('stratal/i18n').FilterByPrefix<import('stratal/i18n').MessageKeys, ${prefixUnion}>`);
|
|
461
|
+
lines.push(" }");
|
|
462
|
+
}
|
|
317
463
|
lines.push("}");
|
|
318
464
|
const configMembers = [];
|
|
319
465
|
if (flashTypes && flashTypes.members.length > 0) {
|
|
@@ -322,7 +468,7 @@ function generateInertiaTypes(input) {
|
|
|
322
468
|
}
|
|
323
469
|
const sharedMembers = [];
|
|
324
470
|
if (sharedData) for (const member of sharedData.members) sharedMembers.push(` ${member.name}${member.optional ? "?" : ""}: ${member.type}`);
|
|
325
|
-
if (
|
|
471
|
+
if (i18n.enabled) {
|
|
326
472
|
sharedMembers.push(" locale: string");
|
|
327
473
|
sharedMembers.push(" translations: Record<string, string>");
|
|
328
474
|
}
|
|
@@ -349,6 +495,7 @@ function widenLiteralType(type, tsObj, fallbackLocation) {
|
|
|
349
495
|
return typeToString(type, tsObj, fallbackLocation);
|
|
350
496
|
}
|
|
351
497
|
function typeToString(type, tsObj, fallbackLocation) {
|
|
498
|
+
if (type.isUnion() && type.getAliasSymbol?.()?.getName() === "MessageKeys") return "import('@stratal/inertia').InertiaTranslationKeys";
|
|
352
499
|
if (type.isObject() || type.isUnion() || type.isIntersection()) return expandTypeToInline(type, tsObj, fallbackLocation);
|
|
353
500
|
const text = type.getText(void 0, tsObj.TypeFormatFlags.NoTruncation | tsObj.TypeFormatFlags.UseFullyQualifiedType);
|
|
354
501
|
if (text.includes("import(")) return expandTypeToInline(type, tsObj, fallbackLocation);
|
|
@@ -393,7 +540,10 @@ function expandTypeToInline(type, tsObj, fallbackLocation, visiting = /* @__PURE
|
|
|
393
540
|
return type.isReadonlyArray() ? `ReadonlyArray<${inner}>` : `Array<${inner}>`;
|
|
394
541
|
}
|
|
395
542
|
}
|
|
396
|
-
if (type.isUnion())
|
|
543
|
+
if (type.isUnion()) {
|
|
544
|
+
if (type.getAliasSymbol?.()?.getName() === "MessageKeys") return "import('@stratal/inertia').InertiaTranslationKeys";
|
|
545
|
+
return type.getUnionTypes().map((t) => expandTypeToInline(t, tsObj, fallbackLocation, visiting)).join(" | ");
|
|
546
|
+
}
|
|
397
547
|
if (type.isIntersection()) return type.getIntersectionTypes().map((t) => expandTypeToInline(t, tsObj, fallbackLocation, visiting)).join(" & ");
|
|
398
548
|
const text = type.getText(void 0, tsObj.TypeFormatFlags.NoTruncation);
|
|
399
549
|
if (text.includes("import(")) return "unknown";
|
|
@@ -433,12 +583,12 @@ async function runTypeGeneration(cwd) {
|
|
|
433
583
|
const { project, SyntaxKind, ts } = await createProject(findTsConfigPath(cwd));
|
|
434
584
|
const pages = extractControllerPageTypes(project, SyntaxKind, ts, srcDir, pagesDir);
|
|
435
585
|
const sharedData = moduleFilePath ? extractSharedDataType(project, SyntaxKind, ts, moduleFilePath) : null;
|
|
436
|
-
const
|
|
586
|
+
const i18n = detectI18nConfig(project, SyntaxKind, srcDir);
|
|
437
587
|
writeInertiaTypes(outputPath, generateInertiaTypes({
|
|
438
588
|
pages,
|
|
439
589
|
sharedData,
|
|
440
590
|
shareCallTypes: extractShareCallTypes(project, SyntaxKind, ts, srcDir),
|
|
441
|
-
|
|
591
|
+
i18n,
|
|
442
592
|
flashTypes: extractFlashTypes(project, SyntaxKind, ts, srcDir)
|
|
443
593
|
}));
|
|
444
594
|
return {
|
|
@@ -449,4 +599,4 @@ async function runTypeGeneration(cwd) {
|
|
|
449
599
|
//#endregion
|
|
450
600
|
export { runTypeGeneration as n, findPagesDir as t };
|
|
451
601
|
|
|
452
|
-
//# sourceMappingURL=type-generator-
|
|
602
|
+
//# sourceMappingURL=type-generator-DFpha_Fp.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type-generator-DFpha_Fp.mjs","names":[],"sources":["../src/generator/type-generator.ts"],"sourcesContent":["import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs'\nimport { dirname, join } from 'node:path'\n\nexport interface PageTypeInfo {\n componentName: string\n propsType: string\n}\n\nexport interface SharedDataTypeInfo {\n members: SharedDataMember[]\n}\n\nexport interface SharedDataMember {\n name: string\n type: string\n optional: boolean\n}\n\nexport interface FlashTypeInfo {\n members: { name: string; type: string }[]\n}\n\nasync function loadTsMorph() {\n return import('ts-morph')\n}\n\ntype TsMorphModule = Awaited<ReturnType<typeof loadTsMorph>>\ntype TsObj = TsMorphModule['ts']\ntype Project = InstanceType<TsMorphModule['Project']>\ntype SourceFile = InstanceType<TsMorphModule['Project']> extends { getSourceFiles(): (infer S)[] } ? S : never\ntype Node = ReturnType<SourceFile['getDescendants']>[number]\ntype Type = ReturnType<Node['getType']>\n\n// --- Shared ts-morph project creation ---\n\nasync function createProject(tsConfigPath?: string): Promise<{ project: Project; SyntaxKind: TsMorphModule['SyntaxKind']; ts: TsObj }> {\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 return { project, SyntaxKind, ts }\n}\n\n// --- Controller ctx.inertia() extraction ---\n\nconst WRAPPER_TYPE_NAMES = [\n 'InertiaDeferredProp',\n 'InertiaMergeProp',\n 'InertiaOptionalProp',\n 'InertiaOnceProp',\n 'InertiaAlwaysProp',\n]\n\nexport function extractControllerPageTypes(\n project: Project,\n SK: TsMorphModule['SyntaxKind'],\n tsObj: TsObj,\n srcDir: string,\n pagesDir: string,\n): PageTypeInfo[] {\n project.addSourceFilesAtPaths(join(srcDir, '**/*.ts'))\n\n // Map from component name to all collected prop type strings (one per call site)\n const pages = new Map<string, string[]>()\n\n for (const sourceFile of project.getSourceFiles()) {\n const filePath = sourceFile.getFilePath()\n if (filePath.includes(pagesDir.replace(/\\\\/g, '/'))) continue\n // Skip test files\n if (filePath.includes('__tests__') || filePath.includes('.spec.') || filePath.includes('.test.')) continue\n\n const callExpressions = sourceFile.getDescendantsOfKind(SK.CallExpression)\n\n for (const call of callExpressions) {\n const expr = call.getExpression()\n if (!expr.isKind(SK.PropertyAccessExpression)) continue\n if (expr.getName() !== 'inertia') continue\n\n const args = call.getArguments()\n if (args.length === 0) continue\n\n // First arg must be a string literal (component name)\n const firstArg = args[0]\n if (!firstArg.isKind(SK.StringLiteral)) continue\n const componentName = firstArg.getLiteralValue()\n\n if (!pages.has(componentName)) {\n pages.set(componentName, [])\n }\n\n // Second arg is the props object\n if (args.length < 2) {\n pages.get(componentName)!.push('Record<string, never>')\n continue\n }\n\n const propsArg = args[1]\n const propsType = propsArg.getType()\n\n // Unwrap prop wrappers from each property\n if (propsType.isObject() && !propsType.isArray()) {\n const properties = propsType.getProperties()\n if (properties.length === 0) {\n pages.get(componentName)!.push('Record<string, never>')\n continue\n }\n\n const members = properties.map((prop) => {\n const decl = prop.getDeclarations()[0] ?? prop.getValueDeclaration()\n const location = decl ?? propsArg\n const isOptional = prop.isOptional()\n const propType = prop.getTypeAtLocation(location)\n const unwrapped = unwrapWrapperType(propType, tsObj, propsArg)\n return `${prop.getName()}${isOptional ? '?' : ''}: ${unwrapped}`\n })\n\n pages.get(componentName)!.push(`{ ${members.join('; ')} }`)\n } else {\n pages.get(componentName)!.push(typeToString(propsType, tsObj, propsArg))\n }\n }\n }\n\n return Array.from(pages.entries())\n .map(([componentName, typeVariants]) => {\n // Deduplicate identical variants then join with union\n const unique = [...new Set(typeVariants)]\n const propsType = unique.length === 1 ? unique[0] : unique.join(' | ')\n return { componentName, propsType }\n })\n .sort((a, b) => a.componentName.localeCompare(b.componentName))\n}\n\nfunction unwrapWrapperType(type: Type, tsObj: TsObj, fallbackLocation?: Node): string {\n if (type.isUnion()) {\n const unionTypes = type.getUnionTypes()\n const unwrapped = unionTypes\n .filter((t) => {\n const text = t.getText(undefined, tsObj.TypeFormatFlags.NoTruncation)\n return !WRAPPER_TYPE_NAMES.some((name) => text.includes(name))\n })\n .map((t) => typeToString(t, tsObj, fallbackLocation))\n\n if (unwrapped.length > 0) {\n return unwrapped.join(' | ')\n }\n }\n\n // Check if the type itself is a wrapper type — extract callback return type\n const text = type.getText(undefined, tsObj.TypeFormatFlags.NoTruncation)\n for (const wrapperName of WRAPPER_TYPE_NAMES) {\n if (text.includes(wrapperName)) {\n const callbackProp = type.getProperty('callback')\n if (callbackProp) {\n const decl = callbackProp.getDeclarations()[0] ?? callbackProp.getValueDeclaration()\n const location = decl ?? fallbackLocation\n if (!location) return 'unknown'\n const callbackType = callbackProp.getTypeAtLocation(location)\n const callSignatures = callbackType.getCallSignatures()\n if (callSignatures.length > 0) {\n return unwrapPromise(callSignatures[0].getReturnType(), tsObj, fallbackLocation)\n }\n }\n return 'unknown'\n }\n }\n\n return widenLiteralType(type, tsObj, fallbackLocation)\n}\n\nfunction unwrapPromise(type: Type, tsObj: TsObj, fallbackLocation?: Node): string {\n // `getAwaitedType()` resolves the `Awaited<T>` of any thenable — covers\n // `Promise<T>`, `PromiseLike<T>`, and branded thenables (e.g. ZenStack's\n // `ZenStackPromise<T>`) whose text doesn't start with `Promise<`.\n const awaited = type.getAwaitedType?.()\n if (awaited && awaited !== type) {\n return stripReadonly(awaited, tsObj, fallbackLocation)\n }\n return stripReadonly(type, tsObj, fallbackLocation)\n}\n\nfunction stripReadonly(type: Type, tsObj: TsObj, fallbackLocation?: Node): string {\n if (type.isTuple()) {\n const elements = type.getTupleElements()\n const parts = elements.map((e) => typeToString(e, tsObj, fallbackLocation))\n return `[${parts.join(', ')}]`\n }\n\n const text = type.getText(undefined, tsObj.TypeFormatFlags.NoTruncation)\n if (text.startsWith('readonly ') && type.isArray()) {\n const elementType = type.getArrayElementType()\n if (elementType) {\n return `Array<${typeToString(elementType, tsObj, fallbackLocation)}>`\n }\n }\n\n return typeToString(type, tsObj, fallbackLocation)\n}\n\n// --- Extract this.inertia.share() call types ---\n\nexport function extractShareCallTypes(\n project: Project,\n SK: TsMorphModule['SyntaxKind'],\n tsObj: TsObj,\n srcDir: string,\n): Map<string, string> {\n const shareTypes = new Map<string, string>()\n\n for (const sourceFile of project.getSourceFiles()) {\n const filePath = sourceFile.getFilePath()\n if (!filePath.startsWith(srcDir.replace(/\\\\/g, '/'))) continue\n if (filePath.includes('__tests__') || filePath.includes('.spec.') || filePath.includes('.test.')) continue\n\n const callExpressions = sourceFile.getDescendantsOfKind(SK.CallExpression)\n\n for (const call of callExpressions) {\n const expr = call.getExpression()\n if (!expr.isKind(SK.PropertyAccessExpression)) continue\n if (expr.getName() !== 'share') continue\n\n // Check that the object is inertia-related (this.inertia.share, inertia.share)\n const objExpr = expr.getExpression()\n const objText = objExpr.getText()\n if (!objText.includes('inertia')) continue\n\n const args = call.getArguments()\n if (args.length < 2) continue\n\n const keyArg = args[0]\n if (!keyArg.isKind(SK.StringLiteral)) continue\n const key = keyArg.getLiteralValue()\n\n if (shareTypes.has(key)) continue\n\n const valueType = widenLiteralType(args[1].getType(), tsObj)\n shareTypes.set(key, valueType)\n }\n }\n\n return shareTypes\n}\n\n// --- Detect i18n config in InertiaModule.forRoot() ---\n\n/**\n * Given the first argument of `Module.forRoot(...)` or `Module.forRootAsync(...)`,\n * return the object literal where downstream options actually live.\n *\n * - For `forRoot({...})` the literal IS the first arg.\n * - For `forRootAsync({ inject, useFactory: (...) => ({...}) })` we drill into\n * the `useFactory`'s return value:\n * `() => ({ … })` — ParenthesizedExpression → ObjectLiteral\n * `() => ({ ... } as Foo)` — AsExpression → ObjectLiteral\n * `() => { return { … } }` — Block → ReturnStatement → ObjectLiteral\n *\n * Returns `null` when nothing usable is found.\n */\nfunction resolveModuleOptionsLiteral(\n optionsArg: Node,\n SK: TsMorphModule['SyntaxKind'],\n): Node | null {\n if (!optionsArg.isKind(SK.ObjectLiteralExpression)) return null\n\n // forRootAsync wrapper: { inject, useFactory: (env) => ({ ... }) }\n const useFactoryProp = optionsArg.getProperty('useFactory')\n if (useFactoryProp?.isKind(SK.PropertyAssignment)) {\n const initializer = useFactoryProp.getInitializer()\n if (initializer?.isKind(SK.ArrowFunction) || initializer?.isKind(SK.FunctionExpression)) {\n const body = initializer.getBody()\n\n // Concise arrow body: () => ({...}) — Parenthesized\n if (body.isKind(SK.ParenthesizedExpression)) {\n const inner = unwrapAs(body.getExpression(), SK)\n if (inner?.isKind(SK.ObjectLiteralExpression)) return inner\n }\n\n // Concise arrow body returning a plain literal (rare without parens but legal)\n const unwrapped = unwrapAs(body, SK)\n if (unwrapped?.isKind(SK.ObjectLiteralExpression)) return unwrapped\n\n // Block body: { ... return {...}; }\n if (body.isKind(SK.Block)) {\n const returnStatements = body.getDescendantsOfKind(SK.ReturnStatement)\n // Walk in reverse so a later `return` wins (last-write-wins semantics)\n for (let i = returnStatements.length - 1; i >= 0; i--) {\n const ret = returnStatements[i]\n const expr = ret.getExpression()\n if (!expr) continue\n if (expr.isKind(SK.ParenthesizedExpression)) {\n const inner = unwrapAs(expr.getExpression(), SK)\n if (inner?.isKind(SK.ObjectLiteralExpression)) return inner\n continue\n }\n const direct = unwrapAs(expr, SK)\n if (direct?.isKind(SK.ObjectLiteralExpression)) return direct\n }\n }\n }\n }\n\n // Plain forRoot({...}) — the first arg IS the options literal.\n return optionsArg\n}\n\n/**\n * Strip a single `as Foo` cast if present, otherwise return the node as-is.\n * `useFactory: (env) => ({ ... } as Options)` is common in TypeScript.\n */\nfunction unwrapAs(node: Node | undefined, SK: TsMorphModule['SyntaxKind']): Node | undefined {\n if (!node) return undefined\n if (node.isKind(SK.AsExpression) || node.isKind(SK.TypeAssertionExpression)) {\n return node.getExpression()\n }\n if (node.isKind(SK.SatisfiesExpression)) {\n return node.getExpression()\n }\n return node\n}\n\nexport interface I18nDetectionResult {\n enabled: boolean\n only: string[]\n}\n\nexport function detectI18nConfig(\n project: Project,\n SK: TsMorphModule['SyntaxKind'],\n srcDir: string,\n): I18nDetectionResult {\n const none: I18nDetectionResult = { enabled: false, only: [] }\n const normalizedSrcDir = srcDir.replace(/\\\\/g, '/')\n\n for (const sourceFile of project.getSourceFiles()) {\n const filePath = sourceFile.getFilePath()\n if (!filePath.startsWith(normalizedSrcDir)) continue\n if (filePath.includes('__tests__') || filePath.includes('.spec.') || filePath.includes('.test.')) continue\n\n const callExpressions = sourceFile.getDescendantsOfKind(SK.CallExpression)\n\n for (const call of callExpressions) {\n const expr = call.getExpression()\n if (!expr.isKind(SK.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(SK.Identifier) || objExpr.getText() !== 'InertiaModule') continue\n\n const args = call.getArguments()\n if (args.length === 0) continue\n\n // 1. AST-based: direct object literals (same-file forRoot / forRootAsync with inline useFactory)\n const optionsLiteral = resolveModuleOptionsLiteral(args[0], SK)\n if (optionsLiteral?.isKind(SK.ObjectLiteralExpression)) {\n const i18nProp = optionsLiteral.getProperty('i18n')\n if (!i18nProp) continue\n return { enabled: true, only: extractOnlyFromLiteral(i18nProp, SK) }\n }\n\n // 2. AST-based cross-file: follow identifier.asProvider() → registerAs factory\n const configLiteral = resolveConfigLiteralFromAsProvider(args[0], SK)\n if (configLiteral?.isKind(SK.ObjectLiteralExpression)) {\n const i18nProp = configLiteral.getProperty('i18n')\n if (i18nProp) return { enabled: true, only: extractOnlyFromLiteral(i18nProp, SK) }\n }\n\n // 3. Type-based fallback: check if the resolved type has an i18n property\n const optionsType = resolveOptionsType(args[0], propName)\n if (optionsType?.getProperty('i18n')) {\n return { enabled: true, only: extractOnlyFromType(optionsType, args[0]) }\n }\n }\n }\n\n return none\n}\n\nfunction resolveConfigLiteralFromAsProvider(\n arg: Node,\n SK: TsMorphModule['SyntaxKind'],\n): Node | null {\n if (!arg.isKind(SK.CallExpression)) return null\n\n const callExpr = arg.getExpression()\n if (!callExpr.isKind(SK.PropertyAccessExpression)) return null\n if (callExpr.getName() !== 'asProvider') return null\n\n const configIdentifier = callExpr.getExpression()\n if (!configIdentifier.isKind(SK.Identifier)) return null\n\n const varDecl = resolveToVariableDeclaration(configIdentifier, SK)\n if (!varDecl) return null\n\n return extractLiteralFromRegisterAs(varDecl, SK)\n}\n\nfunction resolveToVariableDeclaration(\n identifier: Node,\n SK: TsMorphModule['SyntaxKind'],\n): Node | null {\n const symbol = identifier.getSymbol()\n if (!symbol) return null\n\n for (const decl of symbol.getDeclarations()) {\n if (decl.isKind(SK.VariableDeclaration)) return decl\n\n if (decl.isKind(SK.ImportSpecifier)) {\n const sourceFile = decl.getImportDeclaration().getModuleSpecifierSourceFile()\n if (!sourceFile) continue\n\n const exportName = decl.getName()\n const exported = sourceFile.getExportedDeclarations().get(exportName)\n if (!exported) continue\n\n for (const exportDecl of exported) {\n if (exportDecl.isKind(SK.VariableDeclaration)) return exportDecl\n }\n }\n }\n\n return null\n}\n\nfunction extractLiteralFromRegisterAs(\n varDecl: Node,\n SK: TsMorphModule['SyntaxKind'],\n): Node | null {\n if (!varDecl.isKind(SK.VariableDeclaration)) return null\n\n const init = varDecl.getInitializer()\n if (!init?.isKind(SK.CallExpression)) return null\n\n const factoryArgs = init.getArguments()\n if (factoryArgs.length < 2) return null\n\n const factory = factoryArgs[1]\n if (!factory.isKind(SK.ArrowFunction) && !factory.isKind(SK.FunctionExpression)) return null\n\n const body = factory.getBody()\n\n if (body.isKind(SK.ParenthesizedExpression)) {\n const inner = unwrapAs(body.getExpression(), SK)\n if (inner?.isKind(SK.ObjectLiteralExpression)) return inner\n }\n\n const unwrapped = unwrapAs(body, SK)\n if (unwrapped?.isKind(SK.ObjectLiteralExpression)) return unwrapped\n\n if (body.isKind(SK.Block)) {\n const returnStatements = body.getDescendantsOfKind(SK.ReturnStatement)\n for (let i = returnStatements.length - 1; i >= 0; i--) {\n const ret = returnStatements[i]\n const retExpr = ret.getExpression()\n if (!retExpr) continue\n if (retExpr.isKind(SK.ParenthesizedExpression)) {\n const inner = unwrapAs(retExpr.getExpression(), SK)\n if (inner?.isKind(SK.ObjectLiteralExpression)) return inner\n continue\n }\n const direct = unwrapAs(retExpr, SK)\n if (direct?.isKind(SK.ObjectLiteralExpression)) return direct\n }\n }\n\n return null\n}\n\nfunction extractOnlyFromLiteral(i18nProp: Node, SK: TsMorphModule['SyntaxKind']): string[] {\n const only: string[] = []\n if (!i18nProp.isKind(SK.PropertyAssignment)) return only\n const init = i18nProp.getInitializer()\n if (!init?.isKind(SK.ObjectLiteralExpression)) return only\n const onlyProp = init.getProperty('only')\n if (!onlyProp?.isKind(SK.PropertyAssignment)) return only\n const onlyInit = onlyProp.getInitializer()\n if (!onlyInit?.isKind(SK.ArrayLiteralExpression)) return only\n for (const el of onlyInit.getElements()) {\n if (el.isKind(SK.StringLiteral)) {\n only.push(el.getLiteralValue())\n }\n }\n return only\n}\n\nfunction resolveOptionsType(arg: Node, methodName: string): Type | null {\n const argType = arg.getType()\n\n if (methodName === 'forRoot') {\n return argType\n }\n\n // forRootAsync: arg is FactoryProvider-shaped — drill through useFactory return type\n const useFactorySymbol = argType.getProperty('useFactory')\n if (!useFactorySymbol) return null\n\n const useFactoryType = useFactorySymbol.getTypeAtLocation(arg)\n const signatures = useFactoryType.getCallSignatures()\n if (signatures.length === 0) return null\n\n const returnType = signatures[0].getReturnType()\n\n // Return type is T | Promise<T> — find the branch with i18n\n if (returnType.isUnion()) {\n for (const member of returnType.getUnionTypes()) {\n if (member.getProperty('i18n')) return member\n }\n return null\n }\n\n return returnType\n}\n\nfunction extractOnlyFromType(optionsType: Type, locationNode: Node): string[] {\n const i18nSymbol = optionsType.getProperty('i18n')\n if (!i18nSymbol) return []\n\n const i18nType = i18nSymbol.getTypeAtLocation(locationNode)\n const onlySymbol = i18nType.getProperty('only')\n if (!onlySymbol) return []\n\n const onlyType = onlySymbol.getTypeAtLocation(locationNode)\n const elementType = onlyType.getNumberIndexType()\n if (!elementType) return []\n\n const result: string[] = []\n if (elementType.isUnion()) {\n for (const member of elementType.getUnionTypes()) {\n if (member.isStringLiteral()) {\n result.push(member.getLiteralValue() as string)\n }\n }\n } else if (elementType.isStringLiteral()) {\n result.push(elementType.getLiteralValue() as string)\n }\n return result\n}\n\n// --- Extract ctx.flash() call types ---\n\n/**\n * Collect every string-literal value a flash-key argument can resolve to.\n *\n * A direct string literal yields a single key. A conditional expression\n * (`cond ? 'a' : 'b'`, including nested ternaries) contributes the literals\n * from each branch. Non-literal keys (variables, template strings) yield\n * nothing — they can't be statically known.\n */\nfunction collectFlashKeyLiterals(node: Node, SK: TsMorphModule['SyntaxKind']): string[] {\n const stringLiteral = node.asKind(SK.StringLiteral)\n if (stringLiteral) return [stringLiteral.getLiteralValue()]\n\n const conditional = node.asKind(SK.ConditionalExpression)\n if (conditional) {\n return [\n ...collectFlashKeyLiterals(conditional.getWhenTrue(), SK),\n ...collectFlashKeyLiterals(conditional.getWhenFalse(), SK),\n ]\n }\n\n return []\n}\n\nexport function extractFlashTypes(\n project: Project,\n SK: TsMorphModule['SyntaxKind'],\n tsObj: TsObj,\n srcDir: string,\n): FlashTypeInfo | null {\n const flashMembers = new Map<string, string>()\n\n for (const sourceFile of project.getSourceFiles()) {\n const filePath = sourceFile.getFilePath()\n if (!filePath.startsWith(srcDir.replace(/\\\\/g, '/'))) continue\n if (filePath.includes('__tests__') || filePath.includes('.spec.') || filePath.includes('.test.')) continue\n\n const callExpressions = sourceFile.getDescendantsOfKind(SK.CallExpression)\n\n for (const call of callExpressions) {\n const expr = call.getExpression()\n if (!expr.isKind(SK.PropertyAccessExpression)) continue\n if (expr.getName() !== 'flash') continue\n\n const args = call.getArguments()\n if (args.length < 2) continue\n\n // The key may be a plain string literal or a conditional expression\n // selecting between several literals (e.g. `cond ? 'success' : 'error'`).\n // Every literal a branch can produce is a real flash key.\n const keys = collectFlashKeyLiterals(args[0], SK)\n if (keys.length === 0) continue\n\n const valueType = widenLiteralType(args[1].getType(), tsObj)\n for (const key of keys) {\n if (flashMembers.has(key)) continue\n flashMembers.set(key, valueType)\n }\n }\n }\n\n if (flashMembers.size === 0) return null\n\n return {\n members: Array.from(flashMembers.entries()).map(([name, type]) => ({ name, type })),\n }\n}\n\n// --- Extract shared data from module config (existing, refactored) ---\n\nexport function extractSharedDataType(\n project: Project,\n SK: TsMorphModule['SyntaxKind'],\n tsObj: TsObj,\n moduleFilePath: string,\n): SharedDataTypeInfo | null {\n const sourceFile = project.getSourceFile(moduleFilePath)\n ?? project.addSourceFileAtPath(moduleFilePath)\n\n const callExpressions = sourceFile.getDescendantsOfKind(SK.CallExpression)\n\n for (const call of callExpressions) {\n const expr = call.getExpression()\n if (!expr.isKind(SK.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(SK.Identifier) || objExpr.getText() !== 'InertiaModule') continue\n\n const args = call.getArguments()\n if (args.length === 0) continue\n\n const optionsLiteral = resolveModuleOptionsLiteral(args[0], SK)\n if (!optionsLiteral || !optionsLiteral.isKind(SK.ObjectLiteralExpression)) continue\n\n const sharedDataProp = optionsLiteral.getProperty('sharedData')\n if (!sharedDataProp) continue\n\n if (!sharedDataProp.isKind(SK.PropertyAssignment)) continue\n\n const initializer = sharedDataProp.getInitializer()\n if (!initializer?.isKind(SK.ObjectLiteralExpression)) continue\n\n const members: SharedDataMember[] = []\n for (const prop of initializer.getProperties()) {\n if (!prop.isKind(SK.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(SK.ArrowFunction) || value.isKind(SK.FunctionExpression)) {\n const returnType = value.getReturnType()\n valueType = typeToString(returnType, tsObj)\n } else {\n valueType = typeToString(value.getType(), tsObj)\n }\n\n members.push({ name, type: valueType, optional: false })\n }\n\n if (members.length > 0) {\n return { members }\n }\n }\n\n return null\n}\n\n// --- Generate output ---\n\nexport interface GenerateTypesInput {\n pages: PageTypeInfo[]\n sharedData: SharedDataTypeInfo | null\n shareCallTypes: Map<string, string>\n i18n: I18nDetectionResult\n flashTypes: FlashTypeInfo | null\n}\n\nfunction componentNameToPropsTypeName(componentName: string, segmentCount = 2): string {\n const segments = componentName.split('/')\n const used = segments.slice(-segmentCount)\n return used.map(toPascalCase).join('') + 'PageProps'\n}\n\nfunction toPascalCase(segment: string): string {\n return segment\n .split(/[-_\\s]+/)\n .filter((part) => part.length > 0)\n .map((part) => part.charAt(0).toUpperCase() + part.slice(1))\n .join('')\n}\n\nfunction resolvePagePropsTypeNames(pages: PageTypeInfo[]): Map<string, string> {\n const result = new Map<string, string>()\n\n // First pass: use last 2 segments\n const nameToComponents = new Map<string, string[]>()\n for (const page of pages) {\n const typeName = componentNameToPropsTypeName(page.componentName)\n const existing = nameToComponents.get(typeName) ?? []\n existing.push(page.componentName)\n nameToComponents.set(typeName, existing)\n }\n\n // Second pass: resolve collisions by using all segments\n for (const [typeName, components] of nameToComponents) {\n if (components.length === 1) {\n result.set(components[0], typeName)\n } else {\n for (const componentName of components) {\n const fullSegments = componentName.split('/').length\n result.set(componentName, componentNameToPropsTypeName(componentName, fullSegments))\n }\n }\n }\n\n return result\n}\n\nexport function generateInertiaTypes(input: GenerateTypesInput): string {\n const { pages, sharedData, shareCallTypes, i18n, flashTypes } = input\n\n // Compute type names with collision resolution\n const typeNames = resolvePagePropsTypeNames(pages)\n\n const lines: string[] = [\n '// Auto-generated by @stratal/inertia. Do not edit.',\n ]\n\n // Global page props types\n if (pages.length > 0) {\n lines.push('declare global {')\n for (const page of pages) {\n const typeName = typeNames.get(page.componentName)!\n lines.push(` type ${typeName} = ${page.propsType}`)\n }\n lines.push('}')\n lines.push('')\n }\n\n // InertiaPageRegistry augmentation referencing global types\n lines.push(\"declare module '@stratal/inertia' {\")\n lines.push(' interface InertiaPageRegistry {')\n for (const page of pages) {\n const typeName = typeNames.get(page.componentName)!\n lines.push(` '${page.componentName}': ${typeName}`)\n }\n lines.push(' }')\n if (i18n.enabled && i18n.only.length > 0) {\n const prefixUnion = i18n.only.map((p) => `'${p}'`).join(' | ')\n lines.push(' interface InertiaI18nConfig {')\n lines.push(` translationKeys: import('stratal/i18n').FilterByPrefix<import('stratal/i18n').MessageKeys, ${prefixUnion}>`)\n lines.push(' }')\n }\n lines.push('}')\n\n // Build InertiaConfig augmentation\n const configMembers: string[] = []\n\n // Flash data type\n if (flashTypes && flashTypes.members.length > 0) {\n const flashProps = flashTypes.members\n .map((m) => `${m.name}?: ${m.type}`)\n .join('; ')\n configMembers.push(` flashDataType: { ${flashProps} }`)\n }\n\n // Shared page props\n const sharedMembers: string[] = []\n\n // From module config (non-optional)\n if (sharedData) {\n for (const member of sharedData.members) {\n sharedMembers.push(` ${member.name}${member.optional ? '?' : ''}: ${member.type}`)\n }\n }\n\n // From i18n detection (non-optional)\n if (i18n.enabled) {\n sharedMembers.push(' locale: string')\n sharedMembers.push(' translations: Record<string, string>')\n }\n\n // From .share() calls (optional — per-request)\n for (const [key, type] of shareCallTypes) {\n // Skip if already declared by module config\n if (sharedData?.members.some((m) => m.name === key)) continue\n sharedMembers.push(` ${key}?: ${type}`)\n }\n\n if (sharedMembers.length > 0) {\n configMembers.push(` sharedPageProps: {\\n${sharedMembers.join('\\n')}\\n }`)\n }\n\n if (configMembers.length > 0) {\n lines.push('')\n lines.push(\"declare module '@inertiajs/core' {\")\n lines.push(' export interface InertiaConfig {')\n for (const member of configMembers) {\n lines.push(member)\n }\n lines.push(' }')\n lines.push('}')\n }\n\n lines.push('', 'export {}', '')\n\n return lines.join('\\n')\n}\n\n// --- Type string helpers ---\n\nfunction widenLiteralType(type: Type, tsObj: TsObj, fallbackLocation?: Node): string {\n if (type.isStringLiteral()) return 'string'\n if (type.isNumberLiteral()) return 'number'\n if (type.isBooleanLiteral()) return 'boolean'\n return typeToString(type, tsObj, fallbackLocation)\n}\n\nfunction typeToString(type: Type, tsObj: TsObj, fallbackLocation?: Node): string {\n // Preserve MessageKeys as InertiaTranslationKeys — narrows automatically via i18n.only augmentation\n if (type.isUnion() && type.getAliasSymbol?.()?.getName() === 'MessageKeys') {\n return \"import('@stratal/inertia').InertiaTranslationKeys\"\n }\n\n // Always expand objects/unions/intersections so getText() can't leak inline\n // index signatures (e.g. StratalRouteMap params' `[key: string]: ...`).\n if (type.isObject() || type.isUnion() || type.isIntersection()) {\n return expandTypeToInline(type, tsObj, fallbackLocation)\n }\n\n const text = type.getText(undefined, tsObj.TypeFormatFlags.NoTruncation | tsObj.TypeFormatFlags.UseFullyQualifiedType)\n\n if (text.includes('import(')) {\n return expandTypeToInline(type, tsObj, fallbackLocation)\n }\n\n return text\n}\n\nfunction expandPropertyType(\n type: Type,\n tsObj: TsObj,\n fallbackLocation: Node | undefined,\n visiting: Set<Type>,\n isOptional: boolean,\n): string {\n // The `?` marker already implies `undefined`, so strip it from the union\n // to avoid `id?: undefined | string`.\n if (isOptional && type.isUnion()) {\n const parts = type.getUnionTypes().filter((t) => !t.isUndefined())\n if (parts.length === 0) return 'undefined'\n if (parts.length === 1) return expandTypeToInline(parts[0], tsObj, fallbackLocation, visiting)\n return parts.map((t) => expandTypeToInline(t, tsObj, fallbackLocation, visiting)).join(' | ')\n }\n return expandTypeToInline(type, tsObj, fallbackLocation, visiting)\n}\n\nfunction expandTypeToInline(\n type: Type,\n tsObj: TsObj,\n fallbackLocation?: Node,\n visiting = new Set<Type>(),\n): string {\n if (visiting.has(type)) return 'unknown'\n // `boolean` is internally `true | false` — short-circuit before the union branch.\n if (type.isBoolean()) return 'boolean'\n visiting.add(type)\n try {\n if (type.isObject() && !type.isArray() && !type.isReadonlyArray()) {\n // Named global types (Date, RegExp, Map, Set, ...) — emit text as-is.\n // Expanding them iterates every method and produces garbage like\n // `{ toString: ...; getTime: ...; }` for Date.\n const symbolName = type.getSymbol()?.getName()\n const text = type.getText(undefined, tsObj.TypeFormatFlags.NoTruncation | tsObj.TypeFormatFlags.UseFullyQualifiedType)\n if (\n symbolName\n && !symbolName.startsWith('__')\n && symbolName !== 'Object'\n && !text.includes('import(')\n ) {\n return text\n }\n\n const properties = type.getProperties()\n if (properties.length === 0) {\n const stringIndexType = type.getStringIndexType()\n if (stringIndexType) {\n return `Record<string, ${expandTypeToInline(stringIndexType, tsObj, fallbackLocation, visiting)}>`\n }\n // Use `{}` not `Record<string, never>` — `never` collapses intersections.\n return '{}'\n }\n\n const members = properties.map((prop) => {\n const decl = prop.getDeclarations()[0] ?? prop.getValueDeclaration()\n const location = decl ?? fallbackLocation\n const isOptional = prop.isOptional()\n if (!location) return `${prop.getName()}${isOptional ? '?' : ''}: unknown`\n const propType = prop.getTypeAtLocation(location)\n const propTypeStr = expandPropertyType(propType, tsObj, fallbackLocation, visiting, isOptional)\n return `${prop.getName()}${isOptional ? '?' : ''}: ${propTypeStr}`\n })\n\n return `{ ${members.join('; ')} }`\n }\n\n if (type.isArray() || type.isReadonlyArray()) {\n const elementType = type.getArrayElementType()\n if (elementType) {\n const inner = expandTypeToInline(elementType, tsObj, fallbackLocation, visiting)\n return type.isReadonlyArray() ? `ReadonlyArray<${inner}>` : `Array<${inner}>`\n }\n }\n\n if (type.isUnion()) {\n if (type.getAliasSymbol?.()?.getName() === 'MessageKeys') {\n return \"import('@stratal/inertia').InertiaTranslationKeys\"\n }\n return type.getUnionTypes().map((t) => expandTypeToInline(t, tsObj, fallbackLocation, visiting)).join(' | ')\n }\n\n if (type.isIntersection()) {\n return type.getIntersectionTypes().map((t) => expandTypeToInline(t, tsObj, fallbackLocation, visiting)).join(' & ')\n }\n\n const text = type.getText(undefined, tsObj.TypeFormatFlags.NoTruncation)\n if (text.includes('import(')) {\n return 'unknown'\n }\n return text\n } finally {\n visiting.delete(type)\n }\n}\n\n// --- File path helpers ---\n\nexport function writeInertiaTypes(outputPath: string, content: string): boolean {\n if (existsSync(outputPath)) {\n try {\n if (readFileSync(outputPath, 'utf-8') === content) return false\n } catch {\n // fall through and write\n }\n }\n mkdirSync(dirname(outputPath), { recursive: true })\n const tmpPath = `${outputPath}.tmp-${process.pid}-${Date.now()}`\n writeFileSync(tmpPath, content, 'utf-8')\n renameSync(tmpPath, outputPath)\n return true\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\n// --- Main pipeline ---\n\nexport async function runTypeGeneration(cwd: string): Promise<{ outputPath: string; pageCount: number }> {\n const pagesDir = findPagesDir(cwd)\n const srcDir = join(cwd, 'src')\n const outputPath = findOutputPath(cwd)\n const moduleFilePath = findAppModulePath(cwd)\n const tsConfigPath = findTsConfigPath(cwd)\n\n // Single shared project for all extractors\n const { project, SyntaxKind, ts } = await createProject(tsConfigPath)\n\n // 1. Controller ctx.inertia() calls — sole source of truth for InertiaPageRegistry\n const pages = extractControllerPageTypes(project, SyntaxKind, ts, srcDir, pagesDir)\n\n // 2. Module shared data config\n const sharedData = moduleFilePath\n ? extractSharedDataType(project, SyntaxKind, ts, moduleFilePath)\n : null\n\n // 3. i18n detection (scans all source files for InertiaModule.forRoot*)\n const i18n = detectI18nConfig(project, SyntaxKind, srcDir)\n\n // 4. Per-request .share() calls\n const shareCallTypes = extractShareCallTypes(project, SyntaxKind, ts, srcDir)\n\n // 5. Flash ctx.flash() calls\n const flashTypes = extractFlashTypes(project, SyntaxKind, ts, srcDir)\n\n // 6. Generate\n const content = generateInertiaTypes({\n pages,\n sharedData,\n shareCallTypes,\n i18n,\n flashTypes,\n })\n writeInertiaTypes(outputPath, content)\n\n return { outputPath, pageCount: pages.length }\n}\n"],"mappings":";;;AAsBA,eAAe,cAAc;CAC3B,OAAO,OAAO;AAChB;AAWA,eAAe,cAAc,cAA0G;CACrI,MAAM,EAAE,SAAS,YAAY,OAAO,MAAM,YAAY;CActD,OAAO;EAAE,SAAA,IAZW,QAAQ;GAC1B,kBAAkB;GAClB,6BAA6B;GAC7B,iBAAiB,eAAe,KAAA,IAAY;IAC1C,KAAK,GAAG,QAAQ;IAChB,iBAAiB;IACjB,kBAAkB,GAAG,qBAAqB;IAC1C,QAAQ,GAAG,WAAW;IACtB,QAAQ,GAAG,aAAa;GAC1B;EACF,CAEe;EAAG;EAAY;CAAG;AACnC;AAIA,MAAM,qBAAqB;CACzB;CACA;CACA;CACA;CACA;AACF;AAEA,SAAgB,2BACd,SACA,IACA,OACA,QACA,UACgB;CAChB,QAAQ,sBAAsB,KAAK,QAAQ,SAAS,CAAC;CAGrD,MAAM,wBAAQ,IAAI,IAAsB;CAExC,KAAK,MAAM,cAAc,QAAQ,eAAe,GAAG;EACjD,MAAM,WAAW,WAAW,YAAY;EACxC,IAAI,SAAS,SAAS,SAAS,QAAQ,OAAO,GAAG,CAAC,GAAG;EAErD,IAAI,SAAS,SAAS,WAAW,KAAK,SAAS,SAAS,QAAQ,KAAK,SAAS,SAAS,QAAQ,GAAG;EAElG,MAAM,kBAAkB,WAAW,qBAAqB,GAAG,cAAc;EAEzE,KAAK,MAAM,QAAQ,iBAAiB;GAClC,MAAM,OAAO,KAAK,cAAc;GAChC,IAAI,CAAC,KAAK,OAAO,GAAG,wBAAwB,GAAG;GAC/C,IAAI,KAAK,QAAQ,MAAM,WAAW;GAElC,MAAM,OAAO,KAAK,aAAa;GAC/B,IAAI,KAAK,WAAW,GAAG;GAGvB,MAAM,WAAW,KAAK;GACtB,IAAI,CAAC,SAAS,OAAO,GAAG,aAAa,GAAG;GACxC,MAAM,gBAAgB,SAAS,gBAAgB;GAE/C,IAAI,CAAC,MAAM,IAAI,aAAa,GAC1B,MAAM,IAAI,eAAe,CAAC,CAAC;GAI7B,IAAI,KAAK,SAAS,GAAG;IACnB,MAAM,IAAI,aAAa,EAAG,KAAK,uBAAuB;IACtD;GACF;GAEA,MAAM,WAAW,KAAK;GACtB,MAAM,YAAY,SAAS,QAAQ;GAGnC,IAAI,UAAU,SAAS,KAAK,CAAC,UAAU,QAAQ,GAAG;IAChD,MAAM,aAAa,UAAU,cAAc;IAC3C,IAAI,WAAW,WAAW,GAAG;KAC3B,MAAM,IAAI,aAAa,EAAG,KAAK,uBAAuB;KACtD;IACF;IAEA,MAAM,UAAU,WAAW,KAAK,SAAS;KAEvC,MAAM,WADO,KAAK,gBAAgB,EAAE,MAAM,KAAK,oBAAoB,KAC1C;KACzB,MAAM,aAAa,KAAK,WAAW;KAEnC,MAAM,YAAY,kBADD,KAAK,kBAAkB,QACG,GAAG,OAAO,QAAQ;KAC7D,OAAO,GAAG,KAAK,QAAQ,IAAI,aAAa,MAAM,GAAG,IAAI;IACvD,CAAC;IAED,MAAM,IAAI,aAAa,EAAG,KAAK,KAAK,QAAQ,KAAK,IAAI,EAAE,GAAG;GAC5D,OACE,MAAM,IAAI,aAAa,EAAG,KAAK,aAAa,WAAW,OAAO,QAAQ,CAAC;EAE3E;CACF;CAEA,OAAO,MAAM,KAAK,MAAM,QAAQ,CAAC,EAC9B,KAAK,CAAC,eAAe,kBAAkB;EAEtC,MAAM,SAAS,CAAC,GAAG,IAAI,IAAI,YAAY,CAAC;EAExC,OAAO;GAAE;GAAe,WADN,OAAO,WAAW,IAAI,OAAO,KAAK,OAAO,KAAK,KAAK;EACnC;CACpC,CAAC,EACA,MAAM,GAAG,MAAM,EAAE,cAAc,cAAc,EAAE,aAAa,CAAC;AAClE;AAEA,SAAS,kBAAkB,MAAY,OAAc,kBAAiC;CACpF,IAAI,KAAK,QAAQ,GAAG;EAElB,MAAM,YADa,KAAK,cACG,EACxB,QAAQ,MAAM;GACb,MAAM,OAAO,EAAE,QAAQ,KAAA,GAAW,MAAM,gBAAgB,YAAY;GACpE,OAAO,CAAC,mBAAmB,MAAM,SAAS,KAAK,SAAS,IAAI,CAAC;EAC/D,CAAC,EACA,KAAK,MAAM,aAAa,GAAG,OAAO,gBAAgB,CAAC;EAEtD,IAAI,UAAU,SAAS,GACrB,OAAO,UAAU,KAAK,KAAK;CAE/B;CAGA,MAAM,OAAO,KAAK,QAAQ,KAAA,GAAW,MAAM,gBAAgB,YAAY;CACvE,KAAK,MAAM,eAAe,oBACxB,IAAI,KAAK,SAAS,WAAW,GAAG;EAC9B,MAAM,eAAe,KAAK,YAAY,UAAU;EAChD,IAAI,cAAc;GAEhB,MAAM,WADO,aAAa,gBAAgB,EAAE,MAAM,aAAa,oBAAoB,KAC1D;GACzB,IAAI,CAAC,UAAU,OAAO;GAEtB,MAAM,iBADe,aAAa,kBAAkB,QAClB,EAAE,kBAAkB;GACtD,IAAI,eAAe,SAAS,GAC1B,OAAO,cAAc,eAAe,GAAG,cAAc,GAAG,OAAO,gBAAgB;EAEnF;EACA,OAAO;CACT;CAGF,OAAO,iBAAiB,MAAM,OAAO,gBAAgB;AACvD;AAEA,SAAS,cAAc,MAAY,OAAc,kBAAiC;CAIhF,MAAM,UAAU,KAAK,iBAAiB;CACtC,IAAI,WAAW,YAAY,MACzB,OAAO,cAAc,SAAS,OAAO,gBAAgB;CAEvD,OAAO,cAAc,MAAM,OAAO,gBAAgB;AACpD;AAEA,SAAS,cAAc,MAAY,OAAc,kBAAiC;CAChF,IAAI,KAAK,QAAQ,GAGf,OAAO,IAFU,KAAK,iBACD,EAAE,KAAK,MAAM,aAAa,GAAG,OAAO,gBAAgB,CAC1D,EAAE,KAAK,IAAI,EAAE;CAI9B,IADa,KAAK,QAAQ,KAAA,GAAW,MAAM,gBAAgB,YACpD,EAAE,WAAW,WAAW,KAAK,KAAK,QAAQ,GAAG;EAClD,MAAM,cAAc,KAAK,oBAAoB;EAC7C,IAAI,aACF,OAAO,SAAS,aAAa,aAAa,OAAO,gBAAgB,EAAE;CAEvE;CAEA,OAAO,aAAa,MAAM,OAAO,gBAAgB;AACnD;AAIA,SAAgB,sBACd,SACA,IACA,OACA,QACqB;CACrB,MAAM,6BAAa,IAAI,IAAoB;CAE3C,KAAK,MAAM,cAAc,QAAQ,eAAe,GAAG;EACjD,MAAM,WAAW,WAAW,YAAY;EACxC,IAAI,CAAC,SAAS,WAAW,OAAO,QAAQ,OAAO,GAAG,CAAC,GAAG;EACtD,IAAI,SAAS,SAAS,WAAW,KAAK,SAAS,SAAS,QAAQ,KAAK,SAAS,SAAS,QAAQ,GAAG;EAElG,MAAM,kBAAkB,WAAW,qBAAqB,GAAG,cAAc;EAEzE,KAAK,MAAM,QAAQ,iBAAiB;GAClC,MAAM,OAAO,KAAK,cAAc;GAChC,IAAI,CAAC,KAAK,OAAO,GAAG,wBAAwB,GAAG;GAC/C,IAAI,KAAK,QAAQ,MAAM,SAAS;GAKhC,IAAI,CAFY,KAAK,cACC,EAAE,QACb,EAAE,SAAS,SAAS,GAAG;GAElC,MAAM,OAAO,KAAK,aAAa;GAC/B,IAAI,KAAK,SAAS,GAAG;GAErB,MAAM,SAAS,KAAK;GACpB,IAAI,CAAC,OAAO,OAAO,GAAG,aAAa,GAAG;GACtC,MAAM,MAAM,OAAO,gBAAgB;GAEnC,IAAI,WAAW,IAAI,GAAG,GAAG;GAEzB,MAAM,YAAY,iBAAiB,KAAK,GAAG,QAAQ,GAAG,KAAK;GAC3D,WAAW,IAAI,KAAK,SAAS;EAC/B;CACF;CAEA,OAAO;AACT;;;;;;;;;;;;;;AAiBA,SAAS,4BACP,YACA,IACa;CACb,IAAI,CAAC,WAAW,OAAO,GAAG,uBAAuB,GAAG,OAAO;CAG3D,MAAM,iBAAiB,WAAW,YAAY,YAAY;CAC1D,IAAI,gBAAgB,OAAO,GAAG,kBAAkB,GAAG;EACjD,MAAM,cAAc,eAAe,eAAe;EAClD,IAAI,aAAa,OAAO,GAAG,aAAa,KAAK,aAAa,OAAO,GAAG,kBAAkB,GAAG;GACvF,MAAM,OAAO,YAAY,QAAQ;GAGjC,IAAI,KAAK,OAAO,GAAG,uBAAuB,GAAG;IAC3C,MAAM,QAAQ,SAAS,KAAK,cAAc,GAAG,EAAE;IAC/C,IAAI,OAAO,OAAO,GAAG,uBAAuB,GAAG,OAAO;GACxD;GAGA,MAAM,YAAY,SAAS,MAAM,EAAE;GACnC,IAAI,WAAW,OAAO,GAAG,uBAAuB,GAAG,OAAO;GAG1D,IAAI,KAAK,OAAO,GAAG,KAAK,GAAG;IACzB,MAAM,mBAAmB,KAAK,qBAAqB,GAAG,eAAe;IAErE,KAAK,IAAI,IAAI,iBAAiB,SAAS,GAAG,KAAK,GAAG,KAAK;KAErD,MAAM,OADM,iBAAiB,GACZ,cAAc;KAC/B,IAAI,CAAC,MAAM;KACX,IAAI,KAAK,OAAO,GAAG,uBAAuB,GAAG;MAC3C,MAAM,QAAQ,SAAS,KAAK,cAAc,GAAG,EAAE;MAC/C,IAAI,OAAO,OAAO,GAAG,uBAAuB,GAAG,OAAO;MACtD;KACF;KACA,MAAM,SAAS,SAAS,MAAM,EAAE;KAChC,IAAI,QAAQ,OAAO,GAAG,uBAAuB,GAAG,OAAO;IACzD;GACF;EACF;CACF;CAGA,OAAO;AACT;;;;;AAMA,SAAS,SAAS,MAAwB,IAAmD;CAC3F,IAAI,CAAC,MAAM,OAAO,KAAA;CAClB,IAAI,KAAK,OAAO,GAAG,YAAY,KAAK,KAAK,OAAO,GAAG,uBAAuB,GACxE,OAAO,KAAK,cAAc;CAE5B,IAAI,KAAK,OAAO,GAAG,mBAAmB,GACpC,OAAO,KAAK,cAAc;CAE5B,OAAO;AACT;AAOA,SAAgB,iBACd,SACA,IACA,QACqB;CACrB,MAAM,OAA4B;EAAE,SAAS;EAAO,MAAM,CAAC;CAAE;CAC7D,MAAM,mBAAmB,OAAO,QAAQ,OAAO,GAAG;CAElD,KAAK,MAAM,cAAc,QAAQ,eAAe,GAAG;EACjD,MAAM,WAAW,WAAW,YAAY;EACxC,IAAI,CAAC,SAAS,WAAW,gBAAgB,GAAG;EAC5C,IAAI,SAAS,SAAS,WAAW,KAAK,SAAS,SAAS,QAAQ,KAAK,SAAS,SAAS,QAAQ,GAAG;EAElG,MAAM,kBAAkB,WAAW,qBAAqB,GAAG,cAAc;EAEzE,KAAK,MAAM,QAAQ,iBAAiB;GAClC,MAAM,OAAO,KAAK,cAAc;GAChC,IAAI,CAAC,KAAK,OAAO,GAAG,wBAAwB,GAAG;GAE/C,MAAM,WAAW,KAAK,QAAQ;GAC9B,IAAI,aAAa,aAAa,aAAa,gBAAgB;GAE3D,MAAM,UAAU,KAAK,cAAc;GACnC,IAAI,CAAC,QAAQ,OAAO,GAAG,UAAU,KAAK,QAAQ,QAAQ,MAAM,iBAAiB;GAE7E,MAAM,OAAO,KAAK,aAAa;GAC/B,IAAI,KAAK,WAAW,GAAG;GAGvB,MAAM,iBAAiB,4BAA4B,KAAK,IAAI,EAAE;GAC9D,IAAI,gBAAgB,OAAO,GAAG,uBAAuB,GAAG;IACtD,MAAM,WAAW,eAAe,YAAY,MAAM;IAClD,IAAI,CAAC,UAAU;IACf,OAAO;KAAE,SAAS;KAAM,MAAM,uBAAuB,UAAU,EAAE;IAAE;GACrE;GAGA,MAAM,gBAAgB,mCAAmC,KAAK,IAAI,EAAE;GACpE,IAAI,eAAe,OAAO,GAAG,uBAAuB,GAAG;IACrD,MAAM,WAAW,cAAc,YAAY,MAAM;IACjD,IAAI,UAAU,OAAO;KAAE,SAAS;KAAM,MAAM,uBAAuB,UAAU,EAAE;IAAE;GACnF;GAGA,MAAM,cAAc,mBAAmB,KAAK,IAAI,QAAQ;GACxD,IAAI,aAAa,YAAY,MAAM,GACjC,OAAO;IAAE,SAAS;IAAM,MAAM,oBAAoB,aAAa,KAAK,EAAE;GAAE;EAE5E;CACF;CAEA,OAAO;AACT;AAEA,SAAS,mCACP,KACA,IACa;CACb,IAAI,CAAC,IAAI,OAAO,GAAG,cAAc,GAAG,OAAO;CAE3C,MAAM,WAAW,IAAI,cAAc;CACnC,IAAI,CAAC,SAAS,OAAO,GAAG,wBAAwB,GAAG,OAAO;CAC1D,IAAI,SAAS,QAAQ,MAAM,cAAc,OAAO;CAEhD,MAAM,mBAAmB,SAAS,cAAc;CAChD,IAAI,CAAC,iBAAiB,OAAO,GAAG,UAAU,GAAG,OAAO;CAEpD,MAAM,UAAU,6BAA6B,kBAAkB,EAAE;CACjE,IAAI,CAAC,SAAS,OAAO;CAErB,OAAO,6BAA6B,SAAS,EAAE;AACjD;AAEA,SAAS,6BACP,YACA,IACa;CACb,MAAM,SAAS,WAAW,UAAU;CACpC,IAAI,CAAC,QAAQ,OAAO;CAEpB,KAAK,MAAM,QAAQ,OAAO,gBAAgB,GAAG;EAC3C,IAAI,KAAK,OAAO,GAAG,mBAAmB,GAAG,OAAO;EAEhD,IAAI,KAAK,OAAO,GAAG,eAAe,GAAG;GACnC,MAAM,aAAa,KAAK,qBAAqB,EAAE,6BAA6B;GAC5E,IAAI,CAAC,YAAY;GAEjB,MAAM,aAAa,KAAK,QAAQ;GAChC,MAAM,WAAW,WAAW,wBAAwB,EAAE,IAAI,UAAU;GACpE,IAAI,CAAC,UAAU;GAEf,KAAK,MAAM,cAAc,UACvB,IAAI,WAAW,OAAO,GAAG,mBAAmB,GAAG,OAAO;EAE1D;CACF;CAEA,OAAO;AACT;AAEA,SAAS,6BACP,SACA,IACa;CACb,IAAI,CAAC,QAAQ,OAAO,GAAG,mBAAmB,GAAG,OAAO;CAEpD,MAAM,OAAO,QAAQ,eAAe;CACpC,IAAI,CAAC,MAAM,OAAO,GAAG,cAAc,GAAG,OAAO;CAE7C,MAAM,cAAc,KAAK,aAAa;CACtC,IAAI,YAAY,SAAS,GAAG,OAAO;CAEnC,MAAM,UAAU,YAAY;CAC5B,IAAI,CAAC,QAAQ,OAAO,GAAG,aAAa,KAAK,CAAC,QAAQ,OAAO,GAAG,kBAAkB,GAAG,OAAO;CAExF,MAAM,OAAO,QAAQ,QAAQ;CAE7B,IAAI,KAAK,OAAO,GAAG,uBAAuB,GAAG;EAC3C,MAAM,QAAQ,SAAS,KAAK,cAAc,GAAG,EAAE;EAC/C,IAAI,OAAO,OAAO,GAAG,uBAAuB,GAAG,OAAO;CACxD;CAEA,MAAM,YAAY,SAAS,MAAM,EAAE;CACnC,IAAI,WAAW,OAAO,GAAG,uBAAuB,GAAG,OAAO;CAE1D,IAAI,KAAK,OAAO,GAAG,KAAK,GAAG;EACzB,MAAM,mBAAmB,KAAK,qBAAqB,GAAG,eAAe;EACrE,KAAK,IAAI,IAAI,iBAAiB,SAAS,GAAG,KAAK,GAAG,KAAK;GAErD,MAAM,UADM,iBAAiB,GACT,cAAc;GAClC,IAAI,CAAC,SAAS;GACd,IAAI,QAAQ,OAAO,GAAG,uBAAuB,GAAG;IAC9C,MAAM,QAAQ,SAAS,QAAQ,cAAc,GAAG,EAAE;IAClD,IAAI,OAAO,OAAO,GAAG,uBAAuB,GAAG,OAAO;IACtD;GACF;GACA,MAAM,SAAS,SAAS,SAAS,EAAE;GACnC,IAAI,QAAQ,OAAO,GAAG,uBAAuB,GAAG,OAAO;EACzD;CACF;CAEA,OAAO;AACT;AAEA,SAAS,uBAAuB,UAAgB,IAA2C;CACzF,MAAM,OAAiB,CAAC;CACxB,IAAI,CAAC,SAAS,OAAO,GAAG,kBAAkB,GAAG,OAAO;CACpD,MAAM,OAAO,SAAS,eAAe;CACrC,IAAI,CAAC,MAAM,OAAO,GAAG,uBAAuB,GAAG,OAAO;CACtD,MAAM,WAAW,KAAK,YAAY,MAAM;CACxC,IAAI,CAAC,UAAU,OAAO,GAAG,kBAAkB,GAAG,OAAO;CACrD,MAAM,WAAW,SAAS,eAAe;CACzC,IAAI,CAAC,UAAU,OAAO,GAAG,sBAAsB,GAAG,OAAO;CACzD,KAAK,MAAM,MAAM,SAAS,YAAY,GACpC,IAAI,GAAG,OAAO,GAAG,aAAa,GAC5B,KAAK,KAAK,GAAG,gBAAgB,CAAC;CAGlC,OAAO;AACT;AAEA,SAAS,mBAAmB,KAAW,YAAiC;CACtE,MAAM,UAAU,IAAI,QAAQ;CAE5B,IAAI,eAAe,WACjB,OAAO;CAIT,MAAM,mBAAmB,QAAQ,YAAY,YAAY;CACzD,IAAI,CAAC,kBAAkB,OAAO;CAG9B,MAAM,aADiB,iBAAiB,kBAAkB,GAC1B,EAAE,kBAAkB;CACpD,IAAI,WAAW,WAAW,GAAG,OAAO;CAEpC,MAAM,aAAa,WAAW,GAAG,cAAc;CAG/C,IAAI,WAAW,QAAQ,GAAG;EACxB,KAAK,MAAM,UAAU,WAAW,cAAc,GAC5C,IAAI,OAAO,YAAY,MAAM,GAAG,OAAO;EAEzC,OAAO;CACT;CAEA,OAAO;AACT;AAEA,SAAS,oBAAoB,aAAmB,cAA8B;CAC5E,MAAM,aAAa,YAAY,YAAY,MAAM;CACjD,IAAI,CAAC,YAAY,OAAO,CAAC;CAGzB,MAAM,aADW,WAAW,kBAAkB,YACpB,EAAE,YAAY,MAAM;CAC9C,IAAI,CAAC,YAAY,OAAO,CAAC;CAGzB,MAAM,cADW,WAAW,kBAAkB,YACnB,EAAE,mBAAmB;CAChD,IAAI,CAAC,aAAa,OAAO,CAAC;CAE1B,MAAM,SAAmB,CAAC;CAC1B,IAAI,YAAY,QAAQ;OACjB,MAAM,UAAU,YAAY,cAAc,GAC7C,IAAI,OAAO,gBAAgB,GACzB,OAAO,KAAK,OAAO,gBAAgB,CAAW;CAAA,OAG7C,IAAI,YAAY,gBAAgB,GACrC,OAAO,KAAK,YAAY,gBAAgB,CAAW;CAErD,OAAO;AACT;;;;;;;;;AAYA,SAAS,wBAAwB,MAAY,IAA2C;CACtF,MAAM,gBAAgB,KAAK,OAAO,GAAG,aAAa;CAClD,IAAI,eAAe,OAAO,CAAC,cAAc,gBAAgB,CAAC;CAE1D,MAAM,cAAc,KAAK,OAAO,GAAG,qBAAqB;CACxD,IAAI,aACF,OAAO,CACL,GAAG,wBAAwB,YAAY,YAAY,GAAG,EAAE,GACxD,GAAG,wBAAwB,YAAY,aAAa,GAAG,EAAE,CAC3D;CAGF,OAAO,CAAC;AACV;AAEA,SAAgB,kBACd,SACA,IACA,OACA,QACsB;CACtB,MAAM,+BAAe,IAAI,IAAoB;CAE7C,KAAK,MAAM,cAAc,QAAQ,eAAe,GAAG;EACjD,MAAM,WAAW,WAAW,YAAY;EACxC,IAAI,CAAC,SAAS,WAAW,OAAO,QAAQ,OAAO,GAAG,CAAC,GAAG;EACtD,IAAI,SAAS,SAAS,WAAW,KAAK,SAAS,SAAS,QAAQ,KAAK,SAAS,SAAS,QAAQ,GAAG;EAElG,MAAM,kBAAkB,WAAW,qBAAqB,GAAG,cAAc;EAEzE,KAAK,MAAM,QAAQ,iBAAiB;GAClC,MAAM,OAAO,KAAK,cAAc;GAChC,IAAI,CAAC,KAAK,OAAO,GAAG,wBAAwB,GAAG;GAC/C,IAAI,KAAK,QAAQ,MAAM,SAAS;GAEhC,MAAM,OAAO,KAAK,aAAa;GAC/B,IAAI,KAAK,SAAS,GAAG;GAKrB,MAAM,OAAO,wBAAwB,KAAK,IAAI,EAAE;GAChD,IAAI,KAAK,WAAW,GAAG;GAEvB,MAAM,YAAY,iBAAiB,KAAK,GAAG,QAAQ,GAAG,KAAK;GAC3D,KAAK,MAAM,OAAO,MAAM;IACtB,IAAI,aAAa,IAAI,GAAG,GAAG;IAC3B,aAAa,IAAI,KAAK,SAAS;GACjC;EACF;CACF;CAEA,IAAI,aAAa,SAAS,GAAG,OAAO;CAEpC,OAAO,EACL,SAAS,MAAM,KAAK,aAAa,QAAQ,CAAC,EAAE,KAAK,CAAC,MAAM,WAAW;EAAE;EAAM;CAAK,EAAE,EACpF;AACF;AAIA,SAAgB,sBACd,SACA,IACA,OACA,gBAC2B;CAI3B,MAAM,mBAHa,QAAQ,cAAc,cAAc,KAClD,QAAQ,oBAAoB,cAAc,GAEZ,qBAAqB,GAAG,cAAc;CAEzE,KAAK,MAAM,QAAQ,iBAAiB;EAClC,MAAM,OAAO,KAAK,cAAc;EAChC,IAAI,CAAC,KAAK,OAAO,GAAG,wBAAwB,GAAG;EAE/C,MAAM,WAAW,KAAK,QAAQ;EAC9B,IAAI,aAAa,aAAa,aAAa,gBAAgB;EAE3D,MAAM,UAAU,KAAK,cAAc;EACnC,IAAI,CAAC,QAAQ,OAAO,GAAG,UAAU,KAAK,QAAQ,QAAQ,MAAM,iBAAiB;EAE7E,MAAM,OAAO,KAAK,aAAa;EAC/B,IAAI,KAAK,WAAW,GAAG;EAEvB,MAAM,iBAAiB,4BAA4B,KAAK,IAAI,EAAE;EAC9D,IAAI,CAAC,kBAAkB,CAAC,eAAe,OAAO,GAAG,uBAAuB,GAAG;EAE3E,MAAM,iBAAiB,eAAe,YAAY,YAAY;EAC9D,IAAI,CAAC,gBAAgB;EAErB,IAAI,CAAC,eAAe,OAAO,GAAG,kBAAkB,GAAG;EAEnD,MAAM,cAAc,eAAe,eAAe;EAClD,IAAI,CAAC,aAAa,OAAO,GAAG,uBAAuB,GAAG;EAEtD,MAAM,UAA8B,CAAC;EACrC,KAAK,MAAM,QAAQ,YAAY,cAAc,GAAG;GAC9C,IAAI,CAAC,KAAK,OAAO,GAAG,kBAAkB,GAAG;GAEzC,MAAM,OAAO,KAAK,QAAQ;GAC1B,MAAM,QAAQ,KAAK,eAAe;GAClC,IAAI,CAAC,OAAO;GAEZ,IAAI;GAEJ,IAAI,MAAM,OAAO,GAAG,aAAa,KAAK,MAAM,OAAO,GAAG,kBAAkB,GAEtE,YAAY,aADO,MAAM,cACS,GAAG,KAAK;QAE1C,YAAY,aAAa,MAAM,QAAQ,GAAG,KAAK;GAGjD,QAAQ,KAAK;IAAE;IAAM,MAAM;IAAW,UAAU;GAAM,CAAC;EACzD;EAEA,IAAI,QAAQ,SAAS,GACnB,OAAO,EAAE,QAAQ;CAErB;CAEA,OAAO;AACT;AAYA,SAAS,6BAA6B,eAAuB,eAAe,GAAW;CAGrF,OAFiB,cAAc,MAAM,GACjB,EAAE,MAAM,CAAC,YACnB,EAAE,IAAI,YAAY,EAAE,KAAK,EAAE,IAAI;AAC3C;AAEA,SAAS,aAAa,SAAyB;CAC7C,OAAO,QACJ,MAAM,SAAS,EACf,QAAQ,SAAS,KAAK,SAAS,CAAC,EAChC,KAAK,SAAS,KAAK,OAAO,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC,CAAC,EAC1D,KAAK,EAAE;AACZ;AAEA,SAAS,0BAA0B,OAA4C;CAC7E,MAAM,yBAAS,IAAI,IAAoB;CAGvC,MAAM,mCAAmB,IAAI,IAAsB;CACnD,KAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,WAAW,6BAA6B,KAAK,aAAa;EAChE,MAAM,WAAW,iBAAiB,IAAI,QAAQ,KAAK,CAAC;EACpD,SAAS,KAAK,KAAK,aAAa;EAChC,iBAAiB,IAAI,UAAU,QAAQ;CACzC;CAGA,KAAK,MAAM,CAAC,UAAU,eAAe,kBACnC,IAAI,WAAW,WAAW,GACxB,OAAO,IAAI,WAAW,IAAI,QAAQ;MAElC,KAAK,MAAM,iBAAiB,YAAY;EACtC,MAAM,eAAe,cAAc,MAAM,GAAG,EAAE;EAC9C,OAAO,IAAI,eAAe,6BAA6B,eAAe,YAAY,CAAC;CACrF;CAIJ,OAAO;AACT;AAEA,SAAgB,qBAAqB,OAAmC;CACtE,MAAM,EAAE,OAAO,YAAY,gBAAgB,MAAM,eAAe;CAGhE,MAAM,YAAY,0BAA0B,KAAK;CAEjD,MAAM,QAAkB,CACtB,qDACF;CAGA,IAAI,MAAM,SAAS,GAAG;EACpB,MAAM,KAAK,kBAAkB;EAC7B,KAAK,MAAM,QAAQ,OAAO;GACxB,MAAM,WAAW,UAAU,IAAI,KAAK,aAAa;GACjD,MAAM,KAAK,UAAU,SAAS,KAAK,KAAK,WAAW;EACrD;EACA,MAAM,KAAK,GAAG;EACd,MAAM,KAAK,EAAE;CACf;CAGA,MAAM,KAAK,qCAAqC;CAChD,MAAM,KAAK,mCAAmC;CAC9C,KAAK,MAAM,QAAQ,OAAO;EACxB,MAAM,WAAW,UAAU,IAAI,KAAK,aAAa;EACjD,MAAM,KAAK,QAAQ,KAAK,cAAc,KAAK,UAAU;CACvD;CACA,MAAM,KAAK,KAAK;CAChB,IAAI,KAAK,WAAW,KAAK,KAAK,SAAS,GAAG;EACxC,MAAM,cAAc,KAAK,KAAK,KAAK,MAAM,IAAI,EAAE,EAAE,EAAE,KAAK,KAAK;EAC7D,MAAM,KAAK,iCAAiC;EAC5C,MAAM,KAAK,kGAAkG,YAAY,EAAE;EAC3H,MAAM,KAAK,KAAK;CAClB;CACA,MAAM,KAAK,GAAG;CAGd,MAAM,gBAA0B,CAAC;CAGjC,IAAI,cAAc,WAAW,QAAQ,SAAS,GAAG;EAC/C,MAAM,aAAa,WAAW,QAC3B,KAAK,MAAM,GAAG,EAAE,KAAK,KAAK,EAAE,MAAM,EAClC,KAAK,IAAI;EACZ,cAAc,KAAK,wBAAwB,WAAW,GAAG;CAC3D;CAGA,MAAM,gBAA0B,CAAC;CAGjC,IAAI,YACF,KAAK,MAAM,UAAU,WAAW,SAC9B,cAAc,KAAK,SAAS,OAAO,OAAO,OAAO,WAAW,MAAM,GAAG,IAAI,OAAO,MAAM;CAK1F,IAAI,KAAK,SAAS;EAChB,cAAc,KAAK,sBAAsB;EACzC,cAAc,KAAK,4CAA4C;CACjE;CAGA,KAAK,MAAM,CAAC,KAAK,SAAS,gBAAgB;EAExC,IAAI,YAAY,QAAQ,MAAM,MAAM,EAAE,SAAS,GAAG,GAAG;EACrD,cAAc,KAAK,SAAS,IAAI,KAAK,MAAM;CAC7C;CAEA,IAAI,cAAc,SAAS,GACzB,cAAc,KAAK,2BAA2B,cAAc,KAAK,IAAI,EAAE,QAAQ;CAGjF,IAAI,cAAc,SAAS,GAAG;EAC5B,MAAM,KAAK,EAAE;EACb,MAAM,KAAK,oCAAoC;EAC/C,MAAM,KAAK,oCAAoC;EAC/C,KAAK,MAAM,UAAU,eACnB,MAAM,KAAK,MAAM;EAEnB,MAAM,KAAK,KAAK;EAChB,MAAM,KAAK,GAAG;CAChB;CAEA,MAAM,KAAK,IAAI,aAAa,EAAE;CAE9B,OAAO,MAAM,KAAK,IAAI;AACxB;AAIA,SAAS,iBAAiB,MAAY,OAAc,kBAAiC;CACnF,IAAI,KAAK,gBAAgB,GAAG,OAAO;CACnC,IAAI,KAAK,gBAAgB,GAAG,OAAO;CACnC,IAAI,KAAK,iBAAiB,GAAG,OAAO;CACpC,OAAO,aAAa,MAAM,OAAO,gBAAgB;AACnD;AAEA,SAAS,aAAa,MAAY,OAAc,kBAAiC;CAE/E,IAAI,KAAK,QAAQ,KAAK,KAAK,iBAAiB,GAAG,QAAQ,MAAM,eAC3D,OAAO;CAKT,IAAI,KAAK,SAAS,KAAK,KAAK,QAAQ,KAAK,KAAK,eAAe,GAC3D,OAAO,mBAAmB,MAAM,OAAO,gBAAgB;CAGzD,MAAM,OAAO,KAAK,QAAQ,KAAA,GAAW,MAAM,gBAAgB,eAAe,MAAM,gBAAgB,qBAAqB;CAErH,IAAI,KAAK,SAAS,SAAS,GACzB,OAAO,mBAAmB,MAAM,OAAO,gBAAgB;CAGzD,OAAO;AACT;AAEA,SAAS,mBACP,MACA,OACA,kBACA,UACA,YACQ;CAGR,IAAI,cAAc,KAAK,QAAQ,GAAG;EAChC,MAAM,QAAQ,KAAK,cAAc,EAAE,QAAQ,MAAM,CAAC,EAAE,YAAY,CAAC;EACjE,IAAI,MAAM,WAAW,GAAG,OAAO;EAC/B,IAAI,MAAM,WAAW,GAAG,OAAO,mBAAmB,MAAM,IAAI,OAAO,kBAAkB,QAAQ;EAC7F,OAAO,MAAM,KAAK,MAAM,mBAAmB,GAAG,OAAO,kBAAkB,QAAQ,CAAC,EAAE,KAAK,KAAK;CAC9F;CACA,OAAO,mBAAmB,MAAM,OAAO,kBAAkB,QAAQ;AACnE;AAEA,SAAS,mBACP,MACA,OACA,kBACA,2BAAW,IAAI,IAAU,GACjB;CACR,IAAI,SAAS,IAAI,IAAI,GAAG,OAAO;CAE/B,IAAI,KAAK,UAAU,GAAG,OAAO;CAC7B,SAAS,IAAI,IAAI;CACjB,IAAI;EACF,IAAI,KAAK,SAAS,KAAK,CAAC,KAAK,QAAQ,KAAK,CAAC,KAAK,gBAAgB,GAAG;GAIjE,MAAM,aAAa,KAAK,UAAU,GAAG,QAAQ;GAC7C,MAAM,OAAO,KAAK,QAAQ,KAAA,GAAW,MAAM,gBAAgB,eAAe,MAAM,gBAAgB,qBAAqB;GACrH,IACE,cACG,CAAC,WAAW,WAAW,IAAI,KAC3B,eAAe,YACf,CAAC,KAAK,SAAS,SAAS,GAE3B,OAAO;GAGT,MAAM,aAAa,KAAK,cAAc;GACtC,IAAI,WAAW,WAAW,GAAG;IAC3B,MAAM,kBAAkB,KAAK,mBAAmB;IAChD,IAAI,iBACF,OAAO,kBAAkB,mBAAmB,iBAAiB,OAAO,kBAAkB,QAAQ,EAAE;IAGlG,OAAO;GACT;GAYA,OAAO,KAVS,WAAW,KAAK,SAAS;IAEvC,MAAM,WADO,KAAK,gBAAgB,EAAE,MAAM,KAAK,oBAAoB,KAC1C;IACzB,MAAM,aAAa,KAAK,WAAW;IACnC,IAAI,CAAC,UAAU,OAAO,GAAG,KAAK,QAAQ,IAAI,aAAa,MAAM,GAAG;IAEhE,MAAM,cAAc,mBADH,KAAK,kBAAkB,QACM,GAAG,OAAO,kBAAkB,UAAU,UAAU;IAC9F,OAAO,GAAG,KAAK,QAAQ,IAAI,aAAa,MAAM,GAAG,IAAI;GACvD,CAEkB,EAAE,KAAK,IAAI,EAAE;EACjC;EAEA,IAAI,KAAK,QAAQ,KAAK,KAAK,gBAAgB,GAAG;GAC5C,MAAM,cAAc,KAAK,oBAAoB;GAC7C,IAAI,aAAa;IACf,MAAM,QAAQ,mBAAmB,aAAa,OAAO,kBAAkB,QAAQ;IAC/E,OAAO,KAAK,gBAAgB,IAAI,iBAAiB,MAAM,KAAK,SAAS,MAAM;GAC7E;EACF;EAEA,IAAI,KAAK,QAAQ,GAAG;GAClB,IAAI,KAAK,iBAAiB,GAAG,QAAQ,MAAM,eACzC,OAAO;GAET,OAAO,KAAK,cAAc,EAAE,KAAK,MAAM,mBAAmB,GAAG,OAAO,kBAAkB,QAAQ,CAAC,EAAE,KAAK,KAAK;EAC7G;EAEA,IAAI,KAAK,eAAe,GACtB,OAAO,KAAK,qBAAqB,EAAE,KAAK,MAAM,mBAAmB,GAAG,OAAO,kBAAkB,QAAQ,CAAC,EAAE,KAAK,KAAK;EAGpH,MAAM,OAAO,KAAK,QAAQ,KAAA,GAAW,MAAM,gBAAgB,YAAY;EACvE,IAAI,KAAK,SAAS,SAAS,GACzB,OAAO;EAET,OAAO;CACT,UAAU;EACR,SAAS,OAAO,IAAI;CACtB;AACF;AAIA,SAAgB,kBAAkB,YAAoB,SAA0B;CAC9E,IAAI,WAAW,UAAU,GACvB,IAAI;EACF,IAAI,aAAa,YAAY,OAAO,MAAM,SAAS,OAAO;CAC5D,QAAQ,CAER;CAEF,UAAU,QAAQ,UAAU,GAAG,EAAE,WAAW,KAAK,CAAC;CAClD,MAAM,UAAU,GAAG,WAAW,OAAO,QAAQ,IAAI,GAAG,KAAK,IAAI;CAC7D,cAAc,SAAS,SAAS,OAAO;CACvC,WAAW,SAAS,UAAU;CAC9B,OAAO;AACT;AAEA,SAAgB,kBAAkB,KAAiC;CAMjE,OAAO,CAJL,KAAK,KAAK,OAAO,eAAe,GAChC,KAAK,KAAK,OAAO,gBAAgB,CAGnB,EAAE,KAAK,UAAU;AACnC;AAEA,SAAgB,aAAa,KAAqB;CAChD,OAAO,KAAK,KAAK,OAAO,WAAW,OAAO;AAC5C;AAEA,SAAgB,eAAe,KAAqB;CAClD,OAAO,KAAK,KAAK,OAAO,WAAW,cAAc;AACnD;AAEA,SAAgB,iBAAiB,KAAiC;CAChE,MAAM,YAAY,KAAK,KAAK,eAAe;CAC3C,OAAO,WAAW,SAAS,IAAI,YAAY,KAAA;AAC7C;AAIA,eAAsB,kBAAkB,KAAiE;CACvG,MAAM,WAAW,aAAa,GAAG;CACjC,MAAM,SAAS,KAAK,KAAK,KAAK;CAC9B,MAAM,aAAa,eAAe,GAAG;CACrC,MAAM,iBAAiB,kBAAkB,GAAG;CAI5C,MAAM,EAAE,SAAS,YAAY,OAAO,MAAM,cAHrB,iBAAiB,GAG6B,CAAC;CAGpE,MAAM,QAAQ,2BAA2B,SAAS,YAAY,IAAI,QAAQ,QAAQ;CAGlF,MAAM,aAAa,iBACf,sBAAsB,SAAS,YAAY,IAAI,cAAc,IAC7D;CAGJ,MAAM,OAAO,iBAAiB,SAAS,YAAY,MAAM;CAgBzD,kBAAkB,YAPF,qBAAqB;EACnC;EACA;EACA,gBATqB,sBAAsB,SAAS,YAAY,IAAI,MASvD;EACb;EACA,YARiB,kBAAkB,SAAS,YAAY,IAAI,MAQnD;CACX,CACoC,CAAC;CAErC,OAAO;EAAE;EAAY,WAAW,MAAM;CAAO;AAC/C"}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { RouterContext } from "stratal/router";
|
|
2
|
+
import { MessageKeys } from "stratal/i18n";
|
|
3
|
+
import { Page, Page as InertiaPage, SharedPageProps } from "@inertiajs/core";
|
|
4
|
+
import { ContentfulStatusCode } from "hono/utils/http-status";
|
|
5
|
+
|
|
6
|
+
//#region src/types.d.ts
|
|
7
|
+
interface InertiaPageRegistry {}
|
|
8
|
+
interface InertiaI18nConfig {}
|
|
9
|
+
type InertiaTranslationKeys = InertiaI18nConfig extends {
|
|
10
|
+
translationKeys: infer T extends string;
|
|
11
|
+
} ? T : MessageKeys;
|
|
12
|
+
type InertiaSharedProps = SharedPageProps;
|
|
13
|
+
type InertiaPageComponent = keyof InertiaPageRegistry extends never ? string : Extract<keyof InertiaPageRegistry, string>;
|
|
14
|
+
type AllowInertiaWrappers<T> = { [K in keyof T]: T[K] | InertiaDeferredProp | InertiaMergeProp | InertiaOptionalProp | InertiaOnceProp | InertiaAlwaysProp };
|
|
15
|
+
type ResolvedInertiaPageProps<C extends InertiaPageComponent> = C extends keyof InertiaPageRegistry ? AllowInertiaWrappers<InertiaPageRegistry[C]> : Record<string, unknown>;
|
|
16
|
+
type InertiaFullPageProps<C extends InertiaPageComponent> = (C extends keyof InertiaPageRegistry ? InertiaPageRegistry[C] : Record<string, unknown>) & InertiaSharedProps;
|
|
17
|
+
interface InertiaRenderOptions {
|
|
18
|
+
encryptHistory?: boolean;
|
|
19
|
+
clearHistory?: boolean;
|
|
20
|
+
preserveFragment?: boolean;
|
|
21
|
+
/**
|
|
22
|
+
* HTTP status code to use for the rendered response. Defaults to `200`.
|
|
23
|
+
* Useful for rendering Inertia error pages (e.g. `Errors/404` with status 404).
|
|
24
|
+
*/
|
|
25
|
+
status?: ContentfulStatusCode;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Streaming SSR render result. `head` carries the document `<head>` tags Inertia
|
|
29
|
+
* collected during the synchronous shell render (known once the shell is ready);
|
|
30
|
+
* `stream` is React's `renderToReadableStream` output, piped into the `#app` body.
|
|
31
|
+
*/
|
|
32
|
+
interface InertiaSsrResult {
|
|
33
|
+
head: string[];
|
|
34
|
+
stream: ReadableStream<Uint8Array>;
|
|
35
|
+
}
|
|
36
|
+
interface InertiaSsrBundle {
|
|
37
|
+
render(page: Page): Promise<InertiaSsrResult>;
|
|
38
|
+
}
|
|
39
|
+
type SharedDataResolver = (ctx: RouterContext) => any;
|
|
40
|
+
interface ViteManifestEntry {
|
|
41
|
+
file: string;
|
|
42
|
+
css?: string[];
|
|
43
|
+
isEntry?: boolean;
|
|
44
|
+
imports?: string[];
|
|
45
|
+
dynamicImports?: string[];
|
|
46
|
+
src?: string;
|
|
47
|
+
}
|
|
48
|
+
type ViteManifest = Record<string, ViteManifestEntry>;
|
|
49
|
+
declare const INERTIA_PROP_OPTIONAL: unique symbol;
|
|
50
|
+
declare const INERTIA_PROP_DEFERRED: unique symbol;
|
|
51
|
+
declare const INERTIA_PROP_MERGE: unique symbol;
|
|
52
|
+
declare const INERTIA_PROP_ONCE: unique symbol;
|
|
53
|
+
declare const INERTIA_PROP_ALWAYS: unique symbol;
|
|
54
|
+
interface InertiaOptionalProp<T = unknown> {
|
|
55
|
+
[INERTIA_PROP_OPTIONAL]: true;
|
|
56
|
+
callback: () => T;
|
|
57
|
+
}
|
|
58
|
+
interface InertiaDeferredProp<T = unknown> {
|
|
59
|
+
[INERTIA_PROP_DEFERRED]: true;
|
|
60
|
+
callback: () => T;
|
|
61
|
+
group: string;
|
|
62
|
+
}
|
|
63
|
+
type InertiaMergeStrategy = 'append' | 'prepend' | 'deep';
|
|
64
|
+
interface InertiaMergeProp<T = unknown> {
|
|
65
|
+
[INERTIA_PROP_MERGE]: true;
|
|
66
|
+
callback: () => T;
|
|
67
|
+
strategy: InertiaMergeStrategy;
|
|
68
|
+
matchOn?: string;
|
|
69
|
+
}
|
|
70
|
+
interface InertiaOnceProp<T = unknown> {
|
|
71
|
+
[INERTIA_PROP_ONCE]: true;
|
|
72
|
+
callback: () => T;
|
|
73
|
+
expiresAt?: number | null;
|
|
74
|
+
key?: string;
|
|
75
|
+
}
|
|
76
|
+
interface InertiaAlwaysProp<T = unknown> {
|
|
77
|
+
[INERTIA_PROP_ALWAYS]: true;
|
|
78
|
+
callback: () => T;
|
|
79
|
+
}
|
|
80
|
+
//#endregion
|
|
81
|
+
export { ResolvedInertiaPageProps as _, InertiaMergeProp as a, ViteManifestEntry as b, InertiaOptionalProp as c, InertiaPageRegistry as d, InertiaRenderOptions as f, InertiaTranslationKeys as g, InertiaSsrResult as h, InertiaI18nConfig as i, InertiaPage as l, InertiaSsrBundle as m, InertiaDeferredProp as n, InertiaMergeStrategy as o, InertiaSharedProps as p, InertiaFullPageProps as r, InertiaOnceProp as s, InertiaAlwaysProp as t, InertiaPageComponent as u, SharedDataResolver as v, ViteManifest as y };
|
|
82
|
+
//# sourceMappingURL=types-BhgXhWx6.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types-BhgXhWx6.d.mts","names":[],"sources":["../src/types.ts"],"mappings":";;;;;;UAMiB,mBAAA;AAAA,UAEA,iBAAA;AAAA,KAEL,sBAAA,GACV,iBAAA;EAA4B,eAAA;AAAA,IAA4C,CAAA,GAAI,WAAW;AAAA,KAI7E,kBAAA,GAAqB,eAAe;AAAA,KAEpC,oBAAA,SAA6B,mBAAA,0BAErC,OAAA,OAAc,mBAAA;AAAA,KAGb,oBAAA,oBACS,CAAA,GAAI,CAAA,CAAE,CAAA,IAAK,mBAAA,GAAsB,gBAAA,GAAmB,mBAAA,GAAsB,eAAA,GAAkB,iBAAA;AAAA,KAK9F,wBAAA,WAAmC,oBAAA,IAC7C,CAAA,eAAgB,mBAAA,GAAsB,oBAAA,CAAqB,mBAAA,CAAoB,CAAA,KAAM,MAAA;AAAA,KAG3E,oBAAA,WAA+B,oBAAA,KACxC,CAAA,eAAgB,mBAAA,GAAsB,mBAAA,CAAoB,CAAA,IAAK,MAAA,qBAA2B,kBAAA;AAAA,UAK5E,oBAAA;EACf,cAAA;EACA,YAAA;EACA,gBAAA;EA9BwE;;;AAAe;EAmCvF,MAAA,GAAS,oBAAoB;AAAA;;;AA/BiB;AAEhD;;UAqCiB,gBAAA;EACf,IAAA;EACA,MAAA,EAAQ,cAAc,CAAC,UAAA;AAAA;AAAA,UAGR,gBAAA;EACf,MAAA,CAAO,IAAA,EAAM,IAAA,GAAO,OAAA,CAAQ,gBAAA;AAAA;AAAA,KAIlB,kBAAA,IAAsB,GAAkB,EAAb,aAAa;AAAA,UAEnC,iBAAA;EACf,IAAA;EACA,GAAA;EACA,OAAA;EACA,OAAA;EACA,cAAA;EACA,GAAA;AAAA;AAAA,KAGU,YAAA,GAAe,MAAM,SAAS,iBAAA;AAAA,cAE7B,qBAAA;AAAA,cACA,qBAAA;AAAA,cACA,kBAAA;AAAA,cACA,iBAAA;AAAA,cACA,mBAAA;AAAA,UAEI,mBAAA;EAAA,CACd,qBAAA;EACD,QAAA,QAAgB,CAAC;AAAA;AAAA,UAGF,mBAAA;EAAA,CACd,qBAAA;EACD,QAAA,QAAgB,CAAC;EACjB,KAAA;AAAA;AAAA,KAGU,oBAAA;AAAA,UAEK,gBAAA;EAAA,CACd,kBAAA;EACD,QAAA,QAAgB,CAAA;EAChB,QAAA,EAAU,oBAAA;EACV,OAAA;AAAA;AAAA,UAGe,eAAA;EAAA,CACd,iBAAA;EACD,QAAA,QAAgB,CAAC;EACjB,SAAA;EACA,GAAA;AAAA;AAAA,UAGe,iBAAA;EAAA,CACd,mBAAA;EACD,QAAA,QAAgB,CAAC;AAAA"}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
//#region src/seo/types.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Public SEO data model for `@stratal/inertia`.
|
|
4
|
+
*
|
|
5
|
+
* These types are framework-free (no DI, worker, or React imports) so the same
|
|
6
|
+
* definitions can be shared by the server-side {@link import('../services/seo.service').SeoService}
|
|
7
|
+
* and the client-side head-sync runtime.
|
|
8
|
+
*/
|
|
9
|
+
/** Open Graph metadata. Maps to `<meta property="og:*">` tags. */
|
|
10
|
+
interface SeoOpenGraph {
|
|
11
|
+
title?: string;
|
|
12
|
+
description?: string;
|
|
13
|
+
image?: string;
|
|
14
|
+
type?: string;
|
|
15
|
+
url?: string;
|
|
16
|
+
siteName?: string;
|
|
17
|
+
}
|
|
18
|
+
/** Twitter card metadata. Maps to `<meta name="twitter:*">` tags. */
|
|
19
|
+
interface SeoTwitter {
|
|
20
|
+
card?: 'summary' | 'summary_large_image' | 'app' | 'player';
|
|
21
|
+
title?: string;
|
|
22
|
+
description?: string;
|
|
23
|
+
image?: string;
|
|
24
|
+
site?: string;
|
|
25
|
+
creator?: string;
|
|
26
|
+
}
|
|
27
|
+
/** A custom `<meta>` tag. Provide either `name` or `property` plus `content`. */
|
|
28
|
+
interface SeoMetaTag {
|
|
29
|
+
name?: string;
|
|
30
|
+
property?: string;
|
|
31
|
+
content: string;
|
|
32
|
+
}
|
|
33
|
+
/** A custom `<link>` tag. `rel` and `href` are required; extra attributes are passed through. */
|
|
34
|
+
type SeoLinkTag = {
|
|
35
|
+
rel: string;
|
|
36
|
+
href: string;
|
|
37
|
+
} & Record<string, string>;
|
|
38
|
+
/**
|
|
39
|
+
* SEO metadata for a page. Set per-request via `ctx.seo()` and/or as app-wide
|
|
40
|
+
* defaults through {@link import('../inertia.options').InertiaSeoOptions}.
|
|
41
|
+
*/
|
|
42
|
+
interface SeoData {
|
|
43
|
+
/** Document title (`<title>`). Subject to the configured `titleTemplate`. */
|
|
44
|
+
title?: string;
|
|
45
|
+
/** Meta description (`<meta name="description">`). */
|
|
46
|
+
description?: string;
|
|
47
|
+
/** Canonical URL (`<link rel="canonical">`). */
|
|
48
|
+
canonical?: string;
|
|
49
|
+
/** Robots directive (`<meta name="robots">`), e.g. `"noindex, nofollow"`. */
|
|
50
|
+
robots?: string;
|
|
51
|
+
/** Keywords (`<meta name="keywords">`). Arrays are joined with `", "`. */
|
|
52
|
+
keywords?: string | string[];
|
|
53
|
+
/** Author (`<meta name="author">`). */
|
|
54
|
+
author?: string;
|
|
55
|
+
/** Open Graph metadata. */
|
|
56
|
+
openGraph?: SeoOpenGraph;
|
|
57
|
+
/** Twitter card metadata. */
|
|
58
|
+
twitter?: SeoTwitter;
|
|
59
|
+
/** Arbitrary additional `<meta>` tags. */
|
|
60
|
+
meta?: SeoMetaTag[];
|
|
61
|
+
/** Arbitrary additional `<link>` tags. */
|
|
62
|
+
link?: SeoLinkTag[];
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* A renderable description of a single head tag, produced by
|
|
66
|
+
* {@link import('./build-seo-tags').buildSeoTags}. The server turns these into
|
|
67
|
+
* HTML strings; the client turns them into DOM nodes — one source of truth.
|
|
68
|
+
*/
|
|
69
|
+
interface SeoTagDescriptor {
|
|
70
|
+
tag: 'title' | 'meta' | 'link';
|
|
71
|
+
attrs: Record<string, string>;
|
|
72
|
+
content?: string;
|
|
73
|
+
}
|
|
74
|
+
//#endregion
|
|
75
|
+
export { SeoTagDescriptor as a, SeoOpenGraph as i, SeoLinkTag as n, SeoTwitter as o, SeoMetaTag as r, SeoData as t };
|
|
76
|
+
//# sourceMappingURL=types-DzE1pdZs.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types-DzE1pdZs.d.mts","names":[],"sources":["../src/seo/types.ts"],"mappings":";;AASA;;;;;;;UAAiB,YAAA;EACf,KAAA;EACA,WAAA;EACA,KAAA;EACA,IAAA;EACA,GAAA;EACA,QAAA;AAAA;;UAIe,UAAA;EACf,IAAA;EACA,KAAA;EACA,WAAA;EACA,KAAA;EACA,IAAA;EACA,OAAA;AAAA;AAIF;AAAA,UAAiB,UAAA;EACf,IAAA;EACA,QAAA;EACA,OAAA;AAAA;;KAIU,UAAA;EAAe,GAAA;EAAa,IAAA;AAAA,IAAiB,MAAM;;;;;UAM9C,OAAA;EAN8C;EAQ7D,KAAA;EAFe;EAIf,WAAA;;EAEA,SAAA;EAUU;EARV,MAAA;EAYO;EAVP,QAAA;EAUiB;EARjB,MAAA;EARA;EAUA,SAAA,GAAY,YAAA;EANZ;EAQA,OAAA,GAAU,UAAA;EAJV;EAMA,IAAA,GAAO,UAAA;EAJK;EAMZ,IAAA,GAAO,UAAA;AAAA;;;;;;UAQQ,gBAAA;EACf,GAAA;EACA,KAAA,EAAO,MAAM;EACb,OAAA;AAAA"}
|
package/dist/vite.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"vite.d.mts","names":[],"sources":["../src/vite/inertia-dev-css-plugin.ts","../src/vite/inertia-types-plugin.ts","../src/vite.ts"],"mappings":";;;UAMiB,oBAAA;EACf,
|
|
1
|
+
{"version":3,"file":"vite.d.mts","names":[],"sources":["../src/vite/inertia-dev-css-plugin.ts","../src/vite/inertia-types-plugin.ts","../src/vite.ts"],"mappings":";;;UAMiB,oBAAA;EACf,OAAO;AAAA;AAAA,iBAqEO,oBAAA,CAAqB,OAAA,EAAS,oBAAA,GAAuB,MAAM;;;iBCpE3D,mBAAA,IAAuB,MAAM;;;UCA5B,2BAAA;;EAEf,OAAA;EFHO;AAqET;;;;;;;EEzDE,SAAA;EFyDyE;;;;ACpE3E;;;;AAA6C;ECqB3C,kBAAA;AAAA;AAAA,iBAGc,cAAA,CAAe,OAAA,GAAU,2BAAA,GAA8B,MAAM"}
|
package/dist/vite.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { n as runTypeGeneration, t as findPagesDir } from "./type-generator-
|
|
1
|
+
import { n as runTypeGeneration, t as findPagesDir } from "./type-generator-DFpha_Fp.mjs";
|
|
2
2
|
import { existsSync, readFileSync } from "node:fs";
|
|
3
3
|
import { isAbsolute, join, relative } from "node:path";
|
|
4
4
|
import { URL as URL$1 } from "node:url";
|
|
@@ -6,7 +6,7 @@ import { Worker } from "node:worker_threads";
|
|
|
6
6
|
//#region src/vite/inertia-dev-css-plugin.ts
|
|
7
7
|
const CSS_LANGS_RE = /\.(css|scss|sass|less|styl|stylus|pcss|postcss)(?:$|\?)/;
|
|
8
8
|
const VIRTUAL_MODULE_ID = "virtual:inertia-ssr.css";
|
|
9
|
-
const RESOLVED_VIRTUAL_MODULE_ID = "\
|
|
9
|
+
const RESOLVED_VIRTUAL_MODULE_ID = "\0virtual:inertia-ssr.css";
|
|
10
10
|
function collectStyleUrls(server, entries) {
|
|
11
11
|
const urls = [];
|
|
12
12
|
const visited = /* @__PURE__ */ new Set();
|
|
@@ -255,6 +255,9 @@ function stratalInertia(options) {
|
|
|
255
255
|
stratalInertiaTypes(),
|
|
256
256
|
{
|
|
257
257
|
name: "stratal:optimize-deps-fix",
|
|
258
|
+
config(config) {
|
|
259
|
+
config.publicDir ??= "src/inertia/public";
|
|
260
|
+
},
|
|
258
261
|
configEnvironment(name, env) {
|
|
259
262
|
const existing = env.optimizeDeps?.exclude ?? [];
|
|
260
263
|
const existingInclude = env.optimizeDeps?.include ?? [];
|
|
@@ -284,9 +287,26 @@ function stratalInertia(options) {
|
|
|
284
287
|
if (name === "client") env.build.emptyOutDir = false;
|
|
285
288
|
}
|
|
286
289
|
},
|
|
290
|
+
injectSeoRuntime({ entries }),
|
|
287
291
|
injectClientManifestIntoWorker({ clientManifestPath })
|
|
288
292
|
];
|
|
289
293
|
}
|
|
294
|
+
function injectSeoRuntime(args) {
|
|
295
|
+
const runtime = "@stratal/inertia/seo-runtime";
|
|
296
|
+
const targets = args.entries.map((entry) => entry.replace(/^\//, ""));
|
|
297
|
+
return {
|
|
298
|
+
name: "stratal:inertia-inject-seo-runtime",
|
|
299
|
+
transform(code, id) {
|
|
300
|
+
const file = id.split("?")[0];
|
|
301
|
+
if (!targets.some((target) => file.endsWith(target))) return null;
|
|
302
|
+
if (code.includes(runtime)) return null;
|
|
303
|
+
return {
|
|
304
|
+
code: `import '${runtime}';\n${code}`,
|
|
305
|
+
map: null
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
};
|
|
309
|
+
}
|
|
290
310
|
function injectClientManifestIntoWorker(args) {
|
|
291
311
|
let projectRoot = process.cwd();
|
|
292
312
|
return {
|