@dudousxd/nestjs-codegen 0.11.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/dist/index.d.cts CHANGED
@@ -45,6 +45,18 @@ declare function generate(config: ResolvedConfig, inputRoutes?: RouteDescriptor[
45
45
  interface Watcher {
46
46
  close(): Promise<void>;
47
47
  }
48
+ interface WatchOptions {
49
+ /**
50
+ * Run the initial discover + generate as fire-and-forget instead of awaiting it
51
+ * before returning. The lock is still acquired and the chokidar watchers are
52
+ * still set up synchronously; only the initial generate is backgrounded. Used by
53
+ * the Nest `onApplicationBootstrap` hook so codegen never blocks time-to-ready.
54
+ * The one-shot CLI leaves this `false` so the build step stays synchronous.
55
+ *
56
+ * @default false
57
+ */
58
+ deferInitialGenerate?: boolean;
59
+ }
48
60
  /**
49
61
  * Start two chokidar watchers:
50
62
  *
@@ -58,7 +70,7 @@ interface Watcher {
58
70
  * Both watchers share a single lock file in `config.codegen.outDir`. If another live process
59
71
  * already holds the lock, logs a warning and returns a no-op watcher.
60
72
  */
61
- declare function watch(config: ResolvedConfig, onChange?: () => void): Promise<Watcher>;
73
+ declare function watch(config: ResolvedConfig, onChange?: () => void, options?: WatchOptions): Promise<Watcher>;
62
74
 
63
75
  /**
64
76
  * Try to acquire an exclusive lock for a watcher in `outDir`.
@@ -73,6 +85,20 @@ declare function acquireLock(outDir: string): Promise<{
73
85
  release: () => Promise<void>;
74
86
  } | null>;
75
87
 
88
+ /**
89
+ * Persisted record of the last successful generate, written to
90
+ * `<outDir>/.codegen-manifest.json`. Used to skip regeneration when nothing
91
+ * relevant changed (see {@link isManifestFresh}).
92
+ */
93
+ interface CodegenManifest {
94
+ /** Lib version that produced the output. A lib upgrade invalidates the manifest. */
95
+ version: string;
96
+ /** Content hash over all generate inputs (source files + resolved config + version). */
97
+ hash: string;
98
+ /** Generated output files, relative to `outDir`, recorded after the last run. */
99
+ files: string[];
100
+ }
101
+
76
102
  /**
77
103
  * Renders the neutral {@link SchemaNode} IR to a TypeScript *type* expression
78
104
  * (not a validation-lib schema). Used to synthesize the hoisted structural type
@@ -296,6 +322,6 @@ interface FastDiscoveryOptions {
296
322
  }
297
323
  declare function discoverContractsFast(opts: FastDiscoveryOptions): Promise<RouteDescriptor[]>;
298
324
 
299
- declare const VERSION = "0.11.0";
325
+ declare const VERSION = "0.12.0";
300
326
 
301
- export { type ChainModuleRendererOptions, CodegenError, ConfigError, type FastDiscoveryOptions, type JsonSchema, type MocksEmitOptions, type OpenApiDocument, type OpenApiEmitOptions, type OpenApiInfo, RenderContext, RenderedModule, ResolvedConfig, RouteDescriptor, SchemaModule, SchemaNode, type TsTypeContext, UserConfig, VERSION, ValidationAdapter, type Watcher, acquireLock, buildMocksFile, buildOpenApiSpec, createChainModuleRenderer, defineConfig, discoverContractsFast, emitApi, emitForms, emitMocks, emitOpenApi, emitRoutes, extractSchemaFromDto, generate, loadConfig, renderTsType, resolveConfig, schemaModuleToJsonSchema, schemaNodeToJsonSchema, toObjectKey, typeNameFor, watch };
327
+ export { type ChainModuleRendererOptions, CodegenError, type CodegenManifest, ConfigError, type FastDiscoveryOptions, type JsonSchema, type MocksEmitOptions, type OpenApiDocument, type OpenApiEmitOptions, type OpenApiInfo, RenderContext, RenderedModule, ResolvedConfig, RouteDescriptor, SchemaModule, SchemaNode, type TsTypeContext, UserConfig, VERSION, ValidationAdapter, type WatchOptions, type Watcher, acquireLock, buildMocksFile, buildOpenApiSpec, createChainModuleRenderer, defineConfig, discoverContractsFast, emitApi, emitForms, emitMocks, emitOpenApi, emitRoutes, extractSchemaFromDto, generate, loadConfig, renderTsType, resolveConfig, schemaModuleToJsonSchema, schemaNodeToJsonSchema, toObjectKey, typeNameFor, watch };
package/dist/index.d.ts CHANGED
@@ -45,6 +45,18 @@ declare function generate(config: ResolvedConfig, inputRoutes?: RouteDescriptor[
45
45
  interface Watcher {
46
46
  close(): Promise<void>;
47
47
  }
48
+ interface WatchOptions {
49
+ /**
50
+ * Run the initial discover + generate as fire-and-forget instead of awaiting it
51
+ * before returning. The lock is still acquired and the chokidar watchers are
52
+ * still set up synchronously; only the initial generate is backgrounded. Used by
53
+ * the Nest `onApplicationBootstrap` hook so codegen never blocks time-to-ready.
54
+ * The one-shot CLI leaves this `false` so the build step stays synchronous.
55
+ *
56
+ * @default false
57
+ */
58
+ deferInitialGenerate?: boolean;
59
+ }
48
60
  /**
49
61
  * Start two chokidar watchers:
50
62
  *
@@ -58,7 +70,7 @@ interface Watcher {
58
70
  * Both watchers share a single lock file in `config.codegen.outDir`. If another live process
59
71
  * already holds the lock, logs a warning and returns a no-op watcher.
60
72
  */
61
- declare function watch(config: ResolvedConfig, onChange?: () => void): Promise<Watcher>;
73
+ declare function watch(config: ResolvedConfig, onChange?: () => void, options?: WatchOptions): Promise<Watcher>;
62
74
 
63
75
  /**
64
76
  * Try to acquire an exclusive lock for a watcher in `outDir`.
@@ -73,6 +85,20 @@ declare function acquireLock(outDir: string): Promise<{
73
85
  release: () => Promise<void>;
74
86
  } | null>;
75
87
 
88
+ /**
89
+ * Persisted record of the last successful generate, written to
90
+ * `<outDir>/.codegen-manifest.json`. Used to skip regeneration when nothing
91
+ * relevant changed (see {@link isManifestFresh}).
92
+ */
93
+ interface CodegenManifest {
94
+ /** Lib version that produced the output. A lib upgrade invalidates the manifest. */
95
+ version: string;
96
+ /** Content hash over all generate inputs (source files + resolved config + version). */
97
+ hash: string;
98
+ /** Generated output files, relative to `outDir`, recorded after the last run. */
99
+ files: string[];
100
+ }
101
+
76
102
  /**
77
103
  * Renders the neutral {@link SchemaNode} IR to a TypeScript *type* expression
78
104
  * (not a validation-lib schema). Used to synthesize the hoisted structural type
@@ -296,6 +322,6 @@ interface FastDiscoveryOptions {
296
322
  }
297
323
  declare function discoverContractsFast(opts: FastDiscoveryOptions): Promise<RouteDescriptor[]>;
298
324
 
299
- declare const VERSION = "0.11.0";
325
+ declare const VERSION = "0.12.0";
300
326
 
301
- export { type ChainModuleRendererOptions, CodegenError, ConfigError, type FastDiscoveryOptions, type JsonSchema, type MocksEmitOptions, type OpenApiDocument, type OpenApiEmitOptions, type OpenApiInfo, RenderContext, RenderedModule, ResolvedConfig, RouteDescriptor, SchemaModule, SchemaNode, type TsTypeContext, UserConfig, VERSION, ValidationAdapter, type Watcher, acquireLock, buildMocksFile, buildOpenApiSpec, createChainModuleRenderer, defineConfig, discoverContractsFast, emitApi, emitForms, emitMocks, emitOpenApi, emitRoutes, extractSchemaFromDto, generate, loadConfig, renderTsType, resolveConfig, schemaModuleToJsonSchema, schemaNodeToJsonSchema, toObjectKey, typeNameFor, watch };
327
+ export { type ChainModuleRendererOptions, CodegenError, type CodegenManifest, ConfigError, type FastDiscoveryOptions, type JsonSchema, type MocksEmitOptions, type OpenApiDocument, type OpenApiEmitOptions, type OpenApiInfo, RenderContext, RenderedModule, ResolvedConfig, RouteDescriptor, SchemaModule, SchemaNode, type TsTypeContext, UserConfig, VERSION, ValidationAdapter, type WatchOptions, type Watcher, acquireLock, buildMocksFile, buildOpenApiSpec, createChainModuleRenderer, defineConfig, discoverContractsFast, emitApi, emitForms, emitMocks, emitOpenApi, emitRoutes, extractSchemaFromDto, generate, loadConfig, renderTsType, resolveConfig, schemaModuleToJsonSchema, schemaNodeToJsonSchema, toObjectKey, typeNameFor, watch };
package/dist/index.js CHANGED
@@ -188,8 +188,8 @@ Run \`nestjs-codegen init\` to create a starter config.`
188
188
  }
189
189
 
190
190
  // src/generate.ts
191
- import { mkdir as mkdir9, writeFile as writeFile9 } from "fs/promises";
192
- import { dirname as dirname2, join as join12 } from "path";
191
+ import { mkdir as mkdir9, writeFile as writeFile10 } from "fs/promises";
192
+ import { dirname as dirname2, join as join13 } from "path";
193
193
 
194
194
  // src/discovery/pages.ts
195
195
  import { readFile } from "fs/promises";
@@ -2087,6 +2087,99 @@ function buildEmpty() {
2087
2087
  ].join("\n");
2088
2088
  }
2089
2089
 
2090
+ // src/generate-manifest.ts
2091
+ import { createHash } from "crypto";
2092
+ import { readFile as readFile2, readdir, writeFile as writeFile9 } from "fs/promises";
2093
+ import { join as join12, relative as relative6 } from "path";
2094
+ import fg2 from "fast-glob";
2095
+ var MANIFEST_FILE = ".codegen-manifest.json";
2096
+ var LOCK_FILE = ".watcher.lock";
2097
+ function isManifestShape(value) {
2098
+ if (typeof value !== "object" || value === null) return false;
2099
+ const candidate = value;
2100
+ if (typeof candidate.version !== "string") return false;
2101
+ if (typeof candidate.hash !== "string") return false;
2102
+ if (!Array.isArray(candidate.files)) return false;
2103
+ return candidate.files.every((entry) => typeof entry === "string");
2104
+ }
2105
+ function serializeConfig(config) {
2106
+ try {
2107
+ return JSON.stringify(config, (_key, value) => {
2108
+ if (typeof value === "function") return `[fn:${value.name}]${value.toString()}`;
2109
+ return value;
2110
+ });
2111
+ } catch {
2112
+ return `unserializable:${config.codegen.outDir}:${config.contracts.glob}`;
2113
+ }
2114
+ }
2115
+ async function discoverInputFiles(config) {
2116
+ const globs = [config.contracts.glob, config.forms.watch];
2117
+ if (config.pages) globs.push(config.pages.glob);
2118
+ const cwd = config.codegen.cwd;
2119
+ const matched = await fg2(globs, { cwd, absolute: true, onlyFiles: true });
2120
+ return [...new Set(matched)].sort();
2121
+ }
2122
+ async function computeInputsHash(config) {
2123
+ const hash = createHash("sha256");
2124
+ hash.update(`version:${VERSION}
2125
+ `);
2126
+ hash.update(`config:${serializeConfig(config)}
2127
+ `);
2128
+ const inputFiles = await discoverInputFiles(config);
2129
+ const cwd = config.codegen.cwd;
2130
+ for (const file of inputFiles) {
2131
+ const contents = await readFile2(file, "utf8");
2132
+ hash.update(`file:${relative6(cwd, file)}
2133
+ `);
2134
+ hash.update(contents);
2135
+ hash.update("\n");
2136
+ }
2137
+ return hash.digest("hex");
2138
+ }
2139
+ async function readManifest(outDir) {
2140
+ try {
2141
+ const raw = await readFile2(join12(outDir, MANIFEST_FILE), "utf8");
2142
+ const parsed = JSON.parse(raw);
2143
+ if (!isManifestShape(parsed)) return null;
2144
+ return { version: parsed.version, hash: parsed.hash, files: parsed.files };
2145
+ } catch {
2146
+ return null;
2147
+ }
2148
+ }
2149
+ async function writeManifest(outDir, manifest) {
2150
+ await writeFile9(join12(outDir, MANIFEST_FILE), `${JSON.stringify(manifest, null, 2)}
2151
+ `, "utf8");
2152
+ }
2153
+ async function listOutputFiles(outDir) {
2154
+ const found = [];
2155
+ async function walk(dir) {
2156
+ const entries = await readdir(dir, { withFileTypes: true }).catch(() => []);
2157
+ for (const entry of entries) {
2158
+ const abs = join12(dir, entry.name);
2159
+ if (entry.isDirectory()) {
2160
+ await walk(abs);
2161
+ } else if (entry.isFile()) {
2162
+ const rel = relative6(outDir, abs);
2163
+ if (rel === MANIFEST_FILE || rel === LOCK_FILE) continue;
2164
+ found.push(rel);
2165
+ }
2166
+ }
2167
+ }
2168
+ await walk(outDir);
2169
+ return found.sort();
2170
+ }
2171
+ async function allOutputsExist(outDir, files) {
2172
+ const present = new Set(await listOutputFiles(outDir));
2173
+ return files.every((file) => present.has(file));
2174
+ }
2175
+ async function isManifestFresh(outDir, manifest, inputsHash) {
2176
+ if (manifest === null) return false;
2177
+ if (manifest.version !== VERSION) return false;
2178
+ if (manifest.hash !== inputsHash) return false;
2179
+ if (manifest.files.length === 0) return false;
2180
+ return allOutputsExist(outDir, manifest.files);
2181
+ }
2182
+
2090
2183
  // src/util/debug-log.ts
2091
2184
  var debugEnabled = false;
2092
2185
  function setCodegenDebug(enabled) {
@@ -2099,6 +2192,12 @@ function debugWarn(message) {
2099
2192
  // src/generate.ts
2100
2193
  async function generate(config, inputRoutes = []) {
2101
2194
  setCodegenDebug(config.debug);
2195
+ const inputsHash = await computeInputsHash(config);
2196
+ const manifest = await readManifest(config.codegen.outDir);
2197
+ if (await isManifestFresh(config.codegen.outDir, manifest, inputsHash)) {
2198
+ console.log(`[nestjs-codegen] ${config.codegen.outDir} up to date, skipped`);
2199
+ return;
2200
+ }
2102
2201
  const extensions = config.extensions ?? [];
2103
2202
  let routes = inputRoutes;
2104
2203
  const ctx = createExtensionContext(config, () => routes);
@@ -2155,21 +2254,27 @@ async function generate(config, inputRoutes = []) {
2155
2254
  if (extensions.length > 0) {
2156
2255
  const extraFiles = await collectEmittedFiles(extensions, ctx);
2157
2256
  for (const file of extraFiles) {
2158
- const dest = join12(config.codegen.outDir, file.path);
2257
+ const dest = join13(config.codegen.outDir, file.path);
2159
2258
  await mkdir9(dirname2(dest), { recursive: true });
2160
- await writeFile9(dest, file.contents, "utf8");
2259
+ await writeFile10(dest, file.contents, "utf8");
2161
2260
  }
2162
2261
  }
2262
+ const outputFiles = await listOutputFiles(config.codegen.outDir);
2263
+ await writeManifest(config.codegen.outDir, {
2264
+ version: VERSION,
2265
+ hash: inputsHash,
2266
+ files: outputFiles
2267
+ });
2163
2268
  }
2164
2269
 
2165
2270
  // src/watch/watcher.ts
2166
- import { readFile as readFile3 } from "fs/promises";
2167
- import { join as join15 } from "path";
2271
+ import { readFile as readFile4 } from "fs/promises";
2272
+ import { join as join16 } from "path";
2168
2273
  import chokidar from "chokidar";
2169
2274
 
2170
2275
  // src/discovery/contracts-fast.ts
2171
- import { join as join13, resolve as resolve3 } from "path";
2172
- import fg2 from "fast-glob";
2276
+ import { join as join14, resolve as resolve3 } from "path";
2277
+ import fg3 from "fast-glob";
2173
2278
  import {
2174
2279
  Node as Node8,
2175
2280
  Project as Project3
@@ -3946,7 +4051,7 @@ async function discoverContractsFast(opts) {
3946
4051
  const { cwd, glob, tsconfig } = opts;
3947
4052
  const tsconfigPath = resolveTsconfigPath(cwd, tsconfig);
3948
4053
  const project = createDiscoveryProject(tsconfigPath);
3949
- const files = await fg2(glob, { cwd, absolute: true, onlyFiles: true });
4054
+ const files = await fg3(glob, { cwd, absolute: true, onlyFiles: true });
3950
4055
  for (const f of files) {
3951
4056
  project.addSourceFileAtPath(f);
3952
4057
  }
@@ -3954,7 +4059,7 @@ async function discoverContractsFast(opts) {
3954
4059
  return extractAllRoutes(project);
3955
4060
  }
3956
4061
  function resolveTsconfigPath(cwd, tsconfig) {
3957
- return tsconfig ? resolve3(tsconfig) : join13(cwd, "tsconfig.json");
4062
+ return tsconfig ? resolve3(tsconfig) : join14(cwd, "tsconfig.json");
3958
4063
  }
3959
4064
  function createDiscoveryProject(tsconfigPath) {
3960
4065
  try {
@@ -4019,7 +4124,7 @@ var PersistentDiscovery = class _PersistentDiscovery {
4019
4124
  const project = createDiscoveryProject(tsconfigPath);
4020
4125
  bindDiscoveryContext(project, cwd, tsconfigPath);
4021
4126
  const instance = new _PersistentDiscovery(project, cwd, glob);
4022
- const files = await fg2(glob, { cwd, absolute: true, onlyFiles: true });
4127
+ const files = await fg3(glob, { cwd, absolute: true, onlyFiles: true });
4023
4128
  for (const f of files) {
4024
4129
  project.addSourceFileAtPath(f);
4025
4130
  instance.controllerPaths.add(f);
@@ -4048,7 +4153,7 @@ var PersistentDiscovery = class _PersistentDiscovery {
4048
4153
  }
4049
4154
  }
4050
4155
  const globbed = new Set(
4051
- await fg2(this.glob, { cwd: this.cwd, absolute: true, onlyFiles: true })
4156
+ await fg3(this.glob, { cwd: this.cwd, absolute: true, onlyFiles: true })
4052
4157
  );
4053
4158
  for (const f of globbed) {
4054
4159
  if (!this.controllerPaths.has(f)) {
@@ -4329,9 +4434,9 @@ function extractFromSourceFile(sourceFile, project) {
4329
4434
 
4330
4435
  // src/watch/lock-file.ts
4331
4436
  import { open } from "fs/promises";
4332
- import { mkdir as mkdir10, readFile as readFile2, unlink } from "fs/promises";
4333
- import { join as join14 } from "path";
4334
- var LOCK_FILE = ".watcher.lock";
4437
+ import { mkdir as mkdir10, readFile as readFile3, unlink } from "fs/promises";
4438
+ import { join as join15 } from "path";
4439
+ var LOCK_FILE2 = ".watcher.lock";
4335
4440
  function isProcessAlive(pid) {
4336
4441
  try {
4337
4442
  process.kill(pid, 0);
@@ -4342,7 +4447,7 @@ function isProcessAlive(pid) {
4342
4447
  }
4343
4448
  async function acquireLock(outDir) {
4344
4449
  await mkdir10(outDir, { recursive: true });
4345
- const lockPath = join14(outDir, LOCK_FILE);
4450
+ const lockPath = join15(outDir, LOCK_FILE2);
4346
4451
  const lockData = { pid: process.pid, startedAt: (/* @__PURE__ */ new Date()).toISOString() };
4347
4452
  try {
4348
4453
  const fd = await open(lockPath, "wx");
@@ -4352,7 +4457,7 @@ async function acquireLock(outDir) {
4352
4457
  } catch (err) {
4353
4458
  if (err.code === "EEXIST") {
4354
4459
  try {
4355
- const raw = await readFile2(lockPath, "utf8");
4460
+ const raw = await readFile3(lockPath, "utf8");
4356
4461
  const existing = JSON.parse(raw);
4357
4462
  if (isProcessAlive(existing.pid)) return null;
4358
4463
  await unlink(lockPath);
@@ -4377,12 +4482,12 @@ async function acquireLock(outDir) {
4377
4482
  var PAGES_DEBOUNCE_MS = 150;
4378
4483
  var NO_OP_WATCHER = { close: async () => {
4379
4484
  } };
4380
- async function watch(config, onChange) {
4485
+ async function watch(config, onChange, options = {}) {
4381
4486
  const lock = await acquireLock(config.codegen.outDir);
4382
4487
  if (lock === null) {
4383
4488
  let holderPid = "unknown";
4384
4489
  try {
4385
- const raw = await readFile3(join15(config.codegen.outDir, ".watcher.lock"), "utf8");
4490
+ const raw = await readFile4(join16(config.codegen.outDir, ".watcher.lock"), "utf8");
4386
4491
  const data = JSON.parse(raw);
4387
4492
  if (data.pid !== void 0) holderPid = String(data.pid);
4388
4493
  } catch {
@@ -4405,22 +4510,33 @@ async function watch(config, onChange) {
4405
4510
  }
4406
4511
  return discovery;
4407
4512
  }
4408
- try {
4409
- const initialRoutes = (await getDiscovery()).discover();
4410
- lastRoutes = initialRoutes;
4411
- await generate(config, initialRoutes);
4412
- } catch (err) {
4413
- console.warn(
4414
- `[nestjs-codegen] Initial route discovery failed, falling back to pages-only: ${err instanceof Error ? err.message : String(err)}`
4415
- );
4513
+ async function runInitialPass() {
4416
4514
  try {
4417
- await generate(config, lastRoutes);
4418
- } catch {
4515
+ const initialRoutes = (await getDiscovery()).discover();
4516
+ lastRoutes = initialRoutes;
4517
+ await generate(config, initialRoutes);
4518
+ } catch (err) {
4519
+ console.warn(
4520
+ `[nestjs-codegen] Initial route discovery failed, falling back to pages-only: ${err instanceof Error ? err.message : String(err)}`
4521
+ );
4522
+ try {
4523
+ await generate(config, lastRoutes);
4524
+ } catch {
4525
+ }
4419
4526
  }
4420
4527
  }
4528
+ if (options.deferInitialGenerate) {
4529
+ void runInitialPass().catch((err) => {
4530
+ console.warn(
4531
+ `[nestjs-codegen] Background initial generate failed: ${err instanceof Error ? err.message : String(err)}`
4532
+ );
4533
+ });
4534
+ } else {
4535
+ await runInitialPass();
4536
+ }
4421
4537
  let pagesDebounceTimer;
4422
4538
  const pagesGlob = config.pages?.glob ?? ".nestjs-codegen-no-pages";
4423
- const pagesWatcher = chokidar.watch(join15(config.codegen.cwd, pagesGlob), {
4539
+ const pagesWatcher = chokidar.watch(join16(config.codegen.cwd, pagesGlob), {
4424
4540
  ignoreInitial: true,
4425
4541
  persistent: true,
4426
4542
  awaitWriteFinish: { stabilityThreshold: 80, pollInterval: 20 }
@@ -4447,7 +4563,7 @@ async function watch(config, onChange) {
4447
4563
  pagesWatcher.on("unlink", schedulePagesRegenerate);
4448
4564
  let contractsDebounceTimer;
4449
4565
  const pendingChangedPaths = /* @__PURE__ */ new Set();
4450
- const contractsWatcher = chokidar.watch(join15(config.codegen.cwd, config.contracts.glob), {
4566
+ const contractsWatcher = chokidar.watch(join16(config.codegen.cwd, config.contracts.glob), {
4451
4567
  ignoreInitial: true,
4452
4568
  persistent: true,
4453
4569
  awaitWriteFinish: { stabilityThreshold: 80, pollInterval: 20 }
@@ -4477,7 +4593,7 @@ async function watch(config, onChange) {
4477
4593
  contractsWatcher.on("add", (p) => scheduleContractsRegenerate(p));
4478
4594
  contractsWatcher.on("change", (p) => scheduleContractsRegenerate(p));
4479
4595
  contractsWatcher.on("unlink", (p) => scheduleContractsRegenerate(p));
4480
- const formsWatcher = chokidar.watch(join15(config.codegen.cwd, config.forms.watch), {
4596
+ const formsWatcher = chokidar.watch(join16(config.codegen.cwd, config.forms.watch), {
4481
4597
  ignoreInitial: true,
4482
4598
  persistent: true,
4483
4599
  awaitWriteFinish: { stabilityThreshold: 80, pollInterval: 20 }
@@ -4587,7 +4703,7 @@ function createChainModuleRenderer(opts) {
4587
4703
  }
4588
4704
 
4589
4705
  // src/index.ts
4590
- var VERSION = "0.11.0";
4706
+ var VERSION = "0.12.0";
4591
4707
  export {
4592
4708
  CodegenError,
4593
4709
  ConfigError,