@api-client/core 0.15.0 → 0.16.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.
Files changed (126) hide show
  1. package/TESTING_READY.md +114 -0
  2. package/TESTING_SETUP.md +198 -0
  3. package/build/src/modeling/Semantics.d.ts +126 -2
  4. package/build/src/modeling/Semantics.d.ts.map +1 -1
  5. package/build/src/modeling/Semantics.js +281 -13
  6. package/build/src/modeling/Semantics.js.map +1 -1
  7. package/build/src/modeling/definitions/Calculated.d.ts +54 -0
  8. package/build/src/modeling/definitions/Calculated.d.ts.map +1 -0
  9. package/build/src/modeling/definitions/Calculated.js +31 -0
  10. package/build/src/modeling/definitions/Calculated.js.map +1 -0
  11. package/build/src/modeling/definitions/Categories.d.ts +60 -0
  12. package/build/src/modeling/definitions/Categories.d.ts.map +1 -0
  13. package/build/src/modeling/definitions/Categories.js +33 -0
  14. package/build/src/modeling/definitions/Categories.js.map +1 -0
  15. package/build/src/modeling/definitions/Derived.d.ts +54 -0
  16. package/build/src/modeling/definitions/Derived.d.ts.map +1 -0
  17. package/build/src/modeling/definitions/Derived.js +31 -0
  18. package/build/src/modeling/definitions/Derived.js.map +1 -0
  19. package/build/src/modeling/definitions/Description.d.ts +36 -0
  20. package/build/src/modeling/definitions/Description.d.ts.map +1 -0
  21. package/build/src/modeling/definitions/Description.js +28 -0
  22. package/build/src/modeling/definitions/Description.js.map +1 -0
  23. package/build/src/modeling/definitions/Email.d.ts +66 -0
  24. package/build/src/modeling/definitions/Email.d.ts.map +1 -0
  25. package/build/src/modeling/definitions/Email.js +33 -0
  26. package/build/src/modeling/definitions/Email.js.map +1 -0
  27. package/build/src/modeling/definitions/GeospatialCoordinates.d.ts +212 -0
  28. package/build/src/modeling/definitions/GeospatialCoordinates.d.ts.map +1 -0
  29. package/build/src/modeling/definitions/GeospatialCoordinates.js +129 -0
  30. package/build/src/modeling/definitions/GeospatialCoordinates.js.map +1 -0
  31. package/build/src/modeling/definitions/HTML.d.ts +88 -0
  32. package/build/src/modeling/definitions/HTML.d.ts.map +1 -0
  33. package/build/src/modeling/definitions/HTML.js +42 -0
  34. package/build/src/modeling/definitions/HTML.js.map +1 -0
  35. package/build/src/modeling/definitions/Markdown.d.ts +84 -0
  36. package/build/src/modeling/definitions/Markdown.d.ts.map +1 -0
  37. package/build/src/modeling/definitions/Markdown.js +41 -0
  38. package/build/src/modeling/definitions/Markdown.js.map +1 -0
  39. package/build/src/modeling/definitions/Password.d.ts +112 -0
  40. package/build/src/modeling/definitions/Password.d.ts.map +1 -0
  41. package/build/src/modeling/definitions/Password.js +57 -0
  42. package/build/src/modeling/definitions/Password.js.map +1 -0
  43. package/build/src/modeling/definitions/Phone.d.ts +83 -0
  44. package/build/src/modeling/definitions/Phone.d.ts.map +1 -0
  45. package/build/src/modeling/definitions/Phone.js +39 -0
  46. package/build/src/modeling/definitions/Phone.js.map +1 -0
  47. package/build/src/modeling/definitions/Price.d.ts +102 -0
  48. package/build/src/modeling/definitions/Price.d.ts.map +1 -0
  49. package/build/src/modeling/definitions/Price.js +99 -0
  50. package/build/src/modeling/definitions/Price.js.map +1 -0
  51. package/build/src/modeling/definitions/PublicUniqueName.d.ts +69 -0
  52. package/build/src/modeling/definitions/PublicUniqueName.d.ts.map +1 -0
  53. package/build/src/modeling/definitions/PublicUniqueName.js +34 -0
  54. package/build/src/modeling/definitions/PublicUniqueName.js.map +1 -0
  55. package/build/src/modeling/definitions/SKU.d.ts +127 -0
  56. package/build/src/modeling/definitions/SKU.d.ts.map +1 -0
  57. package/build/src/modeling/definitions/SKU.js +142 -0
  58. package/build/src/modeling/definitions/SKU.js.map +1 -0
  59. package/build/src/modeling/definitions/Status.d.ts +150 -0
  60. package/build/src/modeling/definitions/Status.d.ts.map +1 -0
  61. package/build/src/modeling/definitions/Status.js +60 -0
  62. package/build/src/modeling/definitions/Status.js.map +1 -0
  63. package/build/src/modeling/definitions/Summary.d.ts +53 -0
  64. package/build/src/modeling/definitions/Summary.d.ts.map +1 -0
  65. package/build/src/modeling/definitions/Summary.js +50 -0
  66. package/build/src/modeling/definitions/Summary.js.map +1 -0
  67. package/build/src/modeling/definitions/Tags.d.ts +52 -0
  68. package/build/src/modeling/definitions/Tags.d.ts.map +1 -0
  69. package/build/src/modeling/definitions/Tags.js +32 -0
  70. package/build/src/modeling/definitions/Tags.js.map +1 -0
  71. package/build/src/modeling/definitions/URL.d.ts +68 -0
  72. package/build/src/modeling/definitions/URL.d.ts.map +1 -0
  73. package/build/src/modeling/definitions/URL.js +37 -0
  74. package/build/src/modeling/definitions/URL.js.map +1 -0
  75. package/build/src/modeling/validation/semantic_validation.d.ts +4 -0
  76. package/build/src/modeling/validation/semantic_validation.d.ts.map +1 -1
  77. package/build/src/modeling/validation/semantic_validation.js +32 -1
  78. package/build/src/modeling/validation/semantic_validation.js.map +1 -1
  79. package/build/tsconfig.tsbuildinfo +1 -1
  80. package/data/models/example-generator-api.json +9 -9
  81. package/package.json +1 -1
  82. package/src/modeling/Semantics.ts +297 -14
  83. package/src/modeling/definitions/Calculated.ts +76 -0
  84. package/src/modeling/definitions/Categories.ts +84 -0
  85. package/src/modeling/definitions/Derived.ts +76 -0
  86. package/src/modeling/definitions/Description.ts +55 -0
  87. package/src/modeling/definitions/Email.ts +90 -0
  88. package/src/modeling/definitions/GeospatialCoordinates.ts +274 -0
  89. package/src/modeling/definitions/HTML.ts +121 -0
  90. package/src/modeling/definitions/Markdown.ts +116 -0
  91. package/src/modeling/definitions/Password.ts +156 -0
  92. package/src/modeling/definitions/Phone.ts +116 -0
  93. package/src/modeling/definitions/Price.examples.md +158 -0
  94. package/src/modeling/definitions/Price.ts +180 -0
  95. package/src/modeling/definitions/PublicUniqueName.ts +98 -0
  96. package/src/modeling/definitions/SKU.examples.md +230 -0
  97. package/src/modeling/definitions/SKU.ts +254 -0
  98. package/src/modeling/definitions/Status.ts +227 -0
  99. package/src/modeling/definitions/Summary.ts +73 -0
  100. package/src/modeling/definitions/Tags.ts +75 -0
  101. package/src/modeling/definitions/URL.ts +96 -0
  102. package/src/modeling/validation/semantic_validation.ts +35 -1
  103. package/tests/example-test-setup.ts +133 -0
  104. package/tests/template-node.spec.ts +75 -0
  105. package/tests/test-utils.ts +293 -0
  106. package/tests/unit/modeling/definitions/calculated.spec.ts +33 -0
  107. package/tests/unit/modeling/definitions/categories.spec.ts +38 -0
  108. package/tests/unit/modeling/definitions/derived.spec.ts +34 -0
  109. package/tests/unit/modeling/definitions/description.spec.ts +38 -0
  110. package/tests/unit/modeling/definitions/email.spec.ts +38 -0
  111. package/tests/unit/modeling/definitions/geospatial-coordinates.spec.ts +41 -0
  112. package/tests/unit/modeling/definitions/html.spec.ts +38 -0
  113. package/tests/unit/modeling/definitions/markdown.spec.ts +38 -0
  114. package/tests/unit/modeling/definitions/password.spec.ts +347 -0
  115. package/tests/unit/modeling/definitions/phone.spec.ts +38 -0
  116. package/tests/unit/modeling/definitions/price.spec.ts +465 -0
  117. package/tests/unit/modeling/definitions/public-unique-name.spec.ts +38 -0
  118. package/tests/unit/modeling/definitions/sku.spec.ts +240 -0
  119. package/tests/unit/modeling/definitions/status.spec.ts +37 -0
  120. package/tests/unit/modeling/definitions/summary.spec.ts +36 -0
  121. package/tests/unit/modeling/definitions/tags.spec.ts +38 -0
  122. package/tests/unit/modeling/definitions/url.spec.ts +38 -0
  123. package/tests/unit/modeling/domain_property.spec.ts +106 -0
  124. package/tests/unit/modeling/domain_validation.spec.ts +5 -5
  125. package/tests/unit/modeling/semantic-configs.spec.ts +569 -0
  126. package/tests/unit/modeling/semantics.spec.ts +52 -0
@@ -42062,16 +42062,16 @@
42062
42062
  "@id": "#209"
42063
42063
  },
42064
42064
  {
42065
- "@id": "#191"
42065
+ "@id": "#200"
42066
42066
  },
42067
42067
  {
42068
- "@id": "#197"
42068
+ "@id": "#191"
42069
42069
  },
42070
42070
  {
42071
42071
  "@id": "#194"
42072
42072
  },
42073
42073
  {
42074
- "@id": "#200"
42074
+ "@id": "#197"
42075
42075
  },
42076
42076
  {
42077
42077
  "@id": "#203"
@@ -43436,7 +43436,7 @@
43436
43436
  "doc:ExternalDomainElement",
43437
43437
  "doc:DomainElement"
43438
43438
  ],
43439
- "doc:raw": "countryCode: \"BE\"\ngraydonEnterpriseId: 1057155523\nregistrationId: \"0422319093\"\nvatNumber: \"BE0422319093\"\ngraydonCompanyId: \"0422319093\"\nisBranchOffice: false\n",
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
  {
@@ -43478,7 +43478,7 @@
43478
43478
  "doc:ExternalDomainElement",
43479
43479
  "doc:DomainElement"
43480
43480
  ],
43481
- "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",
43481
+ "doc:raw": "class: '3'\ndescription: '150 - 300'\nnumberOfFte: 5500\nnumberOfEmployees: 5232\n",
43482
43482
  "core:mediaType": "application/yaml",
43483
43483
  "sourcemaps:sources": [
43484
43484
  {
@@ -43499,7 +43499,7 @@
43499
43499
  "doc:ExternalDomainElement",
43500
43500
  "doc:DomainElement"
43501
43501
  ],
43502
- "doc:raw": "class: '3'\ndescription: '150 - 300'\nnumberOfFte: 5500\nnumberOfEmployees: 5232\n",
43502
+ "doc:raw": "countryCode: \"BE\"\ngraydonEnterpriseId: 1057155523\nregistrationId: \"0422319093\"\nvatNumber: \"BE0422319093\"\ngraydonCompanyId: \"0422319093\"\nisBranchOffice: false\n",
43503
43503
  "core:mediaType": "application/yaml",
43504
43504
  "sourcemaps:sources": [
43505
43505
  {
@@ -44756,7 +44756,7 @@
44756
44756
  {
44757
44757
  "@id": "#193/source-map/lexical/element_0",
44758
44758
  "sourcemaps:element": "amf://id#193",
44759
- "sourcemaps:value": "[(1,0)-(7,0)]"
44759
+ "sourcemaps:value": "[(1,0)-(10,0)]"
44760
44760
  },
44761
44761
  {
44762
44762
  "@id": "#196/source-map/lexical/element_0",
@@ -44766,12 +44766,12 @@
44766
44766
  {
44767
44767
  "@id": "#199/source-map/lexical/element_0",
44768
44768
  "sourcemaps:element": "amf://id#199",
44769
- "sourcemaps:value": "[(1,0)-(10,0)]"
44769
+ "sourcemaps:value": "[(1,0)-(5,0)]"
44770
44770
  },
44771
44771
  {
44772
44772
  "@id": "#202/source-map/lexical/element_0",
44773
44773
  "sourcemaps:element": "amf://id#202",
44774
- "sourcemaps:value": "[(1,0)-(5,0)]"
44774
+ "sourcemaps:value": "[(1,0)-(7,0)]"
44775
44775
  },
44776
44776
  {
44777
44777
  "@id": "#205/source-map/lexical/element_0",
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@api-client/core",
3
3
  "description": "The API Client's core client library. Works in NodeJS and in a ES enabled browser.",
4
- "version": "0.15.0",
4
+ "version": "0.16.0",
5
5
  "license": "Apache-2.0",
6
6
  "exports": {
7
7
  "./browser.js": {
@@ -6,13 +6,19 @@ import type { DomainPropertyType } from './DataFormat.js'
6
6
  * Using a string enum makes it easy to add or remove semantics in a single place.
7
7
  */
8
8
  export enum SemanticType {
9
+ //
9
10
  // Entity-Level Semantics
11
+ //
12
+
10
13
  /**
11
14
  * Designates a Data Entity that represents users of the system.
12
15
  */
13
16
  User = 'Semantic#User',
14
17
 
18
+ //
15
19
  // Property-Level Semantics
20
+ //
21
+
16
22
  /**
17
23
  * Annotates the field as the user password.
18
24
  * The runtime should treat this field with special care,
@@ -43,11 +49,19 @@ export enum SemanticType {
43
49
  */
44
50
  DeletedFlag = 'Semantic#DeletedFlag',
45
51
  /**
46
- * Designates a Data Property as a unique public identifier for a resource.
52
+ * Designates a Data Property as a unique public identifier for a resource (the slug).
47
53
  * This is often used in URLs to provide a user-friendly way to access the resource.
48
54
  * For example, a blog post might have a public unique name like "my-first-post".
55
+ * A URL-friendly text field. The runtime automatically generates a unique, URL-safe string from another field (like a title or name). The user needs to specify which field is used to generate
56
+ * the slug.
49
57
  */
50
58
  PublicUniqueName = 'Semantic#PublicUniqueName',
59
+ /**
60
+ * A semantic that describes a title of an article, blog post, and so on. This semantic is used with
61
+ * the `PublicUniqueName` to determine which field is responsible for the slug generation. However,
62
+ * we may add more automation related to the `title` property in the future.
63
+ */
64
+ Title = 'Semantic#Title',
51
65
  /**
52
66
  * Designates a Data Property as the `role` of a user within the system.
53
67
  * This is used to define the user's permissions and access levels.
@@ -56,13 +70,140 @@ export enum SemanticType {
56
70
  * Roles are defined on the entity as enums, or as a string property with a controlled vocabulary.
57
71
  */
58
72
  UserRole = 'Semantic#UserRole',
73
+ /**
74
+ * A text or enum field to represent the state of a record (e.g., `draft`, `published`, `pending_review`, `archived`).
75
+ *
76
+ * Defined behaviors:
77
+ * - State-Based Filtering: Automatically prevents public users from seeing records in a draft state.
78
+ * - State Transitions: In principle, the runtime should prevent the user from skipping some states.
79
+ * For example, when the record is in the `draft` state, it cannot be moved to the `archived` state without publishing it first. However,
80
+ * we do not have enough customer feedback to design this functionality correctly right now, so
81
+ * it serves as a placeholder semantic annotation.
82
+ */
83
+ Status = 'Semantic#Status',
84
+
85
+ /**
86
+ * Annotates an integer field that automatically increments.
87
+ * The runtime automatically increments this number on every update, providing a simple way
88
+ * to track changes and implement optimistic locking to prevent mid-air collisions.
89
+ */
90
+ Version = 'Semantic#Version',
91
+
92
+ /**
93
+ * Annotates a field that holds a reference to an image data via an URL.
94
+ * The application + runtime should validate that the input is a well-formed URL.
95
+ */
96
+ ImageURL = 'Semantic#ImageURL',
97
+
98
+ /**
99
+ * Annotates a field that holds a reference to a file object via an URL. Ity is distinct from the
100
+ * `ImageURL` semantic as it implicitly states that the target is non-image, binary data (an attachment, for example).
101
+ */
102
+ FileURL = 'Semantic#FileURL',
103
+
104
+ /**
105
+ * Annotates the field as a markdown-interpreted field.
106
+ * When an object is created, the runtime performs additional sanitization to prevent XSS attacks.
107
+ *
108
+ * The annotation describes whether the data should be translated to the HTML output when
109
+ * record is read or the original MD content should be returned.
110
+ */
111
+ Markdown = 'Semantic#Markdown',
112
+
113
+ /**
114
+ * Annotates the field as containing HTML content.
115
+ * The runtime performs sanitization to prevent XSS attacks and validates HTML structure.
116
+ *
117
+ * The annotation describes whether the data should be rendered as HTML output when
118
+ * record is read or the original HTML content should be returned.
119
+ */
120
+ HTML = 'Semantic#HTML',
121
+
122
+ /**
123
+ * Annotates a field that holds geospatial coordinate data (latitude/longitude).
124
+ * The runtime automatically generates API capabilities for location-based queries,
125
+ * such as "find all restaurants within a 5-mile radius."
126
+ *
127
+ * The field should contain coordinate data in a standard format:
128
+ * - "40.7128,-74.0060" (lat,lon)
129
+ * - "POINT(-74.0060 40.7128)" (PostGIS format)
130
+ * - "40.7128°N, 74.0060°W" (degree format)
131
+ *
132
+ * Defined behaviors:
133
+ * - Spatial Indexing: The runtime automatically creates spatial indexes for efficient location-based queries
134
+ * - Distance Queries: Enables API endpoints for finding records within specified distances
135
+ * - Coordinate Validation: Validates that the input follows proper coordinate format
136
+ * - PostGIS Integration: When using PostgreSQL, automatically maps to PostGIS geometry types
137
+ */
138
+ GeospatialCoordinates = 'Semantic#GeospatialCoordinates',
139
+
140
+ /**
141
+ * Annotates a field as an email address with validation and verification options.
142
+ */
143
+ Email = 'Semantic#Email',
144
+ /**
145
+ * Annotates a field as a phone number with validation and formatting options.
146
+ */
147
+ Phone = 'Semantic#Phone',
148
+ /**
149
+ * Annotates a field as a monetary value with currency support and precision control.
150
+ * Can store simple decimal amounts or complex objects with amount and currency.
151
+ * Enforces proper decimal handling to avoid floating-point errors.
152
+ */
153
+ Price = 'Semantic#Price',
154
+ /**
155
+ * Annotates a field as a URL with validation and allowed protocols.
156
+ */
157
+ URL = 'Semantic#URL',
158
+ /**
159
+ * Annotates a field as a Stock Keeping Unit (SKU).
160
+ * Enforces uniqueness at the database level, critical for product catalogs.
161
+ * Provides automatic validation and formatting for product identification codes.
162
+ */
163
+ SKU = 'Semantic#SKU',
164
+ /**
165
+ * Annotates a field as a long-form description.
166
+ */
167
+ Description = 'Semantic#Description',
168
+ /**
169
+ * Annotates a field as a short summary.
170
+ */
171
+ Summary = 'Semantic#Summary',
172
+ /**
173
+ * Annotates a field as a calculated value based on a formula.
174
+ */
175
+ Calculated = 'Semantic#Calculated',
176
+ /**
177
+ * Annotates a field as derived from other fields.
178
+ */
179
+ Derived = 'Semantic#Derived',
180
+
181
+ //
59
182
  // Association-Level Semantics
183
+ //
184
+
60
185
  /**
61
186
  * Designates an association that links a resource to a "User" entity instance.
62
187
  * This is used to indicate ownership of the resource for access control purposes.
63
188
  * For example, a blog post might have a resource owner identifier that points to the user who created it.
189
+ *
190
+ * Defined behaviors:
191
+ * - Automatic Ownership: When a new record is created, this field is automatically populated with the ID of the authenticated user. It also creates a foreign relationship to the `User` semantic object.
192
+ * - Scoped Access: The runtime automatically filters list and read operations to show only records where the Owner matches the current user. update and delete operations are similarly restricted.
64
193
  */
65
194
  ResourceOwnerIdentifier = 'Semantic#ResourceOwnerIdentifier',
195
+ /**
196
+ * Annotates an association as supporting tag functionality.
197
+ * Applied to associations between entities to enable tagging behavior.
198
+ * For example, a Product-Category association with Tags semantic enables product tagging.
199
+ */
200
+ Tags = 'Semantic#Tags',
201
+ /**
202
+ * Annotates an association as supporting category functionality.
203
+ * Applied to associations between entities to enable categorization behavior.
204
+ * For example, a Product-Category association with Categories semantic enables product categorization.
205
+ */
206
+ Categories = 'Semantic#Categories',
66
207
  }
67
208
 
68
209
  /**
@@ -165,7 +306,10 @@ export type DataSemantic = EntitySemantic | PropertySemantic | AssociationSemant
165
306
  * This acts as a central registry for the application.
166
307
  */
167
308
  export const DataSemantics: Record<SemanticType, DataSemantic> = {
309
+ //
168
310
  // Entity-Level Definitions
311
+ //
312
+
169
313
  [SemanticType.User]: {
170
314
  id: SemanticType.User,
171
315
  displayName: 'User Entity',
@@ -173,7 +317,10 @@ export const DataSemantics: Record<SemanticType, DataSemantic> = {
173
317
  description: 'Designates an entity that represents system users, crucial for authentication and authorization.',
174
318
  },
175
319
 
320
+ //
176
321
  // Property-Level Definitions
322
+ //
323
+
177
324
  [SemanticType.Password]: {
178
325
  id: SemanticType.Password,
179
326
  displayName: 'User Password',
@@ -203,6 +350,55 @@ export const DataSemantics: Record<SemanticType, DataSemantic> = {
203
350
  description: "Marks a field as the field that contains object's deletion timestamp.",
204
351
  applicableDataTypes: ['datetime'],
205
352
  },
353
+ [SemanticType.PublicUniqueName]: {
354
+ id: SemanticType.PublicUniqueName,
355
+ displayName: 'Public Unique Name (Slug)',
356
+ scope: SemanticScope.Property,
357
+ description: 'A user-friendly, unique public identifier for a resource, often used in URLs.',
358
+ applicableDataTypes: ['string'],
359
+ },
360
+ [SemanticType.Title]: {
361
+ id: SemanticType.Title,
362
+ displayName: 'Record Title',
363
+ scope: SemanticScope.Property,
364
+ description: 'A title for the record. Used as a source for the PublicUniqueName semantic.',
365
+ applicableDataTypes: ['string'],
366
+ },
367
+ [SemanticType.UserRole]: {
368
+ id: SemanticType.UserRole,
369
+ displayName: 'User Role Field',
370
+ scope: SemanticScope.Property,
371
+ description: "A text or enum field that defines the user's role for role-based authorization.",
372
+ applicableDataTypes: ['string'],
373
+ },
374
+ [SemanticType.Status]: {
375
+ id: SemanticType.Status,
376
+ displayName: 'Record Status',
377
+ scope: SemanticScope.Property,
378
+ description: 'A text or enum field to represent the state of a record.',
379
+ applicableDataTypes: ['string'],
380
+ },
381
+ [SemanticType.Version]: {
382
+ id: SemanticType.Version,
383
+ displayName: 'Version Number',
384
+ scope: SemanticScope.Property,
385
+ description: 'An integer field that automatically increments on every update.',
386
+ applicableDataTypes: ['number'],
387
+ },
388
+ [SemanticType.ImageURL]: {
389
+ id: SemanticType.ImageURL,
390
+ displayName: 'Image URL',
391
+ scope: SemanticScope.Property,
392
+ description: 'Annotates a field that holds a reference to an image data via an URL.',
393
+ applicableDataTypes: ['string'],
394
+ },
395
+ [SemanticType.FileURL]: {
396
+ id: SemanticType.FileURL,
397
+ displayName: 'File URL',
398
+ scope: SemanticScope.Property,
399
+ description: 'Annotates a field that holds a reference to a file object via an URL (non-image binary data).',
400
+ applicableDataTypes: ['string'],
401
+ },
206
402
  [SemanticType.DeletedFlag]: {
207
403
  id: SemanticType.DeletedFlag,
208
404
  displayName: 'Soft Delete Flag',
@@ -210,27 +406,114 @@ export const DataSemantics: Record<SemanticType, DataSemantic> = {
210
406
  description: 'A boolean property that marks the object as deleted without physically removing it.',
211
407
  applicableDataTypes: ['boolean'],
212
408
  },
213
- [SemanticType.ResourceOwnerIdentifier]: {
214
- id: SemanticType.ResourceOwnerIdentifier,
215
- displayName: 'Resource Owner Identifier',
216
- scope: SemanticScope.Association,
217
- description: 'Links a resource to a "User" entity instance, indicating ownership for access control.',
409
+ [SemanticType.Markdown]: {
410
+ id: SemanticType.Markdown,
411
+ displayName: 'Markdown Content',
412
+ scope: SemanticScope.Property,
413
+ description: 'A text field that contains markdown content.',
414
+ applicableDataTypes: ['string'],
218
415
  },
219
- [SemanticType.PublicUniqueName]: {
220
- id: SemanticType.PublicUniqueName,
221
- displayName: 'Public Unique Name (Slug)',
416
+ [SemanticType.HTML]: {
417
+ id: SemanticType.HTML,
418
+ displayName: 'HTML Content',
222
419
  scope: SemanticScope.Property,
223
- description: 'A user-friendly, unique public identifier for a resource, often used in URLs.',
420
+ description: 'Annotates a field that contains HTML content.',
224
421
  applicableDataTypes: ['string'],
225
422
  },
226
- [SemanticType.UserRole]: {
227
- id: SemanticType.UserRole,
228
- displayName: 'User Role Field',
423
+ [SemanticType.GeospatialCoordinates]: {
424
+ id: SemanticType.GeospatialCoordinates,
425
+ displayName: 'Geospatial Coordinates',
426
+ scope: SemanticScope.Property,
427
+ description: 'Annotates a field that holds geospatial coordinate data (latitude/longitude).',
428
+ applicableDataTypes: ['string'],
429
+ },
430
+ [SemanticType.Email]: {
431
+ id: SemanticType.Email,
432
+ displayName: 'Email',
433
+ scope: SemanticScope.Property,
434
+ description: 'Annotates a field as an email address with validation and verification options.',
435
+ applicableDataTypes: ['string'],
436
+ },
437
+ [SemanticType.Phone]: {
438
+ id: SemanticType.Phone,
439
+ displayName: 'Phone',
440
+ scope: SemanticScope.Property,
441
+ description: 'Annotates a field as a phone number with validation and formatting options.',
442
+ applicableDataTypes: ['string'],
443
+ },
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
+ [SemanticType.URL]: {
452
+ id: SemanticType.URL,
453
+ displayName: 'URL',
454
+ scope: SemanticScope.Property,
455
+ description: 'Annotates a field as a URL with validation and allowed protocols.',
456
+ applicableDataTypes: ['string'],
457
+ },
458
+ [SemanticType.SKU]: {
459
+ id: SemanticType.SKU,
460
+ displayName: 'SKU',
229
461
  scope: SemanticScope.Property,
230
462
  description:
231
- 'A text field that is recognized by the runtime as a role of a user in the API. Used with the role-based authorization strategy.',
463
+ 'Annotates a field as a Stock Keeping Unit (SKU). Enforces uniqueness at the database level, critical for product catalogs. Provides automatic validation and formatting for product identification codes.',
464
+ applicableDataTypes: ['string'],
465
+ },
466
+ [SemanticType.Description]: {
467
+ id: SemanticType.Description,
468
+ displayName: 'Description',
469
+ scope: SemanticScope.Property,
470
+ description: 'Annotates a field as a long-form description.',
471
+ applicableDataTypes: ['string'],
472
+ },
473
+ [SemanticType.Summary]: {
474
+ id: SemanticType.Summary,
475
+ displayName: 'Summary',
476
+ scope: SemanticScope.Property,
477
+ description: 'Annotates a field as a short summary.',
478
+ applicableDataTypes: ['string'],
479
+ },
480
+ [SemanticType.Calculated]: {
481
+ id: SemanticType.Calculated,
482
+ displayName: 'Calculated',
483
+ scope: SemanticScope.Property,
484
+ description: 'Annotates a field as a calculated value based on a formula.',
485
+ applicableDataTypes: ['string'],
486
+ },
487
+ [SemanticType.Derived]: {
488
+ id: SemanticType.Derived,
489
+ displayName: 'Derived',
490
+ scope: SemanticScope.Property,
491
+ description: 'Annotates a field as derived from other fields.',
232
492
  applicableDataTypes: ['string'],
233
493
  },
494
+
495
+ //
496
+ // Association-Level Definitions
497
+ //
498
+
499
+ [SemanticType.ResourceOwnerIdentifier]: {
500
+ id: SemanticType.ResourceOwnerIdentifier,
501
+ displayName: 'Resource Owner Identifier',
502
+ scope: SemanticScope.Association,
503
+ description: 'Links a resource to a "User" entity instance, indicating ownership for access control.',
504
+ },
505
+ [SemanticType.Tags]: {
506
+ id: SemanticType.Tags,
507
+ displayName: 'Tags',
508
+ scope: SemanticScope.Association,
509
+ description: 'Annotates an association as supporting tag functionality.',
510
+ },
511
+ [SemanticType.Categories]: {
512
+ id: SemanticType.Categories,
513
+ displayName: 'Categories',
514
+ scope: SemanticScope.Association,
515
+ description: 'Annotates an association as supporting category functionality.',
516
+ },
234
517
  }
235
518
 
236
519
  /**
@@ -0,0 +1,76 @@
1
+ import type { AppliedDataSemantic } from '../Semantics.js'
2
+ import { SemanticType } from '../Semantics.js'
3
+
4
+ /**
5
+ * Configuration options for the Calculated semantic.
6
+ * Controls formula, dependencies, and recalculation behavior.
7
+ *
8
+ * Use Calculated when you need mathematical operations, aggregations, or complex business logic.
9
+ */
10
+ export interface CalculatedConfig {
11
+ /**
12
+ * Formula to calculate the value (e.g., 'price * quantity').
13
+ */
14
+ formula: string
15
+ /**
16
+ * List of field names this calculation depends on.
17
+ */
18
+ dependencies?: string[]
19
+ /**
20
+ * Whether to recalculate the value on update (default: true).
21
+ */
22
+ recalculateOnUpdate?: boolean
23
+ /**
24
+ * Whether to allow manual override of the calculated value.
25
+ */
26
+ allowManualOverride?: boolean
27
+ /**
28
+ * Custom metadata for the calculated field.
29
+ */
30
+ metadata?: Record<string, unknown>
31
+ /**
32
+ * Index signature to allow additional properties.
33
+ */
34
+ [key: string]: unknown
35
+ }
36
+
37
+ /**
38
+ * Type-safe configuration for Calculated semantic.
39
+ */
40
+ export interface AppliedCalculatedSemantic extends AppliedDataSemantic {
41
+ id: SemanticType.Calculated
42
+ config?: CalculatedConfig
43
+ }
44
+
45
+ /**
46
+ * Type guard to check if a semantic is a Calculated semantic.
47
+ */
48
+ export const isCalculatedSemantic = (semantic: AppliedDataSemantic): semantic is AppliedCalculatedSemantic => {
49
+ return semantic.id === SemanticType.Calculated
50
+ }
51
+
52
+ /**
53
+ * Helper function to create a Calculated semantic with configuration.
54
+ */
55
+ export const createCalculatedSemantic = (config: CalculatedConfig): AppliedCalculatedSemantic => {
56
+ const mergedConfig = {
57
+ ...DEFAULT_CALCULATED_CONFIG,
58
+ ...config,
59
+ }
60
+ if (config.metadata) {
61
+ mergedConfig.metadata = { ...config.metadata }
62
+ }
63
+
64
+ return {
65
+ id: SemanticType.Calculated,
66
+ config: mergedConfig,
67
+ }
68
+ }
69
+
70
+ /**
71
+ * Default configuration for Calculated semantic.
72
+ */
73
+ export const DEFAULT_CALCULATED_CONFIG: Partial<CalculatedConfig> = {
74
+ recalculateOnUpdate: true,
75
+ allowManualOverride: false,
76
+ }
@@ -0,0 +1,84 @@
1
+ import type { AppliedDataSemantic } from '../Semantics.js'
2
+ import { SemanticType } from '../Semantics.js'
3
+
4
+ /**
5
+ * Configuration options for the Categories semantic.
6
+ * Controls allowed categories, hierarchy, and formatting for associations.
7
+ */
8
+ export interface CategoriesConfig {
9
+ /**
10
+ * List of allowed categories.
11
+ */
12
+ allowedCategories?: string[]
13
+ /**
14
+ * Whether to allow custom categories not in the allowedCategories list.
15
+ */
16
+ allowCustomCategories?: boolean
17
+ /**
18
+ * Whether to allow hierarchical categories (tree structure).
19
+ */
20
+ allowHierarchy?: boolean
21
+ /**
22
+ * Maximum depth of the category hierarchy.
23
+ */
24
+ maxDepth?: number
25
+ /**
26
+ * Whether categories are case sensitive.
27
+ */
28
+ caseSensitive?: boolean
29
+ /**
30
+ * Whether to allow Unicode characters in categories.
31
+ */
32
+ allowUnicode?: boolean
33
+ /**
34
+ * Custom metadata for the categories association.
35
+ */
36
+ metadata?: Record<string, unknown>
37
+ /**
38
+ * Index signature to allow additional properties.
39
+ */
40
+ [key: string]: unknown
41
+ }
42
+
43
+ /**
44
+ * Type-safe configuration for Categories semantic.
45
+ */
46
+ export interface AppliedCategoriesSemantic extends AppliedDataSemantic {
47
+ id: SemanticType.Categories
48
+ config?: CategoriesConfig
49
+ }
50
+
51
+ /**
52
+ * Type guard to check if a semantic is a Categories semantic.
53
+ */
54
+ export const isCategoriesSemantic = (semantic: AppliedDataSemantic): semantic is AppliedCategoriesSemantic => {
55
+ return semantic.id === SemanticType.Categories
56
+ }
57
+
58
+ /**
59
+ * Helper function to create a Categories semantic with configuration.
60
+ */
61
+ export const createCategoriesSemantic = (config: CategoriesConfig = {}): AppliedCategoriesSemantic => {
62
+ const mergedConfig = {
63
+ ...DEFAULT_CATEGORIES_CONFIG,
64
+ ...config,
65
+ }
66
+ if (config.metadata) {
67
+ mergedConfig.metadata = { ...config.metadata }
68
+ }
69
+
70
+ return {
71
+ id: SemanticType.Categories,
72
+ config: mergedConfig,
73
+ }
74
+ }
75
+
76
+ /**
77
+ * Default configuration for Categories semantic.
78
+ */
79
+ export const DEFAULT_CATEGORIES_CONFIG: CategoriesConfig = {
80
+ allowCustomCategories: true,
81
+ allowHierarchy: true,
82
+ caseSensitive: false,
83
+ allowUnicode: false,
84
+ }