@lobb-js/lobb-ext-storage 0.14.0 → 0.15.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.
@@ -1,47 +0,0 @@
1
- import { Lobb } from "@lobb-js/core";
2
- import { afterAll, beforeAll, describe, expect, it } from "bun:test";
3
- import { readFileSync } from "node:fs";
4
- import { createSimpleConfig } from "./configs/simple.ts";
5
-
6
- describe("Extra Form Data", () => {
7
- let lobb: Lobb;
8
- let baseUrl: string;
9
-
10
- beforeAll(async () => {
11
- const config = createSimpleConfig();
12
- lobb = await Lobb.init(config);
13
- baseUrl = `http://127.0.0.1:${lobb.webServer.port}`;
14
- });
15
-
16
- afterAll(async () => {
17
- await lobb.close();
18
- });
19
-
20
- it("should persist extra form fields alongside the file record", async () => {
21
- const image = readFileSync(import.meta.dirname + "/files/rose.jpeg");
22
-
23
- const formData = new FormData();
24
- formData.append("file", new File([image], "rose.jpeg"));
25
- formData.append("icon", "Image");
26
-
27
- const response = await fetch(
28
- `${baseUrl}/api/collections/storage_fs`,
29
- {
30
- method: "POST",
31
- body: formData,
32
- },
33
- );
34
- const data = await response.json();
35
-
36
- expect(data).toMatchObject({
37
- data: {
38
- name: "rose.jpeg",
39
- path: "/",
40
- type: "file",
41
- icon: "Image",
42
- file_mime_type: "image/jpeg",
43
- file_size: "1086103",
44
- },
45
- });
46
- });
47
- });
@@ -1,292 +0,0 @@
1
- import { Lobb } from "@lobb-js/core";
2
- import { afterAll, beforeAll, describe, expect, it } from "bun:test";
3
- import { readFileSync, existsSync } from "node:fs";
4
- import { createSimpleConfig } from "./configs/simple.ts";
5
-
6
- describe("Files Storage", () => {
7
- let lobb: Lobb;
8
- let baseUrl: string;
9
- let uploadsPath: string;
10
- let createdFileId: number;
11
-
12
- beforeAll(async () => {
13
- const config = createSimpleConfig();
14
- uploadsPath = config.uploadsPath;
15
- lobb = await Lobb.init(config);
16
- baseUrl = `http://127.0.0.1:${lobb.webServer.port}`;
17
- });
18
-
19
- afterAll(async () => {
20
- await lobb.close();
21
- });
22
-
23
- it("should throw an error if no files were provided", async () => {
24
- const response = await fetch(
25
- `${baseUrl}/api/collections/storage_fs`,
26
- {
27
- method: "POST",
28
- body: new FormData(),
29
- },
30
- );
31
- const data = await response.json();
32
-
33
- expect(data).toEqual({
34
- code: "BAD_REQUEST",
35
- status: 400,
36
- message: "No files were provided.",
37
- });
38
- });
39
-
40
- it("should throw an error if more than one file is provided", async () => {
41
- const image = readFileSync(import.meta.dirname + "/files/rose.jpeg");
42
- const imageFileName = "rose.jpeg";
43
-
44
- const formData = new FormData();
45
- formData.append("file", new File([image], imageFileName));
46
- formData.append("file", new File([image], imageFileName));
47
-
48
- const response = await fetch(
49
- `${baseUrl}/api/collections/storage_fs`,
50
- {
51
- method: "POST",
52
- body: formData,
53
- },
54
- );
55
- const data = await response.json();
56
-
57
- expect(data).toEqual({
58
- code: "BAD_REQUEST",
59
- status: 400,
60
- message: "Only one file can be uploaded at a time.",
61
- });
62
- });
63
-
64
- it("should create a file record and upload it successfully", async () => {
65
- const image = readFileSync(import.meta.dirname + "/files/rose.jpeg");
66
- const imageFileName = "rose.jpeg";
67
-
68
- const formData = new FormData();
69
- formData.append(
70
- "file",
71
- new File([image], imageFileName),
72
- );
73
-
74
- const response = await fetch(
75
- `${baseUrl}/api/collections/storage_fs`,
76
- {
77
- method: "POST",
78
- body: formData,
79
- },
80
- );
81
- const result = await response.json();
82
-
83
- createdFileId = result.data.id;
84
-
85
- expect(result).toMatchObject({
86
- data: {
87
- name: "rose.jpeg",
88
- path: "/",
89
- type: "file",
90
- file_mime_type: "image/jpeg",
91
- file_size: "1086103",
92
- },
93
- });
94
-
95
- const uploadedFileExists = existsSync(`${uploadsPath}/${createdFileId}`);
96
-
97
- expect(uploadedFileExists).toBe(true);
98
- });
99
-
100
- it("should prevent uploading a file in a non existing path", async () => {
101
- const image = readFileSync(import.meta.dirname + "/files/rose.jpeg");
102
- const imageFileName = "rose.jpeg";
103
-
104
- const formData = new FormData();
105
- formData.append("file", new File([image], imageFileName));
106
- formData.append("path", "/some/folder/");
107
-
108
- const response = await fetch(
109
- `${baseUrl}/api/collections/storage_fs`,
110
- {
111
- method: "POST",
112
- body: formData,
113
- },
114
- );
115
- const data = await response.json();
116
-
117
- expect(data).toEqual({
118
- code: "BAD_REQUEST",
119
- status: 400,
120
- message: "The specified path does not exist. Please create it first.",
121
- });
122
- });
123
-
124
- it("should create a directory successfully", async () => {
125
- const response = await fetch(
126
- `${baseUrl}/api/collections/storage_fs`,
127
- {
128
- method: "POST",
129
- body: JSON.stringify({
130
- data: {
131
- name: "test_directory",
132
- path: "/",
133
- },
134
- }),
135
- },
136
- );
137
- const data = await response.json();
138
-
139
- expect(data).toMatchObject({
140
- data: {
141
- name: "test_directory",
142
- path: "/",
143
- type: "directory",
144
- },
145
- });
146
- });
147
-
148
- it("should respond with the record of the requested file from the file system collection", async () => {
149
- const response = await fetch(
150
- `${baseUrl}/api/collections/storage_fs/${createdFileId}`,
151
- {
152
- method: "GET",
153
- },
154
- );
155
- const data = await response.json();
156
-
157
- expect(data).toMatchObject({
158
- data: {
159
- name: "rose.jpeg",
160
- path: "/",
161
- type: "file",
162
- file_mime_type: "image/jpeg",
163
- file_size: "1086103",
164
- },
165
- });
166
- });
167
-
168
- it("should respond with the image itself when you specify the action query into view", async () => {
169
- const response = await fetch(
170
- `${baseUrl}/api/collections/storage_fs/${createdFileId}?action=view`,
171
- {
172
- method: "GET",
173
- },
174
- );
175
- const headers = response.headers;
176
- await response.text();
177
-
178
- expect(headers.get("Content-Type")).toBe("image/jpeg");
179
- });
180
-
181
- it("should respond with the image itself and have the (Content-Disposition) header when you specify the action query into download to download it right away if requested from a browser", async () => {
182
- const response = await fetch(
183
- `${baseUrl}/api/collections/storage_fs/${createdFileId}?action=download`,
184
- {
185
- method: "GET",
186
- },
187
- );
188
- const headers = response.headers;
189
- await response.text();
190
-
191
- expect(headers.get("Content-Type")).toBe("image/jpeg");
192
-
193
- expect(
194
- headers.get("Content-Disposition"),
195
- ).toBe(`attachment; filename="rose.jpeg"`);
196
- });
197
-
198
- it("should update the icon of rose.jpeg file successfully", async () => {
199
- const response = await fetch(
200
- `${baseUrl}/api/collections/storage_fs/${createdFileId}`,
201
- {
202
- method: "PATCH",
203
- body: JSON.stringify({
204
- data: {
205
- icon: "Image",
206
- },
207
- }),
208
- },
209
- );
210
- const data = await response.json();
211
-
212
- expect(data).toMatchObject({
213
- data: {
214
- name: "rose.jpeg",
215
- type: "file",
216
- path: "/",
217
- icon: "Image",
218
- file_mime_type: "image/jpeg",
219
- file_size: "1086103",
220
- },
221
- });
222
- });
223
-
224
- it("should update the name of rose.jpeg file successfully", async () => {
225
- const response = await fetch(
226
- `${baseUrl}/api/collections/storage_fs/${createdFileId}`,
227
- {
228
- method: "PATCH",
229
- body: JSON.stringify({
230
- data: {
231
- name: "renamed_file_name.txt",
232
- },
233
- }),
234
- },
235
- );
236
- const data = await response.json();
237
-
238
- expect(data).toMatchObject({
239
- data: {
240
- name: "renamed_file_name.txt",
241
- type: "file",
242
- path: "/",
243
- icon: "Image",
244
- file_mime_type: "image/jpeg",
245
- file_size: "1086103",
246
- },
247
- });
248
- });
249
-
250
- it("should prevent updating the record if the specified path didnt exist", async () => {
251
- const response = await fetch(
252
- `${baseUrl}/api/collections/storage_fs/${createdFileId}`,
253
- {
254
- method: "PATCH",
255
- body: JSON.stringify({
256
- data: {
257
- icon: "Image",
258
- path: "/none_existing_path/bla_bla_bla",
259
- },
260
- }),
261
- },
262
- );
263
- const data = await response.json();
264
-
265
- expect(data).toEqual({
266
- code: "BAD_REQUEST",
267
- status: 400,
268
- message: "The specified path does not exist. Please create it first.",
269
- });
270
- });
271
-
272
- it("should delete the file record and delete the file itself successfully", async () => {
273
- const response = await fetch(
274
- `${baseUrl}/api/collections/storage_fs/${createdFileId}`,
275
- {
276
- method: "DELETE",
277
- },
278
- );
279
- const data = await response.json();
280
-
281
- expect(response.status).toBe(200);
282
- expect(data).toMatchObject({
283
- data: {
284
- name: "renamed_file_name.txt",
285
- path: "/",
286
- type: "file",
287
- file_mime_type: "image/jpeg",
288
- file_size: "1086103",
289
- },
290
- });
291
- });
292
- });
@@ -1,72 +0,0 @@
1
- import { Lobb } from "@lobb-js/core";
2
- import { afterAll, beforeAll, describe, expect, it } from "bun:test";
3
- import { readFileSync } from "node:fs";
4
- import { createSimpleConfig } from "./configs/simple.ts";
5
-
6
- describe("Force Upload", () => {
7
- let lobb: Lobb;
8
- let baseUrl: string;
9
-
10
- beforeAll(async () => {
11
- const config = createSimpleConfig();
12
- lobb = await Lobb.init(config);
13
- baseUrl = `http://127.0.0.1:${lobb.webServer.port}`;
14
- });
15
-
16
- afterAll(async () => {
17
- await lobb.close();
18
- });
19
-
20
- it("should fail uploading to a non-existent path without force", async () => {
21
- const image = readFileSync(import.meta.dirname + "/files/rose.jpeg");
22
- const formData = new FormData();
23
- formData.append("file", new Blob([image]), "rose.jpeg");
24
- formData.append("path", "/does_not_exist");
25
-
26
- const response = await fetch(
27
- `${baseUrl}/api/collections/storage_fs`,
28
- { method: "POST", body: formData },
29
- );
30
-
31
- const data = await response.json();
32
- expect(data).toMatchObject({ code: "BAD_REQUEST" });
33
- });
34
-
35
- it("should upload to a non-existent path with force=true, auto-creating directories", async () => {
36
- const image = readFileSync(import.meta.dirname + "/files/rose.jpeg");
37
- const formData = new FormData();
38
- formData.append("file", new Blob([image]), "rose.jpeg");
39
- formData.append("path", "/auto_created/nested");
40
-
41
- const response = await fetch(
42
- `${baseUrl}/api/collections/storage_fs?force=true`,
43
- { method: "POST", body: formData },
44
- );
45
-
46
- const data = await response.json();
47
-
48
- expect(data).toMatchObject({
49
- data: {
50
- name: "rose.jpeg",
51
- path: "/auto_created/nested",
52
- type: "file",
53
- },
54
- });
55
- });
56
-
57
- it("should have auto-created the directory entries", async () => {
58
- const response = await fetch(
59
- `${baseUrl}/api/collections/storage_fs?sort=id`,
60
- { method: "GET" },
61
- );
62
- const data = await response.json();
63
-
64
- expect(data).toMatchObject({
65
- data: [
66
- { name: "auto_created", path: "/", type: "directory" },
67
- { name: "nested", path: "/auto_created/", type: "directory" },
68
- { name: "rose.jpeg", path: "/auto_created/nested", type: "file" },
69
- ],
70
- });
71
- });
72
- });
@@ -1,189 +0,0 @@
1
- import { Lobb } from "@lobb-js/core";
2
- import { afterAll, beforeAll, describe, expect, it } from "bun:test";
3
- import { readFileSync } from "node:fs";
4
- import { createSimpleConfig } from "./configs/simple.ts";
5
-
6
- describe("Mass Remove", () => {
7
- let lobb: Lobb;
8
- let baseUrl: string;
9
- let createdEntriesIds: any[];
10
- let fileEntryId: string;
11
-
12
- beforeAll(async () => {
13
- const config = createSimpleConfig();
14
- lobb = await Lobb.init(config);
15
- baseUrl = `http://127.0.0.1:${lobb.webServer.port}`;
16
- });
17
-
18
- afterAll(async () => {
19
- await lobb.close();
20
- });
21
-
22
- ///////////////////////////
23
- // ADDING DEPENDANT DATA //
24
- ///////////////////////////
25
-
26
- it("should upload a file successfully", async () => {
27
- const image = readFileSync(import.meta.dirname + "/files/rose.jpeg");
28
- const imageFileName = "rose.jpeg";
29
-
30
- const formData = new FormData();
31
- formData.append(
32
- "file",
33
- new Blob([image]),
34
- imageFileName,
35
- );
36
- formData.append(
37
- "payload",
38
- JSON.stringify({
39
- data: {},
40
- }),
41
- );
42
-
43
- const response = await fetch(
44
- `${baseUrl}/api/collections/storage_fs`,
45
- {
46
- method: "POST",
47
- body: formData,
48
- },
49
- );
50
- const data = await response.json();
51
-
52
- expect(data).toMatchObject({
53
- data: {
54
- name: "rose.jpeg",
55
- path: "/",
56
- type: "file",
57
- file_mime_type: "image/jpeg",
58
- file_size: "1086103",
59
- },
60
- });
61
- });
62
-
63
- it("should create a directory successfully", async () => {
64
- const response = await fetch(
65
- `${baseUrl}/api/collections/storage_fs`,
66
- {
67
- method: "POST",
68
- body: JSON.stringify({
69
- data: {
70
- name: "test_directory",
71
- path: "/",
72
- },
73
- }),
74
- },
75
- );
76
- const data = await response.json();
77
-
78
- expect(data).toMatchObject({
79
- data: {
80
- name: "test_directory",
81
- path: "/",
82
- type: "directory",
83
- },
84
- });
85
- });
86
-
87
- ////////////////////////////
88
- // Remove MASS OPERATIONS //
89
- ////////////////////////////
90
-
91
- it("should list all available entries", async () => {
92
- const response = await fetch(
93
- `${baseUrl}/api/collections/storage_fs?sort=id`,
94
- {
95
- method: "GET",
96
- },
97
- );
98
- const data = await response.json();
99
-
100
- expect(data).toMatchObject({
101
- data: [
102
- {
103
- name: "rose.jpeg",
104
- type: "file",
105
- path: "/",
106
- icon: null,
107
- file_mime_type: "image/jpeg",
108
- file_size: "1086103",
109
- },
110
- {
111
- name: "test_directory",
112
- path: "/",
113
- type: "directory",
114
- icon: null,
115
- },
116
- ],
117
- meta: {
118
- totalCount: 2,
119
- },
120
- });
121
-
122
- createdEntriesIds = (data.data as any[]).map((el) => el.id);
123
- fileEntryId = (data.data as any[]).find((el) => el.type === "file").id;
124
- });
125
-
126
- it("should respond with the content of the file", async () => {
127
- const response = await fetch(
128
- `${baseUrl}/api/collections/storage_fs/${fileEntryId}?action=view`,
129
- {
130
- method: "GET",
131
- },
132
- );
133
- await response.text();
134
-
135
- expect(
136
- response.headers.get("content-type"),
137
- ).toBe("image/jpeg");
138
- });
139
-
140
- it("should remove all entries", async () => {
141
- const response = await fetch(
142
- `${baseUrl}/api/collections/storage_fs`,
143
- {
144
- method: "DELETE",
145
- body: JSON.stringify({
146
- filter: {
147
- id: {
148
- $in: createdEntriesIds,
149
- },
150
- },
151
- }),
152
- },
153
- );
154
- const data = await response.json();
155
-
156
- expect(data).toMatchObject({
157
- affectedCount: 2,
158
- });
159
- });
160
-
161
- it("shouldnt be able to get the content of the removed file using deleteMany", async () => {
162
- const response = await fetch(
163
- `${baseUrl}/api/collections/storage_fs/${fileEntryId}?action=view`,
164
- {
165
- method: "GET",
166
- },
167
- );
168
- await response.json();
169
-
170
- expect(response.status).toBe(404);
171
- });
172
-
173
- it("should list an empty array since all entries are removed", async () => {
174
- const response = await fetch(
175
- `${baseUrl}/api/collections/storage_fs`,
176
- {
177
- method: "GET",
178
- },
179
- );
180
- const data = await response.json();
181
-
182
- expect(data).toMatchObject({
183
- data: [],
184
- meta: {
185
- totalCount: 0,
186
- },
187
- });
188
- });
189
- });
@@ -1,26 +0,0 @@
1
- import { Lobb } from "@lobb-js/core";
2
- import { afterAll, beforeAll, describe, expect, it } from "bun:test";
3
- import { createSimpleConfig } from "./configs/simple.ts";
4
-
5
- describe("Meta Operations", () => {
6
- let lobb: Lobb;
7
- let baseUrl: string;
8
-
9
- beforeAll(async () => {
10
- const config = createSimpleConfig();
11
- lobb = await Lobb.init(config);
12
- baseUrl = `http://127.0.0.1:${lobb.webServer.port}`;
13
- });
14
-
15
- afterAll(async () => {
16
- await lobb.close();
17
- });
18
-
19
- it("should return true for the refresh token", async () => {
20
- const response = await fetch(`${baseUrl}/api/meta`);
21
- const data = await response.json();
22
- expect(data.extensions.storage).toMatchObject({
23
- storageCollectionName: "storage_fs",
24
- });
25
- });
26
- });