@lunora/values 1.0.0-alpha.1 → 1.0.0-alpha.11
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/LICENSE.md +6 -0
- package/__assets__/package-og.svg +1 -1
- package/dist/index.d.mts +301 -210
- package/dist/index.d.ts +301 -210
- package/dist/index.mjs +5 -9
- package/dist/packem_shared/{parseValidatorMap-CCjevE5Z.mjs → DEFER_VALIDATION-CIKr17sW.mjs} +15 -3
- package/dist/packem_shared/{ValidationError-DWWcFe37.mjs → ValidationError-CoyFtkxj.mjs} +22 -17
- package/dist/packem_shared/{argsToJsonSchema-DdHmmamC.mjs → argsToJsonSchema-DSAZmlYY.mjs} +1 -1
- package/dist/packem_shared/{isOrWrapsFromValidator-DJMAE0l9.mjs → isOrWrapsFromValidator-BQtxt-B8.mjs} +29 -9
- package/dist/packem_shared/{jsonSchemaFromNode-weszUOQG.mjs → jsonSchemaFromNode-e81rO5qr.mjs} +8 -0
- package/package.json +5 -2
package/dist/index.mjs
CHANGED
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
export { ValidationError, describeValue, formatPath } from './packem_shared/ValidationError-
|
|
2
|
-
export { jsonSchemaFromNode, objectSchemaFromNodes } from './packem_shared/jsonSchemaFromNode-
|
|
3
|
-
export { argsToJsonSchema, toJsonSchema } from './packem_shared/argsToJsonSchema-
|
|
4
|
-
export { isOrWrapsFromValidator, optionalInner, v } from './packem_shared/isOrWrapsFromValidator-
|
|
5
|
-
export { parseValidatorMap } from './packem_shared/
|
|
6
|
-
|
|
7
|
-
const VERSION = "0.0.0";
|
|
8
|
-
|
|
9
|
-
export { VERSION };
|
|
1
|
+
export { ValidationError, describeValue, formatPath } from './packem_shared/ValidationError-CoyFtkxj.mjs';
|
|
2
|
+
export { jsonSchemaFromNode, objectSchemaFromNodes } from './packem_shared/jsonSchemaFromNode-e81rO5qr.mjs';
|
|
3
|
+
export { argsToJsonSchema, toJsonSchema } from './packem_shared/argsToJsonSchema-DSAZmlYY.mjs';
|
|
4
|
+
export { isOrWrapsFromValidator, optionalInner, v } from './packem_shared/isOrWrapsFromValidator-BQtxt-B8.mjs';
|
|
5
|
+
export { DEFER_VALIDATION, installCompiledValidatorMap, parseValidatorMap } from './packem_shared/DEFER_VALIDATION-CIKr17sW.mjs';
|
|
@@ -1,13 +1,25 @@
|
|
|
1
|
-
import { ValidationError } from './ValidationError-
|
|
1
|
+
import { ValidationError } from './ValidationError-CoyFtkxj.mjs';
|
|
2
2
|
|
|
3
|
+
const DEFER_VALIDATION = /* @__PURE__ */ Symbol("lunora.deferValidation");
|
|
4
|
+
const COMPILED_PARSERS = /* @__PURE__ */ new WeakMap();
|
|
5
|
+
const installCompiledValidatorMap = (validators, compiled) => {
|
|
6
|
+
COMPILED_PARSERS.set(validators, compiled);
|
|
7
|
+
};
|
|
3
8
|
const parseValidatorMap = (validators, source, label) => {
|
|
9
|
+
const compiled = COMPILED_PARSERS.get(validators);
|
|
10
|
+
if (compiled !== void 0) {
|
|
11
|
+
const fast = compiled(source);
|
|
12
|
+
if (fast !== DEFER_VALIDATION) {
|
|
13
|
+
return fast;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
4
16
|
const out = {};
|
|
5
17
|
for (const key of Object.keys(validators)) {
|
|
6
18
|
const validator = validators[key];
|
|
7
19
|
if (!validator) {
|
|
8
20
|
continue;
|
|
9
21
|
}
|
|
10
|
-
const candidate = source[key];
|
|
22
|
+
const candidate = Object.hasOwn(source, key) ? source[key] : void 0;
|
|
11
23
|
if (candidate === void 0 && validator.kind === "optional") {
|
|
12
24
|
continue;
|
|
13
25
|
}
|
|
@@ -27,4 +39,4 @@ const parseValidatorMap = (validators, source, label) => {
|
|
|
27
39
|
return out;
|
|
28
40
|
};
|
|
29
41
|
|
|
30
|
-
export { parseValidatorMap };
|
|
42
|
+
export { DEFER_VALIDATION, installCompiledValidatorMap, parseValidatorMap };
|
|
@@ -1,18 +1,32 @@
|
|
|
1
|
+
import { LunoraError } from '@lunora/errors';
|
|
2
|
+
|
|
1
3
|
const MAX_DESCRIBED_LENGTH = 80;
|
|
2
4
|
const truncate = (text) => text.length > MAX_DESCRIBED_LENGTH ? `${text.slice(0, MAX_DESCRIBED_LENGTH)}…` : text;
|
|
3
|
-
|
|
5
|
+
const describeObject = (value) => {
|
|
6
|
+
try {
|
|
7
|
+
const { constructor } = value;
|
|
8
|
+
const constructorName = constructor?.name;
|
|
9
|
+
if (constructorName !== void 0 && constructorName !== "Object") {
|
|
10
|
+
return `object ${constructorName}`;
|
|
11
|
+
}
|
|
12
|
+
} catch {
|
|
13
|
+
return "object";
|
|
14
|
+
}
|
|
15
|
+
return "object";
|
|
16
|
+
};
|
|
17
|
+
class ValidationError extends LunoraError {
|
|
4
18
|
path;
|
|
5
19
|
expected;
|
|
6
20
|
received;
|
|
7
21
|
constructor(message, options) {
|
|
8
|
-
super(message);
|
|
9
|
-
this.name = "ValidationError";
|
|
22
|
+
super("VALIDATION_ERROR", message, { name: "ValidationError" });
|
|
10
23
|
this.path = options.path;
|
|
11
24
|
this.expected = options.expected;
|
|
12
25
|
this.received = options.received;
|
|
13
26
|
}
|
|
14
27
|
}
|
|
15
|
-
const describeValue = (value) => {
|
|
28
|
+
const describeValue = (value, options) => {
|
|
29
|
+
const literal = options?.literal ?? true;
|
|
16
30
|
if (value === null) {
|
|
17
31
|
return "null";
|
|
18
32
|
}
|
|
@@ -23,25 +37,16 @@ const describeValue = (value) => {
|
|
|
23
37
|
return "ArrayBuffer";
|
|
24
38
|
}
|
|
25
39
|
if (typeof value === "string") {
|
|
26
|
-
return `string ${truncate(JSON.stringify(value))}
|
|
40
|
+
return literal ? `string ${truncate(JSON.stringify(value))}` : "string";
|
|
27
41
|
}
|
|
28
42
|
if (typeof value === "number" || typeof value === "boolean") {
|
|
29
|
-
return `${typeof value} ${String(value)}
|
|
43
|
+
return literal ? `${typeof value} ${String(value)}` : typeof value;
|
|
30
44
|
}
|
|
31
45
|
if (typeof value === "bigint") {
|
|
32
|
-
return `bigint ${value.toString()}n
|
|
46
|
+
return literal ? `bigint ${value.toString()}n` : "bigint";
|
|
33
47
|
}
|
|
34
48
|
if (typeof value === "object") {
|
|
35
|
-
|
|
36
|
-
const { constructor } = value;
|
|
37
|
-
const constructorName = constructor?.name;
|
|
38
|
-
if (constructorName !== void 0 && constructorName !== "Object") {
|
|
39
|
-
return `object ${constructorName}`;
|
|
40
|
-
}
|
|
41
|
-
} catch {
|
|
42
|
-
return "object";
|
|
43
|
-
}
|
|
44
|
-
return "object";
|
|
49
|
+
return describeObject(value);
|
|
45
50
|
}
|
|
46
51
|
return typeof value;
|
|
47
52
|
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { objectSchemaFromNodes, jsonSchemaFromNode } from './jsonSchemaFromNode-
|
|
1
|
+
import { objectSchemaFromNodes, jsonSchemaFromNode } from './jsonSchemaFromNode-e81rO5qr.mjs';
|
|
2
2
|
|
|
3
3
|
const introspect = (validator) => validator;
|
|
4
4
|
const metaOf = (validator) => introspect(validator)._meta ?? {};
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { LunoraError } from '@lunora/errors';
|
|
2
|
+
import { ValidationError, formatPath, describeValue } from './ValidationError-CoyFtkxj.mjs';
|
|
2
3
|
|
|
3
|
-
function fail(context, expected, received) {
|
|
4
|
+
function fail(context, expected, received, options) {
|
|
4
5
|
const path = [...context.path];
|
|
5
|
-
const receivedDescription = describeValue(received);
|
|
6
|
+
const receivedDescription = describeValue(received, { literal: !options?.redactValue });
|
|
6
7
|
throw new ValidationError(`Expected ${expected} at ${formatPath(path)}, received ${receivedDescription}`, {
|
|
7
8
|
expected,
|
|
8
9
|
path,
|
|
@@ -77,7 +78,7 @@ const createValidator = (kind, parser, meta) => {
|
|
|
77
78
|
const refinedParser = (value, context) => {
|
|
78
79
|
const parsed = parser(value, context);
|
|
79
80
|
if (!predicate(parsed)) {
|
|
80
|
-
fail(context, message ?? "value matching refinement", parsed);
|
|
81
|
+
fail(context, message ?? "value matching refinement", parsed, { redactValue: true });
|
|
81
82
|
}
|
|
82
83
|
return parsed;
|
|
83
84
|
};
|
|
@@ -171,6 +172,24 @@ const storage = (bucket) => asColumn(
|
|
|
171
172
|
bucket === void 0 ? void 0 : { bucket }
|
|
172
173
|
)
|
|
173
174
|
);
|
|
175
|
+
const geoPoint = () => asColumn(
|
|
176
|
+
createValidator("geoPoint", (value, context) => {
|
|
177
|
+
if (typeof value !== "object" || value === null || Array.isArray(value)) {
|
|
178
|
+
fail(context, "geoPoint { lat, lng }", value);
|
|
179
|
+
}
|
|
180
|
+
const point = value;
|
|
181
|
+
const { lat, lng } = point;
|
|
182
|
+
if (typeof lat !== "number" || !Number.isFinite(lat) || lat < -90 || lat > 90) {
|
|
183
|
+
context.path.push("lat");
|
|
184
|
+
fail(context, "latitude in [-90, 90]", lat);
|
|
185
|
+
}
|
|
186
|
+
if (typeof lng !== "number" || !Number.isFinite(lng) || lng < -180 || lng > 180) {
|
|
187
|
+
context.path.push("lng");
|
|
188
|
+
fail(context, "longitude in [-180, 180]", lng);
|
|
189
|
+
}
|
|
190
|
+
return { lat, lng };
|
|
191
|
+
})
|
|
192
|
+
);
|
|
174
193
|
const literal = (literalValue) => asColumn(
|
|
175
194
|
createValidator(
|
|
176
195
|
"literal",
|
|
@@ -193,11 +212,11 @@ const array = (inner) => {
|
|
|
193
212
|
fail(context, "array", value);
|
|
194
213
|
}
|
|
195
214
|
const { length } = value;
|
|
196
|
-
const out =
|
|
215
|
+
const out = [];
|
|
197
216
|
const { path } = context;
|
|
198
217
|
for (let index = 0; index < length; index += 1) {
|
|
199
218
|
path.push(index);
|
|
200
|
-
out
|
|
219
|
+
out.push(innerInternal._parse(value[index], context));
|
|
201
220
|
path.pop();
|
|
202
221
|
}
|
|
203
222
|
return out;
|
|
@@ -222,7 +241,7 @@ const objectValidator = (shape) => {
|
|
|
222
241
|
const out = {};
|
|
223
242
|
const { path } = context;
|
|
224
243
|
for (const { child, isOptional, key } of entries) {
|
|
225
|
-
const fieldValue = input[key];
|
|
244
|
+
const fieldValue = Object.hasOwn(input, key) ? input[key] : void 0;
|
|
226
245
|
if (fieldValue === void 0 && isOptional) {
|
|
227
246
|
continue;
|
|
228
247
|
}
|
|
@@ -264,7 +283,7 @@ const record = (keyValidator, valueValidator) => {
|
|
|
264
283
|
};
|
|
265
284
|
const union = (...members) => {
|
|
266
285
|
if (members.length === 0) {
|
|
267
|
-
throw new
|
|
286
|
+
throw new LunoraError("INTERNAL", "v.union requires at least one member");
|
|
268
287
|
}
|
|
269
288
|
const memberInternals = members.map((member) => toInternal(member));
|
|
270
289
|
return asColumn(
|
|
@@ -324,7 +343,7 @@ const standardIssuePath = (path) => {
|
|
|
324
343
|
const from = (schema) => {
|
|
325
344
|
const props = schema["~standard"];
|
|
326
345
|
if (props?.version !== 1 || typeof props.validate !== "function") {
|
|
327
|
-
throw new
|
|
346
|
+
throw new LunoraError("INTERNAL", '@lunora/values: v.from() expects a Standard Schema v1 object (missing or invalid "~standard")');
|
|
328
347
|
}
|
|
329
348
|
const validate = props.validate;
|
|
330
349
|
return asColumn(
|
|
@@ -396,6 +415,7 @@ const v = {
|
|
|
396
415
|
bytes,
|
|
397
416
|
date,
|
|
398
417
|
from,
|
|
418
|
+
geoPoint,
|
|
399
419
|
id,
|
|
400
420
|
literal,
|
|
401
421
|
null: nullValidator,
|
package/dist/packem_shared/{jsonSchemaFromNode-weszUOQG.mjs → jsonSchemaFromNode-e81rO5qr.mjs}
RENAMED
|
@@ -20,6 +20,14 @@ const jsonSchemaFromNode = (node, reader) => {
|
|
|
20
20
|
case "date": {
|
|
21
21
|
return { description: "epoch milliseconds (date)", type: "integer" };
|
|
22
22
|
}
|
|
23
|
+
case "geoPoint": {
|
|
24
|
+
return {
|
|
25
|
+
description: "geographic point (WGS84 decimal degrees)",
|
|
26
|
+
properties: { lat: { maximum: 90, minimum: -90, type: "number" }, lng: { maximum: 180, minimum: -180, type: "number" } },
|
|
27
|
+
required: ["lat", "lng"],
|
|
28
|
+
type: "object"
|
|
29
|
+
};
|
|
30
|
+
}
|
|
23
31
|
case "id": {
|
|
24
32
|
return { description: `Id<"${String(reader.tableName(node))}">`, type: "string", "x-lunora-table": reader.tableName(node) };
|
|
25
33
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lunora/values",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.11",
|
|
4
4
|
"description": "Validators for Lunora: the v.* validator suite with end-to-end return-type inference",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cloudflare",
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"directory": "packages/values"
|
|
26
26
|
},
|
|
27
27
|
"files": [
|
|
28
|
-
"dist",
|
|
28
|
+
"./dist",
|
|
29
29
|
"README.md",
|
|
30
30
|
"LICENSE.md",
|
|
31
31
|
"__assets__"
|
|
@@ -45,6 +45,9 @@
|
|
|
45
45
|
"publishConfig": {
|
|
46
46
|
"access": "public"
|
|
47
47
|
},
|
|
48
|
+
"dependencies": {
|
|
49
|
+
"@lunora/errors": "1.0.0-alpha.8"
|
|
50
|
+
},
|
|
48
51
|
"engines": {
|
|
49
52
|
"node": "^22.15.0 || >=24.11.0"
|
|
50
53
|
}
|