@btravstack/storage 0.14.0 → 0.15.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/dist/index.cjs +45 -38
- package/dist/index.d.cts +9 -6
- package/dist/index.d.mts +9 -6
- package/dist/index.mjs +46 -39
- package/package.json +12 -13
package/dist/index.cjs
CHANGED
|
@@ -49,8 +49,6 @@ const memoryStorage = () => (0, _btravstack_di.Module)("MemoryStorage")({
|
|
|
49
49
|
//#endregion
|
|
50
50
|
//#region src/instrument.ts
|
|
51
51
|
/**
|
|
52
|
-
* One operation, handed to every observer the graph composed.
|
|
53
|
-
*
|
|
54
52
|
* **A missing object settles `ok` with `result: "not_found"`, not `error`.**
|
|
55
53
|
* Asking for something that is not there is an ordinary answer, and a dashboard
|
|
56
54
|
* that treats it as a fault teaches its readers to ignore the fault line.
|
|
@@ -59,53 +57,62 @@ const memoryStorage = () => (0, _btravstack_di.Module)("MemoryStorage")({
|
|
|
59
57
|
* `reason`, so an operator is not left hunting an object sitting where they put
|
|
60
58
|
* it.
|
|
61
59
|
*/
|
|
62
|
-
const
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
60
|
+
const failed = (failure) => {
|
|
61
|
+
const cause = failure.tag === "Err" ? failure.error : failure.cause;
|
|
62
|
+
const ordinary = failure.tag !== "Err" ? void 0 : failure.error._tag === "ObjectNotFound" ? "the object was not there" : failure.error._tag === "PresignNotSupported" ? "this store cannot mint a url" : void 0;
|
|
63
|
+
return ordinary === void 0 ? {
|
|
64
|
+
outcome: "error",
|
|
65
|
+
attributes: { result: "error" },
|
|
66
|
+
cause
|
|
67
|
+
} : {
|
|
70
68
|
outcome: "ok",
|
|
71
|
-
attributes: {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
outcome: "error",
|
|
77
|
-
attributes: { result: "error" },
|
|
78
|
-
cause
|
|
79
|
-
} : {
|
|
80
|
-
outcome: "ok",
|
|
81
|
-
attributes: {
|
|
82
|
-
result: "not_found",
|
|
83
|
-
reason: ordinary
|
|
84
|
-
}
|
|
85
|
-
});
|
|
86
|
-
});
|
|
69
|
+
attributes: {
|
|
70
|
+
result: "not_found",
|
|
71
|
+
reason: ordinary
|
|
72
|
+
}
|
|
73
|
+
};
|
|
87
74
|
};
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
75
|
+
/** The KEY is a detail, not a dimension: on the span and the line, never on an instrument. */
|
|
76
|
+
const through = (observers) => (operation, key, call) => (0, _btravstack_core.observed)(observers, {
|
|
77
|
+
component: "storage",
|
|
78
|
+
name: operation,
|
|
79
|
+
attributes: { operation },
|
|
80
|
+
details: { "btravstack.storage.key": key }
|
|
81
|
+
}, call, {
|
|
82
|
+
ok: () => ({
|
|
83
|
+
outcome: "ok",
|
|
84
|
+
attributes: { result: "ok" }
|
|
85
|
+
}),
|
|
86
|
+
failure: failed
|
|
94
87
|
});
|
|
88
|
+
/** Every operation handed to the observers the graph composed, transparent to the `Result`. */
|
|
89
|
+
const instrument = (backend, observers) => {
|
|
90
|
+
const observe = through(observers);
|
|
91
|
+
return {
|
|
92
|
+
put: (key, bytes, options) => observe("put", key, () => backend.put(key, bytes, options)),
|
|
93
|
+
get: (key) => observe("get", key, () => backend.get(key)),
|
|
94
|
+
delete: (key) => observe("delete", key, () => backend.delete(key)),
|
|
95
|
+
presignedUrl: (key, options) => observe("presigned_url", key, () => backend.presignedUrl(key, options)),
|
|
96
|
+
presignedUpload: (key, options) => observe("presigned_upload", key, () => backend.presignedUpload(key, options))
|
|
97
|
+
};
|
|
98
|
+
};
|
|
95
99
|
//#endregion
|
|
96
100
|
//#region src/module.ts
|
|
97
101
|
/**
|
|
98
|
-
* The storage starter: an adapter, and `Storage` provided from it
|
|
99
|
-
* instrumented or not, decided here at the composition root.
|
|
102
|
+
* The storage starter: an adapter, and `Storage` provided from it.
|
|
100
103
|
*
|
|
101
104
|
* ```ts
|
|
102
|
-
* storage({ adapter: s3Storage() });
|
|
103
|
-
* storage({ adapter: s3Storage(), instrumented: false }); // just a store
|
|
105
|
+
* storage({ adapter: s3Storage() });
|
|
104
106
|
* ```
|
|
105
107
|
*
|
|
106
108
|
* **Two ports, because di allows one provider per port per graph**: the port an
|
|
107
|
-
* application depends on must not be the one an adapter provides, which is
|
|
108
|
-
*
|
|
109
|
+
* application depends on must not be the one an adapter provides, which is what
|
|
110
|
+
* lets this function be the seam.
|
|
111
|
+
*
|
|
112
|
+
* **There is no `instrumented` flag.** Every operation is handed to whatever
|
|
113
|
+
* contributed to `Observers`; a graph that composed no observability has only
|
|
114
|
+
* this module's own no-op member, so it costs one call per operation and nothing
|
|
115
|
+
* else.
|
|
109
116
|
*/
|
|
110
117
|
const storage = ({ adapter }) => {
|
|
111
118
|
const healthCheck = _btravstack_di.Provider.member(_btravstack_core.HealthChecks)({
|
package/dist/index.d.cts
CHANGED
|
@@ -30,17 +30,20 @@ type StorageOptions<E, N> = {
|
|
|
30
30
|
readonly adapter: Module<StorageBackend, E, N>;
|
|
31
31
|
};
|
|
32
32
|
/**
|
|
33
|
-
* The storage starter: an adapter, and `Storage` provided from it
|
|
34
|
-
* instrumented or not, decided here at the composition root.
|
|
33
|
+
* The storage starter: an adapter, and `Storage` provided from it.
|
|
35
34
|
*
|
|
36
35
|
* ```ts
|
|
37
|
-
* storage({ adapter: s3Storage() });
|
|
38
|
-
* storage({ adapter: s3Storage(), instrumented: false }); // just a store
|
|
36
|
+
* storage({ adapter: s3Storage() });
|
|
39
37
|
* ```
|
|
40
38
|
*
|
|
41
39
|
* **Two ports, because di allows one provider per port per graph**: the port an
|
|
42
|
-
* application depends on must not be the one an adapter provides, which is
|
|
43
|
-
*
|
|
40
|
+
* application depends on must not be the one an adapter provides, which is what
|
|
41
|
+
* lets this function be the seam.
|
|
42
|
+
*
|
|
43
|
+
* **There is no `instrumented` flag.** Every operation is handed to whatever
|
|
44
|
+
* contributed to `Observers`; a graph that composed no observability has only
|
|
45
|
+
* this module's own no-op member, so it costs one call per operation and nothing
|
|
46
|
+
* else.
|
|
44
47
|
*/
|
|
45
48
|
export declare const storage: <E, N>({ adapter }: StorageOptions<E, N>) => Module<Storage | HealthChecks, E, N>;
|
|
46
49
|
//#endregion
|
package/dist/index.d.mts
CHANGED
|
@@ -30,17 +30,20 @@ type StorageOptions<E, N> = {
|
|
|
30
30
|
readonly adapter: Module<StorageBackend, E, N>;
|
|
31
31
|
};
|
|
32
32
|
/**
|
|
33
|
-
* The storage starter: an adapter, and `Storage` provided from it
|
|
34
|
-
* instrumented or not, decided here at the composition root.
|
|
33
|
+
* The storage starter: an adapter, and `Storage` provided from it.
|
|
35
34
|
*
|
|
36
35
|
* ```ts
|
|
37
|
-
* storage({ adapter: s3Storage() });
|
|
38
|
-
* storage({ adapter: s3Storage(), instrumented: false }); // just a store
|
|
36
|
+
* storage({ adapter: s3Storage() });
|
|
39
37
|
* ```
|
|
40
38
|
*
|
|
41
39
|
* **Two ports, because di allows one provider per port per graph**: the port an
|
|
42
|
-
* application depends on must not be the one an adapter provides, which is
|
|
43
|
-
*
|
|
40
|
+
* application depends on must not be the one an adapter provides, which is what
|
|
41
|
+
* lets this function be the seam.
|
|
42
|
+
*
|
|
43
|
+
* **There is no `instrumented` flag.** Every operation is handed to whatever
|
|
44
|
+
* contributed to `Observers`; a graph that composed no observability has only
|
|
45
|
+
* this module's own no-op member, so it costs one call per operation and nothing
|
|
46
|
+
* else.
|
|
44
47
|
*/
|
|
45
48
|
export declare const storage: <E, N>({ adapter }: StorageOptions<E, N>) => Module<Storage | HealthChecks, E, N>;
|
|
46
49
|
//#endregion
|
package/dist/index.mjs
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { a as StorageUnavailable, i as StorageBackend, n as PresignNotSupported, r as Storage, t as ObjectNotFound } from "./storage-CRkwIhac.mjs";
|
|
2
2
|
import { Module, Provider } from "@btravstack/di";
|
|
3
3
|
import { Err, ErrAsync, Ok, OkAsync, P } from "unthrown";
|
|
4
|
-
import { HealthCheckFailed, HealthChecks, Observers, noObserver,
|
|
4
|
+
import { HealthCheckFailed, HealthChecks, Observers, noObserver, observed } from "@btravstack/core";
|
|
5
5
|
//#region src/memory.ts
|
|
6
6
|
/**
|
|
7
7
|
* The in-process adapter: a `Map`, and an honest refusal to presign.
|
|
@@ -48,8 +48,6 @@ const memoryStorage = () => Module("MemoryStorage")({
|
|
|
48
48
|
//#endregion
|
|
49
49
|
//#region src/instrument.ts
|
|
50
50
|
/**
|
|
51
|
-
* One operation, handed to every observer the graph composed.
|
|
52
|
-
*
|
|
53
51
|
* **A missing object settles `ok` with `result: "not_found"`, not `error`.**
|
|
54
52
|
* Asking for something that is not there is an ordinary answer, and a dashboard
|
|
55
53
|
* that treats it as a fault teaches its readers to ignore the fault line.
|
|
@@ -58,53 +56,62 @@ const memoryStorage = () => Module("MemoryStorage")({
|
|
|
58
56
|
* `reason`, so an operator is not left hunting an object sitting where they put
|
|
59
57
|
* it.
|
|
60
58
|
*/
|
|
61
|
-
const
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
59
|
+
const failed = (failure) => {
|
|
60
|
+
const cause = failure.tag === "Err" ? failure.error : failure.cause;
|
|
61
|
+
const ordinary = failure.tag !== "Err" ? void 0 : failure.error._tag === "ObjectNotFound" ? "the object was not there" : failure.error._tag === "PresignNotSupported" ? "this store cannot mint a url" : void 0;
|
|
62
|
+
return ordinary === void 0 ? {
|
|
63
|
+
outcome: "error",
|
|
64
|
+
attributes: { result: "error" },
|
|
65
|
+
cause
|
|
66
|
+
} : {
|
|
69
67
|
outcome: "ok",
|
|
70
|
-
attributes: {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
outcome: "error",
|
|
76
|
-
attributes: { result: "error" },
|
|
77
|
-
cause
|
|
78
|
-
} : {
|
|
79
|
-
outcome: "ok",
|
|
80
|
-
attributes: {
|
|
81
|
-
result: "not_found",
|
|
82
|
-
reason: ordinary
|
|
83
|
-
}
|
|
84
|
-
});
|
|
85
|
-
});
|
|
68
|
+
attributes: {
|
|
69
|
+
result: "not_found",
|
|
70
|
+
reason: ordinary
|
|
71
|
+
}
|
|
72
|
+
};
|
|
86
73
|
};
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
74
|
+
/** The KEY is a detail, not a dimension: on the span and the line, never on an instrument. */
|
|
75
|
+
const through = (observers) => (operation, key, call) => observed(observers, {
|
|
76
|
+
component: "storage",
|
|
77
|
+
name: operation,
|
|
78
|
+
attributes: { operation },
|
|
79
|
+
details: { "btravstack.storage.key": key }
|
|
80
|
+
}, call, {
|
|
81
|
+
ok: () => ({
|
|
82
|
+
outcome: "ok",
|
|
83
|
+
attributes: { result: "ok" }
|
|
84
|
+
}),
|
|
85
|
+
failure: failed
|
|
93
86
|
});
|
|
87
|
+
/** Every operation handed to the observers the graph composed, transparent to the `Result`. */
|
|
88
|
+
const instrument = (backend, observers) => {
|
|
89
|
+
const observe = through(observers);
|
|
90
|
+
return {
|
|
91
|
+
put: (key, bytes, options) => observe("put", key, () => backend.put(key, bytes, options)),
|
|
92
|
+
get: (key) => observe("get", key, () => backend.get(key)),
|
|
93
|
+
delete: (key) => observe("delete", key, () => backend.delete(key)),
|
|
94
|
+
presignedUrl: (key, options) => observe("presigned_url", key, () => backend.presignedUrl(key, options)),
|
|
95
|
+
presignedUpload: (key, options) => observe("presigned_upload", key, () => backend.presignedUpload(key, options))
|
|
96
|
+
};
|
|
97
|
+
};
|
|
94
98
|
//#endregion
|
|
95
99
|
//#region src/module.ts
|
|
96
100
|
/**
|
|
97
|
-
* The storage starter: an adapter, and `Storage` provided from it
|
|
98
|
-
* instrumented or not, decided here at the composition root.
|
|
101
|
+
* The storage starter: an adapter, and `Storage` provided from it.
|
|
99
102
|
*
|
|
100
103
|
* ```ts
|
|
101
|
-
* storage({ adapter: s3Storage() });
|
|
102
|
-
* storage({ adapter: s3Storage(), instrumented: false }); // just a store
|
|
104
|
+
* storage({ adapter: s3Storage() });
|
|
103
105
|
* ```
|
|
104
106
|
*
|
|
105
107
|
* **Two ports, because di allows one provider per port per graph**: the port an
|
|
106
|
-
* application depends on must not be the one an adapter provides, which is
|
|
107
|
-
*
|
|
108
|
+
* application depends on must not be the one an adapter provides, which is what
|
|
109
|
+
* lets this function be the seam.
|
|
110
|
+
*
|
|
111
|
+
* **There is no `instrumented` flag.** Every operation is handed to whatever
|
|
112
|
+
* contributed to `Observers`; a graph that composed no observability has only
|
|
113
|
+
* this module's own no-op member, so it costs one call per operation and nothing
|
|
114
|
+
* else.
|
|
108
115
|
*/
|
|
109
116
|
const storage = ({ adapter }) => {
|
|
110
117
|
const healthCheck = Provider.member(HealthChecks)({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@btravstack/storage",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.15.0",
|
|
4
4
|
"description": "A Storage port for @btravstack/core: an in-memory adapter, an S3-compatible adapter with presigned reads, and a composition that spans, counts and logs every operation",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"dependency-injection",
|
|
@@ -55,6 +55,11 @@
|
|
|
55
55
|
"devDependencies": {
|
|
56
56
|
"@aws-sdk/client-s3": "3.1127.0",
|
|
57
57
|
"@aws-sdk/s3-request-presigner": "3.1127.0",
|
|
58
|
+
"@btravstack/config": "0.15.0",
|
|
59
|
+
"@btravstack/core": "0.15.0",
|
|
60
|
+
"@btravstack/di": "0.15.0",
|
|
61
|
+
"@btravstack/internal-test-infra": "0.0.0",
|
|
62
|
+
"@btravstack/observability": "0.15.0",
|
|
58
63
|
"@btravstack/tsconfig": "0.4.0",
|
|
59
64
|
"@opentelemetry/api": "1.9.1",
|
|
60
65
|
"@opentelemetry/sdk-metrics": "2.11.0",
|
|
@@ -66,20 +71,15 @@
|
|
|
66
71
|
"tsdown": "0.23.0",
|
|
67
72
|
"typescript": "7.0.2",
|
|
68
73
|
"unthrown": "5.8.0",
|
|
69
|
-
"vitest": "4.1.11"
|
|
70
|
-
"@btravstack/config": "0.14.0",
|
|
71
|
-
"@btravstack/core": "0.14.0",
|
|
72
|
-
"@btravstack/di": "0.14.0",
|
|
73
|
-
"@btravstack/internal-test-infra": "0.0.0",
|
|
74
|
-
"@btravstack/observability": "0.14.0"
|
|
74
|
+
"vitest": "4.1.11"
|
|
75
75
|
},
|
|
76
76
|
"peerDependencies": {
|
|
77
77
|
"@aws-sdk/client-s3": "^3.1000.0",
|
|
78
78
|
"@aws-sdk/s3-request-presigner": "^3.1000.0",
|
|
79
|
-
"
|
|
80
|
-
"@btravstack/
|
|
81
|
-
"@btravstack/
|
|
82
|
-
"
|
|
79
|
+
"@btravstack/config": "^0.15.0",
|
|
80
|
+
"@btravstack/core": "^0.15.0",
|
|
81
|
+
"@btravstack/di": "^0.15.0",
|
|
82
|
+
"unthrown": "^5.0.0"
|
|
83
83
|
},
|
|
84
84
|
"peerDependenciesMeta": {
|
|
85
85
|
"@aws-sdk/client-s3": {
|
|
@@ -96,7 +96,6 @@
|
|
|
96
96
|
"build": "tsdown src/index.ts src/s3.ts --format cjs,esm --dts --clean",
|
|
97
97
|
"dev": "tsdown src/index.ts src/s3.ts --format cjs,esm --dts --watch",
|
|
98
98
|
"test": "vitest run --coverage",
|
|
99
|
-
"
|
|
100
|
-
"typecheck": "tsc --noEmit"
|
|
99
|
+
"typecheck": "tsc --noEmit && tsc --noEmit -p tsconfig.test-d.json"
|
|
101
100
|
}
|
|
102
101
|
}
|