@api-client/core 0.15.1 → 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 +11 -11
  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
@@ -0,0 +1,254 @@
1
+ import type { AppliedDataSemantic } from '../Semantics.js'
2
+ import { SemanticType } from '../Semantics.js'
3
+
4
+ /**
5
+ * Supported SKU validation modes.
6
+ */
7
+ export type SKUValidationMode = 'strict' | 'lenient' | 'custom'
8
+
9
+ /**
10
+ * Supported SKU case transformation modes.
11
+ */
12
+ export type SKUCaseMode = 'uppercase' | 'lowercase' | 'preserve'
13
+
14
+ /**
15
+ * Configuration options for the SKU semantic.
16
+ * Controls SKU validation, formatting, uniqueness enforcement, and pattern matching.
17
+ */
18
+ export interface SKUConfig {
19
+ /**
20
+ * The validation mode for SKU format.
21
+ *
22
+ * - 'strict': Enforces alphanumeric characters with optional hyphens/underscores
23
+ * - 'lenient': Allows more special characters but still validates basic format
24
+ * - 'custom': Uses custom regex pattern defined in `customPattern`
25
+ */
26
+ validationMode?: SKUValidationMode
27
+
28
+ /**
29
+ * Custom regex pattern for SKU validation when using 'custom' validation mode.
30
+ * Only used when validationMode is 'custom'.
31
+ */
32
+ customPattern?: string
33
+
34
+ /**
35
+ * Case transformation to apply to SKUs.
36
+ * - 'uppercase': Convert to uppercase (recommended for consistency)
37
+ * - 'lowercase': Convert to lowercase
38
+ * - 'preserve': Keep original case
39
+ */
40
+ caseMode?: SKUCaseMode
41
+
42
+ /**
43
+ * Prefix to automatically add to SKUs if not present.
44
+ * Useful for organizing SKUs by category (e.g., 'PROD-', 'SKU-').
45
+ */
46
+ prefix?: string
47
+
48
+ /**
49
+ * Whether to enforce global uniqueness across all entities.
50
+ * When true, creates unique database constraints.
51
+ * Default: true
52
+ */
53
+ enforceUniqueness?: boolean
54
+
55
+ /**
56
+ * Whether to auto-generate SKUs when not provided.
57
+ * When true, generates SKUs based on other fields or random values.
58
+ * Default: false
59
+ */
60
+ autoGenerate?: boolean
61
+
62
+ /**
63
+ * Field name to use as source for auto-generation.
64
+ * Only used when autoGenerate is true.
65
+ * If not specified, uses random generation.
66
+ */
67
+ autoGenerateSource?: string
68
+
69
+ /**
70
+ * Whether to validate that SKU doesn't conflict with reserved words or patterns.
71
+ * Default: true
72
+ */
73
+ validateReservedWords?: boolean
74
+
75
+ /**
76
+ * List of reserved SKU values that cannot be used.
77
+ * Common examples: 'ADMIN', 'TEST', 'NULL', 'DEFAULT'
78
+ */
79
+ reservedValues?: string[]
80
+
81
+ /**
82
+ * Custom metadata for the SKU field.
83
+ */
84
+ metadata?: Record<string, unknown>
85
+
86
+ /**
87
+ * Index signature to allow additional properties.
88
+ */
89
+ [key: string]: unknown
90
+ }
91
+
92
+ /**
93
+ * Type-safe configuration for SKU semantic.
94
+ */
95
+ export interface AppliedSKUSemantic extends AppliedDataSemantic {
96
+ id: SemanticType.SKU
97
+ config?: SKUConfig
98
+ }
99
+
100
+ /**
101
+ * Type guard to check if a semantic is a SKU semantic.
102
+ */
103
+ export const isSKUSemantic = (semantic: AppliedDataSemantic): semantic is AppliedSKUSemantic => {
104
+ return semantic.id === SemanticType.SKU
105
+ }
106
+
107
+ /**
108
+ * Helper function to create a SKU semantic with configuration.
109
+ */
110
+ export const createSKUSemantic = (config: SKUConfig = {}): AppliedSKUSemantic => {
111
+ const mergedConfig = {
112
+ ...DEFAULT_SKU_CONFIG,
113
+ ...config,
114
+ }
115
+
116
+ // Merge metadata separately
117
+ if (config.metadata) {
118
+ mergedConfig.metadata = { ...config.metadata }
119
+ }
120
+
121
+ return {
122
+ id: SemanticType.SKU,
123
+ config: mergedConfig,
124
+ }
125
+ }
126
+
127
+ /**
128
+ * Default configuration for SKU semantic.
129
+ * Optimized for common product catalog use cases.
130
+ */
131
+ export const DEFAULT_SKU_CONFIG: SKUConfig = {
132
+ validationMode: 'strict',
133
+ caseMode: 'uppercase',
134
+ enforceUniqueness: true,
135
+ autoGenerate: false,
136
+ validateReservedWords: true,
137
+ reservedValues: ['ADMIN', 'TEST', 'NULL', 'DEFAULT', 'UNDEFINED', 'SAMPLE', 'DEMO'],
138
+ }
139
+
140
+ /**
141
+ * Predefined configurations for common use cases.
142
+ */
143
+ export const SKU_PRESETS = {
144
+ /**
145
+ * Standard product SKU with strict validation and uppercase formatting.
146
+ */
147
+ PRODUCT_STANDARD: createSKUSemantic({
148
+ validationMode: 'strict',
149
+ caseMode: 'uppercase',
150
+ prefix: 'PROD-',
151
+ enforceUniqueness: true,
152
+ }),
153
+
154
+ /**
155
+ * Simple SKU configuration for basic catalogs.
156
+ */
157
+ SIMPLE: createSKUSemantic({
158
+ validationMode: 'lenient',
159
+ caseMode: 'preserve',
160
+ enforceUniqueness: true,
161
+ }),
162
+
163
+ /**
164
+ * Auto-generating SKU from product name.
165
+ */
166
+ AUTO_GENERATE: createSKUSemantic({
167
+ validationMode: 'strict',
168
+ caseMode: 'uppercase',
169
+ autoGenerate: true,
170
+ autoGenerateSource: 'name',
171
+ enforceUniqueness: true,
172
+ }),
173
+
174
+ /**
175
+ * Flexible SKU for variable product types.
176
+ */
177
+ FLEXIBLE: createSKUSemantic({
178
+ validationMode: 'lenient',
179
+ caseMode: 'preserve',
180
+ enforceUniqueness: true,
181
+ validateReservedWords: false,
182
+ }),
183
+ } as const
184
+
185
+ /**
186
+ * Helper function to validate a SKU configuration.
187
+ */
188
+ export const validateSKUConfig = (config: SKUConfig): string[] => {
189
+ const errors: string[] = []
190
+
191
+ if (config.validationMode === 'custom' && !config.customPattern) {
192
+ errors.push('customPattern is required when validationMode is custom')
193
+ }
194
+
195
+ if (config.customPattern) {
196
+ try {
197
+ new RegExp(config.customPattern)
198
+ } catch {
199
+ errors.push('customPattern must be a valid regular expression')
200
+ }
201
+ }
202
+
203
+ if (config.prefix && config.prefix.length === 0) {
204
+ errors.push('prefix cannot be empty string')
205
+ }
206
+
207
+ if (config.autoGenerateSource && !config.autoGenerate) {
208
+ errors.push('autoGenerate must be true when autoGenerateSource is specified')
209
+ }
210
+
211
+ return errors
212
+ }
213
+
214
+ /**
215
+ * Helper function to validate SKU value against configuration.
216
+ */
217
+ export const validateSKUValue = (value: string, config: SKUConfig = DEFAULT_SKU_CONFIG): string[] => {
218
+ const errors: string[] = []
219
+ const mergedConfig = { ...DEFAULT_SKU_CONFIG, ...config }
220
+
221
+ if (!value || typeof value !== 'string') {
222
+ errors.push('SKU value must be a non-empty string')
223
+ return errors
224
+ }
225
+
226
+ if (mergedConfig.validateReservedWords && mergedConfig.reservedValues) {
227
+ const normalizedValue = value.toUpperCase()
228
+ if (mergedConfig.reservedValues.some((reserved) => reserved.toUpperCase() === normalizedValue)) {
229
+ errors.push(`SKU cannot use reserved value: ${value}`)
230
+ }
231
+ }
232
+
233
+ // Validation pattern checks
234
+ if (mergedConfig.validationMode === 'strict') {
235
+ if (!/^[A-Za-z0-9_-]+$/.test(value)) {
236
+ errors.push('SKU can only contain alphanumeric characters, hyphens, and underscores')
237
+ }
238
+ } else if (mergedConfig.validationMode === 'lenient') {
239
+ if (!/^[A-Za-z0-9_.-]+$/.test(value)) {
240
+ errors.push('SKU contains invalid characters')
241
+ }
242
+ } else if (mergedConfig.validationMode === 'custom' && mergedConfig.customPattern) {
243
+ try {
244
+ const regex = new RegExp(mergedConfig.customPattern)
245
+ if (!regex.test(value)) {
246
+ errors.push('SKU does not match the required pattern')
247
+ }
248
+ } catch {
249
+ errors.push('Invalid custom pattern configuration')
250
+ }
251
+ }
252
+
253
+ return errors
254
+ }
@@ -0,0 +1,227 @@
1
+ import type { AppliedDataSemantic } from '../Semantics.js'
2
+ import { SemanticType } from '../Semantics.js'
3
+
4
+ /**
5
+ * Configuration options for the Status semantic.
6
+ * These options control state management and workflow behavior.
7
+ */
8
+ export interface StatusConfig {
9
+ /**
10
+ * Allowed states for this status field.
11
+ * Only required when the field doesn't have enum values defined in the schema.
12
+ * If enum values are defined in DomainProperty > Schema, those values will be used instead.
13
+ */
14
+ allowedStates?: string[]
15
+
16
+ /**
17
+ * Default state when creating new records.
18
+ * Must be one of the allowedStates (if specified) or enum values from the schema.
19
+ */
20
+ defaultState: string
21
+
22
+ /**
23
+ * State transitions configuration.
24
+ * Maps from current state to array of allowed next states.
25
+ */
26
+ transitions?: Record<string, string[]>
27
+
28
+ /**
29
+ * State-specific behaviors and permissions.
30
+ */
31
+ stateBehaviors?: Record<
32
+ string,
33
+ {
34
+ /**
35
+ * Whether records in this state are publicly visible.
36
+ * Defaults to true if not specified.
37
+ */
38
+ isPublic?: boolean
39
+
40
+ /**
41
+ * Whether records in this state can be edited.
42
+ * Defaults to true if not specified.
43
+ */
44
+ isEditable?: boolean
45
+
46
+ /**
47
+ * Whether records in this state can be deleted.
48
+ * Defaults to false if not specified.
49
+ */
50
+ isDeletable?: boolean
51
+
52
+ /**
53
+ * Whether this state requires approval before transition.
54
+ * Defaults to false if not specified.
55
+ */
56
+ requiresApproval?: boolean
57
+
58
+ /**
59
+ * Custom display name for this state.
60
+ */
61
+ displayName?: string
62
+
63
+ /**
64
+ * Custom description for this state.
65
+ */
66
+ description?: string
67
+
68
+ /**
69
+ * Color or visual indicator for this state.
70
+ */
71
+ color?: string
72
+
73
+ /**
74
+ * Icon for this state.
75
+ */
76
+ icon?: string
77
+ }
78
+ >
79
+
80
+ /**
81
+ * Workflow configuration for status management.
82
+ */
83
+ workflow?: {
84
+ /**
85
+ * Whether status changes require approval.
86
+ * Defaults to false if not specified.
87
+ */
88
+ requiresApproval?: boolean
89
+
90
+ /**
91
+ * Roles that can approve status changes.
92
+ * Required if requiresApproval is true.
93
+ */
94
+ approvalRoles?: string[]
95
+
96
+ /**
97
+ * Whether to send notifications on status changes.
98
+ * Defaults to false if not specified.
99
+ */
100
+ sendNotifications?: boolean
101
+
102
+ /**
103
+ * Notification channels to use.
104
+ */
105
+ notificationChannels?: ('email' | 'sms' | 'push' | 'webhook')[]
106
+
107
+ /**
108
+ * Whether to log status change history.
109
+ * Defaults to true if not specified.
110
+ */
111
+ logHistory?: boolean
112
+
113
+ /**
114
+ * Whether to allow bulk status changes.
115
+ * Defaults to false if not specified.
116
+ */
117
+ allowBulkChanges?: boolean
118
+ }
119
+
120
+ /**
121
+ * Auto-transitions based on conditions.
122
+ */
123
+ autoTransitions?: {
124
+ /**
125
+ * Current state that triggers the auto-transition.
126
+ */
127
+ from: string
128
+
129
+ /**
130
+ * Target state to transition to.
131
+ */
132
+ to: string
133
+
134
+ /**
135
+ * Condition that triggers the transition.
136
+ * Examples: "after 24 hours", "when approved", "when payment received"
137
+ */
138
+ condition: string
139
+
140
+ /**
141
+ * Whether this auto-transition requires approval.
142
+ * Defaults to false if not specified.
143
+ */
144
+ requiresApproval?: boolean
145
+ }[]
146
+
147
+ /**
148
+ * Custom metadata for the status field.
149
+ */
150
+ metadata?: Record<string, unknown>
151
+
152
+ /**
153
+ * Index signature to allow additional properties.
154
+ */
155
+ [key: string]: unknown
156
+ }
157
+
158
+ /**
159
+ * Type-safe configuration for Status semantic.
160
+ */
161
+ export interface AppliedStatusSemantic extends AppliedDataSemantic {
162
+ id: SemanticType.Status
163
+ config?: StatusConfig
164
+ }
165
+
166
+ /**
167
+ * Type guard to check if a semantic is a Status semantic.
168
+ */
169
+ export const isStatusSemantic = (semantic: AppliedDataSemantic): semantic is AppliedStatusSemantic => {
170
+ return semantic.id === SemanticType.Status
171
+ }
172
+
173
+ /**
174
+ * Helper function to create a Status semantic with configuration.
175
+ */
176
+ export const createStatusSemantic = (config: Partial<StatusConfig> = {}): AppliedStatusSemantic => {
177
+ const mergedConfig = {
178
+ ...DEFAULT_STATUS_CONFIG,
179
+ ...config,
180
+ // Deep merge nested objects
181
+ stateBehaviors: config.stateBehaviors
182
+ ? { ...DEFAULT_STATUS_CONFIG.stateBehaviors, ...config.stateBehaviors }
183
+ : DEFAULT_STATUS_CONFIG.stateBehaviors,
184
+ workflow: config.workflow
185
+ ? { ...DEFAULT_STATUS_CONFIG.workflow, ...config.workflow }
186
+ : DEFAULT_STATUS_CONFIG.workflow,
187
+ }
188
+
189
+ if (config.metadata) {
190
+ mergedConfig.metadata = { ...config.metadata }
191
+ }
192
+
193
+ return {
194
+ id: SemanticType.Status,
195
+ config: mergedConfig,
196
+ }
197
+ }
198
+
199
+ /**
200
+ * Default configuration for Status semantic.
201
+ */
202
+ export const DEFAULT_STATUS_CONFIG: StatusConfig = {
203
+ defaultState: 'draft',
204
+ stateBehaviors: {
205
+ draft: {
206
+ isPublic: false,
207
+ isEditable: true,
208
+ isDeletable: true,
209
+ },
210
+ published: {
211
+ isPublic: true,
212
+ isEditable: true,
213
+ isDeletable: false,
214
+ },
215
+ archived: {
216
+ isPublic: false,
217
+ isEditable: false,
218
+ isDeletable: false,
219
+ },
220
+ },
221
+ workflow: {
222
+ requiresApproval: false,
223
+ sendNotifications: false,
224
+ logHistory: true,
225
+ allowBulkChanges: false,
226
+ },
227
+ }
@@ -0,0 +1,73 @@
1
+ import type { AppliedDataSemantic } from '../Semantics.js'
2
+ import { SemanticType } from '../Semantics.js'
3
+
4
+ /**
5
+ * Configuration for the Summary semantic.
6
+ * Summary is a simple semantic without configuration options.
7
+ */
8
+ export interface SummaryConfig {
9
+ /**
10
+ * Custom metadata for the summary field.
11
+ */
12
+ metadata?: Record<string, unknown>
13
+ /**
14
+ * Index signature to allow additional properties.
15
+ */
16
+ [key: string]: unknown
17
+ }
18
+
19
+ /**
20
+ * Default configuration for the Summary semantic.
21
+ */
22
+ export const DEFAULT_SUMMARY_CONFIG: SummaryConfig = {}
23
+
24
+ /**
25
+ * Creates a Summary semantic application.
26
+ * @param config - Optional configuration (not used for simple semantic)
27
+ * @returns AppliedDataSemantic for Summary
28
+ */
29
+ export const createSummarySemantic = (config?: SummaryConfig): AppliedDataSemantic => ({
30
+ id: SemanticType.Summary,
31
+ config: config ? { ...DEFAULT_SUMMARY_CONFIG, ...config } : { ...DEFAULT_SUMMARY_CONFIG },
32
+ })
33
+
34
+ /**
35
+ * Type guard to check if a semantic is a Summary semantic.
36
+ * @param semantic - The semantic to check
37
+ * @returns True if the semantic is a Summary semantic
38
+ */
39
+ export const isSummarySemantic = (
40
+ semantic: AppliedDataSemantic
41
+ ): semantic is AppliedDataSemantic & { id: SemanticType.Summary } => semantic.id === SemanticType.Summary
42
+
43
+ /**
44
+ * Extracts the configuration from a Summary semantic application.
45
+ * @param semantic - The semantic application
46
+ * @returns The Summary configuration or undefined if not a Summary semantic
47
+ */
48
+ export const getSummaryConfig = (semantic: AppliedDataSemantic): SummaryConfig | undefined => {
49
+ if (!isSummarySemantic(semantic)) {
50
+ return undefined
51
+ }
52
+ return semantic.config as SummaryConfig | undefined
53
+ }
54
+
55
+ /**
56
+ * Validates Summary semantic configuration.
57
+ * @returns True if the configuration is valid
58
+ */
59
+ export const validateSummaryConfig = (): boolean => {
60
+ // No validation needed for simple semantic
61
+ return true
62
+ }
63
+
64
+ /**
65
+ * Merges Summary configurations, with the second config taking precedence.
66
+ * @param base - The base configuration
67
+ * @param override - The configuration to merge on top
68
+ * @returns Merged configuration
69
+ */
70
+ export const mergeSummaryConfig = (base: SummaryConfig, override: SummaryConfig): SummaryConfig => {
71
+ // No merging needed for simple semantic
72
+ return { ...base, ...override }
73
+ }
@@ -0,0 +1,75 @@
1
+ import type { AppliedDataSemantic } from '../Semantics.js'
2
+ import { SemanticType } from '../Semantics.js'
3
+
4
+ /**
5
+ * Configuration options for the Tags semantic.
6
+ * Controls allowed tags, validation, and formatting for associations.
7
+ */
8
+ export interface TagsConfig {
9
+ /**
10
+ * List of allowed tags.
11
+ */
12
+ allowedTags?: string[]
13
+ /**
14
+ * Whether to allow custom tags not in the allowedTags list.
15
+ */
16
+ allowCustomTags?: boolean
17
+ /**
18
+ * Whether tags are case sensitive.
19
+ */
20
+ caseSensitive?: boolean
21
+ /**
22
+ * Whether to allow Unicode characters in tags.
23
+ */
24
+ allowUnicode?: boolean
25
+ /**
26
+ * Custom metadata for the tags association.
27
+ */
28
+ metadata?: Record<string, unknown>
29
+ /**
30
+ * Index signature to allow additional properties.
31
+ */
32
+ [key: string]: unknown
33
+ }
34
+
35
+ /**
36
+ * Type-safe configuration for Tags semantic.
37
+ */
38
+ export interface AppliedTagsSemantic extends AppliedDataSemantic {
39
+ id: SemanticType.Tags
40
+ config?: TagsConfig
41
+ }
42
+
43
+ /**
44
+ * Type guard to check if a semantic is a Tags semantic.
45
+ */
46
+ export const isTagsSemantic = (semantic: AppliedDataSemantic): semantic is AppliedTagsSemantic => {
47
+ return semantic.id === SemanticType.Tags
48
+ }
49
+
50
+ /**
51
+ * Helper function to create a Tags semantic with configuration.
52
+ */
53
+ export const createTagsSemantic = (config: TagsConfig = {}): AppliedTagsSemantic => {
54
+ const mergedConfig = {
55
+ ...DEFAULT_TAGS_CONFIG,
56
+ ...config,
57
+ }
58
+ if (config.metadata) {
59
+ mergedConfig.metadata = { ...config.metadata }
60
+ }
61
+
62
+ return {
63
+ id: SemanticType.Tags,
64
+ config: mergedConfig,
65
+ }
66
+ }
67
+
68
+ /**
69
+ * Default configuration for Tags semantic.
70
+ */
71
+ export const DEFAULT_TAGS_CONFIG: TagsConfig = {
72
+ allowCustomTags: true,
73
+ caseSensitive: false,
74
+ allowUnicode: false,
75
+ }