@kubb/core 4.23.0 → 4.24.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/dist/getBarrelFiles-CvaEQ7z_.d.ts +35 -0
- package/dist/getBarrelFiles-D9yKoizv.d.cts +35 -0
- package/dist/{utils-BclJP5UT.cjs → getBarrelFiles-DCNjiX2W.cjs} +11 -350
- package/dist/getBarrelFiles-DCNjiX2W.cjs.map +1 -0
- package/dist/{utils-C3cuilmF.js → getBarrelFiles-gRyVPFBP.js} +22 -281
- package/dist/getBarrelFiles-gRyVPFBP.js.map +1 -0
- package/dist/index.cjs +19 -156
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +3 -29
- package/dist/index.d.ts +3 -29
- package/dist/index.js +4 -140
- package/dist/index.js.map +1 -1
- package/dist/utils.cjs +288 -24
- package/dist/utils.cjs.map +1 -0
- package/dist/utils.d.cts +226 -3
- package/dist/utils.d.ts +226 -3
- package/dist/utils.js +264 -3
- package/dist/utils.js.map +1 -0
- package/package.json +1 -1
- package/src/index.ts +0 -1
- package/src/server/index.ts +2 -193
- package/src/types.ts +88 -0
- package/dist/index-BfAwjQCB.d.cts +0 -255
- package/dist/index-C0nP9vjm.d.ts +0 -255
- package/dist/utils-BclJP5UT.cjs.map +0 -1
- package/dist/utils-C3cuilmF.js.map +0 -1
package/dist/utils.js
CHANGED
|
@@ -1,4 +1,265 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import "./
|
|
1
|
+
import { t as __name } from "./chunk-iVr_oF3V.js";
|
|
2
|
+
import { a as getElapsedMs, i as formatMs, l as getUniqueName, n as URLPath, o as AsyncEventEmitter, r as formatHrtime, t as getBarrelFiles, u as setUniqueName } from "./getBarrelFiles-gRyVPFBP.js";
|
|
3
|
+
import { m as camelCase } from "./transformers-8ju9ixkG.js";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { orderBy } from "natural-orderby";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
import { readFileSync } from "node:fs";
|
|
8
|
+
import dns from "node:dns";
|
|
9
|
+
import createJiti from "jiti";
|
|
3
10
|
|
|
4
|
-
|
|
11
|
+
//#region src/utils/buildJSDoc.ts
|
|
12
|
+
/**
|
|
13
|
+
* Builds a JSDoc comment block with custom indentation.
|
|
14
|
+
* @param comments - Array of comment strings to include in the JSDoc block
|
|
15
|
+
* @param options - Configuration options for formatting
|
|
16
|
+
* @returns Formatted JSDoc string or fallback string if no comments
|
|
17
|
+
*/
|
|
18
|
+
function buildJSDoc(comments, options = {}) {
|
|
19
|
+
const { indent = " * ", suffix = "\n ", fallback = " " } = options;
|
|
20
|
+
if (comments.length === 0) return fallback;
|
|
21
|
+
return `/**\n${comments.map((c) => `${indent}${c}`).join("\n")}\n */${suffix}`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
//#endregion
|
|
25
|
+
//#region src/utils/Cache.ts
|
|
26
|
+
var Cache = class {
|
|
27
|
+
#buffer = /* @__PURE__ */ new Map();
|
|
28
|
+
async get(key) {
|
|
29
|
+
return this.#buffer.get(key) ?? null;
|
|
30
|
+
}
|
|
31
|
+
async set(key, value) {
|
|
32
|
+
this.#buffer.set(key, value);
|
|
33
|
+
}
|
|
34
|
+
async delete(key) {
|
|
35
|
+
this.#buffer.delete(key);
|
|
36
|
+
}
|
|
37
|
+
async clear() {
|
|
38
|
+
this.#buffer.clear();
|
|
39
|
+
}
|
|
40
|
+
async keys() {
|
|
41
|
+
return [...this.#buffer.keys()];
|
|
42
|
+
}
|
|
43
|
+
async values() {
|
|
44
|
+
return [...this.#buffer.values()];
|
|
45
|
+
}
|
|
46
|
+
async flush() {}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
//#endregion
|
|
50
|
+
//#region src/utils/checkOnlineStatus.ts
|
|
51
|
+
/**
|
|
52
|
+
* Check if the system has internet connectivity
|
|
53
|
+
* Uses DNS lookup to well-known stable domains as a lightweight connectivity test
|
|
54
|
+
*/
|
|
55
|
+
async function isOnline() {
|
|
56
|
+
for (const domain of [
|
|
57
|
+
"dns.google.com",
|
|
58
|
+
"cloudflare.com",
|
|
59
|
+
"one.one.one.one"
|
|
60
|
+
]) try {
|
|
61
|
+
await dns.promises.resolve(domain);
|
|
62
|
+
return true;
|
|
63
|
+
} catch {}
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Execute a function only if online, otherwise silently skip
|
|
68
|
+
*/
|
|
69
|
+
async function executeIfOnline(fn) {
|
|
70
|
+
if (!await isOnline()) return null;
|
|
71
|
+
try {
|
|
72
|
+
return await fn();
|
|
73
|
+
} catch {
|
|
74
|
+
return null;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
//#endregion
|
|
79
|
+
//#region src/utils/FunctionParams.ts
|
|
80
|
+
/**
|
|
81
|
+
* @deprecated
|
|
82
|
+
*/
|
|
83
|
+
var FunctionParams = class FunctionParams {
|
|
84
|
+
#items = [];
|
|
85
|
+
constructor() {
|
|
86
|
+
return this;
|
|
87
|
+
}
|
|
88
|
+
get items() {
|
|
89
|
+
return this.#items.flat();
|
|
90
|
+
}
|
|
91
|
+
add(item) {
|
|
92
|
+
if (!item) return this;
|
|
93
|
+
if (Array.isArray(item)) {
|
|
94
|
+
item.filter(Boolean).forEach((it) => {
|
|
95
|
+
this.#items.push(it);
|
|
96
|
+
});
|
|
97
|
+
return this;
|
|
98
|
+
}
|
|
99
|
+
this.#items.push(item);
|
|
100
|
+
return this;
|
|
101
|
+
}
|
|
102
|
+
static #orderItems(items) {
|
|
103
|
+
return orderBy(items.filter(Boolean), [(v) => {
|
|
104
|
+
if (Array.isArray(v)) return;
|
|
105
|
+
return !v.default;
|
|
106
|
+
}, (v) => {
|
|
107
|
+
if (Array.isArray(v)) return;
|
|
108
|
+
return v.required ?? true;
|
|
109
|
+
}], ["desc", "desc"]);
|
|
110
|
+
}
|
|
111
|
+
static #addParams(acc, item) {
|
|
112
|
+
const { enabled = true, name, type, required = true, ...rest } = item;
|
|
113
|
+
if (!enabled) return acc;
|
|
114
|
+
if (!name) {
|
|
115
|
+
acc.push(`${type}${rest.default ? ` = ${rest.default}` : ""}`);
|
|
116
|
+
return acc;
|
|
117
|
+
}
|
|
118
|
+
const parameterName = name.startsWith("{") ? name : camelCase(name);
|
|
119
|
+
if (type) if (required) acc.push(`${parameterName}: ${type}${rest.default ? ` = ${rest.default}` : ""}`);
|
|
120
|
+
else acc.push(`${parameterName}?: ${type}`);
|
|
121
|
+
else acc.push(`${parameterName}`);
|
|
122
|
+
return acc;
|
|
123
|
+
}
|
|
124
|
+
static toObject(items) {
|
|
125
|
+
let type = [];
|
|
126
|
+
let name = [];
|
|
127
|
+
const enabled = items.every((item) => item.enabled) ? items.at(0)?.enabled : true;
|
|
128
|
+
const required = items.every((item) => item.required) ?? true;
|
|
129
|
+
items.forEach((item) => {
|
|
130
|
+
name = FunctionParams.#addParams(name, {
|
|
131
|
+
...item,
|
|
132
|
+
type: void 0
|
|
133
|
+
});
|
|
134
|
+
if (items.some((item$1) => item$1.type)) type = FunctionParams.#addParams(type, item);
|
|
135
|
+
});
|
|
136
|
+
return {
|
|
137
|
+
name: `{ ${name.join(", ")} }`,
|
|
138
|
+
type: type.length ? `{ ${type.join("; ")} }` : void 0,
|
|
139
|
+
enabled,
|
|
140
|
+
required
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
toObject() {
|
|
144
|
+
const items = FunctionParams.#orderItems(this.#items).flat();
|
|
145
|
+
return FunctionParams.toObject(items);
|
|
146
|
+
}
|
|
147
|
+
static toString(items) {
|
|
148
|
+
return FunctionParams.#orderItems(items).reduce((acc, item) => {
|
|
149
|
+
if (Array.isArray(item)) {
|
|
150
|
+
if (item.length <= 0) return acc;
|
|
151
|
+
const subItems = FunctionParams.#orderItems(item);
|
|
152
|
+
const objectItem = FunctionParams.toObject(subItems);
|
|
153
|
+
return FunctionParams.#addParams(acc, objectItem);
|
|
154
|
+
}
|
|
155
|
+
return FunctionParams.#addParams(acc, item);
|
|
156
|
+
}, []).join(", ");
|
|
157
|
+
}
|
|
158
|
+
toString() {
|
|
159
|
+
const items = FunctionParams.#orderItems(this.#items);
|
|
160
|
+
return FunctionParams.toString(items);
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
|
|
164
|
+
//#endregion
|
|
165
|
+
//#region src/utils/getNestedAccessor.ts
|
|
166
|
+
/**
|
|
167
|
+
* Converts a param path (string with dot notation or array of strings) to a JavaScript accessor expression.
|
|
168
|
+
* @param param - The param path, e.g., 'pagination.next.id' or ['pagination', 'next', 'id']
|
|
169
|
+
* @param accessor - The base accessor, e.g., 'lastPage' or 'firstPage'
|
|
170
|
+
* @returns A JavaScript accessor expression, e.g., "lastPage?.['pagination']?.['next']?.['id']", or undefined if param is empty
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* ```ts
|
|
174
|
+
* getNestedAccessor('pagination.next.id', 'lastPage')
|
|
175
|
+
* // returns: "lastPage?.['pagination']?.['next']?.['id']"
|
|
176
|
+
*
|
|
177
|
+
* getNestedAccessor(['pagination', 'next', 'id'], 'lastPage')
|
|
178
|
+
* // returns: "lastPage?.['pagination']?.['next']?.['id']"
|
|
179
|
+
*
|
|
180
|
+
* getNestedAccessor('', 'lastPage')
|
|
181
|
+
* // returns: undefined
|
|
182
|
+
* ```
|
|
183
|
+
*/
|
|
184
|
+
function getNestedAccessor(param, accessor) {
|
|
185
|
+
const parts = Array.isArray(param) ? param : param.split(".");
|
|
186
|
+
if (parts.length === 0 || parts.length === 1 && parts[0] === "") return;
|
|
187
|
+
return parts.reduce((acc, part) => `${acc}?.['${part}']`, accessor);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
//#endregion
|
|
191
|
+
//#region src/utils/promise.ts
|
|
192
|
+
function isPromise(result) {
|
|
193
|
+
return !!result && typeof result?.then === "function";
|
|
194
|
+
}
|
|
195
|
+
function isPromiseFulfilledResult(result) {
|
|
196
|
+
return result.status === "fulfilled";
|
|
197
|
+
}
|
|
198
|
+
function isPromiseRejectedResult(result) {
|
|
199
|
+
return result.status === "rejected";
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
//#endregion
|
|
203
|
+
//#region src/utils/renderTemplate.ts
|
|
204
|
+
function renderTemplate(template, data = void 0) {
|
|
205
|
+
if (!data || !Object.keys(data).length) return template.replace(/{{(.*?)}}/g, "");
|
|
206
|
+
return template.match(/{{(.*?)}}/g)?.reduce((prev, curr) => {
|
|
207
|
+
const index = curr.split(/{{|}}/).filter(Boolean)[0]?.trim();
|
|
208
|
+
if (index === void 0) return prev;
|
|
209
|
+
const value = data[index];
|
|
210
|
+
if (value === void 0) return prev;
|
|
211
|
+
return prev.replace(curr, () => {
|
|
212
|
+
if (typeof value === "boolean") return `${value.toString()}` || "false";
|
|
213
|
+
return value || "";
|
|
214
|
+
}).trim();
|
|
215
|
+
}, template) || "";
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
//#endregion
|
|
219
|
+
//#region src/utils/resolveModuleSource.ts
|
|
220
|
+
function resolveModuleSource(pkgName) {
|
|
221
|
+
const parentURL = import.meta.url;
|
|
222
|
+
const resolved = createJiti(parentURL).esmResolve(pkgName, parentURL);
|
|
223
|
+
const filePath = resolved.startsWith("file:") ? fileURLToPath(resolved) : resolved;
|
|
224
|
+
return {
|
|
225
|
+
path: filePath,
|
|
226
|
+
source: readFileSync(filePath, { encoding: "utf-8" }),
|
|
227
|
+
ext: path.extname(filePath)
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
//#endregion
|
|
232
|
+
//#region src/utils/serializePluginOptions.ts
|
|
233
|
+
/**
|
|
234
|
+
* Serialize plugin options for safe JSON transport.
|
|
235
|
+
* Strips functions, symbols, and undefined values recursively.
|
|
236
|
+
*/
|
|
237
|
+
function serializePluginOptions(options) {
|
|
238
|
+
if (options === null || options === void 0) return {};
|
|
239
|
+
if (typeof options !== "object") return options;
|
|
240
|
+
if (Array.isArray(options)) return options.map(serializePluginOptions);
|
|
241
|
+
const serialized = {};
|
|
242
|
+
for (const [key, value] of Object.entries(options)) {
|
|
243
|
+
if (typeof value === "function" || typeof value === "symbol" || value === void 0) continue;
|
|
244
|
+
if (typeof value === "object" && value !== null) serialized[key] = serializePluginOptions(value);
|
|
245
|
+
else serialized[key] = value;
|
|
246
|
+
}
|
|
247
|
+
return serialized;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
//#endregion
|
|
251
|
+
//#region src/utils/timeout.ts
|
|
252
|
+
async function timeout(ms) {
|
|
253
|
+
return new Promise((resolve$1) => {
|
|
254
|
+
const timeout$1 = setTimeout(() => {
|
|
255
|
+
resolve$1(timeout$1);
|
|
256
|
+
}, ms);
|
|
257
|
+
}).then((timeout$1) => {
|
|
258
|
+
clearTimeout(timeout$1);
|
|
259
|
+
return true;
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
//#endregion
|
|
264
|
+
export { AsyncEventEmitter, Cache, FunctionParams, URLPath, buildJSDoc, executeIfOnline, formatHrtime, formatMs, getBarrelFiles, getElapsedMs, getNestedAccessor, getUniqueName, isOnline, isPromise, isPromiseFulfilledResult, isPromiseRejectedResult, renderTemplate, resolveModuleSource, serializePluginOptions, setUniqueName, timeout };
|
|
265
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","names":["#buffer","#items","#orderItems","#addParams","item","timeout"],"sources":["../src/utils/buildJSDoc.ts","../src/utils/Cache.ts","../src/utils/checkOnlineStatus.ts","../src/utils/FunctionParams.ts","../src/utils/getNestedAccessor.ts","../src/utils/promise.ts","../src/utils/renderTemplate.ts","../src/utils/resolveModuleSource.ts","../src/utils/serializePluginOptions.ts","../src/utils/timeout.ts"],"sourcesContent":["/**\n * Builds a JSDoc comment block with custom indentation.\n * @param comments - Array of comment strings to include in the JSDoc block\n * @param options - Configuration options for formatting\n * @returns Formatted JSDoc string or fallback string if no comments\n */\nexport function buildJSDoc(\n comments: Array<string>,\n options: {\n /**\n * String to use for indenting each line of the JSDoc comment\n * @default ' * ' (3 spaces + asterisk + space)\n */\n indent?: string\n /**\n * String to append after the closing JSDoc tag\n * @default '\\n ' (newline + 2 spaces)\n */\n suffix?: string\n /**\n * String to return when there are no comments\n * @default ' ' (2 spaces)\n */\n fallback?: string\n } = {},\n): string {\n const { indent = ' * ', suffix = '\\n ', fallback = ' ' } = options\n\n if (comments.length === 0) {\n return fallback\n }\n\n return `/**\\n${comments.map((c) => `${indent}${c}`).join('\\n')}\\n */${suffix}`\n}\n","export class Cache<T> {\n #buffer = new Map<string, T>()\n\n async get(key: string): Promise<T | null> {\n return this.#buffer.get(key) ?? null\n }\n\n async set(key: string, value: T): Promise<void> {\n this.#buffer.set(key, value)\n }\n\n async delete(key: string): Promise<void> {\n this.#buffer.delete(key)\n }\n\n async clear(): Promise<void> {\n this.#buffer.clear()\n }\n\n async keys(): Promise<string[]> {\n return [...this.#buffer.keys()]\n }\n\n async values(): Promise<T[]> {\n return [...this.#buffer.values()]\n }\n\n async flush(): Promise<void> {\n // No-op for base cache\n }\n}\n","import dns from 'node:dns'\n\n/**\n * Check if the system has internet connectivity\n * Uses DNS lookup to well-known stable domains as a lightweight connectivity test\n */\nexport async function isOnline(): Promise<boolean> {\n const testDomains = [\n 'dns.google.com', // Google Public DNS\n 'cloudflare.com', // Cloudflare\n 'one.one.one.one', // Cloudflare DNS\n ]\n\n for (const domain of testDomains) {\n try {\n await dns.promises.resolve(domain)\n return true\n } catch {\n // Try next domain\n }\n }\n\n return false\n}\n\n/**\n * Execute a function only if online, otherwise silently skip\n */\nexport async function executeIfOnline<T>(fn: () => Promise<T>): Promise<T | null> {\n const online = await isOnline()\n if (!online) {\n return null\n }\n\n try {\n return await fn()\n } catch {\n return null\n }\n}\n","import { orderBy } from 'natural-orderby'\n\nimport { camelCase } from '../transformers/casing.ts'\n\ntype FunctionParamsASTWithoutType = {\n name?: string\n type?: string\n /**\n * @default true\n */\n required?: boolean\n /**\n * @default true\n */\n enabled?: boolean\n default?: string\n}\n\ntype FunctionParamsASTWithType = {\n name?: never\n type: string\n /**\n * @default true\n */\n required?: boolean\n /**\n * @default true\n */\n enabled?: boolean\n default?: string\n}\n/**\n * @deprecated\n */\nexport type FunctionParamsAST = FunctionParamsASTWithoutType | FunctionParamsASTWithType\n\n/**\n * @deprecated\n */\nexport class FunctionParams {\n #items: Array<FunctionParamsAST | FunctionParamsAST[]> = []\n constructor() {\n return this\n }\n\n get items(): FunctionParamsAST[] {\n return this.#items.flat()\n }\n\n add(item: FunctionParamsAST | Array<FunctionParamsAST | FunctionParamsAST[] | undefined> | undefined): FunctionParams {\n if (!item) {\n return this\n }\n\n if (Array.isArray(item)) {\n item.filter(Boolean).forEach((it) => {\n this.#items.push(it)\n })\n return this\n }\n this.#items.push(item)\n\n return this\n }\n static #orderItems(items: Array<FunctionParamsAST | FunctionParamsAST[]>) {\n return orderBy(\n items.filter(Boolean),\n [\n (v) => {\n if (Array.isArray(v)) {\n return undefined\n }\n return !v.default\n },\n (v) => {\n if (Array.isArray(v)) {\n return undefined\n }\n return v.required ?? true\n },\n ],\n ['desc', 'desc'],\n )\n }\n\n static #addParams(acc: string[], item: FunctionParamsAST) {\n const { enabled = true, name, type, required = true, ...rest } = item\n\n if (!enabled) {\n return acc\n }\n\n if (!name) {\n // when name is not se we uses TypeScript generics\n acc.push(`${type}${rest.default ? ` = ${rest.default}` : ''}`)\n\n return acc\n }\n // TODO check whey we still need the camelcase here\n const parameterName = name.startsWith('{') ? name : camelCase(name)\n\n if (type) {\n if (required) {\n acc.push(`${parameterName}: ${type}${rest.default ? ` = ${rest.default}` : ''}`)\n } else {\n acc.push(`${parameterName}?: ${type}`)\n }\n } else {\n acc.push(`${parameterName}`)\n }\n\n return acc\n }\n\n static toObject(items: FunctionParamsAST[]): FunctionParamsAST {\n let type: string[] = []\n let name: string[] = []\n\n const enabled = items.every((item) => item.enabled) ? items.at(0)?.enabled : true\n const required = items.every((item) => item.required) ?? true\n\n items.forEach((item) => {\n name = FunctionParams.#addParams(name, { ...item, type: undefined })\n if (items.some((item) => item.type)) {\n type = FunctionParams.#addParams(type, item)\n }\n })\n\n return {\n name: `{ ${name.join(', ')} }`,\n type: type.length ? `{ ${type.join('; ')} }` : undefined,\n enabled,\n required,\n }\n }\n\n toObject(): FunctionParamsAST {\n const items = FunctionParams.#orderItems(this.#items).flat()\n\n return FunctionParams.toObject(items)\n }\n\n static toString(items: (FunctionParamsAST | FunctionParamsAST[])[]): string {\n const sortedData = FunctionParams.#orderItems(items)\n\n return sortedData\n .reduce((acc, item) => {\n if (Array.isArray(item)) {\n if (item.length <= 0) {\n return acc\n }\n const subItems = FunctionParams.#orderItems(item) as FunctionParamsAST[]\n const objectItem = FunctionParams.toObject(subItems)\n\n return FunctionParams.#addParams(acc, objectItem)\n }\n\n return FunctionParams.#addParams(acc, item)\n }, [] as string[])\n .join(', ')\n }\n\n toString(): string {\n const items = FunctionParams.#orderItems(this.#items)\n\n return FunctionParams.toString(items)\n }\n}\n","/**\n * Converts a param path (string with dot notation or array of strings) to a JavaScript accessor expression.\n * @param param - The param path, e.g., 'pagination.next.id' or ['pagination', 'next', 'id']\n * @param accessor - The base accessor, e.g., 'lastPage' or 'firstPage'\n * @returns A JavaScript accessor expression, e.g., \"lastPage?.['pagination']?.['next']?.['id']\", or undefined if param is empty\n *\n * @example\n * ```ts\n * getNestedAccessor('pagination.next.id', 'lastPage')\n * // returns: \"lastPage?.['pagination']?.['next']?.['id']\"\n *\n * getNestedAccessor(['pagination', 'next', 'id'], 'lastPage')\n * // returns: \"lastPage?.['pagination']?.['next']?.['id']\"\n *\n * getNestedAccessor('', 'lastPage')\n * // returns: undefined\n * ```\n */\nexport function getNestedAccessor(param: string | string[], accessor: string): string | undefined {\n const parts = Array.isArray(param) ? param : param.split('.')\n if (parts.length === 0 || (parts.length === 1 && parts[0] === '')) {\n return undefined\n }\n return parts.reduce((acc, part) => `${acc}?.['${part}']`, accessor)\n}\n","import type { PossiblePromise } from './types.ts'\n\nexport function isPromise<T>(result: PossiblePromise<T>): result is Promise<T> {\n return !!result && typeof (result as Promise<unknown>)?.then === 'function'\n}\n\nexport function isPromiseFulfilledResult<T = unknown>(result: PromiseSettledResult<unknown>): result is PromiseFulfilledResult<T> {\n return result.status === 'fulfilled'\n}\n\nexport function isPromiseRejectedResult<T>(result: PromiseSettledResult<unknown>): result is Omit<PromiseRejectedResult, 'reason'> & { reason: T } {\n return result.status === 'rejected'\n}\n","export function renderTemplate<TData extends Record<string, unknown> = Record<string, unknown>>(template: string, data: TData | undefined = undefined): string {\n if (!data || !Object.keys(data).length) {\n return template.replace(/{{(.*?)}}/g, '')\n }\n\n const matches = template.match(/{{(.*?)}}/g)\n\n return (\n matches?.reduce((prev, curr) => {\n const index = curr.split(/{{|}}/).filter(Boolean)[0]?.trim()\n if (index === undefined) {\n return prev\n }\n const value = data[index]\n\n if (value === undefined) {\n return prev\n }\n\n return prev\n .replace(curr, () => {\n if (typeof value === 'boolean') {\n return `${value.toString()}` || 'false'\n }\n\n return (value as string) || ''\n })\n .trim()\n }, template) || ''\n )\n}\n","import { readFileSync } from 'node:fs'\nimport path from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport createJiti from 'jiti'\n\nexport function resolveModuleSource(pkgName: string) {\n const parentURL = import.meta.url\n const jiti = createJiti(parentURL)\n\n const resolved = jiti.esmResolve(pkgName, parentURL)\n const filePath = resolved.startsWith('file:') ? fileURLToPath(resolved) : resolved\n const source = readFileSync(filePath, { encoding: 'utf-8' })\n const ext = path.extname(filePath)\n return { path: filePath, source, ext } as const\n}\n","/**\n * Serialize plugin options for safe JSON transport.\n * Strips functions, symbols, and undefined values recursively.\n */\nexport function serializePluginOptions(options: unknown): unknown {\n if (options === null || options === undefined) {\n return {}\n }\n if (typeof options !== 'object') {\n return options\n }\n if (Array.isArray(options)) {\n return options.map(serializePluginOptions)\n }\n\n const serialized: Record<string, unknown> = {}\n for (const [key, value] of Object.entries(options)) {\n if (typeof value === 'function' || typeof value === 'symbol' || value === undefined) {\n continue\n }\n if (typeof value === 'object' && value !== null) {\n serialized[key] = serializePluginOptions(value)\n } else {\n serialized[key] = value\n }\n }\n return serialized\n}\n","export async function timeout(ms: number): Promise<unknown> {\n return new Promise((resolve) => {\n const timeout = setTimeout(() => {\n resolve(timeout)\n }, ms)\n }).then((timeout) => {\n clearTimeout(timeout as NodeJS.Timeout)\n\n return true\n })\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -7,7 +7,6 @@ export { PackageManager } from './PackageManager.ts'
|
|
|
7
7
|
export { getMode, PluginManager } from './PluginManager.ts'
|
|
8
8
|
export { PromiseManager } from './PromiseManager.ts'
|
|
9
9
|
export type { HealthResponse, InfoResponse, ServerEvents, SseEvent, SseEvents, SseEventType } from './server/index.ts'
|
|
10
|
-
export { startServer } from './server/index.ts'
|
|
11
10
|
export * from './types.ts'
|
|
12
11
|
export type { FileMetaBase } from './utils/getBarrelFiles.ts'
|
|
13
12
|
export { getBarrelFiles } from './utils/getBarrelFiles.ts'
|
package/src/server/index.ts
CHANGED
|
@@ -1,11 +1,5 @@
|
|
|
1
|
-
import { readFileSync } from 'node:fs'
|
|
2
|
-
import type { IncomingMessage, Server, ServerResponse } from 'node:http'
|
|
3
|
-
import { createServer } from 'node:http'
|
|
4
|
-
import path from 'node:path'
|
|
5
|
-
import process from 'node:process'
|
|
6
1
|
import type { KubbFile } from '@kubb/fabric-core/types'
|
|
7
2
|
import type { Config, KubbEvents } from '../types.ts'
|
|
8
|
-
import { type AsyncEventEmitter, serializePluginOptions } from '../utils/index.ts'
|
|
9
3
|
|
|
10
4
|
/**
|
|
11
5
|
* Typed SSE events sent by the Kubb server.
|
|
@@ -76,8 +70,9 @@ export type InfoResponse = {
|
|
|
76
70
|
}>
|
|
77
71
|
}
|
|
78
72
|
}
|
|
73
|
+
|
|
79
74
|
/**
|
|
80
|
-
* Same events
|
|
75
|
+
* Same events as KubbEvents but with server lifecycle events
|
|
81
76
|
*/
|
|
82
77
|
export type ServerEvents = KubbEvents & {
|
|
83
78
|
/**
|
|
@@ -93,189 +88,3 @@ export type ServerEvents = KubbEvents & {
|
|
|
93
88
|
*/
|
|
94
89
|
'server:stopped': []
|
|
95
90
|
}
|
|
96
|
-
|
|
97
|
-
type ServerOptions = {
|
|
98
|
-
port: number
|
|
99
|
-
host: string
|
|
100
|
-
configPath: string
|
|
101
|
-
config: Config
|
|
102
|
-
version: string
|
|
103
|
-
/**
|
|
104
|
-
* Event emitter for both server lifecycle and generation events
|
|
105
|
-
*/
|
|
106
|
-
events: AsyncEventEmitter<ServerEvents>
|
|
107
|
-
/**
|
|
108
|
-
* Callback to handle code generation
|
|
109
|
-
* Should use the events emitter to emit generation events
|
|
110
|
-
*/
|
|
111
|
-
onGenerate: () => Promise<void>
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
export async function startServer({ port, host, configPath, config, version, events, onGenerate }: ServerOptions): Promise<Server> {
|
|
115
|
-
const server = createServer(async (req: IncomingMessage, res: ServerResponse) => {
|
|
116
|
-
// Helper to send SSE events
|
|
117
|
-
function send<T extends SseEventType>(type: T, ...data: SseEvents[T]) {
|
|
118
|
-
const event: SseEvent = { type, data, timestamp: Date.now() }
|
|
119
|
-
|
|
120
|
-
res.write(`data: ${JSON.stringify(event)}\n\n`)
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
// Forward specific events to SSE stream with proper transformations
|
|
124
|
-
events.on('plugin:start', (plugin) => send('plugin:start', plugin))
|
|
125
|
-
events.on('plugin:end', (plugin, meta) => send('plugin:end', plugin, meta))
|
|
126
|
-
|
|
127
|
-
// Transform files:processing events to match StreamEvents format
|
|
128
|
-
events.on('files:processing:start', (files) => send('files:processing:start', { total: files.length }))
|
|
129
|
-
events.on('file:processing:update', (meta) => {
|
|
130
|
-
send('file:processing:update', {
|
|
131
|
-
file: meta.file.path,
|
|
132
|
-
processed: meta.processed,
|
|
133
|
-
total: meta.total,
|
|
134
|
-
percentage: meta.percentage,
|
|
135
|
-
})
|
|
136
|
-
})
|
|
137
|
-
events.on('files:processing:end', (files) => send('files:processing:end', { total: files.length }))
|
|
138
|
-
|
|
139
|
-
// Simple passthrough events
|
|
140
|
-
events.on('info', (message, info) => send('info', message, info))
|
|
141
|
-
events.on('success', (message, info) => send('success', message, info))
|
|
142
|
-
events.on('warn', (message, info) => send('warn', message, info))
|
|
143
|
-
|
|
144
|
-
// Transform generation events to match StreamEvents format
|
|
145
|
-
events.on('generation:start', (config) => {
|
|
146
|
-
send('generation:start', {
|
|
147
|
-
name: config.name,
|
|
148
|
-
plugins: config.plugins?.length || 0,
|
|
149
|
-
})
|
|
150
|
-
})
|
|
151
|
-
events.on('generation:end', (config, files, sources) => {
|
|
152
|
-
// Convert Map to Record for JSON serialization
|
|
153
|
-
const sourcesRecord: Record<string, string> = {}
|
|
154
|
-
sources.forEach((value, key) => {
|
|
155
|
-
sourcesRecord[key] = value
|
|
156
|
-
})
|
|
157
|
-
send('generation:end', config, files, sourcesRecord)
|
|
158
|
-
})
|
|
159
|
-
|
|
160
|
-
// Special handling for error events
|
|
161
|
-
events.on('error', (error: Error) => {
|
|
162
|
-
send('error', {
|
|
163
|
-
message: error.message,
|
|
164
|
-
stack: error.stack,
|
|
165
|
-
})
|
|
166
|
-
})
|
|
167
|
-
|
|
168
|
-
// CORS headers
|
|
169
|
-
res.setHeader('Access-Control-Allow-Origin', '*')
|
|
170
|
-
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS')
|
|
171
|
-
res.setHeader('Access-Control-Allow-Headers', 'Content-Type')
|
|
172
|
-
|
|
173
|
-
if (req.method === 'OPTIONS') {
|
|
174
|
-
res.writeHead(204)
|
|
175
|
-
res.end()
|
|
176
|
-
return
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// Health check endpoint
|
|
180
|
-
if (req.url === '/api/health' && req.method === 'GET') {
|
|
181
|
-
res.writeHead(200, { 'Content-Type': 'application/json' })
|
|
182
|
-
const body: HealthResponse = { status: 'ok', version, configPath: path.relative(process.cwd(), configPath) }
|
|
183
|
-
|
|
184
|
-
res.end(JSON.stringify(body))
|
|
185
|
-
|
|
186
|
-
return
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
// Connect endpoint - returns config metadata and OpenAPI spec
|
|
190
|
-
if (req.url === '/api/info' && req.method === 'GET') {
|
|
191
|
-
res.writeHead(200, { 'Content-Type': 'application/json' })
|
|
192
|
-
|
|
193
|
-
// Read OpenAPI spec if available
|
|
194
|
-
let specContent: string | undefined
|
|
195
|
-
if (config && 'path' in config.input) {
|
|
196
|
-
const specPath = path.resolve(process.cwd(), config.root, config.input.path)
|
|
197
|
-
try {
|
|
198
|
-
specContent = readFileSync(specPath, 'utf-8')
|
|
199
|
-
} catch {
|
|
200
|
-
// Spec file not found or unreadable
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
const body: InfoResponse = {
|
|
205
|
-
version,
|
|
206
|
-
configPath: path.relative(process.cwd(), configPath),
|
|
207
|
-
spec: specContent,
|
|
208
|
-
config: {
|
|
209
|
-
name: config.name,
|
|
210
|
-
root: config.root,
|
|
211
|
-
input: {
|
|
212
|
-
path: 'path' in config.input ? config.input.path : undefined,
|
|
213
|
-
},
|
|
214
|
-
output: {
|
|
215
|
-
path: config.output.path,
|
|
216
|
-
write: config.output.write,
|
|
217
|
-
extension: config.output.extension,
|
|
218
|
-
barrelType: config.output.barrelType,
|
|
219
|
-
},
|
|
220
|
-
plugins: config.plugins?.map((plugin) => ({
|
|
221
|
-
name: `@kubb/${plugin.name}`,
|
|
222
|
-
options: serializePluginOptions(plugin.options),
|
|
223
|
-
})),
|
|
224
|
-
},
|
|
225
|
-
}
|
|
226
|
-
|
|
227
|
-
res.end(JSON.stringify(body))
|
|
228
|
-
return
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
// Generate endpoint
|
|
232
|
-
if (req.url === '/api/generate' && req.method === 'POST') {
|
|
233
|
-
try {
|
|
234
|
-
// Set SSE headers
|
|
235
|
-
res.writeHead(200, {
|
|
236
|
-
'Content-Type': 'text/event-stream',
|
|
237
|
-
'Cache-Control': 'no-cache',
|
|
238
|
-
Connection: 'keep-alive',
|
|
239
|
-
})
|
|
240
|
-
|
|
241
|
-
await onGenerate()
|
|
242
|
-
} catch (error) {
|
|
243
|
-
send('error', {
|
|
244
|
-
message: error instanceof Error ? error.message : 'Unknown error',
|
|
245
|
-
stack: error instanceof Error ? error.stack : undefined,
|
|
246
|
-
})
|
|
247
|
-
} finally {
|
|
248
|
-
send('lifecycle:end')
|
|
249
|
-
|
|
250
|
-
res.end()
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
return
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
// 404 for other routes
|
|
257
|
-
res.writeHead(404, { 'Content-Type': 'application/json' })
|
|
258
|
-
res.end(JSON.stringify({ error: 'Not found' }))
|
|
259
|
-
})
|
|
260
|
-
|
|
261
|
-
return new Promise((resolve) => {
|
|
262
|
-
server.listen(port, host, () => {
|
|
263
|
-
const address = server.address()
|
|
264
|
-
const actualPort = typeof address === 'object' && address ? address.port : port
|
|
265
|
-
const serverUrl = `http://${host}:${actualPort}`
|
|
266
|
-
|
|
267
|
-
events.emit('server:start', serverUrl, path.relative(process.cwd(), configPath))
|
|
268
|
-
|
|
269
|
-
resolve(server)
|
|
270
|
-
})
|
|
271
|
-
|
|
272
|
-
// Graceful shutdown
|
|
273
|
-
process.on('SIGINT', () => {
|
|
274
|
-
events.emit('server:shutdown')
|
|
275
|
-
server.close(() => {
|
|
276
|
-
events.emit('server:stopped')
|
|
277
|
-
process.exit(0)
|
|
278
|
-
})
|
|
279
|
-
})
|
|
280
|
-
})
|
|
281
|
-
}
|
package/src/types.ts
CHANGED
|
@@ -392,4 +392,92 @@ export type Logger<TOptions extends LoggerOptions = LoggerOptions> = {
|
|
|
392
392
|
|
|
393
393
|
export type UserLogger<TOptions extends LoggerOptions = LoggerOptions> = Omit<Logger<TOptions>, 'logLevel'>
|
|
394
394
|
|
|
395
|
+
/**
|
|
396
|
+
* Typed SSE events sent by the Kubb server.
|
|
397
|
+
* Follows the same tuple structure as {@link KubbEvents}.
|
|
398
|
+
* Reusable in consumers like kubb-playground to parse incoming events.
|
|
399
|
+
*/
|
|
400
|
+
export interface SseEvents {
|
|
401
|
+
'plugin:start': [plugin: { name: string }]
|
|
402
|
+
'plugin:end': [plugin: { name: string }, meta: { duration: number; success: boolean }]
|
|
403
|
+
'files:processing:start': [meta: { total: number }]
|
|
404
|
+
'file:processing:update': [
|
|
405
|
+
meta: {
|
|
406
|
+
file: string
|
|
407
|
+
processed: number
|
|
408
|
+
total: number
|
|
409
|
+
percentage: number
|
|
410
|
+
},
|
|
411
|
+
]
|
|
412
|
+
'files:processing:end': [meta: { total: number }]
|
|
413
|
+
info: [message: string, info?: string]
|
|
414
|
+
success: [message: string, info?: string]
|
|
415
|
+
warn: [message: string, info?: string]
|
|
416
|
+
error: [error: { message: string; stack?: string }]
|
|
417
|
+
'generation:start': [config: { name?: string; plugins: number }]
|
|
418
|
+
'generation:end': [Config: Config, files: Array<KubbFile.ResolvedFile>, sources: Record<KubbFile.Path, string>]
|
|
419
|
+
'lifecycle:end': []
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
export type SseEventType = keyof SseEvents
|
|
423
|
+
|
|
424
|
+
export type SseEvent<T extends SseEventType = SseEventType> = {
|
|
425
|
+
type: T
|
|
426
|
+
data: SseEvents[T]
|
|
427
|
+
timestamp: number
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
/**
|
|
431
|
+
* API response types for the Kubb stream server endpoints.
|
|
432
|
+
*/
|
|
433
|
+
|
|
434
|
+
/** GET /api/health */
|
|
435
|
+
export type HealthResponse = {
|
|
436
|
+
status: 'ok'
|
|
437
|
+
version: string
|
|
438
|
+
configPath: string
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
/** GET /api/info */
|
|
442
|
+
export type InfoResponse = {
|
|
443
|
+
version: string
|
|
444
|
+
configPath: string
|
|
445
|
+
spec?: string
|
|
446
|
+
config: {
|
|
447
|
+
name?: string
|
|
448
|
+
root: string
|
|
449
|
+
input: {
|
|
450
|
+
path?: string
|
|
451
|
+
}
|
|
452
|
+
output: {
|
|
453
|
+
path: string
|
|
454
|
+
write?: boolean
|
|
455
|
+
extension?: Record<string, string>
|
|
456
|
+
barrelType?: string | false
|
|
457
|
+
}
|
|
458
|
+
plugins?: Array<{
|
|
459
|
+
name: string
|
|
460
|
+
options: unknown
|
|
461
|
+
}>
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* Same events as KubbEvents but with server lifecycle events
|
|
467
|
+
*/
|
|
468
|
+
export type ServerEvents = KubbEvents & {
|
|
469
|
+
/**
|
|
470
|
+
* Emitted when the server starts successfully
|
|
471
|
+
*/
|
|
472
|
+
'server:start': [serverUrl: string, configPath: string]
|
|
473
|
+
/**
|
|
474
|
+
* Emitted when the server is shutting down
|
|
475
|
+
*/
|
|
476
|
+
'server:shutdown': []
|
|
477
|
+
/**
|
|
478
|
+
* Emitted when the server has stopped
|
|
479
|
+
*/
|
|
480
|
+
'server:stopped': []
|
|
481
|
+
}
|
|
482
|
+
|
|
395
483
|
export type { KubbEvents } from './Kubb.ts'
|