]> Lady’s Gitweb - Etiquette/blob - schema.js
Return undefined not null when resolving fails
[Etiquette] / schema.js
1 // 📧🏷️ Étiquette ∷ schema.js
2 // ====================================================================
3 //
4 // Copyright © 2023 Lady [@ Lady’s Computer].
5 //
6 // This Source Code Form is subject to the terms of the Mozilla Public
7 // License, v. 2.0. If a copy of the MPL was not distributed with this
8 // file, You can obtain one at <https://mozilla.org/MPL/2.0/>.
9 //
10 // ___
11 //
12 // ※ The definitions in this file are minimal and only really geared
13 // towards supporting the functionality that 📧🏷️ Étiquette needs.
14
15 /**
16 * Supported class types.
17 *
18 * The class `"Thing"` is not defined, but is used as a generic
19 * superclass.
20 */
21 const classes = {
22 Tag: { subClassOf: "Thing" },
23 CanonTag: { subClassOf: "Tag" },
24 ConceptualTag: { subClassOf: "Tag" },
25 RelationshipTag: {
26 subClassOf: ["ConceptualTag", {
27 onProperty: "involves",
28 allValuesFrom: {
29 unionOf: ["CharacterTag", "RelationshipTag"],
30 },
31 }],
32 },
33 FriendshipTag: { subClassOf: "RelationshipTag" },
34 RivalryTag: { subClassOf: "RelationshipTag" },
35 FamilialRelationshipTag: { subClassOf: "RelationshipTag" },
36 RomanticRelationshipTag: { subClassOf: "RelationshipTag" },
37 SexualRelationshipTag: { subClassOf: "RelationshipTag" },
38 EntityTag: { subClassOf: "Tag" },
39 CharacterTag: { subClassOf: "EntityTag" },
40 InanimateEntityTag: { subClassOf: "EntityTag" },
41 GenreTag: { subClassOf: "Tag" },
42 SettingTag: { subClassOf: "Tag" },
43 LocationTag: { subClassOf: "SettingTag" },
44 TimePeriodTag: { subClassOf: "SettingTag" },
45 UniverseTag: { subClassOf: "SettingTag" },
46 };
47
48 /** Supported transitive object properties. */
49 const transitiveProperties = {
50 broaderTransitive: { domain: "Tag", range: "Tag" },
51 narrowerTransitive: { inverseOf: "broaderTransitive" },
52 };
53
54 /** Supported object properties. */
55 const objectProperties = {
56 broader: { subPropertyOf: "broaderTransitive" },
57 narrower: {
58 inverseOf: "broader",
59 subPropertyOf: "narrowerTransitive",
60 },
61 inCanon: {
62 domain: { unionOf: ["EntityTag", "SettingTag"] },
63 range: "CanonTag",
64 },
65 hasInCanon: { inverseOf: "inCanon" },
66 involves: { domain: "ConceptualTag", range: "Tag" },
67 involvedIn: { inverseOf: "involves" },
68 ...transitiveProperties,
69 };
70
71 /** Supported data properties. */
72 const dataProperties = {
73 prefLabel: { domain: "Thing", range: "PlainLiteral" },
74 altLabel: { domain: "Thing", range: "PlainLiteral" },
75 hiddenLabel: { domain: "Thing", range: "PlainLiteral" },
76 };
77
78 /**
79 * Returns an immutable, null‐prototype object deeply derived from the
80 * provided one.
81 *
82 * ※ Once records and tuples are added to Ecmascript, the schema
83 * should be defined in terms of those primitives. In the meantime,
84 * this function at least ensures the schema is Very Immutable.
85 */
86 const makeRecord = ($) => {
87 return Object.preventExtensions(
88 Object.create(
89 null,
90 Object.fromEntries([...function* () {
91 for (const [key, value] of Object.entries($)) {
92 if (Object(value) === value) {
93 const recordValue = makeRecord(value);
94 yield [key, { enumerable: true, value: recordValue }];
95 } else {
96 yield [key, { enumerable: true, value }];
97 }
98 }
99 if (Array.isArray($)) {
100 yield ["length", { value: $.length }];
101 } else {
102 /* do nothing */
103 }
104 }()]),
105 ),
106 );
107 };
108
109 export default makeRecord({
110 classes,
111 objectProperties,
112 transitiveProperties,
113 dataProperties,
114 });
This page took 0.055988 seconds and 5 git commands to generate.