@eventcatalog/cli 0.3.2 → 0.3.3

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.
@@ -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
- for (const type of RESOURCE_TYPES) {
231
- const fetcher = getCollectionFetcher(sdk, type);
232
- const resources = await fetcher({ latestOnly: true });
233
- if (!resources || resources.length === 0) continue;
234
- const rawDsl = await sdk.toDSL(resources, { type, hydrate });
235
- dslParts.push(rawDsl);
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 playground...`);
286
+ lines.push("", ` Opening in EventCatalog Modelling...`);
257
287
  } else {
258
- lines.push("", ` Tip: Use --playground to open in the playground`);
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
- if (!RESOURCE_TYPES.includes(type)) {
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 playground...`);
320
+ lines.push("", ` Opening in EventCatalog Modelling...`);
293
321
  } else {
294
- lines.push("", ` Tip: Use --playground to open in the playground`);
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
- if (!RESOURCE_TYPES.includes(type)) {
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 playground...`);
357
+ lines.push("", ` Opening in EventCatalog Modelling...`);
332
358
  } else {
333
- lines.push("", ` Tip: Use --playground to open in the playground`);
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
- async function extractMessageStubs(source, compiledIds, nested = false) {
413
- const { createEcServices } = await import("@eventcatalog/language-server");
414
- const { EmptyFileSystem, URI } = await import("langium");
415
- const services = createEcServices(EmptyFileSystem);
416
- const uri = URI.parse(`file:///stub-extract-${Date.now()}.ec`);
417
- const document = services.shared.workspace.LangiumDocumentFactory.fromString(source, uri);
418
- services.shared.workspace.LangiumDocuments.addDocument(document);
419
- await services.shared.workspace.DocumentBuilder.build([document]);
420
- const program2 = document.parseResult.value;
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 !== "SendsStmt" && stmt.$type !== "ReceivesStmt") continue;
447
- const msgType = stmt.messageType;
448
- const msgName = stmt.messageName;
449
- const hasBody = stmt.body && stmt.body.length > 0;
450
- if (hasBody) continue;
451
- const key = `${msgType}:${msgName}`;
452
- if (compiledIds.has(key) || stubIds.has(key)) continue;
453
- const folder = MESSAGE_TYPE_FOLDER[msgType];
454
- if (!folder) continue;
455
- const version2 = stmt.version || DEFAULT_STUB_VERSION;
456
- const stubFolder = nested && servicePath ? `${servicePath}/${folder}` : folder;
457
- stubIds.add(key);
458
- stubs.push({
459
- type: msgType,
460
- id: msgName,
461
- version: version2,
462
- frontmatter: {
463
- id: msgName,
464
- name: msgName,
465
- version: version2
466
- },
467
- markdown: "",
468
- path: `${stubFolder}/${msgName}/versioned/${version2}/index.md`
469
- });
470
- if (stmt.channelClause) {
471
- const channels = stmt.channelClause.channels || [];
472
- for (const ch of channels) {
473
- const chName = ch.channelName;
474
- const chKey = `channel:${chName}`;
475
- if (compiledIds.has(chKey) || stubIds.has(chKey)) continue;
476
- const chVersion = ch.channelVersion || DEFAULT_STUB_VERSION;
477
- const chFolder = nested && parentPath ? `${parentPath}/channels` : "channels";
478
- stubIds.add(chKey);
479
- stubs.push({
480
- type: "channel",
481
- id: chName,
482
- version: chVersion,
483
- frontmatter: {
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
- name: chName,
486
- version: chVersion
487
- },
488
- markdown: "",
489
- path: `${chFolder}/${chName}/versioned/${chVersion}/index.md`
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 outputs = await parseDSL(source, { nested });
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 compiledIds = new Set(resources.map((r) => `${r.type}:${r.id}`));
713
- const stubs = await extractMessageStubs(source, compiledIds, nested);
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(resource.id, resource.version).catch(() => void 0);
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(resource.id).catch(() => void 0);
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 = reader ? await reader(resource.id, resource.version).catch(() => void 0) : void 0;
743
- let markdown = resource.markdown;
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
- markdown = markdown ? `${markdown}
923
+ if (!markdown) {
924
+ markdown = "<NodeGraph />";
925
+ } else if (!markdown.includes("<NodeGraph />")) {
926
+ markdown = `${markdown}
746
927
 
747
- <NodeGraph />` : "<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: true
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
- user: { color: c.blue, label: "user", order: 7 },
802
- team: { color: c.blue, label: "team", order: 8 }
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 the playground", false).option("-o, --output <path>", "Output file path (defaults to <id>.ec or catalog.ec)").action(async (opts) => {
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 || ".";