@eventcatalog/cli 0.3.1 → 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.
- package/dist/cli/index.js +789 -25
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +789 -25
- package/dist/cli/index.mjs.map +1 -1
- package/dist/cli/logo.png +0 -0
- package/dist/cli-docs.js +53 -2
- package/dist/cli-docs.js.map +1 -1
- package/dist/cli-docs.mjs +53 -2
- package/dist/cli-docs.mjs.map +1 -1
- package/package.json +6 -2
package/dist/cli/index.js
CHANGED
|
@@ -25,8 +25,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
25
25
|
|
|
26
26
|
// src/cli/index.ts
|
|
27
27
|
var import_commander = require("commander");
|
|
28
|
-
var
|
|
29
|
-
var
|
|
28
|
+
var import_node_fs4 = require("fs");
|
|
29
|
+
var import_node_path3 = require("path");
|
|
30
30
|
|
|
31
31
|
// src/cli/executor.ts
|
|
32
32
|
var import_node_fs = require("fs");
|
|
@@ -140,6 +140,7 @@ var import_node_path = require("path");
|
|
|
140
140
|
var import_open = __toESM(require("open"));
|
|
141
141
|
var import_sdk3 = __toESM(require("@eventcatalog/sdk"));
|
|
142
142
|
var RESOURCE_TYPES = ["event", "command", "query", "service", "domain"];
|
|
143
|
+
var SUPPORTED_RESOURCE_TYPES = RESOURCE_TYPES.join(", ");
|
|
143
144
|
var PLURAL_MAP = {
|
|
144
145
|
events: "event",
|
|
145
146
|
commands: "command",
|
|
@@ -147,11 +148,40 @@ var PLURAL_MAP = {
|
|
|
147
148
|
services: "service",
|
|
148
149
|
domains: "domain"
|
|
149
150
|
};
|
|
151
|
+
var KNOWN_UNSUPPORTED_EXPORT_TYPES = /* @__PURE__ */ new Set([
|
|
152
|
+
"channel",
|
|
153
|
+
"channels",
|
|
154
|
+
"team",
|
|
155
|
+
"teams",
|
|
156
|
+
"user",
|
|
157
|
+
"users",
|
|
158
|
+
"container",
|
|
159
|
+
"containers",
|
|
160
|
+
"data-product",
|
|
161
|
+
"data-products",
|
|
162
|
+
"dataproduct",
|
|
163
|
+
"dataproducts",
|
|
164
|
+
"diagram",
|
|
165
|
+
"diagrams",
|
|
166
|
+
"flow",
|
|
167
|
+
"flows"
|
|
168
|
+
]);
|
|
150
169
|
function normalizeResourceType(resource) {
|
|
151
170
|
const lower = resource.toLowerCase();
|
|
152
171
|
if (PLURAL_MAP[lower]) return PLURAL_MAP[lower];
|
|
153
172
|
return lower;
|
|
154
173
|
}
|
|
174
|
+
function assertSupportedExportType(resource, type) {
|
|
175
|
+
const lower = resource.toLowerCase();
|
|
176
|
+
if (KNOWN_UNSUPPORTED_EXPORT_TYPES.has(lower)) {
|
|
177
|
+
throw new Error(
|
|
178
|
+
`Resource type '${resource}' is not yet supported for DSL export. Supported types: ${SUPPORTED_RESOURCE_TYPES}`
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
if (!RESOURCE_TYPES.includes(type)) {
|
|
182
|
+
throw new Error(`Invalid resource type '${resource}'. Must be one of: ${SUPPORTED_RESOURCE_TYPES}`);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
155
185
|
function getResourceFetcher(sdk, type) {
|
|
156
186
|
switch (type) {
|
|
157
187
|
case "event":
|
|
@@ -242,14 +272,14 @@ ${entries.join("\n")}
|
|
|
242
272
|
async function exportCatalog(options) {
|
|
243
273
|
const { hydrate = false, stdout = false, playground = false, output, dir } = options;
|
|
244
274
|
const sdk = (0, import_sdk3.default)(dir);
|
|
245
|
-
const dslParts =
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
275
|
+
const dslParts = (await Promise.all(
|
|
276
|
+
RESOURCE_TYPES.map(async (type) => {
|
|
277
|
+
const fetcher = getCollectionFetcher(sdk, type);
|
|
278
|
+
const resources = await fetcher({ latestOnly: true });
|
|
279
|
+
if (!resources || resources.length === 0) return "";
|
|
280
|
+
return sdk.toDSL(resources, { type, hydrate });
|
|
281
|
+
})
|
|
282
|
+
)).filter((dsl2) => Boolean(dsl2));
|
|
253
283
|
if (dslParts.length === 0) {
|
|
254
284
|
throw new Error(`No resources found in catalog at '${dir}'`);
|
|
255
285
|
}
|
|
@@ -269,9 +299,9 @@ ${vizBlock}` : grouped;
|
|
|
269
299
|
const encoded = Buffer.from(dsl).toString("base64");
|
|
270
300
|
const playgroundUrl = `https://playground.eventcatalog.dev/?code=${encoded}`;
|
|
271
301
|
await (0, import_open.default)(playgroundUrl);
|
|
272
|
-
lines.push("", ` Opening in
|
|
302
|
+
lines.push("", ` Opening in EventCatalog Modelling...`);
|
|
273
303
|
} else {
|
|
274
|
-
lines.push("", ` Tip: Use --playground to open in
|
|
304
|
+
lines.push("", ` Tip: Use --playground to open in EventCatalog Modelling`);
|
|
275
305
|
}
|
|
276
306
|
lines.push("");
|
|
277
307
|
return lines.join("\n");
|
|
@@ -279,9 +309,7 @@ ${vizBlock}` : grouped;
|
|
|
279
309
|
async function exportAll(options) {
|
|
280
310
|
const { resource, hydrate = false, stdout = false, playground = false, output, dir } = options;
|
|
281
311
|
const type = normalizeResourceType(resource);
|
|
282
|
-
|
|
283
|
-
throw new Error(`Invalid resource type '${resource}'. Must be one of: ${RESOURCE_TYPES.join(", ")}`);
|
|
284
|
-
}
|
|
312
|
+
assertSupportedExportType(resource, type);
|
|
285
313
|
const plural = pluralize(type);
|
|
286
314
|
const sdk = (0, import_sdk3.default)(dir);
|
|
287
315
|
const fetcher = getCollectionFetcher(sdk, type);
|
|
@@ -305,9 +333,9 @@ ${vizBlock}` : grouped;
|
|
|
305
333
|
const encoded = Buffer.from(dsl).toString("base64");
|
|
306
334
|
const playgroundUrl = `https://playground.eventcatalog.dev/?code=${encoded}`;
|
|
307
335
|
await (0, import_open.default)(playgroundUrl);
|
|
308
|
-
lines.push("", ` Opening in
|
|
336
|
+
lines.push("", ` Opening in EventCatalog Modelling...`);
|
|
309
337
|
} else {
|
|
310
|
-
lines.push("", ` Tip: Use --playground to open in
|
|
338
|
+
lines.push("", ` Tip: Use --playground to open in EventCatalog Modelling`);
|
|
311
339
|
}
|
|
312
340
|
lines.push("");
|
|
313
341
|
return lines.join("\n");
|
|
@@ -318,9 +346,7 @@ async function exportResource(options) {
|
|
|
318
346
|
return exportAll(options);
|
|
319
347
|
}
|
|
320
348
|
const type = normalizeResourceType(resource);
|
|
321
|
-
|
|
322
|
-
throw new Error(`Invalid resource type '${resource}'. Must be one of: ${RESOURCE_TYPES.join(", ")}`);
|
|
323
|
-
}
|
|
349
|
+
assertSupportedExportType(resource, type);
|
|
324
350
|
const sdk = (0, import_sdk3.default)(dir);
|
|
325
351
|
const fetcher = getResourceFetcher(sdk, type);
|
|
326
352
|
const data = await fetcher(id, version2);
|
|
@@ -344,19 +370,739 @@ ${vizBlock}` : grouped;
|
|
|
344
370
|
const encoded = Buffer.from(dsl).toString("base64");
|
|
345
371
|
const playgroundUrl = `https://playground.eventcatalog.dev/?code=${encoded}`;
|
|
346
372
|
await (0, import_open.default)(playgroundUrl);
|
|
347
|
-
lines.push("", ` Opening in
|
|
373
|
+
lines.push("", ` Opening in EventCatalog Modelling...`);
|
|
348
374
|
} else {
|
|
349
|
-
lines.push("", ` Tip: Use --playground to open in
|
|
375
|
+
lines.push("", ` Tip: Use --playground to open in EventCatalog Modelling`);
|
|
350
376
|
}
|
|
351
377
|
lines.push("");
|
|
352
378
|
return lines.join("\n");
|
|
353
379
|
}
|
|
354
380
|
|
|
381
|
+
// src/cli/import.ts
|
|
382
|
+
var import_node_fs3 = require("fs");
|
|
383
|
+
var import_node_path2 = require("path");
|
|
384
|
+
var import_node_crypto = require("crypto");
|
|
385
|
+
var import_node_readline = require("readline");
|
|
386
|
+
var import_gray_matter = __toESM(require("gray-matter"));
|
|
387
|
+
var import_sdk4 = __toESM(require("@eventcatalog/sdk"));
|
|
388
|
+
function normalizeImportedFrontmatter(type, frontmatter) {
|
|
389
|
+
const normalized = { ...frontmatter };
|
|
390
|
+
if (type === "container") {
|
|
391
|
+
if (normalized.container_type === void 0 && normalized.containerType !== void 0) {
|
|
392
|
+
normalized.container_type = normalized.containerType;
|
|
393
|
+
delete normalized.containerType;
|
|
394
|
+
}
|
|
395
|
+
if (normalized.access_mode === void 0 && normalized.accessMode !== void 0) {
|
|
396
|
+
normalized.access_mode = normalized.accessMode;
|
|
397
|
+
delete normalized.accessMode;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
return normalized;
|
|
401
|
+
}
|
|
402
|
+
var RESOURCE_TYPE_FROM_FOLDER = {
|
|
403
|
+
events: "event",
|
|
404
|
+
commands: "command",
|
|
405
|
+
queries: "query",
|
|
406
|
+
services: "service",
|
|
407
|
+
domains: "domain",
|
|
408
|
+
channels: "channel",
|
|
409
|
+
flows: "flow",
|
|
410
|
+
containers: "container",
|
|
411
|
+
"data-products": "dataProduct",
|
|
412
|
+
diagrams: "diagram",
|
|
413
|
+
users: "user",
|
|
414
|
+
teams: "team"
|
|
415
|
+
};
|
|
416
|
+
async function parseDSL(source, options) {
|
|
417
|
+
const { createEcServices, compile } = await import("@eventcatalog/language-server");
|
|
418
|
+
const { EmptyFileSystem, URI } = await import("langium");
|
|
419
|
+
const services = createEcServices(EmptyFileSystem);
|
|
420
|
+
const uri = URI.parse(`file:///import-${Date.now()}.ec`);
|
|
421
|
+
const document = services.shared.workspace.LangiumDocumentFactory.fromString(source, uri);
|
|
422
|
+
services.shared.workspace.LangiumDocuments.addDocument(document);
|
|
423
|
+
await services.shared.workspace.DocumentBuilder.build([document]);
|
|
424
|
+
const parserErrors = document.parseResult.parserErrors;
|
|
425
|
+
if (parserErrors.length > 0) {
|
|
426
|
+
const messages = parserErrors.map((e) => ` Line ${e.token?.startLine ?? "?"}: ${e.message}`);
|
|
427
|
+
throw new Error(`Parse errors:
|
|
428
|
+
${messages.join("\n")}`);
|
|
429
|
+
}
|
|
430
|
+
const program2 = document.parseResult.value;
|
|
431
|
+
const outputs = compile(program2, { nested: options?.nested });
|
|
432
|
+
try {
|
|
433
|
+
services.shared.workspace.LangiumDocuments.deleteDocument(uri);
|
|
434
|
+
} catch {
|
|
435
|
+
}
|
|
436
|
+
return { outputs, program: program2 };
|
|
437
|
+
}
|
|
438
|
+
function extractResourceTypeFolder(path) {
|
|
439
|
+
const segments = path.split("/");
|
|
440
|
+
let lastTypeFolder = segments[0];
|
|
441
|
+
for (const seg of segments) {
|
|
442
|
+
if (RESOURCE_TYPE_FROM_FOLDER[seg]) {
|
|
443
|
+
lastTypeFolder = seg;
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
return lastTypeFolder;
|
|
447
|
+
}
|
|
448
|
+
function parseCompiledOutput(output) {
|
|
449
|
+
const { data: frontmatter, content: markdown } = (0, import_gray_matter.default)(output.content);
|
|
450
|
+
const typeFolder = extractResourceTypeFolder(output.path);
|
|
451
|
+
const type = RESOURCE_TYPE_FROM_FOLDER[typeFolder] || typeFolder;
|
|
452
|
+
return {
|
|
453
|
+
type,
|
|
454
|
+
id: frontmatter.id,
|
|
455
|
+
version: frontmatter.version,
|
|
456
|
+
frontmatter,
|
|
457
|
+
markdown: markdown.trim(),
|
|
458
|
+
path: output.path
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
var MESSAGE_TYPE_FOLDER = {
|
|
462
|
+
event: "events",
|
|
463
|
+
command: "commands",
|
|
464
|
+
query: "queries",
|
|
465
|
+
channel: "channels"
|
|
466
|
+
};
|
|
467
|
+
var DEFAULT_STUB_VERSION = "0.0.1";
|
|
468
|
+
var NO_VERSION_KEY = "__no_version__";
|
|
469
|
+
function getResourceNameKey(type, id) {
|
|
470
|
+
return `${type}:${id}`;
|
|
471
|
+
}
|
|
472
|
+
function getResourceVersionKey(type, id, version2) {
|
|
473
|
+
return `${type}:${id}@${version2 || NO_VERSION_KEY}`;
|
|
474
|
+
}
|
|
475
|
+
function hasReferenceStatements(source) {
|
|
476
|
+
return /\b(?:sends|receives|writes-to|reads-from)\b/.test(source);
|
|
477
|
+
}
|
|
478
|
+
async function extractMessageStubs(program2, compiledIds, nested = false) {
|
|
479
|
+
const stubs = [];
|
|
480
|
+
const stubIds = /* @__PURE__ */ new Set();
|
|
481
|
+
function processDefinitions(definitions, parentPath = "") {
|
|
482
|
+
for (const def of definitions) {
|
|
483
|
+
if (def.$type === "VisualizerDef" && def.body) {
|
|
484
|
+
processDefinitions(def.body, parentPath);
|
|
485
|
+
continue;
|
|
486
|
+
}
|
|
487
|
+
if (def.$type === "DomainDef") {
|
|
488
|
+
const domainPath = nested ? `domains/${def.name}` : "";
|
|
489
|
+
const domainBody = def.body || [];
|
|
490
|
+
const domainServices = domainBody.filter((d) => d.$type === "ServiceDef");
|
|
491
|
+
processDefinitions(domainServices, domainPath);
|
|
492
|
+
const subdomains = domainBody.filter((d) => d.$type === "SubdomainDef");
|
|
493
|
+
for (const sub of subdomains) {
|
|
494
|
+
const subPath = nested ? `domains/${def.name}/subdomains/${sub.name}` : "";
|
|
495
|
+
const subServices = (sub.body || []).filter((d) => d.$type === "ServiceDef");
|
|
496
|
+
processDefinitions(subServices, subPath);
|
|
497
|
+
}
|
|
498
|
+
continue;
|
|
499
|
+
}
|
|
500
|
+
if (def.$type !== "ServiceDef") continue;
|
|
501
|
+
const servicePath = nested ? parentPath ? `${parentPath}/services/${def.name}` : `services/${def.name}` : "";
|
|
502
|
+
const body = def.body || [];
|
|
503
|
+
for (const stmt of body) {
|
|
504
|
+
if (stmt.$type === "SendsStmt" || stmt.$type === "ReceivesStmt") {
|
|
505
|
+
const msgType = stmt.messageType;
|
|
506
|
+
const msgName = stmt.messageName;
|
|
507
|
+
const hasBody = stmt.body && stmt.body.length > 0;
|
|
508
|
+
const version2 = stmt.version || DEFAULT_STUB_VERSION;
|
|
509
|
+
if (!hasBody) {
|
|
510
|
+
const folder = MESSAGE_TYPE_FOLDER[msgType];
|
|
511
|
+
if (folder) {
|
|
512
|
+
const key = getResourceVersionKey(msgType, msgName, version2);
|
|
513
|
+
const anyVersionKey = getResourceNameKey(msgType, msgName);
|
|
514
|
+
if (!compiledIds.has(key) && !stubIds.has(key) && !(!stmt.version && compiledIds.has(anyVersionKey))) {
|
|
515
|
+
const stubFolder = nested && servicePath ? `${servicePath}/${folder}` : folder;
|
|
516
|
+
stubIds.add(key);
|
|
517
|
+
stubs.push({
|
|
518
|
+
type: msgType,
|
|
519
|
+
id: msgName,
|
|
520
|
+
version: version2,
|
|
521
|
+
frontmatter: {
|
|
522
|
+
id: msgName,
|
|
523
|
+
name: msgName,
|
|
524
|
+
version: version2
|
|
525
|
+
},
|
|
526
|
+
markdown: "",
|
|
527
|
+
path: `${stubFolder}/${msgName}/versioned/${version2}/index.md`
|
|
528
|
+
});
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
if (stmt.channelClause) {
|
|
533
|
+
const channels = stmt.channelClause.channels || [];
|
|
534
|
+
for (const ch of channels) {
|
|
535
|
+
const chName = ch.channelName;
|
|
536
|
+
const chVersion = ch.channelVersion || DEFAULT_STUB_VERSION;
|
|
537
|
+
const chKey = getResourceVersionKey("channel", chName, chVersion);
|
|
538
|
+
const chAnyVersionKey = getResourceNameKey("channel", chName);
|
|
539
|
+
if (compiledIds.has(chKey) || stubIds.has(chKey)) continue;
|
|
540
|
+
if (!ch.channelVersion && compiledIds.has(chAnyVersionKey)) continue;
|
|
541
|
+
const chFolder = nested && parentPath ? `${parentPath}/channels` : "channels";
|
|
542
|
+
stubIds.add(chKey);
|
|
543
|
+
stubs.push({
|
|
544
|
+
type: "channel",
|
|
545
|
+
id: chName,
|
|
546
|
+
version: chVersion,
|
|
547
|
+
frontmatter: {
|
|
548
|
+
id: chName,
|
|
549
|
+
name: chName,
|
|
550
|
+
version: chVersion
|
|
551
|
+
},
|
|
552
|
+
markdown: "",
|
|
553
|
+
path: `${chFolder}/${chName}/versioned/${chVersion}/index.md`
|
|
554
|
+
});
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
continue;
|
|
558
|
+
}
|
|
559
|
+
if (stmt.$type === "WritesToStmt" || stmt.$type === "ReadsFromStmt") {
|
|
560
|
+
const containerName = stmt.ref?.name;
|
|
561
|
+
if (!containerName) continue;
|
|
562
|
+
const containerVersion = stmt.ref?.version || DEFAULT_STUB_VERSION;
|
|
563
|
+
const containerKey = getResourceVersionKey("container", containerName, containerVersion);
|
|
564
|
+
const containerAnyVersionKey = getResourceNameKey("container", containerName);
|
|
565
|
+
if (compiledIds.has(containerKey) || stubIds.has(containerKey)) continue;
|
|
566
|
+
if (!stmt.ref?.version && compiledIds.has(containerAnyVersionKey)) continue;
|
|
567
|
+
const containerFolder = nested && parentPath ? `${parentPath}/containers` : "containers";
|
|
568
|
+
stubIds.add(containerKey);
|
|
569
|
+
stubs.push({
|
|
570
|
+
type: "container",
|
|
571
|
+
id: containerName,
|
|
572
|
+
version: containerVersion,
|
|
573
|
+
frontmatter: {
|
|
574
|
+
id: containerName,
|
|
575
|
+
name: containerName,
|
|
576
|
+
version: containerVersion
|
|
577
|
+
},
|
|
578
|
+
markdown: "",
|
|
579
|
+
path: `${containerFolder}/${containerName}/versioned/${containerVersion}/index.md`
|
|
580
|
+
});
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
processDefinitions(program2.definitions);
|
|
586
|
+
return stubs;
|
|
587
|
+
}
|
|
588
|
+
function getVersionFromBody(body) {
|
|
589
|
+
if (!body) return void 0;
|
|
590
|
+
const versionStmt = body.find((stmt) => stmt?.$type === "VersionStmt");
|
|
591
|
+
return versionStmt?.value;
|
|
592
|
+
}
|
|
593
|
+
function buildServiceOutputPath(serviceName, body, nested, parentPath) {
|
|
594
|
+
const folder = nested && parentPath ? `${parentPath}/services` : "services";
|
|
595
|
+
const version2 = getVersionFromBody(body);
|
|
596
|
+
if (version2) return `${folder}/${serviceName}/versioned/${version2}/index.md`;
|
|
597
|
+
return `${folder}/${serviceName}/index.md`;
|
|
598
|
+
}
|
|
599
|
+
function extractServiceContainerRefs(program2, nested = false) {
|
|
600
|
+
const refsByPath = /* @__PURE__ */ new Map();
|
|
601
|
+
function processDefinitions(definitions, parentPath = "") {
|
|
602
|
+
for (const def of definitions || []) {
|
|
603
|
+
if (def.$type === "VisualizerDef" && def.body) {
|
|
604
|
+
processDefinitions(def.body, parentPath);
|
|
605
|
+
continue;
|
|
606
|
+
}
|
|
607
|
+
if (def.$type === "DomainDef") {
|
|
608
|
+
const domainPath = nested ? `domains/${def.name}` : "";
|
|
609
|
+
const domainBody = def.body || [];
|
|
610
|
+
const domainServices = domainBody.filter((d) => d.$type === "ServiceDef");
|
|
611
|
+
processDefinitions(domainServices, domainPath);
|
|
612
|
+
const subdomains = domainBody.filter((d) => d.$type === "SubdomainDef");
|
|
613
|
+
for (const sub of subdomains) {
|
|
614
|
+
const subPath = nested ? `domains/${def.name}/subdomains/${sub.name}` : "";
|
|
615
|
+
const subServices = (sub.body || []).filter((d) => d.$type === "ServiceDef");
|
|
616
|
+
processDefinitions(subServices, subPath);
|
|
617
|
+
}
|
|
618
|
+
continue;
|
|
619
|
+
}
|
|
620
|
+
if (def.$type !== "ServiceDef") continue;
|
|
621
|
+
const body = def.body || [];
|
|
622
|
+
const writesTo = body.filter((stmt) => stmt.$type === "WritesToStmt" && stmt.ref?.name).map((stmt) => ({
|
|
623
|
+
id: stmt.ref.name,
|
|
624
|
+
...stmt.ref.version ? { version: stmt.ref.version } : {}
|
|
625
|
+
}));
|
|
626
|
+
const readsFrom = body.filter((stmt) => stmt.$type === "ReadsFromStmt" && stmt.ref?.name).map((stmt) => ({
|
|
627
|
+
id: stmt.ref.name,
|
|
628
|
+
...stmt.ref.version ? { version: stmt.ref.version } : {}
|
|
629
|
+
}));
|
|
630
|
+
if (writesTo.length === 0 && readsFrom.length === 0) continue;
|
|
631
|
+
const path = buildServiceOutputPath(def.name, body, nested, parentPath);
|
|
632
|
+
refsByPath.set(path, {
|
|
633
|
+
...writesTo.length > 0 ? { writesTo } : {},
|
|
634
|
+
...readsFrom.length > 0 ? { readsFrom } : {}
|
|
635
|
+
});
|
|
636
|
+
}
|
|
637
|
+
}
|
|
638
|
+
processDefinitions(program2.definitions || []);
|
|
639
|
+
return refsByPath;
|
|
640
|
+
}
|
|
641
|
+
var SDK_WRITER_BASE = {
|
|
642
|
+
event: "events",
|
|
643
|
+
command: "commands",
|
|
644
|
+
query: "queries",
|
|
645
|
+
service: "services",
|
|
646
|
+
domain: "domains",
|
|
647
|
+
channel: "channels",
|
|
648
|
+
container: "containers",
|
|
649
|
+
dataProduct: "data-products",
|
|
650
|
+
diagram: "diagrams",
|
|
651
|
+
team: "teams",
|
|
652
|
+
user: "users"
|
|
653
|
+
};
|
|
654
|
+
function extractSdkPath(compiledPath, resourceType) {
|
|
655
|
+
const dirPath = compiledPath.replace(/\/versioned\/[^/]+\/index\.md$/, "").replace(/\/index\.md$/, "").replace(/\.md$/, "");
|
|
656
|
+
const baseFolder = SDK_WRITER_BASE[resourceType];
|
|
657
|
+
if (!baseFolder) return "";
|
|
658
|
+
if (dirPath.startsWith(`${baseFolder}/`)) {
|
|
659
|
+
const relative = dirPath.slice(baseFolder.length + 1);
|
|
660
|
+
if (!relative.includes("/")) return "";
|
|
661
|
+
return relative;
|
|
662
|
+
}
|
|
663
|
+
return `../${dirPath}`;
|
|
664
|
+
}
|
|
665
|
+
var TYPES_WITH_NODE_GRAPH = /* @__PURE__ */ new Set(["event", "command", "query", "service", "domain", "channel", "flow"]);
|
|
666
|
+
function getWriter(sdk, type) {
|
|
667
|
+
switch (type) {
|
|
668
|
+
case "event":
|
|
669
|
+
return sdk.writeEvent;
|
|
670
|
+
case "command":
|
|
671
|
+
return sdk.writeCommand;
|
|
672
|
+
case "query":
|
|
673
|
+
return sdk.writeQuery;
|
|
674
|
+
case "service":
|
|
675
|
+
return sdk.writeService;
|
|
676
|
+
case "domain":
|
|
677
|
+
return sdk.writeDomain;
|
|
678
|
+
case "channel":
|
|
679
|
+
return sdk.writeChannel;
|
|
680
|
+
case "container":
|
|
681
|
+
return sdk.writeDataStore;
|
|
682
|
+
case "dataProduct":
|
|
683
|
+
return sdk.writeDataProduct;
|
|
684
|
+
case "diagram":
|
|
685
|
+
return sdk.writeDiagram;
|
|
686
|
+
case "team":
|
|
687
|
+
return sdk.writeTeam;
|
|
688
|
+
case "user":
|
|
689
|
+
return sdk.writeUser;
|
|
690
|
+
default:
|
|
691
|
+
return null;
|
|
692
|
+
}
|
|
693
|
+
}
|
|
694
|
+
function getReader(sdk, type) {
|
|
695
|
+
switch (type) {
|
|
696
|
+
case "event":
|
|
697
|
+
return sdk.getEvent;
|
|
698
|
+
case "command":
|
|
699
|
+
return sdk.getCommand;
|
|
700
|
+
case "query":
|
|
701
|
+
return sdk.getQuery;
|
|
702
|
+
case "service":
|
|
703
|
+
return sdk.getService;
|
|
704
|
+
case "domain":
|
|
705
|
+
return sdk.getDomain;
|
|
706
|
+
case "channel":
|
|
707
|
+
return sdk.getChannel;
|
|
708
|
+
case "container":
|
|
709
|
+
return sdk.getDataStore;
|
|
710
|
+
case "dataProduct":
|
|
711
|
+
return sdk.getDataProduct;
|
|
712
|
+
case "diagram":
|
|
713
|
+
return sdk.getDiagram;
|
|
714
|
+
case "team":
|
|
715
|
+
return sdk.getTeam;
|
|
716
|
+
case "user":
|
|
717
|
+
return sdk.getUser;
|
|
718
|
+
default:
|
|
719
|
+
return null;
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
function promptConfirm(message) {
|
|
723
|
+
return new Promise((resolve4) => {
|
|
724
|
+
const rl = (0, import_node_readline.createInterface)({ input: process.stdin, output: process.stdout });
|
|
725
|
+
rl.question(`${message} `, (answer) => {
|
|
726
|
+
rl.close();
|
|
727
|
+
const normalized = answer.trim().toLowerCase();
|
|
728
|
+
resolve4(normalized === "" || normalized === "y" || normalized === "yes");
|
|
729
|
+
});
|
|
730
|
+
});
|
|
731
|
+
}
|
|
732
|
+
function promptInput(message, defaultValue) {
|
|
733
|
+
return new Promise((resolve4) => {
|
|
734
|
+
const rl = (0, import_node_readline.createInterface)({ input: process.stdin, output: process.stdout });
|
|
735
|
+
rl.question(`${message} `, (answer) => {
|
|
736
|
+
rl.close();
|
|
737
|
+
resolve4(answer.trim() || defaultValue);
|
|
738
|
+
});
|
|
739
|
+
});
|
|
740
|
+
}
|
|
741
|
+
function initCatalog(dir, organizationName = "My Organization") {
|
|
742
|
+
const catalogDir = (0, import_node_path2.resolve)(dir);
|
|
743
|
+
(0, import_node_fs3.mkdirSync)(catalogDir, { recursive: true });
|
|
744
|
+
const packageJson = {
|
|
745
|
+
name: "my-catalog",
|
|
746
|
+
version: "0.1.0",
|
|
747
|
+
private: true,
|
|
748
|
+
scripts: {
|
|
749
|
+
dev: "eventcatalog dev",
|
|
750
|
+
build: "eventcatalog build",
|
|
751
|
+
start: "eventcatalog start",
|
|
752
|
+
preview: "eventcatalog preview",
|
|
753
|
+
generate: "eventcatalog generate",
|
|
754
|
+
lint: "eventcatalog-linter",
|
|
755
|
+
test: 'echo "Error: no test specified" && exit 1'
|
|
756
|
+
},
|
|
757
|
+
dependencies: {
|
|
758
|
+
"@eventcatalog/core": "latest",
|
|
759
|
+
"@eventcatalog/linter": "latest"
|
|
760
|
+
}
|
|
761
|
+
};
|
|
762
|
+
(0, import_node_fs3.writeFileSync)((0, import_node_path2.join)(catalogDir, "package.json"), JSON.stringify(packageJson, null, 2) + "\n", "utf-8");
|
|
763
|
+
const cId = (0, import_node_crypto.randomUUID)();
|
|
764
|
+
const config = `/** @type {import('@eventcatalog/core/bin/eventcatalog.config').Config} */
|
|
765
|
+
export default {
|
|
766
|
+
title: 'EventCatalog',
|
|
767
|
+
tagline: 'Discover, Explore and Document your Event Driven Architectures',
|
|
768
|
+
organizationName: '${organizationName}',
|
|
769
|
+
homepageLink: 'https://eventcatalog.dev/',
|
|
770
|
+
output: 'static',
|
|
771
|
+
trailingSlash: false,
|
|
772
|
+
base: '/',
|
|
773
|
+
logo: {
|
|
774
|
+
alt: 'EventCatalog Logo',
|
|
775
|
+
src: '/logo.png',
|
|
776
|
+
text: 'EventCatalog',
|
|
777
|
+
},
|
|
778
|
+
cId: '${cId}',
|
|
779
|
+
};
|
|
780
|
+
`;
|
|
781
|
+
(0, import_node_fs3.writeFileSync)((0, import_node_path2.join)(catalogDir, "eventcatalog.config.js"), config, "utf-8");
|
|
782
|
+
const gitignore = `# Dependencies
|
|
783
|
+
/node_modules
|
|
784
|
+
|
|
785
|
+
# Production
|
|
786
|
+
/build
|
|
787
|
+
|
|
788
|
+
# Generated files
|
|
789
|
+
.astro
|
|
790
|
+
out
|
|
791
|
+
dist
|
|
792
|
+
|
|
793
|
+
# Misc
|
|
794
|
+
.DS_Store
|
|
795
|
+
.env.local
|
|
796
|
+
.env.development.local
|
|
797
|
+
.env.test.local
|
|
798
|
+
.env.production.local
|
|
799
|
+
|
|
800
|
+
npm-debug.log*
|
|
801
|
+
yarn-debug.log*
|
|
802
|
+
yarn-error.log*
|
|
803
|
+
|
|
804
|
+
.eventcatalog-core
|
|
805
|
+
|
|
806
|
+
.env
|
|
807
|
+
.env-*
|
|
808
|
+
`;
|
|
809
|
+
(0, import_node_fs3.writeFileSync)((0, import_node_path2.join)(catalogDir, ".gitignore"), gitignore, "utf-8");
|
|
810
|
+
const envFile = `# EventCatalog Scale License Key, if you want to unlock the scale features
|
|
811
|
+
# You can get a 14 day trial license key from https://eventcatalog.cloud
|
|
812
|
+
|
|
813
|
+
EVENTCATALOG_SCALE_LICENSE_KEY=
|
|
814
|
+
|
|
815
|
+
# Optional key if you are using EventCatalog Chat with OpenAI Models.
|
|
816
|
+
# You need to set \`output\` to \`server\` in your eventcatalog.config.js file.
|
|
817
|
+
# See documentation for more details: https://www.eventcatalog.dev/features/ai-assistant
|
|
818
|
+
OPENAI_API_KEY=
|
|
819
|
+
`;
|
|
820
|
+
(0, import_node_fs3.writeFileSync)((0, import_node_path2.join)(catalogDir, ".env"), envFile, "utf-8");
|
|
821
|
+
(0, import_node_fs3.writeFileSync)((0, import_node_path2.join)(catalogDir, ".npmrc"), "strict-peer-dependencies=false\n", "utf-8");
|
|
822
|
+
(0, import_node_fs3.mkdirSync)((0, import_node_path2.join)(catalogDir, "public"), { recursive: true });
|
|
823
|
+
(0, import_node_fs3.copyFileSync)((0, import_node_path2.join)(__dirname, "logo.png"), (0, import_node_path2.join)(catalogDir, "public", "logo.png"));
|
|
824
|
+
}
|
|
825
|
+
async function importDSL(options) {
|
|
826
|
+
const { files, stdin = false, dryRun = false, flat = false, noInit = false, dir } = options;
|
|
827
|
+
const nested = !flat;
|
|
828
|
+
let source;
|
|
829
|
+
if (stdin) {
|
|
830
|
+
source = await readStdin();
|
|
831
|
+
} else if (files && files.length > 0) {
|
|
832
|
+
const parts = [];
|
|
833
|
+
for (const file of files) {
|
|
834
|
+
const filepath = (0, import_node_path2.resolve)(file);
|
|
835
|
+
if (!(0, import_node_fs3.existsSync)(filepath)) {
|
|
836
|
+
throw new Error(`File not found: ${filepath}`);
|
|
837
|
+
}
|
|
838
|
+
parts.push((0, import_node_fs3.readFileSync)(filepath, "utf-8"));
|
|
839
|
+
}
|
|
840
|
+
source = parts.join("\n\n");
|
|
841
|
+
} else {
|
|
842
|
+
throw new Error("Either provide .ec file paths or use --stdin");
|
|
843
|
+
}
|
|
844
|
+
if (!source.trim()) {
|
|
845
|
+
throw new Error("No DSL content to import");
|
|
846
|
+
}
|
|
847
|
+
const catalogDir = (0, import_node_path2.resolve)(dir);
|
|
848
|
+
let didInit = false;
|
|
849
|
+
if (!noInit && !(0, import_node_fs3.existsSync)((0, import_node_path2.join)(catalogDir, "eventcatalog.config.js")) && process.stdin.isTTY) {
|
|
850
|
+
const confirmed = await promptConfirm(`Initialize a new EventCatalog at ${catalogDir}? (Y/n)`);
|
|
851
|
+
if (confirmed) {
|
|
852
|
+
const organizationName = await promptInput("Organization name (My Organization):", "My Organization");
|
|
853
|
+
initCatalog(dir, organizationName);
|
|
854
|
+
didInit = true;
|
|
855
|
+
}
|
|
856
|
+
}
|
|
857
|
+
const parsed = await parseDSL(source, { nested });
|
|
858
|
+
const outputs = parsed.outputs;
|
|
859
|
+
if (outputs.length === 0) {
|
|
860
|
+
throw new Error("No resources found in DSL content");
|
|
861
|
+
}
|
|
862
|
+
const sdk = (0, import_sdk4.default)(catalogDir);
|
|
863
|
+
const result = { created: [], updated: [], versioned: [], errors: [] };
|
|
864
|
+
const readerCache = /* @__PURE__ */ new Map();
|
|
865
|
+
const readResourceCached = async (reader, type, id, version2) => {
|
|
866
|
+
if (!reader) return void 0;
|
|
867
|
+
const cacheKey = getResourceVersionKey(type, id, version2);
|
|
868
|
+
if (!readerCache.has(cacheKey)) {
|
|
869
|
+
readerCache.set(
|
|
870
|
+
cacheKey,
|
|
871
|
+
reader(id, version2).catch(() => void 0)
|
|
872
|
+
);
|
|
873
|
+
}
|
|
874
|
+
return await readerCache.get(cacheKey);
|
|
875
|
+
};
|
|
876
|
+
const invalidateReaderCache = (type, id, version2) => {
|
|
877
|
+
readerCache.delete(getResourceVersionKey(type, id));
|
|
878
|
+
readerCache.delete(getResourceVersionKey(type, id, version2));
|
|
879
|
+
};
|
|
880
|
+
const resources = outputs.map(parseCompiledOutput);
|
|
881
|
+
const serviceContainerRefsByPath = extractServiceContainerRefs(parsed.program, nested);
|
|
882
|
+
for (const resource of resources) {
|
|
883
|
+
if (resource.type !== "service") continue;
|
|
884
|
+
const refs = serviceContainerRefsByPath.get(resource.path);
|
|
885
|
+
if (!refs) continue;
|
|
886
|
+
resource.frontmatter = {
|
|
887
|
+
...resource.frontmatter,
|
|
888
|
+
...refs
|
|
889
|
+
};
|
|
890
|
+
}
|
|
891
|
+
const compiledIds = /* @__PURE__ */ new Set();
|
|
892
|
+
for (const resource of resources) {
|
|
893
|
+
compiledIds.add(getResourceNameKey(resource.type, resource.id));
|
|
894
|
+
compiledIds.add(getResourceVersionKey(resource.type, resource.id, resource.version));
|
|
895
|
+
}
|
|
896
|
+
const stubs = hasReferenceStatements(source) ? await extractMessageStubs(parsed.program, compiledIds, nested) : [];
|
|
897
|
+
resources.push(...stubs);
|
|
898
|
+
for (const resource of resources) {
|
|
899
|
+
const label = resource.version ? `${resource.type} ${resource.id}@${resource.version}` : `${resource.type} ${resource.id}`;
|
|
900
|
+
if (dryRun) {
|
|
901
|
+
const reader = getReader(sdk, resource.type);
|
|
902
|
+
if (reader) {
|
|
903
|
+
const existing = await readResourceCached(reader, resource.type, resource.id, resource.version);
|
|
904
|
+
if (existing) {
|
|
905
|
+
result.updated.push(label);
|
|
906
|
+
} else {
|
|
907
|
+
const latest = await readResourceCached(reader, resource.type, resource.id);
|
|
908
|
+
if (latest && latest.version && latest.version !== resource.version) {
|
|
909
|
+
result.versioned.push(`${resource.type} ${resource.id}@${latest.version}`);
|
|
910
|
+
}
|
|
911
|
+
result.created.push(label);
|
|
912
|
+
}
|
|
913
|
+
} else {
|
|
914
|
+
result.created.push(label);
|
|
915
|
+
}
|
|
916
|
+
continue;
|
|
917
|
+
}
|
|
918
|
+
const writer = getWriter(sdk, resource.type);
|
|
919
|
+
if (!writer) {
|
|
920
|
+
result.errors.push(`${label}: unsupported resource type '${resource.type}'`);
|
|
921
|
+
continue;
|
|
922
|
+
}
|
|
923
|
+
try {
|
|
924
|
+
const reader = getReader(sdk, resource.type);
|
|
925
|
+
const existing = await readResourceCached(reader, resource.type, resource.id, resource.version);
|
|
926
|
+
const latest = !existing && resource.version ? await readResourceCached(reader, resource.type, resource.id) : void 0;
|
|
927
|
+
const versionedFrom = !existing && resource.version && latest?.version && latest.version !== resource.version ? latest.version : void 0;
|
|
928
|
+
const incomingMarkdown = resource.markdown;
|
|
929
|
+
const hasIncomingMarkdown = incomingMarkdown.trim().length > 0;
|
|
930
|
+
let markdown = incomingMarkdown;
|
|
931
|
+
if (!hasIncomingMarkdown) {
|
|
932
|
+
if (existing?.markdown) {
|
|
933
|
+
markdown = existing.markdown;
|
|
934
|
+
} else if (!existing && latest?.markdown) {
|
|
935
|
+
markdown = latest.markdown;
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
if (!existing && TYPES_WITH_NODE_GRAPH.has(resource.type)) {
|
|
939
|
+
if (!markdown) {
|
|
940
|
+
markdown = "<NodeGraph />";
|
|
941
|
+
} else if (!markdown.includes("<NodeGraph />")) {
|
|
942
|
+
markdown = `${markdown}
|
|
943
|
+
|
|
944
|
+
<NodeGraph />`;
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
const resourceData = {
|
|
948
|
+
...normalizeImportedFrontmatter(resource.type, resource.frontmatter),
|
|
949
|
+
markdown
|
|
950
|
+
};
|
|
951
|
+
const writeOptions = {
|
|
952
|
+
override: true,
|
|
953
|
+
versionExistingContent: Boolean(versionedFrom)
|
|
954
|
+
};
|
|
955
|
+
if (!existing && nested) {
|
|
956
|
+
const sdkPath = extractSdkPath(resource.path, resource.type);
|
|
957
|
+
if (sdkPath) {
|
|
958
|
+
writeOptions.path = sdkPath;
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
await writer(resourceData, writeOptions);
|
|
962
|
+
invalidateReaderCache(resource.type, resource.id, resource.version);
|
|
963
|
+
if (existing) {
|
|
964
|
+
result.updated.push(label);
|
|
965
|
+
} else {
|
|
966
|
+
result.created.push(label);
|
|
967
|
+
if (versionedFrom) {
|
|
968
|
+
result.versioned.push(`${resource.type} ${resource.id}@${versionedFrom}`);
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
} catch (error) {
|
|
972
|
+
result.errors.push(`${label}: ${error instanceof Error ? error.message : String(error)}`);
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
let output = formatResult(result, dryRun);
|
|
976
|
+
if (didInit) {
|
|
977
|
+
output += ` Tip: Run 'npm install' in ${catalogDir} to install dependencies
|
|
978
|
+
`;
|
|
979
|
+
}
|
|
980
|
+
return output;
|
|
981
|
+
}
|
|
982
|
+
var c = {
|
|
983
|
+
reset: "\x1B[0m",
|
|
984
|
+
bold: "\x1B[1m",
|
|
985
|
+
dim: "\x1B[2m",
|
|
986
|
+
green: "\x1B[32m",
|
|
987
|
+
yellow: "\x1B[33m",
|
|
988
|
+
blue: "\x1B[34m",
|
|
989
|
+
magenta: "\x1B[35m",
|
|
990
|
+
cyan: "\x1B[36m",
|
|
991
|
+
red: "\x1B[31m",
|
|
992
|
+
white: "\x1B[37m",
|
|
993
|
+
gray: "\x1B[90m"
|
|
994
|
+
};
|
|
995
|
+
var TYPE_CONFIG = {
|
|
996
|
+
domain: { color: c.magenta, label: "domain", order: 0 },
|
|
997
|
+
service: { color: c.blue, label: "service", order: 1 },
|
|
998
|
+
event: { color: c.green, label: "event", order: 2 },
|
|
999
|
+
command: { color: c.yellow, label: "command", order: 3 },
|
|
1000
|
+
query: { color: c.cyan, label: "query", order: 4 },
|
|
1001
|
+
channel: { color: c.gray, label: "channel", order: 5 },
|
|
1002
|
+
flow: { color: c.white, label: "flow", order: 6 },
|
|
1003
|
+
container: { color: c.white, label: "container", order: 7 },
|
|
1004
|
+
dataProduct: { color: c.white, label: "data product", order: 8 },
|
|
1005
|
+
diagram: { color: c.white, label: "diagram", order: 9 },
|
|
1006
|
+
user: { color: c.blue, label: "user", order: 10 },
|
|
1007
|
+
team: { color: c.blue, label: "team", order: 11 }
|
|
1008
|
+
};
|
|
1009
|
+
var DEFAULT_TYPE_CONFIG = { color: c.white, label: "resource", order: 99 };
|
|
1010
|
+
function parseLabel(label) {
|
|
1011
|
+
const spaceIdx = label.indexOf(" ");
|
|
1012
|
+
if (spaceIdx === -1) return { type: "", name: label };
|
|
1013
|
+
return { type: label.slice(0, spaceIdx), name: label.slice(spaceIdx + 1) };
|
|
1014
|
+
}
|
|
1015
|
+
function groupByType(labels) {
|
|
1016
|
+
const groups = /* @__PURE__ */ new Map();
|
|
1017
|
+
for (const label of labels) {
|
|
1018
|
+
const { type, name } = parseLabel(label);
|
|
1019
|
+
if (!groups.has(type)) groups.set(type, []);
|
|
1020
|
+
groups.get(type).push(name);
|
|
1021
|
+
}
|
|
1022
|
+
const sorted = new Map(
|
|
1023
|
+
[...groups.entries()].sort((a, b) => {
|
|
1024
|
+
const orderA = (TYPE_CONFIG[a[0]] || DEFAULT_TYPE_CONFIG).order;
|
|
1025
|
+
const orderB = (TYPE_CONFIG[b[0]] || DEFAULT_TYPE_CONFIG).order;
|
|
1026
|
+
return orderA - orderB;
|
|
1027
|
+
})
|
|
1028
|
+
);
|
|
1029
|
+
for (const [, names] of sorted) {
|
|
1030
|
+
names.sort();
|
|
1031
|
+
}
|
|
1032
|
+
return sorted;
|
|
1033
|
+
}
|
|
1034
|
+
function typeBadge(type) {
|
|
1035
|
+
const cfg = TYPE_CONFIG[type] || DEFAULT_TYPE_CONFIG;
|
|
1036
|
+
const padded = ` ${cfg.label} `;
|
|
1037
|
+
return `${cfg.color}\x1B[7m${padded}${c.reset}`;
|
|
1038
|
+
}
|
|
1039
|
+
function formatResourceList(labels) {
|
|
1040
|
+
const lines = [];
|
|
1041
|
+
const groups = groupByType(labels);
|
|
1042
|
+
for (const [type, names] of groups) {
|
|
1043
|
+
const cfg = TYPE_CONFIG[type] || DEFAULT_TYPE_CONFIG;
|
|
1044
|
+
const plural = names.length === 1 ? cfg.label : `${cfg.label}s`;
|
|
1045
|
+
lines.push("");
|
|
1046
|
+
lines.push(` ${typeBadge(type)} ${c.dim}${names.length} ${plural}${c.reset}`);
|
|
1047
|
+
for (const name of names) {
|
|
1048
|
+
lines.push(` ${cfg.color}\u2502${c.reset} ${name}`);
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
return lines;
|
|
1052
|
+
}
|
|
1053
|
+
function formatResult(result, dryRun) {
|
|
1054
|
+
const lines = [""];
|
|
1055
|
+
const prefix = dryRun ? `${c.yellow}${c.bold}DRY RUN${c.reset} ` : "";
|
|
1056
|
+
const total = result.created.length + result.updated.length + result.versioned.length;
|
|
1057
|
+
if (total > 0 || result.errors.length > 0) {
|
|
1058
|
+
lines.push(` ${prefix}${c.bold}Import complete${c.reset}`);
|
|
1059
|
+
lines.push(` ${c.dim}${"\u2500".repeat(40)}${c.reset}`);
|
|
1060
|
+
}
|
|
1061
|
+
if (result.created.length > 0) {
|
|
1062
|
+
const verb = dryRun ? "Would create" : "Created";
|
|
1063
|
+
lines.push("");
|
|
1064
|
+
lines.push(` ${c.green}${c.bold}+ ${verb} ${result.created.length} resource(s)${c.reset}`);
|
|
1065
|
+
lines.push(...formatResourceList(result.created));
|
|
1066
|
+
}
|
|
1067
|
+
if (result.updated.length > 0) {
|
|
1068
|
+
const verb = dryRun ? "Would update" : "Updated";
|
|
1069
|
+
lines.push("");
|
|
1070
|
+
lines.push(` ${c.blue}${c.bold}~ ${verb} ${result.updated.length} resource(s)${c.reset}`);
|
|
1071
|
+
lines.push(...formatResourceList(result.updated));
|
|
1072
|
+
}
|
|
1073
|
+
if (result.versioned.length > 0) {
|
|
1074
|
+
const verb = dryRun ? "Would version" : "Versioned";
|
|
1075
|
+
lines.push("");
|
|
1076
|
+
lines.push(` ${c.yellow}${c.bold}\u2191 ${verb} ${result.versioned.length} existing resource(s)${c.reset}`);
|
|
1077
|
+
lines.push(...formatResourceList(result.versioned));
|
|
1078
|
+
}
|
|
1079
|
+
if (result.errors.length > 0) {
|
|
1080
|
+
lines.push("");
|
|
1081
|
+
lines.push(` ${c.red}${c.bold}\u2718 ${result.errors.length} error(s)${c.reset}`);
|
|
1082
|
+
for (const e of result.errors) {
|
|
1083
|
+
lines.push(` ${c.red}\u2502${c.reset} ${c.red}${e}${c.reset}`);
|
|
1084
|
+
}
|
|
1085
|
+
}
|
|
1086
|
+
if (result.created.length === 0 && result.updated.length === 0 && result.errors.length === 0) {
|
|
1087
|
+
lines.push(` ${c.dim}No resources to write.${c.reset}`);
|
|
1088
|
+
}
|
|
1089
|
+
lines.push("");
|
|
1090
|
+
return lines.join("\n");
|
|
1091
|
+
}
|
|
1092
|
+
function readStdin() {
|
|
1093
|
+
return new Promise((resolve4, reject) => {
|
|
1094
|
+
const chunks = [];
|
|
1095
|
+
process.stdin.on("data", (chunk) => chunks.push(chunk));
|
|
1096
|
+
process.stdin.on("end", () => resolve4(Buffer.concat(chunks).toString("utf-8")));
|
|
1097
|
+
process.stdin.on("error", reject);
|
|
1098
|
+
});
|
|
1099
|
+
}
|
|
1100
|
+
|
|
355
1101
|
// src/cli/index.ts
|
|
356
1102
|
var version = "1.0.0";
|
|
357
1103
|
try {
|
|
358
|
-
const packageJsonPath = (0,
|
|
359
|
-
const packageJson = JSON.parse((0,
|
|
1104
|
+
const packageJsonPath = (0, import_node_path3.resolve)(__dirname, "../../package.json");
|
|
1105
|
+
const packageJson = JSON.parse((0, import_node_fs4.readFileSync)(packageJsonPath, "utf-8"));
|
|
360
1106
|
version = packageJson.version;
|
|
361
1107
|
} catch {
|
|
362
1108
|
}
|
|
@@ -371,7 +1117,7 @@ import_commander.program.command("list").description("List all available SDK fun
|
|
|
371
1117
|
process.exit(1);
|
|
372
1118
|
}
|
|
373
1119
|
});
|
|
374
|
-
import_commander.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
|
|
1120
|
+
import_commander.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) => {
|
|
375
1121
|
try {
|
|
376
1122
|
const globalOpts = import_commander.program.opts();
|
|
377
1123
|
const dir = globalOpts.dir || ".";
|
|
@@ -406,6 +1152,24 @@ import_commander.program.command("export").description("Export a catalog resourc
|
|
|
406
1152
|
process.exit(1);
|
|
407
1153
|
}
|
|
408
1154
|
});
|
|
1155
|
+
import_commander.program.command("import [files...]").description("Import EventCatalog DSL (.ec) files into catalog markdown").option("--stdin", "Read DSL from stdin", false).option("--dry-run", "Preview resources without writing", false).option("--flat", "Write resources in flat structure (no nesting under domains/services)", false).option("--no-init", "Skip catalog initialization prompt").action(async (files, opts) => {
|
|
1156
|
+
try {
|
|
1157
|
+
const globalOpts = import_commander.program.opts();
|
|
1158
|
+
const dir = globalOpts.dir || ".";
|
|
1159
|
+
const result = await importDSL({
|
|
1160
|
+
files: files.length > 0 ? files : void 0,
|
|
1161
|
+
stdin: opts.stdin,
|
|
1162
|
+
dryRun: opts.dryRun,
|
|
1163
|
+
flat: opts.flat,
|
|
1164
|
+
noInit: !opts.init,
|
|
1165
|
+
dir
|
|
1166
|
+
});
|
|
1167
|
+
console.log(result);
|
|
1168
|
+
} catch (error) {
|
|
1169
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
1170
|
+
process.exit(1);
|
|
1171
|
+
}
|
|
1172
|
+
});
|
|
409
1173
|
import_commander.program.arguments("<function> [args...]").action(async (functionName, args) => {
|
|
410
1174
|
try {
|
|
411
1175
|
const options = import_commander.program.opts();
|