@eventcatalog/core 4.10.15 → 4.11.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.
Files changed (165) hide show
  1. package/dist/analytics/analytics.cjs +1 -1
  2. package/dist/analytics/analytics.js +2 -2
  3. package/dist/analytics/log-build.cjs +1 -1
  4. package/dist/analytics/log-build.js +3 -3
  5. package/dist/astro-output.cjs +60 -1
  6. package/dist/astro-output.js +1 -1
  7. package/dist/{chunk-U52FCZQ6.js → chunk-2YJRF4ZX.js} +1 -1
  8. package/dist/chunk-634NFV5U.js +75 -0
  9. package/dist/{chunk-I6HUOX4R.js → chunk-AXDNSGAN.js} +1 -1
  10. package/dist/chunk-DHH5U5PF.js +53 -0
  11. package/dist/{chunk-A4JRWRCV.js → chunk-DSCIWCX2.js} +1 -1
  12. package/dist/chunk-FWXEV4LF.js +19 -0
  13. package/dist/{chunk-Q2ATWE7N.js → chunk-GZVDXCYF.js} +1 -1
  14. package/dist/{chunk-7LWOCX4R.js → chunk-RYNPEIHQ.js} +1 -1
  15. package/dist/{chunk-HBVTU6ZP.js → chunk-YYVW4DCO.js} +1 -1
  16. package/dist/constants.cjs +1 -1
  17. package/dist/constants.js +1 -1
  18. package/dist/copy-core.cjs +88 -0
  19. package/dist/copy-core.d.cts +4 -0
  20. package/dist/copy-core.d.ts +4 -0
  21. package/dist/copy-core.js +8 -0
  22. package/dist/eventcatalog.cjs +234 -115
  23. package/dist/eventcatalog.js +36 -30
  24. package/dist/federation/federate.js +3 -3
  25. package/dist/federation/source-provider.js +2 -2
  26. package/dist/generate.cjs +1 -1
  27. package/dist/generate.js +3 -3
  28. package/dist/update-check.cjs +44 -0
  29. package/dist/update-check.d.cts +18 -0
  30. package/dist/update-check.d.ts +18 -0
  31. package/dist/update-check.js +8 -0
  32. package/dist/utils/cli-logger.cjs +1 -1
  33. package/dist/utils/cli-logger.js +2 -2
  34. package/eventcatalog/astro.config.mjs +8 -1
  35. package/eventcatalog/public/icons/languages/android.svg +1 -0
  36. package/eventcatalog/public/icons/languages/angular.svg +1 -0
  37. package/eventcatalog/public/icons/languages/apple.svg +1 -0
  38. package/eventcatalog/public/icons/languages/arduino.svg +1 -0
  39. package/eventcatalog/public/icons/languages/bash.svg +1 -0
  40. package/eventcatalog/public/icons/languages/bun.svg +1 -0
  41. package/eventcatalog/public/icons/languages/c.svg +1 -0
  42. package/eventcatalog/public/icons/languages/clojure.svg +1 -0
  43. package/eventcatalog/public/icons/languages/cpp.svg +1 -0
  44. package/eventcatalog/public/icons/languages/crystal.svg +1 -0
  45. package/eventcatalog/public/icons/languages/csharp.svg +1 -0
  46. package/eventcatalog/public/icons/languages/css.svg +1 -0
  47. package/eventcatalog/public/icons/languages/curl.svg +1 -0
  48. package/eventcatalog/public/icons/languages/dart.svg +1 -0
  49. package/eventcatalog/public/icons/languages/deno.svg +1 -0
  50. package/eventcatalog/public/icons/languages/docker.svg +1 -0
  51. package/eventcatalog/public/icons/languages/elm.svg +1 -0
  52. package/eventcatalog/public/icons/languages/erlang.svg +1 -0
  53. package/eventcatalog/public/icons/languages/flutter.svg +1 -0
  54. package/eventcatalog/public/icons/languages/fortran.svg +1 -0
  55. package/eventcatalog/public/icons/languages/fsharp.svg +1 -0
  56. package/eventcatalog/public/icons/languages/git.svg +1 -0
  57. package/eventcatalog/public/icons/languages/gradle.svg +1 -0
  58. package/eventcatalog/public/icons/languages/graphql.svg +1 -0
  59. package/eventcatalog/public/icons/languages/grpc.svg +1 -0
  60. package/eventcatalog/public/icons/languages/haskell.svg +1 -0
  61. package/eventcatalog/public/icons/languages/hasura.svg +1 -0
  62. package/eventcatalog/public/icons/languages/html.svg +1 -0
  63. package/eventcatalog/public/icons/languages/httpie.svg +1 -0
  64. package/eventcatalog/public/icons/languages/javascript.svg +1 -0
  65. package/eventcatalog/public/icons/languages/json-schema.svg +1 -0
  66. package/eventcatalog/public/icons/languages/json.svg +1 -0
  67. package/eventcatalog/public/icons/languages/julia.svg +1 -0
  68. package/eventcatalog/public/icons/languages/jupyter.svg +1 -0
  69. package/eventcatalog/public/icons/languages/kafka.svg +1 -0
  70. package/eventcatalog/public/icons/languages/kotlin.svg +1 -0
  71. package/eventcatalog/public/icons/languages/lua.svg +1 -0
  72. package/eventcatalog/public/icons/languages/markdown.svg +1 -0
  73. package/eventcatalog/public/icons/languages/maven.svg +1 -0
  74. package/eventcatalog/public/icons/languages/mongodb.svg +1 -0
  75. package/eventcatalog/public/icons/languages/mysql.svg +1 -0
  76. package/eventcatalog/public/icons/languages/nginx.svg +1 -0
  77. package/eventcatalog/public/icons/languages/nim.svg +1 -0
  78. package/eventcatalog/public/icons/languages/ocaml.svg +1 -0
  79. package/eventcatalog/public/icons/languages/perl.svg +1 -0
  80. package/eventcatalog/public/icons/languages/php.svg +1 -0
  81. package/eventcatalog/public/icons/languages/postgresql.svg +1 -0
  82. package/eventcatalog/public/icons/languages/prisma.svg +1 -0
  83. package/eventcatalog/public/icons/languages/purescript.svg +1 -0
  84. package/eventcatalog/public/icons/languages/python.svg +1 -0
  85. package/eventcatalog/public/icons/languages/r.svg +1 -0
  86. package/eventcatalog/public/icons/languages/react.svg +1 -0
  87. package/eventcatalog/public/icons/languages/reasonml.svg +1 -0
  88. package/eventcatalog/public/icons/languages/redis.svg +1 -0
  89. package/eventcatalog/public/icons/languages/ruby.svg +1 -0
  90. package/eventcatalog/public/icons/languages/rust.svg +1 -0
  91. package/eventcatalog/public/icons/languages/sass.svg +1 -0
  92. package/eventcatalog/public/icons/languages/scala.svg +1 -0
  93. package/eventcatalog/public/icons/languages/solidity.svg +1 -0
  94. package/eventcatalog/public/icons/languages/spring.svg +1 -0
  95. package/eventcatalog/public/icons/languages/sqlite.svg +1 -0
  96. package/eventcatalog/public/icons/languages/svelte.svg +1 -0
  97. package/eventcatalog/public/icons/languages/swagger.svg +1 -0
  98. package/eventcatalog/public/icons/languages/swift.svg +1 -0
  99. package/eventcatalog/public/icons/languages/tailwind.svg +1 -0
  100. package/eventcatalog/public/icons/languages/terraform.svg +1 -0
  101. package/eventcatalog/public/icons/languages/toml.svg +1 -0
  102. package/eventcatalog/public/icons/languages/typescript.svg +1 -0
  103. package/eventcatalog/public/icons/languages/unity.svg +1 -0
  104. package/eventcatalog/public/icons/languages/vim.svg +1 -0
  105. package/eventcatalog/public/icons/languages/vue.svg +1 -0
  106. package/eventcatalog/public/icons/languages/webassembly.svg +1 -0
  107. package/eventcatalog/public/icons/languages/yaml.svg +1 -0
  108. package/eventcatalog/public/icons/languages/zig.svg +1 -0
  109. package/eventcatalog/src/components/MDX/CodeGroup/CodeGroup.astro +12 -0
  110. package/eventcatalog/src/components/MDX/CodeGroup/CodeGroup.tsx +176 -0
  111. package/eventcatalog/src/components/MDX/CodeGroup/MarkdownCodeGroup.tsx +22 -0
  112. package/eventcatalog/src/components/MDX/CodeGroup/code-group-icons.ts +345 -0
  113. package/eventcatalog/src/components/MDX/CodeGroup/code-group.css +22 -0
  114. package/eventcatalog/src/components/MDX/CodeGroup/parse-panels.ts +11 -0
  115. package/eventcatalog/src/components/MDX/Columns/Column.astro +10 -0
  116. package/eventcatalog/src/components/MDX/Columns/Columns.astro +14 -0
  117. package/eventcatalog/src/components/MDX/Columns/MarkdownColumns.tsx +37 -0
  118. package/eventcatalog/src/components/MDX/Columns/layout.ts +16 -0
  119. package/eventcatalog/src/components/MDX/components.tsx +6 -0
  120. package/eventcatalog/src/components/SchemaExplorer/ApiContentViewer.tsx +1 -1
  121. package/eventcatalog/src/components/SchemaExplorer/ExamplesViewer.tsx +151 -114
  122. package/eventcatalog/src/components/SchemaExplorer/SchemaDetailsPanel.tsx +510 -248
  123. package/eventcatalog/src/components/SchemaExplorer/SchemaFlows.tsx +76 -0
  124. package/eventcatalog/src/components/SchemaExplorer/SchemaGraph.tsx +47 -0
  125. package/eventcatalog/src/components/SchemaExplorer/SchemaPageViewer.tsx +11 -0
  126. package/eventcatalog/src/components/SchemaExplorer/SchemaUsage.tsx +17 -0
  127. package/eventcatalog/src/components/SchemaExplorer/types.ts +48 -3
  128. package/eventcatalog/src/components/SchemaExplorer/utils.ts +28 -1
  129. package/eventcatalog/src/content.config.ts +28 -0
  130. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/examples/[...filename].astro +38 -7
  131. package/eventcatalog/src/pages/schemas/[type]/[id]/[version]/index.astro +144 -37
  132. package/eventcatalog/src/pages/schemas/explorer/index.astro +5 -0
  133. package/eventcatalog/src/plugins/empty-collection-warning.d.ts +21 -0
  134. package/eventcatalog/src/plugins/empty-collection-warning.mjs +107 -0
  135. package/eventcatalog/src/plugins/quiet-empty-collections-logger.mjs +11 -0
  136. package/eventcatalog/src/remark-plugins/code-group.ts +39 -0
  137. package/eventcatalog/src/remark-plugins/markdown-code-group.ts +59 -0
  138. package/eventcatalog/src/remark-plugins/markdown-columns.ts +66 -0
  139. package/eventcatalog/src/utils/collections/channels.ts +12 -4
  140. package/eventcatalog/src/utils/collections/examples.ts +133 -41
  141. package/eventcatalog/src/utils/collections/flows.ts +43 -0
  142. package/eventcatalog/src/utils/collections/messages.ts +2 -2
  143. package/eventcatalog/src/utils/collections/schemas.ts +15 -0
  144. package/eventcatalog/src/utils/node-graphs/message-node-graph.ts +17 -15
  145. package/eventcatalog/src/utils/schema-explorer.ts +73 -7
  146. package/eventcatalog/src/utils/schema-usage-graph.ts +92 -0
  147. package/package.json +5 -4
  148. package/dist/chunk-RDYYZQYU.js +0 -18
  149. package/eventcatalog/src/components/EnvironmentDropdown.test.ts +0 -64
  150. package/eventcatalog/src/components/Grids/message-link.spec.ts +0 -59
  151. package/eventcatalog/src/components/MDX/CustomProperties/custom-properties.spec.ts +0 -38
  152. package/eventcatalog/src/components/MDX/SchemaViewer/schema-viewer-utils.spec.ts +0 -116
  153. package/eventcatalog/src/components/SchemaExplorer/JSONSchemaViewer.test.tsx +0 -114
  154. package/eventcatalog/src/components/SchemaExplorer/ProtobufSchemaViewer.test.tsx +0 -91
  155. package/eventcatalog/src/components/SchemaExplorer/SchemaViewerHover.test.tsx +0 -33
  156. package/eventcatalog/src/components/SchemaExplorer/protobuf-validation.test.ts +0 -84
  157. package/eventcatalog/src/components/Search/search-utils.spec.ts +0 -173
  158. package/eventcatalog/src/components/SideNav/NestedSideBar/utils.spec.ts +0 -105
  159. package/eventcatalog/src/components/navigation-progress.spec.ts +0 -68
  160. package/eventcatalog/src/enterprise/directory/user-team-directory.spec.ts +0 -527
  161. package/eventcatalog/src/enterprise/fields/field-extractor.test.ts +0 -302
  162. package/eventcatalog/src/enterprise/fields/fields-db.test.ts +0 -185
  163. package/eventcatalog/src/stores/eventcatalog-store.spec.ts +0 -60
  164. package/eventcatalog/src/utils/collections/glob-loader.spec.ts +0 -87
  165. package/dist/{chunk-6K7XZAYI.js → chunk-A2RZR3U4.js} +3 -3
@@ -1,302 +0,0 @@
1
- /**
2
- * Licensed under the EventCatalog Commercial License.
3
- * See /packages/core/eventcatalog/src/enterprise/LICENSE
4
- */
5
-
6
- import { describe, it, expect } from 'vitest';
7
- import { extractSchemaFieldsDeep } from './field-extractor';
8
-
9
- describe('extractSchemaFieldsDeep', () => {
10
- describe('JSON Schema', () => {
11
- it('extracts top-level properties with their types', () => {
12
- const schema = JSON.stringify({
13
- type: 'object',
14
- properties: {
15
- orderId: { type: 'string', description: 'The order ID' },
16
- amount: { type: 'number' },
17
- },
18
- });
19
- const fields = extractSchemaFieldsDeep(schema, 'json-schema');
20
- expect(fields).toEqual([
21
- { path: 'orderId', type: 'string', description: 'The order ID', required: false },
22
- { path: 'amount', type: 'number', description: '', required: false },
23
- ]);
24
- });
25
-
26
- it('marks fields as required when listed in the JSON Schema required array', () => {
27
- const schema = JSON.stringify({
28
- type: 'object',
29
- required: ['orderId'],
30
- properties: {
31
- orderId: { type: 'string' },
32
- notes: { type: 'string' },
33
- },
34
- });
35
- const fields = extractSchemaFieldsDeep(schema, 'json-schema');
36
- expect(fields[0].required).toBe(true);
37
- expect(fields[1].required).toBe(false);
38
- });
39
-
40
- it('extracts nested object fields with dot-notation paths', () => {
41
- const schema = JSON.stringify({
42
- type: 'object',
43
- properties: {
44
- address: {
45
- type: 'object',
46
- properties: {
47
- street: { type: 'string' },
48
- city: { type: 'string' },
49
- },
50
- },
51
- },
52
- });
53
- const fields = extractSchemaFieldsDeep(schema, 'json-schema');
54
- expect(fields.map((f) => f.path)).toEqual(['address', 'address.street', 'address.city']);
55
- });
56
-
57
- it('uses bracket notation for array item fields', () => {
58
- const schema = JSON.stringify({
59
- type: 'object',
60
- properties: {
61
- items: {
62
- type: 'array',
63
- items: {
64
- type: 'object',
65
- properties: {
66
- productId: { type: 'string' },
67
- quantity: { type: 'integer' },
68
- },
69
- },
70
- },
71
- },
72
- });
73
- const fields = extractSchemaFieldsDeep(schema, 'json-schema');
74
- expect(fields.map((f) => f.path)).toEqual(['items', 'items[].productId', 'items[].quantity']);
75
- });
76
-
77
- it('resolves local $ref references within the same schema', () => {
78
- const schema = JSON.stringify({
79
- type: 'object',
80
- properties: {
81
- billing: { $ref: '#/definitions/Address' },
82
- },
83
- definitions: {
84
- Address: {
85
- type: 'object',
86
- properties: {
87
- street: { type: 'string' },
88
- zip: { type: 'string' },
89
- },
90
- },
91
- },
92
- });
93
- const fields = extractSchemaFieldsDeep(schema, 'json-schema');
94
- expect(fields.map((f) => f.path)).toEqual(['billing', 'billing.street', 'billing.zip']);
95
- });
96
-
97
- it('skips external $ref references and returns only local fields', () => {
98
- const schema = JSON.stringify({
99
- type: 'object',
100
- properties: {
101
- orderId: { type: 'string' },
102
- customer: { $ref: './common.json#/definitions/Customer' },
103
- },
104
- });
105
- const fields = extractSchemaFieldsDeep(schema, 'json-schema');
106
- expect(fields).toHaveLength(2);
107
- expect(fields[0].path).toBe('orderId');
108
- expect(fields[1].path).toBe('customer');
109
- expect(fields[1].type).toBe('$ref');
110
- });
111
-
112
- it('merges allOf schemas and extracts combined properties', () => {
113
- const schema = JSON.stringify({
114
- allOf: [
115
- { type: 'object', properties: { id: { type: 'string' } } },
116
- { type: 'object', properties: { name: { type: 'string' } } },
117
- ],
118
- });
119
- const fields = extractSchemaFieldsDeep(schema, 'json-schema');
120
- expect(fields.map((f) => f.path)).toEqual(['id', 'name']);
121
- });
122
-
123
- it('converts array type values to a sorted pipe-separated string (e.g. nullable fields)', () => {
124
- const schema = JSON.stringify({
125
- type: 'object',
126
- properties: {
127
- userId: { type: 'string', description: 'identifier for a user' },
128
- cancellationReason: { type: ['string', 'null'], description: 'optional reason' },
129
- renewalDate: { type: ['null', 'integer'], description: 'unix timestamp or null' },
130
- },
131
- });
132
- const fields = extractSchemaFieldsDeep(schema, 'json-schema');
133
- expect(fields).toEqual([
134
- { path: 'userId', type: 'string', description: 'identifier for a user', required: false },
135
- { path: 'cancellationReason', type: 'null | string', description: 'optional reason', required: false },
136
- { path: 'renewalDate', type: 'integer | null', description: 'unix timestamp or null', required: false },
137
- ]);
138
- });
139
-
140
- it('recurses into nested properties when object type is nullable', () => {
141
- const schema = JSON.stringify({
142
- type: 'object',
143
- properties: {
144
- metadata: {
145
- type: ['object', 'null'],
146
- properties: {
147
- source: { type: 'string' },
148
- version: { type: 'integer' },
149
- },
150
- },
151
- },
152
- });
153
- const fields = extractSchemaFieldsDeep(schema, 'json-schema');
154
- expect(fields.map((f) => f.path)).toEqual(['metadata', 'metadata.source', 'metadata.version']);
155
- expect(fields[0].type).toBe('null | object');
156
- });
157
-
158
- it('recurses into array items when array type is nullable', () => {
159
- const schema = JSON.stringify({
160
- type: 'object',
161
- properties: {
162
- tags: {
163
- type: ['array', 'null'],
164
- items: {
165
- type: 'object',
166
- properties: {
167
- key: { type: 'string' },
168
- value: { type: 'string' },
169
- },
170
- },
171
- },
172
- },
173
- });
174
- const fields = extractSchemaFieldsDeep(schema, 'json-schema');
175
- expect(fields.map((f) => f.path)).toEqual(['tags', 'tags[].key', 'tags[].value']);
176
- expect(fields[0].type).toBe('array | null'); // already sorted alphabetically
177
- });
178
-
179
- it('returns empty array when schema content is malformed JSON', () => {
180
- const fields = extractSchemaFieldsDeep('not valid json{{{', 'json-schema');
181
- expect(fields).toEqual([]);
182
- });
183
-
184
- it('returns empty array when schema content is empty', () => {
185
- const fields = extractSchemaFieldsDeep('', 'json-schema');
186
- expect(fields).toEqual([]);
187
- });
188
- });
189
-
190
- describe('Avro', () => {
191
- it('extracts fields from a simple Avro record', () => {
192
- const schema = JSON.stringify({
193
- type: 'record',
194
- name: 'Order',
195
- fields: [
196
- { name: 'orderId', type: 'string', doc: 'The order identifier' },
197
- { name: 'amount', type: 'double' },
198
- ],
199
- });
200
- const fields = extractSchemaFieldsDeep(schema, 'avro');
201
- expect(fields).toEqual([
202
- { path: 'orderId', type: 'string', description: 'The order identifier', required: true },
203
- { path: 'amount', type: 'double', description: '', required: true },
204
- ]);
205
- });
206
-
207
- it('handles Avro union types containing null as optional fields', () => {
208
- const schema = JSON.stringify({
209
- type: 'record',
210
- name: 'Customer',
211
- fields: [
212
- { name: 'id', type: 'string' },
213
- { name: 'nickname', type: ['null', 'string'] },
214
- ],
215
- });
216
- const fields = extractSchemaFieldsDeep(schema, 'avro');
217
- expect(fields[0].required).toBe(true);
218
- expect(fields[1].required).toBe(false);
219
- expect(fields[1].type).toBe('null | string');
220
- });
221
-
222
- it('extracts nested record fields with dot-notation paths', () => {
223
- const schema = JSON.stringify({
224
- type: 'record',
225
- name: 'Order',
226
- fields: [
227
- {
228
- name: 'customer',
229
- type: {
230
- type: 'record',
231
- name: 'Customer',
232
- fields: [
233
- { name: 'name', type: 'string' },
234
- { name: 'email', type: 'string' },
235
- ],
236
- },
237
- },
238
- ],
239
- });
240
- const fields = extractSchemaFieldsDeep(schema, 'avro');
241
- expect(fields.map((f) => f.path)).toEqual(['customer', 'customer.name', 'customer.email']);
242
- });
243
-
244
- it('uses bracket notation for Avro array items', () => {
245
- const schema = JSON.stringify({
246
- type: 'record',
247
- name: 'Order',
248
- fields: [
249
- {
250
- name: 'items',
251
- type: {
252
- type: 'array',
253
- items: {
254
- type: 'record',
255
- name: 'Item',
256
- fields: [
257
- { name: 'productId', type: 'string' },
258
- { name: 'qty', type: 'int' },
259
- ],
260
- },
261
- },
262
- },
263
- ],
264
- });
265
- const fields = extractSchemaFieldsDeep(schema, 'avro');
266
- expect(fields.map((f) => f.path)).toEqual(['items', 'items[].productId', 'items[].qty']);
267
- });
268
- });
269
-
270
- describe('Protobuf', () => {
271
- it('extracts fields from a simple proto3 message', () => {
272
- const proto = `
273
- syntax = "proto3";
274
- message Order {
275
- string order_id = 1;
276
- double amount = 2; // total amount
277
- }
278
- `;
279
- const fields = extractSchemaFieldsDeep(proto, 'proto');
280
- expect(fields).toEqual([
281
- { path: 'order_id', type: 'string', description: '', required: false },
282
- { path: 'amount', type: 'double', description: 'total amount', required: false },
283
- ]);
284
- });
285
-
286
- it('marks repeated fields with their modifier in the type', () => {
287
- const proto = `
288
- syntax = "proto3";
289
- message Order {
290
- repeated string tags = 1;
291
- }
292
- `;
293
- const fields = extractSchemaFieldsDeep(proto, 'proto');
294
- expect(fields[0].type).toBe('repeated string');
295
- });
296
-
297
- it('returns empty array for empty proto content', () => {
298
- const fields = extractSchemaFieldsDeep('', 'proto');
299
- expect(fields).toEqual([]);
300
- });
301
- });
302
- });
@@ -1,185 +0,0 @@
1
- /**
2
- * Licensed under the EventCatalog Commercial License.
3
- * See /packages/core/eventcatalog/src/enterprise/LICENSE
4
- */
5
-
6
- import { describe, it, expect, beforeEach, afterEach } from 'vitest';
7
- import { FieldsDatabase } from './fields-db';
8
- import path from 'node:path';
9
- import fs from 'node:fs';
10
- import os from 'node:os';
11
-
12
- describe('FieldsDatabase', () => {
13
- let db: FieldsDatabase;
14
- let tmpDir: string;
15
-
16
- beforeEach(async () => {
17
- tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'fields-db-'));
18
- db = await FieldsDatabase.create(path.join(tmpDir, 'fields.db'), { recreate: true });
19
- });
20
-
21
- afterEach(() => {
22
- db.close();
23
- fs.rmSync(tmpDir, { recursive: true, force: true });
24
- });
25
-
26
- it('creates the schema tables on initialization', () => {
27
- const rows = db.db.exec("SELECT name FROM sqlite_master WHERE type='table'");
28
- const tableNames = rows.length > 0 ? rows[0].values.map((r: any) => r[0]) : [];
29
- expect(tableNames).toContain('fields');
30
- expect(tableNames).toContain('message_producers');
31
- expect(tableNames).toContain('message_consumers');
32
- });
33
-
34
- it('inserts fields and retrieves them with pagination', () => {
35
- db.insertField({
36
- path: 'orderId',
37
- type: 'string',
38
- description: 'The order ID',
39
- required: true,
40
- schemaFormat: 'json-schema',
41
- messageId: 'OrderCreated',
42
- messageVersion: '1.0.0',
43
- messageType: 'event',
44
- });
45
- db.insertField({
46
- path: 'amount',
47
- type: 'number',
48
- description: '',
49
- required: false,
50
- schemaFormat: 'json-schema',
51
- messageId: 'OrderCreated',
52
- messageVersion: '1.0.0',
53
- messageType: 'event',
54
- });
55
- const result = db.queryFields({});
56
- expect(result.fields).toHaveLength(2);
57
- expect(result.total).toBe(2);
58
- });
59
-
60
- it('filters fields by text search matching field path', () => {
61
- db.insertField({
62
- path: 'orderId',
63
- type: 'string',
64
- description: '',
65
- required: true,
66
- schemaFormat: 'json-schema',
67
- messageId: 'OrderCreated',
68
- messageVersion: '1.0.0',
69
- messageType: 'event',
70
- });
71
- db.insertField({
72
- path: 'amount',
73
- type: 'number',
74
- description: '',
75
- required: false,
76
- schemaFormat: 'json-schema',
77
- messageId: 'OrderCreated',
78
- messageVersion: '1.0.0',
79
- messageType: 'event',
80
- });
81
- const result = db.queryFields({ q: 'orderId' });
82
- expect(result.fields).toHaveLength(1);
83
- expect(result.fields[0].path).toBe('orderId');
84
- });
85
-
86
- it('filters fields that appear in multiple messages when shared flag is set', () => {
87
- db.insertField({
88
- path: 'customerId',
89
- type: 'string',
90
- description: '',
91
- required: true,
92
- schemaFormat: 'json-schema',
93
- messageId: 'OrderCreated',
94
- messageVersion: '1.0.0',
95
- messageType: 'event',
96
- });
97
- db.insertField({
98
- path: 'customerId',
99
- type: 'string',
100
- description: '',
101
- required: true,
102
- schemaFormat: 'json-schema',
103
- messageId: 'PaymentProcessed',
104
- messageVersion: '1.0.0',
105
- messageType: 'event',
106
- });
107
- db.insertField({
108
- path: 'amount',
109
- type: 'number',
110
- description: '',
111
- required: false,
112
- schemaFormat: 'json-schema',
113
- messageId: 'PaymentProcessed',
114
- messageVersion: '1.0.0',
115
- messageType: 'event',
116
- });
117
- const result = db.queryFields({ shared: true });
118
- expect(result.fields.every((f) => f.path === 'customerId')).toBe(true);
119
- });
120
-
121
- it('returns facet counts reflecting current filters', () => {
122
- db.insertField({
123
- path: 'orderId',
124
- type: 'string',
125
- description: '',
126
- required: true,
127
- schemaFormat: 'json-schema',
128
- messageId: 'OrderCreated',
129
- messageVersion: '1.0.0',
130
- messageType: 'event',
131
- });
132
- db.insertField({
133
- path: 'status',
134
- type: 'string',
135
- description: '',
136
- required: true,
137
- schemaFormat: 'avro',
138
- messageId: 'OrderUpdated',
139
- messageVersion: '1.0.0',
140
- messageType: 'event',
141
- });
142
- const result = db.queryFields({});
143
- expect(result.facets.formats).toContainEqual({ value: 'json-schema', count: 1 });
144
- expect(result.facets.formats).toContainEqual({ value: 'avro', count: 1 });
145
- });
146
-
147
- it('paginates results using keyset cursor', () => {
148
- for (let i = 0; i < 5; i++) {
149
- db.insertField({
150
- path: `field${i}`,
151
- type: 'string',
152
- description: '',
153
- required: false,
154
- schemaFormat: 'json-schema',
155
- messageId: 'TestMsg',
156
- messageVersion: '1.0.0',
157
- messageType: 'event',
158
- });
159
- }
160
- const page1 = db.queryFields({ pageSize: 2 });
161
- expect(page1.fields).toHaveLength(2);
162
- expect(page1.cursor).toBeDefined();
163
- const page2 = db.queryFields({ pageSize: 2, cursor: page1.cursor });
164
- expect(page2.fields).toHaveLength(2);
165
- expect(page2.fields[0].path).not.toBe(page1.fields[0].path);
166
- });
167
-
168
- it('joins producer and consumer data for each field', () => {
169
- db.insertField({
170
- path: 'orderId',
171
- type: 'string',
172
- description: '',
173
- required: true,
174
- schemaFormat: 'json-schema',
175
- messageId: 'OrderCreated',
176
- messageVersion: '1.0.0',
177
- messageType: 'event',
178
- });
179
- db.insertProducer('OrderCreated', '1.0.0', 'OrderService', '1.0.0');
180
- db.insertConsumer('OrderCreated', '1.0.0', 'InventoryService', '2.0.0');
181
- const result = db.queryFields({});
182
- expect(result.fields[0].producers).toEqual([{ id: 'OrderService', version: '1.0.0' }]);
183
- expect(result.fields[0].consumers).toEqual([{ id: 'InventoryService', version: '2.0.0' }]);
184
- });
185
- });
@@ -1,60 +0,0 @@
1
- import { mkdtemp, readFile, rm } from 'node:fs/promises';
2
- import { tmpdir } from 'node:os';
3
- import path from 'node:path';
4
- import { describe, expect, it } from 'vitest';
5
- import { EventCatalogStore } from './eventcatalog-store';
6
-
7
- type TestStoreResources = {
8
- users: { id: string; name: string }[];
9
- teams: { id: string; name: string }[];
10
- };
11
-
12
- describe('EventCatalogStore', () => {
13
- it('writes one collection while preserving the rest of the store', async () => {
14
- const tempDir = await mkdtemp(path.join(tmpdir(), 'eventcatalog-store-'));
15
- const storePath = EventCatalogStore.getStorePath(tempDir, 'directory');
16
- const store = new EventCatalogStore<TestStoreResources>({
17
- storePath,
18
- resources: {
19
- users: [],
20
- teams: [],
21
- },
22
- });
23
-
24
- try {
25
- await store.writeCollection('teams', [{ id: 'platform', name: 'Platform' }]);
26
- await store.writeCollection('users', [{ id: 'jane', name: 'Jane' }]);
27
-
28
- const stored = JSON.parse(await readFile(storePath, 'utf8'));
29
- expect(stored).toMatchObject({
30
- version: '1',
31
- resources: {
32
- users: [{ id: 'jane', name: 'Jane' }],
33
- teams: [{ id: 'platform', name: 'Platform' }],
34
- },
35
- });
36
- expect(stored.generatedAt).toEqual(expect.any(String));
37
- } finally {
38
- await rm(tempDir, { recursive: true, force: true });
39
- }
40
- });
41
-
42
- it('does not create a store file when clearing a collection that has not been generated', async () => {
43
- const tempDir = await mkdtemp(path.join(tmpdir(), 'eventcatalog-store-'));
44
- const storePath = EventCatalogStore.getStorePath(tempDir, 'directory');
45
- const store = new EventCatalogStore<TestStoreResources>({
46
- storePath,
47
- resources: {
48
- users: [],
49
- teams: [],
50
- },
51
- });
52
-
53
- try {
54
- await store.clearCollectionIfStoreExists('users');
55
- expect(await store.exists()).toBe(false);
56
- } finally {
57
- await rm(tempDir, { recursive: true, force: true });
58
- }
59
- });
60
- });
@@ -1,87 +0,0 @@
1
- import picomatch from 'picomatch';
2
- import { afterEach, describe, expect, it, vi } from 'vitest';
3
- import { mkdtemp, mkdir, writeFile, symlink, rm } from 'node:fs/promises';
4
- import { tmpdir } from 'node:os';
5
- import path from 'node:path';
6
- import { pathToFileURL } from 'node:url';
7
- import { globWithSafeWatcher, withFederatedContent, withIgnoredBuildArtifacts } from './glob-loader';
8
-
9
- describe('catalog discovery', () => {
10
- const directories: string[] = [];
11
-
12
- afterEach(async () => {
13
- vi.unstubAllEnvs();
14
- await Promise.all(directories.splice(0).map((directory) => rm(directory, { recursive: true, force: true })));
15
- });
16
-
17
- it.each([undefined, 'false', 'true'])('excludes dependency catalogs when IGNORE_BUILD_ARTIFACTS is %s', async (flag) => {
18
- vi.stubEnv('IGNORE_BUILD_ARTIFACTS', flag);
19
- const root = await mkdtemp(path.join(tmpdir(), 'catalog-discovery-'));
20
- directories.push(root);
21
- const catalog = path.join(root, 'catalog');
22
- const resources = [
23
- 'events/OrderConfirmed/index.md',
24
- 'domains/Orders/services/Inventory/events/Adjusted/versioned/1.0.0/index.mdx',
25
- 'federated/orders/events/OrderConfirmed/index.mdx',
26
- ];
27
- const dependencies = [
28
- 'node_modules/core/src/__tests__/events/OrderConfirmed/index.md',
29
- 'node_modules/core/node_modules/sdk/events/OrderConfirmed/index.mdx',
30
- 'federated/orders/node_modules/sdk/events/OrderConfirmed/index.md',
31
- ];
32
- for (const entry of [...resources, ...dependencies]) {
33
- const file = path.join(catalog, entry);
34
- await mkdir(path.dirname(file), { recursive: true });
35
- await writeFile(file, entry);
36
- }
37
- // Workspace dependencies are often symlinked outside the catalog.
38
- const linkedPackage = path.join(root, 'linked-package');
39
- await mkdir(path.join(linkedPackage, 'events/OrderConfirmed'), { recursive: true });
40
- await writeFile(path.join(linkedPackage, 'events/OrderConfirmed/index.md'), 'dependency');
41
- await symlink(linkedPackage, path.join(catalog, 'node_modules/linked'));
42
-
43
- const loaded = new Map();
44
- const logger = { warn: vi.fn(), error: vi.fn() };
45
- const base = pathToFileURL(`${catalog}/`);
46
- const loader = globWithSafeWatcher({
47
- pattern: withIgnoredBuildArtifacts('**/events/**/index.(md|mdx)'),
48
- base,
49
- generateId: ({ entry }) => entry,
50
- });
51
- await loader.load({
52
- config: { root: base, srcDir: new URL('src/', base) },
53
- collection: 'events',
54
- logger,
55
- store: {
56
- keys: () => loaded.keys(),
57
- get: (id: string) => loaded.get(id),
58
- set: (entry: { id: string }) => loaded.set(entry.id, entry),
59
- delete: (id: string) => loaded.delete(id),
60
- },
61
- parseData: async ({ data }: { data: unknown }) => data,
62
- generateDigest: (contents: string) => contents,
63
- entryTypes: new Map(['.md', '.mdx'].map((ext) => [ext, { getEntryInfo: () => ({ data: {}, body: '' }) }])),
64
- } as unknown as Parameters<typeof loader.load>[0]);
65
-
66
- expect([...loaded.keys()].sort()).toEqual(resources.sort());
67
- expect(logger.warn).not.toHaveBeenCalled();
68
- expect(logger.error).not.toHaveBeenCalled();
69
- });
70
- });
71
-
72
- describe('withFederatedContent', () => {
73
- it('loads root catalog content from every federated source directory', () => {
74
- const patterns = withFederatedContent(['services/*/index.(md|mdx)', 'domains/*/index.(md|mdx)', '!domains/*/services/**']);
75
-
76
- expect(patterns).toEqual([
77
- 'services/*/index.(md|mdx)',
78
- 'domains/*/index.(md|mdx)',
79
- '!domains/*/services/**',
80
- 'federated/*/services/*/index.(md|mdx)',
81
- 'federated/*/domains/*/index.(md|mdx)',
82
- '!federated/*/domains/*/services/**',
83
- ]);
84
- expect(picomatch.isMatch('federated/team-payments--abc123/services/payment-service/index.mdx', patterns)).toBe(true);
85
- expect(picomatch.isMatch('federated/team-payments--abc123/domains/payments/index.mdx', patterns)).toBe(true);
86
- });
87
- });
@@ -1,9 +1,9 @@
1
- import {
2
- createGitHubSourceProvider
3
- } from "./chunk-352FGP6W.js";
4
1
  import {
5
2
  createFileSystemSourceProvider
6
3
  } from "./chunk-SDZQJTJW.js";
4
+ import {
5
+ createGitHubSourceProvider
6
+ } from "./chunk-352FGP6W.js";
7
7
 
8
8
  // src/federation/source-provider.ts
9
9
  var createFederationSourceProvider = (projectDirectory, providers = {}) => {