@pepperhorn/chordl-voicing 0.0.0-stage → 0.1.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/LICENSE +21 -0
- package/README.md +154 -2
- package/dist/canonical.d.ts +22 -0
- package/dist/canonical.js +90 -0
- package/dist/canonical.js.map +1 -0
- package/dist/catalogue.d.ts +14 -0
- package/dist/catalogue.js +164 -0
- package/dist/catalogue.js.map +1 -0
- package/dist/checks.d.ts +8 -0
- package/dist/checks.js +150 -0
- package/dist/checks.js.map +1 -0
- package/dist/chordId.d.ts +16 -0
- package/dist/chordId.js +106 -0
- package/dist/chordId.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +8 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/run.d.ts +6 -0
- package/dist/cli/run.js +438 -0
- package/dist/cli/run.js.map +1 -0
- package/dist/generated/chord.schema.json +29 -0
- package/dist/generated/voicing.schema.json +164 -0
- package/dist/hash.d.ts +4 -0
- package/dist/hash.js +34 -0
- package/dist/hash.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/instruments.d.ts +3 -0
- package/dist/instruments.js +7 -0
- package/dist/instruments.js.map +1 -0
- package/dist/pitch.d.ts +16 -0
- package/dist/pitch.js +63 -0
- package/dist/pitch.js.map +1 -0
- package/dist/realization.d.ts +9 -0
- package/dist/realization.js +78 -0
- package/dist/realization.js.map +1 -0
- package/dist/schema.d.ts +18 -0
- package/dist/schema.js +35 -0
- package/dist/schema.js.map +1 -0
- package/dist/types.d.ts +87 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/docs/CANONICAL.md +36 -0
- package/package.json +57 -3
- package/schema/chord.schema.json +29 -0
- package/schema/voicing.schema.json +164 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 PepperHorn Music / Creative Ranges Foundation
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,155 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @pepperhorn/chordl-voicing
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
An open JSON format for chord voicings (fretted, keyboard, bowed), with TypeScript
|
|
4
|
+
types, JSON Schemas, a canonical formatter, content hashes, a catalogue validator
|
|
5
|
+
and a `chordl-voicing` command line tool.
|
|
6
|
+
|
|
7
|
+
A **chord file** holds one chord and all of its voicings. A **voicing** records which
|
|
8
|
+
notes sound, how they are realized on an instrument, who wrote it, and how it relates
|
|
9
|
+
to other voicings (revisions, supersession, duplicates). Files are plain JSON, one per
|
|
10
|
+
chord, designed to live in a git repository and be reviewed as diffs.
|
|
11
|
+
|
|
12
|
+
## Schemas
|
|
13
|
+
|
|
14
|
+
| Schema id | Describes |
|
|
15
|
+
| --- | --- |
|
|
16
|
+
| `chordl.chord/1` | A chord file: the chord (`id`, `symbol`, `root`, `quality`, `bass`, `aliases`) and its `voicings` |
|
|
17
|
+
| `chordl.voicing/1` | One voicing: `notes`, a `realization`, `provenance`, `relations` and `hashes` |
|
|
18
|
+
|
|
19
|
+
Both are JSON Schema draft 2020-12, shipped as `schema/chord.schema.json` and
|
|
20
|
+
`schema/voicing.schema.json` (also importable as
|
|
21
|
+
`@pepperhorn/chordl-voicing/schema/chord.schema.json`).
|
|
22
|
+
|
|
23
|
+
Chord ids look like `C:maj7` or `C:7/E`: `<root>:<quality>[/<bass>]`. Pitches are
|
|
24
|
+
ASCII scientific pitch (`Eb4`, never `E♭4`). Each note carries a jazz degree such as
|
|
25
|
+
`I`, `bIII`, `#IV`.
|
|
26
|
+
|
|
27
|
+
## Realizations
|
|
28
|
+
|
|
29
|
+
The `realization` of a voicing has a `kind` of `fretted`, `keyboard` or `bowed`.
|
|
30
|
+
|
|
31
|
+
Fretted. `strings` holds absolute frets (`null` is muted), in chordl-guitar string order:
|
|
32
|
+
|
|
33
|
+
```json
|
|
34
|
+
{
|
|
35
|
+
"kind": "fretted",
|
|
36
|
+
"instrument": "guitar",
|
|
37
|
+
"tuning": ["E2", "A2", "D3", "G3", "B3", "E4"],
|
|
38
|
+
"strings": [null, 3, 2, 0, 0, 0],
|
|
39
|
+
"fingers": [null, 3, 2, null, null, null],
|
|
40
|
+
"baseFret": 1,
|
|
41
|
+
"barres": [],
|
|
42
|
+
"capo": null
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Keyboard. Pitches per hand; `fingering` is optional:
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{ "kind": "keyboard", "hands": { "left": ["C3", "G3"], "right": ["E4", "B4"] } }
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Bowed. One stop per sounding string:
|
|
53
|
+
|
|
54
|
+
```json
|
|
55
|
+
{
|
|
56
|
+
"kind": "bowed",
|
|
57
|
+
"instrument": "violin",
|
|
58
|
+
"tuning": ["G3", "D4", "A4", "E5"],
|
|
59
|
+
"stops": [{ "string": 2, "pitch": "C5", "finger": 2 }],
|
|
60
|
+
"position": 1
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Library
|
|
65
|
+
|
|
66
|
+
```ts
|
|
67
|
+
import {
|
|
68
|
+
validateChordFileSchema, checkVoicing, formatChordFile, isCanonical, withHashes,
|
|
69
|
+
} from "@pepperhorn/chordl-voicing";
|
|
70
|
+
|
|
71
|
+
const result = validateChordFileSchema(json);
|
|
72
|
+
if (!result.ok) console.error(result.errors); // [{ path, message }]
|
|
73
|
+
else {
|
|
74
|
+
for (const voicing of result.value.voicings) {
|
|
75
|
+
const { hard, flags } = checkVoicing(voicing); // hard = must fix, flags = review
|
|
76
|
+
}
|
|
77
|
+
const text = formatChordFile(result.value); // canonical JSON text
|
|
78
|
+
}
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Other exports: `parseChordId`, `formatChordId`, `chordIntervals`, `labelNotes`,
|
|
82
|
+
`soundingMidi`, `notesMatchRealization`, `shapeHash`, `pitchHash`, `withHashes`,
|
|
83
|
+
`chordFilePath`, `validateCatalogue` and the types (`ChordFile`, `Voicing`,
|
|
84
|
+
`Realization`, ...).
|
|
85
|
+
|
|
86
|
+
Hashes (`hashes.shape`, `hashes.pitch`) cover musical content only, so tier, status
|
|
87
|
+
and provenance edits never change them. The exact file form and hash rules are in
|
|
88
|
+
[docs/CANONICAL.md](./docs/CANONICAL.md).
|
|
89
|
+
|
|
90
|
+
## CLI
|
|
91
|
+
|
|
92
|
+
Run it inside a catalogue checkout (files live under `chords/`):
|
|
93
|
+
|
|
94
|
+
```sh
|
|
95
|
+
npx @pepperhorn/chordl-voicing <command>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### new
|
|
99
|
+
|
|
100
|
+
Create a voicing and add it to the chord's file (creating the file if needed):
|
|
101
|
+
|
|
102
|
+
```sh
|
|
103
|
+
# Fretted: one character per string, or comma-separated; x = muted
|
|
104
|
+
chordl-voicing new --chord C:maj7 --instrument guitar --frets x32000 --author gh:alice
|
|
105
|
+
|
|
106
|
+
# Barre chords: --barre <fret>:<fromString>-<toString>, repeatable.
|
|
107
|
+
# Strings are numbered from 0 (the first string in the tuning, thickest on guitar).
|
|
108
|
+
# A barre counts as one finger, so a full F shape passes the four-finger check.
|
|
109
|
+
chordl-voicing new --chord F:maj --instrument guitar --frets 133211 \
|
|
110
|
+
--barre 1:0-5 --author gh:alice
|
|
111
|
+
|
|
112
|
+
# Keyboard: --notes "<left> | <right>", pitches space-separated.
|
|
113
|
+
# Without a "|", every note goes to the right hand.
|
|
114
|
+
chordl-voicing new --chord C:maj7 --instrument piano \
|
|
115
|
+
--notes "C3 G3 | E4 B4" --author gh:alice
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
`--author` is a prefixed id such as `gh:alice`. `--tier` is `community` (default) or
|
|
119
|
+
`curated`. Note names and degrees are worked out from the chord, hashes are filled
|
|
120
|
+
in, and the voicing is checked before it is written. Bowed voicings are written by
|
|
121
|
+
hand.
|
|
122
|
+
|
|
123
|
+
### format
|
|
124
|
+
|
|
125
|
+
```sh
|
|
126
|
+
chordl-voicing format # rewrite every file under chords/ to canonical form
|
|
127
|
+
chordl-voicing format --check # print a diff and exit 1 if any file is not canonical
|
|
128
|
+
chordl-voicing format chords/C/C__maj7.json
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
### validate
|
|
132
|
+
|
|
133
|
+
```sh
|
|
134
|
+
chordl-voicing validate [--base <dir>] [--licences <file>]
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Checks schema, canonical form, hashes, notes against realization, and catalogue rules.
|
|
138
|
+
With `--base`, also checks history against an earlier checkout (revisions must be
|
|
139
|
+
appended, not edited). Exits 1 on any error.
|
|
140
|
+
|
|
141
|
+
### bundle
|
|
142
|
+
|
|
143
|
+
```sh
|
|
144
|
+
chordl-voicing bundle --out dist --version v2026.10.1
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
Writes `manifest.json`, `catalogue.json` and `by-instrument/<instrument>.json`.
|
|
148
|
+
`catalogue.json` holds every revision of every voicing, including retired ones;
|
|
149
|
+
`by-instrument/<instrument>.json` and the manifest counts cover live voicings only.
|
|
150
|
+
|
|
151
|
+
Exit codes: 0 success, 1 failure, 2 usage error.
|
|
152
|
+
|
|
153
|
+
## Licence
|
|
154
|
+
|
|
155
|
+
MIT
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { ChordFile } from "./types.js";
|
|
2
|
+
export declare const KEY_ORDER: {
|
|
3
|
+
readonly file: readonly ["schema", "chord", "voicings"];
|
|
4
|
+
readonly chord: readonly ["id", "symbol", "root", "quality", "bass", "aliases"];
|
|
5
|
+
readonly voicing: readonly ["schema", "id", "rev", "previous", "chordId", "status", "tier", "licence", "notes", "realization", "level", "provenance", "relations", "externalIds", "hashes"];
|
|
6
|
+
readonly note: readonly ["pitch", "degree"];
|
|
7
|
+
readonly fretted: readonly ["kind", "instrument", "tuning", "strings", "fingers", "baseFret", "barres", "capo"];
|
|
8
|
+
readonly barre: readonly ["fret", "fromString", "toString"];
|
|
9
|
+
readonly keyboard: readonly ["kind", "hands", "fingering"];
|
|
10
|
+
readonly hands: readonly ["left", "right"];
|
|
11
|
+
readonly fingering: readonly ["left", "right"];
|
|
12
|
+
readonly bowed: readonly ["kind", "instrument", "tuning", "stops", "position"];
|
|
13
|
+
readonly stop: readonly ["string", "pitch", "finger"];
|
|
14
|
+
readonly provenance: readonly ["source", "authorId", "createdAt", "changeNote", "basedOn", "alternativeTo"];
|
|
15
|
+
readonly relations: readonly ["supersedes", "supersededBy", "duplicateOf"];
|
|
16
|
+
readonly hashes: readonly ["shape", "pitch"];
|
|
17
|
+
};
|
|
18
|
+
export declare function formatChordFile(file: ChordFile): string;
|
|
19
|
+
export declare function isCanonical(text: string): {
|
|
20
|
+
ok: boolean;
|
|
21
|
+
expected: string;
|
|
22
|
+
};
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// Key order for every object in a chord file, defined once. Mirrors the property order in types.ts.
|
|
2
|
+
export const KEY_ORDER = {
|
|
3
|
+
file: ["schema", "chord", "voicings"],
|
|
4
|
+
chord: ["id", "symbol", "root", "quality", "bass", "aliases"],
|
|
5
|
+
voicing: [
|
|
6
|
+
"schema", "id", "rev", "previous", "chordId", "status", "tier", "licence", "notes",
|
|
7
|
+
"realization", "level", "provenance", "relations", "externalIds", "hashes",
|
|
8
|
+
],
|
|
9
|
+
note: ["pitch", "degree"],
|
|
10
|
+
fretted: ["kind", "instrument", "tuning", "strings", "fingers", "baseFret", "barres", "capo"],
|
|
11
|
+
barre: ["fret", "fromString", "toString"],
|
|
12
|
+
keyboard: ["kind", "hands", "fingering"],
|
|
13
|
+
hands: ["left", "right"],
|
|
14
|
+
fingering: ["left", "right"],
|
|
15
|
+
bowed: ["kind", "instrument", "tuning", "stops", "position"],
|
|
16
|
+
stop: ["string", "pitch", "finger"],
|
|
17
|
+
provenance: ["source", "authorId", "createdAt", "changeNote", "basedOn", "alternativeTo"],
|
|
18
|
+
relations: ["supersedes", "supersededBy", "duplicateOf"],
|
|
19
|
+
hashes: ["shape", "pitch"],
|
|
20
|
+
};
|
|
21
|
+
// Present keys in the given order; absent keys stay absent. Unknown keys are kept at the end
|
|
22
|
+
// (in their original order) so the formatter never drops data; the schema rejects them.
|
|
23
|
+
function order(o, keys, children = {}) {
|
|
24
|
+
if (o === null || typeof o !== "object" || Array.isArray(o))
|
|
25
|
+
return o;
|
|
26
|
+
const src = o;
|
|
27
|
+
// Null-prototype so a `__proto__` key from JSON.parse is plain data, and own-property checks
|
|
28
|
+
// so inherited names (`toString`, `constructor`) are never mistaken for keys.
|
|
29
|
+
const out = Object.create(null);
|
|
30
|
+
const has = (x, k) => Object.prototype.hasOwnProperty.call(x, k);
|
|
31
|
+
const emit = (k) => { out[k] = has(children, k) ? children[k](src[k]) : src[k]; };
|
|
32
|
+
for (const k of keys)
|
|
33
|
+
if (has(src, k) && src[k] !== undefined)
|
|
34
|
+
emit(k);
|
|
35
|
+
for (const k of Object.keys(src))
|
|
36
|
+
if (!has(out, k) && src[k] !== undefined)
|
|
37
|
+
emit(k);
|
|
38
|
+
return out;
|
|
39
|
+
}
|
|
40
|
+
const list = (f) => (v) => (Array.isArray(v) ? v.map(f) : v);
|
|
41
|
+
const K = KEY_ORDER;
|
|
42
|
+
function realization(v) {
|
|
43
|
+
const kind = v?.kind;
|
|
44
|
+
if (kind === "fretted")
|
|
45
|
+
return order(v, K.fretted, { barres: list((b) => order(b, K.barre)) });
|
|
46
|
+
if (kind === "keyboard") {
|
|
47
|
+
return order(v, K.keyboard, {
|
|
48
|
+
hands: (h) => order(h, K.hands),
|
|
49
|
+
fingering: (f) => order(f, K.fingering),
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
if (kind === "bowed")
|
|
53
|
+
return order(v, K.bowed, { stops: list((s) => order(s, K.stop)) });
|
|
54
|
+
return v;
|
|
55
|
+
}
|
|
56
|
+
const voicing = (v) => order(v, K.voicing, {
|
|
57
|
+
notes: list((n) => order(n, K.note)),
|
|
58
|
+
realization,
|
|
59
|
+
provenance: (p) => order(p, K.provenance),
|
|
60
|
+
relations: (r) => order(r, K.relations),
|
|
61
|
+
hashes: (h) => order(h, K.hashes),
|
|
62
|
+
});
|
|
63
|
+
const cmp = (a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : a.rev - b.rev);
|
|
64
|
+
export function formatChordFile(file) {
|
|
65
|
+
const sorted = Array.isArray(file.voicings) ? [...file.voicings].sort(cmp) : file.voicings;
|
|
66
|
+
const out = order({ ...file, voicings: sorted }, K.file, {
|
|
67
|
+
chord: (c) => order(c, K.chord),
|
|
68
|
+
voicings: list(voicing),
|
|
69
|
+
});
|
|
70
|
+
return JSON.stringify(out, null, 2) + "\n";
|
|
71
|
+
}
|
|
72
|
+
export function isCanonical(text) {
|
|
73
|
+
const normalised = text.replace(/^/, "").replace(/\r\n?/g, "\n");
|
|
74
|
+
let parsed;
|
|
75
|
+
try {
|
|
76
|
+
parsed = JSON.parse(normalised);
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
return { ok: false, expected: "" };
|
|
80
|
+
}
|
|
81
|
+
let expected;
|
|
82
|
+
try {
|
|
83
|
+
expected = formatChordFile(parsed);
|
|
84
|
+
}
|
|
85
|
+
catch {
|
|
86
|
+
return { ok: false, expected: "" };
|
|
87
|
+
}
|
|
88
|
+
return { ok: text === expected, expected };
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=canonical.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"canonical.js","sourceRoot":"","sources":["../src/canonical.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
export interface CatalogueIssue {
|
|
2
|
+
path: string;
|
|
3
|
+
code: string;
|
|
4
|
+
message: string;
|
|
5
|
+
}
|
|
6
|
+
export interface CatalogueReport {
|
|
7
|
+
ok: boolean;
|
|
8
|
+
errors: CatalogueIssue[];
|
|
9
|
+
warnings: CatalogueIssue[];
|
|
10
|
+
}
|
|
11
|
+
export declare function chordFilePath(chordId: string): string;
|
|
12
|
+
export declare function validateCatalogue(head: Map<string, string>, base?: Map<string, string>, opts?: {
|
|
13
|
+
licences: string[];
|
|
14
|
+
}): CatalogueReport;
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { isCanonical } from "./canonical.js";
|
|
2
|
+
import { checkVoicing } from "./checks.js";
|
|
3
|
+
import { parseChordId } from "./chordId.js";
|
|
4
|
+
import { withHashes } from "./hash.js";
|
|
5
|
+
import { validateChordFileSchema } from "./schema.js";
|
|
6
|
+
// chords/<root dir>/<encoded id>.json ; `#`->`s`, `/`->`_over_`, `:`->`__` (raw `#` breaks raw/CDN URLs).
|
|
7
|
+
export function chordFilePath(chordId) {
|
|
8
|
+
const encode = (s) => s.replace(/#/g, "s").replace(/\//g, "_over_").replace(/:/g, "__");
|
|
9
|
+
const root = encode(chordId.split(":")[0]);
|
|
10
|
+
return `chords/${root}/${encode(chordId)}.json`;
|
|
11
|
+
}
|
|
12
|
+
const isChordPath = (p) => p.startsWith("chords/") && p.endsWith(".json");
|
|
13
|
+
const stripBom = (s) => s.replace(/^/, "");
|
|
14
|
+
// Key-sorted JSON, so history comparison ignores key order.
|
|
15
|
+
function stable(v) {
|
|
16
|
+
const sort = (x) => {
|
|
17
|
+
if (Array.isArray(x))
|
|
18
|
+
return x.map(sort);
|
|
19
|
+
if (x && typeof x === "object") {
|
|
20
|
+
return Object.fromEntries(Object.keys(x).sort().map((k) => [k, sort(x[k])]));
|
|
21
|
+
}
|
|
22
|
+
return x;
|
|
23
|
+
};
|
|
24
|
+
return JSON.stringify(sort(v));
|
|
25
|
+
}
|
|
26
|
+
// Voicing entries of a file keyed `id@rev`; tolerant of files that do not pass the schema.
|
|
27
|
+
function historyOf(files) {
|
|
28
|
+
const out = new Map();
|
|
29
|
+
for (const [path, text] of files) {
|
|
30
|
+
if (!isChordPath(path))
|
|
31
|
+
continue;
|
|
32
|
+
let data;
|
|
33
|
+
try {
|
|
34
|
+
data = JSON.parse(stripBom(text));
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
const voicings = data?.voicings;
|
|
40
|
+
if (!Array.isArray(voicings))
|
|
41
|
+
continue;
|
|
42
|
+
for (const v of voicings) {
|
|
43
|
+
if (v && typeof v === "object" && typeof v.id === "string")
|
|
44
|
+
out.set(`${v.id}@${v.rev}`, { path, json: stable(v) });
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return out;
|
|
48
|
+
}
|
|
49
|
+
export function validateCatalogue(head, base, opts = { licences: ["CC0-1.0"] }) {
|
|
50
|
+
const errors = [];
|
|
51
|
+
const warnings = [];
|
|
52
|
+
const err = (path, code, message) => errors.push({ path, code, message });
|
|
53
|
+
const warn = (path, code, message) => warnings.push({ path, code, message });
|
|
54
|
+
const parsed = [];
|
|
55
|
+
for (const path of [...head.keys()].filter(isChordPath).sort()) {
|
|
56
|
+
const text = head.get(path);
|
|
57
|
+
let data;
|
|
58
|
+
try {
|
|
59
|
+
data = JSON.parse(stripBom(text));
|
|
60
|
+
}
|
|
61
|
+
catch (e) {
|
|
62
|
+
err(path, "schema", `Not valid JSON: ${e.message}`);
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
65
|
+
const res = validateChordFileSchema(data);
|
|
66
|
+
if (!res.ok) {
|
|
67
|
+
err(path, "schema", res.errors.map((e) => `${e.path || "/"}: ${e.message}`).join("; "));
|
|
68
|
+
continue;
|
|
69
|
+
}
|
|
70
|
+
parsed.push({ path, file: res.value });
|
|
71
|
+
}
|
|
72
|
+
const idFiles = new Map(); // voicing id -> first file
|
|
73
|
+
for (const { path, file } of parsed) {
|
|
74
|
+
if (!isCanonical(head.get(path)).ok)
|
|
75
|
+
err(path, "not-canonical", "File is not in canonical form; run the formatter");
|
|
76
|
+
const chordOk = parseChordId(file.chord.id) !== null;
|
|
77
|
+
if (!chordOk)
|
|
78
|
+
err(path, "chord-id", `Invalid chord id "${file.chord.id}"`);
|
|
79
|
+
else {
|
|
80
|
+
const p = parseChordId(file.chord.id);
|
|
81
|
+
if (file.chord.root !== p.root || file.chord.quality !== p.quality || file.chord.bass !== p.bass) {
|
|
82
|
+
err(path, "chord-id", `chord root/quality/bass (${file.chord.root}, ${file.chord.quality}, ${file.chord.bass}) disagree with id "${file.chord.id}"`);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
if (chordOk && chordFilePath(file.chord.id) !== path)
|
|
86
|
+
err(path, "path-mismatch", `Expected path ${chordFilePath(file.chord.id)}`);
|
|
87
|
+
const revs = new Map();
|
|
88
|
+
for (const v of file.voicings) {
|
|
89
|
+
if (v.chordId !== file.chord.id)
|
|
90
|
+
err(path, "chord-id", `${v.id}@${v.rev}: chordId "${v.chordId}" differs from chord.id "${file.chord.id}"`);
|
|
91
|
+
if (!opts.licences.includes(v.licence))
|
|
92
|
+
err(path, "licence", `${v.id}@${v.rev}: licence "${v.licence}" is not allowed`);
|
|
93
|
+
try {
|
|
94
|
+
const h = withHashes(v).hashes;
|
|
95
|
+
if (h.shape !== v.hashes.shape || h.pitch !== v.hashes.pitch)
|
|
96
|
+
err(path, "hash-mismatch", `${v.id}@${v.rev}: stored hashes do not match the content`);
|
|
97
|
+
}
|
|
98
|
+
catch (e) {
|
|
99
|
+
err(path, "hash-mismatch", `${v.id}@${v.rev}: cannot compute hashes: ${e.message}`);
|
|
100
|
+
}
|
|
101
|
+
const res = checkVoicing(v);
|
|
102
|
+
for (const f of res.hard)
|
|
103
|
+
err(path, `check:${f.code}`, `${v.id}@${v.rev}: ${f.message}`);
|
|
104
|
+
for (const f of res.flags)
|
|
105
|
+
warn(path, `check:${f.code}`, `${v.id}@${v.rev}: ${f.message}`);
|
|
106
|
+
revs.set(v.id, [...(revs.get(v.id) ?? []), v]);
|
|
107
|
+
}
|
|
108
|
+
for (const [id, list] of revs) {
|
|
109
|
+
const sorted = [...list].sort((a, b) => a.rev - b.rev);
|
|
110
|
+
const bad = sorted.some((v, i) => v.rev !== i + 1 || v.previous !== (i === 0 ? null : i));
|
|
111
|
+
if (bad)
|
|
112
|
+
err(path, "rev-chain", `${id}: revisions must be 1..n with previous = rev-1 (rev 1 previous null)`);
|
|
113
|
+
const first = idFiles.get(id);
|
|
114
|
+
if (first === undefined)
|
|
115
|
+
idFiles.set(id, path);
|
|
116
|
+
else if (first !== path)
|
|
117
|
+
err(path, "id-reused", `${id} is already used in ${first}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
// Latest rev per id across files; only live ones are compared for duplicates.
|
|
121
|
+
const latest = new Map();
|
|
122
|
+
for (const { path, file } of parsed) {
|
|
123
|
+
for (const v of file.voicings) {
|
|
124
|
+
const cur = latest.get(v.id);
|
|
125
|
+
if (!cur || v.rev > cur.v.rev)
|
|
126
|
+
latest.set(v.id, { path, v });
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
const live = [...latest.values()].filter((e) => e.v.status === "live").sort((a, b) => (a.v.id < b.v.id ? -1 : 1));
|
|
130
|
+
const group = (key, report) => {
|
|
131
|
+
const seen = new Map();
|
|
132
|
+
for (const e of live) {
|
|
133
|
+
const k = key(e.v);
|
|
134
|
+
const first = seen.get(k);
|
|
135
|
+
if (first)
|
|
136
|
+
report(e, first);
|
|
137
|
+
else
|
|
138
|
+
seen.set(k, e);
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
group((v) => `${v.chordId}\u0000${v.hashes.shape}`, (e, f) => err(e.path, "duplicate-shape", `${e.v.id} has the same shape as ${f.v.id} for ${e.v.chordId}`));
|
|
142
|
+
group((v) => v.hashes.shape, (e, f) => {
|
|
143
|
+
if (e.v.chordId !== f.v.chordId)
|
|
144
|
+
warn(e.path, "same-shape-other-chord", `${e.v.id} (${e.v.chordId}) has the same shape as ${f.v.id} (${f.v.chordId})`);
|
|
145
|
+
});
|
|
146
|
+
group((v) => v.hashes.pitch, (e, f) => {
|
|
147
|
+
if (e.v.hashes.shape !== f.v.hashes.shape) {
|
|
148
|
+
warn(e.path, "same-pitch", `${e.v.id} sounds the same pitches as ${f.v.id}`);
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
if (base) {
|
|
152
|
+
const before = historyOf(base);
|
|
153
|
+
const after = historyOf(new Map([...head].filter(([p]) => isChordPath(p))));
|
|
154
|
+
for (const [key, b] of before) {
|
|
155
|
+
const h = after.get(key);
|
|
156
|
+
if (!h)
|
|
157
|
+
err(b.path, "removed-history", `${key} was removed`);
|
|
158
|
+
else if (h.json !== b.json)
|
|
159
|
+
err(h.path, "modified-history", `${key} was modified; history is append-only`);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return { ok: errors.length === 0, errors, warnings };
|
|
163
|
+
}
|
|
164
|
+
//# sourceMappingURL=catalogue.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalogue.js","sourceRoot":"","sources":["../src/catalogue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAC7C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,uBAAuB,EAAE,MAAM,aAAa,CAAC;AAMtD,0GAA0G;AAC1G,MAAM,UAAU,aAAa,CAAC,OAAe;IAC3C,MAAM,MAAM,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAChG,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3C,OAAO,UAAU,IAAI,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC;AAClD,CAAC;AAED,MAAM,WAAW,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;AAClF,MAAM,QAAQ,GAAG,CAAC,CAAS,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AAEpD,4DAA4D;AAC5D,SAAS,MAAM,CAAC,CAAU;IACxB,MAAM,IAAI,GAAG,CAAC,CAAU,EAAW,EAAE;QACnC,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACzC,IAAI,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,EAAE,CAAC;YAC/B,OAAO,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,CAAE,CAA6B,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5G,CAAC;QACD,OAAO,CAAC,CAAC;IACX,CAAC,CAAC;IACF,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AACjC,CAAC;AAED,2FAA2F;AAC3F,SAAS,SAAS,CAAC,KAA0B;IAC3C,MAAM,GAAG,GAAG,IAAI,GAAG,EAA0C,CAAC;IAC9D,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,KAAK,EAAE,CAAC;QACjC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC;YAAE,SAAS;QACjC,IAAI,IAAa,CAAC;QAClB,IAAI,CAAC;YAAC,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;QAAC,CAAC;QAAC,MAAM,CAAC;YAAC,SAAS;QAAC,CAAC;QAC9D,MAAM,QAAQ,GAAI,IAA+B,EAAE,QAAQ,CAAC;QAC5D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;YAAE,SAAS;QACvC,KAAK,MAAM,CAAC,IAAI,QAAqB,EAAE,CAAC;YACtC,IAAI,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,OAAO,CAAC,CAAC,EAAE,KAAK,QAAQ;gBAAE,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QACrH,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,MAAM,UAAU,iBAAiB,CAC/B,IAAyB,EACzB,IAA0B,EAC1B,OAA+B,EAAE,QAAQ,EAAE,CAAC,SAAS,CAAC,EAAE;IAExD,MAAM,MAAM,GAAqB,EAAE,CAAC;IACpC,MAAM,QAAQ,GAAqB,EAAE,CAAC;IACtC,MAAM,GAAG,GAAG,CAAC,IAAY,EAAE,IAAY,EAAE,OAAe,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IAClG,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,IAAY,EAAE,OAAe,EAAE,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;IAErG,MAAM,MAAM,GAAwC,EAAE,CAAC;IACvD,KAAK,MAAM,IAAI,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC;QAC/D,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAE,CAAC;QAC7B,IAAI,IAAa,CAAC;QAClB,IAAI,CAAC;YACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;QACpC,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,GAAG,CAAC,IAAI,EAAE,QAAQ,EAAE,mBAAoB,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;YAC/D,SAAS;QACX,CAAC;QACD,MAAM,GAAG,GAAG,uBAAuB,CAAC,IAAI,CAAC,CAAC;QAC1C,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,GAAG,CAAC,IAAI,EAAE,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,IAAI,GAAG,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;YACxF,SAAS;QACX,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC;IACzC,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,GAAG,EAAkB,CAAC,CAAC,2BAA2B;IACtE,KAAK,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,MAAM,EAAE,CAAC;QACpC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAE,CAAC,CAAC,EAAE;YAAE,GAAG,CAAC,IAAI,EAAE,eAAe,EAAE,kDAAkD,CAAC,CAAC;QACrH,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,IAAI,CAAC;QACrD,IAAI,CAAC,OAAO;YAAE,GAAG,CAAC,IAAI,EAAE,UAAU,EAAE,qBAAqB,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC;aACtE,CAAC;YACJ,MAAM,CAAC,GAAG,YAAY,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAE,CAAC;YACvC,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,KAAK,CAAC,CAAC,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,EAAE,CAAC;gBACjG,GAAG,CAAC,IAAI,EAAE,UAAU,EAAE,4BAA4B,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,OAAO,KAAK,IAAI,CAAC,KAAK,CAAC,IAAI,uBAAuB,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC;YACvJ,CAAC;QACH,CAAC;QACD,IAAI,OAAO,IAAI,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,KAAK,IAAI;YAAE,GAAG,CAAC,IAAI,EAAE,eAAe,EAAE,iBAAiB,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QAElI,MAAM,IAAI,GAAG,IAAI,GAAG,EAAqB,CAAC;QAC1C,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC9B,IAAI,CAAC,CAAC,OAAO,KAAK,IAAI,CAAC,KAAK,CAAC,EAAE;gBAAE,GAAG,CAAC,IAAI,EAAE,UAAU,EAAE,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,OAAO,4BAA4B,IAAI,CAAC,KAAK,CAAC,EAAE,GAAG,CAAC,CAAC;YAC5I,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC;gBAAE,GAAG,CAAC,IAAI,EAAE,SAAS,EAAE,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,OAAO,kBAAkB,CAAC,CAAC;YACxH,IAAI,CAAC;gBACH,MAAM,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;gBAC/B,IAAI,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK;oBAAE,GAAG,CAAC,IAAI,EAAE,eAAe,EAAE,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,0CAA0C,CAAC,CAAC;YACvJ,CAAC;YAAC,OAAO,CAAC,EAAE,CAAC;gBACX,GAAG,CAAC,IAAI,EAAE,eAAe,EAAE,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,4BAA6B,CAAW,CAAC,OAAO,EAAE,CAAC,CAAC;YACjG,CAAC;YACD,MAAM,GAAG,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;YAC5B,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,IAAI;gBAAE,GAAG,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;YACzF,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,KAAK;gBAAE,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,IAAI,EAAE,EAAE,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;YAC3F,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;QACjD,CAAC;QACD,KAAK,MAAM,CAAC,EAAE,EAAE,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;YAC9B,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;YACvD,MAAM,GAAG,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC1F,IAAI,GAAG;gBAAE,GAAG,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,sEAAsE,CAAC,CAAC;YAC7G,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YAC9B,IAAI,KAAK,KAAK,SAAS;gBAAE,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;iBAC1C,IAAI,KAAK,KAAK,IAAI;gBAAE,GAAG,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,uBAAuB,KAAK,EAAE,CAAC,CAAC;QACvF,CAAC;IACH,CAAC;IAED,8EAA8E;IAC9E,MAAM,MAAM,GAAG,IAAI,GAAG,EAAwC,CAAC;IAC/D,KAAK,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,MAAM,EAAE,CAAC;QACpC,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC9B,MAAM,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YAC7B,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG;gBAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC;QAC/D,CAAC;IACH,CAAC;IACD,MAAM,IAAI,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IAClH,MAAM,KAAK,GAAG,CAAC,GAA2B,EAAE,MAAsF,EAAE,EAAE;QACpI,MAAM,IAAI,GAAG,IAAI,GAAG,EAAwC,CAAC;QAC7D,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;YACrB,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YACnB,MAAM,KAAK,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YAC1B,IAAI,KAAK;gBAAE,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;;gBACvB,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACtB,CAAC;IACH,CAAC,CAAC;IACF,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,OAAO,SAAS,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,iBAAiB,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,0BAA0B,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;IAC9J,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACpC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO;YAAE,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,wBAAwB,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,2BAA2B,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC;IACzJ,CAAC,CAAC,CAAC;IACH,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACpC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YAC1C,IAAI,CAAC,CAAC,CAAC,IAAI,EAAE,YAAY,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,+BAA+B,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QAC/E,CAAC;IACH,CAAC,CAAC,CAAC;IAEH,IAAI,IAAI,EAAE,CAAC;QACT,MAAM,MAAM,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAC/B,MAAM,KAAK,GAAG,SAAS,CAAC,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5E,KAAK,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,MAAM,EAAE,CAAC;YAC9B,MAAM,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YACzB,IAAI,CAAC,CAAC;gBAAE,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,iBAAiB,EAAE,GAAG,GAAG,cAAc,CAAC,CAAC;iBACxD,IAAI,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI;gBAAE,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,kBAAkB,EAAE,GAAG,GAAG,uCAAuC,CAAC,CAAC;QAC7G,CAAC;IACH,CAAC;IAED,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;AACvD,CAAC"}
|
package/dist/checks.d.ts
ADDED