@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
@@ -0,0 +1,116 @@
1
+ import type { AppliedDataSemantic } from '../Semantics.js'
2
+ import { SemanticType } from '../Semantics.js'
3
+
4
+ /**
5
+ * Configuration options for the Markdown semantic.
6
+ * Controls rendering, sanitization, and allowed features.
7
+ */
8
+ export interface MarkdownConfig {
9
+ /**
10
+ * List of allowed HTML tags in the rendered output.
11
+ */
12
+ allowedTags?: string[]
13
+ /**
14
+ * Maximum length of the markdown content.
15
+ */
16
+ maxLength?: number
17
+ /**
18
+ * Render mode: 'html', 'text', or 'both'.
19
+ */
20
+ renderMode?: 'html' | 'text' | 'both'
21
+ /**
22
+ * Sanitization level: 'strict', 'moderate', or 'none'.
23
+ */
24
+ sanitizeLevel?: 'strict' | 'moderate' | 'none'
25
+ /**
26
+ * Whether to allow images in markdown.
27
+ */
28
+ allowImages?: boolean
29
+ /**
30
+ * Whether to allow links in markdown.
31
+ */
32
+ allowLinks?: boolean
33
+ /**
34
+ * Whether to allow tables in markdown.
35
+ */
36
+ allowTables?: boolean
37
+ /**
38
+ * Whether to allow raw HTML in markdown.
39
+ */
40
+ allowHtml?: boolean
41
+ /**
42
+ * Whether to allow footnotes in markdown.
43
+ */
44
+ allowFootnotes?: boolean
45
+ /**
46
+ * Whether to allow GitHub-style task lists.
47
+ */
48
+ allowTaskLists?: boolean
49
+ /**
50
+ * Whether to allow strikethrough formatting.
51
+ */
52
+ allowStrikethrough?: boolean
53
+ /**
54
+ * Whether to allow math expressions (e.g., LaTeX).
55
+ */
56
+ allowMath?: boolean
57
+ /**
58
+ * Custom metadata for the markdown field.
59
+ */
60
+ metadata?: Record<string, unknown>
61
+ /**
62
+ * Index signature to allow additional properties.
63
+ */
64
+ [key: string]: unknown
65
+ }
66
+
67
+ /**
68
+ * Type-safe configuration for Markdown semantic.
69
+ */
70
+ export interface AppliedMarkdownSemantic extends AppliedDataSemantic {
71
+ id: SemanticType.Markdown
72
+ config?: MarkdownConfig
73
+ }
74
+
75
+ /**
76
+ * Type guard to check if a semantic is a Markdown semantic.
77
+ */
78
+ export const isMarkdownSemantic = (semantic: AppliedDataSemantic): semantic is AppliedMarkdownSemantic => {
79
+ return semantic.id === SemanticType.Markdown
80
+ }
81
+
82
+ /**
83
+ * Helper function to create a Markdown semantic with configuration.
84
+ */
85
+ export const createMarkdownSemantic = (config: MarkdownConfig = {}): AppliedMarkdownSemantic => {
86
+ const mergedConfig = {
87
+ ...DEFAULT_MARKDOWN_CONFIG,
88
+ ...config,
89
+ }
90
+ if (config.metadata) {
91
+ mergedConfig.metadata = { ...config.metadata }
92
+ }
93
+
94
+ return {
95
+ id: SemanticType.Markdown,
96
+ config: mergedConfig,
97
+ }
98
+ }
99
+
100
+ /**
101
+ * Default configuration for Markdown semantic.
102
+ */
103
+ export const DEFAULT_MARKDOWN_CONFIG: MarkdownConfig = {
104
+ allowedTags: ['b', 'i', 'em', 'strong', 'a', 'ul', 'ol', 'li', 'p', 'br', 'pre', 'code'],
105
+ maxLength: 10000,
106
+ renderMode: 'html',
107
+ sanitizeLevel: 'strict',
108
+ allowImages: true,
109
+ allowLinks: true,
110
+ allowTables: true,
111
+ allowHtml: false,
112
+ allowFootnotes: false,
113
+ allowTaskLists: false,
114
+ allowStrikethrough: true,
115
+ allowMath: false,
116
+ }
@@ -0,0 +1,156 @@
1
+ import type { AppliedDataSemantic } from '../Semantics.js'
2
+ import { SemanticType } from '../Semantics.js'
3
+
4
+ /**
5
+ * Supported encryption algorithms for password hashing.
6
+ */
7
+ export enum PasswordEncryptionAlgorithm {
8
+ /**
9
+ * bcrypt - Industry standard, secure, and widely supported
10
+ */
11
+ Bcrypt = 'bcrypt',
12
+ /**
13
+ * Argon2 - Winner of the Password Hashing Competition, very secure
14
+ */
15
+ Argon2 = 'argon2',
16
+ /**
17
+ * scrypt - Memory-hard function, good for high-security applications
18
+ */
19
+ Scrypt = 'scrypt',
20
+ }
21
+
22
+ /**
23
+ * Configuration options for the Password semantic.
24
+ * These options control password validation and encryption behavior.
25
+ */
26
+ export interface PasswordConfig {
27
+ /**
28
+ * Whether to require special characters.
29
+ * Defaults to false if not specified.
30
+ */
31
+ requireSpecialChars?: boolean
32
+
33
+ /**
34
+ * Whether to require numbers.
35
+ * Defaults to false if not specified.
36
+ */
37
+ requireNumbers?: boolean
38
+
39
+ /**
40
+ * Whether to require uppercase letters.
41
+ * Defaults to false if not specified.
42
+ */
43
+ requireUppercase?: boolean
44
+
45
+ /**
46
+ * Whether to require lowercase letters.
47
+ * Defaults to false if not specified.
48
+ */
49
+ requireLowercase?: boolean
50
+
51
+ /**
52
+ * Encryption algorithm to use for password hashing.
53
+ * Defaults to 'bcrypt' if not specified.
54
+ */
55
+ encryptionAlgorithm?: PasswordEncryptionAlgorithm
56
+
57
+ /**
58
+ * Number of salt rounds for bcrypt.
59
+ * Defaults to 12 if not specified.
60
+ */
61
+ saltRounds?: number
62
+
63
+ /**
64
+ * Maximum age of password in days before requiring change.
65
+ * Defaults to null (no expiration) if not specified.
66
+ */
67
+ maxAge?: number
68
+
69
+ /**
70
+ * Whether to prevent reuse of recent passwords.
71
+ * Defaults to false if not specified.
72
+ */
73
+ preventReuse?: boolean
74
+
75
+ /**
76
+ * Number of recent passwords to prevent reuse.
77
+ * Defaults to 5 if preventReuse is true.
78
+ */
79
+ preventReuseCount?: number
80
+
81
+ /**
82
+ * Custom password validation regex pattern.
83
+ * If specified, overrides other validation rules.
84
+ */
85
+ customPattern?: string
86
+
87
+ /**
88
+ * Custom error message for validation failures.
89
+ */
90
+ customErrorMessage?: string
91
+
92
+ /**
93
+ * Whether to allow common passwords.
94
+ * Defaults to false if not specified.
95
+ */
96
+ allowCommonPasswords?: boolean
97
+
98
+ /**
99
+ * Custom metadata for the password field.
100
+ */
101
+ metadata?: Record<string, unknown>
102
+
103
+ /**
104
+ * Index signature to allow additional properties.
105
+ */
106
+ [key: string]: unknown
107
+ }
108
+
109
+ /**
110
+ * Type-safe configuration for Password semantic.
111
+ */
112
+ export interface AppliedPasswordSemantic extends AppliedDataSemantic {
113
+ id: SemanticType.Password
114
+ config?: PasswordConfig
115
+ }
116
+
117
+ /**
118
+ * Type guard to check if a semantic is a Password semantic.
119
+ */
120
+ export const isPasswordSemantic = (semantic: AppliedDataSemantic): semantic is AppliedPasswordSemantic => {
121
+ return semantic.id === SemanticType.Password
122
+ }
123
+
124
+ /**
125
+ * Helper function to create a Password semantic with configuration.
126
+ */
127
+ export const createPasswordSemantic = (config: PasswordConfig = {}): AppliedPasswordSemantic => {
128
+ const mergedConfig = {
129
+ ...DEFAULT_PASSWORD_CONFIG,
130
+ ...config,
131
+ }
132
+ if (config.metadata) {
133
+ mergedConfig.metadata = { ...config.metadata }
134
+ }
135
+
136
+ return {
137
+ id: SemanticType.Password,
138
+ config: mergedConfig,
139
+ }
140
+ }
141
+
142
+ /**
143
+ * Default configuration for Password semantic.
144
+ */
145
+ export const DEFAULT_PASSWORD_CONFIG: PasswordConfig = {
146
+ requireSpecialChars: true,
147
+ requireNumbers: true,
148
+ requireUppercase: true,
149
+ requireLowercase: true,
150
+ encryptionAlgorithm: PasswordEncryptionAlgorithm.Bcrypt,
151
+ saltRounds: 12,
152
+ maxAge: undefined,
153
+ preventReuse: false,
154
+ preventReuseCount: 5,
155
+ allowCommonPasswords: false,
156
+ }
@@ -0,0 +1,116 @@
1
+ import type { AppliedDataSemantic } from '../Semantics.js'
2
+ import { SemanticType } from '../Semantics.js'
3
+
4
+ /**
5
+ * Configuration options for the Phone semantic.
6
+ * Controls validation, formatting, and verification of phone numbers.
7
+ */
8
+ export interface PhoneConfig {
9
+ /**
10
+ * List of allowed country codes (ISO 3166-1 alpha-2 format).
11
+ * If not specified, all countries are allowed.
12
+ * Examples: ['US', 'CA', 'GB', 'DE']
13
+ */
14
+ allowedCountries?: string[]
15
+
16
+ /**
17
+ * Whether the phone number must include a country code.
18
+ * Defaults to true for E.164 format.
19
+ */
20
+ requireCountryCode?: boolean
21
+
22
+ /**
23
+ * Format for phone number validation and display.
24
+ * - 'E.164': International format with + prefix (e.g., +1234567890)
25
+ * - 'national': Country-specific format without country code
26
+ * - 'international': International format with country code
27
+ * - 'custom': Use customFormat pattern
28
+ */
29
+ format?: 'E.164' | 'national' | 'international' | 'custom'
30
+
31
+ /**
32
+ * Custom format pattern for phone number validation.
33
+ * Only used when format is set to 'custom'.
34
+ * Examples: '###-###-####', '(###) ###-####'
35
+ */
36
+ customFormat?: string
37
+
38
+ /**
39
+ * Whether to allow phone extensions (e.g., +1234567890 ext 123).
40
+ * Defaults to false.
41
+ */
42
+ allowExtension?: boolean
43
+
44
+ /**
45
+ * Whether phone number verification is required.
46
+ * Defaults to false.
47
+ */
48
+ requireVerification?: boolean
49
+
50
+ /**
51
+ * Method to use for phone verification.
52
+ * - 'sms': Send verification code via SMS
53
+ * - 'call': Make verification call
54
+ * - 'none': No verification required
55
+ */
56
+ verificationMethod?: 'sms' | 'call' | 'none'
57
+
58
+ /**
59
+ * Custom metadata for the phone field.
60
+ */
61
+ metadata?: Record<string, unknown>
62
+
63
+ /**
64
+ * Index signature to allow additional properties.
65
+ */
66
+ [key: string]: unknown
67
+ }
68
+
69
+ /**
70
+ * Type-safe configuration for Phone semantic.
71
+ */
72
+ export interface AppliedPhoneSemantic extends AppliedDataSemantic {
73
+ id: SemanticType.Phone
74
+ config?: PhoneConfig
75
+ }
76
+
77
+ /**
78
+ * Type guard to check if a semantic is a Phone semantic.
79
+ * @param semantic - The semantic to check
80
+ * @returns True if the semantic is a Phone semantic
81
+ */
82
+ export const isPhoneSemantic = (semantic: AppliedDataSemantic): semantic is AppliedPhoneSemantic => {
83
+ return semantic.id === SemanticType.Phone
84
+ }
85
+
86
+ /**
87
+ * Helper function to create a Phone semantic with configuration.
88
+ * @param config - Configuration options for the phone semantic
89
+ * @returns AppliedPhoneSemantic with the specified configuration
90
+ */
91
+ export const createPhoneSemantic = (config: PhoneConfig = {}): AppliedPhoneSemantic => {
92
+ const mergedConfig = {
93
+ ...DEFAULT_PHONE_CONFIG,
94
+ ...config,
95
+ }
96
+ if (config.metadata) {
97
+ mergedConfig.metadata = { ...config.metadata }
98
+ }
99
+
100
+ return {
101
+ id: SemanticType.Phone,
102
+ config: mergedConfig,
103
+ }
104
+ }
105
+
106
+ /**
107
+ * Default configuration for Phone semantic.
108
+ * Uses E.164 format with country code required and SMS verification.
109
+ */
110
+ export const DEFAULT_PHONE_CONFIG: PhoneConfig = {
111
+ requireCountryCode: true,
112
+ format: 'E.164',
113
+ allowExtension: false,
114
+ requireVerification: false,
115
+ verificationMethod: 'sms',
116
+ }
@@ -0,0 +1,158 @@
1
+ # Price Semantic Examples
2
+
3
+ This document provides examples of how to use the Price semantic with different configurations.
4
+
5
+ ## Basic Usage
6
+
7
+ ```typescript
8
+ import { createPriceSemantic, PRICE_PRESETS } from './Price.js'
9
+
10
+ // Simple USD decimal storage
11
+ const basicPrice = createPriceSemantic({
12
+ storageFormat: 'decimal',
13
+ defaultCurrency: 'USD',
14
+ decimalPlaces: 2,
15
+ allowNegative: false,
16
+ })
17
+
18
+ // Using a preset
19
+ const usdDecimal = PRICE_PRESETS.USD_DECIMAL
20
+ ```
21
+
22
+ ## Configuration Examples
23
+
24
+ ### 1. Simple E-commerce Store (USD only)
25
+
26
+ ```typescript
27
+ const ecommercePrice = createPriceSemantic({
28
+ storageFormat: 'decimal',
29
+ defaultCurrency: 'USD',
30
+ decimalPlaces: 2,
31
+ allowNegative: false,
32
+ })
33
+ ```
34
+
35
+ ### 2. International E-commerce (Multi-currency)
36
+
37
+ ```typescript
38
+ const internationalPrice = createPriceSemantic({
39
+ storageFormat: 'complex_object',
40
+ allowedCurrencies: ['USD', 'EUR', 'GBP', 'JPY', 'CAD', 'AUD'],
41
+ decimalPlaces: 2,
42
+ allowNegative: false,
43
+ })
44
+ ```
45
+
46
+ ### 3. Financial System (High precision, allows negatives)
47
+
48
+ ```typescript
49
+ const financialPrice = createPriceSemantic({
50
+ storageFormat: 'integer_cents',
51
+ defaultCurrency: 'USD',
52
+ decimalPlaces: 4,
53
+ allowNegative: true,
54
+ })
55
+ ```
56
+
57
+ ### 4. Cryptocurrency Trading
58
+
59
+ ```typescript
60
+ const cryptoPrice = createPriceSemantic({
61
+ storageFormat: 'decimal',
62
+ defaultCurrency: 'BTC',
63
+ decimalPlaces: 8,
64
+ allowNegative: false,
65
+ })
66
+ ```
67
+
68
+ ## Storage Format Details
69
+
70
+ ### Decimal Format
71
+
72
+ - **Best for**: Simple single-currency applications
73
+ - **PostgreSQL Type**: DECIMAL(precision, scale)
74
+ - **Example Value**: 19.99
75
+ - **Pros**: Human-readable, direct calculations
76
+ - **Cons**: Currency must be stored separately if needed
77
+
78
+ ### Integer Cents Format
79
+
80
+ - **Best for**: Financial calculations requiring precision
81
+ - **PostgreSQL Type**: BIGINT
82
+ - **Example Value**: 1999 (represents $19.99)
83
+ - **Pros**: No floating-point errors, efficient storage
84
+ - **Cons**: Requires conversion for display
85
+
86
+ ### Complex Object Format
87
+
88
+ - **Best for**: Multi-currency applications
89
+ - **PostgreSQL Type**: JSONB
90
+ - **Example Value**: {"amount": 1999, "currency": "USD"}
91
+ - **Pros**: Stores amount and currency together, flexible
92
+ - **Cons**: More complex queries, larger storage
93
+
94
+ ## Database Schema Generation Examples
95
+
96
+ The runtime will generate appropriate PostgreSQL schemas based on the semantic configuration:
97
+
98
+ ### For Decimal Format
99
+
100
+ Based on `storageFormat: 'decimal'` configuration, the runtime should generate:
101
+
102
+ ```sql
103
+ CREATE TABLE products (
104
+ id SERIAL PRIMARY KEY,
105
+ name VARCHAR(255),
106
+ price DECIMAL(19, 2) NOT NULL,
107
+ currency CHAR(3) DEFAULT 'USD'
108
+ );
109
+
110
+ CREATE INDEX idx_products_price ON products(price);
111
+ ```
112
+
113
+ ### For Integer Cents Format
114
+
115
+ Based on `storageFormat: 'integer_cents'` configuration, the runtime should generate:
116
+
117
+ ```sql
118
+ CREATE TABLE products (
119
+ id SERIAL PRIMARY KEY,
120
+ name VARCHAR(255),
121
+ price_cents BIGINT NOT NULL,
122
+ currency CHAR(3) DEFAULT 'USD'
123
+ );
124
+
125
+ CREATE INDEX idx_products_price_cents ON products(price_cents);
126
+ ```
127
+
128
+ ### For Complex Object Format
129
+
130
+ Based on `storageFormat: 'complex_object'` configuration, the runtime should generate:
131
+
132
+ ```sql
133
+ CREATE TABLE products (
134
+ id SERIAL PRIMARY KEY,
135
+ name VARCHAR(255),
136
+ price JSONB NOT NULL
137
+ );
138
+
139
+ CREATE INDEX idx_products_price_amount ON products USING GIN ((price->>'amount'));
140
+ CREATE INDEX idx_products_price_currency ON products USING GIN ((price->>'currency'));
141
+ ```
142
+
143
+ ## Validation Examples
144
+
145
+ The Price semantic includes built-in validation:
146
+
147
+ ```typescript
148
+ import { validatePriceConfig } from './Price.js'
149
+
150
+ const config = {
151
+ storageFormat: 'decimal' as const,
152
+ // Missing defaultCurrency - this will cause an error
153
+ decimalPlaces: 2,
154
+ }
155
+
156
+ const errors = validatePriceConfig(config)
157
+ console.log(errors) // ['defaultCurrency is required when storageFormat is not complex_object']
158
+ ```