immosquare-cleaner 0.1.38 → 0.1.39
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/immosquare-cleaner/version.rb +1 -1
- data/node_modules/@eslint/config-array/LICENSE +201 -0
- data/node_modules/@eslint/config-array/README.md +340 -0
- data/node_modules/@eslint/config-array/dist/cjs/index.cjs +1260 -0
- data/node_modules/@eslint/config-array/dist/cjs/index.d.cts +146 -0
- data/node_modules/@eslint/config-array/dist/cjs/types.ts +24 -0
- data/node_modules/@eslint/config-array/dist/esm/index.d.ts +146 -0
- data/node_modules/@eslint/config-array/dist/esm/index.js +1258 -0
- data/node_modules/@eslint/config-array/dist/esm/types.d.ts +19 -0
- data/node_modules/@eslint/config-array/dist/esm/types.ts +24 -0
- data/node_modules/@eslint/config-array/node_modules/minimatch/LICENSE +15 -0
- data/node_modules/@eslint/config-array/node_modules/minimatch/README.md +230 -0
- data/node_modules/@eslint/config-array/node_modules/minimatch/minimatch.js +947 -0
- data/node_modules/@eslint/config-array/node_modules/minimatch/node_modules/brace-expansion/LICENSE +21 -0
- data/node_modules/@eslint/config-array/node_modules/minimatch/node_modules/brace-expansion/README.md +129 -0
- data/node_modules/@eslint/config-array/node_modules/minimatch/node_modules/brace-expansion/index.js +201 -0
- data/node_modules/@eslint/config-array/node_modules/minimatch/node_modules/brace-expansion/package.json +47 -0
- data/node_modules/@eslint/config-array/node_modules/minimatch/package.json +33 -0
- data/node_modules/@eslint/config-array/package.json +60 -0
- data/node_modules/@eslint/js/package.json +1 -1
- data/node_modules/@eslint/object-schema/LICENSE +201 -0
- data/node_modules/@eslint/object-schema/README.md +224 -0
- data/node_modules/@eslint/object-schema/dist/cjs/index.cjs +455 -0
- data/node_modules/@eslint/object-schema/dist/cjs/index.d.cts +123 -0
- data/node_modules/@eslint/object-schema/dist/cjs/types.ts +55 -0
- data/node_modules/@eslint/object-schema/dist/esm/index.d.ts +123 -0
- data/node_modules/@eslint/object-schema/dist/esm/index.js +452 -0
- data/node_modules/@eslint/object-schema/dist/esm/types.d.ts +40 -0
- data/node_modules/@eslint/object-schema/dist/esm/types.ts +55 -0
- data/node_modules/@eslint/object-schema/package.json +56 -0
- data/node_modules/eslint/lib/cli.js +2 -2
- data/node_modules/eslint/lib/config/flat-config-array.js +1 -1
- data/node_modules/eslint/lib/eslint/eslint-helpers.js +7 -7
- data/node_modules/eslint/lib/eslint/eslint.js +1 -10
- data/node_modules/eslint/lib/rule-tester/rule-tester.js +1 -1
- data/node_modules/eslint/lib/rules/func-style.js +4 -4
- data/node_modules/eslint/lib/rules/no-constructor-return.js +1 -1
- data/node_modules/eslint/lib/rules/no-loop-func.js +161 -129
- data/node_modules/eslint/package.json +3 -3
- data/node_modules/prettier/LICENSE +56 -535
- data/node_modules/prettier/bin/prettier.cjs +4 -8
- data/node_modules/prettier/doc.js +20 -29
- data/node_modules/prettier/doc.mjs +20 -29
- data/node_modules/prettier/index.cjs +1 -1
- data/node_modules/prettier/index.d.ts +4 -2
- data/node_modules/prettier/index.mjs +3109 -4509
- data/node_modules/prettier/internal/cli.mjs +339 -3544
- data/node_modules/prettier/package.json +1 -1
- data/node_modules/prettier/plugins/acorn.js +11 -11
- data/node_modules/prettier/plugins/acorn.mjs +11 -11
- data/node_modules/prettier/plugins/angular.js +1 -1
- data/node_modules/prettier/plugins/angular.mjs +1 -1
- data/node_modules/prettier/plugins/babel.js +11 -11
- data/node_modules/prettier/plugins/babel.mjs +11 -11
- data/node_modules/prettier/plugins/estree.js +28 -28
- data/node_modules/prettier/plugins/estree.mjs +28 -28
- data/node_modules/prettier/plugins/flow.js +16 -17
- data/node_modules/prettier/plugins/flow.mjs +16 -17
- data/node_modules/prettier/plugins/glimmer.js +22 -22
- data/node_modules/prettier/plugins/glimmer.mjs +22 -22
- data/node_modules/prettier/plugins/graphql.js +4 -4
- data/node_modules/prettier/plugins/graphql.mjs +4 -4
- data/node_modules/prettier/plugins/html.js +15 -15
- data/node_modules/prettier/plugins/html.mjs +15 -15
- data/node_modules/prettier/plugins/markdown.js +42 -42
- data/node_modules/prettier/plugins/markdown.mjs +42 -42
- data/node_modules/prettier/plugins/meriyah.js +5 -5
- data/node_modules/prettier/plugins/meriyah.mjs +5 -5
- data/node_modules/prettier/plugins/postcss.js +26 -26
- data/node_modules/prettier/plugins/postcss.mjs +26 -26
- data/node_modules/prettier/plugins/typescript.js +20 -20
- data/node_modules/prettier/plugins/typescript.mjs +20 -20
- data/node_modules/prettier/plugins/yaml.js +32 -32
- data/node_modules/prettier/plugins/yaml.mjs +32 -32
- data/node_modules/prettier/standalone.js +26 -26
- data/node_modules/prettier/standalone.mjs +26 -26
- data/package.json +3 -3
- metadata +30 -2
@@ -0,0 +1,123 @@
|
|
1
|
+
export type ObjectDefinition = import("./types.ts").ObjectDefinition;
|
2
|
+
export type PropertyDefinition = import("./types.ts").PropertyDefinition;
|
3
|
+
/**
|
4
|
+
* @filedescription Merge Strategy
|
5
|
+
*/
|
6
|
+
/**
|
7
|
+
* Container class for several different merge strategies.
|
8
|
+
*/
|
9
|
+
export class MergeStrategy {
|
10
|
+
/**
|
11
|
+
* Merges two keys by overwriting the first with the second.
|
12
|
+
* @param {*} value1 The value from the first object key.
|
13
|
+
* @param {*} value2 The value from the second object key.
|
14
|
+
* @returns {*} The second value.
|
15
|
+
*/
|
16
|
+
static overwrite(value1: any, value2: any): any;
|
17
|
+
/**
|
18
|
+
* Merges two keys by replacing the first with the second only if the
|
19
|
+
* second is defined.
|
20
|
+
* @param {*} value1 The value from the first object key.
|
21
|
+
* @param {*} value2 The value from the second object key.
|
22
|
+
* @returns {*} The second value if it is defined.
|
23
|
+
*/
|
24
|
+
static replace(value1: any, value2: any): any;
|
25
|
+
/**
|
26
|
+
* Merges two properties by assigning properties from the second to the first.
|
27
|
+
* @param {*} value1 The value from the first object key.
|
28
|
+
* @param {*} value2 The value from the second object key.
|
29
|
+
* @returns {*} A new object containing properties from both value1 and
|
30
|
+
* value2.
|
31
|
+
*/
|
32
|
+
static assign(value1: any, value2: any): any;
|
33
|
+
}
|
34
|
+
/**
|
35
|
+
* Represents an object validation/merging schema.
|
36
|
+
*/
|
37
|
+
export class ObjectSchema {
|
38
|
+
/**
|
39
|
+
* Creates a new instance.
|
40
|
+
* @param {ObjectDefinition} definitions The schema definitions.
|
41
|
+
*/
|
42
|
+
constructor(definitions: ObjectDefinition);
|
43
|
+
/**
|
44
|
+
* Determines if a strategy has been registered for the given object key.
|
45
|
+
* @param {string} key The object key to find a strategy for.
|
46
|
+
* @returns {boolean} True if the key has a strategy registered, false if not.
|
47
|
+
*/
|
48
|
+
hasKey(key: string): boolean;
|
49
|
+
/**
|
50
|
+
* Merges objects together to create a new object comprised of the keys
|
51
|
+
* of the all objects. Keys are merged based on the each key's merge
|
52
|
+
* strategy.
|
53
|
+
* @param {...Object} objects The objects to merge.
|
54
|
+
* @returns {Object} A new object with a mix of all objects' keys.
|
55
|
+
* @throws {Error} If any object is invalid.
|
56
|
+
*/
|
57
|
+
merge(...objects: any[]): any;
|
58
|
+
/**
|
59
|
+
* Validates an object's keys based on the validate strategy for each key.
|
60
|
+
* @param {Object} object The object to validate.
|
61
|
+
* @returns {void}
|
62
|
+
* @throws {Error} When the object is invalid.
|
63
|
+
*/
|
64
|
+
validate(object: any): void;
|
65
|
+
#private;
|
66
|
+
}
|
67
|
+
/**
|
68
|
+
* @filedescription Validation Strategy
|
69
|
+
*/
|
70
|
+
/**
|
71
|
+
* Container class for several different validation strategies.
|
72
|
+
*/
|
73
|
+
export class ValidationStrategy {
|
74
|
+
/**
|
75
|
+
* Validates that a value is an array.
|
76
|
+
* @param {*} value The value to validate.
|
77
|
+
* @returns {void}
|
78
|
+
* @throws {TypeError} If the value is invalid.
|
79
|
+
*/
|
80
|
+
static array(value: any): void;
|
81
|
+
/**
|
82
|
+
* Validates that a value is a boolean.
|
83
|
+
* @param {*} value The value to validate.
|
84
|
+
* @returns {void}
|
85
|
+
* @throws {TypeError} If the value is invalid.
|
86
|
+
*/
|
87
|
+
static boolean(value: any): void;
|
88
|
+
/**
|
89
|
+
* Validates that a value is a number.
|
90
|
+
* @param {*} value The value to validate.
|
91
|
+
* @returns {void}
|
92
|
+
* @throws {TypeError} If the value is invalid.
|
93
|
+
*/
|
94
|
+
static number(value: any): void;
|
95
|
+
/**
|
96
|
+
* Validates that a value is a object.
|
97
|
+
* @param {*} value The value to validate.
|
98
|
+
* @returns {void}
|
99
|
+
* @throws {TypeError} If the value is invalid.
|
100
|
+
*/
|
101
|
+
static object(value: any): void;
|
102
|
+
/**
|
103
|
+
* Validates that a value is a object or null.
|
104
|
+
* @param {*} value The value to validate.
|
105
|
+
* @returns {void}
|
106
|
+
* @throws {TypeError} If the value is invalid.
|
107
|
+
*/
|
108
|
+
static "object?"(value: any): void;
|
109
|
+
/**
|
110
|
+
* Validates that a value is a string.
|
111
|
+
* @param {*} value The value to validate.
|
112
|
+
* @returns {void}
|
113
|
+
* @throws {TypeError} If the value is invalid.
|
114
|
+
*/
|
115
|
+
static string(value: any): void;
|
116
|
+
/**
|
117
|
+
* Validates that a value is a non-empty string.
|
118
|
+
* @param {*} value The value to validate.
|
119
|
+
* @returns {void}
|
120
|
+
* @throws {TypeError} If the value is invalid.
|
121
|
+
*/
|
122
|
+
static "string!"(value: any): void;
|
123
|
+
}
|
@@ -0,0 +1,452 @@
|
|
1
|
+
// @ts-self-types="./index.d.ts"
|
2
|
+
/**
|
3
|
+
* @filedescription Merge Strategy
|
4
|
+
*/
|
5
|
+
|
6
|
+
|
7
|
+
//-----------------------------------------------------------------------------
|
8
|
+
// Class
|
9
|
+
//-----------------------------------------------------------------------------
|
10
|
+
|
11
|
+
/**
|
12
|
+
* Container class for several different merge strategies.
|
13
|
+
*/
|
14
|
+
class MergeStrategy {
|
15
|
+
/**
|
16
|
+
* Merges two keys by overwriting the first with the second.
|
17
|
+
* @param {*} value1 The value from the first object key.
|
18
|
+
* @param {*} value2 The value from the second object key.
|
19
|
+
* @returns {*} The second value.
|
20
|
+
*/
|
21
|
+
static overwrite(value1, value2) {
|
22
|
+
return value2;
|
23
|
+
}
|
24
|
+
|
25
|
+
/**
|
26
|
+
* Merges two keys by replacing the first with the second only if the
|
27
|
+
* second is defined.
|
28
|
+
* @param {*} value1 The value from the first object key.
|
29
|
+
* @param {*} value2 The value from the second object key.
|
30
|
+
* @returns {*} The second value if it is defined.
|
31
|
+
*/
|
32
|
+
static replace(value1, value2) {
|
33
|
+
if (typeof value2 !== "undefined") {
|
34
|
+
return value2;
|
35
|
+
}
|
36
|
+
|
37
|
+
return value1;
|
38
|
+
}
|
39
|
+
|
40
|
+
/**
|
41
|
+
* Merges two properties by assigning properties from the second to the first.
|
42
|
+
* @param {*} value1 The value from the first object key.
|
43
|
+
* @param {*} value2 The value from the second object key.
|
44
|
+
* @returns {*} A new object containing properties from both value1 and
|
45
|
+
* value2.
|
46
|
+
*/
|
47
|
+
static assign(value1, value2) {
|
48
|
+
return Object.assign({}, value1, value2);
|
49
|
+
}
|
50
|
+
}
|
51
|
+
|
52
|
+
/**
|
53
|
+
* @filedescription Validation Strategy
|
54
|
+
*/
|
55
|
+
|
56
|
+
|
57
|
+
//-----------------------------------------------------------------------------
|
58
|
+
// Class
|
59
|
+
//-----------------------------------------------------------------------------
|
60
|
+
|
61
|
+
/**
|
62
|
+
* Container class for several different validation strategies.
|
63
|
+
*/
|
64
|
+
class ValidationStrategy {
|
65
|
+
/**
|
66
|
+
* Validates that a value is an array.
|
67
|
+
* @param {*} value The value to validate.
|
68
|
+
* @returns {void}
|
69
|
+
* @throws {TypeError} If the value is invalid.
|
70
|
+
*/
|
71
|
+
static array(value) {
|
72
|
+
if (!Array.isArray(value)) {
|
73
|
+
throw new TypeError("Expected an array.");
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
/**
|
78
|
+
* Validates that a value is a boolean.
|
79
|
+
* @param {*} value The value to validate.
|
80
|
+
* @returns {void}
|
81
|
+
* @throws {TypeError} If the value is invalid.
|
82
|
+
*/
|
83
|
+
static boolean(value) {
|
84
|
+
if (typeof value !== "boolean") {
|
85
|
+
throw new TypeError("Expected a Boolean.");
|
86
|
+
}
|
87
|
+
}
|
88
|
+
|
89
|
+
/**
|
90
|
+
* Validates that a value is a number.
|
91
|
+
* @param {*} value The value to validate.
|
92
|
+
* @returns {void}
|
93
|
+
* @throws {TypeError} If the value is invalid.
|
94
|
+
*/
|
95
|
+
static number(value) {
|
96
|
+
if (typeof value !== "number") {
|
97
|
+
throw new TypeError("Expected a number.");
|
98
|
+
}
|
99
|
+
}
|
100
|
+
|
101
|
+
/**
|
102
|
+
* Validates that a value is a object.
|
103
|
+
* @param {*} value The value to validate.
|
104
|
+
* @returns {void}
|
105
|
+
* @throws {TypeError} If the value is invalid.
|
106
|
+
*/
|
107
|
+
static object(value) {
|
108
|
+
if (!value || typeof value !== "object") {
|
109
|
+
throw new TypeError("Expected an object.");
|
110
|
+
}
|
111
|
+
}
|
112
|
+
|
113
|
+
/**
|
114
|
+
* Validates that a value is a object or null.
|
115
|
+
* @param {*} value The value to validate.
|
116
|
+
* @returns {void}
|
117
|
+
* @throws {TypeError} If the value is invalid.
|
118
|
+
*/
|
119
|
+
static "object?"(value) {
|
120
|
+
if (typeof value !== "object") {
|
121
|
+
throw new TypeError("Expected an object or null.");
|
122
|
+
}
|
123
|
+
}
|
124
|
+
|
125
|
+
/**
|
126
|
+
* Validates that a value is a string.
|
127
|
+
* @param {*} value The value to validate.
|
128
|
+
* @returns {void}
|
129
|
+
* @throws {TypeError} If the value is invalid.
|
130
|
+
*/
|
131
|
+
static string(value) {
|
132
|
+
if (typeof value !== "string") {
|
133
|
+
throw new TypeError("Expected a string.");
|
134
|
+
}
|
135
|
+
}
|
136
|
+
|
137
|
+
/**
|
138
|
+
* Validates that a value is a non-empty string.
|
139
|
+
* @param {*} value The value to validate.
|
140
|
+
* @returns {void}
|
141
|
+
* @throws {TypeError} If the value is invalid.
|
142
|
+
*/
|
143
|
+
static "string!"(value) {
|
144
|
+
if (typeof value !== "string" || value.length === 0) {
|
145
|
+
throw new TypeError("Expected a non-empty string.");
|
146
|
+
}
|
147
|
+
}
|
148
|
+
}
|
149
|
+
|
150
|
+
/**
|
151
|
+
* @filedescription Object Schema
|
152
|
+
*/
|
153
|
+
|
154
|
+
|
155
|
+
//-----------------------------------------------------------------------------
|
156
|
+
// Types
|
157
|
+
//-----------------------------------------------------------------------------
|
158
|
+
|
159
|
+
/** @typedef {import("./types.ts").ObjectDefinition} ObjectDefinition */
|
160
|
+
/** @typedef {import("./types.ts").PropertyDefinition} PropertyDefinition */
|
161
|
+
|
162
|
+
//-----------------------------------------------------------------------------
|
163
|
+
// Private
|
164
|
+
//-----------------------------------------------------------------------------
|
165
|
+
|
166
|
+
/**
|
167
|
+
* Validates a schema strategy.
|
168
|
+
* @param {string} name The name of the key this strategy is for.
|
169
|
+
* @param {PropertyDefinition} definition The strategy for the object key.
|
170
|
+
* @returns {void}
|
171
|
+
* @throws {Error} When the strategy is missing a name.
|
172
|
+
* @throws {Error} When the strategy is missing a merge() method.
|
173
|
+
* @throws {Error} When the strategy is missing a validate() method.
|
174
|
+
*/
|
175
|
+
function validateDefinition(name, definition) {
|
176
|
+
let hasSchema = false;
|
177
|
+
if (definition.schema) {
|
178
|
+
if (typeof definition.schema === "object") {
|
179
|
+
hasSchema = true;
|
180
|
+
} else {
|
181
|
+
throw new TypeError("Schema must be an object.");
|
182
|
+
}
|
183
|
+
}
|
184
|
+
|
185
|
+
if (typeof definition.merge === "string") {
|
186
|
+
if (!(definition.merge in MergeStrategy)) {
|
187
|
+
throw new TypeError(
|
188
|
+
`Definition for key "${name}" missing valid merge strategy.`,
|
189
|
+
);
|
190
|
+
}
|
191
|
+
} else if (!hasSchema && typeof definition.merge !== "function") {
|
192
|
+
throw new TypeError(
|
193
|
+
`Definition for key "${name}" must have a merge property.`,
|
194
|
+
);
|
195
|
+
}
|
196
|
+
|
197
|
+
if (typeof definition.validate === "string") {
|
198
|
+
if (!(definition.validate in ValidationStrategy)) {
|
199
|
+
throw new TypeError(
|
200
|
+
`Definition for key "${name}" missing valid validation strategy.`,
|
201
|
+
);
|
202
|
+
}
|
203
|
+
} else if (!hasSchema && typeof definition.validate !== "function") {
|
204
|
+
throw new TypeError(
|
205
|
+
`Definition for key "${name}" must have a validate() method.`,
|
206
|
+
);
|
207
|
+
}
|
208
|
+
}
|
209
|
+
|
210
|
+
//-----------------------------------------------------------------------------
|
211
|
+
// Errors
|
212
|
+
//-----------------------------------------------------------------------------
|
213
|
+
|
214
|
+
/**
|
215
|
+
* Error when an unexpected key is found.
|
216
|
+
*/
|
217
|
+
class UnexpectedKeyError extends Error {
|
218
|
+
/**
|
219
|
+
* Creates a new instance.
|
220
|
+
* @param {string} key The key that was unexpected.
|
221
|
+
*/
|
222
|
+
constructor(key) {
|
223
|
+
super(`Unexpected key "${key}" found.`);
|
224
|
+
}
|
225
|
+
}
|
226
|
+
|
227
|
+
/**
|
228
|
+
* Error when a required key is missing.
|
229
|
+
*/
|
230
|
+
class MissingKeyError extends Error {
|
231
|
+
/**
|
232
|
+
* Creates a new instance.
|
233
|
+
* @param {string} key The key that was missing.
|
234
|
+
*/
|
235
|
+
constructor(key) {
|
236
|
+
super(`Missing required key "${key}".`);
|
237
|
+
}
|
238
|
+
}
|
239
|
+
|
240
|
+
/**
|
241
|
+
* Error when a key requires other keys that are missing.
|
242
|
+
*/
|
243
|
+
class MissingDependentKeysError extends Error {
|
244
|
+
/**
|
245
|
+
* Creates a new instance.
|
246
|
+
* @param {string} key The key that was unexpected.
|
247
|
+
* @param {Array<string>} requiredKeys The keys that are required.
|
248
|
+
*/
|
249
|
+
constructor(key, requiredKeys) {
|
250
|
+
super(`Key "${key}" requires keys "${requiredKeys.join('", "')}".`);
|
251
|
+
}
|
252
|
+
}
|
253
|
+
|
254
|
+
/**
|
255
|
+
* Wrapper error for errors occuring during a merge or validate operation.
|
256
|
+
*/
|
257
|
+
class WrapperError extends Error {
|
258
|
+
/**
|
259
|
+
* Creates a new instance.
|
260
|
+
* @param {string} key The object key causing the error.
|
261
|
+
* @param {Error} source The source error.
|
262
|
+
*/
|
263
|
+
constructor(key, source) {
|
264
|
+
super(`Key "${key}": ${source.message}`, { cause: source });
|
265
|
+
|
266
|
+
// copy over custom properties that aren't represented
|
267
|
+
for (const key of Object.keys(source)) {
|
268
|
+
if (!(key in this)) {
|
269
|
+
this[key] = source[key];
|
270
|
+
}
|
271
|
+
}
|
272
|
+
}
|
273
|
+
}
|
274
|
+
|
275
|
+
//-----------------------------------------------------------------------------
|
276
|
+
// Main
|
277
|
+
//-----------------------------------------------------------------------------
|
278
|
+
|
279
|
+
/**
|
280
|
+
* Represents an object validation/merging schema.
|
281
|
+
*/
|
282
|
+
class ObjectSchema {
|
283
|
+
/**
|
284
|
+
* Track all definitions in the schema by key.
|
285
|
+
* @type {Map<string, PropertyDefinition>}
|
286
|
+
*/
|
287
|
+
#definitions = new Map();
|
288
|
+
|
289
|
+
/**
|
290
|
+
* Separately track any keys that are required for faster validtion.
|
291
|
+
* @type {Map<string, PropertyDefinition>}
|
292
|
+
*/
|
293
|
+
#requiredKeys = new Map();
|
294
|
+
|
295
|
+
/**
|
296
|
+
* Creates a new instance.
|
297
|
+
* @param {ObjectDefinition} definitions The schema definitions.
|
298
|
+
*/
|
299
|
+
constructor(definitions) {
|
300
|
+
if (!definitions) {
|
301
|
+
throw new Error("Schema definitions missing.");
|
302
|
+
}
|
303
|
+
|
304
|
+
// add in all strategies
|
305
|
+
for (const key of Object.keys(definitions)) {
|
306
|
+
validateDefinition(key, definitions[key]);
|
307
|
+
|
308
|
+
// normalize merge and validate methods if subschema is present
|
309
|
+
if (typeof definitions[key].schema === "object") {
|
310
|
+
const schema = new ObjectSchema(definitions[key].schema);
|
311
|
+
definitions[key] = {
|
312
|
+
...definitions[key],
|
313
|
+
merge(first = {}, second = {}) {
|
314
|
+
return schema.merge(first, second);
|
315
|
+
},
|
316
|
+
validate(value) {
|
317
|
+
ValidationStrategy.object(value);
|
318
|
+
schema.validate(value);
|
319
|
+
},
|
320
|
+
};
|
321
|
+
}
|
322
|
+
|
323
|
+
// normalize the merge method in case there's a string
|
324
|
+
if (typeof definitions[key].merge === "string") {
|
325
|
+
definitions[key] = {
|
326
|
+
...definitions[key],
|
327
|
+
merge: MergeStrategy[
|
328
|
+
/** @type {string} */ (definitions[key].merge)
|
329
|
+
],
|
330
|
+
};
|
331
|
+
}
|
332
|
+
|
333
|
+
// normalize the validate method in case there's a string
|
334
|
+
if (typeof definitions[key].validate === "string") {
|
335
|
+
definitions[key] = {
|
336
|
+
...definitions[key],
|
337
|
+
validate:
|
338
|
+
ValidationStrategy[
|
339
|
+
/** @type {string} */ (definitions[key].validate)
|
340
|
+
],
|
341
|
+
};
|
342
|
+
}
|
343
|
+
|
344
|
+
this.#definitions.set(key, definitions[key]);
|
345
|
+
|
346
|
+
if (definitions[key].required) {
|
347
|
+
this.#requiredKeys.set(key, definitions[key]);
|
348
|
+
}
|
349
|
+
}
|
350
|
+
}
|
351
|
+
|
352
|
+
/**
|
353
|
+
* Determines if a strategy has been registered for the given object key.
|
354
|
+
* @param {string} key The object key to find a strategy for.
|
355
|
+
* @returns {boolean} True if the key has a strategy registered, false if not.
|
356
|
+
*/
|
357
|
+
hasKey(key) {
|
358
|
+
return this.#definitions.has(key);
|
359
|
+
}
|
360
|
+
|
361
|
+
/**
|
362
|
+
* Merges objects together to create a new object comprised of the keys
|
363
|
+
* of the all objects. Keys are merged based on the each key's merge
|
364
|
+
* strategy.
|
365
|
+
* @param {...Object} objects The objects to merge.
|
366
|
+
* @returns {Object} A new object with a mix of all objects' keys.
|
367
|
+
* @throws {Error} If any object is invalid.
|
368
|
+
*/
|
369
|
+
merge(...objects) {
|
370
|
+
// double check arguments
|
371
|
+
if (objects.length < 2) {
|
372
|
+
throw new TypeError("merge() requires at least two arguments.");
|
373
|
+
}
|
374
|
+
|
375
|
+
if (
|
376
|
+
objects.some(object => object == null || typeof object !== "object")
|
377
|
+
) {
|
378
|
+
throw new TypeError("All arguments must be objects.");
|
379
|
+
}
|
380
|
+
|
381
|
+
return objects.reduce((result, object) => {
|
382
|
+
this.validate(object);
|
383
|
+
|
384
|
+
for (const [key, strategy] of this.#definitions) {
|
385
|
+
try {
|
386
|
+
if (key in result || key in object) {
|
387
|
+
const merge = /** @type {Function} */ (strategy.merge);
|
388
|
+
const value = merge.call(
|
389
|
+
this,
|
390
|
+
result[key],
|
391
|
+
object[key],
|
392
|
+
);
|
393
|
+
if (value !== undefined) {
|
394
|
+
result[key] = value;
|
395
|
+
}
|
396
|
+
}
|
397
|
+
} catch (ex) {
|
398
|
+
throw new WrapperError(key, ex);
|
399
|
+
}
|
400
|
+
}
|
401
|
+
return result;
|
402
|
+
}, {});
|
403
|
+
}
|
404
|
+
|
405
|
+
/**
|
406
|
+
* Validates an object's keys based on the validate strategy for each key.
|
407
|
+
* @param {Object} object The object to validate.
|
408
|
+
* @returns {void}
|
409
|
+
* @throws {Error} When the object is invalid.
|
410
|
+
*/
|
411
|
+
validate(object) {
|
412
|
+
// check existing keys first
|
413
|
+
for (const key of Object.keys(object)) {
|
414
|
+
// check to see if the key is defined
|
415
|
+
if (!this.hasKey(key)) {
|
416
|
+
throw new UnexpectedKeyError(key);
|
417
|
+
}
|
418
|
+
|
419
|
+
// validate existing keys
|
420
|
+
const definition = this.#definitions.get(key);
|
421
|
+
|
422
|
+
// first check to see if any other keys are required
|
423
|
+
if (Array.isArray(definition.requires)) {
|
424
|
+
if (
|
425
|
+
!definition.requires.every(otherKey => otherKey in object)
|
426
|
+
) {
|
427
|
+
throw new MissingDependentKeysError(
|
428
|
+
key,
|
429
|
+
definition.requires,
|
430
|
+
);
|
431
|
+
}
|
432
|
+
}
|
433
|
+
|
434
|
+
// now apply remaining validation strategy
|
435
|
+
try {
|
436
|
+
const validate = /** @type {Function} */ (definition.validate);
|
437
|
+
validate.call(definition, object[key]);
|
438
|
+
} catch (ex) {
|
439
|
+
throw new WrapperError(key, ex);
|
440
|
+
}
|
441
|
+
}
|
442
|
+
|
443
|
+
// ensure required keys aren't missing
|
444
|
+
for (const [key] of this.#requiredKeys) {
|
445
|
+
if (!(key in object)) {
|
446
|
+
throw new MissingKeyError(key);
|
447
|
+
}
|
448
|
+
}
|
449
|
+
}
|
450
|
+
}
|
451
|
+
|
452
|
+
export { MergeStrategy, ObjectSchema, ValidationStrategy };
|
@@ -0,0 +1,40 @@
|
|
1
|
+
/**
|
2
|
+
* @filedescription Types for object-schema package.
|
3
|
+
*/
|
4
|
+
/**
|
5
|
+
* Built-in validation strategies.
|
6
|
+
*/
|
7
|
+
export type BuiltInValidationStrategy = "array" | "boolean" | "number" | "object" | "object?" | "string" | "string!";
|
8
|
+
/**
|
9
|
+
* Built-in merge strategies.
|
10
|
+
*/
|
11
|
+
export type BuiltInMergeStrategy = "assign" | "overwrite" | "replace";
|
12
|
+
/**
|
13
|
+
* Property definition.
|
14
|
+
*/
|
15
|
+
export interface PropertyDefinition {
|
16
|
+
/**
|
17
|
+
* Indicates if the property is required.
|
18
|
+
*/
|
19
|
+
required: boolean;
|
20
|
+
/**
|
21
|
+
* The other properties that must be present when this property is used.
|
22
|
+
*/
|
23
|
+
requires?: string[];
|
24
|
+
/**
|
25
|
+
* The strategy to merge the property.
|
26
|
+
*/
|
27
|
+
merge: BuiltInMergeStrategy | ((target: any, source: any) => any);
|
28
|
+
/**
|
29
|
+
* The strategy to validate the property.
|
30
|
+
*/
|
31
|
+
validate: BuiltInValidationStrategy | ((value: any) => void);
|
32
|
+
/**
|
33
|
+
* The schema for the object value of this property.
|
34
|
+
*/
|
35
|
+
schema?: ObjectDefinition;
|
36
|
+
}
|
37
|
+
/**
|
38
|
+
* Object definition.
|
39
|
+
*/
|
40
|
+
export type ObjectDefinition = Record<string, PropertyDefinition>;
|
@@ -0,0 +1,55 @@
|
|
1
|
+
/**
|
2
|
+
* @filedescription Types for object-schema package.
|
3
|
+
*/
|
4
|
+
|
5
|
+
/**
|
6
|
+
* Built-in validation strategies.
|
7
|
+
*/
|
8
|
+
export type BuiltInValidationStrategy =
|
9
|
+
| "array"
|
10
|
+
| "boolean"
|
11
|
+
| "number"
|
12
|
+
| "object"
|
13
|
+
| "object?"
|
14
|
+
| "string"
|
15
|
+
| "string!";
|
16
|
+
|
17
|
+
/**
|
18
|
+
* Built-in merge strategies.
|
19
|
+
*/
|
20
|
+
export type BuiltInMergeStrategy = "assign" | "overwrite" | "replace";
|
21
|
+
|
22
|
+
/**
|
23
|
+
* Property definition.
|
24
|
+
*/
|
25
|
+
export interface PropertyDefinition {
|
26
|
+
/**
|
27
|
+
* Indicates if the property is required.
|
28
|
+
*/
|
29
|
+
required: boolean;
|
30
|
+
|
31
|
+
/**
|
32
|
+
* The other properties that must be present when this property is used.
|
33
|
+
*/
|
34
|
+
requires?: string[];
|
35
|
+
|
36
|
+
/**
|
37
|
+
* The strategy to merge the property.
|
38
|
+
*/
|
39
|
+
merge: BuiltInMergeStrategy | ((target: any, source: any) => any);
|
40
|
+
|
41
|
+
/**
|
42
|
+
* The strategy to validate the property.
|
43
|
+
*/
|
44
|
+
validate: BuiltInValidationStrategy | ((value: any) => void);
|
45
|
+
|
46
|
+
/**
|
47
|
+
* The schema for the object value of this property.
|
48
|
+
*/
|
49
|
+
schema?: ObjectDefinition;
|
50
|
+
}
|
51
|
+
|
52
|
+
/**
|
53
|
+
* Object definition.
|
54
|
+
*/
|
55
|
+
export type ObjectDefinition = Record<string, PropertyDefinition>;
|