@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 CHANGED
@@ -2,8 +2,8 @@
2
2
 
3
3
  Open a versioned release of an Irish dance results dataset and work with it locally: download,
4
4
  verify, decompress and cache it by tag, keep a user-local cache of releases, and resolve feises,
5
- schools, competitions, registration lists, dancers, results, majors, teachers and
6
- adjudicators against one. A command line, `idq`, is a thin wrapper over the same calls.
5
+ schools, competitions, registration lists, dancers, results, majors, teams, event dates, teachers
6
+ and adjudicators against one. A command line, `idq`, is a thin wrapper over the same calls.
7
7
 
8
8
  Bun 1.4.2 or later (the databases open through `bun:sqlite`). MIT.
9
9
 
@@ -20,7 +20,7 @@ type declarations (`.d.ts`), so a TypeScript project needs Bun's types (`"types"
20
20
  `bunx idq <verb>`.
21
21
 
22
22
  The version is 0.x while the API settles: a minor bump may break, so pin a minor
23
- (`"@finbheara/archive-client": "0.2.x"`).
23
+ (`"@finbheara/archive-client": "0.5.x"`).
24
24
 
25
25
  ## Configuration
26
26
 
@@ -85,6 +85,13 @@ c.features; // [{ feature: "dancers", state: "full" | "missing", missing: [...
85
85
  | `staff` | `staff.teacher`, `staff.adjudicator` | 260 |
86
86
  | `majors.order` | `majors.competitions` | 260 |
87
87
  | `feises`, `comps` | `feises.find`, `feises.series`, `comps.*`, `registrations.resolve` | 265 |
88
+ | `results.stream`, `majors.stream` | `results.stream`, `results.entries` | 255 |
89
+ | `feises.dates` | `feises.dates` | 245 |
90
+ | `dancers.records` | `dancers.records` | 215 |
91
+ | `dancers.years` | `dancers.years` | 245 |
92
+ | `majors.tabs` | `majors.tabulated` | 215 |
93
+ | `teams` | `teams.results`, `teams.rosters`, `teams.resultRosters` | 260 |
94
+ | `events` | `events.years` | 260 |
88
95
 
89
96
  A spec is `pinned` (the default: the user-local pin, else the latest), `latest`, a cut number
90
97
  (`42`, or `42.1` for a fraction) or a tag (`archive-YYYY.MM.DD-N`).
@@ -138,8 +145,9 @@ outside the cache root.
138
145
 
139
146
  The release databases carry a primary key per table and nothing more, so lookups build side
140
147
  indexes, one SQLite file per index per tag, each keyed on its builder's version and the sha256 of
141
- every input it read. A file whose key is stale is rebuilt, never served. Four ship here, and a
142
- caller may hand its own (`builders` option, an `IndexBuilder`):
148
+ every input it read. A file whose key is stale is rebuilt, never served. These ship here, and a
149
+ caller may hand its own (`builders` option, an `IndexBuilder`, with an optional async `load` step
150
+ whose answer its `build` receives):
143
151
 
144
152
  - `schools`: every published school print with the ids its rows carry, filed into a
145
153
  `@finbheara/domain` `schoolEncoder` noun index, with the registry and the retired ids
@@ -151,6 +159,9 @@ caller may hand its own (`builders` option, an `IndexBuilder`):
151
159
  - `staff` (keyed the same way): teachers and adjudicators by name (a `roleEncoder` noun index) and TD number: the
152
160
  schools' staff lists and TD links, the adjudicator register, and the seats each sat
153
161
  - `comps`: every competition by its feis and the feis's own code, with its series and year
162
+ - `teams`: the team results, the roster teams with their members, and how they join, by
163
+ event-year
164
+ - `events`: every event-year's dates and place
154
165
 
155
166
  ## Feises
156
167
 
@@ -270,6 +281,75 @@ A row carries the prints and the ids that stand for them: the address, the compe
270
281
  and age, the place, the name and school as printed with the dancer and school ids. The majors are
271
282
  read from `majors.sqlite`, fetched on first use.
272
283
 
284
+ ## Every row, streamed
285
+
286
+ ```ts
287
+ for await (const row of rel.results.stream({ scope: "majors" })) { ... }
288
+ for await (const row of rel.results.stream({
289
+ scope: "platform", // "majors" | "transcribed" | "platform" | "all"
290
+ primary: true, // only rows no other source stands in for
291
+ year: [2015, 2024], // a year or an inclusive range
292
+ feis_level: [600, 700], // also: event (one or several), tier, category, dancer_id, school_id
293
+ })) { ... }
294
+ for await (const entry of rel.results.entries({ scope: "all", event: "<event>" })) { ... }
295
+ ```
296
+
297
+ A stream yields one row at a time and never holds the table in memory. A row carries its
298
+ competition beside its own fields: `competition`, `event`, `year`, `tier`, `comp_no`, `title`,
299
+ `category`, `age`, `age_printed`, `gender`, `competitors`, `feis_level`, `level_printed`,
300
+ `date_printed`, `source`, `round`, and at a feis its `feis_id`, `feis_date_lo` and
301
+ `feis_date_hi`. Its own: `address`, `section`, `card`, `place`, `place_printed`, `tie`,
302
+ `relative_place`, `atts`, `withdrawn`, `qualifier`, `name_printed`, `name`, `school_printed`,
303
+ `school_loc`, `school_id`, `dancer_id`, `dancer_scope`, `yob`, `yob_printed`, `points_printed`,
304
+ `platform_dancer_id`, `primary_source`. Rows come in the release's own order, a competition's
305
+ rows together.
306
+
307
+ The scopes: `majors` reads the majors (tiers T1 to T3), `transcribed` the transcribed rows of
308
+ every tier, `platform` every row a results platform published, `all` every row.
309
+
310
+ AN ENTRY is one row per address, the row the card stands for: a card printed in several sections
311
+ (a recall order, the final, a single round's solo placing, a qualifying heat) keeps the final's
312
+ row, then the sectionless page's, the recall order's, the standings', the unplaced row, a heat's
313
+ and last a solo round's (`entryRank`), and two rows of one rank keep the later. `recall_place` is
314
+ the place the address's recall row carries.
315
+
316
+ ## Bulk reads
317
+
318
+ ```ts
319
+ await rel.dancers.records(); // every dancer: display, appearances, birth_lo, birth_hi,
320
+ // birth_source, birth_conflict, genders, scope
321
+ await rel.dancers.records({ ids: [1001] });
322
+ await rel.dancers.years({ ids: [1001], year: 2025 }); // region, region_source, nationals, geohash
323
+ await rel.feises.dates(); // every feis id with its first and last day
324
+ await rel.majors.tabulated({ min_true_round: 3 }); // the majors addresses marked to round 3 or later
325
+ ```
326
+
327
+ ## Teams and event-years
328
+
329
+ ```ts
330
+ const r = await rel.teams.results({ event: "<event>", year: 2024 });
331
+ r.results; // [{ address, competition, event, year, comp_no, title, category, hands, letter, label,
332
+ // school_printed, school_id, place, place_printed, tie, competitors, atts, ... }]
333
+ const t = await rel.teams.rosters({ event: "<event>", year: 2024 });
334
+ t.teams; // [{ team, kind, event, year, comp_no, title, team_index, seq, school_id, school_printed,
335
+ // members: [{ seq, name_printed, name, yob, dancer_id, dancer_scope }] }]
336
+ const j = await rel.teams.resultRosters({ event: "<event>", year: 2024 });
337
+ j.joins; // [{ team, result_address, join_kind, via_split, roster_index, result_letter, ... }]
338
+ const e = await rel.events.years({ event: "<event>" });
339
+ e.years; // [{ event, year, date_lo, date_hi, resolution, source, date_printed, place, place_printed }]
340
+ ```
341
+
342
+ A query names an event (case-blind), a year, both, or neither (every row). Everything comes from
343
+ ONE release: a roster member's `dancer_id` is the same release's id as the results', so a caller
344
+ never joins team records of one release to dancer ids of another. A roster is a sheet of a school's
345
+ teams (`kind: "rosterTeam"`) or a result card's own line-up (`lineup`). `join_kind` says how a
346
+ roster team met the results (`exact`, `card`, `branch`) or why it did not (`no-result`,
347
+ `no-school`, `no-roster`, `multi-team-unjoined`), and `result_address` is null where none joined.
348
+ An event-year's dates are a window (`date_lo`, `date_hi`) with how fine it is (`resolution`:
349
+ `day`, `month`, `calendar`) and what it is read from (`source`), and `place` is a place-tree node
350
+ where the release knows one. A field the source left empty is null. The rows are read once per
351
+ release into the `teams` and `events` indexes.
352
+
273
353
  ## Teachers and adjudicators
274
354
 
275
355
  ```ts
@@ -394,6 +474,15 @@ and the competitions still resolve.
394
474
  [--population girls|boys] [--rows]
395
475
  idq results [--release <spec>] [--dancer <id>] [--feis <id>] [--comp <c>] [--school <s>] [--year <y>] [--limit <n>]
396
476
  idq majors [--release <spec>] [--event <e>] [--year <y>] [--comp <c>] [--dancer <id>] [--rows]
477
+ idq stream [--release <spec>] --scope majors|transcribed|platform|all [--entries] [--event <e,...>]
478
+ [--year <y> | --year <from>..<to>] [--tier <t,...>] [--category <c,...>]
479
+ [--level <n,...>] [--dancer <id,...>] [--school <school_id>] [--primary]
480
+ idq records [--release <spec>] [--dancer <id,...>]
481
+ idq records --years [--release <spec>] [--dancer <id,...>] [--year <y>]
482
+ idq feis-dates [--release <spec>]
483
+ idq tabulated [--release <spec>] [--min-round <n>]
484
+ idq teams [--release <spec>] [--event <e>] [--year <y>] [--rosters | --joins]
485
+ idq events [--release <spec>] [--event <e>] [--year <y>]
397
486
  idq teacher [--release <spec>] <name|TD number>
398
487
  idq adjudicator [--release <spec>] <name|TD number>
399
488
  idq comp [--release <spec>] <feis> <code> [--year y] [--title t]
@@ -403,7 +492,7 @@ and the competitions still resolve.
403
492
  idq resolve dancer [<name>] [--school s] [--comp <feis>/<code> | --yob y | --band b --year y]
404
493
  idq resolve registrations
405
494
 
406
- `dancer` prints the results of the one dancer where the answer is unique (every candidate's with
495
+ `stream` prints one JSON line per row (or entry), as it reads them. `dancer` prints the results of the one dancer where the answer is unique (every candidate's with
407
496
  `--rows`). `--json` prints the call's answer as it is. `--cache` and `--repo` override the defaults.
408
497
 
409
498
  `resolve` speaks JSON lines: one answer per line out, and with no positional question the