@arkstack/common 0.12.36 → 0.13.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/index.d.ts CHANGED
@@ -296,6 +296,22 @@ declare const rebuildOutput: () => Promise<void>;
296
296
  * const config = await importFile<AppConfig>('./config/app.ts')
297
297
  */
298
298
  declare const importFile: FileImporter;
299
+ /**
300
+ * Discover console command classes from the application's command directory.
301
+ *
302
+ * Commands are loaded straight from TypeScript source through {@link importFile}
303
+ * (jiti), so they are picked up without a build and reflect edits on every run.
304
+ * The built output is only used as a fallback when the source directory is
305
+ * absent — e.g. a production deploy that ships `dist` without `src`.
306
+ *
307
+ * This exists because musket's own glob discovery imports paths with native
308
+ * `import()`, which silently skips `.ts` files — the reason commands previously
309
+ * only appeared after a `build --dev` and never reflected later edits.
310
+ *
311
+ * @param subPath Command directory relative to the app root (src/dist aware).
312
+ * @returns The discovered command classes.
313
+ */
314
+ declare const discoverCommands: <T = unknown>(subPath?: string) => Promise<T[]>;
299
315
  /**
300
316
  * Resolves the default export from a module, handling both CJS and ESM interop.
301
317
  * In CJS modules, the default export is often the module itself (a function or object),
@@ -441,4 +457,4 @@ declare class Hook {
441
457
  static clear: () => void;
442
458
  }
443
459
  //#endregion
444
- export { AbstractModelConstructor, AppException, ArkstackErrorPayload, ArkstackErrorShape, CONFIG_KEY, 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, isClass, isModelNotFoundError, isValidationError, loadPrototypes, logUnhandledError, nodeEnv, normalizeStatusCode, outputDir, perPage, rebuildOutput, renderError, serializeError, shouldHideStack, shouldLogError, toErrorShape };
460
+ export { AbstractModelConstructor, AppException, ArkstackErrorPayload, ArkstackErrorShape, CONFIG_KEY, 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, discoverCommands, env, getErrorLogger, getModel, getPrimaryError, getValidationErrors, importFile, initializeGlobalContext, interopDefault, isClass, isModelNotFoundError, isValidationError, loadPrototypes, logUnhandledError, nodeEnv, normalizeStatusCode, outputDir, perPage, rebuildOutput, renderError, serializeError, shouldHideStack, shouldLogError, toErrorShape };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { C as importFile, D as rebuildOutput, E as outputDir, S as env, T as nodeEnv, _ as Hash, b as appUrl, c as abortIf, d as initializeGlobalContext, f as isClass, g as Exception, h as AppException, l as assertFound, m as RequestException, p as perPage, s as abort, u as getModel, v as Encryption, w as interopDefault, x as config, y as CONFIG_KEY } from "./utils-CFFiHKel.js";
1
+ import { C as env, D as outputDir, E as nodeEnv, O as rebuildOutput, 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, 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 CONFIG_KEY } from "./utils-yPBhsll_.js";
2
2
  import { Hook as Hook$1 } from "@arkstack/foundry";
3
3
  import { str } from "@h3ravel/support";
4
4
  import { Arkstack } from "@arkstack/contract";
@@ -481,4 +481,4 @@ var Hook = class {
481
481
  };
482
482
  };
483
483
  //#endregion
484
- export { AppException, CONFIG_KEY, Encryption, ErrorHandler, Exception, Hash, Hook, Logger, RequestException, abort, abortIf, appUrl, assertFound, bindGracefulShutdown, bootWithDetectedPort, config, createErrorPayload, env, getErrorLogger, getModel, getPrimaryError, getValidationErrors, importFile, initializeGlobalContext, interopDefault, isClass, isModelNotFoundError, isValidationError, loadPrototypes, logUnhandledError, nodeEnv, normalizeStatusCode, outputDir, perPage, rebuildOutput, renderError, serializeError, shouldHideStack, shouldLogError, toErrorShape };
484
+ export { AppException, CONFIG_KEY, Encryption, ErrorHandler, Exception, Hash, Hook, Logger, RequestException, abort, abortIf, 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, serializeError, shouldHideStack, shouldLogError, toErrorShape };
@@ -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-CFFiHKel.js";
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-yPBhsll_.js";
2
2
  export { Encryption, Hash, abort, abortIf, assertFound, callTraitMethods, crc32, getModel, getTraitMethods, initializeGlobalContext, isClass, perPage, trait, use, uses };
@@ -176,6 +176,67 @@ const importFile = async (filePath, userOptions, resolveOptions) => {
176
176
  }).import(resolvedPath, resolveOptions);
177
177
  };
178
178
  /**
179
+ * Picks the command class out of an imported module. Prefers the export named
180
+ * after the file (musket's discovery convention), then a default export, then
181
+ * the first exported constructor it finds.
182
+ *
183
+ * @param mod The imported module namespace.
184
+ * @param basename The file name without extension.
185
+ * @returns The resolved command class, or undefined when none is found.
186
+ */
187
+ const resolveCommandExport = (mod, basename) => {
188
+ const named = mod[basename];
189
+ if (typeof named === "function") return named;
190
+ if (typeof mod.default === "function") return mod.default;
191
+ return Object.values(mod).find((value) => typeof value === "function");
192
+ };
193
+ /**
194
+ * Discover console command classes from the application's command directory.
195
+ *
196
+ * Commands are loaded straight from TypeScript source through {@link importFile}
197
+ * (jiti), so they are picked up without a build and reflect edits on every run.
198
+ * The built output is only used as a fallback when the source directory is
199
+ * absent — e.g. a production deploy that ships `dist` without `src`.
200
+ *
201
+ * This exists because musket's own glob discovery imports paths with native
202
+ * `import()`, which silently skips `.ts` files — the reason commands previously
203
+ * only appeared after a `build --dev` and never reflected later edits.
204
+ *
205
+ * @param subPath Command directory relative to the app root (src/dist aware).
206
+ * @returns The discovered command classes.
207
+ */
208
+ const discoverCommands = async (subPath = path.join("app", "console", "commands")) => {
209
+ const root = Arkstack.rootDir();
210
+ const dist = path.relative(root, outputDir());
211
+ const candidateDirs = [path.join(root, "src", subPath), path.join(root, dist, subPath)];
212
+ let commandsDir;
213
+ let files = [];
214
+ for (const dir of candidateDirs) try {
215
+ const entries = readdirSync(dir, { withFileTypes: true }).filter((file) => file.isFile() && [
216
+ ".ts",
217
+ ".js",
218
+ ".mjs"
219
+ ].includes(path.extname(file.name)));
220
+ if (entries.length > 0) {
221
+ commandsDir = dir;
222
+ files = entries;
223
+ break;
224
+ }
225
+ } catch {}
226
+ if (!commandsDir) return [];
227
+ const commands = [];
228
+ for (const file of files) {
229
+ const basename = path.basename(file.name, path.extname(file.name));
230
+ try {
231
+ const command = resolveCommandExport(await importFile(path.join(commandsDir, file.name)), basename);
232
+ if (command) commands.push(command);
233
+ } catch (error) {
234
+ console.error(`[arkstack] Failed to load command "${file.name}":`, error);
235
+ }
236
+ }
237
+ return commands;
238
+ };
239
+ /**
179
240
  * Resolves the default export from a module, handling both CJS and ESM interop.
180
241
  * In CJS modules, the default export is often the module itself (a function or object),
181
242
  * while in ESM the default is nested under the `default` property.
@@ -616,4 +677,4 @@ function uses(instance, trait) {
616
677
  return false;
617
678
  }
618
679
  //#endregion
619
- export { importFile as C, rebuildOutput as D, outputDir as E, env as S, nodeEnv 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, 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, interopDefault as w, config as x, CONFIG_KEY as y };
680
+ export { env as C, outputDir as D, nodeEnv as E, rebuildOutput as O, 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, 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 as x, CONFIG_KEY as y };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arkstack/common",
3
- "version": "0.12.36",
3
+ "version": "0.13.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",
@@ -41,9 +41,9 @@
41
41
  },
42
42
  "peerDependencies": {
43
43
  "@h3ravel/support": "^2.1.4",
44
- "arkormx": "^2.9.0",
45
- "@arkstack/foundry": "^0.12.36",
46
- "@arkstack/contract": "^0.12.36"
44
+ "arkormx": "^2.9.2",
45
+ "@arkstack/foundry": "^0.13.0",
46
+ "@arkstack/contract": "^0.13.0"
47
47
  },
48
48
  "scripts": {
49
49
  "build": "tsdown --config-loader unrun",