silgi 0.34.5 → 0.34.6
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/cli/build.mjs +222 -221
- package/dist/cli/index.mjs +1 -1
- package/package.json +1 -1
package/dist/cli/build.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import { consola } from 'consola';
|
|
|
2
2
|
import { createHooks, createDebugger } from 'hookable';
|
|
3
3
|
import { resolve, join, relative, extname, basename, dirname, isAbsolute } from 'pathe';
|
|
4
4
|
import { useSilgiCLI, replaceRuntimeValues, silgiCLICtx, autoImportTypes } from 'silgi';
|
|
5
|
-
import { isPresents, addTemplate, addCoreFile, relativeWithDot, hash, resolveAlias, directoryToURL,
|
|
5
|
+
import { isPresents, addTemplate, addCoreFile, relativeWithDot, hash, removeExtension, resolveAlias, directoryToURL, addImports, baseHeaderBannerComment, writeFile, normalizeTemplate, useLogger, resolveSilgiPath, hasSilgiModule, genEnsureSafeVar, toArray, isDirectory } from 'silgi/kit';
|
|
6
6
|
import { runtimeDir } from 'silgi/runtime/meta';
|
|
7
7
|
import { scanExports, createUnimport, toExports } from 'unimport';
|
|
8
8
|
import * as p from '@clack/prompts';
|
|
@@ -14,7 +14,7 @@ import { h as hasInstalledModule } from './compatibility.mjs';
|
|
|
14
14
|
import { fileURLToPath } from 'node:url';
|
|
15
15
|
import { defu } from 'defu';
|
|
16
16
|
import { resolveModuleURL } from 'exsolve';
|
|
17
|
-
import {
|
|
17
|
+
import { withTrailingSlash, isRelative } from 'ufo';
|
|
18
18
|
import { readFile, readdir } from 'node:fs/promises';
|
|
19
19
|
import { globby } from 'globby';
|
|
20
20
|
import ignore from 'ignore';
|
|
@@ -473,221 +473,6 @@ async function installModule(moduleToInstall, silgi = useSilgiCLI(), inlineOptio
|
|
|
473
473
|
}
|
|
474
474
|
}
|
|
475
475
|
|
|
476
|
-
const MissingModuleMatcher = /Cannot find module\s+['"]?([^'")\s]+)['"]?/i;
|
|
477
|
-
async function _resolveSilgiModule(silgiModule, silgi) {
|
|
478
|
-
let resolvedModulePath;
|
|
479
|
-
let buildTimeModuleMeta = {};
|
|
480
|
-
const jiti = createJiti(silgi.options.rootDir, {
|
|
481
|
-
alias: silgi.options.alias,
|
|
482
|
-
fsCache: true,
|
|
483
|
-
moduleCache: true
|
|
484
|
-
});
|
|
485
|
-
if (typeof silgiModule === "string") {
|
|
486
|
-
silgiModule = resolveAlias(silgiModule, silgi.options.alias);
|
|
487
|
-
if (isRelative(silgiModule)) {
|
|
488
|
-
silgiModule = resolve(silgi.options.rootDir, silgiModule);
|
|
489
|
-
}
|
|
490
|
-
try {
|
|
491
|
-
const src = resolveModuleURL(silgiModule, {
|
|
492
|
-
from: silgi.options.modulesDir.map((m) => directoryToURL(m.replace(/\/node_modules\/?$/, "/"))),
|
|
493
|
-
suffixes: ["silgi", "silgi/index", "module", "module/index", "", "index"],
|
|
494
|
-
extensions: [".js", ".mjs", ".cjs", ".ts", ".mts", ".cts"]
|
|
495
|
-
// Maybe add https://github.com/unjs/exsolve/blob/dfff3e9bbc4a3a173a2d56b9b9ff731ab15598be/src/resolve.ts#L7
|
|
496
|
-
// conditions: silgi.options.conditions,
|
|
497
|
-
});
|
|
498
|
-
resolvedModulePath = fileURLToPath(src);
|
|
499
|
-
const resolvedSilgiModule = await jiti.import(src, { default: true });
|
|
500
|
-
if (typeof resolvedSilgiModule !== "function") {
|
|
501
|
-
throw new TypeError(`Nuxt module should be a function: ${silgiModule}.`);
|
|
502
|
-
}
|
|
503
|
-
silgiModule = await jiti.import(src, {
|
|
504
|
-
default: true,
|
|
505
|
-
conditions: silgi.options.conditions
|
|
506
|
-
});
|
|
507
|
-
const moduleMetadataPath = new URL("module.json", src);
|
|
508
|
-
if (existsSync(moduleMetadataPath)) {
|
|
509
|
-
buildTimeModuleMeta = JSON.parse(await promises.readFile(moduleMetadataPath, "utf-8"));
|
|
510
|
-
} else {
|
|
511
|
-
if (typeof silgiModule === "function") {
|
|
512
|
-
const meta = await silgiModule.getMeta?.();
|
|
513
|
-
const _exports = await scanExports(resolvedModulePath, true);
|
|
514
|
-
buildTimeModuleMeta = {
|
|
515
|
-
...meta,
|
|
516
|
-
exports: _exports.map(({ from, ...rest }) => rest)
|
|
517
|
-
};
|
|
518
|
-
}
|
|
519
|
-
}
|
|
520
|
-
} catch (error) {
|
|
521
|
-
const code = error.code;
|
|
522
|
-
if (code === "MODULE_NOT_FOUND" || code === "ERR_PACKAGE_PATH_NOT_EXPORTED" || code === "ERR_MODULE_NOT_FOUND" || code === "ERR_UNSUPPORTED_DIR_IMPORT" || code === "ENOTDIR") {
|
|
523
|
-
throw new TypeError(`Could not load \`${silgiModule}\`. Is it installed?`);
|
|
524
|
-
}
|
|
525
|
-
if (code === "MODULE_NOT_FOUND" || code === "ERR_MODULE_NOT_FOUND") {
|
|
526
|
-
const module = MissingModuleMatcher.exec(error.message)?.[1];
|
|
527
|
-
if (module && !module.includes(silgiModule)) {
|
|
528
|
-
throw new TypeError(`Error while importing module \`${silgiModule}\`: ${error}`);
|
|
529
|
-
}
|
|
530
|
-
}
|
|
531
|
-
}
|
|
532
|
-
}
|
|
533
|
-
if (!buildTimeModuleMeta) {
|
|
534
|
-
throw new Error(`Module ${silgiModule} is not a valid Silgi module`);
|
|
535
|
-
}
|
|
536
|
-
if (typeof silgiModule === "function") {
|
|
537
|
-
if (!buildTimeModuleMeta.configKey) {
|
|
538
|
-
const meta = await silgiModule.getMeta?.();
|
|
539
|
-
buildTimeModuleMeta = {
|
|
540
|
-
...meta,
|
|
541
|
-
exports: []
|
|
542
|
-
};
|
|
543
|
-
}
|
|
544
|
-
if (silgi.scanModules.some((m) => m.meta?.configKey === buildTimeModuleMeta.configKey)) {
|
|
545
|
-
throw new Error(`Module with key \`${buildTimeModuleMeta.configKey}\` already exists`);
|
|
546
|
-
}
|
|
547
|
-
const options = await silgiModule.getOptions?.() || {};
|
|
548
|
-
if (options) {
|
|
549
|
-
silgi.options._c12.config[buildTimeModuleMeta.configKey] = defu(
|
|
550
|
-
silgi.options._c12.config[buildTimeModuleMeta.configKey] || {},
|
|
551
|
-
options || {}
|
|
552
|
-
);
|
|
553
|
-
} else {
|
|
554
|
-
throw new TypeError(`Could not load \`${silgiModule}\`. Is it installed?`);
|
|
555
|
-
}
|
|
556
|
-
silgi.scanModules.push({
|
|
557
|
-
meta: buildTimeModuleMeta,
|
|
558
|
-
entryPath: resolvedModulePath || void 0,
|
|
559
|
-
installed: false,
|
|
560
|
-
options,
|
|
561
|
-
module: silgiModule
|
|
562
|
-
});
|
|
563
|
-
}
|
|
564
|
-
}
|
|
565
|
-
async function scanModules$1(silgi) {
|
|
566
|
-
const _modules = [
|
|
567
|
-
...silgi.options._modules,
|
|
568
|
-
...silgi.options.modules
|
|
569
|
-
];
|
|
570
|
-
for await (const mod of _modules) {
|
|
571
|
-
await _resolveSilgiModule(mod, silgi);
|
|
572
|
-
}
|
|
573
|
-
const moduleMap = new Map(
|
|
574
|
-
silgi.scanModules.map((m) => [m.meta?.configKey, m])
|
|
575
|
-
);
|
|
576
|
-
const graphData = createDependencyGraph(silgi.scanModules);
|
|
577
|
-
const sortedKeys = topologicalSort(graphData);
|
|
578
|
-
const modules = sortedKeys.map((key) => moduleMap.get(key)).filter((module) => Boolean(module));
|
|
579
|
-
silgi.scanModules = modules;
|
|
580
|
-
}
|
|
581
|
-
function createDependencyGraph(modules) {
|
|
582
|
-
const graph = /* @__PURE__ */ new Map();
|
|
583
|
-
const inDegree = /* @__PURE__ */ new Map();
|
|
584
|
-
modules.forEach((module) => {
|
|
585
|
-
const key = module.meta?.configKey;
|
|
586
|
-
if (key) {
|
|
587
|
-
graph.set(key, /* @__PURE__ */ new Set());
|
|
588
|
-
inDegree.set(key, 0);
|
|
589
|
-
}
|
|
590
|
-
});
|
|
591
|
-
modules.forEach((module) => {
|
|
592
|
-
const key = module.meta?.configKey;
|
|
593
|
-
if (!key) {
|
|
594
|
-
return;
|
|
595
|
-
}
|
|
596
|
-
const requiredDeps = module.meta?.requiredDependencies || [];
|
|
597
|
-
const beforeDeps = module.meta?.beforeDependencies || [];
|
|
598
|
-
const afterDeps = module.meta?.afterDependencies || [];
|
|
599
|
-
const processedDeps = /* @__PURE__ */ new Set();
|
|
600
|
-
requiredDeps.forEach((dep) => {
|
|
601
|
-
if (!graph.has(dep)) {
|
|
602
|
-
throw new Error(`Required dependency "${dep}" for module "${key}" is missing`);
|
|
603
|
-
}
|
|
604
|
-
graph.get(dep)?.add(key);
|
|
605
|
-
inDegree.set(key, (inDegree.get(key) || 0) + 1);
|
|
606
|
-
processedDeps.add(dep);
|
|
607
|
-
});
|
|
608
|
-
beforeDeps.forEach((dep) => {
|
|
609
|
-
if (!graph.has(dep)) {
|
|
610
|
-
return;
|
|
611
|
-
}
|
|
612
|
-
graph.get(key)?.add(dep);
|
|
613
|
-
inDegree.set(dep, (inDegree.get(dep) || 0) + 1);
|
|
614
|
-
});
|
|
615
|
-
afterDeps.forEach((dep) => {
|
|
616
|
-
if (processedDeps.has(dep)) {
|
|
617
|
-
return;
|
|
618
|
-
}
|
|
619
|
-
if (!graph.has(dep)) {
|
|
620
|
-
return;
|
|
621
|
-
}
|
|
622
|
-
graph.get(dep)?.add(key);
|
|
623
|
-
inDegree.set(key, (inDegree.get(key) || 0) + 1);
|
|
624
|
-
});
|
|
625
|
-
});
|
|
626
|
-
return { graph, inDegree };
|
|
627
|
-
}
|
|
628
|
-
function findCyclicDependencies(graph) {
|
|
629
|
-
const visited = /* @__PURE__ */ new Set();
|
|
630
|
-
const recursionStack = /* @__PURE__ */ new Set();
|
|
631
|
-
const cycles = [];
|
|
632
|
-
function dfs(node, path = []) {
|
|
633
|
-
visited.add(node);
|
|
634
|
-
recursionStack.add(node);
|
|
635
|
-
path.push(node);
|
|
636
|
-
for (const neighbor of graph.get(node) || []) {
|
|
637
|
-
if (recursionStack.has(neighbor)) {
|
|
638
|
-
const cycleStart = path.indexOf(neighbor);
|
|
639
|
-
if (cycleStart !== -1) {
|
|
640
|
-
cycles.push([...path.slice(cycleStart), neighbor]);
|
|
641
|
-
}
|
|
642
|
-
} else if (!visited.has(neighbor)) {
|
|
643
|
-
dfs(neighbor, [...path]);
|
|
644
|
-
}
|
|
645
|
-
}
|
|
646
|
-
recursionStack.delete(node);
|
|
647
|
-
path.pop();
|
|
648
|
-
}
|
|
649
|
-
for (const node of graph.keys()) {
|
|
650
|
-
if (!visited.has(node)) {
|
|
651
|
-
dfs(node, []);
|
|
652
|
-
}
|
|
653
|
-
}
|
|
654
|
-
return cycles;
|
|
655
|
-
}
|
|
656
|
-
function topologicalSort(graphData) {
|
|
657
|
-
const { graph, inDegree } = graphData;
|
|
658
|
-
const order = [];
|
|
659
|
-
const queue = [];
|
|
660
|
-
for (const [node, degree] of inDegree.entries()) {
|
|
661
|
-
if (degree === 0) {
|
|
662
|
-
queue.push(node);
|
|
663
|
-
}
|
|
664
|
-
}
|
|
665
|
-
while (queue.length > 0) {
|
|
666
|
-
const node = queue.shift();
|
|
667
|
-
order.push(node);
|
|
668
|
-
const neighbors = Array.from(graph.get(node) || []);
|
|
669
|
-
for (const neighbor of neighbors) {
|
|
670
|
-
const newDegree = (inDegree.get(neighbor) || 0) - 1;
|
|
671
|
-
inDegree.set(neighbor, newDegree);
|
|
672
|
-
if (newDegree === 0) {
|
|
673
|
-
queue.push(neighbor);
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
}
|
|
677
|
-
if (order.length !== graph.size) {
|
|
678
|
-
const cycles = findCyclicDependencies(graph);
|
|
679
|
-
if (cycles.length > 0) {
|
|
680
|
-
const cycleStr = cycles.map((cycle) => ` ${cycle.join(" -> ")}`).join("\n");
|
|
681
|
-
throw new Error(`Circular dependencies detected:
|
|
682
|
-
${cycleStr}`);
|
|
683
|
-
} else {
|
|
684
|
-
const unresolvedModules = Array.from(graph.keys()).filter((key) => !order.includes(key));
|
|
685
|
-
throw new Error(`Unable to resolve dependencies for modules: ${unresolvedModules.join(", ")}`);
|
|
686
|
-
}
|
|
687
|
-
}
|
|
688
|
-
return order;
|
|
689
|
-
}
|
|
690
|
-
|
|
691
476
|
function resolveIgnorePatterns(silgi, relativePath) {
|
|
692
477
|
if (!silgi) {
|
|
693
478
|
return [];
|
|
@@ -867,10 +652,10 @@ async function verifyDirectoryCaseSensitivity(directoryPath, rootDirectory) {
|
|
|
867
652
|
} catch {
|
|
868
653
|
}
|
|
869
654
|
}
|
|
870
|
-
async function
|
|
655
|
+
async function scanSilgiExports(path, silgiInstance = useSilgiCLI()) {
|
|
871
656
|
const processedFilePaths = /* @__PURE__ */ new Set();
|
|
872
657
|
const alreadyScannedPaths = [];
|
|
873
|
-
const serverDirectory = silgiInstance.options.serverDir;
|
|
658
|
+
const serverDirectory = path || silgiInstance.options.serverDir;
|
|
874
659
|
if (!serverDirectory) {
|
|
875
660
|
consola.warn("No server directory specified for scanning");
|
|
876
661
|
return;
|
|
@@ -888,7 +673,7 @@ async function scanExportFile(silgiInstance) {
|
|
|
888
673
|
}
|
|
889
674
|
for (const relativeFilePath of matchedFiles.sort()) {
|
|
890
675
|
const absoluteFilePath = resolve(silgiInstance.options.rootDir, relativeFilePath);
|
|
891
|
-
if (alreadyScannedPaths.find((
|
|
676
|
+
if (alreadyScannedPaths.find((path2) => absoluteFilePath.startsWith(withTrailingSlash(path2))) || isIgnored(absoluteFilePath, silgiInstance) || processedFilePaths.has(absoluteFilePath)) {
|
|
892
677
|
continue;
|
|
893
678
|
}
|
|
894
679
|
processedFilePaths.add(absoluteFilePath);
|
|
@@ -923,6 +708,222 @@ async function scanExportFile(silgiInstance) {
|
|
|
923
708
|
}
|
|
924
709
|
}
|
|
925
710
|
|
|
711
|
+
const MissingModuleMatcher = /Cannot find module\s+['"]?([^'")\s]+)['"]?/i;
|
|
712
|
+
async function _resolveSilgiModule(silgiModule, silgi) {
|
|
713
|
+
let resolvedModulePath;
|
|
714
|
+
let buildTimeModuleMeta = {};
|
|
715
|
+
const jiti = createJiti(silgi.options.rootDir, {
|
|
716
|
+
alias: silgi.options.alias,
|
|
717
|
+
fsCache: true,
|
|
718
|
+
moduleCache: true
|
|
719
|
+
});
|
|
720
|
+
if (typeof silgiModule === "string") {
|
|
721
|
+
silgiModule = resolveAlias(silgiModule, silgi.options.alias);
|
|
722
|
+
if (isRelative(silgiModule)) {
|
|
723
|
+
silgiModule = resolve(silgi.options.rootDir, silgiModule);
|
|
724
|
+
}
|
|
725
|
+
try {
|
|
726
|
+
const src = resolveModuleURL(silgiModule, {
|
|
727
|
+
from: silgi.options.modulesDir.map((m) => directoryToURL(m.replace(/\/node_modules\/?$/, "/"))),
|
|
728
|
+
suffixes: ["silgi", "silgi/index", "module", "module/index", "", "index"],
|
|
729
|
+
extensions: [".js", ".mjs", ".cjs", ".ts", ".mts", ".cts"]
|
|
730
|
+
// Maybe add https://github.com/unjs/exsolve/blob/dfff3e9bbc4a3a173a2d56b9b9ff731ab15598be/src/resolve.ts#L7
|
|
731
|
+
// conditions: silgi.options.conditions,
|
|
732
|
+
});
|
|
733
|
+
resolvedModulePath = fileURLToPath(src);
|
|
734
|
+
const resolvedSilgiModule = await jiti.import(src, { default: true });
|
|
735
|
+
if (typeof resolvedSilgiModule !== "function") {
|
|
736
|
+
throw new TypeError(`Nuxt module should be a function: ${silgiModule}.`);
|
|
737
|
+
}
|
|
738
|
+
silgiModule = await jiti.import(src, {
|
|
739
|
+
default: true,
|
|
740
|
+
conditions: silgi.options.conditions
|
|
741
|
+
});
|
|
742
|
+
const moduleMetadataPath = new URL("module.json", src);
|
|
743
|
+
scanSilgiExports(join(src, "runtime"));
|
|
744
|
+
if (existsSync(moduleMetadataPath)) {
|
|
745
|
+
buildTimeModuleMeta = JSON.parse(await promises.readFile(moduleMetadataPath, "utf-8"));
|
|
746
|
+
} else {
|
|
747
|
+
if (typeof silgiModule === "function") {
|
|
748
|
+
const meta = await silgiModule.getMeta?.();
|
|
749
|
+
const _exports = await scanExports(resolvedModulePath, true);
|
|
750
|
+
buildTimeModuleMeta = {
|
|
751
|
+
...meta,
|
|
752
|
+
exports: _exports.map(({ from, ...rest }) => rest)
|
|
753
|
+
};
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
} catch (error) {
|
|
757
|
+
const code = error.code;
|
|
758
|
+
if (code === "MODULE_NOT_FOUND" || code === "ERR_PACKAGE_PATH_NOT_EXPORTED" || code === "ERR_MODULE_NOT_FOUND" || code === "ERR_UNSUPPORTED_DIR_IMPORT" || code === "ENOTDIR") {
|
|
759
|
+
throw new TypeError(`Could not load \`${silgiModule}\`. Is it installed?`);
|
|
760
|
+
}
|
|
761
|
+
if (code === "MODULE_NOT_FOUND" || code === "ERR_MODULE_NOT_FOUND") {
|
|
762
|
+
const module = MissingModuleMatcher.exec(error.message)?.[1];
|
|
763
|
+
if (module && !module.includes(silgiModule)) {
|
|
764
|
+
throw new TypeError(`Error while importing module \`${silgiModule}\`: ${error}`);
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
if (!buildTimeModuleMeta) {
|
|
770
|
+
throw new Error(`Module ${silgiModule} is not a valid Silgi module`);
|
|
771
|
+
}
|
|
772
|
+
if (typeof silgiModule === "function") {
|
|
773
|
+
if (!buildTimeModuleMeta.configKey) {
|
|
774
|
+
const meta = await silgiModule.getMeta?.();
|
|
775
|
+
buildTimeModuleMeta = {
|
|
776
|
+
...meta,
|
|
777
|
+
exports: []
|
|
778
|
+
};
|
|
779
|
+
}
|
|
780
|
+
if (silgi.scanModules.some((m) => m.meta?.configKey === buildTimeModuleMeta.configKey)) {
|
|
781
|
+
throw new Error(`Module with key \`${buildTimeModuleMeta.configKey}\` already exists`);
|
|
782
|
+
}
|
|
783
|
+
const options = await silgiModule.getOptions?.() || {};
|
|
784
|
+
if (options) {
|
|
785
|
+
silgi.options._c12.config[buildTimeModuleMeta.configKey] = defu(
|
|
786
|
+
silgi.options._c12.config[buildTimeModuleMeta.configKey] || {},
|
|
787
|
+
options || {}
|
|
788
|
+
);
|
|
789
|
+
} else {
|
|
790
|
+
throw new TypeError(`Could not load \`${silgiModule}\`. Is it installed?`);
|
|
791
|
+
}
|
|
792
|
+
silgi.scanModules.push({
|
|
793
|
+
meta: buildTimeModuleMeta,
|
|
794
|
+
entryPath: resolvedModulePath || void 0,
|
|
795
|
+
installed: false,
|
|
796
|
+
options,
|
|
797
|
+
module: silgiModule
|
|
798
|
+
});
|
|
799
|
+
}
|
|
800
|
+
}
|
|
801
|
+
async function scanModules$1(silgi) {
|
|
802
|
+
const _modules = [
|
|
803
|
+
...silgi.options._modules,
|
|
804
|
+
...silgi.options.modules
|
|
805
|
+
];
|
|
806
|
+
for await (const mod of _modules) {
|
|
807
|
+
await _resolveSilgiModule(mod, silgi);
|
|
808
|
+
}
|
|
809
|
+
const moduleMap = new Map(
|
|
810
|
+
silgi.scanModules.map((m) => [m.meta?.configKey, m])
|
|
811
|
+
);
|
|
812
|
+
const graphData = createDependencyGraph(silgi.scanModules);
|
|
813
|
+
const sortedKeys = topologicalSort(graphData);
|
|
814
|
+
const modules = sortedKeys.map((key) => moduleMap.get(key)).filter((module) => Boolean(module));
|
|
815
|
+
silgi.scanModules = modules;
|
|
816
|
+
}
|
|
817
|
+
function createDependencyGraph(modules) {
|
|
818
|
+
const graph = /* @__PURE__ */ new Map();
|
|
819
|
+
const inDegree = /* @__PURE__ */ new Map();
|
|
820
|
+
modules.forEach((module) => {
|
|
821
|
+
const key = module.meta?.configKey;
|
|
822
|
+
if (key) {
|
|
823
|
+
graph.set(key, /* @__PURE__ */ new Set());
|
|
824
|
+
inDegree.set(key, 0);
|
|
825
|
+
}
|
|
826
|
+
});
|
|
827
|
+
modules.forEach((module) => {
|
|
828
|
+
const key = module.meta?.configKey;
|
|
829
|
+
if (!key) {
|
|
830
|
+
return;
|
|
831
|
+
}
|
|
832
|
+
const requiredDeps = module.meta?.requiredDependencies || [];
|
|
833
|
+
const beforeDeps = module.meta?.beforeDependencies || [];
|
|
834
|
+
const afterDeps = module.meta?.afterDependencies || [];
|
|
835
|
+
const processedDeps = /* @__PURE__ */ new Set();
|
|
836
|
+
requiredDeps.forEach((dep) => {
|
|
837
|
+
if (!graph.has(dep)) {
|
|
838
|
+
throw new Error(`Required dependency "${dep}" for module "${key}" is missing`);
|
|
839
|
+
}
|
|
840
|
+
graph.get(dep)?.add(key);
|
|
841
|
+
inDegree.set(key, (inDegree.get(key) || 0) + 1);
|
|
842
|
+
processedDeps.add(dep);
|
|
843
|
+
});
|
|
844
|
+
beforeDeps.forEach((dep) => {
|
|
845
|
+
if (!graph.has(dep)) {
|
|
846
|
+
return;
|
|
847
|
+
}
|
|
848
|
+
graph.get(key)?.add(dep);
|
|
849
|
+
inDegree.set(dep, (inDegree.get(dep) || 0) + 1);
|
|
850
|
+
});
|
|
851
|
+
afterDeps.forEach((dep) => {
|
|
852
|
+
if (processedDeps.has(dep)) {
|
|
853
|
+
return;
|
|
854
|
+
}
|
|
855
|
+
if (!graph.has(dep)) {
|
|
856
|
+
return;
|
|
857
|
+
}
|
|
858
|
+
graph.get(dep)?.add(key);
|
|
859
|
+
inDegree.set(key, (inDegree.get(key) || 0) + 1);
|
|
860
|
+
});
|
|
861
|
+
});
|
|
862
|
+
return { graph, inDegree };
|
|
863
|
+
}
|
|
864
|
+
function findCyclicDependencies(graph) {
|
|
865
|
+
const visited = /* @__PURE__ */ new Set();
|
|
866
|
+
const recursionStack = /* @__PURE__ */ new Set();
|
|
867
|
+
const cycles = [];
|
|
868
|
+
function dfs(node, path = []) {
|
|
869
|
+
visited.add(node);
|
|
870
|
+
recursionStack.add(node);
|
|
871
|
+
path.push(node);
|
|
872
|
+
for (const neighbor of graph.get(node) || []) {
|
|
873
|
+
if (recursionStack.has(neighbor)) {
|
|
874
|
+
const cycleStart = path.indexOf(neighbor);
|
|
875
|
+
if (cycleStart !== -1) {
|
|
876
|
+
cycles.push([...path.slice(cycleStart), neighbor]);
|
|
877
|
+
}
|
|
878
|
+
} else if (!visited.has(neighbor)) {
|
|
879
|
+
dfs(neighbor, [...path]);
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
recursionStack.delete(node);
|
|
883
|
+
path.pop();
|
|
884
|
+
}
|
|
885
|
+
for (const node of graph.keys()) {
|
|
886
|
+
if (!visited.has(node)) {
|
|
887
|
+
dfs(node, []);
|
|
888
|
+
}
|
|
889
|
+
}
|
|
890
|
+
return cycles;
|
|
891
|
+
}
|
|
892
|
+
function topologicalSort(graphData) {
|
|
893
|
+
const { graph, inDegree } = graphData;
|
|
894
|
+
const order = [];
|
|
895
|
+
const queue = [];
|
|
896
|
+
for (const [node, degree] of inDegree.entries()) {
|
|
897
|
+
if (degree === 0) {
|
|
898
|
+
queue.push(node);
|
|
899
|
+
}
|
|
900
|
+
}
|
|
901
|
+
while (queue.length > 0) {
|
|
902
|
+
const node = queue.shift();
|
|
903
|
+
order.push(node);
|
|
904
|
+
const neighbors = Array.from(graph.get(node) || []);
|
|
905
|
+
for (const neighbor of neighbors) {
|
|
906
|
+
const newDegree = (inDegree.get(neighbor) || 0) - 1;
|
|
907
|
+
inDegree.set(neighbor, newDegree);
|
|
908
|
+
if (newDegree === 0) {
|
|
909
|
+
queue.push(neighbor);
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
if (order.length !== graph.size) {
|
|
914
|
+
const cycles = findCyclicDependencies(graph);
|
|
915
|
+
if (cycles.length > 0) {
|
|
916
|
+
const cycleStr = cycles.map((cycle) => ` ${cycle.join(" -> ")}`).join("\n");
|
|
917
|
+
throw new Error(`Circular dependencies detected:
|
|
918
|
+
${cycleStr}`);
|
|
919
|
+
} else {
|
|
920
|
+
const unresolvedModules = Array.from(graph.keys()).filter((key) => !order.includes(key));
|
|
921
|
+
throw new Error(`Unable to resolve dependencies for modules: ${unresolvedModules.join(", ")}`);
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
return order;
|
|
925
|
+
}
|
|
926
|
+
|
|
926
927
|
async function readScanFile(silgi) {
|
|
927
928
|
const path = resolve(silgi.options.silgi.serverDir, "scan.ts");
|
|
928
929
|
const context = await promises.readFile(path, { encoding: "utf-8" });
|
|
@@ -1382,7 +1383,7 @@ async function createSilgiCLI(config = {}, opts = {}) {
|
|
|
1382
1383
|
}
|
|
1383
1384
|
await scanAndSyncOptions(silgi);
|
|
1384
1385
|
await scanModules$1(silgi);
|
|
1385
|
-
await
|
|
1386
|
+
await scanSilgiExports();
|
|
1386
1387
|
await installModules(silgi, true);
|
|
1387
1388
|
useCLIRuntimeConfig(silgi);
|
|
1388
1389
|
await writeScanFiles(silgi);
|
package/dist/cli/index.mjs
CHANGED