@open-mercato/cli 0.6.8-develop.7016.1.4ed7b1e49d → 0.6.8-develop.7019.1.f4c01c4b5c
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/agentic/guides/module-facts.json +130 -130
- package/dist/agentic/guides/module-facts.v2.json +130 -130
- package/dist/agentic/guides/modules/ai_assistant/index.md +1 -1
- package/dist/agentic/guides/modules/api_docs/index.md +1 -1
- package/dist/agentic/guides/modules/api_keys/index.md +1 -1
- package/dist/agentic/guides/modules/attachments/index.md +1 -1
- package/dist/agentic/guides/modules/audit_logs/index.md +1 -1
- package/dist/agentic/guides/modules/auth/index.md +1 -1
- package/dist/agentic/guides/modules/business_rules/index.md +1 -1
- package/dist/agentic/guides/modules/catalog/index.md +1 -1
- package/dist/agentic/guides/modules/channel_apns/index.md +1 -1
- package/dist/agentic/guides/modules/channel_expo/index.md +1 -1
- package/dist/agentic/guides/modules/channel_fcm/index.md +1 -1
- package/dist/agentic/guides/modules/channel_gmail/index.md +1 -1
- package/dist/agentic/guides/modules/channel_imap/index.md +1 -1
- package/dist/agentic/guides/modules/checkout/index.md +1 -1
- package/dist/agentic/guides/modules/communication_channels/index.md +1 -1
- package/dist/agentic/guides/modules/configs/index.md +1 -1
- package/dist/agentic/guides/modules/content/index.md +1 -1
- package/dist/agentic/guides/modules/currencies/index.md +1 -1
- package/dist/agentic/guides/modules/customer_accounts/index.md +1 -1
- package/dist/agentic/guides/modules/customers/index.md +1 -1
- package/dist/agentic/guides/modules/dashboards/index.md +1 -1
- package/dist/agentic/guides/modules/data_sync/exact-override-targets.md +2 -2
- package/dist/agentic/guides/modules/data_sync/index.md +1 -1
- package/dist/agentic/guides/modules/data_sync/workers.md +2 -2
- package/dist/agentic/guides/modules/design_system/index.md +1 -1
- package/dist/agentic/guides/modules/devices/index.md +1 -1
- package/dist/agentic/guides/modules/dictionaries/index.md +1 -1
- package/dist/agentic/guides/modules/directory/index.md +1 -1
- package/dist/agentic/guides/modules/documents/index.md +1 -1
- package/dist/agentic/guides/modules/entities/index.md +1 -1
- package/dist/agentic/guides/modules/eudr/index.md +1 -1
- package/dist/agentic/guides/modules/events/index.md +1 -1
- package/dist/agentic/guides/modules/feature_toggles/index.md +1 -1
- package/dist/agentic/guides/modules/gateway_stripe/index.md +1 -1
- package/dist/agentic/guides/modules/generators/index.md +1 -1
- package/dist/agentic/guides/modules/inbox_ops/index.md +1 -1
- package/dist/agentic/guides/modules/integrations/index.md +1 -1
- package/dist/agentic/guides/modules/messages/index.md +1 -1
- package/dist/agentic/guides/modules/notifications/index.md +1 -1
- package/dist/agentic/guides/modules/onboarding/index.md +1 -1
- package/dist/agentic/guides/modules/payment_gateways/index.md +1 -1
- package/dist/agentic/guides/modules/perspectives/index.md +1 -1
- package/dist/agentic/guides/modules/planner/index.md +1 -1
- package/dist/agentic/guides/modules/portal/index.md +1 -1
- package/dist/agentic/guides/modules/progress/index.md +1 -1
- package/dist/agentic/guides/modules/push_notifications/index.md +1 -1
- package/dist/agentic/guides/modules/query_index/index.md +1 -1
- package/dist/agentic/guides/modules/record_locks/index.md +1 -1
- package/dist/agentic/guides/modules/resources/index.md +1 -1
- package/dist/agentic/guides/modules/sales/index.md +1 -1
- package/dist/agentic/guides/modules/scheduler/index.md +1 -1
- package/dist/agentic/guides/modules/search/index.md +1 -1
- package/dist/agentic/guides/modules/security/index.md +1 -1
- package/dist/agentic/guides/modules/shipping_carriers/index.md +1 -1
- package/dist/agentic/guides/modules/sso/index.md +1 -1
- package/dist/agentic/guides/modules/staff/index.md +1 -1
- package/dist/agentic/guides/modules/storage_s3/index.md +1 -1
- package/dist/agentic/guides/modules/sync_akeneo/index.md +1 -1
- package/dist/agentic/guides/modules/sync_excel/index.md +1 -1
- package/dist/agentic/guides/modules/system_status_overlays/index.md +1 -1
- package/dist/agentic/guides/modules/translations/index.md +1 -1
- package/dist/agentic/guides/modules/warranty_claims/index.md +1 -1
- package/dist/agentic/guides/modules/webhooks/index.md +1 -1
- package/dist/agentic/guides/modules/wms/index.md +1 -1
- package/dist/agentic/guides/modules/workflows/index.md +1 -1
- package/dist/agentic/guides/reference-module-facts.json +1 -1
- package/dist/agentic/guides/upstream/manifest.json +1 -1
- package/dist/lib/generators/module-registry.js +77 -11
- package/dist/lib/generators/module-registry.js.map +2 -2
- package/dist/mercato.js +14 -0
- package/dist/mercato.js.map +2 -2
- package/package.json +6 -6
- package/src/__tests__/resolve-queue-abandon-hook.test.ts +39 -0
- package/src/lib/generators/__tests__/generated-registry-imports.test.ts +128 -0
- package/src/lib/generators/__tests__/metadata-extraction.test.ts +44 -0
- package/src/lib/generators/module-registry.ts +118 -5
- package/src/mercato.ts +27 -0
|
@@ -320,6 +320,38 @@ function extractObjectPropertiesFromAst(sourceFile, exportName) {
|
|
|
320
320
|
}
|
|
321
321
|
return Object.keys(result).length > 0 ? result : null;
|
|
322
322
|
}
|
|
323
|
+
function namedObjectLiteralDeclaresProperty(sourceFile, exportName, propertyName) {
|
|
324
|
+
let source = "";
|
|
325
|
+
try {
|
|
326
|
+
source = fs.readFileSync(sourceFile, "utf8");
|
|
327
|
+
} catch {
|
|
328
|
+
return false;
|
|
329
|
+
}
|
|
330
|
+
const parsed = ts.createSourceFile(sourceFile, source, ts.ScriptTarget.Latest, true, inferScriptKind(sourceFile));
|
|
331
|
+
const exportedNames = /* @__PURE__ */ new Set();
|
|
332
|
+
for (const statement of parsed.statements) {
|
|
333
|
+
if (ts.isExportDeclaration(statement) && statement.exportClause && ts.isNamedExports(statement.exportClause) && !statement.moduleSpecifier) {
|
|
334
|
+
for (const element of statement.exportClause.elements) exportedNames.add(element.name.text);
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
for (const statement of parsed.statements) {
|
|
338
|
+
if (!ts.isVariableStatement(statement)) continue;
|
|
339
|
+
const exportsDirectly = (ts.canHaveModifiers(statement) ? ts.getModifiers(statement) : void 0)?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword);
|
|
340
|
+
for (const declaration of statement.declarationList.declarations) {
|
|
341
|
+
if (!ts.isIdentifier(declaration.name) || declaration.name.text !== exportName) continue;
|
|
342
|
+
if (!exportsDirectly && !exportedNames.has(exportName)) continue;
|
|
343
|
+
const objectLiteral2 = unwrapObjectLiteralExpression(declaration.initializer);
|
|
344
|
+
if (!objectLiteral2) return false;
|
|
345
|
+
return objectLiteral2.properties.some((property) => {
|
|
346
|
+
const name = property.name;
|
|
347
|
+
if (!name) return false;
|
|
348
|
+
const key = ts.isIdentifier(name) ? name.text : ts.isStringLiteral(name) ? name.text : null;
|
|
349
|
+
return key === propertyName;
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
return false;
|
|
354
|
+
}
|
|
323
355
|
function extractNamedObjectLiteralExport(sourceFile, exportName) {
|
|
324
356
|
const literal = extractNamedObjectLiteralSource(sourceFile, exportName);
|
|
325
357
|
if (literal) {
|
|
@@ -1238,6 +1270,7 @@ function normalizeWorkerMetadata(raw) {
|
|
|
1238
1270
|
if (typeof source.concurrency === "number") normalized.concurrency = source.concurrency;
|
|
1239
1271
|
if (typeof source.lockDuration === "number") normalized.lockDuration = source.lockDuration;
|
|
1240
1272
|
if (typeof source.maxStalledCount === "number") normalized.maxStalledCount = source.maxStalledCount;
|
|
1273
|
+
if (typeof source.onJobAbandoned === "function") normalized.hasJobAbandonedHook = true;
|
|
1241
1274
|
return Object.keys(normalized).length > 0 ? normalized : null;
|
|
1242
1275
|
}
|
|
1243
1276
|
async function loadSubscriberMetadata(sourceFile) {
|
|
@@ -1246,7 +1279,12 @@ async function loadSubscriberMetadata(sourceFile) {
|
|
|
1246
1279
|
}
|
|
1247
1280
|
async function loadWorkerMetadata(sourceFile) {
|
|
1248
1281
|
const sourceModule = await loadModuleExportsFromSource(sourceFile);
|
|
1249
|
-
|
|
1282
|
+
const metadata = normalizeWorkerMetadata(sourceModule?.metadata) ?? normalizeWorkerMetadata(extractNamedObjectLiteralExport(sourceFile, "metadata"));
|
|
1283
|
+
if (!metadata) return null;
|
|
1284
|
+
if (!metadata.hasJobAbandonedHook && namedObjectLiteralDeclaresProperty(sourceFile, "metadata", "onJobAbandoned")) {
|
|
1285
|
+
metadata.hasJobAbandonedHook = true;
|
|
1286
|
+
}
|
|
1287
|
+
return metadata;
|
|
1250
1288
|
}
|
|
1251
1289
|
async function discoverSubscribers(roots, imps, modId) {
|
|
1252
1290
|
const subscribers = [];
|
|
@@ -1708,12 +1746,16 @@ function processSubscribers(discovered) {
|
|
|
1708
1746
|
}
|
|
1709
1747
|
return subscribers;
|
|
1710
1748
|
}
|
|
1749
|
+
const ABANDON_HOOK_FACTORY = "createLazyModuleWorkerAbandonHook";
|
|
1750
|
+
function workersDeclareAbandonHook(discovered) {
|
|
1751
|
+
return discovered.some(({ metadata }) => metadata.hasJobAbandonedHook === true);
|
|
1752
|
+
}
|
|
1711
1753
|
function processWorkers(discovered) {
|
|
1712
1754
|
const workers = [];
|
|
1713
1755
|
for (const { id, importPath, metadata } of discovered) {
|
|
1714
1756
|
const workerId = metadata.id ?? id;
|
|
1715
1757
|
workers.push(
|
|
1716
|
-
`{ id: ${toLiteral(workerId)}, queue: ${toLiteral(metadata.queue)}, concurrency: ${toLiteral(metadata.concurrency ?? 1)}${metadata.lockDuration === void 0 ? "" : `, lockDuration: ${toLiteral(metadata.lockDuration)}`}${metadata.maxStalledCount === void 0 ? "" : `, maxStalledCount: ${toLiteral(metadata.maxStalledCount)}`}, handler: createLazyModuleWorker(() => ${buildDynamicImportExpression(importPath)}, ${toLiteral(workerId)}) }`
|
|
1758
|
+
`{ id: ${toLiteral(workerId)}, queue: ${toLiteral(metadata.queue)}, concurrency: ${toLiteral(metadata.concurrency ?? 1)}${metadata.lockDuration === void 0 ? "" : `, lockDuration: ${toLiteral(metadata.lockDuration)}`}${metadata.maxStalledCount === void 0 ? "" : `, maxStalledCount: ${toLiteral(metadata.maxStalledCount)}`}${metadata.hasJobAbandonedHook ? `, onJobAbandoned: ${ABANDON_HOOK_FACTORY}(() => ${buildDynamicImportExpression(importPath)}, ${toLiteral(workerId)})` : ""}, handler: createLazyModuleWorker(() => ${buildDynamicImportExpression(importPath)}, ${toLiteral(workerId)}) }`
|
|
1717
1759
|
);
|
|
1718
1760
|
}
|
|
1719
1761
|
return workers;
|
|
@@ -1920,6 +1962,7 @@ function renderAstModuleRegistryFile(options) {
|
|
|
1920
1962
|
namedImports: [
|
|
1921
1963
|
{ name: "createLazyModuleSubscriber" },
|
|
1922
1964
|
{ name: "createLazyModuleWorker" },
|
|
1965
|
+
...options.includeAbandonHookImport ? [{ name: ABANDON_HOOK_FACTORY }] : [],
|
|
1923
1966
|
{ name: "Module", isTypeOnly: true }
|
|
1924
1967
|
]
|
|
1925
1968
|
});
|
|
@@ -2010,9 +2053,10 @@ function buildLazyRouteComponentExpression(importPath) {
|
|
|
2010
2053
|
return `async (props: any) => { const mod = await ${buildDynamicImportExpression(importPath)}; const Component = (mod.default ?? mod) as any; return createElement(Component, props) }`;
|
|
2011
2054
|
}
|
|
2012
2055
|
function renderAstLegacyModuleRegistryOutput(options) {
|
|
2056
|
+
const needsAbandonHookImport = options.includeAbandonHookImport || options.moduleEntries.some((entry) => entry.includes(ABANDON_HOOK_FACTORY));
|
|
2013
2057
|
const importSection = [
|
|
2014
2058
|
...options.includeCreateElementImport ? ["import { createElement } from 'react'"] : [],
|
|
2015
|
-
"import { createLazyModuleSubscriber, createLazyModuleWorker, type Module } from '@open-mercato/shared/modules/registry'",
|
|
2059
|
+
needsAbandonHookImport ? "import { createLazyModuleSubscriber, createLazyModuleWorker, createLazyModuleWorkerAbandonHook, type Module } from '@open-mercato/shared/modules/registry'" : "import { createLazyModuleSubscriber, createLazyModuleWorker, type Module } from '@open-mercato/shared/modules/registry'",
|
|
2016
2060
|
...options.imports.map((entry) => serializeGeneratedImport(entry))
|
|
2017
2061
|
].join("\n");
|
|
2018
2062
|
return `// AUTO-GENERATED by mercato generate registry
|
|
@@ -2279,6 +2323,13 @@ function processWorkersAst(discovered) {
|
|
|
2279
2323
|
{ name: "concurrency", value: metadata.concurrency ?? 1 },
|
|
2280
2324
|
...metadata.lockDuration === void 0 ? [] : [{ name: "lockDuration", value: metadata.lockDuration }],
|
|
2281
2325
|
...metadata.maxStalledCount === void 0 ? [] : [{ name: "maxStalledCount", value: metadata.maxStalledCount }],
|
|
2326
|
+
...metadata.hasJobAbandonedHook ? [{
|
|
2327
|
+
name: "onJobAbandoned",
|
|
2328
|
+
value: callExpression(identifier(ABANDON_HOOK_FACTORY), [
|
|
2329
|
+
arrowFunction({ body: importExpression(importPath) }),
|
|
2330
|
+
workerId
|
|
2331
|
+
])
|
|
2332
|
+
}] : [],
|
|
2282
2333
|
{
|
|
2283
2334
|
name: "handler",
|
|
2284
2335
|
value: callExpression(identifier("createLazyModuleWorker"), [
|
|
@@ -2588,6 +2639,7 @@ async function generateModuleRegistryFromDiscovery(options) {
|
|
|
2588
2639
|
const requiresByModule = /* @__PURE__ */ new Map();
|
|
2589
2640
|
const commandLoaderEntries = [];
|
|
2590
2641
|
let hasRouteComponents = false;
|
|
2642
|
+
let hasAbandonHookWorkers = false;
|
|
2591
2643
|
const umesConflictSources = [];
|
|
2592
2644
|
const seenBackendRoutePatterns = /* @__PURE__ */ new Map();
|
|
2593
2645
|
for (const discovered of discovery.modules) {
|
|
@@ -2791,7 +2843,9 @@ async function generateModuleRegistryFromDiscovery(options) {
|
|
|
2791
2843
|
extraImports: runtimeImports
|
|
2792
2844
|
}));
|
|
2793
2845
|
subscribers.push(...processSubscribers(await discovered.getSubscribers()));
|
|
2794
|
-
|
|
2846
|
+
const discoveredWorkersForModule = await discovered.getWorkers();
|
|
2847
|
+
if (workersDeclareAbandonHook(discoveredWorkersForModule)) hasAbandonHookWorkers = true;
|
|
2848
|
+
workers.push(...processWorkers(discoveredWorkersForModule));
|
|
2795
2849
|
{
|
|
2796
2850
|
const parts = [];
|
|
2797
2851
|
if (fieldsImportName)
|
|
@@ -2943,13 +2997,15 @@ async function generateModuleRegistryFromDiscovery(options) {
|
|
|
2943
2997
|
fileName: "modules.generated.ts",
|
|
2944
2998
|
imports,
|
|
2945
2999
|
moduleEntries: moduleDecls,
|
|
2946
|
-
includeCreateElementImport: hasRouteComponents
|
|
3000
|
+
includeCreateElementImport: hasRouteComponents,
|
|
3001
|
+
includeAbandonHookImport: hasAbandonHookWorkers
|
|
2947
3002
|
});
|
|
2948
3003
|
const runtimeOutput = renderAstLegacyModuleRegistryOutput({
|
|
2949
3004
|
fileName: "modules.runtime.generated.ts",
|
|
2950
3005
|
imports: runtimeImports,
|
|
2951
3006
|
moduleEntries: runtimeModuleDecls,
|
|
2952
|
-
includeCreateElementImport: true
|
|
3007
|
+
includeCreateElementImport: true,
|
|
3008
|
+
includeAbandonHookImport: hasAbandonHookWorkers
|
|
2953
3009
|
});
|
|
2954
3010
|
const frontendRoutesOutput = renderAstLegacyManifestOutput({
|
|
2955
3011
|
fileName: "frontend-routes.generated.ts",
|
|
@@ -3137,6 +3193,7 @@ async function generateModuleRegistryAppFromDiscovery(options) {
|
|
|
3137
3193
|
const requiresByModule = /* @__PURE__ */ new Map();
|
|
3138
3194
|
const commandLoaderEntries = [];
|
|
3139
3195
|
let hasRouteComponents = false;
|
|
3196
|
+
let hasAbandonHookWorkers = false;
|
|
3140
3197
|
const seenBackendRoutePatterns = /* @__PURE__ */ new Map();
|
|
3141
3198
|
for (const discovered of discovery.modules) {
|
|
3142
3199
|
const { modId, roots, imps, appImportBase } = discovered;
|
|
@@ -3282,7 +3339,9 @@ async function generateModuleRegistryAppFromDiscovery(options) {
|
|
|
3282
3339
|
i18nLocaleShards.set(locale, shard);
|
|
3283
3340
|
}
|
|
3284
3341
|
subscribers.push(...processSubscribersAst(await discovered.getSubscribers()));
|
|
3285
|
-
|
|
3342
|
+
const discoveredWorkersForModule = await discovered.getWorkers();
|
|
3343
|
+
if (workersDeclareAbandonHook(discoveredWorkersForModule)) hasAbandonHookWorkers = true;
|
|
3344
|
+
workers.push(...processWorkersAst(discoveredWorkersForModule));
|
|
3286
3345
|
{
|
|
3287
3346
|
dashboardWidgetsValue = buildModuleDashboardWidgetsValue(discovered.dashboardWidgetEntries);
|
|
3288
3347
|
}
|
|
@@ -3399,19 +3458,22 @@ async function generateModuleRegistryAppFromDiscovery(options) {
|
|
|
3399
3458
|
generator: "registry (app version)",
|
|
3400
3459
|
imports,
|
|
3401
3460
|
moduleEntries: moduleDecls,
|
|
3402
|
-
includeCreateElementImport: hasRouteComponents
|
|
3461
|
+
includeCreateElementImport: hasRouteComponents,
|
|
3462
|
+
includeAbandonHookImport: hasAbandonHookWorkers
|
|
3403
3463
|
});
|
|
3404
3464
|
const bootstrapOutput = renderAstModuleRegistryFile({
|
|
3405
3465
|
fileName: "modules.bootstrap.generated.ts",
|
|
3406
3466
|
generator: "registry (bootstrap version)",
|
|
3407
3467
|
imports: bootstrapImports,
|
|
3408
|
-
moduleEntries: bootstrapModuleDecls
|
|
3468
|
+
moduleEntries: bootstrapModuleDecls,
|
|
3469
|
+
includeAbandonHookImport: hasAbandonHookWorkers
|
|
3409
3470
|
});
|
|
3410
3471
|
const i18nOutput = renderAstModuleRegistryFile({
|
|
3411
3472
|
fileName: "modules.i18n.generated.ts",
|
|
3412
3473
|
generator: "registry (i18n version)",
|
|
3413
3474
|
imports: i18nImports,
|
|
3414
|
-
moduleEntries: i18nModuleDecls
|
|
3475
|
+
moduleEntries: i18nModuleDecls,
|
|
3476
|
+
includeAbandonHookImport: hasAbandonHookWorkers
|
|
3415
3477
|
});
|
|
3416
3478
|
const legacyOutput = renderAstLegacyAliasFile({
|
|
3417
3479
|
fileName: "bootstrap-modules.generated.ts",
|
|
@@ -3486,6 +3548,7 @@ async function generateModuleRegistryAppFromDiscovery(options) {
|
|
|
3486
3548
|
return result;
|
|
3487
3549
|
}
|
|
3488
3550
|
async function generateModuleRegistryCliFromDiscovery(options) {
|
|
3551
|
+
let hasAbandonHookWorkers = false;
|
|
3489
3552
|
const { resolver, quiet = false } = options;
|
|
3490
3553
|
const { discovery } = options;
|
|
3491
3554
|
const result = createGeneratorResult();
|
|
@@ -3604,6 +3667,7 @@ async function generateModuleRegistryCliFromDiscovery(options) {
|
|
|
3604
3667
|
subscribers.push(...processSubscribersAst(await discovered.getSubscribers()));
|
|
3605
3668
|
const discoveredWorkers = await discovered.getWorkers();
|
|
3606
3669
|
const workerGenerationEntries = collectWorkerGenerationEntries(discoveredWorkers, modId);
|
|
3670
|
+
if (workersDeclareAbandonHook(discoveredWorkers)) hasAbandonHookWorkers = true;
|
|
3607
3671
|
workers.push(...processWorkersAst(discoveredWorkers));
|
|
3608
3672
|
devSupervisorWorkers.push(...workerGenerationEntries.map(({ importPath: _importPath, ...worker }) => worker));
|
|
3609
3673
|
{
|
|
@@ -3720,7 +3784,8 @@ async function generateModuleRegistryCliFromDiscovery(options) {
|
|
|
3720
3784
|
fileName: "modules.cli.generated.ts",
|
|
3721
3785
|
generator: "registry (CLI version)",
|
|
3722
3786
|
imports,
|
|
3723
|
-
moduleEntries: moduleDecls
|
|
3787
|
+
moduleEntries: moduleDecls,
|
|
3788
|
+
includeAbandonHookImport: hasAbandonHookWorkers
|
|
3724
3789
|
});
|
|
3725
3790
|
const legacyOutput = renderAstLegacyAliasFile({
|
|
3726
3791
|
fileName: "cli-modules.generated.ts",
|
|
@@ -3806,6 +3871,7 @@ export {
|
|
|
3806
3871
|
generateModuleRegistryApp,
|
|
3807
3872
|
generateModuleRegistryCli,
|
|
3808
3873
|
hasNamedExport,
|
|
3874
|
+
namedObjectLiteralDeclaresProperty,
|
|
3809
3875
|
resetConventionWarnings,
|
|
3810
3876
|
resolveNamedObjectExport,
|
|
3811
3877
|
warnIfPageMetaMissingMetadataExport,
|