typed-openapi 2.2.3 → 2.2.6

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,61 @@
1
+ // src/format.ts
2
+ import { readFile } from "fs/promises";
3
+ import { createRequire } from "module";
4
+ import { dirname, join } from "path";
5
+ import { pathToFileURL } from "url";
6
+ var defaultFilePath = "generated.ts";
7
+ var require2 = createRequire(import.meta.url);
8
+ async function formatWithBundledOxfmt(filePath, input, options) {
9
+ const packageJsonPath = require2.resolve("oxfmt/package.json");
10
+ const packageRoot = dirname(packageJsonPath);
11
+ const indexSource = await readFile(join(packageRoot, "dist", "index.js"), "utf8");
12
+ const match = indexSource.match(/from ["']\.\/(apis-[^"']+\.js)["']/);
13
+ const internalFile = match?.[1];
14
+ if (!internalFile) {
15
+ throw new Error("Unable to locate oxfmt's bundled JS formatter");
16
+ }
17
+ const internalUrl = pathToFileURL(join(packageRoot, "dist", internalFile)).href;
18
+ const { r: formatFile } = await import(internalUrl);
19
+ return formatFile({
20
+ code: input,
21
+ options: {
22
+ printWidth: 120,
23
+ trailingComma: "all",
24
+ ...options,
25
+ filepath: filePath
26
+ }
27
+ });
28
+ }
29
+ async function maybePretty(input, options) {
30
+ const { enabled, filePath = defaultFilePath, ...formatOptions } = options ?? {};
31
+ if (enabled === false) {
32
+ return input;
33
+ }
34
+ try {
35
+ const { format } = await import("oxfmt");
36
+ const result = await format(filePath, input, {
37
+ printWidth: 120,
38
+ trailingComma: "all",
39
+ ...formatOptions
40
+ });
41
+ if (result.errors.length > 0) {
42
+ console.warn(`Failed to format code in ${filePath}`);
43
+ console.warn(result.errors);
44
+ return input;
45
+ }
46
+ return result.code;
47
+ } catch {
48
+ try {
49
+ return await formatWithBundledOxfmt(filePath, input, formatOptions);
50
+ } catch (err) {
51
+ console.warn(`Failed to format code in ${filePath}`);
52
+ console.warn(err);
53
+ return input;
54
+ }
55
+ }
56
+ }
57
+ var prettify = (str, options) => maybePretty(str, options);
58
+
59
+ export {
60
+ prettify
61
+ };
@@ -1,7 +1,3 @@
1
- import {
2
- prettify
3
- } from "./chunk-KAEXXJ7X.js";
4
-
5
1
  // src/asserts.ts
6
2
  var isPrimitiveType = (type2) => primitiveTypeList.includes(type2);
7
3
  var primitiveTypeList = ["string", "number", "integer", "boolean", "null"];
@@ -17,10 +13,10 @@ function normalizeString(text) {
17
13
  const prefixed = prefixStringStartingWithNumberIfNeeded(text);
18
14
  return prefixed.normalize("NFKD").trim().replace(/\s+/g, "_").replace(/-+/g, "_").replace(/[^\w\-]+/g, "_").replace(/--+/g, "-");
19
15
  }
20
- var onlyWordRegex = /^\w+$/;
16
+ var barePropertyNameRegex = /^(?:[A-Za-z_]\w*|\d+)$/;
21
17
  var wrapWithQuotesIfNeeded = (str) => {
22
18
  if (str[0] === '"' && str[str.length - 1] === '"') return str;
23
- if (onlyWordRegex.test(str)) {
19
+ if (barePropertyNameRegex.test(str)) {
24
20
  return str;
25
21
  }
26
22
  return `"${str}"`;
@@ -132,9 +128,9 @@ var openApiSchemaToTs = ({ schema, meta: _inheritedMeta, ctx }) => {
132
128
  }
133
129
  if (schemaType === "object" || schema.properties || schema.additionalProperties) {
134
130
  if (!schema.properties) {
135
- if (schema.additionalProperties && !isReferenceObject(schema.additionalProperties) && typeof schema.additionalProperties !== "boolean") {
131
+ if (schema.additionalProperties && typeof schema.additionalProperties !== "boolean") {
136
132
  const valueSchema = openApiSchemaToTs({ schema: schema.additionalProperties, ctx, meta });
137
- return t.literal(`Record<string, ${valueSchema.value}>`);
133
+ return t.reference("Record", [t.string(), valueSchema]);
138
134
  }
139
135
  return t.literal("Record<string, unknown>");
140
136
  }
@@ -150,9 +146,7 @@ var openApiSchemaToTs = ({ schema, meta: _inheritedMeta, ctx }) => {
150
146
  meta
151
147
  });
152
148
  }
153
- additionalProperties = t.literal(
154
- `Record<string, ${additionalPropertiesType ? additionalPropertiesType.value : t.any().value}>`
155
- );
149
+ additionalProperties = t.reference("Record", [t.string(), additionalPropertiesType ?? t.any()]);
156
150
  }
157
151
  const hasRequiredArray = schema.required && schema.required.length > 0;
158
152
  const isPartial = !schema.required?.length;
@@ -170,12 +164,18 @@ var openApiSchemaToTs = ({ schema, meta: _inheritedMeta, ctx }) => {
170
164
  const objectType = additionalProperties ? t.intersection([t.object(props), additionalProperties]) : t.object(props);
171
165
  return isPartial ? t.reference("Partial", [objectType]) : objectType;
172
166
  }
173
- if (!schemaType) return t.unknown();
167
+ if (!schemaType) {
168
+ const nullableKey = Object.keys(schema).filter((key) => !["nullable"].includes(key));
169
+ if (nullableKey.length === 0 && schema.nullable) {
170
+ return t.literal("null");
171
+ }
172
+ return t.unknown();
173
+ }
174
174
  throw new Error(`Unsupported schema type: ${schemaType}`);
175
175
  };
176
176
  let output = getTs();
177
177
  if (!isReferenceObject(schema)) {
178
- if (schema.nullable) {
178
+ if (schema.nullable && output.value !== "null") {
179
179
  output = t.union([output, t.literal("null")]);
180
180
  }
181
181
  }
@@ -193,6 +193,7 @@ var Box = class _Box {
193
193
  this.schema = definition.schema;
194
194
  this.ctx = definition.ctx;
195
195
  }
196
+ definition;
196
197
  type;
197
198
  value;
198
199
  params;
@@ -378,13 +379,28 @@ var replacerByRuntime = {
378
379
  "$1$2("
379
380
  )
380
381
  };
382
+ var shouldRenderDescriptionComments = (ctx) => ctx.jsdoc && ctx.runtime === "none";
383
+ var escapeCommentText = (text) => text.replace(/\*\//g, "*\\/");
384
+ var renderDescriptionComment = (description, indent = "") => {
385
+ const lines = description.trim().split(/\r?\n/);
386
+ return `${indent}/**
387
+ ${lines.map((line) => `${indent} * ${escapeCommentText(line)}`).join("\n")}
388
+ ${indent} */`;
389
+ };
390
+ var getSchemaDescription = (schema) => {
391
+ if (!schema || typeof schema !== "object") return void 0;
392
+ if ("description" in schema && typeof schema.description === "string") return schema.description;
393
+ return void 0;
394
+ };
395
+ var indentMultiline = (value, indent = " ") => value.includes("\n") ? value.split("\n").map((line, index) => index === 0 ? line : `${indent}${line}`).join("\n") : value;
381
396
  var generateFile = (options) => {
382
397
  const ctx = {
383
398
  ...options,
384
399
  runtime: options.runtime ?? "none",
385
400
  successStatusCodes: options.successStatusCodes ?? DEFAULT_SUCCESS_STATUS_CODES,
386
401
  errorStatusCodes: options.errorStatusCodes ?? DEFAULT_ERROR_STATUS_CODES,
387
- includeClient: options.includeClient ?? true
402
+ includeClient: options.includeClient ?? true,
403
+ jsdoc: options.jsdoc ?? false
388
404
  };
389
405
  const schemaList = generateSchemaList(ctx);
390
406
  const endpointSchemaList = options.schemasOnly ? "" : generateEndpointSchemaList(ctx);
@@ -414,7 +430,8 @@ var generateFile = (options) => {
414
430
  `;
415
431
  return file;
416
432
  };
417
- var generateSchemaList = ({ refs, runtime }) => {
433
+ var generateSchemaList = (ctx) => {
434
+ const { refs, runtime } = ctx;
418
435
  let file = `
419
436
  ${runtime === "none" ? "export namespace Schemas {" : ""}
420
437
  // <Schemas>
@@ -422,7 +439,10 @@ var generateSchemaList = ({ refs, runtime }) => {
422
439
  refs.getOrderedSchemas().forEach(([schema, infos]) => {
423
440
  if (!infos?.name) return;
424
441
  if (infos.kind !== "schemas") return;
425
- file += `export type ${infos.normalized} = ${schema.value}
442
+ const description = shouldRenderDescriptionComments(ctx) ? getSchemaDescription(schema.schema) : void 0;
443
+ const schemaValue = shouldRenderDescriptionComments(ctx) && !Box.isReference(schema) ? boxToString(schema, ctx, { prefixRefsWithSchemas: false }) : schema.value;
444
+ file += `${description ? `${renderDescriptionComment(description)}
445
+ ` : ""}export type ${infos.normalized} = ${schemaValue}
426
446
  `;
427
447
  });
428
448
  return file + `
@@ -430,29 +450,79 @@ var generateSchemaList = ({ refs, runtime }) => {
430
450
  ${runtime === "none" ? "}" : ""}
431
451
  `;
432
452
  };
453
+ var boxToString = (box, ctx, options = {}) => {
454
+ const prefixRefsWithSchemas = options.prefixRefsWithSchemas ?? true;
455
+ if (ctx.runtime !== "none") {
456
+ return box.value;
457
+ }
458
+ const renderValue = (value) => {
459
+ if (typeof value === "string") {
460
+ return value;
461
+ }
462
+ if (Box.isBox(value)) {
463
+ return boxToString(value, ctx, options);
464
+ }
465
+ return value.value;
466
+ };
467
+ if (Box.isUnion(box)) {
468
+ return `(${box.params.types.map((type2) => renderValue(type2)).join(" | ")})`;
469
+ }
470
+ if (Box.isIntersection(box)) {
471
+ return `(${box.params.types.map((type2) => renderValue(type2)).join(" & ")})`;
472
+ }
473
+ if (Box.isArray(box)) {
474
+ return `Array<${renderValue(box.params.type)}>`;
475
+ }
476
+ if (Box.isOptional(box)) {
477
+ return `${renderValue(box.params.type)} | undefined`;
478
+ }
479
+ if (Box.isObject(box)) {
480
+ const renderedProps = Object.entries(box.params.props).map(([prop, type2]) => {
481
+ const isOptional = typeof type2 !== "string" && Box.isBox(type2) && Box.isOptional(type2);
482
+ const renderedValue = indentMultiline(renderValue(type2));
483
+ const description = shouldRenderDescriptionComments(ctx) && typeof type2 !== "string" && Box.isBox(type2) ? getSchemaDescription(type2.schema) : void 0;
484
+ return {
485
+ description,
486
+ line: `${wrapWithQuotesIfNeeded(prop)}${isOptional ? "?" : ""}: ${renderedValue};`
487
+ };
488
+ });
489
+ const shouldRenderMultiline = shouldRenderDescriptionComments(ctx) && renderedProps.some(({ description, line }) => description || line.includes("\n"));
490
+ if (!shouldRenderMultiline) {
491
+ const propsString2 = renderedProps.map(({ line }) => line.slice(0, -1)).join(", ");
492
+ return `{ ${propsString2} }`;
493
+ }
494
+ const propsString = renderedProps.map(({ description, line }) => {
495
+ const comment = description ? `${renderDescriptionComment(description, " ")}
496
+ ` : "";
497
+ return `${comment} ${line}`;
498
+ }).join("\n");
499
+ return `{
500
+ ${propsString}
501
+ }`;
502
+ }
503
+ if (Box.isReference(box)) {
504
+ if (!box.params.generics) {
505
+ return box.value === "null" ? box.value : prefixRefsWithSchemas ? `Schemas.${box.value}` : box.value;
506
+ }
507
+ return `${box.params.name}<${box.params.generics.map((type2) => renderValue(type2)).join(", ")}>`;
508
+ }
509
+ return box.value;
510
+ };
433
511
  var parameterObjectToString = (parameters, ctx) => {
434
512
  if (parameters instanceof Box) {
435
- if (ctx.runtime === "none") {
436
- return parameters.recompute((box) => {
437
- if (Box.isReference(box) && !box.params.generics && box.value !== "null") {
438
- box.value = `Schemas.${box.value}`;
439
- }
440
- return box;
441
- }).value;
442
- }
443
- return parameters.value;
513
+ return boxToString(parameters, ctx);
444
514
  }
445
515
  let str = "{";
446
516
  for (const [key, box] of Object.entries(parameters)) {
447
- str += `${wrapWithQuotesIfNeeded(key)}${box.type === "optional" ? "?" : ""}: ${box.value},
517
+ str += `${wrapWithQuotesIfNeeded(key)}${box.type === "optional" ? "?" : ""}: ${indentMultiline(boxToString(box, ctx))},
448
518
  `;
449
519
  }
450
520
  return str + "}";
451
521
  };
452
- var responseHeadersObjectToString = (responseHeaders) => {
522
+ var responseHeadersObjectToString = (responseHeaders, ctx) => {
453
523
  let str = "{";
454
524
  for (const [key, responseHeader] of Object.entries(responseHeaders)) {
455
- str += `${wrapWithQuotesIfNeeded(key.toLowerCase())}: ${responseHeader.value},
525
+ str += `${wrapWithQuotesIfNeeded(key.toLowerCase())}: ${indentMultiline(boxToString(responseHeader, ctx))},
456
526
  `;
457
527
  }
458
528
  return str + "}";
@@ -460,12 +530,7 @@ var responseHeadersObjectToString = (responseHeaders) => {
460
530
  var generateResponsesObject = (responses, ctx) => {
461
531
  let str = "{";
462
532
  for (const [statusCode, responseType] of Object.entries(responses)) {
463
- const value = ctx.runtime === "none" ? responseType.recompute((box) => {
464
- if (Box.isReference(box) && !box.params.generics && box.value !== "null") {
465
- box.value = `Schemas.${box.value}`;
466
- }
467
- return box;
468
- }).value : responseType.value;
533
+ const value = indentMultiline(boxToString(responseType, ctx));
469
534
  str += `${wrapWithQuotesIfNeeded(statusCode)}: ${value},
470
535
  `;
471
536
  }
@@ -479,7 +544,9 @@ var generateEndpointSchemaList = (ctx) => {
479
544
  `;
480
545
  ctx.endpointList.map((endpoint) => {
481
546
  const parameters = endpoint.parameters ?? {};
482
- file += `export type ${endpoint.meta.alias} = {
547
+ const description = shouldRenderDescriptionComments(ctx) ? endpoint.operation.description : void 0;
548
+ file += `${description ? `${renderDescriptionComment(description)}
549
+ ` : ""}export type ${endpoint.meta.alias} = {
483
550
  method: "${endpoint.method.toUpperCase()}",
484
551
  path: "${endpoint.path}",
485
552
  requestFormat: "${endpoint.requestFormat}",
@@ -487,18 +554,10 @@ var generateEndpointSchemaList = (ctx) => {
487
554
  ${parameters.query ? `query: ${parameterObjectToString(parameters.query, ctx)},` : ""}
488
555
  ${parameters.path ? `path: ${parameterObjectToString(parameters.path, ctx)},` : ""}
489
556
  ${parameters.header ? `header: ${parameterObjectToString(parameters.header, ctx)},` : ""}
490
- ${parameters.body ? `body: ${parameterObjectToString(
491
- ctx.runtime === "none" ? parameters.body.recompute((box) => {
492
- if (Box.isReference(box) && !box.params.generics) {
493
- box.value = `Schemas.${box.value}`;
494
- }
495
- return box;
496
- }) : parameters.body,
497
- ctx
498
- )},` : ""}
557
+ ${parameters.body ? `body: ${parameterObjectToString(parameters.body, ctx)},` : ""}
499
558
  }` : "parameters: never,"}
500
559
  ${endpoint.responses ? `responses: ${generateResponsesObject(endpoint.responses, ctx)},` : ""}
501
- ${endpoint.responseHeaders ? `responseHeaders: ${responseHeadersObjectToString(endpoint.responseHeaders)},` : ""}
560
+ ${endpoint.responseHeaders ? `responseHeaders: ${responseHeadersObjectToString(endpoint.responseHeaders, ctx)},` : ""}
502
561
  }
503
562
  `;
504
563
  });
@@ -576,7 +635,7 @@ export type Endpoint<TConfig extends DefaultEndpoint = DefaultEndpoint> = {
576
635
 
577
636
  export interface Fetcher {
578
637
  decodePathParams?: (path: string, pathParams: Record<string, string>) => string
579
- encodeSearchParams?: (searchParams: Record<string, unknown> | undefined) => URLSearchParams
638
+ encodeSearchParams?: (searchParams: Record<string, unknown> | undefined) => URLSearchParams
580
639
  //
581
640
  fetch: (input: {
582
641
  method: Method;
@@ -1018,15 +1077,28 @@ var createRefResolver = (doc, factory2, nameTransform) => {
1018
1077
  const path = split.slice(1, -1).join("/");
1019
1078
  const normalizedPath = path.replace("#/", "").replace("#", "").replaceAll("/", ".");
1020
1079
  const map = get(doc, normalizedPath) ?? {};
1080
+ const existingInfo = byRef.get(correctRef);
1081
+ if (existingInfo) {
1082
+ return map[split[split.length - 1]];
1083
+ }
1021
1084
  const name = split[split.length - 1];
1022
- let normalized = normalizeString(name);
1023
- if (nameTransform?.transformSchemaName) {
1024
- normalized = nameTransform.transformSchemaName(normalized);
1085
+ const kind = normalizedPath.split(".")[1];
1086
+ const baseNormalized = sanitizeName(
1087
+ nameTransform?.transformSchemaName ? nameTransform.transformSchemaName(normalizeString(name)) : normalizeString(name),
1088
+ "schema"
1089
+ );
1090
+ let normalized = baseNormalized;
1091
+ if (refByName.has(normalized) && refByName.get(normalized) !== correctRef) {
1092
+ const kindSuffix = `${baseNormalized}_${kind}`;
1093
+ normalized = kindSuffix;
1094
+ let suffix = 2;
1095
+ while (refByName.has(normalized) && refByName.get(normalized) !== correctRef) {
1096
+ normalized = `${kindSuffix}_${suffix++}`;
1097
+ }
1025
1098
  }
1026
- normalized = sanitizeName(normalized, "schema");
1027
1099
  nameByRef.set(correctRef, normalized);
1028
1100
  refByName.set(normalized, correctRef);
1029
- const infos = { ref: correctRef, name, normalized, kind: normalizedPath.split(".")[1] };
1101
+ const infos = { ref: correctRef, name, normalized, kind };
1030
1102
  byRef.set(infos.ref, infos);
1031
1103
  byNormalized.set(infos.normalized, infos);
1032
1104
  const schema = map[name];
@@ -1146,12 +1218,17 @@ var getTransitiveDependencies = (directDependencies) => {
1146
1218
 
1147
1219
  // src/ts-factory.ts
1148
1220
  var tsFactory = createFactory({
1149
- union: (types) => `(${types.map(unwrap).join(" | ")})`,
1150
- intersection: (types) => `(${types.map(unwrap).join(" & ")})`,
1221
+ union: (types) => types.length ? `(${types.map(unwrap).join(" | ")})` : "never",
1222
+ intersection: (types) => types.length ? `(${types.map(unwrap).join(" & ")})` : "unknown",
1151
1223
  array: (type2) => `Array<${unwrap(type2)}>`,
1152
1224
  optional: (type2) => `${unwrap(type2)} | undefined`,
1153
1225
  reference: (name, typeArgs) => `${name}${typeArgs ? `<${typeArgs.map(unwrap).join(", ")}>` : ""}`,
1154
- literal: (value) => value.toString(),
1226
+ literal: (value) => {
1227
+ if (typeof value === "string") return value;
1228
+ if (Box.isBox(value)) return unwrap(value);
1229
+ if (Array.isArray(value) || typeof value === "object") return JSON.stringify(value);
1230
+ return String(value);
1231
+ },
1155
1232
  string: () => "string",
1156
1233
  number: () => "number",
1157
1234
  boolean: () => "boolean",
@@ -1538,7 +1615,7 @@ var generateTanstackQueryFile = async (ctx) => {
1538
1615
  // </ApiClient.request>
1539
1616
  }
1540
1617
  `;
1541
- return prettify(file);
1618
+ return file;
1542
1619
  };
1543
1620
 
1544
1621
  export {
@@ -5,10 +5,10 @@ import {
5
5
  generateFile,
6
6
  generateTanstackQueryFile,
7
7
  mapOpenApiEndpoints
8
- } from "./chunk-RVHSVZW7.js";
8
+ } from "./chunk-S3NICEHD.js";
9
9
  import {
10
10
  prettify
11
- } from "./chunk-KAEXXJ7X.js";
11
+ } from "./chunk-MAZKDIN3.js";
12
12
 
13
13
  // src/generate-client-files.ts
14
14
  import SwaggerParser from "@apidevtools/swagger-parser";
@@ -100,6 +100,7 @@ async function ensureDir(dirPath) {
100
100
  var optionsSchema = type({
101
101
  "output?": "string",
102
102
  runtime: allowedRuntimes,
103
+ "format?": "boolean | 'true' | 'false'",
103
104
  tanstack: "boolean | string",
104
105
  "defaultFetcher?": type({
105
106
  "envApiBaseUrl?": "string",
@@ -109,38 +110,47 @@ var optionsSchema = type({
109
110
  }),
110
111
  schemasOnly: "boolean",
111
112
  "includeClient?": "boolean | 'true' | 'false'",
113
+ "jsdoc?": "boolean | 'true' | 'false'",
112
114
  "successStatusCodes?": "string",
113
115
  "errorStatusCodes?": "string"
114
116
  });
117
+ function parseBooleanOption(value) {
118
+ if (value === "false") {
119
+ return false;
120
+ }
121
+ if (value === "true") {
122
+ return true;
123
+ }
124
+ return value;
125
+ }
115
126
  async function generateClientFiles(input, options) {
116
127
  const openApiDoc = await SwaggerParser.bundle(input);
117
128
  const ctx = mapOpenApiEndpoints(openApiDoc, options);
118
129
  console.log(`Found ${ctx.endpointList.length} endpoints`);
119
130
  const successStatusCodes = options.successStatusCodes ? options.successStatusCodes.split(",").map((code) => parseInt(code.trim(), 10)) : void 0;
120
131
  const errorStatusCodes = options.errorStatusCodes ? options.errorStatusCodes.split(",").map((code) => parseInt(code.trim(), 10)) : void 0;
121
- const includeClient = options.includeClient === "false" ? false : options.includeClient === "true" ? true : options.includeClient;
132
+ const includeClient = parseBooleanOption(options.includeClient);
133
+ const jsdoc = parseBooleanOption(options.jsdoc) ?? true;
134
+ const shouldFormat = parseBooleanOption(options.format) ?? false;
122
135
  const generatorOptions = {
123
136
  ...ctx,
124
137
  runtime: options.runtime,
125
138
  schemasOnly: options.schemasOnly,
126
139
  nameTransform: options.nameTransform,
127
140
  includeClient: includeClient ?? true,
141
+ jsdoc,
128
142
  successStatusCodes: successStatusCodes ?? DEFAULT_SUCCESS_STATUS_CODES,
129
143
  errorStatusCodes: errorStatusCodes ?? DEFAULT_ERROR_STATUS_CODES
130
144
  };
131
- const content = await prettify(generateFile(generatorOptions));
132
145
  const outputPath = join(
133
146
  cwd,
134
147
  options.output ?? input + `.${options.runtime === "none" ? "client" : options.runtime}.ts`
135
148
  );
149
+ const content = await prettify(generateFile(generatorOptions), { enabled: shouldFormat, filePath: outputPath });
136
150
  console.log("Generating client...", outputPath);
137
151
  await ensureDir(dirname(outputPath));
138
152
  await writeFile(outputPath, content);
139
153
  if (options.tanstack) {
140
- const tanstackContent = await generateTanstackQueryFile({
141
- ...generatorOptions,
142
- relativeApiClientPath: "./" + basename(outputPath)
143
- });
144
154
  let tanstackOutputPath;
145
155
  if (typeof options.tanstack === "string" && isAbsolute(options.tanstack)) {
146
156
  tanstackOutputPath = options.tanstack;
@@ -150,6 +160,13 @@ async function generateClientFiles(input, options) {
150
160
  typeof options.tanstack === "string" ? options.tanstack : `tanstack.client.ts`
151
161
  );
152
162
  }
163
+ const tanstackContent = await prettify(
164
+ await generateTanstackQueryFile({
165
+ ...generatorOptions,
166
+ relativeApiClientPath: "./" + basename(outputPath)
167
+ }),
168
+ { enabled: shouldFormat, filePath: tanstackOutputPath }
169
+ );
153
170
  console.log("Generating tanstack client...", tanstackOutputPath);
154
171
  await ensureDir(dirname(tanstackOutputPath));
155
172
  await writeFile(tanstackOutputPath, tanstackContent);
@@ -170,9 +187,13 @@ async function generateClientFiles(input, options) {
170
187
  typeof options.defaultFetcher === "string" ? options.defaultFetcher : `api.client.ts`
171
188
  );
172
189
  }
190
+ const formattedDefaultFetcherContent = await prettify(defaultFetcherContent, {
191
+ enabled: shouldFormat,
192
+ filePath: defaultFetcherOutputPath
193
+ });
173
194
  console.log("Generating default fetcher...", defaultFetcherOutputPath);
174
195
  await ensureDir(dirname(defaultFetcherOutputPath));
175
- await writeFile(defaultFetcherOutputPath, defaultFetcherContent);
196
+ await writeFile(defaultFetcherOutputPath, formattedDefaultFetcherContent);
176
197
  }
177
198
  console.log(`Done in ${(/* @__PURE__ */ new Date()).getTime() - now.getTime()}ms !`);
178
199
  }
package/dist/cli.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  generateClientFiles
3
- } from "./chunk-GIUNFA7X.js";
3
+ } from "./chunk-WTE26U5C.js";
4
4
  import {
5
5
  allowedRuntimes
6
- } from "./chunk-RVHSVZW7.js";
7
- import "./chunk-KAEXXJ7X.js";
6
+ } from "./chunk-S3NICEHD.js";
7
+ import "./chunk-MAZKDIN3.js";
8
8
 
9
9
  // src/cli.ts
10
10
  import { cac } from "cac";
@@ -15,7 +15,9 @@ cli.command("<input>", "Generate").option("-o, --output <path>", "Output path fo
15
15
  "-r, --runtime <n>",
16
16
  `Runtime to use for validation; defaults to \`none\`; available: ${allowedRuntimes.toString()}`,
17
17
  { default: "none" }
18
- ).option("--schemas-only", "Only generate schemas, skipping client generation (defaults to false)", { default: false }).option("--include-client", "Include API client types and implementation (defaults to true)", { default: true }).option(
18
+ ).option("--format", "Format generated files with oxfmt (defaults to false)", { default: false }).option("--schemas-only", "Only generate schemas, skipping client generation (defaults to false)", { default: false }).option("--include-client", "Include API client types and implementation (defaults to true)", { default: true }).option("--jsdoc", "Emit OpenAPI descriptions as JSDoc comments (defaults to false)", {
19
+ default: true
20
+ }).option(
19
21
  "--success-status-codes <codes>",
20
22
  "Comma-separated list of success status codes (defaults to 2xx and 3xx ranges)"
21
23
  ).option("--error-status-codes <codes>", "Comma-separated list of error status codes (defaults to 4xx and 5xx ranges)").option(
package/dist/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { ReferenceObject } from 'openapi3-ts/oas31';
2
- import { S as StringOrBox, O as OpenapiSchemaConvertContext, L as LibSchemaObject, B as BoxFactory, m as mapOpenApiEndpoints, N as NameTransformOptions, a as OpenapiSchemaConvertArgs, b as Box, A as AnyBoxDef } from './types-BOJSTQwz.js';
3
- export { q as AnyBox, j as BoxArray, f as BoxDefinition, i as BoxIntersection, o as BoxKeyword, n as BoxLiteral, p as BoxObject, k as BoxOptional, g as BoxParams, l as BoxRef, h as BoxUnion, c as Endpoint, E as EndpointParameters, F as FactoryCreator, G as GenericFactory, M as Method, R as RefInfo, e as RefResolver, W as WithSchema, d as createRefResolver } from './types-BOJSTQwz.js';
4
- import * as arktype_internal_methods_string_ts from 'arktype/internal/methods/string.ts';
2
+ import { L as LibSchemaObject, O as OpenapiSchemaConvertContext, B as BoxFactory, S as StringOrBox, m as mapOpenApiEndpoints, N as NameTransformOptions, a as OpenapiSchemaConvertArgs, b as Box, A as AnyBoxDef } from './types-DjwHsNyZ.js';
3
+ export { c as AnyBox, d as BoxArray, e as BoxDefinition, f as BoxIntersection, g as BoxKeyword, h as BoxLiteral, i as BoxObject, j as BoxOptional, k as BoxParams, l as BoxRef, n as BoxUnion, E as Endpoint, o as EndpointParameters, F as FactoryCreator, G as GenericFactory, M as Method, R as RefInfo, p as RefResolver, W as WithSchema, q as createRefResolver } from './types-DjwHsNyZ.js';
4
+ import * as arktype_internal_variants_string_ts from 'arktype/internal/variants/string.ts';
5
5
  import * as Codegen from '@sinclair/typebox-codegen';
6
6
  import 'openapi3-ts/oas30';
7
7
 
@@ -19,8 +19,9 @@ type GeneratorOptions$1 = ReturnType<typeof mapOpenApiEndpoints> & {
19
19
  successStatusCodes?: readonly number[];
20
20
  errorStatusCodes?: readonly number[];
21
21
  includeClient?: boolean;
22
+ jsdoc?: boolean;
22
23
  };
23
- declare const allowedRuntimes: arktype_internal_methods_string_ts.StringType<"none" | "arktype" | "io-ts" | "typebox" | "valibot" | "yup" | "zod", {}>;
24
+ declare const allowedRuntimes: arktype_internal_variants_string_ts.StringType<"none" | "arktype" | "io-ts" | "typebox" | "valibot" | "yup" | "zod", {}>;
24
25
  type OutputRuntime = typeof allowedRuntimes.infer;
25
26
  declare const runtimeValidationGenerator: {
26
27
  arktype: typeof Codegen.ModelToArkType.Generate;
package/dist/index.js CHANGED
@@ -8,8 +8,7 @@ import {
8
8
  openApiSchemaToTs,
9
9
  tsFactory,
10
10
  unwrap
11
- } from "./chunk-RVHSVZW7.js";
12
- import "./chunk-KAEXXJ7X.js";
11
+ } from "./chunk-S3NICEHD.js";
13
12
  export {
14
13
  createBoxFactory,
15
14
  createFactory,
@@ -1,13 +1,14 @@
1
- import * as arktype_internal_methods_object_ts from 'arktype/internal/methods/object.ts';
2
- import { N as NameTransformOptions } from './types-BOJSTQwz.js';
1
+ import * as arktype_internal_variants_object_ts from 'arktype/internal/variants/object.ts';
2
+ import { N as NameTransformOptions } from './types-DjwHsNyZ.js';
3
3
  import 'openapi3-ts/oas31';
4
4
  import 'openapi3-ts/oas30';
5
5
 
6
- declare const optionsSchema: arktype_internal_methods_object_ts.ObjectType<{
6
+ declare const optionsSchema: arktype_internal_variants_object_ts.ObjectType<{
7
7
  runtime: "none" | "arktype" | "io-ts" | "typebox" | "valibot" | "yup" | "zod";
8
8
  tanstack: string | boolean;
9
9
  schemasOnly: boolean;
10
10
  output?: string;
11
+ format?: boolean | "false" | "true";
11
12
  defaultFetcher?: {
12
13
  envApiBaseUrl?: string;
13
14
  clientPath?: string;
@@ -15,6 +16,7 @@ declare const optionsSchema: arktype_internal_methods_object_ts.ObjectType<{
15
16
  apiName?: string;
16
17
  };
17
18
  includeClient?: boolean | "false" | "true";
19
+ jsdoc?: boolean | "false" | "true";
18
20
  successStatusCodes?: string;
19
21
  errorStatusCodes?: string;
20
22
  }, {}>;
@@ -23,4 +25,4 @@ type GenerateClientFilesOptions = typeof optionsSchema.infer & {
23
25
  };
24
26
  declare function generateClientFiles(input: string, options: GenerateClientFilesOptions): Promise<void>;
25
27
 
26
- export { generateClientFiles };
28
+ export { type GenerateClientFilesOptions, generateClientFiles };
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  generateClientFiles
3
- } from "./chunk-GIUNFA7X.js";
4
- import "./chunk-RVHSVZW7.js";
5
- import "./chunk-KAEXXJ7X.js";
3
+ } from "./chunk-WTE26U5C.js";
4
+ import "./chunk-S3NICEHD.js";
5
+ import "./chunk-MAZKDIN3.js";
6
6
  export {
7
7
  generateClientFiles
8
8
  };
@@ -1,5 +1,10 @@
1
- import { Options } from 'prettier';
1
+ import * as oxfmt from 'oxfmt';
2
2
 
3
- declare const prettify: (str: string, options?: Options | null) => string | Promise<string>;
3
+ type OxcFormatOptions = oxfmt.FormatConfig;
4
+ type PrettifyOptions = OxcFormatOptions & {
5
+ enabled?: boolean;
6
+ filePath?: string;
7
+ };
8
+ declare const prettify: (str: string, options?: PrettifyOptions | null) => Promise<string>;
4
9
 
5
10
  export { prettify };
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  prettify
3
- } from "./chunk-KAEXXJ7X.js";
3
+ } from "./chunk-MAZKDIN3.js";
4
4
  export {
5
5
  prettify
6
6
  };
@@ -43,7 +43,7 @@ type RefInfo = {
43
43
  kind: "schemas" | "responses" | "parameters" | "requestBodies" | "headers";
44
44
  };
45
45
  declare const createRefResolver: (doc: OpenAPIObject, factory: GenericFactory, nameTransform?: NameTransformOptions) => {
46
- get: <T = LibSchemaObject>(ref: string) => NonNullable<T>;
46
+ get: <T = LibSchemaObject>(ref: string) => T;
47
47
  unwrap: <T extends ReferenceObject | {}>(component: T) => Exclude<T, ReferenceObject>;
48
48
  getInfosByRef: (ref: string) => RefInfo;
49
49
  infos: Map<string, RefInfo>;
@@ -63,7 +63,7 @@ declare const mapOpenApiEndpoints: (doc: OpenAPIObject, options?: {
63
63
  }) => {
64
64
  doc: OpenAPIObject;
65
65
  refs: {
66
- get: <T = LibSchemaObject>(ref: string) => NonNullable<T>;
66
+ get: <T = LibSchemaObject>(ref: string) => T;
67
67
  unwrap: <T extends openapi3_ts_oas31.ReferenceObject | {}>(component: T) => Exclude<T, openapi3_ts_oas31.ReferenceObject>;
68
68
  getInfosByRef: (ref: string) => RefInfo;
69
69
  infos: Map<string, RefInfo>;
@@ -239,4 +239,4 @@ type GenericFactory = {
239
239
  never: () => string;
240
240
  };
241
241
 
242
- export { type AnyBoxDef as A, type BoxFactory as B, type EndpointParameters as E, type FactoryCreator as F, type GenericFactory as G, type LibSchemaObject as L, type Method as M, type NameTransformOptions as N, type OpenapiSchemaConvertContext as O, type RefInfo as R, type StringOrBox as S, type WithSchema as W, type OpenapiSchemaConvertArgs as a, Box as b, type Endpoint as c, createRefResolver as d, type RefResolver as e, type BoxDefinition as f, type BoxParams as g, type BoxUnion as h, type BoxIntersection as i, type BoxArray as j, type BoxOptional as k, type BoxRef as l, mapOpenApiEndpoints as m, type BoxLiteral as n, type BoxKeyword as o, type BoxObject as p, type AnyBox as q };
242
+ export { type AnyBoxDef as A, type BoxFactory as B, type Endpoint as E, type FactoryCreator as F, type GenericFactory as G, type LibSchemaObject as L, type Method as M, type NameTransformOptions as N, type OpenapiSchemaConvertContext as O, type RefInfo as R, type StringOrBox as S, type WithSchema as W, type OpenapiSchemaConvertArgs as a, Box as b, type AnyBox as c, type BoxArray as d, type BoxDefinition as e, type BoxIntersection as f, type BoxKeyword as g, type BoxLiteral as h, type BoxObject as i, type BoxOptional as j, type BoxParams as k, type BoxRef as l, mapOpenApiEndpoints as m, type BoxUnion as n, type EndpointParameters as o, type RefResolver as p, createRefResolver as q };