@effected/schemastore 0.18.0 → 0.19.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/InstanceValidator.js +106 -0
- package/index.d.ts +130 -1
- package/index.js +2 -1
- package/package.json +1 -1
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { Context, Effect, Layer, Schema } from "effect";
|
|
2
|
+
|
|
3
|
+
//#region src/InstanceValidator.ts
|
|
4
|
+
/**
|
|
5
|
+
* Indicates that the validation engine behind the {@link InstanceValidator}
|
|
6
|
+
* contract failed as a *mechanism* — it could not run at all.
|
|
7
|
+
*
|
|
8
|
+
* By convention the error channel is reserved for exactly that: an instance
|
|
9
|
+
* that fails the document is an {@link InstanceFinding} list (a value),
|
|
10
|
+
* never an error. A document the engine cannot compile also lands here —
|
|
11
|
+
* unlike {@link SchemaValidatorError}, whose subject IS the document, this
|
|
12
|
+
* contract's subject is the instance, so a document that yields no verdict
|
|
13
|
+
* means the engine could not run against that instance. Raised by
|
|
14
|
+
* implementations of {@link InstanceValidatorShape.validate}.
|
|
15
|
+
*
|
|
16
|
+
* @public
|
|
17
|
+
*/
|
|
18
|
+
var InstanceValidatorError = class extends Schema.TaggedError()("InstanceValidatorError", {
|
|
19
|
+
/** The underlying engine failure, preserved structurally. */
|
|
20
|
+
cause: Schema.Defect() }) {
|
|
21
|
+
get message() {
|
|
22
|
+
return "Instance validation engine failed";
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* One problem a validation engine found with an instance: a value in a
|
|
27
|
+
* report, never an error channel — the consumer decides what a finding
|
|
28
|
+
* gates. Structurally the same report {@link ValidationFinding} is for a
|
|
29
|
+
* schema document, but its pointer addresses the INSTANCE, so the two stay
|
|
30
|
+
* separate types: a caller that mixes them up is a compile error, not a
|
|
31
|
+
* silently misread pointer.
|
|
32
|
+
*
|
|
33
|
+
* @public
|
|
34
|
+
*/
|
|
35
|
+
var InstanceFinding = class extends Schema.Class("InstanceFinding")({
|
|
36
|
+
/** JSON pointer into the instance (`""` is the instance root). */
|
|
37
|
+
path: Schema.String,
|
|
38
|
+
/** Human-readable explanation from the engine. */
|
|
39
|
+
message: Schema.String,
|
|
40
|
+
/** The JSON Schema keyword the finding is about, when the engine names one. */
|
|
41
|
+
keyword: Schema.optionalKey(Schema.String)
|
|
42
|
+
}) {};
|
|
43
|
+
/** The default for an unstubbed {@link InstanceValidator.makeTest} member. */
|
|
44
|
+
const notStubbed = (method) => () => Effect.die(/* @__PURE__ */ new Error(`InstanceValidator.makeTest: ${method}() was called but not stubbed — no honest default exists for a test double; pass a \`${method}\` override.`));
|
|
45
|
+
/**
|
|
46
|
+
* The payload-against-document validation contract — the question
|
|
47
|
+
* {@link SchemaValidator} does not answer: not "is this document valid JSON
|
|
48
|
+
* Schema", but "does this instance conform to the published document it
|
|
49
|
+
* names in `$schema`". Decoding with the source Effect Schema is not a
|
|
50
|
+
* substitute: that proves the instance matches the CODE, not the committed
|
|
51
|
+
* document consumers actually fetch, and the two can drift.
|
|
52
|
+
*
|
|
53
|
+
* Like {@link SchemaValidator}, this package ships the contract and its
|
|
54
|
+
* doubles only: skip validation with {@link InstanceValidator.noop}, stub it
|
|
55
|
+
* with {@link InstanceValidator.layerTest}. The one real implementation is
|
|
56
|
+
* `@effected/schemastore-cli`'s `AjvInstanceValidator.layer` — the same ajv
|
|
57
|
+
* strict-mode setup `AjvValidator` gates documents with, pointed at an
|
|
58
|
+
* instance — which the `schemastore validate` command composes for you and
|
|
59
|
+
* which that package also exports for a program that drives the contract
|
|
60
|
+
* itself. Keeping the engine there keeps `ajv` out of every application
|
|
61
|
+
* that imports this package at runtime.
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* ```ts
|
|
65
|
+
* import { InstanceValidator } from "@effected/schemastore";
|
|
66
|
+
* import { Effect } from "effect";
|
|
67
|
+
*
|
|
68
|
+
* const program = Effect.gen(function* () {
|
|
69
|
+
* const validator = yield* InstanceValidator;
|
|
70
|
+
* return yield* validator.validate({ type: "object" }, { any: "payload" });
|
|
71
|
+
* });
|
|
72
|
+
*
|
|
73
|
+
* // Provide the engine at the edge — the CLI does this for you:
|
|
74
|
+
* // Effect.provide(program, AjvInstanceValidator.layer) (from @effected/schemastore-cli)
|
|
75
|
+
* Effect.runPromise(Effect.provide(program, InstanceValidator.noop));
|
|
76
|
+
* // => []
|
|
77
|
+
* ```
|
|
78
|
+
*
|
|
79
|
+
* @public
|
|
80
|
+
*/
|
|
81
|
+
var InstanceValidator = class InstanceValidator extends Context.Service()("@effected/schemastore/InstanceValidator") {
|
|
82
|
+
/**
|
|
83
|
+
* No-op: `validate` always succeeds with no findings, never consulting an
|
|
84
|
+
* engine. A pure `Layer.succeed`, bound to a const so the layer memoizes
|
|
85
|
+
* by reference. Use it to switch validation off deliberately — for the
|
|
86
|
+
* real engine, provide `AjvInstanceValidator.layer` from
|
|
87
|
+
* `@effected/schemastore-cli`.
|
|
88
|
+
*/
|
|
89
|
+
static noop = Layer.succeed(InstanceValidator, { validate: () => Effect.succeed([]) });
|
|
90
|
+
/**
|
|
91
|
+
* An in-memory double: stub only the members the test exercises; every
|
|
92
|
+
* other member **dies** with a defect naming itself. No member has an
|
|
93
|
+
* honest default — a fabricated clean pass would leak into consumer
|
|
94
|
+
* logic as fact (use {@link InstanceValidator.noop} when a test genuinely
|
|
95
|
+
* wants an always-clean validator).
|
|
96
|
+
*/
|
|
97
|
+
static makeTest = (overrides = {}) => ({
|
|
98
|
+
validate: notStubbed("validate"),
|
|
99
|
+
...overrides
|
|
100
|
+
});
|
|
101
|
+
/** {@link InstanceValidator.makeTest} behind `Layer.succeed`. */
|
|
102
|
+
static layerTest = (overrides = {}) => Layer.succeed(InstanceValidator, InstanceValidator.makeTest(overrides));
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
//#endregion
|
|
106
|
+
export { InstanceFinding, InstanceValidator, InstanceValidatorError };
|
package/index.d.ts
CHANGED
|
@@ -1173,6 +1173,135 @@ export declare class HostedSchema extends HostedSchema_base {
|
|
|
1173
1173
|
private parseLabel;
|
|
1174
1174
|
}
|
|
1175
1175
|
//#endregion
|
|
1176
|
+
//#region src/InstanceValidator.d.ts
|
|
1177
|
+
declare const InstanceValidatorError_base: Schema.Class<InstanceValidatorError, Schema.TaggedStruct<"InstanceValidatorError", {
|
|
1178
|
+
/** The underlying engine failure, preserved structurally. */
|
|
1179
|
+
readonly cause: Schema.Defect;
|
|
1180
|
+
}>, import("effect/Cause").YieldableError>;
|
|
1181
|
+
/**
|
|
1182
|
+
* Indicates that the validation engine behind the {@link InstanceValidator}
|
|
1183
|
+
* contract failed as a *mechanism* — it could not run at all.
|
|
1184
|
+
*
|
|
1185
|
+
* By convention the error channel is reserved for exactly that: an instance
|
|
1186
|
+
* that fails the document is an {@link InstanceFinding} list (a value),
|
|
1187
|
+
* never an error. A document the engine cannot compile also lands here —
|
|
1188
|
+
* unlike {@link SchemaValidatorError}, whose subject IS the document, this
|
|
1189
|
+
* contract's subject is the instance, so a document that yields no verdict
|
|
1190
|
+
* means the engine could not run against that instance. Raised by
|
|
1191
|
+
* implementations of {@link InstanceValidatorShape.validate}.
|
|
1192
|
+
*
|
|
1193
|
+
* @public
|
|
1194
|
+
*/
|
|
1195
|
+
export declare class InstanceValidatorError extends InstanceValidatorError_base {
|
|
1196
|
+
get message(): string;
|
|
1197
|
+
}
|
|
1198
|
+
declare const InstanceFinding_base: Schema.Class<InstanceFinding, Schema.Struct<{
|
|
1199
|
+
/** JSON pointer into the instance (`""` is the instance root). */
|
|
1200
|
+
readonly path: Schema.String;
|
|
1201
|
+
/** Human-readable explanation from the engine. */
|
|
1202
|
+
readonly message: Schema.String;
|
|
1203
|
+
/** The JSON Schema keyword the finding is about, when the engine names one. */
|
|
1204
|
+
readonly keyword: Schema.optionalKey<Schema.String>;
|
|
1205
|
+
}>, {}>;
|
|
1206
|
+
/**
|
|
1207
|
+
* One problem a validation engine found with an instance: a value in a
|
|
1208
|
+
* report, never an error channel — the consumer decides what a finding
|
|
1209
|
+
* gates. Structurally the same report {@link ValidationFinding} is for a
|
|
1210
|
+
* schema document, but its pointer addresses the INSTANCE, so the two stay
|
|
1211
|
+
* separate types: a caller that mixes them up is a compile error, not a
|
|
1212
|
+
* silently misread pointer.
|
|
1213
|
+
*
|
|
1214
|
+
* @public
|
|
1215
|
+
*/
|
|
1216
|
+
export declare class InstanceFinding extends InstanceFinding_base {}
|
|
1217
|
+
/**
|
|
1218
|
+
* Options for {@link InstanceValidatorShape.validate}.
|
|
1219
|
+
*
|
|
1220
|
+
* @public
|
|
1221
|
+
*/
|
|
1222
|
+
interface InstanceValidatorOptions {
|
|
1223
|
+
/**
|
|
1224
|
+
* Whether the engine runs its strictest mode (ajv `strict: true` — the
|
|
1225
|
+
* SchemaStore default gate) when compiling the document. Defaults to
|
|
1226
|
+
* `true`; implementations treat an omitted value as strict.
|
|
1227
|
+
*/
|
|
1228
|
+
readonly strict?: boolean;
|
|
1229
|
+
}
|
|
1230
|
+
/**
|
|
1231
|
+
* The shape of the {@link InstanceValidator} service — what an implementation
|
|
1232
|
+
* provides.
|
|
1233
|
+
*
|
|
1234
|
+
* @public
|
|
1235
|
+
*/
|
|
1236
|
+
interface InstanceValidatorShape {
|
|
1237
|
+
/**
|
|
1238
|
+
* Validates an arbitrary JSON instance against a schema document with a
|
|
1239
|
+
* real JSON Schema engine. An empty array is a clean pass; an instance
|
|
1240
|
+
* the document rejects answers findings as values, each carrying a JSON
|
|
1241
|
+
* pointer into the instance. The error channel is reserved for the
|
|
1242
|
+
* engine failing as a mechanism ({@link InstanceValidatorError}),
|
|
1243
|
+
* including a document the engine cannot compile.
|
|
1244
|
+
*/
|
|
1245
|
+
readonly validate: (document: Record<string, unknown>, instance: unknown, options?: InstanceValidatorOptions) => Effect.Effect<ReadonlyArray<InstanceFinding>, InstanceValidatorError>;
|
|
1246
|
+
}
|
|
1247
|
+
declare const InstanceValidator_base: Context.ServiceClass<InstanceValidator, "@effected/schemastore/InstanceValidator", InstanceValidatorShape>;
|
|
1248
|
+
/**
|
|
1249
|
+
* The payload-against-document validation contract — the question
|
|
1250
|
+
* {@link SchemaValidator} does not answer: not "is this document valid JSON
|
|
1251
|
+
* Schema", but "does this instance conform to the published document it
|
|
1252
|
+
* names in `$schema`". Decoding with the source Effect Schema is not a
|
|
1253
|
+
* substitute: that proves the instance matches the CODE, not the committed
|
|
1254
|
+
* document consumers actually fetch, and the two can drift.
|
|
1255
|
+
*
|
|
1256
|
+
* Like {@link SchemaValidator}, this package ships the contract and its
|
|
1257
|
+
* doubles only: skip validation with {@link InstanceValidator.noop}, stub it
|
|
1258
|
+
* with {@link InstanceValidator.layerTest}. The one real implementation is
|
|
1259
|
+
* `@effected/schemastore-cli`'s `AjvInstanceValidator.layer` — the same ajv
|
|
1260
|
+
* strict-mode setup `AjvValidator` gates documents with, pointed at an
|
|
1261
|
+
* instance — which the `schemastore validate` command composes for you and
|
|
1262
|
+
* which that package also exports for a program that drives the contract
|
|
1263
|
+
* itself. Keeping the engine there keeps `ajv` out of every application
|
|
1264
|
+
* that imports this package at runtime.
|
|
1265
|
+
*
|
|
1266
|
+
* @example
|
|
1267
|
+
* ```ts
|
|
1268
|
+
* import { InstanceValidator } from "@effected/schemastore";
|
|
1269
|
+
* import { Effect } from "effect";
|
|
1270
|
+
*
|
|
1271
|
+
* const program = Effect.gen(function* () {
|
|
1272
|
+
* const validator = yield* InstanceValidator;
|
|
1273
|
+
* return yield* validator.validate({ type: "object" }, { any: "payload" });
|
|
1274
|
+
* });
|
|
1275
|
+
*
|
|
1276
|
+
* // Provide the engine at the edge — the CLI does this for you:
|
|
1277
|
+
* // Effect.provide(program, AjvInstanceValidator.layer) (from @effected/schemastore-cli)
|
|
1278
|
+
* Effect.runPromise(Effect.provide(program, InstanceValidator.noop));
|
|
1279
|
+
* // => []
|
|
1280
|
+
* ```
|
|
1281
|
+
*
|
|
1282
|
+
* @public
|
|
1283
|
+
*/
|
|
1284
|
+
export declare class InstanceValidator extends InstanceValidator_base {
|
|
1285
|
+
/**
|
|
1286
|
+
* No-op: `validate` always succeeds with no findings, never consulting an
|
|
1287
|
+
* engine. A pure `Layer.succeed`, bound to a const so the layer memoizes
|
|
1288
|
+
* by reference. Use it to switch validation off deliberately — for the
|
|
1289
|
+
* real engine, provide `AjvInstanceValidator.layer` from
|
|
1290
|
+
* `@effected/schemastore-cli`.
|
|
1291
|
+
*/
|
|
1292
|
+
static readonly noop: Layer.Layer<InstanceValidator>;
|
|
1293
|
+
/**
|
|
1294
|
+
* An in-memory double: stub only the members the test exercises; every
|
|
1295
|
+
* other member **dies** with a defect naming itself. No member has an
|
|
1296
|
+
* honest default — a fabricated clean pass would leak into consumer
|
|
1297
|
+
* logic as fact (use {@link InstanceValidator.noop} when a test genuinely
|
|
1298
|
+
* wants an always-clean validator).
|
|
1299
|
+
*/
|
|
1300
|
+
static readonly makeTest: (overrides?: Partial<InstanceValidatorShape>) => InstanceValidatorShape;
|
|
1301
|
+
/** {@link InstanceValidator.makeTest} behind `Layer.succeed`. */
|
|
1302
|
+
static readonly layerTest: (overrides?: Partial<InstanceValidatorShape>) => Layer.Layer<InstanceValidator>;
|
|
1303
|
+
}
|
|
1304
|
+
//#endregion
|
|
1176
1305
|
//#region src/KeywordFamilies.d.ts
|
|
1177
1306
|
/**
|
|
1178
1307
|
* The one owner of the declared non-standard keyword families, in two
|
|
@@ -2057,5 +2186,5 @@ export declare const defineConfig: (input: SchemastoreConfigInput) => Schemastor
|
|
|
2057
2186
|
*/
|
|
2058
2187
|
export declare const isSchemastoreConfig: (value: unknown) => value is SchemastoreConfig;
|
|
2059
2188
|
//#endregion
|
|
2060
|
-
export type { CanonicalJsonError, CanonicalJsonOptions, CatalogInput, CatalogUrls, CheckResult, ContractChangePolicy, CustomHostedSchemaInput, DriftOptions, DriftTolerance, DriftVerdict, FrozenVersion, GitHubHostedSchemaInput, HostedSchemaVersionsInput, OnDrift, PipelineCheckResult, PipelineResult, ResolvedSchema, SchemaChange, SchemaEntryInput, SchemaFileShape, SchemaLayout, SchemaPipelineOptions, SchemaValidatorOptions, SchemaValidatorShape, SchemaWriteOptions, SchemastoreConfig, SchemastoreConfigInput, StoreDocumentOptions, WriteChange, WriteOutcome, WriteResult };
|
|
2189
|
+
export type { CanonicalJsonError, CanonicalJsonOptions, CatalogInput, CatalogUrls, CheckResult, ContractChangePolicy, CustomHostedSchemaInput, DriftOptions, DriftTolerance, DriftVerdict, FrozenVersion, GitHubHostedSchemaInput, HostedSchemaVersionsInput, InstanceValidatorOptions, InstanceValidatorShape, OnDrift, PipelineCheckResult, PipelineResult, ResolvedSchema, SchemaChange, SchemaEntryInput, SchemaFileShape, SchemaLayout, SchemaPipelineOptions, SchemaValidatorOptions, SchemaValidatorShape, SchemaWriteOptions, SchemastoreConfig, SchemastoreConfigInput, StoreDocumentOptions, WriteChange, WriteOutcome, WriteResult };
|
|
2061
2190
|
//# sourceMappingURL=index.d.ts.map
|
package/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import { DocumentDiff } from "./DocumentDiff.js";
|
|
|
6
6
|
import { DocumentLint, DocumentLintFinding } from "./DocumentLint.js";
|
|
7
7
|
import { DriftPolicy } from "./DriftPolicy.js";
|
|
8
8
|
import { HostedSchema, SCHEMASTORE_CATALOG_BASE, SCHEMASTORE_ID_BASE } from "./HostedSchema.js";
|
|
9
|
+
import { InstanceFinding, InstanceValidator, InstanceValidatorError } from "./InstanceValidator.js";
|
|
9
10
|
import { SchemaFile, SchemaFileNotFoundError, SchemaFileReadError, SchemaFileWriteError } from "./SchemaFile.js";
|
|
10
11
|
import { SchemaValidator, SchemaValidatorError, ValidationFinding } from "./SchemaValidator.js";
|
|
11
12
|
import { DRAFT_07_META_SCHEMA, SchemaConversionError, StoreDocument, UndeclaredAnnotationKeyError } from "./StoreDocument.js";
|
|
@@ -13,4 +14,4 @@ import { ContractChangeTarget, PipelineFinding, SchemaContractChangeError, Schem
|
|
|
13
14
|
import { SchemaTarget } from "./SchemaTarget.js";
|
|
14
15
|
import { defineConfig, isSchemastoreConfig } from "./SchemastoreConfig.js";
|
|
15
16
|
|
|
16
|
-
export { CanonicalJson, CatalogEntry, CatalogLintFinding, ContractChangeTarget, DRAFT_07_META_SCHEMA, DocumentDiff, DocumentLint, DocumentLintFinding, DriftPolicy, HostedSchema, InvalidSchemaVersionError, JsonDepthExceededError, KeywordFamilies, NonJsonValueError, PipelineFinding, SCHEMASTORE_CATALOG_BASE, SCHEMASTORE_ID_BASE, SchemaContractChangeError, SchemaConversionError, SchemaFile, SchemaFileNotFoundError, SchemaFileReadError, SchemaFileWriteError, SchemaGateError, SchemaPipeline, SchemaTarget, SchemaValidator, SchemaValidatorError, SchemaVersion, SchemaVersioning, StoreDocument, UndeclaredAnnotationKeyError, ValidationFinding, defineConfig, isSchemastoreConfig };
|
|
17
|
+
export { CanonicalJson, CatalogEntry, CatalogLintFinding, ContractChangeTarget, DRAFT_07_META_SCHEMA, DocumentDiff, DocumentLint, DocumentLintFinding, DriftPolicy, HostedSchema, InstanceFinding, InstanceValidator, InstanceValidatorError, InvalidSchemaVersionError, JsonDepthExceededError, KeywordFamilies, NonJsonValueError, PipelineFinding, SCHEMASTORE_CATALOG_BASE, SCHEMASTORE_ID_BASE, SchemaContractChangeError, SchemaConversionError, SchemaFile, SchemaFileNotFoundError, SchemaFileReadError, SchemaFileWriteError, SchemaGateError, SchemaPipeline, SchemaTarget, SchemaValidator, SchemaValidatorError, SchemaVersion, SchemaVersioning, StoreDocument, UndeclaredAnnotationKeyError, ValidationFinding, defineConfig, isSchemastoreConfig };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@effected/schemastore",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.19.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Build, validate, version and publish SchemaStore-shaped Draft-07 JSON Schema documents from Effect Schema sources: document assembly, ajv strict-mode validation, structural lints, catalog entries, canonical JSON and a content-comparing emit pipeline.",
|
|
6
6
|
"keywords": [
|