typed-openapi 2.2.4 → 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;
@@ -171,9 +165,7 @@ var openApiSchemaToTs = ({ schema, meta: _inheritedMeta, ctx }) => {
171
165
  return isPartial ? t.reference("Partial", [objectType]) : objectType;
172
166
  }
173
167
  if (!schemaType) {
174
- const nullableKey = Object.keys(schema).filter(
175
- (key) => !["nullable"].includes(key)
176
- );
168
+ const nullableKey = Object.keys(schema).filter((key) => !["nullable"].includes(key));
177
169
  if (nullableKey.length === 0 && schema.nullable) {
178
170
  return t.literal("null");
179
171
  }
@@ -201,6 +193,7 @@ var Box = class _Box {
201
193
  this.schema = definition.schema;
202
194
  this.ctx = definition.ctx;
203
195
  }
196
+ definition;
204
197
  type;
205
198
  value;
206
199
  params;
@@ -386,13 +379,28 @@ var replacerByRuntime = {
386
379
  "$1$2("
387
380
  )
388
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;
389
396
  var generateFile = (options) => {
390
397
  const ctx = {
391
398
  ...options,
392
399
  runtime: options.runtime ?? "none",
393
400
  successStatusCodes: options.successStatusCodes ?? DEFAULT_SUCCESS_STATUS_CODES,
394
401
  errorStatusCodes: options.errorStatusCodes ?? DEFAULT_ERROR_STATUS_CODES,
395
- includeClient: options.includeClient ?? true
402
+ includeClient: options.includeClient ?? true,
403
+ jsdoc: options.jsdoc ?? false
396
404
  };
397
405
  const schemaList = generateSchemaList(ctx);
398
406
  const endpointSchemaList = options.schemasOnly ? "" : generateEndpointSchemaList(ctx);
@@ -422,7 +430,8 @@ var generateFile = (options) => {
422
430
  `;
423
431
  return file;
424
432
  };
425
- var generateSchemaList = ({ refs, runtime }) => {
433
+ var generateSchemaList = (ctx) => {
434
+ const { refs, runtime } = ctx;
426
435
  let file = `
427
436
  ${runtime === "none" ? "export namespace Schemas {" : ""}
428
437
  // <Schemas>
@@ -430,7 +439,10 @@ var generateSchemaList = ({ refs, runtime }) => {
430
439
  refs.getOrderedSchemas().forEach(([schema, infos]) => {
431
440
  if (!infos?.name) return;
432
441
  if (infos.kind !== "schemas") return;
433
- 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}
434
446
  `;
435
447
  });
436
448
  return file + `
@@ -438,29 +450,79 @@ var generateSchemaList = ({ refs, runtime }) => {
438
450
  ${runtime === "none" ? "}" : ""}
439
451
  `;
440
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
+ };
441
511
  var parameterObjectToString = (parameters, ctx) => {
442
512
  if (parameters instanceof Box) {
443
- if (ctx.runtime === "none") {
444
- return parameters.recompute((box) => {
445
- if (Box.isReference(box) && !box.params.generics && box.value !== "null") {
446
- box.value = `Schemas.${box.value}`;
447
- }
448
- return box;
449
- }).value;
450
- }
451
- return parameters.value;
513
+ return boxToString(parameters, ctx);
452
514
  }
453
515
  let str = "{";
454
516
  for (const [key, box] of Object.entries(parameters)) {
455
- str += `${wrapWithQuotesIfNeeded(key)}${box.type === "optional" ? "?" : ""}: ${box.value},
517
+ str += `${wrapWithQuotesIfNeeded(key)}${box.type === "optional" ? "?" : ""}: ${indentMultiline(boxToString(box, ctx))},
456
518
  `;
457
519
  }
458
520
  return str + "}";
459
521
  };
460
- var responseHeadersObjectToString = (responseHeaders) => {
522
+ var responseHeadersObjectToString = (responseHeaders, ctx) => {
461
523
  let str = "{";
462
524
  for (const [key, responseHeader] of Object.entries(responseHeaders)) {
463
- str += `${wrapWithQuotesIfNeeded(key.toLowerCase())}: ${responseHeader.value},
525
+ str += `${wrapWithQuotesIfNeeded(key.toLowerCase())}: ${indentMultiline(boxToString(responseHeader, ctx))},
464
526
  `;
465
527
  }
466
528
  return str + "}";
@@ -468,12 +530,7 @@ var responseHeadersObjectToString = (responseHeaders) => {
468
530
  var generateResponsesObject = (responses, ctx) => {
469
531
  let str = "{";
470
532
  for (const [statusCode, responseType] of Object.entries(responses)) {
471
- const value = ctx.runtime === "none" ? responseType.recompute((box) => {
472
- if (Box.isReference(box) && !box.params.generics && box.value !== "null") {
473
- box.value = `Schemas.${box.value}`;
474
- }
475
- return box;
476
- }).value : responseType.value;
533
+ const value = indentMultiline(boxToString(responseType, ctx));
477
534
  str += `${wrapWithQuotesIfNeeded(statusCode)}: ${value},
478
535
  `;
479
536
  }
@@ -487,7 +544,9 @@ var generateEndpointSchemaList = (ctx) => {
487
544
  `;
488
545
  ctx.endpointList.map((endpoint) => {
489
546
  const parameters = endpoint.parameters ?? {};
490
- 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} = {
491
550
  method: "${endpoint.method.toUpperCase()}",
492
551
  path: "${endpoint.path}",
493
552
  requestFormat: "${endpoint.requestFormat}",
@@ -495,18 +554,10 @@ var generateEndpointSchemaList = (ctx) => {
495
554
  ${parameters.query ? `query: ${parameterObjectToString(parameters.query, ctx)},` : ""}
496
555
  ${parameters.path ? `path: ${parameterObjectToString(parameters.path, ctx)},` : ""}
497
556
  ${parameters.header ? `header: ${parameterObjectToString(parameters.header, ctx)},` : ""}
498
- ${parameters.body ? `body: ${parameterObjectToString(
499
- ctx.runtime === "none" ? parameters.body.recompute((box) => {
500
- if (Box.isReference(box) && !box.params.generics) {
501
- box.value = `Schemas.${box.value}`;
502
- }
503
- return box;
504
- }) : parameters.body,
505
- ctx
506
- )},` : ""}
557
+ ${parameters.body ? `body: ${parameterObjectToString(parameters.body, ctx)},` : ""}
507
558
  }` : "parameters: never,"}
508
559
  ${endpoint.responses ? `responses: ${generateResponsesObject(endpoint.responses, ctx)},` : ""}
509
- ${endpoint.responseHeaders ? `responseHeaders: ${responseHeadersObjectToString(endpoint.responseHeaders)},` : ""}
560
+ ${endpoint.responseHeaders ? `responseHeaders: ${responseHeadersObjectToString(endpoint.responseHeaders, ctx)},` : ""}
510
561
  }
511
562
  `;
512
563
  });
@@ -584,7 +635,7 @@ export type Endpoint<TConfig extends DefaultEndpoint = DefaultEndpoint> = {
584
635
 
585
636
  export interface Fetcher {
586
637
  decodePathParams?: (path: string, pathParams: Record<string, string>) => string
587
- encodeSearchParams?: (searchParams: Record<string, unknown> | undefined) => URLSearchParams
638
+ encodeSearchParams?: (searchParams: Record<string, unknown> | undefined) => URLSearchParams
588
639
  //
589
640
  fetch: (input: {
590
641
  method: Method;
@@ -1026,15 +1077,28 @@ var createRefResolver = (doc, factory2, nameTransform) => {
1026
1077
  const path = split.slice(1, -1).join("/");
1027
1078
  const normalizedPath = path.replace("#/", "").replace("#", "").replaceAll("/", ".");
1028
1079
  const map = get(doc, normalizedPath) ?? {};
1080
+ const existingInfo = byRef.get(correctRef);
1081
+ if (existingInfo) {
1082
+ return map[split[split.length - 1]];
1083
+ }
1029
1084
  const name = split[split.length - 1];
1030
- let normalized = normalizeString(name);
1031
- if (nameTransform?.transformSchemaName) {
1032
- 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
+ }
1033
1098
  }
1034
- normalized = sanitizeName(normalized, "schema");
1035
1099
  nameByRef.set(correctRef, normalized);
1036
1100
  refByName.set(normalized, correctRef);
1037
- const infos = { ref: correctRef, name, normalized, kind: normalizedPath.split(".")[1] };
1101
+ const infos = { ref: correctRef, name, normalized, kind };
1038
1102
  byRef.set(infos.ref, infos);
1039
1103
  byNormalized.set(infos.normalized, infos);
1040
1104
  const schema = map[name];
@@ -1154,12 +1218,17 @@ var getTransitiveDependencies = (directDependencies) => {
1154
1218
 
1155
1219
  // src/ts-factory.ts
1156
1220
  var tsFactory = createFactory({
1157
- union: (types) => `(${types.map(unwrap).join(" | ")})`,
1158
- 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",
1159
1223
  array: (type2) => `Array<${unwrap(type2)}>`,
1160
1224
  optional: (type2) => `${unwrap(type2)} | undefined`,
1161
1225
  reference: (name, typeArgs) => `${name}${typeArgs ? `<${typeArgs.map(unwrap).join(", ")}>` : ""}`,
1162
- 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
+ },
1163
1232
  string: () => "string",
1164
1233
  number: () => "number",
1165
1234
  boolean: () => "boolean",
@@ -1546,7 +1615,7 @@ var generateTanstackQueryFile = async (ctx) => {
1546
1615
  // </ApiClient.request>
1547
1616
  }
1548
1617
  `;
1549
- return prettify(file);
1618
+ return file;
1550
1619
  };
1551
1620
 
1552
1621
  export {
@@ -5,10 +5,10 @@ import {
5
5
  generateFile,
6
6
  generateTanstackQueryFile,
7
7
  mapOpenApiEndpoints
8
- } from "./chunk-ZM3UP6UJ.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-62WASHT2.js";
3
+ } from "./chunk-WTE26U5C.js";
4
4
  import {
5
5
  allowedRuntimes
6
- } from "./chunk-ZM3UP6UJ.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-ZM3UP6UJ.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-62WASHT2.js";
4
- import "./chunk-ZM3UP6UJ.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 };