s3db.js 1.0.7 → 2.0.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/README.md +379 -189
- package/build/cache/s3-cache.class.js +7 -5
- package/build/cache/s3-resource-cache.class.js +6 -8
- package/build/cache/serializers.type.js +1 -0
- package/build/index.js +23 -6
- package/build/plugins/costs.plugin.js +65 -0
- package/build/plugins/index.js +8 -0
- package/build/{plugin.interface.js → plugins/plugin.interface.js} +0 -0
- package/build/s3-client.class.js +52 -21
- package/build/{resource.interface.js → s3-database-config.interface.js} +0 -0
- package/build/{s3db.class.js → s3-database.class.js} +20 -15
- package/build/{resource.class.js → s3-resource.class.js} +69 -74
- package/build/{s3db-config.interface.js → s3-resource.interface.js} +0 -0
- package/build/stream/index.js +19 -0
- package/build/stream/resource-ids-read-stream.class.js +3 -1
- package/build/stream/resource-ids-transformer.class.js +3 -1
- package/build/stream/resource-write-stream.class.js +4 -2
- package/package.json +16 -9
- package/.github/workflows/pipeline.yml +0 -16
- package/examples/1-bulk-insert.js +0 -64
- package/examples/2-read-stream.js +0 -61
- package/examples/3-read-stream-to-csv.js +0 -57
- package/examples/4-read-stream-to-zip.js +0 -56
- package/examples/5-write-stream.js +0 -98
- package/examples/6-jwt-tokens.js +0 -124
- package/examples/concerns/index.js +0 -64
- package/src/cache/avro.serializer.ts +0 -12
- package/src/cache/json.serializer.ts +0 -4
- package/src/cache/s3-cache.class.ts +0 -155
- package/src/cache/s3-resource-cache.class.ts +0 -75
- package/src/cache/serializers.type.ts +0 -8
- package/src/errors.ts +0 -96
- package/src/index.ts +0 -4
- package/src/metadata.interface.ts +0 -4
- package/src/plugin.interface.ts +0 -4
- package/src/resource.class.ts +0 -529
- package/src/resource.interface.ts +0 -21
- package/src/s3-client.class.ts +0 -297
- package/src/s3db-config.interface.ts +0 -9
- package/src/s3db.class.ts +0 -215
- package/src/stream/resource-ids-read-stream.class.ts +0 -90
- package/src/stream/resource-ids-transformer.class.ts +0 -38
- package/src/stream/resource-write-stream.class.ts +0 -78
- package/src/validator.ts +0 -39
- package/tests/cache.spec.ts +0 -187
- package/tests/concerns/index.ts +0 -16
- package/tests/config.spec.ts +0 -29
- package/tests/resources.spec.ts +0 -197
package/README.md
CHANGED
|
@@ -1,34 +1,49 @@
|
|
|
1
1
|
# s3db.js
|
|
2
2
|
|
|
3
|
+
[](http://unlicense.org/) [](https://www.npmjs.com/package/s3db.js) [](https://codeclimate.com/github/forattini-dev/s3db.js/maintainability) [](https://coveralls.io/github/forattini-dev/s3db.js?branch=main)
|
|
4
|
+
|
|
3
5
|
Another way to create a cheap document-base database with an easy ORM to handle your dataset!
|
|
4
6
|
|
|
7
|
+
<table width="100%">
|
|
8
|
+
<tr>
|
|
9
|
+
<td>
|
|
10
|
+
|
|
5
11
|
1. <a href="#motivation">Motivation</a>
|
|
6
|
-
1. <a href="#install">Install</a>
|
|
7
12
|
1. <a href="#usage">Usage</a>
|
|
13
|
+
1. <a href="#install">Install</a>
|
|
8
14
|
1. <a href="#quick-setup">Quick Setup</a>
|
|
9
15
|
1. <a href="#insights">Insights</a>
|
|
10
16
|
1. <a href="#database">Database</a>
|
|
11
17
|
1. <a href="#create-a-resource">Create a resource</a>
|
|
12
18
|
1. <a href="#resource-methods">Resource methods</a>
|
|
13
|
-
1. <a href="#insert">Insert</a>
|
|
14
|
-
1. <a href="#
|
|
15
|
-
1. <a href="#
|
|
16
|
-
1. <a href="#
|
|
17
|
-
1. <a href="#delete">Delete</a>
|
|
19
|
+
1. <a href="#insert-one">Insert one</a>
|
|
20
|
+
1. <a href="#get-one">Get one</a>
|
|
21
|
+
1. <a href="#update-one">Update one</a>
|
|
22
|
+
1. <a href="#delete-one">Delete one</a>
|
|
18
23
|
1. <a href="#count">Count</a>
|
|
19
|
-
1. <a href="#
|
|
20
|
-
1. <a href="#get-
|
|
21
|
-
1. <a href="#delete-all">Delete all</a>
|
|
24
|
+
1. <a href="#insert-many">Insert many</a>
|
|
25
|
+
1. <a href="#get-many">Get many</a>
|
|
22
26
|
1. <a href="#get-all">Get all</a>
|
|
27
|
+
1. <a href="#delete-many">Delete many</a>
|
|
28
|
+
1. <a href="#delete-all">Delete all</a>
|
|
29
|
+
1. <a href="#list-ids">List ids</a>
|
|
23
30
|
1. <a href="#resource-streams">Resource streams</a>
|
|
24
31
|
1. <a href="#readable-stream">Readable stream</a>
|
|
25
32
|
1. <a href="#writable-stream">Writable stream</a>
|
|
26
|
-
1. <a href="#events">Events</a>
|
|
27
33
|
1. <a href="#s3-client">S3 Client</a>
|
|
34
|
+
1. <a href="#events">Events</a>
|
|
35
|
+
1. <a href="#plugins">Plugins</a>
|
|
28
36
|
1. <a href="#examples">Examples</a>
|
|
29
37
|
1. <a href="#cost-simulation">Cost Simulation</a>
|
|
30
38
|
1. <a href="#big-example">Big Example</a>
|
|
31
39
|
1. <a href="#small-example">Small example</a>
|
|
40
|
+
1. <a href="#roadmap">Roadmap</a>
|
|
41
|
+
|
|
42
|
+
</td>
|
|
43
|
+
</tr>
|
|
44
|
+
</table>
|
|
45
|
+
|
|
46
|
+
---
|
|
32
47
|
|
|
33
48
|
## Motivation
|
|
34
49
|
|
|
@@ -52,24 +67,28 @@ Check the <a href="#cost-simulation">cost simulation</a> section below for a dee
|
|
|
52
67
|
|
|
53
68
|
Lets give it a try! :)
|
|
54
69
|
|
|
55
|
-
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## Usage
|
|
73
|
+
|
|
74
|
+
You may check the snippets bellow or go straight to the <a href="#examples">Examples</a> section!
|
|
75
|
+
|
|
76
|
+
### Install
|
|
56
77
|
|
|
57
78
|
```bash
|
|
58
79
|
npm i s3db.js
|
|
80
|
+
|
|
59
81
|
# or
|
|
82
|
+
|
|
60
83
|
yarn add s3db.js
|
|
61
84
|
```
|
|
62
85
|
|
|
63
|
-
## Usage
|
|
64
|
-
|
|
65
|
-
You may check the snippets bellow or go straight to the <a href="#examples">Examples</a> section!
|
|
66
|
-
|
|
67
86
|
### Quick setup
|
|
68
87
|
|
|
69
88
|
Our S3db client use connection string params.
|
|
70
89
|
|
|
71
90
|
```javascript
|
|
72
|
-
import S3db from "s3db.js";
|
|
91
|
+
import { S3db } from "s3db.js";
|
|
73
92
|
|
|
74
93
|
const {
|
|
75
94
|
AWS_BUCKET,
|
|
@@ -92,14 +111,14 @@ If you do use `dotenv` package:
|
|
|
92
111
|
import * as dotenv from "dotenv";
|
|
93
112
|
dotenv.config();
|
|
94
113
|
|
|
95
|
-
import S3db from "s3db.js";
|
|
114
|
+
import { S3db } from "s3db.js";
|
|
96
115
|
```
|
|
97
116
|
|
|
98
117
|
### Insights
|
|
99
118
|
|
|
100
119
|
- This implementation of ORM simulates a document repository. Due to the fact that `s3db.js` uses `aws-sdk`'s' S3 api; all requests are GET/PUT as `key=value` resources. So the best case scenario is to access like a document implementation.
|
|
101
120
|
|
|
102
|
-
- For better use of the <a href="#cache"
|
|
121
|
+
- For better use of the <a href="#cache">cache</a> and listing, the best ID format is to use sequential ids with leading zeros (eq: 00001, 00002, 00003) due to S3 internal keys sorting method. But you will need to manage this incremental ID by your own.
|
|
103
122
|
|
|
104
123
|
### Database
|
|
105
124
|
|
|
@@ -113,7 +132,7 @@ Your `s3db.js` client can be initiated with options:
|
|
|
113
132
|
| ttl | true | (Coming soon) TTL to your cache duration in seconds | `number` | 86400 |
|
|
114
133
|
| uri | false | A url as your S3 connection string | `string` | `undefined` |
|
|
115
134
|
|
|
116
|
-
|
|
135
|
+
Config example:
|
|
117
136
|
|
|
118
137
|
```javascript
|
|
119
138
|
const {
|
|
@@ -124,11 +143,7 @@ const {
|
|
|
124
143
|
} = process.env;
|
|
125
144
|
|
|
126
145
|
const uri = `s3://${AWS_ACCESS_KEY_ID}:${AWS_SECRET_ACCESS_KEY}@${AWS_BUCKET}/${AWS_BUCKET_PREFIX}`;
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
Config example:
|
|
130
146
|
|
|
131
|
-
```javascript
|
|
132
147
|
const options = {
|
|
133
148
|
uri,
|
|
134
149
|
parallelism: 25,
|
|
@@ -136,19 +151,21 @@ const options = {
|
|
|
136
151
|
};
|
|
137
152
|
```
|
|
138
153
|
|
|
139
|
-
|
|
154
|
+
#### s3db.connect()
|
|
140
155
|
|
|
141
|
-
|
|
156
|
+
This method must always be invoked before any operation take place. This will interact with AWS' S3 api and check the itens below:
|
|
142
157
|
|
|
143
|
-
1.
|
|
144
|
-
|
|
145
|
-
|
|
158
|
+
1. With current credentials:
|
|
159
|
+
- Check if client has access to the S3 bucket.
|
|
160
|
+
- Check if client has access to bucket life-cycle policies.
|
|
161
|
+
1. With defined database:
|
|
162
|
+
- Check if there is already a database in this connection string.
|
|
163
|
+
- If any database is found, downloads it's medatada and loads each `Resource` definition.
|
|
164
|
+
- Else, it will generate an empty <a href="#metadata-file">`metadata`</a> file into this prefix and mark that this is a new database from scratch.
|
|
146
165
|
|
|
147
166
|
#### Metadata file
|
|
148
167
|
|
|
149
|
-
`s3db.js` will generate a file
|
|
150
|
-
|
|
151
|
-
It has this structure:
|
|
168
|
+
`s3db.js` will generate a file `/s3db.json` at the pre-defined prefix with this structure:
|
|
152
169
|
|
|
153
170
|
```javascript
|
|
154
171
|
{
|
|
@@ -180,7 +197,7 @@ It has this structure:
|
|
|
180
197
|
}
|
|
181
198
|
```
|
|
182
199
|
|
|
183
|
-
|
|
200
|
+
### Create a resource
|
|
184
201
|
|
|
185
202
|
Resources are definitions of data collections.
|
|
186
203
|
|
|
@@ -200,8 +217,8 @@ const attributes = {
|
|
|
200
217
|
},
|
|
201
218
|
};
|
|
202
219
|
|
|
203
|
-
await s3db.createResource({
|
|
204
|
-
|
|
220
|
+
const resource = await s3db.createResource({
|
|
221
|
+
name: "leads",
|
|
205
222
|
attributes,
|
|
206
223
|
});
|
|
207
224
|
```
|
|
@@ -240,11 +257,19 @@ const attributes = {
|
|
|
240
257
|
};
|
|
241
258
|
```
|
|
242
259
|
|
|
260
|
+
##### Reference:
|
|
261
|
+
|
|
262
|
+
You may just use the reference:
|
|
263
|
+
|
|
264
|
+
```javascript
|
|
265
|
+
const Leads = s3db.resource("leads");
|
|
266
|
+
```
|
|
267
|
+
|
|
243
268
|
##### Limitations:
|
|
244
269
|
|
|
245
270
|
As we need to store the resource definition within a JSON file, to keep your definitions intact the best way is to use the [string-based shorthand definitions](https://github.com/icebob/fastest-validator#shorthand-definitions) in your resource definition.
|
|
246
271
|
|
|
247
|
-
By design,
|
|
272
|
+
By design, the resource definition **will will strip all functions** in attributes to avoid `eval()` calls.
|
|
248
273
|
|
|
249
274
|
The `fastest-validator` starts with the params below:
|
|
250
275
|
|
|
@@ -260,15 +285,9 @@ The `fastest-validator` starts with the params below:
|
|
|
260
285
|
}
|
|
261
286
|
```
|
|
262
287
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
You may just use the reference:
|
|
288
|
+
---
|
|
266
289
|
|
|
267
|
-
|
|
268
|
-
const Leads = s3db.resource("leads");
|
|
269
|
-
```
|
|
270
|
-
|
|
271
|
-
### Resources methods
|
|
290
|
+
## Resources methods
|
|
272
291
|
|
|
273
292
|
Consider `resource` as:
|
|
274
293
|
|
|
@@ -276,11 +295,11 @@ Consider `resource` as:
|
|
|
276
295
|
const resource = s3db.resource("leads");
|
|
277
296
|
```
|
|
278
297
|
|
|
279
|
-
|
|
298
|
+
### Insert one
|
|
280
299
|
|
|
281
300
|
```javascript
|
|
282
301
|
// data
|
|
283
|
-
const
|
|
302
|
+
const insertedData = await resource.insert({
|
|
284
303
|
id: "mypersonal@email.com", // if not defined a id will be generated!
|
|
285
304
|
utm: {
|
|
286
305
|
source: "abc",
|
|
@@ -291,44 +310,28 @@ const data = {
|
|
|
291
310
|
mobileNumber: "+5511234567890",
|
|
292
311
|
},
|
|
293
312
|
invalidAttr: "this attribute will disappear",
|
|
294
|
-
};
|
|
313
|
+
});
|
|
295
314
|
|
|
296
|
-
|
|
315
|
+
// {
|
|
316
|
+
// id: "mypersonal@email.com",
|
|
317
|
+
// utm: {
|
|
318
|
+
// source: "abc",
|
|
319
|
+
// },
|
|
320
|
+
// lead: {
|
|
321
|
+
// fullName: "My Complex Name",
|
|
322
|
+
// personalEmail: "mypersonal@email.com",
|
|
323
|
+
// mobileNumber: "+5511234567890",
|
|
324
|
+
// },
|
|
325
|
+
// invalidAttr: "this attribute will disappear",
|
|
326
|
+
// }
|
|
297
327
|
```
|
|
298
328
|
|
|
299
329
|
If not defined an id attribute, `s3db.js` will use [`nanoid`](https://github.com/ai/nanoid) to generate a random unique id!
|
|
300
330
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
You may bulk insert data with a friendly method.
|
|
304
|
-
|
|
305
|
-
This method uses [`supercharge/promise-pool`](https://github.com/supercharge/promise-pool) to organize the parallelism of your promises.
|
|
306
|
-
|
|
307
|
-
```javascript
|
|
308
|
-
const s3db = new S3db({
|
|
309
|
-
parallelism: 10, // default
|
|
310
|
-
});
|
|
311
|
-
```
|
|
312
|
-
|
|
313
|
-
Bulk insert:
|
|
314
|
-
|
|
315
|
-
```javascript
|
|
316
|
-
const objects = new Array(100).fill(0).map((v, k) => ({
|
|
317
|
-
id: `bulk-${k}@mymail.com`,
|
|
318
|
-
lead: {
|
|
319
|
-
fullName: "My Test Name",
|
|
320
|
-
personalEmail: `bulk-${k}@mymail.com`,
|
|
321
|
-
mobileNumber: "+55 11 1234567890",
|
|
322
|
-
},
|
|
323
|
-
}));
|
|
324
|
-
|
|
325
|
-
await resource.bulkInsert(objects);
|
|
326
|
-
```
|
|
327
|
-
|
|
328
|
-
#### Get
|
|
331
|
+
### Get one
|
|
329
332
|
|
|
330
333
|
```javascript
|
|
331
|
-
const obj = await resource.
|
|
334
|
+
const obj = await resource.get("mypersonal@email.com");
|
|
332
335
|
|
|
333
336
|
// {
|
|
334
337
|
// id: "mypersonal@email.com",
|
|
@@ -343,11 +346,12 @@ const obj = await resource.getById("mypersonal@email.com");
|
|
|
343
346
|
// }
|
|
344
347
|
```
|
|
345
348
|
|
|
346
|
-
|
|
349
|
+
### Update one
|
|
347
350
|
|
|
348
351
|
```javascript
|
|
349
|
-
const obj = await resource.
|
|
352
|
+
const obj = await resource.update("mypersonal@email.com", {
|
|
350
353
|
lead: {
|
|
354
|
+
fullName: "My New Name",
|
|
351
355
|
mobileNumber: "+5511999999999",
|
|
352
356
|
},
|
|
353
357
|
});
|
|
@@ -358,20 +362,20 @@ const obj = await resource.updateById("mypersonal@email.com", {
|
|
|
358
362
|
// source: "abc",
|
|
359
363
|
// },
|
|
360
364
|
// lead: {
|
|
361
|
-
// fullName: "My
|
|
365
|
+
// fullName: "My New Name",
|
|
362
366
|
// personalEmail: "mypersonal@email.com",
|
|
363
367
|
// mobileNumber: "+5511999999999",
|
|
364
368
|
// },
|
|
365
369
|
// }
|
|
366
370
|
```
|
|
367
371
|
|
|
368
|
-
|
|
372
|
+
### Delete one
|
|
369
373
|
|
|
370
374
|
```javascript
|
|
371
|
-
await resource.
|
|
375
|
+
await resource.delete(id);
|
|
372
376
|
```
|
|
373
377
|
|
|
374
|
-
|
|
378
|
+
### Count
|
|
375
379
|
|
|
376
380
|
```javascript
|
|
377
381
|
await resource.count();
|
|
@@ -379,31 +383,46 @@ await resource.count();
|
|
|
379
383
|
// 101
|
|
380
384
|
```
|
|
381
385
|
|
|
382
|
-
|
|
386
|
+
### Insert many
|
|
387
|
+
|
|
388
|
+
You may bulk insert data with a friendly method that receives a list of objects.
|
|
383
389
|
|
|
384
390
|
```javascript
|
|
385
|
-
|
|
391
|
+
const objects = new Array(100).fill(0).map((v, k) => ({
|
|
392
|
+
id: `bulk-${k}@mymail.com`,
|
|
393
|
+
lead: {
|
|
394
|
+
fullName: "My Test Name",
|
|
395
|
+
personalEmail: `bulk-${k}@mymail.com`,
|
|
396
|
+
mobileNumber: "+55 11 1234567890",
|
|
397
|
+
},
|
|
398
|
+
}));
|
|
399
|
+
|
|
400
|
+
await resource.insertMany(objects);
|
|
386
401
|
```
|
|
387
402
|
|
|
388
|
-
|
|
403
|
+
Keep in mind that we need to send a request to each object to be created. There is an option to change the amount of simultaneos connections that your client will handle.
|
|
389
404
|
|
|
390
405
|
```javascript
|
|
391
|
-
const
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
// 'id1',
|
|
395
|
-
// 'id2',
|
|
396
|
-
// 'id3',
|
|
397
|
-
// ]
|
|
406
|
+
const s3db = new S3db({
|
|
407
|
+
parallelism: 100, // default = 10
|
|
408
|
+
});
|
|
398
409
|
```
|
|
399
410
|
|
|
400
|
-
|
|
411
|
+
This method uses [`supercharge/promise-pool`](https://github.com/supercharge/promise-pool) to organize the parallel promises.
|
|
412
|
+
|
|
413
|
+
### Get many
|
|
401
414
|
|
|
402
415
|
```javascript
|
|
403
|
-
await resource.
|
|
416
|
+
await resource.getMany(["id1", "id2", "id3 "]);
|
|
417
|
+
|
|
418
|
+
// [
|
|
419
|
+
// obj1,
|
|
420
|
+
// obj2,
|
|
421
|
+
// obj3,
|
|
422
|
+
// ]
|
|
404
423
|
```
|
|
405
424
|
|
|
406
|
-
|
|
425
|
+
### Get all
|
|
407
426
|
|
|
408
427
|
```javascript
|
|
409
428
|
const data = await resource.getAll();
|
|
@@ -415,9 +434,37 @@ const data = await resource.getAll();
|
|
|
415
434
|
// ]
|
|
416
435
|
```
|
|
417
436
|
|
|
418
|
-
###
|
|
437
|
+
### Delete many
|
|
438
|
+
|
|
439
|
+
```javascript
|
|
440
|
+
await resource.deleteMany(["id1", "id2", "id3 "]);
|
|
441
|
+
```
|
|
442
|
+
|
|
443
|
+
### Delete all
|
|
444
|
+
|
|
445
|
+
```javascript
|
|
446
|
+
await resource.deleteAll();
|
|
447
|
+
```
|
|
448
|
+
|
|
449
|
+
### List ids
|
|
450
|
+
|
|
451
|
+
```javascript
|
|
452
|
+
const ids = await resource.listIds();
|
|
453
|
+
|
|
454
|
+
// [
|
|
455
|
+
// 'id1',
|
|
456
|
+
// 'id2',
|
|
457
|
+
// 'id3',
|
|
458
|
+
// ]
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
---
|
|
462
|
+
|
|
463
|
+
## Resource streams
|
|
419
464
|
|
|
420
|
-
|
|
465
|
+
As we need to request the metadata for each id to return it's attributes, a better way to handle a huge amount off data might be using streams.
|
|
466
|
+
|
|
467
|
+
### Readable stream
|
|
421
468
|
|
|
422
469
|
```javascript
|
|
423
470
|
const readableStream = await resource.readable();
|
|
@@ -427,7 +474,7 @@ readableStream.on("data", (lead) => console.log("lead.id =", lead.id));
|
|
|
427
474
|
readableStream.on("end", console.log("end"));
|
|
428
475
|
```
|
|
429
476
|
|
|
430
|
-
|
|
477
|
+
### Writable stream
|
|
431
478
|
|
|
432
479
|
```javascript
|
|
433
480
|
const writableStream = await resource.writable();
|
|
@@ -441,180 +488,317 @@ writableStream.write({
|
|
|
441
488
|
});
|
|
442
489
|
```
|
|
443
490
|
|
|
444
|
-
|
|
491
|
+
---
|
|
445
492
|
|
|
446
|
-
|
|
493
|
+
## S3 Client
|
|
447
494
|
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
- resource.deleted
|
|
453
|
-
- error
|
|
454
|
-
1. S3Client
|
|
455
|
-
- action
|
|
456
|
-
- error
|
|
457
|
-
1. Resource
|
|
458
|
-
- id
|
|
459
|
-
- inserted
|
|
460
|
-
- deleted
|
|
461
|
-
- error
|
|
462
|
-
1. stream
|
|
463
|
-
- resource.id
|
|
464
|
-
- resource.data
|
|
465
|
-
- error
|
|
495
|
+
`s3db.js` has a S3 proxied client named [`S3Client`](https://github.com/forattini-dev/s3db.js/blob/main/src/s3-client.class.ts). It brings a few handy and less verbose functions to deal with AWS S3's api.
|
|
496
|
+
|
|
497
|
+
```javascript
|
|
498
|
+
import { S3Client } from "s3db.js";
|
|
466
499
|
|
|
467
|
-
|
|
500
|
+
const client = new S3Client({ connectionString });
|
|
501
|
+
```
|
|
468
502
|
|
|
469
|
-
|
|
503
|
+
Each method has a **[:link:](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html) link** to the official `aws-sdk` docs.
|
|
504
|
+
|
|
505
|
+
##### getObject [:link:](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getObject-property)
|
|
470
506
|
|
|
471
507
|
```javascript
|
|
472
|
-
|
|
508
|
+
const { Body, Metadata } = await client.getObject({
|
|
509
|
+
key: `my-prefixed-file.csv`,
|
|
510
|
+
});
|
|
511
|
+
|
|
512
|
+
// AWS.Response
|
|
473
513
|
```
|
|
474
514
|
|
|
475
|
-
#####
|
|
515
|
+
##### putObject [:link:](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#putObject-property)
|
|
476
516
|
|
|
477
517
|
```javascript
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
518
|
+
const response = await client.putObject({
|
|
519
|
+
key: `my-prefixed-file.csv`,
|
|
520
|
+
contentType: "text/csv",
|
|
521
|
+
metadata: { a: "1", b: "2", c: "3" },
|
|
522
|
+
body: "a;b;c\n1;2;3\n4;5;6",
|
|
523
|
+
});
|
|
524
|
+
|
|
525
|
+
// AWS.Response
|
|
481
526
|
```
|
|
482
527
|
|
|
483
|
-
#####
|
|
528
|
+
##### headObject [:link:](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#headObject-property)
|
|
484
529
|
|
|
485
530
|
```javascript
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
);
|
|
531
|
+
const { Metadata } = await client.headObject({
|
|
532
|
+
key: `my-prefixed-file.csv`,
|
|
533
|
+
});
|
|
534
|
+
|
|
535
|
+
// AWS.Response
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
##### deleteObject [:link:](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#deleteObject-property)
|
|
539
|
+
|
|
540
|
+
```javascript
|
|
541
|
+
const response = await client.deleteObject({
|
|
542
|
+
key: `my-prefixed-file.csv`,
|
|
543
|
+
});
|
|
544
|
+
|
|
545
|
+
// AWS.Response
|
|
546
|
+
```
|
|
547
|
+
|
|
548
|
+
##### deleteObjects [:link:](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#deleteObjects-property)
|
|
549
|
+
|
|
550
|
+
```javascript
|
|
551
|
+
const response = await client.deleteObjects({
|
|
552
|
+
keys: [`my-prefixed-file.csv`, `my-other-prefixed-file.csv`],
|
|
553
|
+
});
|
|
554
|
+
|
|
555
|
+
// AWS.Response
|
|
556
|
+
```
|
|
557
|
+
|
|
558
|
+
##### listObjects [:link:](https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#listObjects-property)
|
|
559
|
+
|
|
560
|
+
```javascript
|
|
561
|
+
const response = await client.listObjects({
|
|
562
|
+
prefix: `my-subdir`,
|
|
563
|
+
});
|
|
564
|
+
|
|
565
|
+
// AWS.Response
|
|
566
|
+
```
|
|
567
|
+
|
|
568
|
+
##### count
|
|
569
|
+
|
|
570
|
+
Custom made method to make it easier to count keys within a listObjects loop.
|
|
571
|
+
|
|
572
|
+
```javascript
|
|
573
|
+
const count = await client.count({
|
|
574
|
+
prefix: `my-subdir`,
|
|
575
|
+
});
|
|
576
|
+
|
|
577
|
+
// 10
|
|
489
578
|
```
|
|
490
579
|
|
|
491
|
-
#####
|
|
580
|
+
##### getAllKeys
|
|
581
|
+
|
|
582
|
+
Custom made method to make it easier to return all keys in a subpath within a listObjects loop.
|
|
583
|
+
|
|
584
|
+
All returned keys will have the it's fullpath replaced with the current "scope" path.
|
|
492
585
|
|
|
493
586
|
```javascript
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
);
|
|
587
|
+
const keys = await client.getAllKeys({
|
|
588
|
+
prefix: `my-subdir`,
|
|
589
|
+
});
|
|
590
|
+
|
|
591
|
+
// [
|
|
592
|
+
// key1,
|
|
593
|
+
// key2,
|
|
594
|
+
// ...
|
|
595
|
+
// ]
|
|
497
596
|
```
|
|
498
597
|
|
|
499
|
-
|
|
598
|
+
---
|
|
599
|
+
|
|
600
|
+
## Events
|
|
601
|
+
|
|
602
|
+
The 3 main classes `S3db`, `Resource` and `S3Client` are extensions of Javascript's `EventEmitter`.
|
|
603
|
+
|
|
604
|
+
| S3Database | S3Client | S3Resource | S3Resource Readable Stream |
|
|
605
|
+
| ---------- | ------------- | ---------- | -------------------------- |
|
|
606
|
+
| error | error | error | error |
|
|
607
|
+
| connected | request | insert | id |
|
|
608
|
+
| | response | get | data |
|
|
609
|
+
| | response | update | |
|
|
610
|
+
| | getObject | delete | |
|
|
611
|
+
| | putObject | count | |
|
|
612
|
+
| | headObject | insertMany | |
|
|
613
|
+
| | deleteObject | deleteAll | |
|
|
614
|
+
| | deleteObjects | listIds | |
|
|
615
|
+
| | listObjects | getMany | |
|
|
616
|
+
| | count | getAll | |
|
|
617
|
+
| | getAllKeys | | |
|
|
618
|
+
|
|
619
|
+
### S3Database
|
|
620
|
+
|
|
621
|
+
#### error
|
|
500
622
|
|
|
501
623
|
```javascript
|
|
502
624
|
s3db.on("error", (error) => console.error(error));
|
|
503
625
|
```
|
|
504
626
|
|
|
505
|
-
####
|
|
627
|
+
#### connected
|
|
506
628
|
|
|
507
|
-
|
|
629
|
+
```javascript
|
|
630
|
+
s3db.on("connected", () => {});
|
|
631
|
+
```
|
|
632
|
+
|
|
633
|
+
### S3Client
|
|
634
|
+
|
|
635
|
+
Using this reference for the events:
|
|
508
636
|
|
|
509
637
|
```javascript
|
|
510
|
-
s3db.client
|
|
511
|
-
console.log(`resource ${resourceName} created`)
|
|
512
|
-
);
|
|
638
|
+
const client = s3db.client;
|
|
513
639
|
```
|
|
514
640
|
|
|
515
|
-
|
|
641
|
+
#### error
|
|
516
642
|
|
|
517
643
|
```javascript
|
|
518
|
-
|
|
644
|
+
client.on("error", (error) => console.error(error));
|
|
519
645
|
```
|
|
520
646
|
|
|
521
|
-
####
|
|
647
|
+
#### request
|
|
522
648
|
|
|
523
|
-
|
|
649
|
+
Emitted when a request is generated to AWS.
|
|
524
650
|
|
|
525
651
|
```javascript
|
|
526
|
-
|
|
652
|
+
client.on("request", (action, params) => {});
|
|
653
|
+
```
|
|
654
|
+
|
|
655
|
+
#### response
|
|
527
656
|
|
|
528
|
-
|
|
657
|
+
Emitted when a response is received from AWS.
|
|
658
|
+
|
|
659
|
+
```javascript
|
|
660
|
+
client.on("response", (action, params, response) => {});
|
|
529
661
|
```
|
|
530
662
|
|
|
531
|
-
####
|
|
663
|
+
#### getObject
|
|
532
664
|
|
|
533
665
|
```javascript
|
|
534
|
-
|
|
666
|
+
client.on("getObject", (options, response) => {});
|
|
667
|
+
```
|
|
668
|
+
|
|
669
|
+
#### putObject
|
|
535
670
|
|
|
536
|
-
|
|
671
|
+
```javascript
|
|
672
|
+
client.on("putObject", (options, response) => {});
|
|
537
673
|
```
|
|
538
674
|
|
|
539
|
-
|
|
675
|
+
#### headObject
|
|
540
676
|
|
|
541
|
-
|
|
677
|
+
```javascript
|
|
678
|
+
client.on("headObject", (options, response) => {});
|
|
679
|
+
```
|
|
680
|
+
|
|
681
|
+
#### deleteObject
|
|
542
682
|
|
|
543
683
|
```javascript
|
|
544
|
-
|
|
684
|
+
client.on("deleteObject", (options, response) => {});
|
|
685
|
+
```
|
|
545
686
|
|
|
546
|
-
|
|
687
|
+
#### deleteObjects
|
|
688
|
+
|
|
689
|
+
```javascript
|
|
690
|
+
client.on("deleteObjects", (options, response) => {});
|
|
547
691
|
```
|
|
548
692
|
|
|
549
|
-
|
|
693
|
+
#### listObjects
|
|
550
694
|
|
|
551
695
|
```javascript
|
|
552
|
-
|
|
553
|
-
key: `my-prefixed-file.csv`,
|
|
554
|
-
});
|
|
696
|
+
client.on("listObjects", (options, response) => {});
|
|
555
697
|
```
|
|
556
698
|
|
|
557
|
-
|
|
699
|
+
#### count
|
|
558
700
|
|
|
559
701
|
```javascript
|
|
560
|
-
|
|
561
|
-
key: `my-prefixed-file.csv`,
|
|
562
|
-
contentType: "text/csv",
|
|
563
|
-
metadata: { a: "1", b: "2", c: "3" },
|
|
564
|
-
body: "a;b;c\n1;2;3\n4;5;6",
|
|
565
|
-
});
|
|
702
|
+
client.on("count", (options, response) => {});
|
|
566
703
|
```
|
|
567
704
|
|
|
568
|
-
|
|
705
|
+
#### getAllKeys
|
|
569
706
|
|
|
570
707
|
```javascript
|
|
571
|
-
|
|
572
|
-
key: `my-prefixed-file.csv`,
|
|
573
|
-
});
|
|
708
|
+
client.on("getAllKeys", (options, response) => {});
|
|
574
709
|
```
|
|
575
710
|
|
|
576
|
-
|
|
711
|
+
### S3Resource
|
|
712
|
+
|
|
713
|
+
Using this reference for the events:
|
|
577
714
|
|
|
578
715
|
```javascript
|
|
579
|
-
const
|
|
580
|
-
key: `my-prefixed-file.csv`,
|
|
581
|
-
});
|
|
716
|
+
const resource = s3db.resource("leads");
|
|
582
717
|
```
|
|
583
718
|
|
|
584
|
-
|
|
719
|
+
#### error
|
|
585
720
|
|
|
586
721
|
```javascript
|
|
587
|
-
|
|
588
|
-
keys: [`my-prefixed-file.csv`, `my-other-prefixed-file.csv`],
|
|
589
|
-
});
|
|
722
|
+
resource.on("error", (err) => console.error(err));
|
|
590
723
|
```
|
|
591
724
|
|
|
592
|
-
|
|
725
|
+
#### insert
|
|
593
726
|
|
|
594
727
|
```javascript
|
|
595
|
-
|
|
596
|
-
prefix: `my-subdir`,
|
|
597
|
-
});
|
|
728
|
+
resource.on("insert", (data) => {});
|
|
598
729
|
```
|
|
599
730
|
|
|
600
|
-
|
|
731
|
+
#### get
|
|
601
732
|
|
|
602
733
|
```javascript
|
|
603
|
-
|
|
604
|
-
prefix: `my-subdir`,
|
|
605
|
-
});
|
|
734
|
+
resource.on("get", (data) => {});
|
|
606
735
|
```
|
|
607
736
|
|
|
608
|
-
|
|
737
|
+
#### update
|
|
609
738
|
|
|
610
|
-
|
|
739
|
+
```javascript
|
|
740
|
+
resource.on("update", (attrs, data) => {});
|
|
741
|
+
```
|
|
742
|
+
|
|
743
|
+
#### delete
|
|
611
744
|
|
|
612
745
|
```javascript
|
|
613
|
-
|
|
614
|
-
prefix: `my-subdir`,
|
|
615
|
-
});
|
|
746
|
+
resource.on("delete", (id) => {});
|
|
616
747
|
```
|
|
617
748
|
|
|
749
|
+
#### count
|
|
750
|
+
|
|
751
|
+
```javascript
|
|
752
|
+
resource.on("count", (count) => {});
|
|
753
|
+
```
|
|
754
|
+
|
|
755
|
+
#### insertMany
|
|
756
|
+
|
|
757
|
+
```javascript
|
|
758
|
+
resource.on("insertMany", (count) => {});
|
|
759
|
+
```
|
|
760
|
+
|
|
761
|
+
#### getMany
|
|
762
|
+
|
|
763
|
+
```javascript
|
|
764
|
+
resource.on("getMany", (count) => {});
|
|
765
|
+
```
|
|
766
|
+
|
|
767
|
+
#### getAll
|
|
768
|
+
|
|
769
|
+
```javascript
|
|
770
|
+
resource.on("getAll", (count) => {});
|
|
771
|
+
```
|
|
772
|
+
|
|
773
|
+
#### deleteAll
|
|
774
|
+
|
|
775
|
+
```javascript
|
|
776
|
+
resource.on("deleteAll", (count) => {});
|
|
777
|
+
```
|
|
778
|
+
|
|
779
|
+
#### listIds
|
|
780
|
+
|
|
781
|
+
```javascript
|
|
782
|
+
resource.on("listIds", (count) => {});
|
|
783
|
+
```
|
|
784
|
+
|
|
785
|
+
---
|
|
786
|
+
|
|
787
|
+
## Plugins
|
|
788
|
+
|
|
789
|
+
Anatomy of a plugin:
|
|
790
|
+
|
|
791
|
+
```javascript
|
|
792
|
+
const MyPlugin = {
|
|
793
|
+
setup(s3db: S3db) {},
|
|
794
|
+
start() {},
|
|
795
|
+
};
|
|
796
|
+
```
|
|
797
|
+
|
|
798
|
+
We have an example of a _costs simulator plugin_ [here!](https://github.com/forattini-dev/s3db.js/blob/main/src/plugins/costs.plugin.js)
|
|
799
|
+
|
|
800
|
+
---
|
|
801
|
+
|
|
618
802
|
## Examples
|
|
619
803
|
|
|
620
804
|
The processing power here was not the priority, just used my little nodebook Dell XPS. Check the `./examples` directory to get some ideas on how to use this package and the code of the examples below.
|
|
@@ -793,7 +977,7 @@ Lets save some JWT tokens using the [RFC:7519](https://www.rfc-editor.org/rfc/rf
|
|
|
793
977
|
|
|
794
978
|
```javascript
|
|
795
979
|
await s3db.createResource({
|
|
796
|
-
|
|
980
|
+
name: "tokens",
|
|
797
981
|
attributes: {
|
|
798
982
|
iss: 'url|max:256',
|
|
799
983
|
sub: 'string',
|
|
@@ -827,3 +1011,9 @@ function validateToken (token) {
|
|
|
827
1011
|
return resource.getById(id)
|
|
828
1012
|
}
|
|
829
1013
|
```
|
|
1014
|
+
|
|
1015
|
+
## Roadmap
|
|
1016
|
+
|
|
1017
|
+
Tasks board can be found at [this link](https://github.com/orgs/forattini-dev/projects/5/views/1)!
|
|
1018
|
+
|
|
1019
|
+
Feel free to interact and PRs are welcome! :)
|