@btravstack/storage 0.9.0 → 0.11.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 CHANGED
@@ -64,7 +64,7 @@ export const invoices = InvoiceProvider(Invoices)({
64
64
  storage
65
65
  .put(keyFor(tenantId, id), pdf, { contentType: "application/pdf" })
66
66
  // A document that failed to store is YOUR decision to make; here it
67
- // is swallowed because the instrumented store already logged and
67
+ // is swallowed because an observer already recorded it and
68
68
  // counted it one layer down.
69
69
  .recoverErrCases((matcher) =>
70
70
  matcher.with(P.tag("StorageUnavailable"), () => undefined),
@@ -83,7 +83,7 @@ export const invoices = InvoiceProvider(Invoices)({
83
83
  });
84
84
  ```
85
85
 
86
- The composition — the adapter, and whether operations are instrumented,
86
+ The composition — the adapter is the only decision,
87
87
  decided here and nowhere else:
88
88
 
89
89
  ```ts
@@ -93,7 +93,8 @@ import { s3Storage } from "@btravstack/storage/s3";
93
93
  export const InvoicesApp = Module("InvoicesApp")({
94
94
  imports: [
95
95
  // Instrumented by default, which is why `observability()` and `otel()`
96
- // are below. Pass `instrumented: false` for the same graph without them.
96
+ // Every call is reported through `Observers`. Drop the two modules
97
+ // below and this composition is unchanged — it just reports to nobody.
97
98
  storage({ adapter: s3Storage() }),
98
99
  observability(),
99
100
  otel(),
@@ -105,14 +106,13 @@ export const InvoicesApp = Module("InvoicesApp")({
105
106
 
106
107
  ## Options
107
108
 
108
- | Option | Where | What it is |
109
- | ----------------------------------------------------------- | ---------------------------------- | ---------------------------------------------------------------------- |
110
- | `adapter` | `storage({ adapter })` | the adapter module providing `StorageBackend` — required |
111
- | `instrumented` | `storage({ instrumented })` | span, count and log every operation (default `true`; `false` opts out) |
112
- | `STORAGE_S3_ENDPOINT` | environment, read by `s3Storage()` | the store's endpoint — required |
113
- | `STORAGE_S3_BUCKET` | environment | the bucket — required |
114
- | `STORAGE_S3_ACCESS_KEY_ID` / `STORAGE_S3_SECRET_ACCESS_KEY` | environment | the credentials — required |
115
- | `STORAGE_S3_REGION` | environment | default `us-east-1` |
109
+ | Option | Where | What it is |
110
+ | ----------------------------------------------------------- | ---------------------------------- | -------------------------------------------------------- |
111
+ | `adapter` | `storage({ adapter })` | the adapter module providing `StorageBackend` — required |
112
+ | `STORAGE_S3_ENDPOINT` | environment, read by `s3Storage()` | the store's endpoint — required |
113
+ | `STORAGE_S3_BUCKET` | environment | the bucket — required |
114
+ | `STORAGE_S3_ACCESS_KEY_ID` / `STORAGE_S3_SECRET_ACCESS_KEY` | environment | the credentials — required |
115
+ | `STORAGE_S3_REGION` | environment | default `us-east-1` |
116
116
 
117
117
  The full table — defaults, semantics and the reasoning — lives on
118
118
  [the reference page](https://btravstack.github.io/btravstack/reference/storage),
package/dist/index.cjs CHANGED
@@ -49,60 +49,49 @@ const memoryStorage = () => (0, _btravstack_di.Module)("MemoryStorage")({
49
49
  //#endregion
50
50
  //#region src/instrument.ts
51
51
  /**
52
- * One operation, wrapped: a span around it, a count of how it came out, and a
53
- * log line if it failed.
52
+ * One operation, handed to every observer the graph composed.
54
53
  *
55
- * **A missing object is counted `not_found` and logged at `info`, not
56
- * `error`.** Asking for something that is not there is an ordinary answer, and
57
- * a dashboard that treats it as a fault teaches its readers to ignore the fault
58
- * line. `StorageUnavailable` is what pages somebody.
54
+ * **A missing object settles `ok` with `result: "not_found"`, not `error`.**
55
+ * Asking for something that is not there is an ordinary answer, and a dashboard
56
+ * that treats it as a fault teaches its readers to ignore the fault line.
57
+ * `StorageUnavailable` is what pages somebody, and it is the only one that
58
+ * settles as an error. The two ordinary answers keep their own words in
59
+ * `reason`, so an operator is not left hunting an object sitting where they put
60
+ * it.
59
61
  */
60
- const observed = (call, { operation, key, logger, tracer, operations }) => {
61
- const span = tracer.startSpan(`storage.${operation}`);
62
- span.setAttributes({ "btravstack.storage.key": key });
63
- return call().tap(() => {
64
- operations.add(1, {
65
- operation,
66
- outcome: "ok"
67
- });
68
- span.end();
69
- }).tapFailure((failure) => {
62
+ const observed = (call, observers, operation, key) => {
63
+ const settle = (0, _btravstack_core.observe)(observers, {
64
+ component: "storage",
65
+ name: operation,
66
+ attributes: { operation },
67
+ details: { "btravstack.storage.key": key }
68
+ });
69
+ return call().tap(() => settle({
70
+ outcome: "ok",
71
+ attributes: { result: "ok" }
72
+ })).tapFailure((failure) => {
70
73
  const cause = failure.tag === "Err" ? failure.error : failure.cause;
71
- const message = 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;
72
- operations.add(1, {
73
- operation,
74
- outcome: message === void 0 ? "error" : "not_found"
75
- });
76
- if (message === void 0) {
77
- logger.error("the store could not answer", {
78
- operation,
79
- key
80
- }, cause);
81
- span.setStatus({ code: _btravstack_core.SPAN_STATUS.error });
82
- } else logger.info(message, {
83
- operation,
84
- key
74
+ 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;
75
+ settle(ordinary === void 0 ? {
76
+ outcome: "error",
77
+ attributes: { result: "error" },
78
+ cause
79
+ } : {
80
+ outcome: "ok",
81
+ attributes: {
82
+ result: "not_found",
83
+ reason: ordinary
84
+ }
85
85
  });
86
- span.end();
87
86
  });
88
87
  };
89
- const instrument = (backend, logger, tracer, meter) => {
90
- const operations = meter.createCounter("btravstack.storage.operations", { description: "Storage operations, by operation and outcome" });
91
- const context = (operation, key) => ({
92
- operation,
93
- key,
94
- logger,
95
- tracer,
96
- operations
97
- });
98
- return {
99
- put: (key, bytes, options) => observed(() => backend.put(key, bytes, options), context("put", key)),
100
- get: (key) => observed(() => backend.get(key), context("get", key)),
101
- delete: (key) => observed(() => backend.delete(key), context("delete", key)),
102
- presignedUrl: (key, options) => observed(() => backend.presignedUrl(key, options), context("presigned_url", key)),
103
- presignedUpload: (key, options) => observed(() => backend.presignedUpload(key, options), context("presigned_upload", key))
104
- };
105
- };
88
+ const instrument = (backend, observers) => ({
89
+ put: (key, bytes, options) => observed(() => backend.put(key, bytes, options), observers, "put", key),
90
+ get: (key) => observed(() => backend.get(key), observers, "get", key),
91
+ delete: (key) => observed(() => backend.delete(key), observers, "delete", key),
92
+ presignedUrl: (key, options) => observed(() => backend.presignedUrl(key, options), observers, "presigned_url", key),
93
+ presignedUpload: (key, options) => observed(() => backend.presignedUpload(key, options), observers, "presigned_upload", key)
94
+ });
106
95
  //#endregion
107
96
  //#region src/module.ts
108
97
  /**
@@ -118,7 +107,7 @@ const instrument = (backend, logger, tracer, meter) => {
118
107
  * application depends on must not be the one an adapter provides, which is also
119
108
  * why instrumentation is a flag on the composition rather than a wrapper.
120
109
  */
121
- const storage = ({ adapter, instrumented }) => {
110
+ const storage = ({ adapter }) => {
122
111
  const healthCheck = _btravstack_di.Provider.member(_btravstack_core.HealthChecks)({
123
112
  inject: { backend: require_storage.StorageBackend },
124
113
  sync: ({ backend }) => ({
@@ -126,29 +115,22 @@ const storage = ({ adapter, instrumented }) => {
126
115
  check: () => backend.get("btravstack:health").map(() => void 0).flatMapErrCases((matcher) => matcher.with(unthrown.P.tag("ObjectNotFound"), () => (0, unthrown.Ok)(void 0)).with(unthrown.P.tag("StorageUnavailable"), ({ reason }) => (0, unthrown.Err)(new _btravstack_core.HealthCheckFailed({ reason: `storage unavailable (${reason})` }))))
127
116
  })
128
117
  });
129
- return instrumented !== false ? (0, _btravstack_di.Module)("InstrumentedStorage")({
130
- needs: [
131
- _btravstack_core.Logger,
132
- _btravstack_core.Meter,
133
- _btravstack_core.Tracer
134
- ],
118
+ return (0, _btravstack_di.Module)("Storage")({
135
119
  imports: [adapter],
136
- provides: [(0, _btravstack_di.Provider)(require_storage.Storage)({
137
- inject: {
138
- backend: require_storage.StorageBackend,
139
- logger: _btravstack_core.Logger,
140
- tracer: _btravstack_core.Tracer,
141
- meter: _btravstack_core.Meter
142
- },
143
- sync: ({ backend, logger, tracer, meter }) => instrument(backend, logger, tracer, meter)
144
- }), healthCheck],
145
- exports: [require_storage.Storage, _btravstack_core.HealthChecks]
146
- }) : (0, _btravstack_di.Module)("Storage")({
147
- imports: [adapter],
148
- provides: [(0, _btravstack_di.Provider)(require_storage.Storage)({
149
- inject: { backend: require_storage.StorageBackend },
150
- sync: ({ backend }) => backend
151
- }), healthCheck],
120
+ provides: [
121
+ _btravstack_di.Provider.member(_btravstack_core.Observers)({
122
+ inject: {},
123
+ value: _btravstack_core.noObserver
124
+ }),
125
+ (0, _btravstack_di.Provider)(require_storage.Storage)({
126
+ inject: {
127
+ backend: require_storage.StorageBackend,
128
+ observers: _btravstack_core.Observers
129
+ },
130
+ sync: ({ backend, observers }) => instrument(backend, observers)
131
+ }),
132
+ healthCheck
133
+ ],
152
134
  exports: [require_storage.Storage, _btravstack_core.HealthChecks]
153
135
  });
154
136
  };
package/dist/index.d.cts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { a as StorageService, i as StorageBackend, n as PresignNotSupported, o as StorageUnavailable, r as Storage, s as StoredObject, t as ObjectNotFound } from "./storage-Cu27C7Oq.cjs";
2
2
  import { Module, Provider } from "@btravstack/di";
3
- import { HealthChecks, Logger, Meter, Tracer } from "@btravstack/core";
3
+ import { HealthChecks } from "@btravstack/core";
4
4
  //#region src/memory.d.ts
5
5
  /**
6
6
  * The in-process adapter: a `Map`, and an honest refusal to presign.
@@ -21,22 +21,13 @@ declare const memoryStorageProvider: () => Provider<StorageBackend, never, never
21
21
  declare const memoryStorage: () => Module<StorageBackend, never, never>;
22
22
  //#endregion
23
23
  //#region src/module.d.ts
24
- type StorageOptions<E, N, Instrumented extends boolean> = {
24
+ type StorageOptions<E, N> = {
25
25
  /**
26
- * The adapter module: `memoryStorage()` from this entry point,
27
- * `s3Storage()` from `@btravstack/storage/s3`, or one an application
28
- * wrote itself over `StorageBackend`.
26
+ * The adapter module: `memoryStorage()` from this entry point, `s3Storage()`
27
+ * from `@btravstack/storage/s3`, or one an application wrote itself over
28
+ * `StorageBackend`.
29
29
  */
30
30
  readonly adapter: Module<StorageBackend, E, N>;
31
- /**
32
- * Span, count and log every operation. **Default `true`**, `false` opts out.
33
- *
34
- * On by default because telemetry that is missing is discovered during an
35
- * incident. The cost is stated rather than hidden: instrumenting puts
36
- * `Logger`, `Meter` and `Tracer` in this module's `Needs`, so a root without
37
- * `observability()` and `otel()` gets a compile error naming all three.
38
- */
39
- readonly instrumented?: Instrumented;
40
31
  };
41
32
  /**
42
33
  * The storage starter: an adapter, and `Storage` provided from it —
@@ -51,6 +42,6 @@ type StorageOptions<E, N, Instrumented extends boolean> = {
51
42
  * application depends on must not be the one an adapter provides, which is also
52
43
  * why instrumentation is a flag on the composition rather than a wrapper.
53
44
  */
54
- declare const storage: <E, N, Instrumented extends boolean = true>({ adapter, instrumented }: StorageOptions<E, N, Instrumented>) => Module<Storage | HealthChecks, E, Instrumented extends true ? N | Logger | Meter | Tracer : N>;
45
+ declare const storage: <E, N>({ adapter }: StorageOptions<E, N>) => Module<Storage | HealthChecks, E, N>;
55
46
  //#endregion
56
47
  export { ObjectNotFound, PresignNotSupported, Storage, StorageBackend, type StorageOptions, type StorageService, StorageUnavailable, type StoredObject, memoryStorage, memoryStorageBackend, memoryStorageProvider, storage };
package/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { a as StorageService, i as StorageBackend, n as PresignNotSupported, o as StorageUnavailable, r as Storage, s as StoredObject, t as ObjectNotFound } from "./storage-Cu27C7Oq.mjs";
2
2
  import { Module, Provider } from "@btravstack/di";
3
- import { HealthChecks, Logger, Meter, Tracer } from "@btravstack/core";
3
+ import { HealthChecks } from "@btravstack/core";
4
4
  //#region src/memory.d.ts
5
5
  /**
6
6
  * The in-process adapter: a `Map`, and an honest refusal to presign.
@@ -21,22 +21,13 @@ declare const memoryStorageProvider: () => Provider<StorageBackend, never, never
21
21
  declare const memoryStorage: () => Module<StorageBackend, never, never>;
22
22
  //#endregion
23
23
  //#region src/module.d.ts
24
- type StorageOptions<E, N, Instrumented extends boolean> = {
24
+ type StorageOptions<E, N> = {
25
25
  /**
26
- * The adapter module: `memoryStorage()` from this entry point,
27
- * `s3Storage()` from `@btravstack/storage/s3`, or one an application
28
- * wrote itself over `StorageBackend`.
26
+ * The adapter module: `memoryStorage()` from this entry point, `s3Storage()`
27
+ * from `@btravstack/storage/s3`, or one an application wrote itself over
28
+ * `StorageBackend`.
29
29
  */
30
30
  readonly adapter: Module<StorageBackend, E, N>;
31
- /**
32
- * Span, count and log every operation. **Default `true`**, `false` opts out.
33
- *
34
- * On by default because telemetry that is missing is discovered during an
35
- * incident. The cost is stated rather than hidden: instrumenting puts
36
- * `Logger`, `Meter` and `Tracer` in this module's `Needs`, so a root without
37
- * `observability()` and `otel()` gets a compile error naming all three.
38
- */
39
- readonly instrumented?: Instrumented;
40
31
  };
41
32
  /**
42
33
  * The storage starter: an adapter, and `Storage` provided from it —
@@ -51,6 +42,6 @@ type StorageOptions<E, N, Instrumented extends boolean> = {
51
42
  * application depends on must not be the one an adapter provides, which is also
52
43
  * why instrumentation is a flag on the composition rather than a wrapper.
53
44
  */
54
- declare const storage: <E, N, Instrumented extends boolean = true>({ adapter, instrumented }: StorageOptions<E, N, Instrumented>) => Module<Storage | HealthChecks, E, Instrumented extends true ? N | Logger | Meter | Tracer : N>;
45
+ declare const storage: <E, N>({ adapter }: StorageOptions<E, N>) => Module<Storage | HealthChecks, E, N>;
55
46
  //#endregion
56
47
  export { ObjectNotFound, PresignNotSupported, Storage, StorageBackend, type StorageOptions, type StorageService, StorageUnavailable, type StoredObject, memoryStorage, memoryStorageBackend, memoryStorageProvider, storage };
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, Logger, Meter, SPAN_STATUS, Tracer } from "@btravstack/core";
4
+ import { HealthCheckFailed, HealthChecks, Observers, noObserver, observe } 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,60 +48,49 @@ const memoryStorage = () => Module("MemoryStorage")({
48
48
  //#endregion
49
49
  //#region src/instrument.ts
50
50
  /**
51
- * One operation, wrapped: a span around it, a count of how it came out, and a
52
- * log line if it failed.
51
+ * One operation, handed to every observer the graph composed.
53
52
  *
54
- * **A missing object is counted `not_found` and logged at `info`, not
55
- * `error`.** Asking for something that is not there is an ordinary answer, and
56
- * a dashboard that treats it as a fault teaches its readers to ignore the fault
57
- * line. `StorageUnavailable` is what pages somebody.
53
+ * **A missing object settles `ok` with `result: "not_found"`, not `error`.**
54
+ * Asking for something that is not there is an ordinary answer, and a dashboard
55
+ * that treats it as a fault teaches its readers to ignore the fault line.
56
+ * `StorageUnavailable` is what pages somebody, and it is the only one that
57
+ * settles as an error. The two ordinary answers keep their own words in
58
+ * `reason`, so an operator is not left hunting an object sitting where they put
59
+ * it.
58
60
  */
59
- const observed = (call, { operation, key, logger, tracer, operations }) => {
60
- const span = tracer.startSpan(`storage.${operation}`);
61
- span.setAttributes({ "btravstack.storage.key": key });
62
- return call().tap(() => {
63
- operations.add(1, {
64
- operation,
65
- outcome: "ok"
66
- });
67
- span.end();
68
- }).tapFailure((failure) => {
61
+ const observed = (call, observers, operation, key) => {
62
+ const settle = observe(observers, {
63
+ component: "storage",
64
+ name: operation,
65
+ attributes: { operation },
66
+ details: { "btravstack.storage.key": key }
67
+ });
68
+ return call().tap(() => settle({
69
+ outcome: "ok",
70
+ attributes: { result: "ok" }
71
+ })).tapFailure((failure) => {
69
72
  const cause = failure.tag === "Err" ? failure.error : failure.cause;
70
- const message = 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;
71
- operations.add(1, {
72
- operation,
73
- outcome: message === void 0 ? "error" : "not_found"
74
- });
75
- if (message === void 0) {
76
- logger.error("the store could not answer", {
77
- operation,
78
- key
79
- }, cause);
80
- span.setStatus({ code: SPAN_STATUS.error });
81
- } else logger.info(message, {
82
- operation,
83
- key
73
+ 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;
74
+ settle(ordinary === void 0 ? {
75
+ outcome: "error",
76
+ attributes: { result: "error" },
77
+ cause
78
+ } : {
79
+ outcome: "ok",
80
+ attributes: {
81
+ result: "not_found",
82
+ reason: ordinary
83
+ }
84
84
  });
85
- span.end();
86
85
  });
87
86
  };
88
- const instrument = (backend, logger, tracer, meter) => {
89
- const operations = meter.createCounter("btravstack.storage.operations", { description: "Storage operations, by operation and outcome" });
90
- const context = (operation, key) => ({
91
- operation,
92
- key,
93
- logger,
94
- tracer,
95
- operations
96
- });
97
- return {
98
- put: (key, bytes, options) => observed(() => backend.put(key, bytes, options), context("put", key)),
99
- get: (key) => observed(() => backend.get(key), context("get", key)),
100
- delete: (key) => observed(() => backend.delete(key), context("delete", key)),
101
- presignedUrl: (key, options) => observed(() => backend.presignedUrl(key, options), context("presigned_url", key)),
102
- presignedUpload: (key, options) => observed(() => backend.presignedUpload(key, options), context("presigned_upload", key))
103
- };
104
- };
87
+ const instrument = (backend, observers) => ({
88
+ put: (key, bytes, options) => observed(() => backend.put(key, bytes, options), observers, "put", key),
89
+ get: (key) => observed(() => backend.get(key), observers, "get", key),
90
+ delete: (key) => observed(() => backend.delete(key), observers, "delete", key),
91
+ presignedUrl: (key, options) => observed(() => backend.presignedUrl(key, options), observers, "presigned_url", key),
92
+ presignedUpload: (key, options) => observed(() => backend.presignedUpload(key, options), observers, "presigned_upload", key)
93
+ });
105
94
  //#endregion
106
95
  //#region src/module.ts
107
96
  /**
@@ -117,7 +106,7 @@ const instrument = (backend, logger, tracer, meter) => {
117
106
  * application depends on must not be the one an adapter provides, which is also
118
107
  * why instrumentation is a flag on the composition rather than a wrapper.
119
108
  */
120
- const storage = ({ adapter, instrumented }) => {
109
+ const storage = ({ adapter }) => {
121
110
  const healthCheck = Provider.member(HealthChecks)({
122
111
  inject: { backend: StorageBackend },
123
112
  sync: ({ backend }) => ({
@@ -125,29 +114,22 @@ const storage = ({ adapter, instrumented }) => {
125
114
  check: () => backend.get("btravstack:health").map(() => void 0).flatMapErrCases((matcher) => matcher.with(P.tag("ObjectNotFound"), () => Ok(void 0)).with(P.tag("StorageUnavailable"), ({ reason }) => Err(new HealthCheckFailed({ reason: `storage unavailable (${reason})` }))))
126
115
  })
127
116
  });
128
- return instrumented !== false ? Module("InstrumentedStorage")({
129
- needs: [
130
- Logger,
131
- Meter,
132
- Tracer
133
- ],
117
+ return Module("Storage")({
134
118
  imports: [adapter],
135
- provides: [Provider(Storage)({
136
- inject: {
137
- backend: StorageBackend,
138
- logger: Logger,
139
- tracer: Tracer,
140
- meter: Meter
141
- },
142
- sync: ({ backend, logger, tracer, meter }) => instrument(backend, logger, tracer, meter)
143
- }), healthCheck],
144
- exports: [Storage, HealthChecks]
145
- }) : Module("Storage")({
146
- imports: [adapter],
147
- provides: [Provider(Storage)({
148
- inject: { backend: StorageBackend },
149
- sync: ({ backend }) => backend
150
- }), healthCheck],
119
+ provides: [
120
+ Provider.member(Observers)({
121
+ inject: {},
122
+ value: noObserver
123
+ }),
124
+ Provider(Storage)({
125
+ inject: {
126
+ backend: StorageBackend,
127
+ observers: Observers
128
+ },
129
+ sync: ({ backend, observers }) => instrument(backend, observers)
130
+ }),
131
+ healthCheck
132
+ ],
151
133
  exports: [Storage, HealthChecks]
152
134
  });
153
135
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@btravstack/storage",
3
- "version": "0.9.0",
3
+ "version": "0.11.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",
@@ -67,19 +67,19 @@
67
67
  "typescript": "7.0.2",
68
68
  "unthrown": "5.7.0",
69
69
  "vitest": "4.1.11",
70
- "@btravstack/config": "0.9.0",
71
- "@btravstack/di": "0.9.0",
70
+ "@btravstack/config": "0.11.0",
71
+ "@btravstack/core": "0.11.0",
72
+ "@btravstack/di": "0.11.0",
72
73
  "@btravstack/internal-test-infra": "0.0.0",
73
- "@btravstack/observability": "0.9.0",
74
- "@btravstack/core": "0.9.0"
74
+ "@btravstack/observability": "0.11.0"
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
79
  "unthrown": "^5.0.0",
80
- "@btravstack/config": "^0.9.0",
81
- "@btravstack/core": "^0.9.0",
82
- "@btravstack/di": "^0.9.0"
80
+ "@btravstack/config": "^0.11.0",
81
+ "@btravstack/core": "^0.11.0",
82
+ "@btravstack/di": "^0.11.0"
83
83
  },
84
84
  "peerDependenciesMeta": {
85
85
  "@aws-sdk/client-s3": {