keepset 0.3.0 → 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bundled-P_132GDn.js +46192 -0
- package/dist/{categories-BIZJUKUw.d.ts → categories-CUf1VecC.d.ts} +23 -23
- package/dist/index.d.ts +9 -1
- package/dist/index.js +41 -3
- package/dist/node/fetch-dataset.d.ts +29 -3
- package/dist/node/fetch-dataset.js +174 -36
- package/dist-cli/keepset.mjs +246 -0
- package/package.json +7 -1
- package/schemas/entry.schema.json +1 -1
- package/schemas/manifest.schema.json +1 -1
- package/dist/bundled--fOitQlP.js +0 -621
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { writeFileSync } from "node:fs";
|
|
3
|
+
import { KeepsetError, countTarget, getDataset, listDatasets, validateDataset } from "keepset";
|
|
4
|
+
import { fetchDataset, roundTripDataset } from "keepset/node";
|
|
5
|
+
import { parseArgs } from "node:util";
|
|
6
|
+
//#region package.json
|
|
7
|
+
var version = "0.5.0";
|
|
8
|
+
const usage = `Usage: keepset <command> [options]
|
|
9
|
+
|
|
10
|
+
Commands:
|
|
11
|
+
search [text] [--kind <kind>] [--domain <domain>] [--category <id>] [--json]
|
|
12
|
+
list the datasets whose id, name, description, domain or
|
|
13
|
+
tags contain the text, filtered by kind, domain or category
|
|
14
|
+
show <id> [--json] print a dataset's metadata, recipe and crosswalk
|
|
15
|
+
fetch <id> [--out <file>]
|
|
16
|
+
run the dataset's recipe and write the normalised result
|
|
17
|
+
to <file> (default <id>.json), with its provenance beside
|
|
18
|
+
it in <file without .json>.provenance.json
|
|
19
|
+
validate <id> check the entry against the entry schema and its
|
|
20
|
+
crosswalk against twindex's validation
|
|
21
|
+
roundtrip <id> fetch the dataset and check that decoding the encoded
|
|
22
|
+
native document gives it back
|
|
23
|
+
|
|
24
|
+
Options:
|
|
25
|
+
--help, -h print this help
|
|
26
|
+
--version, -v print the version
|
|
27
|
+
|
|
28
|
+
Exit status: 0 for a result, a valid entry or a round trip that holds; 1 for an
|
|
29
|
+
invalid entry or a round trip that does not hold; 2 when there is no answer:
|
|
30
|
+
bad usage, an unknown dataset or a recipe that failed.
|
|
31
|
+
`;
|
|
32
|
+
function parseCommandLine(args) {
|
|
33
|
+
return parseArgs({
|
|
34
|
+
args: [...args],
|
|
35
|
+
allowPositionals: true,
|
|
36
|
+
strict: true,
|
|
37
|
+
options: {
|
|
38
|
+
kind: { type: "string" },
|
|
39
|
+
domain: { type: "string" },
|
|
40
|
+
category: { type: "string" },
|
|
41
|
+
json: { type: "boolean" },
|
|
42
|
+
out: { type: "string" },
|
|
43
|
+
help: {
|
|
44
|
+
type: "boolean",
|
|
45
|
+
short: "h"
|
|
46
|
+
},
|
|
47
|
+
version: {
|
|
48
|
+
type: "boolean",
|
|
49
|
+
short: "v"
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* JSON as the command prints it: two-space indented, with a trailing newline.
|
|
56
|
+
* @param value - The value.
|
|
57
|
+
* @returns The text.
|
|
58
|
+
*/
|
|
59
|
+
function json(value) {
|
|
60
|
+
return `${JSON.stringify(value, void 0, 2)}\n`;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* One line per dataset for `search`: id, name, category and whether its recipe can run, tab-separated so the output pipes into other tools.
|
|
64
|
+
* @param datasets - The datasets.
|
|
65
|
+
* @returns The text.
|
|
66
|
+
*/
|
|
67
|
+
function formatSearch(datasets) {
|
|
68
|
+
return datasets.map(({ entry }) => `${entry.id}\t${entry.name}\t${entry.category}\t${entry.recipe.status}\n`).join("");
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* The human-readable form of `show`: the descriptor, sources, licence, citations, recipe and crosswalk rules, one labelled section after another.
|
|
72
|
+
* @param dataset - The dataset.
|
|
73
|
+
* @returns The text.
|
|
74
|
+
*/
|
|
75
|
+
function formatShow(dataset) {
|
|
76
|
+
const { entry, crosswalk } = dataset;
|
|
77
|
+
const lines = [`${entry.name} (${entry.id})`];
|
|
78
|
+
if (entry.description !== void 0) lines.push("", entry.description);
|
|
79
|
+
lines.push("", `category: ${entry.category} (kind ${dataset.kind})`, `catalogue: ${dataset.catalogue.id} ${dataset.catalogue.version}`);
|
|
80
|
+
if (entry.domain !== void 0) lines.push(`domain: ${entry.domain}`);
|
|
81
|
+
if (entry.tags.length > 0) lines.push(`tags: ${entry.tags.join(", ")}`);
|
|
82
|
+
const { licence } = entry;
|
|
83
|
+
lines.push(`licence: ${licence.kind === "spdx" ? licence.id : licence.kind === "custom" ? `${licence.name} <${licence.url}>` : "not recorded by the source"}`);
|
|
84
|
+
lines.push("", "sources:");
|
|
85
|
+
for (const [index, source] of entry.sources.entries()) {
|
|
86
|
+
const snapshot = source.snapshot === void 0 ? "" : `, snapshot ${source.snapshot.timestamp}`;
|
|
87
|
+
lines.push(` [${String(index)}] ${source.url} (${source.status}, retrieved ${source.retrieved}${snapshot})`);
|
|
88
|
+
}
|
|
89
|
+
if (entry.citations.length > 0) {
|
|
90
|
+
lines.push("", "citations:");
|
|
91
|
+
for (const citation of entry.citations) {
|
|
92
|
+
const link = citation.doi === void 0 ? citation.url === void 0 ? "" : ` <${citation.url}>` : ` doi:${citation.doi}`;
|
|
93
|
+
lines.push(` ${citation.text}${link}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
const { recipe } = entry;
|
|
97
|
+
lines.push("", "recipe:");
|
|
98
|
+
if (recipe.status === "not-fetchable") lines.push(` not fetchable: ${recipe.reason}`);
|
|
99
|
+
else {
|
|
100
|
+
const { member } = "member" in recipe.archive ? recipe.archive : { member: void 0 };
|
|
101
|
+
const memberText = member === void 0 ? "" : "path" in member ? `, member ${member.path}` : `, member ending ${member.extensions.join(" or ")}`;
|
|
102
|
+
const { format, ...options } = recipe.parser;
|
|
103
|
+
lines.push(` source: [${String(recipe.source)}]`, ` archive: ${recipe.archive.kind}${memberText}`, ` parser: ${format} ${JSON.stringify(options)}`);
|
|
104
|
+
}
|
|
105
|
+
lines.push("", `crosswalk: ${crosswalk.source} -> ${crosswalk.target}`);
|
|
106
|
+
for (const rule of crosswalk.rules) lines.push(` ${rule.op} ${rule.from} -> ${rule.to}`);
|
|
107
|
+
for (const rule of crosswalk.oneWay) lines.push(rule.op === "drop" ? ` drop ${rule.from} (encode)` : ` default ${rule.to} = ${JSON.stringify(rule.value)} (${rule.direction})`);
|
|
108
|
+
const counts = Object.entries(entry.expectedCounts);
|
|
109
|
+
if (counts.length > 0) lines.push("", `expected counts: ${counts.map(([key, count]) => `${key} ${String(count)}`).join(", ")}`);
|
|
110
|
+
const properties = Object.entries(entry.properties);
|
|
111
|
+
if (properties.length > 0) lines.push("", "properties:", ...properties.map(([key, value]) => ` ${key}: ${JSON.stringify(value)}`));
|
|
112
|
+
return `${lines.join("\n")}\n`;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Where `fetch` writes provenance: beside the result, `.json` replaced by `.provenance.json` (or the suffix appended to a path without one).
|
|
116
|
+
* @param out - The result path.
|
|
117
|
+
* @returns The provenance path.
|
|
118
|
+
*/
|
|
119
|
+
function provenancePath(out) {
|
|
120
|
+
return out.endsWith(".json") ? `${out.slice(0, -5)}.provenance.json` : `${out}.provenance.json`;
|
|
121
|
+
}
|
|
122
|
+
/**
|
|
123
|
+
* Formats a list of validation issues, one per line.
|
|
124
|
+
* @param issues - The issues.
|
|
125
|
+
* @returns The text.
|
|
126
|
+
*/
|
|
127
|
+
function formatIssues(issues) {
|
|
128
|
+
return issues.map((issue) => `${issue.path}: ${issue.message}\n`).join("");
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* Runs the command. A KeepsetError from the library (an unknown dataset, a failing recipe) is the command's failure to answer and becomes exit status 2 with its message; anything else is a bug and propagates.
|
|
132
|
+
* @param args - The arguments after the command name.
|
|
133
|
+
* @param library - The library calls.
|
|
134
|
+
* @param io - Output.
|
|
135
|
+
* @returns The exit status.
|
|
136
|
+
*/
|
|
137
|
+
async function run(args, library, io) {
|
|
138
|
+
let parsed;
|
|
139
|
+
try {
|
|
140
|
+
parsed = parseCommandLine(args);
|
|
141
|
+
} catch (error) {
|
|
142
|
+
io.writeStderr(`${error instanceof Error ? error.message : String(error)}\n\n${usage}`);
|
|
143
|
+
return 2;
|
|
144
|
+
}
|
|
145
|
+
const { values, positionals } = parsed;
|
|
146
|
+
if (values.version === true) {
|
|
147
|
+
io.writeStdout(`${io.version}\n`);
|
|
148
|
+
return 0;
|
|
149
|
+
}
|
|
150
|
+
if (values.help === true) {
|
|
151
|
+
io.writeStdout(usage);
|
|
152
|
+
return 0;
|
|
153
|
+
}
|
|
154
|
+
const [command, ...rest] = positionals;
|
|
155
|
+
const reject = (message) => {
|
|
156
|
+
io.writeStderr(`${message}\n\n${usage}`);
|
|
157
|
+
return 2;
|
|
158
|
+
};
|
|
159
|
+
try {
|
|
160
|
+
if (command === "search") {
|
|
161
|
+
if (rest.length > 1) return reject("search takes at most one text argument; quote a phrase");
|
|
162
|
+
const [text] = rest;
|
|
163
|
+
const query = {
|
|
164
|
+
...text === void 0 ? {} : { text },
|
|
165
|
+
...values.kind === void 0 ? {} : { kind: values.kind },
|
|
166
|
+
...values.domain === void 0 ? {} : { domain: values.domain },
|
|
167
|
+
...values.category === void 0 ? {} : { category: values.category }
|
|
168
|
+
};
|
|
169
|
+
const datasets = library.listDatasets(query);
|
|
170
|
+
io.writeStdout(values.json === true ? json(datasets.map((dataset) => dataset.entry)) : formatSearch(datasets));
|
|
171
|
+
return 0;
|
|
172
|
+
}
|
|
173
|
+
const [id, ...extra] = rest;
|
|
174
|
+
if (command === void 0) return reject("expected a command");
|
|
175
|
+
if (![
|
|
176
|
+
"show",
|
|
177
|
+
"fetch",
|
|
178
|
+
"validate",
|
|
179
|
+
"roundtrip"
|
|
180
|
+
].includes(command)) return reject(`unknown command ${command}`);
|
|
181
|
+
if (id === void 0 || extra.length > 0) return reject(`${command} takes exactly one dataset id`);
|
|
182
|
+
if (command === "show") {
|
|
183
|
+
const dataset = library.getDataset(id);
|
|
184
|
+
io.writeStdout(values.json === true ? json(dataset) : formatShow(dataset));
|
|
185
|
+
return 0;
|
|
186
|
+
}
|
|
187
|
+
if (command === "validate") {
|
|
188
|
+
const issues = library.validateDataset(library.getDataset(id));
|
|
189
|
+
if (issues.length > 0) {
|
|
190
|
+
io.writeStdout(formatIssues(issues));
|
|
191
|
+
return 1;
|
|
192
|
+
}
|
|
193
|
+
io.writeStdout(`${id} is valid\n`);
|
|
194
|
+
return 0;
|
|
195
|
+
}
|
|
196
|
+
if (command === "fetch") {
|
|
197
|
+
const fetched = await library.fetchDataset(id);
|
|
198
|
+
const out = values.out ?? `${id}.json`;
|
|
199
|
+
io.writeFile(out, json(fetched.data));
|
|
200
|
+
io.writeFile(provenancePath(out), json(fetched.provenance));
|
|
201
|
+
for (const warning of fetched.warnings) io.writeStderr(`warning: ${warning}\n`);
|
|
202
|
+
const counts = [...library.countTarget(fetched)].map(([key, count]) => `${key} ${String(count)}`).join(", ");
|
|
203
|
+
io.writeStdout(`wrote ${out} (${counts}) and ${provenancePath(out)}\n`);
|
|
204
|
+
return 0;
|
|
205
|
+
}
|
|
206
|
+
const report = await library.roundTripDataset(id);
|
|
207
|
+
if (report.holds) {
|
|
208
|
+
io.writeStdout(`${id}: the round trip holds\n`);
|
|
209
|
+
return 0;
|
|
210
|
+
}
|
|
211
|
+
io.writeStdout(`${id}: the round trip does not hold at ${report.path === "" ? "(root)" : report.path}: ${report.message}\n`);
|
|
212
|
+
return 1;
|
|
213
|
+
} catch (error) {
|
|
214
|
+
if (error instanceof KeepsetError) {
|
|
215
|
+
io.writeStderr(`${error.message}\n`);
|
|
216
|
+
return 2;
|
|
217
|
+
}
|
|
218
|
+
throw error;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
//#endregion
|
|
222
|
+
//#region cli/keepset.ts
|
|
223
|
+
process.stdout.on("error", (error) => {
|
|
224
|
+
if (error.code !== "EPIPE") throw error;
|
|
225
|
+
});
|
|
226
|
+
process.exitCode = await run(process.argv.slice(2), {
|
|
227
|
+
listDatasets,
|
|
228
|
+
getDataset,
|
|
229
|
+
validateDataset,
|
|
230
|
+
fetchDataset: async (id) => fetchDataset(id),
|
|
231
|
+
roundTripDataset: async (id) => roundTripDataset(id),
|
|
232
|
+
countTarget: (fetched) => countTarget(fetched.dataset.entry.category, fetched.data)
|
|
233
|
+
}, {
|
|
234
|
+
writeStdout: (text) => {
|
|
235
|
+
process.stdout.write(text);
|
|
236
|
+
},
|
|
237
|
+
writeStderr: (text) => {
|
|
238
|
+
process.stderr.write(text);
|
|
239
|
+
},
|
|
240
|
+
writeFile: (path, text) => {
|
|
241
|
+
writeFileSync(path, text, "utf8");
|
|
242
|
+
},
|
|
243
|
+
version
|
|
244
|
+
});
|
|
245
|
+
//#endregion
|
|
246
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "keepset",
|
|
3
3
|
"description": "Library, CLI and statically generated catalogue for dataset fetch-and-normalise recipes",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.5.0",
|
|
5
|
+
"bin": {
|
|
6
|
+
"keepset": "./dist-cli/keepset.mjs"
|
|
7
|
+
},
|
|
5
8
|
"dependencies": {
|
|
6
9
|
"fflate": "0.8.3",
|
|
7
10
|
"twindex": "0.1.1",
|
|
@@ -49,6 +52,7 @@
|
|
|
49
52
|
},
|
|
50
53
|
"files": [
|
|
51
54
|
"dist",
|
|
55
|
+
"dist-cli",
|
|
52
56
|
"schemas"
|
|
53
57
|
],
|
|
54
58
|
"keywords": [
|
|
@@ -79,6 +83,8 @@
|
|
|
79
83
|
"lint:check": "eslint . --cache --max-warnings 0",
|
|
80
84
|
"prepare": "husky",
|
|
81
85
|
"prepublishOnly": "pnpm run lint:check && pnpm run build && pnpm run typecheck && pnpm run test && publint && attw --pack --profile esm-only",
|
|
86
|
+
"seed:check": "tsx scripts/seed/import-phd-catalogue.ts --pipeline scripts/seed/sources/pipeline-catalog.json --graphbox scripts/seed/sources/graphbox-catalog.json --check",
|
|
87
|
+
"seed:import": "tsx scripts/seed/import-phd-catalogue.ts",
|
|
82
88
|
"test": "vitest run",
|
|
83
89
|
"typecheck": "tsc -p tsconfig.json && tsc -p tsconfig.node.json"
|
|
84
90
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"$defs":{"Crosswalk":{"$ref":"https://cdn.jsdelivr.net/npm/twindex@0.1.1/schemas/twindex.schema.json"},"Entry":{"additionalProperties":false,"properties":{"category":{"enum":["graph/v1"],"type":"string"},"citations":{"items":{"additionalProperties":false,"properties":{"doi":{"pattern":"^10\\.\\d{4,9}\\/\\S+$","type":"string"},"text":{"minLength":1,"type":"string"},"url":{"format":"uri","type":"string"}},"required":["text"],"type":"object"},"type":"array"},"crosswalk":{"anyOf":[{"$ref":"#/$defs/Crosswalk"},{"additionalProperties":false,"properties":{"file":{"type":"string"}},"required":["file"],"type":"object"}]},"description":{"minLength":1,"type":"string"},"domain":{"minLength":1,"type":"string"},"expectedCounts":{"additionalProperties":{"maximum":9007199254740991,"minimum":0,"type":"integer"},"propertyNames":{"pattern":"^[A-Za-z][A-Za-z0-9]*$","type":"string"},"type":"object"},"id":{"pattern":"^[A-Za-z0-9][A-Za-z0-9._-]*$","type":"string"},"licence":{"oneOf":[{"additionalProperties":false,"properties":{"id":{"pattern":"^[A-Za-z0-9][A-Za-z0-9.+-]*$","type":"string"},"kind":{"const":"spdx","type":"string"}},"required":["kind","id"],"type":"object"},{"additionalProperties":false,"properties":{"kind":{"const":"custom","type":"string"},"name":{"minLength":1,"type":"string"},"url":{"format":"uri","type":"string"}},"required":["kind","name","url"],"type":"object"},{"additionalProperties":false,"properties":{"kind":{"const":"unrecorded","type":"string"}},"required":["kind"],"type":"object"}]},"name":{"minLength":1,"type":"string"},"properties":{"additionalProperties":{"type":["string","number","boolean","null"]},"propertyNames":{"pattern":"^[A-Za-z][A-Za-z0-9]*$","type":"string"},"type":"object"},"recipe":{"oneOf":[{"additionalProperties":false,"properties":{"archive":{"oneOf":[{"additionalProperties":false,"properties":{"kind":{"const":"none","type":"string"}},"required":["kind"],"type":"object"},{"additionalProperties":false,"properties":{"kind":{"const":"gzip","type":"string"}},"required":["kind"],"type":"object"},{"additionalProperties":false,"properties":{"kind":{"const":"zip","type":"string"},"member":{"anyOf":[{"additionalProperties":false,"properties":{"path":{"type":"string"}},"required":["path"],"type":"object"},{"additionalProperties":false,"properties":{"
|
|
1
|
+
{"$defs":{"Crosswalk":{"$ref":"https://cdn.jsdelivr.net/npm/twindex@0.1.1/schemas/twindex.schema.json"},"Entry":{"additionalProperties":false,"properties":{"category":{"enum":["graph/v1"],"type":"string"},"citations":{"items":{"additionalProperties":false,"properties":{"doi":{"pattern":"^10\\.\\d{4,9}\\/\\S+$","type":"string"},"text":{"minLength":1,"type":"string"},"url":{"format":"uri","type":"string"}},"required":["text"],"type":"object"},"type":"array"},"crosswalk":{"anyOf":[{"$ref":"#/$defs/Crosswalk"},{"additionalProperties":false,"properties":{"file":{"type":"string"}},"required":["file"],"type":"object"}]},"description":{"minLength":1,"type":"string"},"domain":{"minLength":1,"type":"string"},"expectedCounts":{"additionalProperties":{"maximum":9007199254740991,"minimum":0,"type":"integer"},"propertyNames":{"pattern":"^[A-Za-z][A-Za-z0-9]*$","type":"string"},"type":"object"},"id":{"pattern":"^[A-Za-z0-9][A-Za-z0-9._-]*$","type":"string"},"licence":{"oneOf":[{"additionalProperties":false,"properties":{"id":{"pattern":"^[A-Za-z0-9][A-Za-z0-9.+-]*$","type":"string"},"kind":{"const":"spdx","type":"string"}},"required":["kind","id"],"type":"object"},{"additionalProperties":false,"properties":{"kind":{"const":"custom","type":"string"},"name":{"minLength":1,"type":"string"},"url":{"format":"uri","type":"string"}},"required":["kind","name","url"],"type":"object"},{"additionalProperties":false,"properties":{"kind":{"const":"unrecorded","type":"string"}},"required":["kind"],"type":"object"}]},"name":{"minLength":1,"type":"string"},"properties":{"additionalProperties":{"type":["string","number","boolean","null"]},"propertyNames":{"pattern":"^[A-Za-z][A-Za-z0-9]*$","type":"string"},"type":"object"},"recipe":{"oneOf":[{"additionalProperties":false,"properties":{"archive":{"oneOf":[{"additionalProperties":false,"properties":{"kind":{"const":"none","type":"string"}},"required":["kind"],"type":"object"},{"additionalProperties":false,"properties":{"kind":{"const":"gzip","type":"string"}},"required":["kind"],"type":"object"},{"additionalProperties":false,"properties":{"kind":{"const":"zip","type":"string"},"member":{"anyOf":[{"additionalProperties":false,"properties":{"path":{"type":"string"}},"required":["path"],"type":"object"},{"additionalProperties":false,"properties":{"extensions":{"items":{"pattern":"^\\.[A-Za-z0-9][A-Za-z0-9.]*$","type":"string"},"minItems":1,"type":"array"}},"required":["extensions"],"type":"object"}]}},"required":["kind","member"],"type":"object"},{"additionalProperties":false,"properties":{"kind":{"const":"tar","type":"string"},"member":{"anyOf":[{"additionalProperties":false,"properties":{"path":{"type":"string"}},"required":["path"],"type":"object"},{"additionalProperties":false,"properties":{"extensions":{"items":{"pattern":"^\\.[A-Za-z0-9][A-Za-z0-9.]*$","type":"string"},"minItems":1,"type":"array"}},"required":["extensions"],"type":"object"}]}},"required":["kind","member"],"type":"object"},{"additionalProperties":false,"properties":{"kind":{"const":"tar.gz","type":"string"},"member":{"anyOf":[{"additionalProperties":false,"properties":{"path":{"type":"string"}},"required":["path"],"type":"object"},{"additionalProperties":false,"properties":{"extensions":{"items":{"pattern":"^\\.[A-Za-z0-9][A-Za-z0-9.]*$","type":"string"},"minItems":1,"type":"array"}},"required":["extensions"],"type":"object"}]}},"required":["kind","member"],"type":"object"}]},"parser":{"oneOf":[{"additionalProperties":false,"properties":{"commentPrefixes":{"items":{"minLength":1,"type":"string"},"type":"array"},"delimiter":{"enum":["detect","whitespace","tab","comma","space"],"type":"string"},"encoding":{"enum":["utf-8","latin1"],"type":"string"},"format":{"const":"edge-list","type":"string"},"skipLines":{"maximum":9007199254740991,"minimum":0,"type":"integer"},"sourceColumn":{"maximum":9007199254740991,"minimum":0,"type":"integer"},"targetColumn":{"maximum":9007199254740991,"minimum":0,"type":"integer"}},"required":["format","encoding","delimiter","skipLines","commentPrefixes","sourceColumn","targetColumn"],"type":"object"},{"additionalProperties":false,"properties":{"encoding":{"enum":["utf-8","latin1"],"type":"string"},"format":{"const":"matrix-market","type":"string"}},"required":["format","encoding"],"type":"object"},{"additionalProperties":false,"properties":{"encoding":{"enum":["utf-8","latin1"],"type":"string"},"format":{"const":"gml","type":"string"}},"required":["format","encoding"],"type":"object"},{"additionalProperties":false,"properties":{"encoding":{"enum":["utf-8","latin1"],"type":"string"},"format":{"const":"pajek","type":"string"}},"required":["format","encoding"],"type":"object"}]},"source":{"maximum":9007199254740991,"minimum":0,"type":"integer"},"status":{"const":"fetchable","type":"string"}},"required":["status","source","archive","parser"],"type":"object"},{"additionalProperties":false,"properties":{"reason":{"minLength":1,"type":"string"},"status":{"const":"not-fetchable","type":"string"}},"required":["status","reason"],"type":"object"}]},"sources":{"items":{"additionalProperties":false,"properties":{"retrieved":{"format":"date","pattern":"^(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))$","type":"string"},"snapshot":{"additionalProperties":false,"properties":{"timestamp":{"pattern":"^\\d{8}(?:\\d{6})?$","type":"string"},"url":{"format":"uri","type":"string"}},"required":["url","timestamp"],"type":"object"},"status":{"enum":["live","dead"],"type":"string"},"url":{"format":"uri","type":"string"}},"required":["url","retrieved","status"],"type":"object"},"minItems":1,"type":"array"},"tags":{"items":{"minLength":1,"type":"string"},"type":"array"}},"required":["id","name","tags","category","sources","licence","citations","recipe","crosswalk","expectedCounts","properties"],"type":"object"}},"$id":"https://cdn.jsdelivr.net/npm/keepset@0.5.0/schemas/entry.schema.json","$ref":"#/$defs/Entry","$schema":"https://json-schema.org/draft/2020-12/schema"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"$defs":{"Manifest":{"additionalProperties":false,"properties":{"description":{"minLength":1,"type":"string"},"id":{"pattern":"^[A-Za-z0-9][A-Za-z0-9._-]*$","type":"string"},"lineage":{"additionalProperties":false,"properties":{"catalogue":{"pattern":"^[A-Za-z0-9][A-Za-z0-9._-]*$","type":"string"},"repository":{"format":"uri","type":"string"},"version":{"pattern":"^(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(?:-[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?(?:\\+[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?$","type":"string"}},"required":["catalogue","version","repository"],"type":"object"},"name":{"minLength":1,"type":"string"},"repository":{"format":"uri","type":"string"},"version":{"pattern":"^(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(?:-[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?(?:\\+[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?$","type":"string"}},"required":["id","name","description","version","repository"],"type":"object"}},"$id":"https://cdn.jsdelivr.net/npm/keepset@0.
|
|
1
|
+
{"$defs":{"Manifest":{"additionalProperties":false,"properties":{"description":{"minLength":1,"type":"string"},"id":{"pattern":"^[A-Za-z0-9][A-Za-z0-9._-]*$","type":"string"},"lineage":{"additionalProperties":false,"properties":{"catalogue":{"pattern":"^[A-Za-z0-9][A-Za-z0-9._-]*$","type":"string"},"repository":{"format":"uri","type":"string"},"version":{"pattern":"^(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(?:-[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?(?:\\+[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?$","type":"string"}},"required":["catalogue","version","repository"],"type":"object"},"name":{"minLength":1,"type":"string"},"repository":{"format":"uri","type":"string"},"version":{"pattern":"^(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)\\.(?:0|[1-9]\\d*)(?:-[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?(?:\\+[0-9A-Za-z-]+(?:\\.[0-9A-Za-z-]+)*)?$","type":"string"}},"required":["id","name","description","version","repository"],"type":"object"}},"$id":"https://cdn.jsdelivr.net/npm/keepset@0.5.0/schemas/manifest.schema.json","$ref":"#/$defs/Manifest","$schema":"https://json-schema.org/draft/2020-12/schema"}
|