lutaml-jsonschema 0.1.23 → 0.1.25
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.
- checksums.yaml +4 -4
- data/.rubocop_todo.yml +1 -1
- data/CLAUDE.md +7 -3
- data/Rakefile +16 -1
- data/benchmark/pipeline_profile.rb +118 -0
- data/frontend/dist/app.iife.js +6 -6
- data/frontend/dist/style.css +1 -1
- data/frontend/package-lock.json +11 -0
- data/frontend/package.json +1 -0
- data/frontend/src/App.vue +5 -3
- data/frontend/src/__tests__/i18n.test.ts +99 -0
- data/frontend/src/__tests__/spaDataCompleteness.test.ts +118 -0
- data/frontend/src/__tests__/useMarkdownLite.test.ts +47 -0
- data/frontend/src/components/AppHeader.vue +22 -6
- data/frontend/src/components/AppSidebar.vue +38 -24
- data/frontend/src/components/DetailPanel.vue +323 -88
- data/frontend/src/components/SchemaBuilder.vue +48 -47
- data/frontend/src/components/SearchModal.vue +5 -4
- data/frontend/src/components/SeeMore.vue +2 -1
- data/frontend/src/composables/useMarkdownLite.ts +79 -3
- data/frontend/src/composables/useSchemaTypes.ts +144 -2
- data/frontend/src/i18n/index.ts +84 -0
- data/frontend/src/i18n/messages.ts +311 -0
- data/frontend/src/stores/schemaStore.ts +2 -0
- data/frontend/src/stores/uiStore.ts +2 -2
- data/frontend/src/style.css +41 -7
- data/frontend/src/types.ts +49 -0
- data/frontend/src/views/HomeView.vue +8 -8
- data/lib/lutaml/jsonschema/cli.rb +153 -12
- data/lib/lutaml/jsonschema/combiner.rb +3 -34
- data/lib/lutaml/jsonschema/configuration.rb +3 -0
- data/lib/lutaml/jsonschema/dialect.rb +65 -0
- data/lib/lutaml/jsonschema/diff.rb +275 -0
- data/lib/lutaml/jsonschema/exports/adoc.rb +190 -0
- data/lib/lutaml/jsonschema/exports/cddl.rb +172 -0
- data/lib/lutaml/jsonschema/exports/lml.rb +206 -0
- data/lib/lutaml/jsonschema/exports/openapi.rb +48 -0
- data/lib/lutaml/jsonschema/exports/xsd.rb +183 -0
- data/lib/lutaml/jsonschema/meta_schemas/2019-09/meta/applicator.json +53 -0
- data/lib/lutaml/jsonschema/meta_schemas/2019-09/meta/content.json +14 -0
- data/lib/lutaml/jsonschema/meta_schemas/2019-09/meta/core.json +54 -0
- data/lib/lutaml/jsonschema/meta_schemas/2019-09/meta/format.json +11 -0
- data/lib/lutaml/jsonschema/meta_schemas/2019-09/meta/meta-data.json +34 -0
- data/lib/lutaml/jsonschema/meta_schemas/2019-09/meta/validation.json +95 -0
- data/lib/lutaml/jsonschema/meta_schemas/2019-09/schema.json +42 -0
- data/lib/lutaml/jsonschema/meta_schemas/2020-12/meta/applicator.json +45 -0
- data/lib/lutaml/jsonschema/meta_schemas/2020-12/meta/content.json +14 -0
- data/lib/lutaml/jsonschema/meta_schemas/2020-12/meta/core.json +48 -0
- data/lib/lutaml/jsonschema/meta_schemas/2020-12/meta/format-annotation.json +11 -0
- data/lib/lutaml/jsonschema/meta_schemas/2020-12/meta/meta-data.json +34 -0
- data/lib/lutaml/jsonschema/meta_schemas/2020-12/meta/unevaluated.json +12 -0
- data/lib/lutaml/jsonschema/meta_schemas/2020-12/meta/validation.json +95 -0
- data/lib/lutaml/jsonschema/meta_schemas/2020-12/schema.json +58 -0
- data/lib/lutaml/jsonschema/meta_schemas/NOTICE.md +12 -0
- data/lib/lutaml/jsonschema/meta_schemas/draft-04/schema.json +149 -0
- data/lib/lutaml/jsonschema/meta_schemas/draft-06/schema.json +155 -0
- data/lib/lutaml/jsonschema/meta_schemas/draft-07/schema.json +172 -0
- data/lib/lutaml/jsonschema/property_entry.rb +27 -0
- data/lib/lutaml/jsonschema/reference_resolver.rb +151 -36
- data/lib/lutaml/jsonschema/schema.rb +543 -35
- data/lib/lutaml/jsonschema/schema_set.rb +168 -12
- data/lib/lutaml/jsonschema/schema_store.rb +4 -4
- data/lib/lutaml/jsonschema/spa/generator.rb +4 -2
- data/lib/lutaml/jsonschema/spa/metadata.rb +2 -0
- data/lib/lutaml/jsonschema/spa/spa_builder.rb +242 -111
- data/lib/lutaml/jsonschema/spa/spa_definition.rb +10 -0
- data/lib/lutaml/jsonschema/spa/spa_diff_entry.rb +22 -0
- data/lib/lutaml/jsonschema/spa/spa_document.rb +3 -0
- data/lib/lutaml/jsonschema/spa/spa_property.rb +25 -0
- data/lib/lutaml/jsonschema/spa/spa_schema.rb +26 -0
- data/lib/lutaml/jsonschema/tuple_item.rb +20 -0
- data/lib/lutaml/jsonschema/validator.rb +91 -0
- data/lib/lutaml/jsonschema/version.rb +1 -1
- data/lib/lutaml/jsonschema.rb +13 -0
- data/script/axe_audit +96 -0
- metadata +66 -4
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 5def50283e10b93eae1ca02c54374c259f64f8b530b9edde9baddc7aa6e17fee
|
|
4
|
+
data.tar.gz: 5a6367729b6f4543bcc3d09246bdf663918e2bd977cb2591065563887e8c0fec
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fa6880c0ef08bdaa4277f1ca2d71f9943fc7a6facfe6071669d0141ed038949b7cf652f32e1b668e7469d3dac2ac57671696114a2d31e42a12549392132230c7
|
|
7
|
+
data.tar.gz: ab108839554ad9cdd16ec05eb61756fba5e01a51d6ac0b9f1b541d5ad6939de2ec40696e44a39aaf2ceeeed2044659dfee0d5ce8224100509ab960d87489e83c
|
data/.rubocop_todo.yml
CHANGED
|
@@ -187,7 +187,7 @@ Metrics/AbcSize:
|
|
|
187
187
|
# Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns.
|
|
188
188
|
# AllowedMethods: refine
|
|
189
189
|
Metrics/BlockLength:
|
|
190
|
-
Max:
|
|
190
|
+
Max: 57
|
|
191
191
|
|
|
192
192
|
# Offense count: 12
|
|
193
193
|
# Configuration parameters: AllowedMethods, AllowedPatterns, Max.
|
data/CLAUDE.md
CHANGED
|
@@ -21,7 +21,10 @@ bundle exec rake # spec + rubocop (what CI runs)
|
|
|
21
21
|
bundle exec rake frontend:build # npm install + vite build → frontend/dist
|
|
22
22
|
cd frontend && npm test # vitest (frontend unit tests)
|
|
23
23
|
|
|
24
|
-
bundle exec exe/lutaml-jsonschema spa
|
|
24
|
+
bundle exec exe/lutaml-jsonschema spa SCHEMA_FILES... [--diff BASELINE...]
|
|
25
|
+
bundle exec exe/lutaml-jsonschema combine|validate SCHEMA_FILES...
|
|
26
|
+
bundle exec exe/lutaml-jsonschema export SCHEMA_FILES... -f cddl|openapi|xsd|adoc
|
|
27
|
+
bundle exec exe/lutaml-jsonschema diff OLD NEW [--format json]
|
|
25
28
|
```
|
|
26
29
|
|
|
27
30
|
`frontend/dist/` and `Gemfile.lock` are gitignored. `frontend/dist/` must exist (run `rake frontend:build`) for the `spa` command and for packaging — the gemspec ships it via `Dir.glob("frontend/dist/*")`.
|
|
@@ -34,10 +37,11 @@ Data flow: schema files → `SchemaSet.load_from_files` → `Spa::SpaBuilder`
|
|
|
34
37
|
- **`Schema`** — the central model of a JSON Schema document. Every `$`-prefixed keyword is a `dollar_`-prefixed attribute (`$schema` → `dollar_schema`) via json mappings. `Schema.from_json` / `to_json` are lutaml-model serialization.
|
|
35
38
|
- **`SchemaSet`** — in-memory named collection of schemas plus `$ref` resolution (local `#/...` pointers and relative `./file.json` refs through `ReferenceResolver`) and validation.
|
|
36
39
|
- **`SchemaStore`** — `SchemaSet` subclass that adds on-disk persistence through **lutaml-store** (`PackageStore`, package shape from `LjrPackageDefinition`).
|
|
37
|
-
- **`Combiner`** —
|
|
40
|
+
- **`Combiner`** — compatibility facade; bundling lives in `SchemaSet#bundle` (hoists definitions, adds a top-level `$ref` property per source schema, rewrites `#/definitions/` → `#/$defs/`).
|
|
38
41
|
- **`Spa::*`** — `SpaBuilder` flattens a `SchemaSet` into a `SpaDocument` (metadata, `SpaSchema` list, flat `search_index` for FlexSearch). `Spa::Generator` renders through an `OutputStrategy`; `VueInlinedStrategy` is the only implementation.
|
|
39
42
|
- **`Configuration`** — YAML config for the SPA (title, theme, appearance…), loaded by `Cli#spa -c`.
|
|
40
|
-
- **`Cli`** — Thor commands: `spa` (generate docs), `combine` (merge schemas), `
|
|
43
|
+
- **`Cli`** — Thor commands: `spa` (generate docs; `--diff` embeds a classified change set), `combine` (merge schemas), `export` (cddl/openapi/xsd/adoc), `diff` (exits 1 on breaking changes), `validate` (meta-schema checks), `version`.
|
|
44
|
+
- **`TupleItem`** — schema-or-boolean wrapper used by `items`/`prefixItems` arrays and composition collections; models that accept `true`/`false` store booleans in companion `*_boolean` attributes and expose `*_value` helpers.
|
|
41
45
|
|
|
42
46
|
## JSON engine: yeptris
|
|
43
47
|
|
data/Rakefile
CHANGED
|
@@ -9,7 +9,17 @@ require "rubocop/rake_task"
|
|
|
9
9
|
|
|
10
10
|
RuboCop::RakeTask.new
|
|
11
11
|
|
|
12
|
-
task default: %i[spec rubocop]
|
|
12
|
+
task default: %i[spec rubocop perf frontend:audit]
|
|
13
|
+
|
|
14
|
+
namespace :perf do
|
|
15
|
+
desc "Pipeline performance harness with regression caps (TODO.sota/08)"
|
|
16
|
+
task :profile do
|
|
17
|
+
ruby "benchmark/pipeline_profile.rb"
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
desc "Run the pipeline performance regression gate"
|
|
22
|
+
task perf: "perf:profile"
|
|
13
23
|
|
|
14
24
|
namespace :frontend do
|
|
15
25
|
desc "Build the Vue frontend"
|
|
@@ -19,6 +29,11 @@ namespace :frontend do
|
|
|
19
29
|
sh "npm run build"
|
|
20
30
|
end
|
|
21
31
|
end
|
|
32
|
+
|
|
33
|
+
desc "axe-core accessibility audit of the generated SPA (needs Chrome)"
|
|
34
|
+
task :audit do
|
|
35
|
+
ruby "script/axe_audit"
|
|
36
|
+
end
|
|
22
37
|
end
|
|
23
38
|
|
|
24
39
|
task :build_frontend do
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Pipeline performance harness (TODO.sota/08).
|
|
4
|
+
#
|
|
5
|
+
# Measures the two budgeted paths on the real-world heroku.json fixture:
|
|
6
|
+
# - Schema.from_json (model construction)
|
|
7
|
+
# - end-to-end SPA generation (SchemaSet + SpaBuilder + inlined HTML)
|
|
8
|
+
#
|
|
9
|
+
# Metrics are reported both absolutely and as a ratio to a stdlib
|
|
10
|
+
# JSON.parse of the same document. The ratio is the machine-independent
|
|
11
|
+
# signal: CI runners vary wildly in absolute speed, but the C parser is
|
|
12
|
+
# a stable per-machine yardstick. Regression caps apply to the ratio.
|
|
13
|
+
#
|
|
14
|
+
# Usage: bundle exec ruby benchmark/pipeline_profile.rb [runs]
|
|
15
|
+
|
|
16
|
+
require "benchmark"
|
|
17
|
+
require "json"
|
|
18
|
+
require "lutaml/jsonschema"
|
|
19
|
+
require "tmpdir"
|
|
20
|
+
|
|
21
|
+
FIXTURES = Dir[File.expand_path("../spec/fixtures/*.json", __dir__)]
|
|
22
|
+
HEROKU = File.expand_path("../spec/fixtures/heroku.json", __dir__)
|
|
23
|
+
DATA = File.read(HEROKU)
|
|
24
|
+
RUNS = (ARGV[0] || 3).to_i
|
|
25
|
+
|
|
26
|
+
# Regression caps, calibrated per environment: the ratio looked
|
|
27
|
+
# machine-independent but is not — CI runners (2 vCPU, shared) inflate the
|
|
28
|
+
# Ruby-vs-C balance ~2x versus a local M-series machine (first real CI run:
|
|
29
|
+
# from_json 5901x, e2e 7853x, suite itself green). Caps catch real
|
|
30
|
+
# regressions (1.3x+ of the environment's own baseline) without flaking.
|
|
31
|
+
# Aspirational budgets are printed separately.
|
|
32
|
+
IN_CI = ["true", "1"].include?(ENV.fetch("CI", nil))
|
|
33
|
+
CAP_FROM_JSON_RATIO, CAP_E2E_RATIO =
|
|
34
|
+
if IN_CI
|
|
35
|
+
[7_500, 10_000]
|
|
36
|
+
else
|
|
37
|
+
[2_600, 5_000]
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def median(values)
|
|
41
|
+
values.sort[values.length / 2]
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def measure(runs, &)
|
|
45
|
+
Array.new(runs) { Benchmark.realtime(&) }
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
Schema = Lutaml::Jsonschema::Schema
|
|
49
|
+
|
|
50
|
+
# Warmup
|
|
51
|
+
Schema.from_json(DATA)
|
|
52
|
+
JSON.parse(DATA)
|
|
53
|
+
|
|
54
|
+
parse_times = measure(RUNS) { JSON.parse(DATA) }
|
|
55
|
+
from_json_times = measure(RUNS) { Schema.from_json(DATA) }
|
|
56
|
+
|
|
57
|
+
tmp = Dir.mktmpdir
|
|
58
|
+
frontend_built = File.exist?(
|
|
59
|
+
File.join(Lutaml::Jsonschema::Spa::VueInlinedStrategy::FRONTEND_DIST,
|
|
60
|
+
"app.iife.js"),
|
|
61
|
+
)
|
|
62
|
+
generate = lambda do
|
|
63
|
+
set = Lutaml::Jsonschema::SchemaSet.load_from_files(*FIXTURES)
|
|
64
|
+
Lutaml::Jsonschema::Spa::Generator.new(set, tmp).generate
|
|
65
|
+
end
|
|
66
|
+
if frontend_built
|
|
67
|
+
generate.call
|
|
68
|
+
e2e_times = measure(RUNS) { generate.call }
|
|
69
|
+
else
|
|
70
|
+
e2e_times = nil
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
parse_ms = median(parse_times) * 1000
|
|
74
|
+
from_json_ms = median(from_json_times) * 1000
|
|
75
|
+
e2e_ms = e2e_times && (median(e2e_times) * 1000)
|
|
76
|
+
|
|
77
|
+
from_json_ratio = from_json_ms / parse_ms
|
|
78
|
+
e2e_ratio = e2e_ms && (e2e_ms / parse_ms)
|
|
79
|
+
|
|
80
|
+
per_100kb = from_json_ms / (DATA.bytesize / 100_000.0)
|
|
81
|
+
html_bytes = if e2e_ms
|
|
82
|
+
File.size(File.join(tmp, "index.html"))
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
puts "heroku.json: #{DATA.bytesize} bytes, #{FIXTURES.length} fixtures, " \
|
|
86
|
+
"runs=#{RUNS}"
|
|
87
|
+
puts format("JSON.parse (reference): %<ms>10.3f ms", ms: parse_ms)
|
|
88
|
+
puts format("Schema.from_json: %<ms>10.3f ms " \
|
|
89
|
+
"(%<per>0f ms/100KB, %<ref>0fx ref)",
|
|
90
|
+
ms: from_json_ms, per: per_100kb, ref: from_json_ratio)
|
|
91
|
+
if e2e_ms
|
|
92
|
+
puts format("e2e spa generate: %<ms>10.3f ms (%<ref>0fx ref)",
|
|
93
|
+
ms: e2e_ms, ref: e2e_ratio)
|
|
94
|
+
puts format("index.html: %<bytes>10d bytes " \
|
|
95
|
+
"(%<ratio>0.2fx input)",
|
|
96
|
+
bytes: html_bytes, ratio: html_bytes.to_f / DATA.bytesize)
|
|
97
|
+
else
|
|
98
|
+
puts "e2e spa generate: skipped (frontend/dist not built)"
|
|
99
|
+
end
|
|
100
|
+
puts
|
|
101
|
+
puts "environment: #{IN_CI ? 'CI' : 'local'}"
|
|
102
|
+
puts "budgets (aspirational): from_json <= #{DATA.bytesize / 1000} ms " \
|
|
103
|
+
"(100 ms/100KB), e2e <= 1 s/MB"
|
|
104
|
+
puts "regression caps: from_json ratio <= #{CAP_FROM_JSON_RATIO}, " \
|
|
105
|
+
"e2e ratio <= #{CAP_E2E_RATIO}"
|
|
106
|
+
|
|
107
|
+
failures = []
|
|
108
|
+
failures << "from_json ratio #{from_json_ratio.round} > #{CAP_FROM_JSON_RATIO}" \
|
|
109
|
+
if from_json_ratio > CAP_FROM_JSON_RATIO
|
|
110
|
+
failures << "e2e ratio #{e2e_ratio.round} > #{CAP_E2E_RATIO}" \
|
|
111
|
+
if e2e_ratio && e2e_ratio > CAP_E2E_RATIO
|
|
112
|
+
|
|
113
|
+
if failures.empty?
|
|
114
|
+
puts "PERF OK"
|
|
115
|
+
else
|
|
116
|
+
warn "PERF REGRESSION: #{failures.join('; ')}"
|
|
117
|
+
exit 1
|
|
118
|
+
end
|