kizlo 0.17.0 → 0.18.0

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/seo/index.js CHANGED
@@ -1,5 +1,5 @@
1
- import { createProcedure } from "../shared/procedure.js";
2
1
  import { ListSitemapUrlInput, Robots, Seo, SitemapIndex, SitemapList, SitemapUrlList } from "./schema.js";
2
+ import { createProcedure } from "../shared/procedure.js";
3
3
  import { deserializeSeo } from "./utils.js";
4
4
 
5
5
  //#region src/seo/index.ts
@@ -108,17 +108,17 @@ declare const Seo: z.ZodObject<{
108
108
  type Seo = z.infer<typeof Seo>;
109
109
  declare const CONTENT_TYPES: readonly ["post_type", "taxonomy", "author"];
110
110
  declare const ContentType: z.ZodEnum<{
111
- author: "author";
112
111
  post_type: "post_type";
113
112
  taxonomy: "taxonomy";
113
+ author: "author";
114
114
  }>;
115
115
  type ContentType = z.infer<typeof ContentType>;
116
116
  declare const Sitemap: z.ZodObject<{
117
117
  key: z.ZodString;
118
118
  type: z.ZodEnum<{
119
- author: "author";
120
119
  post_type: "post_type";
121
120
  taxonomy: "taxonomy";
121
+ author: "author";
122
122
  }>;
123
123
  pages: z.ZodNumber;
124
124
  lastmod: z.ZodString;
@@ -127,9 +127,9 @@ type Sitemap = z.infer<typeof Sitemap>;
127
127
  declare const SitemapList: z.ZodArray<z.ZodObject<{
128
128
  key: z.ZodString;
129
129
  type: z.ZodEnum<{
130
- author: "author";
131
130
  post_type: "post_type";
132
131
  taxonomy: "taxonomy";
132
+ author: "author";
133
133
  }>;
134
134
  pages: z.ZodNumber;
135
135
  lastmod: z.ZodString;
@@ -140,9 +140,9 @@ declare const SitemapIndex: z.ZodObject<{
140
140
  sitemaps: z.ZodArray<z.ZodObject<{
141
141
  key: z.ZodString;
142
142
  type: z.ZodEnum<{
143
- author: "author";
144
143
  post_type: "post_type";
145
144
  taxonomy: "taxonomy";
145
+ author: "author";
146
146
  }>;
147
147
  pages: z.ZodNumber;
148
148
  lastmod: z.ZodString;
@@ -174,9 +174,9 @@ declare const SitemapUrlList: z.ZodArray<z.ZodObject<{
174
174
  type SitemapUrlList = z.infer<typeof SitemapUrlList>;
175
175
  declare const ListSitemapUrlInputBase: z.ZodObject<{
176
176
  type: z.ZodEnum<{
177
- author: "author";
178
177
  post_type: "post_type";
179
178
  taxonomy: "taxonomy";
179
+ author: "author";
180
180
  }>;
181
181
  page: z.ZodOptional<z.ZodPipe<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>, z.ZodCoercedNumber<string | number>>>;
182
182
  }, z.core.$strip>;
@@ -1,7 +1,7 @@
1
1
  import { HTTPMethod } from "./types.js";
2
2
  import { AnyProcedureTree, InvocationScope } from "./procedure.js";
3
- import { AnyContractRouter } from "@orpc/contract";
4
3
  import { Pathname } from "@kizlo/shared";
4
+ import { AnyContractRouter } from "@orpc/contract";
5
5
 
6
6
  //#region src/shared/contract.d.ts
7
7
  type Contract = {
@@ -1,13 +1,18 @@
1
1
  import { ProcedureContext } from "../context.js";
2
2
  import { DefinedErrorMapLike, ThrowableErrorMap, WithCommonErrorMap } from "./error.js";
3
3
  import { AnyMiddleware, InferMiddlewares, Middleware } from "./middleware.js";
4
- import * as _orpc_contract0 from "@orpc/contract";
5
4
  import { DeepMerge, Pathname, Prettify, Promisify, Schema, SchemaInput, SchemaOutput } from "@kizlo/shared";
5
+ import * as _orpc_contract0 from "@orpc/contract";
6
6
  import * as _orpc_server0 from "@orpc/server";
7
7
  import { HTTPMethod } from "@orpc/server";
8
8
  import { JsonifiedValue } from "@orpc/openapi-client";
9
9
 
10
10
  //#region src/shared/procedure.d.ts
11
+ declare const schemaTypeOutput: unique symbol;
12
+ type TypedSchema<TInput, TOutput = TInput> = Schema<TInput, TOutput> & {
13
+ readonly [schemaTypeOutput]: TOutput;
14
+ };
15
+ type ProcedureOutput<TScope, TOutput extends Schema> = TScope extends "api" ? TOutput extends TypedSchema<any, infer TPreservedOutput> ? TPreservedOutput : JsonifiedValue<SchemaOutput<TOutput>> : SchemaOutput<TOutput>;
11
16
  type AnyProcedureTree = {
12
17
  [K: string]: AnyProcedure | AnyProcedureTree;
13
18
  };
@@ -110,8 +115,12 @@ type ProcedureOptions<TScope extends InvocationScope, TPathname extends Pathname
110
115
  /** Schema for the call's single input argument. */
111
116
  input?: TInput;
112
117
  });
113
- declare function createProcedure<TScope extends InvocationScope, TPathname extends Pathname, TInput extends Schema | undefined = undefined, TBody extends Schema | undefined = undefined, TParams extends Schema | undefined = undefined, TQuery extends Schema | undefined = undefined, THeaders extends Schema | undefined = undefined, TOutput extends Schema = Schema, TError extends DefinedErrorMapLike = DefinedErrorMapLike, TMiddlewares extends Middleware<ResolvedSchemaOutput<TScope, TPathname, TInput, TBody, TParams, TQuery, THeaders>, SchemaOutput<TOutput>, TError>[] = Middleware<ResolvedSchemaOutput<TScope, TPathname, TInput, TBody, TParams, TQuery, THeaders>, SchemaOutput<TOutput>, TError>[], TContext extends ProcedureContext & InferMiddlewares<TMiddlewares> = ProcedureContext & InferMiddlewares<TMiddlewares>>(options: ProcedureOptions<TScope, TPathname, TInput, TBody, TParams, TQuery, THeaders, TOutput, TError, TMiddlewares>, handler: ProcedureHandler<ResolvedSchemaOutput<TScope, TPathname, TInput, TBody, TParams, TQuery, THeaders>, SchemaOutput<TOutput>, TError, TContext>): Procedure<TScope, ResolvedSchemaInput<TScope, TPathname, TInput, TBody, TParams, TQuery, THeaders>, TScope extends "api" ? JsonifiedValue<SchemaOutput<TOutput>> : SchemaOutput<TOutput>, TError>;
114
- declare function schemaType<TInput, TOutput = TInput>(schema?: Schema): Schema<TInput, TOutput>;
118
+ declare function createProcedure<TScope extends InvocationScope, TPathname extends Pathname, TInput extends Schema | undefined = undefined, TBody extends Schema | undefined = undefined, TParams extends Schema | undefined = undefined, TQuery extends Schema | undefined = undefined, THeaders extends Schema | undefined = undefined, TOutput extends Schema = Schema, TError extends DefinedErrorMapLike = DefinedErrorMapLike, TMiddlewares extends Middleware<ResolvedSchemaOutput<TScope, TPathname, TInput, TBody, TParams, TQuery, THeaders>, SchemaOutput<TOutput>, TError>[] = Middleware<ResolvedSchemaOutput<TScope, TPathname, TInput, TBody, TParams, TQuery, THeaders>, SchemaOutput<TOutput>, TError>[], TContext extends ProcedureContext & InferMiddlewares<TMiddlewares> = ProcedureContext & InferMiddlewares<TMiddlewares>>(options: ProcedureOptions<TScope, TPathname, TInput, TBody, TParams, TQuery, THeaders, TOutput, TError, TMiddlewares>, handler: ProcedureHandler<ResolvedSchemaOutput<TScope, TPathname, TInput, TBody, TParams, TQuery, THeaders>, SchemaOutput<TOutput>, TError, TContext>): Procedure<TScope, ResolvedSchemaInput<TScope, TPathname, TInput, TBody, TParams, TQuery, THeaders>, ProcedureOutput<TScope, TOutput>, TError>;
119
+ /**
120
+ * Give a schema an explicit input and output type. For API procedure outputs, the declared output
121
+ * is already the client-visible wire type and is preserved without structural JSON remapping.
122
+ */
123
+ declare function schemaType<TInput, TOutput = TInput>(schema?: Schema): TypedSchema<TInput, TOutput>;
115
124
  declare function buildProcedure(procedure: AnyProcedure): _orpc_server0.DecoratedProcedure<_orpc_server0.Context & Record<never, never>, _orpc_server0.Context, _orpc_contract0.Schema<unknown, unknown>, _orpc_contract0.Schema<any, any>, Record<never, never>, Record<never, never>>;
116
125
  declare function handleUnexpectedError(error: unknown, errors?: DefinedErrorMapLike): never;
117
126
  declare function combineDetailed(parts: Record<string, Schema>): Schema;
@@ -9,6 +9,10 @@ function createProcedure(options, handler) {
9
9
  handler: (ctx) => handler(ctx)
10
10
  } };
11
11
  }
12
+ /**
13
+ * Give a schema an explicit input and output type. For API procedure outputs, the declared output
14
+ * is already the client-visible wire type and is preserved without structural JSON remapping.
15
+ */
12
16
  function schemaType(schema) {
13
17
  return schema ?? { "~standard": {
14
18
  vendor: "custom",
@@ -1,7 +1,7 @@
1
1
  import { DefinedErrorMapLike, KizloError, WithCommonErrorMap } from "./error.js";
2
- import { AnyProcedureTree, Procedure } from "./procedure.js";
3
- import { NestedClient } from "@orpc/client";
2
+ import { AnyProcedure, AnyProcedureTree, Procedure } from "./procedure.js";
4
3
  import { SchemaOutput } from "@kizlo/shared";
4
+ import { NestedClient } from "@orpc/client";
5
5
 
6
6
  //#region src/shared/result.d.ts
7
7
  type MaybeCallerOptions<UInput> = unknown extends UInput ? [] : [UInput] extends [undefined] ? [] : object extends UInput ? [input?: UInput] : [input: UInput];
@@ -9,16 +9,25 @@ type ProcedureMethod<UInput, UOutput, TError extends DefinedErrorMapLike> = {
9
9
  (...rest: MaybeCallerOptions<UInput>): Promise<KizloResult<UOutput, TError>>;
10
10
  call: (...rest: MaybeCallerOptions<UInput>) => Promise<UOutput>;
11
11
  };
12
- type KizloErrorUnion<TErrors extends DefinedErrorMapLike> = { [K in Extract<keyof TErrors, string>]: KizloError<K, SchemaOutput<TErrors[K]["data"]>> }[Extract<keyof TErrors, string>];
13
- type KizloResult<TOutput, TErrors extends DefinedErrorMapLike = DefinedErrorMapLike> = {
14
- data: TOutput;
12
+ type KizloErrorUnion<TErrors$1 extends DefinedErrorMapLike> = { [K in Extract<keyof TErrors$1, string>]: KizloError<K, SchemaOutput<TErrors$1[K]["data"]>> }[Extract<keyof TErrors$1, string>];
13
+ type KizloResult<TOutput$1, TErrors$1 extends DefinedErrorMapLike = DefinedErrorMapLike> = {
14
+ data: TOutput$1;
15
15
  error: null;
16
16
  success: true;
17
17
  } | {
18
18
  data: undefined;
19
- error: KizloErrorUnion<WithCommonErrorMap<TErrors>>;
19
+ error: KizloErrorUnion<WithCommonErrorMap<TErrors$1>>;
20
20
  success: false;
21
21
  };
22
+ /** The input accepted by one public Kizlo procedure object. */
23
+ type InferProcedureInput<TProcedure extends AnyProcedure> = TProcedure extends Procedure<any, infer TInput, any, any> ? TInput : never;
24
+ /** The successful data returned by one public Kizlo procedure object. */
25
+ type InferProcedureData<TProcedure extends AnyProcedure> = TProcedure extends Procedure<any, any, infer TOutput, any> ? TOutput : never;
26
+ /** The declared and common client-visible errors returned by one public Kizlo procedure object. */
27
+ type InferProcedureError<TProcedure extends AnyProcedure> = TProcedure extends Procedure<any, any, any, infer TErrors> ? KizloErrorUnion<WithCommonErrorMap<TErrors>> : never;
28
+ /** The complete wrapped result returned by a normal call to one public Kizlo procedure object. */
29
+ type InferProcedureResult<TProcedure extends AnyProcedure> = TProcedure extends Procedure<any, any, infer TOutput, infer TErrors> ? KizloResult<TOutput, TErrors> : never;
22
30
  type ResultClient<T extends AnyProcedureTree> = { [K in keyof T]: T[K] extends Procedure<infer _Scope, infer Input, infer Output, infer Errors> ? ProcedureMethod<Input, Output, Errors> : T[K] extends AnyProcedureTree ? ResultClient<T[K]> : never };
31
+ declare function createResultClient<T extends AnyProcedureTree>(client: NestedClient<any>): ResultClient<T>;
23
32
  //#endregion
24
- export { ResultClient };
33
+ export { InferProcedureData, InferProcedureError, InferProcedureInput, InferProcedureResult, KizloErrorUnion, KizloResult, MaybeCallerOptions, ProcedureMethod, ResultClient, createResultClient };
@@ -1,6 +1,6 @@
1
1
  import { ListMetadata } from "./schema.js";
2
- import { NestedClient } from "@orpc/client";
3
2
  import { CookieOptions, CookieWithOptions } from "@kizlo/shared";
3
+ import { NestedClient } from "@orpc/client";
4
4
 
5
5
  //#region src/shared/types.d.ts
6
6
  type AnyContext = Record<PropertyKey, any>;
package/dist/tag/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { createProcedure } from "../shared/procedure.js";
1
+ import { createProcedure, schemaType } from "../shared/procedure.js";
2
2
  import { parseIdentifier } from "../shared/identifier.js";
3
3
  import { deserializeListMetadata } from "../shared/serialize.js";
4
4
  import { GET_TAG_ERROR_MAP, LIST_TAG_ERROR_MAP } from "./error.js";
@@ -13,7 +13,7 @@ const TAG_PROCEDURES = {
13
13
  method: "GET",
14
14
  path: "/tags/{identifier}",
15
15
  params: RetrieveTagInput.pick({ identifier: true }),
16
- output: Tag,
16
+ output: schemaType(Tag),
17
17
  errors: GET_TAG_ERROR_MAP
18
18
  }, async ({ input, context, errors }) => {
19
19
  const identifier = parseIdentifier(input.params.identifier);
@@ -38,7 +38,7 @@ const TAG_PROCEDURES = {
38
38
  method: "GET",
39
39
  path: "/tags",
40
40
  query: ListTagInput.optional(),
41
- output: TagList,
41
+ output: schemaType(TagList),
42
42
  errors: LIST_TAG_ERROR_MAP
43
43
  }, async ({ input, context, errors }) => {
44
44
  const response = await context.wordpress.taxonomies.postTag.list({
@@ -0,0 +1,151 @@
1
+ import { WP_CustomFields } from "../wordpress/types.js";
2
+ import "../wordpress/index.js";
3
+ import * as _kizlo_shared24 from "@kizlo/shared";
4
+ import z from "zod/v4";
5
+
6
+ //#region src/tag/schema.d.ts
7
+ type TagCustomFields = WP_CustomFields<"taxonomies.postTag">;
8
+ declare const TagCustomFieldsSchema: z.ZodType<TagCustomFields, TagCustomFields>;
9
+ declare const Tag: z.ZodObject<{
10
+ id: z.ZodNumber;
11
+ name: z.ZodString;
12
+ slug: z.ZodString;
13
+ url: z.ZodNullable<z.ZodString>;
14
+ description: z.ZodNullable<z.ZodString>;
15
+ postCount: z.ZodNumber;
16
+ seo: z.ZodNullable<z.ZodObject<{
17
+ head: z.ZodObject<{
18
+ title: z.ZodString;
19
+ canonical: z.ZodString;
20
+ robots: z.ZodObject<{
21
+ index: z.ZodString;
22
+ follow: z.ZodString;
23
+ maxSnippet: z.ZodString;
24
+ maxImagePreview: z.ZodString;
25
+ maxVideoPreview: z.ZodString;
26
+ }, z.core.$strip>;
27
+ og: z.ZodObject<{
28
+ locale: z.ZodString;
29
+ type: z.ZodString;
30
+ title: z.ZodString;
31
+ url: z.ZodString;
32
+ siteName: z.ZodString;
33
+ description: z.ZodString;
34
+ image: z.ZodNullable<z.ZodObject<{
35
+ url: z.ZodString;
36
+ width: z.ZodNullable<z.ZodNumber>;
37
+ height: z.ZodNullable<z.ZodNumber>;
38
+ type: z.ZodNullable<z.ZodString>;
39
+ alt: z.ZodNullable<z.ZodString>;
40
+ }, z.core.$strip>>;
41
+ }, z.core.$strip>;
42
+ twitter: z.ZodObject<{
43
+ card: z.ZodEnum<{
44
+ summary: "summary";
45
+ summary_large_image: "summary_large_image";
46
+ }>;
47
+ title: z.ZodString;
48
+ site: z.ZodNullable<z.ZodString>;
49
+ creator: z.ZodNullable<z.ZodString>;
50
+ description: z.ZodString;
51
+ image: z.ZodNullable<z.ZodString>;
52
+ imageAlt: z.ZodNullable<z.ZodString>;
53
+ }, z.core.$strip>;
54
+ article: z.ZodNullable<z.ZodObject<{
55
+ publishedTime: z.ZodString;
56
+ modifiedTime: z.ZodString;
57
+ author: z.ZodString;
58
+ authorUrl: z.ZodString;
59
+ section: z.ZodString;
60
+ tags: z.ZodArray<z.ZodString>;
61
+ }, z.core.$strip>>;
62
+ }, z.core.$strip>;
63
+ schema: z.ZodObject<{
64
+ "@context": z.ZodLiteral<"https://schema.org">;
65
+ "@graph": z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
66
+ }, z.core.$strip>;
67
+ }, z.core.$strip>>;
68
+ custom: z.ZodType<Record<string, unknown>, Record<string, unknown>, z.core.$ZodTypeInternals<Record<string, unknown>, Record<string, unknown>>>;
69
+ meta: z.ZodRecord<z.ZodString, z.ZodType<_kizlo_shared24.JSONValue, unknown, z.core.$ZodTypeInternals<_kizlo_shared24.JSONValue, unknown>>>;
70
+ }, z.core.$strip>;
71
+ type Tag = Omit<z.output<typeof Tag>, "custom"> & {
72
+ custom: TagCustomFields;
73
+ };
74
+ declare const TagList: z.ZodObject<{
75
+ items: z.ZodArray<z.ZodObject<{
76
+ id: z.ZodNumber;
77
+ name: z.ZodString;
78
+ slug: z.ZodString;
79
+ url: z.ZodNullable<z.ZodString>;
80
+ description: z.ZodNullable<z.ZodString>;
81
+ postCount: z.ZodNumber;
82
+ seo: z.ZodNullable<z.ZodObject<{
83
+ head: z.ZodObject<{
84
+ title: z.ZodString;
85
+ canonical: z.ZodString;
86
+ robots: z.ZodObject<{
87
+ index: z.ZodString;
88
+ follow: z.ZodString;
89
+ maxSnippet: z.ZodString;
90
+ maxImagePreview: z.ZodString;
91
+ maxVideoPreview: z.ZodString;
92
+ }, z.core.$strip>;
93
+ og: z.ZodObject<{
94
+ locale: z.ZodString;
95
+ type: z.ZodString;
96
+ title: z.ZodString;
97
+ url: z.ZodString;
98
+ siteName: z.ZodString;
99
+ description: z.ZodString;
100
+ image: z.ZodNullable<z.ZodObject<{
101
+ url: z.ZodString;
102
+ width: z.ZodNullable<z.ZodNumber>;
103
+ height: z.ZodNullable<z.ZodNumber>;
104
+ type: z.ZodNullable<z.ZodString>;
105
+ alt: z.ZodNullable<z.ZodString>;
106
+ }, z.core.$strip>>;
107
+ }, z.core.$strip>;
108
+ twitter: z.ZodObject<{
109
+ card: z.ZodEnum<{
110
+ summary: "summary";
111
+ summary_large_image: "summary_large_image";
112
+ }>;
113
+ title: z.ZodString;
114
+ site: z.ZodNullable<z.ZodString>;
115
+ creator: z.ZodNullable<z.ZodString>;
116
+ description: z.ZodString;
117
+ image: z.ZodNullable<z.ZodString>;
118
+ imageAlt: z.ZodNullable<z.ZodString>;
119
+ }, z.core.$strip>;
120
+ article: z.ZodNullable<z.ZodObject<{
121
+ publishedTime: z.ZodString;
122
+ modifiedTime: z.ZodString;
123
+ author: z.ZodString;
124
+ authorUrl: z.ZodString;
125
+ section: z.ZodString;
126
+ tags: z.ZodArray<z.ZodString>;
127
+ }, z.core.$strip>>;
128
+ }, z.core.$strip>;
129
+ schema: z.ZodObject<{
130
+ "@context": z.ZodLiteral<"https://schema.org">;
131
+ "@graph": z.ZodArray<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
132
+ }, z.core.$strip>;
133
+ }, z.core.$strip>>;
134
+ custom: z.ZodType<Record<string, unknown>, Record<string, unknown>, z.core.$ZodTypeInternals<Record<string, unknown>, Record<string, unknown>>>;
135
+ meta: z.ZodRecord<z.ZodString, z.ZodType<_kizlo_shared24.JSONValue, unknown, z.core.$ZodTypeInternals<_kizlo_shared24.JSONValue, unknown>>>;
136
+ }, z.core.$strip>>;
137
+ meta: z.ZodObject<{
138
+ page: z.ZodNumber;
139
+ totalItems: z.ZodNumber;
140
+ totalPages: z.ZodNumber;
141
+ nextPage: z.ZodNullable<z.ZodNumber>;
142
+ prevPage: z.ZodNullable<z.ZodNumber>;
143
+ hasNextPage: z.ZodBoolean;
144
+ hasPrevPage: z.ZodBoolean;
145
+ }, z.core.$strip>;
146
+ }, z.core.$strip>;
147
+ type TagList = Omit<z.output<typeof TagList>, "items"> & {
148
+ items: Tag[];
149
+ };
150
+ //#endregion
151
+ export { Tag, TagCustomFields, TagCustomFieldsSchema, TagList };
@@ -1,5 +1,5 @@
1
- import { IdentifierInput, ListMetadata, ListOrder, customFieldsSchema } from "../shared/schema.js";
2
1
  import { Seo } from "../seo/schema.js";
2
+ import { IdentifierInput, ListMetadata, ListOrder, customFieldsSchema } from "../shared/schema.js";
3
3
  import { BooleanLike, Metadata, NumberLike, arrayable, lenient } from "@kizlo/shared";
4
4
  import z from "zod/v4";
5
5
 
@@ -14,6 +14,7 @@ const WP_TAG_ORDER_BYS = [
14
14
  "description",
15
15
  "count"
16
16
  ];
17
+ const TagCustomFieldsSchema = customFieldsSchema();
17
18
  const Tag = z.object({
18
19
  id: z.number(),
19
20
  name: z.string(),
@@ -22,7 +23,7 @@ const Tag = z.object({
22
23
  description: z.string().nullable(),
23
24
  postCount: z.number(),
24
25
  seo: Seo.nullable(),
25
- custom: customFieldsSchema(),
26
+ custom: TagCustomFieldsSchema,
26
27
  meta: Metadata
27
28
  });
28
29
  const RetrieveTagInput = z.object({ identifier: IdentifierInput });
@@ -45,4 +46,4 @@ const ListTagInput = z.object({
45
46
  });
46
47
 
47
48
  //#endregion
48
- export { ListTagInput, RetrieveTagInput, Tag, TagList };
49
+ export { ListTagInput, RetrieveTagInput, Tag, TagCustomFieldsSchema, TagList };
@@ -300,6 +300,28 @@ function renderEndpointNode(node, indent) {
300
300
  if (entries.length === 0) return "{}";
301
301
  return `{\n${entries.join("\n")}\n${indent.slice(0, -1)}}`;
302
302
  }
303
+ function renderEndpointRegistry(node, path = []) {
304
+ const entries = [];
305
+ for (const [key, child] of sortedChildren(node)) entries.push(...renderEndpointRegistry(child, [...path, key]));
306
+ for (const entry of sortedEndpoints(node)) {
307
+ const input = endpointName(entry.apiId, entry.operationId, "EndpointInput");
308
+ const result = endpointName(entry.apiId, entry.operationId, "EndpointResult");
309
+ entries.push(`\t\t${JSON.stringify([...path, entry.member].join("."))}: WP_Endpoint<${input}, ${result}>`);
310
+ }
311
+ return entries;
312
+ }
313
+ function renderCustomFieldsRegistry(document) {
314
+ const entries = [];
315
+ for (const id of Object.keys(document.schemas).sort((left, right) => left.localeCompare(right))) {
316
+ const match = /^(post-types|taxonomies)\.([^.]+)\.item$/.exec(id);
317
+ if (!match) continue;
318
+ const namespace = match[1] === "post-types" ? "postTypes" : "taxonomies";
319
+ const slug = match[2];
320
+ if (!slug) continue;
321
+ entries.push(`\t\t${JSON.stringify(`${namespace}.${camel(slug)}`)}: ${schemaName(id)}["kizlo"]["custom"]`);
322
+ }
323
+ return entries;
324
+ }
303
325
  function operationEntries(apiId, api) {
304
326
  const entries = [];
305
327
  for (const [, operations] of sortedEntries(api.paths)) for (const [operationId, operation] of sortedEntries(operations)) entries.push([operationId, operation]);
@@ -349,13 +371,29 @@ const RUNTIME_TYPES = [
349
371
  "WP_Success",
350
372
  "WP_TransportFailure"
351
373
  ];
352
- const REGISTRY = `declare module "kizlo" {\n\tinterface WordPressClientRegistry {\n\t\tendpoints: typeof endpoints\n\t}\n}`;
374
+ function renderRegistries(tree, document) {
375
+ const endpoints = renderEndpointRegistry(tree);
376
+ const customFields = renderCustomFieldsRegistry(document);
377
+ return [
378
+ `declare module "kizlo" {`,
379
+ `\tinterface WordPressClientRegistry {`,
380
+ `\t\tendpoints: typeof endpoints`,
381
+ `\t}`,
382
+ `\tinterface WordPressEndpointRegistry {`,
383
+ ...endpoints,
384
+ `\t}`,
385
+ `\tinterface WordPressCustomFieldsRegistry {`,
386
+ ...customFields,
387
+ `\t}`,
388
+ `}`
389
+ ].join("\n");
390
+ }
353
391
  /**
354
392
  * The `kizlo` names a generated module uses. `wpEndpoint` is the only value among them, so the rest
355
393
  * erase at build.
356
394
  */
357
395
  function kizloImports(body, hasEndpoints) {
358
- const types = new Set(["WP_Client", ...RUNTIME_TYPES.filter((name) => (/* @__PURE__ */ new RegExp(`\\b${name}\\b`)).test(body))]);
396
+ const types = new Set(["WP_Client", ...["WP_Endpoint", ...RUNTIME_TYPES].filter((name) => (/* @__PURE__ */ new RegExp(`\\b${name}\\b`)).test(body))]);
359
397
  const values = hasEndpoints ? ["wpEndpoint"] : [];
360
398
  return [...types, ...values].sort().map((name) => types.has(name) ? `type ${name}` : name).join(", ");
361
399
  }
@@ -389,7 +427,7 @@ function generateWordPressModule(document) {
389
427
  body,
390
428
  `export const endpoints = ${endpointBody}`,
391
429
  `export type WordPressClient = WP_Client<typeof endpoints>`,
392
- REGISTRY
430
+ renderRegistries(tree, document)
393
431
  ].join(DECLARATION_SEPARATOR);
394
432
  const imports = `import { ${kizloImports(moduleBody, endpointBody !== "{}")} } from "kizlo"`;
395
433
  const preamble = `${GENERATED_HEADER}// Introspection ${document.hash}\n\n${imports}\n\n`;
@@ -1,5 +1,5 @@
1
1
  import { WP_Error } from "./error.js";
2
- import { ActiveWordPressClient, WP_CallOptions, WP_Client, WP_CommonErrorCode, WP_CurrencyFormat, WP_Endpoint, WP_EndpointData, WP_EndpointDefinition, WP_EndpointInput, WP_EndpointResult, WP_ErrorData, WP_Failure, WP_List, WP_ListMetadata, WP_RequestBuild, WP_RequestContentType, WP_RequestInput, WP_RequestMethod, WP_ResponseContentType, WP_Result, WP_Success, WP_TransportFailure, WP_TypedHeaders, WordPressClientRegistry, WordPressCredentials } from "./types.js";
2
+ import { ActiveWordPressClient, WP_CallOptions, WP_Client, WP_CommonErrorCode, WP_CurrencyFormat, WP_CustomFields, WP_CustomFieldsPath, WP_Endpoint, WP_EndpointData, WP_EndpointDefinition, WP_EndpointError, WP_EndpointInput, WP_EndpointPath, WP_EndpointResult, WP_ErrorData, WP_Failure, WP_List, WP_ListMetadata, WP_RequestBuild, WP_RequestContentType, WP_RequestInput, WP_RequestMethod, WP_ResponseContentType, WP_Result, WP_Success, WP_TransportFailure, WP_TypedHeaders, WordPressClientRegistry, WordPressCredentials, WordPressCustomFieldsRegistry, WordPressEndpointRegistry } from "./types.js";
3
3
  import { WordPressTransport, WordPressTransportOptions, WordPressTransportResult } from "./transport.js";
4
4
  import { buildWordPressRequest, createWordPressClient, wpEndpoint } from "./endpoint.js";
5
5
  import { isWordPressResourceError } from "./utils.js";
@@ -38,6 +38,10 @@ type WP_CallArguments<TInput$1> = Record<string, never> extends TInput$1 ? [inpu
38
38
  type IsAny<T> = 0 extends 1 & T ? true : false;
39
39
  /** Generated WordPress endpoint trees augment this registry in the project that owns them. */
40
40
  interface WordPressClientRegistry {}
41
+ /** Generated WordPress modules augment this flat registry with every raw operation they expose. */
42
+ interface WordPressEndpointRegistry {}
43
+ /** Generated WordPress modules augment this registry from managed-content item schemas. */
44
+ interface WordPressCustomFieldsRegistry {}
41
45
  /**
42
46
  * The WordPress client this project compiles against: its generated endpoints bound to the
43
47
  * transport, or the bare transport. The stub written before the first generation registers `any`,
@@ -46,9 +50,15 @@ interface WordPressClientRegistry {}
46
50
  type ActiveWordPressClient = WordPressClientRegistry extends {
47
51
  endpoints: infer TEndpoints extends object;
48
52
  } ? WP_Client<TEndpoints> & WordPressTransport : WordPressTransport;
49
- /** Walk a dotted endpoint path (`postTypes.post.retrieve`) into the active client. */
50
- type WP_EndpointAtPath<TClient, TPath extends string> = TPath extends `${infer TKey}.${infer TRest}` ? TKey extends keyof TClient ? WP_EndpointAtPath<TClient[TKey], TRest> : never : TPath extends keyof TClient ? TClient[TPath] : never;
51
- type WP_EndpointCallResult<TEndpoint> = IsAny<TEndpoint> extends true ? any : TEndpoint extends ((input: never) => Promise<infer TResult>) ? TResult : never;
53
+ /** Every raw WordPress operation path generated for the active project. */
54
+ type WP_EndpointPath = keyof WordPressEndpointRegistry extends never ? string : Extract<keyof WordPressEndpointRegistry, string>;
55
+ /**
56
+ * Resolve a generated registry entry. The empty-registry branch keeps the package declarations
57
+ * usable before a project writes its first generated module; the generated stub adds the same
58
+ * permissive fallback explicitly.
59
+ */
60
+ type WP_EndpointAtPath<TPath extends WP_EndpointPath> = keyof WordPressEndpointRegistry extends never ? any : TPath extends keyof WordPressEndpointRegistry ? WordPressEndpointRegistry[TPath] : never;
61
+ type WP_EndpointCallResult<TEndpoint> = IsAny<TEndpoint> extends true ? any : TEndpoint extends WP_Endpoint<any, infer TResult> ? TResult : never;
52
62
  /**
53
63
  * `never` is short-circuited rather than let through: every type is assignable to it, so an
54
64
  * unresolved path would otherwise match the `{ data: infer TData }` branch and infer `unknown`,
@@ -65,21 +75,33 @@ type WP_EndpointSuccessData<TEndpoint> = IsAny<TEndpoint> extends true ? any : [
65
75
  * resolves against whichever client is compiling, so it stays well-formed in a project that has
66
76
  * not generated one yet (`any`) or whose WordPress does not serve the endpoint (`never`).
67
77
  */
68
- type WP_EndpointData<TPath extends string> = WP_EndpointSuccessData<WP_EndpointAtPath<ActiveWordPressClient, TPath>>;
78
+ type WP_EndpointData<TPath extends WP_EndpointPath> = WP_EndpointSuccessData<WP_EndpointAtPath<TPath>>;
69
79
  /**
70
80
  * Everything a generated endpoint resolves to, success and failure alike, addressed the same way.
71
81
  * {@link WP_EndpointData} is the success payload on its own; this is what a signature that has to
72
82
  * name the whole result uses, so a service can publish its return type without the project's
73
83
  * generated module leaking into the package's own declarations.
74
84
  */
75
- type WP_EndpointResult<TPath extends string> = WP_EndpointCallResult<WP_EndpointAtPath<ActiveWordPressClient, TPath>>;
76
- type WP_EndpointCallInput<TEndpoint> = IsAny<TEndpoint> extends true ? any : TEndpoint extends ((...args: infer TArguments) => unknown) ? Exclude<TArguments[0], undefined> : never;
85
+ type WP_EndpointResult<TPath extends WP_EndpointPath> = WP_EndpointCallResult<WP_EndpointAtPath<TPath>>;
86
+ type WP_EndpointCallInput<TEndpoint> = IsAny<TEndpoint> extends true ? any : TEndpoint extends WP_Endpoint<infer TInput, any> ? TInput : never;
77
87
  /**
78
88
  * What a generated endpoint accepts, addressed the same way as {@link WP_EndpointData}. Kizlo's own
79
89
  * modules name their WordPress payloads with this rather than restating them, so an input can only
80
90
  * drift from the route it is sent to by the route itself changing.
81
91
  */
82
- type WP_EndpointInput<TPath extends string> = WP_EndpointCallInput<WP_EndpointAtPath<ActiveWordPressClient, TPath>>;
92
+ type WP_EndpointInput<TPath extends WP_EndpointPath> = WP_EndpointCallInput<WP_EndpointAtPath<TPath>>;
93
+ type WP_EndpointCallError<TEndpoint> = IsAny<TEndpoint> extends true ? any : TEndpoint extends WP_Endpoint<any, infer TResult> ? Exclude<TResult extends {
94
+ error: infer TError;
95
+ } ? TError : never, null> : never;
96
+ /** The non-null WordPress error returned by a generated raw endpoint. */
97
+ type WP_EndpointError<TPath extends WP_EndpointPath> = WP_EndpointCallError<WP_EndpointAtPath<TPath>>;
98
+ /** Every canonical managed-content custom-field mapping generated for the active project. */
99
+ type WP_CustomFieldsPath = keyof WordPressCustomFieldsRegistry extends never ? string : Extract<keyof WordPressCustomFieldsRegistry, string>;
100
+ /**
101
+ * Exact custom fields from a managed post type or taxonomy's canonical item schema. The fallback
102
+ * remains permissive until a generated module augments the registry with the project's mappings.
103
+ */
104
+ type WP_CustomFields<TPath extends WP_CustomFieldsPath> = keyof WordPressCustomFieldsRegistry extends never ? Record<string, unknown> : TPath extends keyof WordPressCustomFieldsRegistry ? WordPressCustomFieldsRegistry[TPath] : never;
83
105
  /**
84
106
  * The codes that widen every endpoint's own union, because no introspection document can declare
85
107
  * them. `rest_no_route` is the answer when the route does not exist, which no route can describe
@@ -174,13 +196,13 @@ type WP_Success<TData$1, TStatus extends number = number, THeaders extends Recor
174
196
  headers: WP_TypedHeaders<THeaders, THeaderName>;
175
197
  error: null;
176
198
  };
177
- type WP_Failure<TError extends string, TStatus extends number = number, THeaders extends Record<string, unknown> = Record<string, never>, THeaderName extends string = string> = {
199
+ type WP_Failure<TError$1 extends string, TStatus extends number = number, THeaders extends Record<string, unknown> = Record<string, never>, THeaderName extends string = string> = {
178
200
  data: null;
179
201
  status: TStatus;
180
202
  headers: WP_TypedHeaders<THeaders, THeaderName>;
181
- error: WP_Error<TError>;
203
+ error: WP_Error<TError$1>;
182
204
  };
183
- type WP_TransportFailure<TError extends string, THeaderName extends string = string> = WP_Failure<TError, 0, Record<string, never>, THeaderName>;
184
- type WP_Result<TData$1, TError extends string> = WP_Success<TData$1> | WP_Failure<TError>;
205
+ type WP_TransportFailure<TError$1 extends string, THeaderName extends string = string> = WP_Failure<TError$1, 0, Record<string, never>, THeaderName>;
206
+ type WP_Result<TData$1, TError$1 extends string> = WP_Success<TData$1> | WP_Failure<TError$1>;
185
207
  //#endregion
186
- export { ActiveWordPressClient, WP_CallOptions, WP_Client, WP_CommonErrorCode, WP_CurrencyFormat, WP_Endpoint, WP_EndpointData, WP_EndpointDefinition, WP_EndpointInput, WP_EndpointResult, WP_ErrorData, WP_Failure, WP_List, WP_ListMetadata, WP_RequestBuild, WP_RequestContentType, WP_RequestInput, WP_RequestMethod, WP_ResponseContentType, WP_Result, WP_Success, WP_TransportFailure, WP_TypedHeaders, WordPressClientRegistry, WordPressCredentials };
208
+ export { ActiveWordPressClient, WP_CallOptions, WP_Client, WP_CommonErrorCode, WP_CurrencyFormat, WP_CustomFields, WP_CustomFieldsPath, WP_Endpoint, WP_EndpointData, WP_EndpointDefinition, WP_EndpointError, WP_EndpointInput, WP_EndpointPath, WP_EndpointResult, WP_ErrorData, WP_Failure, WP_List, WP_ListMetadata, WP_RequestBuild, WP_RequestContentType, WP_RequestInput, WP_RequestMethod, WP_ResponseContentType, WP_Result, WP_Success, WP_TransportFailure, WP_TypedHeaders, WordPressClientRegistry, WordPressCredentials, WordPressCustomFieldsRegistry, WordPressEndpointRegistry };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kizlo",
3
- "version": "0.17.0",
3
+ "version": "0.18.0",
4
4
  "type": "module",
5
5
  "description": "A headless WordPress framework for TypeScript.",
6
6
  "keywords": [