@api-client/core 0.16.1 → 0.17.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/bin/test.ts +0 -4
- package/build/src/index.d.ts +72 -72
- package/build/src/index.d.ts.map +1 -1
- package/build/src/index.js +3 -3
- package/build/src/index.js.map +1 -1
- package/build/src/modeling/GraphUtils.d.ts.map +1 -1
- package/build/src/modeling/GraphUtils.js +16 -4
- package/build/src/modeling/GraphUtils.js.map +1 -1
- package/build/src/modeling/Semantics.d.ts +52 -0
- package/build/src/modeling/Semantics.d.ts.map +1 -1
- package/build/src/modeling/Semantics.js +206 -97
- package/build/src/modeling/Semantics.js.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/data/models/example-generator-api.json +12 -12
- package/package.json +1 -1
- package/src/modeling/GraphUtils.ts +15 -4
- package/src/modeling/Semantics.ts +226 -101
- package/tests/unit/modeling/api_model.spec.ts +25 -6
- package/tests/unit/modeling/data_domain.spec.ts +47 -47
- package/tests/unit/modeling/data_domain_associations.spec.ts +41 -30
- package/tests/unit/modeling/data_domain_change_observers.spec.ts +30 -6
- package/tests/unit/modeling/data_domain_entities.spec.ts +62 -62
- package/tests/unit/modeling/data_domain_foreign.spec.ts +59 -59
- package/tests/unit/modeling/data_domain_models.spec.ts +80 -82
- package/tests/unit/modeling/data_domain_namespaces.spec.ts +76 -76
- package/tests/unit/modeling/data_domain_property.spec.ts +29 -29
- package/tests/unit/modeling/data_domain_serialization.spec.ts +9 -9
- package/tests/unit/modeling/domain_asociation_targets.spec.ts +26 -26
- package/tests/unit/modeling/semantics.spec.ts +73 -1
|
@@ -42062,10 +42062,10 @@
|
|
|
42062
42062
|
"@id": "#209"
|
|
42063
42063
|
},
|
|
42064
42064
|
{
|
|
42065
|
-
"@id": "#
|
|
42065
|
+
"@id": "#194"
|
|
42066
42066
|
},
|
|
42067
42067
|
{
|
|
42068
|
-
"@id": "#
|
|
42068
|
+
"@id": "#191"
|
|
42069
42069
|
},
|
|
42070
42070
|
{
|
|
42071
42071
|
"@id": "#197"
|
|
@@ -42816,10 +42816,10 @@
|
|
|
42816
42816
|
"@id": "#213"
|
|
42817
42817
|
},
|
|
42818
42818
|
{
|
|
42819
|
-
"@id": "#
|
|
42819
|
+
"@id": "#219"
|
|
42820
42820
|
},
|
|
42821
42821
|
{
|
|
42822
|
-
"@id": "#
|
|
42822
|
+
"@id": "#216"
|
|
42823
42823
|
}
|
|
42824
42824
|
],
|
|
42825
42825
|
"doc:root": false,
|
|
@@ -43436,7 +43436,7 @@
|
|
|
43436
43436
|
"doc:ExternalDomainElement",
|
|
43437
43437
|
"doc:DomainElement"
|
|
43438
43438
|
],
|
|
43439
|
-
"doc:raw": "
|
|
43439
|
+
"doc:raw": "addressType: 'REGISTERED-OFFICE-ADDRESS'\nstreetName: 'UITBREIDINGSTRAAT'\nhouseNumber: '84'\nhouseNumberAddition: '/1'\npostalCode: '2600'\ncity: 'BERCHEM (ANTWERPEN)'\ncountry: 'Belgium'\ncountryCode: 'BE'\nfullFormatedAddress: \"UITBREIDINGSTRAAT 84 /1, 2600 BERCHEM (ANTWERPEN), BELIUM\"\n",
|
|
43440
43440
|
"core:mediaType": "application/yaml",
|
|
43441
43441
|
"sourcemaps:sources": [
|
|
43442
43442
|
{
|
|
@@ -43457,7 +43457,7 @@
|
|
|
43457
43457
|
"doc:ExternalDomainElement",
|
|
43458
43458
|
"doc:DomainElement"
|
|
43459
43459
|
],
|
|
43460
|
-
"doc:raw": "
|
|
43460
|
+
"doc:raw": "countryCode: \"BE\"\ngraydonEnterpriseId: 1057155523\nregistrationId: \"0422319093\"\nvatNumber: \"BE0422319093\"\ngraydonCompanyId: \"0422319093\"\nisBranchOffice: false\n",
|
|
43461
43461
|
"core:mediaType": "application/yaml",
|
|
43462
43462
|
"sourcemaps:sources": [
|
|
43463
43463
|
{
|
|
@@ -44274,7 +44274,7 @@
|
|
|
44274
44274
|
"doc:ExternalDomainElement",
|
|
44275
44275
|
"doc:DomainElement"
|
|
44276
44276
|
],
|
|
44277
|
-
"doc:raw": "
|
|
44277
|
+
"doc:raw": "type: \"GENERAL\"\nvalue: \"www.company.be\"\n",
|
|
44278
44278
|
"core:mediaType": "application/yaml",
|
|
44279
44279
|
"sourcemaps:sources": [
|
|
44280
44280
|
{
|
|
@@ -44295,7 +44295,7 @@
|
|
|
44295
44295
|
"doc:ExternalDomainElement",
|
|
44296
44296
|
"doc:DomainElement"
|
|
44297
44297
|
],
|
|
44298
|
-
"doc:raw": "type:
|
|
44298
|
+
"doc:raw": "-\n type: 'GENERAL'\n value: 'info@company.be'\n-\n type: 'IT_DEPT'\n value: 'it-service@company.be'\n",
|
|
44299
44299
|
"core:mediaType": "application/yaml",
|
|
44300
44300
|
"sourcemaps:sources": [
|
|
44301
44301
|
{
|
|
@@ -44756,12 +44756,12 @@
|
|
|
44756
44756
|
{
|
|
44757
44757
|
"@id": "#193/source-map/lexical/element_0",
|
|
44758
44758
|
"sourcemaps:element": "amf://id#193",
|
|
44759
|
-
"sourcemaps:value": "[(1,0)-(
|
|
44759
|
+
"sourcemaps:value": "[(1,0)-(10,0)]"
|
|
44760
44760
|
},
|
|
44761
44761
|
{
|
|
44762
44762
|
"@id": "#196/source-map/lexical/element_0",
|
|
44763
44763
|
"sourcemaps:element": "amf://id#196",
|
|
44764
|
-
"sourcemaps:value": "[(1,0)-(
|
|
44764
|
+
"sourcemaps:value": "[(1,0)-(7,0)]"
|
|
44765
44765
|
},
|
|
44766
44766
|
{
|
|
44767
44767
|
"@id": "#199/source-map/lexical/element_0",
|
|
@@ -45126,12 +45126,12 @@
|
|
|
45126
45126
|
{
|
|
45127
45127
|
"@id": "#218/source-map/lexical/element_0",
|
|
45128
45128
|
"sourcemaps:element": "amf://id#218",
|
|
45129
|
-
"sourcemaps:value": "[(1,0)-(
|
|
45129
|
+
"sourcemaps:value": "[(1,0)-(3,0)]"
|
|
45130
45130
|
},
|
|
45131
45131
|
{
|
|
45132
45132
|
"@id": "#221/source-map/lexical/element_0",
|
|
45133
45133
|
"sourcemaps:element": "amf://id#221",
|
|
45134
|
-
"sourcemaps:value": "[(1,0)-(
|
|
45134
|
+
"sourcemaps:value": "[(1,0)-(7,0)]"
|
|
45135
45135
|
},
|
|
45136
45136
|
{
|
|
45137
45137
|
"@id": "#338/source-map/synthesized-field/element_1",
|
package/package.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Graph } from '@api-client/graph/graph/Graph.js'
|
|
2
2
|
import type { DomainGraphEdge, DomainGraphNodeType } from './types.js'
|
|
3
|
+
import { DomainAssociationKind } from '../models/kinds.js'
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* Recursively removes a node and all its children from the graph.
|
|
@@ -9,18 +10,28 @@ export function removeGraphNode(graph: Graph<unknown, DomainGraphNodeType, Domai
|
|
|
9
10
|
if (!graph.hasNode(key)) {
|
|
10
11
|
return
|
|
11
12
|
}
|
|
13
|
+
const node = graph.node(key)
|
|
14
|
+
if (!node) {
|
|
15
|
+
return
|
|
16
|
+
}
|
|
17
|
+
if (node.kind === DomainAssociationKind) {
|
|
18
|
+
// If the node is an association, remove the association from the graph,
|
|
19
|
+
// but do not follow its children, as it would remove entities associated with it.
|
|
20
|
+
graph.removeNode(key)
|
|
21
|
+
return
|
|
22
|
+
}
|
|
12
23
|
for (const child of graph.children(key)) {
|
|
13
24
|
removeGraphNode(graph, child)
|
|
14
25
|
}
|
|
26
|
+
// Remove all edges from the node.
|
|
15
27
|
for (const edge of graph.outEdges(key)) {
|
|
16
28
|
const label = graph.edge(edge)
|
|
17
29
|
if (!label) {
|
|
18
30
|
continue
|
|
19
31
|
}
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
if (['property', 'association'].includes(label.type)) {
|
|
32
|
+
if (label.type === 'association') {
|
|
33
|
+
removeGraphNode(graph, edge.w)
|
|
34
|
+
} else if (label.type === 'property') {
|
|
24
35
|
removeGraphNode(graph, edge.w)
|
|
25
36
|
}
|
|
26
37
|
}
|
|
@@ -227,6 +227,44 @@ export enum SemanticScope {
|
|
|
227
227
|
Association = 'Association',
|
|
228
228
|
}
|
|
229
229
|
|
|
230
|
+
/**
|
|
231
|
+
* Defines categories for organizing semantics in the UI.
|
|
232
|
+
*/
|
|
233
|
+
export enum SemanticCategory {
|
|
234
|
+
/**
|
|
235
|
+
* User management, authentication, and access control
|
|
236
|
+
*/
|
|
237
|
+
Identity = 'Identity & Authentication',
|
|
238
|
+
/**
|
|
239
|
+
* Timestamps, versioning, and record lifecycle
|
|
240
|
+
*/
|
|
241
|
+
Lifecycle = 'Timestamps & Versioning',
|
|
242
|
+
/**
|
|
243
|
+
* Text content, media, and rich content types
|
|
244
|
+
*/
|
|
245
|
+
Content = 'Content & Media',
|
|
246
|
+
/**
|
|
247
|
+
* Business-specific data like pricing, inventory, status
|
|
248
|
+
*/
|
|
249
|
+
Business = 'Business Data',
|
|
250
|
+
/**
|
|
251
|
+
* Contact information and communication
|
|
252
|
+
*/
|
|
253
|
+
Contact = 'Contact Information',
|
|
254
|
+
/**
|
|
255
|
+
* Organization, categorization, and tagging
|
|
256
|
+
*/
|
|
257
|
+
Organization = 'Classification & Organization',
|
|
258
|
+
/**
|
|
259
|
+
* Location and geographical data
|
|
260
|
+
*/
|
|
261
|
+
Location = 'Location & Geography',
|
|
262
|
+
/**
|
|
263
|
+
* Calculated and derived values
|
|
264
|
+
*/
|
|
265
|
+
Computed = 'Computed Values',
|
|
266
|
+
}
|
|
267
|
+
|
|
230
268
|
/**
|
|
231
269
|
* A base interface for all Data Semantics, containing common properties.
|
|
232
270
|
* A semantic is an annotation applied to a Data Entity, Property, or Association
|
|
@@ -250,6 +288,10 @@ interface BaseDataSemantic {
|
|
|
250
288
|
* Specifies whether the semantic applies to an Entity, Property, or Association.
|
|
251
289
|
*/
|
|
252
290
|
scope: SemanticScope
|
|
291
|
+
/**
|
|
292
|
+
* The category this semantic belongs to for UI organization.
|
|
293
|
+
*/
|
|
294
|
+
category: SemanticCategory
|
|
253
295
|
}
|
|
254
296
|
|
|
255
297
|
/**
|
|
@@ -307,213 +349,296 @@ export type DataSemantic = EntitySemantic | PropertySemantic | AssociationSemant
|
|
|
307
349
|
*/
|
|
308
350
|
export const DataSemantics: Record<SemanticType, DataSemantic> = {
|
|
309
351
|
//
|
|
310
|
-
//
|
|
352
|
+
// Identity & Authentication
|
|
311
353
|
//
|
|
312
354
|
|
|
313
355
|
[SemanticType.User]: {
|
|
314
356
|
id: SemanticType.User,
|
|
315
357
|
displayName: 'User Entity',
|
|
316
358
|
scope: SemanticScope.Entity,
|
|
317
|
-
description: '
|
|
359
|
+
description: 'System users and accounts',
|
|
360
|
+
category: SemanticCategory.Identity,
|
|
318
361
|
},
|
|
319
|
-
|
|
320
|
-
//
|
|
321
|
-
// Property-Level Definitions
|
|
322
|
-
//
|
|
323
|
-
|
|
324
362
|
[SemanticType.Password]: {
|
|
325
363
|
id: SemanticType.Password,
|
|
326
364
|
displayName: 'User Password',
|
|
327
365
|
scope: SemanticScope.Property,
|
|
328
|
-
description:
|
|
329
|
-
|
|
366
|
+
description: 'Secure password field',
|
|
367
|
+
category: SemanticCategory.Identity,
|
|
368
|
+
applicableDataTypes: ['string'],
|
|
369
|
+
},
|
|
370
|
+
[SemanticType.UserRole]: {
|
|
371
|
+
id: SemanticType.UserRole,
|
|
372
|
+
displayName: 'User Role Field',
|
|
373
|
+
scope: SemanticScope.Property,
|
|
374
|
+
description: 'User permissions and access level',
|
|
375
|
+
category: SemanticCategory.Identity,
|
|
330
376
|
applicableDataTypes: ['string'],
|
|
331
377
|
},
|
|
378
|
+
[SemanticType.ResourceOwnerIdentifier]: {
|
|
379
|
+
id: SemanticType.ResourceOwnerIdentifier,
|
|
380
|
+
displayName: 'Resource Owner Identifier',
|
|
381
|
+
scope: SemanticScope.Association,
|
|
382
|
+
description: 'Links record to owner user',
|
|
383
|
+
category: SemanticCategory.Identity,
|
|
384
|
+
},
|
|
385
|
+
|
|
386
|
+
//
|
|
387
|
+
// Timestamps & Versioning
|
|
388
|
+
//
|
|
389
|
+
|
|
332
390
|
[SemanticType.CreatedTimestamp]: {
|
|
333
391
|
id: SemanticType.CreatedTimestamp,
|
|
334
392
|
displayName: 'Creation Timestamp',
|
|
335
393
|
scope: SemanticScope.Property,
|
|
336
|
-
description:
|
|
394
|
+
description: 'When record was created',
|
|
395
|
+
category: SemanticCategory.Lifecycle,
|
|
337
396
|
applicableDataTypes: ['datetime'],
|
|
338
397
|
},
|
|
339
398
|
[SemanticType.UpdatedTimestamp]: {
|
|
340
399
|
id: SemanticType.UpdatedTimestamp,
|
|
341
400
|
displayName: 'Update Timestamp',
|
|
342
401
|
scope: SemanticScope.Property,
|
|
343
|
-
description:
|
|
402
|
+
description: 'When record was last modified',
|
|
403
|
+
category: SemanticCategory.Lifecycle,
|
|
344
404
|
applicableDataTypes: ['datetime'],
|
|
345
405
|
},
|
|
346
406
|
[SemanticType.DeletedTimestamp]: {
|
|
347
407
|
id: SemanticType.DeletedTimestamp,
|
|
348
408
|
displayName: 'Soft Delete Timestamp',
|
|
349
409
|
scope: SemanticScope.Property,
|
|
350
|
-
description:
|
|
410
|
+
description: 'When record was marked deleted',
|
|
411
|
+
category: SemanticCategory.Lifecycle,
|
|
351
412
|
applicableDataTypes: ['datetime'],
|
|
352
413
|
},
|
|
353
|
-
[SemanticType.
|
|
354
|
-
id: SemanticType.
|
|
355
|
-
displayName: '
|
|
414
|
+
[SemanticType.DeletedFlag]: {
|
|
415
|
+
id: SemanticType.DeletedFlag,
|
|
416
|
+
displayName: 'Soft Delete Flag',
|
|
356
417
|
scope: SemanticScope.Property,
|
|
357
|
-
description: '
|
|
358
|
-
|
|
418
|
+
description: 'Mark record as deleted',
|
|
419
|
+
category: SemanticCategory.Lifecycle,
|
|
420
|
+
applicableDataTypes: ['boolean'],
|
|
421
|
+
},
|
|
422
|
+
[SemanticType.Version]: {
|
|
423
|
+
id: SemanticType.Version,
|
|
424
|
+
displayName: 'Version Number',
|
|
425
|
+
scope: SemanticScope.Property,
|
|
426
|
+
description: 'Auto-incrementing version counter',
|
|
427
|
+
category: SemanticCategory.Lifecycle,
|
|
428
|
+
applicableDataTypes: ['number'],
|
|
359
429
|
},
|
|
430
|
+
|
|
431
|
+
//
|
|
432
|
+
// Content & Media
|
|
433
|
+
//
|
|
434
|
+
|
|
360
435
|
[SemanticType.Title]: {
|
|
361
436
|
id: SemanticType.Title,
|
|
362
437
|
displayName: 'Record Title',
|
|
363
438
|
scope: SemanticScope.Property,
|
|
364
|
-
description: '
|
|
439
|
+
description: 'Main title or heading',
|
|
440
|
+
category: SemanticCategory.Content,
|
|
365
441
|
applicableDataTypes: ['string'],
|
|
366
442
|
},
|
|
367
|
-
[SemanticType.
|
|
368
|
-
id: SemanticType.
|
|
369
|
-
displayName: '
|
|
443
|
+
[SemanticType.Description]: {
|
|
444
|
+
id: SemanticType.Description,
|
|
445
|
+
displayName: 'Description',
|
|
370
446
|
scope: SemanticScope.Property,
|
|
371
|
-
description:
|
|
447
|
+
description: 'Detailed description text',
|
|
448
|
+
category: SemanticCategory.Content,
|
|
372
449
|
applicableDataTypes: ['string'],
|
|
373
450
|
},
|
|
374
|
-
[SemanticType.
|
|
375
|
-
id: SemanticType.
|
|
376
|
-
displayName: '
|
|
451
|
+
[SemanticType.Summary]: {
|
|
452
|
+
id: SemanticType.Summary,
|
|
453
|
+
displayName: 'Summary',
|
|
377
454
|
scope: SemanticScope.Property,
|
|
378
|
-
description: '
|
|
455
|
+
description: 'Brief summary text',
|
|
456
|
+
category: SemanticCategory.Content,
|
|
379
457
|
applicableDataTypes: ['string'],
|
|
380
458
|
},
|
|
381
|
-
[SemanticType.
|
|
382
|
-
id: SemanticType.
|
|
383
|
-
displayName: '
|
|
459
|
+
[SemanticType.Markdown]: {
|
|
460
|
+
id: SemanticType.Markdown,
|
|
461
|
+
displayName: 'Markdown Content',
|
|
384
462
|
scope: SemanticScope.Property,
|
|
385
|
-
description: '
|
|
386
|
-
|
|
463
|
+
description: 'Formatted text content',
|
|
464
|
+
category: SemanticCategory.Content,
|
|
465
|
+
applicableDataTypes: ['string'],
|
|
466
|
+
},
|
|
467
|
+
[SemanticType.HTML]: {
|
|
468
|
+
id: SemanticType.HTML,
|
|
469
|
+
displayName: 'HTML Content',
|
|
470
|
+
scope: SemanticScope.Property,
|
|
471
|
+
description: 'Rich HTML content',
|
|
472
|
+
category: SemanticCategory.Content,
|
|
473
|
+
applicableDataTypes: ['string'],
|
|
387
474
|
},
|
|
388
475
|
[SemanticType.ImageURL]: {
|
|
389
476
|
id: SemanticType.ImageURL,
|
|
390
477
|
displayName: 'Image URL',
|
|
391
478
|
scope: SemanticScope.Property,
|
|
392
|
-
description: '
|
|
479
|
+
description: 'Link to image file',
|
|
480
|
+
category: SemanticCategory.Content,
|
|
393
481
|
applicableDataTypes: ['string'],
|
|
394
482
|
},
|
|
395
483
|
[SemanticType.FileURL]: {
|
|
396
484
|
id: SemanticType.FileURL,
|
|
397
485
|
displayName: 'File URL',
|
|
398
486
|
scope: SemanticScope.Property,
|
|
399
|
-
description: '
|
|
487
|
+
description: 'Link to file attachment',
|
|
488
|
+
category: SemanticCategory.Content,
|
|
400
489
|
applicableDataTypes: ['string'],
|
|
401
490
|
},
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
id: SemanticType.Markdown,
|
|
411
|
-
displayName: 'Markdown Content',
|
|
491
|
+
|
|
492
|
+
//
|
|
493
|
+
// Business Data
|
|
494
|
+
//
|
|
495
|
+
|
|
496
|
+
[SemanticType.Status]: {
|
|
497
|
+
id: SemanticType.Status,
|
|
498
|
+
displayName: 'Record Status',
|
|
412
499
|
scope: SemanticScope.Property,
|
|
413
|
-
description: '
|
|
500
|
+
description: 'Current state of record',
|
|
501
|
+
category: SemanticCategory.Business,
|
|
414
502
|
applicableDataTypes: ['string'],
|
|
415
503
|
},
|
|
416
|
-
[SemanticType.
|
|
417
|
-
id: SemanticType.
|
|
418
|
-
displayName: '
|
|
504
|
+
[SemanticType.Price]: {
|
|
505
|
+
id: SemanticType.Price,
|
|
506
|
+
displayName: 'Price',
|
|
419
507
|
scope: SemanticScope.Property,
|
|
420
|
-
description: '
|
|
421
|
-
|
|
508
|
+
description: 'Monetary value with currency',
|
|
509
|
+
category: SemanticCategory.Business,
|
|
510
|
+
applicableDataTypes: ['number', 'string'],
|
|
422
511
|
},
|
|
423
|
-
[SemanticType.
|
|
424
|
-
id: SemanticType.
|
|
425
|
-
displayName: '
|
|
512
|
+
[SemanticType.SKU]: {
|
|
513
|
+
id: SemanticType.SKU,
|
|
514
|
+
displayName: 'SKU',
|
|
426
515
|
scope: SemanticScope.Property,
|
|
427
|
-
description: '
|
|
516
|
+
description: 'Product identification code',
|
|
517
|
+
category: SemanticCategory.Business,
|
|
428
518
|
applicableDataTypes: ['string'],
|
|
429
519
|
},
|
|
520
|
+
|
|
521
|
+
//
|
|
522
|
+
// Contact Information
|
|
523
|
+
//
|
|
524
|
+
|
|
430
525
|
[SemanticType.Email]: {
|
|
431
526
|
id: SemanticType.Email,
|
|
432
527
|
displayName: 'Email',
|
|
433
528
|
scope: SemanticScope.Property,
|
|
434
|
-
description: '
|
|
529
|
+
description: 'Email address',
|
|
530
|
+
category: SemanticCategory.Contact,
|
|
435
531
|
applicableDataTypes: ['string'],
|
|
436
532
|
},
|
|
437
533
|
[SemanticType.Phone]: {
|
|
438
534
|
id: SemanticType.Phone,
|
|
439
535
|
displayName: 'Phone',
|
|
440
536
|
scope: SemanticScope.Property,
|
|
441
|
-
description: '
|
|
537
|
+
description: 'Phone number',
|
|
538
|
+
category: SemanticCategory.Contact,
|
|
442
539
|
applicableDataTypes: ['string'],
|
|
443
540
|
},
|
|
444
|
-
[SemanticType.Price]: {
|
|
445
|
-
id: SemanticType.Price,
|
|
446
|
-
displayName: 'Price',
|
|
447
|
-
scope: SemanticScope.Property,
|
|
448
|
-
description: 'Annotates a field as a monetary value with currency support and precision control.',
|
|
449
|
-
applicableDataTypes: ['number', 'string'],
|
|
450
|
-
},
|
|
451
541
|
[SemanticType.URL]: {
|
|
452
542
|
id: SemanticType.URL,
|
|
453
543
|
displayName: 'URL',
|
|
454
544
|
scope: SemanticScope.Property,
|
|
455
|
-
description: '
|
|
545
|
+
description: 'Web address or link',
|
|
546
|
+
category: SemanticCategory.Contact,
|
|
456
547
|
applicableDataTypes: ['string'],
|
|
457
548
|
},
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
549
|
+
|
|
550
|
+
//
|
|
551
|
+
// Classification & Organization
|
|
552
|
+
//
|
|
553
|
+
|
|
554
|
+
[SemanticType.PublicUniqueName]: {
|
|
555
|
+
id: SemanticType.PublicUniqueName,
|
|
556
|
+
displayName: 'Public Unique Name (Slug)',
|
|
461
557
|
scope: SemanticScope.Property,
|
|
462
|
-
description:
|
|
463
|
-
|
|
558
|
+
description: 'URL-friendly unique identifier',
|
|
559
|
+
category: SemanticCategory.Organization,
|
|
464
560
|
applicableDataTypes: ['string'],
|
|
465
561
|
},
|
|
466
|
-
[SemanticType.
|
|
467
|
-
id: SemanticType.
|
|
468
|
-
displayName: '
|
|
469
|
-
scope: SemanticScope.
|
|
470
|
-
description: '
|
|
471
|
-
|
|
562
|
+
[SemanticType.Tags]: {
|
|
563
|
+
id: SemanticType.Tags,
|
|
564
|
+
displayName: 'Tags',
|
|
565
|
+
scope: SemanticScope.Association,
|
|
566
|
+
description: 'Enable tagging functionality',
|
|
567
|
+
category: SemanticCategory.Organization,
|
|
472
568
|
},
|
|
473
|
-
[SemanticType.
|
|
474
|
-
id: SemanticType.
|
|
475
|
-
displayName: '
|
|
569
|
+
[SemanticType.Categories]: {
|
|
570
|
+
id: SemanticType.Categories,
|
|
571
|
+
displayName: 'Categories',
|
|
572
|
+
scope: SemanticScope.Association,
|
|
573
|
+
description: 'Enable categorization functionality',
|
|
574
|
+
category: SemanticCategory.Organization,
|
|
575
|
+
},
|
|
576
|
+
|
|
577
|
+
//
|
|
578
|
+
// Location & Geography
|
|
579
|
+
//
|
|
580
|
+
|
|
581
|
+
[SemanticType.GeospatialCoordinates]: {
|
|
582
|
+
id: SemanticType.GeospatialCoordinates,
|
|
583
|
+
displayName: 'Geospatial Coordinates',
|
|
476
584
|
scope: SemanticScope.Property,
|
|
477
|
-
description: '
|
|
585
|
+
description: 'Location coordinates',
|
|
586
|
+
category: SemanticCategory.Location,
|
|
478
587
|
applicableDataTypes: ['string'],
|
|
479
588
|
},
|
|
589
|
+
|
|
590
|
+
//
|
|
591
|
+
// Computed Values
|
|
592
|
+
//
|
|
593
|
+
|
|
480
594
|
[SemanticType.Calculated]: {
|
|
481
595
|
id: SemanticType.Calculated,
|
|
482
596
|
displayName: 'Calculated',
|
|
483
597
|
scope: SemanticScope.Property,
|
|
484
|
-
description: '
|
|
598
|
+
description: 'Auto-calculated field value',
|
|
599
|
+
category: SemanticCategory.Computed,
|
|
485
600
|
applicableDataTypes: ['string'],
|
|
486
601
|
},
|
|
487
602
|
[SemanticType.Derived]: {
|
|
488
603
|
id: SemanticType.Derived,
|
|
489
604
|
displayName: 'Derived',
|
|
490
605
|
scope: SemanticScope.Property,
|
|
491
|
-
description: '
|
|
606
|
+
description: 'Value derived from other fields',
|
|
607
|
+
category: SemanticCategory.Computed,
|
|
492
608
|
applicableDataTypes: ['string'],
|
|
493
609
|
},
|
|
610
|
+
}
|
|
494
611
|
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
612
|
+
/**
|
|
613
|
+
* Helper function to get all semantics grouped by category.
|
|
614
|
+
* Useful for organizing semantics in UI dropdowns and forms.
|
|
615
|
+
*/
|
|
616
|
+
export const getSemanticsByCategory = (): Record<SemanticCategory, DataSemantic[]> => {
|
|
617
|
+
const result: Record<SemanticCategory, DataSemantic[]> = {
|
|
618
|
+
[SemanticCategory.Identity]: [],
|
|
619
|
+
[SemanticCategory.Lifecycle]: [],
|
|
620
|
+
[SemanticCategory.Content]: [],
|
|
621
|
+
[SemanticCategory.Business]: [],
|
|
622
|
+
[SemanticCategory.Contact]: [],
|
|
623
|
+
[SemanticCategory.Organization]: [],
|
|
624
|
+
[SemanticCategory.Location]: [],
|
|
625
|
+
[SemanticCategory.Computed]: [],
|
|
626
|
+
}
|
|
498
627
|
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
displayName: 'Categories',
|
|
514
|
-
scope: SemanticScope.Association,
|
|
515
|
-
description: 'Annotates an association as supporting category functionality.',
|
|
516
|
-
},
|
|
628
|
+
Object.values(DataSemantics).forEach((semantic) => {
|
|
629
|
+
result[semantic.category].push(semantic)
|
|
630
|
+
})
|
|
631
|
+
|
|
632
|
+
return result
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
/**
|
|
636
|
+
* Helper function to get semantics for a specific category.
|
|
637
|
+
* @param category The category to filter by
|
|
638
|
+
* @returns Array of semantics in the specified category
|
|
639
|
+
*/
|
|
640
|
+
export const getSemanticsByCategoryType = (category: SemanticCategory): DataSemantic[] => {
|
|
641
|
+
return Object.values(DataSemantics).filter((semantic) => semantic.category === category)
|
|
517
642
|
}
|
|
518
643
|
|
|
519
644
|
/**
|
|
@@ -8,7 +8,10 @@ import {
|
|
|
8
8
|
type ExposedEntity,
|
|
9
9
|
} from '../../../src/index.js'
|
|
10
10
|
|
|
11
|
-
test.group('ApiModel.createSchema()', () => {
|
|
11
|
+
test.group('ApiModel.createSchema()', (g) => {
|
|
12
|
+
g.tests.forEach((test) => {
|
|
13
|
+
test.tags(['@modeling', '@api', '@schema'])
|
|
14
|
+
})
|
|
12
15
|
test('creates a schema with default values', ({ assert }) => {
|
|
13
16
|
const schema = ApiModel.createSchema()
|
|
14
17
|
assert.equal(schema.kind, ApiModelKind)
|
|
@@ -64,7 +67,11 @@ test.group('ApiModel.createSchema()', () => {
|
|
|
64
67
|
})
|
|
65
68
|
})
|
|
66
69
|
|
|
67
|
-
test.group('ApiModel.constructor()', () => {
|
|
70
|
+
test.group('ApiModel.constructor()', (g) => {
|
|
71
|
+
g.tests.forEach((test) => {
|
|
72
|
+
test.tags(['@modeling', '@api', '@creation'])
|
|
73
|
+
})
|
|
74
|
+
|
|
68
75
|
test('creates an instance with default values', ({ assert }) => {
|
|
69
76
|
const model = new ApiModel()
|
|
70
77
|
assert.equal(model.kind, ApiModelKind)
|
|
@@ -133,7 +140,10 @@ test.group('ApiModel.constructor()', () => {
|
|
|
133
140
|
})
|
|
134
141
|
})
|
|
135
142
|
|
|
136
|
-
test.group('ApiModel.toJSON()', () => {
|
|
143
|
+
test.group('ApiModel.toJSON()', (g) => {
|
|
144
|
+
g.tests.forEach((test) => {
|
|
145
|
+
test.tags(['@modeling', '@api', '@serialization'])
|
|
146
|
+
})
|
|
137
147
|
test('serializes default values', ({ assert }) => {
|
|
138
148
|
const model = new ApiModel()
|
|
139
149
|
const json = model.toJSON()
|
|
@@ -181,7 +191,10 @@ test.group('ApiModel.toJSON()', () => {
|
|
|
181
191
|
})
|
|
182
192
|
})
|
|
183
193
|
|
|
184
|
-
test.group('ApiModel.exposeEntity()', () => {
|
|
194
|
+
test.group('ApiModel.exposeEntity()', (g) => {
|
|
195
|
+
g.tests.forEach((test) => {
|
|
196
|
+
test.tags(['@modeling', '@api'])
|
|
197
|
+
})
|
|
185
198
|
test('exposes a new entity', ({ assert }) => {
|
|
186
199
|
const model = new ApiModel()
|
|
187
200
|
const entityKey = 'new-entity'
|
|
@@ -228,7 +241,10 @@ test.group('ApiModel.exposeEntity()', () => {
|
|
|
228
241
|
})
|
|
229
242
|
})
|
|
230
243
|
|
|
231
|
-
test.group('ApiModel.removeEntity()', () => {
|
|
244
|
+
test.group('ApiModel.removeEntity()', (g) => {
|
|
245
|
+
g.tests.forEach((test) => {
|
|
246
|
+
test.tags(['@modeling', '@api'])
|
|
247
|
+
})
|
|
232
248
|
test('removes an existing entity', ({ assert }) => {
|
|
233
249
|
const model = new ApiModel()
|
|
234
250
|
const entityKey = 'entity-to-remove'
|
|
@@ -274,7 +290,10 @@ test.group('ApiModel.removeEntity()', () => {
|
|
|
274
290
|
})
|
|
275
291
|
})
|
|
276
292
|
|
|
277
|
-
test.group('ApiModel.getExposedEntity()', () => {
|
|
293
|
+
test.group('ApiModel.getExposedEntity()', (g) => {
|
|
294
|
+
g.tests.forEach((test) => {
|
|
295
|
+
test.tags(['@modeling', '@api'])
|
|
296
|
+
})
|
|
278
297
|
test('returns an existing exposed entity', ({ assert }) => {
|
|
279
298
|
const model = new ApiModel()
|
|
280
299
|
const entityKey = 'get-entity'
|