@stratal/inertia 0.0.20 → 0.0.22
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/decorate-CzXVx7ZH.mjs +9 -0
- package/dist/generator/type-generator.worker.d.mts +1 -0
- package/dist/generator/type-generator.worker.mjs +25 -0
- package/dist/generator/type-generator.worker.mjs.map +1 -0
- package/dist/index.d.mts +68 -105
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +46 -383
- package/dist/index.mjs.map +1 -1
- package/dist/quarry.d.mts +44 -0
- package/dist/quarry.d.mts.map +1 -0
- package/dist/quarry.mjs +392 -0
- package/dist/quarry.mjs.map +1 -0
- package/dist/react.d.mts +1 -31
- package/dist/react.d.mts.map +1 -1
- package/dist/react.mjs +10 -42
- package/dist/react.mjs.map +1 -1
- package/dist/testing.mjs.map +1 -1
- package/dist/{type-generator-C5JljyzK.mjs → type-generator-bfo14BJI.mjs} +75 -14
- package/dist/type-generator-bfo14BJI.mjs.map +1 -0
- package/dist/vite.d.mts +19 -0
- package/dist/vite.d.mts.map +1 -1
- package/dist/vite.mjs +177 -14
- package/dist/vite.mjs.map +1 -1
- package/package.json +19 -21
- package/dist/type-generator-C5JljyzK.mjs.map +0 -1
package/dist/testing.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing.mjs","names":[],"sources":["../src/augment/test-response.ts","../src/testing.ts"],"sourcesContent":["import type { Page } from '@inertiajs/core'\nimport { getValueAtPath, hasValueAtPath, TestResponse } from '@stratal/testing'\nimport { expect } from 'vitest'\n\ndeclare module '@stratal/testing' {\n interface TestResponse {\n /** Assert the response is an Inertia response. Optionally run a callback with the page object for custom assertions. */\n assertInertia(callback?: (page: Page) => void): Promise<this>\n /** Assert the Inertia page component matches the expected name. */\n assertInertiaComponent(component: string): Promise<this>\n /** Assert the Inertia page prop at the given dot-path equals the expected value. */\n assertInertiaProp(path: string, expected: unknown): Promise<this>\n /** Assert the Inertia page prop at the given dot-path exists. */\n assertInertiaPropExists(path: string): Promise<this>\n /** Assert the Inertia page prop at the given dot-path does not exist. */\n assertInertiaPropMissing(path: string): Promise<this>\n /** Assert the Inertia page URL matches the expected value. */\n assertInertiaUrl(url: string): Promise<this>\n /** Assert the Inertia page version matches the expected value. */\n assertInertiaVersion(version: string | null): Promise<this>\n /** Assert the Inertia page flash data contains the given key with the expected value. */\n assertInertiaFlash(key: string, value: unknown): Promise<this>\n /** Assert a prop is listed as deferred in the given group. */\n assertInertiaDeferredProp(prop: string, group: string): Promise<this>\n /** Assert a prop is listed as a merge prop. */\n assertInertiaMergeProp(prop: string): Promise<this>\n /** Assert a prop is listed as a shared prop. */\n assertInertiaSharedProp(prop: string): Promise<this>\n /** Assert the response is a successful precognition response (204 with precognition headers). */\n assertSuccessfulPrecognition(): this\n /** Assert the response is a precognition validation error (422 with precognition headers). Optionally assert specific errors. */\n assertPrecognitionValidationErrors(errors?: Record<string, string>): Promise<this>\n }\n}\n\nexport function augmentTestResponse(): void {\n TestResponse.macro('assertInertia', async function (this: TestResponse, callback?: (page: Page) => void) {\n this.assertHeader('x-inertia', 'true')\n this.assertOk()\n\n if (callback) {\n const page = await this.json<Page>()\n callback(page)\n }\n\n return this\n })\n\n TestResponse.macro('assertInertiaComponent', async function (this: TestResponse, component: string) {\n const page = await this.json<Page>()\n\n expect(\n page.component,\n `Expected Inertia component \"${component}\", got \"${page.component}\"`,\n ).toBe(component)\n\n return this\n })\n\n TestResponse.macro('assertInertiaProp', async function (this: TestResponse, path: string, expected: unknown) {\n const page = await this.json<Page>()\n const actual = getValueAtPath(page.props, path)\n\n expect(\n actual,\n `Expected Inertia prop \"${path}\" to be ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`,\n ).toStrictEqual(expected)\n\n return this\n })\n\n TestResponse.macro('assertInertiaPropExists', async function (this: TestResponse, path: string) {\n const page = await this.json<Page>()\n const exists = hasValueAtPath(page.props, path)\n\n expect(\n exists,\n `Expected Inertia prop \"${path}\" to exist`,\n ).toBe(true)\n\n return this\n })\n\n TestResponse.macro('assertInertiaPropMissing', async function (this: TestResponse, path: string) {\n const page = await this.json<Page>()\n const exists = hasValueAtPath(page.props, path)\n\n expect(\n exists,\n `Expected Inertia prop \"${path}\" to not exist`,\n ).toBe(false)\n\n return this\n })\n\n TestResponse.macro('assertInertiaUrl', async function (this: TestResponse, url: string) {\n const page = await this.json<Page>()\n\n expect(\n page.url,\n `Expected Inertia URL \"${url}\", got \"${page.url}\"`,\n ).toBe(url)\n\n return this\n })\n\n TestResponse.macro('assertInertiaVersion', async function (this: TestResponse, version: string | null) {\n const page = await this.json<Page>()\n\n expect(\n page.version,\n `Expected Inertia version \"${version}\", got \"${page.version}\"`,\n ).toBe(version)\n\n return this\n })\n\n TestResponse.macro('assertInertiaFlash', async function (this: TestResponse, key: string, value: unknown) {\n const page = await this.json<Page>()\n const actual = page.flash?.[key]\n\n expect(\n actual,\n `Expected Inertia flash \"${key}\" to be ${JSON.stringify(value)}, got ${JSON.stringify(actual)}`,\n ).toStrictEqual(value)\n\n return this\n })\n\n TestResponse.macro('assertInertiaDeferredProp', async function (this: TestResponse, prop: string, group: string) {\n const page = await this.json<Page>()\n\n expect(\n page.deferredProps?.[group],\n `Expected Inertia deferred group \"${group}\" to contain \"${prop}\"`,\n ).toContain(prop)\n\n return this\n })\n\n TestResponse.macro('assertInertiaMergeProp', async function (this: TestResponse, prop: string) {\n const page = await this.json<Page>()\n\n expect(\n page.mergeProps,\n `Expected Inertia mergeProps to contain \"${prop}\"`,\n ).toContain(prop)\n\n return this\n })\n\n TestResponse.macro('assertInertiaSharedProp', async function (this: TestResponse, prop: string) {\n const page = await this.json<Page>()\n\n expect(\n page.sharedProps,\n `Expected Inertia sharedProps to contain \"${prop}\"`,\n ).toContain(prop)\n\n return this\n })\n\n TestResponse.macro('assertSuccessfulPrecognition', function (this: TestResponse) {\n this.assertNoContent()\n this.assertHeader('Precognition', 'true')\n this.assertHeader('Precognition-Success', 'true')\n\n return this\n })\n\n TestResponse.macro('assertPrecognitionValidationErrors', async function (this: TestResponse, errors?: Record<string, string>) {\n this.assertUnprocessable()\n this.assertHeader('Precognition', 'true')\n\n if (errors) {\n const body = await this.json<{ errors: Record<string, string> }>()\n\n expect(\n body.errors,\n `Expected precognition errors to match ${JSON.stringify(errors)}, got ${JSON.stringify(body.errors)}`,\n ).toStrictEqual(errors)\n }\n\n return this\n })\n}\n","import { augmentTestResponse } from './augment/test-response'\n\n// Augmentation (side-effect import: augments TestResponse types)\nimport './augment/test-response'\n\n// Patch TestResponse.prototype with Inertia assertion methods\naugmentTestResponse()\n\n// Re-export useful types for test authors\nexport type { Page as InertiaPage } from '@inertiajs/core'\n"],"mappings":";;;AAmCA,SAAgB,sBAA4B;
|
|
1
|
+
{"version":3,"file":"testing.mjs","names":[],"sources":["../src/augment/test-response.ts","../src/testing.ts"],"sourcesContent":["import type { Page } from '@inertiajs/core'\nimport { getValueAtPath, hasValueAtPath, TestResponse } from '@stratal/testing'\nimport { expect } from 'vitest'\n\ndeclare module '@stratal/testing' {\n interface TestResponse {\n /** Assert the response is an Inertia response. Optionally run a callback with the page object for custom assertions. */\n assertInertia(callback?: (page: Page) => void): Promise<this>\n /** Assert the Inertia page component matches the expected name. */\n assertInertiaComponent(component: string): Promise<this>\n /** Assert the Inertia page prop at the given dot-path equals the expected value. */\n assertInertiaProp(path: string, expected: unknown): Promise<this>\n /** Assert the Inertia page prop at the given dot-path exists. */\n assertInertiaPropExists(path: string): Promise<this>\n /** Assert the Inertia page prop at the given dot-path does not exist. */\n assertInertiaPropMissing(path: string): Promise<this>\n /** Assert the Inertia page URL matches the expected value. */\n assertInertiaUrl(url: string): Promise<this>\n /** Assert the Inertia page version matches the expected value. */\n assertInertiaVersion(version: string | null): Promise<this>\n /** Assert the Inertia page flash data contains the given key with the expected value. */\n assertInertiaFlash(key: string, value: unknown): Promise<this>\n /** Assert a prop is listed as deferred in the given group. */\n assertInertiaDeferredProp(prop: string, group: string): Promise<this>\n /** Assert a prop is listed as a merge prop. */\n assertInertiaMergeProp(prop: string): Promise<this>\n /** Assert a prop is listed as a shared prop. */\n assertInertiaSharedProp(prop: string): Promise<this>\n /** Assert the response is a successful precognition response (204 with precognition headers). */\n assertSuccessfulPrecognition(): this\n /** Assert the response is a precognition validation error (422 with precognition headers). Optionally assert specific errors. */\n assertPrecognitionValidationErrors(errors?: Record<string, string>): Promise<this>\n }\n}\n\nexport function augmentTestResponse(): void {\n TestResponse.macro('assertInertia', async function (this: TestResponse, callback?: (page: Page) => void) {\n this.assertHeader('x-inertia', 'true')\n this.assertOk()\n\n if (callback) {\n const page = await this.json<Page>()\n callback(page)\n }\n\n return this\n })\n\n TestResponse.macro('assertInertiaComponent', async function (this: TestResponse, component: string) {\n const page = await this.json<Page>()\n\n expect(\n page.component,\n `Expected Inertia component \"${component}\", got \"${page.component}\"`,\n ).toBe(component)\n\n return this\n })\n\n TestResponse.macro('assertInertiaProp', async function (this: TestResponse, path: string, expected: unknown) {\n const page = await this.json<Page>()\n const actual = getValueAtPath(page.props, path)\n\n expect(\n actual,\n `Expected Inertia prop \"${path}\" to be ${JSON.stringify(expected)}, got ${JSON.stringify(actual)}`,\n ).toStrictEqual(expected)\n\n return this\n })\n\n TestResponse.macro('assertInertiaPropExists', async function (this: TestResponse, path: string) {\n const page = await this.json<Page>()\n const exists = hasValueAtPath(page.props, path)\n\n expect(\n exists,\n `Expected Inertia prop \"${path}\" to exist`,\n ).toBe(true)\n\n return this\n })\n\n TestResponse.macro('assertInertiaPropMissing', async function (this: TestResponse, path: string) {\n const page = await this.json<Page>()\n const exists = hasValueAtPath(page.props, path)\n\n expect(\n exists,\n `Expected Inertia prop \"${path}\" to not exist`,\n ).toBe(false)\n\n return this\n })\n\n TestResponse.macro('assertInertiaUrl', async function (this: TestResponse, url: string) {\n const page = await this.json<Page>()\n\n expect(\n page.url,\n `Expected Inertia URL \"${url}\", got \"${page.url}\"`,\n ).toBe(url)\n\n return this\n })\n\n TestResponse.macro('assertInertiaVersion', async function (this: TestResponse, version: string | null) {\n const page = await this.json<Page>()\n\n expect(\n page.version,\n `Expected Inertia version \"${version}\", got \"${page.version}\"`,\n ).toBe(version)\n\n return this\n })\n\n TestResponse.macro('assertInertiaFlash', async function (this: TestResponse, key: string, value: unknown) {\n const page = await this.json<Page>()\n const actual = page.flash?.[key]\n\n expect(\n actual,\n `Expected Inertia flash \"${key}\" to be ${JSON.stringify(value)}, got ${JSON.stringify(actual)}`,\n ).toStrictEqual(value)\n\n return this\n })\n\n TestResponse.macro('assertInertiaDeferredProp', async function (this: TestResponse, prop: string, group: string) {\n const page = await this.json<Page>()\n\n expect(\n page.deferredProps?.[group],\n `Expected Inertia deferred group \"${group}\" to contain \"${prop}\"`,\n ).toContain(prop)\n\n return this\n })\n\n TestResponse.macro('assertInertiaMergeProp', async function (this: TestResponse, prop: string) {\n const page = await this.json<Page>()\n\n expect(\n page.mergeProps,\n `Expected Inertia mergeProps to contain \"${prop}\"`,\n ).toContain(prop)\n\n return this\n })\n\n TestResponse.macro('assertInertiaSharedProp', async function (this: TestResponse, prop: string) {\n const page = await this.json<Page>()\n\n expect(\n page.sharedProps,\n `Expected Inertia sharedProps to contain \"${prop}\"`,\n ).toContain(prop)\n\n return this\n })\n\n TestResponse.macro('assertSuccessfulPrecognition', function (this: TestResponse) {\n this.assertNoContent()\n this.assertHeader('Precognition', 'true')\n this.assertHeader('Precognition-Success', 'true')\n\n return this\n })\n\n TestResponse.macro('assertPrecognitionValidationErrors', async function (this: TestResponse, errors?: Record<string, string>) {\n this.assertUnprocessable()\n this.assertHeader('Precognition', 'true')\n\n if (errors) {\n const body = await this.json<{ errors: Record<string, string> }>()\n\n expect(\n body.errors,\n `Expected precognition errors to match ${JSON.stringify(errors)}, got ${JSON.stringify(body.errors)}`,\n ).toStrictEqual(errors)\n }\n\n return this\n })\n}\n","import { augmentTestResponse } from './augment/test-response'\n\n// Augmentation (side-effect import: augments TestResponse types)\nimport './augment/test-response'\n\n// Patch TestResponse.prototype with Inertia assertion methods\naugmentTestResponse()\n\n// Re-export useful types for test authors\nexport type { Page as InertiaPage } from '@inertiajs/core'\n"],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { dirname, join } from "node:path";
|
|
3
3
|
//#region src/generator/type-generator.ts
|
|
4
4
|
async function loadTsMorph() {
|
|
@@ -99,10 +99,8 @@ function unwrapWrapperType(type, tsObj, fallbackLocation) {
|
|
|
99
99
|
return widenLiteralType(type, tsObj, fallbackLocation);
|
|
100
100
|
}
|
|
101
101
|
function unwrapPromise(type, tsObj, fallbackLocation) {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
if (typeArgs.length > 0) return stripReadonly(typeArgs[0], tsObj, fallbackLocation);
|
|
105
|
-
}
|
|
102
|
+
const awaited = type.getAwaitedType?.();
|
|
103
|
+
if (awaited && awaited !== type) return stripReadonly(awaited, tsObj, fallbackLocation);
|
|
106
104
|
return stripReadonly(type, tsObj, fallbackLocation);
|
|
107
105
|
}
|
|
108
106
|
function stripReadonly(type, tsObj, fallbackLocation) {
|
|
@@ -137,6 +135,60 @@ function extractShareCallTypes(project, SK, tsObj, srcDir) {
|
|
|
137
135
|
}
|
|
138
136
|
return shareTypes;
|
|
139
137
|
}
|
|
138
|
+
/**
|
|
139
|
+
* Given the first argument of `Module.forRoot(...)` or `Module.forRootAsync(...)`,
|
|
140
|
+
* return the object literal where downstream options actually live.
|
|
141
|
+
*
|
|
142
|
+
* - For `forRoot({...})` the literal IS the first arg.
|
|
143
|
+
* - For `forRootAsync({ inject, useFactory: (...) => ({...}) })` we drill into
|
|
144
|
+
* the `useFactory`'s return value:
|
|
145
|
+
* `() => ({ … })` — ParenthesizedExpression → ObjectLiteral
|
|
146
|
+
* `() => ({ ... } as Foo)` — AsExpression → ObjectLiteral
|
|
147
|
+
* `() => { return { … } }` — Block → ReturnStatement → ObjectLiteral
|
|
148
|
+
*
|
|
149
|
+
* Returns `null` when nothing usable is found.
|
|
150
|
+
*/
|
|
151
|
+
function resolveModuleOptionsLiteral(optionsArg, SK) {
|
|
152
|
+
if (!optionsArg.isKind(SK.ObjectLiteralExpression)) return null;
|
|
153
|
+
const useFactoryProp = optionsArg.getProperty("useFactory");
|
|
154
|
+
if (useFactoryProp?.isKind(SK.PropertyAssignment)) {
|
|
155
|
+
const initializer = useFactoryProp.getInitializer();
|
|
156
|
+
if (initializer?.isKind(SK.ArrowFunction) || initializer?.isKind(SK.FunctionExpression)) {
|
|
157
|
+
const body = initializer.getBody();
|
|
158
|
+
if (body.isKind(SK.ParenthesizedExpression)) {
|
|
159
|
+
const inner = unwrapAs(body.getExpression(), SK);
|
|
160
|
+
if (inner?.isKind(SK.ObjectLiteralExpression)) return inner;
|
|
161
|
+
}
|
|
162
|
+
const unwrapped = unwrapAs(body, SK);
|
|
163
|
+
if (unwrapped?.isKind(SK.ObjectLiteralExpression)) return unwrapped;
|
|
164
|
+
if (body.isKind(SK.Block)) {
|
|
165
|
+
const returnStatements = body.getDescendantsOfKind(SK.ReturnStatement);
|
|
166
|
+
for (let i = returnStatements.length - 1; i >= 0; i--) {
|
|
167
|
+
const expr = returnStatements[i].getExpression();
|
|
168
|
+
if (!expr) continue;
|
|
169
|
+
if (expr.isKind(SK.ParenthesizedExpression)) {
|
|
170
|
+
const inner = unwrapAs(expr.getExpression(), SK);
|
|
171
|
+
if (inner?.isKind(SK.ObjectLiteralExpression)) return inner;
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
174
|
+
const direct = unwrapAs(expr, SK);
|
|
175
|
+
if (direct?.isKind(SK.ObjectLiteralExpression)) return direct;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
return optionsArg;
|
|
181
|
+
}
|
|
182
|
+
/**
|
|
183
|
+
* Strip a single `as Foo` cast if present, otherwise return the node as-is.
|
|
184
|
+
* `useFactory: (env) => ({ ... } as Options)` is common in TypeScript.
|
|
185
|
+
*/
|
|
186
|
+
function unwrapAs(node, SK) {
|
|
187
|
+
if (!node) return void 0;
|
|
188
|
+
if (node.isKind(SK.AsExpression) || node.isKind(SK.TypeAssertionExpression)) return node.getExpression();
|
|
189
|
+
if (node.isKind(SK.SatisfiesExpression)) return node.getExpression();
|
|
190
|
+
return node;
|
|
191
|
+
}
|
|
140
192
|
function detectI18nConfig(project, SK, moduleFilePath) {
|
|
141
193
|
const sourceFile = project.getSourceFile(moduleFilePath);
|
|
142
194
|
if (!sourceFile) return false;
|
|
@@ -150,9 +202,9 @@ function detectI18nConfig(project, SK, moduleFilePath) {
|
|
|
150
202
|
if (!objExpr.isKind(SK.Identifier) || objExpr.getText() !== "InertiaModule") continue;
|
|
151
203
|
const args = call.getArguments();
|
|
152
204
|
if (args.length === 0) continue;
|
|
153
|
-
const
|
|
154
|
-
if (!
|
|
155
|
-
|
|
205
|
+
const optionsLiteral = resolveModuleOptionsLiteral(args[0], SK);
|
|
206
|
+
if (!optionsLiteral) continue;
|
|
207
|
+
if (optionsLiteral.isKind(SK.ObjectLiteralExpression) && optionsLiteral.getProperty("i18n")) return true;
|
|
156
208
|
}
|
|
157
209
|
return false;
|
|
158
210
|
}
|
|
@@ -194,9 +246,9 @@ function extractSharedDataType(project, SK, tsObj, moduleFilePath) {
|
|
|
194
246
|
if (!objExpr.isKind(SK.Identifier) || objExpr.getText() !== "InertiaModule") continue;
|
|
195
247
|
const args = call.getArguments();
|
|
196
248
|
if (args.length === 0) continue;
|
|
197
|
-
const
|
|
198
|
-
if (!
|
|
199
|
-
const sharedDataProp =
|
|
249
|
+
const optionsLiteral = resolveModuleOptionsLiteral(args[0], SK);
|
|
250
|
+
if (!optionsLiteral || !optionsLiteral.isKind(SK.ObjectLiteralExpression)) continue;
|
|
251
|
+
const sharedDataProp = optionsLiteral.getProperty("sharedData");
|
|
200
252
|
if (!sharedDataProp) continue;
|
|
201
253
|
if (!sharedDataProp.isKind(SK.PropertyAssignment)) continue;
|
|
202
254
|
const initializer = sharedDataProp.getInitializer();
|
|
@@ -221,7 +273,10 @@ function extractSharedDataType(project, SK, tsObj, moduleFilePath) {
|
|
|
221
273
|
return null;
|
|
222
274
|
}
|
|
223
275
|
function componentNameToPropsTypeName(componentName, segmentCount = 2) {
|
|
224
|
-
return componentName.split("/").slice(-segmentCount).map(
|
|
276
|
+
return componentName.split("/").slice(-segmentCount).map(toPascalCase).join("") + "PageProps";
|
|
277
|
+
}
|
|
278
|
+
function toPascalCase(segment) {
|
|
279
|
+
return segment.split(/[-_\s]+/).filter((part) => part.length > 0).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join("");
|
|
225
280
|
}
|
|
226
281
|
function resolvePagePropsTypeNames(pages) {
|
|
227
282
|
const result = /* @__PURE__ */ new Map();
|
|
@@ -348,8 +403,14 @@ function expandTypeToInline(type, tsObj, fallbackLocation, visiting = /* @__PURE
|
|
|
348
403
|
}
|
|
349
404
|
}
|
|
350
405
|
function writeInertiaTypes(outputPath, content) {
|
|
406
|
+
if (existsSync(outputPath)) try {
|
|
407
|
+
if (readFileSync(outputPath, "utf-8") === content) return false;
|
|
408
|
+
} catch {}
|
|
351
409
|
mkdirSync(dirname(outputPath), { recursive: true });
|
|
352
|
-
|
|
410
|
+
const tmpPath = `${outputPath}.tmp-${process.pid}-${Date.now()}`;
|
|
411
|
+
writeFileSync(tmpPath, content, "utf-8");
|
|
412
|
+
renameSync(tmpPath, outputPath);
|
|
413
|
+
return true;
|
|
353
414
|
}
|
|
354
415
|
function findAppModulePath(cwd) {
|
|
355
416
|
return [join(cwd, "src", "app.module.ts"), join(cwd, "src", "app.module.tsx")].find(existsSync);
|
|
@@ -388,4 +449,4 @@ async function runTypeGeneration(cwd) {
|
|
|
388
449
|
//#endregion
|
|
389
450
|
export { runTypeGeneration as n, findPagesDir as t };
|
|
390
451
|
|
|
391
|
-
//# sourceMappingURL=type-generator-
|
|
452
|
+
//# sourceMappingURL=type-generator-bfo14BJI.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type-generator-bfo14BJI.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 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 optionsLiteral = resolveModuleOptionsLiteral(args[0], SK)\n if (!optionsLiteral) continue\n\n if (optionsLiteral.isKind(SK.ObjectLiteralExpression) && optionsLiteral.getProperty('i18n')) {\n return true\n }\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 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 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(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, 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): 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\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
CHANGED
|
@@ -14,6 +14,25 @@ declare function stratalInertiaTypes(): Plugin;
|
|
|
14
14
|
interface StratalInertiaPluginOptions {
|
|
15
15
|
/** Client entry path(s) for CSS collection (default: ['/src/inertia/app.tsx']) */
|
|
16
16
|
entries?: string[];
|
|
17
|
+
/**
|
|
18
|
+
* Whether to emit sourcemaps in `vite build`. Default: `'dev-and-staging'`
|
|
19
|
+
* — sourcemaps in development and staging deploys for debugging, but never
|
|
20
|
+
* in production (which would inflate the worker upload).
|
|
21
|
+
*
|
|
22
|
+
* - `true` / `false` — force on / off
|
|
23
|
+
* - `'dev-and-staging'` — on unless `CLOUDFLARE_ENV === 'prod'`
|
|
24
|
+
*/
|
|
25
|
+
sourcemap?: boolean | 'dev-and-staging';
|
|
26
|
+
/**
|
|
27
|
+
* Path (relative to project root) to the Vite client manifest emitted by
|
|
28
|
+
* the standalone browser-bundle build phase. The injector plugin reads it
|
|
29
|
+
* during the worker build and inlines it onto the worker entry chunk so
|
|
30
|
+
* `ManifestService` can resolve hashed asset URLs at runtime.
|
|
31
|
+
*
|
|
32
|
+
* Default: `'dist/client/.vite/manifest.json'` — matches the layout
|
|
33
|
+
* `quarry inertia:build` produces.
|
|
34
|
+
*/
|
|
35
|
+
clientManifestPath?: string;
|
|
17
36
|
}
|
|
18
37
|
declare function stratalInertia(options?: StratalInertiaPluginOptions): Plugin[];
|
|
19
38
|
//#endregion
|
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,OAAA;AAAA;AAAA,iBAqEc,oBAAA,CAAqB,OAAA,EAAS,oBAAA,GAAuB,MAAA;;;
|
|
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;;;iBCpErD,mBAAA,CAAA,GAAuB,MAAA;;;UCAtB,2BAAA;;EAEf,OAAA;EFHO;AAqET;;;;;;;EEzDE,SAAA;EFyDyE;;;;ACpE3E;;;;;ECqBE,kBAAA;AAAA;AAAA,iBAGc,cAAA,CAAe,OAAA,GAAU,2BAAA,GAA8B,MAAA"}
|
package/dist/vite.mjs
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { n as runTypeGeneration, t as findPagesDir } from "./type-generator-
|
|
1
|
+
import { n as runTypeGeneration, t as findPagesDir } from "./type-generator-bfo14BJI.mjs";
|
|
2
2
|
import { existsSync, readFileSync } from "node:fs";
|
|
3
|
-
import { join, relative } from "node:path";
|
|
3
|
+
import { isAbsolute, join, relative } from "node:path";
|
|
4
|
+
import { URL as URL$1 } from "node:url";
|
|
5
|
+
import { Worker } from "node:worker_threads";
|
|
4
6
|
//#region src/vite/inertia-dev-css-plugin.ts
|
|
5
7
|
const CSS_LANGS_RE = /\.(css|scss|sass|less|styl|stylus|pcss|postcss)(?:$|\?)/;
|
|
6
8
|
const VIRTUAL_MODULE_ID = "virtual:inertia-ssr.css";
|
|
@@ -37,6 +39,25 @@ async function collectStyle(server, entries) {
|
|
|
37
39
|
}
|
|
38
40
|
function stratalInertiaDevCss(options) {
|
|
39
41
|
let server;
|
|
42
|
+
let cachedCss = null;
|
|
43
|
+
let inflight = null;
|
|
44
|
+
let cacheEpoch = 0;
|
|
45
|
+
function invalidate() {
|
|
46
|
+
cachedCss = null;
|
|
47
|
+
cacheEpoch++;
|
|
48
|
+
}
|
|
49
|
+
async function getCss() {
|
|
50
|
+
if (cachedCss !== null) return cachedCss;
|
|
51
|
+
if (inflight) return inflight;
|
|
52
|
+
const epoch = cacheEpoch;
|
|
53
|
+
inflight = collectStyle(server, options.entries).then((css) => {
|
|
54
|
+
if (epoch === cacheEpoch) cachedCss = css;
|
|
55
|
+
return css;
|
|
56
|
+
}).finally(() => {
|
|
57
|
+
inflight = null;
|
|
58
|
+
});
|
|
59
|
+
return inflight;
|
|
60
|
+
}
|
|
40
61
|
return {
|
|
41
62
|
name: "stratal:inertia-dev-css",
|
|
42
63
|
apply: "serve",
|
|
@@ -44,7 +65,10 @@ function stratalInertiaDevCss(options) {
|
|
|
44
65
|
if (id === VIRTUAL_MODULE_ID) return RESOLVED_VIRTUAL_MODULE_ID;
|
|
45
66
|
},
|
|
46
67
|
async load(id) {
|
|
47
|
-
if (id === RESOLVED_VIRTUAL_MODULE_ID) return await
|
|
68
|
+
if (id === RESOLVED_VIRTUAL_MODULE_ID) return await getCss();
|
|
69
|
+
},
|
|
70
|
+
handleHotUpdate() {
|
|
71
|
+
invalidate();
|
|
48
72
|
},
|
|
49
73
|
configureServer(devServer) {
|
|
50
74
|
server = devServer;
|
|
@@ -53,7 +77,7 @@ function stratalInertiaDevCss(options) {
|
|
|
53
77
|
next();
|
|
54
78
|
return;
|
|
55
79
|
}
|
|
56
|
-
|
|
80
|
+
getCss().then((css) => {
|
|
57
81
|
res.setHeader("Content-Type", "text/css");
|
|
58
82
|
res.setHeader("Cache-Control", "no-store");
|
|
59
83
|
res.end(css);
|
|
@@ -66,18 +90,90 @@ function stratalInertiaDevCss(options) {
|
|
|
66
90
|
};
|
|
67
91
|
}
|
|
68
92
|
//#endregion
|
|
93
|
+
//#region src/vite/type-gen-dispatcher.ts
|
|
94
|
+
const defaultSpawn = (cwd) => new Worker(new URL$1("./generator/type-generator.worker.mjs", import.meta.url), { workerData: { cwd } });
|
|
95
|
+
function createTypeGenDispatcher(options) {
|
|
96
|
+
const spawn = options.spawn ?? defaultSpawn;
|
|
97
|
+
const debounceMs = options.debounceMs ?? 250;
|
|
98
|
+
let pendingTimer = null;
|
|
99
|
+
let inflight = null;
|
|
100
|
+
let queued = false;
|
|
101
|
+
let disposed = false;
|
|
102
|
+
function fire() {
|
|
103
|
+
pendingTimer = null;
|
|
104
|
+
if (disposed) return;
|
|
105
|
+
if (inflight) {
|
|
106
|
+
queued = true;
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
const worker = spawn(options.cwd);
|
|
110
|
+
inflight = worker;
|
|
111
|
+
const finish = () => {
|
|
112
|
+
if (inflight === worker) inflight = null;
|
|
113
|
+
if (disposed) return;
|
|
114
|
+
if (queued) {
|
|
115
|
+
queued = false;
|
|
116
|
+
fire();
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
worker.on("message", (msg) => {
|
|
120
|
+
options.onResult?.(msg);
|
|
121
|
+
});
|
|
122
|
+
worker.on("error", (err) => {
|
|
123
|
+
options.onError?.(err);
|
|
124
|
+
});
|
|
125
|
+
worker.on("exit", () => {
|
|
126
|
+
finish();
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
schedule() {
|
|
131
|
+
if (disposed) return;
|
|
132
|
+
if (inflight) {
|
|
133
|
+
queued = true;
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
if (pendingTimer) clearTimeout(pendingTimer);
|
|
137
|
+
pendingTimer = setTimeout(fire, debounceMs);
|
|
138
|
+
},
|
|
139
|
+
async dispose() {
|
|
140
|
+
disposed = true;
|
|
141
|
+
queued = false;
|
|
142
|
+
if (pendingTimer) {
|
|
143
|
+
clearTimeout(pendingTimer);
|
|
144
|
+
pendingTimer = null;
|
|
145
|
+
}
|
|
146
|
+
const worker = inflight;
|
|
147
|
+
inflight = null;
|
|
148
|
+
if (worker) try {
|
|
149
|
+
await worker.terminate();
|
|
150
|
+
} catch {}
|
|
151
|
+
}
|
|
152
|
+
};
|
|
153
|
+
}
|
|
154
|
+
//#endregion
|
|
69
155
|
//#region src/vite/inertia-types-plugin.ts
|
|
70
156
|
const INERTIA_CALL_PATTERN = /ctx\.inertia\(|\.share\(|ctx\.flash\(|ctx\.defer\(|ctx\.optional\(|ctx\.merge\(|ctx\.once\(|ctx\.always\(/;
|
|
71
157
|
function stratalInertiaTypes() {
|
|
72
158
|
let cwd;
|
|
73
159
|
let pagesDir;
|
|
74
160
|
let srcDir;
|
|
161
|
+
let dispatcher = null;
|
|
75
162
|
return {
|
|
76
163
|
name: "stratal:inertia-types",
|
|
77
164
|
configResolved(config) {
|
|
78
165
|
cwd = config.root;
|
|
79
166
|
pagesDir = findPagesDir(cwd) + "/";
|
|
80
167
|
srcDir = join(cwd, "src") + "/";
|
|
168
|
+
dispatcher = createTypeGenDispatcher({
|
|
169
|
+
cwd,
|
|
170
|
+
onError(err) {
|
|
171
|
+
console.warn("[stratal:inertia-types] Type generation worker errored:", err.message);
|
|
172
|
+
},
|
|
173
|
+
onResult(result) {
|
|
174
|
+
if (!result.ok && result.error) console.warn("[stratal:inertia-types] Type generation failed:", result.error);
|
|
175
|
+
}
|
|
176
|
+
});
|
|
81
177
|
},
|
|
82
178
|
async buildStart() {
|
|
83
179
|
if (!existsSync(pagesDir)) return;
|
|
@@ -87,7 +183,8 @@ function stratalInertiaTypes() {
|
|
|
87
183
|
console.warn("[stratal:inertia-types] Type generation failed during build:", error);
|
|
88
184
|
}
|
|
89
185
|
},
|
|
90
|
-
|
|
186
|
+
handleHotUpdate({ file }) {
|
|
187
|
+
if (!dispatcher) return;
|
|
91
188
|
if (!/\.(tsx|ts)$/.test(file)) return;
|
|
92
189
|
if (!!relative(srcDir, file).startsWith("..")) return;
|
|
93
190
|
if (!!relative(pagesDir, file).startsWith("..")) try {
|
|
@@ -96,10 +193,12 @@ function stratalInertiaTypes() {
|
|
|
96
193
|
} catch {
|
|
97
194
|
return;
|
|
98
195
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
196
|
+
dispatcher.schedule();
|
|
197
|
+
},
|
|
198
|
+
async closeBundle() {
|
|
199
|
+
if (dispatcher) {
|
|
200
|
+
await dispatcher.dispose();
|
|
201
|
+
dispatcher = null;
|
|
103
202
|
}
|
|
104
203
|
}
|
|
105
204
|
};
|
|
@@ -108,6 +207,8 @@ function stratalInertiaTypes() {
|
|
|
108
207
|
//#region src/vite.ts
|
|
109
208
|
function stratalInertia(options) {
|
|
110
209
|
const entries = options?.entries ?? ["/src/inertia/app.tsx"];
|
|
210
|
+
const sourcemapOption = options?.sourcemap ?? "dev-and-staging";
|
|
211
|
+
const sourcemap = sourcemapOption === "dev-and-staging" ? process.env.CLOUDFLARE_ENV !== "prod" && process.env.CLOUDFLARE_ENV !== "production" : sourcemapOption;
|
|
111
212
|
const optimizeDepsExclude = [
|
|
112
213
|
"@cloudflare/vite-plugin",
|
|
113
214
|
"wrangler",
|
|
@@ -118,19 +219,43 @@ function stratalInertia(options) {
|
|
|
118
219
|
"@hono/zod-openapi",
|
|
119
220
|
"@hono/swagger-ui"
|
|
120
221
|
];
|
|
222
|
+
const dedupe = [
|
|
223
|
+
"react",
|
|
224
|
+
"react-dom",
|
|
225
|
+
"react-is",
|
|
226
|
+
"scheduler",
|
|
227
|
+
"@inertiajs/core",
|
|
228
|
+
"@inertiajs/react"
|
|
229
|
+
];
|
|
230
|
+
const noExternal = [
|
|
231
|
+
"react",
|
|
232
|
+
"react-dom",
|
|
233
|
+
"react-is",
|
|
234
|
+
"scheduler",
|
|
235
|
+
"use-sync-external-store",
|
|
236
|
+
"@inertiajs/core",
|
|
237
|
+
"@inertiajs/react"
|
|
238
|
+
];
|
|
121
239
|
const optimizeDepsInclude = [
|
|
122
240
|
"buffer",
|
|
123
241
|
"buffer/",
|
|
124
242
|
"base64-js",
|
|
125
243
|
"ieee754"
|
|
126
244
|
];
|
|
127
|
-
const devOnlyExternals = [
|
|
245
|
+
const devOnlyExternals = [
|
|
246
|
+
"ts-morph",
|
|
247
|
+
/^langium($|\/)/,
|
|
248
|
+
/^@zenstackhq\/cli($|\/)/,
|
|
249
|
+
/^@zenstackhq\/language($|\/)/,
|
|
250
|
+
/^@zenstackhq\/sdk($|\/)/
|
|
251
|
+
];
|
|
252
|
+
const clientManifestPath = options?.clientManifestPath ?? "dist/client/.vite/manifest.json";
|
|
128
253
|
return [
|
|
129
254
|
stratalInertiaDevCss({ entries }),
|
|
130
255
|
stratalInertiaTypes(),
|
|
131
256
|
{
|
|
132
257
|
name: "stratal:optimize-deps-fix",
|
|
133
|
-
configEnvironment(
|
|
258
|
+
configEnvironment(name, env) {
|
|
134
259
|
const existing = env.optimizeDeps?.exclude ?? [];
|
|
135
260
|
const existingInclude = env.optimizeDeps?.include ?? [];
|
|
136
261
|
env.optimizeDeps = {
|
|
@@ -138,18 +263,56 @@ function stratalInertia(options) {
|
|
|
138
263
|
exclude: [...existing, ...optimizeDepsExclude],
|
|
139
264
|
include: [...existingInclude, ...optimizeDepsInclude]
|
|
140
265
|
};
|
|
141
|
-
const
|
|
266
|
+
const existingDedupe = env.resolve?.dedupe ?? [];
|
|
267
|
+
const existingNoExternal = env.resolve?.noExternal;
|
|
268
|
+
const mergedNoExternal = [...Array.isArray(existingNoExternal) ? existingNoExternal : typeof existingNoExternal === "string" || existingNoExternal instanceof RegExp ? [existingNoExternal] : [], ...noExternal];
|
|
269
|
+
env.resolve = {
|
|
270
|
+
...env.resolve,
|
|
271
|
+
dedupe: [...existingDedupe, ...dedupe],
|
|
272
|
+
noExternal: existingNoExternal === true ? true : mergedNoExternal
|
|
273
|
+
};
|
|
274
|
+
const existingExternal = env.build?.rolldownOptions?.external;
|
|
275
|
+
const existingExternalArray = Array.isArray(existingExternal) ? existingExternal : existingExternal != null ? [existingExternal] : [];
|
|
142
276
|
env.build = {
|
|
143
277
|
...env.build,
|
|
278
|
+
sourcemap: env.build?.sourcemap ?? sourcemap,
|
|
144
279
|
rolldownOptions: {
|
|
145
280
|
...env.build?.rolldownOptions,
|
|
146
|
-
external: [...
|
|
281
|
+
external: [...existingExternalArray, ...devOnlyExternals]
|
|
147
282
|
}
|
|
148
283
|
};
|
|
284
|
+
if (name === "client") env.build.emptyOutDir = false;
|
|
149
285
|
}
|
|
150
|
-
}
|
|
286
|
+
},
|
|
287
|
+
injectClientManifestIntoWorker({ clientManifestPath })
|
|
151
288
|
];
|
|
152
289
|
}
|
|
290
|
+
function injectClientManifestIntoWorker(args) {
|
|
291
|
+
let projectRoot = process.cwd();
|
|
292
|
+
return {
|
|
293
|
+
name: "stratal:inertia-inject-manifest",
|
|
294
|
+
apply: "build",
|
|
295
|
+
configResolved(config) {
|
|
296
|
+
projectRoot = config.root;
|
|
297
|
+
},
|
|
298
|
+
generateBundle(_options, bundle) {
|
|
299
|
+
if (this.environment.name === "client") return;
|
|
300
|
+
const manifestPath = isAbsolute(args.clientManifestPath) ? args.clientManifestPath : join(projectRoot, args.clientManifestPath);
|
|
301
|
+
if (!existsSync(manifestPath)) this.error("@stratal/inertia: client manifest not found at " + manifestPath + ". Run `quarry inertia:build` to build the browser bundle before deploying.");
|
|
302
|
+
const manifestJson = readFileSync(manifestPath, "utf-8");
|
|
303
|
+
const manifest = JSON.parse(manifestJson);
|
|
304
|
+
const inlined = JSON.stringify(manifest);
|
|
305
|
+
const sentinel = "globalThis.__STRATAL_INERTIA_MANIFEST__";
|
|
306
|
+
for (const fileName of Object.keys(bundle)) {
|
|
307
|
+
const chunk = bundle[fileName];
|
|
308
|
+
if (chunk.type !== "chunk") continue;
|
|
309
|
+
if (!chunk.isEntry) continue;
|
|
310
|
+
if (chunk.code.startsWith(sentinel)) continue;
|
|
311
|
+
chunk.code = `${sentinel} = ${inlined};\n${chunk.code}`;
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
};
|
|
315
|
+
}
|
|
153
316
|
//#endregion
|
|
154
317
|
export { stratalInertia, stratalInertiaDevCss, stratalInertiaTypes };
|
|
155
318
|
|