@eventcatalog/cli 0.2.1 → 0.3.1
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 +257 -4
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/index.mjs +256 -3
- package/dist/cli/index.mjs.map +1 -1
- package/dist/cli-docs.js +58 -0
- package/dist/cli-docs.js.map +1 -1
- package/dist/cli-docs.mjs +58 -0
- package/dist/cli-docs.mjs.map +1 -1
- package/package.json +3 -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_fs3 = require("fs");
|
|
29
|
+
var import_node_path2 = require("path");
|
|
30
30
|
|
|
31
31
|
// src/cli/executor.ts
|
|
32
32
|
var import_node_fs = require("fs");
|
|
@@ -134,11 +134,229 @@ function formatListOutput(functions) {
|
|
|
134
134
|
return output;
|
|
135
135
|
}
|
|
136
136
|
|
|
137
|
+
// src/cli/export.ts
|
|
138
|
+
var import_node_fs2 = require("fs");
|
|
139
|
+
var import_node_path = require("path");
|
|
140
|
+
var import_open = __toESM(require("open"));
|
|
141
|
+
var import_sdk3 = __toESM(require("@eventcatalog/sdk"));
|
|
142
|
+
var RESOURCE_TYPES = ["event", "command", "query", "service", "domain"];
|
|
143
|
+
var PLURAL_MAP = {
|
|
144
|
+
events: "event",
|
|
145
|
+
commands: "command",
|
|
146
|
+
queries: "query",
|
|
147
|
+
services: "service",
|
|
148
|
+
domains: "domain"
|
|
149
|
+
};
|
|
150
|
+
function normalizeResourceType(resource) {
|
|
151
|
+
const lower = resource.toLowerCase();
|
|
152
|
+
if (PLURAL_MAP[lower]) return PLURAL_MAP[lower];
|
|
153
|
+
return lower;
|
|
154
|
+
}
|
|
155
|
+
function getResourceFetcher(sdk, type) {
|
|
156
|
+
switch (type) {
|
|
157
|
+
case "event":
|
|
158
|
+
return sdk.getEvent;
|
|
159
|
+
case "command":
|
|
160
|
+
return sdk.getCommand;
|
|
161
|
+
case "query":
|
|
162
|
+
return sdk.getQuery;
|
|
163
|
+
case "service":
|
|
164
|
+
return sdk.getService;
|
|
165
|
+
case "domain":
|
|
166
|
+
return sdk.getDomain;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
function getCollectionFetcher(sdk, type) {
|
|
170
|
+
switch (type) {
|
|
171
|
+
case "event":
|
|
172
|
+
return sdk.getEvents;
|
|
173
|
+
case "command":
|
|
174
|
+
return sdk.getCommands;
|
|
175
|
+
case "query":
|
|
176
|
+
return sdk.getQueries;
|
|
177
|
+
case "service":
|
|
178
|
+
return sdk.getServices;
|
|
179
|
+
case "domain":
|
|
180
|
+
return sdk.getDomains;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
function pluralize(type) {
|
|
184
|
+
if (type === "query") return "queries";
|
|
185
|
+
return `${type}s`;
|
|
186
|
+
}
|
|
187
|
+
var SECTION_ORDER = ["team", "user", "channel", "event", "command", "query", "service", "domain"];
|
|
188
|
+
var SECTION_LABELS = {
|
|
189
|
+
team: "TEAMS",
|
|
190
|
+
user: "USERS",
|
|
191
|
+
channel: "CHANNELS",
|
|
192
|
+
event: "EVENTS",
|
|
193
|
+
command: "COMMANDS",
|
|
194
|
+
query: "QUERIES",
|
|
195
|
+
service: "SERVICES",
|
|
196
|
+
domain: "DOMAINS"
|
|
197
|
+
};
|
|
198
|
+
function groupDSLBlocks(dsl) {
|
|
199
|
+
const blocks = dsl.split(/\n\n/).filter((b) => b.trim());
|
|
200
|
+
const buckets = {};
|
|
201
|
+
for (const block of blocks) {
|
|
202
|
+
const firstWord = block.trimStart().split(/\s/)[0];
|
|
203
|
+
const key = firstWord === "subdomain" ? "domain" : firstWord;
|
|
204
|
+
if (!buckets[key]) buckets[key] = [];
|
|
205
|
+
buckets[key].push(block);
|
|
206
|
+
}
|
|
207
|
+
const sections = [];
|
|
208
|
+
for (const type of SECTION_ORDER) {
|
|
209
|
+
if (!buckets[type] || buckets[type].length === 0) continue;
|
|
210
|
+
const label = SECTION_LABELS[type] || type.toUpperCase();
|
|
211
|
+
sections.push(`// ${label}
|
|
212
|
+
${buckets[type].join("\n\n")}`);
|
|
213
|
+
delete buckets[type];
|
|
214
|
+
}
|
|
215
|
+
for (const [type, items] of Object.entries(buckets)) {
|
|
216
|
+
if (items.length === 0) continue;
|
|
217
|
+
const label = type.toUpperCase();
|
|
218
|
+
sections.push(`// ${label}
|
|
219
|
+
${items.join("\n\n")}`);
|
|
220
|
+
}
|
|
221
|
+
return sections.join("\n\n");
|
|
222
|
+
}
|
|
223
|
+
function buildVisualizerBlock(dsl, name, filterTypes) {
|
|
224
|
+
const types = Array.isArray(filterTypes) ? filterTypes : [filterTypes];
|
|
225
|
+
const entries = [];
|
|
226
|
+
for (const line of dsl.split("\n")) {
|
|
227
|
+
const trimmed = line.trimStart();
|
|
228
|
+
const parts = trimmed.split(/\s/);
|
|
229
|
+
const keyword = parts[0];
|
|
230
|
+
const id = parts[1];
|
|
231
|
+
if (!types.includes(keyword)) continue;
|
|
232
|
+
if (!id || !trimmed.endsWith("{")) continue;
|
|
233
|
+
entries.push(` ${keyword} ${id}`);
|
|
234
|
+
}
|
|
235
|
+
if (entries.length === 0) return "";
|
|
236
|
+
return `
|
|
237
|
+
visualizer main {
|
|
238
|
+
name "${name}"
|
|
239
|
+
${entries.join("\n")}
|
|
240
|
+
}`;
|
|
241
|
+
}
|
|
242
|
+
async function exportCatalog(options) {
|
|
243
|
+
const { hydrate = false, stdout = false, playground = false, output, dir } = options;
|
|
244
|
+
const sdk = (0, import_sdk3.default)(dir);
|
|
245
|
+
const dslParts = [];
|
|
246
|
+
for (const type of RESOURCE_TYPES) {
|
|
247
|
+
const fetcher = getCollectionFetcher(sdk, type);
|
|
248
|
+
const resources = await fetcher({ latestOnly: true });
|
|
249
|
+
if (!resources || resources.length === 0) continue;
|
|
250
|
+
const rawDsl = await sdk.toDSL(resources, { type, hydrate });
|
|
251
|
+
dslParts.push(rawDsl);
|
|
252
|
+
}
|
|
253
|
+
if (dslParts.length === 0) {
|
|
254
|
+
throw new Error(`No resources found in catalog at '${dir}'`);
|
|
255
|
+
}
|
|
256
|
+
const combined = dslParts.join("\n\n");
|
|
257
|
+
const grouped = groupDSLBlocks(combined);
|
|
258
|
+
const vizBlock = buildVisualizerBlock(grouped, "Full Catalog", [...RESOURCE_TYPES]);
|
|
259
|
+
const dsl = vizBlock ? `${grouped}
|
|
260
|
+
${vizBlock}` : grouped;
|
|
261
|
+
if (stdout) {
|
|
262
|
+
return dsl;
|
|
263
|
+
}
|
|
264
|
+
const filename = output || "catalog.ec";
|
|
265
|
+
const filepath = (0, import_node_path.resolve)(filename);
|
|
266
|
+
(0, import_node_fs2.writeFileSync)(filepath, dsl + "\n", "utf-8");
|
|
267
|
+
const lines = ["", ` Exported full catalog to ${filepath}`];
|
|
268
|
+
if (playground) {
|
|
269
|
+
const encoded = Buffer.from(dsl).toString("base64");
|
|
270
|
+
const playgroundUrl = `https://playground.eventcatalog.dev/?code=${encoded}`;
|
|
271
|
+
await (0, import_open.default)(playgroundUrl);
|
|
272
|
+
lines.push("", ` Opening in playground...`);
|
|
273
|
+
} else {
|
|
274
|
+
lines.push("", ` Tip: Use --playground to open in the playground`);
|
|
275
|
+
}
|
|
276
|
+
lines.push("");
|
|
277
|
+
return lines.join("\n");
|
|
278
|
+
}
|
|
279
|
+
async function exportAll(options) {
|
|
280
|
+
const { resource, hydrate = false, stdout = false, playground = false, output, dir } = options;
|
|
281
|
+
const type = normalizeResourceType(resource);
|
|
282
|
+
if (!RESOURCE_TYPES.includes(type)) {
|
|
283
|
+
throw new Error(`Invalid resource type '${resource}'. Must be one of: ${RESOURCE_TYPES.join(", ")}`);
|
|
284
|
+
}
|
|
285
|
+
const plural = pluralize(type);
|
|
286
|
+
const sdk = (0, import_sdk3.default)(dir);
|
|
287
|
+
const fetcher = getCollectionFetcher(sdk, type);
|
|
288
|
+
const allResources = await fetcher({ latestOnly: true }) || [];
|
|
289
|
+
if (allResources.length === 0) {
|
|
290
|
+
throw new Error(`No ${plural} found in catalog at '${dir}'`);
|
|
291
|
+
}
|
|
292
|
+
const rawDsl = await sdk.toDSL(allResources, { type, hydrate });
|
|
293
|
+
const grouped = groupDSLBlocks(rawDsl);
|
|
294
|
+
const vizBlock = buildVisualizerBlock(grouped, `All ${plural}`, type);
|
|
295
|
+
const dsl = vizBlock ? `${grouped}
|
|
296
|
+
${vizBlock}` : grouped;
|
|
297
|
+
if (stdout) {
|
|
298
|
+
return dsl;
|
|
299
|
+
}
|
|
300
|
+
const filename = output || `${plural}.ec`;
|
|
301
|
+
const filepath = (0, import_node_path.resolve)(filename);
|
|
302
|
+
(0, import_node_fs2.writeFileSync)(filepath, dsl + "\n", "utf-8");
|
|
303
|
+
const lines = ["", ` Exported ${allResources.length} ${plural} to ${filepath}`];
|
|
304
|
+
if (playground) {
|
|
305
|
+
const encoded = Buffer.from(dsl).toString("base64");
|
|
306
|
+
const playgroundUrl = `https://playground.eventcatalog.dev/?code=${encoded}`;
|
|
307
|
+
await (0, import_open.default)(playgroundUrl);
|
|
308
|
+
lines.push("", ` Opening in playground...`);
|
|
309
|
+
} else {
|
|
310
|
+
lines.push("", ` Tip: Use --playground to open in the playground`);
|
|
311
|
+
}
|
|
312
|
+
lines.push("");
|
|
313
|
+
return lines.join("\n");
|
|
314
|
+
}
|
|
315
|
+
async function exportResource(options) {
|
|
316
|
+
const { resource, id, version: version2, hydrate = false, stdout = false, playground = false, output, dir } = options;
|
|
317
|
+
if (!id) {
|
|
318
|
+
return exportAll(options);
|
|
319
|
+
}
|
|
320
|
+
const type = normalizeResourceType(resource);
|
|
321
|
+
if (!RESOURCE_TYPES.includes(type)) {
|
|
322
|
+
throw new Error(`Invalid resource type '${resource}'. Must be one of: ${RESOURCE_TYPES.join(", ")}`);
|
|
323
|
+
}
|
|
324
|
+
const sdk = (0, import_sdk3.default)(dir);
|
|
325
|
+
const fetcher = getResourceFetcher(sdk, type);
|
|
326
|
+
const data = await fetcher(id, version2);
|
|
327
|
+
if (!data) {
|
|
328
|
+
const versionStr = version2 ? `@${version2}` : " (latest)";
|
|
329
|
+
throw new Error(`${resource} '${id}${versionStr}' not found in catalog at '${dir}'`);
|
|
330
|
+
}
|
|
331
|
+
const rawDsl = await sdk.toDSL(data, { type, hydrate });
|
|
332
|
+
const grouped = hydrate ? groupDSLBlocks(rawDsl) : rawDsl;
|
|
333
|
+
const vizBlock = buildVisualizerBlock(grouped, `View of ${id}`, type);
|
|
334
|
+
const dsl = vizBlock ? `${grouped}
|
|
335
|
+
${vizBlock}` : grouped;
|
|
336
|
+
if (stdout) {
|
|
337
|
+
return dsl;
|
|
338
|
+
}
|
|
339
|
+
const filename = output || `${id}.ec`;
|
|
340
|
+
const filepath = (0, import_node_path.resolve)(filename);
|
|
341
|
+
(0, import_node_fs2.writeFileSync)(filepath, dsl + "\n", "utf-8");
|
|
342
|
+
const lines = ["", ` Exported ${type} '${id}' to ${filepath}`];
|
|
343
|
+
if (playground) {
|
|
344
|
+
const encoded = Buffer.from(dsl).toString("base64");
|
|
345
|
+
const playgroundUrl = `https://playground.eventcatalog.dev/?code=${encoded}`;
|
|
346
|
+
await (0, import_open.default)(playgroundUrl);
|
|
347
|
+
lines.push("", ` Opening in playground...`);
|
|
348
|
+
} else {
|
|
349
|
+
lines.push("", ` Tip: Use --playground to open in the playground`);
|
|
350
|
+
}
|
|
351
|
+
lines.push("");
|
|
352
|
+
return lines.join("\n");
|
|
353
|
+
}
|
|
354
|
+
|
|
137
355
|
// src/cli/index.ts
|
|
138
356
|
var version = "1.0.0";
|
|
139
357
|
try {
|
|
140
|
-
const packageJsonPath = (0,
|
|
141
|
-
const packageJson = JSON.parse((0,
|
|
358
|
+
const packageJsonPath = (0, import_node_path2.resolve)(__dirname, "../../package.json");
|
|
359
|
+
const packageJson = JSON.parse((0, import_node_fs3.readFileSync)(packageJsonPath, "utf-8"));
|
|
142
360
|
version = packageJson.version;
|
|
143
361
|
} catch {
|
|
144
362
|
}
|
|
@@ -153,6 +371,41 @@ import_commander.program.command("list").description("List all available SDK fun
|
|
|
153
371
|
process.exit(1);
|
|
154
372
|
}
|
|
155
373
|
});
|
|
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 the playground", false).option("-o, --output <path>", "Output file path (defaults to <id>.ec or catalog.ec)").action(async (opts) => {
|
|
375
|
+
try {
|
|
376
|
+
const globalOpts = import_commander.program.opts();
|
|
377
|
+
const dir = globalOpts.dir || ".";
|
|
378
|
+
if (opts.all) {
|
|
379
|
+
const result2 = await exportCatalog({
|
|
380
|
+
hydrate: opts.hydrate,
|
|
381
|
+
stdout: opts.stdout,
|
|
382
|
+
playground: opts.playground,
|
|
383
|
+
output: opts.output,
|
|
384
|
+
dir
|
|
385
|
+
});
|
|
386
|
+
console.log(result2);
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
if (!opts.resource) {
|
|
390
|
+
console.error("Either --all or --resource is required");
|
|
391
|
+
process.exit(1);
|
|
392
|
+
}
|
|
393
|
+
const result = await exportResource({
|
|
394
|
+
resource: opts.resource,
|
|
395
|
+
id: opts.id,
|
|
396
|
+
version: opts.version,
|
|
397
|
+
hydrate: opts.hydrate,
|
|
398
|
+
stdout: opts.stdout,
|
|
399
|
+
playground: opts.playground,
|
|
400
|
+
output: opts.output,
|
|
401
|
+
dir
|
|
402
|
+
});
|
|
403
|
+
console.log(result);
|
|
404
|
+
} catch (error) {
|
|
405
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
406
|
+
process.exit(1);
|
|
407
|
+
}
|
|
408
|
+
});
|
|
156
409
|
import_commander.program.arguments("<function> [args...]").action(async (functionName, args) => {
|
|
157
410
|
try {
|
|
158
411
|
const options = import_commander.program.opts();
|
package/dist/cli/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/cli/index.ts","../../src/cli/executor.ts","../../src/cli/parser.ts","../../src/cli/list.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { program } from 'commander';\nimport { readFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { executeFunction } from './executor';\nimport { listFunctions, formatListOutput } from './list';\n\n// Read package.json to get version\nlet version = '1.0.0';\ntry {\n const packageJsonPath = resolve(__dirname, '../../package.json');\n const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));\n version = packageJson.version;\n} catch {\n // Fall back to default version if package.json not found\n}\n\nprogram\n .name('eventcatalog')\n .description('EventCatalog Command-Line Interface')\n .version(version)\n .option('-d, --dir <path>', 'Path to the EventCatalog directory (default: current directory)', '.');\n\n// List command - show all available functions\nprogram\n .command('list')\n .description('List all available SDK functions')\n .action(() => {\n try {\n const functions = listFunctions('.');\n const output = formatListOutput(functions);\n console.log(output);\n } catch (error) {\n console.error('Error listing functions:', error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n });\n\n// Catch-all for any other command - execute as SDK function\nprogram.arguments('<function> [args...]').action(async (functionName: string, args: string[]) => {\n try {\n const options = program.opts() as any;\n const dir = options.dir || '.';\n const result = await executeFunction(dir, functionName, args);\n console.log(JSON.stringify(result, null, 0));\n } catch (error) {\n console.error(error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n});\n\nprogram.parse(process.argv);\n\n// Show help if no command provided\nif (process.argv.length < 3) {\n program.outputHelp();\n}\n","import { existsSync } from 'node:fs';\nimport { parseArguments } from './parser';\nimport createSDK from '@eventcatalog/sdk';\n\n/**\n * Execute a SDK function with the given arguments\n */\nexport async function executeFunction(catalogDir: string, functionName: string, rawArgs: string[]): Promise<any> {\n // Validate catalog directory exists\n if (!existsSync(catalogDir)) {\n throw new Error(`Catalog directory not found: ${catalogDir}`);\n }\n\n // Initialize the SDK\n const sdk = createSDK(catalogDir);\n\n // Validate function exists\n if (!(functionName in sdk)) {\n throw new Error(`Function '${functionName}' not found. Use 'eventcatalog list' to see available functions.`);\n }\n\n const fn = (sdk as any)[functionName];\n\n // Validate it's callable\n if (typeof fn !== 'function') {\n throw new Error(`'${functionName}' is not a callable function.`);\n }\n\n // Parse arguments\n const parsedArgs = parseArguments(rawArgs);\n\n // Execute function\n try {\n return await fn(...parsedArgs);\n } catch (error) {\n throw new Error(`Error executing '${functionName}': ${error instanceof Error ? error.message : String(error)}`);\n }\n}\n","/**\n * Parse command-line arguments into typed values\n * Supports JSON objects/arrays, booleans, numbers, and strings\n */\nexport function parseArguments(rawArgs: string[]): any[] {\n return rawArgs.map((arg, index) => {\n // Try to parse as JSON object or array if it looks like JSON\n if ((arg.startsWith('{') && arg.endsWith('}')) || (arg.startsWith('[') && arg.endsWith(']'))) {\n try {\n return JSON.parse(arg);\n } catch (error) {\n // If it fails to parse as JSON, treat it as a string\n // Only throw error if it looks like valid JSON syntax was intended\n if (arg.includes(':') || arg.includes(',')) {\n throw new Error(`Invalid JSON in argument ${index + 1}: ${error instanceof Error ? error.message : String(error)}`);\n }\n // Otherwise, return as string\n return arg;\n }\n }\n\n // Parse booleans\n if (arg === 'true') return true;\n if (arg === 'false') return false;\n\n // Parse numbers\n if (/^-?\\d+(\\.\\d+)?$/.test(arg)) {\n return Number(arg);\n }\n\n // Return as string\n return arg;\n });\n}\n","import createSDK from '@eventcatalog/sdk';\n\ninterface CategorizedFunctions {\n [category: string]: string[];\n}\n\n/**\n * Get all available SDK functions organized by category\n */\nexport function listFunctions(catalogDir: string = '.'): CategorizedFunctions {\n // Initialize SDK to get all functions\n const sdk = createSDK(catalogDir);\n\n // Get all function names from SDK\n const functionNames = Object.keys(sdk).filter((key) => typeof (sdk as any)[key] === 'function');\n\n // Categorize functions based on naming patterns\n const categories: CategorizedFunctions = {\n Events: [],\n Commands: [],\n Queries: [],\n Channels: [],\n Services: [],\n Domains: [],\n Entities: [],\n DataStores: [],\n DataProducts: [],\n Teams: [],\n Users: [],\n 'Custom Docs': [],\n Messages: [],\n Utilities: [],\n };\n\n functionNames.forEach((name) => {\n if (name.includes('Event')) categories['Events'].push(name);\n else if (name.includes('Command')) categories['Commands'].push(name);\n else if (name.includes('Query')) categories['Queries'].push(name);\n else if (name.includes('Channel')) categories['Channels'].push(name);\n else if (name.includes('Service')) categories['Services'].push(name);\n else if (name.includes('Domain')) categories['Domains'].push(name);\n else if (name.includes('Entity')) categories['Entities'].push(name);\n else if (name.includes('DataStore')) categories['DataStores'].push(name);\n else if (name.includes('DataProduct')) categories['DataProducts'].push(name);\n else if (name.includes('Team')) categories['Teams'].push(name);\n else if (name.includes('User')) categories['Users'].push(name);\n else if (name.includes('CustomDoc')) categories['Custom Docs'].push(name);\n else if (name.includes('Message') || name.includes('Producers') || name.includes('Consumers'))\n categories['Messages'].push(name);\n else categories['Utilities'].push(name);\n });\n\n // Remove empty categories\n Object.keys(categories).forEach((key) => {\n if (categories[key].length === 0) {\n delete categories[key];\n }\n });\n\n return categories;\n}\n\n/**\n * Format and print categorized functions\n */\nexport function formatListOutput(functions: CategorizedFunctions): string {\n let output = 'Available EventCatalog SDK Functions:\\n\\n';\n\n Object.entries(functions).forEach(([category, names]) => {\n output += `${category}:\\n`;\n names.sort().forEach((name) => {\n output += ` - ${name}\\n`;\n });\n output += '\\n';\n });\n\n return output;\n}\n"],"mappings":"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","names":["import_node_fs","createSDK","import_sdk","createSDK"]}
|
|
1
|
+
{"version":3,"sources":["../../src/cli/index.ts","../../src/cli/executor.ts","../../src/cli/parser.ts","../../src/cli/list.ts","../../src/cli/export.ts"],"sourcesContent":["#!/usr/bin/env node\n\nimport { program } from 'commander';\nimport { readFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { executeFunction } from './executor';\nimport { listFunctions, formatListOutput } from './list';\nimport { exportResource, exportCatalog } from './export';\n\n// Read package.json to get version\nlet version = '1.0.0';\ntry {\n const packageJsonPath = resolve(__dirname, '../../package.json');\n const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));\n version = packageJson.version;\n} catch {\n // Fall back to default version if package.json not found\n}\n\nprogram\n .name('eventcatalog')\n .description('EventCatalog Command-Line Interface')\n .version(version)\n .option('-d, --dir <path>', 'Path to the EventCatalog directory (default: current directory)', '.');\n\n// List command - show all available functions\nprogram\n .command('list')\n .description('List all available SDK functions')\n .action(() => {\n try {\n const functions = listFunctions('.');\n const output = formatListOutput(functions);\n console.log(output);\n } catch (error) {\n console.error('Error listing functions:', error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n });\n\n// Export command - export a resource to .ec DSL format\nprogram\n .command('export')\n .description('Export a catalog resource to EventCatalog DSL (.ec) format')\n .option('-a, --all', 'Export the entire catalog (all resource types)', false)\n .option('-r, --resource <type>', 'Resource type (event, command, query, service, domain)')\n .option('--id <id>', 'Resource ID (omit to export all resources of the given type)')\n .option('-v, --version <version>', 'Resource version (defaults to latest)')\n .option('--hydrate', 'Include referenced resources (messages, channels, owners)', false)\n .option('--stdout', 'Print to stdout instead of writing a file', false)\n .option('--playground', 'Open the exported DSL in the playground', false)\n .option('-o, --output <path>', 'Output file path (defaults to <id>.ec or catalog.ec)')\n .action(async (opts) => {\n try {\n const globalOpts = program.opts() as any;\n const dir = globalOpts.dir || '.';\n\n if (opts.all) {\n const result = await exportCatalog({\n hydrate: opts.hydrate,\n stdout: opts.stdout,\n playground: opts.playground,\n output: opts.output,\n dir,\n });\n console.log(result);\n return;\n }\n\n if (!opts.resource) {\n console.error('Either --all or --resource is required');\n process.exit(1);\n }\n\n const result = await exportResource({\n resource: opts.resource,\n id: opts.id,\n version: opts.version,\n hydrate: opts.hydrate,\n stdout: opts.stdout,\n playground: opts.playground,\n output: opts.output,\n dir,\n });\n console.log(result);\n } catch (error) {\n console.error(error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n });\n\n// Catch-all for any other command - execute as SDK function\nprogram.arguments('<function> [args...]').action(async (functionName: string, args: string[]) => {\n try {\n const options = program.opts() as any;\n const dir = options.dir || '.';\n const result = await executeFunction(dir, functionName, args);\n console.log(JSON.stringify(result, null, 0));\n } catch (error) {\n console.error(error instanceof Error ? error.message : String(error));\n process.exit(1);\n }\n});\n\nprogram.parse(process.argv);\n\n// Show help if no command provided\nif (process.argv.length < 3) {\n program.outputHelp();\n}\n","import { existsSync } from 'node:fs';\nimport { parseArguments } from './parser';\nimport createSDK from '@eventcatalog/sdk';\n\n/**\n * Execute a SDK function with the given arguments\n */\nexport async function executeFunction(catalogDir: string, functionName: string, rawArgs: string[]): Promise<any> {\n // Validate catalog directory exists\n if (!existsSync(catalogDir)) {\n throw new Error(`Catalog directory not found: ${catalogDir}`);\n }\n\n // Initialize the SDK\n const sdk = createSDK(catalogDir);\n\n // Validate function exists\n if (!(functionName in sdk)) {\n throw new Error(`Function '${functionName}' not found. Use 'eventcatalog list' to see available functions.`);\n }\n\n const fn = (sdk as any)[functionName];\n\n // Validate it's callable\n if (typeof fn !== 'function') {\n throw new Error(`'${functionName}' is not a callable function.`);\n }\n\n // Parse arguments\n const parsedArgs = parseArguments(rawArgs);\n\n // Execute function\n try {\n return await fn(...parsedArgs);\n } catch (error) {\n throw new Error(`Error executing '${functionName}': ${error instanceof Error ? error.message : String(error)}`);\n }\n}\n","/**\n * Parse command-line arguments into typed values\n * Supports JSON objects/arrays, booleans, numbers, and strings\n */\nexport function parseArguments(rawArgs: string[]): any[] {\n return rawArgs.map((arg, index) => {\n // Try to parse as JSON object or array if it looks like JSON\n if ((arg.startsWith('{') && arg.endsWith('}')) || (arg.startsWith('[') && arg.endsWith(']'))) {\n try {\n return JSON.parse(arg);\n } catch (error) {\n // If it fails to parse as JSON, treat it as a string\n // Only throw error if it looks like valid JSON syntax was intended\n if (arg.includes(':') || arg.includes(',')) {\n throw new Error(`Invalid JSON in argument ${index + 1}: ${error instanceof Error ? error.message : String(error)}`);\n }\n // Otherwise, return as string\n return arg;\n }\n }\n\n // Parse booleans\n if (arg === 'true') return true;\n if (arg === 'false') return false;\n\n // Parse numbers\n if (/^-?\\d+(\\.\\d+)?$/.test(arg)) {\n return Number(arg);\n }\n\n // Return as string\n return arg;\n });\n}\n","import createSDK from '@eventcatalog/sdk';\n\ninterface CategorizedFunctions {\n [category: string]: string[];\n}\n\n/**\n * Get all available SDK functions organized by category\n */\nexport function listFunctions(catalogDir: string = '.'): CategorizedFunctions {\n // Initialize SDK to get all functions\n const sdk = createSDK(catalogDir);\n\n // Get all function names from SDK\n const functionNames = Object.keys(sdk).filter((key) => typeof (sdk as any)[key] === 'function');\n\n // Categorize functions based on naming patterns\n const categories: CategorizedFunctions = {\n Events: [],\n Commands: [],\n Queries: [],\n Channels: [],\n Services: [],\n Domains: [],\n Entities: [],\n DataStores: [],\n DataProducts: [],\n Teams: [],\n Users: [],\n 'Custom Docs': [],\n Messages: [],\n Utilities: [],\n };\n\n functionNames.forEach((name) => {\n if (name.includes('Event')) categories['Events'].push(name);\n else if (name.includes('Command')) categories['Commands'].push(name);\n else if (name.includes('Query')) categories['Queries'].push(name);\n else if (name.includes('Channel')) categories['Channels'].push(name);\n else if (name.includes('Service')) categories['Services'].push(name);\n else if (name.includes('Domain')) categories['Domains'].push(name);\n else if (name.includes('Entity')) categories['Entities'].push(name);\n else if (name.includes('DataStore')) categories['DataStores'].push(name);\n else if (name.includes('DataProduct')) categories['DataProducts'].push(name);\n else if (name.includes('Team')) categories['Teams'].push(name);\n else if (name.includes('User')) categories['Users'].push(name);\n else if (name.includes('CustomDoc')) categories['Custom Docs'].push(name);\n else if (name.includes('Message') || name.includes('Producers') || name.includes('Consumers'))\n categories['Messages'].push(name);\n else categories['Utilities'].push(name);\n });\n\n // Remove empty categories\n Object.keys(categories).forEach((key) => {\n if (categories[key].length === 0) {\n delete categories[key];\n }\n });\n\n return categories;\n}\n\n/**\n * Format and print categorized functions\n */\nexport function formatListOutput(functions: CategorizedFunctions): string {\n let output = 'Available EventCatalog SDK Functions:\\n\\n';\n\n Object.entries(functions).forEach(([category, names]) => {\n output += `${category}:\\n`;\n names.sort().forEach((name) => {\n output += ` - ${name}\\n`;\n });\n output += '\\n';\n });\n\n return output;\n}\n","import { writeFileSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport open from 'open';\nimport createSDK from '@eventcatalog/sdk';\n\nconst RESOURCE_TYPES = ['event', 'command', 'query', 'service', 'domain'] as const;\ntype ResourceType = (typeof RESOURCE_TYPES)[number];\n\nconst PLURAL_MAP: Record<string, ResourceType> = {\n events: 'event',\n commands: 'command',\n queries: 'query',\n services: 'service',\n domains: 'domain',\n};\n\ninterface ExportOptions {\n resource: string;\n id?: string;\n version?: string;\n hydrate?: boolean;\n stdout?: boolean;\n playground?: boolean;\n output?: string;\n dir: string;\n}\n\nfunction normalizeResourceType(resource: string): ResourceType {\n const lower = resource.toLowerCase();\n if (PLURAL_MAP[lower]) return PLURAL_MAP[lower];\n return lower as ResourceType;\n}\n\nfunction getResourceFetcher(sdk: ReturnType<typeof createSDK>, type: ResourceType) {\n switch (type) {\n case 'event':\n return sdk.getEvent;\n case 'command':\n return sdk.getCommand;\n case 'query':\n return sdk.getQuery;\n case 'service':\n return sdk.getService;\n case 'domain':\n return sdk.getDomain;\n }\n}\n\nfunction getCollectionFetcher(sdk: ReturnType<typeof createSDK>, type: ResourceType) {\n switch (type) {\n case 'event':\n return sdk.getEvents;\n case 'command':\n return sdk.getCommands;\n case 'query':\n return sdk.getQueries;\n case 'service':\n return sdk.getServices;\n case 'domain':\n return sdk.getDomains;\n }\n}\n\nfunction pluralize(type: ResourceType): string {\n if (type === 'query') return 'queries';\n return `${type}s`;\n}\n\nconst SECTION_ORDER = ['team', 'user', 'channel', 'event', 'command', 'query', 'service', 'domain'] as const;\n\nconst SECTION_LABELS: Record<string, string> = {\n team: 'TEAMS',\n user: 'USERS',\n channel: 'CHANNELS',\n event: 'EVENTS',\n command: 'COMMANDS',\n query: 'QUERIES',\n service: 'SERVICES',\n domain: 'DOMAINS',\n};\n\nfunction groupDSLBlocks(dsl: string): string {\n const blocks = dsl.split(/\\n\\n/).filter((b) => b.trim());\n const buckets: Record<string, string[]> = {};\n\n for (const block of blocks) {\n const firstWord = block.trimStart().split(/\\s/)[0];\n const key = firstWord === 'subdomain' ? 'domain' : firstWord;\n if (!buckets[key]) buckets[key] = [];\n buckets[key].push(block);\n }\n\n const sections: string[] = [];\n for (const type of SECTION_ORDER) {\n if (!buckets[type] || buckets[type].length === 0) continue;\n const label = SECTION_LABELS[type] || type.toUpperCase();\n sections.push(`// ${label}\\n${buckets[type].join('\\n\\n')}`);\n delete buckets[type];\n }\n\n // Any remaining types not in SECTION_ORDER\n for (const [type, items] of Object.entries(buckets)) {\n if (items.length === 0) continue;\n const label = type.toUpperCase();\n sections.push(`// ${label}\\n${items.join('\\n\\n')}`);\n }\n\n return sections.join('\\n\\n');\n}\n\nconst VISUALIZER_TYPES = ['event', 'command', 'query', 'service', 'domain'] as const;\n\nfunction buildVisualizerBlock(dsl: string, name: string, filterTypes: ResourceType | ResourceType[]): string {\n const types = Array.isArray(filterTypes) ? filterTypes : [filterTypes];\n const entries: string[] = [];\n\n for (const line of dsl.split('\\n')) {\n const trimmed = line.trimStart();\n const parts = trimmed.split(/\\s/);\n const keyword = parts[0];\n const id = parts[1];\n if (!types.includes(keyword as ResourceType)) continue;\n if (!id || !trimmed.endsWith('{')) continue;\n entries.push(` ${keyword} ${id}`);\n }\n\n if (entries.length === 0) return '';\n return `\\nvisualizer main {\\n name \"${name}\"\\n${entries.join('\\n')}\\n}`;\n}\n\nexport async function exportCatalog(options: Omit<ExportOptions, 'resource'>): Promise<string> {\n const { hydrate = false, stdout = false, playground = false, output, dir } = options;\n\n const sdk = createSDK(dir);\n const dslParts: string[] = [];\n\n for (const type of RESOURCE_TYPES) {\n const fetcher = getCollectionFetcher(sdk, type);\n const resources = await fetcher({ latestOnly: true });\n if (!resources || resources.length === 0) continue;\n const rawDsl = await sdk.toDSL(resources, { type, hydrate });\n dslParts.push(rawDsl);\n }\n\n if (dslParts.length === 0) {\n throw new Error(`No resources found in catalog at '${dir}'`);\n }\n\n const combined = dslParts.join('\\n\\n');\n const grouped = groupDSLBlocks(combined);\n const vizBlock = buildVisualizerBlock(grouped, 'Full Catalog', [...RESOURCE_TYPES]);\n const dsl = vizBlock ? `${grouped}\\n${vizBlock}` : grouped;\n\n if (stdout) {\n return dsl;\n }\n\n const filename = output || 'catalog.ec';\n const filepath = resolve(filename);\n writeFileSync(filepath, dsl + '\\n', 'utf-8');\n\n const lines = ['', ` Exported full catalog to ${filepath}`];\n\n if (playground) {\n const encoded = Buffer.from(dsl).toString('base64');\n const playgroundUrl = `https://playground.eventcatalog.dev/?code=${encoded}`;\n await open(playgroundUrl);\n lines.push('', ` Opening in playground...`);\n } else {\n lines.push('', ` Tip: Use --playground to open in the playground`);\n }\n\n lines.push('');\n return lines.join('\\n');\n}\n\nexport async function exportAll(options: ExportOptions): Promise<string> {\n const { resource, hydrate = false, stdout = false, playground = false, output, dir } = options;\n\n const type = normalizeResourceType(resource);\n if (!RESOURCE_TYPES.includes(type)) {\n throw new Error(`Invalid resource type '${resource}'. Must be one of: ${RESOURCE_TYPES.join(', ')}`);\n }\n\n const plural = pluralize(type);\n const sdk = createSDK(dir);\n\n const fetcher = getCollectionFetcher(sdk, type);\n const allResources = (await fetcher({ latestOnly: true })) || [];\n\n if (allResources.length === 0) {\n throw new Error(`No ${plural} found in catalog at '${dir}'`);\n }\n\n const rawDsl = await sdk.toDSL(allResources, { type, hydrate });\n const grouped = groupDSLBlocks(rawDsl);\n const vizBlock = buildVisualizerBlock(grouped, `All ${plural}`, type);\n const dsl = vizBlock ? `${grouped}\\n${vizBlock}` : grouped;\n\n if (stdout) {\n return dsl;\n }\n\n const filename = output || `${plural}.ec`;\n const filepath = resolve(filename);\n writeFileSync(filepath, dsl + '\\n', 'utf-8');\n\n const lines = ['', ` Exported ${allResources.length} ${plural} to ${filepath}`];\n\n if (playground) {\n const encoded = Buffer.from(dsl).toString('base64');\n const playgroundUrl = `https://playground.eventcatalog.dev/?code=${encoded}`;\n await open(playgroundUrl);\n lines.push('', ` Opening in playground...`);\n } else {\n lines.push('', ` Tip: Use --playground to open in the playground`);\n }\n\n lines.push('');\n return lines.join('\\n');\n}\n\nexport async function exportResource(options: ExportOptions): Promise<string> {\n const { resource, id, version, hydrate = false, stdout = false, playground = false, output, dir } = options;\n\n if (!id) {\n return exportAll(options);\n }\n\n const type = normalizeResourceType(resource);\n if (!RESOURCE_TYPES.includes(type)) {\n throw new Error(`Invalid resource type '${resource}'. Must be one of: ${RESOURCE_TYPES.join(', ')}`);\n }\n\n const sdk = createSDK(dir);\n\n const fetcher = getResourceFetcher(sdk, type);\n const data = await fetcher(id, version);\n\n if (!data) {\n const versionStr = version ? `@${version}` : ' (latest)';\n throw new Error(`${resource} '${id}${versionStr}' not found in catalog at '${dir}'`);\n }\n\n const rawDsl = await sdk.toDSL(data, { type, hydrate });\n const grouped = hydrate ? groupDSLBlocks(rawDsl) : rawDsl;\n const vizBlock = buildVisualizerBlock(grouped, `View of ${id}`, type);\n const dsl = vizBlock ? `${grouped}\\n${vizBlock}` : grouped;\n\n if (stdout) {\n return dsl;\n }\n\n const filename = output || `${id}.ec`;\n const filepath = resolve(filename);\n writeFileSync(filepath, dsl + '\\n', 'utf-8');\n\n const lines = ['', ` Exported ${type} '${id}' to ${filepath}`];\n\n if (playground) {\n const encoded = Buffer.from(dsl).toString('base64');\n const playgroundUrl = `https://playground.eventcatalog.dev/?code=${encoded}`;\n await open(playgroundUrl);\n lines.push('', ` Opening in playground...`);\n } else {\n lines.push('', ` Tip: Use --playground to open in the playground`);\n }\n\n lines.push('');\n return lines.join('\\n');\n}\n"],"mappings":"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","names":["import_node_fs","import_node_path","createSDK","import_sdk","createSDK","import_node_fs","import_sdk","createSDK","open","version","result"]}
|
package/dist/cli/index.mjs
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
// ../../node_modules/.pnpm/tsup@8.5.0_jiti@
|
|
3
|
+
// ../../node_modules/.pnpm/tsup@8.5.0_jiti@2.6.1_postcss@8.5.6_tsx@4.21.0_typescript@5.9.3_yaml@2.8.1/node_modules/tsup/assets/esm_shims.js
|
|
4
4
|
import path from "path";
|
|
5
5
|
import { fileURLToPath } from "url";
|
|
6
6
|
var getFilename = () => fileURLToPath(import.meta.url);
|
|
@@ -10,7 +10,7 @@ var __dirname = /* @__PURE__ */ getDirname();
|
|
|
10
10
|
// src/cli/index.ts
|
|
11
11
|
import { program } from "commander";
|
|
12
12
|
import { readFileSync } from "fs";
|
|
13
|
-
import { resolve } from "path";
|
|
13
|
+
import { resolve as resolve2 } from "path";
|
|
14
14
|
|
|
15
15
|
// src/cli/executor.ts
|
|
16
16
|
import { existsSync } from "fs";
|
|
@@ -118,10 +118,228 @@ function formatListOutput(functions) {
|
|
|
118
118
|
return output;
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
+
// src/cli/export.ts
|
|
122
|
+
import { writeFileSync } from "fs";
|
|
123
|
+
import { resolve } from "path";
|
|
124
|
+
import open from "open";
|
|
125
|
+
import createSDK3 from "@eventcatalog/sdk";
|
|
126
|
+
var RESOURCE_TYPES = ["event", "command", "query", "service", "domain"];
|
|
127
|
+
var PLURAL_MAP = {
|
|
128
|
+
events: "event",
|
|
129
|
+
commands: "command",
|
|
130
|
+
queries: "query",
|
|
131
|
+
services: "service",
|
|
132
|
+
domains: "domain"
|
|
133
|
+
};
|
|
134
|
+
function normalizeResourceType(resource) {
|
|
135
|
+
const lower = resource.toLowerCase();
|
|
136
|
+
if (PLURAL_MAP[lower]) return PLURAL_MAP[lower];
|
|
137
|
+
return lower;
|
|
138
|
+
}
|
|
139
|
+
function getResourceFetcher(sdk, type) {
|
|
140
|
+
switch (type) {
|
|
141
|
+
case "event":
|
|
142
|
+
return sdk.getEvent;
|
|
143
|
+
case "command":
|
|
144
|
+
return sdk.getCommand;
|
|
145
|
+
case "query":
|
|
146
|
+
return sdk.getQuery;
|
|
147
|
+
case "service":
|
|
148
|
+
return sdk.getService;
|
|
149
|
+
case "domain":
|
|
150
|
+
return sdk.getDomain;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
function getCollectionFetcher(sdk, type) {
|
|
154
|
+
switch (type) {
|
|
155
|
+
case "event":
|
|
156
|
+
return sdk.getEvents;
|
|
157
|
+
case "command":
|
|
158
|
+
return sdk.getCommands;
|
|
159
|
+
case "query":
|
|
160
|
+
return sdk.getQueries;
|
|
161
|
+
case "service":
|
|
162
|
+
return sdk.getServices;
|
|
163
|
+
case "domain":
|
|
164
|
+
return sdk.getDomains;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
function pluralize(type) {
|
|
168
|
+
if (type === "query") return "queries";
|
|
169
|
+
return `${type}s`;
|
|
170
|
+
}
|
|
171
|
+
var SECTION_ORDER = ["team", "user", "channel", "event", "command", "query", "service", "domain"];
|
|
172
|
+
var SECTION_LABELS = {
|
|
173
|
+
team: "TEAMS",
|
|
174
|
+
user: "USERS",
|
|
175
|
+
channel: "CHANNELS",
|
|
176
|
+
event: "EVENTS",
|
|
177
|
+
command: "COMMANDS",
|
|
178
|
+
query: "QUERIES",
|
|
179
|
+
service: "SERVICES",
|
|
180
|
+
domain: "DOMAINS"
|
|
181
|
+
};
|
|
182
|
+
function groupDSLBlocks(dsl) {
|
|
183
|
+
const blocks = dsl.split(/\n\n/).filter((b) => b.trim());
|
|
184
|
+
const buckets = {};
|
|
185
|
+
for (const block of blocks) {
|
|
186
|
+
const firstWord = block.trimStart().split(/\s/)[0];
|
|
187
|
+
const key = firstWord === "subdomain" ? "domain" : firstWord;
|
|
188
|
+
if (!buckets[key]) buckets[key] = [];
|
|
189
|
+
buckets[key].push(block);
|
|
190
|
+
}
|
|
191
|
+
const sections = [];
|
|
192
|
+
for (const type of SECTION_ORDER) {
|
|
193
|
+
if (!buckets[type] || buckets[type].length === 0) continue;
|
|
194
|
+
const label = SECTION_LABELS[type] || type.toUpperCase();
|
|
195
|
+
sections.push(`// ${label}
|
|
196
|
+
${buckets[type].join("\n\n")}`);
|
|
197
|
+
delete buckets[type];
|
|
198
|
+
}
|
|
199
|
+
for (const [type, items] of Object.entries(buckets)) {
|
|
200
|
+
if (items.length === 0) continue;
|
|
201
|
+
const label = type.toUpperCase();
|
|
202
|
+
sections.push(`// ${label}
|
|
203
|
+
${items.join("\n\n")}`);
|
|
204
|
+
}
|
|
205
|
+
return sections.join("\n\n");
|
|
206
|
+
}
|
|
207
|
+
function buildVisualizerBlock(dsl, name, filterTypes) {
|
|
208
|
+
const types = Array.isArray(filterTypes) ? filterTypes : [filterTypes];
|
|
209
|
+
const entries = [];
|
|
210
|
+
for (const line of dsl.split("\n")) {
|
|
211
|
+
const trimmed = line.trimStart();
|
|
212
|
+
const parts = trimmed.split(/\s/);
|
|
213
|
+
const keyword = parts[0];
|
|
214
|
+
const id = parts[1];
|
|
215
|
+
if (!types.includes(keyword)) continue;
|
|
216
|
+
if (!id || !trimmed.endsWith("{")) continue;
|
|
217
|
+
entries.push(` ${keyword} ${id}`);
|
|
218
|
+
}
|
|
219
|
+
if (entries.length === 0) return "";
|
|
220
|
+
return `
|
|
221
|
+
visualizer main {
|
|
222
|
+
name "${name}"
|
|
223
|
+
${entries.join("\n")}
|
|
224
|
+
}`;
|
|
225
|
+
}
|
|
226
|
+
async function exportCatalog(options) {
|
|
227
|
+
const { hydrate = false, stdout = false, playground = false, output, dir } = options;
|
|
228
|
+
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
|
+
}
|
|
237
|
+
if (dslParts.length === 0) {
|
|
238
|
+
throw new Error(`No resources found in catalog at '${dir}'`);
|
|
239
|
+
}
|
|
240
|
+
const combined = dslParts.join("\n\n");
|
|
241
|
+
const grouped = groupDSLBlocks(combined);
|
|
242
|
+
const vizBlock = buildVisualizerBlock(grouped, "Full Catalog", [...RESOURCE_TYPES]);
|
|
243
|
+
const dsl = vizBlock ? `${grouped}
|
|
244
|
+
${vizBlock}` : grouped;
|
|
245
|
+
if (stdout) {
|
|
246
|
+
return dsl;
|
|
247
|
+
}
|
|
248
|
+
const filename = output || "catalog.ec";
|
|
249
|
+
const filepath = resolve(filename);
|
|
250
|
+
writeFileSync(filepath, dsl + "\n", "utf-8");
|
|
251
|
+
const lines = ["", ` Exported full catalog to ${filepath}`];
|
|
252
|
+
if (playground) {
|
|
253
|
+
const encoded = Buffer.from(dsl).toString("base64");
|
|
254
|
+
const playgroundUrl = `https://playground.eventcatalog.dev/?code=${encoded}`;
|
|
255
|
+
await open(playgroundUrl);
|
|
256
|
+
lines.push("", ` Opening in playground...`);
|
|
257
|
+
} else {
|
|
258
|
+
lines.push("", ` Tip: Use --playground to open in the playground`);
|
|
259
|
+
}
|
|
260
|
+
lines.push("");
|
|
261
|
+
return lines.join("\n");
|
|
262
|
+
}
|
|
263
|
+
async function exportAll(options) {
|
|
264
|
+
const { resource, hydrate = false, stdout = false, playground = false, output, dir } = options;
|
|
265
|
+
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
|
+
}
|
|
269
|
+
const plural = pluralize(type);
|
|
270
|
+
const sdk = createSDK3(dir);
|
|
271
|
+
const fetcher = getCollectionFetcher(sdk, type);
|
|
272
|
+
const allResources = await fetcher({ latestOnly: true }) || [];
|
|
273
|
+
if (allResources.length === 0) {
|
|
274
|
+
throw new Error(`No ${plural} found in catalog at '${dir}'`);
|
|
275
|
+
}
|
|
276
|
+
const rawDsl = await sdk.toDSL(allResources, { type, hydrate });
|
|
277
|
+
const grouped = groupDSLBlocks(rawDsl);
|
|
278
|
+
const vizBlock = buildVisualizerBlock(grouped, `All ${plural}`, type);
|
|
279
|
+
const dsl = vizBlock ? `${grouped}
|
|
280
|
+
${vizBlock}` : grouped;
|
|
281
|
+
if (stdout) {
|
|
282
|
+
return dsl;
|
|
283
|
+
}
|
|
284
|
+
const filename = output || `${plural}.ec`;
|
|
285
|
+
const filepath = resolve(filename);
|
|
286
|
+
writeFileSync(filepath, dsl + "\n", "utf-8");
|
|
287
|
+
const lines = ["", ` Exported ${allResources.length} ${plural} to ${filepath}`];
|
|
288
|
+
if (playground) {
|
|
289
|
+
const encoded = Buffer.from(dsl).toString("base64");
|
|
290
|
+
const playgroundUrl = `https://playground.eventcatalog.dev/?code=${encoded}`;
|
|
291
|
+
await open(playgroundUrl);
|
|
292
|
+
lines.push("", ` Opening in playground...`);
|
|
293
|
+
} else {
|
|
294
|
+
lines.push("", ` Tip: Use --playground to open in the playground`);
|
|
295
|
+
}
|
|
296
|
+
lines.push("");
|
|
297
|
+
return lines.join("\n");
|
|
298
|
+
}
|
|
299
|
+
async function exportResource(options) {
|
|
300
|
+
const { resource, id, version: version2, hydrate = false, stdout = false, playground = false, output, dir } = options;
|
|
301
|
+
if (!id) {
|
|
302
|
+
return exportAll(options);
|
|
303
|
+
}
|
|
304
|
+
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
|
+
}
|
|
308
|
+
const sdk = createSDK3(dir);
|
|
309
|
+
const fetcher = getResourceFetcher(sdk, type);
|
|
310
|
+
const data = await fetcher(id, version2);
|
|
311
|
+
if (!data) {
|
|
312
|
+
const versionStr = version2 ? `@${version2}` : " (latest)";
|
|
313
|
+
throw new Error(`${resource} '${id}${versionStr}' not found in catalog at '${dir}'`);
|
|
314
|
+
}
|
|
315
|
+
const rawDsl = await sdk.toDSL(data, { type, hydrate });
|
|
316
|
+
const grouped = hydrate ? groupDSLBlocks(rawDsl) : rawDsl;
|
|
317
|
+
const vizBlock = buildVisualizerBlock(grouped, `View of ${id}`, type);
|
|
318
|
+
const dsl = vizBlock ? `${grouped}
|
|
319
|
+
${vizBlock}` : grouped;
|
|
320
|
+
if (stdout) {
|
|
321
|
+
return dsl;
|
|
322
|
+
}
|
|
323
|
+
const filename = output || `${id}.ec`;
|
|
324
|
+
const filepath = resolve(filename);
|
|
325
|
+
writeFileSync(filepath, dsl + "\n", "utf-8");
|
|
326
|
+
const lines = ["", ` Exported ${type} '${id}' to ${filepath}`];
|
|
327
|
+
if (playground) {
|
|
328
|
+
const encoded = Buffer.from(dsl).toString("base64");
|
|
329
|
+
const playgroundUrl = `https://playground.eventcatalog.dev/?code=${encoded}`;
|
|
330
|
+
await open(playgroundUrl);
|
|
331
|
+
lines.push("", ` Opening in playground...`);
|
|
332
|
+
} else {
|
|
333
|
+
lines.push("", ` Tip: Use --playground to open in the playground`);
|
|
334
|
+
}
|
|
335
|
+
lines.push("");
|
|
336
|
+
return lines.join("\n");
|
|
337
|
+
}
|
|
338
|
+
|
|
121
339
|
// src/cli/index.ts
|
|
122
340
|
var version = "1.0.0";
|
|
123
341
|
try {
|
|
124
|
-
const packageJsonPath =
|
|
342
|
+
const packageJsonPath = resolve2(__dirname, "../../package.json");
|
|
125
343
|
const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
|
|
126
344
|
version = packageJson.version;
|
|
127
345
|
} catch {
|
|
@@ -137,6 +355,41 @@ program.command("list").description("List all available SDK functions").action((
|
|
|
137
355
|
process.exit(1);
|
|
138
356
|
}
|
|
139
357
|
});
|
|
358
|
+
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) => {
|
|
359
|
+
try {
|
|
360
|
+
const globalOpts = program.opts();
|
|
361
|
+
const dir = globalOpts.dir || ".";
|
|
362
|
+
if (opts.all) {
|
|
363
|
+
const result2 = await exportCatalog({
|
|
364
|
+
hydrate: opts.hydrate,
|
|
365
|
+
stdout: opts.stdout,
|
|
366
|
+
playground: opts.playground,
|
|
367
|
+
output: opts.output,
|
|
368
|
+
dir
|
|
369
|
+
});
|
|
370
|
+
console.log(result2);
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
if (!opts.resource) {
|
|
374
|
+
console.error("Either --all or --resource is required");
|
|
375
|
+
process.exit(1);
|
|
376
|
+
}
|
|
377
|
+
const result = await exportResource({
|
|
378
|
+
resource: opts.resource,
|
|
379
|
+
id: opts.id,
|
|
380
|
+
version: opts.version,
|
|
381
|
+
hydrate: opts.hydrate,
|
|
382
|
+
stdout: opts.stdout,
|
|
383
|
+
playground: opts.playground,
|
|
384
|
+
output: opts.output,
|
|
385
|
+
dir
|
|
386
|
+
});
|
|
387
|
+
console.log(result);
|
|
388
|
+
} catch (error) {
|
|
389
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
390
|
+
process.exit(1);
|
|
391
|
+
}
|
|
392
|
+
});
|
|
140
393
|
program.arguments("<function> [args...]").action(async (functionName, args) => {
|
|
141
394
|
try {
|
|
142
395
|
const options = program.opts();
|