@openmirai/typeforge 0.1.8 → 0.2.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 +1 -5
- package/dist/adapters/axios/index.d.ts +13 -2
- package/dist/adapters/axios/index.js +1 -43
- package/dist/adapters/fetch/index.d.ts +17 -2
- package/dist/adapters/fetch/index.js +1 -77
- package/dist/cli.d.ts +1 -2
- package/dist/cli.js +5 -168
- package/dist/http/types.d.ts +12 -2
- package/dist/http/types.js +1 -2
- package/dist/http/validate.d.ts +1 -2
- package/dist/http/validate.js +1 -21
- package/dist/index.d.ts +133 -5
- package/dist/index.js +1 -13
- package/dist/init-CqBQsEHz.js +134 -0
- package/dist/routes/index.d.ts +1 -2
- package/dist/routes/index.js +1 -38
- package/dist/validation/zod.d.ts +1 -2
- package/dist/validation/zod.js +1 -8
- package/package.json +3 -4
- package/assets/typeforge-logo.png +0 -0
- package/dist/adapters/axios/index.d.ts.map +0 -1
- package/dist/adapters/axios/index.js.map +0 -1
- package/dist/adapters/fetch/index.d.ts.map +0 -1
- package/dist/adapters/fetch/index.js.map +0 -1
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/http/types.d.ts.map +0 -1
- package/dist/http/validate.d.ts.map +0 -1
- package/dist/http/validate.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/init-BBNO0SYd.js +0 -2029
- package/dist/init-BBNO0SYd.js.map +0 -1
- package/dist/routes/index.d.ts.map +0 -1
- package/dist/routes/index.js.map +0 -1
- package/dist/validation/zod.d.ts.map +0 -1
- package/dist/validation/zod.js.map +0 -1
package/dist/index.d.ts
CHANGED
|
@@ -9,64 +9,134 @@ type QueryParamValue = string | number | boolean | null | undefined;
|
|
|
9
9
|
type QueryParams = Record<string, QueryParamValue>;
|
|
10
10
|
//#endregion
|
|
11
11
|
//#region src/parser/types.d.ts
|
|
12
|
+
/** Intermediate representation of all parsed OpenAPI sources. */
|
|
12
13
|
interface IR {
|
|
14
|
+
/** Parsed API sources. */
|
|
13
15
|
sources: Array<IRSource>;
|
|
14
16
|
}
|
|
17
|
+
/** Parsed paths and component schemas for one OpenAPI source. */
|
|
15
18
|
interface IRSource {
|
|
19
|
+
/** Source key from the Typeforge project configuration. */
|
|
16
20
|
key: string;
|
|
21
|
+
/** Parsed API paths. */
|
|
17
22
|
paths: Array<IRPath>;
|
|
23
|
+
/** Reusable schemas declared by the source specification. */
|
|
18
24
|
components: {
|
|
19
25
|
schemas: Record<string, IRSchema>;
|
|
20
26
|
};
|
|
21
27
|
}
|
|
28
|
+
/** An OpenAPI path and its supported operations. */
|
|
22
29
|
interface IRPath {
|
|
30
|
+
/** Path template as written in the OpenAPI document. */
|
|
23
31
|
path: string;
|
|
32
|
+
/** Filesystem-safe path used for generated output. */
|
|
24
33
|
cleanPath: string;
|
|
34
|
+
/** Supported HTTP operations on this path. */
|
|
25
35
|
operations: Array<IROperation>;
|
|
26
36
|
}
|
|
37
|
+
/** A parsed OpenAPI operation. */
|
|
27
38
|
interface IROperation {
|
|
39
|
+
/** HTTP method for the operation. */
|
|
28
40
|
method: HttpMethod;
|
|
41
|
+
/** Explicit OpenAPI operation identifier, when provided. */
|
|
29
42
|
operationId?: string;
|
|
43
|
+
/** Short operation summary from the OpenAPI document. */
|
|
44
|
+
summary?: string;
|
|
45
|
+
/** Detailed operation description from the OpenAPI document. */
|
|
46
|
+
description?: string;
|
|
47
|
+
/** Whether the OpenAPI operation is deprecated. */
|
|
48
|
+
deprecated?: boolean;
|
|
49
|
+
/** Parameters substituted into the route path. */
|
|
30
50
|
pathParams: Array<IRPathParam>;
|
|
51
|
+
/** Parameters serialized into the query string. */
|
|
31
52
|
queryParams: Array<IRQueryParam>;
|
|
53
|
+
/** JSON request body, when the operation accepts one. */
|
|
32
54
|
requestBody?: IRRequestBody;
|
|
55
|
+
/** Declared operation responses. */
|
|
33
56
|
responses: Array<IRResponse>;
|
|
34
57
|
}
|
|
58
|
+
/** HTTP methods supported by the Typeforge generator. */
|
|
35
59
|
type HttpMethod = "get" | "post" | "put" | "patch" | "delete";
|
|
60
|
+
/** Parsed path parameter metadata. */
|
|
36
61
|
interface IRPathParam {
|
|
62
|
+
/** Parameter name. */
|
|
37
63
|
name: string;
|
|
64
|
+
/** OpenAPI parameter description. */
|
|
65
|
+
description?: string;
|
|
66
|
+
/** Whether the parameter is deprecated. */
|
|
67
|
+
deprecated?: boolean;
|
|
68
|
+
/** Parameter value schema. */
|
|
38
69
|
schema: IRSchema;
|
|
39
70
|
}
|
|
71
|
+
/** Parsed query parameter metadata. */
|
|
40
72
|
interface IRQueryParam {
|
|
73
|
+
/** Parameter name. */
|
|
41
74
|
name: string;
|
|
75
|
+
/** Whether callers must provide the parameter. */
|
|
42
76
|
required: boolean;
|
|
77
|
+
/** OpenAPI parameter description. */
|
|
78
|
+
description?: string;
|
|
79
|
+
/** Whether the parameter is deprecated. */
|
|
80
|
+
deprecated?: boolean;
|
|
81
|
+
/** Parameter value schema. */
|
|
43
82
|
schema: IRSchema;
|
|
44
83
|
}
|
|
84
|
+
/** Parsed request-body metadata. */
|
|
45
85
|
interface IRRequestBody {
|
|
86
|
+
/** Whether callers must provide the request body. */
|
|
46
87
|
required: boolean;
|
|
88
|
+
/** OpenAPI request-body description. */
|
|
89
|
+
description?: string;
|
|
90
|
+
/** JSON request-body schema. */
|
|
47
91
|
schema: IRSchema;
|
|
48
92
|
}
|
|
93
|
+
/** Parsed response metadata for one status code. */
|
|
49
94
|
interface IRResponse {
|
|
95
|
+
/** OpenAPI response status key, such as `"200"` or `"default"`. */
|
|
50
96
|
statusCode: string;
|
|
97
|
+
/** OpenAPI response description. */
|
|
98
|
+
description?: string;
|
|
99
|
+
/** JSON response schema, when one is declared. */
|
|
51
100
|
schema?: IRSchema;
|
|
52
101
|
}
|
|
102
|
+
/** Typeforge's normalized representation of an OpenAPI schema. */
|
|
53
103
|
interface IRSchema {
|
|
104
|
+
/** Normalized schema construct used by the TypeScript renderer. */
|
|
54
105
|
kind: "object" | "array" | "string" | "number" | "boolean" | "null" | "unknown" | "ref" | "oneOf" | "anyOf" | "allOf";
|
|
106
|
+
/** Referenced component name for `ref` schemas. */
|
|
55
107
|
ref?: string;
|
|
108
|
+
/** Element schema for arrays. */
|
|
56
109
|
items?: IRSchema;
|
|
110
|
+
/** Named fields for object schemas. */
|
|
57
111
|
properties?: Record<string, IRSchemaProperty>;
|
|
112
|
+
/** Required object-property names from the source schema. */
|
|
58
113
|
required?: Array<string>;
|
|
114
|
+
/** Allowed literal values. */
|
|
59
115
|
enum?: Array<JsonPrimitive>;
|
|
116
|
+
/** Schema for arbitrary object values, or whether they are allowed. */
|
|
60
117
|
additionalProperties?: IRSchema | boolean;
|
|
118
|
+
/** Exclusive union alternatives. */
|
|
61
119
|
oneOf?: Array<IRSchema>;
|
|
120
|
+
/** Non-exclusive union alternatives. */
|
|
62
121
|
anyOf?: Array<IRSchema>;
|
|
122
|
+
/** Intersected schema parts. */
|
|
63
123
|
allOf?: Array<IRSchema>;
|
|
124
|
+
/** OpenAPI scalar format, such as `uuid` or `date-time`. */
|
|
64
125
|
format?: string;
|
|
126
|
+
/** Whether the schema also accepts `null`. */
|
|
65
127
|
nullable?: boolean;
|
|
128
|
+
/** Human-readable OpenAPI schema description. */
|
|
129
|
+
description?: string;
|
|
130
|
+
/** Whether the OpenAPI schema is deprecated. */
|
|
131
|
+
deprecated?: boolean;
|
|
132
|
+
/** Extension that identifies the schema used for object map keys. */
|
|
66
133
|
"x-map-key-ref"?: string;
|
|
67
134
|
}
|
|
135
|
+
/** A normalized object property and its requiredness. */
|
|
68
136
|
interface IRSchemaProperty {
|
|
137
|
+
/** Property value schema. */
|
|
69
138
|
schema: IRSchema;
|
|
139
|
+
/** Whether the containing object requires the property. */
|
|
70
140
|
required: boolean;
|
|
71
141
|
}
|
|
72
142
|
//#endregion
|
|
@@ -110,48 +180,86 @@ declare function resolveSpecSource(sourceKey: string, opts: {
|
|
|
110
180
|
type ResponseValidator<T> = (value: unknown) => T;
|
|
111
181
|
//#endregion
|
|
112
182
|
//#region src/http/types.d.ts
|
|
183
|
+
/** Per-request options accepted by every Typeforge HTTP adapter method. */
|
|
113
184
|
interface HTTPFetchConfig<TParams extends object = QueryParams, TResponse = unknown> {
|
|
185
|
+
/** Abort signal forwarded to the underlying HTTP client. */
|
|
114
186
|
signal?: AbortSignal;
|
|
187
|
+
/** Query parameters serialized by the HTTP adapter. */
|
|
115
188
|
params?: TParams;
|
|
189
|
+
/** Request headers merged with adapter-level defaults. */
|
|
116
190
|
headers?: Record<string, string>;
|
|
191
|
+
/** Optional runtime validator applied to the response payload. */
|
|
117
192
|
validateResponse?: ResponseValidator<TResponse>;
|
|
118
193
|
}
|
|
194
|
+
/** Transport contract consumed by Typeforge-generated API callers. */
|
|
119
195
|
interface HTTPFetch {
|
|
196
|
+
/** Send a GET request and return its typed response payload. */
|
|
120
197
|
get<TResponse, TParams extends object = QueryParams>(route: string, config?: HTTPFetchConfig<TParams, TResponse>): Promise<{
|
|
121
198
|
data: TResponse;
|
|
122
199
|
}>;
|
|
200
|
+
/** Send a POST request with a typed body and return its typed response payload. */
|
|
123
201
|
post<TResponse, TBody = unknown, TParams extends object = QueryParams>(route: string, body: TBody, config?: HTTPFetchConfig<TParams, TResponse>): Promise<{
|
|
124
202
|
data: TResponse;
|
|
125
203
|
}>;
|
|
204
|
+
/** Send a PUT request with a typed body and return its typed response payload. */
|
|
126
205
|
put<TResponse, TBody = unknown, TParams extends object = QueryParams>(route: string, body: TBody, config?: HTTPFetchConfig<TParams, TResponse>): Promise<{
|
|
127
206
|
data: TResponse;
|
|
128
207
|
}>;
|
|
208
|
+
/** Send a PATCH request with a typed body and return its typed response payload. */
|
|
129
209
|
patch<TResponse, TBody = unknown, TParams extends object = QueryParams>(route: string, body: TBody, config?: HTTPFetchConfig<TParams, TResponse>): Promise<{
|
|
130
210
|
data: TResponse;
|
|
131
211
|
}>;
|
|
212
|
+
/** Send a DELETE request and return its typed response payload. */
|
|
132
213
|
delete<TResponse, TParams extends object = QueryParams>(route: string, config?: HTTPFetchConfig<TParams, TResponse>): Promise<{
|
|
133
214
|
data: TResponse;
|
|
134
215
|
}>;
|
|
135
216
|
}
|
|
136
217
|
//#endregion
|
|
137
218
|
//#region src/config/types.d.ts
|
|
219
|
+
/** Project-wide Typeforge settings loaded from `typeforge.json` or package.json. */
|
|
138
220
|
interface TypeforgeConfig {
|
|
221
|
+
/**
|
|
222
|
+
* Root directory containing HTTP adapters and named API sources.
|
|
223
|
+
* @defaultValue `"src/api"`
|
|
224
|
+
*/
|
|
139
225
|
apiRoot?: string;
|
|
140
226
|
}
|
|
141
|
-
/**
|
|
142
|
-
type OpenApiCodegenConfig = TypeforgeConfig;
|
|
227
|
+
/** Controls whether generated routes replace or preserve existing route entries. */
|
|
143
228
|
type GenerationMode = "authoritative" | "merge";
|
|
229
|
+
/** Selects whether generated function names come from paths or OpenAPI operation IDs. */
|
|
144
230
|
type NamingStrategy = "path" | "operationId";
|
|
231
|
+
/** Maps API query-parameter names to shared pagination and sorting types. */
|
|
145
232
|
interface QueryExtendsConfig {
|
|
233
|
+
/**
|
|
234
|
+
* Name of the page-number query parameter.
|
|
235
|
+
* @defaultValue `"page"`
|
|
236
|
+
*/
|
|
146
237
|
page?: string;
|
|
238
|
+
/**
|
|
239
|
+
* Name of the page-size query parameter.
|
|
240
|
+
* @defaultValue `"limit"`
|
|
241
|
+
*/
|
|
147
242
|
limit?: string;
|
|
243
|
+
/**
|
|
244
|
+
* Name of the sort-field query parameter.
|
|
245
|
+
* @defaultValue `"sortBy"`
|
|
246
|
+
*/
|
|
148
247
|
sortBy?: string;
|
|
248
|
+
/**
|
|
249
|
+
* Name of the sort-direction query parameter.
|
|
250
|
+
* @defaultValue `"sortOrder"`
|
|
251
|
+
*/
|
|
149
252
|
sortOrder?: string;
|
|
253
|
+
/** Shared type that replaces matching page and limit properties. */
|
|
150
254
|
paginationTypeName?: string;
|
|
255
|
+
/** Module specifier from which the shared pagination type is imported. */
|
|
151
256
|
paginationImportPath?: string;
|
|
257
|
+
/** Generic shared type that replaces matching sort properties. */
|
|
152
258
|
sortTypeName?: string;
|
|
259
|
+
/** Module specifier from which the shared sort type is imported. */
|
|
153
260
|
sortImportPath?: string;
|
|
154
261
|
}
|
|
262
|
+
/** Generation settings exported by an API source's `source.ts` file. */
|
|
155
263
|
interface SourceConfig {
|
|
156
264
|
/**
|
|
157
265
|
* Project-relative directory for generated API function files.
|
|
@@ -163,13 +271,33 @@ interface SourceConfig {
|
|
|
163
271
|
* Defaults to `<apiRoot>/<source>/generated/types`.
|
|
164
272
|
*/
|
|
165
273
|
typesDir?: string;
|
|
274
|
+
/** Only generate operations whose paths start with this prefix. */
|
|
166
275
|
pathPrefix?: string;
|
|
276
|
+
/** Exact OpenAPI paths to exclude from generation. */
|
|
167
277
|
ignorePaths?: Array<string>;
|
|
278
|
+
/** Remove the leading `/api` segment from generated route names and values. */
|
|
168
279
|
stripApiPrefix?: boolean;
|
|
280
|
+
/**
|
|
281
|
+
* Name of the generated route-target enum.
|
|
282
|
+
* @defaultValue `"RouteTargets"`
|
|
283
|
+
*/
|
|
169
284
|
routeEnumName?: string;
|
|
285
|
+
/** Whether route generation replaces the file or retains extra existing entries. */
|
|
170
286
|
generationMode?: GenerationMode;
|
|
287
|
+
/**
|
|
288
|
+
* Strategy used to derive generated caller function names.
|
|
289
|
+
* @defaultValue `"path"`
|
|
290
|
+
*/
|
|
171
291
|
naming?: NamingStrategy;
|
|
292
|
+
/**
|
|
293
|
+
* Maximum schema expansion depth before recursive generation fails.
|
|
294
|
+
* @defaultValue `50`
|
|
295
|
+
*/
|
|
172
296
|
maxRenderDepth?: number;
|
|
297
|
+
/**
|
|
298
|
+
* Resolve `x-map-key-ref` extensions into typed `Record` keys.
|
|
299
|
+
* @defaultValue `true`
|
|
300
|
+
*/
|
|
173
301
|
resolveMapKeyRefs?: boolean;
|
|
174
302
|
/**
|
|
175
303
|
* Emit an envelope's `data` schema as the operation response type.
|
|
@@ -177,8 +305,9 @@ interface SourceConfig {
|
|
|
177
305
|
* unwraps response envelopes before returning its `{ data }` value.
|
|
178
306
|
*/
|
|
179
307
|
unwrapResponseData?: boolean;
|
|
308
|
+
/** Replace conventional pagination and sorting properties with shared local types. */
|
|
180
309
|
queryExtends?: QueryExtendsConfig;
|
|
181
|
-
/**
|
|
310
|
+
/** Emit TanStack Query helpers for GET endpoints when `query-scope.ts` exists. */
|
|
182
311
|
tanstackQuery?: boolean;
|
|
183
312
|
/**
|
|
184
313
|
* Explicit import base for generated function files pointing back to the
|
|
@@ -322,5 +451,4 @@ interface KnownTypeMatch {
|
|
|
322
451
|
declare function loadKnownTypeRules(cwd: string, apiRoot: string): Array<KnownTypeRule>;
|
|
323
452
|
declare function matchKnownType(schema: IRSchema, components: Record<string, IRSchema>, rules: Array<KnownTypeRule>): KnownTypeMatch | undefined;
|
|
324
453
|
//#endregion
|
|
325
|
-
export { type DeclarativeKnownTypeRule, type EnvelopeAnalysis, type EnvelopeMode, type EnvelopeShape, type GenerateOptions, type GenerateResult, type GenerationMode, type HTTPFetch, type HTTPFetchConfig, type HttpClient, type HttpMethod, type IR, type IROperation, type IRPath, type IRPathParam, type IRQueryParam, type IRRequestBody, type IRResponse, type IRSchema, type IRSchemaProperty, type IRSource, type InitOptions, type JsonArray, type JsonObject, type JsonPrimitive, type JsonValue, type KnownTypeRule, type NamingStrategy, type
|
|
326
|
-
//# sourceMappingURL=index.d.ts.map
|
|
454
|
+
export { type DeclarativeKnownTypeRule, type EnvelopeAnalysis, type EnvelopeMode, type EnvelopeShape, type GenerateOptions, type GenerateResult, type GenerationMode, type HTTPFetch, type HTTPFetchConfig, type HttpClient, type HttpMethod, type IR, type IROperation, type IRPath, type IRPathParam, type IRQueryParam, type IRRequestBody, type IRResponse, type IRSchema, type IRSchemaProperty, type IRSource, type InitOptions, type JsonArray, type JsonObject, type JsonPrimitive, type JsonValue, type KnownTypeRule, type NamingStrategy, type ProjectLayout, type QueryExtendsConfig, type QueryParams, RecursiveRefError, type SourceConfig, type SpecSource, type TypeforgeConfig, analyzeEnvelope, buildBaseResponseInterface, buildGenerateContext, defineSourceConfig, diffEnvelopeFields, generateForSource, initProject, loadKnownTypeRules, loadSpec, matchKnownType, parseSchema, parseSpec, parseUserBaseResponse, resolveSpecSource };
|
package/dist/index.js
CHANGED
|
@@ -1,13 +1 @@
|
|
|
1
|
-
import
|
|
2
|
-
//#region src/config/define.ts
|
|
3
|
-
/**
|
|
4
|
-
* Identity helper for `source.ts`. Use it so the object is checked against
|
|
5
|
-
* `SourceConfig` and editors can autocomplete fields.
|
|
6
|
-
*/
|
|
7
|
-
function defineSourceConfig(config) {
|
|
8
|
-
return config;
|
|
9
|
-
}
|
|
10
|
-
//#endregion
|
|
11
|
-
export { RecursiveRefError, analyzeEnvelope, buildBaseResponseInterface, buildGenerateContext, defineSourceConfig, diffEnvelopeFields, generateForSource, initProject, loadKnownTypeRules, loadSpec, matchKnownType, parseSchema, parseSpec, parseUserBaseResponse, resolveSpecSource };
|
|
12
|
-
|
|
13
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
import{a as e,c as t,d as n,f as r,i,l as a,m as o,n as s,o as c,p as l,r as u,s as d,t as f,u as p}from"./init-CqBQsEHz.js";function m(e){return e}export{t as RecursiveRefError,n as analyzeEnvelope,r as buildBaseResponseInterface,s as buildGenerateContext,m as defineSourceConfig,l as diffEnvelopeFields,u as generateForSource,f as initProject,c as loadKnownTypeRules,i as loadSpec,d as matchKnownType,a as parseSchema,p as parseSpec,o as parseUserBaseResponse,e as resolveSpecSource};
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import{existsSync as e,mkdirSync as t,readFileSync as n,readdirSync as r,statSync as i,writeFileSync as a}from"node:fs";import{dirname as o,join as s,parse as c,relative as l,resolve as u}from"node:path";import d from"chalk";import{mkdir as f,readFile as p,writeFile as m}from"node:fs/promises";function h(e){return e===null||typeof e==`string`||typeof e==`number`||typeof e==`boolean`}function g(e){return e===null||typeof e==`string`||typeof e==`number`||typeof e==`boolean`?!0:Array.isArray(e)?e.every(g):typeof e==`object`&&e?Object.values(e).every(g):!1}function _(e){return g(e)&&typeof e==`object`&&!!e&&!Array.isArray(e)}function v(e){return Array.isArray(e)&&e.every(g)}function y(e){let t=JSON.parse(e);if(!g(t))throw TypeError(`JSON text did not parse to a valid JSON value`);return t}function b(e){let t=y(e);if(!_(t))throw TypeError(`JSON text did not parse to a JSON object`);return t}function x(e){return v(e)?e.filter(h):[]}function S(t){if(!e(t))return{};try{let e=b(n(t,`utf8`)),r={};return typeof e.apiRoot==`string`&&(r.apiRoot=e.apiRoot),r}catch{return{}}}function C(t){if(!e(t))return{};try{let e=b(n(t,`utf8`)).typeforge;if(typeof e!=`object`||!e||Array.isArray(e))return{};let r={};return typeof e.apiRoot==`string`&&(r.apiRoot=e.apiRoot),r}catch{return{}}}function w(e){let t=e.match(/defineSourceConfig\s*(?:<[^>]*>)?\s*\(\s*\{([\s\S]*)\}\s*\)/);return t?.[1]===void 0?e:`{${t[1]}}`}function T(e){let t=w(e),n={},r=t.match(/pathPrefix:\s*["'`]([^"'`]+)["'`]/);r?.[1]!==void 0&&(n.pathPrefix=r[1]);let i=t.match(/functionsDir:\s*["'`]([^"'`]+)["'`]/);i?.[1]!==void 0&&(n.functionsDir=i[1]);let a=t.match(/typesDir:\s*["'`]([^"'`]+)["'`]/);a?.[1]!==void 0&&(n.typesDir=a[1]);let o=t.match(/ignorePaths:\s*\[([\s\S]*?)\]/);if(o?.[1]!==void 0){let e=[...o[1].matchAll(/["'`]([^"'`]+)["'`]/g)].map(e=>e[1]).filter(e=>e!==void 0);e.length>0&&(n.ignorePaths=e)}/stripApiPrefix:\s*true/.test(t)&&(n.stripApiPrefix=!0);let s=t.match(/routeEnumName:\s*["'`]([^"'`]+)["'`]/);s?.[1]!==void 0&&(n.routeEnumName=s[1]);let c=t.match(/generationMode:\s*["'`](authoritative|merge)["'`]/);(c?.[1]===`authoritative`||c?.[1]===`merge`)&&(n.generationMode=c[1]);let l=t.match(/naming:\s*["'`](path|operationId)["'`]/);(l?.[1]===`path`||l?.[1]===`operationId`)&&(n.naming=l[1]),/resolveMapKeyRefs:\s*false/.test(t)&&(n.resolveMapKeyRefs=!1),/unwrapResponseData:\s*true/.test(t)&&(n.unwrapResponseData=!0),/tanstackQuery:\s*true/.test(t)&&(n.tanstackQuery=!0);let u=t.match(/importBase:\s*["'`]([^"'`]+)["'`]/);u?.[1]!==void 0&&(n.importBase=u[1]);let d=t.match(/maxRenderDepth:\s*(\d+)/)?.[1];d!==void 0&&(n.maxRenderDepth=Number.parseInt(d,10));let f=E(t);f!==void 0&&(n.queryExtends=f);let p=t.match(/spec:\s*["'`]([^"'`]+)["'`]/);return p?.[1]!==void 0&&(n.spec=p[1]),n}function E(e){let t=e.match(/queryExtends:\s*\{([\s\S]*?)\}/)?.[1];if(t===void 0)return;let n={},r=e=>t.match(RegExp(`${e}:\\s*["'\`]([^"'\`]+)["'\`]`))?.[1],i=r(`page`),a=r(`limit`),o=r(`sortBy`),s=r(`sortOrder`),c=r(`paginationTypeName`),l=r(`paginationImportPath`),u=r(`sortTypeName`),d=r(`sortImportPath`);return i!==void 0&&(n.page=i),a!==void 0&&(n.limit=a),o!==void 0&&(n.sortBy=o),s!==void 0&&(n.sortOrder=s),c!==void 0&&(n.paginationTypeName=c),l!==void 0&&(n.paginationImportPath=l),u!==void 0&&(n.sortTypeName=u),d!==void 0&&(n.sortImportPath=d),Object.keys(n).length>0?n:void 0}function D(e){let t=S(u(e,`typeforge.json`)),n=C(u(e,`package.json`));return{apiRoot:t.apiRoot??n.apiRoot??`src/api`}}function ee(t,r,i){let a=u(t,r,i,`source.ts`);return e(a)?T(n(a,`utf8`)):{}}function te(t,r){let i=u(t,r,`models.ts`);if(e(i))return n(i,`utf8`)}function ne(t,n){return e(u(t,n,`query-scope.ts`))}function re(t,r){let i=u(t,r,`http.ts`);if(!e(i))return`injected`;let a=n(i,`utf8`);return/export\s+(const|function)\s+httpFetch\b/.test(a)||/export\s*\{[^}]*\bhttpFetch\b/.test(a)?`singleton`:`injected`}function ie(t,n){let a=u(t,n);return e(a)?r(a).filter(t=>{let n=s(a,t);return i(n).isDirectory()?e(s(n,`source.ts`)):!1}):[]}function ae(e){let t=``,n=0,r=e.length,i=!1;for(;n<r;){let a=e[n];if(i){t+=a,a===`\\`?(n++,n<r&&(t+=e[n])):a===`"`&&(i=!1),n++;continue}if(a===`"`){i=!0,t+=a,n++;continue}if(a===`/`&&e[n+1]===`/`){for(;n<r&&e[n]!==`
|
|
2
|
+
`;)n++;continue}if(a===`/`&&e[n+1]===`*`){for(n+=2;n<r&&(e[n]!==`*`||e[n+1]!==`/`);)n++;n+=2;continue}t+=a,n++}return t.replace(/,(\s*[}\]])/g,`$1`)}function oe(e){let t=u(e),n=c(t).root;for(;;){let e=se(t);if(e!==void 0)return e;if(t===n)return;t=o(t)}}function se(t){let r=u(t,`tsconfig.json`);if(e(r))try{let e=JSON.parse(ae(n(r,`utf8`)));if(typeof e!=`object`||!e||Array.isArray(e))return;let i=e.compilerOptions;if(typeof i!=`object`||!i||Array.isArray(i))return;let a=i,o=a.paths;if(typeof o!=`object`||!o||Array.isArray(o))return;let s=typeof a.baseUrl==`string`?a.baseUrl:`.`,c={};for(let[e,t]of Object.entries(o))Array.isArray(t)&&t.every(e=>typeof e==`string`)&&(c[e]=t);return Object.keys(c).length===0?void 0:{baseDir:t,paths:c,resolvedBaseUrl:u(t,s)}}catch{return}}function ce(e,t){for(let[n,r]of Object.entries(t.paths))for(let i of r)if(n.endsWith(`/*`)&&i.endsWith(`/*`)){let r=n.slice(0,-2),a=i.slice(0,-2),o=u(t.resolvedBaseUrl,a);if(e.startsWith(`${o}/`))return`${r}/${e.slice(o.length+1)}`;if(e===o)return r}else if(!n.includes(`*`)&&!i.includes(`*`)){let r=u(t.resolvedBaseUrl,i);if(le(e)===le(r))return n}}function le(e){return e.replace(/\.(d\.ts|ts|js)$/,``)}function O(e){return e.replace(/\.d\.ts$/,``).replace(/\.ts$/,``)}function ue(e,t){let n=o(O(e)),r=O(t),i=l(n,r).replace(/\\/g,`/`);return i.startsWith(`.`)?i:`./${i}`}function de(e){let{fromAbsolutePath:t,toAbsolutePath:n,importBase:r,generatedDir:i,tsconfigPaths:a}=e;if(r!==void 0&&i!==void 0){let e=i.replace(/\/$/,``),t=O(n);if(t.startsWith(`${e}/`))return`${r}/${t.slice(e.length+1)}`;if(t===e)return r}let o=ue(t,n);if(a!==void 0&&(o.match(/\.\.\//g)??[]).length>=3){let e=ce(n,a);if(e!==void 0)return e}return o}function fe(e,t,n){return s(e,t,`${n}.ts`)}function pe(e){return e.split(`/`).filter(Boolean).map(e=>e.replace(/[{}]/g,``).replace(/[^a-zA-Z0-9]/g,`_`).toUpperCase()).join(`_`)}function me(e,t=!1){return(t?e.replace(/^\/api\//,`/`):e).replace(/\{(\w+)\}/g,`:$1`)}function he(e,t){let n=e.split(`/`).filter(Boolean).map(e=>e.replace(/[{[\]}/]/g,``).split(`-`).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(``)).join(``);return`${t===`get`?`get`:t}${n}`}function ge(e){return e.kind===`array`?`array`:e.kind===`object`?`object`:e.kind===`ref`?`ref:${e.ref??`unknown`}`:e.kind===`oneOf`||e.kind===`anyOf`||e.kind===`allOf`?e.kind:e.enum!==void 0&&e.enum.length>0?`enum`:e.kind}function _e(e){let t=Number.parseInt(e,10);return!Number.isNaN(t)&&t>=200&&t<300}function ve(e){return e.enum!==void 0&&e.enum.length>0?e.enum.map(e=>JSON.stringify(e)).join(` | `):e.kind===`number`?`number`:e.kind===`boolean`?`boolean`:`string`}function ye(e){let t=new Map;for(let n of e.operations)for(let e of n.pathParams)t.has(e.name)||t.set(e.name,e.schema);return t}function be(e,t){let n=e.get(t);return n===void 0?`string`:ve(n)}function xe(e,t){let n=e.split(`/`).filter(Boolean).map(e=>e.replace(/[{[\]}/]/g,``).split(`-`).map(e=>e.charAt(0).toUpperCase()+e.slice(1)).join(``)).join(``);return`${t.toUpperCase()}${n}`}function Se(e){let t=e.requestBody?.schema;return t!==void 0&&!Ce(t)}function Ce(e){return e.kind===`unknown`?!0:e.kind===`object`?e.properties===void 0||Object.keys(e.properties).length===0:!1}function we(e){return e.responses.find(e=>_e(e.statusCode)&&e.schema!==void 0)?.schema}function Te(e){return e.trim().replaceAll(`\r
|
|
3
|
+
`,`
|
|
4
|
+
`).replaceAll(`\r`,`
|
|
5
|
+
`).replaceAll(`*/`,`*\\/`).split(`
|
|
6
|
+
`)}function k(e,t=``){let n=e.description===void 0?[]:Te(e.description),r=n.some(e=>e.length>0),i=e.deprecated===!0;if(!r&&!i)return[];if(n.length===1&&!i)return[`${t}/** ${n[0]} */`];let a=[`${t}/**`];if(r)for(let e of n)a.push(`${t} *${e.length>0?` ${e}`:``}`);return i&&(r&&a.push(`${t} *`),a.push(`${t} * @deprecated`)),a.push(`${t} */`),a}function Ee(e){return(e.match(/\{([^}]+)\}/g)??[]).map(e=>e.slice(1,-1))}function De(e,t,n){let r=e.replace(/\{([^}]+)\}/g,`[$1]`).split(`/`).filter(Boolean).join(`/`),i=fe(n.functionsDir,e,t.toUpperCase()),a=s(n.typesDir,r,t.toUpperCase());return de({fromAbsolutePath:i,generatedDir:n.generatedDir,toAbsolutePath:a,...n.importBase===void 0?{}:{importBase:n.importBase},...n.tsconfigPaths===void 0?{}:{tsconfigPaths:n.tsconfigPaths}})}function Oe(e,t,n){let r=fe(t.functionsDir,e,n.toUpperCase()),i=s(t.generatedDir,`runtime`);return de({fromAbsolutePath:r,generatedDir:t.generatedDir,toAbsolutePath:i,...t.importBase===void 0?{}:{importBase:t.importBase},...t.tsconfigPaths===void 0?{}:{tsconfigPaths:t.tsconfigPaths}})}function ke(e,t,n){let r=e.pathParams.find(e=>e.name===n);return be(r===void 0?t:new Map([[n,r.schema]]),n)}function A(e,t,n=!1){let r={},i=e??t;return i!==void 0&&(r.description=i),n&&(r.deprecated=!0),r}function Ae(e){let t=[];for(let n of e.paths)for(let r of n.operations)t.push({content:je(n,r,e),relativePath:`${n.cleanPath}/${r.method.toUpperCase()}.ts`});return t}function je(e,t,n){let r=t.method,i=he(e.cleanPath,r),a=pe(e.path),o=xe(e.cleanPath,r),s=Ee(e.path),c=ye(e),l=`${Me(i)}Props`,u=`${Me(i)}QueryOptionsProps`,d=r!==`get`&&Se(t),f=t.queryParams.length>0,p=De(e.cleanPath,r,n),m=Oe(e.cleanPath,n,r),h=[`// Auto-generated from OpenAPI spec`,`// Path: ${r.toUpperCase()} ${e.path}`,`// DO NOT EDIT - This file is automatically generated`,``];h.push(`import type {`),h.push(` ${o}Response,`),f&&h.push(` ${o}Params,`),d&&h.push(` ${o}Body,`),h.push(`} from "${p}";`),h.push(``);let g=n.hasQueryScope?`, RouteTargets`:``;n.httpMode===`singleton`?h.push(`import { httpFetch, Routes${g}${n.hasQueryScope?`, getQueryScopeKey, queryOptions`:``} } from "${m}";`):h.push(`import { Routes${g}${n.hasQueryScope?`, getQueryScopeKey, queryOptions`:``} } from "${m}";`);let _=n.httpMode===`injected`?`HTTPFetch, `:``,v=f?``:`, QueryParams`;h.push(`import type { ${_}HTTPFetchConfig${v}${n.hasQueryScope?`, QueryScope`:``} } from "${m}";`),h.push(``),h.push(...k(A(t.description,t.summary,t.deprecated===!0))),h.push(`export interface ${l} {`),n.httpMode===`injected`&&h.push(` http: HTTPFetch;`);for(let e of s){let n=t.pathParams.find(t=>t.name===e);n!==void 0&&h.push(...k(A(n.description,n.schema.description,n.deprecated===!0||n.schema.deprecated===!0),` `)),h.push(` ${e}: ${ke(t,c,e)};`)}if(f){let e=t.queryParams.some(e=>e.required)?``:`?`;h.push(` params${e}: ${o}Params;`)}if(d){let e=t.requestBody;e!==void 0&&h.push(...k(A(e.description,e.schema.description),` `)),h.push(` body: ${o}Body;`)}let y=f?`Omit<HTTPFetchConfig<${o}Params, ${o}Response>, "params" | "signal">`:`Omit<HTTPFetchConfig<QueryParams, ${o}Response>, "params" | "signal">`;h.push(` config?: ${y};`),h.push(` signal?: AbortSignal;`),h.push(`}`),h.push(``),r===`get`&&n.hasQueryScope&&(h.push(`export interface ${u} extends ${l} {`),h.push(` queryScope: QueryScope;`),h.push(`}`),h.push(``));let b=n.httpMode===`singleton`?`httpFetch`:`props.http`,x=[...n.httpMode===`injected`?[`http`]:[],...s.map(e=>e),...f?[`params`]:[],...d?[`body`]:[],`config`,`signal`];h.push(`export async function ${i}(props: ${l}): Promise<${o}Response> {`),x.length>0&&(h.push(` const { ${x.join(`, `)} } = props;`),h.push(``));let S=`Routes.${a}`;s.length>0&&(S=`Routes.${a}({ ${s.map(e=>`${e}`).join(`, `)} })`);let C=f?`{ ...config, params, signal }`:`{ ...config, signal }`,w=f?`<${o}Response, ${o}Params>`:`<${o}Response>`,T=`<${o}Response, ${d?`${o}Body`:`undefined`}${f?`, ${o}Params`:``}>`,E=d?`body`:`undefined`,D=f?`{ ...config, params, signal }`:`{ ...config, signal }`;switch(r){case`get`:h.push(` const { data } = await ${b}.get${w}(${S}, ${C});`);break;case`post`:h.push(` const { data } = await ${b}.post${T}(${S}, ${E}, ${D});`);break;case`put`:h.push(` const { data } = await ${b}.put${T}(${S}, ${E}, ${D});`);break;case`patch`:h.push(` const { data } = await ${b}.patch${T}(${S}, ${E}, ${D});`);break;case`delete`:{let e=C;d&&(e=f?`{ ...config, data: body, params, signal }`:`{ ...config, data: body, signal }`),h.push(` const { data } = await ${b}.delete${w}(${S}, ${e});`);break}}if(h.push(` return data;`),h.push(`}`),r===`get`&&n.hasQueryScope){let e=`${i}QueryOptions`;h.push(``),h.push(`export function ${e}(props: ${u}) {`),h.push(` const { ${f?`params, `:``}queryScope } = props;`),h.push(` return queryOptions({`),h.push(` queryKey: [RouteTargets.${a}, ...getQueryScopeKey(queryScope)${s.length>0?`, ${s.map(e=>`props.${e}`).join(`, `)}`:``}${f?`, params`:``}],`),h.push(` queryFn: ({ signal }) => ${i}({ ...props, signal }).then((data) => data),`),s.length>0&&h.push(` enabled: [${s.map(e=>`props.${e}`).join(`, `)}].every(Boolean),`),h.push(` });`),h.push(`}`)}return h.push(``),h.join(`
|
|
7
|
+
`)}function Me(e){return e.charAt(0).toUpperCase()+e.slice(1)}function Ne(e){let t=[`// Auto-generated from OpenAPI spec`,`// DO NOT EDIT - This file is automatically generated`,``,`export type { HTTPFetch, HTTPFetchConfig, QueryParams } from "../../http";`];return e.httpMode===`singleton`&&t.push(`export { httpFetch } from "../../http";`),t.push(`export { Routes, RouteTargets, buildRoute } from "./routes";`),e.hasQueryScope&&(t.push(`export type { QueryScope } from "../../query-scope";`),t.push(`export { getQueryScopeKey } from "../../query-scope";`),t.push(`export { queryOptions } from "@tanstack/react-query";`)),t.push(``),t.join(`
|
|
8
|
+
`)}function Pe(e){return(e.match(/\{([^}]+)\}/g)??[]).map(e=>e.slice(1,-1))}function Fe(e){let t=new Set,n=[];for(let r of e.paths){let i=pe(r.path);t.has(i)||(t.add(i),n.push({enumName:i,pathParamNames:Pe(r.path),pathParamSchemas:ye(r),routeValue:me(r.path,e.stripApiPrefix===!0)}))}return n}function Ie(e){let t=[`export type RouteParams = {`];for(let n of e){if(n.pathParamNames.length===0){t.push(` ${n.enumName}: undefined;`);continue}t.push(` ${n.enumName}: {`);for(let e of n.pathParamNames)t.push(` ${e}: ${be(n.pathParamSchemas,e)};`);t.push(` };`)}return t.push(`};`,`export type RouteKey = keyof RouteParams;`,``),t}function Le(e){let t=Fe(e),n=[`// Auto-generated from OpenAPI spec`,`// DO NOT EDIT - This file is automatically generated`,``,`import {`,` buildRouteFromHandlers,`,` createRouteHandlers,`,`} from "@openmirai/typeforge/routes";`,``,...Ie(t),`export enum ${e.routeEnumName} {`];for(let e of t)n.push(` ${e.enumName} = "${e.routeValue}",`);return n.push(`}`,``),e.routeEnumName!==`RouteTargets`&&(n.push(`export { ${e.routeEnumName} as RouteTargets };`),n.push(``)),n.push(`export const Routes = createRouteHandlers<RouteParams>(${e.routeEnumName});`),n.push(`export const buildRoute = buildRouteFromHandlers<RouteParams>(Routes);`,``),n.join(`
|
|
9
|
+
`)}function Re(e,t,n,r){let i=ze(e,n),a=ze(t,n);if(r!==void 0)for(let[e,t]of i.entries())t.startsWith(r)&&!a.has(e)&&i.delete(e);return Le({paths:[...new Map([...i,...a]).entries()].map(([,e])=>({cleanPath:e.replace(/:[^/]+/g,e=>`{${e.slice(1)}}`),operations:[],path:e.includes(`:`)?e.replace(/:([^/]+)/g,`{$1}`):e})),routeEnumName:n,stripApiPrefix:!1})}function ze(e,t){let n=new Map,r=e.indexOf(`export enum ${t} {`);if(r===-1)return n;let i=e.slice(r),a=i.indexOf(`}`);if(a===-1)return n;let o=i.slice(0,a),s=/(\w+)\s*=\s*"([^"]+)"/g,c;for(;(c=s.exec(o))!==null;){let e=c[1],t=c[2];e!==void 0&&t!==void 0&&n.set(e,t)}return n}function j(e,t){if(e.kind!==`ref`||e.ref===void 0)return e;let n=e.ref.split(`/`).pop();return n===void 0||t[n]===void 0?{kind:`unknown`}:t[n]}function M(e,t,n=new Set){if(e.kind===`object`)return e;if(e.kind===`ref`){let r=Be(e);if(r===void 0||n.has(r))return;let i=t[r];return i===void 0?void 0:M(i,t,new Set([...n,r]))}if(e.kind!==`allOf`||e.allOf===void 0)return;let r={},i=new Set;for(let a of e.allOf){let e=M(a,t,n);if(e?.properties===void 0)return;for(let[t,n]of Object.entries(e.properties)){let e=r[t];r[t]=e===void 0?{...n}:{required:e.required||n.required,schema:JSON.stringify(e.schema)===JSON.stringify(n.schema)?e.schema:{allOf:[e.schema,n.schema],kind:`allOf`}},n.required&&i.add(t)}}return{kind:`object`,properties:r,required:[...i]}}function Be(e){if(e.kind===`ref`&&e.ref!==void 0)return e.ref.split(`/`).pop()}function Ve(e,t){return e.kind===`ref`?j(e,t):e}function N(e,t){if(e===void 0)return;let n=M(e,t);if(n?.properties===void 0)return;let r=[];for(let[e,i]of Object.entries(n.properties))r.push({kind:e===`data`?`generic`:ge(Ve(i.schema,t)),name:e,required:i.required});return r.sort((e,t)=>e.name.localeCompare(t.name)),{fields:r,schema:n}}function P(e){return JSON.stringify(e.fields.map(e=>({kind:e.kind,name:e.name,required:e.required})))}function He(e,t,n){let r=N(e,t);return r!==void 0&&P(r)===P(n)}const Ue=new Set([`error`,`message`,`requestId`,`success`,`timestamp`]);function F(e){let t=new Set(e.fields.map(e=>e.name));return t.has(`data`)?!0:t.has(`success`)?[...t].every(e=>Ue.has(e)):!1}function We(e,t){let n=N(e,t);return n!==void 0&&F(n)}function Ge(e){let t=[];for(let n of e.paths)for(let r of n.operations){let i=r.responses.find(e=>_e(e.statusCode)&&e.schema!==void 0);if(i?.schema===void 0)continue;let a=N(i.schema,e.components.schemas);a!==void 0&&t.push({method:r.method.toUpperCase(),path:n.path,shape:a})}return t}function Ke(e){let t=Ge(e),n=new Map;for(let e of t){let t=P(e.shape),r=n.get(t)??[];r.push(e),n.set(t,r)}if(t.length===0)return{groups:n,mode:`raw`,operations:t};if(n.size===1){let e=t[0]?.shape;return e!==void 0&&F(e)?{groups:n,mode:`shared`,operations:t,shared:e}:{groups:n,mode:`raw`,operations:t}}let r=[...n.entries()].filter(([,e])=>{let t=e[0];return t!==void 0&&F(t.shape)});if(r.length===0)return{groups:n,mode:`raw`,operations:t};if(r.length===1){let e=r[0],i=e?.[1][0];if(e!==void 0&&e[1].length===t.length&&i!==void 0)return{groups:n,mode:`shared`,operations:t,shared:i.shape}}return{groups:n,mode:`mixed`,operations:t}}function qe(e){if(e.shared!==void 0)return e.shared;if(e.mode!==`mixed`)return;let t,n=0;for(let r of e.groups.values()){let e=r[0];e===void 0||!F(e.shape)||e.shape.fields.some(e=>e.name===`data`)&&r.length>n&&(n=r.length,t=e.shape)}return t}function Je(e){let t=e.match(/export\s+interface\s+BaseResponse\s*<[^>]*>\s*\{([\s\S]*?)\}/);if(t===null){let t=e.match(/export\s+interface\s+BaseResponse\s*\{([\s\S]*?)\}/);return t===null?void 0:Ye(t[1])}return Ye(t[1])}function Ye(e){let t=[],n=/^\s*(\w+)(\?)?:\s*([^;]+);/gm,r;for(;(r=n.exec(e))!==null;){let[,e,n,i]=r;e!==void 0&&i!==void 0&&t.push({kind:i.trim().replace(/\s+/g,` `),name:e,required:n===void 0})}return t.sort((e,t)=>e.name.localeCompare(t.name)),{fields:t,sourcePath:`models.ts`}}function Xe(e,t){let n=[],r=new Map(e.fields.filter(e=>e.name!==`data`).map(e=>[e.name,e])),i=new Map(t.fields.filter(e=>e.name!==`data`&&e.name!==`T`).map(e=>[e.name,e]));for(let[e,t]of r.entries()){let r=i.get(e);if(r===void 0){n.push({field:e,issue:`missing`,spec:t});continue}t.required!==r.required&&n.push({field:e,issue:`required-changed`,spec:t,user:r}),t.kind!==r.kind&&e!==`data`&&n.push({field:e,issue:`type-changed`,spec:t,user:r})}for(let[e,t]of i.entries())r.has(e)||n.push({field:e,issue:`extra`,user:t});return n}function Ze(e,t,n){return t===void 0?`unknown`:e.kind===`generic`?n:e.kind}function Qe(e,t=`T`){let n=[`export interface BaseResponse<${t}> {`];for(let r of e.fields){let i=e.schema.properties?.[r.name];if(i!==void 0&&n.push(...k({...i.schema.description===void 0?{}:{description:i.schema.description},...i.schema.deprecated===!0?{deprecated:!0}:{}},` `)),r.name===`data`){n.push(` data?: ${t};`);continue}let a=r.required?``:`?`,o=Ze(r,i,t);n.push(` ${r.name}${a}: ${o};`)}return n.push(`}`),n.join(`
|
|
10
|
+
`)}const $e=[`get`,`post`,`put`,`patch`,`delete`];function et(e){return v(e)?e.filter(_):[]}function tt(e){return e.split(`/`).at(-1)??e}function nt(e){return e.replace(/^\//,``).replace(/\{([^}]+)\}/g,`[$1]`)}function I(e){return typeof e.description==`string`?e.description:void 0}function rt(e,t){let n=I(e);return n!==void 0&&(t.description=n),e.deprecated===!0&&(t.deprecated=!0),t}function L(e){return _(e)?rt(e,it(e)):{kind:`unknown`}}function it(e){if(typeof e.$ref==`string`)return{kind:`ref`,ref:tt(e.$ref)};if(v(e.oneOf)&&e.oneOf.length>0)return{kind:`oneOf`,oneOf:e.oneOf.map(L)};if(v(e.anyOf)&&e.anyOf.length>0)return{anyOf:e.anyOf.map(L),kind:`anyOf`};if(v(e.allOf)&&e.allOf.length>0)return{allOf:e.allOf.map(L),kind:`allOf`};let t=typeof e.type==`string`?e.type:void 0,n=e.nullable===!0;if(t===`array`){let t={kind:`array`};return e.items!==void 0&&(t.items=L(e.items)),n&&(t.nullable=!0),t}if(t===`object`||t===void 0&&(_(e.properties)||e.additionalProperties!==void 0))return at(e,n);if(t===`integer`||t===`number`){let t={kind:`number`};return typeof e.format==`string`&&(t.format=e.format),n&&(t.nullable=!0),Array.isArray(e.enum)&&(t.enum=x(e.enum)),typeof e[`x-map-key-ref`]==`string`&&(t[`x-map-key-ref`]=e[`x-map-key-ref`]),t}if(t===`string`){let t={kind:`string`};return typeof e.format==`string`&&(t.format=e.format),n&&(t.nullable=!0),Array.isArray(e.enum)&&(t.enum=x(e.enum)),typeof e[`x-map-key-ref`]==`string`&&(t[`x-map-key-ref`]=e[`x-map-key-ref`]),t}if(t===`boolean`){let e={kind:`boolean`};return n&&(e.nullable=!0),e}return t===`null`?{kind:`null`}:{kind:`unknown`}}function at(e,t){let n={kind:`object`};if(t&&(n.nullable=!0),_(e.properties)){let t=v(e.required)?e.required.filter(e=>typeof e==`string`):[],r={};for(let[n,i]of Object.entries(e.properties))r[n]={required:t.includes(n),schema:L(i)};n.properties=r,t.length>0&&(n.required=t)}return e.additionalProperties!==void 0&&(n.additionalProperties=typeof e.additionalProperties==`boolean`?e.additionalProperties:L(e.additionalProperties)),typeof e[`x-map-key-ref`]==`string`&&(n[`x-map-key-ref`]=e[`x-map-key-ref`]),n}function ot(e){if(_(e.schema))return L(e.schema);let t={};return e.enum!==void 0&&(t.enum=e.enum),typeof e.format==`string`&&(t.format=e.format),typeof e.type==`string`&&(t.type=e.type),L(t)}function st(e,t){let n={},r=_(e.definitions)?e.definitions:{};for(let[e,t]of Object.entries(r))n[e]=L(t);let i=lt(e,`swagger2`,t);return{components:{schemas:n},key:``,paths:i}}function ct(e,t){let n={},r=_(e.components)?e.components:{},i=_(r.schemas)?r.schemas:{};for(let[e,t]of Object.entries(i))n[e]=L(t);let a=lt(e,`openapi3`,t);return{components:{schemas:n},key:``,paths:a}}function lt(e,t,n){let r=[],i=e.paths;if(!_(i))return r;for(let[e,a]of Object.entries(i)){if(n.pathPrefix!==void 0&&!e.startsWith(n.pathPrefix)||n.ignorePaths?.includes(e)||!_(a))continue;let i=et(a.parameters),o=[];for(let e of $e){let n=a[e];if(!_(n))continue;let r=pt(e,n,i,t);o.push(r)}o.length>0&&r.push({cleanPath:nt(e),operations:o,path:e})}return r}function ut(e,t){let n=new Map;for(let t of e)typeof t.name==`string`&&n.set(t.name,t);for(let e of t)typeof e.name==`string`&&n.set(e.name,e);return[...n.values()]}function dt(e){return _(e.schema)?L(e.schema):{kind:`unknown`}}function ft(e,t){return t===`openapi3`?dt(e):ot(e)}function pt(e,t,n,r){let i=ut(n,et(t.parameters)),a=[],o=[];for(let e of i)if(typeof e.name==`string`){if(e.in===`path`){let t={name:e.name,schema:ft(e,r)},n=I(e);n!==void 0&&(t.description=n),e.deprecated===!0&&(t.deprecated=!0),a.push(t)}else if(e.in===`query`){let t={name:e.name,required:e.required===!0,schema:ft(e,r)},n=I(e);n!==void 0&&(t.description=n),e.deprecated===!0&&(t.deprecated=!0),o.push(t)}}let s=r===`swagger2`?mt(i):ht(t),c={method:e,pathParams:a,queryParams:o,responses:gt(t,r)};typeof t.operationId==`string`&&(c.operationId=t.operationId),typeof t.summary==`string`&&(c.summary=t.summary);let l=I(t);return l!==void 0&&(c.description=l),t.deprecated===!0&&(c.deprecated=!0),s!==void 0&&(c.requestBody=s),c}function mt(e){let t=e.find(e=>e.in===`body`);if(t===void 0)return;let n=_(t.schema)?L(t.schema):{kind:`unknown`},r={required:t.required===!0,schema:n},i=I(t);return i!==void 0&&(r.description=i),r}function ht(e){if(!_(e.requestBody))return;let t=e.requestBody,n=_(t.content)?t.content:{},r=_(n[`application/json`])?n[`application/json`]:{},i=_(r.schema)?L(r.schema):{kind:`unknown`},a={required:t.required===!0,schema:i},o=I(t);return o!==void 0&&(a.description=o),a}function gt(e,t){let n=[];if(!_(e.responses))return n;for(let[r,i]of Object.entries(e.responses)){if(!_(i)){n.push({statusCode:r});continue}let e={statusCode:r},a=I(i);if(a!==void 0&&(e.description=a),t===`swagger2`)_(i.schema)&&(e.schema=L(i.schema));else{let t=_(i.content)?i.content:{},n=_(t[`application/json`])?t[`application/json`]:{};_(n.schema)&&(e.schema=L(n.schema))}n.push(e)}return n}function _t(e,t){if(!_(e))return{components:{schemas:{}},key:``,paths:[]};let n={};return t.pathPrefix!==void 0&&(n.pathPrefix=t.pathPrefix),t.ignorePaths!==void 0&&(n.ignorePaths=t.ignorePaths),e.swagger===`2.0`?st(e,n):typeof e.openapi==`string`&&e.openapi.startsWith(`3.`)?ct(e,n):{components:{schemas:{}},key:``,paths:[]}}function vt(){return process.env.NO_COLOR===void 0&&process.stdout.isTTY===!0}function R(e,t){return vt()?e(t):t}function z(e){return R(d.bold,e)}function B(e){return R(d.red,e)}function V(e){return R(d.dim,e)}function H(e){return R(d.cyan,e)}function U(e){return R(d.yellow,e)}function yt(e){return R(d.white,e)}var W=class extends Error{cycle;schemaPath;sourceKey;constructor(e,t,n){super(bt(e,t,n)),this.name=`RecursiveRefError`,this.cycle=t,this.schemaPath=n,this.sourceKey=e}};function bt(e,t,n){return[z(B(`typeforge: recursive schema reference in source "${e}"`)),``,z(`Cycle:`),` ${t.join(` → `)}`,``,z(`At:`),V(` ${n}`),``,z(`Fix:`),` • Add a known-type override in known-types.ts for this shape, or`,` • Simplify the OpenAPI schema to remove the circular reference`,H(` • typeforge generate --source ${e} --spec <path>`)].join(`
|
|
11
|
+
`)}function xt(e,t){let n=e.kind===`ref`?j(e,t):e;return n.kind===`object`?n:void 0}function St(e){return e.slice().toSorted((e,t)=>e.localeCompare(t))}function Ct(e,t,n){let r=xt(e,t);if(r?.properties===void 0)return!1;let i=St(Object.keys(r.properties)),a=St(n);return i.length===a.length&&i.every((e,t)=>e===a[t])}function wt(e,t,n){let r=xt(e,t);if(r?.properties===void 0)return!1;let i=Object.keys(r.properties);if(n.maxPropertyCount!==void 0&&i.length>n.maxPropertyCount||n.exactProperties!==void 0&&!Ct(e,t,n.exactProperties))return!1;if(n.requireProperties!==void 0){for(let e of n.requireProperties)if(!(e in r.properties))return!1}if(n.excludeProperties!==void 0){for(let e of n.excludeProperties)if(e in r.properties)return!1}return n.exactProperties!==void 0||n.requireProperties!==void 0}function G(e){if(e===void 0)return;let t=[...e.matchAll(/["'`]([^"'`]+)["'`]/g)].map(e=>e[1]);return t.length>0?t:void 0}function Tt(e){let t=[],n=e.matchAll(/\{([^{}]*(?:\{[^{}]*\}[^{}]*)*)\}/g);for(let e of n){let n=e[1];if(n===void 0||!n.includes(`typeName`))continue;let r=n.match(/name:\s*["'`]([^"'`]+)["'`]/)?.[1],i=n.match(/typeName:\s*["'`]([^"'`]+)["'`]/)?.[1];if(r===void 0||i===void 0)continue;let a={name:r,typeName:i},o=n.match(/importPath:\s*(null|["'`]([^"'`]*)["'`])/)?.[2];n.includes(`importPath: null`)?a.importPath=null:o!==void 0&&(a.importPath=o);let s=G(n.match(/exactProperties:\s*\[([\s\S]*?)\]/)?.[1]);s!==void 0&&(a.exactProperties=s);let c=G(n.match(/requireProperties:\s*\[([\s\S]*?)\]/)?.[1]);c!==void 0&&(a.requireProperties=c);let l=G(n.match(/excludeProperties:\s*\[([\s\S]*?)\]/)?.[1]);l!==void 0&&(a.excludeProperties=l);let u=n.match(/maxPropertyCount:\s*(\d+)/)?.[1];u!==void 0&&(a.maxPropertyCount=Number.parseInt(u,10)),t.push(a)}return t}function Et(t,r){let i=u(t,r,`known-types.ts`);return e(i)?Tt(n(i,`utf8`)).map(e=>({importPath:e.importPath??null,matcher:(t,n)=>wt(t,n,e),name:e.name,typeName:e.typeName})):[]}function Dt(e,t){return Et(e,t)}function Ot(e,t,n){for(let r of n)if(r.matcher(e,t))return{importPath:r.importPath,rule:r,typeName:r.typeName}}function K(e){return` `.repeat(e)}function kt(e){return typeof e==`string`?JSON.stringify(e):typeof e==`number`||typeof e==`boolean`?String(e):e===null?`null`:`unknown`}function At(e){return[...new Set(e.map(kt))].join(` | `)}function q(e,t){return t.nullable===!0?`${e} | null`:e}function jt(e){return decodeURIComponent(e.replace(/~1/g,`/`).replace(/~0/g,`~`))}function Mt(e,t){if(Array.isArray(e)){let n=Number(t);return!Number.isInteger(n)||n<0||n>=e.length?void 0:e[n]}if(_(e)&&t in e)return e[t]}function Nt(e,t){if(!t.startsWith(`#/`))return;let n=e;for(let e of t.slice(2).split(`/`).map(jt))if(n=n===void 0?void 0:Mt(n,e),n===void 0)return;return L(n)}function Pt(e,t){let n=e[`x-map-key-ref`];if(n===void 0)return`string`;if(t.rawSpec!==void 0){let e=Nt(t.rawSpec,n);if(e!==void 0)return X(e,{...t,depth:(t.depth??0)+1})}let r=n.split(`/`).pop();return r!==void 0&&t.components[r]!==void 0?X(t.components[r],{...t,depth:(t.depth??0)+1}):`string`}function Ft(e,t){let n=[...e.refStack??[],t];throw new W(e.sourceKey??`unknown`,n,e.schemaPath??t)}function J(e,t){let n=e.schemaPath??`schema`;return{...e,schemaPath:`${n}.${t}`}}function Y(e,t){let n={},r=new Set,i=e;for(;i!==void 0&&(n.description===void 0&&i.description?.trim().length&&(n.description=i.description),i.deprecated===!0&&(n.deprecated=!0),!(i.kind!==`ref`||i.ref===void 0||r.has(i.ref)));)r.add(i.ref),i=t[i.ref];return n}function X(e,t){let n=t.depth??0,r=t.maxDepth??50;if(n>r)throw new W(t.sourceKey??`unknown`,t.refStack??[],`${t.schemaPath??`schema`} (max depth ${r} exceeded)`);let i={...t,depth:n+1},a=t.knownTypes??[];if(a.length>0){let n=Ot(e,t.components,a);if(n!==void 0)return t.knownTypeImports!==void 0&&!t.knownTypeImports.has(n.typeName)&&t.knownTypeImports.set(n.typeName,n.importPath),q(n.typeName,e)}if(e.enum!==void 0&&e.enum.length>0)return q(At(e.enum),e);if(e.kind===`ref`){let n=Be(e);if(n===void 0)return`unknown`;let r=t.visitedRefs??new Set,a=t.refStack??[];return r.has(n)&&Ft(t,n),X(j(e,t.components),{...i,refStack:[...a,n],visitedRefs:new Set([...r,n])})}switch(e.kind){case`string`:return q(`string`,e);case`number`:return q(`number`,e);case`boolean`:return q(`boolean`,e);case`null`:return`null`;case`unknown`:return`unknown`;case`array`:{let t=e.items===void 0?`unknown`:X(e.items,J(i,`[]`));return q(t===`TiptapDocument`?`TiptapDocument`:`${t.includes(` | `)?`(${t})`:t}[]`,e)}case`object`:{if(e.properties===void 0)return e.additionalProperties===!0?q(`Record<string, unknown>`,e):typeof e.additionalProperties==`object`&&e.additionalProperties!==null?q(`Record<${t.resolveMapKeyRefs!==!1&&e[`x-map-key-ref`]!==void 0?Pt(e,t):`string`}, ${X(e.additionalProperties,J(i,`value`))}>`,e):q(`Record<string, unknown>`,e);let r=[`{`];for(let[a,o]of Object.entries(e.properties)){let e=o.required?``:`?`,s=X(o.schema,J(i,a));r.push(...k(Y(o.schema,t.components),K(n+1))),r.push(`${K(n+1)}${a}${e}: ${s};`)}return r.push(`${K(n)}}`),q(r.join(`
|
|
12
|
+
`),e)}case`oneOf`:case`anyOf`:{let t=e[e.kind];if(t===void 0||t.length===0)return`unknown`;let n=t.map(e=>X(e,i)),r=n.filter(e=>e!==`Record<string, unknown>`);return q((r.length>0?r:n).join(` | `),e)}case`allOf`:{let t=e.allOf;return t===void 0||t.length===0?`unknown`:q(t.map(e=>X(e,i)).join(` & `),e)}default:return`unknown`}}function Z(e,t,n){let r={components:e.source.components.schemas,knownTypeImports:n,knownTypes:e.knownTypes??[],maxDepth:e.maxRenderDepth??50,resolveMapKeyRefs:e.resolveMapKeyRefs!==!1,schemaPath:t};return e.sourceKey!==void 0&&(r.sourceKey=e.sourceKey),e.rawSpec!==void 0&&(r.rawSpec=e.rawSpec),r}function It(e){let t=[],n=new Map;for(let[t,r]of e.entries()){let e=n.get(r)??[];e.push(t),n.set(r,e)}for(let[e,r]of n.entries())e!==null&&t.push(`import type { ${r.join(`, `)} } from "${e}";`);return t}function Q(e,t){let n={},r=e.find(e=>e!==void 0&&e.trim().length>0);return r!==void 0&&(n.description=r),t&&(n.deprecated=!0),n}function $(e,t){let n=k(t);return n.length===0?e:[...n,e].join(`
|
|
13
|
+
`)}function Lt(e,t,n,r){if(t.queryParams.length===0)return;let i=n.queryExtends,a=i?.page??`page`,o=i?.limit??`limit`,s=i?.sortBy??`sortBy`,c=i?.sortOrder??`sortOrder`,l=t.queryParams.some(e=>e.name===a),u=t.queryParams.some(e=>e.name===o),d=t.queryParams.find(e=>e.name===s),f=t.queryParams.some(e=>e.name===c),p=l&&u,m=d!==void 0&&f,h=new Set([p?a:void 0,p?o:void 0,m?s:void 0,m?c:void 0].filter(e=>e!==void 0)),g=t.queryParams.filter(e=>!h.has(e.name)),_=[];if(m&&d!==void 0&&d.schema.enum!==void 0&&d.schema.enum.length>0&&i?.sortTypeName!==void 0){let e=[...new Set(d.schema.enum.map(e=>JSON.stringify(e)))].join(` | `);_.push(`${i.sortTypeName}<${e}>`),i.sortImportPath!==void 0&&r.set(i.sortTypeName,i.sortImportPath)}if(p&&i?.paginationTypeName!==void 0&&(_.push(i.paginationTypeName),i.paginationImportPath!==void 0&&r.set(i.paginationTypeName,i.paginationImportPath)),_.length>0&&g.length===0)return $(`export type ${e}Params = ${_.join(` & `)};`,Q([],t.deprecated===!0));let v=[];v.push(...k(Q([],t.deprecated===!0))),_.length>0?v.push(`export interface ${e}Params extends ${_.join(`, `)} {`):v.push(`export interface ${e}Params {`);for(let t of g)Rt(t,v,n,r,e);return v.push(`}`),v.join(`
|
|
14
|
+
`)}function Rt(e,t,n,r,i){let a=e.required?``:`?`,o=X(e.schema,Z(n,`${i}Params.${e.name}`,r)),s=Y(e.schema,n.source.components.schemas);t.push(...k(Q([e.description,s.description],e.deprecated===!0||s.deprecated===!0),` `)),t.push(` ${e.name}${a}: ${o};`)}function zt(e,t,n,r){if(!Se(t)||t.requestBody===void 0)return;let i=X(t.requestBody.schema,Z(n,`${e}Body`,r)),a=Y(t.requestBody.schema,n.source.components.schemas),o=Q([t.requestBody.description,a.description],t.deprecated===!0||a.deprecated===!0);return i.startsWith(`{`)?$(`export interface ${e}Body ${i}`,o):$(`export type ${e}Body = ${i};`,o)}function Bt(e,t){return M(e,t)??e}function Vt(e,t,n,r,i,a){let o=we(t);if(o===void 0)return`export type ${e}Response = unknown;`;let s=Bt(o,n.source.components.schemas),c=s.kind===`object`&&s.properties?.data!==void 0?s.properties.data.schema:void 0,l=s.kind===`object`&&s.properties?.success!==void 0&&We(o,n.source.components.schemas);return n.unwrapResponseData===!0&&l?c===void 0?`export type ${e}Response = null;`:`export type ${e}Response = ${X(c,Z(n,`${e}Response.data`,i))};`:c===void 0?`export type ${e}Response = ${X(o,Z(n,`${e}Response`,i))};`:r===`shared`||r===`mixed`&&n.sharedEnvelope!==void 0&&He(o,n.source.components.schemas,n.sharedEnvelope)?`export type ${e}Response = import("${a}").BaseResponse<${X(c,Z(n,`${e}Response.data`,i))}> & Omit<${X(o,Z(n,`${e}Response`,i))}, "data">;`:`export type ${e}Response = ${X(o,Z(n,`${e}Response`,i))};`}function Ht(e,t,n,r,i,a){let o=we(t),s=o===void 0?t.responses.find(e=>e.statusCode.startsWith(`2`)):t.responses.find(e=>e.schema===o),c=o===void 0?{}:Y(o,n.source.components.schemas),l=Q([c.description,s?.description],t.deprecated===!0||c.deprecated===!0);return $(Vt(e,t,n,r,i,a),l)}function Ut(e){let t=[];for(let n of e.source.paths)for(let r of n.operations){let i=xe(n.cleanPath,r.method),a=new Map,o=[`// Auto-generated from OpenAPI spec`,`// Path: ${r.method.toUpperCase()} ${n.path}`,`// DO NOT EDIT - This file is automatically generated`,``],s=Lt(i,r,e,a);s!==void 0&&o.push(s,``);let c=zt(i,r,e,a);c!==void 0&&o.push(c,``);let l=de({fromAbsolutePath:`${e.typesDir}/${n.cleanPath}/${r.method.toUpperCase()}.d.ts`,toAbsolutePath:e.baseFile.replace(/\.d\.ts$/,``).replace(/\.ts$/,``),...e.tsconfigPaths===void 0?{}:{tsconfigPaths:e.tsconfigPaths}});o.push(Ht(i,r,e,e.envelopeMode,a,l));let u=It(a),d=[...u,...u.length>0?[``]:[],...o].join(`
|
|
15
|
+
`).trimEnd();t.push({content:`${d}\n`,relativePath:`${n.cleanPath}/${r.method.toUpperCase()}.d.ts`})}return t}function Wt(e){return[`// Auto-generated from OpenAPI spec`,`// DO NOT EDIT - This file is automatically generated`,``,Qe(e),``].join(`
|
|
16
|
+
`)}function Gt(e,t,n,r,i,a=[]){let o=[z(B(`typeforge: base response mismatch in source "${e}"`)),``];o.push(z(`Spec envelope:`));for(let e of t.fields)o.push(` ${e.name}${e.required?``:`?`}: ${e.kind}`);o.push(``),o.push(z(`Your ${n} BaseResponse:`)),o.push(r),o.push(``),o.push(z(`Conflicts:`));for(let e of i)e.issue===`missing`?o.push(U(` • ${e.field}: present in spec, missing in your type`)):e.issue===`extra`?o.push(U(` • ${e.field}: extra field in your type`)):e.issue===`type-changed`?o.push(U(` • ${e.field}: spec is ${e.spec?.kind}, your type is ${e.user?.kind}`)):o.push(U(` • ${e.field}: required/optional mismatch`));if(a.length>0){o.push(``),o.push(V(`Also not matching the spec envelope:`));for(let e of a.slice(0,3))o.push(V(` ${e.method} ${e.path}`))}return o.push(``),o.push(z(`Fix:`)),o.push(` • Update models.ts to match the spec, or`),o.push(H(` • typeforge generate --source ${e} --spec <path> --accept-base`)),o.join(`
|
|
17
|
+
`)}function Kt(e,t,n,r){let i=`${` `.repeat(e+1)}:${`${` `.repeat(Math.max(n-t,1))}|`}`;return r===void 0?i:`${i}\n${` `.repeat(e+n+3)}\`${V(`-- ${r}`)}`}function qt(e){return[V(` ,-[${e.file}:${e.line}:${e.column}]`),yt(`${String(e.line).padStart(4,` `)} | ${e.source}`),Kt(7+e.highlightStart,e.highlightStart,e.highlightEnd,e.label),V(" `----")].join(`
|
|
18
|
+
`)}function Jt(e){let t=[` ${(e.severity??`error`)===`error`?B(`×`):U(`!`)} ${z(`${e.code}`)}: ${e.message}`];return e.snippet!==void 0&&t.push(qt(e.snippet)),e.help!==void 0&&t.push(` ${V(`help:`)} ${e.help}`),t.join(`
|
|
19
|
+
`)}function Yt(e,t){return[z(e),...t.map(e=>` ${H(e)}`)].join(`
|
|
20
|
+
`)}async function Xt(e){let t;switch(e.kind){case`file`:t=u(e.path);break;case`local-override`:t=u(e.path);break;case`env`:{let n=process.env[e.varName];if(n===void 0)throw Error(`Environment variable ${e.varName} is not set`);t=u(n);break}}return y(await p(t,`utf8`))}function Zt(t,r){if(r.specFlag!==void 0)return{kind:`file`,path:r.specFlag};let i=`OPENAPI_SPEC_${t.toUpperCase().replace(/-/g,`_`)}`;if(process.env[i]!==void 0)return{kind:`env`,varName:i};if(r.sourceConfigSpec!==void 0)return{kind:`file`,path:r.sourceConfigSpec};let a=r.localOverridePath??`./typeforge.local.json`;if(e(a))try{let e=b(n(a,`utf8`))[t];if(typeof e==`string`)return{kind:`local-override`,path:e}}catch{}if(r.snapshotPath!==void 0&&e(r.snapshotPath))return{kind:`file`,path:r.snapshotPath};throw Error($t(t,i,r,a))}function Qt(t){return t===void 0?V(`not configured`):e(t)?V(`found at ${t}`):V(`not found at ${t}`)}function $t(t,n,r,i){let a=r.specFlag===void 0?V(`not provided`):r.specFlag,o=V(`not set`),s=r.sourceConfigSpec===void 0?V(`not set in source.ts`):r.sourceConfigSpec,c=e(i)?V(`found at ${i} (no entry for "${t}")`):V(`not found at ${i}`),{snapshotPath:l}=r,u=Qt(l),d=[` --spec flag: ${a}`,` ${n} env: ${o}`,` source.ts spec: ${s}`,` local override: ${c}`,` committed snapshot: ${u}`].join(`
|
|
21
|
+
`),f=[`typeforge generate --source ${t} --spec ./path/to/swagger.json`,`export ${n}=./path/to/swagger.json`];return[Jt({code:`typeforge/spec-not-found`,help:`Provide one of the resolution paths above, for example with --spec or an env var.`,message:`No OpenAPI spec found for source "${t}"`,severity:`error`}),``,z(`Tried:`),d,``,Yt(`Fix:`,f)].join(`
|
|
22
|
+
`)}async function en(e,t=!1){let n=[];for(let r of e){await f(o(r.path),{recursive:!0});let e;try{e=await p(r.path,`utf8`)}catch{e=void 0}e!==r.content&&(n.push(r.path),t||await m(r.path,r.content,`utf8`))}return{changed:n,written:t?0:n.length}}function tn(e,t){let n=D(e).apiRoot??`src/api`,r=ee(e,n,t),i=u(e,n,t),a=s(i,`generated`),c=r.functionsDir===void 0?s(a,`functions`):u(e,r.functionsDir),l=r.typesDir===void 0?s(a,`types`):u(e,r.typesDir);return{apiRoot:n,baseFile:r.typesDir===void 0?s(a,`base.ts`):s(o(l),`base.d.ts`),cwd:e,functionsDir:c,generatedDir:a,hasQueryScope:r.tanstackQuery===!0&&ne(e,n),httpMode:re(e,n),routesFile:s(a,`routes.ts`),snapshotPath:s(i,`spec.json`),sourceConfig:r,sourceDir:i,sourceKey:t,typesDir:l}}function nn(e,t,n){let r=Ke(t);if(r.mode!==`shared`||r.shared===void 0)return{mode:r.mode};let i=te(e.cwd,e.apiRoot);if(i===void 0)return{mode:r.mode};let a=Je(i);if(a===void 0)return{mode:r.mode};let o=Xe(r.shared,a);if(o.length===0||n)return{mode:r.mode};let s=a.fields.map(e=>` ${e.name}${e.required?``:`?`}: ${e.kind};`).join(`
|
|
23
|
+
`);return{error:Gt(e.sourceKey,r.shared,a.sourcePath,s,o),mode:r.mode}}function rn(t,r,i){let o=u(t,r,`models.ts`);if(!e(o))return;let s=n(o,`utf8`).replace(/export\s+interface\s+BaseResponse\s*<[^>]*>\s*\{[\s\S]*?\}/,i);a(o,s,`utf8`)}async function an(t){let r=t.cwd??process.cwd(),i=tn(r,t.sourceKey),a={snapshotPath:i.snapshotPath};t.specFlag!==void 0&&(a.specFlag=t.specFlag),i.sourceConfig.spec!==void 0&&(a.sourceConfigSpec=i.sourceConfig.spec);let o=await Xt(Zt(t.sourceKey,a)),c={};i.sourceConfig.ignorePaths!==void 0&&(c.ignorePaths=i.sourceConfig.ignorePaths),i.sourceConfig.pathPrefix!==void 0&&(c.pathPrefix=i.sourceConfig.pathPrefix);let l=_t(o,c);l.key=t.sourceKey;let u=nn(i,l,t.acceptBase===!0);if(u.error!==void 0)throw Error(u.error);let d=Ke(l),f=[],p=qe(d);p!==void 0&&(f.push({content:Wt(p),path:i.baseFile}),t.acceptBase===!0&&rn(r,i.apiRoot,Qe(p)));let m={baseFile:i.baseFile,envelopeMode:d.mode,knownTypes:Dt(r,i.apiRoot),source:l,sourceKey:t.sourceKey,typesDir:i.typesDir};i.sourceConfig.resolveMapKeyRefs!==void 0&&(m.resolveMapKeyRefs=i.sourceConfig.resolveMapKeyRefs),i.sourceConfig.unwrapResponseData!==void 0&&(m.unwrapResponseData=i.sourceConfig.unwrapResponseData),p!==void 0&&(m.sharedEnvelope=p);let h=oe(i.typesDir);h!==void 0&&(m.tsconfigPaths=h),i.sourceConfig.maxRenderDepth!==void 0&&(m.maxRenderDepth=i.sourceConfig.maxRenderDepth),i.sourceConfig.queryExtends!==void 0&&(m.queryExtends=i.sourceConfig.queryExtends),_(o)&&(m.rawSpec=o);let g=Ut(m);for(let e of g)f.push({content:e.content,path:s(i.typesDir,e.relativePath)});let v=i.sourceConfig.routeEnumName??`RouteTargets`,y={paths:l.paths,routeEnumName:v};i.sourceConfig.stripApiPrefix===!0&&(y.stripApiPrefix=!0);let b=Le(y),x=b;i.sourceConfig.generationMode===`merge`&&e(i.routesFile)&&(x=Re(n(i.routesFile,`utf8`),b,v,i.sourceConfig.pathPrefix)),f.push({content:x,path:i.routesFile}),f.push({content:Ne({hasQueryScope:i.hasQueryScope,httpMode:i.httpMode}),path:s(i.generatedDir,`runtime.ts`)});let S=oe(i.functionsDir),C={functionsDir:i.functionsDir,generatedDir:i.generatedDir,hasQueryScope:i.hasQueryScope,httpMode:i.httpMode,paths:l.paths,routeEnumName:v,typesDir:i.typesDir};i.sourceConfig.importBase===void 0?S!==void 0&&(C.tsconfigPaths=S):C.importBase=i.sourceConfig.importBase;let w=Ae(C);for(let e of w)f.push({content:e.content,path:s(i.functionsDir,e.relativePath)});return{changed:(await en(f,t.check===!0)).changed,check:t.check===!0,files:f.length,sourceKey:t.sourceKey}}function on(e){return e===`packages`?`packages/utils/src/api`:`src/api`}function sn(n,r){return e(n)?`skipped`:(t(s(n,`..`),{recursive:!0}),a(n,r,`utf8`),`created`)}function cn(n){let r=n.cwd??process.cwd(),i=n.layout??`monolith`,o=u(r,`typeforge.json`),c=D(r),l=e(o)?c.apiRoot??`src/api`:on(i),d=u(r,l),f=s(d,n.sourceKey),p=`import type { HTTPFetch, HTTPFetchConfig } from "@openmirai/typeforge/http";
|
|
24
|
+
|
|
25
|
+
export type { HTTPFetch, HTTPFetchConfig };
|
|
26
|
+
|
|
27
|
+
export const httpFetch: HTTPFetch = {
|
|
28
|
+
delete: async <TResponse>(
|
|
29
|
+
_route: string,
|
|
30
|
+
_config?: HTTPFetchConfig
|
|
31
|
+
): Promise<{ data: TResponse }> => {
|
|
32
|
+
throw new Error("Implement httpFetch.delete");
|
|
33
|
+
},
|
|
34
|
+
get: async <TResponse>(
|
|
35
|
+
_route: string,
|
|
36
|
+
_config?: HTTPFetchConfig
|
|
37
|
+
): Promise<{ data: TResponse }> => {
|
|
38
|
+
throw new Error("Implement httpFetch.get");
|
|
39
|
+
},
|
|
40
|
+
patch: async <TResponse, TBody = unknown>(
|
|
41
|
+
_route: string,
|
|
42
|
+
_body: TBody,
|
|
43
|
+
_config?: HTTPFetchConfig
|
|
44
|
+
): Promise<{ data: TResponse }> => {
|
|
45
|
+
throw new Error("Implement httpFetch.patch");
|
|
46
|
+
},
|
|
47
|
+
post: async <TResponse, TBody = unknown>(
|
|
48
|
+
_route: string,
|
|
49
|
+
_body: TBody,
|
|
50
|
+
_config?: HTTPFetchConfig
|
|
51
|
+
): Promise<{ data: TResponse }> => {
|
|
52
|
+
throw new Error("Implement httpFetch.post");
|
|
53
|
+
},
|
|
54
|
+
put: async <TResponse, TBody = unknown>(
|
|
55
|
+
_route: string,
|
|
56
|
+
_body: TBody,
|
|
57
|
+
_config?: HTTPFetchConfig
|
|
58
|
+
): Promise<{ data: TResponse }> => {
|
|
59
|
+
throw new Error("Implement httpFetch.put");
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
`;n.client===`axios`?p=`import axiosBase from "axios";
|
|
63
|
+
import { createAxiosAdapter } from "@openmirai/typeforge/adapters/axios";
|
|
64
|
+
|
|
65
|
+
const axios = axiosBase.create({
|
|
66
|
+
baseURL: process.env.NEXT_PUBLIC_API_URL,
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
axios.interceptors.request.use(
|
|
70
|
+
async (config) => {
|
|
71
|
+
// Add auth headers, tracing, or Content-Type defaults here.
|
|
72
|
+
return config;
|
|
73
|
+
},
|
|
74
|
+
(error) => Promise.reject(error),
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
axios.interceptors.response.use(
|
|
78
|
+
(response) => response,
|
|
79
|
+
(error) => Promise.reject(error),
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
export const httpFetch = createAxiosAdapter(axios);
|
|
83
|
+
export { axios };
|
|
84
|
+
export type { HTTPFetch, HTTPFetchConfig } from "@openmirai/typeforge/adapters/axios";
|
|
85
|
+
`:n.client===`fetch`&&(p=`import { createFetchAdapter } from "@openmirai/typeforge/adapters/fetch";
|
|
86
|
+
|
|
87
|
+
export const httpFetch = createFetchAdapter({
|
|
88
|
+
baseURL: process.env.NEXT_PUBLIC_API_URL,
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
export type { HTTPFetch, HTTPFetchConfig } from "@openmirai/typeforge/adapters/fetch";
|
|
92
|
+
`);let m=[],h=[],g=s(d,`http.ts`);sn(g,p)===`created`?m.push(g):h.push(g);let _=s(f,`source.ts`);sn(_,`import { defineSourceConfig } from "@openmirai/typeforge";
|
|
93
|
+
|
|
94
|
+
export default defineSourceConfig({
|
|
95
|
+
// Path to the OpenAPI spec file, relative to the project root.
|
|
96
|
+
// Set this so \`typeforge generate --source <key>\` (or --all) works
|
|
97
|
+
// without a per-invocation --spec flag.
|
|
98
|
+
// spec: "./specs/acme.json",
|
|
99
|
+
pathPrefix: "/api/acme/v3",
|
|
100
|
+
stripApiPrefix: true,
|
|
101
|
+
routeEnumName: "RouteTargets",
|
|
102
|
+
generationMode: "authoritative",
|
|
103
|
+
naming: "path",
|
|
104
|
+
ignorePaths: [],
|
|
105
|
+
maxRenderDepth: 50,
|
|
106
|
+
resolveMapKeyRefs: true,
|
|
107
|
+
queryExtends: {
|
|
108
|
+
page: "page",
|
|
109
|
+
limit: "limit",
|
|
110
|
+
sortBy: "sortBy",
|
|
111
|
+
sortOrder: "sortOrder",
|
|
112
|
+
paginationTypeName: "OffsetLimitQuery",
|
|
113
|
+
paginationImportPath: "./pagination",
|
|
114
|
+
sortTypeName: "SortParams",
|
|
115
|
+
sortImportPath: "./pagination",
|
|
116
|
+
},
|
|
117
|
+
});
|
|
118
|
+
`)===`created`?m.push(_):h.push(_);let v=s(d,`known-types.ts`);sn(v,`/** Map OpenAPI object shapes to your own TypeScript types by property pattern. */
|
|
119
|
+
export const knownTypes = [
|
|
120
|
+
// {
|
|
121
|
+
// name: "BlobAsset",
|
|
122
|
+
// typeName: "BlobAsset",
|
|
123
|
+
// importPath: "./blob/types",
|
|
124
|
+
// exactProperties: ["id", "url", "file"],
|
|
125
|
+
// },
|
|
126
|
+
// {
|
|
127
|
+
// name: "TiptapNode",
|
|
128
|
+
// typeName: "TiptapNode",
|
|
129
|
+
// importPath: "./tiptap/types",
|
|
130
|
+
// requireProperties: ["type"],
|
|
131
|
+
// excludeProperties: ["courseCount"],
|
|
132
|
+
// },
|
|
133
|
+
];
|
|
134
|
+
`)===`created`?m.push(v):h.push(v);let y=u(r,`typeforge.json`);return e(y)||(a(y,`${JSON.stringify({apiRoot:l},null,2)}\n`,`utf8`),m.push(y)),t(s(f,`generated`),{recursive:!0}),{created:m,skipped:h}}export{Zt as a,W as c,Ke as d,Qe as f,D as g,ie as h,Xt as i,L as l,Je as m,tn as n,Dt as o,Xe as p,an as r,Ot as s,cn as t,_t as u};
|
package/dist/routes/index.d.ts
CHANGED
|
@@ -29,5 +29,4 @@ declare function buildRouteFromRegistry<T extends RouteParamsShape>(routes: Rout
|
|
|
29
29
|
type SearchParamValue = string | number | boolean;
|
|
30
30
|
declare function appendSearchParams(baseUrl: string, params?: Record<string, SearchParamValue | null | undefined>): string;
|
|
31
31
|
//#endregion
|
|
32
|
-
export { type BuildRouteFn, type RouteBuilderFn, type RouteHandlers, type RouteKeyFromParams, type RouteParamsFor, type RouteParamsMap, type RouteParamsShape, type RouteRegistry, type RouteSearchParams, type SearchParamValue, appendSearchParams, buildRouteFromHandlers, buildRouteFromRegistry, createRouteHandlers };
|
|
33
|
-
//# sourceMappingURL=index.d.ts.map
|
|
32
|
+
export { type BuildRouteFn, type RouteBuilderFn, type RouteHandlers, type RouteKeyFromParams, type RouteParamsFor, type RouteParamsMap, type RouteParamsShape, type RouteRegistry, type RouteSearchParams, type SearchParamValue, appendSearchParams, buildRouteFromHandlers, buildRouteFromRegistry, createRouteHandlers };
|
package/dist/routes/index.js
CHANGED
|
@@ -1,38 +1 @@
|
|
|
1
|
-
|
|
2
|
-
function appendSearchParams(baseUrl, params) {
|
|
3
|
-
if (params === void 0 || Object.keys(params).length === 0) return baseUrl;
|
|
4
|
-
const [path, existingQuery] = baseUrl.split("?");
|
|
5
|
-
const searchParams = new URLSearchParams(existingQuery ?? "");
|
|
6
|
-
for (const [key, value] of Object.entries(params)) if (value !== null && value !== void 0) searchParams.set(key, String(value));
|
|
7
|
-
const queryString = searchParams.toString();
|
|
8
|
-
return queryString.length > 0 ? `${path}?${queryString}` : path ?? baseUrl;
|
|
9
|
-
}
|
|
10
|
-
//#endregion
|
|
11
|
-
//#region src/routes/build.ts
|
|
12
|
-
/** Mirrors FE getDynamicRoute, with RouteParams typing and encodeURIComponent. */
|
|
13
|
-
function createRouteHandlers(targets) {
|
|
14
|
-
return Object.fromEntries(Object.entries(targets).map(([key, value]) => {
|
|
15
|
-
if (!/:[^/]+/.test(value)) return [key, value];
|
|
16
|
-
return [key, (params, searchParams) => {
|
|
17
|
-
let result = value;
|
|
18
|
-
for (const [paramKey, paramValue] of Object.entries(params)) result = result.replaceAll(`:${paramKey}`, encodeURIComponent(String(paramValue)));
|
|
19
|
-
return appendSearchParams(result, searchParams);
|
|
20
|
-
}];
|
|
21
|
-
}));
|
|
22
|
-
}
|
|
23
|
-
function buildRouteFromHandlers(routes) {
|
|
24
|
-
const buildRoute = ((key, ...params) => {
|
|
25
|
-
const route = routes[key];
|
|
26
|
-
if (typeof route === "function") return route(params[0]);
|
|
27
|
-
return route;
|
|
28
|
-
});
|
|
29
|
-
return buildRoute;
|
|
30
|
-
}
|
|
31
|
-
/** @deprecated Use createRouteHandlers + buildRouteFromHandlers instead. */
|
|
32
|
-
function buildRouteFromRegistry(routes) {
|
|
33
|
-
return buildRouteFromHandlers(routes);
|
|
34
|
-
}
|
|
35
|
-
//#endregion
|
|
36
|
-
export { appendSearchParams, buildRouteFromHandlers, buildRouteFromRegistry, createRouteHandlers };
|
|
37
|
-
|
|
38
|
-
//# sourceMappingURL=index.js.map
|
|
1
|
+
function e(e,t){if(t===void 0||Object.keys(t).length===0)return e;let[n,r]=e.split(`?`),i=new URLSearchParams(r??``);for(let[e,n]of Object.entries(t))n!=null&&i.set(e,String(n));let a=i.toString();return a.length>0?`${n}?${a}`:n??e}function t(t){return Object.fromEntries(Object.entries(t).map(([t,n])=>/:[^/]+/.test(n)?[t,(t,r)=>{let i=n;for(let[e,n]of Object.entries(t))i=i.replaceAll(`:${e}`,encodeURIComponent(String(n)));return e(i,r)}]:[t,n]))}function n(e){return((t,...n)=>{let r=e[t];return typeof r==`function`?r(n[0]):r})}function r(e){return n(e)}export{e as appendSearchParams,n as buildRouteFromHandlers,r as buildRouteFromRegistry,t as createRouteHandlers};
|
package/dist/validation/zod.d.ts
CHANGED
|
@@ -7,5 +7,4 @@ interface ZodLikeSchema<T> {
|
|
|
7
7
|
}
|
|
8
8
|
declare function createZodValidator<T>(schema: ZodLikeSchema<T>): ResponseValidator<T>;
|
|
9
9
|
//#endregion
|
|
10
|
-
export { type ResponseValidator, ZodLikeSchema, createZodValidator };
|
|
11
|
-
//# sourceMappingURL=zod.d.ts.map
|
|
10
|
+
export { type ResponseValidator, ZodLikeSchema, createZodValidator };
|
package/dist/validation/zod.js
CHANGED
|
@@ -1,8 +1 @@
|
|
|
1
|
-
|
|
2
|
-
function createZodValidator(schema) {
|
|
3
|
-
return (value) => schema.parse(value);
|
|
4
|
-
}
|
|
5
|
-
//#endregion
|
|
6
|
-
export { createZodValidator };
|
|
7
|
-
|
|
8
|
-
//# sourceMappingURL=zod.js.map
|
|
1
|
+
function e(e){return t=>e.parse(t)}export{e as createZodValidator};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openmirai/typeforge",
|
|
3
|
-
"version": "0.1
|
|
3
|
+
"version": "0.2.1",
|
|
4
4
|
"description": "Typeforge: headless OpenAPI to TypeScript codegen CLI and HTTPFetch runtime",
|
|
5
5
|
"homepage": "https://github.com/openmirai/typeforge#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -12,11 +12,9 @@
|
|
|
12
12
|
"url": "git+https://github.com/openmirai/typeforge.git"
|
|
13
13
|
},
|
|
14
14
|
"bin": {
|
|
15
|
-
"openapi-codegen": "./dist/cli.js",
|
|
16
15
|
"typeforge": "./dist/cli.js"
|
|
17
16
|
},
|
|
18
17
|
"files": [
|
|
19
|
-
"assets/typeforge-logo.png",
|
|
20
18
|
"dist"
|
|
21
19
|
],
|
|
22
20
|
"type": "module",
|
|
@@ -59,6 +57,7 @@
|
|
|
59
57
|
},
|
|
60
58
|
"scripts": {
|
|
61
59
|
"build": "tsdown",
|
|
60
|
+
"check:package": "node scripts/check-package.mjs",
|
|
62
61
|
"typecheck": "tsc -p tsconfig.json --pretty false && tsc -p tsconfig.tools.json --pretty false",
|
|
63
62
|
"format": "oxfmt --check .",
|
|
64
63
|
"format:fix": "oxfmt --write .",
|
|
@@ -69,7 +68,7 @@
|
|
|
69
68
|
"test:coverage": "vitest run --coverage",
|
|
70
69
|
"prepare": "husky",
|
|
71
70
|
"release": "release-it",
|
|
72
|
-
"verify": "pnpm format && pnpm lint && pnpm typecheck && pnpm build && pnpm test:coverage"
|
|
71
|
+
"verify": "pnpm format && pnpm lint && pnpm typecheck && pnpm build && pnpm check:package && pnpm test:coverage"
|
|
73
72
|
},
|
|
74
73
|
"dependencies": {
|
|
75
74
|
"chalk": "5.6.2"
|
|
Binary file
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/json/types.ts","../../../src/http/validate.ts","../../../src/http/types.ts","../../../src/adapters/axios/index.ts"],"mappings":";;KAUY;KAEA,cAAc,eAAe;;;KCZ7B,kBAAkB,MAAM,mBAAmB;;;UCOtC,gBACf,yBAAyB,aACzB;EAEA,SAAS;EACT,SAAS;EACT,UAAU;EACV,mBAAmB,kBAAkB;;UAGtB;EACf,IAAI,WAAW,yBAAyB,aACtC,eACA,SAAS,gBAAgB,SAAS,aACjC;IAAU,MAAM;;EACnB,KAAK,WAAW,iBAAiB,yBAAyB,aACxD,eACA,MAAM,OACN,SAAS,gBAAgB,SAAS,aACjC;IAAU,MAAM;;EACnB,IAAI,WAAW,iBAAiB,yBAAyB,aACvD,eACA,MAAM,OACN,SAAS,gBAAgB,SAAS,aACjC;IAAU,MAAM;;EACnB,MAAM,WAAW,iBAAiB,yBAAyB,aACzD,eACA,MAAM,OACN,SAAS,gBAAgB,SAAS,aACjC;IAAU,MAAM;;EACnB,OAAO,WAAW,yBAAyB,aACzC,eACA,SAAS,gBAAgB,SAAS,aACjC;IAAU,MAAM;;;;;iBCLL,mBAAmB,UAAU,gBAAgB"}
|