openapi-typesafe-migrate 0.0.0 → 1.0.0-rc.1

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.
@@ -0,0 +1,1096 @@
1
+ import { mkdirSync, appendFileSync, readFileSync } from 'node:fs';
2
+ import { tmpdir } from 'node:os';
3
+ import { dirname, join, resolve } from 'node:path';
4
+ import { readFile, writeFile, readdir } from 'node:fs/promises';
5
+ import ts from '@typescript/typescript6';
6
+ import { parseArgs } from 'node:util';
7
+
8
+ class JsonLinesLogger {
9
+ #options;
10
+ constructor(options) {
11
+ this.#options = options;
12
+ mkdirSync(dirname(options.path), { recursive: true });
13
+ }
14
+ info(event, fields = {}) {
15
+ this.#append("info", event, fields);
16
+ }
17
+ warn(event, fields = {}) {
18
+ this.#append("warn", event, fields);
19
+ }
20
+ #append(level, event, fields) {
21
+ const time = this.#options.now().toISOString();
22
+ appendFileSync(this.#options.path, `${JSON.stringify({ time, level, event, ...fields })}
23
+ `);
24
+ }
25
+ }
26
+ function createJsonLinesLogger(options) {
27
+ return new JsonLinesLogger(options);
28
+ }
29
+
30
+ const SKIPPED_DIRECTORIES = /* @__PURE__ */ new Set([
31
+ "node_modules",
32
+ ".git",
33
+ "dist",
34
+ ".next",
35
+ ".nuxt",
36
+ ".output",
37
+ ".svelte-kit",
38
+ ".turbo",
39
+ "coverage"
40
+ ]);
41
+ async function listTree(root, relative) {
42
+ const entries = await readdir(join(root, relative), { withFileTypes: true });
43
+ const nested = await Promise.all(
44
+ entries.map((entry) => {
45
+ const path = relative === "" ? entry.name : `${relative}/${entry.name}`;
46
+ if (entry.isDirectory()) {
47
+ return SKIPPED_DIRECTORIES.has(entry.name) ? [] : listTree(root, path);
48
+ }
49
+ return entry.isFile() ? [path] : [];
50
+ })
51
+ );
52
+ return nested.flat();
53
+ }
54
+ class NodeProjectFiles {
55
+ #root;
56
+ constructor(root) {
57
+ this.#root = root;
58
+ }
59
+ listFiles() {
60
+ return listTree(this.#root, "");
61
+ }
62
+ read(path) {
63
+ return readFile(join(this.#root, path), "utf8");
64
+ }
65
+ write(path, text) {
66
+ return writeFile(join(this.#root, path), text, "utf8");
67
+ }
68
+ }
69
+ function createNodeProjectFiles(root) {
70
+ return new NodeProjectFiles(root);
71
+ }
72
+
73
+ function unchanged(text) {
74
+ return { text, changes: [], manualSteps: [] };
75
+ }
76
+ function lineAt(text, offset) {
77
+ let line = 1;
78
+ for (let index = text.indexOf("\n"); index !== -1 && index < offset; ) {
79
+ line++;
80
+ index = text.indexOf("\n", index + 1);
81
+ }
82
+ return line;
83
+ }
84
+
85
+ const GENERATOR_MODULES = /* @__PURE__ */ new Set(["openapi-typesafe", "openapi-typescript"]);
86
+ const TYPESCRIPT_MODULES = /* @__PURE__ */ new Set(["typescript", "@typescript/typescript6"]);
87
+ function namedImports(clause, into) {
88
+ const bindings = clause.namedBindings;
89
+ if (bindings === void 0 || !ts.isNamedImports(bindings)) {
90
+ return;
91
+ }
92
+ for (const element of bindings.elements) {
93
+ into.set(element.name.text, (element.propertyName ?? element.name).text);
94
+ }
95
+ }
96
+ function addTypescriptImport(clause, names) {
97
+ if (clause.name !== void 0) {
98
+ names.typescriptModules.add(clause.name.text);
99
+ }
100
+ const bindings = clause.namedBindings;
101
+ if (bindings !== void 0 && ts.isNamespaceImport(bindings)) {
102
+ names.typescriptModules.add(bindings.name.text);
103
+ }
104
+ namedImports(clause, names.typescriptImports);
105
+ }
106
+ function addGeneratorImport(clause, names) {
107
+ if (clause.name !== void 0) {
108
+ names.generatorFunctions.add(clause.name.text);
109
+ }
110
+ namedImports(clause, names.helperImports);
111
+ }
112
+ function addImport(statement, names) {
113
+ const clause = statement.importClause;
114
+ if (clause === void 0 || !ts.isStringLiteral(statement.moduleSpecifier)) {
115
+ return;
116
+ }
117
+ const specifier = statement.moduleSpecifier.text;
118
+ if (TYPESCRIPT_MODULES.has(specifier)) {
119
+ addTypescriptImport(clause, names);
120
+ } else if (GENERATOR_MODULES.has(specifier)) {
121
+ addGeneratorImport(clause, names);
122
+ }
123
+ }
124
+ function addConstants(statement, names) {
125
+ if ((statement.declarationList.flags & ts.NodeFlags.Const) === 0) {
126
+ return;
127
+ }
128
+ for (const declaration of statement.declarationList.declarations) {
129
+ const initializer = declaration.initializer;
130
+ if (!ts.isIdentifier(declaration.name) || initializer === void 0) {
131
+ continue;
132
+ }
133
+ names.constants.set(declaration.name.text, initializer);
134
+ if (ts.isArrowFunction(initializer) || ts.isFunctionExpression(initializer)) {
135
+ names.functions.set(declaration.name.text, initializer);
136
+ }
137
+ }
138
+ }
139
+ function collectFileNames(file) {
140
+ const names = {
141
+ typescriptModules: /* @__PURE__ */ new Set(),
142
+ typescriptImports: /* @__PURE__ */ new Map(),
143
+ helperImports: /* @__PURE__ */ new Map(),
144
+ constants: /* @__PURE__ */ new Map(),
145
+ generatorFunctions: /* @__PURE__ */ new Set(),
146
+ functions: /* @__PURE__ */ new Map()
147
+ };
148
+ for (const statement of file.statements) {
149
+ if (ts.isImportDeclaration(statement)) {
150
+ addImport(statement, names);
151
+ } else if (ts.isVariableStatement(statement)) {
152
+ addConstants(statement, names);
153
+ } else if (ts.isFunctionDeclaration(statement) && statement.name !== void 0) {
154
+ names.functions.set(statement.name.text, statement);
155
+ }
156
+ }
157
+ return names;
158
+ }
159
+
160
+ const KEYWORDS = /* @__PURE__ */ new Map([
161
+ ["AnyKeyword", "any"],
162
+ ["BigIntKeyword", "bigint"],
163
+ ["BooleanKeyword", "boolean"],
164
+ ["NeverKeyword", "never"],
165
+ ["NumberKeyword", "number"],
166
+ ["ObjectKeyword", "object"],
167
+ ["StringKeyword", "string"],
168
+ ["SymbolKeyword", "symbol"],
169
+ ["UndefinedKeyword", "undefined"],
170
+ ["UnknownKeyword", "unknown"],
171
+ ["VoidKeyword", "void"]
172
+ ]);
173
+ const HELPER_CONSTANTS = /* @__PURE__ */ new Map([
174
+ ["BOOLEAN", "boolean"],
175
+ ["FALSE", "false"],
176
+ ["NEVER", "never"],
177
+ ["NULL", "null"],
178
+ ["NUMBER", "number"],
179
+ ["STRING", "string"],
180
+ ["TRUE", "true"],
181
+ ["UNDEFINED", "undefined"],
182
+ ["UNKNOWN", "unknown"]
183
+ ]);
184
+ const TYPE_NAME_RE = /^[A-Za-z_$][\w$]*(\.[A-Za-z_$][\w$]*)*$/;
185
+ const plain = (text) => ({ text, operator: null });
186
+ function factoryMethod(callee, names) {
187
+ if (!ts.isPropertyAccessExpression(callee)) {
188
+ return void 0;
189
+ }
190
+ const target = callee.expression;
191
+ const isFactory = ts.isIdentifier(target) ? names.typescriptImports.get(target.text) === "factory" : ts.isPropertyAccessExpression(target) && target.name.text === "factory" && ts.isIdentifier(target.expression) && names.typescriptModules.has(target.expression.text);
192
+ return isFactory ? callee.name.text : void 0;
193
+ }
194
+ function syntaxKindMember(expression, names) {
195
+ if (!ts.isPropertyAccessExpression(expression)) {
196
+ return void 0;
197
+ }
198
+ const target = expression.expression;
199
+ const isSyntaxKind = ts.isIdentifier(target) ? names.typescriptImports.get(target.text) === "SyntaxKind" : ts.isPropertyAccessExpression(target) && target.name.text === "SyntaxKind" && ts.isIdentifier(target.expression) && names.typescriptModules.has(target.expression.text);
200
+ return isSyntaxKind ? expression.name.text : void 0;
201
+ }
202
+ function typeName(argument, names) {
203
+ if (argument === void 0) {
204
+ return void 0;
205
+ }
206
+ if (ts.isStringLiteralLike(argument)) {
207
+ return TYPE_NAME_RE.test(argument.text) ? argument.text : void 0;
208
+ }
209
+ if (ts.isCallExpression(argument) && factoryMethod(argument.expression, names) === "createIdentifier") {
210
+ return typeName(argument.arguments[0], names);
211
+ }
212
+ return void 0;
213
+ }
214
+ function literalText(argument, names) {
215
+ if (argument === void 0 || !ts.isCallExpression(argument)) {
216
+ return void 0;
217
+ }
218
+ const method = factoryMethod(argument.expression, names);
219
+ const [value] = argument.arguments;
220
+ switch (method) {
221
+ case "createNull":
222
+ return "null";
223
+ case "createTrue":
224
+ return "true";
225
+ case "createFalse":
226
+ return "false";
227
+ case "createStringLiteral":
228
+ return value !== void 0 && ts.isStringLiteralLike(value) ? JSON.stringify(value.text) : void 0;
229
+ case "createNumericLiteral":
230
+ return value !== void 0 && (ts.isNumericLiteral(value) || ts.isStringLiteralLike(value)) ? String(Number(value.text)) : void 0;
231
+ default:
232
+ return void 0;
233
+ }
234
+ }
235
+ function joined(elements, operator, names) {
236
+ if (elements === void 0 || !ts.isArrayLiteralExpression(elements) || elements.elements.length === 0) {
237
+ return void 0;
238
+ }
239
+ const parts = elements.elements.map((element) => typeTextOf(element, names));
240
+ if (parts.some((part) => part === void 0)) {
241
+ return void 0;
242
+ }
243
+ const texts = parts.map(
244
+ (part) => operator === "&" && part.operator === "|" ? `(${part.text})` : part.text
245
+ );
246
+ return { text: texts.join(` ${operator} `), operator: texts.length > 1 ? operator : null };
247
+ }
248
+ function factoryCallText(call, method, names) {
249
+ const [first, second] = call.arguments;
250
+ switch (method) {
251
+ case "createTypeReferenceNode": {
252
+ const name = second === void 0 ? typeName(first, names) : void 0;
253
+ return name === void 0 ? void 0 : plain(name);
254
+ }
255
+ case "createKeywordTypeNode": {
256
+ const keyword = first === void 0 ? void 0 : KEYWORDS.get(syntaxKindMember(first, names) ?? "");
257
+ return keyword === void 0 ? void 0 : plain(keyword);
258
+ }
259
+ case "createLiteralTypeNode": {
260
+ const literal = literalText(first, names);
261
+ return literal === void 0 ? void 0 : plain(literal);
262
+ }
263
+ case "createUnionTypeNode":
264
+ return joined(first, "|", names);
265
+ case "createIntersectionTypeNode":
266
+ return joined(first, "&", names);
267
+ case "createArrayTypeNode": {
268
+ const element = first === void 0 ? void 0 : typeTextOf(first, names);
269
+ return element === void 0 ? void 0 : plain(element.operator ? `(${element.text})[]` : `${element.text}[]`);
270
+ }
271
+ default:
272
+ return void 0;
273
+ }
274
+ }
275
+ function helperCallText(call, names) {
276
+ if (!ts.isIdentifier(call.expression)) {
277
+ return void 0;
278
+ }
279
+ const helper = names.helperImports.get(call.expression.text);
280
+ if (helper === "tsUnion") {
281
+ return joined(call.arguments[0], "|", names);
282
+ }
283
+ return helper === "tsIntersection" ? joined(call.arguments[0], "&", names) : void 0;
284
+ }
285
+ function identifierText(identifier, names) {
286
+ const helper = names.helperImports.get(identifier.text);
287
+ const constant = helper === void 0 ? void 0 : HELPER_CONSTANTS.get(helper);
288
+ if (constant !== void 0) {
289
+ return plain(constant);
290
+ }
291
+ const initializer = names.constants.get(identifier.text);
292
+ return initializer === void 0 ? void 0 : typeTextOf(initializer, names);
293
+ }
294
+ function typeTextOf(expression, names) {
295
+ if (ts.isParenthesizedExpression(expression)) {
296
+ return typeTextOf(expression.expression, names);
297
+ }
298
+ if (ts.isIdentifier(expression)) {
299
+ return identifierText(expression, names);
300
+ }
301
+ if (!ts.isCallExpression(expression)) {
302
+ return void 0;
303
+ }
304
+ const method = factoryMethod(expression.expression, names);
305
+ return method === void 0 ? helperCallText(expression, names) : factoryCallText(expression, method, names);
306
+ }
307
+
308
+ function returnedExpressions(body) {
309
+ if (!ts.isBlock(body)) {
310
+ return [body];
311
+ }
312
+ const returned = [];
313
+ const visit = (node) => {
314
+ if (ts.isFunctionLike(node) || ts.isClassLike(node)) {
315
+ return;
316
+ }
317
+ if (ts.isReturnStatement(node)) {
318
+ returned.push(node.expression);
319
+ }
320
+ ts.forEachChild(node, visit);
321
+ };
322
+ ts.forEachChild(body, visit);
323
+ return returned;
324
+ }
325
+ const isUndefined = (expression) => ts.isIdentifier(expression) && expression.text === "undefined" || ts.isVoidExpression(expression);
326
+ function typeTextEdit(expression, names) {
327
+ const typeText = typeTextOf(expression, names);
328
+ if (typeText === void 0) {
329
+ return void 0;
330
+ }
331
+ const start = expression.getStart();
332
+ return [{ start, end: expression.getEnd(), text: JSON.stringify(typeText.text) }];
333
+ }
334
+ function resultObjectEdits(object, names) {
335
+ const schema = object.properties.find(
336
+ (property) => property.name !== void 0 && ts.isIdentifier(property.name) && property.name.text === "schema"
337
+ );
338
+ const isPlain = object.properties.every(ts.isPropertyAssignment);
339
+ if (schema === void 0 || !isPlain || !ts.isPropertyAssignment(schema)) {
340
+ return void 0;
341
+ }
342
+ return typeTextEdit(schema.initializer, names);
343
+ }
344
+ function returnEdits(expression, names) {
345
+ if (expression === void 0 || isUndefined(expression)) {
346
+ return [];
347
+ }
348
+ if (ts.isParenthesizedExpression(expression)) {
349
+ return returnEdits(expression.expression, names);
350
+ }
351
+ if (ts.isConditionalExpression(expression)) {
352
+ const whenTrue = returnEdits(expression.whenTrue, names);
353
+ const whenFalse = returnEdits(expression.whenFalse, names);
354
+ return whenTrue === void 0 || whenFalse === void 0 ? void 0 : [...whenTrue, ...whenFalse];
355
+ }
356
+ if (ts.isObjectLiteralExpression(expression)) {
357
+ return resultObjectEdits(expression, names);
358
+ }
359
+ return typeTextEdit(expression, names);
360
+ }
361
+
362
+ const TRANSFORM = "transform";
363
+ const LEGACY_ONLY_CALLBACKS = ["postTransform", "transformProperty"];
364
+ const IR_CALLBACKS_OPTION = "irCallbacks";
365
+ const SCRIPT_KINDS = /* @__PURE__ */ new Map([
366
+ [".ts", ts.ScriptKind.TS],
367
+ [".mts", ts.ScriptKind.TS],
368
+ [".cts", ts.ScriptKind.TS],
369
+ [".tsx", ts.ScriptKind.TSX],
370
+ [".js", ts.ScriptKind.JS],
371
+ [".mjs", ts.ScriptKind.JS],
372
+ [".cjs", ts.ScriptKind.JS],
373
+ [".jsx", ts.ScriptKind.JSX]
374
+ ]);
375
+ function scriptKindOf(path) {
376
+ return SCRIPT_KINDS.get(path.slice(path.lastIndexOf(".")));
377
+ }
378
+ function propertyNamed(options, name) {
379
+ return options.properties.find((property) => {
380
+ const key = property.name;
381
+ return key !== void 0 && (ts.isIdentifier(key) || ts.isStringLiteral(key)) && key.text === name;
382
+ });
383
+ }
384
+ function callbackFunction(property, names) {
385
+ if (ts.isMethodDeclaration(property)) {
386
+ return property;
387
+ }
388
+ if (!ts.isPropertyAssignment(property)) {
389
+ return void 0;
390
+ }
391
+ const value = property.initializer;
392
+ if (ts.isIdentifier(value)) {
393
+ return names.functions.get(value.text);
394
+ }
395
+ return ts.isArrowFunction(value) || ts.isFunctionExpression(value) ? value : void 0;
396
+ }
397
+ function isSharedFunction(property, text) {
398
+ if (!ts.isPropertyAssignment(property) || !ts.isIdentifier(property.initializer)) {
399
+ return false;
400
+ }
401
+ const name = property.initializer.text.replaceAll("$", "\\$");
402
+ const uses = text.match(new RegExp(`(?<![\\w$])${name}(?![\\w$])`, "g")) ?? [];
403
+ return uses.length > 2;
404
+ }
405
+ function returnTypeEdits(callback, text) {
406
+ const type = callback.type;
407
+ if (type === void 0) {
408
+ return [];
409
+ }
410
+ const colon = text.lastIndexOf(":", type.getStart());
411
+ return [{ start: colon, end: type.getEnd(), text: "" }];
412
+ }
413
+ function transformEdits(property, names, text) {
414
+ const callback = callbackFunction(property, names);
415
+ if (callback?.body === void 0) {
416
+ return "not-a-function";
417
+ }
418
+ if (isSharedFunction(property, text)) {
419
+ return "shared-function";
420
+ }
421
+ const edits = returnTypeEdits(callback, text);
422
+ for (const returned of returnedExpressions(callback.body)) {
423
+ const returnEditList = returnEdits(returned, names);
424
+ if (returnEditList === void 0) {
425
+ return "unknown-return";
426
+ }
427
+ edits.push(...returnEditList);
428
+ }
429
+ return edits;
430
+ }
431
+ function irCallbacksOption(text, transformStart) {
432
+ const lineStart = text.lastIndexOf("\n", transformStart - 1) + 1;
433
+ const before = text.slice(lineStart, transformStart);
434
+ const option = `${IR_CALLBACKS_OPTION}: true,`;
435
+ return /^\s*$/.test(before) ? `${option}
436
+ ${before}` : `${option} `;
437
+ }
438
+ function keepReason(options) {
439
+ const hasOther = LEGACY_ONLY_CALLBACKS.some((name) => propertyNamed(options, name) !== void 0);
440
+ return hasOther ? "other-callbacks" : void 0;
441
+ }
442
+ function legacyCallbackSteps(options, text) {
443
+ return LEGACY_ONLY_CALLBACKS.flatMap((callback) => {
444
+ const property = propertyNamed(options, callback);
445
+ return property === void 0 ? [] : [{ kind: "legacy-callback", line: lineAt(text, property.getStart()), callback }];
446
+ });
447
+ }
448
+ function migrateOptions(options, text, names) {
449
+ if (propertyNamed(options, IR_CALLBACKS_OPTION) !== void 0) {
450
+ return { edits: [], changes: [], manualSteps: [] };
451
+ }
452
+ const findings = {
453
+ edits: [],
454
+ changes: [],
455
+ manualSteps: legacyCallbackSteps(options, text)
456
+ };
457
+ const transform = propertyNamed(options, TRANSFORM);
458
+ if (transform === void 0) {
459
+ return findings;
460
+ }
461
+ const start = transform.getStart();
462
+ const line = lineAt(text, start);
463
+ const result = keepReason(options) ?? transformEdits(transform, names, text);
464
+ if (typeof result === "string") {
465
+ findings.manualSteps.push({ kind: "transform-not-rewritten", line, reason: result });
466
+ return findings;
467
+ }
468
+ findings.edits.push({ start, end: start, text: irCallbacksOption(text, start) }, ...result);
469
+ findings.changes.push({ kind: "transform-rewritten", line });
470
+ return findings;
471
+ }
472
+ function generatorOptions(node, names) {
473
+ if (!ts.isCallExpression(node) || !ts.isIdentifier(node.expression)) {
474
+ return void 0;
475
+ }
476
+ const options = node.arguments[1];
477
+ const isGenerator = names.generatorFunctions.has(node.expression.text);
478
+ return isGenerator && options !== void 0 && ts.isObjectLiteralExpression(options) ? options : void 0;
479
+ }
480
+ function applyEdits(text, edits) {
481
+ return [...edits].sort((left, right) => right.start - left.start).reduce(
482
+ (result, edit) => result.slice(0, edit.start) + edit.text + result.slice(edit.end),
483
+ text
484
+ );
485
+ }
486
+ function findCallFindings(file, text, names) {
487
+ const all = { edits: [], changes: [], manualSteps: [] };
488
+ const visit = (node) => {
489
+ const options = generatorOptions(node, names);
490
+ if (options !== void 0) {
491
+ const found = migrateOptions(options, text, names);
492
+ all.edits.push(...found.edits);
493
+ all.changes.push(...found.changes);
494
+ all.manualSteps.push(...found.manualSteps);
495
+ }
496
+ ts.forEachChild(node, visit);
497
+ };
498
+ visit(file);
499
+ return all;
500
+ }
501
+ class TypescriptCallbackRewriter {
502
+ rewrite(text, path) {
503
+ const scriptKind = scriptKindOf(path);
504
+ if (scriptKind === void 0) {
505
+ return unchanged(text);
506
+ }
507
+ const file = ts.createSourceFile(path, text, ts.ScriptTarget.Latest, true, scriptKind);
508
+ const names = collectFileNames(file);
509
+ if (names.generatorFunctions.size === 0) {
510
+ return unchanged(text);
511
+ }
512
+ const { edits, changes, manualSteps } = findCallFindings(file, text, names);
513
+ return { text: applyEdits(text, edits), changes, manualSteps };
514
+ }
515
+ }
516
+ function createTypescriptCallbackRewriter() {
517
+ return new TypescriptCallbackRewriter();
518
+ }
519
+
520
+ const PACKAGE_RENAMES = /* @__PURE__ */ new Map([
521
+ ["openapi-typescript", "openapi-typesafe"],
522
+ ["openapi-fetch", "openapi-typesafe-fetch"],
523
+ ["openapi-react-query", "openapi-typesafe-react-query"],
524
+ ["openapi-typescript-helpers", "openapi-typesafe-helpers"]
525
+ ]);
526
+ const GENERATOR_COMMAND = "openapi-typescript";
527
+ const MIGRATED_GENERATOR_COMMAND = "openapi-typesafe";
528
+ const FLAG_RENAMES = /* @__PURE__ */ new Map([
529
+ ["--immutable-types", "--immutable"],
530
+ ["-it", "--immutable"],
531
+ ["--support-array-length", "--array-length"],
532
+ ["--redoc", "--redocly"],
533
+ ["-ap", "--additional-properties"]
534
+ ]);
535
+ const DEPENDENCY_FIELDS = [
536
+ "dependencies",
537
+ "devDependencies",
538
+ "peerDependencies",
539
+ "optionalDependencies"
540
+ ];
541
+ const OVERRIDE_FIELDS = ["overrides", "resolutions", "pnpm"];
542
+
543
+ const COMMAND_RE = new RegExp(`(?<=^|[\\s"'\`;&|(])${GENERATOR_COMMAND}(?=$|[\\s"'\`;&|)])`, "g");
544
+ const VERSIONED_COMMAND_RE = new RegExp(`(?<=^|[\\s"'\`;&|(])${GENERATOR_COMMAND}@`);
545
+ const MIGRATED_COMMAND_RE = new RegExp(
546
+ `(?<=^|[\\s"'\`;&|(])${MIGRATED_GENERATOR_COMMAND}(?=$|[\\s"'\`;&|)])`
547
+ );
548
+ const FLAG_RE = new RegExp(`(?<=\\s)(${[...FLAG_RENAMES.keys()].join("|")})(?=$|[\\s=])`, "g");
549
+ function renameFlags(text, location, changes) {
550
+ if (!MIGRATED_COMMAND_RE.test(text)) {
551
+ return text;
552
+ }
553
+ return text.replace(FLAG_RE, (flag) => {
554
+ const renamed = FLAG_RENAMES.get(flag);
555
+ changes.push({ kind: "flag-renamed", location, from: flag, to: renamed });
556
+ return renamed;
557
+ });
558
+ }
559
+ function migrateCommand(text, location) {
560
+ const changes = [];
561
+ const manualSteps = [];
562
+ if (VERSIONED_COMMAND_RE.test(text)) {
563
+ manualSteps.push({ kind: "versioned-command", location });
564
+ }
565
+ const renamed = text.replace(COMMAND_RE, () => {
566
+ changes.push({ kind: "command-renamed", location });
567
+ return MIGRATED_GENERATOR_COMMAND;
568
+ });
569
+ return { text: renameFlags(renamed, location, changes), changes, manualSteps };
570
+ }
571
+ function migrateCommandLines(text, file) {
572
+ const changes = [];
573
+ const manualSteps = [];
574
+ const lines = text.split("\n").map((line, index) => {
575
+ const migrated = migrateCommand(line, `${file}:${index + 1}`);
576
+ changes.push(...migrated.changes);
577
+ manualSteps.push(...migrated.manualSteps);
578
+ return migrated.text;
579
+ });
580
+ return { text: lines.join("\n"), changes, manualSteps };
581
+ }
582
+
583
+ const PARENT_SEPARATOR = ">";
584
+ const PATH_SEPARATOR = "/";
585
+ const SCOPE_PREFIX = "@";
586
+ function overrideTarget(key) {
587
+ const child = key.split(PARENT_SEPARATOR).at(-1) ?? key;
588
+ const segments = child.split(PATH_SEPARATOR);
589
+ const isScoped = segments.length > 1 && segments.at(-2)?.startsWith(SCOPE_PREFIX) === true;
590
+ const name = isScoped ? segments.slice(-2).join(PATH_SEPARATOR) : segments.at(-1) ?? child;
591
+ const versionAt = name.indexOf(SCOPE_PREFIX, 1);
592
+ return versionAt === -1 ? name : name.slice(0, versionAt);
593
+ }
594
+ function keysOf(value) {
595
+ if (typeof value !== "object" || value === null || Array.isArray(value)) {
596
+ return [];
597
+ }
598
+ return Object.entries(value).flatMap(([key, nested]) => [key, ...keysOf(nested)]);
599
+ }
600
+ function overriddenPackages(value) {
601
+ const targets = keysOf(value).map(overrideTarget);
602
+ return [...new Set(targets.filter((target) => PACKAGE_RENAMES.has(target)))];
603
+ }
604
+
605
+ const VERSION_STYLE_RE = /^([\^~]|>=)?\d/;
606
+ const KEPT_PROTOCOLS = ["catalog:", "workspace:"];
607
+ function migrateVersionSpec(spec, version) {
608
+ if (KEPT_PROTOCOLS.some((protocol) => spec.startsWith(protocol))) {
609
+ return { kind: "kept", spec, isReported: false };
610
+ }
611
+ const style = VERSION_STYLE_RE.exec(spec);
612
+ if (style === null) {
613
+ return { kind: "kept", spec, isReported: true };
614
+ }
615
+ const prefix = style[1] === ">=" ? "^" : style[1] ?? "";
616
+ return { kind: "replaced", spec: `${prefix}${version}` };
617
+ }
618
+
619
+ const INDENT_RE = /^[ \t]+(?=")/m;
620
+ const DEFAULT_INDENT = " ";
621
+ function isObject(value) {
622
+ return typeof value === "object" && value !== null && !Array.isArray(value);
623
+ }
624
+ function formatLike(original, manifest) {
625
+ const indent = INDENT_RE.exec(original)?.[0] ?? DEFAULT_INDENT;
626
+ const ending = original.endsWith("\n") ? "\n" : "";
627
+ return `${JSON.stringify(manifest, null, indent)}${ending}`;
628
+ }
629
+ function renameDependencies(field, dependencies, version, findings) {
630
+ return Object.fromEntries(
631
+ Object.entries(dependencies).map(([name, spec]) => {
632
+ const renamed = PACKAGE_RENAMES.get(name);
633
+ if (renamed === void 0 || typeof spec !== "string") {
634
+ return [name, spec];
635
+ }
636
+ const decision = migrateVersionSpec(spec, version);
637
+ findings.changes.push({
638
+ kind: "dependency-renamed",
639
+ field,
640
+ from: name,
641
+ to: renamed,
642
+ spec: decision.spec
643
+ });
644
+ if (decision.kind === "kept" && decision.isReported) {
645
+ findings.manualSteps.push({ kind: "spec-kept", name: renamed, spec });
646
+ }
647
+ if (field === "peerDependencies") {
648
+ findings.manualSteps.push({ kind: "peer-dependency-renamed", name: renamed });
649
+ }
650
+ return [renamed, decision.spec];
651
+ })
652
+ );
653
+ }
654
+ function migrateScripts(scripts, findings) {
655
+ return Object.fromEntries(
656
+ Object.entries(scripts).map(([name, script]) => {
657
+ if (typeof script !== "string") {
658
+ return [name, script];
659
+ }
660
+ const migrated = migrateCommand(script, `scripts.${name}`);
661
+ findings.changes.push(...migrated.changes);
662
+ findings.manualSteps.push(...migrated.manualSteps);
663
+ return [name, migrated.text];
664
+ })
665
+ );
666
+ }
667
+ function reportOverrides(manifest, findings) {
668
+ for (const field of OVERRIDE_FIELDS) {
669
+ for (const name of overriddenPackages(manifest[field])) {
670
+ findings.manualSteps.push({ kind: "override-names-package", field, name });
671
+ }
672
+ }
673
+ }
674
+ function migrateFields(manifest, version, findings) {
675
+ const migrated = { ...manifest };
676
+ for (const field of DEPENDENCY_FIELDS) {
677
+ const dependencies = manifest[field];
678
+ if (isObject(dependencies)) {
679
+ migrated[field] = renameDependencies(field, dependencies, version, findings);
680
+ }
681
+ }
682
+ if (isObject(manifest.scripts)) {
683
+ migrated.scripts = migrateScripts(manifest.scripts, findings);
684
+ }
685
+ reportOverrides(manifest, findings);
686
+ return migrated;
687
+ }
688
+ function migratePackageManifest(text, version) {
689
+ let manifest;
690
+ try {
691
+ manifest = JSON.parse(text);
692
+ } catch (error) {
693
+ const reason = error instanceof Error ? error.message : String(error);
694
+ return { ...unchanged(text), manualSteps: [{ kind: "manifest-unreadable", reason }] };
695
+ }
696
+ if (!isObject(manifest)) {
697
+ return unchanged(text);
698
+ }
699
+ const findings = { changes: [], manualSteps: [] };
700
+ const migrated = migrateFields(manifest, version, findings);
701
+ const isChanged = findings.changes.length > 0;
702
+ return { text: isChanged ? formatLike(text, migrated) : text, ...findings };
703
+ }
704
+
705
+ const SPECIFIER_RE = new RegExp(
706
+ `(["'\`])(${[...PACKAGE_RENAMES.keys()].join("|")})(/[^"'\`\\s]*)?\\1`,
707
+ "g"
708
+ );
709
+ const SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([
710
+ ".ts",
711
+ ".tsx",
712
+ ".mts",
713
+ ".cts",
714
+ ".js",
715
+ ".jsx",
716
+ ".mjs",
717
+ ".cjs",
718
+ ".vue",
719
+ ".svelte",
720
+ ".astro"
721
+ ]);
722
+ function migrateModuleSpecifiers(text) {
723
+ const changes = [];
724
+ const manualSteps = [];
725
+ let migrated = "";
726
+ let copiedUpTo = 0;
727
+ for (const match of text.matchAll(SPECIFIER_RE)) {
728
+ const [whole, quote, name, subpath] = match;
729
+ const line = lineAt(text, match.index);
730
+ const to = `${PACKAGE_RENAMES.get(name)}${subpath ?? ""}`;
731
+ changes.push({ kind: "specifier-renamed", line, from: whole.slice(1, -1), to });
732
+ if (subpath !== void 0) {
733
+ manualSteps.push({ kind: "deep-import", line, specifier: to });
734
+ }
735
+ migrated += `${text.slice(copiedUpTo, match.index)}${quote}${to}${quote}`;
736
+ copiedUpTo = match.index + whole.length;
737
+ }
738
+ return { text: migrated + text.slice(copiedUpTo), changes, manualSteps };
739
+ }
740
+
741
+ const ENTRY_RE = /^(\s+)(["']?)([\w@./-]+)\2:\s*(["']?)([^"'#\s]+)\4(.*)$/;
742
+ const TOP_LEVEL_KEY_RE = /^([\w-]+):/;
743
+ const KEY_RE = /^\s+(["']?)(.+?)\1:(?:\s|$)/;
744
+ const CATALOG_SECTIONS = /* @__PURE__ */ new Set(["catalog", "catalogs"]);
745
+ const REPORTED_SECTIONS = /* @__PURE__ */ new Set(["overrides", "patchedDependencies"]);
746
+ function migrateEntry(line, version) {
747
+ const entry = ENTRY_RE.exec(line);
748
+ const renamed = entry === null ? void 0 : PACKAGE_RENAMES.get(entry[3]);
749
+ if (entry === null || renamed === void 0) {
750
+ return { line };
751
+ }
752
+ const [, indent, keyQuote, name, specQuote, spec, rest] = entry;
753
+ const decision = migrateVersionSpec(spec, version);
754
+ const key = `${keyQuote}${renamed}${keyQuote}`;
755
+ const migrated = `${indent}${key}: ${specQuote}${decision.spec}${specQuote}${rest}`;
756
+ const change = { kind: "catalog-entry-renamed", from: name, to: renamed };
757
+ if (decision.kind === "kept" && decision.isReported) {
758
+ return {
759
+ line: migrated,
760
+ change,
761
+ manualStep: { kind: "spec-kept", name: renamed, spec }
762
+ };
763
+ }
764
+ return { line: migrated, change };
765
+ }
766
+ function reportEntry(line, field) {
767
+ const key = KEY_RE.exec(line)?.[2];
768
+ return key === void 0 ? [] : overriddenPackages({ [key]: null }).map((name) => ({
769
+ kind: "override-names-package",
770
+ field,
771
+ name
772
+ }));
773
+ }
774
+ function migrateWorkspaceCatalogs(text, version) {
775
+ const changes = [];
776
+ const manualSteps = [];
777
+ let section;
778
+ const lines = text.split("\n").map((line) => {
779
+ const topLevelKey = TOP_LEVEL_KEY_RE.exec(line)?.[1];
780
+ if (topLevelKey !== void 0) {
781
+ section = topLevelKey;
782
+ return line;
783
+ }
784
+ if (section !== void 0 && REPORTED_SECTIONS.has(section)) {
785
+ manualSteps.push(...reportEntry(line, section));
786
+ return line;
787
+ }
788
+ if (section === void 0 || !CATALOG_SECTIONS.has(section)) {
789
+ return line;
790
+ }
791
+ const result = migrateEntry(line, version);
792
+ changes.push(...result.change ? [result.change] : []);
793
+ manualSteps.push(...result.manualStep ? [result.manualStep] : []);
794
+ return result.line;
795
+ });
796
+ return changes.length === 0 ? { ...unchanged(text), manualSteps } : { text: lines.join("\n"), changes, manualSteps };
797
+ }
798
+
799
+ const SCRIPT_EXTENSIONS = /* @__PURE__ */ new Set([".sh", ".bash", ".zsh", ".yml", ".yaml"]);
800
+ const SCRIPT_NAMES = /* @__PURE__ */ new Set(["Makefile", "justfile", "Dockerfile"]);
801
+ const WORKSPACE_FILE = "pnpm-workspace.yaml";
802
+ const MANIFEST_FILE = "package.json";
803
+ const LOCK_FILES = /* @__PURE__ */ new Set(["pnpm-lock.yaml", "yarn.lock", "bun.lock"]);
804
+ function baseName(path) {
805
+ return path.slice(path.lastIndexOf("/") + 1);
806
+ }
807
+ function extensionOf(path) {
808
+ const name = baseName(path);
809
+ const dot = name.lastIndexOf(".");
810
+ return dot <= 0 ? "" : name.slice(dot);
811
+ }
812
+ function chain(first, next) {
813
+ const second = next(first.text);
814
+ const changes = [...first.changes, ...second.changes];
815
+ const manualSteps = [...first.manualSteps, ...second.manualSteps];
816
+ return { text: second.text, changes, manualSteps };
817
+ }
818
+ const FILE_KINDS = [
819
+ {
820
+ matches: (path) => baseName(path) === MANIFEST_FILE,
821
+ migrate: (text, _path, context) => migratePackageManifest(text, context.version)
822
+ },
823
+ {
824
+ matches: (path) => baseName(path) === WORKSPACE_FILE,
825
+ migrate: (text, _path, context) => migrateWorkspaceCatalogs(text, context.version)
826
+ },
827
+ {
828
+ matches: (path) => SOURCE_EXTENSIONS.has(extensionOf(path)),
829
+ migrate: (text, path, context) => chain(migrateModuleSpecifiers(text), (renamed) => context.rewriter.rewrite(renamed, path))
830
+ },
831
+ {
832
+ matches: (path) => SCRIPT_EXTENSIONS.has(extensionOf(path)) || SCRIPT_NAMES.has(baseName(path)),
833
+ migrate: (text, path) => migrateCommandLines(text, path)
834
+ }
835
+ ];
836
+ function fileMigrationFor(path) {
837
+ if (LOCK_FILES.has(baseName(path))) {
838
+ return void 0;
839
+ }
840
+ return FILE_KINDS.find((kind) => kind.matches(path))?.migrate;
841
+ }
842
+
843
+ async function migrateFile(path, dependencies, input) {
844
+ const migrate = fileMigrationFor(path);
845
+ if (migrate === void 0) {
846
+ return void 0;
847
+ }
848
+ const text = await dependencies.files.read(path);
849
+ const context = { version: input.version, rewriter: dependencies.rewriter };
850
+ const migration = migrate(text, path, context);
851
+ const isChanged = migration.text !== text;
852
+ if (isChanged && input.isWrite) {
853
+ await dependencies.files.write(path, migration.text);
854
+ }
855
+ const { changes, manualSteps } = migration;
856
+ if (isChanged || manualSteps.length > 0) {
857
+ dependencies.logger.info("file_migrated", { path, isChanged, changes, manualSteps });
858
+ }
859
+ return { path, isChanged, changes, manualSteps };
860
+ }
861
+ async function migrateProject(dependencies, input) {
862
+ const paths = (await dependencies.files.listFiles()).sort();
863
+ dependencies.logger.info("migration_started", { fileCount: paths.length, ...input });
864
+ const reports = [];
865
+ for (const path of paths) {
866
+ const report = await migrateFile(path, dependencies, input);
867
+ if (report !== void 0 && (report.isChanged || report.manualSteps.length > 0)) {
868
+ reports.push(report);
869
+ }
870
+ }
871
+ dependencies.logger.info("migration_finished", { changedFiles: reports.length });
872
+ return reports;
873
+ }
874
+
875
+ function assertNever(value) {
876
+ throw new Error(`Unexpected variant: ${JSON.stringify(value)}`);
877
+ }
878
+
879
+ const IR_CALLBACKS_GUIDE = "https://github.com/openapi-typesafe/openapi-typesafe/blob/main/docs/node.md#ir-callbacks";
880
+ function changeMessage(change) {
881
+ switch (change.kind) {
882
+ case "dependency-renamed":
883
+ return `${change.field}: ${change.from} \u2192 ${change.to}@${change.spec}`;
884
+ case "catalog-entry-renamed":
885
+ return `catalog: ${change.from} \u2192 ${change.to}`;
886
+ case "command-renamed":
887
+ return `${change.location}: openapi-typescript \u2192 openapi-typesafe`;
888
+ case "flag-renamed":
889
+ return `${change.location}: ${change.from} \u2192 ${change.to}`;
890
+ case "specifier-renamed":
891
+ return `line ${change.line}: "${change.from}" \u2192 "${change.to}"`;
892
+ case "transform-rewritten":
893
+ return `line ${change.line}: transform returns type text; irCallbacks: true added`;
894
+ default:
895
+ return assertNever(change);
896
+ }
897
+ }
898
+ const KEEP_REASONS = {
899
+ "other-callbacks": "postTransform or transformProperty are set too, and they need TypeScript nodes",
900
+ "not-a-function": "it is not an inline function or a function of this file",
901
+ "shared-function": "the function it names is used elsewhere too",
902
+ "unknown-return": "a return value is not a plain ts.factory type"
903
+ };
904
+ const PEER_NOTE = "users of this package must switch too (a breaking change for them)";
905
+ const PINNED_NOTE = "change it to openapi-typesafe@<version>";
906
+ const DEEP_IMPORT_NOTE = "imports a file inside the package; check that it exists";
907
+ const KEPT_NOTE = `it works, with a deprecation warning. See ${IR_CALLBACKS_GUIDE}`;
908
+ const LEGACY_CALLBACK_NOTE = `receives TypeScript nodes (deprecated). See ${IR_CALLBACKS_GUIDE}`;
909
+ function manualStepMessage(step) {
910
+ switch (step.kind) {
911
+ case "manifest-unreadable":
912
+ return `package.json is not valid JSON (${step.reason}); migrate it by hand`;
913
+ case "peer-dependency-renamed":
914
+ return `${step.name} is a peer dependency: ${PEER_NOTE}`;
915
+ case "spec-kept":
916
+ return `${step.name} kept the spec "${step.spec}": point it at an openapi-typesafe version`;
917
+ case "override-names-package":
918
+ return `"${step.field}" names ${step.name}: update or remove that override`;
919
+ case "versioned-command":
920
+ return `${step.location} runs a pinned openapi-typescript@<version>: ${PINNED_NOTE}`;
921
+ case "deep-import":
922
+ return `line ${step.line}: "${step.specifier}" ${DEEP_IMPORT_NOTE}`;
923
+ case "transform-not-rewritten":
924
+ return `line ${step.line}: transform kept (${KEEP_REASONS[step.reason]}); ${KEPT_NOTE}`;
925
+ case "legacy-callback":
926
+ return `line ${step.line}: ${step.callback} ${LEGACY_CALLBACK_NOTE}`;
927
+ default:
928
+ return assertNever(step);
929
+ }
930
+ }
931
+ const NEXT_STEPS = [
932
+ "Install: run your package manager's install, so the lockfile has the new packages.",
933
+ "Regenerate your types and commit them once: the file header names openapi-typesafe now, so `--check` fails until you do.",
934
+ "Run your type check and tests."
935
+ ];
936
+ const DRY_RUN_NOTE = "Dry run: nothing was written. Run again with --write to apply.";
937
+ const WRITTEN_NOTE = "Files were written.";
938
+ const NOTHING_FOUND = "Nothing to migrate: no openapi-typescript, openapi-fetch, openapi-react-query or openapi-typescript-helpers found.";
939
+
940
+ function changesSection(reports) {
941
+ const changed = reports.filter((report) => report.changes.length > 0);
942
+ if (changed.length === 0) {
943
+ return [];
944
+ }
945
+ return [
946
+ "Changes:",
947
+ ...changed.flatMap((report) => [
948
+ ` ${report.path}`,
949
+ ...report.changes.map((change) => ` ${changeMessage(change)}`)
950
+ ]),
951
+ ""
952
+ ];
953
+ }
954
+ function manualStepsSection(reports) {
955
+ const steps = reports.flatMap(
956
+ (report) => report.manualSteps.map((step) => ` ${report.path}: ${manualStepMessage(step)}`)
957
+ );
958
+ return steps.length === 0 ? [] : ["Manual steps:", ...steps, ""];
959
+ }
960
+ function renderReport(reports, isWrite) {
961
+ if (reports.length === 0) {
962
+ return `${NOTHING_FOUND}
963
+ `;
964
+ }
965
+ const lines = [
966
+ ...changesSection(reports),
967
+ ...manualStepsSection(reports),
968
+ "Next steps:",
969
+ ...NEXT_STEPS.map((step, index) => ` ${index + 1}. ${step}`),
970
+ "",
971
+ isWrite ? WRITTEN_NOTE : DRY_RUN_NOTE
972
+ ];
973
+ return `${lines.join("\n")}
974
+ `;
975
+ }
976
+
977
+ const OPTIONS = {
978
+ write: { type: "boolean" },
979
+ root: { type: "string" },
980
+ log: { type: "string" },
981
+ help: { type: "boolean", short: "h" },
982
+ version: { type: "boolean", short: "v" }
983
+ };
984
+ function parseCliArguments(argv) {
985
+ const { values } = parseArgs({ args: [...argv], options: OPTIONS, strict: true });
986
+ if (values.help === true) {
987
+ return { kind: "help" };
988
+ }
989
+ if (values.version === true) {
990
+ return { kind: "version" };
991
+ }
992
+ return {
993
+ kind: "migrate",
994
+ isWrite: values.write === true,
995
+ root: values.root,
996
+ logPath: values.log
997
+ };
998
+ }
999
+
1000
+ const HELP_TEXT = `Usage
1001
+ openapi-typesafe-migrate [options]
1002
+
1003
+ Move a project from openapi-typescript, openapi-fetch, openapi-react-query and
1004
+ openapi-typescript-helpers to the openapi-typesafe packages. Without --write it only reports.
1005
+
1006
+ Options
1007
+ --write Write the changes (default: dry run)
1008
+ --root <dir> The project directory (default: the current directory)
1009
+ --log <file> The JSON Lines log file (default: a new file in the temporary directory)
1010
+ --help, -h Show this help
1011
+ --version, -v Show the version
1012
+
1013
+ Exit codes
1014
+ 0 Done
1015
+ 1 The migration failed (the message and the log say why)
1016
+ 2 Unknown option or argument
1017
+ `;
1018
+ const usageError = (message) => `${message}
1019
+ Run openapi-typesafe-migrate --help for the options.
1020
+ `;
1021
+ const logNote = (path) => `Log: ${path}
1022
+ `;
1023
+
1024
+ const EXIT_CODES = { success: 0, failure: 1, usage: 2 };
1025
+ function parseRequest(argv, dependencies) {
1026
+ try {
1027
+ return parseCliArguments(argv);
1028
+ } catch (error) {
1029
+ if (error instanceof TypeError) {
1030
+ dependencies.writeStderr(usageError(error.message));
1031
+ return void 0;
1032
+ }
1033
+ throw error;
1034
+ }
1035
+ }
1036
+ async function runMigration(request, dependencies) {
1037
+ const root = dependencies.resolvePath(dependencies.cwd, request.root ?? ".");
1038
+ const { logger, path } = dependencies.createLogger(request.logPath);
1039
+ try {
1040
+ const files = dependencies.createFiles(root);
1041
+ const input = { version: dependencies.version, isWrite: request.isWrite };
1042
+ const reports = await migrateProject({ files, rewriter: dependencies.rewriter, logger }, input);
1043
+ dependencies.writeStdout(renderReport(reports, request.isWrite));
1044
+ return EXIT_CODES.success;
1045
+ } catch (error) {
1046
+ const message = error instanceof Error ? error.message : String(error);
1047
+ logger.warn("migration_failed", { root, message });
1048
+ dependencies.writeStderr(`${message}
1049
+ `);
1050
+ return EXIT_CODES.failure;
1051
+ } finally {
1052
+ dependencies.writeStdout(logNote(path));
1053
+ }
1054
+ }
1055
+ async function runCli(argv, dependencies) {
1056
+ const request = parseRequest(argv, dependencies);
1057
+ if (request === void 0) {
1058
+ return EXIT_CODES.usage;
1059
+ }
1060
+ if (request.kind === "help") {
1061
+ dependencies.writeStdout(HELP_TEXT);
1062
+ return EXIT_CODES.success;
1063
+ }
1064
+ if (request.kind === "version") {
1065
+ dependencies.writeStdout(`${dependencies.version}
1066
+ `);
1067
+ return EXIT_CODES.success;
1068
+ }
1069
+ return runMigration(request, dependencies);
1070
+ }
1071
+
1072
+ const PACKAGE_JSON = new URL("../../package.json", import.meta.url);
1073
+ const LOG_DIRECTORY = "openapi-typesafe-migrate";
1074
+ function readVersion() {
1075
+ const packageJson = JSON.parse(readFileSync(PACKAGE_JSON, "utf8"));
1076
+ return packageJson.version;
1077
+ }
1078
+ const now = () => /* @__PURE__ */ new Date();
1079
+ function createLogger(path) {
1080
+ const logPath = path === void 0 ? join(tmpdir(), LOG_DIRECTORY, `${now().toISOString().replaceAll(":", "-")}.jsonl`) : resolve(path);
1081
+ return { logger: createJsonLinesLogger({ path: logPath, now }), path: logPath };
1082
+ }
1083
+ const dependencies = {
1084
+ version: readVersion(),
1085
+ cwd: process.cwd(),
1086
+ writeStdout: (text) => process.stdout.write(text),
1087
+ writeStderr: (text) => process.stderr.write(text),
1088
+ createFiles: createNodeProjectFiles,
1089
+ createLogger,
1090
+ rewriter: createTypescriptCallbackRewriter(),
1091
+ resolvePath: resolve
1092
+ };
1093
+ runCli(process.argv.slice(2), dependencies).then((exitCode) => {
1094
+ process.exitCode = exitCode;
1095
+ });
1096
+ //# sourceMappingURL=main.mjs.map