@coinbase-sample/prime-sdk-ts 0.6.3 → 0.6.4
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/dist/constants.js +1 -1
- package/dist/model/enumPrefixes.js +330 -0
- package/dist/paymentMethods/index.js +2 -1
- package/dist/shared/dynamicEnumValidation.js +184 -0
- package/dist/shared/dynamicEnumValidation.old.js +746 -0
- package/dist/shared/enumHelpers.js +219 -0
- package/dist/shared/enumRegistry.js +153 -0
- package/dist/shared/enumValidationCore.js +194 -0
- package/dist/shared/enumValidators.js +115 -0
- package/dist/shared/fieldMapping.js +242 -0
- package/dist/shared/serviceContext.js +157 -0
- package/dist/types/balances/types.d.ts +1 -1
- package/dist/types/constants.d.ts +1 -1
- package/dist/types/model/enumPrefixes.d.ts +206 -0
- package/dist/types/paymentMethods/types.d.ts +1 -0
- package/dist/types/shared/dynamicEnumValidation.d.ts +48 -0
- package/dist/types/shared/dynamicEnumValidation.old.d.ts +143 -0
- package/dist/types/shared/enumHelpers.d.ts +135 -0
- package/dist/types/shared/enumRegistry.d.ts +74 -0
- package/dist/types/shared/enumValidationCore.d.ts +68 -0
- package/dist/types/shared/enumValidators.d.ts +117 -0
- package/dist/types/shared/fieldMapping.d.ts +35 -0
- package/dist/types/shared/serviceContext.d.ts +46 -0
- package/package.json +2 -2
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright 2025-present Coinbase Global, Inc.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.normalizeEnumValue = normalizeEnumValue;
|
|
19
|
+
exports.getEnumValue = getEnumValue;
|
|
20
|
+
exports.requireEnumValue = requireEnumValue;
|
|
21
|
+
exports.isValidEnumValue = isValidEnumValue;
|
|
22
|
+
exports.getEnumValues = getEnumValues;
|
|
23
|
+
exports.getEnumKeys = getEnumKeys;
|
|
24
|
+
exports.validateEnumPrefix = validateEnumPrefix;
|
|
25
|
+
exports.transformEnumValue = transformEnumValue;
|
|
26
|
+
/**
|
|
27
|
+
* Enum transformation utilities for JavaScript developers.
|
|
28
|
+
* These helpers make it easier to work with enums by providing:
|
|
29
|
+
* - Case-insensitive enum lookups
|
|
30
|
+
* - CamelCase to SNAKE_CASE conversion
|
|
31
|
+
* - Enum validation with helpful error messages
|
|
32
|
+
* - Support for prefix-aware transformations
|
|
33
|
+
*/
|
|
34
|
+
/**
|
|
35
|
+
* Converts a string from various formats to the expected enum value format (SCREAMING_SNAKE_CASE)
|
|
36
|
+
*
|
|
37
|
+
* @param input - The input string in any case format
|
|
38
|
+
* @returns The normalized SCREAMING_SNAKE_CASE string
|
|
39
|
+
*
|
|
40
|
+
* @example
|
|
41
|
+
* normalizeEnumValue('buy') // 'BUY'
|
|
42
|
+
* normalizeEnumValue('marketOrder') // 'MARKET_ORDER'
|
|
43
|
+
* normalizeEnumValue('STOP_LIMIT') // 'STOP_LIMIT'
|
|
44
|
+
* normalizeEnumValue('Order_Type_Market') // 'ORDER_TYPE_MARKET'
|
|
45
|
+
*/
|
|
46
|
+
function normalizeEnumValue(input) {
|
|
47
|
+
if (!input || typeof input !== 'string') {
|
|
48
|
+
throw new Error('Input must be a non-empty string');
|
|
49
|
+
}
|
|
50
|
+
return (input
|
|
51
|
+
// Convert camelCase to snake_case
|
|
52
|
+
.replace(/([a-z])([A-Z])/g, '$1_$2')
|
|
53
|
+
// Handle existing underscores and hyphens
|
|
54
|
+
.replace(/[-\s]+/g, '_')
|
|
55
|
+
// Convert to uppercase
|
|
56
|
+
.toUpperCase()
|
|
57
|
+
// Clean up multiple underscores
|
|
58
|
+
.replace(/_+/g, '_')
|
|
59
|
+
// Remove leading/trailing underscores
|
|
60
|
+
.replace(/^_+|_+$/g, ''));
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Safely gets an enum value by normalizing the input and checking if it exists
|
|
64
|
+
*
|
|
65
|
+
* @param enumObject - The enum object to search in
|
|
66
|
+
* @param input - The input value to normalize and find
|
|
67
|
+
* @param enumName - Optional enum name for better error messages
|
|
68
|
+
* @returns The matching enum value or undefined if not found
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* import { OrderSide } from '../model/enums/OrderSide';
|
|
72
|
+
*
|
|
73
|
+
* getEnumValue(OrderSide, 'buy') // OrderSide.Buy
|
|
74
|
+
* getEnumValue(OrderSide, 'BUY') // OrderSide.Buy
|
|
75
|
+
* getEnumValue(OrderSide, 'invalid') // undefined
|
|
76
|
+
*/
|
|
77
|
+
function getEnumValue(enumObject, input, enumName) {
|
|
78
|
+
if (!input || typeof input !== 'string') {
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
const normalizedInput = normalizeEnumValue(input);
|
|
82
|
+
// Direct value match (input is already the enum value)
|
|
83
|
+
if (Object.values(enumObject).includes(normalizedInput)) {
|
|
84
|
+
return normalizedInput;
|
|
85
|
+
}
|
|
86
|
+
// Key-based lookup (find enum key that matches)
|
|
87
|
+
for (const [key, value] of Object.entries(enumObject)) {
|
|
88
|
+
if (normalizeEnumValue(key) === normalizedInput) {
|
|
89
|
+
return value;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Gets an enum value with strict validation, throwing an error if not found
|
|
96
|
+
*
|
|
97
|
+
* @param enumObject - The enum object to search in
|
|
98
|
+
* @param input - The input value to normalize and find
|
|
99
|
+
* @param enumName - Optional enum name for better error messages
|
|
100
|
+
* @returns The matching enum value
|
|
101
|
+
* @throws Error if the enum value is not found
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* import { OrderSide } from '../model/enums/OrderSide';
|
|
105
|
+
*
|
|
106
|
+
* requireEnumValue(OrderSide, 'buy') // OrderSide.Buy
|
|
107
|
+
* requireEnumValue(OrderSide, 'invalid') // throws Error
|
|
108
|
+
*/
|
|
109
|
+
function requireEnumValue(enumObject, input, enumName) {
|
|
110
|
+
const result = getEnumValue(enumObject, input, enumName);
|
|
111
|
+
if (result === undefined) {
|
|
112
|
+
const enumNameStr = enumName || 'Enum';
|
|
113
|
+
const validValues = Object.values(enumObject).join(', ');
|
|
114
|
+
const validKeys = Object.keys(enumObject).join(', ');
|
|
115
|
+
throw new Error(`Invalid ${enumNameStr} value: "${input}". ` +
|
|
116
|
+
`Valid values: ${validValues}. ` +
|
|
117
|
+
`Valid keys: ${validKeys}.`);
|
|
118
|
+
}
|
|
119
|
+
return result;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Checks if a string is a valid enum value (case-insensitive)
|
|
123
|
+
*
|
|
124
|
+
* @param enumObject - The enum object to check against
|
|
125
|
+
* @param input - The input value to validate
|
|
126
|
+
* @returns True if the input is a valid enum value
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* import { OrderSide } from '../model/enums/OrderSide';
|
|
130
|
+
*
|
|
131
|
+
* isValidEnumValue(OrderSide, 'buy') // true
|
|
132
|
+
* isValidEnumValue(OrderSide, 'BUY') // true
|
|
133
|
+
* isValidEnumValue(OrderSide, 'invalid') // false
|
|
134
|
+
*/
|
|
135
|
+
function isValidEnumValue(enumObject, input) {
|
|
136
|
+
return getEnumValue(enumObject, input) !== undefined;
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Gets all possible enum values as an array
|
|
140
|
+
*
|
|
141
|
+
* @param enumObject - The enum object
|
|
142
|
+
* @returns Array of all enum values
|
|
143
|
+
*
|
|
144
|
+
* @example
|
|
145
|
+
* import { OrderSide } from '../model/enums/OrderSide';
|
|
146
|
+
*
|
|
147
|
+
* getEnumValues(OrderSide) // ['BUY', 'SELL']
|
|
148
|
+
*/
|
|
149
|
+
function getEnumValues(enumObject) {
|
|
150
|
+
return Object.values(enumObject);
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Gets all possible enum keys as an array
|
|
154
|
+
*
|
|
155
|
+
* @param enumObject - The enum object
|
|
156
|
+
* @returns Array of all enum keys
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* import { OrderSide } from '../model/enums/OrderSide';
|
|
160
|
+
*
|
|
161
|
+
* getEnumKeys(OrderSide) // ['Buy', 'Sell']
|
|
162
|
+
*/
|
|
163
|
+
function getEnumKeys(enumObject) {
|
|
164
|
+
return Object.keys(enumObject);
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Validates that a string has the correct prefix for enum values
|
|
168
|
+
* Useful for ensuring enum values follow expected patterns
|
|
169
|
+
*
|
|
170
|
+
* @param input - The enum value to check
|
|
171
|
+
* @param expectedPrefix - The expected prefix (e.g., 'ORDER_TYPE_', 'ACTIVITY_TYPE_')
|
|
172
|
+
* @param strict - If true, requires exact prefix match. If false, allows values without prefix
|
|
173
|
+
* @returns True if the prefix is correct
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* validateEnumPrefix('ORDER_TYPE_MARKET', 'ORDER_TYPE_') // true
|
|
177
|
+
* validateEnumPrefix('MARKET', 'ORDER_TYPE_', false) // true (non-strict)
|
|
178
|
+
* validateEnumPrefix('MARKET', 'ORDER_TYPE_', true) // false (strict)
|
|
179
|
+
*/
|
|
180
|
+
function validateEnumPrefix(input, expectedPrefix, strict = false) {
|
|
181
|
+
if (!input || !expectedPrefix) {
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
const normalizedInput = normalizeEnumValue(input);
|
|
185
|
+
const normalizedPrefix = normalizeEnumValue(expectedPrefix);
|
|
186
|
+
if (strict) {
|
|
187
|
+
return normalizedInput.startsWith(normalizedPrefix);
|
|
188
|
+
}
|
|
189
|
+
// Non-strict: allow values with or without prefix
|
|
190
|
+
return (normalizedInput.startsWith(normalizedPrefix) ||
|
|
191
|
+
!normalizedInput.includes('_') ||
|
|
192
|
+
normalizedInput ===
|
|
193
|
+
normalizeEnumValue(input.replace(new RegExp(`^${expectedPrefix}`, 'i'), '')));
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Transforms enum input to the correct format, optionally adding a prefix
|
|
197
|
+
*
|
|
198
|
+
* @param input - The input string
|
|
199
|
+
* @param prefix - Optional prefix to add if not present
|
|
200
|
+
* @returns The transformed enum value
|
|
201
|
+
*
|
|
202
|
+
* @example
|
|
203
|
+
* transformEnumValue('market', 'ORDER_TYPE_') // 'ORDER_TYPE_MARKET'
|
|
204
|
+
* transformEnumValue('ORDER_TYPE_MARKET', 'ORDER_TYPE_') // 'ORDER_TYPE_MARKET'
|
|
205
|
+
* transformEnumValue('marketOrder') // 'MARKET_ORDER'
|
|
206
|
+
*/
|
|
207
|
+
function transformEnumValue(input, prefix) {
|
|
208
|
+
const normalized = normalizeEnumValue(input);
|
|
209
|
+
if (!prefix) {
|
|
210
|
+
return normalized;
|
|
211
|
+
}
|
|
212
|
+
const normalizedPrefix = normalizeEnumValue(prefix);
|
|
213
|
+
// If already has the prefix, return as-is
|
|
214
|
+
if (normalized.startsWith(normalizedPrefix)) {
|
|
215
|
+
return normalized;
|
|
216
|
+
}
|
|
217
|
+
// Add prefix
|
|
218
|
+
return `${normalizedPrefix}${normalized}`;
|
|
219
|
+
}
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright 2025-present Coinbase Global, Inc.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
20
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
21
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
22
|
+
}
|
|
23
|
+
Object.defineProperty(o, k2, desc);
|
|
24
|
+
}) : (function(o, m, k, k2) {
|
|
25
|
+
if (k2 === undefined) k2 = k;
|
|
26
|
+
o[k2] = m[k];
|
|
27
|
+
}));
|
|
28
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
29
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
30
|
+
}) : function(o, v) {
|
|
31
|
+
o["default"] = v;
|
|
32
|
+
});
|
|
33
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
34
|
+
var ownKeys = function(o) {
|
|
35
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
36
|
+
var ar = [];
|
|
37
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
38
|
+
return ar;
|
|
39
|
+
};
|
|
40
|
+
return ownKeys(o);
|
|
41
|
+
};
|
|
42
|
+
return function (mod) {
|
|
43
|
+
if (mod && mod.__esModule) return mod;
|
|
44
|
+
var result = {};
|
|
45
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
46
|
+
__setModuleDefault(result, mod);
|
|
47
|
+
return result;
|
|
48
|
+
};
|
|
49
|
+
})();
|
|
50
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
51
|
+
exports.enumRegistry = exports.EnumRegistry = void 0;
|
|
52
|
+
/**
|
|
53
|
+
* Central registry for managing and discovering TypeScript enums
|
|
54
|
+
*/
|
|
55
|
+
// Import all enums dynamically
|
|
56
|
+
const AllEnums = __importStar(require("../model/enums/"));
|
|
57
|
+
/**
|
|
58
|
+
* Registry for managing discovered enums and providing lookup capabilities
|
|
59
|
+
*/
|
|
60
|
+
class EnumRegistry {
|
|
61
|
+
constructor() {
|
|
62
|
+
this.enums = new Map();
|
|
63
|
+
this.enumsByValue = new Map();
|
|
64
|
+
this.enumsByKey = new Map();
|
|
65
|
+
this.populateEnums();
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Automatically discover and register all enums from the model/enums directory
|
|
69
|
+
*/
|
|
70
|
+
populateEnums() {
|
|
71
|
+
Object.entries(AllEnums).forEach(([enumName, enumObject]) => {
|
|
72
|
+
if (this.isValidEnum(enumObject)) {
|
|
73
|
+
this.enums.set(enumName, enumObject);
|
|
74
|
+
this.indexEnumValues(enumName, enumObject);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Check if an object is a valid TypeScript enum
|
|
80
|
+
*/
|
|
81
|
+
isValidEnum(obj) {
|
|
82
|
+
return (obj &&
|
|
83
|
+
typeof obj === 'object' &&
|
|
84
|
+
Object.values(obj).every((value) => typeof value === 'string'));
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Index enum values and keys for fast lookup
|
|
88
|
+
*/
|
|
89
|
+
indexEnumValues(enumName, enumObject) {
|
|
90
|
+
Object.entries(enumObject).forEach(([key, value]) => {
|
|
91
|
+
// Index by value (e.g., "BUY" -> OrderSide)
|
|
92
|
+
this.enumsByValue.set(value.toLowerCase(), {
|
|
93
|
+
enum: enumObject,
|
|
94
|
+
name: enumName,
|
|
95
|
+
});
|
|
96
|
+
// Index by key (e.g., "Buy" -> OrderSide)
|
|
97
|
+
this.enumsByKey.set(key.toLowerCase(), {
|
|
98
|
+
enum: enumObject,
|
|
99
|
+
name: enumName,
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Get a specific enum by name
|
|
105
|
+
*/
|
|
106
|
+
getEnum(enumName) {
|
|
107
|
+
return this.enums.get(enumName) || null;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Get all registered enum names
|
|
111
|
+
*/
|
|
112
|
+
getAllEnumNames() {
|
|
113
|
+
return Array.from(this.enums.keys());
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Find enum by value (exact match)
|
|
117
|
+
*/
|
|
118
|
+
findEnumByValue(value) {
|
|
119
|
+
return this.enumsByValue.get(value.toLowerCase()) || null;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Find enum by key (exact match)
|
|
123
|
+
*/
|
|
124
|
+
findEnumByKey(key) {
|
|
125
|
+
return this.enumsByKey.get(key.toLowerCase()) || null;
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Get statistics about discovered enums
|
|
129
|
+
*/
|
|
130
|
+
getStats() {
|
|
131
|
+
return {
|
|
132
|
+
totalEnums: this.enums.size,
|
|
133
|
+
totalValues: this.enumsByValue.size,
|
|
134
|
+
totalKeys: this.enumsByKey.size,
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Get detailed information about all enums
|
|
139
|
+
*/
|
|
140
|
+
getEnumDetails() {
|
|
141
|
+
const details = {};
|
|
142
|
+
this.enums.forEach((enumObject, enumName) => {
|
|
143
|
+
details[enumName] = {
|
|
144
|
+
values: Object.values(enumObject),
|
|
145
|
+
keys: Object.keys(enumObject),
|
|
146
|
+
};
|
|
147
|
+
});
|
|
148
|
+
return details;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
exports.EnumRegistry = EnumRegistry;
|
|
152
|
+
// Global singleton instance
|
|
153
|
+
exports.enumRegistry = new EnumRegistry();
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright 2025-present Coinbase Global, Inc.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.DynamicEnumValidationError = void 0;
|
|
19
|
+
exports.isValueValidForEnum = isValueValidForEnum;
|
|
20
|
+
exports.detectEnumType = detectEnumType;
|
|
21
|
+
exports.analyzeField = analyzeField;
|
|
22
|
+
exports.validateEnumValue = validateEnumValue;
|
|
23
|
+
/**
|
|
24
|
+
* Core validation logic for enum fields
|
|
25
|
+
*/
|
|
26
|
+
const enumHelpers_1 = require("./enumHelpers");
|
|
27
|
+
const enumPrefixes_1 = require("../model/enumPrefixes");
|
|
28
|
+
const enumRegistry_1 = require("./enumRegistry");
|
|
29
|
+
const fieldMapping_1 = require("./fieldMapping");
|
|
30
|
+
// Sort prefixes by length (longest first) to prevent collision issues
|
|
31
|
+
const ENUM_PREFIXES = [...enumPrefixes_1.GENERATED_ENUM_PREFIXES].sort((a, b) => b.length - a.length);
|
|
32
|
+
/**
|
|
33
|
+
* Error thrown when a request contains invalid enum values
|
|
34
|
+
*/
|
|
35
|
+
class DynamicEnumValidationError extends Error {
|
|
36
|
+
constructor(field, value, enumName, validValues, validKeys) {
|
|
37
|
+
const validValuesStr = validValues.join(', ');
|
|
38
|
+
const validKeysStr = validKeys
|
|
39
|
+
? ` Valid keys: ${validKeys.join(', ')}.`
|
|
40
|
+
: '';
|
|
41
|
+
super(`Invalid ${field} (${enumName}): "${value}". Valid values: ${validValuesStr}.${validKeysStr} ` +
|
|
42
|
+
`Consider using enum helpers for automatic normalization.`);
|
|
43
|
+
this.field = field;
|
|
44
|
+
this.value = value;
|
|
45
|
+
this.enumName = enumName;
|
|
46
|
+
this.validValues = validValues;
|
|
47
|
+
this.validKeys = validKeys;
|
|
48
|
+
this.name = 'DynamicEnumValidationError';
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
exports.DynamicEnumValidationError = DynamicEnumValidationError;
|
|
52
|
+
/**
|
|
53
|
+
* Check if a value is valid for a specific enum (includes normalization)
|
|
54
|
+
*/
|
|
55
|
+
function isValueValidForEnum(value, enumObject) {
|
|
56
|
+
if (!value || !enumObject)
|
|
57
|
+
return false;
|
|
58
|
+
// Direct value match
|
|
59
|
+
if (Object.values(enumObject).includes(value))
|
|
60
|
+
return true;
|
|
61
|
+
// Direct key match
|
|
62
|
+
if (Object.keys(enumObject).includes(value))
|
|
63
|
+
return true;
|
|
64
|
+
// Normalized value matches
|
|
65
|
+
const normalizedValue = (0, enumHelpers_1.normalizeEnumValue)(value);
|
|
66
|
+
if (Object.values(enumObject).includes(normalizedValue))
|
|
67
|
+
return true;
|
|
68
|
+
// Check with prefix normalization
|
|
69
|
+
for (const prefix of ENUM_PREFIXES) {
|
|
70
|
+
const withPrefix = `${prefix}${normalizedValue}`;
|
|
71
|
+
if (Object.values(enumObject).includes(withPrefix))
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
/**
|
|
77
|
+
* Detects the enum type for a field based on field name patterns and value analysis
|
|
78
|
+
*/
|
|
79
|
+
function detectEnumType(fieldName, value, serviceName) {
|
|
80
|
+
// Strategy 1: Direct field name to enum name mapping (with service context)
|
|
81
|
+
const directMapping = (0, fieldMapping_1.getDirectEnumMapping)(fieldName, serviceName);
|
|
82
|
+
if (directMapping) {
|
|
83
|
+
const enumObject = enumRegistry_1.enumRegistry.getEnum(directMapping);
|
|
84
|
+
if (enumObject) {
|
|
85
|
+
// If we have a confident field mapping, use it even if value doesn't match
|
|
86
|
+
// This allows validation to catch invalid values
|
|
87
|
+
return { enum: enumObject, name: directMapping };
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// Strategy 2: Find enum by value (exact match)
|
|
91
|
+
const enumByValue = enumRegistry_1.enumRegistry.findEnumByValue(value);
|
|
92
|
+
if (enumByValue) {
|
|
93
|
+
return enumByValue;
|
|
94
|
+
}
|
|
95
|
+
// Strategy 3: Find enum by value with prefix normalization
|
|
96
|
+
const enumByValueWithPrefix = findEnumWithPrefixHandling(value);
|
|
97
|
+
if (enumByValueWithPrefix) {
|
|
98
|
+
return enumByValueWithPrefix;
|
|
99
|
+
}
|
|
100
|
+
// Strategy 4: Find enum by key (treating value as a potential key)
|
|
101
|
+
const enumByKey = enumRegistry_1.enumRegistry.findEnumByKey(value);
|
|
102
|
+
if (enumByKey) {
|
|
103
|
+
return enumByKey;
|
|
104
|
+
}
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Find enum by value with automatic prefix handling
|
|
109
|
+
*/
|
|
110
|
+
function findEnumWithPrefixHandling(value) {
|
|
111
|
+
const normalizedValue = (0, enumHelpers_1.normalizeEnumValue)(value);
|
|
112
|
+
// Try each prefix
|
|
113
|
+
for (const prefix of ENUM_PREFIXES) {
|
|
114
|
+
const prefixedValue = `${prefix}${normalizedValue}`;
|
|
115
|
+
const enumByPrefixedValue = enumRegistry_1.enumRegistry.findEnumByValue(prefixedValue);
|
|
116
|
+
if (enumByPrefixedValue) {
|
|
117
|
+
return enumByPrefixedValue;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return null;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Analyzes a single field to determine if it's an enum
|
|
124
|
+
*/
|
|
125
|
+
function analyzeField(fieldName, value, serviceName) {
|
|
126
|
+
if (value === undefined || value === null) {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
// Handle array values
|
|
130
|
+
if (Array.isArray(value)) {
|
|
131
|
+
const firstNonNullValue = value.find((v) => v !== null && v !== undefined);
|
|
132
|
+
if (firstNonNullValue && typeof firstNonNullValue === 'string') {
|
|
133
|
+
const enumInfo = detectEnumType(fieldName, firstNonNullValue, serviceName);
|
|
134
|
+
if (enumInfo) {
|
|
135
|
+
return {
|
|
136
|
+
fieldName,
|
|
137
|
+
enumName: enumInfo.name,
|
|
138
|
+
isOptional: false,
|
|
139
|
+
isArray: true,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
// Handle string values (potential enums)
|
|
146
|
+
if (typeof value === 'string') {
|
|
147
|
+
const enumInfo = detectEnumType(fieldName, value, serviceName);
|
|
148
|
+
if (enumInfo) {
|
|
149
|
+
return {
|
|
150
|
+
fieldName,
|
|
151
|
+
enumName: enumInfo.name,
|
|
152
|
+
isOptional: false,
|
|
153
|
+
isArray: false,
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Validate and normalize a single enum value
|
|
161
|
+
*/
|
|
162
|
+
function validateEnumValue(value, enumObject, enumName, fieldName, config) {
|
|
163
|
+
// Direct value match
|
|
164
|
+
if (Object.values(enumObject).includes(value)) {
|
|
165
|
+
return { isValid: true, normalizedValue: value };
|
|
166
|
+
}
|
|
167
|
+
// Direct key match (convert key to value)
|
|
168
|
+
const keyEntry = Object.entries(enumObject).find(([key]) => key === value);
|
|
169
|
+
if (keyEntry) {
|
|
170
|
+
return { isValid: true, normalizedValue: keyEntry[1] };
|
|
171
|
+
}
|
|
172
|
+
if (config.autoNormalize) {
|
|
173
|
+
// Try normalized value
|
|
174
|
+
const normalizedValue = (0, enumHelpers_1.normalizeEnumValue)(value);
|
|
175
|
+
if (Object.values(enumObject).includes(normalizedValue)) {
|
|
176
|
+
return { isValid: true, normalizedValue };
|
|
177
|
+
}
|
|
178
|
+
// Try with prefix normalization
|
|
179
|
+
for (const prefix of ENUM_PREFIXES) {
|
|
180
|
+
const withPrefix = `${prefix}${normalizedValue}`;
|
|
181
|
+
if (Object.values(enumObject).includes(withPrefix)) {
|
|
182
|
+
return { isValid: true, normalizedValue: withPrefix };
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// Try case-insensitive key match
|
|
186
|
+
const normalizedKey = Object.keys(enumObject).find((key) => key.toLowerCase() === value.toLowerCase());
|
|
187
|
+
if (normalizedKey) {
|
|
188
|
+
return { isValid: true, normalizedValue: enumObject[normalizedKey] };
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
// Value is invalid
|
|
192
|
+
const error = `Invalid ${fieldName} (${enumName}): "${value}". Valid values: ${Object.values(enumObject).join(', ')}. Valid keys: ${Object.keys(enumObject).join(', ')}.`;
|
|
193
|
+
return { isValid: false, error };
|
|
194
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Copyright 2025-present Coinbase Global, Inc.
|
|
4
|
+
*
|
|
5
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
* you may not use this file except in compliance with the License.
|
|
7
|
+
* You may obtain a copy of the License at
|
|
8
|
+
*
|
|
9
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
*
|
|
11
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
* See the License for the specific language governing permissions and
|
|
15
|
+
* limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18
|
+
exports.toEnumFormat = exports.TransactionEnums = exports.OrderEnums = void 0;
|
|
19
|
+
exports.createEnumValidators = createEnumValidators;
|
|
20
|
+
/**
|
|
21
|
+
* Convenient enum validators for common Prime API enums.
|
|
22
|
+
* These provide pre-configured validation for frequently used enum types.
|
|
23
|
+
*
|
|
24
|
+
* Note: Most users should use the dynamic validation system instead, which
|
|
25
|
+
* automatically handles all enums. These validators are useful for explicit
|
|
26
|
+
* control or when you need to validate individual enum values.
|
|
27
|
+
*/
|
|
28
|
+
const enumHelpers_1 = require("./enumHelpers");
|
|
29
|
+
Object.defineProperty(exports, "toEnumFormat", { enumerable: true, get: function () { return enumHelpers_1.normalizeEnumValue; } });
|
|
30
|
+
// Import specific enums for validation
|
|
31
|
+
const OrderType_1 = require("../model/enums/OrderType");
|
|
32
|
+
const OrderSide_1 = require("../model/enums/OrderSide");
|
|
33
|
+
const OrderStatus_1 = require("../model/enums/OrderStatus");
|
|
34
|
+
const TransactionType_1 = require("../model/enums/TransactionType");
|
|
35
|
+
const TimeInForceType_1 = require("../model/enums/TimeInForceType");
|
|
36
|
+
/**
|
|
37
|
+
* Order-related enum helpers
|
|
38
|
+
*/
|
|
39
|
+
exports.OrderEnums = {
|
|
40
|
+
/**
|
|
41
|
+
* Validates and normalizes order type values
|
|
42
|
+
* Accepts: 'market', 'limit', 'twap', 'block', 'vwap', 'stopLimit', 'rfq' (case-insensitive)
|
|
43
|
+
*/
|
|
44
|
+
getOrderType: (input) => (0, enumHelpers_1.getEnumValue)(OrderType_1.OrderType, input, 'OrderType'),
|
|
45
|
+
requireOrderType: (input) => (0, enumHelpers_1.requireEnumValue)(OrderType_1.OrderType, input, 'OrderType'),
|
|
46
|
+
isValidOrderType: (input) => (0, enumHelpers_1.isValidEnumValue)(OrderType_1.OrderType, input),
|
|
47
|
+
/**
|
|
48
|
+
* Validates and normalizes order side values
|
|
49
|
+
* Accepts: 'buy', 'sell' (case-insensitive)
|
|
50
|
+
*/
|
|
51
|
+
getOrderSide: (input) => (0, enumHelpers_1.getEnumValue)(OrderSide_1.OrderSide, input, 'OrderSide'),
|
|
52
|
+
requireOrderSide: (input) => (0, enumHelpers_1.requireEnumValue)(OrderSide_1.OrderSide, input, 'OrderSide'),
|
|
53
|
+
isValidOrderSide: (input) => (0, enumHelpers_1.isValidEnumValue)(OrderSide_1.OrderSide, input),
|
|
54
|
+
/**
|
|
55
|
+
* Validates and normalizes order status values
|
|
56
|
+
* Accepts: 'open', 'filled', 'cancelled', 'expired', 'failed', 'pending' (case-insensitive)
|
|
57
|
+
*/
|
|
58
|
+
getOrderStatus: (input) => (0, enumHelpers_1.getEnumValue)(OrderStatus_1.OrderStatus, input, 'OrderStatus'),
|
|
59
|
+
requireOrderStatus: (input) => (0, enumHelpers_1.requireEnumValue)(OrderStatus_1.OrderStatus, input, 'OrderStatus'),
|
|
60
|
+
isValidOrderStatus: (input) => (0, enumHelpers_1.isValidEnumValue)(OrderStatus_1.OrderStatus, input),
|
|
61
|
+
/**
|
|
62
|
+
* Validates and normalizes time in force type values
|
|
63
|
+
* Accepts: 'good_until_cancelled', 'good_until_time', 'immediate_or_cancel', 'fill_or_kill' (case-insensitive)
|
|
64
|
+
*/
|
|
65
|
+
getTimeInForceType: (input) => (0, enumHelpers_1.getEnumValue)(TimeInForceType_1.TimeInForceType, input, 'TimeInForceType'),
|
|
66
|
+
requireTimeInForceType: (input) => (0, enumHelpers_1.requireEnumValue)(TimeInForceType_1.TimeInForceType, input, 'TimeInForceType'),
|
|
67
|
+
isValidTimeInForceType: (input) => (0, enumHelpers_1.isValidEnumValue)(TimeInForceType_1.TimeInForceType, input),
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Transaction-related enum helpers
|
|
71
|
+
*/
|
|
72
|
+
exports.TransactionEnums = {
|
|
73
|
+
/**
|
|
74
|
+
* Validates and normalizes transaction type values
|
|
75
|
+
* Accepts various transaction types like 'deposit', 'withdrawal', 'internalDeposit', etc. (case-insensitive)
|
|
76
|
+
*/
|
|
77
|
+
getTransactionType: (input) => (0, enumHelpers_1.getEnumValue)(TransactionType_1.TransactionType, input, 'TransactionType'),
|
|
78
|
+
requireTransactionType: (input) => (0, enumHelpers_1.requireEnumValue)(TransactionType_1.TransactionType, input, 'TransactionType'),
|
|
79
|
+
isValidTransactionType: (input) => (0, enumHelpers_1.isValidEnumValue)(TransactionType_1.TransactionType, input),
|
|
80
|
+
};
|
|
81
|
+
/**
|
|
82
|
+
* Utility for creating custom enum validators for any enum type
|
|
83
|
+
*
|
|
84
|
+
* @param enumObject - The enum object to create validators for
|
|
85
|
+
* @param enumName - Name of the enum for error messages
|
|
86
|
+
* @returns Object with validation methods
|
|
87
|
+
*
|
|
88
|
+
* @example
|
|
89
|
+
* import { WalletType } from '../model/enums/WalletType';
|
|
90
|
+
*
|
|
91
|
+
* const WalletValidators = createEnumValidators(WalletType, 'WalletType');
|
|
92
|
+
* WalletValidators.get('trading'); // Gets WalletType value
|
|
93
|
+
* WalletValidators.require('custody'); // Gets WalletType value or throws
|
|
94
|
+
* WalletValidators.isValid('invalid'); // false
|
|
95
|
+
*/
|
|
96
|
+
function createEnumValidators(enumObject, enumName) {
|
|
97
|
+
return {
|
|
98
|
+
get: (input) => (0, enumHelpers_1.getEnumValue)(enumObject, input, enumName),
|
|
99
|
+
require: (input) => (0, enumHelpers_1.requireEnumValue)(enumObject, input, enumName),
|
|
100
|
+
isValid: (input) => (0, enumHelpers_1.isValidEnumValue)(enumObject, input),
|
|
101
|
+
values: Object.values(enumObject),
|
|
102
|
+
keys: Object.keys(enumObject),
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* @deprecated Use the dynamic validation system instead.
|
|
107
|
+
*
|
|
108
|
+
* Most users should prefer:
|
|
109
|
+
* ```javascript
|
|
110
|
+
* import { dynamicValidateRequest } from '@coinbase/prime-sdk';
|
|
111
|
+
* const validated = dynamicValidateRequest(request);
|
|
112
|
+
* ```
|
|
113
|
+
*
|
|
114
|
+
* This provides automatic validation for all enum fields without manual configuration.
|
|
115
|
+
*/
|