lucid-extension-sdk 0.0.409 → 0.0.410

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.
@@ -6,7 +6,7 @@ type ObjectAttributeType = keyof any;
6
6
  /**
7
7
  * A generic type for a Validator that narrows FROM to TO.
8
8
  */
9
- type Validator<TO extends FROM, FROM = unknown> = (unknownVariable: FROM) => unknownVariable is TO;
9
+ export type Validator<TO extends FROM, FROM = unknown> = (unknownVariable: FROM) => unknownVariable is TO;
10
10
  /**
11
11
  * A record that maps each key in an object to its respective ValidatorWithOptionalPruner.
12
12
  */
@@ -16,7 +16,7 @@ type ObjectValidatorConfig = Record<ObjectAttributeType, ValidatorWithOptionalPr
16
16
  * - prunerResult: The pruned data (or possibly the same data if no pruning is needed) which also constains
17
17
  * invalidFields: a map of invalid fields (represented by keys) to their original invalid values.
18
18
  */
19
- type Pruner = (unprunedData: unknown) => PrunerResult;
19
+ export type Pruner = (unprunedData: unknown) => PrunerResult;
20
20
  /**
21
21
  * The result object returned from a pruner function.
22
22
  */
@@ -30,11 +30,11 @@ export interface PrunerResult {
30
30
  * - `validator` is the function used to validate the data.
31
31
  * - `pruner` can optionally used to prune invalid data fields if validation fails.
32
32
  */
33
- interface ValidatorWithOptionalPruner<TO = unknown> {
33
+ export interface ValidatorWithOptionalPruner<TO = unknown> {
34
34
  'validator': Validator<TO>;
35
35
  'pruner'?: Pruner;
36
36
  }
37
- interface ValidatorWithPruner<TO = unknown> {
37
+ export interface ValidatorWithPruner<TO = unknown> {
38
38
  'validator': Validator<TO>;
39
39
  'pruner': Pruner;
40
40
  }
@@ -51,19 +51,21 @@ type ExtractValidatedTypeFromConfig<V> = V extends {
51
51
  type ObjectValidatorToValidatedType<T extends ObjectValidatorConfig> = WithUndefinedAsOptional<{
52
52
  [K in keyof T]: ExtractValidatedTypeFromConfig<T[K]>;
53
53
  }>;
54
+ type Primitive = string | number | boolean | null | undefined | symbol | bigint;
55
+ type ExcludedTypes = ((...args: any[]) => any) | Primitive | Date;
54
56
  /**
55
57
  * Recursively applies a "prettifying" transformation to the inferred object type.
56
58
  * - For functions, it leaves them as-is.
57
59
  * - For objects, it recurses down into properties.
58
60
  * - Otherwise, returns the type unchanged.
59
61
  */
60
- type PrettifyDeep<T> = T extends (...args: any[]) => any ? T : T extends object ? {
62
+ type PrettifyDeep<T> = T extends ExcludedTypes ? T : T extends object ? {
61
63
  [K in keyof T]: PrettifyDeep<T[K]>;
62
64
  } : T;
63
65
  /**
64
66
  * Extracts the final type from @param ObjectValidatorConfig
65
67
  */
66
- type PrettifiedObjectValidatorType<T extends ObjectValidatorConfig> = PrettifyDeep<ObjectValidatorToValidatedType<T>>;
68
+ export type PrettifiedObjectValidatorType<T extends ObjectValidatorConfig> = PrettifyDeep<ObjectValidatorToValidatedType<T>>;
67
69
  export type ExtractValidatedTypeFromValidator<V extends Validator<unknown>> = V extends Validator<infer U> ? U : never;
68
70
  /**
69
71
  * Creates a validator and pruner for an object.
@@ -85,6 +87,14 @@ export declare function getObjectValidatorAndPruner<T extends ObjectValidatorCon
85
87
  * @returns ValidatorWithPruner for the array.
86
88
  */
87
89
  export declare function getArrayValidatorAndPruner<ElementType>(arrayElementConfig: ValidatorWithOptionalPruner<ElementType> | Validator<ElementType>): ValidatorWithPruner<ElementType[]>;
90
+ /**
91
+ * Creates a validator and pruner for objects keyed by K and valued by T.
92
+ *
93
+ * @param valueConfig Validator (and optional pruner) for each object's value.
94
+ * @param keyConfig Validator (and optional pruner) for each object's key.
95
+ * @returns A ValidatorWithPruner for a Record<K, T>.
96
+ */
97
+ export declare function getObjectOfValidatorAndPruner<T, K extends string | number | symbol = string>(valueConfig: ValidatorWithOptionalPruner<T> | Validator<T>, keyValidator?: Validator<K>): ValidatorWithPruner<Record<K, T>>;
88
98
  /**
89
99
  * Function used in objectFieldConfig and arrayElementConfig to speficy that invalid
90
100
  * items must be pruned/marked as undefined.
@@ -92,20 +102,44 @@ export declare function getArrayValidatorAndPruner<ElementType>(arrayElementConf
92
102
  */
93
103
  export declare const pruneElement: (element: unknown) => PrunerResult;
94
104
  /**
95
- * Combines a "per-element pruner" for an array’s elements with an "entire array pruner."
105
+ * Selects and applies one of two pruners based on whether the input data is an array.
106
+ *
107
+ * This function acts as a router. If the input `data` is an array, it delegates the pruning
108
+ * task to the `prunerForArray`. If the input `data` is *not* an array (e.g., could be null,
109
+ * a string, an object, etc.), it delegates to the `prunerForNonArray`.
110
+ *
111
+ * Use Case: This is useful when you need distinct pruning logic depending on whether you
112
+ * received an array or something else entirely at a specific point in your data structure.
113
+ * For instance, you might have a pruner designed to process arrays (perhaps iterating
114
+ * through elements) and another pruner designed to handle scalar values or objects that
115
+ * might appear in the same data field.
116
+ *
117
+ * @param prunerForArray The Pruner function to execute if the input `data` is an array.
118
+ * This pruner is responsible for handling the entire array data.
119
+ * @param prunerForNonArray The Pruner function to execute if the input `data` is *not* an array.
120
+ * @returns A new Pruner function that implements this conditional logic.
121
+ */
122
+ export declare function selectPrunerByArrayType(prunerForArray: Pruner, prunerForNonArray: Pruner): Pruner;
123
+ /**
124
+ * Selects and applies one of two pruners based on whether the input data is an object.
96
125
  *
97
- * - If the incoming data is not an array, it applies the `wholeArrayPruner`.
98
- * - If it is an array, it applies the `perElementPruner` to each element.
126
+ * This function acts as a router. If the input `data` is an object it delegates the
127
+ * pruning task to the `prunerForObject`. If the input `data` is *not*
128
+ * an object (e.g., could be null, an array, a string, a number, etc.), it delegates
129
+ * to the `prunerForNonObject`.
99
130
  *
100
- * This is useful when you have specialized logic for array-level pruning
101
- * (e.g., removing the entire array if it fails some overarching condition)
102
- * but still want to prune individual elements if possible.
131
+ * Use Case: Similar to `selectPrunerByArrayType`, this is useful for applying different
132
+ * pruning strategies based on whether the data at a certain point is an object or some other
133
+ * type. For example, within an array pruner you can use this to apply an object pruner
134
+ * if an element is an object, but use a simpler pruner (like `pruneElement` which will
135
+ * remove `null` or invalid types) if the element is not an object.
103
136
  *
104
- * @param perElementPruner A pruner for each element in the array.
105
- * @param wholeArrayPruner A pruner for the entire array.
106
- * @returns A Pruner that handles both array-level and element-level pruning.
137
+ * @param prunerForObject The Pruner function to execute if the input `data` is an object.
138
+ * This pruner is responsible for handling the entire object data.
139
+ * @param prunerForNonObject The Pruner function to execute if the input `data` is *not* an object.
140
+ * @returns A new Pruner function that implements this conditional logic.
107
141
  */
108
- export declare function liftArrayPruner(perElementPruner: Pruner, wholeArrayPruner: Pruner): Pruner;
142
+ export declare function selectPrunerByObjectType(prunerForObject: Pruner, prunerForNonObject: Pruner): Pruner;
109
143
  /**
110
144
  * Helper function to easily create a `ValidatorWithOptionalPruner`.
111
145
  *
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getValidatorPrunerConfig = exports.liftArrayPruner = exports.pruneElement = exports.getArrayValidatorAndPruner = exports.getObjectValidatorAndPruner = void 0;
3
+ exports.getValidatorPrunerConfig = exports.selectPrunerByObjectType = exports.selectPrunerByArrayType = exports.pruneElement = exports.getObjectOfValidatorAndPruner = exports.getArrayValidatorAndPruner = exports.getObjectValidatorAndPruner = void 0;
4
4
  const checks_1 = require("../checks");
5
5
  function getValidatorFromConfig(validatorConfig) {
6
6
  if ('validator' in validatorConfig) {
@@ -115,6 +115,56 @@ function getArrayValidatorAndPruner(arrayElementConfig) {
115
115
  return { validator: arrayValidatorFunction, pruner: arrayPrunerFunction };
116
116
  }
117
117
  exports.getArrayValidatorAndPruner = getArrayValidatorAndPruner;
118
+ /**
119
+ * Creates a validator and pruner for objects keyed by K and valued by T.
120
+ *
121
+ * @param valueConfig Validator (and optional pruner) for each object's value.
122
+ * @param keyConfig Validator (and optional pruner) for each object's key.
123
+ * @returns A ValidatorWithPruner for a Record<K, T>.
124
+ */
125
+ function getObjectOfValidatorAndPruner(valueConfig, keyValidator = (key) => true) {
126
+ const valueValidator = getValidatorFromConfig(valueConfig);
127
+ const valuePruner = getPrunerFromConfig(valueConfig);
128
+ const objectOfValidator = (subject) => {
129
+ if ((0, checks_1.isArray)(subject) || !(0, checks_1.isObjectUnsafe)(subject)) {
130
+ return false;
131
+ }
132
+ return Object.entries(subject).every(([k, v]) => keyValidator(k) && valueValidator(v));
133
+ };
134
+ const objectOfPruner = (subject) => {
135
+ if ((0, checks_1.isArray)(subject) || !(0, checks_1.isObjectUnsafe)(subject)) {
136
+ return {
137
+ prunerResult: subject,
138
+ invalidFields: createElementInvalidField(subject),
139
+ };
140
+ }
141
+ const invalidFields = new Map();
142
+ const prunerResult = Object.assign({}, subject);
143
+ Object.entries(prunerResult).forEach(([k, v]) => {
144
+ if (!keyValidator(k)) {
145
+ invalidFields.set(`key:${k}`, v);
146
+ // If the key is invalid, we remove the key-value pair from the object.
147
+ prunerResult[k] = undefined;
148
+ return;
149
+ }
150
+ if (!valueValidator(v)) {
151
+ if (!valuePruner) {
152
+ invalidFields.set(k, v);
153
+ }
154
+ else {
155
+ const valPrunerResult = valuePruner(v);
156
+ prunerResult[k] = valPrunerResult.prunerResult;
157
+ for (const [subKey, subVal] of valPrunerResult.invalidFields) {
158
+ invalidFields.set(`${k}.${subKey}`, subVal);
159
+ }
160
+ }
161
+ }
162
+ });
163
+ return { prunerResult, invalidFields };
164
+ };
165
+ return { validator: objectOfValidator, pruner: objectOfPruner };
166
+ }
167
+ exports.getObjectOfValidatorAndPruner = getObjectOfValidatorAndPruner;
118
168
  /**
119
169
  * Creates a Map signifying that the entire `element` was invalid,
120
170
  * with a key of `""` or some placeholder to represent the entire item.
@@ -132,28 +182,68 @@ const pruneElement = (element) => {
132
182
  };
133
183
  exports.pruneElement = pruneElement;
134
184
  /**
135
- * Combines a "per-element pruner" for an array’s elements with an "entire array pruner."
185
+ * Selects and applies one of two pruners based on whether the input data is an array.
186
+ *
187
+ * This function acts as a router. If the input `data` is an array, it delegates the pruning
188
+ * task to the `prunerForArray`. If the input `data` is *not* an array (e.g., could be null,
189
+ * a string, an object, etc.), it delegates to the `prunerForNonArray`.
190
+ *
191
+ * Use Case: This is useful when you need distinct pruning logic depending on whether you
192
+ * received an array or something else entirely at a specific point in your data structure.
193
+ * For instance, you might have a pruner designed to process arrays (perhaps iterating
194
+ * through elements) and another pruner designed to handle scalar values or objects that
195
+ * might appear in the same data field.
196
+ *
197
+ * @param prunerForArray The Pruner function to execute if the input `data` is an array.
198
+ * This pruner is responsible for handling the entire array data.
199
+ * @param prunerForNonArray The Pruner function to execute if the input `data` is *not* an array.
200
+ * @returns A new Pruner function that implements this conditional logic.
201
+ */
202
+ function selectPrunerByArrayType(prunerForArray, prunerForNonArray) {
203
+ return (data) => {
204
+ if ((0, checks_1.isArray)(data)) {
205
+ // Data is an array, apply the pruner designated for arrays.
206
+ return prunerForArray(data);
207
+ }
208
+ else {
209
+ // Data is not an array, apply the pruner designated for non-arrays.
210
+ return prunerForNonArray(data);
211
+ }
212
+ };
213
+ }
214
+ exports.selectPrunerByArrayType = selectPrunerByArrayType;
215
+ /**
216
+ * Selects and applies one of two pruners based on whether the input data is an object.
136
217
  *
137
- * - If the incoming data is not an array, it applies the `wholeArrayPruner`.
138
- * - If it is an array, it applies the `perElementPruner` to each element.
218
+ * This function acts as a router. If the input `data` is an object it delegates the
219
+ * pruning task to the `prunerForObject`. If the input `data` is *not*
220
+ * an object (e.g., could be null, an array, a string, a number, etc.), it delegates
221
+ * to the `prunerForNonObject`.
139
222
  *
140
- * This is useful when you have specialized logic for array-level pruning
141
- * (e.g., removing the entire array if it fails some overarching condition)
142
- * but still want to prune individual elements if possible.
223
+ * Use Case: Similar to `selectPrunerByArrayType`, this is useful for applying different
224
+ * pruning strategies based on whether the data at a certain point is an object or some other
225
+ * type. For example, within an array pruner you can use this to apply an object pruner
226
+ * if an element is an object, but use a simpler pruner (like `pruneElement` which will
227
+ * remove `null` or invalid types) if the element is not an object.
143
228
  *
144
- * @param perElementPruner A pruner for each element in the array.
145
- * @param wholeArrayPruner A pruner for the entire array.
146
- * @returns A Pruner that handles both array-level and element-level pruning.
229
+ * @param prunerForObject The Pruner function to execute if the input `data` is an object.
230
+ * This pruner is responsible for handling the entire object data.
231
+ * @param prunerForNonObject The Pruner function to execute if the input `data` is *not* an object.
232
+ * @returns A new Pruner function that implements this conditional logic.
147
233
  */
148
- function liftArrayPruner(perElementPruner, wholeArrayPruner) {
234
+ function selectPrunerByObjectType(prunerForObject, prunerForNonObject) {
149
235
  return (data) => {
150
- if (!(0, checks_1.isArray)(data)) {
151
- return wholeArrayPruner(data);
236
+ if ((0, checks_1.isObjectUnsafe)(data)) {
237
+ // Data is an object, apply the pruner designated for objects.
238
+ return prunerForObject(data);
239
+ }
240
+ else {
241
+ // Data is not an object, apply the pruner designated for non-objects.
242
+ return prunerForNonObject(data);
152
243
  }
153
- return perElementPruner(data);
154
244
  };
155
245
  }
156
- exports.liftArrayPruner = liftArrayPruner;
246
+ exports.selectPrunerByObjectType = selectPrunerByObjectType;
157
247
  /**
158
248
  * Helper function to easily create a `ValidatorWithOptionalPruner`.
159
249
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "lucid-extension-sdk",
3
- "version": "0.0.409",
3
+ "version": "0.0.410",
4
4
  "description": "Utility classes for writing Lucid Software editor extensions",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",