@sdk-it/typescript 0.3.1 → 0.5.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/dist/index.js CHANGED
@@ -30,20 +30,14 @@ async function writeFiles(dir, contents) {
30
30
  })
31
31
  );
32
32
  }
33
- async function getFolderExports(folder, extensions = ["ts"], keepExtensions = false) {
33
+ async function getFolderExports(folder, extensions = ["ts"]) {
34
34
  const files = await readdir(folder, { withFileTypes: true });
35
35
  const exports = [];
36
36
  for (const file of files) {
37
37
  if (file.isDirectory()) {
38
38
  exports.push(`export * from './${file.name}';`);
39
39
  } else if (file.name !== "index.ts" && extensions.includes(getExt(file.name))) {
40
- if (keepExtensions) {
41
- exports.push(`export * from './${file.name}';`);
42
- } else {
43
- exports.push(
44
- `export * from './${file.name.replace(`.${getExt(file.name)}`, "")}';`
45
- );
46
- }
40
+ exports.push(`export * from './${file.name}';`);
47
41
  }
48
42
  }
49
43
  return exports.join("\n");
@@ -74,10 +68,15 @@ import { get as get2, merge } from "lodash-es";
74
68
  import { camelcase as camelcase2, pascalcase as pascalcase2, spinalcase as spinalcase2 } from "stringcase";
75
69
 
76
70
  // packages/typescript/src/lib/json-zod.ts
77
- import { get } from "lodash";
71
+ import { get } from "lodash-es";
78
72
  function cleanRef(ref) {
79
73
  return ref.replace(/^#\//, "");
80
74
  }
75
+ function parseRef(ref) {
76
+ const parts = ref.split(ref);
77
+ const [model] = parts.splice(-1);
78
+ return { model, path: parts.join("/") };
79
+ }
81
80
  function followRef(spec, ref) {
82
81
  const pathParts = cleanRef(ref).split("/");
83
82
  const entry = get(spec, pathParts);
@@ -86,13 +85,13 @@ function followRef(spec, ref) {
86
85
  }
87
86
  return entry;
88
87
  }
89
- function jsonSchemaToZod(spec, schema, required = false, onRef, refProcessingStack = /* @__PURE__ */ new Set()) {
88
+ function jsonSchemaToZod(spec, schema, required = false, onRef, circularRefTracker = /* @__PURE__ */ new Set()) {
90
89
  if ("$ref" in schema) {
91
90
  const schemaName = cleanRef(schema.$ref).split("/").pop();
92
- if (refProcessingStack.has(schemaName)) {
91
+ if (circularRefTracker.has(schemaName)) {
93
92
  return schemaName;
94
93
  }
95
- refProcessingStack.add(schemaName);
94
+ circularRefTracker.add(schemaName);
96
95
  onRef(
97
96
  schemaName,
98
97
  jsonSchemaToZod(
@@ -100,35 +99,41 @@ function jsonSchemaToZod(spec, schema, required = false, onRef, refProcessingSta
100
99
  followRef(spec, schema.$ref),
101
100
  required,
102
101
  onRef,
103
- refProcessingStack
102
+ circularRefTracker
104
103
  )
105
104
  );
106
- refProcessingStack.delete(schemaName);
105
+ circularRefTracker.delete(schemaName);
107
106
  return schemaName;
108
107
  }
109
108
  if (schema.allOf && Array.isArray(schema.allOf)) {
110
109
  const allOfSchemas = schema.allOf.map(
111
- (sub) => jsonSchemaToZod(spec, sub, true, onRef, refProcessingStack)
110
+ (sub) => jsonSchemaToZod(spec, sub, true, onRef, circularRefTracker)
112
111
  );
113
- return `z.intersection(${allOfSchemas.join(", ")})`;
112
+ return allOfSchemas.length ? `z.intersection(${allOfSchemas.join(", ")})` : allOfSchemas[0];
114
113
  }
115
114
  if (schema.anyOf && Array.isArray(schema.anyOf)) {
116
115
  const anyOfSchemas = schema.anyOf.map(
117
- (sub) => jsonSchemaToZod(spec, sub, false, onRef, refProcessingStack)
116
+ (sub) => jsonSchemaToZod(spec, sub, false, onRef, circularRefTracker)
117
+ );
118
+ return anyOfSchemas.length > 1 ? `z.union([${anyOfSchemas.join(", ")}])${appendOptional(required)}` : (
119
+ // Handle an invalid anyOf with one schema
120
+ anyOfSchemas[0]
118
121
  );
119
- return `z.union([${anyOfSchemas.join(", ")}])${appendOptional(required)}`;
120
122
  }
121
123
  if (schema.oneOf && Array.isArray(schema.oneOf)) {
122
124
  const oneOfSchemas = schema.oneOf.map((sub) => {
123
125
  if ("$ref" in sub) {
124
- const refName = cleanRef(sub.$ref).split("/").pop();
125
- if (refProcessingStack.has(refName)) {
126
- return refName;
126
+ const { model } = parseRef(sub.$ref);
127
+ if (circularRefTracker.has(model)) {
128
+ return model;
127
129
  }
128
130
  }
129
- return jsonSchemaToZod(spec, sub, false, onRef, refProcessingStack);
131
+ return jsonSchemaToZod(spec, sub, false, onRef, circularRefTracker);
130
132
  });
131
- return `z.union([${oneOfSchemas.join(", ")}])${appendOptional(required)}`;
133
+ return oneOfSchemas.length > 1 ? `z.union([${oneOfSchemas.join(", ")}])${appendOptional(required)}` : (
134
+ // Handle an invalid oneOf with one schema
135
+ oneOfSchemas[0]
136
+ );
132
137
  }
133
138
  if (schema.enum && Array.isArray(schema.enum)) {
134
139
  const enumVals = schema.enum.map((val) => JSON.stringify(val)).join(", ");
@@ -147,12 +152,12 @@ function jsonSchemaToZod(spec, schema, required = false, onRef, refProcessingSta
147
152
  spec,
148
153
  false,
149
154
  onRef,
150
- refProcessingStack
155
+ circularRefTracker
151
156
  );
152
157
  return `${typeZod}.nullable()${appendOptional(required)}`;
153
158
  }
154
159
  const subSchemas = types.map(
155
- (t) => basicTypeToZod(t, schema, spec, false, onRef, refProcessingStack)
160
+ (t) => basicTypeToZod(t, schema, spec, false, onRef, circularRefTracker)
156
161
  );
157
162
  return `z.union([${subSchemas.join(", ")}])${appendOptional(required)}`;
158
163
  }
@@ -162,7 +167,7 @@ function jsonSchemaToZod(spec, schema, required = false, onRef, refProcessingSta
162
167
  spec,
163
168
  required,
164
169
  onRef,
165
- refProcessingStack
170
+ circularRefTracker
166
171
  );
167
172
  }
168
173
  function basicTypeToZod(type, schema, spec, required = false, onRef, refProcessingStack) {
@@ -317,32 +322,31 @@ function appendDefault(defaultValue) {
317
322
  }
318
323
 
319
324
  // packages/typescript/src/lib/sdk.ts
320
- import { camelcase } from "stringcase";
321
- import { pascalcase, spinalcase } from "stringcase";
325
+ import { camelcase, pascalcase, spinalcase } from "stringcase";
322
326
 
323
- // packages/typescript/src/lib/backend.ts
327
+ // packages/typescript/src/lib/client.ts
324
328
  import { titlecase } from "stringcase";
325
- var backend_default = (spec) => {
329
+ var client_default = (spec) => {
326
330
  const specOptions = {
327
331
  ...spec.options ?? {},
328
332
  fetch: {
329
- schema: "z.function().args(z.instanceof(Request)).returns(z.promise(z.instanceof(Response))).optional()"
333
+ schema: "fetchType"
330
334
  },
331
- baseUrl: { schema: "z.string().url()" }
335
+ baseUrl: {
336
+ schema: `z.enum(servers).default(servers[0])`
337
+ }
332
338
  };
333
339
  if (spec.securityScheme) {
334
340
  specOptions["token"] = { schema: "z.string().optional()" };
335
341
  }
336
342
  const defaultHeaders = spec.securityScheme ? `{Authorization: \`${titlecase(spec.securityScheme.bearerAuth.scheme)} \${this.options.token}\`}` : `{}`;
337
343
  return `
338
-
344
+ import { fetchType, sendRequest } from './http/send-request.ts';
339
345
  import z from 'zod';
340
- import type { Endpoints } from './endpoints';
341
- import type { StreamEndpoints } from './stream-endpoints';
342
- import schemas from './schemas';
343
- import { parse } from './parser';
344
- import { handleError, parseResponse } from './client';
346
+ import type { Endpoints } from './endpoints.ts';
347
+ import schemas from './schemas.ts';
345
348
 
349
+ const servers = ${JSON.stringify(spec.servers || [], null, 2)} as const;
346
350
  const optionsSchema = z.object(${toLitObject(specOptions, (x) => x.schema)});
347
351
  type ${spec.name}Options = z.infer<typeof optionsSchema>;
348
352
  export class ${spec.name} {
@@ -354,24 +358,11 @@ import { handleError, parseResponse } from './client';
354
358
  input: Endpoints[E]['input'],
355
359
  ): Promise<readonly [Endpoints[E]['output'], Endpoints[E]['error'] | null]> {
356
360
  const route = schemas[endpoint];
357
- const [parsedInput, parseError] = parse(route.schema, input);
358
- if (parseError) {
359
- return [
360
- null as never,
361
- { ...parseError, kind: 'parse' } as never,
362
- ] as const;
363
- }
364
- const request = route.toRequest(parsedInput as never, {
365
- headers: this.defaultHeaders,
361
+ return sendRequest(input, route, {
366
362
  baseUrl: this.options.baseUrl,
363
+ fetch: this.options.fetch,
364
+ headers: this.defaultHeaders,
367
365
  });
368
- const response = await (this.options.fetch ?? fetch)(request);
369
- if (response.ok) {
370
- const data = await parseResponse(response);
371
- return [data as Endpoints[E]['output'], null] as const;
372
- }
373
- const error = await handleError(response);
374
- return [null as never, { ...error, kind: 'response' }] as const;
375
366
  }
376
367
 
377
368
  get defaultHeaders() {
@@ -390,26 +381,13 @@ import { handleError, parseResponse } from './client';
390
381
  }`;
391
382
  };
392
383
 
393
- // packages/typescript/src/lib/client.txt
394
- var client_default = "import { parse } from 'fast-content-type-parse';\n\nimport type { Endpoints } from './endpoints';\n\nexport interface RequestInterface<D extends object = object> {\n /**\n * Sends a request based on endpoint options\n *\n * @param {string} route Request method + URL. Example: 'GET /orgs/{org}'\n * @param {object} [parameters] URL, query or body parameters, as well as headers, mediaType.{format|previews}, request, or baseUrl.\n */\n <R extends keyof Endpoints>(\n route: R,\n options?: Endpoints[R]['input'],\n ): Promise<Endpoints[R]['output']>;\n}\n\nexport async function handleError(response: Response) {\n try {\n if (response.status >= 400 && response.status < 500) {\n const body = (await response.json()) as Record<string, any>;\n return {\n status: response.status,\n body: body,\n };\n }\n return new Error(\n `An error occurred while fetching the data. Status: ${response.status}`,\n );\n } catch (error) {\n return error as any;\n }\n}\n\nasync function handleChunkedResponse(response: Response, contentType: string) {\n const { type } = parse(contentType);\n\n switch (type) {\n case 'application/json': {\n let buffer = '';\n const reader = response.body!.getReader();\n const decoder = new TextDecoder();\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value);\n }\n return JSON.parse(buffer);\n }\n case 'text/html':\n case 'text/plain': {\n let buffer = '';\n const reader = response.body!.getReader();\n const decoder = new TextDecoder();\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value);\n }\n return buffer;\n }\n default:\n return response.body;\n }\n}\n\nexport async function parseResponse(response: Response) {\n const contentType = response.headers.get('Content-Type');\n if (!contentType) {\n throw new Error('Content-Type header is missing');\n }\n\n if (response.status === 204) {\n return null;\n }\n const isChunked = response.headers.get('Transfer-Encoding') === 'chunked';\n if (isChunked) {\n return response.body!;\n // return handleChunkedResponse(response, contentType);\n }\n\n const { type } = parse(contentType);\n switch (type) {\n case 'application/json':\n return response.json();\n case 'text/plain':\n return response.text();\n case 'text/html':\n return response.text();\n case 'text/xml':\n case 'application/xml':\n return response.text();\n case 'application/x-www-form-urlencoded':\n const text = await response.text();\n return Object.fromEntries(new URLSearchParams(text));\n case 'multipart/form-data':\n return response.formData();\n default:\n throw new Error(`Unsupported content type: ${contentType}`);\n }\n}\n";
395
-
396
- // packages/typescript/src/lib/parser.txt
397
- var parser_default = "import { z } from 'zod';\n\nexport type ParseError<T extends z.ZodType<any, any, any>> = {\n kind: 'parse';\n} & z.inferFlattenedErrors<T>;\n\nexport function parse<T extends z.ZodType>(\n schema: T,\n input: unknown,\n) {\n const result = schema.safeParse(input);\n if (!result.success) {\n const errors = result.error.flatten((issue) => issue);\n return [null, errors];\n }\n return [result.data as z.infer<T>, null];\n}\n";
398
-
399
- // packages/typescript/src/lib/request.txt
400
- var request_default = "type Method = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\ntype ContentType = 'xml' | 'json' | 'urlencoded' | 'multipart';\ntype Endpoint = `${ContentType} ${Method} ${string}` | `${Method} ${string}`;\n\nexport function createUrl(base: string, path: string, query: URLSearchParams) {\n const url = new URL(path, base);\n url.search = query.toString();\n return url;\n}\nfunction template(\n templateString: string,\n templateVariables: Record<string, any>,\n): string {\n const nargs = /{([0-9a-zA-Z_]+)}/g;\n return templateString.replace(nargs, (match, key: string, index: number) => {\n // Handle escaped double braces\n if (\n templateString[index - 1] === '{' &&\n templateString[index + match.length] === '}'\n ) {\n return key;\n }\n\n const result = key in templateVariables ? templateVariables[key] : null;\n return result === null || result === undefined ? '' : String(result);\n });\n}\n\ninterface ToRequest {\n <T extends Endpoint>(\n endpoint: T,\n input: Record<string, any>,\n props: {\n inputHeaders: string[];\n inputQuery: string[];\n inputBody: string[];\n inputParams: string[];\n },\n defaults: {\n baseUrl: string;\n headers?: Record<string, string>;\n },\n ): Request;\n urlencoded: <T extends Endpoint>(\n endpoint: T,\n input: Record<string, any>,\n props: {\n inputHeaders: string[];\n inputQuery: string[];\n inputBody: string[];\n inputParams: string[];\n },\n defaults: {\n baseUrl: string;\n headers?: Record<string, string>;\n },\n ) => Request;\n}\n\nfunction _json(\n input: Record<string, any>,\n props: {\n inputHeaders: string[];\n inputQuery: string[];\n inputBody: string[];\n inputParams: string[];\n },\n) {\n const headers = new Headers({});\n for (const header of props.inputHeaders) {\n headers.set(header, input[header]);\n }\n\n const body: Record<string, any> = {};\n for (const prop of props.inputBody) {\n body[prop] = input[prop];\n }\n\n const query = new URLSearchParams();\n for (const key of props.inputQuery) {\n const value = input[key];\n if (value !== undefined) {\n query.set(key, String(value));\n }\n }\n\n const params = props.inputParams.reduce<Record<string, any>>((acc, key) => {\n acc[key] = input[key];\n return acc;\n }, {});\n\n return {\n body: JSON.stringify(body),\n query,\n params,\n headers: { 'Content-Type': 'application/json', Accept: 'application/json' },\n };\n}\n\ntype Input = Record<string, any>;\ntype Props = {\n inputHeaders: string[];\n inputQuery: string[];\n inputBody: string[];\n inputParams: string[];\n};\n\nabstract class Serializer {\n constructor(\n protected input: Input,\n protected props: Props,\n ) {}\n abstract getBody(): BodyInit | null;\n abstract getHeaders(): Record<string, string>;\n serialize(): Serialized {\n const headers = new Headers({});\n for (const header of this.props.inputHeaders) {\n headers.set(header, this.input[header]);\n }\n\n const query = new URLSearchParams();\n for (const key of this.props.inputQuery) {\n const value = this.input[key];\n if (value !== undefined) {\n query.set(key, String(value));\n }\n }\n\n const params = this.props.inputParams.reduce<Record<string, any>>(\n (acc, key) => {\n acc[key] = this.input[key];\n return acc;\n },\n {},\n );\n\n return {\n body: this.getBody(),\n query,\n params,\n headers: this.getHeaders(),\n };\n }\n}\n\ninterface Serialized {\n body: BodyInit | null;\n query: URLSearchParams;\n params: Record<string, any>;\n headers: Record<string, string>;\n}\n\nclass JsonSerializer extends Serializer {\n getBody(): BodyInit | null {\n const body: Record<string, any> = {};\n for (const prop of this.props.inputBody) {\n body[prop] = this.input[prop];\n }\n return JSON.stringify(body);\n }\n getHeaders(): Record<string, string> {\n return {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n };\n }\n}\n\nclass UrlencodedSerializer extends Serializer {\n getBody(): BodyInit | null {\n const body = new URLSearchParams();\n for (const prop of this.props.inputBody) {\n body.set(prop, this.input[prop]);\n }\n return body;\n }\n getHeaders(): Record<string, string> {\n return {};\n }\n}\n\nclass FormDataSerializer extends Serializer {\n getBody(): BodyInit | null {\n const body = new FormData();\n for (const prop of this.props.inputBody) {\n body.append(prop, this.input[prop]);\n }\n return body;\n }\n getHeaders(): Record<string, string> {\n return {};\n }\n}\n\nexport function json(input: Input, props: Props) {\n return new JsonSerializer(input, props).serialize();\n}\nexport function urlencoded(input: Input, props: Props) {\n return new UrlencodedSerializer(input, props).serialize();\n}\nexport function formdata(input: Input, props: Props) {\n return new FormDataSerializer(input, props).serialize();\n}\n\nexport function _urlencoded(\n input: Record<string, any>,\n props: {\n inputHeaders: string[];\n inputQuery: string[];\n inputBody: string[];\n inputParams: string[];\n },\n) {\n const headers = new Headers({});\n for (const header of props.inputHeaders) {\n headers.set(header, input[header]);\n }\n\n const body = new URLSearchParams();\n for (const prop of props.inputBody) {\n body.set(prop, input[prop]);\n }\n\n const query = new URLSearchParams();\n for (const key of props.inputQuery) {\n const value = input[key];\n if (value !== undefined) {\n query.set(key, String(value));\n }\n }\n\n const params = props.inputParams.reduce<Record<string, any>>((acc, key) => {\n acc[key] = input[key];\n return acc;\n }, {});\n\n return {\n body,\n query,\n params,\n headers: {},\n };\n}\n\nexport function toRequest<T extends Endpoint>(\n endpoint: T,\n input: Serialized,\n defaults: {\n baseUrl: string;\n headers?: Record<string, string>;\n },\n): Request {\n const [method, path] = endpoint.split(' ');\n\n const headers = new Headers({\n ...defaults?.headers,\n ...input.headers,\n });\n const pathVariable = template(path, input.params);\n\n const url = createUrl(defaults.baseUrl, pathVariable, input.query);\n return new Request(url, {\n method: method,\n headers: headers,\n body: method === 'GET' ? undefined : input.body,\n });\n}\n";
401
-
402
- // packages/typescript/src/lib/response.txt
403
- var response_default = "export interface ApiResponse<Status extends number, Body extends unknown> {\n kind: 'response';\n status: Status;\n body: Body;\n}\n\n// 4xx Client Errors\nexport type BadRequest = ApiResponse<400, { message: string }>;\nexport type Unauthorized = ApiResponse<401, { message: string }>;\nexport type PaymentRequired = ApiResponse<402, { message: string }>;\nexport type Forbidden = ApiResponse<403, { message: string }>;\nexport type NotFound = ApiResponse<404, { message: string }>;\nexport type MethodNotAllowed = ApiResponse<405, { message: string }>;\nexport type NotAcceptable = ApiResponse<406, { message: string }>;\nexport type Conflict = ApiResponse<409, { message: string }>;\nexport type Gone = ApiResponse<410, { message: string }>;\nexport type UnprocessableEntity = ApiResponse<422, { message: string; errors?: Record<string, string[]> }>;\nexport type TooManyRequests = ApiResponse<429, { message: string; retryAfter?: string }>;\nexport type PayloadTooLarge = ApiResponse<413, { message: string; }>;\nexport type UnsupportedMediaType = ApiResponse<415, { message: string; }>;\n\n// 5xx Server Errors\nexport type InternalServerError = ApiResponse<500, { message: string }>;\nexport type NotImplemented = ApiResponse<501, { message: string }>;\nexport type BadGateway = ApiResponse<502, { message: string }>;\nexport type ServiceUnavailable = ApiResponse<503, { message: string; retryAfter?: string }>;\nexport type GatewayTimeout = ApiResponse<504, { message: string }>;\n\nexport type ClientError =\n | BadRequest\n | Unauthorized\n | PaymentRequired\n | Forbidden\n | NotFound\n | MethodNotAllowed\n | NotAcceptable\n | Conflict\n | Gone\n | UnprocessableEntity\n | TooManyRequests;\n\nexport type ServerError =\n | InternalServerError\n | NotImplemented\n | BadGateway\n | ServiceUnavailable\n | GatewayTimeout;\n\nexport type ProblematicResponse = ClientError | ServerError;\n";
404
-
405
384
  // packages/typescript/src/lib/sdk.ts
406
385
  var SchemaEndpoint = class {
407
386
  #imports = [
408
387
  `import z from 'zod';`,
409
- 'import type { Endpoints } from "./endpoints";',
410
- 'import type { StreamEndpoints } from "./stream-endpoints";',
411
- `import { toRequest, json, urlencoded, formdata, createUrl } from './request';`,
412
- `import type { ParseError } from './parser';`
388
+ 'import type { Endpoints } from "./endpoints.ts";',
389
+ `import { toRequest, json, urlencoded, formdata, createUrl } from './http/request.ts';`,
390
+ `import type { ParseError } from './http/parser.ts';`
413
391
  ];
414
392
  #endpoints = [];
415
393
  addEndpoint(endpoint, operation) {
@@ -428,7 +406,7 @@ ${this.#endpoints.join("\n")}
428
406
  var Emitter = class {
429
407
  imports = [
430
408
  `import z from 'zod';`,
431
- `import type { ParseError } from './parser';`
409
+ `import type { ParseError } from './http/parser.ts';`
432
410
  ];
433
411
  endpoints = [];
434
412
  addEndpoint(endpoint, operation) {
@@ -463,13 +441,13 @@ function generateClientSdk(spec) {
463
441
  const featureSchemaFileName = camelcase(name);
464
442
  schemas[featureSchemaFileName] = [`import z from 'zod';`];
465
443
  emitter.addImport(
466
- `import * as ${featureSchemaFileName} from './inputs/${featureSchemaFileName}';`
444
+ `import * as ${featureSchemaFileName} from './inputs/${featureSchemaFileName}.ts';`
467
445
  );
468
446
  streamEmitter.addImport(
469
- `import * as ${featureSchemaFileName} from './inputs/${featureSchemaFileName}';`
447
+ `import * as ${featureSchemaFileName} from './inputs/${featureSchemaFileName}.ts';`
470
448
  );
471
449
  schemaEndpoint.addImport(
472
- `import * as ${featureSchemaFileName} from './inputs/${featureSchemaFileName}';`
450
+ `import * as ${featureSchemaFileName} from './inputs/${featureSchemaFileName}.ts';`
473
451
  );
474
452
  for (const operation of operations) {
475
453
  const schemaName = camelcase(`${operation.name} schema`);
@@ -565,7 +543,7 @@ function generateClientSdk(spec) {
565
543
  }
566
544
  }
567
545
  emitter.addImport(
568
- `import type { ${removeDuplicates(errors, (it) => it).join(", ")} } from './response';`
546
+ `import type { ${removeDuplicates(errors, (it) => it).join(", ")} } from './http/response.ts';`
569
547
  );
570
548
  return {
571
549
  ...Object.fromEntries(
@@ -573,20 +551,15 @@ function generateClientSdk(spec) {
573
551
  `inputs/${key}.ts`,
574
552
  [
575
553
  schemasImports.length ? `import {${removeDuplicates(schemasImports, (it) => it)}} from '../zod';` : "",
576
- spec.commonZod ? 'import * as commonZod from "../zod";' : "",
554
+ spec.commonZod ? 'import * as commonZod from "../zod.ts";' : "",
577
555
  ...value
578
556
  ].map((it) => it.trim()).filter(Boolean).join("\n") + "\n"
579
557
  // add a newline at the end
580
558
  ])
581
559
  ),
582
- "backend.ts": backend_default(spec),
583
- "parser.ts": parser_default,
584
- "client.ts": client_default,
585
- "request.ts": request_default,
560
+ "backend.ts": client_default(spec),
586
561
  "schemas.ts": schemaEndpoint.complete(),
587
- "endpoints.ts": emitter.complete(),
588
- "stream-endpoints.ts": streamEmitter.complete(),
589
- "response.ts": response_default
562
+ "endpoints.ts": emitter.complete()
590
563
  };
591
564
  }
592
565
 
@@ -820,6 +793,24 @@ function importsToString(imports) {
820
793
  });
821
794
  }
822
795
 
796
+ // packages/typescript/src/lib/http/client.txt
797
+ var client_default2 = "import { parse } from 'fast-content-type-parse';\n\nexport async function handleError(response: Response) {\n try {\n if (response.status >= 400 && response.status < 500) {\n const body = (await response.json()) as Record<string, any>;\n return {\n status: response.status,\n body: body,\n };\n }\n return new Error(\n `An error occurred while fetching the data. Status: ${response.status}`,\n );\n } catch (error) {\n return error as any;\n }\n}\n\nasync function handleChunkedResponse(response: Response, contentType: string) {\n const { type } = parse(contentType);\n\n switch (type) {\n case 'application/json': {\n let buffer = '';\n const reader = response.body!.getReader();\n const decoder = new TextDecoder();\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value);\n }\n return JSON.parse(buffer);\n }\n case 'text/html':\n case 'text/plain': {\n let buffer = '';\n const reader = response.body!.getReader();\n const decoder = new TextDecoder();\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value);\n }\n return buffer;\n }\n default:\n return response.body;\n }\n}\n\nexport async function parseResponse(response: Response) {\n const contentType = response.headers.get('Content-Type');\n if (!contentType) {\n throw new Error('Content-Type header is missing');\n }\n\n if (response.status === 204) {\n return null;\n }\n const isChunked = response.headers.get('Transfer-Encoding') === 'chunked';\n if (isChunked) {\n return response.body!;\n // return handleChunkedResponse(response, contentType);\n }\n\n const { type } = parse(contentType);\n switch (type) {\n case 'application/json':\n return response.json();\n case 'text/plain':\n return response.text();\n case 'text/html':\n return response.text();\n case 'text/xml':\n case 'application/xml':\n return response.text();\n case 'application/x-www-form-urlencoded': {\n const text = await response.text();\n return Object.fromEntries(new URLSearchParams(text));\n }\n case 'multipart/form-data':\n return response.formData();\n default:\n throw new Error(`Unsupported content type: ${contentType}`);\n }\n}\n";
798
+
799
+ // packages/typescript/src/lib/http/parser.txt
800
+ var parser_default = "import { z } from 'zod';\n\nexport type ParseError<T extends z.ZodType<any, any, any>> = {\n kind: 'parse';\n} & z.inferFlattenedErrors<T>;\n\nexport function parse<T extends z.ZodType>(\n schema: T,\n input: unknown,\n) {\n const result = schema.safeParse(input);\n if (!result.success) {\n const errors = result.error.flatten((issue) => issue);\n return [null, errors];\n }\n return [result.data as z.infer<T>, null];\n}\n";
801
+
802
+ // packages/typescript/src/lib/http/request.txt
803
+ var request_default = "type Method = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\ntype ContentType = 'xml' | 'json' | 'urlencoded' | 'multipart';\ntype Endpoint = `${ContentType} ${Method} ${string}` | `${Method} ${string}`;\n\nexport function createUrl(base: string, path: string, query: URLSearchParams) {\n const url = new URL(path, base);\n url.search = query.toString();\n return url;\n}\nfunction template(\n templateString: string,\n templateVariables: Record<string, any>,\n): string {\n const nargs = /{([0-9a-zA-Z_]+)}/g;\n return templateString.replace(nargs, (match, key: string, index: number) => {\n // Handle escaped double braces\n if (\n templateString[index - 1] === '{' &&\n templateString[index + match.length] === '}'\n ) {\n return key;\n }\n\n const result = key in templateVariables ? templateVariables[key] : null;\n return result === null || result === undefined ? '' : String(result);\n });\n}\n\ninterface ToRequest {\n <T extends Endpoint>(\n endpoint: T,\n input: Record<string, any>,\n props: {\n inputHeaders: string[];\n inputQuery: string[];\n inputBody: string[];\n inputParams: string[];\n },\n defaults: {\n baseUrl: string;\n headers?: Record<string, string>;\n },\n ): Request;\n urlencoded: <T extends Endpoint>(\n endpoint: T,\n input: Record<string, any>,\n props: {\n inputHeaders: string[];\n inputQuery: string[];\n inputBody: string[];\n inputParams: string[];\n },\n defaults: {\n baseUrl: string;\n headers?: Record<string, string>;\n },\n ) => Request;\n}\n\nfunction _json(\n input: Record<string, any>,\n props: {\n inputHeaders: string[];\n inputQuery: string[];\n inputBody: string[];\n inputParams: string[];\n },\n) {\n const headers = new Headers({});\n for (const header of props.inputHeaders) {\n headers.set(header, input[header]);\n }\n\n const body: Record<string, any> = {};\n for (const prop of props.inputBody) {\n body[prop] = input[prop];\n }\n\n const query = new URLSearchParams();\n for (const key of props.inputQuery) {\n const value = input[key];\n if (value !== undefined) {\n query.set(key, String(value));\n }\n }\n\n const params = props.inputParams.reduce<Record<string, any>>((acc, key) => {\n acc[key] = input[key];\n return acc;\n }, {});\n\n return {\n body: JSON.stringify(body),\n query,\n params,\n headers: { 'Content-Type': 'application/json', Accept: 'application/json' },\n };\n}\n\ntype Input = Record<string, any>;\ntype Props = {\n inputHeaders: string[];\n inputQuery: string[];\n inputBody: string[];\n inputParams: string[];\n};\n\nabstract class Serializer {\n constructor(\n protected input: Input,\n protected props: Props,\n ) {}\n abstract getBody(): BodyInit | null;\n abstract getHeaders(): Record<string, string>;\n serialize(): Serialized {\n const headers = new Headers({});\n for (const header of this.props.inputHeaders) {\n headers.set(header, this.input[header]);\n }\n\n const query = new URLSearchParams();\n for (const key of this.props.inputQuery) {\n const value = this.input[key];\n if (value !== undefined) {\n query.set(key, String(value));\n }\n }\n\n const params = this.props.inputParams.reduce<Record<string, any>>(\n (acc, key) => {\n acc[key] = this.input[key];\n return acc;\n },\n {},\n );\n\n return {\n body: this.getBody(),\n query,\n params,\n headers: this.getHeaders(),\n };\n }\n}\n\ninterface Serialized {\n body: BodyInit | null;\n query: URLSearchParams;\n params: Record<string, any>;\n headers: Record<string, string>;\n}\n\nclass JsonSerializer extends Serializer {\n getBody(): BodyInit | null {\n const body: Record<string, any> = {};\n for (const prop of this.props.inputBody) {\n body[prop] = this.input[prop];\n }\n return JSON.stringify(body);\n }\n getHeaders(): Record<string, string> {\n return {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n };\n }\n}\n\nclass UrlencodedSerializer extends Serializer {\n getBody(): BodyInit | null {\n const body = new URLSearchParams();\n for (const prop of this.props.inputBody) {\n body.set(prop, this.input[prop]);\n }\n return body;\n }\n getHeaders(): Record<string, string> {\n return {};\n }\n}\n\nclass FormDataSerializer extends Serializer {\n getBody(): BodyInit | null {\n const body = new FormData();\n for (const prop of this.props.inputBody) {\n body.append(prop, this.input[prop]);\n }\n return body;\n }\n getHeaders(): Record<string, string> {\n return {};\n }\n}\n\nexport function json(input: Input, props: Props) {\n return new JsonSerializer(input, props).serialize();\n}\nexport function urlencoded(input: Input, props: Props) {\n return new UrlencodedSerializer(input, props).serialize();\n}\nexport function formdata(input: Input, props: Props) {\n return new FormDataSerializer(input, props).serialize();\n}\n\nexport function _urlencoded(\n input: Record<string, any>,\n props: {\n inputHeaders: string[];\n inputQuery: string[];\n inputBody: string[];\n inputParams: string[];\n },\n) {\n const headers = new Headers({});\n for (const header of props.inputHeaders) {\n headers.set(header, input[header]);\n }\n\n const body = new URLSearchParams();\n for (const prop of props.inputBody) {\n body.set(prop, input[prop]);\n }\n\n const query = new URLSearchParams();\n for (const key of props.inputQuery) {\n const value = input[key];\n if (value !== undefined) {\n query.set(key, String(value));\n }\n }\n\n const params = props.inputParams.reduce<Record<string, any>>((acc, key) => {\n acc[key] = input[key];\n return acc;\n }, {});\n\n return {\n body,\n query,\n params,\n headers: {},\n };\n}\n\nexport function toRequest<T extends Endpoint>(\n endpoint: T,\n input: Serialized,\n defaults: {\n baseUrl: string;\n headers?: Record<string, string>;\n },\n): Request {\n const [method, path] = endpoint.split(' ');\n\n const headers = new Headers({\n ...defaults?.headers,\n ...input.headers,\n });\n const pathVariable = template(path, input.params);\n\n const url = createUrl(defaults.baseUrl, pathVariable, input.query);\n return new Request(url, {\n method: method,\n headers: headers,\n body: method === 'GET' ? undefined : input.body,\n });\n}\n";
804
+
805
+ // packages/typescript/src/lib/http/response.txt
806
+ var response_default = "export interface ApiResponse<Status extends number, Body extends unknown> {\n kind: 'response';\n status: Status;\n body: Body;\n}\n\n// 4xx Client Errors\nexport type BadRequest = ApiResponse<400, { message: string }>;\nexport type Unauthorized = ApiResponse<401, { message: string }>;\nexport type PaymentRequired = ApiResponse<402, { message: string }>;\nexport type Forbidden = ApiResponse<403, { message: string }>;\nexport type NotFound = ApiResponse<404, { message: string }>;\nexport type MethodNotAllowed = ApiResponse<405, { message: string }>;\nexport type NotAcceptable = ApiResponse<406, { message: string }>;\nexport type Conflict = ApiResponse<409, { message: string }>;\nexport type Gone = ApiResponse<410, { message: string }>;\nexport type UnprocessableEntity = ApiResponse<422, { message: string; errors?: Record<string, string[]> }>;\nexport type TooManyRequests = ApiResponse<429, { message: string; retryAfter?: string }>;\nexport type PayloadTooLarge = ApiResponse<413, { message: string; }>;\nexport type UnsupportedMediaType = ApiResponse<415, { message: string; }>;\n\n// 5xx Server Errors\nexport type InternalServerError = ApiResponse<500, { message: string }>;\nexport type NotImplemented = ApiResponse<501, { message: string }>;\nexport type BadGateway = ApiResponse<502, { message: string }>;\nexport type ServiceUnavailable = ApiResponse<503, { message: string; retryAfter?: string }>;\nexport type GatewayTimeout = ApiResponse<504, { message: string }>;\n\nexport type ClientError =\n | BadRequest\n | Unauthorized\n | PaymentRequired\n | Forbidden\n | NotFound\n | MethodNotAllowed\n | NotAcceptable\n | Conflict\n | Gone\n | UnprocessableEntity\n | TooManyRequests;\n\nexport type ServerError =\n | InternalServerError\n | NotImplemented\n | BadGateway\n | ServiceUnavailable\n | GatewayTimeout;\n\nexport type ProblematicResponse = ClientError | ServerError;\n";
807
+
808
+ // packages/typescript/src/lib/http/send-request.txt
809
+ var send_request_default = "import z from 'zod';\n\nimport { handleError, parseResponse } from './parse-response.ts';\nimport { parse } from './parser.ts';\n\nexport interface RequestSchema {\n schema: z.ZodType;\n toRequest: (\n input: any,\n init: { baseUrl: string; headers?: Record<string, string> },\n ) => any;\n}\n\nexport const fetchType = z\n .function()\n .args(z.instanceof(Request))\n .returns(z.promise(z.instanceof(Response)))\n .optional();\n\nexport async function sendRequest(\n input: any,\n route: RequestSchema,\n options: {\n baseUrl: string;\n fetch?: z.infer<typeof fetchType>;\n headers?: Record<string, string>;\n },\n) {\n const [parsedInput, parseError] = parse(route.schema, input);\n if (parseError) {\n return [null as never, { ...parseError, kind: 'parse' } as never] as const;\n }\n const request = route.toRequest(parsedInput as never, {\n headers: options.headers,\n baseUrl: options.baseUrl,\n });\n const response = await (options.fetch ?? fetch)(request);\n if (response.ok) {\n const data = await parseResponse(response);\n return [data, null] as const;\n }\n const error = await handleError(response);\n return [null as never, { ...error, kind: 'response' }] as const;\n}\n";
810
+
811
+ // packages/typescript/src/lib/readme-generator.ts
812
+ import { pascalcase as pascalcase3 } from "stringcase";
813
+
823
814
  // packages/typescript/src/lib/generate.ts
824
815
  async function generate(spec, settings) {
825
816
  const { commonSchemas, groups, outputs } = generateCode({
@@ -828,12 +819,21 @@ async function generate(spec, settings) {
828
819
  target: "javascript"
829
820
  });
830
821
  const clientFiles = generateClientSdk({
831
- name: "Client",
832
- groups
822
+ name: settings.name || "Client",
823
+ groups,
824
+ servers: spec.servers?.map((server) => server.url) || []
833
825
  });
834
826
  await writeFiles(settings.output, {
835
827
  "outputs/index.ts": "",
836
828
  "inputs/index.ts": ""
829
+ // 'README.md': readme,
830
+ });
831
+ await writeFiles(join(settings.output, "http"), {
832
+ "parse-response.ts": client_default2,
833
+ "send-request.ts": send_request_default,
834
+ "response.ts": response_default,
835
+ "parser.ts": parser_default,
836
+ "request.ts": request_default
837
837
  });
838
838
  await writeFiles(join(settings.output, "outputs"), outputs);
839
839
  await writeFiles(settings.output, {
@@ -841,15 +841,17 @@ async function generate(spec, settings) {
841
841
  "zod.ts": `import z from 'zod';
842
842
  ${Object.entries(commonSchemas).map(([name, schema]) => `export const ${name} = ${schema};`).join("\n")}`
843
843
  });
844
- const [index, outputIndex, inputsIndex] = await Promise.all([
844
+ const [index, outputIndex, inputsIndex, httpIndex] = await Promise.all([
845
845
  getFolderExports(settings.output),
846
846
  getFolderExports(join(settings.output, "outputs")),
847
- getFolderExports(join(settings.output, "inputs"))
847
+ getFolderExports(join(settings.output, "inputs")),
848
+ getFolderExports(join(settings.output, "http"))
848
849
  ]);
849
850
  await writeFiles(settings.output, {
850
851
  "index.ts": index,
851
852
  "outputs/index.ts": outputIndex,
852
- "inputs/index.ts": inputsIndex
853
+ "inputs/index.ts": inputsIndex,
854
+ "http/index.ts": httpIndex
853
855
  });
854
856
  }
855
857
  export {
package/dist/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
- "sources": ["../src/lib/generate.ts", "../../core/src/lib/deriver.ts", "../../core/src/lib/program.ts", "../../core/src/lib/paths.ts", "../../core/src/lib/file-system.ts", "../../core/src/index.ts", "../src/lib/generator.ts", "../src/lib/json-zod.ts", "../src/lib/sdk.ts", "../src/lib/backend.ts", "../src/lib/client.txt", "../src/lib/parser.txt", "../src/lib/request.txt", "../src/lib/response.txt"],
4
- "sourcesContent": ["import { join } from 'node:path';\nimport type { OpenAPIObject } from 'openapi3-ts/oas31';\n\nimport { getFolderExports, writeFiles } from '@sdk-it/core';\n\nimport { generateCode } from './generator.ts';\nimport { generateClientSdk } from './sdk.ts';\n\nexport async function generate(\n spec: OpenAPIObject,\n settings: {\n output: string;\n },\n) {\n const { commonSchemas, groups, outputs } = generateCode({\n spec,\n style: 'github',\n target: 'javascript',\n });\n const clientFiles = generateClientSdk({\n name: 'Client',\n groups: groups,\n });\n await writeFiles(settings.output, {\n 'outputs/index.ts': '',\n 'inputs/index.ts': '',\n });\n await writeFiles(join(settings.output, 'outputs'), outputs);\n await writeFiles(settings.output, {\n ...clientFiles,\n 'zod.ts': `import z from 'zod';\\n${Object.entries(commonSchemas)\n .map(([name, schema]) => `export const ${name} = ${schema};`)\n .join('\\n')}`,\n });\n\n const [index, outputIndex, inputsIndex] = await Promise.all([\n getFolderExports(settings.output),\n getFolderExports(join(settings.output, 'outputs')),\n getFolderExports(join(settings.output, 'inputs')),\n ]);\n\n await writeFiles(settings.output, {\n 'index.ts': index,\n 'outputs/index.ts': outputIndex,\n 'inputs/index.ts': inputsIndex,\n });\n}\n", "import ts, { TypeFlags, symbolName } from 'typescript';\n\ntype Collector = Record<string, any>;\nexport const deriveSymbol = Symbol.for('serialize');\nexport const $types = Symbol.for('types');\nconst defaults: Record<string, string> = {\n ReadableStream: 'any',\n DateConstructor: 'string',\n ArrayBufferConstructor: 'any',\n SharedArrayBufferConstructor: 'any',\n Int8ArrayConstructor: 'any',\n Uint8Array: 'any',\n};\nexport class TypeDeriver {\n public readonly collector: Collector = {};\n public readonly checker: ts.TypeChecker;\n constructor(checker: ts.TypeChecker) {\n this.checker = checker;\n }\n\n serializeType(type: ts.Type): any {\n if (type.flags & TypeFlags.Any) {\n return {\n [deriveSymbol]: true,\n optional: false,\n [$types]: [],\n };\n }\n if (type.flags & ts.TypeFlags.Boolean) {\n return {\n [deriveSymbol]: true,\n optional: false,\n [$types]: ['boolean'],\n };\n }\n if (type.isIntersection()) {\n let optional: boolean | undefined;\n const types: any[] = [];\n for (const unionType of type.types) {\n if (optional === undefined) {\n optional = (unionType.flags & ts.TypeFlags.Undefined) !== 0;\n if (optional) {\n continue;\n }\n }\n\n types.push(this.serializeType(unionType));\n }\n return {\n [deriveSymbol]: true,\n kind: 'intersection',\n optional,\n [$types]: types,\n };\n }\n if (type.isUnion()) {\n let optional: boolean | undefined;\n const types: any[] = [];\n for (const unionType of type.types) {\n if (optional === undefined) {\n optional = (unionType.flags & ts.TypeFlags.Undefined) !== 0;\n if (optional) {\n continue;\n }\n }\n\n types.push(this.serializeType(unionType));\n }\n return {\n [deriveSymbol]: true,\n kind: 'union',\n optional,\n [$types]: types,\n };\n }\n if (this.checker.isArrayLikeType(type)) {\n const [argType] = this.checker.getTypeArguments(type as ts.TypeReference);\n if (!argType) {\n const typeName = type.symbol?.getName() || '<unknown>';\n console.warn(\n `Could not find generic type argument for array type ${typeName}`,\n );\n return {\n [deriveSymbol]: true,\n optional: false,\n kind: 'array',\n [$types]: ['any'],\n };\n }\n const typeSymbol = argType.getSymbol();\n if (!typeSymbol) {\n console.warn(\n `No symbol found for array type ${this.checker.typeToString(argType)}`,\n );\n const typeString = this.checker.typeToString(argType);\n return {\n [deriveSymbol]: true,\n optional: false,\n kind: 'array',\n [$types]: typeString === 'undefined' ? [] : [typeString],\n };\n }\n\n if (typeSymbol.valueDeclaration) {\n return {\n kind: 'array',\n ...this.serializeNode(typeSymbol.valueDeclaration),\n };\n }\n const maybeDeclaration = typeSymbol.declarations?.[0];\n if (maybeDeclaration) {\n if (ts.isMappedTypeNode(maybeDeclaration)) {\n const resolvedType = this.checker\n .getPropertiesOfType(argType)\n .reduce<Record<string, unknown>>((acc, prop) => {\n const propType = this.checker.getTypeOfSymbol(prop);\n acc[prop.name] = this.serializeType(propType);\n return acc;\n }, {});\n return {\n kind: 'array',\n optional: false,\n [deriveSymbol]: true,\n [$types]: [resolvedType],\n };\n } else {\n return {\n kind: 'array',\n ...this.serializeNode(maybeDeclaration),\n };\n }\n }\n\n return {\n kind: 'array',\n optional: false,\n [deriveSymbol]: true,\n [$types]: ['any'],\n };\n }\n if (type.isClass()) {\n const declaration = type.symbol?.valueDeclaration;\n if (!declaration) {\n return {\n [deriveSymbol]: true,\n optional: false,\n [$types]: [type.symbol.getName()],\n };\n }\n return this.serializeNode(declaration);\n }\n if (isInterfaceType(type)) {\n const valueDeclaration =\n type.symbol.valueDeclaration ?? type.symbol.declarations?.[0];\n if (!valueDeclaration) {\n return {\n [deriveSymbol]: true,\n optional: false,\n [$types]: [type.symbol.getName()],\n };\n }\n return this.serializeNode(valueDeclaration);\n }\n if (type.flags & TypeFlags.Object) {\n if (defaults[symbolName(type.symbol)]) {\n return {\n [deriveSymbol]: true,\n optional: false,\n [$types]: [defaults[type.symbol.name]],\n };\n }\n const properties = this.checker.getPropertiesOfType(type);\n if (properties.length > 0) {\n const serializedProps: Record<string, any> = {};\n for (const prop of properties) {\n if (\n (prop.getDeclarations() ?? []).some((it) =>\n ts.isPropertySignature(it),\n )\n ) {\n const propType = this.checker.getTypeOfSymbol(prop);\n serializedProps[prop.name] = this.serializeType(propType);\n }\n }\n return {\n [deriveSymbol]: true,\n kind: 'object',\n optional: false,\n [$types]: [serializedProps],\n };\n }\n const declaration =\n type.symbol.valueDeclaration ?? type.symbol.declarations?.[0];\n if (!declaration) {\n return {\n [deriveSymbol]: true,\n optional: false,\n [$types]: [type.symbol.getName()],\n };\n }\n return this.serializeNode(declaration);\n }\n\n return {\n [deriveSymbol]: true,\n optional: false,\n [$types]: [\n this.checker.typeToString(\n type,\n undefined,\n ts.TypeFormatFlags.NoTruncation,\n ),\n ],\n };\n }\n\n serializeNode(node: ts.Node): any {\n if (ts.isObjectLiteralExpression(node)) {\n const symbolType = this.checker.getTypeAtLocation(node);\n const props: Record<string, any> = {};\n for (const symbol of symbolType.getProperties()) {\n const type = this.checker.getTypeOfSymbol(symbol);\n props[symbol.name] = this.serializeType(type);\n }\n return props;\n }\n if (ts.isPropertyAccessExpression(node)) {\n const symbol = this.checker.getSymbolAtLocation(node.name);\n if (!symbol) {\n console.warn(`No symbol found for ${node.name.getText()}`);\n return null;\n }\n const type = this.checker.getTypeOfSymbol(symbol);\n return this.serializeType(type);\n }\n if (ts.isPropertySignature(node)) {\n const symbol = this.checker.getSymbolAtLocation(node.name);\n if (!symbol) {\n console.warn(`No symbol found for ${node.name.getText()}`);\n return null;\n }\n const type = this.checker.getTypeOfSymbol(symbol);\n return this.serializeType(type);\n }\n if (ts.isPropertyDeclaration(node)) {\n const symbol = this.checker.getSymbolAtLocation(node.name);\n if (!symbol) {\n console.warn(`No symbol found for ${node.name.getText()}`);\n return null;\n }\n const type = this.checker.getTypeOfSymbol(symbol);\n return this.serializeType(type);\n }\n if (ts.isInterfaceDeclaration(node)) {\n if (!node.name?.text) {\n throw new Error('Interface has no name');\n }\n console.log(node.name.text);\n if (defaults[node.name.text]) {\n return {\n [deriveSymbol]: true,\n optional: false,\n [$types]: [defaults[node.name.text]],\n };\n }\n if (!this.collector[node.name.text]) {\n this.collector[node.name.text] = {};\n const members: Record<string, any> = {};\n for (const member of node.members.filter(ts.isPropertySignature)) {\n members[member.name.getText()] = this.serializeNode(member);\n }\n this.collector[node.name.text] = members;\n }\n return {\n [deriveSymbol]: true,\n optional: false,\n [$types]: [`#/components/schemas/${node.name.text}`],\n };\n }\n if (ts.isClassDeclaration(node)) {\n if (!node.name?.text) {\n throw new Error('Class has no name');\n }\n if (defaults[node.name.text]) {\n return {\n [deriveSymbol]: true,\n optional: false,\n [$types]: [defaults[node.name.text]],\n };\n }\n\n if (!this.collector[node.name.text]) {\n this.collector[node.name.text] = {};\n const members: Record<string, unknown> = {};\n for (const member of node.members.filter(ts.isPropertyDeclaration)) {\n members[member.name!.getText()] = this.serializeNode(member);\n }\n this.collector[node.name.text] = members;\n }\n return {\n [deriveSymbol]: true,\n optional: false,\n [$types]: [`#/components/schemas/${node.name.text}`],\n $ref: `#/components/schemas/${node.name.text}`,\n };\n }\n if (ts.isVariableDeclaration(node)) {\n const symbol = this.checker.getSymbolAtLocation(node.name);\n if (!symbol) {\n console.warn(`No symbol found for ${node.name.getText()}`);\n return null;\n }\n if (!node.type) {\n console.warn(`No type found for ${node.name.getText()}`);\n return 'any';\n }\n const type = this.checker.getTypeFromTypeNode(node.type);\n return this.serializeType(type);\n }\n if (ts.isIdentifier(node)) {\n const symbol = this.checker.getSymbolAtLocation(node);\n if (!symbol) {\n console.warn(`Identifer: No symbol found for ${node.getText()}`);\n return null;\n }\n const type = this.checker.getTypeAtLocation(node);\n return this.serializeType(type);\n }\n if (ts.isAwaitExpression(node)) {\n const type = this.checker.getTypeAtLocation(node);\n return this.serializeType(type);\n }\n if (ts.isCallExpression(node)) {\n const type = this.checker.getTypeAtLocation(node);\n return this.serializeType(type);\n }\n if (ts.isAsExpression(node)) {\n const type = this.checker.getTypeAtLocation(node);\n return this.serializeType(type);\n }\n if (ts.isTypeLiteralNode(node)) {\n const symbolType = this.checker.getTypeAtLocation(node);\n const props: Record<string, unknown> = {};\n for (const symbol of symbolType.getProperties()) {\n const type = this.checker.getTypeOfSymbol(symbol);\n props[symbol.name] = this.serializeType(type);\n }\n return {\n [deriveSymbol]: true,\n optional: false,\n [$types]: [props],\n };\n }\n if (node.kind === ts.SyntaxKind.NullKeyword) {\n return {\n [deriveSymbol]: true,\n optional: true,\n [$types]: ['null'],\n };\n }\n if (node.kind === ts.SyntaxKind.BooleanKeyword) {\n return {\n [deriveSymbol]: true,\n optional: false,\n [$types]: ['boolean'],\n };\n }\n if (\n node.kind === ts.SyntaxKind.TrueKeyword ||\n node.kind === ts.SyntaxKind.FalseKeyword\n ) {\n return {\n [deriveSymbol]: true,\n optional: false,\n [$types]: ['boolean'],\n };\n }\n\n console.warn(`Unhandled node: ${ts.SyntaxKind[node.kind]} ${node.flags}`);\n return {\n [deriveSymbol]: true,\n optional: false,\n [$types]: ['any'],\n };\n }\n}\n\nfunction isInterfaceType(type: ts.Type): boolean {\n if (type.isClassOrInterface()) {\n // Check if it's an interface\n return !!(type.symbol.flags & ts.SymbolFlags.Interface);\n }\n return false;\n}\n", "import debug from 'debug';\nimport { dirname, join } from 'node:path';\nimport ts from 'typescript';\n\n\n\n\n\nconst logger = debug('january:client');\n\nexport function parseTsConfig(tsconfigPath: string) {\n logger(`Using TypeScript version: ${ts.version}`);\n const configContent = ts.readConfigFile(tsconfigPath, ts.sys.readFile);\n\n if (configContent.error) {\n console.error(\n `Failed to read tsconfig file:`,\n ts.formatDiagnosticsWithColorAndContext([configContent.error], {\n getCanonicalFileName: (path) => path,\n getCurrentDirectory: ts.sys.getCurrentDirectory,\n getNewLine: () => ts.sys.newLine,\n }),\n );\n throw new Error('Failed to parse tsconfig.json');\n }\n\n const parsed = ts.parseJsonConfigFileContent(\n configContent.config,\n ts.sys,\n dirname(tsconfigPath),\n );\n\n if (parsed.errors.length > 0) {\n console.error(\n `Errors found in tsconfig.json:`,\n ts.formatDiagnosticsWithColorAndContext(parsed.errors, {\n getCanonicalFileName: (path) => path,\n getCurrentDirectory: ts.sys.getCurrentDirectory,\n getNewLine: () => ts.sys.newLine,\n }),\n );\n throw new Error('Failed to parse tsconfig.json');\n }\n return parsed;\n}\nexport function getProgram(tsconfigPath: string) {\n const tsConfigParseResult = parseTsConfig(tsconfigPath);\n logger(`Parsing tsconfig`);\n return ts.createProgram({\n options: {\n ...tsConfigParseResult.options,\n noEmit: true,\n incremental: true,\n tsBuildInfoFile: join(dirname(tsconfigPath), './.tsbuildinfo'), // not working atm\n },\n rootNames: tsConfigParseResult.fileNames,\n projectReferences: tsConfigParseResult.projectReferences,\n configFileParsingDiagnostics: tsConfigParseResult.errors,\n });\n}\nexport function getPropertyAssignment(node: ts.Node, name: string) {\n if (ts.isObjectLiteralExpression(node)) {\n return node.properties\n .filter((prop) => ts.isPropertyAssignment(prop))\n .find((prop) => prop.name!.getText() === name);\n }\n return undefined;\n}\nexport function isCallExpression(\n node: ts.Node,\n name: string,\n): node is ts.CallExpression {\n return (\n ts.isCallExpression(node) &&\n node.expression &&\n ts.isIdentifier(node.expression) &&\n node.expression.text === name\n );\n}\n\nexport function isInterfaceType(type: ts.Type): boolean {\n if (type.isClassOrInterface()) {\n // Check if it's an interface\n return !!(type.symbol.flags & ts.SymbolFlags.Interface);\n }\n return false;\n}", "import type {\n OperationObject,\n ParameterObject,\n PathsObject,\n ResponseObject,\n ResponsesObject,\n SchemaObject,\n} from 'openapi3-ts/oas31';\n\nimport { $types } from './deriver.ts';\n\nexport type Method = 'get' | 'post' | 'put' | 'patch' | 'delete';\n\nexport type SemanticSource =\n | 'query'\n | 'queries'\n | 'body'\n | 'params'\n | 'headers';\n\nconst semanticSourceToOpenAPI = {\n queries: 'query',\n query: 'query',\n headers: 'header',\n params: 'path',\n} as const;\nexport interface Selector {\n name: string;\n select: string;\n against: string;\n source: SemanticSource;\n nullable: boolean;\n required: boolean;\n}\n\nexport interface ResponseItem {\n statusCode: string;\n response?: DateType;\n contentType: string;\n headers: string[];\n}\n\nexport class Paths {\n #commonZodImport?: string;\n #operations: Array<{\n name: string;\n path: string;\n method: Method;\n selectors: Selector[];\n responses: ResponsesObject;\n tags?: string[];\n description?: string;\n }> = [];\n\n constructor(config: { commonZodImport?: string }) {\n this.#commonZodImport = config.commonZodImport;\n }\n\n addPath(\n name: string,\n path: string,\n method: Method,\n selectors: Selector[],\n responses: ResponseItem[],\n tags?: string[],\n description?: string,\n ) {\n const responsesObject = this.#responseItemToResponses(responses);\n this.#operations.push({\n name,\n path,\n method,\n selectors,\n responses: responsesObject,\n tags,\n description,\n });\n return this;\n }\n\n #responseItemToResponses(responses: ResponseItem[]): ResponsesObject {\n const responsesObject: ResponsesObject = {};\n for (const item of responses) {\n const ct = item.contentType;\n const schema = item.response ? toSchema(item.response) : {};\n if (!responsesObject[item.statusCode]) {\n responsesObject[item.statusCode] = {\n description: `Response for ${item.statusCode}`,\n content: {\n [ct]:\n ct === 'application/octet-stream'\n ? { schema: { type: 'string', format: 'binary' } }\n : { schema },\n },\n headers: item.headers.length\n ? item.headers.reduce(\n (acc, header) => ({\n ...acc,\n [header]: { schema: { type: 'string' } },\n }),\n {},\n )\n : undefined,\n } satisfies ResponseObject;\n } else {\n if (!responsesObject[item.statusCode].content[ct]) {\n responsesObject[item.statusCode].content[ct] = { schema };\n } else {\n const existing = responsesObject[item.statusCode].content[ct]\n .schema as SchemaObject;\n if (existing.oneOf) {\n if (\n !existing.oneOf.find(\n (it) => JSON.stringify(it) === JSON.stringify(schema),\n )\n ) {\n existing.oneOf.push(schema);\n }\n } else if (JSON.stringify(existing) !== JSON.stringify(schema)) {\n responsesObject[item.statusCode].content[ct].schema = {\n oneOf: [existing, schema],\n };\n }\n }\n }\n }\n return responsesObject;\n }\n\n async #selectosToParameters(selectors: Selector[]) {\n const parameters: ParameterObject[] = [];\n const bodySchemaProps: Record<string, SchemaObject> = {};\n for (const selector of selectors) {\n if (selector.source === 'body') {\n bodySchemaProps[selector.name] = await evalZod(\n selector.against,\n this.#commonZodImport,\n );\n continue;\n }\n\n const parameter: ParameterObject = {\n in: semanticSourceToOpenAPI[selector.source],\n name: selector.name,\n required: selector.required,\n schema: await evalZod(selector.against, this.#commonZodImport),\n };\n parameters.push(parameter);\n }\n return { parameters, bodySchemaProps };\n }\n\n async getPaths() {\n const operations: PathsObject = {};\n for (const operation of this.#operations) {\n const { path, method, selectors } = operation;\n const { parameters, bodySchemaProps } =\n await this.#selectosToParameters(selectors);\n const operationObject: OperationObject = {\n operationId: operation.name,\n parameters,\n tags: operation.tags,\n description: operation.description,\n requestBody: Object.keys(bodySchemaProps).length\n ? {\n content: {\n 'application/json': {\n schema: {\n type: 'object',\n properties: bodySchemaProps,\n },\n },\n },\n }\n : undefined,\n responses: operation.responses,\n };\n if (!operations[path]) {\n operations[path] = {};\n }\n operations[path][method] = operationObject;\n }\n return operations;\n }\n}\n\nasync function evalZod(schema: string, commonZodImport?: string) {\n const lines = [\n `import { z } from 'zod';`,\n commonZodImport ? `import * as commonZod from '${commonZodImport}'` : '',\n `import { zodToJsonSchema } from 'zod-to-json-schema';`,\n `const schema = ${schema.replace('.optional()', '')};`,\n `const jsonSchema = zodToJsonSchema(schema, {\n\t\t\t$refStrategy: 'root',\n\t\t\tbasePath: ['#', 'components', 'schemas']\n\t\t});`,\n `export default jsonSchema;`,\n ];\n const base64Code = Buffer.from(lines.join('\\n')).toString('base64');\n const dataUrl = `data:text/javascript;base64,${base64Code}`;\n return import(dataUrl)\n .then((mod) => mod.default)\n .then(({ $schema, ...result }) => result);\n}\n\nconst typeMappings: Record<string, string> = {\n DateConstructor: 'Date',\n};\n\ninterface DateType {\n [$types]: any[];\n kind: string;\n optional: boolean;\n}\n\nexport function toSchema(data: DateType | string | null | undefined): any {\n if (data === null || data === undefined) {\n return { type: 'any' };\n } else if (typeof data === 'string') {\n const isRef = data.startsWith('#');\n if (isRef) {\n return { $ref: data };\n }\n return {\n type: `${typeMappings[data] || data}`,\n };\n } else if (data.kind === 'array') {\n const items = data[$types].map(toSchema);\n return { type: 'array', items: data[$types].length ? items[0] : {} };\n } else if (data.kind === 'union') {\n return { oneOf: data[$types].map(toSchema) };\n } else if (data.kind === 'intersection') {\n return { allOf: data[$types].map(toSchema) };\n } else if ($types in data) {\n return data[$types].map(toSchema)[0] ?? {};\n } else {\n const props: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n props[key] = toSchema(value as any);\n }\n return {\n type: 'object',\n properties: props,\n additionalProperties: false,\n };\n }\n}\n\nexport function isHttpMethod(name: string): name is Method {\n return ['get', 'post', 'put', 'delete', 'patch'].includes(name);\n}\n", "import { mkdir, readFile, readdir, stat, writeFile } from 'node:fs/promises';\nimport { dirname, isAbsolute, join } from 'node:path';\n\nexport async function getFile(filePath: string) {\n if (await exist(filePath)) {\n return readFile(filePath, 'utf-8');\n }\n return null;\n}\n\nexport async function exist(file: string): Promise<boolean> {\n return stat(file)\n .then(() => true)\n .catch(() => false);\n}\n\nexport async function readFolder(path: string) {\n if (await exist(path)) {\n return readdir(path);\n }\n return [] as string[];\n}\n\nexport async function writeFiles(\n dir: string,\n contents: Record<\n string,\n string | { content: string; ignoreIfExists?: boolean }\n >,\n) {\n return Promise.all(\n Object.entries(contents).map(async ([file, content]) => {\n const filePath = isAbsolute(file) ? file : join(dir, file);\n await mkdir(dirname(filePath), { recursive: true });\n if (typeof content === 'string') {\n await writeFile(filePath, content, 'utf-8');\n } else {\n if (content.ignoreIfExists) {\n if (!(await exist(filePath))) {\n await writeFile(filePath, content.content, 'utf-8');\n }\n }\n }\n }),\n );\n}\n\nexport async function getFolderExports(\n folder: string,\n extensions = ['ts'],\n keepExtensions = false,\n) {\n const files = await readdir(folder, { withFileTypes: true });\n const exports: string[] = [];\n for (const file of files) {\n if (file.isDirectory()) {\n exports.push(`export * from './${file.name}';`);\n } else if (\n file.name !== 'index.ts' &&\n extensions.includes(getExt(file.name))\n ) {\n if (keepExtensions) {\n exports.push(`export * from './${file.name}';`);\n } else {\n exports.push(\n `export * from './${file.name.replace(`.${getExt(file.name)}`, '')}';`,\n );\n }\n }\n }\n return exports.join('\\n');\n}\n\nexport const getExt = (fileName?: string) => {\n if (!fileName) {\n return ''; // shouldn't happen as there will always be a file name\n }\n const lastDot = fileName.lastIndexOf('.');\n if (lastDot === -1) {\n return '';\n }\n const ext = fileName\n .slice(lastDot + 1)\n .split('/')\n .filter(Boolean)\n .join('');\n if (ext === fileName) {\n // files that have no extension\n return '';\n }\n return ext || 'txt';\n};\n", "export * from './lib/deriver.ts';\nexport * from './lib/program.ts';\nexport * from './lib/paths.ts';\nexport * from './lib/file-system.ts';\n\nexport function removeDuplicates<T>(\n data: T[],\n accessor: (item: T) => T[keyof T],\n): T[] {\n return [...new Map(data.map((x) => [accessor(x), x])).values()];\n}\n\nexport type InferRecordValue<T> = T extends Record<string, infer U> ? U : any;\n\nexport function toLitObject<T extends Record<string, any>>(\n obj: T,\n accessor: (value: InferRecordValue<T>) => string = (value) => value,\n) {\n return `{${Object.keys(obj)\n .map((key) => `${key}: ${accessor(obj[key])}`)\n .join(', ')}}`;\n}\n", "import { get, merge } from 'lodash-es';\nimport type {\n ContentObject,\n OpenAPIObject,\n OperationObject,\n ReferenceObject,\n ResponseObject,\n} from 'openapi3-ts/oas31';\nimport { camelcase, pascalcase, spinalcase } from 'stringcase';\n\nimport { removeDuplicates } from '@sdk-it/core';\n\nimport { followRef, jsonSchemaToZod } from './json-zod.ts';\nimport { type Operation, type Spec } from './sdk.ts';\n\nexport interface NamedImport {\n name: string;\n alias?: string;\n isTypeOnly: boolean;\n}\nexport interface Import {\n isTypeOnly: boolean;\n moduleSpecifier: string;\n defaultImport: string | undefined;\n namedImports: NamedImport[];\n namespaceImport: string | undefined;\n}\nfunction isRef(obj: any): obj is ReferenceObject {\n return '$ref' in obj;\n}\n\nconst responses: Record<string, string> = {\n '400': 'BadRequest',\n '401': 'Unauthorized',\n '402': 'PaymentRequired',\n '403': 'Forbidden',\n '404': 'NotFound',\n '405': 'MethodNotAllowed',\n '406': 'NotAcceptable',\n '409': 'Conflict',\n '413': 'PayloadTooLarge',\n '410': 'Gone',\n '422': 'UnprocessableEntity',\n '429': 'TooManyRequests',\n '500': 'InternalServerError',\n '501': 'NotImplemented',\n '502': 'BadGateway',\n '503': 'ServiceUnavailable',\n '504': 'GatewayTimeout',\n};\n\nexport interface GenerateSdkConfig {\n spec: OpenAPIObject;\n target?: 'javascript';\n /**\n * No support for jsdoc in vscode\n * @issue https://github.com/microsoft/TypeScript/issues/38106\n */\n style?: 'github';\n operationId?: (\n operation: OperationObject,\n path: string,\n method: string,\n ) => string;\n}\n\nexport const defaults: Partial<GenerateSdkConfig> &\n Required<Pick<GenerateSdkConfig, 'operationId'>> = {\n target: 'javascript',\n style: 'github',\n operationId: (operation, path, method) => {\n if (operation.operationId) {\n return spinalcase(operation.operationId);\n }\n return (\n operation.operationId ||\n camelcase(`${method} ${path.replace(/\\//g, ' ')}`)\n );\n },\n};\n\nexport function generateCode(config: GenerateSdkConfig) {\n const groups: Spec['groups'] = {};\n const commonSchemas: Record<string, string> = {};\n const outputs: Record<string, string> = {};\n\n for (const [path, methods] of Object.entries(config.spec.paths ?? {})) {\n for (const [method, operation] of Object.entries(methods) as [\n string,\n OperationObject,\n ][]) {\n const formatOperationId = config.operationId ?? defaults.operationId;\n const operationName = formatOperationId(operation, path, method);\n\n console.log(`Processing ${method} ${path}`);\n const groupName = (operation.tags ?? ['unknown'])[0];\n groups[groupName] ??= [];\n const inputs: Operation['inputs'] = {};\n const imports: Import[] = [];\n\n const additionalProperties = [];\n for (const param of operation.parameters ?? []) {\n if (isRef(param)) {\n throw new Error(`Found reference in parameter ${param.$ref}`);\n }\n if (!param.schema) {\n throw new Error(`Schema not found for parameter ${param.name}`);\n }\n inputs[param.name] = {\n source: param.in,\n schema: '',\n };\n additionalProperties.push(param);\n }\n\n const types: Record<string, string> = {};\n const shortContenTypeMap: Record<string, string> = {\n 'application/json': 'json',\n 'application/x-www-form-urlencoded': 'urlencoded',\n 'multipart/form-data': 'formdata',\n 'application/xml': 'xml',\n 'text/plain': 'text',\n };\n let contentType: string | undefined;\n if (operation.requestBody && Object.keys(operation.requestBody).length) {\n const content: ContentObject = isRef(operation.requestBody)\n ? get(followRef(config.spec, operation.requestBody.$ref), ['content'])\n : operation.requestBody.content;\n\n for (const type in content) {\n const schema = isRef(content[type].schema)\n ? followRef(config.spec, content[type].schema.$ref)\n : content[type].schema;\n\n types[shortContenTypeMap[type]] = jsonSchemaToZod(\n config.spec,\n merge(schema, {\n required: additionalProperties\n .filter((p) => p.required)\n .map((p) => p.name),\n properties: additionalProperties.reduce<Record<string, any>>(\n (acc, p) => ({\n ...acc,\n [p.name]: p.schema,\n }),\n {},\n ),\n }),\n true,\n (schemaName, zod) => {\n commonSchemas[schemaName] = zod;\n imports.push({\n defaultImport: undefined,\n isTypeOnly: false,\n moduleSpecifier: '../zod',\n namedImports: [{ isTypeOnly: false, name: schemaName }],\n namespaceImport: undefined,\n });\n },\n );\n }\n\n if (content['application/json']) {\n contentType = 'json';\n } else if (content['application/x-www-form-urlencoded']) {\n contentType = 'urlencoded';\n } else if (content['multipart/form-data']) {\n contentType = 'formdata';\n } else {\n contentType = 'json';\n }\n } else {\n types[shortContenTypeMap['application/json']] = jsonSchemaToZod(\n config.spec,\n {\n type: 'object',\n required: additionalProperties\n .filter((p) => p.required)\n .map((p) => p.name),\n properties: additionalProperties.reduce<Record<string, any>>(\n (acc, p) => ({\n ...acc,\n [p.name]: p.schema,\n }),\n {},\n ),\n },\n true,\n (schemaName, zod) => {\n commonSchemas[schemaName] = zod;\n imports.push({\n defaultImport: undefined,\n isTypeOnly: false,\n moduleSpecifier: './zod',\n namedImports: [{ isTypeOnly: false, name: schemaName }],\n namespaceImport: undefined,\n });\n },\n );\n }\n\n const errors: string[] = [];\n operation.responses ??= {};\n\n let foundResponse = false;\n const output = [`import z from 'zod';`];\n for (const status in operation.responses) {\n const response = operation.responses[status] as ResponseObject;\n const statusCode = +status;\n if (statusCode >= 400) {\n errors.push(responses[status] ?? 'ProblematicResponse');\n }\n if (statusCode >= 200 && statusCode < 300) {\n foundResponse = true;\n const responseContent = get(response, ['content']);\n const isJson = responseContent && responseContent['application/json'];\n // TODO: how the user is going to handle multiple response types\n const responseSchema = isJson\n ? jsonSchemaToZod(\n config.spec,\n responseContent['application/json'].schema!,\n true,\n (schemaName, zod) => {\n commonSchemas[schemaName] = zod;\n imports.push({\n defaultImport: undefined,\n isTypeOnly: false,\n moduleSpecifier: '../zod',\n namedImports: [{ isTypeOnly: false, name: schemaName }],\n namespaceImport: undefined,\n });\n },\n )\n : 'z.instanceof(ReadableStream)'; // non-json response treated as stream\n\n output.push(\n importsToString(mergeImports(Object.values(imports).flat())).join(\n '\\n',\n ),\n );\n output.push(\n `export const ${pascalcase(operationName + ' output')} = ${responseSchema}`,\n );\n }\n }\n\n if (!foundResponse) {\n output.push(\n `export const ${pascalcase(operationName + ' output')} = z.void()`,\n );\n }\n outputs[`${spinalcase(operationName)}.ts`] = output.join('\\n');\n groups[groupName].push({\n name: operationName,\n type: 'http',\n imports: mergeImports(Object.values(imports).flat()),\n inputs,\n errors: errors.length ? errors : ['ServerError'],\n contentType,\n schemas: types,\n formatOutput: () => ({\n import: pascalcase(operationName + ' output'),\n use: `z.infer<typeof ${pascalcase(operationName + ' output')}>`,\n }),\n trigger: {\n path,\n method,\n },\n });\n }\n }\n\n return { groups, commonSchemas, outputs };\n}\n\n// TODO - USE CASES\n// 1. Some parameters conflicts with request body\n// 2. Generate 400 and 500 response variations // done\n// 3. Generate 200 response variations\n// 3. Doc Security\n// 4. Operation Security\n// 5. JsDocs\n// 5. test all different types of parameters\n// 6. cookies\n// 6. x-www-form-urlencoded // done\n// 7. multipart/form-data // done\n// 7. application/octet-stream // done\n// 7. chunked response // done\n// we need to remove the stream fn in the backend\n\nfunction mergeImports(imports: Import[]) {\n const merged: Record<string, Import> = {};\n\n for (const i of imports) {\n merged[i.moduleSpecifier] = merged[i.moduleSpecifier] ?? {\n moduleSpecifier: i.moduleSpecifier,\n defaultImport: i.defaultImport,\n namespaceImport: i.namespaceImport,\n namedImports: [],\n };\n if (i.namedImports) {\n merged[i.moduleSpecifier].namedImports.push(...i.namedImports);\n }\n }\n\n return Object.values(merged);\n}\n\nfunction importsToString(imports: Import[]) {\n return imports.map((i) => {\n if (i.defaultImport) {\n return `import ${i.defaultImport} from '${i.moduleSpecifier}'`;\n }\n if (i.namespaceImport) {\n return `import * as ${i.namespaceImport} from '${i.moduleSpecifier}'`;\n }\n if (i.namedImports) {\n return `import {${removeDuplicates(i.namedImports, (it) => it.name)\n .map((n) => n.name)\n .join(', ')}} from '${i.moduleSpecifier}'`;\n }\n throw new Error(`Invalid import ${JSON.stringify(i)}`);\n });\n}\n", "import { get } from 'lodash';\nimport type {\n OpenAPIObject,\n ReferenceObject,\n SchemaObject,\n} from 'openapi3-ts/oas31';\n\n/**\n * Recursively resolve a $ref in the OpenAPI spec.\n */\n\nfunction cleanRef(ref: string) {\n return ref.replace(/^#\\//, '');\n}\nexport function followRef(\n spec: OpenAPIObject,\n ref: string,\n): SchemaObject | ReferenceObject {\n // Adjust get(...) usage for your data structure\n const pathParts = cleanRef(ref).split('/');\n const entry = get(spec, pathParts) as SchemaObject | ReferenceObject;\n if (entry && '$ref' in entry) {\n return followRef(spec, entry.$ref);\n }\n return entry;\n}\n\ntype OnRefCallback = (ref: string, zod: string) => void;\n\n/**\n * Convert an OpenAPI (JSON Schema style) object into a Zod schema string,\n * adapted for OpenAPI 3.1 (fully aligned with JSON Schema 2020-12).\n */\n\nexport function jsonSchemaToZod(\n spec: OpenAPIObject,\n schema: SchemaObject | ReferenceObject,\n required = false,\n onRef: OnRefCallback,\n refProcessingStack = new Set<string>(), // Add as optional parameter with default value\n): string {\n // If it's a reference, resolve and recurse\n if ('$ref' in schema) {\n const schemaName = cleanRef(schema.$ref).split('/').pop()!;\n\n // Check for circular references\n if (refProcessingStack.has(schemaName)) {\n return schemaName;\n }\n\n refProcessingStack.add(schemaName);\n onRef(\n schemaName,\n jsonSchemaToZod(\n spec,\n followRef(spec, schema.$ref),\n required,\n onRef,\n refProcessingStack,\n ),\n );\n refProcessingStack.delete(schemaName);\n\n return schemaName;\n }\n\n // Handle allOf \u2192 intersection\n if (schema.allOf && Array.isArray(schema.allOf)) {\n const allOfSchemas = schema.allOf.map((sub) =>\n jsonSchemaToZod(spec, sub, true, onRef, refProcessingStack),\n );\n return `z.intersection(${allOfSchemas.join(', ')})`;\n }\n\n // anyOf \u2192 union\n if (schema.anyOf && Array.isArray(schema.anyOf)) {\n const anyOfSchemas = schema.anyOf.map((sub) =>\n jsonSchemaToZod(spec, sub, false, onRef, refProcessingStack),\n );\n return `z.union([${anyOfSchemas.join(', ')}])${appendOptional(required)}`;\n }\n\n // oneOf \u2192 union\n if (schema.oneOf && Array.isArray(schema.oneOf)) {\n const oneOfSchemas = schema.oneOf.map((sub) => {\n if ('$ref' in sub) {\n const refName = cleanRef(sub.$ref).split('/').pop()!;\n if (refProcessingStack.has(refName)) {\n return refName;\n }\n }\n return jsonSchemaToZod(spec, sub, false, onRef, refProcessingStack);\n });\n return `z.union([${oneOfSchemas.join(', ')}])${appendOptional(required)}`;\n }\n\n // enum\n if (schema.enum && Array.isArray(schema.enum)) {\n const enumVals = schema.enum.map((val) => JSON.stringify(val)).join(', ');\n return `z.enum([${enumVals}])${appendOptional(required)}`;\n }\n\n // 3.1 can have type: string or type: string[] (e.g. [\"string\",\"null\"])\n // Let's parse that carefully.\n const types = Array.isArray(schema.type)\n ? schema.type\n : schema.type\n ? [schema.type]\n : [];\n\n // If no explicit \"type\", fallback to unknown\n if (!types.length) {\n return `z.unknown()${appendOptional(required)}`;\n }\n\n // If it's a union type (like [\"string\", \"null\"]), we'll build a Zod union\n // or apply .nullable() if it's just \"type + null\".\n if (types.length > 1) {\n // If it\u2019s exactly one real type plus \"null\", we can do e.g. `z.string().nullable()`\n const realTypes = types.filter((t) => t !== 'null');\n if (realTypes.length === 1 && types.includes('null')) {\n // Single real type + \"null\"\n const typeZod = basicTypeToZod(\n realTypes[0],\n schema,\n spec,\n false,\n onRef,\n refProcessingStack,\n );\n return `${typeZod}.nullable()${appendOptional(required)}`;\n }\n // If multiple different types, build a union\n const subSchemas = types.map((t) =>\n basicTypeToZod(t, schema, spec, false, onRef, refProcessingStack),\n );\n return `z.union([${subSchemas.join(', ')}])${appendOptional(required)}`;\n }\n\n // If there's exactly one type\n return basicTypeToZod(\n types[0],\n schema,\n spec,\n required,\n onRef,\n refProcessingStack,\n );\n}\n\n/**\n * Convert a basic type (string | number | boolean | object | array, etc.) to Zod.\n * We'll also handle .optional() if needed.\n */\nfunction basicTypeToZod(\n type: string,\n schema: SchemaObject,\n spec: OpenAPIObject,\n required = false,\n onRef: OnRefCallback,\n refProcessingStack: Set<string>,\n): string {\n switch (type) {\n case 'string':\n return handleString(schema, required);\n case 'number':\n case 'integer':\n return handleNumber(schema, required);\n case 'boolean':\n return `z.boolean()${appendDefault(schema.default)}${appendOptional(required)}`;\n case 'object':\n return handleObject(schema, spec, required, onRef, refProcessingStack);\n case 'array':\n return handleArray(schema, spec, required, onRef, refProcessingStack);\n case 'null':\n // If \"type\": \"null\" alone, this is basically z.null()\n return `z.null()${appendOptional(required)}`;\n default:\n // Unknown type -> fallback\n return `z.unknown()${appendOptional(required)}`;\n }\n}\n\n/**\n * Handle a `string` schema with possible format keywords (JSON Schema).\n */\nfunction handleString(schema: SchemaObject, required?: boolean): string {\n let base = 'z.string()';\n\n // 3.1 replaces `example` in the schema with `examples` (array).\n // We do not strictly need them for the Zod type, so they\u2019re optional\n // for validation. However, we could keep them as metadata if you want.\n\n switch (schema.format) {\n case 'date-time':\n case 'datetime':\n // parse to JS Date\n base = 'z.coerce.date()';\n break;\n case 'date':\n base = 'z.coerce.date() /* or z.string() if you want raw date strings */';\n break;\n case 'time':\n base = 'z.string() /* optionally add .regex(...) for HH:MM:SS format */';\n break;\n case 'email':\n base = 'z.string().email()';\n break;\n case 'uuid':\n base = 'z.string().uuid()';\n break;\n case 'url':\n case 'uri':\n base = 'z.string().url()';\n break;\n case 'ipv4':\n base = 'z.string().ip({version: \"v4\"})';\n break;\n case 'ipv6':\n base = 'z.string().ip({version: \"v6\"})';\n break;\n case 'phone':\n base = 'z.string() /* or add .regex(...) for phone formats */';\n break;\n case 'byte':\n case 'binary':\n base = 'z.instanceof(Blob) /* consider base64 check if needed */';\n break;\n case 'int64':\n // JS numbers can't reliably store int64, consider z.bigint() or keep as string\n base = 'z.string() /* or z.bigint() if your app can handle it */';\n break;\n default:\n // No special format\n break;\n }\n\n return `${base}${appendDefault(schema.default)}${appendOptional(required)}`;\n}\n\n/**\n * Handle number/integer constraints from OpenAPI/JSON Schema.\n * In 3.1, exclusiveMinimum/Maximum hold the actual numeric threshold,\n * rather than a boolean toggling `minimum`/`maximum`.\n */\nfunction handleNumber(schema: SchemaObject, required?: boolean): string {\n let defaultValue =\n schema.default !== undefined ? `.default(${schema.default})` : ``;\n let base = 'z.number()';\n if (schema.format === 'int64') {\n base = 'z.bigint()';\n if (schema.default !== undefined) {\n defaultValue = `.default(BigInt(${schema.default}))`;\n }\n }\n\n if (schema.format === 'int32') {\n // 32-bit integer\n base += '.int()';\n }\n\n // If we see exclusiveMinimum as a number in 3.1:\n if (typeof schema.exclusiveMinimum === 'number') {\n // Zod doesn\u2019t have a direct \"exclusiveMinimum\" method, so we can do .gt()\n // If exclusiveMinimum=7 => .gt(7)\n base += `.gt(${schema.exclusiveMinimum})`;\n }\n // Similarly for exclusiveMaximum\n if (typeof schema.exclusiveMaximum === 'number') {\n // If exclusiveMaximum=10 => .lt(10)\n base += `.lt(${schema.exclusiveMaximum})`;\n }\n\n // If standard minimum/maximum\n if (typeof schema.minimum === 'number') {\n base +=\n schema.format === 'int64'\n ? `.min(BigInt(${schema.minimum}))`\n : `.min(${schema.minimum})`;\n }\n if (typeof schema.maximum === 'number') {\n base +=\n schema.format === 'int64'\n ? `.max(BigInt(${schema.maximum}))`\n : `.max(${schema.maximum})`;\n }\n\n // multipleOf\n if (typeof schema.multipleOf === 'number') {\n // There's no direct multipleOf in Zod. Some folks do a custom refine.\n // For example:\n base += `.refine((val) => Number.isInteger(val / ${schema.multipleOf}), \"Must be a multiple of ${schema.multipleOf}\")`;\n }\n\n return `${base}${defaultValue}${appendOptional(required)}`;\n}\n\n/**\n * Handle objects (properties, additionalProperties).\n */\nfunction handleObject(\n schema: SchemaObject,\n spec: OpenAPIObject,\n required = false,\n onRef: OnRefCallback,\n refProcessingStack: Set<string>,\n): string {\n const properties = schema.properties || {};\n\n // Convert each property\n const propEntries = Object.entries(properties).map(([key, propSchema]) => {\n const isRequired = (schema.required ?? []).includes(key);\n const zodPart = jsonSchemaToZod(\n spec,\n propSchema,\n isRequired,\n onRef,\n refProcessingStack,\n );\n return `'${key}': ${zodPart}`;\n });\n\n // additionalProperties\n let additionalProps = '';\n if (schema.additionalProperties) {\n if (typeof schema.additionalProperties === 'object') {\n // e.g. z.record() if it\u2019s an object schema\n const addPropZod = jsonSchemaToZod(\n spec,\n schema.additionalProperties,\n true,\n onRef,\n refProcessingStack,\n );\n additionalProps = `.catchall(${addPropZod})`;\n } else if (schema.additionalProperties === true) {\n // free-form additional props\n additionalProps = `.catchall(z.unknown())`;\n }\n }\n\n const objectSchema = `z.object({${propEntries.join(', ')}})${additionalProps}`;\n return `${objectSchema}${appendOptional(required)}`;\n}\n\n/**\n * Handle arrays (items could be a single schema or a tuple (array of schemas)).\n * In JSON Schema 2020-12, `items` can be an array \u2192 tuple style.\n */\nfunction handleArray(\n schema: SchemaObject,\n spec: OpenAPIObject,\n required = false,\n onRef: OnRefCallback,\n refProcessingStack: Set<string>,\n): string {\n const { items } = schema;\n if (!items) {\n // No items => z.array(z.unknown())\n return `z.array(z.unknown())${appendOptional(required)}`;\n }\n\n // If items is an array => tuple\n if (Array.isArray(items)) {\n // Build a Zod tuple\n const tupleItems = items.map((sub) =>\n jsonSchemaToZod(spec, sub, true, onRef, refProcessingStack),\n );\n const base = `z.tuple([${tupleItems.join(', ')}])`;\n // // If we have additionalItems: false => that\u2019s a fixed length\n // // If additionalItems is a schema => rest(...)\n // if (schema.additionalItems) {\n // if (typeof schema.additionalItems === 'object') {\n // const restSchema = jsonSchemaToZod(spec, schema.additionalItems, true);\n // base += `.rest(${restSchema})`;\n // }\n // // If `additionalItems: false`, no rest is allowed => do nothing\n // }\n return `${base}${appendOptional(required)}`;\n }\n\n // If items is a single schema => standard z.array(...)\n const itemsSchema = jsonSchemaToZod(\n spec,\n items,\n true,\n onRef,\n refProcessingStack,\n );\n return `z.array(${itemsSchema})${appendOptional(required)}`;\n}\n\n/**\n * Append .optional() if not required\n */\nfunction appendOptional(isRequired?: boolean) {\n return isRequired ? '' : '.optional()';\n}\nfunction appendDefault(defaultValue?: any) {\n return defaultValue !== undefined\n ? `.default(${JSON.stringify(defaultValue)})`\n : '';\n}\n\n// Todo: convert openapi 3.0 to 3.1 before proccesing\n", "import { camelcase } from 'stringcase';\nimport { pascalcase, spinalcase } from 'stringcase';\n\nimport { removeDuplicates, toLitObject } from '@sdk-it/core';\n\nimport backend from './backend.ts';\nimport clientTxt from './client.txt';\nimport parserTxt from './parser.txt';\nimport requestTxt from './request.txt';\nimport responseTxt from './response.txt';\n\nexport interface Import {\n isTypeOnly: boolean;\n moduleSpecifier: string;\n defaultImport: string | undefined;\n namedImports: NamedImport[];\n namespaceImport: string | undefined;\n}\nexport interface NamedImport {\n name: string;\n alias?: string;\n isTypeOnly: boolean;\n}\n\nclass SchemaEndpoint {\n #imports: string[] = [\n `import z from 'zod';`,\n 'import type { Endpoints } from \"./endpoints\";',\n 'import type { StreamEndpoints } from \"./stream-endpoints\";',\n `import { toRequest, json, urlencoded, formdata, createUrl } from './request';`,\n `import type { ParseError } from './parser';`,\n ];\n #endpoints: string[] = [];\n addEndpoint(endpoint: string, operation: any) {\n this.#endpoints.push(` \"${endpoint}\": ${operation},`);\n }\n addImport(value: string) {\n this.#imports.push(value);\n }\n complete() {\n return `${this.#imports.join('\\n')}\\nexport default {\\n${this.#endpoints.join('\\n')}\\n}`;\n }\n}\nclass Emitter {\n protected imports: string[] = [\n `import z from 'zod';`,\n `import type { ParseError } from './parser';`,\n ];\n protected endpoints: string[] = [];\n addEndpoint(endpoint: string, operation: any) {\n this.endpoints.push(` \"${endpoint}\": ${operation};`);\n }\n addImport(value: string) {\n this.imports.push(value);\n }\n complete() {\n return `${this.imports.join('\\n')}\\nexport interface Endpoints {\\n${this.endpoints.join('\\n')}\\n}`;\n }\n}\nclass StreamEmitter extends Emitter {\n override complete() {\n return `${this.imports.join('\\n')}\\nexport interface StreamEndpoints {\\n${this.endpoints.join('\\n')}\\n}`;\n }\n}\n\nexport interface SecurityScheme {\n bearerAuth: {\n type: 'http';\n scheme: 'bearer';\n bearerFormat: 'JWT';\n };\n}\n\nexport interface SdkConfig {\n /**\n * The name of the sdk client\n */\n name: string;\n packageName?: string;\n options?: Record<string, any>;\n emptyBodyAsNull?: boolean;\n stripBodyFromGetAndHead?: boolean;\n securityScheme?: SecurityScheme;\n output: string;\n formatGeneratedCode?: boolean;\n}\n\nexport interface Spec {\n groups: Record<string, Operation[]>;\n commonZod?: string;\n name?: string;\n options?: Record<\n string,\n {\n in: 'header';\n schema: string;\n }\n >;\n securityScheme?: SecurityScheme;\n}\n\nexport interface OperationInput {\n source: string;\n schema: string;\n}\nexport interface Operation {\n name: string;\n errors: string[];\n type: string;\n imports: Import[];\n trigger: Record<string, any>;\n contentType?: string;\n schemas: Record<string, string>;\n schema?: string;\n inputs: Record<string, OperationInput>;\n formatOutput: () => { import: string; use: string };\n}\n\nexport function generateClientSdk(spec: Spec) {\n const emitter = new Emitter();\n const streamEmitter = new StreamEmitter();\n const schemas: Record<string, string[]> = {};\n const schemasImports: string[] = [];\n const schemaEndpoint = new SchemaEndpoint();\n const errors: string[] = [];\n for (const [name, operations] of Object.entries(spec.groups)) {\n const featureSchemaFileName = camelcase(name);\n schemas[featureSchemaFileName] = [`import z from 'zod';`];\n emitter.addImport(\n `import * as ${featureSchemaFileName} from './inputs/${featureSchemaFileName}';`,\n );\n streamEmitter.addImport(\n `import * as ${featureSchemaFileName} from './inputs/${featureSchemaFileName}';`,\n );\n schemaEndpoint.addImport(\n `import * as ${featureSchemaFileName} from './inputs/${featureSchemaFileName}';`,\n );\n for (const operation of operations) {\n const schemaName = camelcase(`${operation.name} schema`);\n\n const schema = `export const ${schemaName} = ${\n Object.keys(operation.schemas).length === 1\n ? Object.values(operation.schemas)[0]\n : toLitObject(operation.schemas)\n };`;\n\n schemas[featureSchemaFileName].push(schema);\n schemasImports.push(\n ...operation.imports\n .map((it) => (it.namedImports ?? []).map((it) => it.name))\n .flat(),\n );\n const schemaRef = `${featureSchemaFileName}.${schemaName}`;\n const output = operation.formatOutput();\n const inputHeaders: string[] = [];\n const inputQuery: string[] = [];\n const inputBody: string[] = [];\n const inputParams: string[] = [];\n for (const [name, prop] of Object.entries(operation.inputs)) {\n if (prop.source === 'headers' || prop.source === 'header') {\n inputHeaders.push(`\"${name}\"`);\n } else if (prop.source === 'query') {\n inputQuery.push(`\"${name}\"`);\n } else if (prop.source === 'body') {\n inputBody.push(`\"${name}\"`);\n } else if (prop.source === 'path') {\n inputParams.push(`\"${name}\"`);\n } else if (prop.source === 'internal') {\n // ignore internal sources\n continue;\n } else {\n throw new Error(\n `Unknown source ${prop.source} in ${name} ${JSON.stringify(\n prop,\n )} in ${operation.name}`,\n );\n }\n }\n if (operation.type === 'sse') {\n const input = `z.infer<typeof ${schemaRef}>`;\n const endpoint = `${operation.trigger.method.toUpperCase()} ${operation.trigger.path}`;\n streamEmitter.addImport(\n `import type {${pascalcase(operation.name)}} from './outputs/${spinalcase(operation.name)}';`,\n );\n streamEmitter.addEndpoint(\n endpoint,\n `{input: ${input}, output: ${output.use}}`,\n );\n schemaEndpoint.addEndpoint(\n endpoint,\n `{\n schema: ${schemaRef},\n toRequest(input: StreamEndpoints['${endpoint}']['input'], init: {baseUrl:string; headers?: Record<string, string>}) {\n const endpoint = '${endpoint}';\n return toRequest(endpoint, json(input, {\n inputHeaders: [${inputHeaders}],\n inputQuery: [${inputQuery}],\n inputBody: [${inputBody}],\n inputParams: [${inputParams}],\n }), init);\n },\n }`,\n );\n } else {\n emitter.addImport(\n `import type {${output.import}} from './outputs/${spinalcase(operation.name)}';`,\n );\n errors.push(...(operation.errors ?? []));\n\n const addTypeParser = Object.keys(operation.schemas).length > 1;\n for (const type in operation.schemas ?? {}) {\n let typePrefix = '';\n if (addTypeParser && type !== 'json') {\n typePrefix = `${type} `;\n }\n const input = `typeof ${schemaRef}${addTypeParser ? `.${type}` : ''}`;\n\n const endpoint = `${typePrefix}${operation.trigger.method.toUpperCase()} ${operation.trigger.path}`;\n emitter.addEndpoint(\n endpoint,\n `{input: z.infer<${input}>; output: ${output.use}; error: ${(operation.errors ?? ['ServerError']).concat(`ParseError<${input}>`).join('|')}}`,\n );\n schemaEndpoint.addEndpoint(\n endpoint,\n `{\n schema: ${schemaRef}${addTypeParser ? `.${type}` : ''},\n toRequest(input: Endpoints['${endpoint}']['input'], init: {baseUrl:string; headers?: Record<string, string>}) {\n const endpoint = '${endpoint}';\n return toRequest(endpoint, ${operation.contentType || 'json'}(input, {\n inputHeaders: [${inputHeaders}],\n inputQuery: [${inputQuery}],\n inputBody: [${inputBody}],\n inputParams: [${inputParams}],\n }), init);\n },\n }`,\n );\n }\n }\n }\n }\n\n emitter.addImport(\n `import type { ${removeDuplicates(errors, (it) => it).join(', ')} } from './response';`,\n );\n return {\n ...Object.fromEntries(\n Object.entries(schemas).map(([key, value]) => [\n `inputs/${key}.ts`,\n [\n schemasImports.length\n ? `import {${removeDuplicates(schemasImports, (it) => it)}} from '../zod';`\n : '',\n spec.commonZod ? 'import * as commonZod from \"../zod\";' : '',\n ...value,\n ]\n .map((it) => it.trim())\n .filter(Boolean)\n .join('\\n') + '\\n', // add a newline at the end\n ]),\n ),\n 'backend.ts': backend(spec),\n 'parser.ts': parserTxt,\n 'client.ts': clientTxt,\n 'request.ts': requestTxt,\n 'schemas.ts': schemaEndpoint.complete(),\n 'endpoints.ts': emitter.complete(),\n 'stream-endpoints.ts': streamEmitter.complete(),\n 'response.ts': responseTxt,\n };\n}\n", "import { titlecase } from 'stringcase';\n\nimport { toLitObject } from '@sdk-it/core';\n\nimport type { Spec } from './sdk.ts';\n\nexport default (spec: Spec) => {\n const specOptions: Record<string, { schema: string }> = {\n ...(spec.options ?? {}),\n fetch: {\n schema:\n 'z.function().args(z.instanceof(Request)).returns(z.promise(z.instanceof(Response))).optional()',\n },\n baseUrl: { schema: 'z.string().url()' },\n };\n if (spec.securityScheme) {\n specOptions['token'] = { schema: 'z.string().optional()' };\n }\n const defaultHeaders = spec.securityScheme\n ? `{Authorization: \\`${titlecase(spec.securityScheme.bearerAuth.scheme)} \\${this.options.token}\\`}`\n : `{}`;\n\n return `\n\nimport z from 'zod';\nimport type { Endpoints } from './endpoints';\nimport type { StreamEndpoints } from './stream-endpoints';\nimport schemas from './schemas';\nimport { parse } from './parser';\nimport { handleError, parseResponse } from './client';\n\n const optionsSchema = z.object(${toLitObject(specOptions, (x) => x.schema)});\n type ${spec.name}Options = z.infer<typeof optionsSchema>;\n export class ${spec.name} {\n\n constructor(public options: ${spec.name}Options) {}\n\n async request<E extends keyof Endpoints>(\n endpoint: E,\n input: Endpoints[E]['input'],\n ): Promise<readonly [Endpoints[E]['output'], Endpoints[E]['error'] | null]> {\n const route = schemas[endpoint];\n const [parsedInput, parseError] = parse(route.schema, input);\n if (parseError) {\n return [\n null as never,\n { ...parseError, kind: 'parse' } as never,\n ] as const;\n }\n const request = route.toRequest(parsedInput as never, {\n headers: this.defaultHeaders,\n baseUrl: this.options.baseUrl,\n });\n const response = await (this.options.fetch ?? fetch)(request);\n if (response.ok) {\n const data = await parseResponse(response);\n return [data as Endpoints[E]['output'], null] as const;\n }\n const error = await handleError(response);\n return [null as never, { ...error, kind: 'response' }] as const;\n }\n\n get defaultHeaders() {\n return ${defaultHeaders}\n }\n\n setOptions(options: Partial<${spec.name}Options>) {\n const validated = optionsSchema.partial().parse(options);\n\n for (const key of Object.keys(validated) as (keyof ${spec.name}Options)[]) {\n if (validated[key] !== undefined) {\n (this.options[key] as typeof validated[typeof key]) = validated[key]!;\n }\n }\n }\n}`;\n};\n", "import { parse } from 'fast-content-type-parse';\n\nimport type { Endpoints } from './endpoints';\n\nexport interface RequestInterface<D extends object = object> {\n /**\n * Sends a request based on endpoint options\n *\n * @param {string} route Request method + URL. Example: 'GET /orgs/{org}'\n * @param {object} [parameters] URL, query or body parameters, as well as headers, mediaType.{format|previews}, request, or baseUrl.\n */\n <R extends keyof Endpoints>(\n route: R,\n options?: Endpoints[R]['input'],\n ): Promise<Endpoints[R]['output']>;\n}\n\nexport async function handleError(response: Response) {\n try {\n if (response.status >= 400 && response.status < 500) {\n const body = (await response.json()) as Record<string, any>;\n return {\n status: response.status,\n body: body,\n };\n }\n return new Error(\n `An error occurred while fetching the data. Status: ${response.status}`,\n );\n } catch (error) {\n return error as any;\n }\n}\n\nasync function handleChunkedResponse(response: Response, contentType: string) {\n const { type } = parse(contentType);\n\n switch (type) {\n case 'application/json': {\n let buffer = '';\n const reader = response.body!.getReader();\n const decoder = new TextDecoder();\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value);\n }\n return JSON.parse(buffer);\n }\n case 'text/html':\n case 'text/plain': {\n let buffer = '';\n const reader = response.body!.getReader();\n const decoder = new TextDecoder();\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value);\n }\n return buffer;\n }\n default:\n return response.body;\n }\n}\n\nexport async function parseResponse(response: Response) {\n const contentType = response.headers.get('Content-Type');\n if (!contentType) {\n throw new Error('Content-Type header is missing');\n }\n\n if (response.status === 204) {\n return null;\n }\n const isChunked = response.headers.get('Transfer-Encoding') === 'chunked';\n if (isChunked) {\n return response.body!;\n // return handleChunkedResponse(response, contentType);\n }\n\n const { type } = parse(contentType);\n switch (type) {\n case 'application/json':\n return response.json();\n case 'text/plain':\n return response.text();\n case 'text/html':\n return response.text();\n case 'text/xml':\n case 'application/xml':\n return response.text();\n case 'application/x-www-form-urlencoded':\n const text = await response.text();\n return Object.fromEntries(new URLSearchParams(text));\n case 'multipart/form-data':\n return response.formData();\n default:\n throw new Error(`Unsupported content type: ${contentType}`);\n }\n}\n", "import { z } from 'zod';\n\nexport type ParseError<T extends z.ZodType<any, any, any>> = {\n kind: 'parse';\n} & z.inferFlattenedErrors<T>;\n\nexport function parse<T extends z.ZodType>(\n schema: T,\n input: unknown,\n) {\n const result = schema.safeParse(input);\n if (!result.success) {\n const errors = result.error.flatten((issue) => issue);\n return [null, errors];\n }\n return [result.data as z.infer<T>, null];\n}\n", "type Method = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\ntype ContentType = 'xml' | 'json' | 'urlencoded' | 'multipart';\ntype Endpoint = `${ContentType} ${Method} ${string}` | `${Method} ${string}`;\n\nexport function createUrl(base: string, path: string, query: URLSearchParams) {\n const url = new URL(path, base);\n url.search = query.toString();\n return url;\n}\nfunction template(\n templateString: string,\n templateVariables: Record<string, any>,\n): string {\n const nargs = /{([0-9a-zA-Z_]+)}/g;\n return templateString.replace(nargs, (match, key: string, index: number) => {\n // Handle escaped double braces\n if (\n templateString[index - 1] === '{' &&\n templateString[index + match.length] === '}'\n ) {\n return key;\n }\n\n const result = key in templateVariables ? templateVariables[key] : null;\n return result === null || result === undefined ? '' : String(result);\n });\n}\n\ninterface ToRequest {\n <T extends Endpoint>(\n endpoint: T,\n input: Record<string, any>,\n props: {\n inputHeaders: string[];\n inputQuery: string[];\n inputBody: string[];\n inputParams: string[];\n },\n defaults: {\n baseUrl: string;\n headers?: Record<string, string>;\n },\n ): Request;\n urlencoded: <T extends Endpoint>(\n endpoint: T,\n input: Record<string, any>,\n props: {\n inputHeaders: string[];\n inputQuery: string[];\n inputBody: string[];\n inputParams: string[];\n },\n defaults: {\n baseUrl: string;\n headers?: Record<string, string>;\n },\n ) => Request;\n}\n\nfunction _json(\n input: Record<string, any>,\n props: {\n inputHeaders: string[];\n inputQuery: string[];\n inputBody: string[];\n inputParams: string[];\n },\n) {\n const headers = new Headers({});\n for (const header of props.inputHeaders) {\n headers.set(header, input[header]);\n }\n\n const body: Record<string, any> = {};\n for (const prop of props.inputBody) {\n body[prop] = input[prop];\n }\n\n const query = new URLSearchParams();\n for (const key of props.inputQuery) {\n const value = input[key];\n if (value !== undefined) {\n query.set(key, String(value));\n }\n }\n\n const params = props.inputParams.reduce<Record<string, any>>((acc, key) => {\n acc[key] = input[key];\n return acc;\n }, {});\n\n return {\n body: JSON.stringify(body),\n query,\n params,\n headers: { 'Content-Type': 'application/json', Accept: 'application/json' },\n };\n}\n\ntype Input = Record<string, any>;\ntype Props = {\n inputHeaders: string[];\n inputQuery: string[];\n inputBody: string[];\n inputParams: string[];\n};\n\nabstract class Serializer {\n constructor(\n protected input: Input,\n protected props: Props,\n ) {}\n abstract getBody(): BodyInit | null;\n abstract getHeaders(): Record<string, string>;\n serialize(): Serialized {\n const headers = new Headers({});\n for (const header of this.props.inputHeaders) {\n headers.set(header, this.input[header]);\n }\n\n const query = new URLSearchParams();\n for (const key of this.props.inputQuery) {\n const value = this.input[key];\n if (value !== undefined) {\n query.set(key, String(value));\n }\n }\n\n const params = this.props.inputParams.reduce<Record<string, any>>(\n (acc, key) => {\n acc[key] = this.input[key];\n return acc;\n },\n {},\n );\n\n return {\n body: this.getBody(),\n query,\n params,\n headers: this.getHeaders(),\n };\n }\n}\n\ninterface Serialized {\n body: BodyInit | null;\n query: URLSearchParams;\n params: Record<string, any>;\n headers: Record<string, string>;\n}\n\nclass JsonSerializer extends Serializer {\n getBody(): BodyInit | null {\n const body: Record<string, any> = {};\n for (const prop of this.props.inputBody) {\n body[prop] = this.input[prop];\n }\n return JSON.stringify(body);\n }\n getHeaders(): Record<string, string> {\n return {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n };\n }\n}\n\nclass UrlencodedSerializer extends Serializer {\n getBody(): BodyInit | null {\n const body = new URLSearchParams();\n for (const prop of this.props.inputBody) {\n body.set(prop, this.input[prop]);\n }\n return body;\n }\n getHeaders(): Record<string, string> {\n return {};\n }\n}\n\nclass FormDataSerializer extends Serializer {\n getBody(): BodyInit | null {\n const body = new FormData();\n for (const prop of this.props.inputBody) {\n body.append(prop, this.input[prop]);\n }\n return body;\n }\n getHeaders(): Record<string, string> {\n return {};\n }\n}\n\nexport function json(input: Input, props: Props) {\n return new JsonSerializer(input, props).serialize();\n}\nexport function urlencoded(input: Input, props: Props) {\n return new UrlencodedSerializer(input, props).serialize();\n}\nexport function formdata(input: Input, props: Props) {\n return new FormDataSerializer(input, props).serialize();\n}\n\nexport function _urlencoded(\n input: Record<string, any>,\n props: {\n inputHeaders: string[];\n inputQuery: string[];\n inputBody: string[];\n inputParams: string[];\n },\n) {\n const headers = new Headers({});\n for (const header of props.inputHeaders) {\n headers.set(header, input[header]);\n }\n\n const body = new URLSearchParams();\n for (const prop of props.inputBody) {\n body.set(prop, input[prop]);\n }\n\n const query = new URLSearchParams();\n for (const key of props.inputQuery) {\n const value = input[key];\n if (value !== undefined) {\n query.set(key, String(value));\n }\n }\n\n const params = props.inputParams.reduce<Record<string, any>>((acc, key) => {\n acc[key] = input[key];\n return acc;\n }, {});\n\n return {\n body,\n query,\n params,\n headers: {},\n };\n}\n\nexport function toRequest<T extends Endpoint>(\n endpoint: T,\n input: Serialized,\n defaults: {\n baseUrl: string;\n headers?: Record<string, string>;\n },\n): Request {\n const [method, path] = endpoint.split(' ');\n\n const headers = new Headers({\n ...defaults?.headers,\n ...input.headers,\n });\n const pathVariable = template(path, input.params);\n\n const url = createUrl(defaults.baseUrl, pathVariable, input.query);\n return new Request(url, {\n method: method,\n headers: headers,\n body: method === 'GET' ? undefined : input.body,\n });\n}\n", "export interface ApiResponse<Status extends number, Body extends unknown> {\n kind: 'response';\n status: Status;\n body: Body;\n}\n\n// 4xx Client Errors\nexport type BadRequest = ApiResponse<400, { message: string }>;\nexport type Unauthorized = ApiResponse<401, { message: string }>;\nexport type PaymentRequired = ApiResponse<402, { message: string }>;\nexport type Forbidden = ApiResponse<403, { message: string }>;\nexport type NotFound = ApiResponse<404, { message: string }>;\nexport type MethodNotAllowed = ApiResponse<405, { message: string }>;\nexport type NotAcceptable = ApiResponse<406, { message: string }>;\nexport type Conflict = ApiResponse<409, { message: string }>;\nexport type Gone = ApiResponse<410, { message: string }>;\nexport type UnprocessableEntity = ApiResponse<422, { message: string; errors?: Record<string, string[]> }>;\nexport type TooManyRequests = ApiResponse<429, { message: string; retryAfter?: string }>;\nexport type PayloadTooLarge = ApiResponse<413, { message: string; }>;\nexport type UnsupportedMediaType = ApiResponse<415, { message: string; }>;\n\n// 5xx Server Errors\nexport type InternalServerError = ApiResponse<500, { message: string }>;\nexport type NotImplemented = ApiResponse<501, { message: string }>;\nexport type BadGateway = ApiResponse<502, { message: string }>;\nexport type ServiceUnavailable = ApiResponse<503, { message: string; retryAfter?: string }>;\nexport type GatewayTimeout = ApiResponse<504, { message: string }>;\n\nexport type ClientError =\n | BadRequest\n | Unauthorized\n | PaymentRequired\n | Forbidden\n | NotFound\n | MethodNotAllowed\n | NotAcceptable\n | Conflict\n | Gone\n | UnprocessableEntity\n | TooManyRequests;\n\nexport type ServerError =\n | InternalServerError\n | NotImplemented\n | BadGateway\n | ServiceUnavailable\n | GatewayTimeout;\n\nexport type ProblematicResponse = ClientError | ServerError;\n"],
5
- "mappings": ";AAAA,SAAS,YAAY;;;ACArB,OAAO,MAAM,WAAW,kBAAkB;ACA1C,OAAO,WAAW;AAElB,OAAOA,SAAQ;AEFf,SAAS,OAAO,UAAU,SAAS,MAAM,iBAAiB;AAC1D,SAAS,WAAAC,UAAS,YAAY,QAAAC,aAAY;AHEnC,IAAM,eAAe,OAAO,IAAI,WAAW;AAC3C,IAAM,SAAS,OAAO,IAAI,OAAO;ACIxC,IAAM,SAAS,MAAM,gBAAgB;AEErC,eAAsB,MAAM,MAAgC;AAC1D,SAAO,KAAK,IAAI,EACb,KAAK,MAAM,IAAI,EACf,MAAM,MAAM,KAAK;AACtB;AASA,eAAsB,WACpB,KACA,UAIA;AACA,SAAO,QAAQ;IACb,OAAO,QAAQ,QAAQ,EAAE,IAAI,OAAO,CAAC,MAAM,OAAO,MAAM;AACtD,YAAM,WAAW,WAAW,IAAI,IAAI,OAAOC,MAAK,KAAK,IAAI;AACzD,YAAM,MAAMC,SAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAClD,UAAI,OAAO,YAAY,UAAU;AAC/B,cAAM,UAAU,UAAU,SAAS,OAAO;MAC5C,OAAO;AACL,YAAI,QAAQ,gBAAgB;AAC1B,cAAI,CAAE,MAAM,MAAM,QAAQ,GAAI;AAC5B,kBAAM,UAAU,UAAU,QAAQ,SAAS,OAAO;UACpD;QACF;MACF;IACF,CAAC;EACH;AACF;AAEA,eAAsB,iBACpB,QACA,aAAa,CAAC,IAAI,GAClB,iBAAiB,OACjB;AACA,QAAM,QAAQ,MAAM,QAAQ,QAAQ,EAAE,eAAe,KAAK,CAAC;AAC3D,QAAM,UAAoB,CAAC;AAC3B,aAAW,QAAQ,OAAO;AACxB,QAAI,KAAK,YAAY,GAAG;AACtB,cAAQ,KAAK,oBAAoB,KAAK,IAAI,IAAI;IAChD,WACE,KAAK,SAAS,cACd,WAAW,SAAS,OAAO,KAAK,IAAI,CAAC,GACrC;AACA,UAAI,gBAAgB;AAClB,gBAAQ,KAAK,oBAAoB,KAAK,IAAI,IAAI;MAChD,OAAO;AACL,gBAAQ;UACN,oBAAoB,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,IAAI,CAAC,IAAI,EAAE,CAAC;QACpE;MACF;IACF;EACF;AACA,SAAO,QAAQ,KAAK,IAAI;AAC1B;AAEO,IAAM,SAAS,CAAC,aAAsB;AAC3C,MAAI,CAAC,UAAU;AACb,WAAO;EACT;AACA,QAAM,UAAU,SAAS,YAAY,GAAG;AACxC,MAAI,YAAY,IAAI;AAClB,WAAO;EACT;AACA,QAAM,MAAM,SACT,MAAM,UAAU,CAAC,EACjB,MAAM,GAAG,EACT,OAAO,OAAO,EACd,KAAK,EAAE;AACV,MAAI,QAAQ,UAAU;AAEpB,WAAO;EACT;AACA,SAAO,OAAO;AAChB;ACtFO,SAAS,iBACd,MACA,UACK;AACL,SAAO,CAAC,GAAG,IAAI,IAAI,KAAK,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,OAAO,CAAC;AAChE;AAIO,SAAS,YACd,KACA,WAAmD,CAAC,UAAU,OAC9D;AACA,SAAO,IAAI,OAAO,KAAK,GAAG,EACvB,IAAI,CAAC,QAAQ,GAAG,GAAG,KAAK,SAAS,IAAI,GAAG,CAAC,CAAC,EAAE,EAC5C,KAAK,IAAI,CAAC;AACf;;;ACrBA,SAAS,OAAAC,MAAK,aAAa;AAQ3B,SAAS,aAAAC,YAAW,cAAAC,aAAY,cAAAC,mBAAkB;;;ACRlD,SAAS,WAAW;AAWpB,SAAS,SAAS,KAAa;AAC7B,SAAO,IAAI,QAAQ,QAAQ,EAAE;AAC/B;AACO,SAAS,UACd,MACA,KACgC;AAEhC,QAAM,YAAY,SAAS,GAAG,EAAE,MAAM,GAAG;AACzC,QAAM,QAAQ,IAAI,MAAM,SAAS;AACjC,MAAI,SAAS,UAAU,OAAO;AAC5B,WAAO,UAAU,MAAM,MAAM,IAAI;AAAA,EACnC;AACA,SAAO;AACT;AASO,SAAS,gBACd,MACA,QACA,WAAW,OACX,OACA,qBAAqB,oBAAI,IAAY,GAC7B;AAER,MAAI,UAAU,QAAQ;AACpB,UAAM,aAAa,SAAS,OAAO,IAAI,EAAE,MAAM,GAAG,EAAE,IAAI;AAGxD,QAAI,mBAAmB,IAAI,UAAU,GAAG;AACtC,aAAO;AAAA,IACT;AAEA,uBAAmB,IAAI,UAAU;AACjC;AAAA,MACE;AAAA,MACA;AAAA,QACE;AAAA,QACA,UAAU,MAAM,OAAO,IAAI;AAAA,QAC3B;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AACA,uBAAmB,OAAO,UAAU;AAEpC,WAAO;AAAA,EACT;AAGA,MAAI,OAAO,SAAS,MAAM,QAAQ,OAAO,KAAK,GAAG;AAC/C,UAAM,eAAe,OAAO,MAAM;AAAA,MAAI,CAAC,QACrC,gBAAgB,MAAM,KAAK,MAAM,OAAO,kBAAkB;AAAA,IAC5D;AACA,WAAO,kBAAkB,aAAa,KAAK,IAAI,CAAC;AAAA,EAClD;AAGA,MAAI,OAAO,SAAS,MAAM,QAAQ,OAAO,KAAK,GAAG;AAC/C,UAAM,eAAe,OAAO,MAAM;AAAA,MAAI,CAAC,QACrC,gBAAgB,MAAM,KAAK,OAAO,OAAO,kBAAkB;AAAA,IAC7D;AACA,WAAO,YAAY,aAAa,KAAK,IAAI,CAAC,KAAK,eAAe,QAAQ,CAAC;AAAA,EACzE;AAGA,MAAI,OAAO,SAAS,MAAM,QAAQ,OAAO,KAAK,GAAG;AAC/C,UAAM,eAAe,OAAO,MAAM,IAAI,CAAC,QAAQ;AAC7C,UAAI,UAAU,KAAK;AACjB,cAAM,UAAU,SAAS,IAAI,IAAI,EAAE,MAAM,GAAG,EAAE,IAAI;AAClD,YAAI,mBAAmB,IAAI,OAAO,GAAG;AACnC,iBAAO;AAAA,QACT;AAAA,MACF;AACA,aAAO,gBAAgB,MAAM,KAAK,OAAO,OAAO,kBAAkB;AAAA,IACpE,CAAC;AACD,WAAO,YAAY,aAAa,KAAK,IAAI,CAAC,KAAK,eAAe,QAAQ,CAAC;AAAA,EACzE;AAGA,MAAI,OAAO,QAAQ,MAAM,QAAQ,OAAO,IAAI,GAAG;AAC7C,UAAM,WAAW,OAAO,KAAK,IAAI,CAAC,QAAQ,KAAK,UAAU,GAAG,CAAC,EAAE,KAAK,IAAI;AACxE,WAAO,WAAW,QAAQ,KAAK,eAAe,QAAQ,CAAC;AAAA,EACzD;AAIA,QAAM,QAAQ,MAAM,QAAQ,OAAO,IAAI,IACnC,OAAO,OACP,OAAO,OACL,CAAC,OAAO,IAAI,IACZ,CAAC;AAGP,MAAI,CAAC,MAAM,QAAQ;AACjB,WAAO,cAAc,eAAe,QAAQ,CAAC;AAAA,EAC/C;AAIA,MAAI,MAAM,SAAS,GAAG;AAEpB,UAAM,YAAY,MAAM,OAAO,CAAC,MAAM,MAAM,MAAM;AAClD,QAAI,UAAU,WAAW,KAAK,MAAM,SAAS,MAAM,GAAG;AAEpD,YAAM,UAAU;AAAA,QACd,UAAU,CAAC;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,aAAO,GAAG,OAAO,cAAc,eAAe,QAAQ,CAAC;AAAA,IACzD;AAEA,UAAM,aAAa,MAAM;AAAA,MAAI,CAAC,MAC5B,eAAe,GAAG,QAAQ,MAAM,OAAO,OAAO,kBAAkB;AAAA,IAClE;AACA,WAAO,YAAY,WAAW,KAAK,IAAI,CAAC,KAAK,eAAe,QAAQ,CAAC;AAAA,EACvE;AAGA,SAAO;AAAA,IACL,MAAM,CAAC;AAAA,IACP;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF;AAMA,SAAS,eACP,MACA,QACA,MACA,WAAW,OACX,OACA,oBACQ;AACR,UAAQ,MAAM;AAAA,IACZ,KAAK;AACH,aAAO,aAAa,QAAQ,QAAQ;AAAA,IACtC,KAAK;AAAA,IACL,KAAK;AACH,aAAO,aAAa,QAAQ,QAAQ;AAAA,IACtC,KAAK;AACH,aAAO,cAAc,cAAc,OAAO,OAAO,CAAC,GAAG,eAAe,QAAQ,CAAC;AAAA,IAC/E,KAAK;AACH,aAAO,aAAa,QAAQ,MAAM,UAAU,OAAO,kBAAkB;AAAA,IACvE,KAAK;AACH,aAAO,YAAY,QAAQ,MAAM,UAAU,OAAO,kBAAkB;AAAA,IACtE,KAAK;AAEH,aAAO,WAAW,eAAe,QAAQ,CAAC;AAAA,IAC5C;AAEE,aAAO,cAAc,eAAe,QAAQ,CAAC;AAAA,EACjD;AACF;AAKA,SAAS,aAAa,QAAsB,UAA4B;AACtE,MAAI,OAAO;AAMX,UAAQ,OAAO,QAAQ;AAAA,IACrB,KAAK;AAAA,IACL,KAAK;AAEH,aAAO;AACP;AAAA,IACF,KAAK;AACH,aAAO;AACP;AAAA,IACF,KAAK;AACH,aAAO;AACP;AAAA,IACF,KAAK;AACH,aAAO;AACP;AAAA,IACF,KAAK;AACH,aAAO;AACP;AAAA,IACF,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AACP;AAAA,IACF,KAAK;AACH,aAAO;AACP;AAAA,IACF,KAAK;AACH,aAAO;AACP;AAAA,IACF,KAAK;AACH,aAAO;AACP;AAAA,IACF,KAAK;AAAA,IACL,KAAK;AACH,aAAO;AACP;AAAA,IACF,KAAK;AAEH,aAAO;AACP;AAAA,IACF;AAEE;AAAA,EACJ;AAEA,SAAO,GAAG,IAAI,GAAG,cAAc,OAAO,OAAO,CAAC,GAAG,eAAe,QAAQ,CAAC;AAC3E;AAOA,SAAS,aAAa,QAAsB,UAA4B;AACtE,MAAI,eACF,OAAO,YAAY,SAAY,YAAY,OAAO,OAAO,MAAM;AACjE,MAAI,OAAO;AACX,MAAI,OAAO,WAAW,SAAS;AAC7B,WAAO;AACP,QAAI,OAAO,YAAY,QAAW;AAChC,qBAAe,mBAAmB,OAAO,OAAO;AAAA,IAClD;AAAA,EACF;AAEA,MAAI,OAAO,WAAW,SAAS;AAE7B,YAAQ;AAAA,EACV;AAGA,MAAI,OAAO,OAAO,qBAAqB,UAAU;AAG/C,YAAQ,OAAO,OAAO,gBAAgB;AAAA,EACxC;AAEA,MAAI,OAAO,OAAO,qBAAqB,UAAU;AAE/C,YAAQ,OAAO,OAAO,gBAAgB;AAAA,EACxC;AAGA,MAAI,OAAO,OAAO,YAAY,UAAU;AACtC,YACE,OAAO,WAAW,UACd,eAAe,OAAO,OAAO,OAC7B,QAAQ,OAAO,OAAO;AAAA,EAC9B;AACA,MAAI,OAAO,OAAO,YAAY,UAAU;AACtC,YACE,OAAO,WAAW,UACd,eAAe,OAAO,OAAO,OAC7B,QAAQ,OAAO,OAAO;AAAA,EAC9B;AAGA,MAAI,OAAO,OAAO,eAAe,UAAU;AAGzC,YAAQ,2CAA2C,OAAO,UAAU,6BAA6B,OAAO,UAAU;AAAA,EACpH;AAEA,SAAO,GAAG,IAAI,GAAG,YAAY,GAAG,eAAe,QAAQ,CAAC;AAC1D;AAKA,SAAS,aACP,QACA,MACA,WAAW,OACX,OACA,oBACQ;AACR,QAAM,aAAa,OAAO,cAAc,CAAC;AAGzC,QAAM,cAAc,OAAO,QAAQ,UAAU,EAAE,IAAI,CAAC,CAAC,KAAK,UAAU,MAAM;AACxE,UAAM,cAAc,OAAO,YAAY,CAAC,GAAG,SAAS,GAAG;AACvD,UAAM,UAAU;AAAA,MACd;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF;AACA,WAAO,IAAI,GAAG,MAAM,OAAO;AAAA,EAC7B,CAAC;AAGD,MAAI,kBAAkB;AACtB,MAAI,OAAO,sBAAsB;AAC/B,QAAI,OAAO,OAAO,yBAAyB,UAAU;AAEnD,YAAM,aAAa;AAAA,QACjB;AAAA,QACA,OAAO;AAAA,QACP;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACA,wBAAkB,aAAa,UAAU;AAAA,IAC3C,WAAW,OAAO,yBAAyB,MAAM;AAE/C,wBAAkB;AAAA,IACpB;AAAA,EACF;AAEA,QAAM,eAAe,aAAa,YAAY,KAAK,IAAI,CAAC,KAAK,eAAe;AAC5E,SAAO,GAAG,YAAY,GAAG,eAAe,QAAQ,CAAC;AACnD;AAMA,SAAS,YACP,QACA,MACA,WAAW,OACX,OACA,oBACQ;AACR,QAAM,EAAE,MAAM,IAAI;AAClB,MAAI,CAAC,OAAO;AAEV,WAAO,uBAAuB,eAAe,QAAQ,CAAC;AAAA,EACxD;AAGA,MAAI,MAAM,QAAQ,KAAK,GAAG;AAExB,UAAM,aAAa,MAAM;AAAA,MAAI,CAAC,QAC5B,gBAAgB,MAAM,KAAK,MAAM,OAAO,kBAAkB;AAAA,IAC5D;AACA,UAAM,OAAO,YAAY,WAAW,KAAK,IAAI,CAAC;AAU9C,WAAO,GAAG,IAAI,GAAG,eAAe,QAAQ,CAAC;AAAA,EAC3C;AAGA,QAAM,cAAc;AAAA,IAClB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,SAAO,WAAW,WAAW,IAAI,eAAe,QAAQ,CAAC;AAC3D;AAKA,SAAS,eAAe,YAAsB;AAC5C,SAAO,aAAa,KAAK;AAC3B;AACA,SAAS,cAAc,cAAoB;AACzC,SAAO,iBAAiB,SACpB,YAAY,KAAK,UAAU,YAAY,CAAC,MACxC;AACN;;;AClZA,SAAS,iBAAiB;AAC1B,SAAS,YAAY,kBAAkB;;;ACDvC,SAAS,iBAAiB;AAM1B,IAAO,kBAAQ,CAAC,SAAe;AAC7B,QAAM,cAAkD;AAAA,IACtD,GAAI,KAAK,WAAW,CAAC;AAAA,IACrB,OAAO;AAAA,MACL,QACE;AAAA,IACJ;AAAA,IACA,SAAS,EAAE,QAAQ,mBAAmB;AAAA,EACxC;AACA,MAAI,KAAK,gBAAgB;AACvB,gBAAY,OAAO,IAAI,EAAE,QAAQ,wBAAwB;AAAA,EAC3D;AACA,QAAM,iBAAiB,KAAK,iBACxB,qBAAqB,UAAU,KAAK,eAAe,WAAW,MAAM,CAAC,+BACrE;AAEJ,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,uCAS8B,YAAY,aAAa,CAAC,MAAM,EAAE,MAAM,CAAC;AAAA,aACnE,KAAK,IAAI;AAAA,mBACH,KAAK,IAAI;AAAA;AAAA,oCAEQ,KAAK,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,iBA4B5B,cAAc;AAAA;AAAA;AAAA,gCAGC,KAAK,IAAI;AAAA;AAAA;AAAA,yDAGgB,KAAK,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAOlE;;;AC5EA;;;ACAA;;;ACAA;;;ACAA;;;ALwBA,IAAM,iBAAN,MAAqB;AAAA,EACnB,WAAqB;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,aAAuB,CAAC;AAAA,EACxB,YAAY,UAAkB,WAAgB;AAC5C,SAAK,WAAW,KAAK,MAAM,QAAQ,MAAM,SAAS,GAAG;AAAA,EACvD;AAAA,EACA,UAAU,OAAe;AACvB,SAAK,SAAS,KAAK,KAAK;AAAA,EAC1B;AAAA,EACA,WAAW;AACT,WAAO,GAAG,KAAK,SAAS,KAAK,IAAI,CAAC;AAAA;AAAA,EAAuB,KAAK,WAAW,KAAK,IAAI,CAAC;AAAA;AAAA,EACrF;AACF;AACA,IAAM,UAAN,MAAc;AAAA,EACF,UAAoB;AAAA,IAC5B;AAAA,IACA;AAAA,EACF;AAAA,EACU,YAAsB,CAAC;AAAA,EACjC,YAAY,UAAkB,WAAgB;AAC5C,SAAK,UAAU,KAAK,MAAM,QAAQ,MAAM,SAAS,GAAG;AAAA,EACtD;AAAA,EACA,UAAU,OAAe;AACvB,SAAK,QAAQ,KAAK,KAAK;AAAA,EACzB;AAAA,EACA,WAAW;AACT,WAAO,GAAG,KAAK,QAAQ,KAAK,IAAI,CAAC;AAAA;AAAA,EAAmC,KAAK,UAAU,KAAK,IAAI,CAAC;AAAA;AAAA,EAC/F;AACF;AACA,IAAM,gBAAN,cAA4B,QAAQ;AAAA,EACzB,WAAW;AAClB,WAAO,GAAG,KAAK,QAAQ,KAAK,IAAI,CAAC;AAAA;AAAA,EAAyC,KAAK,UAAU,KAAK,IAAI,CAAC;AAAA;AAAA,EACrG;AACF;AAuDO,SAAS,kBAAkB,MAAY;AAC5C,QAAM,UAAU,IAAI,QAAQ;AAC5B,QAAM,gBAAgB,IAAI,cAAc;AACxC,QAAM,UAAoC,CAAC;AAC3C,QAAM,iBAA2B,CAAC;AAClC,QAAM,iBAAiB,IAAI,eAAe;AAC1C,QAAM,SAAmB,CAAC;AAC1B,aAAW,CAAC,MAAM,UAAU,KAAK,OAAO,QAAQ,KAAK,MAAM,GAAG;AAC5D,UAAM,wBAAwB,UAAU,IAAI;AAC5C,YAAQ,qBAAqB,IAAI,CAAC,sBAAsB;AACxD,YAAQ;AAAA,MACN,eAAe,qBAAqB,mBAAmB,qBAAqB;AAAA,IAC9E;AACA,kBAAc;AAAA,MACZ,eAAe,qBAAqB,mBAAmB,qBAAqB;AAAA,IAC9E;AACA,mBAAe;AAAA,MACb,eAAe,qBAAqB,mBAAmB,qBAAqB;AAAA,IAC9E;AACA,eAAW,aAAa,YAAY;AAClC,YAAM,aAAa,UAAU,GAAG,UAAU,IAAI,SAAS;AAEvD,YAAM,SAAS,gBAAgB,UAAU,MACvC,OAAO,KAAK,UAAU,OAAO,EAAE,WAAW,IACtC,OAAO,OAAO,UAAU,OAAO,EAAE,CAAC,IAClC,YAAY,UAAU,OAAO,CACnC;AAEA,cAAQ,qBAAqB,EAAE,KAAK,MAAM;AAC1C,qBAAe;AAAA,QACb,GAAG,UAAU,QACV,IAAI,CAAC,QAAQ,GAAG,gBAAgB,CAAC,GAAG,IAAI,CAACC,QAAOA,IAAG,IAAI,CAAC,EACxD,KAAK;AAAA,MACV;AACA,YAAM,YAAY,GAAG,qBAAqB,IAAI,UAAU;AACxD,YAAM,SAAS,UAAU,aAAa;AACtC,YAAM,eAAyB,CAAC;AAChC,YAAM,aAAuB,CAAC;AAC9B,YAAM,YAAsB,CAAC;AAC7B,YAAM,cAAwB,CAAC;AAC/B,iBAAW,CAACC,OAAM,IAAI,KAAK,OAAO,QAAQ,UAAU,MAAM,GAAG;AAC3D,YAAI,KAAK,WAAW,aAAa,KAAK,WAAW,UAAU;AACzD,uBAAa,KAAK,IAAIA,KAAI,GAAG;AAAA,QAC/B,WAAW,KAAK,WAAW,SAAS;AAClC,qBAAW,KAAK,IAAIA,KAAI,GAAG;AAAA,QAC7B,WAAW,KAAK,WAAW,QAAQ;AACjC,oBAAU,KAAK,IAAIA,KAAI,GAAG;AAAA,QAC5B,WAAW,KAAK,WAAW,QAAQ;AACjC,sBAAY,KAAK,IAAIA,KAAI,GAAG;AAAA,QAC9B,WAAW,KAAK,WAAW,YAAY;AAErC;AAAA,QACF,OAAO;AACL,gBAAM,IAAI;AAAA,YACR,kBAAkB,KAAK,MAAM,OAAOA,KAAI,IAAI,KAAK;AAAA,cAC/C;AAAA,YACF,CAAC,OAAO,UAAU,IAAI;AAAA,UACxB;AAAA,QACF;AAAA,MACF;AACA,UAAI,UAAU,SAAS,OAAO;AAC5B,cAAM,QAAQ,kBAAkB,SAAS;AACzC,cAAM,WAAW,GAAG,UAAU,QAAQ,OAAO,YAAY,CAAC,IAAI,UAAU,QAAQ,IAAI;AACpF,sBAAc;AAAA,UACZ,gBAAgB,WAAW,UAAU,IAAI,CAAC,qBAAqB,WAAW,UAAU,IAAI,CAAC;AAAA,QAC3F;AACA,sBAAc;AAAA,UACZ;AAAA,UACA,WAAW,KAAK,aAAa,OAAO,GAAG;AAAA,QACzC;AACA,uBAAe;AAAA,UACb;AAAA,UACA;AAAA,kBACQ,SAAS;AAAA,4CACiB,QAAQ;AAAA,8BACtB,QAAQ;AAAA;AAAA,6BAET,YAAY;AAAA,2BACd,UAAU;AAAA,0BACX,SAAS;AAAA,4BACP,WAAW;AAAA;AAAA;AAAA;AAAA,QAI/B;AAAA,MACF,OAAO;AACL,gBAAQ;AAAA,UACN,gBAAgB,OAAO,MAAM,qBAAqB,WAAW,UAAU,IAAI,CAAC;AAAA,QAC9E;AACA,eAAO,KAAK,GAAI,UAAU,UAAU,CAAC,CAAE;AAEvC,cAAM,gBAAgB,OAAO,KAAK,UAAU,OAAO,EAAE,SAAS;AAC9D,mBAAW,QAAQ,UAAU,WAAW,CAAC,GAAG;AAC1C,cAAI,aAAa;AACjB,cAAI,iBAAiB,SAAS,QAAQ;AACpC,yBAAa,GAAG,IAAI;AAAA,UACtB;AACA,gBAAM,QAAQ,UAAU,SAAS,GAAG,gBAAgB,IAAI,IAAI,KAAK,EAAE;AAEnE,gBAAM,WAAW,GAAG,UAAU,GAAG,UAAU,QAAQ,OAAO,YAAY,CAAC,IAAI,UAAU,QAAQ,IAAI;AACjG,kBAAQ;AAAA,YACN;AAAA,YACA,mBAAmB,KAAK,cAAc,OAAO,GAAG,aAAa,UAAU,UAAU,CAAC,aAAa,GAAG,OAAO,cAAc,KAAK,GAAG,EAAE,KAAK,GAAG,CAAC;AAAA,UAC5I;AACA,yBAAe;AAAA,YACb;AAAA,YACA;AAAA,oBACQ,SAAS,GAAG,gBAAgB,IAAI,IAAI,KAAK,EAAE;AAAA,wCACvB,QAAQ;AAAA,gCAChB,QAAQ;AAAA,2CACG,UAAU,eAAe,MAAM;AAAA,+BAC3C,YAAY;AAAA,6BACd,UAAU;AAAA,4BACX,SAAS;AAAA,8BACP,WAAW;AAAA;AAAA;AAAA;AAAA,UAI/B;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAEA,UAAQ;AAAA,IACN,iBAAiB,iBAAiB,QAAQ,CAAC,OAAO,EAAE,EAAE,KAAK,IAAI,CAAC;AAAA,EAClE;AACA,SAAO;AAAA,IACL,GAAG,OAAO;AAAA,MACR,OAAO,QAAQ,OAAO,EAAE,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM;AAAA,QAC5C,UAAU,GAAG;AAAA,QACb;AAAA,UACE,eAAe,SACX,WAAW,iBAAiB,gBAAgB,CAAC,OAAO,EAAE,CAAC,qBACvD;AAAA,UACJ,KAAK,YAAY,yCAAyC;AAAA,UAC1D,GAAG;AAAA,QACL,EACG,IAAI,CAAC,OAAO,GAAG,KAAK,CAAC,EACrB,OAAO,OAAO,EACd,KAAK,IAAI,IAAI;AAAA;AAAA,MAClB,CAAC;AAAA,IACH;AAAA,IACA,cAAc,gBAAQ,IAAI;AAAA,IAC1B,aAAa;AAAA,IACb,aAAa;AAAA,IACb,cAAc;AAAA,IACd,cAAc,eAAe,SAAS;AAAA,IACtC,gBAAgB,QAAQ,SAAS;AAAA,IACjC,uBAAuB,cAAc,SAAS;AAAA,IAC9C,eAAe;AAAA,EACjB;AACF;;;AFnPA,SAAS,MAAM,KAAkC;AAC/C,SAAO,UAAU;AACnB;AAEA,IAAM,YAAoC;AAAA,EACxC,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AAAA,EACP,OAAO;AACT;AAiBO,IAAM,WACwC;AAAA,EACnD,QAAQ;AAAA,EACR,OAAO;AAAA,EACP,aAAa,CAAC,WAAW,MAAM,WAAW;AACxC,QAAI,UAAU,aAAa;AACzB,aAAOC,YAAW,UAAU,WAAW;AAAA,IACzC;AACA,WACE,UAAU,eACVC,WAAU,GAAG,MAAM,IAAI,KAAK,QAAQ,OAAO,GAAG,CAAC,EAAE;AAAA,EAErD;AACF;AAEO,SAAS,aAAa,QAA2B;AACtD,QAAM,SAAyB,CAAC;AAChC,QAAM,gBAAwC,CAAC;AAC/C,QAAM,UAAkC,CAAC;AAEzC,aAAW,CAAC,MAAM,OAAO,KAAK,OAAO,QAAQ,OAAO,KAAK,SAAS,CAAC,CAAC,GAAG;AACrE,eAAW,CAAC,QAAQ,SAAS,KAAK,OAAO,QAAQ,OAAO,GAGnD;AACH,YAAM,oBAAoB,OAAO,eAAe,SAAS;AACzD,YAAM,gBAAgB,kBAAkB,WAAW,MAAM,MAAM;AAE/D,cAAQ,IAAI,cAAc,MAAM,IAAI,IAAI,EAAE;AAC1C,YAAM,aAAa,UAAU,QAAQ,CAAC,SAAS,GAAG,CAAC;AACnD,aAAO,SAAS,MAAM,CAAC;AACvB,YAAM,SAA8B,CAAC;AACrC,YAAM,UAAoB,CAAC;AAE3B,YAAM,uBAAuB,CAAC;AAC9B,iBAAW,SAAS,UAAU,cAAc,CAAC,GAAG;AAC9C,YAAI,MAAM,KAAK,GAAG;AAChB,gBAAM,IAAI,MAAM,gCAAgC,MAAM,IAAI,EAAE;AAAA,QAC9D;AACA,YAAI,CAAC,MAAM,QAAQ;AACjB,gBAAM,IAAI,MAAM,kCAAkC,MAAM,IAAI,EAAE;AAAA,QAChE;AACA,eAAO,MAAM,IAAI,IAAI;AAAA,UACnB,QAAQ,MAAM;AAAA,UACd,QAAQ;AAAA,QACV;AACA,6BAAqB,KAAK,KAAK;AAAA,MACjC;AAEA,YAAM,QAAgC,CAAC;AACvC,YAAM,qBAA6C;AAAA,QACjD,oBAAoB;AAAA,QACpB,qCAAqC;AAAA,QACrC,uBAAuB;AAAA,QACvB,mBAAmB;AAAA,QACnB,cAAc;AAAA,MAChB;AACA,UAAI;AACJ,UAAI,UAAU,eAAe,OAAO,KAAK,UAAU,WAAW,EAAE,QAAQ;AACtE,cAAM,UAAyB,MAAM,UAAU,WAAW,IACtDC,KAAI,UAAU,OAAO,MAAM,UAAU,YAAY,IAAI,GAAG,CAAC,SAAS,CAAC,IACnE,UAAU,YAAY;AAE1B,mBAAW,QAAQ,SAAS;AAC1B,gBAAM,SAAS,MAAM,QAAQ,IAAI,EAAE,MAAM,IACrC,UAAU,OAAO,MAAM,QAAQ,IAAI,EAAE,OAAO,IAAI,IAChD,QAAQ,IAAI,EAAE;AAElB,gBAAM,mBAAmB,IAAI,CAAC,IAAI;AAAA,YAChC,OAAO;AAAA,YACP,MAAM,QAAQ;AAAA,cACZ,UAAU,qBACP,OAAO,CAAC,MAAM,EAAE,QAAQ,EACxB,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,cACpB,YAAY,qBAAqB;AAAA,gBAC/B,CAAC,KAAK,OAAO;AAAA,kBACX,GAAG;AAAA,kBACH,CAAC,EAAE,IAAI,GAAG,EAAE;AAAA,gBACd;AAAA,gBACA,CAAC;AAAA,cACH;AAAA,YACF,CAAC;AAAA,YACD;AAAA,YACA,CAAC,YAAY,QAAQ;AACnB,4BAAc,UAAU,IAAI;AAC5B,sBAAQ,KAAK;AAAA,gBACX,eAAe;AAAA,gBACf,YAAY;AAAA,gBACZ,iBAAiB;AAAA,gBACjB,cAAc,CAAC,EAAE,YAAY,OAAO,MAAM,WAAW,CAAC;AAAA,gBACtD,iBAAiB;AAAA,cACnB,CAAC;AAAA,YACH;AAAA,UACF;AAAA,QACF;AAEA,YAAI,QAAQ,kBAAkB,GAAG;AAC/B,wBAAc;AAAA,QAChB,WAAW,QAAQ,mCAAmC,GAAG;AACvD,wBAAc;AAAA,QAChB,WAAW,QAAQ,qBAAqB,GAAG;AACzC,wBAAc;AAAA,QAChB,OAAO;AACL,wBAAc;AAAA,QAChB;AAAA,MACF,OAAO;AACL,cAAM,mBAAmB,kBAAkB,CAAC,IAAI;AAAA,UAC9C,OAAO;AAAA,UACP;AAAA,YACE,MAAM;AAAA,YACN,UAAU,qBACP,OAAO,CAAC,MAAM,EAAE,QAAQ,EACxB,IAAI,CAAC,MAAM,EAAE,IAAI;AAAA,YACpB,YAAY,qBAAqB;AAAA,cAC/B,CAAC,KAAK,OAAO;AAAA,gBACX,GAAG;AAAA,gBACH,CAAC,EAAE,IAAI,GAAG,EAAE;AAAA,cACd;AAAA,cACA,CAAC;AAAA,YACH;AAAA,UACF;AAAA,UACA;AAAA,UACA,CAAC,YAAY,QAAQ;AACnB,0BAAc,UAAU,IAAI;AAC5B,oBAAQ,KAAK;AAAA,cACX,eAAe;AAAA,cACf,YAAY;AAAA,cACZ,iBAAiB;AAAA,cACjB,cAAc,CAAC,EAAE,YAAY,OAAO,MAAM,WAAW,CAAC;AAAA,cACtD,iBAAiB;AAAA,YACnB,CAAC;AAAA,UACH;AAAA,QACF;AAAA,MACF;AAEA,YAAM,SAAmB,CAAC;AAC1B,gBAAU,cAAc,CAAC;AAEzB,UAAI,gBAAgB;AACpB,YAAM,SAAS,CAAC,sBAAsB;AACtC,iBAAW,UAAU,UAAU,WAAW;AACxC,cAAM,WAAW,UAAU,UAAU,MAAM;AAC3C,cAAM,aAAa,CAAC;AACpB,YAAI,cAAc,KAAK;AACrB,iBAAO,KAAK,UAAU,MAAM,KAAK,qBAAqB;AAAA,QACxD;AACA,YAAI,cAAc,OAAO,aAAa,KAAK;AACzC,0BAAgB;AAChB,gBAAM,kBAAkBA,KAAI,UAAU,CAAC,SAAS,CAAC;AACjD,gBAAM,SAAS,mBAAmB,gBAAgB,kBAAkB;AAEpE,gBAAM,iBAAiB,SACnB;AAAA,YACE,OAAO;AAAA,YACP,gBAAgB,kBAAkB,EAAE;AAAA,YACpC;AAAA,YACA,CAAC,YAAY,QAAQ;AACnB,4BAAc,UAAU,IAAI;AAC5B,sBAAQ,KAAK;AAAA,gBACX,eAAe;AAAA,gBACf,YAAY;AAAA,gBACZ,iBAAiB;AAAA,gBACjB,cAAc,CAAC,EAAE,YAAY,OAAO,MAAM,WAAW,CAAC;AAAA,gBACtD,iBAAiB;AAAA,cACnB,CAAC;AAAA,YACH;AAAA,UACF,IACA;AAEJ,iBAAO;AAAA,YACL,gBAAgB,aAAa,OAAO,OAAO,OAAO,EAAE,KAAK,CAAC,CAAC,EAAE;AAAA,cAC3D;AAAA,YACF;AAAA,UACF;AACA,iBAAO;AAAA,YACL,gBAAgBC,YAAW,gBAAgB,SAAS,CAAC,MAAM,cAAc;AAAA,UAC3E;AAAA,QACF;AAAA,MACF;AAEA,UAAI,CAAC,eAAe;AAClB,eAAO;AAAA,UACL,gBAAgBA,YAAW,gBAAgB,SAAS,CAAC;AAAA,QACvD;AAAA,MACF;AACA,cAAQ,GAAGH,YAAW,aAAa,CAAC,KAAK,IAAI,OAAO,KAAK,IAAI;AAC7D,aAAO,SAAS,EAAE,KAAK;AAAA,QACrB,MAAM;AAAA,QACN,MAAM;AAAA,QACN,SAAS,aAAa,OAAO,OAAO,OAAO,EAAE,KAAK,CAAC;AAAA,QACnD;AAAA,QACA,QAAQ,OAAO,SAAS,SAAS,CAAC,aAAa;AAAA,QAC/C;AAAA,QACA,SAAS;AAAA,QACT,cAAc,OAAO;AAAA,UACnB,QAAQG,YAAW,gBAAgB,SAAS;AAAA,UAC5C,KAAK,kBAAkBA,YAAW,gBAAgB,SAAS,CAAC;AAAA,QAC9D;AAAA,QACA,SAAS;AAAA,UACP;AAAA,UACA;AAAA,QACF;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AAEA,SAAO,EAAE,QAAQ,eAAe,QAAQ;AAC1C;AAiBA,SAAS,aAAa,SAAmB;AACvC,QAAM,SAAiC,CAAC;AAExC,aAAW,KAAK,SAAS;AACvB,WAAO,EAAE,eAAe,IAAI,OAAO,EAAE,eAAe,KAAK;AAAA,MACvD,iBAAiB,EAAE;AAAA,MACnB,eAAe,EAAE;AAAA,MACjB,iBAAiB,EAAE;AAAA,MACnB,cAAc,CAAC;AAAA,IACjB;AACA,QAAI,EAAE,cAAc;AAClB,aAAO,EAAE,eAAe,EAAE,aAAa,KAAK,GAAG,EAAE,YAAY;AAAA,IAC/D;AAAA,EACF;AAEA,SAAO,OAAO,OAAO,MAAM;AAC7B;AAEA,SAAS,gBAAgB,SAAmB;AAC1C,SAAO,QAAQ,IAAI,CAAC,MAAM;AACxB,QAAI,EAAE,eAAe;AACnB,aAAO,UAAU,EAAE,aAAa,UAAU,EAAE,eAAe;AAAA,IAC7D;AACA,QAAI,EAAE,iBAAiB;AACrB,aAAO,eAAe,EAAE,eAAe,UAAU,EAAE,eAAe;AAAA,IACpE;AACA,QAAI,EAAE,cAAc;AAClB,aAAO,WAAW,iBAAiB,EAAE,cAAc,CAAC,OAAO,GAAG,IAAI,EAC/D,IAAI,CAAC,MAAM,EAAE,IAAI,EACjB,KAAK,IAAI,CAAC,WAAW,EAAE,eAAe;AAAA,IAC3C;AACA,UAAM,IAAI,MAAM,kBAAkB,KAAK,UAAU,CAAC,CAAC,EAAE;AAAA,EACvD,CAAC;AACH;;;AN3TA,eAAsB,SACpB,MACA,UAGA;AACA,QAAM,EAAE,eAAe,QAAQ,QAAQ,IAAI,aAAa;AAAA,IACtD;AAAA,IACA,OAAO;AAAA,IACP,QAAQ;AAAA,EACV,CAAC;AACD,QAAM,cAAc,kBAAkB;AAAA,IACpC,MAAM;AAAA,IACN;AAAA,EACF,CAAC;AACD,QAAM,WAAW,SAAS,QAAQ;AAAA,IAChC,oBAAoB;AAAA,IACpB,mBAAmB;AAAA,EACrB,CAAC;AACD,QAAM,WAAW,KAAK,SAAS,QAAQ,SAAS,GAAG,OAAO;AAC1D,QAAM,WAAW,SAAS,QAAQ;AAAA,IAChC,GAAG;AAAA,IACH,UAAU;AAAA,EAAyB,OAAO,QAAQ,aAAa,EAC5D,IAAI,CAAC,CAAC,MAAM,MAAM,MAAM,gBAAgB,IAAI,MAAM,MAAM,GAAG,EAC3D,KAAK,IAAI,CAAC;AAAA,EACf,CAAC;AAED,QAAM,CAAC,OAAO,aAAa,WAAW,IAAI,MAAM,QAAQ,IAAI;AAAA,IAC1D,iBAAiB,SAAS,MAAM;AAAA,IAChC,iBAAiB,KAAK,SAAS,QAAQ,SAAS,CAAC;AAAA,IACjD,iBAAiB,KAAK,SAAS,QAAQ,QAAQ,CAAC;AAAA,EAClD,CAAC;AAED,QAAM,WAAW,SAAS,QAAQ;AAAA,IAChC,YAAY;AAAA,IACZ,oBAAoB;AAAA,IACpB,mBAAmB;AAAA,EACrB,CAAC;AACH;",
6
- "names": ["ts", "dirname", "join", "join", "dirname", "get", "camelcase", "pascalcase", "spinalcase", "it", "name", "spinalcase", "camelcase", "get", "pascalcase"]
3
+ "sources": ["../src/lib/generate.ts", "../../core/src/lib/deriver.ts", "../../core/src/lib/program.ts", "../../core/src/lib/paths.ts", "../../core/src/lib/file-system.ts", "../../core/src/index.ts", "../src/lib/generator.ts", "../src/lib/json-zod.ts", "../src/lib/sdk.ts", "../src/lib/client.ts", "../src/lib/http/client.txt", "../src/lib/http/parser.txt", "../src/lib/http/request.txt", "../src/lib/http/response.txt", "../src/lib/http/send-request.txt", "../src/lib/readme-generator.ts"],
4
+ "sourcesContent": ["import { join } from 'node:path';\nimport type { OpenAPIObject } from 'openapi3-ts/oas31';\n\nimport { getFolderExports, writeFiles } from '@sdk-it/core';\n\nimport { generateCode } from './generator.ts';\nimport clientTxt from './http/client.txt';\nimport parserTxt from './http/parser.txt';\nimport requestTxt from './http/request.txt';\nimport responseTxt from './http/response.txt';\nimport sendRequest from './http/send-request.txt';\nimport { generateReadme } from './readme-generator.ts';\nimport { generateClientSdk } from './sdk.ts';\n\nexport async function generate(\n spec: OpenAPIObject,\n settings: {\n output: string;\n name?: string;\n },\n) {\n const { commonSchemas, groups, outputs } = generateCode({\n spec,\n style: 'github',\n target: 'javascript',\n });\n\n const clientFiles = generateClientSdk({\n name: settings.name || 'Client',\n groups: groups,\n servers: spec.servers?.map((server) => server.url) || [],\n });\n\n // const readme = generateReadme(spec, {\n // name: settings.name || 'Client',\n // });\n\n await writeFiles(settings.output, {\n 'outputs/index.ts': '',\n 'inputs/index.ts': '',\n // 'README.md': readme,\n });\n\n await writeFiles(join(settings.output, 'http'), {\n 'parse-response.ts': clientTxt,\n 'send-request.ts': sendRequest,\n 'response.ts': responseTxt,\n 'parser.ts': parserTxt,\n 'request.ts': requestTxt,\n });\n\n await writeFiles(join(settings.output, 'outputs'), outputs);\n await writeFiles(settings.output, {\n ...clientFiles,\n 'zod.ts': `import z from 'zod';\\n${Object.entries(commonSchemas)\n .map(([name, schema]) => `export const ${name} = ${schema};`)\n .join('\\n')}`,\n });\n\n const [index, outputIndex, inputsIndex, httpIndex] = await Promise.all([\n getFolderExports(settings.output),\n getFolderExports(join(settings.output, 'outputs')),\n getFolderExports(join(settings.output, 'inputs')),\n getFolderExports(join(settings.output, 'http')),\n ]);\n\n await writeFiles(settings.output, {\n 'index.ts': index,\n 'outputs/index.ts': outputIndex,\n 'inputs/index.ts': inputsIndex,\n 'http/index.ts': httpIndex,\n });\n}\n", "import ts, { TypeFlags, symbolName } from 'typescript';\n\ntype Collector = Record<string, any>;\nexport const deriveSymbol = Symbol.for('serialize');\nexport const $types = Symbol.for('types');\nconst defaults: Record<string, string> = {\n ReadableStream: 'any',\n DateConstructor: 'string',\n ArrayBufferConstructor: 'any',\n SharedArrayBufferConstructor: 'any',\n Int8ArrayConstructor: 'any',\n Uint8Array: 'any',\n};\nexport class TypeDeriver {\n public readonly collector: Collector = {};\n public readonly checker: ts.TypeChecker;\n constructor(checker: ts.TypeChecker) {\n this.checker = checker;\n }\n\n serializeType(type: ts.Type): any {\n if (type.flags & TypeFlags.Any) {\n return {\n [deriveSymbol]: true,\n optional: false,\n [$types]: [],\n };\n }\n if (type.flags & ts.TypeFlags.Boolean) {\n return {\n [deriveSymbol]: true,\n optional: false,\n [$types]: ['boolean'],\n };\n }\n if (type.isIntersection()) {\n let optional: boolean | undefined;\n const types: any[] = [];\n for (const unionType of type.types) {\n if (optional === undefined) {\n optional = (unionType.flags & ts.TypeFlags.Undefined) !== 0;\n if (optional) {\n continue;\n }\n }\n\n types.push(this.serializeType(unionType));\n }\n return {\n [deriveSymbol]: true,\n kind: 'intersection',\n optional,\n [$types]: types,\n };\n }\n if (type.isUnion()) {\n let optional: boolean | undefined;\n const types: any[] = [];\n for (const unionType of type.types) {\n if (optional === undefined) {\n optional = (unionType.flags & ts.TypeFlags.Undefined) !== 0;\n if (optional) {\n continue;\n }\n }\n\n types.push(this.serializeType(unionType));\n }\n return {\n [deriveSymbol]: true,\n kind: 'union',\n optional,\n [$types]: types,\n };\n }\n if (this.checker.isArrayLikeType(type)) {\n const [argType] = this.checker.getTypeArguments(type as ts.TypeReference);\n if (!argType) {\n const typeName = type.symbol?.getName() || '<unknown>';\n console.warn(\n `Could not find generic type argument for array type ${typeName}`,\n );\n return {\n [deriveSymbol]: true,\n optional: false,\n kind: 'array',\n [$types]: ['any'],\n };\n }\n const typeSymbol = argType.getSymbol();\n if (!typeSymbol) {\n console.warn(\n `No symbol found for array type ${this.checker.typeToString(argType)}`,\n );\n return {\n [deriveSymbol]: true,\n optional: false,\n kind: 'array',\n [$types]: [this.serializeType(argType)],\n };\n }\n\n if (typeSymbol.valueDeclaration) {\n return {\n kind: 'array',\n [deriveSymbol]: true,\n [$types]: [this.serializeNode(typeSymbol.valueDeclaration)],\n };\n }\n const maybeDeclaration = typeSymbol.declarations?.[0];\n if (maybeDeclaration) {\n if (ts.isMappedTypeNode(maybeDeclaration)) {\n const resolvedType = this.checker\n .getPropertiesOfType(argType)\n .reduce<Record<string, unknown>>((acc, prop) => {\n const propType = this.checker.getTypeOfSymbol(prop);\n acc[prop.name] = this.serializeType(propType);\n return acc;\n }, {});\n return {\n kind: 'array',\n optional: false,\n [deriveSymbol]: true,\n [$types]: [resolvedType],\n };\n } else {\n return {\n kind: 'array',\n ...this.serializeNode(maybeDeclaration),\n };\n }\n }\n\n return {\n kind: 'array',\n optional: false,\n [deriveSymbol]: true,\n [$types]: ['any'],\n };\n }\n if (type.isClass()) {\n const declaration = type.symbol?.valueDeclaration;\n if (!declaration) {\n return {\n [deriveSymbol]: true,\n optional: false,\n [$types]: [type.symbol.getName()],\n };\n }\n return this.serializeNode(declaration);\n }\n if (isInterfaceType(type)) {\n const valueDeclaration =\n type.symbol.valueDeclaration ?? type.symbol.declarations?.[0];\n if (!valueDeclaration) {\n return {\n [deriveSymbol]: true,\n optional: false,\n [$types]: [type.symbol.getName()],\n };\n }\n return this.serializeNode(valueDeclaration);\n }\n if (type.flags & TypeFlags.Null) {\n return {\n [deriveSymbol]: true,\n optional: true,\n [$types]: ['null'],\n };\n }\n if (type.flags & TypeFlags.Object) {\n if (defaults[symbolName(type.symbol)]) {\n return {\n [deriveSymbol]: true,\n optional: false,\n [$types]: [defaults[type.symbol.name]],\n };\n }\n const properties = this.checker.getPropertiesOfType(type);\n if (properties.length > 0) {\n const serializedProps: Record<string, any> = {};\n for (const prop of properties) {\n if (\n (prop.getDeclarations() ?? []).some(\n (it) => ts.isPropertySignature(it) || ts.isPropertyAssignment(it),\n )\n ) {\n const propType = this.checker.getTypeOfSymbol(prop);\n serializedProps[prop.name] = this.serializeType(propType);\n }\n }\n return {\n [deriveSymbol]: true,\n kind: 'object',\n optional: false,\n [$types]: [serializedProps],\n };\n }\n const declaration =\n type.symbol.valueDeclaration ?? type.symbol.declarations?.[0];\n if (!declaration) {\n return {\n [deriveSymbol]: true,\n optional: false,\n [$types]: [type.symbol.getName()],\n };\n }\n return this.serializeNode(declaration);\n }\n\n return {\n [deriveSymbol]: true,\n optional: false,\n [$types]: [\n this.checker.typeToString(\n type,\n undefined,\n ts.TypeFormatFlags.NoTruncation,\n ),\n ],\n };\n }\n\n serializeNode(node: ts.Node): any {\n if (ts.isObjectLiteralExpression(node)) {\n const symbolType = this.checker.getTypeAtLocation(node);\n const props: Record<string, any> = {};\n for (const symbol of symbolType.getProperties()) {\n const type = this.checker.getTypeOfSymbol(symbol);\n props[symbol.name] = this.serializeType(type);\n }\n return props;\n }\n if (ts.isPropertyAccessExpression(node)) {\n const symbol = this.checker.getSymbolAtLocation(node.name);\n if (!symbol) {\n console.warn(`No symbol found for ${node.name.getText()}`);\n return null;\n }\n const type = this.checker.getTypeOfSymbol(symbol);\n return this.serializeType(type);\n }\n if (ts.isPropertySignature(node)) {\n const symbol = this.checker.getSymbolAtLocation(node.name);\n if (!symbol) {\n console.warn(`No symbol found for ${node.name.getText()}`);\n return null;\n }\n const type = this.checker.getTypeOfSymbol(symbol);\n return this.serializeType(type);\n }\n if (ts.isPropertyDeclaration(node)) {\n const symbol = this.checker.getSymbolAtLocation(node.name);\n if (!symbol) {\n console.warn(`No symbol found for ${node.name.getText()}`);\n return null;\n }\n const type = this.checker.getTypeOfSymbol(symbol);\n return this.serializeType(type);\n }\n if (ts.isInterfaceDeclaration(node)) {\n if (!node.name?.text) {\n throw new Error('Interface has no name');\n }\n console.log(node.name.text);\n if (defaults[node.name.text]) {\n return {\n [deriveSymbol]: true,\n optional: false,\n [$types]: [defaults[node.name.text]],\n };\n }\n if (!this.collector[node.name.text]) {\n this.collector[node.name.text] = {};\n const members: Record<string, any> = {};\n for (const member of node.members.filter(ts.isPropertySignature)) {\n members[member.name.getText()] = this.serializeNode(member);\n }\n this.collector[node.name.text] = members;\n }\n return {\n [deriveSymbol]: true,\n optional: false,\n [$types]: [`#/components/schemas/${node.name.text}`],\n };\n }\n if (ts.isClassDeclaration(node)) {\n if (!node.name?.text) {\n throw new Error('Class has no name');\n }\n if (defaults[node.name.text]) {\n return {\n [deriveSymbol]: true,\n optional: false,\n [$types]: [defaults[node.name.text]],\n };\n }\n\n if (!this.collector[node.name.text]) {\n this.collector[node.name.text] = {};\n const members: Record<string, unknown> = {};\n for (const member of node.members.filter(ts.isPropertyDeclaration)) {\n members[member.name!.getText()] = this.serializeNode(member);\n }\n this.collector[node.name.text] = members;\n }\n return {\n [deriveSymbol]: true,\n optional: false,\n [$types]: [`#/components/schemas/${node.name.text}`],\n $ref: `#/components/schemas/${node.name.text}`,\n };\n }\n if (ts.isVariableDeclaration(node)) {\n const symbol = this.checker.getSymbolAtLocation(node.name);\n if (!symbol) {\n console.warn(`No symbol found for ${node.name.getText()}`);\n return null;\n }\n if (!node.type) {\n console.warn(`No type found for ${node.name.getText()}`);\n return 'any';\n }\n const type = this.checker.getTypeFromTypeNode(node.type);\n return this.serializeType(type);\n }\n if (ts.isIdentifier(node)) {\n const symbol = this.checker.getSymbolAtLocation(node);\n if (!symbol) {\n console.warn(`Identifer: No symbol found for ${node.getText()}`);\n return null;\n }\n const type = this.checker.getTypeAtLocation(node);\n return this.serializeType(type);\n }\n if (ts.isAwaitExpression(node)) {\n const type = this.checker.getTypeAtLocation(node);\n return this.serializeType(type);\n }\n if (ts.isCallExpression(node)) {\n const type = this.checker.getTypeAtLocation(node);\n return this.serializeType(type);\n }\n if (ts.isAsExpression(node)) {\n const type = this.checker.getTypeAtLocation(node);\n return this.serializeType(type);\n }\n if (ts.isTypeLiteralNode(node)) {\n const symbolType = this.checker.getTypeAtLocation(node);\n const props: Record<string, unknown> = {};\n for (const symbol of symbolType.getProperties()) {\n const type = this.checker.getTypeOfSymbol(symbol);\n props[symbol.name] = this.serializeType(type);\n }\n return {\n [deriveSymbol]: true,\n optional: false,\n [$types]: [props],\n };\n }\n if (node.kind === ts.SyntaxKind.NullKeyword) {\n return {\n [deriveSymbol]: true,\n optional: true,\n [$types]: ['null'],\n };\n }\n if (node.kind === ts.SyntaxKind.BooleanKeyword) {\n return {\n [deriveSymbol]: true,\n optional: false,\n [$types]: ['boolean'],\n };\n }\n if (\n node.kind === ts.SyntaxKind.TrueKeyword ||\n node.kind === ts.SyntaxKind.FalseKeyword\n ) {\n return {\n [deriveSymbol]: true,\n optional: false,\n [$types]: ['boolean'],\n };\n }\n if (ts.isArrayLiteralExpression(node)) {\n const type = this.checker.getTypeAtLocation(node);\n return this.serializeType(type);\n }\n\n console.warn(`Unhandled node: ${ts.SyntaxKind[node.kind]} ${node.flags}`);\n return {\n [deriveSymbol]: true,\n optional: false,\n [$types]: ['any'],\n };\n }\n}\n\nfunction isInterfaceType(type: ts.Type): boolean {\n if (type.isClassOrInterface()) {\n // Check if it's an interface\n return !!(type.symbol.flags & ts.SymbolFlags.Interface);\n }\n return false;\n}\n", "import debug from 'debug';\nimport { dirname, join } from 'node:path';\nimport ts from 'typescript';\n\n\n\n\n\nconst logger = debug('january:client');\n\nexport function parseTsConfig(tsconfigPath: string) {\n logger(`Using TypeScript version: ${ts.version}`);\n const configContent = ts.readConfigFile(tsconfigPath, ts.sys.readFile);\n\n if (configContent.error) {\n console.error(\n `Failed to read tsconfig file:`,\n ts.formatDiagnosticsWithColorAndContext([configContent.error], {\n getCanonicalFileName: (path) => path,\n getCurrentDirectory: ts.sys.getCurrentDirectory,\n getNewLine: () => ts.sys.newLine,\n }),\n );\n throw new Error('Failed to parse tsconfig.json');\n }\n\n const parsed = ts.parseJsonConfigFileContent(\n configContent.config,\n ts.sys,\n dirname(tsconfigPath),\n );\n\n if (parsed.errors.length > 0) {\n console.error(\n `Errors found in tsconfig.json:`,\n ts.formatDiagnosticsWithColorAndContext(parsed.errors, {\n getCanonicalFileName: (path) => path,\n getCurrentDirectory: ts.sys.getCurrentDirectory,\n getNewLine: () => ts.sys.newLine,\n }),\n );\n throw new Error('Failed to parse tsconfig.json');\n }\n return parsed;\n}\nexport function getProgram(tsconfigPath: string) {\n const tsConfigParseResult = parseTsConfig(tsconfigPath);\n logger(`Parsing tsconfig`);\n return ts.createProgram({\n options: {\n ...tsConfigParseResult.options,\n noEmit: true,\n incremental: true,\n tsBuildInfoFile: join(dirname(tsconfigPath), './.tsbuildinfo'), // not working atm\n },\n rootNames: tsConfigParseResult.fileNames,\n projectReferences: tsConfigParseResult.projectReferences,\n configFileParsingDiagnostics: tsConfigParseResult.errors,\n });\n}\nexport function getPropertyAssignment(node: ts.Node, name: string) {\n if (ts.isObjectLiteralExpression(node)) {\n return node.properties\n .filter((prop) => ts.isPropertyAssignment(prop))\n .find((prop) => prop.name!.getText() === name);\n }\n return undefined;\n}\nexport function isCallExpression(\n node: ts.Node,\n name: string,\n): node is ts.CallExpression {\n return (\n ts.isCallExpression(node) &&\n node.expression &&\n ts.isIdentifier(node.expression) &&\n node.expression.text === name\n );\n}\n\nexport function isInterfaceType(type: ts.Type): boolean {\n if (type.isClassOrInterface()) {\n // Check if it's an interface\n return !!(type.symbol.flags & ts.SymbolFlags.Interface);\n }\n return false;\n}", "import type {\n OperationObject,\n ParameterObject,\n PathsObject,\n ResponseObject,\n ResponsesObject,\n SchemaObject,\n} from 'openapi3-ts/oas31';\n\nimport { $types } from './deriver.ts';\n\nexport type Method = 'get' | 'post' | 'put' | 'patch' | 'delete';\n\nexport type SemanticSource =\n | 'query'\n | 'queries'\n | 'body'\n | 'params'\n | 'headers';\n\nconst semanticSourceToOpenAPI = {\n queries: 'query',\n query: 'query',\n headers: 'header',\n params: 'path',\n} as const;\nexport interface Selector {\n name: string;\n select: string;\n against: string;\n source: SemanticSource;\n nullable: boolean;\n required: boolean;\n}\n\nexport interface ResponseItem {\n statusCode: string;\n response?: DateType;\n contentType: string;\n headers: string[];\n}\n\nexport class Paths {\n #commonZodImport?: string;\n #operations: Array<{\n name: string;\n path: string;\n method: Method;\n selectors: Selector[];\n responses: ResponsesObject;\n tags?: string[];\n description?: string;\n }> = [];\n\n constructor(config: { commonZodImport?: string }) {\n this.#commonZodImport = config.commonZodImport;\n }\n\n addPath(\n name: string,\n path: string,\n method: Method,\n selectors: Selector[],\n responses: ResponseItem[],\n tags?: string[],\n description?: string,\n ) {\n const responsesObject = this.#responseItemToResponses(responses);\n this.#operations.push({\n name,\n path,\n method,\n selectors,\n responses: responsesObject,\n tags,\n description,\n });\n return this;\n }\n\n #responseItemToResponses(responses: ResponseItem[]): ResponsesObject {\n const responsesObject: ResponsesObject = {};\n for (const item of responses) {\n const ct = item.contentType;\n const schema = item.response ? toSchema(item.response) : {};\n if (!responsesObject[item.statusCode]) {\n responsesObject[item.statusCode] = {\n description: `Response for ${item.statusCode}`,\n content: {\n [ct]:\n ct === 'application/octet-stream'\n ? { schema: { type: 'string', format: 'binary' } }\n : { schema },\n },\n headers: item.headers.length\n ? item.headers.reduce(\n (acc, header) => ({\n ...acc,\n [header]: { schema: { type: 'string' } },\n }),\n {},\n )\n : undefined,\n } satisfies ResponseObject;\n } else {\n if (!responsesObject[item.statusCode].content[ct]) {\n responsesObject[item.statusCode].content[ct] = { schema };\n } else {\n const existing = responsesObject[item.statusCode].content[ct]\n .schema as SchemaObject;\n if (existing.oneOf) {\n if (\n !existing.oneOf.find(\n (it) => JSON.stringify(it) === JSON.stringify(schema),\n )\n ) {\n existing.oneOf.push(schema);\n }\n } else if (JSON.stringify(existing) !== JSON.stringify(schema)) {\n responsesObject[item.statusCode].content[ct].schema = {\n oneOf: [existing, schema],\n };\n }\n }\n }\n }\n return responsesObject;\n }\n\n async #selectosToParameters(selectors: Selector[]) {\n const parameters: ParameterObject[] = [];\n const bodySchemaProps: Record<string, SchemaObject> = {};\n for (const selector of selectors) {\n if (selector.source === 'body') {\n bodySchemaProps[selector.name] = await evalZod(\n selector.against,\n this.#commonZodImport,\n );\n continue;\n }\n\n const parameter: ParameterObject = {\n in: semanticSourceToOpenAPI[selector.source],\n name: selector.name,\n required: selector.required,\n schema: await evalZod(selector.against, this.#commonZodImport),\n };\n parameters.push(parameter);\n }\n return { parameters, bodySchemaProps };\n }\n\n async getPaths() {\n const operations: PathsObject = {};\n for (const operation of this.#operations) {\n const { path, method, selectors } = operation;\n const { parameters, bodySchemaProps } =\n await this.#selectosToParameters(selectors);\n const operationObject: OperationObject = {\n operationId: operation.name,\n parameters,\n tags: operation.tags,\n description: operation.description,\n requestBody: Object.keys(bodySchemaProps).length\n ? {\n content: {\n 'application/json': {\n schema: {\n type: 'object',\n properties: bodySchemaProps,\n },\n },\n },\n }\n : undefined,\n responses: operation.responses,\n };\n if (!operations[path]) {\n operations[path] = {};\n }\n operations[path][method] = operationObject;\n }\n return operations;\n }\n}\n\nasync function evalZod(schema: string, commonZodImport?: string) {\n const lines = [\n `import { z } from 'zod';`,\n commonZodImport ? `import * as commonZod from '${commonZodImport}'` : '',\n `import { zodToJsonSchema } from 'zod-to-json-schema';`,\n `const schema = ${schema.replace('.optional()', '')};`,\n `const jsonSchema = zodToJsonSchema(schema, {\n\t\t\t$refStrategy: 'root',\n\t\t\tbasePath: ['#', 'components', 'schemas']\n\t\t});`,\n `export default jsonSchema;`,\n ];\n const base64Code = Buffer.from(lines.join('\\n')).toString('base64');\n const dataUrl = `data:text/javascript;base64,${base64Code}`;\n return import(dataUrl)\n .then((mod) => mod.default)\n .then(({ $schema, ...result }) => result);\n}\n\nconst typeMappings: Record<string, string> = {\n DateConstructor: 'Date',\n};\n\ninterface DateType {\n [$types]: any[];\n kind: string;\n optional: boolean;\n}\n\nexport function toSchema(data: DateType | string | null | undefined): any {\n if (data === null || data === undefined) {\n return { type: 'any' };\n } else if (typeof data === 'string') {\n const isRef = data.startsWith('#');\n if (isRef) {\n return { $ref: data };\n }\n return { type: data };\n } else if (data.kind === 'array') {\n const items = data[$types].map(toSchema);\n return { type: 'array', items: data[$types].length ? items[0] : {} };\n } else if (data.kind === 'union') {\n return { oneOf: data[$types].map(toSchema) };\n } else if (data.kind === 'intersection') {\n return { allOf: data[$types].map(toSchema) };\n } else if ($types in data) {\n return data[$types].map(toSchema)[0] ?? {};\n } else {\n const props: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(data)) {\n props[key] = toSchema(value as any);\n }\n return {\n type: 'object',\n properties: props,\n additionalProperties: false,\n };\n }\n}\n\nexport function isHttpMethod(name: string): name is Method {\n return ['get', 'post', 'put', 'delete', 'patch'].includes(name);\n}\n", "import { mkdir, readFile, readdir, stat, writeFile } from 'node:fs/promises';\nimport { dirname, isAbsolute, join } from 'node:path';\n\nexport async function getFile(filePath: string) {\n if (await exist(filePath)) {\n return readFile(filePath, 'utf-8');\n }\n return null;\n}\n\nexport async function exist(file: string): Promise<boolean> {\n return stat(file)\n .then(() => true)\n .catch(() => false);\n}\n\nexport async function readFolder(path: string) {\n if (await exist(path)) {\n return readdir(path);\n }\n return [] as string[];\n}\n\nexport async function writeFiles(\n dir: string,\n contents: Record<\n string,\n string | { content: string; ignoreIfExists?: boolean }\n >,\n) {\n return Promise.all(\n Object.entries(contents).map(async ([file, content]) => {\n const filePath = isAbsolute(file) ? file : join(dir, file);\n await mkdir(dirname(filePath), { recursive: true });\n if (typeof content === 'string') {\n await writeFile(filePath, content, 'utf-8');\n } else {\n if (content.ignoreIfExists) {\n if (!(await exist(filePath))) {\n await writeFile(filePath, content.content, 'utf-8');\n }\n }\n }\n }),\n );\n}\n\nexport async function getFolderExports(folder: string, extensions = ['ts']) {\n const files = await readdir(folder, { withFileTypes: true });\n const exports: string[] = [];\n for (const file of files) {\n if (file.isDirectory()) {\n exports.push(`export * from './${file.name}';`);\n } else if (\n file.name !== 'index.ts' &&\n extensions.includes(getExt(file.name))\n ) {\n exports.push(`export * from './${file.name}';`);\n }\n }\n return exports.join('\\n');\n}\n\nexport const getExt = (fileName?: string) => {\n if (!fileName) {\n return ''; // shouldn't happen as there will always be a file name\n }\n const lastDot = fileName.lastIndexOf('.');\n if (lastDot === -1) {\n return '';\n }\n const ext = fileName\n .slice(lastDot + 1)\n .split('/')\n .filter(Boolean)\n .join('');\n if (ext === fileName) {\n // files that have no extension\n return '';\n }\n return ext || 'txt';\n};\n", "export * from './lib/deriver.ts';\nexport * from './lib/program.ts';\nexport * from './lib/paths.ts';\nexport * from './lib/file-system.ts';\n\nexport function removeDuplicates<T>(\n data: T[],\n accessor: (item: T) => T[keyof T],\n): T[] {\n return [...new Map(data.map((x) => [accessor(x), x])).values()];\n}\n\nexport type InferRecordValue<T> = T extends Record<string, infer U> ? U : any;\n\nexport function toLitObject<T extends Record<string, any>>(\n obj: T,\n accessor: (value: InferRecordValue<T>) => string = (value) => value,\n) {\n return `{${Object.keys(obj)\n .map((key) => `${key}: ${accessor(obj[key])}`)\n .join(', ')}}`;\n}\n", "import { get, merge } from 'lodash-es';\nimport type {\n ContentObject,\n OpenAPIObject,\n OperationObject,\n ReferenceObject,\n ResponseObject,\n} from 'openapi3-ts/oas31';\nimport { camelcase, pascalcase, spinalcase } from 'stringcase';\n\nimport { removeDuplicates } from '@sdk-it/core';\n\nimport { followRef, jsonSchemaToZod } from './json-zod.ts';\nimport { type Operation, type Spec } from './sdk.ts';\n\nexport interface NamedImport {\n name: string;\n alias?: string;\n isTypeOnly: boolean;\n}\nexport interface Import {\n isTypeOnly: boolean;\n moduleSpecifier: string;\n defaultImport: string | undefined;\n namedImports: NamedImport[];\n namespaceImport: string | undefined;\n}\nfunction isRef(obj: any): obj is ReferenceObject {\n return '$ref' in obj;\n}\n\nconst responses: Record<string, string> = {\n '400': 'BadRequest',\n '401': 'Unauthorized',\n '402': 'PaymentRequired',\n '403': 'Forbidden',\n '404': 'NotFound',\n '405': 'MethodNotAllowed',\n '406': 'NotAcceptable',\n '409': 'Conflict',\n '413': 'PayloadTooLarge',\n '410': 'Gone',\n '422': 'UnprocessableEntity',\n '429': 'TooManyRequests',\n '500': 'InternalServerError',\n '501': 'NotImplemented',\n '502': 'BadGateway',\n '503': 'ServiceUnavailable',\n '504': 'GatewayTimeout',\n};\n\nexport interface GenerateSdkConfig {\n spec: OpenAPIObject;\n target?: 'javascript';\n /**\n * No support for jsdoc in vscode\n * @issue https://github.com/microsoft/TypeScript/issues/38106\n */\n style?: 'github';\n operationId?: (\n operation: OperationObject,\n path: string,\n method: string,\n ) => string;\n}\n\nexport const defaults: Partial<GenerateSdkConfig> &\n Required<Pick<GenerateSdkConfig, 'operationId'>> = {\n target: 'javascript',\n style: 'github',\n operationId: (operation, path, method) => {\n if (operation.operationId) {\n return spinalcase(operation.operationId);\n }\n return (\n operation.operationId ||\n camelcase(`${method} ${path.replace(/\\//g, ' ')}`)\n );\n },\n};\n\nexport function generateCode(config: GenerateSdkConfig) {\n const groups: Spec['groups'] = {};\n const commonSchemas: Record<string, string> = {};\n const outputs: Record<string, string> = {};\n\n for (const [path, methods] of Object.entries(config.spec.paths ?? {})) {\n for (const [method, operation] of Object.entries(methods) as [\n string,\n OperationObject,\n ][]) {\n const formatOperationId = config.operationId ?? defaults.operationId;\n const operationName = formatOperationId(operation, path, method);\n\n console.log(`Processing ${method} ${path}`);\n const groupName = (operation.tags ?? ['unknown'])[0];\n groups[groupName] ??= [];\n const inputs: Operation['inputs'] = {};\n const imports: Import[] = [];\n\n const additionalProperties = [];\n for (const param of operation.parameters ?? []) {\n if (isRef(param)) {\n throw new Error(`Found reference in parameter ${param.$ref}`);\n }\n if (!param.schema) {\n throw new Error(`Schema not found for parameter ${param.name}`);\n }\n inputs[param.name] = {\n source: param.in,\n schema: '',\n };\n additionalProperties.push(param);\n }\n\n const types: Record<string, string> = {};\n const shortContenTypeMap: Record<string, string> = {\n 'application/json': 'json',\n 'application/x-www-form-urlencoded': 'urlencoded',\n 'multipart/form-data': 'formdata',\n 'application/xml': 'xml',\n 'text/plain': 'text',\n };\n let contentType: string | undefined;\n if (operation.requestBody && Object.keys(operation.requestBody).length) {\n const content: ContentObject = isRef(operation.requestBody)\n ? get(followRef(config.spec, operation.requestBody.$ref), ['content'])\n : operation.requestBody.content;\n\n for (const type in content) {\n const schema = isRef(content[type].schema)\n ? followRef(config.spec, content[type].schema.$ref)\n : content[type].schema;\n\n types[shortContenTypeMap[type]] = jsonSchemaToZod(\n config.spec,\n merge(schema, {\n required: additionalProperties\n .filter((p) => p.required)\n .map((p) => p.name),\n properties: additionalProperties.reduce<Record<string, any>>(\n (acc, p) => ({\n ...acc,\n [p.name]: p.schema,\n }),\n {},\n ),\n }),\n true,\n (schemaName, zod) => {\n commonSchemas[schemaName] = zod;\n imports.push({\n defaultImport: undefined,\n isTypeOnly: false,\n moduleSpecifier: '../zod',\n namedImports: [{ isTypeOnly: false, name: schemaName }],\n namespaceImport: undefined,\n });\n },\n );\n }\n\n if (content['application/json']) {\n contentType = 'json';\n } else if (content['application/x-www-form-urlencoded']) {\n contentType = 'urlencoded';\n } else if (content['multipart/form-data']) {\n contentType = 'formdata';\n } else {\n contentType = 'json';\n }\n } else {\n types[shortContenTypeMap['application/json']] = jsonSchemaToZod(\n config.spec,\n {\n type: 'object',\n required: additionalProperties\n .filter((p) => p.required)\n .map((p) => p.name),\n properties: additionalProperties.reduce<Record<string, any>>(\n (acc, p) => ({\n ...acc,\n [p.name]: p.schema,\n }),\n {},\n ),\n },\n true,\n (schemaName, zod) => {\n commonSchemas[schemaName] = zod;\n imports.push({\n defaultImport: undefined,\n isTypeOnly: false,\n moduleSpecifier: './zod',\n namedImports: [{ isTypeOnly: false, name: schemaName }],\n namespaceImport: undefined,\n });\n },\n );\n }\n\n const errors: string[] = [];\n operation.responses ??= {};\n\n let foundResponse = false;\n const output = [`import z from 'zod';`];\n for (const status in operation.responses) {\n const response = operation.responses[status] as ResponseObject;\n const statusCode = +status;\n if (statusCode >= 400) {\n errors.push(responses[status] ?? 'ProblematicResponse');\n }\n if (statusCode >= 200 && statusCode < 300) {\n foundResponse = true;\n const responseContent = get(response, ['content']);\n const isJson = responseContent && responseContent['application/json'];\n // TODO: how the user is going to handle multiple response types\n const responseSchema = isJson\n ? jsonSchemaToZod(\n config.spec,\n responseContent['application/json'].schema!,\n true,\n (schemaName, zod) => {\n commonSchemas[schemaName] = zod;\n imports.push({\n defaultImport: undefined,\n isTypeOnly: false,\n moduleSpecifier: '../zod',\n namedImports: [{ isTypeOnly: false, name: schemaName }],\n namespaceImport: undefined,\n });\n },\n )\n : 'z.instanceof(ReadableStream)'; // non-json response treated as stream\n\n output.push(\n importsToString(mergeImports(Object.values(imports).flat())).join(\n '\\n',\n ),\n );\n output.push(\n `export const ${pascalcase(operationName + ' output')} = ${responseSchema}`,\n );\n }\n }\n\n if (!foundResponse) {\n output.push(\n `export const ${pascalcase(operationName + ' output')} = z.void()`,\n );\n }\n outputs[`${spinalcase(operationName)}.ts`] = output.join('\\n');\n groups[groupName].push({\n name: operationName,\n type: 'http',\n imports: mergeImports(Object.values(imports).flat()),\n inputs,\n errors: errors.length ? errors : ['ServerError'],\n contentType,\n schemas: types,\n formatOutput: () => ({\n import: pascalcase(operationName + ' output'),\n use: `z.infer<typeof ${pascalcase(operationName + ' output')}>`,\n }),\n trigger: {\n path,\n method,\n },\n });\n }\n }\n\n return { groups, commonSchemas, outputs };\n}\n\n// TODO - USE CASES\n// 1. Some parameters conflicts with request body\n// 2. Generate 400 and 500 response variations // done\n// 3. Generate 200 response variations\n// 3. Doc Security\n// 4. Operation Security\n// 5. JsDocs\n// 5. test all different types of parameters\n// 6. cookies\n// 6. x-www-form-urlencoded // done\n// 7. multipart/form-data // done\n// 7. application/octet-stream // done\n// 7. chunked response // done\n// we need to remove the stream fn in the backend\n\nfunction mergeImports(imports: Import[]) {\n const merged: Record<string, Import> = {};\n\n for (const i of imports) {\n merged[i.moduleSpecifier] = merged[i.moduleSpecifier] ?? {\n moduleSpecifier: i.moduleSpecifier,\n defaultImport: i.defaultImport,\n namespaceImport: i.namespaceImport,\n namedImports: [],\n };\n if (i.namedImports) {\n merged[i.moduleSpecifier].namedImports.push(...i.namedImports);\n }\n }\n\n return Object.values(merged);\n}\n\nfunction importsToString(imports: Import[]) {\n return imports.map((i) => {\n if (i.defaultImport) {\n return `import ${i.defaultImport} from '${i.moduleSpecifier}'`;\n }\n if (i.namespaceImport) {\n return `import * as ${i.namespaceImport} from '${i.moduleSpecifier}'`;\n }\n if (i.namedImports) {\n return `import {${removeDuplicates(i.namedImports, (it) => it.name)\n .map((n) => n.name)\n .join(', ')}} from '${i.moduleSpecifier}'`;\n }\n throw new Error(`Invalid import ${JSON.stringify(i)}`);\n });\n}\n", "import { get } from 'lodash-es';\nimport type {\n OpenAPIObject,\n ReferenceObject,\n SchemaObject,\n} from 'openapi3-ts/oas31';\n\n/**\n * Recursively resolve a $ref in the OpenAPI spec.\n */\n\nfunction cleanRef(ref: string) {\n return ref.replace(/^#\\//, '');\n}\n\nfunction parseRef(ref: string) {\n const parts = ref.split(ref);\n const [model] = parts.splice(-1);\n return { model, path: parts.join('/') };\n}\nexport function followRef(\n spec: OpenAPIObject,\n ref: string,\n): SchemaObject | ReferenceObject {\n // Adjust get(...) usage for your data structure\n const pathParts = cleanRef(ref).split('/');\n const entry = get(spec, pathParts) as SchemaObject | ReferenceObject;\n if (entry && '$ref' in entry) {\n return followRef(spec, entry.$ref);\n }\n return entry;\n}\n\ntype OnRefCallback = (ref: string, zod: string) => void;\n\n/**\n * Convert an OpenAPI (JSON Schema style) object into a Zod schema string,\n * adapted for OpenAPI 3.1 (fully aligned with JSON Schema 2020-12).\n */\n\nexport function jsonSchemaToZod(\n spec: OpenAPIObject,\n schema: SchemaObject | ReferenceObject,\n required = false,\n onRef: OnRefCallback,\n circularRefTracker = new Set<string>(), // Add as optional parameter with default value\n): string {\n // If it's a reference, resolve and recurse\n if ('$ref' in schema) {\n const schemaName = cleanRef(schema.$ref).split('/').pop()!;\n\n // Check for circular references\n if (circularRefTracker.has(schemaName)) {\n return schemaName;\n }\n\n circularRefTracker.add(schemaName);\n onRef(\n schemaName,\n jsonSchemaToZod(\n spec,\n followRef(spec, schema.$ref),\n required,\n onRef,\n circularRefTracker,\n ),\n );\n circularRefTracker.delete(schemaName);\n\n return schemaName;\n }\n\n // Handle allOf \u2192 intersection\n if (schema.allOf && Array.isArray(schema.allOf)) {\n const allOfSchemas = schema.allOf.map((sub) =>\n jsonSchemaToZod(spec, sub, true, onRef, circularRefTracker),\n );\n return allOfSchemas.length\n ? `z.intersection(${allOfSchemas.join(', ')})`\n : allOfSchemas[0];\n }\n\n // anyOf \u2192 union\n if (schema.anyOf && Array.isArray(schema.anyOf)) {\n const anyOfSchemas = schema.anyOf.map((sub) =>\n jsonSchemaToZod(spec, sub, false, onRef, circularRefTracker),\n );\n return anyOfSchemas.length > 1\n ? `z.union([${anyOfSchemas.join(', ')}])${appendOptional(required)}`\n : // Handle an invalid anyOf with one schema\n anyOfSchemas[0];\n }\n\n // oneOf \u2192 union\n if (schema.oneOf && Array.isArray(schema.oneOf)) {\n const oneOfSchemas = schema.oneOf.map((sub) => {\n if ('$ref' in sub) {\n const { model } = parseRef(sub.$ref);\n if (circularRefTracker.has(model)) {\n return model;\n }\n }\n return jsonSchemaToZod(spec, sub, false, onRef, circularRefTracker);\n });\n return oneOfSchemas.length > 1\n ? `z.union([${oneOfSchemas.join(', ')}])${appendOptional(required)}`\n : // Handle an invalid oneOf with one schema\n oneOfSchemas[0];\n }\n\n // enum\n if (schema.enum && Array.isArray(schema.enum)) {\n const enumVals = schema.enum.map((val) => JSON.stringify(val)).join(', ');\n return `z.enum([${enumVals}])${appendOptional(required)}`;\n }\n\n // 3.1 can have type: string or type: string[] (e.g. [\"string\",\"null\"])\n // Let's parse that carefully.\n const types = Array.isArray(schema.type)\n ? schema.type\n : schema.type\n ? [schema.type]\n : [];\n\n // If no explicit \"type\", fallback to unknown\n if (!types.length) {\n return `z.unknown()${appendOptional(required)}`;\n }\n\n // If it's a union type (like [\"string\", \"null\"]), we'll build a Zod union\n // or apply .nullable() if it's just \"type + null\".\n if (types.length > 1) {\n // If it\u2019s exactly one real type plus \"null\", we can do e.g. `z.string().nullable()`\n const realTypes = types.filter((t) => t !== 'null');\n if (realTypes.length === 1 && types.includes('null')) {\n // Single real type + \"null\"\n const typeZod = basicTypeToZod(\n realTypes[0],\n schema,\n spec,\n false,\n onRef,\n circularRefTracker,\n );\n return `${typeZod}.nullable()${appendOptional(required)}`;\n }\n // If multiple different types, build a union\n const subSchemas = types.map((t) =>\n basicTypeToZod(t, schema, spec, false, onRef, circularRefTracker),\n );\n return `z.union([${subSchemas.join(', ')}])${appendOptional(required)}`;\n }\n\n // If there's exactly one type\n return basicTypeToZod(\n types[0],\n schema,\n spec,\n required,\n onRef,\n circularRefTracker,\n );\n}\n\n/**\n * Convert a basic type (string | number | boolean | object | array, etc.) to Zod.\n * We'll also handle .optional() if needed.\n */\nfunction basicTypeToZod(\n type: string,\n schema: SchemaObject,\n spec: OpenAPIObject,\n required = false,\n onRef: OnRefCallback,\n refProcessingStack: Set<string>,\n): string {\n switch (type) {\n case 'string':\n return handleString(schema, required);\n case 'number':\n case 'integer':\n return handleNumber(schema, required);\n case 'boolean':\n return `z.boolean()${appendDefault(schema.default)}${appendOptional(required)}`;\n case 'object':\n return handleObject(schema, spec, required, onRef, refProcessingStack);\n case 'array':\n return handleArray(schema, spec, required, onRef, refProcessingStack);\n case 'null':\n // If \"type\": \"null\" alone, this is basically z.null()\n return `z.null()${appendOptional(required)}`;\n default:\n // Unknown type -> fallback\n return `z.unknown()${appendOptional(required)}`;\n }\n}\n\n/**\n * Handle a `string` schema with possible format keywords (JSON Schema).\n */\nfunction handleString(schema: SchemaObject, required?: boolean): string {\n let base = 'z.string()';\n\n // 3.1 replaces `example` in the schema with `examples` (array).\n // We do not strictly need them for the Zod type, so they\u2019re optional\n // for validation. However, we could keep them as metadata if you want.\n\n switch (schema.format) {\n case 'date-time':\n case 'datetime':\n // parse to JS Date\n base = 'z.coerce.date()';\n break;\n case 'date':\n base = 'z.coerce.date() /* or z.string() if you want raw date strings */';\n break;\n case 'time':\n base = 'z.string() /* optionally add .regex(...) for HH:MM:SS format */';\n break;\n case 'email':\n base = 'z.string().email()';\n break;\n case 'uuid':\n base = 'z.string().uuid()';\n break;\n case 'url':\n case 'uri':\n base = 'z.string().url()';\n break;\n case 'ipv4':\n base = 'z.string().ip({version: \"v4\"})';\n break;\n case 'ipv6':\n base = 'z.string().ip({version: \"v6\"})';\n break;\n case 'phone':\n base = 'z.string() /* or add .regex(...) for phone formats */';\n break;\n case 'byte':\n case 'binary':\n base = 'z.instanceof(Blob) /* consider base64 check if needed */';\n break;\n case 'int64':\n // JS numbers can't reliably store int64, consider z.bigint() or keep as string\n base = 'z.string() /* or z.bigint() if your app can handle it */';\n break;\n default:\n // No special format\n break;\n }\n\n return `${base}${appendDefault(schema.default)}${appendOptional(required)}`;\n}\n\n/**\n * Handle number/integer constraints from OpenAPI/JSON Schema.\n * In 3.1, exclusiveMinimum/Maximum hold the actual numeric threshold,\n * rather than a boolean toggling `minimum`/`maximum`.\n */\nfunction handleNumber(schema: SchemaObject, required?: boolean): string {\n let defaultValue =\n schema.default !== undefined ? `.default(${schema.default})` : ``;\n let base = 'z.number()';\n if (schema.format === 'int64') {\n base = 'z.bigint()';\n if (schema.default !== undefined) {\n defaultValue = `.default(BigInt(${schema.default}))`;\n }\n }\n\n if (schema.format === 'int32') {\n // 32-bit integer\n base += '.int()';\n }\n\n // If we see exclusiveMinimum as a number in 3.1:\n if (typeof schema.exclusiveMinimum === 'number') {\n // Zod doesn\u2019t have a direct \"exclusiveMinimum\" method, so we can do .gt()\n // If exclusiveMinimum=7 => .gt(7)\n base += `.gt(${schema.exclusiveMinimum})`;\n }\n // Similarly for exclusiveMaximum\n if (typeof schema.exclusiveMaximum === 'number') {\n // If exclusiveMaximum=10 => .lt(10)\n base += `.lt(${schema.exclusiveMaximum})`;\n }\n\n // If standard minimum/maximum\n if (typeof schema.minimum === 'number') {\n base +=\n schema.format === 'int64'\n ? `.min(BigInt(${schema.minimum}))`\n : `.min(${schema.minimum})`;\n }\n if (typeof schema.maximum === 'number') {\n base +=\n schema.format === 'int64'\n ? `.max(BigInt(${schema.maximum}))`\n : `.max(${schema.maximum})`;\n }\n\n // multipleOf\n if (typeof schema.multipleOf === 'number') {\n // There's no direct multipleOf in Zod. Some folks do a custom refine.\n // For example:\n base += `.refine((val) => Number.isInteger(val / ${schema.multipleOf}), \"Must be a multiple of ${schema.multipleOf}\")`;\n }\n\n return `${base}${defaultValue}${appendOptional(required)}`;\n}\n\n/**\n * Handle objects (properties, additionalProperties).\n */\nfunction handleObject(\n schema: SchemaObject,\n spec: OpenAPIObject,\n required = false,\n onRef: OnRefCallback,\n refProcessingStack: Set<string>,\n): string {\n const properties = schema.properties || {};\n\n // Convert each property\n const propEntries = Object.entries(properties).map(([key, propSchema]) => {\n const isRequired = (schema.required ?? []).includes(key);\n const zodPart = jsonSchemaToZod(\n spec,\n propSchema,\n isRequired,\n onRef,\n refProcessingStack,\n );\n return `'${key}': ${zodPart}`;\n });\n\n // additionalProperties\n let additionalProps = '';\n if (schema.additionalProperties) {\n if (typeof schema.additionalProperties === 'object') {\n // e.g. z.record() if it\u2019s an object schema\n const addPropZod = jsonSchemaToZod(\n spec,\n schema.additionalProperties,\n true,\n onRef,\n refProcessingStack,\n );\n additionalProps = `.catchall(${addPropZod})`;\n } else if (schema.additionalProperties === true) {\n // free-form additional props\n additionalProps = `.catchall(z.unknown())`;\n }\n }\n\n const objectSchema = `z.object({${propEntries.join(', ')}})${additionalProps}`;\n return `${objectSchema}${appendOptional(required)}`;\n}\n\n/**\n * Handle arrays (items could be a single schema or a tuple (array of schemas)).\n * In JSON Schema 2020-12, `items` can be an array \u2192 tuple style.\n */\nfunction handleArray(\n schema: SchemaObject,\n spec: OpenAPIObject,\n required = false,\n onRef: OnRefCallback,\n refProcessingStack: Set<string>,\n): string {\n const { items } = schema;\n if (!items) {\n // No items => z.array(z.unknown())\n return `z.array(z.unknown())${appendOptional(required)}`;\n }\n\n // If items is an array => tuple\n if (Array.isArray(items)) {\n // Build a Zod tuple\n const tupleItems = items.map((sub) =>\n jsonSchemaToZod(spec, sub, true, onRef, refProcessingStack),\n );\n const base = `z.tuple([${tupleItems.join(', ')}])`;\n // // If we have additionalItems: false => that\u2019s a fixed length\n // // If additionalItems is a schema => rest(...)\n // if (schema.additionalItems) {\n // if (typeof schema.additionalItems === 'object') {\n // const restSchema = jsonSchemaToZod(spec, schema.additionalItems, true);\n // base += `.rest(${restSchema})`;\n // }\n // // If `additionalItems: false`, no rest is allowed => do nothing\n // }\n return `${base}${appendOptional(required)}`;\n }\n\n // If items is a single schema => standard z.array(...)\n const itemsSchema = jsonSchemaToZod(\n spec,\n items,\n true,\n onRef,\n refProcessingStack,\n );\n return `z.array(${itemsSchema})${appendOptional(required)}`;\n}\n\n/**\n * Append .optional() if not required\n */\nfunction appendOptional(isRequired?: boolean) {\n return isRequired ? '' : '.optional()';\n}\nfunction appendDefault(defaultValue?: any) {\n return defaultValue !== undefined\n ? `.default(${JSON.stringify(defaultValue)})`\n : '';\n}\n\n// Todo: convert openapi 3.0 to 3.1 before proccesing\n", "import { camelcase, pascalcase, spinalcase } from 'stringcase';\n\nimport { removeDuplicates, toLitObject } from '@sdk-it/core';\n\nimport backend from './client.ts';\n\nexport interface Import {\n isTypeOnly: boolean;\n moduleSpecifier: string;\n defaultImport: string | undefined;\n namedImports: NamedImport[];\n namespaceImport: string | undefined;\n}\nexport interface NamedImport {\n name: string;\n alias?: string;\n isTypeOnly: boolean;\n}\n\nclass SchemaEndpoint {\n #imports: string[] = [\n `import z from 'zod';`,\n 'import type { Endpoints } from \"./endpoints.ts\";',\n `import { toRequest, json, urlencoded, formdata, createUrl } from './http/request.ts';`,\n `import type { ParseError } from './http/parser.ts';`,\n ];\n #endpoints: string[] = [];\n addEndpoint(endpoint: string, operation: any) {\n this.#endpoints.push(` \"${endpoint}\": ${operation},`);\n }\n addImport(value: string) {\n this.#imports.push(value);\n }\n complete() {\n return `${this.#imports.join('\\n')}\\nexport default {\\n${this.#endpoints.join('\\n')}\\n}`;\n }\n}\nclass Emitter {\n protected imports: string[] = [\n `import z from 'zod';`,\n `import type { ParseError } from './http/parser.ts';`,\n ];\n protected endpoints: string[] = [];\n addEndpoint(endpoint: string, operation: any) {\n this.endpoints.push(` \"${endpoint}\": ${operation};`);\n }\n addImport(value: string) {\n this.imports.push(value);\n }\n complete() {\n return `${this.imports.join('\\n')}\\nexport interface Endpoints {\\n${this.endpoints.join('\\n')}\\n}`;\n }\n}\nclass StreamEmitter extends Emitter {\n override complete() {\n return `${this.imports.join('\\n')}\\nexport interface StreamEndpoints {\\n${this.endpoints.join('\\n')}\\n}`;\n }\n}\n\nexport interface SecurityScheme {\n bearerAuth: {\n type: 'http';\n scheme: 'bearer';\n bearerFormat: 'JWT';\n };\n}\n\nexport interface SdkConfig {\n /**\n * The name of the sdk client\n */\n name: string;\n packageName?: string;\n options?: Record<string, any>;\n emptyBodyAsNull?: boolean;\n stripBodyFromGetAndHead?: boolean;\n securityScheme?: SecurityScheme;\n output: string;\n formatGeneratedCode?: boolean;\n}\n\nexport interface Spec {\n groups: Record<string, Operation[]>;\n commonZod?: string;\n name: string;\n options?: Record<\n string,\n {\n in: 'header';\n schema: string;\n }\n >;\n securityScheme?: SecurityScheme;\n servers?: string[];\n}\n\nexport interface OperationInput {\n source: string;\n schema: string;\n}\nexport interface Operation {\n name: string;\n errors: string[];\n type: string;\n imports: Import[];\n trigger: Record<string, any>;\n contentType?: string;\n schemas: Record<string, string>;\n schema?: string;\n inputs: Record<string, OperationInput>;\n formatOutput: () => { import: string; use: string };\n}\n\nexport function generateClientSdk(spec: Spec) {\n const emitter = new Emitter();\n const streamEmitter = new StreamEmitter();\n const schemas: Record<string, string[]> = {};\n const schemasImports: string[] = [];\n const schemaEndpoint = new SchemaEndpoint();\n const errors: string[] = [];\n for (const [name, operations] of Object.entries(spec.groups)) {\n const featureSchemaFileName = camelcase(name);\n schemas[featureSchemaFileName] = [`import z from 'zod';`];\n emitter.addImport(\n `import * as ${featureSchemaFileName} from './inputs/${featureSchemaFileName}.ts';`,\n );\n streamEmitter.addImport(\n `import * as ${featureSchemaFileName} from './inputs/${featureSchemaFileName}.ts';`,\n );\n schemaEndpoint.addImport(\n `import * as ${featureSchemaFileName} from './inputs/${featureSchemaFileName}.ts';`,\n );\n for (const operation of operations) {\n const schemaName = camelcase(`${operation.name} schema`);\n\n const schema = `export const ${schemaName} = ${\n Object.keys(operation.schemas).length === 1\n ? Object.values(operation.schemas)[0]\n : toLitObject(operation.schemas)\n };`;\n\n schemas[featureSchemaFileName].push(schema);\n schemasImports.push(\n ...operation.imports\n .map((it) => (it.namedImports ?? []).map((it) => it.name))\n .flat(),\n );\n const schemaRef = `${featureSchemaFileName}.${schemaName}`;\n const output = operation.formatOutput();\n const inputHeaders: string[] = [];\n const inputQuery: string[] = [];\n const inputBody: string[] = [];\n const inputParams: string[] = [];\n for (const [name, prop] of Object.entries(operation.inputs)) {\n if (prop.source === 'headers' || prop.source === 'header') {\n inputHeaders.push(`\"${name}\"`);\n } else if (prop.source === 'query') {\n inputQuery.push(`\"${name}\"`);\n } else if (prop.source === 'body') {\n inputBody.push(`\"${name}\"`);\n } else if (prop.source === 'path') {\n inputParams.push(`\"${name}\"`);\n } else if (prop.source === 'internal') {\n // ignore internal sources\n continue;\n } else {\n throw new Error(\n `Unknown source ${prop.source} in ${name} ${JSON.stringify(\n prop,\n )} in ${operation.name}`,\n );\n }\n }\n if (operation.type === 'sse') {\n const input = `z.infer<typeof ${schemaRef}>`;\n const endpoint = `${operation.trigger.method.toUpperCase()} ${operation.trigger.path}`;\n streamEmitter.addImport(\n `import type {${pascalcase(operation.name)}} from './outputs/${spinalcase(operation.name)}';`,\n );\n streamEmitter.addEndpoint(\n endpoint,\n `{input: ${input}, output: ${output.use}}`,\n );\n schemaEndpoint.addEndpoint(\n endpoint,\n `{\n schema: ${schemaRef},\n toRequest(input: StreamEndpoints['${endpoint}']['input'], init: {baseUrl:string; headers?: Record<string, string>}) {\n const endpoint = '${endpoint}';\n return toRequest(endpoint, json(input, {\n inputHeaders: [${inputHeaders}],\n inputQuery: [${inputQuery}],\n inputBody: [${inputBody}],\n inputParams: [${inputParams}],\n }), init);\n },\n }`,\n );\n } else {\n emitter.addImport(\n `import type {${output.import}} from './outputs/${spinalcase(operation.name)}';`,\n );\n errors.push(...(operation.errors ?? []));\n\n const addTypeParser = Object.keys(operation.schemas).length > 1;\n for (const type in operation.schemas ?? {}) {\n let typePrefix = '';\n if (addTypeParser && type !== 'json') {\n typePrefix = `${type} `;\n }\n const input = `typeof ${schemaRef}${addTypeParser ? `.${type}` : ''}`;\n\n const endpoint = `${typePrefix}${operation.trigger.method.toUpperCase()} ${operation.trigger.path}`;\n emitter.addEndpoint(\n endpoint,\n `{input: z.infer<${input}>; output: ${output.use}; error: ${(operation.errors ?? ['ServerError']).concat(`ParseError<${input}>`).join('|')}}`,\n );\n schemaEndpoint.addEndpoint(\n endpoint,\n `{\n schema: ${schemaRef}${addTypeParser ? `.${type}` : ''},\n toRequest(input: Endpoints['${endpoint}']['input'], init: {baseUrl:string; headers?: Record<string, string>}) {\n const endpoint = '${endpoint}';\n return toRequest(endpoint, ${operation.contentType || 'json'}(input, {\n inputHeaders: [${inputHeaders}],\n inputQuery: [${inputQuery}],\n inputBody: [${inputBody}],\n inputParams: [${inputParams}],\n }), init);\n },\n }`,\n );\n }\n }\n }\n }\n\n emitter.addImport(\n `import type { ${removeDuplicates(errors, (it) => it).join(', ')} } from './http/response.ts';`,\n );\n return {\n ...Object.fromEntries(\n Object.entries(schemas).map(([key, value]) => [\n `inputs/${key}.ts`,\n [\n schemasImports.length\n ? `import {${removeDuplicates(schemasImports, (it) => it)}} from '../zod';`\n : '',\n spec.commonZod ? 'import * as commonZod from \"../zod.ts\";' : '',\n ...value,\n ]\n .map((it) => it.trim())\n .filter(Boolean)\n .join('\\n') + '\\n', // add a newline at the end\n ]),\n ),\n 'backend.ts': backend(spec),\n 'schemas.ts': schemaEndpoint.complete(),\n 'endpoints.ts': emitter.complete(),\n };\n}\n", "import { titlecase } from 'stringcase';\n\nimport { toLitObject } from '@sdk-it/core';\n\nimport type { Spec } from './sdk.ts';\n\nexport default (spec: Spec) => {\n const specOptions: Record<string, { schema: string }> = {\n ...(spec.options ?? {}),\n fetch: {\n schema: 'fetchType',\n },\n baseUrl: {\n schema: `z.enum(servers).default(servers[0])`,\n },\n };\n if (spec.securityScheme) {\n specOptions['token'] = { schema: 'z.string().optional()' };\n }\n const defaultHeaders = spec.securityScheme\n ? `{Authorization: \\`${titlecase(spec.securityScheme.bearerAuth.scheme)} \\${this.options.token}\\`}`\n : `{}`;\n\n return `\nimport { fetchType, sendRequest } from './http/send-request.ts';\nimport z from 'zod';\nimport type { Endpoints } from './endpoints.ts';\nimport schemas from './schemas.ts';\n\n const servers = ${JSON.stringify(spec.servers || [], null, 2)} as const;\n const optionsSchema = z.object(${toLitObject(specOptions, (x) => x.schema)});\n type ${spec.name}Options = z.infer<typeof optionsSchema>;\n export class ${spec.name} {\n\n constructor(public options: ${spec.name}Options) {}\n\n async request<E extends keyof Endpoints>(\n endpoint: E,\n input: Endpoints[E]['input'],\n ): Promise<readonly [Endpoints[E]['output'], Endpoints[E]['error'] | null]> {\n const route = schemas[endpoint];\n return sendRequest(input, route, {\n baseUrl: this.options.baseUrl,\n fetch: this.options.fetch,\n headers: this.defaultHeaders,\n });\n }\n\n get defaultHeaders() {\n return ${defaultHeaders}\n }\n\n setOptions(options: Partial<${spec.name}Options>) {\n const validated = optionsSchema.partial().parse(options);\n\n for (const key of Object.keys(validated) as (keyof ${spec.name}Options)[]) {\n if (validated[key] !== undefined) {\n (this.options[key] as typeof validated[typeof key]) = validated[key]!;\n }\n }\n }\n}`;\n};\n", "import { parse } from 'fast-content-type-parse';\n\nexport async function handleError(response: Response) {\n try {\n if (response.status >= 400 && response.status < 500) {\n const body = (await response.json()) as Record<string, any>;\n return {\n status: response.status,\n body: body,\n };\n }\n return new Error(\n `An error occurred while fetching the data. Status: ${response.status}`,\n );\n } catch (error) {\n return error as any;\n }\n}\n\nasync function handleChunkedResponse(response: Response, contentType: string) {\n const { type } = parse(contentType);\n\n switch (type) {\n case 'application/json': {\n let buffer = '';\n const reader = response.body!.getReader();\n const decoder = new TextDecoder();\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value);\n }\n return JSON.parse(buffer);\n }\n case 'text/html':\n case 'text/plain': {\n let buffer = '';\n const reader = response.body!.getReader();\n const decoder = new TextDecoder();\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n buffer += decoder.decode(value);\n }\n return buffer;\n }\n default:\n return response.body;\n }\n}\n\nexport async function parseResponse(response: Response) {\n const contentType = response.headers.get('Content-Type');\n if (!contentType) {\n throw new Error('Content-Type header is missing');\n }\n\n if (response.status === 204) {\n return null;\n }\n const isChunked = response.headers.get('Transfer-Encoding') === 'chunked';\n if (isChunked) {\n return response.body!;\n // return handleChunkedResponse(response, contentType);\n }\n\n const { type } = parse(contentType);\n switch (type) {\n case 'application/json':\n return response.json();\n case 'text/plain':\n return response.text();\n case 'text/html':\n return response.text();\n case 'text/xml':\n case 'application/xml':\n return response.text();\n case 'application/x-www-form-urlencoded': {\n const text = await response.text();\n return Object.fromEntries(new URLSearchParams(text));\n }\n case 'multipart/form-data':\n return response.formData();\n default:\n throw new Error(`Unsupported content type: ${contentType}`);\n }\n}\n", "import { z } from 'zod';\n\nexport type ParseError<T extends z.ZodType<any, any, any>> = {\n kind: 'parse';\n} & z.inferFlattenedErrors<T>;\n\nexport function parse<T extends z.ZodType>(\n schema: T,\n input: unknown,\n) {\n const result = schema.safeParse(input);\n if (!result.success) {\n const errors = result.error.flatten((issue) => issue);\n return [null, errors];\n }\n return [result.data as z.infer<T>, null];\n}\n", "type Method = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';\ntype ContentType = 'xml' | 'json' | 'urlencoded' | 'multipart';\ntype Endpoint = `${ContentType} ${Method} ${string}` | `${Method} ${string}`;\n\nexport function createUrl(base: string, path: string, query: URLSearchParams) {\n const url = new URL(path, base);\n url.search = query.toString();\n return url;\n}\nfunction template(\n templateString: string,\n templateVariables: Record<string, any>,\n): string {\n const nargs = /{([0-9a-zA-Z_]+)}/g;\n return templateString.replace(nargs, (match, key: string, index: number) => {\n // Handle escaped double braces\n if (\n templateString[index - 1] === '{' &&\n templateString[index + match.length] === '}'\n ) {\n return key;\n }\n\n const result = key in templateVariables ? templateVariables[key] : null;\n return result === null || result === undefined ? '' : String(result);\n });\n}\n\ninterface ToRequest {\n <T extends Endpoint>(\n endpoint: T,\n input: Record<string, any>,\n props: {\n inputHeaders: string[];\n inputQuery: string[];\n inputBody: string[];\n inputParams: string[];\n },\n defaults: {\n baseUrl: string;\n headers?: Record<string, string>;\n },\n ): Request;\n urlencoded: <T extends Endpoint>(\n endpoint: T,\n input: Record<string, any>,\n props: {\n inputHeaders: string[];\n inputQuery: string[];\n inputBody: string[];\n inputParams: string[];\n },\n defaults: {\n baseUrl: string;\n headers?: Record<string, string>;\n },\n ) => Request;\n}\n\nfunction _json(\n input: Record<string, any>,\n props: {\n inputHeaders: string[];\n inputQuery: string[];\n inputBody: string[];\n inputParams: string[];\n },\n) {\n const headers = new Headers({});\n for (const header of props.inputHeaders) {\n headers.set(header, input[header]);\n }\n\n const body: Record<string, any> = {};\n for (const prop of props.inputBody) {\n body[prop] = input[prop];\n }\n\n const query = new URLSearchParams();\n for (const key of props.inputQuery) {\n const value = input[key];\n if (value !== undefined) {\n query.set(key, String(value));\n }\n }\n\n const params = props.inputParams.reduce<Record<string, any>>((acc, key) => {\n acc[key] = input[key];\n return acc;\n }, {});\n\n return {\n body: JSON.stringify(body),\n query,\n params,\n headers: { 'Content-Type': 'application/json', Accept: 'application/json' },\n };\n}\n\ntype Input = Record<string, any>;\ntype Props = {\n inputHeaders: string[];\n inputQuery: string[];\n inputBody: string[];\n inputParams: string[];\n};\n\nabstract class Serializer {\n constructor(\n protected input: Input,\n protected props: Props,\n ) {}\n abstract getBody(): BodyInit | null;\n abstract getHeaders(): Record<string, string>;\n serialize(): Serialized {\n const headers = new Headers({});\n for (const header of this.props.inputHeaders) {\n headers.set(header, this.input[header]);\n }\n\n const query = new URLSearchParams();\n for (const key of this.props.inputQuery) {\n const value = this.input[key];\n if (value !== undefined) {\n query.set(key, String(value));\n }\n }\n\n const params = this.props.inputParams.reduce<Record<string, any>>(\n (acc, key) => {\n acc[key] = this.input[key];\n return acc;\n },\n {},\n );\n\n return {\n body: this.getBody(),\n query,\n params,\n headers: this.getHeaders(),\n };\n }\n}\n\ninterface Serialized {\n body: BodyInit | null;\n query: URLSearchParams;\n params: Record<string, any>;\n headers: Record<string, string>;\n}\n\nclass JsonSerializer extends Serializer {\n getBody(): BodyInit | null {\n const body: Record<string, any> = {};\n for (const prop of this.props.inputBody) {\n body[prop] = this.input[prop];\n }\n return JSON.stringify(body);\n }\n getHeaders(): Record<string, string> {\n return {\n 'Content-Type': 'application/json',\n Accept: 'application/json',\n };\n }\n}\n\nclass UrlencodedSerializer extends Serializer {\n getBody(): BodyInit | null {\n const body = new URLSearchParams();\n for (const prop of this.props.inputBody) {\n body.set(prop, this.input[prop]);\n }\n return body;\n }\n getHeaders(): Record<string, string> {\n return {};\n }\n}\n\nclass FormDataSerializer extends Serializer {\n getBody(): BodyInit | null {\n const body = new FormData();\n for (const prop of this.props.inputBody) {\n body.append(prop, this.input[prop]);\n }\n return body;\n }\n getHeaders(): Record<string, string> {\n return {};\n }\n}\n\nexport function json(input: Input, props: Props) {\n return new JsonSerializer(input, props).serialize();\n}\nexport function urlencoded(input: Input, props: Props) {\n return new UrlencodedSerializer(input, props).serialize();\n}\nexport function formdata(input: Input, props: Props) {\n return new FormDataSerializer(input, props).serialize();\n}\n\nexport function _urlencoded(\n input: Record<string, any>,\n props: {\n inputHeaders: string[];\n inputQuery: string[];\n inputBody: string[];\n inputParams: string[];\n },\n) {\n const headers = new Headers({});\n for (const header of props.inputHeaders) {\n headers.set(header, input[header]);\n }\n\n const body = new URLSearchParams();\n for (const prop of props.inputBody) {\n body.set(prop, input[prop]);\n }\n\n const query = new URLSearchParams();\n for (const key of props.inputQuery) {\n const value = input[key];\n if (value !== undefined) {\n query.set(key, String(value));\n }\n }\n\n const params = props.inputParams.reduce<Record<string, any>>((acc, key) => {\n acc[key] = input[key];\n return acc;\n }, {});\n\n return {\n body,\n query,\n params,\n headers: {},\n };\n}\n\nexport function toRequest<T extends Endpoint>(\n endpoint: T,\n input: Serialized,\n defaults: {\n baseUrl: string;\n headers?: Record<string, string>;\n },\n): Request {\n const [method, path] = endpoint.split(' ');\n\n const headers = new Headers({\n ...defaults?.headers,\n ...input.headers,\n });\n const pathVariable = template(path, input.params);\n\n const url = createUrl(defaults.baseUrl, pathVariable, input.query);\n return new Request(url, {\n method: method,\n headers: headers,\n body: method === 'GET' ? undefined : input.body,\n });\n}\n", "export interface ApiResponse<Status extends number, Body extends unknown> {\n kind: 'response';\n status: Status;\n body: Body;\n}\n\n// 4xx Client Errors\nexport type BadRequest = ApiResponse<400, { message: string }>;\nexport type Unauthorized = ApiResponse<401, { message: string }>;\nexport type PaymentRequired = ApiResponse<402, { message: string }>;\nexport type Forbidden = ApiResponse<403, { message: string }>;\nexport type NotFound = ApiResponse<404, { message: string }>;\nexport type MethodNotAllowed = ApiResponse<405, { message: string }>;\nexport type NotAcceptable = ApiResponse<406, { message: string }>;\nexport type Conflict = ApiResponse<409, { message: string }>;\nexport type Gone = ApiResponse<410, { message: string }>;\nexport type UnprocessableEntity = ApiResponse<422, { message: string; errors?: Record<string, string[]> }>;\nexport type TooManyRequests = ApiResponse<429, { message: string; retryAfter?: string }>;\nexport type PayloadTooLarge = ApiResponse<413, { message: string; }>;\nexport type UnsupportedMediaType = ApiResponse<415, { message: string; }>;\n\n// 5xx Server Errors\nexport type InternalServerError = ApiResponse<500, { message: string }>;\nexport type NotImplemented = ApiResponse<501, { message: string }>;\nexport type BadGateway = ApiResponse<502, { message: string }>;\nexport type ServiceUnavailable = ApiResponse<503, { message: string; retryAfter?: string }>;\nexport type GatewayTimeout = ApiResponse<504, { message: string }>;\n\nexport type ClientError =\n | BadRequest\n | Unauthorized\n | PaymentRequired\n | Forbidden\n | NotFound\n | MethodNotAllowed\n | NotAcceptable\n | Conflict\n | Gone\n | UnprocessableEntity\n | TooManyRequests;\n\nexport type ServerError =\n | InternalServerError\n | NotImplemented\n | BadGateway\n | ServiceUnavailable\n | GatewayTimeout;\n\nexport type ProblematicResponse = ClientError | ServerError;\n", "import z from 'zod';\n\nimport { handleError, parseResponse } from './parse-response.ts';\nimport { parse } from './parser.ts';\n\nexport interface RequestSchema {\n schema: z.ZodType;\n toRequest: (\n input: any,\n init: { baseUrl: string; headers?: Record<string, string> },\n ) => any;\n}\n\nexport const fetchType = z\n .function()\n .args(z.instanceof(Request))\n .returns(z.promise(z.instanceof(Response)))\n .optional();\n\nexport async function sendRequest(\n input: any,\n route: RequestSchema,\n options: {\n baseUrl: string;\n fetch?: z.infer<typeof fetchType>;\n headers?: Record<string, string>;\n },\n) {\n const [parsedInput, parseError] = parse(route.schema, input);\n if (parseError) {\n return [null as never, { ...parseError, kind: 'parse' } as never] as const;\n }\n const request = route.toRequest(parsedInput as never, {\n headers: options.headers,\n baseUrl: options.baseUrl,\n });\n const response = await (options.fetch ?? fetch)(request);\n if (response.ok) {\n const data = await parseResponse(response);\n return [data, null] as const;\n }\n const error = await handleError(response);\n return [null as never, { ...error, kind: 'response' }] as const;\n}\n", "import type {\n ExampleObject,\n OpenAPIObject,\n OperationObject,\n ParameterObject,\n PathItemObject,\n ReferenceObject,\n RequestBodyObject,\n ResponseObject,\n SchemaObject,\n Server,\n ServerObject,\n} from 'openapi3-ts/oas31';\nimport { pascalcase } from 'stringcase';\n\nimport { type Method } from '@sdk-it/core';\n\nimport { followRef } from './json-zod.ts';\n\n/**\n * Generate README.md documentation directly from OpenAPI spec\n */\nexport function generateReadme(\n spec: OpenAPIObject,\n settings: { name: string },\n): string {\n const title = spec.info?.title || 'API Client';\n const description =\n spec.info?.description || 'API client generated from OpenAPI specification';\n const version = spec.info?.version || '1.0.0';\n\n // Get server URLs if available\n const servers = spec.servers || [];\n const defaultServerUrl =\n servers.length > 0 ? servers[0].url : 'https://api.example.com';\n\n // Security scheme\n const securityScheme = extractSecurityScheme(spec);\n\n // Extract all operations and organize by tags\n const operationsByTag = extractOperationsByTag(spec);\n\n // Header section\n let markdown = `# ${title} SDK\\n\\n`;\n markdown += `${description}\\n\\n`;\n markdown += `Version: ${version}\\n\\n`;\n\n // Installation section\n markdown += `## Installation\\n\\n`;\n markdown += `\\`\\`\\`bash\\n`;\n markdown += `npm install ${title.toLowerCase().replace(/\\s+/g, '-')}-sdk\\n`;\n markdown += `\\`\\`\\`\\n\\n`;\n\n // Getting started section\n markdown += `## Getting Started\\n\\n`;\n markdown += `\\`\\`\\`typescript\\n`;\n markdown += `import { ${settings.name} } from '${title.toLowerCase().replace(/\\s+/g, '-')}-sdk';\\n\\n`;\n markdown += `// Initialize the client\\n`;\n markdown += `const client = new ${settings.name}({\\n`;\n markdown += ` baseUrl: '${defaultServerUrl}',\\n`;\n\n // Add security if needed\n if (securityScheme) {\n markdown += ` token: 'your-auth-token', // Required for authenticated endpoints\\n`;\n }\n\n markdown += `});\\n\\n`;\n markdown += `// Example request\\n`;\n\n // Generate example using first available endpoint\n const firstTag = Object.keys(operationsByTag)[0];\n if (firstTag && operationsByTag[firstTag].length > 0) {\n const firstOp = operationsByTag[firstTag][0];\n const exampleParams = generateExampleParams(firstOp.operation, spec);\n\n markdown += `const [data, error] = await client.request('${firstOp.method.toUpperCase()} ${firstOp.path}', ${\n Object.keys(exampleParams).length > 0\n ? formatExample(exampleParams)\n : '{}\\n'\n });\\n\\n`;\n } else {\n markdown += `const [data, error] = await client.request('GET /example', {});\\n\\n`;\n }\n\n markdown += `if (error) {\\n`;\n markdown += ` console.error('Error:', error);\\n`;\n markdown += `} else {\\n`;\n markdown += ` console.log('Success:', data);\\n`;\n markdown += `}\\n`;\n markdown += `\\`\\`\\`\\n\\n`;\n\n // API Reference section\n markdown += `## API Reference\\n\\n`;\n\n // Group operations by tag\n for (const [tagName, operations] of Object.entries(operationsByTag)) {\n markdown += `### ${pascalcase(tagName)}\\n\\n`;\n\n for (const opInfo of operations) {\n markdown += generateEndpointDocs(spec, opInfo);\n }\n }\n\n // Add servers section if available\n if (servers.length > 0) {\n markdown += generateServersSection(servers);\n }\n\n return markdown;\n}\n\ninterface OperationInfo {\n path: string;\n method: Method;\n operation: OperationObject;\n errors: string[];\n inputs: Record<string, { source: string }>;\n}\n\n/**\n * Extract operations from spec and organize by tags\n */\nfunction extractOperationsByTag(\n spec: OpenAPIObject,\n): Record<string, OperationInfo[]> {\n const operationsByTag: Record<string, OperationInfo[]> = {};\n\n // Process all paths and their operations\n for (const [path, pathItem] of Object.entries(spec.paths || {})) {\n for (const [methodName, operation] of Object.entries(pathItem || {})) {\n // Skip non-operation properties like parameters, etc.\n if (\n ['parameters', 'servers', 'summary', 'description', '$ref'].includes(\n methodName,\n )\n ) {\n continue;\n }\n\n const method = methodName.toLowerCase() as Method;\n const opObject = operation as OperationObject;\n\n // Determine tags, defaulting to 'general' if none specified\n const tags = opObject.tags?.length ? opObject.tags : ['general'];\n\n // Extract error responses\n const errors = extractErrorResponses(opObject.responses || {});\n\n // Extract inputs (parameters)\n const inputs = extractInputs(opObject, spec);\n\n // Create operation info\n const opInfo: OperationInfo = {\n path,\n method,\n operation: opObject,\n errors,\n inputs,\n };\n\n // Add operation to each of its tags\n for (const tag of tags) {\n operationsByTag[tag] = operationsByTag[tag] || [];\n operationsByTag[tag].push(opInfo);\n }\n }\n }\n\n return operationsByTag;\n}\n\n/**\n * Extract error responses from operation responses\n */\nfunction extractErrorResponses(\n responses: Record<string, ResponseObject | ReferenceObject>,\n): string[] {\n const errorNames: string[] = [];\n const responseMap: Record<string, string> = {\n '400': 'BadRequest',\n '401': 'Unauthorized',\n '403': 'Forbidden',\n '404': 'NotFound',\n '405': 'MethodNotAllowed',\n '409': 'Conflict',\n '422': 'UnprocessableEntity',\n '429': 'TooManyRequests',\n '500': 'InternalServerError',\n '502': 'BadGateway',\n '503': 'ServiceUnavailable',\n };\n\n for (const [code, _] of Object.entries(responses)) {\n const statusCode = parseInt(code, 10);\n if (statusCode >= 400) {\n const errorName = responseMap[code] || `Error${code}`;\n errorNames.push(errorName);\n }\n }\n\n return errorNames.length ? errorNames : ['ServerError'];\n}\n\n/**\n * Extract input parameters from an operation\n */\nfunction extractInputs(\n operation: OperationObject,\n spec: OpenAPIObject,\n): Record<string, { source: string }> {\n const inputs: Record<string, { source: string }> = {};\n\n // Process path, query, header parameters\n for (const param of operation.parameters || []) {\n const parameter = isReferenceObject(param)\n ? (followRef(spec, param.$ref) as ParameterObject)\n : param;\n\n inputs[parameter.name] = { source: parameter.in };\n }\n\n // Process request body properties as inputs\n if (operation.requestBody) {\n const requestBody = isReferenceObject(operation.requestBody)\n ? (followRef(spec, operation.requestBody.$ref) as RequestBodyObject)\n : operation.requestBody;\n\n if (requestBody.content?.['application/json']?.schema) {\n const schema = requestBody.content['application/json'].schema;\n const schemaObj = isReferenceObject(schema)\n ? (followRef(spec, schema.$ref) as SchemaObject)\n : schema;\n\n if (schemaObj.properties) {\n for (const propName of Object.keys(schemaObj.properties)) {\n inputs[propName] = { source: 'body' };\n }\n }\n }\n }\n\n return inputs;\n}\n\n/**\n * Extract security scheme from OpenAPI spec\n */\nfunction extractSecurityScheme(spec: OpenAPIObject) {\n if (spec.components?.securitySchemes?.bearerAuth) {\n const scheme = spec.components.securitySchemes.bearerAuth;\n if (\n typeof scheme === 'object' &&\n !('$ref' in scheme) &&\n scheme.type === 'http' &&\n scheme.scheme === 'bearer'\n ) {\n return {\n bearerAuth: {\n type: 'http',\n scheme: 'bearer',\n bearerFormat: scheme.bearerFormat || 'JWT',\n },\n };\n }\n }\n return undefined;\n}\n\n/**\n * Generate documentation for a single endpoint\n */\nfunction generateEndpointDocs(\n spec: OpenAPIObject,\n opInfo: OperationInfo,\n): string {\n const { path, method, operation, errors, inputs } = opInfo;\n let markdown = `#### \\`${method.toUpperCase()} ${path}\\`\\n\\n`;\n\n if (operation.summary) {\n markdown += `**Summary:** ${operation.summary}\\n\\n`;\n }\n\n if (operation.description) {\n markdown += `**Description:** ${operation.description}\\n\\n`;\n }\n\n // Document request parameters\n if (Object.keys(inputs).length > 0) {\n markdown += `**Parameters:**\\n\\n`;\n markdown += `| Name | Source | Required | Description | Example |\\n`;\n markdown += `| ---- | ------ | -------- | ----------- | ------- |\\n`;\n\n for (const [name, input] of Object.entries(inputs)) {\n const param = findParameterByName(operation, name, spec);\n\n const description =\n param && 'description' in param ? param.description || '-' : '-';\n const required =\n param && 'required' in param ? (param.required ? 'Yes' : 'No') : 'No';\n\n // Get example from parameter, schema, or schema.example\n const example = extractExample(param, spec);\n markdown += `| ${name} | ${input.source} | ${required} | ${description} | ${example} |\\n`;\n }\n markdown += `\\n`;\n }\n\n // Example usage\n markdown += `**Example:**\\n\\n`;\n markdown += `\\`\\`\\`typescript\\n`;\n\n // Generate example with actual examples from schema\n const exampleParams = generateExampleParams(operation, spec);\n markdown += `const [data, error] = await client.request('${method.toUpperCase()} ${path}', ${\n Object.keys(exampleParams).length > 0\n ? formatExample(exampleParams)\n : '{}\\n'\n });\\n`;\n markdown += `\\`\\`\\`\\n\\n`;\n\n // Possible errors\n if (errors.length > 0) {\n markdown += `**Possible Errors:**\\n\\n`;\n for (const error of errors) {\n markdown += `- \\`${error}\\`\\n`;\n }\n markdown += `\\n`;\n }\n\n // Example response if available\n if (operation.responses) {\n const responseExample = getResponseExample(spec, operation);\n if (responseExample) {\n markdown += `**Example Response:**\\n\\n`;\n markdown += `\\`\\`\\`json\\n${responseExample}\\n\\`\\`\\`\\n\\n`;\n }\n }\n\n return markdown;\n}\n\n/**\n * Extract example value from parameter, schema, or examples\n */\nfunction extractExample(param: any, spec: OpenAPIObject): string {\n if (!param) return '-';\n\n // Direct example on parameter\n if ('example' in param && param.example !== undefined) {\n return formatExampleValue(param.example);\n }\n\n // Parameter has examples object\n if (\n 'examples' in param &&\n param.examples &&\n Object.keys(param.examples).length > 0\n ) {\n const firstExampleKey = Object.keys(param.examples)[0];\n const exampleObj = param.examples[firstExampleKey];\n\n if (isExampleObject(exampleObj)) {\n return formatExampleValue(exampleObj.value);\n }\n\n if (isReferenceObject(exampleObj)) {\n const refExample = followRef(spec, exampleObj.$ref);\n if (isExampleObject(refExample)) {\n return formatExampleValue((refExample as any).value);\n }\n }\n }\n\n // Look for example in schema\n if ('schema' in param && param.schema) {\n const schema = isReferenceObject(param.schema)\n ? followRef(spec, param.schema.$ref)\n : param.schema;\n\n if ('example' in schema && schema.example !== undefined) {\n return formatExampleValue(schema.example);\n }\n\n if (\n 'examples' in schema &&\n Array.isArray(schema.examples) &&\n schema.examples.length > 0\n ) {\n return formatExampleValue(schema.examples[0]);\n }\n }\n\n return '-';\n}\n\n/**\n * Get example JSON for successful response\n */\nfunction getResponseExample(\n spec: OpenAPIObject,\n opObject: OperationObject,\n): string | null {\n const successResponses = Object.entries(opObject.responses ?? {}).filter(\n ([code]) => code.startsWith('2'),\n );\n\n if (successResponses.length === 0) return null;\n\n const [_, response] = successResponses[0];\n const responseObj = isReferenceObject(response)\n ? followRef(spec, response.$ref)\n : response;\n\n // Check for examples in the response\n if (responseObj.content?.['application/json']?.examples) {\n const firstExample = Object.values(\n responseObj.content['application/json'].examples,\n )[0];\n\n if (isExampleObject(firstExample)) {\n return JSON.stringify(firstExample.value, null, 2);\n }\n\n if (isReferenceObject(firstExample)) {\n const exampleRef = followRef(spec, firstExample.$ref);\n if (isExampleObject(exampleRef)) {\n return JSON.stringify((exampleRef as any).value, null, 2);\n }\n }\n }\n\n // Check for direct example\n if (responseObj.content?.['application/json']?.example) {\n return JSON.stringify(\n responseObj.content['application/json'].example,\n null,\n 2,\n );\n }\n\n // Check schema for example\n if (responseObj.content?.['application/json']?.schema) {\n const schema = responseObj.content['application/json'].schema;\n const schemaObj = isReferenceObject(schema)\n ? followRef(spec, schema.$ref)\n : schema;\n\n if ('example' in schemaObj && schemaObj.example !== undefined) {\n return JSON.stringify(schemaObj.example, null, 2);\n }\n }\n\n return '// Response structure according to schema';\n}\n\nfunction generateServersSection(servers: ServerObject[]): string {\n let markdown = `## Available Servers\\n\\n`;\n markdown += `The API can be accessed from the following servers:\\n\\n`;\n\n for (const server of servers) {\n markdown += `- \\`${server.url}\\` - ${server.description || 'No description'}\\n`;\n\n // If server has variables, document them\n if (server.variables && Object.keys(server.variables).length > 0) {\n markdown += ` - Variables:\\n`;\n for (const [varName, variable] of Object.entries(server.variables)) {\n markdown += ` - \\`${varName}\\`: ${variable.description || 'No description'} (Default: \\`${variable.default}\\`)\\n`;\n if (variable.enum && variable.enum.length > 0) {\n markdown += ` - Possible values: ${variable.enum.map((v) => `\\`${v}\\``).join(', ')}\\n`;\n }\n }\n }\n }\n markdown += `\\n`;\n\n return markdown;\n}\n\n/**\n * Format a value for display in a markdown table\n */\nfunction formatExampleValue(value: any): string {\n if (value === undefined || value === null) return '-';\n if (typeof value === 'object') return '`' + JSON.stringify(value) + '`';\n return '`' + String(value) + '`';\n}\n\n/**\n * Formats an example object for code display\n */\nfunction formatExample(example: Record<string, any>): string {\n if (Object.keys(example).length === 0) return '{}';\n\n let result = '{\\n';\n for (const [key, value] of Object.entries(example)) {\n const valueStr =\n typeof value === 'string'\n ? `\"${value.replace(/\"/g, '\\\\\"')}\"`\n : JSON.stringify(value);\n result += ` ${key}: ${valueStr},\\n`;\n }\n result += '}';\n return result;\n}\n\n/**\n * Type guard for ExampleObject\n */\nfunction isExampleObject(obj: any): obj is ExampleObject {\n return obj && typeof obj === 'object' && 'value' in obj;\n}\n\n/**\n * Type guard for ReferenceObject\n */\nfunction isReferenceObject(obj: any): obj is ReferenceObject {\n return obj && typeof obj === 'object' && '$ref' in obj;\n}\n\n/**\n * Generate example parameters from the operation object and request body\n */\nfunction generateExampleParams(\n opObject: OperationObject | undefined,\n spec: OpenAPIObject,\n): Record<string, any> {\n if (!opObject) return {};\n\n const examples: Record<string, any> = {};\n\n // Handle parameters (path, query, header)\n if (opObject.parameters) {\n for (const param of opObject.parameters) {\n const parameter = isReferenceObject(param)\n ? (followRef(spec, param.$ref) as ParameterObject)\n : param;\n\n // Get example from parameter\n const exampleValue = extractParameterExample(parameter, spec);\n if (exampleValue !== undefined) {\n examples[parameter.name] = exampleValue;\n }\n }\n }\n\n // Handle request body\n if (opObject.requestBody) {\n Object.assign(\n examples,\n extractRequestBodyExamples(opObject.requestBody, spec),\n );\n }\n\n return examples;\n}\n\n/**\n * Extract example value from a parameter\n */\nfunction extractParameterExample(\n parameter: ParameterObject,\n spec: OpenAPIObject,\n): any {\n if (parameter.example !== undefined) {\n return parameter.example;\n }\n\n if (parameter.examples && Object.keys(parameter.examples).length > 0) {\n const firstExampleKey = Object.keys(parameter.examples)[0];\n const exampleObj = parameter.examples[firstExampleKey];\n\n if (isExampleObject(exampleObj)) {\n return exampleObj.value;\n }\n\n if (isReferenceObject(exampleObj)) {\n const refExample = followRef(spec, exampleObj.$ref);\n if (isExampleObject(refExample)) {\n return (refExample as any).value;\n }\n }\n }\n\n if (parameter.schema) {\n const schema = isReferenceObject(parameter.schema)\n ? (followRef(spec, parameter.schema.$ref) as SchemaObject)\n : parameter.schema;\n\n if (schema.example !== undefined) {\n return schema.example;\n }\n\n if (schema.examples && schema.examples.length > 0) {\n return schema.examples[0];\n }\n }\n\n return undefined;\n}\n\n/**\n * Extract examples from request body\n */\nfunction extractRequestBodyExamples(\n requestBody: RequestBodyObject | ReferenceObject,\n spec: OpenAPIObject,\n): Record<string, any> {\n const examples: Record<string, any> = {};\n\n const resolvedBody = isReferenceObject(requestBody)\n ? (followRef(spec, requestBody.$ref) as RequestBodyObject)\n : requestBody;\n\n if (!resolvedBody.content?.['application/json']) {\n return examples;\n }\n\n const content = resolvedBody.content['application/json'];\n\n // Check for examples object\n if (content.examples && Object.keys(content.examples).length > 0) {\n const firstExampleKey = Object.keys(content.examples)[0];\n const exampleObj = content.examples[firstExampleKey];\n\n if (isExampleObject(exampleObj)) {\n Object.assign(examples, exampleObj.value || {});\n } else if (isReferenceObject(exampleObj)) {\n const refExample = followRef(spec, exampleObj.$ref);\n if (isExampleObject(refExample)) {\n Object.assign(examples, (refExample as any).value || {});\n }\n }\n return examples;\n }\n\n // Check for direct example\n if (content.example) {\n Object.assign(examples, content.example);\n return examples;\n }\n\n // Check schema for examples\n if (content.schema) {\n const schema = isReferenceObject(content.schema)\n ? (followRef(spec, content.schema.$ref) as SchemaObject)\n : content.schema;\n\n if (schema.example) {\n Object.assign(examples, schema.example);\n return examples;\n }\n\n if (schema.properties) {\n // Get examples from properties\n for (const [propName, propSchema] of Object.entries(schema.properties)) {\n const propSchemaObj = isReferenceObject(propSchema)\n ? (followRef(spec, propSchema.$ref) as SchemaObject)\n : propSchema;\n\n if (propSchemaObj.example !== undefined) {\n examples[propName] = propSchemaObj.example;\n } else if (\n propSchemaObj.examples &&\n propSchemaObj.examples.length > 0\n ) {\n examples[propName] = propSchemaObj.examples[0];\n }\n }\n }\n }\n\n return examples;\n}\n\n/**\n * Find a parameter by name in the operation object\n */\nfunction findParameterByName(\n opObject: OperationObject | undefined,\n name: string,\n spec: OpenAPIObject,\n) {\n if (!opObject?.parameters) return undefined;\n\n // Look through parameters\n for (const param of opObject.parameters) {\n if (isReferenceObject(param)) {\n const resolvedParam = followRef(spec, param.$ref) as ParameterObject;\n if (resolvedParam.name === name) return resolvedParam;\n } else if (param.name === name) {\n return param;\n }\n }\n\n // Check requestBody for the parameter\n if (opObject.requestBody) {\n const requestBody = isReferenceObject(opObject.requestBody)\n ? (followRef(spec, opObject.requestBody.$ref) as RequestBodyObject)\n : opObject.requestBody;\n\n if (requestBody.content?.['application/json']?.schema) {\n const schema = requestBody.content['application/json'].schema;\n const schemaObj = isReferenceObject(schema)\n ? (followRef(spec, schema.$ref) as SchemaObject)\n : schema;\n\n if (schemaObj.properties?.[name]) {\n const propSchema = schemaObj.properties[name];\n return {\n name,\n in: 'body',\n required: schemaObj.required?.includes(name) ?? false,\n schema: propSchema,\n description: isReferenceObject(propSchema)\n ? undefined\n : propSchema.description,\n example: isReferenceObject(propSchema)\n ? undefined\n : propSchema.example,\n };\n }\n }\n }\n\n return undefined;\n}\n\n/**\n * Helper function to find operation in OpenAPI spec\n */\nfunction findOperationInSpec(\n spec: OpenAPIObject,\n path: string,\n method: Method,\n): OperationObject | undefined {\n const pathItem = spec.paths?.[path] as PathItemObject | undefined;\n if (!pathItem) return undefined;\n return pathItem[method] as OperationObject | undefined;\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["ts", "dirname", "join", "join", "dirname", "get", "camelcase", "pascalcase", "spinalcase", "it", "name", "spinalcase", "camelcase", "get", "pascalcase", "client_default", "pascalcase", "client_default"]
7
7
  }
@@ -1 +1 @@
1
- {"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../../src/lib/backend.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;+BAEf,IAAI;AAA1B,wBAsEE"}
1
+ {"version":3,"file":"backend.d.ts","sourceRoot":"","sources":["../../src/lib/backend.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;+BAEf,IAAI;AAA1B,wBAwEE"}
@@ -0,0 +1,4 @@
1
+ import type { Spec } from './sdk.ts';
2
+ declare const _default: (spec: Spec) => string;
3
+ export default _default;
4
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/lib/client.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;+BAEf,IAAI;AAA1B,wBAwDE"}
@@ -1,5 +1,6 @@
1
1
  import type { OpenAPIObject } from 'openapi3-ts/oas31';
2
2
  export declare function generate(spec: OpenAPIObject, settings: {
3
3
  output: string;
4
+ name?: string;
4
5
  }): Promise<void>;
5
6
  //# sourceMappingURL=generate.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/lib/generate.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAOvD,wBAAsB,QAAQ,CAC5B,IAAI,EAAE,aAAa,EACnB,QAAQ,EAAE;IACR,MAAM,EAAE,MAAM,CAAC;CAChB,iBAkCF"}
1
+ {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/lib/generate.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAavD,wBAAsB,QAAQ,CAC5B,IAAI,EAAE,aAAa,EACnB,QAAQ,EAAE;IACR,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,iBAqDF"}
@@ -5,6 +5,6 @@ type OnRefCallback = (ref: string, zod: string) => void;
5
5
  * Convert an OpenAPI (JSON Schema style) object into a Zod schema string,
6
6
  * adapted for OpenAPI 3.1 (fully aligned with JSON Schema 2020-12).
7
7
  */
8
- export declare function jsonSchemaToZod(spec: OpenAPIObject, schema: SchemaObject | ReferenceObject, required: boolean | undefined, onRef: OnRefCallback, refProcessingStack?: Set<string>): string;
8
+ export declare function jsonSchemaToZod(spec: OpenAPIObject, schema: SchemaObject | ReferenceObject, required: boolean | undefined, onRef: OnRefCallback, circularRefTracker?: Set<string>): string;
9
9
  export {};
10
10
  //# sourceMappingURL=json-zod.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"json-zod.d.ts","sourceRoot":"","sources":["../../src/lib/json-zod.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,aAAa,EACb,eAAe,EACf,YAAY,EACb,MAAM,mBAAmB,CAAC;AAS3B,wBAAgB,SAAS,CACvB,IAAI,EAAE,aAAa,EACnB,GAAG,EAAE,MAAM,GACV,YAAY,GAAG,eAAe,CAQhC;AAED,KAAK,aAAa,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;AAExD;;;GAGG;AAEH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,aAAa,EACnB,MAAM,EAAE,YAAY,GAAG,eAAe,EACtC,QAAQ,qBAAQ,EAChB,KAAK,EAAE,aAAa,EACpB,kBAAkB,cAAoB,GACrC,MAAM,CA4GR"}
1
+ {"version":3,"file":"json-zod.d.ts","sourceRoot":"","sources":["../../src/lib/json-zod.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,aAAa,EACb,eAAe,EACf,YAAY,EACb,MAAM,mBAAmB,CAAC;AAe3B,wBAAgB,SAAS,CACvB,IAAI,EAAE,aAAa,EACnB,GAAG,EAAE,MAAM,GACV,YAAY,GAAG,eAAe,CAQhC;AAED,KAAK,aAAa,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;AAExD;;;GAGG;AAEH,wBAAgB,eAAe,CAC7B,IAAI,EAAE,aAAa,EACnB,MAAM,EAAE,YAAY,GAAG,eAAe,EACtC,QAAQ,qBAAQ,EAChB,KAAK,EAAE,aAAa,EACpB,kBAAkB,cAAoB,GACrC,MAAM,CAoHR"}
@@ -0,0 +1,8 @@
1
+ import type { OpenAPIObject } from 'openapi3-ts/oas31';
2
+ /**
3
+ * Generate README.md documentation directly from OpenAPI spec
4
+ */
5
+ export declare function generateReadme(spec: OpenAPIObject, settings: {
6
+ name: string;
7
+ }): string;
8
+ //# sourceMappingURL=readme-generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"readme-generator.d.ts","sourceRoot":"","sources":["../../src/lib/readme-generator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,aAAa,EAUd,MAAM,mBAAmB,CAAC;AAO3B;;GAEG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,aAAa,EACnB,QAAQ,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GACzB,MAAM,CAoFR"}
package/dist/lib/sdk.d.ts CHANGED
@@ -33,12 +33,13 @@ export interface SdkConfig {
33
33
  export interface Spec {
34
34
  groups: Record<string, Operation[]>;
35
35
  commonZod?: string;
36
- name?: string;
36
+ name: string;
37
37
  options?: Record<string, {
38
38
  in: 'header';
39
39
  schema: string;
40
40
  }>;
41
41
  securityScheme?: SecurityScheme;
42
+ servers?: string[];
42
43
  }
43
44
  export interface OperationInput {
44
45
  source: string;
@@ -61,12 +62,7 @@ export interface Operation {
61
62
  }
62
63
  export declare function generateClientSdk(spec: Spec): {
63
64
  'backend.ts': string;
64
- 'parser.ts': string;
65
- 'client.ts': string;
66
- 'request.ts': string;
67
65
  'schemas.ts': string;
68
66
  'endpoints.ts': string;
69
- 'stream-endpoints.ts': string;
70
- 'response.ts': string;
71
67
  };
72
68
  //# sourceMappingURL=sdk.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../src/lib/sdk.ts"],"names":[],"mappings":"AAWA,MAAM,WAAW,MAAM;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;CACrC;AACD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,OAAO,CAAC;CACrB;AA2CD,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE;QACV,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,QAAQ,CAAC;QACjB,YAAY,EAAE,KAAK,CAAC;KACrB,CAAC;CACH;AAED,MAAM,WAAW,SAAS;IACxB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED,MAAM,WAAW,IAAI;IACnB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CACd,MAAM,EACN;QACE,EAAE,EAAE,QAAQ,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;KAChB,CACF,CAAC;IACF,cAAc,CAAC,EAAE,cAAc,CAAC;CACjC;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AACD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACvC,YAAY,EAAE,MAAM;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;CACrD;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI;;;;;;;;;EAwJ3C"}
1
+ {"version":3,"file":"sdk.d.ts","sourceRoot":"","sources":["../../src/lib/sdk.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,MAAM;IACrB,UAAU,EAAE,OAAO,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,aAAa,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,YAAY,EAAE,WAAW,EAAE,CAAC;IAC5B,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;CACrC;AACD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,OAAO,CAAC;CACrB;AA0CD,MAAM,WAAW,cAAc;IAC7B,UAAU,EAAE;QACV,IAAI,EAAE,MAAM,CAAC;QACb,MAAM,EAAE,QAAQ,CAAC;QACjB,YAAY,EAAE,KAAK,CAAC;KACrB,CAAC;CACH;AAED,MAAM,WAAW,SAAS;IACxB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC9B,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED,MAAM,WAAW,IAAI;IACnB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,EAAE,CAAC,CAAC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CACd,MAAM,EACN;QACE,EAAE,EAAE,QAAQ,CAAC;QACb,MAAM,EAAE,MAAM,CAAC;KAChB,CACF,CAAC;IACF,cAAc,CAAC,EAAE,cAAc,CAAC;IAChC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AACD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC7B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IACvC,YAAY,EAAE,MAAM;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAC;CACrD;AAED,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,IAAI;;;;EAmJ3C"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sdk-it/typescript",
3
- "version": "0.3.1",
3
+ "version": "0.5.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -21,7 +21,7 @@
21
21
  "!**/*.tsbuildinfo"
22
22
  ],
23
23
  "dependencies": {
24
- "@sdk-it/core": "0.3.1",
24
+ "@sdk-it/core": "0.5.0",
25
25
  "debug": "^4.4.0",
26
26
  "openapi3-ts": "^4.4.0",
27
27
  "stringcase": "^4.3.1",