kizlo 0.1.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/LICENSE +21 -0
- package/README.md +74 -0
- package/dist/adapters/auth.d.ts +18 -0
- package/dist/adapters/auth.js +15 -0
- package/dist/adapters/captcha.d.ts +28 -0
- package/dist/adapters/captcha.js +86 -0
- package/dist/adapters/geo.d.ts +18 -0
- package/dist/adapters/geo.js +18 -0
- package/dist/adapters/geo.vercel.d.ts +6 -0
- package/dist/adapters/geo.vercel.js +41 -0
- package/dist/adapters/logger.d.ts +31 -0
- package/dist/adapters/logger.js +30 -0
- package/dist/cli/banner.js +26 -0
- package/dist/cli/commands/generate.js +34 -0
- package/dist/cli/commands/init.js +313 -0
- package/dist/cli/commands/test.js +68 -0
- package/dist/cli/commands/watch.js +53 -0
- package/dist/cli/commands/wp.js +66 -0
- package/dist/cli/daemon/config.js +87 -0
- package/dist/cli/daemon/generate.js +40 -0
- package/dist/cli/daemon/lock.js +31 -0
- package/dist/cli/daemon/logger.js +8 -0
- package/dist/cli/daemon/watch.js +37 -0
- package/dist/cli/index.d.ts +1 -0
- package/dist/cli/index.js +22 -0
- package/dist/cli/presets/base.js +23 -0
- package/dist/cli/presets/index.js +16 -0
- package/dist/cli/presets/nextjs.js +39 -0
- package/dist/cli/utils.js +182 -0
- package/dist/cli/wp/bootstrap.js +114 -0
- package/dist/cli/wp/compose/docker-compose.yml +73 -0
- package/dist/cli/wp/constants.js +52 -0
- package/dist/cli/wp/docker.d.ts +24 -0
- package/dist/cli/wp/docker.js +69 -0
- package/dist/cli/wp/setup.js +39 -0
- package/dist/cli/wp/types.d.ts +72 -0
- package/dist/cli/wp/types.js +8 -0
- package/dist/cli/wp/utils.d.ts +39 -0
- package/dist/cli/wp/utils.js +105 -0
- package/dist/client.d.ts +24 -0
- package/dist/client.js +55 -0
- package/dist/comment/errors.js +47 -0
- package/dist/comment/index.js +138 -0
- package/dist/comment/schema.js +72 -0
- package/dist/comment/utils.js +35 -0
- package/dist/config.d.ts +39 -0
- package/dist/config.js +7 -0
- package/dist/context.d.ts +73 -0
- package/dist/context.js +145 -0
- package/dist/cookie.d.ts +19 -0
- package/dist/cookie.js +25 -0
- package/dist/email/service.d.ts +11 -0
- package/dist/email/service.interface.d.ts +8 -0
- package/dist/email/service.js +20 -0
- package/dist/index.d.ts +39 -0
- package/dist/index.js +31 -0
- package/dist/integrations/nextjs/kizlo.client.d.ts +10 -0
- package/dist/integrations/nextjs/kizlo.client.js +13 -0
- package/dist/integrations/nextjs/kizlo.server.d.ts +12 -0
- package/dist/integrations/nextjs/kizlo.server.js +13 -0
- package/dist/integrations/nextjs/utils.js +11 -0
- package/dist/kizlo.d.ts +73 -0
- package/dist/kizlo.js +144 -0
- package/dist/menu/errors.js +16 -0
- package/dist/menu/fixture.d.ts +8 -0
- package/dist/menu/fixture.js +62 -0
- package/dist/menu/index.js +70 -0
- package/dist/menu/schema.js +70 -0
- package/dist/menu/utils.js +57 -0
- package/dist/nextjs/server.d.ts +2 -0
- package/dist/nextjs/server.js +3 -0
- package/dist/nextjs.d.ts +2 -0
- package/dist/nextjs.js +3 -0
- package/dist/package.js +5 -0
- package/dist/post/error.js +30 -0
- package/dist/post/fixture.d.ts +8 -0
- package/dist/post/fixture.js +71 -0
- package/dist/post/index.js +123 -0
- package/dist/post/schema.js +120 -0
- package/dist/post/utils.js +42 -0
- package/dist/post-type/service.js +48 -0
- package/dist/router.d.ts +624 -0
- package/dist/router.js +15 -0
- package/dist/seo/index.js +54 -0
- package/dist/seo/schema.d.ts +196 -0
- package/dist/seo/schema.js +96 -0
- package/dist/seo/types.d.ts +80 -0
- package/dist/seo/utils.js +44 -0
- package/dist/service.d.ts +17 -0
- package/dist/service.js +17 -0
- package/dist/shared/constants.js +10 -0
- package/dist/shared/contract.d.ts +21 -0
- package/dist/shared/contract.js +43 -0
- package/dist/shared/crypto.d.ts +28 -0
- package/dist/shared/crypto.js +34 -0
- package/dist/shared/error.d.ts +128 -0
- package/dist/shared/error.js +147 -0
- package/dist/shared/extension.d.ts +25 -0
- package/dist/shared/extension.js +7 -0
- package/dist/shared/identifier.d.ts +11 -0
- package/dist/shared/identifier.js +26 -0
- package/dist/shared/middleware.d.ts +29 -0
- package/dist/shared/procedure.d.ts +114 -0
- package/dist/shared/procedure.js +114 -0
- package/dist/shared/result.d.ts +24 -0
- package/dist/shared/result.js +49 -0
- package/dist/shared/router.d.ts +7 -0
- package/dist/shared/router.js +26 -0
- package/dist/shared/schema.d.ts +55 -0
- package/dist/shared/schema.js +43 -0
- package/dist/shared/serialize.d.ts +12 -0
- package/dist/shared/serialize.js +51 -0
- package/dist/shared/types.d.ts +35 -0
- package/dist/shared/utils.js +17 -0
- package/dist/test/auth.d.ts +7 -0
- package/dist/test/auth.js +15 -0
- package/dist/test/captcha.d.ts +7 -0
- package/dist/test/captcha.js +8 -0
- package/dist/test/client.d.ts +11 -0
- package/dist/test/client.js +14 -0
- package/dist/test/fixtures.d.ts +14 -0
- package/dist/test/fixtures.js +13 -0
- package/dist/test/server.d.ts +10 -0
- package/dist/test/server.js +32 -0
- package/dist/test/users.d.ts +14 -0
- package/dist/test/users.js +17 -0
- package/dist/test.d.ts +12 -0
- package/dist/test.js +13 -0
- package/dist/webhook/index.d.ts +38 -0
- package/dist/webhook/index.js +44 -0
- package/dist/webhook/schema.d.ts +45 -0
- package/dist/webhook/schema.js +72 -0
- package/dist/webhook/utils.js +21 -0
- package/dist/wordpress/comment/service.d.ts +28 -0
- package/dist/wordpress/comment/service.js +55 -0
- package/dist/wordpress/comment/types.d.ts +206 -0
- package/dist/wordpress/constants.d.ts +14 -0
- package/dist/wordpress/constants.js +13 -0
- package/dist/wordpress/error.d.ts +9 -0
- package/dist/wordpress/error.js +12 -0
- package/dist/wordpress/index.d.ts +15 -0
- package/dist/wordpress/menu/items/service.d.ts +28 -0
- package/dist/wordpress/menu/items/service.js +55 -0
- package/dist/wordpress/menu/items/types.d.ts +214 -0
- package/dist/wordpress/menu/service.d.ts +30 -0
- package/dist/wordpress/menu/service.js +58 -0
- package/dist/wordpress/menu/types.d.ts +115 -0
- package/dist/wordpress/post/service.d.ts +28 -0
- package/dist/wordpress/post/service.js +55 -0
- package/dist/wordpress/post/types.d.ts +290 -0
- package/dist/wordpress/service.d.ts +77 -0
- package/dist/wordpress/service.js +180 -0
- package/dist/wordpress/types.d.ts +67 -0
- package/dist/wordpress/user/service.d.ts +28 -0
- package/dist/wordpress/user/service.js +55 -0
- package/dist/wordpress/user/types.d.ts +221 -0
- package/dist/wordpress/utils.d.ts +7 -0
- package/dist/wordpress/utils.js +9 -0
- package/package.json +109 -0
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { buildProcedure } from "./procedure.js";
|
|
2
|
+
|
|
3
|
+
//#region src/shared/router.ts
|
|
4
|
+
function createOrpcRouter(router) {
|
|
5
|
+
const cache = /* @__PURE__ */ new Map();
|
|
6
|
+
return new Proxy(router, { get: (target, p) => {
|
|
7
|
+
if (typeof p === "symbol") return target[p];
|
|
8
|
+
if (cache.has(p)) return cache.get(p);
|
|
9
|
+
const value = target[p];
|
|
10
|
+
if (value === void 0) return void 0;
|
|
11
|
+
let resolved;
|
|
12
|
+
if (isProcedure(value)) resolved = buildProcedure(value);
|
|
13
|
+
else if (typeof value === "object" && value !== null) resolved = createOrpcRouter(value);
|
|
14
|
+
else resolved = value;
|
|
15
|
+
cache.set(p, resolved);
|
|
16
|
+
return resolved;
|
|
17
|
+
} });
|
|
18
|
+
}
|
|
19
|
+
function isProcedure(value) {
|
|
20
|
+
if (typeof value !== "object" || value === null) return false;
|
|
21
|
+
const brand = value["~kizlo"];
|
|
22
|
+
return typeof brand === "object" && brand !== null && "options" in brand && "uses" in brand && "handler" in brand && typeof brand.handler === "function";
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
//#endregion
|
|
26
|
+
export { createOrpcRouter };
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import z from "zod/v4";
|
|
2
|
+
|
|
3
|
+
//#region src/shared/schema.d.ts
|
|
4
|
+
declare const LIST_ORDER: readonly ["asc", "desc"];
|
|
5
|
+
declare const ListOrder: z.ZodEnum<{
|
|
6
|
+
asc: "asc";
|
|
7
|
+
desc: "desc";
|
|
8
|
+
}>;
|
|
9
|
+
type ListOrder = z.infer<typeof ListOrder>;
|
|
10
|
+
declare const ListMetadata: z.ZodObject<{
|
|
11
|
+
page: z.ZodNumber;
|
|
12
|
+
totalItems: z.ZodNumber;
|
|
13
|
+
totalPages: z.ZodNumber;
|
|
14
|
+
nextPage: z.ZodNullable<z.ZodNumber>;
|
|
15
|
+
prevPage: z.ZodNullable<z.ZodNumber>;
|
|
16
|
+
hasNextPage: z.ZodBoolean;
|
|
17
|
+
hasPrevPage: z.ZodBoolean;
|
|
18
|
+
}, z.core.$strip>;
|
|
19
|
+
type ListMetadata = z.infer<typeof ListMetadata>;
|
|
20
|
+
declare const CurrencyFormat: z.ZodObject<{
|
|
21
|
+
currencyCode: z.ZodString;
|
|
22
|
+
currencySymbol: z.ZodString;
|
|
23
|
+
currencyPrefix: z.ZodString;
|
|
24
|
+
currencySuffix: z.ZodString;
|
|
25
|
+
currencyMinorUnit: z.ZodNumber;
|
|
26
|
+
currencyDecimalSeparator: z.ZodString;
|
|
27
|
+
currencyThousandSeparator: z.ZodString;
|
|
28
|
+
}, z.core.$strip>;
|
|
29
|
+
type CurrencyFormat = z.infer<typeof CurrencyFormat>;
|
|
30
|
+
declare const Media: z.ZodObject<{
|
|
31
|
+
id: z.ZodNumber;
|
|
32
|
+
name: z.ZodString;
|
|
33
|
+
alt: z.ZodString;
|
|
34
|
+
src: z.ZodString;
|
|
35
|
+
}, z.core.$strip>;
|
|
36
|
+
type Media = z.infer<typeof Media>;
|
|
37
|
+
declare const IdentifierInput: z.ZodUnion<readonly [z.ZodPipe<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>, z.ZodCoercedNumber<string | number>>, z.ZodString]>;
|
|
38
|
+
type IdentifierInput = z.output<typeof IdentifierInput>;
|
|
39
|
+
declare const PreviewTokenPayload: z.ZodObject<{
|
|
40
|
+
id: z.ZodNumber;
|
|
41
|
+
parent: z.ZodNumber;
|
|
42
|
+
expires: z.ZodNumber;
|
|
43
|
+
}, z.core.$strip>;
|
|
44
|
+
type PreviewTokenPayload = z.infer<typeof PreviewTokenPayload>;
|
|
45
|
+
declare const PreviewTokenData: z.ZodObject<{
|
|
46
|
+
hash: z.ZodString;
|
|
47
|
+
payload: z.ZodObject<{
|
|
48
|
+
id: z.ZodNumber;
|
|
49
|
+
parent: z.ZodNumber;
|
|
50
|
+
expires: z.ZodNumber;
|
|
51
|
+
}, z.core.$strip>;
|
|
52
|
+
}, z.core.$strip>;
|
|
53
|
+
type PreviewTokenData = z.infer<typeof PreviewTokenData>;
|
|
54
|
+
//#endregion
|
|
55
|
+
export { CurrencyFormat, IdentifierInput, LIST_ORDER, ListMetadata, ListOrder, Media, PreviewTokenData, PreviewTokenPayload };
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { NumberLike } from "@kizlo/shared";
|
|
2
|
+
import z from "zod/v4";
|
|
3
|
+
|
|
4
|
+
//#region src/shared/schema.ts
|
|
5
|
+
const LIST_ORDER = ["asc", "desc"];
|
|
6
|
+
const ListOrder = z.enum(LIST_ORDER);
|
|
7
|
+
const ListMetadata = z.object({
|
|
8
|
+
page: z.number(),
|
|
9
|
+
totalItems: z.number(),
|
|
10
|
+
totalPages: z.number(),
|
|
11
|
+
nextPage: z.number().nullable(),
|
|
12
|
+
prevPage: z.number().nullable(),
|
|
13
|
+
hasNextPage: z.boolean(),
|
|
14
|
+
hasPrevPage: z.boolean()
|
|
15
|
+
});
|
|
16
|
+
const CurrencyFormat = z.object({
|
|
17
|
+
currencyCode: z.string(),
|
|
18
|
+
currencySymbol: z.string(),
|
|
19
|
+
currencyPrefix: z.string(),
|
|
20
|
+
currencySuffix: z.string(),
|
|
21
|
+
currencyMinorUnit: z.number(),
|
|
22
|
+
currencyDecimalSeparator: z.string(),
|
|
23
|
+
currencyThousandSeparator: z.string()
|
|
24
|
+
});
|
|
25
|
+
const Media = z.object({
|
|
26
|
+
id: z.number(),
|
|
27
|
+
name: z.string(),
|
|
28
|
+
alt: z.string(),
|
|
29
|
+
src: z.string()
|
|
30
|
+
});
|
|
31
|
+
const IdentifierInput = z.union([NumberLike, z.string()]);
|
|
32
|
+
const PreviewTokenPayload = z.object({
|
|
33
|
+
id: z.number(),
|
|
34
|
+
parent: z.number(),
|
|
35
|
+
expires: z.number()
|
|
36
|
+
});
|
|
37
|
+
const PreviewTokenData = z.object({
|
|
38
|
+
hash: z.string(),
|
|
39
|
+
payload: PreviewTokenPayload
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
//#endregion
|
|
43
|
+
export { CurrencyFormat, IdentifierInput, LIST_ORDER, ListMetadata, ListOrder, Media, PreviewTokenData, PreviewTokenPayload };
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { WP_CurrencyFormat, WP_ListMetadata } from "../wordpress/types.js";
|
|
2
|
+
import "../wordpress/index.js";
|
|
3
|
+
import { CurrencyFormat, ListMetadata } from "./schema.js";
|
|
4
|
+
import { List } from "./types.js";
|
|
5
|
+
|
|
6
|
+
//#region src/shared/serialize.d.ts
|
|
7
|
+
declare function emptyList<T>(): List<T>;
|
|
8
|
+
declare function deserializeListMetadata(data: WP_ListMetadata): ListMetadata;
|
|
9
|
+
declare function serializeCurrencyFormat(data: CurrencyFormat): WP_CurrencyFormat;
|
|
10
|
+
declare function deserializeCurrencyFormat(data: WP_CurrencyFormat): CurrencyFormat;
|
|
11
|
+
//#endregion
|
|
12
|
+
export { deserializeCurrencyFormat, deserializeListMetadata, emptyList, serializeCurrencyFormat };
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
//#region src/shared/serialize.ts
|
|
2
|
+
function emptyList() {
|
|
3
|
+
return {
|
|
4
|
+
items: [],
|
|
5
|
+
meta: {
|
|
6
|
+
hasNextPage: false,
|
|
7
|
+
hasPrevPage: false,
|
|
8
|
+
nextPage: 0,
|
|
9
|
+
page: 0,
|
|
10
|
+
prevPage: 0,
|
|
11
|
+
totalItems: 0,
|
|
12
|
+
totalPages: 0
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function deserializeListMetadata(data) {
|
|
17
|
+
return {
|
|
18
|
+
hasNextPage: data.has_next_page,
|
|
19
|
+
hasPrevPage: data.has_prev_page,
|
|
20
|
+
nextPage: data.next_page,
|
|
21
|
+
page: data.page,
|
|
22
|
+
prevPage: data.prev_page,
|
|
23
|
+
totalItems: data.total_items,
|
|
24
|
+
totalPages: data.total_pages
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
function serializeCurrencyFormat(data) {
|
|
28
|
+
return {
|
|
29
|
+
currency_code: data.currencyCode,
|
|
30
|
+
currency_symbol: data.currencySymbol,
|
|
31
|
+
currency_prefix: data.currencyPrefix,
|
|
32
|
+
currency_suffix: data.currencySuffix,
|
|
33
|
+
currency_minor_unit: data.currencyMinorUnit,
|
|
34
|
+
currency_decimal_separator: data.currencyDecimalSeparator,
|
|
35
|
+
currency_thousand_separator: data.currencyThousandSeparator
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
function deserializeCurrencyFormat(data) {
|
|
39
|
+
return {
|
|
40
|
+
currencyCode: data.currency_code,
|
|
41
|
+
currencySymbol: data.currency_symbol,
|
|
42
|
+
currencyPrefix: data.currency_prefix,
|
|
43
|
+
currencySuffix: data.currency_suffix,
|
|
44
|
+
currencyMinorUnit: data.currency_minor_unit,
|
|
45
|
+
currencyDecimalSeparator: data.currency_decimal_separator,
|
|
46
|
+
currencyThousandSeparator: data.currency_thousand_separator
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
//#endregion
|
|
51
|
+
export { deserializeCurrencyFormat, deserializeListMetadata, emptyList, serializeCurrencyFormat };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { ListMetadata } from "./schema.js";
|
|
2
|
+
import { NestedClient } from "@orpc/client";
|
|
3
|
+
import { CookieOptions, CookieWithOptions } from "@kizlo/shared";
|
|
4
|
+
|
|
5
|
+
//#region src/shared/types.d.ts
|
|
6
|
+
type AnyContext = Record<PropertyKey, any>;
|
|
7
|
+
type AnyNestedClient = NestedClient<any>;
|
|
8
|
+
type HTTPMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH" | "HEAD";
|
|
9
|
+
type List<T> = {
|
|
10
|
+
items: T[];
|
|
11
|
+
meta: ListMetadata;
|
|
12
|
+
};
|
|
13
|
+
type MaybeOptionalOptions<TOptions> = Record<never, never> extends TOptions ? [options?: TOptions] : [options: TOptions];
|
|
14
|
+
type RedirectStatus = 301 | 302 | 303 | 307 | 308;
|
|
15
|
+
interface RedirectInput {
|
|
16
|
+
to: string | URL;
|
|
17
|
+
status?: RedirectStatus;
|
|
18
|
+
searchParams?: Record<string, string>;
|
|
19
|
+
}
|
|
20
|
+
interface CookiesAdapter {
|
|
21
|
+
setAll(cookies: CookieWithOptions[]): Promise<void> | void;
|
|
22
|
+
getAll(): Promise<{
|
|
23
|
+
name: string;
|
|
24
|
+
value: string;
|
|
25
|
+
}[] | null> | {
|
|
26
|
+
name: string;
|
|
27
|
+
value: string;
|
|
28
|
+
}[] | null;
|
|
29
|
+
deleteAll(cookies: {
|
|
30
|
+
name: string;
|
|
31
|
+
options?: CookieOptions;
|
|
32
|
+
}[]): Promise<void> | void;
|
|
33
|
+
}
|
|
34
|
+
//#endregion
|
|
35
|
+
export { AnyContext, AnyNestedClient, CookiesAdapter, HTTPMethod, List, MaybeOptionalOptions, RedirectInput, RedirectStatus };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import "zod/v4";
|
|
2
|
+
|
|
3
|
+
//#region src/shared/utils.ts
|
|
4
|
+
function getObjectProperty(object, path) {
|
|
5
|
+
let current = object;
|
|
6
|
+
for (const key of path) {
|
|
7
|
+
if (!isTypescriptObject(current)) return;
|
|
8
|
+
current = current[key];
|
|
9
|
+
}
|
|
10
|
+
return current;
|
|
11
|
+
}
|
|
12
|
+
function isTypescriptObject(value) {
|
|
13
|
+
return !!value && (typeof value === "object" || typeof value === "function");
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
//#endregion
|
|
17
|
+
export { getObjectProperty, isTypescriptObject };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//#region src/test/auth.ts
|
|
2
|
+
function testAuthAdapter(user) {
|
|
3
|
+
return { getUser() {
|
|
4
|
+
return {
|
|
5
|
+
id: user.wpUserId,
|
|
6
|
+
email: user.email,
|
|
7
|
+
phone: user.phone,
|
|
8
|
+
firstName: user.firstName,
|
|
9
|
+
lastName: user.lastName
|
|
10
|
+
};
|
|
11
|
+
} };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
//#endregion
|
|
15
|
+
export { testAuthAdapter };
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { CaptchaAdapter } from "../adapters/captcha.js";
|
|
2
|
+
|
|
3
|
+
//#region src/test/captcha.d.ts
|
|
4
|
+
declare const CAPTCHA_TEST_TOKEN_PASS = "test-token-pass";
|
|
5
|
+
declare function captchaMock(): CaptchaAdapter;
|
|
6
|
+
//#endregion
|
|
7
|
+
export { CAPTCHA_TEST_TOKEN_PASS, captchaMock };
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { AnyExtension } from "../shared/extension.js";
|
|
2
|
+
import { RootRouter } from "../kizlo.js";
|
|
3
|
+
import { KizloClient } from "../client.js";
|
|
4
|
+
import "../index.js";
|
|
5
|
+
import { KizloTestInstance } from "./server.js";
|
|
6
|
+
|
|
7
|
+
//#region src/test/client.d.ts
|
|
8
|
+
declare function getKizloClientTestInstance(kizlo: KizloTestInstance): Promise<KizloClient<RootRouter<readonly AnyExtension[]>>>;
|
|
9
|
+
type KizloClientTestInstance = Awaited<ReturnType<typeof getKizloClientTestInstance>>;
|
|
10
|
+
//#endregion
|
|
11
|
+
export { KizloClientTestInstance, getKizloClientTestInstance };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { generateContract } from "../shared/contract.js";
|
|
2
|
+
import { KizloClient } from "../client.js";
|
|
3
|
+
|
|
4
|
+
//#region src/test/client.ts
|
|
5
|
+
async function getKizloClientTestInstance(kizlo) {
|
|
6
|
+
return new KizloClient({
|
|
7
|
+
url: "http://test.local",
|
|
8
|
+
fetch: (req) => kizlo.handler(req),
|
|
9
|
+
contract: await generateContract(kizlo.router)
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
//#endregion
|
|
14
|
+
export { getKizloClientTestInstance };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Fixture } from "../cli/wp/types.js";
|
|
2
|
+
import { menuFixture } from "../menu/fixture.js";
|
|
3
|
+
import { postFixture } from "../post/fixture.js";
|
|
4
|
+
|
|
5
|
+
//#region src/test/fixtures.d.ts
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The kizlo core content fixtures (posts/comments + menu). Mount these in
|
|
9
|
+
* `kizlo.config.ts` so the toolkit's own suites have content to read; consumers
|
|
10
|
+
* who only need a clean WP stack can leave them out.
|
|
11
|
+
*/
|
|
12
|
+
declare const coreFixtures: Fixture[];
|
|
13
|
+
//#endregion
|
|
14
|
+
export { coreFixtures };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { menuFixture } from "../menu/fixture.js";
|
|
2
|
+
import { postFixture } from "../post/fixture.js";
|
|
3
|
+
|
|
4
|
+
//#region src/test/fixtures.ts
|
|
5
|
+
/**
|
|
6
|
+
* The kizlo core content fixtures (posts/comments + menu). Mount these in
|
|
7
|
+
* `kizlo.config.ts` so the toolkit's own suites have content to read; consumers
|
|
8
|
+
* who only need a clean WP stack can leave them out.
|
|
9
|
+
*/
|
|
10
|
+
const coreFixtures = [postFixture(), menuFixture()];
|
|
11
|
+
|
|
12
|
+
//#endregion
|
|
13
|
+
export { coreFixtures };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { AnyExtension } from "../shared/extension.js";
|
|
2
|
+
import { Kizlo } from "../kizlo.js";
|
|
3
|
+
|
|
4
|
+
//#region src/test/server.d.ts
|
|
5
|
+
declare function getKizloTestInstance<TExts extends readonly AnyExtension[] = []>(options?: {
|
|
6
|
+
extensions?: TExts;
|
|
7
|
+
}): Kizlo<TExts>;
|
|
8
|
+
type KizloTestInstance = ReturnType<typeof getKizloTestInstance>;
|
|
9
|
+
//#endregion
|
|
10
|
+
export { KizloTestInstance, getKizloTestInstance };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { geoMock } from "../adapters/geo.js";
|
|
2
|
+
import { consoleLog } from "../adapters/logger.js";
|
|
3
|
+
import { Kizlo } from "../kizlo.js";
|
|
4
|
+
import { getTestCredentials } from "../cli/wp/utils.js";
|
|
5
|
+
import { testAuthAdapter } from "./auth.js";
|
|
6
|
+
import { captchaMock } from "./captcha.js";
|
|
7
|
+
import { toTestUser } from "./users.js";
|
|
8
|
+
|
|
9
|
+
//#region src/test/server.ts
|
|
10
|
+
function getKizloTestInstance(options) {
|
|
11
|
+
const creds = getTestCredentials();
|
|
12
|
+
return new Kizlo({
|
|
13
|
+
baseUrl: "http://test.local",
|
|
14
|
+
siteSecret: "test-secret",
|
|
15
|
+
environment: "test",
|
|
16
|
+
credentials: {
|
|
17
|
+
url: creds.url,
|
|
18
|
+
username: creds.users.admin.username,
|
|
19
|
+
password: creds.users.admin.applicationPassword
|
|
20
|
+
},
|
|
21
|
+
adapters: {
|
|
22
|
+
geo: geoMock(),
|
|
23
|
+
auth: testAuthAdapter(toTestUser(creds.users.user)),
|
|
24
|
+
captcha: captchaMock(),
|
|
25
|
+
logger: consoleLog({ levels: ["warn", "error"] })
|
|
26
|
+
},
|
|
27
|
+
extensions: options?.extensions
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
//#endregion
|
|
32
|
+
export { getKizloTestInstance };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { TestCredentials } from "../cli/wp/types.js";
|
|
2
|
+
|
|
3
|
+
//#region src/test/users.d.ts
|
|
4
|
+
interface TestAuthAdapterUser {
|
|
5
|
+
wpUserId: number;
|
|
6
|
+
username: string;
|
|
7
|
+
firstName: string;
|
|
8
|
+
lastName: string;
|
|
9
|
+
email: string;
|
|
10
|
+
phone: string;
|
|
11
|
+
}
|
|
12
|
+
declare function toTestUser(user: TestCredentials["users"]["user"]): TestAuthAdapterUser;
|
|
13
|
+
//#endregion
|
|
14
|
+
export { TestAuthAdapterUser, toTestUser };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region src/test/users.ts
|
|
2
|
+
const STATIC_FIELDS = {
|
|
3
|
+
firstName: "Test",
|
|
4
|
+
lastName: "Customer",
|
|
5
|
+
email: "customer@example.com",
|
|
6
|
+
phone: "+10000000002"
|
|
7
|
+
};
|
|
8
|
+
function toTestUser(user) {
|
|
9
|
+
return {
|
|
10
|
+
wpUserId: user.id,
|
|
11
|
+
username: user.username,
|
|
12
|
+
...STATIC_FIELDS
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
//#endregion
|
|
17
|
+
export { toTestUser };
|
package/dist/test.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { compose, composeDown, composeStop, composeUp, wpCli } from "./cli/wp/docker.js";
|
|
2
|
+
import { Fixture, JsonValue, PluginSource, SeedContext, TestAdminUser, TestCredentials, TestUser, defineFixture } from "./cli/wp/types.js";
|
|
3
|
+
import { credentialsPath, ensurePlugin, findConfigDir, getTestCredentials, githubRelease, isSeeded, resolvePluginSource } from "./cli/wp/utils.js";
|
|
4
|
+
import { TestAuthAdapterUser, toTestUser } from "./test/users.js";
|
|
5
|
+
import { testAuthAdapter } from "./test/auth.js";
|
|
6
|
+
import { CAPTCHA_TEST_TOKEN_PASS, captchaMock } from "./test/captcha.js";
|
|
7
|
+
import { KizloTestInstance, getKizloTestInstance } from "./test/server.js";
|
|
8
|
+
import { KizloClientTestInstance, getKizloClientTestInstance } from "./test/client.js";
|
|
9
|
+
import { menuFixture } from "./menu/fixture.js";
|
|
10
|
+
import { postFixture } from "./post/fixture.js";
|
|
11
|
+
import { coreFixtures } from "./test/fixtures.js";
|
|
12
|
+
export { CAPTCHA_TEST_TOKEN_PASS, Fixture, JsonValue, KizloClientTestInstance, KizloTestInstance, PluginSource, SeedContext, TestAdminUser, TestAuthAdapterUser, TestCredentials, TestUser, captchaMock, compose, composeDown, composeStop, composeUp, coreFixtures, credentialsPath, defineFixture, ensurePlugin, findConfigDir, getKizloClientTestInstance, getKizloTestInstance, getTestCredentials, githubRelease, isSeeded, menuFixture, postFixture, resolvePluginSource, testAuthAdapter, toTestUser, wpCli };
|
package/dist/test.js
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { credentialsPath, ensurePlugin, findConfigDir, getTestCredentials, githubRelease, isSeeded, resolvePluginSource } from "./cli/wp/utils.js";
|
|
2
|
+
import { compose, composeDown, composeStop, composeUp, wpCli } from "./cli/wp/docker.js";
|
|
3
|
+
import { defineFixture } from "./cli/wp/types.js";
|
|
4
|
+
import { testAuthAdapter } from "./test/auth.js";
|
|
5
|
+
import { CAPTCHA_TEST_TOKEN_PASS, captchaMock } from "./test/captcha.js";
|
|
6
|
+
import { getKizloClientTestInstance } from "./test/client.js";
|
|
7
|
+
import { menuFixture } from "./menu/fixture.js";
|
|
8
|
+
import { postFixture } from "./post/fixture.js";
|
|
9
|
+
import { coreFixtures } from "./test/fixtures.js";
|
|
10
|
+
import { toTestUser } from "./test/users.js";
|
|
11
|
+
import { getKizloTestInstance } from "./test/server.js";
|
|
12
|
+
|
|
13
|
+
export { CAPTCHA_TEST_TOKEN_PASS, captchaMock, compose, composeDown, composeStop, composeUp, coreFixtures, credentialsPath, defineFixture, ensurePlugin, findConfigDir, getKizloClientTestInstance, getKizloTestInstance, getTestCredentials, githubRelease, isSeeded, menuFixture, postFixture, resolvePluginSource, testAuthAdapter, toTestUser, wpCli };
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { WebhookEvent } from "./schema.js";
|
|
2
|
+
import { DefinedErrorMapLike } from "../shared/error.js";
|
|
3
|
+
import { ServerContext } from "../context.js";
|
|
4
|
+
import { Procedure } from "../shared/procedure.js";
|
|
5
|
+
import "../index.js";
|
|
6
|
+
import { Pathname, Schema, SchemaOutput } from "@kizlo/shared";
|
|
7
|
+
|
|
8
|
+
//#region src/webhook/index.d.ts
|
|
9
|
+
type AnyWebhookEventSchema<TData = unknown> = Schema<unknown, TData>;
|
|
10
|
+
type AnyWebhookEvents = {
|
|
11
|
+
types: string[];
|
|
12
|
+
data: AnyWebhookEventSchema;
|
|
13
|
+
}[];
|
|
14
|
+
type InferWebhookEventUnion<T extends AnyWebhookEvents> = { [K in keyof T]: {
|
|
15
|
+
type: T[K]["types"][number];
|
|
16
|
+
data: SchemaOutput<T[K]["data"]>;
|
|
17
|
+
} }[number];
|
|
18
|
+
type WebhookHandlerFn<T extends AnyWebhookEvents> = (event: InferWebhookEventUnion<T> | WebhookEvent | null, context: ServerContext) => Promise<void> | void;
|
|
19
|
+
interface WebhookOptions {
|
|
20
|
+
path?: Pathname;
|
|
21
|
+
events?: EventHandler[];
|
|
22
|
+
}
|
|
23
|
+
interface EventHandler {
|
|
24
|
+
events?: AnyWebhookEvents;
|
|
25
|
+
handler: WebhookHandlerFn<AnyWebhookEvents>;
|
|
26
|
+
}
|
|
27
|
+
declare function createEventHandler<const T extends AnyWebhookEvents = never>(handler: WebhookHandlerFn<T>): EventHandler;
|
|
28
|
+
declare function createEventHandler<const T extends AnyWebhookEvents = never>(events: T, handler: WebhookHandlerFn<T>): EventHandler;
|
|
29
|
+
declare function createWebhookRouter(options?: WebhookOptions): {
|
|
30
|
+
webhooks: Procedure<"api", {
|
|
31
|
+
body: {
|
|
32
|
+
type: string;
|
|
33
|
+
data: unknown;
|
|
34
|
+
};
|
|
35
|
+
}, unknown, DefinedErrorMapLike>;
|
|
36
|
+
};
|
|
37
|
+
//#endregion
|
|
38
|
+
export { AnyWebhookEventSchema, AnyWebhookEvents, EventHandler, InferWebhookEventUnion, WebhookHandlerFn, WebhookOptions, createEventHandler, createWebhookRouter };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { KizloError } from "../shared/error.js";
|
|
2
|
+
import { createProcedure } from "../shared/procedure.js";
|
|
3
|
+
import { AnyWebhookEvent } from "./schema.js";
|
|
4
|
+
import { validateWebhookEvent } from "./utils.js";
|
|
5
|
+
import { tryCatchSync, verifyWebhook } from "@kizlo/shared";
|
|
6
|
+
import z from "zod";
|
|
7
|
+
|
|
8
|
+
//#region src/webhook/index.ts
|
|
9
|
+
function createEventHandler(eventsOrHandler, maybeHandler) {
|
|
10
|
+
const events = Array.isArray(eventsOrHandler) ? eventsOrHandler : [];
|
|
11
|
+
const handler = Array.isArray(eventsOrHandler) ? maybeHandler : eventsOrHandler;
|
|
12
|
+
if (!handler) throw new Error("Event handler not defined.");
|
|
13
|
+
return {
|
|
14
|
+
events,
|
|
15
|
+
handler
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function createWebhookRouter(options) {
|
|
19
|
+
return { webhooks: createProcedure({
|
|
20
|
+
scope: "api",
|
|
21
|
+
method: "POST",
|
|
22
|
+
body: AnyWebhookEvent,
|
|
23
|
+
path: options?.path ?? "/webhooks",
|
|
24
|
+
output: z.void()
|
|
25
|
+
}, async ({ context, input }) => {
|
|
26
|
+
const payload = await context.request?.text() ?? "";
|
|
27
|
+
const headers = Object.fromEntries(context.request?.headers.entries() ?? []);
|
|
28
|
+
const [err] = tryCatchSync(() => verifyWebhook({
|
|
29
|
+
secret: context.config.siteSecret,
|
|
30
|
+
payload,
|
|
31
|
+
headers
|
|
32
|
+
}));
|
|
33
|
+
if (err) throw new KizloError("FORBIDDEN", { message: "Signature verification failed." });
|
|
34
|
+
const results = await Promise.allSettled((options?.events ?? []).map(async ({ events, handler }) => {
|
|
35
|
+
const event = await validateWebhookEvent(events, input.body);
|
|
36
|
+
if (!event) return;
|
|
37
|
+
await handler(event, context);
|
|
38
|
+
}));
|
|
39
|
+
for (const result of results) if (result.status === "rejected") context.logger.error("Webhook handler failed", result.reason);
|
|
40
|
+
}) };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
//#endregion
|
|
44
|
+
export { createEventHandler, createWebhookRouter };
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import z from "zod/v4";
|
|
2
|
+
|
|
3
|
+
//#region src/webhook/schema.d.ts
|
|
4
|
+
|
|
5
|
+
declare const WebhookEvent: z.ZodUnion<readonly [z.ZodObject<{
|
|
6
|
+
type: z.ZodEnum<{
|
|
7
|
+
"post.created": "post.created";
|
|
8
|
+
"post.updated": "post.updated";
|
|
9
|
+
"post.trashed": "post.trashed";
|
|
10
|
+
"post.deleted": "post.deleted";
|
|
11
|
+
}>;
|
|
12
|
+
data: z.ZodObject<{
|
|
13
|
+
post_id: z.ZodNumber;
|
|
14
|
+
post_type: z.ZodString;
|
|
15
|
+
}, z.core.$strip>;
|
|
16
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
17
|
+
type: z.ZodEnum<{
|
|
18
|
+
"term.created": "term.created";
|
|
19
|
+
"term.updated": "term.updated";
|
|
20
|
+
"term.deleted": "term.deleted";
|
|
21
|
+
}>;
|
|
22
|
+
data: z.ZodObject<{
|
|
23
|
+
term_id: z.ZodNumber;
|
|
24
|
+
taxonomy: z.ZodString;
|
|
25
|
+
post_types: z.ZodArray<z.ZodString>;
|
|
26
|
+
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;
|
|
36
|
+
}, z.core.$strip>;
|
|
37
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
38
|
+
type: z.ZodEnum<{
|
|
39
|
+
"settings.saved": "settings.saved";
|
|
40
|
+
}>;
|
|
41
|
+
data: z.ZodNull;
|
|
42
|
+
}, z.core.$strip>]>;
|
|
43
|
+
type WebhookEvent = z.infer<typeof WebhookEvent>;
|
|
44
|
+
//#endregion
|
|
45
|
+
export { WebhookEvent };
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import z from "zod/v4";
|
|
2
|
+
|
|
3
|
+
//#region src/webhook/schema.ts
|
|
4
|
+
const TERM_WEBHOOK_EVENT_TYPES = [
|
|
5
|
+
"term.created",
|
|
6
|
+
"term.updated",
|
|
7
|
+
"term.deleted"
|
|
8
|
+
];
|
|
9
|
+
const TermWebhookEventType = z.enum(TERM_WEBHOOK_EVENT_TYPES);
|
|
10
|
+
const POST_WEBHOOK_EVENT_TYPES = [
|
|
11
|
+
"post.created",
|
|
12
|
+
"post.updated",
|
|
13
|
+
"post.trashed",
|
|
14
|
+
"post.deleted"
|
|
15
|
+
];
|
|
16
|
+
const PostWebhookEventType = z.enum(POST_WEBHOOK_EVENT_TYPES);
|
|
17
|
+
const PAYMENT_WEBHOOK_EVENT_TYPES = ["payment.status_requested"];
|
|
18
|
+
const PaymentWebhookEventType = z.enum(PAYMENT_WEBHOOK_EVENT_TYPES);
|
|
19
|
+
const SETTINGS_WEBHOOK_EVENT_TYPES = ["settings.saved"];
|
|
20
|
+
const SettingsWebhookEventType = z.enum(SETTINGS_WEBHOOK_EVENT_TYPES);
|
|
21
|
+
const WEBHOOK_EVENT_TYPES = [
|
|
22
|
+
...TERM_WEBHOOK_EVENT_TYPES,
|
|
23
|
+
...POST_WEBHOOK_EVENT_TYPES,
|
|
24
|
+
...PAYMENT_WEBHOOK_EVENT_TYPES,
|
|
25
|
+
...SETTINGS_WEBHOOK_EVENT_TYPES
|
|
26
|
+
];
|
|
27
|
+
const WebhookEventType = z.enum(WEBHOOK_EVENT_TYPES);
|
|
28
|
+
const PostWebhookEventData = z.object({
|
|
29
|
+
post_id: z.number(),
|
|
30
|
+
post_type: z.string()
|
|
31
|
+
});
|
|
32
|
+
const PostWebhookEvent = z.object({
|
|
33
|
+
type: PostWebhookEventType,
|
|
34
|
+
data: PostWebhookEventData
|
|
35
|
+
});
|
|
36
|
+
const TermWebhookEventData = z.object({
|
|
37
|
+
term_id: z.number(),
|
|
38
|
+
taxonomy: z.string(),
|
|
39
|
+
post_types: z.array(z.string()),
|
|
40
|
+
count: z.number().nonnegative()
|
|
41
|
+
});
|
|
42
|
+
const TermWebhookEvent = z.object({
|
|
43
|
+
type: TermWebhookEventType,
|
|
44
|
+
data: TermWebhookEventData
|
|
45
|
+
});
|
|
46
|
+
const PaymentWebhookEventData = z.object({
|
|
47
|
+
transaction_id: z.nullable(z.string()),
|
|
48
|
+
payment_method_id: z.string(),
|
|
49
|
+
payment_session_id: z.string()
|
|
50
|
+
});
|
|
51
|
+
const PaymentWebhookEvent = z.object({
|
|
52
|
+
type: PaymentWebhookEventType,
|
|
53
|
+
data: PaymentWebhookEventData
|
|
54
|
+
});
|
|
55
|
+
const SettingsWebhookEventData = z.null();
|
|
56
|
+
const SettingsWebhookEvent = z.object({
|
|
57
|
+
type: SettingsWebhookEventType,
|
|
58
|
+
data: SettingsWebhookEventData
|
|
59
|
+
});
|
|
60
|
+
const WebhookEvent = z.union([
|
|
61
|
+
PostWebhookEvent,
|
|
62
|
+
TermWebhookEvent,
|
|
63
|
+
PaymentWebhookEvent,
|
|
64
|
+
SettingsWebhookEvent
|
|
65
|
+
]);
|
|
66
|
+
const AnyWebhookEvent = z.object({
|
|
67
|
+
type: z.string(),
|
|
68
|
+
data: z.unknown()
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
//#endregion
|
|
72
|
+
export { AnyWebhookEvent, WebhookEvent };
|