@dudousxd/nestjs-codegen 0.10.0 → 0.12.0
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/CHANGELOG.md +47 -0
- package/dist/cli/main.cjs +209 -89
- package/dist/cli/main.cjs.map +1 -1
- package/dist/cli/main.js +193 -73
- package/dist/cli/main.js.map +1 -1
- package/dist/index.cjs +167 -47
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +29 -3
- package/dist/index.d.ts +29 -3
- package/dist/index.js +154 -34
- package/dist/index.js.map +1 -1
- package/dist/nest/index.cjs +212 -73
- package/dist/nest/index.cjs.map +1 -1
- package/dist/nest/index.d.cts +15 -4
- package/dist/nest/index.d.ts +15 -4
- package/dist/nest/index.js +212 -73
- package/dist/nest/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/main.js
CHANGED
|
@@ -183,8 +183,8 @@ Run \`nestjs-codegen init\` to create a starter config.`
|
|
|
183
183
|
}
|
|
184
184
|
|
|
185
185
|
// src/generate.ts
|
|
186
|
-
import { mkdir as mkdir9, writeFile as
|
|
187
|
-
import { dirname as dirname2, join as
|
|
186
|
+
import { mkdir as mkdir9, writeFile as writeFile10 } from "fs/promises";
|
|
187
|
+
import { dirname as dirname2, join as join13 } from "path";
|
|
188
188
|
|
|
189
189
|
// src/discovery/pages.ts
|
|
190
190
|
import { readFile } from "fs/promises";
|
|
@@ -798,7 +798,11 @@ function buildRequestModel(c) {
|
|
|
798
798
|
urlExpr,
|
|
799
799
|
optsExpr,
|
|
800
800
|
responseType: `${TA}['response']`,
|
|
801
|
-
|
|
801
|
+
// When no input is supplied the key omits the trailing element entirely
|
|
802
|
+
// (`[name]` rather than `[name, undefined]`) so the bare `.queryKey()` is a
|
|
803
|
+
// clean prefix that partial-matches every parametrized variant — making it
|
|
804
|
+
// directly usable for `invalidateQueries`.
|
|
805
|
+
queryKeyExpr: `(input === undefined ? [${flat}] as const : [${flat}, input] as const)`
|
|
802
806
|
};
|
|
803
807
|
}
|
|
804
808
|
function renderFetcherRequest(req) {
|
|
@@ -2075,6 +2079,99 @@ function buildEmpty() {
|
|
|
2075
2079
|
].join("\n");
|
|
2076
2080
|
}
|
|
2077
2081
|
|
|
2082
|
+
// src/generate-manifest.ts
|
|
2083
|
+
import { createHash } from "crypto";
|
|
2084
|
+
import { readFile as readFile2, readdir, writeFile as writeFile9 } from "fs/promises";
|
|
2085
|
+
import { join as join12, relative as relative6 } from "path";
|
|
2086
|
+
import fg2 from "fast-glob";
|
|
2087
|
+
var MANIFEST_FILE = ".codegen-manifest.json";
|
|
2088
|
+
var LOCK_FILE = ".watcher.lock";
|
|
2089
|
+
function isManifestShape(value) {
|
|
2090
|
+
if (typeof value !== "object" || value === null) return false;
|
|
2091
|
+
const candidate = value;
|
|
2092
|
+
if (typeof candidate.version !== "string") return false;
|
|
2093
|
+
if (typeof candidate.hash !== "string") return false;
|
|
2094
|
+
if (!Array.isArray(candidate.files)) return false;
|
|
2095
|
+
return candidate.files.every((entry) => typeof entry === "string");
|
|
2096
|
+
}
|
|
2097
|
+
function serializeConfig(config) {
|
|
2098
|
+
try {
|
|
2099
|
+
return JSON.stringify(config, (_key, value) => {
|
|
2100
|
+
if (typeof value === "function") return `[fn:${value.name}]${value.toString()}`;
|
|
2101
|
+
return value;
|
|
2102
|
+
});
|
|
2103
|
+
} catch {
|
|
2104
|
+
return `unserializable:${config.codegen.outDir}:${config.contracts.glob}`;
|
|
2105
|
+
}
|
|
2106
|
+
}
|
|
2107
|
+
async function discoverInputFiles(config) {
|
|
2108
|
+
const globs = [config.contracts.glob, config.forms.watch];
|
|
2109
|
+
if (config.pages) globs.push(config.pages.glob);
|
|
2110
|
+
const cwd = config.codegen.cwd;
|
|
2111
|
+
const matched = await fg2(globs, { cwd, absolute: true, onlyFiles: true });
|
|
2112
|
+
return [...new Set(matched)].sort();
|
|
2113
|
+
}
|
|
2114
|
+
async function computeInputsHash(config) {
|
|
2115
|
+
const hash = createHash("sha256");
|
|
2116
|
+
hash.update(`version:${VERSION}
|
|
2117
|
+
`);
|
|
2118
|
+
hash.update(`config:${serializeConfig(config)}
|
|
2119
|
+
`);
|
|
2120
|
+
const inputFiles = await discoverInputFiles(config);
|
|
2121
|
+
const cwd = config.codegen.cwd;
|
|
2122
|
+
for (const file of inputFiles) {
|
|
2123
|
+
const contents = await readFile2(file, "utf8");
|
|
2124
|
+
hash.update(`file:${relative6(cwd, file)}
|
|
2125
|
+
`);
|
|
2126
|
+
hash.update(contents);
|
|
2127
|
+
hash.update("\n");
|
|
2128
|
+
}
|
|
2129
|
+
return hash.digest("hex");
|
|
2130
|
+
}
|
|
2131
|
+
async function readManifest(outDir) {
|
|
2132
|
+
try {
|
|
2133
|
+
const raw = await readFile2(join12(outDir, MANIFEST_FILE), "utf8");
|
|
2134
|
+
const parsed = JSON.parse(raw);
|
|
2135
|
+
if (!isManifestShape(parsed)) return null;
|
|
2136
|
+
return { version: parsed.version, hash: parsed.hash, files: parsed.files };
|
|
2137
|
+
} catch {
|
|
2138
|
+
return null;
|
|
2139
|
+
}
|
|
2140
|
+
}
|
|
2141
|
+
async function writeManifest(outDir, manifest) {
|
|
2142
|
+
await writeFile9(join12(outDir, MANIFEST_FILE), `${JSON.stringify(manifest, null, 2)}
|
|
2143
|
+
`, "utf8");
|
|
2144
|
+
}
|
|
2145
|
+
async function listOutputFiles(outDir) {
|
|
2146
|
+
const found = [];
|
|
2147
|
+
async function walk(dir) {
|
|
2148
|
+
const entries = await readdir(dir, { withFileTypes: true }).catch(() => []);
|
|
2149
|
+
for (const entry of entries) {
|
|
2150
|
+
const abs = join12(dir, entry.name);
|
|
2151
|
+
if (entry.isDirectory()) {
|
|
2152
|
+
await walk(abs);
|
|
2153
|
+
} else if (entry.isFile()) {
|
|
2154
|
+
const rel = relative6(outDir, abs);
|
|
2155
|
+
if (rel === MANIFEST_FILE || rel === LOCK_FILE) continue;
|
|
2156
|
+
found.push(rel);
|
|
2157
|
+
}
|
|
2158
|
+
}
|
|
2159
|
+
}
|
|
2160
|
+
await walk(outDir);
|
|
2161
|
+
return found.sort();
|
|
2162
|
+
}
|
|
2163
|
+
async function allOutputsExist(outDir, files) {
|
|
2164
|
+
const present = new Set(await listOutputFiles(outDir));
|
|
2165
|
+
return files.every((file) => present.has(file));
|
|
2166
|
+
}
|
|
2167
|
+
async function isManifestFresh(outDir, manifest, inputsHash) {
|
|
2168
|
+
if (manifest === null) return false;
|
|
2169
|
+
if (manifest.version !== VERSION) return false;
|
|
2170
|
+
if (manifest.hash !== inputsHash) return false;
|
|
2171
|
+
if (manifest.files.length === 0) return false;
|
|
2172
|
+
return allOutputsExist(outDir, manifest.files);
|
|
2173
|
+
}
|
|
2174
|
+
|
|
2078
2175
|
// src/util/debug-log.ts
|
|
2079
2176
|
var debugEnabled = false;
|
|
2080
2177
|
function setCodegenDebug(enabled) {
|
|
@@ -2087,6 +2184,12 @@ function debugWarn(message) {
|
|
|
2087
2184
|
// src/generate.ts
|
|
2088
2185
|
async function generate(config, inputRoutes = []) {
|
|
2089
2186
|
setCodegenDebug(config.debug);
|
|
2187
|
+
const inputsHash = await computeInputsHash(config);
|
|
2188
|
+
const manifest = await readManifest(config.codegen.outDir);
|
|
2189
|
+
if (await isManifestFresh(config.codegen.outDir, manifest, inputsHash)) {
|
|
2190
|
+
console.log(`[nestjs-codegen] ${config.codegen.outDir} up to date, skipped`);
|
|
2191
|
+
return;
|
|
2192
|
+
}
|
|
2090
2193
|
const extensions = config.extensions ?? [];
|
|
2091
2194
|
let routes = inputRoutes;
|
|
2092
2195
|
const ctx = createExtensionContext(config, () => routes);
|
|
@@ -2143,21 +2246,27 @@ async function generate(config, inputRoutes = []) {
|
|
|
2143
2246
|
if (extensions.length > 0) {
|
|
2144
2247
|
const extraFiles = await collectEmittedFiles(extensions, ctx);
|
|
2145
2248
|
for (const file of extraFiles) {
|
|
2146
|
-
const dest =
|
|
2249
|
+
const dest = join13(config.codegen.outDir, file.path);
|
|
2147
2250
|
await mkdir9(dirname2(dest), { recursive: true });
|
|
2148
|
-
await
|
|
2251
|
+
await writeFile10(dest, file.contents, "utf8");
|
|
2149
2252
|
}
|
|
2150
2253
|
}
|
|
2254
|
+
const outputFiles = await listOutputFiles(config.codegen.outDir);
|
|
2255
|
+
await writeManifest(config.codegen.outDir, {
|
|
2256
|
+
version: VERSION,
|
|
2257
|
+
hash: inputsHash,
|
|
2258
|
+
files: outputFiles
|
|
2259
|
+
});
|
|
2151
2260
|
}
|
|
2152
2261
|
|
|
2153
2262
|
// src/watch/watcher.ts
|
|
2154
|
-
import { readFile as
|
|
2155
|
-
import { join as
|
|
2263
|
+
import { readFile as readFile4 } from "fs/promises";
|
|
2264
|
+
import { join as join16 } from "path";
|
|
2156
2265
|
import chokidar from "chokidar";
|
|
2157
2266
|
|
|
2158
2267
|
// src/discovery/contracts-fast.ts
|
|
2159
|
-
import { join as
|
|
2160
|
-
import
|
|
2268
|
+
import { join as join14, resolve as resolve3 } from "path";
|
|
2269
|
+
import fg3 from "fast-glob";
|
|
2161
2270
|
import {
|
|
2162
2271
|
Node as Node8,
|
|
2163
2272
|
Project as Project3
|
|
@@ -3934,7 +4043,7 @@ async function discoverContractsFast(opts) {
|
|
|
3934
4043
|
const { cwd, glob, tsconfig } = opts;
|
|
3935
4044
|
const tsconfigPath = resolveTsconfigPath(cwd, tsconfig);
|
|
3936
4045
|
const project = createDiscoveryProject(tsconfigPath);
|
|
3937
|
-
const files = await
|
|
4046
|
+
const files = await fg3(glob, { cwd, absolute: true, onlyFiles: true });
|
|
3938
4047
|
for (const f of files) {
|
|
3939
4048
|
project.addSourceFileAtPath(f);
|
|
3940
4049
|
}
|
|
@@ -3942,7 +4051,7 @@ async function discoverContractsFast(opts) {
|
|
|
3942
4051
|
return extractAllRoutes(project);
|
|
3943
4052
|
}
|
|
3944
4053
|
function resolveTsconfigPath(cwd, tsconfig) {
|
|
3945
|
-
return tsconfig ? resolve3(tsconfig) :
|
|
4054
|
+
return tsconfig ? resolve3(tsconfig) : join14(cwd, "tsconfig.json");
|
|
3946
4055
|
}
|
|
3947
4056
|
function createDiscoveryProject(tsconfigPath) {
|
|
3948
4057
|
try {
|
|
@@ -4007,7 +4116,7 @@ var PersistentDiscovery = class _PersistentDiscovery {
|
|
|
4007
4116
|
const project = createDiscoveryProject(tsconfigPath);
|
|
4008
4117
|
bindDiscoveryContext(project, cwd, tsconfigPath);
|
|
4009
4118
|
const instance = new _PersistentDiscovery(project, cwd, glob);
|
|
4010
|
-
const files = await
|
|
4119
|
+
const files = await fg3(glob, { cwd, absolute: true, onlyFiles: true });
|
|
4011
4120
|
for (const f of files) {
|
|
4012
4121
|
project.addSourceFileAtPath(f);
|
|
4013
4122
|
instance.controllerPaths.add(f);
|
|
@@ -4036,7 +4145,7 @@ var PersistentDiscovery = class _PersistentDiscovery {
|
|
|
4036
4145
|
}
|
|
4037
4146
|
}
|
|
4038
4147
|
const globbed = new Set(
|
|
4039
|
-
await
|
|
4148
|
+
await fg3(this.glob, { cwd: this.cwd, absolute: true, onlyFiles: true })
|
|
4040
4149
|
);
|
|
4041
4150
|
for (const f of globbed) {
|
|
4042
4151
|
if (!this.controllerPaths.has(f)) {
|
|
@@ -4317,9 +4426,9 @@ function extractFromSourceFile(sourceFile, project) {
|
|
|
4317
4426
|
|
|
4318
4427
|
// src/watch/lock-file.ts
|
|
4319
4428
|
import { open } from "fs/promises";
|
|
4320
|
-
import { mkdir as mkdir10, readFile as
|
|
4321
|
-
import { join as
|
|
4322
|
-
var
|
|
4429
|
+
import { mkdir as mkdir10, readFile as readFile3, unlink } from "fs/promises";
|
|
4430
|
+
import { join as join15 } from "path";
|
|
4431
|
+
var LOCK_FILE2 = ".watcher.lock";
|
|
4323
4432
|
function isProcessAlive(pid) {
|
|
4324
4433
|
try {
|
|
4325
4434
|
process.kill(pid, 0);
|
|
@@ -4330,7 +4439,7 @@ function isProcessAlive(pid) {
|
|
|
4330
4439
|
}
|
|
4331
4440
|
async function acquireLock(outDir) {
|
|
4332
4441
|
await mkdir10(outDir, { recursive: true });
|
|
4333
|
-
const lockPath =
|
|
4442
|
+
const lockPath = join15(outDir, LOCK_FILE2);
|
|
4334
4443
|
const lockData = { pid: process.pid, startedAt: (/* @__PURE__ */ new Date()).toISOString() };
|
|
4335
4444
|
try {
|
|
4336
4445
|
const fd = await open(lockPath, "wx");
|
|
@@ -4340,7 +4449,7 @@ async function acquireLock(outDir) {
|
|
|
4340
4449
|
} catch (err) {
|
|
4341
4450
|
if (err.code === "EEXIST") {
|
|
4342
4451
|
try {
|
|
4343
|
-
const raw = await
|
|
4452
|
+
const raw = await readFile3(lockPath, "utf8");
|
|
4344
4453
|
const existing = JSON.parse(raw);
|
|
4345
4454
|
if (isProcessAlive(existing.pid)) return null;
|
|
4346
4455
|
await unlink(lockPath);
|
|
@@ -4365,12 +4474,12 @@ async function acquireLock(outDir) {
|
|
|
4365
4474
|
var PAGES_DEBOUNCE_MS = 150;
|
|
4366
4475
|
var NO_OP_WATCHER = { close: async () => {
|
|
4367
4476
|
} };
|
|
4368
|
-
async function watch(config, onChange) {
|
|
4477
|
+
async function watch(config, onChange, options = {}) {
|
|
4369
4478
|
const lock = await acquireLock(config.codegen.outDir);
|
|
4370
4479
|
if (lock === null) {
|
|
4371
4480
|
let holderPid = "unknown";
|
|
4372
4481
|
try {
|
|
4373
|
-
const raw = await
|
|
4482
|
+
const raw = await readFile4(join16(config.codegen.outDir, ".watcher.lock"), "utf8");
|
|
4374
4483
|
const data = JSON.parse(raw);
|
|
4375
4484
|
if (data.pid !== void 0) holderPid = String(data.pid);
|
|
4376
4485
|
} catch {
|
|
@@ -4393,22 +4502,33 @@ async function watch(config, onChange) {
|
|
|
4393
4502
|
}
|
|
4394
4503
|
return discovery;
|
|
4395
4504
|
}
|
|
4396
|
-
|
|
4397
|
-
const initialRoutes = (await getDiscovery()).discover();
|
|
4398
|
-
lastRoutes = initialRoutes;
|
|
4399
|
-
await generate(config, initialRoutes);
|
|
4400
|
-
} catch (err) {
|
|
4401
|
-
console.warn(
|
|
4402
|
-
`[nestjs-codegen] Initial route discovery failed, falling back to pages-only: ${err instanceof Error ? err.message : String(err)}`
|
|
4403
|
-
);
|
|
4505
|
+
async function runInitialPass() {
|
|
4404
4506
|
try {
|
|
4405
|
-
await
|
|
4406
|
-
|
|
4507
|
+
const initialRoutes = (await getDiscovery()).discover();
|
|
4508
|
+
lastRoutes = initialRoutes;
|
|
4509
|
+
await generate(config, initialRoutes);
|
|
4510
|
+
} catch (err) {
|
|
4511
|
+
console.warn(
|
|
4512
|
+
`[nestjs-codegen] Initial route discovery failed, falling back to pages-only: ${err instanceof Error ? err.message : String(err)}`
|
|
4513
|
+
);
|
|
4514
|
+
try {
|
|
4515
|
+
await generate(config, lastRoutes);
|
|
4516
|
+
} catch {
|
|
4517
|
+
}
|
|
4407
4518
|
}
|
|
4408
4519
|
}
|
|
4520
|
+
if (options.deferInitialGenerate) {
|
|
4521
|
+
void runInitialPass().catch((err) => {
|
|
4522
|
+
console.warn(
|
|
4523
|
+
`[nestjs-codegen] Background initial generate failed: ${err instanceof Error ? err.message : String(err)}`
|
|
4524
|
+
);
|
|
4525
|
+
});
|
|
4526
|
+
} else {
|
|
4527
|
+
await runInitialPass();
|
|
4528
|
+
}
|
|
4409
4529
|
let pagesDebounceTimer;
|
|
4410
4530
|
const pagesGlob = config.pages?.glob ?? ".nestjs-codegen-no-pages";
|
|
4411
|
-
const pagesWatcher = chokidar.watch(
|
|
4531
|
+
const pagesWatcher = chokidar.watch(join16(config.codegen.cwd, pagesGlob), {
|
|
4412
4532
|
ignoreInitial: true,
|
|
4413
4533
|
persistent: true,
|
|
4414
4534
|
awaitWriteFinish: { stabilityThreshold: 80, pollInterval: 20 }
|
|
@@ -4435,7 +4555,7 @@ async function watch(config, onChange) {
|
|
|
4435
4555
|
pagesWatcher.on("unlink", schedulePagesRegenerate);
|
|
4436
4556
|
let contractsDebounceTimer;
|
|
4437
4557
|
const pendingChangedPaths = /* @__PURE__ */ new Set();
|
|
4438
|
-
const contractsWatcher = chokidar.watch(
|
|
4558
|
+
const contractsWatcher = chokidar.watch(join16(config.codegen.cwd, config.contracts.glob), {
|
|
4439
4559
|
ignoreInitial: true,
|
|
4440
4560
|
persistent: true,
|
|
4441
4561
|
awaitWriteFinish: { stabilityThreshold: 80, pollInterval: 20 }
|
|
@@ -4465,7 +4585,7 @@ async function watch(config, onChange) {
|
|
|
4465
4585
|
contractsWatcher.on("add", (p) => scheduleContractsRegenerate(p));
|
|
4466
4586
|
contractsWatcher.on("change", (p) => scheduleContractsRegenerate(p));
|
|
4467
4587
|
contractsWatcher.on("unlink", (p) => scheduleContractsRegenerate(p));
|
|
4468
|
-
const formsWatcher = chokidar.watch(
|
|
4588
|
+
const formsWatcher = chokidar.watch(join16(config.codegen.cwd, config.forms.watch), {
|
|
4469
4589
|
ignoreInitial: true,
|
|
4470
4590
|
persistent: true,
|
|
4471
4591
|
awaitWriteFinish: { stabilityThreshold: 80, pollInterval: 20 }
|
|
@@ -4492,7 +4612,7 @@ async function watch(config, onChange) {
|
|
|
4492
4612
|
}
|
|
4493
4613
|
|
|
4494
4614
|
// src/index.ts
|
|
4495
|
-
var VERSION = "0.
|
|
4615
|
+
var VERSION = "0.12.0";
|
|
4496
4616
|
|
|
4497
4617
|
// src/cli/codegen.ts
|
|
4498
4618
|
async function runCodegen(opts = {}) {
|
|
@@ -4521,13 +4641,13 @@ async function runCodegen(opts = {}) {
|
|
|
4521
4641
|
// src/cli/doctor.ts
|
|
4522
4642
|
import { execFileSync as execFileSync2 } from "child_process";
|
|
4523
4643
|
import { appendFileSync, existsSync, readFileSync as readFileSync4, writeFileSync as writeFileSync3 } from "fs";
|
|
4524
|
-
import { join as
|
|
4644
|
+
import { join as join18 } from "path";
|
|
4525
4645
|
|
|
4526
4646
|
// src/cli/init.ts
|
|
4527
4647
|
import { execFileSync } from "child_process";
|
|
4528
4648
|
import { readFileSync as readFileSync3, writeFileSync as writeFileSync2 } from "fs";
|
|
4529
|
-
import { access as access2, mkdir as mkdir11, readFile as
|
|
4530
|
-
import { join as
|
|
4649
|
+
import { access as access2, mkdir as mkdir11, readFile as readFile5, writeFile as writeFile11 } from "fs/promises";
|
|
4650
|
+
import { join as join17 } from "path";
|
|
4531
4651
|
import { createInterface } from "readline";
|
|
4532
4652
|
|
|
4533
4653
|
// src/cli/patch-utils.ts
|
|
@@ -4589,7 +4709,7 @@ ${bold(title)}`);
|
|
|
4589
4709
|
}
|
|
4590
4710
|
async function readPackageJson(cwd) {
|
|
4591
4711
|
try {
|
|
4592
|
-
const raw = await
|
|
4712
|
+
const raw = await readFile5(join17(cwd, "package.json"), "utf8");
|
|
4593
4713
|
return JSON.parse(raw);
|
|
4594
4714
|
} catch {
|
|
4595
4715
|
return {};
|
|
@@ -4620,7 +4740,7 @@ async function detectTemplateEngine(cwd) {
|
|
|
4620
4740
|
async function detectPackageManager(cwd) {
|
|
4621
4741
|
async function exists(file) {
|
|
4622
4742
|
try {
|
|
4623
|
-
await access2(
|
|
4743
|
+
await access2(join17(cwd, file));
|
|
4624
4744
|
return true;
|
|
4625
4745
|
} catch {
|
|
4626
4746
|
return false;
|
|
@@ -4663,13 +4783,13 @@ async function writeIfNotExists(filePath, content, label) {
|
|
|
4663
4783
|
if (dir) {
|
|
4664
4784
|
await mkdir11(dir, { recursive: true });
|
|
4665
4785
|
}
|
|
4666
|
-
await
|
|
4786
|
+
await writeFile11(filePath, content, "utf8");
|
|
4667
4787
|
logCreated(label);
|
|
4668
4788
|
}
|
|
4669
4789
|
async function handleViteConfig(cwd, framework) {
|
|
4670
|
-
const filePath =
|
|
4790
|
+
const filePath = join17(cwd, "vite.config.ts");
|
|
4671
4791
|
if (await fileExists2(filePath)) {
|
|
4672
|
-
const existing = await
|
|
4792
|
+
const existing = await readFile5(filePath, "utf8");
|
|
4673
4793
|
const hasPlugin = existing.includes("nestInertia") || existing.includes("nestjs-inertia-vite/plugin");
|
|
4674
4794
|
if (!hasPlugin) {
|
|
4675
4795
|
logSkipped("vite.config.ts");
|
|
@@ -4687,13 +4807,13 @@ async function handleViteConfig(cwd, framework) {
|
|
|
4687
4807
|
if (dir) {
|
|
4688
4808
|
await mkdir11(dir, { recursive: true });
|
|
4689
4809
|
}
|
|
4690
|
-
await
|
|
4810
|
+
await writeFile11(filePath, viteConfigTemplate(framework), "utf8");
|
|
4691
4811
|
logCreated("vite.config.ts");
|
|
4692
4812
|
}
|
|
4693
4813
|
async function patchGitignore(gitignorePath) {
|
|
4694
4814
|
let existing = "";
|
|
4695
4815
|
if (await fileExists2(gitignorePath)) {
|
|
4696
|
-
existing = await
|
|
4816
|
+
existing = await readFile5(gitignorePath, "utf8");
|
|
4697
4817
|
}
|
|
4698
4818
|
if (existing.split("\n").some((line) => line.trim() === GITIGNORE_ENTRY)) {
|
|
4699
4819
|
console.log(` ${cyan("\u2192")} .gitignore ${dim("(already contains .nestjs-inertia/, skipped)")}`);
|
|
@@ -4703,7 +4823,7 @@ async function patchGitignore(gitignorePath) {
|
|
|
4703
4823
|
` : `${existing}
|
|
4704
4824
|
${GITIGNORE_ENTRY}
|
|
4705
4825
|
`;
|
|
4706
|
-
await
|
|
4826
|
+
await writeFile11(gitignorePath, newContent, "utf8");
|
|
4707
4827
|
logPatched(".gitignore", "added .nestjs-inertia/");
|
|
4708
4828
|
}
|
|
4709
4829
|
function installDeps(pkgManager, deps, dev) {
|
|
@@ -4725,10 +4845,10 @@ function installDeps(pkgManager, deps, dev) {
|
|
|
4725
4845
|
}
|
|
4726
4846
|
}
|
|
4727
4847
|
async function patchPackageJsonScripts(cwd, scripts) {
|
|
4728
|
-
const pkgPath =
|
|
4848
|
+
const pkgPath = join17(cwd, "package.json");
|
|
4729
4849
|
let pkg = {};
|
|
4730
4850
|
try {
|
|
4731
|
-
pkg = JSON.parse(await
|
|
4851
|
+
pkg = JSON.parse(await readFile5(pkgPath, "utf8"));
|
|
4732
4852
|
} catch {
|
|
4733
4853
|
return;
|
|
4734
4854
|
}
|
|
@@ -4747,7 +4867,7 @@ async function patchPackageJsonScripts(cwd, scripts) {
|
|
|
4747
4867
|
return;
|
|
4748
4868
|
}
|
|
4749
4869
|
pkg.scripts = existing;
|
|
4750
|
-
await
|
|
4870
|
+
await writeFile11(pkgPath, `${JSON.stringify(pkg, null, 2)}
|
|
4751
4871
|
`, "utf8");
|
|
4752
4872
|
}
|
|
4753
4873
|
function patchAppModule(filePath, rootView) {
|
|
@@ -5042,7 +5162,7 @@ export class HomeController {
|
|
|
5042
5162
|
}
|
|
5043
5163
|
`;
|
|
5044
5164
|
function patchTsconfigExclude(cwd, dir, filename = "tsconfig.json") {
|
|
5045
|
-
const filePath =
|
|
5165
|
+
const filePath = join17(cwd, filename);
|
|
5046
5166
|
return patchJsonFile(
|
|
5047
5167
|
filePath,
|
|
5048
5168
|
(json) => {
|
|
@@ -5057,7 +5177,7 @@ function patchTsconfigExclude(cwd, dir, filename = "tsconfig.json") {
|
|
|
5057
5177
|
);
|
|
5058
5178
|
}
|
|
5059
5179
|
function patchNestCliJson(cwd, shellDir) {
|
|
5060
|
-
const filePath =
|
|
5180
|
+
const filePath = join17(cwd, "nest-cli.json");
|
|
5061
5181
|
return patchJsonFile(filePath, (json) => {
|
|
5062
5182
|
const compiler = json.compilerOptions ?? {};
|
|
5063
5183
|
const assets = compiler.assets ?? [];
|
|
@@ -5080,46 +5200,46 @@ async function scaffoldFiles(ctx) {
|
|
|
5080
5200
|
const { cwd, framework, engine, shellFileName, entryExt, pageExt } = ctx;
|
|
5081
5201
|
logSection("Scaffold files");
|
|
5082
5202
|
await writeIfNotExists(
|
|
5083
|
-
|
|
5203
|
+
join17(cwd, "nestjs-inertia.config.ts"),
|
|
5084
5204
|
configTemplate(framework),
|
|
5085
5205
|
"nestjs-inertia.config.ts"
|
|
5086
5206
|
);
|
|
5087
|
-
await writeIfNotExists(
|
|
5207
|
+
await writeIfNotExists(join17(cwd, "nestjs-inertia.d.ts"), DTS_TEMPLATE, "nestjs-inertia.d.ts");
|
|
5088
5208
|
await writeIfNotExists(
|
|
5089
|
-
|
|
5209
|
+
join17(cwd, "tsconfig.inertia.json"),
|
|
5090
5210
|
TSCONFIG_INERTIA_TEMPLATE,
|
|
5091
5211
|
"tsconfig.inertia.json"
|
|
5092
5212
|
);
|
|
5093
5213
|
await writeIfNotExists(
|
|
5094
|
-
|
|
5214
|
+
join17(cwd, "inertia", "tsconfig.json"),
|
|
5095
5215
|
INERTIA_TSCONFIG_TEMPLATE,
|
|
5096
5216
|
"inertia/tsconfig.json"
|
|
5097
5217
|
);
|
|
5098
5218
|
await writeIfNotExists(
|
|
5099
|
-
|
|
5219
|
+
join17(cwd, "inertia", shellFileName),
|
|
5100
5220
|
htmlShellTemplate(framework, engine),
|
|
5101
5221
|
`inertia/${shellFileName}`
|
|
5102
5222
|
);
|
|
5103
5223
|
await handleViteConfig(cwd, framework);
|
|
5104
5224
|
await writeIfNotExists(
|
|
5105
|
-
|
|
5225
|
+
join17(cwd, "inertia", "app", `client.${entryExt}`),
|
|
5106
5226
|
entryPointTemplate(framework),
|
|
5107
5227
|
`inertia/app/client.${entryExt}`
|
|
5108
5228
|
);
|
|
5109
5229
|
await writeIfNotExists(
|
|
5110
|
-
|
|
5230
|
+
join17(cwd, "inertia", "pages", `Home.${pageExt}`),
|
|
5111
5231
|
samplePageTemplate(framework),
|
|
5112
5232
|
`inertia/pages/Home.${pageExt}`
|
|
5113
5233
|
);
|
|
5114
5234
|
await writeIfNotExists(
|
|
5115
|
-
|
|
5235
|
+
join17(cwd, "src", "home.controller.ts"),
|
|
5116
5236
|
SAMPLE_CONTROLLER,
|
|
5117
5237
|
"src/home.controller.ts"
|
|
5118
5238
|
);
|
|
5119
5239
|
}
|
|
5120
5240
|
function patchServerAppModule(ctx) {
|
|
5121
5241
|
const { cwd, rootView } = ctx;
|
|
5122
|
-
const appModulePath =
|
|
5242
|
+
const appModulePath = join17(cwd, "src", "app.module.ts");
|
|
5123
5243
|
const appModuleResult = patchAppModule(appModulePath, rootView);
|
|
5124
5244
|
if (appModuleResult === "patched") {
|
|
5125
5245
|
logPatched("src/app.module.ts", "added InertiaModule.forRoot");
|
|
@@ -5133,7 +5253,7 @@ function patchServerAppModule(ctx) {
|
|
|
5133
5253
|
}
|
|
5134
5254
|
}
|
|
5135
5255
|
function patchServerMainTs(ctx) {
|
|
5136
|
-
const mainTsPath =
|
|
5256
|
+
const mainTsPath = join17(ctx.cwd, "src", "main.ts");
|
|
5137
5257
|
const mainTsResult = patchMainTs(mainTsPath);
|
|
5138
5258
|
if (mainTsResult === "patched") {
|
|
5139
5259
|
logPatched("src/main.ts", "added setupInertiaVite after NestFactory.create");
|
|
@@ -5168,7 +5288,7 @@ function patchBuildConfigs(ctx) {
|
|
|
5168
5288
|
}
|
|
5169
5289
|
async function patchGitignoreAndDist(ctx) {
|
|
5170
5290
|
const { cwd } = ctx;
|
|
5171
|
-
await patchGitignore(
|
|
5291
|
+
await patchGitignore(join17(cwd, ".gitignore"));
|
|
5172
5292
|
const tsconfigDistResult = patchTsconfigExclude(cwd, "dist", "tsconfig.json");
|
|
5173
5293
|
if (tsconfigDistResult === "patched") {
|
|
5174
5294
|
logPatched("tsconfig.json", "excluded dist/ from server compilation");
|
|
@@ -5274,7 +5394,7 @@ ${green("\u2713")} Setup complete! Run: ${bold("nest start --watch")}
|
|
|
5274
5394
|
|
|
5275
5395
|
// src/cli/doctor.ts
|
|
5276
5396
|
function checkFileExists(cwd, file) {
|
|
5277
|
-
return existsSync(
|
|
5397
|
+
return existsSync(join18(cwd, file));
|
|
5278
5398
|
}
|
|
5279
5399
|
function readJson(path) {
|
|
5280
5400
|
try {
|
|
@@ -5310,15 +5430,15 @@ function writeJsonField(filePath, dotPath, value) {
|
|
|
5310
5430
|
}
|
|
5311
5431
|
function getPackageVersion(cwd, pkg) {
|
|
5312
5432
|
try {
|
|
5313
|
-
const pkgJson = readJson(
|
|
5433
|
+
const pkgJson = readJson(join18(cwd, "node_modules", pkg, "package.json"));
|
|
5314
5434
|
return pkgJson?.version ?? null;
|
|
5315
5435
|
} catch {
|
|
5316
5436
|
return null;
|
|
5317
5437
|
}
|
|
5318
5438
|
}
|
|
5319
5439
|
function detectPkgManager(cwd) {
|
|
5320
|
-
if (existsSync(
|
|
5321
|
-
if (existsSync(
|
|
5440
|
+
if (existsSync(join18(cwd, "pnpm-lock.yaml"))) return "pnpm";
|
|
5441
|
+
if (existsSync(join18(cwd, "yarn.lock"))) return "yarn";
|
|
5322
5442
|
return "npm";
|
|
5323
5443
|
}
|
|
5324
5444
|
async function runDoctor(opts) {
|
|
@@ -5356,7 +5476,7 @@ async function runDoctor(opts) {
|
|
|
5356
5476
|
autoFix: () => runInit({ cwd })
|
|
5357
5477
|
});
|
|
5358
5478
|
if (foundShellDir) {
|
|
5359
|
-
const nestCliPath =
|
|
5479
|
+
const nestCliPath = join18(cwd, "nest-cli.json");
|
|
5360
5480
|
const nestCli = readJson(nestCliPath);
|
|
5361
5481
|
const compiler = nestCli?.compilerOptions ?? {};
|
|
5362
5482
|
const assets = compiler.assets ?? [];
|
|
@@ -5395,7 +5515,7 @@ async function runDoctor(opts) {
|
|
|
5395
5515
|
fix: "Run: nestjs-codegen codegen",
|
|
5396
5516
|
autoFix: () => runCodegen({ cwd })
|
|
5397
5517
|
});
|
|
5398
|
-
const tsconfigPath =
|
|
5518
|
+
const tsconfigPath = join18(cwd, "tsconfig.json");
|
|
5399
5519
|
const tsconfig = readJson(tsconfigPath);
|
|
5400
5520
|
const paths = tsconfig?.compilerOptions?.paths;
|
|
5401
5521
|
checks.push({
|
|
@@ -5406,7 +5526,7 @@ async function runDoctor(opts) {
|
|
|
5406
5526
|
});
|
|
5407
5527
|
const inertiaDir = foundShellDir ?? "inertia";
|
|
5408
5528
|
for (const tsconfigFile of ["tsconfig.json", "tsconfig.build.json"]) {
|
|
5409
|
-
const tsc = readJson(
|
|
5529
|
+
const tsc = readJson(join18(cwd, tsconfigFile));
|
|
5410
5530
|
if (!tsc) continue;
|
|
5411
5531
|
const excl = tsc.exclude ?? [];
|
|
5412
5532
|
const excludesIt = excl.includes(inertiaDir);
|
|
@@ -5432,7 +5552,7 @@ async function runDoctor(opts) {
|
|
|
5432
5552
|
}
|
|
5433
5553
|
});
|
|
5434
5554
|
}
|
|
5435
|
-
const inertiaTsconfigPath =
|
|
5555
|
+
const inertiaTsconfigPath = join18(cwd, "tsconfig.inertia.json");
|
|
5436
5556
|
const inertiaTsconfig = readJson(inertiaTsconfigPath);
|
|
5437
5557
|
checks.push({
|
|
5438
5558
|
name: "tsconfig.inertia.json exists",
|
|
@@ -5484,7 +5604,7 @@ async function runDoctor(opts) {
|
|
|
5484
5604
|
fix: 'Add "nestjs-inertia.d.ts" to include array (resolves InertiaRegistry augmentation)'
|
|
5485
5605
|
});
|
|
5486
5606
|
}
|
|
5487
|
-
const innerTsconfigPath =
|
|
5607
|
+
const innerTsconfigPath = join18(cwd, "inertia", "tsconfig.json");
|
|
5488
5608
|
checks.push({
|
|
5489
5609
|
name: "inertia/tsconfig.json exists (VSCode picks up ~codegen alias)",
|
|
5490
5610
|
pass: existsSync(innerTsconfigPath),
|
|
@@ -5494,7 +5614,7 @@ async function runDoctor(opts) {
|
|
|
5494
5614
|
}
|
|
5495
5615
|
});
|
|
5496
5616
|
if (checkFileExists(cwd, "vite.config.ts")) {
|
|
5497
|
-
const viteContent = readFileSync4(
|
|
5617
|
+
const viteContent = readFileSync4(join18(cwd, "vite.config.ts"), "utf8");
|
|
5498
5618
|
checks.push({
|
|
5499
5619
|
name: "vite.config.ts has resolve.alias",
|
|
5500
5620
|
pass: viteContent.includes("resolve") && viteContent.includes("alias"),
|
|
@@ -5559,7 +5679,7 @@ async function runDoctor(opts) {
|
|
|
5559
5679
|
});
|
|
5560
5680
|
}
|
|
5561
5681
|
if (checkFileExists(cwd, ".gitignore")) {
|
|
5562
|
-
const gitignorePath =
|
|
5682
|
+
const gitignorePath = join18(cwd, ".gitignore");
|
|
5563
5683
|
const gitignore = readFileSync4(gitignorePath, "utf8");
|
|
5564
5684
|
checks.push({
|
|
5565
5685
|
name: ".gitignore includes .nestjs-inertia/",
|
|
@@ -5568,7 +5688,7 @@ async function runDoctor(opts) {
|
|
|
5568
5688
|
autoFix: () => appendFileSync(gitignorePath, "\n.nestjs-inertia/\n")
|
|
5569
5689
|
});
|
|
5570
5690
|
}
|
|
5571
|
-
const pkgJsonPath =
|
|
5691
|
+
const pkgJsonPath = join18(cwd, "package.json");
|
|
5572
5692
|
const pkgJson = readJson(pkgJsonPath);
|
|
5573
5693
|
const scripts = pkgJson?.scripts ?? {};
|
|
5574
5694
|
checks.push({
|