@sdk-it/cli 0.46.0 → 0.46.1

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/README.md CHANGED
@@ -1,110 +1,115 @@
1
1
  # @sdk-it/cli
2
2
 
3
- <p align="center">Command-line interface for SDK-IT that generates type-safe client SDKs from OpenAPI specifications</p>
3
+ Generate type-safe client SDKs from OpenAPI specifications.
4
4
 
5
- ## Installation
5
+ ## Run the CLI
6
6
 
7
- ```bash
8
- # Install globally
9
- npm install -g @sdk-it/cli
7
+ Use the latest CLI without installing it globally:
10
8
 
11
- # Or use with npx without installing
12
- npx @sdk-it/cli
9
+ ```bash
10
+ npx @sdk-it/cli@latest --help
13
11
  ```
14
12
 
15
- ## Usage
16
-
17
- Generate SDKs from OpenAPI specifications:
18
-
19
- ### Basic Command Structure
13
+ To pin the CLI in a project:
20
14
 
21
15
  ```bash
22
- npx @sdk-it/cli <language> --spec <path-to-spec> --output <output-directory> [options]
16
+ npm install --save-dev @sdk-it/cli
23
17
  ```
24
18
 
25
- ### Options
26
-
27
- | Option | Alias | Description | Default |
28
- | ------------- | ----- | -------------------------------------------------------- | ---------- |
29
- | `--spec` | `-s` | Path to OpenAPI specification file (local or remote URL) | _Required_ |
30
- | `--output` | `-o` | Output directory for the generated SDK | _Required_ |
31
- | `--name` | `-n` | Name of the generated client | `Client` |
32
- | `--mode` | `-m` | Generation mode: `full` or `minimal` | `minimal` |
33
- | `--formatter` | | Formatter command to run on generated code | |
19
+ ## Generate a TypeScript SDK
34
20
 
35
- #### Mode Options
21
+ Inside an existing TypeScript project, install the generated client's runtime
22
+ dependencies:
36
23
 
37
- - `minimal`: Generates only the client SDK files (default)
38
- - `full`: Generates a complete project including package.json and tsconfig.json (useful for monorepo/workspaces)
24
+ ```bash
25
+ npm install zod fast-content-type-parse
26
+ ```
39
27
 
40
- #### Formatter
28
+ Generate the client:
41
29
 
42
- You can specify a command to format the generated code. The special variable `$SDK_IT_OUTPUT` will be replaced with the output directory path.
30
+ ```bash
31
+ npx @sdk-it/cli@latest generate typescript \
32
+ --spec ./openapi.json \
33
+ --output ./src/generated/api \
34
+ --name MyApi \
35
+ --mode minimal
36
+ ```
43
37
 
44
- Examples:
38
+ Use it:
45
39
 
46
- - `--formatter "prettier $SDK_IT_OUTPUT --write"`
47
- - `--formatter "biome check $SDK_IT_OUTPUT --write"`
40
+ ```typescript
41
+ import { MyApi } from './src/generated/api/index.ts';
48
42
 
49
- ### Supported Specification Formats
43
+ const client = new MyApi({
44
+ baseUrl: 'https://api.example.com',
45
+ });
50
46
 
51
- - JSON (`.json`)
52
- - YAML (`.yaml`, `.yml`)
47
+ const users = await client.request('GET /users', {});
48
+ console.log(users);
49
+ ```
53
50
 
54
- ## Examples
51
+ `request` returns the unwrapped response data. Invalid inputs and non-successful
52
+ HTTP responses throw typed errors exported by the generated SDK.
55
53
 
56
- ### Generate SDK from a Remote OpenAPI Specification
54
+ ## TypeScript options
57
55
 
58
- ```bash
59
- npx sdk-it -s https://petstore.swagger.io/v2/swagger.json -o ./client
56
+ ```text
57
+ npx @sdk-it/cli@latest generate typescript [options]
60
58
  ```
61
59
 
62
- ### Generate SDK with Custom Client Name
60
+ | Option | Description | Default |
61
+ | -------------------------- | ------------------------------------------------------------ | --------- |
62
+ | `--spec`, `-s` | Local path or remote URL to an OpenAPI JSON or YAML document | Required |
63
+ | `--output`, `-o` | Output directory | Required |
64
+ | `--name`, `-n` | Generated client class name | `Client` |
65
+ | `--mode`, `-m` | `minimal` source files or a `full` standalone project | `minimal` |
66
+ | `--useTsExtension [value]` | Include `.ts` in generated imports | `true` |
67
+ | `--formatter <command>` | Command used to format the generated source directory | |
68
+ | `--no-default-formatter` | Skip the default Prettier formatter | |
69
+ | `--readme false` | Skip the generated API README | |
70
+ | `--pagination <config>` | Configure pagination, such as `false` or `guess=false` | `true` |
71
+ | `--no-install` | Skip dependency installation in `full` mode | |
72
+ | `--verbose`, `-v` | Show generator and installation output | `false` |
73
+
74
+ `minimal` mode writes client source files directly to `--output`. `full` mode
75
+ writes source files under `<output>/src`, adds `package.json` and `tsconfig.json`,
76
+ and installs its runtime dependencies unless `--no-install` is passed.
77
+
78
+ For a custom formatter, include the generated path explicitly:
63
79
 
64
80
  ```bash
65
- npx sdk-it -s ./openapi.json -o ./client -n PetStore
81
+ npx @sdk-it/cli@latest generate typescript \
82
+ --spec ./openapi.json \
83
+ --output ./src/generated/api \
84
+ --formatter "prettier ./src/generated/api --write"
66
85
  ```
67
86
 
68
- ### Generate Full Project with Formatting
87
+ ## Remote specification example
69
88
 
70
89
  ```bash
71
- npx sdk-it -s ./openapi.yaml -o ./client -m full --formatter "prettier $SDK_IT_OUTPUT --write"
90
+ npx @sdk-it/cli@latest generate typescript \
91
+ --spec https://raw.githubusercontent.com/MaximilianKoestler/hcloud-openapi/refs/heads/main/openapi/hcloud.json \
92
+ --output ./src/generated/hetzner \
93
+ --name Hetzner \
94
+ --mode minimal
72
95
  ```
73
96
 
74
- ## Complete Example
97
+ ```typescript
98
+ import { Hetzner } from './src/generated/hetzner/index.ts';
75
99
 
76
- Let's generate a client SDK for the Hetzner Cloud API with automatic formatting:
100
+ const hetzner = new Hetzner({
101
+ token: process.env.HETZNER_API_TOKEN,
102
+ });
77
103
 
78
- ```bash
79
- # Generate SDK from Hetzner Cloud API spec with Prettier formatting
80
- npx sdk-it -s https://raw.githubusercontent.com/MaximilianKoestler/hcloud-openapi/refs/heads/main/openapi/hcloud.json -o ./client --formatter "prettier $SDK_IT_OUTPUT --write"
104
+ const result = await hetzner.request('GET /servers', {});
105
+ console.log(result.servers);
81
106
  ```
82
107
 
83
- This command:
84
-
85
- 1. Downloads the OpenAPI specification from the Hetzner Cloud documentation
86
- 2. Generates a type-safe TypeScript SDK in the `./client` directory
87
- 3. Runs Prettier on the generated code for consistent formatting
108
+ ## Other generators
88
109
 
89
- Use the generated SDK:
110
+ The same `generate` command also exposes the Dart, Python, API reference, and
111
+ README generators:
90
112
 
91
- ```typescript
92
- import { Client } from './client';
93
-
94
- // Create a client instance with your API token
95
- const client = new Client({
96
- baseUrl: 'https://api.hetzner.cloud/v1',
97
- headers: {
98
- Authorization: 'Bearer your_api_token',
99
- },
100
- });
101
-
102
- // Call API methods with type safety
103
- const [servers, error] = await client.request('GET /servers', {});
104
-
105
- if (error) {
106
- console.error('Error fetching servers:', error);
107
- } else {
108
- console.log('Servers:', servers);
109
- }
113
+ ```bash
114
+ npx @sdk-it/cli@latest generate --help
110
115
  ```
package/dist/bin.js CHANGED
@@ -959,7 +959,7 @@ import { execFile as execFile2, execSync as execSync2 } from "node:child_process
959
959
  import { readdir as readdir2 } from "node:fs/promises";
960
960
  import { join as join7 } from "node:path";
961
961
  import { snakecase as snakecase2 } from "stringcase";
962
- import { isEmpty, isRef as isRef2, pascalcase as pascalcase2 } from "@sdk-it/core";
962
+ import { followRef as followRef2, isEmpty as isEmpty2, isRef as isRef2, pascalcase as pascalcase2 } from "@sdk-it/core";
963
963
  import {
964
964
  createWriterProxy,
965
965
  writeFiles
@@ -973,7 +973,14 @@ import {
973
973
  toIR
974
974
  } from "@sdk-it/spec";
975
975
  import { snakecase } from "stringcase";
976
- import { isRef, notRef, parseRef, pascalcase } from "@sdk-it/core";
976
+ import {
977
+ followRef,
978
+ isEmpty,
979
+ isRef,
980
+ notRef,
981
+ parseRef,
982
+ pascalcase
983
+ } from "@sdk-it/core";
977
984
  import { isPrimitiveSchema } from "@sdk-it/spec";
978
985
  var dispatcher_default = `"""HTTP dispatcher for making API requests."""
979
986
 
@@ -2272,7 +2279,18 @@ var PythonEmitter = class {
2272
2279
  }
2273
2280
  return fieldName;
2274
2281
  }
2275
- #ref(ref) {
2282
+ #isBottom(schema) {
2283
+ if (!schema) {
2284
+ return false;
2285
+ }
2286
+ const resolved = isRef(schema) ? followRef(this.#spec, schema.$ref) : schema;
2287
+ return !!resolved.not && isEmpty(resolved.not);
2288
+ }
2289
+ #ref(ref, context = {}) {
2290
+ const schema = followRef(this.#spec, ref.$ref);
2291
+ if (this.#isBottom(schema) || schema.type === "array" && this.#isBottom(schema.items)) {
2292
+ return this.handle(schema, context);
2293
+ }
2276
2294
  const cacheKey = ref.$ref;
2277
2295
  const cached = this.#typeCache.get(cacheKey);
2278
2296
  if (cached) {
@@ -2332,27 +2350,25 @@ var PythonEmitter = class {
2332
2350
  }
2333
2351
  for (const [propName, propSchema] of Object.entries(properties)) {
2334
2352
  if (isRef(propSchema)) {
2335
- this.#ref(propSchema);
2336
- const refInfo = parseRef(propSchema.$ref);
2337
- const refName = refInfo.model;
2338
- const pythonType = pascalcase(refName);
2353
+ const result = this.#ref(propSchema, context);
2354
+ const pythonType = result.type || "Any";
2339
2355
  const fieldName = this.#formatFieldName(propName);
2340
2356
  const isRequired = required.includes(propName);
2341
- const fieldType = isRequired ? pythonType : `Optional[${pythonType}]`;
2342
- const defaultValue = isRequired ? "" : " = None";
2357
+ const fieldType = isRequired || result.impossible ? pythonType : `Optional[${pythonType}]`;
2358
+ const defaultValue = isRequired ? "" : result.impossible ? " = Field(default=None, exclude=True)" : " = None";
2343
2359
  fields.push(` ${fieldName}: ${fieldType}${defaultValue}`);
2344
2360
  } else {
2345
2361
  const result = this.handle(propSchema, { ...context, name: propName });
2346
2362
  const fieldName = this.#formatFieldName(propName);
2347
2363
  const isRequired = required.includes(propName);
2348
2364
  let fieldType = result.type || "Any";
2349
- if (!isRequired) {
2365
+ if (!isRequired && !result.impossible) {
2350
2366
  fieldType = `Optional[${fieldType}]`;
2351
2367
  }
2352
- const defaultValue = isRequired ? "" : " = None";
2368
+ const defaultValue = isRequired ? "" : result.impossible ? " = Field(default=None, exclude=True)" : " = None";
2353
2369
  let fieldDef = ` ${fieldName}: ${fieldType}${defaultValue}`;
2354
2370
  if (fieldName !== propName) {
2355
- fieldDef = ` ${fieldName}: ${fieldType} = Field(alias='${propName}'${defaultValue ? ", default=None" : ""})`;
2371
+ fieldDef = ` ${fieldName}: ${fieldType} = Field(alias='${propName}'${isRequired ? "" : ", default=None"}${!isRequired && result.impossible ? ", exclude=True" : ""})`;
2356
2372
  }
2357
2373
  if (propSchema.description) {
2358
2374
  fieldDef += ` # ${propSchema.description}`;
@@ -2525,7 +2541,18 @@ ${enumItems.join("\n")}
2525
2541
  }
2526
2542
  handle(schema, context = {}) {
2527
2543
  if (isRef(schema)) {
2528
- return this.#ref(schema);
2544
+ return this.#ref(schema, context);
2545
+ }
2546
+ if (schema.not && isEmpty(schema.not)) {
2547
+ const type = context.pydantic === true ? "_NeverValue" : "Never";
2548
+ return {
2549
+ type,
2550
+ content: "",
2551
+ use: type,
2552
+ fromJson: type,
2553
+ simple: true,
2554
+ impossible: true
2555
+ };
2529
2556
  }
2530
2557
  if ("const" in schema && schema.const !== void 0) {
2531
2558
  return this.#const(schema);
@@ -2609,7 +2636,8 @@ ${docstring}
2609
2636
  (acc, [name, { className, methods }]) => {
2610
2637
  const fileName = `api/${snakecase2(name)}_api.py`;
2611
2638
  const imports = [
2612
- "from typing import Optional",
2639
+ "from typing import Any, Dict, List, Literal, Optional, Union",
2640
+ "from typing_extensions import Never",
2613
2641
  "import httpx",
2614
2642
  "",
2615
2643
  "from ..http.dispatcher import Dispatcher, RequestConfig",
@@ -2743,7 +2771,7 @@ httpx>=0.24.0,<1.0.0
2743
2771
  pydantic>=2.0.0,<3.0.0
2744
2772
 
2745
2773
  # Enhanced type hints
2746
- typing-extensions>=4.0.0
2774
+ typing-extensions>=4.1.0
2747
2775
 
2748
2776
  # Optional: For better datetime handling
2749
2777
  python-dateutil>=2.8.0
@@ -2822,7 +2850,7 @@ ${imports}
2822
2850
  }
2823
2851
  function toInputs(spec, { entry, operation }) {
2824
2852
  const inputName = entry.inputName || "Input";
2825
- const haveInput = !isEmpty(operation.parameters) || !isEmpty(operation.requestBody);
2853
+ const haveInput = !isEmpty2(operation.parameters) || !isEmpty2(operation.requestBody);
2826
2854
  let contentType = "json";
2827
2855
  if (operation.requestBody && !isRef2(operation.requestBody)) {
2828
2856
  const content = operation.requestBody.content;
@@ -2871,26 +2899,48 @@ function toOutput(spec, operation) {
2871
2899
  }
2872
2900
  const [, mediaType] = jsonContent;
2873
2901
  const schema = mediaType.schema;
2874
- if (!schema || isRef2(schema)) {
2902
+ if (!schema) {
2875
2903
  return { returnType: "Any", successModel: null, errorModel: null };
2876
2904
  }
2905
+ let outputSchema = schema;
2906
+ if (isRef2(schema)) {
2907
+ const resolvedSchema = followRef2(spec, schema.$ref);
2908
+ const isBottomResponse = isBottomSchema(spec, resolvedSchema) || resolvedSchema.type === "array" && isBottomSchema(spec, resolvedSchema.items);
2909
+ if (!isBottomResponse) {
2910
+ return { returnType: "Any", successModel: null, errorModel: null };
2911
+ }
2912
+ outputSchema = resolvedSchema;
2913
+ }
2877
2914
  const emitter = new PythonEmitter(spec);
2878
- const result = emitter.handle(schema, {});
2915
+ const result = emitter.handle(outputSchema, {});
2879
2916
  return {
2880
2917
  returnType: result.type || "Any",
2881
- successModel: result.type,
2918
+ successModel: result.simple ? null : result.type,
2882
2919
  errorModel: null
2883
2920
  // TODO: Handle error models
2884
2921
  };
2885
2922
  }
2923
+ function isBottomSchema(spec, schema) {
2924
+ if (!schema) {
2925
+ return false;
2926
+ }
2927
+ const resolved = isRef2(schema) ? followRef2(spec, schema.$ref) : schema;
2928
+ return !!resolved.not && isEmpty2(resolved.not);
2929
+ }
2886
2930
  async function serializeModels(spec, emitter) {
2887
2931
  const models = {};
2888
2932
  const standardImports = [
2889
2933
  "from typing import Any, Dict, List, Optional, Union, Literal",
2890
- "from pydantic import BaseModel, Field",
2934
+ "from typing_extensions import Annotated, Never",
2935
+ "from pydantic import BaseModel, BeforeValidator, Field",
2891
2936
  "from datetime import datetime, date",
2892
2937
  "from uuid import UUID",
2893
- "from enum import Enum"
2938
+ "from enum import Enum",
2939
+ "",
2940
+ "def _reject_never(value: Any) -> Never:",
2941
+ " raise ValueError('Value is forbidden by the schema')",
2942
+ "",
2943
+ "_NeverValue = Annotated[Any, BeforeValidator(_reject_never)]"
2894
2944
  ].join("\n");
2895
2945
  emitter.onEmit((name, content, schema) => {
2896
2946
  const fullContent = `${standardImports}
@@ -2909,7 +2959,7 @@ ${content}`;
2909
2959
  if (spec.components?.schemas) {
2910
2960
  for (const [name, schema] of Object.entries(spec.components.schemas)) {
2911
2961
  if (!isRef2(schema)) {
2912
- emitter.handle(schema, { name });
2962
+ emitter.handle(schema, { name, pydantic: true });
2913
2963
  }
2914
2964
  }
2915
2965
  }
package/dist/bin.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/lib/cli.ts", "../src/lib/commands/init.ts", "../src/lib/project.ts", "../src/lib/project/analysis.ts", "../src/lib/project/output.ts", "../src/lib/project/cache.ts", "../src/lib/project/compiler.ts", "../src/lib/project/config.ts", "../src/lib/commands/find-framework.ts", "../src/lib/commands/find-spec-file.ts", "../src/lib/commands/guess-default-package-name.ts", "../src/lib/generators/apiref.ts", "../src/lib/options.ts", "../src/lib/generators/dart.ts", "../src/lib/generators/python.ts", "../../python/src/lib/generate.ts", "../../python/src/lib/http/dispatcher.txt", "../../python/src/lib/http/interceptors.txt", "../../python/src/lib/http/responses.txt", "../../python/src/lib/python-emitter.ts", "../src/lib/generators/readme.ts", "../src/lib/generators/typescript.ts"],
4
- "sourcesContent": ["#!/usr/bin/env node\nimport { Command, program } from 'commander';\n\nimport { readJson } from '@sdk-it/core/file-system.js';\n\nimport init from './commands/init.ts';\nimport apiref from './generators/apiref.ts';\nimport dart, { runDart } from './generators/dart.ts';\nimport python, { runPython } from './generators/python.ts';\nimport readme, { runReadme } from './generators/readme.ts';\nimport typescript, { runTypescript } from './generators/typescript.ts';\nimport { generateProject, loadProjectConfig } from './project.ts';\nimport type { SdkConfig } from './types.ts';\n\ninterface Options {\n config?: string;\n}\n\nconst generate = new Command('generate')\n .option('-c, --config <path>', 'Path to an SDK-IT configuration file')\n .action(async (options: Options) => {\n if (!options.config || options.config.endsWith('.ts')) {\n try {\n const config = await loadProjectConfig({ config: options.config });\n await generateProject(config);\n console.log('Client generated successfully!');\n return;\n } catch (error) {\n if (\n options.config ||\n !(error instanceof Error) ||\n !error.message.startsWith('Could not find sdk-it.config.ts')\n ) {\n throw error;\n }\n }\n }\n\n options.config ??= 'sdk-it.json';\n const config = await readJson<SdkConfig>(options.config);\n\n const promises: Promise<unknown>[] = [];\n\n if (config.generators?.typescript) {\n promises.push(\n runTypescript({\n spec: config.generators.typescript.spec,\n output: config.generators.typescript.output,\n mode: config.generators.typescript.mode,\n name: config.generators.typescript.name,\n useTsExtension: config.generators.typescript.useTsExtension ?? true,\n install: config.generators.typescript.install ?? false,\n verbose: false,\n defaultFormatter:\n config.generators.typescript.defaultFormatter ?? true,\n readme: config.generators.typescript.readme ?? true,\n pagination: config.generators.typescript.pagination,\n }),\n );\n }\n\n if (config.generators?.python) {\n promises.push(\n runPython({\n spec: config.generators.python.spec,\n output: config.generators.python.output,\n mode: config.generators.python.mode,\n name: config.generators.python.name,\n verbose: false,\n }),\n );\n }\n\n if (config.generators?.dart) {\n promises.push(\n runDart({\n spec: config.generators.dart.spec,\n output: config.generators.dart.output,\n mode: config.generators.dart.mode,\n name: config.generators.dart.name,\n verbose: false,\n pagination: config.generators.dart.pagination,\n }),\n );\n }\n\n // if (config.apiref) {\n // promises.push(runApiRef(config.apiref.spec, config.apiref.output));\n // }\n\n if (config.readme) {\n promises.push(runReadme(config.readme.spec, config.readme.output));\n }\n\n await Promise.all(promises);\n console.log('All configured generators completed successfully!');\n })\n .addCommand(typescript)\n .addCommand(python)\n .addCommand(dart)\n .addCommand(apiref)\n .addCommand(readme);\n\nconst cli = program\n .description(`CLI tool to interact with SDK-IT.`)\n .addCommand(generate, { isDefault: true })\n .addCommand(init)\n .addCommand(\n new Command('_internal').action(() => {\n // do nothing\n }),\n { hidden: true },\n )\n .parse(process.argv);\n\nexport default cli;\n", "import { checkbox, confirm, input, select } from '@inquirer/prompts';\nimport { Command } from 'commander';\nimport { writeFile } from 'node:fs/promises';\nimport { resolve } from 'node:path';\n\nimport type { PaginationConfig } from '@sdk-it/spec';\n\nimport { initializeProject } from '../project.ts';\nimport type { SdkConfig, TypeScriptOptions } from '../types.ts';\nimport { detectMonorepo } from './find-framework.ts';\nimport { findSpecFile } from './find-spec-file.ts';\nimport { guessTypescriptPackageName } from './guess-default-package-name.ts';\n\nconst specInput = async (defaultValue?: string) => {\n return input({\n message: 'OpenAPI or Postman specification file path:',\n default: defaultValue || './openapi.json',\n });\n};\n\nconst generatorConfigs = {\n typescript: {\n name: async (isMultipleGenerators = false) => {\n const defaultName =\n await guessTypescriptPackageName(isMultipleGenerators);\n return input({\n message: 'SDK package name:',\n default: defaultName,\n });\n },\n spec: specInput,\n output: async () => {\n let defaultValue = './ts-sdk';\n const monorepo = await detectMonorepo();\n if (monorepo === 'nx') {\n defaultValue = './packages/ts-sdk';\n }\n return await input({\n message: 'Output directory:',\n default: defaultValue,\n });\n },\n mode: async () => {\n const options = {\n mode: 'full' as 'full' | 'minimal',\n install: false,\n };\n options.mode = await select({\n message: 'Generation mode:',\n choices: [\n {\n name: 'Full (generates package.json and tsconfig.json)',\n value: 'full',\n },\n {\n name: 'Minimal (generates only the client TypeScript files)',\n value: 'minimal',\n },\n ],\n default: options.mode,\n });\n if (options.mode === 'full') {\n const installDeps = await confirm({\n message: 'Install dependencies automatically?',\n default: true,\n });\n options.install = installDeps;\n }\n return options;\n },\n pagination: async () => {\n let pagination: PaginationConfig | false = {\n guess: false,\n };\n const result = await confirm({\n message: 'Enable pagination support?',\n default: false,\n });\n if (result) {\n pagination.guess = await confirm({\n message: 'Would you like to guess pagination parameters?',\n default: false,\n });\n } else {\n pagination = false;\n }\n return pagination;\n },\n readme: () =>\n confirm({\n message: 'Generate README file?',\n default: true,\n }),\n defaultFormatter: () =>\n confirm({\n message: 'Use default formatter (prettier)?',\n default: true,\n }),\n framework: () =>\n input({\n message: 'Framework integrating with the SDK (optional):',\n }),\n formatter: () =>\n input({\n message:\n 'Custom formatter command (optional, e.g., \"prettier $SDK_IT_OUTPUT --write\"):',\n }),\n },\n python: {\n name: () =>\n input({\n message: 'SDK package name:',\n default: 'my-python-sdk',\n }),\n spec: specInput,\n output: () =>\n input({\n message: 'Output directory:',\n default: './python-sdk',\n }),\n mode: async () => {\n const isMonorepo = await detectMonorepo();\n return select({\n message: 'Generation mode:',\n choices: [\n {\n name: 'Full (generates complete project structure)',\n value: 'full',\n },\n {\n name: 'Minimal (generates only the client files)',\n value: 'minimal',\n },\n ],\n default: isMonorepo ? 'full' : 'full', // Default to full, especially for monorepos\n }).then((value) => value as 'full' | 'minimal');\n },\n formatter: () =>\n input({\n message:\n 'Custom formatter command (optional, e.g., \"black $SDK_IT_OUTPUT\" or \"ruff format $SDK_IT_OUTPUT\"):',\n }),\n },\n dart: {\n name: () =>\n input({\n message: 'SDK package name:',\n default: 'my-dart-sdk',\n }),\n spec: specInput,\n output: () =>\n input({\n message: 'Output directory:',\n default: './dart-sdk',\n }),\n mode: async () => {\n const isMonorepo = await detectMonorepo();\n return select({\n message: 'Generation mode:',\n choices: [\n {\n name: 'Full (generates complete project structure)',\n value: 'full',\n },\n {\n name: 'Minimal (generates only the client files)',\n value: 'minimal',\n },\n ],\n default: isMonorepo ? 'full' : 'full', // Default to full, especially for monorepos\n }).then((value) => value as 'full' | 'minimal');\n },\n pagination: async () => {\n let pagination: PaginationConfig | false = {\n guess: false,\n };\n const result = await confirm({\n message: 'Enable pagination support?',\n default: false,\n });\n if (result) {\n pagination.guess = await confirm({\n message: 'Would you like to guess pagination parameters?',\n default: false,\n });\n } else {\n pagination = false;\n }\n return pagination;\n },\n },\n};\n\nconst init = new Command('init')\n .description('Initialize SDK-IT configuration interactively')\n .option('--project <tsconfig>', 'Initialize from a backend tsconfig')\n .action(async (options: { project?: string }) => {\n if (options.project) {\n await initializeProject({ tsconfig: options.project });\n console.log('SDK-IT project configuration initialized.');\n return;\n }\n\n console.log(\"Welcome to SDK-IT! Let's set up your configuration.\\n\");\n\n const possibleSpecFile = await findSpecFile();\n const monorepo = await detectMonorepo();\n\n if (possibleSpecFile) {\n console.log(`\uD83D\uDD0D Auto-detected API specification: ${possibleSpecFile}`);\n }\n if (monorepo) {\n console.log(`\uD83D\uDCE6 Detected monorepo setup`);\n }\n\n if (possibleSpecFile || monorepo) {\n console.log(''); // Add spacing\n }\n\n const config: SdkConfig = {\n generators: {},\n };\n\n // Ask which generators to configure\n const generators = await checkbox({\n message: 'Which SDK generators would you like to configure?',\n loop: false,\n instructions: false,\n required: true,\n\n choices: [\n { name: 'TypeScript', value: 'typescript' },\n { name: 'Python', value: 'python' },\n { name: 'Dart', value: 'dart' },\n ],\n });\n // Configure each selected generator\n for (const generator of generators) {\n console.log(`\\nConfiguring ${generator} generator:`);\n\n if (generator === 'typescript') {\n const tsConfig = generatorConfigs.typescript;\n const isMultipleGenerators = generators.length > 1;\n\n const generatorConfig: TypeScriptOptions = {\n spec: await tsConfig.spec(possibleSpecFile),\n output: await tsConfig.output(),\n name: await tsConfig.name(isMultipleGenerators),\n defaultFormatter: await tsConfig.defaultFormatter(),\n readme: await tsConfig.readme(),\n pagination: await tsConfig.pagination(),\n ...(await tsConfig.mode()),\n };\n\n const customFramework = await tsConfig.framework();\n if (customFramework) {\n generatorConfig.framework = customFramework;\n }\n\n const customFormatter = await tsConfig.formatter();\n if (customFormatter) {\n generatorConfig.formatter = customFormatter;\n }\n\n config.generators.typescript = generatorConfig;\n } else if (generator === 'python') {\n config.generators.python = {\n spec: await generatorConfigs.python.spec(),\n output: await generatorConfigs.python.output(),\n mode: await generatorConfigs.python.mode(),\n name: await generatorConfigs.python.name(),\n };\n } else if (generator === 'dart') {\n config.generators.dart = {\n spec: await generatorConfigs.dart.spec(),\n output: await generatorConfigs.dart.output(),\n mode: await generatorConfigs.dart.mode(),\n name: await generatorConfigs.dart.name(),\n pagination: await generatorConfigs.dart.pagination(),\n };\n }\n }\n\n // Ask about README generation\n const generateReadme = await confirm({\n message: '\\nGenerate README documentation?',\n default: true,\n });\n\n if (generateReadme) {\n const readmeSpec = await input({\n message: 'OpenAPI specification for README:',\n default:\n config.generators.typescript?.spec ||\n possibleSpecFile ||\n './openapi.yaml',\n });\n\n const readmeOutput = await input({\n message: 'README output file:',\n default: './README.md',\n });\n\n config.readme = {\n spec: readmeSpec,\n output: readmeOutput,\n };\n }\n\n // Ask about API reference generation\n const generateApiRef = await confirm({\n message: '\\nGenerate API reference documentation?',\n default: false,\n });\n\n if (generateApiRef) {\n const autoDetected = await findSpecFile();\n const apirefSpec = await input({\n message: 'OpenAPI specification for API reference:',\n default:\n config.generators.typescript?.spec ||\n autoDetected ||\n './openapi.yaml',\n });\n\n const apirefOutput = await input({\n message: 'API reference output directory:',\n default: './docs',\n });\n\n config.apiref = {\n spec: apirefSpec,\n output: apirefOutput,\n };\n }\n\n // Write configuration file\n const configPath = resolve(process.cwd(), 'sdk-it.json');\n await writeFile(configPath, JSON.stringify(config, null, 2));\n\n // Show comprehensive next steps\n console.log(`\\n\u2705 Configuration saved to ${configPath}`);\n console.log('\\n\uD83D\uDE80 Next Steps:\\n');\n\n // Step 1: Generate SDKs\n console.log('1. Generate your SDK(s):');\n console.log(' npx @sdk-it/cli');\n\n // Step 2: Integration examples based on selected generators\n if (config.generators.typescript) {\n console.log('2. Integrate TypeScript SDK:');\n const importName = config.generators.typescript.name.replace(\n /[^a-zA-Z0-9]/g,\n '',\n );\n const outputDir = config.generators.typescript.output.replace('./', '');\n console.log(` import { ${importName} } from './${outputDir}';`);\n console.log(` const client = new ${importName}();`);\n console.log(` const result = await client.request('GET /users');\\n`);\n }\n\n if (config.generators.python) {\n console.log('2. Integrate Python SDK:');\n const outputDir = config.generators.python.output.replace('./', '');\n console.log(` # Add to your Python path or install locally`);\n console.log(` from ${outputDir} import Client`);\n console.log(` client = Client()`);\n console.log(` result = client.users.list_users()\\n`);\n }\n\n if (config.generators.dart) {\n console.log('2. Integrate Dart SDK:');\n const outputDir = config.generators.dart.output.replace('./', '');\n console.log(` # Add dependency to pubspec.yaml`);\n console.log(` import 'package:${outputDir}/client.dart';`);\n console.log(` final client = Client();`);\n console.log(` final result = await client.users.listUsers();\\n`);\n }\n\n // Step 3: Documentation\n console.log('3. Check generated documentation:');\n const outputs: string[] = [];\n if (config.generators.typescript)\n outputs.push(config.generators.typescript.output);\n if (config.generators.python) outputs.push(config.generators.python.output);\n if (config.generators.dart) outputs.push(config.generators.dart.output);\n\n outputs.forEach((output) => {\n if (output) {\n console.log(\n ` \uD83D\uDCD6 ${output}/README.md - Usage examples and API reference`,\n );\n }\n });\n\n if (config.readme) {\n console.log(\n ` \uD83D\uDCD6 ${config.readme.output} - Generated API documentation`,\n );\n }\n\n if (config.apiref) {\n console.log(` \uD83C\uDF10 ${config.apiref.output} - Interactive API reference`);\n }\n\n console.log('\\n4. Useful commands:');\n console.log(\n ' npx @sdk-it/cli # Regenerate SDKs after API changes',\n );\n console.log(\n ' npx @sdk-it/cli typescript --help # See TypeScript-specific options',\n );\n console.log(\n ' npx @sdk-it/cli python --help # See Python-specific options',\n );\n console.log(\n ' npx @sdk-it/cli dart --help # See Dart-specific options',\n );\n\n console.log('\\n\uD83D\uDCA1 Tips:');\n console.log(\n ' \u2022 Update your API spec and re-run `npx @sdk-it/cli generate` to sync changes',\n );\n console.log(\n ' \u2022 Generated SDKs include TypeScript definitions for excellent IDE support',\n );\n console.log(\n ' \u2022 Check the README files for authentication and configuration options',\n );\n\n console.log('\\n\uD83D\uDCDA Need help?');\n console.log(' \u2022 Documentation: https://sdk-it.dev/docs');\n console.log(\n ' \u2022 Examples: https://github.com/JanuaryLabs/sdk-it/tree/main/docs/examples',\n );\n console.log(' \u2022 Issues: https://github.com/JanuaryLabs/sdk-it/issues');\n\n console.log('\\nHappy coding! \uD83C\uDF89\\n');\n });\n\nexport default init;\n", "import { resolve } from 'node:path';\n\nimport { analyzeProject } from './project/analysis.ts';\nimport type { ProjectConfig } from './project/config.ts';\nimport { writeProjectClient } from './project/output.ts';\n\nexport {\n defineConfig,\n initializeProject,\n loadProjectConfig,\n} from './project/config.ts';\nexport type {\n InitializeProjectOptions,\n LoadProjectConfigOptions,\n ProjectConfig,\n ResolvedProjectConfig,\n} from './project/config.ts';\n\nexport async function generateProject(config: ProjectConfig): Promise<void> {\n const tsconfig = resolve(config.tsconfig);\n const openapi = await analyzeProject(tsconfig, config);\n await writeProjectClient(openapi, config);\n}\n", "import { createRequire } from 'node:module';\nimport ts from 'typescript';\n\nimport { type InjectImport, defaultTypesMap, getProgram } from '@sdk-it/core';\nimport { analyze } from '@sdk-it/generic';\nimport { responseAnalyzer as honoResponseAnalyzer } from '@sdk-it/hono';\n\nimport type { ProjectConfig } from './config.ts';\n\nexport async function analyzeProject(tsconfig: string, config: ProjectConfig) {\n const framework = resolveFramework(tsconfig, config.framework);\n if (framework === 'auto') {\n throw new Error(\n `Could not detect a supported framework from ${config.tsconfig}. Set framework to 'hono' to select it explicitly.`,\n );\n }\n\n const prisma = config.preset === 'none' ? undefined : detectPrisma(tsconfig);\n if (config.preset === 'prisma' && !prisma) {\n throw new Error(\n `Prisma preset was requested, but no Prisma client import was found in ${tsconfig}. Run prisma generate or set preset to 'none'.`,\n );\n }\n\n const { paths, components } = await analyze(tsconfig, {\n responseAnalyzer: honoResponseAnalyzer,\n ...(prisma\n ? {\n imports: prisma.imports,\n typesMap: {\n ...defaultTypesMap,\n Decimal: 'string',\n },\n }\n : {}),\n });\n\n return {\n openapi: '3.1.0' as const,\n info: {\n title: 'API',\n version: '0.0.0',\n },\n paths,\n components,\n };\n}\n\nfunction resolveFramework(\n tsconfig: string,\n configured: ProjectConfig['framework'],\n): 'hono' | 'auto' {\n return configured === undefined || configured === 'auto'\n ? detectFramework(tsconfig)\n : configured;\n}\n\nfunction detectFramework(tsconfig: string): 'hono' | 'auto' {\n const program = getProgram(tsconfig);\n for (const sourceFile of program.getSourceFiles()) {\n if (sourceFile.isDeclarationFile) continue;\n for (const statement of sourceFile.statements) {\n if (\n ts.isImportDeclaration(statement) &&\n ts.isStringLiteral(statement.moduleSpecifier) &&\n (statement.moduleSpecifier.text === 'hono' ||\n statement.moduleSpecifier.text.startsWith('@sdk-it/hono'))\n ) {\n return 'hono';\n }\n }\n }\n return 'auto';\n}\n\nfunction detectPrisma(\n tsconfig: string,\n): { imports: InjectImport[] } | undefined {\n const program = getProgram(tsconfig);\n const imports: InjectImport[] = [];\n const reportedModules = new Set<string>();\n for (const sourceFile of program.getSourceFiles()) {\n if (sourceFile.isDeclarationFile) continue;\n for (const statement of sourceFile.statements) {\n const prismaImport = getPrismaImport(statement);\n if (!prismaImport) continue;\n const resolvedModule = ts.resolveModuleName(\n prismaImport.moduleSpecifier,\n sourceFile.fileName,\n program.getCompilerOptions(),\n ts.sys,\n );\n if (!resolvedModule.resolvedModule) continue;\n\n let runtimeModule: string;\n try {\n runtimeModule = createRequire(sourceFile.fileName).resolve(\n prismaImport.moduleSpecifier,\n );\n } catch {\n continue;\n }\n\n if (!reportedModules.has(runtimeModule)) {\n console.log(`SDKIT: detected Prisma from ${runtimeModule}`);\n reportedModules.add(runtimeModule);\n }\n for (const { imported, local } of prismaImport.bindings) {\n if (\n !imports.some(\n (item) => item.import === local && item.from === runtimeModule,\n )\n ) {\n imports.push({\n import: local,\n from: runtimeModule,\n property: imported,\n });\n }\n }\n }\n }\n return imports.length > 0 ? { imports } : undefined;\n}\n\nfunction getPrismaImport(statement: ts.Statement):\n | {\n moduleSpecifier: string;\n bindings: Array<{ imported: string; local: string }>;\n }\n | undefined {\n if (\n !ts.isImportDeclaration(statement) ||\n !ts.isStringLiteral(statement.moduleSpecifier) ||\n !statement.importClause?.namedBindings ||\n !ts.isNamedImports(statement.importClause.namedBindings)\n ) {\n return undefined;\n }\n const bindings = statement.importClause.namedBindings.elements\n .map((element) => ({\n imported: element.propertyName?.text ?? element.name.text,\n local: element.name.text,\n }))\n .filter(({ imported }) => imported === 'Prisma' || imported === '$Enums');\n return bindings.length > 0\n ? { moduleSpecifier: statement.moduleSpecifier.text, bindings }\n : undefined;\n}\n", "import { writeFile } from 'node:fs/promises';\nimport { join, resolve } from 'node:path';\n\nimport { generate } from '@sdk-it/typescript';\n\nimport { hashProject, isCurrentGeneratedPackage } from './cache.ts';\nimport { compileGeneratedPackage } from './compiler.ts';\nimport type { ProjectConfig } from './config.ts';\n\ntype ProjectOpenApi = Parameters<typeof generate>[0];\n\nexport async function writeProjectClient(\n openapi: ProjectOpenApi,\n config: ProjectConfig,\n): Promise<void> {\n const output = resolve(config.output ?? '.sdk-it');\n const packageName = config.packageName ?? '@sdk-it/client';\n const hash = hashProject(openapi, packageName);\n if (await isCurrentGeneratedPackage(output, hash)) return;\n\n await generate(openapi, {\n output,\n mode: 'full',\n name: 'Client',\n packageName,\n readme: false,\n });\n await compileGeneratedPackage(output, packageName);\n await writeFile(join(output, '.project-hash'), hash);\n}\n", "import { createHash } from 'node:crypto';\nimport { access, readFile, readdir } from 'node:fs/promises';\nimport { createRequire } from 'node:module';\nimport { join, relative } from 'node:path';\nimport ts from 'typescript';\n\nimport type { generate } from '@sdk-it/typescript';\n\nconst require = createRequire(import.meta.url);\nconst projectGeneratorVersions = {\n cli: require('@sdk-it/cli/package.json').version,\n compiler: ts.version,\n typescript: require('@sdk-it/typescript/package.json').version,\n};\n\ntype ProjectOpenApi = Parameters<typeof generate>[0];\n\nexport function hashProject(\n openapi: ProjectOpenApi,\n packageName: string,\n): string {\n return createHash('sha256')\n .update(JSON.stringify({ openapi, packageName, projectGeneratorVersions }))\n .digest('hex');\n}\n\nexport async function isCurrentGeneratedPackage(\n output: string,\n hash: string,\n): Promise<boolean> {\n return (\n (await readOptionalFile(join(output, '.project-hash'))) === hash &&\n (await generatedPackageExists(output))\n );\n}\n\nasync function generatedPackageExists(output: string): Promise<boolean> {\n try {\n const sourceRoot = join(output, 'src');\n const sources = await findSourceFiles(sourceRoot);\n if (!sources.includes(join(sourceRoot, 'index.ts'))) return false;\n\n await Promise.all([\n access(join(output, 'package.json')),\n ...sources.flatMap((source) =>\n expectedCompiledFiles(output, sourceRoot, source).map((file) =>\n access(file),\n ),\n ),\n ]);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction expectedCompiledFiles(\n output: string,\n sourceRoot: string,\n source: string,\n): string[] {\n const compiled = relative(sourceRoot, source).slice(0, -3);\n return [\n join(output, 'dist', `${compiled}.js`),\n join(output, 'dist', `${compiled}.d.ts`),\n ];\n}\n\nasync function findSourceFiles(directory: string): Promise<string[]> {\n const entries = await readdir(directory, { withFileTypes: true });\n const files = await Promise.all(\n entries.map(async (entry) => {\n const path = join(directory, entry.name);\n if (entry.isDirectory()) return findSourceFiles(path);\n return entry.isFile() && path.endsWith('.ts') && !path.endsWith('.d.ts')\n ? [path]\n : [];\n }),\n );\n return files.flat();\n}\n\nasync function readOptionalFile(path: string): Promise<string | undefined> {\n try {\n return await readFile(path, 'utf8');\n } catch (error) {\n if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {\n return undefined;\n }\n throw error;\n }\n}\n", "import { readFile, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport ts from 'typescript';\n\ninterface GeneratedPackageManifest {\n name?: string;\n version?: string;\n type?: string;\n main?: string;\n module?: string;\n types?: string;\n publishConfig?: Record<string, unknown>;\n exports?: Record<string, unknown>;\n dependencies?: Record<string, string>;\n}\n\nexport async function compileGeneratedPackage(\n output: string,\n packageName: string,\n): Promise<void> {\n const source = join(output, 'src');\n const program = ts.createProgram({\n rootNames: ts.sys.readDirectory(source, ['.ts']),\n options: {\n allowSyntheticDefaultImports: true,\n declaration: true,\n module: ts.ModuleKind.ESNext,\n moduleResolution: ts.ModuleResolutionKind.Bundler,\n noEmitOnError: true,\n outDir: join(output, 'dist'),\n rewriteRelativeImportExtensions: true,\n rootDir: source,\n skipLibCheck: true,\n target: ts.ScriptTarget.ESNext,\n verbatimModuleSyntax: true,\n },\n });\n const result = program.emit();\n const diagnostics = [\n ...ts.getPreEmitDiagnostics(program),\n ...result.diagnostics,\n ].filter((diagnostic) => diagnostic.category === ts.DiagnosticCategory.Error);\n if (result.emitSkipped || diagnostics.length > 0) {\n throw new Error(formatCompilationError(output, diagnostics));\n }\n\n await synchronizeGeneratedManifest(output, packageName);\n}\n\nfunction formatCompilationError(\n output: string,\n diagnostics: readonly ts.Diagnostic[],\n): string {\n return `Failed to compile generated client:\\n${ts.formatDiagnosticsWithColorAndContext(\n diagnostics,\n {\n getCanonicalFileName: (fileName) => fileName,\n getCurrentDirectory: () => output,\n getNewLine: () => '\\n',\n },\n )}`;\n}\n\nasync function synchronizeGeneratedManifest(\n output: string,\n packageName: string,\n): Promise<void> {\n const manifestPath = join(output, 'package.json');\n const manifest = JSON.parse(\n await readFile(manifestPath, 'utf8'),\n ) as GeneratedPackageManifest;\n Object.assign(manifest, {\n name: packageName,\n version: '0.0.1',\n type: 'module',\n main: './dist/index.js',\n module: './dist/index.js',\n types: './dist/index.d.ts',\n });\n manifest.publishConfig = { ...manifest.publishConfig, access: 'public' };\n manifest.exports = {\n ...manifest.exports,\n './package.json': './package.json',\n '.': {\n types: './dist/index.d.ts',\n import: './dist/index.js',\n default: './dist/index.js',\n },\n };\n manifest.dependencies = {\n ...manifest.dependencies,\n 'fast-content-type-parse': '^3.0.0',\n zod: '^4.3.0',\n };\n await writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\\n`);\n}\n", "import { access, readFile, stat, writeFile } from 'node:fs/promises';\nimport { dirname, join, relative, resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\n\nexport interface ProjectConfig {\n tsconfig: string;\n framework?: 'auto' | 'hono';\n preset?: 'auto' | 'prisma' | 'none';\n output?: string;\n packageName?: string;\n}\n\nexport interface ResolvedProjectConfig extends ProjectConfig {\n output: string;\n}\n\nexport interface LoadProjectConfigOptions {\n cwd?: string;\n config?: string;\n}\n\nexport interface InitializeProjectOptions {\n cwd?: string;\n tsconfig: string;\n}\n\ninterface ProjectPackageManifest {\n workspaces?: string[] | { packages?: string[]; [key: string]: unknown };\n [key: string]: unknown;\n}\n\nexport function defineConfig<const Config extends ProjectConfig>(\n config: Config,\n): Config {\n return config;\n}\n\nexport async function loadProjectConfig(\n options: LoadProjectConfigOptions = {},\n): Promise<ResolvedProjectConfig> {\n const cwd = resolve(options.cwd ?? process.cwd());\n const configPath = options.config\n ? resolve(cwd, options.config)\n : await findProjectConfig(cwd);\n const loaded = await import(pathToFileURL(configPath).href);\n const config = loaded.default as ProjectConfig | undefined;\n if (!config || typeof config.tsconfig !== 'string') {\n throw new Error(\n `Expected ${configPath} to default export an SDK-IT config with a tsconfig path.`,\n );\n }\n\n const directory = dirname(configPath);\n return {\n ...config,\n tsconfig: resolve(directory, config.tsconfig),\n output: resolve(directory, config.output ?? '.sdk-it'),\n };\n}\n\nexport async function initializeProject(\n options: InitializeProjectOptions,\n): Promise<void> {\n const cwd = resolve(options.cwd ?? process.cwd());\n const configPath = join(cwd, 'sdk-it.config.ts');\n const tsconfigPath = resolve(cwd, options.tsconfig);\n await validateTsconfig(tsconfigPath);\n const tsconfig = relative(cwd, tsconfigPath).replaceAll('\\\\', '/');\n const relativeTsconfig = tsconfig.startsWith('.')\n ? tsconfig\n : `./${tsconfig}`;\n const configSource = `import { defineConfig } from '@sdk-it/cli';\n\nexport default defineConfig({\n tsconfig: '${relativeTsconfig}',\n});\n`;\n\n const existingConfig = await readOptionalFile(configPath);\n if (existingConfig !== undefined && existingConfig !== configSource) {\n throw new Error(\n `${configPath} already exists with different settings. Review it before replacing the file.`,\n );\n }\n\n const packagePath = join(cwd, 'package.json');\n const manifest = JSON.parse(\n await readFile(packagePath, 'utf8'),\n ) as ProjectPackageManifest;\n const manifestChanged = addGeneratedWorkspace(manifest);\n\n const gitignorePath = join(cwd, '.gitignore');\n const gitignore = (await readOptionalFile(gitignorePath)) ?? '';\n if (!ignoresGeneratedWorkspace(gitignore)) {\n const prefix =\n gitignore.length > 0 && !gitignore.endsWith('\\n') ? '\\n' : '';\n await writeFile(gitignorePath, `${gitignore}${prefix}.sdk-it/\\n`);\n }\n\n if (manifestChanged) {\n await writeFile(packagePath, `${JSON.stringify(manifest, null, 2)}\\n`);\n }\n\n if (existingConfig === undefined) {\n await writeFile(configPath, configSource);\n }\n}\n\nfunction addGeneratedWorkspace(manifest: ProjectPackageManifest): boolean {\n const workspaces = manifest.workspaces;\n if (Array.isArray(workspaces)) {\n if (workspaces.includes('.sdk-it')) return false;\n workspaces.push('.sdk-it');\n return true;\n }\n if (workspaces && Array.isArray(workspaces.packages)) {\n if (workspaces.packages.includes('.sdk-it')) return false;\n workspaces.packages.push('.sdk-it');\n return true;\n }\n manifest.workspaces = ['.sdk-it'];\n return true;\n}\n\nfunction ignoresGeneratedWorkspace(gitignore: string): boolean {\n return gitignore\n .split(/\\r?\\n/)\n .some((line) => line.trim() === '.sdk-it/' || line.trim() === '.sdk-it');\n}\n\nasync function validateTsconfig(path: string): Promise<void> {\n try {\n if ((await stat(path)).isFile()) return;\n } catch (error) {\n if (!(\n error instanceof Error &&\n 'code' in error &&\n error.code === 'ENOENT'\n )) {\n throw error;\n }\n }\n throw new Error(`Could not find a TypeScript project at ${path}.`);\n}\n\nasync function findProjectConfig(start: string): Promise<string> {\n let directory = start;\n while (true) {\n const candidate = join(directory, 'sdk-it.config.ts');\n try {\n await access(candidate);\n return candidate;\n } catch {\n const parent = dirname(directory);\n if (parent === directory) {\n throw new Error(\n `Could not find sdk-it.config.ts from ${start} or any parent directory.`,\n );\n }\n directory = parent;\n }\n }\n}\n\nasync function readOptionalFile(path: string): Promise<string | undefined> {\n try {\n return await readFile(path, 'utf8');\n } catch (error) {\n if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {\n return undefined;\n }\n throw error;\n }\n}\n", "import { resolve } from 'node:path';\n\nimport { exist } from '@sdk-it/core/file-system.js';\n\nconst monorepoIndicators = {\n lerna: () => exist(resolve(process.cwd(), 'lerna.json')),\n nx: () => exist(resolve(process.cwd(), 'nx.json')),\n pnpm: () => exist(resolve(process.cwd(), 'pnpm-workspace.yaml')),\n rush: () => exist(resolve(process.cwd(), 'rush.json')),\n} as const;\n\ntype Monorepo = keyof typeof monorepoIndicators;\n\nexport async function detectMonorepo(): Promise<Monorepo | undefined> {\n for (const [indicator, check] of Object.entries(monorepoIndicators)) {\n if (await check()) {\n return indicator as Monorepo;\n }\n }\n return void 0;\n}\n", "import { resolve } from 'node:path';\n\nimport { exist } from '@sdk-it/core/file-system.js';\n\nexport async function findSpecFile() {\n const commonNames = [\n 'openapi.json',\n 'openapi.yaml',\n 'openapi.yml',\n 'swagger.json',\n 'swagger.yaml',\n 'swagger.yml',\n 'api.json',\n 'api.yaml',\n 'api.yml',\n 'spec.json',\n 'spec.yaml',\n 'spec.yml',\n 'schema.json',\n 'schema.yaml',\n 'schema.yml',\n ];\n\n for (const name of commonNames) {\n if (await exist(resolve(process.cwd(), name))) {\n return `./${name}`;\n }\n }\n return undefined;\n}\n", "import { join } from 'node:path';\n\nimport { readJson } from '@sdk-it/core/file-system.js';\n\nexport async function guessTypescriptPackageName(\n consideringMultipleGenerator: boolean,\n): Promise<string> {\n try {\n const packageJson = await readJson<{ name: string }>(\n join(process.cwd(), 'package.json'),\n );\n if (packageJson.name) {\n const match = packageJson.name.match(/^@([^/]+)/);\n if (match) {\n const scope = match[1];\n return consideringMultipleGenerator\n ? `@${scope}/ts-sdk`\n : `@${scope}/sdk`;\n }\n }\n } catch {\n // If package.json doesn't exist or can't be read, use fallback\n }\n\n // Fallback if no package.json or no scope found\n return consideringMultipleGenerator ? 'ts-sdk' : 'sdk';\n}\n", "import { Command } from 'commander';\nimport { execa } from 'execa';\nimport { dirname, join } from 'node:path';\n\nimport { outputOption, specOption } from '../options.ts';\n\nexport default new Command('apiref')\n .description('Generate APIREF')\n .addOption(specOption.makeOptionMandatory(true))\n .addOption(outputOption.makeOptionMandatory(true))\n .action(async (options: { spec: string; output: string }) => {\n await runApiRef(options.spec, options.output);\n });\n\nexport function runApiRef(spec: string, output: string) {\n const packageDir = join(dirname(import.meta.url), '..', '..', 'apiref');\n return execa('nx', ['run', 'apiref:build', '--verbose'], {\n stdio: 'inherit',\n extendEnv: true,\n cwd: packageDir,\n env: {\n VITE_SPEC: spec,\n VITE_SDK_IT_OUTPUT: output,\n },\n });\n}\n", "import { Option } from 'commander';\n\nexport const specOption = new Option(\n '-s, --spec <spec>',\n 'Path to OpenAPI specification file',\n);\n\nexport const outputOption = new Option(\n '-o, --output <output>',\n 'Output directory for the generated SDK',\n);\n\n/**\n * Return the correct shell\u2010expansion syntax for an env var\n * on the current platform (cmd.exe vs POSIX).\n */\nexport function shellEnv(name: string): string {\n return process.platform === 'win32'\n ? `%${name}%` // Windows cmd.exe\n : `$${name}`; // POSIX shells\n}\n\n/**\n * Parse pagination configuration from CLI option value with dot notation support\n * @param incoming The pagination configuration value (e.g., \"false\", \"true\", \"guess=false\")\n * @returns PaginationConfig object or false\n */\nexport function parseDotConfig(\n incoming?: string,\n): Record<string, unknown> | boolean | undefined {\n if (incoming === 'false') {\n return false;\n }\n\n if (incoming === 'true') {\n return true;\n }\n\n if (!incoming) {\n return undefined;\n }\n\n // Handle dot notation like \"guess=false\"\n const config: Record<string, unknown> = {};\n const pairs = incoming.split(',');\n\n for (const pair of pairs) {\n if (pair.includes('=')) {\n const [key, val] = pair.split('=', 2);\n if (val === 'true') {\n config[key] = true;\n continue;\n }\n if (val === 'false') {\n config[key] = false;\n continue;\n }\n config[key] = val; // Keep as string if not boolean\n }\n }\n\n return config;\n}\n\nexport function parsePagination(config?: ReturnType<typeof parseDotConfig>) {\n if (config === true || config === undefined) {\n return undefined;\n }\n if (config === false) {\n return false;\n }\n return config;\n}\n", "import { Command } from 'commander';\nimport { execFile, execSync } from 'node:child_process';\n\nimport { generate } from '@sdk-it/dart';\nimport { loadSpec } from '@sdk-it/spec';\n\nimport {\n outputOption,\n parseDotConfig,\n parsePagination,\n shellEnv,\n specOption,\n} from '../options.ts';\nimport type { DartOptions } from '../types.ts';\n\ntype Options = Omit<DartOptions, 'pagination'> & {\n output: string;\n pagination?: DartOptions['pagination'] | string;\n};\nexport default new Command('dart')\n .description('Generate Dart SDK')\n .addOption(specOption.makeOptionMandatory(true))\n .addOption(outputOption.makeOptionMandatory(true))\n .option('-n, --name <name>', 'Name of the generated client', 'Client')\n .option(\n '--pagination <pagination>',\n 'Configure pagination (e.g., \"false\", \"true\", \"guess=false\")',\n 'true',\n )\n .option('-v, --verbose', 'Verbose output', false)\n .action(async (options: Options) => {\n await runDart(options);\n });\n\nexport async function runDart(options: Options) {\n await generate(await loadSpec(options.spec), {\n output: options.output,\n mode: options.mode || 'full',\n name: options.name,\n pagination:\n typeof options.pagination === 'string'\n ? parsePagination(parseDotConfig(options.pagination ?? 'true'))\n : options.pagination,\n formatCode: ({ output }) => {\n if (options.formatter) {\n const [command, ...args] = options.formatter.split(' ');\n execFile(command, args, {\n env: { ...process.env, SDK_IT_OUTPUT: output },\n });\n } else {\n execSync(`dart format ${shellEnv('SDK_IT_OUTPUT')}`, {\n env: { ...process.env, SDK_IT_OUTPUT: output },\n stdio: options.verbose ? 'inherit' : 'pipe',\n });\n // execSync('dart fix --apply $SDK_IT_OUTPUT ', {\n // env: { ...process.env, SDK_IT_OUTPUT: output },\n // stdio: options.verbose ? 'inherit' : 'pipe',\n // });\n }\n },\n });\n}\n", "import { Command } from 'commander';\nimport { execFile, execSync } from 'node:child_process';\n\nimport { generate } from '@sdk-it/python';\nimport { loadSpec, toIR } from '@sdk-it/spec';\n\nimport { outputOption, shellEnv, specOption } from '../options.ts';\nimport type { PythonOptions } from '../types.ts';\n\nexport default new Command('python')\n .description('Generate Python SDK')\n .addOption(specOption.makeOptionMandatory(true))\n .addOption(outputOption.makeOptionMandatory(true))\n .option('-n, --name <n>', 'Name of the generated client', 'Client')\n .option('-v, --verbose', 'Verbose output', false)\n .option('--formatter <formatter>', 'Formatter to use for the generated code')\n .action(async (options: PythonOptions) => {\n await runPython(options);\n });\n\nexport async function runPython(options: PythonOptions) {\n const spec = await toIR({ spec: await loadSpec(options.spec) }, true);\n await generate(spec, {\n output: options.output,\n mode: options.mode || 'full',\n name: options.name,\n formatCode: ({ output }: { output: string }) => {\n if (options.formatter) {\n const [command, ...args] = options.formatter.split(' ');\n execFile(command, args, {\n env: { ...process.env, SDK_IT_OUTPUT: output },\n });\n } else {\n try {\n // Try black first (more common)\n execSync(`black ${shellEnv('SDK_IT_OUTPUT')}`, {\n env: { ...process.env, SDK_IT_OUTPUT: output },\n stdio: options.verbose ? 'inherit' : 'pipe',\n });\n } catch {\n try {\n // Fallback to ruff format if black is not available\n execSync(`ruff format ${shellEnv('SDK_IT_OUTPUT')}`, {\n env: { ...process.env, SDK_IT_OUTPUT: output },\n stdio: options.verbose ? 'inherit' : 'pipe',\n });\n } catch {\n // If neither formatter is available, continue without formatting\n if (options.verbose) {\n console.warn(\n 'No Python formatter found (black or ruff). Skipping formatting.',\n );\n }\n }\n }\n }\n },\n });\n}\n", "import { readdir } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type {\n OpenAPIObject,\n OperationObject,\n ReferenceObject,\n SchemaObject,\n} from 'openapi3-ts/oas31';\nimport { snakecase } from 'stringcase';\n\nimport { isEmpty, isRef, pascalcase } from '@sdk-it/core';\nimport {\n type ReadFolderFn,\n type Writer,\n createWriterProxy,\n writeFiles,\n} from '@sdk-it/core/file-system.js';\nimport {\n type IR,\n cleanFiles,\n forEachOperation,\n isSuccessStatusCode,\n parseJsonContentType,\n readWriteMetadata,\n toIR,\n} from '@sdk-it/spec';\n\nimport dispatcherTxt from './http/dispatcher.txt';\nimport interceptorsTxt from './http/interceptors.txt';\nimport responsesTxt from './http/responses.txt';\nimport { PythonEmitter } from './python-emitter.ts';\n\nexport async function generate(\n openapi: OpenAPIObject,\n settings: {\n output: string;\n cleanup?: boolean;\n name?: string;\n writer?: Writer;\n readFolder?: ReadFolderFn;\n /**\n * full: generate a full project including requirements.txt\n * minimal: generate only the client sdk\n */\n mode?: 'full' | 'minimal';\n formatCode?: (options: { output: string }) => void | Promise<void>;\n },\n) {\n const spec = await toIR({ spec: openapi }, true);\n\n const clientName = settings.name || 'Client';\n const output = settings.output;\n const { writer, files: writtenFiles } = createWriterProxy(\n settings.writer ?? writeFiles,\n settings.output,\n );\n settings.writer = writer;\n settings.readFolder ??= async (folder: string) => {\n const files = await readdir(folder, { withFileTypes: true });\n return files.map((file) => ({\n fileName: file.name,\n filePath: join(file.parentPath, file.name),\n isFolder: file.isDirectory(),\n }));\n };\n\n const groups: Record<\n string,\n {\n className: string;\n methods: string[];\n }\n > = {};\n\n // Process each operation and group by tags\n forEachOperation(spec, (entry, operation) => {\n console.log(`Processing ${entry.method} ${entry.path}`);\n const group = (groups[entry.tag] ??= {\n className: `${pascalcase(entry.tag)}Api`,\n methods: [],\n });\n\n const input = toInputs(spec, { entry, operation });\n const response = toOutput(spec, operation);\n\n // Generate method for this operation\n const methodName = snakecase(\n operation.operationId ||\n `${entry.method}_${entry.path.replace(/[^a-zA-Z0-9]/g, '_')}`,\n );\n const returnType = response ? response.returnType : 'httpx.Response';\n\n const docstring =\n operation.summary || operation.description\n ? ` \"\"\"${operation.summary || operation.description}\"\"\"`\n : '';\n\n group.methods.push(`\n async def ${methodName}(self${input.haveInput ? `, input_data: ${input.inputName}` : ''}) -> ${returnType}:\n${docstring}\n config = RequestConfig(\n method='${entry.method.toUpperCase()}',\n url='${entry.path}',\n )\n\n ${input.haveInput ? 'config = input_data.to_request_config(config)' : ''}\n\n response = await self.dispatcher.${input.contentType}(config)\n ${response ? `return await self.receiver.json(response, ${response.successModel || 'None'}, ${response.errorModel || 'None'})` : 'return response'}\n `);\n });\n\n // Generate models using the Python emitter\n const emitter = new PythonEmitter(spec);\n const models = await serializeModels(spec, emitter);\n\n // Generate API group classes\n const apiClasses = Object.entries(groups).reduce<Record<string, string>>(\n (acc, [name, { className, methods }]) => {\n const fileName = `api/${snakecase(name)}_api.py`;\n const imports = [\n 'from typing import Optional',\n 'import httpx',\n '',\n 'from ..http.dispatcher import Dispatcher, RequestConfig',\n 'from ..http.responses import Receiver',\n 'from ..inputs import *',\n 'from ..outputs import *',\n 'from ..models import *',\n '',\n ].join('\\n');\n\n acc[fileName] = `${imports}\nclass ${className}:\n \"\"\"API client for ${name} operations.\"\"\"\n\n def __init__(self, dispatcher: Dispatcher, receiver: Receiver):\n self.dispatcher = dispatcher\n self.receiver = receiver\n${methods.join('\\n')}\n`;\n return acc;\n },\n {},\n );\n\n // Generate main client\n const apiImports = Object.keys(groups)\n .map(\n (name) =>\n `from .api.${snakecase(name)}_api import ${pascalcase(name)}Api`,\n )\n .join('\\n');\n\n const apiProperties = Object.keys(groups)\n .map(\n (name) =>\n ` self.${snakecase(name)} = ${pascalcase(name)}Api(dispatcher, receiver)`,\n )\n .join('\\n');\n\n const clientCode = `\"\"\"Main API client.\"\"\"\n\nfrom typing import Optional, List\nimport httpx\n\n${apiImports}\nfrom .http.dispatcher import Dispatcher, RequestConfig\nfrom .http.responses import Receiver\nfrom .http.interceptors import (\n Interceptor,\n BaseUrlInterceptor,\n LoggingInterceptor,\n AuthInterceptor,\n UserAgentInterceptor,\n)\n\n\nclass ${clientName}:\n \"\"\"Main API client for the SDK.\"\"\"\n\n def __init__(\n self,\n base_url: str,\n token: Optional[str] = None,\n api_key: Optional[str] = None,\n api_key_header: str = 'X-API-Key',\n enable_logging: bool = False,\n user_agent: Optional[str] = None,\n custom_interceptors: Optional[List[Interceptor]] = None,\n ):\n \"\"\"\n Initialize the API client.\n\n Args:\n base_url: Base URL for the API\n token: Bearer token for authentication\n api_key: API key for authentication\n api_key_header: Header name for API key authentication\n enable_logging: Enable request/response logging\n user_agent: Custom User-Agent header\n custom_interceptors: Additional custom interceptors\n \"\"\"\n self.base_url = base_url\n\n # Build interceptor chain\n interceptors = []\n\n # Base URL interceptor (always first)\n interceptors.append(BaseUrlInterceptor(base_url))\n\n # Authentication interceptor\n if token or api_key:\n interceptors.append(AuthInterceptor(token=token, api_key=api_key, api_key_header=api_key_header))\n\n # User agent interceptor\n if user_agent:\n interceptors.append(UserAgentInterceptor(user_agent))\n\n # Logging interceptor\n if enable_logging:\n interceptors.append(LoggingInterceptor())\n\n # Custom interceptors\n if custom_interceptors:\n interceptors.extend(custom_interceptors)\n\n # Initialize dispatcher and receiver\n self.dispatcher = Dispatcher(interceptors)\n self.receiver = Receiver(interceptors)\n\n # Initialize API clients\n${apiProperties}\n\n async def __aenter__(self):\n return self\n\n async def __aexit__(self, exc_type, exc_val, exc_tb):\n await self.close()\n\n async def close(self):\n \"\"\"Close the HTTP client.\"\"\"\n await self.dispatcher.close()\n`;\n\n // Write all files\n await settings.writer(output, {\n ...models,\n ...apiClasses,\n 'client.py': clientCode,\n 'http/dispatcher.py': dispatcherTxt,\n 'http/interceptors.py': interceptorsTxt,\n 'http/responses.py': responsesTxt,\n '__init__.py': `\"\"\"SDK package.\"\"\"\n\nfrom .client import ${clientName}\n\n__all__ = ['${clientName}']\n`,\n });\n\n // Generate requirements.txt if in full mode\n if (settings.mode === 'full') {\n const requirements = `# HTTP client\nhttpx>=0.24.0,<1.0.0\n\n# Data validation and serialization\npydantic>=2.0.0,<3.0.0\n\n# Enhanced type hints\ntyping-extensions>=4.0.0\n\n# Optional: For better datetime handling\npython-dateutil>=2.8.0\n`;\n\n await settings.writer(output, {\n 'requirements.txt': requirements,\n });\n }\n\n // Handle metadata and cleanup\n const metadata = await readWriteMetadata(\n settings.output,\n Array.from(writtenFiles),\n );\n\n if (settings.cleanup !== false && writtenFiles.size > 0) {\n await cleanFiles(metadata.content, settings.output, [\n '/__init__.py',\n 'requirements.txt',\n '/metadata.json',\n ]);\n }\n\n // Generate __init__.py files for packages\n await settings.writer(output, {\n 'models/__init__.py': await generateModuleInit(\n join(output, 'models'),\n settings.readFolder,\n ),\n 'inputs/__init__.py': await generateModuleInit(\n join(output, 'inputs'),\n settings.readFolder,\n ),\n 'outputs/__init__.py': await generateModuleInit(\n join(output, 'outputs'),\n settings.readFolder,\n ),\n 'api/__init__.py': await generateModuleInit(\n join(output, 'api'),\n settings.readFolder,\n ),\n 'http/__init__.py': `\"\"\"HTTP utilities.\"\"\"\n\nfrom .dispatcher import Dispatcher, RequestConfig\nfrom .interceptors import *\nfrom .responses import *\n\n__all__ = [\n 'Dispatcher',\n 'RequestConfig',\n 'ApiResponse',\n 'ErrorResponse',\n 'Interceptor',\n 'BaseUrlInterceptor',\n 'LoggingInterceptor',\n 'AuthInterceptor',\n]\n`,\n });\n\n // Run formatter if provided\n if (settings.formatCode) {\n await settings.formatCode({ output: settings.output });\n }\n}\n\nasync function generateModuleInit(\n folder: string,\n readFolder: ReadFolderFn,\n): Promise<string> {\n try {\n const files = await readFolder(folder);\n const pyFiles = files\n .filter(\n (file) =>\n file.fileName.endsWith('.py') && file.fileName !== '__init__.py',\n )\n .map((file) => file.fileName.replace('.py', ''));\n\n if (pyFiles.length === 0) {\n return '\"\"\"Package module.\"\"\"\\n';\n }\n\n const imports = pyFiles.map((name) => `from .${name} import *`).join('\\n');\n return `\"\"\"Package module.\"\"\"\\n\\n${imports}\\n`;\n } catch {\n return '\"\"\"Package module.\"\"\"\\n';\n }\n}\n\nfunction toInputs(\n spec: IR,\n { entry, operation }: { entry: unknown; operation: OperationObject },\n) {\n const inputName = (entry as { inputName?: string }).inputName || 'Input';\n const haveInput =\n !isEmpty(operation.parameters) || !isEmpty(operation.requestBody);\n\n let contentType = 'json';\n if (operation.requestBody && !isRef(operation.requestBody)) {\n const content = operation.requestBody.content;\n if (content) {\n const contentTypes = Object.keys(content);\n if (contentTypes.some((type) => type.includes('multipart'))) {\n contentType = 'multipart';\n } else if (contentTypes.some((type) => type.includes('form'))) {\n contentType = 'form';\n }\n }\n }\n\n return {\n inputName,\n haveInput,\n contentType,\n };\n}\n\nfunction toOutput(spec: IR, operation: OperationObject) {\n if (!operation.responses) {\n return null;\n }\n\n // Find success response\n const successResponse = Object.entries(operation.responses).find(([code]) =>\n isSuccessStatusCode(Number(code)),\n );\n\n if (!successResponse) {\n return null;\n }\n\n const [, response] = successResponse;\n if (isRef(response)) {\n return null;\n }\n\n const content = response.content;\n if (!content) {\n return { returnType: 'None', successModel: null, errorModel: null };\n }\n\n // Find JSON content type\n const jsonContent = Object.entries(content).find(([type]) =>\n parseJsonContentType(type),\n );\n\n if (!jsonContent) {\n return {\n returnType: 'httpx.Response',\n successModel: null,\n errorModel: null,\n };\n }\n\n const [, mediaType] = jsonContent;\n const schema = (mediaType as { schema?: SchemaObject | ReferenceObject })\n .schema;\n\n if (!schema || isRef(schema)) {\n return { returnType: 'Any', successModel: null, errorModel: null };\n }\n\n // Generate return type based on schema\n const emitter = new PythonEmitter(spec);\n const result = emitter.handle(schema, {});\n\n return {\n returnType: result.type || 'Any',\n successModel: result.type,\n errorModel: null, // TODO: Handle error models\n };\n}\n\nasync function serializeModels(\n spec: IR,\n emitter: PythonEmitter,\n): Promise<Record<string, string>> {\n const models: Record<string, string> = {};\n\n // Standard imports for all Python model files\n const standardImports = [\n 'from typing import Any, Dict, List, Optional, Union, Literal',\n 'from pydantic import BaseModel, Field',\n 'from datetime import datetime, date',\n 'from uuid import UUID',\n 'from enum import Enum',\n ].join('\\n');\n\n // Emit all schemas\n emitter.onEmit((name: string, content: string, schema: SchemaObject) => {\n // Add imports to the content\n const fullContent = `${standardImports}\n${schema['x-inputname'] ? 'from ..http.dispatcher import RequestConfig' : ''}\n\n\n${content}`;\n\n if (schema['x-inputname']) {\n models[`inputs/${snakecase(name)}.py`] = fullContent;\n } else if (schema['x-response-name']) {\n models[`outputs/${snakecase(name)}.py`] = fullContent;\n } else {\n models[`models/${snakecase(name)}.py`] = fullContent;\n }\n });\n\n // Process all schemas in components\n if (spec.components?.schemas) {\n for (const [name, schema] of Object.entries(spec.components.schemas)) {\n if (!isRef(schema)) {\n emitter.handle(schema, { name });\n }\n }\n }\n\n return models;\n}\n", "\"\"\"HTTP dispatcher for making API requests.\"\"\"\n\nimport asyncio\nimport logging\nfrom typing import Any, Dict, List, Optional, Union\nfrom urllib.parse import urljoin, urlparse\n\nimport httpx\nfrom pydantic import BaseModel\n\nfrom .interceptors import Interceptor\nfrom .responses import ApiResponse, ErrorResponse\n\n\nclass RequestConfig(BaseModel):\n \"\"\"Configuration for an HTTP request.\"\"\"\n\n method: str\n url: str\n headers: Optional[Dict[str, str]] = None\n params: Optional[Dict[str, Any]] = None\n json_data: Optional[Dict[str, Any]] = None\n form_data: Optional[Dict[str, Any]] = None\n files: Optional[Dict[str, Any]] = None\n timeout: Optional[Union[float, httpx.Timeout]] = None\n \n class Config:\n \"\"\"Pydantic configuration.\"\"\"\n arbitrary_types_allowed = True\n\n\nclass Dispatcher:\n \"\"\"HTTP client dispatcher with interceptor support.\"\"\"\n\n def __init__(\n self, \n interceptors: Optional[List[Interceptor]] = None,\n client: Optional[httpx.AsyncClient] = None,\n timeout: Optional[Union[float, httpx.Timeout]] = None\n ):\n \"\"\"Initialize the dispatcher.\n \n Args:\n interceptors: List of interceptors to apply to requests/responses\n client: Custom httpx.AsyncClient instance (creates default if None)\n timeout: Default timeout for requests\n \"\"\"\n self.interceptors = interceptors or []\n self.client = client or httpx.AsyncClient(timeout=timeout)\n self.logger = logging.getLogger(__name__)\n\n async def __aenter__(self):\n \"\"\"Async context manager entry.\"\"\"\n return self\n\n async def __aexit__(self, exc_type, exc_val, exc_tb):\n \"\"\"Async context manager exit.\"\"\"\n await self.client.aclose()\n\n async def request(self, config: RequestConfig) -> httpx.Response:\n \"\"\"Execute an HTTP request with interceptor processing.\n \n Args:\n config: Request configuration\n \n Returns:\n HTTP response after processing through interceptors\n \n Raises:\n httpx.HTTPError: For HTTP-related errors\n ValueError: For invalid request configuration\n \"\"\"\n # Process request interceptors\n processed_config = config\n for interceptor in self.interceptors:\n processed_config = await interceptor.process_request(processed_config)\n\n # Prepare request arguments\n request_kwargs = self._prepare_request_kwargs(processed_config)\n\n try:\n # Execute request\n response = await self.client.request(**request_kwargs)\n \n # Process response interceptors (in reverse order)\n for interceptor in reversed(self.interceptors):\n response = await interceptor.process_response(response)\n\n return response\n \n except httpx.RequestError as e:\n self.logger.error(f\"Request failed: {e}\")\n raise\n except Exception as e:\n self.logger.error(f\"Unexpected error during request: {e}\")\n raise\n\n def _prepare_request_kwargs(self, config: RequestConfig) -> Dict[str, Any]:\n \"\"\"Prepare keyword arguments for httpx request.\n \n Args:\n config: Request configuration\n \n Returns:\n Dictionary of kwargs for httpx.request\n \n Raises:\n ValueError: If request configuration is invalid\n \"\"\"\n if not config.method:\n raise ValueError(\"Request method cannot be empty\")\n \n if not config.url:\n raise ValueError(\"Request URL cannot be empty\")\n\n request_kwargs = {\n 'method': config.method.upper(),\n 'url': config.url,\n 'headers': config.headers or {},\n 'params': config.params,\n 'timeout': config.timeout,\n }\n\n # Handle different content types\n content_type_set = False\n \n if config.json_data is not None:\n request_kwargs['json'] = config.json_data\n if 'Content-Type' not in request_kwargs['headers']:\n request_kwargs['headers']['Content-Type'] = 'application/json'\n content_type_set = True\n \n elif config.form_data is not None:\n request_kwargs['data'] = config.form_data\n if 'Content-Type' not in request_kwargs['headers']:\n request_kwargs['headers']['Content-Type'] = 'application/x-www-form-urlencoded'\n content_type_set = True\n \n elif config.files is not None:\n request_kwargs['files'] = config.files\n # Don't set Content-Type for multipart/form-data - httpx will handle it automatically\n content_type_set = True\n\n # Validate that only one content type is set\n content_fields = [config.json_data, config.form_data, config.files]\n non_none_count = sum(1 for field in content_fields if field is not None)\n \n if non_none_count > 1:\n raise ValueError(\n \"Only one of json_data, form_data, or files can be set in a single request\"\n )\n\n return request_kwargs\n\n async def json(self, config: RequestConfig) -> httpx.Response:\n \"\"\"Make a JSON request.\n \n Args:\n config: Request configuration\n \n Returns:\n HTTP response\n \"\"\"\n return await self.request(config)\n\n async def form(self, config: RequestConfig) -> httpx.Response:\n \"\"\"Make a form-encoded request.\n \n Args:\n config: Request configuration\n \n Returns:\n HTTP response\n \"\"\"\n return await self.request(config)\n\n async def multipart(self, config: RequestConfig) -> httpx.Response:\n \"\"\"Make a multipart/form-data request.\n \n Args:\n config: Request configuration\n \n Returns:\n HTTP response\n \"\"\"\n return await self.request(config)\n\n async def close(self):\n \"\"\"Close the HTTP client and clean up resources.\"\"\"\n await self.client.aclose()\n\n\nclass Receiver:\n \"\"\"Response processor with interceptor support.\"\"\"\n\n def __init__(\n self, \n interceptors: Optional[List[Interceptor]] = None,\n logger: Optional[logging.Logger] = None\n ):\n \"\"\"Initialize the receiver.\n \n Args:\n interceptors: List of interceptors to apply to responses\n logger: Custom logger instance\n \"\"\"\n self.interceptors = interceptors or []\n self.logger = logger or logging.getLogger(__name__)\n\n async def json(\n self, \n response: httpx.Response, \n success_model: Optional[type] = None, \n error_model: Optional[type] = None\n ) -> Any:\n \"\"\"Process a JSON response.\n \n Args:\n response: HTTP response to process\n success_model: Pydantic model for successful responses\n error_model: Pydantic model for error responses\n \n Returns:\n Parsed response data, optionally as model instances\n \n Raises:\n ErrorResponse: For HTTP error status codes\n ValueError: For response parsing errors\n \"\"\"\n # Process response interceptors\n processed_response = response\n for interceptor in self.interceptors:\n processed_response = await interceptor.process_response(processed_response)\n\n # Handle different status codes\n if 200 <= processed_response.status_code < 300:\n return await self._handle_success_response(\n processed_response, success_model\n )\n else:\n await self._handle_error_response(\n processed_response, error_model\n )\n\n async def _handle_success_response(\n self, \n response: httpx.Response, \n success_model: Optional[type] = None\n ) -> Any:\n \"\"\"Handle successful response.\n \n Args:\n response: HTTP response\n success_model: Pydantic model for successful responses\n \n Returns:\n Parsed response data\n \n Raises:\n ValueError: For parsing errors\n \"\"\"\n if not response.content:\n return None\n\n try:\n data = response.json()\n \n if success_model:\n if isinstance(data, list):\n return [success_model(**item) for item in data]\n else:\n return success_model(**data)\n \n return data\n \n except Exception as e:\n self.logger.error(f\"Failed to parse success response: {e}\")\n raise ValueError(f\"Failed to parse response: {e}\")\n\n async def _handle_error_response(\n self, \n response: httpx.Response, \n error_model: Optional[type] = None\n ) -> None:\n \"\"\"Handle error response.\n \n Args:\n response: HTTP response\n error_model: Pydantic model for error responses\n \n Raises:\n ErrorResponse: Always raises with error details\n \"\"\"\n error_data = {}\n \n if response.content:\n try:\n error_data = response.json()\n except Exception:\n # Fallback to text content if JSON parsing fails\n error_data = {'message': response.text}\n\n if error_model:\n try:\n error = error_model(**error_data)\n raise ErrorResponse(error, response.status_code, dict(response.headers))\n except Exception as e:\n self.logger.warning(f\"Failed to parse error with model {error_model}: {e}\")\n\n raise ErrorResponse(error_data, response.status_code, dict(response.headers))\n\n async def stream(self, response: httpx.Response) -> httpx.Response:\n \"\"\"Return streaming response as-is.\n \n Args:\n response: HTTP response\n \n Returns:\n The unmodified streaming response\n \"\"\"\n return response\n\n async def text(self, response: httpx.Response) -> str:\n \"\"\"Get response as text.\n \n Args:\n response: HTTP response\n \n Returns:\n Response body as text\n \n Raises:\n ErrorResponse: For HTTP error status codes\n \"\"\"\n # Process response interceptors\n processed_response = response\n for interceptor in self.interceptors:\n processed_response = await interceptor.process_response(processed_response)\n\n if 200 <= processed_response.status_code < 300:\n return processed_response.text\n else:\n error_data = {'message': processed_response.text}\n raise ErrorResponse(error_data, processed_response.status_code, dict(processed_response.headers))\n\n async def bytes(self, response: httpx.Response) -> bytes:\n \"\"\"Get response as bytes.\n \n Args:\n response: HTTP response\n \n Returns:\n Response body as bytes\n \n Raises:\n ErrorResponse: For HTTP error status codes\n \"\"\"\n # Process response interceptors\n processed_response = response\n for interceptor in self.interceptors:\n processed_response = await interceptor.process_response(processed_response)\n\n if 200 <= processed_response.status_code < 300:\n return processed_response.content\n else:\n error_data = {'message': 'Binary response error'}\n raise ErrorResponse(error_data, processed_response.status_code, dict(processed_response.headers))\n\n\n# Convenience functions for common use cases\nasync def quick_request(\n method: str,\n url: str,\n interceptors: Optional[List[Interceptor]] = None,\n **kwargs\n) -> httpx.Response:\n \"\"\"Make a quick HTTP request with interceptors.\n \n Args:\n method: HTTP method\n url: Request URL\n interceptors: List of interceptors to apply\n **kwargs: Additional request configuration\n \n Returns:\n HTTP response\n \"\"\"\n config = RequestConfig(method=method, url=url, **kwargs)\n \n async with Dispatcher(interceptors=interceptors) as dispatcher:\n return await dispatcher.request(config)\n\n\nasync def quick_json_request(\n method: str,\n url: str,\n json_data: Optional[Dict[str, Any]] = None,\n interceptors: Optional[List[Interceptor]] = None,\n success_model: Optional[type] = None,\n error_model: Optional[type] = None,\n **kwargs\n) -> Any:\n \"\"\"Make a quick JSON HTTP request with interceptors.\n \n Args:\n method: HTTP method\n url: Request URL\n json_data: JSON data to send\n interceptors: List of interceptors to apply\n success_model: Pydantic model for successful responses\n error_model: Pydantic model for error responses\n **kwargs: Additional request configuration\n \n Returns:\n Parsed JSON response\n \"\"\"\n config = RequestConfig(method=method, url=url, json_data=json_data, **kwargs)\n \n async with Dispatcher(interceptors=interceptors) as dispatcher:\n response = await dispatcher.request(config)\n receiver = Receiver(interceptors=interceptors)\n return await receiver.json(response, success_model, error_model)\n", "\"\"\"HTTP interceptors for request/response processing.\"\"\"\n\nimport asyncio\nimport logging\nimport time\nfrom abc import ABC, abstractmethod\nfrom typing import Dict, Optional, List, Any, Union\nfrom urllib.parse import urljoin\n\nimport httpx\n\nfrom .dispatcher import RequestConfig\n\n\nclass Interceptor(ABC):\n \"\"\"Base class for HTTP interceptors.\"\"\"\n\n @abstractmethod\n async def process_request(self, config: RequestConfig) -> RequestConfig:\n \"\"\"Process an outgoing request.\n\n Args:\n config: The request configuration to process\n\n Returns:\n The modified request configuration\n \"\"\"\n pass\n\n @abstractmethod\n async def process_response(self, response: httpx.Response) -> httpx.Response:\n \"\"\"Process an incoming response.\n\n Args:\n response: The HTTP response to process\n\n Returns:\n The processed response\n \"\"\"\n pass\n\n\nclass BaseUrlInterceptor(Interceptor):\n \"\"\"Interceptor that prepends base URL to relative URLs.\"\"\"\n\n def __init__(self, base_url: str):\n \"\"\"Initialize the base URL interceptor.\n\n Args:\n base_url: The base URL to prepend to relative URLs\n \"\"\"\n self.base_url = base_url.rstrip('/')\n\n async def process_request(self, config: RequestConfig) -> RequestConfig:\n \"\"\"Prepend base URL if the request URL is relative.\n\n Args:\n config: The request configuration\n\n Returns:\n The modified request configuration with absolute URL\n \"\"\"\n if not config.url.startswith(('http://', 'https://')):\n # Use urljoin for proper URL joining, ensuring single slash\n config.url = urljoin(self.base_url + '/', config.url.lstrip('/'))\n return config\n\n async def process_response(self, response: httpx.Response) -> httpx.Response:\n \"\"\"Pass through response unchanged.\n\n Args:\n response: The HTTP response\n\n Returns:\n The unmodified response\n \"\"\"\n return response\n\n\nclass LoggingInterceptor(Interceptor):\n \"\"\"Interceptor that logs requests and responses using Python's logging module.\"\"\"\n\n def __init__(\n self,\n enabled: bool = True,\n logger: Optional[logging.Logger] = None,\n log_level: int = logging.INFO,\n include_headers: bool = True,\n include_sensitive_headers: bool = False\n ):\n \"\"\"Initialize the logging interceptor.\n\n Args:\n enabled: Whether logging is enabled\n logger: Custom logger instance (creates default if None)\n log_level: Logging level to use\n include_headers: Whether to log request/response headers\n include_sensitive_headers: Whether to log sensitive headers like Authorization\n \"\"\"\n self.enabled = enabled\n self.logger = logger or logging.getLogger(__name__)\n self.log_level = log_level\n self.include_headers = include_headers\n self.include_sensitive_headers = include_sensitive_headers\n self._sensitive_headers = {'authorization', 'x-api-key', 'cookie', 'set-cookie'}\n\n async def process_request(self, config: RequestConfig) -> RequestConfig:\n \"\"\"Log outgoing request.\n\n Args:\n config: The request configuration\n\n Returns:\n The unmodified request configuration\n \"\"\"\n if not self.enabled:\n return config\n\n self.logger.log(self.log_level, f\"\u2192 {config.method.upper()} {config.url}\")\n\n if self.include_headers and config.headers:\n for key, value in config.headers.items():\n if (key.lower() in self._sensitive_headers and\n not self.include_sensitive_headers):\n self.logger.log(self.log_level, f\" {key}: [REDACTED]\")\n else:\n self.logger.log(self.log_level, f\" {key}: {value}\")\n\n return config\n\n async def process_response(self, response: httpx.Response) -> httpx.Response:\n \"\"\"Log incoming response.\n\n Args:\n response: The HTTP response\n\n Returns:\n The unmodified response\n \"\"\"\n if not self.enabled:\n return response\n\n status_icon = \"\u2713\" if 200 <= response.status_code < 300 else \"\u2717\"\n self.logger.log(\n self.log_level,\n f\"\u2190 {status_icon} {response.status_code} {response.reason_phrase or ''}\"\n )\n\n if self.include_headers and response.headers:\n for key, value in response.headers.items():\n if (key.lower() in self._sensitive_headers and\n not self.include_sensitive_headers):\n self.logger.log(self.log_level, f\" {key}: [REDACTED]\")\n else:\n self.logger.log(self.log_level, f\" {key}: {value}\")\n\n return response\n\n\nclass AuthInterceptor(Interceptor):\n \"\"\"Interceptor that adds authentication headers.\"\"\"\n\n def __init__(\n self,\n token: Optional[str] = None,\n api_key: Optional[str] = None,\n api_key_header: str = 'X-API-Key',\n auth_type: str = 'Bearer'\n ):\n \"\"\"Initialize the authentication interceptor.\n\n Args:\n token: Bearer token for Authorization header\n api_key: API key value\n api_key_header: Header name for API key\n auth_type: Type of authentication (Bearer, Basic, etc.)\n \"\"\"\n self.token = token\n self.api_key = api_key\n self.api_key_header = api_key_header\n self.auth_type = auth_type\n\n async def process_request(self, config: RequestConfig) -> RequestConfig:\n \"\"\"Add authentication headers.\n\n Args:\n config: The request configuration\n\n Returns:\n The modified request configuration with auth headers\n \"\"\"\n if config.headers is None:\n config.headers = {}\n\n if self.token:\n config.headers['Authorization'] = f'{self.auth_type} {self.token}'\n elif self.api_key:\n config.headers[self.api_key_header] = self.api_key\n\n return config\n\n async def process_response(self, response: httpx.Response) -> httpx.Response:\n \"\"\"Pass through response unchanged.\n\n Args:\n response: The HTTP response\n\n Returns:\n The unmodified response\n \"\"\"\n return response\n\n\nclass RetryInterceptor(Interceptor):\n \"\"\"Interceptor that retries failed requests with exponential backoff.\"\"\"\n\n def __init__(\n self,\n max_retries: int = 3,\n retry_delay: float = 1.0,\n backoff_factor: float = 2.0,\n retry_on_status: Optional[List[int]] = None,\n retry_on_exceptions: Optional[List[type]] = None\n ):\n \"\"\"Initialize the retry interceptor.\n\n Args:\n max_retries: Maximum number of retry attempts\n retry_delay: Initial delay between retries in seconds\n backoff_factor: Exponential backoff multiplier\n retry_on_status: HTTP status codes that should trigger retries\n retry_on_exceptions: Exception types that should trigger retries\n \"\"\"\n self.max_retries = max_retries\n self.retry_delay = retry_delay\n self.backoff_factor = backoff_factor\n self.retry_on_status = retry_on_status or [500, 502, 503, 504, 408, 429]\n self.retry_on_exceptions = retry_on_exceptions or [\n httpx.TimeoutException,\n httpx.ConnectError,\n httpx.RemoteProtocolError\n ]\n self._original_request_func = None\n self.logger = logging.getLogger(__name__)\n\n async def process_request(self, config: RequestConfig) -> RequestConfig:\n \"\"\"Store original request for potential retries.\n\n Args:\n config: The request configuration\n\n Returns:\n The unmodified request configuration\n \"\"\"\n # Store the original config for retries\n self._original_config = config.model_copy() if hasattr(config, 'model_copy') else config\n return config\n\n async def process_response(self, response: httpx.Response) -> httpx.Response:\n \"\"\"Check if response needs retry and handle accordingly.\n\n Args:\n response: The HTTP response\n\n Returns:\n The response (possibly after retries)\n \"\"\"\n # For retry logic to work properly, it needs to be integrated at the dispatcher level\n # This is a simplified version that just passes through\n # In a full implementation, the retry logic would need access to the original request method\n return response\n\n async def execute_with_retry(self, request_func, *args, **kwargs) -> httpx.Response:\n \"\"\"Execute a request function with retry logic.\n\n Args:\n request_func: Function that executes the HTTP request\n *args: Arguments to pass to request_func\n **kwargs: Keyword arguments to pass to request_func\n\n Returns:\n The HTTP response after potential retries\n\n Raises:\n The last exception encountered if all retries fail\n \"\"\"\n last_exception = None\n\n for attempt in range(self.max_retries + 1):\n try:\n response = await request_func(*args, **kwargs)\n\n # Check if response status requires retry\n if response.status_code not in self.retry_on_status:\n return response\n\n if attempt == self.max_retries:\n self.logger.warning(\n f\"Max retries ({self.max_retries}) reached for request. \"\n f\"Final status: {response.status_code}\"\n )\n return response\n\n # Wait before retry\n delay = self.retry_delay * (self.backoff_factor ** attempt)\n self.logger.info(\n f\"Retrying request (attempt {attempt + 1}/{self.max_retries + 1}) \"\n f\"after {delay:.2f}s due to status {response.status_code}\"\n )\n await asyncio.sleep(delay)\n\n except Exception as e:\n # Check if exception type requires retry\n if not any(isinstance(e, exc_type) for exc_type in self.retry_on_exceptions):\n raise e\n\n last_exception = e\n\n if attempt == self.max_retries:\n self.logger.error(\n f\"Max retries ({self.max_retries}) reached. \"\n f\"Final exception: {type(e).__name__}: {e}\"\n )\n raise e\n\n # Wait before retry\n delay = self.retry_delay * (self.backoff_factor ** attempt)\n self.logger.info(\n f\"Retrying request (attempt {attempt + 1}/{self.max_retries + 1}) \"\n f\"after {delay:.2f}s due to {type(e).__name__}: {e}\"\n )\n await asyncio.sleep(delay)\n\n\nclass UserAgentInterceptor(Interceptor):\n \"\"\"Interceptor that adds a User-Agent header.\"\"\"\n\n def __init__(self, user_agent: str):\n \"\"\"Initialize the User-Agent interceptor.\n\n Args:\n user_agent: The User-Agent string to set\n \"\"\"\n self.user_agent = user_agent\n\n async def process_request(self, config: RequestConfig) -> RequestConfig:\n \"\"\"Add User-Agent header if not already present.\n\n Args:\n config: The request configuration\n\n Returns:\n The modified request configuration with User-Agent header\n \"\"\"\n if config.headers is None:\n config.headers = {}\n\n # Only set User-Agent if not already present (case-insensitive check)\n has_user_agent = any(\n key.lower() == 'user-agent'\n for key in config.headers.keys()\n )\n\n if not has_user_agent:\n config.headers['User-Agent'] = self.user_agent\n\n return config\n\n async def process_response(self, response: httpx.Response) -> httpx.Response:\n \"\"\"Pass through response unchanged.\n\n Args:\n response: The HTTP response\n\n Returns:\n The unmodified response\n \"\"\"\n return response\n\n\nclass TimeoutInterceptor(Interceptor):\n \"\"\"Interceptor that sets request timeouts.\"\"\"\n\n def __init__(self, timeout: Union[float, httpx.Timeout]):\n \"\"\"Initialize the timeout interceptor.\n\n Args:\n timeout: Timeout value in seconds or httpx.Timeout object\n \"\"\"\n self.timeout = timeout\n\n async def process_request(self, config: RequestConfig) -> RequestConfig:\n \"\"\"Set timeout for the request.\n\n Args:\n config: The request configuration\n\n Returns:\n The modified request configuration with timeout\n \"\"\"\n if config.timeout is None:\n config.timeout = self.timeout\n return config\n\n async def process_response(self, response: httpx.Response) -> httpx.Response:\n \"\"\"Pass through response unchanged.\n\n Args:\n response: The HTTP response\n\n Returns:\n The unmodified response\n \"\"\"\n return response\n\n\nclass RateLimitInterceptor(Interceptor):\n \"\"\"Interceptor that implements client-side rate limiting.\"\"\"\n\n def __init__(self, max_requests: int, time_window: float = 60.0):\n \"\"\"Initialize the rate limit interceptor.\n\n Args:\n max_requests: Maximum number of requests allowed in the time window\n time_window: Time window in seconds\n \"\"\"\n self.max_requests = max_requests\n self.time_window = time_window\n self.requests = []\n self._lock = asyncio.Lock()\n\n async def process_request(self, config: RequestConfig) -> RequestConfig:\n \"\"\"Apply rate limiting before request.\n\n Args:\n config: The request configuration\n\n Returns:\n The unmodified request configuration\n \"\"\"\n async with self._lock:\n now = time.time()\n\n # Remove requests outside the time window\n self.requests = [req_time for req_time in self.requests\n if now - req_time < self.time_window]\n\n # Check if we've exceeded the rate limit\n if len(self.requests) >= self.max_requests:\n # Calculate how long to wait\n oldest_request = min(self.requests)\n wait_time = self.time_window - (now - oldest_request)\n\n if wait_time > 0:\n await asyncio.sleep(wait_time)\n\n # Record this request\n self.requests.append(now)\n\n return config\n\n async def process_response(self, response: httpx.Response) -> httpx.Response:\n \"\"\"Pass through response unchanged.\n\n Args:\n response: The HTTP response\n\n Returns:\n The unmodified response\n \"\"\"\n return response\n\n\n# Factory functions for convenient interceptor creation\ndef create_base_url_interceptor(base_url: str) -> BaseUrlInterceptor:\n \"\"\"Create a BaseUrlInterceptor instance.\n\n Args:\n base_url: The base URL to prepend to relative URLs\n\n Returns:\n Configured BaseUrlInterceptor instance\n \"\"\"\n return BaseUrlInterceptor(base_url)\n\n\ndef create_logging_interceptor(\n enabled: bool = True,\n log_level: int = logging.INFO,\n include_headers: bool = True,\n include_sensitive_headers: bool = False\n) -> LoggingInterceptor:\n \"\"\"Create a LoggingInterceptor instance.\n\n Args:\n enabled: Whether logging is enabled\n log_level: Logging level to use\n include_headers: Whether to log headers\n include_sensitive_headers: Whether to log sensitive headers\n\n Returns:\n Configured LoggingInterceptor instance\n \"\"\"\n return LoggingInterceptor(\n enabled=enabled,\n log_level=log_level,\n include_headers=include_headers,\n include_sensitive_headers=include_sensitive_headers\n )\n\n\ndef create_auth_interceptor(\n token: Optional[str] = None,\n api_key: Optional[str] = None,\n api_key_header: str = 'X-API-Key',\n auth_type: str = 'Bearer'\n) -> AuthInterceptor:\n \"\"\"Create an AuthInterceptor instance.\n\n Args:\n token: Bearer token for Authorization header\n api_key: API key value\n api_key_header: Header name for API key\n auth_type: Type of authentication\n\n Returns:\n Configured AuthInterceptor instance\n \"\"\"\n return AuthInterceptor(\n token=token,\n api_key=api_key,\n api_key_header=api_key_header,\n auth_type=auth_type\n )\n\n\ndef create_retry_interceptor(\n max_retries: int = 3,\n retry_delay: float = 1.0,\n backoff_factor: float = 2.0,\n retry_on_status: Optional[List[int]] = None\n) -> RetryInterceptor:\n \"\"\"Create a RetryInterceptor instance.\n\n Args:\n max_retries: Maximum number of retry attempts\n retry_delay: Initial delay between retries in seconds\n backoff_factor: Exponential backoff multiplier\n retry_on_status: HTTP status codes that should trigger retries\n\n Returns:\n Configured RetryInterceptor instance\n \"\"\"\n return RetryInterceptor(\n max_retries=max_retries,\n retry_delay=retry_delay,\n backoff_factor=backoff_factor,\n retry_on_status=retry_on_status\n )\n\n\ndef create_user_agent_interceptor(user_agent: str) -> UserAgentInterceptor:\n \"\"\"Create a UserAgentInterceptor instance.\n\n Args:\n user_agent: The User-Agent string to set\n\n Returns:\n Configured UserAgentInterceptor instance\n \"\"\"\n return UserAgentInterceptor(user_agent)\n", "\"\"\"HTTP response models and exceptions.\"\"\"\n\nfrom typing import Any, Dict, Optional, Union\n\nimport httpx\nfrom pydantic import BaseModel\n\n\nclass ApiResponse(BaseModel):\n \"\"\"Base class for API responses.\"\"\"\n\n status_code: int\n headers: Dict[str, str]\n data: Any\n\n class Config:\n \"\"\"Pydantic configuration.\"\"\"\n arbitrary_types_allowed = True\n\n\nclass SuccessResponse(ApiResponse):\n \"\"\"Represents a successful API response.\"\"\"\n\n def __init__(self, data: Any, status_code: int = 200, headers: Optional[Dict[str, str]] = None):\n \"\"\"Initialize success response.\n\n Args:\n data: Response data\n status_code: HTTP status code\n headers: Response headers\n \"\"\"\n super().__init__(\n status_code=status_code,\n headers=headers or {},\n data=data\n )\n\n\nclass ErrorResponse(Exception):\n \"\"\"Exception raised for HTTP error responses.\"\"\"\n\n def __init__(\n self,\n data: Any,\n status_code: int,\n headers: Optional[Dict[str, str]] = None,\n message: Optional[str] = None\n ):\n \"\"\"Initialize error response.\n\n Args:\n data: Error response data\n status_code: HTTP status code\n headers: Response headers\n message: Custom error message\n \"\"\"\n self.data = data\n self.status_code = status_code\n self.headers = headers or {}\n self.message = message or f\"HTTP {status_code} Error\"\n\n super().__init__(self.message)\n\n def __str__(self) -> str:\n \"\"\"String representation of the error.\"\"\"\n return f\"ErrorResponse(status_code={self.status_code}, message='{self.message}')\"\n\n def __repr__(self) -> str:\n \"\"\"Detailed string representation of the error.\"\"\"\n return (\n f\"ErrorResponse(status_code={self.status_code}, \"\n f\"message='{self.message}', data={self.data})\"\n )\n\n\nclass TimeoutError(ErrorResponse):\n \"\"\"Exception raised for request timeouts.\"\"\"\n\n def __init__(self, message: str = \"Request timed out\"):\n \"\"\"Initialize timeout error.\n\n Args:\n message: Error message\n \"\"\"\n super().__init__(\n data={'error': 'timeout'},\n status_code=408,\n message=message\n )\n\n\nclass ConnectionError(ErrorResponse):\n \"\"\"Exception raised for connection errors.\"\"\"\n\n def __init__(self, message: str = \"Connection failed\"):\n \"\"\"Initialize connection error.\n\n Args:\n message: Error message\n \"\"\"\n super().__init__(\n data={'error': 'connection'},\n status_code=503,\n message=message\n )\n\n\nclass BadRequestError(ErrorResponse):\n \"\"\"Exception raised for 400 Bad Request errors.\"\"\"\n\n def __init__(self, data: Any = None, message: str = \"Bad Request\"):\n \"\"\"Initialize bad request error.\n\n Args:\n data: Error data\n message: Error message\n \"\"\"\n super().__init__(\n data=data or {'error': 'bad_request'},\n status_code=400,\n message=message\n )\n\n\nclass UnauthorizedError(ErrorResponse):\n \"\"\"Exception raised for 401 Unauthorized errors.\"\"\"\n\n def __init__(self, data: Any = None, message: str = \"Unauthorized\"):\n \"\"\"Initialize unauthorized error.\n\n Args:\n data: Error data\n message: Error message\n \"\"\"\n super().__init__(\n data=data or {'error': 'unauthorized'},\n status_code=401,\n message=message\n )\n\n\nclass ForbiddenError(ErrorResponse):\n \"\"\"Exception raised for 403 Forbidden errors.\"\"\"\n\n def __init__(self, data: Any = None, message: str = \"Forbidden\"):\n \"\"\"Initialize forbidden error.\n\n Args:\n data: Error data\n message: Error message\n \"\"\"\n super().__init__(\n data=data or {'error': 'forbidden'},\n status_code=403,\n message=message\n )\n\n\nclass NotFoundError(ErrorResponse):\n \"\"\"Exception raised for 404 Not Found errors.\"\"\"\n\n def __init__(self, data: Any = None, message: str = \"Not Found\"):\n \"\"\"Initialize not found error.\n\n Args:\n data: Error data\n message: Error message\n \"\"\"\n super().__init__(\n data=data or {'error': 'not_found'},\n status_code=404,\n message=message\n )\n\n\nclass InternalServerError(ErrorResponse):\n \"\"\"Exception raised for 500 Internal Server Error.\"\"\"\n\n def __init__(self, data: Any = None, message: str = \"Internal Server Error\"):\n \"\"\"Initialize internal server error.\n\n Args:\n data: Error data\n message: Error message\n \"\"\"\n super().__init__(\n data=data or {'error': 'internal_server_error'},\n status_code=500,\n message=message\n )\n\n\ndef create_error_from_response(response: httpx.Response) -> ErrorResponse:\n \"\"\"Create appropriate error exception from HTTP response.\n\n Args:\n response: HTTP response\n\n Returns:\n Appropriate error exception\n \"\"\"\n status_code = response.status_code\n headers = dict(response.headers)\n\n # Try to parse error data\n try:\n data = response.json()\n except Exception:\n data = {'message': response.text}\n\n # Create specific error types based on status code\n error_classes = {\n 400: BadRequestError,\n 401: UnauthorizedError,\n 403: ForbiddenError,\n 404: NotFoundError,\n 500: InternalServerError,\n }\n\n error_class = error_classes.get(status_code, ErrorResponse)\n\n if error_class == ErrorResponse:\n return ErrorResponse(data, status_code, headers)\n else:\n return error_class(data)\n", "import type { ReferenceObject, SchemaObject } from 'openapi3-ts/oas31';\nimport { snakecase } from 'stringcase';\n\nimport { isRef, notRef, parseRef, pascalcase } from '@sdk-it/core';\nimport { type IR, isPrimitiveSchema } from '@sdk-it/spec';\n\nexport function coerceObject(schema: SchemaObject): SchemaObject {\n schema = structuredClone(schema);\n if (schema['x-properties']) {\n schema.properties = {\n ...(schema.properties ?? {}),\n ...(schema['x-properties'] ?? {}),\n };\n }\n if (schema['x-required']) {\n schema.required = Array.from(\n new Set([\n ...(Array.isArray(schema.required) ? schema.required : []),\n ...(schema['x-required'] || []),\n ]),\n );\n }\n return schema;\n}\n\ntype Context = Record<string, unknown>;\ntype Serialized = {\n nullable?: boolean;\n encode?: string;\n encodeV2?: string;\n use: string;\n matches?: string;\n fromJson: unknown;\n type?: string;\n literal?: unknown;\n content: string;\n simple?: boolean;\n};\ntype Emit = (name: string, content: string, schema: SchemaObject) => void;\n\n/**\n * Convert an OpenAPI (JSON Schema style) object into Python classes with Pydantic\n */\nexport class PythonEmitter {\n #spec: IR;\n #emitHandler?: Emit;\n #emitHistory = new Set<string>();\n #typeCache = new Map<string, Serialized>(); // Cache for resolved types\n\n #emit(name: string, content: string, schema: SchemaObject): void {\n if (this.#emitHistory.has(content)) {\n return;\n }\n this.#emitHistory.add(content);\n this.#emitHandler?.(name, content, schema);\n }\n\n constructor(spec: IR) {\n this.#spec = spec;\n }\n\n onEmit(emit: Emit): void {\n this.#emitHandler = emit;\n }\n\n #formatFieldName(name: string): string {\n // Convert to snake_case and handle special cases\n let fieldName = snakecase(name);\n\n // Handle reserved keywords\n const reservedKeywords = [\n 'class',\n 'def',\n 'if',\n 'else',\n 'elif',\n 'while',\n 'for',\n 'try',\n 'except',\n 'finally',\n 'with',\n 'as',\n 'import',\n 'from',\n 'global',\n 'nonlocal',\n 'lambda',\n 'yield',\n 'return',\n 'pass',\n 'break',\n 'continue',\n 'True',\n 'False',\n 'None',\n 'and',\n 'or',\n 'not',\n 'in',\n 'is',\n ];\n\n if (reservedKeywords.includes(fieldName)) {\n fieldName = `${fieldName}_`;\n }\n\n return fieldName;\n }\n\n #ref(ref: ReferenceObject): Serialized {\n const cacheKey = ref.$ref;\n const cached = this.#typeCache.get(cacheKey);\n if (cached) {\n return cached;\n }\n\n const refInfo = parseRef(ref.$ref);\n const refName = refInfo.model;\n const className = pascalcase(refName);\n\n const result: Serialized = {\n type: className,\n content: '',\n use: className,\n fromJson: `${className}.parse_obj`,\n simple: false,\n };\n\n this.#typeCache.set(cacheKey, result);\n return result;\n }\n\n #oneOf(\n variants: (SchemaObject | ReferenceObject)[],\n context: Context,\n ): Serialized {\n const variantTypes = variants\n .map((variant) => this.handle(variant, context))\n .map((result) => result.type || 'Any')\n .filter((type, index, arr) => arr.indexOf(type) === index); // Remove duplicates\n\n if (variantTypes.length === 0) {\n return {\n type: 'Any',\n content: '',\n use: 'Any',\n fromJson: 'Any',\n simple: true,\n };\n }\n\n if (variantTypes.length === 1) {\n return {\n type: variantTypes[0],\n content: '',\n use: variantTypes[0],\n fromJson: variantTypes[0],\n simple: true,\n };\n }\n\n const unionType = `Union[${variantTypes.join(', ')}]`;\n return {\n type: unionType,\n content: '',\n use: unionType,\n fromJson: unionType,\n simple: true,\n };\n }\n\n #object(\n className: string,\n schema: SchemaObject,\n context: Context,\n ): Serialized {\n const { properties = {}, required = [] } = coerceObject(schema);\n\n const fields: string[] = [];\n\n // Handle allOf inheritance\n let baseClass = 'BaseModel';\n if (schema.allOf) {\n const bases = schema.allOf\n .filter(notRef)\n .map((s) => this.handle(s, context))\n .filter((result) => result.type)\n .map((result) => result.type);\n\n if (bases.length > 0 && bases[0]) {\n baseClass = bases[0];\n }\n }\n\n // Process properties\n for (const [propName, propSchema] of Object.entries(properties)) {\n if (isRef(propSchema)) {\n this.#ref(propSchema);\n const refInfo = parseRef(propSchema.$ref);\n const refName = refInfo.model;\n const pythonType = pascalcase(refName);\n\n const fieldName = this.#formatFieldName(propName);\n const isRequired = required.includes(propName);\n const fieldType = isRequired ? pythonType : `Optional[${pythonType}]`;\n const defaultValue = isRequired ? '' : ' = None';\n\n fields.push(` ${fieldName}: ${fieldType}${defaultValue}`);\n } else {\n const result = this.handle(propSchema, { ...context, name: propName });\n const fieldName = this.#formatFieldName(propName);\n const isRequired = required.includes(propName);\n\n let fieldType = result.type || 'Any';\n if (!isRequired) {\n fieldType = `Optional[${fieldType}]`;\n }\n\n const defaultValue = isRequired ? '' : ' = None';\n let fieldDef = ` ${fieldName}: ${fieldType}${defaultValue}`;\n\n // Add Field() for alias or validation if needed\n if (fieldName !== propName) {\n fieldDef = ` ${fieldName}: ${fieldType} = Field(alias='${propName}'${defaultValue ? ', default=None' : ''})`;\n }\n\n // Add description as comment if available\n if (propSchema.description) {\n fieldDef += ` # ${propSchema.description}`;\n }\n\n fields.push(fieldDef);\n }\n }\n\n // Handle oneOf/anyOf as Union types using centralized logic\n if (schema.oneOf || schema.anyOf) {\n const unionResult = this.#oneOf(\n schema.oneOf || schema.anyOf || [],\n context,\n );\n fields.push(` value: ${unionResult.type}`);\n }\n\n // Handle additionalProperties\n if (\n schema.additionalProperties &&\n typeof schema.additionalProperties === 'object'\n ) {\n const addlResult = this.handle(schema.additionalProperties, context);\n fields.push(\n ` additional_properties: Optional[Dict[str, ${addlResult.type || 'Any'}]] = None`,\n );\n }\n\n // Generate class docstring\n const docstring = schema.description\n ? ` \"\"\"${schema.description}\"\"\"\\n`\n : '';\n\n // Generate to_request_config method for input models\n let requestConfigMethod = '';\n if (schema['x-inputname']) {\n requestConfigMethod = `\n def to_request_config(self, config: RequestConfig) -> RequestConfig:\n \"\"\"Convert this input model to request configuration.\"\"\"\n # Handle path parameters\n path_params = {}\n for key, value in self.dict(exclude_none=True).items():\n if key in config.url:\n path_params[key] = str(value)\n config.url = config.url.replace(f'{{{key}}}', str(value))\n\n # Handle query parameters\n query_params = {k: v for k, v in self.dict(exclude_none=True).items()\n if k not in path_params}\n if query_params:\n config.params = query_params\n\n return config\n`;\n }\n\n const content = `class ${className}(${baseClass}):\n${docstring}${fields.length > 0 ? fields.join('\\n') : ' pass'}${requestConfigMethod}\n`;\n\n this.#emit(className, content, schema);\n\n return {\n type: className,\n content,\n use: className,\n fromJson: `${className}.parse_obj`,\n simple: false,\n };\n }\n\n #primitive(schema: SchemaObject): Serialized {\n const { type, format } = schema;\n const nullable = (schema as { nullable?: boolean }).nullable; // Handle nullable as it may not be in the type definition\n\n let pythonType = 'Any';\n\n switch (type) {\n case 'string':\n if (format === 'date-time') {\n pythonType = 'datetime';\n } else if (format === 'date') {\n pythonType = 'date';\n } else if (format === 'uuid') {\n pythonType = 'UUID';\n } else if (format === 'binary' || format === 'byte') {\n pythonType = 'bytes';\n } else {\n pythonType = 'str';\n }\n break;\n\n case 'integer':\n if (format === 'int64') {\n pythonType = 'int'; // Python 3 ints are arbitrary precision\n } else {\n pythonType = 'int';\n }\n break;\n\n case 'number':\n pythonType = 'float';\n break;\n\n case 'boolean':\n pythonType = 'bool';\n break;\n\n default:\n pythonType = 'Any';\n }\n\n if (nullable) {\n pythonType = `Optional[${pythonType}]`;\n }\n\n return {\n type: pythonType,\n content: '',\n use: pythonType,\n fromJson: pythonType,\n simple: true,\n nullable,\n };\n }\n\n #array(schema: SchemaObject, context: Context): Serialized {\n const itemsSchema = schema.items;\n if (!itemsSchema) {\n return {\n type: 'List[Any]',\n content: '',\n use: 'List[Any]',\n fromJson: 'list',\n simple: true,\n };\n }\n\n const itemsResult = this.handle(itemsSchema, context);\n const listType = `List[${itemsResult.type || 'Any'}]`;\n\n return {\n type: listType,\n content: itemsResult.content,\n use: listType,\n fromJson: `List[${itemsResult.fromJson || itemsResult.type}]`,\n simple: true,\n };\n }\n\n #enum(schema: SchemaObject, _context: Context): Serialized {\n const { enum: enumValues } = schema;\n if (!enumValues || enumValues.length === 0) {\n return this.#primitive(schema);\n }\n\n if (!_context.name || typeof _context.name !== 'string') {\n throw new Error('Enum schemas must have a name in context');\n }\n\n const className = pascalcase(_context.name as string);\n\n const enumItems = enumValues.map((value, index) => {\n const name =\n typeof value === 'string'\n ? value.toUpperCase().replace(/[^A-Z0-9]/g, '_')\n : `VALUE_${index}`;\n\n const pythonValue =\n typeof value === 'string' ? `'${value}'` : String(value);\n return ` ${name} = ${pythonValue}`;\n });\n\n const content = `class ${className}(Enum):\n \"\"\"Enumeration for ${_context.name}.\"\"\"\n${enumItems.join('\\n')}\n`;\n\n this.#emit(className, content, schema);\n\n return {\n type: className,\n content,\n use: className,\n fromJson: className,\n simple: false,\n };\n }\n\n #const(schema: SchemaObject): Serialized {\n const { const: constValue } = schema;\n\n if (typeof constValue === 'string') {\n return {\n type: `Literal['${constValue}']`,\n content: '',\n use: `Literal['${constValue}']`,\n fromJson: `'${constValue}'`,\n simple: true,\n literal: constValue,\n };\n }\n\n return {\n type: `Literal[${JSON.stringify(constValue)}]`,\n content: '',\n use: `Literal[${JSON.stringify(constValue)}]`,\n fromJson: JSON.stringify(constValue),\n simple: true,\n literal: constValue,\n };\n }\n handle(\n schema: SchemaObject | ReferenceObject,\n context: Context = {},\n ): Serialized {\n if (isRef(schema)) {\n return this.#ref(schema);\n }\n\n // Handle const values\n if ('const' in schema && schema.const !== undefined) {\n return this.#const(schema);\n }\n\n // Handle enums\n if (schema.enum) {\n return this.#enum(schema, context);\n }\n\n // Handle arrays\n if (schema.type === 'array') {\n return this.#array(schema, context);\n }\n\n // Handle oneOf/anyOf at top level using centralized logic\n if (schema.oneOf || schema.anyOf) {\n return this.#oneOf(schema.oneOf || schema.anyOf || [], context);\n }\n\n // Handle objects\n if (\n schema.type === 'object' ||\n schema.properties ||\n schema.allOf ||\n schema.oneOf ||\n schema.anyOf\n ) {\n if (!context.name || typeof context.name !== 'string') {\n throw new Error('Object schemas must have a name in context');\n }\n const className = pascalcase(context.name as string);\n return this.#object(className, schema, context);\n }\n\n // Handle primitives\n if (isPrimitiveSchema(schema)) {\n return this.#primitive(schema);\n }\n\n // Fallback to Any\n return {\n type: 'Any',\n content: '',\n use: 'Any',\n fromJson: 'Any',\n simple: true,\n };\n }\n}\n", "import { Command } from 'commander';\nimport { writeFile } from 'node:fs/promises';\n\nimport { toReadme } from '@sdk-it/readme';\nimport { loadSpec, toIR } from '@sdk-it/spec';\n\nimport { outputOption, specOption } from '../options.ts';\n\nexport default new Command('readme')\n .description('Generate README')\n .addOption(specOption.makeOptionMandatory(true))\n .addOption(outputOption.makeOptionMandatory(true))\n .action(async (options: { spec: string; output: string }) => {\n await runReadme(options.spec, options.output);\n });\n\nexport async function runReadme(specFile: string, output: string) {\n const spec = await toIR({ spec: await loadSpec(specFile) });\n const content = toReadme(spec);\n await writeFile(output, content, 'utf-8');\n}\n", "import { Command, Option } from 'commander';\nimport { publish } from 'libnpmpublish';\nimport { execFile, execSync, spawnSync } from 'node:child_process';\nimport { readFile } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport type { OpenAPIObject } from 'openapi3-ts/oas31';\nimport getAuthToken from 'registry-auth-token';\n\nimport { writeFiles } from '@sdk-it/core/file-system.js';\nimport { loadSpec } from '@sdk-it/spec';\nimport { generate } from '@sdk-it/typescript';\n\nimport {\n outputOption,\n parseDotConfig,\n parsePagination,\n specOption,\n} from '../options.ts';\nimport type { TypeScriptOptions } from '../types.ts';\n\ntype Options = Omit<TypeScriptOptions, 'pagination'> & {\n output: string;\n pagination?: TypeScriptOptions['pagination'] | string;\n};\n\nexport default new Command('typescript')\n .alias('ts')\n .description('Generate TypeScript SDK')\n .addOption(specOption.makeOptionMandatory(true))\n .addOption(outputOption.makeOptionMandatory(false))\n .option(\n '--useTsExtension [value]',\n 'Use .ts extension for generated files',\n (value) => (value === 'false' ? false : true),\n true,\n )\n .option(\n '-m, --mode <mode>',\n 'full: generate a full project including package.json and tsconfig.json. useful for monorepo/workspaces minimal: generate only the client sdk',\n )\n .option('-n, --name <name>', 'Name of the generated client', 'Client')\n .option(\n '-f, --framework <framework>',\n 'Framework that is integrating with the SDK',\n )\n .option('--formatter <formatter>', 'Formatter to use for the generated code')\n .option(\n '--install',\n 'Install dependencies using npm (only in full mode)',\n true,\n )\n .option(\n '--readme <readme>',\n 'Generate a README file',\n (value) => (value === 'false' ? false : true),\n true,\n )\n .option('--no-default-formatter', 'Do not use the default formatter')\n .option('--no-install', 'Do not install dependencies')\n .option('-v, --verbose', 'Verbose output', false)\n .option(\n '--pagination <pagination>',\n 'Configure pagination (e.g., \"false\", \"true\", \"guess=false\")',\n 'true',\n )\n .addOption(\n new Option(\n '--publish <publish>',\n 'Publish the SDK to a package registry (npm, github, or a custom registry)',\n )\n .hideHelp(true)\n .makeOptionMandatory(false),\n )\n .action(async (options: Options) => {\n await runTypescript(options);\n });\n\nexport async function runTypescript(options: Options) {\n if (!options.publish && !options.output) {\n throw new Error('Error: --publish or --output option is required.');\n }\n const spec = await loadSpec(options.spec);\n\n if (options.output) {\n await emitLocal(spec, {\n ...options,\n output: options.output,\n });\n }\n if (options.publish) {\n await emitRemote(spec, {\n ...options,\n publish: options.publish,\n });\n }\n}\n\nasync function emitLocal(spec: OpenAPIObject, options: Options) {\n await generate(spec, {\n writer: writeFiles,\n output: options.output,\n mode: options.mode || 'minimal',\n name: options.name,\n pagination:\n typeof options.pagination === 'string'\n ? parsePagination(parseDotConfig(options.pagination ?? 'true'))\n : options.pagination,\n style: {\n name: 'github',\n },\n readme: options.readme,\n useTsExtension: options.useTsExtension,\n formatCode: ({ env, output }) => {\n if (options.formatter) {\n const [command, ...args] = options.formatter.split(' ');\n execFile(command, args, {\n env: { ...env, SDK_IT_OUTPUT: output },\n });\n } else if (options.defaultFormatter) {\n spawnSync('npx', ['-y', 'prettier', output, '--write'], {\n env: {\n ...env,\n SDK_IT_OUTPUT: output,\n },\n stdio: options.verbose ? 'inherit' : 'pipe',\n });\n }\n },\n });\n\n // Install dependencies if in full mode and install option is enabled\n if (options.install && options.mode === 'full') {\n console.log('Installing dependencies...');\n execSync('npm install', {\n cwd: options.output,\n stdio: options.verbose ? 'inherit' : 'pipe',\n });\n }\n}\n\nasync function emitRemote(\n spec: OpenAPIObject,\n options: Options & { publish: string },\n) {\n const registry =\n options.publish === 'npm'\n ? 'https://registry.npmjs.org/'\n : options.publish === 'github'\n ? 'https://npm.pkg.github.com/'\n : options.publish;\n\n console.log('Publishing to registry:', registry);\n const path = join(tmpdir(), crypto.randomUUID());\n await emitLocal(spec, {\n ...options,\n output: path,\n install: false,\n mode: 'full',\n });\n const manifest = JSON.parse(\n await readFile(join(path, 'package.json'), 'utf-8'),\n );\n const registryUrl = new URL(registry);\n const npmrc = process.env.NPM_TOKEN\n ? {\n npmrc: {\n registry,\n [`//${registryUrl.hostname}:_authToken`]: process.env.NPM_TOKEN,\n },\n }\n : registry;\n const auth = getAuthToken(npmrc);\n if (!auth || !auth.token) {\n throw new Error(\n 'No npm auth token found in .npmrc or environment. please provide NPM_TOKEN.',\n );\n }\n const packResult = execSync('npm pack --pack-destination .', { cwd: path });\n const [tgzName] = packResult.toString().trim().split('\\n');\n await publish(manifest, await readFile(join(path, tgzName)), {\n registry,\n defaultTag: 'latest',\n forceAuth: {\n token: auth.token,\n },\n strictSSL: true,\n preferOnline: true,\n });\n}\n"],
5
- "mappings": "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",
6
- "names": ["Command", "readJson", "writeFile", "resolve", "resolve", "program", "writeFile", "join", "createRequire", "ts", "require", "readFile", "join", "ts", "program", "writeFile", "join", "access", "readFile", "writeFile", "join", "relative", "resolve", "resolve", "join", "relative", "readOptionalFile", "readFile", "writeFile", "access", "resolve", "resolve", "resolve", "exist", "join", "resolve", "writeFile", "Command", "dirname", "join", "Command", "join", "dirname", "Command", "generate", "Command", "generate", "Command", "execFile", "execSync", "readdir", "join", "snakecase", "isRef", "pascalcase", "generate", "input", "loadSpec", "toIR", "Command", "toIR", "loadSpec", "generate", "execFile", "execSync", "Command", "writeFile", "loadSpec", "toIR", "Command", "toIR", "loadSpec", "writeFile", "Command", "Option", "execFile", "execSync", "readFile", "join", "writeFiles", "loadSpec", "generate", "Command", "Option", "loadSpec", "generate", "writeFiles", "execFile", "execSync", "join", "readFile", "generate", "Command", "config", "readJson"]
4
+ "sourcesContent": ["#!/usr/bin/env node\nimport { Command, program } from 'commander';\n\nimport { readJson } from '@sdk-it/core/file-system.js';\n\nimport init from './commands/init.ts';\nimport apiref from './generators/apiref.ts';\nimport dart, { runDart } from './generators/dart.ts';\nimport python, { runPython } from './generators/python.ts';\nimport readme, { runReadme } from './generators/readme.ts';\nimport typescript, { runTypescript } from './generators/typescript.ts';\nimport { generateProject, loadProjectConfig } from './project.ts';\nimport type { SdkConfig } from './types.ts';\n\ninterface Options {\n config?: string;\n}\n\nconst generate = new Command('generate')\n .option('-c, --config <path>', 'Path to an SDK-IT configuration file')\n .action(async (options: Options) => {\n if (!options.config || options.config.endsWith('.ts')) {\n try {\n const config = await loadProjectConfig({ config: options.config });\n await generateProject(config);\n console.log('Client generated successfully!');\n return;\n } catch (error) {\n if (\n options.config ||\n !(error instanceof Error) ||\n !error.message.startsWith('Could not find sdk-it.config.ts')\n ) {\n throw error;\n }\n }\n }\n\n options.config ??= 'sdk-it.json';\n const config = await readJson<SdkConfig>(options.config);\n\n const promises: Promise<unknown>[] = [];\n\n if (config.generators?.typescript) {\n promises.push(\n runTypescript({\n spec: config.generators.typescript.spec,\n output: config.generators.typescript.output,\n mode: config.generators.typescript.mode,\n name: config.generators.typescript.name,\n useTsExtension: config.generators.typescript.useTsExtension ?? true,\n install: config.generators.typescript.install ?? false,\n verbose: false,\n defaultFormatter:\n config.generators.typescript.defaultFormatter ?? true,\n readme: config.generators.typescript.readme ?? true,\n pagination: config.generators.typescript.pagination,\n }),\n );\n }\n\n if (config.generators?.python) {\n promises.push(\n runPython({\n spec: config.generators.python.spec,\n output: config.generators.python.output,\n mode: config.generators.python.mode,\n name: config.generators.python.name,\n verbose: false,\n }),\n );\n }\n\n if (config.generators?.dart) {\n promises.push(\n runDart({\n spec: config.generators.dart.spec,\n output: config.generators.dart.output,\n mode: config.generators.dart.mode,\n name: config.generators.dart.name,\n verbose: false,\n pagination: config.generators.dart.pagination,\n }),\n );\n }\n\n // if (config.apiref) {\n // promises.push(runApiRef(config.apiref.spec, config.apiref.output));\n // }\n\n if (config.readme) {\n promises.push(runReadme(config.readme.spec, config.readme.output));\n }\n\n await Promise.all(promises);\n console.log('All configured generators completed successfully!');\n })\n .addCommand(typescript)\n .addCommand(python)\n .addCommand(dart)\n .addCommand(apiref)\n .addCommand(readme);\n\nconst cli = program\n .description(`CLI tool to interact with SDK-IT.`)\n .addCommand(generate, { isDefault: true })\n .addCommand(init)\n .addCommand(\n new Command('_internal').action(() => {\n // do nothing\n }),\n { hidden: true },\n )\n .parse(process.argv);\n\nexport default cli;\n", "import { checkbox, confirm, input, select } from '@inquirer/prompts';\nimport { Command } from 'commander';\nimport { writeFile } from 'node:fs/promises';\nimport { resolve } from 'node:path';\n\nimport type { PaginationConfig } from '@sdk-it/spec';\n\nimport { initializeProject } from '../project.ts';\nimport type { SdkConfig, TypeScriptOptions } from '../types.ts';\nimport { detectMonorepo } from './find-framework.ts';\nimport { findSpecFile } from './find-spec-file.ts';\nimport { guessTypescriptPackageName } from './guess-default-package-name.ts';\n\nconst specInput = async (defaultValue?: string) => {\n return input({\n message: 'OpenAPI or Postman specification file path:',\n default: defaultValue || './openapi.json',\n });\n};\n\nconst generatorConfigs = {\n typescript: {\n name: async (isMultipleGenerators = false) => {\n const defaultName =\n await guessTypescriptPackageName(isMultipleGenerators);\n return input({\n message: 'SDK package name:',\n default: defaultName,\n });\n },\n spec: specInput,\n output: async () => {\n let defaultValue = './ts-sdk';\n const monorepo = await detectMonorepo();\n if (monorepo === 'nx') {\n defaultValue = './packages/ts-sdk';\n }\n return await input({\n message: 'Output directory:',\n default: defaultValue,\n });\n },\n mode: async () => {\n const options = {\n mode: 'full' as 'full' | 'minimal',\n install: false,\n };\n options.mode = await select({\n message: 'Generation mode:',\n choices: [\n {\n name: 'Full (generates package.json and tsconfig.json)',\n value: 'full',\n },\n {\n name: 'Minimal (generates only the client TypeScript files)',\n value: 'minimal',\n },\n ],\n default: options.mode,\n });\n if (options.mode === 'full') {\n const installDeps = await confirm({\n message: 'Install dependencies automatically?',\n default: true,\n });\n options.install = installDeps;\n }\n return options;\n },\n pagination: async () => {\n let pagination: PaginationConfig | false = {\n guess: false,\n };\n const result = await confirm({\n message: 'Enable pagination support?',\n default: false,\n });\n if (result) {\n pagination.guess = await confirm({\n message: 'Would you like to guess pagination parameters?',\n default: false,\n });\n } else {\n pagination = false;\n }\n return pagination;\n },\n readme: () =>\n confirm({\n message: 'Generate README file?',\n default: true,\n }),\n defaultFormatter: () =>\n confirm({\n message: 'Use default formatter (prettier)?',\n default: true,\n }),\n framework: () =>\n input({\n message: 'Framework integrating with the SDK (optional):',\n }),\n formatter: () =>\n input({\n message:\n 'Custom formatter command (optional, e.g., \"prettier $SDK_IT_OUTPUT --write\"):',\n }),\n },\n python: {\n name: () =>\n input({\n message: 'SDK package name:',\n default: 'my-python-sdk',\n }),\n spec: specInput,\n output: () =>\n input({\n message: 'Output directory:',\n default: './python-sdk',\n }),\n mode: async () => {\n const isMonorepo = await detectMonorepo();\n return select({\n message: 'Generation mode:',\n choices: [\n {\n name: 'Full (generates complete project structure)',\n value: 'full',\n },\n {\n name: 'Minimal (generates only the client files)',\n value: 'minimal',\n },\n ],\n default: isMonorepo ? 'full' : 'full', // Default to full, especially for monorepos\n }).then((value) => value as 'full' | 'minimal');\n },\n formatter: () =>\n input({\n message:\n 'Custom formatter command (optional, e.g., \"black $SDK_IT_OUTPUT\" or \"ruff format $SDK_IT_OUTPUT\"):',\n }),\n },\n dart: {\n name: () =>\n input({\n message: 'SDK package name:',\n default: 'my-dart-sdk',\n }),\n spec: specInput,\n output: () =>\n input({\n message: 'Output directory:',\n default: './dart-sdk',\n }),\n mode: async () => {\n const isMonorepo = await detectMonorepo();\n return select({\n message: 'Generation mode:',\n choices: [\n {\n name: 'Full (generates complete project structure)',\n value: 'full',\n },\n {\n name: 'Minimal (generates only the client files)',\n value: 'minimal',\n },\n ],\n default: isMonorepo ? 'full' : 'full', // Default to full, especially for monorepos\n }).then((value) => value as 'full' | 'minimal');\n },\n pagination: async () => {\n let pagination: PaginationConfig | false = {\n guess: false,\n };\n const result = await confirm({\n message: 'Enable pagination support?',\n default: false,\n });\n if (result) {\n pagination.guess = await confirm({\n message: 'Would you like to guess pagination parameters?',\n default: false,\n });\n } else {\n pagination = false;\n }\n return pagination;\n },\n },\n};\n\nconst init = new Command('init')\n .description('Initialize SDK-IT configuration interactively')\n .option('--project <tsconfig>', 'Initialize from a backend tsconfig')\n .action(async (options: { project?: string }) => {\n if (options.project) {\n await initializeProject({ tsconfig: options.project });\n console.log('SDK-IT project configuration initialized.');\n return;\n }\n\n console.log(\"Welcome to SDK-IT! Let's set up your configuration.\\n\");\n\n const possibleSpecFile = await findSpecFile();\n const monorepo = await detectMonorepo();\n\n if (possibleSpecFile) {\n console.log(`\uD83D\uDD0D Auto-detected API specification: ${possibleSpecFile}`);\n }\n if (monorepo) {\n console.log(`\uD83D\uDCE6 Detected monorepo setup`);\n }\n\n if (possibleSpecFile || monorepo) {\n console.log(''); // Add spacing\n }\n\n const config: SdkConfig = {\n generators: {},\n };\n\n // Ask which generators to configure\n const generators = await checkbox({\n message: 'Which SDK generators would you like to configure?',\n loop: false,\n instructions: false,\n required: true,\n\n choices: [\n { name: 'TypeScript', value: 'typescript' },\n { name: 'Python', value: 'python' },\n { name: 'Dart', value: 'dart' },\n ],\n });\n // Configure each selected generator\n for (const generator of generators) {\n console.log(`\\nConfiguring ${generator} generator:`);\n\n if (generator === 'typescript') {\n const tsConfig = generatorConfigs.typescript;\n const isMultipleGenerators = generators.length > 1;\n\n const generatorConfig: TypeScriptOptions = {\n spec: await tsConfig.spec(possibleSpecFile),\n output: await tsConfig.output(),\n name: await tsConfig.name(isMultipleGenerators),\n defaultFormatter: await tsConfig.defaultFormatter(),\n readme: await tsConfig.readme(),\n pagination: await tsConfig.pagination(),\n ...(await tsConfig.mode()),\n };\n\n const customFramework = await tsConfig.framework();\n if (customFramework) {\n generatorConfig.framework = customFramework;\n }\n\n const customFormatter = await tsConfig.formatter();\n if (customFormatter) {\n generatorConfig.formatter = customFormatter;\n }\n\n config.generators.typescript = generatorConfig;\n } else if (generator === 'python') {\n config.generators.python = {\n spec: await generatorConfigs.python.spec(),\n output: await generatorConfigs.python.output(),\n mode: await generatorConfigs.python.mode(),\n name: await generatorConfigs.python.name(),\n };\n } else if (generator === 'dart') {\n config.generators.dart = {\n spec: await generatorConfigs.dart.spec(),\n output: await generatorConfigs.dart.output(),\n mode: await generatorConfigs.dart.mode(),\n name: await generatorConfigs.dart.name(),\n pagination: await generatorConfigs.dart.pagination(),\n };\n }\n }\n\n // Ask about README generation\n const generateReadme = await confirm({\n message: '\\nGenerate README documentation?',\n default: true,\n });\n\n if (generateReadme) {\n const readmeSpec = await input({\n message: 'OpenAPI specification for README:',\n default:\n config.generators.typescript?.spec ||\n possibleSpecFile ||\n './openapi.yaml',\n });\n\n const readmeOutput = await input({\n message: 'README output file:',\n default: './README.md',\n });\n\n config.readme = {\n spec: readmeSpec,\n output: readmeOutput,\n };\n }\n\n // Ask about API reference generation\n const generateApiRef = await confirm({\n message: '\\nGenerate API reference documentation?',\n default: false,\n });\n\n if (generateApiRef) {\n const autoDetected = await findSpecFile();\n const apirefSpec = await input({\n message: 'OpenAPI specification for API reference:',\n default:\n config.generators.typescript?.spec ||\n autoDetected ||\n './openapi.yaml',\n });\n\n const apirefOutput = await input({\n message: 'API reference output directory:',\n default: './docs',\n });\n\n config.apiref = {\n spec: apirefSpec,\n output: apirefOutput,\n };\n }\n\n // Write configuration file\n const configPath = resolve(process.cwd(), 'sdk-it.json');\n await writeFile(configPath, JSON.stringify(config, null, 2));\n\n // Show comprehensive next steps\n console.log(`\\n\u2705 Configuration saved to ${configPath}`);\n console.log('\\n\uD83D\uDE80 Next Steps:\\n');\n\n // Step 1: Generate SDKs\n console.log('1. Generate your SDK(s):');\n console.log(' npx @sdk-it/cli');\n\n // Step 2: Integration examples based on selected generators\n if (config.generators.typescript) {\n console.log('2. Integrate TypeScript SDK:');\n const importName = config.generators.typescript.name.replace(\n /[^a-zA-Z0-9]/g,\n '',\n );\n const outputDir = config.generators.typescript.output.replace('./', '');\n console.log(` import { ${importName} } from './${outputDir}';`);\n console.log(` const client = new ${importName}();`);\n console.log(` const result = await client.request('GET /users');\\n`);\n }\n\n if (config.generators.python) {\n console.log('2. Integrate Python SDK:');\n const outputDir = config.generators.python.output.replace('./', '');\n console.log(` # Add to your Python path or install locally`);\n console.log(` from ${outputDir} import Client`);\n console.log(` client = Client()`);\n console.log(` result = client.users.list_users()\\n`);\n }\n\n if (config.generators.dart) {\n console.log('2. Integrate Dart SDK:');\n const outputDir = config.generators.dart.output.replace('./', '');\n console.log(` # Add dependency to pubspec.yaml`);\n console.log(` import 'package:${outputDir}/client.dart';`);\n console.log(` final client = Client();`);\n console.log(` final result = await client.users.listUsers();\\n`);\n }\n\n // Step 3: Documentation\n console.log('3. Check generated documentation:');\n const outputs: string[] = [];\n if (config.generators.typescript)\n outputs.push(config.generators.typescript.output);\n if (config.generators.python) outputs.push(config.generators.python.output);\n if (config.generators.dart) outputs.push(config.generators.dart.output);\n\n outputs.forEach((output) => {\n if (output) {\n console.log(\n ` \uD83D\uDCD6 ${output}/README.md - Usage examples and API reference`,\n );\n }\n });\n\n if (config.readme) {\n console.log(\n ` \uD83D\uDCD6 ${config.readme.output} - Generated API documentation`,\n );\n }\n\n if (config.apiref) {\n console.log(` \uD83C\uDF10 ${config.apiref.output} - Interactive API reference`);\n }\n\n console.log('\\n4. Useful commands:');\n console.log(\n ' npx @sdk-it/cli # Regenerate SDKs after API changes',\n );\n console.log(\n ' npx @sdk-it/cli typescript --help # See TypeScript-specific options',\n );\n console.log(\n ' npx @sdk-it/cli python --help # See Python-specific options',\n );\n console.log(\n ' npx @sdk-it/cli dart --help # See Dart-specific options',\n );\n\n console.log('\\n\uD83D\uDCA1 Tips:');\n console.log(\n ' \u2022 Update your API spec and re-run `npx @sdk-it/cli generate` to sync changes',\n );\n console.log(\n ' \u2022 Generated SDKs include TypeScript definitions for excellent IDE support',\n );\n console.log(\n ' \u2022 Check the README files for authentication and configuration options',\n );\n\n console.log('\\n\uD83D\uDCDA Need help?');\n console.log(' \u2022 Documentation: https://sdk-it.dev/docs');\n console.log(\n ' \u2022 Examples: https://github.com/JanuaryLabs/sdk-it/tree/main/docs/examples',\n );\n console.log(' \u2022 Issues: https://github.com/JanuaryLabs/sdk-it/issues');\n\n console.log('\\nHappy coding! \uD83C\uDF89\\n');\n });\n\nexport default init;\n", "import { resolve } from 'node:path';\n\nimport { analyzeProject } from './project/analysis.ts';\nimport type { ProjectConfig } from './project/config.ts';\nimport { writeProjectClient } from './project/output.ts';\n\nexport {\n defineConfig,\n initializeProject,\n loadProjectConfig,\n} from './project/config.ts';\nexport type {\n InitializeProjectOptions,\n LoadProjectConfigOptions,\n ProjectConfig,\n ResolvedProjectConfig,\n} from './project/config.ts';\n\nexport async function generateProject(config: ProjectConfig): Promise<void> {\n const tsconfig = resolve(config.tsconfig);\n const openapi = await analyzeProject(tsconfig, config);\n await writeProjectClient(openapi, config);\n}\n", "import { createRequire } from 'node:module';\nimport ts from 'typescript';\n\nimport { type InjectImport, defaultTypesMap, getProgram } from '@sdk-it/core';\nimport { analyze } from '@sdk-it/generic';\nimport { responseAnalyzer as honoResponseAnalyzer } from '@sdk-it/hono';\n\nimport type { ProjectConfig } from './config.ts';\n\nexport async function analyzeProject(tsconfig: string, config: ProjectConfig) {\n const framework = resolveFramework(tsconfig, config.framework);\n if (framework === 'auto') {\n throw new Error(\n `Could not detect a supported framework from ${config.tsconfig}. Set framework to 'hono' to select it explicitly.`,\n );\n }\n\n const prisma = config.preset === 'none' ? undefined : detectPrisma(tsconfig);\n if (config.preset === 'prisma' && !prisma) {\n throw new Error(\n `Prisma preset was requested, but no Prisma client import was found in ${tsconfig}. Run prisma generate or set preset to 'none'.`,\n );\n }\n\n const { paths, components } = await analyze(tsconfig, {\n responseAnalyzer: honoResponseAnalyzer,\n ...(prisma\n ? {\n imports: prisma.imports,\n typesMap: {\n ...defaultTypesMap,\n Decimal: 'string',\n },\n }\n : {}),\n });\n\n return {\n openapi: '3.1.0' as const,\n info: {\n title: 'API',\n version: '0.0.0',\n },\n paths,\n components,\n };\n}\n\nfunction resolveFramework(\n tsconfig: string,\n configured: ProjectConfig['framework'],\n): 'hono' | 'auto' {\n return configured === undefined || configured === 'auto'\n ? detectFramework(tsconfig)\n : configured;\n}\n\nfunction detectFramework(tsconfig: string): 'hono' | 'auto' {\n const program = getProgram(tsconfig);\n for (const sourceFile of program.getSourceFiles()) {\n if (sourceFile.isDeclarationFile) continue;\n for (const statement of sourceFile.statements) {\n if (\n ts.isImportDeclaration(statement) &&\n ts.isStringLiteral(statement.moduleSpecifier) &&\n (statement.moduleSpecifier.text === 'hono' ||\n statement.moduleSpecifier.text.startsWith('@sdk-it/hono'))\n ) {\n return 'hono';\n }\n }\n }\n return 'auto';\n}\n\nfunction detectPrisma(\n tsconfig: string,\n): { imports: InjectImport[] } | undefined {\n const program = getProgram(tsconfig);\n const imports: InjectImport[] = [];\n const reportedModules = new Set<string>();\n for (const sourceFile of program.getSourceFiles()) {\n if (sourceFile.isDeclarationFile) continue;\n for (const statement of sourceFile.statements) {\n const prismaImport = getPrismaImport(statement);\n if (!prismaImport) continue;\n const resolvedModule = ts.resolveModuleName(\n prismaImport.moduleSpecifier,\n sourceFile.fileName,\n program.getCompilerOptions(),\n ts.sys,\n );\n if (!resolvedModule.resolvedModule) continue;\n\n let runtimeModule: string;\n try {\n runtimeModule = createRequire(sourceFile.fileName).resolve(\n prismaImport.moduleSpecifier,\n );\n } catch {\n continue;\n }\n\n if (!reportedModules.has(runtimeModule)) {\n console.log(`SDKIT: detected Prisma from ${runtimeModule}`);\n reportedModules.add(runtimeModule);\n }\n for (const { imported, local } of prismaImport.bindings) {\n if (\n !imports.some(\n (item) => item.import === local && item.from === runtimeModule,\n )\n ) {\n imports.push({\n import: local,\n from: runtimeModule,\n property: imported,\n });\n }\n }\n }\n }\n return imports.length > 0 ? { imports } : undefined;\n}\n\nfunction getPrismaImport(statement: ts.Statement):\n | {\n moduleSpecifier: string;\n bindings: Array<{ imported: string; local: string }>;\n }\n | undefined {\n if (\n !ts.isImportDeclaration(statement) ||\n !ts.isStringLiteral(statement.moduleSpecifier) ||\n !statement.importClause?.namedBindings ||\n !ts.isNamedImports(statement.importClause.namedBindings)\n ) {\n return undefined;\n }\n const bindings = statement.importClause.namedBindings.elements\n .map((element) => ({\n imported: element.propertyName?.text ?? element.name.text,\n local: element.name.text,\n }))\n .filter(({ imported }) => imported === 'Prisma' || imported === '$Enums');\n return bindings.length > 0\n ? { moduleSpecifier: statement.moduleSpecifier.text, bindings }\n : undefined;\n}\n", "import { writeFile } from 'node:fs/promises';\nimport { join, resolve } from 'node:path';\n\nimport { generate } from '@sdk-it/typescript';\n\nimport { hashProject, isCurrentGeneratedPackage } from './cache.ts';\nimport { compileGeneratedPackage } from './compiler.ts';\nimport type { ProjectConfig } from './config.ts';\n\ntype ProjectOpenApi = Parameters<typeof generate>[0];\n\nexport async function writeProjectClient(\n openapi: ProjectOpenApi,\n config: ProjectConfig,\n): Promise<void> {\n const output = resolve(config.output ?? '.sdk-it');\n const packageName = config.packageName ?? '@sdk-it/client';\n const hash = hashProject(openapi, packageName);\n if (await isCurrentGeneratedPackage(output, hash)) return;\n\n await generate(openapi, {\n output,\n mode: 'full',\n name: 'Client',\n packageName,\n readme: false,\n });\n await compileGeneratedPackage(output, packageName);\n await writeFile(join(output, '.project-hash'), hash);\n}\n", "import { createHash } from 'node:crypto';\nimport { access, readFile, readdir } from 'node:fs/promises';\nimport { createRequire } from 'node:module';\nimport { join, relative } from 'node:path';\nimport ts from 'typescript';\n\nimport type { generate } from '@sdk-it/typescript';\n\nconst require = createRequire(import.meta.url);\nconst projectGeneratorVersions = {\n cli: require('@sdk-it/cli/package.json').version,\n compiler: ts.version,\n typescript: require('@sdk-it/typescript/package.json').version,\n};\n\ntype ProjectOpenApi = Parameters<typeof generate>[0];\n\nexport function hashProject(\n openapi: ProjectOpenApi,\n packageName: string,\n): string {\n return createHash('sha256')\n .update(JSON.stringify({ openapi, packageName, projectGeneratorVersions }))\n .digest('hex');\n}\n\nexport async function isCurrentGeneratedPackage(\n output: string,\n hash: string,\n): Promise<boolean> {\n return (\n (await readOptionalFile(join(output, '.project-hash'))) === hash &&\n (await generatedPackageExists(output))\n );\n}\n\nasync function generatedPackageExists(output: string): Promise<boolean> {\n try {\n const sourceRoot = join(output, 'src');\n const sources = await findSourceFiles(sourceRoot);\n if (!sources.includes(join(sourceRoot, 'index.ts'))) return false;\n\n await Promise.all([\n access(join(output, 'package.json')),\n ...sources.flatMap((source) =>\n expectedCompiledFiles(output, sourceRoot, source).map((file) =>\n access(file),\n ),\n ),\n ]);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction expectedCompiledFiles(\n output: string,\n sourceRoot: string,\n source: string,\n): string[] {\n const compiled = relative(sourceRoot, source).slice(0, -3);\n return [\n join(output, 'dist', `${compiled}.js`),\n join(output, 'dist', `${compiled}.d.ts`),\n ];\n}\n\nasync function findSourceFiles(directory: string): Promise<string[]> {\n const entries = await readdir(directory, { withFileTypes: true });\n const files = await Promise.all(\n entries.map(async (entry) => {\n const path = join(directory, entry.name);\n if (entry.isDirectory()) return findSourceFiles(path);\n return entry.isFile() && path.endsWith('.ts') && !path.endsWith('.d.ts')\n ? [path]\n : [];\n }),\n );\n return files.flat();\n}\n\nasync function readOptionalFile(path: string): Promise<string | undefined> {\n try {\n return await readFile(path, 'utf8');\n } catch (error) {\n if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {\n return undefined;\n }\n throw error;\n }\n}\n", "import { readFile, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport ts from 'typescript';\n\ninterface GeneratedPackageManifest {\n name?: string;\n version?: string;\n type?: string;\n main?: string;\n module?: string;\n types?: string;\n publishConfig?: Record<string, unknown>;\n exports?: Record<string, unknown>;\n dependencies?: Record<string, string>;\n}\n\nexport async function compileGeneratedPackage(\n output: string,\n packageName: string,\n): Promise<void> {\n const source = join(output, 'src');\n const program = ts.createProgram({\n rootNames: ts.sys.readDirectory(source, ['.ts']),\n options: {\n allowSyntheticDefaultImports: true,\n declaration: true,\n module: ts.ModuleKind.ESNext,\n moduleResolution: ts.ModuleResolutionKind.Bundler,\n noEmitOnError: true,\n outDir: join(output, 'dist'),\n rewriteRelativeImportExtensions: true,\n rootDir: source,\n skipLibCheck: true,\n target: ts.ScriptTarget.ESNext,\n verbatimModuleSyntax: true,\n },\n });\n const result = program.emit();\n const diagnostics = [\n ...ts.getPreEmitDiagnostics(program),\n ...result.diagnostics,\n ].filter((diagnostic) => diagnostic.category === ts.DiagnosticCategory.Error);\n if (result.emitSkipped || diagnostics.length > 0) {\n throw new Error(formatCompilationError(output, diagnostics));\n }\n\n await synchronizeGeneratedManifest(output, packageName);\n}\n\nfunction formatCompilationError(\n output: string,\n diagnostics: readonly ts.Diagnostic[],\n): string {\n return `Failed to compile generated client:\\n${ts.formatDiagnosticsWithColorAndContext(\n diagnostics,\n {\n getCanonicalFileName: (fileName) => fileName,\n getCurrentDirectory: () => output,\n getNewLine: () => '\\n',\n },\n )}`;\n}\n\nasync function synchronizeGeneratedManifest(\n output: string,\n packageName: string,\n): Promise<void> {\n const manifestPath = join(output, 'package.json');\n const manifest = JSON.parse(\n await readFile(manifestPath, 'utf8'),\n ) as GeneratedPackageManifest;\n Object.assign(manifest, {\n name: packageName,\n version: '0.0.1',\n type: 'module',\n main: './dist/index.js',\n module: './dist/index.js',\n types: './dist/index.d.ts',\n });\n manifest.publishConfig = { ...manifest.publishConfig, access: 'public' };\n manifest.exports = {\n ...manifest.exports,\n './package.json': './package.json',\n '.': {\n types: './dist/index.d.ts',\n import: './dist/index.js',\n default: './dist/index.js',\n },\n };\n manifest.dependencies = {\n ...manifest.dependencies,\n 'fast-content-type-parse': '^3.0.0',\n zod: '^4.3.0',\n };\n await writeFile(manifestPath, `${JSON.stringify(manifest, null, 2)}\\n`);\n}\n", "import { access, readFile, stat, writeFile } from 'node:fs/promises';\nimport { dirname, join, relative, resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\n\nexport interface ProjectConfig {\n tsconfig: string;\n framework?: 'auto' | 'hono';\n preset?: 'auto' | 'prisma' | 'none';\n output?: string;\n packageName?: string;\n}\n\nexport interface ResolvedProjectConfig extends ProjectConfig {\n output: string;\n}\n\nexport interface LoadProjectConfigOptions {\n cwd?: string;\n config?: string;\n}\n\nexport interface InitializeProjectOptions {\n cwd?: string;\n tsconfig: string;\n}\n\ninterface ProjectPackageManifest {\n workspaces?: string[] | { packages?: string[]; [key: string]: unknown };\n [key: string]: unknown;\n}\n\nexport function defineConfig<const Config extends ProjectConfig>(\n config: Config,\n): Config {\n return config;\n}\n\nexport async function loadProjectConfig(\n options: LoadProjectConfigOptions = {},\n): Promise<ResolvedProjectConfig> {\n const cwd = resolve(options.cwd ?? process.cwd());\n const configPath = options.config\n ? resolve(cwd, options.config)\n : await findProjectConfig(cwd);\n const loaded = await import(pathToFileURL(configPath).href);\n const config = loaded.default as ProjectConfig | undefined;\n if (!config || typeof config.tsconfig !== 'string') {\n throw new Error(\n `Expected ${configPath} to default export an SDK-IT config with a tsconfig path.`,\n );\n }\n\n const directory = dirname(configPath);\n return {\n ...config,\n tsconfig: resolve(directory, config.tsconfig),\n output: resolve(directory, config.output ?? '.sdk-it'),\n };\n}\n\nexport async function initializeProject(\n options: InitializeProjectOptions,\n): Promise<void> {\n const cwd = resolve(options.cwd ?? process.cwd());\n const configPath = join(cwd, 'sdk-it.config.ts');\n const tsconfigPath = resolve(cwd, options.tsconfig);\n await validateTsconfig(tsconfigPath);\n const tsconfig = relative(cwd, tsconfigPath).replaceAll('\\\\', '/');\n const relativeTsconfig = tsconfig.startsWith('.')\n ? tsconfig\n : `./${tsconfig}`;\n const configSource = `import { defineConfig } from '@sdk-it/cli';\n\nexport default defineConfig({\n tsconfig: '${relativeTsconfig}',\n});\n`;\n\n const existingConfig = await readOptionalFile(configPath);\n if (existingConfig !== undefined && existingConfig !== configSource) {\n throw new Error(\n `${configPath} already exists with different settings. Review it before replacing the file.`,\n );\n }\n\n const packagePath = join(cwd, 'package.json');\n const manifest = JSON.parse(\n await readFile(packagePath, 'utf8'),\n ) as ProjectPackageManifest;\n const manifestChanged = addGeneratedWorkspace(manifest);\n\n const gitignorePath = join(cwd, '.gitignore');\n const gitignore = (await readOptionalFile(gitignorePath)) ?? '';\n if (!ignoresGeneratedWorkspace(gitignore)) {\n const prefix =\n gitignore.length > 0 && !gitignore.endsWith('\\n') ? '\\n' : '';\n await writeFile(gitignorePath, `${gitignore}${prefix}.sdk-it/\\n`);\n }\n\n if (manifestChanged) {\n await writeFile(packagePath, `${JSON.stringify(manifest, null, 2)}\\n`);\n }\n\n if (existingConfig === undefined) {\n await writeFile(configPath, configSource);\n }\n}\n\nfunction addGeneratedWorkspace(manifest: ProjectPackageManifest): boolean {\n const workspaces = manifest.workspaces;\n if (Array.isArray(workspaces)) {\n if (workspaces.includes('.sdk-it')) return false;\n workspaces.push('.sdk-it');\n return true;\n }\n if (workspaces && Array.isArray(workspaces.packages)) {\n if (workspaces.packages.includes('.sdk-it')) return false;\n workspaces.packages.push('.sdk-it');\n return true;\n }\n manifest.workspaces = ['.sdk-it'];\n return true;\n}\n\nfunction ignoresGeneratedWorkspace(gitignore: string): boolean {\n return gitignore\n .split(/\\r?\\n/)\n .some((line) => line.trim() === '.sdk-it/' || line.trim() === '.sdk-it');\n}\n\nasync function validateTsconfig(path: string): Promise<void> {\n try {\n if ((await stat(path)).isFile()) return;\n } catch (error) {\n if (!(\n error instanceof Error &&\n 'code' in error &&\n error.code === 'ENOENT'\n )) {\n throw error;\n }\n }\n throw new Error(`Could not find a TypeScript project at ${path}.`);\n}\n\nasync function findProjectConfig(start: string): Promise<string> {\n let directory = start;\n while (true) {\n const candidate = join(directory, 'sdk-it.config.ts');\n try {\n await access(candidate);\n return candidate;\n } catch {\n const parent = dirname(directory);\n if (parent === directory) {\n throw new Error(\n `Could not find sdk-it.config.ts from ${start} or any parent directory.`,\n );\n }\n directory = parent;\n }\n }\n}\n\nasync function readOptionalFile(path: string): Promise<string | undefined> {\n try {\n return await readFile(path, 'utf8');\n } catch (error) {\n if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {\n return undefined;\n }\n throw error;\n }\n}\n", "import { resolve } from 'node:path';\n\nimport { exist } from '@sdk-it/core/file-system.js';\n\nconst monorepoIndicators = {\n lerna: () => exist(resolve(process.cwd(), 'lerna.json')),\n nx: () => exist(resolve(process.cwd(), 'nx.json')),\n pnpm: () => exist(resolve(process.cwd(), 'pnpm-workspace.yaml')),\n rush: () => exist(resolve(process.cwd(), 'rush.json')),\n} as const;\n\ntype Monorepo = keyof typeof monorepoIndicators;\n\nexport async function detectMonorepo(): Promise<Monorepo | undefined> {\n for (const [indicator, check] of Object.entries(monorepoIndicators)) {\n if (await check()) {\n return indicator as Monorepo;\n }\n }\n return void 0;\n}\n", "import { resolve } from 'node:path';\n\nimport { exist } from '@sdk-it/core/file-system.js';\n\nexport async function findSpecFile() {\n const commonNames = [\n 'openapi.json',\n 'openapi.yaml',\n 'openapi.yml',\n 'swagger.json',\n 'swagger.yaml',\n 'swagger.yml',\n 'api.json',\n 'api.yaml',\n 'api.yml',\n 'spec.json',\n 'spec.yaml',\n 'spec.yml',\n 'schema.json',\n 'schema.yaml',\n 'schema.yml',\n ];\n\n for (const name of commonNames) {\n if (await exist(resolve(process.cwd(), name))) {\n return `./${name}`;\n }\n }\n return undefined;\n}\n", "import { join } from 'node:path';\n\nimport { readJson } from '@sdk-it/core/file-system.js';\n\nexport async function guessTypescriptPackageName(\n consideringMultipleGenerator: boolean,\n): Promise<string> {\n try {\n const packageJson = await readJson<{ name: string }>(\n join(process.cwd(), 'package.json'),\n );\n if (packageJson.name) {\n const match = packageJson.name.match(/^@([^/]+)/);\n if (match) {\n const scope = match[1];\n return consideringMultipleGenerator\n ? `@${scope}/ts-sdk`\n : `@${scope}/sdk`;\n }\n }\n } catch {\n // If package.json doesn't exist or can't be read, use fallback\n }\n\n // Fallback if no package.json or no scope found\n return consideringMultipleGenerator ? 'ts-sdk' : 'sdk';\n}\n", "import { Command } from 'commander';\nimport { execa } from 'execa';\nimport { dirname, join } from 'node:path';\n\nimport { outputOption, specOption } from '../options.ts';\n\nexport default new Command('apiref')\n .description('Generate APIREF')\n .addOption(specOption.makeOptionMandatory(true))\n .addOption(outputOption.makeOptionMandatory(true))\n .action(async (options: { spec: string; output: string }) => {\n await runApiRef(options.spec, options.output);\n });\n\nexport function runApiRef(spec: string, output: string) {\n const packageDir = join(dirname(import.meta.url), '..', '..', 'apiref');\n return execa('nx', ['run', 'apiref:build', '--verbose'], {\n stdio: 'inherit',\n extendEnv: true,\n cwd: packageDir,\n env: {\n VITE_SPEC: spec,\n VITE_SDK_IT_OUTPUT: output,\n },\n });\n}\n", "import { Option } from 'commander';\n\nexport const specOption = new Option(\n '-s, --spec <spec>',\n 'Path to OpenAPI specification file',\n);\n\nexport const outputOption = new Option(\n '-o, --output <output>',\n 'Output directory for the generated SDK',\n);\n\n/**\n * Return the correct shell\u2010expansion syntax for an env var\n * on the current platform (cmd.exe vs POSIX).\n */\nexport function shellEnv(name: string): string {\n return process.platform === 'win32'\n ? `%${name}%` // Windows cmd.exe\n : `$${name}`; // POSIX shells\n}\n\n/**\n * Parse pagination configuration from CLI option value with dot notation support\n * @param incoming The pagination configuration value (e.g., \"false\", \"true\", \"guess=false\")\n * @returns PaginationConfig object or false\n */\nexport function parseDotConfig(\n incoming?: string,\n): Record<string, unknown> | boolean | undefined {\n if (incoming === 'false') {\n return false;\n }\n\n if (incoming === 'true') {\n return true;\n }\n\n if (!incoming) {\n return undefined;\n }\n\n // Handle dot notation like \"guess=false\"\n const config: Record<string, unknown> = {};\n const pairs = incoming.split(',');\n\n for (const pair of pairs) {\n if (pair.includes('=')) {\n const [key, val] = pair.split('=', 2);\n if (val === 'true') {\n config[key] = true;\n continue;\n }\n if (val === 'false') {\n config[key] = false;\n continue;\n }\n config[key] = val; // Keep as string if not boolean\n }\n }\n\n return config;\n}\n\nexport function parsePagination(config?: ReturnType<typeof parseDotConfig>) {\n if (config === true || config === undefined) {\n return undefined;\n }\n if (config === false) {\n return false;\n }\n return config;\n}\n", "import { Command } from 'commander';\nimport { execFile, execSync } from 'node:child_process';\n\nimport { generate } from '@sdk-it/dart';\nimport { loadSpec } from '@sdk-it/spec';\n\nimport {\n outputOption,\n parseDotConfig,\n parsePagination,\n shellEnv,\n specOption,\n} from '../options.ts';\nimport type { DartOptions } from '../types.ts';\n\ntype Options = Omit<DartOptions, 'pagination'> & {\n output: string;\n pagination?: DartOptions['pagination'] | string;\n};\nexport default new Command('dart')\n .description('Generate Dart SDK')\n .addOption(specOption.makeOptionMandatory(true))\n .addOption(outputOption.makeOptionMandatory(true))\n .option('-n, --name <name>', 'Name of the generated client', 'Client')\n .option(\n '--pagination <pagination>',\n 'Configure pagination (e.g., \"false\", \"true\", \"guess=false\")',\n 'true',\n )\n .option('-v, --verbose', 'Verbose output', false)\n .action(async (options: Options) => {\n await runDart(options);\n });\n\nexport async function runDart(options: Options) {\n await generate(await loadSpec(options.spec), {\n output: options.output,\n mode: options.mode || 'full',\n name: options.name,\n pagination:\n typeof options.pagination === 'string'\n ? parsePagination(parseDotConfig(options.pagination ?? 'true'))\n : options.pagination,\n formatCode: ({ output }) => {\n if (options.formatter) {\n const [command, ...args] = options.formatter.split(' ');\n execFile(command, args, {\n env: { ...process.env, SDK_IT_OUTPUT: output },\n });\n } else {\n execSync(`dart format ${shellEnv('SDK_IT_OUTPUT')}`, {\n env: { ...process.env, SDK_IT_OUTPUT: output },\n stdio: options.verbose ? 'inherit' : 'pipe',\n });\n // execSync('dart fix --apply $SDK_IT_OUTPUT ', {\n // env: { ...process.env, SDK_IT_OUTPUT: output },\n // stdio: options.verbose ? 'inherit' : 'pipe',\n // });\n }\n },\n });\n}\n", "import { Command } from 'commander';\nimport { execFile, execSync } from 'node:child_process';\n\nimport { generate } from '@sdk-it/python';\nimport { loadSpec, toIR } from '@sdk-it/spec';\n\nimport { outputOption, shellEnv, specOption } from '../options.ts';\nimport type { PythonOptions } from '../types.ts';\n\nexport default new Command('python')\n .description('Generate Python SDK')\n .addOption(specOption.makeOptionMandatory(true))\n .addOption(outputOption.makeOptionMandatory(true))\n .option('-n, --name <n>', 'Name of the generated client', 'Client')\n .option('-v, --verbose', 'Verbose output', false)\n .option('--formatter <formatter>', 'Formatter to use for the generated code')\n .action(async (options: PythonOptions) => {\n await runPython(options);\n });\n\nexport async function runPython(options: PythonOptions) {\n const spec = await toIR({ spec: await loadSpec(options.spec) }, true);\n await generate(spec, {\n output: options.output,\n mode: options.mode || 'full',\n name: options.name,\n formatCode: ({ output }: { output: string }) => {\n if (options.formatter) {\n const [command, ...args] = options.formatter.split(' ');\n execFile(command, args, {\n env: { ...process.env, SDK_IT_OUTPUT: output },\n });\n } else {\n try {\n // Try black first (more common)\n execSync(`black ${shellEnv('SDK_IT_OUTPUT')}`, {\n env: { ...process.env, SDK_IT_OUTPUT: output },\n stdio: options.verbose ? 'inherit' : 'pipe',\n });\n } catch {\n try {\n // Fallback to ruff format if black is not available\n execSync(`ruff format ${shellEnv('SDK_IT_OUTPUT')}`, {\n env: { ...process.env, SDK_IT_OUTPUT: output },\n stdio: options.verbose ? 'inherit' : 'pipe',\n });\n } catch {\n // If neither formatter is available, continue without formatting\n if (options.verbose) {\n console.warn(\n 'No Python formatter found (black or ruff). Skipping formatting.',\n );\n }\n }\n }\n }\n },\n });\n}\n", "import { readdir } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type {\n OpenAPIObject,\n OperationObject,\n ReferenceObject,\n SchemaObject,\n} from 'openapi3-ts/oas31';\nimport { snakecase } from 'stringcase';\n\nimport { followRef, isEmpty, isRef, pascalcase } from '@sdk-it/core';\nimport {\n type ReadFolderFn,\n type Writer,\n createWriterProxy,\n writeFiles,\n} from '@sdk-it/core/file-system.js';\nimport {\n type IR,\n cleanFiles,\n forEachOperation,\n isSuccessStatusCode,\n parseJsonContentType,\n readWriteMetadata,\n toIR,\n} from '@sdk-it/spec';\n\nimport dispatcherTxt from './http/dispatcher.txt';\nimport interceptorsTxt from './http/interceptors.txt';\nimport responsesTxt from './http/responses.txt';\nimport { PythonEmitter } from './python-emitter.ts';\n\nexport async function generate(\n openapi: OpenAPIObject,\n settings: {\n output: string;\n cleanup?: boolean;\n name?: string;\n writer?: Writer;\n readFolder?: ReadFolderFn;\n /**\n * full: generate a full project including requirements.txt\n * minimal: generate only the client sdk\n */\n mode?: 'full' | 'minimal';\n formatCode?: (options: { output: string }) => void | Promise<void>;\n },\n) {\n const spec = await toIR({ spec: openapi }, true);\n\n const clientName = settings.name || 'Client';\n const output = settings.output;\n const { writer, files: writtenFiles } = createWriterProxy(\n settings.writer ?? writeFiles,\n settings.output,\n );\n settings.writer = writer;\n settings.readFolder ??= async (folder: string) => {\n const files = await readdir(folder, { withFileTypes: true });\n return files.map((file) => ({\n fileName: file.name,\n filePath: join(file.parentPath, file.name),\n isFolder: file.isDirectory(),\n }));\n };\n\n const groups: Record<\n string,\n {\n className: string;\n methods: string[];\n }\n > = {};\n\n // Process each operation and group by tags\n forEachOperation(spec, (entry, operation) => {\n console.log(`Processing ${entry.method} ${entry.path}`);\n const group = (groups[entry.tag] ??= {\n className: `${pascalcase(entry.tag)}Api`,\n methods: [],\n });\n\n const input = toInputs(spec, { entry, operation });\n const response = toOutput(spec, operation);\n\n // Generate method for this operation\n const methodName = snakecase(\n operation.operationId ||\n `${entry.method}_${entry.path.replace(/[^a-zA-Z0-9]/g, '_')}`,\n );\n const returnType = response ? response.returnType : 'httpx.Response';\n\n const docstring =\n operation.summary || operation.description\n ? ` \"\"\"${operation.summary || operation.description}\"\"\"`\n : '';\n\n group.methods.push(`\n async def ${methodName}(self${input.haveInput ? `, input_data: ${input.inputName}` : ''}) -> ${returnType}:\n${docstring}\n config = RequestConfig(\n method='${entry.method.toUpperCase()}',\n url='${entry.path}',\n )\n\n ${input.haveInput ? 'config = input_data.to_request_config(config)' : ''}\n\n response = await self.dispatcher.${input.contentType}(config)\n ${response ? `return await self.receiver.json(response, ${response.successModel || 'None'}, ${response.errorModel || 'None'})` : 'return response'}\n `);\n });\n\n // Generate models using the Python emitter\n const emitter = new PythonEmitter(spec);\n const models = await serializeModels(spec, emitter);\n\n // Generate API group classes\n const apiClasses = Object.entries(groups).reduce<Record<string, string>>(\n (acc, [name, { className, methods }]) => {\n const fileName = `api/${snakecase(name)}_api.py`;\n const imports = [\n 'from typing import Any, Dict, List, Literal, Optional, Union',\n 'from typing_extensions import Never',\n 'import httpx',\n '',\n 'from ..http.dispatcher import Dispatcher, RequestConfig',\n 'from ..http.responses import Receiver',\n 'from ..inputs import *',\n 'from ..outputs import *',\n 'from ..models import *',\n '',\n ].join('\\n');\n\n acc[fileName] = `${imports}\nclass ${className}:\n \"\"\"API client for ${name} operations.\"\"\"\n\n def __init__(self, dispatcher: Dispatcher, receiver: Receiver):\n self.dispatcher = dispatcher\n self.receiver = receiver\n${methods.join('\\n')}\n`;\n return acc;\n },\n {},\n );\n\n // Generate main client\n const apiImports = Object.keys(groups)\n .map(\n (name) =>\n `from .api.${snakecase(name)}_api import ${pascalcase(name)}Api`,\n )\n .join('\\n');\n\n const apiProperties = Object.keys(groups)\n .map(\n (name) =>\n ` self.${snakecase(name)} = ${pascalcase(name)}Api(dispatcher, receiver)`,\n )\n .join('\\n');\n\n const clientCode = `\"\"\"Main API client.\"\"\"\n\nfrom typing import Optional, List\nimport httpx\n\n${apiImports}\nfrom .http.dispatcher import Dispatcher, RequestConfig\nfrom .http.responses import Receiver\nfrom .http.interceptors import (\n Interceptor,\n BaseUrlInterceptor,\n LoggingInterceptor,\n AuthInterceptor,\n UserAgentInterceptor,\n)\n\n\nclass ${clientName}:\n \"\"\"Main API client for the SDK.\"\"\"\n\n def __init__(\n self,\n base_url: str,\n token: Optional[str] = None,\n api_key: Optional[str] = None,\n api_key_header: str = 'X-API-Key',\n enable_logging: bool = False,\n user_agent: Optional[str] = None,\n custom_interceptors: Optional[List[Interceptor]] = None,\n ):\n \"\"\"\n Initialize the API client.\n\n Args:\n base_url: Base URL for the API\n token: Bearer token for authentication\n api_key: API key for authentication\n api_key_header: Header name for API key authentication\n enable_logging: Enable request/response logging\n user_agent: Custom User-Agent header\n custom_interceptors: Additional custom interceptors\n \"\"\"\n self.base_url = base_url\n\n # Build interceptor chain\n interceptors = []\n\n # Base URL interceptor (always first)\n interceptors.append(BaseUrlInterceptor(base_url))\n\n # Authentication interceptor\n if token or api_key:\n interceptors.append(AuthInterceptor(token=token, api_key=api_key, api_key_header=api_key_header))\n\n # User agent interceptor\n if user_agent:\n interceptors.append(UserAgentInterceptor(user_agent))\n\n # Logging interceptor\n if enable_logging:\n interceptors.append(LoggingInterceptor())\n\n # Custom interceptors\n if custom_interceptors:\n interceptors.extend(custom_interceptors)\n\n # Initialize dispatcher and receiver\n self.dispatcher = Dispatcher(interceptors)\n self.receiver = Receiver(interceptors)\n\n # Initialize API clients\n${apiProperties}\n\n async def __aenter__(self):\n return self\n\n async def __aexit__(self, exc_type, exc_val, exc_tb):\n await self.close()\n\n async def close(self):\n \"\"\"Close the HTTP client.\"\"\"\n await self.dispatcher.close()\n`;\n\n // Write all files\n await settings.writer(output, {\n ...models,\n ...apiClasses,\n 'client.py': clientCode,\n 'http/dispatcher.py': dispatcherTxt,\n 'http/interceptors.py': interceptorsTxt,\n 'http/responses.py': responsesTxt,\n '__init__.py': `\"\"\"SDK package.\"\"\"\n\nfrom .client import ${clientName}\n\n__all__ = ['${clientName}']\n`,\n });\n\n // Generate requirements.txt if in full mode\n if (settings.mode === 'full') {\n const requirements = `# HTTP client\nhttpx>=0.24.0,<1.0.0\n\n# Data validation and serialization\npydantic>=2.0.0,<3.0.0\n\n# Enhanced type hints\ntyping-extensions>=4.1.0\n\n# Optional: For better datetime handling\npython-dateutil>=2.8.0\n`;\n\n await settings.writer(output, {\n 'requirements.txt': requirements,\n });\n }\n\n // Handle metadata and cleanup\n const metadata = await readWriteMetadata(\n settings.output,\n Array.from(writtenFiles),\n );\n\n if (settings.cleanup !== false && writtenFiles.size > 0) {\n await cleanFiles(metadata.content, settings.output, [\n '/__init__.py',\n 'requirements.txt',\n '/metadata.json',\n ]);\n }\n\n // Generate __init__.py files for packages\n await settings.writer(output, {\n 'models/__init__.py': await generateModuleInit(\n join(output, 'models'),\n settings.readFolder,\n ),\n 'inputs/__init__.py': await generateModuleInit(\n join(output, 'inputs'),\n settings.readFolder,\n ),\n 'outputs/__init__.py': await generateModuleInit(\n join(output, 'outputs'),\n settings.readFolder,\n ),\n 'api/__init__.py': await generateModuleInit(\n join(output, 'api'),\n settings.readFolder,\n ),\n 'http/__init__.py': `\"\"\"HTTP utilities.\"\"\"\n\nfrom .dispatcher import Dispatcher, RequestConfig\nfrom .interceptors import *\nfrom .responses import *\n\n__all__ = [\n 'Dispatcher',\n 'RequestConfig',\n 'ApiResponse',\n 'ErrorResponse',\n 'Interceptor',\n 'BaseUrlInterceptor',\n 'LoggingInterceptor',\n 'AuthInterceptor',\n]\n`,\n });\n\n // Run formatter if provided\n if (settings.formatCode) {\n await settings.formatCode({ output: settings.output });\n }\n}\n\nasync function generateModuleInit(\n folder: string,\n readFolder: ReadFolderFn,\n): Promise<string> {\n try {\n const files = await readFolder(folder);\n const pyFiles = files\n .filter(\n (file) =>\n file.fileName.endsWith('.py') && file.fileName !== '__init__.py',\n )\n .map((file) => file.fileName.replace('.py', ''));\n\n if (pyFiles.length === 0) {\n return '\"\"\"Package module.\"\"\"\\n';\n }\n\n const imports = pyFiles.map((name) => `from .${name} import *`).join('\\n');\n return `\"\"\"Package module.\"\"\"\\n\\n${imports}\\n`;\n } catch {\n return '\"\"\"Package module.\"\"\"\\n';\n }\n}\n\nfunction toInputs(\n spec: IR,\n { entry, operation }: { entry: unknown; operation: OperationObject },\n) {\n const inputName = (entry as { inputName?: string }).inputName || 'Input';\n const haveInput =\n !isEmpty(operation.parameters) || !isEmpty(operation.requestBody);\n\n let contentType = 'json';\n if (operation.requestBody && !isRef(operation.requestBody)) {\n const content = operation.requestBody.content;\n if (content) {\n const contentTypes = Object.keys(content);\n if (contentTypes.some((type) => type.includes('multipart'))) {\n contentType = 'multipart';\n } else if (contentTypes.some((type) => type.includes('form'))) {\n contentType = 'form';\n }\n }\n }\n\n return {\n inputName,\n haveInput,\n contentType,\n };\n}\n\nfunction toOutput(spec: IR, operation: OperationObject) {\n if (!operation.responses) {\n return null;\n }\n\n // Find success response\n const successResponse = Object.entries(operation.responses).find(([code]) =>\n isSuccessStatusCode(Number(code)),\n );\n\n if (!successResponse) {\n return null;\n }\n\n const [, response] = successResponse;\n if (isRef(response)) {\n return null;\n }\n\n const content = response.content;\n if (!content) {\n return { returnType: 'None', successModel: null, errorModel: null };\n }\n\n // Find JSON content type\n const jsonContent = Object.entries(content).find(([type]) =>\n parseJsonContentType(type),\n );\n\n if (!jsonContent) {\n return {\n returnType: 'httpx.Response',\n successModel: null,\n errorModel: null,\n };\n }\n\n const [, mediaType] = jsonContent;\n const schema = (mediaType as { schema?: SchemaObject | ReferenceObject })\n .schema;\n\n if (!schema) {\n return { returnType: 'Any', successModel: null, errorModel: null };\n }\n\n let outputSchema = schema;\n if (isRef(schema)) {\n const resolvedSchema = followRef<SchemaObject>(spec, schema.$ref);\n const isBottomResponse =\n isBottomSchema(spec, resolvedSchema) ||\n (resolvedSchema.type === 'array' &&\n isBottomSchema(spec, resolvedSchema.items));\n\n if (!isBottomResponse) {\n return { returnType: 'Any', successModel: null, errorModel: null };\n }\n outputSchema = resolvedSchema;\n }\n\n // Generate return type based on schema\n const emitter = new PythonEmitter(spec);\n const result = emitter.handle(outputSchema, {});\n\n return {\n returnType: result.type || 'Any',\n successModel: result.simple ? null : result.type,\n errorModel: null, // TODO: Handle error models\n };\n}\n\nfunction isBottomSchema(\n spec: IR,\n schema: SchemaObject | ReferenceObject | undefined,\n): boolean {\n if (!schema) {\n return false;\n }\n const resolved = isRef(schema)\n ? followRef<SchemaObject>(spec, schema.$ref)\n : schema;\n return !!resolved.not && isEmpty(resolved.not);\n}\n\nasync function serializeModels(\n spec: IR,\n emitter: PythonEmitter,\n): Promise<Record<string, string>> {\n const models: Record<string, string> = {};\n\n // Standard imports for all Python model files\n const standardImports = [\n 'from typing import Any, Dict, List, Optional, Union, Literal',\n 'from typing_extensions import Annotated, Never',\n 'from pydantic import BaseModel, BeforeValidator, Field',\n 'from datetime import datetime, date',\n 'from uuid import UUID',\n 'from enum import Enum',\n '',\n 'def _reject_never(value: Any) -> Never:',\n \" raise ValueError('Value is forbidden by the schema')\",\n '',\n '_NeverValue = Annotated[Any, BeforeValidator(_reject_never)]',\n ].join('\\n');\n\n // Emit all schemas\n emitter.onEmit((name: string, content: string, schema: SchemaObject) => {\n // Add imports to the content\n const fullContent = `${standardImports}\n${schema['x-inputname'] ? 'from ..http.dispatcher import RequestConfig' : ''}\n\n\n${content}`;\n\n if (schema['x-inputname']) {\n models[`inputs/${snakecase(name)}.py`] = fullContent;\n } else if (schema['x-response-name']) {\n models[`outputs/${snakecase(name)}.py`] = fullContent;\n } else {\n models[`models/${snakecase(name)}.py`] = fullContent;\n }\n });\n\n // Process all schemas in components\n if (spec.components?.schemas) {\n for (const [name, schema] of Object.entries(spec.components.schemas)) {\n if (!isRef(schema)) {\n emitter.handle(schema, { name, pydantic: true });\n }\n }\n }\n\n return models;\n}\n", "\"\"\"HTTP dispatcher for making API requests.\"\"\"\n\nimport asyncio\nimport logging\nfrom typing import Any, Dict, List, Optional, Union\nfrom urllib.parse import urljoin, urlparse\n\nimport httpx\nfrom pydantic import BaseModel\n\nfrom .interceptors import Interceptor\nfrom .responses import ApiResponse, ErrorResponse\n\n\nclass RequestConfig(BaseModel):\n \"\"\"Configuration for an HTTP request.\"\"\"\n\n method: str\n url: str\n headers: Optional[Dict[str, str]] = None\n params: Optional[Dict[str, Any]] = None\n json_data: Optional[Dict[str, Any]] = None\n form_data: Optional[Dict[str, Any]] = None\n files: Optional[Dict[str, Any]] = None\n timeout: Optional[Union[float, httpx.Timeout]] = None\n \n class Config:\n \"\"\"Pydantic configuration.\"\"\"\n arbitrary_types_allowed = True\n\n\nclass Dispatcher:\n \"\"\"HTTP client dispatcher with interceptor support.\"\"\"\n\n def __init__(\n self, \n interceptors: Optional[List[Interceptor]] = None,\n client: Optional[httpx.AsyncClient] = None,\n timeout: Optional[Union[float, httpx.Timeout]] = None\n ):\n \"\"\"Initialize the dispatcher.\n \n Args:\n interceptors: List of interceptors to apply to requests/responses\n client: Custom httpx.AsyncClient instance (creates default if None)\n timeout: Default timeout for requests\n \"\"\"\n self.interceptors = interceptors or []\n self.client = client or httpx.AsyncClient(timeout=timeout)\n self.logger = logging.getLogger(__name__)\n\n async def __aenter__(self):\n \"\"\"Async context manager entry.\"\"\"\n return self\n\n async def __aexit__(self, exc_type, exc_val, exc_tb):\n \"\"\"Async context manager exit.\"\"\"\n await self.client.aclose()\n\n async def request(self, config: RequestConfig) -> httpx.Response:\n \"\"\"Execute an HTTP request with interceptor processing.\n \n Args:\n config: Request configuration\n \n Returns:\n HTTP response after processing through interceptors\n \n Raises:\n httpx.HTTPError: For HTTP-related errors\n ValueError: For invalid request configuration\n \"\"\"\n # Process request interceptors\n processed_config = config\n for interceptor in self.interceptors:\n processed_config = await interceptor.process_request(processed_config)\n\n # Prepare request arguments\n request_kwargs = self._prepare_request_kwargs(processed_config)\n\n try:\n # Execute request\n response = await self.client.request(**request_kwargs)\n \n # Process response interceptors (in reverse order)\n for interceptor in reversed(self.interceptors):\n response = await interceptor.process_response(response)\n\n return response\n \n except httpx.RequestError as e:\n self.logger.error(f\"Request failed: {e}\")\n raise\n except Exception as e:\n self.logger.error(f\"Unexpected error during request: {e}\")\n raise\n\n def _prepare_request_kwargs(self, config: RequestConfig) -> Dict[str, Any]:\n \"\"\"Prepare keyword arguments for httpx request.\n \n Args:\n config: Request configuration\n \n Returns:\n Dictionary of kwargs for httpx.request\n \n Raises:\n ValueError: If request configuration is invalid\n \"\"\"\n if not config.method:\n raise ValueError(\"Request method cannot be empty\")\n \n if not config.url:\n raise ValueError(\"Request URL cannot be empty\")\n\n request_kwargs = {\n 'method': config.method.upper(),\n 'url': config.url,\n 'headers': config.headers or {},\n 'params': config.params,\n 'timeout': config.timeout,\n }\n\n # Handle different content types\n content_type_set = False\n \n if config.json_data is not None:\n request_kwargs['json'] = config.json_data\n if 'Content-Type' not in request_kwargs['headers']:\n request_kwargs['headers']['Content-Type'] = 'application/json'\n content_type_set = True\n \n elif config.form_data is not None:\n request_kwargs['data'] = config.form_data\n if 'Content-Type' not in request_kwargs['headers']:\n request_kwargs['headers']['Content-Type'] = 'application/x-www-form-urlencoded'\n content_type_set = True\n \n elif config.files is not None:\n request_kwargs['files'] = config.files\n # Don't set Content-Type for multipart/form-data - httpx will handle it automatically\n content_type_set = True\n\n # Validate that only one content type is set\n content_fields = [config.json_data, config.form_data, config.files]\n non_none_count = sum(1 for field in content_fields if field is not None)\n \n if non_none_count > 1:\n raise ValueError(\n \"Only one of json_data, form_data, or files can be set in a single request\"\n )\n\n return request_kwargs\n\n async def json(self, config: RequestConfig) -> httpx.Response:\n \"\"\"Make a JSON request.\n \n Args:\n config: Request configuration\n \n Returns:\n HTTP response\n \"\"\"\n return await self.request(config)\n\n async def form(self, config: RequestConfig) -> httpx.Response:\n \"\"\"Make a form-encoded request.\n \n Args:\n config: Request configuration\n \n Returns:\n HTTP response\n \"\"\"\n return await self.request(config)\n\n async def multipart(self, config: RequestConfig) -> httpx.Response:\n \"\"\"Make a multipart/form-data request.\n \n Args:\n config: Request configuration\n \n Returns:\n HTTP response\n \"\"\"\n return await self.request(config)\n\n async def close(self):\n \"\"\"Close the HTTP client and clean up resources.\"\"\"\n await self.client.aclose()\n\n\nclass Receiver:\n \"\"\"Response processor with interceptor support.\"\"\"\n\n def __init__(\n self, \n interceptors: Optional[List[Interceptor]] = None,\n logger: Optional[logging.Logger] = None\n ):\n \"\"\"Initialize the receiver.\n \n Args:\n interceptors: List of interceptors to apply to responses\n logger: Custom logger instance\n \"\"\"\n self.interceptors = interceptors or []\n self.logger = logger or logging.getLogger(__name__)\n\n async def json(\n self, \n response: httpx.Response, \n success_model: Optional[type] = None, \n error_model: Optional[type] = None\n ) -> Any:\n \"\"\"Process a JSON response.\n \n Args:\n response: HTTP response to process\n success_model: Pydantic model for successful responses\n error_model: Pydantic model for error responses\n \n Returns:\n Parsed response data, optionally as model instances\n \n Raises:\n ErrorResponse: For HTTP error status codes\n ValueError: For response parsing errors\n \"\"\"\n # Process response interceptors\n processed_response = response\n for interceptor in self.interceptors:\n processed_response = await interceptor.process_response(processed_response)\n\n # Handle different status codes\n if 200 <= processed_response.status_code < 300:\n return await self._handle_success_response(\n processed_response, success_model\n )\n else:\n await self._handle_error_response(\n processed_response, error_model\n )\n\n async def _handle_success_response(\n self, \n response: httpx.Response, \n success_model: Optional[type] = None\n ) -> Any:\n \"\"\"Handle successful response.\n \n Args:\n response: HTTP response\n success_model: Pydantic model for successful responses\n \n Returns:\n Parsed response data\n \n Raises:\n ValueError: For parsing errors\n \"\"\"\n if not response.content:\n return None\n\n try:\n data = response.json()\n \n if success_model:\n if isinstance(data, list):\n return [success_model(**item) for item in data]\n else:\n return success_model(**data)\n \n return data\n \n except Exception as e:\n self.logger.error(f\"Failed to parse success response: {e}\")\n raise ValueError(f\"Failed to parse response: {e}\")\n\n async def _handle_error_response(\n self, \n response: httpx.Response, \n error_model: Optional[type] = None\n ) -> None:\n \"\"\"Handle error response.\n \n Args:\n response: HTTP response\n error_model: Pydantic model for error responses\n \n Raises:\n ErrorResponse: Always raises with error details\n \"\"\"\n error_data = {}\n \n if response.content:\n try:\n error_data = response.json()\n except Exception:\n # Fallback to text content if JSON parsing fails\n error_data = {'message': response.text}\n\n if error_model:\n try:\n error = error_model(**error_data)\n raise ErrorResponse(error, response.status_code, dict(response.headers))\n except Exception as e:\n self.logger.warning(f\"Failed to parse error with model {error_model}: {e}\")\n\n raise ErrorResponse(error_data, response.status_code, dict(response.headers))\n\n async def stream(self, response: httpx.Response) -> httpx.Response:\n \"\"\"Return streaming response as-is.\n \n Args:\n response: HTTP response\n \n Returns:\n The unmodified streaming response\n \"\"\"\n return response\n\n async def text(self, response: httpx.Response) -> str:\n \"\"\"Get response as text.\n \n Args:\n response: HTTP response\n \n Returns:\n Response body as text\n \n Raises:\n ErrorResponse: For HTTP error status codes\n \"\"\"\n # Process response interceptors\n processed_response = response\n for interceptor in self.interceptors:\n processed_response = await interceptor.process_response(processed_response)\n\n if 200 <= processed_response.status_code < 300:\n return processed_response.text\n else:\n error_data = {'message': processed_response.text}\n raise ErrorResponse(error_data, processed_response.status_code, dict(processed_response.headers))\n\n async def bytes(self, response: httpx.Response) -> bytes:\n \"\"\"Get response as bytes.\n \n Args:\n response: HTTP response\n \n Returns:\n Response body as bytes\n \n Raises:\n ErrorResponse: For HTTP error status codes\n \"\"\"\n # Process response interceptors\n processed_response = response\n for interceptor in self.interceptors:\n processed_response = await interceptor.process_response(processed_response)\n\n if 200 <= processed_response.status_code < 300:\n return processed_response.content\n else:\n error_data = {'message': 'Binary response error'}\n raise ErrorResponse(error_data, processed_response.status_code, dict(processed_response.headers))\n\n\n# Convenience functions for common use cases\nasync def quick_request(\n method: str,\n url: str,\n interceptors: Optional[List[Interceptor]] = None,\n **kwargs\n) -> httpx.Response:\n \"\"\"Make a quick HTTP request with interceptors.\n \n Args:\n method: HTTP method\n url: Request URL\n interceptors: List of interceptors to apply\n **kwargs: Additional request configuration\n \n Returns:\n HTTP response\n \"\"\"\n config = RequestConfig(method=method, url=url, **kwargs)\n \n async with Dispatcher(interceptors=interceptors) as dispatcher:\n return await dispatcher.request(config)\n\n\nasync def quick_json_request(\n method: str,\n url: str,\n json_data: Optional[Dict[str, Any]] = None,\n interceptors: Optional[List[Interceptor]] = None,\n success_model: Optional[type] = None,\n error_model: Optional[type] = None,\n **kwargs\n) -> Any:\n \"\"\"Make a quick JSON HTTP request with interceptors.\n \n Args:\n method: HTTP method\n url: Request URL\n json_data: JSON data to send\n interceptors: List of interceptors to apply\n success_model: Pydantic model for successful responses\n error_model: Pydantic model for error responses\n **kwargs: Additional request configuration\n \n Returns:\n Parsed JSON response\n \"\"\"\n config = RequestConfig(method=method, url=url, json_data=json_data, **kwargs)\n \n async with Dispatcher(interceptors=interceptors) as dispatcher:\n response = await dispatcher.request(config)\n receiver = Receiver(interceptors=interceptors)\n return await receiver.json(response, success_model, error_model)\n", "\"\"\"HTTP interceptors for request/response processing.\"\"\"\n\nimport asyncio\nimport logging\nimport time\nfrom abc import ABC, abstractmethod\nfrom typing import Dict, Optional, List, Any, Union\nfrom urllib.parse import urljoin\n\nimport httpx\n\nfrom .dispatcher import RequestConfig\n\n\nclass Interceptor(ABC):\n \"\"\"Base class for HTTP interceptors.\"\"\"\n\n @abstractmethod\n async def process_request(self, config: RequestConfig) -> RequestConfig:\n \"\"\"Process an outgoing request.\n\n Args:\n config: The request configuration to process\n\n Returns:\n The modified request configuration\n \"\"\"\n pass\n\n @abstractmethod\n async def process_response(self, response: httpx.Response) -> httpx.Response:\n \"\"\"Process an incoming response.\n\n Args:\n response: The HTTP response to process\n\n Returns:\n The processed response\n \"\"\"\n pass\n\n\nclass BaseUrlInterceptor(Interceptor):\n \"\"\"Interceptor that prepends base URL to relative URLs.\"\"\"\n\n def __init__(self, base_url: str):\n \"\"\"Initialize the base URL interceptor.\n\n Args:\n base_url: The base URL to prepend to relative URLs\n \"\"\"\n self.base_url = base_url.rstrip('/')\n\n async def process_request(self, config: RequestConfig) -> RequestConfig:\n \"\"\"Prepend base URL if the request URL is relative.\n\n Args:\n config: The request configuration\n\n Returns:\n The modified request configuration with absolute URL\n \"\"\"\n if not config.url.startswith(('http://', 'https://')):\n # Use urljoin for proper URL joining, ensuring single slash\n config.url = urljoin(self.base_url + '/', config.url.lstrip('/'))\n return config\n\n async def process_response(self, response: httpx.Response) -> httpx.Response:\n \"\"\"Pass through response unchanged.\n\n Args:\n response: The HTTP response\n\n Returns:\n The unmodified response\n \"\"\"\n return response\n\n\nclass LoggingInterceptor(Interceptor):\n \"\"\"Interceptor that logs requests and responses using Python's logging module.\"\"\"\n\n def __init__(\n self,\n enabled: bool = True,\n logger: Optional[logging.Logger] = None,\n log_level: int = logging.INFO,\n include_headers: bool = True,\n include_sensitive_headers: bool = False\n ):\n \"\"\"Initialize the logging interceptor.\n\n Args:\n enabled: Whether logging is enabled\n logger: Custom logger instance (creates default if None)\n log_level: Logging level to use\n include_headers: Whether to log request/response headers\n include_sensitive_headers: Whether to log sensitive headers like Authorization\n \"\"\"\n self.enabled = enabled\n self.logger = logger or logging.getLogger(__name__)\n self.log_level = log_level\n self.include_headers = include_headers\n self.include_sensitive_headers = include_sensitive_headers\n self._sensitive_headers = {'authorization', 'x-api-key', 'cookie', 'set-cookie'}\n\n async def process_request(self, config: RequestConfig) -> RequestConfig:\n \"\"\"Log outgoing request.\n\n Args:\n config: The request configuration\n\n Returns:\n The unmodified request configuration\n \"\"\"\n if not self.enabled:\n return config\n\n self.logger.log(self.log_level, f\"\u2192 {config.method.upper()} {config.url}\")\n\n if self.include_headers and config.headers:\n for key, value in config.headers.items():\n if (key.lower() in self._sensitive_headers and\n not self.include_sensitive_headers):\n self.logger.log(self.log_level, f\" {key}: [REDACTED]\")\n else:\n self.logger.log(self.log_level, f\" {key}: {value}\")\n\n return config\n\n async def process_response(self, response: httpx.Response) -> httpx.Response:\n \"\"\"Log incoming response.\n\n Args:\n response: The HTTP response\n\n Returns:\n The unmodified response\n \"\"\"\n if not self.enabled:\n return response\n\n status_icon = \"\u2713\" if 200 <= response.status_code < 300 else \"\u2717\"\n self.logger.log(\n self.log_level,\n f\"\u2190 {status_icon} {response.status_code} {response.reason_phrase or ''}\"\n )\n\n if self.include_headers and response.headers:\n for key, value in response.headers.items():\n if (key.lower() in self._sensitive_headers and\n not self.include_sensitive_headers):\n self.logger.log(self.log_level, f\" {key}: [REDACTED]\")\n else:\n self.logger.log(self.log_level, f\" {key}: {value}\")\n\n return response\n\n\nclass AuthInterceptor(Interceptor):\n \"\"\"Interceptor that adds authentication headers.\"\"\"\n\n def __init__(\n self,\n token: Optional[str] = None,\n api_key: Optional[str] = None,\n api_key_header: str = 'X-API-Key',\n auth_type: str = 'Bearer'\n ):\n \"\"\"Initialize the authentication interceptor.\n\n Args:\n token: Bearer token for Authorization header\n api_key: API key value\n api_key_header: Header name for API key\n auth_type: Type of authentication (Bearer, Basic, etc.)\n \"\"\"\n self.token = token\n self.api_key = api_key\n self.api_key_header = api_key_header\n self.auth_type = auth_type\n\n async def process_request(self, config: RequestConfig) -> RequestConfig:\n \"\"\"Add authentication headers.\n\n Args:\n config: The request configuration\n\n Returns:\n The modified request configuration with auth headers\n \"\"\"\n if config.headers is None:\n config.headers = {}\n\n if self.token:\n config.headers['Authorization'] = f'{self.auth_type} {self.token}'\n elif self.api_key:\n config.headers[self.api_key_header] = self.api_key\n\n return config\n\n async def process_response(self, response: httpx.Response) -> httpx.Response:\n \"\"\"Pass through response unchanged.\n\n Args:\n response: The HTTP response\n\n Returns:\n The unmodified response\n \"\"\"\n return response\n\n\nclass RetryInterceptor(Interceptor):\n \"\"\"Interceptor that retries failed requests with exponential backoff.\"\"\"\n\n def __init__(\n self,\n max_retries: int = 3,\n retry_delay: float = 1.0,\n backoff_factor: float = 2.0,\n retry_on_status: Optional[List[int]] = None,\n retry_on_exceptions: Optional[List[type]] = None\n ):\n \"\"\"Initialize the retry interceptor.\n\n Args:\n max_retries: Maximum number of retry attempts\n retry_delay: Initial delay between retries in seconds\n backoff_factor: Exponential backoff multiplier\n retry_on_status: HTTP status codes that should trigger retries\n retry_on_exceptions: Exception types that should trigger retries\n \"\"\"\n self.max_retries = max_retries\n self.retry_delay = retry_delay\n self.backoff_factor = backoff_factor\n self.retry_on_status = retry_on_status or [500, 502, 503, 504, 408, 429]\n self.retry_on_exceptions = retry_on_exceptions or [\n httpx.TimeoutException,\n httpx.ConnectError,\n httpx.RemoteProtocolError\n ]\n self._original_request_func = None\n self.logger = logging.getLogger(__name__)\n\n async def process_request(self, config: RequestConfig) -> RequestConfig:\n \"\"\"Store original request for potential retries.\n\n Args:\n config: The request configuration\n\n Returns:\n The unmodified request configuration\n \"\"\"\n # Store the original config for retries\n self._original_config = config.model_copy() if hasattr(config, 'model_copy') else config\n return config\n\n async def process_response(self, response: httpx.Response) -> httpx.Response:\n \"\"\"Check if response needs retry and handle accordingly.\n\n Args:\n response: The HTTP response\n\n Returns:\n The response (possibly after retries)\n \"\"\"\n # For retry logic to work properly, it needs to be integrated at the dispatcher level\n # This is a simplified version that just passes through\n # In a full implementation, the retry logic would need access to the original request method\n return response\n\n async def execute_with_retry(self, request_func, *args, **kwargs) -> httpx.Response:\n \"\"\"Execute a request function with retry logic.\n\n Args:\n request_func: Function that executes the HTTP request\n *args: Arguments to pass to request_func\n **kwargs: Keyword arguments to pass to request_func\n\n Returns:\n The HTTP response after potential retries\n\n Raises:\n The last exception encountered if all retries fail\n \"\"\"\n last_exception = None\n\n for attempt in range(self.max_retries + 1):\n try:\n response = await request_func(*args, **kwargs)\n\n # Check if response status requires retry\n if response.status_code not in self.retry_on_status:\n return response\n\n if attempt == self.max_retries:\n self.logger.warning(\n f\"Max retries ({self.max_retries}) reached for request. \"\n f\"Final status: {response.status_code}\"\n )\n return response\n\n # Wait before retry\n delay = self.retry_delay * (self.backoff_factor ** attempt)\n self.logger.info(\n f\"Retrying request (attempt {attempt + 1}/{self.max_retries + 1}) \"\n f\"after {delay:.2f}s due to status {response.status_code}\"\n )\n await asyncio.sleep(delay)\n\n except Exception as e:\n # Check if exception type requires retry\n if not any(isinstance(e, exc_type) for exc_type in self.retry_on_exceptions):\n raise e\n\n last_exception = e\n\n if attempt == self.max_retries:\n self.logger.error(\n f\"Max retries ({self.max_retries}) reached. \"\n f\"Final exception: {type(e).__name__}: {e}\"\n )\n raise e\n\n # Wait before retry\n delay = self.retry_delay * (self.backoff_factor ** attempt)\n self.logger.info(\n f\"Retrying request (attempt {attempt + 1}/{self.max_retries + 1}) \"\n f\"after {delay:.2f}s due to {type(e).__name__}: {e}\"\n )\n await asyncio.sleep(delay)\n\n\nclass UserAgentInterceptor(Interceptor):\n \"\"\"Interceptor that adds a User-Agent header.\"\"\"\n\n def __init__(self, user_agent: str):\n \"\"\"Initialize the User-Agent interceptor.\n\n Args:\n user_agent: The User-Agent string to set\n \"\"\"\n self.user_agent = user_agent\n\n async def process_request(self, config: RequestConfig) -> RequestConfig:\n \"\"\"Add User-Agent header if not already present.\n\n Args:\n config: The request configuration\n\n Returns:\n The modified request configuration with User-Agent header\n \"\"\"\n if config.headers is None:\n config.headers = {}\n\n # Only set User-Agent if not already present (case-insensitive check)\n has_user_agent = any(\n key.lower() == 'user-agent'\n for key in config.headers.keys()\n )\n\n if not has_user_agent:\n config.headers['User-Agent'] = self.user_agent\n\n return config\n\n async def process_response(self, response: httpx.Response) -> httpx.Response:\n \"\"\"Pass through response unchanged.\n\n Args:\n response: The HTTP response\n\n Returns:\n The unmodified response\n \"\"\"\n return response\n\n\nclass TimeoutInterceptor(Interceptor):\n \"\"\"Interceptor that sets request timeouts.\"\"\"\n\n def __init__(self, timeout: Union[float, httpx.Timeout]):\n \"\"\"Initialize the timeout interceptor.\n\n Args:\n timeout: Timeout value in seconds or httpx.Timeout object\n \"\"\"\n self.timeout = timeout\n\n async def process_request(self, config: RequestConfig) -> RequestConfig:\n \"\"\"Set timeout for the request.\n\n Args:\n config: The request configuration\n\n Returns:\n The modified request configuration with timeout\n \"\"\"\n if config.timeout is None:\n config.timeout = self.timeout\n return config\n\n async def process_response(self, response: httpx.Response) -> httpx.Response:\n \"\"\"Pass through response unchanged.\n\n Args:\n response: The HTTP response\n\n Returns:\n The unmodified response\n \"\"\"\n return response\n\n\nclass RateLimitInterceptor(Interceptor):\n \"\"\"Interceptor that implements client-side rate limiting.\"\"\"\n\n def __init__(self, max_requests: int, time_window: float = 60.0):\n \"\"\"Initialize the rate limit interceptor.\n\n Args:\n max_requests: Maximum number of requests allowed in the time window\n time_window: Time window in seconds\n \"\"\"\n self.max_requests = max_requests\n self.time_window = time_window\n self.requests = []\n self._lock = asyncio.Lock()\n\n async def process_request(self, config: RequestConfig) -> RequestConfig:\n \"\"\"Apply rate limiting before request.\n\n Args:\n config: The request configuration\n\n Returns:\n The unmodified request configuration\n \"\"\"\n async with self._lock:\n now = time.time()\n\n # Remove requests outside the time window\n self.requests = [req_time for req_time in self.requests\n if now - req_time < self.time_window]\n\n # Check if we've exceeded the rate limit\n if len(self.requests) >= self.max_requests:\n # Calculate how long to wait\n oldest_request = min(self.requests)\n wait_time = self.time_window - (now - oldest_request)\n\n if wait_time > 0:\n await asyncio.sleep(wait_time)\n\n # Record this request\n self.requests.append(now)\n\n return config\n\n async def process_response(self, response: httpx.Response) -> httpx.Response:\n \"\"\"Pass through response unchanged.\n\n Args:\n response: The HTTP response\n\n Returns:\n The unmodified response\n \"\"\"\n return response\n\n\n# Factory functions for convenient interceptor creation\ndef create_base_url_interceptor(base_url: str) -> BaseUrlInterceptor:\n \"\"\"Create a BaseUrlInterceptor instance.\n\n Args:\n base_url: The base URL to prepend to relative URLs\n\n Returns:\n Configured BaseUrlInterceptor instance\n \"\"\"\n return BaseUrlInterceptor(base_url)\n\n\ndef create_logging_interceptor(\n enabled: bool = True,\n log_level: int = logging.INFO,\n include_headers: bool = True,\n include_sensitive_headers: bool = False\n) -> LoggingInterceptor:\n \"\"\"Create a LoggingInterceptor instance.\n\n Args:\n enabled: Whether logging is enabled\n log_level: Logging level to use\n include_headers: Whether to log headers\n include_sensitive_headers: Whether to log sensitive headers\n\n Returns:\n Configured LoggingInterceptor instance\n \"\"\"\n return LoggingInterceptor(\n enabled=enabled,\n log_level=log_level,\n include_headers=include_headers,\n include_sensitive_headers=include_sensitive_headers\n )\n\n\ndef create_auth_interceptor(\n token: Optional[str] = None,\n api_key: Optional[str] = None,\n api_key_header: str = 'X-API-Key',\n auth_type: str = 'Bearer'\n) -> AuthInterceptor:\n \"\"\"Create an AuthInterceptor instance.\n\n Args:\n token: Bearer token for Authorization header\n api_key: API key value\n api_key_header: Header name for API key\n auth_type: Type of authentication\n\n Returns:\n Configured AuthInterceptor instance\n \"\"\"\n return AuthInterceptor(\n token=token,\n api_key=api_key,\n api_key_header=api_key_header,\n auth_type=auth_type\n )\n\n\ndef create_retry_interceptor(\n max_retries: int = 3,\n retry_delay: float = 1.0,\n backoff_factor: float = 2.0,\n retry_on_status: Optional[List[int]] = None\n) -> RetryInterceptor:\n \"\"\"Create a RetryInterceptor instance.\n\n Args:\n max_retries: Maximum number of retry attempts\n retry_delay: Initial delay between retries in seconds\n backoff_factor: Exponential backoff multiplier\n retry_on_status: HTTP status codes that should trigger retries\n\n Returns:\n Configured RetryInterceptor instance\n \"\"\"\n return RetryInterceptor(\n max_retries=max_retries,\n retry_delay=retry_delay,\n backoff_factor=backoff_factor,\n retry_on_status=retry_on_status\n )\n\n\ndef create_user_agent_interceptor(user_agent: str) -> UserAgentInterceptor:\n \"\"\"Create a UserAgentInterceptor instance.\n\n Args:\n user_agent: The User-Agent string to set\n\n Returns:\n Configured UserAgentInterceptor instance\n \"\"\"\n return UserAgentInterceptor(user_agent)\n", "\"\"\"HTTP response models and exceptions.\"\"\"\n\nfrom typing import Any, Dict, Optional, Union\n\nimport httpx\nfrom pydantic import BaseModel\n\n\nclass ApiResponse(BaseModel):\n \"\"\"Base class for API responses.\"\"\"\n\n status_code: int\n headers: Dict[str, str]\n data: Any\n\n class Config:\n \"\"\"Pydantic configuration.\"\"\"\n arbitrary_types_allowed = True\n\n\nclass SuccessResponse(ApiResponse):\n \"\"\"Represents a successful API response.\"\"\"\n\n def __init__(self, data: Any, status_code: int = 200, headers: Optional[Dict[str, str]] = None):\n \"\"\"Initialize success response.\n\n Args:\n data: Response data\n status_code: HTTP status code\n headers: Response headers\n \"\"\"\n super().__init__(\n status_code=status_code,\n headers=headers or {},\n data=data\n )\n\n\nclass ErrorResponse(Exception):\n \"\"\"Exception raised for HTTP error responses.\"\"\"\n\n def __init__(\n self,\n data: Any,\n status_code: int,\n headers: Optional[Dict[str, str]] = None,\n message: Optional[str] = None\n ):\n \"\"\"Initialize error response.\n\n Args:\n data: Error response data\n status_code: HTTP status code\n headers: Response headers\n message: Custom error message\n \"\"\"\n self.data = data\n self.status_code = status_code\n self.headers = headers or {}\n self.message = message or f\"HTTP {status_code} Error\"\n\n super().__init__(self.message)\n\n def __str__(self) -> str:\n \"\"\"String representation of the error.\"\"\"\n return f\"ErrorResponse(status_code={self.status_code}, message='{self.message}')\"\n\n def __repr__(self) -> str:\n \"\"\"Detailed string representation of the error.\"\"\"\n return (\n f\"ErrorResponse(status_code={self.status_code}, \"\n f\"message='{self.message}', data={self.data})\"\n )\n\n\nclass TimeoutError(ErrorResponse):\n \"\"\"Exception raised for request timeouts.\"\"\"\n\n def __init__(self, message: str = \"Request timed out\"):\n \"\"\"Initialize timeout error.\n\n Args:\n message: Error message\n \"\"\"\n super().__init__(\n data={'error': 'timeout'},\n status_code=408,\n message=message\n )\n\n\nclass ConnectionError(ErrorResponse):\n \"\"\"Exception raised for connection errors.\"\"\"\n\n def __init__(self, message: str = \"Connection failed\"):\n \"\"\"Initialize connection error.\n\n Args:\n message: Error message\n \"\"\"\n super().__init__(\n data={'error': 'connection'},\n status_code=503,\n message=message\n )\n\n\nclass BadRequestError(ErrorResponse):\n \"\"\"Exception raised for 400 Bad Request errors.\"\"\"\n\n def __init__(self, data: Any = None, message: str = \"Bad Request\"):\n \"\"\"Initialize bad request error.\n\n Args:\n data: Error data\n message: Error message\n \"\"\"\n super().__init__(\n data=data or {'error': 'bad_request'},\n status_code=400,\n message=message\n )\n\n\nclass UnauthorizedError(ErrorResponse):\n \"\"\"Exception raised for 401 Unauthorized errors.\"\"\"\n\n def __init__(self, data: Any = None, message: str = \"Unauthorized\"):\n \"\"\"Initialize unauthorized error.\n\n Args:\n data: Error data\n message: Error message\n \"\"\"\n super().__init__(\n data=data or {'error': 'unauthorized'},\n status_code=401,\n message=message\n )\n\n\nclass ForbiddenError(ErrorResponse):\n \"\"\"Exception raised for 403 Forbidden errors.\"\"\"\n\n def __init__(self, data: Any = None, message: str = \"Forbidden\"):\n \"\"\"Initialize forbidden error.\n\n Args:\n data: Error data\n message: Error message\n \"\"\"\n super().__init__(\n data=data or {'error': 'forbidden'},\n status_code=403,\n message=message\n )\n\n\nclass NotFoundError(ErrorResponse):\n \"\"\"Exception raised for 404 Not Found errors.\"\"\"\n\n def __init__(self, data: Any = None, message: str = \"Not Found\"):\n \"\"\"Initialize not found error.\n\n Args:\n data: Error data\n message: Error message\n \"\"\"\n super().__init__(\n data=data or {'error': 'not_found'},\n status_code=404,\n message=message\n )\n\n\nclass InternalServerError(ErrorResponse):\n \"\"\"Exception raised for 500 Internal Server Error.\"\"\"\n\n def __init__(self, data: Any = None, message: str = \"Internal Server Error\"):\n \"\"\"Initialize internal server error.\n\n Args:\n data: Error data\n message: Error message\n \"\"\"\n super().__init__(\n data=data or {'error': 'internal_server_error'},\n status_code=500,\n message=message\n )\n\n\ndef create_error_from_response(response: httpx.Response) -> ErrorResponse:\n \"\"\"Create appropriate error exception from HTTP response.\n\n Args:\n response: HTTP response\n\n Returns:\n Appropriate error exception\n \"\"\"\n status_code = response.status_code\n headers = dict(response.headers)\n\n # Try to parse error data\n try:\n data = response.json()\n except Exception:\n data = {'message': response.text}\n\n # Create specific error types based on status code\n error_classes = {\n 400: BadRequestError,\n 401: UnauthorizedError,\n 403: ForbiddenError,\n 404: NotFoundError,\n 500: InternalServerError,\n }\n\n error_class = error_classes.get(status_code, ErrorResponse)\n\n if error_class == ErrorResponse:\n return ErrorResponse(data, status_code, headers)\n else:\n return error_class(data)\n", "import type { ReferenceObject, SchemaObject } from 'openapi3-ts/oas31';\nimport { snakecase } from 'stringcase';\n\nimport {\n followRef,\n isEmpty,\n isRef,\n notRef,\n parseRef,\n pascalcase,\n} from '@sdk-it/core';\nimport { type IR, isPrimitiveSchema } from '@sdk-it/spec';\n\nexport function coerceObject(schema: SchemaObject): SchemaObject {\n schema = structuredClone(schema);\n if (schema['x-properties']) {\n schema.properties = {\n ...(schema.properties ?? {}),\n ...(schema['x-properties'] ?? {}),\n };\n }\n if (schema['x-required']) {\n schema.required = Array.from(\n new Set([\n ...(Array.isArray(schema.required) ? schema.required : []),\n ...(schema['x-required'] || []),\n ]),\n );\n }\n return schema;\n}\n\ntype Context = Record<string, unknown>;\ntype Serialized = {\n nullable?: boolean;\n encode?: string;\n encodeV2?: string;\n use: string;\n matches?: string;\n fromJson: unknown;\n type?: string;\n literal?: unknown;\n content: string;\n simple?: boolean;\n impossible?: boolean;\n};\ntype Emit = (name: string, content: string, schema: SchemaObject) => void;\n\n/**\n * Convert an OpenAPI (JSON Schema style) object into Python classes with Pydantic\n */\nexport class PythonEmitter {\n #spec: IR;\n #emitHandler?: Emit;\n #emitHistory = new Set<string>();\n #typeCache = new Map<string, Serialized>(); // Cache for resolved types\n\n #emit(name: string, content: string, schema: SchemaObject): void {\n if (this.#emitHistory.has(content)) {\n return;\n }\n this.#emitHistory.add(content);\n this.#emitHandler?.(name, content, schema);\n }\n\n constructor(spec: IR) {\n this.#spec = spec;\n }\n\n onEmit(emit: Emit): void {\n this.#emitHandler = emit;\n }\n\n #formatFieldName(name: string): string {\n // Convert to snake_case and handle special cases\n let fieldName = snakecase(name);\n\n // Handle reserved keywords\n const reservedKeywords = [\n 'class',\n 'def',\n 'if',\n 'else',\n 'elif',\n 'while',\n 'for',\n 'try',\n 'except',\n 'finally',\n 'with',\n 'as',\n 'import',\n 'from',\n 'global',\n 'nonlocal',\n 'lambda',\n 'yield',\n 'return',\n 'pass',\n 'break',\n 'continue',\n 'True',\n 'False',\n 'None',\n 'and',\n 'or',\n 'not',\n 'in',\n 'is',\n ];\n\n if (reservedKeywords.includes(fieldName)) {\n fieldName = `${fieldName}_`;\n }\n\n return fieldName;\n }\n\n #isBottom(schema: SchemaObject | ReferenceObject | undefined): boolean {\n if (!schema) {\n return false;\n }\n const resolved = isRef(schema)\n ? followRef<SchemaObject>(this.#spec, schema.$ref)\n : schema;\n return !!resolved.not && isEmpty(resolved.not);\n }\n\n #ref(ref: ReferenceObject, context: Context = {}): Serialized {\n const schema = followRef<SchemaObject>(this.#spec, ref.$ref);\n if (\n this.#isBottom(schema) ||\n (schema.type === 'array' && this.#isBottom(schema.items))\n ) {\n return this.handle(schema, context);\n }\n\n const cacheKey = ref.$ref;\n const cached = this.#typeCache.get(cacheKey);\n if (cached) {\n return cached;\n }\n\n const refInfo = parseRef(ref.$ref);\n const refName = refInfo.model;\n const className = pascalcase(refName);\n\n const result: Serialized = {\n type: className,\n content: '',\n use: className,\n fromJson: `${className}.parse_obj`,\n simple: false,\n };\n\n this.#typeCache.set(cacheKey, result);\n return result;\n }\n\n #oneOf(\n variants: (SchemaObject | ReferenceObject)[],\n context: Context,\n ): Serialized {\n const variantTypes = variants\n .map((variant) => this.handle(variant, context))\n .map((result) => result.type || 'Any')\n .filter((type, index, arr) => arr.indexOf(type) === index); // Remove duplicates\n\n if (variantTypes.length === 0) {\n return {\n type: 'Any',\n content: '',\n use: 'Any',\n fromJson: 'Any',\n simple: true,\n };\n }\n\n if (variantTypes.length === 1) {\n return {\n type: variantTypes[0],\n content: '',\n use: variantTypes[0],\n fromJson: variantTypes[0],\n simple: true,\n };\n }\n\n const unionType = `Union[${variantTypes.join(', ')}]`;\n return {\n type: unionType,\n content: '',\n use: unionType,\n fromJson: unionType,\n simple: true,\n };\n }\n\n #object(\n className: string,\n schema: SchemaObject,\n context: Context,\n ): Serialized {\n const { properties = {}, required = [] } = coerceObject(schema);\n\n const fields: string[] = [];\n\n // Handle allOf inheritance\n let baseClass = 'BaseModel';\n if (schema.allOf) {\n const bases = schema.allOf\n .filter(notRef)\n .map((s) => this.handle(s, context))\n .filter((result) => result.type)\n .map((result) => result.type);\n\n if (bases.length > 0 && bases[0]) {\n baseClass = bases[0];\n }\n }\n\n // Process properties\n for (const [propName, propSchema] of Object.entries(properties)) {\n if (isRef(propSchema)) {\n const result = this.#ref(propSchema, context);\n const pythonType = result.type || 'Any';\n\n const fieldName = this.#formatFieldName(propName);\n const isRequired = required.includes(propName);\n const fieldType =\n isRequired || result.impossible\n ? pythonType\n : `Optional[${pythonType}]`;\n const defaultValue = isRequired\n ? ''\n : result.impossible\n ? ' = Field(default=None, exclude=True)'\n : ' = None';\n\n fields.push(` ${fieldName}: ${fieldType}${defaultValue}`);\n } else {\n const result = this.handle(propSchema, { ...context, name: propName });\n const fieldName = this.#formatFieldName(propName);\n const isRequired = required.includes(propName);\n\n let fieldType = result.type || 'Any';\n if (!isRequired && !result.impossible) {\n fieldType = `Optional[${fieldType}]`;\n }\n\n const defaultValue = isRequired\n ? ''\n : result.impossible\n ? ' = Field(default=None, exclude=True)'\n : ' = None';\n let fieldDef = ` ${fieldName}: ${fieldType}${defaultValue}`;\n\n // Add Field() for alias or validation if needed\n if (fieldName !== propName) {\n fieldDef = ` ${fieldName}: ${fieldType} = Field(alias='${propName}'${isRequired ? '' : ', default=None'}${!isRequired && result.impossible ? ', exclude=True' : ''})`;\n }\n\n // Add description as comment if available\n if (propSchema.description) {\n fieldDef += ` # ${propSchema.description}`;\n }\n\n fields.push(fieldDef);\n }\n }\n\n // Handle oneOf/anyOf as Union types using centralized logic\n if (schema.oneOf || schema.anyOf) {\n const unionResult = this.#oneOf(\n schema.oneOf || schema.anyOf || [],\n context,\n );\n fields.push(` value: ${unionResult.type}`);\n }\n\n // Handle additionalProperties\n if (\n schema.additionalProperties &&\n typeof schema.additionalProperties === 'object'\n ) {\n const addlResult = this.handle(schema.additionalProperties, context);\n fields.push(\n ` additional_properties: Optional[Dict[str, ${addlResult.type || 'Any'}]] = None`,\n );\n }\n\n // Generate class docstring\n const docstring = schema.description\n ? ` \"\"\"${schema.description}\"\"\"\\n`\n : '';\n\n // Generate to_request_config method for input models\n let requestConfigMethod = '';\n if (schema['x-inputname']) {\n requestConfigMethod = `\n def to_request_config(self, config: RequestConfig) -> RequestConfig:\n \"\"\"Convert this input model to request configuration.\"\"\"\n # Handle path parameters\n path_params = {}\n for key, value in self.dict(exclude_none=True).items():\n if key in config.url:\n path_params[key] = str(value)\n config.url = config.url.replace(f'{{{key}}}', str(value))\n\n # Handle query parameters\n query_params = {k: v for k, v in self.dict(exclude_none=True).items()\n if k not in path_params}\n if query_params:\n config.params = query_params\n\n return config\n`;\n }\n\n const content = `class ${className}(${baseClass}):\n${docstring}${fields.length > 0 ? fields.join('\\n') : ' pass'}${requestConfigMethod}\n`;\n\n this.#emit(className, content, schema);\n\n return {\n type: className,\n content,\n use: className,\n fromJson: `${className}.parse_obj`,\n simple: false,\n };\n }\n\n #primitive(schema: SchemaObject): Serialized {\n const { type, format } = schema;\n const nullable = (schema as { nullable?: boolean }).nullable; // Handle nullable as it may not be in the type definition\n\n let pythonType = 'Any';\n\n switch (type) {\n case 'string':\n if (format === 'date-time') {\n pythonType = 'datetime';\n } else if (format === 'date') {\n pythonType = 'date';\n } else if (format === 'uuid') {\n pythonType = 'UUID';\n } else if (format === 'binary' || format === 'byte') {\n pythonType = 'bytes';\n } else {\n pythonType = 'str';\n }\n break;\n\n case 'integer':\n if (format === 'int64') {\n pythonType = 'int'; // Python 3 ints are arbitrary precision\n } else {\n pythonType = 'int';\n }\n break;\n\n case 'number':\n pythonType = 'float';\n break;\n\n case 'boolean':\n pythonType = 'bool';\n break;\n\n default:\n pythonType = 'Any';\n }\n\n if (nullable) {\n pythonType = `Optional[${pythonType}]`;\n }\n\n return {\n type: pythonType,\n content: '',\n use: pythonType,\n fromJson: pythonType,\n simple: true,\n nullable,\n };\n }\n\n #array(schema: SchemaObject, context: Context): Serialized {\n const itemsSchema = schema.items;\n if (!itemsSchema) {\n return {\n type: 'List[Any]',\n content: '',\n use: 'List[Any]',\n fromJson: 'list',\n simple: true,\n };\n }\n\n const itemsResult = this.handle(itemsSchema, context);\n const listType = `List[${itemsResult.type || 'Any'}]`;\n\n return {\n type: listType,\n content: itemsResult.content,\n use: listType,\n fromJson: `List[${itemsResult.fromJson || itemsResult.type}]`,\n simple: true,\n };\n }\n\n #enum(schema: SchemaObject, _context: Context): Serialized {\n const { enum: enumValues } = schema;\n if (!enumValues || enumValues.length === 0) {\n return this.#primitive(schema);\n }\n\n if (!_context.name || typeof _context.name !== 'string') {\n throw new Error('Enum schemas must have a name in context');\n }\n\n const className = pascalcase(_context.name as string);\n\n const enumItems = enumValues.map((value, index) => {\n const name =\n typeof value === 'string'\n ? value.toUpperCase().replace(/[^A-Z0-9]/g, '_')\n : `VALUE_${index}`;\n\n const pythonValue =\n typeof value === 'string' ? `'${value}'` : String(value);\n return ` ${name} = ${pythonValue}`;\n });\n\n const content = `class ${className}(Enum):\n \"\"\"Enumeration for ${_context.name}.\"\"\"\n${enumItems.join('\\n')}\n`;\n\n this.#emit(className, content, schema);\n\n return {\n type: className,\n content,\n use: className,\n fromJson: className,\n simple: false,\n };\n }\n\n #const(schema: SchemaObject): Serialized {\n const { const: constValue } = schema;\n\n if (typeof constValue === 'string') {\n return {\n type: `Literal['${constValue}']`,\n content: '',\n use: `Literal['${constValue}']`,\n fromJson: `'${constValue}'`,\n simple: true,\n literal: constValue,\n };\n }\n\n return {\n type: `Literal[${JSON.stringify(constValue)}]`,\n content: '',\n use: `Literal[${JSON.stringify(constValue)}]`,\n fromJson: JSON.stringify(constValue),\n simple: true,\n literal: constValue,\n };\n }\n handle(\n schema: SchemaObject | ReferenceObject,\n context: Context = {},\n ): Serialized {\n if (isRef(schema)) {\n return this.#ref(schema, context);\n }\n\n if (schema.not && isEmpty(schema.not)) {\n const type = context.pydantic === true ? '_NeverValue' : 'Never';\n return {\n type,\n content: '',\n use: type,\n fromJson: type,\n simple: true,\n impossible: true,\n };\n }\n\n // Handle const values\n if ('const' in schema && schema.const !== undefined) {\n return this.#const(schema);\n }\n\n // Handle enums\n if (schema.enum) {\n return this.#enum(schema, context);\n }\n\n // Handle arrays\n if (schema.type === 'array') {\n return this.#array(schema, context);\n }\n\n // Handle oneOf/anyOf at top level using centralized logic\n if (schema.oneOf || schema.anyOf) {\n return this.#oneOf(schema.oneOf || schema.anyOf || [], context);\n }\n\n // Handle objects\n if (\n schema.type === 'object' ||\n schema.properties ||\n schema.allOf ||\n schema.oneOf ||\n schema.anyOf\n ) {\n if (!context.name || typeof context.name !== 'string') {\n throw new Error('Object schemas must have a name in context');\n }\n const className = pascalcase(context.name as string);\n return this.#object(className, schema, context);\n }\n\n // Handle primitives\n if (isPrimitiveSchema(schema)) {\n return this.#primitive(schema);\n }\n\n // Fallback to Any\n return {\n type: 'Any',\n content: '',\n use: 'Any',\n fromJson: 'Any',\n simple: true,\n };\n }\n}\n", "import { Command } from 'commander';\nimport { writeFile } from 'node:fs/promises';\n\nimport { toReadme } from '@sdk-it/readme';\nimport { loadSpec, toIR } from '@sdk-it/spec';\n\nimport { outputOption, specOption } from '../options.ts';\n\nexport default new Command('readme')\n .description('Generate README')\n .addOption(specOption.makeOptionMandatory(true))\n .addOption(outputOption.makeOptionMandatory(true))\n .action(async (options: { spec: string; output: string }) => {\n await runReadme(options.spec, options.output);\n });\n\nexport async function runReadme(specFile: string, output: string) {\n const spec = await toIR({ spec: await loadSpec(specFile) });\n const content = toReadme(spec);\n await writeFile(output, content, 'utf-8');\n}\n", "import { Command, Option } from 'commander';\nimport { publish } from 'libnpmpublish';\nimport { execFile, execSync, spawnSync } from 'node:child_process';\nimport { readFile } from 'node:fs/promises';\nimport { tmpdir } from 'node:os';\nimport { join } from 'node:path';\nimport type { OpenAPIObject } from 'openapi3-ts/oas31';\nimport getAuthToken from 'registry-auth-token';\n\nimport { writeFiles } from '@sdk-it/core/file-system.js';\nimport { loadSpec } from '@sdk-it/spec';\nimport { generate } from '@sdk-it/typescript';\n\nimport {\n outputOption,\n parseDotConfig,\n parsePagination,\n specOption,\n} from '../options.ts';\nimport type { TypeScriptOptions } from '../types.ts';\n\ntype Options = Omit<TypeScriptOptions, 'pagination'> & {\n output: string;\n pagination?: TypeScriptOptions['pagination'] | string;\n};\n\nexport default new Command('typescript')\n .alias('ts')\n .description('Generate TypeScript SDK')\n .addOption(specOption.makeOptionMandatory(true))\n .addOption(outputOption.makeOptionMandatory(false))\n .option(\n '--useTsExtension [value]',\n 'Use .ts extension for generated files',\n (value) => (value === 'false' ? false : true),\n true,\n )\n .option(\n '-m, --mode <mode>',\n 'full: generate a full project including package.json and tsconfig.json. useful for monorepo/workspaces minimal: generate only the client sdk',\n )\n .option('-n, --name <name>', 'Name of the generated client', 'Client')\n .option(\n '-f, --framework <framework>',\n 'Framework that is integrating with the SDK',\n )\n .option('--formatter <formatter>', 'Formatter to use for the generated code')\n .option(\n '--install',\n 'Install dependencies using npm (only in full mode)',\n true,\n )\n .option(\n '--readme <readme>',\n 'Generate a README file',\n (value) => (value === 'false' ? false : true),\n true,\n )\n .option('--no-default-formatter', 'Do not use the default formatter')\n .option('--no-install', 'Do not install dependencies')\n .option('-v, --verbose', 'Verbose output', false)\n .option(\n '--pagination <pagination>',\n 'Configure pagination (e.g., \"false\", \"true\", \"guess=false\")',\n 'true',\n )\n .addOption(\n new Option(\n '--publish <publish>',\n 'Publish the SDK to a package registry (npm, github, or a custom registry)',\n )\n .hideHelp(true)\n .makeOptionMandatory(false),\n )\n .action(async (options: Options) => {\n await runTypescript(options);\n });\n\nexport async function runTypescript(options: Options) {\n if (!options.publish && !options.output) {\n throw new Error('Error: --publish or --output option is required.');\n }\n const spec = await loadSpec(options.spec);\n\n if (options.output) {\n await emitLocal(spec, {\n ...options,\n output: options.output,\n });\n }\n if (options.publish) {\n await emitRemote(spec, {\n ...options,\n publish: options.publish,\n });\n }\n}\n\nasync function emitLocal(spec: OpenAPIObject, options: Options) {\n await generate(spec, {\n writer: writeFiles,\n output: options.output,\n mode: options.mode || 'minimal',\n name: options.name,\n pagination:\n typeof options.pagination === 'string'\n ? parsePagination(parseDotConfig(options.pagination ?? 'true'))\n : options.pagination,\n style: {\n name: 'github',\n },\n readme: options.readme,\n useTsExtension: options.useTsExtension,\n formatCode: ({ env, output }) => {\n if (options.formatter) {\n const [command, ...args] = options.formatter.split(' ');\n execFile(command, args, {\n env: { ...env, SDK_IT_OUTPUT: output },\n });\n } else if (options.defaultFormatter) {\n spawnSync('npx', ['-y', 'prettier', output, '--write'], {\n env: {\n ...env,\n SDK_IT_OUTPUT: output,\n },\n stdio: options.verbose ? 'inherit' : 'pipe',\n });\n }\n },\n });\n\n // Install dependencies if in full mode and install option is enabled\n if (options.install && options.mode === 'full') {\n console.log('Installing dependencies...');\n execSync('npm install', {\n cwd: options.output,\n stdio: options.verbose ? 'inherit' : 'pipe',\n });\n }\n}\n\nasync function emitRemote(\n spec: OpenAPIObject,\n options: Options & { publish: string },\n) {\n const registry =\n options.publish === 'npm'\n ? 'https://registry.npmjs.org/'\n : options.publish === 'github'\n ? 'https://npm.pkg.github.com/'\n : options.publish;\n\n console.log('Publishing to registry:', registry);\n const path = join(tmpdir(), crypto.randomUUID());\n await emitLocal(spec, {\n ...options,\n output: path,\n install: false,\n mode: 'full',\n });\n const manifest = JSON.parse(\n await readFile(join(path, 'package.json'), 'utf-8'),\n );\n const registryUrl = new URL(registry);\n const npmrc = process.env.NPM_TOKEN\n ? {\n npmrc: {\n registry,\n [`//${registryUrl.hostname}:_authToken`]: process.env.NPM_TOKEN,\n },\n }\n : registry;\n const auth = getAuthToken(npmrc);\n if (!auth || !auth.token) {\n throw new Error(\n 'No npm auth token found in .npmrc or environment. please provide NPM_TOKEN.',\n );\n }\n const packResult = execSync('npm pack --pack-destination .', { cwd: path });\n const [tgzName] = packResult.toString().trim().split('\\n');\n await publish(manifest, await readFile(join(path, tgzName)), {\n registry,\n defaultTag: 'latest',\n forceAuth: {\n token: auth.token,\n },\n strictSSL: true,\n preferOnline: true,\n });\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["Command", "readJson", "writeFile", "resolve", "resolve", "program", "writeFile", "join", "createRequire", "ts", "require", "readFile", "join", "ts", "program", "writeFile", "join", "access", "readFile", "writeFile", "join", "relative", "resolve", "resolve", "join", "relative", "readOptionalFile", "readFile", "writeFile", "access", "resolve", "resolve", "resolve", "exist", "join", "resolve", "writeFile", "Command", "dirname", "join", "Command", "join", "dirname", "Command", "generate", "Command", "generate", "Command", "execFile", "execSync", "readdir", "join", "snakecase", "followRef", "isEmpty", "isRef", "pascalcase", "generate", "input", "loadSpec", "toIR", "Command", "toIR", "loadSpec", "generate", "execFile", "execSync", "Command", "writeFile", "loadSpec", "toIR", "Command", "toIR", "loadSpec", "writeFile", "Command", "Option", "execFile", "execSync", "readFile", "join", "writeFiles", "loadSpec", "generate", "Command", "Option", "loadSpec", "generate", "writeFiles", "execFile", "execSync", "join", "readFile", "generate", "Command", "config", "readJson"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sdk-it/cli",
3
- "version": "0.46.0",
3
+ "version": "0.46.1",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
@@ -20,19 +20,19 @@
20
20
  "!**/*.test.*"
21
21
  ],
22
22
  "dependencies": {
23
- "@sdk-it/typescript": "0.46.0",
24
- "@sdk-it/dart": "0.46.0",
25
- "@sdk-it/spec": "0.46.0",
23
+ "@sdk-it/typescript": "0.46.1",
24
+ "@sdk-it/dart": "0.46.1",
25
+ "@sdk-it/spec": "0.46.1",
26
26
  "commander": "^13.1.0",
27
- "@sdk-it/core": "0.46.0",
28
- "@sdk-it/generic": "0.46.0",
29
- "@sdk-it/hono": "0.46.0",
27
+ "@sdk-it/core": "0.46.1",
28
+ "@sdk-it/generic": "0.46.1",
29
+ "@sdk-it/hono": "0.46.1",
30
30
  "libnpmpublish": "^11.0.0",
31
31
  "openapi3-ts": "4.5.0",
32
32
  "registry-auth-token": "^5.1.0",
33
- "@sdk-it/python": "0.46.0",
33
+ "@sdk-it/python": "0.46.1",
34
34
  "execa": "^9.6.0",
35
- "@sdk-it/readme": "0.46.0",
35
+ "@sdk-it/readme": "0.46.1",
36
36
  "@inquirer/prompts": "^7.7.1"
37
37
  },
38
38
  "peerDependencies": {