@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 CHANGED
@@ -1,5 +1,5 @@
1
1
  <p align="center">
2
- <img src="./assets/typeforge-logo.png" alt="Typeforge logo" width="280" />
2
+ <img src="https://raw.githubusercontent.com/openmirai/typeforge/HEAD/assets/typeforge-logo.png" alt="Typeforge logo" width="280" />
3
3
  </p>
4
4
 
5
5
  # @openmirai/typeforge
@@ -11,10 +11,6 @@ Headless **OpenAPI / Swagger → TypeScript** codegen. The CLI is `typeforge`. I
11
11
 
12
12
  You own `http.ts` (the `HTTPFetch` adapter). Generated files import that adapter — they do not invent axios/fetch calls inline.
13
13
 
14
- ## Migrating from `@openmirai/openapi-codegen`
15
-
16
- Install `@openmirai/typeforge` and update package imports and scripts to use the canonical `typeforge` name. During migration, the package also exposes the legacy `openapi-codegen` binary and reads `openapi-codegen.json`, `openapi-codegen.local.json`, and the `openapiCodegen` package.json key. New projects created by `typeforge init` use the Typeforge names.
17
-
18
14
  ## What it generates
19
15
 
20
16
  For each **source** (a named API, e.g. `atlas`), under `<apiRoot>/<source>/generated/`:
@@ -7,32 +7,43 @@ type QueryParams = Record<string, QueryParamValue>;
7
7
  type ResponseValidator<T> = (value: unknown) => T;
8
8
  //#endregion
9
9
  //#region src/http/types.d.ts
10
+ /** Per-request options accepted by every Typeforge HTTP adapter method. */
10
11
  interface HTTPFetchConfig<TParams extends object = QueryParams, TResponse = unknown> {
12
+ /** Abort signal forwarded to the underlying HTTP client. */
11
13
  signal?: AbortSignal;
14
+ /** Query parameters serialized by the HTTP adapter. */
12
15
  params?: TParams;
16
+ /** Request headers merged with adapter-level defaults. */
13
17
  headers?: Record<string, string>;
18
+ /** Optional runtime validator applied to the response payload. */
14
19
  validateResponse?: ResponseValidator<TResponse>;
15
20
  }
21
+ /** Transport contract consumed by Typeforge-generated API callers. */
16
22
  interface HTTPFetch {
23
+ /** Send a GET request and return its typed response payload. */
17
24
  get<TResponse, TParams extends object = QueryParams>(route: string, config?: HTTPFetchConfig<TParams, TResponse>): Promise<{
18
25
  data: TResponse;
19
26
  }>;
27
+ /** Send a POST request with a typed body and return its typed response payload. */
20
28
  post<TResponse, TBody = unknown, TParams extends object = QueryParams>(route: string, body: TBody, config?: HTTPFetchConfig<TParams, TResponse>): Promise<{
21
29
  data: TResponse;
22
30
  }>;
31
+ /** Send a PUT request with a typed body and return its typed response payload. */
23
32
  put<TResponse, TBody = unknown, TParams extends object = QueryParams>(route: string, body: TBody, config?: HTTPFetchConfig<TParams, TResponse>): Promise<{
24
33
  data: TResponse;
25
34
  }>;
35
+ /** Send a PATCH request with a typed body and return its typed response payload. */
26
36
  patch<TResponse, TBody = unknown, TParams extends object = QueryParams>(route: string, body: TBody, config?: HTTPFetchConfig<TParams, TResponse>): Promise<{
27
37
  data: TResponse;
28
38
  }>;
39
+ /** Send a DELETE request and return its typed response payload. */
29
40
  delete<TResponse, TParams extends object = QueryParams>(route: string, config?: HTTPFetchConfig<TParams, TResponse>): Promise<{
30
41
  data: TResponse;
31
42
  }>;
32
43
  }
33
44
  //#endregion
34
45
  //#region src/adapters/axios/index.d.ts
46
+ /** Create an `HTTPFetch` implementation backed by an Axios instance. */
35
47
  declare function createAxiosAdapter(instance: AxiosInstance): HTTPFetch;
36
48
  //#endregion
37
- export { type HTTPFetch, type HTTPFetchConfig, createAxiosAdapter };
38
- //# sourceMappingURL=index.d.ts.map
49
+ export { type HTTPFetch, type HTTPFetchConfig, createAxiosAdapter };
@@ -1,43 +1 @@
1
- //#region src/http/validate.ts
2
- var ResponseValidationError = class extends Error {
3
- cause;
4
- constructor(message, cause) {
5
- super(message);
6
- this.name = "ResponseValidationError";
7
- this.cause = cause;
8
- }
9
- };
10
- function coerceResponseData(value, validator) {
11
- if (validator === void 0) return value;
12
- try {
13
- return validator(value);
14
- } catch (error) {
15
- throw new ResponseValidationError("Response validation failed", error);
16
- }
17
- }
18
- //#endregion
19
- //#region src/adapters/axios/index.ts
20
- function toAxiosConfig(config) {
21
- if (config === void 0) return;
22
- const axiosConfig = {};
23
- if (config.signal !== void 0) axiosConfig.signal = config.signal;
24
- if (config.params !== void 0) axiosConfig.params = config.params;
25
- if (config.headers !== void 0) axiosConfig.headers = config.headers;
26
- return axiosConfig;
27
- }
28
- function mapResponse(data, config) {
29
- return { data: coerceResponseData(data, config?.validateResponse) };
30
- }
31
- function createAxiosAdapter(instance) {
32
- return {
33
- delete: (route, config) => instance.delete(route, toAxiosConfig(config)).then((response) => mapResponse(response.data, config)),
34
- get: (route, config) => instance.get(route, toAxiosConfig(config)).then((response) => mapResponse(response.data, config)),
35
- patch: (route, body, config) => instance.patch(route, body, toAxiosConfig(config)).then((response) => mapResponse(response.data, config)),
36
- post: (route, body, config) => instance.post(route, body, toAxiosConfig(config)).then((response) => mapResponse(response.data, config)),
37
- put: (route, body, config) => instance.put(route, body, toAxiosConfig(config)).then((response) => mapResponse(response.data, config))
38
- };
39
- }
40
- //#endregion
41
- export { createAxiosAdapter };
42
-
43
- //# sourceMappingURL=index.js.map
1
+ var e=class extends Error{cause;constructor(e,t){super(e),this.name=`ResponseValidationError`,this.cause=t}};function t(t,n){if(n===void 0)return t;try{return n(t)}catch(t){throw new e(`Response validation failed`,t)}}function n(e){if(e===void 0)return;let t={};return e.signal!==void 0&&(t.signal=e.signal),e.params!==void 0&&(t.params=e.params),e.headers!==void 0&&(t.headers=e.headers),t}function r(e,n){return{data:t(e,n?.validateResponse)}}function i(e){return{delete:(t,i)=>e.delete(t,n(i)).then(e=>r(e.data,i)),get:(t,i)=>e.get(t,n(i)).then(e=>r(e.data,i)),patch:(t,i,a)=>e.patch(t,i,n(a)).then(e=>r(e.data,a)),post:(t,i,a)=>e.post(t,i,n(a)).then(e=>r(e.data,a)),put:(t,i,a)=>e.put(t,i,n(a)).then(e=>r(e.data,a))}}export{i as createAxiosAdapter};
@@ -6,37 +6,52 @@ type QueryParams = Record<string, QueryParamValue>;
6
6
  type ResponseValidator<T> = (value: unknown) => T;
7
7
  //#endregion
8
8
  //#region src/http/types.d.ts
9
+ /** Per-request options accepted by every Typeforge HTTP adapter method. */
9
10
  interface HTTPFetchConfig<TParams extends object = QueryParams, TResponse = unknown> {
11
+ /** Abort signal forwarded to the underlying HTTP client. */
10
12
  signal?: AbortSignal;
13
+ /** Query parameters serialized by the HTTP adapter. */
11
14
  params?: TParams;
15
+ /** Request headers merged with adapter-level defaults. */
12
16
  headers?: Record<string, string>;
17
+ /** Optional runtime validator applied to the response payload. */
13
18
  validateResponse?: ResponseValidator<TResponse>;
14
19
  }
20
+ /** Transport contract consumed by Typeforge-generated API callers. */
15
21
  interface HTTPFetch {
22
+ /** Send a GET request and return its typed response payload. */
16
23
  get<TResponse, TParams extends object = QueryParams>(route: string, config?: HTTPFetchConfig<TParams, TResponse>): Promise<{
17
24
  data: TResponse;
18
25
  }>;
26
+ /** Send a POST request with a typed body and return its typed response payload. */
19
27
  post<TResponse, TBody = unknown, TParams extends object = QueryParams>(route: string, body: TBody, config?: HTTPFetchConfig<TParams, TResponse>): Promise<{
20
28
  data: TResponse;
21
29
  }>;
30
+ /** Send a PUT request with a typed body and return its typed response payload. */
22
31
  put<TResponse, TBody = unknown, TParams extends object = QueryParams>(route: string, body: TBody, config?: HTTPFetchConfig<TParams, TResponse>): Promise<{
23
32
  data: TResponse;
24
33
  }>;
34
+ /** Send a PATCH request with a typed body and return its typed response payload. */
25
35
  patch<TResponse, TBody = unknown, TParams extends object = QueryParams>(route: string, body: TBody, config?: HTTPFetchConfig<TParams, TResponse>): Promise<{
26
36
  data: TResponse;
27
37
  }>;
38
+ /** Send a DELETE request and return its typed response payload. */
28
39
  delete<TResponse, TParams extends object = QueryParams>(route: string, config?: HTTPFetchConfig<TParams, TResponse>): Promise<{
29
40
  data: TResponse;
30
41
  }>;
31
42
  }
32
43
  //#endregion
33
44
  //#region src/adapters/fetch/index.d.ts
45
+ /** Options for the Fetch-based `HTTPFetch` adapter. */
34
46
  interface FetchAdapterOptions {
47
+ /** Base URL prepended to every generated route. */
35
48
  baseURL?: string;
49
+ /** Headers included with every request unless overridden per request. */
36
50
  headers?: Record<string, string>;
51
+ /** Fetch implementation to use, such as a test double or platform polyfill. */
37
52
  fetch?: typeof fetch;
38
53
  }
54
+ /** Create an `HTTPFetch` implementation backed by the Fetch API. */
39
55
  declare function createFetchAdapter(options?: FetchAdapterOptions): HTTPFetch;
40
56
  //#endregion
41
- export { FetchAdapterOptions, type HTTPFetch, type HTTPFetchConfig, createFetchAdapter };
42
- //# sourceMappingURL=index.d.ts.map
57
+ export { FetchAdapterOptions, type HTTPFetch, type HTTPFetchConfig, createFetchAdapter };
@@ -1,77 +1 @@
1
- //#region src/json/types.ts
2
- function isJsonValue(value) {
3
- if (value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean") return true;
4
- if (Array.isArray(value)) return value.every(isJsonValue);
5
- if (typeof value === "object" && value !== null) return Object.values(value).every(isJsonValue);
6
- return false;
7
- }
8
- function parseJson(text) {
9
- const parsed = JSON.parse(text);
10
- if (!isJsonValue(parsed)) throw new TypeError("JSON text did not parse to a valid JSON value");
11
- return parsed;
12
- }
13
- //#endregion
14
- //#region src/http/validate.ts
15
- var ResponseValidationError = class extends Error {
16
- cause;
17
- constructor(message, cause) {
18
- super(message);
19
- this.name = "ResponseValidationError";
20
- this.cause = cause;
21
- }
22
- };
23
- function coerceResponseData(value, validator) {
24
- if (validator === void 0) return value;
25
- try {
26
- return validator(value);
27
- } catch (error) {
28
- throw new ResponseValidationError("Response validation failed", error);
29
- }
30
- }
31
- //#endregion
32
- //#region src/adapters/fetch/index.ts
33
- function appendQuery(url, params) {
34
- if (params === void 0 || Object.keys(params).length === 0) return url;
35
- const search = new URLSearchParams();
36
- for (const [key, value] of Object.entries(params)) search.append(key, String(value));
37
- const query = search.toString();
38
- if (query.length === 0) return url;
39
- return `${url}${url.includes("?") ? "&" : "?"}${query}`;
40
- }
41
- function readResponseBody(text) {
42
- if (text.length === 0) return;
43
- return parseJson(text);
44
- }
45
- async function request(method, route, options, body, config) {
46
- const fetchImpl = options.fetch ?? globalThis.fetch;
47
- const url = appendQuery(`${options.baseURL ?? ""}${route}`, config?.params);
48
- const headers = {
49
- ...options.headers,
50
- ...config?.headers
51
- };
52
- const init = {
53
- headers,
54
- method
55
- };
56
- if (config?.signal !== void 0) init.signal = config.signal;
57
- if (body !== void 0) {
58
- headers["Content-Type"] ??= "application/json";
59
- init.body = JSON.stringify(body);
60
- }
61
- const response = await fetchImpl(url, init);
62
- if (!response.ok) throw new Error(`HTTP ${response.status} ${response.statusText}`);
63
- return { data: coerceResponseData(readResponseBody(await response.text()), config?.validateResponse) };
64
- }
65
- function createFetchAdapter(options = {}) {
66
- return {
67
- delete: (route, config) => request("DELETE", route, options, void 0, config),
68
- get: (route, config) => request("GET", route, options, void 0, config),
69
- patch: (route, body, config) => request("PATCH", route, options, body, config),
70
- post: (route, body, config) => request("POST", route, options, body, config),
71
- put: (route, body, config) => request("PUT", route, options, body, config)
72
- };
73
- }
74
- //#endregion
75
- export { createFetchAdapter };
76
-
77
- //# sourceMappingURL=index.js.map
1
+ function e(t){return t===null||typeof t==`string`||typeof t==`number`||typeof t==`boolean`?!0:Array.isArray(t)?t.every(e):typeof t==`object`&&t?Object.values(t).every(e):!1}function t(t){let n=JSON.parse(t);if(!e(n))throw TypeError(`JSON text did not parse to a valid JSON value`);return n}var n=class extends Error{cause;constructor(e,t){super(e),this.name=`ResponseValidationError`,this.cause=t}};function r(e,t){if(t===void 0)return e;try{return t(e)}catch(e){throw new n(`Response validation failed`,e)}}function i(e,t){if(t===void 0||Object.keys(t).length===0)return e;let n=new URLSearchParams;for(let[e,r]of Object.entries(t))n.append(e,String(r));let r=n.toString();return r.length===0?e:`${e}${e.includes(`?`)?`&`:`?`}${r}`}function a(e){if(e.length!==0)return t(e)}async function o(e,t,n,o,s){let c=n.fetch??globalThis.fetch,l=i(`${n.baseURL??``}${t}`,s?.params),u={...n.headers,...s?.headers},d={headers:u,method:e};s?.signal!==void 0&&(d.signal=s.signal),o!==void 0&&(u[`Content-Type`]??=`application/json`,d.body=JSON.stringify(o));let f=await c(l,d);if(!f.ok)throw Error(`HTTP ${f.status} ${f.statusText}`);return{data:r(a(await f.text()),s?.validateResponse)}}function s(e={}){return{delete:(t,n)=>o(`DELETE`,t,e,void 0,n),get:(t,n)=>o(`GET`,t,e,void 0,n),patch:(t,n,r)=>o(`PATCH`,t,e,n,r),post:(t,n,r)=>o(`POST`,t,e,n,r),put:(t,n,r)=>o(`PUT`,t,e,n,r)}}export{s as createFetchAdapter};
package/dist/cli.d.ts CHANGED
@@ -14,5 +14,4 @@ interface ParsedArgs {
14
14
  }
15
15
  declare function parseArgs(argv: Array<string>): ParsedArgs;
16
16
  //#endregion
17
- export { parseArgs };
18
- //# sourceMappingURL=cli.d.ts.map
17
+ export { parseArgs };
package/dist/cli.js CHANGED
@@ -1,87 +1,5 @@
1
1
  #!/usr/bin/env node
2
- import { g as loadProjectConfig, h as listSourceKeys, r as generateForSource, t as initProject } from "./init-BBNO0SYd.js";
3
- import { realpathSync } from "node:fs";
4
- import { pathToFileURL } from "node:url";
5
- //#region src/cli.ts
6
- function parseArgs(argv) {
7
- const parsed = { sources: [] };
8
- const positional = [];
9
- for (let index = 0; index < argv.length; index += 1) {
10
- const arg = argv[index];
11
- if (arg === void 0) continue;
12
- if (arg === "--check") {
13
- parsed.check = true;
14
- continue;
15
- }
16
- if (arg === "--accept-base") {
17
- parsed.acceptBase = true;
18
- continue;
19
- }
20
- if (arg === "--all") {
21
- parsed.all = true;
22
- continue;
23
- }
24
- if (arg.startsWith("--source=")) {
25
- const value = arg.slice(9);
26
- parsed.sources.push(value);
27
- if (parsed.source === void 0) parsed.source = value;
28
- continue;
29
- }
30
- if (arg === "--source") {
31
- const value = argv[index + 1];
32
- if (value !== void 0) {
33
- parsed.sources.push(value);
34
- if (parsed.source === void 0) parsed.source = value;
35
- index += 1;
36
- }
37
- continue;
38
- }
39
- if (arg.startsWith("--spec=")) {
40
- parsed.spec = arg.slice(7);
41
- continue;
42
- }
43
- if (arg === "--spec") {
44
- const value = argv[index + 1];
45
- if (value !== void 0) {
46
- parsed.spec = value;
47
- index += 1;
48
- }
49
- continue;
50
- }
51
- if (arg.startsWith("--client=")) {
52
- const value = arg.slice(9);
53
- if (value === "axios" || value === "fetch" || value === "custom") parsed.client = value;
54
- continue;
55
- }
56
- if (arg === "--client") {
57
- const value = argv[index + 1];
58
- if (value === "axios" || value === "fetch" || value === "custom") {
59
- parsed.client = value;
60
- index += 1;
61
- }
62
- continue;
63
- }
64
- if (arg.startsWith("--layout=")) {
65
- const value = arg.slice(9);
66
- if (value === "monolith" || value === "packages") parsed.layout = value;
67
- continue;
68
- }
69
- if (arg === "--layout") {
70
- const value = argv[index + 1];
71
- if (value === "monolith" || value === "packages") {
72
- parsed.layout = value;
73
- index += 1;
74
- }
75
- continue;
76
- }
77
- if (!arg.startsWith("-")) positional.push(arg);
78
- }
79
- const command = positional[0];
80
- if (command !== void 0) parsed.command = command;
81
- return parsed;
82
- }
83
- function printHelp() {
84
- process.stdout.write(`typeforge — headless OpenAPI TypeScript codegen
2
+ import{g as e,h as t,r as n,t as r}from"./init-CqBQsEHz.js";import{realpathSync as i}from"node:fs";import{pathToFileURL as a}from"node:url";function o(e){let t={sources:[]},n=[];for(let r=0;r<e.length;r+=1){let i=e[r];if(i!==void 0){if(i===`--check`){t.check=!0;continue}if(i===`--accept-base`){t.acceptBase=!0;continue}if(i===`--all`){t.all=!0;continue}if(i.startsWith(`--source=`)){let e=i.slice(9);t.sources.push(e),t.source===void 0&&(t.source=e);continue}if(i===`--source`){let n=e[r+1];n!==void 0&&(t.sources.push(n),t.source===void 0&&(t.source=n),r+=1);continue}if(i.startsWith(`--spec=`)){t.spec=i.slice(7);continue}if(i===`--spec`){let n=e[r+1];n!==void 0&&(t.spec=n,r+=1);continue}if(i.startsWith(`--client=`)){let e=i.slice(9);(e===`axios`||e===`fetch`||e===`custom`)&&(t.client=e);continue}if(i===`--client`){let n=e[r+1];(n===`axios`||n===`fetch`||n===`custom`)&&(t.client=n,r+=1);continue}if(i.startsWith(`--layout=`)){let e=i.slice(9);(e===`monolith`||e===`packages`)&&(t.layout=e);continue}if(i===`--layout`){let n=e[r+1];(n===`monolith`||n===`packages`)&&(t.layout=n,r+=1);continue}i.startsWith(`-`)||n.push(i)}}let r=n[0];return r!==void 0&&(t.command=r),t}function s(){process.stdout.write(`typeforge — headless OpenAPI TypeScript codegen
85
3
 
86
4
  Usage:
87
5
  typeforge init --source <key> --client axios|fetch|custom [--layout monolith|packages]
@@ -95,88 +13,7 @@ Multi-source generate:
95
13
  Configure per-source spec paths in each source.ts:
96
14
  import { defineSourceConfig } from "@openmirai/typeforge";
97
15
  export default defineSourceConfig({ spec: "./specs/acme.json", ... });
98
- `);
99
- }
100
- async function runGenerate(args) {
101
- if (args.check === true && args.acceptBase === true) {
102
- process.stderr.write("typeforge: --accept-base is not allowed with --check\n");
103
- return 1;
104
- }
105
- const cwd = process.cwd();
106
- const apiRoot = loadProjectConfig(cwd).apiRoot ?? "src/api";
107
- let sources;
108
- if (args.all === true) sources = listSourceKeys(cwd, apiRoot);
109
- else if (args.sources.length > 0) sources = args.sources;
110
- else sources = [];
111
- if (sources.length === 0) {
112
- process.stderr.write("typeforge: --source <key> or --all is required\n");
113
- return 1;
114
- }
115
- let exitCode = 0;
116
- for (const sourceKey of sources) try {
117
- const generateOptions = { sourceKey };
118
- if (args.acceptBase === true) generateOptions.acceptBase = true;
119
- if (args.check === true) generateOptions.check = true;
120
- if (args.spec !== void 0) generateOptions.specFlag = args.spec;
121
- const result = await generateForSource(generateOptions);
122
- if (args.check === true) {
123
- if (result.changed.length > 0) {
124
- process.stderr.write(`typeforge: stale generated files for "${sourceKey}":\n`);
125
- for (const file of result.changed) process.stderr.write(` ${file}\n`);
126
- exitCode = 1;
127
- } else process.stdout.write(`typeforge: "${sourceKey}" is up to date\n`);
128
- } else process.stdout.write(`typeforge: generated ${result.files} files for "${sourceKey}" (${result.changed.length} changed)\n`);
129
- } catch (error) {
130
- exitCode = 1;
131
- const message = error instanceof Error ? error.message : String(error);
132
- process.stderr.write(`${message}\n`);
133
- }
134
- return exitCode;
135
- }
136
- async function main() {
137
- const args = parseArgs(process.argv.slice(2));
138
- if (args.command === void 0 || args.command === "help" || args.command === "--help" || args.command === "-h") {
139
- printHelp();
140
- process.exit(0);
141
- }
142
- if (args.command === "init") {
143
- if (args.source === void 0 || args.client === void 0) {
144
- process.stderr.write("typeforge: init requires --source and --client\n");
145
- process.exit(1);
146
- }
147
- const initOptions = {
148
- client: args.client,
149
- sourceKey: args.source
150
- };
151
- if (args.layout !== void 0) initOptions.layout = args.layout;
152
- const result = initProject(initOptions);
153
- for (const file of result.created) process.stdout.write(`created ${file}\n`);
154
- for (const file of result.skipped) process.stdout.write(`skipped ${file} (already exists)\n`);
155
- process.exit(0);
156
- }
157
- if (args.command === "generate" || args.command === "check" || args.command === "accept-base") {
158
- if (args.command === "check") args.check = true;
159
- if (args.command === "accept-base") args.acceptBase = true;
160
- process.exit(await runGenerate(args));
161
- }
162
- process.stderr.write(`typeforge: unknown command "${args.command}"\n`);
163
- printHelp();
164
- process.exit(1);
165
- }
166
- if ((() => {
167
- const entry = process.argv[1];
168
- if (entry === void 0) return false;
169
- try {
170
- return import.meta.url === pathToFileURL(realpathSync(entry)).href;
171
- } catch {
172
- return false;
173
- }
174
- })()) main().catch((error) => {
175
- const message = error instanceof Error ? error.message : String(error);
176
- process.stderr.write(`${message}\n`);
177
- process.exit(1);
178
- });
179
- //#endregion
180
- export { parseArgs };
181
-
182
- //# sourceMappingURL=cli.js.map
16
+ `)}async function c(r){if(r.check===!0&&r.acceptBase===!0)return process.stderr.write(`typeforge: --accept-base is not allowed with --check
17
+ `),1;let i=process.cwd(),a=e(i).apiRoot??`src/api`,o;if(o=r.all===!0?t(i,a):r.sources.length>0?r.sources:[],o.length===0)return process.stderr.write(`typeforge: --source <key> or --all is required
18
+ `),1;let s=0;for(let e of o)try{let t={sourceKey:e};r.acceptBase===!0&&(t.acceptBase=!0),r.check===!0&&(t.check=!0),r.spec!==void 0&&(t.specFlag=r.spec);let i=await n(t);if(r.check===!0){if(i.changed.length>0){process.stderr.write(`typeforge: stale generated files for "${e}":\n`);for(let e of i.changed)process.stderr.write(` ${e}\n`);s=1}else process.stdout.write(`typeforge: "${e}" is up to date\n`)}else process.stdout.write(`typeforge: generated ${i.files} files for "${e}" (${i.changed.length} changed)\n`)}catch(e){s=1;let t=e instanceof Error?e.message:String(e);process.stderr.write(`${t}\n`)}return s}async function l(){let e=o(process.argv.slice(2));if((e.command===void 0||e.command===`help`||e.command===`--help`||e.command===`-h`)&&(s(),process.exit(0)),e.command===`init`){(e.source===void 0||e.client===void 0)&&(process.stderr.write(`typeforge: init requires --source and --client
19
+ `),process.exit(1));let t={client:e.client,sourceKey:e.source};e.layout!==void 0&&(t.layout=e.layout);let n=r(t);for(let e of n.created)process.stdout.write(`created ${e}\n`);for(let e of n.skipped)process.stdout.write(`skipped ${e} (already exists)\n`);process.exit(0)}(e.command===`generate`||e.command===`check`||e.command===`accept-base`)&&(e.command===`check`&&(e.check=!0),e.command===`accept-base`&&(e.acceptBase=!0),process.exit(await c(e))),process.stderr.write(`typeforge: unknown command "${e.command}"\n`),s(),process.exit(1)}(()=>{let e=process.argv[1];if(e===void 0)return!1;try{return import.meta.url===a(i(e)).href}catch{return!1}})()&&l().catch(e=>{let t=e instanceof Error?e.message:String(e);process.stderr.write(`${t}\n`),process.exit(1)});export{o as parseArgs};
@@ -4,29 +4,39 @@ type QueryParamValue = string | number | boolean | null | undefined;
4
4
  type QueryParams = Record<string, QueryParamValue>;
5
5
  //#endregion
6
6
  //#region src/http/types.d.ts
7
+ /** Per-request options accepted by every Typeforge HTTP adapter method. */
7
8
  interface HTTPFetchConfig<TParams extends object = QueryParams, TResponse = unknown> {
9
+ /** Abort signal forwarded to the underlying HTTP client. */
8
10
  signal?: AbortSignal;
11
+ /** Query parameters serialized by the HTTP adapter. */
9
12
  params?: TParams;
13
+ /** Request headers merged with adapter-level defaults. */
10
14
  headers?: Record<string, string>;
15
+ /** Optional runtime validator applied to the response payload. */
11
16
  validateResponse?: ResponseValidator<TResponse>;
12
17
  }
18
+ /** Transport contract consumed by Typeforge-generated API callers. */
13
19
  interface HTTPFetch {
20
+ /** Send a GET request and return its typed response payload. */
14
21
  get<TResponse, TParams extends object = QueryParams>(route: string, config?: HTTPFetchConfig<TParams, TResponse>): Promise<{
15
22
  data: TResponse;
16
23
  }>;
24
+ /** Send a POST request with a typed body and return its typed response payload. */
17
25
  post<TResponse, TBody = unknown, TParams extends object = QueryParams>(route: string, body: TBody, config?: HTTPFetchConfig<TParams, TResponse>): Promise<{
18
26
  data: TResponse;
19
27
  }>;
28
+ /** Send a PUT request with a typed body and return its typed response payload. */
20
29
  put<TResponse, TBody = unknown, TParams extends object = QueryParams>(route: string, body: TBody, config?: HTTPFetchConfig<TParams, TResponse>): Promise<{
21
30
  data: TResponse;
22
31
  }>;
32
+ /** Send a PATCH request with a typed body and return its typed response payload. */
23
33
  patch<TResponse, TBody = unknown, TParams extends object = QueryParams>(route: string, body: TBody, config?: HTTPFetchConfig<TParams, TResponse>): Promise<{
24
34
  data: TResponse;
25
35
  }>;
36
+ /** Send a DELETE request and return its typed response payload. */
26
37
  delete<TResponse, TParams extends object = QueryParams>(route: string, config?: HTTPFetchConfig<TParams, TResponse>): Promise<{
27
38
  data: TResponse;
28
39
  }>;
29
40
  }
30
41
  //#endregion
31
- export { HTTPFetch, HTTPFetchConfig, type QueryParamValue, type QueryParams, ResponseValidationError, type ResponseValidator, coerceResponseData };
32
- //# sourceMappingURL=types.d.ts.map
42
+ export { HTTPFetch, HTTPFetchConfig, type QueryParamValue, type QueryParams, ResponseValidationError, type ResponseValidator, coerceResponseData };
@@ -1,2 +1 @@
1
- import { ResponseValidationError, coerceResponseData } from "./validate.js";
2
- export { ResponseValidationError, coerceResponseData };
1
+ import{ResponseValidationError as e,coerceResponseData as t}from"./validate.js";export{e as ResponseValidationError,t as coerceResponseData};
@@ -6,5 +6,4 @@ declare class ResponseValidationError extends Error {
6
6
  }
7
7
  declare function coerceResponseData<T>(value: unknown, validator?: ResponseValidator<T>): T;
8
8
  //#endregion
9
- export { ResponseValidationError, ResponseValidator, coerceResponseData };
10
- //# sourceMappingURL=validate.d.ts.map
9
+ export { ResponseValidationError, ResponseValidator, coerceResponseData };
@@ -1,21 +1 @@
1
- //#region src/http/validate.ts
2
- var ResponseValidationError = class extends Error {
3
- cause;
4
- constructor(message, cause) {
5
- super(message);
6
- this.name = "ResponseValidationError";
7
- this.cause = cause;
8
- }
9
- };
10
- function coerceResponseData(value, validator) {
11
- if (validator === void 0) return value;
12
- try {
13
- return validator(value);
14
- } catch (error) {
15
- throw new ResponseValidationError("Response validation failed", error);
16
- }
17
- }
18
- //#endregion
19
- export { ResponseValidationError, coerceResponseData };
20
-
21
- //# sourceMappingURL=validate.js.map
1
+ var e=class extends Error{cause;constructor(e,t){super(e),this.name=`ResponseValidationError`,this.cause=t}};function t(t,n){if(n===void 0)return t;try{return n(t)}catch(t){throw new e(`Response validation failed`,t)}}export{e as ResponseValidationError,t as coerceResponseData};