@pod-os/core 0.11.2-fe7524c.0 → 0.12.1-eddb6ac.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pod-os/core",
3
- "version": "0.11.2-fe7524c.0",
3
+ "version": "0.12.1-eddb6ac.0",
4
4
  "main": "./dist/index.js",
5
5
  "types": "./types/index.d.ts",
6
6
  "files": [
@@ -24,8 +24,8 @@
24
24
  "author": "Angelo Veltens",
25
25
  "license": "MIT",
26
26
  "devDependencies": {
27
- "@babel/preset-env": "^7.24.0",
28
- "@babel/preset-typescript": "^7.23.3",
27
+ "@babel/preset-env": "^7.24.5",
28
+ "@babel/preset-typescript": "^7.24.1",
29
29
  "@types/jest": "^29.5.12",
30
30
  "@types/jest-when": "^3.5.5",
31
31
  "@types/sparqljs": "^3.1.10",
@@ -37,17 +37,18 @@
37
37
  "jest-when": "^3.6.0",
38
38
  "prettier": "^3.2.5",
39
39
  "rdf-namespaces": "^1.12.0",
40
- "rimraf": "^5.0.5",
40
+ "rimraf": "^5.0.7",
41
41
  "sparqljs": "^3.7.1",
42
- "typescript": "^5.3.3"
42
+ "typescript": "^5.4.5"
43
43
  },
44
44
  "dependencies": {
45
45
  "@inrupt/solid-client-authn-browser": "^1.17.5",
46
- "@solid-data-modules/contacts-rdflib": "^0.4.0",
46
+ "@solid-data-modules/contacts-rdflib": "^0.5.0",
47
47
  "@types/lunr": "^2.3.7",
48
48
  "buffer": "^6.0.3",
49
49
  "lunr": "^2.3.9",
50
- "rdflib": "^2.2.33",
50
+ "rdflib": "^2.2.35",
51
+ "rxjs": "^7.8.1",
51
52
  "slugify": "^1.6.6",
52
53
  "url": "^0.11.3"
53
54
  },
@@ -1,15 +1,23 @@
1
1
  import { ISessionInfo } from "@inrupt/solid-client-authn-browser";
2
+ import { BehaviorSubject } from "rxjs";
2
3
  export type AuthenticatedFetch = (url: RequestInfo, init?: RequestInit | undefined) => Promise<Response>;
4
+ export type SessionInfo = ISessionInfo;
3
5
  export interface PodOsSession {
4
6
  authenticatedFetch: AuthenticatedFetch;
5
7
  }
6
8
  export declare class BrowserSession implements PodOsSession {
7
9
  private readonly session;
8
10
  private readonly _authenticatedFetch;
11
+ private readonly sessionInfo$;
9
12
  get authenticatedFetch(): (url: RequestInfo, init?: RequestInit | undefined) => Promise<Response>;
10
13
  constructor();
11
- handleIncomingRedirect(): Promise<ISessionInfo | undefined>;
14
+ handleIncomingRedirect(restorePreviousSession?: boolean): Promise<ISessionInfo | undefined>;
12
15
  login(oidcIssuer: string): Promise<void>;
13
16
  logout(): Promise<void>;
14
- trackSession(callback: (session: ISessionInfo) => unknown): void;
17
+ /**
18
+ * @deprecated use observeSession instead
19
+ */
20
+ trackSession(callback: (session: SessionInfo) => unknown): void;
21
+ observeSession(): BehaviorSubject<SessionInfo>;
22
+ onSessionRestore(callback: (url: string) => void): void;
15
23
  }
@@ -0,0 +1,4 @@
1
+ import { Session } from "@inrupt/solid-client-authn-browser";
2
+ import { BehaviorSubject } from "rxjs";
3
+ import { SessionInfo } from "./index";
4
+ export declare function observeSession(session: Session): BehaviorSubject<SessionInfo>;
@@ -0,0 +1 @@
1
+ export {};
package/types/index.d.ts CHANGED
@@ -1,8 +1,9 @@
1
- import { ISessionInfo } from "@inrupt/solid-client-authn-browser";
2
1
  import { ContactsModule } from "@solid-data-modules/contacts-rdflib";
2
+ import { BehaviorSubject } from "rxjs";
3
+ import { SessionInfo } from "./authentication";
3
4
  import { SolidFile } from "./files";
4
5
  import { WebIdProfile } from "./profile";
5
- import { SearchIndex } from "./search/SearchIndex";
6
+ import { SearchIndex } from "./search";
6
7
  import { Store } from "./Store";
7
8
  import { Term } from "./terms";
8
9
  import { Thing } from "./thing";
@@ -20,7 +21,8 @@ export declare class PodOS {
20
21
  readonly uriService: UriService;
21
22
  private fileFetcher;
22
23
  constructor();
23
- handleIncomingRedirect(): void;
24
+ private flagAuthorizationMetaDataOnSessionChange;
25
+ handleIncomingRedirect(restorePreviousSession?: boolean): void;
24
26
  fetch(uri: string): Promise<Response>;
25
27
  fetchAll(uris: string[]): Promise<PromiseSettledResult<Response>[]>;
26
28
  fetchFile(url: string): Promise<SolidFile>;
@@ -28,7 +30,20 @@ export declare class PodOS {
28
30
  listKnownTerms(): Term[];
29
31
  addNewThing(uri: string, name: string, type: string): Promise<void>;
30
32
  proposeUriForNewThing(referenceUri: string, name: string): string;
31
- trackSession(callback: (session: ISessionInfo) => unknown): void;
33
+ /**
34
+ * @deprecated use observeSession instead
35
+ * @param callback
36
+ */
37
+ trackSession(callback: (session: SessionInfo) => unknown): void;
38
+ /**
39
+ * returns a behavior subject that can be used to observe changes in the session state
40
+ */
41
+ observeSession(): BehaviorSubject<SessionInfo>;
42
+ /**
43
+ * Calls the provided callback with the original URL that was open before the silent auth redirect
44
+ * @param callback
45
+ */
46
+ onSessionRestore(callback: (url: string) => unknown): void;
32
47
  /**
33
48
  * Fetch the WebId profile and preferences file for the given WebID
34
49
  * @param webId
@@ -1,384 +0,0 @@
1
- import {
2
- Namespace,
3
- isNamedNode,
4
- lit,
5
- namedNode,
6
- st,
7
- v4_default
8
- } from "./chunk-NJZBRQIY.js";
9
- import "./chunk-5NEDDTD5.js";
10
-
11
- // ../node_modules/@solid-data-modules/contacts-rdflib/dist/rdflib/namespaces.js
12
- var rdf = Namespace("http://www.w3.org/1999/02/22-rdf-syntax-ns#");
13
- var vcard = Namespace("http://www.w3.org/2006/vcard/ns#");
14
- var dc = Namespace("http://purl.org/dc/elements/1.1/");
15
-
16
- // ../node_modules/@solid-data-modules/contacts-rdflib/dist/rdflib/queries/AddressBookQuery.js
17
- var AddressBookQuery = class {
18
- constructor(store, addressBookNode) {
19
- this.store = store;
20
- this.addressBookNode = addressBookNode;
21
- this.addressBookDoc = addressBookNode.doc();
22
- }
23
- proposeNewContactNode() {
24
- return this.proposeNewNode("Person");
25
- }
26
- proposeNewGroupNode() {
27
- return this.proposeNewNode("Group");
28
- }
29
- proposeNewNode(containerPath) {
30
- const id = v4_default();
31
- const baseUri = this.addressBookNode.dir()?.uri;
32
- return namedNode(`${baseUri}${containerPath}/${id}/index.ttl#this`);
33
- }
34
- queryTitle() {
35
- return this.store.anyValue(this.addressBookNode, dc("title"), void 0, this.addressBookDoc) ?? "";
36
- }
37
- queryNameEmailIndex() {
38
- const index = this.store.any(this.addressBookNode, vcard("nameEmailIndex"), void 0, this.addressBookDoc);
39
- if (isNamedNode(index)) {
40
- return index;
41
- } else {
42
- return null;
43
- }
44
- }
45
- queryContacts() {
46
- const nameEmailIndex = this.queryNameEmailIndex();
47
- return nameEmailIndex && isNamedNode(nameEmailIndex) ? this.store.each(null, vcard("inAddressBook"), this.addressBookNode, nameEmailIndex).filter((it) => isNamedNode(it)).map((node) => ({
48
- name: this.store.anyValue(node, vcard("fn"), null, nameEmailIndex) ?? "",
49
- uri: node.value
50
- })) : [];
51
- }
52
- queryGroupIndex() {
53
- const index = this.store.any(this.addressBookNode, vcard("groupIndex"), void 0, this.addressBookDoc);
54
- if (isNamedNode(index)) {
55
- return index;
56
- } else {
57
- return null;
58
- }
59
- }
60
- queryGroups() {
61
- const groupIndex = this.queryGroupIndex();
62
- return groupIndex && isNamedNode(groupIndex) ? this.store.each(this.addressBookNode, vcard("includesGroup"), null, groupIndex).filter((it) => isNamedNode(it)).map((node) => ({
63
- name: this.store.anyValue(node, vcard("fn"), null, groupIndex) ?? "",
64
- uri: node.value
65
- })) : [];
66
- }
67
- };
68
-
69
- // ../node_modules/@solid-data-modules/contacts-rdflib/dist/rdflib/queries/ContactQuery.js
70
- var MAILTO_URI_SCHEME = "mailto:";
71
- var TEl_URI_SCHEME = "tel:";
72
- var ContactQuery = class {
73
- constructor(store, contactNode) {
74
- this.store = store;
75
- this.contactNode = contactNode;
76
- this.contactDoc = contactNode.doc();
77
- }
78
- queryName() {
79
- return this.store.anyValue(this.contactNode, vcard("fn"), void 0, this.contactDoc) ?? "";
80
- }
81
- queryEmails() {
82
- const uris = this.getValuesOf(vcard("hasEmail"));
83
- if (uris.length === 0) {
84
- return [];
85
- }
86
- return uris.map((uri) => {
87
- const valueNode = this.getValueNode(uri);
88
- if (isMailtoNode(valueNode)) {
89
- return {
90
- uri,
91
- value: valueNode.value.split(MAILTO_URI_SCHEME)[1]
92
- };
93
- }
94
- }).filter((value) => !!value);
95
- }
96
- queryPhoneNumbers() {
97
- const uris = this.getValuesOf(vcard("hasTelephone"));
98
- if (uris.length === 0) {
99
- return [];
100
- }
101
- return uris.map((uri) => {
102
- const valueNode = this.getValueNode(uri);
103
- if (isTelNode(valueNode)) {
104
- return {
105
- uri,
106
- value: valueNode.value.split(TEl_URI_SCHEME)[1]
107
- };
108
- }
109
- }).filter((value) => !!value);
110
- }
111
- getValuesOf(predicate) {
112
- return this.store.statementsMatching(this.contactNode, predicate, void 0, this.contactDoc).map((it) => it.object.value);
113
- }
114
- getValueNode(uri) {
115
- return this.store.any(namedNode(uri), vcard("value"), void 0, this.contactDoc);
116
- }
117
- };
118
- function isMailtoNode(valueNode) {
119
- return isNamedNode(valueNode) && valueNode.value.startsWith(MAILTO_URI_SCHEME);
120
- }
121
- function isTelNode(valueNode) {
122
- return isNamedNode(valueNode) && valueNode.value.startsWith(TEl_URI_SCHEME);
123
- }
124
-
125
- // ../node_modules/@solid-data-modules/contacts-rdflib/dist/rdflib/update-operations/createAddressBook.js
126
- function createAddressBook(container, name) {
127
- const id = v4_default();
128
- const uri = `${container}${id}/index.ttl#this`;
129
- const nameEmailIndexUri = `${container}${id}/people.ttl`;
130
- const groupIndexUri = `${container}${id}/groups.ttl`;
131
- const insertions = [
132
- st(namedNode(uri), namedNode("http://www.w3.org/1999/02/22-rdf-syntax-ns#type"), vcard("AddressBook"), namedNode(uri).doc()),
133
- st(namedNode(uri), dc("title"), lit(name), namedNode(uri).doc()),
134
- st(namedNode(uri), vcard("nameEmailIndex"), namedNode(nameEmailIndexUri), namedNode(uri).doc()),
135
- st(namedNode(uri), vcard("groupIndex"), namedNode(groupIndexUri), namedNode(uri).doc())
136
- ];
137
- return {
138
- uri,
139
- deletions: [],
140
- insertions,
141
- filesToCreate: [{ uri: nameEmailIndexUri }, { uri: groupIndexUri }]
142
- };
143
- }
144
-
145
- // ../node_modules/@solid-data-modules/contacts-rdflib/dist/rdflib/update-operations/createNewContact.js
146
- function createNewContact(addressBook, newContact) {
147
- const contactNode = addressBook.proposeNewContactNode();
148
- const nameEmailIndex = addressBook.queryNameEmailIndex();
149
- if (!nameEmailIndex) {
150
- throw new Error("name-email index is missing or invalid");
151
- }
152
- const insertions = [
153
- st(contactNode, vcard("inAddressBook"), addressBook.addressBookNode, nameEmailIndex),
154
- st(contactNode, vcard("fn"), lit(newContact.name), nameEmailIndex),
155
- st(contactNode, vcard("fn"), lit(newContact.name), contactNode.doc()),
156
- st(contactNode, rdf("type"), vcard("Individual"), contactNode.doc())
157
- ];
158
- if (newContact.email) {
159
- const emailNode = namedNode(contactNode.doc().uri + "#email");
160
- insertions.push(st(contactNode, vcard("hasEmail"), emailNode, contactNode.doc()), st(emailNode, vcard("value"), namedNode("mailto:" + newContact.email), contactNode.doc()));
161
- }
162
- if (newContact.phoneNumber) {
163
- const phoneNode = namedNode(contactNode.doc().uri + "#phone");
164
- insertions.push(st(contactNode, vcard("hasTelephone"), phoneNode, contactNode.doc()), st(phoneNode, vcard("value"), namedNode("tel:" + newContact.phoneNumber), contactNode.doc()));
165
- }
166
- return {
167
- uri: contactNode.uri,
168
- deletions: [],
169
- insertions,
170
- filesToCreate: []
171
- };
172
- }
173
-
174
- // ../node_modules/@solid-data-modules/contacts-rdflib/dist/rdflib/web-operations/executeUpdate.js
175
- async function executeUpdate(fetcher, updater, operation) {
176
- await updater.updateMany(operation.deletions, operation.insertions);
177
- operation.filesToCreate.map((file) => {
178
- createEmptyTurtleFile(fetcher, file.uri);
179
- });
180
- }
181
- function createEmptyTurtleFile(fetcher, uri) {
182
- return fetcher.webOperation("PUT", uri, {
183
- contentType: "text/turtle"
184
- });
185
- }
186
-
187
- // ../node_modules/@solid-data-modules/contacts-rdflib/dist/rdflib/web-operations/fetchNode.js
188
- async function fetchNode(fetcher, node) {
189
- if (node) {
190
- await fetcher.load(node.value);
191
- }
192
- }
193
-
194
- // ../node_modules/@solid-data-modules/contacts-rdflib/dist/rdflib/update-operations/createNewGroup.js
195
- function createNewGroup(addressBook, groupName) {
196
- const groupIndex = addressBook.queryGroupIndex();
197
- if (!groupIndex) {
198
- throw new Error("group index is missing or invalid");
199
- }
200
- const groupNode = addressBook.proposeNewGroupNode();
201
- const groupDoc = groupNode.doc();
202
- return {
203
- uri: groupNode.uri,
204
- insertions: [
205
- st(groupNode, vcard("fn"), lit(groupName), groupIndex),
206
- st(groupNode, vcard("fn"), lit(groupName), groupDoc),
207
- st(groupNode, rdf("type"), vcard("Group"), groupDoc),
208
- st(addressBook.addressBookNode, vcard("includesGroup"), groupNode, groupIndex)
209
- ],
210
- deletions: [],
211
- filesToCreate: []
212
- };
213
- }
214
-
215
- // ../node_modules/@solid-data-modules/contacts-rdflib/dist/rdflib/queries/GroupQuery.js
216
- var GroupQuery = class {
217
- constructor(store, groupNode) {
218
- this.store = store;
219
- this.groupNode = groupNode;
220
- this.groupDoc = groupNode.doc();
221
- }
222
- queryName() {
223
- return this.store.anyValue(this.groupNode, vcard("fn"), void 0, this.groupDoc) ?? "";
224
- }
225
- queryMembers() {
226
- return this.store.each(this.groupNode, vcard("hasMember"), null, this.groupDoc).filter((it) => isNamedNode(it)).map((node) => ({
227
- uri: node.value,
228
- name: this.store.anyValue(node, vcard("fn"), null, this.groupDoc) ?? ""
229
- }));
230
- }
231
- };
232
-
233
- // ../node_modules/@solid-data-modules/contacts-rdflib/dist/rdflib/update-operations/addContactToGroup.js
234
- function addContactToGroup(contactQuery, groupQuery) {
235
- const name = contactQuery.queryName();
236
- return {
237
- uri: "",
238
- insertions: [
239
- st(groupQuery.groupNode, vcard("hasMember"), contactQuery.contactNode, groupQuery.groupNode.doc()),
240
- st(contactQuery.contactNode, vcard("fn"), lit(name), groupQuery.groupNode.doc())
241
- ],
242
- deletions: [],
243
- filesToCreate: []
244
- };
245
- }
246
-
247
- // ../node_modules/@solid-data-modules/contacts-rdflib/dist/rdflib/update-operations/removeContactFromGroup.js
248
- function removeContactFromGroup(contactQuery, groupQuery) {
249
- const contactUri = contactQuery.contactNode.uri;
250
- const member = groupQuery.queryMembers().find((it) => it.uri === contactUri);
251
- if (!member) {
252
- throw new Error("member not found in group");
253
- }
254
- return {
255
- uri: "",
256
- insertions: [],
257
- deletions: [
258
- st(groupQuery.groupNode, vcard("hasMember"), contactQuery.contactNode, groupQuery.groupNode.doc()),
259
- st(contactQuery.contactNode, vcard("fn"), lit(member.name), groupQuery.groupNode.doc())
260
- ],
261
- filesToCreate: []
262
- };
263
- }
264
-
265
- // ../node_modules/@solid-data-modules/contacts-rdflib/dist/rdflib/ContactsModuleRdfLib.js
266
- var ContactsModuleRdfLib = class {
267
- constructor(config) {
268
- this.store = config.store;
269
- this.fetcher = config.fetcher;
270
- this.updater = config.updater;
271
- }
272
- async readAddressBook(uri) {
273
- const addressBookNode = namedNode(uri);
274
- await this.fetchNode(addressBookNode);
275
- const query = new AddressBookQuery(this.store, addressBookNode);
276
- const title = query.queryTitle();
277
- const nameEmailIndex = query.queryNameEmailIndex();
278
- const groupIndex = query.queryGroupIndex();
279
- await Promise.allSettled([
280
- this.fetchNode(nameEmailIndex),
281
- this.fetchNode(groupIndex)
282
- ]);
283
- await this.fetchAll([nameEmailIndex, groupIndex]);
284
- const contacts = query.queryContacts();
285
- const groups = query.queryGroups();
286
- return {
287
- uri,
288
- title,
289
- contacts,
290
- groups
291
- };
292
- }
293
- async fetchNode(node) {
294
- return fetchNode(this.fetcher, node);
295
- }
296
- async fetchAll(nodes) {
297
- return Promise.all(nodes.map((it) => this.fetchNode(it)));
298
- }
299
- async createAddressBook({ containerUri, name }) {
300
- const operation = createAddressBook(containerUri, name);
301
- await executeUpdate(this.fetcher, this.updater, operation);
302
- return operation.uri;
303
- }
304
- async createNewContact({ addressBookUri, contact, groupUris }) {
305
- const contactQuery = await this.executeCreateNewContact(addressBookUri, contact);
306
- await this.executeAddContactToGroups(groupUris, contactQuery);
307
- return contactQuery.contactNode.uri;
308
- }
309
- async executeAddContactToGroups(groupUris, contactQuery) {
310
- const groupNodes = (groupUris ?? []).map((it) => namedNode(it));
311
- await this.fetchAll(groupNodes);
312
- const groupUpdates = groupNodes.map((groupNode) => {
313
- const groupQuery = new GroupQuery(this.store, groupNode);
314
- const operation = addContactToGroup(contactQuery, groupQuery);
315
- return executeUpdate(this.fetcher, this.updater, operation);
316
- });
317
- await Promise.allSettled(groupUpdates);
318
- }
319
- async executeCreateNewContact(addressBookUri, contact) {
320
- const addressBookNode = namedNode(addressBookUri);
321
- await this.fetchNode(addressBookNode);
322
- const operation = createNewContact(new AddressBookQuery(this.store, addressBookNode), contact);
323
- await executeUpdate(this.fetcher, this.updater, operation);
324
- return new ContactQuery(this.store, namedNode(operation.uri));
325
- }
326
- async readContact(uri) {
327
- const contactNode = namedNode(uri);
328
- await this.fetchNode(contactNode);
329
- const query = new ContactQuery(this.store, contactNode);
330
- const name = query.queryName();
331
- const emails = query.queryEmails();
332
- const phoneNumbers = query.queryPhoneNumbers();
333
- return {
334
- uri,
335
- name,
336
- emails,
337
- phoneNumbers
338
- };
339
- }
340
- async createNewGroup({ addressBookUri, groupName }) {
341
- const addressBookNode = namedNode(addressBookUri);
342
- await this.fetchNode(addressBookNode);
343
- const query = new AddressBookQuery(this.store, addressBookNode);
344
- const operation = createNewGroup(query, groupName);
345
- await executeUpdate(this.fetcher, this.updater, operation);
346
- return operation.uri;
347
- }
348
- async readGroup(uri) {
349
- const groupNode = namedNode(uri);
350
- await this.fetchNode(groupNode);
351
- const query = new GroupQuery(this.store, groupNode);
352
- const name = query.queryName();
353
- const members = query.queryMembers();
354
- return {
355
- uri,
356
- name,
357
- members
358
- };
359
- }
360
- async addContactToGroup({ contactUri, groupUri }) {
361
- const contactNode = namedNode(contactUri);
362
- const groupNode = namedNode(groupUri);
363
- await this.fetchNode(contactNode);
364
- const contactQuery = new ContactQuery(this.store, contactNode);
365
- const groupQuery = new GroupQuery(this.store, groupNode);
366
- const operation = addContactToGroup(contactQuery, groupQuery);
367
- await executeUpdate(this.fetcher, this.updater, operation);
368
- }
369
- async removeContactFromGroup({ contactUri, groupUri }) {
370
- const contactNode = namedNode(contactUri);
371
- const groupNode = namedNode(groupUri);
372
- await this.fetchNode(groupNode);
373
- const contactQuery = new ContactQuery(this.store, contactNode);
374
- const groupQuery = new GroupQuery(this.store, groupNode);
375
- const operation = removeContactFromGroup(contactQuery, groupQuery);
376
- await executeUpdate(this.fetcher, this.updater, operation);
377
- }
378
- };
379
-
380
- // ../node_modules/@solid-data-modules/contacts-rdflib/dist/index.js
381
- var dist_default = ContactsModuleRdfLib;
382
- export {
383
- dist_default as default
384
- };