@vlynk-studios/nodulus-core 1.2.0 → 1.2.5
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/CHANGELOG.md +27 -0
- package/README.md +25 -0
- package/dist/cli/index.js +534 -370
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +22 -31
- package/dist/index.js +114 -93
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,21 +1,5 @@
|
|
|
1
|
-
import { RequestHandler,
|
|
1
|
+
import { RequestHandler, Application } from 'express';
|
|
2
2
|
|
|
3
|
-
interface ControllerEntry {
|
|
4
|
-
name: string;
|
|
5
|
-
path: string;
|
|
6
|
-
prefix: string;
|
|
7
|
-
middlewares: RequestHandler[];
|
|
8
|
-
router?: Router;
|
|
9
|
-
enabled: boolean;
|
|
10
|
-
}
|
|
11
|
-
interface ModuleEntry {
|
|
12
|
-
name: string;
|
|
13
|
-
path: string;
|
|
14
|
-
indexPath: string;
|
|
15
|
-
imports: string[];
|
|
16
|
-
exports: string[];
|
|
17
|
-
controllers: ControllerEntry[];
|
|
18
|
-
}
|
|
19
3
|
type LogLevel = 'debug' | 'info' | 'warn' | 'error';
|
|
20
4
|
/**
|
|
21
5
|
* Function that receives a log event from Nodulus.
|
|
@@ -93,9 +77,24 @@ interface SchemaEntry {
|
|
|
93
77
|
}
|
|
94
78
|
/** Discriminated union for all file-level identifier entries. */
|
|
95
79
|
type FileEntry = ServiceEntry | RepositoryEntry | SchemaEntry;
|
|
80
|
+
interface NitsConfig {
|
|
81
|
+
/**
|
|
82
|
+
* Custom similarity threshold (0.0 to 1.0).
|
|
83
|
+
* If omitted, a dynamic threshold based on module size is used.
|
|
84
|
+
*/
|
|
85
|
+
similarityThreshold?: number;
|
|
86
|
+
/** Whether to enable NITS identity tracking. Default: true. */
|
|
87
|
+
enabled?: boolean;
|
|
88
|
+
/** Custom path to the NITS registry file. Default: '.nodulus/registry.json'. */
|
|
89
|
+
registryPath?: string;
|
|
90
|
+
}
|
|
96
91
|
interface CreateAppOptions {
|
|
97
92
|
/** Glob pointing to module folders. Default: 'src/modules/*'. */
|
|
98
93
|
modules?: string;
|
|
94
|
+
/** Glob pointing to domain folders (v2.0.0+). Default: undefined. */
|
|
95
|
+
domains?: string;
|
|
96
|
+
/** Glob pointing to shared global folders (v2.0.0+). Default: undefined. */
|
|
97
|
+
shared?: string;
|
|
99
98
|
/** Global route prefix. Example: '/api/v1'. Default: ''. */
|
|
100
99
|
prefix?: string;
|
|
101
100
|
/** Folder aliases beyond the auto-generated @modules/* entries. Default: {}. */
|
|
@@ -122,16 +121,8 @@ interface CreateAppOptions {
|
|
|
122
121
|
* Default: 'info' (debug is off unless explicitly set).
|
|
123
122
|
*/
|
|
124
123
|
logLevel?: LogLevel;
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
interface ResolvedConfig {
|
|
128
|
-
modules: string;
|
|
129
|
-
prefix: string;
|
|
130
|
-
aliases: Record<string, string>;
|
|
131
|
-
strict: boolean;
|
|
132
|
-
resolveAliases: boolean;
|
|
133
|
-
logger: LogHandler;
|
|
134
|
-
logLevel: LogLevel;
|
|
124
|
+
/** NITS (Nodulus Integrated Tracking System) configuration. */
|
|
125
|
+
nits?: NitsConfig;
|
|
135
126
|
}
|
|
136
127
|
/** A module as it appears in the NodularApp result after bootstrap. */
|
|
137
128
|
interface RegisteredModule {
|
|
@@ -184,6 +175,8 @@ interface GetAliasesOptions {
|
|
|
184
175
|
absolute?: boolean;
|
|
185
176
|
}
|
|
186
177
|
|
|
178
|
+
type ModuleRegistration = RegisteredModule;
|
|
179
|
+
type FeatureRegistration = FileEntry;
|
|
187
180
|
/**
|
|
188
181
|
* Returns a read-only view of the registry active in the current async context.
|
|
189
182
|
*
|
|
@@ -193,14 +186,12 @@ interface GetAliasesOptions {
|
|
|
193
186
|
*/
|
|
194
187
|
declare const getRegistry: () => NodulusRegistryAdvanced;
|
|
195
188
|
|
|
196
|
-
type NodulusErrorCode = "MODULE_NOT_FOUND" | "DUPLICATE_MODULE" | "MISSING_IMPORT" | "UNDECLARED_IMPORT" | "CIRCULAR_DEPENDENCY" | "EXPORT_MISMATCH" | "INVALID_CONTROLLER" | "ALIAS_NOT_FOUND" | "DUPLICATE_ALIAS" | "DUPLICATE_BOOTSTRAP" | "REGISTRY_MISSING_CONTEXT" | "INVALID_MODULE_DECLARATION" | "DUPLICATE_SERVICE" | "DUPLICATE_REPOSITORY" | "DUPLICATE_SCHEMA" | "INVALID_ESM_ENV";
|
|
189
|
+
type NodulusErrorCode = "MODULE_NOT_FOUND" | "DUPLICATE_MODULE" | "MISSING_IMPORT" | "UNDECLARED_IMPORT" | "CIRCULAR_DEPENDENCY" | "EXPORT_MISMATCH" | "INVALID_CONTROLLER" | "ALIAS_NOT_FOUND" | "DUPLICATE_ALIAS" | "DUPLICATE_BOOTSTRAP" | "REGISTRY_MISSING_CONTEXT" | "INVALID_MODULE_DECLARATION" | "DUPLICATE_SERVICE" | "DUPLICATE_REPOSITORY" | "DUPLICATE_SCHEMA" | "INVALID_ESM_ENV" | "CLI_ERROR";
|
|
197
190
|
declare class NodulusError extends Error {
|
|
198
191
|
readonly code: NodulusErrorCode;
|
|
199
192
|
readonly details?: string;
|
|
200
193
|
constructor(code: NodulusErrorCode, message: string, details?: string);
|
|
201
194
|
}
|
|
202
|
-
/** @deprecated — not used internally. Messages are defined at each throw site. */
|
|
203
|
-
declare const ERROR_MESSAGES: Record<NodulusErrorCode, string>;
|
|
204
195
|
|
|
205
196
|
declare function Module(name: string, options?: ModuleOptions): void;
|
|
206
197
|
|
|
@@ -264,4 +255,4 @@ declare function createApp(app: Application, options?: CreateAppOptions): Promis
|
|
|
264
255
|
|
|
265
256
|
declare function getAliases(options?: GetAliasesOptions): Promise<Record<string, string>>;
|
|
266
257
|
|
|
267
|
-
export { Controller, type
|
|
258
|
+
export { Controller, type ControllerOptions, type CreateAppOptions, type FeatureRegistration, type GetAliasesOptions, type LogHandler, type LogLevel, Module, type ModuleOptions, type ModuleRegistration, type MountedRoute, type NodulusApp, type NodulusConfig, NodulusError, type NodulusErrorCode, type NodulusRegistry, type NodulusRegistryAdvanced, type RegisteredModule, Repository, type RepositoryOptions, Schema, type SchemaOptions, Service, type ServiceOptions, createApp, getAliases, getRegistry };
|
package/dist/index.js
CHANGED
|
@@ -12,24 +12,36 @@ var NodulusError = class extends Error {
|
|
|
12
12
|
this.details = details;
|
|
13
13
|
}
|
|
14
14
|
};
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
15
|
+
|
|
16
|
+
// src/core/utils/cycle-detector.ts
|
|
17
|
+
function findCircularDependencies(dependencyMap) {
|
|
18
|
+
const cycles = [];
|
|
19
|
+
const visited = /* @__PURE__ */ new Set();
|
|
20
|
+
const recStack = /* @__PURE__ */ new Set();
|
|
21
|
+
const path10 = [];
|
|
22
|
+
const dfs = (node) => {
|
|
23
|
+
visited.add(node);
|
|
24
|
+
recStack.add(node);
|
|
25
|
+
path10.push(node);
|
|
26
|
+
const deps = dependencyMap.get(node) || [];
|
|
27
|
+
for (const neighbor of deps) {
|
|
28
|
+
if (!visited.has(neighbor)) {
|
|
29
|
+
dfs(neighbor);
|
|
30
|
+
} else if (recStack.has(neighbor)) {
|
|
31
|
+
const cycleStart = path10.indexOf(neighbor);
|
|
32
|
+
cycles.push([...path10.slice(cycleStart), neighbor]);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
recStack.delete(node);
|
|
36
|
+
path10.pop();
|
|
37
|
+
};
|
|
38
|
+
for (const node of dependencyMap.keys()) {
|
|
39
|
+
if (!visited.has(node)) {
|
|
40
|
+
dfs(node);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return cycles;
|
|
44
|
+
}
|
|
33
45
|
|
|
34
46
|
// src/core/registry.ts
|
|
35
47
|
var toRegisteredModule = (entry) => ({
|
|
@@ -71,32 +83,11 @@ function createRegistry() {
|
|
|
71
83
|
return graph;
|
|
72
84
|
},
|
|
73
85
|
findCircularDependencies() {
|
|
74
|
-
const
|
|
75
|
-
const
|
|
76
|
-
|
|
77
|
-
const path10 = [];
|
|
78
|
-
const dfs = (node) => {
|
|
79
|
-
visited.add(node);
|
|
80
|
-
recStack.add(node);
|
|
81
|
-
path10.push(node);
|
|
82
|
-
const deps = modules.get(node)?.imports || [];
|
|
83
|
-
for (const neighbor of deps) {
|
|
84
|
-
if (!visited.has(neighbor)) {
|
|
85
|
-
dfs(neighbor);
|
|
86
|
-
} else if (recStack.has(neighbor)) {
|
|
87
|
-
const cycleStart = path10.indexOf(neighbor);
|
|
88
|
-
cycles.push([...path10.slice(cycleStart), neighbor]);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
recStack.delete(node);
|
|
92
|
-
path10.pop();
|
|
93
|
-
};
|
|
94
|
-
for (const node of modules.keys()) {
|
|
95
|
-
if (!visited.has(node)) {
|
|
96
|
-
dfs(node);
|
|
97
|
-
}
|
|
86
|
+
const dependencyMap = /* @__PURE__ */ new Map();
|
|
87
|
+
for (const [name, entry] of modules.entries()) {
|
|
88
|
+
dependencyMap.set(name, entry.imports);
|
|
98
89
|
}
|
|
99
|
-
return
|
|
90
|
+
return findCircularDependencies(dependencyMap);
|
|
100
91
|
},
|
|
101
92
|
registerModule(name, options, dirPath, indexPath) {
|
|
102
93
|
if (modules.has(name)) {
|
|
@@ -366,7 +357,7 @@ function Schema(name, options = {}) {
|
|
|
366
357
|
// src/bootstrap/createApp.ts
|
|
367
358
|
import fs2 from "fs";
|
|
368
359
|
import path8 from "path";
|
|
369
|
-
import { pathToFileURL as
|
|
360
|
+
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
370
361
|
import fg from "fast-glob";
|
|
371
362
|
|
|
372
363
|
// src/core/config.ts
|
|
@@ -432,25 +423,27 @@ function createLogger(handler, minLevel) {
|
|
|
432
423
|
var defaultStrict = typeof process !== "undefined" && process.env?.NODE_ENV !== "production";
|
|
433
424
|
var DEFAULTS = {
|
|
434
425
|
modules: "src/modules/*",
|
|
426
|
+
domains: void 0,
|
|
427
|
+
shared: void 0,
|
|
435
428
|
prefix: "",
|
|
436
429
|
aliases: {},
|
|
437
430
|
strict: defaultStrict,
|
|
438
431
|
resolveAliases: true,
|
|
439
432
|
logger: defaultLogHandler,
|
|
440
|
-
logLevel: resolveLogLevel()
|
|
433
|
+
logLevel: resolveLogLevel(),
|
|
434
|
+
nits: {
|
|
435
|
+
enabled: true,
|
|
436
|
+
similarityThreshold: void 0,
|
|
437
|
+
// Use dynamic by default
|
|
438
|
+
registryPath: ".nodulus/registry.json"
|
|
439
|
+
}
|
|
441
440
|
};
|
|
442
441
|
var loadConfig = async (options = {}) => {
|
|
443
442
|
const cwd = process.cwd();
|
|
444
443
|
let fileConfig = {};
|
|
445
444
|
const tsPath = path7.join(cwd, "nodulus.config.ts");
|
|
446
445
|
const jsPath = path7.join(cwd, "nodulus.config.js");
|
|
447
|
-
const
|
|
448
|
-
const hasTsLoader = process.execArgv.some((arg) => arg.includes("ts-node") || arg.includes("tsx")) || process._preload_modules?.some((m) => m.includes("ts-node") || m.includes("tsx"));
|
|
449
|
-
const candidates = [];
|
|
450
|
-
if (!isProduction || hasTsLoader) {
|
|
451
|
-
candidates.push(tsPath);
|
|
452
|
-
}
|
|
453
|
-
candidates.push(jsPath);
|
|
446
|
+
const candidates = [tsPath, jsPath];
|
|
454
447
|
let configPathToLoad = null;
|
|
455
448
|
for (const candidate of candidates) {
|
|
456
449
|
if (fs.existsSync(candidate)) {
|
|
@@ -477,6 +470,8 @@ var loadConfig = async (options = {}) => {
|
|
|
477
470
|
}
|
|
478
471
|
return {
|
|
479
472
|
modules: options.modules ?? fileConfig.modules ?? DEFAULTS.modules,
|
|
473
|
+
domains: options.domains ?? fileConfig.domains ?? DEFAULTS.domains,
|
|
474
|
+
shared: options.shared ?? fileConfig.shared ?? DEFAULTS.shared,
|
|
480
475
|
prefix: options.prefix ?? fileConfig.prefix ?? DEFAULTS.prefix,
|
|
481
476
|
aliases: {
|
|
482
477
|
...DEFAULTS.aliases,
|
|
@@ -487,25 +482,33 @@ var loadConfig = async (options = {}) => {
|
|
|
487
482
|
strict: options.strict ?? fileConfig.strict ?? DEFAULTS.strict,
|
|
488
483
|
resolveAliases: options.resolveAliases ?? fileConfig.resolveAliases ?? DEFAULTS.resolveAliases,
|
|
489
484
|
logger: options.logger ?? fileConfig.logger ?? DEFAULTS.logger,
|
|
490
|
-
logLevel: resolveLogLevel(options.logLevel ?? fileConfig.logLevel)
|
|
485
|
+
logLevel: resolveLogLevel(options.logLevel ?? fileConfig.logLevel),
|
|
486
|
+
nits: {
|
|
487
|
+
enabled: options.nits?.enabled ?? fileConfig.nits?.enabled ?? DEFAULTS.nits.enabled,
|
|
488
|
+
similarityThreshold: options.nits?.similarityThreshold ?? fileConfig.nits?.similarityThreshold ?? DEFAULTS.nits.similarityThreshold,
|
|
489
|
+
registryPath: options.nits?.registryPath ?? fileConfig.nits?.registryPath ?? DEFAULTS.nits.registryPath
|
|
490
|
+
}
|
|
491
491
|
};
|
|
492
492
|
};
|
|
493
493
|
|
|
494
494
|
// src/aliases/resolver.ts
|
|
495
495
|
import { register } from "module";
|
|
496
|
-
import { pathToFileURL as pathToFileURL2 } from "url";
|
|
497
496
|
var isHookRegistered = false;
|
|
498
|
-
|
|
497
|
+
var registrationPromise = null;
|
|
498
|
+
async function activateAliasResolver(moduleAliases, folderAliases, log) {
|
|
499
499
|
if (isHookRegistered) return;
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
500
|
+
if (registrationPromise) return registrationPromise;
|
|
501
|
+
registrationPromise = (async () => {
|
|
502
|
+
try {
|
|
503
|
+
const combinedAliases = { ...moduleAliases, ...folderAliases };
|
|
504
|
+
for (const [alias, target] of Object.entries(folderAliases)) {
|
|
505
|
+
log.debug(`Alias registered: ${alias} \u2192 ${target}`, { alias, target, source: "config" });
|
|
506
|
+
}
|
|
507
|
+
for (const [alias, target] of Object.entries(moduleAliases)) {
|
|
508
|
+
log.debug(`Alias registered: ${alias} \u2192 ${target}`, { alias, target, source: "module" });
|
|
509
|
+
}
|
|
510
|
+
const serialisedAliases = JSON.stringify(combinedAliases);
|
|
511
|
+
const loaderCode = `
|
|
509
512
|
import { pathToFileURL } from 'node:url';
|
|
510
513
|
import path from 'node:path';
|
|
511
514
|
|
|
@@ -513,43 +516,57 @@ const aliases = ${serialisedAliases};
|
|
|
513
516
|
|
|
514
517
|
export async function resolve(specifier, context, nextResolve) {
|
|
515
518
|
for (const alias of Object.keys(aliases)) {
|
|
516
|
-
if (
|
|
519
|
+
if (alias.endsWith('/*')) {
|
|
520
|
+
const baseAlias = alias.slice(0, -2);
|
|
521
|
+
if (specifier.startsWith(baseAlias + '/')) {
|
|
522
|
+
const baseTarget = aliases[alias].slice(0, -2);
|
|
523
|
+
const subPath = specifier.slice(baseAlias.length + 1);
|
|
524
|
+
const resolvedPath = path.resolve(baseTarget, subPath);
|
|
525
|
+
return nextResolve(pathToFileURL(resolvedPath).href, context);
|
|
526
|
+
}
|
|
527
|
+
} else if (specifier === alias) {
|
|
517
528
|
const target = aliases[alias];
|
|
518
|
-
|
|
519
|
-
return nextResolve(pathToFileURL(path.resolve(resolvedPath)).href, context);
|
|
529
|
+
return nextResolve(pathToFileURL(path.resolve(target)).href, context);
|
|
520
530
|
}
|
|
521
531
|
}
|
|
522
532
|
return nextResolve(specifier, context);
|
|
523
533
|
}
|
|
524
534
|
`;
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
}
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
535
|
+
const dataUrl = `data:text/javascript,${encodeURIComponent(loaderCode)}`;
|
|
536
|
+
const parentUrl = import.meta.url;
|
|
537
|
+
if (typeof register === "function") {
|
|
538
|
+
register(dataUrl, { parentURL: parentUrl });
|
|
539
|
+
isHookRegistered = true;
|
|
540
|
+
log.info(`ESM alias hook activated (${Object.keys(combinedAliases).length} alias(es))`, {
|
|
541
|
+
aliasCount: Object.keys(combinedAliases).length
|
|
542
|
+
});
|
|
543
|
+
} else {
|
|
544
|
+
log.warn("ESM alias hook could not be registered \u2014 upgrade to Node.js >= 20.6.0 for runtime alias support", {
|
|
545
|
+
nodeVersion: process.version
|
|
546
|
+
});
|
|
547
|
+
}
|
|
548
|
+
} catch (err) {
|
|
549
|
+
log.warn("ESM alias hook registration threw an unexpected error \u2014 aliases may not resolve at runtime", {
|
|
550
|
+
error: err?.message ?? String(err)
|
|
537
551
|
});
|
|
552
|
+
} finally {
|
|
553
|
+
registrationPromise = null;
|
|
538
554
|
}
|
|
539
|
-
}
|
|
540
|
-
|
|
541
|
-
error: err?.message ?? String(err)
|
|
542
|
-
});
|
|
543
|
-
}
|
|
555
|
+
})();
|
|
556
|
+
return registrationPromise;
|
|
544
557
|
}
|
|
545
558
|
|
|
546
559
|
// src/aliases/cache.ts
|
|
547
|
-
var
|
|
560
|
+
var globalAliasCache = {};
|
|
548
561
|
function updateAliasCache(aliases) {
|
|
549
|
-
|
|
562
|
+
globalAliasCache = { ...aliases };
|
|
550
563
|
}
|
|
551
564
|
function getAliasCache() {
|
|
552
|
-
|
|
565
|
+
const activeRegistry = registryContext.getStore();
|
|
566
|
+
if (activeRegistry) {
|
|
567
|
+
return activeRegistry.getAllAliases();
|
|
568
|
+
}
|
|
569
|
+
return globalAliasCache;
|
|
553
570
|
}
|
|
554
571
|
|
|
555
572
|
// src/bootstrap/createApp.ts
|
|
@@ -585,6 +602,9 @@ async function createApp(app, options = {}) {
|
|
|
585
602
|
try {
|
|
586
603
|
const config = await loadConfig(options);
|
|
587
604
|
const log = createLogger(config.logger, config.logLevel);
|
|
605
|
+
if (config.domains || config.shared) {
|
|
606
|
+
log.warn("Infrastructure (domains/shared) is not yet supported in v1.2.x. These keys in configuration will be ignored until v2.0.0.");
|
|
607
|
+
}
|
|
588
608
|
log.info("Bootstrap started", {
|
|
589
609
|
modules: pc2.cyan(config.modules),
|
|
590
610
|
prefix: pc2.cyan(config.prefix || "(none)"),
|
|
@@ -623,14 +643,16 @@ async function createApp(app, options = {}) {
|
|
|
623
643
|
for (const mod of resolvedModules) {
|
|
624
644
|
const modName = path8.basename(mod.dirPath);
|
|
625
645
|
const aliasKey = `@modules/${modName}`;
|
|
626
|
-
pureModuleAliases[aliasKey] = mod.
|
|
627
|
-
|
|
646
|
+
pureModuleAliases[aliasKey] = mod.indexPath;
|
|
647
|
+
pureModuleAliases[`${aliasKey}/*`] = `${mod.dirPath}/*`;
|
|
648
|
+
registry.registerAlias(aliasKey, mod.indexPath);
|
|
649
|
+
registry.registerAlias(`${aliasKey}/*`, `${mod.dirPath}/*`);
|
|
628
650
|
}
|
|
629
|
-
activateAliasResolver(pureModuleAliases, config.aliases, log);
|
|
651
|
+
await activateAliasResolver(pureModuleAliases, config.aliases, log);
|
|
630
652
|
updateAliasCache(registry.getAllAliases());
|
|
631
653
|
}
|
|
632
654
|
for (const mod of resolvedModules) {
|
|
633
|
-
const imported = await import(
|
|
655
|
+
const imported = await import(pathToFileURL2(mod.indexPath).href);
|
|
634
656
|
const allRegistered = registry.getAllModules();
|
|
635
657
|
const registeredMod = allRegistered.find((m) => path8.normalize(m.path) === path8.normalize(mod.dirPath));
|
|
636
658
|
if (!registeredMod) {
|
|
@@ -712,7 +734,7 @@ async function createApp(app, options = {}) {
|
|
|
712
734
|
file = path8.normalize(file);
|
|
713
735
|
let imported;
|
|
714
736
|
try {
|
|
715
|
-
imported = await import(
|
|
737
|
+
imported = await import(pathToFileURL2(file).href);
|
|
716
738
|
} catch (err) {
|
|
717
739
|
throw new NodulusError(
|
|
718
740
|
"INVALID_CONTROLLER",
|
|
@@ -867,7 +889,6 @@ async function getAliases(options = {}) {
|
|
|
867
889
|
}
|
|
868
890
|
export {
|
|
869
891
|
Controller,
|
|
870
|
-
ERROR_MESSAGES,
|
|
871
892
|
Module,
|
|
872
893
|
NodulusError,
|
|
873
894
|
Repository,
|