@finbheara/archive-client 0.37.0 → 0.38.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
@@ -325,6 +325,8 @@ r.initials; // an initials-only name with a school: { open, heldByDanceUp, re
325
325
  r.unlinked; // rows printing a matched name that the release linked to no dancer
326
326
 
327
327
  await rel.dancers.search({ surname: "Quellan" }); // or { like: "a* quellan" }, or { name }
328
+ // at most `limit` (default 50, 0 for all);
329
+ // `truncated` counts the rest
328
330
  await rel.dancers.get(1001); // every print and school of one dancer
329
331
  ```
330
332
 
@@ -510,6 +512,9 @@ await rel.majors.competitions({ event: "<event>", year: 2023 });
510
512
  await rel.majors.results({ dancer_id: 1001 }); // a dancer's majors
511
513
  ```
512
514
 
515
+ A query keeps at most `limit` rows (default 500; `0` is no limit) and `truncated` says how many
516
+ more there were. Check it is `0` before reading the rows as the whole answer.
517
+
513
518
  A row carries the prints and the ids that stand for them: the address, the competition's title
514
519
  and age, the place, the name and school as printed with the dancer and school ids. The majors are
515
520
  read from `majors.sqlite`, fetched on first use.
@@ -975,9 +980,9 @@ is passed to the dancer resolver as asked (`rel.dancers`, above).
975
980
  idq dancer [--release <spec>] <name> | --surname <s> | --like <glob> | --id <dancer_id>
976
981
  [--order surname-first|given-first] [--school <print|id>]
977
982
  [--yob <y> | --band <band> [--year <y>] | --comp <competition>] [--as-of <date>]
978
- [--population girls|boys] [--oireachtas <region>[:<year>]] [--rows]
983
+ [--population girls|boys] [--oireachtas <region>[:<year>]] [--rows] [--limit <n>]
979
984
  idq results [--release <spec>] [--dancer <id>] [--feis <id>] [--comp <c>] [--school <s>] [--year <y>] [--limit <n>]
980
- idq majors [--release <spec>] [--event <e>] [--year <y>] [--comp <c>] [--dancer <id>] [--rows]
985
+ idq majors [--release <spec>] [--event <e>] [--year <y>] [--comp <c>] [--dancer <id>] [--rows] [--limit <n>]
981
986
  idq stream [--release <spec>] --scope majors|transcribed|platform|all [--entries] [--event <e,...>]
982
987
  [--year <y> | --year <from>..<to>] [--tier <t,...>] [--category <c,...>]
983
988
  [--level <n,...>] [--dancer <id,...>] [--school <school_id>] [--primary]
@@ -1012,9 +1017,20 @@ is passed to the dancer resolver as asked (`rel.dancers`, above).
1012
1017
  idq resolve dancer [<name>] [--school s] [--comp <feis>/<code> | --yob y | --band b --year y]
1013
1018
  [--oireachtas <region>[:<year>]]
1014
1019
  idq resolve registrations
1020
+ idq resolve teacher|adjudicator [<name|TD number>]
1015
1021
 
1016
1022
  `stream` (and `tabs --stream`) prints one JSON line per row (or entry, or cell), as it reads them. `dancer` prints the results of the one dancer where the answer is unique (every candidate's with
1017
- `--rows`). `--json` prints the call's answer as it is. `--cache` and `--repo` override the defaults.
1023
+ `--rows`), and `--id` every row of the one dancer. `--json` prints the call's answer as it is.
1024
+
1025
+ A LIMIT THAT CUTS AN ANSWER SAYS SO. `results`, `majors --comp|--dancer` (500 rows) and a
1026
+ `dancer` search (50 candidates) take `--limit <n>`, and `--limit 0` is no limit. Where the limit
1027
+ cut the answer, one line goes to stderr, in text and `--json` alike, and stdout is unchanged:
1028
+
1029
+ answered 500 of 979 rows: pass --limit 979 (or --limit 0 for all) for the rest
1030
+
1031
+ A `dancer` search prints the same line of its candidates, and each trajectory it reads (one per
1032
+ candidate, 500 rows each) that was cut prints `answered 500 of 979 rows of dancer <id>: pass --id
1033
+ <id> for all of them`. `--cache` and `--repo` override the defaults.
1018
1034
 
1019
1035
  `update` moves to the newest published release, as a package manager's `update` moves to the newest
1020
1036
  version: it fetches it (verified as every download is), builds every index it knows, and only then
@@ -1061,7 +1077,10 @@ only when the release is published: `teams`, `events`) answers from the pinned r
1061
1077
  `resolve` speaks JSON lines: one answer per line out, and with no positional question the
1062
1078
  questions are JSON lines on stdin, one per line (`{feis, code, year?, title?}`,
1063
1079
  `{name, school?, age?, population?, oireachtas?}`,
1064
- `{name, school?, codes, feis, year?, population?, oireachtas?}`). A line that is no JSON object,
1080
+ `{name, school?, codes, feis, year?, population?, oireachtas?}`, and for `teacher` and
1081
+ `adjudicator` `{name}` or the TD number under the key `StaffPerson` carries it in, the number read
1082
+ first where a line has both, each answered by `rel.staff.teacher` / `rel.staff.adjudicator`, one
1083
+ `StaffAnswer` a line). A line that is no JSON object,
1065
1084
  or no question of its kind, answers `{tag, line, error}` and the other lines still answer. The
1066
1085
  exit is non-zero where any line erred. A dancer's age may be given as a comp
1067
1086
  (`{"comp": "<feis>/<code>"}`, or `--comp` on the command line): `rel.registrations.dancer` reads
@@ -1502,7 +1502,7 @@ function queryResults(rel, db, q) {
1502
1502
  where.push("c.year = ?");
1503
1503
  args.push(q.year);
1504
1504
  }
1505
- const limit = q.limit ?? 500;
1505
+ const asked = q.limit ?? 500;
1506
1506
  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
1507
1507
  WHERE ${where.join(" AND ")}
1508
1508
  ORDER BY c.year, c.event, r.competition, r.place IS NULL, r.place, r.address`).all(...args);
@@ -1510,11 +1510,11 @@ function queryResults(rel, db, q) {
1510
1510
  tag: rel.tag,
1511
1511
  db,
1512
1512
  asked: q,
1513
- rows: all.slice(0, limit).map((r) => ({
1513
+ rows: (asked === 0 ? all : all.slice(0, asked)).map((r) => ({
1514
1514
  ...r,
1515
1515
  dancer_scope: r.dancer_id === null ? null : r.dancer_id >= FEIS_LOCAL_ID_FLOOR2 ? "per-release" : "stable"
1516
1516
  })),
1517
- truncated: Math.max(0, all.length - limit)
1517
+ truncated: asked === 0 ? 0 : Math.max(0, all.length - asked)
1518
1518
  };
1519
1519
  }
1520
1520
 
@@ -2237,6 +2237,7 @@ class DancerResolver2 {
2237
2237
  asked: q,
2238
2238
  arm: "none",
2239
2239
  candidates: [],
2240
+ truncated: 0,
2240
2241
  excluded: [],
2241
2242
  unlinked: [],
2242
2243
  refused: asked.printsNoName() ? "the print names no person" : "the print reads as no person (a bare word is a surname: search it)"
@@ -2348,7 +2349,13 @@ class DancerResolver2 {
2348
2349
  return this.capped(a, q.limit);
2349
2350
  }
2350
2351
  capped(a, limit = 50) {
2351
- return { ...a, candidates: a.candidates.slice(0, limit) };
2352
+ if (limit === 0 || a.candidates.length <= limit)
2353
+ return a;
2354
+ return {
2355
+ ...a,
2356
+ candidates: a.candidates.slice(0, limit),
2357
+ truncated: a.candidates.length - limit
2358
+ };
2352
2359
  }
2353
2360
  async get(dancerId) {
2354
2361
  const db = await this.rel.indexDb("dancers");
@@ -2606,6 +2613,7 @@ class DancerResolver2 {
2606
2613
  asked: q,
2607
2614
  arm: kept.length === 0 ? "none" : kept.length === 1 ? "unique" : "ambiguous",
2608
2615
  candidates: kept,
2616
+ truncated: 0,
2609
2617
  excluded,
2610
2618
  ...preferred !== undefined ? { preferred } : {},
2611
2619
  unlinked: [...unlinked].map(([print, rows]) => ({ print, rows })).sort((a, b) => b.rows - a.rows || (a.print < b.print ? -1 : 1)),
package/dist/cli.js CHANGED
@@ -21,7 +21,7 @@ import {
21
21
  latestCheck2,
22
22
  within,
23
23
  staleWarning2
24
- } from "./chunks/index-hfpcedbh.js";
24
+ } from "./chunks/index-z9zxdmw5.js";
25
25
  import"./chunks/index-hghdy980.js";
26
26
 
27
27
  var USAGE_HEADER = "usage: idq <verb> [--cache <dir>] [--repo <owner/name>] [--json] [--live]";
@@ -199,20 +199,23 @@ var VERBS = [
199
199
  "--comp",
200
200
  "--as-of",
201
201
  "--population",
202
- "--oireachtas"
202
+ "--oireachtas",
203
+ "--limit"
203
204
  ],
204
205
  bool: ["--rows"],
205
206
  usage: [
206
207
  " dancer [--release <spec>] <name> | --surname <s> | --like <glob> | --id <dancer_id>",
207
208
  " [--order surname-first|given-first] [--school <print|id>]",
208
209
  " [--yob <y> | --band <U10> [--year <y>] | --comp <competition>] [--as-of <date>]",
209
- " [--population girls|boys] [--oireachtas <region>[:<year>]] [--rows]",
210
+ " [--population girls|boys] [--oireachtas <region>[:<year>]] [--rows] [--limit <n>]",
210
211
  " the dancers a name reaches, each with its evidence",
211
212
  " (name level, age, school, population, region) and the arm;",
212
213
  " --oireachtas is the regional the roster is for, its region in",
213
214
  " the release's spelling (SRO, MAO), its year the --as-of year",
214
215
  " where none is given; the results of",
215
- " the one dancer where one answers (or --rows for each)"
216
+ " the one dancer where one answers (or --rows for each, 500",
217
+ " rows a dancer; --id reads every row); at most --limit",
218
+ " candidates (default 50, 0 for all)"
216
219
  ]
217
220
  },
218
221
  {
@@ -222,17 +225,20 @@ var VERBS = [
222
225
  usage: [
223
226
  " results [--release <spec>] [--dancer <id>] [--feis <id>] [--comp <competition>]",
224
227
  " [--school <print|id>] [--year <y>] [--limit <n>]",
225
- " the published result rows, prints and ids"
228
+ " the published result rows, prints and ids; at most",
229
+ " --limit rows (default 500, 0 for all)"
226
230
  ]
227
231
  },
228
232
  {
229
233
  verb: "majors",
230
- value: ["--release", "--event", "--year", "--comp", "--dancer"],
234
+ value: ["--release", "--event", "--year", "--comp", "--dancer", "--limit"],
231
235
  bool: [],
232
236
  usage: [
233
237
  " majors [--release <spec>] [--event <e>] [--year <y>] [--comp <competition>] [--dancer <id>]",
238
+ " [--limit <n>]",
234
239
  " the majors: every event and its years; an event's",
235
- " competitions; a competition's, an event's or a dancer's rows"
240
+ " competitions; a competition's, an event's or a dancer's rows",
241
+ " (at most --limit, default 500, 0 for all)"
236
242
  ]
237
243
  },
238
244
  {
@@ -491,11 +497,15 @@ var VERBS = [
491
497
  " [--order <o>] [--as-of <date>] [--population girls|boys]",
492
498
  " [--oireachtas <region>[:<year>]]",
493
499
  " resolve registrations",
500
+ " resolve teacher|adjudicator [<name|TD number>]",
494
501
  " JSONL out, one answer per line; with no positional the",
495
502
  " questions are JSONL on stdin, one per line (a comp:",
496
503
  " {feis, code, year?, title?}, a dancer: {name, school?, age?,",
497
504
  " population?, oireachtas?}, a registration: {name, school?,",
498
- " codes[], feis, year?, population?, oireachtas?})"
505
+ " codes[], feis, year?, population?, oireachtas?}, a teacher or",
506
+ " adjudicator: {clrg} or {name}, the TD number first)",
507
+ " A line that is no question answers {tag, line, error}, and",
508
+ " the exit is 1 where any line erred"
499
509
  ]
500
510
  }
501
511
  ];
@@ -600,6 +610,21 @@ function printResults(a, say) {
600
610
  say(" * a feis-local dancer id: valid in this release only");
601
611
  say(`${a.rows.length} row(s) from ${a.db} in ${a.tag}${a.truncated > 0 ? `, ${a.truncated} more past the limit` : ""}`);
602
612
  }
613
+ function cutNotice(shown, more, what = "rows") {
614
+ if (more <= 0)
615
+ return null;
616
+ const total = shown + more;
617
+ return `answered ${shown} of ${total} ${what}: pass --limit ${total} (or --limit 0 for all) for the rest`;
618
+ }
619
+ function limitOf(p) {
620
+ const v = p.flags.get("--limit");
621
+ if (v === undefined)
622
+ return {};
623
+ const n = Number(v);
624
+ if (!Number.isInteger(n) || n < 0)
625
+ throw new Error(`--limit takes a count (0 for no limit), not "${v}"`);
626
+ return { limit: n };
627
+ }
603
628
  function printStaff(a, say) {
604
629
  say(`${a.arm} ${a.role} "${a.asked}" in ${a.tag}${a.refused !== undefined ? ` (refused: ${a.refused})` : ""}`);
605
630
  for (const p of a.people) {
@@ -661,6 +686,14 @@ function oireachtasFlag(v) {
661
686
  };
662
687
  }
663
688
  var checkDancer = (q) => typeof q.name !== "string" || q.name.trim() === "" ? "a dancer question needs name" : null;
689
+ function staffAsked(q) {
690
+ if (q.clrg !== undefined && q.clrg !== null) {
691
+ const n = typeof q.clrg === "string" && q.clrg.trim() !== "" ? Number(q.clrg) : q.clrg;
692
+ return typeof n === "number" && Number.isInteger(n) && n > 0 ? String(n) : null;
693
+ }
694
+ return typeof q.name === "string" && q.name.trim() !== "" ? q.name.trim() : null;
695
+ }
696
+ var checkStaff = (q) => q.clrg !== undefined && q.clrg !== null && staffAsked(q) === null ? "a staff question's clrg is a TD number" : staffAsked(q) === null ? "a staff question needs name or clrg" : null;
664
697
  var checkRegistration = (r) => typeof r.name !== "string" || r.name.trim() === "" ? "a registration row needs name" : typeof r.feis !== "string" || r.feis.trim() === "" ? "a registration row needs feis" : !Array.isArray(r.codes) ? "a registration row needs codes[]" : null;
665
698
  async function resolveVerb(rel, what, args, p, say, stdin) {
666
699
  const year = p.flags.has("--year") ? Number(p.flags.get("--year")) : undefined;
@@ -743,8 +776,21 @@ async function resolveVerb(rel, what, args, p, say, stdin) {
743
776
  await each(lines, async () => answers[k++]);
744
777
  return errors > 0 ? 1 : 0;
745
778
  }
779
+ case "teacher":
780
+ case "adjudicator": {
781
+ const qs = args.length > 0 ? [{ line: 0, value: { name: args.join(" ") } }] : jsonLines(await stdin(), checkStaff);
782
+ let none = 0;
783
+ await each(qs, async (q) => {
784
+ const asked = staffAsked(q);
785
+ const a = what === "teacher" ? await rel.staff.teacher(asked) : await rel.staff.adjudicator(asked);
786
+ if (a.arm === "none")
787
+ none++;
788
+ return a;
789
+ });
790
+ return errors > 0 || args.length > 0 && none === 1 ? 1 : 0;
791
+ }
746
792
  default:
747
- throw new Error("resolve comp|dancer|registrations");
793
+ throw new Error("resolve comp|dancer|registrations|teacher|adjudicator");
748
794
  }
749
795
  }
750
796
  var SCOPES = ["majors", "transcribed", "platform", "all"];
@@ -1130,7 +1176,7 @@ async function main(argv, io = {}) {
1130
1176
  const id = p.flags.get("--id");
1131
1177
  if (id !== undefined) {
1132
1178
  const d = await rel.dancers.get(Number(id));
1133
- const rows = d === null ? null : await rel.results.query({ dancer_id: d.dancer_id });
1179
+ const rows = d === null ? null : await rel.results.query({ dancer_id: d.dancer_id, limit: 0 });
1134
1180
  out({ dancer: d, results: rows }, () => {
1135
1181
  if (d === null) {
1136
1182
  say(`no dancer ${id} in ${rel.tag}`);
@@ -1158,7 +1204,7 @@ async function main(argv, io = {}) {
1158
1204
  ...p.flags.has("--as-of") ? { asOf: p.flags.get("--as-of") } : {},
1159
1205
  ...p.flags.has("--population") ? { population: p.flags.get("--population") } : {},
1160
1206
  ...oireachtasFlag(p.flags.get("--oireachtas")),
1161
- ...p.flags.has("--limit") ? { limit: Number(p.flags.get("--limit")) } : {}
1207
+ ...limitOf(p)
1162
1208
  };
1163
1209
  const surname = p.flags.get("--surname");
1164
1210
  const like = p.flags.get("--like");
@@ -1178,6 +1224,12 @@ async function main(argv, io = {}) {
1178
1224
  printResults(t, say);
1179
1225
  }
1180
1226
  });
1227
+ const cut = cutNotice(a.candidates.length, a.truncated, "candidates");
1228
+ if (cut !== null)
1229
+ log(cut);
1230
+ for (const t of trajectories)
1231
+ if (t.truncated > 0)
1232
+ log(`answered ${t.rows.length} of ${t.rows.length + t.truncated} rows of dancer ${t.asked.dancer_id}: pass --id ${t.asked.dancer_id} for all of them`);
1181
1233
  return a.candidates.length === 0 ? 1 : 0;
1182
1234
  } finally {
1183
1235
  rel.close();
@@ -1192,10 +1244,13 @@ async function main(argv, io = {}) {
1192
1244
  ...p.flags.has("--comp") ? { competition: p.flags.get("--comp") } : {},
1193
1245
  ...p.flags.has("--school") ? { school_id: await schoolIdOf(rel, p.flags.get("--school")) } : {},
1194
1246
  ...p.flags.has("--year") ? { year: Number(p.flags.get("--year")) } : {},
1195
- ...p.flags.has("--limit") ? { limit: Number(p.flags.get("--limit")) } : {}
1247
+ ...limitOf(p)
1196
1248
  };
1197
1249
  const a = await rel.results.query(q);
1198
1250
  out(a, () => printResults(a, say));
1251
+ const cut = cutNotice(a.rows.length, a.truncated);
1252
+ if (cut !== null)
1253
+ log(cut);
1199
1254
  return a.rows.length === 0 ? 1 : 0;
1200
1255
  } finally {
1201
1256
  rel.close();
@@ -1214,9 +1269,12 @@ async function main(argv, io = {}) {
1214
1269
  ...dancer !== undefined ? { dancer_id: Number(dancer) } : {},
1215
1270
  ...event !== undefined ? { feis: event } : {},
1216
1271
  ...year !== undefined ? { year: Number(year) } : {},
1217
- ...p.flags.has("--limit") ? { limit: Number(p.flags.get("--limit")) } : {}
1272
+ ...limitOf(p)
1218
1273
  });
1219
1274
  out(a, () => printResults(a, say));
1275
+ const cut = cutNotice(a.rows.length, a.truncated);
1276
+ if (cut !== null)
1277
+ log(cut);
1220
1278
  return a.rows.length === 0 ? 1 : 0;
1221
1279
  }
1222
1280
  if (event !== undefined) {
@@ -1742,6 +1800,7 @@ export {
1742
1800
  USAGE_FOOTER,
1743
1801
  USAGE_HEADER,
1744
1802
  VERBS,
1803
+ cutNotice,
1745
1804
  jsonLines,
1746
1805
  main,
1747
1806
  parseArgs,
package/dist/index.js CHANGED
@@ -80,7 +80,7 @@ import {
80
80
  readLatestCheck2,
81
81
  latestCheck2,
82
82
  staleWarning2
83
- } from "./chunks/index-hfpcedbh.js";
83
+ } from "./chunks/index-z9zxdmw5.js";
84
84
  import {
85
85
  cacheRoot2,
86
86
  repoOf2
@@ -12,6 +12,7 @@ export interface Parsed {
12
12
  bools: Set<string>;
13
13
  }
14
14
  export declare function parseArgs(argv: readonly string[]): Parsed;
15
+ export declare function cutNotice(shown: number, more: number, what?: string): string | null;
15
16
  type Line<T> = {
16
17
  line: number;
17
18
  value: T;
@@ -106,6 +106,7 @@ export interface DancerAnswer {
106
106
  asked: DancerQuery;
107
107
  arm: "unique" | "ambiguous" | "none";
108
108
  candidates: DancerCandidate[];
109
+ truncated: number;
109
110
  excluded: ExcludedCandidate[];
110
111
  preferred?: {
111
112
  dancer_id: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@finbheara/archive-client",
3
- "version": "0.37.0",
3
+ "version": "0.38.0",
4
4
  "description": "Open a versioned release of an Irish dance results archive: download, verify, decompress and cache it by tag, keep the cache, and resolve feises and schools against it",
5
5
  "keywords": ["irish-dance", "results", "release", "cache", "sqlite"],
6
6
  "license": "MIT",