@arkstack/common 0.11.5 → 0.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.d.ts +41 -0
- package/dist/{helpers-CCnLLifY.d.ts → helpers-D3QVIFSV.d.ts} +5 -2
- package/dist/index.d.ts +6 -5
- package/dist/index.js +19 -56
- package/dist/index.js.map +1 -1
- package/dist/utils/index.d.ts +2 -2
- package/dist/utils/index.js +2 -2
- package/dist/{utils-CpOKE57m.js → utils-C6d-ohT-.js} +97 -3
- package/dist/utils-C6d-ohT-.js.map +1 -0
- package/package.json +3 -3
- package/dist/utils-CpOKE57m.js.map +0 -1
package/dist/app.d.ts
CHANGED
|
@@ -12,6 +12,47 @@ interface Stubs {
|
|
|
12
12
|
declare global {
|
|
13
13
|
var env: GlobalEnv
|
|
14
14
|
var config: GlobalConfig
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Thows to abort the current request
|
|
18
|
+
*
|
|
19
|
+
* @param message
|
|
20
|
+
* @param code
|
|
21
|
+
* @throws {RequestException}
|
|
22
|
+
*/
|
|
23
|
+
function abort (
|
|
24
|
+
message?: string,
|
|
25
|
+
code?: number
|
|
26
|
+
): void
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Asserts that a boolean condition is true.
|
|
30
|
+
*
|
|
31
|
+
* @param boolean
|
|
32
|
+
* @param message
|
|
33
|
+
* @param code
|
|
34
|
+
* @throws {RequestException} Throws if the boolean condition is true.
|
|
35
|
+
*/
|
|
36
|
+
function abortIf<T> (
|
|
37
|
+
boolean: T,
|
|
38
|
+
message?: string,
|
|
39
|
+
code?: number,
|
|
40
|
+
): asserts boolean is T
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Asserts that a value is not null or undefined.
|
|
44
|
+
*
|
|
45
|
+
* @param value
|
|
46
|
+
* @param message
|
|
47
|
+
* @param code
|
|
48
|
+
* @throws {RequestException} Throws if the value is null or undefined.
|
|
49
|
+
*/
|
|
50
|
+
function assertFound<T> (
|
|
51
|
+
value: T | null | undefined,
|
|
52
|
+
message: string,
|
|
53
|
+
code: number = 404,
|
|
54
|
+
): asserts value is T
|
|
55
|
+
|
|
15
56
|
interface String {
|
|
16
57
|
/**
|
|
17
58
|
* Converts the string to title case.
|
|
@@ -37,6 +37,9 @@ declare const initializeGlobalContext: ({
|
|
|
37
37
|
Response?: any;
|
|
38
38
|
Session?: any;
|
|
39
39
|
}) => Promise<void>;
|
|
40
|
+
declare const abort: (message?: string, code?: number) => void;
|
|
41
|
+
declare const abortIf: <T>(boolean: T, message?: string, code?: number) => asserts boolean is T;
|
|
42
|
+
declare const assertFound: <T>(value: T | null | undefined, message: string, code?: number) => asserts value is T;
|
|
40
43
|
//#endregion
|
|
41
|
-
export {
|
|
42
|
-
//# sourceMappingURL=helpers-
|
|
44
|
+
export { abortIf as a, initializeGlobalContext as c, Encryption as d, abort as i, perPage as l, ModelConstructor as n, assertFound as o, ModelRegistry as r, getModel as s, AbstractModelConstructor as t, Hash as u };
|
|
45
|
+
//# sourceMappingURL=helpers-D3QVIFSV.d.ts.map
|
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
/// <reference path="./app.d.ts" />
|
|
2
|
-
import { a as
|
|
2
|
+
import { a as abortIf, c as initializeGlobalContext, d as Encryption, i as abort, l as perPage, n as ModelConstructor, o as assertFound, r as ModelRegistry, s as getModel, t as AbstractModelConstructor, u as Hash } from "./helpers-D3QVIFSV.js";
|
|
3
3
|
import { JitiOptions, JitiResolveOptions } from "jiti";
|
|
4
4
|
import { Arkstack } from "@arkstack/contract";
|
|
5
5
|
import pino from "pino";
|
|
6
6
|
import { ChalkInstance } from "chalk";
|
|
7
7
|
|
|
8
8
|
//#region src/lifecycle.d.ts
|
|
9
|
-
declare const bindGracefulShutdown: (shutdown: () => Promise<void> | void) => void;
|
|
9
|
+
declare const bindGracefulShutdown: (shutdown: () => Promise<void> | void, defer?: boolean) => void;
|
|
10
10
|
//#endregion
|
|
11
11
|
//#region src/network.d.ts
|
|
12
|
-
declare const bootWithDetectedPort: <TApp, TRoutes = unknown, THandler = unknown>(boot: (port: number) => Promise<void>, preferredPort?: number, app?: Arkstack<TApp, TRoutes, THandler
|
|
12
|
+
declare const bootWithDetectedPort: <TApp, TRoutes = unknown, THandler = unknown>(boot: (port: number) => Promise<void>, preferredPort?: number, app?: Arkstack<TApp, TRoutes, THandler>, defer?: boolean) => Promise<void>;
|
|
13
13
|
declare const renderError: ({
|
|
14
14
|
message,
|
|
15
15
|
stack,
|
|
@@ -67,7 +67,7 @@ interface ConfigRegistry {}
|
|
|
67
67
|
interface EnvRegistry {}
|
|
68
68
|
type UnionToIntersection<U> = (U extends any ? (x: U) => void : never) extends ((x: infer I) => void) ? I : never;
|
|
69
69
|
type MergedConfig<X> = UnionToIntersection<X>;
|
|
70
|
-
type Primitive = string | number | boolean | null | undefined |
|
|
70
|
+
type Primitive = string | number | boolean | null | undefined | Function;
|
|
71
71
|
type LoggerChalk = keyof ChalkInstance | ChalkInstance | (keyof ChalkInstance)[];
|
|
72
72
|
type LoggerParseSignature = [string, LoggerChalk][];
|
|
73
73
|
type DotPathValue<T, P extends string> = P extends `${infer Head}.${infer Tail}` ? Head extends keyof T ? DotPathValue<T[Head], Tail> : never : P extends keyof T ? T[P] : never;
|
|
@@ -148,6 +148,7 @@ declare class AppException extends Exception {
|
|
|
148
148
|
declare class RequestException extends AppException {
|
|
149
149
|
statusCode: number;
|
|
150
150
|
constructor(message?: string, statusCode?: number, options?: ErrorOptions);
|
|
151
|
+
static assertFound<T>(value: T | null | undefined, message: string, code?: number): asserts value is T;
|
|
151
152
|
static assertNotEmpty<T>(value: T | null | undefined, message: string, code?: number): asserts value is T;
|
|
152
153
|
static abortIf<T>(boolean: T, message: string, code?: number): asserts boolean is T;
|
|
153
154
|
}
|
|
@@ -195,5 +196,5 @@ declare class Hook {
|
|
|
195
196
|
static clear: () => void;
|
|
196
197
|
}
|
|
197
198
|
//#endregion
|
|
198
|
-
export { AbstractModelConstructor, AppException, ArkstackErrorPayload, ArkstackErrorShape, ConfigRegistry, ConfigShape, DotPath, DotPathValue, Encryption, EnvRegistry, ErrorHandler, Exception, FileImporter, GlobalConfig, GlobalEnv, Hash, Hook, HookArgs, HookFor, HookName, HookPos, HookPositions, HookRegistry, IHook, Logger, LoggerChalk, LoggerLog, LoggerParseSignature, MergedConfig, ModelConstructor, ModelRegistry, Primitive, RequestException, UnionToIntersection, appUrl, bindGracefulShutdown, bootWithDetectedPort, config, createErrorPayload, env, getErrorLogger, getModel, getPrimaryError, getValidationErrors, importFile, initializeGlobalContext, interopDefault, isModelNotFoundError, isValidationError, loadPrototypes, logUnhandledError, nodeEnv, normalizeStatusCode, outputDir, perPage, renderError, serializeError, shouldHideStack, shouldLogError, toErrorShape };
|
|
199
|
+
export { AbstractModelConstructor, AppException, ArkstackErrorPayload, ArkstackErrorShape, ConfigRegistry, ConfigShape, DotPath, DotPathValue, Encryption, EnvRegistry, ErrorHandler, Exception, FileImporter, GlobalConfig, GlobalEnv, Hash, Hook, HookArgs, HookFor, HookName, HookPos, HookPositions, HookRegistry, IHook, Logger, LoggerChalk, LoggerLog, LoggerParseSignature, MergedConfig, ModelConstructor, ModelRegistry, Primitive, RequestException, UnionToIntersection, abort, abortIf, appUrl, assertFound, bindGracefulShutdown, bootWithDetectedPort, config, createErrorPayload, env, getErrorLogger, getModel, getPrimaryError, getValidationErrors, importFile, initializeGlobalContext, interopDefault, isModelNotFoundError, isValidationError, loadPrototypes, logUnhandledError, nodeEnv, normalizeStatusCode, outputDir, perPage, renderError, serializeError, shouldHideStack, shouldLogError, toErrorShape };
|
|
199
200
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { S as outputDir, _ as config, a as abort, b as interopDefault, c as getModel, d as RequestException, f as AppException, g as appUrl, h as Encryption, l as initializeGlobalContext, m as Hash, o as abortIf, p as Exception, s as assertFound, u as perPage, v as env, x as nodeEnv, y as importFile } from "./utils-C6d-ohT-.js";
|
|
2
2
|
import { Hook as Hook$1 } from "@arkstack/foundry";
|
|
3
3
|
import { Arkstack } from "@arkstack/contract";
|
|
4
4
|
import { str } from "@h3ravel/support";
|
|
5
5
|
import path from "node:path";
|
|
6
|
-
import { detect } from "detect-port";
|
|
7
6
|
import { ModelNotFoundException } from "arkormx";
|
|
7
|
+
import { detect } from "detect-port";
|
|
8
8
|
import pino from "pino";
|
|
9
9
|
import chalk from "chalk";
|
|
10
10
|
//#region src/lifecycle.ts
|
|
11
|
-
const bindGracefulShutdown = (shutdown) => {
|
|
11
|
+
const bindGracefulShutdown = (shutdown, defer) => {
|
|
12
|
+
if (defer) return;
|
|
12
13
|
[
|
|
13
14
|
"SIGINT",
|
|
14
15
|
"SIGTERM",
|
|
@@ -22,17 +23,29 @@ const bindGracefulShutdown = (shutdown) => {
|
|
|
22
23
|
};
|
|
23
24
|
//#endregion
|
|
24
25
|
//#region src/network.ts
|
|
25
|
-
|
|
26
|
+
/**
|
|
27
|
+
* Boots the app using an available port close to the requested port
|
|
28
|
+
*when requested port is not available
|
|
29
|
+
*
|
|
30
|
+
* @param boot
|
|
31
|
+
* @param preferredPort
|
|
32
|
+
* @param app
|
|
33
|
+
* @param defer
|
|
34
|
+
*/
|
|
35
|
+
const bootWithDetectedPort = async (boot, preferredPort = 3e3, app, defer) => {
|
|
26
36
|
const port = await detect(preferredPort);
|
|
27
37
|
if (Hook$1.has("boot", "before")) Hook$1.get("boot", "before", port, app);
|
|
28
38
|
if (app && !globalThis.app) globalThis.app = () => app;
|
|
29
39
|
globalThis.env = env;
|
|
30
40
|
globalThis.config = config;
|
|
31
41
|
globalThis.str = str;
|
|
42
|
+
globalThis.abort = abort;
|
|
43
|
+
globalThis.abortIf = abortIf;
|
|
44
|
+
globalThis.assertFound = assertFound;
|
|
32
45
|
globalThis.arkctx = { runtime: "HTTP" };
|
|
33
46
|
await boot(port);
|
|
34
47
|
await initializeGlobalContext();
|
|
35
|
-
bindGracefulShutdown(async () => await app?.shutdown());
|
|
48
|
+
bindGracefulShutdown(async () => await app?.shutdown(), defer);
|
|
36
49
|
if (Hook$1.has("boot", "after")) Hook$1.get("boot", "after", port, app);
|
|
37
50
|
};
|
|
38
51
|
const renderError = ({ message = "An unexpected error occurred.", stack, title, code = 500 }) => {
|
|
@@ -81,56 +94,6 @@ const loadPrototypes = () => {
|
|
|
81
94
|
};
|
|
82
95
|
};
|
|
83
96
|
//#endregion
|
|
84
|
-
//#region src/Exceptions/Exception.ts
|
|
85
|
-
var Exception = class extends Error {
|
|
86
|
-
name;
|
|
87
|
-
constructor(message, options) {
|
|
88
|
-
super(message, options);
|
|
89
|
-
this.name = "Exception";
|
|
90
|
-
}
|
|
91
|
-
};
|
|
92
|
-
//#endregion
|
|
93
|
-
//#region src/Exceptions/AppException.ts
|
|
94
|
-
var AppException = class extends Exception {
|
|
95
|
-
errors = void 0;
|
|
96
|
-
statusCode;
|
|
97
|
-
constructor(message, statusCode = 400, options) {
|
|
98
|
-
super(message, options);
|
|
99
|
-
this.statusCode = statusCode;
|
|
100
|
-
}
|
|
101
|
-
};
|
|
102
|
-
//#endregion
|
|
103
|
-
//#region src/Exceptions/RequestException.ts
|
|
104
|
-
var RequestException = class RequestException extends AppException {
|
|
105
|
-
statusCode;
|
|
106
|
-
constructor(message, statusCode = 400, options) {
|
|
107
|
-
super(message, statusCode, options);
|
|
108
|
-
this.statusCode = statusCode;
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* Asserts that a value is not null or undefined.
|
|
112
|
-
*
|
|
113
|
-
* @param value
|
|
114
|
-
* @param message
|
|
115
|
-
* @param code
|
|
116
|
-
* @throws {RequestException} Throws if the value is null or undefined.
|
|
117
|
-
*/
|
|
118
|
-
static assertNotEmpty(value, message, code = 404) {
|
|
119
|
-
if (!value) throw new RequestException(message, code);
|
|
120
|
-
}
|
|
121
|
-
/**
|
|
122
|
-
* Asserts that a boolean condition is true.
|
|
123
|
-
*
|
|
124
|
-
* @param boolean
|
|
125
|
-
* @param message
|
|
126
|
-
* @param code
|
|
127
|
-
* @throws {RequestException} Throws if the boolean condition is true.
|
|
128
|
-
*/
|
|
129
|
-
static abortIf(boolean, message, code) {
|
|
130
|
-
if (boolean) throw new RequestException(message, code);
|
|
131
|
-
}
|
|
132
|
-
};
|
|
133
|
-
//#endregion
|
|
134
97
|
//#region src/ErrorHandler.ts
|
|
135
98
|
var ErrorHandler = class ErrorHandler {
|
|
136
99
|
static loggerCache = /* @__PURE__ */ new Map();
|
|
@@ -518,6 +481,6 @@ var Hook = class {
|
|
|
518
481
|
};
|
|
519
482
|
};
|
|
520
483
|
//#endregion
|
|
521
|
-
export { AppException, Encryption, ErrorHandler, Exception, Hash, Hook, Logger, RequestException, appUrl, bindGracefulShutdown, bootWithDetectedPort, config, createErrorPayload, env, getErrorLogger, getModel, getPrimaryError, getValidationErrors, importFile, initializeGlobalContext, interopDefault, isModelNotFoundError, isValidationError, loadPrototypes, logUnhandledError, nodeEnv, normalizeStatusCode, outputDir, perPage, renderError, serializeError, shouldHideStack, shouldLogError, toErrorShape };
|
|
484
|
+
export { AppException, Encryption, ErrorHandler, Exception, Hash, Hook, Logger, RequestException, abort, abortIf, appUrl, assertFound, bindGracefulShutdown, bootWithDetectedPort, config, createErrorPayload, env, getErrorLogger, getModel, getPrimaryError, getValidationErrors, importFile, initializeGlobalContext, interopDefault, isModelNotFoundError, isValidationError, loadPrototypes, logUnhandledError, nodeEnv, normalizeStatusCode, outputDir, perPage, renderError, serializeError, shouldHideStack, shouldLogError, toErrorShape };
|
|
522
485
|
|
|
523
486
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["Hook","Hook"],"sources":["../src/lifecycle.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/Hook.ts"],"sourcesContent":["import { Hook } from '@arkstack/foundry'\n\nexport const bindGracefulShutdown = (shutdown: () => Promise<void> | void) => {\n ['SIGINT', 'SIGTERM', 'SIGQUIT'].forEach((signal) => {\n process.on(signal, async () => {\n if (Hook.has('shutdown', 'before')) Hook.get('shutdown', 'after', {})\n await shutdown()\n })\n })\n}\n","import { config, env } from './system'\n\nimport { Arkstack } from '@arkstack/contract'\nimport { Hook } from '@arkstack/foundry'\nimport { bindGracefulShutdown } from './lifecycle'\nimport { detect } from 'detect-port'\nimport { initializeGlobalContext } from './utils'\nimport { str } from '@h3ravel/support'\n\nexport const bootWithDetectedPort = async <TApp, TRoutes = unknown, THandler = unknown> (\n boot: (port: number) => Promise<void>,\n preferredPort: number = 3000,\n app?: Arkstack<TApp, TRoutes, THandler>\n) => {\n const port = await detect(preferredPort)\n\n if (Hook.has('boot', 'before')) Hook.get('boot', 'before', port, app)\n\n if (app && !globalThis.app) globalThis.app = () => app as never\n globalThis.env = env\n globalThis.config = config\n globalThis.str = str\n globalThis.arkctx = {\n runtime: 'HTTP',\n }\n await boot(port)\n await initializeGlobalContext()\n\n // Handle graceful shutdown\n bindGracefulShutdown(async () => await app?.shutdown())\n\n if (Hook.has('boot', 'after')) Hook.get('boot', 'after', port, app)\n}\n\nexport const renderError = ({\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 globalThis.view('~arkstack/common.error', {\n code,\n title,\n stack,\n message,\n }).renderSync()\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'\nimport { Arkstack } from '@arkstack/contract'\nimport { ModelNotFoundException } from 'arkormx'\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(Arkstack.rootDir(), '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 if ((error as any).cause && (error as any).cause instanceof ModelNotFoundException) {\n (error as any).getModelName = (error as any).cause.getModelName\n\n return true\n }\n\n return typeof candidate?.getModelName === 'function' ||\n error instanceof ModelNotFoundException\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\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 { HookArgs, HookFor, HookName, HookPos, HookPositions, HookRegistry, IHook } from './types'\n\nexport class Hook {\n private static hooks = new Map<string, IHook>()\n\n /**\n * Hooks define code that should run within defined boundaries to add extra functionalities.\n * \n * @param name \n * @param value \n */\n static set<N extends HookName> (\n name: N | (string & {}),\n hook: HookFor<N>\n ) {\n const oldhook = this.hooks.get(name) ?? {}\n\n this.hooks.set(name, {\n ...oldhook,\n ...hook,\n })\n }\n\n /**\n * Check if a hook is defined by name\n * \n * @param name \n */\n static has<N extends HookName, P extends HookPositions<N>> (name: N | (string & {}), pos?: P) {\n if (pos && this.hooks.has(name))\n return Boolean(this.get(name, pos))\n\n return this.hooks.has(name)\n }\n\n /**\n * Retrieve a defined hook by name\n * \n * @param name \n */\n static get<N extends HookName> (name: N): HookFor<N> | undefined\n /**\n * Retrieve a defined hook by name and position\n * \n * @param name \n * @param pos \n */\n static get<N extends HookName, P extends HookPositions<N>> (name: N, pos: P): HookPos<N, P> | undefined\n /**\n * Retrieve a defined hook by name and position the set args for callback\n * \n * @param name \n * @param pos \n */\n static get<N extends HookName, P extends HookPositions<N>> (name: N, pos: P, ...args: HookArgs<N, P>): void\n static get<N extends HookName, P extends HookPositions<N>> (\n name: N,\n pos?: P,\n ...args: HookArgs<N, P> | any[]\n ): HookFor<N> | HookPos<N, P> | undefined {\n const hook = this.hooks.get(name)\n\n if (!hook) return undefined\n if (pos === undefined) return hook as HookFor<N>\n\n const fn = hook[pos]\n if (!fn) return undefined\n\n if (args.length > 0) return fn(...args) as HookPos<N, P>\n\n return fn as HookPos<N, P>\n }\n\n /**\n * Retrieve all defined hooks\n * \n * @param name \n */\n static getAll = () => {\n const hooks: Record<string, IHook> & HookRegistry = {}\n\n for (const [name, value] of this.hooks)\n hooks[name] = value\n\n return hooks\n }\n\n /**\n * Remove the defined hook\n * \n * @param name \n */\n static unset<N extends HookName, P extends HookPositions<N>> (name?: N | (string & {}), pos?: P) {\n if (name && this.hooks.has(name)) {\n if (pos !== undefined) {\n const hook = this.get(name)\n if (hook?.[pos]) delete hook[pos]\n\n return Object.keys(hook ?? {}).length < 1\n ? void this.hooks.delete(name)\n : undefined\n }\n\n this.hooks.delete(name)\n } else this.clear()\n }\n\n /**\n * Clear all the defined hooks\n */\n static clear = () => {\n this.hooks.clear()\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["Hook","Hook"],"sources":["../src/lifecycle.ts","../src/network.ts","../src/prototypes.ts","../src/ErrorHandler.ts","../src/Logger.ts","../src/Hook.ts"],"sourcesContent":["import { Hook } from '@arkstack/foundry'\n\nexport const bindGracefulShutdown = (shutdown: () => Promise<void> | void, defer?: boolean) => {\n if (defer) return\n\n ['SIGINT', 'SIGTERM', 'SIGQUIT'].forEach((signal) => {\n process.on(signal, async () => {\n if (Hook.has('shutdown', 'before')) Hook.get('shutdown', 'after', {})\n await shutdown()\n })\n })\n}\n","import { abort, abortIf, assertFound, initializeGlobalContext } from './utils'\nimport { config, env } from './system'\n\nimport { Arkstack } from '@arkstack/contract'\nimport { Hook } from '@arkstack/foundry'\nimport { bindGracefulShutdown } from './lifecycle'\nimport { detect } from 'detect-port'\nimport { str } from '@h3ravel/support'\n\n/**\n * Boots the app using an available port close to the requested port \n *when requested port is not available\n * \n * @param boot \n * @param preferredPort \n * @param app \n * @param defer \n */\nexport const bootWithDetectedPort = async <TApp, TRoutes = unknown, THandler = unknown> (\n boot: (port: number) => Promise<void>,\n preferredPort: number = 3000,\n app?: Arkstack<TApp, TRoutes, THandler>,\n defer?: boolean\n) => {\n const port = await detect(preferredPort)\n\n if (Hook.has('boot', 'before')) Hook.get('boot', 'before', port, app)\n\n if (app && !globalThis.app) globalThis.app = () => app as never\n globalThis.env = env\n globalThis.config = config\n globalThis.str = str\n globalThis.abort = abort\n globalThis.abortIf = abortIf\n globalThis.assertFound = assertFound\n globalThis.arkctx = {\n runtime: 'HTTP',\n }\n await boot(port)\n await initializeGlobalContext()\n\n // Handle graceful shutdown\n bindGracefulShutdown(async () => await app?.shutdown(), defer)\n\n if (Hook.has('boot', 'after')) Hook.get('boot', 'after', port, app)\n}\n\nexport const renderError = ({\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 globalThis.view('~arkstack/common.error', {\n code,\n title,\n stack,\n message,\n }).renderSync()\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'\nimport { Arkstack } from '@arkstack/contract'\nimport { ModelNotFoundException } from 'arkormx'\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(Arkstack.rootDir(), '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 if ((error as any).cause && (error as any).cause instanceof ModelNotFoundException) {\n (error as any).getModelName = (error as any).cause.getModelName\n\n return true\n }\n\n return typeof candidate?.getModelName === 'function' ||\n error instanceof ModelNotFoundException\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\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 { HookArgs, HookFor, HookName, HookPos, HookPositions, HookRegistry, IHook } from './types'\n\nexport class Hook {\n private static hooks = new Map<string, IHook>()\n\n /**\n * Hooks define code that should run within defined boundaries to add extra functionalities.\n * \n * @param name \n * @param value \n */\n static set<N extends HookName> (\n name: N | (string & {}),\n hook: HookFor<N>\n ) {\n const oldhook = this.hooks.get(name) ?? {}\n\n this.hooks.set(name, {\n ...oldhook,\n ...hook,\n })\n }\n\n /**\n * Check if a hook is defined by name\n * \n * @param name \n */\n static has<N extends HookName, P extends HookPositions<N>> (name: N | (string & {}), pos?: P) {\n if (pos && this.hooks.has(name))\n return Boolean(this.get(name, pos))\n\n return this.hooks.has(name)\n }\n\n /**\n * Retrieve a defined hook by name\n * \n * @param name \n */\n static get<N extends HookName> (name: N): HookFor<N> | undefined\n /**\n * Retrieve a defined hook by name and position\n * \n * @param name \n * @param pos \n */\n static get<N extends HookName, P extends HookPositions<N>> (name: N, pos: P): HookPos<N, P> | undefined\n /**\n * Retrieve a defined hook by name and position the set args for callback\n * \n * @param name \n * @param pos \n */\n static get<N extends HookName, P extends HookPositions<N>> (name: N, pos: P, ...args: HookArgs<N, P>): void\n static get<N extends HookName, P extends HookPositions<N>> (\n name: N,\n pos?: P,\n ...args: HookArgs<N, P> | any[]\n ): HookFor<N> | HookPos<N, P> | undefined {\n const hook = this.hooks.get(name)\n\n if (!hook) return undefined\n if (pos === undefined) return hook as HookFor<N>\n\n const fn = hook[pos]\n if (!fn) return undefined\n\n if (args.length > 0) return fn(...args) as HookPos<N, P>\n\n return fn as HookPos<N, P>\n }\n\n /**\n * Retrieve all defined hooks\n * \n * @param name \n */\n static getAll = () => {\n const hooks: Record<string, IHook> & HookRegistry = {}\n\n for (const [name, value] of this.hooks)\n hooks[name] = value\n\n return hooks\n }\n\n /**\n * Remove the defined hook\n * \n * @param name \n */\n static unset<N extends HookName, P extends HookPositions<N>> (name?: N | (string & {}), pos?: P) {\n if (name && this.hooks.has(name)) {\n if (pos !== undefined) {\n const hook = this.get(name)\n if (hook?.[pos]) delete hook[pos]\n\n return Object.keys(hook ?? {}).length < 1\n ? void this.hooks.delete(name)\n : undefined\n }\n\n this.hooks.delete(name)\n } else this.clear()\n }\n\n /**\n * Clear all the defined hooks\n */\n static clear = () => {\n this.hooks.clear()\n }\n}\n"],"mappings":"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"}
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as
|
|
1
|
+
import { a as abortIf, c as initializeGlobalContext, d as Encryption, i as abort, l as perPage, n as ModelConstructor, o as assertFound, r as ModelRegistry, s as getModel, t as AbstractModelConstructor, u as Hash } from "../helpers-D3QVIFSV.js";
|
|
2
2
|
import { Model } from "arkormx";
|
|
3
3
|
|
|
4
4
|
//#region src/utils/traits.d.ts
|
|
@@ -59,5 +59,5 @@ type DerivedType<T extends Trait> = InstanceType<ExtractFactory<T>>;
|
|
|
59
59
|
type Derived<T extends (Trait | TypeFactory<Trait> | Cons)> = T extends TypeFactory<Trait> ? DerivedType<ReturnType<T>> : T extends Trait ? DerivedType<T> : T extends Cons ? T : never;
|
|
60
60
|
declare function uses<T extends (Trait | TypeFactory<Trait> | Cons)>(instance: unknown, trait: T): instance is Derived<T>;
|
|
61
61
|
//#endregion
|
|
62
|
-
export { AbstractModelConstructor, Derived, Encryption, Hash, ModelConstructor, ModelRegistry, Trait, crc32, getModel, initializeGlobalContext, perPage, trait, use, uses };
|
|
62
|
+
export { AbstractModelConstructor, Derived, Encryption, Hash, ModelConstructor, ModelRegistry, Trait, abort, abortIf, assertFound, crc32, getModel, initializeGlobalContext, perPage, trait, use, uses };
|
|
63
63
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/utils/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
export { Encryption, Hash, crc32, getModel, initializeGlobalContext, perPage, trait, use, uses };
|
|
1
|
+
import { a as abort, c as getModel, h as Encryption, i as uses, l as initializeGlobalContext, m as Hash, n as trait, o as abortIf, r as use, s as assertFound, t as crc32, u as perPage } from "../utils-C6d-ohT-.js";
|
|
2
|
+
export { Encryption, Hash, abort, abortIf, assertFound, crc32, getModel, initializeGlobalContext, perPage, trait, use, uses };
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createCipheriv, createDecipheriv, createHash, randomBytes } from "node:crypto";
|
|
1
2
|
import { createJiti } from "jiti";
|
|
2
3
|
import { Arkstack } from "@arkstack/contract";
|
|
3
4
|
import { Obj } from "@h3ravel/support";
|
|
@@ -5,7 +6,6 @@ import { createRequire } from "module";
|
|
|
5
6
|
import path, { resolve } from "node:path";
|
|
6
7
|
import { pathToFileURL } from "node:url";
|
|
7
8
|
import { readdirSync } from "fs";
|
|
8
|
-
import { createCipheriv, createDecipheriv, createHash, randomBytes } from "node:crypto";
|
|
9
9
|
import { Secret, TOTP } from "otpauth";
|
|
10
10
|
import { compare, genSalt, hash } from "bcryptjs";
|
|
11
11
|
import { getUserConfig } from "arkormx";
|
|
@@ -219,6 +219,68 @@ var Hash = class {
|
|
|
219
219
|
}
|
|
220
220
|
};
|
|
221
221
|
//#endregion
|
|
222
|
+
//#region src/Exceptions/Exception.ts
|
|
223
|
+
var Exception = class extends Error {
|
|
224
|
+
name;
|
|
225
|
+
constructor(message, options) {
|
|
226
|
+
super(message, options);
|
|
227
|
+
this.name = "Exception";
|
|
228
|
+
}
|
|
229
|
+
};
|
|
230
|
+
//#endregion
|
|
231
|
+
//#region src/Exceptions/AppException.ts
|
|
232
|
+
var AppException = class extends Exception {
|
|
233
|
+
errors = void 0;
|
|
234
|
+
statusCode;
|
|
235
|
+
constructor(message, statusCode = 400, options) {
|
|
236
|
+
super(message, options);
|
|
237
|
+
this.statusCode = statusCode;
|
|
238
|
+
}
|
|
239
|
+
};
|
|
240
|
+
//#endregion
|
|
241
|
+
//#region src/Exceptions/RequestException.ts
|
|
242
|
+
var RequestException = class RequestException extends AppException {
|
|
243
|
+
statusCode;
|
|
244
|
+
constructor(message, statusCode = 400, options) {
|
|
245
|
+
super(message, statusCode, options);
|
|
246
|
+
this.statusCode = statusCode;
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Asserts that a value is not null or undefined.
|
|
250
|
+
*
|
|
251
|
+
* @param value
|
|
252
|
+
* @param message
|
|
253
|
+
* @param code
|
|
254
|
+
* @throws {RequestException} Throws if the value is null or undefined.
|
|
255
|
+
*/
|
|
256
|
+
static assertFound(value, message, code = 404) {
|
|
257
|
+
if (!value) throw new RequestException(message, code);
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Asserts that a value is not null or undefined.
|
|
261
|
+
*
|
|
262
|
+
* @param value
|
|
263
|
+
* @param message
|
|
264
|
+
* @param code
|
|
265
|
+
* @throws {RequestException} Throws if the value is null or undefined.
|
|
266
|
+
* @deprecated Use assertFound instead
|
|
267
|
+
*/
|
|
268
|
+
static assertNotEmpty(value, message, code = 404) {
|
|
269
|
+
return this.assertFound(value, message, code);
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Asserts that a boolean condition is true.
|
|
273
|
+
*
|
|
274
|
+
* @param boolean
|
|
275
|
+
* @param message
|
|
276
|
+
* @param code
|
|
277
|
+
* @throws {RequestException} Throws if the boolean condition is true.
|
|
278
|
+
*/
|
|
279
|
+
static abortIf(boolean, message, code) {
|
|
280
|
+
if (boolean) throw new RequestException(message, code);
|
|
281
|
+
}
|
|
282
|
+
};
|
|
283
|
+
//#endregion
|
|
222
284
|
//#region src/utils/helpers.ts
|
|
223
285
|
/**
|
|
224
286
|
* Determine the number of items to return per page based on the provided query parameters.
|
|
@@ -256,6 +318,38 @@ const initializeGlobalContext = async ({ Request, Response, Session } = {}) => {
|
|
|
256
318
|
globalThis.request ??= () => Request;
|
|
257
319
|
globalThis.response ??= () => Response;
|
|
258
320
|
};
|
|
321
|
+
/**
|
|
322
|
+
* Thows to abort the current request
|
|
323
|
+
*
|
|
324
|
+
* @param message
|
|
325
|
+
* @param code
|
|
326
|
+
* @throws {RequestException}
|
|
327
|
+
*/
|
|
328
|
+
const abort = (message = "Request Aborted", code = 404) => {
|
|
329
|
+
RequestException.abortIf(true, message, code);
|
|
330
|
+
};
|
|
331
|
+
/**
|
|
332
|
+
* Asserts that a boolean condition is true.
|
|
333
|
+
*
|
|
334
|
+
* @param boolean
|
|
335
|
+
* @param message
|
|
336
|
+
* @param code
|
|
337
|
+
* @throws {RequestException} Throws if the boolean condition is true.
|
|
338
|
+
*/
|
|
339
|
+
const abortIf = (boolean, message = "Request Aborted", code = 404) => {
|
|
340
|
+
RequestException.abortIf(boolean, message, code);
|
|
341
|
+
};
|
|
342
|
+
/**
|
|
343
|
+
* Asserts that a value is not null or undefined.
|
|
344
|
+
*
|
|
345
|
+
* @param value
|
|
346
|
+
* @param message
|
|
347
|
+
* @param code
|
|
348
|
+
* @throws {RequestException} Throws if the value is null or undefined.
|
|
349
|
+
*/
|
|
350
|
+
const assertFound = (value, message, code = 404) => {
|
|
351
|
+
if (!value) throw new RequestException(message, code);
|
|
352
|
+
};
|
|
259
353
|
//#endregion
|
|
260
354
|
//#region src/utils/traits.ts
|
|
261
355
|
/**
|
|
@@ -385,6 +479,6 @@ function uses(instance, trait) {
|
|
|
385
479
|
return false;
|
|
386
480
|
}
|
|
387
481
|
//#endregion
|
|
388
|
-
export {
|
|
482
|
+
export { outputDir as S, config as _, abort as a, interopDefault as b, getModel as c, RequestException as d, AppException as f, appUrl as g, Encryption as h, uses as i, initializeGlobalContext as l, Hash as m, trait as n, abortIf as o, Exception as p, use as r, assertFound as s, crc32 as t, perPage as u, env as v, nodeEnv as x, importFile as y };
|
|
389
483
|
|
|
390
|
-
//# sourceMappingURL=utils-
|
|
484
|
+
//# sourceMappingURL=utils-C6d-ohT-.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils-C6d-ohT-.js","names":[],"sources":["../src/system.ts","../src/utils/encryption.ts","../src/utils/hash.ts","../src/Exceptions/Exception.ts","../src/Exceptions/AppException.ts","../src/Exceptions/RequestException.ts","../src/utils/helpers.ts","../src/utils/traits.ts"],"sourcesContent":["import { ConfigRegistry, DotPath, FileImporter, GlobalConfig, GlobalEnv } from './types'\nimport { JitiOptions, JitiResolveOptions, createJiti } from 'jiti'\n\nimport { Arkstack } from '@arkstack/contract'\nimport { Dirent } from 'node:fs'\nimport { Obj } from '@h3ravel/support'\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 =\n 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 (\n !isNaN(Number(val)) &&\n typeof val !== 'boolean' &&\n typeof val !== 'undefined' &&\n val !== ''\n ) {\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 = <\n X extends ConfigRegistry,\n P extends DotPath<X> | undefined = undefined,\n> (\n key?: P,\n defaultValue?: any,\n) => {\n if (typeof globalThis.env === 'undefined') {\n globalThis.env = (key?: string, def?: any): any => key\n ? process.env[key] ?? def\n : process.env\n }\n\n let files: Dirent<string>[]\n const dist = path.relative(Arkstack.rootDir(), outputDir())\n const require = createRequire(import.meta.url)\n\n try {\n files = readdirSync(path.join(Arkstack.rootDir(), `${dist}/config`), {\n withFileTypes: true,\n }).filter((file) => {\n if (file.name.includes('middleware') && globalThis.arkctx?.runtime === 'CLI')\n return false\n\n return (\n file.isFile() && (file.name.endsWith('.js') || file.name.endsWith('.ts'))\n )\n })\n } catch {\n files = [] as Dirent<string>[]\n }\n\n const config = files.reduce(\n (configs, file) => {\n const configName = path.basename(file.name, path.extname(file.name))\n\n configs[configName] = require(\n path.join(file.parentPath, file.name),\n ).default(typeof globalThis.app === 'function' ? globalThis.app() : {})\n\n return configs\n },\n {} as Record<string, any>,\n ) as X\n\n if (key) {\n return Obj.get(config, key as never, 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 Arkstack.rootDir()).\n * @returns\n */\nexport const outputDir = (cwd?: string) => {\n cwd ??= Arkstack.rootDir()\n\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 * \n * Dynamically imports a file at the given path with full TypeScript support,\n * including `tsconfig.json` path aliases. \n *\n * @param filePath - The path to the file to import. \n * @returns The imported module typed as `T`.\n *\n * @example\n * const config = await importFile<AppConfig>('./config/app.ts')\n */\nexport const importFile: FileImporter = async <T = unknown> (\n filePath: string,\n userOptions?: JitiOptions | undefined,\n resolveOptions?: (JitiResolveOptions & { default?: true })\n): Promise<T> => {\n const resolvedPath = resolve(filePath)\n const jiti = createJiti(pathToFileURL(resolvedPath).href, {\n ...userOptions,\n interopDefault: false,\n tsconfigPaths: true,\n })\n\n return await jiti.import<T>(resolvedPath, resolveOptions)\n}\n\n/**\n * Resolves the default export from a module, handling both CJS and ESM interop.\n * In CJS modules, the default export is often the module itself (a function or object),\n * while in ESM the default is nested under the `default` property.\n *\n * @param imp - The imported module\n * @returns The resolved default export\n */\nexport const interopDefault = <T> (imp: T | { default: T }): T => {\n return typeof imp === 'function'\n ? imp as T\n : (imp as { default: T }).default\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}","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 assertFound<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 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 * @deprecated Use assertFound instead\n */\n static assertNotEmpty<T> (\n value: T | null | undefined,\n message: string,\n code: number = 404,\n ): asserts value is T {\n return this.assertFound(value, message, code)\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 { getUserConfig, type Model, type ModelStatic } from 'arkormx'\nimport { importFile } from '../system'\nimport path from 'node:path'\nimport { Arkstack } from '@arkstack/contract'\nimport { RequestException } from '../Exceptions/RequestException'\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\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(Arkstack.rootDir(), 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\nexport const initializeGlobalContext = async (\n { Request, Response, Session }: { Request?: any, Response?: any, Session?: any } = {}\n) => {\n try {\n const { Request: Req, Response: Res, Session: Ses } = await import('@arkstack/http')\n Session ??= new Ses()\n Request ??= new Req()\n Response ??= new Res()\n } catch {\n Session ??= new class { }\n Request ??= new class { }\n Response ??= new class { }\n }\n\n globalThis.session ??= () => Session\n globalThis.request ??= () => Request\n globalThis.response ??= () => Response\n}\n\n/**\n * Thows to abort the current request\n * \n * @param message \n * @param code \n * @throws {RequestException}\n */\nexport const abort = (\n message: string = 'Request Aborted',\n code: number = 404,\n): void => {\n RequestException.abortIf(true, message, code)\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 */\nexport const abortIf = <T> (\n boolean: T,\n message: string = 'Request Aborted',\n code: number = 404,\n): asserts boolean is T => {\n RequestException.abortIf(boolean, message, code)\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 */\nexport const assertFound = <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** Extracted from @traits-ts/core - Traits for TypeScript Classes\n** Copyright (c) 2025 Dr. Ralf S. Engelschall <rse@engelschall.com>\n** Licensed under MIT license <https://spdx.org/licenses/MIT>\n*/\n\nimport type { Model as ArkormModel } from 'arkormx'\n\n/**\n * CRC32 implementation in TypeScript, adapted from https://stackoverflow.com/a/18639999\n * Note: This implementation is not cryptographically secure and is only used for generating \n * unique identifiers for traits based on their factory function's string representation. \n */\nconst crcTable = [] as number[]\nfor (let n = 0; n < 256; n++) {\n let c = n\n for (let k = 0; k < 8; k++)\n c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1))\n crcTable[n] = c\n}\nexport const crc32 = (str: string) => {\n let crc = 0 ^ (-1)\n for (let i = 0; i < str.length; i++)\n crc = (crc >>> 8) ^ crcTable[(crc ^ str.charCodeAt(i)) & 0xFF]\n\n return (crc ^ (-1)) >>> 0\n}\n\ntype ResolveTraitLike<T extends Trait | TypeFactory<Trait>> =\n T extends TypeFactory<Trait>\n ? ExtractFactory<ReturnType<T>>\n : T extends Trait\n ? ExtractFactory<T>\n : unknown;\n\ntype Combine<T extends any[]> =\n T extends [infer Head, ...infer Tail]\n ? Head & Combine<Tail>\n : object;\n\ntype MapClassesToPrototypes<T extends Array<(new () => any) & { prototype: any }>> = {\n [K in keyof T]: T[K]['prototype'];\n}\n\ntype MapClassesToInstances<T extends Array<(new () => any) & { prototype: any }>> = {\n [K in keyof T]: InstanceType<T[K]>;\n}\n\ntype CombineClasses<T extends Array<(new () => any) & { prototype: any }>> =\n (new () => Combine<MapClassesToInstances<T>>) & { prototype: Combine<MapClassesToPrototypes<T>> };\n\ntype ResolveTraitLikeArray<T extends Array<Trait | TypeFactory<Trait>>> = CombineClasses<{\n [K in keyof T]: ResolveTraitLike<T[K]>;\n}>;\n\n/**\n * utility type and function: constructor (function)\n */\ntype Cons<T = any> =\n new (...args: any[]) => T\nconst isCons =\n <T = any>\n (fn: unknown): fn is Cons<T> =>\n typeof fn === 'function' && !!fn.prototype && !!fn.prototype.constructor\n\ntype ArkormModelCons<T extends ArkormModel = ArkormModel> =\n abstract new (...args: any[]) => T\n\ntype DirectCons<T = any> =\n Cons<T> | ArkormModelCons<ArkormModel>\n\ntype DirectBase =\n DirectCons | ArkormModel\n\nconst isArkormModelInstance =\n (value: unknown): value is ArkormModel =>\n typeof value === 'object' &&\n value !== null &&\n typeof (value as { constructor?: unknown }).constructor === 'function' &&\n typeof (value as { getAttribute?: unknown }).getAttribute === 'function' &&\n typeof (value as { setAttribute?: unknown }).setAttribute === 'function'\n\n/**\n * utility type and function: constructor factory (function)\n */\ntype ConsFactory<T extends Cons = Cons, B = any> =\n (base: B) => T\n\n/**\n * utility type and function: type factory (function)\n */\ntype TypeFactory<T = any> =\n () => T\nconst isTypeFactory =\n <T = any>\n (fn: unknown): fn is TypeFactory<T> =>\n typeof fn === 'function' && !fn.prototype && fn.length === 0\n\n/**\n * utility type: map an object type into a bare properties type\n */\ntype Explode<T = any> =\n { [P in keyof T]: T[P] }\n\n/**\n * utility type: convert two arrays of types into an array of union types\n */\ntype MixParams<T1 extends any[], T2 extends any[]> =\n T1 extends [] ? (\n T2 extends [] ? [] : T2\n ) : (\n T2 extends [] ? T1 : (\n T1 extends [infer H1, ...infer R1] ? (\n T2 extends [infer H2, ...infer R2] ?\n [H1 & H2, ...MixParams<R1, R2>]\n : []\n ) : []\n )\n )\n\n/**\n * API: trait type\n */\ntype TraitDefTypeT = ConsFactory<Cons>\ntype TraitDefTypeST = (Trait | TypeFactory<Trait>)[] | undefined\nexport type Trait<\n T extends TraitDefTypeT = TraitDefTypeT,\n ST extends TraitDefTypeST = TraitDefTypeST\n> = {\n id: number /* unique id (primary, for hasTrait) */\n symbol: symbol /* unique id (secondary, currently unused) */\n factory: T\n superTraits: ST\n}\n\n/**\n * API: generate trait (regular variant)\n * \n * @param factory \n */\nexport function trait<\n T extends ConsFactory<Cons>\n> (factory: T): Trait<T, undefined>\n\n/**\n * API: generate trait (super-trait variant)\n * \n * @param superTraits \n * @param factory \n */\nexport function trait<\n const ST extends (Trait | TypeFactory<Trait>)[],\n T extends ConsFactory<Cons, ResolveTraitLikeArray<ST>>\n> (superTraits: ST, factory: T): Trait<T, ST>\n\n/**\n * API: generate trait (technical implementation)\n * \n * @param args \n */\nexport function trait (...args: any[]): Trait<any, any> {\n const factory: ConsFactory<any, any> = (args.length === 2 ? args[1] : args[0])\n const superTraits: (Trait | TypeFactory<Trait>)[] = (args.length === 2 ? args[0] : undefined)\n\n return {\n id: crc32(factory.toString()),\n symbol: Symbol('trait'),\n factory,\n superTraits\n }\n}\n\n/**\n * utility types: extract factory from a trait\n */\ntype ExtractFactory<\n T extends Trait\n> =\n T extends Trait<\n ConsFactory<infer C>,\n TraitDefTypeST\n > ? C : never\n\n/**\n * utility types: extract supertraits from a trait\n */\ntype ExtractSuperTrait<\n T extends Trait\n> =\n T extends Trait<\n TraitDefTypeT,\n infer ST extends TraitDefTypeST\n > ? ST : never\n\n/**\n * utility type: derive type constructor: merge two constructors\n */\ntype DeriveTraitsConsConsMerge<\n A extends Cons,\n B extends Cons\n> =\n A extends (new (...args: infer ArgsA) => infer RetA) ? (\n B extends (new (...args: infer ArgsB) => infer RetB) ? (\n new (...args: MixParams<ArgsA, ArgsB>) => RetA & RetB\n ) : never\n ) : never\n\n/**\n * utility type: derive type constructor: extract plain constructor\n */\ntype DeriveTraitsConsCons<\n T extends DirectCons\n> =\n new (...args: ConstructorParameters<T>) => InstanceType<T>\n\ntype DeriveTraitsConsDirectBase<\n T extends DirectBase\n> =\n T extends ArkormModel ? new (...args: any[]) => T :\n T extends DirectCons ? DeriveTraitsConsCons<T> :\n never\n\n/**\n * utility type: derive type constructor: from trait parts\n */\ntype DeriveTraitsConsTraitParts<\n C extends Cons,\n ST extends ((Trait | TypeFactory<Trait>)[] | undefined)\n> =\n ST extends undefined ? DeriveTraitsConsCons<C> :\n ST extends [] ? DeriveTraitsConsCons<C> :\n DeriveTraitsConsConsMerge<\n DeriveTraitsConsCons<C>,\n DeriveTraitsConsAll<ST>> /* RECURSION */\n\n/**\n * utility type: derive type constructor: from single trait\n */\ntype DeriveTraitsConsTrait<\n T extends Trait\n> =\n DeriveTraitsConsTraitParts<\n ExtractFactory<T>,\n ExtractSuperTrait<T>>\n\n/**\n * utility type: derive type constructor: from single trait or trait factory\n */\ntype DeriveTraitsConsOne<\n T extends (Trait | TypeFactory<Trait>)\n> =\n T extends Trait ? DeriveTraitsConsTrait<T> :\n T extends TypeFactory<Trait> ? DeriveTraitsConsTrait<ReturnType<T>> :\n never\n\n/**\n * utility type: derive type constructor: from one or more traits or trait factories\n */\ntype DeriveTraitsConsAll<\n T extends (((Trait | TypeFactory<Trait>)[] | [...(Trait | TypeFactory<Trait>)[], DirectBase]) | undefined)\n> =\n T extends [infer Only extends DirectBase] ? DeriveTraitsConsDirectBase<Only> :\n T extends [...infer Others extends (Trait | TypeFactory<Trait>)[], infer Last extends DirectBase] ? (\n Others extends [] ? DeriveTraitsConsDirectBase<Last> :\n DeriveTraitsConsConsMerge<\n DeriveTraitsConsAll<Others>, /* RECURSION */\n DeriveTraitsConsDirectBase<Last>>\n ) :\n T extends (Trait | TypeFactory<Trait>)[] ? (\n T extends [infer First extends (Trait | TypeFactory<Trait>)] ? (\n DeriveTraitsConsOne<First>\n ) : (\n T extends [\n infer First extends (Trait | TypeFactory<Trait>),\n ...infer Rest extends (Trait | TypeFactory<Trait>)[]] ? (\n DeriveTraitsConsConsMerge<\n DeriveTraitsConsOne<First>,\n DeriveTraitsConsAll<Rest>> /* RECURSION */\n ) : never\n )\n ) : never\n\n/**\n * utility type: derive type constructor\n */\ntype DeriveTraitsCons<\n T extends ((Trait | TypeFactory<Trait>)[] | [...(Trait | TypeFactory<Trait>)[], DirectBase])\n> =\n DeriveTraitsConsAll<T>\n\n/**\n * utility type: derive type statics: merge two objects with statics\n */\ntype DeriveTraitsStatsConsMerge<\n T1 extends object,\n T2 extends object\n> =\n T1 & T2\n\n/**\n * utility type: derive type statics: extract plain statics\n */\ntype DeriveTraitsStatsCons<\n T extends DirectCons\n> =\n Explode<T>\n\ntype DeriveTraitsStatsDirectBase<\n T extends DirectBase\n> =\n T extends ArkormModel ? object :\n T extends DirectCons ? DeriveTraitsStatsCons<T> :\n never\n\n/**\n * utility type: derive type statics: from trait parts\n */\ntype DeriveTraitsStatsTraitParts<\n C extends Cons,\n ST extends ((Trait | TypeFactory<Trait>)[] | undefined)\n> =\n ST extends undefined ? DeriveTraitsStatsCons<C> :\n ST extends [] ? DeriveTraitsStatsCons<C> :\n DeriveTraitsStatsConsMerge<\n DeriveTraitsStatsCons<C>,\n DeriveTraitsStatsAll<ST>> /* RECURSION */\n\n/**\n * utility type: derive type statics: from single trait\n */\ntype DeriveTraitsStatsTrait<\n T extends Trait\n> =\n DeriveTraitsStatsTraitParts<\n ExtractFactory<T>,\n ExtractSuperTrait<T>>\n\n/**\n * utility type: derive type statics: from single trait or trait factory\n */\ntype DeriveTraitsStatsOne<\n T extends (Trait | TypeFactory<Trait>)\n> =\n T extends Trait ? DeriveTraitsStatsTrait<T> :\n T extends TypeFactory<Trait> ? DeriveTraitsStatsTrait<ReturnType<T>> :\n never\n\n/**\n * utility type: derive type statics: from one or more traits or trait factories\n */\ntype DeriveTraitsStatsAll<\n T extends (((Trait | TypeFactory<Trait>)[] | [...(Trait | TypeFactory<Trait>)[], DirectBase]) | undefined)\n> =\n T extends [infer Only extends DirectBase] ? DeriveTraitsStatsDirectBase<Only> :\n T extends [...infer Others extends (Trait | TypeFactory<Trait>)[], infer Last extends DirectBase] ? (\n Others extends [] ? DeriveTraitsStatsDirectBase<Last> :\n DeriveTraitsStatsConsMerge<\n DeriveTraitsStatsAll<Others>, /* RECURSION */\n DeriveTraitsStatsDirectBase<Last>>\n ) :\n T extends (Trait | TypeFactory<Trait>)[] ? (\n T extends [infer First extends (Trait | TypeFactory<Trait>)] ? (\n DeriveTraitsStatsOne<First>\n ) : (\n T extends [\n infer First extends (Trait | TypeFactory<Trait>),\n ...infer Rest extends (Trait | TypeFactory<Trait>)[]] ? (\n DeriveTraitsStatsConsMerge<\n DeriveTraitsStatsOne<First>,\n DeriveTraitsStatsAll<Rest>> /* RECURSION */\n ) : never\n )\n ) : never\n\n/**\n * utility type: derive type statics\n */\ntype DeriveTraitsStats<\n T extends ((Trait | TypeFactory<Trait>)[] | [...(Trait | TypeFactory<Trait>)[], DirectBase])\n> =\n DeriveTraitsStatsAll<T>\n\n/**\n * utility type: derive type from one or more traits or trait type factories\n */\ntype DeriveTraits<\n T extends ((Trait | TypeFactory<Trait>)[] | [...(Trait | TypeFactory<Trait>)[], DirectBase])\n> =\n DeriveTraitsCons<T> &\n DeriveTraitsStats<T>\n\n/**\n * utility function: add an additional invisible property to an object\n * \n * @param cons \n * @param field \n * @param value \n * @returns \n */\nconst extendProperties =\n (cons: Cons, field: string | symbol, value: any) =>\n Object.defineProperty(cons, field, { value, enumerable: false, writable: false })\n\n/**\n * utility function: get raw trait\n * \n * @param x \n * @returns \n */\nconst rawTrait = (x: (Trait | TypeFactory<Trait>)) =>\n isTypeFactory(x) ? x() : x\n\n/**\n * utility function: derive a trait\n * \n * @param trait$ \n * @param baseClz \n * @param derived \n * @returns \n */\nconst deriveTrait = (\n trait$: Trait | TypeFactory<Trait>,\n baseClz: Cons<any>,\n derived: Map<number, boolean>\n) => {\n /* get real trait */\n const trait = rawTrait(trait$)\n\n /* start with base class */\n let clz = baseClz\n\n /* in case we still have not derived this trait... */\n if (!derived.has(trait.id)) {\n derived.set(trait.id, true)\n\n /* iterate over all of its super traits */\n if (trait.superTraits !== undefined)\n for (const superTrait of reverseTraitList(trait.superTraits))\n clz = deriveTrait(superTrait, clz, derived) /* RECURSION */\n\n /* derive this trait */\n clz = trait.factory(clz)\n extendProperties(clz, 'id', crc32(trait.factory.toString()))\n extendProperties(clz, trait.symbol, true)\n }\n\n return clz\n}\n\n/**\n * utility function: get reversed trait list\n * \n * @param traits \n * @returns \n */\nconst reverseTraitList = (traits: (Trait | TypeFactory<Trait>)[]) =>\n traits.slice().reverse() as (Trait | TypeFactory<Trait>)[]\n\n/**\n * API: derive a class from one or more traits or trait type factories\n * \n * @param traits \n * @returns \n */\nexport function use\n <T extends (\n [Trait | TypeFactory<Trait>, ...(Trait | TypeFactory<Trait>)[]] |\n [...(Trait | TypeFactory<Trait>)[], DirectBase]\n )>\n (...traits: T): DeriveTraits<T> {\n /* run-time sanity check */\n if (traits.length === 0)\n throw new Error('invalid number of parameters (expected one or more traits)')\n\n /* determine the base class (clz) and the list of traits (lot) */\n let clz: Cons<any>\n let lot: (Trait | TypeFactory<Trait>)[]\n const last = traits[traits.length - 1]\n if (isCons(last) && !isTypeFactory(last)) {\n /* case 1: with trailing regular class */\n clz = last\n lot = traits.slice(0, -1) as (Trait | TypeFactory<Trait>)[]\n } else if (isArkormModelInstance(last)) {\n /* case 2: with trailing Arkorm model instance */\n clz = last.constructor as Cons<any>\n lot = traits.slice(0, -1) as (Trait | TypeFactory<Trait>)[]\n } else {\n /* case 3: just regular traits or trait type factories */\n clz = class ROOT { }\n lot = traits as (Trait | TypeFactory<Trait>)[]\n }\n\n /* track already derived traits */\n const derived = new Map<number, boolean>()\n\n /* iterate over all traits */\n for (const trait of reverseTraitList(lot))\n clz = deriveTrait(trait, clz, derived)\n\n return clz as DeriveTraits<T>\n}\n\n/**\n * internal type: implements trait type\n */\ntype DerivedType<T extends Trait> =\n InstanceType<ExtractFactory<T>>\n\n/**\n * internal type: implements trait type or trait type factory\n */\nexport type Derived<T extends (Trait | TypeFactory<Trait> | Cons)> =\n T extends TypeFactory<Trait> ? DerivedType<ReturnType<T>> :\n T extends Trait ? DerivedType<T> :\n T extends Cons ? T :\n never\n\n/**\n * API: type guard for checking whether class instance is derived from a trait\n * \n * @param instance \n * @param trait \n * @returns \n */\nexport function uses\n <T extends (Trait | TypeFactory<Trait> | Cons)>\n (instance: unknown, trait: T): instance is Derived<T> {\n /* ensure the class instance is really an object */\n if (typeof instance !== 'object' || instance === null)\n return false\n let obj = instance\n\n /* special case: regular class */\n if (isCons(trait) && !isTypeFactory(trait))\n return (instance instanceof trait)\n\n /* regular case: trait or trait type factory... */\n const t = (isTypeFactory(trait) ? trait() : trait) as Trait\n const idTrait = t['id']\n while (obj) {\n if (Object.hasOwn(obj, 'constructor')) {\n const id = ((obj.constructor as any)['id'] as number) ?? 0\n if (id === idTrait)\n return true\n }\n obj = Object.getPrototypeOf(obj)\n }\n\n return false\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
|
+
"version": "0.12.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Core utilities, primitives, and shared infrastructure for the Arkstack ecosystem.",
|
|
6
6
|
"homepage": "https://arkstack.toneflix.net",
|
|
@@ -42,8 +42,8 @@
|
|
|
42
42
|
"peerDependencies": {
|
|
43
43
|
"@h3ravel/support": "^0.15.11",
|
|
44
44
|
"arkormx": "^ 2.4.1",
|
|
45
|
-
"@arkstack/foundry": "^0.
|
|
46
|
-
"@arkstack/contract": "^0.
|
|
45
|
+
"@arkstack/foundry": "^0.12.0",
|
|
46
|
+
"@arkstack/contract": "^0.12.0"
|
|
47
47
|
},
|
|
48
48
|
"scripts": {
|
|
49
49
|
"build": "tsdown --config-loader unrun",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"utils-CpOKE57m.js","names":[],"sources":["../src/system.ts","../src/utils/encryption.ts","../src/utils/hash.ts","../src/utils/helpers.ts","../src/utils/traits.ts"],"sourcesContent":["import { ConfigRegistry, DotPath, FileImporter, GlobalConfig, GlobalEnv } from './types'\nimport { JitiOptions, JitiResolveOptions, createJiti } from 'jiti'\n\nimport { Arkstack } from '@arkstack/contract'\nimport { Dirent } from 'node:fs'\nimport { Obj } from '@h3ravel/support'\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 =\n 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 (\n !isNaN(Number(val)) &&\n typeof val !== 'boolean' &&\n typeof val !== 'undefined' &&\n val !== ''\n ) {\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 = <\n X extends ConfigRegistry,\n P extends DotPath<X> | undefined = undefined,\n> (\n key?: P,\n defaultValue?: any,\n) => {\n if (typeof globalThis.env === 'undefined') {\n globalThis.env = (key?: string, def?: any): any => key\n ? process.env[key] ?? def\n : process.env\n }\n\n let files: Dirent<string>[]\n const dist = path.relative(Arkstack.rootDir(), outputDir())\n const require = createRequire(import.meta.url)\n\n try {\n files = readdirSync(path.join(Arkstack.rootDir(), `${dist}/config`), {\n withFileTypes: true,\n }).filter((file) => {\n if (file.name.includes('middleware') && globalThis.arkctx?.runtime === 'CLI')\n return false\n\n return (\n file.isFile() && (file.name.endsWith('.js') || file.name.endsWith('.ts'))\n )\n })\n } catch {\n files = [] as Dirent<string>[]\n }\n\n const config = files.reduce(\n (configs, file) => {\n const configName = path.basename(file.name, path.extname(file.name))\n\n configs[configName] = require(\n path.join(file.parentPath, file.name),\n ).default(typeof globalThis.app === 'function' ? globalThis.app() : {})\n\n return configs\n },\n {} as Record<string, any>,\n ) as X\n\n if (key) {\n return Obj.get(config, key as never, 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 Arkstack.rootDir()).\n * @returns\n */\nexport const outputDir = (cwd?: string) => {\n cwd ??= Arkstack.rootDir()\n\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 * \n * Dynamically imports a file at the given path with full TypeScript support,\n * including `tsconfig.json` path aliases. \n *\n * @param filePath - The path to the file to import. \n * @returns The imported module typed as `T`.\n *\n * @example\n * const config = await importFile<AppConfig>('./config/app.ts')\n */\nexport const importFile: FileImporter = async <T = unknown> (\n filePath: string,\n userOptions?: JitiOptions | undefined,\n resolveOptions?: (JitiResolveOptions & { default?: true })\n): Promise<T> => {\n const resolvedPath = resolve(filePath)\n const jiti = createJiti(pathToFileURL(resolvedPath).href, {\n ...userOptions,\n interopDefault: false,\n tsconfigPaths: true,\n })\n\n return await jiti.import<T>(resolvedPath, resolveOptions)\n}\n\n/**\n * Resolves the default export from a module, handling both CJS and ESM interop.\n * In CJS modules, the default export is often the module itself (a function or object),\n * while in ESM the default is nested under the `default` property.\n *\n * @param imp - The imported module\n * @returns The resolved default export\n */\nexport const interopDefault = <T> (imp: T | { default: T }): T => {\n return typeof imp === 'function'\n ? imp as T\n : (imp as { default: T }).default\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'\nimport { Arkstack } from '@arkstack/contract'\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(Arkstack.rootDir(), 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\nexport const initializeGlobalContext = async (\n { Request, Response, Session }: { Request?: any, Response?: any, Session?: any } = {}\n) => {\n try {\n const { Request: Req, Response: Res, Session: Ses } = await import('@arkstack/http')\n Session ??= new Ses()\n Request ??= new Req()\n Response ??= new Res()\n } catch {\n Session ??= new class { }\n Request ??= new class { }\n Response ??= new class { }\n }\n\n globalThis.session ??= () => Session\n globalThis.request ??= () => Request\n globalThis.response ??= () => Response\n}","/*\n** Extracted from @traits-ts/core - Traits for TypeScript Classes\n** Copyright (c) 2025 Dr. Ralf S. Engelschall <rse@engelschall.com>\n** Licensed under MIT license <https://spdx.org/licenses/MIT>\n*/\n\nimport type { Model as ArkormModel } from 'arkormx'\n\n/**\n * CRC32 implementation in TypeScript, adapted from https://stackoverflow.com/a/18639999\n * Note: This implementation is not cryptographically secure and is only used for generating \n * unique identifiers for traits based on their factory function's string representation. \n */\nconst crcTable = [] as number[]\nfor (let n = 0; n < 256; n++) {\n let c = n\n for (let k = 0; k < 8; k++)\n c = ((c & 1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1))\n crcTable[n] = c\n}\nexport const crc32 = (str: string) => {\n let crc = 0 ^ (-1)\n for (let i = 0; i < str.length; i++)\n crc = (crc >>> 8) ^ crcTable[(crc ^ str.charCodeAt(i)) & 0xFF]\n\n return (crc ^ (-1)) >>> 0\n}\n\ntype ResolveTraitLike<T extends Trait | TypeFactory<Trait>> =\n T extends TypeFactory<Trait>\n ? ExtractFactory<ReturnType<T>>\n : T extends Trait\n ? ExtractFactory<T>\n : unknown;\n\ntype Combine<T extends any[]> =\n T extends [infer Head, ...infer Tail]\n ? Head & Combine<Tail>\n : object;\n\ntype MapClassesToPrototypes<T extends Array<(new () => any) & { prototype: any }>> = {\n [K in keyof T]: T[K]['prototype'];\n}\n\ntype MapClassesToInstances<T extends Array<(new () => any) & { prototype: any }>> = {\n [K in keyof T]: InstanceType<T[K]>;\n}\n\ntype CombineClasses<T extends Array<(new () => any) & { prototype: any }>> =\n (new () => Combine<MapClassesToInstances<T>>) & { prototype: Combine<MapClassesToPrototypes<T>> };\n\ntype ResolveTraitLikeArray<T extends Array<Trait | TypeFactory<Trait>>> = CombineClasses<{\n [K in keyof T]: ResolveTraitLike<T[K]>;\n}>;\n\n/**\n * utility type and function: constructor (function)\n */\ntype Cons<T = any> =\n new (...args: any[]) => T\nconst isCons =\n <T = any>\n (fn: unknown): fn is Cons<T> =>\n typeof fn === 'function' && !!fn.prototype && !!fn.prototype.constructor\n\ntype ArkormModelCons<T extends ArkormModel = ArkormModel> =\n abstract new (...args: any[]) => T\n\ntype DirectCons<T = any> =\n Cons<T> | ArkormModelCons<ArkormModel>\n\ntype DirectBase =\n DirectCons | ArkormModel\n\nconst isArkormModelInstance =\n (value: unknown): value is ArkormModel =>\n typeof value === 'object' &&\n value !== null &&\n typeof (value as { constructor?: unknown }).constructor === 'function' &&\n typeof (value as { getAttribute?: unknown }).getAttribute === 'function' &&\n typeof (value as { setAttribute?: unknown }).setAttribute === 'function'\n\n/**\n * utility type and function: constructor factory (function)\n */\ntype ConsFactory<T extends Cons = Cons, B = any> =\n (base: B) => T\n\n/**\n * utility type and function: type factory (function)\n */\ntype TypeFactory<T = any> =\n () => T\nconst isTypeFactory =\n <T = any>\n (fn: unknown): fn is TypeFactory<T> =>\n typeof fn === 'function' && !fn.prototype && fn.length === 0\n\n/**\n * utility type: map an object type into a bare properties type\n */\ntype Explode<T = any> =\n { [P in keyof T]: T[P] }\n\n/**\n * utility type: convert two arrays of types into an array of union types\n */\ntype MixParams<T1 extends any[], T2 extends any[]> =\n T1 extends [] ? (\n T2 extends [] ? [] : T2\n ) : (\n T2 extends [] ? T1 : (\n T1 extends [infer H1, ...infer R1] ? (\n T2 extends [infer H2, ...infer R2] ?\n [H1 & H2, ...MixParams<R1, R2>]\n : []\n ) : []\n )\n )\n\n/**\n * API: trait type\n */\ntype TraitDefTypeT = ConsFactory<Cons>\ntype TraitDefTypeST = (Trait | TypeFactory<Trait>)[] | undefined\nexport type Trait<\n T extends TraitDefTypeT = TraitDefTypeT,\n ST extends TraitDefTypeST = TraitDefTypeST\n> = {\n id: number /* unique id (primary, for hasTrait) */\n symbol: symbol /* unique id (secondary, currently unused) */\n factory: T\n superTraits: ST\n}\n\n/**\n * API: generate trait (regular variant)\n * \n * @param factory \n */\nexport function trait<\n T extends ConsFactory<Cons>\n> (factory: T): Trait<T, undefined>\n\n/**\n * API: generate trait (super-trait variant)\n * \n * @param superTraits \n * @param factory \n */\nexport function trait<\n const ST extends (Trait | TypeFactory<Trait>)[],\n T extends ConsFactory<Cons, ResolveTraitLikeArray<ST>>\n> (superTraits: ST, factory: T): Trait<T, ST>\n\n/**\n * API: generate trait (technical implementation)\n * \n * @param args \n */\nexport function trait (...args: any[]): Trait<any, any> {\n const factory: ConsFactory<any, any> = (args.length === 2 ? args[1] : args[0])\n const superTraits: (Trait | TypeFactory<Trait>)[] = (args.length === 2 ? args[0] : undefined)\n\n return {\n id: crc32(factory.toString()),\n symbol: Symbol('trait'),\n factory,\n superTraits\n }\n}\n\n/**\n * utility types: extract factory from a trait\n */\ntype ExtractFactory<\n T extends Trait\n> =\n T extends Trait<\n ConsFactory<infer C>,\n TraitDefTypeST\n > ? C : never\n\n/**\n * utility types: extract supertraits from a trait\n */\ntype ExtractSuperTrait<\n T extends Trait\n> =\n T extends Trait<\n TraitDefTypeT,\n infer ST extends TraitDefTypeST\n > ? ST : never\n\n/**\n * utility type: derive type constructor: merge two constructors\n */\ntype DeriveTraitsConsConsMerge<\n A extends Cons,\n B extends Cons\n> =\n A extends (new (...args: infer ArgsA) => infer RetA) ? (\n B extends (new (...args: infer ArgsB) => infer RetB) ? (\n new (...args: MixParams<ArgsA, ArgsB>) => RetA & RetB\n ) : never\n ) : never\n\n/**\n * utility type: derive type constructor: extract plain constructor\n */\ntype DeriveTraitsConsCons<\n T extends DirectCons\n> =\n new (...args: ConstructorParameters<T>) => InstanceType<T>\n\ntype DeriveTraitsConsDirectBase<\n T extends DirectBase\n> =\n T extends ArkormModel ? new (...args: any[]) => T :\n T extends DirectCons ? DeriveTraitsConsCons<T> :\n never\n\n/**\n * utility type: derive type constructor: from trait parts\n */\ntype DeriveTraitsConsTraitParts<\n C extends Cons,\n ST extends ((Trait | TypeFactory<Trait>)[] | undefined)\n> =\n ST extends undefined ? DeriveTraitsConsCons<C> :\n ST extends [] ? DeriveTraitsConsCons<C> :\n DeriveTraitsConsConsMerge<\n DeriveTraitsConsCons<C>,\n DeriveTraitsConsAll<ST>> /* RECURSION */\n\n/**\n * utility type: derive type constructor: from single trait\n */\ntype DeriveTraitsConsTrait<\n T extends Trait\n> =\n DeriveTraitsConsTraitParts<\n ExtractFactory<T>,\n ExtractSuperTrait<T>>\n\n/**\n * utility type: derive type constructor: from single trait or trait factory\n */\ntype DeriveTraitsConsOne<\n T extends (Trait | TypeFactory<Trait>)\n> =\n T extends Trait ? DeriveTraitsConsTrait<T> :\n T extends TypeFactory<Trait> ? DeriveTraitsConsTrait<ReturnType<T>> :\n never\n\n/**\n * utility type: derive type constructor: from one or more traits or trait factories\n */\ntype DeriveTraitsConsAll<\n T extends (((Trait | TypeFactory<Trait>)[] | [...(Trait | TypeFactory<Trait>)[], DirectBase]) | undefined)\n> =\n T extends [infer Only extends DirectBase] ? DeriveTraitsConsDirectBase<Only> :\n T extends [...infer Others extends (Trait | TypeFactory<Trait>)[], infer Last extends DirectBase] ? (\n Others extends [] ? DeriveTraitsConsDirectBase<Last> :\n DeriveTraitsConsConsMerge<\n DeriveTraitsConsAll<Others>, /* RECURSION */\n DeriveTraitsConsDirectBase<Last>>\n ) :\n T extends (Trait | TypeFactory<Trait>)[] ? (\n T extends [infer First extends (Trait | TypeFactory<Trait>)] ? (\n DeriveTraitsConsOne<First>\n ) : (\n T extends [\n infer First extends (Trait | TypeFactory<Trait>),\n ...infer Rest extends (Trait | TypeFactory<Trait>)[]] ? (\n DeriveTraitsConsConsMerge<\n DeriveTraitsConsOne<First>,\n DeriveTraitsConsAll<Rest>> /* RECURSION */\n ) : never\n )\n ) : never\n\n/**\n * utility type: derive type constructor\n */\ntype DeriveTraitsCons<\n T extends ((Trait | TypeFactory<Trait>)[] | [...(Trait | TypeFactory<Trait>)[], DirectBase])\n> =\n DeriveTraitsConsAll<T>\n\n/**\n * utility type: derive type statics: merge two objects with statics\n */\ntype DeriveTraitsStatsConsMerge<\n T1 extends object,\n T2 extends object\n> =\n T1 & T2\n\n/**\n * utility type: derive type statics: extract plain statics\n */\ntype DeriveTraitsStatsCons<\n T extends DirectCons\n> =\n Explode<T>\n\ntype DeriveTraitsStatsDirectBase<\n T extends DirectBase\n> =\n T extends ArkormModel ? object :\n T extends DirectCons ? DeriveTraitsStatsCons<T> :\n never\n\n/**\n * utility type: derive type statics: from trait parts\n */\ntype DeriveTraitsStatsTraitParts<\n C extends Cons,\n ST extends ((Trait | TypeFactory<Trait>)[] | undefined)\n> =\n ST extends undefined ? DeriveTraitsStatsCons<C> :\n ST extends [] ? DeriveTraitsStatsCons<C> :\n DeriveTraitsStatsConsMerge<\n DeriveTraitsStatsCons<C>,\n DeriveTraitsStatsAll<ST>> /* RECURSION */\n\n/**\n * utility type: derive type statics: from single trait\n */\ntype DeriveTraitsStatsTrait<\n T extends Trait\n> =\n DeriveTraitsStatsTraitParts<\n ExtractFactory<T>,\n ExtractSuperTrait<T>>\n\n/**\n * utility type: derive type statics: from single trait or trait factory\n */\ntype DeriveTraitsStatsOne<\n T extends (Trait | TypeFactory<Trait>)\n> =\n T extends Trait ? DeriveTraitsStatsTrait<T> :\n T extends TypeFactory<Trait> ? DeriveTraitsStatsTrait<ReturnType<T>> :\n never\n\n/**\n * utility type: derive type statics: from one or more traits or trait factories\n */\ntype DeriveTraitsStatsAll<\n T extends (((Trait | TypeFactory<Trait>)[] | [...(Trait | TypeFactory<Trait>)[], DirectBase]) | undefined)\n> =\n T extends [infer Only extends DirectBase] ? DeriveTraitsStatsDirectBase<Only> :\n T extends [...infer Others extends (Trait | TypeFactory<Trait>)[], infer Last extends DirectBase] ? (\n Others extends [] ? DeriveTraitsStatsDirectBase<Last> :\n DeriveTraitsStatsConsMerge<\n DeriveTraitsStatsAll<Others>, /* RECURSION */\n DeriveTraitsStatsDirectBase<Last>>\n ) :\n T extends (Trait | TypeFactory<Trait>)[] ? (\n T extends [infer First extends (Trait | TypeFactory<Trait>)] ? (\n DeriveTraitsStatsOne<First>\n ) : (\n T extends [\n infer First extends (Trait | TypeFactory<Trait>),\n ...infer Rest extends (Trait | TypeFactory<Trait>)[]] ? (\n DeriveTraitsStatsConsMerge<\n DeriveTraitsStatsOne<First>,\n DeriveTraitsStatsAll<Rest>> /* RECURSION */\n ) : never\n )\n ) : never\n\n/**\n * utility type: derive type statics\n */\ntype DeriveTraitsStats<\n T extends ((Trait | TypeFactory<Trait>)[] | [...(Trait | TypeFactory<Trait>)[], DirectBase])\n> =\n DeriveTraitsStatsAll<T>\n\n/**\n * utility type: derive type from one or more traits or trait type factories\n */\ntype DeriveTraits<\n T extends ((Trait | TypeFactory<Trait>)[] | [...(Trait | TypeFactory<Trait>)[], DirectBase])\n> =\n DeriveTraitsCons<T> &\n DeriveTraitsStats<T>\n\n/**\n * utility function: add an additional invisible property to an object\n * \n * @param cons \n * @param field \n * @param value \n * @returns \n */\nconst extendProperties =\n (cons: Cons, field: string | symbol, value: any) =>\n Object.defineProperty(cons, field, { value, enumerable: false, writable: false })\n\n/**\n * utility function: get raw trait\n * \n * @param x \n * @returns \n */\nconst rawTrait = (x: (Trait | TypeFactory<Trait>)) =>\n isTypeFactory(x) ? x() : x\n\n/**\n * utility function: derive a trait\n * \n * @param trait$ \n * @param baseClz \n * @param derived \n * @returns \n */\nconst deriveTrait = (\n trait$: Trait | TypeFactory<Trait>,\n baseClz: Cons<any>,\n derived: Map<number, boolean>\n) => {\n /* get real trait */\n const trait = rawTrait(trait$)\n\n /* start with base class */\n let clz = baseClz\n\n /* in case we still have not derived this trait... */\n if (!derived.has(trait.id)) {\n derived.set(trait.id, true)\n\n /* iterate over all of its super traits */\n if (trait.superTraits !== undefined)\n for (const superTrait of reverseTraitList(trait.superTraits))\n clz = deriveTrait(superTrait, clz, derived) /* RECURSION */\n\n /* derive this trait */\n clz = trait.factory(clz)\n extendProperties(clz, 'id', crc32(trait.factory.toString()))\n extendProperties(clz, trait.symbol, true)\n }\n\n return clz\n}\n\n/**\n * utility function: get reversed trait list\n * \n * @param traits \n * @returns \n */\nconst reverseTraitList = (traits: (Trait | TypeFactory<Trait>)[]) =>\n traits.slice().reverse() as (Trait | TypeFactory<Trait>)[]\n\n/**\n * API: derive a class from one or more traits or trait type factories\n * \n * @param traits \n * @returns \n */\nexport function use\n <T extends (\n [Trait | TypeFactory<Trait>, ...(Trait | TypeFactory<Trait>)[]] |\n [...(Trait | TypeFactory<Trait>)[], DirectBase]\n )>\n (...traits: T): DeriveTraits<T> {\n /* run-time sanity check */\n if (traits.length === 0)\n throw new Error('invalid number of parameters (expected one or more traits)')\n\n /* determine the base class (clz) and the list of traits (lot) */\n let clz: Cons<any>\n let lot: (Trait | TypeFactory<Trait>)[]\n const last = traits[traits.length - 1]\n if (isCons(last) && !isTypeFactory(last)) {\n /* case 1: with trailing regular class */\n clz = last\n lot = traits.slice(0, -1) as (Trait | TypeFactory<Trait>)[]\n } else if (isArkormModelInstance(last)) {\n /* case 2: with trailing Arkorm model instance */\n clz = last.constructor as Cons<any>\n lot = traits.slice(0, -1) as (Trait | TypeFactory<Trait>)[]\n } else {\n /* case 3: just regular traits or trait type factories */\n clz = class ROOT { }\n lot = traits as (Trait | TypeFactory<Trait>)[]\n }\n\n /* track already derived traits */\n const derived = new Map<number, boolean>()\n\n /* iterate over all traits */\n for (const trait of reverseTraitList(lot))\n clz = deriveTrait(trait, clz, derived)\n\n return clz as DeriveTraits<T>\n}\n\n/**\n * internal type: implements trait type\n */\ntype DerivedType<T extends Trait> =\n InstanceType<ExtractFactory<T>>\n\n/**\n * internal type: implements trait type or trait type factory\n */\nexport type Derived<T extends (Trait | TypeFactory<Trait> | Cons)> =\n T extends TypeFactory<Trait> ? DerivedType<ReturnType<T>> :\n T extends Trait ? DerivedType<T> :\n T extends Cons ? T :\n never\n\n/**\n * API: type guard for checking whether class instance is derived from a trait\n * \n * @param instance \n * @param trait \n * @returns \n */\nexport function uses\n <T extends (Trait | TypeFactory<Trait> | Cons)>\n (instance: unknown, trait: T): instance is Derived<T> {\n /* ensure the class instance is really an object */\n if (typeof instance !== 'object' || instance === null)\n return false\n let obj = instance\n\n /* special case: regular class */\n if (isCons(trait) && !isTypeFactory(trait))\n return (instance instanceof trait)\n\n /* regular case: trait or trait type factory... */\n const t = (isTypeFactory(trait) ? trait() : trait) as Trait\n const idTrait = t['id']\n while (obj) {\n if (Object.hasOwn(obj, 'constructor')) {\n const id = ((obj.constructor as any)['id'] as number) ?? 0\n if (id === idTrait)\n return true\n }\n obj = Object.getPrototypeOf(obj)\n }\n\n return false\n}\n"],"mappings":"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"}
|