@ifc-lite/semantic 0.1.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.
- package/LICENSE +373 -0
- package/README.md +22 -0
- package/dist/bsdd.d.ts +40 -0
- package/dist/bsdd.d.ts.map +1 -0
- package/dist/bsdd.js +53 -0
- package/dist/bsdd.js.map +1 -0
- package/dist/dictionary.d.ts +26 -0
- package/dist/dictionary.d.ts.map +1 -0
- package/dist/dictionary.js +36 -0
- package/dist/dictionary.js.map +1 -0
- package/dist/graph-import.d.ts +11 -0
- package/dist/graph-import.d.ts.map +1 -0
- package/dist/graph-import.js +79 -0
- package/dist/graph-import.js.map +1 -0
- package/dist/graph.d.ts +4 -0
- package/dist/graph.d.ts.map +1 -0
- package/dist/graph.js +29 -0
- package/dist/graph.js.map +1 -0
- package/dist/index.d.ts +15 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +13 -0
- package/dist/index.js.map +1 -0
- package/dist/profile-artifacts.d.ts +104 -0
- package/dist/profile-artifacts.d.ts.map +1 -0
- package/dist/profile-artifacts.js +123 -0
- package/dist/profile-artifacts.js.map +1 -0
- package/dist/profile-index.d.ts +15 -0
- package/dist/profile-index.d.ts.map +1 -0
- package/dist/profile-index.js +11 -0
- package/dist/profile-index.js.map +1 -0
- package/dist/profile-types.d.ts +21 -0
- package/dist/profile-types.d.ts.map +1 -0
- package/dist/profile-types.js +5 -0
- package/dist/profile-types.js.map +1 -0
- package/dist/profiles.d.ts +38 -0
- package/dist/profiles.d.ts.map +1 -0
- package/dist/profiles.js +174 -0
- package/dist/profiles.js.map +1 -0
- package/dist/projection.d.ts +8 -0
- package/dist/projection.d.ts.map +1 -0
- package/dist/projection.js +70 -0
- package/dist/projection.js.map +1 -0
- package/dist/provider.d.ts +35 -0
- package/dist/provider.d.ts.map +1 -0
- package/dist/provider.js +98 -0
- package/dist/provider.js.map +1 -0
- package/dist/query.d.ts +7 -0
- package/dist/query.d.ts.map +1 -0
- package/dist/query.js +57 -0
- package/dist/query.js.map +1 -0
- package/dist/resolver.d.ts +56 -0
- package/dist/resolver.d.ts.map +1 -0
- package/dist/resolver.js +89 -0
- package/dist/resolver.js.map +1 -0
- package/dist/results.d.ts +14 -0
- package/dist/results.d.ts.map +1 -0
- package/dist/results.js +73 -0
- package/dist/results.js.map +1 -0
- package/dist/server-listener.d.ts +5 -0
- package/dist/server-listener.d.ts.map +1 -0
- package/dist/server-listener.js +46 -0
- package/dist/server-listener.js.map +1 -0
- package/dist/server.d.ts +21 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +141 -0
- package/dist/server.js.map +1 -0
- package/dist/shacl-parameters.d.ts +6 -0
- package/dist/shacl-parameters.d.ts.map +1 -0
- package/dist/shacl-parameters.js +65 -0
- package/dist/shacl-parameters.js.map +1 -0
- package/dist/shacl-targets.d.ts +12 -0
- package/dist/shacl-targets.d.ts.map +1 -0
- package/dist/shacl-targets.js +114 -0
- package/dist/shacl-targets.js.map +1 -0
- package/dist/types.d.ts +40 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +19 -0
- package/dist/types.js.map +1 -0
- package/dist/validation-report.d.ts +35 -0
- package/dist/validation-report.d.ts.map +1 -0
- package/dist/validation-report.js +20 -0
- package/dist/validation-report.js.map +1 -0
- package/dist/validation.d.ts +26 -0
- package/dist/validation.d.ts.map +1 -0
- package/dist/validation.js +201 -0
- package/dist/validation.js.map +1 -0
- package/dist/workspace.d.ts +32 -0
- package/dist/workspace.d.ts.map +1 -0
- package/dist/workspace.js +140 -0
- package/dist/workspace.js.map +1 -0
- package/package.json +52 -0
package/dist/profiles.js
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
/** Technology-neutral profile. This is the only source for exchange and graph constraints. */
|
|
5
|
+
import { isObject, GUID_PATTERN, assertIri } from './types.js';
|
|
6
|
+
export { GUID_PATTERN } from './types.js';
|
|
7
|
+
export const PROFILE_ID = 'https://example.org/ifc-lite/semantic-pilot/v1';
|
|
8
|
+
export const VOCAB = 'https://example.org/ifc-lite/semantic-pilot#';
|
|
9
|
+
export const RESOURCE_TYPES = ['Building', 'Logbook', 'Installation', 'Product', 'Passport', 'Inspection'];
|
|
10
|
+
const iri = (name, targetType) => ({ iri: VOCAB + name, kind: 'iri', targetType });
|
|
11
|
+
const common = ['label', 'dictionaryUri', 'evidenceId'];
|
|
12
|
+
const type = (name, extra, required) => ({ iri: VOCAB + name,
|
|
13
|
+
fields: Object.fromEntries([...common, ...extra].map(key => [key, { maxCount: 1, minCount: key === 'label' || required.includes(key) ? 1 : 0 }])) });
|
|
14
|
+
export const DEFAULT_PROFILE = {
|
|
15
|
+
id: PROFILE_ID, version: '1.0.0', vocabulary: VOCAB,
|
|
16
|
+
fields: {
|
|
17
|
+
label: { iri: VOCAB + 'label', kind: 'string' },
|
|
18
|
+
buildingId: iri('buildingId', 'Building'), productId: iri('productId', 'Product'), passportId: iri('passportId', 'Passport'),
|
|
19
|
+
installationId: iri('installationId', 'Installation'), replacesId: iri('replacesId', 'Installation'),
|
|
20
|
+
evidenceId: { ...iri('evidenceId'), external: true }, dictionaryUri: { ...iri('dictionaryUri'), external: true },
|
|
21
|
+
modelRevision: { ...iri('modelRevision'), external: true }, GlobalId: { iri: VOCAB + 'GlobalId', kind: 'string', pattern: GUID_PATTERN },
|
|
22
|
+
granularity: { iri: VOCAB + 'granularity', kind: 'string', enum: ['model', 'batch', 'item'] }, fireRating: { iri: VOCAB + 'fireRating', kind: 'string' },
|
|
23
|
+
thermalTransmittance: { iri: VOCAB + 'thermalTransmittance', kind: 'number', minimum: 0, unit: 'W/(m2.K)' },
|
|
24
|
+
},
|
|
25
|
+
types: {
|
|
26
|
+
Building: type('Building', [], []), Logbook: type('Logbook', ['buildingId'], ['buildingId']),
|
|
27
|
+
Installation: type('Installation', ['buildingId', 'productId', 'replacesId', 'GlobalId', 'modelRevision'], ['buildingId', 'productId']),
|
|
28
|
+
Product: type('Product', ['passportId', 'granularity', 'fireRating', 'thermalTransmittance'], ['granularity']),
|
|
29
|
+
Passport: type('Passport', ['productId', 'granularity', 'fireRating', 'thermalTransmittance'], ['productId', 'granularity']),
|
|
30
|
+
Inspection: type('Inspection', ['installationId'], ['installationId']),
|
|
31
|
+
},
|
|
32
|
+
};
|
|
33
|
+
export function isUri(value) {
|
|
34
|
+
try {
|
|
35
|
+
assertIri(value);
|
|
36
|
+
return true;
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return false;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/** Shared bounded pattern policy for both profile-generated and imported shapes. */
|
|
43
|
+
export function assertBoundedPattern(pattern, location) {
|
|
44
|
+
// Several optional/ranged repetitions can backtrack combinatorially even
|
|
45
|
+
// without groups. Count actual quantifiers, ignoring escapes and classes.
|
|
46
|
+
let variableRepetitions = 0;
|
|
47
|
+
let inClass = false;
|
|
48
|
+
let alternation = false;
|
|
49
|
+
for (let index = 0; index < pattern.length; index++) {
|
|
50
|
+
const character = pattern[index];
|
|
51
|
+
if (character === '\\') {
|
|
52
|
+
// XPath/SPARQL and JavaScript assign different alphabets to shorthand
|
|
53
|
+
// and property classes. Require explicit ranges, including in classes.
|
|
54
|
+
if ('dDwWsSpP'.includes(pattern[index + 1] ?? '\0'))
|
|
55
|
+
throw new Error(`Pattern for ${location} requires explicit character ranges instead of shorthand or property classes`);
|
|
56
|
+
index++;
|
|
57
|
+
continue;
|
|
58
|
+
}
|
|
59
|
+
if (inClass) {
|
|
60
|
+
if (character === ']')
|
|
61
|
+
inClass = false;
|
|
62
|
+
continue;
|
|
63
|
+
}
|
|
64
|
+
if (character === '[') {
|
|
65
|
+
inClass = true;
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
if (character === '|')
|
|
69
|
+
alternation = true;
|
|
70
|
+
if ('+*?'.includes(character))
|
|
71
|
+
variableRepetitions++;
|
|
72
|
+
if (character === '{') {
|
|
73
|
+
const range = /^\{(\d+)(?:,(\d+))?\}/.exec(pattern.slice(index));
|
|
74
|
+
if (range) {
|
|
75
|
+
if (range[2] !== undefined && Number(range[1]) !== Number(range[2]))
|
|
76
|
+
variableRepetitions++;
|
|
77
|
+
index += range[0].length - 1;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
if (pattern.length > 256 || /[()]|\\[1-9]/.test(pattern) || /[{}]/.test(pattern.replace(/\{[0-9]+(?:,[0-9]+)?\}/g, ''))
|
|
82
|
+
|| variableRepetitions > 1 || variableRepetitions > 0 && (!pattern.startsWith('^') || alternation)
|
|
83
|
+
|| [...pattern.matchAll(/\{([0-9]+)(?:,([0-9]+))?\}/g)].some(match => Number(match[1]) > 5000 || Number(match[2] ?? 0) > 5000)) {
|
|
84
|
+
throw new Error(`Pattern for ${location} exceeds the supported bounded regular-expression subset`);
|
|
85
|
+
}
|
|
86
|
+
new RegExp(pattern, 'u');
|
|
87
|
+
}
|
|
88
|
+
/** Validate profiles before compiling schemas or executing graph validation. */
|
|
89
|
+
export function assertProfile(value) {
|
|
90
|
+
if (!isObject(value) || typeof value.id !== 'string' || typeof value.vocabulary !== 'string'
|
|
91
|
+
|| typeof value.version !== 'string' || !isObject(value.fields) || !isObject(value.types))
|
|
92
|
+
throw new Error('Profile requires id, version, vocabulary, fields and types');
|
|
93
|
+
const closed = (object, allowed, location) => {
|
|
94
|
+
const unknown = Object.keys(object).find(key => !allowed.includes(key));
|
|
95
|
+
if (unknown)
|
|
96
|
+
throw new Error(`Unsupported profile member ${location}.${unknown}`);
|
|
97
|
+
};
|
|
98
|
+
closed(value, ['id', 'version', 'vocabulary', 'fields', 'types'], 'profile');
|
|
99
|
+
const labels = (candidate) => candidate === undefined || isObject(candidate) && Object.values(candidate).every(label => typeof label === 'string');
|
|
100
|
+
for (const [name, field] of Object.entries(value.fields)) {
|
|
101
|
+
if (!isObject(field) || typeof field.iri !== 'string' || typeof field.kind !== 'string'
|
|
102
|
+
|| !labels(field.labels) || field.enum !== undefined && (!Array.isArray(field.enum) || field.enum.some(item => !['string', 'number', 'boolean'].includes(typeof item)))
|
|
103
|
+
|| field.pattern !== undefined && typeof field.pattern !== 'string' || field.minimum !== undefined && typeof field.minimum !== 'number'
|
|
104
|
+
|| field.maximum !== undefined && typeof field.maximum !== 'number' || field.unit !== undefined && typeof field.unit !== 'string'
|
|
105
|
+
|| field.targetType !== undefined && typeof field.targetType !== 'string' || field.external !== undefined && typeof field.external !== 'boolean')
|
|
106
|
+
throw new Error('Invalid profile field definition');
|
|
107
|
+
closed(field, ['iri', 'kind', 'labels', 'enum', 'pattern', 'minimum', 'maximum', 'unit', 'targetType', 'external'], `field ${name}`);
|
|
108
|
+
}
|
|
109
|
+
for (const [name, definition] of Object.entries(value.types)) {
|
|
110
|
+
if (!isObject(definition) || typeof definition.iri !== 'string' || !isObject(definition.fields) || !labels(definition.labels))
|
|
111
|
+
throw new Error('Invalid profile type definition');
|
|
112
|
+
closed(definition, ['iri', 'labels', 'fields'], `type ${name}`);
|
|
113
|
+
for (const [key, count] of Object.entries(definition.fields)) {
|
|
114
|
+
if (!isObject(count) || count.minCount !== undefined && typeof count.minCount !== 'number'
|
|
115
|
+
|| count.maxCount !== undefined && typeof count.maxCount !== 'number')
|
|
116
|
+
throw new Error('Invalid profile cardinality');
|
|
117
|
+
closed(count, ['minCount', 'maxCount'], `${name}.${key}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
const profile = value;
|
|
121
|
+
if (!isUri(profile.id) || !isUri(profile.vocabulary) || !profile.version)
|
|
122
|
+
throw new Error('Profile requires absolute identifiers and a version');
|
|
123
|
+
if (!Object.keys(profile.types).length || Object.keys(profile.types).length > 100 || Object.keys(profile.fields).length > 500)
|
|
124
|
+
throw new Error('Profile exceeds the 100 type / 500 field limit');
|
|
125
|
+
const terms = new Set();
|
|
126
|
+
for (const [name, field] of Object.entries(profile.fields)) {
|
|
127
|
+
if (['id', 'type', '__proto__', 'constructor', 'prototype'].includes(name) || !isUri(field.iri) || terms.has(field.iri))
|
|
128
|
+
throw new Error(`Invalid or duplicate profile field: ${name}`);
|
|
129
|
+
terms.add(field.iri);
|
|
130
|
+
if (!['string', 'number', 'integer', 'boolean', 'iri', 'language'].includes(field.kind))
|
|
131
|
+
throw new Error(`Unsupported field kind: ${name}`);
|
|
132
|
+
if (field.pattern && !['string', 'iri'].includes(field.kind))
|
|
133
|
+
throw new Error(`Pattern requires a string field: ${name}`);
|
|
134
|
+
if ((field.minimum !== undefined || field.maximum !== undefined) && !['number', 'integer'].includes(field.kind))
|
|
135
|
+
throw new Error(`Range requires a numeric field: ${name}`);
|
|
136
|
+
if (field.pattern)
|
|
137
|
+
assertBoundedPattern(field.pattern, name);
|
|
138
|
+
if (field.enum && (!field.enum.length || field.enum.length > 1000))
|
|
139
|
+
throw new Error(`Invalid enum: ${name}`);
|
|
140
|
+
if (field.enum?.some(value => field.kind === 'iri' ? typeof value !== 'string' || !isUri(value)
|
|
141
|
+
: field.kind === 'integer' ? typeof value !== 'number' || !Number.isSafeInteger(value)
|
|
142
|
+
: field.kind === 'number' ? typeof value !== 'number' || !Number.isFinite(value)
|
|
143
|
+
: field.kind === 'language' || typeof value !== field.kind))
|
|
144
|
+
throw new Error(`Enum values do not match field kind: ${name}`);
|
|
145
|
+
if (field.minimum !== undefined && !Number.isFinite(field.minimum) || field.maximum !== undefined && !Number.isFinite(field.maximum))
|
|
146
|
+
throw new Error(`Non-finite range: ${name}`);
|
|
147
|
+
if (field.minimum !== undefined && field.maximum !== undefined && field.minimum > field.maximum)
|
|
148
|
+
throw new Error(`Inverted range: ${name}`);
|
|
149
|
+
if (field.kind === 'integer' && (field.minimum !== undefined && !Number.isSafeInteger(field.minimum)
|
|
150
|
+
|| field.maximum !== undefined && !Number.isSafeInteger(field.maximum)))
|
|
151
|
+
throw new Error(`Integer profile ranges must use JavaScript safe integers: ${name}`);
|
|
152
|
+
if (field.targetType && (!Object.hasOwn(profile.types, field.targetType) || field.kind !== 'iri'))
|
|
153
|
+
throw new Error(`Invalid target type: ${name}`);
|
|
154
|
+
}
|
|
155
|
+
for (const [name, definition] of Object.entries(profile.types)) {
|
|
156
|
+
if (!isUri(definition.iri) || terms.has(definition.iri) || ['id', 'type', '__proto__', 'constructor', 'prototype'].includes(name) || Object.hasOwn(profile.fields, name))
|
|
157
|
+
throw new Error(`Invalid type: ${name}`);
|
|
158
|
+
if (!definition.fields.label || profile.fields.label?.kind !== 'string'
|
|
159
|
+
|| definition.fields.label.minCount !== 1 || (definition.fields.label.maxCount ?? 1) !== 1)
|
|
160
|
+
throw new Error(`Type ${name} requires exactly one common string label field`);
|
|
161
|
+
terms.add(definition.iri);
|
|
162
|
+
for (const [key, count] of Object.entries(definition.fields)) {
|
|
163
|
+
if (!Object.hasOwn(profile.fields, key))
|
|
164
|
+
throw new Error(`Unknown field ${key} on ${name}`);
|
|
165
|
+
const min = count.minCount ?? 0;
|
|
166
|
+
const max = count.maxCount ?? 1;
|
|
167
|
+
if (!Number.isInteger(min) || !Number.isInteger(max) || min < 0 || max < min || max < 1 || max > 5000)
|
|
168
|
+
throw new Error(`Invalid cardinality: ${name}.${key}`);
|
|
169
|
+
if (profile.fields[key].kind === 'language' && (max !== 1 || min > 1))
|
|
170
|
+
throw new Error(`Language maps use one value per language: ${name}.${key}`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=profiles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profiles.js","sourceRoot":"","sources":["../src/profiles.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type ProfileDefinition } from './profiles.js';
|
|
2
|
+
import type { SemanticDocument } from './profile-types.js';
|
|
3
|
+
import type { SparqlResults } from './types.js';
|
|
4
|
+
export type BindingMapping = Record<string, string>;
|
|
5
|
+
export declare const DEFAULT_MAPPING: BindingMapping;
|
|
6
|
+
/** Explicit profile projection; raw SELECT rows remain the authoritative lossless data. */
|
|
7
|
+
export declare function resourcesFromResults(results: SparqlResults, source: string, mapping?: BindingMapping, profile?: ProfileDefinition): SemanticDocument;
|
|
8
|
+
//# sourceMappingURL=projection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projection.d.ts","sourceRoot":"","sources":["../src/projection.ts"],"names":[],"mappings":"AAIA,OAAO,EAAmB,KAAK,iBAAiB,EAAE,MAAM,eAAe,CAAC;AACxE,OAAO,KAAK,EAAoB,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC7E,OAAO,KAAK,EAAc,aAAa,EAAE,MAAM,YAAY,CAAC;AAE5D,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;AACpD,eAAO,MAAM,eAAe,EAAE,cAAiH,CAAC;AAsBhJ,2FAA2F;AAC3F,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,cAAgC,EACpH,OAAO,GAAE,iBAAmC,GAAG,gBAAgB,CAqBhE"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
import { DEFAULT_PROFILE } from './profiles.js';
|
|
5
|
+
import { documentOf } from './validation.js';
|
|
6
|
+
export const DEFAULT_MAPPING = { id: 'id', type: 'type', label: 'label', GlobalId: 'GlobalId', modelRevision: 'modelRevision' };
|
|
7
|
+
const XSD = 'http://www.w3.org/2001/XMLSchema#';
|
|
8
|
+
function projected(term, kind, field) {
|
|
9
|
+
if (kind === 'iri') {
|
|
10
|
+
if (term.type !== 'uri')
|
|
11
|
+
throw new Error(`Expected IRI: ${field}`);
|
|
12
|
+
return term.value;
|
|
13
|
+
}
|
|
14
|
+
if (term.type !== 'literal')
|
|
15
|
+
throw new Error(`Expected literal: ${field}`);
|
|
16
|
+
if (kind === 'language') {
|
|
17
|
+
if (!term['xml:lang'])
|
|
18
|
+
throw new Error(`Expected language-tagged literal: ${field}`);
|
|
19
|
+
return { [term['xml:lang']]: term.value };
|
|
20
|
+
}
|
|
21
|
+
if (term['xml:lang'])
|
|
22
|
+
throw new Error(`Profile string cannot discard language: ${field}`);
|
|
23
|
+
if (kind === 'string') {
|
|
24
|
+
if (term.datatype && term.datatype !== XSD + 'string')
|
|
25
|
+
throw new Error(`Expected string datatype: ${field}`);
|
|
26
|
+
return term.value;
|
|
27
|
+
}
|
|
28
|
+
if (kind === 'boolean') {
|
|
29
|
+
if (term.datatype !== XSD + 'boolean' || !['true', 'false', '1', '0'].includes(term.value))
|
|
30
|
+
throw new Error(`Expected boolean: ${field}`);
|
|
31
|
+
return term.value === 'true' || term.value === '1';
|
|
32
|
+
}
|
|
33
|
+
if (!term.datatype || ![XSD + 'integer', XSD + 'decimal', XSD + 'double', XSD + 'float'].includes(term.datatype)
|
|
34
|
+
|| !term.value.trim() || !Number.isFinite(Number(term.value)) || (kind === 'integer' && !Number.isSafeInteger(Number(term.value))))
|
|
35
|
+
throw new Error(`Expected bounded numeric literal: ${field}`);
|
|
36
|
+
return Number(term.value);
|
|
37
|
+
}
|
|
38
|
+
/** Explicit profile projection; raw SELECT rows remain the authoritative lossless data. */
|
|
39
|
+
export function resourcesFromResults(results, source, mapping = DEFAULT_MAPPING, profile = DEFAULT_PROFILE) {
|
|
40
|
+
const records = new Map();
|
|
41
|
+
for (const row of results.rows) {
|
|
42
|
+
const id = row[mapping.id ?? 'id'];
|
|
43
|
+
const type = row[mapping.type ?? 'type'];
|
|
44
|
+
const label = row[mapping.label ?? 'label'];
|
|
45
|
+
if (id?.type !== 'uri' || !type || type.type === 'bnode' || label?.type !== 'literal')
|
|
46
|
+
throw new Error('Project resource id, type and label columns explicitly');
|
|
47
|
+
const typeName = type.type === 'uri' ? Object.keys(profile.types).find(key => profile.types[key].iri === type.value) : type.value;
|
|
48
|
+
if (!typeName || !Object.hasOwn(profile.types, typeName))
|
|
49
|
+
throw new Error(`Unsupported profile type: ${type.value}`);
|
|
50
|
+
const projectedLabel = projected(label, 'string', 'label');
|
|
51
|
+
if (typeof projectedLabel !== 'string')
|
|
52
|
+
throw new Error('Label must be a profile string');
|
|
53
|
+
const record = { id: id.value, type: typeName, label: projectedLabel };
|
|
54
|
+
for (const key of Object.keys(profile.types[typeName].fields)) {
|
|
55
|
+
if (key === 'label')
|
|
56
|
+
continue;
|
|
57
|
+
const term = row[mapping[key] ?? key];
|
|
58
|
+
if (!term)
|
|
59
|
+
continue;
|
|
60
|
+
const value = projected(term, profile.fields[key].kind, key);
|
|
61
|
+
record[key] = (profile.types[typeName].fields[key].maxCount ?? 1) > 1 ? [value] : value;
|
|
62
|
+
}
|
|
63
|
+
const existing = records.get(record.id);
|
|
64
|
+
if (existing && JSON.stringify(existing) !== JSON.stringify(record))
|
|
65
|
+
throw new Error(`Conflicting profile rows for ${record.id}; raw dataset is preserved, aggregate projection explicitly`);
|
|
66
|
+
records.set(record.id, record);
|
|
67
|
+
}
|
|
68
|
+
return documentOf([...records.values()], source, profile);
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=projection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"projection.js","sourceRoot":"","sources":["../src/projection.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type FetchTransport } from '@ifc-lite/sandbox/network';
|
|
2
|
+
import { type SparqlResults } from './types.js';
|
|
3
|
+
export interface ProviderReadOptions {
|
|
4
|
+
endpoint: string;
|
|
5
|
+
host: string;
|
|
6
|
+
kind: 'json' | 'select' | 'construct';
|
|
7
|
+
query?: string;
|
|
8
|
+
bearer?: string;
|
|
9
|
+
authorizedGraphs?: readonly string[];
|
|
10
|
+
relayProvider?: string;
|
|
11
|
+
timeoutMs?: number;
|
|
12
|
+
maxBytes?: number;
|
|
13
|
+
}
|
|
14
|
+
export type ProviderResult = {
|
|
15
|
+
source: string;
|
|
16
|
+
retrievedAt: string;
|
|
17
|
+
} & ({
|
|
18
|
+
kind: 'json';
|
|
19
|
+
value: unknown;
|
|
20
|
+
} | {
|
|
21
|
+
kind: 'select';
|
|
22
|
+
value: SparqlResults;
|
|
23
|
+
} | {
|
|
24
|
+
kind: 'construct';
|
|
25
|
+
value: string;
|
|
26
|
+
format: 'text/turtle';
|
|
27
|
+
quadCount: number;
|
|
28
|
+
});
|
|
29
|
+
export interface SemanticProvider {
|
|
30
|
+
read(options: ProviderReadOptions, signal?: AbortSignal): Promise<ProviderResult>;
|
|
31
|
+
}
|
|
32
|
+
export declare function createSemanticProvider(transport?: FetchTransport): SemanticProvider;
|
|
33
|
+
/** Compatibility helper for existing JSON/SELECT integrations. Credentials are never persisted. */
|
|
34
|
+
export declare function request(endpoint: string, host: string, signal?: AbortSignal, query?: string, transport?: FetchTransport, options?: Pick<ProviderReadOptions, 'bearer' | 'authorizedGraphs' | 'relayProvider'>): Promise<unknown>;
|
|
35
|
+
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"AAIA,OAAO,EAAsB,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAKpF,OAAO,EAAU,KAAK,aAAa,EAAE,MAAM,YAAY,CAAC;AACxD,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,WAAW,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACtF,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACtH;AACD,MAAM,MAAM,cAAc,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GAAG,CACnE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,aAAa,CAAA;CAAE,GAC3E;IAAE,IAAI,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,aAAa,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,CAAC;AACpF,MAAM,WAAW,gBAAgB;IAAG,IAAI,CAAC,OAAO,EAAE,mBAAmB,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,cAAc,CAAC,CAAA;CAAE;AAYvH,wBAAgB,sBAAsB,CAAC,SAAS,CAAC,EAAE,cAAc,GAAG,gBAAgB,CAuCnF;AACD,mGAAmG;AACnG,wBAAsB,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,WAAW,EAAE,KAAK,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,cAAc,EAC5H,OAAO,GAAE,IAAI,CAAC,mBAAmB,EAAE,QAAQ,GAAG,kBAAkB,GAAG,eAAe,CAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAK5G"}
|
package/dist/provider.js
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
import { coreNetworkRequest } from '@ifc-lite/sandbox/network';
|
|
5
|
+
import { parseCapability } from '@ifc-lite/extensions';
|
|
6
|
+
import { Parser as RdfParser } from 'n3';
|
|
7
|
+
import { assertReadOnlyQuery } from './query.js';
|
|
8
|
+
import { parseResults } from './results.js';
|
|
9
|
+
import { LIMITS } from './types.js';
|
|
10
|
+
/** Inspect decoded strings and keys so JSON escapes cannot conceal a credential. */
|
|
11
|
+
function assertNoCredential(value, bearer) {
|
|
12
|
+
if (!bearer)
|
|
13
|
+
return;
|
|
14
|
+
const pending = [value];
|
|
15
|
+
while (pending.length) {
|
|
16
|
+
const item = pending.pop();
|
|
17
|
+
if (typeof item === 'string' && item.includes(bearer))
|
|
18
|
+
throw new Error('Provider response contained a credential');
|
|
19
|
+
if (Array.isArray(item))
|
|
20
|
+
for (const nested of item)
|
|
21
|
+
pending.push(nested);
|
|
22
|
+
else if (item !== null && typeof item === 'object')
|
|
23
|
+
for (const [key, nested] of Object.entries(item))
|
|
24
|
+
pending.push(key, nested);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
export function createSemanticProvider(transport) {
|
|
28
|
+
return { async read(options, signal) {
|
|
29
|
+
const timeoutMs = options.timeoutMs ?? LIMITS.timeoutMs;
|
|
30
|
+
const maxBytes = options.maxBytes ?? LIMITS.bytes;
|
|
31
|
+
if (!Number.isInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > 60000 || !Number.isInteger(maxBytes) || maxBytes < 1 || maxBytes > LIMITS.bytes)
|
|
32
|
+
throw new Error('Invalid semantic provider limits');
|
|
33
|
+
if (options.relayProvider !== undefined && !/^[A-Za-z0-9_-]{1,80}$/.test(options.relayProvider))
|
|
34
|
+
throw new Error('Invalid relay provider id');
|
|
35
|
+
const capability = parseCapability(`network.fetch:${options.host}`);
|
|
36
|
+
if (!capability.ok)
|
|
37
|
+
throw new Error('Enter a valid explicitly granted hostname');
|
|
38
|
+
const endpoint = new URL(options.endpoint);
|
|
39
|
+
if (endpoint.username || endpoint.password || endpoint.search || endpoint.hash)
|
|
40
|
+
throw new Error('Endpoint credentials must be supplied separately; query parameters and fragments are disabled');
|
|
41
|
+
if (options.kind !== 'json' && (!options.query || assertReadOnlyQuery(options.query, options.authorizedGraphs) !== options.kind))
|
|
42
|
+
throw new Error('Query kind does not match provider request');
|
|
43
|
+
if (options.bearer !== undefined && (!options.bearer || /[\r\n]/u.test(options.bearer)))
|
|
44
|
+
throw new Error('Invalid bearer credential');
|
|
45
|
+
const headers = { Accept: options.kind === 'construct' ? 'text/turtle' : options.kind === 'select' ? 'application/sparql-results+json' : 'application/json' };
|
|
46
|
+
if (options.bearer)
|
|
47
|
+
headers.Authorization = `Bearer ${options.bearer}`;
|
|
48
|
+
if (options.relayProvider)
|
|
49
|
+
headers['Content-Type'] = 'application/json';
|
|
50
|
+
else if (options.kind !== 'json')
|
|
51
|
+
headers['Content-Type'] = 'application/x-www-form-urlencoded';
|
|
52
|
+
const response = await coreNetworkRequest({ url: endpoint.href, method: options.relayProvider || options.kind !== 'json' ? 'POST' : 'GET', headers,
|
|
53
|
+
body: options.relayProvider ? JSON.stringify({ providerId: options.relayProvider, kind: options.kind, query: options.query })
|
|
54
|
+
: options.kind === 'json' ? undefined : new URLSearchParams({ query: options.query }).toString(),
|
|
55
|
+
signal, maxBytes, timeoutMs }, [capability.value], transport);
|
|
56
|
+
if (response.status < 200 || response.status >= 300)
|
|
57
|
+
throw new Error(`Endpoint returned HTTP ${response.status}`);
|
|
58
|
+
if (response.truncated)
|
|
59
|
+
throw new Error('Endpoint response exceeded semantic byte limit');
|
|
60
|
+
if (options.bearer && response.body.includes(options.bearer))
|
|
61
|
+
throw new Error('Provider response contained a credential');
|
|
62
|
+
const contentType = Object.entries(response.headers).find(([name]) => name.toLowerCase() === 'content-type')?.[1].split(';')[0].trim().toLowerCase();
|
|
63
|
+
const allowedContent = options.kind === 'construct' ? ['text/turtle'] : options.kind === 'select' ? ['application/sparql-results+json', 'application/json'] : ['application/json', 'application/ld+json'];
|
|
64
|
+
if (!contentType || !allowedContent.includes(contentType))
|
|
65
|
+
throw new Error('Unsupported semantic provider content type');
|
|
66
|
+
const source = new URL(endpoint.href);
|
|
67
|
+
source.search = '';
|
|
68
|
+
source.hash = '';
|
|
69
|
+
const provenance = { source: source.href, retrievedAt: new Date().toISOString() };
|
|
70
|
+
if (options.kind === 'construct') {
|
|
71
|
+
const quads = new RdfParser({ format: 'text/turtle' }).parse(response.body);
|
|
72
|
+
if (quads.length > LIMITS.quads)
|
|
73
|
+
throw new Error('CONSTRUCT response exceeded quad limit');
|
|
74
|
+
if (options.bearer)
|
|
75
|
+
for (const quad of quads)
|
|
76
|
+
assertNoCredential([quad.subject.value, quad.predicate.value, quad.object.value, quad.graph.value], options.bearer);
|
|
77
|
+
return { ...provenance, kind: 'construct', value: response.body, format: 'text/turtle', quadCount: quads.length };
|
|
78
|
+
}
|
|
79
|
+
let value;
|
|
80
|
+
try {
|
|
81
|
+
value = JSON.parse(response.body);
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
throw new Error('Invalid semantic provider JSON');
|
|
85
|
+
}
|
|
86
|
+
assertNoCredential(value, options.bearer);
|
|
87
|
+
return options.kind === 'select' ? { ...provenance, kind: 'select', value: parseResults(value) } : { ...provenance, kind: 'json', value };
|
|
88
|
+
} };
|
|
89
|
+
}
|
|
90
|
+
/** Compatibility helper for existing JSON/SELECT integrations. Credentials are never persisted. */
|
|
91
|
+
export async function request(endpoint, host, signal, query, transport, options = {}) {
|
|
92
|
+
const kind = query === undefined ? 'json' : assertReadOnlyQuery(query, options.authorizedGraphs);
|
|
93
|
+
const result = await createSemanticProvider(transport).read({ endpoint, host, kind, query, ...options }, signal);
|
|
94
|
+
if (result.kind === 'select')
|
|
95
|
+
return { head: { vars: result.value.columns }, results: { bindings: result.value.rows } };
|
|
96
|
+
return result.value;
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../src/provider.ts"],"names":[],"mappings":"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"}
|
package/dist/query.d.ts
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Parse the grammar first, then inspect nested AST nodes (including subqueries). */
|
|
2
|
+
export declare function assertReadOnlyQuery(query: string, authorizedGraphs?: readonly string[]): 'select' | 'construct';
|
|
3
|
+
/** VALUES uses validated IRIs, never interpolated user syntax or unescaped literals. */
|
|
4
|
+
export declare function relatedResourceQuery(ids: readonly string[], limit?: number): string;
|
|
5
|
+
/** Discover subjects by an explicit identity predicate, preserving the same bounded adjacency query. */
|
|
6
|
+
export declare function relatedIdentityQuery(predicate: string, identities: readonly string[], limit?: number): string;
|
|
7
|
+
//# sourceMappingURL=query.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.d.ts","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"AAOA,qFAAqF;AACrF,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,gBAAgB,GAAE,SAAS,MAAM,EAAO,GAAG,QAAQ,GAAG,WAAW,CAmBnH;AASD,wFAAwF;AACxF,wBAAgB,oBAAoB,CAAC,GAAG,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,GAAE,MAAoB,GAAG,MAAM,CAIhG;AACD,wGAAwG;AACxG,wBAAgB,oBAAoB,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,EAAE,SAAS,MAAM,EAAE,EAAE,KAAK,GAAE,MAAoB,GAAG,MAAM,CAM1H"}
|
package/dist/query.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
|
4
|
+
import { Parser } from '@traqula/parser-sparql-1-1';
|
|
5
|
+
import { LIMITS, assertIri, isObject } from './types.js';
|
|
6
|
+
/** Parse the grammar first, then inspect nested AST nodes (including subqueries). */
|
|
7
|
+
export function assertReadOnlyQuery(query, authorizedGraphs = []) {
|
|
8
|
+
if (query.length > LIMITS.query)
|
|
9
|
+
throw new Error('SPARQL query exceeds limit');
|
|
10
|
+
const ast = new Parser().parse(query);
|
|
11
|
+
if (!isObject(ast) || ast.type !== 'query' || (ast.subType !== 'select' && ast.subType !== 'construct'))
|
|
12
|
+
throw new Error('Only SELECT and CONSTRUCT queries are supported');
|
|
13
|
+
const pending = [ast];
|
|
14
|
+
while (pending.length) {
|
|
15
|
+
const current = pending.pop();
|
|
16
|
+
if (Array.isArray(current))
|
|
17
|
+
pending.push(...current);
|
|
18
|
+
else if (isObject(current)) {
|
|
19
|
+
if (current.subType === 'service')
|
|
20
|
+
throw new Error('Federated SERVICE queries are not permitted');
|
|
21
|
+
if (current.type === 'datasetClauses' && Array.isArray(current.clauses)) {
|
|
22
|
+
for (const clause of current.clauses) {
|
|
23
|
+
if (!isObject(clause) || !isObject(clause.value) || !authorizedGraphs.includes(String(clause.value.value)))
|
|
24
|
+
throw new Error('FROM graph has not been explicitly authorized');
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
pending.push(...Object.values(current));
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return ast.subType;
|
|
31
|
+
}
|
|
32
|
+
// Bind each branch from its own triple pattern before joining the outer resource constraints.
|
|
33
|
+
const RELATED_PATTERN = '{ ?resource ?predicate ?object BIND(?resource AS ?subject) } UNION { ?subject ?predicate ?resource BIND(?resource AS ?object) }';
|
|
34
|
+
function boundedRelatedQuery(selector, count, limit) {
|
|
35
|
+
if (!count || count > LIMITS.rows || !Number.isInteger(limit) || limit < 1 || limit > LIMITS.rows)
|
|
36
|
+
throw new Error('Invalid related query bounds');
|
|
37
|
+
const query = `SELECT DISTINCT ?subject ?predicate ?object WHERE { ${selector} ${RELATED_PATTERN} } LIMIT ${limit}`;
|
|
38
|
+
if (query.length > LIMITS.query)
|
|
39
|
+
throw new Error('Related query exceeds query limit');
|
|
40
|
+
return query;
|
|
41
|
+
}
|
|
42
|
+
/** VALUES uses validated IRIs, never interpolated user syntax or unescaped literals. */
|
|
43
|
+
export function relatedResourceQuery(ids, limit = LIMITS.rows) {
|
|
44
|
+
ids.forEach(assertIri);
|
|
45
|
+
const unique = [...new Set(ids)];
|
|
46
|
+
return boundedRelatedQuery(`VALUES ?resource { ${unique.map(id => `<${id}>`).join(' ')} }`, unique.length, limit);
|
|
47
|
+
}
|
|
48
|
+
/** Discover subjects by an explicit identity predicate, preserving the same bounded adjacency query. */
|
|
49
|
+
export function relatedIdentityQuery(predicate, identities, limit = LIMITS.rows) {
|
|
50
|
+
assertIri(predicate);
|
|
51
|
+
if (identities.some(value => typeof value !== 'string'))
|
|
52
|
+
throw new Error('Identity query values must be strings');
|
|
53
|
+
const unique = [...new Set(identities)];
|
|
54
|
+
const values = unique.map(value => JSON.stringify(value)).join(' ');
|
|
55
|
+
return boundedRelatedQuery(`VALUES ?identity { ${values} } ?resource <${predicate}> ?identity .`, unique.length, limit);
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"query.js","sourceRoot":"","sources":["../src/query.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export { GUID_PATTERN } from './types.js';
|
|
2
|
+
export interface EntityAddress {
|
|
3
|
+
modelId: string;
|
|
4
|
+
expressId: number;
|
|
5
|
+
}
|
|
6
|
+
export interface LiveEntity extends EntityAddress {
|
|
7
|
+
GlobalId: string;
|
|
8
|
+
}
|
|
9
|
+
export type Resolution = {
|
|
10
|
+
status: 'resolved';
|
|
11
|
+
ref: EntityAddress;
|
|
12
|
+
} | {
|
|
13
|
+
status: 'ambiguous';
|
|
14
|
+
candidates: EntityAddress[];
|
|
15
|
+
} | {
|
|
16
|
+
status: 'unmatched' | 'unscoped' | 'external' | 'invalid';
|
|
17
|
+
};
|
|
18
|
+
export interface IdentityRecord {
|
|
19
|
+
GlobalId?: unknown;
|
|
20
|
+
modelRevision?: unknown;
|
|
21
|
+
[key: string]: unknown;
|
|
22
|
+
}
|
|
23
|
+
export interface ResolverContext {
|
|
24
|
+
entities: readonly LiveEntity[];
|
|
25
|
+
revisions: ReadonlyMap<string, string>;
|
|
26
|
+
modelScope?: string;
|
|
27
|
+
}
|
|
28
|
+
export interface IdentityStrategy {
|
|
29
|
+
id: string;
|
|
30
|
+
resolve(record: IdentityRecord, context: ResolverContext): Resolution;
|
|
31
|
+
}
|
|
32
|
+
/** Generic revision identifiers are non-empty opaque strings; profiles may constrain them further. */
|
|
33
|
+
export declare function assertRevisionIdentifier(value: unknown): asserts value is string;
|
|
34
|
+
export declare const IFC_GLOBAL_ID_STRATEGY: IdentityStrategy;
|
|
35
|
+
/** Strategies are explicit: never try increasingly permissive fallbacks after a failed match. */
|
|
36
|
+
export declare class ResolverRegistry {
|
|
37
|
+
private readonly strategies;
|
|
38
|
+
constructor(strategies?: readonly IdentityStrategy[]);
|
|
39
|
+
register(strategy: IdentityStrategy): void;
|
|
40
|
+
resolve(strategyId: string, record: IdentityRecord, context: ResolverContext): Resolution;
|
|
41
|
+
ids(): string[];
|
|
42
|
+
}
|
|
43
|
+
export declare function resolveResource(record: IdentityRecord, entities: readonly LiveEntity[], revisions: ReadonlyMap<string, string>, modelScope?: string): Resolution;
|
|
44
|
+
/** Portable association references semantic revision and IFC GlobalId, never express ids. */
|
|
45
|
+
export interface ResourceIdentityLink {
|
|
46
|
+
resourceId: string;
|
|
47
|
+
modelRevision: string;
|
|
48
|
+
GlobalId: string;
|
|
49
|
+
}
|
|
50
|
+
export declare function createResourceLinkStrategy(links: readonly ResourceIdentityLink[], id?: string): IdentityStrategy;
|
|
51
|
+
/** Map named domain identity fields explicitly, retaining the same safe IFC strategy. */
|
|
52
|
+
export declare function createProfileMappingStrategy(id: string, fields: {
|
|
53
|
+
GlobalId: string;
|
|
54
|
+
modelRevision?: string;
|
|
55
|
+
}): IdentityStrategy;
|
|
56
|
+
//# sourceMappingURL=resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../src/resolver.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,MAAM,WAAW,aAAa;IAAG,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE;AACrE,MAAM,WAAW,UAAW,SAAQ,aAAa;IAAG,QAAQ,EAAE,MAAM,CAAA;CAAE;AACtE,MAAM,MAAM,UAAU,GAAG;IAAE,MAAM,EAAE,UAAU,CAAC;IAAC,GAAG,EAAE,aAAa,CAAA;CAAE,GAAG;IAAE,MAAM,EAAE,WAAW,CAAC;IAAC,UAAU,EAAE,aAAa,EAAE,CAAA;CAAE,GACtH;IAAE,MAAM,EAAE,WAAW,GAAG,UAAU,GAAG,UAAU,GAAG,SAAS,CAAA;CAAE,CAAC;AAClE,MAAM,WAAW,cAAc;IAAG,QAAQ,CAAC,EAAE,OAAO,CAAC;IAAC,aAAa,CAAC,EAAE,OAAO,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAE;AACvG,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,SAAS,UAAU,EAAE,CAAC;IAAC,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9F;AACD,MAAM,WAAW,gBAAgB;IAAG,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,eAAe,GAAG,UAAU,CAAA;CAAE;AAEvH,sGAAsG;AACtG,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAAC,KAAK,IAAI,MAAM,CAEhF;AAED,eAAO,MAAM,sBAAsB,EAAE,gBAgBpC,CAAC;AACF,iGAAiG;AACjG,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAuC;gBACtD,UAAU,GAAE,SAAS,gBAAgB,EAA6B;IAC9E,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,GAAG,IAAI;IAI1C,OAAO,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,eAAe,GAAG,UAAU;IAKzF,GAAG,IAAI,MAAM,EAAE;CAChB;AACD,wBAAgB,eAAe,CAAC,MAAM,EAAE,cAAc,EAAE,QAAQ,EAAE,SAAS,UAAU,EAAE,EAAE,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,UAAU,CAEhK;AACD,6FAA6F;AAC7F,MAAM,WAAW,oBAAoB;IAAG,UAAU,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE;AACrG,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,SAAS,oBAAoB,EAAE,EAAE,EAAE,SAAmB,GAAG,gBAAgB,CAsB1H;AACD,yFAAyF;AACzF,wBAAgB,4BAA4B,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE;IAAE,QAAQ,EAAE,MAAM,CAAC;IAAC,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,gBAAgB,CAK/H"}
|