@open-mercato/cli 0.6.6-develop.6351.1.c140d703c9 → 0.6.6-develop.6353.1.efc82affea
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.
|
@@ -708,6 +708,136 @@ function buildBareImportStatement(importPath) {
|
|
|
708
708
|
function buildDynamicImportExpression(importPath) {
|
|
709
709
|
return `import(${toLiteral(sanitizeGeneratedModuleSpecifier(importPath))})`;
|
|
710
710
|
}
|
|
711
|
+
const COMMAND_SCAN_CONFIG = {
|
|
712
|
+
folder: "commands",
|
|
713
|
+
include: (name) => [".ts", ".js", ".tsx", ".jsx"].some((extension) => name.endsWith(extension)) && !name.endsWith(".d.ts") && !/\.(test|spec)\.[jt]sx?$/.test(name) && stripModuleCodeExtension(name) !== "index",
|
|
714
|
+
sort: (a, b) => a.localeCompare(b)
|
|
715
|
+
};
|
|
716
|
+
function getStaticStringExpression(expr, stringConstants = /* @__PURE__ */ new Map()) {
|
|
717
|
+
const unwrapped = unwrapExpression(expr);
|
|
718
|
+
if (ts.isStringLiteral(unwrapped) || ts.isNoSubstitutionTemplateLiteral(unwrapped)) return unwrapped.text;
|
|
719
|
+
if (ts.isIdentifier(unwrapped)) {
|
|
720
|
+
const direct = stringConstants.get(unwrapped.text);
|
|
721
|
+
if (direct) return direct;
|
|
722
|
+
}
|
|
723
|
+
return null;
|
|
724
|
+
}
|
|
725
|
+
function getPropertyNameText(name) {
|
|
726
|
+
if (ts.isIdentifier(name) || ts.isStringLiteral(name) || ts.isNumericLiteral(name)) return name.text;
|
|
727
|
+
return null;
|
|
728
|
+
}
|
|
729
|
+
function getObjectStringProperty(object, propertyName, stringConstants = /* @__PURE__ */ new Map()) {
|
|
730
|
+
for (const property of object.properties) {
|
|
731
|
+
if (!ts.isPropertyAssignment(property)) continue;
|
|
732
|
+
const name = getPropertyNameText(property.name);
|
|
733
|
+
if (name !== propertyName) continue;
|
|
734
|
+
return getStaticStringExpression(property.initializer, stringConstants);
|
|
735
|
+
}
|
|
736
|
+
return null;
|
|
737
|
+
}
|
|
738
|
+
function collectStringArrayElements(expr, stringConstants = /* @__PURE__ */ new Map()) {
|
|
739
|
+
const unwrapped = unwrapExpression(expr);
|
|
740
|
+
if (!ts.isArrayLiteralExpression(unwrapped)) return [];
|
|
741
|
+
const values = [];
|
|
742
|
+
for (const element of unwrapped.elements) {
|
|
743
|
+
const value = getStaticStringExpression(element, stringConstants);
|
|
744
|
+
if (value) values.push(value);
|
|
745
|
+
}
|
|
746
|
+
return values;
|
|
747
|
+
}
|
|
748
|
+
function extractCommandIdsFromSource(sourcePath) {
|
|
749
|
+
const sourceText = fs.readFileSync(sourcePath, "utf8");
|
|
750
|
+
const sourceFile = ts.createSourceFile(sourcePath, sourceText, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
|
|
751
|
+
const ids = /* @__PURE__ */ new Set();
|
|
752
|
+
const stringConstants = /* @__PURE__ */ new Map();
|
|
753
|
+
const variableCommandIds = /* @__PURE__ */ new Map();
|
|
754
|
+
const collectVariables = (node) => {
|
|
755
|
+
if (ts.isVariableDeclaration(node) && ts.isIdentifier(node.name) && node.initializer) {
|
|
756
|
+
const stringValue = getStaticStringExpression(node.initializer, stringConstants);
|
|
757
|
+
if (stringValue) {
|
|
758
|
+
stringConstants.set(node.name.text, stringValue);
|
|
759
|
+
}
|
|
760
|
+
if (ts.isObjectLiteralExpression(node.initializer)) {
|
|
761
|
+
const id = getObjectStringProperty(node.initializer, "id", stringConstants);
|
|
762
|
+
if (id) variableCommandIds.set(node.name.text, id);
|
|
763
|
+
} else if (node.name.text === "commandIds") {
|
|
764
|
+
for (const id of collectStringArrayElements(node.initializer, stringConstants)) ids.add(id);
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
ts.forEachChild(node, collectVariables);
|
|
768
|
+
};
|
|
769
|
+
const collectRegistrations = (node) => {
|
|
770
|
+
if (ts.isCallExpression(node) && ts.isIdentifier(node.expression)) {
|
|
771
|
+
const callName = node.expression.text;
|
|
772
|
+
const firstArg = node.arguments[0];
|
|
773
|
+
if (callName === "registerCommand" && firstArg) {
|
|
774
|
+
if (ts.isIdentifier(firstArg)) {
|
|
775
|
+
const id = variableCommandIds.get(firstArg.text);
|
|
776
|
+
if (id) ids.add(id);
|
|
777
|
+
} else if (ts.isObjectLiteralExpression(firstArg)) {
|
|
778
|
+
const id = getObjectStringProperty(firstArg, "id", stringConstants);
|
|
779
|
+
if (id) ids.add(id);
|
|
780
|
+
}
|
|
781
|
+
}
|
|
782
|
+
if (callName === "registerDictionaryEntryCommands" && firstArg && ts.isObjectLiteralExpression(firstArg)) {
|
|
783
|
+
const prefix = getObjectStringProperty(firstArg, "commandPrefix", stringConstants);
|
|
784
|
+
if (prefix) {
|
|
785
|
+
ids.add(`${prefix}.create`);
|
|
786
|
+
ids.add(`${prefix}.update`);
|
|
787
|
+
ids.add(`${prefix}.delete`);
|
|
788
|
+
}
|
|
789
|
+
}
|
|
790
|
+
}
|
|
791
|
+
ts.forEachChild(node, collectRegistrations);
|
|
792
|
+
};
|
|
793
|
+
collectVariables(sourceFile);
|
|
794
|
+
collectRegistrations(sourceFile);
|
|
795
|
+
return Array.from(ids).sort((a, b) => a.localeCompare(b));
|
|
796
|
+
}
|
|
797
|
+
function collectCommandLoaderEntries(roots, imps, modId) {
|
|
798
|
+
const files = scanModuleDir(roots, COMMAND_SCAN_CONFIG);
|
|
799
|
+
const entries = [];
|
|
800
|
+
for (const file of files) {
|
|
801
|
+
const relPath = `commands/${file.relPath}`;
|
|
802
|
+
const resolved = resolveModuleFile(roots, imps, relPath);
|
|
803
|
+
if (!resolved) continue;
|
|
804
|
+
const logicalKey = stripModuleCodeExtension(file.relPath);
|
|
805
|
+
const basename = path.basename(logicalKey);
|
|
806
|
+
if (basename === "shared" || basename === "factory") continue;
|
|
807
|
+
entries.push({
|
|
808
|
+
moduleId: modId,
|
|
809
|
+
key: `${modId}:commands:${logicalKey}`,
|
|
810
|
+
importPath: resolved.importPath,
|
|
811
|
+
ids: extractCommandIdsFromSource(resolved.absolutePath)
|
|
812
|
+
});
|
|
813
|
+
}
|
|
814
|
+
return entries;
|
|
815
|
+
}
|
|
816
|
+
function renderCommandLoadersFile(entries) {
|
|
817
|
+
const seenCommandIds = /* @__PURE__ */ new Map();
|
|
818
|
+
const rendered = [];
|
|
819
|
+
for (const entry of entries) {
|
|
820
|
+
const loadExpr = `() => ${buildDynamicImportExpression(entry.importPath)}`;
|
|
821
|
+
for (const id of entry.ids) {
|
|
822
|
+
const previous = seenCommandIds.get(id);
|
|
823
|
+
if (previous && previous !== entry.key) {
|
|
824
|
+
throw new Error(`[generate] Duplicate command id "${id}" discovered in "${previous}" and "${entry.key}"`);
|
|
825
|
+
}
|
|
826
|
+
seenCommandIds.set(id, entry.key);
|
|
827
|
+
rendered.push(` { moduleId: ${toLiteral(entry.moduleId)}, id: ${toLiteral(id)}, key: ${toLiteral(entry.key)}, load: ${loadExpr} },`);
|
|
828
|
+
}
|
|
829
|
+
rendered.push(` { moduleId: ${toLiteral(entry.moduleId)}, key: ${toLiteral(entry.key)}, load: ${loadExpr} },`);
|
|
830
|
+
}
|
|
831
|
+
return `// AUTO-GENERATED by mercato generate command-loaders
|
|
832
|
+
import type { CommandLoader } from '@open-mercato/shared/lib/commands'
|
|
833
|
+
|
|
834
|
+
export const commandLoaderEntries: CommandLoader[] = [
|
|
835
|
+
${rendered.join("\n")}
|
|
836
|
+
]
|
|
837
|
+
|
|
838
|
+
export default commandLoaderEntries
|
|
839
|
+
`;
|
|
840
|
+
}
|
|
711
841
|
function serializeGeneratedImport(statement) {
|
|
712
842
|
if (typeof statement === "string") {
|
|
713
843
|
return statement;
|
|
@@ -1994,6 +2124,8 @@ async function generateModuleRegistry(options) {
|
|
|
1994
2124
|
const bootstrapRegsChecksumFile = path.join(outputDir, "bootstrap-registrations.generated.checksum");
|
|
1995
2125
|
const legacySubscribersOutFile = path.join(outputDir, "subscribers.generated.ts");
|
|
1996
2126
|
const legacySubscribersChecksumFile = path.join(outputDir, "subscribers.generated.checksum");
|
|
2127
|
+
const commandLoadersOutFile = path.join(outputDir, "command-loaders.generated.ts");
|
|
2128
|
+
const commandLoadersChecksumFile = path.join(outputDir, "command-loaders.generated.checksum");
|
|
1997
2129
|
const enabled = resolver.loadEnabledModules();
|
|
1998
2130
|
for (const entry of enabled) {
|
|
1999
2131
|
verifyThirdPartyModuleShape(entry, resolver.getModulePaths(entry).pkgBase);
|
|
@@ -2033,6 +2165,7 @@ async function generateModuleRegistry(options) {
|
|
|
2033
2165
|
const importIdRef = { value: 0 };
|
|
2034
2166
|
const trackedRoots = /* @__PURE__ */ new Set();
|
|
2035
2167
|
const requiresByModule = /* @__PURE__ */ new Map();
|
|
2168
|
+
const commandLoaderEntries = [];
|
|
2036
2169
|
let hasRouteComponents = false;
|
|
2037
2170
|
const umesConflictSources = [];
|
|
2038
2171
|
for (const entry of enabled) {
|
|
@@ -2044,6 +2177,7 @@ async function generateModuleRegistry(options) {
|
|
|
2044
2177
|
const isAppModule = entry.from === "@app";
|
|
2045
2178
|
const appImportBase = isAppModule ? `../../src/modules/${modId}` : rawImps.appBase;
|
|
2046
2179
|
const imps = { appBase: appImportBase, pkgBase: rawImps.pkgBase };
|
|
2180
|
+
commandLoaderEntries.push(...collectCommandLoaderEntries(roots, imps, modId));
|
|
2047
2181
|
const frontendRoutes = [];
|
|
2048
2182
|
const backendRoutes = [];
|
|
2049
2183
|
const apis = [];
|
|
@@ -2473,6 +2607,8 @@ async function generateModuleRegistry(options) {
|
|
|
2473
2607
|
writeGeneratedFile({ outFile: backendRoutesOutFile, checksumFile: backendRoutesChecksumFile, content: backendRoutesOutput, structureChecksum, result, quiet });
|
|
2474
2608
|
writeGeneratedFile({ outFile: apiRoutesOutFile, checksumFile: apiRoutesChecksumFile, content: apiRoutesOutput, structureChecksum, result, quiet });
|
|
2475
2609
|
writeGeneratedFile({ outFile: legacySubscribersOutFile, checksumFile: legacySubscribersChecksumFile, content: legacySubscribersOutput, structureChecksum, result, quiet });
|
|
2610
|
+
const commandLoadersOutput = renderCommandLoadersFile(commandLoaderEntries);
|
|
2611
|
+
writeGeneratedFile({ outFile: commandLoadersOutFile, checksumFile: commandLoadersChecksumFile, content: commandLoadersOutput, structureChecksum, result, quiet });
|
|
2476
2612
|
for (const extension of extensions) {
|
|
2477
2613
|
const outputs = extension.generateOutput();
|
|
2478
2614
|
for (const [fileName, content] of outputs) {
|
|
@@ -2539,6 +2675,8 @@ async function generateModuleRegistryApp(options) {
|
|
|
2539
2675
|
const legacyChecksumFile = path.join(outputDir, "bootstrap-modules.generated.checksum");
|
|
2540
2676
|
const enabledIdsOutFile = path.join(outputDir, "enabled-module-ids.generated.ts");
|
|
2541
2677
|
const enabledIdsChecksumFile = path.join(outputDir, "enabled-module-ids.generated.checksum");
|
|
2678
|
+
const commandLoadersOutFile = path.join(outputDir, "command-loaders.generated.ts");
|
|
2679
|
+
const commandLoadersChecksumFile = path.join(outputDir, "command-loaders.generated.checksum");
|
|
2542
2680
|
const enabled = resolver.loadEnabledModules();
|
|
2543
2681
|
for (const entry of enabled) {
|
|
2544
2682
|
verifyThirdPartyModuleShape(entry, resolver.getModulePaths(entry).pkgBase);
|
|
@@ -2548,6 +2686,7 @@ async function generateModuleRegistryApp(options) {
|
|
|
2548
2686
|
const importIdRef = { value: 0 };
|
|
2549
2687
|
const trackedRoots = /* @__PURE__ */ new Set();
|
|
2550
2688
|
const requiresByModule = /* @__PURE__ */ new Map();
|
|
2689
|
+
const commandLoaderEntries = [];
|
|
2551
2690
|
let hasRouteComponents = false;
|
|
2552
2691
|
for (const entry of enabled) {
|
|
2553
2692
|
const modId = entry.id;
|
|
@@ -2558,6 +2697,7 @@ async function generateModuleRegistryApp(options) {
|
|
|
2558
2697
|
const isAppModule = entry.from === "@app";
|
|
2559
2698
|
const appImportBase = isAppModule ? `../../src/modules/${modId}` : rawImps.appBase;
|
|
2560
2699
|
const imps = { appBase: appImportBase, pkgBase: rawImps.pkgBase };
|
|
2700
|
+
commandLoaderEntries.push(...collectCommandLoaderEntries(roots, imps, modId));
|
|
2561
2701
|
const frontendRoutes = [];
|
|
2562
2702
|
const backendRoutes = [];
|
|
2563
2703
|
const translations = [];
|
|
@@ -2824,6 +2964,8 @@ async function generateModuleRegistryApp(options) {
|
|
|
2824
2964
|
writeGeneratedFile({ outFile: legacyOutFile, checksumFile: legacyChecksumFile, content: legacyOutput, structureChecksum, result, quiet });
|
|
2825
2965
|
const enabledIdsOutput = renderEnabledModuleIdsFile(enabled.map((entry) => entry.id));
|
|
2826
2966
|
writeGeneratedFile({ outFile: enabledIdsOutFile, checksumFile: enabledIdsChecksumFile, content: enabledIdsOutput, structureChecksum, result, quiet });
|
|
2967
|
+
const commandLoadersOutput = renderCommandLoadersFile(commandLoaderEntries);
|
|
2968
|
+
writeGeneratedFile({ outFile: commandLoadersOutFile, checksumFile: commandLoadersChecksumFile, content: commandLoadersOutput, structureChecksum, result, quiet });
|
|
2827
2969
|
return result;
|
|
2828
2970
|
}
|
|
2829
2971
|
async function generateModuleRegistryCli(options) {
|
|
@@ -2834,6 +2976,8 @@ async function generateModuleRegistryCli(options) {
|
|
|
2834
2976
|
const checksumFile = path.join(outputDir, "modules.cli.generated.checksum");
|
|
2835
2977
|
const legacyOutFile = path.join(outputDir, "cli-modules.generated.ts");
|
|
2836
2978
|
const legacyChecksumFile = path.join(outputDir, "cli-modules.generated.checksum");
|
|
2979
|
+
const commandLoadersOutFile = path.join(outputDir, "command-loaders.generated.ts");
|
|
2980
|
+
const commandLoadersChecksumFile = path.join(outputDir, "command-loaders.generated.checksum");
|
|
2837
2981
|
const enabled = resolver.loadEnabledModules();
|
|
2838
2982
|
for (const entry of enabled) {
|
|
2839
2983
|
verifyThirdPartyModuleShape(entry, resolver.getModulePaths(entry).pkgBase);
|
|
@@ -2843,6 +2987,7 @@ async function generateModuleRegistryCli(options) {
|
|
|
2843
2987
|
const importIdRef = { value: 0 };
|
|
2844
2988
|
const trackedRoots = /* @__PURE__ */ new Set();
|
|
2845
2989
|
const requiresByModule = /* @__PURE__ */ new Map();
|
|
2990
|
+
const commandLoaderEntries = [];
|
|
2846
2991
|
for (const entry of enabled) {
|
|
2847
2992
|
const modId = entry.id;
|
|
2848
2993
|
const roots = resolver.getModulePaths(entry);
|
|
@@ -2852,6 +2997,7 @@ async function generateModuleRegistryCli(options) {
|
|
|
2852
2997
|
const isAppModule = entry.from === "@app";
|
|
2853
2998
|
const appImportBase = isAppModule ? `../../src/modules/${modId}` : rawImps.appBase;
|
|
2854
2999
|
const imps = { appBase: appImportBase, pkgBase: rawImps.pkgBase };
|
|
3000
|
+
commandLoaderEntries.push(...collectCommandLoaderEntries(roots, imps, modId));
|
|
2855
3001
|
let cliImportName = null;
|
|
2856
3002
|
const translations = [];
|
|
2857
3003
|
const subscribers = [];
|
|
@@ -3105,6 +3251,8 @@ async function generateModuleRegistryCli(options) {
|
|
|
3105
3251
|
const structureChecksum = calculateStructureChecksum(Array.from(trackedRoots));
|
|
3106
3252
|
writeGeneratedFile({ outFile, checksumFile, content: output, structureChecksum, result, quiet });
|
|
3107
3253
|
writeGeneratedFile({ outFile: legacyOutFile, checksumFile: legacyChecksumFile, content: legacyOutput, structureChecksum, result, quiet });
|
|
3254
|
+
const commandLoadersOutput = renderCommandLoadersFile(commandLoaderEntries);
|
|
3255
|
+
writeGeneratedFile({ outFile: commandLoadersOutFile, checksumFile: commandLoadersChecksumFile, content: commandLoadersOutput, structureChecksum, result, quiet });
|
|
3108
3256
|
return result;
|
|
3109
3257
|
}
|
|
3110
3258
|
export {
|