@chartcoach/catalog 0.1.7 → 0.2.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/README.md +324 -38
- package/dist/duckdb-wasm.d.ts +8 -0
- package/dist/duckdb-wasm.js +22 -0
- package/dist/duckdb.d.ts +8 -0
- package/dist/duckdb.js +9 -0
- package/dist/index-cache-Cx1gIK6N.js +280 -0
- package/dist/index.d.ts +40 -8
- package/dist/index.js +22 -7
- package/dist/json-CBWjz9b4.js +29 -0
- package/dist/model-De0MF-zg.d.ts +255 -0
- package/dist/node.d.ts +15 -0
- package/dist/node.js +218 -0
- package/dist/open-Nnzkr_bE.d.ts +15 -0
- package/dist/open-Uu3-r8kp.js +1244 -0
- package/dist/registration-CgQGMUIH.d.ts +6 -0
- package/dist/registration-DXhS7vgr.js +41 -0
- package/dist/tables-DcgKnXwF.js +389 -0
- package/package.json +47 -18
- package/src/catalog/artifacts.ts +309 -100
- package/src/catalog/description.ts +198 -0
- package/src/catalog/errors.ts +26 -1
- package/src/catalog/identity.ts +69 -0
- package/src/catalog/json.ts +32 -0
- package/src/catalog/labels.ts +8 -6
- package/src/catalog/manifest.ts +81 -20
- package/src/catalog/markdown.ts +2 -2
- package/src/catalog/model.ts +222 -37
- package/src/catalog/open.ts +428 -0
- package/src/catalog/parquet.ts +164 -0
- package/src/catalog/profile-layout.ts +86 -0
- package/src/catalog/profile.ts +345 -0
- package/src/catalog/query.ts +125 -0
- package/src/catalog/read.ts +101 -0
- package/src/catalog/references.ts +336 -0
- package/src/catalog/registration.ts +74 -0
- package/src/catalog/tables.ts +250 -0
- package/src/catalog/wire.ts +38 -65
- package/src/duckdb-wasm.ts +33 -0
- package/src/duckdb.ts +18 -0
- package/src/index.ts +51 -20
- package/src/node/index-cache.ts +432 -0
- package/src/node.ts +347 -0
- package/dist/catalog/artifacts.d.ts +0 -28
- package/dist/catalog/artifacts.d.ts.map +0 -1
- package/dist/catalog/artifacts.js +0 -89
- package/dist/catalog/chartcoach-defaults.d.ts +0 -17
- package/dist/catalog/chartcoach-defaults.d.ts.map +0 -1
- package/dist/catalog/chartcoach-defaults.js +0 -8
- package/dist/catalog/errors.d.ts +0 -4
- package/dist/catalog/errors.d.ts.map +0 -1
- package/dist/catalog/errors.js +0 -6
- package/dist/catalog/labels.d.ts +0 -9
- package/dist/catalog/labels.d.ts.map +0 -1
- package/dist/catalog/labels.js +0 -23
- package/dist/catalog/load-parquet-core.d.ts +0 -15
- package/dist/catalog/load-parquet-core.d.ts.map +0 -1
- package/dist/catalog/load-parquet-core.js +0 -45
- package/dist/catalog/manifest.d.ts +0 -15
- package/dist/catalog/manifest.d.ts.map +0 -1
- package/dist/catalog/manifest.js +0 -143
- package/dist/catalog/markdown.d.ts +0 -3
- package/dist/catalog/markdown.d.ts.map +0 -1
- package/dist/catalog/markdown.js +0 -13
- package/dist/catalog/model.d.ts +0 -33
- package/dist/catalog/model.d.ts.map +0 -1
- package/dist/catalog/model.js +0 -67
- package/dist/catalog/wire.d.ts +0 -18
- package/dist/catalog/wire.d.ts.map +0 -1
- package/dist/catalog/wire.js +0 -78
- package/dist/index.d.ts.map +0 -1
- package/src/catalog/chartcoach-defaults.ts +0 -17
- package/src/catalog/load-parquet-core.ts +0 -78
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { a as CatalogError, r as isJsonString } from "./json-CBWjz9b4.js";
|
|
2
|
+
import { i as tableSchemas, r as tableNames } from "./tables-DcgKnXwF.js";
|
|
3
|
+
//#region src/catalog/registration.ts
|
|
4
|
+
function registrationPlan(catalog, options, source) {
|
|
5
|
+
if (Object.prototype.toString.call(options) !== "[object Object]") throw new CatalogError("Registration options must be an object.");
|
|
6
|
+
if (options.ids !== void 0 && (!Array.isArray(options.ids) || !options.ids.every(isJsonString))) throw new CatalogError("ids must be an array of strings.");
|
|
7
|
+
const ids = options.ids === void 0 ? void 0 : new Set(options.ids);
|
|
8
|
+
for (const id of ids ?? []) catalog.require(id);
|
|
9
|
+
const tables = selectedTables(catalog, ids);
|
|
10
|
+
const json = source === "file" ? "(SELECT content FROM read_text(?))" : "?";
|
|
11
|
+
return tableNames.map((name) => {
|
|
12
|
+
const columns = tableSchemas[name].map(({ name, type }) => `"${name}" ${sqlType(type)}`).join(", ");
|
|
13
|
+
return {
|
|
14
|
+
sql: `CREATE OR REPLACE TABLE "${name}" AS SELECT record.*
|
|
15
|
+
FROM UNNEST(CAST(CAST(${json} AS JSON) AS STRUCT(${columns})[])) AS records(record)`,
|
|
16
|
+
rows: JSON.stringify(tables[name])
|
|
17
|
+
};
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
function selectedTables(catalog, ids) {
|
|
21
|
+
const links = catalog.table("guideline_references");
|
|
22
|
+
const selectedLinks = ids ? links.filter(({ guideline_id }) => ids.has(guideline_id)) : links;
|
|
23
|
+
const references = new Set(selectedLinks.map(({ reference_id }) => reference_id));
|
|
24
|
+
return {
|
|
25
|
+
guidelines: ids ? catalog.table("guidelines").filter(({ id }) => ids.has(id)) : catalog.table("guidelines"),
|
|
26
|
+
sections: ids ? catalog.table("sections").filter(({ guideline_id }) => ids.has(guideline_id)) : catalog.table("sections"),
|
|
27
|
+
guideline_labels: ids ? catalog.table("guideline_labels").filter(({ guideline_id }) => ids.has(guideline_id)) : catalog.table("guideline_labels"),
|
|
28
|
+
references: ids ? catalog.table("references").filter(({ id }) => references.has(id)) : catalog.table("references"),
|
|
29
|
+
guideline_references: selectedLinks,
|
|
30
|
+
guideline_sources: ids ? catalog.table("guideline_sources").filter(({ guideline_id }) => ids.has(guideline_id)) : catalog.table("guideline_sources")
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function sqlType(type) {
|
|
34
|
+
switch (type) {
|
|
35
|
+
case "String": return "VARCHAR";
|
|
36
|
+
case "List(String)": return "VARCHAR[]";
|
|
37
|
+
case "List(Struct({'role': String, 'title': String, 'content': String}))": return "STRUCT(role VARCHAR, title VARCHAR, content VARCHAR)[]";
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
41
|
+
export { registrationPlan as t };
|
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
import { a as CatalogError, n as isJsonObject, r as isJsonString } from "./json-CBWjz9b4.js";
|
|
2
|
+
import { BibDocument, Document, Library, ParseError, Style, init } from "refkit-js";
|
|
3
|
+
//#region src/catalog/labels.ts
|
|
4
|
+
function parseLabel(value, context = "label") {
|
|
5
|
+
const parts = value.trim().split(":").map((part) => part.trim());
|
|
6
|
+
if (parts.length !== 2 && parts.length !== 3 || parts.some((part) => part.length === 0)) throw new CatalogError(`${context} must use <family>:<category> or <family>:<category>:<modifier>.`);
|
|
7
|
+
const family = parts[0];
|
|
8
|
+
const category = parts[1];
|
|
9
|
+
const modifier = parts[2];
|
|
10
|
+
return {
|
|
11
|
+
value: modifier === void 0 ? `${family}:${category}` : `${family}:${category}:${modifier}`,
|
|
12
|
+
family,
|
|
13
|
+
category,
|
|
14
|
+
modifier
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
function normalizeLabel(value, context = "label") {
|
|
18
|
+
return parseLabel(value, context).value;
|
|
19
|
+
}
|
|
20
|
+
//#endregion
|
|
21
|
+
//#region src/catalog/identity.ts
|
|
22
|
+
async function catalogEntriesDigest(guidelines) {
|
|
23
|
+
return sha256Text([...guidelines].sort((left, right) => compareUnicode(left.id, right.id)).map((guideline) => ({
|
|
24
|
+
id: guideline.id,
|
|
25
|
+
title: guideline.title,
|
|
26
|
+
description: guideline.description,
|
|
27
|
+
labels: guideline.labels,
|
|
28
|
+
sections: guideline.sections.map((section) => ({
|
|
29
|
+
role: section.role,
|
|
30
|
+
title: section.title,
|
|
31
|
+
content: section.content
|
|
32
|
+
})),
|
|
33
|
+
references: guideline.references
|
|
34
|
+
})).map(canonicalJson).join(""));
|
|
35
|
+
}
|
|
36
|
+
async function manifestDigest(markdown) {
|
|
37
|
+
return sha256Text(markdown);
|
|
38
|
+
}
|
|
39
|
+
function canonicalJson(value) {
|
|
40
|
+
if (Array.isArray(value)) return `[${value.map(canonicalJson).join(",")}]`;
|
|
41
|
+
if (!isJsonObject(value)) return JSON.stringify(value) ?? "null";
|
|
42
|
+
return `{${Object.keys(value).sort(compareUnicode).map((key) => `${JSON.stringify(key)}:${canonicalJson(value[key])}`).join(",")}}`;
|
|
43
|
+
}
|
|
44
|
+
async function sha256Bytes(value) {
|
|
45
|
+
const subtle = globalThis.crypto?.subtle;
|
|
46
|
+
if (!subtle) throw new CatalogError("SHA-256 digest support is unavailable in this runtime.", { code: "unavailable_capability" });
|
|
47
|
+
const digest = await subtle.digest("SHA-256", value.slice().buffer);
|
|
48
|
+
return [...new Uint8Array(digest)].map((byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
49
|
+
}
|
|
50
|
+
function compareUnicode(left, right) {
|
|
51
|
+
const leftPoints = Array.from(left, (character) => character.codePointAt(0));
|
|
52
|
+
const rightPoints = Array.from(right, (character) => character.codePointAt(0));
|
|
53
|
+
const length = Math.min(leftPoints.length, rightPoints.length);
|
|
54
|
+
for (let index = 0; index < length; index += 1) {
|
|
55
|
+
const difference = leftPoints[index] - rightPoints[index];
|
|
56
|
+
if (difference !== 0) return difference;
|
|
57
|
+
}
|
|
58
|
+
return leftPoints.length - rightPoints.length;
|
|
59
|
+
}
|
|
60
|
+
async function sha256Text(value) {
|
|
61
|
+
return sha256Bytes(new TextEncoder().encode(value));
|
|
62
|
+
}
|
|
63
|
+
//#endregion
|
|
64
|
+
//#region src/catalog/references.ts
|
|
65
|
+
await init();
|
|
66
|
+
const citationStyle = Style.load("apa");
|
|
67
|
+
const DEFAULT_GUIDELINE_URL_TEMPLATE = "https://chartcoach.dev/guidelines/{id}";
|
|
68
|
+
const indexes = /* @__PURE__ */ new WeakMap();
|
|
69
|
+
function sourceRecords(catalog, guidelineId, detail) {
|
|
70
|
+
const index = referenceIndex(catalog);
|
|
71
|
+
const ids = index.idsByGuideline.get(guidelineId) ?? [];
|
|
72
|
+
return Object.freeze(ids.map((id) => {
|
|
73
|
+
const reference = index.byId.get(id);
|
|
74
|
+
return detail === "minimal" ? minimalSource(reference) : fullSource(guidelineId, reference);
|
|
75
|
+
}));
|
|
76
|
+
}
|
|
77
|
+
function citationRecords(catalog, options) {
|
|
78
|
+
if (Object.prototype.toString.call(options) !== "[object Object]") throw new CatalogError("Citation options must be an object.");
|
|
79
|
+
if (!Array.isArray(options.ids) || !options.ids.every(isJsonString)) throw new CatalogError("ids must be an array of strings.");
|
|
80
|
+
const urlTemplate = options.urlTemplate ?? DEFAULT_GUIDELINE_URL_TEMPLATE;
|
|
81
|
+
if (!isJsonString(urlTemplate) || !urlTemplate.includes("{id}")) throw new CatalogError("Guideline URL template must include `{id}`.", { hints: [`Use a template such as \`${DEFAULT_GUIDELINE_URL_TEMPLATE}\`.`] });
|
|
82
|
+
if (options.ids.length === 0) return Object.freeze([]);
|
|
83
|
+
const index = referenceIndex(catalog);
|
|
84
|
+
return Object.freeze(options.ids.map((id) => {
|
|
85
|
+
const guideline = catalog.require(id);
|
|
86
|
+
const url = urlTemplate.replace("{id}", id);
|
|
87
|
+
const sources = Object.freeze((index.idsByGuideline.get(id) ?? []).map((referenceId) => citationSource(index.byId.get(referenceId))));
|
|
88
|
+
return Object.freeze({
|
|
89
|
+
id,
|
|
90
|
+
title: guideline.title,
|
|
91
|
+
url,
|
|
92
|
+
guideline_citation: `[${guideline.title}](${url}) (\`${id}\`)`,
|
|
93
|
+
sources
|
|
94
|
+
});
|
|
95
|
+
}));
|
|
96
|
+
}
|
|
97
|
+
function referenceIndex(catalog) {
|
|
98
|
+
const cached = indexes.get(catalog);
|
|
99
|
+
if (cached) return cached;
|
|
100
|
+
const byId = /* @__PURE__ */ new Map();
|
|
101
|
+
const parsed = /* @__PURE__ */ new Map();
|
|
102
|
+
const idsByGuideline = /* @__PURE__ */ new Map();
|
|
103
|
+
for (const guideline of catalog.guidelines) {
|
|
104
|
+
const ids = /* @__PURE__ */ new Set();
|
|
105
|
+
for (const bibtex of guideline.references) {
|
|
106
|
+
let reference = parsed.get(bibtex);
|
|
107
|
+
if (!reference) {
|
|
108
|
+
reference = parseReference(bibtex);
|
|
109
|
+
parsed.set(bibtex, reference);
|
|
110
|
+
}
|
|
111
|
+
const previous = byId.get(reference.id);
|
|
112
|
+
if (previous && previous.fingerprint !== reference.fingerprint) throw new CatalogError(`Conflicting BibTeX definitions for reference id: ${reference.id}.`, { details: { reference_id: reference.id } });
|
|
113
|
+
byId.set(reference.id, previous && compareUnicode(previous.bibtex, reference.bibtex) <= 0 ? previous : reference);
|
|
114
|
+
ids.add(reference.id);
|
|
115
|
+
}
|
|
116
|
+
idsByGuideline.set(guideline.id, Object.freeze([...ids].sort(compareUnicode)));
|
|
117
|
+
}
|
|
118
|
+
const created = Object.freeze({
|
|
119
|
+
byId,
|
|
120
|
+
idsByGuideline
|
|
121
|
+
});
|
|
122
|
+
indexes.set(catalog, created);
|
|
123
|
+
return created;
|
|
124
|
+
}
|
|
125
|
+
function parseReference(bibtex) {
|
|
126
|
+
try {
|
|
127
|
+
return parsedReference(bibtex);
|
|
128
|
+
} catch (error) {
|
|
129
|
+
if (error instanceof CatalogError) throw error;
|
|
130
|
+
const details = { exception_type: error instanceof Error ? error.name : "Error" };
|
|
131
|
+
if (error instanceof ParseError) details.diagnostics = error.diagnostics.map((diagnostic) => ({ ...diagnostic }));
|
|
132
|
+
throw new CatalogError("BibTeX reference could not be parsed.", { details });
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
function parsedReference(bibtex) {
|
|
136
|
+
const document = BibDocument.parse(bibtex);
|
|
137
|
+
const entries = document.resolve();
|
|
138
|
+
if (entries.length !== 1) throw new CatalogError(`Expected one BibTeX entry, found ${entries.length}.`);
|
|
139
|
+
const entry = entries[0];
|
|
140
|
+
const properties = entry.fields;
|
|
141
|
+
const authorsText = textOrNull(properties.author);
|
|
142
|
+
const authors = Object.freeze(authorsText === null ? [] : authorsText.split(" and ").map((author) => author.trim()).filter(Boolean));
|
|
143
|
+
return Object.freeze({
|
|
144
|
+
id: entry.key,
|
|
145
|
+
bibtex,
|
|
146
|
+
sourceType: entry.entryType,
|
|
147
|
+
authors,
|
|
148
|
+
authorsText,
|
|
149
|
+
year: textOrNull(properties.year),
|
|
150
|
+
title: textOrNull(properties.title),
|
|
151
|
+
journal: textOrNull(properties.journal),
|
|
152
|
+
booktitle: textOrNull(properties.booktitle),
|
|
153
|
+
publisher: textOrNull(properties.publisher),
|
|
154
|
+
url: referenceUrl(properties),
|
|
155
|
+
doi: textOrNull(properties.doi),
|
|
156
|
+
citation: new Document(Library.parseBibtex(document.tidy().bibtex, { recovery: "report" }), citationStyle, { locale: "en-US" }).fullBibliography().text,
|
|
157
|
+
fingerprint: canonicalJson({
|
|
158
|
+
type: entry.entryType,
|
|
159
|
+
label: entry.key,
|
|
160
|
+
properties: { ...properties }
|
|
161
|
+
})
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
function minimalSource(reference) {
|
|
165
|
+
return Object.freeze({
|
|
166
|
+
reference_id: reference.id,
|
|
167
|
+
authors_text: reference.authorsText,
|
|
168
|
+
year: reference.year,
|
|
169
|
+
source_title: reference.title,
|
|
170
|
+
doi: reference.doi,
|
|
171
|
+
url: reference.url
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
function fullSource(guidelineId, reference) {
|
|
175
|
+
return Object.freeze({
|
|
176
|
+
guideline_id: guidelineId,
|
|
177
|
+
reference_id: reference.id,
|
|
178
|
+
source_type: reference.sourceType,
|
|
179
|
+
authors: reference.authors,
|
|
180
|
+
authors_text: reference.authorsText,
|
|
181
|
+
year: reference.year,
|
|
182
|
+
source_title: reference.title,
|
|
183
|
+
journal: reference.journal,
|
|
184
|
+
booktitle: reference.booktitle,
|
|
185
|
+
publisher: reference.publisher,
|
|
186
|
+
url: reference.url,
|
|
187
|
+
doi: reference.doi
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
function citationSource(reference) {
|
|
191
|
+
const source = {
|
|
192
|
+
reference_id: reference.id,
|
|
193
|
+
source_type: reference.sourceType,
|
|
194
|
+
authors_text: reference.authorsText,
|
|
195
|
+
year: reference.year,
|
|
196
|
+
source_title: reference.title,
|
|
197
|
+
journal: reference.journal,
|
|
198
|
+
booktitle: reference.booktitle,
|
|
199
|
+
publisher: reference.publisher,
|
|
200
|
+
doi: reference.doi,
|
|
201
|
+
url: reference.url
|
|
202
|
+
};
|
|
203
|
+
const locators = [source.doi ? doiUrl(source.doi) : null, source.url].filter((value) => value !== null && !reference.citation.includes(value));
|
|
204
|
+
return Object.freeze({
|
|
205
|
+
...source,
|
|
206
|
+
citation: [reference.citation, ...new Set(locators)].join(" ")
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
function textOrNull(value) {
|
|
210
|
+
if (value === void 0) return null;
|
|
211
|
+
return value.trim() || null;
|
|
212
|
+
}
|
|
213
|
+
function referenceUrl(properties) {
|
|
214
|
+
const explicit = textOrNull(properties.url);
|
|
215
|
+
const value = explicit ?? textOrNull(properties.howpublished);
|
|
216
|
+
if (value === null) return null;
|
|
217
|
+
const candidate = /^\\url\{([^{}]*)\}$/.exec(value)?.[1] ?? value;
|
|
218
|
+
return /^https?:\/\/[^\s{}\\/?#]+[^\s{}\\]*$/i.test(candidate) ? candidate : explicit;
|
|
219
|
+
}
|
|
220
|
+
function doiUrl(value) {
|
|
221
|
+
return `https://doi.org/${value.replace(/^https?:\/\/doi\.org\//, "")}`;
|
|
222
|
+
}
|
|
223
|
+
//#endregion
|
|
224
|
+
//#region src/catalog/tables.ts
|
|
225
|
+
function columns(schema) {
|
|
226
|
+
return Object.freeze(Object.entries(schema).map(([name, type]) => Object.freeze({
|
|
227
|
+
name,
|
|
228
|
+
type
|
|
229
|
+
})));
|
|
230
|
+
}
|
|
231
|
+
const tableSchemas = Object.freeze({
|
|
232
|
+
guidelines: columns({
|
|
233
|
+
id: "String",
|
|
234
|
+
title: "String",
|
|
235
|
+
description: "String",
|
|
236
|
+
labels: "List(String)",
|
|
237
|
+
body: "String",
|
|
238
|
+
sections: "List(Struct({'role': String, 'title': String, 'content': String}))"
|
|
239
|
+
}),
|
|
240
|
+
sections: columns({
|
|
241
|
+
guideline_id: "String",
|
|
242
|
+
role: "String",
|
|
243
|
+
title: "String",
|
|
244
|
+
content: "String"
|
|
245
|
+
}),
|
|
246
|
+
guideline_labels: columns({
|
|
247
|
+
guideline_id: "String",
|
|
248
|
+
label: "String",
|
|
249
|
+
family: "String",
|
|
250
|
+
category: "String",
|
|
251
|
+
modifier: "String"
|
|
252
|
+
}),
|
|
253
|
+
references: columns({
|
|
254
|
+
id: "String",
|
|
255
|
+
source_type: "String",
|
|
256
|
+
authors: "List(String)",
|
|
257
|
+
authors_text: "String",
|
|
258
|
+
year: "String",
|
|
259
|
+
title: "String",
|
|
260
|
+
journal: "String",
|
|
261
|
+
booktitle: "String",
|
|
262
|
+
publisher: "String",
|
|
263
|
+
url: "String",
|
|
264
|
+
doi: "String",
|
|
265
|
+
bibtex: "String"
|
|
266
|
+
}),
|
|
267
|
+
guideline_references: columns({
|
|
268
|
+
guideline_id: "String",
|
|
269
|
+
reference_id: "String"
|
|
270
|
+
}),
|
|
271
|
+
guideline_sources: columns({
|
|
272
|
+
guideline_id: "String",
|
|
273
|
+
reference_id: "String",
|
|
274
|
+
source_type: "String",
|
|
275
|
+
authors: "List(String)",
|
|
276
|
+
authors_text: "String",
|
|
277
|
+
year: "String",
|
|
278
|
+
source_title: "String",
|
|
279
|
+
journal: "String",
|
|
280
|
+
booktitle: "String",
|
|
281
|
+
publisher: "String",
|
|
282
|
+
url: "String",
|
|
283
|
+
doi: "String",
|
|
284
|
+
bibtex: "String"
|
|
285
|
+
})
|
|
286
|
+
});
|
|
287
|
+
const tableNames = Object.freeze([
|
|
288
|
+
"guidelines",
|
|
289
|
+
"sections",
|
|
290
|
+
"guideline_labels",
|
|
291
|
+
"references",
|
|
292
|
+
"guideline_references",
|
|
293
|
+
"guideline_sources"
|
|
294
|
+
]);
|
|
295
|
+
const tablesByCatalog = /* @__PURE__ */ new WeakMap();
|
|
296
|
+
function catalogTable(catalog, name) {
|
|
297
|
+
if (!Object.hasOwn(tableSchemas, name)) throw new CatalogError(`Unknown table: ${name}`, {
|
|
298
|
+
code: "lookup",
|
|
299
|
+
details: {
|
|
300
|
+
table: name,
|
|
301
|
+
available: tableNames
|
|
302
|
+
},
|
|
303
|
+
hints: ["Call catalog.describe() to inspect catalog tables."]
|
|
304
|
+
});
|
|
305
|
+
let tables = tablesByCatalog.get(catalog);
|
|
306
|
+
if (!tables) {
|
|
307
|
+
tables = /* @__PURE__ */ new Map();
|
|
308
|
+
tablesByCatalog.set(catalog, tables);
|
|
309
|
+
}
|
|
310
|
+
let rows = tables.get(name);
|
|
311
|
+
if (!rows) {
|
|
312
|
+
rows = tableBuilders[name](catalog);
|
|
313
|
+
Object.freeze(rows);
|
|
314
|
+
tables.set(name, rows);
|
|
315
|
+
}
|
|
316
|
+
return rows;
|
|
317
|
+
}
|
|
318
|
+
function catalogTableInfo(catalog) {
|
|
319
|
+
return Object.freeze(tableNames.map((name) => Object.freeze({
|
|
320
|
+
name,
|
|
321
|
+
rows: catalog.table(name).length,
|
|
322
|
+
columns: tableSchemas[name]
|
|
323
|
+
})));
|
|
324
|
+
}
|
|
325
|
+
const tableBuilders = {
|
|
326
|
+
guidelines: (catalog) => catalog.guidelines.map(({ id, title, description, labels, body, sections }) => Object.freeze({
|
|
327
|
+
id,
|
|
328
|
+
title,
|
|
329
|
+
description,
|
|
330
|
+
labels,
|
|
331
|
+
body,
|
|
332
|
+
sections
|
|
333
|
+
})),
|
|
334
|
+
sections: (catalog) => catalog.guidelines.flatMap((guideline) => guideline.sections.map((section) => Object.freeze({
|
|
335
|
+
guideline_id: guideline.id,
|
|
336
|
+
...section
|
|
337
|
+
}))),
|
|
338
|
+
guideline_labels: (catalog) => catalog.guidelines.flatMap((guideline) => [...new Set(guideline.labels)].map((label) => {
|
|
339
|
+
const parsed = parseLabel(label);
|
|
340
|
+
return Object.freeze({
|
|
341
|
+
guideline_id: guideline.id,
|
|
342
|
+
label,
|
|
343
|
+
family: parsed.family,
|
|
344
|
+
category: parsed.category,
|
|
345
|
+
modifier: parsed.modifier ?? null
|
|
346
|
+
});
|
|
347
|
+
})).sort((left, right) => compareUnicode(left.guideline_id, right.guideline_id) || compareUnicode(left.label, right.label)),
|
|
348
|
+
references: (catalog) => [...referenceIndex(catalog).byId.values()].sort((left, right) => compareUnicode(left.id, right.id)).map((reference) => Object.freeze({
|
|
349
|
+
id: reference.id,
|
|
350
|
+
source_type: reference.sourceType,
|
|
351
|
+
authors: reference.authors,
|
|
352
|
+
authors_text: reference.authorsText,
|
|
353
|
+
year: reference.year,
|
|
354
|
+
title: reference.title,
|
|
355
|
+
journal: reference.journal,
|
|
356
|
+
booktitle: reference.booktitle,
|
|
357
|
+
publisher: reference.publisher,
|
|
358
|
+
url: reference.url,
|
|
359
|
+
doi: reference.doi,
|
|
360
|
+
bibtex: reference.bibtex
|
|
361
|
+
})),
|
|
362
|
+
guideline_references: (catalog) => [...referenceIndex(catalog).idsByGuideline].sort(([left], [right]) => compareUnicode(left, right)).flatMap(([guideline_id, ids]) => ids.map((reference_id) => Object.freeze({
|
|
363
|
+
guideline_id,
|
|
364
|
+
reference_id
|
|
365
|
+
}))),
|
|
366
|
+
guideline_sources: (catalog) => {
|
|
367
|
+
const references = new Map(catalog.table("references").map((reference) => [reference.id, reference]));
|
|
368
|
+
return catalog.table("guideline_references").map(({ guideline_id, reference_id }) => {
|
|
369
|
+
const reference = references.get(reference_id);
|
|
370
|
+
return Object.freeze({
|
|
371
|
+
guideline_id,
|
|
372
|
+
reference_id,
|
|
373
|
+
source_type: reference.source_type,
|
|
374
|
+
authors: reference.authors,
|
|
375
|
+
authors_text: reference.authors_text,
|
|
376
|
+
year: reference.year,
|
|
377
|
+
source_title: reference.title,
|
|
378
|
+
journal: reference.journal,
|
|
379
|
+
booktitle: reference.booktitle,
|
|
380
|
+
publisher: reference.publisher,
|
|
381
|
+
url: reference.url,
|
|
382
|
+
doi: reference.doi,
|
|
383
|
+
bibtex: reference.bibtex
|
|
384
|
+
});
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
};
|
|
388
|
+
//#endregion
|
|
389
|
+
export { citationRecords as a, catalogEntriesDigest as c, sha256Bytes as d, normalizeLabel as f, tableSchemas as i, compareUnicode as l, catalogTableInfo as n, sourceRecords as o, parseLabel as p, tableNames as r, canonicalJson as s, catalogTable as t, manifestDigest as u };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@chartcoach/catalog",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "JavaScript models and artifact parsers for the chartcoach visualization guideline catalog.",
|
|
5
5
|
"bugs": {
|
|
6
6
|
"url": "https://github.com/chartcoach/chartcoach/issues"
|
|
@@ -23,30 +23,59 @@
|
|
|
23
23
|
"types": "./dist/index.d.ts",
|
|
24
24
|
"source": "./src/index.ts",
|
|
25
25
|
"default": "./dist/index.js"
|
|
26
|
+
},
|
|
27
|
+
"./duckdb": {
|
|
28
|
+
"types": "./dist/duckdb.d.ts",
|
|
29
|
+
"source": "./src/duckdb.ts",
|
|
30
|
+
"default": "./dist/duckdb.js"
|
|
31
|
+
},
|
|
32
|
+
"./duckdb-wasm": {
|
|
33
|
+
"types": "./dist/duckdb-wasm.d.ts",
|
|
34
|
+
"source": "./src/duckdb-wasm.ts",
|
|
35
|
+
"default": "./dist/duckdb-wasm.js"
|
|
36
|
+
},
|
|
37
|
+
"./node": {
|
|
38
|
+
"types": "./dist/node.d.ts",
|
|
39
|
+
"source": "./src/node.ts",
|
|
40
|
+
"default": "./dist/node.js"
|
|
26
41
|
}
|
|
27
42
|
},
|
|
28
43
|
"publishConfig": {
|
|
29
44
|
"access": "public"
|
|
30
45
|
},
|
|
46
|
+
"scripts": {
|
|
47
|
+
"build": "vp pack",
|
|
48
|
+
"check": "vp check",
|
|
49
|
+
"prepack": "vp run build",
|
|
50
|
+
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
51
|
+
},
|
|
31
52
|
"dependencies": {
|
|
32
|
-
"hyparquet": "
|
|
33
|
-
"hyparquet-compressors": "
|
|
34
|
-
"
|
|
53
|
+
"hyparquet": ">=1.29.2",
|
|
54
|
+
"hyparquet-compressors": ">=1.1.1",
|
|
55
|
+
"refkit-js": ">=0.3.0",
|
|
56
|
+
"tar": ">=7.5.22",
|
|
57
|
+
"yaml": ">=2.9.0"
|
|
35
58
|
},
|
|
36
59
|
"devDependencies": {
|
|
37
|
-
"@
|
|
38
|
-
"
|
|
39
|
-
"
|
|
40
|
-
"
|
|
60
|
+
"@duckdb/duckdb-wasm": "catalog:",
|
|
61
|
+
"@duckdb/node-api": "catalog:",
|
|
62
|
+
"@types/node": "catalog:",
|
|
63
|
+
"typescript": "catalog:",
|
|
64
|
+
"vite-plus": "catalog:"
|
|
41
65
|
},
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
"
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
"
|
|
66
|
+
"peerDependencies": {
|
|
67
|
+
"@duckdb/duckdb-wasm": ">=1.33.1-dev57.0",
|
|
68
|
+
"@duckdb/node-api": ">=1.5.5-r.4"
|
|
69
|
+
},
|
|
70
|
+
"peerDependenciesMeta": {
|
|
71
|
+
"@duckdb/duckdb-wasm": {
|
|
72
|
+
"optional": true
|
|
73
|
+
},
|
|
74
|
+
"@duckdb/node-api": {
|
|
75
|
+
"optional": true
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"engines": {
|
|
79
|
+
"node": ">=22.19.0"
|
|
51
80
|
}
|
|
52
|
-
}
|
|
81
|
+
}
|