@stratal/inertia 0.0.18 → 0.0.19
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +472 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +1158 -0
- package/dist/index.mjs.map +1 -0
- package/dist/react.d.mts +83 -0
- package/dist/react.d.mts.map +1 -0
- package/dist/react.mjs +158 -0
- package/dist/react.mjs.map +1 -0
- package/dist/testing.d.mts +36 -0
- package/dist/testing.d.mts.map +1 -0
- package/dist/testing.mjs +78 -0
- package/dist/testing.mjs.map +1 -0
- package/dist/type-generator-C5JljyzK.mjs +391 -0
- package/dist/type-generator-C5JljyzK.mjs.map +1 -0
- package/dist/vite.d.mts +21 -0
- package/dist/vite.d.mts.map +1 -0
- package/dist/vite.mjs +152 -0
- package/dist/vite.mjs.map +1 -0
- package/package.json +20 -20
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { dirname, join } from "node:path";
|
|
3
|
+
//#region src/generator/type-generator.ts
|
|
4
|
+
async function loadTsMorph() {
|
|
5
|
+
return import("ts-morph");
|
|
6
|
+
}
|
|
7
|
+
async function createProject(tsConfigPath) {
|
|
8
|
+
const { Project, SyntaxKind, ts } = await loadTsMorph();
|
|
9
|
+
return {
|
|
10
|
+
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
|
+
SyntaxKind,
|
|
22
|
+
ts
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
const WRAPPER_TYPE_NAMES = [
|
|
26
|
+
"InertiaDeferredProp",
|
|
27
|
+
"InertiaMergeProp",
|
|
28
|
+
"InertiaOptionalProp",
|
|
29
|
+
"InertiaOnceProp",
|
|
30
|
+
"InertiaAlwaysProp"
|
|
31
|
+
];
|
|
32
|
+
function extractControllerPageTypes(project, SK, tsObj, srcDir, pagesDir) {
|
|
33
|
+
project.addSourceFilesAtPaths(join(srcDir, "**/*.ts"));
|
|
34
|
+
const pages = /* @__PURE__ */ new Map();
|
|
35
|
+
for (const sourceFile of project.getSourceFiles()) {
|
|
36
|
+
const filePath = sourceFile.getFilePath();
|
|
37
|
+
if (filePath.includes(pagesDir.replace(/\\/g, "/"))) continue;
|
|
38
|
+
if (filePath.includes("__tests__") || filePath.includes(".spec.") || filePath.includes(".test.")) continue;
|
|
39
|
+
const callExpressions = sourceFile.getDescendantsOfKind(SK.CallExpression);
|
|
40
|
+
for (const call of callExpressions) {
|
|
41
|
+
const expr = call.getExpression();
|
|
42
|
+
if (!expr.isKind(SK.PropertyAccessExpression)) continue;
|
|
43
|
+
if (expr.getName() !== "inertia") continue;
|
|
44
|
+
const args = call.getArguments();
|
|
45
|
+
if (args.length === 0) continue;
|
|
46
|
+
const firstArg = args[0];
|
|
47
|
+
if (!firstArg.isKind(SK.StringLiteral)) continue;
|
|
48
|
+
const componentName = firstArg.getLiteralValue();
|
|
49
|
+
if (!pages.has(componentName)) pages.set(componentName, []);
|
|
50
|
+
if (args.length < 2) {
|
|
51
|
+
pages.get(componentName).push("Record<string, never>");
|
|
52
|
+
continue;
|
|
53
|
+
}
|
|
54
|
+
const propsArg = args[1];
|
|
55
|
+
const propsType = propsArg.getType();
|
|
56
|
+
if (propsType.isObject() && !propsType.isArray()) {
|
|
57
|
+
const properties = propsType.getProperties();
|
|
58
|
+
if (properties.length === 0) {
|
|
59
|
+
pages.get(componentName).push("Record<string, never>");
|
|
60
|
+
continue;
|
|
61
|
+
}
|
|
62
|
+
const members = properties.map((prop) => {
|
|
63
|
+
const location = prop.getDeclarations()[0] ?? prop.getValueDeclaration() ?? propsArg;
|
|
64
|
+
const isOptional = prop.isOptional();
|
|
65
|
+
const unwrapped = unwrapWrapperType(prop.getTypeAtLocation(location), tsObj, propsArg);
|
|
66
|
+
return `${prop.getName()}${isOptional ? "?" : ""}: ${unwrapped}`;
|
|
67
|
+
});
|
|
68
|
+
pages.get(componentName).push(`{ ${members.join("; ")} }`);
|
|
69
|
+
} else pages.get(componentName).push(typeToString(propsType, tsObj, propsArg));
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
return Array.from(pages.entries()).map(([componentName, typeVariants]) => {
|
|
73
|
+
const unique = [...new Set(typeVariants)];
|
|
74
|
+
return {
|
|
75
|
+
componentName,
|
|
76
|
+
propsType: unique.length === 1 ? unique[0] : unique.join(" | ")
|
|
77
|
+
};
|
|
78
|
+
}).sort((a, b) => a.componentName.localeCompare(b.componentName));
|
|
79
|
+
}
|
|
80
|
+
function unwrapWrapperType(type, tsObj, fallbackLocation) {
|
|
81
|
+
if (type.isUnion()) {
|
|
82
|
+
const unwrapped = type.getUnionTypes().filter((t) => {
|
|
83
|
+
const text = t.getText(void 0, tsObj.TypeFormatFlags.NoTruncation);
|
|
84
|
+
return !WRAPPER_TYPE_NAMES.some((name) => text.includes(name));
|
|
85
|
+
}).map((t) => typeToString(t, tsObj, fallbackLocation));
|
|
86
|
+
if (unwrapped.length > 0) return unwrapped.join(" | ");
|
|
87
|
+
}
|
|
88
|
+
const text = type.getText(void 0, tsObj.TypeFormatFlags.NoTruncation);
|
|
89
|
+
for (const wrapperName of WRAPPER_TYPE_NAMES) if (text.includes(wrapperName)) {
|
|
90
|
+
const callbackProp = type.getProperty("callback");
|
|
91
|
+
if (callbackProp) {
|
|
92
|
+
const location = callbackProp.getDeclarations()[0] ?? callbackProp.getValueDeclaration() ?? fallbackLocation;
|
|
93
|
+
if (!location) return "unknown";
|
|
94
|
+
const callSignatures = callbackProp.getTypeAtLocation(location).getCallSignatures();
|
|
95
|
+
if (callSignatures.length > 0) return unwrapPromise(callSignatures[0].getReturnType(), tsObj, fallbackLocation);
|
|
96
|
+
}
|
|
97
|
+
return "unknown";
|
|
98
|
+
}
|
|
99
|
+
return widenLiteralType(type, tsObj, fallbackLocation);
|
|
100
|
+
}
|
|
101
|
+
function unwrapPromise(type, tsObj, fallbackLocation) {
|
|
102
|
+
if (type.getText(void 0, tsObj.TypeFormatFlags.NoTruncation).startsWith("Promise<")) {
|
|
103
|
+
const typeArgs = type.getTypeArguments();
|
|
104
|
+
if (typeArgs.length > 0) return stripReadonly(typeArgs[0], tsObj, fallbackLocation);
|
|
105
|
+
}
|
|
106
|
+
return stripReadonly(type, tsObj, fallbackLocation);
|
|
107
|
+
}
|
|
108
|
+
function stripReadonly(type, tsObj, fallbackLocation) {
|
|
109
|
+
if (type.isTuple()) return `[${type.getTupleElements().map((e) => typeToString(e, tsObj, fallbackLocation)).join(", ")}]`;
|
|
110
|
+
if (type.getText(void 0, tsObj.TypeFormatFlags.NoTruncation).startsWith("readonly ") && type.isArray()) {
|
|
111
|
+
const elementType = type.getArrayElementType();
|
|
112
|
+
if (elementType) return `Array<${typeToString(elementType, tsObj, fallbackLocation)}>`;
|
|
113
|
+
}
|
|
114
|
+
return typeToString(type, tsObj, fallbackLocation);
|
|
115
|
+
}
|
|
116
|
+
function extractShareCallTypes(project, SK, tsObj, srcDir) {
|
|
117
|
+
const shareTypes = /* @__PURE__ */ new Map();
|
|
118
|
+
for (const sourceFile of project.getSourceFiles()) {
|
|
119
|
+
const filePath = sourceFile.getFilePath();
|
|
120
|
+
if (!filePath.startsWith(srcDir.replace(/\\/g, "/"))) continue;
|
|
121
|
+
if (filePath.includes("__tests__") || filePath.includes(".spec.") || filePath.includes(".test.")) continue;
|
|
122
|
+
const callExpressions = sourceFile.getDescendantsOfKind(SK.CallExpression);
|
|
123
|
+
for (const call of callExpressions) {
|
|
124
|
+
const expr = call.getExpression();
|
|
125
|
+
if (!expr.isKind(SK.PropertyAccessExpression)) continue;
|
|
126
|
+
if (expr.getName() !== "share") continue;
|
|
127
|
+
if (!expr.getExpression().getText().includes("inertia")) continue;
|
|
128
|
+
const args = call.getArguments();
|
|
129
|
+
if (args.length < 2) continue;
|
|
130
|
+
const keyArg = args[0];
|
|
131
|
+
if (!keyArg.isKind(SK.StringLiteral)) continue;
|
|
132
|
+
const key = keyArg.getLiteralValue();
|
|
133
|
+
if (shareTypes.has(key)) continue;
|
|
134
|
+
const valueType = widenLiteralType(args[1].getType(), tsObj);
|
|
135
|
+
shareTypes.set(key, valueType);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return shareTypes;
|
|
139
|
+
}
|
|
140
|
+
function detectI18nConfig(project, SK, moduleFilePath) {
|
|
141
|
+
const sourceFile = project.getSourceFile(moduleFilePath);
|
|
142
|
+
if (!sourceFile) return false;
|
|
143
|
+
const callExpressions = sourceFile.getDescendantsOfKind(SK.CallExpression);
|
|
144
|
+
for (const call of callExpressions) {
|
|
145
|
+
const expr = call.getExpression();
|
|
146
|
+
if (!expr.isKind(SK.PropertyAccessExpression)) continue;
|
|
147
|
+
const propName = expr.getName();
|
|
148
|
+
if (propName !== "forRoot" && propName !== "forRootAsync") continue;
|
|
149
|
+
const objExpr = expr.getExpression();
|
|
150
|
+
if (!objExpr.isKind(SK.Identifier) || objExpr.getText() !== "InertiaModule") continue;
|
|
151
|
+
const args = call.getArguments();
|
|
152
|
+
if (args.length === 0) continue;
|
|
153
|
+
const optionsArg = args[0];
|
|
154
|
+
if (!optionsArg.isKind(SK.ObjectLiteralExpression)) continue;
|
|
155
|
+
return !!optionsArg.getProperty("i18n");
|
|
156
|
+
}
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
function extractFlashTypes(project, SK, tsObj, srcDir) {
|
|
160
|
+
const flashMembers = /* @__PURE__ */ new Map();
|
|
161
|
+
for (const sourceFile of project.getSourceFiles()) {
|
|
162
|
+
const filePath = sourceFile.getFilePath();
|
|
163
|
+
if (!filePath.startsWith(srcDir.replace(/\\/g, "/"))) continue;
|
|
164
|
+
if (filePath.includes("__tests__") || filePath.includes(".spec.") || filePath.includes(".test.")) continue;
|
|
165
|
+
const callExpressions = sourceFile.getDescendantsOfKind(SK.CallExpression);
|
|
166
|
+
for (const call of callExpressions) {
|
|
167
|
+
const expr = call.getExpression();
|
|
168
|
+
if (!expr.isKind(SK.PropertyAccessExpression)) continue;
|
|
169
|
+
if (expr.getName() !== "flash") continue;
|
|
170
|
+
const args = call.getArguments();
|
|
171
|
+
if (args.length < 2) continue;
|
|
172
|
+
const keyArg = args[0];
|
|
173
|
+
if (!keyArg.isKind(SK.StringLiteral)) continue;
|
|
174
|
+
const key = keyArg.getLiteralValue();
|
|
175
|
+
if (flashMembers.has(key)) continue;
|
|
176
|
+
const valueType = widenLiteralType(args[1].getType(), tsObj);
|
|
177
|
+
flashMembers.set(key, valueType);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
if (flashMembers.size === 0) return null;
|
|
181
|
+
return { members: Array.from(flashMembers.entries()).map(([name, type]) => ({
|
|
182
|
+
name,
|
|
183
|
+
type
|
|
184
|
+
})) };
|
|
185
|
+
}
|
|
186
|
+
function extractSharedDataType(project, SK, tsObj, moduleFilePath) {
|
|
187
|
+
const callExpressions = (project.getSourceFile(moduleFilePath) ?? project.addSourceFileAtPath(moduleFilePath)).getDescendantsOfKind(SK.CallExpression);
|
|
188
|
+
for (const call of callExpressions) {
|
|
189
|
+
const expr = call.getExpression();
|
|
190
|
+
if (!expr.isKind(SK.PropertyAccessExpression)) continue;
|
|
191
|
+
const propName = expr.getName();
|
|
192
|
+
if (propName !== "forRoot" && propName !== "forRootAsync") continue;
|
|
193
|
+
const objExpr = expr.getExpression();
|
|
194
|
+
if (!objExpr.isKind(SK.Identifier) || objExpr.getText() !== "InertiaModule") continue;
|
|
195
|
+
const args = call.getArguments();
|
|
196
|
+
if (args.length === 0) continue;
|
|
197
|
+
const optionsArg = args[0];
|
|
198
|
+
if (!optionsArg.isKind(SK.ObjectLiteralExpression)) continue;
|
|
199
|
+
const sharedDataProp = optionsArg.getProperty("sharedData");
|
|
200
|
+
if (!sharedDataProp) continue;
|
|
201
|
+
if (!sharedDataProp.isKind(SK.PropertyAssignment)) continue;
|
|
202
|
+
const initializer = sharedDataProp.getInitializer();
|
|
203
|
+
if (!initializer?.isKind(SK.ObjectLiteralExpression)) continue;
|
|
204
|
+
const members = [];
|
|
205
|
+
for (const prop of initializer.getProperties()) {
|
|
206
|
+
if (!prop.isKind(SK.PropertyAssignment)) continue;
|
|
207
|
+
const name = prop.getName();
|
|
208
|
+
const value = prop.getInitializer();
|
|
209
|
+
if (!value) continue;
|
|
210
|
+
let valueType;
|
|
211
|
+
if (value.isKind(SK.ArrowFunction) || value.isKind(SK.FunctionExpression)) valueType = typeToString(value.getReturnType(), tsObj);
|
|
212
|
+
else valueType = typeToString(value.getType(), tsObj);
|
|
213
|
+
members.push({
|
|
214
|
+
name,
|
|
215
|
+
type: valueType,
|
|
216
|
+
optional: false
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
if (members.length > 0) return { members };
|
|
220
|
+
}
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
223
|
+
function componentNameToPropsTypeName(componentName, segmentCount = 2) {
|
|
224
|
+
return componentName.split("/").slice(-segmentCount).map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join("") + "PageProps";
|
|
225
|
+
}
|
|
226
|
+
function resolvePagePropsTypeNames(pages) {
|
|
227
|
+
const result = /* @__PURE__ */ new Map();
|
|
228
|
+
const nameToComponents = /* @__PURE__ */ new Map();
|
|
229
|
+
for (const page of pages) {
|
|
230
|
+
const typeName = componentNameToPropsTypeName(page.componentName);
|
|
231
|
+
const existing = nameToComponents.get(typeName) ?? [];
|
|
232
|
+
existing.push(page.componentName);
|
|
233
|
+
nameToComponents.set(typeName, existing);
|
|
234
|
+
}
|
|
235
|
+
for (const [typeName, components] of nameToComponents) if (components.length === 1) result.set(components[0], typeName);
|
|
236
|
+
else for (const componentName of components) {
|
|
237
|
+
const fullSegments = componentName.split("/").length;
|
|
238
|
+
result.set(componentName, componentNameToPropsTypeName(componentName, fullSegments));
|
|
239
|
+
}
|
|
240
|
+
return result;
|
|
241
|
+
}
|
|
242
|
+
function generateInertiaTypes(input) {
|
|
243
|
+
const { pages, sharedData, shareCallTypes, hasI18n, flashTypes } = input;
|
|
244
|
+
const typeNames = resolvePagePropsTypeNames(pages);
|
|
245
|
+
const lines = ["// Auto-generated by @stratal/inertia. Do not edit."];
|
|
246
|
+
if (pages.length > 0) {
|
|
247
|
+
lines.push("declare global {");
|
|
248
|
+
for (const page of pages) {
|
|
249
|
+
const typeName = typeNames.get(page.componentName);
|
|
250
|
+
lines.push(` type ${typeName} = ${page.propsType}`);
|
|
251
|
+
}
|
|
252
|
+
lines.push("}");
|
|
253
|
+
lines.push("");
|
|
254
|
+
}
|
|
255
|
+
lines.push("declare module '@stratal/inertia' {");
|
|
256
|
+
lines.push(" interface InertiaPageRegistry {");
|
|
257
|
+
for (const page of pages) {
|
|
258
|
+
const typeName = typeNames.get(page.componentName);
|
|
259
|
+
lines.push(` '${page.componentName}': ${typeName}`);
|
|
260
|
+
}
|
|
261
|
+
lines.push(" }");
|
|
262
|
+
lines.push("}");
|
|
263
|
+
const configMembers = [];
|
|
264
|
+
if (flashTypes && flashTypes.members.length > 0) {
|
|
265
|
+
const flashProps = flashTypes.members.map((m) => `${m.name}?: ${m.type}`).join("; ");
|
|
266
|
+
configMembers.push(` flashDataType: { ${flashProps} }`);
|
|
267
|
+
}
|
|
268
|
+
const sharedMembers = [];
|
|
269
|
+
if (sharedData) for (const member of sharedData.members) sharedMembers.push(` ${member.name}${member.optional ? "?" : ""}: ${member.type}`);
|
|
270
|
+
if (hasI18n) {
|
|
271
|
+
sharedMembers.push(" locale: string");
|
|
272
|
+
sharedMembers.push(" translations: Record<string, string>");
|
|
273
|
+
}
|
|
274
|
+
for (const [key, type] of shareCallTypes) {
|
|
275
|
+
if (sharedData?.members.some((m) => m.name === key)) continue;
|
|
276
|
+
sharedMembers.push(` ${key}?: ${type}`);
|
|
277
|
+
}
|
|
278
|
+
if (sharedMembers.length > 0) configMembers.push(` sharedPageProps: {\n${sharedMembers.join("\n")}\n }`);
|
|
279
|
+
if (configMembers.length > 0) {
|
|
280
|
+
lines.push("");
|
|
281
|
+
lines.push("declare module '@inertiajs/core' {");
|
|
282
|
+
lines.push(" export interface InertiaConfig {");
|
|
283
|
+
for (const member of configMembers) lines.push(member);
|
|
284
|
+
lines.push(" }");
|
|
285
|
+
lines.push("}");
|
|
286
|
+
}
|
|
287
|
+
lines.push("", "export {}", "");
|
|
288
|
+
return lines.join("\n");
|
|
289
|
+
}
|
|
290
|
+
function widenLiteralType(type, tsObj, fallbackLocation) {
|
|
291
|
+
if (type.isStringLiteral()) return "string";
|
|
292
|
+
if (type.isNumberLiteral()) return "number";
|
|
293
|
+
if (type.isBooleanLiteral()) return "boolean";
|
|
294
|
+
return typeToString(type, tsObj, fallbackLocation);
|
|
295
|
+
}
|
|
296
|
+
function typeToString(type, tsObj, fallbackLocation) {
|
|
297
|
+
if (type.isObject() || type.isUnion() || type.isIntersection()) return expandTypeToInline(type, tsObj, fallbackLocation);
|
|
298
|
+
const text = type.getText(void 0, tsObj.TypeFormatFlags.NoTruncation | tsObj.TypeFormatFlags.UseFullyQualifiedType);
|
|
299
|
+
if (text.includes("import(")) return expandTypeToInline(type, tsObj, fallbackLocation);
|
|
300
|
+
return text;
|
|
301
|
+
}
|
|
302
|
+
function expandPropertyType(type, tsObj, fallbackLocation, visiting, isOptional) {
|
|
303
|
+
if (isOptional && type.isUnion()) {
|
|
304
|
+
const parts = type.getUnionTypes().filter((t) => !t.isUndefined());
|
|
305
|
+
if (parts.length === 0) return "undefined";
|
|
306
|
+
if (parts.length === 1) return expandTypeToInline(parts[0], tsObj, fallbackLocation, visiting);
|
|
307
|
+
return parts.map((t) => expandTypeToInline(t, tsObj, fallbackLocation, visiting)).join(" | ");
|
|
308
|
+
}
|
|
309
|
+
return expandTypeToInline(type, tsObj, fallbackLocation, visiting);
|
|
310
|
+
}
|
|
311
|
+
function expandTypeToInline(type, tsObj, fallbackLocation, visiting = /* @__PURE__ */ new Set()) {
|
|
312
|
+
if (visiting.has(type)) return "unknown";
|
|
313
|
+
if (type.isBoolean()) return "boolean";
|
|
314
|
+
visiting.add(type);
|
|
315
|
+
try {
|
|
316
|
+
if (type.isObject() && !type.isArray() && !type.isReadonlyArray()) {
|
|
317
|
+
const symbolName = type.getSymbol()?.getName();
|
|
318
|
+
const text = type.getText(void 0, tsObj.TypeFormatFlags.NoTruncation | tsObj.TypeFormatFlags.UseFullyQualifiedType);
|
|
319
|
+
if (symbolName && !symbolName.startsWith("__") && symbolName !== "Object" && !text.includes("import(")) return text;
|
|
320
|
+
const properties = type.getProperties();
|
|
321
|
+
if (properties.length === 0) {
|
|
322
|
+
const stringIndexType = type.getStringIndexType();
|
|
323
|
+
if (stringIndexType) return `Record<string, ${expandTypeToInline(stringIndexType, tsObj, fallbackLocation, visiting)}>`;
|
|
324
|
+
return "{}";
|
|
325
|
+
}
|
|
326
|
+
return `{ ${properties.map((prop) => {
|
|
327
|
+
const location = prop.getDeclarations()[0] ?? prop.getValueDeclaration() ?? fallbackLocation;
|
|
328
|
+
const isOptional = prop.isOptional();
|
|
329
|
+
if (!location) return `${prop.getName()}${isOptional ? "?" : ""}: unknown`;
|
|
330
|
+
const propTypeStr = expandPropertyType(prop.getTypeAtLocation(location), tsObj, fallbackLocation, visiting, isOptional);
|
|
331
|
+
return `${prop.getName()}${isOptional ? "?" : ""}: ${propTypeStr}`;
|
|
332
|
+
}).join("; ")} }`;
|
|
333
|
+
}
|
|
334
|
+
if (type.isArray() || type.isReadonlyArray()) {
|
|
335
|
+
const elementType = type.getArrayElementType();
|
|
336
|
+
if (elementType) {
|
|
337
|
+
const inner = expandTypeToInline(elementType, tsObj, fallbackLocation, visiting);
|
|
338
|
+
return type.isReadonlyArray() ? `ReadonlyArray<${inner}>` : `Array<${inner}>`;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
if (type.isUnion()) return type.getUnionTypes().map((t) => expandTypeToInline(t, tsObj, fallbackLocation, visiting)).join(" | ");
|
|
342
|
+
if (type.isIntersection()) return type.getIntersectionTypes().map((t) => expandTypeToInline(t, tsObj, fallbackLocation, visiting)).join(" & ");
|
|
343
|
+
const text = type.getText(void 0, tsObj.TypeFormatFlags.NoTruncation);
|
|
344
|
+
if (text.includes("import(")) return "unknown";
|
|
345
|
+
return text;
|
|
346
|
+
} finally {
|
|
347
|
+
visiting.delete(type);
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
function writeInertiaTypes(outputPath, content) {
|
|
351
|
+
mkdirSync(dirname(outputPath), { recursive: true });
|
|
352
|
+
writeFileSync(outputPath, content, "utf-8");
|
|
353
|
+
}
|
|
354
|
+
function findAppModulePath(cwd) {
|
|
355
|
+
return [join(cwd, "src", "app.module.ts"), join(cwd, "src", "app.module.tsx")].find(existsSync);
|
|
356
|
+
}
|
|
357
|
+
function findPagesDir(cwd) {
|
|
358
|
+
return join(cwd, "src", "inertia", "pages");
|
|
359
|
+
}
|
|
360
|
+
function findOutputPath(cwd) {
|
|
361
|
+
return join(cwd, "src", "inertia", "inertia.d.ts");
|
|
362
|
+
}
|
|
363
|
+
function findTsConfigPath(cwd) {
|
|
364
|
+
const candidate = join(cwd, "tsconfig.json");
|
|
365
|
+
return existsSync(candidate) ? candidate : void 0;
|
|
366
|
+
}
|
|
367
|
+
async function runTypeGeneration(cwd) {
|
|
368
|
+
const pagesDir = findPagesDir(cwd);
|
|
369
|
+
const srcDir = join(cwd, "src");
|
|
370
|
+
const outputPath = findOutputPath(cwd);
|
|
371
|
+
const moduleFilePath = findAppModulePath(cwd);
|
|
372
|
+
const { project, SyntaxKind, ts } = await createProject(findTsConfigPath(cwd));
|
|
373
|
+
const pages = extractControllerPageTypes(project, SyntaxKind, ts, srcDir, pagesDir);
|
|
374
|
+
const sharedData = moduleFilePath ? extractSharedDataType(project, SyntaxKind, ts, moduleFilePath) : null;
|
|
375
|
+
const hasI18n = moduleFilePath ? detectI18nConfig(project, SyntaxKind, moduleFilePath) : false;
|
|
376
|
+
writeInertiaTypes(outputPath, generateInertiaTypes({
|
|
377
|
+
pages,
|
|
378
|
+
sharedData,
|
|
379
|
+
shareCallTypes: extractShareCallTypes(project, SyntaxKind, ts, srcDir),
|
|
380
|
+
hasI18n,
|
|
381
|
+
flashTypes: extractFlashTypes(project, SyntaxKind, ts, srcDir)
|
|
382
|
+
}));
|
|
383
|
+
return {
|
|
384
|
+
outputPath,
|
|
385
|
+
pageCount: pages.length
|
|
386
|
+
};
|
|
387
|
+
}
|
|
388
|
+
//#endregion
|
|
389
|
+
export { runTypeGeneration as n, findPagesDir as t };
|
|
390
|
+
|
|
391
|
+
//# sourceMappingURL=type-generator-C5JljyzK.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type-generator-C5JljyzK.mjs","names":[],"sources":["../src/generator/type-generator.ts"],"sourcesContent":["import { existsSync, mkdirSync, 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 const text = type.getText(undefined, tsObj.TypeFormatFlags.NoTruncation)\n if (text.startsWith('Promise<')) {\n const typeArgs = type.getTypeArguments()\n if (typeArgs.length > 0) {\n return stripReadonly(typeArgs[0], tsObj, fallbackLocation)\n }\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\nexport function detectI18nConfig(\n project: Project,\n SK: TsMorphModule['SyntaxKind'],\n moduleFilePath: string,\n): boolean {\n const sourceFile = project.getSourceFile(moduleFilePath)\n if (!sourceFile) return false\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 optionsArg = args[0]\n if (!optionsArg.isKind(SK.ObjectLiteralExpression)) continue\n\n return !!optionsArg.getProperty('i18n')\n }\n\n return false\n}\n\n// --- Extract ctx.flash() call types ---\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 const keyArg = args[0]\n if (!keyArg.isKind(SK.StringLiteral)) continue\n const key = keyArg.getLiteralValue()\n\n if (flashMembers.has(key)) continue\n\n const valueType = widenLiteralType(args[1].getType(), tsObj)\n flashMembers.set(key, valueType)\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 optionsArg = args[0]\n if (!optionsArg.isKind(SK.ObjectLiteralExpression)) continue\n\n const sharedDataProp = optionsArg.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 hasI18n: boolean\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((s) => s.charAt(0).toUpperCase() + s.slice(1)).join('') + 'PageProps'\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, hasI18n, 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 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 (hasI18n) {\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 // 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 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): 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\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\n const hasI18n = moduleFilePath\n ? detectI18nConfig(project, SyntaxKind, moduleFilePath)\n : false\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 hasI18n,\n flashTypes,\n })\n writeInertiaTypes(outputPath, content)\n\n return { outputPath, pageCount: pages.length }\n}\n"],"mappings":"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"}
|
package/dist/vite.d.mts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
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
|
+
//#region src/vite.d.ts
|
|
14
|
+
interface StratalInertiaPluginOptions {
|
|
15
|
+
/** Client entry path(s) for CSS collection (default: ['/src/inertia/app.tsx']) */
|
|
16
|
+
entries?: string[];
|
|
17
|
+
}
|
|
18
|
+
declare function stratalInertia(options?: StratalInertiaPluginOptions): Plugin[];
|
|
19
|
+
//#endregion
|
|
20
|
+
export { StratalInertiaPluginOptions, stratalInertia, stratalInertiaDevCss, stratalInertiaTypes };
|
|
21
|
+
//# sourceMappingURL=vite.d.mts.map
|
|
@@ -0,0 +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,OAAA;AAAA;AAAA,iBAqEc,oBAAA,CAAqB,OAAA,EAAS,oBAAA,GAAuB,MAAA;;;iBCrErD,mBAAA,CAAA,GAAuB,MAAA;;;UCDtB,2BAAA;;EAEf,OAAA;AAAA;AAAA,iBAGc,cAAA,CAAe,OAAA,GAAU,2BAAA,GAA8B,MAAA"}
|
package/dist/vite.mjs
ADDED
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import { n as runTypeGeneration, t as findPagesDir } from "./type-generator-C5JljyzK.mjs";
|
|
2
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
3
|
+
import { join, relative } from "node:path";
|
|
4
|
+
//#region src/vite/inertia-dev-css-plugin.ts
|
|
5
|
+
const CSS_LANGS_RE = /\.(css|scss|sass|less|styl|stylus|pcss|postcss)(?:$|\?)/;
|
|
6
|
+
const VIRTUAL_MODULE_ID = "virtual:inertia-ssr.css";
|
|
7
|
+
const RESOLVED_VIRTUAL_MODULE_ID = "\0" + VIRTUAL_MODULE_ID;
|
|
8
|
+
function collectStyleUrls(server, entries) {
|
|
9
|
+
const urls = [];
|
|
10
|
+
const visited = /* @__PURE__ */ new Set();
|
|
11
|
+
function traverse(mod) {
|
|
12
|
+
if (visited.has(mod.url)) return;
|
|
13
|
+
visited.add(mod.url);
|
|
14
|
+
if (CSS_LANGS_RE.test(mod.url)) urls.push(mod.url);
|
|
15
|
+
for (const imported of mod.importedModules) traverse(imported);
|
|
16
|
+
}
|
|
17
|
+
for (const entry of entries) {
|
|
18
|
+
const mod = server.moduleGraph.getModulesByFile(entry.startsWith("/") ? entry.slice(1) : entry);
|
|
19
|
+
if (mod) for (const m of mod) traverse(m);
|
|
20
|
+
const urlMod = server.moduleGraph.urlToModuleMap.get(entry);
|
|
21
|
+
if (urlMod) traverse(urlMod);
|
|
22
|
+
}
|
|
23
|
+
return urls;
|
|
24
|
+
}
|
|
25
|
+
async function collectStyle(server, entries) {
|
|
26
|
+
for (const entry of entries) try {
|
|
27
|
+
await server.transformRequest(entry);
|
|
28
|
+
} catch {}
|
|
29
|
+
const urls = collectStyleUrls(server, entries);
|
|
30
|
+
const styles = [];
|
|
31
|
+
for (const url of urls) try {
|
|
32
|
+
const separator = url.includes("?") ? "&" : "?";
|
|
33
|
+
const result = await server.transformRequest(url + separator + "direct");
|
|
34
|
+
if (result?.code) styles.push(result.code);
|
|
35
|
+
} catch {}
|
|
36
|
+
return styles.join("\n");
|
|
37
|
+
}
|
|
38
|
+
function stratalInertiaDevCss(options) {
|
|
39
|
+
let server;
|
|
40
|
+
return {
|
|
41
|
+
name: "stratal:inertia-dev-css",
|
|
42
|
+
apply: "serve",
|
|
43
|
+
resolveId(id) {
|
|
44
|
+
if (id === VIRTUAL_MODULE_ID) return RESOLVED_VIRTUAL_MODULE_ID;
|
|
45
|
+
},
|
|
46
|
+
async load(id) {
|
|
47
|
+
if (id === RESOLVED_VIRTUAL_MODULE_ID) return await collectStyle(server, options.entries);
|
|
48
|
+
},
|
|
49
|
+
configureServer(devServer) {
|
|
50
|
+
server = devServer;
|
|
51
|
+
server.middlewares.use((req, res, next) => {
|
|
52
|
+
if (new URL(req.url ?? "", "http://localhost").pathname !== "/__inertia/ssr-css") {
|
|
53
|
+
next();
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
collectStyle(server, options.entries).then((css) => {
|
|
57
|
+
res.setHeader("Content-Type", "text/css");
|
|
58
|
+
res.setHeader("Cache-Control", "no-store");
|
|
59
|
+
res.end(css);
|
|
60
|
+
}).catch(() => {
|
|
61
|
+
res.statusCode = 500;
|
|
62
|
+
res.end("");
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
//#endregion
|
|
69
|
+
//#region src/vite/inertia-types-plugin.ts
|
|
70
|
+
const INERTIA_CALL_PATTERN = /ctx\.inertia\(|\.share\(|ctx\.flash\(|ctx\.defer\(|ctx\.optional\(|ctx\.merge\(|ctx\.once\(|ctx\.always\(/;
|
|
71
|
+
function stratalInertiaTypes() {
|
|
72
|
+
let cwd;
|
|
73
|
+
let pagesDir;
|
|
74
|
+
let srcDir;
|
|
75
|
+
return {
|
|
76
|
+
name: "stratal:inertia-types",
|
|
77
|
+
configResolved(config) {
|
|
78
|
+
cwd = config.root;
|
|
79
|
+
pagesDir = findPagesDir(cwd) + "/";
|
|
80
|
+
srcDir = join(cwd, "src") + "/";
|
|
81
|
+
},
|
|
82
|
+
async buildStart() {
|
|
83
|
+
if (!existsSync(pagesDir)) return;
|
|
84
|
+
try {
|
|
85
|
+
await runTypeGeneration(cwd);
|
|
86
|
+
} catch (error) {
|
|
87
|
+
console.warn("[stratal:inertia-types] Type generation failed during build:", error);
|
|
88
|
+
}
|
|
89
|
+
},
|
|
90
|
+
async handleHotUpdate({ file }) {
|
|
91
|
+
if (!/\.(tsx|ts)$/.test(file)) return;
|
|
92
|
+
if (!!relative(srcDir, file).startsWith("..")) return;
|
|
93
|
+
if (!!relative(pagesDir, file).startsWith("..")) try {
|
|
94
|
+
const content = readFileSync(file, "utf-8");
|
|
95
|
+
if (!INERTIA_CALL_PATTERN.test(content)) return;
|
|
96
|
+
} catch {
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
try {
|
|
100
|
+
await runTypeGeneration(cwd);
|
|
101
|
+
} catch (error) {
|
|
102
|
+
console.warn("[stratal:inertia-types] Type generation failed during HMR:", error);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
//#endregion
|
|
108
|
+
//#region src/vite.ts
|
|
109
|
+
function stratalInertia(options) {
|
|
110
|
+
const entries = options?.entries ?? ["/src/inertia/app.tsx"];
|
|
111
|
+
const optimizeDepsExclude = [
|
|
112
|
+
"@cloudflare/vite-plugin",
|
|
113
|
+
"wrangler",
|
|
114
|
+
"blake3-wasm",
|
|
115
|
+
"@stratal/inertia"
|
|
116
|
+
];
|
|
117
|
+
const optimizeDepsInclude = [
|
|
118
|
+
"buffer",
|
|
119
|
+
"buffer/",
|
|
120
|
+
"base64-js",
|
|
121
|
+
"ieee754"
|
|
122
|
+
];
|
|
123
|
+
const devOnlyExternals = ["ts-morph"];
|
|
124
|
+
return [
|
|
125
|
+
stratalInertiaDevCss({ entries }),
|
|
126
|
+
stratalInertiaTypes(),
|
|
127
|
+
{
|
|
128
|
+
name: "stratal:optimize-deps-fix",
|
|
129
|
+
configEnvironment(_name, env) {
|
|
130
|
+
const existing = env.optimizeDeps?.exclude ?? [];
|
|
131
|
+
const existingInclude = env.optimizeDeps?.include ?? [];
|
|
132
|
+
env.optimizeDeps = {
|
|
133
|
+
...env.optimizeDeps,
|
|
134
|
+
exclude: [...existing, ...optimizeDepsExclude],
|
|
135
|
+
include: [...existingInclude, ...optimizeDepsInclude]
|
|
136
|
+
};
|
|
137
|
+
const existingExternal = env.build?.rolldownOptions?.external ?? [];
|
|
138
|
+
env.build = {
|
|
139
|
+
...env.build,
|
|
140
|
+
rolldownOptions: {
|
|
141
|
+
...env.build?.rolldownOptions,
|
|
142
|
+
external: [...existingExternal, ...devOnlyExternals]
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
];
|
|
148
|
+
}
|
|
149
|
+
//#endregion
|
|
150
|
+
export { stratalInertia, stratalInertiaDevCss, stratalInertiaTypes };
|
|
151
|
+
|
|
152
|
+
//# sourceMappingURL=vite.mjs.map
|