New:Socket for Asana Is Now Available.Learn more
Get Started

@ultimat3/schema

Package Overview
Dependencies
Maintainers
1
Versions
26
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@ultimat3/schema - npm Package Compare versions

Comparing version
16.0.0
to
17.0.0
+8
-0
CLAUDE.md

@@ -121,2 +121,10 @@ # @ultimat3/schema — agent notes

reintroduce either half, and never assume a parsed object has `Object.prototype` on it.
- **Every map keyed by a DECLARED FIELD NAME is built on `Object.create(null)`** — `objectSchema`'s
`properties`, `json-schema.ts`'s converted `properties`, and `pick`/`omit`'s rebuilt shape. That
last pair is the one with teeth: `next['__proto__'] = member` on a `{}` literal hits the setter,
so `pick('__proto__')` answered a schema with **zero** properties and dropped the one field the
caller asked to keep from validation, from the IR and from `parse()`'s output. `extend` needs
nothing: object spread defines own properties and never invokes a setter. A field named
`__proto__` is declarable — `t.object({ ['__proto__']: t.string })`, a COMPUTED key, which is an
ordinary own property where the literal `{ __proto__: … }` form is the setter.
- `t.date` refuses a clock time with no offset and no `Z` (`iso-date.ts`): a zone-less string is a

@@ -123,0 +131,0 @@ different instant per host `TZ`, and `coerceQuery` puts it one query parameter from the wire.

+1
-1
{
"name": "@ultimat3/schema",
"version": "16.0.0",
"version": "17.0.0",
"description": "Ultimate's validation seam: Standard Schema interface, the t namespace, JSON Schema output",

@@ -5,0 +5,0 @@ "license": "MIT",

@@ -19,3 +19,7 @@ // Single responsibility: this package's error codes. `@ultimat3/schema` is tier 0 and may not

const CONTROL = /[\u0000-\u001f\u007f\u2028\u2029]/g;
const ESCAPES: Readonly<Record<string, string>> = {
// Null-prototype, so `ESCAPES[char]` cannot answer an `Object.prototype` member no matter what
// `CONTROL` matched. The domain argument — a key is exactly one control character, and no
// prototype member has a single-character name — was true and is no longer load-bearing; a table
// that cannot reach the prototype needs no argument, and `bun run proto-index` stops reporting it.
const ESCAPES: Readonly<Record<string, string>> = Object.assign(Object.create(null), {
'\n': String.raw`\n`,

@@ -26,7 +30,3 @@ '\r': String.raw`\r`,

'\f': String.raw`\f`,
};
// `ESCAPES[char]` is a computed read on a plain object and is safe by DOMAIN, not by luck: the
// key is whatever `CONTROL` matched, so it is exactly one control character — and no
// `Object.prototype` member has a single-character name. Every other computed read in this file
// goes through `Object.hasOwn`.
});
const singleLine = (text: string): string =>

@@ -33,0 +33,0 @@ text.replace(

@@ -234,3 +234,9 @@ // Single responsibility: SchemaNode -> JSON Schema. Load-bearing: OpenAPI request/response

case 'object': {
const properties: Record<string, JsonSchema> = {};
// `Object.create(null)`, the same rule `validators.ts` applies to the IR this reads: a
// `__proto__` property assigned into a `{}` literal reaches the setter and is published
// nowhere, so the document would omit a field the server enforces.
const properties: Record<string, JsonSchema> = Object.create(null) as Record<
string,
JsonSchema
>;
for (const [key, child] of Object.entries(node.properties ?? {})) {

@@ -237,0 +243,0 @@ properties[key] = convert(child);

@@ -158,3 +158,7 @@ // Single responsibility: the builtin, dependency-free validators behind `t`. Small on purpose —

export function objectSchema<S extends Shape>(shape: S): ObjectSchema<S> {
const properties: Record<string, SchemaNode> = {};
// `Object.create(null)` for the same reason the parse output below uses one, on the other side
// of the same rule: a DECLARED `__proto__` field assigned into a `{}` literal hits the prototype
// setter and never becomes a key, so the field vanished from the IR `json-schema.ts` publishes
// and `coerce.ts` walks while the `checks` list beside it went on validating it.
const properties: Record<string, SchemaNode> = Object.create(null) as Record<string, SchemaNode>;
const checks: [string, Check<unknown>][] = [];

@@ -199,4 +203,10 @@ for (const [key, member] of Object.entries(shape)) {

extend: (extra) => objectSchema({ ...shape, ...extra } as Simplified<S & typeof extra>),
// `Object.create(null)` in both, for the reason the IR above states and with a worse outcome
// here: `next['__proto__'] = member` on a `{}` literal hits the prototype SETTER, so the field
// is not mis-published, it is GONE — `pick('__proto__')` answered a schema with no properties
// at all, dropping the one field the caller asked to keep from validation, from the IR and
// from `parse()`'s output. `extend` needs none of this: object spread defines own properties
// and never invokes a setter.
pick: (...keys) => {
const next: Record<string, AnySchema> = {};
const next: Record<string, AnySchema> = Object.create(null) as Record<string, AnySchema>;
for (const key of keys) next[key] = shape[key] as AnySchema;

@@ -207,3 +217,3 @@ return objectSchema(next) as ObjectSchema<Pick<S, (typeof keys)[number]>>;

const drop = new Set<string>(keys);
const next: Record<string, AnySchema> = {};
const next: Record<string, AnySchema> = Object.create(null) as Record<string, AnySchema>;
for (const [key, member] of Object.entries(shape)) {

@@ -210,0 +220,0 @@ if (!drop.has(key)) next[key] = member;