@toa.io/extensions.storages 1.0.0-alpha.31 → 1.0.0-alpha.310
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 +38 -18
- package/readme.md +115 -47
- package/transpiled/Aspect.d.ts +8 -4
- package/transpiled/Aspect.js +12 -14
- package/transpiled/Aspect.js.map +1 -1
- package/transpiled/Entry.d.ts +14 -11
- package/transpiled/Entry.js +1 -2
- package/transpiled/Factory.d.ts +1 -1
- package/transpiled/Factory.js +29 -30
- package/transpiled/Factory.js.map +1 -1
- package/transpiled/Provider.d.ts +17 -19
- package/transpiled/Provider.js +10 -33
- package/transpiled/Provider.js.map +1 -1
- package/transpiled/Scanner.d.ts +5 -4
- package/transpiled/Scanner.js +33 -26
- package/transpiled/Scanner.js.map +1 -1
- package/transpiled/Secrets.d.ts +5 -0
- package/transpiled/Secrets.js +2 -0
- package/transpiled/Secrets.js.map +1 -0
- package/transpiled/Storage.d.ts +23 -22
- package/transpiled/Storage.js +79 -142
- package/transpiled/Storage.js.map +1 -1
- package/transpiled/errors.d.ts +7 -0
- package/transpiled/errors.js +4 -0
- package/transpiled/errors.js.map +1 -0
- package/transpiled/index.d.ts +4 -4
- package/transpiled/index.js +1 -9
- package/transpiled/index.js.map +1 -1
- package/transpiled/measurements.d.ts +3 -0
- package/transpiled/measurements.js +23 -0
- package/transpiled/measurements.js.map +1 -0
- package/transpiled/providers/Cloudinary.d.ts +50 -0
- package/transpiled/providers/Cloudinary.js +223 -0
- package/transpiled/providers/Cloudinary.js.map +1 -0
- package/transpiled/providers/Declaration.d.ts +9 -5
- package/transpiled/providers/Declaration.js +1 -2
- package/transpiled/providers/FileSystem.d.ts +16 -11
- package/transpiled/providers/FileSystem.js +64 -43
- package/transpiled/providers/FileSystem.js.map +1 -1
- package/transpiled/providers/S3.d.ts +14 -19
- package/transpiled/providers/S3.js +72 -123
- package/transpiled/providers/S3.js.map +1 -1
- package/transpiled/providers/Spaces.d.ts +12 -0
- package/transpiled/providers/Spaces.js +13 -0
- package/transpiled/providers/Spaces.js.map +1 -0
- package/transpiled/providers/Temporary.d.ts +2 -3
- package/transpiled/providers/Temporary.js +7 -11
- package/transpiled/providers/Temporary.js.map +1 -1
- package/transpiled/providers/Test.d.ts +4 -4
- package/transpiled/providers/Test.js +6 -12
- package/transpiled/providers/Test.js.map +1 -1
- package/transpiled/providers/index.d.ts +23 -11
- package/transpiled/providers/index.js +30 -14
- package/transpiled/providers/index.js.map +1 -1
- package/transpiled/providers/index.types.d.ts +5 -0
- package/transpiled/providers/index.types.js +2 -0
- package/transpiled/providers/index.types.js.map +1 -0
- package/transpiled/test/util.d.ts +113 -6
- package/transpiled/test/util.js +68 -15
- package/transpiled/test/util.js.map +1 -1
- package/schemas/annotation.cos.yaml +0 -10
- package/schemas/fs.cos.yaml +0 -9
- package/schemas/mem.cos.yaml +0 -6
- package/schemas/s3.cos.yaml +0 -16
- package/schemas/test.cos.yaml +0 -8
- package/schemas/tmp.cos.yaml +0 -9
- package/source/Annotation.ts +0 -39
- package/source/Aspect.ts +0 -25
- package/source/Entry.ts +0 -14
- package/source/Factory.ts +0 -68
- package/source/Provider.ts +0 -37
- package/source/Scanner.ts +0 -153
- package/source/Storage.test.ts +0 -472
- package/source/Storage.ts +0 -235
- package/source/deployment.ts +0 -57
- package/source/index.ts +0 -5
- package/source/manifest.ts +0 -8
- package/source/providers/Declaration.ts +0 -10
- package/source/providers/FileSystem.test.ts +0 -5
- package/source/providers/FileSystem.ts +0 -63
- package/source/providers/Memory.ts +0 -55
- package/source/providers/S3.test.ts +0 -134
- package/source/providers/S3.ts +0 -196
- package/source/providers/Temporary.ts +0 -16
- package/source/providers/Test.ts +0 -13
- package/source/providers/index.test.ts +0 -136
- package/source/providers/index.ts +0 -16
- package/source/providers/readme.md +0 -25
- package/source/schemas.test.ts +0 -58
- package/source/schemas.ts +0 -15
- package/source/test/.env.example +0 -1
- package/source/test/albert.jpg +0 -0
- package/source/test/empty.txt +0 -0
- package/source/test/lenna.ascii +0 -64
- package/source/test/lenna.png +0 -0
- package/source/test/sample.avi +0 -0
- package/source/test/sample.avif +0 -0
- package/source/test/sample.gif +0 -0
- package/source/test/sample.heic +0 -0
- package/source/test/sample.jpeg +0 -0
- package/source/test/sample.jxl +0 -0
- package/source/test/sample.svg +0 -4
- package/source/test/sample.wav +0 -0
- package/source/test/sample.webp +0 -0
- package/source/test/util.ts +0 -45
- package/transpiled/Annotation.d.ts +0 -3
- package/transpiled/Annotation.js +0 -57
- package/transpiled/Annotation.js.map +0 -1
- package/transpiled/deployment.d.ts +0 -5
- package/transpiled/deployment.js +0 -68
- package/transpiled/deployment.js.map +0 -1
- package/transpiled/manifest.d.ts +0 -1
- package/transpiled/manifest.js +0 -9
- package/transpiled/manifest.js.map +0 -1
- package/transpiled/providers/Memory.d.ts +0 -15
- package/transpiled/providers/Memory.js +0 -72
- package/transpiled/providers/Memory.js.map +0 -1
- package/transpiled/schemas.d.ts +0 -9
- package/transpiled/schemas.js +0 -14
- package/transpiled/schemas.js.map +0 -1
- package/transpiled/tsconfig.tsbuildinfo +0 -1
- package/tsconfig.json +0 -12
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@toa.io/extensions.storages",
|
|
3
|
-
"version": "1.0.0-alpha.
|
|
3
|
+
"version": "1.0.0-alpha.310",
|
|
4
|
+
"type": "module",
|
|
4
5
|
"description": "Toa Storages",
|
|
5
6
|
"author": "temich <tema.gurtovoy@gmail.com>",
|
|
6
7
|
"homepage": "https://github.com/toa-io/toa#readme",
|
|
@@ -16,27 +17,46 @@
|
|
|
16
17
|
"publishConfig": {
|
|
17
18
|
"access": "public"
|
|
18
19
|
},
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
|
|
20
|
+
"files": [
|
|
21
|
+
"transpiled",
|
|
22
|
+
"readme.md",
|
|
23
|
+
"!**/tsconfig.tsbuildinfo",
|
|
24
|
+
"!**/*.test.*",
|
|
25
|
+
"!**/.env*"
|
|
26
|
+
],
|
|
23
27
|
"scripts": {
|
|
24
|
-
"test": "
|
|
28
|
+
"test": "echo \"Error: run tests from root\" && exit 1",
|
|
25
29
|
"transpile": "npx tsc"
|
|
26
30
|
},
|
|
31
|
+
"devDependencies": {
|
|
32
|
+
"@aws-sdk/client-s3": "3.1131.0",
|
|
33
|
+
"@aws-sdk/lib-storage": "3.1131.0",
|
|
34
|
+
"cloudinary": "2.11.0",
|
|
35
|
+
"dotenv": "17.4.2"
|
|
36
|
+
},
|
|
27
37
|
"peerDependencies": {
|
|
28
|
-
"
|
|
38
|
+
"@aws-sdk/client-s3": "3.1131.0",
|
|
39
|
+
"@aws-sdk/lib-storage": "3.1131.0",
|
|
40
|
+
"cloudinary": "2.11.0"
|
|
41
|
+
},
|
|
42
|
+
"peerDependenciesMeta": {
|
|
43
|
+
"@aws-sdk/client-s3": {
|
|
44
|
+
"optional": true
|
|
45
|
+
},
|
|
46
|
+
"@aws-sdk/lib-storage": {
|
|
47
|
+
"optional": true
|
|
48
|
+
},
|
|
49
|
+
"cloudinary": {
|
|
50
|
+
"optional": true
|
|
51
|
+
}
|
|
29
52
|
},
|
|
30
53
|
"dependencies": {
|
|
31
|
-
"@
|
|
32
|
-
"@
|
|
33
|
-
"@toa.io/
|
|
34
|
-
"@toa.io/
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
"smithy-node-native-fetch": "1.0.6"
|
|
40
|
-
},
|
|
41
|
-
"gitHead": "91839a488176853a0731f49abc70dc7103ed7cca"
|
|
54
|
+
"@toa.io/core": "1.0.0-alpha.310",
|
|
55
|
+
"@toa.io/definitions": "1.0.0-alpha.310",
|
|
56
|
+
"@toa.io/generic": "1.0.0-alpha.310",
|
|
57
|
+
"@toa.io/schemas": "1.0.0-alpha.310",
|
|
58
|
+
"negotiator": "1.1.0",
|
|
59
|
+
"openspan": "1.0.0-alpha.305"
|
|
60
|
+
},
|
|
61
|
+
"gitHead": "d952c57f77279729e26d52d50c6df47138ad0a4f"
|
|
42
62
|
}
|
package/readme.md
CHANGED
|
@@ -2,19 +2,30 @@
|
|
|
2
2
|
|
|
3
3
|
Shared BLOB storage.
|
|
4
4
|
|
|
5
|
+
## Installing a provider
|
|
6
|
+
|
|
7
|
+
A provider's SDK is not installed with this extension: `s3` and `spaces` need
|
|
8
|
+
`@aws-sdk/client-s3` and `@aws-sdk/lib-storage`, `cloudinary` needs `cloudinary`, and `fs`, `tmp`
|
|
9
|
+
and `test` need nothing. A deploy installs what the components of each composition declare, so
|
|
10
|
+
an image carries the SDK of a provider it uses and no other.
|
|
11
|
+
|
|
12
|
+
A workspace installs the same set itself, once, and again when a storage is added:
|
|
13
|
+
|
|
14
|
+
```shell
|
|
15
|
+
$ toa npm -p application
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Without it a composition fails to start, naming the package and version it wants.
|
|
19
|
+
|
|
5
20
|
## Entry
|
|
6
21
|
|
|
7
22
|
BLOBs are stored with the meta-information object (Entry) having the following properties:
|
|
8
23
|
|
|
9
|
-
- `
|
|
10
|
-
- `
|
|
11
|
-
- `
|
|
12
|
-
- `created
|
|
13
|
-
- `
|
|
14
|
-
- `name` - unique name
|
|
15
|
-
- `size` - size in bytes
|
|
16
|
-
- `type` - variant MIME type
|
|
17
|
-
- `meta` - object with application-specific information, empty by default
|
|
24
|
+
- `size`: size in bytes
|
|
25
|
+
- `type`: MIME type
|
|
26
|
+
- `checksum`: content checksum
|
|
27
|
+
- `created`: creation timestamp (ISO 8601)
|
|
28
|
+
- `attributes`: `Record<string, string>` with application-specific information, empty by default
|
|
18
29
|
|
|
19
30
|
### Example
|
|
20
31
|
|
|
@@ -22,12 +33,7 @@ BLOBs are stored with the meta-information object (Entry) having the following p
|
|
|
22
33
|
id: eecd837c
|
|
23
34
|
type: image/jpeg
|
|
24
35
|
created: 1698004822358
|
|
25
|
-
|
|
26
|
-
- name: thumbnail.jpeg
|
|
27
|
-
type: image/jpeg
|
|
28
|
-
- name: thumbnail.webp
|
|
29
|
-
type: image/webp
|
|
30
|
-
meta:
|
|
36
|
+
attributes:
|
|
31
37
|
face: true
|
|
32
38
|
nudity: false
|
|
33
39
|
```
|
|
@@ -38,8 +44,8 @@ The Storages extension provides `storages` aspect,
|
|
|
38
44
|
containing named Storage instances, according to the annotation.
|
|
39
45
|
|
|
40
46
|
```javascript
|
|
41
|
-
async function effect
|
|
42
|
-
await context.storages.photos.
|
|
47
|
+
async function effect(_, context) {
|
|
48
|
+
await context.storages.photos.get('/path/to/b4f577e0.thumbnail.jpeg')
|
|
43
49
|
}
|
|
44
50
|
```
|
|
45
51
|
|
|
@@ -49,11 +55,11 @@ async function effect (_, context) {
|
|
|
49
55
|
|
|
50
56
|
#### `async put(path: string, stream: Readable, options?: Options): Maybe<Entry>`
|
|
51
57
|
|
|
52
|
-
```
|
|
58
|
+
```ts
|
|
53
59
|
interface Options {
|
|
54
60
|
claim?: string
|
|
55
61
|
accept?: string
|
|
56
|
-
|
|
62
|
+
attributes?: Record<string, string>
|
|
57
63
|
}
|
|
58
64
|
```
|
|
59
65
|
|
|
@@ -75,13 +81,13 @@ are: `image/jpeg`, `image/png`, `image/gif`, `image/webp`, `image/heic`, `image/
|
|
|
75
81
|
|
|
76
82
|
See [source](source/Scanner.ts).
|
|
77
83
|
|
|
78
|
-
#### `async
|
|
84
|
+
#### `async head(path: string): Maybe<Entry>`
|
|
79
85
|
|
|
80
86
|
Get an entry.
|
|
81
87
|
|
|
82
88
|
If the entry does not exist, a `NOT_FOUND` error is returned.
|
|
83
89
|
|
|
84
|
-
#### `async
|
|
90
|
+
#### `async get(path: string): Maybe<Readable>`
|
|
85
91
|
|
|
86
92
|
Fetch the BLOB specified by `path`. If the path does not exist, a `NOT_FOUND` error is returned.
|
|
87
93
|
|
|
@@ -110,18 +116,6 @@ await storage.move('/path/to/eecd837c', './sub/eecd837c')
|
|
|
110
116
|
await storage.move('/path/to/eecd837c', './sub/')
|
|
111
117
|
```
|
|
112
118
|
|
|
113
|
-
#### `async entries(path: string): Entry[]`
|
|
114
|
-
|
|
115
|
-
Get a list of entries under the `path`.
|
|
116
|
-
|
|
117
|
-
#### `async diversify(path: string, name: string, stream: Readable): Maybe<void>`
|
|
118
|
-
|
|
119
|
-
Add or replace a `name` variant of the entry specified by `path`.
|
|
120
|
-
|
|
121
|
-
#### `async annotate(path: string, key: string, value: any): Maybe<void>`
|
|
122
|
-
|
|
123
|
-
Set a `key` property in the `meta` of the entry specified by `path`.
|
|
124
|
-
|
|
125
119
|
## Providers
|
|
126
120
|
|
|
127
121
|
Storage uses underlying providers to store BLOBs and entries.
|
|
@@ -152,40 +146,114 @@ and [`toa env`](/runtime/cli/readme.md#env)
|
|
|
152
146
|
for local environment.
|
|
153
147
|
`endpoint` parameter is optional.
|
|
154
148
|
|
|
155
|
-
###
|
|
149
|
+
### DigitalOcean Spaces
|
|
156
150
|
|
|
157
151
|
Annotation format is:
|
|
158
152
|
|
|
159
153
|
```yaml
|
|
160
154
|
storages:
|
|
161
|
-
photos
|
|
162
|
-
provider:
|
|
163
|
-
|
|
155
|
+
photos:
|
|
156
|
+
provider: spaces
|
|
157
|
+
space: my-space
|
|
158
|
+
region: fra1
|
|
164
159
|
```
|
|
165
160
|
|
|
166
|
-
|
|
161
|
+
`region` is the datacenter slug, the endpoint is derived from it.
|
|
167
162
|
|
|
168
|
-
|
|
163
|
+
Secrets `ACCESS_KEY_ID` and `SECRET_ACCESS_KEY` are required.
|
|
164
|
+
Keys are created in the DigitalOcean control panel,
|
|
165
|
+
under Spaces Object Storage, on the Access Keys tab.
|
|
166
|
+
|
|
167
|
+
### Cloudinary
|
|
168
|
+
|
|
169
|
+
[Cloudinary](https://cloudinary.com) provider is used to store and transform media files.
|
|
170
|
+
|
|
171
|
+
Objects stored in the Cloudinary storage can be requested with transformations,
|
|
172
|
+
using dot-separated path extensions: `/path/to/eecd837c.{extension}.{extension}`.
|
|
173
|
+
|
|
174
|
+
Transformation is defined by the `extension` property, which is a regular expression with named
|
|
175
|
+
groups.
|
|
176
|
+
The named groups are used to replace the placeholders in the `transform` object.
|
|
177
|
+
|
|
178
|
+
`transform` object is an element of
|
|
179
|
+
the [Cloudinary `transformation` array](https://cloudinary.com/documentation/node_image_manipulation#apply_common_image_transformations).
|
|
180
|
+
|
|
181
|
+
> - `zoom` should be specified as integer [0–100].
|
|
182
|
+
> - `format` value `jpeg` is converted to `jpg`.
|
|
183
|
+
> - `^` and `$` are added to the regular expression automatically, unless they are already present.
|
|
169
184
|
|
|
170
185
|
Annotation format is:
|
|
171
186
|
|
|
172
187
|
```yaml
|
|
173
188
|
storages:
|
|
174
|
-
|
|
175
|
-
provider:
|
|
176
|
-
|
|
189
|
+
media:
|
|
190
|
+
provider: cloudinary
|
|
191
|
+
environment: my-cloud
|
|
192
|
+
type: image # image or video
|
|
193
|
+
prefix: my-app
|
|
194
|
+
transformations:
|
|
195
|
+
- extension: (?<width>\d*)x(?<height>\d*)(z(?<zoom>\d*))?
|
|
196
|
+
transformation:
|
|
197
|
+
width: <width>
|
|
198
|
+
height: <height>
|
|
199
|
+
zoom: <zoom>
|
|
200
|
+
crop: thumb
|
|
201
|
+
gravity: face
|
|
202
|
+
optional: true
|
|
203
|
+
- extension: (?<format>jpeg|webp)
|
|
204
|
+
transformation:
|
|
205
|
+
fetch_format: <format>
|
|
177
206
|
```
|
|
178
207
|
|
|
179
|
-
|
|
208
|
+
Path extensions must be specified in the same order as in the annotation.
|
|
180
209
|
|
|
181
|
-
|
|
210
|
+
For the example above:
|
|
182
211
|
|
|
183
|
-
|
|
212
|
+
- `/path/to/eecd837c.100x100.jpeg`: matches
|
|
213
|
+
- `/path/to/eecd837c.jpeg.100x100`: does not match
|
|
214
|
+
|
|
215
|
+
If a path extension is not matched,
|
|
216
|
+
or if at least one of the transformations is not matched (unless it is `optional`),
|
|
217
|
+
then an error is returned.
|
|
218
|
+
|
|
219
|
+
Secrets:
|
|
220
|
+
|
|
221
|
+
- `API_KEY`
|
|
222
|
+
- `API_SECRET`
|
|
223
|
+
|
|
224
|
+
### Filesystem
|
|
225
|
+
|
|
226
|
+
Annotation format is:
|
|
227
|
+
|
|
228
|
+
```yaml
|
|
229
|
+
storages:
|
|
230
|
+
photos:
|
|
231
|
+
provider: fs
|
|
232
|
+
path: /var/my-photos
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
[Kubernetes PVC](https://kubernetes.io/docs/concepts/storage/persistent-volumes/) can be mounted to
|
|
236
|
+
the storage:
|
|
237
|
+
|
|
238
|
+
```yaml
|
|
239
|
+
storages:
|
|
240
|
+
photos:
|
|
241
|
+
provider: fs
|
|
242
|
+
path: /var/my-photos
|
|
243
|
+
claim: photos-pvc
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
### Temporary
|
|
247
|
+
|
|
248
|
+
Filesystem using OS temporary directory.
|
|
249
|
+
|
|
250
|
+
Annotation format is:
|
|
184
251
|
|
|
185
252
|
```yaml
|
|
186
253
|
storages:
|
|
187
254
|
photos@dev:
|
|
188
|
-
provider:
|
|
255
|
+
provider: tmp
|
|
256
|
+
directory: my-app-tmp
|
|
189
257
|
```
|
|
190
258
|
|
|
191
259
|
## Deduplication
|
|
@@ -196,7 +264,7 @@ Variants, on the other hand, are not deduplicated across different entries.
|
|
|
196
264
|
|
|
197
265
|
Underlying directory structure:
|
|
198
266
|
|
|
199
|
-
```
|
|
267
|
+
```text
|
|
200
268
|
/temp
|
|
201
269
|
c28f4dfd # random id
|
|
202
270
|
/blobs
|
package/transpiled/Aspect.d.ts
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
import { Connector
|
|
2
|
-
import
|
|
1
|
+
import { Connector } from '@toa.io/core';
|
|
2
|
+
import type { extensions } from '@toa.io/core/types';
|
|
3
|
+
import { type Storage, type Storages } from './Storage.ts';
|
|
3
4
|
export declare class Aspect extends Connector implements extensions.Aspect {
|
|
4
5
|
readonly name = "storages";
|
|
5
|
-
private readonly
|
|
6
|
-
|
|
6
|
+
private readonly create;
|
|
7
|
+
private storages;
|
|
8
|
+
/** The storages are made as the aspect connects: their providers load then, not before. */
|
|
9
|
+
constructor(create: () => Promise<Storages>);
|
|
10
|
+
protected open(): Promise<void>;
|
|
7
11
|
invoke(name: string, method: keyof Storage, ...args: unknown[]): unknown;
|
|
8
12
|
}
|
package/transpiled/Aspect.js
CHANGED
|
@@ -1,25 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.Aspect = void 0;
|
|
7
|
-
const node_assert_1 = __importDefault(require("node:assert"));
|
|
8
|
-
const core_1 = require("@toa.io/core");
|
|
9
|
-
class Aspect extends core_1.Connector {
|
|
1
|
+
import { Connector } from '@toa.io/core';
|
|
2
|
+
export class Aspect extends Connector {
|
|
10
3
|
name = 'storages';
|
|
11
|
-
|
|
12
|
-
|
|
4
|
+
create;
|
|
5
|
+
storages = {};
|
|
6
|
+
/** The storages are made as the aspect connects: their providers load then, not before. */
|
|
7
|
+
constructor(create) {
|
|
13
8
|
super();
|
|
14
|
-
this.
|
|
9
|
+
this.create = create;
|
|
10
|
+
}
|
|
11
|
+
async open() {
|
|
12
|
+
this.storages = await this.create();
|
|
15
13
|
}
|
|
16
14
|
invoke(name, method, ...args) {
|
|
17
15
|
const storage = this.storages[name];
|
|
18
|
-
|
|
16
|
+
if (storage === undefined)
|
|
17
|
+
throw new Error(`Storage '${name}' is not defined`);
|
|
19
18
|
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
20
19
|
// @ts-expect-error
|
|
21
20
|
return storage[method](...args);
|
|
22
21
|
}
|
|
23
22
|
}
|
|
24
|
-
exports.Aspect = Aspect;
|
|
25
23
|
//# sourceMappingURL=Aspect.js.map
|
package/transpiled/Aspect.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Aspect.js","sourceRoot":"","sources":["../source/Aspect.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Aspect.js","sourceRoot":"","sources":["../source/Aspect.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAA;AAIxC,MAAM,OAAO,MAAO,SAAQ,SAAS;IACnB,IAAI,GAAG,UAAU,CAAA;IAEhB,MAAM,CAAyB;IACxC,QAAQ,GAAa,EAAE,CAAA;IAE/B,2FAA2F;IAC3F,YAAmB,MAA+B;QAChD,KAAK,EAAE,CAAA;QAEP,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;IACtB,CAAC;IAEkB,KAAK,CAAC,IAAI;QAC3B,IAAI,CAAC,QAAQ,GAAG,MAAM,IAAI,CAAC,MAAM,EAAE,CAAA;IACrC,CAAC;IAEM,MAAM,CAAC,IAAY,EAAE,MAAqB,EAAE,GAAG,IAAe;QACnE,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;QAEnC,IAAI,OAAO,KAAK,SAAS;YAAE,MAAM,IAAI,KAAK,CAAC,YAAY,IAAI,kBAAkB,CAAC,CAAA;QAE9E,6DAA6D;QAC7D,mBAAmB;QACnB,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC,CAAA;IACjC,CAAC;CACF"}
|
package/transpiled/Entry.d.ts
CHANGED
|
@@ -1,14 +1,17 @@
|
|
|
1
|
-
|
|
1
|
+
import type { Readable } from 'node:stream';
|
|
2
|
+
export type Entry = {
|
|
2
3
|
id: string;
|
|
3
|
-
|
|
4
|
+
} & Metadata;
|
|
5
|
+
export type Stream = {
|
|
6
|
+
stream: Readable;
|
|
7
|
+
} & Metadata;
|
|
8
|
+
export interface Metadata {
|
|
4
9
|
type: string;
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
10
|
+
size: number | null;
|
|
11
|
+
checksum: string;
|
|
12
|
+
created: string;
|
|
13
|
+
attributes: Attributes;
|
|
14
|
+
range?: string;
|
|
15
|
+
partial?: boolean;
|
|
8
16
|
}
|
|
9
|
-
|
|
10
|
-
name: string;
|
|
11
|
-
size: number;
|
|
12
|
-
type: string;
|
|
13
|
-
}
|
|
14
|
-
export {};
|
|
17
|
+
export type Attributes = Record<string, string>;
|
package/transpiled/Entry.js
CHANGED
package/transpiled/Factory.d.ts
CHANGED
package/transpiled/Factory.js
CHANGED
|
@@ -1,53 +1,52 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
};
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
const generic_1 = require("@toa.io/generic");
|
|
9
|
-
const providers_1 = require("./providers");
|
|
10
|
-
const Storage_1 = require("./Storage");
|
|
11
|
-
const Aspect_1 = require("./Aspect");
|
|
12
|
-
const deployment_1 = require("./deployment");
|
|
13
|
-
const Annotation_1 = require("./Annotation");
|
|
14
|
-
class Factory {
|
|
1
|
+
import { console } from 'openspan';
|
|
2
|
+
import { provider as load } from './providers/index.js';
|
|
3
|
+
import { Storage } from './Storage.js';
|
|
4
|
+
import { Aspect } from './Aspect.js';
|
|
5
|
+
import { ENV_PREFIX, validateAnnotation } from '@toa.io/definitions/extensions.storages';
|
|
6
|
+
import { environment } from '@toa.io/generic';
|
|
7
|
+
export class Factory {
|
|
15
8
|
annotation;
|
|
16
9
|
constructor() {
|
|
17
|
-
const env =
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
10
|
+
const env = environment.get(ENV_PREFIX);
|
|
11
|
+
if (env === undefined)
|
|
12
|
+
throw new Error(`${ENV_PREFIX} is not defined`);
|
|
13
|
+
this.annotation = JSON.parse(env);
|
|
14
|
+
validateAnnotation(this.annotation);
|
|
21
15
|
}
|
|
22
16
|
aspect() {
|
|
23
|
-
|
|
24
|
-
return new Aspect_1.Aspect(storages);
|
|
17
|
+
return new Aspect(() => this.createStorages());
|
|
25
18
|
}
|
|
26
|
-
createStorages() {
|
|
19
|
+
async createStorages() {
|
|
27
20
|
const storages = {};
|
|
28
21
|
for (const [name, declaration] of Object.entries(this.annotation))
|
|
29
|
-
|
|
22
|
+
// the annotation is validated above, so a declaration is its provider's
|
|
23
|
+
storages[name] = await this.createStorage(name, declaration);
|
|
30
24
|
return storages;
|
|
31
25
|
}
|
|
32
|
-
createStorage(name, declaration) {
|
|
33
|
-
const { provider:
|
|
34
|
-
const Provider =
|
|
26
|
+
async createStorage(name, declaration) {
|
|
27
|
+
const { provider: id, ...options } = declaration;
|
|
28
|
+
const Provider = await load(id);
|
|
35
29
|
const secrets = this.resolveSecrets(name, Provider);
|
|
36
30
|
const provider = new Provider(options, secrets);
|
|
37
|
-
|
|
31
|
+
console.debug('Storage created', {
|
|
32
|
+
name,
|
|
33
|
+
provider: id,
|
|
34
|
+
...(provider.root === undefined ? undefined : { root: provider.root })
|
|
35
|
+
});
|
|
36
|
+
return new Storage(provider, { name, provider: id });
|
|
38
37
|
}
|
|
39
38
|
resolveSecrets(storageName, Class) {
|
|
40
39
|
if (Class.SECRETS === undefined)
|
|
41
40
|
return {};
|
|
42
41
|
const secrets = {};
|
|
43
42
|
for (const secret of Class.SECRETS) {
|
|
44
|
-
const variable = `${
|
|
45
|
-
const value =
|
|
46
|
-
|
|
43
|
+
const variable = `${ENV_PREFIX}_${storageName}_${secret.name}`.toUpperCase();
|
|
44
|
+
const value = environment.get(variable);
|
|
45
|
+
if (secret.optional !== true && value === undefined)
|
|
46
|
+
throw new Error(`'${variable}' is not defined`);
|
|
47
47
|
secrets[secret.name] = value;
|
|
48
48
|
}
|
|
49
49
|
return secrets;
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
|
-
exports.Factory = Factory;
|
|
53
52
|
//# sourceMappingURL=Factory.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Factory.js","sourceRoot":"","sources":["../source/Factory.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Factory.js","sourceRoot":"","sources":["../source/Factory.ts"],"names":[],"mappings":"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"}
|
package/transpiled/Provider.d.ts
CHANGED
|
@@ -1,22 +1,20 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
readonly
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
abstract
|
|
12
|
-
abstract
|
|
13
|
-
abstract
|
|
1
|
+
import type { Metadata, Stream } from './Entry.ts';
|
|
2
|
+
import type { Readable } from 'node:stream';
|
|
3
|
+
import type { Maybe } from '@toa.io/core/types';
|
|
4
|
+
import type { Secret, Secrets } from './Secrets.ts';
|
|
5
|
+
export declare abstract class Provider<Options = unknown> {
|
|
6
|
+
static readonly SECRETS?: readonly Secret[];
|
|
7
|
+
readonly root?: string;
|
|
8
|
+
readonly options: Options;
|
|
9
|
+
protected constructor(options: Options, secrets?: Secrets);
|
|
10
|
+
abstract get(path: string, options?: unknown): Promise<Maybe<Stream>>;
|
|
11
|
+
abstract head(path: string): Promise<Maybe<Metadata>>;
|
|
12
|
+
abstract put(path: string, stream: Readable): Promise<void>;
|
|
13
|
+
abstract commit(path: string, metadata: Metadata): Promise<void>;
|
|
14
14
|
abstract delete(path: string): Promise<void>;
|
|
15
|
-
abstract move(from: string, to: string): Promise<void
|
|
16
|
-
abstract moveDir(from: string, to: string): Promise<void>;
|
|
15
|
+
abstract move(from: string, to: string): Promise<Maybe<void>>;
|
|
17
16
|
}
|
|
18
|
-
export interface
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
new (options: any, secrets?: ProviderSecrets): Provider;
|
|
17
|
+
export interface Constructor<Options = any> {
|
|
18
|
+
SECRETS?: readonly Secret[];
|
|
19
|
+
new (options: Options, secrets?: Secrets): Provider<Options>;
|
|
22
20
|
}
|
package/transpiled/Provider.js
CHANGED
|
@@ -1,36 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.Provider = void 0;
|
|
27
|
-
const assert = __importStar(require("node:assert"));
|
|
28
|
-
class Provider {
|
|
29
|
-
static SECRETS = [];
|
|
30
|
-
constructor(_, secrets) {
|
|
31
|
-
for (const { name, optional = false } of new.target.SECRETS)
|
|
32
|
-
assert.ok(optional || secrets?.[name] !== undefined, `Missing secret '${name}'`);
|
|
1
|
+
export class Provider {
|
|
2
|
+
static SECRETS;
|
|
3
|
+
root;
|
|
4
|
+
options;
|
|
5
|
+
constructor(options, secrets) {
|
|
6
|
+
this.options = options;
|
|
7
|
+
new.target.SECRETS?.forEach(({ name, optional }) => {
|
|
8
|
+
if (optional !== true && secrets?.[name] === undefined)
|
|
9
|
+
throw new Error(`Missing secret '${name}'`);
|
|
10
|
+
});
|
|
33
11
|
}
|
|
34
12
|
}
|
|
35
|
-
exports.Provider = Provider;
|
|
36
13
|
//# sourceMappingURL=Provider.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Provider.js","sourceRoot":"","sources":["../source/Provider.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Provider.js","sourceRoot":"","sources":["../source/Provider.ts"],"names":[],"mappings":"AAKA,MAAM,OAAgB,QAAQ;IACrB,MAAM,CAAU,OAAO,CAAoB;IAClC,IAAI,CAAS;IACb,OAAO,CAAS;IAEhC,YAAsB,OAAgB,EAAE,OAAiB;QACvD,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;QAEtB,IAAI,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE,EAAE;YACjD,IAAI,QAAQ,KAAK,IAAI,IAAI,OAAO,EAAE,CAAC,IAAI,CAAC,KAAK,SAAS;gBACpD,MAAM,IAAI,KAAK,CAAC,mBAAmB,IAAI,GAAG,CAAC,CAAA;QAC/C,CAAC,CAAC,CAAA;IACJ,CAAC;CAaF"}
|
package/transpiled/Scanner.d.ts
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
|
-
/// <reference types="node" />
|
|
3
1
|
import { PassThrough, type TransformCallback } from 'node:stream';
|
|
4
2
|
export declare class Scanner extends PassThrough {
|
|
5
3
|
size: number;
|
|
6
4
|
type: string;
|
|
7
|
-
error
|
|
5
|
+
error?: Error;
|
|
8
6
|
private readonly hash;
|
|
9
7
|
private readonly claim?;
|
|
10
8
|
private readonly accept?;
|
|
9
|
+
private readonly limit?;
|
|
11
10
|
private position;
|
|
12
|
-
private
|
|
11
|
+
private completed;
|
|
13
12
|
private readonly chunks;
|
|
14
13
|
constructor(control?: ScanOptions);
|
|
15
14
|
digest(): string;
|
|
@@ -18,9 +17,11 @@ export declare class Scanner extends PassThrough {
|
|
|
18
17
|
private complete;
|
|
19
18
|
private verify;
|
|
20
19
|
private match;
|
|
20
|
+
private negotiate;
|
|
21
21
|
private interrupt;
|
|
22
22
|
}
|
|
23
23
|
export interface ScanOptions {
|
|
24
24
|
claim?: string;
|
|
25
25
|
accept?: string;
|
|
26
|
+
limit?: number;
|
|
26
27
|
}
|