@btravstack/amqp-worker 0.7.0 → 0.9.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
@@ -50,37 +50,35 @@ import { ErrAsync, OkAsync, P } from "unthrown";
50
50
  // built by di from the use cases it lists — no injected context — on the
51
51
  // starter's own handlers port, typed by the contract (a consumer serves one
52
52
  // handlers record, so there is nothing to name).
53
- const orderHandlers = AmqpHandlers(orderContract)(
54
- { placeOrder: PlaceOrder },
55
- {
56
- sync: ({ placeOrder }) => ({
57
- orderNotifications: (message) =>
58
- placeOrder
59
- .execute(
60
- TenantId(message.payload.tenantId),
61
- message.payload.id,
62
- message.payload.payload?.quantity ?? 0,
63
- )
64
- .map(() => undefined)
65
- // A modeled domain error is permanent: dead-letter it, no retry.
66
- .mapErrCases((matcher) =>
67
- matcher.with(
68
- P.tag("InvalidQuantity"),
69
- P.tag("InvalidOrderId"),
70
- P.tag("DuplicateOrder"),
71
- (error) => new NonRetryableError(error._tag, error),
72
- ),
73
- )
74
- // Infrastructure failing is not: recover the defect into a retry.
75
- .recoverDefect((cause) =>
76
- ErrAsync(new RetryableError("placing the order failed", cause)),
53
+ const orderHandlers = AmqpHandlers(orderContract)({
54
+ inject: { placeOrder: PlaceOrder },
55
+ sync: ({ placeOrder }) => ({
56
+ orderNotifications: (message) =>
57
+ placeOrder
58
+ .execute(
59
+ TenantId(message.payload.tenantId),
60
+ message.payload.id,
61
+ message.payload.payload?.quantity ?? 0,
62
+ )
63
+ .map(() => undefined)
64
+ // A modeled domain error is permanent: dead-letter it, no retry.
65
+ .mapErrCases((matcher) =>
66
+ matcher.with(
67
+ P.tag("InvalidQuantity"),
68
+ P.tag("InvalidOrderId"),
69
+ P.tag("DuplicateOrder"),
70
+ (error) => new NonRetryableError(error._tag, error),
77
71
  ),
78
- // Every consumer the contract declares must be covered — an uncovered
79
- // key is refused at this call, not on the first delivery.
80
- orderAudit: () => OkAsync(undefined),
81
- }),
82
- },
83
- );
72
+ )
73
+ // Infrastructure failing is not: recover the defect into a retry.
74
+ .recoverDefect((cause) =>
75
+ ErrAsync(new RetryableError("placing the order failed", cause)),
76
+ ),
77
+ // Every consumer the contract declares must be covered — an uncovered
78
+ // key is refused at this call, not on the first delivery.
79
+ orderAudit: () => OkAsync(undefined),
80
+ }),
81
+ });
84
82
 
85
83
  const Worker = AmqpModule("Worker")({
86
84
  needs: [Env],
@@ -99,7 +97,7 @@ call, not on the first delivery. `runtimeInfo()` reads `{ queues }` back once
99
97
  consuming.
100
98
 
101
99
  A worker with several consumers can be several slices instead of one record:
102
- `AmqpHandler(contract, key)({ name: Dep }, arm)` mints a provider for ONE consumer or
100
+ `AmqpHandler(contract, key)({ inject: { name: Dep }, ...arm })` mints a provider for ONE consumer or
103
101
  rpc, typed by the key alone, and `AmqpHandlers(contract)([...])` composes an
104
102
  array of them into the same handlers provider `AmqpModule` takes — the array
105
103
  must cover every key the contract declares, and each piece's own port must
package/dist/index.cjs CHANGED
@@ -116,26 +116,29 @@ const amqp = (options) => {
116
116
  return (0, _btravstack_di.Module)("Amqp")({
117
117
  needs: [_btravstack_config.Env, AmqpHandlersPort],
118
118
  provides: [config, (0, _btravstack_di.Provider)(AmqpRuntime)({
119
- config: AmqpConfig,
120
- handlers: AmqpHandlersPort
121
- }, { sync: ({ config: bound, handlers }) => ({
122
- name: "amqp",
123
- resolves: [],
124
- start: (host) => createWorker(host, bound, options, handlers)
125
- }) })],
119
+ inject: {
120
+ config: AmqpConfig,
121
+ handlers: AmqpHandlersPort
122
+ },
123
+ sync: ({ config: bound, handlers }) => ({
124
+ name: "amqp",
125
+ resolves: [],
126
+ start: (host) => createWorker(host, bound, options, handlers)
127
+ })
128
+ })],
126
129
  exports: [AmqpRuntime, AmqpConfig]
127
130
  });
128
131
  };
129
132
  /**
130
- * The handlers as a provider, from the contract. Three call forms, one port.
133
+ * The handlers as a provider, from the contract. Two call forms, one port.
131
134
  *
132
135
  * ```ts
133
- * AmqpHandlers(orderContract)({ logger: Logger }, { sync: ({ logger }) => ({ orderNotifications: (m) => … }) })
136
+ * AmqpHandlers(orderContract)({ inject: { logger: Logger }, sync: ({ logger }) => ({ orderNotifications: (m) => … }) })
134
137
  * AmqpHandlers(orderContract)([orderNotifications, orderAudit])
135
138
  * ```
136
139
  *
137
- * The first two are di's own `Provider(port)` on the starter's handlers port
138
- * typed for the contract. The third takes the pieces `AmqpHandler(contract,
140
+ * The first is di's own `Provider(port)` on the starter's handlers port
141
+ * typed for the contract. The second takes the pieces `AmqpHandler(contract,
139
142
  * key)` builds: they are the provider's deps, keyed by the contract key each
140
143
  * piece's port id carries, so the services record IS the handlers record. Every
141
144
  * declared key must be covered, and two slices claiming one key are di's
@@ -143,8 +146,11 @@ const amqp = (options) => {
143
146
  */
144
147
  const AmqpHandlers = (contract) => {
145
148
  const build = (0, _btravstack_di.Provider)(AmqpHandlersPort);
146
- const compose = (pieces) => build(Object.fromEntries(pieces.map((piece) => [piece.port.portId.slice(12), piece.port])), { sync: (services) => services });
147
- return ((first, second) => second === void 0 && Array.isArray(first) ? compose(first) : build(first, second));
149
+ const compose = (pieces) => build({
150
+ inject: Object.fromEntries(pieces.map((piece) => [piece.port.portId.slice(12), piece.port])),
151
+ sync: (services) => services
152
+ });
153
+ return ((first) => Array.isArray(first) ? compose(first) : build(first));
148
154
  };
149
155
  const startFailed = (cause) => new _btravstack_core.RuntimeStartFailed({
150
156
  runtime: "amqp",
package/dist/index.d.cts CHANGED
@@ -123,15 +123,15 @@ type Compose<C extends AnyAmqpContract> = <const T extends readonly PieceOf<C>[]
123
123
  readonly port: HandlersPortOf<C>;
124
124
  };
125
125
  /**
126
- * The handlers as a provider, from the contract. Three call forms, one port.
126
+ * The handlers as a provider, from the contract. Two call forms, one port.
127
127
  *
128
128
  * ```ts
129
- * AmqpHandlers(orderContract)({ logger: Logger }, { sync: ({ logger }) => ({ orderNotifications: (m) => … }) })
129
+ * AmqpHandlers(orderContract)({ inject: { logger: Logger }, sync: ({ logger }) => ({ orderNotifications: (m) => … }) })
130
130
  * AmqpHandlers(orderContract)([orderNotifications, orderAudit])
131
131
  * ```
132
132
  *
133
- * The first two are di's own `Provider(port)` on the starter's handlers port
134
- * typed for the contract. The third takes the pieces `AmqpHandler(contract,
133
+ * The first is di's own `Provider(port)` on the starter's handlers port
134
+ * typed for the contract. The second takes the pieces `AmqpHandler(contract,
135
135
  * key)` builds: they are the provider's deps, keyed by the contract key each
136
136
  * piece's port id carries, so the services record IS the handlers record. Every
137
137
  * declared key must be covered, and two slices claiming one key are di's
package/dist/index.d.mts CHANGED
@@ -123,15 +123,15 @@ type Compose<C extends AnyAmqpContract> = <const T extends readonly PieceOf<C>[]
123
123
  readonly port: HandlersPortOf<C>;
124
124
  };
125
125
  /**
126
- * The handlers as a provider, from the contract. Three call forms, one port.
126
+ * The handlers as a provider, from the contract. Two call forms, one port.
127
127
  *
128
128
  * ```ts
129
- * AmqpHandlers(orderContract)({ logger: Logger }, { sync: ({ logger }) => ({ orderNotifications: (m) => … }) })
129
+ * AmqpHandlers(orderContract)({ inject: { logger: Logger }, sync: ({ logger }) => ({ orderNotifications: (m) => … }) })
130
130
  * AmqpHandlers(orderContract)([orderNotifications, orderAudit])
131
131
  * ```
132
132
  *
133
- * The first two are di's own `Provider(port)` on the starter's handlers port
134
- * typed for the contract. The third takes the pieces `AmqpHandler(contract,
133
+ * The first is di's own `Provider(port)` on the starter's handlers port
134
+ * typed for the contract. The second takes the pieces `AmqpHandler(contract,
135
135
  * key)` builds: they are the provider's deps, keyed by the contract key each
136
136
  * piece's port id carries, so the services record IS the handlers record. Every
137
137
  * declared key must be covered, and two slices claiming one key are di's
package/dist/index.mjs CHANGED
@@ -115,26 +115,29 @@ const amqp = (options) => {
115
115
  return Module("Amqp")({
116
116
  needs: [Env, AmqpHandlersPort],
117
117
  provides: [config, Provider(AmqpRuntime)({
118
- config: AmqpConfig,
119
- handlers: AmqpHandlersPort
120
- }, { sync: ({ config: bound, handlers }) => ({
121
- name: "amqp",
122
- resolves: [],
123
- start: (host) => createWorker(host, bound, options, handlers)
124
- }) })],
118
+ inject: {
119
+ config: AmqpConfig,
120
+ handlers: AmqpHandlersPort
121
+ },
122
+ sync: ({ config: bound, handlers }) => ({
123
+ name: "amqp",
124
+ resolves: [],
125
+ start: (host) => createWorker(host, bound, options, handlers)
126
+ })
127
+ })],
125
128
  exports: [AmqpRuntime, AmqpConfig]
126
129
  });
127
130
  };
128
131
  /**
129
- * The handlers as a provider, from the contract. Three call forms, one port.
132
+ * The handlers as a provider, from the contract. Two call forms, one port.
130
133
  *
131
134
  * ```ts
132
- * AmqpHandlers(orderContract)({ logger: Logger }, { sync: ({ logger }) => ({ orderNotifications: (m) => … }) })
135
+ * AmqpHandlers(orderContract)({ inject: { logger: Logger }, sync: ({ logger }) => ({ orderNotifications: (m) => … }) })
133
136
  * AmqpHandlers(orderContract)([orderNotifications, orderAudit])
134
137
  * ```
135
138
  *
136
- * The first two are di's own `Provider(port)` on the starter's handlers port
137
- * typed for the contract. The third takes the pieces `AmqpHandler(contract,
139
+ * The first is di's own `Provider(port)` on the starter's handlers port
140
+ * typed for the contract. The second takes the pieces `AmqpHandler(contract,
138
141
  * key)` builds: they are the provider's deps, keyed by the contract key each
139
142
  * piece's port id carries, so the services record IS the handlers record. Every
140
143
  * declared key must be covered, and two slices claiming one key are di's
@@ -142,8 +145,11 @@ const amqp = (options) => {
142
145
  */
143
146
  const AmqpHandlers = (contract) => {
144
147
  const build = Provider(AmqpHandlersPort);
145
- const compose = (pieces) => build(Object.fromEntries(pieces.map((piece) => [piece.port.portId.slice(12), piece.port])), { sync: (services) => services });
146
- return ((first, second) => second === void 0 && Array.isArray(first) ? compose(first) : build(first, second));
148
+ const compose = (pieces) => build({
149
+ inject: Object.fromEntries(pieces.map((piece) => [piece.port.portId.slice(12), piece.port])),
150
+ sync: (services) => services
151
+ });
152
+ return ((first) => Array.isArray(first) ? compose(first) : build(first));
147
153
  };
148
154
  const startFailed = (cause) => new RuntimeStartFailed({
149
155
  runtime: "amqp",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@btravstack/amqp-worker",
3
- "version": "0.7.0",
3
+ "version": "0.9.0",
4
4
  "description": "The AMQP starter for @btravstack/core: the handlers as a port, one unit per delivery, and a drain the kernel's deadline releases",
5
5
  "keywords": [
6
6
  "amqp",
@@ -49,27 +49,27 @@
49
49
  "@amqp-contract/worker": "3.0.0-beta.6",
50
50
  "@btravstack/tsconfig": "0.2.0",
51
51
  "@opentelemetry/api": "1.9.1",
52
- "@types/node": "26.2.0",
52
+ "@types/node": "26.4.0",
53
53
  "@unthrown/vitest": "5.7.0",
54
54
  "@vitest/coverage-v8": "4.1.11",
55
55
  "tsdown": "0.22.14",
56
56
  "typescript": "7.0.2",
57
57
  "unthrown": "5.7.0",
58
58
  "vitest": "4.1.11",
59
- "zod": "4.4.3",
60
- "@btravstack/config": "0.7.0",
61
- "@btravstack/core": "0.7.0",
62
- "@btravstack/di": "0.7.0",
59
+ "zod": "4.5.1",
60
+ "@btravstack/config": "0.9.0",
61
+ "@btravstack/core": "0.9.0",
62
+ "@btravstack/di": "0.9.0",
63
63
  "@btravstack/internal-test-infra": "0.0.0",
64
- "@btravstack/testing": "0.7.0"
64
+ "@btravstack/testing": "0.9.0"
65
65
  },
66
66
  "peerDependencies": {
67
67
  "@amqp-contract/worker": "^3.0.0-beta.6",
68
68
  "@opentelemetry/api": "^1",
69
69
  "unthrown": "^5.0.0",
70
- "@btravstack/config": "^0.7.0",
71
- "@btravstack/core": "^0.7.0",
72
- "@btravstack/di": "^0.7.0"
70
+ "@btravstack/config": "^0.9.0",
71
+ "@btravstack/core": "^0.9.0",
72
+ "@btravstack/di": "^0.9.0"
73
73
  },
74
74
  "engines": {
75
75
  "node": ">=22"