@heroiclands/package-build 23.7.0 → 23.7.1

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.
@@ -33,6 +33,13 @@
33
33
  * `elements` and `roots` — one row per entry, the list keys always lists;
34
34
  * - `scope` — one row per value, with the `kind` of `data.scope` it is under;
35
35
  * - `clusters` — one row per language stating `data.sounds.clusters`;
36
+ * - `cluster_groups` and `mutations` — one row per entry of
37
+ * `data.sounds.clusters.groups` and `data.sounds.mutations`;
38
+ * - `older` — one row per `data.older` entry;
39
+ * - `negation` — one row per language stating `data.negation`;
40
+ * - `name_shapes`, `name_edges`, `name_draws` and `held_from` — one row per
41
+ * entry of the lists of `data.naming`, and `near_names` one per worked
42
+ * near name, with the language's `min_syllables`;
36
43
  * - `cognates` — one row per form of each set, with the set's `gloss`.
37
44
  *
38
45
  * @module
@@ -40,7 +47,9 @@
40
47
 
41
48
  import { isLanguageRecord, noteAddressOf } from "./word-rows.mjs";
42
49
  import {
50
+ ANY_NAME,
43
51
  CALLING_CLOSING_KEYS,
52
+ CLUSTER_GROUP_KEYS,
44
53
  EDGE_KEYS,
45
54
  ELEMENT_KEYS,
46
55
  FINAL_KEYS,
@@ -48,6 +57,8 @@ import {
48
57
  JOIN_KEYS,
49
58
  LETTER_KEYS,
50
59
  MARK_KEYS,
60
+ MUTATION_KEYS,
61
+ OLDER_KEYS,
51
62
  READ_PAST_KEYS,
52
63
  REGISTER_KEYS,
53
64
  RETIRED_KEYS,
@@ -86,6 +97,38 @@ export const LETTER_COLUMNS = Object.freeze([...IDENTITY, ...LETTER_KEYS]);
86
97
  export const EDGE_COLUMNS = Object.freeze([...IDENTITY, ...EDGE_KEYS]);
87
98
  /** Every column of the `clusters` relation, in order. */
88
99
  export const CLUSTER_COLUMNS = Object.freeze(["language", "max"]);
100
+ /** Every column of the `cluster_groups` relation, in order. */
101
+ export const CLUSTER_GROUP_COLUMNS = Object.freeze([...IDENTITY, ...CLUSTER_GROUP_KEYS]);
102
+ /** Every column of the `mutations` relation, in order. */
103
+ export const MUTATION_COLUMNS = Object.freeze([...IDENTITY, ...MUTATION_KEYS]);
104
+ /** Every column of the `older` relation, in order. */
105
+ export const OLDER_COLUMNS = Object.freeze([...IDENTITY, ...OLDER_KEYS]);
106
+ /** Every column of the `name_shapes` relation, in order. */
107
+ export const NAME_SHAPE_COLUMNS = Object.freeze([
108
+ ...IDENTITY,
109
+ "of",
110
+ "syllables_min",
111
+ "syllables_max",
112
+ "per_vowel_min",
113
+ "per_vowel_max",
114
+ ]);
115
+ /** Every column of the `name_edges` relation, in order. */
116
+ export const NAME_EDGE_COLUMNS = Object.freeze([...IDENTITY, "edge", "sounds", "vowel", "of"]);
117
+ /** Every column of the `name_draws` relation, in order. */
118
+ export const NAME_DRAW_COLUMNS = Object.freeze([...IDENTITY, "kind", "elements"]);
119
+ /** Every column of the `held_from` relation, in order. */
120
+ export const HELD_FROM_COLUMNS = Object.freeze([
121
+ ...IDENTITY,
122
+ "source",
123
+ "takes",
124
+ "clip",
125
+ "genitive",
126
+ "elements",
127
+ ]);
128
+ /** Every column of the `near_names` relation, in order. */
129
+ export const NEAR_NAME_COLUMNS = Object.freeze([...IDENTITY, "near", "given", "min_syllables"]);
130
+ /** Every column of the `negation` relation, in order: one row per language. */
131
+ export const NEGATION_COLUMNS = Object.freeze(["language", "particle", "mutation"]);
89
132
  /** Every column of the `stress` relation, in order. */
90
133
  export const STRESS_COLUMNS = Object.freeze(["language", "stress"]);
91
134
  /** Every column of the `finals` relation, in order. */
@@ -106,6 +149,7 @@ export const SYLLABLE_COLUMNS = Object.freeze([
106
149
  "harmony_front",
107
150
  "harmony_neutral",
108
151
  "harmony_neutralAs",
152
+ "harmony_partners",
109
153
  ]);
110
154
  /** Every column of the `joining` relation, in order. */
111
155
  export const JOINING_COLUMNS = Object.freeze([...IDENTITY, ...JOINING_KEYS]);
@@ -132,6 +176,7 @@ export const SOUND_CHANGE_COLUMNS = Object.freeze([
132
176
  "name",
133
177
  "from_language",
134
178
  "to_language",
179
+ "takes",
135
180
  "step_position",
136
181
  ...SOUND_CHANGE_STEP_KEYS,
137
182
  ]);
@@ -174,6 +219,21 @@ export const LANGUAGE_COLUMN_TYPES = Object.freeze({
174
219
  letters: { position: "BIGINT", letters: LIST, tongue: LIST },
175
220
  edges: { position: "BIGINT", sounds: LIST },
176
221
  clusters: { max: "BIGINT" },
222
+ cluster_groups: { position: "BIGINT", clusters: LIST },
223
+ mutations: { position: "BIGINT" },
224
+ older: { position: "BIGINT" },
225
+ negation: {},
226
+ name_shapes: {
227
+ position: "BIGINT",
228
+ syllables_min: "BIGINT",
229
+ syllables_max: "BIGINT",
230
+ per_vowel_min: "DOUBLE",
231
+ per_vowel_max: "DOUBLE",
232
+ },
233
+ name_edges: { position: "BIGINT", sounds: LIST, vowel: "BOOLEAN" },
234
+ name_draws: { position: "BIGINT", elements: LIST },
235
+ held_from: { position: "BIGINT", genitive: LIST, elements: LIST },
236
+ near_names: { position: "BIGINT", min_syllables: "BIGINT" },
177
237
  stress: {},
178
238
  finals: { position: "BIGINT" },
179
239
  syllables: {
@@ -188,6 +248,7 @@ export const LANGUAGE_COLUMN_TYPES = Object.freeze({
188
248
  harmony_back: LIST,
189
249
  harmony_front: LIST,
190
250
  harmony_neutral: LIST,
251
+ harmony_partners: "STRUCT(vowel VARCHAR, partner VARCHAR)[]",
191
252
  },
192
253
  joining: { position: "BIGINT", first: LIST, second: LIST },
193
254
  joins: { position: "BIGINT", letters: LIST },
@@ -470,6 +531,159 @@ export function clusterRows(records) {
470
531
  return rows;
471
532
  }
472
533
 
534
+ /**
535
+ * The `cluster_groups` rows: one per `data.sounds.clusters.groups` entry,
536
+ * `clusters` a list.
537
+ *
538
+ * @param {Iterable<Record<string, any>>} records - Index records.
539
+ * @returns {object[]}
540
+ */
541
+ export function clusterGroupRows(records) {
542
+ return listRows(records, (data) => soundsOf(data).clusters?.groups, CLUSTER_GROUP_KEYS, {
543
+ lists: ["clusters"],
544
+ });
545
+ }
546
+
547
+ /**
548
+ * The `mutations` rows: one per `data.sounds.mutations` entry.
549
+ *
550
+ * @param {Iterable<Record<string, any>>} records - Index records.
551
+ * @returns {object[]}
552
+ */
553
+ export function mutationRows(records) {
554
+ return listRows(records, (data) => soundsOf(data).mutations, MUTATION_KEYS);
555
+ }
556
+
557
+ /**
558
+ * The `older` rows: one per `data.older` entry.
559
+ *
560
+ * @param {Iterable<Record<string, any>>} records - Index records.
561
+ * @returns {object[]}
562
+ */
563
+ export function olderRows(records) {
564
+ return listRows(records, (data) => data.older, OLDER_KEYS);
565
+ }
566
+
567
+ /**
568
+ * The `negation` rows: one per language stating `data.negation`.
569
+ *
570
+ * @param {Iterable<Record<string, any>>} records - Index records.
571
+ * @returns {object[]}
572
+ */
573
+ export function negationRows(records) {
574
+ const rows = [];
575
+ for (const [language, record] of languagesOf(records)) {
576
+ const negation = record.data?.negation;
577
+ if (isMap(negation))
578
+ rows.push({
579
+ language,
580
+ particle: negation.particle ?? null,
581
+ mutation: negation.mutation ?? null,
582
+ });
583
+ }
584
+ return rows;
585
+ }
586
+
587
+ /** A language's `data.naming`, or an empty map. */
588
+ const namingOf = (data) => (isMap(data.naming) ? data.naming : {});
589
+
590
+ /** A range's bound, or `null`. */
591
+ const bound = (range, key) => (isMap(range) && typeof range[key] === "number" ? range[key] : null);
592
+
593
+ /**
594
+ * The `name_shapes` rows: one per `data.naming.shapes` entry, each range as
595
+ * its two bounds.
596
+ *
597
+ * @param {Iterable<Record<string, any>>} records - Index records.
598
+ * @returns {object[]}
599
+ */
600
+ export function nameShapeRows(records) {
601
+ const rows = [];
602
+ for (const [language, record] of languagesOf(records)) {
603
+ const shapes = namingOf(isMap(record.data) ? record.data : {}).shapes;
604
+ if (!Array.isArray(shapes)) continue;
605
+ shapes.forEach((shape, position) => {
606
+ if (!isMap(shape)) return;
607
+ rows.push({
608
+ language,
609
+ position,
610
+ of: shape.of ?? null,
611
+ syllables_min: bound(shape.syllables, "min"),
612
+ syllables_max: bound(shape.syllables, "max"),
613
+ per_vowel_min: bound(shape.perVowel, "min"),
614
+ per_vowel_max: bound(shape.perVowel, "max"),
615
+ });
616
+ });
617
+ }
618
+ return rows;
619
+ }
620
+
621
+ /**
622
+ * The `name_edges` rows: one per `data.naming.edges` entry, `sounds` a list,
623
+ * `vowel` `false` and `of` `name` where unstated.
624
+ *
625
+ * @param {Iterable<Record<string, any>>} records - Index records.
626
+ * @returns {object[]}
627
+ */
628
+ export function nameEdgeRows(records) {
629
+ return listRows(records, (data) => namingOf(data).edges, ["edge", "sounds", "vowel", "of"], {
630
+ lists: ["sounds"],
631
+ }).map((row) => ({ ...row, vowel: row.vowel === true, of: row.of ?? ANY_NAME }));
632
+ }
633
+
634
+ /**
635
+ * The `name_draws` rows: one per `data.naming.draws` entry.
636
+ *
637
+ * @param {Iterable<Record<string, any>>} records - Index records.
638
+ * @returns {object[]}
639
+ */
640
+ export function nameDrawRows(records) {
641
+ return listRows(records, (data) => namingOf(data).draws, ["kind", "elements"], {
642
+ lists: ["elements"],
643
+ });
644
+ }
645
+
646
+ /**
647
+ * The `held_from` rows: one per `data.naming.heldFrom` entry.
648
+ *
649
+ * @param {Iterable<Record<string, any>>} records - Index records.
650
+ * @returns {object[]}
651
+ */
652
+ export function heldFromRows(records) {
653
+ return listRows(
654
+ records,
655
+ (data) => namingOf(data).heldFrom,
656
+ ["source", "takes", "clip", "genitive", "elements"],
657
+ { lists: ["genitive", "elements"] },
658
+ );
659
+ }
660
+
661
+ /**
662
+ * The `near_names` rows: one per worked example of `data.naming.nearName`,
663
+ * each with the language's `min_syllables`.
664
+ *
665
+ * @param {Iterable<Record<string, any>>} records - Index records.
666
+ * @returns {object[]}
667
+ */
668
+ export function nearNameRows(records) {
669
+ const rows = [];
670
+ for (const [language, record] of languagesOf(records)) {
671
+ const near = namingOf(isMap(record.data) ? record.data : {}).nearName;
672
+ if (!isMap(near) || !Array.isArray(near.examples)) continue;
673
+ near.examples.forEach((example, position) => {
674
+ if (!isMap(example)) return;
675
+ rows.push({
676
+ language,
677
+ position,
678
+ near: example.near ?? null,
679
+ given: example.given ?? null,
680
+ min_syllables: near.minSyllables ?? null,
681
+ });
682
+ });
683
+ }
684
+ return rows;
685
+ }
686
+
473
687
  /**
474
688
  * The `read_past` rows: one per `data.sounds.readPast` entry.
475
689
  *
@@ -482,8 +696,8 @@ export function readPastRows(records) {
482
696
 
483
697
  /**
484
698
  * The `sound_changes` rows: one per step of each `data.soundChanges` set, with
485
- * the set's `position`, `name`, `from_language` and `to_language`, and the
486
- * step's `step_position` within it.
699
+ * the set's `position`, `name`, `from_language`, `to_language` and `takes`,
700
+ * and the step's `step_position` within it.
487
701
  *
488
702
  * @param {Iterable<Record<string, any>>} records - Index records.
489
703
  * @returns {object[]}
@@ -503,6 +717,7 @@ export function soundChangeRows(records) {
503
717
  name: set.name ?? null,
504
718
  from_language: set.from ?? null,
505
719
  to_language: set.to ?? null,
720
+ takes: set.takes ?? null,
506
721
  step_position: stepPosition,
507
722
  };
508
723
  for (const key of SOUND_CHANGE_STEP_KEYS) row[key] = step[key] ?? null;
@@ -592,7 +807,8 @@ export function finalRows(records) {
592
807
  /**
593
808
  * The `syllables` rows: one per language stating `data.sounds.syllables`, a
594
809
  * list rule always a list (`any` a list of one), the harmony's sets each a
595
- * column of its own.
810
+ * column of its own, its partners a list of `{ vowel, partner }` in the order
811
+ * stated.
596
812
  *
597
813
  * @param {Iterable<Record<string, any>>} records - Index records.
598
814
  * @returns {object[]}
@@ -618,6 +834,13 @@ export function syllableRows(records) {
618
834
  harmony_front: asList(harmony.front),
619
835
  harmony_neutral: asList(harmony.neutral),
620
836
  harmony_neutralAs: harmony.neutralAs ?? null,
837
+ harmony_partners:
838
+ isMap(harmony.partners) && Object.keys(harmony.partners).length ?
839
+ Object.entries(harmony.partners).map(([vowel, partner]) => ({
840
+ vowel,
841
+ partner: partner == null ? null : String(partner),
842
+ }))
843
+ : null,
621
844
  });
622
845
  }
623
846
  return rows;
@@ -744,6 +967,8 @@ export const LANGUAGE_RELATIONS = Object.freeze([
744
967
  ["letters", letterRows, LETTER_COLUMNS],
745
968
  ["edges", edgeRows, EDGE_COLUMNS],
746
969
  ["clusters", clusterRows, CLUSTER_COLUMNS],
970
+ ["cluster_groups", clusterGroupRows, CLUSTER_GROUP_COLUMNS],
971
+ ["mutations", mutationRows, MUTATION_COLUMNS],
747
972
  ["stress", stressRows, STRESS_COLUMNS],
748
973
  ["finals", finalRows, FINAL_COLUMNS],
749
974
  ["syllables", syllableRows, SYLLABLE_COLUMNS],
@@ -758,4 +983,11 @@ export const LANGUAGE_RELATIONS = Object.freeze([
758
983
  ["roots", rootRows, ROOT_COLUMNS],
759
984
  ["cognates", cognateRows, COGNATE_COLUMNS],
760
985
  ["calling_names", callingNameRows, CALLING_NAME_COLUMNS],
986
+ ["older", olderRows, OLDER_COLUMNS],
987
+ ["negation", negationRows, NEGATION_COLUMNS],
988
+ ["name_shapes", nameShapeRows, NAME_SHAPE_COLUMNS],
989
+ ["name_edges", nameEdgeRows, NAME_EDGE_COLUMNS],
990
+ ["name_draws", nameDrawRows, NAME_DRAW_COLUMNS],
991
+ ["held_from", heldFromRows, HELD_FROM_COLUMNS],
992
+ ["near_names", nearNameRows, NEAR_NAME_COLUMNS],
761
993
  ]);