@effected/schemastore 0.4.0 → 0.5.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/DocumentLint.js +2 -2
- package/KeywordFamilies.js +47 -7
- package/README.md +32 -5
- package/SchemaPipeline.js +91 -6
- package/SchemaValidator.js +8 -5
- package/SchemaVersioning.js +56 -0
- package/index.d.ts +632 -427
- package/index.js +2 -2
- package/package.json +2 -2
- package/tsdoc-metadata.json +1 -1
package/index.d.ts
CHANGED
|
@@ -165,201 +165,6 @@ declare class CanonicalJson {
|
|
|
165
165
|
static readonly serialize: (value: unknown, options?: CanonicalJsonOptions | undefined) => Effect.Effect<string, CanonicalJsonError, never>;
|
|
166
166
|
}
|
|
167
167
|
//#endregion
|
|
168
|
-
//#region src/SchemaVersioning.d.ts
|
|
169
|
-
declare const InvalidSchemaVersionError_base: Schema.Class<InvalidSchemaVersionError, Schema.TaggedStruct<"InvalidSchemaVersionError", {
|
|
170
|
-
/** The raw input string that failed to parse. */
|
|
171
|
-
readonly input: Schema.String;
|
|
172
|
-
}>, import("effect/Cause").YieldableError>;
|
|
173
|
-
/**
|
|
174
|
-
* Indicates that a string is not a valid SchemaStore version label.
|
|
175
|
-
*
|
|
176
|
-
* Raised by {@link SchemaVersioning.parse}.
|
|
177
|
-
*
|
|
178
|
-
* @public
|
|
179
|
-
*/
|
|
180
|
-
declare class InvalidSchemaVersionError extends InvalidSchemaVersionError_base {
|
|
181
|
-
get message(): string;
|
|
182
|
-
}
|
|
183
|
-
/**
|
|
184
|
-
* A schema version label: a branded string holding a **full three-component
|
|
185
|
-
* SemVer** — `major.minor.patch` with an optional prerelease, validated by
|
|
186
|
-
* `@effected/semver` itself. Build metadata is rejected (see below).
|
|
187
|
-
*
|
|
188
|
-
* `1.2` and `1` are NOT accepted, though SchemaStore's own corpus uses such
|
|
189
|
-
* labels: requiring all three components makes a label unambiguous to split
|
|
190
|
-
* back out of `<name>-<version>.json` or its URL, which is what consumers
|
|
191
|
-
* do with it. The file-name convention around the label stays SchemaStore's.
|
|
192
|
-
*
|
|
193
|
-
* The label round-trips verbatim into file names and catalog `versions`
|
|
194
|
-
* keys; ordering parses it directly (see {@link SchemaVersioning.Order}).
|
|
195
|
-
*
|
|
196
|
-
* @public
|
|
197
|
-
*/
|
|
198
|
-
declare const SchemaVersion: Schema.brand<Schema.String, "SchemaVersion">;
|
|
199
|
-
/**
|
|
200
|
-
* The type of a validated SchemaStore version label.
|
|
201
|
-
*
|
|
202
|
-
* @public
|
|
203
|
-
*/
|
|
204
|
-
type SchemaVersion = typeof SchemaVersion.Type;
|
|
205
|
-
/**
|
|
206
|
-
* The `url`/`versions` half of a catalog entry, as assembled by
|
|
207
|
-
* {@link SchemaVersioning.catalogUrls}.
|
|
208
|
-
*
|
|
209
|
-
* @public
|
|
210
|
-
*/
|
|
211
|
-
interface CatalogUrls {
|
|
212
|
-
/** The catalog `url` — the unversioned file, or the latest versioned file. */
|
|
213
|
-
readonly url: string;
|
|
214
|
-
/**
|
|
215
|
-
* The versioned catalog's `versions` map (label → url), inserted — and,
|
|
216
|
-
* since a three-component label can never be integer-like, enumerated
|
|
217
|
-
* and serialized — in ascending version order.
|
|
218
|
-
*/
|
|
219
|
-
readonly versions?: Readonly<Record<string, string>>;
|
|
220
|
-
}
|
|
221
|
-
/**
|
|
222
|
-
* Both SchemaStore catalog modes as pure derivations: unversioned (a plain
|
|
223
|
-
* `name.json` file, `url` only) and versioned (`name-<version>.json` files
|
|
224
|
-
* — SchemaStore's own suffix convention — a `versions` map, and `url`
|
|
225
|
-
* pointing at the latest version).
|
|
226
|
-
*
|
|
227
|
-
* Version labels are full three-component SemVer, so ordering is plain
|
|
228
|
-
* SemVer precedence: `1.10.0` above `1.9.0`, `2.0.0-beta` below `2.0.0`.
|
|
229
|
-
*
|
|
230
|
-
* @public
|
|
231
|
-
*/
|
|
232
|
-
declare class SchemaVersioning {
|
|
233
|
-
private constructor();
|
|
234
|
-
/**
|
|
235
|
-
* Parses a version label. Pure and synchronous — the primitive form;
|
|
236
|
-
* {@link SchemaVersioning.parse} is the same check behind a span.
|
|
237
|
-
*/
|
|
238
|
-
static parseResult(input: string): Result.Result<SchemaVersion, InvalidSchemaVersionError>;
|
|
239
|
-
/**
|
|
240
|
-
* Effect form of {@link SchemaVersioning.parseResult}, adding only the
|
|
241
|
-
* `SchemaVersioning.parse` span. Defined in terms of the `Result`
|
|
242
|
-
* primitive — synchronous callers can use that variant directly.
|
|
243
|
-
*/
|
|
244
|
-
static readonly parse: (input: string) => Effect.Effect<string & import("effect/Brand").Brand<"SchemaVersion">, InvalidSchemaVersionError, never>;
|
|
245
|
-
/**
|
|
246
|
-
* `Order` instance over version labels: plain SemVer precedence.
|
|
247
|
-
* `1.10.0` sorts above `1.9.0` (numeric, not lexical) and `2.0.0-beta`
|
|
248
|
-
* below `2.0.0` (prerelease precedence).
|
|
249
|
-
*/
|
|
250
|
-
static readonly Order: Order.Order<SchemaVersion>;
|
|
251
|
-
/**
|
|
252
|
-
* The highest version label by {@link SchemaVersioning.Order}, or
|
|
253
|
-
* `Option.none()` for an empty collection.
|
|
254
|
-
*/
|
|
255
|
-
static latest(versions: ReadonlyArray<SchemaVersion>): Option.Option<SchemaVersion>;
|
|
256
|
-
/**
|
|
257
|
-
* Derives the schema file name for a catalog name: `name.json`
|
|
258
|
-
* unversioned, `name-<version>.json` versioned.
|
|
259
|
-
*
|
|
260
|
-
* The name must be a simple file base name (no separators, no
|
|
261
|
-
* whitespace); anything else is a wiring mistake and throws.
|
|
262
|
-
*/
|
|
263
|
-
static fileName(name: string, version?: SchemaVersion): string;
|
|
264
|
-
/**
|
|
265
|
-
* The canonical URL a schema file is hosted at: `baseUrl` joined with
|
|
266
|
-
* {@link SchemaVersioning.fileName}.
|
|
267
|
-
*/
|
|
268
|
-
static schemaUrl(baseUrl: string, name: string, version?: SchemaVersion): string;
|
|
269
|
-
/**
|
|
270
|
-
* Assembles the `url`/`versions` half of a catalog entry.
|
|
271
|
-
*
|
|
272
|
-
* Omitting `versions` selects the unversioned mode (`url` only,
|
|
273
|
-
* pointing at the plain `name.json`). Providing them selects the
|
|
274
|
-
* versioned mode: the `versions` map carries every label, and `url`
|
|
275
|
-
* points at the latest version's file. An **empty** `versions` array is
|
|
276
|
-
* a contradiction (versioned mode with no versions) and throws — pass
|
|
277
|
-
* `undefined` for the unversioned mode.
|
|
278
|
-
*
|
|
279
|
-
* Labels are inserted in ascending {@link SchemaVersioning.Order} and
|
|
280
|
-
* stay that way on serialization. Requiring three components is what
|
|
281
|
-
* buys this: JavaScript enumerates array-index-like keys first, so the
|
|
282
|
-
* old grammar's bare-major label (`"2"`) jumped ahead of every dotted
|
|
283
|
-
* one regardless of insertion order. No SemVer label is integer-like,
|
|
284
|
-
* so that hazard is gone. Deriving ordering from the labels themselves
|
|
285
|
-
* (as {@link SchemaVersioning.latest} does) is still the robust read.
|
|
286
|
-
*/
|
|
287
|
-
static catalogUrls(options: {
|
|
288
|
-
readonly baseUrl: string;
|
|
289
|
-
readonly name: string;
|
|
290
|
-
readonly versions?: ReadonlyArray<SchemaVersion>;
|
|
291
|
-
}): CatalogUrls;
|
|
292
|
-
}
|
|
293
|
-
//#endregion
|
|
294
|
-
//#region src/CatalogEntry.d.ts
|
|
295
|
-
declare const CatalogLintFinding_base: Schema.Class<CatalogLintFinding, Schema.Struct<{
|
|
296
|
-
/** Which hygiene check fired. */
|
|
297
|
-
readonly check: Schema.Literals<readonly ["GenericFileMatch", "ComplexFileMatch"]>;
|
|
298
|
-
/** The `fileMatch` pattern the finding is about. */
|
|
299
|
-
readonly pattern: Schema.String;
|
|
300
|
-
/** Human-readable explanation with the SchemaStore rationale. */
|
|
301
|
-
readonly message: Schema.String;
|
|
302
|
-
}>, {}>;
|
|
303
|
-
/**
|
|
304
|
-
* A fileMatch hygiene finding: a value in a lint report, not an error —
|
|
305
|
-
* SchemaStore reviewers reject entries over these, so surfacing them
|
|
306
|
-
* locally is the point, but a warned entry is still a valid entry.
|
|
307
|
-
*
|
|
308
|
-
* @public
|
|
309
|
-
*/
|
|
310
|
-
declare class CatalogLintFinding extends CatalogLintFinding_base {}
|
|
311
|
-
declare const CatalogEntry_base: Schema.Class<CatalogEntry, Schema.Struct<{
|
|
312
|
-
/** The schema's display name in the catalog. */
|
|
313
|
-
readonly name: Schema.String;
|
|
314
|
-
/** The catalog description. */
|
|
315
|
-
readonly description: Schema.String;
|
|
316
|
-
/** Glob patterns editors match files against. */
|
|
317
|
-
readonly fileMatch: Schema.$Array<Schema.String>;
|
|
318
|
-
/** The schema URL — the unversioned file, or the latest version. */
|
|
319
|
-
readonly url: Schema.String;
|
|
320
|
-
/**
|
|
321
|
-
* Versioned mode only: label → schema URL. Inserted ascending, but key
|
|
322
|
-
* order is not a contract — bare-major labels enumerate first (see
|
|
323
|
-
* `SchemaVersioning.catalogUrls`); derive ordering from the labels.
|
|
324
|
-
*/
|
|
325
|
-
readonly versions: Schema.optionalKey<Schema.$Record<Schema.String, Schema.String>>;
|
|
326
|
-
}>, {}>;
|
|
327
|
-
/**
|
|
328
|
-
* A SchemaStore `catalog.json` entry: the class is the schema, so decoding
|
|
329
|
-
* an existing entry and encoding one for submission are the same artifact.
|
|
330
|
-
* `versions` is present only for versioned catalogs
|
|
331
|
-
* ({@link SchemaVersioning.catalogUrls} assembles both modes).
|
|
332
|
-
*
|
|
333
|
-
* @public
|
|
334
|
-
*/
|
|
335
|
-
declare class CatalogEntry extends CatalogEntry_base {
|
|
336
|
-
/**
|
|
337
|
-
* Assembles an entry from a catalog identity plus
|
|
338
|
-
* {@link SchemaVersioning.catalogUrls}' inputs: pass `versions` for the
|
|
339
|
-
* versioned mode (the `versions` map and latest-pointing `url` are
|
|
340
|
-
* derived), omit it for the unversioned mode.
|
|
341
|
-
*/
|
|
342
|
-
static assemble(options: {
|
|
343
|
-
readonly name: string;
|
|
344
|
-
readonly description: string;
|
|
345
|
-
readonly fileMatch: ReadonlyArray<string>;
|
|
346
|
-
readonly baseUrl: string;
|
|
347
|
-
readonly fileBaseName?: string;
|
|
348
|
-
readonly versions?: ReadonlyArray<SchemaVersion>;
|
|
349
|
-
}): CatalogEntry;
|
|
350
|
-
/**
|
|
351
|
-
* The fileMatch hygiene lint over this entry's patterns — pure shape
|
|
352
|
-
* analysis (no glob engine): generic patterns SchemaStore rejects and
|
|
353
|
-
* complex constructs it asks contributors to expand.
|
|
354
|
-
*/
|
|
355
|
-
lint(): ReadonlyArray<CatalogLintFinding>;
|
|
356
|
-
/**
|
|
357
|
-
* {@link CatalogEntry.lint} over a bare pattern list, for callers
|
|
358
|
-
* checking patterns before an entry exists.
|
|
359
|
-
*/
|
|
360
|
-
static lintFileMatch(patterns: ReadonlyArray<string>): ReadonlyArray<CatalogLintFinding>;
|
|
361
|
-
}
|
|
362
|
-
//#endregion
|
|
363
168
|
//#region src/DocumentDiff.d.ts
|
|
364
169
|
/**
|
|
365
170
|
* What differs between two schema documents:
|
|
@@ -571,7 +376,456 @@ declare class StoreDocument extends StoreDocument_base {
|
|
|
571
376
|
* {@link CanonicalJson.serializeResult} — one serializer, so the
|
|
572
377
|
* document and any consumer-serialized value cannot drift.
|
|
573
378
|
*/
|
|
574
|
-
serializeResult(options?: CanonicalJsonOptions): Result.Result<string, CanonicalJsonError>;
|
|
379
|
+
serializeResult(options?: CanonicalJsonOptions): Result.Result<string, CanonicalJsonError>;
|
|
380
|
+
}
|
|
381
|
+
//#endregion
|
|
382
|
+
//#region src/SchemaFile.d.ts
|
|
383
|
+
declare const SchemaFileReadError_base: Schema.Class<SchemaFileReadError, Schema.TaggedStruct<"SchemaFileReadError", {
|
|
384
|
+
/** The path that could not be read. */
|
|
385
|
+
readonly path: Schema.String;
|
|
386
|
+
/** The underlying filesystem failure, preserved structurally. */
|
|
387
|
+
readonly cause: Schema.Defect;
|
|
388
|
+
}>, import("effect/Cause").YieldableError>;
|
|
389
|
+
/**
|
|
390
|
+
* Indicates that a schema file could not be read from the filesystem (a
|
|
391
|
+
* filesystem error other than not-found).
|
|
392
|
+
*
|
|
393
|
+
* @public
|
|
394
|
+
*/
|
|
395
|
+
declare class SchemaFileReadError extends SchemaFileReadError_base {
|
|
396
|
+
get message(): string;
|
|
397
|
+
}
|
|
398
|
+
declare const SchemaFileNotFoundError_base: Schema.Class<SchemaFileNotFoundError, Schema.TaggedStruct<"SchemaFileNotFoundError", {
|
|
399
|
+
/** The path where the schema file was expected. */
|
|
400
|
+
readonly path: Schema.String;
|
|
401
|
+
}>, import("effect/Cause").YieldableError>;
|
|
402
|
+
/**
|
|
403
|
+
* Indicates that no schema file exists at the expected path. Carries its
|
|
404
|
+
* own tag for `catchTag` routing.
|
|
405
|
+
*
|
|
406
|
+
* @public
|
|
407
|
+
*/
|
|
408
|
+
declare class SchemaFileNotFoundError extends SchemaFileNotFoundError_base {
|
|
409
|
+
get message(): string;
|
|
410
|
+
}
|
|
411
|
+
declare const SchemaFileWriteError_base: Schema.Class<SchemaFileWriteError, Schema.TaggedStruct<"SchemaFileWriteError", {
|
|
412
|
+
/** The path that could not be written. */
|
|
413
|
+
readonly path: Schema.String;
|
|
414
|
+
/** The underlying filesystem failure, preserved structurally. */
|
|
415
|
+
readonly cause: Schema.Defect;
|
|
416
|
+
}>, import("effect/Cause").YieldableError>;
|
|
417
|
+
/**
|
|
418
|
+
* Indicates that a schema file could not be written to the filesystem.
|
|
419
|
+
* Narrowed to the filesystem failure only — a serialization failure
|
|
420
|
+
* surfaces as its own `CanonicalJsonError`, never wrapped here.
|
|
421
|
+
*
|
|
422
|
+
* @public
|
|
423
|
+
*/
|
|
424
|
+
declare class SchemaFileWriteError extends SchemaFileWriteError_base {
|
|
425
|
+
get message(): string;
|
|
426
|
+
}
|
|
427
|
+
/**
|
|
428
|
+
* What {@link SchemaFileShape.write} did to the filesystem: `"written"`
|
|
429
|
+
* when it wrote, `"unchanged"` when it left the file alone — reported as a
|
|
430
|
+
* value so the caller decides what to surface, never a log.
|
|
431
|
+
*
|
|
432
|
+
* @public
|
|
433
|
+
*/
|
|
434
|
+
type WriteOutcome = "written" | "unchanged";
|
|
435
|
+
/**
|
|
436
|
+
* How the document being written relates to what was already on disk:
|
|
437
|
+
* {@link SchemaChange} plus `"created"` for a file that did not exist, so
|
|
438
|
+
* there was nothing to compare against.
|
|
439
|
+
*
|
|
440
|
+
* @public
|
|
441
|
+
*/
|
|
442
|
+
type WriteChange = SchemaChange | "created";
|
|
443
|
+
/**
|
|
444
|
+
* The result of {@link SchemaFileShape.write}: what happened to the file,
|
|
445
|
+
* and what the difference MEANT.
|
|
446
|
+
*
|
|
447
|
+
* The two are independent on purpose. `change` answers the versioning
|
|
448
|
+
* question — `"annotations"` means only prose and editor affordances moved,
|
|
449
|
+
* so the document replaces its predecessor transparently and needs no new
|
|
450
|
+
* {@link SchemaVersioning} version, while `"contract"` means an assertion
|
|
451
|
+
* keyword moved and a consumer's document valid yesterday may be invalid
|
|
452
|
+
* today. `outcome` answers only whether bytes were written, which under
|
|
453
|
+
* `compare: "bytes"` can be `"written"` even when `change` is `"none"`.
|
|
454
|
+
*
|
|
455
|
+
* @public
|
|
456
|
+
*/
|
|
457
|
+
interface WriteResult {
|
|
458
|
+
/**
|
|
459
|
+
* Whether the file was written. **This is the authoritative answer to
|
|
460
|
+
* "did the filesystem get touched"** — always, under either `compare`
|
|
461
|
+
* mode. Do not infer it from `change`: under `compare: "bytes"` a
|
|
462
|
+
* `change` of `"none"` still writes.
|
|
463
|
+
*/
|
|
464
|
+
readonly outcome: WriteOutcome;
|
|
465
|
+
/** What differs between the previous content and the new document. */
|
|
466
|
+
readonly change: WriteChange;
|
|
467
|
+
}
|
|
468
|
+
/**
|
|
469
|
+
* The result of {@link SchemaFileShape.check}: the same two answers
|
|
470
|
+
* {@link WriteResult} carries, for a call that touched nothing.
|
|
471
|
+
*
|
|
472
|
+
* `wouldWrite` is `outcome`'s counterpart — it honors `compare`, so it
|
|
473
|
+
* answers "would `write` do anything with these same options", which
|
|
474
|
+
* `change` alone cannot under `compare: "bytes"`.
|
|
475
|
+
*
|
|
476
|
+
* @public
|
|
477
|
+
*/
|
|
478
|
+
interface CheckResult {
|
|
479
|
+
/** Whether a `write` with the same options would touch the file. */
|
|
480
|
+
readonly wouldWrite: boolean;
|
|
481
|
+
/** What differs between the on-disk content and the new document. */
|
|
482
|
+
readonly change: WriteChange;
|
|
483
|
+
}
|
|
484
|
+
/**
|
|
485
|
+
* Options for {@link SchemaFileShape.write} and
|
|
486
|
+
* {@link SchemaFileShape.check}: the {@link CanonicalJsonOptions} the
|
|
487
|
+
* document serializes under, plus how `write` decides whether to touch the
|
|
488
|
+
* file.
|
|
489
|
+
*
|
|
490
|
+
* @public
|
|
491
|
+
*/
|
|
492
|
+
interface SchemaWriteOptions extends CanonicalJsonOptions {
|
|
493
|
+
/**
|
|
494
|
+
* How `write` decides the file needs rewriting:
|
|
495
|
+
*
|
|
496
|
+
* - `"value"` (the default) — compare the parsed content. Immune to any
|
|
497
|
+
* other tool that reformats the file, which is the common case: a repo
|
|
498
|
+
* whose pre-commit hook runs Biome or Prettier over `*.json` would
|
|
499
|
+
* otherwise see every run rewrite the file forever, because the
|
|
500
|
+
* formatter's bytes never match `CanonicalJson`'s.
|
|
501
|
+
* - `"bytes"` — compare the exact text, so the file on disk is only ever
|
|
502
|
+
* `CanonicalJson`'s own output. Choose this when the emitted bytes are
|
|
503
|
+
* themselves the artifact and no other tool is allowed to touch them.
|
|
504
|
+
*
|
|
505
|
+
* `change` in the {@link WriteResult} is classified by content either
|
|
506
|
+
* way; this option decides only whether a byte-level difference is
|
|
507
|
+
* enough to rewrite.
|
|
508
|
+
*/
|
|
509
|
+
readonly compare?: "bytes" | "value";
|
|
510
|
+
}
|
|
511
|
+
/**
|
|
512
|
+
* The shape of the {@link SchemaFile} service — the value produced by
|
|
513
|
+
* {@link SchemaFile.make} and carried by its layer.
|
|
514
|
+
*
|
|
515
|
+
* @public
|
|
516
|
+
*/
|
|
517
|
+
interface SchemaFileShape {
|
|
518
|
+
/**
|
|
519
|
+
* Read a schema file's exact text (the drift-test read side: compare it
|
|
520
|
+
* against `StoreDocument.serializeResult`). Fails with
|
|
521
|
+
* `SchemaFileNotFoundError` (ENOENT) or `SchemaFileReadError` (other
|
|
522
|
+
* filesystem errors).
|
|
523
|
+
*/
|
|
524
|
+
readonly read: (path: string) => Effect.Effect<string, SchemaFileReadError | SchemaFileNotFoundError>;
|
|
525
|
+
/**
|
|
526
|
+
* Serialize a document to canonical JSON and write it **only if the
|
|
527
|
+
* on-disk content differs** (a missing file counts as different),
|
|
528
|
+
* creating parent directories as needed. Answers a {@link WriteResult}
|
|
529
|
+
* as a value: what happened to the file, and what the difference meant.
|
|
530
|
+
* Fails with a `CanonicalJsonError` (the document does not serialize),
|
|
531
|
+
* `SchemaFileReadError` (the existing content could not be read for
|
|
532
|
+
* comparison) or `SchemaFileWriteError` (the filesystem write failed).
|
|
533
|
+
*/
|
|
534
|
+
readonly write: (path: string, document: StoreDocument, options?: SchemaWriteOptions) => Effect.Effect<WriteResult, CanonicalJsonError | SchemaFileReadError | SchemaFileWriteError>;
|
|
535
|
+
/**
|
|
536
|
+
* The same comparison {@link SchemaFileShape.write} makes, **without
|
|
537
|
+
* touching the filesystem** — the drift-check half of the pair, for a
|
|
538
|
+
* CI job that must assert a committed schema is current rather than
|
|
539
|
+
* regenerate it.
|
|
540
|
+
*
|
|
541
|
+
* Answers both questions the writer answers: `change` classifies the
|
|
542
|
+
* content (immune to a formatter having reflowed the committed file),
|
|
543
|
+
* and `wouldWrite` honors `compare`, so it agrees with `write` under
|
|
544
|
+
* either mode. Checking drift is `change`; predicting the writer is
|
|
545
|
+
* `wouldWrite`.
|
|
546
|
+
*/
|
|
547
|
+
readonly check: (path: string, document: StoreDocument, options?: SchemaWriteOptions) => Effect.Effect<CheckResult, CanonicalJsonError | SchemaFileReadError>;
|
|
548
|
+
}
|
|
549
|
+
declare const SchemaFile_base: Context.ServiceClass<SchemaFile, "@effected/schemastore/SchemaFile", SchemaFileShape>;
|
|
550
|
+
/**
|
|
551
|
+
* Reads and writes emitted schema documents over core `FileSystem` /
|
|
552
|
+
* `Path` — the package's one IO surface. The layer requires those
|
|
553
|
+
* services; provide `@effect/platform-node`'s `NodeFileSystem` / `NodePath`
|
|
554
|
+
* (or a bun equivalent) at the application boundary.
|
|
555
|
+
*
|
|
556
|
+
* `write` is write-if-changed, and by default compares **content**: an
|
|
557
|
+
* unchanged document never touches the file even if another tool has
|
|
558
|
+
* reformatted it, so a generator committed to a repo whose pre-commit hook
|
|
559
|
+
* formats JSON does not churn on every run. It also reports what the
|
|
560
|
+
* difference meant — `"annotations"` (prose only, replaces its predecessor
|
|
561
|
+
* transparently) versus `"contract"` (an assertion moved, so a new
|
|
562
|
+
* `SchemaVersioning` version is warranted). `check` makes the same
|
|
563
|
+
* comparison without writing, which is what a CI drift job wants.
|
|
564
|
+
*
|
|
565
|
+
* @example
|
|
566
|
+
* ```ts
|
|
567
|
+
* import { SchemaFile, StoreDocument } from "@effected/schemastore";
|
|
568
|
+
* import { NodeFileSystem, NodePath } from "@effect/platform-node";
|
|
569
|
+
* import { Effect, Layer, Schema } from "effect";
|
|
570
|
+
*
|
|
571
|
+
* const program = Effect.gen(function* () {
|
|
572
|
+
* const files = yield* SchemaFile;
|
|
573
|
+
* const document = yield* StoreDocument.fromSchema(Schema.Struct({ name: Schema.String }), {
|
|
574
|
+
* $id: "https://example.com/config.schema.json",
|
|
575
|
+
* });
|
|
576
|
+
* return yield* files.write("schemas/config.schema.json", document);
|
|
577
|
+
* }).pipe(
|
|
578
|
+
* Effect.provide(SchemaFile.layer),
|
|
579
|
+
* Effect.provide(Layer.mergeAll(NodeFileSystem.layer, NodePath.layer)),
|
|
580
|
+
* );
|
|
581
|
+
* ```
|
|
582
|
+
*
|
|
583
|
+
* @public
|
|
584
|
+
*/
|
|
585
|
+
declare class SchemaFile extends SchemaFile_base {
|
|
586
|
+
/** Build the service implementation from `FileSystem` / `Path` in context; use {@link SchemaFile.layer} to provide it. */
|
|
587
|
+
static readonly make: Effect.Effect<SchemaFileShape, never, FileSystem.FileSystem | Path.Path>;
|
|
588
|
+
/**
|
|
589
|
+
* The live layer. Requires core `FileSystem` / `Path`, provided by the
|
|
590
|
+
* consumer's platform implementation at the edge.
|
|
591
|
+
*/
|
|
592
|
+
static readonly layer: Layer.Layer<SchemaFile, never, FileSystem.FileSystem | Path.Path>;
|
|
593
|
+
}
|
|
594
|
+
//#endregion
|
|
595
|
+
//#region src/SchemaVersioning.d.ts
|
|
596
|
+
declare const InvalidSchemaVersionError_base: Schema.Class<InvalidSchemaVersionError, Schema.TaggedStruct<"InvalidSchemaVersionError", {
|
|
597
|
+
/** The raw input string that failed to parse. */
|
|
598
|
+
readonly input: Schema.String;
|
|
599
|
+
}>, import("effect/Cause").YieldableError>;
|
|
600
|
+
/**
|
|
601
|
+
* Indicates that a string is not a valid SchemaStore version label.
|
|
602
|
+
*
|
|
603
|
+
* Raised by {@link SchemaVersioning.parse}.
|
|
604
|
+
*
|
|
605
|
+
* @public
|
|
606
|
+
*/
|
|
607
|
+
declare class InvalidSchemaVersionError extends InvalidSchemaVersionError_base {
|
|
608
|
+
get message(): string;
|
|
609
|
+
}
|
|
610
|
+
/**
|
|
611
|
+
* A schema version label: a branded string holding a **full three-component
|
|
612
|
+
* SemVer** — `major.minor.patch` with an optional prerelease, validated by
|
|
613
|
+
* `@effected/semver` itself. Build metadata is rejected (see below).
|
|
614
|
+
*
|
|
615
|
+
* `1.2` and `1` are NOT accepted, though SchemaStore's own corpus uses such
|
|
616
|
+
* labels: requiring all three components makes a label unambiguous to split
|
|
617
|
+
* back out of `<name>-<version>.json` or its URL, which is what consumers
|
|
618
|
+
* do with it. The file-name convention around the label stays SchemaStore's.
|
|
619
|
+
*
|
|
620
|
+
* The label round-trips verbatim into file names and catalog `versions`
|
|
621
|
+
* keys; ordering parses it directly (see {@link SchemaVersioning.Order}).
|
|
622
|
+
*
|
|
623
|
+
* @public
|
|
624
|
+
*/
|
|
625
|
+
declare const SchemaVersion: Schema.brand<Schema.String, "SchemaVersion">;
|
|
626
|
+
/**
|
|
627
|
+
* The type of a validated SchemaStore version label.
|
|
628
|
+
*
|
|
629
|
+
* @public
|
|
630
|
+
*/
|
|
631
|
+
type SchemaVersion = typeof SchemaVersion.Type;
|
|
632
|
+
/**
|
|
633
|
+
* The `url`/`versions` half of a catalog entry, as assembled by
|
|
634
|
+
* {@link SchemaVersioning.catalogUrls}.
|
|
635
|
+
*
|
|
636
|
+
* @public
|
|
637
|
+
*/
|
|
638
|
+
interface CatalogUrls {
|
|
639
|
+
/** The catalog `url` — the unversioned file, or the latest versioned file. */
|
|
640
|
+
readonly url: string;
|
|
641
|
+
/**
|
|
642
|
+
* The versioned catalog's `versions` map (label → url), inserted — and,
|
|
643
|
+
* since a three-component label can never be integer-like, enumerated
|
|
644
|
+
* and serialized — in ascending version order.
|
|
645
|
+
*/
|
|
646
|
+
readonly versions?: Readonly<Record<string, string>>;
|
|
647
|
+
}
|
|
648
|
+
/**
|
|
649
|
+
* Both SchemaStore catalog modes as pure derivations: unversioned (a plain
|
|
650
|
+
* `name.json` file, `url` only) and versioned (`name-<version>.json` files
|
|
651
|
+
* — SchemaStore's own suffix convention — a `versions` map, and `url`
|
|
652
|
+
* pointing at the latest version).
|
|
653
|
+
*
|
|
654
|
+
* Version labels are full three-component SemVer, so ordering is plain
|
|
655
|
+
* SemVer precedence: `1.10.0` above `1.9.0`, `2.0.0-beta` below `2.0.0`.
|
|
656
|
+
*
|
|
657
|
+
* @public
|
|
658
|
+
*/
|
|
659
|
+
declare class SchemaVersioning {
|
|
660
|
+
private constructor();
|
|
661
|
+
/**
|
|
662
|
+
* Parses a version label. Pure and synchronous — the primitive form;
|
|
663
|
+
* {@link SchemaVersioning.parse} is the same check behind a span.
|
|
664
|
+
*/
|
|
665
|
+
static parseResult(input: string): Result.Result<SchemaVersion, InvalidSchemaVersionError>;
|
|
666
|
+
/**
|
|
667
|
+
* Effect form of {@link SchemaVersioning.parseResult}, adding only the
|
|
668
|
+
* `SchemaVersioning.parse` span. Defined in terms of the `Result`
|
|
669
|
+
* primitive — synchronous callers can use that variant directly.
|
|
670
|
+
*/
|
|
671
|
+
static readonly parse: (input: string) => Effect.Effect<string & import("effect/Brand").Brand<"SchemaVersion">, InvalidSchemaVersionError, never>;
|
|
672
|
+
/**
|
|
673
|
+
* `Order` instance over version labels: plain SemVer precedence.
|
|
674
|
+
* `1.10.0` sorts above `1.9.0` (numeric, not lexical) and `2.0.0-beta`
|
|
675
|
+
* below `2.0.0` (prerelease precedence).
|
|
676
|
+
*/
|
|
677
|
+
static readonly Order: Order.Order<SchemaVersion>;
|
|
678
|
+
/**
|
|
679
|
+
* The highest version label by {@link SchemaVersioning.Order}, or
|
|
680
|
+
* `Option.none()` for an empty collection.
|
|
681
|
+
*/
|
|
682
|
+
static latest(versions: ReadonlyArray<SchemaVersion>): Option.Option<SchemaVersion>;
|
|
683
|
+
/**
|
|
684
|
+
* Whether a label names a pinned, published document — i.e. it is NOT a
|
|
685
|
+
* prerelease. SemVer §9 makes a prerelease's own instability explicit, so
|
|
686
|
+
* a contract change inside one is not a break for anyone.
|
|
687
|
+
*
|
|
688
|
+
* ONE predicate consumed by two policies so they cannot drift:
|
|
689
|
+
* `SchemaPipeline`'s `"block-versioned"` guard (a pinned versioned target
|
|
690
|
+
* refuses an in-place contract change) and {@link SchemaVersioning.next}
|
|
691
|
+
* (a non-pinned label is not bumped). If the two used different tests, a
|
|
692
|
+
* caller could be refused a write AND told to keep the same label — a
|
|
693
|
+
* deadlock.
|
|
694
|
+
*/
|
|
695
|
+
static isPinned(version: SchemaVersion): boolean;
|
|
696
|
+
/**
|
|
697
|
+
* The version label a change classification calls for. Pure and
|
|
698
|
+
* synchronous; total over validated labels — a non-label input is a wiring
|
|
699
|
+
* bug and dies as a defect, the same as {@link SchemaVersioning.Order}.
|
|
700
|
+
*
|
|
701
|
+
* - `change !== "contract"` (`"none"`, `"annotations"`, `"created"`) →
|
|
702
|
+
* `current`. A created file has no predecessor to break; an annotation
|
|
703
|
+
* change is transparently replaceable (`DocumentDiff`).
|
|
704
|
+
* - `current` is not pinned (a prerelease) → `current`. A prerelease
|
|
705
|
+
* declares its own instability; the pipeline's `"block-versioned"`
|
|
706
|
+
* policy uses the same {@link SchemaVersioning.isPinned}, so the gate
|
|
707
|
+
* and the bump agree.
|
|
708
|
+
* - `major === 0` → MINOR bump (`0.4.0` → `0.5.0`): on the 0.x line MINOR
|
|
709
|
+
* is the breaking axis.
|
|
710
|
+
* - otherwise → MAJOR bump (`5.0.0` → `6.0.0`).
|
|
711
|
+
*
|
|
712
|
+
* The bump's job is to be strictly greater and conspicuous, NOT to encode
|
|
713
|
+
* SemVer compatibility: `DocumentDiff` cannot tell an added optional
|
|
714
|
+
* property from a removed required one, so every contract change reads as
|
|
715
|
+
* breaking. Each label is its own file and URL, so an over-bump costs a
|
|
716
|
+
* file; an under-bump would overwrite a pinned document. `next` never
|
|
717
|
+
* introduces a prerelease from a stable input.
|
|
718
|
+
*
|
|
719
|
+
* A component that would be bumped past `Number.MAX_SAFE_INTEGER` cannot be
|
|
720
|
+
* represented, and throws this module's explicit invariant `Error` naming
|
|
721
|
+
* the label and the ceiling rather than `SemVer.make`'s bare schema failure.
|
|
722
|
+
*/
|
|
723
|
+
static next(current: SchemaVersion, change: WriteChange): SchemaVersion;
|
|
724
|
+
/**
|
|
725
|
+
* Derives the schema file name for a catalog name: `name.json`
|
|
726
|
+
* unversioned, `name-<version>.json` versioned.
|
|
727
|
+
*
|
|
728
|
+
* The name must be a simple file base name (no separators, no
|
|
729
|
+
* whitespace); anything else is a wiring mistake and throws.
|
|
730
|
+
*/
|
|
731
|
+
static fileName(name: string, version?: SchemaVersion): string;
|
|
732
|
+
/**
|
|
733
|
+
* The canonical URL a schema file is hosted at: `baseUrl` joined with
|
|
734
|
+
* {@link SchemaVersioning.fileName}.
|
|
735
|
+
*/
|
|
736
|
+
static schemaUrl(baseUrl: string, name: string, version?: SchemaVersion): string;
|
|
737
|
+
/**
|
|
738
|
+
* Assembles the `url`/`versions` half of a catalog entry.
|
|
739
|
+
*
|
|
740
|
+
* Omitting `versions` selects the unversioned mode (`url` only,
|
|
741
|
+
* pointing at the plain `name.json`). Providing them selects the
|
|
742
|
+
* versioned mode: the `versions` map carries every label, and `url`
|
|
743
|
+
* points at the latest version's file. An **empty** `versions` array is
|
|
744
|
+
* a contradiction (versioned mode with no versions) and throws — pass
|
|
745
|
+
* `undefined` for the unversioned mode.
|
|
746
|
+
*
|
|
747
|
+
* Labels are inserted in ascending {@link SchemaVersioning.Order} and
|
|
748
|
+
* stay that way on serialization. Requiring three components is what
|
|
749
|
+
* buys this: JavaScript enumerates array-index-like keys first, so the
|
|
750
|
+
* old grammar's bare-major label (`"2"`) jumped ahead of every dotted
|
|
751
|
+
* one regardless of insertion order. No SemVer label is integer-like,
|
|
752
|
+
* so that hazard is gone. Deriving ordering from the labels themselves
|
|
753
|
+
* (as {@link SchemaVersioning.latest} does) is still the robust read.
|
|
754
|
+
*/
|
|
755
|
+
static catalogUrls(options: {
|
|
756
|
+
readonly baseUrl: string;
|
|
757
|
+
readonly name: string;
|
|
758
|
+
readonly versions?: ReadonlyArray<SchemaVersion>;
|
|
759
|
+
}): CatalogUrls;
|
|
760
|
+
}
|
|
761
|
+
//#endregion
|
|
762
|
+
//#region src/CatalogEntry.d.ts
|
|
763
|
+
declare const CatalogLintFinding_base: Schema.Class<CatalogLintFinding, Schema.Struct<{
|
|
764
|
+
/** Which hygiene check fired. */
|
|
765
|
+
readonly check: Schema.Literals<readonly ["GenericFileMatch", "ComplexFileMatch"]>;
|
|
766
|
+
/** The `fileMatch` pattern the finding is about. */
|
|
767
|
+
readonly pattern: Schema.String;
|
|
768
|
+
/** Human-readable explanation with the SchemaStore rationale. */
|
|
769
|
+
readonly message: Schema.String;
|
|
770
|
+
}>, {}>;
|
|
771
|
+
/**
|
|
772
|
+
* A fileMatch hygiene finding: a value in a lint report, not an error —
|
|
773
|
+
* SchemaStore reviewers reject entries over these, so surfacing them
|
|
774
|
+
* locally is the point, but a warned entry is still a valid entry.
|
|
775
|
+
*
|
|
776
|
+
* @public
|
|
777
|
+
*/
|
|
778
|
+
declare class CatalogLintFinding extends CatalogLintFinding_base {}
|
|
779
|
+
declare const CatalogEntry_base: Schema.Class<CatalogEntry, Schema.Struct<{
|
|
780
|
+
/** The schema's display name in the catalog. */
|
|
781
|
+
readonly name: Schema.String;
|
|
782
|
+
/** The catalog description. */
|
|
783
|
+
readonly description: Schema.String;
|
|
784
|
+
/** Glob patterns editors match files against. */
|
|
785
|
+
readonly fileMatch: Schema.$Array<Schema.String>;
|
|
786
|
+
/** The schema URL — the unversioned file, or the latest version. */
|
|
787
|
+
readonly url: Schema.String;
|
|
788
|
+
/**
|
|
789
|
+
* Versioned mode only: label → schema URL. Inserted ascending, but key
|
|
790
|
+
* order is not a contract — bare-major labels enumerate first (see
|
|
791
|
+
* `SchemaVersioning.catalogUrls`); derive ordering from the labels.
|
|
792
|
+
*/
|
|
793
|
+
readonly versions: Schema.optionalKey<Schema.$Record<Schema.String, Schema.String>>;
|
|
794
|
+
}>, {}>;
|
|
795
|
+
/**
|
|
796
|
+
* A SchemaStore `catalog.json` entry: the class is the schema, so decoding
|
|
797
|
+
* an existing entry and encoding one for submission are the same artifact.
|
|
798
|
+
* `versions` is present only for versioned catalogs
|
|
799
|
+
* ({@link SchemaVersioning.catalogUrls} assembles both modes).
|
|
800
|
+
*
|
|
801
|
+
* @public
|
|
802
|
+
*/
|
|
803
|
+
declare class CatalogEntry extends CatalogEntry_base {
|
|
804
|
+
/**
|
|
805
|
+
* Assembles an entry from a catalog identity plus
|
|
806
|
+
* {@link SchemaVersioning.catalogUrls}' inputs: pass `versions` for the
|
|
807
|
+
* versioned mode (the `versions` map and latest-pointing `url` are
|
|
808
|
+
* derived), omit it for the unversioned mode.
|
|
809
|
+
*/
|
|
810
|
+
static assemble(options: {
|
|
811
|
+
readonly name: string;
|
|
812
|
+
readonly description: string;
|
|
813
|
+
readonly fileMatch: ReadonlyArray<string>;
|
|
814
|
+
readonly baseUrl: string;
|
|
815
|
+
readonly fileBaseName?: string;
|
|
816
|
+
readonly versions?: ReadonlyArray<SchemaVersion>;
|
|
817
|
+
}): CatalogEntry;
|
|
818
|
+
/**
|
|
819
|
+
* The fileMatch hygiene lint over this entry's patterns — pure shape
|
|
820
|
+
* analysis (no glob engine): generic patterns SchemaStore rejects and
|
|
821
|
+
* complex constructs it asks contributors to expand.
|
|
822
|
+
*/
|
|
823
|
+
lint(): ReadonlyArray<CatalogLintFinding>;
|
|
824
|
+
/**
|
|
825
|
+
* {@link CatalogEntry.lint} over a bare pattern list, for callers
|
|
826
|
+
* checking patterns before an entry exists.
|
|
827
|
+
*/
|
|
828
|
+
static lintFileMatch(patterns: ReadonlyArray<string>): ReadonlyArray<CatalogLintFinding>;
|
|
575
829
|
}
|
|
576
830
|
//#endregion
|
|
577
831
|
//#region src/DocumentLint.d.ts
|
|
@@ -603,7 +857,7 @@ declare class DocumentLintFinding extends DocumentLintFinding_base {}
|
|
|
603
857
|
* `#/definitions/...` pointer, is a warning).
|
|
604
858
|
* - `UnknownKeyword` — no keyword outside Draft-07 plus the declared
|
|
605
859
|
* non-standard families ({@link KeywordFamilies}: `x-taplo*`, `x-tombi-*`,
|
|
606
|
-
* `x-intellij-*` and the vscode set), which ajv strict mode would reject.
|
|
860
|
+
* `x-intellij-*`, `x-ai-*` and the vscode set), which ajv strict mode would reject.
|
|
607
861
|
* - `DescriptionWithoutUrl` — advisory: SchemaStore's description
|
|
608
862
|
* convention ends the root description with a docs URL line.
|
|
609
863
|
*
|
|
@@ -623,10 +877,12 @@ declare class DocumentLint {
|
|
|
623
877
|
//#endregion
|
|
624
878
|
//#region src/KeywordFamilies.d.ts
|
|
625
879
|
/**
|
|
626
|
-
* The one owner of the declared non-standard keyword families
|
|
627
|
-
*
|
|
628
|
-
*
|
|
629
|
-
*
|
|
880
|
+
* The one owner of the declared non-standard keyword families, in two
|
|
881
|
+
* groups.
|
|
882
|
+
*
|
|
883
|
+
* **Upstream language-server families** — mirrored from SchemaStore's
|
|
884
|
+
* CONTRIBUTING, the keyword sets legitimately consumed by editor
|
|
885
|
+
* toolchains that ajv strict mode would otherwise reject:
|
|
630
886
|
*
|
|
631
887
|
* - **vscode-json-languageservice** (exact names): `allowTrailingCommas`,
|
|
632
888
|
* `defaultSnippets`, `enumDescriptions`, `markdownDescription`,
|
|
@@ -639,6 +895,43 @@ declare class DocumentLint {
|
|
|
639
895
|
* - **IntelliJ**: the `x-intellij-` prefix (`x-intellij-language-injection`,
|
|
640
896
|
* `x-intellij-html-description`, `x-intellij-enum-metadata`).
|
|
641
897
|
*
|
|
898
|
+
* **The house machine-annotation family** — `x-ai-` (WITH the trailing
|
|
899
|
+
* dash; bare `x-ai` and a look-alike prefix like `x-aida-foo` are NOT
|
|
900
|
+
* declared), owned by this package rather than mirrored from anywhere:
|
|
901
|
+
*
|
|
902
|
+
* - It is a NAMESPACE, not a vocabulary — any `x-ai-*` key is declared, and
|
|
903
|
+
* this package does not enumerate specific keys.
|
|
904
|
+
* - The key itself must be one ajv can register: after the prefix, only
|
|
905
|
+
* `[A-Za-z0-9_$:-]` (ajv holds a keyword name to
|
|
906
|
+
* `/^[a-z_$][a-z0-9_$:-]*$/i`). A dot, a space, a slash, an `@`, a `+` or
|
|
907
|
+
* any non-ASCII character makes the engine gate reject the whole document
|
|
908
|
+
* — as a root-pathed `ValidationFinding`, not an error.
|
|
909
|
+
* - A value under a declared `x-ai-*` key must be JSON — `CanonicalJson`
|
|
910
|
+
* fails typed (`NonJsonValueError`) on anything else, the same as
|
|
911
|
+
* every other emitted value.
|
|
912
|
+
* - The one recommended, non-binding key is `x-ai-hint`: a string carrying
|
|
913
|
+
* an instruction to a machine reader about the annotated value.
|
|
914
|
+
* - `x-ai-example` is deliberately NOT recommended. Draft-07's own
|
|
915
|
+
* `examples` keyword already exists, is carried by the assembly, and
|
|
916
|
+
* classifies as a CONTRACT change in `DocumentDiff`; an `x-ai-*`
|
|
917
|
+
* key classifies as ANNOTATIONS. The two would be two example channels
|
|
918
|
+
* with opposite version semantics.
|
|
919
|
+
* - A declared-family value must not contain an `$id` — or a repeated
|
|
920
|
+
* `$anchor` — at ANY depth, not merely as its own top-level key: ajv's
|
|
921
|
+
* reference collection walks unknown keywords looking for them, so a
|
|
922
|
+
* colliding one buried anywhere inside an annotation payload fails the
|
|
923
|
+
* compile, surfacing as a blocking root-pathed `ValidationFinding` rather
|
|
924
|
+
* than a silent no-op. An empty-string `$id` collides too — it resolves
|
|
925
|
+
* to the root id.
|
|
926
|
+
* - No upstream tool sanctions `x-ai-`: a document carrying it that is
|
|
927
|
+
* submitted to schemastore.org needs the corresponding entry added to
|
|
928
|
+
* that repo's own validation config. Until then it is intended for
|
|
929
|
+
* self-hosted publication.
|
|
930
|
+
* - `DocumentDiff` classifies a delta confined to `x-ai-*` keys as
|
|
931
|
+
* `"annotations"`, so adopting the family on an already-published
|
|
932
|
+
* versioned document rewrites that file in place — correct, because
|
|
933
|
+
* annotations are transparently replaceable.
|
|
934
|
+
*
|
|
642
935
|
* Both consumers of the registry route through {@link KeywordFamilies.isDeclared}:
|
|
643
936
|
* `DocumentLint`'s `UnknownKeyword` check (a declared key is not flagged) and
|
|
644
937
|
* `AnnotationCarriers` (only declared keys are re-grafted after the Draft-07
|
|
@@ -647,7 +940,7 @@ declare class DocumentLint {
|
|
|
647
940
|
/**
|
|
648
941
|
* The declared non-standard keyword families as one predicate: the
|
|
649
942
|
* vscode-json-languageservice set by exact name, plus the `x-taplo`,
|
|
650
|
-
* `x-tombi-` and `x-
|
|
943
|
+
* `x-tombi-`, `x-intellij-` and `x-ai-` prefixes.
|
|
651
944
|
*
|
|
652
945
|
* @public
|
|
653
946
|
*/
|
|
@@ -656,224 +949,12 @@ declare class KeywordFamilies {
|
|
|
656
949
|
/**
|
|
657
950
|
* Whether `key` belongs to a declared non-standard keyword family.
|
|
658
951
|
* Draft-07's own keywords are a separate vocabulary — this predicate
|
|
659
|
-
* answers only for the language-server extension families
|
|
952
|
+
* answers only for the language-server extension families and the
|
|
953
|
+
* house `x-ai-` machine-annotation namespace.
|
|
660
954
|
*/
|
|
661
955
|
static isDeclared(key: string): boolean;
|
|
662
956
|
}
|
|
663
957
|
//#endregion
|
|
664
|
-
//#region src/SchemaFile.d.ts
|
|
665
|
-
declare const SchemaFileReadError_base: Schema.Class<SchemaFileReadError, Schema.TaggedStruct<"SchemaFileReadError", {
|
|
666
|
-
/** The path that could not be read. */
|
|
667
|
-
readonly path: Schema.String;
|
|
668
|
-
/** The underlying filesystem failure, preserved structurally. */
|
|
669
|
-
readonly cause: Schema.Defect;
|
|
670
|
-
}>, import("effect/Cause").YieldableError>;
|
|
671
|
-
/**
|
|
672
|
-
* Indicates that a schema file could not be read from the filesystem (a
|
|
673
|
-
* filesystem error other than not-found).
|
|
674
|
-
*
|
|
675
|
-
* @public
|
|
676
|
-
*/
|
|
677
|
-
declare class SchemaFileReadError extends SchemaFileReadError_base {
|
|
678
|
-
get message(): string;
|
|
679
|
-
}
|
|
680
|
-
declare const SchemaFileNotFoundError_base: Schema.Class<SchemaFileNotFoundError, Schema.TaggedStruct<"SchemaFileNotFoundError", {
|
|
681
|
-
/** The path where the schema file was expected. */
|
|
682
|
-
readonly path: Schema.String;
|
|
683
|
-
}>, import("effect/Cause").YieldableError>;
|
|
684
|
-
/**
|
|
685
|
-
* Indicates that no schema file exists at the expected path. Carries its
|
|
686
|
-
* own tag for `catchTag` routing.
|
|
687
|
-
*
|
|
688
|
-
* @public
|
|
689
|
-
*/
|
|
690
|
-
declare class SchemaFileNotFoundError extends SchemaFileNotFoundError_base {
|
|
691
|
-
get message(): string;
|
|
692
|
-
}
|
|
693
|
-
declare const SchemaFileWriteError_base: Schema.Class<SchemaFileWriteError, Schema.TaggedStruct<"SchemaFileWriteError", {
|
|
694
|
-
/** The path that could not be written. */
|
|
695
|
-
readonly path: Schema.String;
|
|
696
|
-
/** The underlying filesystem failure, preserved structurally. */
|
|
697
|
-
readonly cause: Schema.Defect;
|
|
698
|
-
}>, import("effect/Cause").YieldableError>;
|
|
699
|
-
/**
|
|
700
|
-
* Indicates that a schema file could not be written to the filesystem.
|
|
701
|
-
* Narrowed to the filesystem failure only — a serialization failure
|
|
702
|
-
* surfaces as its own `CanonicalJsonError`, never wrapped here.
|
|
703
|
-
*
|
|
704
|
-
* @public
|
|
705
|
-
*/
|
|
706
|
-
declare class SchemaFileWriteError extends SchemaFileWriteError_base {
|
|
707
|
-
get message(): string;
|
|
708
|
-
}
|
|
709
|
-
/**
|
|
710
|
-
* What {@link SchemaFileShape.write} did to the filesystem: `"written"`
|
|
711
|
-
* when it wrote, `"unchanged"` when it left the file alone — reported as a
|
|
712
|
-
* value so the caller decides what to surface, never a log.
|
|
713
|
-
*
|
|
714
|
-
* @public
|
|
715
|
-
*/
|
|
716
|
-
type WriteOutcome = "written" | "unchanged";
|
|
717
|
-
/**
|
|
718
|
-
* How the document being written relates to what was already on disk:
|
|
719
|
-
* {@link SchemaChange} plus `"created"` for a file that did not exist, so
|
|
720
|
-
* there was nothing to compare against.
|
|
721
|
-
*
|
|
722
|
-
* @public
|
|
723
|
-
*/
|
|
724
|
-
type WriteChange = SchemaChange | "created";
|
|
725
|
-
/**
|
|
726
|
-
* The result of {@link SchemaFileShape.write}: what happened to the file,
|
|
727
|
-
* and what the difference MEANT.
|
|
728
|
-
*
|
|
729
|
-
* The two are independent on purpose. `change` answers the versioning
|
|
730
|
-
* question — `"annotations"` means only prose and editor affordances moved,
|
|
731
|
-
* so the document replaces its predecessor transparently and needs no new
|
|
732
|
-
* {@link SchemaVersioning} version, while `"contract"` means an assertion
|
|
733
|
-
* keyword moved and a consumer's document valid yesterday may be invalid
|
|
734
|
-
* today. `outcome` answers only whether bytes were written, which under
|
|
735
|
-
* `compare: "bytes"` can be `"written"` even when `change` is `"none"`.
|
|
736
|
-
*
|
|
737
|
-
* @public
|
|
738
|
-
*/
|
|
739
|
-
interface WriteResult {
|
|
740
|
-
/**
|
|
741
|
-
* Whether the file was written. **This is the authoritative answer to
|
|
742
|
-
* "did the filesystem get touched"** — always, under either `compare`
|
|
743
|
-
* mode. Do not infer it from `change`: under `compare: "bytes"` a
|
|
744
|
-
* `change` of `"none"` still writes.
|
|
745
|
-
*/
|
|
746
|
-
readonly outcome: WriteOutcome;
|
|
747
|
-
/** What differs between the previous content and the new document. */
|
|
748
|
-
readonly change: WriteChange;
|
|
749
|
-
}
|
|
750
|
-
/**
|
|
751
|
-
* The result of {@link SchemaFileShape.check}: the same two answers
|
|
752
|
-
* {@link WriteResult} carries, for a call that touched nothing.
|
|
753
|
-
*
|
|
754
|
-
* `wouldWrite` is `outcome`'s counterpart — it honors `compare`, so it
|
|
755
|
-
* answers "would `write` do anything with these same options", which
|
|
756
|
-
* `change` alone cannot under `compare: "bytes"`.
|
|
757
|
-
*
|
|
758
|
-
* @public
|
|
759
|
-
*/
|
|
760
|
-
interface CheckResult {
|
|
761
|
-
/** Whether a `write` with the same options would touch the file. */
|
|
762
|
-
readonly wouldWrite: boolean;
|
|
763
|
-
/** What differs between the on-disk content and the new document. */
|
|
764
|
-
readonly change: WriteChange;
|
|
765
|
-
}
|
|
766
|
-
/**
|
|
767
|
-
* Options for {@link SchemaFileShape.write} and
|
|
768
|
-
* {@link SchemaFileShape.check}: the {@link CanonicalJsonOptions} the
|
|
769
|
-
* document serializes under, plus how `write` decides whether to touch the
|
|
770
|
-
* file.
|
|
771
|
-
*
|
|
772
|
-
* @public
|
|
773
|
-
*/
|
|
774
|
-
interface SchemaWriteOptions extends CanonicalJsonOptions {
|
|
775
|
-
/**
|
|
776
|
-
* How `write` decides the file needs rewriting:
|
|
777
|
-
*
|
|
778
|
-
* - `"value"` (the default) — compare the parsed content. Immune to any
|
|
779
|
-
* other tool that reformats the file, which is the common case: a repo
|
|
780
|
-
* whose pre-commit hook runs Biome or Prettier over `*.json` would
|
|
781
|
-
* otherwise see every run rewrite the file forever, because the
|
|
782
|
-
* formatter's bytes never match `CanonicalJson`'s.
|
|
783
|
-
* - `"bytes"` — compare the exact text, so the file on disk is only ever
|
|
784
|
-
* `CanonicalJson`'s own output. Choose this when the emitted bytes are
|
|
785
|
-
* themselves the artifact and no other tool is allowed to touch them.
|
|
786
|
-
*
|
|
787
|
-
* `change` in the {@link WriteResult} is classified by content either
|
|
788
|
-
* way; this option decides only whether a byte-level difference is
|
|
789
|
-
* enough to rewrite.
|
|
790
|
-
*/
|
|
791
|
-
readonly compare?: "bytes" | "value";
|
|
792
|
-
}
|
|
793
|
-
/**
|
|
794
|
-
* The shape of the {@link SchemaFile} service — the value produced by
|
|
795
|
-
* {@link SchemaFile.make} and carried by its layer.
|
|
796
|
-
*
|
|
797
|
-
* @public
|
|
798
|
-
*/
|
|
799
|
-
interface SchemaFileShape {
|
|
800
|
-
/**
|
|
801
|
-
* Read a schema file's exact text (the drift-test read side: compare it
|
|
802
|
-
* against `StoreDocument.serializeResult`). Fails with
|
|
803
|
-
* `SchemaFileNotFoundError` (ENOENT) or `SchemaFileReadError` (other
|
|
804
|
-
* filesystem errors).
|
|
805
|
-
*/
|
|
806
|
-
readonly read: (path: string) => Effect.Effect<string, SchemaFileReadError | SchemaFileNotFoundError>;
|
|
807
|
-
/**
|
|
808
|
-
* Serialize a document to canonical JSON and write it **only if the
|
|
809
|
-
* on-disk content differs** (a missing file counts as different),
|
|
810
|
-
* creating parent directories as needed. Answers a {@link WriteResult}
|
|
811
|
-
* as a value: what happened to the file, and what the difference meant.
|
|
812
|
-
* Fails with a `CanonicalJsonError` (the document does not serialize),
|
|
813
|
-
* `SchemaFileReadError` (the existing content could not be read for
|
|
814
|
-
* comparison) or `SchemaFileWriteError` (the filesystem write failed).
|
|
815
|
-
*/
|
|
816
|
-
readonly write: (path: string, document: StoreDocument, options?: SchemaWriteOptions) => Effect.Effect<WriteResult, CanonicalJsonError | SchemaFileReadError | SchemaFileWriteError>;
|
|
817
|
-
/**
|
|
818
|
-
* The same comparison {@link SchemaFileShape.write} makes, **without
|
|
819
|
-
* touching the filesystem** — the drift-check half of the pair, for a
|
|
820
|
-
* CI job that must assert a committed schema is current rather than
|
|
821
|
-
* regenerate it.
|
|
822
|
-
*
|
|
823
|
-
* Answers both questions the writer answers: `change` classifies the
|
|
824
|
-
* content (immune to a formatter having reflowed the committed file),
|
|
825
|
-
* and `wouldWrite` honors `compare`, so it agrees with `write` under
|
|
826
|
-
* either mode. Checking drift is `change`; predicting the writer is
|
|
827
|
-
* `wouldWrite`.
|
|
828
|
-
*/
|
|
829
|
-
readonly check: (path: string, document: StoreDocument, options?: SchemaWriteOptions) => Effect.Effect<CheckResult, CanonicalJsonError | SchemaFileReadError>;
|
|
830
|
-
}
|
|
831
|
-
declare const SchemaFile_base: Context.ServiceClass<SchemaFile, "@effected/schemastore/SchemaFile", SchemaFileShape>;
|
|
832
|
-
/**
|
|
833
|
-
* Reads and writes emitted schema documents over core `FileSystem` /
|
|
834
|
-
* `Path` — the package's one IO surface. The layer requires those
|
|
835
|
-
* services; provide `@effect/platform-node`'s `NodeFileSystem` / `NodePath`
|
|
836
|
-
* (or a bun equivalent) at the application boundary.
|
|
837
|
-
*
|
|
838
|
-
* `write` is write-if-changed, and by default compares **content**: an
|
|
839
|
-
* unchanged document never touches the file even if another tool has
|
|
840
|
-
* reformatted it, so a generator committed to a repo whose pre-commit hook
|
|
841
|
-
* formats JSON does not churn on every run. It also reports what the
|
|
842
|
-
* difference meant — `"annotations"` (prose only, replaces its predecessor
|
|
843
|
-
* transparently) versus `"contract"` (an assertion moved, so a new
|
|
844
|
-
* `SchemaVersioning` version is warranted). `check` makes the same
|
|
845
|
-
* comparison without writing, which is what a CI drift job wants.
|
|
846
|
-
*
|
|
847
|
-
* @example
|
|
848
|
-
* ```ts
|
|
849
|
-
* import { SchemaFile, StoreDocument } from "@effected/schemastore";
|
|
850
|
-
* import { NodeFileSystem, NodePath } from "@effect/platform-node";
|
|
851
|
-
* import { Effect, Layer, Schema } from "effect";
|
|
852
|
-
*
|
|
853
|
-
* const program = Effect.gen(function* () {
|
|
854
|
-
* const files = yield* SchemaFile;
|
|
855
|
-
* const document = yield* StoreDocument.fromSchema(Schema.Struct({ name: Schema.String }), {
|
|
856
|
-
* $id: "https://example.com/config.schema.json",
|
|
857
|
-
* });
|
|
858
|
-
* return yield* files.write("schemas/config.schema.json", document);
|
|
859
|
-
* }).pipe(
|
|
860
|
-
* Effect.provide(SchemaFile.layer),
|
|
861
|
-
* Effect.provide(Layer.mergeAll(NodeFileSystem.layer, NodePath.layer)),
|
|
862
|
-
* );
|
|
863
|
-
* ```
|
|
864
|
-
*
|
|
865
|
-
* @public
|
|
866
|
-
*/
|
|
867
|
-
declare class SchemaFile extends SchemaFile_base {
|
|
868
|
-
/** Build the service implementation from `FileSystem` / `Path` in context; use {@link SchemaFile.layer} to provide it. */
|
|
869
|
-
static readonly make: Effect.Effect<SchemaFileShape, never, FileSystem.FileSystem | Path.Path>;
|
|
870
|
-
/**
|
|
871
|
-
* The live layer. Requires core `FileSystem` / `Path`, provided by the
|
|
872
|
-
* consumer's platform implementation at the edge.
|
|
873
|
-
*/
|
|
874
|
-
static readonly layer: Layer.Layer<SchemaFile, never, FileSystem.FileSystem | Path.Path>;
|
|
875
|
-
}
|
|
876
|
-
//#endregion
|
|
877
958
|
//#region src/SchemaTarget.d.ts
|
|
878
959
|
/**
|
|
879
960
|
* A single schema publication target: an Effect Schema source paired with
|
|
@@ -903,7 +984,20 @@ interface SchemaTarget {
|
|
|
903
984
|
readonly name?: string;
|
|
904
985
|
/** The destination path the document is written to (`SchemaFile`). */
|
|
905
986
|
readonly path: string;
|
|
906
|
-
/**
|
|
987
|
+
/**
|
|
988
|
+
* The version label, for versioned catalog mode. Omit for unversioned.
|
|
989
|
+
*
|
|
990
|
+
* It carries a second meaning the catalog does not: presence of a
|
|
991
|
+
* **pinned** label (one with no prerelease) declares that consumers pin
|
|
992
|
+
* this document's URL, so `SchemaPipeline.run` refuses to rewrite it in
|
|
993
|
+
* place when its validation contract changes — bump `version`, `$id` and
|
|
994
|
+
* `path` together instead, or pass `contractChanges: "allow"`. That is
|
|
995
|
+
* only coherent when the version participates in `path`
|
|
996
|
+
* (`schemas/<version>/<name>-<version>.json`): a versioned target at a
|
|
997
|
+
* fixed path compares the same file forever, and bumping `version` does
|
|
998
|
+
* not move it. A prerelease label declares its own instability and is
|
|
999
|
+
* rewritten in place.
|
|
1000
|
+
*/
|
|
907
1001
|
readonly version?: SchemaVersion;
|
|
908
1002
|
}
|
|
909
1003
|
/**
|
|
@@ -1045,9 +1139,12 @@ declare class SchemaValidator extends SchemaValidator_base {
|
|
|
1045
1139
|
* `validate` checks the document against the Draft-07 meta-schema and
|
|
1046
1140
|
* then compiles it, reporting BOTH as {@link ValidationFinding} values:
|
|
1047
1141
|
* meta-schema failures keep ajv's structured `instancePath` and
|
|
1048
|
-
* `keyword`, while a
|
|
1049
|
-
*
|
|
1050
|
-
*
|
|
1142
|
+
* `keyword`, while a rejection ajv raises by *throwing* becomes a
|
|
1143
|
+
* root-pathed finding — both a strict-mode compile failure and a
|
|
1144
|
+
* declared keyword whose NAME ajv's own grammar
|
|
1145
|
+
* (`/^[a-z_$][a-z0-9_$:-]*$/i`) refuses, such as an `x-ai-*` key
|
|
1146
|
+
* carrying a dot or a space. The error channel stays reserved for the
|
|
1147
|
+
* engine failing as a mechanism.
|
|
1051
1148
|
*
|
|
1052
1149
|
* `strict` defaults to `true` — SchemaStore's gate. Each call builds its
|
|
1053
1150
|
* own ajv instance, so documents sharing an `$id` never collide.
|
|
@@ -1121,6 +1218,63 @@ declare const SchemaGateError_base: Schema.Class<SchemaGateError, Schema.TaggedS
|
|
|
1121
1218
|
declare class SchemaGateError extends SchemaGateError_base {
|
|
1122
1219
|
get message(): string;
|
|
1123
1220
|
}
|
|
1221
|
+
/**
|
|
1222
|
+
* How {@link SchemaPipeline.run} treats a target whose document would change
|
|
1223
|
+
* its validation contract.
|
|
1224
|
+
*
|
|
1225
|
+
* - `"block-versioned"` (the default) — a target carrying a PINNED `version`
|
|
1226
|
+
* ({@link SchemaVersioning.isPinned}) is a published, URL-pinned document:
|
|
1227
|
+
* a `"contract"` change fails with {@link SchemaContractChangeError} BEFORE
|
|
1228
|
+
* any write. A target with no `version`, or with a prerelease label, is a
|
|
1229
|
+
* document that replaces its predecessor in place and is rewritten as
|
|
1230
|
+
* before.
|
|
1231
|
+
* - `"allow"` — classify and report only, never refuse: the pre-guard
|
|
1232
|
+
* behaviour. Also the sanctioned REPAIR path for a published file whose
|
|
1233
|
+
* text no longer parses — `SchemaFile` classifies unparseable text as
|
|
1234
|
+
* `"contract"` so it stays regenerable, and under the default that
|
|
1235
|
+
* classification is refused.
|
|
1236
|
+
*
|
|
1237
|
+
* The policy reads `change`, which is content-classified under either
|
|
1238
|
+
* `write.compare` mode, so `"bytes"` neither strengthens nor weakens it.
|
|
1239
|
+
*
|
|
1240
|
+
* The policy is only coherent when the version participates in `path`
|
|
1241
|
+
* (`schemas/<version>/<name>-<version>.json`): a versioned target at a fixed
|
|
1242
|
+
* path compares the same file forever, and bumping `version` does not move
|
|
1243
|
+
* it.
|
|
1244
|
+
*
|
|
1245
|
+
* @public
|
|
1246
|
+
*/
|
|
1247
|
+
type ContractChangePolicy = "block-versioned" | "allow";
|
|
1248
|
+
declare const ContractChangeTarget_base: Schema.Class<ContractChangeTarget, Schema.Struct<{
|
|
1249
|
+
/** The target's `$id`. */
|
|
1250
|
+
readonly $id: Schema.String;
|
|
1251
|
+
/** The path the document would have been written to. */
|
|
1252
|
+
readonly path: Schema.String;
|
|
1253
|
+
/** The target's pinned label. */
|
|
1254
|
+
readonly version: Schema.brand<Schema.String, "SchemaVersion">;
|
|
1255
|
+
/** The label to publish under instead — {@link SchemaVersioning.next} of `version`. */
|
|
1256
|
+
readonly nextVersion: Schema.brand<Schema.String, "SchemaVersion">;
|
|
1257
|
+
}>, {}>;
|
|
1258
|
+
/**
|
|
1259
|
+
* One published document whose validation contract would change.
|
|
1260
|
+
*
|
|
1261
|
+
* @public
|
|
1262
|
+
*/
|
|
1263
|
+
declare class ContractChangeTarget extends ContractChangeTarget_base {}
|
|
1264
|
+
declare const SchemaContractChangeError_base: Schema.Class<SchemaContractChangeError, Schema.TaggedStruct<"SchemaContractChangeError", {
|
|
1265
|
+
/** Every published target whose contract would change, in target order. */
|
|
1266
|
+
readonly targets: Schema.$Array<typeof ContractChangeTarget>;
|
|
1267
|
+
}>, import("effect/Cause").YieldableError>;
|
|
1268
|
+
/**
|
|
1269
|
+
* Indicates that at least one published target's contract changed under the
|
|
1270
|
+
* active {@link ContractChangePolicy}. Raised BEFORE any target is written
|
|
1271
|
+
* and total over the targets, so two broken documents surface in one run.
|
|
1272
|
+
*
|
|
1273
|
+
* @public
|
|
1274
|
+
*/
|
|
1275
|
+
declare class SchemaContractChangeError extends SchemaContractChangeError_base {
|
|
1276
|
+
get message(): string;
|
|
1277
|
+
}
|
|
1124
1278
|
/**
|
|
1125
1279
|
* What the pipeline did with one target.
|
|
1126
1280
|
*
|
|
@@ -1161,6 +1315,17 @@ interface PipelineCheckResult {
|
|
|
1161
1315
|
* never mistaken for clean drift.
|
|
1162
1316
|
*/
|
|
1163
1317
|
readonly blocked: boolean;
|
|
1318
|
+
/**
|
|
1319
|
+
* Whether the {@link ContractChangePolicy} would refuse this write.
|
|
1320
|
+
*
|
|
1321
|
+
* Read it side by side with {@link PipelineCheckResult.blocked}: `blocked`
|
|
1322
|
+
* answers "would findings block a run under `blocking`", while
|
|
1323
|
+
* `contractBlocked` answers "would the contract policy refuse this write
|
|
1324
|
+
* under `contractChanges`". A drift test that reads `contractBlocked` can
|
|
1325
|
+
* print the right remedy — "regenerate" is wrong advice for a target the
|
|
1326
|
+
* generator will refuse; the fix is a version bump.
|
|
1327
|
+
*/
|
|
1328
|
+
readonly contractBlocked: boolean;
|
|
1164
1329
|
/** What differs between the on-disk content and the new document. */
|
|
1165
1330
|
readonly change: WriteChange;
|
|
1166
1331
|
/** Every finding, blocking or not. */
|
|
@@ -1195,6 +1360,14 @@ interface SchemaPipelineOptions {
|
|
|
1195
1360
|
* which a schema can genuinely exceed.
|
|
1196
1361
|
*/
|
|
1197
1362
|
readonly blocking?: (finding: PipelineFinding) => boolean;
|
|
1363
|
+
/**
|
|
1364
|
+
* How {@link SchemaPipeline.run} treats a target whose document would
|
|
1365
|
+
* change its validation contract. Defaults to `"block-versioned"`: a
|
|
1366
|
+
* target carrying a pinned `version` is refused rather than rewritten in
|
|
1367
|
+
* place. Pass `"allow"` to classify and report only — including to repair
|
|
1368
|
+
* a published file whose on-disk text no longer parses.
|
|
1369
|
+
*/
|
|
1370
|
+
readonly contractChanges?: ContractChangePolicy;
|
|
1198
1371
|
/** Passed through to `SchemaValidator.validate`. */
|
|
1199
1372
|
readonly validator?: SchemaValidatorOptions;
|
|
1200
1373
|
/** Passed through to `SchemaFile.write` / `SchemaFile.check`. */
|
|
@@ -1237,13 +1410,45 @@ declare class SchemaPipeline {
|
|
|
1237
1410
|
private constructor();
|
|
1238
1411
|
/**
|
|
1239
1412
|
* Run every target: build its document, gather both gates' findings,
|
|
1240
|
-
* fail with a {@link SchemaGateError} if any block,
|
|
1413
|
+
* fail with a {@link SchemaGateError} if any block, refuse a published
|
|
1414
|
+
* target whose contract changed, and write otherwise.
|
|
1241
1415
|
*
|
|
1242
|
-
*
|
|
1243
|
-
*
|
|
1244
|
-
*
|
|
1416
|
+
* **The run writes nothing unless every target passes both gates.** It
|
|
1417
|
+
* is two-phase: every target is generated, gated and (for a target the
|
|
1418
|
+
* {@link ContractChangePolicy} guards) compared against its predecessor
|
|
1419
|
+
* before any file is touched, and only then are the held documents
|
|
1420
|
+
* written in target order. A gate failure on the third target therefore
|
|
1421
|
+
* leaves the first two unwritten.
|
|
1422
|
+
*
|
|
1423
|
+
* Phase 2 itself is sequential and **not transactional**: a filesystem or
|
|
1424
|
+
* serialization failure part-way through it leaves the targets already
|
|
1425
|
+
* written in place, with no rollback. The guarantee is "no writes unless
|
|
1426
|
+
* every gate passes", not "every write or none".
|
|
1427
|
+
*
|
|
1428
|
+
* The gates run in a fixed precedence: {@link SchemaGateError} is
|
|
1429
|
+
* fail-fast on the first blocked target, because a document the engine
|
|
1430
|
+
* rejects would never be written under any contract policy, so its
|
|
1431
|
+
* classification is noise. {@link SchemaContractChangeError} is total
|
|
1432
|
+
* over the remaining targets, so two published documents whose contracts
|
|
1433
|
+
* moved surface in one run.
|
|
1434
|
+
*
|
|
1435
|
+
* @example
|
|
1436
|
+
* ```ts
|
|
1437
|
+
* import { SchemaContractChangeError, SchemaPipeline } from "@effected/schemastore";
|
|
1438
|
+
* import { Effect } from "effect";
|
|
1439
|
+
*
|
|
1440
|
+
* declare const targets: Parameters<typeof SchemaPipeline.run>[0];
|
|
1441
|
+
*
|
|
1442
|
+
* const program = SchemaPipeline.run(targets).pipe(
|
|
1443
|
+
* Effect.catchTag("SchemaContractChangeError", (error: SchemaContractChangeError) =>
|
|
1444
|
+
* Effect.succeed(
|
|
1445
|
+
* error.targets.map((target) => `${target.$id}: ${target.version} -> ${target.nextVersion}`),
|
|
1446
|
+
* ),
|
|
1447
|
+
* ),
|
|
1448
|
+
* );
|
|
1449
|
+
* ```
|
|
1245
1450
|
*/
|
|
1246
|
-
static run(targets: ReadonlyArray<SchemaTarget>, options?: SchemaPipelineOptions): Effect.Effect<ReadonlyArray<PipelineResult>, SchemaGateError | SchemaConversionError | SchemaValidatorError | CanonicalJsonError | SchemaFileReadError | SchemaFileWriteError, SchemaFile | SchemaValidator>;
|
|
1451
|
+
static run(targets: ReadonlyArray<SchemaTarget>, options?: SchemaPipelineOptions): Effect.Effect<ReadonlyArray<PipelineResult>, SchemaGateError | SchemaContractChangeError | SchemaConversionError | SchemaValidatorError | CanonicalJsonError | SchemaFileReadError | SchemaFileWriteError, SchemaFile | SchemaValidator>;
|
|
1247
1452
|
/**
|
|
1248
1453
|
* The same walk with **no writes** — the drift-check counterpart, for a
|
|
1249
1454
|
* CI job asserting the committed schemas are current.
|
|
@@ -1264,7 +1469,7 @@ declare class SchemaPipeline {
|
|
|
1264
1469
|
* result directly — so a caller with one target does not index into an
|
|
1265
1470
|
* array and prove to the type system that element zero exists.
|
|
1266
1471
|
*/
|
|
1267
|
-
static runOne(target: SchemaTarget, options?: SchemaPipelineOptions): Effect.Effect<PipelineResult, SchemaGateError | SchemaConversionError | SchemaValidatorError | CanonicalJsonError | SchemaFileReadError | SchemaFileWriteError, SchemaFile | SchemaValidator>;
|
|
1472
|
+
static runOne(target: SchemaTarget, options?: SchemaPipelineOptions): Effect.Effect<PipelineResult, SchemaGateError | SchemaContractChangeError | SchemaConversionError | SchemaValidatorError | CanonicalJsonError | SchemaFileReadError | SchemaFileWriteError, SchemaFile | SchemaValidator>;
|
|
1268
1473
|
/**
|
|
1269
1474
|
* {@link SchemaPipeline.check} for a single target, answering its one
|
|
1270
1475
|
* result directly.
|
|
@@ -1272,5 +1477,5 @@ declare class SchemaPipeline {
|
|
|
1272
1477
|
static checkOne(target: SchemaTarget, options?: SchemaPipelineOptions): Effect.Effect<PipelineCheckResult, SchemaConversionError | SchemaValidatorError | CanonicalJsonError | SchemaFileReadError, SchemaFile | SchemaValidator>;
|
|
1273
1478
|
}
|
|
1274
1479
|
//#endregion
|
|
1275
|
-
export { AnnotationCarriers, CanonicalJson, type CanonicalJsonError, type CanonicalJsonOptions, CarrierDepthExceededError, CatalogEntry, CatalogLintFinding, type CatalogUrls, type CheckResult, DRAFT_07_META_SCHEMA, DocumentDiff, DocumentLint, DocumentLintFinding, InvalidSchemaVersionError, JsonDepthExceededError, KeywordFamilies, NonJsonValueError, type PipelineCheckResult, PipelineFinding, type PipelineResult, type SchemaChange, SchemaConversionError, SchemaFile, SchemaFileNotFoundError, SchemaFileReadError, type SchemaFileShape, SchemaFileWriteError, SchemaGateError, SchemaPipeline, type SchemaPipelineOptions, SchemaTarget, SchemaValidator, SchemaValidatorError, type SchemaValidatorOptions, type SchemaValidatorShape, SchemaVersion, SchemaVersioning, type SchemaWriteOptions, StoreDocument, type StoreDocumentOptions, ValidationFinding, type WriteChange, type WriteOutcome, type WriteResult };
|
|
1480
|
+
export { AnnotationCarriers, CanonicalJson, type CanonicalJsonError, type CanonicalJsonOptions, CarrierDepthExceededError, CatalogEntry, CatalogLintFinding, type CatalogUrls, type CheckResult, type ContractChangePolicy, ContractChangeTarget, DRAFT_07_META_SCHEMA, DocumentDiff, DocumentLint, DocumentLintFinding, InvalidSchemaVersionError, JsonDepthExceededError, KeywordFamilies, NonJsonValueError, type PipelineCheckResult, PipelineFinding, type PipelineResult, type SchemaChange, SchemaContractChangeError, SchemaConversionError, SchemaFile, SchemaFileNotFoundError, SchemaFileReadError, type SchemaFileShape, SchemaFileWriteError, SchemaGateError, SchemaPipeline, type SchemaPipelineOptions, SchemaTarget, SchemaValidator, SchemaValidatorError, type SchemaValidatorOptions, type SchemaValidatorShape, SchemaVersion, SchemaVersioning, type SchemaWriteOptions, StoreDocument, type StoreDocumentOptions, ValidationFinding, type WriteChange, type WriteOutcome, type WriteResult };
|
|
1276
1481
|
//# sourceMappingURL=index.d.ts.map
|