@datastream/validate
Advanced tools
+30
| // Copyright 2026 will Farrell, and datastream contributors. | ||
| // SPDX-License-Identifier: MIT | ||
| import type { StreamOptions, StreamResult } from "@datastream/core"; | ||
| export interface ValidateError { | ||
| id: string; | ||
| keys: string[]; | ||
| message: string; | ||
| idx: number[]; | ||
| } | ||
| export function transpileSchema( | ||
| schema: Record<string, unknown>, | ||
| ajvOptions?: Record<string, unknown>, | ||
| ): (data: unknown) => boolean; | ||
| export function validateStream( | ||
| options: { | ||
| schema: Record<string, unknown> | ((data: unknown) => boolean); | ||
| idxStart?: number; | ||
| onErrorEnqueue?: boolean; | ||
| allowCoerceTypes?: boolean; | ||
| resultKey?: string; | ||
| }, | ||
| streamOptions?: StreamOptions, | ||
| ): unknown & { | ||
| result: () => StreamResult<Record<string, ValidateError>>; | ||
| }; | ||
| export default validateStream; |
+52
| <div align="center"> | ||
| <h1><datastream> `validate`</h1> | ||
| <img alt="datastream logo" src="https://raw.githubusercontent.com/willfarrell/datastream/main/docs/img/datastream-logo.svg"/> | ||
| <p><strong>JSON schema validation streams.</strong></p> | ||
| <p> | ||
| <a href="https://github.com/willfarrell/datastream/actions/workflows/test-unit.yml"><img src="https://github.com/willfarrell/datastream/actions/workflows/test-unit.yml/badge.svg" alt="GitHub Actions unit test status"></a> | ||
| <a href="https://github.com/willfarrell/datastream/actions/workflows/test-dast.yml"><img src="https://github.com/willfarrell/datastream/actions/workflows/test-dast.yml/badge.svg" alt="GitHub Actions dast test status"></a> | ||
| <a href="https://github.com/willfarrell/datastream/actions/workflows/test-perf.yml"><img src="https://github.com/willfarrell/datastream/actions/workflows/test-perf.yml/badge.svg" alt="GitHub Actions perf test status"></a> | ||
| <a href="https://github.com/willfarrell/datastream/actions/workflows/test-sast.yml"><img src="https://github.com/willfarrell/datastream/actions/workflows/test-sast.yml/badge.svg" alt="GitHub Actions SAST test status"></a> | ||
| <a href="https://github.com/willfarrell/datastream/actions/workflows/test-lint.yml"><img src="https://github.com/willfarrell/datastream/actions/workflows/test-lint.yml/badge.svg" alt="GitHub Actions lint test status"></a> | ||
| <br/> | ||
| <a href="https://www.npmjs.com/package/@datastream/validate"><img alt="npm version" src="https://img.shields.io/npm/v/@datastream/validate.svg"></a> | ||
| <a href="https://packagephobia.com/result?p=@datastream/validate"><img src="https://packagephobia.com/badge?p=@datastream/validate" alt="npm install size"></a> | ||
| <a href="https://www.npmjs.com/package/@datastream/validate"> | ||
| <img alt="npm weekly downloads" src="https://img.shields.io/npm/dw/@datastream/validate.svg"></a> | ||
| <a href="https://www.npmjs.com/package/@datastream/validate#provenance"> | ||
| <img alt="npm provenance" src="https://img.shields.io/badge/provenance-Yes-brightgreen"></a> | ||
| <br/> | ||
| <a href="https://scorecard.dev/viewer/?uri=github.com/willfarrell/datastream"><img src="https://api.scorecard.dev/projects/github.com/willfarrell/datastream/badge" alt="Open Source Security Foundation (OpenSSF) Scorecard"></a> | ||
| <a href="https://slsa.dev"><img src="https://slsa.dev/images/gh-badge-level3.svg" alt="SLSA 3"></a> | ||
| <a href="https://github.com/willfarrell/datastream/blob/main/docs/CODE_OF_CONDUCT.md"><img src="https://img.shields.io/badge/Contributor%20Covenant-2.1-4baaaa.svg"></a> | ||
| <a href="https://biomejs.dev"><img alt="Checked with Biome" src="https://img.shields.io/badge/Checked_with-Biome-60a5fa?style=flat&logo=biome"></a> | ||
| <a href="https://conventionalcommits.org"><img alt="Conventional Commits" src="https://img.shields.io/badge/Conventional%20Commits-1.0.0-%23FE5196?logo=conventionalcommits&logoColor=white"></a> | ||
| <a href="https://github.com/willfarrell/datastream/blob/main/package.json#L32"> | ||
| <img alt="code coverage" src="https://img.shields.io/badge/code%20coverage-95%25-brightgreen"></a> | ||
| </p> | ||
| <p>You can read the documentation at: <a href="https://datastream.js.org">https://datastream.js.org</a></p> | ||
| </div> | ||
| ## Install | ||
| To install datastream you can use NPM: | ||
| ```bash | ||
| npm install --save @datastream/validate | ||
| ``` | ||
| ## Documentation and examples | ||
| For documentation and examples, refer to the main [datastream monorepo on GitHub](https://github.com/willfarrell/datastream) or [datastream official website](https://datastream.js.org). | ||
| ## Contributing | ||
| Everyone is very welcome to contribute to this repository. Feel free to [raise issues](https://github.com/willfarrell/datastream/issues) or to [submit Pull Requests](https://github.com/willfarrell/datastream/pulls). | ||
| ## License | ||
| Licensed under [MIT License](LICENSE). Copyright (c) 2026 [will Farrell](https://github.com/willfarrell), and [datastream contributors](https://github.com/willfarrell/datastream/graphs/contributors). |
+2
-3
@@ -24,3 +24,3 @@ import { createTransformStream } from "@datastream/core"; | ||
| idx += 1; | ||
| const data = structuredClone(chunk); | ||
| const data = allowCoerceTypes === false ? structuredClone(chunk) : void 0; | ||
| const chunkValid = schema(chunk); | ||
@@ -37,4 +37,3 @@ if (!chunkValid) { | ||
| if (chunkValid || onErrorEnqueue) { | ||
| chunk = allowCoerceTypes ? chunk : data; | ||
| enqueue(chunk); | ||
| enqueue(data ?? chunk); | ||
| } | ||
@@ -41,0 +40,0 @@ }; |
| { | ||
| "version": 3, | ||
| "sources": ["index.js"], | ||
| "sourcesContent": ["import { createTransformStream } from \"@datastream/core\";\nimport { compile } from \"ajv-cmd\";\n\nconst ajvDefaults = {\n\tstrict: true,\n\tcoerceTypes: true,\n\tallErrors: true,\n\tuseDefaults: \"empty\",\n\tmessages: true, // needs to be true to allow multi-locale errorMessage to work\n};\n\n// This is pulled out due to it's performance cost (50-100ms on cold start)\n// Precompile your schema during a build step is recommended.\nexport const transpileSchema = (schema, ajvOptions) => {\n\tconst options = { ...ajvDefaults, ...ajvOptions };\n\treturn compile(schema, options);\n};\n\nexport const validateStream = (\n\t{ schema, idxStart, onErrorEnqueue, allowCoerceTypes, resultKey },\n\tstreamOptions = {},\n) => {\n\tidxStart ??= 0;\n\n\tif (typeof schema !== \"function\") {\n\t\tschema = transpileSchema(schema);\n\t}\n\n\tconst value = {}; // aka errors\n\tlet idx = idxStart - 1;\n\tconst transform = (chunk, enqueue) => {\n\t\tidx += 1;\n\t\tconst data = structuredClone(chunk);\n\t\tconst chunkValid = schema(chunk);\n\t\tif (!chunkValid) {\n\t\t\tfor (const error of schema.errors) {\n\t\t\t\tconst { id, keys, message } = processError(error);\n\n\t\t\t\tif (!value[id]) {\n\t\t\t\t\tvalue[id] = { id, keys, message, idx: [] };\n\t\t\t\t}\n\t\t\t\tvalue[id].idx.push(idx);\n\t\t\t}\n\t\t}\n\t\tif (chunkValid || onErrorEnqueue) {\n\t\t\tchunk = allowCoerceTypes ? chunk : data;\n\t\t\tenqueue(chunk);\n\t\t}\n\t};\n\tconst stream = createTransformStream(transform, streamOptions);\n\tstream.result = () => ({ key: resultKey ?? \"validate\", value });\n\treturn stream;\n};\n\nconst processError = (error) => {\n\tconst message = error.message || \"\";\n\n\tlet id = error.schemaPath;\n\n\tlet keys = [];\n\tif (error.keyword === \"errorMessage\") {\n\t\terror.params.errors.forEach((error) => {\n\t\t\tconst value = makeKeys(error);\n\t\t\tif (value) keys.push(value);\n\t\t});\n\t\tkeys = [...new Set(keys.sort())];\n\t} else {\n\t\tkeys.push(makeKeys(error));\n\t}\n\tif (!error.instancePath && keys.length) {\n\t\tid += `/${keys.join(\"|\")}`;\n\t}\n\treturn { id, keys, message };\n};\n\nconst makeKeys = (error) => {\n\t// deps groups columns that are related in anyOf/oneOf.\n\t/* error.params.deps ?? */\n\treturn (\n\t\terror.params.missingProperty ||\n\t\terror.params.additionalProperty ||\n\t\terror.instancePath.replace(\"/\", \"\")\n\t);\n};\n\nexport default validateStream;\n"], | ||
| "mappings": "AAAA,SAAS,6BAA6B;AACtC,SAAS,eAAe;AAExB,MAAM,cAAc;AAAA,EACnB,QAAQ;AAAA,EACR,aAAa;AAAA,EACb,WAAW;AAAA,EACX,aAAa;AAAA,EACb,UAAU;AAAA;AACX;AAIO,MAAM,kBAAkB,CAAC,QAAQ,eAAe;AACtD,QAAM,UAAU,EAAE,GAAG,aAAa,GAAG,WAAW;AAChD,SAAO,QAAQ,QAAQ,OAAO;AAC/B;AAEO,MAAM,iBAAiB,CAC7B,EAAE,QAAQ,UAAU,gBAAgB,kBAAkB,UAAU,GAChE,gBAAgB,CAAC,MACb;AACJ,eAAa;AAEb,MAAI,OAAO,WAAW,YAAY;AACjC,aAAS,gBAAgB,MAAM;AAAA,EAChC;AAEA,QAAM,QAAQ,CAAC;AACf,MAAI,MAAM,WAAW;AACrB,QAAM,YAAY,CAAC,OAAO,YAAY;AACrC,WAAO;AACP,UAAM,OAAO,gBAAgB,KAAK;AAClC,UAAM,aAAa,OAAO,KAAK;AAC/B,QAAI,CAAC,YAAY;AAChB,iBAAW,SAAS,OAAO,QAAQ;AAClC,cAAM,EAAE,IAAI,MAAM,QAAQ,IAAI,aAAa,KAAK;AAEhD,YAAI,CAAC,MAAM,EAAE,GAAG;AACf,gBAAM,EAAE,IAAI,EAAE,IAAI,MAAM,SAAS,KAAK,CAAC,EAAE;AAAA,QAC1C;AACA,cAAM,EAAE,EAAE,IAAI,KAAK,GAAG;AAAA,MACvB;AAAA,IACD;AACA,QAAI,cAAc,gBAAgB;AACjC,cAAQ,mBAAmB,QAAQ;AACnC,cAAQ,KAAK;AAAA,IACd;AAAA,EACD;AACA,QAAM,SAAS,sBAAsB,WAAW,aAAa;AAC7D,SAAO,SAAS,OAAO,EAAE,KAAK,aAAa,YAAY,MAAM;AAC7D,SAAO;AACR;AAEA,MAAM,eAAe,CAAC,UAAU;AAC/B,QAAM,UAAU,MAAM,WAAW;AAEjC,MAAI,KAAK,MAAM;AAEf,MAAI,OAAO,CAAC;AACZ,MAAI,MAAM,YAAY,gBAAgB;AACrC,UAAM,OAAO,OAAO,QAAQ,CAACA,WAAU;AACtC,YAAM,QAAQ,SAASA,MAAK;AAC5B,UAAI,MAAO,MAAK,KAAK,KAAK;AAAA,IAC3B,CAAC;AACD,WAAO,CAAC,GAAG,IAAI,IAAI,KAAK,KAAK,CAAC,CAAC;AAAA,EAChC,OAAO;AACN,SAAK,KAAK,SAAS,KAAK,CAAC;AAAA,EAC1B;AACA,MAAI,CAAC,MAAM,gBAAgB,KAAK,QAAQ;AACvC,UAAM,IAAI,KAAK,KAAK,GAAG,CAAC;AAAA,EACzB;AACA,SAAO,EAAE,IAAI,MAAM,QAAQ;AAC5B;AAEA,MAAM,WAAW,CAAC,UAAU;AAG3B,SACC,MAAM,OAAO,mBACb,MAAM,OAAO,sBACb,MAAM,aAAa,QAAQ,KAAK,EAAE;AAEpC;AAEA,IAAO,gBAAQ;", | ||
| "sourcesContent": ["// Copyright 2026 will Farrell, and datastream contributors.\n// SPDX-License-Identifier: MIT\nimport { createTransformStream } from \"@datastream/core\";\nimport { compile } from \"ajv-cmd\";\n\nconst ajvDefaults = {\n\tstrict: true,\n\tcoerceTypes: true,\n\tallErrors: true,\n\tuseDefaults: \"empty\",\n\tmessages: true, // needs to be true to allow multi-locale errorMessage to work\n};\n\n// This is pulled out due to it's performance cost (50-100ms on cold start)\n// Precompile your schema during a build step is recommended.\nexport const transpileSchema = (schema, ajvOptions) => {\n\tconst options = { ...ajvDefaults, ...ajvOptions };\n\treturn compile(schema, options);\n};\n\nexport const validateStream = (\n\t{ schema, idxStart, onErrorEnqueue, allowCoerceTypes, resultKey },\n\tstreamOptions = {},\n) => {\n\tidxStart ??= 0;\n\n\tif (typeof schema !== \"function\") {\n\t\tschema = transpileSchema(schema);\n\t}\n\n\tconst value = {}; // aka errors\n\tlet idx = idxStart - 1;\n\tconst transform = (chunk, enqueue) => {\n\t\tidx += 1;\n\t\tconst data =\n\t\t\tallowCoerceTypes === false ? structuredClone(chunk) : undefined;\n\t\tconst chunkValid = schema(chunk);\n\t\tif (!chunkValid) {\n\t\t\tfor (const error of schema.errors) {\n\t\t\t\tconst { id, keys, message } = processError(error);\n\n\t\t\t\tif (!value[id]) {\n\t\t\t\t\tvalue[id] = { id, keys, message, idx: [] };\n\t\t\t\t}\n\t\t\t\tvalue[id].idx.push(idx);\n\t\t\t}\n\t\t}\n\t\tif (chunkValid || onErrorEnqueue) {\n\t\t\tenqueue(data ?? chunk);\n\t\t}\n\t};\n\tconst stream = createTransformStream(transform, streamOptions);\n\tstream.result = () => ({ key: resultKey ?? \"validate\", value });\n\treturn stream;\n};\n\nconst processError = (error) => {\n\tconst message = error.message || \"\";\n\n\tlet id = error.schemaPath;\n\n\tlet keys = [];\n\tif (error.keyword === \"errorMessage\") {\n\t\terror.params.errors.forEach((error) => {\n\t\t\tconst value = makeKeys(error);\n\t\t\tif (value) keys.push(value);\n\t\t});\n\t\tkeys = [...new Set(keys.sort())];\n\t} else {\n\t\tkeys.push(makeKeys(error));\n\t}\n\tif (!error.instancePath && keys.length) {\n\t\tid += `/${keys.join(\"|\")}`;\n\t}\n\treturn { id, keys, message };\n};\n\nconst makeKeys = (error) => {\n\t// deps groups columns that are related in anyOf/oneOf.\n\t/* error.params.deps ?? */\n\treturn (\n\t\terror.params.missingProperty ||\n\t\terror.params.additionalProperty ||\n\t\terror.instancePath.replace(\"/\", \"\")\n\t);\n};\n\nexport default validateStream;\n"], | ||
| "mappings": "AAEA,SAAS,6BAA6B;AACtC,SAAS,eAAe;AAExB,MAAM,cAAc;AAAA,EACnB,QAAQ;AAAA,EACR,aAAa;AAAA,EACb,WAAW;AAAA,EACX,aAAa;AAAA,EACb,UAAU;AAAA;AACX;AAIO,MAAM,kBAAkB,CAAC,QAAQ,eAAe;AACtD,QAAM,UAAU,EAAE,GAAG,aAAa,GAAG,WAAW;AAChD,SAAO,QAAQ,QAAQ,OAAO;AAC/B;AAEO,MAAM,iBAAiB,CAC7B,EAAE,QAAQ,UAAU,gBAAgB,kBAAkB,UAAU,GAChE,gBAAgB,CAAC,MACb;AACJ,eAAa;AAEb,MAAI,OAAO,WAAW,YAAY;AACjC,aAAS,gBAAgB,MAAM;AAAA,EAChC;AAEA,QAAM,QAAQ,CAAC;AACf,MAAI,MAAM,WAAW;AACrB,QAAM,YAAY,CAAC,OAAO,YAAY;AACrC,WAAO;AACP,UAAM,OACL,qBAAqB,QAAQ,gBAAgB,KAAK,IAAI;AACvD,UAAM,aAAa,OAAO,KAAK;AAC/B,QAAI,CAAC,YAAY;AAChB,iBAAW,SAAS,OAAO,QAAQ;AAClC,cAAM,EAAE,IAAI,MAAM,QAAQ,IAAI,aAAa,KAAK;AAEhD,YAAI,CAAC,MAAM,EAAE,GAAG;AACf,gBAAM,EAAE,IAAI,EAAE,IAAI,MAAM,SAAS,KAAK,CAAC,EAAE;AAAA,QAC1C;AACA,cAAM,EAAE,EAAE,IAAI,KAAK,GAAG;AAAA,MACvB;AAAA,IACD;AACA,QAAI,cAAc,gBAAgB;AACjC,cAAQ,QAAQ,KAAK;AAAA,IACtB;AAAA,EACD;AACA,QAAM,SAAS,sBAAsB,WAAW,aAAa;AAC7D,SAAO,SAAS,OAAO,EAAE,KAAK,aAAa,YAAY,MAAM;AAC7D,SAAO;AACR;AAEA,MAAM,eAAe,CAAC,UAAU;AAC/B,QAAM,UAAU,MAAM,WAAW;AAEjC,MAAI,KAAK,MAAM;AAEf,MAAI,OAAO,CAAC;AACZ,MAAI,MAAM,YAAY,gBAAgB;AACrC,UAAM,OAAO,OAAO,QAAQ,CAACA,WAAU;AACtC,YAAM,QAAQ,SAASA,MAAK;AAC5B,UAAI,MAAO,MAAK,KAAK,KAAK;AAAA,IAC3B,CAAC;AACD,WAAO,CAAC,GAAG,IAAI,IAAI,KAAK,KAAK,CAAC,CAAC;AAAA,EAChC,OAAO;AACN,SAAK,KAAK,SAAS,KAAK,CAAC;AAAA,EAC1B;AACA,MAAI,CAAC,MAAM,gBAAgB,KAAK,QAAQ;AACvC,UAAM,IAAI,KAAK,KAAK,GAAG,CAAC;AAAA,EACzB;AACA,SAAO,EAAE,IAAI,MAAM,QAAQ;AAC5B;AAEA,MAAM,WAAW,CAAC,UAAU;AAG3B,SACC,MAAM,OAAO,mBACb,MAAM,OAAO,sBACb,MAAM,aAAa,QAAQ,KAAK,EAAE;AAEpC;AAEA,IAAO,gBAAQ;", | ||
| "names": ["error"] | ||
| } |
+2
-3
@@ -24,3 +24,3 @@ import { createTransformStream } from "@datastream/core"; | ||
| idx += 1; | ||
| const data = structuredClone(chunk); | ||
| const data = allowCoerceTypes === false ? structuredClone(chunk) : void 0; | ||
| const chunkValid = schema(chunk); | ||
@@ -37,4 +37,3 @@ if (!chunkValid) { | ||
| if (chunkValid || onErrorEnqueue) { | ||
| chunk = allowCoerceTypes ? chunk : data; | ||
| enqueue(chunk); | ||
| enqueue(data ?? chunk); | ||
| } | ||
@@ -41,0 +40,0 @@ }; |
| { | ||
| "version": 3, | ||
| "sources": ["index.js"], | ||
| "sourcesContent": ["import { createTransformStream } from \"@datastream/core\";\nimport { compile } from \"ajv-cmd\";\n\nconst ajvDefaults = {\n\tstrict: true,\n\tcoerceTypes: true,\n\tallErrors: true,\n\tuseDefaults: \"empty\",\n\tmessages: true, // needs to be true to allow multi-locale errorMessage to work\n};\n\n// This is pulled out due to it's performance cost (50-100ms on cold start)\n// Precompile your schema during a build step is recommended.\nexport const transpileSchema = (schema, ajvOptions) => {\n\tconst options = { ...ajvDefaults, ...ajvOptions };\n\treturn compile(schema, options);\n};\n\nexport const validateStream = (\n\t{ schema, idxStart, onErrorEnqueue, allowCoerceTypes, resultKey },\n\tstreamOptions = {},\n) => {\n\tidxStart ??= 0;\n\n\tif (typeof schema !== \"function\") {\n\t\tschema = transpileSchema(schema);\n\t}\n\n\tconst value = {}; // aka errors\n\tlet idx = idxStart - 1;\n\tconst transform = (chunk, enqueue) => {\n\t\tidx += 1;\n\t\tconst data = structuredClone(chunk);\n\t\tconst chunkValid = schema(chunk);\n\t\tif (!chunkValid) {\n\t\t\tfor (const error of schema.errors) {\n\t\t\t\tconst { id, keys, message } = processError(error);\n\n\t\t\t\tif (!value[id]) {\n\t\t\t\t\tvalue[id] = { id, keys, message, idx: [] };\n\t\t\t\t}\n\t\t\t\tvalue[id].idx.push(idx);\n\t\t\t}\n\t\t}\n\t\tif (chunkValid || onErrorEnqueue) {\n\t\t\tchunk = allowCoerceTypes ? chunk : data;\n\t\t\tenqueue(chunk);\n\t\t}\n\t};\n\tconst stream = createTransformStream(transform, streamOptions);\n\tstream.result = () => ({ key: resultKey ?? \"validate\", value });\n\treturn stream;\n};\n\nconst processError = (error) => {\n\tconst message = error.message || \"\";\n\n\tlet id = error.schemaPath;\n\n\tlet keys = [];\n\tif (error.keyword === \"errorMessage\") {\n\t\terror.params.errors.forEach((error) => {\n\t\t\tconst value = makeKeys(error);\n\t\t\tif (value) keys.push(value);\n\t\t});\n\t\tkeys = [...new Set(keys.sort())];\n\t} else {\n\t\tkeys.push(makeKeys(error));\n\t}\n\tif (!error.instancePath && keys.length) {\n\t\tid += `/${keys.join(\"|\")}`;\n\t}\n\treturn { id, keys, message };\n};\n\nconst makeKeys = (error) => {\n\t// deps groups columns that are related in anyOf/oneOf.\n\t/* error.params.deps ?? */\n\treturn (\n\t\terror.params.missingProperty ||\n\t\terror.params.additionalProperty ||\n\t\terror.instancePath.replace(\"/\", \"\")\n\t);\n};\n\nexport default validateStream;\n"], | ||
| "mappings": "AAAA,SAAS,6BAA6B;AACtC,SAAS,eAAe;AAExB,MAAM,cAAc;AAAA,EACnB,QAAQ;AAAA,EACR,aAAa;AAAA,EACb,WAAW;AAAA,EACX,aAAa;AAAA,EACb,UAAU;AAAA;AACX;AAIO,MAAM,kBAAkB,CAAC,QAAQ,eAAe;AACtD,QAAM,UAAU,EAAE,GAAG,aAAa,GAAG,WAAW;AAChD,SAAO,QAAQ,QAAQ,OAAO;AAC/B;AAEO,MAAM,iBAAiB,CAC7B,EAAE,QAAQ,UAAU,gBAAgB,kBAAkB,UAAU,GAChE,gBAAgB,CAAC,MACb;AACJ,eAAa;AAEb,MAAI,OAAO,WAAW,YAAY;AACjC,aAAS,gBAAgB,MAAM;AAAA,EAChC;AAEA,QAAM,QAAQ,CAAC;AACf,MAAI,MAAM,WAAW;AACrB,QAAM,YAAY,CAAC,OAAO,YAAY;AACrC,WAAO;AACP,UAAM,OAAO,gBAAgB,KAAK;AAClC,UAAM,aAAa,OAAO,KAAK;AAC/B,QAAI,CAAC,YAAY;AAChB,iBAAW,SAAS,OAAO,QAAQ;AAClC,cAAM,EAAE,IAAI,MAAM,QAAQ,IAAI,aAAa,KAAK;AAEhD,YAAI,CAAC,MAAM,EAAE,GAAG;AACf,gBAAM,EAAE,IAAI,EAAE,IAAI,MAAM,SAAS,KAAK,CAAC,EAAE;AAAA,QAC1C;AACA,cAAM,EAAE,EAAE,IAAI,KAAK,GAAG;AAAA,MACvB;AAAA,IACD;AACA,QAAI,cAAc,gBAAgB;AACjC,cAAQ,mBAAmB,QAAQ;AACnC,cAAQ,KAAK;AAAA,IACd;AAAA,EACD;AACA,QAAM,SAAS,sBAAsB,WAAW,aAAa;AAC7D,SAAO,SAAS,OAAO,EAAE,KAAK,aAAa,YAAY,MAAM;AAC7D,SAAO;AACR;AAEA,MAAM,eAAe,CAAC,UAAU;AAC/B,QAAM,UAAU,MAAM,WAAW;AAEjC,MAAI,KAAK,MAAM;AAEf,MAAI,OAAO,CAAC;AACZ,MAAI,MAAM,YAAY,gBAAgB;AACrC,UAAM,OAAO,OAAO,QAAQ,CAACA,WAAU;AACtC,YAAM,QAAQ,SAASA,MAAK;AAC5B,UAAI,MAAO,MAAK,KAAK,KAAK;AAAA,IAC3B,CAAC;AACD,WAAO,CAAC,GAAG,IAAI,IAAI,KAAK,KAAK,CAAC,CAAC;AAAA,EAChC,OAAO;AACN,SAAK,KAAK,SAAS,KAAK,CAAC;AAAA,EAC1B;AACA,MAAI,CAAC,MAAM,gBAAgB,KAAK,QAAQ;AACvC,UAAM,IAAI,KAAK,KAAK,GAAG,CAAC;AAAA,EACzB;AACA,SAAO,EAAE,IAAI,MAAM,QAAQ;AAC5B;AAEA,MAAM,WAAW,CAAC,UAAU;AAG3B,SACC,MAAM,OAAO,mBACb,MAAM,OAAO,sBACb,MAAM,aAAa,QAAQ,KAAK,EAAE;AAEpC;AAEA,IAAO,gBAAQ;", | ||
| "sourcesContent": ["// Copyright 2026 will Farrell, and datastream contributors.\n// SPDX-License-Identifier: MIT\nimport { createTransformStream } from \"@datastream/core\";\nimport { compile } from \"ajv-cmd\";\n\nconst ajvDefaults = {\n\tstrict: true,\n\tcoerceTypes: true,\n\tallErrors: true,\n\tuseDefaults: \"empty\",\n\tmessages: true, // needs to be true to allow multi-locale errorMessage to work\n};\n\n// This is pulled out due to it's performance cost (50-100ms on cold start)\n// Precompile your schema during a build step is recommended.\nexport const transpileSchema = (schema, ajvOptions) => {\n\tconst options = { ...ajvDefaults, ...ajvOptions };\n\treturn compile(schema, options);\n};\n\nexport const validateStream = (\n\t{ schema, idxStart, onErrorEnqueue, allowCoerceTypes, resultKey },\n\tstreamOptions = {},\n) => {\n\tidxStart ??= 0;\n\n\tif (typeof schema !== \"function\") {\n\t\tschema = transpileSchema(schema);\n\t}\n\n\tconst value = {}; // aka errors\n\tlet idx = idxStart - 1;\n\tconst transform = (chunk, enqueue) => {\n\t\tidx += 1;\n\t\tconst data =\n\t\t\tallowCoerceTypes === false ? structuredClone(chunk) : undefined;\n\t\tconst chunkValid = schema(chunk);\n\t\tif (!chunkValid) {\n\t\t\tfor (const error of schema.errors) {\n\t\t\t\tconst { id, keys, message } = processError(error);\n\n\t\t\t\tif (!value[id]) {\n\t\t\t\t\tvalue[id] = { id, keys, message, idx: [] };\n\t\t\t\t}\n\t\t\t\tvalue[id].idx.push(idx);\n\t\t\t}\n\t\t}\n\t\tif (chunkValid || onErrorEnqueue) {\n\t\t\tenqueue(data ?? chunk);\n\t\t}\n\t};\n\tconst stream = createTransformStream(transform, streamOptions);\n\tstream.result = () => ({ key: resultKey ?? \"validate\", value });\n\treturn stream;\n};\n\nconst processError = (error) => {\n\tconst message = error.message || \"\";\n\n\tlet id = error.schemaPath;\n\n\tlet keys = [];\n\tif (error.keyword === \"errorMessage\") {\n\t\terror.params.errors.forEach((error) => {\n\t\t\tconst value = makeKeys(error);\n\t\t\tif (value) keys.push(value);\n\t\t});\n\t\tkeys = [...new Set(keys.sort())];\n\t} else {\n\t\tkeys.push(makeKeys(error));\n\t}\n\tif (!error.instancePath && keys.length) {\n\t\tid += `/${keys.join(\"|\")}`;\n\t}\n\treturn { id, keys, message };\n};\n\nconst makeKeys = (error) => {\n\t// deps groups columns that are related in anyOf/oneOf.\n\t/* error.params.deps ?? */\n\treturn (\n\t\terror.params.missingProperty ||\n\t\terror.params.additionalProperty ||\n\t\terror.instancePath.replace(\"/\", \"\")\n\t);\n};\n\nexport default validateStream;\n"], | ||
| "mappings": "AAEA,SAAS,6BAA6B;AACtC,SAAS,eAAe;AAExB,MAAM,cAAc;AAAA,EACnB,QAAQ;AAAA,EACR,aAAa;AAAA,EACb,WAAW;AAAA,EACX,aAAa;AAAA,EACb,UAAU;AAAA;AACX;AAIO,MAAM,kBAAkB,CAAC,QAAQ,eAAe;AACtD,QAAM,UAAU,EAAE,GAAG,aAAa,GAAG,WAAW;AAChD,SAAO,QAAQ,QAAQ,OAAO;AAC/B;AAEO,MAAM,iBAAiB,CAC7B,EAAE,QAAQ,UAAU,gBAAgB,kBAAkB,UAAU,GAChE,gBAAgB,CAAC,MACb;AACJ,eAAa;AAEb,MAAI,OAAO,WAAW,YAAY;AACjC,aAAS,gBAAgB,MAAM;AAAA,EAChC;AAEA,QAAM,QAAQ,CAAC;AACf,MAAI,MAAM,WAAW;AACrB,QAAM,YAAY,CAAC,OAAO,YAAY;AACrC,WAAO;AACP,UAAM,OACL,qBAAqB,QAAQ,gBAAgB,KAAK,IAAI;AACvD,UAAM,aAAa,OAAO,KAAK;AAC/B,QAAI,CAAC,YAAY;AAChB,iBAAW,SAAS,OAAO,QAAQ;AAClC,cAAM,EAAE,IAAI,MAAM,QAAQ,IAAI,aAAa,KAAK;AAEhD,YAAI,CAAC,MAAM,EAAE,GAAG;AACf,gBAAM,EAAE,IAAI,EAAE,IAAI,MAAM,SAAS,KAAK,CAAC,EAAE;AAAA,QAC1C;AACA,cAAM,EAAE,EAAE,IAAI,KAAK,GAAG;AAAA,MACvB;AAAA,IACD;AACA,QAAI,cAAc,gBAAgB;AACjC,cAAQ,QAAQ,KAAK;AAAA,IACtB;AAAA,EACD;AACA,QAAM,SAAS,sBAAsB,WAAW,aAAa;AAC7D,SAAO,SAAS,OAAO,EAAE,KAAK,aAAa,YAAY,MAAM;AAC7D,SAAO;AACR;AAEA,MAAM,eAAe,CAAC,UAAU;AAC/B,QAAM,UAAU,MAAM,WAAW;AAEjC,MAAI,KAAK,MAAM;AAEf,MAAI,OAAO,CAAC;AACZ,MAAI,MAAM,YAAY,gBAAgB;AACrC,UAAM,OAAO,OAAO,QAAQ,CAACA,WAAU;AACtC,YAAM,QAAQ,SAASA,MAAK;AAC5B,UAAI,MAAO,MAAK,KAAK,KAAK;AAAA,IAC3B,CAAC;AACD,WAAO,CAAC,GAAG,IAAI,IAAI,KAAK,KAAK,CAAC,CAAC;AAAA,EAChC,OAAO;AACN,SAAK,KAAK,SAAS,KAAK,CAAC;AAAA,EAC1B;AACA,MAAI,CAAC,MAAM,gBAAgB,KAAK,QAAQ;AACvC,UAAM,IAAI,KAAK,KAAK,GAAG,CAAC;AAAA,EACzB;AACA,SAAO,EAAE,IAAI,MAAM,QAAQ;AAC5B;AAEA,MAAM,WAAW,CAAC,UAAU;AAG3B,SACC,MAAM,OAAO,mBACb,MAAM,OAAO,sBACb,MAAM,aAAa,QAAQ,KAAK,EAAE;AAEpC;AAEA,IAAO,gBAAQ;", | ||
| "names": ["error"] | ||
| } |
+7
-14
| { | ||
| "name": "@datastream/validate", | ||
| "version": "0.0.42", | ||
| "description": "", | ||
| "version": "0.1.4", | ||
| "description": "JSON Schema validation transform streams using Ajv", | ||
| "type": "module", | ||
@@ -13,3 +13,3 @@ "engines": { | ||
| }, | ||
| "main": "./index.web.mjs", | ||
| "main": "./index.node.mjs", | ||
| "module": "./index.web.mjs", | ||
@@ -22,6 +22,2 @@ "exports": { | ||
| "default": "./index.node.mjs" | ||
| }, | ||
| "__require": { | ||
| "types": "./index.d.ts", | ||
| "default": "./index.node.cjs" | ||
| } | ||
@@ -42,3 +38,2 @@ }, | ||
| "*.mjs", | ||
| "*.cjs", | ||
| "*.map", | ||
@@ -64,3 +59,3 @@ "*.d.ts" | ||
| "url": "github:willfarrell/datastream", | ||
| "directory": "packages/digest" | ||
| "directory": "packages/validate" | ||
| }, | ||
@@ -72,7 +67,5 @@ "bugs": { | ||
| "dependencies": { | ||
| "@datastream/core": "0.0.42", | ||
| "@datastream/validate": "0.0.42", | ||
| "ajv-cmd": "0.8.1" | ||
| }, | ||
| "gitHead": "6ddc0fadabf5f3702a51aebae1fc6b252c6ae8d4" | ||
| "@datastream/core": "0.1.4", | ||
| "ajv-cmd": "0.8.2" | ||
| } | ||
| } |
No README
QualityPackage does not have a README. This may indicate a failed publish or a low quality package.
Found 1 instance in 1 package
18499
34.63%2
-33.33%7
40%164
17.14%1
-50%52
Infinity%+ Added
+ Added
+ Added
+ Added
+ Added
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
Updated
Updated