@oscarpalmer/atoms 0.85.0 → 0.86.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +2 -0
- package/dist/index.js +2 -0
- package/dist/schema.cjs +65 -12
- package/dist/schema.js +65 -12
- package/package.json +2 -2
- package/src/index.ts +1 -0
- package/src/schema.ts +88 -19
- package/types/index.d.cts +36 -0
- package/types/index.d.ts +1 -0
- package/types/schema.d.cts +1 -1
- package/types/schema.d.ts +1 -1
package/dist/index.cjs
CHANGED
|
@@ -12,6 +12,7 @@ const number = require("./number.cjs");
|
|
|
12
12
|
const query = require("./query.cjs");
|
|
13
13
|
const queue = require("./queue.cjs");
|
|
14
14
|
const random = require("./random.cjs");
|
|
15
|
+
const schema = require("./schema.cjs");
|
|
15
16
|
const sized = require("./sized.cjs");
|
|
16
17
|
const string_index = require("./string/index.cjs");
|
|
17
18
|
require("./touch.cjs");
|
|
@@ -87,6 +88,7 @@ exports.getRandomHex = random.getRandomHex;
|
|
|
87
88
|
exports.getRandomInteger = random.getRandomInteger;
|
|
88
89
|
exports.getRandomItem = random.getRandomItem;
|
|
89
90
|
exports.getRandomItems = random.getRandomItems;
|
|
91
|
+
exports.schematic = schema.schematic;
|
|
90
92
|
exports.SizedMap = sized.SizedMap;
|
|
91
93
|
exports.SizedSet = sized.SizedSet;
|
|
92
94
|
exports.createUuid = string_index.createUuid;
|
package/dist/index.js
CHANGED
|
@@ -10,6 +10,7 @@ import { between, clamp, getNumber } from "./number.js";
|
|
|
10
10
|
import { fromQuery, toQuery } from "./query.js";
|
|
11
11
|
import { queue } from "./queue.js";
|
|
12
12
|
import { getRandomBoolean, getRandomCharacters, getRandomColor, getRandomFloat, getRandomHex, getRandomInteger, getRandomItem, getRandomItems } from "./random.js";
|
|
13
|
+
import { schematic } from "./schema.js";
|
|
13
14
|
import { SizedMap, SizedSet } from "./sized.js";
|
|
14
15
|
import { createUuid, getString, join, parse, truncate, words } from "./string/index.js";
|
|
15
16
|
import "./touch.js";
|
|
@@ -122,6 +123,7 @@ export {
|
|
|
122
123
|
rgbToHex,
|
|
123
124
|
rgbToHsl,
|
|
124
125
|
round,
|
|
126
|
+
schematic,
|
|
125
127
|
setValue,
|
|
126
128
|
shuffle,
|
|
127
129
|
smush,
|
package/dist/schema.cjs
CHANGED
|
@@ -1,25 +1,78 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
const valueTypes = /* @__PURE__ */ new Set([
|
|
4
|
+
"array",
|
|
5
|
+
"bigint",
|
|
6
|
+
"boolean",
|
|
7
|
+
"date",
|
|
8
|
+
"function",
|
|
9
|
+
"number",
|
|
10
|
+
"object",
|
|
11
|
+
"string",
|
|
12
|
+
"symbol"
|
|
13
|
+
]);
|
|
14
|
+
function getValidatedSchema(schema) {
|
|
15
|
+
const validated = {
|
|
16
|
+
keys: [],
|
|
17
|
+
length: 0,
|
|
18
|
+
schema: {}
|
|
19
|
+
};
|
|
20
|
+
if (typeof schema !== "object" || schema === null) {
|
|
21
|
+
return validated;
|
|
22
|
+
}
|
|
23
|
+
const keys = Object.keys(schema);
|
|
24
|
+
const { length } = keys;
|
|
25
|
+
for (let index = 0; index < length; index += 1) {
|
|
26
|
+
const key = keys[index];
|
|
27
|
+
const value = schema[key];
|
|
28
|
+
const types = [];
|
|
29
|
+
if (valueTypes.has(value)) {
|
|
30
|
+
types.push(value);
|
|
31
|
+
} else if (Array.isArray(value)) {
|
|
32
|
+
const typesLength = value.length;
|
|
33
|
+
for (let typeIndex = 0; typeIndex < typesLength; typeIndex += 1) {
|
|
34
|
+
const type = value[typeIndex];
|
|
35
|
+
if (valueTypes.has(type)) {
|
|
36
|
+
types.push(type);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
if (types.length > 0) {
|
|
41
|
+
validated.keys.push(key);
|
|
42
|
+
validated.schema[key] = types;
|
|
43
|
+
validated.length += 1;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return validated;
|
|
5
47
|
}
|
|
6
48
|
function schematic(schema) {
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const canValidate = length > 0;
|
|
49
|
+
const validated = getValidatedSchema(schema);
|
|
50
|
+
const canValidate = validated.length > 0;
|
|
10
51
|
return Object.freeze({
|
|
11
|
-
is: (value) => canValidate && validate(
|
|
52
|
+
is: (value) => canValidate && validate(validated, value)
|
|
12
53
|
});
|
|
13
54
|
}
|
|
14
|
-
function validate(
|
|
15
|
-
if (
|
|
55
|
+
function validate(validated, value) {
|
|
56
|
+
if (typeof value !== "object" || value === null) {
|
|
16
57
|
return false;
|
|
17
58
|
}
|
|
18
|
-
for (let index = 0; index < length; index += 1) {
|
|
19
|
-
const key = keys[index];
|
|
20
|
-
|
|
21
|
-
|
|
59
|
+
outer: for (let index = 0; index < validated.length; index += 1) {
|
|
60
|
+
const key = validated.keys[index];
|
|
61
|
+
const types = validated.schema[key];
|
|
62
|
+
const val = value[key];
|
|
63
|
+
const typesLength = types.length;
|
|
64
|
+
if (typesLength === 1) {
|
|
65
|
+
if (!validators[types[0]](val)) {
|
|
66
|
+
return false;
|
|
67
|
+
}
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
for (let typeIndex = 0; typeIndex < typesLength; typeIndex += 1) {
|
|
71
|
+
if (validators[types[typeIndex]](val)) {
|
|
72
|
+
continue outer;
|
|
73
|
+
}
|
|
22
74
|
}
|
|
75
|
+
return false;
|
|
23
76
|
}
|
|
24
77
|
return true;
|
|
25
78
|
}
|
package/dist/schema.js
CHANGED
|
@@ -1,23 +1,76 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
const valueTypes = /* @__PURE__ */ new Set([
|
|
2
|
+
"array",
|
|
3
|
+
"bigint",
|
|
4
|
+
"boolean",
|
|
5
|
+
"date",
|
|
6
|
+
"function",
|
|
7
|
+
"number",
|
|
8
|
+
"object",
|
|
9
|
+
"string",
|
|
10
|
+
"symbol"
|
|
11
|
+
]);
|
|
12
|
+
function getValidatedSchema(schema) {
|
|
13
|
+
const validated = {
|
|
14
|
+
keys: [],
|
|
15
|
+
length: 0,
|
|
16
|
+
schema: {}
|
|
17
|
+
};
|
|
18
|
+
if (typeof schema !== "object" || schema === null) {
|
|
19
|
+
return validated;
|
|
20
|
+
}
|
|
21
|
+
const keys = Object.keys(schema);
|
|
22
|
+
const { length } = keys;
|
|
23
|
+
for (let index = 0; index < length; index += 1) {
|
|
24
|
+
const key = keys[index];
|
|
25
|
+
const value = schema[key];
|
|
26
|
+
const types = [];
|
|
27
|
+
if (valueTypes.has(value)) {
|
|
28
|
+
types.push(value);
|
|
29
|
+
} else if (Array.isArray(value)) {
|
|
30
|
+
const typesLength = value.length;
|
|
31
|
+
for (let typeIndex = 0; typeIndex < typesLength; typeIndex += 1) {
|
|
32
|
+
const type = value[typeIndex];
|
|
33
|
+
if (valueTypes.has(type)) {
|
|
34
|
+
types.push(type);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (types.length > 0) {
|
|
39
|
+
validated.keys.push(key);
|
|
40
|
+
validated.schema[key] = types;
|
|
41
|
+
validated.length += 1;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return validated;
|
|
3
45
|
}
|
|
4
46
|
function schematic(schema) {
|
|
5
|
-
const
|
|
6
|
-
const
|
|
7
|
-
const canValidate = length > 0;
|
|
47
|
+
const validated = getValidatedSchema(schema);
|
|
48
|
+
const canValidate = validated.length > 0;
|
|
8
49
|
return Object.freeze({
|
|
9
|
-
is: (value) => canValidate && validate(
|
|
50
|
+
is: (value) => canValidate && validate(validated, value)
|
|
10
51
|
});
|
|
11
52
|
}
|
|
12
|
-
function validate(
|
|
13
|
-
if (
|
|
53
|
+
function validate(validated, value) {
|
|
54
|
+
if (typeof value !== "object" || value === null) {
|
|
14
55
|
return false;
|
|
15
56
|
}
|
|
16
|
-
for (let index = 0; index < length; index += 1) {
|
|
17
|
-
const key = keys[index];
|
|
18
|
-
|
|
19
|
-
|
|
57
|
+
outer: for (let index = 0; index < validated.length; index += 1) {
|
|
58
|
+
const key = validated.keys[index];
|
|
59
|
+
const types = validated.schema[key];
|
|
60
|
+
const val = value[key];
|
|
61
|
+
const typesLength = types.length;
|
|
62
|
+
if (typesLength === 1) {
|
|
63
|
+
if (!validators[types[0]](val)) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
for (let typeIndex = 0; typeIndex < typesLength; typeIndex += 1) {
|
|
69
|
+
if (validators[types[typeIndex]](val)) {
|
|
70
|
+
continue outer;
|
|
71
|
+
}
|
|
20
72
|
}
|
|
73
|
+
return false;
|
|
21
74
|
}
|
|
22
75
|
return true;
|
|
23
76
|
}
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"url": "https://oscarpalmer.se"
|
|
5
5
|
},
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"type-fest": "^4.
|
|
7
|
+
"type-fest": "^4.34"
|
|
8
8
|
},
|
|
9
9
|
"description": "Atomic utilities for making your JavaScript better.",
|
|
10
10
|
"devDependencies": {
|
|
@@ -218,5 +218,5 @@
|
|
|
218
218
|
},
|
|
219
219
|
"type": "module",
|
|
220
220
|
"types": "./types/index.d.cts",
|
|
221
|
-
"version": "0.
|
|
221
|
+
"version": "0.86.0"
|
|
222
222
|
}
|
package/src/index.ts
CHANGED
package/src/schema.ts
CHANGED
|
@@ -17,7 +17,7 @@ type ReverseInferred<Model extends Typed> = {
|
|
|
17
17
|
: never;
|
|
18
18
|
};
|
|
19
19
|
|
|
20
|
-
export type Schema = Record<string, keyof Values>;
|
|
20
|
+
export type Schema = Record<string, keyof Values | (keyof Values)[]>;
|
|
21
21
|
|
|
22
22
|
export type Schematic<Model> = {
|
|
23
23
|
/**
|
|
@@ -28,6 +28,12 @@ export type Schematic<Model> = {
|
|
|
28
28
|
|
|
29
29
|
type Typed = Record<string, unknown>;
|
|
30
30
|
|
|
31
|
+
type ValidatedSchema = {
|
|
32
|
+
keys: string[];
|
|
33
|
+
length: number;
|
|
34
|
+
schema: Record<string, (keyof Values)[]>;
|
|
35
|
+
};
|
|
36
|
+
|
|
31
37
|
type Values = {
|
|
32
38
|
array: unknown[];
|
|
33
39
|
bigint: bigint;
|
|
@@ -41,8 +47,62 @@ type Values = {
|
|
|
41
47
|
symbol: symbol;
|
|
42
48
|
};
|
|
43
49
|
|
|
44
|
-
|
|
45
|
-
|
|
50
|
+
const valueTypes = new Set<keyof Values>([
|
|
51
|
+
'array',
|
|
52
|
+
'bigint',
|
|
53
|
+
'boolean',
|
|
54
|
+
'date',
|
|
55
|
+
'function',
|
|
56
|
+
'number',
|
|
57
|
+
'object',
|
|
58
|
+
'string',
|
|
59
|
+
'symbol',
|
|
60
|
+
]);
|
|
61
|
+
|
|
62
|
+
function getValidatedSchema(schema: unknown): ValidatedSchema {
|
|
63
|
+
const validated: ValidatedSchema = {
|
|
64
|
+
keys: [],
|
|
65
|
+
length: 0,
|
|
66
|
+
schema: {},
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
if (typeof schema !== 'object' || schema === null) {
|
|
70
|
+
return validated;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
const keys = Object.keys(schema);
|
|
74
|
+
const {length} = keys;
|
|
75
|
+
|
|
76
|
+
for (let index = 0; index < length; index += 1) {
|
|
77
|
+
const key = keys[index];
|
|
78
|
+
const value = (schema as Schema)[key];
|
|
79
|
+
|
|
80
|
+
const types: (keyof Values)[] = [];
|
|
81
|
+
|
|
82
|
+
if (valueTypes.has(value as never)) {
|
|
83
|
+
types.push(value as never);
|
|
84
|
+
} else if (Array.isArray(value)) {
|
|
85
|
+
const typesLength = value.length;
|
|
86
|
+
|
|
87
|
+
for (let typeIndex = 0; typeIndex < typesLength; typeIndex += 1) {
|
|
88
|
+
const type = value[typeIndex];
|
|
89
|
+
|
|
90
|
+
if (valueTypes.has(type)) {
|
|
91
|
+
types.push(type);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (types.length > 0) {
|
|
97
|
+
validated.keys.push(key);
|
|
98
|
+
|
|
99
|
+
validated.schema[key] = types;
|
|
100
|
+
|
|
101
|
+
validated.length += 1;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return validated;
|
|
46
106
|
}
|
|
47
107
|
|
|
48
108
|
/**
|
|
@@ -60,33 +120,42 @@ export function schematic<Model extends Schema>(
|
|
|
60
120
|
): Schematic<Simplify<Inferred<Model>>>;
|
|
61
121
|
|
|
62
122
|
export function schematic<Model extends Schema>(schema: Model) {
|
|
63
|
-
const
|
|
64
|
-
const {length} = keys;
|
|
123
|
+
const validated = getValidatedSchema(schema);
|
|
65
124
|
|
|
66
|
-
const canValidate = length > 0;
|
|
125
|
+
const canValidate = validated.length > 0;
|
|
67
126
|
|
|
68
127
|
return Object.freeze({
|
|
69
|
-
is: (value: unknown) =>
|
|
70
|
-
canValidate && validate(schema, keys, length, value),
|
|
128
|
+
is: (value: unknown) => canValidate && validate(validated, value),
|
|
71
129
|
});
|
|
72
130
|
}
|
|
73
131
|
|
|
74
|
-
function validate(
|
|
75
|
-
|
|
76
|
-
keys: string[],
|
|
77
|
-
length: number,
|
|
78
|
-
value: unknown,
|
|
79
|
-
): boolean {
|
|
80
|
-
if (getKeys(value).length !== length) {
|
|
132
|
+
function validate(validated: ValidatedSchema, value: unknown): boolean {
|
|
133
|
+
if (typeof value !== 'object' || value === null) {
|
|
81
134
|
return false;
|
|
82
135
|
}
|
|
83
136
|
|
|
84
|
-
for (let index = 0; index < length; index += 1) {
|
|
85
|
-
const key = keys[index];
|
|
137
|
+
outer: for (let index = 0; index < validated.length; index += 1) {
|
|
138
|
+
const key = validated.keys[index];
|
|
139
|
+
const types = validated.schema[key];
|
|
140
|
+
const val = (value as PlainObject)[key];
|
|
141
|
+
|
|
142
|
+
const typesLength = types.length;
|
|
86
143
|
|
|
87
|
-
if (
|
|
88
|
-
|
|
144
|
+
if (typesLength === 1) {
|
|
145
|
+
if (!validators[types[0]](val)) {
|
|
146
|
+
return false;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
continue;
|
|
89
150
|
}
|
|
151
|
+
|
|
152
|
+
for (let typeIndex = 0; typeIndex < typesLength; typeIndex += 1) {
|
|
153
|
+
if (validators[types[typeIndex]](val)) {
|
|
154
|
+
continue outer;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return false;
|
|
90
159
|
}
|
|
91
160
|
|
|
92
161
|
return true;
|
package/types/index.d.cts
CHANGED
|
@@ -1321,6 +1321,42 @@ export type Get<BaseType, Path extends readonly string[] | LiteralStringUnion<To
|
|
|
1321
1321
|
bracketNotation: true;
|
|
1322
1322
|
maxRecursionDepth: 2;
|
|
1323
1323
|
}>>>, Options extends GetOptions = {}> = GetWithPath<BaseType, Path extends string ? ToPath<Path> : Path, Options>;
|
|
1324
|
+
export type FindKey<Model, Value> = {
|
|
1325
|
+
[Key in keyof Model]: Model[Key] extends Value ? Key : never;
|
|
1326
|
+
}[keyof Model];
|
|
1327
|
+
export type Inferred<Model extends Schema> = {
|
|
1328
|
+
[Key in keyof Model]: Model[Key] extends keyof Values ? Values[Model[Key]] : never;
|
|
1329
|
+
};
|
|
1330
|
+
export type ReverseInferred<Model extends Typed> = {
|
|
1331
|
+
[Key in keyof Model]: Model[Key] extends Values[keyof Values] ? FindKey<Values, Model[Key]> : never;
|
|
1332
|
+
};
|
|
1333
|
+
export type Schema = Record<string, keyof Values | (keyof Values)[]>;
|
|
1334
|
+
export type Schematic<Model> = {
|
|
1335
|
+
/**
|
|
1336
|
+
* Does the value match the schema?
|
|
1337
|
+
*/
|
|
1338
|
+
is(value: unknown): value is Model;
|
|
1339
|
+
};
|
|
1340
|
+
export type Typed = Record<string, unknown>;
|
|
1341
|
+
export type Values = {
|
|
1342
|
+
array: unknown[];
|
|
1343
|
+
bigint: bigint;
|
|
1344
|
+
boolean: boolean;
|
|
1345
|
+
date: Date;
|
|
1346
|
+
function: Function;
|
|
1347
|
+
number: number;
|
|
1348
|
+
object: object;
|
|
1349
|
+
string: string;
|
|
1350
|
+
symbol: symbol;
|
|
1351
|
+
};
|
|
1352
|
+
/**
|
|
1353
|
+
* Create a schematic from a typed schema
|
|
1354
|
+
*/
|
|
1355
|
+
export declare function schematic<Model extends Typed>(schema: ReverseInferred<Model>): Schematic<Model>;
|
|
1356
|
+
/**
|
|
1357
|
+
* Create a schematic from a schema
|
|
1358
|
+
*/
|
|
1359
|
+
export declare function schematic<Model extends Schema>(schema: Model): Schematic<Simplify<Inferred<Model>>>;
|
|
1324
1360
|
/**
|
|
1325
1361
|
* Get a random boolean
|
|
1326
1362
|
*/
|
package/types/index.d.ts
CHANGED
package/types/schema.d.cts
CHANGED
|
@@ -69,7 +69,7 @@ export type Inferred<Model extends Schema> = {
|
|
|
69
69
|
export type ReverseInferred<Model extends Typed> = {
|
|
70
70
|
[Key in keyof Model]: Model[Key] extends Values[keyof Values] ? FindKey<Values, Model[Key]> : never;
|
|
71
71
|
};
|
|
72
|
-
export type Schema = Record<string, keyof Values>;
|
|
72
|
+
export type Schema = Record<string, keyof Values | (keyof Values)[]>;
|
|
73
73
|
export type Schematic<Model> = {
|
|
74
74
|
/**
|
|
75
75
|
* Does the value match the schema?
|
package/types/schema.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ type Inferred<Model extends Schema> = {
|
|
|
8
8
|
type ReverseInferred<Model extends Typed> = {
|
|
9
9
|
[Key in keyof Model]: Model[Key] extends Values[keyof Values] ? FindKey<Values, Model[Key]> : never;
|
|
10
10
|
};
|
|
11
|
-
export type Schema = Record<string, keyof Values>;
|
|
11
|
+
export type Schema = Record<string, keyof Values | (keyof Values)[]>;
|
|
12
12
|
export type Schematic<Model> = {
|
|
13
13
|
/**
|
|
14
14
|
* Does the value match the schema?
|