@eventcatalog/cli 0.3.2 → 0.3.4
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/index.js +281 -92
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +281 -92
- package/dist/cli/index.mjs.map +1 -1
- package/dist/cli-docs.js +23 -3
- package/dist/cli-docs.js.map +1 -1
- package/dist/cli-docs.mjs +23 -3
- package/dist/cli-docs.mjs.map +1 -1
- package/package.json +4 -3
package/dist/cli/index.mjs
CHANGED
|
@@ -124,6 +124,7 @@ import { resolve } from "path";
|
|
|
124
124
|
import open from "open";
|
|
125
125
|
import createSDK3 from "@eventcatalog/sdk";
|
|
126
126
|
var RESOURCE_TYPES = ["event", "command", "query", "service", "domain"];
|
|
127
|
+
var SUPPORTED_RESOURCE_TYPES = RESOURCE_TYPES.join(", ");
|
|
127
128
|
var PLURAL_MAP = {
|
|
128
129
|
events: "event",
|
|
129
130
|
commands: "command",
|
|
@@ -131,11 +132,40 @@ var PLURAL_MAP = {
|
|
|
131
132
|
services: "service",
|
|
132
133
|
domains: "domain"
|
|
133
134
|
};
|
|
135
|
+
var KNOWN_UNSUPPORTED_EXPORT_TYPES = /* @__PURE__ */ new Set([
|
|
136
|
+
"channel",
|
|
137
|
+
"channels",
|
|
138
|
+
"team",
|
|
139
|
+
"teams",
|
|
140
|
+
"user",
|
|
141
|
+
"users",
|
|
142
|
+
"container",
|
|
143
|
+
"containers",
|
|
144
|
+
"data-product",
|
|
145
|
+
"data-products",
|
|
146
|
+
"dataproduct",
|
|
147
|
+
"dataproducts",
|
|
148
|
+
"diagram",
|
|
149
|
+
"diagrams",
|
|
150
|
+
"flow",
|
|
151
|
+
"flows"
|
|
152
|
+
]);
|
|
134
153
|
function normalizeResourceType(resource) {
|
|
135
154
|
const lower = resource.toLowerCase();
|
|
136
155
|
if (PLURAL_MAP[lower]) return PLURAL_MAP[lower];
|
|
137
156
|
return lower;
|
|
138
157
|
}
|
|
158
|
+
function assertSupportedExportType(resource, type) {
|
|
159
|
+
const lower = resource.toLowerCase();
|
|
160
|
+
if (KNOWN_UNSUPPORTED_EXPORT_TYPES.has(lower)) {
|
|
161
|
+
throw new Error(
|
|
162
|
+
`Resource type '${resource}' is not yet supported for DSL export. Supported types: ${SUPPORTED_RESOURCE_TYPES}`
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
if (!RESOURCE_TYPES.includes(type)) {
|
|
166
|
+
throw new Error(`Invalid resource type '${resource}'. Must be one of: ${SUPPORTED_RESOURCE_TYPES}`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
139
169
|
function getResourceFetcher(sdk, type) {
|
|
140
170
|
switch (type) {
|
|
141
171
|
case "event":
|
|
@@ -226,14 +256,14 @@ ${entries.join("\n")}
|
|
|
226
256
|
async function exportCatalog(options) {
|
|
227
257
|
const { hydrate = false, stdout = false, playground = false, output, dir } = options;
|
|
228
258
|
const sdk = createSDK3(dir);
|
|
229
|
-
const dslParts =
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
259
|
+
const dslParts = (await Promise.all(
|
|
260
|
+
RESOURCE_TYPES.map(async (type) => {
|
|
261
|
+
const fetcher = getCollectionFetcher(sdk, type);
|
|
262
|
+
const resources = await fetcher({ latestOnly: true });
|
|
263
|
+
if (!resources || resources.length === 0) return "";
|
|
264
|
+
return sdk.toDSL(resources, { type, hydrate });
|
|
265
|
+
})
|
|
266
|
+
)).filter((dsl2) => Boolean(dsl2));
|
|
237
267
|
if (dslParts.length === 0) {
|
|
238
268
|
throw new Error(`No resources found in catalog at '${dir}'`);
|
|
239
269
|
}
|
|
@@ -253,9 +283,9 @@ ${vizBlock}` : grouped;
|
|
|
253
283
|
const encoded = Buffer.from(dsl).toString("base64");
|
|
254
284
|
const playgroundUrl = `https://playground.eventcatalog.dev/?code=${encoded}`;
|
|
255
285
|
await open(playgroundUrl);
|
|
256
|
-
lines.push("", ` Opening in
|
|
286
|
+
lines.push("", ` Opening in EventCatalog Modelling...`);
|
|
257
287
|
} else {
|
|
258
|
-
lines.push("", ` Tip: Use --playground to open in
|
|
288
|
+
lines.push("", ` Tip: Use --playground to open in EventCatalog Modelling`);
|
|
259
289
|
}
|
|
260
290
|
lines.push("");
|
|
261
291
|
return lines.join("\n");
|
|
@@ -263,9 +293,7 @@ ${vizBlock}` : grouped;
|
|
|
263
293
|
async function exportAll(options) {
|
|
264
294
|
const { resource, hydrate = false, stdout = false, playground = false, output, dir } = options;
|
|
265
295
|
const type = normalizeResourceType(resource);
|
|
266
|
-
|
|
267
|
-
throw new Error(`Invalid resource type '${resource}'. Must be one of: ${RESOURCE_TYPES.join(", ")}`);
|
|
268
|
-
}
|
|
296
|
+
assertSupportedExportType(resource, type);
|
|
269
297
|
const plural = pluralize(type);
|
|
270
298
|
const sdk = createSDK3(dir);
|
|
271
299
|
const fetcher = getCollectionFetcher(sdk, type);
|
|
@@ -289,9 +317,9 @@ ${vizBlock}` : grouped;
|
|
|
289
317
|
const encoded = Buffer.from(dsl).toString("base64");
|
|
290
318
|
const playgroundUrl = `https://playground.eventcatalog.dev/?code=${encoded}`;
|
|
291
319
|
await open(playgroundUrl);
|
|
292
|
-
lines.push("", ` Opening in
|
|
320
|
+
lines.push("", ` Opening in EventCatalog Modelling...`);
|
|
293
321
|
} else {
|
|
294
|
-
lines.push("", ` Tip: Use --playground to open in
|
|
322
|
+
lines.push("", ` Tip: Use --playground to open in EventCatalog Modelling`);
|
|
295
323
|
}
|
|
296
324
|
lines.push("");
|
|
297
325
|
return lines.join("\n");
|
|
@@ -302,9 +330,7 @@ async function exportResource(options) {
|
|
|
302
330
|
return exportAll(options);
|
|
303
331
|
}
|
|
304
332
|
const type = normalizeResourceType(resource);
|
|
305
|
-
|
|
306
|
-
throw new Error(`Invalid resource type '${resource}'. Must be one of: ${RESOURCE_TYPES.join(", ")}`);
|
|
307
|
-
}
|
|
333
|
+
assertSupportedExportType(resource, type);
|
|
308
334
|
const sdk = createSDK3(dir);
|
|
309
335
|
const fetcher = getResourceFetcher(sdk, type);
|
|
310
336
|
const data = await fetcher(id, version2);
|
|
@@ -328,9 +354,9 @@ ${vizBlock}` : grouped;
|
|
|
328
354
|
const encoded = Buffer.from(dsl).toString("base64");
|
|
329
355
|
const playgroundUrl = `https://playground.eventcatalog.dev/?code=${encoded}`;
|
|
330
356
|
await open(playgroundUrl);
|
|
331
|
-
lines.push("", ` Opening in
|
|
357
|
+
lines.push("", ` Opening in EventCatalog Modelling...`);
|
|
332
358
|
} else {
|
|
333
|
-
lines.push("", ` Tip: Use --playground to open in
|
|
359
|
+
lines.push("", ` Tip: Use --playground to open in EventCatalog Modelling`);
|
|
334
360
|
}
|
|
335
361
|
lines.push("");
|
|
336
362
|
return lines.join("\n");
|
|
@@ -343,6 +369,20 @@ import { randomUUID } from "crypto";
|
|
|
343
369
|
import { createInterface } from "readline";
|
|
344
370
|
import matter from "gray-matter";
|
|
345
371
|
import createSDK4 from "@eventcatalog/sdk";
|
|
372
|
+
function normalizeImportedFrontmatter(type, frontmatter) {
|
|
373
|
+
const normalized = { ...frontmatter };
|
|
374
|
+
if (type === "container") {
|
|
375
|
+
if (normalized.container_type === void 0 && normalized.containerType !== void 0) {
|
|
376
|
+
normalized.container_type = normalized.containerType;
|
|
377
|
+
delete normalized.containerType;
|
|
378
|
+
}
|
|
379
|
+
if (normalized.access_mode === void 0 && normalized.accessMode !== void 0) {
|
|
380
|
+
normalized.access_mode = normalized.accessMode;
|
|
381
|
+
delete normalized.accessMode;
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
return normalized;
|
|
385
|
+
}
|
|
346
386
|
var RESOURCE_TYPE_FROM_FOLDER = {
|
|
347
387
|
events: "event",
|
|
348
388
|
commands: "command",
|
|
@@ -377,7 +417,7 @@ ${messages.join("\n")}`);
|
|
|
377
417
|
services.shared.workspace.LangiumDocuments.deleteDocument(uri);
|
|
378
418
|
} catch {
|
|
379
419
|
}
|
|
380
|
-
return outputs;
|
|
420
|
+
return { outputs, program: program2 };
|
|
381
421
|
}
|
|
382
422
|
function extractResourceTypeFolder(path2) {
|
|
383
423
|
const segments = path2.split("/");
|
|
@@ -409,15 +449,17 @@ var MESSAGE_TYPE_FOLDER = {
|
|
|
409
449
|
channel: "channels"
|
|
410
450
|
};
|
|
411
451
|
var DEFAULT_STUB_VERSION = "0.0.1";
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
452
|
+
var NO_VERSION_KEY = "__no_version__";
|
|
453
|
+
function getResourceNameKey(type, id) {
|
|
454
|
+
return `${type}:${id}`;
|
|
455
|
+
}
|
|
456
|
+
function getResourceVersionKey(type, id, version2) {
|
|
457
|
+
return `${type}:${id}@${version2 || NO_VERSION_KEY}`;
|
|
458
|
+
}
|
|
459
|
+
function hasReferenceStatements(source) {
|
|
460
|
+
return /\b(?:sends|receives|writes-to|reads-from)\b/.test(source);
|
|
461
|
+
}
|
|
462
|
+
async function extractMessageStubs(program2, compiledIds, nested = false) {
|
|
421
463
|
const stubs = [];
|
|
422
464
|
const stubIds = /* @__PURE__ */ new Set();
|
|
423
465
|
function processDefinitions(definitions, parentPath = "") {
|
|
@@ -443,63 +485,143 @@ async function extractMessageStubs(source, compiledIds, nested = false) {
|
|
|
443
485
|
const servicePath = nested ? parentPath ? `${parentPath}/services/${def.name}` : `services/${def.name}` : "";
|
|
444
486
|
const body = def.body || [];
|
|
445
487
|
for (const stmt of body) {
|
|
446
|
-
if (stmt.$type
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
const
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
488
|
+
if (stmt.$type === "SendsStmt" || stmt.$type === "ReceivesStmt") {
|
|
489
|
+
const msgType = stmt.messageType;
|
|
490
|
+
const msgName = stmt.messageName;
|
|
491
|
+
const hasBody = stmt.body && stmt.body.length > 0;
|
|
492
|
+
const version2 = stmt.version || DEFAULT_STUB_VERSION;
|
|
493
|
+
if (!hasBody) {
|
|
494
|
+
const folder = MESSAGE_TYPE_FOLDER[msgType];
|
|
495
|
+
if (folder) {
|
|
496
|
+
const key = getResourceVersionKey(msgType, msgName, version2);
|
|
497
|
+
const anyVersionKey = getResourceNameKey(msgType, msgName);
|
|
498
|
+
if (!compiledIds.has(key) && !stubIds.has(key) && !(!stmt.version && compiledIds.has(anyVersionKey))) {
|
|
499
|
+
const stubFolder = nested && servicePath ? `${servicePath}/${folder}` : folder;
|
|
500
|
+
stubIds.add(key);
|
|
501
|
+
stubs.push({
|
|
502
|
+
type: msgType,
|
|
503
|
+
id: msgName,
|
|
504
|
+
version: version2,
|
|
505
|
+
frontmatter: {
|
|
506
|
+
id: msgName,
|
|
507
|
+
name: msgName,
|
|
508
|
+
version: version2
|
|
509
|
+
},
|
|
510
|
+
markdown: "",
|
|
511
|
+
path: `${stubFolder}/${msgName}/versioned/${version2}/index.md`
|
|
512
|
+
});
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
if (stmt.channelClause) {
|
|
517
|
+
const channels = stmt.channelClause.channels || [];
|
|
518
|
+
for (const ch of channels) {
|
|
519
|
+
const chName = ch.channelName;
|
|
520
|
+
const chVersion = ch.channelVersion || DEFAULT_STUB_VERSION;
|
|
521
|
+
const chKey = getResourceVersionKey("channel", chName, chVersion);
|
|
522
|
+
const chAnyVersionKey = getResourceNameKey("channel", chName);
|
|
523
|
+
if (compiledIds.has(chKey) || stubIds.has(chKey)) continue;
|
|
524
|
+
if (!ch.channelVersion && compiledIds.has(chAnyVersionKey)) continue;
|
|
525
|
+
const chFolder = nested && parentPath ? `${parentPath}/channels` : "channels";
|
|
526
|
+
stubIds.add(chKey);
|
|
527
|
+
stubs.push({
|
|
528
|
+
type: "channel",
|
|
484
529
|
id: chName,
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
530
|
+
version: chVersion,
|
|
531
|
+
frontmatter: {
|
|
532
|
+
id: chName,
|
|
533
|
+
name: chName,
|
|
534
|
+
version: chVersion
|
|
535
|
+
},
|
|
536
|
+
markdown: "",
|
|
537
|
+
path: `${chFolder}/${chName}/versioned/${chVersion}/index.md`
|
|
538
|
+
});
|
|
539
|
+
}
|
|
491
540
|
}
|
|
541
|
+
continue;
|
|
542
|
+
}
|
|
543
|
+
if (stmt.$type === "WritesToStmt" || stmt.$type === "ReadsFromStmt") {
|
|
544
|
+
const containerName = stmt.ref?.name;
|
|
545
|
+
if (!containerName) continue;
|
|
546
|
+
const containerVersion = stmt.ref?.version || DEFAULT_STUB_VERSION;
|
|
547
|
+
const containerKey = getResourceVersionKey("container", containerName, containerVersion);
|
|
548
|
+
const containerAnyVersionKey = getResourceNameKey("container", containerName);
|
|
549
|
+
if (compiledIds.has(containerKey) || stubIds.has(containerKey)) continue;
|
|
550
|
+
if (!stmt.ref?.version && compiledIds.has(containerAnyVersionKey)) continue;
|
|
551
|
+
const containerFolder = nested && parentPath ? `${parentPath}/containers` : "containers";
|
|
552
|
+
stubIds.add(containerKey);
|
|
553
|
+
stubs.push({
|
|
554
|
+
type: "container",
|
|
555
|
+
id: containerName,
|
|
556
|
+
version: containerVersion,
|
|
557
|
+
frontmatter: {
|
|
558
|
+
id: containerName,
|
|
559
|
+
name: containerName,
|
|
560
|
+
version: containerVersion
|
|
561
|
+
},
|
|
562
|
+
markdown: "",
|
|
563
|
+
path: `${containerFolder}/${containerName}/versioned/${containerVersion}/index.md`
|
|
564
|
+
});
|
|
492
565
|
}
|
|
493
566
|
}
|
|
494
567
|
}
|
|
495
568
|
}
|
|
496
569
|
processDefinitions(program2.definitions);
|
|
497
|
-
try {
|
|
498
|
-
services.shared.workspace.LangiumDocuments.deleteDocument(uri);
|
|
499
|
-
} catch {
|
|
500
|
-
}
|
|
501
570
|
return stubs;
|
|
502
571
|
}
|
|
572
|
+
function getVersionFromBody(body) {
|
|
573
|
+
if (!body) return void 0;
|
|
574
|
+
const versionStmt = body.find((stmt) => stmt?.$type === "VersionStmt");
|
|
575
|
+
return versionStmt?.value;
|
|
576
|
+
}
|
|
577
|
+
function buildServiceOutputPath(serviceName, body, nested, parentPath) {
|
|
578
|
+
const folder = nested && parentPath ? `${parentPath}/services` : "services";
|
|
579
|
+
const version2 = getVersionFromBody(body);
|
|
580
|
+
if (version2) return `${folder}/${serviceName}/versioned/${version2}/index.md`;
|
|
581
|
+
return `${folder}/${serviceName}/index.md`;
|
|
582
|
+
}
|
|
583
|
+
function extractServiceContainerRefs(program2, nested = false) {
|
|
584
|
+
const refsByPath = /* @__PURE__ */ new Map();
|
|
585
|
+
function processDefinitions(definitions, parentPath = "") {
|
|
586
|
+
for (const def of definitions || []) {
|
|
587
|
+
if (def.$type === "VisualizerDef" && def.body) {
|
|
588
|
+
processDefinitions(def.body, parentPath);
|
|
589
|
+
continue;
|
|
590
|
+
}
|
|
591
|
+
if (def.$type === "DomainDef") {
|
|
592
|
+
const domainPath = nested ? `domains/${def.name}` : "";
|
|
593
|
+
const domainBody = def.body || [];
|
|
594
|
+
const domainServices = domainBody.filter((d) => d.$type === "ServiceDef");
|
|
595
|
+
processDefinitions(domainServices, domainPath);
|
|
596
|
+
const subdomains = domainBody.filter((d) => d.$type === "SubdomainDef");
|
|
597
|
+
for (const sub of subdomains) {
|
|
598
|
+
const subPath = nested ? `domains/${def.name}/subdomains/${sub.name}` : "";
|
|
599
|
+
const subServices = (sub.body || []).filter((d) => d.$type === "ServiceDef");
|
|
600
|
+
processDefinitions(subServices, subPath);
|
|
601
|
+
}
|
|
602
|
+
continue;
|
|
603
|
+
}
|
|
604
|
+
if (def.$type !== "ServiceDef") continue;
|
|
605
|
+
const body = def.body || [];
|
|
606
|
+
const writesTo = body.filter((stmt) => stmt.$type === "WritesToStmt" && stmt.ref?.name).map((stmt) => ({
|
|
607
|
+
id: stmt.ref.name,
|
|
608
|
+
...stmt.ref.version ? { version: stmt.ref.version } : {}
|
|
609
|
+
}));
|
|
610
|
+
const readsFrom = body.filter((stmt) => stmt.$type === "ReadsFromStmt" && stmt.ref?.name).map((stmt) => ({
|
|
611
|
+
id: stmt.ref.name,
|
|
612
|
+
...stmt.ref.version ? { version: stmt.ref.version } : {}
|
|
613
|
+
}));
|
|
614
|
+
if (writesTo.length === 0 && readsFrom.length === 0) continue;
|
|
615
|
+
const path2 = buildServiceOutputPath(def.name, body, nested, parentPath);
|
|
616
|
+
refsByPath.set(path2, {
|
|
617
|
+
...writesTo.length > 0 ? { writesTo } : {},
|
|
618
|
+
...readsFrom.length > 0 ? { readsFrom } : {}
|
|
619
|
+
});
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
processDefinitions(program2.definitions || []);
|
|
623
|
+
return refsByPath;
|
|
624
|
+
}
|
|
503
625
|
var SDK_WRITER_BASE = {
|
|
504
626
|
event: "events",
|
|
505
627
|
command: "commands",
|
|
@@ -508,6 +630,8 @@ var SDK_WRITER_BASE = {
|
|
|
508
630
|
domain: "domains",
|
|
509
631
|
channel: "channels",
|
|
510
632
|
container: "containers",
|
|
633
|
+
dataProduct: "data-products",
|
|
634
|
+
diagram: "diagrams",
|
|
511
635
|
team: "teams",
|
|
512
636
|
user: "users"
|
|
513
637
|
};
|
|
@@ -537,6 +661,12 @@ function getWriter(sdk, type) {
|
|
|
537
661
|
return sdk.writeDomain;
|
|
538
662
|
case "channel":
|
|
539
663
|
return sdk.writeChannel;
|
|
664
|
+
case "container":
|
|
665
|
+
return sdk.writeDataStore;
|
|
666
|
+
case "dataProduct":
|
|
667
|
+
return sdk.writeDataProduct;
|
|
668
|
+
case "diagram":
|
|
669
|
+
return sdk.writeDiagram;
|
|
540
670
|
case "team":
|
|
541
671
|
return sdk.writeTeam;
|
|
542
672
|
case "user":
|
|
@@ -559,6 +689,12 @@ function getReader(sdk, type) {
|
|
|
559
689
|
return sdk.getDomain;
|
|
560
690
|
case "channel":
|
|
561
691
|
return sdk.getChannel;
|
|
692
|
+
case "container":
|
|
693
|
+
return sdk.getDataStore;
|
|
694
|
+
case "dataProduct":
|
|
695
|
+
return sdk.getDataProduct;
|
|
696
|
+
case "diagram":
|
|
697
|
+
return sdk.getDiagram;
|
|
562
698
|
case "team":
|
|
563
699
|
return sdk.getTeam;
|
|
564
700
|
case "user":
|
|
@@ -702,26 +838,57 @@ async function importDSL(options) {
|
|
|
702
838
|
didInit = true;
|
|
703
839
|
}
|
|
704
840
|
}
|
|
705
|
-
const
|
|
841
|
+
const parsed = await parseDSL(source, { nested });
|
|
842
|
+
const outputs = parsed.outputs;
|
|
706
843
|
if (outputs.length === 0) {
|
|
707
844
|
throw new Error("No resources found in DSL content");
|
|
708
845
|
}
|
|
709
846
|
const sdk = createSDK4(catalogDir);
|
|
710
847
|
const result = { created: [], updated: [], versioned: [], errors: [] };
|
|
848
|
+
const readerCache = /* @__PURE__ */ new Map();
|
|
849
|
+
const readResourceCached = async (reader, type, id, version2) => {
|
|
850
|
+
if (!reader) return void 0;
|
|
851
|
+
const cacheKey = getResourceVersionKey(type, id, version2);
|
|
852
|
+
if (!readerCache.has(cacheKey)) {
|
|
853
|
+
readerCache.set(
|
|
854
|
+
cacheKey,
|
|
855
|
+
reader(id, version2).catch(() => void 0)
|
|
856
|
+
);
|
|
857
|
+
}
|
|
858
|
+
return await readerCache.get(cacheKey);
|
|
859
|
+
};
|
|
860
|
+
const invalidateReaderCache = (type, id, version2) => {
|
|
861
|
+
readerCache.delete(getResourceVersionKey(type, id));
|
|
862
|
+
readerCache.delete(getResourceVersionKey(type, id, version2));
|
|
863
|
+
};
|
|
711
864
|
const resources = outputs.map(parseCompiledOutput);
|
|
712
|
-
const
|
|
713
|
-
const
|
|
865
|
+
const serviceContainerRefsByPath = extractServiceContainerRefs(parsed.program, nested);
|
|
866
|
+
for (const resource of resources) {
|
|
867
|
+
if (resource.type !== "service") continue;
|
|
868
|
+
const refs = serviceContainerRefsByPath.get(resource.path);
|
|
869
|
+
if (!refs) continue;
|
|
870
|
+
resource.frontmatter = {
|
|
871
|
+
...resource.frontmatter,
|
|
872
|
+
...refs
|
|
873
|
+
};
|
|
874
|
+
}
|
|
875
|
+
const compiledIds = /* @__PURE__ */ new Set();
|
|
876
|
+
for (const resource of resources) {
|
|
877
|
+
compiledIds.add(getResourceNameKey(resource.type, resource.id));
|
|
878
|
+
compiledIds.add(getResourceVersionKey(resource.type, resource.id, resource.version));
|
|
879
|
+
}
|
|
880
|
+
const stubs = hasReferenceStatements(source) ? await extractMessageStubs(parsed.program, compiledIds, nested) : [];
|
|
714
881
|
resources.push(...stubs);
|
|
715
882
|
for (const resource of resources) {
|
|
716
883
|
const label = resource.version ? `${resource.type} ${resource.id}@${resource.version}` : `${resource.type} ${resource.id}`;
|
|
717
884
|
if (dryRun) {
|
|
718
885
|
const reader = getReader(sdk, resource.type);
|
|
719
886
|
if (reader) {
|
|
720
|
-
const existing = await reader
|
|
887
|
+
const existing = await readResourceCached(reader, resource.type, resource.id, resource.version);
|
|
721
888
|
if (existing) {
|
|
722
889
|
result.updated.push(label);
|
|
723
890
|
} else {
|
|
724
|
-
const latest = await reader
|
|
891
|
+
const latest = await readResourceCached(reader, resource.type, resource.id);
|
|
725
892
|
if (latest && latest.version && latest.version !== resource.version) {
|
|
726
893
|
result.versioned.push(`${resource.type} ${resource.id}@${latest.version}`);
|
|
727
894
|
}
|
|
@@ -739,20 +906,35 @@ async function importDSL(options) {
|
|
|
739
906
|
}
|
|
740
907
|
try {
|
|
741
908
|
const reader = getReader(sdk, resource.type);
|
|
742
|
-
const existing =
|
|
743
|
-
|
|
909
|
+
const existing = await readResourceCached(reader, resource.type, resource.id, resource.version);
|
|
910
|
+
const latest = !existing && resource.version ? await readResourceCached(reader, resource.type, resource.id) : void 0;
|
|
911
|
+
const versionedFrom = !existing && resource.version && latest?.version && latest.version !== resource.version ? latest.version : void 0;
|
|
912
|
+
const incomingMarkdown = resource.markdown;
|
|
913
|
+
const hasIncomingMarkdown = incomingMarkdown.trim().length > 0;
|
|
914
|
+
let markdown = incomingMarkdown;
|
|
915
|
+
if (!hasIncomingMarkdown) {
|
|
916
|
+
if (existing?.markdown) {
|
|
917
|
+
markdown = existing.markdown;
|
|
918
|
+
} else if (!existing && latest?.markdown) {
|
|
919
|
+
markdown = latest.markdown;
|
|
920
|
+
}
|
|
921
|
+
}
|
|
744
922
|
if (!existing && TYPES_WITH_NODE_GRAPH.has(resource.type)) {
|
|
745
|
-
|
|
923
|
+
if (!markdown) {
|
|
924
|
+
markdown = "<NodeGraph />";
|
|
925
|
+
} else if (!markdown.includes("<NodeGraph />")) {
|
|
926
|
+
markdown = `${markdown}
|
|
746
927
|
|
|
747
|
-
<NodeGraph
|
|
928
|
+
<NodeGraph />`;
|
|
929
|
+
}
|
|
748
930
|
}
|
|
749
931
|
const resourceData = {
|
|
750
|
-
...resource.frontmatter,
|
|
932
|
+
...normalizeImportedFrontmatter(resource.type, resource.frontmatter),
|
|
751
933
|
markdown
|
|
752
934
|
};
|
|
753
935
|
const writeOptions = {
|
|
754
936
|
override: true,
|
|
755
|
-
versionExistingContent:
|
|
937
|
+
versionExistingContent: Boolean(versionedFrom)
|
|
756
938
|
};
|
|
757
939
|
if (!existing && nested) {
|
|
758
940
|
const sdkPath = extractSdkPath(resource.path, resource.type);
|
|
@@ -761,10 +943,14 @@ async function importDSL(options) {
|
|
|
761
943
|
}
|
|
762
944
|
}
|
|
763
945
|
await writer(resourceData, writeOptions);
|
|
946
|
+
invalidateReaderCache(resource.type, resource.id, resource.version);
|
|
764
947
|
if (existing) {
|
|
765
948
|
result.updated.push(label);
|
|
766
949
|
} else {
|
|
767
950
|
result.created.push(label);
|
|
951
|
+
if (versionedFrom) {
|
|
952
|
+
result.versioned.push(`${resource.type} ${resource.id}@${versionedFrom}`);
|
|
953
|
+
}
|
|
768
954
|
}
|
|
769
955
|
} catch (error) {
|
|
770
956
|
result.errors.push(`${label}: ${error instanceof Error ? error.message : String(error)}`);
|
|
@@ -798,8 +984,11 @@ var TYPE_CONFIG = {
|
|
|
798
984
|
query: { color: c.cyan, label: "query", order: 4 },
|
|
799
985
|
channel: { color: c.gray, label: "channel", order: 5 },
|
|
800
986
|
flow: { color: c.white, label: "flow", order: 6 },
|
|
801
|
-
|
|
802
|
-
|
|
987
|
+
container: { color: c.white, label: "container", order: 7 },
|
|
988
|
+
dataProduct: { color: c.white, label: "data product", order: 8 },
|
|
989
|
+
diagram: { color: c.white, label: "diagram", order: 9 },
|
|
990
|
+
user: { color: c.blue, label: "user", order: 10 },
|
|
991
|
+
team: { color: c.blue, label: "team", order: 11 }
|
|
803
992
|
};
|
|
804
993
|
var DEFAULT_TYPE_CONFIG = { color: c.white, label: "resource", order: 99 };
|
|
805
994
|
function parseLabel(label) {
|
|
@@ -912,7 +1101,7 @@ program.command("list").description("List all available SDK functions").action((
|
|
|
912
1101
|
process.exit(1);
|
|
913
1102
|
}
|
|
914
1103
|
});
|
|
915
|
-
program.command("export").description("Export a catalog resource to EventCatalog DSL (.ec) format").option("-a, --all", "Export the entire catalog (all resource types)", false).option("-r, --resource <type>", "Resource type (event, command, query, service, domain)").option("--id <id>", "Resource ID (omit to export all resources of the given type)").option("-v, --version <version>", "Resource version (defaults to latest)").option("--hydrate", "Include referenced resources (messages, channels, owners)", false).option("--stdout", "Print to stdout instead of writing a file", false).option("--playground", "Open the exported DSL in
|
|
1104
|
+
program.command("export").description("Export a catalog resource to EventCatalog DSL (.ec) format").option("-a, --all", "Export the entire catalog (all resource types)", false).option("-r, --resource <type>", "Resource type (event, command, query, service, domain)").option("--id <id>", "Resource ID (omit to export all resources of the given type)").option("-v, --version <version>", "Resource version (defaults to latest)").option("--hydrate", "Include referenced resources (messages, channels, owners)", false).option("--stdout", "Print to stdout instead of writing a file", false).option("--playground", "Open the exported DSL in EventCatalog Modelling", false).option("-o, --output <path>", "Output file path (defaults to <id>.ec or catalog.ec)").action(async (opts) => {
|
|
916
1105
|
try {
|
|
917
1106
|
const globalOpts = program.opts();
|
|
918
1107
|
const dir = globalOpts.dir || ".";
|