@open-captable-protocol/canton 0.2.230 → 0.2.232
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/functions/OpenCapTable/capTable/CapTableBatch.d.ts.map +1 -1
- package/dist/functions/OpenCapTable/capTable/CapTableBatch.js +2 -4
- package/dist/functions/OpenCapTable/capTable/CapTableBatch.js.map +1 -1
- package/dist/functions/OpenCapTable/capTable/getCapTableState.d.ts.map +1 -1
- package/dist/functions/OpenCapTable/capTable/getCapTableState.js +1 -4
- package/dist/functions/OpenCapTable/capTable/getCapTableState.js.map +1 -1
- package/dist/functions/OpenCapTable/capTable/ocfToDaml.d.ts +2 -7
- package/dist/functions/OpenCapTable/capTable/ocfToDaml.d.ts.map +1 -1
- package/dist/functions/OpenCapTable/capTable/ocfToDaml.js +3 -18
- package/dist/functions/OpenCapTable/capTable/ocfToDaml.js.map +1 -1
- package/dist/functions/OpenCapTable/convertibleIssuance/createConvertibleIssuance.d.ts +1 -1
- package/dist/functions/OpenCapTable/convertibleIssuance/createConvertibleIssuance.d.ts.map +1 -1
- package/dist/functions/OpenCapTable/convertibleIssuance/createConvertibleIssuance.js +2 -4
- package/dist/functions/OpenCapTable/convertibleIssuance/createConvertibleIssuance.js.map +1 -1
- package/dist/functions/OpenCapTable/equityCompensationIssuance/createEquityCompensationIssuance.js +1 -1
- package/dist/functions/OpenCapTable/equityCompensationIssuance/createEquityCompensationIssuance.js.map +1 -1
- package/dist/functions/OpenCapTable/issuer/createIssuer.d.ts.map +1 -1
- package/dist/functions/OpenCapTable/issuer/createIssuer.js +1 -13
- package/dist/functions/OpenCapTable/issuer/createIssuer.js.map +1 -1
- package/dist/functions/OpenCapTable/issuerAuthorization/authorizeIssuer.d.ts.map +1 -1
- package/dist/functions/OpenCapTable/issuerAuthorization/authorizeIssuer.js +1 -2
- package/dist/functions/OpenCapTable/issuerAuthorization/authorizeIssuer.js.map +1 -1
- package/dist/functions/OpenCapTable/issuerAuthorization/withdrawAuthorization.d.ts.map +1 -1
- package/dist/functions/OpenCapTable/issuerAuthorization/withdrawAuthorization.js +1 -2
- package/dist/functions/OpenCapTable/issuerAuthorization/withdrawAuthorization.js.map +1 -1
- package/dist/functions/OpenCapTable/stakeholder/getStakeholderAsOcf.d.ts.map +1 -1
- package/dist/functions/OpenCapTable/stakeholder/getStakeholderAsOcf.js.map +1 -1
- package/dist/functions/OpenCapTable/stakeholder/stakeholderDataToDaml.d.ts.map +1 -1
- package/dist/functions/OpenCapTable/stakeholder/stakeholderDataToDaml.js +1 -7
- package/dist/functions/OpenCapTable/stakeholder/stakeholderDataToDaml.js.map +1 -1
- package/dist/functions/OpenCapTable/stakeholderStatusChangeEvent/damlToOcf.d.ts +2 -1
- package/dist/functions/OpenCapTable/stakeholderStatusChangeEvent/damlToOcf.d.ts.map +1 -1
- package/dist/functions/OpenCapTable/stakeholderStatusChangeEvent/damlToOcf.js +1 -9
- package/dist/functions/OpenCapTable/stakeholderStatusChangeEvent/damlToOcf.js.map +1 -1
- package/dist/functions/OpenCapTable/stakeholderStatusChangeEvent/getStakeholderStatusChangeEventAsOcf.d.ts.map +1 -1
- package/dist/functions/OpenCapTable/stakeholderStatusChangeEvent/getStakeholderStatusChangeEventAsOcf.js +1 -8
- package/dist/functions/OpenCapTable/stakeholderStatusChangeEvent/getStakeholderStatusChangeEventAsOcf.js.map +1 -1
- package/dist/functions/OpenCapTable/stockClass/stockClassDataToDaml.d.ts.map +1 -1
- package/dist/functions/OpenCapTable/stockClass/stockClassDataToDaml.js +9 -31
- package/dist/functions/OpenCapTable/stockClass/stockClassDataToDaml.js.map +1 -1
- package/dist/functions/OpenCapTable/stockClassAuthorizedSharesAdjustment/getStockClassAuthorizedSharesAdjustmentAsOcf.d.ts.map +1 -1
- package/dist/functions/OpenCapTable/stockClassAuthorizedSharesAdjustment/getStockClassAuthorizedSharesAdjustmentAsOcf.js +0 -4
- package/dist/functions/OpenCapTable/stockClassAuthorizedSharesAdjustment/getStockClassAuthorizedSharesAdjustmentAsOcf.js.map +1 -1
- package/dist/functions/OpenCapTable/stockPlan/createStockPlan.d.ts.map +1 -1
- package/dist/functions/OpenCapTable/stockPlan/createStockPlan.js +2 -6
- package/dist/functions/OpenCapTable/stockPlan/createStockPlan.js.map +1 -1
- package/dist/functions/OpenCapTable/vestingTerms/createVestingTerms.js +3 -3
- package/dist/functions/OpenCapTable/vestingTerms/createVestingTerms.js.map +1 -1
- package/dist/functions/OpenCapTable/warrantExercise/getWarrantExerciseAsOcf.js.map +1 -1
- package/dist/functions/OpenCapTable/warrantIssuance/createWarrantIssuance.d.ts +5 -5
- package/dist/functions/OpenCapTable/warrantIssuance/createWarrantIssuance.d.ts.map +1 -1
- package/dist/functions/OpenCapTable/warrantIssuance/createWarrantIssuance.js +4 -2
- package/dist/functions/OpenCapTable/warrantIssuance/createWarrantIssuance.js.map +1 -1
- package/dist/functions/OpenCapTableReports/companyValuationReport/addObserversToCompanyValuationReport.d.ts.map +1 -1
- package/dist/functions/OpenCapTableReports/companyValuationReport/addObserversToCompanyValuationReport.js +1 -2
- package/dist/functions/OpenCapTableReports/companyValuationReport/addObserversToCompanyValuationReport.js.map +1 -1
- package/dist/functions/OpenCapTableReports/companyValuationReport/createCompanyValuationReport.d.ts.map +1 -1
- package/dist/functions/OpenCapTableReports/companyValuationReport/createCompanyValuationReport.js +1 -2
- package/dist/functions/OpenCapTableReports/companyValuationReport/createCompanyValuationReport.js.map +1 -1
- package/dist/functions/OpenCapTableReports/companyValuationReport/updateCompanyValuationReport.d.ts.map +1 -1
- package/dist/functions/OpenCapTableReports/companyValuationReport/updateCompanyValuationReport.js +1 -2
- package/dist/functions/OpenCapTableReports/companyValuationReport/updateCompanyValuationReport.js.map +1 -1
- package/dist/types/native.d.ts +76 -78
- package/dist/types/native.d.ts.map +1 -1
- package/dist/utils/entityValidators.d.ts.map +1 -1
- package/dist/utils/entityValidators.js +37 -26
- package/dist/utils/entityValidators.js.map +1 -1
- package/dist/utils/enumConversions.d.ts +6 -9
- package/dist/utils/enumConversions.d.ts.map +1 -1
- package/dist/utils/enumConversions.js +21 -18
- package/dist/utils/enumConversions.js.map +1 -1
- package/dist/utils/index.d.ts +0 -1
- package/dist/utils/index.d.ts.map +1 -1
- package/dist/utils/index.js +0 -1
- package/dist/utils/index.js.map +1 -1
- package/dist/utils/planSecurityAliases.d.ts +8 -4
- package/dist/utils/planSecurityAliases.d.ts.map +1 -1
- package/dist/utils/planSecurityAliases.js +51 -8
- package/dist/utils/planSecurityAliases.js.map +1 -1
- package/dist/utils/replicationHelpers.d.ts +0 -4
- package/dist/utils/replicationHelpers.d.ts.map +1 -1
- package/dist/utils/replicationHelpers.js +7 -9
- package/dist/utils/replicationHelpers.js.map +1 -1
- package/dist/utils/typeConversions.d.ts +32 -30
- package/dist/utils/typeConversions.d.ts.map +1 -1
- package/dist/utils/typeConversions.js +82 -90
- package/dist/utils/typeConversions.js.map +1 -1
- package/dist/utils/typeGuards.d.ts +4 -4
- package/dist/utils/typeGuards.d.ts.map +1 -1
- package/dist/utils/typeGuards.js +5 -10
- package/dist/utils/typeGuards.js.map +1 -1
- package/dist/utils/validation.d.ts +17 -17
- package/dist/utils/validation.d.ts.map +1 -1
- package/dist/utils/validation.js +48 -57
- package/dist/utils/validation.js.map +1 -1
- package/package.json +2 -2
- package/dist/utils/deprecatedFieldNormalization.d.ts +0 -881
- package/dist/utils/deprecatedFieldNormalization.d.ts.map +0 -1
- package/dist/utils/deprecatedFieldNormalization.js +0 -1462
- package/dist/utils/deprecatedFieldNormalization.js.map +0 -1
|
@@ -1,1462 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Utilities for normalizing deprecated OCF fields to their current equivalents.
|
|
4
|
-
*
|
|
5
|
-
* OCF schema evolves over time, and some fields are deprecated in favor of new ones.
|
|
6
|
-
* These utilities provide type-safe normalization and verification helpers.
|
|
7
|
-
*
|
|
8
|
-
* @example
|
|
9
|
-
* ```typescript
|
|
10
|
-
* import { normalizeSingularToArray, normalizeDeprecatedStockPlanFields } from './deprecatedFieldNormalization';
|
|
11
|
-
*
|
|
12
|
-
* // Generic singular → array normalization
|
|
13
|
-
* const stockClassIds = normalizeSingularToArray({
|
|
14
|
-
* singularValue: data.stock_class_id,
|
|
15
|
-
* arrayValue: data.stock_class_ids,
|
|
16
|
-
* });
|
|
17
|
-
*
|
|
18
|
-
* // Stock plan specific helper
|
|
19
|
-
* const normalized = normalizeDeprecatedStockPlanFields(inputData);
|
|
20
|
-
* ```
|
|
21
|
-
*/
|
|
22
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
-
exports.REQUIRED_ARRAY_FIELDS = exports.DEFAULT_INTERNAL_FIELDS = exports.DEFAULT_DEPRECATED_FIELDS = exports.OCF_DEPRECATED_FIELDS = exports.OPTION_GRANT_TYPE_TO_COMPENSATION_TYPE = exports.deprecationWarningConfig = void 0;
|
|
24
|
-
exports.emitDeprecationWarning = emitDeprecationWarning;
|
|
25
|
-
exports.normalizeSingularToArray = normalizeSingularToArray;
|
|
26
|
-
exports.normalizeDeprecatedStockPlanFields = normalizeDeprecatedStockPlanFields;
|
|
27
|
-
exports.normalizeDeprecatedStakeholderFields = normalizeDeprecatedStakeholderFields;
|
|
28
|
-
exports.checkStakeholderDeprecatedFieldUsage = checkStakeholderDeprecatedFieldUsage;
|
|
29
|
-
exports.migrateStakeholderFields = migrateStakeholderFields;
|
|
30
|
-
exports.migrateStakeholderFieldsBatch = migrateStakeholderFieldsBatch;
|
|
31
|
-
exports.convertOptionGrantTypeToCompensationType = convertOptionGrantTypeToCompensationType;
|
|
32
|
-
exports.normalizeDeprecatedEquityCompensationIssuanceFields = normalizeDeprecatedEquityCompensationIssuanceFields;
|
|
33
|
-
exports.checkEquityCompensationIssuanceDeprecatedFieldUsage = checkEquityCompensationIssuanceDeprecatedFieldUsage;
|
|
34
|
-
exports.migrateEquityCompensationIssuanceFields = migrateEquityCompensationIssuanceFields;
|
|
35
|
-
exports.migrateEquityCompensationIssuanceFieldsBatch = migrateEquityCompensationIssuanceFieldsBatch;
|
|
36
|
-
exports.checkStockPlanDeprecatedFieldUsage = checkStockPlanDeprecatedFieldUsage;
|
|
37
|
-
exports.getDeprecatedFieldMappings = getDeprecatedFieldMappings;
|
|
38
|
-
exports.getFieldDeprecation = getFieldDeprecation;
|
|
39
|
-
exports.checkDeprecatedFields = checkDeprecatedFields;
|
|
40
|
-
exports.checkDeprecatedFieldsBatch = checkDeprecatedFieldsBatch;
|
|
41
|
-
exports.checkDeprecatedFieldsForType = checkDeprecatedFieldsForType;
|
|
42
|
-
exports.migrateStockPlanFields = migrateStockPlanFields;
|
|
43
|
-
exports.migrateStockPlanFieldsBatch = migrateStockPlanFieldsBatch;
|
|
44
|
-
exports.generateDeprecationReport = generateDeprecationReport;
|
|
45
|
-
exports.validateDeprecatedFields = validateDeprecatedFields;
|
|
46
|
-
exports.createDeprecatedFieldsValidator = createDeprecatedFieldsValidator;
|
|
47
|
-
exports.assertNoDeprecatedFields = assertNoDeprecatedFields;
|
|
48
|
-
exports.registerDeprecatedFieldMapping = registerDeprecatedFieldMapping;
|
|
49
|
-
exports.getRegisteredObjectTypes = getRegisteredObjectTypes;
|
|
50
|
-
exports.getAllDeprecatedFieldMappings = getAllDeprecatedFieldMappings;
|
|
51
|
-
exports.normalizeDeprecatedOcfFields = normalizeDeprecatedOcfFields;
|
|
52
|
-
exports.hasDeprecationsForEntityType = hasDeprecationsForEntityType;
|
|
53
|
-
exports.registerEntityTypeMapping = registerEntityTypeMapping;
|
|
54
|
-
exports.normalizeOcfObject = normalizeOcfObject;
|
|
55
|
-
exports.areOcfObjectsEquivalent = areOcfObjectsEquivalent;
|
|
56
|
-
exports.compareOcfObjects = compareOcfObjects;
|
|
57
|
-
exports.normalizeRequiredArrayFields = normalizeRequiredArrayFields;
|
|
58
|
-
exports.registerRequiredArrayFields = registerRequiredArrayFields;
|
|
59
|
-
exports.getRequiredArrayFields = getRequiredArrayFields;
|
|
60
|
-
const ocfComparison_1 = require("./ocfComparison");
|
|
61
|
-
Object.defineProperty(exports, "DEFAULT_DEPRECATED_FIELDS", { enumerable: true, get: function () { return ocfComparison_1.DEFAULT_DEPRECATED_FIELDS; } });
|
|
62
|
-
Object.defineProperty(exports, "DEFAULT_INTERNAL_FIELDS", { enumerable: true, get: function () { return ocfComparison_1.DEFAULT_INTERNAL_FIELDS; } });
|
|
63
|
-
const planSecurityAliases_1 = require("./planSecurityAliases");
|
|
64
|
-
/**
|
|
65
|
-
* Global deprecation warning configuration.
|
|
66
|
-
* Can be modified for testing or to customize warning behavior.
|
|
67
|
-
*/
|
|
68
|
-
exports.deprecationWarningConfig = {
|
|
69
|
-
enabled: process.env.NODE_ENV !== 'test',
|
|
70
|
-
handler: undefined,
|
|
71
|
-
};
|
|
72
|
-
/**
|
|
73
|
-
* Emit a deprecation warning.
|
|
74
|
-
*
|
|
75
|
-
* @param details - Details about the deprecated field usage
|
|
76
|
-
*/
|
|
77
|
-
function emitDeprecationWarning(details) {
|
|
78
|
-
if (!exports.deprecationWarningConfig.enabled) {
|
|
79
|
-
return;
|
|
80
|
-
}
|
|
81
|
-
const message = `[OCF Deprecation] Field '${details.deprecatedField}' is deprecated and was auto-converted to '${details.replacementField}'.` +
|
|
82
|
-
`${details.context ? ` Context: ${details.context}` : ''}`;
|
|
83
|
-
if (exports.deprecationWarningConfig.handler) {
|
|
84
|
-
exports.deprecationWarningConfig.handler(message, details);
|
|
85
|
-
}
|
|
86
|
-
else {
|
|
87
|
-
// eslint-disable-next-line no-console -- Intentional deprecation warning to help developers migrate to current API
|
|
88
|
-
console.warn(message);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Normalize a deprecated singular field to an array field.
|
|
93
|
-
*
|
|
94
|
-
* When both singular and array values are provided, the array takes precedence.
|
|
95
|
-
* If the array is empty/undefined but singular has a value, wraps it in an array.
|
|
96
|
-
*
|
|
97
|
-
* @param params - Parameters for the normalization
|
|
98
|
-
* @returns The normalized array value (empty array if both inputs are empty/undefined)
|
|
99
|
-
*
|
|
100
|
-
* @example
|
|
101
|
-
* ```typescript
|
|
102
|
-
* // Only deprecated field provided
|
|
103
|
-
* normalizeSingularToArray({
|
|
104
|
-
* singularValue: 'class-1',
|
|
105
|
-
* arrayValue: undefined,
|
|
106
|
-
* }); // Returns ['class-1']
|
|
107
|
-
*
|
|
108
|
-
* // Both provided - array takes precedence
|
|
109
|
-
* normalizeSingularToArray({
|
|
110
|
-
* singularValue: 'class-1',
|
|
111
|
-
* arrayValue: ['class-2', 'class-3'],
|
|
112
|
-
* }); // Returns ['class-2', 'class-3']
|
|
113
|
-
*
|
|
114
|
-
* // Neither provided
|
|
115
|
-
* normalizeSingularToArray({
|
|
116
|
-
* singularValue: undefined,
|
|
117
|
-
* arrayValue: undefined,
|
|
118
|
-
* }); // Returns []
|
|
119
|
-
* ```
|
|
120
|
-
*/
|
|
121
|
-
function normalizeSingularToArray(params) {
|
|
122
|
-
const { singularValue, arrayValue, deprecatedFieldName, replacementFieldName, context } = params;
|
|
123
|
-
// If array has values, use it (ignoring deprecated singular)
|
|
124
|
-
if (Array.isArray(arrayValue) && arrayValue.length > 0) {
|
|
125
|
-
return arrayValue;
|
|
126
|
-
}
|
|
127
|
-
// If singular value exists, convert to array and emit warning
|
|
128
|
-
// Also exclude empty strings to match original truthy-check behavior
|
|
129
|
-
if (singularValue !== undefined && singularValue !== null && singularValue !== '') {
|
|
130
|
-
if (deprecatedFieldName && replacementFieldName) {
|
|
131
|
-
emitDeprecationWarning({
|
|
132
|
-
deprecatedField: deprecatedFieldName,
|
|
133
|
-
replacementField: replacementFieldName,
|
|
134
|
-
deprecatedValue: singularValue,
|
|
135
|
-
context,
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
return [singularValue];
|
|
139
|
-
}
|
|
140
|
-
// Neither provided - return empty array
|
|
141
|
-
return [];
|
|
142
|
-
}
|
|
143
|
-
/**
|
|
144
|
-
* Normalize deprecated stock plan fields.
|
|
145
|
-
*
|
|
146
|
-
* Handles the OCF deprecation of `stock_class_id` (singular) → `stock_class_ids` (array).
|
|
147
|
-
*
|
|
148
|
-
* @param data - Stock plan data that may contain deprecated fields
|
|
149
|
-
* @param context - Optional context for deprecation warnings (e.g., "stockPlan.create")
|
|
150
|
-
* @returns Object containing normalized stock_class_ids and deprecation usage flag
|
|
151
|
-
*
|
|
152
|
-
* @example
|
|
153
|
-
* ```typescript
|
|
154
|
-
* // Old format (deprecated)
|
|
155
|
-
* const result = normalizeDeprecatedStockPlanFields({
|
|
156
|
-
* stock_class_id: 'sc-1',
|
|
157
|
-
* });
|
|
158
|
-
* // Returns { stock_class_ids: ['sc-1'], usedDeprecatedField: true }
|
|
159
|
-
*
|
|
160
|
-
* // New format
|
|
161
|
-
* const result = normalizeDeprecatedStockPlanFields({
|
|
162
|
-
* stock_class_ids: ['sc-1', 'sc-2'],
|
|
163
|
-
* });
|
|
164
|
-
* // Returns { stock_class_ids: ['sc-1', 'sc-2'], usedDeprecatedField: false }
|
|
165
|
-
* ```
|
|
166
|
-
*/
|
|
167
|
-
function normalizeDeprecatedStockPlanFields(data, context) {
|
|
168
|
-
// Also exclude empty strings to match original truthy-check behavior
|
|
169
|
-
const hasDeprecatedField = data.stock_class_id !== undefined && data.stock_class_id !== null && data.stock_class_id !== '';
|
|
170
|
-
const hasCurrentField = Array.isArray(data.stock_class_ids) && data.stock_class_ids.length > 0;
|
|
171
|
-
// Only count as using deprecated field if deprecated is present and current is not
|
|
172
|
-
const usedDeprecatedField = hasDeprecatedField && !hasCurrentField;
|
|
173
|
-
// Normalize null to undefined for the generic function, then filter results
|
|
174
|
-
const singularValue = data.stock_class_id ?? undefined;
|
|
175
|
-
const arrayValue = data.stock_class_ids ?? undefined;
|
|
176
|
-
const stock_class_ids = normalizeSingularToArray({
|
|
177
|
-
singularValue,
|
|
178
|
-
arrayValue,
|
|
179
|
-
deprecatedFieldName: 'stock_class_id',
|
|
180
|
-
replacementFieldName: 'stock_class_ids',
|
|
181
|
-
context: context ?? 'StockPlan',
|
|
182
|
-
});
|
|
183
|
-
return {
|
|
184
|
-
stock_class_ids,
|
|
185
|
-
usedDeprecatedField,
|
|
186
|
-
};
|
|
187
|
-
}
|
|
188
|
-
/**
|
|
189
|
-
* Normalize deprecated stakeholder relationship fields to their canonical form.
|
|
190
|
-
*
|
|
191
|
-
* This helper accepts stakeholder data that may use the legacy singular
|
|
192
|
-
* `current_relationship` field or the newer array-based `current_relationships`
|
|
193
|
-
* field and returns a normalized representation plus metadata about deprecation use.
|
|
194
|
-
*
|
|
195
|
-
* Behavior:
|
|
196
|
-
* - If only `current_relationship` is provided, it is converted to a single-element
|
|
197
|
-
* `current_relationships` array and `usedDeprecatedField` is set to `true`.
|
|
198
|
-
* - If `current_relationships` is provided and non-empty, it is used as-is and
|
|
199
|
-
* `usedDeprecatedField` is set to `false`, even if `current_relationship` is
|
|
200
|
-
* also present.
|
|
201
|
-
* - If neither field is provided, `current_relationships` will be an empty array
|
|
202
|
-
* and `usedDeprecatedField` will be `false`.
|
|
203
|
-
*
|
|
204
|
-
* The input object is not mutated.
|
|
205
|
-
*
|
|
206
|
-
* @param data - Stakeholder data that may contain either the deprecated
|
|
207
|
-
* `current_relationship` field, the newer `current_relationships` field, or both.
|
|
208
|
-
* @param context - Optional human-readable context used when emitting deprecation
|
|
209
|
-
* warnings. Defaults to `"Stakeholder"` when not provided.
|
|
210
|
-
* @returns Normalized stakeholder relationship fields, including
|
|
211
|
-
* `current_relationships` (always an array) and a `usedDeprecatedField` flag
|
|
212
|
-
* indicating whether only the deprecated field was relied upon.
|
|
213
|
-
*
|
|
214
|
-
* @example
|
|
215
|
-
* ```typescript
|
|
216
|
-
* const normalized = normalizeDeprecatedStakeholderFields({
|
|
217
|
-
* current_relationship: 'EMPLOYEE',
|
|
218
|
-
* });
|
|
219
|
-
* normalized.current_relationships; // ['EMPLOYEE']
|
|
220
|
-
* normalized.usedDeprecatedField; // true
|
|
221
|
-
* ```
|
|
222
|
-
*
|
|
223
|
-
* @example
|
|
224
|
-
* ```typescript
|
|
225
|
-
* const normalized = normalizeDeprecatedStakeholderFields({
|
|
226
|
-
* current_relationship: 'ADVISOR',
|
|
227
|
-
* current_relationships: ['FOUNDER', 'DIRECTOR'],
|
|
228
|
-
* });
|
|
229
|
-
* // The array field takes precedence when both are present.
|
|
230
|
-
* normalized.current_relationships; // ['FOUNDER', 'DIRECTOR']
|
|
231
|
-
* normalized.usedDeprecatedField; // false
|
|
232
|
-
* ```
|
|
233
|
-
*/
|
|
234
|
-
function normalizeDeprecatedStakeholderFields(data, context) {
|
|
235
|
-
const hasDeprecatedField = data.current_relationship !== undefined && data.current_relationship !== null && data.current_relationship !== '';
|
|
236
|
-
const hasCurrentField = Array.isArray(data.current_relationships) && data.current_relationships.length > 0;
|
|
237
|
-
const usedDeprecatedField = hasDeprecatedField && !hasCurrentField;
|
|
238
|
-
const singularValue = data.current_relationship ?? undefined;
|
|
239
|
-
const arrayValue = data.current_relationships ?? undefined;
|
|
240
|
-
const current_relationships = normalizeSingularToArray({
|
|
241
|
-
singularValue,
|
|
242
|
-
arrayValue,
|
|
243
|
-
deprecatedFieldName: 'current_relationship',
|
|
244
|
-
replacementFieldName: 'current_relationships',
|
|
245
|
-
context: context ?? 'Stakeholder',
|
|
246
|
-
});
|
|
247
|
-
return { current_relationships, usedDeprecatedField };
|
|
248
|
-
}
|
|
249
|
-
/**
|
|
250
|
-
* Check stakeholder data for deprecated field usage without modifying the data.
|
|
251
|
-
*/
|
|
252
|
-
function checkStakeholderDeprecatedFieldUsage(data) {
|
|
253
|
-
const deprecatedFieldsUsed = [];
|
|
254
|
-
if (data.current_relationship !== undefined &&
|
|
255
|
-
data.current_relationship !== null &&
|
|
256
|
-
data.current_relationship !== '') {
|
|
257
|
-
deprecatedFieldsUsed.push('current_relationship');
|
|
258
|
-
}
|
|
259
|
-
return { hasDeprecatedFields: deprecatedFieldsUsed.length > 0, deprecatedFieldsUsed };
|
|
260
|
-
}
|
|
261
|
-
/**
|
|
262
|
-
* Migrate deprecated stakeholder fields to their current equivalents.
|
|
263
|
-
*/
|
|
264
|
-
function migrateStakeholderFields(data) {
|
|
265
|
-
const warnings = [];
|
|
266
|
-
const migratedFields = [];
|
|
267
|
-
const hasDeprecatedField = data.current_relationship !== undefined && data.current_relationship !== null && data.current_relationship !== '';
|
|
268
|
-
const hasCurrentField = Array.isArray(data.current_relationships) && data.current_relationships.length > 0;
|
|
269
|
-
if (hasDeprecatedField && hasCurrentField) {
|
|
270
|
-
warnings.push(`Both 'current_relationship' (deprecated) and 'current_relationships' are present. Using 'current_relationships' value.`);
|
|
271
|
-
}
|
|
272
|
-
const { current_relationships, usedDeprecatedField } = normalizeDeprecatedStakeholderFields(data);
|
|
273
|
-
if (usedDeprecatedField)
|
|
274
|
-
migratedFields.push('current_relationship');
|
|
275
|
-
const { current_relationship: _removed, ...rest } = data;
|
|
276
|
-
return {
|
|
277
|
-
data: { ...rest, current_relationships },
|
|
278
|
-
migrated: migratedFields.length > 0,
|
|
279
|
-
migratedFields,
|
|
280
|
-
warnings,
|
|
281
|
-
};
|
|
282
|
-
}
|
|
283
|
-
/**
|
|
284
|
-
* Migrate deprecated fields in multiple stakeholder objects.
|
|
285
|
-
*/
|
|
286
|
-
function migrateStakeholderFieldsBatch(items) {
|
|
287
|
-
const migratedFieldsSummary = {};
|
|
288
|
-
let itemsMigrated = 0;
|
|
289
|
-
let itemsWithWarnings = 0;
|
|
290
|
-
const migratedItems = items.map((item) => {
|
|
291
|
-
const result = migrateStakeholderFields(item);
|
|
292
|
-
if (result.migrated) {
|
|
293
|
-
itemsMigrated++;
|
|
294
|
-
for (const field of result.migratedFields) {
|
|
295
|
-
migratedFieldsSummary[field] = (migratedFieldsSummary[field] ?? 0) + 1;
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
if (result.warnings.length > 0)
|
|
299
|
-
itemsWithWarnings++;
|
|
300
|
-
return result;
|
|
301
|
-
});
|
|
302
|
-
return {
|
|
303
|
-
items: migratedItems,
|
|
304
|
-
totalProcessed: items.length,
|
|
305
|
-
itemsMigrated,
|
|
306
|
-
itemsWithWarnings,
|
|
307
|
-
migratedFieldsSummary,
|
|
308
|
-
};
|
|
309
|
-
}
|
|
310
|
-
/**
|
|
311
|
-
* Convert deprecated option_grant_type value to current compensation_type value.
|
|
312
|
-
*/
|
|
313
|
-
function convertOptionGrantTypeToCompensationType(optionGrantType) {
|
|
314
|
-
return exports.OPTION_GRANT_TYPE_TO_COMPENSATION_TYPE[optionGrantType] ?? optionGrantType;
|
|
315
|
-
}
|
|
316
|
-
/**
|
|
317
|
-
* Normalize deprecated equity compensation issuance fields to their canonical form.
|
|
318
|
-
*
|
|
319
|
-
* This helper converts the legacy `option_grant_type` field to the current
|
|
320
|
-
* `compensation_type` field, applying value mappings as needed:
|
|
321
|
-
* - `NSO` → `OPTION_NSO`
|
|
322
|
-
* - `ISO` → `OPTION_ISO`
|
|
323
|
-
* - `INTL` → `OPTION`
|
|
324
|
-
* - Unknown values are passed through unchanged
|
|
325
|
-
*
|
|
326
|
-
* Behavior:
|
|
327
|
-
* - If only `option_grant_type` is provided, it is converted to `compensation_type`
|
|
328
|
-
* with the appropriate value mapping and `usedDeprecatedField` is set to `true`.
|
|
329
|
-
* - If `compensation_type` is provided and non-empty, it is used as-is and
|
|
330
|
-
* `usedDeprecatedField` is set to `false`, even if `option_grant_type` is
|
|
331
|
-
* also present.
|
|
332
|
-
* - If neither field is provided, `compensation_type` will be `null`.
|
|
333
|
-
*
|
|
334
|
-
* The input object is not mutated.
|
|
335
|
-
*
|
|
336
|
-
* @param data - Equity compensation issuance data that may contain either the deprecated
|
|
337
|
-
* `option_grant_type` field, the newer `compensation_type` field, or both.
|
|
338
|
-
* @param context - Optional human-readable context used when emitting deprecation
|
|
339
|
-
* warnings. Defaults to `"EquityCompensationIssuance"` when not provided.
|
|
340
|
-
* @returns Normalized fields including `compensation_type`, a `usedDeprecatedField` flag,
|
|
341
|
-
* and optionally the `originalDeprecatedValue` if conversion occurred.
|
|
342
|
-
*
|
|
343
|
-
* @example
|
|
344
|
-
* ```typescript
|
|
345
|
-
* const normalized = normalizeDeprecatedEquityCompensationIssuanceFields({
|
|
346
|
-
* option_grant_type: 'NSO',
|
|
347
|
-
* });
|
|
348
|
-
* normalized.compensation_type; // 'OPTION_NSO'
|
|
349
|
-
* normalized.usedDeprecatedField; // true
|
|
350
|
-
* normalized.originalDeprecatedValue; // 'NSO'
|
|
351
|
-
* ```
|
|
352
|
-
*
|
|
353
|
-
* @example
|
|
354
|
-
* ```typescript
|
|
355
|
-
* const normalized = normalizeDeprecatedEquityCompensationIssuanceFields({
|
|
356
|
-
* option_grant_type: 'ISO',
|
|
357
|
-
* compensation_type: 'RSU',
|
|
358
|
-
* });
|
|
359
|
-
* // The current field takes precedence when both are present.
|
|
360
|
-
* normalized.compensation_type; // 'RSU'
|
|
361
|
-
* normalized.usedDeprecatedField; // false
|
|
362
|
-
* ```
|
|
363
|
-
*/
|
|
364
|
-
function normalizeDeprecatedEquityCompensationIssuanceFields(data, context) {
|
|
365
|
-
const hasDeprecatedField = data.option_grant_type !== undefined && data.option_grant_type !== null && data.option_grant_type !== '';
|
|
366
|
-
const hasCurrentField = data.compensation_type !== undefined && data.compensation_type !== null && data.compensation_type !== '';
|
|
367
|
-
const usedDeprecatedField = hasDeprecatedField && !hasCurrentField;
|
|
368
|
-
let compensation_type = null;
|
|
369
|
-
let originalDeprecatedValue;
|
|
370
|
-
if (hasCurrentField) {
|
|
371
|
-
compensation_type = data.compensation_type ?? null;
|
|
372
|
-
}
|
|
373
|
-
else if (hasDeprecatedField && data.option_grant_type) {
|
|
374
|
-
// Re-check in condition to narrow type for TypeScript
|
|
375
|
-
originalDeprecatedValue = data.option_grant_type;
|
|
376
|
-
compensation_type = convertOptionGrantTypeToCompensationType(data.option_grant_type);
|
|
377
|
-
emitDeprecationWarning({
|
|
378
|
-
deprecatedField: 'option_grant_type',
|
|
379
|
-
replacementField: 'compensation_type',
|
|
380
|
-
deprecatedValue: data.option_grant_type,
|
|
381
|
-
context: context ?? 'EquityCompensationIssuance',
|
|
382
|
-
});
|
|
383
|
-
}
|
|
384
|
-
return { compensation_type, usedDeprecatedField, originalDeprecatedValue };
|
|
385
|
-
}
|
|
386
|
-
/**
|
|
387
|
-
* Check equity compensation issuance data for deprecated field usage.
|
|
388
|
-
*/
|
|
389
|
-
function checkEquityCompensationIssuanceDeprecatedFieldUsage(data) {
|
|
390
|
-
const deprecatedFieldsUsed = [];
|
|
391
|
-
if (data.option_grant_type !== undefined && data.option_grant_type !== null && data.option_grant_type !== '') {
|
|
392
|
-
deprecatedFieldsUsed.push('option_grant_type');
|
|
393
|
-
}
|
|
394
|
-
return { hasDeprecatedFields: deprecatedFieldsUsed.length > 0, deprecatedFieldsUsed };
|
|
395
|
-
}
|
|
396
|
-
/**
|
|
397
|
-
* Migrate deprecated equity compensation issuance fields.
|
|
398
|
-
*/
|
|
399
|
-
function migrateEquityCompensationIssuanceFields(data) {
|
|
400
|
-
const warnings = [];
|
|
401
|
-
const migratedFields = [];
|
|
402
|
-
const hasDeprecatedField = data.option_grant_type !== undefined && data.option_grant_type !== null && data.option_grant_type !== '';
|
|
403
|
-
const hasCurrentField = data.compensation_type !== undefined && data.compensation_type !== null && data.compensation_type !== '';
|
|
404
|
-
if (hasDeprecatedField && hasCurrentField) {
|
|
405
|
-
warnings.push(`Both 'option_grant_type' (deprecated) and 'compensation_type' are present. Using 'compensation_type' value.`);
|
|
406
|
-
}
|
|
407
|
-
const { compensation_type, usedDeprecatedField } = normalizeDeprecatedEquityCompensationIssuanceFields(data);
|
|
408
|
-
if (usedDeprecatedField)
|
|
409
|
-
migratedFields.push('option_grant_type');
|
|
410
|
-
const { option_grant_type: _removed, ...rest } = data;
|
|
411
|
-
return {
|
|
412
|
-
data: { ...rest, compensation_type },
|
|
413
|
-
migrated: migratedFields.length > 0,
|
|
414
|
-
migratedFields,
|
|
415
|
-
warnings,
|
|
416
|
-
};
|
|
417
|
-
}
|
|
418
|
-
/**
|
|
419
|
-
* Migrate deprecated fields in multiple equity compensation issuance objects.
|
|
420
|
-
*/
|
|
421
|
-
function migrateEquityCompensationIssuanceFieldsBatch(items) {
|
|
422
|
-
const migratedFieldsSummary = {};
|
|
423
|
-
let itemsMigrated = 0;
|
|
424
|
-
let itemsWithWarnings = 0;
|
|
425
|
-
const migratedItems = items.map((item) => {
|
|
426
|
-
const result = migrateEquityCompensationIssuanceFields(item);
|
|
427
|
-
if (result.migrated) {
|
|
428
|
-
itemsMigrated++;
|
|
429
|
-
for (const field of result.migratedFields) {
|
|
430
|
-
migratedFieldsSummary[field] = (migratedFieldsSummary[field] ?? 0) + 1;
|
|
431
|
-
}
|
|
432
|
-
}
|
|
433
|
-
if (result.warnings.length > 0)
|
|
434
|
-
itemsWithWarnings++;
|
|
435
|
-
return result;
|
|
436
|
-
});
|
|
437
|
-
return {
|
|
438
|
-
items: migratedItems,
|
|
439
|
-
totalProcessed: items.length,
|
|
440
|
-
itemsMigrated,
|
|
441
|
-
itemsWithWarnings,
|
|
442
|
-
migratedFieldsSummary,
|
|
443
|
-
};
|
|
444
|
-
}
|
|
445
|
-
/**
|
|
446
|
-
* Check stock plan data for deprecated field usage without modifying the data.
|
|
447
|
-
*
|
|
448
|
-
* @param data - Stock plan data to check
|
|
449
|
-
* @returns Result indicating whether deprecated fields were used
|
|
450
|
-
*
|
|
451
|
-
* @example
|
|
452
|
-
* ```typescript
|
|
453
|
-
* const result = checkStockPlanDeprecatedFieldUsage({
|
|
454
|
-
* stock_class_id: 'sc-1', // deprecated
|
|
455
|
-
* });
|
|
456
|
-
* // Returns { hasDeprecatedFields: true, deprecatedFieldsUsed: ['stock_class_id'] }
|
|
457
|
-
* ```
|
|
458
|
-
*/
|
|
459
|
-
function checkStockPlanDeprecatedFieldUsage(data) {
|
|
460
|
-
const deprecatedFieldsUsed = [];
|
|
461
|
-
// Check for deprecated stock_class_id field (exclude empty strings to match original truthy-check behavior)
|
|
462
|
-
if (data.stock_class_id !== undefined && data.stock_class_id !== null && data.stock_class_id !== '') {
|
|
463
|
-
deprecatedFieldsUsed.push('stock_class_id');
|
|
464
|
-
}
|
|
465
|
-
return {
|
|
466
|
-
hasDeprecatedFields: deprecatedFieldsUsed.length > 0,
|
|
467
|
-
deprecatedFieldsUsed,
|
|
468
|
-
};
|
|
469
|
-
}
|
|
470
|
-
/**
|
|
471
|
-
* Value mapping for option_grant_type -> compensation_type conversion.
|
|
472
|
-
*/
|
|
473
|
-
exports.OPTION_GRANT_TYPE_TO_COMPENSATION_TYPE = {
|
|
474
|
-
NSO: 'OPTION_NSO',
|
|
475
|
-
ISO: 'OPTION_ISO',
|
|
476
|
-
INTL: 'OPTION',
|
|
477
|
-
};
|
|
478
|
-
/**
|
|
479
|
-
* Known OCF deprecated field mappings.
|
|
480
|
-
* Add new deprecations here as they are discovered.
|
|
481
|
-
*/
|
|
482
|
-
exports.OCF_DEPRECATED_FIELDS = {
|
|
483
|
-
StockPlan: [
|
|
484
|
-
{
|
|
485
|
-
deprecatedField: 'stock_class_id',
|
|
486
|
-
replacementField: 'stock_class_ids',
|
|
487
|
-
deprecationType: 'singular_to_array',
|
|
488
|
-
},
|
|
489
|
-
],
|
|
490
|
-
Stakeholder: [
|
|
491
|
-
{
|
|
492
|
-
deprecatedField: 'current_relationship',
|
|
493
|
-
replacementField: 'current_relationships',
|
|
494
|
-
deprecationType: 'singular_to_array',
|
|
495
|
-
},
|
|
496
|
-
],
|
|
497
|
-
EquityCompensationIssuance: [
|
|
498
|
-
{
|
|
499
|
-
deprecatedField: 'option_grant_type',
|
|
500
|
-
replacementField: 'compensation_type',
|
|
501
|
-
deprecationType: 'value_mapped',
|
|
502
|
-
valueMap: exports.OPTION_GRANT_TYPE_TO_COMPENSATION_TYPE,
|
|
503
|
-
},
|
|
504
|
-
],
|
|
505
|
-
};
|
|
506
|
-
/**
|
|
507
|
-
* Get the list of deprecated field mappings for an OCF object type.
|
|
508
|
-
*
|
|
509
|
-
* @param objectType - The OCF object type name (e.g., 'StockPlan')
|
|
510
|
-
* @returns Array of deprecated field mappings for the object type
|
|
511
|
-
*/
|
|
512
|
-
function getDeprecatedFieldMappings(objectType) {
|
|
513
|
-
return exports.OCF_DEPRECATED_FIELDS[objectType] ?? [];
|
|
514
|
-
}
|
|
515
|
-
/**
|
|
516
|
-
* Check if a specific field is deprecated for an OCF object type.
|
|
517
|
-
*
|
|
518
|
-
* @param objectType - The OCF object type name
|
|
519
|
-
* @param fieldName - The field name to check
|
|
520
|
-
* @returns The deprecation mapping if the field is deprecated, undefined otherwise
|
|
521
|
-
*/
|
|
522
|
-
function getFieldDeprecation(objectType, fieldName) {
|
|
523
|
-
const mappings = getDeprecatedFieldMappings(objectType);
|
|
524
|
-
return mappings.find((m) => m.deprecatedField === fieldName);
|
|
525
|
-
}
|
|
526
|
-
/**
|
|
527
|
-
* Check an object for any deprecated field usage based on known deprecations.
|
|
528
|
-
*
|
|
529
|
-
* @param objectType - The OCF object type name
|
|
530
|
-
* @param data - The object data to check
|
|
531
|
-
* @returns Result indicating which deprecated fields were used
|
|
532
|
-
*
|
|
533
|
-
* @example
|
|
534
|
-
* ```typescript
|
|
535
|
-
* const result = checkDeprecatedFields('StockPlan', {
|
|
536
|
-
* stock_class_id: 'sc-1', // deprecated
|
|
537
|
-
* plan_name: 'Equity Plan',
|
|
538
|
-
* });
|
|
539
|
-
* // Returns { hasDeprecatedFields: true, deprecatedFieldsUsed: ['stock_class_id'] }
|
|
540
|
-
* ```
|
|
541
|
-
*/
|
|
542
|
-
function checkDeprecatedFields(objectType, data) {
|
|
543
|
-
const mappings = getDeprecatedFieldMappings(objectType);
|
|
544
|
-
const deprecatedFieldsUsed = [];
|
|
545
|
-
for (const mapping of mappings) {
|
|
546
|
-
const value = data[mapping.deprecatedField];
|
|
547
|
-
// Also exclude empty strings to match original truthy-check behavior
|
|
548
|
-
if (value !== undefined && value !== null && value !== '') {
|
|
549
|
-
deprecatedFieldsUsed.push(mapping.deprecatedField);
|
|
550
|
-
}
|
|
551
|
-
}
|
|
552
|
-
return {
|
|
553
|
-
hasDeprecatedFields: deprecatedFieldsUsed.length > 0,
|
|
554
|
-
deprecatedFieldsUsed,
|
|
555
|
-
};
|
|
556
|
-
}
|
|
557
|
-
/**
|
|
558
|
-
* Check multiple objects for deprecated field usage in a single batch operation.
|
|
559
|
-
*
|
|
560
|
-
* @param items - Array of items to check, each with objectType and data
|
|
561
|
-
* @returns Aggregated result with summary statistics and per-item details
|
|
562
|
-
*
|
|
563
|
-
* @example
|
|
564
|
-
* ```typescript
|
|
565
|
-
* const result = checkDeprecatedFieldsBatch([
|
|
566
|
-
* { objectType: 'StockPlan', data: { stock_class_id: 'sc-1', plan_name: 'Plan A' }, id: 'plan-1' },
|
|
567
|
-
* { objectType: 'StockPlan', data: { stock_class_ids: ['sc-2'], plan_name: 'Plan B' }, id: 'plan-2' },
|
|
568
|
-
* ]);
|
|
569
|
-
* // result.objectsWithDeprecatedFields === 1
|
|
570
|
-
* // result.deprecatedFieldSummary === { stock_class_id: 1 }
|
|
571
|
-
* ```
|
|
572
|
-
*/
|
|
573
|
-
function checkDeprecatedFieldsBatch(items) {
|
|
574
|
-
var _a;
|
|
575
|
-
const itemsWithDeprecatedFields = [];
|
|
576
|
-
const deprecatedFieldSummary = {};
|
|
577
|
-
const objectTypeSummary = {};
|
|
578
|
-
for (let i = 0; i < items.length; i++) {
|
|
579
|
-
const item = items[i];
|
|
580
|
-
const itemId = item.id ?? `index:${i}`;
|
|
581
|
-
const result = checkDeprecatedFields(item.objectType, item.data);
|
|
582
|
-
// Update object type summary
|
|
583
|
-
objectTypeSummary[_a = item.objectType] ?? (objectTypeSummary[_a] = { total: 0, withDeprecated: 0 });
|
|
584
|
-
objectTypeSummary[item.objectType].total++;
|
|
585
|
-
if (result.hasDeprecatedFields) {
|
|
586
|
-
objectTypeSummary[item.objectType].withDeprecated++;
|
|
587
|
-
itemsWithDeprecatedFields.push({
|
|
588
|
-
itemId,
|
|
589
|
-
objectType: item.objectType,
|
|
590
|
-
...result,
|
|
591
|
-
});
|
|
592
|
-
// Update field summary
|
|
593
|
-
for (const field of result.deprecatedFieldsUsed) {
|
|
594
|
-
deprecatedFieldSummary[field] = (deprecatedFieldSummary[field] ?? 0) + 1;
|
|
595
|
-
}
|
|
596
|
-
}
|
|
597
|
-
}
|
|
598
|
-
return {
|
|
599
|
-
totalChecked: items.length,
|
|
600
|
-
objectsWithDeprecatedFields: itemsWithDeprecatedFields.length,
|
|
601
|
-
objectsWithoutDeprecatedFields: items.length - itemsWithDeprecatedFields.length,
|
|
602
|
-
hasDeprecatedFields: itemsWithDeprecatedFields.length > 0,
|
|
603
|
-
itemsWithDeprecatedFields,
|
|
604
|
-
deprecatedFieldSummary,
|
|
605
|
-
objectTypeSummary,
|
|
606
|
-
};
|
|
607
|
-
}
|
|
608
|
-
/**
|
|
609
|
-
* Check an array of objects of the same type for deprecated field usage.
|
|
610
|
-
*
|
|
611
|
-
* @param objectType - The OCF object type for all items
|
|
612
|
-
* @param items - Array of data objects to check
|
|
613
|
-
* @returns Aggregated result with summary statistics
|
|
614
|
-
*
|
|
615
|
-
* @example
|
|
616
|
-
* ```typescript
|
|
617
|
-
* const stockPlans = [
|
|
618
|
-
* { id: 'plan-1', stock_class_id: 'sc-1', plan_name: 'Plan A' },
|
|
619
|
-
* { id: 'plan-2', stock_class_ids: ['sc-2'], plan_name: 'Plan B' },
|
|
620
|
-
* ];
|
|
621
|
-
* const result = checkDeprecatedFieldsForType('StockPlan', stockPlans);
|
|
622
|
-
* ```
|
|
623
|
-
*/
|
|
624
|
-
function checkDeprecatedFieldsForType(objectType, items) {
|
|
625
|
-
const batchItems = items.map((data, index) => ({
|
|
626
|
-
objectType,
|
|
627
|
-
data,
|
|
628
|
-
id: typeof data.id === 'string' ? data.id : `index:${index}`,
|
|
629
|
-
}));
|
|
630
|
-
return checkDeprecatedFieldsBatch(batchItems);
|
|
631
|
-
}
|
|
632
|
-
/**
|
|
633
|
-
* Migrate deprecated stock plan fields to their current equivalents.
|
|
634
|
-
*
|
|
635
|
-
* This function creates a new object with deprecated fields converted to current format.
|
|
636
|
-
* The original object is not modified.
|
|
637
|
-
*
|
|
638
|
-
* @param data - Stock plan data that may contain deprecated fields
|
|
639
|
-
* @returns Migration result with normalized data and migration details
|
|
640
|
-
*
|
|
641
|
-
* @example
|
|
642
|
-
* ```typescript
|
|
643
|
-
* const result = migrateStockPlanFields({
|
|
644
|
-
* id: 'plan-1',
|
|
645
|
-
* stock_class_id: 'sc-1', // deprecated
|
|
646
|
-
* plan_name: 'Equity Plan',
|
|
647
|
-
* });
|
|
648
|
-
* // result.data.stock_class_ids === ['sc-1']
|
|
649
|
-
* // result.migrated === true
|
|
650
|
-
* // result.migratedFields === ['stock_class_id']
|
|
651
|
-
* ```
|
|
652
|
-
*/
|
|
653
|
-
function migrateStockPlanFields(data) {
|
|
654
|
-
const warnings = [];
|
|
655
|
-
const migratedFields = [];
|
|
656
|
-
const hasDeprecatedField = data.stock_class_id !== undefined && data.stock_class_id !== null && data.stock_class_id !== '';
|
|
657
|
-
const hasCurrentField = Array.isArray(data.stock_class_ids) && data.stock_class_ids.length > 0;
|
|
658
|
-
// Check for both fields present
|
|
659
|
-
if (hasDeprecatedField && hasCurrentField) {
|
|
660
|
-
warnings.push(`Both 'stock_class_id' (deprecated) and 'stock_class_ids' are present. Using 'stock_class_ids' value.`);
|
|
661
|
-
}
|
|
662
|
-
// Normalize using existing helper
|
|
663
|
-
const { stock_class_ids, usedDeprecatedField } = normalizeDeprecatedStockPlanFields(data);
|
|
664
|
-
if (usedDeprecatedField) {
|
|
665
|
-
migratedFields.push('stock_class_id');
|
|
666
|
-
}
|
|
667
|
-
// Create new object without the deprecated field
|
|
668
|
-
const { stock_class_id: _removed, ...rest } = data;
|
|
669
|
-
return {
|
|
670
|
-
data: {
|
|
671
|
-
...rest,
|
|
672
|
-
stock_class_ids,
|
|
673
|
-
},
|
|
674
|
-
migrated: migratedFields.length > 0,
|
|
675
|
-
migratedFields,
|
|
676
|
-
warnings,
|
|
677
|
-
};
|
|
678
|
-
}
|
|
679
|
-
/**
|
|
680
|
-
* Migrate deprecated fields in multiple stock plan objects.
|
|
681
|
-
*
|
|
682
|
-
* @param items - Array of stock plan data objects
|
|
683
|
-
* @returns Batch migration result with all migrated items
|
|
684
|
-
*
|
|
685
|
-
* @example
|
|
686
|
-
* ```typescript
|
|
687
|
-
* const plans = [
|
|
688
|
-
* { id: 'plan-1', stock_class_id: 'sc-1' },
|
|
689
|
-
* { id: 'plan-2', stock_class_ids: ['sc-2'] },
|
|
690
|
-
* ];
|
|
691
|
-
* const result = migrateStockPlanFieldsBatch(plans);
|
|
692
|
-
* // result.itemsMigrated === 1
|
|
693
|
-
* ```
|
|
694
|
-
*/
|
|
695
|
-
function migrateStockPlanFieldsBatch(items) {
|
|
696
|
-
const migratedFieldsSummary = {};
|
|
697
|
-
let itemsMigrated = 0;
|
|
698
|
-
let itemsWithWarnings = 0;
|
|
699
|
-
const migratedItems = items.map((item) => {
|
|
700
|
-
const result = migrateStockPlanFields(item);
|
|
701
|
-
if (result.migrated) {
|
|
702
|
-
itemsMigrated++;
|
|
703
|
-
for (const field of result.migratedFields) {
|
|
704
|
-
migratedFieldsSummary[field] = (migratedFieldsSummary[field] ?? 0) + 1;
|
|
705
|
-
}
|
|
706
|
-
}
|
|
707
|
-
if (result.warnings.length > 0) {
|
|
708
|
-
itemsWithWarnings++;
|
|
709
|
-
}
|
|
710
|
-
return result;
|
|
711
|
-
});
|
|
712
|
-
return {
|
|
713
|
-
items: migratedItems,
|
|
714
|
-
totalProcessed: items.length,
|
|
715
|
-
itemsMigrated,
|
|
716
|
-
itemsWithWarnings,
|
|
717
|
-
migratedFieldsSummary,
|
|
718
|
-
};
|
|
719
|
-
}
|
|
720
|
-
/**
|
|
721
|
-
* Generate a detailed deprecation report from batch verification results.
|
|
722
|
-
*
|
|
723
|
-
* @param batchResult - Result from checkDeprecatedFieldsBatch or checkDeprecatedFieldsForType
|
|
724
|
-
* @param options - Options for report generation
|
|
725
|
-
* @returns Detailed deprecation report
|
|
726
|
-
*
|
|
727
|
-
* @example
|
|
728
|
-
* ```typescript
|
|
729
|
-
* const items = [
|
|
730
|
-
* { objectType: 'StockPlan', data: { stock_class_id: 'sc-1' }, id: 'plan-1' },
|
|
731
|
-
* ];
|
|
732
|
-
* const batchResult = checkDeprecatedFieldsBatch(items);
|
|
733
|
-
* const report = generateDeprecationReport(batchResult);
|
|
734
|
-
* console.log(`${report.summary.deprecationPercentage}% of objects use deprecated fields`);
|
|
735
|
-
* ```
|
|
736
|
-
*/
|
|
737
|
-
function generateDeprecationReport(batchResult, options = {}) {
|
|
738
|
-
const { includeAffectedItems = false, maxAffectedItems = 100 } = options;
|
|
739
|
-
// Calculate summary
|
|
740
|
-
const deprecationPercentage = batchResult.totalChecked > 0
|
|
741
|
-
? Math.round((batchResult.objectsWithDeprecatedFields / batchResult.totalChecked) * 10000) / 100
|
|
742
|
-
: 0;
|
|
743
|
-
const totalDeprecatedFieldUsages = Object.values(batchResult.deprecatedFieldSummary).reduce((sum, count) => sum + count, 0);
|
|
744
|
-
// Build by-object-type breakdown
|
|
745
|
-
const byObjectType = {};
|
|
746
|
-
for (const [objectType, stats] of Object.entries(batchResult.objectTypeSummary)) {
|
|
747
|
-
const fieldsUsed = {};
|
|
748
|
-
// Count field usages for this object type
|
|
749
|
-
for (const item of batchResult.itemsWithDeprecatedFields) {
|
|
750
|
-
if (item.objectType === objectType) {
|
|
751
|
-
for (const field of item.deprecatedFieldsUsed) {
|
|
752
|
-
fieldsUsed[field] = (fieldsUsed[field] ?? 0) + 1;
|
|
753
|
-
}
|
|
754
|
-
}
|
|
755
|
-
}
|
|
756
|
-
byObjectType[objectType] = {
|
|
757
|
-
total: stats.total,
|
|
758
|
-
withDeprecatedFields: stats.withDeprecated,
|
|
759
|
-
deprecationPercentage: stats.total > 0 ? Math.round((stats.withDeprecated / stats.total) * 10000) / 100 : 0,
|
|
760
|
-
fieldsUsed,
|
|
761
|
-
};
|
|
762
|
-
}
|
|
763
|
-
// Build by-field breakdown
|
|
764
|
-
const byField = {};
|
|
765
|
-
for (const [field, count] of Object.entries(batchResult.deprecatedFieldSummary)) {
|
|
766
|
-
const objectTypesAffected = new Set();
|
|
767
|
-
for (const item of batchResult.itemsWithDeprecatedFields) {
|
|
768
|
-
if (item.deprecatedFieldsUsed.includes(field)) {
|
|
769
|
-
objectTypesAffected.add(item.objectType);
|
|
770
|
-
}
|
|
771
|
-
}
|
|
772
|
-
// Find the mapping for this field to get replacement info
|
|
773
|
-
let foundMapping;
|
|
774
|
-
for (const objectType of objectTypesAffected) {
|
|
775
|
-
const mapping = getFieldDeprecation(objectType, field);
|
|
776
|
-
if (mapping) {
|
|
777
|
-
foundMapping = mapping;
|
|
778
|
-
break;
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
const { replacementField = 'unknown', deprecationType = 'unknown' } = foundMapping ?? {};
|
|
782
|
-
byField[field] = {
|
|
783
|
-
totalUsages: count,
|
|
784
|
-
objectTypesAffected: Array.from(objectTypesAffected),
|
|
785
|
-
replacementField,
|
|
786
|
-
deprecationType,
|
|
787
|
-
};
|
|
788
|
-
}
|
|
789
|
-
// Build affected items list if requested
|
|
790
|
-
let affectedItems;
|
|
791
|
-
if (includeAffectedItems) {
|
|
792
|
-
affectedItems = batchResult.itemsWithDeprecatedFields.slice(0, maxAffectedItems).map((item) => ({
|
|
793
|
-
itemId: item.itemId,
|
|
794
|
-
objectType: item.objectType,
|
|
795
|
-
deprecatedFieldsUsed: item.deprecatedFieldsUsed,
|
|
796
|
-
}));
|
|
797
|
-
}
|
|
798
|
-
return {
|
|
799
|
-
generatedAt: new Date().toISOString(),
|
|
800
|
-
summary: {
|
|
801
|
-
totalObjects: batchResult.totalChecked,
|
|
802
|
-
objectsWithDeprecatedFields: batchResult.objectsWithDeprecatedFields,
|
|
803
|
-
deprecationPercentage,
|
|
804
|
-
totalDeprecatedFieldUsages,
|
|
805
|
-
},
|
|
806
|
-
byObjectType,
|
|
807
|
-
byField,
|
|
808
|
-
affectedItems,
|
|
809
|
-
};
|
|
810
|
-
}
|
|
811
|
-
/**
|
|
812
|
-
* Validate an object for deprecated field usage.
|
|
813
|
-
*
|
|
814
|
-
* This is useful for validation pipelines where you want to:
|
|
815
|
-
* - Warn users about deprecated field usage
|
|
816
|
-
* - Optionally fail validation on deprecated fields
|
|
817
|
-
* - Generate clear validation messages
|
|
818
|
-
*
|
|
819
|
-
* @param objectType - The OCF object type
|
|
820
|
-
* @param data - The data to validate
|
|
821
|
-
* @param options - Validation options
|
|
822
|
-
* @returns Validation result
|
|
823
|
-
*
|
|
824
|
-
* @example
|
|
825
|
-
* ```typescript
|
|
826
|
-
* const result = validateDeprecatedFields('StockPlan', {
|
|
827
|
-
* stock_class_id: 'sc-1',
|
|
828
|
-
* }, { treatAsError: false });
|
|
829
|
-
*
|
|
830
|
-
* if (!result.valid) {
|
|
831
|
-
* console.error(result.errors.join('\n'));
|
|
832
|
-
* } else if (result.warnings.length > 0) {
|
|
833
|
-
* console.warn(result.warnings.join('\n'));
|
|
834
|
-
* }
|
|
835
|
-
* ```
|
|
836
|
-
*/
|
|
837
|
-
function validateDeprecatedFields(objectType, data, options = {}) {
|
|
838
|
-
const { treatAsError = false, ignoreFields = [], errorMessagePrefix = '' } = options;
|
|
839
|
-
const checkResult = checkDeprecatedFields(objectType, data);
|
|
840
|
-
const errors = [];
|
|
841
|
-
const warnings = [];
|
|
842
|
-
// Filter out ignored fields
|
|
843
|
-
const relevantFields = checkResult.deprecatedFieldsUsed.filter((field) => !ignoreFields.includes(field));
|
|
844
|
-
if (relevantFields.length > 0) {
|
|
845
|
-
const messages = relevantFields.map((field) => {
|
|
846
|
-
const mapping = getFieldDeprecation(objectType, field);
|
|
847
|
-
const replacement = mapping?.replacementField ?? 'unknown';
|
|
848
|
-
const prefix = errorMessagePrefix ? `${errorMessagePrefix}: ` : '';
|
|
849
|
-
return `${prefix}Field '${field}' is deprecated. Use '${replacement}' instead.`;
|
|
850
|
-
});
|
|
851
|
-
if (treatAsError) {
|
|
852
|
-
errors.push(...messages);
|
|
853
|
-
}
|
|
854
|
-
else {
|
|
855
|
-
warnings.push(...messages);
|
|
856
|
-
}
|
|
857
|
-
}
|
|
858
|
-
return {
|
|
859
|
-
valid: errors.length === 0,
|
|
860
|
-
errors,
|
|
861
|
-
warnings,
|
|
862
|
-
checkResult: {
|
|
863
|
-
hasDeprecatedFields: relevantFields.length > 0,
|
|
864
|
-
deprecatedFieldsUsed: relevantFields,
|
|
865
|
-
},
|
|
866
|
-
};
|
|
867
|
-
}
|
|
868
|
-
/**
|
|
869
|
-
* Create a validator function for use in validation pipelines.
|
|
870
|
-
*
|
|
871
|
-
* @param objectType - The OCF object type to validate
|
|
872
|
-
* @param options - Validation options
|
|
873
|
-
* @returns A validator function that returns DeprecationValidationResult
|
|
874
|
-
*
|
|
875
|
-
* @example
|
|
876
|
-
* ```typescript
|
|
877
|
-
* const validateStockPlan = createDeprecatedFieldsValidator('StockPlan', {
|
|
878
|
-
* treatAsError: false,
|
|
879
|
-
* });
|
|
880
|
-
*
|
|
881
|
-
* // Use in a validation pipeline
|
|
882
|
-
* const result = validateStockPlan(stockPlanData);
|
|
883
|
-
* ```
|
|
884
|
-
*/
|
|
885
|
-
function createDeprecatedFieldsValidator(objectType, options = {}) {
|
|
886
|
-
return (data) => validateDeprecatedFields(objectType, data, options);
|
|
887
|
-
}
|
|
888
|
-
/**
|
|
889
|
-
* Assert that an object does not use deprecated fields.
|
|
890
|
-
* Throws an error if deprecated fields are detected.
|
|
891
|
-
*
|
|
892
|
-
* @param objectType - The OCF object type
|
|
893
|
-
* @param data - The data to check
|
|
894
|
-
* @param options - Validation options (ignoreFields only)
|
|
895
|
-
* @throws Error if deprecated fields are detected
|
|
896
|
-
*
|
|
897
|
-
* @example
|
|
898
|
-
* ```typescript
|
|
899
|
-
* try {
|
|
900
|
-
* assertNoDeprecatedFields('StockPlan', stockPlanData);
|
|
901
|
-
* // Proceed with operation
|
|
902
|
-
* } catch (error) {
|
|
903
|
-
* // Handle deprecated field usage
|
|
904
|
-
* }
|
|
905
|
-
* ```
|
|
906
|
-
*/
|
|
907
|
-
function assertNoDeprecatedFields(objectType, data, options = {}) {
|
|
908
|
-
const result = validateDeprecatedFields(objectType, data, {
|
|
909
|
-
...options,
|
|
910
|
-
treatAsError: true,
|
|
911
|
-
});
|
|
912
|
-
if (!result.valid) {
|
|
913
|
-
throw new Error(`Deprecated field usage detected: ${result.errors.join('; ')}`);
|
|
914
|
-
}
|
|
915
|
-
}
|
|
916
|
-
// ===== Helper to Register New Deprecations =====
|
|
917
|
-
/**
|
|
918
|
-
* Register a new deprecated field mapping.
|
|
919
|
-
*
|
|
920
|
-
* This is useful for extending the built-in deprecation registry with
|
|
921
|
-
* custom or newly discovered deprecations.
|
|
922
|
-
*
|
|
923
|
-
* @param objectType - The OCF object type
|
|
924
|
-
* @param mapping - The deprecation mapping to register
|
|
925
|
-
*
|
|
926
|
-
* @example
|
|
927
|
-
* ```typescript
|
|
928
|
-
* // Register a new deprecation
|
|
929
|
-
* registerDeprecatedFieldMapping('SomeOcfType', {
|
|
930
|
-
* deprecatedField: 'old_field',
|
|
931
|
-
* replacementField: 'new_fields',
|
|
932
|
-
* deprecationType: 'singular_to_array',
|
|
933
|
-
* });
|
|
934
|
-
* ```
|
|
935
|
-
*/
|
|
936
|
-
function registerDeprecatedFieldMapping(objectType, mapping) {
|
|
937
|
-
exports.OCF_DEPRECATED_FIELDS[objectType] ?? (exports.OCF_DEPRECATED_FIELDS[objectType] = []);
|
|
938
|
-
// Check if mapping already exists
|
|
939
|
-
const existing = exports.OCF_DEPRECATED_FIELDS[objectType].find((m) => m.deprecatedField === mapping.deprecatedField);
|
|
940
|
-
if (!existing) {
|
|
941
|
-
exports.OCF_DEPRECATED_FIELDS[objectType].push(mapping);
|
|
942
|
-
}
|
|
943
|
-
}
|
|
944
|
-
/**
|
|
945
|
-
* Get all registered object types that have deprecated field mappings.
|
|
946
|
-
*
|
|
947
|
-
* @returns Array of object type names
|
|
948
|
-
*/
|
|
949
|
-
function getRegisteredObjectTypes() {
|
|
950
|
-
return Object.keys(exports.OCF_DEPRECATED_FIELDS);
|
|
951
|
-
}
|
|
952
|
-
/**
|
|
953
|
-
* Get all registered deprecated field mappings.
|
|
954
|
-
*
|
|
955
|
-
* @returns Copy of the deprecated fields registry
|
|
956
|
-
*/
|
|
957
|
-
function getAllDeprecatedFieldMappings() {
|
|
958
|
-
// Return a deep copy to prevent external modification
|
|
959
|
-
const result = {};
|
|
960
|
-
for (const [key, value] of Object.entries(exports.OCF_DEPRECATED_FIELDS)) {
|
|
961
|
-
result[key] = value.map((m) => ({ ...m }));
|
|
962
|
-
}
|
|
963
|
-
return result;
|
|
964
|
-
}
|
|
965
|
-
// ===== Automatic Normalization for SDK Integration =====
|
|
966
|
-
/**
|
|
967
|
-
* Map from OcfEntityType (used in batch API) to the object type name used in deprecation registry.
|
|
968
|
-
* This allows the SDK to automatically look up deprecations based on entity type.
|
|
969
|
-
*/
|
|
970
|
-
const ENTITY_TYPE_TO_OBJECT_TYPE = {
|
|
971
|
-
stockPlan: 'StockPlan',
|
|
972
|
-
stakeholder: 'Stakeholder',
|
|
973
|
-
equityCompensationIssuance: 'EquityCompensationIssuance',
|
|
974
|
-
// Add more mappings as deprecations are discovered for other types
|
|
975
|
-
};
|
|
976
|
-
/**
|
|
977
|
-
* Automatically normalize deprecated fields in OCF data based on entity type.
|
|
978
|
-
*
|
|
979
|
-
* This function is designed to be called by the SDK internally when processing
|
|
980
|
-
* OCF data, making deprecated field handling transparent to end-users.
|
|
981
|
-
*
|
|
982
|
-
* @param entityType - The OCF entity type (e.g., 'stockPlan')
|
|
983
|
-
* @param data - The OCF data that may contain deprecated fields
|
|
984
|
-
* @param options - Optional configuration
|
|
985
|
-
* @returns The normalized data with deprecated fields converted to current format
|
|
986
|
-
*
|
|
987
|
-
* @example
|
|
988
|
-
* ```typescript
|
|
989
|
-
* // SDK automatically normalizes deprecated fields
|
|
990
|
-
* const result = normalizeDeprecatedOcfFields('stockPlan', {
|
|
991
|
-
* id: 'plan-1',
|
|
992
|
-
* stock_class_id: 'sc-1', // deprecated, automatically converted
|
|
993
|
-
* plan_name: 'Equity Plan',
|
|
994
|
-
* });
|
|
995
|
-
* // result.data.stock_class_ids === ['sc-1']
|
|
996
|
-
* ```
|
|
997
|
-
*/
|
|
998
|
-
function normalizeDeprecatedOcfFields(entityType, data, options = {}) {
|
|
999
|
-
const { emitWarnings = true, context } = options;
|
|
1000
|
-
const normalizedFields = [];
|
|
1001
|
-
const warnings = [];
|
|
1002
|
-
// Step 1: Normalize required array fields to empty arrays if null/undefined
|
|
1003
|
-
// This uses lazy cloning internally - only clones if normalization is needed
|
|
1004
|
-
const arrayNormResult = normalizeRequiredArrayFields(entityType, data);
|
|
1005
|
-
let result = arrayNormResult.data;
|
|
1006
|
-
normalizedFields.push(...arrayNormResult.normalizedFields);
|
|
1007
|
-
// Track whether we've cloned the result (arrayNormResult.data may be the original or a clone)
|
|
1008
|
-
let hasCloned = arrayNormResult.normalizedFields.length > 0;
|
|
1009
|
-
// Step 2: Look up the object type for deprecated field mappings
|
|
1010
|
-
const objectType = ENTITY_TYPE_TO_OBJECT_TYPE[entityType];
|
|
1011
|
-
// If no deprecation mappings exist for this type, return with just array normalization
|
|
1012
|
-
if (!objectType) {
|
|
1013
|
-
return {
|
|
1014
|
-
data: result,
|
|
1015
|
-
normalized: normalizedFields.length > 0,
|
|
1016
|
-
normalizedFields,
|
|
1017
|
-
warnings: [],
|
|
1018
|
-
};
|
|
1019
|
-
}
|
|
1020
|
-
const mappings = getDeprecatedFieldMappings(objectType);
|
|
1021
|
-
if (mappings.length === 0) {
|
|
1022
|
-
return {
|
|
1023
|
-
data: result,
|
|
1024
|
-
normalized: normalizedFields.length > 0,
|
|
1025
|
-
normalizedFields,
|
|
1026
|
-
warnings: [],
|
|
1027
|
-
};
|
|
1028
|
-
}
|
|
1029
|
-
// Helper to ensure we have a mutable clone
|
|
1030
|
-
const ensureCloned = () => {
|
|
1031
|
-
if (!hasCloned) {
|
|
1032
|
-
result = { ...result };
|
|
1033
|
-
hasCloned = true;
|
|
1034
|
-
}
|
|
1035
|
-
};
|
|
1036
|
-
// Track which deprecated fields we normalized (for removal at the end)
|
|
1037
|
-
const deprecatedFieldsToRemove = [];
|
|
1038
|
-
for (const mapping of mappings) {
|
|
1039
|
-
const deprecatedValue = result[mapping.deprecatedField];
|
|
1040
|
-
const hasDeprecated = deprecatedValue !== undefined && deprecatedValue !== null && deprecatedValue !== '';
|
|
1041
|
-
if (!hasDeprecated) {
|
|
1042
|
-
continue;
|
|
1043
|
-
}
|
|
1044
|
-
switch (mapping.deprecationType) {
|
|
1045
|
-
case 'singular_to_array': {
|
|
1046
|
-
const currentValue = result[mapping.replacementField];
|
|
1047
|
-
const hasCurrentArray = Array.isArray(currentValue) && currentValue.length > 0;
|
|
1048
|
-
if (!hasCurrentArray) {
|
|
1049
|
-
// Convert singular to array
|
|
1050
|
-
ensureCloned();
|
|
1051
|
-
result[mapping.replacementField] = [deprecatedValue];
|
|
1052
|
-
normalizedFields.push(mapping.deprecatedField);
|
|
1053
|
-
deprecatedFieldsToRemove.push(mapping.deprecatedField);
|
|
1054
|
-
if (emitWarnings) {
|
|
1055
|
-
emitDeprecationWarning({
|
|
1056
|
-
deprecatedField: mapping.deprecatedField,
|
|
1057
|
-
replacementField: mapping.replacementField,
|
|
1058
|
-
deprecatedValue,
|
|
1059
|
-
context: context ?? `${entityType}.create`,
|
|
1060
|
-
});
|
|
1061
|
-
}
|
|
1062
|
-
}
|
|
1063
|
-
else {
|
|
1064
|
-
// Both present - current takes precedence, emit warning
|
|
1065
|
-
warnings.push(`Both '${mapping.deprecatedField}' (deprecated) and '${mapping.replacementField}' are present. ` +
|
|
1066
|
-
`Using '${mapping.replacementField}' value.`);
|
|
1067
|
-
}
|
|
1068
|
-
break;
|
|
1069
|
-
}
|
|
1070
|
-
case 'renamed': {
|
|
1071
|
-
const currentValue = result[mapping.replacementField];
|
|
1072
|
-
const hasCurrent = currentValue !== undefined && currentValue !== null;
|
|
1073
|
-
if (!hasCurrent) {
|
|
1074
|
-
// Copy deprecated value to new field
|
|
1075
|
-
ensureCloned();
|
|
1076
|
-
result[mapping.replacementField] = deprecatedValue;
|
|
1077
|
-
normalizedFields.push(mapping.deprecatedField);
|
|
1078
|
-
deprecatedFieldsToRemove.push(mapping.deprecatedField);
|
|
1079
|
-
if (emitWarnings) {
|
|
1080
|
-
emitDeprecationWarning({
|
|
1081
|
-
deprecatedField: mapping.deprecatedField,
|
|
1082
|
-
replacementField: mapping.replacementField,
|
|
1083
|
-
deprecatedValue,
|
|
1084
|
-
context: context ?? `${entityType}.create`,
|
|
1085
|
-
});
|
|
1086
|
-
}
|
|
1087
|
-
}
|
|
1088
|
-
else {
|
|
1089
|
-
warnings.push(`Both '${mapping.deprecatedField}' (deprecated) and '${mapping.replacementField}' are present. ` +
|
|
1090
|
-
`Using '${mapping.replacementField}' value.`);
|
|
1091
|
-
}
|
|
1092
|
-
break;
|
|
1093
|
-
}
|
|
1094
|
-
case 'value_mapped': {
|
|
1095
|
-
const currentValue = result[mapping.replacementField];
|
|
1096
|
-
const hasCurrent = currentValue !== undefined && currentValue !== null && currentValue !== '';
|
|
1097
|
-
if (!hasCurrent) {
|
|
1098
|
-
// value_mapped requires string values; skip non-string types
|
|
1099
|
-
if (typeof deprecatedValue !== 'string') {
|
|
1100
|
-
warnings.push(`Expected string value for '${mapping.deprecatedField}', got ${typeof deprecatedValue}`);
|
|
1101
|
-
break;
|
|
1102
|
-
}
|
|
1103
|
-
const valueMap = mapping.valueMap ?? {};
|
|
1104
|
-
const mappedValue = valueMap[deprecatedValue] ?? deprecatedValue;
|
|
1105
|
-
ensureCloned();
|
|
1106
|
-
result[mapping.replacementField] = mappedValue;
|
|
1107
|
-
normalizedFields.push(mapping.deprecatedField);
|
|
1108
|
-
deprecatedFieldsToRemove.push(mapping.deprecatedField);
|
|
1109
|
-
if (emitWarnings) {
|
|
1110
|
-
emitDeprecationWarning({
|
|
1111
|
-
deprecatedField: mapping.deprecatedField,
|
|
1112
|
-
replacementField: mapping.replacementField,
|
|
1113
|
-
deprecatedValue,
|
|
1114
|
-
context: context ?? `${entityType}.create`,
|
|
1115
|
-
});
|
|
1116
|
-
}
|
|
1117
|
-
}
|
|
1118
|
-
else {
|
|
1119
|
-
warnings.push(`Both '${mapping.deprecatedField}' (deprecated) and '${mapping.replacementField}' are present. ` +
|
|
1120
|
-
`Using '${mapping.replacementField}' value.`);
|
|
1121
|
-
}
|
|
1122
|
-
break;
|
|
1123
|
-
}
|
|
1124
|
-
case 'removed': {
|
|
1125
|
-
// Field is removed, just warn
|
|
1126
|
-
warnings.push(`Field '${mapping.deprecatedField}' is deprecated and will be ignored. ` +
|
|
1127
|
-
`It has been removed in the current schema.`);
|
|
1128
|
-
normalizedFields.push(mapping.deprecatedField);
|
|
1129
|
-
deprecatedFieldsToRemove.push(mapping.deprecatedField);
|
|
1130
|
-
break;
|
|
1131
|
-
}
|
|
1132
|
-
}
|
|
1133
|
-
}
|
|
1134
|
-
// Remove deprecated fields from the result to keep data clean
|
|
1135
|
-
// (They've been migrated to their replacements, or removed entirely for 'removed' type)
|
|
1136
|
-
if (deprecatedFieldsToRemove.length > 0) {
|
|
1137
|
-
ensureCloned();
|
|
1138
|
-
for (const field of deprecatedFieldsToRemove) {
|
|
1139
|
-
delete result[field];
|
|
1140
|
-
}
|
|
1141
|
-
}
|
|
1142
|
-
return {
|
|
1143
|
-
data: result,
|
|
1144
|
-
normalized: normalizedFields.length > 0,
|
|
1145
|
-
normalizedFields,
|
|
1146
|
-
warnings,
|
|
1147
|
-
};
|
|
1148
|
-
}
|
|
1149
|
-
/**
|
|
1150
|
-
* Check if an entity type has registered deprecations.
|
|
1151
|
-
*
|
|
1152
|
-
* @param entityType - The OCF entity type (e.g., 'stockPlan')
|
|
1153
|
-
* @returns true if the entity type has deprecation mappings
|
|
1154
|
-
*/
|
|
1155
|
-
function hasDeprecationsForEntityType(entityType) {
|
|
1156
|
-
const objectType = ENTITY_TYPE_TO_OBJECT_TYPE[entityType];
|
|
1157
|
-
if (!objectType) {
|
|
1158
|
-
return false;
|
|
1159
|
-
}
|
|
1160
|
-
return getDeprecatedFieldMappings(objectType).length > 0;
|
|
1161
|
-
}
|
|
1162
|
-
/**
|
|
1163
|
-
* Register a mapping from entity type to object type for automatic normalization.
|
|
1164
|
-
*
|
|
1165
|
-
* @param entityType - The OcfEntityType used in batch API (e.g., 'stockPlan')
|
|
1166
|
-
* @param objectType - The object type name used in deprecation registry (e.g., 'StockPlan')
|
|
1167
|
-
*/
|
|
1168
|
-
function registerEntityTypeMapping(entityType, objectType) {
|
|
1169
|
-
ENTITY_TYPE_TO_OBJECT_TYPE[entityType] = objectType;
|
|
1170
|
-
}
|
|
1171
|
-
// ===== Unified OCF Object Normalization =====
|
|
1172
|
-
/**
|
|
1173
|
-
* Map from OCF object_type to the object type name used in deprecation registry.
|
|
1174
|
-
*/
|
|
1175
|
-
const OBJECT_TYPE_TO_REGISTRY_TYPE = {
|
|
1176
|
-
STOCK_PLAN: 'StockPlan',
|
|
1177
|
-
STAKEHOLDER: 'Stakeholder',
|
|
1178
|
-
TX_EQUITY_COMPENSATION_ISSUANCE: 'EquityCompensationIssuance',
|
|
1179
|
-
TX_PLAN_SECURITY_ISSUANCE: 'EquityCompensationIssuance',
|
|
1180
|
-
};
|
|
1181
|
-
/**
|
|
1182
|
-
* Normalize quantity_source field for OCF objects.
|
|
1183
|
-
*
|
|
1184
|
-
* Handles two scenarios to ensure consistent comparison:
|
|
1185
|
-
*
|
|
1186
|
-
* 1. When quantity is NOT present (null/undefined): quantity_source is meaningless
|
|
1187
|
-
* and should be stripped. This ensures:
|
|
1188
|
-
* - DB with { quantity_source: 'UNSPECIFIED' } (no quantity)
|
|
1189
|
-
* - Canton readback with {} (no quantity, no quantity_source)
|
|
1190
|
-
* are treated as semantically equivalent.
|
|
1191
|
-
*
|
|
1192
|
-
* 2. When quantity IS present but quantity_source is missing: quantity_source should
|
|
1193
|
-
* be set to 'UNSPECIFIED' because the OCF-to-DAML converter defaults to 'UNSPECIFIED'
|
|
1194
|
-
* when quantity is present without quantity_source. This ensures:
|
|
1195
|
-
* - DB with { quantity: '1000' } (no quantity_source)
|
|
1196
|
-
* - Canton readback with { quantity: '1000', quantity_source: 'UNSPECIFIED' }
|
|
1197
|
-
* are treated as semantically equivalent.
|
|
1198
|
-
*
|
|
1199
|
-
* @param data - OCF object that may have quantity and quantity_source fields
|
|
1200
|
-
* @returns Object with quantity_source normalized based on quantity presence
|
|
1201
|
-
*/
|
|
1202
|
-
function normalizeQuantitySource(data) {
|
|
1203
|
-
const { quantity, quantity_source: quantitySource } = data;
|
|
1204
|
-
// Case 1: Strip quantity_source if quantity is not present (null/undefined)
|
|
1205
|
-
// and quantity_source is 'UNSPECIFIED' (which is equivalent to "don't know")
|
|
1206
|
-
if ((quantity === null || quantity === undefined) && quantitySource === 'UNSPECIFIED') {
|
|
1207
|
-
const { quantity_source: _, ...rest } = data;
|
|
1208
|
-
return rest;
|
|
1209
|
-
}
|
|
1210
|
-
// Case 2: Add quantity_source: 'UNSPECIFIED' if quantity IS present but quantity_source is missing
|
|
1211
|
-
// This matches the OCF-to-DAML converter behavior that defaults to 'UNSPECIFIED'
|
|
1212
|
-
if (quantity !== null && quantity !== undefined && quantitySource === undefined) {
|
|
1213
|
-
return { ...data, quantity_source: 'UNSPECIFIED' };
|
|
1214
|
-
}
|
|
1215
|
-
return data;
|
|
1216
|
-
}
|
|
1217
|
-
/**
|
|
1218
|
-
* Normalize an OCF object by applying all deprecation normalizations.
|
|
1219
|
-
*
|
|
1220
|
-
* This function auto-detects the object type from the `object_type` field and applies:
|
|
1221
|
-
* 1. PlanSecurity -> EquityCompensation object_type normalization
|
|
1222
|
-
* 2. Deprecated field normalizations (singular->array, value mappings, etc.)
|
|
1223
|
-
* 3. Semantic normalizations (e.g., quantity_source: 'UNSPECIFIED' when quantity is absent)
|
|
1224
|
-
*/
|
|
1225
|
-
function normalizeOcfObject(data, options = {}) {
|
|
1226
|
-
const { emitWarnings = true, context } = options;
|
|
1227
|
-
const normalizedFields = [];
|
|
1228
|
-
const warnings = [];
|
|
1229
|
-
// Step 0: Normalize quantity_source (strip if UNSPECIFIED and no quantity)
|
|
1230
|
-
// This must happen before other normalizations to ensure consistent comparison
|
|
1231
|
-
let result = normalizeQuantitySource(data);
|
|
1232
|
-
// Step 1: Normalize PlanSecurity object_type to EquityCompensation
|
|
1233
|
-
result = (0, planSecurityAliases_1.normalizeOcfData)(result);
|
|
1234
|
-
const originalObjectType = data.object_type;
|
|
1235
|
-
const normalizedObjectType = result.object_type;
|
|
1236
|
-
if (originalObjectType !== normalizedObjectType && typeof originalObjectType === 'string') {
|
|
1237
|
-
normalizedFields.push('object_type');
|
|
1238
|
-
if (emitWarnings) {
|
|
1239
|
-
emitDeprecationWarning({
|
|
1240
|
-
deprecatedField: 'object_type',
|
|
1241
|
-
replacementField: 'object_type',
|
|
1242
|
-
deprecatedValue: originalObjectType,
|
|
1243
|
-
context: context ?? 'normalizeOcfObject',
|
|
1244
|
-
});
|
|
1245
|
-
}
|
|
1246
|
-
}
|
|
1247
|
-
// Step 2: Determine the registry type from object_type
|
|
1248
|
-
const objectType = typeof normalizedObjectType === 'string' ? normalizedObjectType : undefined;
|
|
1249
|
-
const registryType = objectType ? OBJECT_TYPE_TO_REGISTRY_TYPE[objectType] : undefined;
|
|
1250
|
-
if (!registryType) {
|
|
1251
|
-
return { data: result, normalized: normalizedFields.length > 0, normalizedFields, warnings };
|
|
1252
|
-
}
|
|
1253
|
-
// Step 3: Apply deprecated field normalizations
|
|
1254
|
-
const mappings = getDeprecatedFieldMappings(registryType);
|
|
1255
|
-
for (const mapping of mappings) {
|
|
1256
|
-
const deprecatedValue = result[mapping.deprecatedField];
|
|
1257
|
-
const hasDeprecated = deprecatedValue !== undefined && deprecatedValue !== null && deprecatedValue !== '';
|
|
1258
|
-
if (!hasDeprecated)
|
|
1259
|
-
continue;
|
|
1260
|
-
switch (mapping.deprecationType) {
|
|
1261
|
-
case 'singular_to_array': {
|
|
1262
|
-
const currentValue = result[mapping.replacementField];
|
|
1263
|
-
const hasCurrentArray = Array.isArray(currentValue) && currentValue.length > 0;
|
|
1264
|
-
if (!hasCurrentArray) {
|
|
1265
|
-
result = { ...result, [mapping.replacementField]: [deprecatedValue] };
|
|
1266
|
-
normalizedFields.push(mapping.deprecatedField);
|
|
1267
|
-
if (emitWarnings) {
|
|
1268
|
-
emitDeprecationWarning({
|
|
1269
|
-
deprecatedField: mapping.deprecatedField,
|
|
1270
|
-
replacementField: mapping.replacementField,
|
|
1271
|
-
deprecatedValue,
|
|
1272
|
-
context: context ?? registryType,
|
|
1273
|
-
});
|
|
1274
|
-
}
|
|
1275
|
-
}
|
|
1276
|
-
else {
|
|
1277
|
-
warnings.push(`Both '${mapping.deprecatedField}' (deprecated) and '${mapping.replacementField}' are present. Using '${mapping.replacementField}' value.`);
|
|
1278
|
-
}
|
|
1279
|
-
break;
|
|
1280
|
-
}
|
|
1281
|
-
case 'value_mapped': {
|
|
1282
|
-
const currentValue = result[mapping.replacementField];
|
|
1283
|
-
const hasCurrent = currentValue !== undefined && currentValue !== null && currentValue !== '';
|
|
1284
|
-
if (!hasCurrent) {
|
|
1285
|
-
// value_mapped requires string values; skip non-string types
|
|
1286
|
-
if (typeof deprecatedValue !== 'string') {
|
|
1287
|
-
warnings.push(`Expected string value for '${mapping.deprecatedField}', got ${typeof deprecatedValue}`);
|
|
1288
|
-
break;
|
|
1289
|
-
}
|
|
1290
|
-
const valueMap = mapping.valueMap ?? {};
|
|
1291
|
-
const mappedValue = valueMap[deprecatedValue] ?? deprecatedValue;
|
|
1292
|
-
result = { ...result, [mapping.replacementField]: mappedValue };
|
|
1293
|
-
normalizedFields.push(mapping.deprecatedField);
|
|
1294
|
-
if (emitWarnings) {
|
|
1295
|
-
emitDeprecationWarning({
|
|
1296
|
-
deprecatedField: mapping.deprecatedField,
|
|
1297
|
-
replacementField: mapping.replacementField,
|
|
1298
|
-
deprecatedValue,
|
|
1299
|
-
context: context ?? registryType,
|
|
1300
|
-
});
|
|
1301
|
-
}
|
|
1302
|
-
}
|
|
1303
|
-
else {
|
|
1304
|
-
warnings.push(`Both '${mapping.deprecatedField}' (deprecated) and '${mapping.replacementField}' are present. Using '${mapping.replacementField}' value.`);
|
|
1305
|
-
}
|
|
1306
|
-
break;
|
|
1307
|
-
}
|
|
1308
|
-
case 'renamed': {
|
|
1309
|
-
const currentValue = result[mapping.replacementField];
|
|
1310
|
-
const hasCurrent = currentValue !== undefined && currentValue !== null;
|
|
1311
|
-
if (!hasCurrent) {
|
|
1312
|
-
result = { ...result, [mapping.replacementField]: deprecatedValue };
|
|
1313
|
-
normalizedFields.push(mapping.deprecatedField);
|
|
1314
|
-
if (emitWarnings) {
|
|
1315
|
-
emitDeprecationWarning({
|
|
1316
|
-
deprecatedField: mapping.deprecatedField,
|
|
1317
|
-
replacementField: mapping.replacementField,
|
|
1318
|
-
deprecatedValue,
|
|
1319
|
-
context: context ?? registryType,
|
|
1320
|
-
});
|
|
1321
|
-
}
|
|
1322
|
-
}
|
|
1323
|
-
else {
|
|
1324
|
-
warnings.push(`Both '${mapping.deprecatedField}' (deprecated) and '${mapping.replacementField}' are present. Using '${mapping.replacementField}' value.`);
|
|
1325
|
-
}
|
|
1326
|
-
break;
|
|
1327
|
-
}
|
|
1328
|
-
case 'removed': {
|
|
1329
|
-
warnings.push(`Field '${mapping.deprecatedField}' is deprecated and will be ignored.`);
|
|
1330
|
-
normalizedFields.push(mapping.deprecatedField);
|
|
1331
|
-
break;
|
|
1332
|
-
}
|
|
1333
|
-
}
|
|
1334
|
-
}
|
|
1335
|
-
// Step 4: Remove deprecated fields from the result
|
|
1336
|
-
// Note: The `as T` assertion is intentional - TypeScript cannot track field removal through
|
|
1337
|
-
// computed property spread. The result type may differ from T (deprecated fields removed),
|
|
1338
|
-
// but this is the expected behavior and callers handle it via Record<string, unknown>.
|
|
1339
|
-
for (const mapping of mappings) {
|
|
1340
|
-
if (normalizedFields.includes(mapping.deprecatedField) && mapping.deprecatedField !== 'object_type') {
|
|
1341
|
-
const { [mapping.deprecatedField]: _removed, ...rest } = result;
|
|
1342
|
-
result = rest;
|
|
1343
|
-
}
|
|
1344
|
-
}
|
|
1345
|
-
return { data: result, normalized: normalizedFields.length > 0, normalizedFields, warnings };
|
|
1346
|
-
}
|
|
1347
|
-
/**
|
|
1348
|
-
* Compare two OCF objects for semantic equivalence after normalizing deprecated fields.
|
|
1349
|
-
*/
|
|
1350
|
-
function areOcfObjectsEquivalent(dbObject, chainObject, options = {}) {
|
|
1351
|
-
const result = compareOcfObjects(dbObject, chainObject, options);
|
|
1352
|
-
return result.equivalent;
|
|
1353
|
-
}
|
|
1354
|
-
/**
|
|
1355
|
-
* Compare two OCF objects with detailed results.
|
|
1356
|
-
*/
|
|
1357
|
-
function compareOcfObjects(dbObject, chainObject, options = {}) {
|
|
1358
|
-
const { normalizeBeforeCompare = true, emitNormalizationWarnings = false, ignoredFields = [...ocfComparison_1.DEFAULT_INTERNAL_FIELDS], deprecatedFields = [...ocfComparison_1.DEFAULT_DEPRECATED_FIELDS], reportDifferences, } = options;
|
|
1359
|
-
let normalizedA = dbObject;
|
|
1360
|
-
let normalizedB = chainObject;
|
|
1361
|
-
let normResultA = { normalized: false, normalizedFields: [], warnings: [] };
|
|
1362
|
-
let normResultB = { normalized: false, normalizedFields: [], warnings: [] };
|
|
1363
|
-
if (normalizeBeforeCompare) {
|
|
1364
|
-
const resultA = normalizeOcfObject(dbObject, { emitWarnings: emitNormalizationWarnings });
|
|
1365
|
-
normalizedA = resultA.data;
|
|
1366
|
-
normResultA = {
|
|
1367
|
-
normalized: resultA.normalized,
|
|
1368
|
-
normalizedFields: resultA.normalizedFields,
|
|
1369
|
-
warnings: resultA.warnings,
|
|
1370
|
-
};
|
|
1371
|
-
const resultB = normalizeOcfObject(chainObject, { emitWarnings: emitNormalizationWarnings });
|
|
1372
|
-
normalizedB = resultB.data;
|
|
1373
|
-
normResultB = {
|
|
1374
|
-
normalized: resultB.normalized,
|
|
1375
|
-
normalizedFields: resultB.normalizedFields,
|
|
1376
|
-
warnings: resultB.warnings,
|
|
1377
|
-
};
|
|
1378
|
-
}
|
|
1379
|
-
const equivalent = (0, ocfComparison_1.ocfDeepEqual)(normalizedA, normalizedB, { ignoredFields, deprecatedFields, reportDifferences });
|
|
1380
|
-
return {
|
|
1381
|
-
equivalent,
|
|
1382
|
-
normalizationA: {
|
|
1383
|
-
wasNormalized: normResultA.normalized,
|
|
1384
|
-
normalizedFields: normResultA.normalizedFields,
|
|
1385
|
-
warnings: normResultA.warnings,
|
|
1386
|
-
},
|
|
1387
|
-
normalizationB: {
|
|
1388
|
-
wasNormalized: normResultB.normalized,
|
|
1389
|
-
normalizedFields: normResultB.normalizedFields,
|
|
1390
|
-
warnings: normResultB.warnings,
|
|
1391
|
-
},
|
|
1392
|
-
};
|
|
1393
|
-
}
|
|
1394
|
-
// ===== Required Array Field Normalization =====
|
|
1395
|
-
/**
|
|
1396
|
-
* Configuration for required array fields by entity type.
|
|
1397
|
-
* These fields must be arrays (empty or populated), but raw data might have them as null/undefined.
|
|
1398
|
-
* The SDK normalizes these to empty arrays automatically.
|
|
1399
|
-
*/
|
|
1400
|
-
exports.REQUIRED_ARRAY_FIELDS = {
|
|
1401
|
-
// issuer is handled separately in createIssuer.ts
|
|
1402
|
-
stockPlan: ['stock_class_ids'],
|
|
1403
|
-
convertibleIssuance: ['conversion_triggers', 'security_law_exemptions'],
|
|
1404
|
-
warrantIssuance: ['exercise_triggers', 'security_law_exemptions'],
|
|
1405
|
-
stakeholderRelationshipChangeEvent: ['new_relationships'],
|
|
1406
|
-
// vestingTerms.vesting_conditions requires at least one condition, so we don't auto-normalize to empty
|
|
1407
|
-
// resulting_security_ids must be explicitly provided, not auto-normalized
|
|
1408
|
-
};
|
|
1409
|
-
/**
|
|
1410
|
-
* Normalize required array fields in OCF data.
|
|
1411
|
-
* This ensures array fields that are null/undefined become empty arrays.
|
|
1412
|
-
*
|
|
1413
|
-
* Uses lazy cloning - only creates a copy when modification is actually needed,
|
|
1414
|
-
* and clones once then mutates the clone for efficiency.
|
|
1415
|
-
*
|
|
1416
|
-
* @param entityType - The OCF entity type
|
|
1417
|
-
* @param data - The OCF data that may have null/undefined array fields
|
|
1418
|
-
* @returns The normalized data with array fields as arrays
|
|
1419
|
-
*/
|
|
1420
|
-
function normalizeRequiredArrayFields(entityType, data) {
|
|
1421
|
-
const requiredArrays = exports.REQUIRED_ARRAY_FIELDS[entityType];
|
|
1422
|
-
if (!requiredArrays || requiredArrays.length === 0) {
|
|
1423
|
-
return { data, normalizedFields: [] };
|
|
1424
|
-
}
|
|
1425
|
-
// First pass: identify which fields need normalization
|
|
1426
|
-
const fieldsToNormalize = [];
|
|
1427
|
-
for (const field of requiredArrays) {
|
|
1428
|
-
const value = data[field];
|
|
1429
|
-
if (value === null || value === undefined) {
|
|
1430
|
-
fieldsToNormalize.push(field);
|
|
1431
|
-
}
|
|
1432
|
-
}
|
|
1433
|
-
// If no fields need normalization, return original data (no clone)
|
|
1434
|
-
if (fieldsToNormalize.length === 0) {
|
|
1435
|
-
return { data, normalizedFields: [] };
|
|
1436
|
-
}
|
|
1437
|
-
// Clone once, then mutate the clone for all fields
|
|
1438
|
-
const result = { ...data };
|
|
1439
|
-
for (const field of fieldsToNormalize) {
|
|
1440
|
-
result[field] = [];
|
|
1441
|
-
}
|
|
1442
|
-
return { data: result, normalizedFields: fieldsToNormalize };
|
|
1443
|
-
}
|
|
1444
|
-
/**
|
|
1445
|
-
* Register required array fields for an entity type.
|
|
1446
|
-
*
|
|
1447
|
-
* @param entityType - The OCF entity type (e.g., 'stockPlan')
|
|
1448
|
-
* @param fields - Array of field names that must be arrays
|
|
1449
|
-
*/
|
|
1450
|
-
function registerRequiredArrayFields(entityType, fields) {
|
|
1451
|
-
exports.REQUIRED_ARRAY_FIELDS[entityType] = fields;
|
|
1452
|
-
}
|
|
1453
|
-
/**
|
|
1454
|
-
* Get required array fields for an entity type.
|
|
1455
|
-
*
|
|
1456
|
-
* @param entityType - The OCF entity type
|
|
1457
|
-
* @returns Array of field names that must be arrays
|
|
1458
|
-
*/
|
|
1459
|
-
function getRequiredArrayFields(entityType) {
|
|
1460
|
-
return exports.REQUIRED_ARRAY_FIELDS[entityType] ?? [];
|
|
1461
|
-
}
|
|
1462
|
-
//# sourceMappingURL=deprecatedFieldNormalization.js.map
|