@effected/schemastore 0.11.0 → 0.12.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/index.d.ts CHANGED
@@ -264,6 +264,14 @@ interface StoreDocumentOptions {
264
264
  * (`onExcessProperty`, `generateDescriptions`,
265
265
  * `includeAnnotationKey`).
266
266
  *
267
+ * `onExcessProperty` defaults to `"error"` here — every object is
268
+ * emitted closed (`additionalProperties: false`) because a published
269
+ * document is a contract — where core's own default has been `"ignore"`
270
+ * (open) since rc.113. Pass `{ onExcessProperty: "ignore" }` to reopen
271
+ * one document's objects. Omitting `jsonSchema` altogether reproduces
272
+ * byte-for-byte what the CLI writes for a target that declares none — a
273
+ * consumer test may call `fromSchemaResult(schema, { $id })` and compare.
274
+ *
267
275
  * The declared non-standard keyword families ({@link KeywordFamilies})
268
276
  * are **always admitted**, regardless of what a supplied
269
277
  * `includeAnnotationKey` answers — annotate a schema node
@@ -653,8 +661,9 @@ export type SchemaVersion = typeof SchemaVersion.Type;
653
661
  /**
654
662
  * Where a versioned document sits relative to its base: `flat` is
655
663
  * `<name>-<version>.json` (the only shape SchemaStore serves), `versioned`
656
- * nests it as `<version>/<name>-<version>.json`. An unversioned document is
657
- * `<name>.json` under either.
664
+ * nests it as `<version>/<name>-<version>.json` — or, with `appendVersion`
665
+ * off, `<version>/<name>.json`, the directory alone carrying the label. An
666
+ * unversioned document is `<name>.json` under either.
658
667
  *
659
668
  * @public
660
669
  */
@@ -776,17 +785,20 @@ export declare class SchemaVersioning {
776
785
  * Derives the schema file name for a catalog name: `name.json`
777
786
  * unversioned, `name-<version>.json` versioned under the `"flat"`
778
787
  * layout (the default and the only shape SchemaStore serves), or
779
- * `<version>/name-<version>.json` under `"versioned"`.
788
+ * `<version>/name-<version>.json` under `"versioned"` — `<version>/name.json`
789
+ * when `appendVersion` is `false`, which only the versioned layout can
790
+ * carry (under `"flat"` two versions would share one file name, so that
791
+ * combination throws).
780
792
  *
781
793
  * The name must be a simple file base name (no separators, no
782
794
  * whitespace); anything else is a wiring mistake and throws.
783
795
  */
784
- static fileName(name: string, version?: SchemaVersion, layout?: SchemaLayout): string;
796
+ static fileName(name: string, version?: SchemaVersion, layout?: SchemaLayout, appendVersion?: boolean): string;
785
797
  /**
786
798
  * The canonical URL a schema file is hosted at: `baseUrl` joined with
787
799
  * {@link SchemaVersioning.fileName}.
788
800
  */
789
- static schemaUrl(baseUrl: string, name: string, version?: SchemaVersion, layout?: SchemaLayout): string;
801
+ static schemaUrl(baseUrl: string, name: string, version?: SchemaVersion, layout?: SchemaLayout, appendVersion?: boolean): string;
790
802
  /**
791
803
  * Assembles the `url`/`versions` half of a catalog entry.
792
804
  *
@@ -803,9 +815,10 @@ export declare class SchemaVersioning {
803
815
  * verbatim — so a differently-spelled equivalent (`"1.2"` matching a
804
816
  * `"1.2.0"` member) still points `url` at the same file the map does.
805
817
  *
806
- * `layout` (default `"flat"`) is forwarded to every URL derivation, so
807
- * `"versioned"` nests every map value and `url` under its own version
808
- * directory.
818
+ * `layout` (default `"flat"`) and `appendVersion` (default `true`) are
819
+ * forwarded to every URL derivation, so `"versioned"` nests every map
820
+ * value and `url` under its own version directory, with or without the
821
+ * `-<version>` file suffix.
809
822
  *
810
823
  * Labels are inserted in ascending {@link SchemaVersioning.Order}; see
811
824
  * {@link CatalogUrls.versions} for why a bare-major key's serialized
@@ -816,6 +829,7 @@ export declare class SchemaVersioning {
816
829
  readonly name: string;
817
830
  readonly versions?: ReadonlyArray<SchemaVersion>;
818
831
  readonly layout?: SchemaLayout;
832
+ readonly appendVersion?: boolean;
819
833
  readonly current?: SchemaVersion;
820
834
  }): CatalogUrls;
821
835
  }
@@ -867,8 +881,9 @@ export declare class CatalogEntry extends CatalogEntry_base {
867
881
  * {@link SchemaVersioning.catalogUrls}' inputs: pass `versions` for the
868
882
  * versioned mode (the `versions` map and latest-pointing `url` are
869
883
  * derived), omit it for the unversioned mode. `layout` (default
870
- * `"flat"`) and `current` (default: the newest label) are forwarded to
871
- * {@link SchemaVersioning.catalogUrls} verbatim. Throws an `Error` naming
884
+ * `"flat"`), `appendVersion` (default `true`) and `current` (default: the
885
+ * newest label) are forwarded to {@link SchemaVersioning.catalogUrls}
886
+ * verbatim. Throws an `Error` naming
872
887
  * both spellings when two labels compare equal under
873
888
  * {@link SchemaVersioning.Order} (`1.2` and `1.2.0`): each would be its
874
889
  * own key and URL for one document.
@@ -881,6 +896,7 @@ export declare class CatalogEntry extends CatalogEntry_base {
881
896
  readonly fileBaseName?: string;
882
897
  readonly versions?: ReadonlyArray<SchemaVersion>;
883
898
  readonly layout?: SchemaLayout;
899
+ readonly appendVersion?: boolean;
884
900
  readonly current?: SchemaVersion;
885
901
  }): CatalogEntry;
886
902
  /**
@@ -1009,6 +1025,135 @@ export declare class DriftPolicy {
1009
1025
  }, policy: DriftTolerance): DriftVerdict;
1010
1026
  }
1011
1027
  //#endregion
1028
+ //#region src/HostedSchema.d.ts
1029
+ /** The host SchemaStore-hosted documents declare in `$id`. @public */
1030
+ export declare const SCHEMASTORE_ID_BASE = "https://json.schemastore.org";
1031
+ /** The host SchemaStore's `catalog.json` points `url` at. @public */
1032
+ export declare const SCHEMASTORE_CATALOG_BASE = "https://www.schemastore.org";
1033
+ /**
1034
+ * The identity every hosted document derives from: `versions` and `current`
1035
+ * as `defineConfig` accepts them, minus the host, which each constructor
1036
+ * supplies.
1037
+ *
1038
+ * @public
1039
+ */
1040
+ interface HostedSchemaVersionsInput {
1041
+ /** The schema's file base name — the key it takes in `defineConfig`'s `schemas`. */
1042
+ readonly name: string;
1043
+ /** Every version label the schema advertises; omit for an unversioned schema. */
1044
+ readonly versions?: ReadonlyArray<string>;
1045
+ /** Which of `versions` is current. Defaults to the newest under {@link SchemaVersioning.Order}. */
1046
+ readonly current?: string;
1047
+ /**
1048
+ * Whether a versioned file name carries the `-<version>` suffix
1049
+ * (`<version>/<name>-<version>.json`, SchemaStore's own convention, the
1050
+ * default) or the version directory alone names it
1051
+ * (`<version>/<name>.json`). `false` requires the `"versioned"` layout
1052
+ * and is rejected under `"flat"`, including SchemaStore hosting.
1053
+ */
1054
+ readonly appendVersion?: boolean;
1055
+ }
1056
+ /** Input to {@link HostedSchema.github}. @public */
1057
+ interface GitHubHostedSchemaInput extends HostedSchemaVersionsInput {
1058
+ /** The repository, as `owner/repo`. */
1059
+ readonly repo: string;
1060
+ /** The branch (or tag) the files are served from. Defaults to `"main"`. */
1061
+ readonly branch?: string;
1062
+ /** The directory under the repository root the files live in, e.g. `"schemas"`. Defaults to the root. */
1063
+ readonly path?: string;
1064
+ /** How a versioned file nests under `path`. Defaults to `"versioned"`. */
1065
+ readonly layout?: SchemaLayout;
1066
+ }
1067
+ /** Input to {@link HostedSchema.custom}. @public */
1068
+ interface CustomHostedSchemaInput extends HostedSchemaVersionsInput {
1069
+ /** The `https://` directory URL the files are served under; a trailing slash is trimmed. */
1070
+ readonly baseUrl: string | URL;
1071
+ /** How a versioned file nests under `baseUrl`. Defaults to `"versioned"`. */
1072
+ readonly layout?: SchemaLayout;
1073
+ }
1074
+ declare const HostedSchema_base: Schema.Class<HostedSchema, Schema.Struct<{
1075
+ readonly name: Schema.String;
1076
+ readonly baseUrl: Schema.String;
1077
+ readonly versions: Schema.optionalKey<Schema.$Array<Schema.String>>;
1078
+ readonly current: Schema.optionalKey<Schema.String>;
1079
+ readonly layout: Schema.optionalKey<Schema.Literals<readonly ["flat", "versioned"]>>;
1080
+ readonly appendVersion: Schema.optionalKey<Schema.Boolean>;
1081
+ }>, {}>;
1082
+ /**
1083
+ * Where a JSON Schema document is hosted and which version of it is current
1084
+ * — the one value an application derives its `$schema` URL from and hands
1085
+ * to `defineConfig`, so the URL the code emits and the `$id` the CLI writes
1086
+ * cannot disagree.
1087
+ *
1088
+ * @remarks
1089
+ * Build one with {@link HostedSchema.github},
1090
+ * {@link HostedSchema.schemastore} or
1091
+ * {@link HostedSchema.custom}; each validates the identity and
1092
+ * throws a plain `Error` naming the reason. The derivation is
1093
+ * {@link SchemaVersioning.schemaUrl}'s: `<base>/<name>.json` unversioned,
1094
+ * `<base>/<name>-<version>.json` under the `"flat"` layout and
1095
+ * `<base>/<version>/<name>-<version>.json` under `"versioned"` (or
1096
+ * `<base>/<version>/<name>.json` with `appendVersion: false`, when the
1097
+ * version directory alone should name the file). The raw fields are what
1098
+ * `defineConfig` accepts by hand (`baseUrl`, `versions`, `current`,
1099
+ * `layout`, `appendVersion`); the getters are the resolved identity.
1100
+ *
1101
+ * @example
1102
+ * ```ts
1103
+ * import { HostedSchema } from "@effected/schemastore";
1104
+ * import { Schema } from "effect";
1105
+ *
1106
+ * export const OutputSchema = HostedSchema.github({
1107
+ * repo: "savvy-web/silk-release-action",
1108
+ * path: "schemas",
1109
+ * name: "silk-release-action.output",
1110
+ * versions: ["5.2"],
1111
+ * });
1112
+ *
1113
+ * // In the application: every payload names the schema it was written against.
1114
+ * const Output = Schema.Struct({ $schema: Schema.Literal(OutputSchema.$id) });
1115
+ *
1116
+ * // In schemastore.config.ts: the same value, so nothing is re-derived.
1117
+ * // schemas: { [OutputSchema.name]: { schema: Output, hosted: OutputSchema } }
1118
+ * ```
1119
+ *
1120
+ * @public
1121
+ */
1122
+ export declare class HostedSchema extends HostedSchema_base {
1123
+ /** A schema served raw from a GitHub repository. */
1124
+ static github(input: GitHubHostedSchemaInput): HostedSchema;
1125
+ /** A schema published to SchemaStore: `$id` on {@link SCHEMASTORE_ID_BASE}, catalog URL on {@link SCHEMASTORE_CATALOG_BASE}, flat layout. */
1126
+ static schemastore(input: HostedSchemaVersionsInput): HostedSchema;
1127
+ /** A schema served from any `https://` directory. */
1128
+ static custom(input: CustomHostedSchemaInput): HostedSchema;
1129
+ private get resolved();
1130
+ /** The base `$id` is derived from: {@link SCHEMASTORE_ID_BASE} under SchemaStore, else `baseUrl`. */
1131
+ get idBase(): string;
1132
+ /** The base the catalog URL is derived from: {@link SCHEMASTORE_CATALOG_BASE} under SchemaStore, else `baseUrl`. */
1133
+ get catalogBase(): string;
1134
+ /** The effective layout: `"flat"` under SchemaStore, else `layout` defaulting to `"versioned"`. */
1135
+ get resolvedLayout(): SchemaLayout;
1136
+ /** Whether versioned file names carry the `-<version>` suffix: `appendVersion` defaulting to `true`. */
1137
+ get resolvedAppendVersion(): boolean;
1138
+ /** Every advertised version, parsed; empty for an unversioned schema. */
1139
+ get resolvedVersions(): ReadonlyArray<SchemaVersion>;
1140
+ /** The current version — `current`, else the newest of `versions`; `undefined` for an unversioned schema. */
1141
+ get resolvedCurrent(): SchemaVersion | undefined;
1142
+ /** The `$id` of the current document — what an application writes as `$schema`. */
1143
+ get $id(): string;
1144
+ /** The catalog URL of the current document; equals {@link HostedSchema.$id} except under SchemaStore. */
1145
+ get url(): string;
1146
+ /** The current document's file name relative to the output directory. */
1147
+ get fileName(): string;
1148
+ /** The `$id` of the document at `version` (or the unversioned document). */
1149
+ idFor(version?: string): string;
1150
+ /** The catalog URL of the document at `version` (or the unversioned document). */
1151
+ urlFor(version?: string): string;
1152
+ /** The file name of the document at `version` (or the unversioned document), relative to the output directory. */
1153
+ fileNameFor(version?: string): string;
1154
+ private parseLabel;
1155
+ }
1156
+ //#endregion
1012
1157
  //#region src/KeywordFamilies.d.ts
1013
1158
  /**
1014
1159
  * The one owner of the declared non-standard keyword families, in two
@@ -1153,8 +1298,9 @@ export interface SchemaTarget {
1153
1298
  * document's generation contract self-describing, so
1154
1299
  * {@link SchemaPipeline} reproduces a document deterministically
1155
1300
  * regardless of core's own default — for example, an `onExcessProperty`
1156
- * setting of `error` restores closed objects after rc.113 flipped that
1157
- * default open. See {@link StoreDocumentOptions.jsonSchema} for the
1301
+ * setting of `"ignore"` reopens a document's objects, which
1302
+ * {@link StoreDocument.fromSchema} closes by default. See
1303
+ * {@link StoreDocumentOptions.jsonSchema} for that default and the
1158
1304
  * `includeAnnotationKey` gate this option is also subject to.
1159
1305
  */
1160
1306
  readonly jsonSchema?: Schema.ToJsonSchemaOptions;
@@ -1271,31 +1417,22 @@ interface SchemaValidatorShape {
1271
1417
  }
1272
1418
  declare const SchemaValidator_base: Context.ServiceClass<SchemaValidator, "@effected/schemastore/SchemaValidator", SchemaValidatorShape>;
1273
1419
  /**
1274
- * Real-engine JSON Schema document validation, closed by default over ajv —
1275
- * the engine SchemaStore's own gate is defined in terms of.
1276
- *
1277
- * {@link SchemaValidator.layer} is the shipped implementation: provide it and
1278
- * validation works, with no adapter to write. The service stays an interface
1279
- * so a test can swap it ({@link SchemaValidator.layerTest}) or skip it
1280
- * ({@link SchemaValidator.noop}), and so a consumer standardized on a
1281
- * different engine can substitute one — but writing an adapter is no longer
1282
- * the price of admission. `DocumentLint` remains the owned, engine-free
1283
- * structural half of the validation story, and answers questions ajv does
1284
- * not (SchemaStore's own hygiene conventions).
1285
- *
1286
- * The shipped layer registers every declared {@link KeywordFamilies} keyword
1287
- * present in the document before compiling, so ajv strict mode does not
1288
- * reject the language-server families `DocumentLint` deliberately allows —
1289
- * one predicate governs both verdicts. It also registers the standard
1290
- * ajv-formats vocabulary (`date-time`, `date`, `time`, `duration`, `uri`,
1291
- * `uri-reference`, `uri-template`, `url`, `email`, `hostname`, `ipv4`,
1292
- * `ipv6`, `regex`, `uuid`, `json-pointer`, `relative-json-pointer`, …), so a
1293
- * published document can say "this string is an ISO-8601 instant" with a
1294
- * `format` instead of falling back to a `pattern` plus a runtime filter;
1295
- * an UNKNOWN format string remains a strict-mode rejection. The plugin's
1296
- * `formatMaximum` / `formatMinimum` limit keywords are deliberately NOT
1297
- * registered — `DocumentLint` answers those as unknown keywords, and the
1298
- * two verdicts must not drift.
1420
+ * The JSON Schema document validation contract — the engine SchemaStore's
1421
+ * own gate is defined in terms of, as a service the pipeline requires in
1422
+ * `R` and never owns.
1423
+ *
1424
+ * This package ships the contract and its doubles only: skip validation
1425
+ * with {@link SchemaValidator.noop}, stub it with
1426
+ * {@link SchemaValidator.layerTest}. The one real implementation is
1427
+ * `@effected/schemastore-cli`'s `AjvValidator.layer` — ajv strict mode over
1428
+ * the declared `KeywordFamilies` and the standard `ajv-formats`
1429
+ * vocabulary — which the `schemastore` command composes for you and which
1430
+ * that package also exports for a program that drives `SchemaPipeline`
1431
+ * itself. Keeping the engine there keeps `ajv` out of every application that
1432
+ * imports this package at runtime (to read a `HostedSchema`, say) and out of
1433
+ * its bundle. `DocumentLint` is the owned, engine-free structural half of the
1434
+ * validation story, and answers questions ajv does not (SchemaStore's own
1435
+ * hygiene conventions).
1299
1436
  *
1300
1437
  * @example
1301
1438
  * ```ts
@@ -1307,38 +1444,20 @@ declare const SchemaValidator_base: Context.ServiceClass<SchemaValidator, "@effe
1307
1444
  * return yield* validator.validate({ type: "object" });
1308
1445
  * });
1309
1446
  *
1310
- * Effect.runPromise(Effect.provide(program, SchemaValidator.layer));
1447
+ * // Provide the engine at the edge — the CLI does this for you:
1448
+ * // Effect.provide(program, AjvValidator.layer) (from @effected/schemastore-cli)
1449
+ * Effect.runPromise(Effect.provide(program, SchemaValidator.noop));
1311
1450
  * // => []
1312
1451
  * ```
1313
1452
  *
1314
1453
  * @public
1315
1454
  */
1316
1455
  export declare class SchemaValidator extends SchemaValidator_base {
1317
- /**
1318
- * The shipped ajv implementation — the default a consumer provides.
1319
- *
1320
- * `validate` checks the document against the Draft-07 meta-schema and
1321
- * then compiles it, reporting BOTH as {@link ValidationFinding} values:
1322
- * meta-schema failures keep ajv's structured `instancePath` and
1323
- * `keyword`, while a rejection ajv raises by *throwing* becomes a
1324
- * root-pathed finding — both a strict-mode compile failure and a
1325
- * declared keyword whose NAME ajv's own grammar
1326
- * (`/^[a-z_$][a-z0-9_$:-]*$/i`) refuses, such as an `x-ai-*` key
1327
- * carrying a dot or a space. The error channel stays reserved for the
1328
- * engine failing as a mechanism.
1329
- *
1330
- * `strict` defaults to `true` — SchemaStore's gate. Each call builds its
1331
- * own ajv instance, so documents sharing an `$id` never collide. The
1332
- * standard ajv-formats vocabulary is registered on every instance, so
1333
- * `format: "date-time"` (and the rest of the standard set) compiles under
1334
- * strict mode instead of being rejected as an unknown format.
1335
- */
1336
- static readonly layer: Layer.Layer<SchemaValidator>;
1337
1456
  /**
1338
1457
  * No-op: `validate` always succeeds with no findings, never consulting an
1339
1458
  * engine. A pure `Layer.succeed`, bound to a const so the layer memoizes
1340
1459
  * by reference. Use it to switch validation off deliberately — for the
1341
- * real engine, provide {@link SchemaValidator.layer}.
1460
+ * real engine, provide `AjvValidator.layer` from `@effected/schemastore-cli`.
1342
1461
  */
1343
1462
  static readonly noop: Layer.Layer<SchemaValidator>;
1344
1463
  /**
@@ -1563,15 +1682,18 @@ interface SchemaPipelineOptions {
1563
1682
  * write — the loop every consumer of this package was writing by hand.
1564
1683
  *
1565
1684
  * Requires `SchemaFile` and `SchemaValidator` in `R`; provide
1566
- * `SchemaFile.layer` and `SchemaValidator.layer` (plus a platform
1567
- * `FileSystem` / `Path`) at the edge. Findings come back as **values**, so
1685
+ * `SchemaFile.layer` and an engine — `AjvValidator.layer` from
1686
+ * `@effected/schemastore-cli`, which is what the `schemastore` command
1687
+ * composes, or `SchemaValidator.noop` to skip validation — plus a platform
1688
+ * `FileSystem` / `Path` at the edge. Findings come back as **values**, so
1568
1689
  * the package never chooses your log wording — but the gating decision,
1569
1690
  * which is the part that must not silently differ between consumers, has
1570
1691
  * one default and one override point.
1571
1692
  *
1572
1693
  * @example
1573
1694
  * ```ts
1574
- * import { SchemaFile, SchemaPipeline, SchemaTarget, SchemaValidator } from "@effected/schemastore";
1695
+ * import { SchemaFile, SchemaPipeline, SchemaTarget } from "@effected/schemastore";
1696
+ * import { AjvValidator } from "@effected/schemastore-cli";
1575
1697
  * import { NodeServices } from "@effect/platform-node";
1576
1698
  * import { Effect, Layer, Schema } from "effect";
1577
1699
  *
@@ -1584,7 +1706,7 @@ interface SchemaPipelineOptions {
1584
1706
  * ];
1585
1707
  *
1586
1708
  * const program = SchemaPipeline.run(targets).pipe(
1587
- * Effect.provide(Layer.mergeAll(SchemaFile.layer, SchemaValidator.layer)),
1709
+ * Effect.provide(Layer.mergeAll(SchemaFile.layer, AjvValidator.layer)),
1588
1710
  * Effect.provide(NodeServices.layer),
1589
1711
  * );
1590
1712
  * ```
@@ -1664,10 +1786,6 @@ export declare class SchemaPipeline {
1664
1786
  //#endregion
1665
1787
  //#region src/SchemastoreConfig.d.ts
1666
1788
  declare const ConfigBrand: unique symbol;
1667
- /** The host SchemaStore-hosted documents declare in `$id`. @public */
1668
- export declare const SCHEMASTORE_ID_BASE = "https://json.schemastore.org";
1669
- /** The host SchemaStore's `catalog.json` points `url` at. @public */
1670
- export declare const SCHEMASTORE_CATALOG_BASE = "https://www.schemastore.org";
1671
1789
  /**
1672
1790
  * The SchemaStore `catalog.json` fields a schema entry declares, minus
1673
1791
  * `url`/`versions` — those are derived from the entry's `baseUrl`, `layout`
@@ -1693,6 +1811,13 @@ interface CatalogInput {
1693
1811
  interface SchemaEntryInput {
1694
1812
  /** The Effect Schema source the document is generated from. */
1695
1813
  readonly schema: Schema.Constraint;
1814
+ /**
1815
+ * The schema's hosted identity, when the application already holds one
1816
+ * (to derive its `$schema` URL from). Supplies `baseUrl`, `versions`,
1817
+ * `current` and `layout`, which must then not be spelled here, and its
1818
+ * `name` must equal this entry's key.
1819
+ */
1820
+ readonly hosted?: HostedSchema;
1696
1821
  /**
1697
1822
  * Every version label this schema advertises. Omit for an unversioned
1698
1823
  * schema (`<name>.json`). An empty array is rejected — omit the field
@@ -1730,6 +1855,13 @@ interface SchemaEntryInput {
1730
1855
  * only the flat layout.
1731
1856
  */
1732
1857
  readonly layout?: SchemaLayout;
1858
+ /**
1859
+ * Whether a versioned file name carries the `-<version>` suffix
1860
+ * (`<version>/<name>-<version>.json`, the default) or the version
1861
+ * directory alone names it (`<version>/<name>.json`). `false` requires
1862
+ * the `"versioned"` layout. Owned by `hosted` when that is given.
1863
+ */
1864
+ readonly appendVersion?: boolean;
1733
1865
  /** Overrides {@link SchemastoreConfigInput.drift} for this schema. */
1734
1866
  readonly drift?: DriftTolerance;
1735
1867
  /**
@@ -1770,9 +1902,9 @@ interface SchemastoreConfigInput {
1770
1902
  }
1771
1903
  /**
1772
1904
  * One version of a schema that is advertised (via `versions`) but not the
1773
- * one currently generated — a file the CLI verifies exists on disk before
1774
- * any write (existence only — content is never compared), never
1775
- * regenerates.
1905
+ * one currently generated — a file the CLI verifies before any write (it
1906
+ * exists, and its own `$id` is the derived one — the rest of its content is
1907
+ * never compared), never regenerates.
1776
1908
  *
1777
1909
  * @public
1778
1910
  */
@@ -1781,6 +1913,8 @@ interface FrozenVersion {
1781
1913
  readonly version: SchemaVersion;
1782
1914
  /** The path the frozen file lives at. */
1783
1915
  readonly path: string;
1916
+ /** The `$id` the frozen document must declare; differs from `url` only under `baseUrl: "schemastore"`. */
1917
+ readonly $id: string;
1784
1918
  /** The catalog URL the frozen file is hosted at. */
1785
1919
  readonly url: string;
1786
1920
  }
@@ -1835,23 +1969,23 @@ interface SchemastoreConfig {
1835
1969
  * for the catalog URL, forcing the `"flat"` layout; any other `baseUrl` is
1836
1970
  * used as one base for both, defaulting to the `"versioned"` layout.
1837
1971
  *
1838
- * Throws a plain `Error` (never a raw `TypeError`) naming the offending
1839
- * schema on: a non-object `input`; an empty `schemas` record; a
1840
- * missing/empty `outputDir`; a schema key that is not a simple file base
1841
- * name; a schema whose `schema` is not an Effect Schema; a schema with no
1842
- * `baseUrl` anywhere, or a `baseUrl` that is not a string; a `baseUrl` that
1843
- * is neither `"schemastore"` nor an `https://` URL; a `versions` that is not
1844
- * an array, or an empty `versions` array; a version label (or `current`)
1845
- * that is not a string, or an otherwise invalid version label; two labels
1846
- * spelling the same version; `current` given without `versions`, or naming
1847
- * one not among them; a non-boolean `published`; `layout` declared under
1848
- * `baseUrl: "schemastore"`; a missing `catalog` under
1849
- * `baseUrl: "schemastore"`, or one with an empty `fileMatch`; an invalid
1850
- * `drift` or top-level `onDrift`; and an output path (a target, a frozen
1851
- * file, or the catalog path) declared twice, compared after a lexical
1852
- * normalisation (`./`, `..`, trailing `/`) — the CLI's loader re-checks on
1853
- * the resolved absolute paths. Branding the result lets a loader recognise a
1854
- * config module's default export via {@link isSchemastoreConfig}.
1972
+ * Throws a plain `Error` (never a raw `TypeError`) on every malformed
1973
+ * input. The shape is decoded once per level with a `Schema.Struct`
1974
+ * (`errors: "all"`, so every issue on an entry is reported at once, and
1975
+ * `onExcessProperty: "error"`, so a typo'd key is named rather than
1976
+ * dropped); the message is `defineConfig: schema "<name>" ` followed by the
1977
+ * decode issues (`Expected string at ["baseUrl"]`). After a shape-clean
1978
+ * decode the cross-field rules run: the entry's identity — its
1979
+ * {@link HostedSchema}, or one built from `baseUrl`/`versions`/`current`/
1980
+ * `layout` and the config default — is validated by `HostedSchema` itself
1981
+ * (a `hosted` entry must be keyed by `hosted.name` and must not spell those
1982
+ * four fields beside it); a schema key must be a simple file base name; a
1983
+ * `catalog` is required under `baseUrl: "schemastore"`; an empty `schemas`
1984
+ * record is rejected; and an output path (a target, a frozen file, or the
1985
+ * catalog path) declared twice is rejected after a lexical normalisation
1986
+ * (`./`, `..`, trailing `/`) — the CLI's loader re-checks on the resolved
1987
+ * absolute paths. Branding the result lets a loader recognise a config
1988
+ * module's default export via {@link isSchemastoreConfig}.
1855
1989
  *
1856
1990
  * @public
1857
1991
  */
@@ -1864,5 +1998,5 @@ export declare const defineConfig: (input: SchemastoreConfigInput) => Schemastor
1864
1998
  */
1865
1999
  export declare const isSchemastoreConfig: (value: unknown) => value is SchemastoreConfig;
1866
2000
  //#endregion
1867
- export type { CanonicalJsonError, CanonicalJsonOptions, CatalogInput, CatalogUrls, CheckResult, ContractChangePolicy, DriftOptions, DriftTolerance, DriftVerdict, FrozenVersion, OnDrift, PipelineCheckResult, PipelineResult, ResolvedSchema, SchemaChange, SchemaEntryInput, SchemaFileShape, SchemaLayout, SchemaPipelineOptions, SchemaValidatorOptions, SchemaValidatorShape, SchemaWriteOptions, SchemastoreConfig, SchemastoreConfigInput, StoreDocumentOptions, WriteChange, WriteOutcome, WriteResult };
2001
+ 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 };
1868
2002
  //# sourceMappingURL=index.d.ts.map
package/index.js CHANGED
@@ -5,11 +5,12 @@ import { KeywordFamilies } from "./KeywordFamilies.js";
5
5
  import { DocumentDiff } from "./DocumentDiff.js";
6
6
  import { DocumentLint, DocumentLintFinding } from "./DocumentLint.js";
7
7
  import { DriftPolicy } from "./DriftPolicy.js";
8
+ import { HostedSchema, SCHEMASTORE_CATALOG_BASE, SCHEMASTORE_ID_BASE } from "./HostedSchema.js";
8
9
  import { SchemaFile, SchemaFileNotFoundError, SchemaFileReadError, SchemaFileWriteError } from "./SchemaFile.js";
9
10
  import { SchemaValidator, SchemaValidatorError, ValidationFinding } from "./SchemaValidator.js";
10
11
  import { DRAFT_07_META_SCHEMA, SchemaConversionError, StoreDocument, UndeclaredAnnotationKeyError } from "./StoreDocument.js";
11
12
  import { ContractChangeTarget, PipelineFinding, SchemaContractChangeError, SchemaGateError, SchemaPipeline } from "./SchemaPipeline.js";
12
13
  import { SchemaTarget } from "./SchemaTarget.js";
13
- import { SCHEMASTORE_CATALOG_BASE, SCHEMASTORE_ID_BASE, defineConfig, isSchemastoreConfig } from "./SchemastoreConfig.js";
14
+ import { defineConfig, isSchemastoreConfig } from "./SchemastoreConfig.js";
14
15
 
15
- export { CanonicalJson, CatalogEntry, CatalogLintFinding, ContractChangeTarget, DRAFT_07_META_SCHEMA, DocumentDiff, DocumentLint, DocumentLintFinding, DriftPolicy, 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 };
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 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effected/schemastore",
3
- "version": "0.11.0",
3
+ "version": "0.12.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": [
@@ -38,9 +38,7 @@
38
38
  "./package.json": "./package.json"
39
39
  },
40
40
  "dependencies": {
41
- "@effected/semver": "^0.7.0",
42
- "ajv": "^8.20.0",
43
- "ajv-formats": "^3.0.1"
41
+ "@effected/semver": "^0.7.0"
44
42
  },
45
43
  "peerDependencies": {
46
44
  "effect": "4.0.0-rc.115"