@sidekick-coder/zenith-kit 0.0.8 → 0.0.11
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/server/index.d.mts +686 -1
- package/dist/server/index.mjs +1388 -25
- package/dist/shared/chunk-CfYAbeIz.mjs +13 -0
- package/dist/shared/index.d.mts +275 -4
- package/dist/shared/index.mjs +658 -8
- package/eslint.config.mts +1 -0
- package/package.json +15 -2
- package/tsconfig.server.json +1 -1
- package/tsdown.config.ts +15 -1
package/dist/shared/index.mjs
CHANGED
|
@@ -1,8 +1,206 @@
|
|
|
1
|
-
import "
|
|
1
|
+
import { t as __exportAll } from "./chunk-CfYAbeIz.mjs";
|
|
2
|
+
import { debounce, get, has, set, unset } from "lodash-es";
|
|
2
3
|
import * as v from "valibot";
|
|
4
|
+
import { format } from "date-fns";
|
|
5
|
+
import qs from "qs";
|
|
3
6
|
import fg from "fast-glob";
|
|
4
7
|
import fs from "fs";
|
|
5
8
|
import path from "path";
|
|
9
|
+
//#region src/shared/services/ConfigService.ts
|
|
10
|
+
var ConfigService = class {
|
|
11
|
+
entries;
|
|
12
|
+
constructor() {
|
|
13
|
+
this.entries = /* @__PURE__ */ new Map();
|
|
14
|
+
}
|
|
15
|
+
list() {
|
|
16
|
+
return Array.from(this.entries.values());
|
|
17
|
+
}
|
|
18
|
+
parseValue(value) {
|
|
19
|
+
if (typeof value === "string" && value.endsWith(":boolean")) return value.replace(":boolean", "").trim() === "true";
|
|
20
|
+
return value;
|
|
21
|
+
}
|
|
22
|
+
loadFromRecord(record, source = "unknow") {
|
|
23
|
+
for (const [key, value] of Object.entries(record)) this.entries.set(key, {
|
|
24
|
+
key,
|
|
25
|
+
value: this.parseValue(value),
|
|
26
|
+
source
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
loadFromEntries(entries, source = "unknow") {
|
|
30
|
+
for (const [key, value] of entries) this.entries.set(key, {
|
|
31
|
+
key,
|
|
32
|
+
value: this.parseValue(value),
|
|
33
|
+
source
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
toRecord() {
|
|
37
|
+
const record = {};
|
|
38
|
+
for (const [key, entry] of this.entries.entries()) record[key] = entry.value;
|
|
39
|
+
return record;
|
|
40
|
+
}
|
|
41
|
+
has(key) {
|
|
42
|
+
if (this.entries.get(key)) return true;
|
|
43
|
+
if (!key.includes(".")) return false;
|
|
44
|
+
const primary = key.split(".")[0];
|
|
45
|
+
const primaryEntry = this.entries.get(primary);
|
|
46
|
+
if (!primaryEntry) return this.entries.get(key) ? true : false;
|
|
47
|
+
const value = primaryEntry.value;
|
|
48
|
+
if (typeof value !== "object" || Array.isArray(value)) return false;
|
|
49
|
+
return has(value, key.substring(primary.length + 1));
|
|
50
|
+
}
|
|
51
|
+
get(key, defaultValue) {
|
|
52
|
+
const entry = this.entries.get(key);
|
|
53
|
+
if (entry) return entry.value;
|
|
54
|
+
if (!key.includes(".")) return defaultValue;
|
|
55
|
+
const primary = key.split(".")[0];
|
|
56
|
+
const primaryEntry = this.entries.get(primary);
|
|
57
|
+
if (!primaryEntry) {
|
|
58
|
+
const entry = this.entries.get(key);
|
|
59
|
+
return entry ? entry.value : defaultValue;
|
|
60
|
+
}
|
|
61
|
+
const value = primaryEntry.value;
|
|
62
|
+
if (typeof value !== "object" || Array.isArray(value)) return defaultValue;
|
|
63
|
+
return get(value, key.substring(primary.length + 1), defaultValue);
|
|
64
|
+
}
|
|
65
|
+
getOne(keys, defaultValue) {
|
|
66
|
+
for (const key of keys) if (this.has(key)) return this.get(key);
|
|
67
|
+
return defaultValue;
|
|
68
|
+
}
|
|
69
|
+
set(key, value, source = "runtime") {
|
|
70
|
+
if (!key.includes(".")) {
|
|
71
|
+
this.entries.set(key, {
|
|
72
|
+
key,
|
|
73
|
+
source,
|
|
74
|
+
value
|
|
75
|
+
});
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const primary = key.split(".")[0];
|
|
79
|
+
let primaryValue = this.get(primary, {});
|
|
80
|
+
if (typeof primaryValue !== "object" || Array.isArray(primaryValue)) primaryValue = {};
|
|
81
|
+
set(primaryValue, key.substring(primary.length + 1), value);
|
|
82
|
+
this.entries.set(primary, {
|
|
83
|
+
key: primary,
|
|
84
|
+
source,
|
|
85
|
+
value: primaryValue
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
unset(key) {
|
|
89
|
+
if (!key.includes(".")) {
|
|
90
|
+
this.entries.delete(key);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
const primary = key.split(".")[0];
|
|
94
|
+
const primaryValue = this.get(primary, {});
|
|
95
|
+
if (!primaryValue) return;
|
|
96
|
+
if (typeof primaryValue !== "object" || Array.isArray(primaryValue)) return;
|
|
97
|
+
unset(primaryValue, key.substring(primary.length + 1));
|
|
98
|
+
this.entries.set(primary, {
|
|
99
|
+
key: primary,
|
|
100
|
+
source: "runtime",
|
|
101
|
+
value: primaryValue
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
clear() {
|
|
105
|
+
this.entries.clear();
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
//#endregion
|
|
109
|
+
//#region src/shared/services/ContainerService.ts
|
|
110
|
+
var ContainerService = class {
|
|
111
|
+
entries = /* @__PURE__ */ new Map();
|
|
112
|
+
loadFromRecord(record) {
|
|
113
|
+
Object.entries(record).forEach(([key, value]) => {
|
|
114
|
+
this.set(key, value);
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
toRecord() {
|
|
118
|
+
const record = {};
|
|
119
|
+
for (const [key, value] of this.entries.entries()) record[String(key)] = value;
|
|
120
|
+
return record;
|
|
121
|
+
}
|
|
122
|
+
set(payload, value) {
|
|
123
|
+
let key = payload;
|
|
124
|
+
if (typeof payload === "function" || typeof payload === "object") key = payload.name;
|
|
125
|
+
this.entries.set(key, value);
|
|
126
|
+
}
|
|
127
|
+
has(payload) {
|
|
128
|
+
let key = payload;
|
|
129
|
+
if (typeof payload === "function" || typeof payload === "object") key = payload.name;
|
|
130
|
+
return this.entries.has(key);
|
|
131
|
+
}
|
|
132
|
+
get(payload) {
|
|
133
|
+
let key = payload;
|
|
134
|
+
if (typeof payload === "function" || typeof payload === "object") key = payload.name;
|
|
135
|
+
if (!this.has(key)) throw new Error(`entry not found: ${String(key)}`);
|
|
136
|
+
return this.entries.get(key);
|
|
137
|
+
}
|
|
138
|
+
singleton(classConstructor) {
|
|
139
|
+
const key = classConstructor.name;
|
|
140
|
+
const existingInstance = this.entries.get(key);
|
|
141
|
+
if (existingInstance) return existingInstance;
|
|
142
|
+
const newInstance = new classConstructor();
|
|
143
|
+
this.entries.set(key, newInstance);
|
|
144
|
+
return newInstance;
|
|
145
|
+
}
|
|
146
|
+
load(entries) {
|
|
147
|
+
Object.entries(entries).forEach(([key, value]) => {
|
|
148
|
+
this.set(key, value);
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
proxy(key) {
|
|
152
|
+
return new Proxy({}, {
|
|
153
|
+
get: (_target, prop) => {
|
|
154
|
+
const entry = this.get(key);
|
|
155
|
+
const value = entry[prop];
|
|
156
|
+
if (typeof value === "function") return value.bind(entry);
|
|
157
|
+
return entry[prop];
|
|
158
|
+
},
|
|
159
|
+
set: (_target, prop, value) => {
|
|
160
|
+
const entry = this.get(key);
|
|
161
|
+
entry[prop] = value;
|
|
162
|
+
return true;
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
keys() {
|
|
167
|
+
return Array.from(this.entries.keys());
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
//#endregion
|
|
171
|
+
//#region src/shared/services/CookieService.ts
|
|
172
|
+
var CookieService = class {
|
|
173
|
+
cookies;
|
|
174
|
+
prefix;
|
|
175
|
+
constructor(data = {}) {
|
|
176
|
+
this.cookies = data.cookies || /* @__PURE__ */ new Map();
|
|
177
|
+
this.prefix = data.prefix || "";
|
|
178
|
+
}
|
|
179
|
+
load(cookies) {
|
|
180
|
+
if (cookies instanceof Map) {
|
|
181
|
+
for (const [key, value] of cookies.entries()) this.set(key, value);
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
for (const key of Object.keys(cookies)) this.set(key, cookies[key]);
|
|
185
|
+
}
|
|
186
|
+
get(name, defaultValue = null) {
|
|
187
|
+
const fullName = this.prefix + name;
|
|
188
|
+
return this.cookies.get(fullName) || defaultValue;
|
|
189
|
+
}
|
|
190
|
+
set(name, value, options) {
|
|
191
|
+
const fullName = this.prefix + name;
|
|
192
|
+
this.cookies.set(fullName, value);
|
|
193
|
+
}
|
|
194
|
+
toRecord() {
|
|
195
|
+
const result = {};
|
|
196
|
+
for (const [key, value] of this.cookies.entries()) if (key.startsWith(this.prefix)) {
|
|
197
|
+
const unprefixedKey = key.slice(this.prefix.length);
|
|
198
|
+
result[unprefixedKey] = value;
|
|
199
|
+
}
|
|
200
|
+
return result;
|
|
201
|
+
}
|
|
202
|
+
};
|
|
203
|
+
//#endregion
|
|
6
204
|
//#region src/shared/utils/compose.ts
|
|
7
205
|
/**
|
|
8
206
|
* Composes multiple mixins into a single class that can be extended.
|
|
@@ -128,6 +326,334 @@ function createId(prefix = "") {
|
|
|
128
326
|
return prefix + uuid();
|
|
129
327
|
}
|
|
130
328
|
//#endregion
|
|
329
|
+
//#region src/shared/services/LoggerService.ts
|
|
330
|
+
var LoggerService = class LoggerService {
|
|
331
|
+
info(message, meta) {}
|
|
332
|
+
debug(message, meta) {}
|
|
333
|
+
warn(message, meta) {}
|
|
334
|
+
error(message, meta) {}
|
|
335
|
+
child(options) {
|
|
336
|
+
return new LoggerService();
|
|
337
|
+
}
|
|
338
|
+
};
|
|
339
|
+
//#endregion
|
|
340
|
+
//#region src/shared/services/EmmitterService.ts
|
|
341
|
+
var EmmitterService = class {
|
|
342
|
+
handlers = [];
|
|
343
|
+
debug;
|
|
344
|
+
logger;
|
|
345
|
+
load(options) {
|
|
346
|
+
this.debug = options?.debug || false;
|
|
347
|
+
this.logger = options?.logger || new LoggerService();
|
|
348
|
+
if (this.debug) this.logger.debug("emmitter loaded with debug mode enabled");
|
|
349
|
+
}
|
|
350
|
+
on(event, listener, options) {
|
|
351
|
+
const id = options?.id || createId();
|
|
352
|
+
if (options?.unique) {
|
|
353
|
+
if (this.handlers.some((h) => h.event === event && h.listener === listener || h.id === id)) return;
|
|
354
|
+
}
|
|
355
|
+
const handler = {
|
|
356
|
+
id,
|
|
357
|
+
event,
|
|
358
|
+
listener
|
|
359
|
+
};
|
|
360
|
+
this.handlers.push(handler);
|
|
361
|
+
if (this.debug) this.logger.debug("handler added", handler);
|
|
362
|
+
return handler;
|
|
363
|
+
}
|
|
364
|
+
once(event, listener, options) {
|
|
365
|
+
const wrapper = (args) => {
|
|
366
|
+
listener(args);
|
|
367
|
+
this.off(event, wrapper);
|
|
368
|
+
};
|
|
369
|
+
return this.on(event, wrapper, options);
|
|
370
|
+
}
|
|
371
|
+
onDebounce(event, listener, options) {
|
|
372
|
+
const debounced = debounce(listener, options?.debounce || 300);
|
|
373
|
+
const handler = this.on(event, debounced, options);
|
|
374
|
+
if (handler) handler.originalListener = listener;
|
|
375
|
+
return handler;
|
|
376
|
+
}
|
|
377
|
+
onAnyOf(events, listener, options) {
|
|
378
|
+
const handlers = [];
|
|
379
|
+
for (const event of events) {
|
|
380
|
+
const handler = this.on(event, listener, options);
|
|
381
|
+
if (handler) handlers.push(handler);
|
|
382
|
+
}
|
|
383
|
+
return handlers;
|
|
384
|
+
}
|
|
385
|
+
off(event, listener) {
|
|
386
|
+
this.handlers = this.handlers.filter((h) => {
|
|
387
|
+
if (h.event === event && (h.listener === listener || h.originalListener === listener)) return false;
|
|
388
|
+
return true;
|
|
389
|
+
});
|
|
390
|
+
if (this.debug) this.logger.debug("handler removed", { event });
|
|
391
|
+
}
|
|
392
|
+
emit(event, args) {
|
|
393
|
+
if (this.debug) this.logger.debug("emitting event", {
|
|
394
|
+
event,
|
|
395
|
+
args
|
|
396
|
+
});
|
|
397
|
+
const handlers = this.handlers.filter((h) => h.event === event);
|
|
398
|
+
for (const handler of handlers) tryCatch.sync(() => handler.listener(args));
|
|
399
|
+
}
|
|
400
|
+
async emitAndWait(event, args) {
|
|
401
|
+
const handlers = this.handlers.filter((h) => h.event === event);
|
|
402
|
+
if (this.debug) this.logger.debug("emitting event", {
|
|
403
|
+
handlers: handlers.length,
|
|
404
|
+
event,
|
|
405
|
+
args
|
|
406
|
+
});
|
|
407
|
+
for await (const handler of handlers) await handler.listener(args);
|
|
408
|
+
}
|
|
409
|
+
list() {
|
|
410
|
+
return this.handlers;
|
|
411
|
+
}
|
|
412
|
+
listByEvent(event) {
|
|
413
|
+
return this.handlers.filter((h) => h.event === event);
|
|
414
|
+
}
|
|
415
|
+
remove(payload) {
|
|
416
|
+
const ids = Array.isArray(payload) ? payload : [payload];
|
|
417
|
+
this.handlers = this.handlers.filter((h) => !ids.includes(h.id));
|
|
418
|
+
if (this.debug) this.logger.debug("handlers removed", { ids });
|
|
419
|
+
}
|
|
420
|
+
clear() {
|
|
421
|
+
this.handlers = [];
|
|
422
|
+
if (this.debug) this.logger.debug("all handlers cleared");
|
|
423
|
+
}
|
|
424
|
+
hasHandlers() {
|
|
425
|
+
return this.handlers.length > 0;
|
|
426
|
+
}
|
|
427
|
+
};
|
|
428
|
+
//#endregion
|
|
429
|
+
//#region src/shared/services/LifecycleService.ts
|
|
430
|
+
var LifecycleService = class {
|
|
431
|
+
hooks;
|
|
432
|
+
logger;
|
|
433
|
+
debug = false;
|
|
434
|
+
constructor(data = {}) {
|
|
435
|
+
this.debug = data.debug ?? this.debug;
|
|
436
|
+
this.hooks = data.hooks ?? /* @__PURE__ */ new Map();
|
|
437
|
+
this.logger = data.logger ?? new LoggerService();
|
|
438
|
+
}
|
|
439
|
+
async executeHookMethod(hook, method) {
|
|
440
|
+
await hook[method]();
|
|
441
|
+
if (this.debug) this.logger.debug(`${method} ${hook.hook_id}`);
|
|
442
|
+
const subhooks = hook.subhooks || [];
|
|
443
|
+
for (const subhook of subhooks) {
|
|
444
|
+
await this.executeHookMethod(subhook, method);
|
|
445
|
+
if (this.debug) this.logger.debug(`${method} subhook ${subhook.hook_id} of ${hook.hook_id}`);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
list(options) {
|
|
449
|
+
let hooks = Array.from(this.hooks.values());
|
|
450
|
+
if (options?.exclude) {
|
|
451
|
+
const ids = options.exclude.filter((item) => typeof item === "string");
|
|
452
|
+
const constructors = options.exclude.filter((item) => typeof item === "function");
|
|
453
|
+
const instances = options.exclude.filter((item) => typeof item === "object");
|
|
454
|
+
hooks = hooks.filter((hook) => {
|
|
455
|
+
if (ids.includes(hook.hook_id)) return false;
|
|
456
|
+
if (constructors.find((ctor) => hook instanceof ctor)) return false;
|
|
457
|
+
if (instances.find((inst) => hook === inst)) return false;
|
|
458
|
+
return true;
|
|
459
|
+
});
|
|
460
|
+
}
|
|
461
|
+
hooks.sort((a, b) => {
|
|
462
|
+
return (a.order ?? 0) - (b.order ?? 0);
|
|
463
|
+
});
|
|
464
|
+
return hooks;
|
|
465
|
+
}
|
|
466
|
+
add(...payload) {
|
|
467
|
+
const instances = [];
|
|
468
|
+
for (const item of payload) {
|
|
469
|
+
if (typeof item === "function") {
|
|
470
|
+
instances.push(new item());
|
|
471
|
+
continue;
|
|
472
|
+
}
|
|
473
|
+
instances.push(item);
|
|
474
|
+
}
|
|
475
|
+
for (const hook of instances) {
|
|
476
|
+
this.hooks.set(hook.hook_id, hook);
|
|
477
|
+
if (this.debug) this.logger.debug("add " + hook.hook_id);
|
|
478
|
+
if (hook.subhooks) hook.subhooks.forEach((subhook) => this.add(subhook));
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
async register(options) {
|
|
482
|
+
for (const hook of this.list(options)) {
|
|
483
|
+
const [error] = await tryCatch(() => this.executeHookMethod(hook, "onRegister"));
|
|
484
|
+
if (error) {
|
|
485
|
+
Object.assign(error, { hookId: hook.hook_id });
|
|
486
|
+
this.logger.error("error in hook register: ", error);
|
|
487
|
+
continue;
|
|
488
|
+
}
|
|
489
|
+
if (this.debug) this.logger.debug("register " + hook.hook_id);
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
async load(options) {
|
|
493
|
+
for (const hook of this.list(options)) {
|
|
494
|
+
const [error] = await tryCatch(() => this.executeHookMethod(hook, "onLoad"));
|
|
495
|
+
if (error) {
|
|
496
|
+
Object.assign(error, { hookId: hook.hook_id });
|
|
497
|
+
this.logger.error("error in hook load:", error);
|
|
498
|
+
continue;
|
|
499
|
+
}
|
|
500
|
+
if (this.debug) this.logger.debug("load " + hook.hook_id);
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
async boot(options) {
|
|
504
|
+
const hooks = this.list(options);
|
|
505
|
+
for (const hook of hooks) {
|
|
506
|
+
const [error] = await tryCatch(() => this.executeHookMethod(hook, "onBoot"));
|
|
507
|
+
if (error) {
|
|
508
|
+
Object.assign(error, { hookId: hook.hook_id });
|
|
509
|
+
this.logger.error("error in hook boot:", error);
|
|
510
|
+
continue;
|
|
511
|
+
}
|
|
512
|
+
if (this.debug) this.logger.debug("boot " + hook.hook_id);
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
async shutdown(options) {
|
|
516
|
+
for (const hook of this.list(options)) {
|
|
517
|
+
const [error] = await tryCatch(() => this.executeHookMethod(hook, "onShutdown"));
|
|
518
|
+
if (error) {
|
|
519
|
+
Object.assign(error, { hookId: hook.hook_id });
|
|
520
|
+
this.logger.error("error in hook shutdown:", error);
|
|
521
|
+
continue;
|
|
522
|
+
}
|
|
523
|
+
if (this.debug) this.logger.debug("shutdown " + hook.hook_id);
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
clear() {
|
|
527
|
+
this.hooks.clear();
|
|
528
|
+
}
|
|
529
|
+
};
|
|
530
|
+
//#endregion
|
|
531
|
+
//#region src/shared/services/TranslatorService.ts
|
|
532
|
+
var TranslatorService = class {
|
|
533
|
+
entries;
|
|
534
|
+
locale;
|
|
535
|
+
localeLoaders;
|
|
536
|
+
debug = false;
|
|
537
|
+
logger;
|
|
538
|
+
cache;
|
|
539
|
+
constructor(data = {}) {
|
|
540
|
+
this.entries = data.entries || /* @__PURE__ */ new Map();
|
|
541
|
+
this.locale = data.locale || "en";
|
|
542
|
+
this.debug = data.debug || false;
|
|
543
|
+
this.cache = data.cache || /* @__PURE__ */ new Map();
|
|
544
|
+
this.logger = data.logger || new LoggerService();
|
|
545
|
+
this.localeLoaders = /* @__PURE__ */ new Map();
|
|
546
|
+
if (this.debug) this.logger.debug("initialized in debug mode", { locale: this.locale });
|
|
547
|
+
}
|
|
548
|
+
get locales() {
|
|
549
|
+
return Array.from(this.localeLoaders.keys());
|
|
550
|
+
}
|
|
551
|
+
list() {
|
|
552
|
+
const items = [];
|
|
553
|
+
this.entries.forEach((value, key) => {
|
|
554
|
+
items.push({
|
|
555
|
+
key,
|
|
556
|
+
value
|
|
557
|
+
});
|
|
558
|
+
});
|
|
559
|
+
return items;
|
|
560
|
+
}
|
|
561
|
+
async getEntries(locale) {
|
|
562
|
+
const cache = this.cache.get(locale);
|
|
563
|
+
if (cache && this.debug) this.logger.debug(`load locale "${locale}" from cache`, {
|
|
564
|
+
locale,
|
|
565
|
+
length: Object.keys(cache).length
|
|
566
|
+
});
|
|
567
|
+
if (cache) return cache;
|
|
568
|
+
const loader = this.localeLoaders.get(locale);
|
|
569
|
+
if (!loader) {
|
|
570
|
+
this.logger.warn(`no loader found for locale "${locale}"`);
|
|
571
|
+
return {};
|
|
572
|
+
}
|
|
573
|
+
const entries = await loader();
|
|
574
|
+
this.cache.set(locale, entries);
|
|
575
|
+
if (this.debug) this.logger.debug(`load locale ${locale}`, {
|
|
576
|
+
locale,
|
|
577
|
+
keys: Object.keys(entries).length
|
|
578
|
+
});
|
|
579
|
+
return entries;
|
|
580
|
+
}
|
|
581
|
+
async load(locale) {
|
|
582
|
+
const entries = await this.getEntries(locale);
|
|
583
|
+
this.entries = new Map(Object.entries(entries));
|
|
584
|
+
this.locale = locale;
|
|
585
|
+
}
|
|
586
|
+
t(key, args = {}) {
|
|
587
|
+
if (!this.entries.has(key) && this.debug) this.logger.debug(`missing translation for key "${key}"`, {
|
|
588
|
+
key,
|
|
589
|
+
locale: this.locale
|
|
590
|
+
});
|
|
591
|
+
let translation = this.entries.get(key) || key;
|
|
592
|
+
if (!Object.keys(args).length) return translation;
|
|
593
|
+
Object.entries(args).forEach(([aKey, aValue]) => {
|
|
594
|
+
translation = translation.replace(`:${aKey}`, aValue);
|
|
595
|
+
});
|
|
596
|
+
return translation;
|
|
597
|
+
}
|
|
598
|
+
date(data) {
|
|
599
|
+
return new Date(data).toLocaleDateString(this.locale, {
|
|
600
|
+
year: "numeric",
|
|
601
|
+
month: "2-digit",
|
|
602
|
+
day: "2-digit"
|
|
603
|
+
});
|
|
604
|
+
}
|
|
605
|
+
datetime(data) {
|
|
606
|
+
return new Date(data).toLocaleString(this.locale, {
|
|
607
|
+
year: "numeric",
|
|
608
|
+
month: "2-digit",
|
|
609
|
+
day: "2-digit",
|
|
610
|
+
hour: "2-digit",
|
|
611
|
+
minute: "2-digit"
|
|
612
|
+
});
|
|
613
|
+
}
|
|
614
|
+
};
|
|
615
|
+
//#endregion
|
|
616
|
+
//#region src/shared/services/UploadService.ts
|
|
617
|
+
var UploadService = class {
|
|
618
|
+
single(name) {
|
|
619
|
+
const error = /* @__PURE__ */ new Error("Method not implemented.");
|
|
620
|
+
Object.assign(error, { name });
|
|
621
|
+
throw error;
|
|
622
|
+
}
|
|
623
|
+
multiple(name) {
|
|
624
|
+
const error = /* @__PURE__ */ new Error("Method not implemented.");
|
|
625
|
+
Object.assign(error, { name });
|
|
626
|
+
throw error;
|
|
627
|
+
}
|
|
628
|
+
};
|
|
629
|
+
//#endregion
|
|
630
|
+
//#region src/shared/validators/url.ts
|
|
631
|
+
var url_exports = /* @__PURE__ */ __exportAll({
|
|
632
|
+
array: () => array,
|
|
633
|
+
arrayNumber: () => arrayNumber,
|
|
634
|
+
boolean: () => boolean,
|
|
635
|
+
date: () => date,
|
|
636
|
+
datetime: () => datetime,
|
|
637
|
+
number: () => number,
|
|
638
|
+
object: () => object
|
|
639
|
+
});
|
|
640
|
+
const number = () => v.pipe(v.union([v.string(), v.number()]), v.transform(Number), v.integer());
|
|
641
|
+
const boolean = () => v.pipe(v.union([v.string(), v.boolean()]), v.transform((v) => v === true || v === "true"));
|
|
642
|
+
const date = () => v.pipe(v.union([v.string(), v.date()]), v.transform((v) => v instanceof Date ? v : new Date(v)), v.transform((v) => v ? format(v, "yyyy-MM-dd") : v));
|
|
643
|
+
const datetime = () => v.pipe(v.union([v.string(), v.date()]), v.transform((v) => {
|
|
644
|
+
if (!v) return v;
|
|
645
|
+
if (v === "null") return null;
|
|
646
|
+
if (typeof v === "string") v = new Date(v);
|
|
647
|
+
return format(v, "yyyy-MM-dd HH:mm");
|
|
648
|
+
}));
|
|
649
|
+
const array = (schema = v.any()) => v.pipe(v.union([v.string(), v.array(v.string())]), v.transform((value) => Array.isArray(value) ? value : value.split(",")), v.array(schema));
|
|
650
|
+
const arrayNumber = () => v.pipe(array(), v.transform((value) => value.map(Number)));
|
|
651
|
+
const object = () => v.pipe(v.union([v.string(), v.record(v.string(), v.any())]), v.transform((value) => typeof value === "string" ? qs.parse(value) : value), v.transform((value) => {
|
|
652
|
+
const result = {};
|
|
653
|
+
for (const key in value) set(result, key, get(value, key));
|
|
654
|
+
return result;
|
|
655
|
+
}));
|
|
656
|
+
//#endregion
|
|
131
657
|
//#region src/shared/exceptions/BaseException.ts
|
|
132
658
|
var BaseException = class BaseException extends Error {
|
|
133
659
|
statusCode = 500;
|
|
@@ -142,12 +668,17 @@ var BaseException = class BaseException extends Error {
|
|
|
142
668
|
};
|
|
143
669
|
//#endregion
|
|
144
670
|
//#region src/shared/services/ValidatorService.ts
|
|
671
|
+
const extras = { url: url_exports };
|
|
145
672
|
var ValidatorService = class {
|
|
673
|
+
v = {
|
|
674
|
+
...v,
|
|
675
|
+
extras
|
|
676
|
+
};
|
|
146
677
|
create(cb) {
|
|
147
|
-
return cb(v);
|
|
678
|
+
return cb(this.v);
|
|
148
679
|
}
|
|
149
680
|
validate(payload, cb) {
|
|
150
|
-
const schema = typeof cb === "function" ? cb(v) : cb;
|
|
681
|
+
const schema = typeof cb === "function" ? cb(this.v) : cb;
|
|
151
682
|
const { output, issues, success } = v.safeParse(schema, payload);
|
|
152
683
|
if (!success) {
|
|
153
684
|
const flatten = v.flatten(issues);
|
|
@@ -165,7 +696,7 @@ var ValidatorService = class {
|
|
|
165
696
|
return output;
|
|
166
697
|
}
|
|
167
698
|
async validateAsync(payload, cb) {
|
|
168
|
-
const schema = typeof cb === "function" ? cb(v) : cb;
|
|
699
|
+
const schema = typeof cb === "function" ? cb(this.v) : cb;
|
|
169
700
|
const { output, issues, success } = await v.safeParseAsync(schema, payload);
|
|
170
701
|
if (!success) {
|
|
171
702
|
const error = /* @__PURE__ */ new Error("Validation failed");
|
|
@@ -180,27 +711,146 @@ var ValidatorService = class {
|
|
|
180
711
|
return output;
|
|
181
712
|
}
|
|
182
713
|
isValid(payload, cb) {
|
|
183
|
-
const schema = typeof cb === "function" ? cb(v) : cb;
|
|
714
|
+
const schema = typeof cb === "function" ? cb(this.v) : cb;
|
|
184
715
|
const { success } = v.safeParse(schema, payload);
|
|
185
716
|
return success;
|
|
186
717
|
}
|
|
187
718
|
};
|
|
188
|
-
new ValidatorService();
|
|
189
719
|
//#endregion
|
|
190
720
|
//#region src/shared/utils/generateIndexFile.ts
|
|
191
721
|
function generateIndexFile(options) {
|
|
192
722
|
const folders = options.folders;
|
|
193
723
|
const filename = options.filename;
|
|
724
|
+
const defaultIgnore = [
|
|
725
|
+
"**/index.ts",
|
|
726
|
+
"**/*.spec.ts",
|
|
727
|
+
"**/*.test.ts"
|
|
728
|
+
];
|
|
729
|
+
const ignore = options.ignore || [];
|
|
194
730
|
let content = "";
|
|
195
731
|
for (const folder of folders) {
|
|
196
|
-
const files = fg.sync(`${folder}/**/*.ts`, { ignore: [
|
|
732
|
+
const files = fg.sync(`${folder}/**/*.ts`, { ignore: [...defaultIgnore, ...ignore] });
|
|
197
733
|
for (const file of files) {
|
|
198
734
|
const filePath = path.relative(path.dirname(filename), file);
|
|
735
|
+
const hasDefaultExport = fs.readFileSync(file, "utf-8").includes("export default") && !filePath.includes("generateIndexFile.ts");
|
|
199
736
|
content += `export * from './${filePath}'\n`;
|
|
737
|
+
if (hasDefaultExport) content += `export { default as ${path.basename(file, ".ts")} } from './${filePath}'\n`;
|
|
200
738
|
}
|
|
201
739
|
}
|
|
202
740
|
content = content.trim();
|
|
203
741
|
fs.writeFileSync(filename, content);
|
|
204
742
|
}
|
|
205
743
|
//#endregion
|
|
206
|
-
|
|
744
|
+
//#region src/shared/schemas/permissionAssignmentSchema.ts
|
|
745
|
+
const permissionAssignmentSchema = v.object({
|
|
746
|
+
id: v.number(),
|
|
747
|
+
permission_id: v.number(),
|
|
748
|
+
assignable_type: v.string(),
|
|
749
|
+
assignable_id: v.string(),
|
|
750
|
+
created_at: v.string(),
|
|
751
|
+
updated_at: v.string()
|
|
752
|
+
});
|
|
753
|
+
//#endregion
|
|
754
|
+
//#region src/shared/schemas/permissionSchema.ts
|
|
755
|
+
const permissionSchema = v.object({
|
|
756
|
+
id: v.number(),
|
|
757
|
+
name: v.nullable(v.string()),
|
|
758
|
+
description: v.nullable(v.string()),
|
|
759
|
+
action: v.string(),
|
|
760
|
+
subject: v.string(),
|
|
761
|
+
conditions: v.nullable(v.string()),
|
|
762
|
+
created_at: v.string(),
|
|
763
|
+
updated_at: v.string(),
|
|
764
|
+
expires_at: v.string()
|
|
765
|
+
});
|
|
766
|
+
//#endregion
|
|
767
|
+
//#region src/shared/schemas/tokenSchema.ts
|
|
768
|
+
const tokenSchema = v.object({
|
|
769
|
+
id: v.number(),
|
|
770
|
+
name: v.nullable(v.string()),
|
|
771
|
+
type: v.string(),
|
|
772
|
+
user_id: v.number(),
|
|
773
|
+
token: v.string(),
|
|
774
|
+
created_at: v.string(),
|
|
775
|
+
updated_at: v.string(),
|
|
776
|
+
expires_at: v.string()
|
|
777
|
+
});
|
|
778
|
+
//#endregion
|
|
779
|
+
//#region src/shared/exceptions/ShellException.ts
|
|
780
|
+
var ShellException = class extends BaseException {
|
|
781
|
+
output;
|
|
782
|
+
bin;
|
|
783
|
+
args;
|
|
784
|
+
constructor(message, output, bin, args) {
|
|
785
|
+
super(message, 501);
|
|
786
|
+
this.output = output;
|
|
787
|
+
this.bin = bin;
|
|
788
|
+
this.args = args;
|
|
789
|
+
}
|
|
790
|
+
};
|
|
791
|
+
//#endregion
|
|
792
|
+
//#region src/shared/facades/validator.ts
|
|
793
|
+
const validator = new ValidatorService();
|
|
794
|
+
//#endregion
|
|
795
|
+
//#region src/shared/entities/LifecycleHook.ts
|
|
796
|
+
var LifecycleHook = class {
|
|
797
|
+
hook_id;
|
|
798
|
+
order;
|
|
799
|
+
subhooks;
|
|
800
|
+
constructor() {
|
|
801
|
+
if (!this.hook_id) this.hook_id = this.constructor.name;
|
|
802
|
+
}
|
|
803
|
+
async onRegister() {}
|
|
804
|
+
async onLoad() {}
|
|
805
|
+
async onBoot() {}
|
|
806
|
+
async onShutdown() {}
|
|
807
|
+
};
|
|
808
|
+
//#endregion
|
|
809
|
+
//#region src/shared/mixins/BaseEntityMixin.ts
|
|
810
|
+
function BaseEntity(Base) {
|
|
811
|
+
return class extends Base {
|
|
812
|
+
static from(data) {
|
|
813
|
+
const contructor = typeof this === "function" ? this : Base;
|
|
814
|
+
const instance = new contructor();
|
|
815
|
+
let payload = { ...data };
|
|
816
|
+
if (typeof contructor?.parse === "function") payload = contructor.parse(data);
|
|
817
|
+
if (typeof this?.parse === "function") payload = this.parse(data);
|
|
818
|
+
Object.assign(instance, payload);
|
|
819
|
+
return instance;
|
|
820
|
+
}
|
|
821
|
+
merge(data) {
|
|
822
|
+
Object.assign(this, data);
|
|
823
|
+
return this;
|
|
824
|
+
}
|
|
825
|
+
};
|
|
826
|
+
}
|
|
827
|
+
//#endregion
|
|
828
|
+
//#region src/shared/entities/ModuleEntity.ts
|
|
829
|
+
var Module = class extends compose(BaseEntity, mixin(LifecycleHook)) {
|
|
830
|
+
id;
|
|
831
|
+
name;
|
|
832
|
+
enabled = false;
|
|
833
|
+
dependencies = {};
|
|
834
|
+
build = {};
|
|
835
|
+
directory;
|
|
836
|
+
upgrade_info;
|
|
837
|
+
setData(data) {
|
|
838
|
+
const filtered = Object.fromEntries(Object.entries(data).filter(([, v]) => v !== void 0));
|
|
839
|
+
Object.assign(this, filtered);
|
|
840
|
+
this.hook_id = `module:${this.id}`;
|
|
841
|
+
}
|
|
842
|
+
};
|
|
843
|
+
//#endregion
|
|
844
|
+
//#region src/shared/entities/ModuleManifestEntity.ts
|
|
845
|
+
var ModuleManifest = class extends compose(BaseEntity) {
|
|
846
|
+
id;
|
|
847
|
+
name;
|
|
848
|
+
version;
|
|
849
|
+
description;
|
|
850
|
+
enabled;
|
|
851
|
+
author;
|
|
852
|
+
dependencies;
|
|
853
|
+
build;
|
|
854
|
+
};
|
|
855
|
+
//#endregion
|
|
856
|
+
export { BaseException, ConfigService, ContainerService, CookieService, EmmitterService, LifecycleHook, LifecycleService, LoggerService, Module as ModuleEntity, ModuleManifest as ModuleManifestEntity, ShellException, TranslatorService, UploadService, ValidatorService, compose, composeWith, createId, flatten, formatBytes, generateIndexFile, mixin, permissionAssignmentSchema, permissionSchema, tokenSchema, tryCatch, unflatten, validator };
|