@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/resolver.js
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
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 { GUID_PATTERN } from './types.js';
|
|
5
|
+
export { GUID_PATTERN } from './types.js';
|
|
6
|
+
function isRevisionIdentifier(value) { return typeof value === 'string' && Boolean(value.trim()); }
|
|
7
|
+
/** Generic revision identifiers are non-empty opaque strings; profiles may constrain them further. */
|
|
8
|
+
export function assertRevisionIdentifier(value) {
|
|
9
|
+
if (!isRevisionIdentifier(value))
|
|
10
|
+
throw new Error('Revision identifier must be a non-empty string');
|
|
11
|
+
}
|
|
12
|
+
export const IFC_GLOBAL_ID_STRATEGY = {
|
|
13
|
+
id: 'ifc-global-id', resolve(record, { entities, revisions, modelScope }) {
|
|
14
|
+
if (record.GlobalId === undefined)
|
|
15
|
+
return { status: 'external' };
|
|
16
|
+
if (typeof record.GlobalId !== 'string' || !new RegExp(GUID_PATTERN).test(record.GlobalId)
|
|
17
|
+
|| (record.modelRevision !== undefined && !isRevisionIdentifier(record.modelRevision)))
|
|
18
|
+
return { status: 'invalid' };
|
|
19
|
+
const revisionModel = record.modelRevision ? revisions.get(String(record.modelRevision)) : undefined;
|
|
20
|
+
if (record.modelRevision && !revisionModel)
|
|
21
|
+
return { status: 'unscoped' };
|
|
22
|
+
if (revisionModel && modelScope && revisionModel !== modelScope)
|
|
23
|
+
return { status: 'unmatched' };
|
|
24
|
+
const scope = revisionModel ?? modelScope;
|
|
25
|
+
const unique = new Map();
|
|
26
|
+
for (const entity of entities)
|
|
27
|
+
if (entity.GlobalId === record.GlobalId && (!scope || scope === entity.modelId)) {
|
|
28
|
+
unique.set(`${entity.modelId}:${entity.expressId}`, { modelId: entity.modelId, expressId: entity.expressId });
|
|
29
|
+
}
|
|
30
|
+
const candidates = [...unique.values()];
|
|
31
|
+
return candidates.length === 1 ? { status: 'resolved', ref: candidates[0] } : candidates.length ? { status: 'ambiguous', candidates } : { status: 'unmatched' };
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
/** Strategies are explicit: never try increasingly permissive fallbacks after a failed match. */
|
|
35
|
+
export class ResolverRegistry {
|
|
36
|
+
strategies = new Map();
|
|
37
|
+
constructor(strategies = [IFC_GLOBAL_ID_STRATEGY]) { strategies.forEach(strategy => this.register(strategy)); }
|
|
38
|
+
register(strategy) {
|
|
39
|
+
if (!strategy.id || this.strategies.has(strategy.id))
|
|
40
|
+
throw new Error('Resolver strategy id must be unique');
|
|
41
|
+
this.strategies.set(strategy.id, strategy);
|
|
42
|
+
}
|
|
43
|
+
resolve(strategyId, record, context) {
|
|
44
|
+
const strategy = this.strategies.get(strategyId);
|
|
45
|
+
if (!strategy)
|
|
46
|
+
throw new Error(`Unknown resolver strategy: ${strategyId}`);
|
|
47
|
+
return strategy.resolve(record, context);
|
|
48
|
+
}
|
|
49
|
+
ids() { return [...this.strategies.keys()]; }
|
|
50
|
+
}
|
|
51
|
+
export function resolveResource(record, entities, revisions, modelScope) {
|
|
52
|
+
return IFC_GLOBAL_ID_STRATEGY.resolve(record, { entities, revisions, modelScope });
|
|
53
|
+
}
|
|
54
|
+
export function createResourceLinkStrategy(links, id = 'resource-links') {
|
|
55
|
+
const byResource = new Map();
|
|
56
|
+
for (const link of links) {
|
|
57
|
+
assertRevisionIdentifier(link.modelRevision);
|
|
58
|
+
if (!link.resourceId || !link.modelRevision || !new RegExp(GUID_PATTERN).test(link.GlobalId))
|
|
59
|
+
throw new Error('Invalid portable resource identity link');
|
|
60
|
+
byResource.set(link.resourceId, [...(byResource.get(link.resourceId) ?? []), { ...link }]);
|
|
61
|
+
}
|
|
62
|
+
return { id, resolve(record, context) {
|
|
63
|
+
if (typeof record.id !== 'string')
|
|
64
|
+
return { status: 'invalid' };
|
|
65
|
+
const linked = byResource.get(record.id);
|
|
66
|
+
if (!linked)
|
|
67
|
+
return { status: 'external' };
|
|
68
|
+
// Several declared identities are alternatives, not permission to choose the first.
|
|
69
|
+
const resolved = linked.map(link => IFC_GLOBAL_ID_STRATEGY.resolve({ GlobalId: link.GlobalId, modelRevision: link.modelRevision }, context));
|
|
70
|
+
if (resolved.some(result => result.status === 'invalid' || result.status === 'unscoped'))
|
|
71
|
+
return { status: 'unscoped' };
|
|
72
|
+
const candidates = new Map();
|
|
73
|
+
for (const result of resolved) {
|
|
74
|
+
const refs = result.status === 'resolved' ? [result.ref] : result.status === 'ambiguous' ? result.candidates : [];
|
|
75
|
+
refs.forEach(ref => candidates.set(`${ref.modelId}:${ref.expressId}`, ref));
|
|
76
|
+
}
|
|
77
|
+
const refs = [...candidates.values()];
|
|
78
|
+
return refs.length === 1 ? { status: 'resolved', ref: refs[0] } : refs.length ? { status: 'ambiguous', candidates: refs } : { status: 'unmatched' };
|
|
79
|
+
} };
|
|
80
|
+
}
|
|
81
|
+
/** Map named domain identity fields explicitly, retaining the same safe IFC strategy. */
|
|
82
|
+
export function createProfileMappingStrategy(id, fields) {
|
|
83
|
+
if (!id || !fields.GlobalId)
|
|
84
|
+
throw new Error('Profile identity mapping needs a strategy id and GlobalId field');
|
|
85
|
+
return { id, resolve(record, context) {
|
|
86
|
+
return IFC_GLOBAL_ID_STRATEGY.resolve({ GlobalId: record[fields.GlobalId], modelRevision: fields.modelRevision ? record[fields.modelRevision] : undefined }, context);
|
|
87
|
+
} };
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../src/resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { type RdfBinding, type SparqlResults, type SemanticRecord } from './types.js';
|
|
2
|
+
export declare function parseResults(value: unknown): SparqlResults;
|
|
3
|
+
/** Shared linear RDF set projection; preserve first occurrence and lexical metadata. */
|
|
4
|
+
export declare function createRecordAccumulator(): {
|
|
5
|
+
append: (subject: RdfBinding | undefined, predicate: RdfBinding | undefined, object: RdfBinding | undefined) => void;
|
|
6
|
+
records: () => SemanticRecord[];
|
|
7
|
+
};
|
|
8
|
+
/** RDF-shaped SELECT results are optional; arbitrary analytical columns stay in raw rows. */
|
|
9
|
+
export declare function recordsFromResults(results: SparqlResults, mapping?: {
|
|
10
|
+
subject: string;
|
|
11
|
+
predicate: string;
|
|
12
|
+
object: string;
|
|
13
|
+
}): SemanticRecord[];
|
|
14
|
+
//# sourceMappingURL=results.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"results.d.ts","sourceRoot":"","sources":["../src/results.ts"],"names":[],"mappings":"AAIA,OAAO,EAA+B,KAAK,UAAU,EAAE,KAAK,aAAa,EAAE,KAAK,cAAc,EAAE,MAAM,YAAY,CAAC;AAEnH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,aAAa,CA8B1D;AAED,wFAAwF;AACxF,wBAAgB,uBAAuB;sBAGZ,UAAU,GAAG,SAAS,aAAa,UAAU,GAAG,SAAS,UAAU,UAAU,GAAG,SAAS;;EAcnH;AACD,6FAA6F;AAC7F,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,aAAa,EAAE,OAAO;;;;CAAmE,GAAG,cAAc,EAAE,CAIvJ"}
|
package/dist/results.js
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
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 { LIMITS, assertIri, isObject } from './types.js';
|
|
5
|
+
export function parseResults(value) {
|
|
6
|
+
if (!isObject(value) || !isObject(value.head) || !Array.isArray(value.head.vars)
|
|
7
|
+
|| !value.head.vars.every(v => typeof v === 'string') || !isObject(value.results)
|
|
8
|
+
|| !Array.isArray(value.results.bindings) || value.results.bindings.length > LIMITS.rows) {
|
|
9
|
+
throw new Error('Expected bounded SPARQL SELECT JSON results');
|
|
10
|
+
}
|
|
11
|
+
const columns = value.head.vars;
|
|
12
|
+
if (new Set(columns).size !== columns.length || columns.some(v => !v || v.length > 1024))
|
|
13
|
+
throw new Error('Invalid SPARQL columns');
|
|
14
|
+
const rows = value.results.bindings.map((row) => {
|
|
15
|
+
if (!isObject(row))
|
|
16
|
+
throw new Error('Invalid SPARQL result row');
|
|
17
|
+
const result = Object.create(null);
|
|
18
|
+
for (const [name, raw] of Object.entries(row)) {
|
|
19
|
+
if (!columns.includes(name) || !isObject(raw) || typeof raw.value !== 'string'
|
|
20
|
+
|| !['uri', 'literal', 'bnode'].includes(String(raw.type)))
|
|
21
|
+
throw new Error(`Invalid RDF binding: ${name}`);
|
|
22
|
+
const type = raw.type;
|
|
23
|
+
if ((raw.datatype !== undefined && typeof raw.datatype !== 'string')
|
|
24
|
+
|| (raw['xml:lang'] !== undefined && typeof raw['xml:lang'] !== 'string')
|
|
25
|
+
|| (type !== 'literal' && (raw.datatype !== undefined || raw['xml:lang'] !== undefined))
|
|
26
|
+
|| (raw.datatype !== undefined && raw['xml:lang'] !== undefined))
|
|
27
|
+
throw new Error(`Invalid RDF literal metadata: ${name}`);
|
|
28
|
+
if (type === 'uri')
|
|
29
|
+
assertIri(raw.value);
|
|
30
|
+
if (typeof raw.datatype === 'string')
|
|
31
|
+
assertIri(raw.datatype);
|
|
32
|
+
if (typeof raw['xml:lang'] === 'string' && !/^[a-zA-Z]+(?:-[a-zA-Z0-9]+)*$/u.test(raw['xml:lang']))
|
|
33
|
+
throw new Error('Invalid language tag');
|
|
34
|
+
if (type === 'bnode' && !raw.value)
|
|
35
|
+
throw new Error('Blank node label is empty');
|
|
36
|
+
result[name] = { type, value: raw.value,
|
|
37
|
+
...(typeof raw.datatype === 'string' ? { datatype: raw.datatype } : {}),
|
|
38
|
+
...(typeof raw['xml:lang'] === 'string' ? { 'xml:lang': raw['xml:lang'] } : {}) };
|
|
39
|
+
}
|
|
40
|
+
return result;
|
|
41
|
+
});
|
|
42
|
+
return { columns: [...columns], rows };
|
|
43
|
+
}
|
|
44
|
+
/** Shared linear RDF set projection; preserve first occurrence and lexical metadata. */
|
|
45
|
+
export function createRecordAccumulator() {
|
|
46
|
+
const records = new Map();
|
|
47
|
+
const seen = new Set();
|
|
48
|
+
const append = (subject, predicate, object) => {
|
|
49
|
+
if (!subject || !predicate || !object || !['uri', 'bnode'].includes(subject.type) || predicate.type !== 'uri')
|
|
50
|
+
throw new Error('Expected subject, predicate and object RDF bindings');
|
|
51
|
+
const id = subject.type === 'bnode' ? `_:${subject.value}` : subject.value;
|
|
52
|
+
// Tuple serialization distinguishes embedded delimiters, URI/literal/blank
|
|
53
|
+
// node terms, lexical datatypes and language tags without array scans.
|
|
54
|
+
const key = JSON.stringify([id, predicate.value, object.type, object.value, object.datatype ?? null, object['xml:lang'] ?? null]);
|
|
55
|
+
if (seen.has(key))
|
|
56
|
+
return;
|
|
57
|
+
seen.add(key);
|
|
58
|
+
const record = records.get(id) ?? { id, types: [], properties: Object.create(null) };
|
|
59
|
+
(record.properties[predicate.value] ??= []).push({ ...object });
|
|
60
|
+
if (predicate.value === 'http://www.w3.org/1999/02/22-rdf-syntax-ns#type' && object.type === 'uri')
|
|
61
|
+
record.types.push(object.value);
|
|
62
|
+
records.set(id, record);
|
|
63
|
+
};
|
|
64
|
+
return { append, records: () => [...records.values()] };
|
|
65
|
+
}
|
|
66
|
+
/** RDF-shaped SELECT results are optional; arbitrary analytical columns stay in raw rows. */
|
|
67
|
+
export function recordsFromResults(results, mapping = { subject: 'subject', predicate: 'predicate', object: 'object' }) {
|
|
68
|
+
const accumulator = createRecordAccumulator();
|
|
69
|
+
for (const row of results.rows)
|
|
70
|
+
accumulator.append(row[mapping.subject], row[mapping.predicate], row[mapping.object]);
|
|
71
|
+
return accumulator.records();
|
|
72
|
+
}
|
|
73
|
+
//# sourceMappingURL=results.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"results.js","sourceRoot":"","sources":["../src/results.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Node HTTPS adapter. Semantic relay policy itself remains shared in server.ts. */
|
|
2
|
+
import { type ServerOptions, type Server } from 'node:https';
|
|
3
|
+
import { type RelayOptions } from './server.js';
|
|
4
|
+
export declare function createSemanticRelayServer(options: RelayOptions, tls: Pick<ServerOptions, 'cert' | 'key'>): Server;
|
|
5
|
+
//# sourceMappingURL=server-listener.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-listener.d.ts","sourceRoot":"","sources":["../src/server-listener.ts"],"names":[],"mappings":"AAIA,oFAAoF;AACpF,OAAO,EAAgB,KAAK,aAAa,EAAE,KAAK,MAAM,EAAE,MAAM,YAAY,CAAC;AAE3E,OAAO,EAAuB,KAAK,YAAY,EAAE,MAAM,aAAa,CAAC;AACrE,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,EAAE,IAAI,CAAC,aAAa,EAAE,MAAM,GAAG,KAAK,CAAC,GAAG,MAAM,CA2BjH"}
|
|
@@ -0,0 +1,46 @@
|
|
|
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
|
+
/** Node HTTPS adapter. Semantic relay policy itself remains shared in server.ts. */
|
|
5
|
+
import { createServer } from 'node:https';
|
|
6
|
+
import { Readable } from 'node:stream';
|
|
7
|
+
import { createSemanticRelay } from './server.js';
|
|
8
|
+
export function createSemanticRelayServer(options, tls) {
|
|
9
|
+
if (!tls.cert || !tls.key)
|
|
10
|
+
throw new Error('Relay requires a TLS certificate and private key');
|
|
11
|
+
const handle = createSemanticRelay(options);
|
|
12
|
+
const server = createServer(tls, async (incoming, outgoing) => {
|
|
13
|
+
const controller = new AbortController();
|
|
14
|
+
const abort = () => controller.abort();
|
|
15
|
+
incoming.once('aborted', abort);
|
|
16
|
+
outgoing.once('close', abort);
|
|
17
|
+
try {
|
|
18
|
+
const headers = new Headers();
|
|
19
|
+
for (const [name, values] of Object.entries(incoming.headers)) {
|
|
20
|
+
for (const value of Array.isArray(values) ? values : values === undefined ? [] : [values])
|
|
21
|
+
headers.append(name, value);
|
|
22
|
+
}
|
|
23
|
+
const init = { method: incoming.method, headers, signal: controller.signal };
|
|
24
|
+
if (!['GET', 'HEAD'].includes(incoming.method ?? 'GET')) {
|
|
25
|
+
init.body = Readable.toWeb(incoming);
|
|
26
|
+
init.duplex = 'half';
|
|
27
|
+
}
|
|
28
|
+
const response = await handle(new Request(new URL(incoming.url ?? '/', 'https://relay.invalid'), init));
|
|
29
|
+
outgoing.writeHead(response.status, Object.fromEntries(response.headers.entries()));
|
|
30
|
+
outgoing.end(Buffer.from(await response.arrayBuffer()));
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
if (!outgoing.headersSent)
|
|
34
|
+
outgoing.writeHead(500, { 'Content-Type': 'application/json', 'Cache-Control': 'no-store' });
|
|
35
|
+
outgoing.end('{"error":"Relay request failed"}');
|
|
36
|
+
}
|
|
37
|
+
finally {
|
|
38
|
+
incoming.removeListener('aborted', abort);
|
|
39
|
+
outgoing.removeListener('close', abort);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
server.requestTimeout = (options.timeoutMs ?? 15000) + 1000;
|
|
43
|
+
server.headersTimeout = Math.min(server.requestTimeout, 10000);
|
|
44
|
+
return server;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=server-listener.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-listener.js","sourceRoot":"","sources":["../src/server-listener.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { FetchTransport } from '@ifc-lite/sandbox/network';
|
|
2
|
+
export interface RelayProvider {
|
|
3
|
+
endpoint: string;
|
|
4
|
+
grantedHost: string;
|
|
5
|
+
kind: 'json' | 'sparql';
|
|
6
|
+
/** Resolved at request time from an environment/keychain; never serialized in responses. */
|
|
7
|
+
bearerToken?: () => string | undefined;
|
|
8
|
+
}
|
|
9
|
+
export interface RelayOptions {
|
|
10
|
+
providers: Readonly<Record<string, RelayProvider>>;
|
|
11
|
+
clientToken: string;
|
|
12
|
+
allowedOrigins: readonly string[];
|
|
13
|
+
timeoutMs?: number;
|
|
14
|
+
maxBytes?: number;
|
|
15
|
+
/** Test transport changes byte movement, never HTTPS/grant/redirect authorization. */
|
|
16
|
+
transport?: FetchTransport;
|
|
17
|
+
}
|
|
18
|
+
/** Mount behind HTTPS; requests authorize a fixed provider id, not an arbitrary proxy destination. */
|
|
19
|
+
export declare function createSemanticRelay(options: RelayOptions): (request: Request) => Promise<Response>;
|
|
20
|
+
export { createSemanticRelayServer } from './server-listener.js';
|
|
21
|
+
//# sourceMappingURL=server.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAIhE,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,GAAG,QAAQ,CAAC;IACxB,4FAA4F;IAC5F,WAAW,CAAC,EAAE,MAAM,MAAM,GAAG,SAAS,CAAC;CACxC;AACD,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC;IACnD,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,sFAAsF;IACtF,SAAS,CAAC,EAAE,cAAc,CAAC;CAC5B;AA2BD,sGAAsG;AACtG,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,YAAY,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CAwDlG;AACD,OAAO,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC"}
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,141 @@
|
|
|
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
|
+
/** Node-only authenticated relay. Provider URLs and credentials are host configuration, never caller input. */
|
|
5
|
+
import { createHash, timingSafeEqual } from 'node:crypto';
|
|
6
|
+
import { createSemanticProvider } from './provider.js';
|
|
7
|
+
import { assertReadOnlyQuery } from './query.js';
|
|
8
|
+
const REQUEST_LIMIT = 300000;
|
|
9
|
+
function sameSecret(a, b) {
|
|
10
|
+
return timingSafeEqual(createHash('sha256').update(a).digest(), createHash('sha256').update(b).digest());
|
|
11
|
+
}
|
|
12
|
+
function jsonError(status, message, headers) {
|
|
13
|
+
headers.set('Content-Type', 'application/json');
|
|
14
|
+
if (status === 401)
|
|
15
|
+
headers.set('WWW-Authenticate', 'Bearer realm="ifc-lite-semantic"');
|
|
16
|
+
if (status === 405)
|
|
17
|
+
headers.set('Allow', 'POST, OPTIONS');
|
|
18
|
+
return new Response(JSON.stringify({ error: message }), { status, headers });
|
|
19
|
+
}
|
|
20
|
+
async function readBody(request, signal) {
|
|
21
|
+
if (!request.body)
|
|
22
|
+
throw new Error('Missing body');
|
|
23
|
+
const reader = request.body.getReader();
|
|
24
|
+
const chunks = [];
|
|
25
|
+
let length = 0;
|
|
26
|
+
const abort = () => { void reader.cancel('Request cancelled').catch(() => console.error('Relay request stream cancellation failed')); };
|
|
27
|
+
signal.addEventListener('abort', abort, { once: true });
|
|
28
|
+
try {
|
|
29
|
+
for (;;) {
|
|
30
|
+
signal.throwIfAborted();
|
|
31
|
+
const { done, value } = await reader.read();
|
|
32
|
+
signal.throwIfAborted();
|
|
33
|
+
if (done)
|
|
34
|
+
break;
|
|
35
|
+
length += value.byteLength;
|
|
36
|
+
if (length > REQUEST_LIMIT) {
|
|
37
|
+
await reader.cancel('Body limit');
|
|
38
|
+
throw new Error('Request exceeds byte limit');
|
|
39
|
+
}
|
|
40
|
+
chunks.push(value);
|
|
41
|
+
}
|
|
42
|
+
return Buffer.concat(chunks).toString('utf8');
|
|
43
|
+
}
|
|
44
|
+
finally {
|
|
45
|
+
signal.removeEventListener('abort', abort);
|
|
46
|
+
reader.releaseLock();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
/** Mount behind HTTPS; requests authorize a fixed provider id, not an arbitrary proxy destination. */
|
|
50
|
+
export function createSemanticRelay(options) {
|
|
51
|
+
if (options.clientToken.length < 32 || options.clientToken.length > 4096 || /[\r\n]/.test(options.clientToken))
|
|
52
|
+
throw new Error('Relay client token must contain 32–4096 characters');
|
|
53
|
+
const clientToken = options.clientToken;
|
|
54
|
+
const timeoutMs = options.timeoutMs ?? 15000;
|
|
55
|
+
const maxBytes = options.maxBytes ?? 5 * 1024 * 1024;
|
|
56
|
+
if (!Number.isInteger(timeoutMs) || timeoutMs < 1 || timeoutMs > 60000 || !Number.isInteger(maxBytes) || maxBytes < 1 || maxBytes > 5 * 1024 * 1024)
|
|
57
|
+
throw new Error('Relay limits are invalid');
|
|
58
|
+
if (options.allowedOrigins.length > 100 || Object.keys(options.providers).length > 100)
|
|
59
|
+
throw new Error('Relay configuration exceeds the 100 origin/provider limit');
|
|
60
|
+
const origins = new Set(options.allowedOrigins);
|
|
61
|
+
for (const origin of origins) {
|
|
62
|
+
const url = new URL(origin);
|
|
63
|
+
if (url.protocol !== 'https:' || url.origin !== origin)
|
|
64
|
+
throw new Error('Allowed origins must be exact HTTPS origins');
|
|
65
|
+
}
|
|
66
|
+
const providers = new Map();
|
|
67
|
+
for (const [id, provider] of Object.entries(options.providers)) {
|
|
68
|
+
const url = new URL(provider.endpoint);
|
|
69
|
+
if (!/^[A-Za-z0-9_-]{1,80}$/.test(id) || url.protocol !== 'https:' || url.username || url.password || url.search || url.hash
|
|
70
|
+
|| url.hostname !== provider.grantedHost || !['json', 'sparql'].includes(provider.kind))
|
|
71
|
+
throw new Error('Provider requires a fixed HTTPS endpoint and exact hostname grant');
|
|
72
|
+
providers.set(id, { ...provider });
|
|
73
|
+
}
|
|
74
|
+
return async (request) => {
|
|
75
|
+
const headers = new Headers({ 'Cache-Control': 'no-store', 'X-Content-Type-Options': 'nosniff', Vary: 'Origin' });
|
|
76
|
+
const origin = request.headers.get('Origin');
|
|
77
|
+
if (origin && !origins.has(origin))
|
|
78
|
+
return jsonError(403, 'Origin is not authorized', headers);
|
|
79
|
+
if (origin)
|
|
80
|
+
headers.set('Access-Control-Allow-Origin', origin);
|
|
81
|
+
if (new URL(request.url).protocol !== 'https:')
|
|
82
|
+
return jsonError(400, 'HTTPS required', headers);
|
|
83
|
+
if (request.method === 'OPTIONS') {
|
|
84
|
+
if (!origin || request.headers.get('Access-Control-Request-Method') !== 'POST')
|
|
85
|
+
return jsonError(403, 'Invalid preflight', headers);
|
|
86
|
+
headers.set('Access-Control-Allow-Methods', 'POST');
|
|
87
|
+
headers.set('Access-Control-Allow-Headers', 'Authorization, Content-Type');
|
|
88
|
+
return new Response(null, { status: 204, headers });
|
|
89
|
+
}
|
|
90
|
+
if (request.method !== 'POST')
|
|
91
|
+
return jsonError(405, 'POST required', headers);
|
|
92
|
+
if (!sameSecret(request.headers.get('Authorization') ?? '', `Bearer ${clientToken}`))
|
|
93
|
+
return jsonError(401, 'Unauthorized', headers);
|
|
94
|
+
if (request.headers.get('Content-Type')?.split(';')[0].trim().toLowerCase() !== 'application/json')
|
|
95
|
+
return jsonError(415, 'JSON required', headers);
|
|
96
|
+
const signal = AbortSignal.any([request.signal, AbortSignal.timeout(timeoutMs)]);
|
|
97
|
+
let body;
|
|
98
|
+
try {
|
|
99
|
+
body = JSON.parse(await readBody(request, signal));
|
|
100
|
+
}
|
|
101
|
+
catch {
|
|
102
|
+
return jsonError(signal.aborted ? 408 : 400, 'Invalid or oversized request', headers);
|
|
103
|
+
}
|
|
104
|
+
if (!body || typeof body !== 'object' || Array.isArray(body))
|
|
105
|
+
return jsonError(400, 'Invalid relay request', headers);
|
|
106
|
+
const input = body;
|
|
107
|
+
if (Object.keys(input).some(key => !['providerId', 'kind', 'query'].includes(key)) || typeof input.providerId !== 'string'
|
|
108
|
+
|| !['json', 'select', 'construct'].includes(String(input.kind)))
|
|
109
|
+
return jsonError(400, 'Invalid relay request', headers);
|
|
110
|
+
const provider = providers.get(input.providerId);
|
|
111
|
+
if (!provider)
|
|
112
|
+
return jsonError(404, 'Unknown provider', headers);
|
|
113
|
+
if ((input.kind === 'json') !== (provider.kind === 'json') || (input.kind === 'json' ? input.query !== undefined : typeof input.query !== 'string'))
|
|
114
|
+
return jsonError(400, 'Provider kind mismatch', headers);
|
|
115
|
+
try {
|
|
116
|
+
if (typeof input.query === 'string') {
|
|
117
|
+
const kind = assertReadOnlyQuery(input.query);
|
|
118
|
+
if (kind.toLowerCase() !== input.kind)
|
|
119
|
+
return jsonError(400, 'Query kind mismatch', headers);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
return jsonError(400, 'Only bounded SELECT/CONSTRUCT without SERVICE or FROM is allowed', headers);
|
|
124
|
+
}
|
|
125
|
+
try {
|
|
126
|
+
const result = await createSemanticProvider(options.transport).read({ endpoint: provider.endpoint, host: provider.grantedHost,
|
|
127
|
+
kind: input.kind, query: typeof input.query === 'string' ? input.query : undefined,
|
|
128
|
+
bearer: provider.bearerToken?.(), timeoutMs, maxBytes }, signal);
|
|
129
|
+
headers.set('Content-Type', result.kind === 'construct' ? result.format
|
|
130
|
+
: result.kind === 'select' ? 'application/sparql-results+json' : 'application/json');
|
|
131
|
+
const payload = result.kind === 'construct' ? result.value : result.kind === 'select'
|
|
132
|
+
? JSON.stringify({ head: { vars: result.value.columns }, results: { bindings: result.value.rows } }) : JSON.stringify(result.value);
|
|
133
|
+
return new Response(payload, { headers });
|
|
134
|
+
}
|
|
135
|
+
catch {
|
|
136
|
+
return jsonError(signal.aborted ? 504 : 502, signal.aborted ? 'Provider request timed out or was cancelled' : 'Provider request failed', headers);
|
|
137
|
+
}
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
export { createSemanticRelayServer } from './server-listener.js';
|
|
141
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type Store } from 'n3';
|
|
2
|
+
/** Check executable scalar parameters before the engine can coerce or ignore them.
|
|
3
|
+
* SHACL 4.2 / 4.4 / 4.8 and 2.1.6: https://www.w3.org/TR/shacl/.
|
|
4
|
+
*/
|
|
5
|
+
export declare function assertShapeParameters(shapes: Store): void;
|
|
6
|
+
//# sourceMappingURL=shacl-parameters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shacl-parameters.d.ts","sourceRoot":"","sources":["../src/shacl-parameters.ts"],"names":[],"mappings":"AAIA,OAAO,EAAe,KAAK,KAAK,EAAE,MAAM,IAAI,CAAC;AAO7C;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,KAAK,GAAG,IAAI,CA2CzD"}
|
|
@@ -0,0 +1,65 @@
|
|
|
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 { DataFactory } from 'n3';
|
|
5
|
+
import { assertBoundedPattern } from './profiles.js';
|
|
6
|
+
const SH = 'http://www.w3.org/ns/shacl#';
|
|
7
|
+
const XSD = 'http://www.w3.org/2001/XMLSchema#';
|
|
8
|
+
const counts = new Set(['minCount', 'maxCount', 'maxLength']);
|
|
9
|
+
const booleans = new Set(['closed', 'uniqueLang', 'deactivated']);
|
|
10
|
+
const strings = new Set(['pattern', 'flags']);
|
|
11
|
+
/** Check executable scalar parameters before the engine can coerce or ignore them.
|
|
12
|
+
* SHACL 4.2 / 4.4 / 4.8 and 2.1.6: https://www.w3.org/TR/shacl/.
|
|
13
|
+
*/
|
|
14
|
+
export function assertShapeParameters(shapes) {
|
|
15
|
+
const seen = new Set();
|
|
16
|
+
const normalized = [];
|
|
17
|
+
for (const quad of shapes) {
|
|
18
|
+
if (!quad.predicate.value.startsWith(SH))
|
|
19
|
+
continue;
|
|
20
|
+
const name = quad.predicate.value.slice(SH.length);
|
|
21
|
+
if (!counts.has(name) && !booleans.has(name) && !strings.has(name))
|
|
22
|
+
continue;
|
|
23
|
+
const key = JSON.stringify([quad.subject.termType, quad.subject.value, name]);
|
|
24
|
+
if (seen.has(key))
|
|
25
|
+
throw new Error(`SHACL ${name} requires at most one value per shape`);
|
|
26
|
+
seen.add(key);
|
|
27
|
+
const value = quad.object;
|
|
28
|
+
if (counts.has(name) && (value.termType !== 'Literal' || value.datatype.value !== XSD + 'integer'
|
|
29
|
+
|| !/^\+?\d+$/.test(value.value) || !Number.isSafeInteger(Number(value.value)))) {
|
|
30
|
+
throw new Error(`SHACL ${name} must be a non-negative integer within the supported safe range`);
|
|
31
|
+
}
|
|
32
|
+
if (booleans.has(name)) {
|
|
33
|
+
if (value.termType !== 'Literal' || value.datatype.value !== XSD + 'boolean' || !/^(true|false|1|0)$/.test(value.value)) {
|
|
34
|
+
throw new Error(`SHACL ${name} must be an xsd:boolean`);
|
|
35
|
+
}
|
|
36
|
+
// The engine compares RDF terms against the canonical lexical 'true'.
|
|
37
|
+
if (value.value === '1' || value.value === '0')
|
|
38
|
+
normalized.push(DataFactory.quad(quad.subject, quad.predicate, quad.object, quad.graph));
|
|
39
|
+
}
|
|
40
|
+
if (strings.has(name)) {
|
|
41
|
+
if (value.termType !== 'Literal' || value.datatype.value !== XSD + 'string')
|
|
42
|
+
throw new Error(`SHACL ${name} must be an xsd:string`);
|
|
43
|
+
if (name === 'pattern')
|
|
44
|
+
assertBoundedPattern(value.value, 'SHACL shape');
|
|
45
|
+
if (name === 'flags' && (!/^[is]*$/.test(value.value) || new Set(value.value).size !== value.value.length)) {
|
|
46
|
+
throw new Error('Unsupported SHACL regular-expression flags');
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
for (const quad of normalized) {
|
|
51
|
+
shapes.removeQuad(quad);
|
|
52
|
+
shapes.addQuad(quad.subject, quad.predicate, DataFactory.literal(quad.object.value === '1' ? 'true' : 'false', DataFactory.namedNode(XSD + 'boolean')), quad.graph);
|
|
53
|
+
}
|
|
54
|
+
// SHACL uses SPARQL/XPath regex semantics: Unicode is intrinsic and 'u' is
|
|
55
|
+
// not a portable flag. Adapt only this private, parsed runtime graph for the
|
|
56
|
+
// JavaScript-based engine; generated/exported shapes retain standard flags.
|
|
57
|
+
const flagsPredicate = DataFactory.namedNode(SH + 'flags');
|
|
58
|
+
for (const pattern of shapes.getQuads(null, SH + 'pattern', null, null)) {
|
|
59
|
+
const flags = shapes.getQuads(pattern.subject, flagsPredicate, null, null)[0];
|
|
60
|
+
if (flags)
|
|
61
|
+
shapes.removeQuad(flags);
|
|
62
|
+
shapes.addQuad(pattern.subject, flagsPredicate, DataFactory.literal((flags?.object.value ?? '') + 'u'), flags?.graph ?? pattern.graph);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
//# sourceMappingURL=shacl-parameters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shacl-parameters.js","sourceRoot":"","sources":["../src/shacl-parameters.ts"],"names":[],"mappings":"AAAA;;+DAE+D;AAE/D,OAAO,EAAE,WAAW,EAAc,MAAM,IAAI,CAAC;AAC7C,OAAO,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACrD,MAAM,EAAE,GAAG,6BAA6B,CAAC;AACzC,MAAM,GAAG,GAAG,mCAAmC,CAAC;AAChD,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,CAAC,UAAU,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC;AAC9D,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,CAAC,QAAQ,EAAE,YAAY,EAAE,aAAa,CAAC,CAAC,CAAC;AAClE,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC;AAC9C;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAAa;IACjD,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,UAAU,GAAkC,EAAE,CAAC;IACrD,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;QAC1B,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC;YAAE,SAAS;QACnD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC;QACnD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,SAAS;QAC7E,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC;QAC9E,IAAI,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,SAAS,IAAI,uCAAuC,CAAC,CAAC;QACzF,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC;QAC1B,IAAI,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,KAAK,SAAS,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,KAAK,GAAG,GAAG,SAAS;eAC5F,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;YAClF,MAAM,IAAI,KAAK,CAAC,SAAS,IAAI,iEAAiE,CAAC,CAAC;QAClG,CAAC;QACD,IAAI,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACvB,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,KAAK,GAAG,GAAG,SAAS,IAAI,CAAC,oBAAoB,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;gBACxH,MAAM,IAAI,KAAK,CAAC,SAAS,IAAI,yBAAyB,CAAC,CAAC;YAC1D,CAAC;YACD,sEAAsE;YACtE,IAAI,KAAK,CAAC,KAAK,KAAK,GAAG,IAAI,KAAK,CAAC,KAAK,KAAK,GAAG;gBAAE,UAAU,CAAC,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QAC3I,CAAC;QACD,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACtB,IAAI,KAAK,CAAC,QAAQ,KAAK,SAAS,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,KAAK,GAAG,GAAG,QAAQ;gBAAE,MAAM,IAAI,KAAK,CAAC,SAAS,IAAI,wBAAwB,CAAC,CAAC;YACpI,IAAI,IAAI,KAAK,SAAS;gBAAE,oBAAoB,CAAC,KAAK,CAAC,KAAK,EAAE,aAAa,CAAC,CAAC;YACzE,IAAI,IAAI,KAAK,OAAO,IAAI,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,CAAC;gBAC3G,MAAM,IAAI,KAAK,CAAC,4CAA4C,CAAC,CAAC;YAChE,CAAC;QACH,CAAC;IACH,CAAC;IACD,KAAK,MAAM,IAAI,IAAI,UAAU,EAAE,CAAC;QAC9B,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;QACxB,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,KAAK,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,EAAE,WAAW,CAAC,SAAS,CAAC,GAAG,GAAG,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IACtK,CAAC;IACD,2EAA2E;IAC3E,6EAA6E;IAC7E,4EAA4E;IAC5E,MAAM,cAAc,GAAG,WAAW,CAAC,SAAS,CAAC,EAAE,GAAG,OAAO,CAAC,CAAC;IAC3D,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,GAAG,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC;QACxE,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;QAC9E,IAAI,KAAK;YAAE,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QACpC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,cAAc,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,IAAI,EAAE,CAAC,GAAG,GAAG,CAAC,EAAE,KAAK,EAAE,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC;IACzI,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Store } from 'n3';
|
|
2
|
+
/** SHACL property references may compose nonrecursive shapes. Imported cycles
|
|
3
|
+
* must fail before the validator's repeated-pair cache can silently accept them. */
|
|
4
|
+
export declare function assertBoundedPropertyShapes(shapes: Store): void;
|
|
5
|
+
/** The installed validator recursively traverses subclasses. Reject unsafe RDF
|
|
6
|
+
* before handing it off: cycles, deep acyclic paths and repeated DAG fan-out
|
|
7
|
+
* require separate checks. The raw imported graph remains unchanged. */
|
|
8
|
+
export declare function assertBoundedSubclasses(store: Store): void;
|
|
9
|
+
/** SHACL instances include explicitly typed subclasses in the supplied graph.
|
|
10
|
+
* This is local SHACL class membership, without remote ontologies or OWL inference. */
|
|
11
|
+
export declare function countShapeTargets(data: Store, shapes: Store): number;
|
|
12
|
+
//# sourceMappingURL=shacl-targets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shacl-targets.d.ts","sourceRoot":"","sources":["../src/shacl-targets.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,IAAI,CAAC;AA8BhC;oFACoF;AACpF,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,KAAK,GAAG,IAAI,CAU/D;AAED;;wEAEwE;AACxE,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,KAAK,GAAG,IAAI,CAU1D;AAED;uFACuF;AACvF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,GAAG,MAAM,CAmBpE"}
|