Skip to content
Source
Sign inSign up
Open History to see the last commit

Config.ts

255 lines5.9 KB

1/**
2 * Configuration schema and types for AI provider code generation.
3 *
4 * @since 4.0.0
5 */
6import * as Data from "effect/Data"
7import type * as Path from "effect/Path"
8import * as Schema from "effect/Schema"
9​
10/**
11 * A text replacement to apply to generated code.
12 *
13 * @category models
14 * @since 4.0.0
15 */
16export class Replacement extends Schema.Class<Replacement>("Replacement")({
17 from: Schema.String,
18 to: Schema.String
19}) {}
20​
21/**
22 * Configuration for AI provider code generation.
23 *
24 * **Example** (Decoding a codegen configuration)
25 *
26 * ```ts import.meta.vitest
27 * import * as Config from "@effect/ai-codegen/Config"
28 * import { Schema } from "effect"
29 *
30 * const config = Schema.decodeUnknownSync(Config.CodegenConfig)({
31 * spec: "https://example.com/openapi.json",
32 * output: "Generated.ts",
33 * name: "MyClient"
34 * })
35 *
36 * config.spec // => "https://example.com/openapi.json"
37 * ```
38 *
39 * @category models
40 * @since 4.0.0
41 */
42export class CodegenConfig extends Schema.Class<CodegenConfig>("CodegenConfig")({
43 spec: Schema.String,
44 output: Schema.String,
45 name: Schema.optional(Schema.String),
46 typeOnly: Schema.optional(Schema.Boolean),
47 header: Schema.optional(Schema.String),
48 patches: Schema.optional(Schema.Array(Schema.String)),
49 includePaths: Schema.optional(Schema.Array(Schema.String)),
50 includeSchemas: Schema.optional(Schema.Array(Schema.String)),
51 collapseErrorResponses: Schema.optional(Schema.Boolean),
52 replacements: Schema.optional(Schema.Array(Replacement)),
53 excludeAnnotations: Schema.optional(Schema.Array(Schema.String)),
54 disableAdditionalProperties: Schema.optional(Schema.Boolean)
55}) {
56 /**
57 * Get the client name, defaulting to "Client" if not specified.
58 *
59 * @since 4.0.0
60 */
61 get clientName(): string {
62 return this.name ?? "Client"
63 }
64​
65 /**
66 * Check if type-only generation is enabled.
67 *
68 * @since 4.0.0
69 */
70 get isTypeOnly(): boolean {
71 return this.typeOnly ?? false
72 }
73​
74 /**
75 * Get the list of patch files/strings to apply.
76 *
77 * @since 4.0.0
78 */
79 get patchList(): ReadonlyArray<string> {
80 return this.patches ?? []
81 }
82​
83 /**
84 * Get the list of text replacements to apply.
85 *
86 * @since 4.0.0
87 */
88 get replacementList(): ReadonlyArray<Replacement> {
89 return this.replacements ?? []
90 }
91​
92 /**
93 * Get the header content to prepend to generated files.
94 *
95 * @since 4.0.0
96 */
97 get headerContent(): string | undefined {
98 return this.header
99 }
100​
101 /**
102 * Get the list of annotation keys to exclude from generated code.
103 *
104 * @since 4.0.0
105 */
106 get excludeAnnotationsList(): ReadonlyArray<string> | undefined {
107 return this.excludeAnnotations
108 }
109​
110 /**
111 * Whether to close objects with declared properties and no explicit `additionalProperties`.
112 *
113 * @since 4.0.0
114 */
115 get shouldDisableAdditionalProperties(): boolean {
116 return this.disableAdditionalProperties ?? false
117 }
119​
120/**
121 * Represents the source of an OpenAPI specification.
122 *
123 * @category models
124 * @since 4.0.0
125 */
126export type SpecSource = SpecSource.Url | SpecSource.File
127​
128/**
129 * Namespace containing the supported OpenAPI specification source variants.
130 *
131 * @since 4.0.0
132 */
133export declare namespace SpecSource {
134 /**
135 * A URL-based spec source.
136 *
137 * @category models
138 * @since 4.0.0
139 */
140 export interface Url {
141 readonly _tag: "Url"
142 readonly url: string
143 }
144​
145 /**
146 * A file-based spec source.
147 *
148 * @category models
149 * @since 4.0.0
150 */
151 export interface File {
152 readonly _tag: "File"
153 readonly path: string
154 }
156​
157/**
158 * Constructors and utilities for `SpecSource`.
159 *
160 * **Example** (Creating spec sources)
161 *
162 * ```ts import.meta.vitest
163 * import * as Config from "@effect/ai-codegen/Config"
164 *
165 * // Create a URL-based source
166 * const urlSource = Config.SpecSource.Url("https://example.com/openapi.json")
167 *
168 * // Create a file-based source
169 * const fileSource = Config.SpecSource.File("/path/to/spec.json")
170 *
171 * urlSource._tag // => "Url"
172 * fileSource._tag // => "File"
173 * ```
174 *
175 * @category constructors
176 * @since 4.0.0
177 */
178export const SpecSource = {
179 /**
180 * Create a URL-based spec source.
181 *
182 * @since 4.0.0
183 */
184 Url: (url: string): SpecSource => ({ _tag: "Url", url }),
185​
186 /**
187 * Create a file-based spec source.
188 *
189 * @since 4.0.0
190 */
191 File: (path: string): SpecSource => ({ _tag: "File", path }),
192​
193 /**
194 * Parse a spec string into a `SpecSource`.
195 * URLs (http:// or https://) become `Url`, otherwise `File`.
196 *
197 * @since 4.0.0
198 */
199 fromString: (spec: string, packagePath: string, pathService: Path.Path): SpecSource => {
200 if (spec.startsWith("http://") || spec.startsWith("https://")) {
201 return SpecSource.Url(spec)
202 }
203 return SpecSource.File(pathService.join(packagePath, spec))
204 }
206​
207/**
208 * Error when parsing a codegen configuration file fails.
209 *
210 * **Example** (Creating a config parse error)
211 *
212 * ```ts import.meta.vitest
213 * import * as Config from "@effect/ai-codegen/Config"
214 *
215 * const error = new Config.ConfigParseError({
216 * path: "/path/to/codegen.json",
217 * cause: new Error("Invalid JSON")
218 * })
219 *
220 * error._tag // => "ConfigParseError"
221 * error.path // => "/path/to/codegen.json"
222 * ```
223 *
224 * @category errors
225 * @since 4.0.0
226 */
227export class ConfigParseError extends Data.TaggedError("ConfigParseError")<{
228 readonly path: string
229 readonly cause: unknown
230}> {}
231​
232/**
233 * Error when a codegen configuration file is not found.
234 *
235 * **Example** (Creating a config not found error)
236 *
237 * ```ts import.meta.vitest
238 * import * as Config from "@effect/ai-codegen/Config"
239 *
240 * const error = new Config.ConfigNotFoundError({
241 * provider: "openai",
242 * expectedPath: "/path/to/packages/ai/openai/codegen.json"
243 * })
244 *
245 * error._tag // => "ConfigNotFoundError"
246 * error.provider // => "openai"
247 * ```
248 *
249 * @category errors
250 * @since 4.0.0
251 */
252export class ConfigNotFoundError extends Data.TaggedError("ConfigNotFoundError")<{
253 readonly provider: string
254 readonly expectedPath: string
255}> {}