kizlo 0.2.1 → 0.3.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.
Files changed (47) hide show
  1. package/README.md +7 -11
  2. package/dist/adapters/captcha.js +13 -5
  3. package/dist/cli/commands/dev.js +1 -1
  4. package/dist/cli/commands/init.js +51 -36
  5. package/dist/cli/commands/test.js +4 -1
  6. package/dist/cli/presets/base.js +17 -9
  7. package/dist/cli/presets/nextjs.js +61 -14
  8. package/dist/cli/wp/dev.js +1 -1
  9. package/dist/cli/wp/phpunit.js +104 -0
  10. package/dist/context.js +2 -2
  11. package/dist/index.d.ts +6 -4
  12. package/dist/index.js +4 -3
  13. package/dist/integrations/nextjs/kizlo.server.d.ts +5 -6
  14. package/dist/integrations/nextjs/kizlo.server.js +7 -5
  15. package/dist/integrations/nextjs/revalidate.d.ts +28 -0
  16. package/dist/integrations/nextjs/revalidate.js +49 -0
  17. package/dist/integrations/nextjs/robots.d.ts +7 -0
  18. package/dist/integrations/nextjs/robots.js +23 -0
  19. package/dist/integrations/nextjs/seo.d.ts +7 -0
  20. package/dist/integrations/nextjs/seo.js +41 -0
  21. package/dist/integrations/nextjs/sitemap.d.ts +33 -0
  22. package/dist/integrations/nextjs/sitemap.js +31 -0
  23. package/dist/nextjs/server.d.ts +3 -1
  24. package/dist/nextjs/server.js +3 -1
  25. package/dist/nextjs.d.ts +2 -1
  26. package/dist/nextjs.js +2 -1
  27. package/dist/package.js +1 -1
  28. package/dist/post/index.js +2 -2
  29. package/dist/router.d.ts +71 -13
  30. package/dist/seo/index.js +71 -6
  31. package/dist/seo/robots.js +18 -0
  32. package/dist/seo/schema.d.ts +15 -1
  33. package/dist/seo/schema.js +5 -1
  34. package/dist/seo/sitemap.d.ts +39 -0
  35. package/dist/seo/sitemap.js +64 -0
  36. package/dist/seo/types.d.ts +5 -1
  37. package/dist/seo/utils.d.ts +6 -0
  38. package/dist/seo/utils.js +33 -1
  39. package/dist/settings/service.interface.d.ts +1 -0
  40. package/dist/shared/crypto.d.ts +11 -8
  41. package/dist/shared/crypto.js +26 -9
  42. package/dist/shared/error.d.ts +3 -3
  43. package/dist/shared/procedure.d.ts +10 -10
  44. package/dist/webhook/schema.d.ts +2 -9
  45. package/dist/webhook/schema.js +5 -16
  46. package/dist/wordpress/service.js +4 -1
  47. package/package.json +2 -2
@@ -0,0 +1,64 @@
1
+ import { parseSitemapSlug, renderSitemapIndex, renderUrlSet, xmlResponse } from "./utils.js";
2
+
3
+ //#region src/seo/sitemap.ts
4
+ /**
5
+ * Every generated sitemap is served from `/sitemaps`: the index at `/sitemaps/index.xml`
6
+ * and each collection page at `/sitemaps/{key}.xml` (later pages `-{n}`). The base is fixed
7
+ * because the index `<loc>` entries (built by `sitemapEntryPath`) point at it, so the route
8
+ * must be mounted there for the links to resolve. How the route is mounted is a
9
+ * framework concern; this handler only cares about the trailing slug.
10
+ */
11
+ const SITEMAP_BASE = "/sitemaps";
12
+ /** Slug that serves the sitemap index (`/sitemaps/index.xml`) rather than a collection. */
13
+ const SITEMAP_INDEX_SLUG = "index.xml";
14
+ /**
15
+ * Builds a Web `Request` -> `Response` handler that serves the sitemap index
16
+ * (`/sitemaps/index.xml`) and every collection page, merging any `extra` sitemaps in.
17
+ * Framework-agnostic: the slug is the last path segment of the request URL, so this runs
18
+ * as-is on any web-standard server (Hono, a plain fetch handler, a Next route handler).
19
+ * Mounting it at the right path is the caller's job; framework wrappers (e.g. the Next
20
+ * integration) add mount assertions on top.
21
+ */
22
+ function createSitemapRoute(client, options) {
23
+ const extra = options?.extra ?? [];
24
+ return async function GET(request) {
25
+ const url = new URL(request.url);
26
+ const slug = lastPathSegment(url);
27
+ if (!slug) return notFound();
28
+ if (slug === SITEMAP_INDEX_SLUG) {
29
+ const { data: data$1 } = await client.seo.sitemaps.index();
30
+ return xmlResponse(renderSitemapIndex([...data$1?.sitemaps ?? [], ...extra.map((item) => item.entry)], data$1?.origin ?? url.origin));
31
+ }
32
+ const parsed = parseSitemapSlug(slug);
33
+ if (!parsed) return notFound();
34
+ const custom = extra.find((item) => item.entry.key === parsed.key);
35
+ if (custom) {
36
+ if (parsed.page > custom.entry.pages) return notFound();
37
+ const { data: data$1 } = await client.seo.sitemaps.index();
38
+ return xmlResponse(renderUrlSet(await custom.urls(data$1?.origin ?? url.origin, parsed.page)));
39
+ }
40
+ const { data: sitemaps } = await client.seo.sitemaps.list();
41
+ if (!sitemaps) return notFound();
42
+ const entry = sitemaps.find((item) => item.key === parsed.key);
43
+ if (!entry || parsed.page > entry.pages) return notFound();
44
+ const { data } = await client.seo.urls(entry.type === "author" ? {
45
+ type: "author",
46
+ page: parsed.page
47
+ } : {
48
+ type: entry.type,
49
+ key: entry.key,
50
+ page: parsed.page
51
+ });
52
+ if (!data) return notFound();
53
+ return xmlResponse(renderUrlSet(data));
54
+ };
55
+ }
56
+ function lastPathSegment(url) {
57
+ return decodeURIComponent(url.pathname.split("/").filter(Boolean).pop() ?? "");
58
+ }
59
+ function notFound() {
60
+ return new Response("Not Found", { status: 404 });
61
+ }
62
+
63
+ //#endregion
64
+ export { SITEMAP_BASE, SITEMAP_INDEX_SLUG, createSitemapRoute };
@@ -62,6 +62,10 @@ interface WPK_Sitemap {
62
62
  pages: number;
63
63
  lastmod: string;
64
64
  }
65
+ interface WPK_SitemapIndex {
66
+ origin: string;
67
+ sitemaps: WPK_Sitemap[];
68
+ }
65
69
  interface WPK_SitemapUrlImage {
66
70
  loc: string;
67
71
  title: string;
@@ -77,4 +81,4 @@ interface WPK_ListSitemapUrlInput {
77
81
  page?: number;
78
82
  }
79
83
  //#endregion
80
- export { WPK_ListSitemapUrlInput, WPK_RobotRule, WPK_Robots, WPK_Seo, WPK_Sitemap, WPK_SitemapContentType, WPK_SitemapUrl, WPK_SitemapUrlImage };
84
+ export { WPK_ListSitemapUrlInput, WPK_RobotRule, WPK_Robots, WPK_Seo, WPK_Sitemap, WPK_SitemapContentType, WPK_SitemapIndex, WPK_SitemapUrl, WPK_SitemapUrlImage };
@@ -0,0 +1,6 @@
1
+ import { Sitemap } from "./schema.js";
2
+
3
+ //#region src/seo/utils.d.ts
4
+ type SitemapIndexEntry = Pick<Sitemap, "key" | "pages" | "lastmod">;
5
+ //#endregion
6
+ export { SitemapIndexEntry };
package/dist/seo/utils.js CHANGED
@@ -39,6 +39,38 @@ function deserializeSeo(data) {
39
39
  schema: data.schema
40
40
  };
41
41
  }
42
+ function sitemapEntryPath(key, page) {
43
+ return `/sitemaps/${key}${page > 1 ? `-${page}` : ""}.xml`;
44
+ }
45
+ function parseSitemapSlug(slug) {
46
+ const match = /^(.+?)(?:-(\d+))?\.xml$/.exec(slug);
47
+ if (!match) return null;
48
+ const [, key, rawPage] = match;
49
+ const page = rawPage ? Number(rawPage) : 1;
50
+ if (!key || !Number.isInteger(page) || page < 1) return null;
51
+ return {
52
+ key,
53
+ page
54
+ };
55
+ }
56
+ function escapeXml(value) {
57
+ return value.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
58
+ }
59
+ function renderSitemapIndex(sitemaps, origin) {
60
+ return `<?xml version="1.0" encoding="UTF-8"?>\n<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">\n${sitemaps.flatMap((sitemap) => Array.from({ length: sitemap.pages }, (_, index) => {
61
+ return `\t<sitemap>\n\t\t<loc>${escapeXml(`${origin}${sitemapEntryPath(sitemap.key, index + 1)}`)}</loc>\n\t\t<lastmod>${escapeXml(sitemap.lastmod)}</lastmod>\n\t</sitemap>`;
62
+ })).join("\n")}\n</sitemapindex>\n`;
63
+ }
64
+ function renderUrlSet(urls) {
65
+ return `<?xml version="1.0" encoding="UTF-8"?>\n<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">\n${urls.map((url) => {
66
+ const images = url.images.map((image) => `\t\t<image:image>\n\t\t\t<image:loc>${escapeXml(image.loc)}</image:loc>\n\t\t</image:image>`).join("\n");
67
+ const imageBlock = images ? `\n${images}` : "";
68
+ return `\t<url>\n\t\t<loc>${escapeXml(url.loc)}</loc>\n\t\t<lastmod>${escapeXml(url.lastmod)}</lastmod>${imageBlock}\n\t</url>`;
69
+ }).join("\n")}\n</urlset>\n`;
70
+ }
71
+ function xmlResponse(body) {
72
+ return new Response(body, { headers: { "Content-Type": "application/xml; charset=utf-8" } });
73
+ }
42
74
 
43
75
  //#endregion
44
- export { deserializeSeo };
76
+ export { deserializeSeo, parseSitemapSlug, renderSitemapIndex, renderUrlSet, xmlResponse };
@@ -17,6 +17,7 @@ interface KizloSiteSettings {
17
17
  title_separator: string;
18
18
  fallback_image: KizloMedia | null;
19
19
  search_action_structure: string | null;
20
+ discourage_search_engines: boolean;
20
21
  }
21
22
  interface KizloPersonSettings {
22
23
  name: string;
@@ -1,15 +1,18 @@
1
- import { BinaryLike } from "node:crypto";
2
-
3
1
  //#region src/shared/crypto.d.ts
4
-
2
+ /** SHA family accepted by the Web Crypto API. */
3
+ type ShaAlgorithm = "SHA-256" | "SHA-384" | "SHA-512";
5
4
  /**
6
5
  * Compares two strings in a timing-safe manner to prevent timing attacks.
7
6
  *
7
+ * Both inputs are hashed to fixed-length digests before comparison, so the
8
+ * check is constant-time regardless of input length and never throws on a
9
+ * length mismatch.
10
+ *
8
11
  * @param a - The first string to compare.
9
12
  * @param b - The second string to compare.
10
13
  * @returns `true` if the strings match, `false` otherwise.
11
14
  */
12
- declare function compare(a: string, b: string): boolean;
15
+ declare function compare(a: string, b: string): Promise<boolean>;
13
16
  /**
14
17
  * Hashes a secret API key with SHA-256 for secure database storage.
15
18
  * Safe to use in place of bcrypt/argon2 because API keys are high-entropy
@@ -19,10 +22,10 @@ declare function compare(a: string, b: string): boolean;
19
22
  * @param key - The raw secret API key to hash.
20
23
  * @returns A SHA-256 hex string suitable for database storage.
21
24
  */
22
- declare function hash(key: string): string;
25
+ declare function hash(key: string, algorithm?: ShaAlgorithm): Promise<string>;
23
26
  /**
24
- * Create hmac using node crypto lib.
27
+ * Create an HMAC hex digest using the Web Crypto API. Defaults to SHA-256.
25
28
  */
26
- declare function hmac(key: string, value: BinaryLike): string;
29
+ declare function hmac(key: string, value: string, algorithm?: ShaAlgorithm): Promise<string>;
27
30
  //#endregion
28
- export { compare, hash, hmac };
31
+ export { ShaAlgorithm, compare, hash, hmac };
@@ -1,15 +1,28 @@
1
- import { createHash, createHmac, timingSafeEqual } from "node:crypto";
2
-
3
1
  //#region src/shared/crypto.ts
2
+ const encoder = new TextEncoder();
3
+ function toHex(buffer) {
4
+ let hex = "";
5
+ for (const byte of new Uint8Array(buffer)) hex += byte.toString(16).padStart(2, "0");
6
+ return hex;
7
+ }
4
8
  /**
5
9
  * Compares two strings in a timing-safe manner to prevent timing attacks.
6
10
  *
11
+ * Both inputs are hashed to fixed-length digests before comparison, so the
12
+ * check is constant-time regardless of input length and never throws on a
13
+ * length mismatch.
14
+ *
7
15
  * @param a - The first string to compare.
8
16
  * @param b - The second string to compare.
9
17
  * @returns `true` if the strings match, `false` otherwise.
10
18
  */
11
- function compare(a, b) {
12
- return timingSafeEqual(Buffer.from(a), Buffer.from(b));
19
+ async function compare(a, b) {
20
+ const [ha, hb] = await Promise.all([crypto.subtle.digest("SHA-256", encoder.encode(a)), crypto.subtle.digest("SHA-256", encoder.encode(b))]);
21
+ const va = new Uint8Array(ha);
22
+ const vb = new Uint8Array(hb);
23
+ let diff = 0;
24
+ for (let i = 0; i < va.length; i++) diff |= (va[i] ?? 0) ^ (vb[i] ?? 0);
25
+ return diff === 0;
13
26
  }
14
27
  /**
15
28
  * Hashes a secret API key with SHA-256 for secure database storage.
@@ -20,14 +33,18 @@ function compare(a, b) {
20
33
  * @param key - The raw secret API key to hash.
21
34
  * @returns A SHA-256 hex string suitable for database storage.
22
35
  */
23
- function hash(key) {
24
- return createHash("sha256").update(key).digest("hex");
36
+ async function hash(key, algorithm = "SHA-256") {
37
+ return toHex(await crypto.subtle.digest(algorithm, encoder.encode(key)));
25
38
  }
26
39
  /**
27
- * Create hmac using node crypto lib.
40
+ * Create an HMAC hex digest using the Web Crypto API. Defaults to SHA-256.
28
41
  */
29
- function hmac(key, value) {
30
- return createHmac("sha256", key).update(value).digest("hex");
42
+ async function hmac(key, value, algorithm = "SHA-256") {
43
+ const cryptoKey = await crypto.subtle.importKey("raw", encoder.encode(key), {
44
+ name: "HMAC",
45
+ hash: algorithm
46
+ }, false, ["sign"]);
47
+ return toHex(await crypto.subtle.sign("HMAC", cryptoKey, encoder.encode(value)));
31
48
  }
32
49
 
33
50
  //#endregion
@@ -1,4 +1,4 @@
1
- import { AnySchema, LiteralUnion, Metadata, SchemaInput, SchemaOutput } from "@kizlo/shared";
1
+ import { LiteralUnion, Metadata, Schema, SchemaInput, SchemaOutput } from "@kizlo/shared";
2
2
 
3
3
  //#region src/shared/error.d.ts
4
4
  declare const COMMON_ERRORS: {
@@ -116,11 +116,11 @@ type ErrorDefinition = {
116
116
  /** Human-readable message. Overridable per throw via `errors.CODE({ message })`. */
117
117
  message?: string;
118
118
  /** Standard Schema for the error's `data` payload — validated and typed when you throw `errors.CODE({ data })`. */
119
- data?: AnySchema;
119
+ data?: Schema;
120
120
  };
121
121
  declare function defineErrorMap<const T extends Partial<Record<CommonErrorLiteral, ErrorDefinition>>>(map: T): T;
122
122
  type DefinedErrorMapLike = Record<string, ErrorDefinition>;
123
- type ThrowableErrorFn<TCode extends string, T extends ErrorDefinition> = T["data"] extends AnySchema ? undefined extends SchemaInput<T["data"]> ? (options?: {
123
+ type ThrowableErrorFn<TCode extends string, T extends ErrorDefinition> = T["data"] extends Schema ? undefined extends SchemaInput<T["data"]> ? (options?: {
124
124
  status?: number;
125
125
  message?: string;
126
126
  data?: SchemaInput<T["data"]>;
@@ -2,7 +2,7 @@ import { DefinedErrorMapLike, ThrowableErrorMap, WithCommonErrorMap } from "./er
2
2
  import { ServerContext } from "../context.js";
3
3
  import { AnyMiddleware, InferUses, Middleware } from "./middleware.js";
4
4
  import * as _orpc_contract0 from "@orpc/contract";
5
- import { AnySchema, DeepMerge, Pathname, Prettify, Promisify, Schema, SchemaInput, SchemaOutput } from "@kizlo/shared";
5
+ import { DeepMerge, Pathname, Prettify, Promisify, Schema, SchemaInput, SchemaOutput } from "@kizlo/shared";
6
6
  import * as _orpc_server0 from "@orpc/server";
7
7
  import { HTTPMethod } from "@orpc/server";
8
8
  import { JsonifiedValue } from "@orpc/openapi-client";
@@ -33,25 +33,25 @@ interface Procedure<TScope extends InvocationScope, TInput, TOutput, TError exte
33
33
  options: {
34
34
  scope: TScope;
35
35
  errors?: TError;
36
- output: AnySchema;
36
+ output: Schema;
37
37
  inputValidation?: boolean;
38
38
  outputValidation?: boolean;
39
39
  middlewares?: AnyMiddleware[];
40
40
  } & ({
41
41
  scope: "internal";
42
- input?: AnySchema;
42
+ input?: Schema;
43
43
  } | {
44
44
  scope: "remote";
45
- input?: AnySchema;
45
+ input?: Schema;
46
46
  method?: HTTPMethod;
47
47
  } | {
48
48
  scope: "api";
49
49
  method?: HTTPMethod;
50
50
  path?: Pathname;
51
- body?: AnySchema;
52
- query?: AnySchema;
53
- params?: AnySchema;
54
- headers?: AnySchema;
51
+ body?: Schema;
52
+ query?: Schema;
53
+ params?: Schema;
54
+ headers?: Schema;
55
55
  });
56
56
  };
57
57
  }
@@ -112,9 +112,9 @@ type ProcedureOptions<TScope extends InvocationScope, TPathname extends Pathname
112
112
  input?: TInput;
113
113
  });
114
114
  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<TMiddlewares> = ProcedureContext<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>;
115
- declare function schemaType<TInput, TOutput = TInput>(schema?: AnySchema): Schema<TInput, TOutput>;
115
+ declare function schemaType<TInput, TOutput = TInput>(schema?: Schema): Schema<TInput, TOutput>;
116
116
  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>>;
117
117
  declare function handleUnexpectedError(error: unknown, errors?: DefinedErrorMapLike): never;
118
- declare function combineDetailed(parts: Record<string, AnySchema>): AnySchema;
118
+ declare function combineDetailed(parts: Record<string, Schema>): Schema;
119
119
  //#endregion
120
120
  export { AnyProcedure, AnyProcedureRouter, BaseHandlerOptions, ExtractParams, ExtractProcedureByScope, InvocationScope, OpenapiPart, Procedure, ProcedureContext, ProcedureErrors, ProcedureHandler, ProcedureOptions, ResolveParamsPart, ResolvedSchemaInput, ResolvedSchemaOutput, RouterDepthTuple, SchemaIO, buildProcedure, combineDetailed, createProcedure, handleUnexpectedError, schemaType };
@@ -12,6 +12,7 @@ declare const KizloEvent: z.ZodUnion<readonly [z.ZodObject<{
12
12
  data: z.ZodObject<{
13
13
  post_id: z.ZodNumber;
14
14
  post_type: z.ZodString;
15
+ url: z.ZodOptional<z.ZodString>;
15
16
  }, z.core.$strip>;
16
17
  }, z.core.$strip>, z.ZodObject<{
17
18
  type: z.ZodEnum<{
@@ -24,15 +25,7 @@ declare const KizloEvent: z.ZodUnion<readonly [z.ZodObject<{
24
25
  taxonomy: z.ZodString;
25
26
  post_types: z.ZodArray<z.ZodString>;
26
27
  count: z.ZodNumber;
27
- }, z.core.$strip>;
28
- }, z.core.$strip>, z.ZodObject<{
29
- type: z.ZodEnum<{
30
- "payment.status_requested": "payment.status_requested";
31
- }>;
32
- data: z.ZodObject<{
33
- transaction_id: z.ZodNullable<z.ZodString>;
34
- payment_method_id: z.ZodString;
35
- payment_session_id: z.ZodString;
28
+ url: z.ZodOptional<z.ZodString>;
36
29
  }, z.core.$strip>;
37
30
  }, z.core.$strip>, z.ZodObject<{
38
31
  type: z.ZodEnum<{
@@ -14,20 +14,18 @@ const POST_EVENT_TYPES = [
14
14
  "post.deleted"
15
15
  ];
16
16
  const PostEventType = z.enum(POST_EVENT_TYPES);
17
- const PAYMENT_EVENT_TYPES = ["payment.status_requested"];
18
- const PaymentEventType = z.enum(PAYMENT_EVENT_TYPES);
19
17
  const SETTINGS_EVENT_TYPES = ["settings.saved"];
20
18
  const SettingsEventType = z.enum(SETTINGS_EVENT_TYPES);
21
19
  const EVENT_TYPES = [
22
20
  ...TERM_EVENT_TYPES,
23
21
  ...POST_EVENT_TYPES,
24
- ...PAYMENT_EVENT_TYPES,
25
22
  ...SETTINGS_EVENT_TYPES
26
23
  ];
27
24
  const EventType = z.enum(EVENT_TYPES);
28
25
  const PostEventData = z.object({
29
26
  post_id: z.number(),
30
- post_type: z.string()
27
+ post_type: z.string(),
28
+ url: z.string().optional()
31
29
  });
32
30
  const PostEvent = z.object({
33
31
  type: PostEventType,
@@ -37,21 +35,13 @@ const TermEventData = z.object({
37
35
  term_id: z.number(),
38
36
  taxonomy: z.string(),
39
37
  post_types: z.array(z.string()),
40
- count: z.number().nonnegative()
38
+ count: z.number().nonnegative(),
39
+ url: z.string().optional()
41
40
  });
42
41
  const TermEvent = z.object({
43
42
  type: TermEventType,
44
43
  data: TermEventData
45
44
  });
46
- const PaymentEventData = z.object({
47
- transaction_id: z.nullable(z.string()),
48
- payment_method_id: z.string(),
49
- payment_session_id: z.string()
50
- });
51
- const PaymentEvent = z.object({
52
- type: PaymentEventType,
53
- data: PaymentEventData
54
- });
55
45
  const SettingsEventData = z.null();
56
46
  const SettingsEvent = z.object({
57
47
  type: SettingsEventType,
@@ -60,7 +50,6 @@ const SettingsEvent = z.object({
60
50
  const KizloEvent = z.union([
61
51
  PostEvent,
62
52
  TermEvent,
63
- PaymentEvent,
64
53
  SettingsEvent
65
54
  ]);
66
55
  const AnyEvent = z.object({
@@ -69,4 +58,4 @@ const AnyEvent = z.object({
69
58
  });
70
59
 
71
60
  //#endregion
72
- export { AnyEvent, KizloEvent };
61
+ export { AnyEvent, KizloEvent, POST_EVENT_TYPES, TERM_EVENT_TYPES };
@@ -17,7 +17,10 @@ var WordPressService = class {
17
17
  authHeader;
18
18
  defaultTimeout;
19
19
  constructor(context) {
20
- this.authHeader = `${WP_AUTH_TYPE} ${Buffer.from(`${context.credentials.username}:${context.credentials.password}`, "utf8").toString("base64")}`;
20
+ const credentialBytes = new TextEncoder().encode(`${context.credentials.username}:${context.credentials.password}`);
21
+ let binary = "";
22
+ for (const byte of credentialBytes) binary += String.fromCharCode(byte);
23
+ this.authHeader = `${WP_AUTH_TYPE} ${btoa(binary)}`;
21
24
  this.siteBase = context.credentials.url.endsWith("/") ? context.credentials.url : `${context.credentials.url}/`;
22
25
  this.defaultTimeout = context.timeout ?? SAFE_REQUEST_TIMEOUT;
23
26
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kizlo",
3
- "version": "0.2.1",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
5
  "description": "A headless WordPress toolkit for TypeScript.",
6
6
  "keywords": [
@@ -76,7 +76,7 @@
76
76
  },
77
77
  "dependencies": {
78
78
  "@clack/prompts": "^1.5.1",
79
- "@kizlo/shared": "0.1.1",
79
+ "@kizlo/shared": "0.1.2",
80
80
  "@orpc/client": "^1.14.3",
81
81
  "@orpc/contract": "^1.14.3",
82
82
  "@orpc/openapi": "^1.14.3",