@nyrra/prismantix-cli 0.0.4-next.23 → 0.0.4-next.25
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 +2 -2
- package/dist/foundry-import/actions.d.ts +9 -2
- package/dist/foundry-import/actions.d.ts.map +1 -1
- package/dist/foundry-import/actions.js +436 -19
- package/dist/foundry-import/convert.d.ts.map +1 -1
- package/dist/foundry-import/convert.js +68 -4
- package/dist/foundry-import/emit.d.ts.map +1 -1
- package/dist/foundry-import/emit.js +172 -5
- package/dist/foundry-import/interfaces.d.ts +11 -2
- package/dist/foundry-import/interfaces.d.ts.map +1 -1
- package/dist/foundry-import/interfaces.js +132 -24
- package/dist/foundry-import/names.d.ts +1 -0
- package/dist/foundry-import/names.d.ts.map +1 -1
- package/dist/foundry-import/names.js +18 -0
- package/dist/foundry-import/objects.d.ts +2 -1
- package/dist/foundry-import/objects.d.ts.map +1 -1
- package/dist/foundry-import/objects.js +92 -10
- package/dist/foundry-import/parse.d.ts.map +1 -1
- package/dist/foundry-import/parse.js +520 -0
- package/dist/foundry-import/types.d.ts +78 -5
- package/dist/foundry-import/types.d.ts.map +1 -1
- package/dist/foundry-import/validate.js +15 -3
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
|
@@ -1,8 +1,14 @@
|
|
|
1
1
|
import { arrayField, isRecord } from "./utils.js";
|
|
2
|
+
const baseTypeFields = ["baseType", "dataType", "type"];
|
|
3
|
+
const dataTypeFields = ["dataType", "type"];
|
|
4
|
+
const interfaceTypeFields = ["type", "dataType", "fieldType"];
|
|
2
5
|
export function parseFoundryV2Export(input, diagnostics) {
|
|
3
6
|
if (!isRecord(input)) {
|
|
4
7
|
throw new Error("Expected a JSON object.");
|
|
5
8
|
}
|
|
9
|
+
if (isFoundryFullMetadataExport(input)) {
|
|
10
|
+
return parseFoundryFullMetadataExport(input, diagnostics);
|
|
11
|
+
}
|
|
6
12
|
const version = typeof input.version === "number" ? input.version : 0;
|
|
7
13
|
addVersionDiagnostic(version, input.version, diagnostics);
|
|
8
14
|
return {
|
|
@@ -15,6 +21,520 @@ export function parseFoundryV2Export(input, diagnostics) {
|
|
|
15
21
|
version,
|
|
16
22
|
};
|
|
17
23
|
}
|
|
24
|
+
function isFoundryFullMetadataExport(input) {
|
|
25
|
+
const objectTypes = input.objectTypes;
|
|
26
|
+
return (isRecord(objectTypes) &&
|
|
27
|
+
Object.values(objectTypes).some((value) => isRecord(value) && isRecord(value.objectType)));
|
|
28
|
+
}
|
|
29
|
+
function parseFoundryFullMetadataExport(input, diagnostics) {
|
|
30
|
+
const objectTypes = recordField(input, "objectTypes");
|
|
31
|
+
return {
|
|
32
|
+
actionTypes: recordValues(input, "actionTypes").map(fullMetadataActionType),
|
|
33
|
+
interfaces: recordValues(input, "interfaceTypes").map(fullMetadataInterface),
|
|
34
|
+
objectTypes: Object.values(objectTypes).map(fullMetadataObjectType),
|
|
35
|
+
relations: fullMetadataRelations(objectTypes, diagnostics),
|
|
36
|
+
sharedProperties: recordValues(input, "sharedPropertyTypes").map(fullMetadataSharedProperty),
|
|
37
|
+
typeGroups: arrayField(input, "typeGroups"),
|
|
38
|
+
version: 2,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function fullMetadataObjectType(value) {
|
|
42
|
+
const wrapper = isRecord(value) ? value : {};
|
|
43
|
+
const objectType = isRecord(wrapper.objectType)
|
|
44
|
+
? wrapper.objectType
|
|
45
|
+
: wrapper;
|
|
46
|
+
return {
|
|
47
|
+
aliases: stringArray(objectType.aliases),
|
|
48
|
+
apiName: stringField(objectType, "apiName"),
|
|
49
|
+
datasources: arrayField(objectType, "datasources"),
|
|
50
|
+
displayMetadata: fullMetadataDisplayMetadata(objectType),
|
|
51
|
+
interfaces: fullMetadataObjectInterfaces(wrapper),
|
|
52
|
+
interfaceImplementations: fullMetadataObjectInterfaceImplementations(wrapper),
|
|
53
|
+
primaryKeys: fullMetadataPrimaryKeys(objectType),
|
|
54
|
+
properties: recordEntries(objectType, "properties").map(([key, property]) => fullMetadataProperty(key, property)),
|
|
55
|
+
rid: stringField(objectType, "rid"),
|
|
56
|
+
status: fullMetadataStatus(objectType.status),
|
|
57
|
+
titlePropertyId: fullMetadataTitleProperty(objectType),
|
|
58
|
+
typeGroups: stringArray(objectType.typeGroups),
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function fullMetadataPrimaryKeys(objectType) {
|
|
62
|
+
const primaryKey = stringField(objectType, "primaryKey");
|
|
63
|
+
return primaryKey ? [primaryKey] : stringArray(objectType.primaryKeys);
|
|
64
|
+
}
|
|
65
|
+
function fullMetadataTitleProperty(objectType) {
|
|
66
|
+
return firstStringField(objectType, ["titleProperty", "titlePropertyId"]);
|
|
67
|
+
}
|
|
68
|
+
function fullMetadataObjectInterfaces(wrapper) {
|
|
69
|
+
const implementsInterfaces = stringArray(wrapper.implementsInterfaces);
|
|
70
|
+
if (implementsInterfaces.length > 0) {
|
|
71
|
+
return implementsInterfaces;
|
|
72
|
+
}
|
|
73
|
+
const implementsInterfaces2 = wrapper.implementsInterfaces2;
|
|
74
|
+
return isRecord(implementsInterfaces2)
|
|
75
|
+
? Object.keys(implementsInterfaces2)
|
|
76
|
+
: [];
|
|
77
|
+
}
|
|
78
|
+
function fullMetadataObjectInterfaceImplementations(wrapper) {
|
|
79
|
+
const implementsInterfaces2 = wrapper.implementsInterfaces2;
|
|
80
|
+
if (!isRecord(implementsInterfaces2)) {
|
|
81
|
+
return [];
|
|
82
|
+
}
|
|
83
|
+
return Object.entries(implementsInterfaces2).map(([interfaceApiName, implementation]) => ({
|
|
84
|
+
interfaceApiName: fullMetadataImplementationApiName(interfaceApiName, implementation),
|
|
85
|
+
propertyMappings: fullMetadataObjectInterfacePropertyMappings(implementation),
|
|
86
|
+
}));
|
|
87
|
+
}
|
|
88
|
+
function fullMetadataImplementationApiName(interfaceApiName, implementation) {
|
|
89
|
+
const record = isRecord(implementation) ? implementation : {};
|
|
90
|
+
return stringField(record, "apiName") ?? interfaceApiName;
|
|
91
|
+
}
|
|
92
|
+
function fullMetadataObjectInterfacePropertyMappings(implementation) {
|
|
93
|
+
const record = isRecord(implementation) ? implementation : {};
|
|
94
|
+
const propertiesV2 = recordField(record, "propertiesV2");
|
|
95
|
+
const v2Entries = Object.entries(propertiesV2).flatMap(([interfacePropertyApiName, mapping]) => {
|
|
96
|
+
const objectPropertyApiName = fullMetadataPropertyMappingTarget(mapping);
|
|
97
|
+
return objectPropertyApiName
|
|
98
|
+
? [{ interfacePropertyApiName, objectPropertyApiName }]
|
|
99
|
+
: [];
|
|
100
|
+
});
|
|
101
|
+
if (v2Entries.length > 0) {
|
|
102
|
+
return v2Entries;
|
|
103
|
+
}
|
|
104
|
+
return recordEntries(record, "properties").flatMap(([interfacePropertyApiName, objectPropertyApiName]) => typeof objectPropertyApiName === "string"
|
|
105
|
+
? [{ interfacePropertyApiName, objectPropertyApiName }]
|
|
106
|
+
: []);
|
|
107
|
+
}
|
|
108
|
+
function fullMetadataPropertyMappingTarget(mapping) {
|
|
109
|
+
if (typeof mapping === "string") {
|
|
110
|
+
return mapping;
|
|
111
|
+
}
|
|
112
|
+
const record = isRecord(mapping) ? mapping : {};
|
|
113
|
+
return (stringField(record, "propertyApiName") ??
|
|
114
|
+
stringField(record, "propertyTypeRid"));
|
|
115
|
+
}
|
|
116
|
+
function fullMetadataProperty(apiName, value) {
|
|
117
|
+
const property = isRecord(value) ? value : {};
|
|
118
|
+
return {
|
|
119
|
+
apiName: stringFieldWithFallback(property, "apiName", apiName),
|
|
120
|
+
baseFormatter: property.baseFormatter,
|
|
121
|
+
baseType: fullMetadataBaseType(firstPresentValue(property, baseTypeFields)),
|
|
122
|
+
dataConstraints: dataConstraints(property),
|
|
123
|
+
displayMetadata: fullMetadataDisplayMetadata(property),
|
|
124
|
+
id: stringFieldWithFallback(property, "id", apiName),
|
|
125
|
+
indexedForSearch: booleanField(property, "indexedForSearch"),
|
|
126
|
+
renderHints: renderHints(property),
|
|
127
|
+
rid: stringField(property, "rid"),
|
|
128
|
+
source: recordOrUndefined(property.source),
|
|
129
|
+
status: fullMetadataStatus(property.status),
|
|
130
|
+
typeClasses: arrayField(property, "typeClasses"),
|
|
131
|
+
valueType: fullMetadataValueType(property),
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
function fullMetadataActionType(value) {
|
|
135
|
+
const action = isRecord(value) ? value : {};
|
|
136
|
+
const operations = arrayField(action, "operations").map(fullMetadataActionOperation);
|
|
137
|
+
return {
|
|
138
|
+
actionTypeLogic: {
|
|
139
|
+
logic: {
|
|
140
|
+
rules: operations.map((operation) => ({
|
|
141
|
+
objectTypeApiName: operation.objectTypeApiName,
|
|
142
|
+
type: operation.type,
|
|
143
|
+
})),
|
|
144
|
+
},
|
|
145
|
+
},
|
|
146
|
+
metadata: {
|
|
147
|
+
apiName: stringField(action, "apiName"),
|
|
148
|
+
displayMetadata: fullMetadataDisplayMetadata(action),
|
|
149
|
+
formContentInOrder: recordEntries(action, "parameters").map(([id, parameter]) => ({
|
|
150
|
+
parameter: fullMetadataActionParameter(id, parameter),
|
|
151
|
+
type: "parameter",
|
|
152
|
+
})),
|
|
153
|
+
rid: stringField(action, "rid"),
|
|
154
|
+
status: fullMetadataStatus(action.status),
|
|
155
|
+
},
|
|
156
|
+
operations,
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
function fullMetadataActionOperation(value) {
|
|
160
|
+
const operation = isRecord(value) ? value : {};
|
|
161
|
+
return {
|
|
162
|
+
objectTypeApiName: stringField(operation, "objectTypeApiName"),
|
|
163
|
+
type: stringField(operation, "type"),
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
function fullMetadataActionParameter(id, value) {
|
|
167
|
+
const parameter = isRecord(value) ? value : {};
|
|
168
|
+
return {
|
|
169
|
+
displayMetadata: fullMetadataDisplayMetadata(parameter),
|
|
170
|
+
id,
|
|
171
|
+
required: booleanField(parameter, "required"),
|
|
172
|
+
type: fullMetadataBaseType(firstPresentValue(parameter, dataTypeFields)),
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
function fullMetadataInterface(value) {
|
|
176
|
+
const interfaceType = isRecord(value) ? value : {};
|
|
177
|
+
return {
|
|
178
|
+
apiName: stringField(interfaceType, "apiName"),
|
|
179
|
+
displayMetadata: fullMetadataDisplayMetadata(interfaceType),
|
|
180
|
+
extendsInterfaces: stringArray(interfaceType.extendsInterfaces),
|
|
181
|
+
links: recordOrArrayEntries(interfaceType.links).map(([key, link]) => fullMetadataInterfaceLink(key, link)),
|
|
182
|
+
properties: recordOrArrayEntries(interfaceType.properties).map(([key, property]) => fullMetadataInterfaceProperty(key, property)),
|
|
183
|
+
rid: stringField(interfaceType, "rid"),
|
|
184
|
+
searchable: booleanField(interfaceType, "searchable"),
|
|
185
|
+
status: fullMetadataStatus(interfaceType.status),
|
|
186
|
+
};
|
|
187
|
+
}
|
|
188
|
+
function fullMetadataInterfaceProperty(apiName, value) {
|
|
189
|
+
const property = isRecord(value) ? value : {};
|
|
190
|
+
return {
|
|
191
|
+
apiName: stringFieldWithFallback(property, "apiName", apiName),
|
|
192
|
+
displayName: stringField(property, "displayName"),
|
|
193
|
+
isSharedProperty: booleanField(property, "isSharedProperty"),
|
|
194
|
+
required: firstBooleanField(property, [
|
|
195
|
+
"required",
|
|
196
|
+
"requireImplementation",
|
|
197
|
+
]),
|
|
198
|
+
sharedPropertyRid: stringField(property, "sharedPropertyRid"),
|
|
199
|
+
type: fullMetadataBaseType(firstPresentValue(property, interfaceTypeFields)),
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
function fullMetadataInterfaceLink(apiName, value) {
|
|
203
|
+
const link = isRecord(value) ? value : {};
|
|
204
|
+
const linkedEntity = isRecord(link.linkedEntityApiName)
|
|
205
|
+
? link.linkedEntityApiName
|
|
206
|
+
: {};
|
|
207
|
+
return {
|
|
208
|
+
apiName: stringFieldWithFallback(link, "apiName", apiName),
|
|
209
|
+
cardinality: stringField(link, "cardinality"),
|
|
210
|
+
description: nullableStringField(link, "description") ?? undefined,
|
|
211
|
+
displayName: stringField(link, "displayName"),
|
|
212
|
+
linkedEntityApiName: stringField(linkedEntity, "apiName"),
|
|
213
|
+
linkedEntityType: stringField(linkedEntity, "type"),
|
|
214
|
+
required: booleanField(link, "required"),
|
|
215
|
+
rid: stringField(link, "rid"),
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
function fullMetadataSharedProperty(value) {
|
|
219
|
+
const property = isRecord(value) ? value : {};
|
|
220
|
+
return {
|
|
221
|
+
aliases: stringArray(property.aliases),
|
|
222
|
+
apiName: stringField(property, "apiName"),
|
|
223
|
+
baseType: fullMetadataBaseType(firstPresentValue(property, baseTypeFields)),
|
|
224
|
+
dataConstraints: dataConstraints(property),
|
|
225
|
+
displayMetadata: fullMetadataDisplayMetadata(property),
|
|
226
|
+
indexedForSearch: booleanField(property, "indexedForSearch"),
|
|
227
|
+
renderHints: renderHints(property),
|
|
228
|
+
rid: stringField(property, "rid"),
|
|
229
|
+
valueType: fullMetadataValueType(property),
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
function fullMetadataRelations(objectTypes, diagnostics) {
|
|
233
|
+
const groups = fullMetadataLinkGroups(objectTypes);
|
|
234
|
+
return [...groups.entries()].flatMap(([relationRid, links], relationIndex) => fullMetadataRelation(relationRid, links, relationIndex, diagnostics));
|
|
235
|
+
}
|
|
236
|
+
function fullMetadataLinkGroups(objectTypes) {
|
|
237
|
+
const groups = new Map();
|
|
238
|
+
for (const value of Object.values(objectTypes)) {
|
|
239
|
+
addFullMetadataObjectLinks(groups, value);
|
|
240
|
+
}
|
|
241
|
+
return groups;
|
|
242
|
+
}
|
|
243
|
+
function addFullMetadataObjectLinks(groups, value) {
|
|
244
|
+
const wrapper = isRecord(value) ? value : {};
|
|
245
|
+
const context = fullMetadataLinkContext(wrapper);
|
|
246
|
+
if (!context) {
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
for (const link of arrayField(wrapper, "linkTypes")) {
|
|
250
|
+
addFullMetadataLink(groups, context, link);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
function addFullMetadataLink(groups, context, value) {
|
|
254
|
+
const linkRecord = isRecord(value) ? value : {};
|
|
255
|
+
const relationRid = fullMetadataRelationRid(context.sourceApiName, linkRecord);
|
|
256
|
+
const group = groups.get(relationRid) ?? [];
|
|
257
|
+
group.push({ link: linkRecord, ...context });
|
|
258
|
+
groups.set(relationRid, group);
|
|
259
|
+
}
|
|
260
|
+
function fullMetadataLinkContext(wrapper) {
|
|
261
|
+
const objectType = fullMetadataWrappedObjectType(wrapper);
|
|
262
|
+
const sourceApiName = stringField(objectType, "apiName");
|
|
263
|
+
const sourceRid = stringField(objectType, "rid");
|
|
264
|
+
return sourceApiName && sourceRid ? { sourceApiName, sourceRid } : undefined;
|
|
265
|
+
}
|
|
266
|
+
function fullMetadataRelationRid(sourceApiName, link) {
|
|
267
|
+
return (stringField(link, "linkTypeRid") ??
|
|
268
|
+
`${sourceApiName}:${stringFieldWithFallback(link, "apiName", "link")}`);
|
|
269
|
+
}
|
|
270
|
+
function fullMetadataRelation(relationRid, links, relationIndex, diagnostics) {
|
|
271
|
+
if (links.length !== 2) {
|
|
272
|
+
diagnostics.push({
|
|
273
|
+
code: "skipped.fullMetadataLinkGroup",
|
|
274
|
+
message: `Foundry full-metadata link group ${relationRid} has ${links.length} sides; expected 2.`,
|
|
275
|
+
path: `$.objectTypes.*.linkTypes[${relationIndex}]`,
|
|
276
|
+
severity: "warning",
|
|
277
|
+
});
|
|
278
|
+
return [];
|
|
279
|
+
}
|
|
280
|
+
const foreignKeySide = links.find((link) => Boolean(stringField(link.link, "foreignKeyPropertyApiName")));
|
|
281
|
+
if (foreignKeySide) {
|
|
282
|
+
return fullMetadataOneToManyRelation(relationRid, links, foreignKeySide);
|
|
283
|
+
}
|
|
284
|
+
return [fullMetadataManyToManyRelation(relationRid, linkPair(links))];
|
|
285
|
+
}
|
|
286
|
+
function fullMetadataManyToManyRelation(relationRid, [a, b]) {
|
|
287
|
+
return {
|
|
288
|
+
definition: {
|
|
289
|
+
manyToMany: {
|
|
290
|
+
objectTypeAToBLinkMetadata: fullMetadataLinkMetadata(a.link),
|
|
291
|
+
objectTypeBToALinkMetadata: fullMetadataLinkMetadata(b.link),
|
|
292
|
+
objectTypeRidA: a.sourceRid,
|
|
293
|
+
objectTypeRidB: b.sourceRid,
|
|
294
|
+
},
|
|
295
|
+
type: "manyToMany",
|
|
296
|
+
},
|
|
297
|
+
id: relationRid,
|
|
298
|
+
rid: relationRid,
|
|
299
|
+
status: fullMetadataStatus(firstPresentValueFromList([a.link, b.link], "status")),
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
function fullMetadataOneToManyRelation(relationRid, links, foreignKeySide) {
|
|
303
|
+
const oneSide = links.find((link) => link !== foreignKeySide);
|
|
304
|
+
if (!oneSide) {
|
|
305
|
+
return [];
|
|
306
|
+
}
|
|
307
|
+
return [
|
|
308
|
+
{
|
|
309
|
+
definition: {
|
|
310
|
+
oneToMany: {
|
|
311
|
+
cardinalityHint: stringField(oneSide.link, "cardinality") === "ONE"
|
|
312
|
+
? "ONE_TO_ONE"
|
|
313
|
+
: "ONE_TO_MANY",
|
|
314
|
+
manySideForeignKeyPropertyId: stringField(foreignKeySide.link, "foreignKeyPropertyApiName"),
|
|
315
|
+
manyToOneLinkMetadata: fullMetadataLinkMetadata(foreignKeySide.link),
|
|
316
|
+
objectTypeRidManySide: foreignKeySide.sourceRid,
|
|
317
|
+
objectTypeRidOneSide: oneSide.sourceRid,
|
|
318
|
+
oneToManyLinkMetadata: fullMetadataLinkMetadata(oneSide.link),
|
|
319
|
+
},
|
|
320
|
+
type: "oneToMany",
|
|
321
|
+
},
|
|
322
|
+
id: relationRid,
|
|
323
|
+
rid: relationRid,
|
|
324
|
+
status: fullMetadataStatus(foreignKeySide.link.status ?? oneSide.link.status),
|
|
325
|
+
},
|
|
326
|
+
];
|
|
327
|
+
}
|
|
328
|
+
function fullMetadataLinkMetadata(link) {
|
|
329
|
+
return {
|
|
330
|
+
apiName: stringField(link, "apiName"),
|
|
331
|
+
displayMetadata: fullMetadataDisplayMetadata(link),
|
|
332
|
+
typeClasses: arrayField(link, "typeClasses"),
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
function fullMetadataWrappedObjectType(value) {
|
|
336
|
+
const wrapper = isRecord(value) ? value : {};
|
|
337
|
+
return isRecord(wrapper.objectType) ? wrapper.objectType : wrapper;
|
|
338
|
+
}
|
|
339
|
+
function fullMetadataBaseType(value) {
|
|
340
|
+
const record = recordOrUndefined(value);
|
|
341
|
+
return record ? fullMetadataBaseTypeFromRecord(record) : undefined;
|
|
342
|
+
}
|
|
343
|
+
function fullMetadataBaseTypeFromRecord(value) {
|
|
344
|
+
const type = stringField(value, "type");
|
|
345
|
+
return type
|
|
346
|
+
? typedFullMetadataBaseType(value, type)
|
|
347
|
+
: value;
|
|
348
|
+
}
|
|
349
|
+
function typedFullMetadataBaseType(value, type) {
|
|
350
|
+
const normalizedType = normalizeFullMetadataType(type);
|
|
351
|
+
return {
|
|
352
|
+
...value,
|
|
353
|
+
...fullMetadataBaseTypeExtras(value, normalizedType),
|
|
354
|
+
type: normalizedType,
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
function fullMetadataBaseTypeExtras(value, type) {
|
|
358
|
+
const extras = {
|
|
359
|
+
ARRAY: () => ({ subType: fullMetadataBaseType(value.subType) }),
|
|
360
|
+
STRUCT: () => ({
|
|
361
|
+
structFields: recordOrArrayValues(value.fields).map((field) => fullMetadataStructField(field)),
|
|
362
|
+
}),
|
|
363
|
+
};
|
|
364
|
+
return extras[type]?.() ?? {};
|
|
365
|
+
}
|
|
366
|
+
function fullMetadataStructField(value) {
|
|
367
|
+
const field = isRecord(value) ? value : {};
|
|
368
|
+
return {
|
|
369
|
+
apiName: stringField(field, "apiName") ?? stringField(field, "name"),
|
|
370
|
+
displayMetadata: fullMetadataDisplayMetadata(field),
|
|
371
|
+
fieldType: fullMetadataBaseType(field.fieldType ?? field.dataType),
|
|
372
|
+
};
|
|
373
|
+
}
|
|
374
|
+
function normalizeFullMetadataType(type) {
|
|
375
|
+
const typeMap = {
|
|
376
|
+
array: "ARRAY",
|
|
377
|
+
attachment: "ATTACHMENT",
|
|
378
|
+
boolean: "BOOLEAN",
|
|
379
|
+
date: "DATE",
|
|
380
|
+
double: "DOUBLE",
|
|
381
|
+
geohash: "GEOHASH",
|
|
382
|
+
geopoint: "GEOHASH",
|
|
383
|
+
geoshape: "GEOSHAPE",
|
|
384
|
+
integer: "INTEGER",
|
|
385
|
+
long: "LONG",
|
|
386
|
+
marking: "MARKING",
|
|
387
|
+
mediaReference: "MEDIA_REFERENCE",
|
|
388
|
+
string: "STRING",
|
|
389
|
+
struct: "STRUCT",
|
|
390
|
+
timestamp: "TIMESTAMP",
|
|
391
|
+
vector: "VECTOR",
|
|
392
|
+
};
|
|
393
|
+
return typeMap[type] ?? type;
|
|
394
|
+
}
|
|
395
|
+
function fullMetadataStatus(value) {
|
|
396
|
+
const type = fullMetadataStatusType(value);
|
|
397
|
+
return type
|
|
398
|
+
? { ...fullMetadataStatusRecord(value), type: type.toLowerCase() }
|
|
399
|
+
: undefined;
|
|
400
|
+
}
|
|
401
|
+
function fullMetadataStatusRecord(value) {
|
|
402
|
+
return isRecord(value) ? value : {};
|
|
403
|
+
}
|
|
404
|
+
function fullMetadataStatusType(value) {
|
|
405
|
+
return typeof value === "string"
|
|
406
|
+
? nonEmptyString(value)
|
|
407
|
+
: stringField(fullMetadataStatusRecord(value), "type");
|
|
408
|
+
}
|
|
409
|
+
function fullMetadataDisplayMetadata(record) {
|
|
410
|
+
const nested = recordOrUndefined(record.displayMetadata);
|
|
411
|
+
return nested ? nested : displayMetadataFromTopLevelFields(record);
|
|
412
|
+
}
|
|
413
|
+
function displayMetadataFromTopLevelFields(record) {
|
|
414
|
+
const displayMetadata = {
|
|
415
|
+
description: nullableStringField(record, "description"),
|
|
416
|
+
displayName: nullableStringField(record, "displayName"),
|
|
417
|
+
groupDisplayName: nullableStringField(record, "groupDisplayName"),
|
|
418
|
+
icon: definedValue(record.icon),
|
|
419
|
+
pluralDisplayName: nullableStringField(record, "pluralDisplayName"),
|
|
420
|
+
visibility: nullableStringField(record, "visibility"),
|
|
421
|
+
};
|
|
422
|
+
const compact = compactRecord(displayMetadata);
|
|
423
|
+
return Object.keys(compact).length > 0
|
|
424
|
+
? compact
|
|
425
|
+
: undefined;
|
|
426
|
+
}
|
|
427
|
+
function linkPair(links) {
|
|
428
|
+
return [links[0], links[1]];
|
|
429
|
+
}
|
|
430
|
+
function fullMetadataValueType(record) {
|
|
431
|
+
const explicit = record.valueType;
|
|
432
|
+
return explicit === undefined ? valueTypeReference(record) : explicit;
|
|
433
|
+
}
|
|
434
|
+
function firstPresentValue(record, keys) {
|
|
435
|
+
for (const key of keys) {
|
|
436
|
+
const value = record[key];
|
|
437
|
+
if (value !== undefined) {
|
|
438
|
+
return value;
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
return undefined;
|
|
442
|
+
}
|
|
443
|
+
function firstPresentValueFromList(records, key) {
|
|
444
|
+
for (const record of records) {
|
|
445
|
+
const value = record[key];
|
|
446
|
+
if (value !== undefined) {
|
|
447
|
+
return value;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
return undefined;
|
|
451
|
+
}
|
|
452
|
+
function firstStringField(record, keys) {
|
|
453
|
+
for (const key of keys) {
|
|
454
|
+
const value = stringField(record, key);
|
|
455
|
+
if (value) {
|
|
456
|
+
return value;
|
|
457
|
+
}
|
|
458
|
+
}
|
|
459
|
+
return undefined;
|
|
460
|
+
}
|
|
461
|
+
function firstBooleanField(record, keys) {
|
|
462
|
+
for (const key of keys) {
|
|
463
|
+
const value = booleanField(record, key);
|
|
464
|
+
if (value !== undefined) {
|
|
465
|
+
return value;
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
return undefined;
|
|
469
|
+
}
|
|
470
|
+
function stringFieldWithFallback(record, key, fallback) {
|
|
471
|
+
return stringField(record, key) ?? fallback;
|
|
472
|
+
}
|
|
473
|
+
function recordOrUndefined(value) {
|
|
474
|
+
return isRecord(value) ? value : undefined;
|
|
475
|
+
}
|
|
476
|
+
function nonEmptyString(value) {
|
|
477
|
+
return value === "" ? undefined : value;
|
|
478
|
+
}
|
|
479
|
+
function nullableStringField(record, key) {
|
|
480
|
+
const value = record[key];
|
|
481
|
+
return typeof value === "string" || value === null ? value : undefined;
|
|
482
|
+
}
|
|
483
|
+
function definedValue(value) {
|
|
484
|
+
return value === undefined ? undefined : value;
|
|
485
|
+
}
|
|
486
|
+
function compactRecord(record) {
|
|
487
|
+
return Object.fromEntries(Object.entries(record).filter((entry) => entry[1] !== undefined));
|
|
488
|
+
}
|
|
489
|
+
function dataConstraints(record) {
|
|
490
|
+
return isRecord(record.dataConstraints) ? record.dataConstraints : undefined;
|
|
491
|
+
}
|
|
492
|
+
function valueTypeReference(record) {
|
|
493
|
+
const valueTypeApiName = stringField(record, "valueTypeApiName");
|
|
494
|
+
return valueTypeApiName ? { apiName: valueTypeApiName } : undefined;
|
|
495
|
+
}
|
|
496
|
+
function renderHints(record) {
|
|
497
|
+
const explicit = stringArray(record.renderHints);
|
|
498
|
+
if (explicit.length > 0) {
|
|
499
|
+
return explicit;
|
|
500
|
+
}
|
|
501
|
+
return arrayField(record, "typeClasses").flatMap((typeClass) => typeClass.kind === "render_hint" && typeClass.name ? [typeClass.name] : []);
|
|
502
|
+
}
|
|
503
|
+
function recordField(record, key) {
|
|
504
|
+
const value = record[key];
|
|
505
|
+
return isRecord(value) ? value : {};
|
|
506
|
+
}
|
|
507
|
+
function recordValues(record, key) {
|
|
508
|
+
return Object.values(recordField(record, key));
|
|
509
|
+
}
|
|
510
|
+
function recordEntries(record, key) {
|
|
511
|
+
return Object.entries(recordField(record, key));
|
|
512
|
+
}
|
|
513
|
+
function recordOrArrayValues(value) {
|
|
514
|
+
if (Array.isArray(value)) {
|
|
515
|
+
return value;
|
|
516
|
+
}
|
|
517
|
+
return isRecord(value) ? Object.values(value) : [];
|
|
518
|
+
}
|
|
519
|
+
function recordOrArrayEntries(value) {
|
|
520
|
+
if (Array.isArray(value)) {
|
|
521
|
+
return value.map((item, index) => [String(index), item]);
|
|
522
|
+
}
|
|
523
|
+
return isRecord(value) ? Object.entries(value) : [];
|
|
524
|
+
}
|
|
525
|
+
function stringField(record, key) {
|
|
526
|
+
const value = record[key];
|
|
527
|
+
return typeof value === "string" && value !== "" ? value : undefined;
|
|
528
|
+
}
|
|
529
|
+
function booleanField(record, key) {
|
|
530
|
+
const value = record[key];
|
|
531
|
+
return typeof value === "boolean" ? value : undefined;
|
|
532
|
+
}
|
|
533
|
+
function stringArray(value) {
|
|
534
|
+
return Array.isArray(value)
|
|
535
|
+
? value.filter((item) => typeof item === "string")
|
|
536
|
+
: [];
|
|
537
|
+
}
|
|
18
538
|
function addVersionDiagnostic(version, rawVersion, diagnostics) {
|
|
19
539
|
if (version === 2) {
|
|
20
540
|
return;
|
|
@@ -71,6 +71,7 @@ export interface FoundryObjectType {
|
|
|
71
71
|
readonly displayMetadata?: FoundryDisplayMetadata;
|
|
72
72
|
readonly id?: string;
|
|
73
73
|
readonly interfaces?: readonly string[];
|
|
74
|
+
readonly interfaceImplementations?: readonly FoundryObjectInterfaceImplementation[];
|
|
74
75
|
readonly primaryKeys?: readonly string[];
|
|
75
76
|
readonly properties?: readonly FoundryProperty[];
|
|
76
77
|
readonly rid?: string;
|
|
@@ -79,6 +80,14 @@ export interface FoundryObjectType {
|
|
|
79
80
|
readonly typeGroups?: readonly string[];
|
|
80
81
|
readonly [key: string]: unknown;
|
|
81
82
|
}
|
|
83
|
+
export interface FoundryObjectInterfaceImplementation {
|
|
84
|
+
readonly interfaceApiName: string;
|
|
85
|
+
readonly propertyMappings: readonly FoundryObjectInterfacePropertyMapping[];
|
|
86
|
+
}
|
|
87
|
+
export interface FoundryObjectInterfacePropertyMapping {
|
|
88
|
+
readonly interfacePropertyApiName: string;
|
|
89
|
+
readonly objectPropertyApiName: string;
|
|
90
|
+
}
|
|
82
91
|
export interface FoundryLinkMetadata {
|
|
83
92
|
readonly apiName?: string;
|
|
84
93
|
readonly displayMetadata?: FoundryDisplayMetadata;
|
|
@@ -121,17 +130,25 @@ export interface FoundryRelation {
|
|
|
121
130
|
export interface FoundryActionParameter {
|
|
122
131
|
readonly displayMetadata?: FoundryDisplayMetadata;
|
|
123
132
|
readonly id?: string;
|
|
133
|
+
readonly required?: boolean;
|
|
124
134
|
readonly type?: {
|
|
125
135
|
readonly type?: string;
|
|
126
136
|
readonly [key: string]: unknown;
|
|
127
137
|
};
|
|
138
|
+
readonly validation?: unknown;
|
|
139
|
+
}
|
|
140
|
+
export interface FoundryActionRule {
|
|
141
|
+
readonly [key: string]: unknown;
|
|
142
|
+
readonly type?: string;
|
|
143
|
+
}
|
|
144
|
+
export interface FoundryActionOperation {
|
|
145
|
+
readonly objectTypeApiName?: string;
|
|
146
|
+
readonly type?: string;
|
|
128
147
|
}
|
|
129
148
|
export interface FoundryActionType {
|
|
130
149
|
readonly actionTypeLogic?: {
|
|
131
150
|
readonly logic?: {
|
|
132
|
-
readonly rules?: readonly
|
|
133
|
-
readonly type?: string;
|
|
134
|
-
}[];
|
|
151
|
+
readonly rules?: readonly FoundryActionRule[];
|
|
135
152
|
};
|
|
136
153
|
};
|
|
137
154
|
readonly metadata?: {
|
|
@@ -144,19 +161,31 @@ export interface FoundryActionType {
|
|
|
144
161
|
readonly rid?: string;
|
|
145
162
|
readonly status?: FoundryStatus;
|
|
146
163
|
};
|
|
164
|
+
readonly operations?: readonly FoundryActionOperation[];
|
|
147
165
|
}
|
|
148
166
|
export interface FoundryInterfaceProperty {
|
|
167
|
+
readonly apiName?: string;
|
|
149
168
|
readonly displayName?: string;
|
|
150
169
|
readonly isSharedProperty?: boolean;
|
|
151
170
|
readonly required?: boolean;
|
|
152
171
|
readonly sharedPropertyRid?: string;
|
|
153
172
|
readonly type?: FoundryBaseType;
|
|
154
173
|
}
|
|
174
|
+
export interface FoundryInterfaceLink {
|
|
175
|
+
readonly apiName?: string;
|
|
176
|
+
readonly cardinality?: string;
|
|
177
|
+
readonly description?: string;
|
|
178
|
+
readonly displayName?: string;
|
|
179
|
+
readonly linkedEntityApiName?: string;
|
|
180
|
+
readonly linkedEntityType?: string;
|
|
181
|
+
readonly required?: boolean;
|
|
182
|
+
readonly rid?: string;
|
|
183
|
+
}
|
|
155
184
|
export interface FoundryInterface {
|
|
156
185
|
readonly apiName?: string;
|
|
157
186
|
readonly displayMetadata?: FoundryDisplayMetadata;
|
|
158
187
|
readonly extendsInterfaces?: readonly string[];
|
|
159
|
-
readonly links?: readonly
|
|
188
|
+
readonly links?: readonly FoundryInterfaceLink[];
|
|
160
189
|
readonly properties?: readonly FoundryInterfaceProperty[];
|
|
161
190
|
readonly rid?: string;
|
|
162
191
|
readonly searchable?: boolean;
|
|
@@ -202,6 +231,8 @@ export interface NormalizedObject {
|
|
|
202
231
|
readonly apiName: NamePair;
|
|
203
232
|
readonly description?: string;
|
|
204
233
|
readonly displayName: string;
|
|
234
|
+
readonly id?: string;
|
|
235
|
+
readonly interfaceImplementations: readonly NormalizedObjectInterfaceImplementation[];
|
|
205
236
|
readonly pluralDisplayName: string;
|
|
206
237
|
readonly primaryKeyPropertyApiName: string;
|
|
207
238
|
readonly properties: readonly NormalizedProperty[];
|
|
@@ -211,6 +242,15 @@ export interface NormalizedObject {
|
|
|
211
242
|
readonly titlePropertyApiName: string;
|
|
212
243
|
readonly variableName: string;
|
|
213
244
|
}
|
|
245
|
+
export interface NormalizedObjectInterfaceImplementation {
|
|
246
|
+
readonly interfaceApiName: NamePair;
|
|
247
|
+
readonly interfaceVariableName: string;
|
|
248
|
+
readonly propertyMappings: readonly NormalizedObjectInterfacePropertyMapping[];
|
|
249
|
+
}
|
|
250
|
+
export interface NormalizedObjectInterfacePropertyMapping {
|
|
251
|
+
readonly interfacePropertyApiName: string;
|
|
252
|
+
readonly objectPropertyApiName: string;
|
|
253
|
+
}
|
|
214
254
|
export interface NormalizedSharedProperty {
|
|
215
255
|
readonly apiName: NamePair;
|
|
216
256
|
readonly array: boolean;
|
|
@@ -230,11 +270,34 @@ export interface NormalizedInterface {
|
|
|
230
270
|
readonly apiName: NamePair;
|
|
231
271
|
readonly description?: string;
|
|
232
272
|
readonly displayName: string;
|
|
273
|
+
readonly extendsInterfaces: readonly NormalizedInterfaceReference[];
|
|
274
|
+
readonly links: readonly NormalizedInterfaceLink[];
|
|
275
|
+
readonly properties: readonly NormalizedInterfaceProperty[];
|
|
233
276
|
readonly rid?: string;
|
|
234
277
|
readonly searchable: boolean;
|
|
235
278
|
readonly status?: string;
|
|
236
279
|
readonly variableName: string;
|
|
237
280
|
}
|
|
281
|
+
export interface NormalizedInterfaceReference {
|
|
282
|
+
readonly apiName: NamePair;
|
|
283
|
+
readonly variableName: string;
|
|
284
|
+
}
|
|
285
|
+
export interface NormalizedInterfaceProperty {
|
|
286
|
+
readonly apiName: NamePair;
|
|
287
|
+
readonly displayName: string;
|
|
288
|
+
readonly required: boolean;
|
|
289
|
+
readonly sharedPropertyVariableName?: string;
|
|
290
|
+
readonly type?: unknown;
|
|
291
|
+
}
|
|
292
|
+
export interface NormalizedInterfaceLink {
|
|
293
|
+
readonly apiName: NamePair;
|
|
294
|
+
readonly cardinality: "MANY" | "SINGLE";
|
|
295
|
+
readonly description?: string;
|
|
296
|
+
readonly displayName: string;
|
|
297
|
+
readonly required?: boolean;
|
|
298
|
+
readonly targetApiName: NamePair;
|
|
299
|
+
readonly targetVariableName: string;
|
|
300
|
+
}
|
|
238
301
|
export interface NormalizedRelation {
|
|
239
302
|
readonly apiName: NamePair;
|
|
240
303
|
readonly definition: unknown;
|
|
@@ -246,9 +309,19 @@ export interface NormalizedRelation {
|
|
|
246
309
|
export interface NormalizedAction {
|
|
247
310
|
readonly apiName: NamePair;
|
|
248
311
|
readonly displayName: string;
|
|
249
|
-
readonly
|
|
312
|
+
readonly parameters: readonly NormalizedActionParameter[];
|
|
250
313
|
readonly ruleTypes: readonly string[];
|
|
314
|
+
readonly rules: readonly unknown[];
|
|
251
315
|
readonly status?: string;
|
|
316
|
+
readonly variableName: string;
|
|
317
|
+
}
|
|
318
|
+
export interface NormalizedActionParameter {
|
|
319
|
+
readonly description?: string;
|
|
320
|
+
readonly displayName: string;
|
|
321
|
+
readonly id: NamePair;
|
|
322
|
+
readonly required: boolean;
|
|
323
|
+
readonly type: unknown;
|
|
324
|
+
readonly validationAllowedValues: unknown;
|
|
252
325
|
}
|
|
253
326
|
export interface NormalizedTypeGroup {
|
|
254
327
|
readonly displayName: string;
|