@api-client/core 0.17.4 → 0.17.5
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/build/src/modeling/Semantics.d.ts +1 -1
- package/build/src/modeling/Semantics.d.ts.map +1 -1
- package/build/src/modeling/Semantics.js +6 -6
- package/build/src/modeling/Semantics.js.map +1 -1
- package/build/src/modeling/definitions/{Price.d.ts → Currency.d.ts} +24 -24
- package/build/src/modeling/definitions/Currency.d.ts.map +1 -0
- package/build/src/modeling/definitions/{Price.js → Currency.js} +18 -18
- package/build/src/modeling/definitions/Currency.js.map +1 -0
- package/build/src/modeling/definitions/HTML.d.ts +17 -4
- package/build/src/modeling/definitions/HTML.d.ts.map +1 -1
- package/build/src/modeling/definitions/HTML.js +0 -1
- package/build/src/modeling/definitions/HTML.js.map +1 -1
- package/build/src/modeling/definitions/Markdown.d.ts +12 -4
- package/build/src/modeling/definitions/Markdown.d.ts.map +1 -1
- package/build/src/modeling/definitions/Markdown.js +0 -1
- package/build/src/modeling/definitions/Markdown.js.map +1 -1
- package/build/src/modeling/definitions/Status.d.ts +1 -1
- package/build/src/modeling/definitions/Status.d.ts.map +1 -1
- package/build/src/modeling/definitions/Status.js +1 -0
- package/build/src/modeling/definitions/Status.js.map +1 -1
- package/build/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/modeling/Semantics.ts +6 -6
- package/src/modeling/definitions/{Price.examples.md → Currency.examples.md} +12 -12
- package/src/modeling/definitions/{Price.ts → Currency.ts} +26 -26
- package/src/modeling/definitions/HTML.ts +17 -5
- package/src/modeling/definitions/Markdown.ts +12 -5
- package/src/modeling/definitions/Status.ts +2 -1
- package/tests/unit/modeling/definitions/{price.spec.ts → currency.spec.ts} +114 -114
- package/tests/unit/modeling/definitions/description.spec.ts +0 -2
- package/tests/unit/modeling/semantic-configs.spec.ts +44 -44
- package/tests/unit/modeling/semantics.spec.ts +10 -1
- package/build/src/modeling/definitions/Price.d.ts.map +0 -1
- package/build/src/modeling/definitions/Price.js.map +0 -1
|
@@ -69,12 +69,12 @@ import {
|
|
|
69
69
|
} from '../../../src/modeling/definitions/URL.js'
|
|
70
70
|
|
|
71
71
|
import {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
type
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
} from '../../../src/modeling/definitions/
|
|
72
|
+
createCurrencySemantic,
|
|
73
|
+
isCurrencySemantic,
|
|
74
|
+
type CurrencyConfig,
|
|
75
|
+
DEFAULT_CURRENCY_CONFIG,
|
|
76
|
+
CURRENCY_PRESETS,
|
|
77
|
+
} from '../../../src/modeling/definitions/Currency.js'
|
|
78
78
|
|
|
79
79
|
import {
|
|
80
80
|
createSKUSemantic,
|
|
@@ -322,27 +322,27 @@ test.group('Semantic Configurations', () => {
|
|
|
322
322
|
assert.isTrue(isURLSemantic(semantic))
|
|
323
323
|
})
|
|
324
324
|
|
|
325
|
-
test('
|
|
326
|
-
const semantic =
|
|
327
|
-
assert.equal(semantic.id, SemanticType.
|
|
328
|
-
assert.deepEqual(semantic.config,
|
|
325
|
+
test('Currency: should create semantic with default config', ({ assert }) => {
|
|
326
|
+
const semantic = createCurrencySemantic()
|
|
327
|
+
assert.equal(semantic.id, SemanticType.Currency)
|
|
328
|
+
assert.deepEqual(semantic.config, DEFAULT_CURRENCY_CONFIG)
|
|
329
329
|
})
|
|
330
330
|
|
|
331
|
-
test('
|
|
332
|
-
const config:
|
|
331
|
+
test('Currency: should create semantic with custom config', ({ assert }) => {
|
|
332
|
+
const config: CurrencyConfig = {
|
|
333
333
|
storageFormat: 'complex_object',
|
|
334
334
|
allowedCurrencies: ['USD', 'EUR'],
|
|
335
335
|
decimalPlaces: 4,
|
|
336
336
|
allowNegative: true,
|
|
337
337
|
}
|
|
338
|
-
const semantic =
|
|
339
|
-
assert.equal(semantic.id, SemanticType.
|
|
340
|
-
assert.deepEqual(semantic.config, { ...
|
|
338
|
+
const semantic = createCurrencySemantic(config)
|
|
339
|
+
assert.equal(semantic.id, SemanticType.Currency)
|
|
340
|
+
assert.deepEqual(semantic.config, { ...DEFAULT_CURRENCY_CONFIG, ...config })
|
|
341
341
|
})
|
|
342
342
|
|
|
343
|
-
test('
|
|
344
|
-
const semantic =
|
|
345
|
-
assert.isTrue(
|
|
343
|
+
test('Currency: should identify currency semantic', ({ assert }) => {
|
|
344
|
+
const semantic = createCurrencySemantic()
|
|
345
|
+
assert.isTrue(isCurrencySemantic(semantic))
|
|
346
346
|
})
|
|
347
347
|
|
|
348
348
|
test('SKU: should create semantic with default config', ({ assert }) => {
|
|
@@ -491,33 +491,33 @@ test.group('Semantic Configurations', () => {
|
|
|
491
491
|
assert.isTrue(isCategoriesSemantic(semantic))
|
|
492
492
|
})
|
|
493
493
|
|
|
494
|
-
test('
|
|
495
|
-
const semantic =
|
|
496
|
-
assert.equal(semantic.id, SemanticType.
|
|
497
|
-
assert.deepEqual(semantic.config,
|
|
494
|
+
test('Currency: should create semantic with default config', ({ assert }) => {
|
|
495
|
+
const semantic = createCurrencySemantic()
|
|
496
|
+
assert.equal(semantic.id, SemanticType.Currency)
|
|
497
|
+
assert.deepEqual(semantic.config, DEFAULT_CURRENCY_CONFIG)
|
|
498
498
|
})
|
|
499
499
|
|
|
500
|
-
test('
|
|
501
|
-
const config:
|
|
500
|
+
test('Currency: should create semantic with custom config', ({ assert }) => {
|
|
501
|
+
const config: CurrencyConfig = {
|
|
502
502
|
storageFormat: 'complex_object',
|
|
503
503
|
allowedCurrencies: ['USD', 'EUR'],
|
|
504
504
|
decimalPlaces: 4,
|
|
505
505
|
allowNegative: true,
|
|
506
506
|
}
|
|
507
|
-
const semantic =
|
|
508
|
-
assert.equal(semantic.id, SemanticType.
|
|
509
|
-
assert.deepEqual(semantic.config, { ...
|
|
507
|
+
const semantic = createCurrencySemantic(config)
|
|
508
|
+
assert.equal(semantic.id, SemanticType.Currency)
|
|
509
|
+
assert.deepEqual(semantic.config, { ...DEFAULT_CURRENCY_CONFIG, ...config })
|
|
510
510
|
})
|
|
511
511
|
|
|
512
|
-
test('
|
|
513
|
-
const semantic =
|
|
514
|
-
assert.isTrue(
|
|
512
|
+
test('Currency: should identify currency semantic', ({ assert }) => {
|
|
513
|
+
const semantic = createCurrencySemantic()
|
|
514
|
+
assert.isTrue(isCurrencySemantic(semantic))
|
|
515
515
|
})
|
|
516
516
|
|
|
517
|
-
test('
|
|
518
|
-
Object.values(
|
|
519
|
-
assert.isTrue(
|
|
520
|
-
assert.equal(preset.id, SemanticType.
|
|
517
|
+
test('Currency: presets should be valid', ({ assert }) => {
|
|
518
|
+
Object.values(CURRENCY_PRESETS).forEach((preset) => {
|
|
519
|
+
assert.isTrue(isCurrencySemantic(preset))
|
|
520
|
+
assert.equal(preset.id, SemanticType.Currency)
|
|
521
521
|
})
|
|
522
522
|
})
|
|
523
523
|
|
|
@@ -532,38 +532,38 @@ test.group('Semantic Configurations', () => {
|
|
|
532
532
|
const emailSemantic = createEmailSemantic()
|
|
533
533
|
const phoneSemantic = createPhoneSemantic()
|
|
534
534
|
const statusSemantic = createStatusSemantic()
|
|
535
|
-
const
|
|
535
|
+
const currencySemantic = createCurrencySemantic()
|
|
536
536
|
const skuSemantic = createSKUSemantic()
|
|
537
537
|
|
|
538
538
|
// Each should only be identified as its own type
|
|
539
539
|
assert.isTrue(isEmailSemantic(emailSemantic))
|
|
540
540
|
assert.isFalse(isEmailSemantic(phoneSemantic))
|
|
541
541
|
assert.isFalse(isEmailSemantic(statusSemantic))
|
|
542
|
-
assert.isFalse(isEmailSemantic(
|
|
542
|
+
assert.isFalse(isEmailSemantic(currencySemantic))
|
|
543
543
|
assert.isFalse(isEmailSemantic(skuSemantic))
|
|
544
544
|
|
|
545
545
|
assert.isFalse(isPhoneSemantic(emailSemantic))
|
|
546
546
|
assert.isTrue(isPhoneSemantic(phoneSemantic))
|
|
547
547
|
assert.isFalse(isPhoneSemantic(statusSemantic))
|
|
548
|
-
assert.isFalse(isPhoneSemantic(
|
|
548
|
+
assert.isFalse(isPhoneSemantic(currencySemantic))
|
|
549
549
|
assert.isFalse(isPhoneSemantic(skuSemantic))
|
|
550
550
|
|
|
551
551
|
assert.isFalse(isStatusSemantic(emailSemantic))
|
|
552
552
|
assert.isFalse(isStatusSemantic(phoneSemantic))
|
|
553
553
|
assert.isTrue(isStatusSemantic(statusSemantic))
|
|
554
|
-
assert.isFalse(isStatusSemantic(
|
|
554
|
+
assert.isFalse(isStatusSemantic(currencySemantic))
|
|
555
555
|
assert.isFalse(isStatusSemantic(skuSemantic))
|
|
556
556
|
|
|
557
|
-
assert.isFalse(
|
|
558
|
-
assert.isFalse(
|
|
559
|
-
assert.isFalse(
|
|
560
|
-
assert.isTrue(
|
|
561
|
-
assert.isFalse(
|
|
557
|
+
assert.isFalse(isCurrencySemantic(emailSemantic))
|
|
558
|
+
assert.isFalse(isCurrencySemantic(phoneSemantic))
|
|
559
|
+
assert.isFalse(isCurrencySemantic(statusSemantic))
|
|
560
|
+
assert.isTrue(isCurrencySemantic(currencySemantic))
|
|
561
|
+
assert.isFalse(isCurrencySemantic(skuSemantic))
|
|
562
562
|
|
|
563
563
|
assert.isFalse(isSKUSemantic(emailSemantic))
|
|
564
564
|
assert.isFalse(isSKUSemantic(phoneSemantic))
|
|
565
565
|
assert.isFalse(isSKUSemantic(statusSemantic))
|
|
566
|
-
assert.isFalse(isSKUSemantic(
|
|
566
|
+
assert.isFalse(isSKUSemantic(currencySemantic))
|
|
567
567
|
assert.isTrue(isSKUSemantic(skuSemantic))
|
|
568
568
|
})
|
|
569
569
|
})
|
|
@@ -31,7 +31,7 @@ test.group('Semantics', () => {
|
|
|
31
31
|
assert.equal(SemanticType.FileURL, 'Semantic#FileURL')
|
|
32
32
|
assert.equal(SemanticType.Markdown, 'Semantic#Markdown')
|
|
33
33
|
assert.equal(SemanticType.GeospatialCoordinates, 'Semantic#GeospatialCoordinates')
|
|
34
|
-
assert.equal(SemanticType.
|
|
34
|
+
assert.equal(SemanticType.Currency, 'Semantic#Currency')
|
|
35
35
|
assert.equal(SemanticType.ResourceOwnerIdentifier, 'Semantic#ResourceOwnerIdentifier')
|
|
36
36
|
assert.equal(SemanticType.SKU, 'Semantic#SKU')
|
|
37
37
|
})
|
|
@@ -49,6 +49,7 @@ test.group('Semantics', () => {
|
|
|
49
49
|
description: 'Test',
|
|
50
50
|
scope: SemanticScope.Entity,
|
|
51
51
|
category: SemanticCategory.Identity,
|
|
52
|
+
hasConfig: false,
|
|
52
53
|
}
|
|
53
54
|
const propertySemantic: PropertySemantic = {
|
|
54
55
|
id: SemanticType.CreatedTimestamp,
|
|
@@ -56,6 +57,7 @@ test.group('Semantics', () => {
|
|
|
56
57
|
description: 'Test',
|
|
57
58
|
scope: SemanticScope.Property,
|
|
58
59
|
category: SemanticCategory.Lifecycle,
|
|
60
|
+
hasConfig: false,
|
|
59
61
|
}
|
|
60
62
|
const associationSemantic: AssociationSemantic = {
|
|
61
63
|
id: SemanticType.ResourceOwnerIdentifier,
|
|
@@ -63,6 +65,7 @@ test.group('Semantics', () => {
|
|
|
63
65
|
description: 'Test',
|
|
64
66
|
scope: SemanticScope.Association,
|
|
65
67
|
category: SemanticCategory.Identity,
|
|
68
|
+
hasConfig: false,
|
|
66
69
|
}
|
|
67
70
|
|
|
68
71
|
assert.isTrue(isEntitySemantic(entitySemantic))
|
|
@@ -77,6 +80,7 @@ test.group('Semantics', () => {
|
|
|
77
80
|
description: 'Test',
|
|
78
81
|
scope: SemanticScope.Entity,
|
|
79
82
|
category: SemanticCategory.Identity,
|
|
83
|
+
hasConfig: false,
|
|
80
84
|
}
|
|
81
85
|
const propertySemantic: PropertySemantic = {
|
|
82
86
|
id: SemanticType.CreatedTimestamp,
|
|
@@ -84,6 +88,7 @@ test.group('Semantics', () => {
|
|
|
84
88
|
description: 'Test',
|
|
85
89
|
scope: SemanticScope.Property,
|
|
86
90
|
category: SemanticCategory.Lifecycle,
|
|
91
|
+
hasConfig: false,
|
|
87
92
|
}
|
|
88
93
|
const associationSemantic: AssociationSemantic = {
|
|
89
94
|
id: SemanticType.ResourceOwnerIdentifier,
|
|
@@ -91,6 +96,7 @@ test.group('Semantics', () => {
|
|
|
91
96
|
description: 'Test',
|
|
92
97
|
scope: SemanticScope.Association,
|
|
93
98
|
category: SemanticCategory.Identity,
|
|
99
|
+
hasConfig: false,
|
|
94
100
|
}
|
|
95
101
|
|
|
96
102
|
assert.isFalse(isPropertySemantic(entitySemantic))
|
|
@@ -105,6 +111,7 @@ test.group('Semantics', () => {
|
|
|
105
111
|
description: 'Test',
|
|
106
112
|
scope: SemanticScope.Entity,
|
|
107
113
|
category: SemanticCategory.Identity,
|
|
114
|
+
hasConfig: false,
|
|
108
115
|
}
|
|
109
116
|
const propertySemantic: PropertySemantic = {
|
|
110
117
|
id: SemanticType.CreatedTimestamp,
|
|
@@ -112,6 +119,7 @@ test.group('Semantics', () => {
|
|
|
112
119
|
description: 'Test',
|
|
113
120
|
scope: SemanticScope.Property,
|
|
114
121
|
category: SemanticCategory.Lifecycle,
|
|
122
|
+
hasConfig: false,
|
|
115
123
|
}
|
|
116
124
|
const associationSemantic: AssociationSemantic = {
|
|
117
125
|
id: SemanticType.ResourceOwnerIdentifier,
|
|
@@ -119,6 +127,7 @@ test.group('Semantics', () => {
|
|
|
119
127
|
description: 'Test',
|
|
120
128
|
scope: SemanticScope.Association,
|
|
121
129
|
category: SemanticCategory.Identity,
|
|
130
|
+
hasConfig: false,
|
|
122
131
|
}
|
|
123
132
|
|
|
124
133
|
assert.isFalse(isAssociationSemantic(entitySemantic))
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Price.d.ts","sourceRoot":"","sources":["../../../../src/modeling/definitions/Price.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAA;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAE9C;;GAEG;AACH,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG,eAAe,GAAG,gBAAgB,CAAA;AAE/E;;;GAGG;AACH,MAAM,WAAW,WAAW;IAC1B;;;;;;OAMG;IACH,aAAa,CAAC,EAAE,kBAAkB,CAAA;IAElC;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;IAExB;;;OAGG;IACH,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAA;IAE5B;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAA;IAEtB;;OAEG;IACH,aAAa,CAAC,EAAE,OAAO,CAAA;IAEvB;;OAEG;IACH,oBAAoB,CAAC,EAAE,OAAO,CAAA;IAE9B;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAElC;;OAEG;IACH,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAqB,SAAQ,mBAAmB;IAC/D,EAAE,EAAE,YAAY,CAAC,KAAK,CAAA;IACtB,MAAM,CAAC,EAAE,WAAW,CAAA;CACrB;AAED;;GAEG;AACH,eAAO,MAAM,eAAe,GAAI,UAAU,mBAAmB,KAAG,QAAQ,IAAI,oBAE3E,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,mBAAmB,GAAI,SAAQ,WAAgB,KAAG,oBAe9D,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,WAMlC,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,aAAa;IACxB;;OAEG;;IAQH;;OAEG;;IAQH;;OAEG;;IAQH;;OAEG;;IAQH;;OAEG;;CAOK,CAAA;AAEV;;GAEG;AACH,eAAO,MAAM,mBAAmB,GAAI,QAAQ,WAAW,KAAG,MAAM,EAY/D,CAAA"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"Price.js","sourceRoot":"","sources":["../../../../src/modeling/definitions/Price.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAqE9C;;GAEG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,QAA6B,EAAoC,EAAE;IACjG,OAAO,QAAQ,CAAC,EAAE,KAAK,YAAY,CAAC,KAAK,CAAA;AAC3C,CAAC,CAAA;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,SAAsB,EAAE,EAAwB,EAAE;IACpF,MAAM,YAAY,GAAG;QACnB,GAAG,oBAAoB;QACvB,GAAG,MAAM;KACV,CAAA;IAED,4BAA4B;IAC5B,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QACpB,YAAY,CAAC,QAAQ,GAAG,EAAE,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAA;IAChD,CAAC;IAED,OAAO;QACL,EAAE,EAAE,YAAY,CAAC,KAAK;QACtB,MAAM,EAAE,YAAY;KACrB,CAAA;AACH,CAAC,CAAA;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAgB;IAC/C,aAAa,EAAE,SAAS;IACxB,eAAe,EAAE,KAAK;IACtB,aAAa,EAAE,CAAC;IAChB,aAAa,EAAE,KAAK;IACpB,oBAAoB,EAAE,IAAI;CAC3B,CAAA;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG;IAC3B;;OAEG;IACH,WAAW,EAAE,mBAAmB,CAAC;QAC/B,aAAa,EAAE,SAAS;QACxB,eAAe,EAAE,KAAK;QACtB,aAAa,EAAE,CAAC;QAChB,aAAa,EAAE,KAAK;KACrB,CAAC;IAEF;;OAEG;IACH,SAAS,EAAE,mBAAmB,CAAC;QAC7B,aAAa,EAAE,eAAe;QAC9B,eAAe,EAAE,KAAK;QACtB,aAAa,EAAE,CAAC;QAChB,aAAa,EAAE,KAAK;KACrB,CAAC;IAEF;;OAEG;IACH,cAAc,EAAE,mBAAmB,CAAC;QAClC,aAAa,EAAE,gBAAgB;QAC/B,iBAAiB,EAAE,CAAC,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,KAAK,CAAC;QACtD,aAAa,EAAE,CAAC;QAChB,aAAa,EAAE,KAAK;KACrB,CAAC;IAEF;;OAEG;IACH,cAAc,EAAE,mBAAmB,CAAC;QAClC,aAAa,EAAE,SAAS;QACxB,eAAe,EAAE,KAAK;QACtB,aAAa,EAAE,CAAC;QAChB,aAAa,EAAE,IAAI;KACpB,CAAC;IAEF;;OAEG;IACH,cAAc,EAAE,mBAAmB,CAAC;QAClC,aAAa,EAAE,SAAS;QACxB,eAAe,EAAE,KAAK;QACtB,aAAa,EAAE,CAAC;QAChB,aAAa,EAAE,KAAK;KACrB,CAAC;CACM,CAAA;AAEV;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,MAAmB,EAAY,EAAE;IACnE,MAAM,MAAM,GAAa,EAAE,CAAA;IAE3B,IAAI,MAAM,CAAC,aAAa,KAAK,gBAAgB,IAAI,CAAC,MAAM,CAAC,eAAe,EAAE,CAAC;QACzE,MAAM,CAAC,IAAI,CAAC,sEAAsE,CAAC,CAAA;IACrF,CAAC;IAED,IAAI,MAAM,CAAC,aAAa,KAAK,SAAS,IAAI,MAAM,CAAC,aAAa,GAAG,CAAC,EAAE,CAAC;QACnE,MAAM,CAAC,IAAI,CAAC,oCAAoC,CAAC,CAAA;IACnD,CAAC;IAED,OAAO,MAAM,CAAA;AACf,CAAC,CAAA","sourcesContent":["import type { AppliedDataSemantic } from '../Semantics.js'\nimport { SemanticType } from '../Semantics.js'\n\n/**\n * Supported storage formats for monetary values.\n */\nexport type PriceStorageFormat = 'decimal' | 'integer_cents' | 'complex_object'\n\n/**\n * Configuration options for the Price semantic.\n * Controls monetary value storage, validation, currency handling, and precision.\n */\nexport interface PriceConfig {\n /**\n * How the monetary value is stored in the database.\n *\n * - 'decimal': Store as DECIMAL/NUMERIC type (e.g., 19.99)\n * - 'integer_cents': Store as INTEGER in smallest currency unit (e.g., 1999 for $19.99)\n * - 'complex_object': Store as JSON/JSONB with amount and currency (e.g., {\"amount\": 1999, \"currency\": \"USD\"})\n */\n storageFormat?: PriceStorageFormat\n\n /**\n * Default currency code (ISO 4217) when not specified.\n * Required when using 'decimal' or 'integer_cents' format.\n */\n defaultCurrency?: string\n\n /**\n * List of allowed currency codes (ISO 4217).\n * If not specified, all valid ISO 4217 currencies are allowed.\n */\n allowedCurrencies?: string[]\n\n /**\n * Number of decimal places for precision.\n * Default: 2 (for most currencies like USD, EUR)\n * Some currencies may need 0 (JPY, KRW) or 3 (BHD, KWD)\n */\n decimalPlaces?: number\n\n /**\n * Whether negative values are allowed (for refunds, discounts, etc.).\n */\n allowNegative?: boolean\n\n /**\n * Whether to automatically validate currency codes against ISO 4217.\n */\n validateCurrencyCode?: boolean\n\n /**\n * Custom metadata for the price field.\n */\n metadata?: Record<string, unknown>\n\n /**\n * Index signature to allow additional properties.\n */\n [key: string]: unknown\n}\n\n/**\n * Type-safe configuration for Price semantic.\n */\nexport interface AppliedPriceSemantic extends AppliedDataSemantic {\n id: SemanticType.Price\n config?: PriceConfig\n}\n\n/**\n * Type guard to check if a semantic is a Price semantic.\n */\nexport const isPriceSemantic = (semantic: AppliedDataSemantic): semantic is AppliedPriceSemantic => {\n return semantic.id === SemanticType.Price\n}\n\n/**\n * Helper function to create a Price semantic with configuration.\n */\nexport const createPriceSemantic = (config: PriceConfig = {}): AppliedPriceSemantic => {\n const mergedConfig = {\n ...DEFAULT_PRICE_CONFIG,\n ...config,\n }\n\n // Merge metadata separately\n if (config.metadata) {\n mergedConfig.metadata = { ...config.metadata }\n }\n\n return {\n id: SemanticType.Price,\n config: mergedConfig,\n }\n}\n\n/**\n * Default configuration for Price semantic.\n * Optimized for common e-commerce use cases with USD currency.\n */\nexport const DEFAULT_PRICE_CONFIG: PriceConfig = {\n storageFormat: 'decimal',\n defaultCurrency: 'USD',\n decimalPlaces: 2,\n allowNegative: false,\n validateCurrencyCode: true,\n}\n\n/**\n * Predefined configurations for common use cases.\n */\nexport const PRICE_PRESETS = {\n /**\n * Simple USD decimal storage - good for most e-commerce sites.\n */\n USD_DECIMAL: createPriceSemantic({\n storageFormat: 'decimal',\n defaultCurrency: 'USD',\n decimalPlaces: 2,\n allowNegative: false,\n }),\n\n /**\n * Integer cents storage - avoids floating point issues, good for financial calculations.\n */\n USD_CENTS: createPriceSemantic({\n storageFormat: 'integer_cents',\n defaultCurrency: 'USD',\n decimalPlaces: 2,\n allowNegative: false,\n }),\n\n /**\n * Multi-currency support with complex object storage.\n */\n MULTI_CURRENCY: createPriceSemantic({\n storageFormat: 'complex_object',\n allowedCurrencies: ['USD', 'EUR', 'GBP', 'JPY', 'CAD'],\n decimalPlaces: 2,\n allowNegative: false,\n }),\n\n /**\n * Configuration that allows negative values for refunds, discounts, etc.\n */\n WITH_NEGATIVES: createPriceSemantic({\n storageFormat: 'decimal',\n defaultCurrency: 'USD',\n decimalPlaces: 2,\n allowNegative: true,\n }),\n\n /**\n * High-precision configuration for cryptocurrency or precious metals.\n */\n HIGH_PRECISION: createPriceSemantic({\n storageFormat: 'decimal',\n defaultCurrency: 'BTC',\n decimalPlaces: 8,\n allowNegative: false,\n }),\n} as const\n\n/**\n * Helper function to validate a price configuration.\n */\nexport const validatePriceConfig = (config: PriceConfig): string[] => {\n const errors: string[] = []\n\n if (config.storageFormat !== 'complex_object' && !config.defaultCurrency) {\n errors.push('defaultCurrency is required when storageFormat is not complex_object')\n }\n\n if (config.decimalPlaces !== undefined && config.decimalPlaces < 0) {\n errors.push('decimalPlaces must be non-negative')\n }\n\n return errors\n}\n"]}
|