kyro-connect 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.
@@ -0,0 +1,244 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+
4
+ // bin/kyro-codegen.ts
5
+ var import_fs = require("fs");
6
+ var import_path = require("path");
7
+
8
+ // src/codegen.ts
9
+ function capitalize(s) {
10
+ return s.replace(/[-_]\w/g, (m) => m[1].toUpperCase()).replace(/^\w/, (c) => c.toUpperCase());
11
+ }
12
+ function toTSName(slug) {
13
+ return slug.replace(/[-_]\w/g, (m) => m[1].toUpperCase()).replace(/^_+/g, "");
14
+ }
15
+ function fieldToTS(field, depth = 0) {
16
+ const indent = " ".repeat(depth + 1);
17
+ if (field.type === "group" || field.type === "row" || field.type === "collapsible") {
18
+ const fields = (field.fields ?? []).map((f) => fieldToTS(f, depth + 1)).join("\n");
19
+ return `${indent}${field.name}: {
20
+ ${fields}
21
+ ${indent}}${field.required ? "" : " | null"};`;
22
+ }
23
+ if (field.type === "array") {
24
+ const inner = (field.fields ?? []).map((f) => fieldToTS(f, depth + 2)).join("\n");
25
+ return `${indent}${field.name}: Array<{
26
+ ${inner}
27
+ ${indent} }>;`;
28
+ }
29
+ if (field.type === "blocks") {
30
+ const blockTypes = (field.blocks ?? []).map((b) => {
31
+ const fields = b.fields.map((f) => fieldToTS(f, depth + 2)).join("\n");
32
+ return `${indent} { blockType: "${b.slug}";
33
+ ${fields}
34
+ ${indent} }`;
35
+ }).join(" |\n");
36
+ return `${indent}${field.name}: Array<${blockTypes}>;
37
+ `;
38
+ }
39
+ if (field.type === "tabs") {
40
+ const all = [];
41
+ for (const tab of field.tabs ?? []) {
42
+ for (const f of tab.fields ?? []) {
43
+ all.push(fieldToTS(f, depth));
44
+ }
45
+ }
46
+ return all.join("\n");
47
+ }
48
+ if (field.type === "relationship") {
49
+ const relType = field.hasMany ? `Array<${field.relationTo ? capitalize(field.relationTo) : "any"} | string>` : `${field.relationTo ? capitalize(field.relationTo) : "any"} | string`;
50
+ return `${indent}${field.name}${field.required ? "" : "?"}: ${relType};`;
51
+ }
52
+ if (field.type === "upload") {
53
+ const upType = field.hasMany ? "string[]" : "string";
54
+ return `${indent}${field.name}${field.required ? "" : "?"}: ${upType};`;
55
+ }
56
+ if (field.type === "checkbox") {
57
+ return `${indent}${field.name}${field.required ? "" : "?"}: boolean;`;
58
+ }
59
+ if (field.type === "number") {
60
+ return `${indent}${field.name}${field.required ? "" : "?"}: number;`;
61
+ }
62
+ if (field.type === "date") {
63
+ return `${indent}${field.name}${field.required ? "" : "?"}: string;`;
64
+ }
65
+ if (field.type === "select" || field.type === "radio") {
66
+ if (field.hasMany && field.options) {
67
+ return `${indent}${field.name}${field.required ? "" : "?"}: ${field.options.map((o) => `"${o.value}"`).join(" | ")}[];`;
68
+ }
69
+ if (field.options) {
70
+ return `${indent}${field.name}${field.required ? "" : "?"}: ${field.options.map((o) => `"${o.value}"`).join(" | ")};`;
71
+ }
72
+ return `${indent}${field.name}${field.required ? "" : "?"}: string;`;
73
+ }
74
+ if (field.type === "code" || field.type === "json" || field.type === "richtext" || field.type === "markdown") {
75
+ return `${indent}${field.name}${field.required ? "" : "?"}: any;`;
76
+ }
77
+ return `${indent}${field.name}${field.required ? "" : "?"}: string;`;
78
+ }
79
+ function fieldsToInterface(name, fields, depth = 0) {
80
+ const indent = " ".repeat(depth);
81
+ const body = fields.map((f) => fieldToTS(f, depth)).join("\n");
82
+ return `${indent}export interface ${name} {
83
+ ${body}
84
+ ${indent}}`;
85
+ }
86
+ function generateDTS(schema) {
87
+ const lines = [
88
+ "// ============================================================================",
89
+ "// Kyro CMS \u2014 Generated Type Definitions",
90
+ "// Run: npx kyro-codegen --url <url> --api-key <key>",
91
+ "// ============================================================================",
92
+ "",
93
+ "/* eslint-disable */",
94
+ "/* @ts-nocheck */",
95
+ ""
96
+ ];
97
+ const routerEntries = [];
98
+ for (const [slug, col] of Object.entries(schema.collections ?? {})) {
99
+ const name = capitalize(toTSName(slug));
100
+ const fields = col.fields ?? [];
101
+ lines.push(fieldsToInterface(name, fields));
102
+ lines.push("");
103
+ lines.push(`export interface ${name}FindInput {`);
104
+ lines.push(` where?: Record<string, any>;`);
105
+ lines.push(` sort?: string;`);
106
+ lines.push(` limit?: number;`);
107
+ lines.push(` page?: number;`);
108
+ lines.push(` depth?: number;`);
109
+ lines.push(` select?: string[];`);
110
+ lines.push(` draft?: boolean;`);
111
+ lines.push(`}`);
112
+ lines.push("");
113
+ lines.push(`export interface ${name}FindOutput {`);
114
+ lines.push(` docs: ${name}[];`);
115
+ lines.push(` totalDocs: number;`);
116
+ lines.push(` limit: number;`);
117
+ lines.push(` totalPages: number;`);
118
+ lines.push(` page: number;`);
119
+ lines.push(` pagingCounter: number;`);
120
+ lines.push(` hasPrevPage: boolean;`);
121
+ lines.push(` hasNextPage: boolean;`);
122
+ lines.push(` prevPage: number | null;`);
123
+ lines.push(` nextPage: number | null;`);
124
+ lines.push(`}`);
125
+ lines.push("");
126
+ lines.push(`export interface ${name}FindByIDInput {`);
127
+ lines.push(` id: string;`);
128
+ lines.push(` depth?: number;`);
129
+ lines.push(` select?: string[];`);
130
+ lines.push(` draft?: boolean;`);
131
+ lines.push(`}`);
132
+ lines.push("");
133
+ lines.push(`export interface ${name}CreateInput {`);
134
+ lines.push(` data: Partial<${name}>;`);
135
+ lines.push(` depth?: number;`);
136
+ lines.push(` select?: string[];`);
137
+ lines.push(`}`);
138
+ lines.push("");
139
+ lines.push(`export interface ${name}UpdateInput {`);
140
+ lines.push(` id: string;`);
141
+ lines.push(` data: Partial<${name}>;`);
142
+ lines.push(` depth?: number;`);
143
+ lines.push(` select?: string[];`);
144
+ lines.push(` baseUpdatedAt?: string;`);
145
+ lines.push(`}`);
146
+ lines.push("");
147
+ lines.push(`export interface ${name}DeleteInput {`);
148
+ lines.push(` id: string;`);
149
+ lines.push(`}`);
150
+ lines.push("");
151
+ lines.push(`export interface ${name}CountInput {`);
152
+ lines.push(` where?: Record<string, any>;`);
153
+ lines.push(`}`);
154
+ lines.push("");
155
+ routerEntries.push(` "${slug}": {`);
156
+ routerEntries.push(` find: { input: ${name}FindInput; output: ${name}FindOutput };`);
157
+ routerEntries.push(` findByID: { input: ${name}FindByIDInput; output: ${name} };`);
158
+ routerEntries.push(` create: { input: ${name}CreateInput; output: { doc: ${name} } };`);
159
+ routerEntries.push(` update: { input: ${name}UpdateInput; output: { doc: ${name} } };`);
160
+ routerEntries.push(` delete: { input: ${name}DeleteInput; output: { doc: ${name}; message: string } };`);
161
+ routerEntries.push(` count: { input: ${name}CountInput; output: { totalDocs: number } };`);
162
+ routerEntries.push(` };`);
163
+ }
164
+ for (const [slug, global] of Object.entries(schema.globals ?? {})) {
165
+ const name = `${capitalize(toTSName(slug))}Global`;
166
+ const fields = global.fields ?? [];
167
+ lines.push(fieldsToInterface(name, fields));
168
+ lines.push("");
169
+ routerEntries.push(` "_globals_${slug}": {`);
170
+ routerEntries.push(` get: { input: Record<string, never>; output: ${name} };`);
171
+ routerEntries.push(` update: { input: { data: Partial<${name}> }; output: ${name} };`);
172
+ routerEntries.push(` };`);
173
+ }
174
+ lines.push("export interface AppRouter {");
175
+ lines.push(routerEntries.join("\n"));
176
+ lines.push("}");
177
+ lines.push("");
178
+ return lines.join("\n");
179
+ }
180
+
181
+ // bin/kyro-codegen.ts
182
+ async function main() {
183
+ const args = process.argv.slice(2);
184
+ const url = getArg(args, "--url");
185
+ const apiKey = getArg(args, "--api-key");
186
+ const output = getArg(args, "--output") || "kyro.generated.d.ts";
187
+ if (!url || !apiKey) {
188
+ console.error("");
189
+ console.error(" kyro-codegen \u2014 Generate Kyro CMS type definitions");
190
+ console.error("");
191
+ console.error(" Usage:");
192
+ console.error(" npx kyro-codegen --url <url> --api-key <key> [--output <path>]");
193
+ console.error("");
194
+ console.error(" Example:");
195
+ console.error(" npx kyro-codegen --url http://localhost:4321/api --api-key kyro_abc123");
196
+ console.error("");
197
+ process.exit(1);
198
+ }
199
+ const schemaUrl = `${url.replace(/\/$/, "")}/kyro/schema`;
200
+ console.log(`[kyro-codegen] Fetching schema from ${schemaUrl}...`);
201
+ let res;
202
+ try {
203
+ res = await fetch(schemaUrl, {
204
+ headers: { "x-api-key": apiKey }
205
+ });
206
+ } catch (err) {
207
+ console.error(`[kyro-codegen] Failed to connect: ${err.message}`);
208
+ process.exit(1);
209
+ }
210
+ if (!res.ok) {
211
+ let body;
212
+ try {
213
+ body = await res.json();
214
+ } catch {
215
+ }
216
+ console.error(`[kyro-codegen] Schema request failed (${res.status}): ${body?.error ?? res.statusText}`);
217
+ process.exit(1);
218
+ }
219
+ let schema;
220
+ try {
221
+ schema = await res.json();
222
+ } catch {
223
+ console.error("[kyro-codegen] Invalid JSON response from schema endpoint");
224
+ process.exit(1);
225
+ }
226
+ const dts = generateDTS(schema);
227
+ const outPath = (0, import_path.resolve)(process.cwd(), output);
228
+ (0, import_fs.writeFileSync)(outPath, dts, "utf-8");
229
+ const colCount = Object.keys(schema.collections ?? {}).length;
230
+ const globalCount = Object.keys(schema.globals ?? {}).length;
231
+ console.log(`[kyro-codegen] Generated ${outPath}`);
232
+ console.log(`[kyro-codegen] ${colCount} collections, ${globalCount} globals`);
233
+ }
234
+ function getArg(args, name) {
235
+ const idx = args.indexOf(name);
236
+ if (idx !== -1 && idx + 1 < args.length) {
237
+ return args[idx + 1];
238
+ }
239
+ return void 0;
240
+ }
241
+ main().catch((err) => {
242
+ console.error(`[kyro-codegen] Fatal error: ${err.message}`);
243
+ process.exit(1);
244
+ });
@@ -0,0 +1,243 @@
1
+ #!/usr/bin/env node
2
+
3
+ // bin/kyro-codegen.ts
4
+ import { writeFileSync } from "fs";
5
+ import { resolve } from "path";
6
+
7
+ // src/codegen.ts
8
+ function capitalize(s) {
9
+ return s.replace(/[-_]\w/g, (m) => m[1].toUpperCase()).replace(/^\w/, (c) => c.toUpperCase());
10
+ }
11
+ function toTSName(slug) {
12
+ return slug.replace(/[-_]\w/g, (m) => m[1].toUpperCase()).replace(/^_+/g, "");
13
+ }
14
+ function fieldToTS(field, depth = 0) {
15
+ const indent = " ".repeat(depth + 1);
16
+ if (field.type === "group" || field.type === "row" || field.type === "collapsible") {
17
+ const fields = (field.fields ?? []).map((f) => fieldToTS(f, depth + 1)).join("\n");
18
+ return `${indent}${field.name}: {
19
+ ${fields}
20
+ ${indent}}${field.required ? "" : " | null"};`;
21
+ }
22
+ if (field.type === "array") {
23
+ const inner = (field.fields ?? []).map((f) => fieldToTS(f, depth + 2)).join("\n");
24
+ return `${indent}${field.name}: Array<{
25
+ ${inner}
26
+ ${indent} }>;`;
27
+ }
28
+ if (field.type === "blocks") {
29
+ const blockTypes = (field.blocks ?? []).map((b) => {
30
+ const fields = b.fields.map((f) => fieldToTS(f, depth + 2)).join("\n");
31
+ return `${indent} { blockType: "${b.slug}";
32
+ ${fields}
33
+ ${indent} }`;
34
+ }).join(" |\n");
35
+ return `${indent}${field.name}: Array<${blockTypes}>;
36
+ `;
37
+ }
38
+ if (field.type === "tabs") {
39
+ const all = [];
40
+ for (const tab of field.tabs ?? []) {
41
+ for (const f of tab.fields ?? []) {
42
+ all.push(fieldToTS(f, depth));
43
+ }
44
+ }
45
+ return all.join("\n");
46
+ }
47
+ if (field.type === "relationship") {
48
+ const relType = field.hasMany ? `Array<${field.relationTo ? capitalize(field.relationTo) : "any"} | string>` : `${field.relationTo ? capitalize(field.relationTo) : "any"} | string`;
49
+ return `${indent}${field.name}${field.required ? "" : "?"}: ${relType};`;
50
+ }
51
+ if (field.type === "upload") {
52
+ const upType = field.hasMany ? "string[]" : "string";
53
+ return `${indent}${field.name}${field.required ? "" : "?"}: ${upType};`;
54
+ }
55
+ if (field.type === "checkbox") {
56
+ return `${indent}${field.name}${field.required ? "" : "?"}: boolean;`;
57
+ }
58
+ if (field.type === "number") {
59
+ return `${indent}${field.name}${field.required ? "" : "?"}: number;`;
60
+ }
61
+ if (field.type === "date") {
62
+ return `${indent}${field.name}${field.required ? "" : "?"}: string;`;
63
+ }
64
+ if (field.type === "select" || field.type === "radio") {
65
+ if (field.hasMany && field.options) {
66
+ return `${indent}${field.name}${field.required ? "" : "?"}: ${field.options.map((o) => `"${o.value}"`).join(" | ")}[];`;
67
+ }
68
+ if (field.options) {
69
+ return `${indent}${field.name}${field.required ? "" : "?"}: ${field.options.map((o) => `"${o.value}"`).join(" | ")};`;
70
+ }
71
+ return `${indent}${field.name}${field.required ? "" : "?"}: string;`;
72
+ }
73
+ if (field.type === "code" || field.type === "json" || field.type === "richtext" || field.type === "markdown") {
74
+ return `${indent}${field.name}${field.required ? "" : "?"}: any;`;
75
+ }
76
+ return `${indent}${field.name}${field.required ? "" : "?"}: string;`;
77
+ }
78
+ function fieldsToInterface(name, fields, depth = 0) {
79
+ const indent = " ".repeat(depth);
80
+ const body = fields.map((f) => fieldToTS(f, depth)).join("\n");
81
+ return `${indent}export interface ${name} {
82
+ ${body}
83
+ ${indent}}`;
84
+ }
85
+ function generateDTS(schema) {
86
+ const lines = [
87
+ "// ============================================================================",
88
+ "// Kyro CMS \u2014 Generated Type Definitions",
89
+ "// Run: npx kyro-codegen --url <url> --api-key <key>",
90
+ "// ============================================================================",
91
+ "",
92
+ "/* eslint-disable */",
93
+ "/* @ts-nocheck */",
94
+ ""
95
+ ];
96
+ const routerEntries = [];
97
+ for (const [slug, col] of Object.entries(schema.collections ?? {})) {
98
+ const name = capitalize(toTSName(slug));
99
+ const fields = col.fields ?? [];
100
+ lines.push(fieldsToInterface(name, fields));
101
+ lines.push("");
102
+ lines.push(`export interface ${name}FindInput {`);
103
+ lines.push(` where?: Record<string, any>;`);
104
+ lines.push(` sort?: string;`);
105
+ lines.push(` limit?: number;`);
106
+ lines.push(` page?: number;`);
107
+ lines.push(` depth?: number;`);
108
+ lines.push(` select?: string[];`);
109
+ lines.push(` draft?: boolean;`);
110
+ lines.push(`}`);
111
+ lines.push("");
112
+ lines.push(`export interface ${name}FindOutput {`);
113
+ lines.push(` docs: ${name}[];`);
114
+ lines.push(` totalDocs: number;`);
115
+ lines.push(` limit: number;`);
116
+ lines.push(` totalPages: number;`);
117
+ lines.push(` page: number;`);
118
+ lines.push(` pagingCounter: number;`);
119
+ lines.push(` hasPrevPage: boolean;`);
120
+ lines.push(` hasNextPage: boolean;`);
121
+ lines.push(` prevPage: number | null;`);
122
+ lines.push(` nextPage: number | null;`);
123
+ lines.push(`}`);
124
+ lines.push("");
125
+ lines.push(`export interface ${name}FindByIDInput {`);
126
+ lines.push(` id: string;`);
127
+ lines.push(` depth?: number;`);
128
+ lines.push(` select?: string[];`);
129
+ lines.push(` draft?: boolean;`);
130
+ lines.push(`}`);
131
+ lines.push("");
132
+ lines.push(`export interface ${name}CreateInput {`);
133
+ lines.push(` data: Partial<${name}>;`);
134
+ lines.push(` depth?: number;`);
135
+ lines.push(` select?: string[];`);
136
+ lines.push(`}`);
137
+ lines.push("");
138
+ lines.push(`export interface ${name}UpdateInput {`);
139
+ lines.push(` id: string;`);
140
+ lines.push(` data: Partial<${name}>;`);
141
+ lines.push(` depth?: number;`);
142
+ lines.push(` select?: string[];`);
143
+ lines.push(` baseUpdatedAt?: string;`);
144
+ lines.push(`}`);
145
+ lines.push("");
146
+ lines.push(`export interface ${name}DeleteInput {`);
147
+ lines.push(` id: string;`);
148
+ lines.push(`}`);
149
+ lines.push("");
150
+ lines.push(`export interface ${name}CountInput {`);
151
+ lines.push(` where?: Record<string, any>;`);
152
+ lines.push(`}`);
153
+ lines.push("");
154
+ routerEntries.push(` "${slug}": {`);
155
+ routerEntries.push(` find: { input: ${name}FindInput; output: ${name}FindOutput };`);
156
+ routerEntries.push(` findByID: { input: ${name}FindByIDInput; output: ${name} };`);
157
+ routerEntries.push(` create: { input: ${name}CreateInput; output: { doc: ${name} } };`);
158
+ routerEntries.push(` update: { input: ${name}UpdateInput; output: { doc: ${name} } };`);
159
+ routerEntries.push(` delete: { input: ${name}DeleteInput; output: { doc: ${name}; message: string } };`);
160
+ routerEntries.push(` count: { input: ${name}CountInput; output: { totalDocs: number } };`);
161
+ routerEntries.push(` };`);
162
+ }
163
+ for (const [slug, global] of Object.entries(schema.globals ?? {})) {
164
+ const name = `${capitalize(toTSName(slug))}Global`;
165
+ const fields = global.fields ?? [];
166
+ lines.push(fieldsToInterface(name, fields));
167
+ lines.push("");
168
+ routerEntries.push(` "_globals_${slug}": {`);
169
+ routerEntries.push(` get: { input: Record<string, never>; output: ${name} };`);
170
+ routerEntries.push(` update: { input: { data: Partial<${name}> }; output: ${name} };`);
171
+ routerEntries.push(` };`);
172
+ }
173
+ lines.push("export interface AppRouter {");
174
+ lines.push(routerEntries.join("\n"));
175
+ lines.push("}");
176
+ lines.push("");
177
+ return lines.join("\n");
178
+ }
179
+
180
+ // bin/kyro-codegen.ts
181
+ async function main() {
182
+ const args = process.argv.slice(2);
183
+ const url = getArg(args, "--url");
184
+ const apiKey = getArg(args, "--api-key");
185
+ const output = getArg(args, "--output") || "kyro.generated.d.ts";
186
+ if (!url || !apiKey) {
187
+ console.error("");
188
+ console.error(" kyro-codegen \u2014 Generate Kyro CMS type definitions");
189
+ console.error("");
190
+ console.error(" Usage:");
191
+ console.error(" npx kyro-codegen --url <url> --api-key <key> [--output <path>]");
192
+ console.error("");
193
+ console.error(" Example:");
194
+ console.error(" npx kyro-codegen --url http://localhost:4321/api --api-key kyro_abc123");
195
+ console.error("");
196
+ process.exit(1);
197
+ }
198
+ const schemaUrl = `${url.replace(/\/$/, "")}/kyro/schema`;
199
+ console.log(`[kyro-codegen] Fetching schema from ${schemaUrl}...`);
200
+ let res;
201
+ try {
202
+ res = await fetch(schemaUrl, {
203
+ headers: { "x-api-key": apiKey }
204
+ });
205
+ } catch (err) {
206
+ console.error(`[kyro-codegen] Failed to connect: ${err.message}`);
207
+ process.exit(1);
208
+ }
209
+ if (!res.ok) {
210
+ let body;
211
+ try {
212
+ body = await res.json();
213
+ } catch {
214
+ }
215
+ console.error(`[kyro-codegen] Schema request failed (${res.status}): ${body?.error ?? res.statusText}`);
216
+ process.exit(1);
217
+ }
218
+ let schema;
219
+ try {
220
+ schema = await res.json();
221
+ } catch {
222
+ console.error("[kyro-codegen] Invalid JSON response from schema endpoint");
223
+ process.exit(1);
224
+ }
225
+ const dts = generateDTS(schema);
226
+ const outPath = resolve(process.cwd(), output);
227
+ writeFileSync(outPath, dts, "utf-8");
228
+ const colCount = Object.keys(schema.collections ?? {}).length;
229
+ const globalCount = Object.keys(schema.globals ?? {}).length;
230
+ console.log(`[kyro-codegen] Generated ${outPath}`);
231
+ console.log(`[kyro-codegen] ${colCount} collections, ${globalCount} globals`);
232
+ }
233
+ function getArg(args, name) {
234
+ const idx = args.indexOf(name);
235
+ if (idx !== -1 && idx + 1 < args.length) {
236
+ return args[idx + 1];
237
+ }
238
+ return void 0;
239
+ }
240
+ main().catch((err) => {
241
+ console.error(`[kyro-codegen] Fatal error: ${err.message}`);
242
+ process.exit(1);
243
+ });
package/dist/index.cjs ADDED
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var src_exports = {};
22
+ __export(src_exports, {
23
+ KyroConnectError: () => KyroConnectError,
24
+ createClient: () => createClient
25
+ });
26
+ module.exports = __toCommonJS(src_exports);
27
+
28
+ // src/errors.ts
29
+ var KyroConnectError = class extends Error {
30
+ status;
31
+ code;
32
+ raw;
33
+ constructor(message, status = 500, raw) {
34
+ super(message);
35
+ this.name = "KyroConnectError";
36
+ this.status = status;
37
+ this.code = raw?.error?.code ?? -32603;
38
+ this.raw = raw;
39
+ }
40
+ };
41
+
42
+ // src/client.ts
43
+ var MUTATIONS = /* @__PURE__ */ new Set(["create", "update", "delete"]);
44
+ async function handleResponse(res) {
45
+ if (!res.ok) {
46
+ let body2;
47
+ try {
48
+ body2 = await res.json();
49
+ } catch {
50
+ throw new KyroConnectError(res.statusText, res.status);
51
+ }
52
+ throw new KyroConnectError(
53
+ body2?.error?.message ?? res.statusText,
54
+ res.status,
55
+ body2
56
+ );
57
+ }
58
+ const body = await res.json();
59
+ return body?.result?.data ?? body;
60
+ }
61
+ function createClient(opts) {
62
+ const baseUrl = opts.url.replace(/\/$/, "");
63
+ const doFetch = opts.fetch ?? globalThis.fetch;
64
+ function headers(extra) {
65
+ return {
66
+ ...opts.apiKey ? { "x-api-key": opts.apiKey } : {},
67
+ ...extra
68
+ };
69
+ }
70
+ function makeRequest(path, input) {
71
+ const name = path[path.length - 1];
72
+ const pathStr = path.join(".");
73
+ const isMutation = MUTATIONS.has(name);
74
+ if (isMutation) {
75
+ return doFetch(`${baseUrl}/${pathStr}`, {
76
+ method: "POST",
77
+ headers: { "Content-Type": "application/json", ...headers() },
78
+ body: JSON.stringify(input)
79
+ }).then(handleResponse);
80
+ }
81
+ const qs = encodeURIComponent(JSON.stringify(input));
82
+ return doFetch(`${baseUrl}/${pathStr}?input=${qs}`, {
83
+ method: "GET",
84
+ headers: headers()
85
+ }).then(handleResponse);
86
+ }
87
+ function buildProxy(path) {
88
+ return new Proxy(function() {
89
+ }, {
90
+ get(_, prop) {
91
+ return buildProxy([...path, prop]);
92
+ },
93
+ apply(_, __, args) {
94
+ return makeRequest(path, args[0] ?? {});
95
+ }
96
+ });
97
+ }
98
+ return buildProxy([]);
99
+ }
100
+ // Annotate the CommonJS export names for ESM import in node:
101
+ 0 && (module.exports = {
102
+ KyroConnectError,
103
+ createClient
104
+ });
@@ -0,0 +1,15 @@
1
+ interface ClientOptions {
2
+ url: string;
3
+ apiKey?: string;
4
+ fetch?: typeof globalThis.fetch;
5
+ }
6
+ declare function createClient(opts: ClientOptions): any;
7
+
8
+ declare class KyroConnectError extends Error {
9
+ readonly status: number;
10
+ readonly code: number;
11
+ readonly raw: any;
12
+ constructor(message: string, status?: number, raw?: any);
13
+ }
14
+
15
+ export { type ClientOptions, KyroConnectError, createClient };
@@ -0,0 +1,15 @@
1
+ interface ClientOptions {
2
+ url: string;
3
+ apiKey?: string;
4
+ fetch?: typeof globalThis.fetch;
5
+ }
6
+ declare function createClient(opts: ClientOptions): any;
7
+
8
+ declare class KyroConnectError extends Error {
9
+ readonly status: number;
10
+ readonly code: number;
11
+ readonly raw: any;
12
+ constructor(message: string, status?: number, raw?: any);
13
+ }
14
+
15
+ export { type ClientOptions, KyroConnectError, createClient };
package/dist/index.js ADDED
@@ -0,0 +1,76 @@
1
+ // src/errors.ts
2
+ var KyroConnectError = class extends Error {
3
+ status;
4
+ code;
5
+ raw;
6
+ constructor(message, status = 500, raw) {
7
+ super(message);
8
+ this.name = "KyroConnectError";
9
+ this.status = status;
10
+ this.code = raw?.error?.code ?? -32603;
11
+ this.raw = raw;
12
+ }
13
+ };
14
+
15
+ // src/client.ts
16
+ var MUTATIONS = /* @__PURE__ */ new Set(["create", "update", "delete"]);
17
+ async function handleResponse(res) {
18
+ if (!res.ok) {
19
+ let body2;
20
+ try {
21
+ body2 = await res.json();
22
+ } catch {
23
+ throw new KyroConnectError(res.statusText, res.status);
24
+ }
25
+ throw new KyroConnectError(
26
+ body2?.error?.message ?? res.statusText,
27
+ res.status,
28
+ body2
29
+ );
30
+ }
31
+ const body = await res.json();
32
+ return body?.result?.data ?? body;
33
+ }
34
+ function createClient(opts) {
35
+ const baseUrl = opts.url.replace(/\/$/, "");
36
+ const doFetch = opts.fetch ?? globalThis.fetch;
37
+ function headers(extra) {
38
+ return {
39
+ ...opts.apiKey ? { "x-api-key": opts.apiKey } : {},
40
+ ...extra
41
+ };
42
+ }
43
+ function makeRequest(path, input) {
44
+ const name = path[path.length - 1];
45
+ const pathStr = path.join(".");
46
+ const isMutation = MUTATIONS.has(name);
47
+ if (isMutation) {
48
+ return doFetch(`${baseUrl}/${pathStr}`, {
49
+ method: "POST",
50
+ headers: { "Content-Type": "application/json", ...headers() },
51
+ body: JSON.stringify(input)
52
+ }).then(handleResponse);
53
+ }
54
+ const qs = encodeURIComponent(JSON.stringify(input));
55
+ return doFetch(`${baseUrl}/${pathStr}?input=${qs}`, {
56
+ method: "GET",
57
+ headers: headers()
58
+ }).then(handleResponse);
59
+ }
60
+ function buildProxy(path) {
61
+ return new Proxy(function() {
62
+ }, {
63
+ get(_, prop) {
64
+ return buildProxy([...path, prop]);
65
+ },
66
+ apply(_, __, args) {
67
+ return makeRequest(path, args[0] ?? {});
68
+ }
69
+ });
70
+ }
71
+ return buildProxy([]);
72
+ }
73
+ export {
74
+ KyroConnectError,
75
+ createClient
76
+ };
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "kyro-connect",
3
+ "version": "0.1.0",
4
+ "description": "Universal SDK for Kyro CMS. Type-safe client + codegen for any platform.",
5
+ "type": "module",
6
+ "exports": {
7
+ ".": {
8
+ "types": "./dist/index.d.ts",
9
+ "import": "./dist/index.js",
10
+ "require": "./dist/index.cjs"
11
+ }
12
+ },
13
+ "bin": {
14
+ "kyro-codegen": "./dist/bin/kyro-codegen.js"
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsup",
21
+ "prepublishOnly": "pnpm build"
22
+ },
23
+ "repository": {
24
+ "type": "git",
25
+ "url": "https://github.com/danielDozie/kyro-cms"
26
+ },
27
+ "keywords": [
28
+ "kyro",
29
+ "cms",
30
+ "sdk",
31
+ "client",
32
+ "typescript"
33
+ ],
34
+ "license": "MIT",
35
+ "devDependencies": {
36
+ "tsup": "^8.0.0",
37
+ "typescript": "^5.0.0"
38
+ }
39
+ }