@pod-os/core 0.21.1-rc.ec4cab1.0 → 0.21.1-rc.f28b628.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/dist/index.js CHANGED
@@ -3721,22 +3721,26 @@ var FileFetcher = class {
3721
3721
  });
3722
3722
  }
3723
3723
  createNewFile(container2, name9) {
3724
- const encodedName = encodeURIComponent(name9);
3724
+ const isFile = name9 instanceof File;
3725
+ const fileName = isFile ? name9.name : name9;
3726
+ const encodedName = encodeURIComponent(fileName);
3725
3727
  const url7 = container2.uri + encodedName;
3726
- const contentTypeHeader = index_lite_default.getType(encodedName) ?? "text/turtle";
3728
+ const contentTypeHeader = isFile ? name9.type : index_lite_default.getType(encodedName) ?? "text/turtle";
3729
+ const body = isFile ? name9 : void 0;
3727
3730
  return ResultAsync.fromPromise(
3728
3731
  this.session.authenticatedFetch(url7, {
3729
3732
  method: "PUT",
3730
3733
  headers: {
3731
3734
  "Content-Type": contentTypeHeader,
3732
3735
  "If-None-Match": "*"
3733
- }
3736
+ },
3737
+ body
3734
3738
  }),
3735
3739
  (e) => networkProblem("The file could not be created", e)
3736
3740
  ).andThen(
3737
3741
  (response6) => response6.ok ? ok({
3738
3742
  url: url7,
3739
- name: name9,
3743
+ name: fileName,
3740
3744
  contentType: contentTypeHeader
3741
3745
  }) : err(httpProblem("The file could not be created", response6))
3742
3746
  );
@@ -3994,6 +3998,89 @@ var Thing = class {
3994
3998
  assume(SpecificThing) {
3995
3999
  return new SpecificThing(this.uri, this.store, this.editable);
3996
4000
  }
4001
+ /**
4002
+ * Returns the container that contains this thing's document
4003
+ * The container URI is derived from the thing's URI.
4004
+ */
4005
+ container() {
4006
+ const doc = namedNode(this.uri).doc();
4007
+ const baseUri = doc.value.endsWith("/") ? doc.value.slice(0, -1) : doc.value;
4008
+ const uri6 = new URL(".", baseUri).toString();
4009
+ return { uri: uri6 };
4010
+ }
4011
+ };
4012
+
4013
+ // src/ldp-container/LdpContainer.ts
4014
+ var LdpContainer = class extends Thing {
4015
+ constructor(uri6, store, editable = false) {
4016
+ super(uri6, store, editable);
4017
+ this.uri = uri6;
4018
+ this.store = store;
4019
+ this.editable = editable;
4020
+ }
4021
+ contains() {
4022
+ const contains3 = this.store.statementsMatching(
4023
+ namedNode(this.uri),
4024
+ namedNode("http://www.w3.org/ns/ldp#contains"),
4025
+ null,
4026
+ namedNode(this.uri)
4027
+ );
4028
+ return contains3.map((content5) => ({
4029
+ uri: content5.object.value,
4030
+ name: labelFromUri(content5.object.value)
4031
+ }));
4032
+ }
4033
+ };
4034
+
4035
+ // src/picture/createPictureLinkOperation.ts
4036
+ var SCHEMA_IMAGE = "http://schema.org/image";
4037
+ function createPictureLinkOperation(thing, file2) {
4038
+ return {
4039
+ deletions: [],
4040
+ filesToCreate: [],
4041
+ insertions: [
4042
+ st(
4043
+ namedNode(thing.uri),
4044
+ namedNode(SCHEMA_IMAGE),
4045
+ namedNode(file2.url),
4046
+ namedNode(thing.uri).doc()
4047
+ )
4048
+ ]
4049
+ };
4050
+ }
4051
+
4052
+ // src/picture/PictureGateway.ts
4053
+ var PictureGateway = class {
4054
+ constructor(store, fileFetcher) {
4055
+ this.store = store;
4056
+ this.fileFetcher = fileFetcher;
4057
+ }
4058
+ /**
4059
+ * Uploads a picture file and associates it with a thing.
4060
+ * The container is automatically derived from the thing's URI.
4061
+ * Uses schema:image as the predicate.
4062
+ *
4063
+ * @param thing - The thing to add the picture to
4064
+ * @param pictureFile - The picture file to upload
4065
+ * @returns Result with the uploaded picture metadata (url, name, contentType) or error
4066
+ */
4067
+ uploadAndAddPicture(thing, pictureFile) {
4068
+ const container2 = this.getContainerFromThing(thing);
4069
+ return this.fileFetcher.createNewFile(container2, pictureFile).andThen((file2) => this.linkPictureToThing(thing, file2));
4070
+ }
4071
+ linkPictureToThing(thing, file2) {
4072
+ const operation3 = createPictureLinkOperation(thing, file2);
4073
+ return ResultAsync.fromPromise(
4074
+ this.store.executeUpdate(operation3).then(() => file2),
4075
+ () => ({
4076
+ type: "network",
4077
+ title: "Failed to link picture to thing"
4078
+ })
4079
+ );
4080
+ }
4081
+ getContainerFromThing(thing) {
4082
+ return this.store.get(thing.container().uri).assume(LdpContainer);
4083
+ }
3997
4084
  };
3998
4085
 
3999
4086
  // src/profile/WebIdProfile.ts
@@ -25788,28 +25875,6 @@ var AnonymousSession = class {
25788
25875
  }
25789
25876
  };
25790
25877
 
25791
- // src/ldp-container/LdpContainer.ts
25792
- var LdpContainer = class extends Thing {
25793
- constructor(uri6, store, editable = false) {
25794
- super(uri6, store, editable);
25795
- this.uri = uri6;
25796
- this.store = store;
25797
- this.editable = editable;
25798
- }
25799
- contains() {
25800
- const contains3 = this.store.statementsMatching(
25801
- namedNode(this.uri),
25802
- namedNode("http://www.w3.org/ns/ldp#contains"),
25803
- null,
25804
- namedNode(this.uri)
25805
- );
25806
- return contains3.map((content5) => ({
25807
- uri: content5.object.value,
25808
- name: labelFromUri(content5.object.value)
25809
- }));
25810
- }
25811
- };
25812
-
25813
25878
  // src/index.ts
25814
25879
  var PodOS = class {
25815
25880
  constructor({
@@ -25827,9 +25892,10 @@ var PodOS = class {
25827
25892
  internalStore
25828
25893
  );
25829
25894
  this.searchGateway = new SearchGateway(this.store);
25895
+ this.fileFetcher = new FileFetcher(this.session);
25896
+ this.pictureGateway = new PictureGateway(this.store, this.fileFetcher);
25830
25897
  this.flagAuthorizationMetaDataOnSessionChange();
25831
25898
  this.uriService = new UriService(this.store);
25832
- this.fileFetcher = new FileFetcher(this.session);
25833
25899
  }
25834
25900
  /*
25835
25901
  Flagging authorization metadata is necessary every time the user
@@ -25931,6 +25997,17 @@ var PodOS = class {
25931
25997
  async createDefaultLabelIndex(profile2) {
25932
25998
  return await this.searchGateway.createDefaultLabelIndex(profile2);
25933
25999
  }
26000
+ /**
26001
+ * Uploads a picture file and associates it with a thing.
26002
+ * The container is automatically derived from the thing's URI.
26003
+ *
26004
+ * @param thing - The thing to add the picture to
26005
+ * @param pictureFile - The picture file to upload
26006
+ * @returns Result with the picture URL or error
26007
+ */
26008
+ uploadAndAddPicture(thing, pictureFile) {
26009
+ return this.pictureGateway.uploadAndAddPicture(thing, pictureFile);
26010
+ }
25934
26011
  };
25935
26012
  export {
25936
26013
  AnonymousSession,
@@ -25943,6 +26020,7 @@ export {
25943
26020
  LdpContainer,
25944
26021
  NoOfflineCache,
25945
26022
  OfflineCapableFetcher,
26023
+ PictureGateway,
25946
26024
  PodOS,
25947
26025
  RdfDocument,
25948
26026
  SearchGateway,
@@ -25951,6 +26029,7 @@ export {
25951
26029
  Thing,
25952
26030
  UriService,
25953
26031
  WebIdProfile,
26032
+ createPictureLinkOperation,
25954
26033
  httpProblem,
25955
26034
  labelFromUri,
25956
26035
  listKnownTerms,
package/lib/index.js CHANGED
@@ -34751,6 +34751,7 @@ _:patch
34751
34751
  LdpContainer: () => LdpContainer,
34752
34752
  NoOfflineCache: () => NoOfflineCache,
34753
34753
  OfflineCapableFetcher: () => OfflineCapableFetcher,
34754
+ PictureGateway: () => PictureGateway,
34754
34755
  PodOS: () => PodOS,
34755
34756
  RdfDocument: () => RdfDocument,
34756
34757
  SearchGateway: () => SearchGateway,
@@ -34759,6 +34760,7 @@ _:patch
34759
34760
  Thing: () => Thing,
34760
34761
  UriService: () => UriService,
34761
34762
  WebIdProfile: () => WebIdProfile,
34763
+ createPictureLinkOperation: () => createPictureLinkOperation,
34762
34764
  httpProblem: () => httpProblem,
34763
34765
  labelFromUri: () => labelFromUri,
34764
34766
  listKnownTerms: () => listKnownTerms,
@@ -36685,22 +36687,26 @@ _:patch
36685
36687
  });
36686
36688
  }
36687
36689
  createNewFile(container2, name9) {
36688
- const encodedName = encodeURIComponent(name9);
36690
+ const isFile = name9 instanceof File;
36691
+ const fileName = isFile ? name9.name : name9;
36692
+ const encodedName = encodeURIComponent(fileName);
36689
36693
  const url7 = container2.uri + encodedName;
36690
- const contentTypeHeader = index_lite_default.getType(encodedName) ?? "text/turtle";
36694
+ const contentTypeHeader = isFile ? name9.type : index_lite_default.getType(encodedName) ?? "text/turtle";
36695
+ const body = isFile ? name9 : void 0;
36691
36696
  return ResultAsync.fromPromise(
36692
36697
  this.session.authenticatedFetch(url7, {
36693
36698
  method: "PUT",
36694
36699
  headers: {
36695
36700
  "Content-Type": contentTypeHeader,
36696
36701
  "If-None-Match": "*"
36697
- }
36702
+ },
36703
+ body
36698
36704
  }),
36699
36705
  (e) => networkProblem("The file could not be created", e)
36700
36706
  ).andThen(
36701
36707
  (response6) => response6.ok ? ok({
36702
36708
  url: url7,
36703
- name: name9,
36709
+ name: fileName,
36704
36710
  contentType: contentTypeHeader
36705
36711
  }) : err(httpProblem("The file could not be created", response6))
36706
36712
  );
@@ -36728,7 +36734,7 @@ _:patch
36728
36734
  return store.loadModule(module3);
36729
36735
  }
36730
36736
 
36731
- // src/profile/WebIdProfile.ts
36737
+ // src/ldp-container/LdpContainer.ts
36732
36738
  init_esm();
36733
36739
 
36734
36740
  // src/thing/Thing.ts
@@ -36965,9 +36971,94 @@ _:patch
36965
36971
  assume(SpecificThing) {
36966
36972
  return new SpecificThing(this.uri, this.store, this.editable);
36967
36973
  }
36974
+ /**
36975
+ * Returns the container that contains this thing's document
36976
+ * The container URI is derived from the thing's URI.
36977
+ */
36978
+ container() {
36979
+ const doc = namedNode(this.uri).doc();
36980
+ const baseUri = doc.value.endsWith("/") ? doc.value.slice(0, -1) : doc.value;
36981
+ const uri6 = new URL(".", baseUri).toString();
36982
+ return { uri: uri6 };
36983
+ }
36984
+ };
36985
+
36986
+ // src/ldp-container/LdpContainer.ts
36987
+ var LdpContainer = class extends Thing {
36988
+ constructor(uri6, store, editable = false) {
36989
+ super(uri6, store, editable);
36990
+ this.uri = uri6;
36991
+ this.store = store;
36992
+ this.editable = editable;
36993
+ }
36994
+ contains() {
36995
+ const contains3 = this.store.statementsMatching(
36996
+ namedNode(this.uri),
36997
+ namedNode("http://www.w3.org/ns/ldp#contains"),
36998
+ null,
36999
+ namedNode(this.uri)
37000
+ );
37001
+ return contains3.map((content5) => ({
37002
+ uri: content5.object.value,
37003
+ name: labelFromUri(content5.object.value)
37004
+ }));
37005
+ }
37006
+ };
37007
+
37008
+ // src/picture/createPictureLinkOperation.ts
37009
+ init_esm();
37010
+ var SCHEMA_IMAGE = "http://schema.org/image";
37011
+ function createPictureLinkOperation(thing, file2) {
37012
+ return {
37013
+ deletions: [],
37014
+ filesToCreate: [],
37015
+ insertions: [
37016
+ st(
37017
+ namedNode(thing.uri),
37018
+ namedNode(SCHEMA_IMAGE),
37019
+ namedNode(file2.url),
37020
+ namedNode(thing.uri).doc()
37021
+ )
37022
+ ]
37023
+ };
37024
+ }
37025
+
37026
+ // src/picture/PictureGateway.ts
37027
+ var PictureGateway = class {
37028
+ constructor(store, fileFetcher) {
37029
+ this.store = store;
37030
+ this.fileFetcher = fileFetcher;
37031
+ }
37032
+ /**
37033
+ * Uploads a picture file and associates it with a thing.
37034
+ * The container is automatically derived from the thing's URI.
37035
+ * Uses schema:image as the predicate.
37036
+ *
37037
+ * @param thing - The thing to add the picture to
37038
+ * @param pictureFile - The picture file to upload
37039
+ * @returns Result with the uploaded picture metadata (url, name, contentType) or error
37040
+ */
37041
+ uploadAndAddPicture(thing, pictureFile) {
37042
+ const container2 = this.getContainerFromThing(thing);
37043
+ return this.fileFetcher.createNewFile(container2, pictureFile).andThen((file2) => this.linkPictureToThing(thing, file2));
37044
+ }
37045
+ linkPictureToThing(thing, file2) {
37046
+ const operation3 = createPictureLinkOperation(thing, file2);
37047
+ return ResultAsync.fromPromise(
37048
+ this.store.executeUpdate(operation3).then(() => file2),
37049
+ () => ({
37050
+ type: "network",
37051
+ title: "Failed to link picture to thing"
37052
+ })
37053
+ );
37054
+ }
37055
+ getContainerFromThing(thing) {
37056
+ return this.store.get(thing.container().uri).assume(LdpContainer);
37057
+ }
36968
37058
  };
36969
37059
 
36970
37060
  // src/profile/WebIdProfile.ts
37061
+ init_esm();
36971
37062
  var WebIdProfile = class extends Thing {
36972
37063
  constructor(webId, store, editable = false) {
36973
37064
  super(webId, store, editable);
@@ -58773,29 +58864,6 @@ _:patch
58773
58864
  }
58774
58865
  };
58775
58866
 
58776
- // src/ldp-container/LdpContainer.ts
58777
- init_esm();
58778
- var LdpContainer = class extends Thing {
58779
- constructor(uri6, store, editable = false) {
58780
- super(uri6, store, editable);
58781
- this.uri = uri6;
58782
- this.store = store;
58783
- this.editable = editable;
58784
- }
58785
- contains() {
58786
- const contains3 = this.store.statementsMatching(
58787
- namedNode(this.uri),
58788
- namedNode("http://www.w3.org/ns/ldp#contains"),
58789
- null,
58790
- namedNode(this.uri)
58791
- );
58792
- return contains3.map((content5) => ({
58793
- uri: content5.object.value,
58794
- name: labelFromUri(content5.object.value)
58795
- }));
58796
- }
58797
- };
58798
-
58799
58867
  // src/index.ts
58800
58868
  var PodOS = class {
58801
58869
  constructor({
@@ -58813,9 +58881,10 @@ _:patch
58813
58881
  internalStore
58814
58882
  );
58815
58883
  this.searchGateway = new SearchGateway(this.store);
58884
+ this.fileFetcher = new FileFetcher(this.session);
58885
+ this.pictureGateway = new PictureGateway(this.store, this.fileFetcher);
58816
58886
  this.flagAuthorizationMetaDataOnSessionChange();
58817
58887
  this.uriService = new UriService(this.store);
58818
- this.fileFetcher = new FileFetcher(this.session);
58819
58888
  }
58820
58889
  /*
58821
58890
  Flagging authorization metadata is necessary every time the user
@@ -58917,6 +58986,17 @@ _:patch
58917
58986
  async createDefaultLabelIndex(profile2) {
58918
58987
  return await this.searchGateway.createDefaultLabelIndex(profile2);
58919
58988
  }
58989
+ /**
58990
+ * Uploads a picture file and associates it with a thing.
58991
+ * The container is automatically derived from the thing's URI.
58992
+ *
58993
+ * @param thing - The thing to add the picture to
58994
+ * @param pictureFile - The picture file to upload
58995
+ * @returns Result with the picture URL or error
58996
+ */
58997
+ uploadAndAddPicture(thing, pictureFile) {
58998
+ return this.pictureGateway.uploadAndAddPicture(thing, pictureFile);
58999
+ }
58920
59000
  };
58921
59001
  return __toCommonJS(index_exports);
58922
59002
  })();
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@pod-os/core",
3
3
  "description": "Core module of PodOS",
4
- "version": "0.21.1-rc.ec4cab1.0",
4
+ "version": "0.21.1-rc.f28b628.0",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./types/index.d.ts",
@@ -19,14 +19,14 @@ export declare class FileFetcher {
19
19
  * @returns {Promise<Response>} The HTTP response
20
20
  */
21
21
  putFile(file: SolidFile, newContent: string): Promise<Response>;
22
- createNewFile(container: LdpContainer, name: string): ResultAsync<NewFile, NotCreated>;
22
+ createNewFile(container: LdpContainer, name: string | File): ResultAsync<NewFile, NotCreated>;
23
23
  createNewFolder(container: LdpContainer, name: string): ResultAsync<NewFolder, NotCreated>;
24
24
  }
25
- interface NewFolder {
25
+ export interface NewFolder {
26
26
  url: string;
27
27
  name: string;
28
28
  }
29
- interface NewFile {
29
+ export interface NewFile {
30
30
  url: string;
31
31
  name: string;
32
32
  contentType: string;
package/types/index.d.ts CHANGED
@@ -11,11 +11,14 @@ import { Thing } from "./thing";
11
11
  import { UriService } from "./uri/UriService";
12
12
  import { OfflineCache, OnlineStatus } from "./offline-cache";
13
13
  import { IndexedFormula } from "rdflib";
14
+ import { ResultAsync } from "neverthrow";
15
+ import { HttpProblem, NetworkProblem } from "./problems";
14
16
  export * from "./authentication";
15
17
  export * from "./files";
16
18
  export * from "./thing";
17
19
  export * from "./rdf-document";
18
20
  export * from "./ldp-container";
21
+ export * from "./picture";
19
22
  export * from "./profile";
20
23
  export * from "./search";
21
24
  export * from "./offline-cache";
@@ -35,6 +38,7 @@ export declare class PodOS {
35
38
  readonly uriService: UriService;
36
39
  private readonly fileFetcher;
37
40
  private readonly searchGateway;
41
+ private readonly pictureGateway;
38
42
  private readonly offlineCache;
39
43
  constructor({ session, offlineCache, onlineStatus, internalStore, }?: PodOsConfiguration);
40
44
  private flagAuthorizationMetaDataOnSessionChange;
@@ -85,4 +89,15 @@ export declare class PodOS {
85
89
  * @returns the newly created label index
86
90
  */
87
91
  createDefaultLabelIndex(profile: WebIdProfile): Promise<LabelIndex>;
92
+ /**
93
+ * Uploads a picture file and associates it with a thing.
94
+ * The container is automatically derived from the thing's URI.
95
+ *
96
+ * @param thing - The thing to add the picture to
97
+ * @param pictureFile - The picture file to upload
98
+ * @returns Result with the picture URL or error
99
+ */
100
+ uploadAndAddPicture(thing: Thing, pictureFile: File): ResultAsync<{
101
+ url: string;
102
+ }, HttpProblem | NetworkProblem>;
88
103
  }
@@ -0,0 +1,24 @@
1
+ import { ResultAsync } from "neverthrow";
2
+ import { Thing } from "../thing";
3
+ import { Store } from "../Store";
4
+ import { FileFetcher, NewFile } from "../files";
5
+ import { HttpProblem, NetworkProblem } from "../problems";
6
+ export declare class PictureGateway {
7
+ private readonly store;
8
+ private readonly fileFetcher;
9
+ constructor(store: Store, fileFetcher: FileFetcher);
10
+ /**
11
+ * Uploads a picture file and associates it with a thing.
12
+ * The container is automatically derived from the thing's URI.
13
+ * Uses schema:image as the predicate.
14
+ *
15
+ * @param thing - The thing to add the picture to
16
+ * @param pictureFile - The picture file to upload
17
+ * @returns Result with the uploaded picture metadata (url, name, contentType) or error
18
+ */
19
+ uploadAndAddPicture(thing: Thing, pictureFile: File): ResultAsync<UploadedPicture, HttpProblem | NetworkProblem>;
20
+ private linkPictureToThing;
21
+ private getContainerFromThing;
22
+ }
23
+ type UploadedPicture = NewFile;
24
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,12 @@
1
+ import { UpdateOperation } from "@solid-data-modules/rdflib-utils";
2
+ import { Thing } from "../thing";
3
+ import { NewFile } from "../files";
4
+ /**
5
+ * Creates an update operation to link a picture file to a thing.
6
+ * Uses schema:image as the predicate to establish the relationship.
7
+ *
8
+ * @param thing - The thing to link the picture to
9
+ * @param file - The uploaded picture file metadata
10
+ * @returns UpdateOperation that adds the picture link to the thing's document
11
+ */
12
+ export declare function createPictureLinkOperation(thing: Thing, file: NewFile): UpdateOperation;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,2 @@
1
+ export * from "./PictureGateway";
2
+ export * from "./createPictureLinkOperation";
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -75,4 +75,11 @@ export declare class Thing {
75
75
  * @param SpecificThing - a subclass of Thing to assume
76
76
  */
77
77
  assume<T>(SpecificThing: new (uri: string, store: IndexedFormula, editable: boolean) => T): T;
78
+ /**
79
+ * Returns the container that contains this thing's document
80
+ * The container URI is derived from the thing's URI.
81
+ */
82
+ container(): {
83
+ uri: string;
84
+ };
78
85
  }