@rexeus/typeweaver 0.10.4 → 0.10.5

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.
@@ -9,12 +9,52 @@ import os from "node:os";
9
9
  import { build } from "rolldown";
10
10
  import { createHash } from "node:crypto";
11
11
  import { HttpMethod, HttpStatusCode } from "@rexeus/typeweaver-core";
12
+ //#region src/errors/InvalidConfigExportError.ts
13
+ var InvalidConfigExportError = class extends Error {
14
+ name = "InvalidConfigExportError";
15
+ constructor(configPath, reason) {
16
+ super(getInvalidConfigExportMessage(configPath, reason));
17
+ this.configPath = configPath;
18
+ this.reason = reason;
19
+ }
20
+ };
21
+ const getInvalidConfigExportMessage = (configPath, reason) => {
22
+ switch (reason) {
23
+ case "both-default-and-named-config": return `Configuration file '${configPath}' must choose one export style: use either 'export default' or 'export const config = ...', but not both.`;
24
+ case "default-namespace-wrapper": return `Configuration file '${configPath}' default export must be the config object itself, not a module namespace-like wrapper. Export the config directly with 'export default { ... }' or use 'export const config = ...'.`;
25
+ case "missing-config-export": return `Configuration file '${configPath}' must export its config via 'export default' or 'export const config = ...'.`;
26
+ case "non-object-config": return `Configuration file '${configPath}' must export a config object via 'export default' or 'export const config = ...'.`;
27
+ }
28
+ };
29
+ //#endregion
30
+ //#region src/errors/UnsupportedConfigExtensionError.ts
31
+ var UnsupportedConfigExtensionError = class extends Error {
32
+ name = "UnsupportedConfigExtensionError";
33
+ constructor(configPath, extension, supportedExtensions) {
34
+ super(`Unsupported config file extension '${extension}' for '${configPath}'. TypeWeaver accepts only these config extensions: ${supportedExtensions.join(", ")}.`);
35
+ this.configPath = configPath;
36
+ this.extension = extension;
37
+ this.supportedExtensions = supportedExtensions;
38
+ }
39
+ };
40
+ //#endregion
41
+ //#region src/errors/UnsupportedTypeScriptConfigError.ts
42
+ var UnsupportedTypeScriptConfigError = class extends Error {
43
+ name = "UnsupportedTypeScriptConfigError";
44
+ constructor(configPath, extension) {
45
+ super(`TypeScript config files are not supported: '${configPath}' uses '${extension}'. Use a JavaScript config file with one of these extensions: .js, .mjs, or .cjs.`);
46
+ this.configPath = configPath;
47
+ this.extension = extension;
48
+ }
49
+ };
50
+ //#endregion
12
51
  //#region src/configLoader.ts
13
- const SUPPORTED_CONFIG_EXTENSIONS = new Set([
52
+ const SUPPORTED_CONFIG_EXTENSIONS = [
14
53
  ".js",
15
54
  ".mjs",
16
55
  ".cjs"
17
- ]);
56
+ ];
57
+ const SUPPORTED_CONFIG_EXTENSION_SET = new Set(SUPPORTED_CONFIG_EXTENSIONS);
18
58
  const UNSUPPORTED_TYPESCRIPT_CONFIG_EXTENSIONS = new Set([
19
59
  ".ts",
20
60
  ".mts",
@@ -25,25 +65,25 @@ const getResolvedConfigPath = (configPath, currentWorkingDirectory = process.cwd
25
65
  };
26
66
  const assertSupportedConfigPath = (configPath) => {
27
67
  const extension = path.extname(configPath).toLowerCase();
28
- if (UNSUPPORTED_TYPESCRIPT_CONFIG_EXTENSIONS.has(extension)) throw new Error(`TypeScript config files are no longer supported: '${configPath}'. Convert the config to .js, .mjs, or .cjs, or compile it before passing --config.`);
29
- if (!SUPPORTED_CONFIG_EXTENSIONS.has(extension)) throw new Error(`Unsupported config file extension for '${configPath}'. TypeWeaver only accepts .js, .mjs, or .cjs config files.`);
68
+ if (UNSUPPORTED_TYPESCRIPT_CONFIG_EXTENSIONS.has(extension)) throw new UnsupportedTypeScriptConfigError(configPath, extension);
69
+ if (!SUPPORTED_CONFIG_EXTENSION_SET.has(extension)) throw new UnsupportedConfigExtensionError(configPath, extension, SUPPORTED_CONFIG_EXTENSIONS);
30
70
  };
31
71
  const loadConfig = async (configPath) => {
32
72
  assertSupportedConfigPath(configPath);
33
73
  const loadedConfig = getConfigExport(await import(pathToFileURL(path.resolve(configPath)).toString()), configPath);
34
- if (!isConfigObject(loadedConfig)) throw new Error(`Configuration file '${configPath}' must export a config object via 'export default' or 'export const config = ...'.`);
74
+ if (!isConfigObject(loadedConfig)) throw new InvalidConfigExportError(configPath, "non-object-config");
35
75
  return loadedConfig;
36
76
  };
37
77
  const getConfigExport = (configModule, configPath) => {
38
78
  const hasDefaultExport = Object.hasOwn(configModule, "default");
39
79
  const hasNamedConfigExport = Object.hasOwn(configModule, "config");
40
- if (hasDefaultExport && hasNamedConfigExport) throw new Error(`Configuration file '${configPath}' must choose a single export style: either 'export default' or 'export const config = ...', but not both.`);
80
+ if (hasDefaultExport && hasNamedConfigExport) throw new InvalidConfigExportError(configPath, "both-default-and-named-config");
41
81
  if (hasDefaultExport) {
42
- if (isNamespaceLikeConfigExport(configModule.default)) throw new Error(`Configuration file '${configPath}' default export must be the config object itself, not a module namespace-like wrapper. Export the config directly with 'export default { ... }' or use 'export const config = ...'.`);
82
+ if (isNamespaceLikeConfigExport(configModule.default)) throw new InvalidConfigExportError(configPath, "default-namespace-wrapper");
43
83
  return configModule.default;
44
84
  }
45
85
  if (hasNamedConfigExport) return configModule.config;
46
- throw new Error(`Configuration file '${configPath}' must export its config via 'export default' or 'export const config = ...'.`);
86
+ throw new InvalidConfigExportError(configPath, "missing-config-export");
47
87
  };
48
88
  const isConfigObject = (value) => {
49
89
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -53,6 +93,35 @@ const isNamespaceLikeConfigExport = (value) => {
53
93
  return Object.hasOwn(value, "default") || Object.hasOwn(value, "config");
54
94
  };
55
95
  //#endregion
96
+ //#region src/generators/errors/UnsafeCleanTargetError.ts
97
+ var UnsafeCleanTargetError = class extends Error {
98
+ name = "UnsafeCleanTargetError";
99
+ resolvedOutputDir;
100
+ currentWorkingDirectory;
101
+ protectedWorkspaceRoot;
102
+ filesystemRoot;
103
+ constructor(outputDir, reason, diagnostics = {}) {
104
+ super(getUnsafeCleanTargetMessage(outputDir, reason, diagnostics));
105
+ this.outputDir = outputDir;
106
+ this.reason = reason;
107
+ this.resolvedOutputDir = diagnostics.resolvedOutputDir;
108
+ this.currentWorkingDirectory = diagnostics.currentWorkingDirectory;
109
+ this.protectedWorkspaceRoot = diagnostics.protectedWorkspaceRoot;
110
+ this.filesystemRoot = diagnostics.filesystemRoot;
111
+ }
112
+ };
113
+ const getUnsafeCleanTargetMessage = (outputDir, reason, diagnostics) => {
114
+ const targetDescription = `Refusing to clean '${outputDir}'`;
115
+ const suffix = "Use a dedicated generated output directory instead.";
116
+ switch (reason) {
117
+ case "empty-path": return `Refusing to clean an empty output directory path. ${suffix}`;
118
+ case "filesystem-root": return `${targetDescription} because it resolves to the filesystem root '${diagnostics.filesystemRoot ?? diagnostics.resolvedOutputDir ?? outputDir}'. ${suffix}`;
119
+ case "current-working-directory": return `${targetDescription} because it resolves to the current working directory '${diagnostics.currentWorkingDirectory ?? diagnostics.resolvedOutputDir ?? outputDir}'. ${suffix}`;
120
+ case "workspace-root": return `${targetDescription} because it resolves to the protected workspace root '${diagnostics.protectedWorkspaceRoot ?? diagnostics.resolvedOutputDir ?? outputDir}'. ${suffix}`;
121
+ case "ancestor-of-current-working-directory": return `${targetDescription} because it resolves to an ancestor directory of the current working directory '${diagnostics.currentWorkingDirectory ?? ""}'. ${suffix}`;
122
+ }
123
+ };
124
+ //#endregion
56
125
  //#region src/generators/formatter.ts
57
126
  async function formatCode(outputDir, startDir) {
58
127
  const format = await loadFormatter();
@@ -254,6 +323,17 @@ function reportSuccessfulLoads(successful) {
254
323
  }
255
324
  }
256
325
  //#endregion
326
+ //#region src/generators/spec/errors/SpecBundleOutputMissingError.ts
327
+ var SpecBundleOutputMissingError = class extends Error {
328
+ name = "SpecBundleOutputMissingError";
329
+ constructor(inputFile, bundledSpecFile, specOutputDir) {
330
+ super(`Spec bundling completed but did not create the expected output '${bundledSpecFile}' for entrypoint '${inputFile}'. Expected the bundle inside '${specOutputDir}'.`);
331
+ this.inputFile = inputFile;
332
+ this.bundledSpecFile = bundledSpecFile;
333
+ this.specOutputDir = specOutputDir;
334
+ }
335
+ };
336
+ //#endregion
257
337
  //#region src/generators/spec/specBundler.ts
258
338
  const WINDOWS_ABSOLUTE_PATH_PATTERN = /^[A-Za-z]:[\\/]/;
259
339
  const WINDOWS_UNC_PATH_PATTERN = /^\\\\/;
@@ -267,7 +347,7 @@ function createWrapperImportSpecifier(wrapperFile, inputFile) {
267
347
  if (relativeInputFile.startsWith(".") || relativeInputFile.startsWith("..")) return relativeInputFile;
268
348
  return `./${relativeInputFile}`;
269
349
  }
270
- async function bundle(config) {
350
+ async function bundle(config, deps = {}) {
271
351
  const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "typeweaver-spec-loader-"));
272
352
  const wrapperFile = path.join(tempDir, "spec-entrypoint.ts");
273
353
  const bundledSpecFile = path.join(config.specOutputDir, "spec.js");
@@ -283,7 +363,7 @@ async function bundle(config) {
283
363
  ""
284
364
  ].join("\n"));
285
365
  try {
286
- await build({
366
+ await (deps.build ?? build)({
287
367
  cwd: tempDir,
288
368
  input: wrapperFile,
289
369
  treeshake: true,
@@ -303,7 +383,7 @@ async function bundle(config) {
303
383
  force: true
304
384
  });
305
385
  }
306
- if (!fs.existsSync(bundledSpecFile)) throw new Error(`Failed to bundle spec entrypoint '${config.inputFile}' to '${bundledSpecFile}'.`);
386
+ if (!(deps.existsSync ?? fs.existsSync)(bundledSpecFile)) throw new SpecBundleOutputMissingError(config.inputFile, bundledSpecFile, config.specOutputDir);
307
387
  return bundledSpecFile;
308
388
  }
309
389
  function resolveBundledInputFile(inputFile) {
@@ -385,17 +465,32 @@ function writeSpecDeclarationFile(specOutputDir) {
385
465
  const moduleDir$1 = path.dirname(fileURLToPath(import.meta.url));
386
466
  const assertSafeCleanTarget = (outputDir, currentWorkingDirectory) => {
387
467
  const trimmedOutputDir = outputDir.trim();
388
- if (trimmedOutputDir.length === 0) throw new Error("Refusing to clean an empty output directory path. Pass a dedicated generated output directory instead.");
468
+ if (trimmedOutputDir.length === 0) throw new UnsafeCleanTargetError(outputDir, "empty-path");
389
469
  const resolvedWorkingDirectory = path.resolve(currentWorkingDirectory);
390
470
  const canonicalWorkingDirectory = fs.realpathSync.native(resolvedWorkingDirectory);
391
471
  const resolvedOutputDir = path.resolve(resolvedWorkingDirectory, trimmedOutputDir);
392
472
  const canonicalOutputDir = canonicalizePathForContainment(resolvedOutputDir);
393
- if (canonicalOutputDir === path.parse(canonicalOutputDir).root) throw new Error(`Refusing to clean '${outputDir}' because it resolves to the filesystem root.`);
394
- if (resolvedOutputDir === resolvedWorkingDirectory || canonicalOutputDir === canonicalWorkingDirectory) throw new Error(`Refusing to clean '${outputDir}' because it resolves to the current working directory.`);
473
+ const filesystemRoot = path.parse(canonicalOutputDir).root;
474
+ if (canonicalOutputDir === filesystemRoot) throw new UnsafeCleanTargetError(outputDir, "filesystem-root", {
475
+ resolvedOutputDir,
476
+ currentWorkingDirectory: resolvedWorkingDirectory,
477
+ filesystemRoot
478
+ });
479
+ if (resolvedOutputDir === resolvedWorkingDirectory || canonicalOutputDir === canonicalWorkingDirectory) throw new UnsafeCleanTargetError(outputDir, "current-working-directory", {
480
+ resolvedOutputDir,
481
+ currentWorkingDirectory: resolvedWorkingDirectory
482
+ });
395
483
  const protectedWorkspaceRoots = [findProtectedWorkspaceRoot(resolvedWorkingDirectory), findProtectedWorkspaceRoot(canonicalWorkingDirectory)].filter((root) => root !== void 0);
396
484
  const protectedWorkspaceRootTarget = protectedWorkspaceRoots.find((protectedWorkspaceRoot) => resolvedOutputDir === protectedWorkspaceRoot || canonicalOutputDir === fs.realpathSync.native(protectedWorkspaceRoot));
397
- if (protectedWorkspaceRootTarget !== void 0) throw new Error(`Refusing to clean '${outputDir}' because it resolves to the inferred workspace root '${protectedWorkspaceRootTarget}'. Choose a dedicated output subdirectory instead.`);
398
- if (protectedWorkspaceRoots.length > 0 && (isSameOrDescendantOf(resolvedWorkingDirectory, resolvedOutputDir) || isSameOrDescendantOf(canonicalWorkingDirectory, canonicalOutputDir))) throw new Error(`Refusing to clean '${outputDir}' because it resolves to an ancestor directory of the current working directory. Choose a dedicated output subdirectory instead.`);
485
+ if (protectedWorkspaceRootTarget !== void 0) throw new UnsafeCleanTargetError(outputDir, "workspace-root", {
486
+ resolvedOutputDir,
487
+ currentWorkingDirectory: resolvedWorkingDirectory,
488
+ protectedWorkspaceRoot: protectedWorkspaceRootTarget
489
+ });
490
+ if (protectedWorkspaceRoots.length > 0 && (isSameOrDescendantOf(resolvedWorkingDirectory, resolvedOutputDir) || isSameOrDescendantOf(canonicalWorkingDirectory, canonicalOutputDir))) throw new UnsafeCleanTargetError(outputDir, "ancestor-of-current-working-directory", {
491
+ resolvedOutputDir,
492
+ currentWorkingDirectory: resolvedWorkingDirectory
493
+ });
399
494
  };
400
495
  /**
401
496
  * Main generator for typeweaver
@@ -508,6 +603,40 @@ const isSameOrDescendantOf = (directory, ancestor) => {
508
603
  return relativePath === "" || !escapesAncestor && !path.isAbsolute(relativePath);
509
604
  };
510
605
  //#endregion
606
+ //#region src/errors/MissingGenerateOptionError.ts
607
+ var MissingGenerateOptionError = class extends Error {
608
+ name = "MissingGenerateOptionError";
609
+ constructor(optionName, flag, configKey) {
610
+ super(`Missing required generate option '${optionName}'. Pass ${flag} or set '${configKey}' in the TypeWeaver config file.`);
611
+ this.optionName = optionName;
612
+ this.flag = flag;
613
+ this.configKey = configKey;
614
+ }
615
+ };
616
+ //#endregion
617
+ //#region src/resolveGenerateOptions.ts
618
+ const resolveGenerateOptions = (options, config, currentWorkingDirectory) => {
619
+ const inputPath = options.input ?? config.input;
620
+ const outputDir = options.output ?? config.output;
621
+ if (!inputPath) throw new MissingGenerateOptionError("input", "--input", "input");
622
+ if (!outputDir) throw new MissingGenerateOptionError("output", "--output", "output");
623
+ const resolvedInputPath = path.isAbsolute(inputPath) ? inputPath : path.join(currentWorkingDirectory, inputPath);
624
+ const resolvedOutputDir = path.isAbsolute(outputDir) ? outputDir : path.join(currentWorkingDirectory, outputDir);
625
+ const finalConfig = {
626
+ input: resolvedInputPath,
627
+ output: resolvedOutputDir,
628
+ format: options.format ?? config.format ?? true,
629
+ clean: options.clean ?? config.clean ?? true
630
+ };
631
+ if (options.plugins) finalConfig.plugins = options.plugins.split(",").map((plugin) => plugin.trim());
632
+ else if (config.plugins) finalConfig.plugins = config.plugins;
633
+ return {
634
+ inputPath: resolvedInputPath,
635
+ outputDir: resolvedOutputDir,
636
+ config: finalConfig
637
+ };
638
+ };
639
+ //#endregion
511
640
  //#region src/cli.ts
512
641
  const moduleDir = path.dirname(fileURLToPath(import.meta.url));
513
642
  const packageJson = JSON.parse(fs.readFileSync(path.join(moduleDir, "../package.json"), "utf-8"));
@@ -527,21 +656,8 @@ program.command("generate").description("Generate types, validators, and clients
527
656
  process.exit(1);
528
657
  }
529
658
  }
530
- const inputPath = options.input ?? config.input;
531
- const outputDir = options.output ?? config.output;
532
- if (!inputPath) throw new Error("No input spec entrypoint provided. Use --input or specify in config file.");
533
- if (!outputDir) throw new Error("No output directory provided. Use --output or specify in config file.");
534
- const resolvedInputPath = path.isAbsolute(inputPath) ? inputPath : path.join(execDir, inputPath);
535
- const resolvedOutputDir = path.isAbsolute(outputDir) ? outputDir : path.join(execDir, outputDir);
536
- const finalConfig = {
537
- input: resolvedInputPath,
538
- output: resolvedOutputDir,
539
- format: options.format ?? config.format ?? true,
540
- clean: options.clean ?? config.clean ?? true
541
- };
542
- if (options.plugins) finalConfig.plugins = options.plugins.split(",").map((p) => p.trim());
543
- else if (config.plugins) finalConfig.plugins = config.plugins;
544
- return new Generator().generate(resolvedInputPath, resolvedOutputDir, finalConfig, execDir);
659
+ const resolvedGenerateOptions = resolveGenerateOptions(options, config, execDir);
660
+ return new Generator().generate(resolvedGenerateOptions.inputPath, resolvedGenerateOptions.outputDir, resolvedGenerateOptions.config, execDir);
545
661
  });
546
662
  program.command("init").description("Initialize a new typeweaver project (coming soon)").action(() => {
547
663
  console.log("The init command is coming soon!");
package/dist/cli.cjs CHANGED
@@ -33,12 +33,52 @@ node_os = __toESM(node_os);
33
33
  let rolldown = require("rolldown");
34
34
  let node_crypto = require("node:crypto");
35
35
  let _rexeus_typeweaver_core = require("@rexeus/typeweaver-core");
36
+ //#region src/errors/InvalidConfigExportError.ts
37
+ var InvalidConfigExportError = class extends Error {
38
+ name = "InvalidConfigExportError";
39
+ constructor(configPath, reason) {
40
+ super(getInvalidConfigExportMessage(configPath, reason));
41
+ this.configPath = configPath;
42
+ this.reason = reason;
43
+ }
44
+ };
45
+ const getInvalidConfigExportMessage = (configPath, reason) => {
46
+ switch (reason) {
47
+ case "both-default-and-named-config": return `Configuration file '${configPath}' must choose one export style: use either 'export default' or 'export const config = ...', but not both.`;
48
+ case "default-namespace-wrapper": return `Configuration file '${configPath}' default export must be the config object itself, not a module namespace-like wrapper. Export the config directly with 'export default { ... }' or use 'export const config = ...'.`;
49
+ case "missing-config-export": return `Configuration file '${configPath}' must export its config via 'export default' or 'export const config = ...'.`;
50
+ case "non-object-config": return `Configuration file '${configPath}' must export a config object via 'export default' or 'export const config = ...'.`;
51
+ }
52
+ };
53
+ //#endregion
54
+ //#region src/errors/UnsupportedConfigExtensionError.ts
55
+ var UnsupportedConfigExtensionError = class extends Error {
56
+ name = "UnsupportedConfigExtensionError";
57
+ constructor(configPath, extension, supportedExtensions) {
58
+ super(`Unsupported config file extension '${extension}' for '${configPath}'. TypeWeaver accepts only these config extensions: ${supportedExtensions.join(", ")}.`);
59
+ this.configPath = configPath;
60
+ this.extension = extension;
61
+ this.supportedExtensions = supportedExtensions;
62
+ }
63
+ };
64
+ //#endregion
65
+ //#region src/errors/UnsupportedTypeScriptConfigError.ts
66
+ var UnsupportedTypeScriptConfigError = class extends Error {
67
+ name = "UnsupportedTypeScriptConfigError";
68
+ constructor(configPath, extension) {
69
+ super(`TypeScript config files are not supported: '${configPath}' uses '${extension}'. Use a JavaScript config file with one of these extensions: .js, .mjs, or .cjs.`);
70
+ this.configPath = configPath;
71
+ this.extension = extension;
72
+ }
73
+ };
74
+ //#endregion
36
75
  //#region src/configLoader.ts
37
- const SUPPORTED_CONFIG_EXTENSIONS = new Set([
76
+ const SUPPORTED_CONFIG_EXTENSIONS = [
38
77
  ".js",
39
78
  ".mjs",
40
79
  ".cjs"
41
- ]);
80
+ ];
81
+ const SUPPORTED_CONFIG_EXTENSION_SET = new Set(SUPPORTED_CONFIG_EXTENSIONS);
42
82
  const UNSUPPORTED_TYPESCRIPT_CONFIG_EXTENSIONS = new Set([
43
83
  ".ts",
44
84
  ".mts",
@@ -49,25 +89,25 @@ const getResolvedConfigPath = (configPath, currentWorkingDirectory = process.cwd
49
89
  };
50
90
  const assertSupportedConfigPath = (configPath) => {
51
91
  const extension = node_path.default.extname(configPath).toLowerCase();
52
- if (UNSUPPORTED_TYPESCRIPT_CONFIG_EXTENSIONS.has(extension)) throw new Error(`TypeScript config files are no longer supported: '${configPath}'. Convert the config to .js, .mjs, or .cjs, or compile it before passing --config.`);
53
- if (!SUPPORTED_CONFIG_EXTENSIONS.has(extension)) throw new Error(`Unsupported config file extension for '${configPath}'. TypeWeaver only accepts .js, .mjs, or .cjs config files.`);
92
+ if (UNSUPPORTED_TYPESCRIPT_CONFIG_EXTENSIONS.has(extension)) throw new UnsupportedTypeScriptConfigError(configPath, extension);
93
+ if (!SUPPORTED_CONFIG_EXTENSION_SET.has(extension)) throw new UnsupportedConfigExtensionError(configPath, extension, SUPPORTED_CONFIG_EXTENSIONS);
54
94
  };
55
95
  const loadConfig = async (configPath) => {
56
96
  assertSupportedConfigPath(configPath);
57
97
  const loadedConfig = getConfigExport(await import((0, node_url.pathToFileURL)(node_path.default.resolve(configPath)).toString()), configPath);
58
- if (!isConfigObject(loadedConfig)) throw new Error(`Configuration file '${configPath}' must export a config object via 'export default' or 'export const config = ...'.`);
98
+ if (!isConfigObject(loadedConfig)) throw new InvalidConfigExportError(configPath, "non-object-config");
59
99
  return loadedConfig;
60
100
  };
61
101
  const getConfigExport = (configModule, configPath) => {
62
102
  const hasDefaultExport = Object.hasOwn(configModule, "default");
63
103
  const hasNamedConfigExport = Object.hasOwn(configModule, "config");
64
- if (hasDefaultExport && hasNamedConfigExport) throw new Error(`Configuration file '${configPath}' must choose a single export style: either 'export default' or 'export const config = ...', but not both.`);
104
+ if (hasDefaultExport && hasNamedConfigExport) throw new InvalidConfigExportError(configPath, "both-default-and-named-config");
65
105
  if (hasDefaultExport) {
66
- if (isNamespaceLikeConfigExport(configModule.default)) throw new Error(`Configuration file '${configPath}' default export must be the config object itself, not a module namespace-like wrapper. Export the config directly with 'export default { ... }' or use 'export const config = ...'.`);
106
+ if (isNamespaceLikeConfigExport(configModule.default)) throw new InvalidConfigExportError(configPath, "default-namespace-wrapper");
67
107
  return configModule.default;
68
108
  }
69
109
  if (hasNamedConfigExport) return configModule.config;
70
- throw new Error(`Configuration file '${configPath}' must export its config via 'export default' or 'export const config = ...'.`);
110
+ throw new InvalidConfigExportError(configPath, "missing-config-export");
71
111
  };
72
112
  const isConfigObject = (value) => {
73
113
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -77,6 +117,35 @@ const isNamespaceLikeConfigExport = (value) => {
77
117
  return Object.hasOwn(value, "default") || Object.hasOwn(value, "config");
78
118
  };
79
119
  //#endregion
120
+ //#region src/generators/errors/UnsafeCleanTargetError.ts
121
+ var UnsafeCleanTargetError = class extends Error {
122
+ name = "UnsafeCleanTargetError";
123
+ resolvedOutputDir;
124
+ currentWorkingDirectory;
125
+ protectedWorkspaceRoot;
126
+ filesystemRoot;
127
+ constructor(outputDir, reason, diagnostics = {}) {
128
+ super(getUnsafeCleanTargetMessage(outputDir, reason, diagnostics));
129
+ this.outputDir = outputDir;
130
+ this.reason = reason;
131
+ this.resolvedOutputDir = diagnostics.resolvedOutputDir;
132
+ this.currentWorkingDirectory = diagnostics.currentWorkingDirectory;
133
+ this.protectedWorkspaceRoot = diagnostics.protectedWorkspaceRoot;
134
+ this.filesystemRoot = diagnostics.filesystemRoot;
135
+ }
136
+ };
137
+ const getUnsafeCleanTargetMessage = (outputDir, reason, diagnostics) => {
138
+ const targetDescription = `Refusing to clean '${outputDir}'`;
139
+ const suffix = "Use a dedicated generated output directory instead.";
140
+ switch (reason) {
141
+ case "empty-path": return `Refusing to clean an empty output directory path. ${suffix}`;
142
+ case "filesystem-root": return `${targetDescription} because it resolves to the filesystem root '${diagnostics.filesystemRoot ?? diagnostics.resolvedOutputDir ?? outputDir}'. ${suffix}`;
143
+ case "current-working-directory": return `${targetDescription} because it resolves to the current working directory '${diagnostics.currentWorkingDirectory ?? diagnostics.resolvedOutputDir ?? outputDir}'. ${suffix}`;
144
+ case "workspace-root": return `${targetDescription} because it resolves to the protected workspace root '${diagnostics.protectedWorkspaceRoot ?? diagnostics.resolvedOutputDir ?? outputDir}'. ${suffix}`;
145
+ case "ancestor-of-current-working-directory": return `${targetDescription} because it resolves to an ancestor directory of the current working directory '${diagnostics.currentWorkingDirectory ?? ""}'. ${suffix}`;
146
+ }
147
+ };
148
+ //#endregion
80
149
  //#region src/generators/formatter.ts
81
150
  async function formatCode(outputDir, startDir) {
82
151
  const format = await loadFormatter();
@@ -278,6 +347,17 @@ function reportSuccessfulLoads(successful) {
278
347
  }
279
348
  }
280
349
  //#endregion
350
+ //#region src/generators/spec/errors/SpecBundleOutputMissingError.ts
351
+ var SpecBundleOutputMissingError = class extends Error {
352
+ name = "SpecBundleOutputMissingError";
353
+ constructor(inputFile, bundledSpecFile, specOutputDir) {
354
+ super(`Spec bundling completed but did not create the expected output '${bundledSpecFile}' for entrypoint '${inputFile}'. Expected the bundle inside '${specOutputDir}'.`);
355
+ this.inputFile = inputFile;
356
+ this.bundledSpecFile = bundledSpecFile;
357
+ this.specOutputDir = specOutputDir;
358
+ }
359
+ };
360
+ //#endregion
281
361
  //#region src/generators/spec/specBundler.ts
282
362
  const WINDOWS_ABSOLUTE_PATH_PATTERN = /^[A-Za-z]:[\\/]/;
283
363
  const WINDOWS_UNC_PATH_PATTERN = /^\\\\/;
@@ -291,7 +371,7 @@ function createWrapperImportSpecifier(wrapperFile, inputFile) {
291
371
  if (relativeInputFile.startsWith(".") || relativeInputFile.startsWith("..")) return relativeInputFile;
292
372
  return `./${relativeInputFile}`;
293
373
  }
294
- async function bundle(config) {
374
+ async function bundle(config, deps = {}) {
295
375
  const tempDir = node_fs.default.mkdtempSync(node_path.default.join(node_os.default.tmpdir(), "typeweaver-spec-loader-"));
296
376
  const wrapperFile = node_path.default.join(tempDir, "spec-entrypoint.ts");
297
377
  const bundledSpecFile = node_path.default.join(config.specOutputDir, "spec.js");
@@ -307,7 +387,7 @@ async function bundle(config) {
307
387
  ""
308
388
  ].join("\n"));
309
389
  try {
310
- await (0, rolldown.build)({
390
+ await (deps.build ?? rolldown.build)({
311
391
  cwd: tempDir,
312
392
  input: wrapperFile,
313
393
  treeshake: true,
@@ -327,7 +407,7 @@ async function bundle(config) {
327
407
  force: true
328
408
  });
329
409
  }
330
- if (!node_fs.default.existsSync(bundledSpecFile)) throw new Error(`Failed to bundle spec entrypoint '${config.inputFile}' to '${bundledSpecFile}'.`);
410
+ if (!(deps.existsSync ?? node_fs.default.existsSync)(bundledSpecFile)) throw new SpecBundleOutputMissingError(config.inputFile, bundledSpecFile, config.specOutputDir);
331
411
  return bundledSpecFile;
332
412
  }
333
413
  function resolveBundledInputFile(inputFile) {
@@ -409,17 +489,32 @@ function writeSpecDeclarationFile(specOutputDir) {
409
489
  const moduleDir$1 = node_path.default.dirname((0, node_url.fileURLToPath)(require("url").pathToFileURL(__filename).href));
410
490
  const assertSafeCleanTarget = (outputDir, currentWorkingDirectory) => {
411
491
  const trimmedOutputDir = outputDir.trim();
412
- if (trimmedOutputDir.length === 0) throw new Error("Refusing to clean an empty output directory path. Pass a dedicated generated output directory instead.");
492
+ if (trimmedOutputDir.length === 0) throw new UnsafeCleanTargetError(outputDir, "empty-path");
413
493
  const resolvedWorkingDirectory = node_path.default.resolve(currentWorkingDirectory);
414
494
  const canonicalWorkingDirectory = node_fs.default.realpathSync.native(resolvedWorkingDirectory);
415
495
  const resolvedOutputDir = node_path.default.resolve(resolvedWorkingDirectory, trimmedOutputDir);
416
496
  const canonicalOutputDir = canonicalizePathForContainment(resolvedOutputDir);
417
- if (canonicalOutputDir === node_path.default.parse(canonicalOutputDir).root) throw new Error(`Refusing to clean '${outputDir}' because it resolves to the filesystem root.`);
418
- if (resolvedOutputDir === resolvedWorkingDirectory || canonicalOutputDir === canonicalWorkingDirectory) throw new Error(`Refusing to clean '${outputDir}' because it resolves to the current working directory.`);
497
+ const filesystemRoot = node_path.default.parse(canonicalOutputDir).root;
498
+ if (canonicalOutputDir === filesystemRoot) throw new UnsafeCleanTargetError(outputDir, "filesystem-root", {
499
+ resolvedOutputDir,
500
+ currentWorkingDirectory: resolvedWorkingDirectory,
501
+ filesystemRoot
502
+ });
503
+ if (resolvedOutputDir === resolvedWorkingDirectory || canonicalOutputDir === canonicalWorkingDirectory) throw new UnsafeCleanTargetError(outputDir, "current-working-directory", {
504
+ resolvedOutputDir,
505
+ currentWorkingDirectory: resolvedWorkingDirectory
506
+ });
419
507
  const protectedWorkspaceRoots = [findProtectedWorkspaceRoot(resolvedWorkingDirectory), findProtectedWorkspaceRoot(canonicalWorkingDirectory)].filter((root) => root !== void 0);
420
508
  const protectedWorkspaceRootTarget = protectedWorkspaceRoots.find((protectedWorkspaceRoot) => resolvedOutputDir === protectedWorkspaceRoot || canonicalOutputDir === node_fs.default.realpathSync.native(protectedWorkspaceRoot));
421
- if (protectedWorkspaceRootTarget !== void 0) throw new Error(`Refusing to clean '${outputDir}' because it resolves to the inferred workspace root '${protectedWorkspaceRootTarget}'. Choose a dedicated output subdirectory instead.`);
422
- if (protectedWorkspaceRoots.length > 0 && (isSameOrDescendantOf(resolvedWorkingDirectory, resolvedOutputDir) || isSameOrDescendantOf(canonicalWorkingDirectory, canonicalOutputDir))) throw new Error(`Refusing to clean '${outputDir}' because it resolves to an ancestor directory of the current working directory. Choose a dedicated output subdirectory instead.`);
509
+ if (protectedWorkspaceRootTarget !== void 0) throw new UnsafeCleanTargetError(outputDir, "workspace-root", {
510
+ resolvedOutputDir,
511
+ currentWorkingDirectory: resolvedWorkingDirectory,
512
+ protectedWorkspaceRoot: protectedWorkspaceRootTarget
513
+ });
514
+ if (protectedWorkspaceRoots.length > 0 && (isSameOrDescendantOf(resolvedWorkingDirectory, resolvedOutputDir) || isSameOrDescendantOf(canonicalWorkingDirectory, canonicalOutputDir))) throw new UnsafeCleanTargetError(outputDir, "ancestor-of-current-working-directory", {
515
+ resolvedOutputDir,
516
+ currentWorkingDirectory: resolvedWorkingDirectory
517
+ });
423
518
  };
424
519
  /**
425
520
  * Main generator for typeweaver
@@ -532,6 +627,40 @@ const isSameOrDescendantOf = (directory, ancestor) => {
532
627
  return relativePath === "" || !escapesAncestor && !node_path.default.isAbsolute(relativePath);
533
628
  };
534
629
  //#endregion
630
+ //#region src/errors/MissingGenerateOptionError.ts
631
+ var MissingGenerateOptionError = class extends Error {
632
+ name = "MissingGenerateOptionError";
633
+ constructor(optionName, flag, configKey) {
634
+ super(`Missing required generate option '${optionName}'. Pass ${flag} or set '${configKey}' in the TypeWeaver config file.`);
635
+ this.optionName = optionName;
636
+ this.flag = flag;
637
+ this.configKey = configKey;
638
+ }
639
+ };
640
+ //#endregion
641
+ //#region src/resolveGenerateOptions.ts
642
+ const resolveGenerateOptions = (options, config, currentWorkingDirectory) => {
643
+ const inputPath = options.input ?? config.input;
644
+ const outputDir = options.output ?? config.output;
645
+ if (!inputPath) throw new MissingGenerateOptionError("input", "--input", "input");
646
+ if (!outputDir) throw new MissingGenerateOptionError("output", "--output", "output");
647
+ const resolvedInputPath = node_path.default.isAbsolute(inputPath) ? inputPath : node_path.default.join(currentWorkingDirectory, inputPath);
648
+ const resolvedOutputDir = node_path.default.isAbsolute(outputDir) ? outputDir : node_path.default.join(currentWorkingDirectory, outputDir);
649
+ const finalConfig = {
650
+ input: resolvedInputPath,
651
+ output: resolvedOutputDir,
652
+ format: options.format ?? config.format ?? true,
653
+ clean: options.clean ?? config.clean ?? true
654
+ };
655
+ if (options.plugins) finalConfig.plugins = options.plugins.split(",").map((plugin) => plugin.trim());
656
+ else if (config.plugins) finalConfig.plugins = config.plugins;
657
+ return {
658
+ inputPath: resolvedInputPath,
659
+ outputDir: resolvedOutputDir,
660
+ config: finalConfig
661
+ };
662
+ };
663
+ //#endregion
535
664
  //#region src/cli.ts
536
665
  const moduleDir = node_path.default.dirname((0, node_url.fileURLToPath)(require("url").pathToFileURL(__filename).href));
537
666
  const packageJson = JSON.parse(node_fs.default.readFileSync(node_path.default.join(moduleDir, "../package.json"), "utf-8"));
@@ -551,21 +680,8 @@ program.command("generate").description("Generate types, validators, and clients
551
680
  process.exit(1);
552
681
  }
553
682
  }
554
- const inputPath = options.input ?? config.input;
555
- const outputDir = options.output ?? config.output;
556
- if (!inputPath) throw new Error("No input spec entrypoint provided. Use --input or specify in config file.");
557
- if (!outputDir) throw new Error("No output directory provided. Use --output or specify in config file.");
558
- const resolvedInputPath = node_path.default.isAbsolute(inputPath) ? inputPath : node_path.default.join(execDir, inputPath);
559
- const resolvedOutputDir = node_path.default.isAbsolute(outputDir) ? outputDir : node_path.default.join(execDir, outputDir);
560
- const finalConfig = {
561
- input: resolvedInputPath,
562
- output: resolvedOutputDir,
563
- format: options.format ?? config.format ?? true,
564
- clean: options.clean ?? config.clean ?? true
565
- };
566
- if (options.plugins) finalConfig.plugins = options.plugins.split(",").map((p) => p.trim());
567
- else if (config.plugins) finalConfig.plugins = config.plugins;
568
- return new Generator().generate(resolvedInputPath, resolvedOutputDir, finalConfig, execDir);
683
+ const resolvedGenerateOptions = resolveGenerateOptions(options, config, execDir);
684
+ return new Generator().generate(resolvedGenerateOptions.inputPath, resolvedGenerateOptions.outputDir, resolvedGenerateOptions.config, execDir);
569
685
  });
570
686
  program.command("init").description("Initialize a new typeweaver project (coming soon)").action(() => {
571
687
  console.log("The init command is coming soon!");
package/dist/cli.mjs CHANGED
@@ -8,12 +8,52 @@ import os from "node:os";
8
8
  import { build } from "rolldown";
9
9
  import { createHash } from "node:crypto";
10
10
  import { HttpMethod, HttpStatusCode } from "@rexeus/typeweaver-core";
11
+ //#region src/errors/InvalidConfigExportError.ts
12
+ var InvalidConfigExportError = class extends Error {
13
+ name = "InvalidConfigExportError";
14
+ constructor(configPath, reason) {
15
+ super(getInvalidConfigExportMessage(configPath, reason));
16
+ this.configPath = configPath;
17
+ this.reason = reason;
18
+ }
19
+ };
20
+ const getInvalidConfigExportMessage = (configPath, reason) => {
21
+ switch (reason) {
22
+ case "both-default-and-named-config": return `Configuration file '${configPath}' must choose one export style: use either 'export default' or 'export const config = ...', but not both.`;
23
+ case "default-namespace-wrapper": return `Configuration file '${configPath}' default export must be the config object itself, not a module namespace-like wrapper. Export the config directly with 'export default { ... }' or use 'export const config = ...'.`;
24
+ case "missing-config-export": return `Configuration file '${configPath}' must export its config via 'export default' or 'export const config = ...'.`;
25
+ case "non-object-config": return `Configuration file '${configPath}' must export a config object via 'export default' or 'export const config = ...'.`;
26
+ }
27
+ };
28
+ //#endregion
29
+ //#region src/errors/UnsupportedConfigExtensionError.ts
30
+ var UnsupportedConfigExtensionError = class extends Error {
31
+ name = "UnsupportedConfigExtensionError";
32
+ constructor(configPath, extension, supportedExtensions) {
33
+ super(`Unsupported config file extension '${extension}' for '${configPath}'. TypeWeaver accepts only these config extensions: ${supportedExtensions.join(", ")}.`);
34
+ this.configPath = configPath;
35
+ this.extension = extension;
36
+ this.supportedExtensions = supportedExtensions;
37
+ }
38
+ };
39
+ //#endregion
40
+ //#region src/errors/UnsupportedTypeScriptConfigError.ts
41
+ var UnsupportedTypeScriptConfigError = class extends Error {
42
+ name = "UnsupportedTypeScriptConfigError";
43
+ constructor(configPath, extension) {
44
+ super(`TypeScript config files are not supported: '${configPath}' uses '${extension}'. Use a JavaScript config file with one of these extensions: .js, .mjs, or .cjs.`);
45
+ this.configPath = configPath;
46
+ this.extension = extension;
47
+ }
48
+ };
49
+ //#endregion
11
50
  //#region src/configLoader.ts
12
- const SUPPORTED_CONFIG_EXTENSIONS = new Set([
51
+ const SUPPORTED_CONFIG_EXTENSIONS = [
13
52
  ".js",
14
53
  ".mjs",
15
54
  ".cjs"
16
- ]);
55
+ ];
56
+ const SUPPORTED_CONFIG_EXTENSION_SET = new Set(SUPPORTED_CONFIG_EXTENSIONS);
17
57
  const UNSUPPORTED_TYPESCRIPT_CONFIG_EXTENSIONS = new Set([
18
58
  ".ts",
19
59
  ".mts",
@@ -24,25 +64,25 @@ const getResolvedConfigPath = (configPath, currentWorkingDirectory = process.cwd
24
64
  };
25
65
  const assertSupportedConfigPath = (configPath) => {
26
66
  const extension = path.extname(configPath).toLowerCase();
27
- if (UNSUPPORTED_TYPESCRIPT_CONFIG_EXTENSIONS.has(extension)) throw new Error(`TypeScript config files are no longer supported: '${configPath}'. Convert the config to .js, .mjs, or .cjs, or compile it before passing --config.`);
28
- if (!SUPPORTED_CONFIG_EXTENSIONS.has(extension)) throw new Error(`Unsupported config file extension for '${configPath}'. TypeWeaver only accepts .js, .mjs, or .cjs config files.`);
67
+ if (UNSUPPORTED_TYPESCRIPT_CONFIG_EXTENSIONS.has(extension)) throw new UnsupportedTypeScriptConfigError(configPath, extension);
68
+ if (!SUPPORTED_CONFIG_EXTENSION_SET.has(extension)) throw new UnsupportedConfigExtensionError(configPath, extension, SUPPORTED_CONFIG_EXTENSIONS);
29
69
  };
30
70
  const loadConfig = async (configPath) => {
31
71
  assertSupportedConfigPath(configPath);
32
72
  const loadedConfig = getConfigExport(await import(pathToFileURL(path.resolve(configPath)).toString()), configPath);
33
- if (!isConfigObject(loadedConfig)) throw new Error(`Configuration file '${configPath}' must export a config object via 'export default' or 'export const config = ...'.`);
73
+ if (!isConfigObject(loadedConfig)) throw new InvalidConfigExportError(configPath, "non-object-config");
34
74
  return loadedConfig;
35
75
  };
36
76
  const getConfigExport = (configModule, configPath) => {
37
77
  const hasDefaultExport = Object.hasOwn(configModule, "default");
38
78
  const hasNamedConfigExport = Object.hasOwn(configModule, "config");
39
- if (hasDefaultExport && hasNamedConfigExport) throw new Error(`Configuration file '${configPath}' must choose a single export style: either 'export default' or 'export const config = ...', but not both.`);
79
+ if (hasDefaultExport && hasNamedConfigExport) throw new InvalidConfigExportError(configPath, "both-default-and-named-config");
40
80
  if (hasDefaultExport) {
41
- if (isNamespaceLikeConfigExport(configModule.default)) throw new Error(`Configuration file '${configPath}' default export must be the config object itself, not a module namespace-like wrapper. Export the config directly with 'export default { ... }' or use 'export const config = ...'.`);
81
+ if (isNamespaceLikeConfigExport(configModule.default)) throw new InvalidConfigExportError(configPath, "default-namespace-wrapper");
42
82
  return configModule.default;
43
83
  }
44
84
  if (hasNamedConfigExport) return configModule.config;
45
- throw new Error(`Configuration file '${configPath}' must export its config via 'export default' or 'export const config = ...'.`);
85
+ throw new InvalidConfigExportError(configPath, "missing-config-export");
46
86
  };
47
87
  const isConfigObject = (value) => {
48
88
  return typeof value === "object" && value !== null && !Array.isArray(value);
@@ -52,6 +92,35 @@ const isNamespaceLikeConfigExport = (value) => {
52
92
  return Object.hasOwn(value, "default") || Object.hasOwn(value, "config");
53
93
  };
54
94
  //#endregion
95
+ //#region src/generators/errors/UnsafeCleanTargetError.ts
96
+ var UnsafeCleanTargetError = class extends Error {
97
+ name = "UnsafeCleanTargetError";
98
+ resolvedOutputDir;
99
+ currentWorkingDirectory;
100
+ protectedWorkspaceRoot;
101
+ filesystemRoot;
102
+ constructor(outputDir, reason, diagnostics = {}) {
103
+ super(getUnsafeCleanTargetMessage(outputDir, reason, diagnostics));
104
+ this.outputDir = outputDir;
105
+ this.reason = reason;
106
+ this.resolvedOutputDir = diagnostics.resolvedOutputDir;
107
+ this.currentWorkingDirectory = diagnostics.currentWorkingDirectory;
108
+ this.protectedWorkspaceRoot = diagnostics.protectedWorkspaceRoot;
109
+ this.filesystemRoot = diagnostics.filesystemRoot;
110
+ }
111
+ };
112
+ const getUnsafeCleanTargetMessage = (outputDir, reason, diagnostics) => {
113
+ const targetDescription = `Refusing to clean '${outputDir}'`;
114
+ const suffix = "Use a dedicated generated output directory instead.";
115
+ switch (reason) {
116
+ case "empty-path": return `Refusing to clean an empty output directory path. ${suffix}`;
117
+ case "filesystem-root": return `${targetDescription} because it resolves to the filesystem root '${diagnostics.filesystemRoot ?? diagnostics.resolvedOutputDir ?? outputDir}'. ${suffix}`;
118
+ case "current-working-directory": return `${targetDescription} because it resolves to the current working directory '${diagnostics.currentWorkingDirectory ?? diagnostics.resolvedOutputDir ?? outputDir}'. ${suffix}`;
119
+ case "workspace-root": return `${targetDescription} because it resolves to the protected workspace root '${diagnostics.protectedWorkspaceRoot ?? diagnostics.resolvedOutputDir ?? outputDir}'. ${suffix}`;
120
+ case "ancestor-of-current-working-directory": return `${targetDescription} because it resolves to an ancestor directory of the current working directory '${diagnostics.currentWorkingDirectory ?? ""}'. ${suffix}`;
121
+ }
122
+ };
123
+ //#endregion
55
124
  //#region src/generators/formatter.ts
56
125
  async function formatCode(outputDir, startDir) {
57
126
  const format = await loadFormatter();
@@ -253,6 +322,17 @@ function reportSuccessfulLoads(successful) {
253
322
  }
254
323
  }
255
324
  //#endregion
325
+ //#region src/generators/spec/errors/SpecBundleOutputMissingError.ts
326
+ var SpecBundleOutputMissingError = class extends Error {
327
+ name = "SpecBundleOutputMissingError";
328
+ constructor(inputFile, bundledSpecFile, specOutputDir) {
329
+ super(`Spec bundling completed but did not create the expected output '${bundledSpecFile}' for entrypoint '${inputFile}'. Expected the bundle inside '${specOutputDir}'.`);
330
+ this.inputFile = inputFile;
331
+ this.bundledSpecFile = bundledSpecFile;
332
+ this.specOutputDir = specOutputDir;
333
+ }
334
+ };
335
+ //#endregion
256
336
  //#region src/generators/spec/specBundler.ts
257
337
  const WINDOWS_ABSOLUTE_PATH_PATTERN = /^[A-Za-z]:[\\/]/;
258
338
  const WINDOWS_UNC_PATH_PATTERN = /^\\\\/;
@@ -266,7 +346,7 @@ function createWrapperImportSpecifier(wrapperFile, inputFile) {
266
346
  if (relativeInputFile.startsWith(".") || relativeInputFile.startsWith("..")) return relativeInputFile;
267
347
  return `./${relativeInputFile}`;
268
348
  }
269
- async function bundle(config) {
349
+ async function bundle(config, deps = {}) {
270
350
  const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), "typeweaver-spec-loader-"));
271
351
  const wrapperFile = path.join(tempDir, "spec-entrypoint.ts");
272
352
  const bundledSpecFile = path.join(config.specOutputDir, "spec.js");
@@ -282,7 +362,7 @@ async function bundle(config) {
282
362
  ""
283
363
  ].join("\n"));
284
364
  try {
285
- await build({
365
+ await (deps.build ?? build)({
286
366
  cwd: tempDir,
287
367
  input: wrapperFile,
288
368
  treeshake: true,
@@ -302,7 +382,7 @@ async function bundle(config) {
302
382
  force: true
303
383
  });
304
384
  }
305
- if (!fs.existsSync(bundledSpecFile)) throw new Error(`Failed to bundle spec entrypoint '${config.inputFile}' to '${bundledSpecFile}'.`);
385
+ if (!(deps.existsSync ?? fs.existsSync)(bundledSpecFile)) throw new SpecBundleOutputMissingError(config.inputFile, bundledSpecFile, config.specOutputDir);
306
386
  return bundledSpecFile;
307
387
  }
308
388
  function resolveBundledInputFile(inputFile) {
@@ -384,17 +464,32 @@ function writeSpecDeclarationFile(specOutputDir) {
384
464
  const moduleDir$1 = path.dirname(fileURLToPath(import.meta.url));
385
465
  const assertSafeCleanTarget = (outputDir, currentWorkingDirectory) => {
386
466
  const trimmedOutputDir = outputDir.trim();
387
- if (trimmedOutputDir.length === 0) throw new Error("Refusing to clean an empty output directory path. Pass a dedicated generated output directory instead.");
467
+ if (trimmedOutputDir.length === 0) throw new UnsafeCleanTargetError(outputDir, "empty-path");
388
468
  const resolvedWorkingDirectory = path.resolve(currentWorkingDirectory);
389
469
  const canonicalWorkingDirectory = fs.realpathSync.native(resolvedWorkingDirectory);
390
470
  const resolvedOutputDir = path.resolve(resolvedWorkingDirectory, trimmedOutputDir);
391
471
  const canonicalOutputDir = canonicalizePathForContainment(resolvedOutputDir);
392
- if (canonicalOutputDir === path.parse(canonicalOutputDir).root) throw new Error(`Refusing to clean '${outputDir}' because it resolves to the filesystem root.`);
393
- if (resolvedOutputDir === resolvedWorkingDirectory || canonicalOutputDir === canonicalWorkingDirectory) throw new Error(`Refusing to clean '${outputDir}' because it resolves to the current working directory.`);
472
+ const filesystemRoot = path.parse(canonicalOutputDir).root;
473
+ if (canonicalOutputDir === filesystemRoot) throw new UnsafeCleanTargetError(outputDir, "filesystem-root", {
474
+ resolvedOutputDir,
475
+ currentWorkingDirectory: resolvedWorkingDirectory,
476
+ filesystemRoot
477
+ });
478
+ if (resolvedOutputDir === resolvedWorkingDirectory || canonicalOutputDir === canonicalWorkingDirectory) throw new UnsafeCleanTargetError(outputDir, "current-working-directory", {
479
+ resolvedOutputDir,
480
+ currentWorkingDirectory: resolvedWorkingDirectory
481
+ });
394
482
  const protectedWorkspaceRoots = [findProtectedWorkspaceRoot(resolvedWorkingDirectory), findProtectedWorkspaceRoot(canonicalWorkingDirectory)].filter((root) => root !== void 0);
395
483
  const protectedWorkspaceRootTarget = protectedWorkspaceRoots.find((protectedWorkspaceRoot) => resolvedOutputDir === protectedWorkspaceRoot || canonicalOutputDir === fs.realpathSync.native(protectedWorkspaceRoot));
396
- if (protectedWorkspaceRootTarget !== void 0) throw new Error(`Refusing to clean '${outputDir}' because it resolves to the inferred workspace root '${protectedWorkspaceRootTarget}'. Choose a dedicated output subdirectory instead.`);
397
- if (protectedWorkspaceRoots.length > 0 && (isSameOrDescendantOf(resolvedWorkingDirectory, resolvedOutputDir) || isSameOrDescendantOf(canonicalWorkingDirectory, canonicalOutputDir))) throw new Error(`Refusing to clean '${outputDir}' because it resolves to an ancestor directory of the current working directory. Choose a dedicated output subdirectory instead.`);
484
+ if (protectedWorkspaceRootTarget !== void 0) throw new UnsafeCleanTargetError(outputDir, "workspace-root", {
485
+ resolvedOutputDir,
486
+ currentWorkingDirectory: resolvedWorkingDirectory,
487
+ protectedWorkspaceRoot: protectedWorkspaceRootTarget
488
+ });
489
+ if (protectedWorkspaceRoots.length > 0 && (isSameOrDescendantOf(resolvedWorkingDirectory, resolvedOutputDir) || isSameOrDescendantOf(canonicalWorkingDirectory, canonicalOutputDir))) throw new UnsafeCleanTargetError(outputDir, "ancestor-of-current-working-directory", {
490
+ resolvedOutputDir,
491
+ currentWorkingDirectory: resolvedWorkingDirectory
492
+ });
398
493
  };
399
494
  /**
400
495
  * Main generator for typeweaver
@@ -507,6 +602,40 @@ const isSameOrDescendantOf = (directory, ancestor) => {
507
602
  return relativePath === "" || !escapesAncestor && !path.isAbsolute(relativePath);
508
603
  };
509
604
  //#endregion
605
+ //#region src/errors/MissingGenerateOptionError.ts
606
+ var MissingGenerateOptionError = class extends Error {
607
+ name = "MissingGenerateOptionError";
608
+ constructor(optionName, flag, configKey) {
609
+ super(`Missing required generate option '${optionName}'. Pass ${flag} or set '${configKey}' in the TypeWeaver config file.`);
610
+ this.optionName = optionName;
611
+ this.flag = flag;
612
+ this.configKey = configKey;
613
+ }
614
+ };
615
+ //#endregion
616
+ //#region src/resolveGenerateOptions.ts
617
+ const resolveGenerateOptions = (options, config, currentWorkingDirectory) => {
618
+ const inputPath = options.input ?? config.input;
619
+ const outputDir = options.output ?? config.output;
620
+ if (!inputPath) throw new MissingGenerateOptionError("input", "--input", "input");
621
+ if (!outputDir) throw new MissingGenerateOptionError("output", "--output", "output");
622
+ const resolvedInputPath = path.isAbsolute(inputPath) ? inputPath : path.join(currentWorkingDirectory, inputPath);
623
+ const resolvedOutputDir = path.isAbsolute(outputDir) ? outputDir : path.join(currentWorkingDirectory, outputDir);
624
+ const finalConfig = {
625
+ input: resolvedInputPath,
626
+ output: resolvedOutputDir,
627
+ format: options.format ?? config.format ?? true,
628
+ clean: options.clean ?? config.clean ?? true
629
+ };
630
+ if (options.plugins) finalConfig.plugins = options.plugins.split(",").map((plugin) => plugin.trim());
631
+ else if (config.plugins) finalConfig.plugins = config.plugins;
632
+ return {
633
+ inputPath: resolvedInputPath,
634
+ outputDir: resolvedOutputDir,
635
+ config: finalConfig
636
+ };
637
+ };
638
+ //#endregion
510
639
  //#region src/cli.ts
511
640
  const moduleDir = path.dirname(fileURLToPath(import.meta.url));
512
641
  const packageJson = JSON.parse(fs.readFileSync(path.join(moduleDir, "../package.json"), "utf-8"));
@@ -526,21 +655,8 @@ program.command("generate").description("Generate types, validators, and clients
526
655
  process.exit(1);
527
656
  }
528
657
  }
529
- const inputPath = options.input ?? config.input;
530
- const outputDir = options.output ?? config.output;
531
- if (!inputPath) throw new Error("No input spec entrypoint provided. Use --input or specify in config file.");
532
- if (!outputDir) throw new Error("No output directory provided. Use --output or specify in config file.");
533
- const resolvedInputPath = path.isAbsolute(inputPath) ? inputPath : path.join(execDir, inputPath);
534
- const resolvedOutputDir = path.isAbsolute(outputDir) ? outputDir : path.join(execDir, outputDir);
535
- const finalConfig = {
536
- input: resolvedInputPath,
537
- output: resolvedOutputDir,
538
- format: options.format ?? config.format ?? true,
539
- clean: options.clean ?? config.clean ?? true
540
- };
541
- if (options.plugins) finalConfig.plugins = options.plugins.split(",").map((p) => p.trim());
542
- else if (config.plugins) finalConfig.plugins = config.plugins;
543
- return new Generator().generate(resolvedInputPath, resolvedOutputDir, finalConfig, execDir);
658
+ const resolvedGenerateOptions = resolveGenerateOptions(options, config, execDir);
659
+ return new Generator().generate(resolvedGenerateOptions.inputPath, resolvedGenerateOptions.outputDir, resolvedGenerateOptions.config, execDir);
544
660
  });
545
661
  program.command("init").description("Initialize a new typeweaver project (coming soon)").action(() => {
546
662
  console.log("The init command is coming soon!");
package/dist/cli.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.mjs","names":["moduleDir"],"sources":["../src/configLoader.ts","../src/generators/formatter.ts","../src/generators/indexFileGenerator.ts","../src/generators/errors/PluginLoadingFailure.ts","../src/generators/pluginLoader.ts","../src/generators/spec/specBundler.ts","../src/generators/spec/InvalidSpecEntrypointError.ts","../src/generators/spec/specGuards.ts","../src/generators/spec/specImporter.ts","../src/generators/specLoader.ts","../src/generators/Generator.ts","../src/cli.ts"],"sourcesContent":["import path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport type { TypeweaverConfig } from \"@rexeus/typeweaver-gen\";\n\nconst SUPPORTED_CONFIG_EXTENSIONS = new Set([\".js\", \".mjs\", \".cjs\"]);\nconst UNSUPPORTED_TYPESCRIPT_CONFIG_EXTENSIONS = new Set([\n \".ts\",\n \".mts\",\n \".cts\",\n]);\n\nexport const getResolvedConfigPath = (\n configPath: string,\n currentWorkingDirectory: string = process.cwd()\n): string => {\n return path.isAbsolute(configPath)\n ? configPath\n : path.resolve(currentWorkingDirectory, configPath);\n};\n\nexport const assertSupportedConfigPath = (configPath: string): void => {\n const extension = path.extname(configPath).toLowerCase();\n\n if (UNSUPPORTED_TYPESCRIPT_CONFIG_EXTENSIONS.has(extension)) {\n throw new Error(\n `TypeScript config files are no longer supported: '${configPath}'. Convert the config to .js, .mjs, or .cjs, or compile it before passing --config.`\n );\n }\n\n if (!SUPPORTED_CONFIG_EXTENSIONS.has(extension)) {\n throw new Error(\n `Unsupported config file extension for '${configPath}'. TypeWeaver only accepts .js, .mjs, or .cjs config files.`\n );\n }\n};\n\nexport const loadConfig = async (\n configPath: string\n): Promise<Partial<TypeweaverConfig>> => {\n assertSupportedConfigPath(configPath);\n\n const resolvedPath = path.resolve(configPath);\n const configUrl = pathToFileURL(resolvedPath).toString();\n const configModule = await import(configUrl);\n const loadedConfig = getConfigExport(configModule, configPath);\n\n if (!isConfigObject(loadedConfig)) {\n throw new Error(\n `Configuration file '${configPath}' must export a config object via 'export default' or 'export const config = ...'.`\n );\n }\n\n return loadedConfig;\n};\n\nconst getConfigExport = (\n configModule: Record<string, unknown>,\n configPath: string\n): unknown => {\n const hasDefaultExport = Object.hasOwn(configModule, \"default\");\n const hasNamedConfigExport = Object.hasOwn(configModule, \"config\");\n\n if (hasDefaultExport && hasNamedConfigExport) {\n throw new Error(\n `Configuration file '${configPath}' must choose a single export style: either 'export default' or 'export const config = ...', but not both.`\n );\n }\n\n if (hasDefaultExport) {\n if (isNamespaceLikeConfigExport(configModule.default)) {\n throw new Error(\n `Configuration file '${configPath}' default export must be the config object itself, not a module namespace-like wrapper. Export the config directly with 'export default { ... }' or use 'export const config = ...'.`\n );\n }\n\n return configModule.default;\n }\n\n if (hasNamedConfigExport) {\n return configModule.config;\n }\n\n throw new Error(\n `Configuration file '${configPath}' must export its config via 'export default' or 'export const config = ...'.`\n );\n};\n\nconst isConfigObject = (value: unknown): value is Partial<TypeweaverConfig> => {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n};\n\nconst isNamespaceLikeConfigExport = (value: unknown): boolean => {\n if (!isConfigObject(value)) {\n return false;\n }\n\n return Object.hasOwn(value, \"default\") || Object.hasOwn(value, \"config\");\n};\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\ntype FormatFn = (filename: string, source: string) => Promise<{ code: string }>;\n\nexport async function formatCode(\n outputDir: string,\n startDir?: string\n): Promise<void> {\n const format = await loadFormatter();\n if (!format) {\n return;\n }\n\n const targetDir = startDir ?? outputDir;\n await formatDirectory(targetDir, format);\n}\n\nasync function loadFormatter(): Promise<FormatFn | undefined> {\n try {\n const oxfmt = await import(\"oxfmt\");\n return oxfmt.format;\n } catch {\n console.warn(\n \"oxfmt not installed - skipping formatting. Install with: npm install -D oxfmt\"\n );\n return undefined;\n }\n}\n\nasync function formatDirectory(\n targetDir: string,\n format: FormatFn\n): Promise<void> {\n const contents = fs.readdirSync(targetDir, { withFileTypes: true });\n\n for (const content of contents) {\n if (content.isFile()) {\n const filePath = path.join(targetDir, content.name);\n const unformatted = fs.readFileSync(filePath, \"utf8\");\n const { code } = await format(filePath, unformatted);\n fs.writeFileSync(filePath, code);\n } else if (content.isDirectory()) {\n await formatDirectory(path.join(targetDir, content.name), format);\n }\n }\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { renderTemplate } from \"@rexeus/typeweaver-gen\";\nimport type { GeneratorContext } from \"@rexeus/typeweaver-gen\";\n\nexport type IndexFileGenerationContext = Pick<\n GeneratorContext,\n \"outputDir\" | \"getGeneratedFiles\"\n>;\n\nexport function generateIndexFiles(\n templateDir: string,\n context: IndexFileGenerationContext\n): void {\n const templateFilePath = path.join(templateDir, \"Index.ejs\");\n const template = fs.readFileSync(templateFilePath, \"utf8\");\n\n const generatedFiles = context.getGeneratedFiles();\n const groups = new Map<string, Set<string>>();\n const rootFiles = new Set<string>();\n const existingBarrels = new Set<string>();\n\n for (const file of generatedFiles) {\n const normalizedFile = file.replace(/\\\\/g, \"/\");\n const withJsExt = normalizedFile.replace(/\\.ts$/, \".js\");\n const stripped = normalizedFile.replace(/\\.ts$/, \"\");\n const firstSlash = stripped.indexOf(\"/\");\n\n if (stripped === \"index\") {\n continue;\n }\n\n if (firstSlash === -1) {\n rootFiles.add(`./${withJsExt}`);\n continue;\n }\n\n const firstSegment = stripped.slice(0, firstSlash);\n\n if (stripped === \"lib/index\") {\n existingBarrels.add(\"lib\");\n continue;\n }\n\n if (firstSegment === \"lib\") {\n const secondSlash = stripped.indexOf(\"/\", firstSlash + 1);\n const groupKey =\n secondSlash === -1 ? stripped : stripped.slice(0, secondSlash);\n\n const entryName = stripped.slice(groupKey.length + 1);\n\n if (entryName === \"index\") {\n existingBarrels.add(groupKey);\n } else {\n if (!groups.has(groupKey)) {\n groups.set(groupKey, new Set());\n }\n groups.get(groupKey)!.add(`./${entryName}.js`);\n }\n } else {\n const entryName = stripped.slice(firstSlash + 1);\n\n if (entryName === \"index\") {\n existingBarrels.add(firstSegment);\n } else {\n if (!groups.has(firstSegment)) {\n groups.set(firstSegment, new Set());\n }\n groups.get(firstSegment)!.add(`./${entryName}.js`);\n }\n }\n }\n\n for (const [groupKey, entries] of groups) {\n if (existingBarrels.has(groupKey)) {\n continue;\n }\n\n const domainBarrelContent = renderTemplate(template, {\n indexPaths: Array.from(entries).sort(),\n });\n\n const domainIndexPath = path.join(context.outputDir, groupKey, \"index.ts\");\n fs.mkdirSync(path.dirname(domainIndexPath), { recursive: true });\n fs.writeFileSync(domainIndexPath, domainBarrelContent);\n }\n\n const rootIndexPaths = new Set<string>(rootFiles);\n for (const groupKey of groups.keys()) {\n rootIndexPaths.add(`./${groupKey}/index.js`);\n }\n for (const barrelKey of existingBarrels) {\n rootIndexPaths.add(`./${barrelKey}/index.js`);\n }\n\n const rootContent = renderTemplate(template, {\n indexPaths: Array.from(rootIndexPaths).sort(),\n });\n\n fs.writeFileSync(path.join(context.outputDir, \"index.ts\"), rootContent);\n}\n","export type PluginLoadError = {\n readonly pluginName: string;\n readonly attempts: readonly {\n readonly path: string;\n readonly error: string;\n }[];\n};\n\nexport class PluginLoadingFailure extends Error implements PluginLoadError {\n public constructor(\n public readonly pluginName: string,\n public readonly attempts: readonly {\n readonly path: string;\n readonly error: string;\n }[]\n ) {\n super(`Failed to load plugin '${pluginName}'`);\n Object.setPrototypeOf(this, PluginLoadingFailure.prototype);\n }\n}\n","import path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport type {\n PluginConfig,\n PluginConstructor,\n TypeweaverConfig,\n TypeweaverPlugin,\n} from \"@rexeus/typeweaver-gen\";\nimport { PluginLoadingFailure } from \"./errors/PluginLoadingFailure.js\";\nimport type { PluginLoadError } from \"./errors/PluginLoadingFailure.js\";\n\nexport type PluginResolutionStrategy = \"npm\" | \"local\" | \"scoped\";\n\nexport type PluginRegistrar = {\n readonly register: (plugin: TypeweaverPlugin, config?: unknown) => void;\n};\n\nexport type PluginLoadResult = {\n readonly plugin: TypeweaverPlugin;\n readonly source: string;\n readonly config?: PluginConfig;\n};\n\ntype PluginCandidate = {\n readonly exportName: string;\n readonly constructor: PluginConstructor;\n};\n\ntype LoadResult<T, E> =\n | { success: true; value: T }\n | { success: false; error: E };\n\nexport async function loadPlugins(\n registry: PluginRegistrar,\n requiredPlugins: readonly TypeweaverPlugin[],\n strategies: readonly PluginResolutionStrategy[],\n config?: TypeweaverConfig\n): Promise<void> {\n for (const requiredPlugin of requiredPlugins) {\n registry.register(requiredPlugin);\n }\n\n if (!config?.plugins) {\n return;\n }\n\n const successful: PluginLoadResult[] = [];\n\n for (const plugin of config.plugins) {\n const pluginName = typeof plugin === \"string\" ? plugin : plugin[0];\n const pluginConfig = typeof plugin === \"string\" ? undefined : plugin[1];\n const result = await loadPlugin(pluginName, strategies, pluginConfig);\n\n if (result.success === false) {\n throw new PluginLoadingFailure(\n result.error.pluginName,\n result.error.attempts\n );\n }\n\n successful.push(result.value);\n registry.register(result.value.plugin, result.value.config);\n }\n\n reportSuccessfulLoads(successful);\n}\n\nasync function loadPlugin(\n pluginName: string,\n strategies: readonly PluginResolutionStrategy[],\n pluginConfig?: PluginConfig\n): Promise<LoadResult<PluginLoadResult, PluginLoadError>> {\n const possiblePaths = generatePluginPaths(pluginName, strategies);\n const attempts: { path: string; error: string }[] = [];\n\n for (const possiblePath of possiblePaths) {\n try {\n const pluginPackage = await import(possiblePath);\n const plugin = createPluginInstance(pluginPackage, pluginConfig);\n if (plugin.success) {\n return {\n success: true,\n value: {\n plugin: plugin.value,\n source: possiblePath,\n config: pluginConfig,\n },\n };\n }\n attempts.push({\n path: possiblePath,\n error: plugin.error,\n });\n } catch (error) {\n attempts.push({\n path: possiblePath,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n return {\n success: false,\n error: {\n pluginName,\n attempts,\n },\n };\n}\n\nfunction createPluginInstance(\n pluginModule: Record<string, unknown>,\n pluginConfig?: PluginConfig\n): LoadResult<TypeweaverPlugin, string> {\n const candidates = findPluginConstructorCandidates(pluginModule);\n if (candidates.length === 0) {\n return {\n success: false,\n error: \"No plugin constructor export found\",\n };\n }\n\n const errors: string[] = [];\n for (const candidate of candidates) {\n try {\n const plugin = new candidate.constructor(pluginConfig);\n if (isTypeweaverPlugin(plugin)) {\n return {\n success: true,\n value: plugin,\n };\n }\n\n errors.push(\n `Export '${candidate.exportName}' did not produce a valid plugin with a string name`\n );\n } catch (error) {\n errors.push(\n `Export '${candidate.exportName}' could not be instantiated: ${formatError(error)}`\n );\n }\n }\n\n return {\n success: false,\n error: errors.join(\"; \"),\n };\n}\n\nfunction findPluginConstructorCandidates(\n pluginModule: Record<string, unknown>\n): PluginCandidate[] {\n const candidates: PluginCandidate[] = [];\n\n for (const [key, value] of Object.entries(pluginModule)) {\n if (key !== \"default\" && typeof value === \"function\") {\n candidates.push({\n exportName: key,\n constructor: value as PluginConstructor,\n });\n }\n }\n\n // Fall back to default export for third-party plugin compatibility\n const defaultExport = pluginModule.default;\n if (typeof defaultExport === \"function\") {\n candidates.push({\n exportName: \"default\",\n constructor: defaultExport as PluginConstructor,\n });\n }\n\n return candidates;\n}\n\nfunction isTypeweaverPlugin(value: unknown): value is TypeweaverPlugin {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { readonly name?: unknown }).name === \"string\" &&\n (value as { readonly name: string }).name.length > 0\n );\n}\n\nfunction formatError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction generatePluginPaths(\n pluginName: string,\n strategies: readonly PluginResolutionStrategy[]\n): string[] {\n const paths: string[] = [];\n\n for (const strategy of strategies) {\n switch (strategy) {\n case \"npm\":\n paths.push(`@rexeus/typeweaver-${pluginName}`);\n paths.push(`@rexeus/${pluginName}`);\n break;\n case \"local\":\n paths.push(toLocalImportSpecifier(pluginName));\n break;\n case \"scoped\":\n paths.push(pluginName);\n break;\n }\n }\n\n return paths;\n}\n\nfunction toLocalImportSpecifier(pluginName: string): string {\n if (pluginName.startsWith(\"file:\")) {\n return pluginName;\n }\n\n if (path.isAbsolute(pluginName)) {\n return pathToFileURL(pluginName).href;\n }\n\n return pluginName;\n}\n\nfunction reportSuccessfulLoads(successful: PluginLoadResult[]): void {\n if (successful.length > 0) {\n console.info(`Successfully loaded ${successful.length} plugin(s):`);\n for (const result of successful) {\n console.info(` - ${result.plugin.name} (from ${result.source})`);\n }\n }\n}\n","import fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { build } from \"rolldown\";\n\nconst WINDOWS_ABSOLUTE_PATH_PATTERN = /^[A-Za-z]:[\\\\/]/;\nconst WINDOWS_UNC_PATH_PATTERN = /^\\\\\\\\/;\n\nexport type SpecBundlerConfig = {\n readonly inputFile: string;\n readonly specOutputDir: string;\n};\n\nexport function createWrapperImportSpecifier(\n wrapperFile: string,\n inputFile: string\n): string {\n const absoluteInputFile = resolveBundledInputFile(inputFile);\n const useWindowsPathSemantics = usesWindowsPathSemantics(\n wrapperFile,\n absoluteInputFile\n );\n const pathModule = useWindowsPathSemantics ? path.win32 : path.posix;\n const wrapperDir = useWindowsPathSemantics\n ? pathModule.dirname(wrapperFile)\n : resolveRealFilePath(pathModule.dirname(wrapperFile));\n const resolvedInputFile = useWindowsPathSemantics\n ? absoluteInputFile\n : resolveRealFilePath(absoluteInputFile);\n const relativeInputFile = pathModule\n .relative(wrapperDir, resolvedInputFile)\n .replaceAll(pathModule.sep, \"/\");\n\n if (relativeInputFile.startsWith(\".\") || relativeInputFile.startsWith(\"..\")) {\n return relativeInputFile;\n }\n\n return `./${relativeInputFile}`;\n}\n\nexport async function bundle(config: SpecBundlerConfig): Promise<string> {\n const tempDir = fs.mkdtempSync(\n path.join(os.tmpdir(), \"typeweaver-spec-loader-\")\n );\n const wrapperFile = path.join(tempDir, \"spec-entrypoint.ts\");\n const bundledSpecFile = path.join(config.specOutputDir, \"spec.js\");\n const wrapperImportSpecifier = createWrapperImportSpecifier(\n wrapperFile,\n config.inputFile\n );\n\n fs.writeFileSync(\n wrapperFile,\n [\n `import * as specModule from ${JSON.stringify(wrapperImportSpecifier)};`,\n \"const resolvedSpec =\",\n ' Reflect.get(specModule, \"spec\") ??',\n ' Reflect.get(specModule, \"default\") ??',\n \" specModule;\",\n \"\",\n \"export const spec = resolvedSpec;\",\n \"\",\n ].join(\"\\n\")\n );\n\n try {\n await build({\n cwd: tempDir,\n input: wrapperFile,\n treeshake: true,\n experimental: {\n attachDebugInfo: \"none\",\n },\n external: (source: string) => {\n if (source.startsWith(\"node:\")) {\n return true;\n }\n\n return !source.startsWith(\".\") && !path.isAbsolute(source);\n },\n output: {\n file: bundledSpecFile,\n format: \"esm\",\n },\n });\n } finally {\n fs.rmSync(tempDir, { recursive: true, force: true });\n }\n\n if (!fs.existsSync(bundledSpecFile)) {\n throw new Error(\n `Failed to bundle spec entrypoint '${config.inputFile}' to '${bundledSpecFile}'.`\n );\n }\n\n return bundledSpecFile;\n}\n\nfunction resolveBundledInputFile(inputFile: string): string {\n if (path.isAbsolute(inputFile)) {\n return inputFile;\n }\n\n if (WINDOWS_ABSOLUTE_PATH_PATTERN.test(inputFile)) {\n return path.win32.normalize(inputFile);\n }\n\n if (WINDOWS_UNC_PATH_PATTERN.test(inputFile)) {\n return path.win32.normalize(inputFile);\n }\n\n return path.resolve(inputFile);\n}\n\nfunction usesWindowsPathSemantics(...filePaths: string[]): boolean {\n return filePaths.some(filePath => {\n return (\n WINDOWS_ABSOLUTE_PATH_PATTERN.test(filePath) ||\n WINDOWS_UNC_PATH_PATTERN.test(filePath)\n );\n });\n}\n\nfunction resolveRealFilePath(filePath: string): string {\n if (!fs.existsSync(filePath)) {\n return filePath;\n }\n\n return fs.realpathSync.native(filePath);\n}\n","export class InvalidSpecEntrypointError extends Error {\n public constructor(specEntrypoint: string) {\n super(\n `Spec entrypoint '${specEntrypoint}' must export a SpecDefinition as its default export, named 'spec' export, or module namespace.`\n );\n this.name = \"InvalidSpecEntrypointError\";\n }\n}\n","import { HttpMethod, HttpStatusCode } from \"@rexeus/typeweaver-core\";\nimport type { SpecDefinition } from \"@rexeus/typeweaver-core\";\n\nconst validHttpStatusCodes = new Set<HttpStatusCode>(\n Object.values(HttpStatusCode).filter(\n (statusCode): statusCode is HttpStatusCode => typeof statusCode === \"number\"\n )\n);\n\nconst isRecord = (value: unknown): value is Record<string, unknown> => {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n};\n\nconst isResponseDefinition = (value: unknown): boolean => {\n if (!isRecord(value)) {\n return false;\n }\n\n return (\n typeof value.name === \"string\" &&\n value.name.length > 0 &&\n typeof value.description === \"string\" &&\n value.description.length > 0 &&\n validHttpStatusCodes.has(value.statusCode as HttpStatusCode)\n );\n};\n\nconst isOperationDefinition = (value: unknown): boolean => {\n if (!isRecord(value) || !Array.isArray(value.responses)) {\n return false;\n }\n\n return (\n typeof value.operationId === \"string\" &&\n value.operationId.length > 0 &&\n typeof value.path === \"string\" &&\n value.path.length > 0 &&\n typeof value.summary === \"string\" &&\n value.summary.length > 0 &&\n Object.values(HttpMethod).includes(value.method as HttpMethod) &&\n isRecord(value.request) &&\n value.responses.length > 0 &&\n value.responses.every(response => isResponseDefinition(response))\n );\n};\n\nconst isResourceDefinition = (value: unknown): boolean => {\n return (\n isRecord(value) &&\n Array.isArray(value.operations) &&\n value.operations.every(isOperationDefinition)\n );\n};\n\nexport const isSpecDefinition = (value: unknown): value is SpecDefinition => {\n if (!isRecord(value) || !isRecord(value.resources)) {\n return false;\n }\n\n return Object.values(value.resources).every(isResourceDefinition);\n};\n","import { createHash } from \"node:crypto\";\nimport fs from \"node:fs\";\nimport { pathToFileURL } from \"node:url\";\nimport type { SpecDefinition } from \"@rexeus/typeweaver-core\";\nimport { InvalidSpecEntrypointError } from \"./InvalidSpecEntrypointError.js\";\nimport { isSpecDefinition } from \"./specGuards.js\";\n\nexport async function importDefinition(\n bundledSpecFile: string\n): Promise<SpecDefinition> {\n const contentHash = createHash(\"sha256\")\n .update(fs.readFileSync(bundledSpecFile))\n .digest(\"hex\");\n const moduleUrl = pathToFileURL(bundledSpecFile);\n\n moduleUrl.searchParams.set(\"content\", contentHash);\n\n const specModule = (await import(moduleUrl.toString())) as {\n readonly spec?: unknown;\n readonly default?: unknown;\n };\n const definition = specModule.spec ?? specModule.default ?? specModule;\n\n if (!isSpecDefinition(definition)) {\n throw new InvalidSpecEntrypointError(bundledSpecFile);\n }\n\n return definition;\n}\n","import fs from \"node:fs\";\nimport type { SpecDefinition } from \"@rexeus/typeweaver-core\";\nimport { normalizeSpec } from \"@rexeus/typeweaver-gen\";\nimport type { NormalizedSpec } from \"@rexeus/typeweaver-gen\";\nimport { bundle } from \"./spec/specBundler.js\";\nimport { importDefinition } from \"./spec/specImporter.js\";\n\nexport type SpecLoaderConfig = {\n readonly inputFile: string;\n readonly specOutputDir: string;\n};\n\nexport type LoadedSpec = {\n readonly definition: SpecDefinition;\n readonly normalizedSpec: NormalizedSpec;\n};\n\nexport async function loadSpec(config: SpecLoaderConfig): Promise<LoadedSpec> {\n fs.mkdirSync(config.specOutputDir, { recursive: true });\n\n const bundledSpecFile = await bundle(config);\n writeSpecDeclarationFile(config.specOutputDir);\n\n const definition = await importDefinition(bundledSpecFile);\n const normalizedSpec = normalizeSpec(definition);\n\n return {\n definition,\n normalizedSpec,\n };\n}\n\nfunction writeSpecDeclarationFile(specOutputDir: string): void {\n fs.writeFileSync(\n `${specOutputDir}/spec.d.ts`,\n [\n 'import type { SpecDefinition } from \"@rexeus/typeweaver-core\";',\n \"export declare const spec: SpecDefinition;\",\n \"\",\n ].join(\"\\n\")\n );\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport {\n createPluginContextBuilder,\n createPluginRegistry,\n} from \"@rexeus/typeweaver-gen\";\nimport type { PluginConfig, TypeweaverConfig } from \"@rexeus/typeweaver-gen\";\nimport { TypesPlugin } from \"@rexeus/typeweaver-types\";\nimport { formatCode } from \"./formatter.js\";\nimport { generateIndexFiles } from \"./indexFileGenerator.js\";\nimport { loadPlugins } from \"./pluginLoader.js\";\nimport { loadSpec } from \"./specLoader.js\";\nimport type { PluginResolutionStrategy } from \"./pluginLoader.js\";\n\nconst moduleDir = path.dirname(fileURLToPath(import.meta.url));\n\nexport const assertSafeCleanTarget = (\n outputDir: string,\n currentWorkingDirectory: string\n): void => {\n const trimmedOutputDir = outputDir.trim();\n if (trimmedOutputDir.length === 0) {\n throw new Error(\n \"Refusing to clean an empty output directory path. Pass a dedicated generated output directory instead.\"\n );\n }\n\n const resolvedWorkingDirectory = path.resolve(currentWorkingDirectory);\n const canonicalWorkingDirectory = fs.realpathSync.native(\n resolvedWorkingDirectory\n );\n const resolvedOutputDir = path.resolve(\n resolvedWorkingDirectory,\n trimmedOutputDir\n );\n const canonicalOutputDir = canonicalizePathForContainment(resolvedOutputDir);\n const filesystemRoot = path.parse(canonicalOutputDir).root;\n\n if (canonicalOutputDir === filesystemRoot) {\n throw new Error(\n `Refusing to clean '${outputDir}' because it resolves to the filesystem root.`\n );\n }\n\n if (\n resolvedOutputDir === resolvedWorkingDirectory ||\n canonicalOutputDir === canonicalWorkingDirectory\n ) {\n throw new Error(\n `Refusing to clean '${outputDir}' because it resolves to the current working directory.`\n );\n }\n\n const logicalProtectedWorkspaceRoot = findProtectedWorkspaceRoot(\n resolvedWorkingDirectory\n );\n const canonicalProtectedWorkspaceRoot = findProtectedWorkspaceRoot(\n canonicalWorkingDirectory\n );\n const protectedWorkspaceRoots = [\n logicalProtectedWorkspaceRoot,\n canonicalProtectedWorkspaceRoot,\n ].filter((root): root is string => root !== undefined);\n const protectedWorkspaceRootTarget = protectedWorkspaceRoots.find(\n protectedWorkspaceRoot =>\n resolvedOutputDir === protectedWorkspaceRoot ||\n canonicalOutputDir === fs.realpathSync.native(protectedWorkspaceRoot)\n );\n\n if (protectedWorkspaceRootTarget !== undefined) {\n throw new Error(\n `Refusing to clean '${outputDir}' because it resolves to the inferred workspace root '${protectedWorkspaceRootTarget}'. Choose a dedicated output subdirectory instead.`\n );\n }\n\n if (\n protectedWorkspaceRoots.length > 0 &&\n (isSameOrDescendantOf(resolvedWorkingDirectory, resolvedOutputDir) ||\n isSameOrDescendantOf(canonicalWorkingDirectory, canonicalOutputDir))\n ) {\n throw new Error(\n `Refusing to clean '${outputDir}' because it resolves to an ancestor directory of the current working directory. Choose a dedicated output subdirectory instead.`\n );\n }\n};\n\n/**\n * Main generator for typeweaver\n * Uses a plugin-based architecture for extensible code generation\n */\nexport class Generator {\n public readonly coreDir = \"@rexeus/typeweaver-core\";\n public readonly templateDir = path.join(moduleDir, \"templates\");\n\n private readonly registry = createPluginRegistry();\n private readonly contextBuilder = createPluginContextBuilder();\n private readonly requiredPlugins: [TypesPlugin];\n private readonly strategies: PluginResolutionStrategy[];\n\n private inputFile = \"\";\n private outputDir = \"\";\n private specOutputDir = \"\";\n private responsesOutputDir = \"\";\n\n public constructor(\n requiredPlugins: [TypesPlugin] = [new TypesPlugin()],\n strategies?: PluginResolutionStrategy[]\n ) {\n this.requiredPlugins = requiredPlugins;\n this.strategies = strategies ?? [\"npm\", \"local\"];\n }\n\n /**\n * Generate code using the plugin system\n */\n public async generate(\n specFile: string,\n outputDir: string,\n config?: TypeweaverConfig,\n currentWorkingDirectory: string = process.cwd()\n ): Promise<void> {\n console.info(\"Starting generation...\");\n\n this.initializeDirectories(specFile, outputDir, currentWorkingDirectory);\n\n if (config?.clean ?? true) {\n assertSafeCleanTarget(this.outputDir, currentWorkingDirectory);\n console.info(\"Cleaning output directory...\");\n fs.rmSync(this.outputDir, { recursive: true, force: true });\n }\n\n fs.mkdirSync(this.outputDir, { recursive: true });\n fs.mkdirSync(this.responsesOutputDir, { recursive: true });\n fs.mkdirSync(this.specOutputDir, { recursive: true });\n\n await loadPlugins(\n this.registry,\n this.requiredPlugins,\n this.strategies,\n config\n );\n\n console.info(\n `Bundling spec from '${this.inputFile}' to '${this.specOutputDir}'...`\n );\n let { normalizedSpec } = await loadSpec({\n inputFile: this.inputFile,\n specOutputDir: this.specOutputDir,\n });\n\n const pluginContext = this.contextBuilder.createPluginContext({\n outputDir: this.outputDir,\n inputDir: path.dirname(this.inputFile),\n config: (config ?? {}) as PluginConfig,\n });\n\n console.info(\"Initializing plugins...\");\n for (const registration of this.registry.getAll()) {\n if (registration.plugin.initialize) {\n await registration.plugin.initialize(pluginContext);\n }\n }\n\n console.info(\"Collecting resources...\");\n for (const registration of this.registry.getAll()) {\n if (registration.plugin.collectResources) {\n normalizedSpec =\n await registration.plugin.collectResources(normalizedSpec);\n }\n }\n\n const generatorContext = this.contextBuilder.createGeneratorContext({\n outputDir: this.outputDir,\n inputDir: path.dirname(this.inputFile),\n config: (config ?? {}) as PluginConfig,\n normalizedSpec,\n templateDir: this.templateDir,\n coreDir: this.coreDir,\n responsesOutputDir: this.responsesOutputDir,\n specOutputDir: this.specOutputDir,\n });\n\n console.info(\"Generating code...\");\n for (const registration of this.registry.getAll()) {\n console.info(`Running plugin: ${registration.plugin.name}`);\n if (registration.plugin.generate) {\n await registration.plugin.generate(generatorContext);\n }\n }\n\n generateIndexFiles(this.templateDir, generatorContext);\n\n console.info(\"Finalizing plugins...\");\n for (const registration of this.registry.getAll()) {\n if (registration.plugin.finalize) {\n await registration.plugin.finalize(pluginContext);\n }\n }\n\n if (config?.format ?? true) {\n await formatCode(this.outputDir);\n }\n\n console.info(\"Generation complete!\");\n console.info(\n `Generated files: ${this.contextBuilder.getGeneratedFiles().length}`\n );\n }\n\n private initializeDirectories(\n specFile: string,\n outputDir: string,\n currentWorkingDirectory: string\n ): void {\n this.inputFile = path.resolve(currentWorkingDirectory, specFile);\n this.outputDir = path.resolve(currentWorkingDirectory, outputDir);\n this.responsesOutputDir = path.join(this.outputDir, \"responses\");\n this.specOutputDir = path.join(this.outputDir, \"spec\");\n }\n}\n\nconst findProtectedWorkspaceRoot = (\n startDirectory: string\n): string | undefined => {\n let currentDirectory = startDirectory;\n\n while (true) {\n if (hasWorkspaceMarker(currentDirectory)) {\n return currentDirectory;\n }\n\n const parentDirectory = path.dirname(currentDirectory);\n if (parentDirectory === currentDirectory) {\n return undefined;\n }\n\n currentDirectory = parentDirectory;\n }\n};\n\nconst hasWorkspaceMarker = (directory: string): boolean => {\n return [\"pnpm-workspace.yaml\", \".git\"].some(marker =>\n fs.existsSync(path.join(directory, marker))\n );\n};\n\nconst canonicalizePathForContainment = (targetPath: string): string => {\n const remainingSegments: string[] = [];\n let nearestExistingPath = path.resolve(targetPath);\n\n while (!fs.existsSync(nearestExistingPath)) {\n const parentPath = path.dirname(nearestExistingPath);\n if (parentPath === nearestExistingPath) {\n break;\n }\n\n remainingSegments.unshift(path.basename(nearestExistingPath));\n nearestExistingPath = parentPath;\n }\n\n const canonicalExistingPath = fs.realpathSync.native(nearestExistingPath);\n\n return path.join(canonicalExistingPath, ...remainingSegments);\n};\n\nconst isSameOrDescendantOf = (directory: string, ancestor: string): boolean => {\n const relativePath = path.relative(ancestor, directory);\n const parentTraversalPrefix = `..${path.sep}`;\n const escapesAncestor =\n relativePath === \"..\" || relativePath.startsWith(parentTraversalPrefix);\n\n return (\n relativePath === \"\" || (!escapesAncestor && !path.isAbsolute(relativePath))\n );\n};\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { TypeweaverConfig } from \"@rexeus/typeweaver-gen\";\nimport { Command } from \"commander\";\nimport { getResolvedConfigPath, loadConfig } from \"./configLoader.js\";\nimport { Generator } from \"./generators/Generator.js\";\nimport type { CommandOptions as CommanderOptions } from \"commander\";\n\nconst moduleDir = path.dirname(fileURLToPath(import.meta.url));\nconst packageJson = JSON.parse(\n fs.readFileSync(path.join(moduleDir, \"../package.json\"), \"utf-8\")\n) as {\n readonly version: string;\n readonly name: string;\n readonly description: string;\n};\n\ntype CommandOptions = CommanderOptions & {\n input?: string;\n output?: string;\n config?: string;\n plugins?: string;\n format?: boolean;\n clean?: boolean;\n};\n\nconst program = new Command();\nconst execDir = process.cwd();\n\nprogram\n .name(\"@rexeus/typeweaver\")\n .description(\"Type-safe API framework with code generation for TypeScript\")\n .version(packageJson.version);\n\nprogram\n .command(\"generate\")\n .description(\"Generate types, validators, and clients from an API spec\")\n .option(\"-i, --input <inputPath>\", \"path to spec entrypoint file\")\n .option(\"-o, --output <outputDir>\", \"output directory for generated files\")\n .option(\n \"-c, --config <configFile>\",\n \"path to a .js, .mjs, or .cjs configuration file\"\n )\n .option(\"-p, --plugins <plugins>\", \"comma-separated list of plugins to use\")\n .option(\"--format\", \"format generated code with oxfmt (default: true)\")\n .option(\"--no-format\", \"disable code formatting\")\n .option(\"--clean\", \"clean output directory before generation (default: true)\")\n .option(\"--no-clean\", \"disable cleaning output directory\")\n .action(async (options: CommandOptions) => {\n let config: Partial<TypeweaverConfig> = {};\n\n // Load configuration file if provided\n if (options.config) {\n const configPath = getResolvedConfigPath(options.config, execDir);\n\n try {\n config = await loadConfig(configPath);\n console.info(`Loaded configuration from ${configPath}`);\n } catch (error) {\n console.error(`Failed to load configuration file: ${options.config}`);\n console.error(error);\n process.exit(1);\n }\n }\n\n // Override with CLI options\n const inputPath = options.input ?? config.input;\n const outputDir = options.output ?? config.output;\n // Validate required options\n if (!inputPath) {\n throw new Error(\n \"No input spec entrypoint provided. Use --input or specify in config file.\"\n );\n }\n if (!outputDir) {\n throw new Error(\n \"No output directory provided. Use --output or specify in config file.\"\n );\n }\n\n // Resolve paths\n const resolvedInputPath = path.isAbsolute(inputPath)\n ? inputPath\n : path.join(execDir, inputPath);\n const resolvedOutputDir = path.isAbsolute(outputDir)\n ? outputDir\n : path.join(execDir, outputDir);\n\n // Build final configuration\n const finalConfig: TypeweaverConfig = {\n input: resolvedInputPath,\n output: resolvedOutputDir,\n format: options.format ?? config.format ?? true,\n clean: options.clean ?? config.clean ?? true,\n };\n\n // Handle plugins\n if (options.plugins) {\n // Parse comma-separated plugins from CLI\n finalConfig.plugins = options.plugins.split(\",\").map(p => p.trim());\n } else if (config.plugins) {\n // Use plugins from config file\n finalConfig.plugins = config.plugins;\n }\n // If no plugins specified, Generator will use defaults\n\n // Run generation\n const generator = new Generator();\n return generator.generate(\n resolvedInputPath,\n resolvedOutputDir,\n finalConfig,\n execDir\n );\n });\n\n// Add future commands placeholder\nprogram\n .command(\"init\")\n .description(\"Initialize a new typeweaver project (coming soon)\")\n .action(() => {\n console.log(\"The init command is coming soon!\");\n });\n\nprogram.parse(process.argv);\n"],"mappings":"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"}
1
+ {"version":3,"file":"cli.mjs","names":["moduleDir"],"sources":["../src/errors/InvalidConfigExportError.ts","../src/errors/UnsupportedConfigExtensionError.ts","../src/errors/UnsupportedTypeScriptConfigError.ts","../src/configLoader.ts","../src/generators/errors/UnsafeCleanTargetError.ts","../src/generators/formatter.ts","../src/generators/indexFileGenerator.ts","../src/generators/errors/PluginLoadingFailure.ts","../src/generators/pluginLoader.ts","../src/generators/spec/errors/SpecBundleOutputMissingError.ts","../src/generators/spec/specBundler.ts","../src/generators/spec/InvalidSpecEntrypointError.ts","../src/generators/spec/specGuards.ts","../src/generators/spec/specImporter.ts","../src/generators/specLoader.ts","../src/generators/Generator.ts","../src/errors/MissingGenerateOptionError.ts","../src/resolveGenerateOptions.ts","../src/cli.ts"],"sourcesContent":["export type InvalidConfigExportReason =\n | \"both-default-and-named-config\"\n | \"default-namespace-wrapper\"\n | \"missing-config-export\"\n | \"non-object-config\";\n\nexport class InvalidConfigExportError extends Error {\n public override readonly name = \"InvalidConfigExportError\";\n\n public constructor(\n public readonly configPath: string,\n public readonly reason: InvalidConfigExportReason\n ) {\n super(getInvalidConfigExportMessage(configPath, reason));\n }\n}\n\nconst getInvalidConfigExportMessage = (\n configPath: string,\n reason: InvalidConfigExportReason\n): string => {\n switch (reason) {\n case \"both-default-and-named-config\":\n return `Configuration file '${configPath}' must choose one export style: use either 'export default' or 'export const config = ...', but not both.`;\n case \"default-namespace-wrapper\":\n return `Configuration file '${configPath}' default export must be the config object itself, not a module namespace-like wrapper. Export the config directly with 'export default { ... }' or use 'export const config = ...'.`;\n case \"missing-config-export\":\n return `Configuration file '${configPath}' must export its config via 'export default' or 'export const config = ...'.`;\n case \"non-object-config\":\n return `Configuration file '${configPath}' must export a config object via 'export default' or 'export const config = ...'.`;\n }\n};\n","export class UnsupportedConfigExtensionError extends Error {\n public override readonly name = \"UnsupportedConfigExtensionError\";\n\n public constructor(\n public readonly configPath: string,\n public readonly extension: string,\n public readonly supportedExtensions: readonly string[]\n ) {\n super(\n `Unsupported config file extension '${extension}' for '${configPath}'. TypeWeaver accepts only these config extensions: ${supportedExtensions.join(\", \")}.`\n );\n }\n}\n","export class UnsupportedTypeScriptConfigError extends Error {\n public override readonly name = \"UnsupportedTypeScriptConfigError\";\n\n public constructor(\n public readonly configPath: string,\n public readonly extension: string\n ) {\n super(\n `TypeScript config files are not supported: '${configPath}' uses '${extension}'. Use a JavaScript config file with one of these extensions: .js, .mjs, or .cjs.`\n );\n }\n}\n","import path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport type { TypeweaverConfig } from \"@rexeus/typeweaver-gen\";\nimport { InvalidConfigExportError } from \"./errors/InvalidConfigExportError.js\";\nimport { UnsupportedConfigExtensionError } from \"./errors/UnsupportedConfigExtensionError.js\";\nimport { UnsupportedTypeScriptConfigError } from \"./errors/UnsupportedTypeScriptConfigError.js\";\n\nconst SUPPORTED_CONFIG_EXTENSIONS = [\".js\", \".mjs\", \".cjs\"] as const;\nconst SUPPORTED_CONFIG_EXTENSION_SET = new Set<string>(\n SUPPORTED_CONFIG_EXTENSIONS\n);\nconst UNSUPPORTED_TYPESCRIPT_CONFIG_EXTENSIONS = new Set([\n \".ts\",\n \".mts\",\n \".cts\",\n]);\n\nexport const getResolvedConfigPath = (\n configPath: string,\n currentWorkingDirectory: string = process.cwd()\n): string => {\n return path.isAbsolute(configPath)\n ? configPath\n : path.resolve(currentWorkingDirectory, configPath);\n};\n\nexport const assertSupportedConfigPath = (configPath: string): void => {\n const extension = path.extname(configPath).toLowerCase();\n\n if (UNSUPPORTED_TYPESCRIPT_CONFIG_EXTENSIONS.has(extension)) {\n throw new UnsupportedTypeScriptConfigError(configPath, extension);\n }\n\n if (!SUPPORTED_CONFIG_EXTENSION_SET.has(extension)) {\n throw new UnsupportedConfigExtensionError(\n configPath,\n extension,\n SUPPORTED_CONFIG_EXTENSIONS\n );\n }\n};\n\nexport const loadConfig = async (\n configPath: string\n): Promise<Partial<TypeweaverConfig>> => {\n assertSupportedConfigPath(configPath);\n\n const resolvedPath = path.resolve(configPath);\n const configUrl = pathToFileURL(resolvedPath).toString();\n const configModule = await import(configUrl);\n const loadedConfig = getConfigExport(configModule, configPath);\n\n if (!isConfigObject(loadedConfig)) {\n throw new InvalidConfigExportError(configPath, \"non-object-config\");\n }\n\n return loadedConfig;\n};\n\nconst getConfigExport = (\n configModule: Record<string, unknown>,\n configPath: string\n): unknown => {\n const hasDefaultExport = Object.hasOwn(configModule, \"default\");\n const hasNamedConfigExport = Object.hasOwn(configModule, \"config\");\n\n if (hasDefaultExport && hasNamedConfigExport) {\n throw new InvalidConfigExportError(\n configPath,\n \"both-default-and-named-config\"\n );\n }\n\n if (hasDefaultExport) {\n if (isNamespaceLikeConfigExport(configModule.default)) {\n throw new InvalidConfigExportError(\n configPath,\n \"default-namespace-wrapper\"\n );\n }\n\n return configModule.default;\n }\n\n if (hasNamedConfigExport) {\n return configModule.config;\n }\n\n throw new InvalidConfigExportError(configPath, \"missing-config-export\");\n};\n\nconst isConfigObject = (value: unknown): value is Partial<TypeweaverConfig> => {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n};\n\nconst isNamespaceLikeConfigExport = (value: unknown): boolean => {\n if (!isConfigObject(value)) {\n return false;\n }\n\n return Object.hasOwn(value, \"default\") || Object.hasOwn(value, \"config\");\n};\n","export type UnsafeCleanTargetReason =\n | \"empty-path\"\n | \"filesystem-root\"\n | \"current-working-directory\"\n | \"workspace-root\"\n | \"ancestor-of-current-working-directory\";\n\nexport type UnsafeCleanTargetDiagnostics = {\n readonly resolvedOutputDir?: string;\n readonly currentWorkingDirectory?: string;\n readonly protectedWorkspaceRoot?: string;\n readonly filesystemRoot?: string;\n};\n\nexport class UnsafeCleanTargetError extends Error {\n public override readonly name = \"UnsafeCleanTargetError\";\n public readonly resolvedOutputDir: string | undefined;\n public readonly currentWorkingDirectory: string | undefined;\n public readonly protectedWorkspaceRoot: string | undefined;\n public readonly filesystemRoot: string | undefined;\n\n public constructor(\n public readonly outputDir: string,\n public readonly reason: UnsafeCleanTargetReason,\n diagnostics: UnsafeCleanTargetDiagnostics = {}\n ) {\n super(getUnsafeCleanTargetMessage(outputDir, reason, diagnostics));\n this.resolvedOutputDir = diagnostics.resolvedOutputDir;\n this.currentWorkingDirectory = diagnostics.currentWorkingDirectory;\n this.protectedWorkspaceRoot = diagnostics.protectedWorkspaceRoot;\n this.filesystemRoot = diagnostics.filesystemRoot;\n }\n}\n\nconst getUnsafeCleanTargetMessage = (\n outputDir: string,\n reason: UnsafeCleanTargetReason,\n diagnostics: UnsafeCleanTargetDiagnostics\n): string => {\n const targetDescription = `Refusing to clean '${outputDir}'`;\n const suffix = \"Use a dedicated generated output directory instead.\";\n\n switch (reason) {\n case \"empty-path\":\n return `Refusing to clean an empty output directory path. ${suffix}`;\n case \"filesystem-root\":\n return `${targetDescription} because it resolves to the filesystem root '${diagnostics.filesystemRoot ?? diagnostics.resolvedOutputDir ?? outputDir}'. ${suffix}`;\n case \"current-working-directory\":\n return `${targetDescription} because it resolves to the current working directory '${diagnostics.currentWorkingDirectory ?? diagnostics.resolvedOutputDir ?? outputDir}'. ${suffix}`;\n case \"workspace-root\":\n return `${targetDescription} because it resolves to the protected workspace root '${diagnostics.protectedWorkspaceRoot ?? diagnostics.resolvedOutputDir ?? outputDir}'. ${suffix}`;\n case \"ancestor-of-current-working-directory\":\n return `${targetDescription} because it resolves to an ancestor directory of the current working directory '${diagnostics.currentWorkingDirectory ?? \"\"}'. ${suffix}`;\n }\n};\n","import fs from \"node:fs\";\nimport path from \"node:path\";\n\ntype FormatFn = (filename: string, source: string) => Promise<{ code: string }>;\n\nexport async function formatCode(\n outputDir: string,\n startDir?: string\n): Promise<void> {\n const format = await loadFormatter();\n if (!format) {\n return;\n }\n\n const targetDir = startDir ?? outputDir;\n await formatDirectory(targetDir, format);\n}\n\nasync function loadFormatter(): Promise<FormatFn | undefined> {\n try {\n const oxfmt = await import(\"oxfmt\");\n return oxfmt.format;\n } catch {\n console.warn(\n \"oxfmt not installed - skipping formatting. Install with: npm install -D oxfmt\"\n );\n return undefined;\n }\n}\n\nasync function formatDirectory(\n targetDir: string,\n format: FormatFn\n): Promise<void> {\n const contents = fs.readdirSync(targetDir, { withFileTypes: true });\n\n for (const content of contents) {\n if (content.isFile()) {\n const filePath = path.join(targetDir, content.name);\n const unformatted = fs.readFileSync(filePath, \"utf8\");\n const { code } = await format(filePath, unformatted);\n fs.writeFileSync(filePath, code);\n } else if (content.isDirectory()) {\n await formatDirectory(path.join(targetDir, content.name), format);\n }\n }\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { renderTemplate } from \"@rexeus/typeweaver-gen\";\nimport type { GeneratorContext } from \"@rexeus/typeweaver-gen\";\n\nexport type IndexFileGenerationContext = Pick<\n GeneratorContext,\n \"outputDir\" | \"getGeneratedFiles\"\n>;\n\nexport function generateIndexFiles(\n templateDir: string,\n context: IndexFileGenerationContext\n): void {\n const templateFilePath = path.join(templateDir, \"Index.ejs\");\n const template = fs.readFileSync(templateFilePath, \"utf8\");\n\n const generatedFiles = context.getGeneratedFiles();\n const groups = new Map<string, Set<string>>();\n const rootFiles = new Set<string>();\n const existingBarrels = new Set<string>();\n\n for (const file of generatedFiles) {\n const normalizedFile = file.replace(/\\\\/g, \"/\");\n const withJsExt = normalizedFile.replace(/\\.ts$/, \".js\");\n const stripped = normalizedFile.replace(/\\.ts$/, \"\");\n const firstSlash = stripped.indexOf(\"/\");\n\n if (stripped === \"index\") {\n continue;\n }\n\n if (firstSlash === -1) {\n rootFiles.add(`./${withJsExt}`);\n continue;\n }\n\n const firstSegment = stripped.slice(0, firstSlash);\n\n if (stripped === \"lib/index\") {\n existingBarrels.add(\"lib\");\n continue;\n }\n\n if (firstSegment === \"lib\") {\n const secondSlash = stripped.indexOf(\"/\", firstSlash + 1);\n const groupKey =\n secondSlash === -1 ? stripped : stripped.slice(0, secondSlash);\n\n const entryName = stripped.slice(groupKey.length + 1);\n\n if (entryName === \"index\") {\n existingBarrels.add(groupKey);\n } else {\n if (!groups.has(groupKey)) {\n groups.set(groupKey, new Set());\n }\n groups.get(groupKey)!.add(`./${entryName}.js`);\n }\n } else {\n const entryName = stripped.slice(firstSlash + 1);\n\n if (entryName === \"index\") {\n existingBarrels.add(firstSegment);\n } else {\n if (!groups.has(firstSegment)) {\n groups.set(firstSegment, new Set());\n }\n groups.get(firstSegment)!.add(`./${entryName}.js`);\n }\n }\n }\n\n for (const [groupKey, entries] of groups) {\n if (existingBarrels.has(groupKey)) {\n continue;\n }\n\n const domainBarrelContent = renderTemplate(template, {\n indexPaths: Array.from(entries).sort(),\n });\n\n const domainIndexPath = path.join(context.outputDir, groupKey, \"index.ts\");\n fs.mkdirSync(path.dirname(domainIndexPath), { recursive: true });\n fs.writeFileSync(domainIndexPath, domainBarrelContent);\n }\n\n const rootIndexPaths = new Set<string>(rootFiles);\n for (const groupKey of groups.keys()) {\n rootIndexPaths.add(`./${groupKey}/index.js`);\n }\n for (const barrelKey of existingBarrels) {\n rootIndexPaths.add(`./${barrelKey}/index.js`);\n }\n\n const rootContent = renderTemplate(template, {\n indexPaths: Array.from(rootIndexPaths).sort(),\n });\n\n fs.writeFileSync(path.join(context.outputDir, \"index.ts\"), rootContent);\n}\n","export type PluginLoadError = {\n readonly pluginName: string;\n readonly attempts: readonly {\n readonly path: string;\n readonly error: string;\n }[];\n};\n\nexport class PluginLoadingFailure extends Error implements PluginLoadError {\n public constructor(\n public readonly pluginName: string,\n public readonly attempts: readonly {\n readonly path: string;\n readonly error: string;\n }[]\n ) {\n super(`Failed to load plugin '${pluginName}'`);\n Object.setPrototypeOf(this, PluginLoadingFailure.prototype);\n }\n}\n","import path from \"node:path\";\nimport { pathToFileURL } from \"node:url\";\nimport type {\n PluginConfig,\n PluginConstructor,\n TypeweaverConfig,\n TypeweaverPlugin,\n} from \"@rexeus/typeweaver-gen\";\nimport { PluginLoadingFailure } from \"./errors/PluginLoadingFailure.js\";\nimport type { PluginLoadError } from \"./errors/PluginLoadingFailure.js\";\n\nexport type PluginResolutionStrategy = \"npm\" | \"local\" | \"scoped\";\n\nexport type PluginRegistrar = {\n readonly register: (plugin: TypeweaverPlugin, config?: unknown) => void;\n};\n\nexport type PluginLoadResult = {\n readonly plugin: TypeweaverPlugin;\n readonly source: string;\n readonly config?: PluginConfig;\n};\n\ntype PluginCandidate = {\n readonly exportName: string;\n readonly constructor: PluginConstructor;\n};\n\ntype LoadResult<T, E> =\n | { success: true; value: T }\n | { success: false; error: E };\n\nexport async function loadPlugins(\n registry: PluginRegistrar,\n requiredPlugins: readonly TypeweaverPlugin[],\n strategies: readonly PluginResolutionStrategy[],\n config?: TypeweaverConfig\n): Promise<void> {\n for (const requiredPlugin of requiredPlugins) {\n registry.register(requiredPlugin);\n }\n\n if (!config?.plugins) {\n return;\n }\n\n const successful: PluginLoadResult[] = [];\n\n for (const plugin of config.plugins) {\n const pluginName = typeof plugin === \"string\" ? plugin : plugin[0];\n const pluginConfig = typeof plugin === \"string\" ? undefined : plugin[1];\n const result = await loadPlugin(pluginName, strategies, pluginConfig);\n\n if (result.success === false) {\n throw new PluginLoadingFailure(\n result.error.pluginName,\n result.error.attempts\n );\n }\n\n successful.push(result.value);\n registry.register(result.value.plugin, result.value.config);\n }\n\n reportSuccessfulLoads(successful);\n}\n\nasync function loadPlugin(\n pluginName: string,\n strategies: readonly PluginResolutionStrategy[],\n pluginConfig?: PluginConfig\n): Promise<LoadResult<PluginLoadResult, PluginLoadError>> {\n const possiblePaths = generatePluginPaths(pluginName, strategies);\n const attempts: { path: string; error: string }[] = [];\n\n for (const possiblePath of possiblePaths) {\n try {\n const pluginPackage = await import(possiblePath);\n const plugin = createPluginInstance(pluginPackage, pluginConfig);\n if (plugin.success) {\n return {\n success: true,\n value: {\n plugin: plugin.value,\n source: possiblePath,\n config: pluginConfig,\n },\n };\n }\n attempts.push({\n path: possiblePath,\n error: plugin.error,\n });\n } catch (error) {\n attempts.push({\n path: possiblePath,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n\n return {\n success: false,\n error: {\n pluginName,\n attempts,\n },\n };\n}\n\nfunction createPluginInstance(\n pluginModule: Record<string, unknown>,\n pluginConfig?: PluginConfig\n): LoadResult<TypeweaverPlugin, string> {\n const candidates = findPluginConstructorCandidates(pluginModule);\n if (candidates.length === 0) {\n return {\n success: false,\n error: \"No plugin constructor export found\",\n };\n }\n\n const errors: string[] = [];\n for (const candidate of candidates) {\n try {\n const plugin = new candidate.constructor(pluginConfig);\n if (isTypeweaverPlugin(plugin)) {\n return {\n success: true,\n value: plugin,\n };\n }\n\n errors.push(\n `Export '${candidate.exportName}' did not produce a valid plugin with a string name`\n );\n } catch (error) {\n errors.push(\n `Export '${candidate.exportName}' could not be instantiated: ${formatError(error)}`\n );\n }\n }\n\n return {\n success: false,\n error: errors.join(\"; \"),\n };\n}\n\nfunction findPluginConstructorCandidates(\n pluginModule: Record<string, unknown>\n): PluginCandidate[] {\n const candidates: PluginCandidate[] = [];\n\n for (const [key, value] of Object.entries(pluginModule)) {\n if (key !== \"default\" && typeof value === \"function\") {\n candidates.push({\n exportName: key,\n constructor: value as PluginConstructor,\n });\n }\n }\n\n // Fall back to default export for third-party plugin compatibility\n const defaultExport = pluginModule.default;\n if (typeof defaultExport === \"function\") {\n candidates.push({\n exportName: \"default\",\n constructor: defaultExport as PluginConstructor,\n });\n }\n\n return candidates;\n}\n\nfunction isTypeweaverPlugin(value: unknown): value is TypeweaverPlugin {\n return (\n typeof value === \"object\" &&\n value !== null &&\n typeof (value as { readonly name?: unknown }).name === \"string\" &&\n (value as { readonly name: string }).name.length > 0\n );\n}\n\nfunction formatError(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\nfunction generatePluginPaths(\n pluginName: string,\n strategies: readonly PluginResolutionStrategy[]\n): string[] {\n const paths: string[] = [];\n\n for (const strategy of strategies) {\n switch (strategy) {\n case \"npm\":\n paths.push(`@rexeus/typeweaver-${pluginName}`);\n paths.push(`@rexeus/${pluginName}`);\n break;\n case \"local\":\n paths.push(toLocalImportSpecifier(pluginName));\n break;\n case \"scoped\":\n paths.push(pluginName);\n break;\n }\n }\n\n return paths;\n}\n\nfunction toLocalImportSpecifier(pluginName: string): string {\n if (pluginName.startsWith(\"file:\")) {\n return pluginName;\n }\n\n if (path.isAbsolute(pluginName)) {\n return pathToFileURL(pluginName).href;\n }\n\n return pluginName;\n}\n\nfunction reportSuccessfulLoads(successful: PluginLoadResult[]): void {\n if (successful.length > 0) {\n console.info(`Successfully loaded ${successful.length} plugin(s):`);\n for (const result of successful) {\n console.info(` - ${result.plugin.name} (from ${result.source})`);\n }\n }\n}\n","export class SpecBundleOutputMissingError extends Error {\n public override readonly name = \"SpecBundleOutputMissingError\";\n\n public constructor(\n public readonly inputFile: string,\n public readonly bundledSpecFile: string,\n public readonly specOutputDir: string\n ) {\n super(\n `Spec bundling completed but did not create the expected output '${bundledSpecFile}' for entrypoint '${inputFile}'. Expected the bundle inside '${specOutputDir}'.`\n );\n }\n}\n","import fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { build } from \"rolldown\";\nimport { SpecBundleOutputMissingError } from \"./errors/SpecBundleOutputMissingError.js\";\n\nconst WINDOWS_ABSOLUTE_PATH_PATTERN = /^[A-Za-z]:[\\\\/]/;\nconst WINDOWS_UNC_PATH_PATTERN = /^\\\\\\\\/;\n\nexport type SpecBundlerConfig = {\n readonly inputFile: string;\n readonly specOutputDir: string;\n};\n\nexport type SpecBundlerDeps = {\n readonly build?: typeof build;\n readonly existsSync?: (filePath: string) => boolean;\n};\n\nexport function createWrapperImportSpecifier(\n wrapperFile: string,\n inputFile: string\n): string {\n const absoluteInputFile = resolveBundledInputFile(inputFile);\n const useWindowsPathSemantics = usesWindowsPathSemantics(\n wrapperFile,\n absoluteInputFile\n );\n const pathModule = useWindowsPathSemantics ? path.win32 : path.posix;\n const wrapperDir = useWindowsPathSemantics\n ? pathModule.dirname(wrapperFile)\n : resolveRealFilePath(pathModule.dirname(wrapperFile));\n const resolvedInputFile = useWindowsPathSemantics\n ? absoluteInputFile\n : resolveRealFilePath(absoluteInputFile);\n const relativeInputFile = pathModule\n .relative(wrapperDir, resolvedInputFile)\n .replaceAll(pathModule.sep, \"/\");\n\n if (relativeInputFile.startsWith(\".\") || relativeInputFile.startsWith(\"..\")) {\n return relativeInputFile;\n }\n\n return `./${relativeInputFile}`;\n}\n\nexport async function bundle(\n config: SpecBundlerConfig,\n deps: SpecBundlerDeps = {}\n): Promise<string> {\n const tempDir = fs.mkdtempSync(\n path.join(os.tmpdir(), \"typeweaver-spec-loader-\")\n );\n const wrapperFile = path.join(tempDir, \"spec-entrypoint.ts\");\n const bundledSpecFile = path.join(config.specOutputDir, \"spec.js\");\n const wrapperImportSpecifier = createWrapperImportSpecifier(\n wrapperFile,\n config.inputFile\n );\n\n fs.writeFileSync(\n wrapperFile,\n [\n `import * as specModule from ${JSON.stringify(wrapperImportSpecifier)};`,\n \"const resolvedSpec =\",\n ' Reflect.get(specModule, \"spec\") ??',\n ' Reflect.get(specModule, \"default\") ??',\n \" specModule;\",\n \"\",\n \"export const spec = resolvedSpec;\",\n \"\",\n ].join(\"\\n\")\n );\n\n try {\n await (deps.build ?? build)({\n cwd: tempDir,\n input: wrapperFile,\n treeshake: true,\n experimental: {\n attachDebugInfo: \"none\",\n },\n external: (source: string) => {\n if (source.startsWith(\"node:\")) {\n return true;\n }\n\n return !source.startsWith(\".\") && !path.isAbsolute(source);\n },\n output: {\n file: bundledSpecFile,\n format: \"esm\",\n },\n });\n } finally {\n fs.rmSync(tempDir, { recursive: true, force: true });\n }\n\n if (!(deps.existsSync ?? fs.existsSync)(bundledSpecFile)) {\n throw new SpecBundleOutputMissingError(\n config.inputFile,\n bundledSpecFile,\n config.specOutputDir\n );\n }\n\n return bundledSpecFile;\n}\n\nfunction resolveBundledInputFile(inputFile: string): string {\n if (path.isAbsolute(inputFile)) {\n return inputFile;\n }\n\n if (WINDOWS_ABSOLUTE_PATH_PATTERN.test(inputFile)) {\n return path.win32.normalize(inputFile);\n }\n\n if (WINDOWS_UNC_PATH_PATTERN.test(inputFile)) {\n return path.win32.normalize(inputFile);\n }\n\n return path.resolve(inputFile);\n}\n\nfunction usesWindowsPathSemantics(...filePaths: string[]): boolean {\n return filePaths.some(filePath => {\n return (\n WINDOWS_ABSOLUTE_PATH_PATTERN.test(filePath) ||\n WINDOWS_UNC_PATH_PATTERN.test(filePath)\n );\n });\n}\n\nfunction resolveRealFilePath(filePath: string): string {\n if (!fs.existsSync(filePath)) {\n return filePath;\n }\n\n return fs.realpathSync.native(filePath);\n}\n","export class InvalidSpecEntrypointError extends Error {\n public constructor(specEntrypoint: string) {\n super(\n `Spec entrypoint '${specEntrypoint}' must export a SpecDefinition as its default export, named 'spec' export, or module namespace.`\n );\n this.name = \"InvalidSpecEntrypointError\";\n }\n}\n","import { HttpMethod, HttpStatusCode } from \"@rexeus/typeweaver-core\";\nimport type { SpecDefinition } from \"@rexeus/typeweaver-core\";\n\nconst validHttpStatusCodes = new Set<HttpStatusCode>(\n Object.values(HttpStatusCode).filter(\n (statusCode): statusCode is HttpStatusCode => typeof statusCode === \"number\"\n )\n);\n\nconst isRecord = (value: unknown): value is Record<string, unknown> => {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n};\n\nconst isResponseDefinition = (value: unknown): boolean => {\n if (!isRecord(value)) {\n return false;\n }\n\n return (\n typeof value.name === \"string\" &&\n value.name.length > 0 &&\n typeof value.description === \"string\" &&\n value.description.length > 0 &&\n validHttpStatusCodes.has(value.statusCode as HttpStatusCode)\n );\n};\n\nconst isOperationDefinition = (value: unknown): boolean => {\n if (!isRecord(value) || !Array.isArray(value.responses)) {\n return false;\n }\n\n return (\n typeof value.operationId === \"string\" &&\n value.operationId.length > 0 &&\n typeof value.path === \"string\" &&\n value.path.length > 0 &&\n typeof value.summary === \"string\" &&\n value.summary.length > 0 &&\n Object.values(HttpMethod).includes(value.method as HttpMethod) &&\n isRecord(value.request) &&\n value.responses.length > 0 &&\n value.responses.every(response => isResponseDefinition(response))\n );\n};\n\nconst isResourceDefinition = (value: unknown): boolean => {\n return (\n isRecord(value) &&\n Array.isArray(value.operations) &&\n value.operations.every(isOperationDefinition)\n );\n};\n\nexport const isSpecDefinition = (value: unknown): value is SpecDefinition => {\n if (!isRecord(value) || !isRecord(value.resources)) {\n return false;\n }\n\n return Object.values(value.resources).every(isResourceDefinition);\n};\n","import { createHash } from \"node:crypto\";\nimport fs from \"node:fs\";\nimport { pathToFileURL } from \"node:url\";\nimport type { SpecDefinition } from \"@rexeus/typeweaver-core\";\nimport { InvalidSpecEntrypointError } from \"./InvalidSpecEntrypointError.js\";\nimport { isSpecDefinition } from \"./specGuards.js\";\n\nexport async function importDefinition(\n bundledSpecFile: string\n): Promise<SpecDefinition> {\n const contentHash = createHash(\"sha256\")\n .update(fs.readFileSync(bundledSpecFile))\n .digest(\"hex\");\n const moduleUrl = pathToFileURL(bundledSpecFile);\n\n moduleUrl.searchParams.set(\"content\", contentHash);\n\n const specModule = (await import(moduleUrl.toString())) as {\n readonly spec?: unknown;\n readonly default?: unknown;\n };\n const definition = specModule.spec ?? specModule.default ?? specModule;\n\n if (!isSpecDefinition(definition)) {\n throw new InvalidSpecEntrypointError(bundledSpecFile);\n }\n\n return definition;\n}\n","import fs from \"node:fs\";\nimport type { SpecDefinition } from \"@rexeus/typeweaver-core\";\nimport { normalizeSpec } from \"@rexeus/typeweaver-gen\";\nimport type { NormalizedSpec } from \"@rexeus/typeweaver-gen\";\nimport { bundle } from \"./spec/specBundler.js\";\nimport { importDefinition } from \"./spec/specImporter.js\";\n\nexport type SpecLoaderConfig = {\n readonly inputFile: string;\n readonly specOutputDir: string;\n};\n\nexport type LoadedSpec = {\n readonly definition: SpecDefinition;\n readonly normalizedSpec: NormalizedSpec;\n};\n\nexport async function loadSpec(config: SpecLoaderConfig): Promise<LoadedSpec> {\n fs.mkdirSync(config.specOutputDir, { recursive: true });\n\n const bundledSpecFile = await bundle(config);\n writeSpecDeclarationFile(config.specOutputDir);\n\n const definition = await importDefinition(bundledSpecFile);\n const normalizedSpec = normalizeSpec(definition);\n\n return {\n definition,\n normalizedSpec,\n };\n}\n\nfunction writeSpecDeclarationFile(specOutputDir: string): void {\n fs.writeFileSync(\n `${specOutputDir}/spec.d.ts`,\n [\n 'import type { SpecDefinition } from \"@rexeus/typeweaver-core\";',\n \"export declare const spec: SpecDefinition;\",\n \"\",\n ].join(\"\\n\")\n );\n}\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport {\n createPluginContextBuilder,\n createPluginRegistry,\n} from \"@rexeus/typeweaver-gen\";\nimport type { PluginConfig, TypeweaverConfig } from \"@rexeus/typeweaver-gen\";\nimport { TypesPlugin } from \"@rexeus/typeweaver-types\";\nimport { UnsafeCleanTargetError } from \"./errors/UnsafeCleanTargetError.js\";\nimport { formatCode } from \"./formatter.js\";\nimport { generateIndexFiles } from \"./indexFileGenerator.js\";\nimport { loadPlugins } from \"./pluginLoader.js\";\nimport { loadSpec } from \"./specLoader.js\";\nimport type { PluginResolutionStrategy } from \"./pluginLoader.js\";\n\nconst moduleDir = path.dirname(fileURLToPath(import.meta.url));\n\nexport const assertSafeCleanTarget = (\n outputDir: string,\n currentWorkingDirectory: string\n): void => {\n const trimmedOutputDir = outputDir.trim();\n if (trimmedOutputDir.length === 0) {\n throw new UnsafeCleanTargetError(outputDir, \"empty-path\");\n }\n\n const resolvedWorkingDirectory = path.resolve(currentWorkingDirectory);\n const canonicalWorkingDirectory = fs.realpathSync.native(\n resolvedWorkingDirectory\n );\n const resolvedOutputDir = path.resolve(\n resolvedWorkingDirectory,\n trimmedOutputDir\n );\n const canonicalOutputDir = canonicalizePathForContainment(resolvedOutputDir);\n const filesystemRoot = path.parse(canonicalOutputDir).root;\n\n if (canonicalOutputDir === filesystemRoot) {\n throw new UnsafeCleanTargetError(outputDir, \"filesystem-root\", {\n resolvedOutputDir,\n currentWorkingDirectory: resolvedWorkingDirectory,\n filesystemRoot,\n });\n }\n\n if (\n resolvedOutputDir === resolvedWorkingDirectory ||\n canonicalOutputDir === canonicalWorkingDirectory\n ) {\n throw new UnsafeCleanTargetError(outputDir, \"current-working-directory\", {\n resolvedOutputDir,\n currentWorkingDirectory: resolvedWorkingDirectory,\n });\n }\n\n const logicalProtectedWorkspaceRoot = findProtectedWorkspaceRoot(\n resolvedWorkingDirectory\n );\n const canonicalProtectedWorkspaceRoot = findProtectedWorkspaceRoot(\n canonicalWorkingDirectory\n );\n const protectedWorkspaceRoots = [\n logicalProtectedWorkspaceRoot,\n canonicalProtectedWorkspaceRoot,\n ].filter((root): root is string => root !== undefined);\n const protectedWorkspaceRootTarget = protectedWorkspaceRoots.find(\n protectedWorkspaceRoot =>\n resolvedOutputDir === protectedWorkspaceRoot ||\n canonicalOutputDir === fs.realpathSync.native(protectedWorkspaceRoot)\n );\n\n if (protectedWorkspaceRootTarget !== undefined) {\n throw new UnsafeCleanTargetError(outputDir, \"workspace-root\", {\n resolvedOutputDir,\n currentWorkingDirectory: resolvedWorkingDirectory,\n protectedWorkspaceRoot: protectedWorkspaceRootTarget,\n });\n }\n\n if (\n protectedWorkspaceRoots.length > 0 &&\n (isSameOrDescendantOf(resolvedWorkingDirectory, resolvedOutputDir) ||\n isSameOrDescendantOf(canonicalWorkingDirectory, canonicalOutputDir))\n ) {\n throw new UnsafeCleanTargetError(\n outputDir,\n \"ancestor-of-current-working-directory\",\n {\n resolvedOutputDir,\n currentWorkingDirectory: resolvedWorkingDirectory,\n }\n );\n }\n};\n\n/**\n * Main generator for typeweaver\n * Uses a plugin-based architecture for extensible code generation\n */\nexport class Generator {\n public readonly coreDir = \"@rexeus/typeweaver-core\";\n public readonly templateDir = path.join(moduleDir, \"templates\");\n\n private readonly registry = createPluginRegistry();\n private readonly contextBuilder = createPluginContextBuilder();\n private readonly requiredPlugins: [TypesPlugin];\n private readonly strategies: PluginResolutionStrategy[];\n\n private inputFile = \"\";\n private outputDir = \"\";\n private specOutputDir = \"\";\n private responsesOutputDir = \"\";\n\n public constructor(\n requiredPlugins: [TypesPlugin] = [new TypesPlugin()],\n strategies?: PluginResolutionStrategy[]\n ) {\n this.requiredPlugins = requiredPlugins;\n this.strategies = strategies ?? [\"npm\", \"local\"];\n }\n\n /**\n * Generate code using the plugin system\n */\n public async generate(\n specFile: string,\n outputDir: string,\n config?: TypeweaverConfig,\n currentWorkingDirectory: string = process.cwd()\n ): Promise<void> {\n console.info(\"Starting generation...\");\n\n this.initializeDirectories(specFile, outputDir, currentWorkingDirectory);\n\n if (config?.clean ?? true) {\n assertSafeCleanTarget(this.outputDir, currentWorkingDirectory);\n console.info(\"Cleaning output directory...\");\n fs.rmSync(this.outputDir, { recursive: true, force: true });\n }\n\n fs.mkdirSync(this.outputDir, { recursive: true });\n fs.mkdirSync(this.responsesOutputDir, { recursive: true });\n fs.mkdirSync(this.specOutputDir, { recursive: true });\n\n await loadPlugins(\n this.registry,\n this.requiredPlugins,\n this.strategies,\n config\n );\n\n console.info(\n `Bundling spec from '${this.inputFile}' to '${this.specOutputDir}'...`\n );\n let { normalizedSpec } = await loadSpec({\n inputFile: this.inputFile,\n specOutputDir: this.specOutputDir,\n });\n\n const pluginContext = this.contextBuilder.createPluginContext({\n outputDir: this.outputDir,\n inputDir: path.dirname(this.inputFile),\n config: (config ?? {}) as PluginConfig,\n });\n\n console.info(\"Initializing plugins...\");\n for (const registration of this.registry.getAll()) {\n if (registration.plugin.initialize) {\n await registration.plugin.initialize(pluginContext);\n }\n }\n\n console.info(\"Collecting resources...\");\n for (const registration of this.registry.getAll()) {\n if (registration.plugin.collectResources) {\n normalizedSpec =\n await registration.plugin.collectResources(normalizedSpec);\n }\n }\n\n const generatorContext = this.contextBuilder.createGeneratorContext({\n outputDir: this.outputDir,\n inputDir: path.dirname(this.inputFile),\n config: (config ?? {}) as PluginConfig,\n normalizedSpec,\n templateDir: this.templateDir,\n coreDir: this.coreDir,\n responsesOutputDir: this.responsesOutputDir,\n specOutputDir: this.specOutputDir,\n });\n\n console.info(\"Generating code...\");\n for (const registration of this.registry.getAll()) {\n console.info(`Running plugin: ${registration.plugin.name}`);\n if (registration.plugin.generate) {\n await registration.plugin.generate(generatorContext);\n }\n }\n\n generateIndexFiles(this.templateDir, generatorContext);\n\n console.info(\"Finalizing plugins...\");\n for (const registration of this.registry.getAll()) {\n if (registration.plugin.finalize) {\n await registration.plugin.finalize(pluginContext);\n }\n }\n\n if (config?.format ?? true) {\n await formatCode(this.outputDir);\n }\n\n console.info(\"Generation complete!\");\n console.info(\n `Generated files: ${this.contextBuilder.getGeneratedFiles().length}`\n );\n }\n\n private initializeDirectories(\n specFile: string,\n outputDir: string,\n currentWorkingDirectory: string\n ): void {\n this.inputFile = path.resolve(currentWorkingDirectory, specFile);\n this.outputDir = path.resolve(currentWorkingDirectory, outputDir);\n this.responsesOutputDir = path.join(this.outputDir, \"responses\");\n this.specOutputDir = path.join(this.outputDir, \"spec\");\n }\n}\n\nconst findProtectedWorkspaceRoot = (\n startDirectory: string\n): string | undefined => {\n let currentDirectory = startDirectory;\n\n while (true) {\n if (hasWorkspaceMarker(currentDirectory)) {\n return currentDirectory;\n }\n\n const parentDirectory = path.dirname(currentDirectory);\n if (parentDirectory === currentDirectory) {\n return undefined;\n }\n\n currentDirectory = parentDirectory;\n }\n};\n\nconst hasWorkspaceMarker = (directory: string): boolean => {\n return [\"pnpm-workspace.yaml\", \".git\"].some(marker =>\n fs.existsSync(path.join(directory, marker))\n );\n};\n\nconst canonicalizePathForContainment = (targetPath: string): string => {\n const remainingSegments: string[] = [];\n let nearestExistingPath = path.resolve(targetPath);\n\n while (!fs.existsSync(nearestExistingPath)) {\n const parentPath = path.dirname(nearestExistingPath);\n if (parentPath === nearestExistingPath) {\n break;\n }\n\n remainingSegments.unshift(path.basename(nearestExistingPath));\n nearestExistingPath = parentPath;\n }\n\n const canonicalExistingPath = fs.realpathSync.native(nearestExistingPath);\n\n return path.join(canonicalExistingPath, ...remainingSegments);\n};\n\nconst isSameOrDescendantOf = (directory: string, ancestor: string): boolean => {\n const relativePath = path.relative(ancestor, directory);\n const parentTraversalPrefix = `..${path.sep}`;\n const escapesAncestor =\n relativePath === \"..\" || relativePath.startsWith(parentTraversalPrefix);\n\n return (\n relativePath === \"\" || (!escapesAncestor && !path.isAbsolute(relativePath))\n );\n};\n","export class MissingGenerateOptionError extends Error {\n public override readonly name = \"MissingGenerateOptionError\";\n\n public constructor(\n public readonly optionName: string,\n public readonly flag: string,\n public readonly configKey: string\n ) {\n super(\n `Missing required generate option '${optionName}'. Pass ${flag} or set '${configKey}' in the TypeWeaver config file.`\n );\n }\n}\n","import path from \"node:path\";\nimport type { TypeweaverConfig } from \"@rexeus/typeweaver-gen\";\nimport { MissingGenerateOptionError } from \"./errors/MissingGenerateOptionError.js\";\n\nexport type GenerateCommandOptions = {\n readonly input?: string;\n readonly output?: string;\n readonly plugins?: string;\n readonly format?: boolean;\n readonly clean?: boolean;\n};\n\nexport type ResolvedGenerateOptions = {\n readonly inputPath: string;\n readonly outputDir: string;\n readonly config: TypeweaverConfig;\n};\n\nexport const resolveGenerateOptions = (\n options: GenerateCommandOptions,\n config: Partial<TypeweaverConfig>,\n currentWorkingDirectory: string\n): ResolvedGenerateOptions => {\n const inputPath = options.input ?? config.input;\n const outputDir = options.output ?? config.output;\n\n if (!inputPath) {\n throw new MissingGenerateOptionError(\"input\", \"--input\", \"input\");\n }\n\n if (!outputDir) {\n throw new MissingGenerateOptionError(\"output\", \"--output\", \"output\");\n }\n\n const resolvedInputPath = path.isAbsolute(inputPath)\n ? inputPath\n : path.join(currentWorkingDirectory, inputPath);\n const resolvedOutputDir = path.isAbsolute(outputDir)\n ? outputDir\n : path.join(currentWorkingDirectory, outputDir);\n const finalConfig: TypeweaverConfig = {\n input: resolvedInputPath,\n output: resolvedOutputDir,\n format: options.format ?? config.format ?? true,\n clean: options.clean ?? config.clean ?? true,\n };\n\n if (options.plugins) {\n finalConfig.plugins = options.plugins\n .split(\",\")\n .map(plugin => plugin.trim());\n } else if (config.plugins) {\n finalConfig.plugins = config.plugins;\n }\n\n return {\n inputPath: resolvedInputPath,\n outputDir: resolvedOutputDir,\n config: finalConfig,\n };\n};\n","import fs from \"node:fs\";\nimport path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { TypeweaverConfig } from \"@rexeus/typeweaver-gen\";\nimport { Command } from \"commander\";\nimport { getResolvedConfigPath, loadConfig } from \"./configLoader.js\";\nimport { Generator } from \"./generators/Generator.js\";\nimport { resolveGenerateOptions } from \"./resolveGenerateOptions.js\";\nimport type { CommandOptions as CommanderOptions } from \"commander\";\n\nconst moduleDir = path.dirname(fileURLToPath(import.meta.url));\nconst packageJson = JSON.parse(\n fs.readFileSync(path.join(moduleDir, \"../package.json\"), \"utf-8\")\n) as {\n readonly version: string;\n readonly name: string;\n readonly description: string;\n};\n\ntype CommandOptions = CommanderOptions & {\n input?: string;\n output?: string;\n config?: string;\n plugins?: string;\n format?: boolean;\n clean?: boolean;\n};\n\nconst program = new Command();\nconst execDir = process.cwd();\n\nprogram\n .name(\"@rexeus/typeweaver\")\n .description(\"Type-safe API framework with code generation for TypeScript\")\n .version(packageJson.version);\n\nprogram\n .command(\"generate\")\n .description(\"Generate types, validators, and clients from an API spec\")\n .option(\"-i, --input <inputPath>\", \"path to spec entrypoint file\")\n .option(\"-o, --output <outputDir>\", \"output directory for generated files\")\n .option(\n \"-c, --config <configFile>\",\n \"path to a .js, .mjs, or .cjs configuration file\"\n )\n .option(\"-p, --plugins <plugins>\", \"comma-separated list of plugins to use\")\n .option(\"--format\", \"format generated code with oxfmt (default: true)\")\n .option(\"--no-format\", \"disable code formatting\")\n .option(\"--clean\", \"clean output directory before generation (default: true)\")\n .option(\"--no-clean\", \"disable cleaning output directory\")\n .action(async (options: CommandOptions) => {\n let config: Partial<TypeweaverConfig> = {};\n\n // Load configuration file if provided\n if (options.config) {\n const configPath = getResolvedConfigPath(options.config, execDir);\n\n try {\n config = await loadConfig(configPath);\n console.info(`Loaded configuration from ${configPath}`);\n } catch (error) {\n console.error(`Failed to load configuration file: ${options.config}`);\n console.error(error);\n process.exit(1);\n }\n }\n\n const resolvedGenerateOptions = resolveGenerateOptions(\n options,\n config,\n execDir\n );\n\n // Run generation\n const generator = new Generator();\n return generator.generate(\n resolvedGenerateOptions.inputPath,\n resolvedGenerateOptions.outputDir,\n resolvedGenerateOptions.config,\n execDir\n );\n });\n\n// Add future commands placeholder\nprogram\n .command(\"init\")\n .description(\"Initialize a new typeweaver project (coming soon)\")\n .action(() => {\n console.log(\"The init command is coming soon!\");\n });\n\nprogram.parse(process.argv);\n"],"mappings":";;;;;;;;;;;AAMA,IAAa,2BAAb,cAA8C,MAAM;CAClD,OAAgC;CAEhC,YACE,YACA,QACA;AACA,QAAM,8BAA8B,YAAY,OAAO,CAAC;AAHxC,OAAA,aAAA;AACA,OAAA,SAAA;;;AAMpB,MAAM,iCACJ,YACA,WACW;AACX,SAAQ,QAAR;EACE,KAAK,gCACH,QAAO,uBAAuB,WAAW;EAC3C,KAAK,4BACH,QAAO,uBAAuB,WAAW;EAC3C,KAAK,wBACH,QAAO,uBAAuB,WAAW;EAC3C,KAAK,oBACH,QAAO,uBAAuB,WAAW;;;;;AC7B/C,IAAa,kCAAb,cAAqD,MAAM;CACzD,OAAgC;CAEhC,YACE,YACA,WACA,qBACA;AACA,QACE,sCAAsC,UAAU,SAAS,WAAW,sDAAsD,oBAAoB,KAAK,KAAK,CAAC,GAC1J;AANe,OAAA,aAAA;AACA,OAAA,YAAA;AACA,OAAA,sBAAA;;;;;ACNpB,IAAa,mCAAb,cAAsD,MAAM;CAC1D,OAAgC;CAEhC,YACE,YACA,WACA;AACA,QACE,+CAA+C,WAAW,UAAU,UAAU,mFAC/E;AALe,OAAA,aAAA;AACA,OAAA,YAAA;;;;;ACEpB,MAAM,8BAA8B;CAAC;CAAO;CAAQ;CAAO;AAC3D,MAAM,iCAAiC,IAAI,IACzC,4BACD;AACD,MAAM,2CAA2C,IAAI,IAAI;CACvD;CACA;CACA;CACD,CAAC;AAEF,MAAa,yBACX,YACA,0BAAkC,QAAQ,KAAK,KACpC;AACX,QAAO,KAAK,WAAW,WAAW,GAC9B,aACA,KAAK,QAAQ,yBAAyB,WAAW;;AAGvD,MAAa,6BAA6B,eAA6B;CACrE,MAAM,YAAY,KAAK,QAAQ,WAAW,CAAC,aAAa;AAExD,KAAI,yCAAyC,IAAI,UAAU,CACzD,OAAM,IAAI,iCAAiC,YAAY,UAAU;AAGnE,KAAI,CAAC,+BAA+B,IAAI,UAAU,CAChD,OAAM,IAAI,gCACR,YACA,WACA,4BACD;;AAIL,MAAa,aAAa,OACxB,eACuC;AACvC,2BAA0B,WAAW;CAKrC,MAAM,eAAe,gBADA,MAAM,OADT,cADG,KAAK,QAAQ,WAAW,CACA,CAAC,UAAU,GAEL,WAAW;AAE9D,KAAI,CAAC,eAAe,aAAa,CAC/B,OAAM,IAAI,yBAAyB,YAAY,oBAAoB;AAGrE,QAAO;;AAGT,MAAM,mBACJ,cACA,eACY;CACZ,MAAM,mBAAmB,OAAO,OAAO,cAAc,UAAU;CAC/D,MAAM,uBAAuB,OAAO,OAAO,cAAc,SAAS;AAElE,KAAI,oBAAoB,qBACtB,OAAM,IAAI,yBACR,YACA,gCACD;AAGH,KAAI,kBAAkB;AACpB,MAAI,4BAA4B,aAAa,QAAQ,CACnD,OAAM,IAAI,yBACR,YACA,4BACD;AAGH,SAAO,aAAa;;AAGtB,KAAI,qBACF,QAAO,aAAa;AAGtB,OAAM,IAAI,yBAAyB,YAAY,wBAAwB;;AAGzE,MAAM,kBAAkB,UAAuD;AAC7E,QAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,MAAM;;AAG7E,MAAM,+BAA+B,UAA4B;AAC/D,KAAI,CAAC,eAAe,MAAM,CACxB,QAAO;AAGT,QAAO,OAAO,OAAO,OAAO,UAAU,IAAI,OAAO,OAAO,OAAO,SAAS;;;;ACtF1E,IAAa,yBAAb,cAA4C,MAAM;CAChD,OAAgC;CAChC;CACA;CACA;CACA;CAEA,YACE,WACA,QACA,cAA4C,EAAE,EAC9C;AACA,QAAM,4BAA4B,WAAW,QAAQ,YAAY,CAAC;AAJlD,OAAA,YAAA;AACA,OAAA,SAAA;AAIhB,OAAK,oBAAoB,YAAY;AACrC,OAAK,0BAA0B,YAAY;AAC3C,OAAK,yBAAyB,YAAY;AAC1C,OAAK,iBAAiB,YAAY;;;AAItC,MAAM,+BACJ,WACA,QACA,gBACW;CACX,MAAM,oBAAoB,sBAAsB,UAAU;CAC1D,MAAM,SAAS;AAEf,SAAQ,QAAR;EACE,KAAK,aACH,QAAO,qDAAqD;EAC9D,KAAK,kBACH,QAAO,GAAG,kBAAkB,+CAA+C,YAAY,kBAAkB,YAAY,qBAAqB,UAAU,KAAK;EAC3J,KAAK,4BACH,QAAO,GAAG,kBAAkB,yDAAyD,YAAY,2BAA2B,YAAY,qBAAqB,UAAU,KAAK;EAC9K,KAAK,iBACH,QAAO,GAAG,kBAAkB,wDAAwD,YAAY,0BAA0B,YAAY,qBAAqB,UAAU,KAAK;EAC5K,KAAK,wCACH,QAAO,GAAG,kBAAkB,kFAAkF,YAAY,2BAA2B,GAAG,KAAK;;;;;AC/CnK,eAAsB,WACpB,WACA,UACe;CACf,MAAM,SAAS,MAAM,eAAe;AACpC,KAAI,CAAC,OACH;AAIF,OAAM,gBADY,YAAY,WACG,OAAO;;AAG1C,eAAe,gBAA+C;AAC5D,KAAI;AAEF,UADc,MAAM,OAAO,UACd;SACP;AACN,UAAQ,KACN,gFACD;AACD;;;AAIJ,eAAe,gBACb,WACA,QACe;CACf,MAAM,WAAW,GAAG,YAAY,WAAW,EAAE,eAAe,MAAM,CAAC;AAEnE,MAAK,MAAM,WAAW,SACpB,KAAI,QAAQ,QAAQ,EAAE;EACpB,MAAM,WAAW,KAAK,KAAK,WAAW,QAAQ,KAAK;EAEnD,MAAM,EAAE,SAAS,MAAM,OAAO,UADV,GAAG,aAAa,UAAU,OAAO,CACD;AACpD,KAAG,cAAc,UAAU,KAAK;YACvB,QAAQ,aAAa,CAC9B,OAAM,gBAAgB,KAAK,KAAK,WAAW,QAAQ,KAAK,EAAE,OAAO;;;;ACjCvE,SAAgB,mBACd,aACA,SACM;CACN,MAAM,mBAAmB,KAAK,KAAK,aAAa,YAAY;CAC5D,MAAM,WAAW,GAAG,aAAa,kBAAkB,OAAO;CAE1D,MAAM,iBAAiB,QAAQ,mBAAmB;CAClD,MAAM,yBAAS,IAAI,KAA0B;CAC7C,MAAM,4BAAY,IAAI,KAAa;CACnC,MAAM,kCAAkB,IAAI,KAAa;AAEzC,MAAK,MAAM,QAAQ,gBAAgB;EACjC,MAAM,iBAAiB,KAAK,QAAQ,OAAO,IAAI;EAC/C,MAAM,YAAY,eAAe,QAAQ,SAAS,MAAM;EACxD,MAAM,WAAW,eAAe,QAAQ,SAAS,GAAG;EACpD,MAAM,aAAa,SAAS,QAAQ,IAAI;AAExC,MAAI,aAAa,QACf;AAGF,MAAI,eAAe,IAAI;AACrB,aAAU,IAAI,KAAK,YAAY;AAC/B;;EAGF,MAAM,eAAe,SAAS,MAAM,GAAG,WAAW;AAElD,MAAI,aAAa,aAAa;AAC5B,mBAAgB,IAAI,MAAM;AAC1B;;AAGF,MAAI,iBAAiB,OAAO;GAC1B,MAAM,cAAc,SAAS,QAAQ,KAAK,aAAa,EAAE;GACzD,MAAM,WACJ,gBAAgB,KAAK,WAAW,SAAS,MAAM,GAAG,YAAY;GAEhE,MAAM,YAAY,SAAS,MAAM,SAAS,SAAS,EAAE;AAErD,OAAI,cAAc,QAChB,iBAAgB,IAAI,SAAS;QACxB;AACL,QAAI,CAAC,OAAO,IAAI,SAAS,CACvB,QAAO,IAAI,0BAAU,IAAI,KAAK,CAAC;AAEjC,WAAO,IAAI,SAAS,CAAE,IAAI,KAAK,UAAU,KAAK;;SAE3C;GACL,MAAM,YAAY,SAAS,MAAM,aAAa,EAAE;AAEhD,OAAI,cAAc,QAChB,iBAAgB,IAAI,aAAa;QAC5B;AACL,QAAI,CAAC,OAAO,IAAI,aAAa,CAC3B,QAAO,IAAI,8BAAc,IAAI,KAAK,CAAC;AAErC,WAAO,IAAI,aAAa,CAAE,IAAI,KAAK,UAAU,KAAK;;;;AAKxD,MAAK,MAAM,CAAC,UAAU,YAAY,QAAQ;AACxC,MAAI,gBAAgB,IAAI,SAAS,CAC/B;EAGF,MAAM,sBAAsB,eAAe,UAAU,EACnD,YAAY,MAAM,KAAK,QAAQ,CAAC,MAAM,EACvC,CAAC;EAEF,MAAM,kBAAkB,KAAK,KAAK,QAAQ,WAAW,UAAU,WAAW;AAC1E,KAAG,UAAU,KAAK,QAAQ,gBAAgB,EAAE,EAAE,WAAW,MAAM,CAAC;AAChE,KAAG,cAAc,iBAAiB,oBAAoB;;CAGxD,MAAM,iBAAiB,IAAI,IAAY,UAAU;AACjD,MAAK,MAAM,YAAY,OAAO,MAAM,CAClC,gBAAe,IAAI,KAAK,SAAS,WAAW;AAE9C,MAAK,MAAM,aAAa,gBACtB,gBAAe,IAAI,KAAK,UAAU,WAAW;CAG/C,MAAM,cAAc,eAAe,UAAU,EAC3C,YAAY,MAAM,KAAK,eAAe,CAAC,MAAM,EAC9C,CAAC;AAEF,IAAG,cAAc,KAAK,KAAK,QAAQ,WAAW,WAAW,EAAE,YAAY;;;;AC3FzE,IAAa,uBAAb,MAAa,6BAA6B,MAAiC;CACzE,YACE,YACA,UAIA;AACA,QAAM,0BAA0B,WAAW,GAAG;AAN9B,OAAA,aAAA;AACA,OAAA,WAAA;AAMhB,SAAO,eAAe,MAAM,qBAAqB,UAAU;;;;;ACe/D,eAAsB,YACpB,UACA,iBACA,YACA,QACe;AACf,MAAK,MAAM,kBAAkB,gBAC3B,UAAS,SAAS,eAAe;AAGnC,KAAI,CAAC,QAAQ,QACX;CAGF,MAAM,aAAiC,EAAE;AAEzC,MAAK,MAAM,UAAU,OAAO,SAAS;EAGnC,MAAM,SAAS,MAAM,WAFF,OAAO,WAAW,WAAW,SAAS,OAAO,IAEpB,YADvB,OAAO,WAAW,WAAW,KAAA,IAAY,OAAO,GACA;AAErE,MAAI,OAAO,YAAY,MACrB,OAAM,IAAI,qBACR,OAAO,MAAM,YACb,OAAO,MAAM,SACd;AAGH,aAAW,KAAK,OAAO,MAAM;AAC7B,WAAS,SAAS,OAAO,MAAM,QAAQ,OAAO,MAAM,OAAO;;AAG7D,uBAAsB,WAAW;;AAGnC,eAAe,WACb,YACA,YACA,cACwD;CACxD,MAAM,gBAAgB,oBAAoB,YAAY,WAAW;CACjE,MAAM,WAA8C,EAAE;AAEtD,MAAK,MAAM,gBAAgB,cACzB,KAAI;EAEF,MAAM,SAAS,qBADO,MAAM,OAAO,eACgB,aAAa;AAChE,MAAI,OAAO,QACT,QAAO;GACL,SAAS;GACT,OAAO;IACL,QAAQ,OAAO;IACf,QAAQ;IACR,QAAQ;IACT;GACF;AAEH,WAAS,KAAK;GACZ,MAAM;GACN,OAAO,OAAO;GACf,CAAC;UACK,OAAO;AACd,WAAS,KAAK;GACZ,MAAM;GACN,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;GAC9D,CAAC;;AAIN,QAAO;EACL,SAAS;EACT,OAAO;GACL;GACA;GACD;EACF;;AAGH,SAAS,qBACP,cACA,cACsC;CACtC,MAAM,aAAa,gCAAgC,aAAa;AAChE,KAAI,WAAW,WAAW,EACxB,QAAO;EACL,SAAS;EACT,OAAO;EACR;CAGH,MAAM,SAAmB,EAAE;AAC3B,MAAK,MAAM,aAAa,WACtB,KAAI;EACF,MAAM,SAAS,IAAI,UAAU,YAAY,aAAa;AACtD,MAAI,mBAAmB,OAAO,CAC5B,QAAO;GACL,SAAS;GACT,OAAO;GACR;AAGH,SAAO,KACL,WAAW,UAAU,WAAW,qDACjC;UACM,OAAO;AACd,SAAO,KACL,WAAW,UAAU,WAAW,+BAA+B,YAAY,MAAM,GAClF;;AAIL,QAAO;EACL,SAAS;EACT,OAAO,OAAO,KAAK,KAAK;EACzB;;AAGH,SAAS,gCACP,cACmB;CACnB,MAAM,aAAgC,EAAE;AAExC,MAAK,MAAM,CAAC,KAAK,UAAU,OAAO,QAAQ,aAAa,CACrD,KAAI,QAAQ,aAAa,OAAO,UAAU,WACxC,YAAW,KAAK;EACd,YAAY;EACZ,aAAa;EACd,CAAC;CAKN,MAAM,gBAAgB,aAAa;AACnC,KAAI,OAAO,kBAAkB,WAC3B,YAAW,KAAK;EACd,YAAY;EACZ,aAAa;EACd,CAAC;AAGJ,QAAO;;AAGT,SAAS,mBAAmB,OAA2C;AACrE,QACE,OAAO,UAAU,YACjB,UAAU,QACV,OAAQ,MAAsC,SAAS,YACtD,MAAoC,KAAK,SAAS;;AAIvD,SAAS,YAAY,OAAwB;AAC3C,QAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;;AAG/D,SAAS,oBACP,YACA,YACU;CACV,MAAM,QAAkB,EAAE;AAE1B,MAAK,MAAM,YAAY,WACrB,SAAQ,UAAR;EACE,KAAK;AACH,SAAM,KAAK,sBAAsB,aAAa;AAC9C,SAAM,KAAK,WAAW,aAAa;AACnC;EACF,KAAK;AACH,SAAM,KAAK,uBAAuB,WAAW,CAAC;AAC9C;EACF,KAAK;AACH,SAAM,KAAK,WAAW;AACtB;;AAIN,QAAO;;AAGT,SAAS,uBAAuB,YAA4B;AAC1D,KAAI,WAAW,WAAW,QAAQ,CAChC,QAAO;AAGT,KAAI,KAAK,WAAW,WAAW,CAC7B,QAAO,cAAc,WAAW,CAAC;AAGnC,QAAO;;AAGT,SAAS,sBAAsB,YAAsC;AACnE,KAAI,WAAW,SAAS,GAAG;AACzB,UAAQ,KAAK,uBAAuB,WAAW,OAAO,aAAa;AACnE,OAAK,MAAM,UAAU,WACnB,SAAQ,KAAK,OAAO,OAAO,OAAO,KAAK,SAAS,OAAO,OAAO,GAAG;;;;;ACpOvE,IAAa,+BAAb,cAAkD,MAAM;CACtD,OAAgC;CAEhC,YACE,WACA,iBACA,eACA;AACA,QACE,mEAAmE,gBAAgB,oBAAoB,UAAU,iCAAiC,cAAc,IACjK;AANe,OAAA,YAAA;AACA,OAAA,kBAAA;AACA,OAAA,gBAAA;;;;;ACApB,MAAM,gCAAgC;AACtC,MAAM,2BAA2B;AAYjC,SAAgB,6BACd,aACA,WACQ;CACR,MAAM,oBAAoB,wBAAwB,UAAU;CAC5D,MAAM,0BAA0B,yBAC9B,aACA,kBACD;CACD,MAAM,aAAa,0BAA0B,KAAK,QAAQ,KAAK;CAC/D,MAAM,aAAa,0BACf,WAAW,QAAQ,YAAY,GAC/B,oBAAoB,WAAW,QAAQ,YAAY,CAAC;CACxD,MAAM,oBAAoB,0BACtB,oBACA,oBAAoB,kBAAkB;CAC1C,MAAM,oBAAoB,WACvB,SAAS,YAAY,kBAAkB,CACvC,WAAW,WAAW,KAAK,IAAI;AAElC,KAAI,kBAAkB,WAAW,IAAI,IAAI,kBAAkB,WAAW,KAAK,CACzE,QAAO;AAGT,QAAO,KAAK;;AAGd,eAAsB,OACpB,QACA,OAAwB,EAAE,EACT;CACjB,MAAM,UAAU,GAAG,YACjB,KAAK,KAAK,GAAG,QAAQ,EAAE,0BAA0B,CAClD;CACD,MAAM,cAAc,KAAK,KAAK,SAAS,qBAAqB;CAC5D,MAAM,kBAAkB,KAAK,KAAK,OAAO,eAAe,UAAU;CAClE,MAAM,yBAAyB,6BAC7B,aACA,OAAO,UACR;AAED,IAAG,cACD,aACA;EACE,+BAA+B,KAAK,UAAU,uBAAuB,CAAC;EACtE;EACA;EACA;EACA;EACA;EACA;EACA;EACD,CAAC,KAAK,KAAK,CACb;AAED,KAAI;AACF,SAAO,KAAK,SAAS,OAAO;GAC1B,KAAK;GACL,OAAO;GACP,WAAW;GACX,cAAc,EACZ,iBAAiB,QAClB;GACD,WAAW,WAAmB;AAC5B,QAAI,OAAO,WAAW,QAAQ,CAC5B,QAAO;AAGT,WAAO,CAAC,OAAO,WAAW,IAAI,IAAI,CAAC,KAAK,WAAW,OAAO;;GAE5D,QAAQ;IACN,MAAM;IACN,QAAQ;IACT;GACF,CAAC;WACM;AACR,KAAG,OAAO,SAAS;GAAE,WAAW;GAAM,OAAO;GAAM,CAAC;;AAGtD,KAAI,EAAE,KAAK,cAAc,GAAG,YAAY,gBAAgB,CACtD,OAAM,IAAI,6BACR,OAAO,WACP,iBACA,OAAO,cACR;AAGH,QAAO;;AAGT,SAAS,wBAAwB,WAA2B;AAC1D,KAAI,KAAK,WAAW,UAAU,CAC5B,QAAO;AAGT,KAAI,8BAA8B,KAAK,UAAU,CAC/C,QAAO,KAAK,MAAM,UAAU,UAAU;AAGxC,KAAI,yBAAyB,KAAK,UAAU,CAC1C,QAAO,KAAK,MAAM,UAAU,UAAU;AAGxC,QAAO,KAAK,QAAQ,UAAU;;AAGhC,SAAS,yBAAyB,GAAG,WAA8B;AACjE,QAAO,UAAU,MAAK,aAAY;AAChC,SACE,8BAA8B,KAAK,SAAS,IAC5C,yBAAyB,KAAK,SAAS;GAEzC;;AAGJ,SAAS,oBAAoB,UAA0B;AACrD,KAAI,CAAC,GAAG,WAAW,SAAS,CAC1B,QAAO;AAGT,QAAO,GAAG,aAAa,OAAO,SAAS;;;;AC3IzC,IAAa,6BAAb,cAAgD,MAAM;CACpD,YAAmB,gBAAwB;AACzC,QACE,oBAAoB,eAAe,iGACpC;AACD,OAAK,OAAO;;;;;ACFhB,MAAM,uBAAuB,IAAI,IAC/B,OAAO,OAAO,eAAe,CAAC,QAC3B,eAA6C,OAAO,eAAe,SACrE,CACF;AAED,MAAM,YAAY,UAAqD;AACrE,QAAO,OAAO,UAAU,YAAY,UAAU,QAAQ,CAAC,MAAM,QAAQ,MAAM;;AAG7E,MAAM,wBAAwB,UAA4B;AACxD,KAAI,CAAC,SAAS,MAAM,CAClB,QAAO;AAGT,QACE,OAAO,MAAM,SAAS,YACtB,MAAM,KAAK,SAAS,KACpB,OAAO,MAAM,gBAAgB,YAC7B,MAAM,YAAY,SAAS,KAC3B,qBAAqB,IAAI,MAAM,WAA6B;;AAIhE,MAAM,yBAAyB,UAA4B;AACzD,KAAI,CAAC,SAAS,MAAM,IAAI,CAAC,MAAM,QAAQ,MAAM,UAAU,CACrD,QAAO;AAGT,QACE,OAAO,MAAM,gBAAgB,YAC7B,MAAM,YAAY,SAAS,KAC3B,OAAO,MAAM,SAAS,YACtB,MAAM,KAAK,SAAS,KACpB,OAAO,MAAM,YAAY,YACzB,MAAM,QAAQ,SAAS,KACvB,OAAO,OAAO,WAAW,CAAC,SAAS,MAAM,OAAqB,IAC9D,SAAS,MAAM,QAAQ,IACvB,MAAM,UAAU,SAAS,KACzB,MAAM,UAAU,OAAM,aAAY,qBAAqB,SAAS,CAAC;;AAIrE,MAAM,wBAAwB,UAA4B;AACxD,QACE,SAAS,MAAM,IACf,MAAM,QAAQ,MAAM,WAAW,IAC/B,MAAM,WAAW,MAAM,sBAAsB;;AAIjD,MAAa,oBAAoB,UAA4C;AAC3E,KAAI,CAAC,SAAS,MAAM,IAAI,CAAC,SAAS,MAAM,UAAU,CAChD,QAAO;AAGT,QAAO,OAAO,OAAO,MAAM,UAAU,CAAC,MAAM,qBAAqB;;;;ACpDnE,eAAsB,iBACpB,iBACyB;CACzB,MAAM,cAAc,WAAW,SAAS,CACrC,OAAO,GAAG,aAAa,gBAAgB,CAAC,CACxC,OAAO,MAAM;CAChB,MAAM,YAAY,cAAc,gBAAgB;AAEhD,WAAU,aAAa,IAAI,WAAW,YAAY;CAElD,MAAM,aAAc,MAAM,OAAO,UAAU,UAAU;CAIrD,MAAM,aAAa,WAAW,QAAQ,WAAW,WAAW;AAE5D,KAAI,CAAC,iBAAiB,WAAW,CAC/B,OAAM,IAAI,2BAA2B,gBAAgB;AAGvD,QAAO;;;;ACVT,eAAsB,SAAS,QAA+C;AAC5E,IAAG,UAAU,OAAO,eAAe,EAAE,WAAW,MAAM,CAAC;CAEvD,MAAM,kBAAkB,MAAM,OAAO,OAAO;AAC5C,0BAAyB,OAAO,cAAc;CAE9C,MAAM,aAAa,MAAM,iBAAiB,gBAAgB;AAG1D,QAAO;EACL;EACA,gBAJqB,cAAc,WAAW;EAK/C;;AAGH,SAAS,yBAAyB,eAA6B;AAC7D,IAAG,cACD,GAAG,cAAc,aACjB;EACE;EACA;EACA;EACD,CAAC,KAAK,KAAK,CACb;;;;ACxBH,MAAMA,cAAY,KAAK,QAAQ,cAAc,OAAO,KAAK,IAAI,CAAC;AAE9D,MAAa,yBACX,WACA,4BACS;CACT,MAAM,mBAAmB,UAAU,MAAM;AACzC,KAAI,iBAAiB,WAAW,EAC9B,OAAM,IAAI,uBAAuB,WAAW,aAAa;CAG3D,MAAM,2BAA2B,KAAK,QAAQ,wBAAwB;CACtE,MAAM,4BAA4B,GAAG,aAAa,OAChD,yBACD;CACD,MAAM,oBAAoB,KAAK,QAC7B,0BACA,iBACD;CACD,MAAM,qBAAqB,+BAA+B,kBAAkB;CAC5E,MAAM,iBAAiB,KAAK,MAAM,mBAAmB,CAAC;AAEtD,KAAI,uBAAuB,eACzB,OAAM,IAAI,uBAAuB,WAAW,mBAAmB;EAC7D;EACA,yBAAyB;EACzB;EACD,CAAC;AAGJ,KACE,sBAAsB,4BACtB,uBAAuB,0BAEvB,OAAM,IAAI,uBAAuB,WAAW,6BAA6B;EACvE;EACA,yBAAyB;EAC1B,CAAC;CASJ,MAAM,0BAA0B,CANM,2BACpC,yBACD,EACuC,2BACtC,0BACD,CAIA,CAAC,QAAQ,SAAyB,SAAS,KAAA,EAAU;CACtD,MAAM,+BAA+B,wBAAwB,MAC3D,2BACE,sBAAsB,0BACtB,uBAAuB,GAAG,aAAa,OAAO,uBAAuB,CACxE;AAED,KAAI,iCAAiC,KAAA,EACnC,OAAM,IAAI,uBAAuB,WAAW,kBAAkB;EAC5D;EACA,yBAAyB;EACzB,wBAAwB;EACzB,CAAC;AAGJ,KACE,wBAAwB,SAAS,MAChC,qBAAqB,0BAA0B,kBAAkB,IAChE,qBAAqB,2BAA2B,mBAAmB,EAErE,OAAM,IAAI,uBACR,WACA,yCACA;EACE;EACA,yBAAyB;EAC1B,CACF;;;;;;AAQL,IAAa,YAAb,MAAuB;CACrB,UAA0B;CAC1B,cAA8B,KAAK,KAAKA,aAAW,YAAY;CAE/D,WAA4B,sBAAsB;CAClD,iBAAkC,4BAA4B;CAC9D;CACA;CAEA,YAAoB;CACpB,YAAoB;CACpB,gBAAwB;CACxB,qBAA6B;CAE7B,YACE,kBAAiC,CAAC,IAAI,aAAa,CAAC,EACpD,YACA;AACA,OAAK,kBAAkB;AACvB,OAAK,aAAa,cAAc,CAAC,OAAO,QAAQ;;;;;CAMlD,MAAa,SACX,UACA,WACA,QACA,0BAAkC,QAAQ,KAAK,EAChC;AACf,UAAQ,KAAK,yBAAyB;AAEtC,OAAK,sBAAsB,UAAU,WAAW,wBAAwB;AAExE,MAAI,QAAQ,SAAS,MAAM;AACzB,yBAAsB,KAAK,WAAW,wBAAwB;AAC9D,WAAQ,KAAK,+BAA+B;AAC5C,MAAG,OAAO,KAAK,WAAW;IAAE,WAAW;IAAM,OAAO;IAAM,CAAC;;AAG7D,KAAG,UAAU,KAAK,WAAW,EAAE,WAAW,MAAM,CAAC;AACjD,KAAG,UAAU,KAAK,oBAAoB,EAAE,WAAW,MAAM,CAAC;AAC1D,KAAG,UAAU,KAAK,eAAe,EAAE,WAAW,MAAM,CAAC;AAErD,QAAM,YACJ,KAAK,UACL,KAAK,iBACL,KAAK,YACL,OACD;AAED,UAAQ,KACN,uBAAuB,KAAK,UAAU,QAAQ,KAAK,cAAc,MAClE;EACD,IAAI,EAAE,mBAAmB,MAAM,SAAS;GACtC,WAAW,KAAK;GAChB,eAAe,KAAK;GACrB,CAAC;EAEF,MAAM,gBAAgB,KAAK,eAAe,oBAAoB;GAC5D,WAAW,KAAK;GAChB,UAAU,KAAK,QAAQ,KAAK,UAAU;GACtC,QAAS,UAAU,EAAE;GACtB,CAAC;AAEF,UAAQ,KAAK,0BAA0B;AACvC,OAAK,MAAM,gBAAgB,KAAK,SAAS,QAAQ,CAC/C,KAAI,aAAa,OAAO,WACtB,OAAM,aAAa,OAAO,WAAW,cAAc;AAIvD,UAAQ,KAAK,0BAA0B;AACvC,OAAK,MAAM,gBAAgB,KAAK,SAAS,QAAQ,CAC/C,KAAI,aAAa,OAAO,iBACtB,kBACE,MAAM,aAAa,OAAO,iBAAiB,eAAe;EAIhE,MAAM,mBAAmB,KAAK,eAAe,uBAAuB;GAClE,WAAW,KAAK;GAChB,UAAU,KAAK,QAAQ,KAAK,UAAU;GACtC,QAAS,UAAU,EAAE;GACrB;GACA,aAAa,KAAK;GAClB,SAAS,KAAK;GACd,oBAAoB,KAAK;GACzB,eAAe,KAAK;GACrB,CAAC;AAEF,UAAQ,KAAK,qBAAqB;AAClC,OAAK,MAAM,gBAAgB,KAAK,SAAS,QAAQ,EAAE;AACjD,WAAQ,KAAK,mBAAmB,aAAa,OAAO,OAAO;AAC3D,OAAI,aAAa,OAAO,SACtB,OAAM,aAAa,OAAO,SAAS,iBAAiB;;AAIxD,qBAAmB,KAAK,aAAa,iBAAiB;AAEtD,UAAQ,KAAK,wBAAwB;AACrC,OAAK,MAAM,gBAAgB,KAAK,SAAS,QAAQ,CAC/C,KAAI,aAAa,OAAO,SACtB,OAAM,aAAa,OAAO,SAAS,cAAc;AAIrD,MAAI,QAAQ,UAAU,KACpB,OAAM,WAAW,KAAK,UAAU;AAGlC,UAAQ,KAAK,uBAAuB;AACpC,UAAQ,KACN,oBAAoB,KAAK,eAAe,mBAAmB,CAAC,SAC7D;;CAGH,sBACE,UACA,WACA,yBACM;AACN,OAAK,YAAY,KAAK,QAAQ,yBAAyB,SAAS;AAChE,OAAK,YAAY,KAAK,QAAQ,yBAAyB,UAAU;AACjE,OAAK,qBAAqB,KAAK,KAAK,KAAK,WAAW,YAAY;AAChE,OAAK,gBAAgB,KAAK,KAAK,KAAK,WAAW,OAAO;;;AAI1D,MAAM,8BACJ,mBACuB;CACvB,IAAI,mBAAmB;AAEvB,QAAO,MAAM;AACX,MAAI,mBAAmB,iBAAiB,CACtC,QAAO;EAGT,MAAM,kBAAkB,KAAK,QAAQ,iBAAiB;AACtD,MAAI,oBAAoB,iBACtB;AAGF,qBAAmB;;;AAIvB,MAAM,sBAAsB,cAA+B;AACzD,QAAO,CAAC,uBAAuB,OAAO,CAAC,MAAK,WAC1C,GAAG,WAAW,KAAK,KAAK,WAAW,OAAO,CAAC,CAC5C;;AAGH,MAAM,kCAAkC,eAA+B;CACrE,MAAM,oBAA8B,EAAE;CACtC,IAAI,sBAAsB,KAAK,QAAQ,WAAW;AAElD,QAAO,CAAC,GAAG,WAAW,oBAAoB,EAAE;EAC1C,MAAM,aAAa,KAAK,QAAQ,oBAAoB;AACpD,MAAI,eAAe,oBACjB;AAGF,oBAAkB,QAAQ,KAAK,SAAS,oBAAoB,CAAC;AAC7D,wBAAsB;;CAGxB,MAAM,wBAAwB,GAAG,aAAa,OAAO,oBAAoB;AAEzE,QAAO,KAAK,KAAK,uBAAuB,GAAG,kBAAkB;;AAG/D,MAAM,wBAAwB,WAAmB,aAA8B;CAC7E,MAAM,eAAe,KAAK,SAAS,UAAU,UAAU;CACvD,MAAM,wBAAwB,KAAK,KAAK;CACxC,MAAM,kBACJ,iBAAiB,QAAQ,aAAa,WAAW,sBAAsB;AAEzE,QACE,iBAAiB,MAAO,CAAC,mBAAmB,CAAC,KAAK,WAAW,aAAa;;;;AC1R9E,IAAa,6BAAb,cAAgD,MAAM;CACpD,OAAgC;CAEhC,YACE,YACA,MACA,WACA;AACA,QACE,qCAAqC,WAAW,UAAU,KAAK,WAAW,UAAU,kCACrF;AANe,OAAA,aAAA;AACA,OAAA,OAAA;AACA,OAAA,YAAA;;;;;ACYpB,MAAa,0BACX,SACA,QACA,4BAC4B;CAC5B,MAAM,YAAY,QAAQ,SAAS,OAAO;CAC1C,MAAM,YAAY,QAAQ,UAAU,OAAO;AAE3C,KAAI,CAAC,UACH,OAAM,IAAI,2BAA2B,SAAS,WAAW,QAAQ;AAGnE,KAAI,CAAC,UACH,OAAM,IAAI,2BAA2B,UAAU,YAAY,SAAS;CAGtE,MAAM,oBAAoB,KAAK,WAAW,UAAU,GAChD,YACA,KAAK,KAAK,yBAAyB,UAAU;CACjD,MAAM,oBAAoB,KAAK,WAAW,UAAU,GAChD,YACA,KAAK,KAAK,yBAAyB,UAAU;CACjD,MAAM,cAAgC;EACpC,OAAO;EACP,QAAQ;EACR,QAAQ,QAAQ,UAAU,OAAO,UAAU;EAC3C,OAAO,QAAQ,SAAS,OAAO,SAAS;EACzC;AAED,KAAI,QAAQ,QACV,aAAY,UAAU,QAAQ,QAC3B,MAAM,IAAI,CACV,KAAI,WAAU,OAAO,MAAM,CAAC;UACtB,OAAO,QAChB,aAAY,UAAU,OAAO;AAG/B,QAAO;EACL,WAAW;EACX,WAAW;EACX,QAAQ;EACT;;;;ACjDH,MAAM,YAAY,KAAK,QAAQ,cAAc,OAAO,KAAK,IAAI,CAAC;AAC9D,MAAM,cAAc,KAAK,MACvB,GAAG,aAAa,KAAK,KAAK,WAAW,kBAAkB,EAAE,QAAQ,CAClE;AAeD,MAAM,UAAU,IAAI,SAAS;AAC7B,MAAM,UAAU,QAAQ,KAAK;AAE7B,QACG,KAAK,qBAAqB,CAC1B,YAAY,8DAA8D,CAC1E,QAAQ,YAAY,QAAQ;AAE/B,QACG,QAAQ,WAAW,CACnB,YAAY,2DAA2D,CACvE,OAAO,2BAA2B,+BAA+B,CACjE,OAAO,4BAA4B,uCAAuC,CAC1E,OACC,6BACA,kDACD,CACA,OAAO,2BAA2B,yCAAyC,CAC3E,OAAO,YAAY,mDAAmD,CACtE,OAAO,eAAe,0BAA0B,CAChD,OAAO,WAAW,2DAA2D,CAC7E,OAAO,cAAc,oCAAoC,CACzD,OAAO,OAAO,YAA4B;CACzC,IAAI,SAAoC,EAAE;AAG1C,KAAI,QAAQ,QAAQ;EAClB,MAAM,aAAa,sBAAsB,QAAQ,QAAQ,QAAQ;AAEjE,MAAI;AACF,YAAS,MAAM,WAAW,WAAW;AACrC,WAAQ,KAAK,6BAA6B,aAAa;WAChD,OAAO;AACd,WAAQ,MAAM,sCAAsC,QAAQ,SAAS;AACrE,WAAQ,MAAM,MAAM;AACpB,WAAQ,KAAK,EAAE;;;CAInB,MAAM,0BAA0B,uBAC9B,SACA,QACA,QACD;AAID,QADkB,IAAI,WAAW,CAChB,SACf,wBAAwB,WACxB,wBAAwB,WACxB,wBAAwB,QACxB,QACD;EACD;AAGJ,QACG,QAAQ,OAAO,CACf,YAAY,oDAAoD,CAChE,aAAa;AACZ,SAAQ,IAAI,mCAAmC;EAC/C;AAEJ,QAAQ,MAAM,QAAQ,KAAK"}
package/dist/entry.mjs CHANGED
@@ -17,7 +17,7 @@ const getRuntimeDisplayName = (runtime) => {
17
17
  const main = async () => {
18
18
  const runtime = detectRuntime();
19
19
  console.info(`Running on ${getRuntimeDisplayName(runtime)}`);
20
- await import("./cli-C-s7e7_U.mjs");
20
+ await import("./cli-BVUW7VcY.mjs");
21
21
  };
22
22
  main().catch((error) => {
23
23
  console.error("Failed to start TypeWeaver CLI:", error);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rexeus/typeweaver",
3
- "version": "0.10.4",
3
+ "version": "0.10.5",
4
4
  "description": "🧵✨ Typeweaver CLI. Entry point into the Typeweaver framework to scaffold, validate, and generate API assets.",
5
5
  "type": "module",
6
6
  "sideEffects": false,
@@ -54,13 +54,13 @@
54
54
  "commander": "^14.0.3",
55
55
  "oxc-transform": "^0.121.0",
56
56
  "rolldown": "^1.0.0-rc.13",
57
- "@rexeus/typeweaver-clients": "^0.10.4",
58
- "@rexeus/typeweaver-aws-cdk": "^0.10.4",
59
- "@rexeus/typeweaver-gen": "^0.10.4",
60
- "@rexeus/typeweaver-hono": "^0.10.4",
61
- "@rexeus/typeweaver-server": "^0.10.4",
62
- "@rexeus/typeweaver-core": "^0.10.4",
63
- "@rexeus/typeweaver-types": "^0.10.4"
57
+ "@rexeus/typeweaver-core": "^0.10.5",
58
+ "@rexeus/typeweaver-clients": "^0.10.5",
59
+ "@rexeus/typeweaver-server": "^0.10.5",
60
+ "@rexeus/typeweaver-hono": "^0.10.5",
61
+ "@rexeus/typeweaver-types": "^0.10.5",
62
+ "@rexeus/typeweaver-aws-cdk": "^0.10.5",
63
+ "@rexeus/typeweaver-gen": "^0.10.5"
64
64
  },
65
65
  "peerDependencies": {
66
66
  "oxfmt": ">=0.30.0"