@mailwoman/geographic-model 0.0.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.
Files changed (51) hide show
  1. package/README.md +155 -0
  2. package/artifact.ts +198 -0
  3. package/compile.ts +350 -0
  4. package/data/geographic-model.json +172 -0
  5. package/data/model/concepts.json +114 -0
  6. package/data/model/mappings.json +18 -0
  7. package/data/model/model.json +3 -0
  8. package/data/model/relations.json +14 -0
  9. package/index.ts +51 -0
  10. package/load.ts +396 -0
  11. package/lookup.ts +129 -0
  12. package/out/artifact.d.ts +106 -0
  13. package/out/artifact.d.ts.map +1 -0
  14. package/out/artifact.js +135 -0
  15. package/out/artifact.js.map +1 -0
  16. package/out/compile.d.ts +84 -0
  17. package/out/compile.d.ts.map +1 -0
  18. package/out/compile.js +259 -0
  19. package/out/compile.js.map +1 -0
  20. package/out/index.d.ts +51 -0
  21. package/out/index.d.ts.map +1 -0
  22. package/out/index.js +51 -0
  23. package/out/index.js.map +1 -0
  24. package/out/load.d.ts +122 -0
  25. package/out/load.d.ts.map +1 -0
  26. package/out/load.js +269 -0
  27. package/out/load.js.map +1 -0
  28. package/out/lookup.d.ts +64 -0
  29. package/out/lookup.d.ts.map +1 -0
  30. package/out/lookup.js +68 -0
  31. package/out/lookup.js.map +1 -0
  32. package/out/schema.d.ts +366 -0
  33. package/out/schema.d.ts.map +1 -0
  34. package/out/schema.js +166 -0
  35. package/out/schema.js.map +1 -0
  36. package/out/scripts/build-artifact.d.ts +51 -0
  37. package/out/scripts/build-artifact.d.ts.map +1 -0
  38. package/out/scripts/build-artifact.js +78 -0
  39. package/out/scripts/build-artifact.js.map +1 -0
  40. package/out/validate.d.ts +67 -0
  41. package/out/validate.d.ts.map +1 -0
  42. package/out/validate.js +465 -0
  43. package/out/validate.js.map +1 -0
  44. package/out/validation-issues.d.ts +84 -0
  45. package/out/validation-issues.d.ts.map +1 -0
  46. package/out/validation-issues.js +190 -0
  47. package/out/validation-issues.js.map +1 -0
  48. package/package.json +120 -0
  49. package/schema.ts +399 -0
  50. package/validate.ts +845 -0
  51. package/validation-issues.ts +305 -0
@@ -0,0 +1,366 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license AGPL-3.0
4
+ * @author Teffen Ellis, et al.
5
+ *
6
+ * The authored-record schema for `@mailwoman/geographic-model`: the stable identifiers, the closed
7
+ * vocabularies, and the record shapes for concepts, relations, external-vocabulary mappings, source
8
+ * observations, and derived facts.
9
+ *
10
+ * Three properties hold by construction, and they are why the file reads the way it does.
11
+ *
12
+ * **No numeric field exists anywhere in this schema** — not a strength, not a confidence, not a
13
+ * count. {@link Modality} is an ordinal vocabulary of WORDS and this module exports no order over
14
+ * it, because a number attached to an authored relationship is a ranking weight whatever it is
15
+ * called, and ranking belongs to `@mailwoman/resolver` and `@mailwoman/neural`.
16
+ *
17
+ * **An authored assertion, a source observation, and a derived fact are three different types.** A
18
+ * {@link RelationAssertion} is authored by a curator and lives on the concept it is about; a
19
+ * {@link SourceObservationRecord} records what a named external source states and never enters the
20
+ * concept table; a {@link DerivedFactRecord} names the procedure that produced it and every input
21
+ * that procedure read. Their identifiers are separately branded, so one is not assignable where
22
+ * another is expected.
23
+ *
24
+ * **Every record carries provenance, and a derived fact carries it structurally.** A derived fact
25
+ * has no {@link SourceProvenance} of its own: its `derivation` plus its resolved `inputs` ARE its
26
+ * provenance, and each input carries source provenance in turn.
27
+ *
28
+ * Identifier namespaces are per-table. A {@link ConceptID} and a {@link RelationID} may read the
29
+ * same string without colliding; the brands are what keep them apart in a consumer.
30
+ *
31
+ * Consumed by `./validate.ts` (which refuses a document violating any rule above), by #1926's
32
+ * deterministic compiler, and by the first authored document in #1927.
33
+ *
34
+ * Boundary record: `docs/superpowers/specs/2026-08-26-geographic-model-boundaries.md` (#1917).
35
+ */
36
+ import type { POICategoryID } from "@mailwoman/poi-taxonomy/types";
37
+ import type { Tagged } from "type-fest";
38
+ /**
39
+ * A concept identifier, e.g. `pharmacy`, `obtain_medication`. Branded — convert via {@link toConceptID}.
40
+ */
41
+ export type ConceptID = Tagged<string, "GeographicConceptID">;
42
+ /**
43
+ * Brand a raw string as a {@link ConceptID}. Purely a compile-time assertion; the string is unchanged.
44
+ */
45
+ export declare function toConceptID(id: string): ConceptID;
46
+ /**
47
+ * A relation identifier, e.g. `affords`. Branded — convert via {@link toRelationID}.
48
+ */
49
+ export type RelationID = Tagged<string, "GeographicRelationID">;
50
+ /**
51
+ * Brand a raw string as a {@link RelationID}. Purely a compile-time assertion; the string is unchanged.
52
+ */
53
+ export declare function toRelationID(id: string): RelationID;
54
+ /**
55
+ * The identifier of one authored {@link RelationAssertion}. Branded — convert via {@link toRuleID}.
56
+ */
57
+ export type RuleID = Tagged<string, "GeographicRuleID">;
58
+ /**
59
+ * Brand a raw string as a {@link RuleID}. Purely a compile-time assertion; the string is unchanged.
60
+ */
61
+ export declare function toRuleID(id: string): RuleID;
62
+ /**
63
+ * The identifier of one {@link ExternalMappingRecord}. Branded — convert via {@link toMappingID}.
64
+ */
65
+ export type MappingID = Tagged<string, "GeographicMappingID">;
66
+ /**
67
+ * Brand a raw string as a {@link MappingID}. Purely a compile-time assertion; the string is unchanged.
68
+ */
69
+ export declare function toMappingID(id: string): MappingID;
70
+ /**
71
+ * The identifier of one {@link SourceObservationRecord}. Branded — convert via {@link toObservationID}.
72
+ */
73
+ export type ObservationID = Tagged<string, "GeographicObservationID">;
74
+ /**
75
+ * Brand a raw string as an {@link ObservationID}. Purely a compile-time assertion; the string is unchanged.
76
+ */
77
+ export declare function toObservationID(id: string): ObservationID;
78
+ /**
79
+ * The identifier of one {@link DerivedFactRecord}. Branded — convert via {@link toDerivedFactID}.
80
+ */
81
+ export type DerivedFactID = Tagged<string, "GeographicDerivedFactID">;
82
+ /**
83
+ * Brand a raw string as a {@link DerivedFactID}. Purely a compile-time assertion; the string is unchanged.
84
+ */
85
+ export declare function toDerivedFactID(id: string): DerivedFactID;
86
+ /**
87
+ * The complete set of concept kinds. Three, deliberately: the first executable slice needs an establishment class, an
88
+ * activity, and the place class an establishment is sited in. Widening this vocabulary is a reviewed schema revision,
89
+ * which is the review cost the program accepted in exchange for refusing speculative upper-ontology breadth.
90
+ */
91
+ export declare const ConceptKind: {
92
+ /**
93
+ * A geographic place — an area or a point that other things are sited in or near.
94
+ */
95
+ readonly Place: "place";
96
+ /**
97
+ * A class of premises a person can go to, e.g. `pharmacy`.
98
+ */
99
+ readonly Establishment: "establishment";
100
+ /**
101
+ * Something a person does, e.g. `obtain_medication`. The identifier is owned here; any statistics fitted against it
102
+ * are owned by #1683.
103
+ */
104
+ readonly Activity: "activity";
105
+ };
106
+ export type ConceptKind = (typeof ConceptKind)[keyof typeof ConceptKind];
107
+ /**
108
+ * How strongly an assertion, an observation, or a derived fact claims its proposition holds.
109
+ *
110
+ * The vocabulary is ordinal in meaning and this module exports no order over it, on purpose. An exported rank would be
111
+ * one arithmetic step from a weight, and an authored weight is the single thing the package boundary forbids.
112
+ */
113
+ export declare const Modality: {
114
+ /**
115
+ * Holds in every instance; a counter-example falsifies the record rather than qualifying it.
116
+ */
117
+ readonly Necessary: "necessary";
118
+ /**
119
+ * Never holds.
120
+ */
121
+ readonly Prohibited: "prohibited";
122
+ readonly StronglyExpected: "strongly_expected";
123
+ readonly Expected: "expected";
124
+ readonly WeaklyExpected: "weakly_expected";
125
+ /**
126
+ * Consistent with the concept and asserts nothing about how often it holds.
127
+ */
128
+ readonly Possible: "possible";
129
+ readonly Unusual: "unusual";
130
+ readonly StronglyUnusual: "strongly_unusual";
131
+ };
132
+ export type Modality = (typeof Modality)[keyof typeof Modality];
133
+ /**
134
+ * Whether a relation's assertions admit exceptions.
135
+ */
136
+ export declare const RelationSemantics: {
137
+ /**
138
+ * An exception is a defect in the record set.
139
+ */
140
+ readonly Hard: "hard";
141
+ /**
142
+ * An exception is expected and does not falsify the relation.
143
+ */
144
+ readonly Defeasible: "defeasible";
145
+ };
146
+ export type RelationSemantics = (typeof RelationSemantics)[keyof typeof RelationSemantics];
147
+ /**
148
+ * A concept's authoring lifecycle. It says whether a consumer should read the record, and nothing about how much the
149
+ * record is worth.
150
+ */
151
+ export declare const ConceptStatus: {
152
+ /**
153
+ * Authored, not yet reviewed. A compiler may refuse to emit it.
154
+ */
155
+ readonly Draft: "draft";
156
+ readonly Active: "active";
157
+ /**
158
+ * Kept so existing references resolve; no new reference should be authored against it.
159
+ */
160
+ readonly Deprecated: "deprecated";
161
+ };
162
+ export type ConceptStatus = (typeof ConceptStatus)[keyof typeof ConceptStatus];
163
+ /**
164
+ * The external vocabularies a concept can be mapped into. One today, and the mapping record below is typed against it
165
+ * directly; a second vocabulary turns {@link ExternalMappingRecord} into a union discriminated on `vocabulary`.
166
+ */
167
+ export declare const ExternalVocabulary: {
168
+ /**
169
+ * `@mailwoman/poi-taxonomy` category identifiers — the owner of external and curated POI categories.
170
+ */
171
+ readonly POITaxonomy: "poi-taxonomy";
172
+ };
173
+ export type ExternalVocabulary = (typeof ExternalVocabulary)[keyof typeof ExternalVocabulary];
174
+ /**
175
+ * Where a record came from. `source` is required and non-empty on every record that carries provenance: a record whose
176
+ * source is blank is indistinguishable from a record nobody stands behind.
177
+ */
178
+ export interface SourceProvenance {
179
+ /**
180
+ * The naming authority, dataset, publication, or curator, e.g. `overture-places` or `mailwoman-curated`.
181
+ */
182
+ source: string;
183
+ /**
184
+ * The source's own version or release string, when it has one, e.g. an Overture release.
185
+ */
186
+ sourceVersion?: string;
187
+ /**
188
+ * The identifier of the specific record within the source, when the claim is traceable to one.
189
+ */
190
+ sourceRecord?: string;
191
+ sourceURL?: string;
192
+ /**
193
+ * ISO 8601 calendar date the record was authored, `YYYY-MM-DD`.
194
+ */
195
+ authoredAt?: string;
196
+ notes?: string;
197
+ }
198
+ /**
199
+ * One relation's definition. Relations are vocabulary, not claims: the record says what the relation MEANS and which
200
+ * concept kinds may stand on either side of it, and asserts nothing about any particular pair.
201
+ */
202
+ export interface RelationRecord {
203
+ id: RelationID;
204
+ label: string;
205
+ description: string;
206
+ /**
207
+ * The concept kinds allowed on the asserting side.
208
+ */
209
+ domainKinds: ConceptKind[];
210
+ /**
211
+ * The concept kinds allowed on the target side.
212
+ */
213
+ rangeKinds: ConceptKind[];
214
+ transitive: boolean;
215
+ symmetric: boolean;
216
+ /**
217
+ * The relation reading the same edge in the other direction. When present it must resolve, and the relation it names
218
+ * must name this one back.
219
+ */
220
+ inverse?: RelationID;
221
+ semantics: RelationSemantics;
222
+ }
223
+ /**
224
+ * One authored claim, attached to the concept it is about. This is curated semantics — what a curator states holds, not
225
+ * what a dataset was observed to contain.
226
+ */
227
+ export interface RelationAssertion {
228
+ id: RuleID;
229
+ relation: RelationID;
230
+ target: ConceptID;
231
+ modality: Modality;
232
+ /**
233
+ * ISO 3166-1 alpha-2 codes the claim is scoped to. Absent means the curator scoped it to nowhere in particular, which
234
+ * is a weaker statement than scoping it to everywhere.
235
+ */
236
+ countries?: string[];
237
+ provenance: SourceProvenance;
238
+ }
239
+ /**
240
+ * One concept, and everything authored about it.
241
+ */
242
+ export interface ConceptRecord {
243
+ id: ConceptID;
244
+ label: string;
245
+ description: string;
246
+ kind: ConceptKind;
247
+ /**
248
+ * Broader concepts this one is a kind of. May be empty; may not name this concept, directly or around a cycle.
249
+ */
250
+ isA: ConceptID[];
251
+ assertions: RelationAssertion[];
252
+ provenance: SourceProvenance;
253
+ status: ConceptStatus;
254
+ }
255
+ /**
256
+ * A translation from an external vocabulary's identifier into a concept owned here. It carries no semantics of its own:
257
+ * it says which external identifier names the same thing, and on whose authority.
258
+ */
259
+ export interface ExternalMappingRecord {
260
+ id: MappingID;
261
+ concept: ConceptID;
262
+ vocabulary: ExternalVocabulary;
263
+ /**
264
+ * The identifier in the external vocabulary. Typed as a `POICategoryID` because `poi-taxonomy` is the only member of
265
+ * {@link ExternalVocabulary}; a second member makes this field a per-vocabulary type.
266
+ */
267
+ externalID: POICategoryID;
268
+ provenance: SourceProvenance;
269
+ }
270
+ /**
271
+ * A proposition a named external source states, recorded in this model's vocabulary.
272
+ *
273
+ * It is kept out of the concept table on purpose. An observation is evidence about the world that someone else
274
+ * collected; promoting one into an authored assertion is a curation decision that has to be made and provenanced
275
+ * explicitly, never by the record sitting in a convenient place.
276
+ */
277
+ export interface SourceObservationRecord {
278
+ id: ObservationID;
279
+ subject: ConceptID;
280
+ relation: RelationID;
281
+ object: ConceptID;
282
+ modality: Modality;
283
+ /**
284
+ * ISO 3166-1 alpha-2 codes the source scoped its statement to.
285
+ */
286
+ countries?: string[];
287
+ provenance: SourceProvenance;
288
+ }
289
+ /**
290
+ * Which table a {@link DerivationInput} points into.
291
+ */
292
+ export declare const DerivationInputKind: {
293
+ readonly Concept: "concept";
294
+ readonly Relation: "relation";
295
+ readonly Assertion: "assertion";
296
+ readonly Mapping: "mapping";
297
+ readonly Observation: "observation";
298
+ readonly DerivedFact: "derived_fact";
299
+ };
300
+ export type DerivationInputKind = (typeof DerivationInputKind)[keyof typeof DerivationInputKind];
301
+ /**
302
+ * One record a derivation read. The union is discriminated on `kind` so the identifier's brand matches the table it
303
+ * resolves against.
304
+ */
305
+ export type DerivationInput = {
306
+ kind: typeof DerivationInputKind.Concept;
307
+ id: ConceptID;
308
+ } | {
309
+ kind: typeof DerivationInputKind.Relation;
310
+ id: RelationID;
311
+ } | {
312
+ kind: typeof DerivationInputKind.Assertion;
313
+ id: RuleID;
314
+ } | {
315
+ kind: typeof DerivationInputKind.Mapping;
316
+ id: MappingID;
317
+ } | {
318
+ kind: typeof DerivationInputKind.Observation;
319
+ id: ObservationID;
320
+ } | {
321
+ kind: typeof DerivationInputKind.DerivedFact;
322
+ id: DerivedFactID;
323
+ };
324
+ /**
325
+ * A fact a named procedure computed from named inputs. Never hand-authored: #1926's compiler writes this table, and the
326
+ * validator refuses a fact whose derivation is unnamed or whose inputs do not resolve.
327
+ *
328
+ * There is no provenance field. The derivation plus the inputs is the provenance, and it is the stronger kind — a
329
+ * source string can be copied onto a record that did not come from it, while an input list either resolves or the
330
+ * document does not validate.
331
+ */
332
+ export interface DerivedFactRecord {
333
+ id: DerivedFactID;
334
+ /**
335
+ * The deterministic procedure that produced this fact, named so a reader can re-run it.
336
+ */
337
+ derivation: string;
338
+ /**
339
+ * Every record the derivation read. At least one, and each must resolve.
340
+ */
341
+ inputs: DerivationInput[];
342
+ subject: ConceptID;
343
+ relation: RelationID;
344
+ object: ConceptID;
345
+ modality: Modality;
346
+ countries?: string[];
347
+ }
348
+ /**
349
+ * One authored document: the whole record set a validator, and later a compiler, reads at once.
350
+ *
351
+ * All six fields are required, `derivedFacts` included. A hand-authored file therefore writes `"derivedFacts": []`,
352
+ * which is the point — an absent table and an empty table are different claims, and the format that allows the first to
353
+ * stand in for the second is the format where a dropped table reads as a world with no derived facts in it.
354
+ */
355
+ export interface GeographicModelDocument {
356
+ /**
357
+ * The document's own schema/data version.
358
+ */
359
+ version: string;
360
+ relations: RelationRecord[];
361
+ concepts: ConceptRecord[];
362
+ mappings: ExternalMappingRecord[];
363
+ observations: SourceObservationRecord[];
364
+ derivedFacts: DerivedFactRecord[];
365
+ }
366
+ //# sourceMappingURL=schema.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../schema.ts"],"names":[],"mappings":"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"}
package/out/schema.js ADDED
@@ -0,0 +1,166 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license AGPL-3.0
4
+ * @author Teffen Ellis, et al.
5
+ *
6
+ * The authored-record schema for `@mailwoman/geographic-model`: the stable identifiers, the closed
7
+ * vocabularies, and the record shapes for concepts, relations, external-vocabulary mappings, source
8
+ * observations, and derived facts.
9
+ *
10
+ * Three properties hold by construction, and they are why the file reads the way it does.
11
+ *
12
+ * **No numeric field exists anywhere in this schema** — not a strength, not a confidence, not a
13
+ * count. {@link Modality} is an ordinal vocabulary of WORDS and this module exports no order over
14
+ * it, because a number attached to an authored relationship is a ranking weight whatever it is
15
+ * called, and ranking belongs to `@mailwoman/resolver` and `@mailwoman/neural`.
16
+ *
17
+ * **An authored assertion, a source observation, and a derived fact are three different types.** A
18
+ * {@link RelationAssertion} is authored by a curator and lives on the concept it is about; a
19
+ * {@link SourceObservationRecord} records what a named external source states and never enters the
20
+ * concept table; a {@link DerivedFactRecord} names the procedure that produced it and every input
21
+ * that procedure read. Their identifiers are separately branded, so one is not assignable where
22
+ * another is expected.
23
+ *
24
+ * **Every record carries provenance, and a derived fact carries it structurally.** A derived fact
25
+ * has no {@link SourceProvenance} of its own: its `derivation` plus its resolved `inputs` ARE its
26
+ * provenance, and each input carries source provenance in turn.
27
+ *
28
+ * Identifier namespaces are per-table. A {@link ConceptID} and a {@link RelationID} may read the
29
+ * same string without colliding; the brands are what keep them apart in a consumer.
30
+ *
31
+ * Consumed by `./validate.ts` (which refuses a document violating any rule above), by #1926's
32
+ * deterministic compiler, and by the first authored document in #1927.
33
+ *
34
+ * Boundary record: `docs/superpowers/specs/2026-08-26-geographic-model-boundaries.md` (#1917).
35
+ */
36
+ /**
37
+ * Brand a raw string as a {@link ConceptID}. Purely a compile-time assertion; the string is unchanged.
38
+ */
39
+ export function toConceptID(id) {
40
+ return id;
41
+ }
42
+ /**
43
+ * Brand a raw string as a {@link RelationID}. Purely a compile-time assertion; the string is unchanged.
44
+ */
45
+ export function toRelationID(id) {
46
+ return id;
47
+ }
48
+ /**
49
+ * Brand a raw string as a {@link RuleID}. Purely a compile-time assertion; the string is unchanged.
50
+ */
51
+ export function toRuleID(id) {
52
+ return id;
53
+ }
54
+ /**
55
+ * Brand a raw string as a {@link MappingID}. Purely a compile-time assertion; the string is unchanged.
56
+ */
57
+ export function toMappingID(id) {
58
+ return id;
59
+ }
60
+ /**
61
+ * Brand a raw string as an {@link ObservationID}. Purely a compile-time assertion; the string is unchanged.
62
+ */
63
+ export function toObservationID(id) {
64
+ return id;
65
+ }
66
+ /**
67
+ * Brand a raw string as a {@link DerivedFactID}. Purely a compile-time assertion; the string is unchanged.
68
+ */
69
+ export function toDerivedFactID(id) {
70
+ return id;
71
+ }
72
+ /**
73
+ * The complete set of concept kinds. Three, deliberately: the first executable slice needs an establishment class, an
74
+ * activity, and the place class an establishment is sited in. Widening this vocabulary is a reviewed schema revision,
75
+ * which is the review cost the program accepted in exchange for refusing speculative upper-ontology breadth.
76
+ */
77
+ export const ConceptKind = {
78
+ /**
79
+ * A geographic place — an area or a point that other things are sited in or near.
80
+ */
81
+ Place: "place",
82
+ /**
83
+ * A class of premises a person can go to, e.g. `pharmacy`.
84
+ */
85
+ Establishment: "establishment",
86
+ /**
87
+ * Something a person does, e.g. `obtain_medication`. The identifier is owned here; any statistics fitted against it
88
+ * are owned by #1683.
89
+ */
90
+ Activity: "activity",
91
+ };
92
+ /**
93
+ * How strongly an assertion, an observation, or a derived fact claims its proposition holds.
94
+ *
95
+ * The vocabulary is ordinal in meaning and this module exports no order over it, on purpose. An exported rank would be
96
+ * one arithmetic step from a weight, and an authored weight is the single thing the package boundary forbids.
97
+ */
98
+ export const Modality = {
99
+ /**
100
+ * Holds in every instance; a counter-example falsifies the record rather than qualifying it.
101
+ */
102
+ Necessary: "necessary",
103
+ /**
104
+ * Never holds.
105
+ */
106
+ Prohibited: "prohibited",
107
+ StronglyExpected: "strongly_expected",
108
+ Expected: "expected",
109
+ WeaklyExpected: "weakly_expected",
110
+ /**
111
+ * Consistent with the concept and asserts nothing about how often it holds.
112
+ */
113
+ Possible: "possible",
114
+ Unusual: "unusual",
115
+ StronglyUnusual: "strongly_unusual",
116
+ };
117
+ /**
118
+ * Whether a relation's assertions admit exceptions.
119
+ */
120
+ export const RelationSemantics = {
121
+ /**
122
+ * An exception is a defect in the record set.
123
+ */
124
+ Hard: "hard",
125
+ /**
126
+ * An exception is expected and does not falsify the relation.
127
+ */
128
+ Defeasible: "defeasible",
129
+ };
130
+ /**
131
+ * A concept's authoring lifecycle. It says whether a consumer should read the record, and nothing about how much the
132
+ * record is worth.
133
+ */
134
+ export const ConceptStatus = {
135
+ /**
136
+ * Authored, not yet reviewed. A compiler may refuse to emit it.
137
+ */
138
+ Draft: "draft",
139
+ Active: "active",
140
+ /**
141
+ * Kept so existing references resolve; no new reference should be authored against it.
142
+ */
143
+ Deprecated: "deprecated",
144
+ };
145
+ /**
146
+ * The external vocabularies a concept can be mapped into. One today, and the mapping record below is typed against it
147
+ * directly; a second vocabulary turns {@link ExternalMappingRecord} into a union discriminated on `vocabulary`.
148
+ */
149
+ export const ExternalVocabulary = {
150
+ /**
151
+ * `@mailwoman/poi-taxonomy` category identifiers — the owner of external and curated POI categories.
152
+ */
153
+ POITaxonomy: "poi-taxonomy",
154
+ };
155
+ /**
156
+ * Which table a {@link DerivationInput} points into.
157
+ */
158
+ export const DerivationInputKind = {
159
+ Concept: "concept",
160
+ Relation: "relation",
161
+ Assertion: "assertion",
162
+ Mapping: "mapping",
163
+ Observation: "observation",
164
+ DerivedFact: "derived_fact",
165
+ };
166
+ //# sourceMappingURL=schema.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AAUH;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,EAAU;IACrC,OAAO,EAAe,CAAA;AACvB,CAAC;AAOD;;GAEG;AACH,MAAM,UAAU,YAAY,CAAC,EAAU;IACtC,OAAO,EAAgB,CAAA;AACxB,CAAC;AAOD;;GAEG;AACH,MAAM,UAAU,QAAQ,CAAC,EAAU;IAClC,OAAO,EAAY,CAAA;AACpB,CAAC;AAOD;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,EAAU;IACrC,OAAO,EAAe,CAAA;AACvB,CAAC;AAOD;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,EAAU;IACzC,OAAO,EAAmB,CAAA;AAC3B,CAAC;AAOD;;GAEG;AACH,MAAM,UAAU,eAAe,CAAC,EAAU;IACzC,OAAO,EAAmB,CAAA;AAC3B,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG;IAC1B;;OAEG;IACH,KAAK,EAAE,OAAO;IACd;;OAEG;IACH,aAAa,EAAE,eAAe;IAC9B;;;OAGG;IACH,QAAQ,EAAE,UAAU;CACX,CAAA;AAIV;;;;;GAKG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAG;IACvB;;OAEG;IACH,SAAS,EAAE,WAAW;IACtB;;OAEG;IACH,UAAU,EAAE,YAAY;IACxB,gBAAgB,EAAE,mBAAmB;IACrC,QAAQ,EAAE,UAAU;IACpB,cAAc,EAAE,iBAAiB;IACjC;;OAEG;IACH,QAAQ,EAAE,UAAU;IACpB,OAAO,EAAE,SAAS;IAClB,eAAe,EAAE,kBAAkB;CAC1B,CAAA;AAIV;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG;IAChC;;OAEG;IACH,IAAI,EAAE,MAAM;IACZ;;OAEG;IACH,UAAU,EAAE,YAAY;CACf,CAAA;AAIV;;;GAGG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG;IAC5B;;OAEG;IACH,KAAK,EAAE,OAAO;IACd,MAAM,EAAE,QAAQ;IAChB;;OAEG;IACH,UAAU,EAAE,YAAY;CACf,CAAA;AAIV;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG;IACjC;;OAEG;IACH,WAAW,EAAE,cAAc;CAClB,CAAA;AA6HV;;GAEG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG;IAClC,OAAO,EAAE,SAAS;IAClB,QAAQ,EAAE,UAAU;IACpB,SAAS,EAAE,WAAW;IACtB,OAAO,EAAE,SAAS;IAClB,WAAW,EAAE,aAAa;IAC1B,WAAW,EAAE,cAAc;CAClB,CAAA"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license AGPL-3.0
4
+ * @author Teffen Ellis, et al.
5
+ *
6
+ * Generator for `data/geographic-model.json` — the committed compiled artifact, built from the
7
+ * authored records under `data/model/`.
8
+ *
9
+ * The build step is the whole of what this file does: load the authoring directory, compile it,
10
+ * serialize the result. Every decision inside those three calls belongs to `../load.ts`,
11
+ * `../compile.ts` and `../artifact.ts`, and none of them is re-made here.
12
+ *
13
+ * **A committed artifact is these bytes run through `oxfmt`.** The repository formatter also formats
14
+ * committed JSON, and it inlines short arrays, which `JSON.stringify` cannot reproduce. So the
15
+ * freshness check in `test/unit/pharmacy-slice.test.ts` compares the PARSED artifact against a fresh
16
+ * compile, and byte equality is asserted between two compiles instead. The same convention holds
17
+ * `taxonomy.json` in `@mailwoman/poi-taxonomy`; its `data/PROVENANCE.md` states it for that table.
18
+ *
19
+ * Nothing here reaches `@mailwoman/core`: the package's build project declares no reference to it in
20
+ * either direction, and a generator is not the reason to reverse that. `import.meta.main` is what
21
+ * `runIfScript` reads anyway, and reading it directly keeps this file inside the package's own
22
+ * dependency graph.
23
+ */
24
+ import { type CompiledGeographicModel } from "../artifact.ts";
25
+ /**
26
+ * The command that rewrites the committed artifact. Stated once, and quoted by the freshness test's failure message, so
27
+ * a reader who trips it is told what to run rather than left to reconstruct it.
28
+ */
29
+ export declare const REGENERATE_ARTIFACT_COMMAND = "node packages/geographic-model/scripts/build-artifact.ts && npx oxfmt packages/geographic-model/data/geographic-model.json";
30
+ /**
31
+ * The authoring directory and the artifact it compiles to.
32
+ *
33
+ * Two candidates, because this module runs from two places: `scripts/` in the repository, where `data/` is one level
34
+ * up, and `out/scripts/` in a published tarball, where it is two. Probing for the file distinguishes those from a
35
+ * genuinely missing `data/`, which throws with both paths named.
36
+ */
37
+ export declare function packagedModelPaths(): {
38
+ source: string;
39
+ artifact: string;
40
+ };
41
+ /**
42
+ * Load the authored records and compile them. Throws with every violation if they do not load, and with every reason if
43
+ * they load but do not compile; nothing partial is returned.
44
+ */
45
+ export declare function compileAuthoredGeographicModel(): CompiledGeographicModel;
46
+ /**
47
+ * Read the committed artifact. The format version is checked; the records are not re-validated, because they were
48
+ * validated on the way in.
49
+ */
50
+ export declare function readCompiledGeographicModel(): CompiledGeographicModel;
51
+ //# sourceMappingURL=build-artifact.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-artifact.d.ts","sourceRoot":"","sources":["../../scripts/build-artifact.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAKH,OAAO,EAAE,KAAK,uBAAuB,EAAwD,MAAM,gBAAgB,CAAA;AAInH;;;GAGG;AACH,eAAO,MAAM,2BAA2B,+HACqF,CAAA;AAE7H;;;;;;GAMG;AACH,wBAAgB,kBAAkB,IAAI;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CASzE;AAED;;;GAGG;AACH,wBAAgB,8BAA8B,IAAI,uBAAuB,CAExE;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,IAAI,uBAAuB,CAOrE"}
@@ -0,0 +1,78 @@
1
+ /**
2
+ * @copyright Sister Software
3
+ * @license AGPL-3.0
4
+ * @author Teffen Ellis, et al.
5
+ *
6
+ * Generator for `data/geographic-model.json` — the committed compiled artifact, built from the
7
+ * authored records under `data/model/`.
8
+ *
9
+ * The build step is the whole of what this file does: load the authoring directory, compile it,
10
+ * serialize the result. Every decision inside those three calls belongs to `../load.ts`,
11
+ * `../compile.ts` and `../artifact.ts`, and none of them is re-made here.
12
+ *
13
+ * **A committed artifact is these bytes run through `oxfmt`.** The repository formatter also formats
14
+ * committed JSON, and it inlines short arrays, which `JSON.stringify` cannot reproduce. So the
15
+ * freshness check in `test/unit/pharmacy-slice.test.ts` compares the PARSED artifact against a fresh
16
+ * compile, and byte equality is asserted between two compiles instead. The same convention holds
17
+ * `taxonomy.json` in `@mailwoman/poi-taxonomy`; its `data/PROVENANCE.md` states it for that table.
18
+ *
19
+ * Nothing here reaches `@mailwoman/core`: the package's build project declares no reference to it in
20
+ * either direction, and a generator is not the reason to reverse that. `import.meta.main` is what
21
+ * `runIfScript` reads anyway, and reading it directly keeps this file inside the package's own
22
+ * dependency graph.
23
+ */
24
+ import { existsSync, readFileSync, writeFileSync } from "node:fs";
25
+ import { resolve } from "node:path";
26
+ import { parseCompiledGeographicModel, serializeCompiledModel } from "../artifact.js";
27
+ import { compileGeographicModel } from "../compile.js";
28
+ import { loadGeographicModelDirectory } from "../load.js";
29
+ /**
30
+ * The command that rewrites the committed artifact. Stated once, and quoted by the freshness test's failure message, so
31
+ * a reader who trips it is told what to run rather than left to reconstruct it.
32
+ */
33
+ export const REGENERATE_ARTIFACT_COMMAND = "node packages/geographic-model/scripts/build-artifact.ts && npx oxfmt packages/geographic-model/data/geographic-model.json";
34
+ /**
35
+ * The authoring directory and the artifact it compiles to.
36
+ *
37
+ * Two candidates, because this module runs from two places: `scripts/` in the repository, where `data/` is one level
38
+ * up, and `out/scripts/` in a published tarball, where it is two. Probing for the file distinguishes those from a
39
+ * genuinely missing `data/`, which throws with both paths named.
40
+ */
41
+ export function packagedModelPaths() {
42
+ const candidates = [resolve(import.meta.dirname, "../data"), resolve(import.meta.dirname, "../../data")];
43
+ const found = candidates.find((candidate) => existsSync(resolve(candidate, "model/model.json")));
44
+ if (!found) {
45
+ throw new Error(`geographic-model: could not find data/model — looked in ${candidates.join(", ")}`);
46
+ }
47
+ return { source: resolve(found, "model"), artifact: resolve(found, "geographic-model.json") };
48
+ }
49
+ /**
50
+ * Load the authored records and compile them. Throws with every violation if they do not load, and with every reason if
51
+ * they load but do not compile; nothing partial is returned.
52
+ */
53
+ export function compileAuthoredGeographicModel() {
54
+ return compileGeographicModel(loadGeographicModelDirectory(packagedModelPaths().source));
55
+ }
56
+ /**
57
+ * Read the committed artifact. The format version is checked; the records are not re-validated, because they were
58
+ * validated on the way in.
59
+ */
60
+ export function readCompiledGeographicModel() {
61
+ const text = readFileSync(packagedModelPaths().artifact, "utf8");
62
+ // A corrupt committed artifact is a broken build, and the `SyntaxError` names the offset. The package's parse
63
+ // wrappers live in `@mailwoman/core`, which this package deliberately does not depend on.
64
+ // oxlint-disable-next-line no-restricted-properties -- see the note above.
65
+ return parseCompiledGeographicModel(JSON.parse(text));
66
+ }
67
+ function main() {
68
+ const { artifact } = packagedModelPaths();
69
+ const model = compileAuthoredGeographicModel();
70
+ writeFileSync(artifact, serializeCompiledModel(model));
71
+ console.log(`wrote ${artifact}: ${model.concepts.length} concepts, ${model.relations.length} relations, ${model.mappings.length} mappings, ${model.observations.length} observations, ${model.derivedFacts.length} derived facts (model ${model.modelVersion})`);
72
+ }
73
+ // `import.meta.main` is undefined under a Vite/vitest module graph, so importing this module from a test stays
74
+ // side-effect-free and never rewrites the committed artifact.
75
+ if (import.meta.main) {
76
+ main();
77
+ }
78
+ //# sourceMappingURL=build-artifact.js.map