@sidekick-coder/zenith-kit 0.0.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.
@@ -0,0 +1,72 @@
1
+ import { ChildProcess } from "node:child_process";
2
+
3
+ //#region src/server/services/PluginIpcClient.d.ts
4
+ type IpcMessage<T = any> = {
5
+ id: string;
6
+ event: string;
7
+ data: T;
8
+ };
9
+ type IpcListener$1<T = any> = (data: T) => void;
10
+ declare class PluginIpcClient {
11
+ private listeners;
12
+ private pending;
13
+ constructor();
14
+ on<T = any>(event: string, callback: IpcListener$1<T>): void;
15
+ off<T = any>(event: string, callback: IpcListener$1<T>): void;
16
+ emit<T = any>(event: string, data?: T): string;
17
+ emitAsync<TData = any, TReply = any>(event: string, data?: TData): Promise<TReply>;
18
+ }
19
+ //#endregion
20
+ //#region src/server/services/PluginIpcHost.d.ts
21
+ type IpcListener<T = any> = (data: T) => void;
22
+ declare class PluginIpcHost {
23
+ private readonly child;
24
+ private listeners;
25
+ private pending;
26
+ constructor(child: ChildProcess);
27
+ on<T = any>(event: string, callback: IpcListener<T>): void;
28
+ off<T = any>(event: string, callback: IpcListener<T>): void;
29
+ emit<T = any>(event: string, data?: T): string;
30
+ emitAsync<TData = any, TReply = any>(event: string, data?: TData): Promise<TReply>;
31
+ }
32
+ //#endregion
33
+ //#region src/server/services/PluginRouter.d.ts
34
+ type HttpMethod = 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE';
35
+ interface RouteDefinition {
36
+ method: HttpMethod;
37
+ path: string;
38
+ }
39
+ interface RouteRequest {
40
+ requestId: string;
41
+ method: HttpMethod;
42
+ path: string;
43
+ body?: any;
44
+ headers?: Record<string, string>;
45
+ query?: Record<string, string>;
46
+ params?: Record<string, string>;
47
+ }
48
+ interface RouteResponsePayload {
49
+ requestId: string;
50
+ status: number;
51
+ body?: any;
52
+ headers?: Record<string, string>;
53
+ }
54
+ interface RouteReply {
55
+ status(code: number): RouteReply;
56
+ send(body?: any): void;
57
+ }
58
+ type RouteHandler = (req: RouteRequest, reply: RouteReply) => void | Promise<void>;
59
+ declare class PluginRouter {
60
+ private readonly client;
61
+ private routes;
62
+ constructor(client: PluginIpcClient);
63
+ private dispatch;
64
+ private register;
65
+ get(path: string, handler: RouteHandler): void;
66
+ post(path: string, handler: RouteHandler): void;
67
+ put(path: string, handler: RouteHandler): void;
68
+ patch(path: string, handler: RouteHandler): void;
69
+ delete(path: string, handler: RouteHandler): void;
70
+ }
71
+ //#endregion
72
+ export { HttpMethod, IpcMessage, PluginIpcClient, PluginIpcHost, PluginRouter, RouteDefinition, RouteHandler, RouteReply, RouteRequest, RouteResponsePayload };
@@ -0,0 +1,185 @@
1
+ //#region src/shared/utils/createId.ts
2
+ function uuid() {
3
+ if (typeof crypto !== "undefined" && crypto.randomUUID) return crypto.randomUUID();
4
+ if (typeof self !== "undefined" && self.crypto && self.crypto.randomUUID) return self.crypto.randomUUID();
5
+ if (typeof window !== "undefined" && window.crypto && window.crypto.randomUUID) return window.crypto.randomUUID();
6
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
7
+ const r = Math.random() * 16 | 0;
8
+ return (c === "x" ? r : r & 3 | 8).toString(16);
9
+ });
10
+ }
11
+ function createId(prefix = "") {
12
+ return prefix + uuid();
13
+ }
14
+ //#endregion
15
+ //#region src/server/services/PluginIpcClient.ts
16
+ var PluginIpcClient = class {
17
+ listeners = /* @__PURE__ */ new Map();
18
+ pending = /* @__PURE__ */ new Map();
19
+ constructor() {
20
+ process.on("message", (message) => {
21
+ if (this.pending.has(message.id)) {
22
+ this.pending.get(message.id)(message.data);
23
+ this.pending.delete(message.id);
24
+ }
25
+ const handlers = this.listeners.get(message.event);
26
+ if (!handlers) return;
27
+ for (const handler of handlers) handler(message.data);
28
+ });
29
+ }
30
+ on(event, callback) {
31
+ if (!this.listeners.has(event)) this.listeners.set(event, /* @__PURE__ */ new Set());
32
+ this.listeners.get(event).add(callback);
33
+ }
34
+ off(event, callback) {
35
+ this.listeners.get(event)?.delete(callback);
36
+ }
37
+ emit(event, data) {
38
+ if (!process.send) throw new Error("PluginIpcClient.emit: process.send is not available — process was not spawned with IPC channel");
39
+ const id = createId();
40
+ const message = {
41
+ id,
42
+ event,
43
+ data
44
+ };
45
+ process.send(message);
46
+ return id;
47
+ }
48
+ emitAsync(event, data) {
49
+ return new Promise((resolve) => {
50
+ const id = this.emit(event, data);
51
+ this.pending.set(id, resolve);
52
+ });
53
+ }
54
+ };
55
+ //#endregion
56
+ //#region src/server/services/PluginIpcHost.ts
57
+ var PluginIpcHost = class {
58
+ listeners = /* @__PURE__ */ new Map();
59
+ pending = /* @__PURE__ */ new Map();
60
+ constructor(child) {
61
+ this.child = child;
62
+ this.child.on("message", (message) => {
63
+ if (this.pending.has(message.id)) {
64
+ this.pending.get(message.id)(message.data);
65
+ this.pending.delete(message.id);
66
+ }
67
+ const handlers = this.listeners.get(message.event);
68
+ if (!handlers) return;
69
+ for (const handler of handlers) handler(message.data);
70
+ });
71
+ }
72
+ on(event, callback) {
73
+ if (!this.listeners.has(event)) this.listeners.set(event, /* @__PURE__ */ new Set());
74
+ this.listeners.get(event).add(callback);
75
+ }
76
+ off(event, callback) {
77
+ this.listeners.get(event)?.delete(callback);
78
+ }
79
+ emit(event, data) {
80
+ if (!this.child.send) throw new Error("PluginIpcHost.emit: child process was not spawned with an IPC channel");
81
+ const id = createId();
82
+ const message = {
83
+ id,
84
+ event,
85
+ data
86
+ };
87
+ this.child.send(message);
88
+ return id;
89
+ }
90
+ emitAsync(event, data) {
91
+ return new Promise((resolve) => {
92
+ const id = this.emit(event, data);
93
+ this.pending.set(id, resolve);
94
+ });
95
+ }
96
+ };
97
+ //#endregion
98
+ //#region src/server/services/PluginRouter.ts
99
+ function buildPattern(path) {
100
+ const paramNames = [];
101
+ const regexStr = path.replace(/:[a-zA-Z_][a-zA-Z0-9_]*/g, (match) => {
102
+ paramNames.push(match.slice(1));
103
+ return "([^/]+)";
104
+ }).replace(/\//g, "\\/");
105
+ return {
106
+ pattern: new RegExp(`^${regexStr}$`),
107
+ paramNames
108
+ };
109
+ }
110
+ var PluginRouter = class {
111
+ routes = [];
112
+ constructor(client) {
113
+ this.client = client;
114
+ this.client.on("router:request", (req) => this.dispatch(req));
115
+ }
116
+ async dispatch(req) {
117
+ for (const route of this.routes) {
118
+ if (route.method !== req.method) continue;
119
+ const match = route.pattern.exec(req.path);
120
+ if (!match) continue;
121
+ const params = {};
122
+ route.paramNames.forEach((name, i) => {
123
+ params[name] = match[i + 1];
124
+ });
125
+ let statusCode = 200;
126
+ const headers = {};
127
+ const reply = {
128
+ status(code) {
129
+ statusCode = code;
130
+ return this;
131
+ },
132
+ send: (body) => {
133
+ const response = {
134
+ requestId: req.requestId,
135
+ status: statusCode,
136
+ body,
137
+ headers
138
+ };
139
+ this.client.emit("router:response", response);
140
+ }
141
+ };
142
+ await route.handler({
143
+ ...req,
144
+ params
145
+ }, reply);
146
+ return;
147
+ }
148
+ this.client.emit("router:response", {
149
+ requestId: req.requestId,
150
+ status: 404,
151
+ body: { message: "Not Found" }
152
+ });
153
+ }
154
+ register(method, path, handler) {
155
+ const { pattern, paramNames } = buildPattern(path);
156
+ this.routes.push({
157
+ method,
158
+ path,
159
+ handler,
160
+ pattern,
161
+ paramNames
162
+ });
163
+ this.client.emit("router:register", {
164
+ method,
165
+ path
166
+ });
167
+ }
168
+ get(path, handler) {
169
+ this.register("GET", path, handler);
170
+ }
171
+ post(path, handler) {
172
+ this.register("POST", path, handler);
173
+ }
174
+ put(path, handler) {
175
+ this.register("PUT", path, handler);
176
+ }
177
+ patch(path, handler) {
178
+ this.register("PATCH", path, handler);
179
+ }
180
+ delete(path, handler) {
181
+ this.register("DELETE", path, handler);
182
+ }
183
+ };
184
+ //#endregion
185
+ export { PluginIpcClient, PluginIpcHost, PluginRouter };
@@ -0,0 +1,107 @@
1
+ import * as v from "valibot";
2
+
3
+ //#region src/shared/services/LoggerService.d.ts
4
+ declare class LoggerService {
5
+ info(message: string, meta?: any): void;
6
+ debug(message: string, meta?: any): void;
7
+ warn(message: string, meta?: any): void;
8
+ error(message: string, meta?: any): void;
9
+ child(options: any): LoggerService;
10
+ }
11
+ //#endregion
12
+ //#region src/shared/services/EmmitterService.d.ts
13
+ interface EmmitterServiceOptions {
14
+ debug?: boolean;
15
+ logger?: LoggerService;
16
+ }
17
+ //#endregion
18
+ //#region src/shared/utils/typing.d.ts
19
+ type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends ((k: infer I) => void) ? I : never;
20
+ type PartialBy<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
21
+ type PublicData<T> = { [K in keyof T as T[K] extends Function ? never : K]: T[K] };
22
+ //#endregion
23
+ //#region src/shared/utils/compose.d.ts
24
+ type AnyClass = new (...args: any[]) => any;
25
+ type Constructor<T = {}> = new (...args: any[]) => T;
26
+ type Mixin<T> = (base: Constructor) => Constructor<T>;
27
+ /**
28
+ * Composes multiple mixins into a single class that can be extended.
29
+ * Allows for multiple inheritance-like behavior by applying mixins sequentially.
30
+ *
31
+ * @param mixins - Array of mixin functions to compose
32
+ * @returns A class constructor that includes all mixin functionality
33
+ *
34
+ * @example
35
+ * ```typescript
36
+ * class User extends compose(Timestamp, SoftDelete) {
37
+ * constructor(public name: string) {
38
+ * super()
39
+ * }
40
+ * }
41
+ * ```
42
+ */
43
+ declare function compose<M extends Array<(base: Constructor<any>) => Constructor<any>>>(...mixins: M): UnionToIntersection<ReturnType<M[number]>>;
44
+ /**
45
+ * Alternative compose function that starts with a base class
46
+ *
47
+ * @param baseClass - The base class to start with
48
+ * @param mixins - Array of mixin functions to apply
49
+ * @returns A class constructor that extends the base class with all mixin functionality
50
+ *
51
+ * @example
52
+ * ```typescript
53
+ * class User extends composeWith(BaseEntity, Timestamp, SoftDelete) {
54
+ * constructor(public name: string) {
55
+ * super()
56
+ * }
57
+ * }
58
+ * ```
59
+ */
60
+ declare function composeWith<TBase extends Constructor, M extends Array<(base: Constructor) => Constructor<any>>>(baseClass: TBase, ...mixins: M): TBase & UnionToIntersection<ReturnType<M[number]>>;
61
+ declare function mixin<TBase extends Constructor>(Source: TBase): <TTarget extends Constructor>(Target: TTarget) => TTarget & TBase;
62
+ //#endregion
63
+ //#region src/shared/services/ValidatorService.d.ts
64
+ type Valibot = typeof v;
65
+ type ValibotSchema = v.BaseSchema<unknown, unknown, v.BaseIssue<unknown>>;
66
+ type ValibotSchemaAsync = v.BaseSchemaAsync<unknown, unknown, v.BaseIssue<unknown>>;
67
+ interface ValidatorCallback<T extends ValibotSchema> {
68
+ (_v: typeof v): T;
69
+ }
70
+ type ValidatorCallbackAsync<T extends ValibotSchemaAsync> = {
71
+ (_v: typeof v): T;
72
+ };
73
+ type ValidatorResult<T extends v.ObjectEntries> = v.InferOutput<v.ObjectSchema<T, undefined>>;
74
+ type ValidatePayload<T extends ValibotSchema = ValibotSchema> = ValidatorCallback<T> | T;
75
+ type ValidateResult<T extends ValidatePayload> = T extends ValibotSchema ? v.InferOutput<T> : T extends ValidatorCallback<infer U> ? v.InferOutput<U> : unknown;
76
+ declare class ValidatorService {
77
+ create<T extends ValibotSchema>(cb: ValidatorCallback<T>): T;
78
+ validate<T extends ValibotSchema>(payload: any, cb: ValidatePayload<T>): v.InferOutput<T>;
79
+ validateAsync<T extends ValibotSchemaAsync>(payload: any, cb: ValidatorCallbackAsync<T> | T): Promise<v.InferOutput<T>>;
80
+ isValid<T extends ValibotSchema>(payload: any, cb: ValidatePayload<T>): boolean;
81
+ }
82
+ //#endregion
83
+ //#region src/shared/utils/createId.d.ts
84
+ declare function createId(prefix?: string): string;
85
+ //#endregion
86
+ //#region src/shared/utils/flatten.d.ts
87
+ declare function flatten(obj: any, prefix?: string, res?: any): Record<string, any>;
88
+ declare function unflatten(obj: any): Record<string, any>;
89
+ //#endregion
90
+ //#region src/shared/utils/formatBytes.d.ts
91
+ declare function formatBytes(bytes: number, decimals?: number): string;
92
+ //#endregion
93
+ //#region src/shared/utils/tryCatch.d.ts
94
+ interface Tryer {
95
+ (...args: any[]): any;
96
+ }
97
+ interface TryerAsync {
98
+ (...args: any[]): Promise<any> | any;
99
+ }
100
+ type TryCatchResult<T extends Tryer> = [null, ReturnType<T>] | [Error, null];
101
+ type TryCatchAsyncResult<T extends TryerAsync> = [null, Awaited<ReturnType<T>>] | [Error, null];
102
+ declare function tryCatch<T extends TryerAsync>(tryer: T): Promise<TryCatchAsyncResult<T>>;
103
+ declare namespace tryCatch {
104
+ var sync: <T extends Tryer>(tryer: T) => TryCatchResult<T>;
105
+ }
106
+ //#endregion
107
+ export { AnyClass, Constructor, EmmitterServiceOptions, Mixin, PartialBy, PublicData, UnionToIntersection, Valibot, ValibotSchema, ValibotSchemaAsync, ValidatePayload, ValidateResult, ValidatorCallback, ValidatorCallbackAsync, ValidatorResult, ValidatorService, compose, composeWith, createId, flatten, formatBytes, mixin, tryCatch, unflatten };
@@ -0,0 +1,187 @@
1
+ import "lodash-es";
2
+ import * as v from "valibot";
3
+ //#region src/shared/utils/compose.ts
4
+ /**
5
+ * Composes multiple mixins into a single class that can be extended.
6
+ * Allows for multiple inheritance-like behavior by applying mixins sequentially.
7
+ *
8
+ * @param mixins - Array of mixin functions to compose
9
+ * @returns A class constructor that includes all mixin functionality
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * class User extends compose(Timestamp, SoftDelete) {
14
+ * constructor(public name: string) {
15
+ * super()
16
+ * }
17
+ * }
18
+ * ```
19
+ */
20
+ function compose(...mixins) {
21
+ return mixins.reduce((base, mixin) => mixin(base), class {});
22
+ }
23
+ /**
24
+ * Alternative compose function that starts with a base class
25
+ *
26
+ * @param baseClass - The base class to start with
27
+ * @param mixins - Array of mixin functions to apply
28
+ * @returns A class constructor that extends the base class with all mixin functionality
29
+ *
30
+ * @example
31
+ * ```typescript
32
+ * class User extends composeWith(BaseEntity, Timestamp, SoftDelete) {
33
+ * constructor(public name: string) {
34
+ * super()
35
+ * }
36
+ * }
37
+ * ```
38
+ */
39
+ function composeWith(baseClass, ...mixins) {
40
+ return mixins.reduce((base, mixin) => mixin(base), baseClass);
41
+ }
42
+ function mixin(Source) {
43
+ return function(Target) {
44
+ class Mixed extends Target {
45
+ constructor(...args) {
46
+ super(...args);
47
+ const source = new Source(...args);
48
+ Object.assign(this, source);
49
+ }
50
+ }
51
+ for (const key of Reflect.ownKeys(Source.prototype)) if (key !== "constructor") Object.defineProperty(Mixed.prototype, key, Object.getOwnPropertyDescriptor(Source.prototype, key));
52
+ return Mixed;
53
+ };
54
+ }
55
+ //#endregion
56
+ //#region src/shared/utils/formatBytes.ts
57
+ function formatBytes(bytes, decimals = 2) {
58
+ if (bytes === 0) return "0 Bytes";
59
+ const k = 1024;
60
+ const dm = decimals < 0 ? 0 : decimals;
61
+ const sizes = [
62
+ "Bytes",
63
+ "KB",
64
+ "MB",
65
+ "GB",
66
+ "TB",
67
+ "PB"
68
+ ];
69
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
70
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + " " + sizes[i];
71
+ }
72
+ //#endregion
73
+ //#region src/shared/utils/flatten.ts
74
+ function flatten(obj, prefix = "", res = {}) {
75
+ for (const [key, value] of Object.entries(obj)) {
76
+ const newKey = prefix ? `${prefix}.${key}` : key;
77
+ if (value && typeof value === "object" && !Array.isArray(value)) flatten(value, newKey, res);
78
+ else res[newKey] = value;
79
+ }
80
+ return res;
81
+ }
82
+ function unflatten(obj) {
83
+ const result = {};
84
+ for (const [key, value] of Object.entries(obj)) {
85
+ const parts = key.split(".");
86
+ let current = result;
87
+ parts.forEach((part, i) => {
88
+ if (i === parts.length - 1) current[part] = value;
89
+ else {
90
+ if (!current[part] || typeof current[part] !== "object") current[part] = {};
91
+ current = current[part];
92
+ }
93
+ });
94
+ }
95
+ return result;
96
+ }
97
+ //#endregion
98
+ //#region src/shared/utils/tryCatch.ts
99
+ async function tryCatch(tryer) {
100
+ try {
101
+ return [null, await tryer()];
102
+ } catch (error) {
103
+ return [error, null];
104
+ }
105
+ }
106
+ tryCatch.sync = function(tryer) {
107
+ try {
108
+ return [null, tryer()];
109
+ } catch (error) {
110
+ return [error, null];
111
+ }
112
+ };
113
+ //#endregion
114
+ //#region src/shared/utils/createId.ts
115
+ function uuid() {
116
+ if (typeof crypto !== "undefined" && crypto.randomUUID) return crypto.randomUUID();
117
+ if (typeof self !== "undefined" && self.crypto && self.crypto.randomUUID) return self.crypto.randomUUID();
118
+ if (typeof window !== "undefined" && window.crypto && window.crypto.randomUUID) return window.crypto.randomUUID();
119
+ return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
120
+ const r = Math.random() * 16 | 0;
121
+ return (c === "x" ? r : r & 3 | 8).toString(16);
122
+ });
123
+ }
124
+ function createId(prefix = "") {
125
+ return prefix + uuid();
126
+ }
127
+ //#endregion
128
+ //#region src/shared/exceptions/BaseException.ts
129
+ var BaseException = class BaseException extends Error {
130
+ statusCode = 500;
131
+ constructor(message, statusCode = 500) {
132
+ super(message);
133
+ this.name = this.constructor.name;
134
+ this.statusCode = statusCode;
135
+ }
136
+ static fromError(error) {
137
+ return new BaseException(error.message, 500);
138
+ }
139
+ };
140
+ //#endregion
141
+ //#region src/shared/services/ValidatorService.ts
142
+ var ValidatorService = class {
143
+ create(cb) {
144
+ return cb(v);
145
+ }
146
+ validate(payload, cb) {
147
+ const schema = typeof cb === "function" ? cb(v) : cb;
148
+ const { output, issues, success } = v.safeParse(schema, payload);
149
+ if (!success) {
150
+ const flatten = v.flatten(issues);
151
+ const messages = [];
152
+ if (flatten.root) messages.push(...flatten.root);
153
+ if (flatten.nested) Object.entries(flatten.nested).forEach((entry) => {
154
+ const [key, value] = entry;
155
+ messages.push(...value.map((v) => `${key}: ${v}`));
156
+ });
157
+ const error = new BaseException(messages.length ? messages.join(", ") : "Validation failed", 422);
158
+ error.name = "ValidationError";
159
+ Object.assign(error, { messages });
160
+ throw error;
161
+ }
162
+ return output;
163
+ }
164
+ async validateAsync(payload, cb) {
165
+ const schema = typeof cb === "function" ? cb(v) : cb;
166
+ const { output, issues, success } = await v.safeParseAsync(schema, payload);
167
+ if (!success) {
168
+ const error = /* @__PURE__ */ new Error("Validation failed");
169
+ const flatten = v.flatten(issues);
170
+ const details = {
171
+ ...flatten.root,
172
+ ...flatten.nested
173
+ };
174
+ Object.assign(error, { details });
175
+ throw error;
176
+ }
177
+ return output;
178
+ }
179
+ isValid(payload, cb) {
180
+ const schema = typeof cb === "function" ? cb(v) : cb;
181
+ const { success } = v.safeParse(schema, payload);
182
+ return success;
183
+ }
184
+ };
185
+ new ValidatorService();
186
+ //#endregion
187
+ export { ValidatorService, compose, composeWith, createId, flatten, formatBytes, mixin, tryCatch, unflatten };
@@ -0,0 +1,22 @@
1
+ import js from "@eslint/js";
2
+ import globals from "globals";
3
+ import tseslint from "typescript-eslint";
4
+ import pluginVue from "eslint-plugin-vue";
5
+ import json from "@eslint/json";
6
+ import eslintConfigPrettier from "eslint-config-prettier/flat";
7
+ import { defineConfig } from "eslint/config";
8
+
9
+ export default defineConfig([
10
+ { files: ["**/*.{js,mjs,cjs,ts,mts,cts,vue}"], plugins: { js }, extends: ["js/recommended"], languageOptions: { globals: { ...globals.browser, ...globals.node } } },
11
+ tseslint.configs.recommended,
12
+ pluginVue.configs["flat/essential"],
13
+ { files: ["**/*.vue"], languageOptions: { parserOptions: { parser: tseslint.parser } } },
14
+ { files: ["**/*.json"], plugins: { json }, language: "json/json", extends: ["json/recommended"] },
15
+ { files: ["**/*.jsonc"], plugins: { json }, language: "json/jsonc", extends: ["json/recommended"] },
16
+ eslintConfigPrettier,
17
+ {
18
+ rules: {
19
+ '@typescript-eslint/no-explicit-any': 'off',
20
+ }
21
+ }
22
+ ]);
package/indexes.js ADDED
@@ -0,0 +1,37 @@
1
+ import fg from 'fast-glob'
2
+ import fs from 'fs'
3
+ import path from 'path'
4
+
5
+ // generate indexes for folders
6
+
7
+ function generate(options) {
8
+ const folders = options.folders
9
+ const filename = options.filename
10
+
11
+ let content = ''
12
+
13
+ for (const folder of folders) {
14
+ const files = fg.sync(`${folder}/**/*.ts`, { ignore: ['**/index.ts'] })
15
+
16
+ for (const file of files) {
17
+ const filePath = path.relative(path.dirname(filename), file)
18
+
19
+ content += `export * from './${filePath}'\n`
20
+ }
21
+ }
22
+
23
+ content = content.trim()
24
+
25
+ fs.writeFileSync(filename, content)
26
+ }
27
+
28
+
29
+ generate({
30
+ folders: ['src/shared/services', 'src/shared/utils'],
31
+ filename: 'src/shared/index.ts'
32
+ })
33
+
34
+ generate({
35
+ folders: ['src/server/services'],
36
+ filename: 'src/server/index.ts'
37
+ })
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@sidekick-coder/zenith-kit",
3
+ "version": "0.0.1",
4
+ "license": "MIT",
5
+ "description": "A collection of utilities and tools for building language servers and related applications.",
6
+ "keywords": [],
7
+ "author": "Henrique Oliveira <henriqueoliwork@gmail.com>",
8
+ "homepage": "https://github.com/sidekick-coder/language-kit",
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git+https://github.com/sidekick-coder/language-kit.git"
12
+ },
13
+ "publishConfig": {
14
+ "access": "public"
15
+ },
16
+ "exports": {
17
+ "./shared": {
18
+ "import": "./dist/shared/index.mjs",
19
+ "require": "./dist/shared/index.js",
20
+ "types": "./dist/shared/index.d.mts"
21
+ },
22
+ "./server": {
23
+ "import": "./dist/server/index.mjs",
24
+ "require": "./dist/server/index.js",
25
+ "types": "./dist/server/index.d.mts"
26
+ }
27
+ },
28
+ "scripts": {
29
+ "generate:indexes": "node indexes.js",
30
+ "build": "node indexes.js && tsdown"
31
+ },
32
+ "devDependencies": {
33
+ "@eslint/js": "^9.39.4",
34
+ "@eslint/json": "^0.14.0",
35
+ "@types/lodash-es": "^4.17.12",
36
+ "@types/node": "^25.6.0",
37
+ "@vue/tsconfig": "^0.9.1",
38
+ "eslint": "^9.39.4",
39
+ "eslint-config-prettier": "^10.1.8",
40
+ "eslint-plugin-vue": "^10.8.0",
41
+ "globals": "^17.5.0",
42
+ "jiti": "^2.6.1",
43
+ "tsdown": "^0.21.9",
44
+ "typescript": "^6.0.3",
45
+ "typescript-eslint": "^8.58.2"
46
+ },
47
+ "dependencies": {
48
+ "fast-glob": "^3.3.3",
49
+ "lodash-es": "^4.18.1",
50
+ "valibot": "^1.3.1"
51
+ }
52
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "extends": [
3
+ "@vue/tsconfig/tsconfig.dom.json"
4
+ ],
5
+ "compilerOptions": {
6
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
7
+ "strict": true,
8
+ "noUnusedLocals": false,
9
+ "noUnusedParameters": true,
10
+ "erasableSyntaxOnly": true,
11
+ "noFallthroughCasesInSwitch": true,
12
+ "noUncheckedSideEffectImports": true,
13
+ "strictPropertyInitialization": false,
14
+ "baseUrl": ".",
15
+ "lib": [
16
+ "es2023",
17
+ "dom",
18
+ "dom.iterable"
19
+ ]
20
+ },
21
+ "include": [
22
+ "client/**/**/*.ts",
23
+ "client/**/**/*.vue",
24
+ "shared/**/**/*.ts",
25
+ ]
26
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,8 @@
1
+ {
2
+ "files": [],
3
+ "references": [
4
+ { "path": "./tsconfig.client.json" },
5
+ { "path": "./tsconfig.server.json" },
6
+ { "path": "./tsconfig.shared.json" }
7
+ ]
8
+ }
@@ -0,0 +1,30 @@
1
+ {
2
+ "compilerOptions": {
3
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
4
+ "target": "ES2023",
5
+ "lib": [
6
+ "ES2023"
7
+ ],
8
+ "types": [
9
+ "node"
10
+ ],
11
+ "module": "ESNext",
12
+ "skipLibCheck": true,
13
+ "moduleResolution": "bundler",
14
+ "allowImportingTsExtensions": true,
15
+ "verbatimModuleSyntax": true,
16
+ "moduleDetection": "force",
17
+ "noEmit": true,
18
+ "strict": true,
19
+ "noUnusedLocals": false,
20
+ "noUnusedParameters": true,
21
+ "erasableSyntaxOnly": true,
22
+ "noFallthroughCasesInSwitch": true,
23
+ "noUncheckedSideEffectImports": true,
24
+ "strictPropertyInitialization": false
25
+ },
26
+ "include": [
27
+ "src/server/**/*.ts",
28
+ "src/shared/**/*.ts"
29
+ ]
30
+ }
@@ -0,0 +1,26 @@
1
+ {
2
+ "compilerOptions": {
3
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
4
+ "target": "ES2023",
5
+ "lib": [
6
+ "ES2023"
7
+ ],
8
+ "module": "ESNext",
9
+ "skipLibCheck": true,
10
+ "moduleResolution": "bundler",
11
+ "allowImportingTsExtensions": true,
12
+ "verbatimModuleSyntax": true,
13
+ "moduleDetection": "force",
14
+ "noEmit": true,
15
+ "strict": false,
16
+ "noUnusedLocals": false,
17
+ "noUnusedParameters": true,
18
+ "erasableSyntaxOnly": true,
19
+ "noFallthroughCasesInSwitch": true,
20
+ "noUncheckedSideEffectImports": true,
21
+ "strictPropertyInitialization": false
22
+ },
23
+ "include": [
24
+ "src/shared/**/*.ts",
25
+ ]
26
+ }
@@ -0,0 +1,14 @@
1
+ import { defineConfig } from 'tsdown'
2
+
3
+ export default defineConfig([
4
+ {
5
+ entry: 'src/shared/index.ts',
6
+ outDir: 'dist/shared',
7
+ tsconfig: 'tsconfig.shared.json',
8
+ },
9
+ {
10
+ entry: 'src/server/index.ts',
11
+ outDir: 'dist/server',
12
+ tsconfig: 'tsconfig.server.json',
13
+ }
14
+ ])