@rexeus/typeweaver 0.10.2 → 0.10.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{cli-Dz7saa33.mjs → cli-C-s7e7_U.mjs} +93 -19
- package/dist/cli.cjs +93 -19
- package/dist/cli.mjs +93 -19
- package/dist/cli.mjs.map +1 -1
- package/dist/entry.mjs +1 -1
- package/dist/templates/Index.ejs +2 -2
- package/package.json +8 -8
|
@@ -7,6 +7,7 @@ import { createPluginContextBuilder, createPluginRegistry, normalizeSpec, render
|
|
|
7
7
|
import { TypesPlugin } from "@rexeus/typeweaver-types";
|
|
8
8
|
import os from "node:os";
|
|
9
9
|
import { build } from "rolldown";
|
|
10
|
+
import { createHash } from "node:crypto";
|
|
10
11
|
import { HttpMethod, HttpStatusCode } from "@rexeus/typeweaver-core";
|
|
11
12
|
//#region src/configLoader.ts
|
|
12
13
|
const SUPPORTED_CONFIG_EXTENSIONS = new Set([
|
|
@@ -20,7 +21,7 @@ const UNSUPPORTED_TYPESCRIPT_CONFIG_EXTENSIONS = new Set([
|
|
|
20
21
|
".cts"
|
|
21
22
|
]);
|
|
22
23
|
const getResolvedConfigPath = (configPath, currentWorkingDirectory = process.cwd()) => {
|
|
23
|
-
return path.isAbsolute(configPath) ? configPath : path.
|
|
24
|
+
return path.isAbsolute(configPath) ? configPath : path.resolve(currentWorkingDirectory, configPath);
|
|
24
25
|
};
|
|
25
26
|
const assertSupportedConfigPath = (configPath) => {
|
|
26
27
|
const extension = path.extname(configPath).toLowerCase();
|
|
@@ -88,11 +89,16 @@ function generateIndexFiles(templateDir, context) {
|
|
|
88
89
|
const withJsExt = normalizedFile.replace(/\.ts$/, ".js");
|
|
89
90
|
const stripped = normalizedFile.replace(/\.ts$/, "");
|
|
90
91
|
const firstSlash = stripped.indexOf("/");
|
|
92
|
+
if (stripped === "index") continue;
|
|
91
93
|
if (firstSlash === -1) {
|
|
92
94
|
rootFiles.add(`./${withJsExt}`);
|
|
93
95
|
continue;
|
|
94
96
|
}
|
|
95
97
|
const firstSegment = stripped.slice(0, firstSlash);
|
|
98
|
+
if (stripped === "lib/index") {
|
|
99
|
+
existingBarrels.add("lib");
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
96
102
|
if (firstSegment === "lib") {
|
|
97
103
|
const secondSlash = stripped.indexOf("/", firstSlash + 1);
|
|
98
104
|
const groupKey = secondSlash === -1 ? stripped : stripped.slice(0, secondSlash);
|
|
@@ -141,30 +147,29 @@ async function loadPlugins(registry, requiredPlugins, strategies, config) {
|
|
|
141
147
|
if (!config?.plugins) return;
|
|
142
148
|
const successful = [];
|
|
143
149
|
for (const plugin of config.plugins) {
|
|
144
|
-
|
|
145
|
-
if (typeof plugin === "string") result = await loadPlugin(plugin, strategies);
|
|
146
|
-
else result = await loadPlugin(plugin[0], strategies);
|
|
150
|
+
const result = await loadPlugin(typeof plugin === "string" ? plugin : plugin[0], strategies, typeof plugin === "string" ? void 0 : plugin[1]);
|
|
147
151
|
if (result.success === false) throw new PluginLoadingFailure(result.error.pluginName, result.error.attempts);
|
|
148
152
|
successful.push(result.value);
|
|
149
|
-
registry.register(result.value.plugin);
|
|
153
|
+
registry.register(result.value.plugin, result.value.config);
|
|
150
154
|
}
|
|
151
155
|
reportSuccessfulLoads(successful);
|
|
152
156
|
}
|
|
153
|
-
async function loadPlugin(pluginName, strategies) {
|
|
157
|
+
async function loadPlugin(pluginName, strategies, pluginConfig) {
|
|
154
158
|
const possiblePaths = generatePluginPaths(pluginName, strategies);
|
|
155
159
|
const attempts = [];
|
|
156
160
|
for (const possiblePath of possiblePaths) try {
|
|
157
|
-
const
|
|
158
|
-
if (
|
|
161
|
+
const plugin = createPluginInstance(await import(possiblePath), pluginConfig);
|
|
162
|
+
if (plugin.success) return {
|
|
159
163
|
success: true,
|
|
160
164
|
value: {
|
|
161
|
-
plugin:
|
|
162
|
-
source: possiblePath
|
|
165
|
+
plugin: plugin.value,
|
|
166
|
+
source: possiblePath,
|
|
167
|
+
config: pluginConfig
|
|
163
168
|
}
|
|
164
169
|
};
|
|
165
170
|
attempts.push({
|
|
166
171
|
path: possiblePath,
|
|
167
|
-
error:
|
|
172
|
+
error: plugin.error
|
|
168
173
|
});
|
|
169
174
|
} catch (error) {
|
|
170
175
|
attempts.push({
|
|
@@ -180,10 +185,46 @@ async function loadPlugin(pluginName, strategies) {
|
|
|
180
185
|
}
|
|
181
186
|
};
|
|
182
187
|
}
|
|
183
|
-
function
|
|
184
|
-
|
|
188
|
+
function createPluginInstance(pluginModule, pluginConfig) {
|
|
189
|
+
const candidates = findPluginConstructorCandidates(pluginModule);
|
|
190
|
+
if (candidates.length === 0) return {
|
|
191
|
+
success: false,
|
|
192
|
+
error: "No plugin constructor export found"
|
|
193
|
+
};
|
|
194
|
+
const errors = [];
|
|
195
|
+
for (const candidate of candidates) try {
|
|
196
|
+
const plugin = new candidate.constructor(pluginConfig);
|
|
197
|
+
if (isTypeweaverPlugin(plugin)) return {
|
|
198
|
+
success: true,
|
|
199
|
+
value: plugin
|
|
200
|
+
};
|
|
201
|
+
errors.push(`Export '${candidate.exportName}' did not produce a valid plugin with a string name`);
|
|
202
|
+
} catch (error) {
|
|
203
|
+
errors.push(`Export '${candidate.exportName}' could not be instantiated: ${formatError(error)}`);
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
success: false,
|
|
207
|
+
error: errors.join("; ")
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
function findPluginConstructorCandidates(pluginModule) {
|
|
211
|
+
const candidates = [];
|
|
212
|
+
for (const [key, value] of Object.entries(pluginModule)) if (key !== "default" && typeof value === "function") candidates.push({
|
|
213
|
+
exportName: key,
|
|
214
|
+
constructor: value
|
|
215
|
+
});
|
|
185
216
|
const defaultExport = pluginModule.default;
|
|
186
|
-
if (typeof defaultExport === "function")
|
|
217
|
+
if (typeof defaultExport === "function") candidates.push({
|
|
218
|
+
exportName: "default",
|
|
219
|
+
constructor: defaultExport
|
|
220
|
+
});
|
|
221
|
+
return candidates;
|
|
222
|
+
}
|
|
223
|
+
function isTypeweaverPlugin(value) {
|
|
224
|
+
return typeof value === "object" && value !== null && typeof value.name === "string" && value.name.length > 0;
|
|
225
|
+
}
|
|
226
|
+
function formatError(error) {
|
|
227
|
+
return error instanceof Error ? error.message : String(error);
|
|
187
228
|
}
|
|
188
229
|
function generatePluginPaths(pluginName, strategies) {
|
|
189
230
|
const paths = [];
|
|
@@ -193,11 +234,19 @@ function generatePluginPaths(pluginName, strategies) {
|
|
|
193
234
|
paths.push(`@rexeus/${pluginName}`);
|
|
194
235
|
break;
|
|
195
236
|
case "local":
|
|
237
|
+
paths.push(toLocalImportSpecifier(pluginName));
|
|
238
|
+
break;
|
|
239
|
+
case "scoped":
|
|
196
240
|
paths.push(pluginName);
|
|
197
241
|
break;
|
|
198
242
|
}
|
|
199
243
|
return paths;
|
|
200
244
|
}
|
|
245
|
+
function toLocalImportSpecifier(pluginName) {
|
|
246
|
+
if (pluginName.startsWith("file:")) return pluginName;
|
|
247
|
+
if (path.isAbsolute(pluginName)) return pathToFileURL(pluginName).href;
|
|
248
|
+
return pluginName;
|
|
249
|
+
}
|
|
201
250
|
function reportSuccessfulLoads(successful) {
|
|
202
251
|
if (successful.length > 0) {
|
|
203
252
|
console.info(`Successfully loaded ${successful.length} plugin(s):`);
|
|
@@ -304,7 +353,10 @@ const isSpecDefinition = (value) => {
|
|
|
304
353
|
//#endregion
|
|
305
354
|
//#region src/generators/spec/specImporter.ts
|
|
306
355
|
async function importDefinition(bundledSpecFile) {
|
|
307
|
-
const
|
|
356
|
+
const contentHash = createHash("sha256").update(fs.readFileSync(bundledSpecFile)).digest("hex");
|
|
357
|
+
const moduleUrl = pathToFileURL(bundledSpecFile);
|
|
358
|
+
moduleUrl.searchParams.set("content", contentHash);
|
|
359
|
+
const specModule = await import(moduleUrl.toString());
|
|
308
360
|
const definition = specModule.spec ?? specModule.default ?? specModule;
|
|
309
361
|
if (!isSpecDefinition(definition)) throw new InvalidSpecEntrypointError(bundledSpecFile);
|
|
310
362
|
return definition;
|
|
@@ -335,11 +387,15 @@ const assertSafeCleanTarget = (outputDir, currentWorkingDirectory) => {
|
|
|
335
387
|
const trimmedOutputDir = outputDir.trim();
|
|
336
388
|
if (trimmedOutputDir.length === 0) throw new Error("Refusing to clean an empty output directory path. Pass a dedicated generated output directory instead.");
|
|
337
389
|
const resolvedWorkingDirectory = path.resolve(currentWorkingDirectory);
|
|
390
|
+
const canonicalWorkingDirectory = fs.realpathSync.native(resolvedWorkingDirectory);
|
|
338
391
|
const resolvedOutputDir = path.resolve(resolvedWorkingDirectory, trimmedOutputDir);
|
|
339
|
-
|
|
340
|
-
if (
|
|
341
|
-
|
|
342
|
-
|
|
392
|
+
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.`);
|
|
395
|
+
const protectedWorkspaceRoots = [findProtectedWorkspaceRoot(resolvedWorkingDirectory), findProtectedWorkspaceRoot(canonicalWorkingDirectory)].filter((root) => root !== void 0);
|
|
396
|
+
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.`);
|
|
343
399
|
};
|
|
344
400
|
/**
|
|
345
401
|
* Main generator for typeweaver
|
|
@@ -433,6 +489,24 @@ const findProtectedWorkspaceRoot = (startDirectory) => {
|
|
|
433
489
|
const hasWorkspaceMarker = (directory) => {
|
|
434
490
|
return ["pnpm-workspace.yaml", ".git"].some((marker) => fs.existsSync(path.join(directory, marker)));
|
|
435
491
|
};
|
|
492
|
+
const canonicalizePathForContainment = (targetPath) => {
|
|
493
|
+
const remainingSegments = [];
|
|
494
|
+
let nearestExistingPath = path.resolve(targetPath);
|
|
495
|
+
while (!fs.existsSync(nearestExistingPath)) {
|
|
496
|
+
const parentPath = path.dirname(nearestExistingPath);
|
|
497
|
+
if (parentPath === nearestExistingPath) break;
|
|
498
|
+
remainingSegments.unshift(path.basename(nearestExistingPath));
|
|
499
|
+
nearestExistingPath = parentPath;
|
|
500
|
+
}
|
|
501
|
+
const canonicalExistingPath = fs.realpathSync.native(nearestExistingPath);
|
|
502
|
+
return path.join(canonicalExistingPath, ...remainingSegments);
|
|
503
|
+
};
|
|
504
|
+
const isSameOrDescendantOf = (directory, ancestor) => {
|
|
505
|
+
const relativePath = path.relative(ancestor, directory);
|
|
506
|
+
const parentTraversalPrefix = `..${path.sep}`;
|
|
507
|
+
const escapesAncestor = relativePath === ".." || relativePath.startsWith(parentTraversalPrefix);
|
|
508
|
+
return relativePath === "" || !escapesAncestor && !path.isAbsolute(relativePath);
|
|
509
|
+
};
|
|
436
510
|
//#endregion
|
|
437
511
|
//#region src/cli.ts
|
|
438
512
|
const moduleDir = path.dirname(fileURLToPath(import.meta.url));
|
package/dist/cli.cjs
CHANGED
|
@@ -31,6 +31,7 @@ let _rexeus_typeweaver_types = require("@rexeus/typeweaver-types");
|
|
|
31
31
|
let node_os = require("node:os");
|
|
32
32
|
node_os = __toESM(node_os);
|
|
33
33
|
let rolldown = require("rolldown");
|
|
34
|
+
let node_crypto = require("node:crypto");
|
|
34
35
|
let _rexeus_typeweaver_core = require("@rexeus/typeweaver-core");
|
|
35
36
|
//#region src/configLoader.ts
|
|
36
37
|
const SUPPORTED_CONFIG_EXTENSIONS = new Set([
|
|
@@ -44,7 +45,7 @@ const UNSUPPORTED_TYPESCRIPT_CONFIG_EXTENSIONS = new Set([
|
|
|
44
45
|
".cts"
|
|
45
46
|
]);
|
|
46
47
|
const getResolvedConfigPath = (configPath, currentWorkingDirectory = process.cwd()) => {
|
|
47
|
-
return node_path.default.isAbsolute(configPath) ? configPath : node_path.default.
|
|
48
|
+
return node_path.default.isAbsolute(configPath) ? configPath : node_path.default.resolve(currentWorkingDirectory, configPath);
|
|
48
49
|
};
|
|
49
50
|
const assertSupportedConfigPath = (configPath) => {
|
|
50
51
|
const extension = node_path.default.extname(configPath).toLowerCase();
|
|
@@ -112,11 +113,16 @@ function generateIndexFiles(templateDir, context) {
|
|
|
112
113
|
const withJsExt = normalizedFile.replace(/\.ts$/, ".js");
|
|
113
114
|
const stripped = normalizedFile.replace(/\.ts$/, "");
|
|
114
115
|
const firstSlash = stripped.indexOf("/");
|
|
116
|
+
if (stripped === "index") continue;
|
|
115
117
|
if (firstSlash === -1) {
|
|
116
118
|
rootFiles.add(`./${withJsExt}`);
|
|
117
119
|
continue;
|
|
118
120
|
}
|
|
119
121
|
const firstSegment = stripped.slice(0, firstSlash);
|
|
122
|
+
if (stripped === "lib/index") {
|
|
123
|
+
existingBarrels.add("lib");
|
|
124
|
+
continue;
|
|
125
|
+
}
|
|
120
126
|
if (firstSegment === "lib") {
|
|
121
127
|
const secondSlash = stripped.indexOf("/", firstSlash + 1);
|
|
122
128
|
const groupKey = secondSlash === -1 ? stripped : stripped.slice(0, secondSlash);
|
|
@@ -165,30 +171,29 @@ async function loadPlugins(registry, requiredPlugins, strategies, config) {
|
|
|
165
171
|
if (!config?.plugins) return;
|
|
166
172
|
const successful = [];
|
|
167
173
|
for (const plugin of config.plugins) {
|
|
168
|
-
|
|
169
|
-
if (typeof plugin === "string") result = await loadPlugin(plugin, strategies);
|
|
170
|
-
else result = await loadPlugin(plugin[0], strategies);
|
|
174
|
+
const result = await loadPlugin(typeof plugin === "string" ? plugin : plugin[0], strategies, typeof plugin === "string" ? void 0 : plugin[1]);
|
|
171
175
|
if (result.success === false) throw new PluginLoadingFailure(result.error.pluginName, result.error.attempts);
|
|
172
176
|
successful.push(result.value);
|
|
173
|
-
registry.register(result.value.plugin);
|
|
177
|
+
registry.register(result.value.plugin, result.value.config);
|
|
174
178
|
}
|
|
175
179
|
reportSuccessfulLoads(successful);
|
|
176
180
|
}
|
|
177
|
-
async function loadPlugin(pluginName, strategies) {
|
|
181
|
+
async function loadPlugin(pluginName, strategies, pluginConfig) {
|
|
178
182
|
const possiblePaths = generatePluginPaths(pluginName, strategies);
|
|
179
183
|
const attempts = [];
|
|
180
184
|
for (const possiblePath of possiblePaths) try {
|
|
181
|
-
const
|
|
182
|
-
if (
|
|
185
|
+
const plugin = createPluginInstance(await import(possiblePath), pluginConfig);
|
|
186
|
+
if (plugin.success) return {
|
|
183
187
|
success: true,
|
|
184
188
|
value: {
|
|
185
|
-
plugin:
|
|
186
|
-
source: possiblePath
|
|
189
|
+
plugin: plugin.value,
|
|
190
|
+
source: possiblePath,
|
|
191
|
+
config: pluginConfig
|
|
187
192
|
}
|
|
188
193
|
};
|
|
189
194
|
attempts.push({
|
|
190
195
|
path: possiblePath,
|
|
191
|
-
error:
|
|
196
|
+
error: plugin.error
|
|
192
197
|
});
|
|
193
198
|
} catch (error) {
|
|
194
199
|
attempts.push({
|
|
@@ -204,10 +209,46 @@ async function loadPlugin(pluginName, strategies) {
|
|
|
204
209
|
}
|
|
205
210
|
};
|
|
206
211
|
}
|
|
207
|
-
function
|
|
208
|
-
|
|
212
|
+
function createPluginInstance(pluginModule, pluginConfig) {
|
|
213
|
+
const candidates = findPluginConstructorCandidates(pluginModule);
|
|
214
|
+
if (candidates.length === 0) return {
|
|
215
|
+
success: false,
|
|
216
|
+
error: "No plugin constructor export found"
|
|
217
|
+
};
|
|
218
|
+
const errors = [];
|
|
219
|
+
for (const candidate of candidates) try {
|
|
220
|
+
const plugin = new candidate.constructor(pluginConfig);
|
|
221
|
+
if (isTypeweaverPlugin(plugin)) return {
|
|
222
|
+
success: true,
|
|
223
|
+
value: plugin
|
|
224
|
+
};
|
|
225
|
+
errors.push(`Export '${candidate.exportName}' did not produce a valid plugin with a string name`);
|
|
226
|
+
} catch (error) {
|
|
227
|
+
errors.push(`Export '${candidate.exportName}' could not be instantiated: ${formatError(error)}`);
|
|
228
|
+
}
|
|
229
|
+
return {
|
|
230
|
+
success: false,
|
|
231
|
+
error: errors.join("; ")
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
function findPluginConstructorCandidates(pluginModule) {
|
|
235
|
+
const candidates = [];
|
|
236
|
+
for (const [key, value] of Object.entries(pluginModule)) if (key !== "default" && typeof value === "function") candidates.push({
|
|
237
|
+
exportName: key,
|
|
238
|
+
constructor: value
|
|
239
|
+
});
|
|
209
240
|
const defaultExport = pluginModule.default;
|
|
210
|
-
if (typeof defaultExport === "function")
|
|
241
|
+
if (typeof defaultExport === "function") candidates.push({
|
|
242
|
+
exportName: "default",
|
|
243
|
+
constructor: defaultExport
|
|
244
|
+
});
|
|
245
|
+
return candidates;
|
|
246
|
+
}
|
|
247
|
+
function isTypeweaverPlugin(value) {
|
|
248
|
+
return typeof value === "object" && value !== null && typeof value.name === "string" && value.name.length > 0;
|
|
249
|
+
}
|
|
250
|
+
function formatError(error) {
|
|
251
|
+
return error instanceof Error ? error.message : String(error);
|
|
211
252
|
}
|
|
212
253
|
function generatePluginPaths(pluginName, strategies) {
|
|
213
254
|
const paths = [];
|
|
@@ -217,11 +258,19 @@ function generatePluginPaths(pluginName, strategies) {
|
|
|
217
258
|
paths.push(`@rexeus/${pluginName}`);
|
|
218
259
|
break;
|
|
219
260
|
case "local":
|
|
261
|
+
paths.push(toLocalImportSpecifier(pluginName));
|
|
262
|
+
break;
|
|
263
|
+
case "scoped":
|
|
220
264
|
paths.push(pluginName);
|
|
221
265
|
break;
|
|
222
266
|
}
|
|
223
267
|
return paths;
|
|
224
268
|
}
|
|
269
|
+
function toLocalImportSpecifier(pluginName) {
|
|
270
|
+
if (pluginName.startsWith("file:")) return pluginName;
|
|
271
|
+
if (node_path.default.isAbsolute(pluginName)) return (0, node_url.pathToFileURL)(pluginName).href;
|
|
272
|
+
return pluginName;
|
|
273
|
+
}
|
|
225
274
|
function reportSuccessfulLoads(successful) {
|
|
226
275
|
if (successful.length > 0) {
|
|
227
276
|
console.info(`Successfully loaded ${successful.length} plugin(s):`);
|
|
@@ -328,7 +377,10 @@ const isSpecDefinition = (value) => {
|
|
|
328
377
|
//#endregion
|
|
329
378
|
//#region src/generators/spec/specImporter.ts
|
|
330
379
|
async function importDefinition(bundledSpecFile) {
|
|
331
|
-
const
|
|
380
|
+
const contentHash = (0, node_crypto.createHash)("sha256").update(node_fs.default.readFileSync(bundledSpecFile)).digest("hex");
|
|
381
|
+
const moduleUrl = (0, node_url.pathToFileURL)(bundledSpecFile);
|
|
382
|
+
moduleUrl.searchParams.set("content", contentHash);
|
|
383
|
+
const specModule = await import(moduleUrl.toString());
|
|
332
384
|
const definition = specModule.spec ?? specModule.default ?? specModule;
|
|
333
385
|
if (!isSpecDefinition(definition)) throw new InvalidSpecEntrypointError(bundledSpecFile);
|
|
334
386
|
return definition;
|
|
@@ -359,11 +411,15 @@ const assertSafeCleanTarget = (outputDir, currentWorkingDirectory) => {
|
|
|
359
411
|
const trimmedOutputDir = outputDir.trim();
|
|
360
412
|
if (trimmedOutputDir.length === 0) throw new Error("Refusing to clean an empty output directory path. Pass a dedicated generated output directory instead.");
|
|
361
413
|
const resolvedWorkingDirectory = node_path.default.resolve(currentWorkingDirectory);
|
|
414
|
+
const canonicalWorkingDirectory = node_fs.default.realpathSync.native(resolvedWorkingDirectory);
|
|
362
415
|
const resolvedOutputDir = node_path.default.resolve(resolvedWorkingDirectory, trimmedOutputDir);
|
|
363
|
-
|
|
364
|
-
if (
|
|
365
|
-
|
|
366
|
-
|
|
416
|
+
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.`);
|
|
419
|
+
const protectedWorkspaceRoots = [findProtectedWorkspaceRoot(resolvedWorkingDirectory), findProtectedWorkspaceRoot(canonicalWorkingDirectory)].filter((root) => root !== void 0);
|
|
420
|
+
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.`);
|
|
367
423
|
};
|
|
368
424
|
/**
|
|
369
425
|
* Main generator for typeweaver
|
|
@@ -457,6 +513,24 @@ const findProtectedWorkspaceRoot = (startDirectory) => {
|
|
|
457
513
|
const hasWorkspaceMarker = (directory) => {
|
|
458
514
|
return ["pnpm-workspace.yaml", ".git"].some((marker) => node_fs.default.existsSync(node_path.default.join(directory, marker)));
|
|
459
515
|
};
|
|
516
|
+
const canonicalizePathForContainment = (targetPath) => {
|
|
517
|
+
const remainingSegments = [];
|
|
518
|
+
let nearestExistingPath = node_path.default.resolve(targetPath);
|
|
519
|
+
while (!node_fs.default.existsSync(nearestExistingPath)) {
|
|
520
|
+
const parentPath = node_path.default.dirname(nearestExistingPath);
|
|
521
|
+
if (parentPath === nearestExistingPath) break;
|
|
522
|
+
remainingSegments.unshift(node_path.default.basename(nearestExistingPath));
|
|
523
|
+
nearestExistingPath = parentPath;
|
|
524
|
+
}
|
|
525
|
+
const canonicalExistingPath = node_fs.default.realpathSync.native(nearestExistingPath);
|
|
526
|
+
return node_path.default.join(canonicalExistingPath, ...remainingSegments);
|
|
527
|
+
};
|
|
528
|
+
const isSameOrDescendantOf = (directory, ancestor) => {
|
|
529
|
+
const relativePath = node_path.default.relative(ancestor, directory);
|
|
530
|
+
const parentTraversalPrefix = `..${node_path.default.sep}`;
|
|
531
|
+
const escapesAncestor = relativePath === ".." || relativePath.startsWith(parentTraversalPrefix);
|
|
532
|
+
return relativePath === "" || !escapesAncestor && !node_path.default.isAbsolute(relativePath);
|
|
533
|
+
};
|
|
460
534
|
//#endregion
|
|
461
535
|
//#region src/cli.ts
|
|
462
536
|
const moduleDir = node_path.default.dirname((0, node_url.fileURLToPath)(require("url").pathToFileURL(__filename).href));
|
package/dist/cli.mjs
CHANGED
|
@@ -6,6 +6,7 @@ import { createPluginContextBuilder, createPluginRegistry, normalizeSpec, render
|
|
|
6
6
|
import { TypesPlugin } from "@rexeus/typeweaver-types";
|
|
7
7
|
import os from "node:os";
|
|
8
8
|
import { build } from "rolldown";
|
|
9
|
+
import { createHash } from "node:crypto";
|
|
9
10
|
import { HttpMethod, HttpStatusCode } from "@rexeus/typeweaver-core";
|
|
10
11
|
//#region src/configLoader.ts
|
|
11
12
|
const SUPPORTED_CONFIG_EXTENSIONS = new Set([
|
|
@@ -19,7 +20,7 @@ const UNSUPPORTED_TYPESCRIPT_CONFIG_EXTENSIONS = new Set([
|
|
|
19
20
|
".cts"
|
|
20
21
|
]);
|
|
21
22
|
const getResolvedConfigPath = (configPath, currentWorkingDirectory = process.cwd()) => {
|
|
22
|
-
return path.isAbsolute(configPath) ? configPath : path.
|
|
23
|
+
return path.isAbsolute(configPath) ? configPath : path.resolve(currentWorkingDirectory, configPath);
|
|
23
24
|
};
|
|
24
25
|
const assertSupportedConfigPath = (configPath) => {
|
|
25
26
|
const extension = path.extname(configPath).toLowerCase();
|
|
@@ -87,11 +88,16 @@ function generateIndexFiles(templateDir, context) {
|
|
|
87
88
|
const withJsExt = normalizedFile.replace(/\.ts$/, ".js");
|
|
88
89
|
const stripped = normalizedFile.replace(/\.ts$/, "");
|
|
89
90
|
const firstSlash = stripped.indexOf("/");
|
|
91
|
+
if (stripped === "index") continue;
|
|
90
92
|
if (firstSlash === -1) {
|
|
91
93
|
rootFiles.add(`./${withJsExt}`);
|
|
92
94
|
continue;
|
|
93
95
|
}
|
|
94
96
|
const firstSegment = stripped.slice(0, firstSlash);
|
|
97
|
+
if (stripped === "lib/index") {
|
|
98
|
+
existingBarrels.add("lib");
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
95
101
|
if (firstSegment === "lib") {
|
|
96
102
|
const secondSlash = stripped.indexOf("/", firstSlash + 1);
|
|
97
103
|
const groupKey = secondSlash === -1 ? stripped : stripped.slice(0, secondSlash);
|
|
@@ -140,30 +146,29 @@ async function loadPlugins(registry, requiredPlugins, strategies, config) {
|
|
|
140
146
|
if (!config?.plugins) return;
|
|
141
147
|
const successful = [];
|
|
142
148
|
for (const plugin of config.plugins) {
|
|
143
|
-
|
|
144
|
-
if (typeof plugin === "string") result = await loadPlugin(plugin, strategies);
|
|
145
|
-
else result = await loadPlugin(plugin[0], strategies);
|
|
149
|
+
const result = await loadPlugin(typeof plugin === "string" ? plugin : plugin[0], strategies, typeof plugin === "string" ? void 0 : plugin[1]);
|
|
146
150
|
if (result.success === false) throw new PluginLoadingFailure(result.error.pluginName, result.error.attempts);
|
|
147
151
|
successful.push(result.value);
|
|
148
|
-
registry.register(result.value.plugin);
|
|
152
|
+
registry.register(result.value.plugin, result.value.config);
|
|
149
153
|
}
|
|
150
154
|
reportSuccessfulLoads(successful);
|
|
151
155
|
}
|
|
152
|
-
async function loadPlugin(pluginName, strategies) {
|
|
156
|
+
async function loadPlugin(pluginName, strategies, pluginConfig) {
|
|
153
157
|
const possiblePaths = generatePluginPaths(pluginName, strategies);
|
|
154
158
|
const attempts = [];
|
|
155
159
|
for (const possiblePath of possiblePaths) try {
|
|
156
|
-
const
|
|
157
|
-
if (
|
|
160
|
+
const plugin = createPluginInstance(await import(possiblePath), pluginConfig);
|
|
161
|
+
if (plugin.success) return {
|
|
158
162
|
success: true,
|
|
159
163
|
value: {
|
|
160
|
-
plugin:
|
|
161
|
-
source: possiblePath
|
|
164
|
+
plugin: plugin.value,
|
|
165
|
+
source: possiblePath,
|
|
166
|
+
config: pluginConfig
|
|
162
167
|
}
|
|
163
168
|
};
|
|
164
169
|
attempts.push({
|
|
165
170
|
path: possiblePath,
|
|
166
|
-
error:
|
|
171
|
+
error: plugin.error
|
|
167
172
|
});
|
|
168
173
|
} catch (error) {
|
|
169
174
|
attempts.push({
|
|
@@ -179,10 +184,46 @@ async function loadPlugin(pluginName, strategies) {
|
|
|
179
184
|
}
|
|
180
185
|
};
|
|
181
186
|
}
|
|
182
|
-
function
|
|
183
|
-
|
|
187
|
+
function createPluginInstance(pluginModule, pluginConfig) {
|
|
188
|
+
const candidates = findPluginConstructorCandidates(pluginModule);
|
|
189
|
+
if (candidates.length === 0) return {
|
|
190
|
+
success: false,
|
|
191
|
+
error: "No plugin constructor export found"
|
|
192
|
+
};
|
|
193
|
+
const errors = [];
|
|
194
|
+
for (const candidate of candidates) try {
|
|
195
|
+
const plugin = new candidate.constructor(pluginConfig);
|
|
196
|
+
if (isTypeweaverPlugin(plugin)) return {
|
|
197
|
+
success: true,
|
|
198
|
+
value: plugin
|
|
199
|
+
};
|
|
200
|
+
errors.push(`Export '${candidate.exportName}' did not produce a valid plugin with a string name`);
|
|
201
|
+
} catch (error) {
|
|
202
|
+
errors.push(`Export '${candidate.exportName}' could not be instantiated: ${formatError(error)}`);
|
|
203
|
+
}
|
|
204
|
+
return {
|
|
205
|
+
success: false,
|
|
206
|
+
error: errors.join("; ")
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
function findPluginConstructorCandidates(pluginModule) {
|
|
210
|
+
const candidates = [];
|
|
211
|
+
for (const [key, value] of Object.entries(pluginModule)) if (key !== "default" && typeof value === "function") candidates.push({
|
|
212
|
+
exportName: key,
|
|
213
|
+
constructor: value
|
|
214
|
+
});
|
|
184
215
|
const defaultExport = pluginModule.default;
|
|
185
|
-
if (typeof defaultExport === "function")
|
|
216
|
+
if (typeof defaultExport === "function") candidates.push({
|
|
217
|
+
exportName: "default",
|
|
218
|
+
constructor: defaultExport
|
|
219
|
+
});
|
|
220
|
+
return candidates;
|
|
221
|
+
}
|
|
222
|
+
function isTypeweaverPlugin(value) {
|
|
223
|
+
return typeof value === "object" && value !== null && typeof value.name === "string" && value.name.length > 0;
|
|
224
|
+
}
|
|
225
|
+
function formatError(error) {
|
|
226
|
+
return error instanceof Error ? error.message : String(error);
|
|
186
227
|
}
|
|
187
228
|
function generatePluginPaths(pluginName, strategies) {
|
|
188
229
|
const paths = [];
|
|
@@ -192,11 +233,19 @@ function generatePluginPaths(pluginName, strategies) {
|
|
|
192
233
|
paths.push(`@rexeus/${pluginName}`);
|
|
193
234
|
break;
|
|
194
235
|
case "local":
|
|
236
|
+
paths.push(toLocalImportSpecifier(pluginName));
|
|
237
|
+
break;
|
|
238
|
+
case "scoped":
|
|
195
239
|
paths.push(pluginName);
|
|
196
240
|
break;
|
|
197
241
|
}
|
|
198
242
|
return paths;
|
|
199
243
|
}
|
|
244
|
+
function toLocalImportSpecifier(pluginName) {
|
|
245
|
+
if (pluginName.startsWith("file:")) return pluginName;
|
|
246
|
+
if (path.isAbsolute(pluginName)) return pathToFileURL(pluginName).href;
|
|
247
|
+
return pluginName;
|
|
248
|
+
}
|
|
200
249
|
function reportSuccessfulLoads(successful) {
|
|
201
250
|
if (successful.length > 0) {
|
|
202
251
|
console.info(`Successfully loaded ${successful.length} plugin(s):`);
|
|
@@ -303,7 +352,10 @@ const isSpecDefinition = (value) => {
|
|
|
303
352
|
//#endregion
|
|
304
353
|
//#region src/generators/spec/specImporter.ts
|
|
305
354
|
async function importDefinition(bundledSpecFile) {
|
|
306
|
-
const
|
|
355
|
+
const contentHash = createHash("sha256").update(fs.readFileSync(bundledSpecFile)).digest("hex");
|
|
356
|
+
const moduleUrl = pathToFileURL(bundledSpecFile);
|
|
357
|
+
moduleUrl.searchParams.set("content", contentHash);
|
|
358
|
+
const specModule = await import(moduleUrl.toString());
|
|
307
359
|
const definition = specModule.spec ?? specModule.default ?? specModule;
|
|
308
360
|
if (!isSpecDefinition(definition)) throw new InvalidSpecEntrypointError(bundledSpecFile);
|
|
309
361
|
return definition;
|
|
@@ -334,11 +386,15 @@ const assertSafeCleanTarget = (outputDir, currentWorkingDirectory) => {
|
|
|
334
386
|
const trimmedOutputDir = outputDir.trim();
|
|
335
387
|
if (trimmedOutputDir.length === 0) throw new Error("Refusing to clean an empty output directory path. Pass a dedicated generated output directory instead.");
|
|
336
388
|
const resolvedWorkingDirectory = path.resolve(currentWorkingDirectory);
|
|
389
|
+
const canonicalWorkingDirectory = fs.realpathSync.native(resolvedWorkingDirectory);
|
|
337
390
|
const resolvedOutputDir = path.resolve(resolvedWorkingDirectory, trimmedOutputDir);
|
|
338
|
-
|
|
339
|
-
if (
|
|
340
|
-
|
|
341
|
-
|
|
391
|
+
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.`);
|
|
394
|
+
const protectedWorkspaceRoots = [findProtectedWorkspaceRoot(resolvedWorkingDirectory), findProtectedWorkspaceRoot(canonicalWorkingDirectory)].filter((root) => root !== void 0);
|
|
395
|
+
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.`);
|
|
342
398
|
};
|
|
343
399
|
/**
|
|
344
400
|
* Main generator for typeweaver
|
|
@@ -432,6 +488,24 @@ const findProtectedWorkspaceRoot = (startDirectory) => {
|
|
|
432
488
|
const hasWorkspaceMarker = (directory) => {
|
|
433
489
|
return ["pnpm-workspace.yaml", ".git"].some((marker) => fs.existsSync(path.join(directory, marker)));
|
|
434
490
|
};
|
|
491
|
+
const canonicalizePathForContainment = (targetPath) => {
|
|
492
|
+
const remainingSegments = [];
|
|
493
|
+
let nearestExistingPath = path.resolve(targetPath);
|
|
494
|
+
while (!fs.existsSync(nearestExistingPath)) {
|
|
495
|
+
const parentPath = path.dirname(nearestExistingPath);
|
|
496
|
+
if (parentPath === nearestExistingPath) break;
|
|
497
|
+
remainingSegments.unshift(path.basename(nearestExistingPath));
|
|
498
|
+
nearestExistingPath = parentPath;
|
|
499
|
+
}
|
|
500
|
+
const canonicalExistingPath = fs.realpathSync.native(nearestExistingPath);
|
|
501
|
+
return path.join(canonicalExistingPath, ...remainingSegments);
|
|
502
|
+
};
|
|
503
|
+
const isSameOrDescendantOf = (directory, ancestor) => {
|
|
504
|
+
const relativePath = path.relative(ancestor, directory);
|
|
505
|
+
const parentTraversalPrefix = `..${path.sep}`;
|
|
506
|
+
const escapesAncestor = relativePath === ".." || relativePath.startsWith(parentTraversalPrefix);
|
|
507
|
+
return relativePath === "" || !escapesAncestor && !path.isAbsolute(relativePath);
|
|
508
|
+
};
|
|
435
509
|
//#endregion
|
|
436
510
|
//#region src/cli.ts
|
|
437
511
|
const moduleDir = path.dirname(fileURLToPath(import.meta.url));
|
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.join(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 function generateIndexFiles(\n templateDir: string,\n context: GeneratorContext\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 (firstSlash === -1) {\n rootFiles.add(`./${withJsExt}`);\n continue;\n }\n\n const firstSegment = stripped.slice(0, firstSlash);\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 type {\n PluginRegistryApi,\n TypeweaverConfig,\n TypeweaverPlugin,\n} from \"@rexeus/typeweaver-gen\";\nimport { TypesPlugin } from \"@rexeus/typeweaver-types\";\nimport { PluginLoadingFailure } from \"./errors/PluginLoadingFailure.js\";\nimport type { PluginLoadError } from \"./errors/PluginLoadingFailure.js\";\n\nexport type PluginResolutionStrategy = \"npm\" | \"local\" | \"scoped\";\n\nexport type PluginLoadResult = {\n plugin: TypeweaverPlugin;\n source: string;\n};\n\ntype LoadResult<T, E> =\n | { success: true; value: T }\n | { success: false; error: E };\n\nexport async function loadPlugins(\n registry: PluginRegistryApi,\n requiredPlugins: [TypesPlugin],\n strategies: 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 let result: LoadResult<PluginLoadResult, PluginLoadError>;\n if (typeof plugin === \"string\") {\n result = await loadPlugin(plugin, strategies);\n } else {\n result = await loadPlugin(plugin[0], strategies);\n }\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);\n }\n\n reportSuccessfulLoads(successful);\n}\n\nasync function loadPlugin(\n pluginName: string,\n strategies: PluginResolutionStrategy[]\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 PluginClass = findPluginConstructor(pluginPackage);\n if (PluginClass) {\n return {\n success: true,\n value: {\n plugin: new PluginClass(),\n source: possiblePath,\n },\n };\n }\n attempts.push({\n path: possiblePath,\n error: \"No plugin class export found\",\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 findPluginConstructor(\n pluginModule: Record<string, unknown>\n): (new () => TypeweaverPlugin) | undefined {\n for (const [key, value] of Object.entries(pluginModule)) {\n if (key !== \"default\" && typeof value === \"function\") {\n return value as new () => TypeweaverPlugin;\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 return defaultExport as new () => TypeweaverPlugin;\n }\n\n return undefined;\n}\n\nfunction generatePluginPaths(\n pluginName: string,\n strategies: 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(pluginName);\n break;\n }\n }\n\n return paths;\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 { 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 moduleUrl = pathToFileURL(bundledSpecFile).toString();\n const specModule = (await import(moduleUrl)) 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 resolvedOutputDir = path.resolve(\n resolvedWorkingDirectory,\n trimmedOutputDir\n );\n const filesystemRoot = path.parse(resolvedOutputDir).root;\n\n if (resolvedOutputDir === filesystemRoot) {\n throw new Error(\n `Refusing to clean '${outputDir}' because it resolves to the filesystem root.`\n );\n }\n\n if (resolvedOutputDir === resolvedWorkingDirectory) {\n throw new Error(\n `Refusing to clean '${outputDir}' because it resolves to the current working directory.`\n );\n }\n\n const protectedWorkspaceRoot = findProtectedWorkspaceRoot(\n resolvedWorkingDirectory\n );\n\n if (\n protectedWorkspaceRoot !== undefined &&\n resolvedOutputDir === protectedWorkspaceRoot\n ) {\n throw new Error(\n `Refusing to clean '${outputDir}' because it resolves to the inferred workspace root '${protectedWorkspaceRoot}'. 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","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/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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"}
|
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-
|
|
20
|
+
await import("./cli-C-s7e7_U.mjs");
|
|
21
21
|
};
|
|
22
22
|
main().catch((error) => {
|
|
23
23
|
console.error("Failed to start TypeWeaver CLI:", error);
|
package/dist/templates/Index.ejs
CHANGED
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* This file was automatically generated by typeweaver.
|
|
4
4
|
* DO NOT EDIT. Instead, modify the source definition file and generate again.
|
|
5
|
-
*
|
|
5
|
+
*
|
|
6
6
|
* @generated by @rexeus/typeweaver
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
<% for (const indexPath of indexPaths) { %>
|
|
10
10
|
export * from "<%= indexPath %>";
|
|
11
|
-
<% } %>
|
|
11
|
+
<% } %>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rexeus/typeweaver",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.4",
|
|
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-
|
|
58
|
-
"@rexeus/typeweaver-
|
|
59
|
-
"@rexeus/typeweaver-
|
|
60
|
-
"@rexeus/typeweaver-
|
|
61
|
-
"@rexeus/typeweaver-
|
|
62
|
-
"@rexeus/typeweaver-
|
|
63
|
-
"@rexeus/typeweaver-types": "^0.10.
|
|
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"
|
|
64
64
|
},
|
|
65
65
|
"peerDependencies": {
|
|
66
66
|
"oxfmt": ">=0.30.0"
|