@living-architecture/riviere-schema 0.2.0
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/CLAUDE.md +9 -0
- package/README.md +11 -0
- package/dist/component-id.d.ts +74 -0
- package/dist/component-id.d.ts.map +1 -0
- package/dist/component-id.js +82 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/schema.d.ts +144 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +1 -0
- package/dist/tsconfig.lib.tsbuildinfo +1 -0
- package/dist/validation.d.ts +10 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +21 -0
- package/examples/ecommerce-complete-v2.json +2633 -0
- package/examples/ecommerce-complete.json +2486 -0
- package/package.json +26 -0
- package/project.json +3 -0
- package/riviere.schema.json +581 -0
- package/src/component-id.spec.ts +65 -0
- package/src/component-id.ts +97 -0
- package/src/index.ts +3 -0
- package/src/schema.spec.ts +169 -0
- package/src/schema.ts +184 -0
- package/src/validation.ts +32 -0
- package/tsconfig.json +13 -0
- package/tsconfig.lib.json +28 -0
- package/tsconfig.spec.json +34 -0
- package/tsconfig.tsbuildinfo +1 -0
- package/vite.config.ts +20 -0
- package/vitest.config.mts +24 -0
package/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@living-architecture/riviere-schema",
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"publishConfig": {
|
|
6
|
+
"access": "public"
|
|
7
|
+
},
|
|
8
|
+
"main": "./dist/index.js",
|
|
9
|
+
"module": "./dist/index.js",
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"exports": {
|
|
12
|
+
"./package.json": "./package.json",
|
|
13
|
+
".": {
|
|
14
|
+
"@living-architecture/source": "./src/index.ts",
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"import": "./dist/index.js",
|
|
17
|
+
"default": "./dist/index.js"
|
|
18
|
+
},
|
|
19
|
+
"./schema.json": "./riviere.schema.json"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"ajv": "^8.17.1",
|
|
23
|
+
"ajv-formats": "^3.0.1",
|
|
24
|
+
"tslib": "^2.3.0"
|
|
25
|
+
}
|
|
26
|
+
}
|
package/project.json
ADDED
|
@@ -0,0 +1,581 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://riviere.arch/schema/riviere.schema.json",
|
|
4
|
+
"title": "Rivière Architecture Graph",
|
|
5
|
+
"description": "Flow-based architecture graph format for operational visualization",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["version", "metadata", "components", "links"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"version": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"description": "Schema version",
|
|
12
|
+
"pattern": "^[0-9]+\\.[0-9]+$"
|
|
13
|
+
},
|
|
14
|
+
"metadata": {
|
|
15
|
+
"type": "object",
|
|
16
|
+
"description": "Graph-level metadata",
|
|
17
|
+
"required": ["domains"],
|
|
18
|
+
"properties": {
|
|
19
|
+
"name": {
|
|
20
|
+
"type": "string",
|
|
21
|
+
"description": "Human-readable name for this architecture graph"
|
|
22
|
+
},
|
|
23
|
+
"description": {
|
|
24
|
+
"type": "string",
|
|
25
|
+
"description": "Description of what this graph represents"
|
|
26
|
+
},
|
|
27
|
+
"generated": {
|
|
28
|
+
"type": "string",
|
|
29
|
+
"format": "date-time",
|
|
30
|
+
"description": "Timestamp when this graph was generated"
|
|
31
|
+
},
|
|
32
|
+
"sources": {
|
|
33
|
+
"type": "array",
|
|
34
|
+
"description": "Source repositories this graph was extracted from",
|
|
35
|
+
"items": {
|
|
36
|
+
"type": "object",
|
|
37
|
+
"required": ["repository"],
|
|
38
|
+
"properties": {
|
|
39
|
+
"repository": {
|
|
40
|
+
"type": "string",
|
|
41
|
+
"description": "Repository name or identifier"
|
|
42
|
+
},
|
|
43
|
+
"commit": {
|
|
44
|
+
"type": "string",
|
|
45
|
+
"description": "Git commit SHA"
|
|
46
|
+
},
|
|
47
|
+
"extractedAt": {
|
|
48
|
+
"type": "string",
|
|
49
|
+
"format": "date-time",
|
|
50
|
+
"description": "When this repository was extracted"
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
"domains": {
|
|
56
|
+
"type": "object",
|
|
57
|
+
"description": "Domain-level metadata keyed by domain name",
|
|
58
|
+
"minProperties": 1,
|
|
59
|
+
"additionalProperties": {
|
|
60
|
+
"$ref": "#/definitions/domainMetadata"
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
"customTypes": {
|
|
64
|
+
"type": "object",
|
|
65
|
+
"description": "User-defined custom component types with their required and optional properties",
|
|
66
|
+
"additionalProperties": {
|
|
67
|
+
"$ref": "#/definitions/customTypeDefinition"
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
"components": {
|
|
73
|
+
"type": "array",
|
|
74
|
+
"description": "Architectural components in the system",
|
|
75
|
+
"items": {
|
|
76
|
+
"$ref": "#/definitions/component"
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
"links": {
|
|
80
|
+
"type": "array",
|
|
81
|
+
"description": "Operational flows between components",
|
|
82
|
+
"items": {
|
|
83
|
+
"$ref": "#/definitions/link"
|
|
84
|
+
}
|
|
85
|
+
},
|
|
86
|
+
"externalLinks": {
|
|
87
|
+
"type": "array",
|
|
88
|
+
"description": "Links to external systems outside the graph",
|
|
89
|
+
"items": {
|
|
90
|
+
"$ref": "#/definitions/externalLink"
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
"definitions": {
|
|
95
|
+
"component": {
|
|
96
|
+
"oneOf": [
|
|
97
|
+
{ "$ref": "#/definitions/uiComponent" },
|
|
98
|
+
{ "$ref": "#/definitions/apiRestComponent" },
|
|
99
|
+
{ "$ref": "#/definitions/apiGraphqlComponent" },
|
|
100
|
+
{ "$ref": "#/definitions/apiOtherComponent" },
|
|
101
|
+
{ "$ref": "#/definitions/useCaseComponent" },
|
|
102
|
+
{ "$ref": "#/definitions/domainOpComponent" },
|
|
103
|
+
{ "$ref": "#/definitions/eventComponent" },
|
|
104
|
+
{ "$ref": "#/definitions/eventHandlerComponent" },
|
|
105
|
+
{ "$ref": "#/definitions/customComponent" }
|
|
106
|
+
]
|
|
107
|
+
},
|
|
108
|
+
"baseComponentProperties": {
|
|
109
|
+
"type": "object",
|
|
110
|
+
"properties": {
|
|
111
|
+
"id": {
|
|
112
|
+
"type": "string",
|
|
113
|
+
"description": "Globally unique identifier following format: {domain}:{module}:{type}:{name}[:{lineNumber}].",
|
|
114
|
+
"minLength": 1
|
|
115
|
+
},
|
|
116
|
+
"name": {
|
|
117
|
+
"type": "string",
|
|
118
|
+
"description": "Human-readable name",
|
|
119
|
+
"minLength": 1
|
|
120
|
+
},
|
|
121
|
+
"domain": {
|
|
122
|
+
"type": "string",
|
|
123
|
+
"description": "Domain boundary this node belongs to",
|
|
124
|
+
"minLength": 1
|
|
125
|
+
},
|
|
126
|
+
"module": {
|
|
127
|
+
"type": "string",
|
|
128
|
+
"description": "Functional module within the domain",
|
|
129
|
+
"minLength": 1
|
|
130
|
+
},
|
|
131
|
+
"description": {
|
|
132
|
+
"type": "string",
|
|
133
|
+
"description": "Optional description of what this node does"
|
|
134
|
+
},
|
|
135
|
+
"sourceLocation": {
|
|
136
|
+
"$ref": "#/definitions/sourceLocation"
|
|
137
|
+
},
|
|
138
|
+
"metadata": {
|
|
139
|
+
"type": "object",
|
|
140
|
+
"description": "Extensible metadata for custom properties",
|
|
141
|
+
"additionalProperties": true
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
},
|
|
145
|
+
"uiComponent": {
|
|
146
|
+
"type": "object",
|
|
147
|
+
"required": ["id", "type", "name", "domain", "module", "sourceLocation", "route"],
|
|
148
|
+
"properties": {
|
|
149
|
+
"id": { "type": "string", "minLength": 1 },
|
|
150
|
+
"type": { "const": "UI" },
|
|
151
|
+
"name": { "type": "string", "minLength": 1 },
|
|
152
|
+
"domain": { "type": "string", "minLength": 1 },
|
|
153
|
+
"module": { "type": "string", "minLength": 1 },
|
|
154
|
+
"description": { "type": "string" },
|
|
155
|
+
"sourceLocation": { "$ref": "#/definitions/sourceLocation" },
|
|
156
|
+
"metadata": { "type": "object", "additionalProperties": true },
|
|
157
|
+
"route": { "type": "string", "description": "URL route where UI component is rendered", "minLength": 1 }
|
|
158
|
+
},
|
|
159
|
+
"additionalProperties": false
|
|
160
|
+
},
|
|
161
|
+
"apiRestComponent": {
|
|
162
|
+
"type": "object",
|
|
163
|
+
"required": ["id", "type", "name", "domain", "module", "sourceLocation", "apiType", "httpMethod", "path"],
|
|
164
|
+
"properties": {
|
|
165
|
+
"id": { "type": "string", "minLength": 1 },
|
|
166
|
+
"type": { "const": "API" },
|
|
167
|
+
"name": { "type": "string", "minLength": 1 },
|
|
168
|
+
"domain": { "type": "string", "minLength": 1 },
|
|
169
|
+
"module": { "type": "string", "minLength": 1 },
|
|
170
|
+
"description": { "type": "string" },
|
|
171
|
+
"sourceLocation": { "$ref": "#/definitions/sourceLocation" },
|
|
172
|
+
"metadata": { "type": "object", "additionalProperties": true },
|
|
173
|
+
"apiType": { "const": "REST" },
|
|
174
|
+
"httpMethod": { "type": "string", "enum": ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"] },
|
|
175
|
+
"path": { "type": "string", "description": "API path" }
|
|
176
|
+
},
|
|
177
|
+
"additionalProperties": false
|
|
178
|
+
},
|
|
179
|
+
"apiGraphqlComponent": {
|
|
180
|
+
"type": "object",
|
|
181
|
+
"required": ["id", "type", "name", "domain", "module", "sourceLocation", "apiType", "operationName"],
|
|
182
|
+
"properties": {
|
|
183
|
+
"id": { "type": "string", "minLength": 1 },
|
|
184
|
+
"type": { "const": "API" },
|
|
185
|
+
"name": { "type": "string", "minLength": 1 },
|
|
186
|
+
"domain": { "type": "string", "minLength": 1 },
|
|
187
|
+
"module": { "type": "string", "minLength": 1 },
|
|
188
|
+
"description": { "type": "string" },
|
|
189
|
+
"sourceLocation": { "$ref": "#/definitions/sourceLocation" },
|
|
190
|
+
"metadata": { "type": "object", "additionalProperties": true },
|
|
191
|
+
"apiType": { "const": "GraphQL" },
|
|
192
|
+
"operationName": { "type": "string", "description": "GraphQL operation name" }
|
|
193
|
+
},
|
|
194
|
+
"additionalProperties": false
|
|
195
|
+
},
|
|
196
|
+
"apiOtherComponent": {
|
|
197
|
+
"type": "object",
|
|
198
|
+
"required": ["id", "type", "name", "domain", "module", "sourceLocation", "apiType"],
|
|
199
|
+
"properties": {
|
|
200
|
+
"id": { "type": "string", "minLength": 1 },
|
|
201
|
+
"type": { "const": "API" },
|
|
202
|
+
"name": { "type": "string", "minLength": 1 },
|
|
203
|
+
"domain": { "type": "string", "minLength": 1 },
|
|
204
|
+
"module": { "type": "string", "minLength": 1 },
|
|
205
|
+
"description": { "type": "string" },
|
|
206
|
+
"sourceLocation": { "$ref": "#/definitions/sourceLocation" },
|
|
207
|
+
"metadata": { "type": "object", "additionalProperties": true },
|
|
208
|
+
"apiType": { "const": "other" }
|
|
209
|
+
},
|
|
210
|
+
"additionalProperties": false
|
|
211
|
+
},
|
|
212
|
+
"useCaseComponent": {
|
|
213
|
+
"type": "object",
|
|
214
|
+
"required": ["id", "type", "name", "domain", "module", "sourceLocation"],
|
|
215
|
+
"properties": {
|
|
216
|
+
"id": { "type": "string", "minLength": 1 },
|
|
217
|
+
"type": { "const": "UseCase" },
|
|
218
|
+
"name": { "type": "string", "minLength": 1 },
|
|
219
|
+
"domain": { "type": "string", "minLength": 1 },
|
|
220
|
+
"module": { "type": "string", "minLength": 1 },
|
|
221
|
+
"description": { "type": "string" },
|
|
222
|
+
"sourceLocation": { "$ref": "#/definitions/sourceLocation" },
|
|
223
|
+
"metadata": { "type": "object", "additionalProperties": true }
|
|
224
|
+
},
|
|
225
|
+
"additionalProperties": false
|
|
226
|
+
},
|
|
227
|
+
"domainOpComponent": {
|
|
228
|
+
"type": "object",
|
|
229
|
+
"required": ["id", "type", "name", "domain", "module", "sourceLocation", "operationName"],
|
|
230
|
+
"properties": {
|
|
231
|
+
"id": { "type": "string", "minLength": 1 },
|
|
232
|
+
"type": { "const": "DomainOp" },
|
|
233
|
+
"name": { "type": "string", "minLength": 1 },
|
|
234
|
+
"domain": { "type": "string", "minLength": 1 },
|
|
235
|
+
"module": { "type": "string", "minLength": 1 },
|
|
236
|
+
"description": { "type": "string" },
|
|
237
|
+
"sourceLocation": { "$ref": "#/definitions/sourceLocation" },
|
|
238
|
+
"metadata": { "type": "object", "additionalProperties": true },
|
|
239
|
+
"operationName": { "type": "string", "description": "Operation name" },
|
|
240
|
+
"entity": { "type": "string", "description": "Entity name" },
|
|
241
|
+
"signature": { "$ref": "#/definitions/operationSignature" },
|
|
242
|
+
"behavior": { "$ref": "#/definitions/operationBehavior" },
|
|
243
|
+
"stateChanges": { "type": "array", "items": { "$ref": "#/definitions/stateTransition" } },
|
|
244
|
+
"businessRules": { "type": "array", "items": { "type": "string", "minLength": 1 } }
|
|
245
|
+
},
|
|
246
|
+
"additionalProperties": false
|
|
247
|
+
},
|
|
248
|
+
"eventComponent": {
|
|
249
|
+
"type": "object",
|
|
250
|
+
"required": ["id", "type", "name", "domain", "module", "sourceLocation", "eventName"],
|
|
251
|
+
"properties": {
|
|
252
|
+
"id": { "type": "string", "minLength": 1 },
|
|
253
|
+
"type": { "const": "Event" },
|
|
254
|
+
"name": { "type": "string", "minLength": 1 },
|
|
255
|
+
"domain": { "type": "string", "minLength": 1 },
|
|
256
|
+
"module": { "type": "string", "minLength": 1 },
|
|
257
|
+
"description": { "type": "string" },
|
|
258
|
+
"sourceLocation": { "$ref": "#/definitions/sourceLocation" },
|
|
259
|
+
"metadata": { "type": "object", "additionalProperties": true },
|
|
260
|
+
"eventName": { "type": "string", "description": "Event name" },
|
|
261
|
+
"eventSchema": { "type": "string", "description": "Event schema definition" }
|
|
262
|
+
},
|
|
263
|
+
"additionalProperties": false
|
|
264
|
+
},
|
|
265
|
+
"eventHandlerComponent": {
|
|
266
|
+
"type": "object",
|
|
267
|
+
"required": ["id", "type", "name", "domain", "module", "sourceLocation", "subscribedEvents"],
|
|
268
|
+
"properties": {
|
|
269
|
+
"id": { "type": "string", "minLength": 1 },
|
|
270
|
+
"type": { "const": "EventHandler" },
|
|
271
|
+
"name": { "type": "string", "minLength": 1 },
|
|
272
|
+
"domain": { "type": "string", "minLength": 1 },
|
|
273
|
+
"module": { "type": "string", "minLength": 1 },
|
|
274
|
+
"description": { "type": "string" },
|
|
275
|
+
"sourceLocation": { "$ref": "#/definitions/sourceLocation" },
|
|
276
|
+
"metadata": { "type": "object", "additionalProperties": true },
|
|
277
|
+
"subscribedEvents": { "type": "array", "items": { "type": "string" }, "description": "Events this handler subscribes to" }
|
|
278
|
+
},
|
|
279
|
+
"additionalProperties": false
|
|
280
|
+
},
|
|
281
|
+
"customComponent": {
|
|
282
|
+
"type": "object",
|
|
283
|
+
"required": ["id", "type", "name", "domain", "module", "sourceLocation", "customTypeName"],
|
|
284
|
+
"properties": {
|
|
285
|
+
"id": { "type": "string", "minLength": 1 },
|
|
286
|
+
"type": { "const": "Custom" },
|
|
287
|
+
"name": { "type": "string", "minLength": 1 },
|
|
288
|
+
"domain": { "type": "string", "minLength": 1 },
|
|
289
|
+
"module": { "type": "string", "minLength": 1 },
|
|
290
|
+
"description": { "type": "string" },
|
|
291
|
+
"sourceLocation": { "$ref": "#/definitions/sourceLocation" },
|
|
292
|
+
"metadata": { "type": "object", "additionalProperties": true },
|
|
293
|
+
"customTypeName": { "type": "string", "description": "Name of the custom type (must match a key in metadata.customTypes)", "minLength": 1 }
|
|
294
|
+
},
|
|
295
|
+
"additionalProperties": false
|
|
296
|
+
},
|
|
297
|
+
"link": {
|
|
298
|
+
"type": "object",
|
|
299
|
+
"required": ["source", "target"],
|
|
300
|
+
"properties": {
|
|
301
|
+
"id": {
|
|
302
|
+
"type": "string",
|
|
303
|
+
"description": "Optional unique identifier for this link"
|
|
304
|
+
},
|
|
305
|
+
"source": {
|
|
306
|
+
"type": "string",
|
|
307
|
+
"description": "Source component ID",
|
|
308
|
+
"minLength": 1
|
|
309
|
+
},
|
|
310
|
+
"target": {
|
|
311
|
+
"type": "string",
|
|
312
|
+
"description": "Target component ID",
|
|
313
|
+
"minLength": 1
|
|
314
|
+
},
|
|
315
|
+
"type": {
|
|
316
|
+
"type": "string",
|
|
317
|
+
"enum": ["sync", "async"],
|
|
318
|
+
"description": "Link type: sync (request/response) or async (fire-and-forget, events)"
|
|
319
|
+
},
|
|
320
|
+
"payload": {
|
|
321
|
+
"type": "object",
|
|
322
|
+
"description": "Data transferred through this flow",
|
|
323
|
+
"properties": {
|
|
324
|
+
"type": {
|
|
325
|
+
"type": "string",
|
|
326
|
+
"description": "Payload type name"
|
|
327
|
+
},
|
|
328
|
+
"schema": {
|
|
329
|
+
"type": "object",
|
|
330
|
+
"description": "Schema definition as JSON object"
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
},
|
|
334
|
+
"sourceLocation": {
|
|
335
|
+
"$ref": "#/definitions/sourceLocation"
|
|
336
|
+
},
|
|
337
|
+
"metadata": {
|
|
338
|
+
"type": "object",
|
|
339
|
+
"description": "Extensible metadata for custom properties",
|
|
340
|
+
"additionalProperties": true
|
|
341
|
+
}
|
|
342
|
+
},
|
|
343
|
+
"additionalProperties": false
|
|
344
|
+
},
|
|
345
|
+
"externalLink": {
|
|
346
|
+
"type": "object",
|
|
347
|
+
"description": "Link from an internal component to an external system",
|
|
348
|
+
"required": ["source", "target"],
|
|
349
|
+
"properties": {
|
|
350
|
+
"id": {
|
|
351
|
+
"type": "string",
|
|
352
|
+
"description": "Optional unique identifier for this link"
|
|
353
|
+
},
|
|
354
|
+
"source": {
|
|
355
|
+
"type": "string",
|
|
356
|
+
"description": "Source component ID (must exist in graph)",
|
|
357
|
+
"minLength": 1
|
|
358
|
+
},
|
|
359
|
+
"target": {
|
|
360
|
+
"$ref": "#/definitions/externalTarget",
|
|
361
|
+
"description": "External system being called"
|
|
362
|
+
},
|
|
363
|
+
"type": {
|
|
364
|
+
"type": "string",
|
|
365
|
+
"enum": ["sync", "async"],
|
|
366
|
+
"description": "Link type: sync (request/response) or async (fire-and-forget)"
|
|
367
|
+
},
|
|
368
|
+
"description": {
|
|
369
|
+
"type": "string",
|
|
370
|
+
"description": "Human-readable description of this integration"
|
|
371
|
+
},
|
|
372
|
+
"sourceLocation": {
|
|
373
|
+
"$ref": "#/definitions/sourceLocation"
|
|
374
|
+
},
|
|
375
|
+
"metadata": {
|
|
376
|
+
"type": "object",
|
|
377
|
+
"description": "Extensible metadata for custom properties",
|
|
378
|
+
"additionalProperties": true
|
|
379
|
+
}
|
|
380
|
+
},
|
|
381
|
+
"additionalProperties": false
|
|
382
|
+
},
|
|
383
|
+
"externalTarget": {
|
|
384
|
+
"type": "object",
|
|
385
|
+
"description": "Reference to an external system outside the graph",
|
|
386
|
+
"required": ["name"],
|
|
387
|
+
"properties": {
|
|
388
|
+
"name": {
|
|
389
|
+
"type": "string",
|
|
390
|
+
"description": "Name of the external system",
|
|
391
|
+
"minLength": 1
|
|
392
|
+
},
|
|
393
|
+
"domain": {
|
|
394
|
+
"type": "string",
|
|
395
|
+
"description": "Domain name if known"
|
|
396
|
+
},
|
|
397
|
+
"repository": {
|
|
398
|
+
"type": "string",
|
|
399
|
+
"description": "Repository name if known"
|
|
400
|
+
},
|
|
401
|
+
"url": {
|
|
402
|
+
"type": "string",
|
|
403
|
+
"format": "uri",
|
|
404
|
+
"description": "URL to the external system"
|
|
405
|
+
}
|
|
406
|
+
},
|
|
407
|
+
"additionalProperties": false
|
|
408
|
+
},
|
|
409
|
+
"sourceLocation": {
|
|
410
|
+
"type": "object",
|
|
411
|
+
"required": ["repository", "filePath"],
|
|
412
|
+
"properties": {
|
|
413
|
+
"repository": {
|
|
414
|
+
"type": "string",
|
|
415
|
+
"description": "Repository name or identifier"
|
|
416
|
+
},
|
|
417
|
+
"filePath": {
|
|
418
|
+
"type": "string",
|
|
419
|
+
"description": "Relative file path within repository",
|
|
420
|
+
"minLength": 1
|
|
421
|
+
},
|
|
422
|
+
"lineNumber": {
|
|
423
|
+
"type": "integer",
|
|
424
|
+
"description": "Starting line number",
|
|
425
|
+
"minimum": 1
|
|
426
|
+
},
|
|
427
|
+
"endLineNumber": {
|
|
428
|
+
"type": "integer",
|
|
429
|
+
"description": "Ending line number",
|
|
430
|
+
"minimum": 1
|
|
431
|
+
},
|
|
432
|
+
"methodName": {
|
|
433
|
+
"type": "string",
|
|
434
|
+
"description": "Method or function name"
|
|
435
|
+
},
|
|
436
|
+
"url": {
|
|
437
|
+
"type": "string",
|
|
438
|
+
"format": "uri",
|
|
439
|
+
"description": "Direct URL to view this location in source control"
|
|
440
|
+
}
|
|
441
|
+
},
|
|
442
|
+
"additionalProperties": false
|
|
443
|
+
},
|
|
444
|
+
"domainMetadata": {
|
|
445
|
+
"type": "object",
|
|
446
|
+
"description": "Domain-level metadata for UI display",
|
|
447
|
+
"required": ["description", "systemType"],
|
|
448
|
+
"properties": {
|
|
449
|
+
"description": {
|
|
450
|
+
"type": "string",
|
|
451
|
+
"description": "Human-readable description of domain purpose"
|
|
452
|
+
},
|
|
453
|
+
"systemType": {
|
|
454
|
+
"type": "string",
|
|
455
|
+
"enum": ["domain", "bff", "ui", "other"],
|
|
456
|
+
"description": "Classification of domain's role in system"
|
|
457
|
+
}
|
|
458
|
+
},
|
|
459
|
+
"additionalProperties": true
|
|
460
|
+
},
|
|
461
|
+
"customTypeDefinition": {
|
|
462
|
+
"type": "object",
|
|
463
|
+
"description": "Definition of a custom component type with required and optional properties",
|
|
464
|
+
"properties": {
|
|
465
|
+
"description": {
|
|
466
|
+
"type": "string",
|
|
467
|
+
"description": "Human-readable description of this custom type"
|
|
468
|
+
},
|
|
469
|
+
"requiredProperties": {
|
|
470
|
+
"type": "object",
|
|
471
|
+
"description": "Properties required for components of this custom type (beyond base component properties)",
|
|
472
|
+
"additionalProperties": {
|
|
473
|
+
"$ref": "#/definitions/customPropertyDefinition"
|
|
474
|
+
}
|
|
475
|
+
},
|
|
476
|
+
"optionalProperties": {
|
|
477
|
+
"type": "object",
|
|
478
|
+
"description": "Optional properties for components of this custom type",
|
|
479
|
+
"additionalProperties": {
|
|
480
|
+
"$ref": "#/definitions/customPropertyDefinition"
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
},
|
|
484
|
+
"additionalProperties": false
|
|
485
|
+
},
|
|
486
|
+
"customPropertyDefinition": {
|
|
487
|
+
"type": "object",
|
|
488
|
+
"description": "Definition of a property in a custom type",
|
|
489
|
+
"required": ["type"],
|
|
490
|
+
"properties": {
|
|
491
|
+
"type": {
|
|
492
|
+
"type": "string",
|
|
493
|
+
"description": "JSON Schema type (string, number, boolean, array, object)",
|
|
494
|
+
"enum": ["string", "number", "boolean", "array", "object"]
|
|
495
|
+
},
|
|
496
|
+
"description": {
|
|
497
|
+
"type": "string",
|
|
498
|
+
"description": "Human-readable description of this property"
|
|
499
|
+
}
|
|
500
|
+
},
|
|
501
|
+
"additionalProperties": false
|
|
502
|
+
},
|
|
503
|
+
"operationSignature": {
|
|
504
|
+
"type": "object",
|
|
505
|
+
"description": "Method signature including parameters and return type",
|
|
506
|
+
"properties": {
|
|
507
|
+
"parameters": {
|
|
508
|
+
"type": "array",
|
|
509
|
+
"items": {
|
|
510
|
+
"type": "object",
|
|
511
|
+
"required": ["name", "type"],
|
|
512
|
+
"properties": {
|
|
513
|
+
"name": {
|
|
514
|
+
"type": "string",
|
|
515
|
+
"minLength": 1
|
|
516
|
+
},
|
|
517
|
+
"type": {
|
|
518
|
+
"type": "string",
|
|
519
|
+
"minLength": 1
|
|
520
|
+
},
|
|
521
|
+
"description": {
|
|
522
|
+
"type": "string"
|
|
523
|
+
}
|
|
524
|
+
},
|
|
525
|
+
"additionalProperties": false
|
|
526
|
+
}
|
|
527
|
+
},
|
|
528
|
+
"returnType": {
|
|
529
|
+
"type": "string",
|
|
530
|
+
"minLength": 1
|
|
531
|
+
}
|
|
532
|
+
},
|
|
533
|
+
"additionalProperties": false
|
|
534
|
+
},
|
|
535
|
+
"operationBehavior": {
|
|
536
|
+
"type": "object",
|
|
537
|
+
"description": "Behavioral characteristics of the operation",
|
|
538
|
+
"properties": {
|
|
539
|
+
"reads": {
|
|
540
|
+
"type": "array",
|
|
541
|
+
"description": "Entity fields or state read by this operation",
|
|
542
|
+
"items": { "type": "string" }
|
|
543
|
+
},
|
|
544
|
+
"validates": {
|
|
545
|
+
"type": "array",
|
|
546
|
+
"description": "Invariants or preconditions validated",
|
|
547
|
+
"items": { "type": "string" }
|
|
548
|
+
},
|
|
549
|
+
"modifies": {
|
|
550
|
+
"type": "array",
|
|
551
|
+
"description": "Entity fields or state modified by this operation",
|
|
552
|
+
"items": { "type": "string" }
|
|
553
|
+
},
|
|
554
|
+
"emits": {
|
|
555
|
+
"type": "array",
|
|
556
|
+
"description": "Events emitted by this operation",
|
|
557
|
+
"items": { "type": "string" }
|
|
558
|
+
}
|
|
559
|
+
},
|
|
560
|
+
"additionalProperties": false
|
|
561
|
+
},
|
|
562
|
+
"stateTransition": {
|
|
563
|
+
"type": "object",
|
|
564
|
+
"description": "A single state transition caused by an operation",
|
|
565
|
+
"required": ["from", "to"],
|
|
566
|
+
"properties": {
|
|
567
|
+
"from": {
|
|
568
|
+
"type": "string",
|
|
569
|
+
"description": "Source state (use '*' for any state)",
|
|
570
|
+
"minLength": 1
|
|
571
|
+
},
|
|
572
|
+
"to": {
|
|
573
|
+
"type": "string",
|
|
574
|
+
"description": "Target state",
|
|
575
|
+
"minLength": 1
|
|
576
|
+
}
|
|
577
|
+
},
|
|
578
|
+
"additionalProperties": false
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { ComponentId } from './component-id'
|
|
2
|
+
|
|
3
|
+
describe('ComponentId', () => {
|
|
4
|
+
describe('create', () => {
|
|
5
|
+
it('creates ID from parts with correct format', () => {
|
|
6
|
+
const id = ComponentId.create({
|
|
7
|
+
domain: 'orders',
|
|
8
|
+
module: 'checkout',
|
|
9
|
+
type: 'domainop',
|
|
10
|
+
name: 'Place Order',
|
|
11
|
+
})
|
|
12
|
+
|
|
13
|
+
expect(id.toString()).toBe('orders:checkout:domainop:place-order')
|
|
14
|
+
})
|
|
15
|
+
|
|
16
|
+
it('lowercases and hyphenates name', () => {
|
|
17
|
+
const id = ComponentId.create({
|
|
18
|
+
domain: 'orders',
|
|
19
|
+
module: 'checkout',
|
|
20
|
+
type: 'usecase',
|
|
21
|
+
name: 'Handle Customer Request',
|
|
22
|
+
})
|
|
23
|
+
|
|
24
|
+
expect(id.toString()).toBe('orders:checkout:usecase:handle-customer-request')
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
it('exposes name segment', () => {
|
|
28
|
+
const id = ComponentId.create({
|
|
29
|
+
domain: 'orders',
|
|
30
|
+
module: 'checkout',
|
|
31
|
+
type: 'domainop',
|
|
32
|
+
name: 'Place Order',
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
expect(id.name()).toBe('place-order')
|
|
36
|
+
})
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
describe('parse', () => {
|
|
40
|
+
it('parses valid ID string', () => {
|
|
41
|
+
const id = ComponentId.parse('orders:checkout:domainop:place-order')
|
|
42
|
+
|
|
43
|
+
expect(id.name()).toBe('place-order')
|
|
44
|
+
expect(id.toString()).toBe('orders:checkout:domainop:place-order')
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
it('throws on invalid format with too few segments', () => {
|
|
48
|
+
expect(() => ComponentId.parse('orders:checkout')).toThrow(
|
|
49
|
+
"Invalid component ID format: 'orders:checkout'. Expected 'domain:module:type:name'"
|
|
50
|
+
)
|
|
51
|
+
})
|
|
52
|
+
|
|
53
|
+
it('throws on invalid format with too many segments', () => {
|
|
54
|
+
expect(() => ComponentId.parse('orders:checkout:domainop:place:order')).toThrow(
|
|
55
|
+
"Invalid component ID format: 'orders:checkout:domainop:place:order'. Expected 'domain:module:type:name'"
|
|
56
|
+
)
|
|
57
|
+
})
|
|
58
|
+
|
|
59
|
+
it('throws on empty string', () => {
|
|
60
|
+
expect(() => ComponentId.parse('')).toThrow(
|
|
61
|
+
"Invalid component ID format: ''. Expected 'domain:module:type:name'"
|
|
62
|
+
)
|
|
63
|
+
})
|
|
64
|
+
})
|
|
65
|
+
})
|