@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 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
- function getKeys(value) {
4
- return value && typeof value === "object" ? Object.keys(value) : [];
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 keys = getKeys(schema);
8
- const { length } = keys;
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(schema, keys, length, value)
52
+ is: (value) => canValidate && validate(validated, value)
12
53
  });
13
54
  }
14
- function validate(schema, keys, length, value) {
15
- if (getKeys(value).length !== length) {
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
- if (!validators[schema[key]](value[key])) {
21
- return false;
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
- function getKeys(value) {
2
- return value && typeof value === "object" ? Object.keys(value) : [];
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 keys = getKeys(schema);
6
- const { length } = keys;
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(schema, keys, length, value)
50
+ is: (value) => canValidate && validate(validated, value)
10
51
  });
11
52
  }
12
- function validate(schema, keys, length, value) {
13
- if (getKeys(value).length !== length) {
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
- if (!validators[schema[key]](value[key])) {
19
- return false;
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.33"
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.85.0"
221
+ "version": "0.86.0"
222
222
  }
package/src/index.ts CHANGED
@@ -11,6 +11,7 @@ export * from './number';
11
11
  export * from './query';
12
12
  export * from './queue';
13
13
  export * from './random';
14
+ export * from './schema';
14
15
  export * from './sized';
15
16
  export * from './string/index';
16
17
  export * from './touch';
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
- function getKeys(value: unknown): string[] {
45
- return value && typeof value === 'object' ? Object.keys(value) : [];
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 keys = getKeys(schema);
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
- schema: Schema,
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 (!validators[schema[key]]((value as PlainObject)[key])) {
88
- return false;
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
@@ -11,6 +11,7 @@ export * from './number';
11
11
  export * from './query';
12
12
  export * from './queue';
13
13
  export * from './random';
14
+ export * from './schema';
14
15
  export * from './sized';
15
16
  export * from './string/index';
16
17
  export * from './touch';
@@ -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?