@arkstack/common 0.3.12 → 0.3.15

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -4,5 +4,34 @@ Common utilities and helpers shared across Arkstack kits, including:
4
4
 
5
5
  - Logging utilities
6
6
  - Configuration management
7
- - Error handling helpers
8
- - Data validation functions
7
+ - `ErrorHandler` and shared exception classes
8
+ - Hashing and encryption helpers
9
+ - Typed model resolution with `getModel()`
10
+ - Pagination helpers
11
+
12
+ ## Model Resolution
13
+
14
+ ```ts
15
+ import { getModel } from '@arkstack/common';
16
+ import type User from './src/app/models/User';
17
+
18
+ const UserModel = await getModel<typeof User>('User');
19
+ ```
20
+
21
+ Apps can augment `ModelRegistry` for typed model names:
22
+
23
+ ```ts
24
+ declare module '@arkstack/common' {
25
+ interface ModelRegistry {
26
+ User: typeof User;
27
+ }
28
+ }
29
+ ```
30
+
31
+ ## Error Handling
32
+
33
+ ```ts
34
+ import { ErrorHandler } from '@arkstack/common';
35
+
36
+ const payload = ErrorHandler.createErrorPayload(error);
37
+ ```
package/dist/index.d.ts CHANGED
@@ -2,6 +2,8 @@
2
2
  import { DotPath } from "@h3ravel/support";
3
3
  import pino from "pino";
4
4
  import { ChalkInstance } from "chalk";
5
+ import { TOTP } from "otpauth";
6
+ import { Model, ModelStatic } from "arkormx";
5
7
 
6
8
  //#region src/lifecycle.d.ts
7
9
  declare const bindGracefulShutdown: (shutdown: () => Promise<void> | void) => void;
@@ -102,19 +104,86 @@ declare const nodeEnv: () => "prod" | "dev";
102
104
  declare const outputDir: (cwd?: string) => string;
103
105
  declare const importFile: <T = unknown>(filePath: string) => Promise<T>;
104
106
  //#endregion
105
- //#region src/error-handling.d.ts
106
- declare const toErrorShape: (value: unknown) => ArkstackErrorShape | undefined;
107
- declare const normalizeStatusCode: (value: unknown, fallback?: number) => number;
108
- declare const getErrorLogger: () => pino.Logger;
109
- declare const serializeError: (value: unknown, seen?: WeakSet<object>) => unknown;
110
- declare const getPrimaryError: (error: ArkstackErrorShape | string) => string | ArkstackErrorShape;
111
- declare const getValidationErrors: (error: ArkstackErrorShape) => any;
112
- declare const isValidationError: (error: unknown) => error is ArkstackErrorShape;
113
- declare const isModelNotFoundError: (error: unknown) => error is ArkstackErrorShape;
114
- declare const shouldHideStack: () => boolean;
115
- declare const shouldLogError: (error: unknown) => boolean;
116
- declare const createErrorPayload: (err: ArkstackErrorShape | string, fallbackMessage?: string) => ArkstackErrorPayload;
117
- declare const logUnhandledError: (err: unknown, request: Record<string, unknown>, message: string) => void;
107
+ //#region src/Exceptions/Exception.d.ts
108
+ declare class Exception extends Error {
109
+ name: string;
110
+ constructor(message?: string, options?: ErrorOptions);
111
+ }
112
+ //#endregion
113
+ //#region src/Exceptions/AppException.d.ts
114
+ declare class AppException extends Exception {
115
+ errors?: {
116
+ [key: string]: string[] | string;
117
+ } | undefined;
118
+ statusCode: number;
119
+ constructor(message?: string, statusCode?: number, options?: ErrorOptions);
120
+ }
121
+ //#endregion
122
+ //#region src/Exceptions/RequestException.d.ts
123
+ declare class RequestException extends AppException {
124
+ statusCode: number;
125
+ constructor(message?: string, statusCode?: number, options?: ErrorOptions);
126
+ static assertNotEmpty<T>(value: T | null | undefined, message: string, code?: number): asserts value is T;
127
+ static abortIf<T>(boolean: T, message: string, code?: number): asserts boolean is T;
128
+ }
129
+ //#endregion
130
+ //#region src/ErrorHandler.d.ts
131
+ declare class ErrorHandler {
132
+ private static loggerCache;
133
+ private static isRecord;
134
+ static toErrorShape(value: unknown): ArkstackErrorShape | undefined;
135
+ static normalizeStatusCode(value: unknown, fallback?: number): number;
136
+ static getErrorLogger(): pino.Logger;
137
+ static serializeError(value: unknown, seen?: WeakSet<object>): unknown;
138
+ static getPrimaryError(error: ArkstackErrorShape | string): string | ArkstackErrorShape;
139
+ static getValidationErrors(error: ArkstackErrorShape): any;
140
+ static isValidationError(error: unknown): error is ArkstackErrorShape;
141
+ static isModelNotFoundError(error: unknown): error is ArkstackErrorShape;
142
+ static shouldHideStack(): boolean;
143
+ static shouldLogError(error: unknown): boolean;
144
+ static createErrorPayload(err: ArkstackErrorShape | string, fallbackMessage?: string): ArkstackErrorPayload;
145
+ static logUnhandledError(err: unknown, request: Record<string, unknown>, message: string): void;
146
+ }
147
+ declare const toErrorShape: typeof ErrorHandler.toErrorShape;
148
+ declare const normalizeStatusCode: typeof ErrorHandler.normalizeStatusCode;
149
+ declare const getErrorLogger: typeof ErrorHandler.getErrorLogger;
150
+ declare const serializeError: typeof ErrorHandler.serializeError;
151
+ declare const getPrimaryError: typeof ErrorHandler.getPrimaryError;
152
+ declare const getValidationErrors: typeof ErrorHandler.getValidationErrors;
153
+ declare const isValidationError: typeof ErrorHandler.isValidationError;
154
+ declare const isModelNotFoundError: typeof ErrorHandler.isModelNotFoundError;
155
+ declare const shouldHideStack: typeof ErrorHandler.shouldHideStack;
156
+ declare const shouldLogError: typeof ErrorHandler.shouldLogError;
157
+ declare const createErrorPayload: typeof ErrorHandler.createErrorPayload;
158
+ declare const logUnhandledError: typeof ErrorHandler.logUnhandledError;
159
+ //#endregion
160
+ //#region src/utils/encryption.d.ts
161
+ declare class Encryption {
162
+ private static readonly algorithm;
163
+ private static getKey;
164
+ static encrypt(value: string): string;
165
+ static decrypt(payload: string): string;
166
+ }
167
+ //#endregion
168
+ //#region src/utils/hash.d.ts
169
+ declare class Hash {
170
+ static make(value: string): Promise<string>;
171
+ static verify(value: string, hashedValue: string): Promise<boolean>;
172
+ static otp(digits?: number, label?: string, period?: number): TOTP;
173
+ static totp(secret: string, label: string, issuer?: string, period?: number): TOTP;
174
+ }
175
+ //#endregion
176
+ //#region src/utils/helpers.d.ts
177
+ type AbstractModelConstructor<TModel = unknown> = abstract new (attributes?: Record<string, unknown>) => TModel;
178
+ type ModelConstructor<TModel extends Model = Model> = AbstractModelConstructor<TModel> & Pick<ModelStatic<TModel>, keyof ModelStatic<TModel>>;
179
+ interface ModelRegistry {}
180
+ type ModelName = Extract<keyof ModelRegistry, string>;
181
+ declare const perPage: (query: {
182
+ limit?: number;
183
+ perPage?: number;
184
+ }) => number;
185
+ declare function getModel<TName extends ModelName>(modelName: TName): Promise<ModelRegistry[TName]>;
186
+ declare function getModel<TModel extends AbstractModelConstructor = ModelConstructor>(modelName: string): Promise<TModel>;
118
187
  //#endregion
119
- export { ArkstackErrorPayload, ArkstackErrorShape, DotPathValue, GlobalConfig, GlobalEnv, Logger, LoggerChalk, LoggerLog, LoggerParseSignature, appUrl, bindGracefulShutdown, bootWithDetectedPort, buildHtmlErrorResponse, config, createErrorPayload, env, getErrorLogger, getPrimaryError, getValidationErrors, importFile, isModelNotFoundError, isValidationError, loadPrototypes, logUnhandledError, nodeEnv, normalizeStatusCode, outputDir, serializeError, shouldHideStack, shouldLogError, toErrorShape };
188
+ export { AbstractModelConstructor, AppException, ArkstackErrorPayload, ArkstackErrorShape, DotPathValue, Encryption, ErrorHandler, Exception, GlobalConfig, GlobalEnv, Hash, Logger, LoggerChalk, LoggerLog, LoggerParseSignature, ModelConstructor, ModelRegistry, RequestException, appUrl, bindGracefulShutdown, bootWithDetectedPort, buildHtmlErrorResponse, config, createErrorPayload, env, getErrorLogger, getModel, getPrimaryError, getValidationErrors, importFile, isModelNotFoundError, isValidationError, loadPrototypes, logUnhandledError, nodeEnv, normalizeStatusCode, outputDir, perPage, serializeError, shouldHideStack, shouldLogError, toErrorShape };
120
189
  //# sourceMappingURL=index.d.ts.map
package/dist/index.js CHANGED
@@ -7,6 +7,10 @@ import { readdirSync } from "fs";
7
7
  import { detect } from "detect-port";
8
8
  import pino from "pino";
9
9
  import chalk from "chalk";
10
+ import { createCipheriv, createDecipheriv, createHash, randomBytes } from "node:crypto";
11
+ import { Secret, TOTP } from "otpauth";
12
+ import { compare, genSalt, hash } from "bcryptjs";
13
+ import { getUserConfig } from "arkormx";
10
14
 
11
15
  //#region src/lifecycle.ts
12
16
  const bindGracefulShutdown = (shutdown) => {
@@ -210,96 +214,169 @@ const loadPrototypes = () => {
210
214
  };
211
215
 
212
216
  //#endregion
213
- //#region src/error-handling.ts
214
- const loggerCache = /* @__PURE__ */ new Map();
215
- const isRecord = (value) => typeof value === "object" && value !== null;
216
- const toErrorShape = (value) => isRecord(value) ? value : void 0;
217
- const normalizeStatusCode = (value, fallback = 500) => {
218
- const code = typeof value === "number" ? value : Number(value);
219
- return Number.isInteger(code) && code >= 100 && code < 600 ? code : fallback;
220
- };
221
- const getErrorLogger = () => {
222
- const destination = path.resolve(process.cwd(), "storage/logs/error.log");
223
- if (!loggerCache.has(destination)) loggerCache.set(destination, pino({ level: "error" }, pino.destination({
224
- dest: destination,
225
- mkdir: true,
226
- sync: false
227
- })));
228
- return loggerCache.get(destination);
229
- };
230
- const serializeError = (value, seen = /* @__PURE__ */ new WeakSet()) => {
231
- if (Array.isArray(value)) return value.map((entry) => serializeError(entry, seen));
232
- if (!isRecord(value)) return value;
233
- if (seen.has(value)) return "[Circular]";
234
- seen.add(value);
235
- const serialized = {};
236
- if (value instanceof Error) {
237
- serialized.name = value.name;
238
- serialized.message = value.message;
239
- serialized.stack = value.stack;
240
- }
241
- for (const key of Reflect.ownKeys(value)) {
242
- const property = typeof key === "string" ? key : key.toString();
243
- const descriptor = Object.getOwnPropertyDescriptor(value, key);
244
- if (!descriptor || !("value" in descriptor)) continue;
245
- serialized[property] = serializeError(descriptor.value, seen);
246
- }
247
- return serialized;
248
- };
249
- const getPrimaryError = (error) => {
250
- if (typeof error === "string") return error;
251
- return toErrorShape(error.cause) ?? error;
252
- };
253
- const getValidationErrors = (error) => {
254
- if (typeof error.errors === "function") return error.errors();
255
- return error.errors;
256
- };
257
- const isValidationError = (error) => {
258
- return typeof toErrorShape(error)?.errors !== "undefined";
259
- };
260
- const isModelNotFoundError = (error) => {
261
- return typeof toErrorShape(error)?.getModelName === "function";
217
+ //#region src/Exceptions/Exception.ts
218
+ var Exception = class extends Error {
219
+ name;
220
+ constructor(message, options) {
221
+ super(message, options);
222
+ this.name = "Exception";
223
+ }
262
224
  };
263
- const shouldHideStack = () => {
264
- const value = process.env.HIDE_ERROR_STACK;
265
- return value === "true" || value === "1" || value === "on";
225
+
226
+ //#endregion
227
+ //#region src/Exceptions/AppException.ts
228
+ var AppException = class extends Exception {
229
+ errors = void 0;
230
+ statusCode;
231
+ constructor(message, statusCode = 400, options) {
232
+ super(message, options);
233
+ this.statusCode = statusCode;
234
+ }
266
235
  };
267
- const shouldLogError = (error) => !isValidationError(error) && !isModelNotFoundError(error);
268
- const createErrorPayload = (err, fallbackMessage = "Something went wrong") => {
269
- const primaryError = getPrimaryError(err);
270
- const detailedError = typeof primaryError === "string" ? void 0 : primaryError;
271
- const validationError = detailedError && isValidationError(detailedError) ? detailedError : void 0;
272
- const modelNotFoundError = detailedError && isModelNotFoundError(detailedError) ? detailedError : void 0;
273
- const payload = {
274
- status: "error",
275
- code: typeof err === "string" ? 500 : normalizeStatusCode(detailedError?.statusCode ?? detailedError?.status),
276
- message: typeof err === "string" ? `${fallbackMessage}: ${err}` : detailedError?.message || err.message || fallbackMessage
277
- };
278
- if (validationError) {
279
- payload.code = normalizeStatusCode(validationError.statusCode ?? validationError.status, 422);
280
- payload.message = validationError.message || fallbackMessage;
281
- payload.errors = getValidationErrors(validationError);
282
- } else if (modelNotFoundError) {
283
- payload.code = 404;
284
- payload.message = `${modelNotFoundError.getModelName?.()} not found!`;
285
- } else if (detailedError?.stack) {
286
- const [stackLine, ...rest] = detailedError.stack.split("\n");
287
- const [key, content = ""] = stackLine.split(":");
288
- payload.errors = { [key]: [content.trim(), ...rest.map((entry) => entry.trim())] };
289
- }
290
- if (detailedError && process.env.NODE_ENV === "development" && !shouldHideStack() && !validationError) payload.stack = detailedError.stack;
291
- if (!validationError || payload.code === 404) {
292
- delete payload.errors;
293
- delete payload.stack;
294
- }
295
- return payload;
236
+
237
+ //#endregion
238
+ //#region src/Exceptions/RequestException.ts
239
+ var RequestException = class RequestException extends AppException {
240
+ statusCode;
241
+ constructor(message, statusCode = 400, options) {
242
+ super(message, statusCode, options);
243
+ this.statusCode = statusCode;
244
+ }
245
+ /**
246
+ * Asserts that a value is not null or undefined.
247
+ *
248
+ * @param value
249
+ * @param message
250
+ * @param code
251
+ * @throws {RequestException} Throws if the value is null or undefined.
252
+ */
253
+ static assertNotEmpty(value, message, code = 404) {
254
+ if (!value) throw new RequestException(message, code);
255
+ }
256
+ /**
257
+ * Asserts that a boolean condition is true.
258
+ *
259
+ * @param boolean
260
+ * @param message
261
+ * @param code
262
+ * @throws {RequestException} Throws if the boolean condition is true.
263
+ */
264
+ static abortIf(boolean, message, code) {
265
+ if (boolean) throw new RequestException(message, code);
266
+ }
296
267
  };
297
- const logUnhandledError = (err, request, message) => {
298
- getErrorLogger().error({
299
- error: serializeError(err),
300
- request
301
- }, message);
268
+
269
+ //#endregion
270
+ //#region src/ErrorHandler.ts
271
+ var ErrorHandler = class ErrorHandler {
272
+ static loggerCache = /* @__PURE__ */ new Map();
273
+ static isRecord(value) {
274
+ return typeof value === "object" && value !== null;
275
+ }
276
+ static toErrorShape(value) {
277
+ return ErrorHandler.isRecord(value) ? value : void 0;
278
+ }
279
+ static normalizeStatusCode(value, fallback = 500) {
280
+ const code = typeof value === "number" ? value : Number(value);
281
+ return Number.isInteger(code) && code >= 100 && code < 600 ? code : fallback;
282
+ }
283
+ static getErrorLogger() {
284
+ const destination = path.resolve(process.cwd(), "storage/logs/error.log");
285
+ if (!ErrorHandler.loggerCache.has(destination)) ErrorHandler.loggerCache.set(destination, pino({ level: "error" }, pino.destination({
286
+ dest: destination,
287
+ mkdir: true,
288
+ sync: false
289
+ })));
290
+ return ErrorHandler.loggerCache.get(destination);
291
+ }
292
+ static serializeError(value, seen = /* @__PURE__ */ new WeakSet()) {
293
+ if (Array.isArray(value)) return value.map((entry) => ErrorHandler.serializeError(entry, seen));
294
+ if (!ErrorHandler.isRecord(value)) return value;
295
+ if (seen.has(value)) return "[Circular]";
296
+ seen.add(value);
297
+ const serialized = {};
298
+ if (value instanceof Error) {
299
+ serialized.name = value.name;
300
+ serialized.message = value.message;
301
+ serialized.stack = value.stack;
302
+ }
303
+ for (const key of Reflect.ownKeys(value)) {
304
+ const property = typeof key === "string" ? key : key.toString();
305
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
306
+ if (!descriptor || !("value" in descriptor)) continue;
307
+ serialized[property] = ErrorHandler.serializeError(descriptor.value, seen);
308
+ }
309
+ return serialized;
310
+ }
311
+ static getPrimaryError(error) {
312
+ if (typeof error === "string") return error;
313
+ return ErrorHandler.toErrorShape(error.cause) ?? error;
314
+ }
315
+ static getValidationErrors(error) {
316
+ if (typeof error.errors === "function") return error.errors();
317
+ return error.errors;
318
+ }
319
+ static isValidationError(error) {
320
+ return typeof ErrorHandler.toErrorShape(error)?.errors !== "undefined";
321
+ }
322
+ static isModelNotFoundError(error) {
323
+ return typeof ErrorHandler.toErrorShape(error)?.getModelName === "function";
324
+ }
325
+ static shouldHideStack() {
326
+ const value = process.env.HIDE_ERROR_STACK;
327
+ return value === "true" || value === "1" || value === "on";
328
+ }
329
+ static shouldLogError(error) {
330
+ return !ErrorHandler.isValidationError(error) && !ErrorHandler.isModelNotFoundError(error);
331
+ }
332
+ static createErrorPayload(err, fallbackMessage = "Something went wrong") {
333
+ const primaryError = ErrorHandler.getPrimaryError(err);
334
+ const detailedError = typeof primaryError === "string" ? void 0 : primaryError;
335
+ const validationError = detailedError && ErrorHandler.isValidationError(detailedError) ? detailedError : void 0;
336
+ const modelNotFoundError = detailedError && ErrorHandler.isModelNotFoundError(detailedError) ? detailedError : void 0;
337
+ const payload = {
338
+ status: "error",
339
+ code: typeof err === "string" ? 500 : ErrorHandler.normalizeStatusCode(detailedError?.statusCode ?? detailedError?.status),
340
+ message: typeof err === "string" ? `${fallbackMessage}: ${err}` : detailedError?.message || err.message || fallbackMessage
341
+ };
342
+ if (validationError) {
343
+ payload.code = ErrorHandler.normalizeStatusCode(validationError.statusCode ?? validationError.status, 422);
344
+ payload.message = validationError.message || fallbackMessage;
345
+ payload.errors = ErrorHandler.getValidationErrors(validationError);
346
+ } else if (modelNotFoundError) {
347
+ payload.code = 404;
348
+ payload.message = `${modelNotFoundError.getModelName?.()} not found!`;
349
+ } else if (detailedError?.stack) {
350
+ const [stackLine, ...rest] = detailedError.stack.split("\n");
351
+ const [key, content = ""] = stackLine.split(":");
352
+ payload.errors = { [key]: [content.trim(), ...rest.map((entry) => entry.trim())] };
353
+ }
354
+ if (detailedError && process.env.NODE_ENV === "development" && !ErrorHandler.shouldHideStack() && !validationError) payload.stack = detailedError.stack;
355
+ if (!validationError || payload.code === 404) {
356
+ delete payload.errors;
357
+ delete payload.stack;
358
+ }
359
+ return payload;
360
+ }
361
+ static logUnhandledError(err, request, message) {
362
+ ErrorHandler.getErrorLogger().error({
363
+ error: ErrorHandler.serializeError(err),
364
+ request
365
+ }, message);
366
+ }
302
367
  };
368
+ const toErrorShape = ErrorHandler.toErrorShape;
369
+ const normalizeStatusCode = ErrorHandler.normalizeStatusCode;
370
+ const getErrorLogger = ErrorHandler.getErrorLogger;
371
+ const serializeError = ErrorHandler.serializeError;
372
+ const getPrimaryError = ErrorHandler.getPrimaryError;
373
+ const getValidationErrors = ErrorHandler.getValidationErrors;
374
+ const isValidationError = ErrorHandler.isValidationError;
375
+ const isModelNotFoundError = ErrorHandler.isModelNotFoundError;
376
+ const shouldHideStack = ErrorHandler.shouldHideStack;
377
+ const shouldLogError = ErrorHandler.shouldLogError;
378
+ const createErrorPayload = ErrorHandler.createErrorPayload;
379
+ const logUnhandledError = ErrorHandler.logUnhandledError;
303
380
 
304
381
  //#endregion
305
382
  //#region src/Logger.ts
@@ -506,5 +583,109 @@ var Logger = class Logger {
506
583
  };
507
584
 
508
585
  //#endregion
509
- export { Logger, appUrl, bindGracefulShutdown, bootWithDetectedPort, buildHtmlErrorResponse, config, createErrorPayload, env, getErrorLogger, getPrimaryError, getValidationErrors, importFile, isModelNotFoundError, isValidationError, loadPrototypes, logUnhandledError, nodeEnv, normalizeStatusCode, outputDir, serializeError, shouldHideStack, shouldLogError, toErrorShape };
586
+ //#region src/utils/encryption.ts
587
+ var Encryption = class {
588
+ static algorithm = "aes-256-gcm";
589
+ static getKey() {
590
+ const secret = env("TWO_FACTOR_ENCRYPTION_KEY");
591
+ if (!secret) throw new Error("TWO_FACTOR_ENCRYPTION_KEY is required to use two-factor authentication");
592
+ return createHash("sha256").update(secret).digest();
593
+ }
594
+ static encrypt(value) {
595
+ const iv = randomBytes(12);
596
+ const cipher = createCipheriv(this.algorithm, this.getKey(), iv);
597
+ const ciphertext = Buffer.concat([cipher.update(value, "utf8"), cipher.final()]);
598
+ return [
599
+ iv,
600
+ cipher.getAuthTag(),
601
+ ciphertext
602
+ ].map((part) => part.toString("base64url")).join(":");
603
+ }
604
+ static decrypt(payload) {
605
+ const [iv, authTag, ciphertext] = payload.split(":");
606
+ if (!iv || !authTag || !ciphertext) throw new Error("Invalid encrypted payload format");
607
+ const decipher = createDecipheriv(this.algorithm, this.getKey(), Buffer.from(iv, "base64url"));
608
+ decipher.setAuthTag(Buffer.from(authTag, "base64url"));
609
+ return Buffer.concat([decipher.update(Buffer.from(ciphertext, "base64url")), decipher.final()]).toString("utf8");
610
+ }
611
+ };
612
+
613
+ //#endregion
614
+ //#region src/utils/hash.ts
615
+ var Hash = class {
616
+ /**
617
+ * Hash a value using bcrypt
618
+ *
619
+ * @param value
620
+ * @returns
621
+ */
622
+ static async make(value) {
623
+ return await hash(value, await genSalt(10));
624
+ }
625
+ /**
626
+ * Verify a value against a hashed value
627
+ *
628
+ * @param value
629
+ * @param hashedValue
630
+ * @returns
631
+ */
632
+ static async verify(value, hashedValue) {
633
+ return await compare(value, hashedValue);
634
+ }
635
+ /**
636
+ * Generate a one-time password (OTP) using TOTP algorithm
637
+ *
638
+ * @param digits The number of digits for the OTP, default is 6.
639
+ * @param label A label to identify the OTP, can be an email or phone number.
640
+ * @param period Interval of time for which a token is valid, in seconds.
641
+ * @returns
642
+ */
643
+ static otp(digits = 6, label = "Alice", period = 30) {
644
+ return new TOTP({
645
+ label,
646
+ digits,
647
+ issuer: env("APP_NAME", "Roseed"),
648
+ algorithm: "SHA1",
649
+ period,
650
+ secret: "US3WHSG7X5KAPV27VANWKQHF3SH3HULL"
651
+ });
652
+ }
653
+ static totp(secret, label, issuer = env("APP_NAME", "Roseed"), period = 30) {
654
+ return new TOTP({
655
+ issuer,
656
+ label,
657
+ algorithm: "SHA1",
658
+ digits: 6,
659
+ period,
660
+ secret: Secret.fromBase32(secret)
661
+ });
662
+ }
663
+ };
664
+
665
+ //#endregion
666
+ //#region src/utils/helpers.ts
667
+ /**
668
+ * Determine the number of items to return per page based on the provided query parameters.
669
+ *
670
+ * @param query
671
+ * @returns
672
+ */
673
+ const perPage = (query) => {
674
+ const requestedPerPage = Number(query.limit ?? query.perPage ?? 15);
675
+ return Number.isFinite(requestedPerPage) && requestedPerPage > 0 ? Math.min(requestedPerPage, 50) : 15;
676
+ };
677
+ async function getModel(modelName) {
678
+ const resolveModelExport = (module, modelName) => {
679
+ if (!isModelModule(module)) return module;
680
+ return module.default ?? module[modelName] ?? module;
681
+ };
682
+ const isModelModule = (value) => typeof value === "object" && value !== null;
683
+ const modelPath = getUserConfig().paths?.models || "./src/models";
684
+ const model = resolveModelExport(await importFile(path.join(path.isAbsolute(modelPath) ? modelPath : path.join(process.cwd(), modelPath), modelName)), path.basename(modelName, path.extname(modelName)));
685
+ if (typeof model !== "function") throw new Error(`Model "${modelName}" not found`);
686
+ return model;
687
+ }
688
+
689
+ //#endregion
690
+ export { AppException, Encryption, ErrorHandler, Exception, Hash, Logger, RequestException, appUrl, bindGracefulShutdown, bootWithDetectedPort, buildHtmlErrorResponse, config, createErrorPayload, env, getErrorLogger, getModel, getPrimaryError, getValidationErrors, importFile, isModelNotFoundError, isValidationError, loadPrototypes, logUnhandledError, nodeEnv, normalizeStatusCode, outputDir, perPage, serializeError, shouldHideStack, shouldLogError, toErrorShape };
510
691
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../src/lifecycle.ts","../src/system.ts","../src/network.ts","../src/prototypes.ts","../src/error-handling.ts","../src/Logger.ts"],"sourcesContent":["export const bindGracefulShutdown = (shutdown: () => Promise<void> | void) => {\n ['SIGINT', 'SIGTERM', 'SIGQUIT'].forEach((signal) => {\n process.on(signal, async () => {\n await shutdown()\n })\n })\n}\n","import { DotPath, Obj } from '@h3ravel/support'\nimport { GlobalConfig, GlobalEnv } from './types'\n\n// TODO: @rexxars/jiti has to be replaced with jiti once a new release is available. See https://github.com/unjs/jiti/pull/427\nimport { createJiti } from '@rexxars/jiti'\nimport { createRequire } from 'module'\nimport path from 'node:path'\nimport { pathToFileURL } from 'node:url'\nimport { readdirSync } from 'fs'\nimport { resolve } from 'node:path'\n\n/**\n * Read the .env file\n *\n * @param env\n * @param def\n * @returns\n */\nexport const env: GlobalEnv = <X = string, Y = undefined | X> (\n env: string,\n defaultValue?: Y,\n) => {\n let val: string | number | boolean | undefined | null = process.env[env] ?? ''\n\n if ([true, 'true', 'on', false, 'false', 'off'].includes(val)) {\n val = [true, 'true', 'on'].includes(val)\n }\n\n if (!isNaN(Number(val)) && typeof val !== 'boolean' && typeof val !== 'undefined' && val !== '') {\n val = Number(val)\n }\n\n if (val === '') {\n val = undefined\n }\n\n if (val === 'null') {\n val = null\n }\n\n val ??= defaultValue as typeof val\n\n return val as Y extends undefined ? X : Y\n}\n\n/**\n * Build the app url\n *\n * @param link\n * @returns\n */\nexport const appUrl = (link?: string): string => {\n const port = env('PORT') || '3000'\n const defaultUrl = `http://localhost:${port}`\n const appUrl = env('APP_URL') ?? defaultUrl\n\n try {\n const url = new URL(appUrl)\n // Append port only if APP_URL has a port or is localhost\n if (url.port || url.hostname === 'localhost') {\n url.port = port\n }\n // Remove trailing slash from base URL\n const baseUrl = url.toString().replace(/\\/$/, '')\n // Append link with proper path separator\n if (link) {\n // Ensure link starts with '/' and remove duplicate slashes\n const normalizedLink = `/${link.replace(/^\\/+/, '')}`\n\n return `${baseUrl}${normalizedLink}`\n }\n\n return baseUrl\n } catch {\n // Return default URL with link if provided\n return link ? `${defaultUrl}/${link.replace(/^\\/+/, '')}` : defaultUrl\n }\n}\n\n/**\n * Gets the application configuration.\n * \n * @param key The configuration key to retrieve.\n * @param defaultValue The default value to return if the key is not found.\n * @returns The configuration value.\n */\nexport const config: GlobalConfig = <X extends Record<string, any>, P extends DotPath<X> | undefined = undefined> (\n key?: P,\n defaultValue?: any\n) => {\n const dist = path.relative(process.cwd(), outputDir())\n const require = createRequire(import.meta.url)\n\n const files = readdirSync(path.join(process.cwd(), `${dist}/config`), { withFileTypes: true })\n .filter(file => {\n if (file.name.includes('middleware') && globalThis.arkctx.runtime === 'CLI') return false\n\n return file.isFile() && (file.name.endsWith('.js') || file.name.endsWith('.ts'))\n })\n\n const config = files.reduce((configs, file) => {\n const configName = path.basename(file.name, path.extname(file.name))\n\n configs[configName] = require(path.join(file.parentPath, file.name))\n .default((globalThis as any).app())\n\n return configs\n }, {} as Record<string, any>) as X\n\n\n if (key) {\n return Obj.get(config, key, defaultValue)\n }\n\n return config\n}\n\n/**\n * Gets the current Node environment (development or production).\n * \n * @returns \n */\nexport const nodeEnv = () => {\n let envValue = env<'development' | 'production'>('NODE_ENV', 'development')\n\n if (envValue !== 'development' && envValue !== 'production') {\n envValue = 'development'\n }\n\n return envValue === 'production' ? 'prod' : 'dev'\n}\n\n/**\n * Gets the output directory for the application based on the current environment.\n * \n * @param cwd The current working directory (optional, defaults to process.cwd()).\n * @returns \n */\nexport const outputDir = (cwd = process.cwd()) => {\n const NODE_ENV = nodeEnv()\n\n const output = {\n dev: env('OUTPUT_DIR_DEV', '.arkstack/build'),\n prod: env('OUTPUT_DIR', 'dist'),\n }\n\n return path.isAbsolute(output[NODE_ENV] ?? output.dev)\n ? (output[NODE_ENV] ?? output.dev)\n : path.join(cwd, output[NODE_ENV] ?? output.dev)\n}\n\n\nexport const importFile = async <T = unknown> (filePath: string): Promise<T> => {\n const resolvedPath = resolve(filePath)\n const jiti = createJiti(pathToFileURL(resolvedPath).href, {\n interopDefault: false,\n tsconfigPaths: true,\n })\n\n return await jiti.import<T>(resolvedPath)\n}","import { config, env } from './system'\n\nimport { detect } from 'detect-port'\n\nexport const bootWithDetectedPort = async (\n boot: (port: number) => Promise<void>,\n preferredPort: number = 3000,\n app?: any\n) => {\n if (app && !globalThis.app)\n globalThis.app = () => app\n globalThis.env = env\n globalThis.config = config\n globalThis.arkctx = {\n runtime: 'HTTP',\n }\n const port = await detect(preferredPort)\n await boot(port)\n}\n\n\nexport const buildHtmlErrorResponse = ({\n message = 'An unexpected error occurred.',\n stack,\n title,\n code = 500,\n}: {\n message?: string;\n stack?: string;\n code?: number;\n title?: string;\n}) => {\n const titleMap: Record<number, string> = {\n 400: 'Bad Request',\n 401: 'Unauthorized',\n 403: 'Forbidden',\n 404: 'Not Found',\n 500: 'Internal Server Error',\n 502: 'Bad Gateway',\n 503: 'Service Unavailable',\n 504: 'Gateway Timeout',\n }\n\n title = titleMap[code] || title || 'Error'\n\n return `\n <html>\n <head>\n <title>${code} | ${title}</title>\n <style>\n body {\n font-family: Arial, sans-serif;\n background-color: #f8f8f8;\n color: #333;\n padding: 20px;\n }\n h1 {\n color: #e74c3c;\n }\n h3 {\n color: #3498db;\n }\n p {\n color: #555;\n }\n pre {\n background-color: #eee;\n padding: 10px;\n border-radius: 5px;\n overflow-x: auto;\n }\n </style>\n </head>\n <body>\n <h1>${code}</h1>\n <h3>${title}</h3>\n <p>${message}</p>\n ${stack ? `<h2>Stack Trace:</h2><pre>${stack}</pre>` : ''}\n </body>\n </html>\n `\n}","export const loadPrototypes = () => {\n String.prototype.titleCase = function () {\n return this.toLowerCase()\n .replace(/_/g, ' ')\n .replace(/-/g, ' ')\n .replace(/(?:^|\\s)\\w/g, function (match) {\n return match.toUpperCase()\n })\n }\n\n String.prototype.camelCase = function () {\n return this.replace(/(?:^\\w|[A-Z]|\\b\\w|\\s+)/g, function (match, index) {\n if (+match === 0) return '' // or if (/\\s+/.test(match)) for white spaces\n\n return index === 0 ? match.toLowerCase() : match.toUpperCase()\n })\n }\n\n String.prototype.pascalCase = function () {\n return this.replace(/(?:^\\w|[A-Z]|\\b\\w|\\s+)/g, function (match) {\n return match.toUpperCase()\n })\n }\n\n String.prototype.truncate = function (len: number = 20, suffix: string = '...') {\n if (this.length <= len) {\n return this.toString()\n }\n\n const truncated = this.substring(0, len)\n const lastSpaceIndex = truncated.lastIndexOf(' ')\n if (lastSpaceIndex > 0) {\n return truncated.substring(0, lastSpaceIndex) + suffix\n }\n\n return truncated + suffix\n }\n} \n","import pino, { type Logger as PinoLogger } from 'pino'\nimport path from 'node:path'\nimport { ArkstackErrorPayload, ArkstackErrorShape } from './types'\n\nconst loggerCache = new Map<string, PinoLogger>()\n\nconst isRecord = (value: unknown): value is Record<string, unknown> => (\n typeof value === 'object' && value !== null\n)\n\nexport const toErrorShape = (value: unknown): ArkstackErrorShape | undefined => (\n isRecord(value) ? value as unknown as ArkstackErrorShape : undefined\n)\n\nexport const normalizeStatusCode = (value: unknown, fallback: number = 500) => {\n const code = typeof value === 'number' ? value : Number(value)\n\n return Number.isInteger(code) && code >= 100 && code < 600 ? code : fallback\n}\n\nexport const getErrorLogger = () => {\n const destination = path.resolve(process.cwd(), 'storage/logs/error.log')\n\n if (!loggerCache.has(destination)) {\n loggerCache.set(destination, pino({\n level: 'error',\n }, pino.destination({\n dest: destination,\n mkdir: true,\n sync: false,\n })))\n }\n\n return loggerCache.get(destination)!\n}\n\nexport const serializeError = (value: unknown, seen: WeakSet<object> = new WeakSet()): unknown => {\n if (Array.isArray(value)) {\n return value.map((entry) => serializeError(entry, seen))\n }\n\n if (!isRecord(value)) {\n return value\n }\n\n if (seen.has(value)) {\n return '[Circular]'\n }\n\n seen.add(value)\n\n const serialized: Record<string, unknown> = {}\n\n if (value instanceof Error) {\n serialized.name = value.name\n serialized.message = value.message\n serialized.stack = value.stack\n }\n\n for (const key of Reflect.ownKeys(value)) {\n const property = typeof key === 'string' ? key : key.toString()\n const descriptor = Object.getOwnPropertyDescriptor(value, key)\n\n if (!descriptor || !('value' in descriptor)) {\n continue\n }\n\n serialized[property] = serializeError(descriptor.value, seen)\n }\n\n return serialized\n}\n\nexport const getPrimaryError = (error: ArkstackErrorShape | string) => {\n if (typeof error === 'string') {\n return error\n }\n\n return toErrorShape(error.cause) ?? error\n}\n\nexport const getValidationErrors = (error: ArkstackErrorShape) => {\n if (typeof error.errors === 'function') {\n return error.errors()\n }\n\n return error.errors\n}\n\nexport const isValidationError = (error: unknown): error is ArkstackErrorShape => {\n const candidate = toErrorShape(error)\n\n return typeof candidate?.errors !== 'undefined'\n}\n\nexport const isModelNotFoundError = (error: unknown): error is ArkstackErrorShape => {\n const candidate = toErrorShape(error)\n\n return typeof candidate?.getModelName === 'function'\n}\n\nexport const shouldHideStack = () => {\n const value = process.env.HIDE_ERROR_STACK\n\n return value === 'true' || value === '1' || value === 'on'\n}\n\nexport const shouldLogError = (error: unknown) =>\n !isValidationError(error) &&\n !isModelNotFoundError(error)\n\nexport const createErrorPayload = (\n err: ArkstackErrorShape | string,\n fallbackMessage: string = 'Something went wrong',\n): ArkstackErrorPayload => {\n const primaryError = getPrimaryError(err)\n const detailedError = typeof primaryError === 'string'\n ? undefined\n : primaryError\n const validationError = detailedError && isValidationError(detailedError)\n ? detailedError\n : undefined\n const modelNotFoundError = detailedError && isModelNotFoundError(detailedError)\n ? detailedError\n : undefined\n const payload: ArkstackErrorPayload = {\n status: 'error',\n code: typeof err === 'string'\n ? 500\n : normalizeStatusCode(detailedError?.statusCode ?? detailedError?.status),\n message: typeof err === 'string'\n ? `${fallbackMessage}: ${err}`\n : detailedError?.message || err.message || fallbackMessage,\n }\n\n if (validationError) {\n payload.code = normalizeStatusCode(validationError.statusCode ?? validationError.status, 422)\n payload.message = validationError.message || fallbackMessage\n payload.errors = getValidationErrors(validationError)\n } else if (modelNotFoundError) {\n payload.code = 404\n payload.message = `${modelNotFoundError.getModelName?.()} not found!`\n } else if (detailedError?.stack) {\n const [stackLine, ...rest] = detailedError.stack.split('\\n')\n const [key, content = ''] = stackLine.split(':')\n\n payload.errors = {\n [key]: [content.trim(), ...rest.map((entry: string) => entry.trim())]\n }\n }\n\n if (\n detailedError &&\n process.env.NODE_ENV === 'development' &&\n !shouldHideStack() &&\n !validationError\n ) {\n payload.stack = detailedError.stack\n }\n\n if (!validationError || payload.code === 404) {\n delete payload.errors\n delete payload.stack\n }\n\n return payload\n}\n\nexport const logUnhandledError = (\n err: unknown,\n request: Record<string, unknown>,\n message: string,\n) => {\n getErrorLogger().error({\n error: serializeError(err),\n request,\n }, message)\n}","import chalk, { type ChalkInstance } from 'chalk'\nimport { LoggerChalk, LoggerLog, LoggerParseSignature } from './types'\n\nclass Console {\n static log = (...args: any[]) => Logger.log(args.map(e => [e, 'white']))\n static debug = (...args: any[]) => Logger.debug(args, false, true)\n static warn = (...args: any[]) => args.map(e => Logger.warn(e, false, true))\n static info = (...args: any[]) => args.map(e => Logger.info(e, false, true))\n static error = (...args: any[]) => args.map(e => Logger.error(e, false), true)\n}\n\nexport class Logger {\n /**\n * Global verbosity configuration\n */\n private static verbosity: number = 0\n private static isQuiet: boolean = false\n private static isSilent: boolean = false\n\n /**\n * Configure global verbosity levels\n */\n static configure (options: { verbosity?: number, quiet?: boolean, silent?: boolean } = {}) {\n this.verbosity = options.verbosity ?? 0\n this.isQuiet = options.quiet ?? false\n this.isSilent = options.silent ?? false\n }\n\n /**\n * Check if output should be suppressed\n */\n private static shouldSuppressOutput (level: 'line' | 'debug' | 'info' | 'warn' | 'error' | 'success'): boolean {\n if (this.isSilent) return true\n if (this.isQuiet && (level === 'info' || level === 'success')) return true\n if (level === 'debug' && this.verbosity < 3) return true\n\n return false\n }\n /**\n * Logs the message in two columns\n * \n * @param name \n * @param value \n * @param log If set to false, array of [name, dots, value] output will be returned and not logged \n * @returns \n */\n static twoColumnDetail (name: string, value: string, log?: true, spacer?: string): void\n static twoColumnDetail (name: string, value: string, log?: false, spacer?: string): [string, string, string]\n static twoColumnDetail (name: string, value: string, log = true, spacer = '.'): [string, string, string] | void {\n // eslint-disable-next-line no-control-regex\n const regex = /\\x1b\\[\\d+m/g\n const width = Math.max(process.stdout.columns, 100)\n const dots = Math.max(width - name.replace(regex, '').length - value.replace(regex, '').length - 10, 0)\n\n if (log) return console.log(name, chalk.gray(spacer.repeat(dots)), value)\n else return [name, chalk.gray(spacer.repeat(dots)), value]\n }\n\n /**\n * Logs the message in two columns\n * \n * @param name \n * @param desc \n * @param width \n * @param log If set to false, array of [name, dots, value] output will be returned and not logged \n * @returns \n */\n static describe (name: string, desc: string, width?: number, log?: true): void\n static describe (name: string, desc: string, width?: number, log?: false): [string, string, string]\n static describe (name: string, desc: string, width = 50, log = true): [string, string, string] | void {\n width = Math.max(width, 30)\n // eslint-disable-next-line no-control-regex\n const regex = /\\x1b\\[\\d+m/g\n const dots = Math.max(width - name.replace(regex, '').length, 0)\n\n if (log) return console.log(name, ' '.repeat(dots), desc)\n else return [name, ' '.repeat(dots), desc]\n }\n\n /**\n * Logs the message in two columns but allways passing status\n * \n * @param name \n * @param value \n * @param status \n * @param exit \n * @param preserveCol \n */\n static split (name: string, value: string, status?: 'success' | 'info' | 'error', exit = false, preserveCol = false, spacer = '.') {\n status ??= 'info'\n const color = { success: chalk.bgGreen, info: chalk.bgBlue, error: chalk.bgRed }\n\n const [_name, dots, val] = this.twoColumnDetail(name, value, false, spacer)\n\n console.log(this.textFormat(_name, color[status], preserveCol), dots, val)\n\n if (exit) process.exit(0)\n }\n\n /**\n * Wraps text with chalk\n * \n * @param txt \n * @param color \n * @param preserveCol \n * @returns \n */\n static textFormat (\n txt: unknown | unknown[],\n color: (...text: unknown[]) => string,\n preserveCol = false\n ): string {\n if (txt instanceof Error) {\n const err: Error & { code?: number, statusCode?: number } = txt\n const code = err.code ?? err.statusCode ? ` (${err.code ?? err.statusCode})` : ''\n const output: string[] = []\n\n if (err.message) {\n output.push(this.textFormat(`${err.constructor.name}${code}: ${err.message}`, chalk.bgRed, preserveCol))\n }\n\n if (err.stack) {\n output.push(' ' + chalk.white(err.stack.replace(`${err.name}: ${err.message}`, '').trim()))\n }\n\n return output.join('\\n')\n }\n\n if (Array.isArray(txt)) {\n return txt.map(e => this.textFormat(e, color, preserveCol)).join('\\n')\n }\n\n if (typeof txt === 'object') {\n return this.textFormat(Object.values(txt!), color, preserveCol)\n }\n\n if (typeof txt !== 'string') {\n return color(txt)\n }\n\n const str = String(txt)\n\n if (preserveCol) return str\n\n const [first, ...rest] = str.split(':')\n if (rest.length === 0) return str\n\n return color(` ${first} `) + rest.join(':')\n }\n\n /**\n * Logs a success message\n * \n * @param msg \n * @param exit \n * @param preserveCol \n */\n static success (msg: any, exit = false, preserveCol = false) {\n if (!this.shouldSuppressOutput('success')) {\n console.log(chalk.green('✓'), this.textFormat(msg, chalk.bgGreen, preserveCol))\n }\n if (exit) process.exit(0)\n }\n\n /**\n * Logs an informational message\n * \n * @param msg \n * @param exit \n * @param preserveCol \n */\n static info (msg: any, exit = false, preserveCol = false) {\n if (!this.shouldSuppressOutput('info')) {\n console.log(chalk.blue('ℹ'), this.textFormat(msg, chalk.bgBlue, preserveCol))\n }\n if (exit) process.exit(0)\n }\n\n /**\n * Logs an error message\n * \n * @param msg \n * @param exit \n * @param preserveCol \n */\n static error (msg: any, exit = true, preserveCol = false) {\n if (!this.shouldSuppressOutput('error')) {\n if (msg instanceof Error) {\n if (msg.message) {\n console.error(chalk.red('✖'), this.textFormat('ERROR:' + msg.message, chalk.bgRed, preserveCol))\n }\n console.error(chalk.red(`${(msg as any).detail ? `${(msg as any).detail}\\n` : ''}${msg.stack}`))\n } else {\n console.error(chalk.red('✖'), this.textFormat(msg, chalk.bgRed, preserveCol))\n }\n }\n if (exit) process.exit(1)\n }\n\n /**\n * Logs a warning message\n * \n * @param msg \n * @param exit \n * @param preserveCol \n */\n static warn (msg: any, exit = false, preserveCol = false) {\n if (!this.shouldSuppressOutput('warn')) {\n console.warn(chalk.yellow('⚠'), this.textFormat(msg, chalk.bgYellow, preserveCol))\n }\n if (exit) process.exit(0)\n }\n\n /**\n * Logs a debug message (only shown with verbosity >= 3)\n * \n * @param msg \n * @param exit \n * @param preserveCol \n */\n static debug<M = any> (msg: M | M[], exit = false, preserveCol = false) {\n if (!this.shouldSuppressOutput('debug')) {\n if (Array.isArray(msg)) {\n for (let i = 0; i < msg.length; i++) {\n console.log(chalk.gray('🐛'), chalk.bgGray(i + 1), this.textFormat(msg[i], chalk.bgGray, preserveCol))\n }\n } else {\n console.log(chalk.gray('🐛'), this.textFormat(msg, chalk.bgGray, preserveCol))\n }\n }\n if (exit) process.exit(0)\n }\n\n /**\n * Terminates the process\n */\n static quiet () {\n process.exit(0)\n }\n\n static chalker (styles: LoggerChalk[]) {\n return (input: any): string =>\n styles.reduce((acc, style) => {\n if ((style as any) in chalk) {\n const fn = typeof style === 'function'\n ? style\n : chalk[style as never]\n\n return fn(acc)\n }\n\n return acc\n }, input)\n }\n\n /**\n * Parse an array formated message and logs it\n * \n * @param config \n * @param joiner \n * @param log If set to false, string output will be returned and not logged \n * @param sc color to use ue on split text if : is found \n */\n static parse (config: LoggerParseSignature, joiner?: string, log?: true, sc?: LoggerChalk): void\n static parse (config: LoggerParseSignature, joiner?: string, log?: false, sc?: LoggerChalk): string\n static parse (config: LoggerParseSignature, joiner = ' ', log = true, sc?: LoggerChalk): string | void {\n const string = config.map(([str, opt]) => {\n if (Array.isArray(opt)) {\n opt = Logger.chalker(opt) as ChalkInstance\n }\n\n const output = typeof opt === 'string' && typeof chalk[opt] === 'function'\n ? (chalk as any)[opt](str)\n : typeof opt === 'function' ? opt(str) : str\n\n if (!sc) {\n return output\n }\n\n return this.textFormat(output, Logger.chalker(Array.isArray(sc) ? sc : [sc]))\n }).join(joiner)\n\n if (log && !this.shouldSuppressOutput('line')) console.log(string)\n else return string\n }\n\n /**\n * Ouput formater object or format the output\n * \n * @returns \n */\n static log: LoggerLog = ((config, joiner, log: boolean = true, sc) => {\n if (typeof config === 'string') {\n const conf = [[config, joiner]] as [string, keyof ChalkInstance][]\n\n return this.parse(conf, '', log as false, sc)\n } else if (Array.isArray(config)) {\n return this.parse(config, String(joiner), log as false, sc)\n } else if (log && !this.shouldSuppressOutput('line')) {\n return console.log(this.textFormat(config, Logger.chalker(['blue'])))\n }\n\n return this\n }) as LoggerLog\n\n /**\n * A simple console like output logger\n * \n * @returns \n */\n static console () {\n return Console\n }\n}"],"mappings":";;;;;;;;;;;AAAA,MAAa,wBAAwB,aAAyC;AAC5E;EAAC;EAAU;EAAW;EAAU,CAAC,SAAS,WAAW;AACnD,UAAQ,GAAG,QAAQ,YAAY;AAC7B,SAAM,UAAU;IAChB;GACF;;;;;;;;;;;;ACaJ,MAAa,OACT,KACA,iBACC;CACD,IAAI,MAAoD,QAAQ,IAAI,QAAQ;AAE5E,KAAI;EAAC;EAAM;EAAQ;EAAM;EAAO;EAAS;EAAM,CAAC,SAAS,IAAI,CACzD,OAAM;EAAC;EAAM;EAAQ;EAAK,CAAC,SAAS,IAAI;AAG5C,KAAI,CAAC,MAAM,OAAO,IAAI,CAAC,IAAI,OAAO,QAAQ,aAAa,OAAO,QAAQ,eAAe,QAAQ,GACzF,OAAM,OAAO,IAAI;AAGrB,KAAI,QAAQ,GACR,OAAM;AAGV,KAAI,QAAQ,OACR,OAAM;AAGV,SAAQ;AAER,QAAO;;;;;;;;AASX,MAAa,UAAU,SAA0B;CAC7C,MAAM,OAAO,IAAI,OAAO,IAAI;CAC5B,MAAM,aAAa,oBAAoB;CACvC,MAAM,SAAS,IAAI,UAAU,IAAI;AAEjC,KAAI;EACA,MAAM,MAAM,IAAI,IAAI,OAAO;AAE3B,MAAI,IAAI,QAAQ,IAAI,aAAa,YAC7B,KAAI,OAAO;EAGf,MAAM,UAAU,IAAI,UAAU,CAAC,QAAQ,OAAO,GAAG;AAEjD,MAAI,KAIA,QAAO,GAAG,UAFa,IAAI,KAAK,QAAQ,QAAQ,GAAG;AAKvD,SAAO;SACH;AAEJ,SAAO,OAAO,GAAG,WAAW,GAAG,KAAK,QAAQ,QAAQ,GAAG,KAAK;;;;;;;;;;AAWpE,MAAa,UACT,KACA,iBACC;CACD,MAAM,OAAO,KAAK,SAAS,QAAQ,KAAK,EAAE,WAAW,CAAC;CACtD,MAAM,UAAU,cAAc,OAAO,KAAK,IAAI;CAS9C,MAAM,SAPQ,YAAY,KAAK,KAAK,QAAQ,KAAK,EAAE,GAAG,KAAK,SAAS,EAAE,EAAE,eAAe,MAAM,CAAC,CACzF,QAAO,SAAQ;AACZ,MAAI,KAAK,KAAK,SAAS,aAAa,IAAI,WAAW,OAAO,YAAY,MAAO,QAAO;AAEpF,SAAO,KAAK,QAAQ,KAAK,KAAK,KAAK,SAAS,MAAM,IAAI,KAAK,KAAK,SAAS,MAAM;GACjF,CAEe,QAAQ,SAAS,SAAS;EAC3C,MAAM,aAAa,KAAK,SAAS,KAAK,MAAM,KAAK,QAAQ,KAAK,KAAK,CAAC;AAEpE,UAAQ,cAAc,QAAQ,KAAK,KAAK,KAAK,YAAY,KAAK,KAAK,CAAC,CAC/D,QAAS,WAAmB,KAAK,CAAC;AAEvC,SAAO;IACR,EAAE,CAAwB;AAG7B,KAAI,IACA,QAAO,IAAI,IAAI,QAAQ,KAAK,aAAa;AAG7C,QAAO;;;;;;;AAQX,MAAa,gBAAgB;CACzB,IAAI,WAAW,IAAkC,YAAY,cAAc;AAE3E,KAAI,aAAa,iBAAiB,aAAa,aAC3C,YAAW;AAGf,QAAO,aAAa,eAAe,SAAS;;;;;;;;AAShD,MAAa,aAAa,MAAM,QAAQ,KAAK,KAAK;CAC9C,MAAM,WAAW,SAAS;CAE1B,MAAM,SAAS;EACX,KAAK,IAAI,kBAAkB,kBAAkB;EAC7C,MAAM,IAAI,cAAc,OAAO;EAClC;AAED,QAAO,KAAK,WAAW,OAAO,aAAa,OAAO,IAAI,GAC/C,OAAO,aAAa,OAAO,MAC5B,KAAK,KAAK,KAAK,OAAO,aAAa,OAAO,IAAI;;AAIxD,MAAa,aAAa,OAAqB,aAAiC;CAC5E,MAAM,eAAe,QAAQ,SAAS;AAMtC,QAAO,MALM,WAAW,cAAc,aAAa,CAAC,MAAM;EACtD,gBAAgB;EAChB,eAAe;EAClB,CAAC,CAEgB,OAAU,aAAa;;;;;AC3J7C,MAAa,uBAAuB,OAClC,MACA,gBAAwB,KACxB,QACG;AACH,KAAI,OAAO,CAAC,WAAW,IACrB,YAAW,YAAY;AACzB,YAAW,MAAM;AACjB,YAAW,SAAS;AACpB,YAAW,SAAS,EAClB,SAAS,QACV;AAED,OAAM,KADO,MAAM,OAAO,cAAc,CACxB;;AAIlB,MAAa,0BAA0B,EACrC,UAAU,iCACV,OACA,OACA,OAAO,UAMH;AAYJ,SAXyC;EACvC,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACL,KAAK;EACN,CAEgB,SAAS,SAAS;AAEnC,QAAO;;;iBAGQ,KAAK,KAAK,MAAM;;;;;;;;;;;;;;;;;;;;;;;;;;cA0BnB,KAAK;cACL,MAAM;aACP,QAAQ;UACX,QAAQ,6BAA6B,MAAM,UAAU,GAAG;;;;;;;;AC7ElE,MAAa,uBAAuB;AAChC,QAAO,UAAU,YAAY,WAAY;AACrC,SAAO,KAAK,aAAa,CACpB,QAAQ,MAAM,IAAI,CAClB,QAAQ,MAAM,IAAI,CAClB,QAAQ,eAAe,SAAU,OAAO;AACrC,UAAO,MAAM,aAAa;IAC5B;;AAGV,QAAO,UAAU,YAAY,WAAY;AACrC,SAAO,KAAK,QAAQ,2BAA2B,SAAU,OAAO,OAAO;AACnE,OAAI,CAAC,UAAU,EAAG,QAAO;AAEzB,UAAO,UAAU,IAAI,MAAM,aAAa,GAAG,MAAM,aAAa;IAChE;;AAGN,QAAO,UAAU,aAAa,WAAY;AACtC,SAAO,KAAK,QAAQ,2BAA2B,SAAU,OAAO;AAC5D,UAAO,MAAM,aAAa;IAC5B;;AAGN,QAAO,UAAU,WAAW,SAAU,MAAc,IAAI,SAAiB,OAAO;AAC5E,MAAI,KAAK,UAAU,IACf,QAAO,KAAK,UAAU;EAG1B,MAAM,YAAY,KAAK,UAAU,GAAG,IAAI;EACxC,MAAM,iBAAiB,UAAU,YAAY,IAAI;AACjD,MAAI,iBAAiB,EACjB,QAAO,UAAU,UAAU,GAAG,eAAe,GAAG;AAGpD,SAAO,YAAY;;;;;;AC/B3B,MAAM,8BAAc,IAAI,KAAyB;AAEjD,MAAM,YAAY,UACd,OAAO,UAAU,YAAY,UAAU;AAG3C,MAAa,gBAAgB,UACzB,SAAS,MAAM,GAAG,QAAyC;AAG/D,MAAa,uBAAuB,OAAgB,WAAmB,QAAQ;CAC3E,MAAM,OAAO,OAAO,UAAU,WAAW,QAAQ,OAAO,MAAM;AAE9D,QAAO,OAAO,UAAU,KAAK,IAAI,QAAQ,OAAO,OAAO,MAAM,OAAO;;AAGxE,MAAa,uBAAuB;CAChC,MAAM,cAAc,KAAK,QAAQ,QAAQ,KAAK,EAAE,yBAAyB;AAEzE,KAAI,CAAC,YAAY,IAAI,YAAY,CAC7B,aAAY,IAAI,aAAa,KAAK,EAC9B,OAAO,SACV,EAAE,KAAK,YAAY;EAChB,MAAM;EACN,OAAO;EACP,MAAM;EACT,CAAC,CAAC,CAAC;AAGR,QAAO,YAAY,IAAI,YAAY;;AAGvC,MAAa,kBAAkB,OAAgB,uBAAwB,IAAI,SAAS,KAAc;AAC9F,KAAI,MAAM,QAAQ,MAAM,CACpB,QAAO,MAAM,KAAK,UAAU,eAAe,OAAO,KAAK,CAAC;AAG5D,KAAI,CAAC,SAAS,MAAM,CAChB,QAAO;AAGX,KAAI,KAAK,IAAI,MAAM,CACf,QAAO;AAGX,MAAK,IAAI,MAAM;CAEf,MAAM,aAAsC,EAAE;AAE9C,KAAI,iBAAiB,OAAO;AACxB,aAAW,OAAO,MAAM;AACxB,aAAW,UAAU,MAAM;AAC3B,aAAW,QAAQ,MAAM;;AAG7B,MAAK,MAAM,OAAO,QAAQ,QAAQ,MAAM,EAAE;EACtC,MAAM,WAAW,OAAO,QAAQ,WAAW,MAAM,IAAI,UAAU;EAC/D,MAAM,aAAa,OAAO,yBAAyB,OAAO,IAAI;AAE9D,MAAI,CAAC,cAAc,EAAE,WAAW,YAC5B;AAGJ,aAAW,YAAY,eAAe,WAAW,OAAO,KAAK;;AAGjE,QAAO;;AAGX,MAAa,mBAAmB,UAAuC;AACnE,KAAI,OAAO,UAAU,SACjB,QAAO;AAGX,QAAO,aAAa,MAAM,MAAM,IAAI;;AAGxC,MAAa,uBAAuB,UAA8B;AAC9D,KAAI,OAAO,MAAM,WAAW,WACxB,QAAO,MAAM,QAAQ;AAGzB,QAAO,MAAM;;AAGjB,MAAa,qBAAqB,UAAgD;AAG9E,QAAO,OAFW,aAAa,MAAM,EAEZ,WAAW;;AAGxC,MAAa,wBAAwB,UAAgD;AAGjF,QAAO,OAFW,aAAa,MAAM,EAEZ,iBAAiB;;AAG9C,MAAa,wBAAwB;CACjC,MAAM,QAAQ,QAAQ,IAAI;AAE1B,QAAO,UAAU,UAAU,UAAU,OAAO,UAAU;;AAG1D,MAAa,kBAAkB,UAC3B,CAAC,kBAAkB,MAAM,IACzB,CAAC,qBAAqB,MAAM;AAEhC,MAAa,sBACT,KACA,kBAA0B,2BACH;CACvB,MAAM,eAAe,gBAAgB,IAAI;CACzC,MAAM,gBAAgB,OAAO,iBAAiB,WACxC,SACA;CACN,MAAM,kBAAkB,iBAAiB,kBAAkB,cAAc,GACnE,gBACA;CACN,MAAM,qBAAqB,iBAAiB,qBAAqB,cAAc,GACzE,gBACA;CACN,MAAM,UAAgC;EAClC,QAAQ;EACR,MAAM,OAAO,QAAQ,WACf,MACA,oBAAoB,eAAe,cAAc,eAAe,OAAO;EAC7E,SAAS,OAAO,QAAQ,WAClB,GAAG,gBAAgB,IAAI,QACvB,eAAe,WAAW,IAAI,WAAW;EAClD;AAED,KAAI,iBAAiB;AACjB,UAAQ,OAAO,oBAAoB,gBAAgB,cAAc,gBAAgB,QAAQ,IAAI;AAC7F,UAAQ,UAAU,gBAAgB,WAAW;AAC7C,UAAQ,SAAS,oBAAoB,gBAAgB;YAC9C,oBAAoB;AAC3B,UAAQ,OAAO;AACf,UAAQ,UAAU,GAAG,mBAAmB,gBAAgB,CAAC;YAClD,eAAe,OAAO;EAC7B,MAAM,CAAC,WAAW,GAAG,QAAQ,cAAc,MAAM,MAAM,KAAK;EAC5D,MAAM,CAAC,KAAK,UAAU,MAAM,UAAU,MAAM,IAAI;AAEhD,UAAQ,SAAS,GACZ,MAAM,CAAC,QAAQ,MAAM,EAAE,GAAG,KAAK,KAAK,UAAkB,MAAM,MAAM,CAAC,CAAC,EACxE;;AAGL,KACI,iBACA,QAAQ,IAAI,aAAa,iBACzB,CAAC,iBAAiB,IAClB,CAAC,gBAED,SAAQ,QAAQ,cAAc;AAGlC,KAAI,CAAC,mBAAmB,QAAQ,SAAS,KAAK;AAC1C,SAAO,QAAQ;AACf,SAAO,QAAQ;;AAGnB,QAAO;;AAGX,MAAa,qBACT,KACA,SACA,YACC;AACD,iBAAgB,CAAC,MAAM;EACnB,OAAO,eAAe,IAAI;EAC1B;EACH,EAAE,QAAQ;;;;;AC7Kf,IAAM,UAAN,MAAc;CACV,OAAO,OAAO,GAAG,SAAgB,OAAO,IAAI,KAAK,KAAI,MAAK,CAAC,GAAG,QAAQ,CAAC,CAAC;CACxE,OAAO,SAAS,GAAG,SAAgB,OAAO,MAAM,MAAM,OAAO,KAAK;CAClE,OAAO,QAAQ,GAAG,SAAgB,KAAK,KAAI,MAAK,OAAO,KAAK,GAAG,OAAO,KAAK,CAAC;CAC5E,OAAO,QAAQ,GAAG,SAAgB,KAAK,KAAI,MAAK,OAAO,KAAK,GAAG,OAAO,KAAK,CAAC;CAC5E,OAAO,SAAS,GAAG,SAAgB,KAAK,KAAI,MAAK,OAAO,MAAM,GAAG,MAAM,EAAE,KAAK;;AAGlF,IAAa,SAAb,MAAa,OAAO;;;;CAIhB,OAAe,YAAoB;CACnC,OAAe,UAAmB;CAClC,OAAe,WAAoB;;;;CAKnC,OAAO,UAAW,UAAqE,EAAE,EAAE;AACvF,OAAK,YAAY,QAAQ,aAAa;AACtC,OAAK,UAAU,QAAQ,SAAS;AAChC,OAAK,WAAW,QAAQ,UAAU;;;;;CAMtC,OAAe,qBAAsB,OAA0E;AAC3G,MAAI,KAAK,SAAU,QAAO;AAC1B,MAAI,KAAK,YAAY,UAAU,UAAU,UAAU,WAAY,QAAO;AACtE,MAAI,UAAU,WAAW,KAAK,YAAY,EAAG,QAAO;AAEpD,SAAO;;CAYX,OAAO,gBAAiB,MAAc,OAAe,MAAM,MAAM,SAAS,KAAsC;EAE5G,MAAM,QAAQ;EACd,MAAM,QAAQ,KAAK,IAAI,QAAQ,OAAO,SAAS,IAAI;EACnD,MAAM,OAAO,KAAK,IAAI,QAAQ,KAAK,QAAQ,OAAO,GAAG,CAAC,SAAS,MAAM,QAAQ,OAAO,GAAG,CAAC,SAAS,IAAI,EAAE;AAEvG,MAAI,IAAK,QAAO,QAAQ,IAAI,MAAM,MAAM,KAAK,OAAO,OAAO,KAAK,CAAC,EAAE,MAAM;MACpE,QAAO;GAAC;GAAM,MAAM,KAAK,OAAO,OAAO,KAAK,CAAC;GAAE;GAAM;;CAc9D,OAAO,SAAU,MAAc,MAAc,QAAQ,IAAI,MAAM,MAAuC;AAClG,UAAQ,KAAK,IAAI,OAAO,GAAG;EAG3B,MAAM,OAAO,KAAK,IAAI,QAAQ,KAAK,QADrB,eACoC,GAAG,CAAC,QAAQ,EAAE;AAEhE,MAAI,IAAK,QAAO,QAAQ,IAAI,MAAM,IAAI,OAAO,KAAK,EAAE,KAAK;MACpD,QAAO;GAAC;GAAM,IAAI,OAAO,KAAK;GAAE;GAAK;;;;;;;;;;;CAY9C,OAAO,MAAO,MAAc,OAAe,QAAuC,OAAO,OAAO,cAAc,OAAO,SAAS,KAAK;AAC/H,aAAW;EACX,MAAM,QAAQ;GAAE,SAAS,MAAM;GAAS,MAAM,MAAM;GAAQ,OAAO,MAAM;GAAO;EAEhF,MAAM,CAAC,OAAO,MAAM,OAAO,KAAK,gBAAgB,MAAM,OAAO,OAAO,OAAO;AAE3E,UAAQ,IAAI,KAAK,WAAW,OAAO,MAAM,SAAS,YAAY,EAAE,MAAM,IAAI;AAE1E,MAAI,KAAM,SAAQ,KAAK,EAAE;;;;;;;;;;CAW7B,OAAO,WACH,KACA,OACA,cAAc,OACR;AACN,MAAI,eAAe,OAAO;GACtB,MAAM,MAAsD;GAC5D,MAAM,OAAO,IAAI,QAAQ,IAAI,aAAa,KAAK,IAAI,QAAQ,IAAI,WAAW,KAAK;GAC/E,MAAM,SAAmB,EAAE;AAE3B,OAAI,IAAI,QACJ,QAAO,KAAK,KAAK,WAAW,GAAG,IAAI,YAAY,OAAO,KAAK,IAAI,IAAI,WAAW,MAAM,OAAO,YAAY,CAAC;AAG5G,OAAI,IAAI,MACJ,QAAO,KAAK,SAAS,MAAM,MAAM,IAAI,MAAM,QAAQ,GAAG,IAAI,KAAK,IAAI,IAAI,WAAW,GAAG,CAAC,MAAM,CAAC,CAAC;AAGlG,UAAO,OAAO,KAAK,KAAK;;AAG5B,MAAI,MAAM,QAAQ,IAAI,CAClB,QAAO,IAAI,KAAI,MAAK,KAAK,WAAW,GAAG,OAAO,YAAY,CAAC,CAAC,KAAK,KAAK;AAG1E,MAAI,OAAO,QAAQ,SACf,QAAO,KAAK,WAAW,OAAO,OAAO,IAAK,EAAE,OAAO,YAAY;AAGnE,MAAI,OAAO,QAAQ,SACf,QAAO,MAAM,IAAI;EAGrB,MAAM,MAAM,OAAO,IAAI;AAEvB,MAAI,YAAa,QAAO;EAExB,MAAM,CAAC,OAAO,GAAG,QAAQ,IAAI,MAAM,IAAI;AACvC,MAAI,KAAK,WAAW,EAAG,QAAO;AAE9B,SAAO,MAAM,IAAI,MAAM,GAAG,GAAG,KAAK,KAAK,IAAI;;;;;;;;;CAU/C,OAAO,QAAS,KAAU,OAAO,OAAO,cAAc,OAAO;AACzD,MAAI,CAAC,KAAK,qBAAqB,UAAU,CACrC,SAAQ,IAAI,MAAM,MAAM,IAAI,EAAE,KAAK,WAAW,KAAK,MAAM,SAAS,YAAY,CAAC;AAEnF,MAAI,KAAM,SAAQ,KAAK,EAAE;;;;;;;;;CAU7B,OAAO,KAAM,KAAU,OAAO,OAAO,cAAc,OAAO;AACtD,MAAI,CAAC,KAAK,qBAAqB,OAAO,CAClC,SAAQ,IAAI,MAAM,KAAK,IAAI,EAAE,KAAK,WAAW,KAAK,MAAM,QAAQ,YAAY,CAAC;AAEjF,MAAI,KAAM,SAAQ,KAAK,EAAE;;;;;;;;;CAU7B,OAAO,MAAO,KAAU,OAAO,MAAM,cAAc,OAAO;AACtD,MAAI,CAAC,KAAK,qBAAqB,QAAQ,CACnC,KAAI,eAAe,OAAO;AACtB,OAAI,IAAI,QACJ,SAAQ,MAAM,MAAM,IAAI,IAAI,EAAE,KAAK,WAAW,WAAW,IAAI,SAAS,MAAM,OAAO,YAAY,CAAC;AAEpG,WAAQ,MAAM,MAAM,IAAI,GAAI,IAAY,SAAS,GAAI,IAAY,OAAO,MAAM,KAAK,IAAI,QAAQ,CAAC;QAEhG,SAAQ,MAAM,MAAM,IAAI,IAAI,EAAE,KAAK,WAAW,KAAK,MAAM,OAAO,YAAY,CAAC;AAGrF,MAAI,KAAM,SAAQ,KAAK,EAAE;;;;;;;;;CAU7B,OAAO,KAAM,KAAU,OAAO,OAAO,cAAc,OAAO;AACtD,MAAI,CAAC,KAAK,qBAAqB,OAAO,CAClC,SAAQ,KAAK,MAAM,OAAO,IAAI,EAAE,KAAK,WAAW,KAAK,MAAM,UAAU,YAAY,CAAC;AAEtF,MAAI,KAAM,SAAQ,KAAK,EAAE;;;;;;;;;CAU7B,OAAO,MAAgB,KAAc,OAAO,OAAO,cAAc,OAAO;AACpE,MAAI,CAAC,KAAK,qBAAqB,QAAQ,CACnC,KAAI,MAAM,QAAQ,IAAI,CAClB,MAAK,IAAI,IAAI,GAAG,IAAI,IAAI,QAAQ,IAC5B,SAAQ,IAAI,MAAM,KAAK,KAAK,EAAE,MAAM,OAAO,IAAI,EAAE,EAAE,KAAK,WAAW,IAAI,IAAI,MAAM,QAAQ,YAAY,CAAC;MAG1G,SAAQ,IAAI,MAAM,KAAK,KAAK,EAAE,KAAK,WAAW,KAAK,MAAM,QAAQ,YAAY,CAAC;AAGtF,MAAI,KAAM,SAAQ,KAAK,EAAE;;;;;CAM7B,OAAO,QAAS;AACZ,UAAQ,KAAK,EAAE;;CAGnB,OAAO,QAAS,QAAuB;AACnC,UAAQ,UACJ,OAAO,QAAQ,KAAK,UAAU;AAC1B,OAAK,SAAiB,MAKlB,SAJW,OAAO,UAAU,aACtB,QACA,MAAM,QAEF,IAAI;AAGlB,UAAO;KACR,MAAM;;CAajB,OAAO,MAAO,QAA8B,SAAS,KAAK,MAAM,MAAM,IAAiC;EACnG,MAAM,SAAS,OAAO,KAAK,CAAC,KAAK,SAAS;AACtC,OAAI,MAAM,QAAQ,IAAI,CAClB,OAAM,OAAO,QAAQ,IAAI;GAG7B,MAAM,SAAS,OAAO,QAAQ,YAAY,OAAO,MAAM,SAAS,aACzD,MAAc,KAAK,IAAI,GACxB,OAAO,QAAQ,aAAa,IAAI,IAAI,GAAG;AAE7C,OAAI,CAAC,GACD,QAAO;AAGX,UAAO,KAAK,WAAW,QAAQ,OAAO,QAAQ,MAAM,QAAQ,GAAG,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;IAC/E,CAAC,KAAK,OAAO;AAEf,MAAI,OAAO,CAAC,KAAK,qBAAqB,OAAO,CAAE,SAAQ,IAAI,OAAO;MAC7D,QAAO;;;;;;;CAQhB,OAAO,QAAmB,QAAQ,QAAQ,MAAe,MAAM,OAAO;AAClE,MAAI,OAAO,WAAW,UAAU;GAC5B,MAAM,OAAO,CAAC,CAAC,QAAQ,OAAO,CAAC;AAE/B,UAAO,KAAK,MAAM,MAAM,IAAI,KAAc,GAAG;aACtC,MAAM,QAAQ,OAAO,CAC5B,QAAO,KAAK,MAAM,QAAQ,OAAO,OAAO,EAAE,KAAc,GAAG;WACpD,OAAO,CAAC,KAAK,qBAAqB,OAAO,CAChD,QAAO,QAAQ,IAAI,KAAK,WAAW,QAAQ,OAAO,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;AAGzE,SAAO;;;;;;;CAQX,OAAO,UAAW;AACd,SAAO"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../src/lifecycle.ts","../src/system.ts","../src/network.ts","../src/prototypes.ts","../src/Exceptions/Exception.ts","../src/Exceptions/AppException.ts","../src/Exceptions/RequestException.ts","../src/ErrorHandler.ts","../src/Logger.ts","../src/utils/encryption.ts","../src/utils/hash.ts","../src/utils/helpers.ts"],"sourcesContent":["export const bindGracefulShutdown = (shutdown: () => Promise<void> | void) => {\n ['SIGINT', 'SIGTERM', 'SIGQUIT'].forEach((signal) => {\n process.on(signal, async () => {\n await shutdown()\n })\n })\n}\n","import { DotPath, Obj } from '@h3ravel/support'\nimport { GlobalConfig, GlobalEnv } from './types'\n\n// TODO: @rexxars/jiti has to be replaced with jiti once a new release is available. See https://github.com/unjs/jiti/pull/427\nimport { createJiti } from '@rexxars/jiti'\nimport { createRequire } from 'module'\nimport path from 'node:path'\nimport { pathToFileURL } from 'node:url'\nimport { readdirSync } from 'fs'\nimport { resolve } from 'node:path'\n\n/**\n * Read the .env file\n *\n * @param env\n * @param def\n * @returns\n */\nexport const env: GlobalEnv = <X = string, Y = undefined | X> (\n env: string,\n defaultValue?: Y,\n) => {\n let val: string | number | boolean | undefined | null = process.env[env] ?? ''\n\n if ([true, 'true', 'on', false, 'false', 'off'].includes(val)) {\n val = [true, 'true', 'on'].includes(val)\n }\n\n if (!isNaN(Number(val)) && typeof val !== 'boolean' && typeof val !== 'undefined' && val !== '') {\n val = Number(val)\n }\n\n if (val === '') {\n val = undefined\n }\n\n if (val === 'null') {\n val = null\n }\n\n val ??= defaultValue as typeof val\n\n return val as Y extends undefined ? X : Y\n}\n\n/**\n * Build the app url\n *\n * @param link\n * @returns\n */\nexport const appUrl = (link?: string): string => {\n const port = env('PORT') || '3000'\n const defaultUrl = `http://localhost:${port}`\n const appUrl = env('APP_URL') ?? defaultUrl\n\n try {\n const url = new URL(appUrl)\n // Append port only if APP_URL has a port or is localhost\n if (url.port || url.hostname === 'localhost') {\n url.port = port\n }\n // Remove trailing slash from base URL\n const baseUrl = url.toString().replace(/\\/$/, '')\n // Append link with proper path separator\n if (link) {\n // Ensure link starts with '/' and remove duplicate slashes\n const normalizedLink = `/${link.replace(/^\\/+/, '')}`\n\n return `${baseUrl}${normalizedLink}`\n }\n\n return baseUrl\n } catch {\n // Return default URL with link if provided\n return link ? `${defaultUrl}/${link.replace(/^\\/+/, '')}` : defaultUrl\n }\n}\n\n/**\n * Gets the application configuration.\n * \n * @param key The configuration key to retrieve.\n * @param defaultValue The default value to return if the key is not found.\n * @returns The configuration value.\n */\nexport const config: GlobalConfig = <X extends Record<string, any>, P extends DotPath<X> | undefined = undefined> (\n key?: P,\n defaultValue?: any\n) => {\n const dist = path.relative(process.cwd(), outputDir())\n const require = createRequire(import.meta.url)\n\n const files = readdirSync(path.join(process.cwd(), `${dist}/config`), { withFileTypes: true })\n .filter(file => {\n if (file.name.includes('middleware') && globalThis.arkctx.runtime === 'CLI') return false\n\n return file.isFile() && (file.name.endsWith('.js') || file.name.endsWith('.ts'))\n })\n\n const config = files.reduce((configs, file) => {\n const configName = path.basename(file.name, path.extname(file.name))\n\n configs[configName] = require(path.join(file.parentPath, file.name))\n .default((globalThis as any).app())\n\n return configs\n }, {} as Record<string, any>) as X\n\n\n if (key) {\n return Obj.get(config, key, defaultValue)\n }\n\n return config\n}\n\n/**\n * Gets the current Node environment (development or production).\n * \n * @returns \n */\nexport const nodeEnv = () => {\n let envValue = env<'development' | 'production'>('NODE_ENV', 'development')\n\n if (envValue !== 'development' && envValue !== 'production') {\n envValue = 'development'\n }\n\n return envValue === 'production' ? 'prod' : 'dev'\n}\n\n/**\n * Gets the output directory for the application based on the current environment.\n * \n * @param cwd The current working directory (optional, defaults to process.cwd()).\n * @returns \n */\nexport const outputDir = (cwd = process.cwd()) => {\n const NODE_ENV = nodeEnv()\n\n const output = {\n dev: env('OUTPUT_DIR_DEV', '.arkstack/build'),\n prod: env('OUTPUT_DIR', 'dist'),\n }\n\n return path.isAbsolute(output[NODE_ENV] ?? output.dev)\n ? (output[NODE_ENV] ?? output.dev)\n : path.join(cwd, output[NODE_ENV] ?? output.dev)\n}\n\n\nexport const importFile = async <T = unknown> (filePath: string): Promise<T> => {\n const resolvedPath = resolve(filePath)\n const jiti = createJiti(pathToFileURL(resolvedPath).href, {\n interopDefault: false,\n tsconfigPaths: true,\n })\n\n return await jiti.import<T>(resolvedPath)\n}","import { config, env } from './system'\n\nimport { detect } from 'detect-port'\n\nexport const bootWithDetectedPort = async (\n boot: (port: number) => Promise<void>,\n preferredPort: number = 3000,\n app?: any\n) => {\n if (app && !globalThis.app)\n globalThis.app = () => app\n globalThis.env = env\n globalThis.config = config\n globalThis.arkctx = {\n runtime: 'HTTP',\n }\n const port = await detect(preferredPort)\n await boot(port)\n}\n\n\nexport const buildHtmlErrorResponse = ({\n message = 'An unexpected error occurred.',\n stack,\n title,\n code = 500,\n}: {\n message?: string;\n stack?: string;\n code?: number;\n title?: string;\n}) => {\n const titleMap: Record<number, string> = {\n 400: 'Bad Request',\n 401: 'Unauthorized',\n 403: 'Forbidden',\n 404: 'Not Found',\n 500: 'Internal Server Error',\n 502: 'Bad Gateway',\n 503: 'Service Unavailable',\n 504: 'Gateway Timeout',\n }\n\n title = titleMap[code] || title || 'Error'\n\n return `\n <html>\n <head>\n <title>${code} | ${title}</title>\n <style>\n body {\n font-family: Arial, sans-serif;\n background-color: #f8f8f8;\n color: #333;\n padding: 20px;\n }\n h1 {\n color: #e74c3c;\n }\n h3 {\n color: #3498db;\n }\n p {\n color: #555;\n }\n pre {\n background-color: #eee;\n padding: 10px;\n border-radius: 5px;\n overflow-x: auto;\n }\n </style>\n </head>\n <body>\n <h1>${code}</h1>\n <h3>${title}</h3>\n <p>${message}</p>\n ${stack ? `<h2>Stack Trace:</h2><pre>${stack}</pre>` : ''}\n </body>\n </html>\n `\n}","export const loadPrototypes = () => {\n String.prototype.titleCase = function () {\n return this.toLowerCase()\n .replace(/_/g, ' ')\n .replace(/-/g, ' ')\n .replace(/(?:^|\\s)\\w/g, function (match) {\n return match.toUpperCase()\n })\n }\n\n String.prototype.camelCase = function () {\n return this.replace(/(?:^\\w|[A-Z]|\\b\\w|\\s+)/g, function (match, index) {\n if (+match === 0) return '' // or if (/\\s+/.test(match)) for white spaces\n\n return index === 0 ? match.toLowerCase() : match.toUpperCase()\n })\n }\n\n String.prototype.pascalCase = function () {\n return this.replace(/(?:^\\w|[A-Z]|\\b\\w|\\s+)/g, function (match) {\n return match.toUpperCase()\n })\n }\n\n String.prototype.truncate = function (len: number = 20, suffix: string = '...') {\n if (this.length <= len) {\n return this.toString()\n }\n\n const truncated = this.substring(0, len)\n const lastSpaceIndex = truncated.lastIndexOf(' ')\n if (lastSpaceIndex > 0) {\n return truncated.substring(0, lastSpaceIndex) + suffix\n }\n\n return truncated + suffix\n }\n} \n","export class Exception extends Error {\n name: string\n\n constructor(message?: string, options?: ErrorOptions) {\n super(message, options)\n this.name = 'Exception'\n }\n}","import { Exception } from './Exception'\n\nexport class AppException extends Exception {\n errors?: { [key: string]: string[] | string } | undefined = undefined\n\n statusCode: number\n\n constructor(message?: string, statusCode: number = 400, options?: ErrorOptions) {\n super(message, options)\n this.statusCode = statusCode\n }\n}","import { AppException } from './AppException'\n\nexport class RequestException extends AppException {\n statusCode: number\n\n constructor(message?: string, statusCode: number = 400, options?: ErrorOptions) {\n super(message, statusCode, options)\n this.statusCode = statusCode\n }\n\n /**\n * Asserts that a value is not null or undefined. \n * \n * @param value \n * @param message \n * @param code \n * @throws {RequestException} Throws if the value is null or undefined.\n */\n static assertNotEmpty<T> (\n value: T | null | undefined,\n message: string,\n code: number = 404,\n ): asserts value is T {\n if (!value) {\n throw new RequestException(message, code)\n }\n }\n\n /**\n * Asserts that a boolean condition is true. \n * \n * @param boolean \n * @param message \n * @param code \n * @throws {RequestException} Throws if the boolean condition is true.\n */\n static abortIf<T> (\n boolean: T,\n message: string,\n code?: number,\n ): asserts boolean is T {\n if (boolean) {\n throw new RequestException(message, code)\n }\n }\n}","import pino, { type Logger as PinoLogger } from 'pino'\nimport path from 'node:path'\nimport { ArkstackErrorPayload, ArkstackErrorShape } from './types'\n\nexport class ErrorHandler {\n private static loggerCache = new Map<string, PinoLogger>()\n\n private static isRecord (value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null\n }\n\n static toErrorShape (value: unknown): ArkstackErrorShape | undefined {\n return ErrorHandler.isRecord(value) ? value as unknown as ArkstackErrorShape : undefined\n }\n\n static normalizeStatusCode (value: unknown, fallback: number = 500) {\n const code = typeof value === 'number' ? value : Number(value)\n\n return Number.isInteger(code) && code >= 100 && code < 600 ? code : fallback\n }\n\n static getErrorLogger () {\n const destination = path.resolve(process.cwd(), 'storage/logs/error.log')\n\n if (!ErrorHandler.loggerCache.has(destination)) {\n ErrorHandler.loggerCache.set(destination, pino({\n level: 'error',\n }, pino.destination({\n dest: destination,\n mkdir: true,\n sync: false,\n })))\n }\n\n return ErrorHandler.loggerCache.get(destination)!\n }\n\n static serializeError (\n value: unknown,\n seen: WeakSet<object> = new WeakSet()\n ): unknown {\n if (Array.isArray(value)) {\n return value.map((entry) => ErrorHandler.serializeError(entry, seen))\n }\n\n if (!ErrorHandler.isRecord(value)) {\n return value\n }\n\n if (seen.has(value)) {\n return '[Circular]'\n }\n\n seen.add(value)\n\n const serialized: Record<string, unknown> = {}\n\n if (value instanceof Error) {\n serialized.name = value.name\n serialized.message = value.message\n serialized.stack = value.stack\n }\n\n for (const key of Reflect.ownKeys(value)) {\n const property = typeof key === 'string' ? key : key.toString()\n const descriptor = Object.getOwnPropertyDescriptor(value, key)\n\n if (!descriptor || !('value' in descriptor)) {\n continue\n }\n\n serialized[property] = ErrorHandler.serializeError(descriptor.value, seen)\n }\n\n return serialized\n }\n\n static getPrimaryError (error: ArkstackErrorShape | string) {\n if (typeof error === 'string') {\n return error\n }\n\n return ErrorHandler.toErrorShape(error.cause) ?? error\n }\n\n static getValidationErrors (error: ArkstackErrorShape) {\n if (typeof error.errors === 'function') {\n return error.errors()\n }\n\n return error.errors\n }\n\n static isValidationError (error: unknown): error is ArkstackErrorShape {\n const candidate = ErrorHandler.toErrorShape(error)\n\n return typeof candidate?.errors !== 'undefined'\n }\n\n static isModelNotFoundError (error: unknown): error is ArkstackErrorShape {\n const candidate = ErrorHandler.toErrorShape(error)\n\n return typeof candidate?.getModelName === 'function'\n }\n\n static shouldHideStack () {\n const value = process.env.HIDE_ERROR_STACK\n\n return value === 'true' || value === '1' || value === 'on'\n }\n\n static shouldLogError (error: unknown) {\n return !ErrorHandler.isValidationError(error) &&\n !ErrorHandler.isModelNotFoundError(error)\n }\n\n static createErrorPayload (\n err: ArkstackErrorShape | string,\n fallbackMessage: string = 'Something went wrong',\n ): ArkstackErrorPayload {\n const primaryError = ErrorHandler.getPrimaryError(err)\n const detailedError = typeof primaryError === 'string'\n ? undefined\n : primaryError\n const validationError = detailedError && ErrorHandler.isValidationError(detailedError)\n ? detailedError\n : undefined\n const modelNotFoundError = detailedError && ErrorHandler.isModelNotFoundError(detailedError)\n ? detailedError\n : undefined\n const payload: ArkstackErrorPayload = {\n status: 'error',\n code: typeof err === 'string'\n ? 500\n : ErrorHandler.normalizeStatusCode(detailedError?.statusCode ?? detailedError?.status),\n message: typeof err === 'string'\n ? `${fallbackMessage}: ${err}`\n : detailedError?.message || err.message || fallbackMessage,\n }\n\n if (validationError) {\n payload.code = ErrorHandler.normalizeStatusCode(validationError.statusCode ?? validationError.status, 422)\n payload.message = validationError.message || fallbackMessage\n payload.errors = ErrorHandler.getValidationErrors(validationError)\n } else if (modelNotFoundError) {\n payload.code = 404\n payload.message = `${modelNotFoundError.getModelName?.()} not found!`\n } else if (detailedError?.stack) {\n const [stackLine, ...rest] = detailedError.stack.split('\\n')\n const [key, content = ''] = stackLine.split(':')\n\n payload.errors = {\n [key]: [content.trim(), ...rest.map((entry: string) => entry.trim())]\n }\n }\n\n if (\n detailedError &&\n process.env.NODE_ENV === 'development' &&\n !ErrorHandler.shouldHideStack() &&\n !validationError\n ) {\n payload.stack = detailedError.stack\n }\n\n if (!validationError || payload.code === 404) {\n delete payload.errors\n delete payload.stack\n }\n\n return payload\n }\n\n static logUnhandledError (\n err: unknown,\n request: Record<string, unknown>,\n message: string,\n ) {\n ErrorHandler.getErrorLogger().error({\n error: ErrorHandler.serializeError(err),\n request,\n }, message)\n }\n}\n\nexport const toErrorShape = ErrorHandler.toErrorShape\nexport const normalizeStatusCode = ErrorHandler.normalizeStatusCode\nexport const getErrorLogger = ErrorHandler.getErrorLogger\nexport const serializeError = ErrorHandler.serializeError\nexport const getPrimaryError = ErrorHandler.getPrimaryError\nexport const getValidationErrors = ErrorHandler.getValidationErrors\nexport const isValidationError = ErrorHandler.isValidationError\nexport const isModelNotFoundError = ErrorHandler.isModelNotFoundError\nexport const shouldHideStack = ErrorHandler.shouldHideStack\nexport const shouldLogError = ErrorHandler.shouldLogError\nexport const createErrorPayload = ErrorHandler.createErrorPayload\nexport const logUnhandledError = ErrorHandler.logUnhandledError\n","import chalk, { type ChalkInstance } from 'chalk'\nimport { LoggerChalk, LoggerLog, LoggerParseSignature } from './types'\n\nclass Console {\n static log = (...args: any[]) => Logger.log(args.map(e => [e, 'white']))\n static debug = (...args: any[]) => Logger.debug(args, false, true)\n static warn = (...args: any[]) => args.map(e => Logger.warn(e, false, true))\n static info = (...args: any[]) => args.map(e => Logger.info(e, false, true))\n static error = (...args: any[]) => args.map(e => Logger.error(e, false), true)\n}\n\nexport class Logger {\n /**\n * Global verbosity configuration\n */\n private static verbosity: number = 0\n private static isQuiet: boolean = false\n private static isSilent: boolean = false\n\n /**\n * Configure global verbosity levels\n */\n static configure (options: { verbosity?: number, quiet?: boolean, silent?: boolean } = {}) {\n this.verbosity = options.verbosity ?? 0\n this.isQuiet = options.quiet ?? false\n this.isSilent = options.silent ?? false\n }\n\n /**\n * Check if output should be suppressed\n */\n private static shouldSuppressOutput (level: 'line' | 'debug' | 'info' | 'warn' | 'error' | 'success'): boolean {\n if (this.isSilent) return true\n if (this.isQuiet && (level === 'info' || level === 'success')) return true\n if (level === 'debug' && this.verbosity < 3) return true\n\n return false\n }\n /**\n * Logs the message in two columns\n * \n * @param name \n * @param value \n * @param log If set to false, array of [name, dots, value] output will be returned and not logged \n * @returns \n */\n static twoColumnDetail (name: string, value: string, log?: true, spacer?: string): void\n static twoColumnDetail (name: string, value: string, log?: false, spacer?: string): [string, string, string]\n static twoColumnDetail (name: string, value: string, log = true, spacer = '.'): [string, string, string] | void {\n // eslint-disable-next-line no-control-regex\n const regex = /\\x1b\\[\\d+m/g\n const width = Math.max(process.stdout.columns, 100)\n const dots = Math.max(width - name.replace(regex, '').length - value.replace(regex, '').length - 10, 0)\n\n if (log) return console.log(name, chalk.gray(spacer.repeat(dots)), value)\n else return [name, chalk.gray(spacer.repeat(dots)), value]\n }\n\n /**\n * Logs the message in two columns\n * \n * @param name \n * @param desc \n * @param width \n * @param log If set to false, array of [name, dots, value] output will be returned and not logged \n * @returns \n */\n static describe (name: string, desc: string, width?: number, log?: true): void\n static describe (name: string, desc: string, width?: number, log?: false): [string, string, string]\n static describe (name: string, desc: string, width = 50, log = true): [string, string, string] | void {\n width = Math.max(width, 30)\n // eslint-disable-next-line no-control-regex\n const regex = /\\x1b\\[\\d+m/g\n const dots = Math.max(width - name.replace(regex, '').length, 0)\n\n if (log) return console.log(name, ' '.repeat(dots), desc)\n else return [name, ' '.repeat(dots), desc]\n }\n\n /**\n * Logs the message in two columns but allways passing status\n * \n * @param name \n * @param value \n * @param status \n * @param exit \n * @param preserveCol \n */\n static split (name: string, value: string, status?: 'success' | 'info' | 'error', exit = false, preserveCol = false, spacer = '.') {\n status ??= 'info'\n const color = { success: chalk.bgGreen, info: chalk.bgBlue, error: chalk.bgRed }\n\n const [_name, dots, val] = this.twoColumnDetail(name, value, false, spacer)\n\n console.log(this.textFormat(_name, color[status], preserveCol), dots, val)\n\n if (exit) process.exit(0)\n }\n\n /**\n * Wraps text with chalk\n * \n * @param txt \n * @param color \n * @param preserveCol \n * @returns \n */\n static textFormat (\n txt: unknown | unknown[],\n color: (...text: unknown[]) => string,\n preserveCol = false\n ): string {\n if (txt instanceof Error) {\n const err: Error & { code?: number, statusCode?: number } = txt\n const code = err.code ?? err.statusCode ? ` (${err.code ?? err.statusCode})` : ''\n const output: string[] = []\n\n if (err.message) {\n output.push(this.textFormat(`${err.constructor.name}${code}: ${err.message}`, chalk.bgRed, preserveCol))\n }\n\n if (err.stack) {\n output.push(' ' + chalk.white(err.stack.replace(`${err.name}: ${err.message}`, '').trim()))\n }\n\n return output.join('\\n')\n }\n\n if (Array.isArray(txt)) {\n return txt.map(e => this.textFormat(e, color, preserveCol)).join('\\n')\n }\n\n if (typeof txt === 'object') {\n return this.textFormat(Object.values(txt!), color, preserveCol)\n }\n\n if (typeof txt !== 'string') {\n return color(txt)\n }\n\n const str = String(txt)\n\n if (preserveCol) return str\n\n const [first, ...rest] = str.split(':')\n if (rest.length === 0) return str\n\n return color(` ${first} `) + rest.join(':')\n }\n\n /**\n * Logs a success message\n * \n * @param msg \n * @param exit \n * @param preserveCol \n */\n static success (msg: any, exit = false, preserveCol = false) {\n if (!this.shouldSuppressOutput('success')) {\n console.log(chalk.green('✓'), this.textFormat(msg, chalk.bgGreen, preserveCol))\n }\n if (exit) process.exit(0)\n }\n\n /**\n * Logs an informational message\n * \n * @param msg \n * @param exit \n * @param preserveCol \n */\n static info (msg: any, exit = false, preserveCol = false) {\n if (!this.shouldSuppressOutput('info')) {\n console.log(chalk.blue('ℹ'), this.textFormat(msg, chalk.bgBlue, preserveCol))\n }\n if (exit) process.exit(0)\n }\n\n /**\n * Logs an error message\n * \n * @param msg \n * @param exit \n * @param preserveCol \n */\n static error (msg: any, exit = true, preserveCol = false) {\n if (!this.shouldSuppressOutput('error')) {\n if (msg instanceof Error) {\n if (msg.message) {\n console.error(chalk.red('✖'), this.textFormat('ERROR:' + msg.message, chalk.bgRed, preserveCol))\n }\n console.error(chalk.red(`${(msg as any).detail ? `${(msg as any).detail}\\n` : ''}${msg.stack}`))\n } else {\n console.error(chalk.red('✖'), this.textFormat(msg, chalk.bgRed, preserveCol))\n }\n }\n if (exit) process.exit(1)\n }\n\n /**\n * Logs a warning message\n * \n * @param msg \n * @param exit \n * @param preserveCol \n */\n static warn (msg: any, exit = false, preserveCol = false) {\n if (!this.shouldSuppressOutput('warn')) {\n console.warn(chalk.yellow('⚠'), this.textFormat(msg, chalk.bgYellow, preserveCol))\n }\n if (exit) process.exit(0)\n }\n\n /**\n * Logs a debug message (only shown with verbosity >= 3)\n * \n * @param msg \n * @param exit \n * @param preserveCol \n */\n static debug<M = any> (msg: M | M[], exit = false, preserveCol = false) {\n if (!this.shouldSuppressOutput('debug')) {\n if (Array.isArray(msg)) {\n for (let i = 0; i < msg.length; i++) {\n console.log(chalk.gray('🐛'), chalk.bgGray(i + 1), this.textFormat(msg[i], chalk.bgGray, preserveCol))\n }\n } else {\n console.log(chalk.gray('🐛'), this.textFormat(msg, chalk.bgGray, preserveCol))\n }\n }\n if (exit) process.exit(0)\n }\n\n /**\n * Terminates the process\n */\n static quiet () {\n process.exit(0)\n }\n\n static chalker (styles: LoggerChalk[]) {\n return (input: any): string =>\n styles.reduce((acc, style) => {\n if ((style as any) in chalk) {\n const fn = typeof style === 'function'\n ? style\n : chalk[style as never]\n\n return fn(acc)\n }\n\n return acc\n }, input)\n }\n\n /**\n * Parse an array formated message and logs it\n * \n * @param config \n * @param joiner \n * @param log If set to false, string output will be returned and not logged \n * @param sc color to use ue on split text if : is found \n */\n static parse (config: LoggerParseSignature, joiner?: string, log?: true, sc?: LoggerChalk): void\n static parse (config: LoggerParseSignature, joiner?: string, log?: false, sc?: LoggerChalk): string\n static parse (config: LoggerParseSignature, joiner = ' ', log = true, sc?: LoggerChalk): string | void {\n const string = config.map(([str, opt]) => {\n if (Array.isArray(opt)) {\n opt = Logger.chalker(opt) as ChalkInstance\n }\n\n const output = typeof opt === 'string' && typeof chalk[opt] === 'function'\n ? (chalk as any)[opt](str)\n : typeof opt === 'function' ? opt(str) : str\n\n if (!sc) {\n return output\n }\n\n return this.textFormat(output, Logger.chalker(Array.isArray(sc) ? sc : [sc]))\n }).join(joiner)\n\n if (log && !this.shouldSuppressOutput('line')) console.log(string)\n else return string\n }\n\n /**\n * Ouput formater object or format the output\n * \n * @returns \n */\n static log: LoggerLog = ((config, joiner, log: boolean = true, sc) => {\n if (typeof config === 'string') {\n const conf = [[config, joiner]] as [string, keyof ChalkInstance][]\n\n return this.parse(conf, '', log as false, sc)\n } else if (Array.isArray(config)) {\n return this.parse(config, String(joiner), log as false, sc)\n } else if (log && !this.shouldSuppressOutput('line')) {\n return console.log(this.textFormat(config, Logger.chalker(['blue'])))\n }\n\n return this\n }) as LoggerLog\n\n /**\n * A simple console like output logger\n * \n * @returns \n */\n static console () {\n return Console\n }\n}","import { createCipheriv, createDecipheriv, createHash, randomBytes } from 'node:crypto'\n\nimport { env } from '../system'\n\nexport class Encryption {\n private static readonly algorithm = 'aes-256-gcm'\n\n private static getKey () {\n const secret = env('TWO_FACTOR_ENCRYPTION_KEY')\n\n if (!secret) {\n throw new Error('TWO_FACTOR_ENCRYPTION_KEY is required to use two-factor authentication')\n }\n\n return createHash('sha256').update(secret).digest()\n }\n\n static encrypt (value: string) {\n const iv = randomBytes(12)\n const cipher = createCipheriv(this.algorithm, this.getKey(), iv)\n const ciphertext = Buffer.concat([\n cipher.update(value, 'utf8'),\n cipher.final(),\n ])\n const authTag = cipher.getAuthTag()\n\n return [iv, authTag, ciphertext].map((part) => part.toString('base64url')).join(':')\n }\n\n static decrypt (payload: string) {\n const [iv, authTag, ciphertext] = payload.split(':')\n\n if (!iv || !authTag || !ciphertext) {\n throw new Error('Invalid encrypted payload format')\n }\n\n const decipher = createDecipheriv(\n this.algorithm,\n this.getKey(),\n Buffer.from(iv, 'base64url'),\n )\n\n decipher.setAuthTag(Buffer.from(authTag, 'base64url'))\n\n const plaintext = Buffer.concat([\n decipher.update(Buffer.from(ciphertext, 'base64url')),\n decipher.final(),\n ])\n\n return plaintext.toString('utf8')\n }\n}","import { Secret, TOTP } from 'otpauth'\nimport { compare, genSalt, hash } from 'bcryptjs'\n\nimport { env } from '../system'\n\nexport class Hash {\n /**\n * Hash a value using bcrypt\n * \n * @param value \n * @returns \n */\n static async make (value: string): Promise<string> {\n const salt = await genSalt(10)\n\n return await hash(value, salt)\n }\n\n /**\n * Verify a value against a hashed value\n * \n * @param value \n * @param hashedValue \n * @returns \n */\n static async verify (value: string, hashedValue: string): Promise<boolean> {\n return await compare(value, hashedValue)\n }\n\n /**\n * Generate a one-time password (OTP) using TOTP algorithm\n * \n * @param digits The number of digits for the OTP, default is 6.\n * @param label A label to identify the OTP, can be an email or phone number.\n * @param period Interval of time for which a token is valid, in seconds.\n * @returns \n */\n static otp (digits: number = 6, label: string = 'Alice', period: number = 30) {\n return new TOTP({\n label,\n digits,\n issuer: env('APP_NAME', 'Roseed'),\n algorithm: 'SHA1',\n period, // in seconds.\n secret: 'US3WHSG7X5KAPV27VANWKQHF3SH3HULL',\n })\n }\n\n static totp (secret: string, label: string, issuer: string = env('APP_NAME', 'Roseed'), period: number = 30) {\n return new TOTP({\n issuer,\n label,\n algorithm: 'SHA1',\n digits: 6,\n period,\n secret: Secret.fromBase32(secret),\n })\n }\n}","import { getUserConfig, type Model, type ModelStatic } from 'arkormx'\nimport { importFile } from '../system'\nimport path from 'node:path'\n\nexport type AbstractModelConstructor<TModel = unknown> =\n abstract new (attributes?: Record<string, unknown>) => TModel\n\nexport type ModelConstructor<TModel extends Model = Model> =\n AbstractModelConstructor<TModel> &\n Pick<ModelStatic<TModel>, keyof ModelStatic<TModel>>\n\n// eslint-disable-next-line @typescript-eslint/no-empty-object-type\nexport interface ModelRegistry { }\n\ntype ModelName = Extract<keyof ModelRegistry, string>\ntype ModelModule = Record<string, unknown> & {\n default?: unknown;\n}\n\n/**\n * Determine the number of items to return per page based on the provided query parameters.\n * \n * @param query \n * @returns \n */\nexport const perPage = (query: { limit?: number; perPage?: number }) => {\n\n const requestedPerPage = Number(query.limit ?? query.perPage ?? 15)\n\n return Number.isFinite(requestedPerPage) && requestedPerPage > 0\n ? Math.min(requestedPerPage, 50)\n : 15\n}\n\n/**\n * Import an application model by name.\n *\n * Apps can augment `ModelRegistry` to make `getModel('User')` return `typeof User`.\n * Without a registry entry, pass the class type explicitly: `getModel<typeof User>('User')`.\n * \n * @param modelName \n */\nexport async function getModel<TName extends ModelName> (\n modelName: TName\n): Promise<ModelRegistry[TName]>\nexport async function getModel<TModel extends AbstractModelConstructor = ModelConstructor> (\n modelName: string\n): Promise<TModel>\nexport async function getModel (modelName: string) {\n const resolveModelExport = (module: ModelModule | unknown, modelName: string) => {\n if (!isModelModule(module)) {\n return module\n }\n\n return module.default ?? module[modelName] ?? module\n }\n\n const isModelModule = (value: unknown): value is ModelModule => (\n typeof value === 'object' && value !== null\n )\n\n const modelPath = getUserConfig().paths?.models || './src/models'\n const modulePath = path.join(\n path.isAbsolute(modelPath) ? modelPath : path.join(process.cwd(), modelPath),\n modelName\n )\n const module = await importFile<ModelModule | unknown>(modulePath)\n const exportName = path.basename(modelName, path.extname(modelName))\n const model = resolveModelExport(module, exportName)\n\n if (typeof model !== 'function') {\n throw new Error(`Model \"${modelName}\" not found`)\n }\n\n return model\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arkstack/common",
3
- "version": "0.3.12",
3
+ "version": "0.3.15",
4
4
  "type": "module",
5
5
  "description": "Common package for Arkstack providing common implementations of core Arkstack features such as routing, middleware, and database integration.",
6
6
  "homepage": "https://arkstack.toneflix.net",
@@ -31,12 +31,15 @@
31
31
  },
32
32
  "dependencies": {
33
33
  "@rexxars/jiti": "^2.6.2",
34
+ "bcryptjs": "^3.0.3",
34
35
  "chalk": "^5.6.2",
35
36
  "detect-port": "^2.1.0",
37
+ "otpauth": "^9.5.1",
36
38
  "pino": "^10.3.1"
37
39
  },
38
40
  "peerDependencies": {
39
- "@h3ravel/support": "^0.15.11"
41
+ "@h3ravel/support": "^0.15.11",
42
+ "arkormx": "^2.0.6"
40
43
  },
41
44
  "scripts": {
42
45
  "build": "tsdown --config-loader unconfig",