@owlmeans/storage-resource 0.1.18-rc.2 → 0.1.18-rc.20
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 +9 -5
- package/agent-meta/manifest.json +2 -2
- package/agent-meta/skills/storage-resource/SKILL.md +51 -14
- package/build/resource.d.ts.map +1 -1
- package/build/resource.js +1 -0
- package/build/resource.js.map +1 -1
- package/build/types.d.ts +7 -2
- package/build/types.d.ts.map +1 -1
- package/package.json +6 -6
- package/src/resource.ts +4 -5
- package/src/types.ts +7 -2
package/README.md
CHANGED
|
@@ -6,13 +6,15 @@ S3-compatible object storage resource for OwlMeans server applications.
|
|
|
6
6
|
|
|
7
7
|
- `createStorageResource(alias?, configKey?)` — creates an S3-backed storage resource
|
|
8
8
|
- `appendStorageResource(ctx, alias?, configKey?)` — registers the resource in the context
|
|
9
|
-
- `StorageResource` —
|
|
9
|
+
- `StorageResource` — an upload and nothing else: `Pick<Resource<StoredRecord>, 'create'>` plus
|
|
10
|
+
`BasicResource`. The bucket takes a stream and hands back a URL; there is no record store behind
|
|
11
|
+
it to read, list or delete against
|
|
10
12
|
- `StoredConfigAppend` — config mixin type for storage bucket credentials
|
|
11
13
|
|
|
12
14
|
## Installation
|
|
13
15
|
|
|
14
16
|
```bash
|
|
15
|
-
bun add @owlmeans/storage-resource
|
|
17
|
+
bun add @owlmeans/storage-resource@^0.1.18-rc.11
|
|
16
18
|
```
|
|
17
19
|
|
|
18
20
|
## Usage
|
|
@@ -51,19 +53,21 @@ Upload a file:
|
|
|
51
53
|
|
|
52
54
|
```typescript
|
|
53
55
|
const storage = context.resource<StorageResource>('images')
|
|
54
|
-
await storage.
|
|
56
|
+
const stored = await storage.create({
|
|
55
57
|
id: fileId,
|
|
56
58
|
prefix: 'uploads',
|
|
57
59
|
stream: readableStream,
|
|
58
60
|
type: 'image/jpeg'
|
|
59
61
|
})
|
|
62
|
+
// stored.url — where the object now lives
|
|
60
63
|
```
|
|
61
64
|
|
|
62
65
|
## API
|
|
63
66
|
|
|
64
67
|
### `createStorageResource(alias?, configKey?): StorageResource`
|
|
65
68
|
|
|
66
|
-
Creates an S3 storage resource. `alias` defaults to `DEFAULT_ALIAS` (`'s3-storage'`).
|
|
69
|
+
Creates an S3 storage resource. `alias` defaults to `DEFAULT_ALIAS` (`'s3-storage'`). The only data
|
|
70
|
+
method is `create(record)`, which uploads the stream and answers the record with its `url` filled in.
|
|
67
71
|
|
|
68
72
|
### `appendStorageResource<C, T>(ctx, alias?, configKey?): T`
|
|
69
73
|
|
|
@@ -98,7 +102,7 @@ This package ships embedded agent skills under `agent-meta/`. After installing y
|
|
|
98
102
|
your project's skill store (`.agents/skills/`):
|
|
99
103
|
|
|
100
104
|
```sh
|
|
101
|
-
npx @owlmeans/agent-skills
|
|
105
|
+
npx @owlmeans/agent-skills@^0.1.18-rc.20
|
|
102
106
|
```
|
|
103
107
|
|
|
104
108
|
The embedded files are version-matched to this package release. Do not edit them
|
package/agent-meta/manifest.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 2,
|
|
3
3
|
"package": "@owlmeans/storage-resource",
|
|
4
|
-
"version": "0.1.18-rc.
|
|
5
|
-
"generatedAt": "2026-
|
|
4
|
+
"version": "0.1.18-rc.20",
|
|
5
|
+
"generatedAt": "2026-09-12T14:21:25.461Z",
|
|
6
6
|
"canonicalRepo": "https://github.com/owlmeans/common",
|
|
7
7
|
"entries": [
|
|
8
8
|
{
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: storage-resource
|
|
3
|
-
description: How to use @owlmeans/storage-resource — S3-compatible object storage
|
|
3
|
+
description: How to use @owlmeans/storage-resource — the upload-only S3-compatible object storage resource, with mime sniffing on the way in. Auto-invoked when uploading files to a bucket or wiring cfg.storageBuckets.
|
|
4
4
|
user-invocable: false
|
|
5
5
|
---
|
|
6
6
|
<!-- AUTO-GENERATED — do not edit. Regenerate via sync-agent-meta. -->
|
|
@@ -8,31 +8,68 @@ user-invocable: false
|
|
|
8
8
|
# @owlmeans/storage-resource
|
|
9
9
|
|
|
10
10
|
**Layer:** Infra
|
|
11
|
-
**Install:** `"@owlmeans/storage-resource": "^0.1.18-rc.
|
|
11
|
+
**Install:** `"@owlmeans/storage-resource": "^0.1.18-rc.20"` in `dependencies`
|
|
12
12
|
|
|
13
13
|
## Key Exports
|
|
14
14
|
|
|
15
15
|
| Export | Description |
|
|
16
16
|
|--------|-------------|
|
|
17
|
-
| `
|
|
18
|
-
| `
|
|
19
|
-
|
|
|
20
|
-
|
|
|
17
|
+
| `appendStorageResource(context, alias?, configKey?)` | Register the upload resource on a server context |
|
|
18
|
+
| `createStorageResource(alias?, configKey?)` | The bare resource, when you register it yourself |
|
|
19
|
+
| `StorageResource` | `Pick<Resource<StoredRecord>, 'create'>` plus `BasicResource` — **an upload and nothing else** |
|
|
20
|
+
| `StoredRecord`, `StorageConfig`, `StoredConfigAppend` | The uploaded object, one bucket's config, and the `cfg.storageBuckets` shape |
|
|
21
|
+
| `stripData` | Drop the inline payload from a `StoredFileWithData` before it goes on the wire |
|
|
22
|
+
| `supportedMimeTypes`, `DEFAULT_ALIAS` (`s3-storage`) | Constants |
|
|
21
23
|
|
|
22
24
|
## Usage
|
|
23
25
|
|
|
24
26
|
```typescript
|
|
25
|
-
import {
|
|
27
|
+
import { appendStorageResource } from '@owlmeans/storage-resource'
|
|
26
28
|
|
|
27
|
-
context
|
|
28
|
-
alias: 'uploads',
|
|
29
|
-
bucket: WL_BUCKET,
|
|
30
|
-
}))
|
|
29
|
+
appendStorageResource(context, 'uploads', 'media-bucket')
|
|
31
30
|
|
|
32
|
-
|
|
31
|
+
const uploads = context.resource<StorageResource>('uploads')
|
|
32
|
+
const stored = await uploads.create({ stream, size, type: 'image/png', prefix: `${entityId}/${id}` })
|
|
33
|
+
stored.url // the public URL the bucket answers on
|
|
33
34
|
```
|
|
34
35
|
|
|
36
|
+
`configKey` selects the entry in `cfg.storageBuckets`, defaulting to the alias. The entry is
|
|
37
|
+
`{ url, apiKey, basePrefix }`:
|
|
38
|
+
|
|
39
|
+
| Key | Value |
|
|
40
|
+
|---|---|
|
|
41
|
+
| `url` | **`<bucket>.<endpoint-host>`, no scheme and no path** — the first dot-label is the S3 `Bucket`, everything after it is the endpoint (`https://<rest>`), e.g. `media.s3.eu-central-1.amazonaws.com` uploads to bucket `media` |
|
|
42
|
+
| `apiKey` | `"<keyId>:<keySecret>"` — one string, split on **every** colon with only the first two parts read, so a secret containing a colon is silently truncated at the next one |
|
|
43
|
+
| `basePrefix` | prepended to every key; the object lands at `<basePrefix>/<record.prefix>` and answers on `https://<url>/<basePrefix>/<record.prefix>` |
|
|
44
|
+
|
|
45
|
+
A `url` written as a plain endpoint (`https://s3.amazonaws.com`) uploads to a bucket literally named
|
|
46
|
+
`https://s3` and fails against the endpoint `amazonaws.com` — bucket-prefixed virtual-host style is
|
|
47
|
+
the only shape this reads. The region is fixed at `eu-central-1`, so a bucket elsewhere must be
|
|
48
|
+
addressed by an endpoint host that already carries its region.
|
|
49
|
+
|
|
50
|
+
## A bucket is not a record store
|
|
51
|
+
|
|
52
|
+
The type names the one method that works. There is no index behind a bucket to read, list or
|
|
53
|
+
delete against, so `StorageResource` exposes `create` alone rather than promising a full
|
|
54
|
+
`Resource<T>` whose rest would only throw. Keep the *record* — its url, size, mime type and
|
|
55
|
+
owner — in a mongo or postgres resource, and let this one carry the bytes; that record is what
|
|
56
|
+
answers criteria, sorting and paging.
|
|
57
|
+
|
|
58
|
+
`create` refuses anything it cannot vouch for: no `stream` raises `FileStreamError`, a missing
|
|
59
|
+
`size` `FilePropertyError`, and a body whose sniffed mime type disagrees with the declared `type`
|
|
60
|
+
raises `FileTypeError('mime-mismatch')` — a caller's claim about a file is checked against its
|
|
61
|
+
bytes, never taken. Bucket failures surface as `StorageApiError`. `opts.ttl` has nothing to act on
|
|
62
|
+
here: a bucket object never expires on its own.
|
|
63
|
+
|
|
35
64
|
## Depends On
|
|
36
65
|
|
|
37
|
-
- `@owlmeans/storage-common`, `@owlmeans/resource`, `@owlmeans/server-context
|
|
38
|
-
|
|
66
|
+
- `@owlmeans/storage-common`, `@owlmeans/resource`, `@owlmeans/context`, `@owlmeans/server-context`,
|
|
67
|
+
`@owlmeans/error`
|
|
68
|
+
- `@aws-sdk/client-s3`, `file-type` (runtime)
|
|
69
|
+
- The manifest also carries a `react` peer that nothing here imports — this is a server-side
|
|
70
|
+
package, and a consumer without React can ignore the peer warning.
|
|
71
|
+
|
|
72
|
+
## Related
|
|
73
|
+
|
|
74
|
+
- [[storage-common]] — the shared file types, schemas and errors
|
|
75
|
+
- [[image-resource]] — the image-shaped specialization of those types
|
package/build/resource.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resource.d.ts","sourceRoot":"","sources":["../src/resource.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,EAAgB,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"resource.d.ts","sourceRoot":"","sources":["../src/resource.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,EAAgB,MAAM,YAAY,CAAA;AAOhF,eAAO,MAAM,qBAAqB,WAAW,MAAM,cAA8B,MAAM,oBAwEtF,CAAA;AAED,eAAO,MAAM,qBAAqB,GAAI,CAAC,SAAS,MAAM,EAAE,CAAC,SAAS,OAAO,CAAC,CAAC,CAAC,OACrE,CAAC,UAAS,MAAM,cAA8B,MAAM,KACxD,CAMF,CAAA"}
|
package/build/resource.js
CHANGED
|
@@ -7,6 +7,7 @@ import { fileTypeFromBuffer } from 'file-type';
|
|
|
7
7
|
export const createStorageResource = (alias = DEFAULT_ALIAS, configKey) => {
|
|
8
8
|
configKey ??= alias;
|
|
9
9
|
const resource = appendContextual(alias, {
|
|
10
|
+
/** A bucket object never expires on its own, so `opts.ttl` has nothing to act on here. */
|
|
10
11
|
create: async (record, _opts) => {
|
|
11
12
|
if (record.stream == null) {
|
|
12
13
|
throw new FileStreamError('no');
|
package/build/resource.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resource.js","sourceRoot":"","sources":["../src/resource.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAG3C,OAAO,EAAE,iBAAiB,EAAE,eAAe,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAA;AAC7G,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAC/D,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAChD,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;
|
|
1
|
+
{"version":3,"file":"resource.js","sourceRoot":"","sources":["../src/resource.ts"],"names":[],"mappings":"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"}
|
package/build/types.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { BasicResource } from '@owlmeans/context';
|
|
1
2
|
import type { Resource, ResourceRecord } from '@owlmeans/resource';
|
|
2
3
|
import type { StoredFileFormat } from '@owlmeans/storage-common';
|
|
3
4
|
import type { ServerConfig, ServerContext } from '@owlmeans/server-context';
|
|
@@ -22,8 +23,12 @@ export interface StorageConfig {
|
|
|
22
23
|
apiKey: string;
|
|
23
24
|
basePrefix: string;
|
|
24
25
|
}
|
|
25
|
-
|
|
26
|
-
|
|
26
|
+
/**
|
|
27
|
+
* An upload and nothing else. The bucket takes a stream and hands back a URL; there is no record
|
|
28
|
+
* store behind it to read, list or delete against, so the type names the one method that works
|
|
29
|
+
* rather than promising a full {@link Resource} whose rest would only throw.
|
|
30
|
+
*/
|
|
31
|
+
export type StorageResource = Pick<Resource<StoredRecord>, 'create'> & BasicResource;
|
|
27
32
|
export interface Config extends ServerConfig, StoredConfigAppend {
|
|
28
33
|
}
|
|
29
34
|
export interface Context<C extends Config = Config> extends ServerContext<C> {
|
package/build/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAClE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAC3E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAEtC,MAAM,WAAW,YAAa,SAAQ,cAAc;IAClD,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,QAAQ,CAAA;IACjB,MAAM,CAAC,EAAE,gBAAgB,CAAA;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,UAAU,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,cAAc,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAAA;KAAE,CAAA;CACjD;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,MAAM,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAA;AACtD,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAClE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAChE,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAC3E,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AAEtC,MAAM,WAAW,YAAa,SAAQ,cAAc;IAClD,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,QAAQ,CAAA;IACjB,MAAM,CAAC,EAAE,gBAAgB,CAAA;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,UAAU,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,cAAc,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,aAAa,CAAA;KAAE,CAAA;CACjD;AAED,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;IACd,UAAU,EAAE,MAAM,CAAA;CACnB;AAED;;;;GAIG;AACH,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,QAAQ,CAAC,GAAG,aAAa,CAAA;AAEpF,MAAM,WAAW,MAAO,SAAQ,YAAY,EAAE,kBAAkB;CAAI;AACpE,MAAM,WAAW,OAAO,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,CAAE,SAAQ,aAAa,CAAC,CAAC,CAAC;CAAI"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@owlmeans/storage-resource",
|
|
3
|
-
"version": "0.1.18-rc.
|
|
3
|
+
"version": "0.1.18-rc.20",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
@@ -25,11 +25,11 @@
|
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
27
|
"@aws-sdk/client-s3": "^3.701.0",
|
|
28
|
-
"@owlmeans/context": "^0.1.18-rc.
|
|
29
|
-
"@owlmeans/error": "^0.1.18-rc.
|
|
30
|
-
"@owlmeans/resource": "^0.1.18-rc.
|
|
31
|
-
"@owlmeans/server-context": "^0.1.18-rc.
|
|
32
|
-
"@owlmeans/storage-common": "^0.1.18-rc.
|
|
28
|
+
"@owlmeans/context": "^0.1.18-rc.16",
|
|
29
|
+
"@owlmeans/error": "^0.1.18-rc.16",
|
|
30
|
+
"@owlmeans/resource": "^0.1.18-rc.17",
|
|
31
|
+
"@owlmeans/server-context": "^0.1.18-rc.20",
|
|
32
|
+
"@owlmeans/storage-common": "^0.1.18-rc.17",
|
|
33
33
|
"file-type": "^22.0.1"
|
|
34
34
|
},
|
|
35
35
|
"devDependencies": {
|
package/src/resource.ts
CHANGED
|
@@ -1,19 +1,18 @@
|
|
|
1
1
|
import { appendContextual } from '@owlmeans/context'
|
|
2
2
|
import { DEFAULT_ALIAS } from './consts.js'
|
|
3
3
|
import type { Config, Context, StorageResource, StoredRecord } from './types.js'
|
|
4
|
-
import type {
|
|
4
|
+
import type { WriteOptions } from '@owlmeans/resource'
|
|
5
5
|
import { FilePropertyError, FileStreamError, FileTypeError, StorageApiError } from '@owlmeans/storage-common'
|
|
6
6
|
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3'
|
|
7
7
|
import { ResilientError } from '@owlmeans/error'
|
|
8
8
|
import { fileTypeFromBuffer } from 'file-type'
|
|
9
9
|
|
|
10
|
-
type Getter = string | GetterOptions
|
|
11
|
-
|
|
12
10
|
export const createStorageResource = (alias: string = DEFAULT_ALIAS, configKey?: string) => {
|
|
13
11
|
configKey ??= alias
|
|
14
12
|
|
|
15
13
|
const resource = appendContextual<StorageResource>(alias, {
|
|
16
|
-
|
|
14
|
+
/** A bucket object never expires on its own, so `opts.ttl` has nothing to act on here. */
|
|
15
|
+
create: async (record: Partial<StoredRecord>, _opts?: WriteOptions) => {
|
|
17
16
|
if (record.stream == null) {
|
|
18
17
|
throw new FileStreamError('no')
|
|
19
18
|
}
|
|
@@ -75,7 +74,7 @@ export const createStorageResource = (alias: string = DEFAULT_ALIAS, configKey?:
|
|
|
75
74
|
throw new StorageApiError()
|
|
76
75
|
}
|
|
77
76
|
|
|
78
|
-
return record as
|
|
77
|
+
return record as StoredRecord
|
|
79
78
|
}
|
|
80
79
|
})
|
|
81
80
|
|
package/src/types.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { BasicResource } from '@owlmeans/context'
|
|
1
2
|
import type { Resource, ResourceRecord } from '@owlmeans/resource'
|
|
2
3
|
import type { StoredFileFormat } from '@owlmeans/storage-common'
|
|
3
4
|
import type { ServerConfig, ServerContext } from '@owlmeans/server-context'
|
|
@@ -24,8 +25,12 @@ export interface StorageConfig {
|
|
|
24
25
|
basePrefix: string
|
|
25
26
|
}
|
|
26
27
|
|
|
27
|
-
|
|
28
|
-
|
|
28
|
+
/**
|
|
29
|
+
* An upload and nothing else. The bucket takes a stream and hands back a URL; there is no record
|
|
30
|
+
* store behind it to read, list or delete against, so the type names the one method that works
|
|
31
|
+
* rather than promising a full {@link Resource} whose rest would only throw.
|
|
32
|
+
*/
|
|
33
|
+
export type StorageResource = Pick<Resource<StoredRecord>, 'create'> & BasicResource
|
|
29
34
|
|
|
30
35
|
export interface Config extends ServerConfig, StoredConfigAppend { }
|
|
31
36
|
export interface Context<C extends Config = Config> extends ServerContext<C> { }
|