@finbheara/archive-client 0.3.1 → 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/README.md +95 -6
- package/dist/chunks/{index-3va2jzse.js → index-8gna56w2.js} +609 -8
- package/dist/cli.js +200 -3
- package/dist/index.js +9 -1
- package/dist/types/cli.d.ts +3 -1
- package/dist/types/dancers.d.ts +33 -0
- package/dist/types/feises.d.ts +8 -0
- package/dist/types/index.d.ts +4 -2
- package/dist/types/indexes.d.ts +7 -1
- package/dist/types/parquet.d.ts +4 -0
- package/dist/types/release.d.ts +3 -0
- package/dist/types/results.d.ts +11 -0
- package/dist/types/schema.d.ts +1 -0
- package/dist/types/stream.d.ts +71 -0
- package/dist/types/teams.d.ts +105 -0
- package/package.json +3 -2
|
@@ -106,8 +106,149 @@ function nameLevel2(q, c) {
|
|
|
106
106
|
return null;
|
|
107
107
|
}
|
|
108
108
|
|
|
109
|
+
var ENTRY_RANK = new Map([
|
|
110
|
+
["final", 0],
|
|
111
|
+
["", 1],
|
|
112
|
+
["recall", 2],
|
|
113
|
+
["standings", 3],
|
|
114
|
+
["unplaced", 4],
|
|
115
|
+
["qual", 5],
|
|
116
|
+
["qual-a", 5],
|
|
117
|
+
["qual-b", 5]
|
|
118
|
+
]);
|
|
119
|
+
function entryRank2(section) {
|
|
120
|
+
const known = ENTRY_RANK.get(section);
|
|
121
|
+
if (known !== undefined)
|
|
122
|
+
return known;
|
|
123
|
+
if (/^solo(?:-r\d+)?$/.test(section))
|
|
124
|
+
return 6;
|
|
125
|
+
return 9;
|
|
126
|
+
}
|
|
127
|
+
var COLUMNS = `r.address AS address, r.competition AS competition, c.event AS event,
|
|
128
|
+
c.year AS year, c.tier AS tier, c.comp_no AS comp_no, c.title AS title, c.category AS category,
|
|
129
|
+
c.age AS age, c.age_printed AS age_printed, c.gender AS gender, c.competitors AS competitors,
|
|
130
|
+
c.feis_level AS feis_level, c.level_printed AS level_printed, c.date_printed AS date_printed,
|
|
131
|
+
c.source AS source, c.round AS round, r.section AS section, r.card AS card, r.place AS place,
|
|
132
|
+
r.place_printed AS place_printed, r.tie AS tie, r.relative_place AS relative_place,
|
|
133
|
+
r.atts AS atts, r.withdrawn AS withdrawn, r.qualifier AS qualifier,
|
|
134
|
+
r.name_printed AS name_printed, r.name AS name, r.school_printed AS school_printed,
|
|
135
|
+
r.school_loc AS school_loc, r.school_id AS school_id, r.dancer_id AS dancer_id, r.yob AS yob,
|
|
136
|
+
r.yob_printed AS yob_printed, r.points_printed AS points_printed,
|
|
137
|
+
r.platform_dancer_id AS platform_dancer_id, r.primary_source AS primary_source,
|
|
138
|
+
r.file AS file`;
|
|
139
|
+
var TRANSCRIBED = "('transcript', 'manifested')";
|
|
140
|
+
var scopeDb = (s) => s === "majors" ? "majors" : "results";
|
|
141
|
+
function streamSql(q) {
|
|
142
|
+
const where = [];
|
|
143
|
+
const args = [];
|
|
144
|
+
const list = (col, v, nocase = false) => {
|
|
145
|
+
if (v.length === 0) {
|
|
146
|
+
where.push("0");
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
where.push(`${col}${nocase ? " COLLATE NOCASE" : ""} IN (${v.map(() => "?").join(", ")})`);
|
|
150
|
+
args.push(...v);
|
|
151
|
+
};
|
|
152
|
+
if (q.scope === "transcribed")
|
|
153
|
+
where.push(`r.source IN ${TRANSCRIBED}`);
|
|
154
|
+
else if (q.scope === "platform")
|
|
155
|
+
where.push(`r.source NOT IN ${TRANSCRIBED}`);
|
|
156
|
+
else if (q.scope !== "majors" && q.scope !== "all")
|
|
157
|
+
throw new Error(`archive-client: no stream scope "${String(q.scope)}"`);
|
|
158
|
+
if (q.event !== undefined)
|
|
159
|
+
list("c.event", typeof q.event === "string" ? [q.event] : q.event, true);
|
|
160
|
+
if (typeof q.year === "number") {
|
|
161
|
+
where.push("c.year = ?");
|
|
162
|
+
args.push(q.year);
|
|
163
|
+
} else if (Array.isArray(q.year)) {
|
|
164
|
+
where.push("c.year BETWEEN ? AND ?");
|
|
165
|
+
args.push(q.year[0], q.year[1]);
|
|
166
|
+
}
|
|
167
|
+
if (q.tier !== undefined)
|
|
168
|
+
list("c.tier", q.tier);
|
|
169
|
+
if (q.category !== undefined)
|
|
170
|
+
list("c.category", q.category);
|
|
171
|
+
if (q.feis_level !== undefined)
|
|
172
|
+
list("c.feis_level", q.feis_level);
|
|
173
|
+
if (q.dancer_id !== undefined)
|
|
174
|
+
list("r.dancer_id", q.dancer_id);
|
|
175
|
+
if (q.school_id !== undefined) {
|
|
176
|
+
where.push("r.school_id = ?");
|
|
177
|
+
args.push(q.school_id);
|
|
178
|
+
}
|
|
179
|
+
if (q.primary === true)
|
|
180
|
+
where.push("(r.primary_source IS NULL OR r.primary_source = '')");
|
|
181
|
+
return {
|
|
182
|
+
sql: `SELECT ${COLUMNS} FROM results r JOIN competitions c ON c.file = r.file AND c.line = r.competition_line${where.length === 0 ? "" : ` WHERE ${where.join(" AND ")}`} ORDER BY r.file, r.line`,
|
|
183
|
+
args
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
function feisDates(db) {
|
|
187
|
+
const out = new Map;
|
|
188
|
+
for (const f of db.query("SELECT feis_id, min(date_lo) AS lo, max(date_hi) AS hi FROM feises GROUP BY feis_id").all())
|
|
189
|
+
out.set(f.feis_id, { lo: f.lo, hi: f.hi });
|
|
190
|
+
return out;
|
|
191
|
+
}
|
|
192
|
+
var text = (v) => v === null || v === "" ? null : v;
|
|
193
|
+
function rowOf(r, dates) {
|
|
194
|
+
const { file: _file, atts, withdrawn, ...rest } = r;
|
|
195
|
+
const d = dates.get(r.event);
|
|
196
|
+
return {
|
|
197
|
+
...rest,
|
|
198
|
+
feis_id: d === undefined ? null : r.event,
|
|
199
|
+
feis_date_lo: d?.lo ?? null,
|
|
200
|
+
feis_date_hi: d?.hi ?? null,
|
|
201
|
+
atts: atts === "" ? [] : atts.split(","),
|
|
202
|
+
withdrawn: text(withdrawn),
|
|
203
|
+
qualifier: text(rest.qualifier),
|
|
204
|
+
primary_source: text(rest.primary_source),
|
|
205
|
+
dancer_scope: r.dancer_id === null ? null : r.dancer_id >= FEIS_LOCAL_ID_FLOOR2 ? "per-release" : "stable"
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
async function* streamRows(db, q) {
|
|
209
|
+
const dates = feisDates(db);
|
|
210
|
+
const { sql, args } = streamSql(q);
|
|
211
|
+
const stmt = db.prepare(sql);
|
|
212
|
+
try {
|
|
213
|
+
for (const r of stmt.iterate(...args))
|
|
214
|
+
yield rowOf(r, dates);
|
|
215
|
+
} finally {
|
|
216
|
+
stmt.finalize();
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
async function* entryRows(db, q) {
|
|
220
|
+
const dates = feisDates(db);
|
|
221
|
+
const { sql, args } = streamSql(q);
|
|
222
|
+
const stmt = db.prepare(sql);
|
|
223
|
+
let file = null;
|
|
224
|
+
let held = new Map;
|
|
225
|
+
const flush = function* () {
|
|
226
|
+
for (const h of held.values())
|
|
227
|
+
yield { ...rowOf(h.raw, dates), recall_place: h.recall };
|
|
228
|
+
held = new Map;
|
|
229
|
+
};
|
|
230
|
+
try {
|
|
231
|
+
for (const r of stmt.iterate(...args)) {
|
|
232
|
+
if (r.file !== file) {
|
|
233
|
+
yield* flush();
|
|
234
|
+
file = r.file;
|
|
235
|
+
}
|
|
236
|
+
const rank = entryRank2(r.section);
|
|
237
|
+
const h = held.get(r.address);
|
|
238
|
+
const recall = r.section === "recall" ? r.place : h?.recall ?? null;
|
|
239
|
+
if (h === undefined || rank <= h.rank)
|
|
240
|
+
held.set(r.address, { raw: r, rank, recall });
|
|
241
|
+
else
|
|
242
|
+
h.recall = recall;
|
|
243
|
+
}
|
|
244
|
+
yield* flush();
|
|
245
|
+
} finally {
|
|
246
|
+
stmt.finalize();
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
|
|
109
250
|
var FEIS_LOCAL_ID_FLOOR2 = 17179869184;
|
|
110
|
-
var
|
|
251
|
+
var COLUMNS2 = `r.address AS address, r.competition AS competition, c.event AS event, c.year AS year,
|
|
111
252
|
c.tier AS tier, c.title AS title, c.age AS age, c.category AS category, c.gender AS gender,
|
|
112
253
|
c.feis_level AS feis_level, c.comp_no AS comp_no, r.place AS place,
|
|
113
254
|
r.place_printed AS place_printed, c.competitors AS competitors, r.name_printed AS name_printed,
|
|
@@ -139,7 +280,7 @@ function queryResults(rel, db, q) {
|
|
|
139
280
|
args.push(q.year);
|
|
140
281
|
}
|
|
141
282
|
const limit = q.limit ?? 500;
|
|
142
|
-
const all = rel.db(db).query(`SELECT ${
|
|
283
|
+
const all = rel.db(db).query(`SELECT ${COLUMNS2} FROM results r JOIN competitions c ON c.file = r.file AND c.line = r.competition_line
|
|
143
284
|
WHERE ${where.join(" AND ")}
|
|
144
285
|
ORDER BY c.year, c.event, r.competition, r.place IS NULL, r.place, r.address`).all(...args);
|
|
145
286
|
return {
|
|
@@ -164,6 +305,18 @@ class ResultFinder2 {
|
|
|
164
305
|
await this.rel.require("results.level");
|
|
165
306
|
return queryResults(this.rel, "results", q);
|
|
166
307
|
}
|
|
308
|
+
async streamDb(q) {
|
|
309
|
+
const db = scopeDb(q.scope);
|
|
310
|
+
await this.rel.fetch(db);
|
|
311
|
+
await this.rel.require(db === "majors" ? "majors.stream" : "results.stream");
|
|
312
|
+
return this.rel.db(db);
|
|
313
|
+
}
|
|
314
|
+
async* stream(q) {
|
|
315
|
+
yield* streamRows(await this.streamDb(q), q);
|
|
316
|
+
}
|
|
317
|
+
async* entries(q) {
|
|
318
|
+
yield* entryRows(await this.streamDb(q), q);
|
|
319
|
+
}
|
|
167
320
|
}
|
|
168
321
|
|
|
169
322
|
class MajorsFinder2 {
|
|
@@ -208,6 +361,13 @@ class MajorsFinder2 {
|
|
|
208
361
|
ORDER BY c.year, c.seq, c.competition`).all(...args).map((c) => ({ ...c, rows: rows.get(c.competition) ?? 0 }));
|
|
209
362
|
return { tag: this.rel.tag, competitions };
|
|
210
363
|
}
|
|
364
|
+
async tabulated(q = {}) {
|
|
365
|
+
const db = await this.db();
|
|
366
|
+
await this.rel.require("majors.tabs");
|
|
367
|
+
const min = q.min_true_round ?? 3;
|
|
368
|
+
const addresses = db.query("SELECT DISTINCT address FROM tabs WHERE true_round >= ? ORDER BY address").all(min).map((r) => r.address);
|
|
369
|
+
return { tag: this.rel.tag, min_true_round: min, addresses };
|
|
370
|
+
}
|
|
211
371
|
async results(q) {
|
|
212
372
|
await this.db();
|
|
213
373
|
await this.rel.require("results.level");
|
|
@@ -365,6 +525,12 @@ var SCHOOL_WEIGHT = {
|
|
|
365
525
|
unresolved: 0,
|
|
366
526
|
unasked: 0
|
|
367
527
|
};
|
|
528
|
+
function idChunks(ids) {
|
|
529
|
+
const out = [];
|
|
530
|
+
for (let i = 0;i < ids.length; i += 500)
|
|
531
|
+
out.push(ids.slice(i, i + 500));
|
|
532
|
+
return out;
|
|
533
|
+
}
|
|
368
534
|
|
|
369
535
|
class DancerResolver2 {
|
|
370
536
|
rel;
|
|
@@ -372,6 +538,34 @@ class DancerResolver2 {
|
|
|
372
538
|
constructor(rel) {
|
|
373
539
|
this.rel = rel;
|
|
374
540
|
}
|
|
541
|
+
async records(q = {}) {
|
|
542
|
+
await this.rel.fetch("results");
|
|
543
|
+
await this.rel.require("dancers.records");
|
|
544
|
+
const db = this.rel.db("results");
|
|
545
|
+
const sql = "SELECT dancer_id, display, appearances, birth_lo, birth_hi, birth_source, birth_conflict, genders FROM dancers";
|
|
546
|
+
const rows = q.ids === undefined ? db.query(`${sql} ORDER BY dancer_id`).all() : idChunks(q.ids).flatMap((c) => db.query(`${sql} WHERE dancer_id IN (${c.map(() => "?").join(",")})`).all(...c));
|
|
547
|
+
rows.sort((a, b) => a.dancer_id - b.dancer_id);
|
|
548
|
+
return {
|
|
549
|
+
tag: this.rel.tag,
|
|
550
|
+
records: rows.map((r) => ({
|
|
551
|
+
...r,
|
|
552
|
+
scope: r.dancer_id >= FEIS_LOCAL_ID_FLOOR2 ? "per-release" : "stable",
|
|
553
|
+
birth_conflict: r.birth_conflict === 1,
|
|
554
|
+
genders: r.genders === "" ? [] : r.genders.split(",")
|
|
555
|
+
}))
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
async years(q = {}) {
|
|
559
|
+
await this.rel.fetch("results");
|
|
560
|
+
await this.rel.require("dancers.years");
|
|
561
|
+
const db = this.rel.db("results");
|
|
562
|
+
const sql = "SELECT dancer_id, year, region, region_source, nationals, nationals_source, geohash FROM dancer_years";
|
|
563
|
+
const yearSql = q.year === undefined ? "" : " AND year = ?";
|
|
564
|
+
const yearArgs = q.year === undefined ? [] : [q.year];
|
|
565
|
+
const rows = q.ids === undefined ? db.query(`${sql} WHERE 1${yearSql} ORDER BY dancer_id, year`).all(...yearArgs) : idChunks(q.ids).flatMap((c) => db.query(`${sql} WHERE dancer_id IN (${c.map(() => "?").join(",")})${yearSql}`).all(...c, ...yearArgs));
|
|
566
|
+
rows.sort((a, b) => a.dancer_id - b.dancer_id || a.year - b.year);
|
|
567
|
+
return { tag: this.rel.tag, years: rows };
|
|
568
|
+
}
|
|
375
569
|
async resolve(q) {
|
|
376
570
|
const db = await this.rel.indexDb("dancers");
|
|
377
571
|
const asked = dancerName(q.name, q.order === "unknown" ? undefined : q.order);
|
|
@@ -1067,6 +1261,12 @@ class FeisFinder2 {
|
|
|
1067
1261
|
constructor(rel) {
|
|
1068
1262
|
this.rel = rel;
|
|
1069
1263
|
}
|
|
1264
|
+
async dates() {
|
|
1265
|
+
await this.rel.fetch("results");
|
|
1266
|
+
await this.rel.require("feises.dates");
|
|
1267
|
+
const dates = this.rel.db("results").query("SELECT feis_id, min(date_lo) AS date_lo, max(date_hi) AS date_hi FROM feises GROUP BY feis_id ORDER BY feis_id").all();
|
|
1268
|
+
return { tag: this.rel.tag, dates };
|
|
1269
|
+
}
|
|
1070
1270
|
async find(q) {
|
|
1071
1271
|
const db = await this.rel.indexDb("feises");
|
|
1072
1272
|
const where = [];
|
|
@@ -1586,8 +1786,240 @@ class SchoolResolver2 {
|
|
|
1586
1786
|
}
|
|
1587
1787
|
}
|
|
1588
1788
|
|
|
1789
|
+
import { parquetMetadata, parquetReadObjects, parquetSchema } from "hyparquet";
|
|
1790
|
+
var COMPRESSORS = {
|
|
1791
|
+
ZSTD: (input) => new Uint8Array(Bun.zstdDecompressSync(input))
|
|
1792
|
+
};
|
|
1793
|
+
var tableAsset = (table) => `${table}.parquet`;
|
|
1794
|
+
function plain(v) {
|
|
1795
|
+
if (typeof v === "bigint")
|
|
1796
|
+
return v >= BigInt(Number.MIN_SAFE_INTEGER) && v <= BigInt(Number.MAX_SAFE_INTEGER) ? Number(v) : v;
|
|
1797
|
+
if (Array.isArray(v))
|
|
1798
|
+
return v.map(plain);
|
|
1799
|
+
if (v !== null && typeof v === "object" && !(v instanceof Date)) {
|
|
1800
|
+
const o = {};
|
|
1801
|
+
for (const [k, x] of Object.entries(v))
|
|
1802
|
+
o[k] = plain(x);
|
|
1803
|
+
return o;
|
|
1804
|
+
}
|
|
1805
|
+
return v;
|
|
1806
|
+
}
|
|
1807
|
+
async function readParquet(path, columns) {
|
|
1808
|
+
const file = await Bun.file(path).arrayBuffer();
|
|
1809
|
+
const rows = await parquetReadObjects({
|
|
1810
|
+
file,
|
|
1811
|
+
compressors: COMPRESSORS,
|
|
1812
|
+
...columns !== undefined ? { columns: [...columns] } : {}
|
|
1813
|
+
});
|
|
1814
|
+
return rows.map((r) => plain(r));
|
|
1815
|
+
}
|
|
1816
|
+
async function parquetColumns(path) {
|
|
1817
|
+
const meta = parquetMetadata(await Bun.file(path).arrayBuffer());
|
|
1818
|
+
return new Set(parquetSchema(meta).children.map((c) => c.element.name));
|
|
1819
|
+
}
|
|
1820
|
+
|
|
1821
|
+
var str = (v) => typeof v === "string" && v !== "" ? v : null;
|
|
1822
|
+
var num = (v) => typeof v === "number" ? v : null;
|
|
1823
|
+
var strs = (v) => Array.isArray(v) ? v.filter((x) => typeof x === "string") : [];
|
|
1824
|
+
var scope = (id) => id === null ? null : id >= FEIS_LOCAL_ID_FLOOR2 ? "per-release" : "stable";
|
|
1825
|
+
var TEAM_TABLES = [
|
|
1826
|
+
"team_results",
|
|
1827
|
+
"roster_teams",
|
|
1828
|
+
"roster_members",
|
|
1829
|
+
"team_result_rosters",
|
|
1830
|
+
"event_years"
|
|
1831
|
+
];
|
|
1832
|
+
var TEAMS_SCHEMA = `
|
|
1833
|
+
CREATE TABLE event_year(event_year TEXT PRIMARY KEY, event TEXT NOT NULL, year INTEGER NOT NULL);
|
|
1834
|
+
CREATE TABLE result(address TEXT PRIMARY KEY, competition TEXT, event TEXT, year INTEGER,
|
|
1835
|
+
card TEXT, comp_no TEXT, title TEXT, category TEXT, hands INTEGER, letter TEXT, label TEXT,
|
|
1836
|
+
name_printed TEXT, school_printed TEXT, school_loc TEXT, school_id TEXT, place INTEGER,
|
|
1837
|
+
place_printed TEXT, tie INTEGER, competitors INTEGER, atts TEXT, ord INTEGER);
|
|
1838
|
+
CREATE TABLE roster_team(team TEXT PRIMARY KEY, kind TEXT, event TEXT, year INTEGER,
|
|
1839
|
+
comp_no TEXT, title TEXT, team_index TEXT, seq INTEGER, school_id TEXT, school_printed TEXT,
|
|
1840
|
+
ord INTEGER);
|
|
1841
|
+
CREATE TABLE roster_member(team TEXT, seq INTEGER, name_printed TEXT, name TEXT, yob INTEGER,
|
|
1842
|
+
dancer_id INTEGER, ord INTEGER);
|
|
1843
|
+
CREATE TABLE result_roster(team TEXT, event TEXT, year INTEGER, comp_no TEXT, school_id TEXT,
|
|
1844
|
+
result_address TEXT, join_kind TEXT, via_split INTEGER, roster_teams INTEGER,
|
|
1845
|
+
result_teams INTEGER, roster_index TEXT, result_letter TEXT, ord INTEGER);
|
|
1846
|
+
`;
|
|
1847
|
+
var TEAMS_INDEXES = [
|
|
1848
|
+
"CREATE INDEX result_ey ON result(event COLLATE NOCASE, year)",
|
|
1849
|
+
"CREATE INDEX result_year ON result(year)",
|
|
1850
|
+
"CREATE INDEX roster_team_ey ON roster_team(event COLLATE NOCASE, year)",
|
|
1851
|
+
"CREATE INDEX roster_team_year ON roster_team(year)",
|
|
1852
|
+
"CREATE INDEX roster_member_team ON roster_member(team)",
|
|
1853
|
+
"CREATE INDEX result_roster_ey ON result_roster(event COLLATE NOCASE, year)",
|
|
1854
|
+
"CREATE INDEX result_roster_year ON result_roster(year)"
|
|
1855
|
+
];
|
|
1856
|
+
async function readTables(rel, tables) {
|
|
1857
|
+
const out = {};
|
|
1858
|
+
for (const t of tables) {
|
|
1859
|
+
await rel.fetch(tableAsset(t));
|
|
1860
|
+
out[t] = await readParquet(rel.path(tableAsset(t)));
|
|
1861
|
+
}
|
|
1862
|
+
return out;
|
|
1863
|
+
}
|
|
1864
|
+
var teamsIndex = {
|
|
1865
|
+
name: "teams",
|
|
1866
|
+
version: "1",
|
|
1867
|
+
inputs: TEAM_TABLES.map(tableAsset),
|
|
1868
|
+
says: "the team results, the roster teams with their members, and how they join, by event-year",
|
|
1869
|
+
load: (rel) => readTables(rel, TEAM_TABLES),
|
|
1870
|
+
build(_rel, out, loaded) {
|
|
1871
|
+
const t = loaded;
|
|
1872
|
+
out.run(TEAMS_SCHEMA);
|
|
1873
|
+
const ey = new Map;
|
|
1874
|
+
const putEy = out.prepare("INSERT OR IGNORE INTO event_year VALUES (?, ?, ?)");
|
|
1875
|
+
for (const r of t.event_years) {
|
|
1876
|
+
const k = str(r.event_year);
|
|
1877
|
+
const event = str(r.event);
|
|
1878
|
+
const year = num(r.year);
|
|
1879
|
+
if (k === null || event === null || year === null)
|
|
1880
|
+
continue;
|
|
1881
|
+
ey.set(k, { event, year });
|
|
1882
|
+
putEy.run(k, event, year);
|
|
1883
|
+
}
|
|
1884
|
+
const putR = out.prepare("INSERT OR IGNORE INTO result VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
1885
|
+
let ord = 0;
|
|
1886
|
+
for (const r of t.team_results)
|
|
1887
|
+
putR.run(str(r.address), str(r.slug), str(r.event), num(r.year), str(r.card), str(r.comp_no), str(r.title), str(r.category), num(r.hands), str(r.letter), str(r.label), str(r.name_printed), str(r.school_printed), str(r.school_loc), str(r.school_id), num(r.place), str(r.place_printed), num(r.tie), num(r.competitors), JSON.stringify(strs(r.atts)), ord++);
|
|
1888
|
+
const putT = out.prepare("INSERT OR IGNORE INTO roster_team VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
1889
|
+
for (const r of t.roster_teams) {
|
|
1890
|
+
const e = ey.get(str(r.event_year) ?? "");
|
|
1891
|
+
putT.run(str(r.team), str(r.kind), e?.event ?? null, num(r.year) ?? e?.year ?? null, str(r.comp_no), str(r.title), str(r.team_index), num(r.seq), str(r.school_id), str(r.school_print_materialized), ord++);
|
|
1892
|
+
}
|
|
1893
|
+
const putM = out.prepare("INSERT INTO roster_member VALUES (?, ?, ?, ?, ?, ?, ?)");
|
|
1894
|
+
for (const r of t.roster_members)
|
|
1895
|
+
putM.run(str(r.team), num(r.seq), typeof r.name_printed === "string" ? r.name_printed : "", str(r.name), num(r.yob), num(r.dancer_id), ord++);
|
|
1896
|
+
const putJ = out.prepare("INSERT INTO result_roster VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
1897
|
+
for (const r of t.team_result_rosters) {
|
|
1898
|
+
const e = ey.get(str(r.event_year) ?? "");
|
|
1899
|
+
putJ.run(str(r.team), e?.event ?? null, e?.year ?? null, str(r.comp_no), str(r.school_id), str(r.result_address), str(r.join_kind), num(r.via_split) === 1 ? 1 : 0, num(r.roster_teams), num(r.result_teams), str(r.roster_index), str(r.result_letter), ord++);
|
|
1900
|
+
}
|
|
1901
|
+
for (const s of TEAMS_INDEXES)
|
|
1902
|
+
out.run(s);
|
|
1903
|
+
}
|
|
1904
|
+
};
|
|
1905
|
+
var EVENTS_SCHEMA = `CREATE TABLE event_year(event TEXT NOT NULL, year INTEGER NOT NULL,
|
|
1906
|
+
date_lo TEXT, date_hi TEXT, resolution TEXT, source TEXT, date_printed TEXT, place TEXT,
|
|
1907
|
+
place_printed TEXT, PRIMARY KEY(event, year))`;
|
|
1908
|
+
var eventsIndex = {
|
|
1909
|
+
name: "events",
|
|
1910
|
+
version: "1",
|
|
1911
|
+
inputs: [tableAsset("event_years")],
|
|
1912
|
+
says: "every event-year: its dates (and how fine they are) and its place",
|
|
1913
|
+
load: (rel) => readTables(rel, ["event_years"]),
|
|
1914
|
+
build(_rel, out, loaded) {
|
|
1915
|
+
const rows = loaded.event_years ?? [];
|
|
1916
|
+
out.run(EVENTS_SCHEMA);
|
|
1917
|
+
const put = out.prepare("INSERT OR IGNORE INTO event_year VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)");
|
|
1918
|
+
for (const r of rows) {
|
|
1919
|
+
const event = str(r.event);
|
|
1920
|
+
const year = num(r.year);
|
|
1921
|
+
if (event === null || year === null)
|
|
1922
|
+
continue;
|
|
1923
|
+
put.run(event, year, str(r.date_lo), str(r.date_hi), str(r.resolution), str(r.source), JSON.stringify(strs(r.date_printed)), str(r.place), JSON.stringify(strs(r.place_printed)));
|
|
1924
|
+
}
|
|
1925
|
+
out.run("CREATE INDEX event_year_event ON event_year(event COLLATE NOCASE)");
|
|
1926
|
+
}
|
|
1927
|
+
};
|
|
1928
|
+
function whereOf(q, prefix = "") {
|
|
1929
|
+
const where = [];
|
|
1930
|
+
const args = [];
|
|
1931
|
+
if (q.event !== undefined) {
|
|
1932
|
+
where.push(`${prefix}event = ? COLLATE NOCASE`);
|
|
1933
|
+
args.push(q.event);
|
|
1934
|
+
}
|
|
1935
|
+
if (q.year !== undefined) {
|
|
1936
|
+
where.push(`${prefix}year = ?`);
|
|
1937
|
+
args.push(q.year);
|
|
1938
|
+
}
|
|
1939
|
+
return { sql: where.length === 0 ? "" : ` WHERE ${where.join(" AND ")}`, args };
|
|
1940
|
+
}
|
|
1941
|
+
|
|
1942
|
+
class TeamFinder2 {
|
|
1943
|
+
rel;
|
|
1944
|
+
constructor(rel) {
|
|
1945
|
+
this.rel = rel;
|
|
1946
|
+
}
|
|
1947
|
+
db() {
|
|
1948
|
+
return this.rel.indexDb("teams");
|
|
1949
|
+
}
|
|
1950
|
+
async results(q = {}) {
|
|
1951
|
+
const db = await this.db();
|
|
1952
|
+
const w = whereOf(q);
|
|
1953
|
+
const rows = db.query(`SELECT address, competition, event, year, card, comp_no, title, category, hands, letter,
|
|
1954
|
+
label, name_printed, school_printed, school_loc, school_id, place, place_printed, tie,
|
|
1955
|
+
competitors, atts
|
|
1956
|
+
FROM result${w.sql} ORDER BY year, event, competition, place IS NULL, place, ord`).all(...w.args);
|
|
1957
|
+
return {
|
|
1958
|
+
tag: this.rel.tag,
|
|
1959
|
+
asked: q,
|
|
1960
|
+
results: rows.map((r) => ({ ...r, atts: JSON.parse(r.atts) }))
|
|
1961
|
+
};
|
|
1962
|
+
}
|
|
1963
|
+
async rosters(q = {}) {
|
|
1964
|
+
const db = await this.db();
|
|
1965
|
+
const w = whereOf(q, "t.");
|
|
1966
|
+
const teams = db.query(`SELECT team, kind, event, year, comp_no, title, team_index, seq, school_id, school_printed
|
|
1967
|
+
FROM roster_team t${w.sql} ORDER BY year, event, ord`).all(...w.args);
|
|
1968
|
+
const members = new Map;
|
|
1969
|
+
for (const m of db.query(`SELECT m.team AS team, m.seq AS seq, m.name_printed AS name_printed, m.name AS name,
|
|
1970
|
+
m.yob AS yob, m.dancer_id AS dancer_id
|
|
1971
|
+
FROM roster_member m JOIN roster_team t ON t.team = m.team${w.sql}
|
|
1972
|
+
ORDER BY m.team, m.seq, m.ord`).all(...w.args)) {
|
|
1973
|
+
const { team, ...rest } = m;
|
|
1974
|
+
let list = members.get(team);
|
|
1975
|
+
if (list === undefined)
|
|
1976
|
+
members.set(team, list = []);
|
|
1977
|
+
list.push({ ...rest, dancer_scope: scope(rest.dancer_id) });
|
|
1978
|
+
}
|
|
1979
|
+
return {
|
|
1980
|
+
tag: this.rel.tag,
|
|
1981
|
+
asked: q,
|
|
1982
|
+
teams: teams.map((t) => ({ ...t, members: members.get(t.team) ?? [] }))
|
|
1983
|
+
};
|
|
1984
|
+
}
|
|
1985
|
+
async resultRosters(q = {}) {
|
|
1986
|
+
const db = await this.db();
|
|
1987
|
+
const w = whereOf(q);
|
|
1988
|
+
const rows = db.query(`SELECT team, event, year, comp_no, school_id, result_address, join_kind, via_split,
|
|
1989
|
+
roster_teams, result_teams, roster_index, result_letter
|
|
1990
|
+
FROM result_roster${w.sql} ORDER BY year, event, ord`).all(...w.args);
|
|
1991
|
+
return {
|
|
1992
|
+
tag: this.rel.tag,
|
|
1993
|
+
asked: q,
|
|
1994
|
+
joins: rows.map((r) => ({ ...r, via_split: r.via_split === 1 }))
|
|
1995
|
+
};
|
|
1996
|
+
}
|
|
1997
|
+
}
|
|
1998
|
+
|
|
1999
|
+
class EventFinder2 {
|
|
2000
|
+
rel;
|
|
2001
|
+
constructor(rel) {
|
|
2002
|
+
this.rel = rel;
|
|
2003
|
+
}
|
|
2004
|
+
async years(q = {}) {
|
|
2005
|
+
const db = await this.rel.indexDb("events");
|
|
2006
|
+
const w = whereOf(q);
|
|
2007
|
+
const rows = db.query(`SELECT event, year, date_lo, date_hi, resolution, source, date_printed, place, place_printed
|
|
2008
|
+
FROM event_year${w.sql} ORDER BY year, event`).all(...w.args);
|
|
2009
|
+
return {
|
|
2010
|
+
tag: this.rel.tag,
|
|
2011
|
+
asked: q,
|
|
2012
|
+
years: rows.map((r) => ({
|
|
2013
|
+
...r,
|
|
2014
|
+
date_printed: JSON.parse(r.date_printed),
|
|
2015
|
+
place_printed: JSON.parse(r.place_printed)
|
|
2016
|
+
}))
|
|
2017
|
+
};
|
|
2018
|
+
}
|
|
2019
|
+
}
|
|
2020
|
+
|
|
1589
2021
|
function defaultBuilders2() {
|
|
1590
|
-
return [schoolsIndex, feisesIndex, compsIndex, dancersIndex, staffIndex];
|
|
2022
|
+
return [schoolsIndex, feisesIndex, compsIndex, dancersIndex, staffIndex, teamsIndex, eventsIndex];
|
|
1591
2023
|
}
|
|
1592
2024
|
var indexDir = (rel) => join(rel.dir, "index");
|
|
1593
2025
|
var indexPath2 = (rel, name) => join(indexDir(rel), `${name}.sqlite`);
|
|
@@ -1623,6 +2055,8 @@ function buildIndex2(rel, b, o) {
|
|
|
1623
2055
|
const key = indexKey2(rel, b);
|
|
1624
2056
|
if (!o.force && keyOf(out) === key)
|
|
1625
2057
|
return out;
|
|
2058
|
+
if (b.load !== undefined && o.loaded === undefined)
|
|
2059
|
+
throw new Error(`archive-client: index "${b.name}" reads its inputs first: build it with ensureIndex (or rel.index)`);
|
|
1626
2060
|
mkdirSync(indexDir(rel), { recursive: true });
|
|
1627
2061
|
const tmp = `${out}.building.${process.pid}`;
|
|
1628
2062
|
rmSync(tmp, { force: true });
|
|
@@ -1632,7 +2066,7 @@ function buildIndex2(rel, b, o) {
|
|
|
1632
2066
|
db.run("PRAGMA journal_mode = OFF");
|
|
1633
2067
|
db.run("PRAGMA synchronous = OFF");
|
|
1634
2068
|
db.run("CREATE TABLE meta(k TEXT PRIMARY KEY, v TEXT NOT NULL)");
|
|
1635
|
-
db.transaction(() => b.build(rel, db))();
|
|
2069
|
+
db.transaction(() => b.build(rel, db, o.loaded))();
|
|
1636
2070
|
const put = db.prepare("INSERT INTO meta(k, v) VALUES (?, ?)");
|
|
1637
2071
|
put.run("key", key);
|
|
1638
2072
|
put.run("builder", b.name);
|
|
@@ -1649,6 +2083,12 @@ function buildIndex2(rel, b, o) {
|
|
|
1649
2083
|
o.log?.(`index ${rel.tag} ${b.name}: built in ${((performance.now() - t0) / 1000).toFixed(1)} s`);
|
|
1650
2084
|
return out;
|
|
1651
2085
|
}
|
|
2086
|
+
async function ensureIndex2(rel, b, o) {
|
|
2087
|
+
if (!o.force && isCurrent2(rel, b))
|
|
2088
|
+
return indexPath2(rel, b.name);
|
|
2089
|
+
const loaded = b.load === undefined ? undefined : await b.load(rel);
|
|
2090
|
+
return buildIndex2(rel, b, { ...o, loaded });
|
|
2091
|
+
}
|
|
1652
2092
|
function listIndexes2(rel) {
|
|
1653
2093
|
const dir = indexDir(rel);
|
|
1654
2094
|
if (!existsSync(dir))
|
|
@@ -2058,6 +2498,149 @@ var FEATURES2 = [
|
|
|
2058
2498
|
since: 265,
|
|
2059
2499
|
calls: "comps.resolve, comps.syllabus, comps.syllabusFor, registrations.resolve (the comps index)"
|
|
2060
2500
|
},
|
|
2501
|
+
{
|
|
2502
|
+
feature: "results.stream",
|
|
2503
|
+
needs: [
|
|
2504
|
+
"results:competitions.round",
|
|
2505
|
+
"results:competitions.feis_level",
|
|
2506
|
+
"results:competitions.level_printed",
|
|
2507
|
+
"results:competitions.age_printed",
|
|
2508
|
+
"results:results.yob_printed",
|
|
2509
|
+
"results:results.primary_source",
|
|
2510
|
+
"results:results.platform_dancer_id",
|
|
2511
|
+
"results:results.relative_place",
|
|
2512
|
+
"results:feises.date_lo",
|
|
2513
|
+
"results:feises.date_hi"
|
|
2514
|
+
],
|
|
2515
|
+
since: 255,
|
|
2516
|
+
calls: "results.stream, results.entries (scopes transcribed, platform, all)"
|
|
2517
|
+
},
|
|
2518
|
+
{
|
|
2519
|
+
feature: "majors.stream",
|
|
2520
|
+
needs: [
|
|
2521
|
+
"majors:competitions.round",
|
|
2522
|
+
"majors:competitions.feis_level",
|
|
2523
|
+
"majors:results.yob_printed",
|
|
2524
|
+
"majors:results.primary_source",
|
|
2525
|
+
"majors:results.relative_place",
|
|
2526
|
+
"majors:feises.date_lo"
|
|
2527
|
+
],
|
|
2528
|
+
since: 255,
|
|
2529
|
+
calls: "results.stream, results.entries (scope majors)"
|
|
2530
|
+
},
|
|
2531
|
+
{
|
|
2532
|
+
feature: "majors.tabs",
|
|
2533
|
+
needs: ["majors:tabs.address", "majors:tabs.true_round"],
|
|
2534
|
+
since: 215,
|
|
2535
|
+
calls: "majors.tabulated"
|
|
2536
|
+
},
|
|
2537
|
+
{
|
|
2538
|
+
feature: "feises.dates",
|
|
2539
|
+
needs: ["results:feises.feis_id", "results:feises.date_lo", "results:feises.date_hi"],
|
|
2540
|
+
since: 245,
|
|
2541
|
+
calls: "feises.dates"
|
|
2542
|
+
},
|
|
2543
|
+
{
|
|
2544
|
+
feature: "dancers.records",
|
|
2545
|
+
needs: [
|
|
2546
|
+
"results:dancers.display",
|
|
2547
|
+
"results:dancers.appearances",
|
|
2548
|
+
"results:dancers.birth_lo",
|
|
2549
|
+
"results:dancers.birth_hi",
|
|
2550
|
+
"results:dancers.birth_source",
|
|
2551
|
+
"results:dancers.birth_conflict",
|
|
2552
|
+
"results:dancers.genders"
|
|
2553
|
+
],
|
|
2554
|
+
since: 215,
|
|
2555
|
+
calls: "dancers.records"
|
|
2556
|
+
},
|
|
2557
|
+
{
|
|
2558
|
+
feature: "dancers.years",
|
|
2559
|
+
needs: [
|
|
2560
|
+
"results:dancer_years.region",
|
|
2561
|
+
"results:dancer_years.region_source",
|
|
2562
|
+
"results:dancer_years.nationals",
|
|
2563
|
+
"results:dancer_years.nationals_source",
|
|
2564
|
+
"results:dancer_years.geohash"
|
|
2565
|
+
],
|
|
2566
|
+
since: 245,
|
|
2567
|
+
calls: "dancers.years"
|
|
2568
|
+
},
|
|
2569
|
+
{
|
|
2570
|
+
feature: "teams",
|
|
2571
|
+
needs: [
|
|
2572
|
+
...[
|
|
2573
|
+
"slug",
|
|
2574
|
+
"address",
|
|
2575
|
+
"event",
|
|
2576
|
+
"year",
|
|
2577
|
+
"card",
|
|
2578
|
+
"comp_no",
|
|
2579
|
+
"title",
|
|
2580
|
+
"category",
|
|
2581
|
+
"hands",
|
|
2582
|
+
"letter",
|
|
2583
|
+
"label",
|
|
2584
|
+
"name_printed",
|
|
2585
|
+
"school_printed",
|
|
2586
|
+
"school_loc",
|
|
2587
|
+
"school_id",
|
|
2588
|
+
"place",
|
|
2589
|
+
"place_printed",
|
|
2590
|
+
"tie",
|
|
2591
|
+
"competitors",
|
|
2592
|
+
"atts"
|
|
2593
|
+
].map((c) => `table:team_results.${c}`),
|
|
2594
|
+
...[
|
|
2595
|
+
"team",
|
|
2596
|
+
"kind",
|
|
2597
|
+
"event_year",
|
|
2598
|
+
"year",
|
|
2599
|
+
"comp_no",
|
|
2600
|
+
"title",
|
|
2601
|
+
"team_index",
|
|
2602
|
+
"seq",
|
|
2603
|
+
"school_id",
|
|
2604
|
+
"school_print_materialized"
|
|
2605
|
+
].map((c) => `table:roster_teams.${c}`),
|
|
2606
|
+
...["team", "seq", "name_printed", "name", "yob", "dancer_id"].map((c) => `table:roster_members.${c}`),
|
|
2607
|
+
...[
|
|
2608
|
+
"event_year",
|
|
2609
|
+
"comp_no",
|
|
2610
|
+
"team",
|
|
2611
|
+
"result_address",
|
|
2612
|
+
"school_id",
|
|
2613
|
+
"join_kind",
|
|
2614
|
+
"via_split",
|
|
2615
|
+
"roster_teams",
|
|
2616
|
+
"result_teams",
|
|
2617
|
+
"roster_index",
|
|
2618
|
+
"result_letter"
|
|
2619
|
+
].map((c) => `table:team_result_rosters.${c}`),
|
|
2620
|
+
"table:event_years.event_year",
|
|
2621
|
+
"table:event_years.event",
|
|
2622
|
+
"table:event_years.year"
|
|
2623
|
+
],
|
|
2624
|
+
since: 260,
|
|
2625
|
+
calls: "teams.results, teams.rosters, teams.resultRosters (the teams index)"
|
|
2626
|
+
},
|
|
2627
|
+
{
|
|
2628
|
+
feature: "events",
|
|
2629
|
+
needs: [
|
|
2630
|
+
"event_year",
|
|
2631
|
+
"event",
|
|
2632
|
+
"year",
|
|
2633
|
+
"date_lo",
|
|
2634
|
+
"date_hi",
|
|
2635
|
+
"resolution",
|
|
2636
|
+
"source",
|
|
2637
|
+
"date_printed",
|
|
2638
|
+
"place",
|
|
2639
|
+
"place_printed"
|
|
2640
|
+
].map((c) => `table:event_years.${c}`),
|
|
2641
|
+
since: 260,
|
|
2642
|
+
calls: "events.years (the events index)"
|
|
2643
|
+
},
|
|
2061
2644
|
{
|
|
2062
2645
|
feature: "staff",
|
|
2063
2646
|
needs: [
|
|
@@ -2072,6 +2655,13 @@ var FEATURES2 = [
|
|
|
2072
2655
|
}
|
|
2073
2656
|
];
|
|
2074
2657
|
async function hasNeed(probe, n) {
|
|
2658
|
+
const t = /^table:([A-Za-z_]+)(?:\.([A-Za-z_]+))?$/.exec(n);
|
|
2659
|
+
if (t !== null) {
|
|
2660
|
+
if (probe.tableColumns === undefined)
|
|
2661
|
+
return false;
|
|
2662
|
+
const cols = await probe.tableColumns(t[1]);
|
|
2663
|
+
return t[2] === undefined ? cols.size > 0 : cols.has(t[2]);
|
|
2664
|
+
}
|
|
2075
2665
|
const m = /^(results|majors):([A-Za-z_]+)(?:\.([A-Za-z_]+))?$/.exec(n);
|
|
2076
2666
|
if (m === null)
|
|
2077
2667
|
return probe.publishes(n);
|
|
@@ -2143,6 +2733,8 @@ class Release2 {
|
|
|
2143
2733
|
staff;
|
|
2144
2734
|
comps;
|
|
2145
2735
|
registrations;
|
|
2736
|
+
teams;
|
|
2737
|
+
events;
|
|
2146
2738
|
opts;
|
|
2147
2739
|
handles = new Map;
|
|
2148
2740
|
remoteAssets = null;
|
|
@@ -2163,6 +2755,8 @@ class Release2 {
|
|
|
2163
2755
|
this.staff = new StaffFinder2(this);
|
|
2164
2756
|
this.comps = new CompResolver2(this);
|
|
2165
2757
|
this.registrations = new RegistrationResolver2(this, this.comps, opts.dancerResolver);
|
|
2758
|
+
this.teams = new TeamFinder2(this);
|
|
2759
|
+
this.events = new EventFinder2(this);
|
|
2166
2760
|
}
|
|
2167
2761
|
receipt() {
|
|
2168
2762
|
return readReceipt(this.dir) ?? { tag: this.tag, source: "unknown", files: {} };
|
|
@@ -2207,7 +2801,14 @@ class Release2 {
|
|
|
2207
2801
|
await this.fetch(name);
|
|
2208
2802
|
return this.db(name);
|
|
2209
2803
|
},
|
|
2210
|
-
publishes: (asset) => this.publishes(asset)
|
|
2804
|
+
publishes: (asset) => this.publishes(asset),
|
|
2805
|
+
tableColumns: async (table) => {
|
|
2806
|
+
const asset = tableAsset(table);
|
|
2807
|
+
if (!await this.publishes(asset))
|
|
2808
|
+
return new Set;
|
|
2809
|
+
await this.fetch(asset);
|
|
2810
|
+
return parquetColumns(this.path(asset));
|
|
2811
|
+
}
|
|
2211
2812
|
};
|
|
2212
2813
|
checked = new Map;
|
|
2213
2814
|
async capability(feature) {
|
|
@@ -2304,7 +2905,7 @@ class Release2 {
|
|
|
2304
2905
|
if (FEATURES2.some((f) => f.feature === b.name))
|
|
2305
2906
|
await this.require(b.name);
|
|
2306
2907
|
await this.fetch(...b.inputs);
|
|
2307
|
-
return
|
|
2908
|
+
return ensureIndex2(this, b, { force: o.force ?? false, log: this.opts.log });
|
|
2308
2909
|
}
|
|
2309
2910
|
async indexDb(name) {
|
|
2310
2911
|
const key = `index:${name}`;
|
|
@@ -2523,7 +3124,7 @@ class ReleaseManager2 {
|
|
|
2523
3124
|
await rel.fetch(...b.inputs);
|
|
2524
3125
|
built.push({
|
|
2525
3126
|
name,
|
|
2526
|
-
path:
|
|
3127
|
+
path: await ensureIndex2(rel, b, { force: o.force ?? false, log: this.opts.log })
|
|
2527
3128
|
});
|
|
2528
3129
|
}
|
|
2529
3130
|
rel.close();
|
|
@@ -2596,4 +3197,4 @@ function releases2(opts = {}) {
|
|
|
2596
3197
|
return new ReleaseManager2(opts);
|
|
2597
3198
|
}
|
|
2598
3199
|
|
|
2599
|
-
export { DATABASES2, planAsset2, sha256File2, unzstdTo2, NAME_LEVELS2, nameLevel2, FEIS_LOCAL_ID_FLOOR2, ResultFinder2, MajorsFinder2, nameOrderOf, DancerResolver2, readPopulation2, canonicalOf2, CompResolver2, NO_CALENDAR2, FeisFinder2, StaffFinder2, SchoolResolver2, defaultBuilders2, indexPath2, indexKey2, isCurrent2, buildIndex2, listIndexes2, readPin2, youngest2, dancerResolverOf2, RegistrationResolver2, ghRemote2, httpsRemote2, fallbackRemote2, setRemote2, columnsOf2, FEATURES2, capabilityOf2, needsRelease2, resolveTag2, Release2, openRelease2, openCached2, ReleaseManager2, releases2 };
|
|
3200
|
+
export { DATABASES2, planAsset2, sha256File2, unzstdTo2, NAME_LEVELS2, nameLevel2, entryRank2, FEIS_LOCAL_ID_FLOOR2, ResultFinder2, MajorsFinder2, nameOrderOf, DancerResolver2, readPopulation2, canonicalOf2, CompResolver2, NO_CALENDAR2, FeisFinder2, StaffFinder2, SchoolResolver2, TeamFinder2, EventFinder2, defaultBuilders2, indexPath2, indexKey2, isCurrent2, buildIndex2, ensureIndex2, listIndexes2, readPin2, youngest2, dancerResolverOf2, RegistrationResolver2, ghRemote2, httpsRemote2, fallbackRemote2, setRemote2, columnsOf2, FEATURES2, capabilityOf2, needsRelease2, resolveTag2, Release2, openRelease2, openCached2, ReleaseManager2, releases2 };
|