typed-openapi 0.10.0 → 1.0.0

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/LICENSE ADDED
@@ -0,0 +1,7 @@
1
+ Copyright (c) 2025 Alexandre Stahmer
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
+
5
+ The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
6
+
7
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -15,8 +15,7 @@ function normalizeString(text) {
15
15
  }
16
16
  var onlyWordRegex = /^\w+$/;
17
17
  var wrapWithQuotesIfNeeded = (str) => {
18
- if (str[0] === '"' && str[str.length - 1] === '"')
19
- return str;
18
+ if (str[0] === '"' && str[str.length - 1] === '"') return str;
20
19
  if (onlyWordRegex.test(str)) {
21
20
  return str;
22
21
  }
@@ -52,7 +51,7 @@ var openApiSchemaToTs = ({ schema, meta: _inheritedMeta, ctx }) => {
52
51
  return t.union(schema.type.map((prop) => openApiSchemaToTs({ schema: { ...schema, type: prop }, ctx, meta })));
53
52
  }
54
53
  if (schema.type === "null") {
55
- return t.reference("null");
54
+ return t.literal("null");
56
55
  }
57
56
  if (schema.oneOf) {
58
57
  if (schema.oneOf.length === 1) {
@@ -89,14 +88,10 @@ var openApiSchemaToTs = ({ schema, meta: _inheritedMeta, ctx }) => {
89
88
  }
90
89
  return t.union(schema.enum.map((value) => t.literal(value === null ? "null" : value)));
91
90
  }
92
- if (schemaType === "string")
93
- return t.string();
94
- if (schemaType === "boolean")
95
- return t.boolean();
96
- if (schemaType === "number" || schemaType === "integer")
97
- return t.number();
98
- if (schemaType === "null")
99
- return t.reference("null");
91
+ if (schemaType === "string") return t.string();
92
+ if (schemaType === "boolean") return t.boolean();
93
+ if (schemaType === "number" || schemaType === "integer") return t.number();
94
+ if (schemaType === "null") return t.literal("null");
100
95
  }
101
96
  if (schemaType === "array") {
102
97
  if (schema.items) {
@@ -110,7 +105,11 @@ var openApiSchemaToTs = ({ schema, meta: _inheritedMeta, ctx }) => {
110
105
  }
111
106
  if (schemaType === "object" || schema.properties || schema.additionalProperties) {
112
107
  if (!schema.properties) {
113
- return t.unknown();
108
+ if (schema.additionalProperties && !isReferenceObject(schema.additionalProperties) && typeof schema.additionalProperties !== "boolean" && schema.additionalProperties.type) {
109
+ const valueSchema = openApiSchemaToTs({ schema: schema.additionalProperties, ctx, meta });
110
+ return t.literal(`Record<string, ${valueSchema.value}>`);
111
+ }
112
+ return t.literal("Record<string, unknown>");
114
113
  }
115
114
  let additionalProperties;
116
115
  if (schema.additionalProperties) {
@@ -142,14 +141,13 @@ var openApiSchemaToTs = ({ schema, meta: _inheritedMeta, ctx }) => {
142
141
  const objectType = additionalProperties ? t.intersection([t.object(props), additionalProperties]) : t.object(props);
143
142
  return isPartial ? t.reference("Partial", [objectType]) : objectType;
144
143
  }
145
- if (!schemaType)
146
- return t.unknown();
144
+ if (!schemaType) return t.unknown();
147
145
  throw new Error(`Unsupported schema type: ${schemaType}`);
148
146
  };
149
147
  let output = getTs();
150
148
  if (!isReferenceObject(schema)) {
151
149
  if (schema.nullable) {
152
- output = t.union([output, t.reference("null")]);
150
+ output = t.union([output, t.literal("null")]);
153
151
  }
154
152
  }
155
153
  return output;
@@ -254,26 +252,6 @@ var createBoxFactory = (schema, ctx) => {
254
252
 
255
253
  // src/generator.ts
256
254
  import { capitalize as capitalize2, groupBy } from "pastable/server";
257
-
258
- // src/format.ts
259
- import prettier from "prettier";
260
- import parserTypescript from "prettier/parser-typescript";
261
- function maybePretty(input, options) {
262
- try {
263
- return prettier.format(input, {
264
- parser: "typescript",
265
- plugins: [parserTypescript],
266
- ...options
267
- });
268
- } catch (err) {
269
- console.warn("Failed to format code");
270
- console.warn(err);
271
- return input;
272
- }
273
- }
274
- var prettify = (str, options) => maybePretty(str, { printWidth: 120, trailingComma: "all", ...options });
275
-
276
- // src/generator.ts
277
255
  import * as Codegen from "@sinclair/typebox-codegen";
278
256
  import { match } from "ts-pattern";
279
257
  import { type } from "arktype";
@@ -328,7 +306,7 @@ var generateFile = (options) => {
328
306
  ${transform(schemaList + endpointSchemaList)}
329
307
  ${apiClient}
330
308
  `;
331
- return prettify(file);
309
+ return file;
332
310
  };
333
311
  var generateSchemaList = ({ refs, runtime }) => {
334
312
  let file = `
@@ -336,10 +314,8 @@ var generateSchemaList = ({ refs, runtime }) => {
336
314
  // <Schemas>
337
315
  `;
338
316
  refs.getOrderedSchemas().forEach(([schema, infos]) => {
339
- if (!infos?.name)
340
- return;
341
- if (infos.kind !== "schemas")
342
- return;
317
+ if (!infos?.name) return;
318
+ if (infos.kind !== "schemas") return;
343
319
  file += `export type ${infos.normalized} = ${schema.value}
344
320
  `;
345
321
  });
@@ -349,8 +325,7 @@ var generateSchemaList = ({ refs, runtime }) => {
349
325
  `;
350
326
  };
351
327
  var parameterObjectToString = (parameters) => {
352
- if (parameters instanceof Box)
353
- return parameters.value;
328
+ if (parameters instanceof Box) return parameters.value;
354
329
  let str = "{";
355
330
  for (const [key, box] of Object.entries(parameters)) {
356
331
  str += `${wrapWithQuotesIfNeeded(key)}: ${box.value},
@@ -384,7 +359,7 @@ var generateEndpointSchemaList = (ctx) => {
384
359
  )},` : ""}
385
360
  }` : "parameters: never,"}
386
361
  response: ${ctx.runtime === "none" ? endpoint.response.recompute((box) => {
387
- if (Box.isReference(box) && !box.params.generics) {
362
+ if (Box.isReference(box) && !box.params.generics && box.value !== "null") {
388
363
  box.value = `Schemas.${box.value}`;
389
364
  }
390
365
  return box;
@@ -525,8 +500,7 @@ import { get } from "pastable/server";
525
500
  function topologicalSort(graph) {
526
501
  const sorted = [], visited = {};
527
502
  function visit(name, ancestors) {
528
- if (!Array.isArray(ancestors))
529
- ancestors = [];
503
+ if (!Array.isArray(ancestors)) ancestors = [];
530
504
  ancestors.push(name);
531
505
  visited[name] = true;
532
506
  const deps = graph.get(name);
@@ -535,13 +509,11 @@ function topologicalSort(graph) {
535
509
  if (ancestors.includes(dep)) {
536
510
  return;
537
511
  }
538
- if (visited[dep])
539
- return;
512
+ if (visited[dep]) return;
540
513
  visit(dep, ancestors.slice(0));
541
514
  });
542
515
  }
543
- if (!sorted.includes(name))
544
- sorted.push(name);
516
+ if (!sorted.includes(name)) sorted.push(name);
545
517
  }
546
518
  graph.forEach((_, name) => visit(name, []));
547
519
  return sorted;
@@ -620,8 +592,7 @@ var createRefResolver = (doc, factory2) => {
620
592
  };
621
593
  var setSchemaDependencies = (schema, deps) => {
622
594
  const visit = (schema2) => {
623
- if (!schema2)
624
- return;
595
+ if (!schema2) return;
625
596
  if (isReferenceObject(schema2)) {
626
597
  deps.add(schema2.$ref);
627
598
  return;
@@ -645,8 +616,7 @@ var setSchemaDependencies = (schema, deps) => {
645
616
  return;
646
617
  }
647
618
  if (schema2.type === "array") {
648
- if (!schema2.items)
649
- return;
619
+ if (!schema2.items) return;
650
620
  return void visit(schema2.items);
651
621
  }
652
622
  if (schema2.type === "object" || schema2.properties || schema2.additionalProperties) {
@@ -675,8 +645,7 @@ var getTransitiveDependencies = (directDependencies) => {
675
645
  if (deps2 && ref !== depRef) {
676
646
  deps2.forEach((transitive) => {
677
647
  const key = ref + "__" + transitive;
678
- if (visitedsDeepRefs.has(key))
679
- return;
648
+ if (visitedsDeepRefs.has(key)) return;
680
649
  visitedsDeepRefs.add(key);
681
650
  visit(transitive);
682
651
  });
@@ -722,8 +691,7 @@ var mapOpenApiEndpoints = (doc) => {
722
691
  Object.entries(doc.paths ?? {}).forEach(([path, pathItemObj]) => {
723
692
  const pathItem = pick(pathItemObj, ["get", "put", "post", "delete", "options", "head", "patch", "trace"]);
724
693
  Object.entries(pathItem).forEach(([method, operation]) => {
725
- if (operation.deprecated)
726
- return;
694
+ if (operation.deprecated) return;
727
695
  const endpoint = {
728
696
  operation,
729
697
  method,
@@ -741,8 +709,7 @@ var mapOpenApiEndpoints = (doc) => {
741
709
  (acc, paramOrRef) => {
742
710
  const param = refs.unwrap(paramOrRef);
743
711
  const schema = openApiSchemaToTs({ schema: refs.unwrap(param.schema ?? {}), ctx });
744
- if (param.required)
745
- endpoint.meta.areParametersRequired = true;
712
+ if (param.required) endpoint.meta.areParametersRequired = true;
746
713
  endpoint.meta.hasParameters = true;
747
714
  if (param.in === "query") {
748
715
  lists.query.push(param);
@@ -798,13 +765,13 @@ var mapOpenApiEndpoints = (doc) => {
798
765
  endpoint.parameters = Object.keys(params).length ? params : void 0;
799
766
  }
800
767
  let responseObject;
801
- Object.entries(operation.responses).map(([status, responseOrRef]) => {
768
+ Object.entries(operation.responses ?? {}).map(([status, responseOrRef]) => {
802
769
  const statusCode = Number(status);
803
770
  if (statusCode >= 200 && statusCode < 300) {
804
771
  responseObject = refs.unwrap(responseOrRef);
805
772
  }
806
773
  });
807
- if (!responseObject && operation.responses.default) {
774
+ if (!responseObject && operation.responses?.default) {
808
775
  responseObject = refs.unwrap(operation.responses.default);
809
776
  }
810
777
  const content = responseObject?.content;
@@ -832,6 +799,121 @@ var isAllowedParamMediaTypes = (mediaType) => mediaType.includes("application/")
832
799
  var isResponseMediaType = (mediaType) => mediaType === "application/json";
833
800
  var getAlias = ({ path, method, operation }) => (method + "_" + capitalize3(operation.operationId ?? pathToVariableName(path))).replace(/-/g, "__");
834
801
 
802
+ // src/format.ts
803
+ import prettier from "prettier";
804
+ import parserTypescript from "prettier/parser-typescript";
805
+ function maybePretty(input, options) {
806
+ try {
807
+ return prettier.format(input, {
808
+ parser: "typescript",
809
+ plugins: [parserTypescript],
810
+ ...options
811
+ });
812
+ } catch (err) {
813
+ console.warn("Failed to format code");
814
+ console.warn(err);
815
+ return input;
816
+ }
817
+ }
818
+ var prettify = (str, options) => maybePretty(str, { printWidth: 120, trailingComma: "all", ...options });
819
+
820
+ // src/tanstack-query.generator.ts
821
+ import { capitalize as capitalize4 } from "pastable/server";
822
+ var generateTanstackQueryFile = async (ctx) => {
823
+ const endpointMethods = new Set(ctx.endpointList.map((endpoint) => endpoint.method.toLowerCase()));
824
+ const file = `
825
+ import { queryOptions, QueryClient } from "@tanstack/react-query"
826
+ import type { EndpointByMethod, ApiClient } from "${ctx.relativeApiClientPath}"
827
+
828
+ type EndpointQueryKey<TOptions extends EndpointParameters> = [
829
+ TOptions & {
830
+ _id: string;
831
+ _infinite?: boolean;
832
+ }
833
+ ];
834
+
835
+ const createQueryKey = <TOptions extends EndpointParameters>(id: string, options?: TOptions, infinite?: boolean): [
836
+ EndpointQueryKey<TOptions>[0]
837
+ ] => {
838
+ const params: EndpointQueryKey<TOptions>[0] = { _id: id, } as EndpointQueryKey<TOptions>[0];
839
+ if (infinite) {
840
+ params._infinite = infinite;
841
+ }
842
+ if (options?.body) {
843
+ params.body = options.body;
844
+ }
845
+ if (options?.header) {
846
+ params.header = options.header;
847
+ }
848
+ if (options?.path) {
849
+ params.path = options.path;
850
+ }
851
+ if (options?.query) {
852
+ params.query = options.query;
853
+ }
854
+ return [
855
+ params
856
+ ];
857
+ };
858
+
859
+ // <EndpointByMethod.Shorthands>
860
+ ${Array.from(endpointMethods).map((method) => `export type ${capitalize4(method)}Endpoints = EndpointByMethod["${method}"];`).join("\n")}
861
+ // </EndpointByMethod.Shorthands>
862
+
863
+ // <ApiClientTypes>
864
+ export type EndpointParameters = {
865
+ body?: unknown;
866
+ query?: Record<string, unknown>;
867
+ header?: Record<string, unknown>;
868
+ path?: Record<string, unknown>;
869
+ };
870
+
871
+ type RequiredKeys<T> = {
872
+ [P in keyof T]-?: undefined extends T[P] ? never : P;
873
+ }[keyof T];
874
+
875
+ type MaybeOptionalArg<T> = RequiredKeys<T> extends never ? [config?: T] : [config: T];
876
+
877
+ // </ApiClientTypes>
878
+
879
+ // <ApiClient>
880
+ export class TanstackQueryApiClient {
881
+ constructor(public client: ApiClient) { }
882
+
883
+ ${Array.from(endpointMethods).map((method) => `
884
+ // <ApiClient.${method}>
885
+ ${method}<Path extends keyof ${capitalize4(method)}Endpoints, TEndpoint extends ${capitalize4(method)}Endpoints[Path]>(
886
+ path: Path,
887
+ ...params: MaybeOptionalArg<TEndpoint["parameters"]>
888
+ ) {
889
+ const queryKey = createQueryKey(path, params[0]);
890
+ const query = {
891
+ endpoint: {} as TEndpoint,
892
+ res: {} as TEndpoint["response"],
893
+ queryKey,
894
+ options: queryOptions({
895
+ queryFn: async ({ queryKey, signal, }) => {
896
+ const res = await this.client.${method}(path, {
897
+ ...params,
898
+ ...queryKey[0],
899
+ signal,
900
+ throwOnError: true
901
+ });
902
+ return res as TEndpoint["response"];
903
+ },
904
+ queryKey: queryKey
905
+ }),
906
+ };
907
+
908
+ return query
909
+ }
910
+ // </ApiClient.get>
911
+ `).join("\n")}
912
+ }
913
+ `;
914
+ return prettify(file);
915
+ };
916
+
835
917
  export {
836
918
  unwrap,
837
919
  createFactory,
@@ -841,5 +923,7 @@ export {
841
923
  generateFile,
842
924
  createRefResolver,
843
925
  tsFactory,
844
- mapOpenApiEndpoints
926
+ mapOpenApiEndpoints,
927
+ prettify,
928
+ generateTanstackQueryFile
845
929
  };
package/dist/cli.d.ts CHANGED
@@ -1,2 +1,2 @@
1
1
 
2
- export { }
2
+ export { }
package/dist/cli.js CHANGED
@@ -1,41 +1,48 @@
1
1
  import {
2
2
  allowedRuntimes,
3
3
  generateFile,
4
- mapOpenApiEndpoints
5
- } from "./chunk-WT2PCM73.js";
4
+ generateTanstackQueryFile,
5
+ mapOpenApiEndpoints,
6
+ prettify
7
+ } from "./chunk-STLPDNLW.js";
6
8
 
7
9
  // src/cli.ts
8
10
  import SwaggerParser from "@apidevtools/swagger-parser";
9
11
  import { cac } from "cac";
10
- import { join } from "pathe";
12
+ import { basename, join } from "pathe";
11
13
  import { type } from "arktype";
12
14
  import { writeFile } from "fs/promises";
13
-
14
- // package.json
15
- var name = "typed-openapi";
16
- var version = "0.10.0";
17
-
18
- // src/cli.ts
15
+ import { readFileSync } from "fs";
16
+ var { name, version } = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8"));
19
17
  var cwd = process.cwd();
20
18
  var cli = cac(name);
21
19
  var now = /* @__PURE__ */ new Date();
22
- var optionsSchema = type({ "output?": "string", runtime: allowedRuntimes });
20
+ var optionsSchema = type({ "output?": "string", runtime: allowedRuntimes, tanstack: "boolean | string" });
23
21
  cli.command("<input>", "Generate").option("-o, --output <path>", "Output path for the api client ts file (defaults to `<input>.<runtime>.ts`)").option(
24
22
  "-r, --runtime <name>",
25
- `Runtime to use for validation; defaults to \`none\`; available: ${allowedRuntimes.definition}`,
23
+ `Runtime to use for validation; defaults to \`none\`; available: ${allowedRuntimes.toString()}`,
26
24
  { default: "none" }
27
- ).action(async (input, _options) => {
25
+ ).option("--tanstack [name]", "Generate tanstack client, defaults to false, can optionally specify a name for the generated file").action(async (input, _options) => {
28
26
  const options = optionsSchema.assert(_options);
29
27
  const openApiDoc = await SwaggerParser.bundle(input);
30
28
  const ctx = mapOpenApiEndpoints(openApiDoc);
31
29
  console.log(`Found ${ctx.endpointList.length} endpoints`);
32
- const content = generateFile({ ...ctx, runtime: options.runtime });
33
- const output = join(
30
+ const content = await prettify(generateFile({ ...ctx, runtime: options.runtime }));
31
+ const outputPath = join(
34
32
  cwd,
35
33
  options.output ?? input + `.${options.runtime === "none" ? "client" : options.runtime}.ts`
36
34
  );
37
- console.log("Generating...", output);
38
- await writeFile(output, content);
35
+ console.log("Generating client...", outputPath);
36
+ await writeFile(outputPath, content);
37
+ if (options.tanstack) {
38
+ const tanstackContent = await generateTanstackQueryFile({
39
+ ...ctx,
40
+ relativeApiClientPath: "./" + basename(outputPath)
41
+ });
42
+ const tanstackOutputPath = join(cwd, typeof options.tanstack === "string" ? options.tanstack : `tanstack.client.ts`);
43
+ console.log("Generating tanstack client...", tanstackOutputPath);
44
+ await writeFile(tanstackOutputPath, tanstackContent);
45
+ }
39
46
  console.log(`Done in ${(/* @__PURE__ */ new Date()).getTime() - now.getTime()}ms !`);
40
47
  });
41
48
  cli.help();
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import * as openapi3_ts_oas31 from 'openapi3-ts/oas31';
2
- import { OpenAPIObject, SchemaObject, ReferenceObject, OperationObject } from 'openapi3-ts/oas31';
3
- import * as arktype from 'arktype';
2
+ import { OpenAPIObject, ReferenceObject, SchemaObject, OperationObject } from 'openapi3-ts/oas31';
3
+ import { SchemaObject as SchemaObject$1 } from 'openapi3-ts/oas30';
4
+ import * as arktype_internal_methods_string_ts from 'arktype/internal/methods/string.ts';
4
5
  import * as Codegen from '@sinclair/typebox-codegen';
5
6
 
6
7
  declare class Box<T extends AnyBoxDef = AnyBoxDef> {
@@ -44,8 +45,8 @@ type RefInfo = {
44
45
  kind: "schemas" | "responses" | "parameters" | "requestBodies" | "headers";
45
46
  };
46
47
  declare const createRefResolver: (doc: OpenAPIObject, factory: GenericFactory) => {
47
- get: <T = SchemaObject>(ref: string) => NonNullable<T>;
48
- unwrap: <T_1 extends {} | ReferenceObject>(component: T_1) => Exclude<T_1, ReferenceObject>;
48
+ get: <T = LibSchemaObject>(ref: string) => NonNullable<T>;
49
+ unwrap: <T extends ReferenceObject | {}>(component: T) => Exclude<T, ReferenceObject>;
49
50
  getInfosByRef: (ref: string) => RefInfo;
50
51
  infos: Map<string, RefInfo>;
51
52
  /**
@@ -59,6 +60,7 @@ declare const createRefResolver: (doc: OpenAPIObject, factory: GenericFactory) =
59
60
  interface RefResolver extends ReturnType<typeof createRefResolver> {
60
61
  }
61
62
 
63
+ type LibSchemaObject = SchemaObject & SchemaObject$1;
62
64
  type BoxDefinition = {
63
65
  type: string;
64
66
  params: unknown;
@@ -66,7 +68,7 @@ type BoxDefinition = {
66
68
  };
67
69
  type BoxParams = string | BoxDefinition;
68
70
  type WithSchema = {
69
- schema: SchemaObject | ReferenceObject | undefined;
71
+ schema: LibSchemaObject | ReferenceObject | undefined;
70
72
  ctx: OpenapiSchemaConvertContext;
71
73
  };
72
74
  type BoxUnion = WithSchema & {
@@ -171,17 +173,17 @@ type GenericFactory = {
171
173
  };
172
174
 
173
175
  declare const unwrap: (param: StringOrBox) => string;
174
- declare const createFactory: <T extends GenericFactory | FactoryCreator>(f: T) => T;
176
+ declare const createFactory: <T extends OpenapiSchemaConvertContext["factory"]>(f: T) => T;
175
177
  /**
176
178
  * Create a box-factory using your schema provider and automatically add the input schema to each box.
177
179
  */
178
- declare const createBoxFactory: (schema: SchemaObject | ReferenceObject, ctx: OpenapiSchemaConvertContext) => BoxFactory;
180
+ declare const createBoxFactory: (schema: LibSchemaObject | ReferenceObject, ctx: OpenapiSchemaConvertContext) => BoxFactory;
179
181
 
180
182
  declare const mapOpenApiEndpoints: (doc: OpenAPIObject) => {
181
183
  doc: OpenAPIObject;
182
184
  refs: {
183
- get: <T = openapi3_ts_oas31.SchemaObject>(ref: string) => NonNullable<T>;
184
- unwrap: <T_1 extends {} | openapi3_ts_oas31.ReferenceObject>(component: T_1) => Exclude<T_1, openapi3_ts_oas31.ReferenceObject>;
185
+ get: <T = LibSchemaObject>(ref: string) => NonNullable<T>;
186
+ unwrap: <T extends openapi3_ts_oas31.ReferenceObject | {}>(component: T) => Exclude<T, openapi3_ts_oas31.ReferenceObject>;
185
187
  getInfosByRef: (ref: string) => RefInfo;
186
188
  infos: Map<string, RefInfo>;
187
189
  getOrderedSchemas: () => [schema: Box<AnyBoxDef>, infos: RefInfo][];
@@ -232,10 +234,10 @@ type Endpoint<TConfig extends DefaultEndpoint = DefaultEndpoint> = {
232
234
  response: TConfig["response"];
233
235
  };
234
236
 
235
- type GeneratorOptions = ReturnType<typeof mapOpenApiEndpoints> & {
237
+ type GeneratorOptions$1 = ReturnType<typeof mapOpenApiEndpoints> & {
236
238
  runtime?: "none" | keyof typeof runtimeValidationGenerator;
237
239
  };
238
- declare const allowedRuntimes: arktype.Type<"zod" | "arktype" | "typebox" | "valibot" | "yup" | "io-ts" | "none">;
240
+ declare const allowedRuntimes: arktype_internal_methods_string_ts.StringType<"none" | "arktype" | "io-ts" | "typebox" | "valibot" | "yup" | "zod", {}>;
239
241
  type OutputRuntime = typeof allowedRuntimes.infer;
240
242
  declare const runtimeValidationGenerator: {
241
243
  arktype: typeof Codegen.ModelToArkType.Generate;
@@ -245,7 +247,13 @@ declare const runtimeValidationGenerator: {
245
247
  yup: typeof Codegen.ModelToYup.Generate;
246
248
  zod: typeof Codegen.ModelToZod.Generate;
247
249
  };
248
- declare const generateFile: (options: GeneratorOptions) => string;
250
+ declare const generateFile: (options: GeneratorOptions$1) => string;
251
+
252
+ type GeneratorOptions = ReturnType<typeof mapOpenApiEndpoints>;
253
+ type GeneratorContext = Required<GeneratorOptions>;
254
+ declare const generateTanstackQueryFile: (ctx: GeneratorContext & {
255
+ relativeApiClientPath: string;
256
+ }) => Promise<string>;
249
257
 
250
258
  declare const openApiSchemaToTs: ({ schema, meta: _inheritedMeta, ctx }: OpenapiSchemaConvertArgs) => Box<AnyBoxDef>;
251
259
 
@@ -265,4 +273,4 @@ declare const tsFactory: {
265
273
  object: (props: Record<string, StringOrBox>) => string;
266
274
  };
267
275
 
268
- export { AnyBox, AnyBoxDef, BoxArray, BoxDefinition, BoxFactory, BoxIntersection, BoxKeyword, BoxLiteral, BoxObject, BoxOptional, BoxParams, BoxRef, BoxUnion, Endpoint, EndpointParameters, FactoryCreator, GenericFactory, OpenapiSchemaConvertArgs, OpenapiSchemaConvertContext, OutputRuntime, RefInfo, RefResolver, StringOrBox, WithSchema, createBoxFactory, createFactory, createRefResolver, generateFile, mapOpenApiEndpoints, openApiSchemaToTs, tsFactory, unwrap };
276
+ export { type AnyBox, type AnyBoxDef, type BoxArray, type BoxDefinition, type BoxFactory, type BoxIntersection, type BoxKeyword, type BoxLiteral, type BoxObject, type BoxOptional, type BoxParams, type BoxRef, type BoxUnion, type Endpoint, type EndpointParameters, type FactoryCreator, type GenericFactory, type LibSchemaObject, type OpenapiSchemaConvertArgs, type OpenapiSchemaConvertContext, type OutputRuntime, type RefInfo, type RefResolver, type StringOrBox, type WithSchema, createBoxFactory, createFactory, createRefResolver, generateFile, generateTanstackQueryFile, mapOpenApiEndpoints, openApiSchemaToTs, tsFactory, unwrap };
package/dist/index.js CHANGED
@@ -3,16 +3,18 @@ import {
3
3
  createFactory,
4
4
  createRefResolver,
5
5
  generateFile,
6
+ generateTanstackQueryFile,
6
7
  mapOpenApiEndpoints,
7
8
  openApiSchemaToTs,
8
9
  tsFactory,
9
10
  unwrap
10
- } from "./chunk-WT2PCM73.js";
11
+ } from "./chunk-STLPDNLW.js";
11
12
  export {
12
13
  createBoxFactory,
13
14
  createFactory,
14
15
  createRefResolver,
15
16
  generateFile,
17
+ generateTanstackQueryFile,
16
18
  mapOpenApiEndpoints,
17
19
  openApiSchemaToTs,
18
20
  tsFactory,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "typed-openapi",
3
3
  "type": "module",
4
- "version": "0.10.0",
4
+ "version": "1.0.0",
5
5
  "main": "dist/index.cjs",
6
6
  "module": "dist/index.js",
7
7
  "bin": {
@@ -13,24 +13,23 @@
13
13
  "directory": "packages/typed-openapi"
14
14
  },
15
15
  "dependencies": {
16
- "@apidevtools/swagger-parser": "^10.1.0",
17
- "@changesets/cli": "^2.26.2",
18
- "@sinclair/typebox-codegen": "^0.10.5",
19
- "arktype": "1.0.18-alpha",
16
+ "@apidevtools/swagger-parser": "^10.1.1",
17
+ "@sinclair/typebox-codegen": "^0.11.1",
18
+ "arktype": "2.1.20",
20
19
  "cac": "^6.7.14",
21
- "openapi3-ts": "^4.1.2",
20
+ "openapi3-ts": "^4.4.0",
22
21
  "pastable": "^2.2.1",
23
- "pathe": "^1.1.1",
24
- "prettier": "2.8.4",
25
- "ts-pattern": "^5.0.4"
22
+ "pathe": "^2.0.3",
23
+ "prettier": "3.5.3",
24
+ "ts-pattern": "^5.7.0"
26
25
  },
27
26
  "devDependencies": {
28
- "@types/node": "^20.4.5",
29
- "@types/prettier": "2.7.3",
30
- "tsup": "^7.1.0",
31
- "typescript": "^5.1.6",
32
- "vite-node": "^0.33.0",
33
- "vitest": "^0.33.0"
27
+ "@changesets/cli": "^2.29.4",
28
+ "@types/node": "^22.15.17",
29
+ "@types/prettier": "3.0.0",
30
+ "tsup": "^8.4.0",
31
+ "typescript": "^5.8.3",
32
+ "vitest": "^3.1.3"
34
33
  },
35
34
  "files": [
36
35
  "src",
@@ -60,6 +59,6 @@
60
59
  "dev": "tsup --watch",
61
60
  "build": "tsup",
62
61
  "test": "vitest",
63
- "typecheck": "tsc --noEmit"
62
+ "typecheck": "tsc -b ./tsconfig.build.json"
64
63
  }
65
64
  }
package/src/asserts.ts CHANGED
@@ -1,6 +1,6 @@
1
- import type { SchemaObject } from "openapi3-ts/oas31";
1
+ import type { LibSchemaObject } from "./types.ts";
2
2
 
3
- export type SingleType = Exclude<SchemaObject["type"], any[] | undefined>;
3
+ export type SingleType = Exclude<LibSchemaObject["type"], any[] | undefined>;
4
4
  export const isPrimitiveType = (type: unknown): type is PrimitiveType => primitiveTypeList.includes(type as any);
5
5
 
6
6
  const primitiveTypeList = ["string", "number", "integer", "boolean", "null"] as const;
@@ -1,6 +1,6 @@
1
- import type { ReferenceObject, SchemaObject } from "openapi3-ts/oas31";
2
- import { Box } from "./box";
3
- import { AnyBoxDef, BoxFactory, OpenapiSchemaConvertContext, StringOrBox } from "./types";
1
+ import type { ReferenceObject } from "openapi3-ts/oas31";
2
+ import { Box } from "./box.ts";
3
+ import { AnyBoxDef, BoxFactory, OpenapiSchemaConvertContext, StringOrBox, type LibSchemaObject } from "./types.ts";
4
4
 
5
5
  export const unwrap = (param: StringOrBox) => (typeof param === "string" ? param : param.value);
6
6
  export const createFactory = <T extends OpenapiSchemaConvertContext["factory"]>(f: T) => f;
@@ -8,7 +8,7 @@ export const createFactory = <T extends OpenapiSchemaConvertContext["factory"]>(
8
8
  /**
9
9
  * Create a box-factory using your schema provider and automatically add the input schema to each box.
10
10
  */
11
- export const createBoxFactory = (schema: SchemaObject | ReferenceObject, ctx: OpenapiSchemaConvertContext) => {
11
+ export const createBoxFactory = (schema: LibSchemaObject | ReferenceObject, ctx: OpenapiSchemaConvertContext) => {
12
12
  const f = typeof ctx.factory === "function" ? ctx.factory(schema, ctx) : ctx.factory;
13
13
  const callback = <T extends AnyBoxDef>(box: Box<T>) => {
14
14
  if (f.callback) {
package/src/box.ts CHANGED
@@ -1,5 +1,4 @@
1
- import { SchemaObject } from "openapi3-ts/oas31";
2
- import { openApiSchemaToTs } from "./openapi-schema-to-ts";
1
+ import { openApiSchemaToTs } from "./openapi-schema-to-ts.ts";
3
2
  import {
4
3
  AnyBoxDef,
5
4
  BoxArray,
@@ -11,7 +10,8 @@ import {
11
10
  BoxRef,
12
11
  BoxUnion,
13
12
  OpenapiSchemaConvertContext,
14
- } from "./types";
13
+ type LibSchemaObject,
14
+ } from "./types.ts";
15
15
 
16
16
  // TODO rename SchemaBox
17
17
  export class Box<T extends AnyBoxDef = AnyBoxDef> {
@@ -39,7 +39,7 @@ export class Box<T extends AnyBoxDef = AnyBoxDef> {
39
39
  }
40
40
 
41
41
  recompute(callback: OpenapiSchemaConvertContext["onBox"]) {
42
- return openApiSchemaToTs({ schema: this.schema as SchemaObject, ctx: { ...this.ctx, onBox: callback! } });
42
+ return openApiSchemaToTs({ schema: this.schema as LibSchemaObject, ctx: { ...this.ctx, onBox: callback! } });
43
43
  }
44
44
 
45
45
  static fromJSON(json: string) {