@plugable-io/js 0.0.5 → 0.0.6

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/README.md CHANGED
@@ -147,6 +147,14 @@ const updatedFile = await client.update('file_id', {
147
147
  await client.delete('file_id');
148
148
  ```
149
149
 
150
+ ## Performance & Caching
151
+
152
+ The client automatically leverages browser HTTP caching based on file checksums:
153
+ - File list responses are cached for 5 minutes in the browser
154
+ - Cache is validated using ETags based on file checksums
155
+ - If files haven't changed, the browser returns cached data instantly
156
+ - No manual cache management needed - it just works!
157
+
150
158
  ## License
151
159
 
152
160
  MIT
package/dist/index.d.mts CHANGED
@@ -3,7 +3,7 @@ interface BucketClientConfig {
3
3
  getToken: () => Promise<string> | string;
4
4
  baseUrl?: string;
5
5
  }
6
- interface FileObject {
6
+ declare class FileObject {
7
7
  id: string;
8
8
  name: string;
9
9
  metadata: Record<string, any>;
@@ -13,6 +13,11 @@ interface FileObject {
13
13
  download_url?: string;
14
14
  created_at: string;
15
15
  updated_at: string;
16
+ private _client?;
17
+ constructor(data: any, client?: any);
18
+ update(metadata?: Record<string, any>, name?: string): Promise<FileObject>;
19
+ delete(): Promise<void>;
20
+ download(): Promise<void>;
16
21
  }
17
22
  interface ListResponse {
18
23
  files: FileObject[];
@@ -45,6 +50,7 @@ declare class BucketClient {
45
50
  private config;
46
51
  constructor(config: BucketClientConfig);
47
52
  private request;
53
+ private wrapFileObject;
48
54
  list(options?: SearchOptions): Promise<ListResponse>;
49
55
  get(id: string): Promise<FileObject>;
50
56
  find(options: SearchOptions): Promise<FileObject | null>;
@@ -53,4 +59,4 @@ declare class BucketClient {
53
59
  upload(file: File, options?: UploadOptions): Promise<FileObject>;
54
60
  }
55
61
 
56
- export { BucketClient, type BucketClientConfig, type FileObject, type ListResponse, type SearchOptions, type UpdateOptions, type UploadOptions };
62
+ export { BucketClient, type BucketClientConfig, FileObject, type ListResponse, type SearchOptions, type UpdateOptions, type UploadOptions };
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ interface BucketClientConfig {
3
3
  getToken: () => Promise<string> | string;
4
4
  baseUrl?: string;
5
5
  }
6
- interface FileObject {
6
+ declare class FileObject {
7
7
  id: string;
8
8
  name: string;
9
9
  metadata: Record<string, any>;
@@ -13,6 +13,11 @@ interface FileObject {
13
13
  download_url?: string;
14
14
  created_at: string;
15
15
  updated_at: string;
16
+ private _client?;
17
+ constructor(data: any, client?: any);
18
+ update(metadata?: Record<string, any>, name?: string): Promise<FileObject>;
19
+ delete(): Promise<void>;
20
+ download(): Promise<void>;
16
21
  }
17
22
  interface ListResponse {
18
23
  files: FileObject[];
@@ -45,6 +50,7 @@ declare class BucketClient {
45
50
  private config;
46
51
  constructor(config: BucketClientConfig);
47
52
  private request;
53
+ private wrapFileObject;
48
54
  list(options?: SearchOptions): Promise<ListResponse>;
49
55
  get(id: string): Promise<FileObject>;
50
56
  find(options: SearchOptions): Promise<FileObject | null>;
@@ -53,4 +59,4 @@ declare class BucketClient {
53
59
  upload(file: File, options?: UploadOptions): Promise<FileObject>;
54
60
  }
55
61
 
56
- export { BucketClient, type BucketClientConfig, type FileObject, type ListResponse, type SearchOptions, type UpdateOptions, type UploadOptions };
62
+ export { BucketClient, type BucketClientConfig, FileObject, type ListResponse, type SearchOptions, type UpdateOptions, type UploadOptions };
package/dist/index.js CHANGED
@@ -32,7 +32,8 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
32
32
  // src/index.ts
33
33
  var index_exports = {};
34
34
  __export(index_exports, {
35
- BucketClient: () => BucketClient
35
+ BucketClient: () => BucketClient,
36
+ FileObject: () => FileObject
36
37
  });
37
38
  module.exports = __toCommonJS(index_exports);
38
39
 
@@ -72,6 +73,68 @@ var calculateChecksum = (file) => {
72
73
  });
73
74
  };
74
75
 
76
+ // src/types.ts
77
+ var FileObject = class {
78
+ constructor(data, client) {
79
+ __publicField(this, "id");
80
+ __publicField(this, "name");
81
+ __publicField(this, "metadata");
82
+ __publicField(this, "checksum");
83
+ __publicField(this, "byte_size");
84
+ __publicField(this, "content_type");
85
+ __publicField(this, "download_url");
86
+ __publicField(this, "created_at");
87
+ __publicField(this, "updated_at");
88
+ __publicField(this, "_client");
89
+ this.id = data.id;
90
+ this.name = data.name;
91
+ this.metadata = data.metadata;
92
+ this.checksum = data.checksum;
93
+ this.byte_size = data.byte_size;
94
+ this.content_type = data.content_type;
95
+ this.download_url = data.download_url;
96
+ this.created_at = data.created_at;
97
+ this.updated_at = data.updated_at;
98
+ this._client = client;
99
+ }
100
+ async update(metadata, name) {
101
+ if (!this._client) {
102
+ throw new Error("Cannot update: File object not associated with a client");
103
+ }
104
+ const updates = {};
105
+ if (metadata !== void 0) updates.metadata = metadata;
106
+ if (name !== void 0) updates.filename = name;
107
+ const updated = await this._client.update(this.id, updates);
108
+ Object.assign(this, updated);
109
+ return this;
110
+ }
111
+ async delete() {
112
+ if (!this._client) {
113
+ throw new Error("Cannot delete: File object not associated with a client");
114
+ }
115
+ await this._client.delete(this.id);
116
+ }
117
+ async download() {
118
+ if (!this._client) {
119
+ throw new Error("Cannot download: File object not associated with a client");
120
+ }
121
+ const refreshed = await this._client.get(this.id);
122
+ Object.assign(this, refreshed);
123
+ if (!this.download_url) {
124
+ throw new Error("No download URL available");
125
+ }
126
+ if (typeof window !== "undefined") {
127
+ const link = document.createElement("a");
128
+ link.href = this.download_url;
129
+ link.download = this.name;
130
+ link.target = "_blank";
131
+ document.body.appendChild(link);
132
+ link.click();
133
+ document.body.removeChild(link);
134
+ }
135
+ }
136
+ };
137
+
75
138
  // src/client.ts
76
139
  var BucketClient = class {
77
140
  constructor(config) {
@@ -79,7 +142,10 @@ var BucketClient = class {
79
142
  __publicField(this, "config");
80
143
  this.config = config;
81
144
  this.client = import_axios.default.create({
82
- baseURL: config.baseUrl || "http://localhost:3000/v1"
145
+ baseURL: config.baseUrl || "http://localhost:3000/v1",
146
+ // Enable axios to respect cache headers
147
+ adapter: "fetch"
148
+ // Use fetch adapter which respects browser cache
83
149
  });
84
150
  this.client.interceptors.request.use(async (req) => {
85
151
  const token = await Promise.resolve(this.config.getToken());
@@ -105,24 +171,32 @@ var BucketClient = class {
105
171
  throw error;
106
172
  }
107
173
  }
174
+ wrapFileObject(data) {
175
+ return new FileObject(data, this);
176
+ }
108
177
  async list(options) {
109
- return this.request("POST", `/buckets/${this.config.bucketId}/files/search`, {
178
+ const response = await this.request("POST", `/buckets/${this.config.bucketId}/files/search`, {
110
179
  ...options
111
180
  });
181
+ return {
182
+ files: response.files.map((f) => this.wrapFileObject(f)),
183
+ paging: response.paging
184
+ };
112
185
  }
113
186
  async get(id) {
114
187
  const file = await this.request("GET", `/buckets/${this.config.bucketId}/files/${id}`);
115
188
  if (!file.checksum) {
116
189
  console.warn(`File ${id} missing checksum`);
117
190
  }
118
- return file;
191
+ return this.wrapFileObject(file);
119
192
  }
120
193
  async find(options) {
121
194
  const response = await this.list({ ...options, per_page: 1 });
122
195
  return response.files.length > 0 ? response.files[0] : null;
123
196
  }
124
197
  async update(id, updates) {
125
- return this.request("PATCH", `/buckets/${this.config.bucketId}/files/${id}`, updates);
198
+ const updated = await this.request("PATCH", `/buckets/${this.config.bucketId}/files/${id}`, updates);
199
+ return this.wrapFileObject(updated);
126
200
  }
127
201
  async delete(id) {
128
202
  await this.request("DELETE", `/buckets/${this.config.bucketId}/files/${id}`);
@@ -149,10 +223,11 @@ var BucketClient = class {
149
223
  }
150
224
  }
151
225
  });
152
- const confirmedFile = await this.request("POST", `/buckets/${this.config.bucketId}/files/confirm`, {
226
+ const confirmedFileData = await this.request("POST", `/buckets/${this.config.bucketId}/files/confirm`, {
153
227
  signed_id: uploadInit.sid,
154
228
  metadata: options?.metadata
155
229
  });
230
+ const confirmedFile = this.wrapFileObject(confirmedFileData);
156
231
  if (options?.onCompleted) {
157
232
  options.onCompleted(confirmedFile);
158
233
  }
@@ -167,5 +242,6 @@ var BucketClient = class {
167
242
  };
168
243
  // Annotate the CommonJS export names for ESM import in node:
169
244
  0 && (module.exports = {
170
- BucketClient
245
+ BucketClient,
246
+ FileObject
171
247
  });
package/dist/index.mjs CHANGED
@@ -38,6 +38,68 @@ var calculateChecksum = (file) => {
38
38
  });
39
39
  };
40
40
 
41
+ // src/types.ts
42
+ var FileObject = class {
43
+ constructor(data, client) {
44
+ __publicField(this, "id");
45
+ __publicField(this, "name");
46
+ __publicField(this, "metadata");
47
+ __publicField(this, "checksum");
48
+ __publicField(this, "byte_size");
49
+ __publicField(this, "content_type");
50
+ __publicField(this, "download_url");
51
+ __publicField(this, "created_at");
52
+ __publicField(this, "updated_at");
53
+ __publicField(this, "_client");
54
+ this.id = data.id;
55
+ this.name = data.name;
56
+ this.metadata = data.metadata;
57
+ this.checksum = data.checksum;
58
+ this.byte_size = data.byte_size;
59
+ this.content_type = data.content_type;
60
+ this.download_url = data.download_url;
61
+ this.created_at = data.created_at;
62
+ this.updated_at = data.updated_at;
63
+ this._client = client;
64
+ }
65
+ async update(metadata, name) {
66
+ if (!this._client) {
67
+ throw new Error("Cannot update: File object not associated with a client");
68
+ }
69
+ const updates = {};
70
+ if (metadata !== void 0) updates.metadata = metadata;
71
+ if (name !== void 0) updates.filename = name;
72
+ const updated = await this._client.update(this.id, updates);
73
+ Object.assign(this, updated);
74
+ return this;
75
+ }
76
+ async delete() {
77
+ if (!this._client) {
78
+ throw new Error("Cannot delete: File object not associated with a client");
79
+ }
80
+ await this._client.delete(this.id);
81
+ }
82
+ async download() {
83
+ if (!this._client) {
84
+ throw new Error("Cannot download: File object not associated with a client");
85
+ }
86
+ const refreshed = await this._client.get(this.id);
87
+ Object.assign(this, refreshed);
88
+ if (!this.download_url) {
89
+ throw new Error("No download URL available");
90
+ }
91
+ if (typeof window !== "undefined") {
92
+ const link = document.createElement("a");
93
+ link.href = this.download_url;
94
+ link.download = this.name;
95
+ link.target = "_blank";
96
+ document.body.appendChild(link);
97
+ link.click();
98
+ document.body.removeChild(link);
99
+ }
100
+ }
101
+ };
102
+
41
103
  // src/client.ts
42
104
  var BucketClient = class {
43
105
  constructor(config) {
@@ -45,7 +107,10 @@ var BucketClient = class {
45
107
  __publicField(this, "config");
46
108
  this.config = config;
47
109
  this.client = axios.create({
48
- baseURL: config.baseUrl || "http://localhost:3000/v1"
110
+ baseURL: config.baseUrl || "http://localhost:3000/v1",
111
+ // Enable axios to respect cache headers
112
+ adapter: "fetch"
113
+ // Use fetch adapter which respects browser cache
49
114
  });
50
115
  this.client.interceptors.request.use(async (req) => {
51
116
  const token = await Promise.resolve(this.config.getToken());
@@ -71,24 +136,32 @@ var BucketClient = class {
71
136
  throw error;
72
137
  }
73
138
  }
139
+ wrapFileObject(data) {
140
+ return new FileObject(data, this);
141
+ }
74
142
  async list(options) {
75
- return this.request("POST", `/buckets/${this.config.bucketId}/files/search`, {
143
+ const response = await this.request("POST", `/buckets/${this.config.bucketId}/files/search`, {
76
144
  ...options
77
145
  });
146
+ return {
147
+ files: response.files.map((f) => this.wrapFileObject(f)),
148
+ paging: response.paging
149
+ };
78
150
  }
79
151
  async get(id) {
80
152
  const file = await this.request("GET", `/buckets/${this.config.bucketId}/files/${id}`);
81
153
  if (!file.checksum) {
82
154
  console.warn(`File ${id} missing checksum`);
83
155
  }
84
- return file;
156
+ return this.wrapFileObject(file);
85
157
  }
86
158
  async find(options) {
87
159
  const response = await this.list({ ...options, per_page: 1 });
88
160
  return response.files.length > 0 ? response.files[0] : null;
89
161
  }
90
162
  async update(id, updates) {
91
- return this.request("PATCH", `/buckets/${this.config.bucketId}/files/${id}`, updates);
163
+ const updated = await this.request("PATCH", `/buckets/${this.config.bucketId}/files/${id}`, updates);
164
+ return this.wrapFileObject(updated);
92
165
  }
93
166
  async delete(id) {
94
167
  await this.request("DELETE", `/buckets/${this.config.bucketId}/files/${id}`);
@@ -115,10 +188,11 @@ var BucketClient = class {
115
188
  }
116
189
  }
117
190
  });
118
- const confirmedFile = await this.request("POST", `/buckets/${this.config.bucketId}/files/confirm`, {
191
+ const confirmedFileData = await this.request("POST", `/buckets/${this.config.bucketId}/files/confirm`, {
119
192
  signed_id: uploadInit.sid,
120
193
  metadata: options?.metadata
121
194
  });
195
+ const confirmedFile = this.wrapFileObject(confirmedFileData);
122
196
  if (options?.onCompleted) {
123
197
  options.onCompleted(confirmedFile);
124
198
  }
@@ -132,5 +206,6 @@ var BucketClient = class {
132
206
  }
133
207
  };
134
208
  export {
135
- BucketClient
209
+ BucketClient,
210
+ FileObject
136
211
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plugable-io/js",
3
- "version": "0.0.5",
3
+ "version": "0.0.6",
4
4
  "description": "JavaScript client for Plugable File Management API",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",