@open-mercato/cli 0.6.6-develop.6352.1.8eee7e1399 → 0.6.6-develop.6354.1.4730e55f76

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 {