@sdk-it/typescript 0.4.0 → 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");
@@ -328,31 +322,31 @@ function appendDefault(defaultValue) {
328
322
  }
329
323
 
330
324
  // packages/typescript/src/lib/sdk.ts
331
- import { camelcase } from "stringcase";
332
- import { pascalcase, spinalcase } from "stringcase";
325
+ import { camelcase, pascalcase, spinalcase } from "stringcase";
333
326
 
334
- // packages/typescript/src/lib/backend.ts
327
+ // packages/typescript/src/lib/client.ts
335
328
  import { titlecase } from "stringcase";
336
- var backend_default = (spec) => {
329
+ var client_default = (spec) => {
337
330
  const specOptions = {
338
331
  ...spec.options ?? {},
339
332
  fetch: {
340
- schema: "z.function().args(z.instanceof(Request)).returns(z.promise(z.instanceof(Response))).optional()"
333
+ schema: "fetchType"
341
334
  },
342
- baseUrl: { schema: "z.string().url()" }
335
+ baseUrl: {
336
+ schema: `z.enum(servers).default(servers[0])`
337
+ }
343
338
  };
344
339
  if (spec.securityScheme) {
345
340
  specOptions["token"] = { schema: "z.string().optional()" };
346
341
  }
347
342
  const defaultHeaders = spec.securityScheme ? `{Authorization: \`${titlecase(spec.securityScheme.bearerAuth.scheme)} \${this.options.token}\`}` : `{}`;
348
343
  return `
349
-
344
+ import { fetchType, sendRequest } from './http/send-request.ts';
350
345
  import z from 'zod';
351
- import type { Endpoints } from './endpoints';
352
- import schemas from './schemas';
353
- import { parse } from './parser';
354
- import { handleError, parseResponse } from './client';
346
+ import type { Endpoints } from './endpoints.ts';
347
+ import schemas from './schemas.ts';
355
348
 
349
+ const servers = ${JSON.stringify(spec.servers || [], null, 2)} as const;
356
350
  const optionsSchema = z.object(${toLitObject(specOptions, (x) => x.schema)});
357
351
  type ${spec.name}Options = z.infer<typeof optionsSchema>;
358
352
  export class ${spec.name} {
@@ -364,24 +358,11 @@ import { handleError, parseResponse } from './client';
364
358
  input: Endpoints[E]['input'],
365
359
  ): Promise<readonly [Endpoints[E]['output'], Endpoints[E]['error'] | null]> {
366
360
  const route = schemas[endpoint];
367
- const [parsedInput, parseError] = parse(route.schema, input);
368
- if (parseError) {
369
- return [
370
- null as never,
371
- { ...parseError, kind: 'parse' } as never,
372
- ] as const;
373
- }
374
- const request = route.toRequest(parsedInput as never, {
375
- headers: this.defaultHeaders,
361
+ return sendRequest(input, route, {
376
362
  baseUrl: this.options.baseUrl,
363
+ fetch: this.options.fetch,
364
+ headers: this.defaultHeaders,
377
365
  });
378
- const response = await (this.options.fetch ?? fetch)(request);
379
- if (response.ok) {
380
- const data = await parseResponse(response);
381
- return [data as Endpoints[E]['output'], null] as const;
382
- }
383
- const error = await handleError(response);
384
- return [null as never, { ...error, kind: 'response' }] as const;
385
366
  }
386
367
 
387
368
  get defaultHeaders() {
@@ -400,25 +381,13 @@ import { handleError, parseResponse } from './client';
400
381
  }`;
401
382
  };
402
383
 
403
- // packages/typescript/src/lib/client.txt
404
- 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";
405
-
406
- // packages/typescript/src/lib/parser.txt
407
- 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";
408
-
409
- // packages/typescript/src/lib/request.txt
410
- 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";
411
-
412
- // packages/typescript/src/lib/response.txt
413
- 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";
414
-
415
384
  // packages/typescript/src/lib/sdk.ts
416
385
  var SchemaEndpoint = class {
417
386
  #imports = [
418
387
  `import z from 'zod';`,
419
- 'import type { Endpoints } from "./endpoints";',
420
- `import { toRequest, json, urlencoded, formdata, createUrl } from './request';`,
421
- `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';`
422
391
  ];
423
392
  #endpoints = [];
424
393
  addEndpoint(endpoint, operation) {
@@ -437,7 +406,7 @@ ${this.#endpoints.join("\n")}
437
406
  var Emitter = class {
438
407
  imports = [
439
408
  `import z from 'zod';`,
440
- `import type { ParseError } from './parser';`
409
+ `import type { ParseError } from './http/parser.ts';`
441
410
  ];
442
411
  endpoints = [];
443
412
  addEndpoint(endpoint, operation) {
@@ -472,13 +441,13 @@ function generateClientSdk(spec) {
472
441
  const featureSchemaFileName = camelcase(name);
473
442
  schemas[featureSchemaFileName] = [`import z from 'zod';`];
474
443
  emitter.addImport(
475
- `import * as ${featureSchemaFileName} from './inputs/${featureSchemaFileName}';`
444
+ `import * as ${featureSchemaFileName} from './inputs/${featureSchemaFileName}.ts';`
476
445
  );
477
446
  streamEmitter.addImport(
478
- `import * as ${featureSchemaFileName} from './inputs/${featureSchemaFileName}';`
447
+ `import * as ${featureSchemaFileName} from './inputs/${featureSchemaFileName}.ts';`
479
448
  );
480
449
  schemaEndpoint.addImport(
481
- `import * as ${featureSchemaFileName} from './inputs/${featureSchemaFileName}';`
450
+ `import * as ${featureSchemaFileName} from './inputs/${featureSchemaFileName}.ts';`
482
451
  );
483
452
  for (const operation of operations) {
484
453
  const schemaName = camelcase(`${operation.name} schema`);
@@ -574,7 +543,7 @@ function generateClientSdk(spec) {
574
543
  }
575
544
  }
576
545
  emitter.addImport(
577
- `import type { ${removeDuplicates(errors, (it) => it).join(", ")} } from './response';`
546
+ `import type { ${removeDuplicates(errors, (it) => it).join(", ")} } from './http/response.ts';`
578
547
  );
579
548
  return {
580
549
  ...Object.fromEntries(
@@ -582,19 +551,15 @@ function generateClientSdk(spec) {
582
551
  `inputs/${key}.ts`,
583
552
  [
584
553
  schemasImports.length ? `import {${removeDuplicates(schemasImports, (it) => it)}} from '../zod';` : "",
585
- spec.commonZod ? 'import * as commonZod from "../zod";' : "",
554
+ spec.commonZod ? 'import * as commonZod from "../zod.ts";' : "",
586
555
  ...value
587
556
  ].map((it) => it.trim()).filter(Boolean).join("\n") + "\n"
588
557
  // add a newline at the end
589
558
  ])
590
559
  ),
591
- "backend.ts": backend_default(spec),
592
- "parser.ts": parser_default,
593
- "client.ts": client_default,
594
- "request.ts": request_default,
560
+ "backend.ts": client_default(spec),
595
561
  "schemas.ts": schemaEndpoint.complete(),
596
- "endpoints.ts": emitter.complete(),
597
- "response.ts": response_default
562
+ "endpoints.ts": emitter.complete()
598
563
  };
599
564
  }
600
565
 
@@ -828,6 +793,24 @@ function importsToString(imports) {
828
793
  });
829
794
  }
830
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
+
831
814
  // packages/typescript/src/lib/generate.ts
832
815
  async function generate(spec, settings) {
833
816
  const { commonSchemas, groups, outputs } = generateCode({
@@ -836,12 +819,21 @@ async function generate(spec, settings) {
836
819
  target: "javascript"
837
820
  });
838
821
  const clientFiles = generateClientSdk({
839
- name: "Client",
840
- groups
822
+ name: settings.name || "Client",
823
+ groups,
824
+ servers: spec.servers?.map((server) => server.url) || []
841
825
  });
842
826
  await writeFiles(settings.output, {
843
827
  "outputs/index.ts": "",
844
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
845
837
  });
846
838
  await writeFiles(join(settings.output, "outputs"), outputs);
847
839
  await writeFiles(settings.output, {
@@ -849,15 +841,17 @@ async function generate(spec, settings) {
849
841
  "zod.ts": `import z from 'zod';
850
842
  ${Object.entries(commonSchemas).map(([name, schema]) => `export const ${name} = ${schema};`).join("\n")}`
851
843
  });
852
- const [index, outputIndex, inputsIndex] = await Promise.all([
844
+ const [index, outputIndex, inputsIndex, httpIndex] = await Promise.all([
853
845
  getFolderExports(settings.output),
854
846
  getFolderExports(join(settings.output, "outputs")),
855
- getFolderExports(join(settings.output, "inputs"))
847
+ getFolderExports(join(settings.output, "inputs")),
848
+ getFolderExports(join(settings.output, "http"))
856
849
  ]);
857
850
  await writeFiles(settings.output, {
858
851
  "index.ts": index,
859
852
  "outputs/index.ts": outputIndex,
860
- "inputs/index.ts": inputsIndex
853
+ "inputs/index.ts": inputsIndex,
854
+ "http/index.ts": httpIndex
861
855
  });
862
856
  }
863
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 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(\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-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 } 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 { 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 '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 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": "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",
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,wBAqEE"}
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"}
@@ -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,11 +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
- 'response.ts': string;
70
67
  };
71
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;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,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;;;;;;;;EAuJ3C"}
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.4.0",
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.4.0",
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",