@kizunajs/fetch 2.0.0-beta.3 → 2.0.0-beta.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/server.cjs CHANGED
@@ -27,6 +27,15 @@ var TypeCollector = class {
27
27
  }
28
28
  };
29
29
  const quote = (value) => JSON.stringify(value);
30
+ /**
31
+ * A literal as the type the JSON carries, so `z.literal(true)` is `true`.
32
+ */
33
+ const literalType = (value) => {
34
+ if (typeof value === "string") return quote(value);
35
+ if (typeof value === "bigint") return `${value}n`;
36
+ if (value === void 0) return "undefined";
37
+ return String(value);
38
+ };
30
39
  const indent$1 = (text, depth = 1) => text.split("\n").map((line) => line.length > 0 ? " ".repeat(depth) + line : line).join("\n");
31
40
  /**
32
41
  * A property name, quoted only when it is not a plain identifier.
@@ -165,14 +174,21 @@ const typeOf = (schema, collector, hint) => {
165
174
  return side ? typeOf(side, collector, hint) : "unknown";
166
175
  }
167
176
  const modelName = (0, kizunajs_generator.readMetaId)(schema);
168
- if (modelName !== void 0 && def.type === "object") {
177
+ if (modelName !== void 0) {
169
178
  if (collector.claim(modelName)) collector.add({
170
179
  name: modelName,
171
180
  description: (0, kizunajs_generator.readMetaDescription)(schema),
172
- body: objectBody(schema, collector, modelName)
181
+ body: structuralType(schema, collector, modelName)
173
182
  });
174
183
  return modelName;
175
184
  }
185
+ return structuralType(schema, collector, hint);
186
+ };
187
+ /**
188
+ * The type a schema describes by its shape, its name already spent by the caller.
189
+ */
190
+ const structuralType = (schema, collector, hint) => {
191
+ const def = (0, kizunajs_generator.readDef)(schema);
176
192
  switch (def.type) {
177
193
  case "string": return "string";
178
194
  case "number":
@@ -188,11 +204,11 @@ const typeOf = (schema, collector, hint) => {
188
204
  case "undefined": return "undefined";
189
205
  case "literal": {
190
206
  const values = def.values ?? [];
191
- return values.length > 0 ? values.map((value) => quote(String(value))).join(" | ") : "never";
207
+ return values.length > 0 ? values.map(literalType).join(" | ") : "never";
192
208
  }
193
209
  case "enum": {
194
210
  const values = Object.values(def.entries ?? {});
195
- return values.length > 0 ? values.map((value) => quote(String(value))).join(" | ") : "never";
211
+ return values.length > 0 ? values.map(literalType).join(" | ") : "never";
196
212
  }
197
213
  case "array": return def.element ? `Array<${typeOf(def.element, collector, `${hint}Item`)}>` : "unknown[]";
198
214
  case "object": return objectBody(schema, collector, hint);
@@ -275,7 +291,7 @@ const routeDoc = (routeKey, route) => {
275
291
  lines.push("@example", exampleCall(routeKey, route));
276
292
  return docComment(lines);
277
293
  };
278
- const emitRoute = (routeKey, key, route, collector) => {
294
+ const emitRoute = (routeKey, key, route, collector, namespaceName) => {
279
295
  const namespace = routeKey.split(".").map(kizunajs_generator.toPascalCase).join("");
280
296
  const members = [];
281
297
  const args = [];
@@ -283,19 +299,19 @@ const emitRoute = (routeKey, key, route, collector) => {
283
299
  if (params.length > 0) {
284
300
  const body = route.pathParams ? typeOf(route.pathParams, collector, `${namespace}Params`) : `{\n${indent(params.map((name) => `${name}: string;`).join("\n"))}\n}`;
285
301
  members.push(`export type Params = ${body};`);
286
- args.push(`params: API.${namespace}.Params`);
302
+ args.push(`params: ${namespaceName}.${namespace}.Params`);
287
303
  }
288
304
  if (route.query) {
289
305
  members.push(`export type Query = ${typeOf(route.query, collector, `${namespace}Query`)};`);
290
- args.push(`query?: API.${namespace}.Query`);
306
+ args.push(`query?: ${namespaceName}.${namespace}.Query`);
291
307
  }
292
308
  if (route.body && !(0, kizunajs_generator.isVoidSchema)(route.body)) {
293
309
  members.push(`export type Body = ${typeOf(route.body, collector, `${namespace}Body`)};`);
294
- args.push(`body: API.${namespace}.Body`);
310
+ args.push(`body: ${namespaceName}.${namespace}.Body`);
295
311
  }
296
312
  if (route.headers) {
297
313
  members.push(`export type Headers = ${typeOf(route.headers, collector, `${namespace}Headers`)};`);
298
- args.push(`headers?: API.${namespace}.Headers`);
314
+ args.push(`headers?: ${namespaceName}.${namespace}.Headers`);
299
315
  } else args.push("headers?: Record<string, string>");
300
316
  args.push("fetchOptions?: RequestInit");
301
317
  const validates = route.body !== void 0 || route.query !== void 0;
@@ -319,13 +335,13 @@ const emitRoute = (routeKey, key, route, collector) => {
319
335
  const streams = Object.values(route.responses).some((response) => (0, kizunajs_generator.isStreamResponse)(response));
320
336
  return {
321
337
  namespace,
322
- signature: `${routeDoc(routeKey, route)}${key}: ClientMethod<'${route.method}', ${streams}, ${argsType}, API.${namespace}.Result>;`,
338
+ signature: `${routeDoc(routeKey, route)}${key}: ClientMethod<'${route.method}', ${streams}, ${argsType}, ${namespaceName}.${namespace}.Result>;`,
323
339
  declaration: `export namespace ${namespace} {\n${indent(members.join("\n\n"))}\n}`,
324
340
  table: `${key}: {\n${indent(tableEntries.map((entry) => `${entry},`).join("\n"))}\n},`
325
341
  };
326
342
  };
327
343
  const isRoute = (value) => !!value && typeof value === "object" && typeof value.method === "string";
328
- const emitTree = (routes, prefix, collector) => {
344
+ const emitTree = (routes, prefix, collector, namespaceName) => {
329
345
  const signatures = [];
330
346
  const tables = [];
331
347
  const declarations = [];
@@ -333,14 +349,14 @@ const emitTree = (routes, prefix, collector) => {
333
349
  const node = routes[key];
334
350
  const routeKey = prefix ? `${prefix}.${key}` : key;
335
351
  if (isRoute(node)) {
336
- const emitted = emitRoute(routeKey, key, node, collector);
352
+ const emitted = emitRoute(routeKey, key, node, collector, namespaceName);
337
353
  signatures.push(emitted.signature);
338
354
  tables.push(emitted.table);
339
355
  declarations.push(emitted.declaration);
340
356
  continue;
341
357
  }
342
358
  if (node && typeof node === "object") {
343
- const group = emitTree(node, routeKey, collector);
359
+ const group = emitTree(node, routeKey, collector, namespaceName);
344
360
  signatures.push(`${key}: {\n${indent(group.signatures)}\n};`);
345
361
  tables.push(`${key}: {\n${indent(group.table)}\n},`);
346
362
  declarations.push(...group.declarations);
@@ -372,9 +388,9 @@ const emitRequestContext = (contract, collector) => {
372
388
  return fields.length > 0 ? `export interface RequestContext {\n${indent(fields.join("\n"))}\n}` : void 0;
373
389
  };
374
390
  const generateFetchClient = (contract, options = {}) => {
375
- const { runtimeModule = "@kizunajs/fetch", regenerateCommand = "kizuna generate", source } = options;
391
+ const { namespace: namespaceName = "API", runtimeModule = "@kizunajs/fetch", regenerateCommand = "kizuna generate", source } = options;
376
392
  const collector = new TypeCollector();
377
- const tree = emitTree(contract.routes, "", collector);
393
+ const tree = emitTree(contract.routes, "", collector, namespaceName);
378
394
  const api = [...collector.all().map((model) => {
379
395
  return `${model.description ? `/**\n * ${model.description}\n */\n` : ""}export type ${model.name} = ${model.body};`;
380
396
  }), ...tree.declarations].join("\n\n");
@@ -390,7 +406,7 @@ ${[
390
406
  */
391
407
  import { createGeneratedClient, type ClientConfig, type ClientMethod, type GeneratedRoutes } from '${runtimeModule}';
392
408
 
393
- export namespace API {
409
+ export namespace ${namespaceName} {
394
410
  ${indent(api)}
395
411
  }
396
412
 
package/dist/server.d.cts CHANGED
@@ -5,6 +5,13 @@ import { ApiDefinition, ClientTarget } from "kizunajs";
5
5
  * What a generated client is called and where its runtime comes from.
6
6
  */
7
7
  interface FetchClientOptions {
8
+ /**
9
+ * Name of the generated namespace holding every model and every route's
10
+ * `Params`, `Query`, `Body`, `Headers` and `Result`.
11
+ *
12
+ * @default 'API'
13
+ */
14
+ namespace?: string;
8
15
  /**
9
16
  * Module the generated file imports its runtime from.
10
17
  *
package/dist/server.d.mts CHANGED
@@ -5,6 +5,13 @@ import { ApiDefinition, ClientTarget } from "kizunajs";
5
5
  * What a generated client is called and where its runtime comes from.
6
6
  */
7
7
  interface FetchClientOptions {
8
+ /**
9
+ * Name of the generated namespace holding every model and every route's
10
+ * `Params`, `Query`, `Body`, `Headers` and `Result`.
11
+ *
12
+ * @default 'API'
13
+ */
14
+ namespace?: string;
8
15
  /**
9
16
  * Module the generated file imports its runtime from.
10
17
  *
package/dist/server.mjs CHANGED
@@ -26,6 +26,15 @@ var TypeCollector = class {
26
26
  }
27
27
  };
28
28
  const quote = (value) => JSON.stringify(value);
29
+ /**
30
+ * A literal as the type the JSON carries, so `z.literal(true)` is `true`.
31
+ */
32
+ const literalType = (value) => {
33
+ if (typeof value === "string") return quote(value);
34
+ if (typeof value === "bigint") return `${value}n`;
35
+ if (value === void 0) return "undefined";
36
+ return String(value);
37
+ };
29
38
  const indent$1 = (text, depth = 1) => text.split("\n").map((line) => line.length > 0 ? " ".repeat(depth) + line : line).join("\n");
30
39
  /**
31
40
  * A property name, quoted only when it is not a plain identifier.
@@ -164,14 +173,21 @@ const typeOf = (schema, collector, hint) => {
164
173
  return side ? typeOf(side, collector, hint) : "unknown";
165
174
  }
166
175
  const modelName = readMetaId(schema);
167
- if (modelName !== void 0 && def.type === "object") {
176
+ if (modelName !== void 0) {
168
177
  if (collector.claim(modelName)) collector.add({
169
178
  name: modelName,
170
179
  description: readMetaDescription(schema),
171
- body: objectBody(schema, collector, modelName)
180
+ body: structuralType(schema, collector, modelName)
172
181
  });
173
182
  return modelName;
174
183
  }
184
+ return structuralType(schema, collector, hint);
185
+ };
186
+ /**
187
+ * The type a schema describes by its shape, its name already spent by the caller.
188
+ */
189
+ const structuralType = (schema, collector, hint) => {
190
+ const def = readDef(schema);
175
191
  switch (def.type) {
176
192
  case "string": return "string";
177
193
  case "number":
@@ -187,11 +203,11 @@ const typeOf = (schema, collector, hint) => {
187
203
  case "undefined": return "undefined";
188
204
  case "literal": {
189
205
  const values = def.values ?? [];
190
- return values.length > 0 ? values.map((value) => quote(String(value))).join(" | ") : "never";
206
+ return values.length > 0 ? values.map(literalType).join(" | ") : "never";
191
207
  }
192
208
  case "enum": {
193
209
  const values = Object.values(def.entries ?? {});
194
- return values.length > 0 ? values.map((value) => quote(String(value))).join(" | ") : "never";
210
+ return values.length > 0 ? values.map(literalType).join(" | ") : "never";
195
211
  }
196
212
  case "array": return def.element ? `Array<${typeOf(def.element, collector, `${hint}Item`)}>` : "unknown[]";
197
213
  case "object": return objectBody(schema, collector, hint);
@@ -274,7 +290,7 @@ const routeDoc = (routeKey, route) => {
274
290
  lines.push("@example", exampleCall(routeKey, route));
275
291
  return docComment(lines);
276
292
  };
277
- const emitRoute = (routeKey, key, route, collector) => {
293
+ const emitRoute = (routeKey, key, route, collector, namespaceName) => {
278
294
  const namespace = routeKey.split(".").map(toPascalCase).join("");
279
295
  const members = [];
280
296
  const args = [];
@@ -282,19 +298,19 @@ const emitRoute = (routeKey, key, route, collector) => {
282
298
  if (params.length > 0) {
283
299
  const body = route.pathParams ? typeOf(route.pathParams, collector, `${namespace}Params`) : `{\n${indent(params.map((name) => `${name}: string;`).join("\n"))}\n}`;
284
300
  members.push(`export type Params = ${body};`);
285
- args.push(`params: API.${namespace}.Params`);
301
+ args.push(`params: ${namespaceName}.${namespace}.Params`);
286
302
  }
287
303
  if (route.query) {
288
304
  members.push(`export type Query = ${typeOf(route.query, collector, `${namespace}Query`)};`);
289
- args.push(`query?: API.${namespace}.Query`);
305
+ args.push(`query?: ${namespaceName}.${namespace}.Query`);
290
306
  }
291
307
  if (route.body && !isVoidSchema(route.body)) {
292
308
  members.push(`export type Body = ${typeOf(route.body, collector, `${namespace}Body`)};`);
293
- args.push(`body: API.${namespace}.Body`);
309
+ args.push(`body: ${namespaceName}.${namespace}.Body`);
294
310
  }
295
311
  if (route.headers) {
296
312
  members.push(`export type Headers = ${typeOf(route.headers, collector, `${namespace}Headers`)};`);
297
- args.push(`headers?: API.${namespace}.Headers`);
313
+ args.push(`headers?: ${namespaceName}.${namespace}.Headers`);
298
314
  } else args.push("headers?: Record<string, string>");
299
315
  args.push("fetchOptions?: RequestInit");
300
316
  const validates = route.body !== void 0 || route.query !== void 0;
@@ -318,13 +334,13 @@ const emitRoute = (routeKey, key, route, collector) => {
318
334
  const streams = Object.values(route.responses).some((response) => isStreamResponse(response));
319
335
  return {
320
336
  namespace,
321
- signature: `${routeDoc(routeKey, route)}${key}: ClientMethod<'${route.method}', ${streams}, ${argsType}, API.${namespace}.Result>;`,
337
+ signature: `${routeDoc(routeKey, route)}${key}: ClientMethod<'${route.method}', ${streams}, ${argsType}, ${namespaceName}.${namespace}.Result>;`,
322
338
  declaration: `export namespace ${namespace} {\n${indent(members.join("\n\n"))}\n}`,
323
339
  table: `${key}: {\n${indent(tableEntries.map((entry) => `${entry},`).join("\n"))}\n},`
324
340
  };
325
341
  };
326
342
  const isRoute = (value) => !!value && typeof value === "object" && typeof value.method === "string";
327
- const emitTree = (routes, prefix, collector) => {
343
+ const emitTree = (routes, prefix, collector, namespaceName) => {
328
344
  const signatures = [];
329
345
  const tables = [];
330
346
  const declarations = [];
@@ -332,14 +348,14 @@ const emitTree = (routes, prefix, collector) => {
332
348
  const node = routes[key];
333
349
  const routeKey = prefix ? `${prefix}.${key}` : key;
334
350
  if (isRoute(node)) {
335
- const emitted = emitRoute(routeKey, key, node, collector);
351
+ const emitted = emitRoute(routeKey, key, node, collector, namespaceName);
336
352
  signatures.push(emitted.signature);
337
353
  tables.push(emitted.table);
338
354
  declarations.push(emitted.declaration);
339
355
  continue;
340
356
  }
341
357
  if (node && typeof node === "object") {
342
- const group = emitTree(node, routeKey, collector);
358
+ const group = emitTree(node, routeKey, collector, namespaceName);
343
359
  signatures.push(`${key}: {\n${indent(group.signatures)}\n};`);
344
360
  tables.push(`${key}: {\n${indent(group.table)}\n},`);
345
361
  declarations.push(...group.declarations);
@@ -371,9 +387,9 @@ const emitRequestContext = (contract, collector) => {
371
387
  return fields.length > 0 ? `export interface RequestContext {\n${indent(fields.join("\n"))}\n}` : void 0;
372
388
  };
373
389
  const generateFetchClient = (contract, options = {}) => {
374
- const { runtimeModule = "@kizunajs/fetch", regenerateCommand = "kizuna generate", source } = options;
390
+ const { namespace: namespaceName = "API", runtimeModule = "@kizunajs/fetch", regenerateCommand = "kizuna generate", source } = options;
375
391
  const collector = new TypeCollector();
376
- const tree = emitTree(contract.routes, "", collector);
392
+ const tree = emitTree(contract.routes, "", collector, namespaceName);
377
393
  const api = [...collector.all().map((model) => {
378
394
  return `${model.description ? `/**\n * ${model.description}\n */\n` : ""}export type ${model.name} = ${model.body};`;
379
395
  }), ...tree.declarations].join("\n\n");
@@ -389,7 +405,7 @@ ${[
389
405
  */
390
406
  import { createGeneratedClient, type ClientConfig, type ClientMethod, type GeneratedRoutes } from '${runtimeModule}';
391
407
 
392
- export namespace API {
408
+ export namespace ${namespaceName} {
393
409
  ${indent(api)}
394
410
  }
395
411
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kizunajs/fetch",
3
- "version": "2.0.0-beta.3",
3
+ "version": "2.0.0-beta.5",
4
4
  "description": "Typed fetch client for Kizuna.js APIs",
5
5
  "keywords": [
6
6
  "kizunajs",
@@ -68,7 +68,7 @@
68
68
  },
69
69
  "peerDependencies": {
70
70
  "zod": "^4.0.0",
71
- "kizunajs": "2.0.0-beta.3"
71
+ "kizunajs": "2.0.0-beta.5"
72
72
  },
73
73
  "devDependencies": {
74
74
  "@types/express": "^5.0.0",
@@ -76,8 +76,8 @@
76
76
  "tsdown": "^0.21.0",
77
77
  "typescript": "^6.0.3",
78
78
  "zod": "^4.0.0",
79
- "kizunajs": "2.0.0-beta.3",
80
- "@kizunajs/express": "2.0.0-beta.3"
79
+ "kizunajs": "2.0.0-beta.5",
80
+ "@kizunajs/express": "2.0.0-beta.5"
81
81
  },
82
82
  "scripts": {
83
83
  "build": "tsdown src/index.ts src/server.ts --format esm,cjs --dts --clean --external kizunajs --external zod",