@nekostack/schema 1.0.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/CHANGELOG.md +422 -0
- package/LICENSE +202 -0
- package/README.md +656 -0
- package/dist/src/builders/array.d.ts +12 -0
- package/dist/src/builders/array.d.ts.map +1 -0
- package/dist/src/builders/array.js +29 -0
- package/dist/src/builders/array.js.map +1 -0
- package/dist/src/builders/object.d.ts +62 -0
- package/dist/src/builders/object.d.ts.map +1 -0
- package/dist/src/builders/object.js +263 -0
- package/dist/src/builders/object.js.map +1 -0
- package/dist/src/builders/primitives.d.ts +37 -0
- package/dist/src/builders/primitives.d.ts.map +1 -0
- package/dist/src/builders/primitives.js +125 -0
- package/dist/src/builders/primitives.js.map +1 -0
- package/dist/src/builders/s.d.ts +27 -0
- package/dist/src/builders/s.d.ts.map +1 -0
- package/dist/src/builders/s.js +39 -0
- package/dist/src/builders/s.js.map +1 -0
- package/dist/src/builders/schema.d.ts +70 -0
- package/dist/src/builders/schema.d.ts.map +1 -0
- package/dist/src/builders/schema.js +98 -0
- package/dist/src/builders/schema.js.map +1 -0
- package/dist/src/cli-integration.d.ts +43 -0
- package/dist/src/cli-integration.d.ts.map +1 -0
- package/dist/src/cli-integration.js +48 -0
- package/dist/src/cli-integration.js.map +1 -0
- package/dist/src/errors/issue.d.ts +34 -0
- package/dist/src/errors/issue.d.ts.map +1 -0
- package/dist/src/errors/issue.js +89 -0
- package/dist/src/errors/issue.js.map +1 -0
- package/dist/src/generators/errors.d.ts +31 -0
- package/dist/src/generators/errors.d.ts.map +1 -0
- package/dist/src/generators/errors.js +34 -0
- package/dist/src/generators/errors.js.map +1 -0
- package/dist/src/generators/header.d.ts +42 -0
- package/dist/src/generators/header.d.ts.map +1 -0
- package/dist/src/generators/header.js +43 -0
- package/dist/src/generators/header.js.map +1 -0
- package/dist/src/generators/json-schema-meta.d.ts +36 -0
- package/dist/src/generators/json-schema-meta.d.ts.map +1 -0
- package/dist/src/generators/json-schema-meta.js +35 -0
- package/dist/src/generators/json-schema-meta.js.map +1 -0
- package/dist/src/generators/json-schema.d.ts +26 -0
- package/dist/src/generators/json-schema.d.ts.map +1 -0
- package/dist/src/generators/json-schema.js +88 -0
- package/dist/src/generators/json-schema.js.map +1 -0
- package/dist/src/generators/openapi.d.ts +33 -0
- package/dist/src/generators/openapi.d.ts.map +1 -0
- package/dist/src/generators/openapi.js +61 -0
- package/dist/src/generators/openapi.js.map +1 -0
- package/dist/src/generators/schema-fragment.d.ts +55 -0
- package/dist/src/generators/schema-fragment.d.ts.map +1 -0
- package/dist/src/generators/schema-fragment.js +253 -0
- package/dist/src/generators/schema-fragment.js.map +1 -0
- package/dist/src/generators/ts.d.ts +19 -0
- package/dist/src/generators/ts.d.ts.map +1 -0
- package/dist/src/generators/ts.js +252 -0
- package/dist/src/generators/ts.js.map +1 -0
- package/dist/src/generators/types.d.ts +96 -0
- package/dist/src/generators/types.d.ts.map +1 -0
- package/dist/src/generators/types.js +10 -0
- package/dist/src/generators/types.js.map +1 -0
- package/dist/src/generators/version.d.ts +11 -0
- package/dist/src/generators/version.d.ts.map +1 -0
- package/dist/src/generators/version.js +11 -0
- package/dist/src/generators/version.js.map +1 -0
- package/dist/src/generators/zod-mapping.d.ts +90 -0
- package/dist/src/generators/zod-mapping.d.ts.map +1 -0
- package/dist/src/generators/zod-mapping.js +174 -0
- package/dist/src/generators/zod-mapping.js.map +1 -0
- package/dist/src/generators/zod.d.ts +17 -0
- package/dist/src/generators/zod.d.ts.map +1 -0
- package/dist/src/generators/zod.js +118 -0
- package/dist/src/generators/zod.js.map +1 -0
- package/dist/src/index.d.ts +21 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +43 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/ir/hash.d.ts +19 -0
- package/dist/src/ir/hash.d.ts.map +1 -0
- package/dist/src/ir/hash.js +22 -0
- package/dist/src/ir/hash.js.map +1 -0
- package/dist/src/ir/nodes.d.ts +121 -0
- package/dist/src/ir/nodes.d.ts.map +1 -0
- package/dist/src/ir/nodes.js +14 -0
- package/dist/src/ir/nodes.js.map +1 -0
- package/dist/src/ir/serialize.d.ts +8 -0
- package/dist/src/ir/serialize.d.ts.map +1 -0
- package/dist/src/ir/serialize.js +23 -0
- package/dist/src/ir/serialize.js.map +1 -0
- package/dist/src/migrations/build-migration-registry.d.ts +46 -0
- package/dist/src/migrations/build-migration-registry.d.ts.map +1 -0
- package/dist/src/migrations/build-migration-registry.js +134 -0
- package/dist/src/migrations/build-migration-registry.js.map +1 -0
- package/dist/src/migrations/handlers/list.d.ts +35 -0
- package/dist/src/migrations/handlers/list.d.ts.map +1 -0
- package/dist/src/migrations/handlers/list.js +55 -0
- package/dist/src/migrations/handlers/list.js.map +1 -0
- package/dist/src/migrations/handlers/plan.d.ts +26 -0
- package/dist/src/migrations/handlers/plan.d.ts.map +1 -0
- package/dist/src/migrations/handlers/plan.js +28 -0
- package/dist/src/migrations/handlers/plan.js.map +1 -0
- package/dist/src/migrations/handlers/stub.d.ts +22 -0
- package/dist/src/migrations/handlers/stub.d.ts.map +1 -0
- package/dist/src/migrations/handlers/stub.js +24 -0
- package/dist/src/migrations/handlers/stub.js.map +1 -0
- package/dist/src/migrations/handlers/verify.d.ts +25 -0
- package/dist/src/migrations/handlers/verify.d.ts.map +1 -0
- package/dist/src/migrations/handlers/verify.js +27 -0
- package/dist/src/migrations/handlers/verify.js.map +1 -0
- package/dist/src/migrations/parse-provenance.d.ts +78 -0
- package/dist/src/migrations/parse-provenance.d.ts.map +1 -0
- package/dist/src/migrations/parse-provenance.js +157 -0
- package/dist/src/migrations/parse-provenance.js.map +1 -0
- package/dist/src/migrations/plan-migration.d.ts +50 -0
- package/dist/src/migrations/plan-migration.d.ts.map +1 -0
- package/dist/src/migrations/plan-migration.js +256 -0
- package/dist/src/migrations/plan-migration.js.map +1 -0
- package/dist/src/migrations/stub.d.ts +55 -0
- package/dist/src/migrations/stub.d.ts.map +1 -0
- package/dist/src/migrations/stub.js +201 -0
- package/dist/src/migrations/stub.js.map +1 -0
- package/dist/src/migrations/types.d.ts +297 -0
- package/dist/src/migrations/types.d.ts.map +1 -0
- package/dist/src/migrations/types.js +28 -0
- package/dist/src/migrations/types.js.map +1 -0
- package/dist/src/migrations/verify-provenance.d.ts +46 -0
- package/dist/src/migrations/verify-provenance.d.ts.map +1 -0
- package/dist/src/migrations/verify-provenance.js +158 -0
- package/dist/src/migrations/verify-provenance.js.map +1 -0
- package/dist/src/registry/build-registry.d.ts +65 -0
- package/dist/src/registry/build-registry.d.ts.map +1 -0
- package/dist/src/registry/build-registry.js +172 -0
- package/dist/src/registry/build-registry.js.map +1 -0
- package/dist/src/registry/diff.d.ts +25 -0
- package/dist/src/registry/diff.d.ts.map +1 -0
- package/dist/src/registry/diff.js +497 -0
- package/dist/src/registry/diff.js.map +1 -0
- package/dist/src/registry/handlers/check.d.ts +57 -0
- package/dist/src/registry/handlers/check.d.ts.map +1 -0
- package/dist/src/registry/handlers/check.js +181 -0
- package/dist/src/registry/handlers/check.js.map +1 -0
- package/dist/src/registry/handlers/diff.d.ts +33 -0
- package/dist/src/registry/handlers/diff.d.ts.map +1 -0
- package/dist/src/registry/handlers/diff.js +61 -0
- package/dist/src/registry/handlers/diff.js.map +1 -0
- package/dist/src/registry/handlers/generate.d.ts +87 -0
- package/dist/src/registry/handlers/generate.d.ts.map +1 -0
- package/dist/src/registry/handlers/generate.js +223 -0
- package/dist/src/registry/handlers/generate.js.map +1 -0
- package/dist/src/registry/handlers/list.d.ts +36 -0
- package/dist/src/registry/handlers/list.d.ts.map +1 -0
- package/dist/src/registry/handlers/list.js +84 -0
- package/dist/src/registry/handlers/list.js.map +1 -0
- package/dist/src/registry/parse-provenance.d.ts +63 -0
- package/dist/src/registry/parse-provenance.d.ts.map +1 -0
- package/dist/src/registry/parse-provenance.js +182 -0
- package/dist/src/registry/parse-provenance.js.map +1 -0
- package/dist/src/registry/source-hash.d.ts +28 -0
- package/dist/src/registry/source-hash.d.ts.map +1 -0
- package/dist/src/registry/source-hash.js +32 -0
- package/dist/src/registry/source-hash.js.map +1 -0
- package/dist/src/registry/types.d.ts +185 -0
- package/dist/src/registry/types.d.ts.map +1 -0
- package/dist/src/registry/types.js +22 -0
- package/dist/src/registry/types.js.map +1 -0
- package/dist/src/runtime/compile.d.ts +38 -0
- package/dist/src/runtime/compile.d.ts.map +1 -0
- package/dist/src/runtime/compile.js +45 -0
- package/dist/src/runtime/compile.js.map +1 -0
- package/dist/src/runtime/errors.d.ts +25 -0
- package/dist/src/runtime/errors.d.ts.map +1 -0
- package/dist/src/runtime/errors.js +43 -0
- package/dist/src/runtime/errors.js.map +1 -0
- package/dist/src/runtime/normalize-issues.d.ts +65 -0
- package/dist/src/runtime/normalize-issues.d.ts.map +1 -0
- package/dist/src/runtime/normalize-issues.js +208 -0
- package/dist/src/runtime/normalize-issues.js.map +1 -0
- package/dist/src/runtime/parse.d.ts +62 -0
- package/dist/src/runtime/parse.d.ts.map +1 -0
- package/dist/src/runtime/parse.js +107 -0
- package/dist/src/runtime/parse.js.map +1 -0
- package/dist/src/runtime/strip-defaults.d.ts +51 -0
- package/dist/src/runtime/strip-defaults.d.ts.map +1 -0
- package/dist/src/runtime/strip-defaults.js +81 -0
- package/dist/src/runtime/strip-defaults.js.map +1 -0
- package/dist/src/runtime/zod-compile.d.ts +27 -0
- package/dist/src/runtime/zod-compile.d.ts.map +1 -0
- package/dist/src/runtime/zod-compile.js +92 -0
- package/dist/src/runtime/zod-compile.js.map +1 -0
- package/dist/src/types.d.ts +116 -0
- package/dist/src/types.d.ts.map +1 -0
- package/dist/src/types.js +2 -0
- package/dist/src/types.js.map +1 -0
- package/docs/ABSENCE_SEMANTICS.md +37 -0
- package/docs/BENCHMARKS.md +64 -0
- package/docs/COMPOSITION.md +206 -0
- package/docs/DIFF_CLASSIFICATION.md +137 -0
- package/docs/EXAMPLES.md +221 -0
- package/docs/HEADER_FORMAT.md +66 -0
- package/docs/INVARIANTS.md +58 -0
- package/docs/IR_CONTRACT.md +67 -0
- package/docs/ISSUE_CODES.md +99 -0
- package/docs/JSON_SCHEMA_MAPPING.md +149 -0
- package/docs/MIGRATIONS.md +406 -0
- package/docs/MIGRATION_GUIDE.md +150 -0
- package/docs/OPENAPI_MAPPING.md +66 -0
- package/docs/REGISTRY.md +336 -0
- package/docs/RUNTIME.md +279 -0
- package/docs/SCOPE.md +119 -0
- package/docs/USAGE.md +376 -0
- package/docs/ZOD_MODIFIER_ORDERING.md +77 -0
- package/package.json +45 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,422 @@
|
|
|
1
|
+
# `@nekostack/schema` — Changelog
|
|
2
|
+
|
|
3
|
+
Per-milestone changes. Pairs with the git tags (`schema-vX.Y.Z`) and the [GitHub releases](https://github.com/cmclicker/NekoStack/releases). Format: newest first.
|
|
4
|
+
|
|
5
|
+
Published to npm as `@nekostack/schema` (Apache-2.0). Milestone identifiers pair with the git tags (`schema-vX.Y.Z`).
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## schema-v1.0.0 — 2026-06-19
|
|
10
|
+
|
|
11
|
+
First stable release. **Public API frozen.** No source changes from v0.8.0 — this milestone freezes the exported surface and ships release metadata (Apache-2.0 license; the `nekostack` metapackage).
|
|
12
|
+
|
|
13
|
+
### Test count
|
|
14
|
+
|
|
15
|
+
- 1294 passing
|
|
16
|
+
|
|
17
|
+
### Frozen surface
|
|
18
|
+
|
|
19
|
+
- Builders, modifiers, portable refinements, composition, the four generators (TS / Zod / JSON Schema / OpenAPI), and runtime `parse` / `safeParse` / `validate`.
|
|
20
|
+
- 1,294 tests passing; `tsc -b` clean.
|
|
21
|
+
- `zod` is now a **peerDependency** (one shared instance) — consumers provide it.
|
|
22
|
+
|
|
23
|
+
### Reserved for post-1.0
|
|
24
|
+
|
|
25
|
+
- Unions, `lazy` / recursive refs, transforms, and date types are reserved IR capacity with no shipped builders. They arrive in post-1.0 minors and do not affect the frozen surface.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## schema-v0.8.0 — 2026-05-20
|
|
30
|
+
|
|
31
|
+
[Tag](https://github.com/cmclicker/NekoStack/releases/tag/schema-v0.8.0) · merge commit [`ec742e8`](https://github.com/cmclicker/NekoStack/commit/ec742e894c499a282b855374dbe2f20a927dfdb4). Schema-data migration planning + provenance verification + stub generation. Joint schema + CLI phase; v0.8 primitives ship under this tag alongside the four `neko schema migrate *` verbs.
|
|
32
|
+
|
|
33
|
+
### Shipped
|
|
34
|
+
|
|
35
|
+
- **Hard-locked v0.8 boundary** — schema-data migration *planning*, *verification*, and *stub generation* only. **No `apply` verb. No `migration.transform` execution. No data mutation. No rollback. No DDL migrations.** Enforced by cross-cutting `.transform(` static-scan gates on both the schema-side handler reach and the CLI command surface (`cli.ts` + every file under `src/commands/schema/migrate/`).
|
|
36
|
+
- **Migration type surface** — `Migration<SchemaId, FromVersion, ToVersion, Input, Output>`, `MigrationSourceEntry`, `MigrationEntry`, `MigrationRegistry` (three-level `(schemaId → fromVersion → toVersion)` Map), `MigrationPlan`, `PlanNote` (`over_specified` / `additive_no_migration`), `MigrationVerdict` (four-way), `VerificationResult`, `MigrationStub`, plus four `*Opts`/`*Result` pairs.
|
|
37
|
+
- **`parseMigrationProvenanceFromText`** — JSDoc-only carrier; 9 required fields (`schemaId`, `fromVersion`, `toVersion`, `fromIrHash`, `toIrHash`, `fromSourceHash`, `toSourceHash`, `generator`, `generatorVersion`). Fail-loud `integrity_error` + stable `metadata.reason` (`unknown_format` / `missing_migration_provenance` / `missing_field` / `malformed_hash` / `malformed_field`); never silently skips.
|
|
38
|
+
- **`buildMigrationRegistry`** — pure constructor with first-seen-wins duplicate handling; `duplicate_migration` Issues collected without short-circuit; preserves `MigrationEntry` and `AnyMigration` object identity.
|
|
39
|
+
- **`planMigration({ schemaRegistry, migrationRegistry, schemaId, fromVersion, toVersion })`** — diff-aware planner consuming **both** registries (Round-3 contract). Severity-gated chain requirement: null/cosmetic → empty chain (`over_specified` note when an exact migration is registered); additive → empty + `additive_no_migration` note OR include exact migration; breaking → DFS chain enumeration with `migration_not_found` / `migration_chain_broken` / `migration_ambiguous_chain` on the four failure shapes.
|
|
40
|
+
- **`verifyMigrationProvenance({ schemaRegistry, migrationRegistry })`** — four-way verdict matrix mirroring v0.7's two-hash freshness: `bound` / `cosmetic_drift` / `drift` / `missing_endpoint`. `bound` and `cosmetic_drift` are success-compatible (`cosmetic_drift` is warning-class); `drift` and `missing_endpoint` are failure-class. Deterministic iteration sorted by `(schemaId, fromVersion, toVersion)`.
|
|
41
|
+
- **`stubMigration` + `suggestedMigrationPathFor`** — pure file-content generator emitting the 9-field provenance header + `import type { Migration } from "@nekostack/schema/cli"` + typed declaration + `transform(input) { throw "Not yet implemented" }` body + default export. Slug rule reuses v0.7's `suggestedPathFor` shape.
|
|
42
|
+
- **Four pure handlers** — `listMigrationsHandler`, `planMigrationHandler`, `verifyMigrationsHandler`, `stubMigrationHandler`. Data-in / data-out; never touch the filesystem; never call `.transform(`. Gated by [`tests/migrations/handler-purity.test.ts`](tests/migrations/handler-purity.test.ts) (static-import scan over 9 modules × 12 forbidden patterns + 15 sentinel rows).
|
|
43
|
+
- **`@nekostack/schema/cli` subpath extension** — 10 runtime + 18 type names exposed for `@nekostack/cli` consumption. Root `@nekostack/schema` remains unchanged from v0.6 / v0.7; negative-leakage gate at [`tests/public-surface.test.ts`](tests/public-surface.test.ts) enforces zero v0.8 names on the root surface (10 runtime forbidden + 18 `@ts-expect-error` type rows).
|
|
44
|
+
- **CLI-side** — `read-migrations` loader (discovers `*.migration.ts` via shared `tsx` ESM hook; structural default-export validation; never calls `transform`); four `neko schema migrate *` verbs:
|
|
45
|
+
- `neko schema migrate list`
|
|
46
|
+
- `neko schema migrate plan <schemaId> <fromVersion> <toVersion>`
|
|
47
|
+
- `neko schema migrate verify`
|
|
48
|
+
- `neko schema migrate stub <schemaId> <fromVersion> <toVersion>`
|
|
49
|
+
All four accept `--root` / `--json` / `--quiet`. **No `neko schema migrate apply` command. No `--force` flag. `stub` refuses to overwrite an existing file** (`stub_path_exists` failure → `LOGICAL_FAILURE`; existing content preserved byte-identically).
|
|
50
|
+
- **New ISSUE_CODES** — `duplicate_migration`, `migration_missing_endpoint`, `migration_not_found`, `migration_chain_broken`, `migration_ambiguous_chain`, `migration_drift`, `migration_cosmetic_drift` — added at first-use sites per the locked change-control rule.
|
|
51
|
+
- **`GENERATOR_VERSION` bumped to `@nekostack/schema@0.8.0`** — 47 snapshot files + 12 example artifacts regenerated. Diff was version-string-only.
|
|
52
|
+
|
|
53
|
+
### New contract docs
|
|
54
|
+
|
|
55
|
+
- [`docs/MIGRATIONS.md`](docs/MIGRATIONS.md) — full v0.8 contract: hard-locked boundary, 9-field provenance header, registry semantics, planner severity dispatch table, verifier verdict matrix, stub contract, schema/CLI ownership, explicit non-goals.
|
|
56
|
+
- [`docs/PHASE_PLAN_v0.8.md`](docs/PHASE_PLAN_v0.8.md) — locked sequencing for the 29-step implementation.
|
|
57
|
+
|
|
58
|
+
### Invariants
|
|
59
|
+
|
|
60
|
+
Seven new v0.8 corollaries in [`docs/INVARIANTS.md`](docs/INVARIANTS.md): no-apply/no-transform-execution boundary; subpath gate extends to v0.8 names; forward-only + one-schemaId-per-migration; fail-loud provenance; four-way verifier matrix mirrors freshness; planner consumes both registries; pure migration handlers. Plus two v0.8-specific corollaries: **migrations are append-only** (frozen historical records; in-place rewrites surface as `drift` / `cosmetic_drift` via the verifier) and **migration files are content-addressed by `(fromIrHash, toIrHash)`** (semantic binding by IR-hash pair; `(fromSourceHash, toSourceHash)` layered on top for literal-source drift).
|
|
61
|
+
|
|
62
|
+
### Docs sweep
|
|
63
|
+
|
|
64
|
+
[`SCOPE.md`](docs/SCOPE.md), [`INVARIANTS.md`](docs/INVARIANTS.md), [`ROADMAP.md`](docs/ROADMAP.md), [`USAGE.md`](docs/USAGE.md), [`EXAMPLES.md`](docs/EXAMPLES.md), and repo-root [`BOUNDARIES.md`](../../BOUNDARIES.md) all updated to reflect the v0.8 surface and locked non-goals.
|
|
65
|
+
|
|
66
|
+
### Dependency changes
|
|
67
|
+
|
|
68
|
+
None. No new runtime deps in either `@nekostack/schema` or `@nekostack/cli`.
|
|
69
|
+
|
|
70
|
+
### Test count
|
|
71
|
+
|
|
72
|
+
- 871 → 1292 (+421 net, schema-only). CLI: 327 → 504 (+177 net, including 24+30+29+24 per-verb command tests + dispatch + envelope hardening). Workspace-wide schema + CLI total is 1,796.
|
|
73
|
+
|
|
74
|
+
### Still deferred
|
|
75
|
+
|
|
76
|
+
- **Migration `apply` / runner / executor** — explicit non-goal of the v0.8 schema-package contract; no schema-package verb runs `transform(input)` against real data. If a future runner exists, it lives in a downstream package, never in `@nekostack/schema`.
|
|
77
|
+
- **Rollback / reverse migrations** — Decision #2 (forward-only) is locked.
|
|
78
|
+
- **Cross-schema migrations** — Decision #4 (exactly one `schemaId` per authored migration) is locked.
|
|
79
|
+
- **Database / DDL migrations** — `@nekostack/migrate`'s concern.
|
|
80
|
+
- **Date / union / recursiveRef / transform IR** — still throws `UnsupportedNodeKindError` from generators, `diffNodes`, and the diff path inside `planMigration`.
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## schema-v0.7.0 — 2026-05-19
|
|
85
|
+
|
|
86
|
+
[Tag](https://github.com/cmclicker/NekoStack/releases/tag/schema-v0.7.0) · merge commit [`931aa15`](https://github.com/cmclicker/NekoStack/commit/931aa15048f74942a21406ad885283c50da07631). Registry-lite + `neko schema *`. Joint schema + CLI phase; the schema-side primitives ship under this tag and the first real implementation of [`@nekostack/cli`](../cli) ships alongside.
|
|
87
|
+
|
|
88
|
+
### Shipped
|
|
89
|
+
|
|
90
|
+
- **`@nekostack/schema/cli` integration subpath** — wired through the `package.json` `exports` map. Exposes the registry primitives, four pure handlers, two-hash provenance helpers, and the full registry / diff / freshness / generation type surface to `@nekostack/cli`. **External consumers should not import from this path; it is subject to internal change.** The root `@nekostack/schema` import surface is unchanged from v0.6 and does not carry any v0.7 registry name — engine-swap-safety holds.
|
|
91
|
+
- **Decision #1 — pure handler boundary** — `listHandler`, `diffHandler`, `checkHandler`, `generateHandler` are data-in / data-out. No `fs.*`, no dynamic `import()`, no `process.*`, no `console.*`. Gated by [`tests/registry/handler-purity.test.ts`](tests/registry/handler-purity.test.ts) — hybrid static-file-level import scan plus runtime spies for `console.*` / `process.exit` / `process.abort` over each handler's full module-graph reach.
|
|
92
|
+
- **Decision #6 — locked artifact path convention** — `<schema-dir>/generated/<basename>[.<discriminator>].<artifact-kind>`. Multi-schema source files gain a slugged `schemaId` discriminator; same-id-multiple-versions auto-promotes to a version-suffixed slug. **Partial generation is not supported in v0.7** — `generateHandler` emits all four artifact kinds per named schema and `checkHandler` expects all four.
|
|
93
|
+
- **Decision #8 — `sourceHash` provenance is opt-in** — `ProvenanceOptions.sourceHash` slice on every generator. Omitted callers continue to produce byte-identical pre-v0.7 output. A v0.6-era artifact missing `sourceHash` is **never** an integrity error — `parseProvenanceFromText` returns `sourceHash: undefined` and `checkHandler` falls back to the irHash-only verdict. Backward compatibility is gated by every v0.2–v0.6 snapshot test, all of which stayed byte-identical post-introduction.
|
|
94
|
+
- **Decision #10 — `@nekostack/schema/cli` subpath is the only entry point** — both directions of the boundary are gated: [`tests/registry-surface.test.ts`](tests/registry-surface.test.ts) asserts the subpath positively exposes the surface; [`tests/public-surface.test.ts`](tests/public-surface.test.ts) asserts root `@nekostack/schema` exports none of the 11 v0.7 runtime names or 18 v0.7 types.
|
|
95
|
+
- **Decision #11 / #12 / #13 — diff classifier** — `diffNodes(before, after): readonly DiffChange[]` walks two `SchemaNode` trees per the locked Decision #12 classification table. Severity uses the **input-acceptance lens** (would data the old schema accepted still pass the new schema?). `diffHandler` adds `worstSeverity` aggregation with precedence `breaking > additive > cosmetic` and `null` for empty change lists. A `schemaVersion`-only change is cosmetic; paired with structural changes it inherits the worst structural severity.
|
|
96
|
+
- **Decision #14 — fail-loud on unsupported IR** — `diffNodes` throws `UnsupportedNodeKindError({ generator: "diff", kind })` for `date` / `union` / `recursiveRef` / `transform`. Same fail-loud discipline as the v0.3 / v0.6 generators.
|
|
97
|
+
- **Registry primitives** — `buildRegistry(entries): Result<Registry>` (pure; duplicate `(schemaId, version)` pairs surfaced as `duplicate_schema_id` Issues; never throws); `findSchema(registry, id, version?)` (exact match when version is given; highest-semver fallback when omitted; versioned wins over unversioned; empty-string inner key addresses unversioned schemas exactly).
|
|
98
|
+
- **Provenance parser** — `parseProvenanceFromText(text)` auto-detects JSDoc-header and `x-nekostack` carriers, validates `sha256:<64-hex>` shape, returns `Result<ParsedProvenance>`. Failures use the existing `integrity_error` code with `metadata.reason` (`unknown_format` / `missing_provenance` / `missing_field` / `malformed_hash` / `json_parse_error` / `malformed_field`); no new code invented.
|
|
99
|
+
- **Two-hash freshness matrix** (Decision #7 realized) — `clean` / `cosmetic_drift` / `stale` / `integrity_error`. The impossible row (sourceHash matches + irHash differs) means a hand-edited artifact or tampered provenance; the CLI exits 4 and refuses to auto-regenerate.
|
|
100
|
+
- **New ISSUE_CODES** — `integrity_error`, `duplicate_schema_id`, `schema_not_found`, `version_not_found` added per the locked change-control rule, each at its first use site.
|
|
101
|
+
- **`GENERATOR_VERSION` bumped to `@nekostack/schema@0.7.0`** — 59 generator snapshots + 12 example artifacts regenerated. Example artifacts also gain `sourceHash` provenance (the regen test reads each schema's UTF-8 source and threads `sourceHashFromText` through `ProvenanceOptions`).
|
|
102
|
+
|
|
103
|
+
### New contract docs
|
|
104
|
+
|
|
105
|
+
- [`docs/REGISTRY.md`](docs/REGISTRY.md) — schema/CLI ownership boundary, registry shapes, two-hash discipline, handler contracts, locked path convention, multi-schema disambiguation, `/cli` subpath visibility.
|
|
106
|
+
- [`docs/DIFF_CLASSIFICATION.md`](docs/DIFF_CLASSIFICATION.md) — input-acceptance lens, three severity values, `worstSeverity` aggregation rule, every locked classification row, `schemaVersion` aggregation nuance, `UnsupportedNodeKindError` boundary, migrations deferred to v0.8+.
|
|
107
|
+
|
|
108
|
+
### Five new INVARIANTS corollaries
|
|
109
|
+
|
|
110
|
+
Registry collision is an error (`duplicate_schema_id`); pure handlers (no fs/import/process/console); subpath boundary (both directions gated); two-hash freshness discipline (matrix locked; v0.6 backward compatibility codified); diff classification (input-acceptance lens; `worstSeverity` precedence; fail-loud on unsupported IR).
|
|
111
|
+
|
|
112
|
+
### Docs sweep
|
|
113
|
+
|
|
114
|
+
[`SCOPE.md`](docs/SCOPE.md), [`INVARIANTS.md`](docs/INVARIANTS.md), [`ROADMAP.md`](docs/ROADMAP.md), [`USAGE.md`](docs/USAGE.md), [`EXAMPLES.md`](docs/EXAMPLES.md) all updated. Repo-root [`BOUNDARIES.md`](../../BOUNDARIES.md) §7 refined: local registry, diff classification, freshness verdict, and generation planning attributed to `schema`; CLI orchestration row attributed to `cli`.
|
|
115
|
+
|
|
116
|
+
### Dependency changes
|
|
117
|
+
|
|
118
|
+
None. No new runtime deps in `@nekostack/schema`. The CLI's new `commander` and `tsx` deps are isolated to `@nekostack/cli`.
|
|
119
|
+
|
|
120
|
+
### Test count
|
|
121
|
+
|
|
122
|
+
- 587 → 871 (+284 net, schema-only). Workspace-wide (schema + cli) total is 1,177.
|
|
123
|
+
|
|
124
|
+
### Still deferred
|
|
125
|
+
|
|
126
|
+
- Migrations (registry, forward migrations, pre/post validation, audit) — v0.8+.
|
|
127
|
+
- Partial artifact-kind generation — explicitly out of scope; locked by Decision #6.
|
|
128
|
+
- Date / union / recursiveRef / transform IR — still throws `UnsupportedNodeKindError` from generators and from `diffNodes`.
|
|
129
|
+
- Runtime refinement execution — IR shape declared; runtime fails loud.
|
|
130
|
+
- CLI plugin contract / additional `neko` command families — out of v0.7.
|
|
131
|
+
|
|
132
|
+
---
|
|
133
|
+
|
|
134
|
+
## schema-v0.6.0 — 2026-05-18
|
|
135
|
+
|
|
136
|
+
[Tag](https://github.com/cmclicker/NekoStack/releases/tag/schema-v0.6.0) · merge commit [`c55ce95`](https://github.com/cmclicker/NekoStack/commit/c55ce952bc027b98cc1f4d270db4ec5b9e2b758d). Runtime validation as a NekoStack-owned workflow on the v0.2 source-generator + v0.5 composition foundation.
|
|
137
|
+
|
|
138
|
+
### Shipped
|
|
139
|
+
|
|
140
|
+
- **Runtime API on the package surface** — `parse(schema, input): s.output<S>` (throws `ParseError`), `safeParse(schema, input): Result<s.output<S>>`, `validate(schema, input): Result<s.input<S>>` (structural check; does NOT fill defaults; portable refinements still run). `ParseError extends Error` with `code: "parse_failed"` and a frozen `readonly issues: Issue[]`.
|
|
141
|
+
- **Engine-swap-safe boundary** — Zod is the internal execution engine. Consumers never import Zod for runtime validation. The public surface carries NekoStack types only (`Result`, `Issue`, `ParseError`), never a `ZodSchema` or `ZodError`. This is the [`PRODUCT_THESIS`](../../PRODUCT_THESIS.md) lens applied to validation.
|
|
142
|
+
- **Decision #6 shared semantic mapping** — `ZodEmitter<T>` / `emit<T>()` is the contract; the v0.2 string generator and the v0.6 value compiler are independent consumers. No `eval`, no source-to-value, no value-to-source. All v0.2 Zod source snapshots remain byte-identical post-extraction.
|
|
143
|
+
- **Decision #7 compile cache** — `WeakMap<SchemaNode, ZodTypeAny>` keyed on node identity; lazy first-call build; byte-identical IR with distinct node identity does NOT share (explicit dedup via `irHash` remains a v0.7 registry concern).
|
|
144
|
+
- **Decision #8 validate-only IR variant** — `stripDefaultsForValidate` drops `modifiers.default` and sets `modifiers.optional = true` at the same level; preserves `nullable` / refinements / metadata / `unknownKeys`. Cached per original-node identity in a separate `WeakMap` so repeated `validate(sameSchema, ...)` calls reuse both the variant and its compiled Zod.
|
|
145
|
+
- **Decision #12 issue normalization** — `ZodError → readonly Issue[]` per a locked mapping table; `unrecognized_keys` splits into one `unknown_key` issue per key. Round-2 fallback: unmapped Zod codes surface as `custom_refinement_failed` with `metadata.source = "zod"` and `metadata.zodCode = <original>` so triage never loses traceability.
|
|
146
|
+
- **Decision #19 four-oracle parity matrix** — NekoStack runtime / generated-Zod execution / Ajv 2020 over generated JSON Schema / small IR-walker. Compare-only contract: accept/reject. All four oracles agree on every fixture (primitives, literal/enum, arrays, object policies, absence semantics, full portable-refinement set).
|
|
147
|
+
- **Decision #19a OpenAPI spec-validity carry-forward** — Redocly validates that every runtime-supported schema still emits a clean OpenAPI 3.1 component. **Not** a runtime data oracle; the round-2 audit correction is permanent.
|
|
148
|
+
- **New contract doc** — [`docs/RUNTIME.md`](docs/RUNTIME.md) covering public API, default semantics, unknown-key policies, the issue normalization table, the engine boundary, the compile + validate-variant caches, semantic parity, unsupported behavior, and non-goals.
|
|
149
|
+
- **Six new INVARIANTS corollaries** — engine-swap-safe public surface, default-semantics split, `Issue[]` as the only public error vocabulary, cache invariance (`SchemaNode` identity), Redocly spec-validity-only role, fail-loud throws for unsupported runtime IR.
|
|
150
|
+
- **Docs sweep** — [`USAGE.md`](docs/USAGE.md), [`EXAMPLES.md`](docs/EXAMPLES.md), [`SCOPE.md`](docs/SCOPE.md), [`INVARIANTS.md`](docs/INVARIANTS.md), [`ROADMAP.md`](docs/ROADMAP.md), and [`BOUNDARIES.md`](../../BOUNDARIES.md) all reframed: runtime validation is the primary workflow, generators are the artifact / interoperability path.
|
|
151
|
+
- **`GENERATOR_VERSION` bumped to `@nekostack/schema@0.6.0`** — 59 snapshots regenerated; only the version field changed, `irHash` values unchanged.
|
|
152
|
+
- **Tooling alignment** — `scripts/generate-status.mjs` `parseActiveTarget` recognizes both `← *active target*` and `← *candidate implementation in progress*` so the status layer tracks candidate state without flagging false drift.
|
|
153
|
+
|
|
154
|
+
### Dependency changes
|
|
155
|
+
|
|
156
|
+
- **`zod` promoted from `peerDependenciesMeta.optional: true` to a regular `dependency`.** Range `^3.22.0` unchanged. Consumers no longer install or import Zod manually.
|
|
157
|
+
- `@redocly/openapi-core`, `ajv`, `ajv-formats` remain devDeps (used by the spec-validity and parity tests only).
|
|
158
|
+
- No other dep changes.
|
|
159
|
+
|
|
160
|
+
### Test count
|
|
161
|
+
|
|
162
|
+
- 342 → 587 (+245 net).
|
|
163
|
+
|
|
164
|
+
### Still deferred
|
|
165
|
+
|
|
166
|
+
- `neko schema generate / check / diff` CLI — v0.7
|
|
167
|
+
- `sourceHash` in headers — v0.7
|
|
168
|
+
- Local schema registry / freshness check — v0.7 (consumes the v0.2 `irHash`)
|
|
169
|
+
- Date / union / recursiveRef / transform IR runtime support
|
|
170
|
+
- Runtime refinement execution (IR shape declared; runtime currently throws `UnsupportedNodeKindError`)
|
|
171
|
+
- Method-style API (`schema.parse(input)`); v0.6 ships free functions only
|
|
172
|
+
- `ValidateError` companion to `ParseError`; `validate` returns `Result` only
|
|
173
|
+
- Locale / i18n of error messages
|
|
174
|
+
- Migrations between schema versions — v0.8+
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## schema-v0.5.0 — 2026-05-17
|
|
179
|
+
|
|
180
|
+
[Tag](https://github.com/cmclicker/NekoStack/releases/tag/schema-v0.5.0) · merge commit [`70f19e9`](https://github.com/cmclicker/NekoStack/commit/70f19e9). Composition layer on the v0.1 IR foundation.
|
|
181
|
+
|
|
182
|
+
### Shipped
|
|
183
|
+
|
|
184
|
+
- **Seven new methods on `ObjectSchema`** — `extend`, `pick`, `omit`, `partial`, `required`, `merge`, `override`. All return a new `ObjectSchema` (no mutation), drop top-level metadata, preserve field-level metadata, and fail loudly on collisions / unknown keys / missing keys / merge conflicts / `unknownKeys` mismatches.
|
|
185
|
+
- **`extend(E)`** throws on key collision. To replace deliberately, use `override`. To combine with explicit resolution, use `merge`.
|
|
186
|
+
- **`override(O)`** throws on key not in base. Accepts any schema type for the replacement — that's the whole point.
|
|
187
|
+
- **`partial(mask?)` and `required(mask?)`** are symmetric on `default` — both strip it. Rationale: in v0.1, `default(v)` means input-optional + output-required, so preserving `default` through `partial` would leave output required while claiming optional. Symmetric strip is the only self-consistent rule.
|
|
188
|
+
- **`merge(other, options?)`** has three overloads encoding the conflict policy at the type level (`MergeThrowShape` / `MergeLeftShape` / `MergeRightShape`). Throws by default on field conflict AND on `unknownKeys` mismatch. Two independent knobs: `conflict` and `unknownKeys`. `unknownKeys` mismatch is fail-loud because strict-vs-passthrough is a real validation-semantics policy, not cosmetic.
|
|
189
|
+
- **Three new public types**: `Mask<S>`, `OverrideMask<S>`, `MergeOptions`. Internal `*Shape` helpers stay package-internal.
|
|
190
|
+
- **New contract doc** — [`docs/COMPOSITION.md`](docs/COMPOSITION.md).
|
|
191
|
+
- **Two new INVARIANTS corollaries** — composition fail-loudly; composition strips top-level metadata.
|
|
192
|
+
- **`Schema.clone()` JSDoc** now documents the v0.5 subclass invariant: `clone(node)` must be a pure IR-replacement operation. Future Schema subclasses that violate this silently break `partial`/`required`'s field-modifier swapping.
|
|
193
|
+
- **`MergeThrowShape` is `Identity<S & Other>`** — preserves disjoint merges and lets TypeScript surface some conflicts through normal intersection behavior, but **runtime conflict detection is the load-bearing guarantee**.
|
|
194
|
+
- **Generator parity** — composition produces a plain `ObjectNode`; all four generators (TS / Zod / JSON Schema / OpenAPI) handle composed schemas byte-identically to hand-written equivalents (proven by a 7-operator × 4-generator parity matrix).
|
|
195
|
+
- **`GENERATOR_VERSION` bumped to `@nekostack/schema@0.5.0`** — 59 snapshots regenerated.
|
|
196
|
+
|
|
197
|
+
### Dependency changes
|
|
198
|
+
|
|
199
|
+
None. Pure-TS work on top of v0.1–v0.4.
|
|
200
|
+
|
|
201
|
+
### Test count
|
|
202
|
+
|
|
203
|
+
- 248 → 342 (+94 net).
|
|
204
|
+
|
|
205
|
+
### Still deferred
|
|
206
|
+
|
|
207
|
+
- Runtime `parse` / `validate` from this package — v0.6
|
|
208
|
+
- `neko schema generate / check / diff` CLI — v0.7
|
|
209
|
+
- `sourceHash` in headers — v0.7
|
|
210
|
+
- `$defs` extraction + cross-package `$ref` — v0.7 (registry-lite)
|
|
211
|
+
- Deep / recursive composition — future
|
|
212
|
+
- `merge` with `"merge"` mode (recursive type-union) — future
|
|
213
|
+
- Static `s.merge(A, B)` top-level form — future
|
|
214
|
+
- Migrations — v0.8+
|
|
215
|
+
- Zod 4 target — future generator option
|
|
216
|
+
|
|
217
|
+
---
|
|
218
|
+
|
|
219
|
+
## schema-v0.4.0 — 2026-05-17
|
|
220
|
+
|
|
221
|
+
[Tag](https://github.com/cmclicker/NekoStack/releases/tag/schema-v0.4.0) · merge commit [`c9d15d0`](https://github.com/cmclicker/NekoStack/commit/c9d15d0). Fourth generator on the v0.1 IR foundation.
|
|
222
|
+
|
|
223
|
+
### Shipped
|
|
224
|
+
|
|
225
|
+
- **`generateOpenApiSchemaComponent(node, options?)`** — emits a single OpenAPI 3.1 Schema Component (the value at `components.schemas.<Name>`). Canonical JSON. Not a full OpenAPI document — that belongs to a future `@nekostack/api`.
|
|
226
|
+
- **Shared `emitSchemaFragment`** — new [`src/generators/schema-fragment.ts`](src/generators/schema-fragment.ts) owns the IR-to-fragment translation. `json-schema.ts` and `openapi.ts` are now thin wrappers differing only on root structure, `$schema` / `$id`, and provenance `generator` value. Eliminates the JSON-Schema-vs-OpenAPI drift vector. Hard gate verified: v0.3 JSON Schema snapshots remained byte-identical through the extraction.
|
|
227
|
+
- **No `$schema`, no `$id`** in component-position output (Decision #5 — component identity is the position in the document).
|
|
228
|
+
- **`x-nekostack` provenance with `generator: "openApi"`** — `irHash` identical to the JSON Schema generator's for the same node (proven by test).
|
|
229
|
+
- **Throw contract** identical to v0.3: runtime refinements + regex-with-non-empty-flags throw `UnsupportedNodeKindError` with `generator: "openApi"`. Same stable `code` / `kind` / `generator` shape from v0.2.
|
|
230
|
+
- **`OpenApiGeneratorOptions = Record<string, never>`** — explicit no-options contract enforced at compile time. `@ts-expect-error`-backed test guards against regression. Widens to a richer interface when the first real option lands (likely `discriminator` with union builders).
|
|
231
|
+
- **`@redocly/openapi-core` round-trip tests** — every emitted component composed into a synthetic OpenAPI 3.1 document (with explicit `jsonSchemaDialect: "https://json-schema.org/draft/2020-12/schema"`) and validated clean. Per the v0.4 plan fallback, can switch to spawning the Redocly CLI if the programmatic API ever proves impractical.
|
|
232
|
+
- **Three new committed example artifacts** under [`examples/generated/`](examples/generated/): `tenant.openapi.json`, `audit-event.openapi.json`, `entitlement.openapi.json`.
|
|
233
|
+
- **New contract doc** — [`docs/OPENAPI_MAPPING.md`](docs/OPENAPI_MAPPING.md). Deliberately delta-only; everything else defers to `JSON_SCHEMA_MAPPING.md`.
|
|
234
|
+
- **Two new INVARIANTS corollaries** — "Redocly round-trip must pass" and "IR-to-fragment translation lives once in `schema-fragment.ts`; parallel implementations are explicitly rejected."
|
|
235
|
+
- **Stale-doc cleanups** — `src/index.ts` generator section phase-neutralized, `UnsupportedNodeKindError` JSDoc generator-neutralized.
|
|
236
|
+
- **`GENERATOR_VERSION` bumped to `@nekostack/schema@0.4.0`** — 56 snapshots regenerated; new artifact provenance lines match this milestone.
|
|
237
|
+
|
|
238
|
+
### Dependency changes
|
|
239
|
+
|
|
240
|
+
- New devDep: `@redocly/openapi-core ^1.34.0`. No new runtime dep.
|
|
241
|
+
|
|
242
|
+
### Test count
|
|
243
|
+
|
|
244
|
+
- 219 → 248 (+29 net).
|
|
245
|
+
|
|
246
|
+
### Still deferred
|
|
247
|
+
|
|
248
|
+
- Composition operators — v0.5
|
|
249
|
+
- Runtime `parse` / `validate` from this package — v0.6
|
|
250
|
+
- `neko schema generate / check / diff` CLI — v0.7
|
|
251
|
+
- `sourceHash` in headers — v0.7
|
|
252
|
+
- `$defs` extraction + cross-package `$ref` — v0.7 (registry-lite)
|
|
253
|
+
- Full OpenAPI documents (paths/operations/etc.) — `@nekostack/api`'s concern
|
|
254
|
+
- OpenAPI 3.0 target — future generator option
|
|
255
|
+
- `discriminator` keyword — needs union builders
|
|
256
|
+
- `example` / `xml` / `externalDocs` — no IR construct uses them
|
|
257
|
+
- Migrations — v0.8+
|
|
258
|
+
- Zod 4 target — future generator option
|
|
259
|
+
|
|
260
|
+
---
|
|
261
|
+
|
|
262
|
+
## schema-v0.3.0 — 2026-05-17
|
|
263
|
+
|
|
264
|
+
[Tag](https://github.com/cmclicker/NekoStack/releases/tag/schema-v0.3.0) · merge commit [`9c50364`](https://github.com/cmclicker/NekoStack/commit/9c50364). Third generator on the v0.1 IR foundation.
|
|
265
|
+
|
|
266
|
+
### Shipped
|
|
267
|
+
|
|
268
|
+
- **`generateJsonSchema(node, options?)`** — canonical draft 2020-12 output. Sorted keys, 2-space indent, single trailing newline. Same IR + same generator version → byte-identical output. Models accepted input only — no `mode` option in v0.3.
|
|
269
|
+
- **Identity** — URN `$id` by default (`urn:nekostack:schema:<id>:<version>`); URL form via `options.idBase`; anonymous schemas omit `$id`; never emits `$defs` in v0.3 (inline only — strategy documented for future).
|
|
270
|
+
- **Absence semantics** — `optional` / `nullish` / `default` omitted from `required`; `nullable` / `nullish` encode `null` in the type array; `default` emits annotation + `x-nekostack-default-applied-by: "runtime"`.
|
|
271
|
+
- **Object policy** — `strict` → `additionalProperties: false`; `passthrough` → `true`; `stripUnknown` → `true` + `x-nekostack-strip: true` (JSON Schema cannot strip; runtime does).
|
|
272
|
+
- **Refinement mapping** — full table in [`docs/JSON_SCHEMA_MAPPING.md`](docs/JSON_SCHEMA_MAPPING.md).
|
|
273
|
+
- **Throw contract** (Invariant 7) — runtime refinements (`kind: "runtimeRefinement"`) and regex-with-non-empty-flags (`kind: "regexFlags"`) throw `UnsupportedNodeKindError` rather than silently emit a schema that changes validation behavior. Stable `code` / `kind` / `generator` shape unchanged from v0.2; `generator` field union extended to include `"jsonSchema"`.
|
|
274
|
+
- **Provenance via `x-nekostack` extension object** — JSON has no comment syntax, so v0.2's JSDoc header concept moves into a single extension object at the root.
|
|
275
|
+
- **Codified extension keys** — `src/generators/json-schema-meta.ts` exports `JSON_SCHEMA_EXTENSIONS` constants. Any new `x-nekostack-*` key has to land in this file first.
|
|
276
|
+
- **New contract doc** — [`docs/JSON_SCHEMA_MAPPING.md`](docs/JSON_SCHEMA_MAPPING.md).
|
|
277
|
+
- **Three new committed example artifacts** under [`examples/generated/`](examples/generated/): `tenant.json.schema.json`, `audit-event.json.schema.json`, `entitlement.json.schema.json`. Validated by the regenerate test alongside the v0.2 TS/Zod outputs.
|
|
278
|
+
- **`GENERATOR_VERSION` bumped to `@nekostack/schema@0.3.0`** — provenance on every generated artifact (v0.2 and v0.3 outputs alike) now matches this milestone. 50 snapshots regenerated.
|
|
279
|
+
- **`UnsupportedNodeKindError` message** is now phase-neutral (previously pointed at `PHASE_PLAN_v0.2.md`).
|
|
280
|
+
- **`INVARIANTS.md`** extended with the v0.3 corollary on `x-nekostack-*` extensions vs. throw.
|
|
281
|
+
|
|
282
|
+
### Dependency changes
|
|
283
|
+
|
|
284
|
+
- New devDeps: `ajv ^8.12.0` (imported only via `ajv/dist/2020.js`, the draft-2020-12 class) and `ajv-formats ^3.0.1` (for `format: "email" / "uri"` execution tests). No new runtime dep.
|
|
285
|
+
|
|
286
|
+
### Test count
|
|
287
|
+
|
|
288
|
+
- 163 → 219 (+56 net).
|
|
289
|
+
|
|
290
|
+
### Still deferred
|
|
291
|
+
|
|
292
|
+
- OpenAPI 3.1 — v0.4
|
|
293
|
+
- Composition operators — v0.5
|
|
294
|
+
- Runtime `parse` / `validate` from this package — v0.6
|
|
295
|
+
- `neko schema generate / check / diff` CLI — v0.7
|
|
296
|
+
- `sourceHash` in headers — v0.7
|
|
297
|
+
- `$defs` extraction + cross-package `$ref` — v0.7 (registry-lite)
|
|
298
|
+
- Output-shape JSON Schema (default-applied, all-required) — deferred indefinitely (no concrete consumer needs it)
|
|
299
|
+
- Opt-in lossy regex-with-flags mode — deferred (current behavior is throw)
|
|
300
|
+
- Migrations between schema versions — v0.8+
|
|
301
|
+
- Zod 4 target — future generator option
|
|
302
|
+
|
|
303
|
+
---
|
|
304
|
+
|
|
305
|
+
## schema-v0.2.1 — 2026-05-16
|
|
306
|
+
|
|
307
|
+
[Tag](https://github.com/cmclicker/NekoStack/releases/tag/schema-v0.2.1) · merge commit [`17cd182`](https://github.com/cmclicker/NekoStack/commit/17cd182). Patch release on the v0.2 line — proof artifacts + generator output polish from the dogfood pass.
|
|
308
|
+
|
|
309
|
+
### Shipped
|
|
310
|
+
|
|
311
|
+
- **v0.2 dogfood examples** — three realistic schemas (`Tenant`, `AuditEvent`, `Entitlement`) under [`examples/`](examples/) with committed generated artifacts under [`examples/generated/`](examples/generated/). The committed files double as snapshots for [`tests/examples/regenerate.test.ts`](tests/examples/regenerate.test.ts), so example drift fails CI.
|
|
312
|
+
- **Author-facing docs** — [`docs/USAGE.md`](docs/USAGE.md) and [`docs/EXAMPLES.md`](docs/EXAMPLES.md).
|
|
313
|
+
- **TS generator: nested object indentation** — nested object types now indent per depth (was: collapsed to outer-field column).
|
|
314
|
+
- **TS generator: array-of-object element parens** — replaced unsafe `startsWith("{")` heuristic with a structural top-level-union scanner. Closes the semantic hole where `s.array(s.object({...}).optional())` could emit `{...} | undefined[]` (parsed as "object OR array of undefined") instead of the correct `({...} | undefined)[]`.
|
|
315
|
+
|
|
316
|
+
### Test count
|
|
317
|
+
|
|
318
|
+
- 144 → 163 (+19 since v0.2.0): 9 regenerate-test cases, 4 nested-indent assertions, 6 array-paren assertions.
|
|
319
|
+
|
|
320
|
+
### Why this was its own release
|
|
321
|
+
|
|
322
|
+
The dogfood polish changed generator behavior (real bug fix in the array-paren case, presentational change in the nested-indent case). Folding it under `schema-v0.2.0` would have understated the change and made the tagged release diverge from main. A patch tag preserves honesty without bumping the minor version.
|
|
323
|
+
|
|
324
|
+
### No public API change
|
|
325
|
+
|
|
326
|
+
- No new exports.
|
|
327
|
+
- No new dependency.
|
|
328
|
+
- `src/index.ts` unchanged from v0.2.0.
|
|
329
|
+
|
|
330
|
+
### Still deferred
|
|
331
|
+
|
|
332
|
+
Same as v0.2.0 (see below).
|
|
333
|
+
|
|
334
|
+
---
|
|
335
|
+
|
|
336
|
+
## schema-v0.2.0 — 2026-05-16
|
|
337
|
+
|
|
338
|
+
[Tag](https://github.com/cmclicker/NekoStack/releases/tag/schema-v0.2.0) · merge commit [`eee079c`](https://github.com/cmclicker/NekoStack/commit/eee079c).
|
|
339
|
+
|
|
340
|
+
### Shipped
|
|
341
|
+
|
|
342
|
+
- **`generateTypeScript(node, options?)`** — TS type-alias generator with `mode: "input" | "output" | "both"` (default `"output"`). Absence-semantics input/output split preserved end-to-end.
|
|
343
|
+
- **`generateZod(node, options?)`** — Zod 3.x generator with fixed modifier ordering. See [`docs/ZOD_MODIFIER_ORDERING.md`](docs/ZOD_MODIFIER_ORDERING.md).
|
|
344
|
+
- **`irHash(node)`** — sha256 of canonical IR serialization, hex-encoded. Used by generated-file headers in v0.2; consumed (not introduced) by the v0.7 freshness check.
|
|
345
|
+
- **Deterministic generated-file headers** — schemaId, schemaVersion, irHash, generator, generatorVersion. See [`docs/HEADER_FORMAT.md`](docs/HEADER_FORMAT.md). `sourceHash` deferred to v0.7.
|
|
346
|
+
- **`UnsupportedNodeKindError`** — stable `code` / `kind` / `generator` fields. Tests assert on fields, not message text.
|
|
347
|
+
- **Runtime refinements throw, not skip** — both generators throw `UnsupportedNodeKindError({ kind: "runtimeRefinement" })` rather than silently dropping unsupported refinement kinds.
|
|
348
|
+
- **Snapshot tests** for generator output (`vitest` `toMatchFileSnapshot`, external `.snap` files).
|
|
349
|
+
- **Zod-execution tests** — load generated code into a real Zod runtime, validate fixtures.
|
|
350
|
+
- **Zod-modifier-composition tests** — the eight-row matrix from Decision #8 (optional / nullable / nullish / default and combinations).
|
|
351
|
+
|
|
352
|
+
### Dependency changes
|
|
353
|
+
|
|
354
|
+
- Added `zod ^3.22.0` as **optional `peerDependency`** (consumers using the generated Zod runtime install it themselves) and `devDependency` (for the execution test harness). Generators ship as pure TS; no runtime import of Zod from the package itself.
|
|
355
|
+
|
|
356
|
+
### Test count
|
|
357
|
+
|
|
358
|
+
- 44 → 144 (+100 net at the tag commit; v0.2.1 took it to 163).
|
|
359
|
+
|
|
360
|
+
### Still deferred
|
|
361
|
+
|
|
362
|
+
- JSON Schema — v0.3
|
|
363
|
+
- OpenAPI 3.1 — v0.4
|
|
364
|
+
- Composition operators (`extend` / `pick` / `omit` / `partial` / `merge`) — v0.5
|
|
365
|
+
- Runtime `parse` / `validate` from this package directly — v0.6
|
|
366
|
+
- `neko schema generate / check / diff` CLI — v0.7
|
|
367
|
+
- `sourceHash` in generated headers — v0.7
|
|
368
|
+
- Migrations between schema versions — v0.8+
|
|
369
|
+
- Zod 4 target — future generator option (Zod 4 is stable; intentionally deferred for scope)
|
|
370
|
+
|
|
371
|
+
---
|
|
372
|
+
|
|
373
|
+
## schema-v0.1.0 — 2026-05-16
|
|
374
|
+
|
|
375
|
+
[Tag](https://github.com/cmclicker/NekoStack/releases/tag/schema-v0.1.0) · merge commit [`8a94853`](https://github.com/cmclicker/NekoStack/commit/8a94853). First package phase accepted under [`standards/package-development.md`](../../standards/package-development.md).
|
|
376
|
+
|
|
377
|
+
### Shipped
|
|
378
|
+
|
|
379
|
+
- **Canonical `SchemaNode` IR** — all 12 node kinds typed; 7 with v0.1 builders (string / number / boolean / literal / enum / array / object). Future kinds (date / union / recursiveRef / transform) declared internally but not surfaced.
|
|
380
|
+
- **DSL builders** — `s.string` / `s.number` / `s.boolean` / `s.literal` / `s.enum` / `s.array` / `s.object`.
|
|
381
|
+
- **Modifiers** — `optional` / `nullable` / `nullish` / `default`. `Schema` base tracks `TInputKey` and `TOutputKey` separately so default-bearing fields are correctly input-optional + output-required.
|
|
382
|
+
- **Metadata** — `id` / `version` / `describe` / `deprecated`.
|
|
383
|
+
- **Strict-by-default object policy** — `strict` (default) / `stripUnknown` / `passthrough`. Stored in IR; runtime enforcement deferred to v0.6.
|
|
384
|
+
- **Type inference** — `s.infer` / `s.input` / `s.output`.
|
|
385
|
+
- **`Issue` / `IssueCode` / `Result`** — vocabulary pinned; the parser that produces them ships in v0.6.
|
|
386
|
+
- **Canonical IR serialization** — `serializeIR(node)` sorts keys recursively, strips undefined. Foundation for v0.2's `irHash` and v0.7's freshness check.
|
|
387
|
+
- **Tight public API** — `src/index.ts` re-exports only v0.1-buildable node kinds. Implementation classes exported as type-only.
|
|
388
|
+
- **Package-local docs** — `README.md`, [`docs/SCOPE.md`](docs/SCOPE.md), [`docs/INVARIANTS.md`](docs/INVARIANTS.md), [`docs/ROADMAP.md`](docs/ROADMAP.md), [`docs/IR_CONTRACT.md`](docs/IR_CONTRACT.md), [`docs/ABSENCE_SEMANTICS.md`](docs/ABSENCE_SEMANTICS.md).
|
|
389
|
+
- **Package tooling** — first concrete package in the monorepo to wire `tsconfig.json` + `vitest.config.ts` + per-package scripts.
|
|
390
|
+
|
|
391
|
+
### Test count
|
|
392
|
+
|
|
393
|
+
- 0 → 44 (29 runtime + 15 type-level via `expectTypeOf`).
|
|
394
|
+
|
|
395
|
+
### Still deferred
|
|
396
|
+
|
|
397
|
+
- TypeScript generation — v0.2
|
|
398
|
+
- Zod generation — v0.2
|
|
399
|
+
- JSON Schema — v0.3
|
|
400
|
+
- OpenAPI — v0.4
|
|
401
|
+
- Composition operators — v0.5
|
|
402
|
+
- Runtime `parse` / `validate` — v0.6
|
|
403
|
+
- Schema registry + CLI + diff — v0.7
|
|
404
|
+
- Migrations — v0.8+
|
|
405
|
+
|
|
406
|
+
---
|
|
407
|
+
|
|
408
|
+
## Milestone process
|
|
409
|
+
|
|
410
|
+
For every shipped schema milestone:
|
|
411
|
+
|
|
412
|
+
1. Merge the implementation PR.
|
|
413
|
+
2. Merge the dogfood / proof PR if one exists (examples, generator polish surfaced during dogfooding, regenerate snapshots).
|
|
414
|
+
3. Merge the ROADMAP status PR (`candidate` → `shipped`; advance the next phase to `active target`).
|
|
415
|
+
4. Tag the **final** commit on the milestone — i.e. the dogfood merge if there is one, otherwise the implementation merge. Use `git tag -a schema-vX.Y.Z <sha> -m "..."` + `git push origin schema-vX.Y.Z`.
|
|
416
|
+
5. Create a GitHub release pointing at the tag.
|
|
417
|
+
6. Add a new section at the top of this file.
|
|
418
|
+
7. Keep `docs/` and `README.md` current — never duplicate them under `docs/v0.x/`.
|
|
419
|
+
|
|
420
|
+
Behavior-changing dogfood polish that lands AFTER the implementation has already been tagged gets its own patch milestone (`schema-v0.2.1`-style) — see the v0.2 line in this changelog for the working precedent. Folding it back into the implementation tag would make the tagged release diverge from main and understate the change.
|
|
421
|
+
|
|
422
|
+
The git history is the implementation truth; tags + releases + this changelog are the milestone-visible truth.
|
package/LICENSE
ADDED
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
|
|
2
|
+
Apache License
|
|
3
|
+
Version 2.0, January 2004
|
|
4
|
+
http://www.apache.org/licenses/
|
|
5
|
+
|
|
6
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
7
|
+
|
|
8
|
+
1. Definitions.
|
|
9
|
+
|
|
10
|
+
"License" shall mean the terms and conditions for use, reproduction,
|
|
11
|
+
and distribution as defined by Sections 1 through 9 of this document.
|
|
12
|
+
|
|
13
|
+
"Licensor" shall mean the copyright owner or entity authorized by
|
|
14
|
+
the copyright owner that is granting the License.
|
|
15
|
+
|
|
16
|
+
"Legal Entity" shall mean the union of the acting entity and all
|
|
17
|
+
other entities that control, are controlled by, or are under common
|
|
18
|
+
control with that entity. For the purposes of this definition,
|
|
19
|
+
"control" means (i) the power, direct or indirect, to cause the
|
|
20
|
+
direction or management of such entity, whether by contract or
|
|
21
|
+
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
|
22
|
+
outstanding shares, or (iii) beneficial ownership of such entity.
|
|
23
|
+
|
|
24
|
+
"You" (or "Your") shall mean an individual or Legal Entity
|
|
25
|
+
exercising permissions granted by this License.
|
|
26
|
+
|
|
27
|
+
"Source" form shall mean the preferred form for making modifications,
|
|
28
|
+
including but not limited to software source code, documentation
|
|
29
|
+
source, and configuration files.
|
|
30
|
+
|
|
31
|
+
"Object" form shall mean any form resulting from mechanical
|
|
32
|
+
transformation or translation of a Source form, including but
|
|
33
|
+
not limited to compiled object code, generated documentation,
|
|
34
|
+
and conversions to other media types.
|
|
35
|
+
|
|
36
|
+
"Work" shall mean the work of authorship, whether in Source or
|
|
37
|
+
Object form, made available under the License, as indicated by a
|
|
38
|
+
copyright notice that is included in or attached to the work
|
|
39
|
+
(an example is provided in the Appendix below).
|
|
40
|
+
|
|
41
|
+
"Derivative Works" shall mean any work, whether in Source or Object
|
|
42
|
+
form, that is based on (or derived from) the Work and for which the
|
|
43
|
+
editorial revisions, annotations, elaborations, or other modifications
|
|
44
|
+
represent, as a whole, an original work of authorship. For the purposes
|
|
45
|
+
of this License, Derivative Works shall not include works that remain
|
|
46
|
+
separable from, or merely link (or bind by name) to the interfaces of,
|
|
47
|
+
the Work and Derivative Works thereof.
|
|
48
|
+
|
|
49
|
+
"Contribution" shall mean any work of authorship, including
|
|
50
|
+
the original version of the Work and any modifications or additions
|
|
51
|
+
to that Work or Derivative Works thereof, that is intentionally
|
|
52
|
+
submitted to Licensor for inclusion in the Work by the copyright owner
|
|
53
|
+
or by an individual or Legal Entity authorized to submit on behalf of
|
|
54
|
+
the copyright owner. For the purposes of this definition, "submitted"
|
|
55
|
+
means any form of electronic, verbal, or written communication sent
|
|
56
|
+
to the Licensor or its representatives, including but not limited to
|
|
57
|
+
communication on electronic mailing lists, source code control systems,
|
|
58
|
+
and issue tracking systems that are managed by, or on behalf of, the
|
|
59
|
+
Licensor for the purpose of discussing and improving the Work, but
|
|
60
|
+
excluding communication that is conspicuously marked or otherwise
|
|
61
|
+
designated in writing by the copyright owner as "Not a Contribution."
|
|
62
|
+
|
|
63
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity
|
|
64
|
+
on behalf of whom a Contribution has been received by Licensor and
|
|
65
|
+
subsequently incorporated within the Work.
|
|
66
|
+
|
|
67
|
+
2. Grant of Copyright License. Subject to the terms and conditions of
|
|
68
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
69
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
70
|
+
copyright license to reproduce, prepare Derivative Works of,
|
|
71
|
+
publicly display, publicly perform, sublicense, and distribute the
|
|
72
|
+
Work and such Derivative Works in Source or Object form.
|
|
73
|
+
|
|
74
|
+
3. Grant of Patent License. Subject to the terms and conditions of
|
|
75
|
+
this License, each Contributor hereby grants to You a perpetual,
|
|
76
|
+
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
|
77
|
+
(except as stated in this section) patent license to make, have made,
|
|
78
|
+
use, offer to sell, sell, import, and otherwise transfer the Work,
|
|
79
|
+
where such license applies only to those patent claims licensable
|
|
80
|
+
by such Contributor that are necessarily infringed by their
|
|
81
|
+
Contribution(s) alone or by combination of their Contribution(s)
|
|
82
|
+
with the Work to which such Contribution(s) was submitted. If You
|
|
83
|
+
institute patent litigation against any entity (including a
|
|
84
|
+
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
|
85
|
+
or a Contribution incorporated within the Work constitutes direct
|
|
86
|
+
or contributory patent infringement, then any patent licenses
|
|
87
|
+
granted to You under this License for that Work shall terminate
|
|
88
|
+
as of the date such litigation is filed.
|
|
89
|
+
|
|
90
|
+
4. Redistribution. You may reproduce and distribute copies of the
|
|
91
|
+
Work or Derivative Works thereof in any medium, with or without
|
|
92
|
+
modifications, and in Source or Object form, provided that You
|
|
93
|
+
meet the following conditions:
|
|
94
|
+
|
|
95
|
+
(a) You must give any other recipients of the Work or
|
|
96
|
+
Derivative Works a copy of this License; and
|
|
97
|
+
|
|
98
|
+
(b) You must cause any modified files to carry prominent notices
|
|
99
|
+
stating that You changed the files; and
|
|
100
|
+
|
|
101
|
+
(c) You must retain, in the Source form of any Derivative Works
|
|
102
|
+
that You distribute, all copyright, patent, trademark, and
|
|
103
|
+
attribution notices from the Source form of the Work,
|
|
104
|
+
excluding those notices that do not pertain to any part of
|
|
105
|
+
the Derivative Works; and
|
|
106
|
+
|
|
107
|
+
(d) If the Work includes a "NOTICE" text file as part of its
|
|
108
|
+
distribution, then any Derivative Works that You distribute must
|
|
109
|
+
include a readable copy of the attribution notices contained
|
|
110
|
+
within such NOTICE file, excluding those notices that do not
|
|
111
|
+
pertain to any part of the Derivative Works, in at least one
|
|
112
|
+
of the following places: within a NOTICE text file distributed
|
|
113
|
+
as part of the Derivative Works; within the Source form or
|
|
114
|
+
documentation, if provided along with the Derivative Works; or,
|
|
115
|
+
within a display generated by the Derivative Works, if and
|
|
116
|
+
wherever such third-party notices normally appear. The contents
|
|
117
|
+
of the NOTICE file are for informational purposes only and
|
|
118
|
+
do not modify the License. You may add Your own attribution
|
|
119
|
+
notices within Derivative Works that You distribute, alongside
|
|
120
|
+
or as an addendum to the NOTICE text from the Work, provided
|
|
121
|
+
that such additional attribution notices cannot be construed
|
|
122
|
+
as modifying the License.
|
|
123
|
+
|
|
124
|
+
You may add Your own copyright statement to Your modifications and
|
|
125
|
+
may provide additional or different license terms and conditions
|
|
126
|
+
for use, reproduction, or distribution of Your modifications, or
|
|
127
|
+
for any such Derivative Works as a whole, provided Your use,
|
|
128
|
+
reproduction, and distribution of the Work otherwise complies with
|
|
129
|
+
the conditions stated in this License.
|
|
130
|
+
|
|
131
|
+
5. Submission of Contributions. Unless You explicitly state otherwise,
|
|
132
|
+
any Contribution intentionally submitted for inclusion in the Work
|
|
133
|
+
by You to the Licensor shall be under the terms and conditions of
|
|
134
|
+
this License, without any additional terms or conditions.
|
|
135
|
+
Notwithstanding the above, nothing herein shall supersede or modify
|
|
136
|
+
the terms of any separate license agreement you may have executed
|
|
137
|
+
with Licensor regarding such Contributions.
|
|
138
|
+
|
|
139
|
+
6. Trademarks. This License does not grant permission to use the trade
|
|
140
|
+
names, trademarks, service marks, or product names of the Licensor,
|
|
141
|
+
except as required for reasonable and customary use in describing the
|
|
142
|
+
origin of the Work and reproducing the content of the NOTICE file.
|
|
143
|
+
|
|
144
|
+
7. Disclaimer of Warranty. Unless required by applicable law or
|
|
145
|
+
agreed to in writing, Licensor provides the Work (and each
|
|
146
|
+
Contributor provides its Contributions) on an "AS IS" BASIS,
|
|
147
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
|
148
|
+
implied, including, without limitation, any warranties or conditions
|
|
149
|
+
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
|
150
|
+
PARTICULAR PURPOSE. You are solely responsible for determining the
|
|
151
|
+
appropriateness of using or redistributing the Work and assume any
|
|
152
|
+
risks associated with Your exercise of permissions under this License.
|
|
153
|
+
|
|
154
|
+
8. Limitation of Liability. In no event and under no legal theory,
|
|
155
|
+
whether in tort (including negligence), contract, or otherwise,
|
|
156
|
+
unless required by applicable law (such as deliberate and grossly
|
|
157
|
+
negligent acts) or agreed to in writing, shall any Contributor be
|
|
158
|
+
liable to You for damages, including any direct, indirect, special,
|
|
159
|
+
incidental, or consequential damages of any character arising as a
|
|
160
|
+
result of this License or out of the use or inability to use the
|
|
161
|
+
Work (including but not limited to damages for loss of goodwill,
|
|
162
|
+
work stoppage, computer failure or malfunction, or any and all
|
|
163
|
+
other commercial damages or losses), even if such Contributor
|
|
164
|
+
has been advised of the possibility of such damages.
|
|
165
|
+
|
|
166
|
+
9. Accepting Warranty or Additional Liability. While redistributing
|
|
167
|
+
the Work or Derivative Works thereof, You may choose to offer,
|
|
168
|
+
and charge a fee for, acceptance of support, warranty, indemnity,
|
|
169
|
+
or other liability obligations and/or rights consistent with this
|
|
170
|
+
License. However, in accepting such obligations, You may act only
|
|
171
|
+
on Your own behalf and on Your sole responsibility, not on behalf
|
|
172
|
+
of any other Contributor, and only if You agree to indemnify,
|
|
173
|
+
defend, and hold each Contributor harmless for any liability
|
|
174
|
+
incurred by, or claims asserted against, such Contributor by reason
|
|
175
|
+
of your accepting any such warranty or additional liability.
|
|
176
|
+
|
|
177
|
+
END OF TERMS AND CONDITIONS
|
|
178
|
+
|
|
179
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
180
|
+
|
|
181
|
+
To apply the Apache License to your work, attach the following
|
|
182
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
183
|
+
replaced with your own identifying information. (Don't include
|
|
184
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
185
|
+
comment syntax for the file format. We also recommend that a
|
|
186
|
+
file or class name and description of purpose be included on the
|
|
187
|
+
same "printed page" as the copyright notice for easier
|
|
188
|
+
identification within third-party archives.
|
|
189
|
+
|
|
190
|
+
Copyright [yyyy] [name of copyright owner]
|
|
191
|
+
|
|
192
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
193
|
+
you may not use this file except in compliance with the License.
|
|
194
|
+
You may obtain a copy of the License at
|
|
195
|
+
|
|
196
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
197
|
+
|
|
198
|
+
Unless required by applicable law or agreed to in writing, software
|
|
199
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
200
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
201
|
+
See the License for the specific language governing permissions and
|
|
202
|
+
limitations under the License.
|