@lazrus/nukle 0.0.0-stage → 0.2.1
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/README.md +92 -2
- package/dist/index.d.ts +108 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +155 -0
- package/package.json +30 -3
package/README.md
CHANGED
|
@@ -1,3 +1,93 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @lazrus/nukle
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
The official TypeScript client for Nukle. Read website content, access media
|
|
4
|
+
metadata, manage input-form schemas from your server, and accept browser-safe
|
|
5
|
+
form submissions.
|
|
6
|
+
|
|
7
|
+
[Documentation](https://docs.nukle.in) · [API reference](https://docs.nukle.in)
|
|
8
|
+
|
|
9
|
+
## Install
|
|
10
|
+
|
|
11
|
+
```sh
|
|
12
|
+
npm install @lazrus/nukle
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
pnpm add @lazrus/nukle
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Quick start
|
|
20
|
+
|
|
21
|
+
Create a website-scoped API key in Nukle Studio, then use it only on your
|
|
22
|
+
server. Never expose a `nukle_live_...` key in browser code.
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
import { createNukleClient } from "@lazrus/nukle";
|
|
26
|
+
|
|
27
|
+
const nukle = createNukleClient({ apiKey: process.env.NUKLE_API_KEY! });
|
|
28
|
+
|
|
29
|
+
const hero = await nukle.getSingleton<{ title: string; subtitle: string }>(
|
|
30
|
+
"hero",
|
|
31
|
+
);
|
|
32
|
+
const cards = await nukle.getRepeatable<{ title: string }>("cards");
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
The client uses `https://api.nukle.in` by default. For local development,
|
|
36
|
+
provide your Core origin without `/v1`:
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
const nukle = createNukleClient({
|
|
40
|
+
apiKey: process.env.NUKLE_API_KEY!,
|
|
41
|
+
baseUrl: "http://localhost:3001",
|
|
42
|
+
});
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## What you can do
|
|
46
|
+
|
|
47
|
+
- Read all modules, a single module, singleton content, or repeatable content.
|
|
48
|
+
- List media, retrieve media metadata, and download authenticated media bytes.
|
|
49
|
+
- Create, inspect, activate, deactivate, and rotate public credentials for
|
|
50
|
+
input forms from server-only code.
|
|
51
|
+
- Submit a public form from a browser using its restricted `nukle_form_...`
|
|
52
|
+
credential.
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
import { createNukleFormClient } from "@lazrus/nukle";
|
|
56
|
+
|
|
57
|
+
const contact = createNukleFormClient({
|
|
58
|
+
formKey: "nukle_form_REPLACE_ME",
|
|
59
|
+
});
|
|
60
|
+
|
|
61
|
+
await contact.submit({
|
|
62
|
+
email: "reader@example.com",
|
|
63
|
+
message: "Hello from our website",
|
|
64
|
+
});
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
The form credential is safe for browser code. It cannot access website
|
|
68
|
+
content, media, or form-management operations. Configure the form's allowed
|
|
69
|
+
origins in Nukle before accepting browser submissions.
|
|
70
|
+
|
|
71
|
+
## Errors
|
|
72
|
+
|
|
73
|
+
API failures are thrown as `NukleApiError`, with an HTTP `status`, stable
|
|
74
|
+
`code`, and optional `details` field.
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
import { NukleApiError } from "@lazrus/nukle";
|
|
78
|
+
|
|
79
|
+
try {
|
|
80
|
+
await nukle.getModule("hero");
|
|
81
|
+
} catch (error) {
|
|
82
|
+
if (error instanceof NukleApiError) {
|
|
83
|
+
console.error(error.status, error.code, error.message);
|
|
84
|
+
} else {
|
|
85
|
+
throw error;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Documentation
|
|
91
|
+
|
|
92
|
+
Visit [docs.nukle.in](https://docs.nukle.in) for the complete API reference,
|
|
93
|
+
form-management guide, local-development setup, and runnable examples.
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
export type ContentEntry<T = Record<string, unknown>> = {
|
|
2
|
+
id: string;
|
|
3
|
+
data: T;
|
|
4
|
+
position: number;
|
|
5
|
+
createdAt: string;
|
|
6
|
+
updatedAt: string;
|
|
7
|
+
};
|
|
8
|
+
export type PublicModule<T = Record<string, unknown>> = {
|
|
9
|
+
key: string;
|
|
10
|
+
name: string;
|
|
11
|
+
kind: "singleton" | "repeatable";
|
|
12
|
+
position: number;
|
|
13
|
+
entries: ContentEntry<T>[];
|
|
14
|
+
};
|
|
15
|
+
export type PublicMedia = {
|
|
16
|
+
id: string;
|
|
17
|
+
websiteId: string | null;
|
|
18
|
+
originalName: string;
|
|
19
|
+
mimeType: string;
|
|
20
|
+
sizeBytes: number;
|
|
21
|
+
altText: string | null;
|
|
22
|
+
url: string;
|
|
23
|
+
createdAt: string;
|
|
24
|
+
updatedAt: string;
|
|
25
|
+
};
|
|
26
|
+
export type NukleClientOptions = {
|
|
27
|
+
apiKey: string;
|
|
28
|
+
baseUrl?: string;
|
|
29
|
+
fetch?: typeof globalThis.fetch;
|
|
30
|
+
};
|
|
31
|
+
export declare class NukleApiError extends Error {
|
|
32
|
+
readonly status: number;
|
|
33
|
+
readonly code: string;
|
|
34
|
+
readonly details?: unknown | undefined;
|
|
35
|
+
constructor(status: number, code: string, message: string, details?: unknown | undefined);
|
|
36
|
+
}
|
|
37
|
+
export declare function createNukleClient(options: NukleClientOptions): {
|
|
38
|
+
getModules: () => Promise<PublicModule<Record<string, unknown>>[]>;
|
|
39
|
+
getModule: <T = Record<string, unknown>>(moduleKey: string) => Promise<PublicModule<T>>;
|
|
40
|
+
getSingleton<T = Record<string, unknown>>(moduleKey: string): Promise<NonNullable<T> | null>;
|
|
41
|
+
getRepeatable<T = Record<string, unknown>>(moduleKey: string): Promise<T[]>;
|
|
42
|
+
listMedia: () => Promise<PublicMedia[]>;
|
|
43
|
+
getMedia: (mediaId: string) => Promise<PublicMedia>;
|
|
44
|
+
getMediaFile: (mediaId: string) => Promise<ArrayBuffer>;
|
|
45
|
+
};
|
|
46
|
+
export type NukleClient = ReturnType<typeof createNukleClient>;
|
|
47
|
+
export type InputFormField = {
|
|
48
|
+
key: string;
|
|
49
|
+
label: string;
|
|
50
|
+
type: "text" | "email" | "tel" | "textarea" | "checkbox" | "select";
|
|
51
|
+
required?: boolean;
|
|
52
|
+
maxLength?: number;
|
|
53
|
+
options?: string[];
|
|
54
|
+
};
|
|
55
|
+
export type InputFormSchema = {
|
|
56
|
+
name: string;
|
|
57
|
+
allowedOrigins: string[];
|
|
58
|
+
fields: InputFormField[];
|
|
59
|
+
};
|
|
60
|
+
export type InputForm = InputFormSchema & {
|
|
61
|
+
id: string;
|
|
62
|
+
websiteId: string;
|
|
63
|
+
key: string;
|
|
64
|
+
schemaVersion: number;
|
|
65
|
+
active: boolean;
|
|
66
|
+
createdAt: string;
|
|
67
|
+
updatedAt: string;
|
|
68
|
+
};
|
|
69
|
+
export type InputFormWithPublicKey = InputForm & {
|
|
70
|
+
publicKey: string;
|
|
71
|
+
};
|
|
72
|
+
export type InputFormUpsertResult = InputForm & {
|
|
73
|
+
publicKey?: string;
|
|
74
|
+
};
|
|
75
|
+
export type NukleFormManagementClientOptions = {
|
|
76
|
+
apiKey: string;
|
|
77
|
+
websiteId: string;
|
|
78
|
+
baseUrl?: string;
|
|
79
|
+
fetch?: typeof globalThis.fetch;
|
|
80
|
+
};
|
|
81
|
+
export type NukleFormClientOptions = {
|
|
82
|
+
formKey: string;
|
|
83
|
+
baseUrl?: string;
|
|
84
|
+
fetch?: typeof globalThis.fetch;
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* Manages a single website's input-form schemas. Keep this client and its
|
|
88
|
+
* `nukle_live_...` API key in server-only code.
|
|
89
|
+
*/
|
|
90
|
+
export declare function createNukleFormManagementClient(options: NukleFormManagementClientOptions): {
|
|
91
|
+
upsert: (formKey: string, schema: InputFormSchema) => Promise<InputFormUpsertResult>;
|
|
92
|
+
get: (formKey: string) => Promise<InputForm>;
|
|
93
|
+
rotatePublicKey: (formKey: string) => Promise<InputFormWithPublicKey>;
|
|
94
|
+
setActive: (formKey: string, active: boolean) => Promise<InputForm>;
|
|
95
|
+
};
|
|
96
|
+
/**
|
|
97
|
+
* Submits data to exactly one public input form. It is safe to use in browser
|
|
98
|
+
* code because a `nukle_form_...` key cannot read content or manage schemas.
|
|
99
|
+
*/
|
|
100
|
+
export declare function createNukleFormClient(options: NukleFormClientOptions): {
|
|
101
|
+
submit(data: Record<string, unknown>): Promise<{
|
|
102
|
+
ok: boolean;
|
|
103
|
+
submissionId?: string;
|
|
104
|
+
}>;
|
|
105
|
+
};
|
|
106
|
+
export type NukleFormManagementClient = ReturnType<typeof createNukleFormManagementClient>;
|
|
107
|
+
export type NukleFormClient = ReturnType<typeof createNukleFormClient>;
|
|
108
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
export class NukleApiError extends Error {
|
|
2
|
+
status;
|
|
3
|
+
code;
|
|
4
|
+
details;
|
|
5
|
+
constructor(status, code, message, details) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.status = status;
|
|
8
|
+
this.code = code;
|
|
9
|
+
this.details = details;
|
|
10
|
+
this.name = "NukleApiError";
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
const DEFAULT_BASE_URL = "https://api.nukle.in";
|
|
14
|
+
function normalizeBaseUrl(baseUrl) {
|
|
15
|
+
return baseUrl.replace(/\/+$/, "");
|
|
16
|
+
}
|
|
17
|
+
export function createNukleClient(options) {
|
|
18
|
+
if (!options.apiKey.trim())
|
|
19
|
+
throw new Error("Nukle API key is required.");
|
|
20
|
+
const baseUrl = normalizeBaseUrl(options.baseUrl ?? DEFAULT_BASE_URL);
|
|
21
|
+
const requestFetch = options.fetch ?? globalThis.fetch;
|
|
22
|
+
if (!requestFetch)
|
|
23
|
+
throw new Error("A fetch implementation is required.");
|
|
24
|
+
async function request(path, init) {
|
|
25
|
+
const response = await requestFetch(`${baseUrl}/v1${path}`, {
|
|
26
|
+
...init,
|
|
27
|
+
headers: {
|
|
28
|
+
Accept: "application/json",
|
|
29
|
+
...init?.headers,
|
|
30
|
+
"x-nukle-api-key": options.apiKey,
|
|
31
|
+
},
|
|
32
|
+
});
|
|
33
|
+
if (!response.ok) {
|
|
34
|
+
let payload = {};
|
|
35
|
+
try {
|
|
36
|
+
payload = (await response.json());
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
// Preserve the HTTP status when the server returns a non-JSON error.
|
|
40
|
+
}
|
|
41
|
+
throw new NukleApiError(response.status, payload.error?.code ?? "NUKLE_REQUEST_FAILED", payload.error?.message ?? `Nukle request failed (${response.status}).`, payload.error?.details);
|
|
42
|
+
}
|
|
43
|
+
return (await response.json());
|
|
44
|
+
}
|
|
45
|
+
async function getModule(moduleKey) {
|
|
46
|
+
return request(`/public/modules/${encodeURIComponent(moduleKey)}`);
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
getModules: () => request("/public/modules"),
|
|
50
|
+
getModule,
|
|
51
|
+
async getSingleton(moduleKey) {
|
|
52
|
+
const module = await getModule(moduleKey);
|
|
53
|
+
return module.entries[0]?.data ?? null;
|
|
54
|
+
},
|
|
55
|
+
async getRepeatable(moduleKey) {
|
|
56
|
+
const module = await getModule(moduleKey);
|
|
57
|
+
return module.entries.map((entry) => entry.data);
|
|
58
|
+
},
|
|
59
|
+
listMedia: () => request("/public/media"),
|
|
60
|
+
getMedia: (mediaId) => request(`/public/media/${encodeURIComponent(mediaId)}`),
|
|
61
|
+
getMediaFile: async (mediaId) => {
|
|
62
|
+
const response = await requestFetch(`${baseUrl}/v1/public/media/${encodeURIComponent(mediaId)}/file`, {
|
|
63
|
+
headers: { "x-nukle-api-key": options.apiKey },
|
|
64
|
+
});
|
|
65
|
+
if (!response.ok) {
|
|
66
|
+
let payload = {};
|
|
67
|
+
try {
|
|
68
|
+
payload = (await response.json());
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
// Preserve the HTTP status when the server returns a non-JSON error.
|
|
72
|
+
}
|
|
73
|
+
throw new NukleApiError(response.status, payload.error?.code ?? "NUKLE_REQUEST_FAILED", payload.error?.message ??
|
|
74
|
+
`Nukle request failed (${response.status}).`, payload.error?.details);
|
|
75
|
+
}
|
|
76
|
+
return response.arrayBuffer();
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
function createJsonRequest(baseUrl, requestFetch, path, init) {
|
|
81
|
+
return requestFetch(`${baseUrl}/v1${path}`, {
|
|
82
|
+
...init,
|
|
83
|
+
headers: {
|
|
84
|
+
Accept: "application/json",
|
|
85
|
+
"Content-Type": "application/json",
|
|
86
|
+
...init.headers,
|
|
87
|
+
},
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
async function readJson(response) {
|
|
91
|
+
if (response.ok)
|
|
92
|
+
return (await response.json());
|
|
93
|
+
let payload = {};
|
|
94
|
+
try {
|
|
95
|
+
payload = (await response.json());
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
// Preserve the HTTP status when the server returns a non-JSON error.
|
|
99
|
+
}
|
|
100
|
+
throw new NukleApiError(response.status, payload.error?.code ?? "NUKLE_REQUEST_FAILED", payload.error?.message ?? `Nukle request failed (${response.status}).`, payload.error?.details);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Manages a single website's input-form schemas. Keep this client and its
|
|
104
|
+
* `nukle_live_...` API key in server-only code.
|
|
105
|
+
*/
|
|
106
|
+
export function createNukleFormManagementClient(options) {
|
|
107
|
+
if (!options.apiKey.trim())
|
|
108
|
+
throw new Error("Nukle API key is required.");
|
|
109
|
+
if (!options.websiteId.trim())
|
|
110
|
+
throw new Error("Nukle website ID is required.");
|
|
111
|
+
const baseUrl = normalizeBaseUrl(options.baseUrl ?? DEFAULT_BASE_URL);
|
|
112
|
+
const requestFetch = options.fetch ?? globalThis.fetch;
|
|
113
|
+
if (!requestFetch)
|
|
114
|
+
throw new Error("A fetch implementation is required.");
|
|
115
|
+
const formsPath = `/websites/${encodeURIComponent(options.websiteId)}/forms`;
|
|
116
|
+
function request(path, init) {
|
|
117
|
+
return createJsonRequest(baseUrl, requestFetch, path, {
|
|
118
|
+
...init,
|
|
119
|
+
headers: { ...init.headers, "x-nukle-api-key": options.apiKey },
|
|
120
|
+
}).then((readJson));
|
|
121
|
+
}
|
|
122
|
+
return {
|
|
123
|
+
upsert: (formKey, schema) => request(`${formsPath}/${encodeURIComponent(formKey)}`, { method: "PUT", body: JSON.stringify(schema) }),
|
|
124
|
+
get: (formKey) => request(`${formsPath}/${encodeURIComponent(formKey)}`, {
|
|
125
|
+
method: "GET",
|
|
126
|
+
}),
|
|
127
|
+
rotatePublicKey: (formKey) => request(`${formsPath}/${encodeURIComponent(formKey)}/rotate-key`, { method: "POST" }),
|
|
128
|
+
setActive: (formKey, active) => request(`${formsPath}/${encodeURIComponent(formKey)}`, {
|
|
129
|
+
method: "PATCH",
|
|
130
|
+
body: JSON.stringify({ active }),
|
|
131
|
+
}),
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Submits data to exactly one public input form. It is safe to use in browser
|
|
136
|
+
* code because a `nukle_form_...` key cannot read content or manage schemas.
|
|
137
|
+
*/
|
|
138
|
+
export function createNukleFormClient(options) {
|
|
139
|
+
if (!options.formKey.trim())
|
|
140
|
+
throw new Error("Nukle form key is required.");
|
|
141
|
+
const baseUrl = normalizeBaseUrl(options.baseUrl ?? DEFAULT_BASE_URL);
|
|
142
|
+
const requestFetch = options.fetch ?? globalThis.fetch;
|
|
143
|
+
if (!requestFetch)
|
|
144
|
+
throw new Error("A fetch implementation is required.");
|
|
145
|
+
return {
|
|
146
|
+
async submit(data) {
|
|
147
|
+
const response = await createJsonRequest(baseUrl, requestFetch, `/public/forms/${encodeURIComponent(options.formKey)}/submissions`, {
|
|
148
|
+
method: "POST",
|
|
149
|
+
headers: { "x-nukle-form-key": options.formKey },
|
|
150
|
+
body: JSON.stringify({ data, website: "" }),
|
|
151
|
+
});
|
|
152
|
+
return readJson(response);
|
|
153
|
+
},
|
|
154
|
+
};
|
|
155
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,33 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lazrus/nukle",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.2.1",
|
|
4
|
+
"description": "Typed client for Nukle public website delivery APIs.",
|
|
5
|
+
"homepage": "https://docs.nukle.in",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"main": "./dist/index.js",
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"import": "./dist/index.js",
|
|
13
|
+
"default": "./dist/index.js"
|
|
14
|
+
}
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"@types/node": "^26.6.2",
|
|
21
|
+
"eslint": "^9",
|
|
22
|
+
"tsx": "^4.23.15",
|
|
23
|
+
"typescript": "5.9.2",
|
|
24
|
+
"@repo/eslint-config": "0.0.0",
|
|
25
|
+
"@repo/typescript-config": "0.0.0"
|
|
26
|
+
},
|
|
27
|
+
"scripts": {
|
|
28
|
+
"build": "tsc",
|
|
29
|
+
"check-types": "tsc --noEmit",
|
|
30
|
+
"test": "tsx --test src/**/*.test.ts",
|
|
31
|
+
"lint": "eslint . --max-warnings 0"
|
|
32
|
+
}
|
|
6
33
|
}
|