bsdata-parser 0.1.0 → 0.1.2
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 +37 -149
- package/dist/index.d.ts +4 -236
- package/dist/index.js +13 -301
- package/dist/index.js.map +1 -1
- package/dist/ir/types.d.ts +229 -0
- package/dist/ir/types.js +10 -0
- package/dist/ir/types.js.map +1 -0
- package/dist/parse/index.d.ts +2 -0
- package/dist/parse/index.js +12 -0
- package/dist/parse/index.js.map +1 -0
- package/dist/parse/xml.d.ts +2 -0
- package/dist/parse/xml.js +296 -0
- package/dist/parse/xml.js.map +1 -0
- package/dist/project/catalogue.d.ts +17 -0
- package/dist/project/catalogue.js +19 -0
- package/dist/project/catalogue.js.map +1 -0
- package/package.json +8 -23
package/dist/index.js
CHANGED
|
@@ -1,302 +1,14 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
"rule",
|
|
15
|
-
"categoryLink",
|
|
16
|
-
"categoryEntry",
|
|
17
|
-
"infoLink",
|
|
18
|
-
"modifier",
|
|
19
|
-
"condition",
|
|
20
|
-
"conditionGroup",
|
|
21
|
-
"repeat",
|
|
22
|
-
"forceEntry",
|
|
23
|
-
"catalogueLink"
|
|
24
|
-
]);
|
|
25
|
-
var xmlParser = new XMLParser({
|
|
26
|
-
ignoreAttributes: false,
|
|
27
|
-
attributeNamePrefix: "@_",
|
|
28
|
-
textNodeName: "#text",
|
|
29
|
-
isArray: (name) => ALWAYS_ARRAY.has(name),
|
|
30
|
-
parseAttributeValue: true
|
|
31
|
-
});
|
|
32
|
-
function arr(v) {
|
|
33
|
-
if (!v) return [];
|
|
34
|
-
if (Array.isArray(v)) return v;
|
|
35
|
-
return [v];
|
|
36
|
-
}
|
|
37
|
-
function bool(v) {
|
|
38
|
-
return v === true || v === "true";
|
|
39
|
-
}
|
|
40
|
-
function parseConstraint(n) {
|
|
41
|
-
return {
|
|
42
|
-
id: String(n["@_id"] ?? ""),
|
|
43
|
-
type: n["@_type"] === "min" ? "min" : "max",
|
|
44
|
-
value: Number(n["@_value"] ?? 0),
|
|
45
|
-
scope: String(n["@_scope"] ?? ""),
|
|
46
|
-
field: String(n["@_field"] ?? "selections"),
|
|
47
|
-
shared: bool(n["@_shared"]),
|
|
48
|
-
includeChildSelections: bool(n["@_includeChildSelections"])
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
function parseCost(n) {
|
|
52
|
-
return {
|
|
53
|
-
name: String(n["@_name"] ?? ""),
|
|
54
|
-
typeId: String(n["@_typeId"] ?? ""),
|
|
55
|
-
value: Number(n["@_value"] ?? 0)
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
function parseCharacteristic(n) {
|
|
59
|
-
const raw = n["#text"];
|
|
60
|
-
return {
|
|
61
|
-
name: String(n["@_name"] ?? ""),
|
|
62
|
-
typeId: String(n["@_typeId"] ?? ""),
|
|
63
|
-
value: raw != null ? String(raw) : ""
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
function parseProfile(n) {
|
|
67
|
-
return {
|
|
68
|
-
id: String(n["@_id"] ?? ""),
|
|
69
|
-
name: String(n["@_name"] ?? ""),
|
|
70
|
-
hidden: bool(n["@_hidden"]),
|
|
71
|
-
typeId: String(n["@_typeId"] ?? ""),
|
|
72
|
-
typeName: String(n["@_typeName"] ?? ""),
|
|
73
|
-
characteristics: arr(n.characteristics?.characteristic).map(parseCharacteristic)
|
|
74
|
-
};
|
|
75
|
-
}
|
|
76
|
-
function parseRule(n) {
|
|
77
|
-
return {
|
|
78
|
-
id: String(n["@_id"] ?? ""),
|
|
79
|
-
name: String(n["@_name"] ?? ""),
|
|
80
|
-
hidden: bool(n["@_hidden"]),
|
|
81
|
-
description: n.description != null ? String(n.description) : ""
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
function parseInfoLink(n) {
|
|
85
|
-
return {
|
|
86
|
-
id: String(n["@_id"] ?? ""),
|
|
87
|
-
name: String(n["@_name"] ?? ""),
|
|
88
|
-
hidden: bool(n["@_hidden"]),
|
|
89
|
-
targetId: String(n["@_targetId"] ?? ""),
|
|
90
|
-
type: String(n["@_type"] ?? "")
|
|
91
|
-
};
|
|
92
|
-
}
|
|
93
|
-
function parseCategoryLink(n) {
|
|
94
|
-
return {
|
|
95
|
-
id: String(n["@_id"] ?? ""),
|
|
96
|
-
targetId: String(n["@_targetId"] ?? ""),
|
|
97
|
-
primary: bool(n["@_primary"])
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
function parseCondition(n) {
|
|
101
|
-
const out = {
|
|
102
|
-
type: String(n["@_type"] ?? ""),
|
|
103
|
-
value: Number(n["@_value"] ?? 0),
|
|
104
|
-
field: String(n["@_field"] ?? ""),
|
|
105
|
-
scope: String(n["@_scope"] ?? "")
|
|
106
|
-
};
|
|
107
|
-
if (n["@_childId"] != null) out.childId = String(n["@_childId"]);
|
|
108
|
-
if (n["@_shared"] != null) out.shared = bool(n["@_shared"]);
|
|
109
|
-
if (n["@_includeChildSelections"] != null) out.includeChildSelections = bool(n["@_includeChildSelections"]);
|
|
110
|
-
if (n["@_percentValue"] != null) out.percentValue = bool(n["@_percentValue"]);
|
|
111
|
-
return out;
|
|
112
|
-
}
|
|
113
|
-
function parseConditionGroup(n) {
|
|
114
|
-
return {
|
|
115
|
-
type: String(n["@_type"] ?? ""),
|
|
116
|
-
conditions: arr(n.conditions?.condition).map(parseCondition),
|
|
117
|
-
conditionGroups: arr(n.conditionGroups?.conditionGroup).map(parseConditionGroup)
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
function parseRepeat(n) {
|
|
121
|
-
const out = {
|
|
122
|
-
value: Number(n["@_value"] ?? 0),
|
|
123
|
-
repeats: Number(n["@_repeats"] ?? 0),
|
|
124
|
-
field: String(n["@_field"] ?? ""),
|
|
125
|
-
scope: String(n["@_scope"] ?? "")
|
|
126
|
-
};
|
|
127
|
-
if (n["@_childId"] != null) out.childId = String(n["@_childId"]);
|
|
128
|
-
if (n["@_shared"] != null) out.shared = bool(n["@_shared"]);
|
|
129
|
-
if (n["@_includeChildSelections"] != null) out.includeChildSelections = bool(n["@_includeChildSelections"]);
|
|
130
|
-
if (n["@_roundUp"] != null) out.roundUp = bool(n["@_roundUp"]);
|
|
131
|
-
return out;
|
|
132
|
-
}
|
|
133
|
-
function parseModifier(n) {
|
|
134
|
-
return {
|
|
135
|
-
type: String(n["@_type"] ?? ""),
|
|
136
|
-
field: String(n["@_field"] ?? ""),
|
|
137
|
-
value: n["@_value"] ?? "",
|
|
138
|
-
conditions: arr(n.conditions?.condition).map(parseCondition),
|
|
139
|
-
conditionGroups: arr(n.conditionGroups?.conditionGroup).map(parseConditionGroup),
|
|
140
|
-
repeats: arr(n.repeats?.repeat).map(parseRepeat)
|
|
141
|
-
};
|
|
142
|
-
}
|
|
143
|
-
function parseSelectionEntry(n) {
|
|
144
|
-
return {
|
|
145
|
-
id: String(n["@_id"] ?? ""),
|
|
146
|
-
name: String(n["@_name"] ?? ""),
|
|
147
|
-
hidden: bool(n["@_hidden"]),
|
|
148
|
-
collective: bool(n["@_collective"]),
|
|
149
|
-
import: bool(n["@_import"]),
|
|
150
|
-
type: n["@_type"] ?? "upgrade",
|
|
151
|
-
...n["@_defaultAmount"] != null ? { defaultAmount: Number(n["@_defaultAmount"]) } : {},
|
|
152
|
-
constraints: arr(n.constraints?.constraint).map(parseConstraint),
|
|
153
|
-
profiles: arr(n.profiles?.profile).map(parseProfile),
|
|
154
|
-
rules: arr(n.rules?.rule).map(parseRule),
|
|
155
|
-
infoLinks: arr(n.infoLinks?.infoLink).map(parseInfoLink),
|
|
156
|
-
categoryLinks: arr(n.categoryLinks?.categoryLink).map(parseCategoryLink),
|
|
157
|
-
costs: arr(n.costs?.cost).map(parseCost),
|
|
158
|
-
modifiers: arr(n.modifiers?.modifier).map(parseModifier),
|
|
159
|
-
selectionEntries: arr(n.selectionEntries?.selectionEntry).map(parseSelectionEntry),
|
|
160
|
-
selectionEntryGroups: arr(n.selectionEntryGroups?.selectionEntryGroup).map(parseSelectionEntryGroup),
|
|
161
|
-
entryLinks: arr(n.entryLinks?.entryLink).map(parseEntryLink)
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
function parseSelectionEntryGroup(n) {
|
|
165
|
-
return {
|
|
166
|
-
id: String(n["@_id"] ?? ""),
|
|
167
|
-
name: String(n["@_name"] ?? ""),
|
|
168
|
-
hidden: bool(n["@_hidden"]),
|
|
169
|
-
collective: bool(n["@_collective"]),
|
|
170
|
-
import: bool(n["@_import"]),
|
|
171
|
-
...n["@_defaultSelectionEntryId"] != null ? { defaultSelectionEntryId: String(n["@_defaultSelectionEntryId"]) } : {},
|
|
172
|
-
constraints: arr(n.constraints?.constraint).map(parseConstraint),
|
|
173
|
-
modifiers: arr(n.modifiers?.modifier).map(parseModifier),
|
|
174
|
-
selectionEntries: arr(n.selectionEntries?.selectionEntry).map(parseSelectionEntry),
|
|
175
|
-
selectionEntryGroups: arr(n.selectionEntryGroups?.selectionEntryGroup).map(parseSelectionEntryGroup),
|
|
176
|
-
entryLinks: arr(n.entryLinks?.entryLink).map(parseEntryLink)
|
|
177
|
-
};
|
|
178
|
-
}
|
|
179
|
-
function parseEntryLink(n) {
|
|
180
|
-
return {
|
|
181
|
-
id: String(n["@_id"] ?? ""),
|
|
182
|
-
name: String(n["@_name"] ?? ""),
|
|
183
|
-
hidden: bool(n["@_hidden"]),
|
|
184
|
-
collective: bool(n["@_collective"]),
|
|
185
|
-
import: bool(n["@_import"]),
|
|
186
|
-
targetId: String(n["@_targetId"] ?? ""),
|
|
187
|
-
type: String(n["@_type"] ?? ""),
|
|
188
|
-
...n["@_defaultAmount"] != null ? { defaultAmount: Number(n["@_defaultAmount"]) } : {},
|
|
189
|
-
...n.comment != null ? { comment: String(n.comment).trim() } : {},
|
|
190
|
-
constraints: arr(n.constraints?.constraint).map(parseConstraint),
|
|
191
|
-
costs: arr(n.costs?.cost).map(parseCost),
|
|
192
|
-
modifiers: arr(n.modifiers?.modifier).map(parseModifier),
|
|
193
|
-
profiles: arr(n.profiles?.profile).map(parseProfile),
|
|
194
|
-
infoLinks: arr(n.infoLinks?.infoLink).map(parseInfoLink),
|
|
195
|
-
categoryLinks: arr(n.categoryLinks?.categoryLink).map(parseCategoryLink),
|
|
196
|
-
selectionEntries: arr(n.selectionEntries?.selectionEntry).map(parseSelectionEntry),
|
|
197
|
-
selectionEntryGroups: arr(n.selectionEntryGroups?.selectionEntryGroup).map(parseSelectionEntryGroup),
|
|
198
|
-
entryLinks: arr(n.entryLinks?.entryLink).map(parseEntryLink)
|
|
199
|
-
};
|
|
200
|
-
}
|
|
201
|
-
function parseForceCategoryLink(n) {
|
|
202
|
-
return {
|
|
203
|
-
id: String(n["@_id"] ?? ""),
|
|
204
|
-
targetId: String(n["@_targetId"] ?? ""),
|
|
205
|
-
primary: bool(n["@_primary"]),
|
|
206
|
-
hidden: bool(n["@_hidden"]),
|
|
207
|
-
constraints: arr(n.constraints?.constraint).map(parseConstraint)
|
|
208
|
-
};
|
|
209
|
-
}
|
|
210
|
-
function parseForceEntry(n) {
|
|
211
|
-
return {
|
|
212
|
-
id: String(n["@_id"] ?? ""),
|
|
213
|
-
name: String(n["@_name"] ?? ""),
|
|
214
|
-
hidden: bool(n["@_hidden"]),
|
|
215
|
-
categoryLinks: arr(n.categoryLinks?.categoryLink).map(parseForceCategoryLink),
|
|
216
|
-
rules: arr(n.rules?.rule).map(parseRule),
|
|
217
|
-
modifiers: arr(n.modifiers?.modifier).map(parseModifier),
|
|
218
|
-
forceEntries: arr(n.forceEntries?.forceEntry).map(parseForceEntry)
|
|
219
|
-
};
|
|
220
|
-
}
|
|
221
|
-
function parseCatalogueLink(n) {
|
|
222
|
-
return {
|
|
223
|
-
id: String(n["@_id"] ?? ""),
|
|
224
|
-
name: String(n["@_name"] ?? ""),
|
|
225
|
-
targetId: String(n["@_targetId"] ?? ""),
|
|
226
|
-
type: String(n["@_type"] ?? ""),
|
|
227
|
-
importRootEntries: bool(n["@_importRootEntries"])
|
|
228
|
-
};
|
|
229
|
-
}
|
|
230
|
-
function parseCatalogueRoot(r) {
|
|
231
|
-
return {
|
|
232
|
-
costTypes: arr(r.costTypes?.costType).map((n) => ({
|
|
233
|
-
id: String(n["@_id"] ?? ""),
|
|
234
|
-
name: String(n["@_name"] ?? ""),
|
|
235
|
-
defaultCostLimit: Number(n["@_defaultCostLimit"] ?? -1)
|
|
236
|
-
})),
|
|
237
|
-
profileTypes: arr(r.profileTypes?.profileType).map((n) => ({
|
|
238
|
-
id: String(n["@_id"] ?? ""),
|
|
239
|
-
name: String(n["@_name"] ?? ""),
|
|
240
|
-
characteristicTypes: arr(n.characteristicTypes?.characteristicType).map((c) => ({
|
|
241
|
-
id: String(c["@_id"] ?? ""),
|
|
242
|
-
name: String(c["@_name"] ?? "")
|
|
243
|
-
}))
|
|
244
|
-
})),
|
|
245
|
-
categoryEntries: arr(r.categoryEntries?.categoryEntry).map((n) => ({
|
|
246
|
-
id: String(n["@_id"] ?? ""),
|
|
247
|
-
name: String(n["@_name"] ?? ""),
|
|
248
|
-
hidden: bool(n["@_hidden"])
|
|
249
|
-
})),
|
|
250
|
-
rules: arr(r.rules?.rule).map(parseRule),
|
|
251
|
-
sharedRules: arr(r.sharedRules?.rule).map(parseRule),
|
|
252
|
-
sharedProfiles: arr(r.sharedProfiles?.profile).map(parseProfile),
|
|
253
|
-
selectionEntries: arr(r.selectionEntries?.selectionEntry).map(parseSelectionEntry),
|
|
254
|
-
sharedSelectionEntries: arr(r.sharedSelectionEntries?.selectionEntry).map(parseSelectionEntry),
|
|
255
|
-
sharedSelectionEntryGroups: arr(r.sharedSelectionEntryGroups?.selectionEntryGroup).map(parseSelectionEntryGroup),
|
|
256
|
-
entryLinks: arr(r.entryLinks?.entryLink).map(parseEntryLink),
|
|
257
|
-
forceEntries: arr(r.forceEntries?.forceEntry).map(parseForceEntry)
|
|
258
|
-
};
|
|
259
|
-
}
|
|
260
|
-
function parseFile(filename, xml) {
|
|
261
|
-
const doc = xmlParser.parse(xml);
|
|
262
|
-
const isGst = "gameSystem" in doc;
|
|
263
|
-
const root = isGst ? doc.gameSystem : doc.catalogue;
|
|
264
|
-
const kind = isGst ? "gameSystem" : "catalogue";
|
|
265
|
-
return {
|
|
266
|
-
filename,
|
|
267
|
-
kind,
|
|
268
|
-
id: String(root["@_id"] ?? ""),
|
|
269
|
-
name: String(root["@_name"] ?? ""),
|
|
270
|
-
...root["@_gameSystemId"] != null ? { gameSystemId: String(root["@_gameSystemId"]) } : {},
|
|
271
|
-
catalogueLinks: arr(root.catalogueLinks?.catalogueLink).map(parseCatalogueLink),
|
|
272
|
-
root: parseCatalogueRoot(root)
|
|
273
|
-
};
|
|
274
|
-
}
|
|
275
|
-
|
|
276
|
-
// src/parse/index.ts
|
|
277
|
-
function parseToIr(files) {
|
|
278
|
-
const parsed = Object.entries(files).map(([filename, xml]) => parseFile(filename, xml));
|
|
279
|
-
const gameSystem = parsed.find((f) => f.kind === "gameSystem");
|
|
280
|
-
if (!gameSystem) throw new Error("parseToIr: no .gst file in source set");
|
|
281
|
-
return {
|
|
282
|
-
gameSystem,
|
|
283
|
-
catalogues: parsed.filter((f) => f.kind === "catalogue")
|
|
284
|
-
};
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
// src/project/catalogue.ts
|
|
288
|
-
function projectCatalogue(_ir) {
|
|
289
|
-
return {};
|
|
290
|
-
}
|
|
291
|
-
|
|
292
|
-
// src/index.ts
|
|
293
|
-
function buildCatalogue(files) {
|
|
294
|
-
const ir = parseToIr(files);
|
|
295
|
-
return projectCatalogue(ir);
|
|
296
|
-
}
|
|
297
|
-
export {
|
|
298
|
-
buildCatalogue,
|
|
299
|
-
parseToIr,
|
|
300
|
-
projectCatalogue
|
|
301
|
-
};
|
|
1
|
+
import { parseToIr } from './parse/index';
|
|
2
|
+
import { projectCatalogue } from './project/catalogue';
|
|
3
|
+
/**
|
|
4
|
+
* Public entry point. `filename -> XML` map in, projected output object out. The signature matches
|
|
5
|
+
* the downstream consumer's existing build step so this can be wired in incrementally (swap the
|
|
6
|
+
* import, keep the golden diff green) without touching the consumer.
|
|
7
|
+
*/
|
|
8
|
+
export function buildCatalogue(files) {
|
|
9
|
+
const ir = parseToIr(files);
|
|
10
|
+
return projectCatalogue(ir);
|
|
11
|
+
}
|
|
12
|
+
export { parseToIr } from './parse/index';
|
|
13
|
+
export { projectCatalogue } from './project/catalogue';
|
|
302
14
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/parse/xml.ts","../src/parse/index.ts","../src/project/catalogue.ts","../src/index.ts"],"sourcesContent":["import { XMLParser } from 'fast-xml-parser'\nimport type {\n IrCatalogueFile, IrCatalogueRoot,\n IrConstraint, IrCost, IrProfile, IrCharacteristic,\n IrRule, IrInfoLink, IrCategoryLink,\n IrModifier, IrCondition, IrConditionGroup, IrRepeat,\n IrSelectionEntry, IrSelectionEntryGroup, IrEntryLink,\n IrCostType, IrProfileType, IrCategoryEntry,\n IrEntryType,\n IrForceCategoryLink, IrForceEntry,\n IrCatalogueLink,\n} from '../ir/types.ts'\n\nconst ALWAYS_ARRAY = new Set([\n 'selectionEntry', 'selectionEntryGroup', 'entryLink',\n 'constraint', 'profile', 'characteristic', 'characteristicType',\n 'cost', 'costType', 'profileType',\n 'rule', 'categoryLink', 'categoryEntry',\n 'infoLink', 'modifier', 'condition', 'conditionGroup', 'repeat',\n 'forceEntry', 'catalogueLink',\n])\n\nconst xmlParser = new XMLParser({\n ignoreAttributes: false,\n attributeNamePrefix: '@_',\n textNodeName: '#text',\n isArray: (name) => ALWAYS_ARRAY.has(name),\n parseAttributeValue: true,\n})\n\n// ---- helpers ----\n\nfunction arr<T>(v: unknown): T[] {\n if (!v) return []\n if (Array.isArray(v)) return v as T[]\n return [v as T]\n}\n\nfunction bool(v: unknown): boolean {\n return v === true || v === 'true'\n}\n\n// ---- primitive node parsers ----\n\nfunction parseConstraint(n: any): IrConstraint {\n return {\n id: String(n['@_id'] ?? ''),\n type: n['@_type'] === 'min' ? 'min' : 'max',\n value: Number(n['@_value'] ?? 0),\n scope: String(n['@_scope'] ?? ''),\n field: String(n['@_field'] ?? 'selections'),\n shared: bool(n['@_shared']),\n includeChildSelections: bool(n['@_includeChildSelections']),\n }\n}\n\nfunction parseCost(n: any): IrCost {\n return {\n name: String(n['@_name'] ?? ''),\n typeId: String(n['@_typeId'] ?? ''),\n value: Number(n['@_value'] ?? 0),\n }\n}\n\nfunction parseCharacteristic(n: any): IrCharacteristic {\n const raw = n['#text']\n return {\n name: String(n['@_name'] ?? ''),\n typeId: String(n['@_typeId'] ?? ''),\n value: raw != null ? String(raw) : '',\n }\n}\n\nfunction parseProfile(n: any): IrProfile {\n return {\n id: String(n['@_id'] ?? ''),\n name: String(n['@_name'] ?? ''),\n hidden: bool(n['@_hidden']),\n typeId: String(n['@_typeId'] ?? ''),\n typeName: String(n['@_typeName'] ?? ''),\n characteristics: arr<any>(n.characteristics?.characteristic).map(parseCharacteristic),\n }\n}\n\nfunction parseRule(n: any): IrRule {\n return {\n id: String(n['@_id'] ?? ''),\n name: String(n['@_name'] ?? ''),\n hidden: bool(n['@_hidden']),\n description: n.description != null ? String(n.description) : '',\n }\n}\n\nfunction parseInfoLink(n: any): IrInfoLink {\n return {\n id: String(n['@_id'] ?? ''),\n name: String(n['@_name'] ?? ''),\n hidden: bool(n['@_hidden']),\n targetId: String(n['@_targetId'] ?? ''),\n type: String(n['@_type'] ?? ''),\n }\n}\n\nfunction parseCategoryLink(n: any): IrCategoryLink {\n return {\n id: String(n['@_id'] ?? ''),\n targetId: String(n['@_targetId'] ?? ''),\n primary: bool(n['@_primary']),\n }\n}\n\nfunction parseCondition(n: any): IrCondition {\n const out: IrCondition = {\n type: String(n['@_type'] ?? ''),\n value: Number(n['@_value'] ?? 0),\n field: String(n['@_field'] ?? ''),\n scope: String(n['@_scope'] ?? ''),\n }\n if (n['@_childId'] != null) out.childId = String(n['@_childId'])\n if (n['@_shared'] != null) out.shared = bool(n['@_shared'])\n if (n['@_includeChildSelections'] != null) out.includeChildSelections = bool(n['@_includeChildSelections'])\n if (n['@_percentValue'] != null) out.percentValue = bool(n['@_percentValue'])\n return out\n}\n\nfunction parseConditionGroup(n: any): IrConditionGroup {\n return {\n type: String(n['@_type'] ?? ''),\n conditions: arr<any>(n.conditions?.condition).map(parseCondition),\n conditionGroups: arr<any>(n.conditionGroups?.conditionGroup).map(parseConditionGroup),\n }\n}\n\nfunction parseRepeat(n: any): IrRepeat {\n const out: IrRepeat = {\n value: Number(n['@_value'] ?? 0),\n repeats: Number(n['@_repeats'] ?? 0),\n field: String(n['@_field'] ?? ''),\n scope: String(n['@_scope'] ?? ''),\n }\n if (n['@_childId'] != null) out.childId = String(n['@_childId'])\n if (n['@_shared'] != null) out.shared = bool(n['@_shared'])\n if (n['@_includeChildSelections'] != null) out.includeChildSelections = bool(n['@_includeChildSelections'])\n if (n['@_roundUp'] != null) out.roundUp = bool(n['@_roundUp'])\n return out\n}\n\nfunction parseModifier(n: any): IrModifier {\n return {\n type: String(n['@_type'] ?? ''),\n field: String(n['@_field'] ?? ''),\n value: n['@_value'] ?? '',\n conditions: arr<any>(n.conditions?.condition).map(parseCondition),\n conditionGroups: arr<any>(n.conditionGroups?.conditionGroup).map(parseConditionGroup),\n repeats: arr<any>(n.repeats?.repeat).map(parseRepeat),\n }\n}\n\n// ---- structural node parsers (mutually recursive) ----\n\nfunction parseSelectionEntry(n: any): IrSelectionEntry {\n return {\n id: String(n['@_id'] ?? ''),\n name: String(n['@_name'] ?? ''),\n hidden: bool(n['@_hidden']),\n collective: bool(n['@_collective']),\n import: bool(n['@_import']),\n type: (n['@_type'] ?? 'upgrade') as IrEntryType,\n ...(n['@_defaultAmount'] != null ? { defaultAmount: Number(n['@_defaultAmount']) } : {}),\n constraints: arr<any>(n.constraints?.constraint).map(parseConstraint),\n profiles: arr<any>(n.profiles?.profile).map(parseProfile),\n rules: arr<any>(n.rules?.rule).map(parseRule),\n infoLinks: arr<any>(n.infoLinks?.infoLink).map(parseInfoLink),\n categoryLinks: arr<any>(n.categoryLinks?.categoryLink).map(parseCategoryLink),\n costs: arr<any>(n.costs?.cost).map(parseCost),\n modifiers: arr<any>(n.modifiers?.modifier).map(parseModifier),\n selectionEntries: arr<any>(n.selectionEntries?.selectionEntry).map(parseSelectionEntry),\n selectionEntryGroups: arr<any>(n.selectionEntryGroups?.selectionEntryGroup).map(parseSelectionEntryGroup),\n entryLinks: arr<any>(n.entryLinks?.entryLink).map(parseEntryLink),\n }\n}\n\nfunction parseSelectionEntryGroup(n: any): IrSelectionEntryGroup {\n return {\n id: String(n['@_id'] ?? ''),\n name: String(n['@_name'] ?? ''),\n hidden: bool(n['@_hidden']),\n collective: bool(n['@_collective']),\n import: bool(n['@_import']),\n ...(n['@_defaultSelectionEntryId'] != null\n ? { defaultSelectionEntryId: String(n['@_defaultSelectionEntryId']) }\n : {}),\n constraints: arr<any>(n.constraints?.constraint).map(parseConstraint),\n modifiers: arr<any>(n.modifiers?.modifier).map(parseModifier),\n selectionEntries: arr<any>(n.selectionEntries?.selectionEntry).map(parseSelectionEntry),\n selectionEntryGroups: arr<any>(n.selectionEntryGroups?.selectionEntryGroup).map(parseSelectionEntryGroup),\n entryLinks: arr<any>(n.entryLinks?.entryLink).map(parseEntryLink),\n }\n}\n\nfunction parseEntryLink(n: any): IrEntryLink {\n return {\n id: String(n['@_id'] ?? ''),\n name: String(n['@_name'] ?? ''),\n hidden: bool(n['@_hidden']),\n collective: bool(n['@_collective']),\n import: bool(n['@_import']),\n targetId: String(n['@_targetId'] ?? ''),\n type: String(n['@_type'] ?? ''),\n ...(n['@_defaultAmount'] != null ? { defaultAmount: Number(n['@_defaultAmount']) } : {}),\n ...(n.comment != null ? { comment: String(n.comment).trim() } : {}),\n constraints: arr<any>(n.constraints?.constraint).map(parseConstraint),\n costs: arr<any>(n.costs?.cost).map(parseCost),\n modifiers: arr<any>(n.modifiers?.modifier).map(parseModifier),\n profiles: arr<any>(n.profiles?.profile).map(parseProfile),\n infoLinks: arr<any>(n.infoLinks?.infoLink).map(parseInfoLink),\n categoryLinks: arr<any>(n.categoryLinks?.categoryLink).map(parseCategoryLink),\n selectionEntries: arr<any>(n.selectionEntries?.selectionEntry).map(parseSelectionEntry),\n selectionEntryGroups: arr<any>(n.selectionEntryGroups?.selectionEntryGroup).map(parseSelectionEntryGroup),\n entryLinks: arr<any>(n.entryLinks?.entryLink).map(parseEntryLink),\n }\n}\n\n// ---- force entry parsers ----\n\nfunction parseForceCategoryLink(n: any): IrForceCategoryLink {\n return {\n id: String(n['@_id'] ?? ''),\n targetId: String(n['@_targetId'] ?? ''),\n primary: bool(n['@_primary']),\n hidden: bool(n['@_hidden']),\n constraints: arr<any>(n.constraints?.constraint).map(parseConstraint),\n }\n}\n\nfunction parseForceEntry(n: any): IrForceEntry {\n return {\n id: String(n['@_id'] ?? ''),\n name: String(n['@_name'] ?? ''),\n hidden: bool(n['@_hidden']),\n categoryLinks: arr<any>(n.categoryLinks?.categoryLink).map(parseForceCategoryLink),\n rules: arr<any>(n.rules?.rule).map(parseRule),\n modifiers: arr<any>(n.modifiers?.modifier).map(parseModifier),\n forceEntries: arr<any>(n.forceEntries?.forceEntry).map(parseForceEntry),\n }\n}\n\n// ---- catalogue link parser ----\n\nfunction parseCatalogueLink(n: any): IrCatalogueLink {\n return {\n id: String(n['@_id'] ?? ''),\n name: String(n['@_name'] ?? ''),\n targetId: String(n['@_targetId'] ?? ''),\n type: String(n['@_type'] ?? ''),\n importRootEntries: bool(n['@_importRootEntries']),\n }\n}\n\n// ---- catalogue root ----\n\nfunction parseCatalogueRoot(r: any): IrCatalogueRoot {\n return {\n costTypes: arr<any>(r.costTypes?.costType).map((n: any): IrCostType => ({\n id: String(n['@_id'] ?? ''),\n name: String(n['@_name'] ?? ''),\n defaultCostLimit: Number(n['@_defaultCostLimit'] ?? -1),\n })),\n profileTypes: arr<any>(r.profileTypes?.profileType).map((n: any): IrProfileType => ({\n id: String(n['@_id'] ?? ''),\n name: String(n['@_name'] ?? ''),\n characteristicTypes: arr<any>(n.characteristicTypes?.characteristicType).map((c: any) => ({\n id: String(c['@_id'] ?? ''),\n name: String(c['@_name'] ?? ''),\n })),\n })),\n categoryEntries: arr<any>(r.categoryEntries?.categoryEntry).map((n: any): IrCategoryEntry => ({\n id: String(n['@_id'] ?? ''),\n name: String(n['@_name'] ?? ''),\n hidden: bool(n['@_hidden']),\n })),\n rules: arr<any>(r.rules?.rule).map(parseRule),\n sharedRules: arr<any>(r.sharedRules?.rule).map(parseRule),\n sharedProfiles: arr<any>(r.sharedProfiles?.profile).map(parseProfile),\n selectionEntries: arr<any>(r.selectionEntries?.selectionEntry).map(parseSelectionEntry),\n sharedSelectionEntries: arr<any>(r.sharedSelectionEntries?.selectionEntry).map(parseSelectionEntry),\n sharedSelectionEntryGroups: arr<any>(r.sharedSelectionEntryGroups?.selectionEntryGroup).map(parseSelectionEntryGroup),\n entryLinks: arr<any>(r.entryLinks?.entryLink).map(parseEntryLink),\n forceEntries: arr<any>(r.forceEntries?.forceEntry).map(parseForceEntry),\n }\n}\n\n// ---- public entry ----\n\nexport function parseFile(filename: string, xml: string): IrCatalogueFile {\n const doc = xmlParser.parse(xml)\n const isGst = 'gameSystem' in doc\n const root = isGst ? doc.gameSystem : doc.catalogue\n const kind: 'gameSystem' | 'catalogue' = isGst ? 'gameSystem' : 'catalogue'\n return {\n filename,\n kind,\n id: String(root['@_id'] ?? ''),\n name: String(root['@_name'] ?? ''),\n ...(root['@_gameSystemId'] != null ? { gameSystemId: String(root['@_gameSystemId']) } : {}),\n catalogueLinks: arr<any>(root.catalogueLinks?.catalogueLink).map(parseCatalogueLink),\n root: parseCatalogueRoot(root),\n }\n}\n","import type { Ir } from '../ir/types.ts'\nimport { parseFile } from './xml.ts'\n\nexport function parseToIr(files: Record<string, string>): Ir {\n const parsed = Object.entries(files).map(([filename, xml]) => parseFile(filename, xml))\n const gameSystem = parsed.find(f => f.kind === 'gameSystem')\n if (!gameSystem) throw new Error('parseToIr: no .gst file in source set')\n return {\n gameSystem,\n catalogues: parsed.filter(f => f.kind === 'catalogue'),\n }\n}\n","import type { Ir } from '../ir/types.ts'\n\n/**\n * IR -> downstream projection.\n *\n * Projects the faithful IR into the flattened, ready-to-consume shape the downstream application\n * needs. ALL domain interpretation lives here; the IR and parser stay domain-agnostic. The concrete\n * projector and its reference data are supplied locally and are never committed to this repo (see\n * README) -- this repo ships the framework, not any specific data model.\n *\n * \"Superset\" is the contract: the projection MUST reproduce every field the reference output carries\n * (so the existing consumer keeps working unchanged), and MAY add fields the current consumer lacks.\n * The golden-diff harness asserts the reproduction half; new fields are additive and ignored.\n *\n * STUB. Supply a local implementation that imports your projector modules. The local file is\n * gitignored so it never reaches this public repo. See CLAUDE.md for the hygiene rule.\n */\nexport function projectCatalogue(_ir: Ir): Record<string, unknown> {\n return {}\n}\n","import { parseToIr } from './parse/index.ts'\nimport { projectCatalogue } from './project/catalogue.ts'\n\n/**\n * Public entry point. `filename -> XML` map in, projected output object out. The signature matches\n * the downstream consumer's existing build step so this can be wired in incrementally (swap the\n * import, keep the golden diff green) without touching the consumer.\n */\nexport function buildCatalogue(files: Record<string, string>): Record<string, unknown> {\n const ir = parseToIr(files)\n return projectCatalogue(ir)\n}\n\nexport { parseToIr } from './parse/index.ts'\nexport { projectCatalogue } from './project/catalogue.ts'\nexport type { Ir, IrCatalogueFile } from './ir/types.ts'\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA;AAEtD;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,KAA6B;IAC1D,MAAM,EAAE,GAAG,SAAS,CAAC,KAAK,CAAC,CAAA;IAC3B,OAAO,gBAAgB,CAAC,EAAE,CAAC,CAAA;AAC7B,CAAC;AAED,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AACzC,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAA"}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BSData intermediate representation (IR).
|
|
3
|
+
*
|
|
4
|
+
* A FAITHFUL, lossless-by-intent tree mirror of the BSData .gst / .cat model.
|
|
5
|
+
* Nothing is resolved, flattened, or interpreted here. Scope strings are raw BSData
|
|
6
|
+
* values. Modifier/condition trees are opaque. All interpretation belongs in the
|
|
7
|
+
* projection (src/project).
|
|
8
|
+
*/
|
|
9
|
+
export interface IrConstraint {
|
|
10
|
+
id: string;
|
|
11
|
+
type: 'min' | 'max';
|
|
12
|
+
value: number;
|
|
13
|
+
scope: string;
|
|
14
|
+
field: string;
|
|
15
|
+
shared?: boolean;
|
|
16
|
+
includeChildSelections?: boolean;
|
|
17
|
+
}
|
|
18
|
+
export interface IrCharacteristic {
|
|
19
|
+
name: string;
|
|
20
|
+
typeId: string;
|
|
21
|
+
value: string;
|
|
22
|
+
}
|
|
23
|
+
export interface IrProfile {
|
|
24
|
+
id: string;
|
|
25
|
+
name: string;
|
|
26
|
+
hidden: boolean;
|
|
27
|
+
typeId: string;
|
|
28
|
+
typeName: string;
|
|
29
|
+
characteristics: IrCharacteristic[];
|
|
30
|
+
}
|
|
31
|
+
export interface IrCost {
|
|
32
|
+
name: string;
|
|
33
|
+
typeId: string;
|
|
34
|
+
value: number;
|
|
35
|
+
}
|
|
36
|
+
export interface IrRule {
|
|
37
|
+
id: string;
|
|
38
|
+
name: string;
|
|
39
|
+
hidden: boolean;
|
|
40
|
+
description: string;
|
|
41
|
+
}
|
|
42
|
+
export interface IrInfoLink {
|
|
43
|
+
id: string;
|
|
44
|
+
name: string;
|
|
45
|
+
hidden: boolean;
|
|
46
|
+
targetId: string;
|
|
47
|
+
type: string;
|
|
48
|
+
}
|
|
49
|
+
export interface IrCategoryLink {
|
|
50
|
+
id: string;
|
|
51
|
+
targetId: string;
|
|
52
|
+
primary: boolean;
|
|
53
|
+
}
|
|
54
|
+
/** Verbatim condition node - not evaluated, retained for the modifier tree. */
|
|
55
|
+
export interface IrCondition {
|
|
56
|
+
type: string;
|
|
57
|
+
value: number;
|
|
58
|
+
field: string;
|
|
59
|
+
scope: string;
|
|
60
|
+
childId?: string;
|
|
61
|
+
shared?: boolean;
|
|
62
|
+
includeChildSelections?: boolean;
|
|
63
|
+
percentValue?: boolean;
|
|
64
|
+
}
|
|
65
|
+
export interface IrConditionGroup {
|
|
66
|
+
type: string;
|
|
67
|
+
conditions: IrCondition[];
|
|
68
|
+
conditionGroups: IrConditionGroup[];
|
|
69
|
+
}
|
|
70
|
+
/** Verbatim modifier node - not evaluated. */
|
|
71
|
+
export interface IrModifier {
|
|
72
|
+
type: string;
|
|
73
|
+
field: string;
|
|
74
|
+
value: string | number;
|
|
75
|
+
conditions: IrCondition[];
|
|
76
|
+
conditionGroups: IrConditionGroup[];
|
|
77
|
+
repeats: IrRepeat[];
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* A BSData modifierGroup node: a block of modifiers that share a common set of conditions.
|
|
81
|
+
* Equivalent to a conditional modifier block - the conditions guard when ALL the inner modifiers apply.
|
|
82
|
+
*/
|
|
83
|
+
export interface IrModifierGroup {
|
|
84
|
+
type: string;
|
|
85
|
+
modifiers: IrModifier[];
|
|
86
|
+
conditions: IrCondition[];
|
|
87
|
+
conditionGroups: IrConditionGroup[];
|
|
88
|
+
modifierGroups: IrModifierGroup[];
|
|
89
|
+
}
|
|
90
|
+
export interface IrRepeat {
|
|
91
|
+
value: number;
|
|
92
|
+
repeats: number;
|
|
93
|
+
field: string;
|
|
94
|
+
scope: string;
|
|
95
|
+
childId?: string;
|
|
96
|
+
shared?: boolean;
|
|
97
|
+
includeChildSelections?: boolean;
|
|
98
|
+
roundUp?: boolean;
|
|
99
|
+
}
|
|
100
|
+
export type IrEntryType = 'unit' | 'model' | 'upgrade' | 'mount';
|
|
101
|
+
export interface IrSelectionEntry {
|
|
102
|
+
id: string;
|
|
103
|
+
name: string;
|
|
104
|
+
hidden: boolean;
|
|
105
|
+
collective: boolean;
|
|
106
|
+
import: boolean;
|
|
107
|
+
type: IrEntryType;
|
|
108
|
+
defaultAmount?: number;
|
|
109
|
+
constraints: IrConstraint[];
|
|
110
|
+
profiles: IrProfile[];
|
|
111
|
+
rules: IrRule[];
|
|
112
|
+
infoLinks: IrInfoLink[];
|
|
113
|
+
categoryLinks: IrCategoryLink[];
|
|
114
|
+
costs: IrCost[];
|
|
115
|
+
modifiers: IrModifier[];
|
|
116
|
+
modifierGroups?: IrModifierGroup[];
|
|
117
|
+
selectionEntries: IrSelectionEntry[];
|
|
118
|
+
selectionEntryGroups: IrSelectionEntryGroup[];
|
|
119
|
+
entryLinks: IrEntryLink[];
|
|
120
|
+
}
|
|
121
|
+
export interface IrSelectionEntryGroup {
|
|
122
|
+
id: string;
|
|
123
|
+
name: string;
|
|
124
|
+
hidden: boolean;
|
|
125
|
+
collective: boolean;
|
|
126
|
+
import: boolean;
|
|
127
|
+
defaultSelectionEntryId?: string;
|
|
128
|
+
constraints: IrConstraint[];
|
|
129
|
+
modifiers: IrModifier[];
|
|
130
|
+
modifierGroups?: IrModifierGroup[];
|
|
131
|
+
selectionEntries: IrSelectionEntry[];
|
|
132
|
+
selectionEntryGroups: IrSelectionEntryGroup[];
|
|
133
|
+
entryLinks: IrEntryLink[];
|
|
134
|
+
}
|
|
135
|
+
export interface IrEntryLink {
|
|
136
|
+
id: string;
|
|
137
|
+
name: string;
|
|
138
|
+
hidden: boolean;
|
|
139
|
+
collective: boolean;
|
|
140
|
+
import: boolean;
|
|
141
|
+
flatten: boolean;
|
|
142
|
+
targetId: string;
|
|
143
|
+
type: string;
|
|
144
|
+
defaultAmount?: number;
|
|
145
|
+
comment?: string;
|
|
146
|
+
constraints: IrConstraint[];
|
|
147
|
+
costs: IrCost[];
|
|
148
|
+
modifiers: IrModifier[];
|
|
149
|
+
modifierGroups?: IrModifierGroup[];
|
|
150
|
+
profiles: IrProfile[];
|
|
151
|
+
infoLinks: IrInfoLink[];
|
|
152
|
+
categoryLinks: IrCategoryLink[];
|
|
153
|
+
selectionEntries: IrSelectionEntry[];
|
|
154
|
+
selectionEntryGroups: IrSelectionEntryGroup[];
|
|
155
|
+
entryLinks: IrEntryLink[];
|
|
156
|
+
}
|
|
157
|
+
export interface IrCategoryEntry {
|
|
158
|
+
id: string;
|
|
159
|
+
name: string;
|
|
160
|
+
hidden: boolean;
|
|
161
|
+
}
|
|
162
|
+
export interface IrForceCategoryLink {
|
|
163
|
+
id: string;
|
|
164
|
+
targetId: string;
|
|
165
|
+
primary: boolean;
|
|
166
|
+
hidden: boolean;
|
|
167
|
+
constraints: IrConstraint[];
|
|
168
|
+
}
|
|
169
|
+
export interface IrForceEntry {
|
|
170
|
+
id: string;
|
|
171
|
+
name: string;
|
|
172
|
+
hidden: boolean;
|
|
173
|
+
constraints: IrConstraint[];
|
|
174
|
+
categoryLinks: IrForceCategoryLink[];
|
|
175
|
+
rules: IrRule[];
|
|
176
|
+
modifiers: IrModifier[];
|
|
177
|
+
forceEntries: IrForceEntry[];
|
|
178
|
+
}
|
|
179
|
+
export interface IrCostType {
|
|
180
|
+
id: string;
|
|
181
|
+
name: string;
|
|
182
|
+
defaultCostLimit: number;
|
|
183
|
+
}
|
|
184
|
+
/** A BSData catalogueLink node: references another catalogue this one imports from. */
|
|
185
|
+
export interface IrCatalogueLink {
|
|
186
|
+
id: string;
|
|
187
|
+
name: string;
|
|
188
|
+
targetId: string;
|
|
189
|
+
type: string;
|
|
190
|
+
importRootEntries: boolean;
|
|
191
|
+
}
|
|
192
|
+
export interface IrProfileType {
|
|
193
|
+
id: string;
|
|
194
|
+
name: string;
|
|
195
|
+
characteristicTypes: Array<{
|
|
196
|
+
id: string;
|
|
197
|
+
name: string;
|
|
198
|
+
}>;
|
|
199
|
+
}
|
|
200
|
+
export interface IrCatalogueRoot {
|
|
201
|
+
costTypes: IrCostType[];
|
|
202
|
+
profileTypes: IrProfileType[];
|
|
203
|
+
categoryEntries: IrCategoryEntry[];
|
|
204
|
+
rules: IrRule[];
|
|
205
|
+
/** Rules from the BSData sharedRules element: the canonical rule-definition pool. */
|
|
206
|
+
sharedRules: IrRule[];
|
|
207
|
+
/** Profiles from the BSData sharedProfiles element: abilities with Summary/Description characteristics. */
|
|
208
|
+
sharedProfiles: IrProfile[];
|
|
209
|
+
selectionEntries: IrSelectionEntry[];
|
|
210
|
+
sharedSelectionEntries: IrSelectionEntry[];
|
|
211
|
+
sharedSelectionEntryGroups: IrSelectionEntryGroup[];
|
|
212
|
+
entryLinks: IrEntryLink[];
|
|
213
|
+
forceEntries: IrForceEntry[];
|
|
214
|
+
}
|
|
215
|
+
/** A single parsed BSData file (game system or catalogue). */
|
|
216
|
+
export interface IrCatalogueFile {
|
|
217
|
+
filename: string;
|
|
218
|
+
kind: 'gameSystem' | 'catalogue';
|
|
219
|
+
id: string;
|
|
220
|
+
name: string;
|
|
221
|
+
gameSystemId?: string;
|
|
222
|
+
catalogueLinks: IrCatalogueLink[];
|
|
223
|
+
root: IrCatalogueRoot;
|
|
224
|
+
}
|
|
225
|
+
/** The whole parsed source set: the game system plus every catalogue. */
|
|
226
|
+
export interface Ir {
|
|
227
|
+
gameSystem: IrCatalogueFile;
|
|
228
|
+
catalogues: IrCatalogueFile[];
|
|
229
|
+
}
|
package/dist/ir/types.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* BSData intermediate representation (IR).
|
|
3
|
+
*
|
|
4
|
+
* A FAITHFUL, lossless-by-intent tree mirror of the BSData .gst / .cat model.
|
|
5
|
+
* Nothing is resolved, flattened, or interpreted here. Scope strings are raw BSData
|
|
6
|
+
* values. Modifier/condition trees are opaque. All interpretation belongs in the
|
|
7
|
+
* projection (src/project).
|
|
8
|
+
*/
|
|
9
|
+
export {};
|
|
10
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/ir/types.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { parseFile } from './xml';
|
|
2
|
+
export function parseToIr(files) {
|
|
3
|
+
const parsed = Object.entries(files).map(([filename, xml]) => parseFile(filename, xml));
|
|
4
|
+
const gameSystem = parsed.find(f => f.kind === 'gameSystem');
|
|
5
|
+
if (!gameSystem)
|
|
6
|
+
throw new Error('parseToIr: no .gst file in source set');
|
|
7
|
+
return {
|
|
8
|
+
gameSystem,
|
|
9
|
+
catalogues: parsed.filter(f => f.kind === 'catalogue'),
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/parse/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,OAAO,CAAA;AAEjC,MAAM,UAAU,SAAS,CAAC,KAA6B;IACrD,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,QAAQ,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC,CAAA;IACvF,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,YAAY,CAAC,CAAA;IAC5D,IAAI,CAAC,UAAU;QAAE,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAA;IACzE,OAAO;QACL,UAAU;QACV,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC;KACvD,CAAA;AACH,CAAC"}
|