@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/dist/cli.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  nameOrderOf,
5
5
  openRelease2,
6
6
  releases2
7
- } from "./chunks/index-3va2jzse.js";
7
+ } from "./chunks/index-8gna56w2.js";
8
8
  import"./chunks/index-hne1wadw.js";
9
9
  import"./chunks/index-hghdy980.js";
10
10
 
@@ -50,6 +50,27 @@ var USAGE = `usage: idq <verb> [--cache <dir>] [--repo <owner/name>] [--json]
50
50
  majors [--release <spec>] [--event <e>] [--year <y>] [--comp <competition>] [--dancer <id>]
51
51
  the majors: every event and its years; an event's
52
52
  competitions; a competition's, an event's or a dancer's rows
53
+ stream [--release <spec>] --scope majors|transcribed|platform|all [--entries] [--event <e,...>]
54
+ [--year <y> | --year <from>..<to>] [--tier <t,...>] [--category <c,...>]
55
+ [--level <feis_level,...>] [--dancer <id,...>] [--school <school_id>] [--primary]
56
+ every row a scope holds, one JSON line each, never the
57
+ whole table in memory; --entries one per address (the row
58
+ it stands for, with its recall order)
59
+ records [--release <spec>] [--dancer <id,...>]
60
+ every dancer's record: display, appearances, birth window,
61
+ populations
62
+ records --years [--release <spec>] [--dancer <id,...>] [--year <y>]
63
+ each dancer's region, nationals and place per year
64
+ feis-dates [--release <spec>] every feis's first and last day
65
+ tabulated [--release <spec>] [--min-round <n>]
66
+ the majors addresses the marks sheets tabulate to round n
67
+ or later (default 3)
68
+ teams [--release <spec>] [--event <e>] [--year <y>] [--rosters | --joins]
69
+ the team result rows of an event-year; with --rosters its
70
+ roster teams and their dancers; with --joins how each roster
71
+ team meets the results
72
+ events [--release <spec>] [--event <e>] [--year <y>]
73
+ each event-year's dates and place
53
74
  teacher [--release <spec>] <name|TD number>
54
75
  the staff lists' people: where they taught, the register,
55
76
  where they sat
@@ -101,7 +122,12 @@ var VALUE = new Set([
101
122
  "--limit",
102
123
  "--event",
103
124
  "--title",
104
- "--for"
125
+ "--for",
126
+ "--scope",
127
+ "--tier",
128
+ "--category",
129
+ "--level",
130
+ "--min-round"
105
131
  ]);
106
132
  function parseArgs(argv) {
107
133
  const positional = [];
@@ -313,6 +339,53 @@ async function resolveVerb(rel, what, args, p, say, stdin) {
313
339
  throw new Error("resolve comp|dancer|registrations");
314
340
  }
315
341
  }
342
+ var SCOPES = ["majors", "transcribed", "platform", "all"];
343
+ var listOf = (v) => v.split(",").map((x) => x.trim()).filter((x) => x !== "");
344
+ var idsOf = (v) => v === undefined ? undefined : listOf(v).map(Number);
345
+ function streamQueryOf(p) {
346
+ const scope = p.flags.get("--scope");
347
+ if (scope === undefined || !SCOPES.includes(scope))
348
+ throw new Error(`stream takes --scope ${SCOPES.join("|")}`);
349
+ const q = { scope };
350
+ const event = p.flags.get("--event");
351
+ if (event !== undefined)
352
+ q.event = listOf(event);
353
+ const year = p.flags.get("--year");
354
+ if (year !== undefined) {
355
+ const m = /^(\d{4})\.\.(\d{4})$/.exec(year);
356
+ q.year = m === null ? Number(year) : [Number(m[1]), Number(m[2])];
357
+ if (typeof q.year === "number" && !Number.isInteger(q.year))
358
+ throw new Error(`--year takes a year or <from>..<to>, not "${year}"`);
359
+ }
360
+ for (const [flag, key] of [
361
+ ["--tier", "tier"],
362
+ ["--category", "category"]
363
+ ]) {
364
+ const v = p.flags.get(flag);
365
+ if (v !== undefined)
366
+ q[key] = listOf(v);
367
+ }
368
+ const level = p.flags.get("--level");
369
+ if (level !== undefined)
370
+ q.feis_level = listOf(level).map(Number);
371
+ const dancers = idsOf(p.flags.get("--dancer"));
372
+ if (dancers !== undefined)
373
+ q.dancer_id = dancers;
374
+ const school = p.flags.get("--school");
375
+ if (school !== undefined)
376
+ q.school_id = school;
377
+ if (p.bools.has("--primary"))
378
+ q.primary = true;
379
+ return q;
380
+ }
381
+ function eventYearOf(p) {
382
+ const event = p.flags.get("--event");
383
+ const year = p.flags.get("--year");
384
+ return {
385
+ ...event !== undefined ? { event } : {},
386
+ ...year !== undefined ? { year: Number(year) } : {}
387
+ };
388
+ }
316
389
  async function main(argv, io = {}) {
317
390
  const say = io.say ?? ((s) => console.log(s));
318
391
  const log = io.log ?? ((s) => console.error(s));
@@ -630,6 +703,129 @@ async function main(argv, io = {}) {
630
703
  rel.close();
631
704
  }
632
705
  }
706
+ case "stream": {
707
+ const q = streamQueryOf(p);
708
+ const rel = await openRelease2(spec, { ...opts, assets: [] });
709
+ try {
710
+ let n = 0;
711
+ const rows = p.bools.has("--entries") ? rel.results.entries(q) : rel.results.stream(q);
712
+ for await (const r of rows) {
713
+ say(JSON.stringify(r));
714
+ n++;
715
+ }
716
+ log(`${n} ${p.bools.has("--entries") ? "entries" : "rows"} in ${rel.tag}`);
717
+ return n === 0 ? 1 : 0;
718
+ } finally {
719
+ rel.close();
720
+ }
721
+ }
722
+ case "records": {
723
+ const rel = await openRelease2(spec, { ...opts, assets: [] });
724
+ try {
725
+ const ids = idsOf(p.flags.get("--dancer"));
726
+ if (p.bools.has("--years")) {
727
+ const year = p.flags.get("--year");
728
+ const a = await rel.dancers.years({
729
+ ...ids !== undefined ? { ids } : {},
730
+ ...year !== undefined ? { year: Number(year) } : {}
731
+ });
732
+ out(a, () => {
733
+ for (const y of a.years)
734
+ say(` ${y.dancer_id} ${y.year} ${y.region ?? "-"} (${y.region_source ?? "-"}) nationals ${y.nationals ?? "-"} ${y.geohash ?? "-"}`);
735
+ say(`${a.years.length} dancer-year(s) in ${a.tag}`);
736
+ });
737
+ return a.years.length === 0 ? 1 : 0;
738
+ }
739
+ const a = await rel.dancers.records(ids !== undefined ? { ids } : {});
740
+ out(a, () => {
741
+ for (const r of a.records)
742
+ say(` ${r.dancer_id} ${r.display} ${r.appearances} entries born ${r.birth_lo ?? "?"}..${r.birth_hi ?? "?"} (${r.birth_source}${r.birth_conflict ? ", conflict" : ""}) ${r.genders.join(",") || "-"}`);
743
+ say(`${a.records.length} dancer(s) in ${a.tag}`);
744
+ });
745
+ return a.records.length === 0 ? 1 : 0;
746
+ } finally {
747
+ rel.close();
748
+ }
749
+ }
750
+ case "feis-dates": {
751
+ const rel = await openRelease2(spec, { ...opts, assets: [] });
752
+ try {
753
+ const a = await rel.feises.dates();
754
+ out(a, () => {
755
+ for (const d of a.dates)
756
+ say(` ${d.feis_id} ${d.date_lo ?? "?"}..${d.date_hi ?? "?"}`);
757
+ say(`${a.dates.length} feis(es) in ${a.tag}`);
758
+ });
759
+ return a.dates.length === 0 ? 1 : 0;
760
+ } finally {
761
+ rel.close();
762
+ }
763
+ }
764
+ case "tabulated": {
765
+ const rel = await openRelease2(spec, { ...opts, assets: [] });
766
+ try {
767
+ const min = p.flags.get("--min-round");
768
+ const a = await rel.majors.tabulated(min !== undefined ? { min_true_round: Number(min) } : {});
769
+ out(a, () => {
770
+ for (const x of a.addresses)
771
+ say(` ${x}`);
772
+ say(`${a.addresses.length} address(es) tabulated to round ${a.min_true_round} or later in ${a.tag}`);
773
+ });
774
+ return a.addresses.length === 0 ? 1 : 0;
775
+ } finally {
776
+ rel.close();
777
+ }
778
+ }
779
+ case "teams": {
780
+ const rel = await openRelease2(spec, { ...opts, assets: [] });
781
+ try {
782
+ const q = eventYearOf(p);
783
+ if (p.bools.has("--rosters")) {
784
+ const a = await rel.teams.rosters(q);
785
+ out(a, () => {
786
+ for (const t of a.teams) {
787
+ say(` ${t.year} ${t.event ?? "?"} ${t.comp_no ?? "-"} ${t.team_index ?? "-"} ${t.school_id ?? "(no id)"} "${t.school_printed ?? ""}" ${t.title ?? ""} [${t.kind}]`);
788
+ for (const m of t.members)
789
+ say(` ${m.seq} ${m.dancer_id ?? "-"} ${m.name_printed}${m.yob === null ? "" : ` (${m.yob})`}`);
790
+ }
791
+ say(`${a.teams.length} roster team(s) in ${a.tag}`);
792
+ });
793
+ return a.teams.length === 0 ? 1 : 0;
794
+ }
795
+ if (p.bools.has("--joins")) {
796
+ const a = await rel.teams.resultRosters(q);
797
+ out(a, () => {
798
+ for (const j of a.joins)
799
+ say(` ${j.year ?? "?"} ${j.event ?? "?"} ${j.comp_no ?? "-"} ${j.team} ${j.join_kind} ${j.result_address ?? "-"} roster ${j.roster_index ?? "-"} result ${j.result_letter ?? "-"}`);
800
+ say(`${a.joins.length} join(s) in ${a.tag}`);
801
+ });
802
+ return a.joins.length === 0 ? 1 : 0;
803
+ }
804
+ const a = await rel.teams.results(q);
805
+ out(a, () => {
806
+ for (const r of a.results)
807
+ say(` ${r.address} ${r.place_printed ?? "-"} ${r.label ?? "-"} ${r.school_id ?? "(no id)"} "${r.school_printed ?? ""}" ${r.title ?? ""}${r.atts.length > 0 ? ` [${r.atts.join(",")}]` : ""}`);
808
+ say(`${a.results.length} team result(s) in ${a.tag}`);
809
+ });
810
+ return a.results.length === 0 ? 1 : 0;
811
+ } finally {
812
+ rel.close();
813
+ }
814
+ }
815
+ case "events": {
816
+ const rel = await openRelease2(spec, { ...opts, assets: [] });
817
+ try {
818
+ const a = await rel.events.years(eventYearOf(p));
819
+ out(a, () => {
820
+ for (const y of a.years)
821
+ say(` ${y.event} ${y.year} ${y.date_lo ?? "?"}..${y.date_hi ?? "?"} (${y.resolution ?? "-"}, ${y.source ?? "-"}) ${y.place ?? "-"}${y.place_printed.length > 0 ? ` "${y.place_printed.join("; ")}"` : ""}`);
822
+ say(`${a.years.length} event-year(s) in ${a.tag}`);
823
+ });
824
+ return a.years.length === 0 ? 1 : 0;
825
+ } finally {
826
+ rel.close();
827
+ }
828
+ }
633
829
  case "teacher":
634
830
  case "adjudicator": {
635
831
  if (rest.length === 0) {
@@ -719,5 +915,6 @@ export {
719
915
  USAGE,
720
916
  jsonLines,
721
917
  main,
722
- parseArgs
918
+ parseArgs,
919
+ streamQueryOf
723
920
  };
package/dist/index.js CHANGED
@@ -6,6 +6,7 @@ import {
6
6
  unzstdTo2,
7
7
  NAME_LEVELS2,
8
8
  nameLevel2,
9
+ entryRank2,
9
10
  FEIS_LOCAL_ID_FLOOR2,
10
11
  ResultFinder2,
11
12
  MajorsFinder2,
@@ -17,11 +18,14 @@ import {
17
18
  FeisFinder2,
18
19
  StaffFinder2,
19
20
  SchoolResolver2,
21
+ TeamFinder2,
22
+ EventFinder2,
20
23
  defaultBuilders2,
21
24
  indexPath2,
22
25
  indexKey2,
23
26
  isCurrent2,
24
27
  buildIndex2,
28
+ ensureIndex2,
25
29
  listIndexes2,
26
30
  readPin2,
27
31
  youngest2,
@@ -41,7 +45,7 @@ import {
41
45
  openCached2,
42
46
  ReleaseManager2,
43
47
  releases2
44
- } from "./chunks/index-3va2jzse.js";
48
+ } from "./chunks/index-8gna56w2.js";
45
49
  import {
46
50
  cacheRoot2,
47
51
  repoOf2
@@ -60,6 +64,7 @@ export {
60
64
  CompResolver2 as CompResolver,
61
65
  DATABASES2 as DATABASES,
62
66
  DancerResolver2 as DancerResolver,
67
+ EventFinder2 as EventFinder,
63
68
  FEATURES2 as FEATURES,
64
69
  FEIS_LOCAL_ID_FLOOR2 as FEIS_LOCAL_ID_FLOOR,
65
70
  FeisFinder2 as FeisFinder,
@@ -72,6 +77,7 @@ export {
72
77
  ResultFinder2 as ResultFinder,
73
78
  SchoolResolver2 as SchoolResolver,
74
79
  StaffFinder2 as StaffFinder,
80
+ TeamFinder2 as TeamFinder,
75
81
  buildIndex2 as buildIndex,
76
82
  cacheRoot2 as cacheRoot,
77
83
  canonicalOf2 as canonicalOf,
@@ -81,6 +87,8 @@ export {
81
87
  cutOf2 as cutOf,
82
88
  dancerResolverOf2 as dancerResolverOf,
83
89
  defaultBuilders2 as defaultBuilders,
90
+ ensureIndex2 as ensureIndex,
91
+ entryRank2 as entryRank,
84
92
  fallbackRemote2 as fallbackRemote,
85
93
  ghRemote2 as ghRemote,
86
94
  httpsRemote2 as httpsRemote,
@@ -1,6 +1,7 @@
1
1
  #!/usr/bin/env bun
2
2
  import type { OpenOptions } from "./release.js";
3
- export declare const USAGE = "usage: idq <verb> [--cache <dir>] [--repo <owner/name>] [--json]\n\n config repo <owner/name> set the user-local repository the releases come from\n list [--remote] the cached releases (size, files, indexes, the pin), and\n with --remote the published tags\n fetch [--release <spec>] [--assets results,majors,<file>...]\n download, verify and cache a release (default: results)\n pin <spec> the user-local pin: what a bare open (spec \"pinned\") opens\n unpin remove the pin (a bare open is then \"latest\")\n current the pin, and whether it is cached\n add <dir> --tag <tag> add a release built locally (its MANIFEST.json and files)\n to the cache under its tag\n index [--release <spec>] [<name>...] [--force]\n build the per-tag indexes (default: every one)\n verify [--release <spec>] re-hash every cached file against its receipt\n capabilities [--release <spec>] what the release carries of what the client reads, from\n its own schema: each feature full or missing (its calls\n refuse, naming the first cut that publishes it)\n prune [--keep N] [--dry-run] remove all but the N newest cached releases (default 1)\n and the pinned one\n rm <tag> [--dry-run] remove one cached release (not the pinned one)\n drop-indexes [<tag>] [--dry-run] remove the index files (of one release, or of every one)\n feis [--release <spec>] [--platform <p>] [--code <c>] [--id <id>] [--name <glob>] [--year <y>]\n the feises a query names\n series [--release <spec>] <name|host code|feis id>\n the series a name, a host code (fweb:ABC) or any feis id\n names: its years, hosts, codes and next instance\n school [--release <spec>] <print|school_id> [--region <code>]\n a school print or id to the published schools\n dancer [--release <spec>] <name> | --surname <s> | --like <glob> | --id <dancer_id>\n [--order surname-first|given-first] [--school <print|id>]\n [--yob <y> | --band <U10> [--year <y>] | --comp <competition>] [--as-of <date>]\n [--population girls|boys] [--rows]\n the dancers a name reaches, each with its evidence\n (name level, age, school, population) and the arm; the results of\n the one dancer where one answers (or --rows for each)\n results [--release <spec>] [--dancer <id>] [--feis <id>] [--comp <competition>]\n [--school <print|id>] [--year <y>] [--limit <n>]\n the published result rows, prints and ids\n majors [--release <spec>] [--event <e>] [--year <y>] [--comp <competition>] [--dancer <id>]\n the majors: every event and its years; an event's\n competitions; a competition's, an event's or a dancer's rows\n teacher [--release <spec>] <name|TD number>\n the staff lists' people: where they taught, the register,\n where they sat\n adjudicator [--release <spec>] <name|TD number>\n the register's and the panels' people: the same answer\n comp [--release <spec>] <feis> <code> [--year <y>] [--title <t>]\n a feis's own comp code to the comp it names, through that\n feis's syllabus (or the prior year's)\n syllabus [--release <spec>] <feis> [year]\n one feis-year's comps, in printed order\n syllabus [--release <spec>] --for <series> [year]\n a series' syllabus for a year: that year's where held,\n else the newest, saying which and what it is read from\n resolve comp [<feis> <code>] [--year <y>] [--title <t>]\n resolve dancer [<name>] [--school <s>] [--comp <feis>/<code> | --yob <y> | --band <b> --year <y>]\n [--order <o>] [--as-of <date>] [--population girls|boys]\n resolve registrations\n JSONL out, one answer per line; with no positional the\n questions are JSONL on stdin, one per line (a comp:\n {feis, code, year?, title?}, a dancer: {name, school?, age?,\n population?}, a registration: {name, school?, codes[], feis,\n year?, population?})\n\n <spec>: pinned (the default) | latest | a cut (42, 42.1) | a tag (archive-YYYY.MM.DD-N)";
3
+ import type { StreamQuery } from "./stream.js";
4
+ export declare const USAGE = "usage: idq <verb> [--cache <dir>] [--repo <owner/name>] [--json]\n\n config repo <owner/name> set the user-local repository the releases come from\n list [--remote] the cached releases (size, files, indexes, the pin), and\n with --remote the published tags\n fetch [--release <spec>] [--assets results,majors,<file>...]\n download, verify and cache a release (default: results)\n pin <spec> the user-local pin: what a bare open (spec \"pinned\") opens\n unpin remove the pin (a bare open is then \"latest\")\n current the pin, and whether it is cached\n add <dir> --tag <tag> add a release built locally (its MANIFEST.json and files)\n to the cache under its tag\n index [--release <spec>] [<name>...] [--force]\n build the per-tag indexes (default: every one)\n verify [--release <spec>] re-hash every cached file against its receipt\n capabilities [--release <spec>] what the release carries of what the client reads, from\n its own schema: each feature full or missing (its calls\n refuse, naming the first cut that publishes it)\n prune [--keep N] [--dry-run] remove all but the N newest cached releases (default 1)\n and the pinned one\n rm <tag> [--dry-run] remove one cached release (not the pinned one)\n drop-indexes [<tag>] [--dry-run] remove the index files (of one release, or of every one)\n feis [--release <spec>] [--platform <p>] [--code <c>] [--id <id>] [--name <glob>] [--year <y>]\n the feises a query names\n series [--release <spec>] <name|host code|feis id>\n the series a name, a host code (fweb:ABC) or any feis id\n names: its years, hosts, codes and next instance\n school [--release <spec>] <print|school_id> [--region <code>]\n a school print or id to the published schools\n dancer [--release <spec>] <name> | --surname <s> | --like <glob> | --id <dancer_id>\n [--order surname-first|given-first] [--school <print|id>]\n [--yob <y> | --band <U10> [--year <y>] | --comp <competition>] [--as-of <date>]\n [--population girls|boys] [--rows]\n the dancers a name reaches, each with its evidence\n (name level, age, school, population) and the arm; the results of\n the one dancer where one answers (or --rows for each)\n results [--release <spec>] [--dancer <id>] [--feis <id>] [--comp <competition>]\n [--school <print|id>] [--year <y>] [--limit <n>]\n the published result rows, prints and ids\n majors [--release <spec>] [--event <e>] [--year <y>] [--comp <competition>] [--dancer <id>]\n the majors: every event and its years; an event's\n competitions; a competition's, an event's or a dancer's rows\n stream [--release <spec>] --scope majors|transcribed|platform|all [--entries] [--event <e,...>]\n [--year <y> | --year <from>..<to>] [--tier <t,...>] [--category <c,...>]\n [--level <feis_level,...>] [--dancer <id,...>] [--school <school_id>] [--primary]\n every row a scope holds, one JSON line each, never the\n whole table in memory; --entries one per address (the row\n it stands for, with its recall order)\n records [--release <spec>] [--dancer <id,...>]\n every dancer's record: display, appearances, birth window,\n populations\n records --years [--release <spec>] [--dancer <id,...>] [--year <y>]\n each dancer's region, nationals and place per year\n feis-dates [--release <spec>] every feis's first and last day\n tabulated [--release <spec>] [--min-round <n>]\n the majors addresses the marks sheets tabulate to round n\n or later (default 3)\n teams [--release <spec>] [--event <e>] [--year <y>] [--rosters | --joins]\n the team result rows of an event-year; with --rosters its\n roster teams and their dancers; with --joins how each roster\n team meets the results\n events [--release <spec>] [--event <e>] [--year <y>]\n each event-year's dates and place\n teacher [--release <spec>] <name|TD number>\n the staff lists' people: where they taught, the register,\n where they sat\n adjudicator [--release <spec>] <name|TD number>\n the register's and the panels' people: the same answer\n comp [--release <spec>] <feis> <code> [--year <y>] [--title <t>]\n a feis's own comp code to the comp it names, through that\n feis's syllabus (or the prior year's)\n syllabus [--release <spec>] <feis> [year]\n one feis-year's comps, in printed order\n syllabus [--release <spec>] --for <series> [year]\n a series' syllabus for a year: that year's where held,\n else the newest, saying which and what it is read from\n resolve comp [<feis> <code>] [--year <y>] [--title <t>]\n resolve dancer [<name>] [--school <s>] [--comp <feis>/<code> | --yob <y> | --band <b> --year <y>]\n [--order <o>] [--as-of <date>] [--population girls|boys]\n resolve registrations\n JSONL out, one answer per line; with no positional the\n questions are JSONL on stdin, one per line (a comp:\n {feis, code, year?, title?}, a dancer: {name, school?, age?,\n population?}, a registration: {name, school?, codes[], feis,\n year?, population?})\n\n <spec>: pinned (the default) | latest | a cut (42, 42.1) | a tag (archive-YYYY.MM.DD-N)";
4
5
  export interface Parsed {
5
6
  positional: string[];
6
7
  flags: Map<string, string>;
@@ -15,6 +16,7 @@ type Line<T> = {
15
16
  error: string;
16
17
  };
17
18
  export declare function jsonLines<T>(text: string, check: (v: T) => string | null): Line<T>[];
19
+ export declare function streamQueryOf(p: Parsed): StreamQuery;
18
20
  export declare function main(argv: readonly string[], io?: {
19
21
  say?: (s: string) => void;
20
22
  log?: (s: string) => void;
@@ -140,10 +140,43 @@ export interface DancerRecord {
140
140
  export declare const PACKAGE_KEY_PARTS: readonly string[];
141
141
  export declare const dancersIndex: IndexBuilder;
142
142
  export declare function yearOf(asOf: string | undefined): number | null;
143
+ export interface DancerBulkRecord {
144
+ dancer_id: number;
145
+ display: string;
146
+ scope: "per-release" | "stable";
147
+ appearances: number;
148
+ birth_lo: number | null;
149
+ birth_hi: number | null;
150
+ birth_source: string;
151
+ birth_conflict: boolean;
152
+ genders: string[];
153
+ }
154
+ export interface DancerYear {
155
+ dancer_id: number;
156
+ year: number;
157
+ region: string | null;
158
+ region_source: string | null;
159
+ nationals: string | null;
160
+ nationals_source: string | null;
161
+ geohash: string | null;
162
+ }
143
163
  export declare class DancerResolver {
144
164
  private readonly rel;
145
165
  private readonly printIds;
146
166
  constructor(rel: Release);
167
+ records(q?: {
168
+ ids?: readonly number[];
169
+ }): Promise<{
170
+ tag: string;
171
+ records: DancerBulkRecord[];
172
+ }>;
173
+ years(q?: {
174
+ ids?: readonly number[];
175
+ year?: number;
176
+ }): Promise<{
177
+ tag: string;
178
+ years: DancerYear[];
179
+ }>;
147
180
  resolve(q: DancerQuery): Promise<DancerAnswer>;
148
181
  search(q: DancerSearchQuery): Promise<DancerAnswer>;
149
182
  private capped;
@@ -77,6 +77,14 @@ export declare const NO_CALENDAR = "the release holds a feis-year once its resul
77
77
  export declare class FeisFinder {
78
78
  private readonly rel;
79
79
  constructor(rel: Release);
80
+ dates(): Promise<{
81
+ tag: string;
82
+ dates: {
83
+ feis_id: string;
84
+ date_lo: string | null;
85
+ date_hi: string | null;
86
+ }[];
87
+ }>;
80
88
  find(q: FeisQuery): Promise<FeisAnswer>;
81
89
  codeStem(token: string, stem: string): Promise<string[]>;
82
90
  seriesOf(brand: string): Promise<Series>;
@@ -1,11 +1,11 @@
1
1
  export { type AssetPlan, DATABASES, type DatabaseName, type LandedFile, type Receipt, type ReleaseManifest, planAsset, } from "./assets.js";
2
2
  export { sha256File, unzstdTo } from "./bytes.js";
3
- export { type AgeAsked, type AgeEvidence, type DancerAnswer, type DancerCandidate, type DancerQuery, type DancerRecord, DancerResolver, type DancerSchool, type DancerSearchQuery, type ExcludedCandidate, FEIS_LOCAL_ID_FLOOR, type PopulationEvidence, type SchoolEvidence, readPopulation, } from "./dancers.js";
3
+ export { type AgeAsked, type AgeEvidence, type DancerAnswer, type DancerBulkRecord, type DancerCandidate, type DancerQuery, type DancerRecord, DancerResolver, type DancerSchool, type DancerSearchQuery, type DancerYear, type ExcludedCandidate, FEIS_LOCAL_ID_FLOOR, type PopulationEvidence, type SchoolEvidence, readPopulation, } from "./dancers.js";
4
4
  export { NAME_LEVELS, type NameLevel, nameLevel } from "./dancers-names.js";
5
5
  export { type Comp, type CompAnswer, type CompKind, type CompQuery, CompResolver, type CompSource, type FeisPlace, type SyllabusAnswer, type SyllabusForAnswer, type SyllabusSource, type TitleCheck, canonicalOf, } from "./comps.js";
6
6
  export { type ClientOptions, cacheRoot, repoOf } from "./config.js";
7
7
  export { type Feis, type FeisAnswer, FeisFinder, type FeisQuery, NO_CALENDAR, type Series, type SeriesAnswer, type SeriesInstance, type SeriesNext, } from "./feises.js";
8
- export { type IndexBuilder, type IndexFile, buildIndex, defaultBuilders, indexKey, indexPath, isCurrent, listIndexes, } from "./indexes.js";
8
+ export { type IndexBuilder, type IndexFile, buildIndex, defaultBuilders, ensureIndex, indexKey, indexPath, isCurrent, listIndexes, } from "./indexes.js";
9
9
  export { type CachedRelease, type ReleaseList, ReleaseManager, type RemovalPlan, releases, } from "./manager.js";
10
10
  export { type Registered, type Sat, type StaffAnswer, StaffFinder, type StaffPerson, type Taught, type TdLink, } from "./people.js";
11
11
  export { type Pin, readPin } from "./pin.js";
@@ -15,4 +15,6 @@ export { type MajorCompetition, type MajorEvent, MajorsFinder, type ResultAnswer
15
15
  export { type DancerAnswerLike, type DancerQueryLike, type DancerResolverLike, type DancerUnavailable, type RegistrationRow, type ResolvedDancer, RegistrationResolver, type ResolvedRegistration, dancerResolverOf, youngest, } from "./registrations.js";
16
16
  export { type SchoolAnswer, type SchoolCandidate, type SchoolQuery, SchoolResolver, type SchoolRung, } from "./schools.js";
17
17
  export { type Capability, FEATURES, type Feature, type SchemaProbe, capabilityOf, columnsOf, needsRelease, } from "./schema.js";
18
+ export { type EntryRow, type StreamQuery, type StreamRow, type StreamScope, entryRank, } from "./stream.js";
19
+ export { EventFinder, type EventYear, type EventYearQuery, type ResultRoster, type RosterMember, type RosterTeam, TeamFinder, type TeamResult, } from "./teams.js";
18
20
  export { ARCHIVE_TAG, type ArchiveTag, type ReleaseSpec, compareTagsNewestFirst, cutOf, parseArchiveTag, parseReleaseSpec, pickTag, renderArchiveTag, } from "./tag.js";
@@ -6,7 +6,8 @@ export interface IndexBuilder {
6
6
  readonly inputs: readonly string[];
7
7
  readonly says: string;
8
8
  keyParts?(rel: Release): string[];
9
- build(rel: Release, out: Database): void;
9
+ load?(rel: Release): Promise<unknown>;
10
+ build(rel: Release, out: Database, loaded?: unknown): void;
10
11
  }
11
12
  export declare function defaultBuilders(): IndexBuilder[];
12
13
  export declare const indexDir: (rel: {
@@ -21,7 +22,12 @@ export declare function isCurrent(rel: Release, b: IndexBuilder): boolean;
21
22
  export declare function buildIndex(rel: Release, b: IndexBuilder, o: {
22
23
  force: boolean;
23
24
  log?: (line: string) => void;
25
+ loaded?: unknown;
24
26
  }): string;
27
+ export declare function ensureIndex(rel: Release, b: IndexBuilder, o: {
28
+ force: boolean;
29
+ log?: (line: string) => void;
30
+ }): Promise<string>;
25
31
  export interface IndexFile {
26
32
  name: string;
27
33
  path: string;
@@ -0,0 +1,4 @@
1
+ export declare const tableAsset: (table: string) => string;
2
+ export declare function plain(v: unknown): unknown;
3
+ export declare function readParquet(path: string, columns?: readonly string[]): Promise<Record<string, unknown>[]>;
4
+ export declare function parquetColumns(path: string): Promise<Set<string>>;
@@ -12,6 +12,7 @@ import { MajorsFinder, ResultFinder } from "./results.js";
12
12
  import { type Capability } from "./schema.js";
13
13
  import { type SchoolReaderChoice, SchoolResolver } from "./schools.js";
14
14
  import { type ReleaseSpec } from "./tag.js";
15
+ import { EventFinder, TeamFinder } from "./teams.js";
15
16
  export interface OpenOptions extends ClientOptions {
16
17
  assets?: readonly string[];
17
18
  remote?: Remote;
@@ -41,6 +42,8 @@ export declare class Release {
41
42
  readonly staff: StaffFinder;
42
43
  readonly comps: CompResolver;
43
44
  readonly registrations: RegistrationResolver;
45
+ readonly teams: TeamFinder;
46
+ readonly events: EventFinder;
44
47
  private readonly opts;
45
48
  private readonly handles;
46
49
  private remoteAssets;
@@ -1,4 +1,5 @@
1
1
  import type { Release } from "./release.js";
2
+ import { type EntryRow, type StreamQuery, type StreamRow } from "./stream.js";
2
3
  export declare const FEIS_LOCAL_ID_FLOOR = 17179869184;
3
4
  export interface ResultQuery {
4
5
  dancer_id?: number;
@@ -43,6 +44,9 @@ export declare class ResultFinder {
43
44
  private readonly rel;
44
45
  constructor(rel: Release);
45
46
  query(q: ResultQuery): Promise<ResultAnswer>;
47
+ private streamDb;
48
+ stream(q: StreamQuery): AsyncGenerator<StreamRow>;
49
+ entries(q: StreamQuery): AsyncGenerator<EntryRow>;
46
50
  }
47
51
  export interface MajorEvent {
48
52
  event: string;
@@ -78,5 +82,12 @@ export declare class MajorsFinder {
78
82
  tag: string;
79
83
  competitions: MajorCompetition[];
80
84
  }>;
85
+ tabulated(q?: {
86
+ min_true_round?: number;
87
+ }): Promise<{
88
+ tag: string;
89
+ min_true_round: number;
90
+ addresses: string[];
91
+ }>;
81
92
  results(q: ResultQuery): Promise<ResultAnswer>;
82
93
  }
@@ -14,6 +14,7 @@ export interface Capability extends Feature {
14
14
  export interface SchemaProbe {
15
15
  db(name: string): Promise<Database>;
16
16
  publishes(asset: string): Promise<boolean>;
17
+ tableColumns?(table: string): Promise<Set<string>>;
17
18
  }
18
19
  export declare function hasNeed(probe: SchemaProbe, n: string): Promise<boolean>;
19
20
  export declare function capabilityOf(probe: SchemaProbe, f: Feature): Promise<Capability>;
@@ -0,0 +1,71 @@
1
+ import type { Database } from "bun:sqlite";
2
+ export type StreamScope = "majors" | "transcribed" | "platform" | "all";
3
+ export interface StreamQuery {
4
+ scope: StreamScope;
5
+ event?: string | string[];
6
+ year?: number | [number, number];
7
+ tier?: string[];
8
+ category?: string[];
9
+ feis_level?: number[];
10
+ dancer_id?: number[];
11
+ school_id?: string;
12
+ primary?: boolean;
13
+ }
14
+ export interface StreamRow {
15
+ address: string;
16
+ competition: string;
17
+ event: string;
18
+ year: number | null;
19
+ tier: string;
20
+ comp_no: string | null;
21
+ title: string | null;
22
+ category: string | null;
23
+ age: string | null;
24
+ age_printed: string | null;
25
+ gender: string | null;
26
+ competitors: number | null;
27
+ feis_level: number | null;
28
+ level_printed: string | null;
29
+ date_printed: string | null;
30
+ source: string;
31
+ round: string | null;
32
+ feis_id: string | null;
33
+ feis_date_lo: string | null;
34
+ feis_date_hi: string | null;
35
+ section: string;
36
+ card: string;
37
+ place: number | null;
38
+ place_printed: string;
39
+ tie: number;
40
+ relative_place: number | null;
41
+ atts: string[];
42
+ withdrawn: string | null;
43
+ qualifier: string | null;
44
+ name_printed: string;
45
+ name: string | null;
46
+ school_printed: string;
47
+ school_loc: string;
48
+ school_id: string | null;
49
+ dancer_id: number | null;
50
+ dancer_scope: "per-release" | "stable" | null;
51
+ yob: number | null;
52
+ yob_printed: string | null;
53
+ points_printed: string | null;
54
+ platform_dancer_id: string | null;
55
+ primary_source: string | null;
56
+ }
57
+ export interface EntryRow extends StreamRow {
58
+ recall_place: number | null;
59
+ }
60
+ export declare function entryRank(section: string): number;
61
+ export declare const scopeDb: (s: StreamScope) => "majors" | "results";
62
+ export declare function streamSql(q: StreamQuery): {
63
+ sql: string;
64
+ args: (string | number)[];
65
+ };
66
+ export declare function feisDates(db: Database): Map<string, {
67
+ lo: string | null;
68
+ hi: string | null;
69
+ }>;
70
+ export declare function streamRows(db: Database, q: StreamQuery): AsyncGenerator<StreamRow>;
71
+ export declare function entryRows(db: Database, q: StreamQuery): AsyncGenerator<EntryRow>;