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
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Kizlo
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<br>
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<a name="readme-top"></a>
|
|
5
|
+
<a href="https://kizlo.io">
|
|
6
|
+
<picture>
|
|
7
|
+
<source media="(prefers-color-scheme: dark)" srcset="https://cdn.kizlo.io/logo/icon-light.svg">
|
|
8
|
+
<source media="(prefers-color-scheme: light)" srcset="https://cdn.kizlo.io/logo/icon-dark.svg">
|
|
9
|
+
<img alt="Kizlo" src="https://cdn.kizlo.io/logo/icon-dark.svg" height="100">
|
|
10
|
+
</picture>
|
|
11
|
+
</a>
|
|
12
|
+
</p>
|
|
13
|
+
|
|
14
|
+
<h3 align="center">Headless WordPress Toolkit</h3>
|
|
15
|
+
|
|
16
|
+
<p align="center">
|
|
17
|
+
Your backend, your frontend — Kizlo handles the plumbing.
|
|
18
|
+
</p>
|
|
19
|
+
|
|
20
|
+
<p align="center">
|
|
21
|
+
<a href="https://www.npmjs.com/package/kizlo"><img src="https://img.shields.io/npm/v/kizlo?style=flat-square&color=333" alt="npm version"></a>
|
|
22
|
+
<a href="./LICENSE"><img src="https://img.shields.io/github/license/kizlo-io/kizlo?style=flat-square&color=333" alt="License"></a>
|
|
23
|
+
<a href="https://www.npmjs.com/package/kizlo"><img src="https://img.shields.io/npm/dt/kizlo?style=flat-square&color=333" alt="npm downloads"></a>
|
|
24
|
+
</p>
|
|
25
|
+
|
|
26
|
+
<p align="center">
|
|
27
|
+
<a href="https://kizlo.io"><strong>Website</strong></a> ·
|
|
28
|
+
<a href="https://kizlo.io/docs"><strong>Docs</strong></a> ·
|
|
29
|
+
<a href="https://discord.com/invite/MjAUZamx5g"><strong>Discord</strong></a> ·
|
|
30
|
+
<a href="https://x.com/kizlo_io"><strong>Twitter</strong></a>
|
|
31
|
+
</p>
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## What is Kizlo?
|
|
36
|
+
|
|
37
|
+
Kizlo is a framework-agnostic toolkit for headless WordPress, built for a stack you host and own from top to bottom. Use it to build websites, mobile apps, agentic applications, and more — Kizlo takes care of the plumbing so you can focus on the design.
|
|
38
|
+
|
|
39
|
+
## Quick start
|
|
40
|
+
|
|
41
|
+
Set up Kizlo in your project:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
npx kizlo init
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Watch your extensions and regenerate the contract during development:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
npx kizlo dev
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Generate the contract once for production builds:
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
npx kizlo generate
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
See the [docs](https://kizlo.io/docs) for the full guide.
|
|
60
|
+
|
|
61
|
+
## Contributing
|
|
62
|
+
|
|
63
|
+
Contributions are welcome — see [CONTRIBUTING.md](https://github.com/kizlo-io/kizlo/blob/main/CONTRIBUTING.md) for setup,
|
|
64
|
+
workflow, and PR guidelines.
|
|
65
|
+
|
|
66
|
+
## Security
|
|
67
|
+
|
|
68
|
+
If you discover a security vulnerability within Kizlo, please send an e-mail to security@kizlo.io.
|
|
69
|
+
|
|
70
|
+
All reports will be promptly addressed, and you'll be credited accordingly.
|
|
71
|
+
|
|
72
|
+
## Disclaimer
|
|
73
|
+
|
|
74
|
+
Kizlo is an independent project and is not endorsed by, sponsored by, or affiliated with the WordPress Foundation or WooCommerce, Inc. The WordPress® trademarks are the intellectual property of the WordPress Foundation, and the Woo® and WooCommerce® trademarks are the intellectual property of WooCommerce, Inc. Uses of the WordPress®, Woo®, and WooCommerce® names in this organization are for identification purposes only and do not imply endorsement.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Promisify } from "@kizlo/shared";
|
|
2
|
+
|
|
3
|
+
//#region src/adapters/auth.d.ts
|
|
4
|
+
interface AuthUser {
|
|
5
|
+
id: number;
|
|
6
|
+
email?: string;
|
|
7
|
+
phone?: string;
|
|
8
|
+
firstName: string;
|
|
9
|
+
lastName: string;
|
|
10
|
+
}
|
|
11
|
+
interface AuthAdapter {
|
|
12
|
+
getUser(request: Request | null): Promisify<AuthUser | null>;
|
|
13
|
+
}
|
|
14
|
+
declare function authMock(options?: {
|
|
15
|
+
mockUserId?: number;
|
|
16
|
+
}): AuthAdapter;
|
|
17
|
+
//#endregion
|
|
18
|
+
export { AuthAdapter, AuthUser, authMock };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
//#region src/adapters/auth.ts
|
|
2
|
+
function authMock(options) {
|
|
3
|
+
return { getUser() {
|
|
4
|
+
return {
|
|
5
|
+
id: options?.mockUserId ?? 0,
|
|
6
|
+
firstName: "Karan",
|
|
7
|
+
lastName: "Gill",
|
|
8
|
+
email: "karan@gmail.con",
|
|
9
|
+
phone: "12345678901"
|
|
10
|
+
};
|
|
11
|
+
} };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
//#endregion
|
|
15
|
+
export { authMock };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
//#region src/adapters/captcha.d.ts
|
|
2
|
+
type CaptchaAdapter = (input: {
|
|
3
|
+
token: string;
|
|
4
|
+
ip: string;
|
|
5
|
+
}) => Promise<boolean>;
|
|
6
|
+
declare function recaptcha(opts: {
|
|
7
|
+
secret: string;
|
|
8
|
+
minScore?: number;
|
|
9
|
+
}): CaptchaAdapter;
|
|
10
|
+
declare function turnstile(opts: {
|
|
11
|
+
secret: string;
|
|
12
|
+
}): CaptchaAdapter;
|
|
13
|
+
declare function hcaptcha(opts: {
|
|
14
|
+
secret: string;
|
|
15
|
+
sitekey?: string;
|
|
16
|
+
}): CaptchaAdapter;
|
|
17
|
+
declare function friendlyCaptcha(opts: {
|
|
18
|
+
secret: string;
|
|
19
|
+
sitekey?: string;
|
|
20
|
+
}): CaptchaAdapter;
|
|
21
|
+
declare function arkose(opts: {
|
|
22
|
+
privateKey: string;
|
|
23
|
+
}): CaptchaAdapter;
|
|
24
|
+
declare function altcha(opts: {
|
|
25
|
+
hmacKey: string;
|
|
26
|
+
}): CaptchaAdapter;
|
|
27
|
+
//#endregion
|
|
28
|
+
export { CaptchaAdapter, altcha, arkose, friendlyCaptcha, hcaptcha, recaptcha, turnstile };
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
//#region src/adapters/captcha.ts
|
|
2
|
+
function recaptcha(opts) {
|
|
3
|
+
return async ({ token, ip }) => {
|
|
4
|
+
const data = await (await fetch("https://www.google.com/recaptcha/api/siteverify", {
|
|
5
|
+
method: "POST",
|
|
6
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
7
|
+
body: new URLSearchParams({
|
|
8
|
+
secret: opts.secret,
|
|
9
|
+
response: token,
|
|
10
|
+
...ip && { remoteip: ip }
|
|
11
|
+
})
|
|
12
|
+
})).json();
|
|
13
|
+
if (!data.success) return false;
|
|
14
|
+
if (opts.minScore !== void 0 && data.score !== void 0) return data.score >= opts.minScore;
|
|
15
|
+
return true;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function turnstile(opts) {
|
|
19
|
+
return async ({ token, ip }) => {
|
|
20
|
+
return (await (await fetch("https://challenges.cloudflare.com/turnstile/v0/siteverify", {
|
|
21
|
+
method: "POST",
|
|
22
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
23
|
+
body: new URLSearchParams({
|
|
24
|
+
secret: opts.secret,
|
|
25
|
+
response: token,
|
|
26
|
+
...ip && { remoteip: ip }
|
|
27
|
+
})
|
|
28
|
+
})).json()).success === true;
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
function hcaptcha(opts) {
|
|
32
|
+
return async ({ token, ip }) => {
|
|
33
|
+
return (await (await fetch("https://api.hcaptcha.com/siteverify", {
|
|
34
|
+
method: "POST",
|
|
35
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
36
|
+
body: new URLSearchParams({
|
|
37
|
+
secret: opts.secret,
|
|
38
|
+
response: token,
|
|
39
|
+
...ip && { remoteip: ip },
|
|
40
|
+
...opts.sitekey && { sitekey: opts.sitekey }
|
|
41
|
+
})
|
|
42
|
+
})).json()).success === true;
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
function friendlyCaptcha(opts) {
|
|
46
|
+
return async ({ token }) => {
|
|
47
|
+
return (await (await fetch("https://api.friendlycaptcha.com/api/v1/siteverify", {
|
|
48
|
+
method: "POST",
|
|
49
|
+
headers: { "Content-Type": "application/json" },
|
|
50
|
+
body: JSON.stringify({
|
|
51
|
+
solution: token,
|
|
52
|
+
secret: opts.secret,
|
|
53
|
+
...opts.sitekey && { sitekey: opts.sitekey }
|
|
54
|
+
})
|
|
55
|
+
})).json()).success === true;
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
function arkose(opts) {
|
|
59
|
+
return async ({ token, ip }) => {
|
|
60
|
+
return (await (await fetch("https://verify-api.arkoselabs.com/api/v4/verify/", {
|
|
61
|
+
method: "POST",
|
|
62
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
63
|
+
body: new URLSearchParams({
|
|
64
|
+
private_key: opts.privateKey,
|
|
65
|
+
session_token: token,
|
|
66
|
+
...ip && { log_data: ip }
|
|
67
|
+
})
|
|
68
|
+
})).json()).session_details?.solved === true;
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
function altcha(opts) {
|
|
72
|
+
return async ({ token }) => {
|
|
73
|
+
try {
|
|
74
|
+
const payload = JSON.parse(Buffer.from(token, "base64").toString("utf-8"));
|
|
75
|
+
const { createHmac, createHash } = await import("node:crypto");
|
|
76
|
+
const algo = payload.algorithm.toLowerCase().replace("-", "");
|
|
77
|
+
if (createHash(algo).update(`${payload.salt}${payload.number}`).digest("hex") !== payload.challenge) return false;
|
|
78
|
+
return createHmac(algo, opts.hmacKey).update(payload.challenge).digest("hex") === payload.signature;
|
|
79
|
+
} catch {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
//#endregion
|
|
86
|
+
export { altcha, arkose, friendlyCaptcha, hcaptcha, recaptcha, turnstile };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Promisify } from "@kizlo/shared";
|
|
2
|
+
|
|
3
|
+
//#region src/adapters/geo.d.ts
|
|
4
|
+
interface ConnInfo {
|
|
5
|
+
ip: string | null;
|
|
6
|
+
country: string | null;
|
|
7
|
+
city: string | null;
|
|
8
|
+
state: string | null;
|
|
9
|
+
postcode: string | null;
|
|
10
|
+
timezone: string | null;
|
|
11
|
+
userAgent: string | null;
|
|
12
|
+
}
|
|
13
|
+
interface GeoAdapter {
|
|
14
|
+
getConnInfo(request: Request | null): Promisify<ConnInfo>;
|
|
15
|
+
}
|
|
16
|
+
declare function geoMock(values?: Partial<ConnInfo>): GeoAdapter;
|
|
17
|
+
//#endregion
|
|
18
|
+
export { ConnInfo, GeoAdapter, geoMock };
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
//#region src/adapters/geo.ts
|
|
2
|
+
function geoMock(values) {
|
|
3
|
+
return { getConnInfo(request) {
|
|
4
|
+
return {
|
|
5
|
+
ip: "49.205.46.133",
|
|
6
|
+
city: "DL",
|
|
7
|
+
state: "HR",
|
|
8
|
+
country: "IN",
|
|
9
|
+
postcode: "110058",
|
|
10
|
+
userAgent: request?.headers.get("User-Agent") ?? null,
|
|
11
|
+
timezone: null,
|
|
12
|
+
...values
|
|
13
|
+
};
|
|
14
|
+
} };
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
//#endregion
|
|
18
|
+
export { geoMock };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
//#region src/adapters/geo.vercel.ts
|
|
2
|
+
function geoVercelNext() {
|
|
3
|
+
return { getConnInfo: async (request) => {
|
|
4
|
+
if (request) return readVercelHeaders(request.headers);
|
|
5
|
+
let nextHeaders;
|
|
6
|
+
try {
|
|
7
|
+
nextHeaders = await (await import("next/headers")).headers();
|
|
8
|
+
} catch (err) {
|
|
9
|
+
throw new Error("geoVercelNext: no Request was provided and `next/headers` could not be loaded. Install `next` as a peer dependency, or pass a Request to the SDK.", { cause: err });
|
|
10
|
+
}
|
|
11
|
+
return readVercelHeaders(nextHeaders);
|
|
12
|
+
} };
|
|
13
|
+
}
|
|
14
|
+
function readVercelHeaders(headers) {
|
|
15
|
+
const xRealIp = headers.get("x-real-ip");
|
|
16
|
+
const xff = headers.get("x-forwarded-for");
|
|
17
|
+
const ip = xRealIp || xff?.split(",")[0]?.trim() || null;
|
|
18
|
+
const country = headers.get("x-vercel-ip-country") || null;
|
|
19
|
+
const cityRaw = headers.get("x-vercel-ip-city");
|
|
20
|
+
const tzRaw = headers.get("x-vercel-ip-timezone");
|
|
21
|
+
const userAgent = headers.get("User-Agent");
|
|
22
|
+
return {
|
|
23
|
+
ip,
|
|
24
|
+
country,
|
|
25
|
+
city: cityRaw ? safeDecode(cityRaw) : null,
|
|
26
|
+
timezone: tzRaw ? safeDecode(tzRaw) : null,
|
|
27
|
+
postcode: null,
|
|
28
|
+
state: null,
|
|
29
|
+
userAgent
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
function safeDecode(value) {
|
|
33
|
+
try {
|
|
34
|
+
return decodeURIComponent(value);
|
|
35
|
+
} catch {
|
|
36
|
+
return value || null;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
//#endregion
|
|
41
|
+
export { geoVercelNext };
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { LiteralUnion } from "@kizlo/shared";
|
|
2
|
+
|
|
3
|
+
//#region src/adapters/logger.d.ts
|
|
4
|
+
type LogLevel = "debug" | "info" | "warn" | "error";
|
|
5
|
+
type Environment = LiteralUnion<"development" | "production" | "test", string>;
|
|
6
|
+
interface LogPayload {
|
|
7
|
+
level: LogLevel;
|
|
8
|
+
message: string;
|
|
9
|
+
timestamp: Date;
|
|
10
|
+
context?: Record<string, unknown>;
|
|
11
|
+
error?: Error;
|
|
12
|
+
}
|
|
13
|
+
type LoggerAdapter = (payload: LogPayload) => void | Promise<void>;
|
|
14
|
+
interface Logger {
|
|
15
|
+
debug(message: string, context?: Record<string, unknown>): void;
|
|
16
|
+
info(message: string, context?: Record<string, unknown>): void;
|
|
17
|
+
warn(message: string, context?: Record<string, unknown>): void;
|
|
18
|
+
error(message: string, error?: Error, context?: Record<string, unknown>): void;
|
|
19
|
+
child(context: Record<string, unknown>): Logger;
|
|
20
|
+
}
|
|
21
|
+
interface ConsoleLogAdapterOptions {
|
|
22
|
+
/**
|
|
23
|
+
* Which levels to log. `true` means all, an array means only those.
|
|
24
|
+
* Default: all levels.
|
|
25
|
+
*/
|
|
26
|
+
levels?: boolean | LogLevel[];
|
|
27
|
+
}
|
|
28
|
+
declare function consoleLog(opts?: ConsoleLogAdapterOptions): LoggerAdapter;
|
|
29
|
+
declare const noopAdapter: LoggerAdapter;
|
|
30
|
+
//#endregion
|
|
31
|
+
export { ConsoleLogAdapterOptions, Environment, LogLevel, LogPayload, Logger, LoggerAdapter, consoleLog, noopAdapter };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//#region src/adapters/logger.ts
|
|
2
|
+
function consoleLog(opts = {}) {
|
|
3
|
+
const levelsOpt = opts.levels ?? true;
|
|
4
|
+
const allowed = levelsOpt === true ? null : new Set(levelsOpt === false ? [] : levelsOpt);
|
|
5
|
+
return (payload) => {
|
|
6
|
+
if (allowed && !allowed.has(payload.level)) return;
|
|
7
|
+
const { level, message, timestamp, context, error } = payload;
|
|
8
|
+
const args = [`[${timestamp.toISOString()}] [${level.toUpperCase()}]`, message];
|
|
9
|
+
if (context) args.push(context);
|
|
10
|
+
if (error) args.push(error);
|
|
11
|
+
switch (level) {
|
|
12
|
+
case "debug":
|
|
13
|
+
console.debug(...args);
|
|
14
|
+
break;
|
|
15
|
+
case "info":
|
|
16
|
+
console.info(...args);
|
|
17
|
+
break;
|
|
18
|
+
case "warn":
|
|
19
|
+
console.warn(...args);
|
|
20
|
+
break;
|
|
21
|
+
case "error":
|
|
22
|
+
console.error(...args);
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
const noopAdapter = () => {};
|
|
28
|
+
|
|
29
|
+
//#endregion
|
|
30
|
+
export { consoleLog, noopAdapter };
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
//#region src/cli/banner.ts
|
|
2
|
+
const KIZLO_CLI_WORD_MARK = [
|
|
3
|
+
"██╗ ██╗██╗███████╗██╗ ██████╗ ",
|
|
4
|
+
"██║ ██╔╝██║╚══███╔╝██║ ██╔═══██╗",
|
|
5
|
+
"█████╔╝ ██║ ███╔╝ ██║ ██║ ██║",
|
|
6
|
+
"██╔═██╗ ██║ ███╔╝ ██║ ██║ ██║",
|
|
7
|
+
"██║ ██╗██║███████╗███████╗╚██████╔╝",
|
|
8
|
+
"╚═╝ ╚═╝╚═╝╚══════╝╚══════╝ ╚═════╝ "
|
|
9
|
+
];
|
|
10
|
+
const KIZLO_TAGLINE = "Headless WordPress toolkit for TypeScript";
|
|
11
|
+
function colorSupported() {
|
|
12
|
+
return Boolean(process.stdout.isTTY) && process.env.NO_COLOR === void 0 && process.env.TERM !== "dumb";
|
|
13
|
+
}
|
|
14
|
+
function printBanner(version) {
|
|
15
|
+
const color = colorSupported();
|
|
16
|
+
const cyan = color ? "\x1B[38;5;44m" : "";
|
|
17
|
+
const bold = color ? "\x1B[1m" : "";
|
|
18
|
+
const dim = color ? "\x1B[2m" : "";
|
|
19
|
+
const reset = color ? "\x1B[0m" : "";
|
|
20
|
+
const art = KIZLO_CLI_WORD_MARK.map((line) => `${cyan}${line}${reset}`).join("\n");
|
|
21
|
+
process.stdout.write(`\n${art}\n\n`);
|
|
22
|
+
process.stdout.write(`${dim}${KIZLO_TAGLINE}${reset} ${bold}v${version}${reset}\n\n`);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
//#endregion
|
|
26
|
+
export { printBanner };
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { log } from "../daemon/logger.js";
|
|
2
|
+
import { resolveConfig } from "../daemon/config.js";
|
|
3
|
+
import { generateOnce } from "../daemon/generate.js";
|
|
4
|
+
import { defineCommand } from "citty";
|
|
5
|
+
|
|
6
|
+
//#region src/cli/commands/generate.ts
|
|
7
|
+
const generate = defineCommand({
|
|
8
|
+
meta: {
|
|
9
|
+
name: "generate",
|
|
10
|
+
description: "Generate the Kizlo contract once (for builds and CI)"
|
|
11
|
+
},
|
|
12
|
+
args: { dir: {
|
|
13
|
+
type: "string",
|
|
14
|
+
description: "Override the Kizlo directory (defaults to kizlo.config.ts)"
|
|
15
|
+
} },
|
|
16
|
+
async run({ args }) {
|
|
17
|
+
const cfg = await resolveConfig(process.cwd(), { dir: args.dir });
|
|
18
|
+
let ok;
|
|
19
|
+
try {
|
|
20
|
+
ok = await generateOnce(cfg);
|
|
21
|
+
} catch (error) {
|
|
22
|
+
log.error("Failed to generate the Kizlo contract:", error);
|
|
23
|
+
process.exit(1);
|
|
24
|
+
}
|
|
25
|
+
if (!ok) {
|
|
26
|
+
log.error(`No Kizlo server found in ${cfg.serverEntry}`);
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
log.success("Contract generated");
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
//#endregion
|
|
34
|
+
export { generate };
|