@eventcatalog/sdk 2.13.2 → 2.14.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/index.d.mts +74 -36
- package/dist/index.d.ts +74 -36
- package/dist/index.js +572 -31
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +572 -31
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,50 +1,533 @@
|
|
|
1
1
|
// src/index.ts
|
|
2
2
|
import { join as join18 } from "path";
|
|
3
3
|
|
|
4
|
+
// src/dsl/utils.ts
|
|
5
|
+
import { globSync } from "glob";
|
|
6
|
+
function serializeBaseFields(resource, indent = " ") {
|
|
7
|
+
const lines = [];
|
|
8
|
+
if (resource.version) {
|
|
9
|
+
lines.push(`${indent}version ${resource.version}`);
|
|
10
|
+
}
|
|
11
|
+
if (resource.name) {
|
|
12
|
+
lines.push(`${indent}name "${resource.name}"`);
|
|
13
|
+
}
|
|
14
|
+
if (resource.summary) {
|
|
15
|
+
lines.push(`${indent}summary "${resource.summary.trim()}"`);
|
|
16
|
+
}
|
|
17
|
+
if (resource.owners && resource.owners.length > 0) {
|
|
18
|
+
for (const owner of resource.owners) {
|
|
19
|
+
lines.push(`${indent}owner ${owner}`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
if (resource.deprecated === true) {
|
|
23
|
+
lines.push(`${indent}deprecated true`);
|
|
24
|
+
}
|
|
25
|
+
if (resource.draft === true) {
|
|
26
|
+
lines.push(`${indent}draft true`);
|
|
27
|
+
}
|
|
28
|
+
return lines.join("\n");
|
|
29
|
+
}
|
|
30
|
+
function buildMessageTypeIndex(catalogDir) {
|
|
31
|
+
const index = /* @__PURE__ */ new Map();
|
|
32
|
+
const types = ["events", "commands", "queries"];
|
|
33
|
+
const typeMap = { events: "event", commands: "command", queries: "query" };
|
|
34
|
+
for (const type of types) {
|
|
35
|
+
const matches = globSync(`**/${type}/*/index.{md,mdx}`, { cwd: catalogDir });
|
|
36
|
+
for (const match of matches) {
|
|
37
|
+
const parts = match.replace(/\\/g, "/").split("/");
|
|
38
|
+
const typeIdx = parts.lastIndexOf(type);
|
|
39
|
+
if (typeIdx !== -1 && typeIdx + 1 < parts.length) {
|
|
40
|
+
const id = parts[typeIdx + 1];
|
|
41
|
+
if (!index.has(id)) index.set(id, typeMap[type]);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return index;
|
|
46
|
+
}
|
|
47
|
+
function resolveMessageType(catalogDirOrIndex, id) {
|
|
48
|
+
if (typeof catalogDirOrIndex !== "string") {
|
|
49
|
+
return catalogDirOrIndex.get(id);
|
|
50
|
+
}
|
|
51
|
+
if (globSync(`**/events/${id}/index.{md,mdx}`, { cwd: catalogDirOrIndex }).length > 0) return "event";
|
|
52
|
+
if (globSync(`**/commands/${id}/index.{md,mdx}`, { cwd: catalogDirOrIndex }).length > 0) return "command";
|
|
53
|
+
if (globSync(`**/queries/${id}/index.{md,mdx}`, { cwd: catalogDirOrIndex }).length > 0) return "query";
|
|
54
|
+
return void 0;
|
|
55
|
+
}
|
|
56
|
+
function serializeChannelRef(channel) {
|
|
57
|
+
let ref = channel.id;
|
|
58
|
+
if (channel.version) ref += `@${channel.version}`;
|
|
59
|
+
return ref;
|
|
60
|
+
}
|
|
61
|
+
function serializeMessagePointers(items, direction, catalogDirOrIndex, indent = " ") {
|
|
62
|
+
const lines = [];
|
|
63
|
+
for (const item of items) {
|
|
64
|
+
const msgType = resolveMessageType(catalogDirOrIndex, item.id);
|
|
65
|
+
if (!msgType) continue;
|
|
66
|
+
let ref = `${item.id}`;
|
|
67
|
+
if (item.version) ref += `@${item.version}`;
|
|
68
|
+
const channels = direction === "sends" ? item.to : item.from;
|
|
69
|
+
const channelKeyword = direction === "sends" ? "to" : "from";
|
|
70
|
+
if (channels && channels.length === 1) {
|
|
71
|
+
lines.push(`${indent}${direction} ${msgType} ${ref} ${channelKeyword} ${serializeChannelRef(channels[0])}`);
|
|
72
|
+
} else if (channels && channels.length > 1) {
|
|
73
|
+
const channelRefs = channels.map(serializeChannelRef).join(", ");
|
|
74
|
+
lines.push(`${indent}${direction} ${msgType} ${ref} ${channelKeyword} ${channelRefs}`);
|
|
75
|
+
} else {
|
|
76
|
+
lines.push(`${indent}${direction} ${msgType} ${ref}`);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
return lines.join("\n");
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// src/dsl/message.ts
|
|
83
|
+
function messageToDSL(resource, type) {
|
|
84
|
+
const body = serializeBaseFields(resource);
|
|
85
|
+
if (!body) {
|
|
86
|
+
return `${type} ${resource.id}`;
|
|
87
|
+
}
|
|
88
|
+
return `${type} ${resource.id} {
|
|
89
|
+
${body}
|
|
90
|
+
}`;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// src/dsl/service.ts
|
|
94
|
+
async function serviceToDSL(resource, options, getMessageFn) {
|
|
95
|
+
const { catalogDir, hydrate = false, _seen = /* @__PURE__ */ new Set() } = options;
|
|
96
|
+
const msgIndex = options._msgIndex || buildMessageTypeIndex(catalogDir);
|
|
97
|
+
const parts = [];
|
|
98
|
+
if (hydrate && getMessageFn) {
|
|
99
|
+
const allMessages = [...resource.sends || [], ...resource.receives || []];
|
|
100
|
+
for (const msg of allMessages) {
|
|
101
|
+
const key = `${msg.id}@${msg.version || "latest"}`;
|
|
102
|
+
if (_seen.has(key)) continue;
|
|
103
|
+
_seen.add(key);
|
|
104
|
+
const msgType = resolveMessageType(msgIndex, msg.id);
|
|
105
|
+
if (!msgType) continue;
|
|
106
|
+
const msgResource = await getMessageFn(msg.id, msg.version);
|
|
107
|
+
if (msgResource) {
|
|
108
|
+
parts.push(messageToDSL(msgResource, msgType));
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
const lines = [];
|
|
113
|
+
const baseFields = serializeBaseFields(resource);
|
|
114
|
+
if (baseFields) lines.push(baseFields);
|
|
115
|
+
if (resource.sends && resource.sends.length > 0) {
|
|
116
|
+
const sendsStr = serializeMessagePointers(resource.sends, "sends", msgIndex);
|
|
117
|
+
if (sendsStr) lines.push(sendsStr);
|
|
118
|
+
}
|
|
119
|
+
if (resource.receives && resource.receives.length > 0) {
|
|
120
|
+
const recvStr = serializeMessagePointers(resource.receives, "receives", msgIndex);
|
|
121
|
+
if (recvStr) lines.push(recvStr);
|
|
122
|
+
}
|
|
123
|
+
if (resource.writesTo && resource.writesTo.length > 0) {
|
|
124
|
+
for (const container of resource.writesTo) {
|
|
125
|
+
let ref = container.id;
|
|
126
|
+
if (container.version) ref += `@${container.version}`;
|
|
127
|
+
lines.push(` writes-to container ${ref}`);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (resource.readsFrom && resource.readsFrom.length > 0) {
|
|
131
|
+
for (const container of resource.readsFrom) {
|
|
132
|
+
let ref = container.id;
|
|
133
|
+
if (container.version) ref += `@${container.version}`;
|
|
134
|
+
lines.push(` reads-from container ${ref}`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
const body = lines.join("\n");
|
|
138
|
+
parts.push(`service ${resource.id} {
|
|
139
|
+
${body}
|
|
140
|
+
}`);
|
|
141
|
+
return parts.join("\n\n");
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// src/dsl/channel.ts
|
|
145
|
+
function channelToDSL(resource) {
|
|
146
|
+
const lines = [];
|
|
147
|
+
if (resource.version) {
|
|
148
|
+
lines.push(` version ${resource.version}`);
|
|
149
|
+
}
|
|
150
|
+
if (resource.name) {
|
|
151
|
+
lines.push(` name "${resource.name}"`);
|
|
152
|
+
}
|
|
153
|
+
if (resource.address) {
|
|
154
|
+
lines.push(` address "${resource.address}"`);
|
|
155
|
+
}
|
|
156
|
+
if (resource.protocols && resource.protocols.length > 0) {
|
|
157
|
+
for (const protocol of resource.protocols) {
|
|
158
|
+
lines.push(` protocol "${protocol}"`);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
if (resource.summary) {
|
|
162
|
+
lines.push(` summary "${resource.summary.trim()}"`);
|
|
163
|
+
}
|
|
164
|
+
if (!lines.length) {
|
|
165
|
+
return `channel ${resource.id}`;
|
|
166
|
+
}
|
|
167
|
+
return `channel ${resource.id} {
|
|
168
|
+
${lines.join("\n")}
|
|
169
|
+
}`;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
// src/dsl/owner.ts
|
|
173
|
+
function teamToDSL(team) {
|
|
174
|
+
const lines = [];
|
|
175
|
+
if (team.name) lines.push(` name "${team.name}"`);
|
|
176
|
+
if (team.avatarUrl) lines.push(` avatar "${team.avatarUrl}"`);
|
|
177
|
+
if (team.role) lines.push(` role "${team.role}"`);
|
|
178
|
+
if (team.summary) lines.push(` summary "${team.summary}"`);
|
|
179
|
+
if (team.email) lines.push(` email "${team.email}"`);
|
|
180
|
+
if (team.slackDirectMessageUrl) lines.push(` slack "${team.slackDirectMessageUrl}"`);
|
|
181
|
+
return `team ${team.id} {
|
|
182
|
+
${lines.join("\n")}
|
|
183
|
+
}`;
|
|
184
|
+
}
|
|
185
|
+
function userToDSL(user) {
|
|
186
|
+
const lines = [];
|
|
187
|
+
if (user.name) lines.push(` name "${user.name}"`);
|
|
188
|
+
if (user.avatarUrl) lines.push(` avatar "${user.avatarUrl}"`);
|
|
189
|
+
if (user.role) lines.push(` role "${user.role}"`);
|
|
190
|
+
if (user.email) lines.push(` email "${user.email}"`);
|
|
191
|
+
if (user.slackDirectMessageUrl) lines.push(` slack "${user.slackDirectMessageUrl}"`);
|
|
192
|
+
return `user ${user.id} {
|
|
193
|
+
${lines.join("\n")}
|
|
194
|
+
}`;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
// src/dsl/domain.ts
|
|
198
|
+
async function hydrateOwners(owners, resolvers, seen, parts) {
|
|
199
|
+
if (!owners || !resolvers.getTeam || !resolvers.getUser) return;
|
|
200
|
+
for (const ownerId of owners) {
|
|
201
|
+
const key = `owner:${ownerId}`;
|
|
202
|
+
if (seen.has(key)) continue;
|
|
203
|
+
seen.add(key);
|
|
204
|
+
const team = await resolvers.getTeam(ownerId);
|
|
205
|
+
if (team) {
|
|
206
|
+
parts.push(teamToDSL(team));
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
const user = await resolvers.getUser(ownerId);
|
|
210
|
+
if (user) {
|
|
211
|
+
parts.push(userToDSL(user));
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
async function hydrateChannelsFromMessages(messages, resolvers, seen, parts) {
|
|
216
|
+
if (!resolvers.getChannel) return;
|
|
217
|
+
for (const msg of messages) {
|
|
218
|
+
const channels = msg.to || msg.from;
|
|
219
|
+
if (!channels) continue;
|
|
220
|
+
for (const ch of channels) {
|
|
221
|
+
const key = `channel:${ch.id}@${ch.version || "latest"}`;
|
|
222
|
+
if (seen.has(key)) continue;
|
|
223
|
+
seen.add(key);
|
|
224
|
+
const channel = await resolvers.getChannel(ch.id, ch.version);
|
|
225
|
+
if (channel) {
|
|
226
|
+
parts.push(channelToDSL(channel));
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
async function buildDomainBody(resource, options, resolvers, keyword) {
|
|
232
|
+
const { catalogDir, hydrate = false, _seen = /* @__PURE__ */ new Set() } = options;
|
|
233
|
+
const msgIndex = options._msgIndex || buildMessageTypeIndex(catalogDir);
|
|
234
|
+
const topLevelParts = [];
|
|
235
|
+
if (hydrate && resolvers) {
|
|
236
|
+
if (resource.services && resource.services.length > 0 && resolvers.getService) {
|
|
237
|
+
for (const svcRef of resource.services) {
|
|
238
|
+
const svcKey = `service:${svcRef.id}@${svcRef.version || "latest"}`;
|
|
239
|
+
if (_seen.has(svcKey)) continue;
|
|
240
|
+
_seen.add(svcKey);
|
|
241
|
+
const svc = await resolvers.getService(svcRef.id, svcRef.version);
|
|
242
|
+
if (svc) {
|
|
243
|
+
await hydrateOwners(svc.owners, resolvers, _seen, topLevelParts);
|
|
244
|
+
const svcMessages = [...svc.sends || [], ...svc.receives || []];
|
|
245
|
+
await hydrateChannelsFromMessages(svcMessages, resolvers, _seen, topLevelParts);
|
|
246
|
+
const svcDsl = await serviceToDSL(svc, { catalogDir, hydrate: true, _seen, _msgIndex: msgIndex }, resolvers.getMessage);
|
|
247
|
+
topLevelParts.push(svcDsl);
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
const domainMessages = [...resource.sends || [], ...resource.receives || []];
|
|
252
|
+
await hydrateChannelsFromMessages(domainMessages, resolvers, _seen, topLevelParts);
|
|
253
|
+
if (resolvers.getMessage) {
|
|
254
|
+
for (const msg of domainMessages) {
|
|
255
|
+
const key = `${msg.id}@${msg.version || "latest"}`;
|
|
256
|
+
if (_seen.has(key)) continue;
|
|
257
|
+
_seen.add(key);
|
|
258
|
+
const msgType = resolveMessageType(msgIndex, msg.id);
|
|
259
|
+
if (!msgType) continue;
|
|
260
|
+
const msgResource = await resolvers.getMessage(msg.id, msg.version);
|
|
261
|
+
if (msgResource) {
|
|
262
|
+
topLevelParts.push(messageToDSL(msgResource, msgType));
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
const lines = [];
|
|
268
|
+
const baseFields = serializeBaseFields(resource);
|
|
269
|
+
if (baseFields) lines.push(baseFields);
|
|
270
|
+
if (resource.services && resource.services.length > 0) {
|
|
271
|
+
for (const svc of resource.services) {
|
|
272
|
+
let ref = svc.id;
|
|
273
|
+
if (svc.version) ref += `@${svc.version}`;
|
|
274
|
+
lines.push(` service ${ref}`);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
if (resource.sends && resource.sends.length > 0) {
|
|
278
|
+
const sendsStr = serializeMessagePointers(resource.sends, "sends", msgIndex);
|
|
279
|
+
if (sendsStr) lines.push(sendsStr);
|
|
280
|
+
}
|
|
281
|
+
if (resource.receives && resource.receives.length > 0) {
|
|
282
|
+
const recvStr = serializeMessagePointers(resource.receives, "receives", msgIndex);
|
|
283
|
+
if (recvStr) lines.push(recvStr);
|
|
284
|
+
}
|
|
285
|
+
if (resource.domains && resource.domains.length > 0) {
|
|
286
|
+
if (hydrate && resolvers?.getDomain) {
|
|
287
|
+
for (const subRef of resource.domains) {
|
|
288
|
+
const subKey = `domain:${subRef.id}@${subRef.version || "latest"}`;
|
|
289
|
+
if (_seen.has(subKey)) continue;
|
|
290
|
+
_seen.add(subKey);
|
|
291
|
+
const subDomain = await resolvers.getDomain(subRef.id, subRef.version);
|
|
292
|
+
if (subDomain) {
|
|
293
|
+
await hydrateOwners(subDomain.owners, resolvers, _seen, topLevelParts);
|
|
294
|
+
const sub = await buildDomainBody(
|
|
295
|
+
subDomain,
|
|
296
|
+
{ catalogDir, hydrate, _seen, _msgIndex: msgIndex },
|
|
297
|
+
resolvers,
|
|
298
|
+
"subdomain"
|
|
299
|
+
);
|
|
300
|
+
topLevelParts.push(...sub.topLevelParts);
|
|
301
|
+
const indented = sub.block.split("\n").map((line) => ` ${line}`).join("\n");
|
|
302
|
+
lines.push(indented);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
} else {
|
|
306
|
+
for (const sub of resource.domains) {
|
|
307
|
+
let ref = sub.id;
|
|
308
|
+
if (sub.version) ref += `@${sub.version}`;
|
|
309
|
+
lines.push(` subdomain ${ref}`);
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
const body = lines.join("\n");
|
|
314
|
+
const block = `${keyword} ${resource.id} {
|
|
315
|
+
${body}
|
|
316
|
+
}`;
|
|
317
|
+
return { topLevelParts, block };
|
|
318
|
+
}
|
|
319
|
+
async function domainToDSL(resource, options, resolvers) {
|
|
320
|
+
const { catalogDir, hydrate = false, _seen = /* @__PURE__ */ new Set() } = options;
|
|
321
|
+
const msgIndex = options._msgIndex || buildMessageTypeIndex(catalogDir);
|
|
322
|
+
const result = await buildDomainBody(resource, { catalogDir, hydrate, _seen, _msgIndex: msgIndex }, resolvers, "domain");
|
|
323
|
+
const parts = [...result.topLevelParts, result.block];
|
|
324
|
+
return parts.join("\n\n");
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
// src/dsl/index.ts
|
|
328
|
+
function getMessage(resolvers, msgIndex) {
|
|
329
|
+
return async (id, version) => {
|
|
330
|
+
const msgType = resolveMessageType(msgIndex, id);
|
|
331
|
+
if (!msgType) return void 0;
|
|
332
|
+
switch (msgType) {
|
|
333
|
+
case "event":
|
|
334
|
+
return resolvers.getEvent(id, version);
|
|
335
|
+
case "command":
|
|
336
|
+
return resolvers.getCommand(id, version);
|
|
337
|
+
case "query":
|
|
338
|
+
return resolvers.getQuery(id, version);
|
|
339
|
+
}
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
async function hydrateChannels(resource, resolvers, seen, parts) {
|
|
343
|
+
const allMessages = [...resource.sends || [], ...resource.receives || []];
|
|
344
|
+
for (const msg of allMessages) {
|
|
345
|
+
const channels = "to" in msg ? msg.to : "from" in msg ? msg.from : void 0;
|
|
346
|
+
if (!channels) continue;
|
|
347
|
+
for (const ch of channels) {
|
|
348
|
+
const key = `channel:${ch.id}@${ch.version || "latest"}`;
|
|
349
|
+
if (seen.has(key)) continue;
|
|
350
|
+
seen.add(key);
|
|
351
|
+
const channel = await resolvers.getChannel(ch.id, ch.version);
|
|
352
|
+
if (channel) {
|
|
353
|
+
parts.push(channelToDSL(channel));
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
async function hydrateOwners2(owners, resolvers, seen, parts) {
|
|
359
|
+
if (!owners) return;
|
|
360
|
+
for (const ownerId of owners) {
|
|
361
|
+
const key = `owner:${ownerId}`;
|
|
362
|
+
if (seen.has(key)) continue;
|
|
363
|
+
seen.add(key);
|
|
364
|
+
const team = await resolvers.getTeam(ownerId);
|
|
365
|
+
if (team) {
|
|
366
|
+
parts.push(teamToDSL(team));
|
|
367
|
+
continue;
|
|
368
|
+
}
|
|
369
|
+
const user = await resolvers.getUser(ownerId);
|
|
370
|
+
if (user) {
|
|
371
|
+
parts.push(userToDSL(user));
|
|
372
|
+
}
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
var toDSL = (catalogDir, resolvers) => async (resource, options) => {
|
|
376
|
+
const resources = Array.isArray(resource) ? resource : [resource];
|
|
377
|
+
const seen = /* @__PURE__ */ new Set();
|
|
378
|
+
const parts = [];
|
|
379
|
+
const msgIndex = buildMessageTypeIndex(catalogDir);
|
|
380
|
+
for (const res of resources) {
|
|
381
|
+
const key = `${options.type}:${res.id}@${res.version || "latest"}`;
|
|
382
|
+
if (seen.has(key)) continue;
|
|
383
|
+
seen.add(key);
|
|
384
|
+
switch (options.type) {
|
|
385
|
+
case "event":
|
|
386
|
+
case "command":
|
|
387
|
+
case "query":
|
|
388
|
+
if (options.hydrate) {
|
|
389
|
+
await hydrateOwners2(res.owners, resolvers, seen, parts);
|
|
390
|
+
}
|
|
391
|
+
parts.push(messageToDSL(res, options.type));
|
|
392
|
+
break;
|
|
393
|
+
case "service":
|
|
394
|
+
if (options.hydrate) {
|
|
395
|
+
await hydrateOwners2(res.owners, resolvers, seen, parts);
|
|
396
|
+
await hydrateChannels(res, resolvers, seen, parts);
|
|
397
|
+
}
|
|
398
|
+
parts.push(
|
|
399
|
+
await serviceToDSL(
|
|
400
|
+
res,
|
|
401
|
+
{ catalogDir, hydrate: options.hydrate, _seen: seen, _msgIndex: msgIndex },
|
|
402
|
+
getMessage(resolvers, msgIndex)
|
|
403
|
+
)
|
|
404
|
+
);
|
|
405
|
+
break;
|
|
406
|
+
case "domain":
|
|
407
|
+
if (options.hydrate) {
|
|
408
|
+
await hydrateOwners2(res.owners, resolvers, seen, parts);
|
|
409
|
+
}
|
|
410
|
+
parts.push(
|
|
411
|
+
await domainToDSL(
|
|
412
|
+
res,
|
|
413
|
+
{ catalogDir, hydrate: options.hydrate, _seen: seen, _msgIndex: msgIndex },
|
|
414
|
+
{
|
|
415
|
+
getService: resolvers.getService,
|
|
416
|
+
getDomain: resolvers.getDomain,
|
|
417
|
+
getMessage: getMessage(resolvers, msgIndex),
|
|
418
|
+
getChannel: resolvers.getChannel,
|
|
419
|
+
getTeam: resolvers.getTeam,
|
|
420
|
+
getUser: resolvers.getUser
|
|
421
|
+
}
|
|
422
|
+
)
|
|
423
|
+
);
|
|
424
|
+
break;
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
return parts.join("\n\n");
|
|
428
|
+
};
|
|
429
|
+
|
|
4
430
|
// src/events.ts
|
|
5
431
|
import fs2 from "fs/promises";
|
|
6
432
|
import { join as join3 } from "path";
|
|
7
433
|
|
|
8
434
|
// src/internal/utils.ts
|
|
9
|
-
import { globSync } from "glob";
|
|
435
|
+
import { globSync as globSync2 } from "glob";
|
|
10
436
|
import fsSync from "fs";
|
|
11
437
|
import { copy } from "fs-extra";
|
|
12
438
|
import { join, dirname, normalize, resolve, relative } from "path";
|
|
13
439
|
import matter from "gray-matter";
|
|
14
440
|
import { satisfies, validRange } from "semver";
|
|
441
|
+
var _fileIndexCache = null;
|
|
442
|
+
var _fileIndexCatalogDir = null;
|
|
443
|
+
var _matterCache = null;
|
|
444
|
+
var _fileIndexMtimeMs = 0;
|
|
445
|
+
function buildFileCache(catalogDir) {
|
|
446
|
+
const files = globSync2("**/index.{md,mdx}", {
|
|
447
|
+
cwd: catalogDir,
|
|
448
|
+
ignore: ["node_modules/**"],
|
|
449
|
+
absolute: true,
|
|
450
|
+
nodir: true
|
|
451
|
+
}).map(normalize);
|
|
452
|
+
const index = /* @__PURE__ */ new Map();
|
|
453
|
+
const matterResults = /* @__PURE__ */ new Map();
|
|
454
|
+
for (const file of files) {
|
|
455
|
+
const content = fsSync.readFileSync(file, "utf-8");
|
|
456
|
+
const parsed = matter(content);
|
|
457
|
+
matterResults.set(file, parsed);
|
|
458
|
+
const id = parsed.data.id;
|
|
459
|
+
if (!id) continue;
|
|
460
|
+
const version = parsed.data.version || "";
|
|
461
|
+
const isVersioned = file.includes("versioned");
|
|
462
|
+
const entry = { path: file, id, version: String(version), isVersioned };
|
|
463
|
+
const existing = index.get(id);
|
|
464
|
+
if (existing) {
|
|
465
|
+
existing.push(entry);
|
|
466
|
+
} else {
|
|
467
|
+
index.set(id, [entry]);
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
_fileIndexCache = index;
|
|
471
|
+
_fileIndexCatalogDir = catalogDir;
|
|
472
|
+
_matterCache = matterResults;
|
|
473
|
+
try {
|
|
474
|
+
_fileIndexMtimeMs = fsSync.statSync(catalogDir).mtimeMs;
|
|
475
|
+
} catch {
|
|
476
|
+
_fileIndexMtimeMs = 0;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
function ensureFileCache(catalogDir) {
|
|
480
|
+
if (!_fileIndexCache || _fileIndexCatalogDir !== catalogDir) {
|
|
481
|
+
buildFileCache(catalogDir);
|
|
482
|
+
return;
|
|
483
|
+
}
|
|
484
|
+
try {
|
|
485
|
+
const currentMtime = fsSync.statSync(catalogDir).mtimeMs;
|
|
486
|
+
if (currentMtime !== _fileIndexMtimeMs) {
|
|
487
|
+
buildFileCache(catalogDir);
|
|
488
|
+
}
|
|
489
|
+
} catch {
|
|
490
|
+
buildFileCache(catalogDir);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
function invalidateFileCache() {
|
|
494
|
+
_fileIndexCache = null;
|
|
495
|
+
_fileIndexCatalogDir = null;
|
|
496
|
+
_matterCache = null;
|
|
497
|
+
}
|
|
498
|
+
function cachedMatterRead(filePath) {
|
|
499
|
+
if (_matterCache) {
|
|
500
|
+
const cached = _matterCache.get(filePath);
|
|
501
|
+
if (cached) return cached;
|
|
502
|
+
}
|
|
503
|
+
return matter.read(filePath);
|
|
504
|
+
}
|
|
15
505
|
var versionExists = async (catalogDir, id, version) => {
|
|
16
|
-
|
|
17
|
-
const
|
|
18
|
-
|
|
506
|
+
ensureFileCache(catalogDir);
|
|
507
|
+
const entries = _fileIndexCache.get(id);
|
|
508
|
+
if (!entries) return false;
|
|
509
|
+
return entries.some((e) => e.version === version);
|
|
19
510
|
};
|
|
20
511
|
var findFileById = async (catalogDir, id, version) => {
|
|
21
|
-
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
const parsedFiles = matchedFiles.map((path6) => {
|
|
28
|
-
const { data } = matter.read(path6);
|
|
29
|
-
return { ...data, path: path6 };
|
|
30
|
-
});
|
|
31
|
-
if (version === "latest") {
|
|
32
|
-
return latestVersion;
|
|
33
|
-
}
|
|
34
|
-
const exactMatch = parsedFiles.find((c) => c.version === version);
|
|
35
|
-
if (exactMatch) {
|
|
36
|
-
return exactMatch.path;
|
|
512
|
+
ensureFileCache(catalogDir);
|
|
513
|
+
const entries = _fileIndexCache.get(id);
|
|
514
|
+
if (!entries || entries.length === 0) return void 0;
|
|
515
|
+
const latestEntry = entries.find((e) => !e.isVersioned);
|
|
516
|
+
if (!version || version === "latest") {
|
|
517
|
+
return latestEntry?.path;
|
|
37
518
|
}
|
|
519
|
+
const exactMatch = entries.find((e) => e.version === version);
|
|
520
|
+
if (exactMatch) return exactMatch.path;
|
|
38
521
|
const semverRange = validRange(version);
|
|
39
522
|
if (semverRange) {
|
|
40
|
-
const match =
|
|
523
|
+
const match = entries.find((e) => {
|
|
41
524
|
try {
|
|
42
|
-
return satisfies(
|
|
43
|
-
} catch
|
|
525
|
+
return satisfies(e.version, semverRange);
|
|
526
|
+
} catch {
|
|
44
527
|
return false;
|
|
45
528
|
}
|
|
46
529
|
});
|
|
47
|
-
return match
|
|
530
|
+
return match?.path;
|
|
48
531
|
}
|
|
49
532
|
return void 0;
|
|
50
533
|
};
|
|
@@ -57,7 +540,7 @@ var getFiles = async (pattern, ignore = "") => {
|
|
|
57
540
|
let relativePattern = relative(absoluteBaseDir, normalizedInputPattern);
|
|
58
541
|
relativePattern = relativePattern.replace(/\\/g, "/");
|
|
59
542
|
const ignoreList = Array.isArray(ignore) ? ignore : [ignore];
|
|
60
|
-
const files =
|
|
543
|
+
const files = globSync2(relativePattern, {
|
|
61
544
|
cwd: absoluteBaseDir,
|
|
62
545
|
ignore: ["node_modules/**", ...ignoreList],
|
|
63
546
|
absolute: true,
|
|
@@ -160,6 +643,7 @@ var versionResource = async (catalogDir, id) => {
|
|
|
160
643
|
})
|
|
161
644
|
);
|
|
162
645
|
});
|
|
646
|
+
invalidateFileCache();
|
|
163
647
|
};
|
|
164
648
|
var writeResource = async (catalogDir, resource, options = {
|
|
165
649
|
path: "",
|
|
@@ -199,6 +683,7 @@ var writeResource = async (catalogDir, resource, options = {
|
|
|
199
683
|
}
|
|
200
684
|
const document = matter2.stringify(markdown.trim(), frontmatter);
|
|
201
685
|
fsSync2.writeFileSync(lockPath, document);
|
|
686
|
+
invalidateFileCache();
|
|
202
687
|
} finally {
|
|
203
688
|
await unlock(lockPath).catch(() => {
|
|
204
689
|
});
|
|
@@ -208,7 +693,7 @@ var getResource = async (catalogDir, id, version, options, filePath) => {
|
|
|
208
693
|
const attachSchema = options?.attachSchema || false;
|
|
209
694
|
const file = filePath || (id ? await findFileById(catalogDir, id, version) : void 0);
|
|
210
695
|
if (!file || !fsSync2.existsSync(file)) return;
|
|
211
|
-
const { data, content } =
|
|
696
|
+
const { data, content } = cachedMatterRead(file);
|
|
212
697
|
if (attachSchema && data?.schemaPath) {
|
|
213
698
|
const resourceDirectory = dirname2(file);
|
|
214
699
|
const pathToSchema = join2(resourceDirectory, data.schemaPath);
|
|
@@ -259,7 +744,7 @@ var getResources = async (catalogDir, {
|
|
|
259
744
|
const files = await getFiles(filePattern, [ignoreList, ...ignore]);
|
|
260
745
|
if (files.length === 0) return;
|
|
261
746
|
return files.map((file) => {
|
|
262
|
-
const { data, content } =
|
|
747
|
+
const { data, content } = cachedMatterRead(file);
|
|
263
748
|
if (attachSchema && data?.schemaPath) {
|
|
264
749
|
const resourceDirectory = dirname2(file);
|
|
265
750
|
const pathToSchema = join2(resourceDirectory, data.schemaPath);
|
|
@@ -300,6 +785,7 @@ var rmResourceById = async (catalogDir, id, version, options) => {
|
|
|
300
785
|
})
|
|
301
786
|
);
|
|
302
787
|
}
|
|
788
|
+
invalidateFileCache();
|
|
303
789
|
};
|
|
304
790
|
var waitForFileRemoval = async (path6, maxRetries = 50, delay = 10) => {
|
|
305
791
|
for (let i = 0; i < maxRetries; i++) {
|
|
@@ -365,6 +851,7 @@ var writeEventToService = (directory) => async (event, service, options = { path
|
|
|
365
851
|
};
|
|
366
852
|
var rmEvent = (directory) => async (path6) => {
|
|
367
853
|
await fs2.rm(join3(directory, path6), { recursive: true });
|
|
854
|
+
invalidateFileCache();
|
|
368
855
|
};
|
|
369
856
|
var rmEventById = (directory) => async (id, version, persistFiles) => {
|
|
370
857
|
await rmResourceById(directory, id, version, { type: "event", persistFiles });
|
|
@@ -401,6 +888,7 @@ var writeCommandToService = (directory) => async (command, service, options = {
|
|
|
401
888
|
};
|
|
402
889
|
var rmCommand = (directory) => async (path6) => {
|
|
403
890
|
await fs3.rm(join4(directory, path6), { recursive: true });
|
|
891
|
+
invalidateFileCache();
|
|
404
892
|
};
|
|
405
893
|
var rmCommandById = (directory) => async (id, version, persistFiles) => rmResourceById(directory, id, version, { type: "command", persistFiles });
|
|
406
894
|
var versionCommand = (directory) => async (id) => versionResource(directory, id);
|
|
@@ -435,6 +923,7 @@ var writeQueryToService = (directory) => async (query, service, options = { path
|
|
|
435
923
|
};
|
|
436
924
|
var rmQuery = (directory) => async (path6) => {
|
|
437
925
|
await fs4.rm(join5(directory, path6), { recursive: true });
|
|
926
|
+
invalidateFileCache();
|
|
438
927
|
};
|
|
439
928
|
var rmQueryById = (directory) => async (id, version, persistFiles) => {
|
|
440
929
|
await rmResourceById(directory, id, version, { type: "query", persistFiles });
|
|
@@ -459,7 +948,18 @@ var getServiceByPath = (directory) => async (path6) => {
|
|
|
459
948
|
};
|
|
460
949
|
var getServices = (directory) => async (options) => getResources(directory, {
|
|
461
950
|
type: "services",
|
|
462
|
-
ignore: [
|
|
951
|
+
ignore: [
|
|
952
|
+
"**/events/**",
|
|
953
|
+
"**/commands/**",
|
|
954
|
+
"**/queries/**",
|
|
955
|
+
"**/entities/**",
|
|
956
|
+
"**/channels/**",
|
|
957
|
+
"**/containers/**",
|
|
958
|
+
"**/data-products/**",
|
|
959
|
+
"**/data-stores/**",
|
|
960
|
+
"**/flows/**",
|
|
961
|
+
"**/subdomains/**/entities/**"
|
|
962
|
+
],
|
|
463
963
|
...options
|
|
464
964
|
});
|
|
465
965
|
var writeService = (directory) => async (service, options = {
|
|
@@ -489,6 +989,7 @@ var writeServiceToDomain = (directory) => async (service, domain, options = { pa
|
|
|
489
989
|
var versionService = (directory) => async (id) => versionResource(directory, id);
|
|
490
990
|
var rmService = (directory) => async (path6) => {
|
|
491
991
|
await fs5.rm(join6(directory, path6), { recursive: true });
|
|
992
|
+
invalidateFileCache();
|
|
492
993
|
};
|
|
493
994
|
var rmServiceById = (directory) => async (id, version, persistFiles) => {
|
|
494
995
|
await rmResourceById(directory, id, version, { type: "service", persistFiles });
|
|
@@ -665,6 +1166,7 @@ var writeDomain = (directory) => async (domain, options = {
|
|
|
665
1166
|
var versionDomain = (directory) => async (id) => versionResource(directory, id);
|
|
666
1167
|
var rmDomain = (directory) => async (path6) => {
|
|
667
1168
|
await fs6.rm(join7(directory, path6), { recursive: true });
|
|
1169
|
+
invalidateFileCache();
|
|
668
1170
|
};
|
|
669
1171
|
var rmDomainById = (directory) => async (id, version, persistFiles) => rmResourceById(directory, id, version, { type: "domain", persistFiles });
|
|
670
1172
|
var addFileToDomain = (directory) => async (id, file, version) => addFileToResource(directory, id, file, version);
|
|
@@ -796,6 +1298,7 @@ var getChannels = (directory) => async (options) => getResources(directory, { ty
|
|
|
796
1298
|
var writeChannel = (directory) => async (channel, options = { path: "" }) => writeResource(directory, { ...channel }, { ...options, type: "channel" });
|
|
797
1299
|
var rmChannel = (directory) => async (path6) => {
|
|
798
1300
|
await fs7.rm(join8(directory, path6), { recursive: true });
|
|
1301
|
+
invalidateFileCache();
|
|
799
1302
|
};
|
|
800
1303
|
var rmChannelById = (directory) => async (id, version, persistFiles) => rmResourceById(directory, id, version, { type: "channel", persistFiles });
|
|
801
1304
|
var versionChannel = (directory) => async (id) => versionResource(directory, id);
|
|
@@ -822,8 +1325,8 @@ var addMessageToChannel = (directory, collection) => async (id, _message, versio
|
|
|
822
1325
|
writeMessage: writeQuery
|
|
823
1326
|
}
|
|
824
1327
|
};
|
|
825
|
-
const { getMessage, rmMessageById, writeMessage } = functions[collection];
|
|
826
|
-
const message = await
|
|
1328
|
+
const { getMessage: getMessage2, rmMessageById, writeMessage } = functions[collection];
|
|
1329
|
+
const message = await getMessage2(directory)(_message.id, _message.version);
|
|
827
1330
|
const messagePath = await getResourcePath(directory, _message.id, _message.version);
|
|
828
1331
|
const extension = extname2(messagePath?.fullPath || "");
|
|
829
1332
|
if (!message) throw new Error(`Message ${_message.id} with version ${_message.version} not found`);
|
|
@@ -968,10 +1471,12 @@ var writeCustomDoc = (directory) => async (customDoc, options = { path: "" }) =>
|
|
|
968
1471
|
fsSync4.mkdirSync(path3.dirname(fullPath), { recursive: true });
|
|
969
1472
|
const document = matter5.stringify(customDoc.markdown.trim(), rest);
|
|
970
1473
|
fsSync4.writeFileSync(fullPath, document);
|
|
1474
|
+
invalidateFileCache();
|
|
971
1475
|
};
|
|
972
1476
|
var rmCustomDoc = (directory) => async (filePath) => {
|
|
973
1477
|
const withExtension = filePath.endsWith(".mdx") ? filePath : `${filePath}.mdx`;
|
|
974
1478
|
await fs8.rm(join10(directory, withExtension), { recursive: true });
|
|
1479
|
+
invalidateFileCache();
|
|
975
1480
|
};
|
|
976
1481
|
|
|
977
1482
|
// src/teams.ts
|
|
@@ -1023,9 +1528,11 @@ var writeUser = (catalogDir) => async (user, options = {}) => {
|
|
|
1023
1528
|
const document = matter6.stringify(markdown, frontmatter);
|
|
1024
1529
|
fsSync5.mkdirSync(join11(catalogDir, ""), { recursive: true });
|
|
1025
1530
|
fsSync5.writeFileSync(join11(catalogDir, "", `${resource.id}.mdx`), document);
|
|
1531
|
+
invalidateFileCache();
|
|
1026
1532
|
};
|
|
1027
1533
|
var rmUserById = (catalogDir) => async (id) => {
|
|
1028
1534
|
fsSync5.rmSync(join11(catalogDir, `${id}.mdx`), { recursive: true });
|
|
1535
|
+
invalidateFileCache();
|
|
1029
1536
|
};
|
|
1030
1537
|
|
|
1031
1538
|
// src/teams.ts
|
|
@@ -1065,9 +1572,11 @@ var writeTeam = (catalogDir) => async (team, options = {}) => {
|
|
|
1065
1572
|
const document = matter7.stringify(markdown, frontmatter);
|
|
1066
1573
|
fsSync6.mkdirSync(join12(catalogDir, ""), { recursive: true });
|
|
1067
1574
|
fsSync6.writeFileSync(join12(catalogDir, "", `${resource.id}.mdx`), document);
|
|
1575
|
+
invalidateFileCache();
|
|
1068
1576
|
};
|
|
1069
1577
|
var rmTeamById = (catalogDir) => async (id) => {
|
|
1070
1578
|
await fs9.rm(join12(catalogDir, `${id}.mdx`), { recursive: true });
|
|
1579
|
+
invalidateFileCache();
|
|
1071
1580
|
};
|
|
1072
1581
|
var getOwnersForResource = (catalogDir) => async (id, version) => {
|
|
1073
1582
|
const resource = await getResource(catalogDir, id, version);
|
|
@@ -1197,6 +1706,7 @@ var writeEntity = (directory) => async (entity, options = {
|
|
|
1197
1706
|
}) => writeResource(directory, { ...entity }, { ...options, type: "entity" });
|
|
1198
1707
|
var rmEntity = (directory) => async (path6) => {
|
|
1199
1708
|
await fs11.rm(join14(directory, path6), { recursive: true });
|
|
1709
|
+
invalidateFileCache();
|
|
1200
1710
|
};
|
|
1201
1711
|
var rmEntityById = (directory) => async (id, version, persistFiles) => {
|
|
1202
1712
|
await rmResourceById(directory, id, version, { type: "entity", persistFiles });
|
|
@@ -1220,6 +1730,7 @@ var writeContainer = (directory) => async (data, options = {
|
|
|
1220
1730
|
var versionContainer = (directory) => async (id) => versionResource(directory, id);
|
|
1221
1731
|
var rmContainer = (directory) => async (path6) => {
|
|
1222
1732
|
await fs12.rm(join15(directory, path6), { recursive: true });
|
|
1733
|
+
invalidateFileCache();
|
|
1223
1734
|
};
|
|
1224
1735
|
var rmContainerById = (directory) => async (id, version, persistFiles) => {
|
|
1225
1736
|
await rmResourceById(directory, id, version, { type: "container", persistFiles });
|
|
@@ -1267,6 +1778,7 @@ var writeDataProductToDomain = (directory) => async (dataProduct, domain, option
|
|
|
1267
1778
|
};
|
|
1268
1779
|
var rmDataProduct = (directory) => async (path6) => {
|
|
1269
1780
|
await fs13.rm(join16(directory, path6), { recursive: true });
|
|
1781
|
+
invalidateFileCache();
|
|
1270
1782
|
};
|
|
1271
1783
|
var rmDataProductById = (directory) => async (id, version, persistFiles) => {
|
|
1272
1784
|
await rmResourceById(directory, id, version, { type: "data-product", persistFiles });
|
|
@@ -1290,6 +1802,7 @@ var writeDiagram = (directory) => async (diagram, options = {
|
|
|
1290
1802
|
}) => writeResource(directory, { ...diagram }, { ...options, type: "diagram" });
|
|
1291
1803
|
var rmDiagram = (directory) => async (path6) => {
|
|
1292
1804
|
await fs14.rm(join17(directory, path6), { recursive: true });
|
|
1805
|
+
invalidateFileCache();
|
|
1293
1806
|
};
|
|
1294
1807
|
var rmDiagramById = (directory) => async (id, version, persistFiles) => {
|
|
1295
1808
|
await rmResourceById(directory, id, version, { type: "diagram", persistFiles });
|
|
@@ -2394,7 +2907,35 @@ var src_default = (path6) => {
|
|
|
2394
2907
|
* @param version - Optional version of the diagram to add the file to
|
|
2395
2908
|
* @returns
|
|
2396
2909
|
*/
|
|
2397
|
-
addFileToDiagram: addFileToDiagram(join18(path6))
|
|
2910
|
+
addFileToDiagram: addFileToDiagram(join18(path6)),
|
|
2911
|
+
/**
|
|
2912
|
+
* ================================
|
|
2913
|
+
* DSL
|
|
2914
|
+
* ================================
|
|
2915
|
+
*/
|
|
2916
|
+
/**
|
|
2917
|
+
* Converts catalog resources to EventCatalog DSL (.ec) format strings.
|
|
2918
|
+
*
|
|
2919
|
+
* @param resource - A resource or array of resources to convert
|
|
2920
|
+
* @param options - Options including type ('event'|'command'|'query'|'service'|'domain') and optional hydrate flag
|
|
2921
|
+
* @returns A DSL string representation
|
|
2922
|
+
*
|
|
2923
|
+
* @example
|
|
2924
|
+
* ```ts
|
|
2925
|
+
* const dsl = await sdk.toDSL(event, { type: 'event' });
|
|
2926
|
+
* const dsl = await sdk.toDSL(services, { type: 'service', hydrate: true });
|
|
2927
|
+
* ```
|
|
2928
|
+
*/
|
|
2929
|
+
toDSL: toDSL(join18(path6), {
|
|
2930
|
+
getEvent: getEvent(join18(path6)),
|
|
2931
|
+
getCommand: getCommand(join18(path6)),
|
|
2932
|
+
getQuery: getQuery(join18(path6)),
|
|
2933
|
+
getService: getService(join18(path6)),
|
|
2934
|
+
getDomain: getDomain(join18(path6, "domains")),
|
|
2935
|
+
getChannel: getChannel(join18(path6)),
|
|
2936
|
+
getTeam: getTeam(join18(path6, "teams")),
|
|
2937
|
+
getUser: getUser(join18(path6, "users"))
|
|
2938
|
+
})
|
|
2398
2939
|
};
|
|
2399
2940
|
};
|
|
2400
2941
|
export {
|