@rdfx/resource 0.0.1

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.
Files changed (43) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +42 -0
  3. package/dist/DatasetValues.d.ts +24 -0
  4. package/dist/DatasetValues.js +172 -0
  5. package/dist/Identifier.d.ts +10 -0
  6. package/dist/Identifier.js +26 -0
  7. package/dist/ListStructureError.d.ts +4 -0
  8. package/dist/ListStructureError.js +4 -0
  9. package/dist/LiteralDecoder.d.ts +20 -0
  10. package/dist/LiteralDecoder.js +213 -0
  11. package/dist/LiteralFactory.d.ts +19 -0
  12. package/dist/LiteralFactory.js +183 -0
  13. package/dist/MissingValueError.d.ts +10 -0
  14. package/dist/MissingValueError.js +13 -0
  15. package/dist/MistypedPrimitiveValueError.d.ts +13 -0
  16. package/dist/MistypedPrimitiveValueError.js +15 -0
  17. package/dist/MistypedTermValueError.d.ts +13 -0
  18. package/dist/MistypedTermValueError.js +15 -0
  19. package/dist/MistypedValueError.d.ts +15 -0
  20. package/dist/MistypedValueError.js +13 -0
  21. package/dist/Primitive.d.ts +2 -0
  22. package/dist/Primitive.js +2 -0
  23. package/dist/PropertyPath.d.ts +46 -0
  24. package/dist/PropertyPath.js +179 -0
  25. package/dist/Resource.d.ts +112 -0
  26. package/dist/Resource.js +354 -0
  27. package/dist/ResourceSet.d.ts +24 -0
  28. package/dist/ResourceSet.js +76 -0
  29. package/dist/Term.d.ts +6 -0
  30. package/dist/Term.js +31 -0
  31. package/dist/Value.d.ts +103 -0
  32. package/dist/Value.js +173 -0
  33. package/dist/ValueError.d.ts +12 -0
  34. package/dist/ValueError.js +8 -0
  35. package/dist/Values.d.ts +114 -0
  36. package/dist/Values.js +221 -0
  37. package/dist/index.d.ts +4 -0
  38. package/dist/index.js +4 -0
  39. package/dist/literalDatatypeDefinitions.d.ts +24 -0
  40. package/dist/literalDatatypeDefinitions.js +116 -0
  41. package/dist/vocabularies.d.ts +36 -0
  42. package/dist/vocabularies.js +41 -0
  43. package/package.json +42 -0
@@ -0,0 +1,179 @@
1
+ import dataFactory from "@rdfjs/data-model";
2
+ import datasetFactory from "@rdfjs/dataset";
3
+ import { Either, Left } from "purify-ts";
4
+ import { Resource } from "./Resource.js";
5
+ import { ResourceSet } from "./ResourceSet.js";
6
+ import { sh } from "./vocabularies.js";
7
+ export var PropertyPath;
8
+ (function (PropertyPath) {
9
+ function equals(left, right) {
10
+ if (left.termType !== right.termType) {
11
+ return false;
12
+ }
13
+ switch (left.termType) {
14
+ case "AlternativePath":
15
+ case "SequencePath": {
16
+ const right_ = right;
17
+ if (left.members.length !== right_.members.length) {
18
+ return false;
19
+ }
20
+ for (let memberI = 0; memberI < left.members.length; memberI++) {
21
+ if (!PropertyPath.equals(left.members[memberI], right_.members[memberI])) {
22
+ return false;
23
+ }
24
+ }
25
+ return true;
26
+ }
27
+ case "NamedNode":
28
+ return left.equals(right);
29
+ case "InversePath":
30
+ case "OneOrMorePath":
31
+ case "ZeroOrMorePath":
32
+ case "ZeroOrOnePath":
33
+ return PropertyPath.equals(left.path, right.path);
34
+ }
35
+ }
36
+ PropertyPath.equals = equals;
37
+ function fromResource(resource, options) {
38
+ // Predicate path
39
+ // sh:path ex:parent
40
+ if (resource.identifier.termType === "NamedNode") {
41
+ return Either.of(resource.identifier);
42
+ }
43
+ // The other property path types are BlankNodes
44
+ const getPropertyPathList = (list) => {
45
+ return list.chain((values) => {
46
+ const members = [];
47
+ for (const value of values) {
48
+ const resource = value.toResource().toMaybe();
49
+ if (resource.isNothing()) {
50
+ return Left(new Error("non-identifier in property path list"));
51
+ }
52
+ const member = PropertyPath.fromResource(resource.unsafeCoerce(), options);
53
+ if (member.isLeft()) {
54
+ return member;
55
+ }
56
+ members.push(member.unsafeCoerce());
57
+ }
58
+ return Either.of(members);
59
+ });
60
+ };
61
+ // Sequence path
62
+ // sh:path ( ex:parent ex:firstName )
63
+ {
64
+ const list = resource.toList();
65
+ if (list.isRight()) {
66
+ return getPropertyPathList(list).map((members) => ({
67
+ termType: "SequencePath",
68
+ members,
69
+ }));
70
+ }
71
+ }
72
+ for (const quad of resource.dataset.match(resource.identifier, null, null, options?.graph)) {
73
+ switch (quad.object.termType) {
74
+ case "BlankNode":
75
+ case "NamedNode":
76
+ break;
77
+ default:
78
+ return Left(new Error(`non-BlankNode/NamedNode property path object on path ${Resource.Identifier.toString(resource.identifier)}: ${quad.object.termType} ${quad.object.value}`));
79
+ }
80
+ const objectResource = new Resource(resource.dataset, quad.object);
81
+ // Alternative path
82
+ // sh:path: [ sh:alternativePath ( ex:father ex:mother ) ]
83
+ if (quad.predicate.equals(sh.alternativePath)) {
84
+ return getPropertyPathList(objectResource.toList()).map((members) => ({
85
+ termType: "AlternativePath",
86
+ members,
87
+ }));
88
+ }
89
+ // Inverse path
90
+ // sh:path: [ sh:inversePath ex:parent ]
91
+ if (quad.predicate.equals(sh.inversePath)) {
92
+ return PropertyPath.fromResource(objectResource, options).map((path) => ({
93
+ termType: "InversePath",
94
+ path,
95
+ }));
96
+ }
97
+ // One or more path
98
+ if (quad.predicate.equals(sh.oneOrMorePath)) {
99
+ return PropertyPath.fromResource(objectResource, options).map((path) => ({
100
+ termType: "OneOrMorePath",
101
+ path,
102
+ }));
103
+ }
104
+ // Zero or more path
105
+ if (quad.predicate.equals(sh.zeroOrMorePath)) {
106
+ return PropertyPath.fromResource(objectResource).map((path) => ({
107
+ termType: "ZeroOrMorePath",
108
+ path,
109
+ }));
110
+ }
111
+ if (quad.predicate.equals(sh.zeroOrOnePath)) {
112
+ return PropertyPath.fromResource(objectResource).map((path) => ({
113
+ termType: "ZeroOrOnePath",
114
+ path,
115
+ }));
116
+ }
117
+ }
118
+ return Left(new Error(`unrecognized or ill-formed SHACL property path ${Resource.Identifier.toString(resource.identifier)}`));
119
+ }
120
+ PropertyPath.fromResource = fromResource;
121
+ function toResource(propertyPath, options) {
122
+ const graph = options?.graph;
123
+ const resourceSet = options?.resourceSet ??
124
+ new ResourceSet(datasetFactory.dataset(), { dataFactory: dataFactory });
125
+ if (propertyPath.termType === "NamedNode") {
126
+ return resourceSet.resource(propertyPath);
127
+ }
128
+ const resource = resourceSet.resource(dataFactory.blankNode());
129
+ switch (propertyPath.termType) {
130
+ case "AlternativePath":
131
+ case "SequencePath": {
132
+ const members = propertyPath.members.map((member) => PropertyPath.toResource(member, { graph, resourceSet }).identifier);
133
+ if (propertyPath.termType === "AlternativePath") {
134
+ resource.addList(sh.alternativePath, members, { graph });
135
+ }
136
+ else {
137
+ resource.addListItems(members, { graph });
138
+ }
139
+ return resource;
140
+ }
141
+ }
142
+ let predicate;
143
+ switch (propertyPath.termType) {
144
+ case "InversePath":
145
+ predicate = sh.inversePath;
146
+ break;
147
+ case "OneOrMorePath":
148
+ predicate = sh.oneOrMorePath;
149
+ break;
150
+ case "ZeroOrMorePath":
151
+ predicate = sh.zeroOrMorePath;
152
+ break;
153
+ case "ZeroOrOnePath":
154
+ predicate = sh.zeroOrOnePath;
155
+ break;
156
+ }
157
+ resource.add(predicate, PropertyPath.toResource(propertyPath.path, { graph, resourceSet })
158
+ .identifier, graph);
159
+ return resource;
160
+ }
161
+ PropertyPath.toResource = toResource;
162
+ // biome-ignore lint/suspicious/noShadowRestrictedNames: intentional
163
+ function toString(propertyPath) {
164
+ switch (propertyPath.termType) {
165
+ case "AlternativePath":
166
+ case "SequencePath":
167
+ return `${propertyPath.termType}([${propertyPath.members.map(PropertyPath.toString).join(", ")}])`;
168
+ case "InversePath":
169
+ case "OneOrMorePath":
170
+ case "ZeroOrMorePath":
171
+ case "ZeroOrOnePath":
172
+ return `${propertyPath.termType}(${PropertyPath.toString(propertyPath.path)})`;
173
+ case "NamedNode":
174
+ return `PredicatePath(${propertyPath.value})`;
175
+ }
176
+ }
177
+ PropertyPath.toString = toString;
178
+ })(PropertyPath || (PropertyPath = {}));
179
+ //# sourceMappingURL=PropertyPath.js.map
@@ -0,0 +1,112 @@
1
+ import type { BlankNode, DataFactory, DatasetCore, Literal, NamedNode, Quad_Graph, Variable } from "@rdfjs/types";
2
+ import { Either } from "purify-ts";
3
+ import { Identifier as _Identifier, type Identifier } from "./Identifier.js";
4
+ import { ListStructureError as _ListStructureError } from "./ListStructureError.js";
5
+ import { MistypedTermValueError as _MistypedTermValueError } from "./MistypedTermValueError.js";
6
+ import type { Primitive } from "./Primitive.js";
7
+ import type { PropertyPath } from "./PropertyPath.js";
8
+ import type { Term } from "./Term.js";
9
+ import { Value as _Value } from "./Value.js";
10
+ import { ValueError as _ValueError } from "./ValueError.js";
11
+ import { Values as _Values } from "./Values.js";
12
+ /**
13
+ * A Resource abstraction over subjects or objects in an RDF/JS dataset.
14
+ */
15
+ export declare class Resource<IdentifierT extends Resource.Identifier = Resource.Identifier> {
16
+ readonly dataset: DatasetCore;
17
+ readonly identifier: IdentifierT;
18
+ private readonly dataFactory;
19
+ private readonly graph?;
20
+ private readonly literalFactory;
21
+ constructor(dataset: DatasetCore, identifier: IdentifierT, options?: {
22
+ dataFactory?: DataFactory;
23
+ });
24
+ /**
25
+ * Add zero or more values to this resource.
26
+ */
27
+ add(propertyPath: InversePath, value: AddableSubject | readonly AddableSubject[], graph?: Graph): this;
28
+ add(propertyPath: NamedNode, value: AddableObject | readonly AddableObject[], graph?: Graph): this;
29
+ /**
30
+ * Create a new list, add items to it, and attach it to this resource via predicate in a
31
+ * (this, predicate, newList) statement.
32
+ *
33
+ * Returns the list resource.
34
+ */
35
+ addList(predicate: NamedNode, items: Iterable<AddableObject>, options?: Parameters<Resource["addListItems"]>[1]): Resource;
36
+ /**
37
+ * Add rdf:first and rdf:rest predicates to the current Resource.
38
+ */
39
+ addListItems(items: Iterable<AddableObject>, options?: {
40
+ addSubListResourceValues?: (subListResource: Resource) => void;
41
+ graph?: Graph;
42
+ mintSubListIdentifier?: (item: AddableObject, itemIndex: number) => Identifier;
43
+ }): this;
44
+ /**
45
+ * Delete zero or more values from this resource.
46
+ *
47
+ * If value is empty, delete all values of p
48
+ * Else delete (p, arrayValue) for each value in the array.
49
+ */
50
+ delete(propertyPath: InversePath, value?: AddableSubject | readonly AddableSubject[], graph?: Graph): this;
51
+ delete(propertyPath: NamedNode, value?: AddableObject | readonly AddableObject[], graph?: Graph): this;
52
+ isInstanceOf(class_: NamedNode, options?: {
53
+ excludeSubclasses?: boolean;
54
+ graph?: Graph;
55
+ instanceOfPredicate?: NamedNode;
56
+ subClassOfPredicate?: NamedNode;
57
+ }): boolean;
58
+ isSubClassOf(class_: NamedNode, options?: {
59
+ graph?: Graph;
60
+ subClassOfPredicate?: NamedNode;
61
+ }): boolean;
62
+ /**
63
+ * Delete all existing values of p and then add the specified values.
64
+ */
65
+ set(propertyPath: InversePath, value: AddableSubject | readonly AddableSubject[], graph?: Graph): this;
66
+ set(propertyPath: NamedNode, value: AddableObject | readonly AddableObject[], graph?: Graph): this;
67
+ /**
68
+ * Consider the resource itself as an RDF list.
69
+ */
70
+ toList(options?: {
71
+ graph?: Graph;
72
+ }): Either<Resource.ValueError, Resource.Values>;
73
+ /**
74
+ * Get the first matching value for the property path.
75
+ */
76
+ value(propertyPath: PropertyPath, options?: {
77
+ graph?: Graph;
78
+ }): Either<Resource.ValueError, Resource.Value>;
79
+ /**
80
+ * Get all values for the property path.
81
+ */
82
+ values(propertyPath: PropertyPath, options?: {
83
+ graph?: Graph;
84
+ unique?: boolean;
85
+ }): Resource.Values;
86
+ private addableObjectToTerm;
87
+ private addableObjectsToTerms;
88
+ private addableSubjectsToTerms;
89
+ }
90
+ type AddableSubject = BlankNode | NamedNode;
91
+ type AddableObject = BlankNode | Literal | NamedNode | Exclude<Primitive, Date>;
92
+ type Graph = Exclude<Quad_Graph, Variable>;
93
+ type InversePath = {
94
+ readonly path: NamedNode;
95
+ readonly termType: "InversePath";
96
+ };
97
+ export declare namespace Resource {
98
+ const Identifier: typeof _Identifier;
99
+ type Identifier = _Identifier;
100
+ const ListStructureError: typeof _ListStructureError;
101
+ type ListStructureError = _ListStructureError;
102
+ const MistypedTermValueError: typeof _MistypedTermValueError;
103
+ type MistypedTermValueError = _MistypedTermValueError;
104
+ const ValueError: typeof _ValueError;
105
+ type ValueError = _ValueError;
106
+ const Value: typeof _Value;
107
+ type Value<TermT extends Term = Term> = _Value<TermT>;
108
+ const Values: typeof _Values;
109
+ type Values<T = Value> = _Values<T>;
110
+ }
111
+ export {};
112
+ //# sourceMappingURL=Resource.d.ts.map
@@ -0,0 +1,354 @@
1
+ import DefaultDataFactory from "@rdfjs/data-model";
2
+ import TermSet from "@rdfjs/term-set";
3
+ import { LiteralFactory } from "@rdfx/literal";
4
+ import { Either, Left } from "purify-ts";
5
+ import { DatasetValues } from "./DatasetValues.js";
6
+ import { Identifier as _Identifier } from "./Identifier.js";
7
+ import { ListStructureError as _ListStructureError } from "./ListStructureError.js";
8
+ import { MistypedTermValueError as _MistypedTermValueError } from "./MistypedTermValueError.js";
9
+ import { Value as _Value } from "./Value.js";
10
+ import { ValueError as _ValueError } from "./ValueError.js";
11
+ import { Values as _Values } from "./Values.js";
12
+ import { rdf, rdfs } from "./vocabularies.js";
13
+ /**
14
+ * A Resource abstraction over subjects or objects in an RDF/JS dataset.
15
+ */
16
+ export class Resource {
17
+ constructor(dataset, identifier, options) {
18
+ this.dataset = dataset;
19
+ this.identifier = identifier;
20
+ this.dataFactory = options?.dataFactory ?? DefaultDataFactory;
21
+ this.literalFactory = new LiteralFactory({ dataFactory: this.dataFactory });
22
+ }
23
+ add(propertyPath, value, graph) {
24
+ if (!graph) {
25
+ graph = this.graph;
26
+ }
27
+ switch (propertyPath.termType) {
28
+ case "InversePath":
29
+ for (const subject of this.addableSubjectsToTerms(value)) {
30
+ this.dataset.add(this.dataFactory.quad(subject, propertyPath.path, this.identifier, graph));
31
+ }
32
+ break;
33
+ case "NamedNode":
34
+ for (const object of this.addableObjectsToTerms(value)) {
35
+ this.dataset.add(this.dataFactory.quad(this.identifier, propertyPath, object, graph));
36
+ }
37
+ break;
38
+ }
39
+ return this;
40
+ }
41
+ /**
42
+ * Create a new list, add items to it, and attach it to this resource via predicate in a
43
+ * (this, predicate, newList) statement.
44
+ *
45
+ * Returns the list resource.
46
+ */
47
+ addList(predicate, items, options) {
48
+ const itemsArray = [...items];
49
+ if (itemsArray.length === 0) {
50
+ return new Resource(this.dataset, rdf.nil, {
51
+ dataFactory: this.dataFactory,
52
+ });
53
+ }
54
+ const mintSubListIdentifier = options?.mintSubListIdentifier ?? (() => this.dataFactory.blankNode());
55
+ const listResource = new Resource(this.dataset, mintSubListIdentifier(itemsArray[0], 0), { dataFactory: this.dataFactory });
56
+ listResource.addListItems(itemsArray, {
57
+ graph: options?.graph,
58
+ mintSubListIdentifier,
59
+ });
60
+ this.add(predicate, listResource.identifier, options?.graph);
61
+ return listResource;
62
+ }
63
+ /**
64
+ * Add rdf:first and rdf:rest predicates to the current Resource.
65
+ */
66
+ addListItems(items, options) {
67
+ const addSubListResourceValues = options?.addSubListResourceValues ?? (() => { });
68
+ const graph = options?.graph ?? this.graph;
69
+ const mintSubListIdentifier = options?.mintSubListIdentifier ?? (() => this.dataFactory.blankNode());
70
+ let currentHead = this;
71
+ let itemIndex = 0;
72
+ for (const item of items) {
73
+ if (itemIndex > 0) {
74
+ // If currentHead !== this, then create a new head and point the current head's rdf:rest at it
75
+ const newHead = new Resource(this.dataset, mintSubListIdentifier(item, itemIndex), { dataFactory: this.dataFactory });
76
+ addSubListResourceValues(newHead);
77
+ currentHead.add(rdf.rest, newHead.identifier, graph);
78
+ currentHead = newHead;
79
+ }
80
+ currentHead.add(rdf.first, item, graph);
81
+ itemIndex++;
82
+ }
83
+ if (itemIndex > 0) {
84
+ // If there were any items there was an rdf:first on the current head
85
+ // Close that head by adding an rdf:rest rdf:nil
86
+ currentHead.add(rdf.rest, rdf.nil, graph);
87
+ }
88
+ return this;
89
+ }
90
+ delete(propertyPath, value, graph) {
91
+ if (!graph) {
92
+ graph = this.graph;
93
+ }
94
+ switch (propertyPath.termType) {
95
+ case "InversePath": {
96
+ if (value) {
97
+ for (const subject of this.addableSubjectsToTerms(value)) {
98
+ for (const quad of [
99
+ ...this.dataset.match(subject, propertyPath.path, this.identifier, graph),
100
+ ]) {
101
+ this.dataset.delete(quad);
102
+ }
103
+ }
104
+ }
105
+ else {
106
+ for (const quad of [
107
+ ...this.dataset.match(null, propertyPath.path, this.identifier, graph),
108
+ ]) {
109
+ this.dataset.delete(quad);
110
+ }
111
+ }
112
+ break;
113
+ }
114
+ case "NamedNode": {
115
+ if (value) {
116
+ for (const object of this.addableObjectsToTerms(value)) {
117
+ for (const quad of [
118
+ ...this.dataset.match(this.identifier, propertyPath, object, graph),
119
+ ]) {
120
+ this.dataset.delete(quad);
121
+ }
122
+ }
123
+ }
124
+ else {
125
+ for (const quad of [
126
+ ...this.dataset.match(this.identifier, propertyPath, null, graph),
127
+ ]) {
128
+ this.dataset.delete(quad);
129
+ }
130
+ }
131
+ break;
132
+ }
133
+ }
134
+ return this;
135
+ }
136
+ isInstanceOf(class_, options) {
137
+ return isInstanceOfRecursive({
138
+ class_,
139
+ dataset: this.dataset,
140
+ graph: options?.graph ?? this.graph,
141
+ instance: this.identifier,
142
+ visitedClasses: new TermSet(),
143
+ });
144
+ function isInstanceOfRecursive({ class_, dataset, graph, instance, visitedClasses, }) {
145
+ for (const _ of dataset.match(instance, options?.instanceOfPredicate ?? rdf.type, class_, graph)) {
146
+ return true;
147
+ }
148
+ visitedClasses.add(class_);
149
+ if (options?.excludeSubclasses) {
150
+ return false;
151
+ }
152
+ // Recurse into class's sub-classes that haven't been visited yet.
153
+ for (const quad of dataset.match(null, options?.subClassOfPredicate ?? rdfs.subClassOf, class_, graph)) {
154
+ if (quad.subject.termType !== "NamedNode") {
155
+ continue;
156
+ }
157
+ if (visitedClasses.has(quad.subject)) {
158
+ continue;
159
+ }
160
+ if (isInstanceOfRecursive({
161
+ class_: quad.subject,
162
+ dataset,
163
+ graph,
164
+ instance,
165
+ visitedClasses,
166
+ })) {
167
+ return true;
168
+ }
169
+ }
170
+ return false;
171
+ }
172
+ }
173
+ isSubClassOf(class_, options) {
174
+ return isSubClassOfRecursive({
175
+ class_,
176
+ dataset: this.dataset,
177
+ graph: options?.graph ?? this.graph,
178
+ thisIdentifier: this.identifier,
179
+ visitedClasses: new TermSet(),
180
+ });
181
+ function isSubClassOfRecursive({ class_, dataset, graph, thisIdentifier, visitedClasses, }) {
182
+ for (const _ of dataset.match(thisIdentifier, options?.subClassOfPredicate ?? rdfs.subClassOf, class_, graph)) {
183
+ return true;
184
+ }
185
+ visitedClasses.add(class_);
186
+ // Recurse into class's sub-classes that haven't been visited yet.
187
+ for (const quad of dataset.match(null, options?.subClassOfPredicate ?? rdfs.subClassOf, class_, graph)) {
188
+ if (quad.subject.termType !== "NamedNode") {
189
+ continue;
190
+ }
191
+ if (visitedClasses.has(quad.subject)) {
192
+ continue;
193
+ }
194
+ if (isSubClassOfRecursive({
195
+ class_: quad.subject,
196
+ dataset,
197
+ graph,
198
+ thisIdentifier,
199
+ visitedClasses,
200
+ })) {
201
+ return true;
202
+ }
203
+ }
204
+ return false;
205
+ }
206
+ }
207
+ set(propertyPath, value, graph) {
208
+ switch (propertyPath.termType) {
209
+ case "InversePath":
210
+ this.delete(propertyPath, undefined, graph);
211
+ return this.add(propertyPath, value, graph);
212
+ case "NamedNode":
213
+ this.delete(propertyPath, undefined, graph);
214
+ return this.add(propertyPath, value, graph);
215
+ }
216
+ }
217
+ /**
218
+ * Consider the resource itself as an RDF list.
219
+ */
220
+ toList(options) {
221
+ if (this.identifier.equals(rdf.nil)) {
222
+ return Either.of(Resource.Values.fromArray({
223
+ focusResource: this,
224
+ propertyPath: rdf.nil,
225
+ values: [],
226
+ }));
227
+ }
228
+ const graph = options?.graph ?? this.graph;
229
+ const firstObjects = [
230
+ ...new TermSet([...this.dataset.match(this.identifier, rdf.first, null, graph)].map((quad) => quad.object)),
231
+ ];
232
+ if (firstObjects.length === 0) {
233
+ return Left(new Resource.ListStructureError({
234
+ focusResource: this,
235
+ message: "list has no rdf:first statements",
236
+ propertyPath: rdf.first,
237
+ }));
238
+ }
239
+ if (firstObjects.length > 1) {
240
+ return Left(new Resource.ListStructureError({
241
+ focusResource: this,
242
+ message: "list has multiple rdf:first statements",
243
+ propertyPath: rdf.first,
244
+ }));
245
+ }
246
+ const firstObject = firstObjects[0];
247
+ switch (firstObject.termType) {
248
+ case "BlankNode":
249
+ case "Literal":
250
+ case "NamedNode":
251
+ break;
252
+ default:
253
+ return Left(new Resource.MistypedTermValueError({
254
+ actualValue: firstObject,
255
+ expectedValueType: "BlankNode | Literal | NamedNode",
256
+ focusResource: this,
257
+ propertyPath: rdf.first,
258
+ }));
259
+ }
260
+ const restObjects = [
261
+ ...new TermSet([...this.dataset.match(this.identifier, rdf.rest, null, graph)].map((quad) => quad.object)),
262
+ ];
263
+ if (restObjects.length === 0) {
264
+ return Left(new Resource.ListStructureError({
265
+ focusResource: this,
266
+ message: "list has no rdf:rest statements",
267
+ propertyPath: rdf.rest,
268
+ }));
269
+ }
270
+ if (restObjects.length > 1) {
271
+ return Left(new Resource.ListStructureError({
272
+ focusResource: this,
273
+ message: "list has multiple rdf:rest statements",
274
+ propertyPath: rdf.rest,
275
+ }));
276
+ }
277
+ const restObject = restObjects[0];
278
+ switch (restObject.termType) {
279
+ case "BlankNode":
280
+ case "NamedNode":
281
+ break;
282
+ default:
283
+ return Left(new Resource.MistypedTermValueError({
284
+ actualValue: restObject,
285
+ expectedValueType: "BlankNode | NamedNode",
286
+ focusResource: this,
287
+ propertyPath: rdf.rest,
288
+ }));
289
+ }
290
+ return Either.of(new Resource.Value({
291
+ dataFactory: this.dataFactory,
292
+ focusResource: this,
293
+ propertyPath: rdf.first,
294
+ term: firstObject,
295
+ }).toValues()).chain((items) => new Resource(this.dataset, restObject, {
296
+ dataFactory: this.dataFactory,
297
+ })
298
+ .toList({ graph })
299
+ .map((restItems) => items.concat(...restItems)));
300
+ }
301
+ /**
302
+ * Get the first matching value for the property path.
303
+ */
304
+ value(propertyPath, options) {
305
+ return this.values(propertyPath, options).head();
306
+ }
307
+ /**
308
+ * Get all values for the property path.
309
+ */
310
+ values(propertyPath, options) {
311
+ return new DatasetValues({
312
+ dataFactory: this.dataFactory,
313
+ focusResource: this,
314
+ graph: options?.graph ?? this.graph ?? null,
315
+ propertyPath,
316
+ unique: !!options?.unique,
317
+ });
318
+ }
319
+ addableObjectToTerm(object) {
320
+ switch (typeof object) {
321
+ case "bigint":
322
+ return this.literalFactory.bigint(object);
323
+ case "boolean":
324
+ return this.literalFactory.boolean(object);
325
+ case "number":
326
+ return this.literalFactory.number(object);
327
+ case "string":
328
+ return this.literalFactory.string(object);
329
+ case "object":
330
+ return object;
331
+ }
332
+ }
333
+ addableObjectsToTerms(objects) {
334
+ if (Array.isArray(objects)) {
335
+ return objects.map((value) => this.addableObjectToTerm(value));
336
+ }
337
+ return [this.addableObjectToTerm(objects)];
338
+ }
339
+ addableSubjectsToTerms(subjects) {
340
+ if (Array.isArray(subjects)) {
341
+ return subjects;
342
+ }
343
+ return [subjects];
344
+ }
345
+ }
346
+ (function (Resource) {
347
+ Resource.Identifier = _Identifier;
348
+ Resource.ListStructureError = _ListStructureError;
349
+ Resource.MistypedTermValueError = _MistypedTermValueError;
350
+ Resource.ValueError = _ValueError;
351
+ Resource.Value = _Value;
352
+ Resource.Values = _Values;
353
+ })(Resource || (Resource = {}));
354
+ //# sourceMappingURL=Resource.js.map
@@ -0,0 +1,24 @@
1
+ import type { DataFactory, DatasetCore, NamedNode, Quad_Graph, Variable } from "@rdfjs/types";
2
+ import { Resource } from "./Resource.js";
3
+ /**
4
+ * A ResourceSet wraps an RDF/JS dataset with convenient resource factory methods.
5
+ */
6
+ export declare class ResourceSet {
7
+ readonly dataset: DatasetCore;
8
+ private readonly dataFactory;
9
+ private readonly graph?;
10
+ constructor(dataset: DatasetCore, options?: {
11
+ dataFactory?: DataFactory;
12
+ graph?: Exclude<Quad_Graph, Variable>;
13
+ });
14
+ instancesOf(class_: NamedNode, options?: {
15
+ excludeSubclasses?: boolean;
16
+ graph?: Exclude<Quad_Graph, Variable>;
17
+ instanceOfPredicate?: NamedNode;
18
+ subClassOfPredicate?: NamedNode;
19
+ }): Generator<Resource>;
20
+ namedInstancesOf(class_: NamedNode, options?: Parameters<ResourceSet["instancesOf"]>[1]): Generator<Resource<NamedNode>>;
21
+ resource<IdentifierT extends Resource.Identifier>(identifier: IdentifierT): Resource<IdentifierT>;
22
+ private instanceIdentifiers;
23
+ }
24
+ //# sourceMappingURL=ResourceSet.d.ts.map