@arkstack/common 0.14.18 → 0.14.19
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/index.d.ts +157 -4
- package/dist/index.js +3 -3
- package/dist/utils/index.js +1 -1
- package/dist/{utils-DJQAOLbx.js → utils-DEflBOXp.js} +169 -64
- package/package.json +4 -3
package/dist/index.d.ts
CHANGED
|
@@ -172,7 +172,75 @@ declare class Logger {
|
|
|
172
172
|
//#endregion
|
|
173
173
|
//#region src/types.d.ts
|
|
174
174
|
interface ConfigRegistry {}
|
|
175
|
-
|
|
175
|
+
/**
|
|
176
|
+
* Map of known environment variables to their (coerced) value types.
|
|
177
|
+
*
|
|
178
|
+
* Used to give {@link GlobalEnv | env()} precise return types. Unknown keys fall
|
|
179
|
+
* back to `string`. Augment this interface (declaration merging) to register
|
|
180
|
+
* application-specific variables:
|
|
181
|
+
*
|
|
182
|
+
* ```ts
|
|
183
|
+
* declare module '@arkstack/common' {
|
|
184
|
+
* interface EnvRegistry { MY_FLAG: boolean }
|
|
185
|
+
* }
|
|
186
|
+
* ```
|
|
187
|
+
*/
|
|
188
|
+
interface EnvRegistry {
|
|
189
|
+
APP_NAME: string;
|
|
190
|
+
APP_ENV: 'development' | 'production' | 'staging' | 'local';
|
|
191
|
+
APP_KEY: string;
|
|
192
|
+
APP_URL: string;
|
|
193
|
+
APP_HOST: string;
|
|
194
|
+
APP_PORT: number;
|
|
195
|
+
NODE_ENV: 'development' | 'production' | 'test';
|
|
196
|
+
PORT: number;
|
|
197
|
+
HOST: string;
|
|
198
|
+
FRONTEND_URL: string;
|
|
199
|
+
OUTPUT_DIR: string;
|
|
200
|
+
OUTPUT_DIR_DEV: string;
|
|
201
|
+
CONFIG_PATH: string;
|
|
202
|
+
TUNNEL: boolean;
|
|
203
|
+
FILESYSTEM_DISK: string;
|
|
204
|
+
CACHE_STORE: string;
|
|
205
|
+
CACHE_PREFIX: string;
|
|
206
|
+
CACHE_TABLE: string;
|
|
207
|
+
QUEUE_CONNECTION: string;
|
|
208
|
+
QUEUE_TABLE: string;
|
|
209
|
+
QUEUE_NAME: string;
|
|
210
|
+
QUEUE_RETRY_AFTER: number;
|
|
211
|
+
REDIS_HOST: string;
|
|
212
|
+
REDIS_PORT: number;
|
|
213
|
+
REDIS_PASSWORD: string;
|
|
214
|
+
REDIS_CACHE_DB: number;
|
|
215
|
+
REDIS_QUEUE_DB: number;
|
|
216
|
+
JWT_EXPIRES_IN: string;
|
|
217
|
+
SESSION_LIFETIME: number;
|
|
218
|
+
TWO_FACTOR_SMS_TTL_MINUTES: number;
|
|
219
|
+
DATABASE_URL: string;
|
|
220
|
+
DB_CONNECTION: string;
|
|
221
|
+
DB_HOST: string;
|
|
222
|
+
DB_PORT: number;
|
|
223
|
+
DB_DATABASE: string;
|
|
224
|
+
DB_USERNAME: string;
|
|
225
|
+
DB_PASSWORD: string;
|
|
226
|
+
MAIL_HOST: string;
|
|
227
|
+
MAIL_PORT: number;
|
|
228
|
+
MAIL_SECURE: boolean;
|
|
229
|
+
MAIL_USERNAME: string;
|
|
230
|
+
MAIL_PASSWORD: string;
|
|
231
|
+
MAIL_FROM_ADDRESS: string;
|
|
232
|
+
MAIL_TEST_ADDRESS: string;
|
|
233
|
+
AWS_ACCESS_KEY_ID: string;
|
|
234
|
+
AWS_SECRET_ACCESS_KEY: string;
|
|
235
|
+
AWS_DEFAULT_REGION: string;
|
|
236
|
+
AWS_BUCKET: string;
|
|
237
|
+
AWS_URL: string;
|
|
238
|
+
AWS_ENDPOINT: string;
|
|
239
|
+
}
|
|
240
|
+
/** Known environment variable names. */
|
|
241
|
+
type EnvKey = keyof EnvRegistry & string;
|
|
242
|
+
/** The registered type for a known key, or `string` for an unknown one. */
|
|
243
|
+
type EnvLookup<K extends string> = [K] extends [EnvKey] ? EnvRegistry[K] : string;
|
|
176
244
|
type UnionToIntersection<U> = (U extends any ? (x: U) => void : never) extends ((x: infer I) => void) ? I : never;
|
|
177
245
|
type MergedConfig<X> = UnionToIntersection<X>;
|
|
178
246
|
type Primitive = string | number | boolean | null | undefined | Function;
|
|
@@ -196,8 +264,17 @@ interface LoggerLog {
|
|
|
196
264
|
<L extends boolean>(config: LoggerParseSignature, joiner?: string, log?: L, sc?: LoggerChalk): L extends true ? void : string;
|
|
197
265
|
<L extends boolean>(config?: LoggerParseSignature, joiner?: string, log?: L, sc?: LoggerChalk): L extends true ? void : string | Logger;
|
|
198
266
|
}
|
|
267
|
+
/**
|
|
268
|
+
* Return type of {@link GlobalEnv | env()}.
|
|
269
|
+
*
|
|
270
|
+
* When an explicit value type `X` is given it wins (backward compatible with
|
|
271
|
+
* `env<boolean>('FLAG')`). Otherwise the type registered for the key `K` is used
|
|
272
|
+
* — falling back to `string` for unknown keys. A provided default `D` is unioned
|
|
273
|
+
* into the result.
|
|
274
|
+
*/
|
|
275
|
+
type EnvReturn<X, K extends string, D> = [X] extends [never] ? [D] extends [undefined] ? EnvLookup<K> : EnvLookup<K> | D : [D] extends [undefined] ? X : X | D;
|
|
199
276
|
interface GlobalEnv {
|
|
200
|
-
<X =
|
|
277
|
+
<X = never, D = undefined, K extends string = string>(env: K, defaultValue?: D): EnvReturn<X, K, D>;
|
|
201
278
|
}
|
|
202
279
|
type ConfigShape = keyof ConfigRegistry extends never ? Record<string, any> : ConfigRegistry;
|
|
203
280
|
interface GlobalConfig {
|
|
@@ -285,7 +362,6 @@ declare const env: GlobalEnv;
|
|
|
285
362
|
* @returns
|
|
286
363
|
*/
|
|
287
364
|
declare const appUrl: (link?: string) => string;
|
|
288
|
-
declare const CONFIG_KEY: unique symbol;
|
|
289
365
|
/**
|
|
290
366
|
* Gets the application configuration.
|
|
291
367
|
*
|
|
@@ -589,4 +665,81 @@ declare class Hook {
|
|
|
589
665
|
static clear: () => void;
|
|
590
666
|
}
|
|
591
667
|
//#endregion
|
|
592
|
-
|
|
668
|
+
//#region src/EnvLoader.d.ts
|
|
669
|
+
/**
|
|
670
|
+
* Loads environment variables, reading the `.env` file on first access.
|
|
671
|
+
*
|
|
672
|
+
* The `.env` file is loaded lazily the first time a variable is read, so
|
|
673
|
+
* environment access never depends on a side-effect `import 'dotenv/config'`
|
|
674
|
+
* running first. Import ordering — which linters and bundlers may rewrite —
|
|
675
|
+
* could otherwise place an env-reading module before dotenv has populated
|
|
676
|
+
* `process.env`, leaving that module with default/stale values.
|
|
677
|
+
* `dotenv.config()` never overrides variables already set, so the lazy load is
|
|
678
|
+
* safe alongside other loaders.
|
|
679
|
+
*/
|
|
680
|
+
declare class EnvLoader {
|
|
681
|
+
private loaded;
|
|
682
|
+
/**
|
|
683
|
+
* Load the `.env` file once.
|
|
684
|
+
*
|
|
685
|
+
* @returns
|
|
686
|
+
*/
|
|
687
|
+
private ensureLoaded;
|
|
688
|
+
/**
|
|
689
|
+
* Read an environment variable, coercing booleans, numbers and `null`, and
|
|
690
|
+
* falling back to `defaultValue` when it is unset.
|
|
691
|
+
*
|
|
692
|
+
* @param name The variable name.
|
|
693
|
+
* @param defaultValue Returned when the variable is unset.
|
|
694
|
+
*/
|
|
695
|
+
get<X = never, D = undefined, K extends string = string>(name: K, defaultValue?: D): EnvReturn<X, K, D>;
|
|
696
|
+
}
|
|
697
|
+
/**
|
|
698
|
+
* Shared environment loader backing {@link env}.
|
|
699
|
+
*/
|
|
700
|
+
declare const envLoader: EnvLoader;
|
|
701
|
+
//#endregion
|
|
702
|
+
//#region src/ConfigLoader.d.ts
|
|
703
|
+
declare const CONFIG_KEY: unique symbol;
|
|
704
|
+
/**
|
|
705
|
+
* Loads and resolves application configuration from the config directory.
|
|
706
|
+
*
|
|
707
|
+
* Config modules are read once (lazily) from the output directory and cached on
|
|
708
|
+
* a global symbol, then queried by dot-path. A partial config object can also be
|
|
709
|
+
* merged in at runtime.
|
|
710
|
+
*/
|
|
711
|
+
declare class ConfigLoader {
|
|
712
|
+
/**
|
|
713
|
+
* The cached config store, shared across instances via a global symbol.
|
|
714
|
+
*/
|
|
715
|
+
private get store();
|
|
716
|
+
private set store(value);
|
|
717
|
+
/**
|
|
718
|
+
* Read and cache config modules from the config directory on first use.
|
|
719
|
+
*/
|
|
720
|
+
private load;
|
|
721
|
+
/**
|
|
722
|
+
* Resolve the directory to load config modules from.
|
|
723
|
+
*
|
|
724
|
+
* Prefers an explicit `CONFIG_PATH`, then the environment-selected output
|
|
725
|
+
* directory. Falls back to the other build output (`dist` ⇄
|
|
726
|
+
* `.arkstack/build`) so config still loads if the selected directory is
|
|
727
|
+
* missing or transiently emptied — e.g. a concurrent rebuild (`clean: true`)
|
|
728
|
+
* during a test run.
|
|
729
|
+
*/
|
|
730
|
+
private resolveConfigDir;
|
|
731
|
+
/**
|
|
732
|
+
* Resolve configuration: read a dot-path value, merge a partial config
|
|
733
|
+
* object, or return the whole config.
|
|
734
|
+
*
|
|
735
|
+
* @param key Dot-path to read, or an object to merge in.
|
|
736
|
+
* @param defaultValue Returned when a string key is not found.
|
|
737
|
+
*/
|
|
738
|
+
resolve<X extends ConfigRegistry | unknown = unknown, P extends DotPath<X> | undefined = undefined>(key?: P, defaultValue?: any): any;
|
|
739
|
+
}
|
|
740
|
+
/**
|
|
741
|
+
* Shared config loader backing {@link config}.
|
|
742
|
+
*/
|
|
743
|
+
declare const configLoader: ConfigLoader;
|
|
744
|
+
//#endregion
|
|
745
|
+
export { AbstractModelConstructor, AppException, ArkstackErrorPayload, ArkstackErrorShape, CONFIG_KEY, ConfigLoader, ConfigRegistry, ConfigShape, DotPath, DotPathValue, Encryption, EnvKey, EnvLoader, EnvLookup, EnvRegistry, EnvReturn, ErrorHandler, Exception, FileImporter, GlobalConfig, GlobalEnv, Hash, Hook, HookArgs, HookFor, HookName, HookPos, HookPositions, HookRegistry, IHook, Logger, LoggerChalk, LoggerLog, LoggerParseSignature, MergedConfig, ModelConstructor, ModelRegistry, Primitive, PublishEntry, PublishFilter, PublishGroup, Publisher, RequestException, UnionToIntersection, abort, abortIf, appKey, appUrl, assertFound, bindGracefulShutdown, bootWithDetectedPort, config, configLoader, createErrorPayload, discoverCommands, env, envLoader, getErrorLogger, getModel, getPrimaryError, getValidationErrors, importFile, initializeGlobalContext, interopDefault, isClass, isModelNotFoundError, isValidationError, loadPrototypes, logUnhandledError, nodeEnv, normalizeStatusCode, outputDir, perPage, rebuildOutput, renderError, resolveRuntimeDir, resolveRuntimeModule, serializeError, shouldHideStack, shouldLogError, toErrorShape, toOutputPath };
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { A as resolveRuntimeModule, C as env, D as outputDir, E as nodeEnv, F as ConfigLoader, I as configLoader, M as EnvLoader, N as envLoader, O as rebuildOutput, P as CONFIG_KEY, S as discoverCommands, T as interopDefault, _ as Hash, b as appUrl, c as abortIf, d as initializeGlobalContext, f as isClass, g as Exception, h as AppException, j as toOutputPath, k as resolveRuntimeDir, l as assertFound, m as RequestException, p as perPage, s as abort, u as getModel, v as Encryption, w as importFile, x as config, y as appKey } from "./utils-DEflBOXp.js";
|
|
2
2
|
import { Hook as Hook$1 } from "@arkstack/foundry";
|
|
3
|
-
import { str } from "@h3ravel/support";
|
|
4
3
|
import { Arkstack } from "@arkstack/contract";
|
|
4
|
+
import { str } from "@h3ravel/support";
|
|
5
5
|
import path from "node:path";
|
|
6
6
|
import { ModelNotFoundException } from "arkormx";
|
|
7
7
|
import { detect } from "detect-port";
|
|
@@ -529,4 +529,4 @@ var Hook = class {
|
|
|
529
529
|
};
|
|
530
530
|
};
|
|
531
531
|
//#endregion
|
|
532
|
-
export { AppException, CONFIG_KEY, Encryption, ErrorHandler, Exception, Hash, Hook, Logger, Publisher, RequestException, abort, abortIf, appKey, appUrl, assertFound, bindGracefulShutdown, bootWithDetectedPort, config, createErrorPayload, discoverCommands, env, getErrorLogger, getModel, getPrimaryError, getValidationErrors, importFile, initializeGlobalContext, interopDefault, isClass, isModelNotFoundError, isValidationError, loadPrototypes, logUnhandledError, nodeEnv, normalizeStatusCode, outputDir, perPage, rebuildOutput, renderError, resolveRuntimeDir, resolveRuntimeModule, serializeError, shouldHideStack, shouldLogError, toErrorShape, toOutputPath };
|
|
532
|
+
export { AppException, CONFIG_KEY, ConfigLoader, Encryption, EnvLoader, ErrorHandler, Exception, Hash, Hook, Logger, Publisher, RequestException, abort, abortIf, appKey, appUrl, assertFound, bindGracefulShutdown, bootWithDetectedPort, config, configLoader, createErrorPayload, discoverCommands, env, envLoader, getErrorLogger, getModel, getPrimaryError, getValidationErrors, importFile, initializeGlobalContext, interopDefault, isClass, isModelNotFoundError, isValidationError, loadPrototypes, logUnhandledError, nodeEnv, normalizeStatusCode, outputDir, perPage, rebuildOutput, renderError, resolveRuntimeDir, resolveRuntimeModule, serializeError, shouldHideStack, shouldLogError, toErrorShape, toOutputPath };
|
package/dist/utils/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { _ as Hash, a as use, c as abortIf, d as initializeGlobalContext, f as isClass, i as trait, l as assertFound, n as crc32, o as uses, p as perPage, r as getTraitMethods, s as abort, t as callTraitMethods, u as getModel, v as Encryption } from "../utils-
|
|
1
|
+
import { _ as Hash, a as use, c as abortIf, d as initializeGlobalContext, f as isClass, i as trait, l as assertFound, n as crc32, o as uses, p as perPage, r as getTraitMethods, s as abort, t as callTraitMethods, u as getModel, v as Encryption } from "../utils-DEflBOXp.js";
|
|
2
2
|
export { Encryption, Hash, abort, abortIf, assertFound, callTraitMethods, crc32, getModel, getTraitMethods, initializeGlobalContext, isClass, perPage, trait, use, uses };
|
|
@@ -1,16 +1,170 @@
|
|
|
1
1
|
import { createCipheriv, createDecipheriv, createHash, randomBytes } from "node:crypto";
|
|
2
|
-
import { Arr, Obj, undot } from "@h3ravel/support";
|
|
3
2
|
import { createJiti } from "jiti";
|
|
4
3
|
import { existsSync, readdirSync } from "fs";
|
|
5
4
|
import { Arkstack } from "@arkstack/contract";
|
|
5
|
+
import { Arr, Obj, undot } from "@h3ravel/support";
|
|
6
|
+
import { readdirSync as readdirSync$1 } from "node:fs";
|
|
6
7
|
import { createRequire } from "module";
|
|
7
8
|
import path, { resolve } from "node:path";
|
|
9
|
+
import { config } from "dotenv";
|
|
8
10
|
import { pathToFileURL } from "node:url";
|
|
9
11
|
import { rm } from "node:fs/promises";
|
|
10
12
|
import { spawn } from "node:child_process";
|
|
11
13
|
import { Secret, TOTP } from "otpauth";
|
|
12
14
|
import { compare, genSalt, hash } from "bcryptjs";
|
|
13
15
|
import { getUserConfig } from "arkormx";
|
|
16
|
+
//#region src/ConfigLoader.ts
|
|
17
|
+
const CONFIG_KEY = Symbol("globalConfig");
|
|
18
|
+
globalThis[CONFIG_KEY] = {};
|
|
19
|
+
/**
|
|
20
|
+
* Loads and resolves application configuration from the config directory.
|
|
21
|
+
*
|
|
22
|
+
* Config modules are read once (lazily) from the output directory and cached on
|
|
23
|
+
* a global symbol, then queried by dot-path. A partial config object can also be
|
|
24
|
+
* merged in at runtime.
|
|
25
|
+
*/
|
|
26
|
+
var ConfigLoader = class {
|
|
27
|
+
/**
|
|
28
|
+
* The cached config store, shared across instances via a global symbol.
|
|
29
|
+
*/
|
|
30
|
+
get store() {
|
|
31
|
+
return globalThis[CONFIG_KEY];
|
|
32
|
+
}
|
|
33
|
+
set store(value) {
|
|
34
|
+
globalThis[CONFIG_KEY] = value;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Read and cache config modules from the config directory on first use.
|
|
38
|
+
*/
|
|
39
|
+
load() {
|
|
40
|
+
if (Object.entries(this.store).length >= 1) return;
|
|
41
|
+
let files;
|
|
42
|
+
const require = createRequire(import.meta.url);
|
|
43
|
+
const configDir = this.resolveConfigDir();
|
|
44
|
+
try {
|
|
45
|
+
files = readdirSync$1(configDir, { withFileTypes: true }).filter((file) => {
|
|
46
|
+
if (file.name.includes("middleware") && globalThis.arkctx?.runtime === "CLI") return false;
|
|
47
|
+
return file.isFile() && (file.name.endsWith(".js") || file.name.endsWith(".ts"));
|
|
48
|
+
});
|
|
49
|
+
} catch {
|
|
50
|
+
files = [];
|
|
51
|
+
}
|
|
52
|
+
Object.assign(this.store, files.reduce((configs, file) => {
|
|
53
|
+
const configName = path.basename(file.name, path.extname(file.name));
|
|
54
|
+
try {
|
|
55
|
+
configs[configName] = require(path.join(file.parentPath, file.name)).default(typeof globalThis.app === "function" ? globalThis.app() : {});
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.warn(`[arkstack] Skipped config "${configName}": ${error.message}`);
|
|
58
|
+
}
|
|
59
|
+
return configs;
|
|
60
|
+
}, {}));
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Resolve the directory to load config modules from.
|
|
64
|
+
*
|
|
65
|
+
* Prefers an explicit `CONFIG_PATH`, then the environment-selected output
|
|
66
|
+
* directory. Falls back to the other build output (`dist` ⇄
|
|
67
|
+
* `.arkstack/build`) so config still loads if the selected directory is
|
|
68
|
+
* missing or transiently emptied — e.g. a concurrent rebuild (`clean: true`)
|
|
69
|
+
* during a test run.
|
|
70
|
+
*/
|
|
71
|
+
resolveConfigDir() {
|
|
72
|
+
const root = Arkstack.rootDir();
|
|
73
|
+
const explicit = env("CONFIG_PATH");
|
|
74
|
+
if (explicit) return explicit;
|
|
75
|
+
const candidates = [
|
|
76
|
+
path.join(outputDir(), "config"),
|
|
77
|
+
path.join(root, env("OUTPUT_DIR", "dist"), "config"),
|
|
78
|
+
path.join(root, env("OUTPUT_DIR_DEV", ".arkstack/build"), "config")
|
|
79
|
+
];
|
|
80
|
+
return candidates.find((dir) => {
|
|
81
|
+
try {
|
|
82
|
+
return readdirSync$1(dir).some((file) => file.endsWith(".js") || file.endsWith(".ts"));
|
|
83
|
+
} catch {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
}) ?? candidates[0];
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Resolve configuration: read a dot-path value, merge a partial config
|
|
90
|
+
* object, or return the whole config.
|
|
91
|
+
*
|
|
92
|
+
* @param key Dot-path to read, or an object to merge in.
|
|
93
|
+
* @param defaultValue Returned when a string key is not found.
|
|
94
|
+
*/
|
|
95
|
+
resolve(key, defaultValue) {
|
|
96
|
+
if (typeof globalThis.env === "undefined") globalThis.env = (k, def) => k ? process.env[k] ?? def : process.env;
|
|
97
|
+
this.load();
|
|
98
|
+
if (typeof key === "object" && key !== null) this.store = undot(Object.assign({}, Arr.dot(this.store), Arr.dot(key)));
|
|
99
|
+
else if (typeof key === "string") return Obj.get(this.store, key, defaultValue);
|
|
100
|
+
return this.store;
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
/**
|
|
104
|
+
* Shared config loader backing {@link config}.
|
|
105
|
+
*/
|
|
106
|
+
const configLoader = new ConfigLoader();
|
|
107
|
+
//#endregion
|
|
108
|
+
//#region src/EnvLoader.ts
|
|
109
|
+
/**
|
|
110
|
+
* Loads environment variables, reading the `.env` file on first access.
|
|
111
|
+
*
|
|
112
|
+
* The `.env` file is loaded lazily the first time a variable is read, so
|
|
113
|
+
* environment access never depends on a side-effect `import 'dotenv/config'`
|
|
114
|
+
* running first. Import ordering — which linters and bundlers may rewrite —
|
|
115
|
+
* could otherwise place an env-reading module before dotenv has populated
|
|
116
|
+
* `process.env`, leaving that module with default/stale values.
|
|
117
|
+
* `dotenv.config()` never overrides variables already set, so the lazy load is
|
|
118
|
+
* safe alongside other loaders.
|
|
119
|
+
*/
|
|
120
|
+
var EnvLoader = class {
|
|
121
|
+
loaded = false;
|
|
122
|
+
/**
|
|
123
|
+
* Load the `.env` file once.
|
|
124
|
+
*
|
|
125
|
+
* @returns
|
|
126
|
+
*/
|
|
127
|
+
ensureLoaded() {
|
|
128
|
+
if (this.loaded) return;
|
|
129
|
+
this.loaded = true;
|
|
130
|
+
try {
|
|
131
|
+
config({ quiet: true });
|
|
132
|
+
} catch {}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Read an environment variable, coercing booleans, numbers and `null`, and
|
|
136
|
+
* falling back to `defaultValue` when it is unset.
|
|
137
|
+
*
|
|
138
|
+
* @param name The variable name.
|
|
139
|
+
* @param defaultValue Returned when the variable is unset.
|
|
140
|
+
*/
|
|
141
|
+
get(name, defaultValue) {
|
|
142
|
+
this.ensureLoaded();
|
|
143
|
+
let val = process.env[name] ?? "";
|
|
144
|
+
if ([
|
|
145
|
+
true,
|
|
146
|
+
"true",
|
|
147
|
+
"on",
|
|
148
|
+
false,
|
|
149
|
+
"false",
|
|
150
|
+
"off"
|
|
151
|
+
].includes(val)) val = [
|
|
152
|
+
true,
|
|
153
|
+
"true",
|
|
154
|
+
"on"
|
|
155
|
+
].includes(val);
|
|
156
|
+
if (!isNaN(Number(val)) && typeof val !== "boolean" && typeof val !== "undefined" && val !== "") val = Number(val);
|
|
157
|
+
if (val === "") val = void 0;
|
|
158
|
+
if (val === "null") val = null;
|
|
159
|
+
val ??= defaultValue;
|
|
160
|
+
return val;
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
/**
|
|
164
|
+
* Shared environment loader backing {@link env}.
|
|
165
|
+
*/
|
|
166
|
+
const envLoader = new EnvLoader();
|
|
167
|
+
//#endregion
|
|
14
168
|
//#region src/system.ts
|
|
15
169
|
/**
|
|
16
170
|
* Read the .env file
|
|
@@ -19,26 +173,7 @@ import { getUserConfig } from "arkormx";
|
|
|
19
173
|
* @param def
|
|
20
174
|
* @returns
|
|
21
175
|
*/
|
|
22
|
-
const env = (env, defaultValue) =>
|
|
23
|
-
let val = process.env[env] ?? "";
|
|
24
|
-
if ([
|
|
25
|
-
true,
|
|
26
|
-
"true",
|
|
27
|
-
"on",
|
|
28
|
-
false,
|
|
29
|
-
"false",
|
|
30
|
-
"off"
|
|
31
|
-
].includes(val)) val = [
|
|
32
|
-
true,
|
|
33
|
-
"true",
|
|
34
|
-
"on"
|
|
35
|
-
].includes(val);
|
|
36
|
-
if (!isNaN(Number(val)) && typeof val !== "boolean" && typeof val !== "undefined" && val !== "") val = Number(val);
|
|
37
|
-
if (val === "") val = void 0;
|
|
38
|
-
if (val === "null") val = null;
|
|
39
|
-
val ??= defaultValue;
|
|
40
|
-
return val;
|
|
41
|
-
};
|
|
176
|
+
const env$1 = (env, defaultValue) => envLoader.get(env, defaultValue);
|
|
42
177
|
/**
|
|
43
178
|
* Build the app url
|
|
44
179
|
*
|
|
@@ -46,12 +181,12 @@ const env = (env, defaultValue) => {
|
|
|
46
181
|
* @returns
|
|
47
182
|
*/
|
|
48
183
|
const appUrl = (link) => {
|
|
49
|
-
const port = env("PORT", env("APP_PORT", "3000"));
|
|
184
|
+
const port = env$1("PORT", env$1("APP_PORT", "3000"));
|
|
50
185
|
const defaultUrl = `http://localhost:${port}`;
|
|
51
|
-
const appUrl = env("APP_URL", `http://localhost:${port}`);
|
|
186
|
+
const appUrl = env$1("APP_URL", `http://localhost:${port}`);
|
|
52
187
|
try {
|
|
53
188
|
const url = new URL(appUrl);
|
|
54
|
-
if (url.port || url.hostname === "localhost") url.port = port;
|
|
189
|
+
if (url.port || url.hostname === "localhost") url.port = String(port);
|
|
55
190
|
const baseUrl = url.toString().replace(/\/$/, "");
|
|
56
191
|
if (link) return `${baseUrl}${`/${link.replace(/^\/+/, "")}`}`;
|
|
57
192
|
return baseUrl;
|
|
@@ -59,8 +194,6 @@ const appUrl = (link) => {
|
|
|
59
194
|
return link ? `${defaultUrl}/${link.replace(/^\/+/, "")}` : defaultUrl;
|
|
60
195
|
}
|
|
61
196
|
};
|
|
62
|
-
const CONFIG_KEY = Symbol("globalConfig");
|
|
63
|
-
globalThis[CONFIG_KEY] = {};
|
|
64
197
|
/**
|
|
65
198
|
* Gets the application configuration.
|
|
66
199
|
*
|
|
@@ -68,35 +201,7 @@ globalThis[CONFIG_KEY] = {};
|
|
|
68
201
|
* @param defaultValue The default value to return if the key is not found.
|
|
69
202
|
* @returns The configuration value.
|
|
70
203
|
*/
|
|
71
|
-
const config = (key, defaultValue) =>
|
|
72
|
-
if (typeof globalThis.env === "undefined") globalThis.env = (key, def) => key ? process.env[key] ?? def : process.env;
|
|
73
|
-
const config = globalThis[CONFIG_KEY];
|
|
74
|
-
if (Object.entries(config).length < 1) {
|
|
75
|
-
let files;
|
|
76
|
-
const dist = path.relative(Arkstack.rootDir(), outputDir());
|
|
77
|
-
const require = createRequire(import.meta.url);
|
|
78
|
-
const configDir = env("CONFIG_PATH", path.join(Arkstack.rootDir(), `${dist}/config`));
|
|
79
|
-
try {
|
|
80
|
-
files = readdirSync(configDir, { withFileTypes: true }).filter((file) => {
|
|
81
|
-
if (file.name.includes("middleware") && globalThis.arkctx?.runtime === "CLI") return false;
|
|
82
|
-
return file.isFile() && (file.name.endsWith(".js") || file.name.endsWith(".ts"));
|
|
83
|
-
});
|
|
84
|
-
} catch {
|
|
85
|
-
files = [];
|
|
86
|
-
}
|
|
87
|
-
Object.assign(config, files.reduce((configs, file) => {
|
|
88
|
-
const configName = path.basename(file.name, path.extname(file.name));
|
|
89
|
-
configs[configName] = require(path.join(file.parentPath, file.name)).default(typeof globalThis.app === "function" ? globalThis.app() : {});
|
|
90
|
-
return configs;
|
|
91
|
-
}, {}));
|
|
92
|
-
globalThis[CONFIG_KEY] = config;
|
|
93
|
-
}
|
|
94
|
-
if (typeof key === "object" && key !== null) {
|
|
95
|
-
const config = Object.assign({}, Arr.dot(globalThis[CONFIG_KEY]), Arr.dot(key));
|
|
96
|
-
globalThis[CONFIG_KEY] = undot(config);
|
|
97
|
-
} else if (typeof key === "string") return Obj.get(globalThis[CONFIG_KEY], key, defaultValue);
|
|
98
|
-
return globalThis[CONFIG_KEY];
|
|
99
|
-
};
|
|
204
|
+
const config$1 = (key, defaultValue) => configLoader.resolve(key, defaultValue);
|
|
100
205
|
/**
|
|
101
206
|
* Resolve the unified application key.
|
|
102
207
|
*
|
|
@@ -114,13 +219,13 @@ const config = (key, defaultValue) => {
|
|
|
114
219
|
* @returns The resolved key, or `undefined` when none is configured.
|
|
115
220
|
*/
|
|
116
221
|
const appKey = (legacy = []) => {
|
|
117
|
-
const explicit = env("APP_KEY");
|
|
222
|
+
const explicit = env$1("APP_KEY");
|
|
118
223
|
if (explicit) return explicit;
|
|
119
224
|
for (const name of Array.isArray(legacy) ? legacy : [legacy]) {
|
|
120
|
-
const value = env(name);
|
|
225
|
+
const value = env$1(name);
|
|
121
226
|
if (value) return value;
|
|
122
227
|
}
|
|
123
|
-
return config("app.key") || void 0;
|
|
228
|
+
return config$1("app.key") || void 0;
|
|
124
229
|
};
|
|
125
230
|
/**
|
|
126
231
|
* Gets the current Node environment (development or production).
|
|
@@ -128,7 +233,7 @@ const appKey = (legacy = []) => {
|
|
|
128
233
|
* @returns
|
|
129
234
|
*/
|
|
130
235
|
const nodeEnv = () => {
|
|
131
|
-
let envValue = env("NODE_ENV", "development");
|
|
236
|
+
let envValue = env$1("NODE_ENV", "development");
|
|
132
237
|
if (envValue !== "development" && envValue !== "production") envValue = "development";
|
|
133
238
|
return envValue === "production" ? "prod" : "dev";
|
|
134
239
|
};
|
|
@@ -142,8 +247,8 @@ const outputDir = (cwd) => {
|
|
|
142
247
|
cwd ??= Arkstack.rootDir();
|
|
143
248
|
const NODE_ENV = nodeEnv();
|
|
144
249
|
const output = {
|
|
145
|
-
dev: env("OUTPUT_DIR_DEV", ".arkstack/build"),
|
|
146
|
-
prod: env("OUTPUT_DIR", "dist")
|
|
250
|
+
dev: env$1("OUTPUT_DIR_DEV", ".arkstack/build"),
|
|
251
|
+
prod: env$1("OUTPUT_DIR", "dist")
|
|
147
252
|
};
|
|
148
253
|
return path.isAbsolute(output[NODE_ENV] ?? output.dev) ? output[NODE_ENV] ?? output.dev : path.join(cwd, output[NODE_ENV] ?? output.dev);
|
|
149
254
|
};
|
|
@@ -431,13 +536,13 @@ var Hash = class {
|
|
|
431
536
|
return new TOTP({
|
|
432
537
|
label,
|
|
433
538
|
digits,
|
|
434
|
-
issuer: env("APP_NAME", "Roseed"),
|
|
539
|
+
issuer: env$1("APP_NAME", "Roseed"),
|
|
435
540
|
algorithm: "SHA1",
|
|
436
541
|
period,
|
|
437
542
|
secret: "US3WHSG7X5KAPV27VANWKQHF3SH3HULL"
|
|
438
543
|
});
|
|
439
544
|
}
|
|
440
|
-
static totp(secret, label, issuer = env("APP_NAME", "Roseed"), period = 30) {
|
|
545
|
+
static totp(secret, label, issuer = env$1("APP_NAME", "Roseed"), period = 30) {
|
|
441
546
|
return new TOTP({
|
|
442
547
|
issuer,
|
|
443
548
|
label,
|
|
@@ -800,4 +905,4 @@ function uses(instance, trait) {
|
|
|
800
905
|
return false;
|
|
801
906
|
}
|
|
802
907
|
//#endregion
|
|
803
|
-
export {
|
|
908
|
+
export { resolveRuntimeModule as A, env$1 as C, outputDir as D, nodeEnv as E, ConfigLoader as F, configLoader as I, EnvLoader as M, envLoader as N, rebuildOutput as O, CONFIG_KEY as P, discoverCommands as S, interopDefault as T, Hash as _, use as a, appUrl as b, abortIf as c, initializeGlobalContext as d, isClass as f, Exception as g, AppException as h, trait as i, toOutputPath as j, resolveRuntimeDir as k, assertFound as l, RequestException as m, crc32 as n, uses as o, perPage as p, getTraitMethods as r, abort as s, callTraitMethods as t, getModel as u, Encryption as v, importFile as w, config$1 as x, appKey as y };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@arkstack/common",
|
|
3
|
-
"version": "0.14.
|
|
3
|
+
"version": "0.14.19",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Core utilities, primitives, and shared infrastructure for the Arkstack ecosystem.",
|
|
6
6
|
"homepage": "https://arkstack.toneflix.net",
|
|
@@ -36,14 +36,15 @@
|
|
|
36
36
|
"bcryptjs": "^3.0.3",
|
|
37
37
|
"chalk": "^5.6.2",
|
|
38
38
|
"detect-port": "^2.1.0",
|
|
39
|
+
"dotenv": "^17.4.2",
|
|
39
40
|
"otpauth": "^9.5.1",
|
|
40
41
|
"pino": "^10.3.1"
|
|
41
42
|
},
|
|
42
43
|
"peerDependencies": {
|
|
43
44
|
"@h3ravel/support": "^2.2.0",
|
|
44
45
|
"arkormx": "^2.10.1",
|
|
45
|
-
"@arkstack/foundry": "^0.14.
|
|
46
|
-
"@arkstack/contract": "^0.14.
|
|
46
|
+
"@arkstack/foundry": "^0.14.19",
|
|
47
|
+
"@arkstack/contract": "^0.14.19"
|
|
47
48
|
},
|
|
48
49
|
"scripts": {
|
|
49
50
|
"build": "tsdown --config-loader unrun",
|