@sdk-it/cli 0.32.0 → 0.33.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.
package/dist/index.js CHANGED
@@ -1,13 +1,460 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  // packages/cli/src/lib/cli.ts
4
- import { Command as Command6, program } from "commander";
5
- import { readFile as readFile2 } from "node:fs/promises";
4
+ import { Command as Command7, program } from "commander";
5
+ import { readJson as readJson2 } from "@sdk-it/core/file-system.js";
6
6
 
7
- // packages/cli/src/lib/generators/apiref.ts
7
+ // packages/cli/src/lib/commands/init.ts
8
+ import { checkbox, confirm, input, select } from "@inquirer/prompts";
8
9
  import { Command } from "commander";
10
+ import { writeFile } from "node:fs/promises";
11
+ import { resolve as resolve3 } from "node:path";
12
+
13
+ // packages/cli/src/lib/commands/find-framework.ts
14
+ import { resolve } from "node:path";
15
+ import { exist } from "@sdk-it/core/file-system.js";
16
+ var monorepoIndicators = {
17
+ lerna: () => exist(resolve(process.cwd(), "lerna.json")),
18
+ nx: () => exist(resolve(process.cwd(), "nx.json")),
19
+ pnpm: () => exist(resolve(process.cwd(), "pnpm-workspace.yaml")),
20
+ rush: () => exist(resolve(process.cwd(), "rush.json"))
21
+ };
22
+ async function detectMonorepo() {
23
+ for (const [indicator, check] of Object.entries(monorepoIndicators)) {
24
+ if (await check()) {
25
+ return indicator;
26
+ }
27
+ }
28
+ return void 0;
29
+ }
30
+
31
+ // packages/cli/src/lib/commands/find-spec-file.ts
32
+ import { resolve as resolve2 } from "node:path";
33
+ import { exist as exist2 } from "@sdk-it/core/file-system.js";
34
+ async function findSpecFile() {
35
+ const commonNames = [
36
+ "openapi.json",
37
+ "openapi.yaml",
38
+ "openapi.yml",
39
+ "swagger.json",
40
+ "swagger.yaml",
41
+ "swagger.yml",
42
+ "api.json",
43
+ "api.yaml",
44
+ "api.yml",
45
+ "spec.json",
46
+ "spec.yaml",
47
+ "spec.yml",
48
+ "schema.json",
49
+ "schema.yaml",
50
+ "schema.yml"
51
+ ];
52
+ for (const name of commonNames) {
53
+ if (await exist2(resolve2(process.cwd(), name))) {
54
+ return `./${name}`;
55
+ }
56
+ }
57
+ return void 0;
58
+ }
59
+
60
+ // packages/cli/src/lib/commands/guess-default-package-name.ts
61
+ import { join } from "node:path";
62
+ import { readJson } from "@sdk-it/core/file-system.js";
63
+ async function guessTypescriptPackageName(consideringMultipleGenerator) {
64
+ try {
65
+ const packageJson = await readJson(
66
+ join(process.cwd(), "package.json")
67
+ );
68
+ if (packageJson.name) {
69
+ const match = packageJson.name.match(/^@([^/]+)/);
70
+ if (match) {
71
+ const scope = match[1];
72
+ return consideringMultipleGenerator ? `@${scope}/ts-sdk` : `@${scope}/sdk`;
73
+ }
74
+ }
75
+ } catch {
76
+ }
77
+ return consideringMultipleGenerator ? "ts-sdk" : "sdk";
78
+ }
79
+
80
+ // packages/cli/src/lib/commands/init.ts
81
+ var specInput = async (defaultValue) => {
82
+ return input({
83
+ message: "OpenAPI or Postman specification file path:",
84
+ default: defaultValue || "./openapi.json"
85
+ });
86
+ };
87
+ var generatorConfigs = {
88
+ typescript: {
89
+ name: async (isMultipleGenerators = false) => {
90
+ const defaultName = await guessTypescriptPackageName(isMultipleGenerators);
91
+ return input({
92
+ message: "SDK package name:",
93
+ default: defaultName
94
+ });
95
+ },
96
+ spec: specInput,
97
+ output: async () => {
98
+ let defaultValue = "./ts-sdk";
99
+ const monorepo = await detectMonorepo();
100
+ if (monorepo === "nx") {
101
+ defaultValue = "./packages/ts-sdk";
102
+ }
103
+ return await input({
104
+ message: "Output directory:",
105
+ default: defaultValue
106
+ });
107
+ },
108
+ mode: async () => {
109
+ const options = {
110
+ mode: "full",
111
+ install: false
112
+ };
113
+ options.mode = await select({
114
+ message: "Generation mode:",
115
+ choices: [
116
+ {
117
+ name: "Full (generates package.json and tsconfig.json)",
118
+ value: "full"
119
+ },
120
+ {
121
+ name: "Minimal (generates only the client TypeScript files)",
122
+ value: "minimal"
123
+ }
124
+ ],
125
+ default: options.mode
126
+ });
127
+ if (options.mode === "full") {
128
+ const installDeps = await confirm({
129
+ message: "Install dependencies automatically?",
130
+ default: true
131
+ });
132
+ options.install = installDeps;
133
+ }
134
+ return options;
135
+ },
136
+ pagination: async () => {
137
+ let pagination = {
138
+ guess: false
139
+ };
140
+ const result = await confirm({
141
+ message: "Enable pagination support?",
142
+ default: false
143
+ });
144
+ if (result) {
145
+ pagination.guess = await confirm({
146
+ message: "Would you like to guess pagination parameters?",
147
+ default: false
148
+ });
149
+ } else {
150
+ pagination = false;
151
+ }
152
+ return pagination;
153
+ },
154
+ outputType: () => select({
155
+ message: "Endpoint output type:",
156
+ choices: [
157
+ { name: "Default", value: "default" },
158
+ { name: "Status", value: "status" }
159
+ ],
160
+ default: "default"
161
+ }),
162
+ readme: () => confirm({
163
+ message: "Generate README file?",
164
+ default: true
165
+ }),
166
+ defaultFormatter: () => confirm({
167
+ message: "Use default formatter (prettier)?",
168
+ default: true
169
+ }),
170
+ framework: () => input({
171
+ message: "Framework integrating with the SDK (optional):"
172
+ }),
173
+ formatter: () => input({
174
+ message: 'Custom formatter command (optional, e.g., "prettier $SDK_IT_OUTPUT --write"):'
175
+ })
176
+ },
177
+ python: {
178
+ name: () => input({
179
+ message: "SDK package name:",
180
+ default: "my-python-sdk"
181
+ }),
182
+ spec: specInput,
183
+ output: () => input({
184
+ message: "Output directory:",
185
+ default: "./python-sdk"
186
+ }),
187
+ mode: async () => {
188
+ const isMonorepo = await detectMonorepo();
189
+ return select({
190
+ message: "Generation mode:",
191
+ choices: [
192
+ {
193
+ name: "Full (generates complete project structure)",
194
+ value: "full"
195
+ },
196
+ {
197
+ name: "Minimal (generates only the client files)",
198
+ value: "minimal"
199
+ }
200
+ ],
201
+ default: isMonorepo ? "full" : "full"
202
+ // Default to full, especially for monorepos
203
+ }).then((value) => value);
204
+ },
205
+ formatter: () => input({
206
+ message: 'Custom formatter command (optional, e.g., "black $SDK_IT_OUTPUT" or "ruff format $SDK_IT_OUTPUT"):'
207
+ })
208
+ },
209
+ dart: {
210
+ name: () => input({
211
+ message: "SDK package name:",
212
+ default: "my-dart-sdk"
213
+ }),
214
+ spec: specInput,
215
+ output: () => input({
216
+ message: "Output directory:",
217
+ default: "./dart-sdk"
218
+ }),
219
+ mode: async () => {
220
+ const isMonorepo = await detectMonorepo();
221
+ return select({
222
+ message: "Generation mode:",
223
+ choices: [
224
+ {
225
+ name: "Full (generates complete project structure)",
226
+ value: "full"
227
+ },
228
+ {
229
+ name: "Minimal (generates only the client files)",
230
+ value: "minimal"
231
+ }
232
+ ],
233
+ default: isMonorepo ? "full" : "full"
234
+ // Default to full, especially for monorepos
235
+ }).then((value) => value);
236
+ },
237
+ pagination: async () => {
238
+ let pagination = {
239
+ guess: false
240
+ };
241
+ const result = await confirm({
242
+ message: "Enable pagination support?",
243
+ default: false
244
+ });
245
+ if (result) {
246
+ pagination.guess = await confirm({
247
+ message: "Would you like to guess pagination parameters?",
248
+ default: false
249
+ });
250
+ } else {
251
+ pagination = false;
252
+ }
253
+ return pagination;
254
+ }
255
+ }
256
+ };
257
+ var init = new Command("init").description("Initialize SDK-IT configuration interactively").action(async () => {
258
+ console.log("Welcome to SDK-IT! Let's set up your configuration.\n");
259
+ const possibleSpecFile = await findSpecFile();
260
+ const monorepo = await detectMonorepo();
261
+ if (possibleSpecFile) {
262
+ console.log(`\u{1F50D} Auto-detected API specification: ${possibleSpecFile}`);
263
+ }
264
+ if (monorepo) {
265
+ console.log(`\u{1F4E6} Detected monorepo setup`);
266
+ }
267
+ if (possibleSpecFile || monorepo) {
268
+ console.log("");
269
+ }
270
+ const config = {
271
+ generators: {}
272
+ };
273
+ const generators = await checkbox({
274
+ message: "Which SDK generators would you like to configure?",
275
+ loop: false,
276
+ instructions: false,
277
+ required: true,
278
+ choices: [
279
+ { name: "TypeScript", value: "typescript" },
280
+ { name: "Python", value: "python" },
281
+ { name: "Dart", value: "dart" }
282
+ ]
283
+ });
284
+ for (const generator of generators) {
285
+ console.log(`
286
+ Configuring ${generator} generator:`);
287
+ if (generator === "typescript") {
288
+ const tsConfig = generatorConfigs.typescript;
289
+ const isMultipleGenerators = generators.length > 1;
290
+ const generatorConfig = {
291
+ spec: await tsConfig.spec(possibleSpecFile),
292
+ output: await tsConfig.output(),
293
+ name: await tsConfig.name(isMultipleGenerators),
294
+ defaultFormatter: await tsConfig.defaultFormatter(),
295
+ outputType: await tsConfig.outputType(),
296
+ readme: await tsConfig.readme(),
297
+ pagination: await tsConfig.pagination(),
298
+ ...await tsConfig.mode()
299
+ };
300
+ const customFramework = await tsConfig.framework();
301
+ if (customFramework) {
302
+ generatorConfig.framework = customFramework;
303
+ }
304
+ const customFormatter = await tsConfig.formatter();
305
+ if (customFormatter) {
306
+ generatorConfig.formatter = customFormatter;
307
+ }
308
+ config.generators.typescript = generatorConfig;
309
+ } else if (generator === "python") {
310
+ config.generators.python = {
311
+ spec: await generatorConfigs.python.spec(),
312
+ output: await generatorConfigs.python.output(),
313
+ mode: await generatorConfigs.python.mode(),
314
+ name: await generatorConfigs.python.name()
315
+ };
316
+ } else if (generator === "dart") {
317
+ config.generators.dart = {
318
+ spec: await generatorConfigs.dart.spec(),
319
+ output: await generatorConfigs.dart.output(),
320
+ mode: await generatorConfigs.dart.mode(),
321
+ name: await generatorConfigs.dart.name(),
322
+ pagination: await generatorConfigs.dart.pagination()
323
+ };
324
+ }
325
+ }
326
+ const generateReadme = await confirm({
327
+ message: "\nGenerate README documentation?",
328
+ default: true
329
+ });
330
+ if (generateReadme) {
331
+ const readmeSpec = await input({
332
+ message: "OpenAPI specification for README:",
333
+ default: config.generators.typescript?.spec || possibleSpecFile || "./openapi.yaml"
334
+ });
335
+ const readmeOutput = await input({
336
+ message: "README output file:",
337
+ default: "./README.md"
338
+ });
339
+ config.readme = {
340
+ spec: readmeSpec,
341
+ output: readmeOutput
342
+ };
343
+ }
344
+ const generateApiRef = await confirm({
345
+ message: "\nGenerate API reference documentation?",
346
+ default: false
347
+ });
348
+ if (generateApiRef) {
349
+ const autoDetected = await findSpecFile();
350
+ const apirefSpec = await input({
351
+ message: "OpenAPI specification for API reference:",
352
+ default: config.generators.typescript?.spec || autoDetected || "./openapi.yaml"
353
+ });
354
+ const apirefOutput = await input({
355
+ message: "API reference output directory:",
356
+ default: "./docs"
357
+ });
358
+ config.apiref = {
359
+ spec: apirefSpec,
360
+ output: apirefOutput
361
+ };
362
+ }
363
+ const configPath = resolve3(process.cwd(), "sdk-it.json");
364
+ await writeFile(configPath, JSON.stringify(config, null, 2));
365
+ console.log(`
366
+ \u2705 Configuration saved to ${configPath}`);
367
+ console.log("\n\u{1F680} Next Steps:\n");
368
+ console.log("1. Generate your SDK(s):");
369
+ console.log(" npx @sdk-it/cli");
370
+ if (config.generators.typescript) {
371
+ console.log("2. Integrate TypeScript SDK:");
372
+ const importName = config.generators.typescript.name.replace(
373
+ /[^a-zA-Z0-9]/g,
374
+ ""
375
+ );
376
+ const outputDir = config.generators.typescript.output.replace("./", "");
377
+ console.log(` import { ${importName} } from './${outputDir}';`);
378
+ console.log(` const client = new ${importName}();`);
379
+ console.log(` const result = await client.request('GET /users');
380
+ `);
381
+ }
382
+ if (config.generators.python) {
383
+ console.log("2. Integrate Python SDK:");
384
+ const outputDir = config.generators.python.output.replace("./", "");
385
+ console.log(` # Add to your Python path or install locally`);
386
+ console.log(` from ${outputDir} import Client`);
387
+ console.log(` client = Client()`);
388
+ console.log(` result = client.users.list_users()
389
+ `);
390
+ }
391
+ if (config.generators.dart) {
392
+ console.log("2. Integrate Dart SDK:");
393
+ const outputDir = config.generators.dart.output.replace("./", "");
394
+ console.log(` # Add dependency to pubspec.yaml`);
395
+ console.log(` import 'package:${outputDir}/client.dart';`);
396
+ console.log(` final client = Client();`);
397
+ console.log(` final result = await client.users.listUsers();
398
+ `);
399
+ }
400
+ console.log("3. Check generated documentation:");
401
+ const outputs = [];
402
+ if (config.generators.typescript)
403
+ outputs.push(config.generators.typescript.output);
404
+ if (config.generators.python) outputs.push(config.generators.python.output);
405
+ if (config.generators.dart) outputs.push(config.generators.dart.output);
406
+ outputs.forEach((output) => {
407
+ if (output) {
408
+ console.log(
409
+ ` \u{1F4D6} ${output}/README.md - Usage examples and API reference`
410
+ );
411
+ }
412
+ });
413
+ if (config.readme) {
414
+ console.log(
415
+ ` \u{1F4D6} ${config.readme.output} - Generated API documentation`
416
+ );
417
+ }
418
+ if (config.apiref) {
419
+ console.log(` \u{1F310} ${config.apiref.output} - Interactive API reference`);
420
+ }
421
+ console.log("\n4. Useful commands:");
422
+ console.log(
423
+ " npx @sdk-it/cli # Regenerate SDKs after API changes"
424
+ );
425
+ console.log(
426
+ " npx @sdk-it/cli typescript --help # See TypeScript-specific options"
427
+ );
428
+ console.log(
429
+ " npx @sdk-it/cli python --help # See Python-specific options"
430
+ );
431
+ console.log(
432
+ " npx @sdk-it/cli dart --help # See Dart-specific options"
433
+ );
434
+ console.log("\n\u{1F4A1} Tips:");
435
+ console.log(
436
+ " \u2022 Update your API spec and re-run `npx @sdk-it/cli generate` to sync changes"
437
+ );
438
+ console.log(
439
+ " \u2022 Generated SDKs include TypeScript definitions for excellent IDE support"
440
+ );
441
+ console.log(
442
+ " \u2022 Check the README files for authentication and configuration options"
443
+ );
444
+ console.log("\n\u{1F4DA} Need help?");
445
+ console.log(" \u2022 Documentation: https://sdk-it.dev/docs");
446
+ console.log(
447
+ " \u2022 Examples: https://github.com/JanuaryLabs/sdk-it/tree/main/docs/examples"
448
+ );
449
+ console.log(" \u2022 Issues: https://github.com/JanuaryLabs/sdk-it/issues");
450
+ console.log("\nHappy coding! \u{1F389}\n");
451
+ });
452
+ var init_default = init;
453
+
454
+ // packages/cli/src/lib/generators/apiref.ts
455
+ import { Command as Command2 } from "commander";
9
456
  import { execa } from "execa";
10
- import { dirname, join } from "node:path";
457
+ import { dirname, join as join2 } from "node:path";
11
458
 
12
459
  // packages/cli/src/lib/options.ts
13
460
  import { Option } from "commander";
@@ -61,11 +508,11 @@ function parsePagination(config) {
61
508
  }
62
509
 
63
510
  // packages/cli/src/lib/generators/apiref.ts
64
- var apiref_default = new Command("apiref").description("Generate APIREF").addOption(specOption.makeOptionMandatory(true)).addOption(outputOption.makeOptionMandatory(true)).action(async (options) => {
511
+ var apiref_default = new Command2("apiref").description("Generate APIREF").addOption(specOption.makeOptionMandatory(true)).addOption(outputOption.makeOptionMandatory(true)).action(async (options) => {
65
512
  await runApiRef(options.spec, options.output);
66
513
  });
67
514
  function runApiRef(spec, output) {
68
- const packageDir = join(dirname(import.meta.url), "..", "..", "apiref");
515
+ const packageDir = join2(dirname(import.meta.url), "..", "..", "apiref");
69
516
  return execa("nx", ["run", "apiref:build", "--verbose"], {
70
517
  stdio: "inherit",
71
518
  extendEnv: true,
@@ -78,11 +525,11 @@ function runApiRef(spec, output) {
78
525
  }
79
526
 
80
527
  // packages/cli/src/lib/generators/dart.ts
81
- import { Command as Command2 } from "commander";
528
+ import { Command as Command3 } from "commander";
82
529
  import { execFile, execSync } from "node:child_process";
83
530
  import { generate } from "@sdk-it/dart";
84
531
  import { loadSpec } from "@sdk-it/spec";
85
- var dart_default = new Command2("dart").description("Generate Dart SDK").addOption(specOption.makeOptionMandatory(true)).addOption(outputOption.makeOptionMandatory(true)).option("-n, --name <name>", "Name of the generated client", "Client").option(
532
+ var dart_default = new Command3("dart").description("Generate Dart SDK").addOption(specOption.makeOptionMandatory(true)).addOption(outputOption.makeOptionMandatory(true)).option("-n, --name <name>", "Name of the generated client", "Client").option(
86
533
  "--pagination <pagination>",
87
534
  'Configure pagination (e.g., "false", "true", "guess=false")',
88
535
  "true"
@@ -94,7 +541,7 @@ async function runDart(options) {
94
541
  output: options.output,
95
542
  mode: options.mode || "full",
96
543
  name: options.name,
97
- pagination: parsePagination(parseDotConfig(options.pagination ?? "true")),
544
+ pagination: typeof options.pagination === "string" ? parsePagination(parseDotConfig(options.pagination ?? "true")) : options.pagination,
98
545
  formatCode: ({ output }) => {
99
546
  if (options.formatter) {
100
547
  const [command, ...args] = options.formatter.split(" ");
@@ -112,12 +559,12 @@ async function runDart(options) {
112
559
  }
113
560
 
114
561
  // packages/cli/src/lib/generators/python.ts
115
- import { Command as Command3 } from "commander";
562
+ import { Command as Command4 } from "commander";
116
563
  import { execFile as execFile2, execSync as execSync2 } from "node:child_process";
117
564
 
118
565
  // packages/python/dist/index.js
119
566
  import { readdir } from "node:fs/promises";
120
- import { join as join2 } from "node:path";
567
+ import { join as join3 } from "node:path";
121
568
  import { snakecase as snakecase2 } from "stringcase";
122
569
  import { isEmpty, isRef as isRef2, pascalcase as pascalcase2 } from "@sdk-it/core";
123
570
  import {
@@ -1730,7 +2177,7 @@ async function generate2(openapi, settings) {
1730
2177
  const files = await readdir(folder, { withFileTypes: true });
1731
2178
  return files.map((file) => ({
1732
2179
  fileName: file.name,
1733
- filePath: join2(file.parentPath, file.name),
2180
+ filePath: join3(file.parentPath, file.name),
1734
2181
  isFolder: file.isDirectory()
1735
2182
  }));
1736
2183
  };
@@ -1741,7 +2188,7 @@ async function generate2(openapi, settings) {
1741
2188
  className: `${pascalcase2(entry.tag)}Api`,
1742
2189
  methods: []
1743
2190
  };
1744
- const input = toInputs(spec, { entry, operation });
2191
+ const input2 = toInputs(spec, { entry, operation });
1745
2192
  const response = toOutput(spec, operation);
1746
2193
  const methodName = snakecase2(
1747
2194
  operation.operationId || `${entry.method}_${entry.path.replace(/[^a-zA-Z0-9]/g, "_")}`
@@ -1749,16 +2196,16 @@ async function generate2(openapi, settings) {
1749
2196
  const returnType = response ? response.returnType : "httpx.Response";
1750
2197
  const docstring = operation.summary || operation.description ? ` """${operation.summary || operation.description}"""` : "";
1751
2198
  group.methods.push(`
1752
- async def ${methodName}(self${input.haveInput ? `, input_data: ${input.inputName}` : ""}) -> ${returnType}:
2199
+ async def ${methodName}(self${input2.haveInput ? `, input_data: ${input2.inputName}` : ""}) -> ${returnType}:
1753
2200
  ${docstring}
1754
2201
  config = RequestConfig(
1755
2202
  method='${entry.method.toUpperCase()}',
1756
2203
  url='${entry.path}',
1757
2204
  )
1758
2205
 
1759
- ${input.haveInput ? "config = input_data.to_request_config(config)" : ""}
2206
+ ${input2.haveInput ? "config = input_data.to_request_config(config)" : ""}
1760
2207
 
1761
- response = await self.dispatcher.${input.contentType}(config)
2208
+ response = await self.dispatcher.${input2.contentType}(config)
1762
2209
  ${response ? `return await self.receiver.json(response, ${response.successModel || "None"}, ${response.errorModel || "None"})` : "return response"}
1763
2210
  `);
1764
2211
  });
@@ -1924,19 +2371,19 @@ python-dateutil>=2.8.0
1924
2371
  }
1925
2372
  await settings.writer(output, {
1926
2373
  "models/__init__.py": await generateModuleInit(
1927
- join2(output, "models"),
2374
+ join3(output, "models"),
1928
2375
  settings.readFolder
1929
2376
  ),
1930
2377
  "inputs/__init__.py": await generateModuleInit(
1931
- join2(output, "inputs"),
2378
+ join3(output, "inputs"),
1932
2379
  settings.readFolder
1933
2380
  ),
1934
2381
  "outputs/__init__.py": await generateModuleInit(
1935
- join2(output, "outputs"),
2382
+ join3(output, "outputs"),
1936
2383
  settings.readFolder
1937
2384
  ),
1938
2385
  "api/__init__.py": await generateModuleInit(
1939
- join2(output, "api"),
2386
+ join3(output, "api"),
1940
2387
  settings.readFolder
1941
2388
  ),
1942
2389
  "http/__init__.py": `"""HTTP utilities."""
@@ -2077,7 +2524,7 @@ ${content}`;
2077
2524
 
2078
2525
  // packages/cli/src/lib/generators/python.ts
2079
2526
  import { loadSpec as loadSpec2, toIR as toIR2 } from "@sdk-it/spec";
2080
- var python_default = new Command3("python").description("Generate Python SDK").addOption(specOption.makeOptionMandatory(true)).addOption(outputOption.makeOptionMandatory(true)).option("-n, --name <n>", "Name of the generated client", "Client").option("-v, --verbose", "Verbose output", false).option("--formatter <formatter>", "Formatter to use for the generated code").action(async (options) => {
2527
+ var python_default = new Command4("python").description("Generate Python SDK").addOption(specOption.makeOptionMandatory(true)).addOption(outputOption.makeOptionMandatory(true)).option("-n, --name <n>", "Name of the generated client", "Client").option("-v, --verbose", "Verbose output", false).option("--formatter <formatter>", "Formatter to use for the generated code").action(async (options) => {
2081
2528
  await runPython(options);
2082
2529
  });
2083
2530
  async function runPython(options) {
@@ -2118,31 +2565,31 @@ async function runPython(options) {
2118
2565
  }
2119
2566
 
2120
2567
  // packages/cli/src/lib/generators/readme.ts
2121
- import { Command as Command4 } from "commander";
2122
- import { writeFile } from "node:fs/promises";
2568
+ import { Command as Command5 } from "commander";
2569
+ import { writeFile as writeFile2 } from "node:fs/promises";
2123
2570
  import { toReadme } from "@sdk-it/readme";
2124
2571
  import { loadSpec as loadSpec3, toIR as toIR3 } from "@sdk-it/spec";
2125
- var readme_default = new Command4("readme").description("Generate README").addOption(specOption.makeOptionMandatory(true)).addOption(outputOption.makeOptionMandatory(true)).action(async (options) => {
2572
+ var readme_default = new Command5("readme").description("Generate README").addOption(specOption.makeOptionMandatory(true)).addOption(outputOption.makeOptionMandatory(true)).action(async (options) => {
2126
2573
  await runReadme(options.spec, options.output);
2127
2574
  });
2128
2575
  async function runReadme(specFile, output) {
2129
2576
  const spec = toIR3({ spec: await loadSpec3(specFile) });
2130
2577
  const content = toReadme(spec);
2131
- await writeFile(output, content, "utf-8");
2578
+ await writeFile2(output, content, "utf-8");
2132
2579
  }
2133
2580
 
2134
2581
  // packages/cli/src/lib/generators/typescript.ts
2135
- import { Command as Command5, Option as Option2 } from "commander";
2582
+ import { Command as Command6, Option as Option2 } from "commander";
2136
2583
  import { publish } from "libnpmpublish";
2137
2584
  import { execFile as execFile3, execSync as execSync3, spawnSync } from "node:child_process";
2138
2585
  import { readFile } from "node:fs/promises";
2139
2586
  import { tmpdir } from "node:os";
2140
- import { join as join3 } from "node:path";
2587
+ import { join as join4 } from "node:path";
2141
2588
  import getAuthToken from "registry-auth-token";
2142
2589
  import { writeFiles as writeFiles2 } from "@sdk-it/core/file-system.js";
2143
2590
  import { loadSpec as loadSpec4 } from "@sdk-it/spec";
2144
2591
  import { generate as generate3 } from "@sdk-it/typescript";
2145
- var typescript_default = new Command5("typescript").alias("ts").description("Generate TypeScript SDK").addOption(specOption.makeOptionMandatory(true)).addOption(outputOption.makeOptionMandatory(false)).option(
2592
+ var typescript_default = new Command6("typescript").alias("ts").description("Generate TypeScript SDK").addOption(specOption.makeOptionMandatory(true)).addOption(outputOption.makeOptionMandatory(false)).option(
2146
2593
  "--useTsExtension [value]",
2147
2594
  "Use .ts extension for generated files",
2148
2595
  (value) => value === "false" ? false : true,
@@ -2185,7 +2632,10 @@ async function runTypescript(options) {
2185
2632
  }
2186
2633
  const spec = await loadSpec4(options.spec);
2187
2634
  if (options.output) {
2188
- await emitLocal(spec, { ...options, output: options.output });
2635
+ await emitLocal(spec, {
2636
+ ...options,
2637
+ output: options.output
2638
+ });
2189
2639
  }
2190
2640
  if (options.publish) {
2191
2641
  await emitRemote(spec, {
@@ -2200,7 +2650,7 @@ async function emitLocal(spec, options) {
2200
2650
  output: options.output,
2201
2651
  mode: options.mode || "minimal",
2202
2652
  name: options.name,
2203
- pagination: parsePagination(parseDotConfig(options.pagination ?? "true")),
2653
+ pagination: typeof options.pagination === "string" ? parsePagination(parseDotConfig(options.pagination ?? "true")) : options.pagination,
2204
2654
  style: {
2205
2655
  name: "github",
2206
2656
  outputType: options.outputType,
@@ -2237,7 +2687,7 @@ async function emitLocal(spec, options) {
2237
2687
  async function emitRemote(spec, options) {
2238
2688
  const registry = options.publish === "npm" ? "https://registry.npmjs.org/" : options.publish === "github" ? "https://npm.pkg.github.com/" : options.publish;
2239
2689
  console.log("Publishing to registry:", registry);
2240
- const path = join3(tmpdir(), crypto.randomUUID());
2690
+ const path = join4(tmpdir(), crypto.randomUUID());
2241
2691
  await emitLocal(spec, {
2242
2692
  ...options,
2243
2693
  output: path,
@@ -2245,7 +2695,7 @@ async function emitRemote(spec, options) {
2245
2695
  mode: "full"
2246
2696
  });
2247
2697
  const manifest = JSON.parse(
2248
- await readFile(join3(path, "package.json"), "utf-8")
2698
+ await readFile(join4(path, "package.json"), "utf-8")
2249
2699
  );
2250
2700
  const registryUrl = new URL(registry);
2251
2701
  const npmrc = process.env.NPM_TOKEN ? {
@@ -2262,7 +2712,7 @@ async function emitRemote(spec, options) {
2262
2712
  }
2263
2713
  const packResult = execSync3("npm pack --pack-destination .", { cwd: path });
2264
2714
  const [tgzName] = packResult.toString().trim().split("\n");
2265
- await publish(manifest, await readFile(join3(path, tgzName)), {
2715
+ await publish(manifest, await readFile(join4(path, tgzName)), {
2266
2716
  registry,
2267
2717
  defaultTag: "latest",
2268
2718
  forceAuth: {
@@ -2274,11 +2724,9 @@ async function emitRemote(spec, options) {
2274
2724
  }
2275
2725
 
2276
2726
  // packages/cli/src/lib/cli.ts
2277
- var generate4 = new Command6("generate").action(async (options) => {
2727
+ var generate4 = new Command7("generate").action(async (options) => {
2278
2728
  options.config ??= "sdk-it.json";
2279
- const config = await readFile2(options.config, "utf-8").then(
2280
- (data) => JSON.parse(data)
2281
- );
2729
+ const config = await readJson2(options.config);
2282
2730
  const promises = [];
2283
2731
  if (config.generators?.typescript) {
2284
2732
  promises.push(
@@ -2287,13 +2735,13 @@ var generate4 = new Command6("generate").action(async (options) => {
2287
2735
  output: config.generators.typescript.output,
2288
2736
  mode: config.generators.typescript.mode,
2289
2737
  name: config.generators.typescript.name,
2290
- useTsExtension: true,
2291
- install: true,
2738
+ useTsExtension: config.generators.typescript.useTsExtension ?? true,
2739
+ install: config.generators.typescript.install ?? false,
2292
2740
  verbose: false,
2293
- defaultFormatter: true,
2741
+ defaultFormatter: config.generators.typescript.defaultFormatter ?? true,
2294
2742
  outputType: "default",
2295
- readme: true,
2296
- pagination: config.generators.typescript.pagination?.toString()
2743
+ readme: config.generators.typescript.readme ?? true,
2744
+ pagination: config.generators.typescript.pagination
2297
2745
  })
2298
2746
  );
2299
2747
  }
@@ -2315,9 +2763,8 @@ var generate4 = new Command6("generate").action(async (options) => {
2315
2763
  output: config.generators.dart.output,
2316
2764
  mode: config.generators.dart.mode,
2317
2765
  name: config.generators.dart.name,
2318
- useTsExtension: false,
2319
2766
  verbose: false,
2320
- pagination: config.generators.dart.pagination?.toString()
2767
+ pagination: config.generators.dart.pagination
2321
2768
  })
2322
2769
  );
2323
2770
  }
@@ -2327,8 +2774,8 @@ var generate4 = new Command6("generate").action(async (options) => {
2327
2774
  await Promise.all(promises);
2328
2775
  console.log("All configured generators completed successfully!");
2329
2776
  }).addCommand(typescript_default).addCommand(python_default).addCommand(dart_default).addCommand(apiref_default).addCommand(readme_default);
2330
- var cli = program.description(`CLI tool to interact with SDK-IT.`).addCommand(generate4, { isDefault: true }).addCommand(
2331
- new Command6("_internal").action(() => {
2777
+ var cli = program.description(`CLI tool to interact with SDK-IT.`).addCommand(generate4, { isDefault: true }).addCommand(init_default).addCommand(
2778
+ new Command7("_internal").action(() => {
2332
2779
  }),
2333
2780
  { hidden: true }
2334
2781
  ).parse(process.argv);