@arkstack/common 0.5.2 → 0.5.3

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 CHANGED
@@ -1,15 +1,24 @@
1
1
  /// <reference path="./app.d.ts" />
2
- import { DotPath } from "@h3ravel/support";
2
+ import { a as abortIf, c as initializeGlobalContext, d as Hash, f as Encryption, i as abort, l as isClass, n as ModelConstructor, o as assertFound, r as ModelRegistry, s as getModel, t as AbstractModelConstructor, u as perPage } from "./helpers-BrQ0B-EX.js";
3
+ import { JitiOptions, JitiResolveOptions } from "jiti";
4
+ import { Arkstack } from "@arkstack/contract";
3
5
  import pino from "pino";
4
6
  import { ChalkInstance } from "chalk";
5
- import { TOTP } from "otpauth";
6
- import { Model, ModelStatic } from "arkormx";
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: (boot: (port: number) => Promise<void>, preferredPort?: number, app?: any) => Promise<void>;
12
+ /**
13
+ * Boots the app using an available port close to the requested port
14
+ *when requested port is not available
15
+ *
16
+ * @param boot
17
+ * @param preferredPort
18
+ * @param app
19
+ * @param defer
20
+ */
21
+ 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
22
  declare const renderError: ({
14
23
  message,
15
24
  stack,
@@ -34,51 +43,281 @@ declare class Console {
34
43
  static error: (...args: any[]) => void[];
35
44
  }
36
45
  declare class Logger {
46
+ /**
47
+ * Global verbosity configuration
48
+ */
37
49
  private static verbosity;
38
50
  private static isQuiet;
39
51
  private static isSilent;
52
+ /**
53
+ * Configure global verbosity levels
54
+ */
40
55
  static configure(options?: {
41
56
  verbosity?: number;
42
57
  quiet?: boolean;
43
58
  silent?: boolean;
44
59
  }): void;
60
+ /**
61
+ * Check if output should be suppressed
62
+ */
45
63
  private static shouldSuppressOutput;
64
+ /**
65
+ * Logs the message in two columns
66
+ *
67
+ * @param name
68
+ * @param value
69
+ * @param log If set to false, array of [name, dots, value] output will be returned and not logged
70
+ * @returns
71
+ */
46
72
  static twoColumnDetail(name: string, value: string, log?: true, spacer?: string): void;
47
73
  static twoColumnDetail(name: string, value: string, log?: false, spacer?: string): [string, string, string];
74
+ /**
75
+ * Logs the message in two columns
76
+ *
77
+ * @param name
78
+ * @param desc
79
+ * @param width
80
+ * @param log If set to false, array of [name, dots, value] output will be returned and not logged
81
+ * @returns
82
+ */
48
83
  static describe(name: string, desc: string, width?: number, log?: true): void;
49
84
  static describe(name: string, desc: string, width?: number, log?: false): [string, string, string];
85
+ /**
86
+ * Logs the message in two columns but allways passing status
87
+ *
88
+ * @param name
89
+ * @param value
90
+ * @param status
91
+ * @param exit
92
+ * @param preserveCol
93
+ */
50
94
  static split(name: string, value: string, status?: 'success' | 'info' | 'error', exit?: boolean, preserveCol?: boolean, spacer?: string): void;
95
+ /**
96
+ * Wraps text with chalk
97
+ *
98
+ * @param txt
99
+ * @param color
100
+ * @param preserveCol
101
+ * @returns
102
+ */
51
103
  static textFormat(txt: unknown | unknown[], color: (...text: unknown[]) => string, preserveCol?: boolean): string;
104
+ /**
105
+ * Logs a success message
106
+ *
107
+ * @param msg
108
+ * @param exit
109
+ * @param preserveCol
110
+ */
52
111
  static success(msg: any, exit?: boolean, preserveCol?: boolean): void;
112
+ /**
113
+ * Logs an informational message
114
+ *
115
+ * @param msg
116
+ * @param exit
117
+ * @param preserveCol
118
+ */
53
119
  static info(msg: any, exit?: boolean, preserveCol?: boolean): void;
120
+ /**
121
+ * Logs an error message
122
+ *
123
+ * @param msg
124
+ * @param exit
125
+ * @param preserveCol
126
+ */
54
127
  static error(msg: any, exit?: boolean, preserveCol?: boolean): void;
128
+ /**
129
+ * Logs a warning message
130
+ *
131
+ * @param msg
132
+ * @param exit
133
+ * @param preserveCol
134
+ */
55
135
  static warn(msg: any, exit?: boolean, preserveCol?: boolean): void;
136
+ /**
137
+ * Logs a debug message (only shown with verbosity >= 3)
138
+ *
139
+ * @param msg
140
+ * @param exit
141
+ * @param preserveCol
142
+ */
56
143
  static debug<M = any>(msg: M | M[], exit?: boolean, preserveCol?: boolean): void;
144
+ /**
145
+ * Terminates the process
146
+ */
57
147
  static quiet(): void;
58
148
  static chalker(styles: LoggerChalk[]): (input: any) => string;
149
+ /**
150
+ * Parse an array formated message and logs it
151
+ *
152
+ * @param config
153
+ * @param joiner
154
+ * @param log If set to false, string output will be returned and not logged
155
+ * @param sc color to use ue on split text if : is found
156
+ */
59
157
  static parse(config: LoggerParseSignature, joiner?: string, log?: true, sc?: LoggerChalk): void;
60
158
  static parse(config: LoggerParseSignature, joiner?: string, log?: false, sc?: LoggerChalk): string;
159
+ /**
160
+ * Ouput formater object or format the output
161
+ *
162
+ * @returns
163
+ */
61
164
  static log: LoggerLog;
165
+ /**
166
+ * A simple console like output logger
167
+ *
168
+ * @returns
169
+ */
62
170
  static console(): typeof Console;
63
171
  }
64
172
  //#endregion
173
+ //#region src/locales.d.ts
174
+ declare const locales: readonly ["af_ZA", "ar", "az", "bn_BD", "cs_CZ", "cy", "da", "de", "de_AT", "de_CH", "dv", "el", "en", "en_AU", "en_AU_ocker", "en_BORK", "en_CA", "en_GB", "en_GH", "en_HK", "en_IE", "en_IN", "en_NG", "en_US", "en_ZA", "eo", "es", "es_MX", "fa", "fi", "fr", "fr_BE", "fr_CA", "fr_CH", "fr_LU", "fr_SN", "he", "hr", "hu", "hy", "id_ID", "it", "ja", "ka_GE", "ko", "ku_ckb", "ku_kmr_latin", "lv", "mk", "mn_MN_cyrl", "nb_NO", "ne", "nl", "nl_BE", "pl", "pt_BR", "pt_PT", "ro", "ro_MD", "ru", "sk", "sl_SI", "sr_RS_latin", "sv", "ta_IN", "th", "tr", "uk", "ur", "uz_UZ_latin", "vi", "yo_NG", "zh_CN", "zh_TW", "zu_ZA"];
175
+ //#endregion
65
176
  //#region src/types.d.ts
177
+ interface ConfigRegistry {}
178
+ /**
179
+ * Map of known environment variables to their (coerced) value types.
180
+ *
181
+ * Used to give {@link GlobalEnv | env()} precise return types. Unknown keys fall
182
+ * back to `string`. Augment this interface (declaration merging) to register
183
+ * application-specific variables:
184
+ *
185
+ * ```ts
186
+ * declare module '@arkstack/common' {
187
+ * interface EnvRegistry { MY_FLAG: boolean }
188
+ * }
189
+ * ```
190
+ */
191
+ interface EnvRegistry {
192
+ APP_NAME: string;
193
+ APP_ENV: 'development' | 'production' | 'staging' | 'local';
194
+ APP_KEY: string;
195
+ APP_URL: string;
196
+ APP_HOST: string;
197
+ APP_PORT: number;
198
+ APP_DEBUG: boolean;
199
+ APP_TIMEZONE: string;
200
+ APP_LOCALE: typeof locales[number];
201
+ APP_FALLBACK_LOCALE: typeof locales[number];
202
+ APP_FAKER_LOCALE: typeof locales[number];
203
+ NODE_ENV: 'development' | 'production' | 'test';
204
+ PORT: number;
205
+ HOST: string;
206
+ FRONTEND_URL: string;
207
+ OUTPUT_DIR: string;
208
+ OUTPUT_DIR_DEV: string;
209
+ CONFIG_PATH: string;
210
+ TUNNEL: boolean;
211
+ NGROK_AUTHTOKEN: string;
212
+ NGROK_DOMAIN: string;
213
+ FILESYSTEM_DISK: string;
214
+ CACHE_STORE: string;
215
+ CACHE_PREFIX: string;
216
+ CACHE_TABLE: string;
217
+ QUEUE_CONNECTION: string;
218
+ QUEUE_TABLE: string;
219
+ QUEUE_NAME: string;
220
+ QUEUE_RETRY_AFTER: number;
221
+ REDIS_HOST: string;
222
+ REDIS_PORT: number;
223
+ REDIS_PASSWORD: string;
224
+ REDIS_CACHE_DB: number;
225
+ REDIS_QUEUE_DB: number;
226
+ JWT_EXPIRES_IN: string;
227
+ SESSION_LIFETIME: number;
228
+ TWO_FACTOR_SMS_TTL_MINUTES: number;
229
+ DATABASE_URL: string;
230
+ DB_CONNECTION: string;
231
+ DB_HOST: string;
232
+ DB_PORT: number;
233
+ DB_DATABASE: string;
234
+ DB_USERNAME: string;
235
+ DB_PASSWORD: string;
236
+ MAIL_HOST: string;
237
+ MAIL_PORT: number;
238
+ MAIL_SECURE: boolean;
239
+ MAIL_USERNAME: string;
240
+ MAIL_PASSWORD: string;
241
+ MAIL_FROM_ADDRESS: string;
242
+ MAIL_TEST_ADDRESS: string;
243
+ AWS_ACCESS_KEY_ID: string;
244
+ AWS_SECRET_ACCESS_KEY: string;
245
+ AWS_DEFAULT_REGION: string;
246
+ AWS_BUCKET: string;
247
+ AWS_URL: string;
248
+ AWS_ENDPOINT: string;
249
+ }
250
+ /**
251
+ * App Confifuration
252
+ */
253
+ interface AppConfig {
254
+ [key: string]: any;
255
+ env: string;
256
+ key: string;
257
+ url: string;
258
+ host: string;
259
+ name: string;
260
+ frontend_url: string;
261
+ debug: boolean;
262
+ timezone: string;
263
+ locale: typeof locales[number];
264
+ fallback_locale: typeof locales[number];
265
+ faker_locale: typeof locales[number];
266
+ }
267
+ /**
268
+ * Known environment variable names.
269
+ */
270
+ type EnvKey = keyof EnvRegistry & string;
271
+ /** The registered type for a known key, or `string` for an unknown one. */
272
+ type EnvLookup<K extends string> = [K] extends [EnvKey] ? EnvRegistry[K] : string;
273
+ type UnionToIntersection<U> = (U extends any ? (x: U) => void : never) extends ((x: infer I) => void) ? I : never;
274
+ type MergedConfig<X> = UnionToIntersection<X>;
275
+ type Primitive = string | number | boolean | null | undefined | Function;
66
276
  type LoggerChalk = keyof ChalkInstance | ChalkInstance | (keyof ChalkInstance)[];
67
277
  type LoggerParseSignature = [string, LoggerChalk][];
68
278
  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;
279
+ type DotPath<T> = T extends Primitive ? never : T extends any[] ? never : { [K in keyof T & string]: T[K] extends Primitive ? `${K}` : T[K] extends any[] ? `${K}` : `${K}` | `${K}.${DotPath<T[K]>}` }[keyof T & string];
280
+ /**
281
+ * Ouput formater object or format the output
282
+ *
283
+ * @param config
284
+ * @param joiner
285
+ * @param log If set to false, string output will be returned and not logged
286
+ * @param sc color to use ue on split text if : is found
287
+ *
288
+ * @returns
289
+ */
69
290
  interface LoggerLog {
70
291
  (): typeof Logger;
71
292
  <L extends boolean>(config: string, joiner: LoggerChalk, log?: L, sc?: LoggerChalk): L extends true ? void : string;
72
293
  <L extends boolean>(config: LoggerParseSignature, joiner?: string, log?: L, sc?: LoggerChalk): L extends true ? void : string;
73
294
  <L extends boolean>(config?: LoggerParseSignature, joiner?: string, log?: L, sc?: LoggerChalk): L extends true ? void : string | Logger;
74
295
  }
296
+ /**
297
+ * Return type of {@link GlobalEnv | env()}.
298
+ *
299
+ * When an explicit value type `X` is given it wins (backward compatible with
300
+ * `env<boolean>('FLAG')`). Otherwise the type registered for the key `K` is used
301
+ * — falling back to `string` for unknown keys. A provided default `D` is unioned
302
+ * into the result.
303
+ */
304
+ type EnvReturn<X, K extends string, D> = [X] extends [never] ? [D] extends [undefined] ? EnvLookup<K> : EnvLookup<K> | D : [D] extends [undefined] ? X : X | D;
75
305
  interface GlobalEnv {
76
- <X = string, Y = undefined | X>(env: string, defaultValue?: Y): Y extends undefined ? X : Y;
306
+ <X = never, D = undefined, K extends (keyof EnvRegistry | (string & {})) = keyof EnvRegistry>(env: K, defaultValue?: D): EnvReturn<X, K, D>;
77
307
  }
308
+ type ConfigShape = keyof ConfigRegistry extends never ? Record<string, any> : ConfigRegistry;
78
309
  interface GlobalConfig {
79
- <X extends Record<string, any>>(): X;
80
- <X extends Record<string, any>, P extends DotPath<X>>(key: P): DotPathValue<X, P>;
81
- <X extends Record<string, any>, P extends DotPath<X>, D>(key: P, defaultValue: D): DotPathValue<X, P> | D;
310
+ <X extends ConfigShape>(): X;
311
+ <X extends ConfigShape, P extends DotPath<X>>(key: P): DotPathValue<X, P>;
312
+ <X extends ConfigShape, P extends DotPath<X>>(key: Record<P, Partial<DotPathValue<X, P>>>): void;
313
+ <X extends ConfigShape, P extends DotPath<X>, D>(key: P, defaultValue: D): DotPathValue<X, P> | D;
314
+ }
315
+ interface FileImporter {
316
+ <T = unknown>(filePath: string): Promise<T>;
317
+ <T = unknown>(filePath: string, userOptions?: JitiOptions | undefined): Promise<T>;
318
+ <T = unknown>(filePath: string, userOptions?: JitiOptions | undefined, resolveOptions?: (JitiResolveOptions & {
319
+ default?: true;
320
+ })): Promise<T>;
82
321
  }
83
322
  type ArkstackErrorShape = Error & {
84
323
  cause?: unknown;
@@ -86,7 +325,8 @@ type ArkstackErrorShape = Error & {
86
325
  errors?: unknown;
87
326
  getModelName?: () => string;
88
327
  status?: number;
89
- statusCode?: number;
328
+ statusCode?: number; /** Custom properties merged into the error response payload. */
329
+ body?: Record<string, unknown>;
90
330
  };
91
331
  interface ArkstackErrorPayload {
92
332
  status: 'error';
@@ -94,15 +334,196 @@ interface ArkstackErrorPayload {
94
334
  message: string;
95
335
  errors?: unknown;
96
336
  stack?: string;
337
+ /** Custom fields contributed by an exception's `body`. */
338
+ [key: string]: unknown;
339
+ }
340
+ interface HookRegistry {}
341
+ type Position = 'before' | 'after' | (string & {});
342
+ type IHook = { [P in Position]?: (...args: any[]) => void };
343
+ type HookName = keyof HookRegistry extends never ? string : keyof HookRegistry | (string & {});
344
+ type HookFor<N extends string> = N extends keyof HookRegistry ? HookRegistry[N] : IHook;
345
+ type HookPos<N extends string, P extends string> = N extends keyof HookRegistry ? P extends keyof HookRegistry[N] ? HookRegistry[N][P] : (...args: any[]) => void : (...args: any[]) => void;
346
+ type HookPositions<N extends string> = N extends keyof HookRegistry ? keyof HookRegistry[N] : Position;
347
+ type HookArgs<N extends string, P extends string> = N extends keyof HookRegistry ? P extends keyof HookRegistry[N] ? HookRegistry[N][P] extends ((...args: infer A) => any) ? A : any[] : any[] : any[];
348
+ /**
349
+ * A single source → destination mapping a package wants to publish into the
350
+ * consuming application.
351
+ */
352
+ interface PublishEntry {
353
+ /** Absolute path to the file or directory shipped by the package. */
354
+ from: string;
355
+ /**
356
+ * Destination path, relative to the application root, where the artifact is
357
+ * written when published.
358
+ */
359
+ to: string;
360
+ }
361
+ /**
362
+ * A group of publishable artifacts registered by a package.
363
+ */
364
+ interface PublishGroup {
365
+ /** The package registering the artifacts, e.g. `@arkstack/cache`. */
366
+ package: string;
367
+ /**
368
+ * Optional tag for selective publishing (`ark publish --tag <tag>`). A
369
+ * package may register several groups under different tags.
370
+ */
371
+ tag?: string;
372
+ /** The files/directories to publish. */
373
+ entries: PublishEntry[];
374
+ }
375
+ /** Optional filter applied when reading the registry. */
376
+ interface PublishFilter {
377
+ package?: string;
378
+ tag?: string;
97
379
  }
98
380
  //#endregion
99
381
  //#region src/system.d.ts
382
+ /**
383
+ * Read the .env file
384
+ *
385
+ * @param env
386
+ * @param def
387
+ * @returns
388
+ */
100
389
  declare const env: GlobalEnv;
390
+ /**
391
+ * Build the app url
392
+ *
393
+ * @param link
394
+ * @returns
395
+ */
101
396
  declare const appUrl: (link?: string) => string;
397
+ /**
398
+ * Gets the application configuration.
399
+ *
400
+ * @param key The configuration key to retrieve.
401
+ * @param defaultValue The default value to return if the key is not found.
402
+ * @returns The configuration value.
403
+ */
102
404
  declare const config: GlobalConfig;
405
+ /**
406
+ * Resolve the unified application key.
407
+ *
408
+ * `APP_KEY` (exposed as `config('app.key')`) is the single secret used for
409
+ * signing and encryption across the framework. Resolution order:
410
+ *
411
+ * 1. An explicit `APP_KEY` environment variable.
412
+ * 2. Any legacy environment variable(s) passed in, for backward compatibility
413
+ * with apps that predate `APP_KEY` (e.g. `JWT_SECRET`,
414
+ * `TWO_FACTOR_ENCRYPTION_KEY`).
415
+ * 3. `config('app.key')` — the value from `src/config/app.ts`, which may itself
416
+ * be a placeholder default when no config is loaded.
417
+ *
418
+ * @param legacy Legacy env var name(s) to fall back to.
419
+ * @returns The resolved key, or `undefined` when none is configured.
420
+ */
421
+ declare const appKey: (legacy?: string | string[]) => string | undefined;
422
+ /**
423
+ * Gets the current Node environment (development or production).
424
+ *
425
+ * @returns
426
+ */
103
427
  declare const nodeEnv: () => "prod" | "dev";
428
+ /**
429
+ * Gets the output directory for the application based on the current environment.
430
+ *
431
+ * @param cwd The current working directory (optional, defaults to Arkstack.rootDir()).
432
+ * @returns
433
+ */
104
434
  declare const outputDir: (cwd?: string) => string;
105
- declare const importFile: <T = unknown>(filePath: string) => Promise<T>;
435
+ /**
436
+ * Map an application source path to its build-output counterpart.
437
+ *
438
+ * Application code is authored under `src/` and compiled into {@link outputDir},
439
+ * which strips the leading `src/` segment and emits JavaScript (e.g.
440
+ * `src/app/models/User.ts` -> `dist/app/models/User.js`). A TypeScript source
441
+ * extension is rewritten to `.js`; paths without one (directories) keep their
442
+ * shape. Absolute or root-relative paths outside the app root are returned
443
+ * unchanged.
444
+ *
445
+ * This is a pure path transform — it does not touch the filesystem. Use
446
+ * {@link resolveRuntimeModule} / {@link resolveRuntimeDir} when you need an
447
+ * existing file/dir for the current environment.
448
+ *
449
+ * @param sourcePath Absolute or root-relative source path.
450
+ */
451
+ declare const toOutputPath: (sourcePath: string) => string;
452
+ /**
453
+ * Resolve an application module's source path to a file that can be imported at
454
+ * runtime.
455
+ *
456
+ * In development the TypeScript source is loaded directly (jiti compiles on the
457
+ * fly); in production only the build output ships, so the path is remapped into
458
+ * {@link outputDir} with a compiled extension. The first existing candidate
459
+ * wins — production prefers the build output, development prefers source — so a
460
+ * deploy that ships only `dist` never reaches for `src`.
461
+ *
462
+ * @param sourcePath Absolute or root-relative source path, with or without extension.
463
+ * @returns An existing importable path, or `sourcePath` unchanged when none exists.
464
+ */
465
+ declare const resolveRuntimeModule: (sourcePath: string) => string;
466
+ /**
467
+ * Resolve an application source directory to the directory that exists at
468
+ * runtime.
469
+ *
470
+ * The directory counterpart of {@link resolveRuntimeModule}: it maps the source
471
+ * directory into {@link outputDir} (stripping the leading `src/` segment) but
472
+ * appends no file extension. Production prefers the build output, development
473
+ * prefers source, and the absolute source path is returned when neither exists.
474
+ *
475
+ * @param sourcePath Absolute or root-relative source directory.
476
+ * @returns An existing directory path, or the absolute source path when none exists.
477
+ */
478
+ declare const resolveRuntimeDir: (sourcePath: string) => string;
479
+ /**
480
+ * Rebuild the application output (tsdown) into {@link outputDir}, wiping it first
481
+ * so no stale emitted modules survive a source change. Standalone — it does NOT
482
+ * boot the app — so the console kernel can call it to self-heal a stale or
483
+ * incomplete build artifact that would otherwise wedge startup. Build-only: it
484
+ * sets `CLI_BUILD` so tsdown emits without starting a watcher/dev server, and
485
+ * inherits the current `NODE_ENV` so it targets the same dir the kernel reads.
486
+ */
487
+ declare const rebuildOutput: () => Promise<void>;
488
+ /**
489
+ *
490
+ * Dynamically imports a file at the given path with full TypeScript support,
491
+ * including `tsconfig.json` path aliases.
492
+ *
493
+ * @param filePath - The path to the file to import.
494
+ * @returns The imported module typed as `T`.
495
+ *
496
+ * @example
497
+ * const config = await importFile<AppConfig>('./config/app.ts')
498
+ */
499
+ declare const importFile: FileImporter;
500
+ /**
501
+ * Discover console command classes from the application's command directory.
502
+ *
503
+ * Commands are loaded straight from TypeScript source through {@link importFile}
504
+ * (jiti), so they are picked up without a build and reflect edits on every run.
505
+ * The built output is only used as a fallback when the source directory is
506
+ * absent — e.g. a production deploy that ships `dist` without `src`.
507
+ *
508
+ * This exists because musket's own glob discovery imports paths with native
509
+ * `import()`, which silently skips `.ts` files — the reason commands previously
510
+ * only appeared after a `build --dev` and never reflected later edits.
511
+ *
512
+ * @param subPath Command directory relative to the app root (src/dist aware).
513
+ * @returns The discovered command classes.
514
+ */
515
+ declare const discoverCommands: <T = unknown>(subPath?: string) => Promise<T[]>;
516
+ /**
517
+ * Resolves the default export from a module, handling both CJS and ESM interop.
518
+ * In CJS modules, the default export is often the module itself (a function or object),
519
+ * while in ESM the default is nested under the `default` property.
520
+ *
521
+ * @param imp - The imported module
522
+ * @returns The resolved default export
523
+ */
524
+ declare const interopDefault: <T>(imp: T | {
525
+ default: T;
526
+ }) => T;
106
527
  //#endregion
107
528
  //#region src/Exceptions/Exception.d.ts
108
529
  declare class Exception extends Error {
@@ -116,6 +537,21 @@ declare class AppException extends Exception {
116
537
  [key: string]: string[] | string;
117
538
  } | undefined;
118
539
  statusCode: number;
540
+ /**
541
+ * Custom properties merged into the error response payload.
542
+ *
543
+ * When set, these are merged over the standard error payload (`status`,
544
+ * `code`, `message`, …), letting a subclass add fields to — or reshape — the
545
+ * returned error body.
546
+ *
547
+ * @example
548
+ * ```ts
549
+ * class PaymentException extends AppException {
550
+ * body = { error_code: 'PAYMENT_FAILED', retryable: true }
551
+ * }
552
+ * ```
553
+ */
554
+ body?: Record<string, unknown>;
119
555
  constructor(message?: string, statusCode?: number, options?: ErrorOptions);
120
556
  }
121
557
  //#endregion
@@ -123,7 +559,33 @@ declare class AppException extends Exception {
123
559
  declare class RequestException extends AppException {
124
560
  statusCode: number;
125
561
  constructor(message?: string, statusCode?: number, options?: ErrorOptions);
562
+ /**
563
+ * Asserts that a value is not null or undefined.
564
+ *
565
+ * @param value
566
+ * @param message
567
+ * @param code
568
+ * @throws {RequestException} Throws if the value is null or undefined.
569
+ */
570
+ static assertFound<T>(value: T | null | undefined, message: string, code?: number): asserts value is T;
571
+ /**
572
+ * Asserts that a value is not null or undefined.
573
+ *
574
+ * @param value
575
+ * @param message
576
+ * @param code
577
+ * @throws {RequestException} Throws if the value is null or undefined.
578
+ * @deprecated Use assertFound instead
579
+ */
126
580
  static assertNotEmpty<T>(value: T | null | undefined, message: string, code?: number): asserts value is T;
581
+ /**
582
+ * Asserts that a boolean condition is true.
583
+ *
584
+ * @param boolean
585
+ * @param message
586
+ * @param code
587
+ * @throws {RequestException} Throws if the boolean condition is true.
588
+ */
127
589
  static abortIf<T>(boolean: T, message: string, code?: number): asserts boolean is T;
128
590
  }
129
591
  //#endregion
@@ -157,47 +619,198 @@ declare const shouldLogError: typeof ErrorHandler.shouldLogError;
157
619
  declare const createErrorPayload: typeof ErrorHandler.createErrorPayload;
158
620
  declare const logUnhandledError: typeof ErrorHandler.logUnhandledError;
159
621
  //#endregion
622
+ //#region src/Publisher.d.ts
623
+ /**
624
+ * Registry of artifacts packages want to publish into the consuming application.
625
+ *
626
+ * Packages call {@link Publisher.publishes} from their `setup` module so that
627
+ * `ark publish` can copy the artifacts (migrations, config stubs, assets, …)
628
+ * into the app. The registry is backed by a global symbol so it stays a single
629
+ * shared instance even across duplicated module copies.
630
+ */
631
+ declare class Publisher {
632
+ /** The shared, global-symbol-backed registry of publishable groups. */
633
+ private static get registry();
634
+ /**
635
+ * Register artifacts a package wants to publish into the application.
636
+ *
637
+ * @example
638
+ * ```ts
639
+ * Publisher.publishes({
640
+ * package: '@arkstack/cache',
641
+ * tag: 'cache-migrations',
642
+ * entries: [{ from: join(here, '../stubs/...'), to: 'src/database/migrations/...' }],
643
+ * })
644
+ * ```
645
+ *
646
+ * @param group The publishable group to register.
647
+ */
648
+ static publishes(group: PublishGroup): void;
649
+ /**
650
+ * Read the registered publishable groups, optionally filtered by package or
651
+ * tag.
652
+ *
653
+ * @param filter Restrict the result to a package and/or tag.
654
+ * @returns The matching publishable groups.
655
+ */
656
+ static publishables(filter?: PublishFilter): PublishGroup[];
657
+ /** Remove every registered publishable group (primarily for tests). */
658
+ static clear(): void;
659
+ }
660
+ //#endregion
160
661
  //#region src/Hook.d.ts
161
- type Position = 'before' | 'after' | (string & {});
162
- type IHook = { [P in Position]?: (...args: any[]) => void };
163
662
  declare class Hook {
164
663
  private static hooks;
165
- static set: (name: string, hook: IHook) => void;
166
- static has: (name: string, pos?: Position) => boolean;
167
- static get<N extends string>(name: N): IHook | undefined;
168
- static get<N extends string>(name: N, pos: Position): IHook[Position] | undefined;
169
- static getAll: () => Record<string, IHook>;
170
- static unset: (name?: string, pos?: Position) => undefined;
664
+ /**
665
+ * Hooks define code that should run within defined boundaries to add extra functionalities.
666
+ *
667
+ * @param name
668
+ * @param value
669
+ */
670
+ static set<N extends HookName>(name: N | (string & {}), hook: HookFor<N>): void;
671
+ /**
672
+ * Check if a hook is defined by name
673
+ *
674
+ * @param name
675
+ */
676
+ static has<N extends HookName, P extends HookPositions<N>>(name: N | (string & {}), pos?: P): boolean;
677
+ /**
678
+ * Retrieve a defined hook by name
679
+ *
680
+ * @param name
681
+ */
682
+ static get<N extends HookName>(name: N): HookFor<N> | undefined;
683
+ /**
684
+ * Retrieve a defined hook by name and position
685
+ *
686
+ * @param name
687
+ * @param pos
688
+ */
689
+ static get<N extends HookName, P extends HookPositions<N>>(name: N, pos: P): HookPos<N, P> | undefined;
690
+ /**
691
+ * Retrieve a defined hook by name and position the set args for callback
692
+ *
693
+ * @param name
694
+ * @param pos
695
+ */
696
+ static get<N extends HookName, P extends HookPositions<N>>(name: N, pos: P, ...args: HookArgs<N, P>): void;
697
+ /**
698
+ * Retrieve all defined hooks
699
+ *
700
+ * @param name
701
+ */
702
+ static getAll: () => Record<string, IHook> & HookRegistry;
703
+ /**
704
+ * Remove the defined hook
705
+ *
706
+ * @param name
707
+ */
708
+ static unset<N extends HookName, P extends HookPositions<N>>(name?: N | (string & {}), pos?: P): undefined;
709
+ /**
710
+ * Clear all the defined hooks
711
+ */
171
712
  static clear: () => void;
172
713
  }
173
714
  //#endregion
174
- //#region src/utils/encryption.d.ts
175
- declare class Encryption {
176
- private static readonly algorithm;
177
- private static getKey;
178
- static encrypt(value: string): string;
179
- static decrypt(payload: string): string;
180
- }
181
- //#endregion
182
- //#region src/utils/hash.d.ts
183
- declare class Hash {
184
- static make(value: string): Promise<string>;
185
- static verify(value: string, hashedValue: string): Promise<boolean>;
186
- static otp(digits?: number, label?: string, period?: number): TOTP;
187
- static totp(secret: string, label: string, issuer?: string, period?: number): TOTP;
188
- }
189
- //#endregion
190
- //#region src/utils/helpers.d.ts
191
- type AbstractModelConstructor<TModel = unknown> = abstract new (attributes?: Record<string, unknown>) => TModel;
192
- type ModelConstructor<TModel extends Model = Model> = AbstractModelConstructor<TModel> & Pick<ModelStatic<TModel>, keyof ModelStatic<TModel>>;
193
- interface ModelRegistry {}
194
- type ModelName = Extract<keyof ModelRegistry, string>;
195
- declare const perPage: (query: {
196
- limit?: number;
197
- perPage?: number;
198
- }) => number;
199
- declare function getModel<TName extends ModelName>(modelName: TName): Promise<ModelRegistry[TName]>;
200
- declare function getModel<TModel extends AbstractModelConstructor = ModelConstructor>(modelName: string): Promise<TModel>;
201
- //#endregion
202
- export { AbstractModelConstructor, AppException, ArkstackErrorPayload, ArkstackErrorShape, DotPathValue, Encryption, ErrorHandler, Exception, GlobalConfig, GlobalEnv, Hash, Hook, IHook, Logger, LoggerChalk, LoggerLog, LoggerParseSignature, ModelConstructor, ModelRegistry, RequestException, appUrl, bindGracefulShutdown, bootWithDetectedPort, config, createErrorPayload, env, getErrorLogger, getModel, getPrimaryError, getValidationErrors, importFile, isModelNotFoundError, isValidationError, loadPrototypes, logUnhandledError, nodeEnv, normalizeStatusCode, outputDir, perPage, renderError, serializeError, shouldHideStack, shouldLogError, toErrorShape };
203
- //# sourceMappingURL=index.d.ts.map
715
+ //#region src/EnvLoader.d.ts
716
+ /**
717
+ * Loads environment variables, reading the `.env` file on first access.
718
+ *
719
+ * The `.env` file is loaded lazily the first time a variable is read, so
720
+ * environment access never depends on a side-effect `import 'dotenv/config'`
721
+ * running first. Import ordering — which linters and bundlers may rewrite —
722
+ * could otherwise place an env-reading module before dotenv has populated
723
+ * `process.env`, leaving that module with default/stale values.
724
+ * `dotenv.config()` never overrides variables already set, so the lazy load is
725
+ * safe alongside other loaders.
726
+ */
727
+ declare class EnvLoader {
728
+ private loaded;
729
+ /**
730
+ * Load the `.env` file once.
731
+ *
732
+ * @returns
733
+ */
734
+ private ensureLoaded;
735
+ /**
736
+ * Read an environment variable, coercing booleans, numbers and `null`, and
737
+ * falling back to `defaultValue` when it is unset.
738
+ *
739
+ * @param name The variable name.
740
+ * @param defaultValue Returned when the variable is unset.
741
+ */
742
+ get<X = never, D = undefined, K extends string = string>(name: K, defaultValue?: D): EnvReturn<X, K, D>;
743
+ }
744
+ /**
745
+ * Shared environment loader backing {@link env}.
746
+ */
747
+ declare const envLoader: EnvLoader;
748
+ //#endregion
749
+ //#region src/ConfigLoader.d.ts
750
+ declare const CONFIG_KEY: unique symbol;
751
+ /**
752
+ * Loads and resolves application configuration from the config directory.
753
+ *
754
+ * Config modules are read once (lazily) from the output directory and cached on
755
+ * a global symbol, then queried by dot-path. A partial config object can also be
756
+ * merged in at runtime.
757
+ */
758
+ declare class ConfigLoader {
759
+ /**
760
+ * The cached config store, shared across instances via a global symbol.
761
+ */
762
+ private get store();
763
+ private set store(value);
764
+ /**
765
+ * Read and cache config modules from the config directory on first use.
766
+ */
767
+ private load;
768
+ /**
769
+ * Resolve the directory to load config modules from.
770
+ *
771
+ * Prefers an explicit `CONFIG_PATH`, then the environment-selected output
772
+ * directory. Falls back to the other build output (`dist` ⇄
773
+ * `.arkstack/build`) so config still loads if the selected directory is
774
+ * missing or transiently emptied — e.g. a concurrent rebuild (`clean: true`)
775
+ * during a test run.
776
+ */
777
+ private resolveConfigDir;
778
+ /**
779
+ * Resolve configuration: read a dot-path value, merge a partial config
780
+ * object, or return the whole config.
781
+ *
782
+ * @param key Dot-path to read, or an object to merge in.
783
+ * @param defaultValue Returned when a string key is not found.
784
+ */
785
+ resolve<X extends ConfigRegistry | unknown = unknown, P extends DotPath<X> | undefined = undefined>(key?: P, defaultValue?: any): any;
786
+ }
787
+ /**
788
+ * Shared config loader backing {@link config}.
789
+ */
790
+ declare const configLoader: ConfigLoader;
791
+ //#endregion
792
+ //#region src/tls.d.ts
793
+ interface TlsCredentials {
794
+ /** PEM-encoded private key. */
795
+ key: string;
796
+ /** PEM-encoded certificate. */
797
+ cert: string;
798
+ }
799
+ /**
800
+ * Generate (and cache) an in-memory self-signed TLS certificate for local HTTPS
801
+ * development. `selfsigned` is imported lazily so it's only loaded when secure
802
+ * dev mode is actually used.
803
+ *
804
+ * The certificate is not trusted by browsers (expect the usual self-signed
805
+ * warning); it exists only so the dev server can speak HTTPS.
806
+ *
807
+ * @param host The common name for the certificate (defaults to `localhost`).
808
+ */
809
+ declare const devTlsCredentials: (host?: string) => Promise<TlsCredentials>;
810
+ /**
811
+ * The machine's first non-internal IPv4 address — its address on the local
812
+ * network — or `undefined` when only loopback interfaces are available.
813
+ */
814
+ declare const localNetworkAddress: () => string | undefined;
815
+ //#endregion
816
+ export { AbstractModelConstructor, AppConfig, 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, TlsCredentials, UnionToIntersection, abort, abortIf, appKey, appUrl, assertFound, bindGracefulShutdown, bootWithDetectedPort, config, configLoader, createErrorPayload, devTlsCredentials, discoverCommands, env, envLoader, getErrorLogger, getModel, getPrimaryError, getValidationErrors, importFile, initializeGlobalContext, interopDefault, isClass, isModelNotFoundError, isValidationError, loadPrototypes, localNetworkAddress, logUnhandledError, nodeEnv, normalizeStatusCode, outputDir, perPage, rebuildOutput, renderError, resolveRuntimeDir, resolveRuntimeModule, serializeError, shouldHideStack, shouldLogError, toErrorShape, toOutputPath };