@camstack/server 1.2.84 → 1.2.85
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.
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
23
|
exports.COLLECTION_ARRAY_METHODS = void 0;
|
|
24
24
|
exports.aggregateCollectionCall = aggregateCollectionCall;
|
|
25
|
+
exports.addonPinOf = addonPinOf;
|
|
25
26
|
exports.pinnedCollectionCall = pinnedCollectionCall;
|
|
26
27
|
exports.createCapRouterPrimitives = createCapRouterPrimitives;
|
|
27
28
|
exports.createCapRouterServices = createCapRouterServices;
|
|
@@ -120,6 +121,35 @@ async function aggregateCollectionCall(reg, capName, method, args) {
|
|
|
120
121
|
const out = await fn(args);
|
|
121
122
|
return Array.isArray(out) ? out : null;
|
|
122
123
|
}
|
|
124
|
+
/**
|
|
125
|
+
* The `{ addonId }` a call PINS to, or `null` when the call is not an
|
|
126
|
+
* addon-pinned collection call and must route normally.
|
|
127
|
+
*
|
|
128
|
+
* ONE definition, because there are two places that must agree about it and
|
|
129
|
+
* they are in different packages. `LocalChildRegistry` decides whether to
|
|
130
|
+
* short-circuit a child's egress to a local sibling — and that decision happens
|
|
131
|
+
* BEFORE `onUnownedCall` runs, so a pin honoured only there is honoured never.
|
|
132
|
+
* That is precisely how the first attempt at this fix failed on the live hub:
|
|
133
|
+
* the handler was correct and unreachable, and the probe that proved it was a
|
|
134
|
+
* DELIBERATELY BOGUS addonId — refused if the selector routes, answered `null`
|
|
135
|
+
* if it is discarded. It came back `null`.
|
|
136
|
+
*
|
|
137
|
+
* Not an array method (that contract is the union) and not a non-collection cap
|
|
138
|
+
* (there `addonId` is provider DATA: `addons.getLogs({addonId})` names the addon
|
|
139
|
+
* whose logs you want, it does not name a provider).
|
|
140
|
+
*/
|
|
141
|
+
function addonPinOf(reg, capName, method, args) {
|
|
142
|
+
if (!reg)
|
|
143
|
+
return null;
|
|
144
|
+
if (reg.getDefinition(capName)?.mode !== 'collection')
|
|
145
|
+
return null;
|
|
146
|
+
if (exports.COLLECTION_ARRAY_METHODS.get(capName)?.includes(method) === true)
|
|
147
|
+
return null;
|
|
148
|
+
if (args === null || typeof args !== 'object' || Array.isArray(args))
|
|
149
|
+
return null;
|
|
150
|
+
const addonId = args['addonId'];
|
|
151
|
+
return typeof addonId === 'string' && addonId.length > 0 ? addonId : null;
|
|
152
|
+
}
|
|
123
153
|
/**
|
|
124
154
|
* The `{ addonId }` PIN for a cap call arriving OUTSIDE the tRPC router — a
|
|
125
155
|
* forked addon's `ctx.api.<cap>.<method>` reaching the parent's
|
|
@@ -160,20 +190,12 @@ async function aggregateCollectionCall(reg, capName, method, args) {
|
|
|
160
190
|
* `null` legitimately, so a bare `null` could not be told from "not handled".
|
|
161
191
|
*/
|
|
162
192
|
async function pinnedCollectionCall(reg, capName, method, args) {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
if (reg.getDefinition(capName)?.mode !== 'collection')
|
|
166
|
-
return null;
|
|
167
|
-
if (exports.COLLECTION_ARRAY_METHODS.get(capName)?.includes(method) === true)
|
|
168
|
-
return null;
|
|
169
|
-
if (args === null || typeof args !== 'object' || Array.isArray(args))
|
|
170
|
-
return null;
|
|
171
|
-
const addonId = args['addonId'];
|
|
172
|
-
if (typeof addonId !== 'string' || addonId.length === 0)
|
|
193
|
+
const addonId = addonPinOf(reg, capName, method, args);
|
|
194
|
+
if (addonId === null)
|
|
173
195
|
return null;
|
|
174
|
-
const provider = reg
|
|
196
|
+
const provider = reg?.getProviderByAddonId(capName, addonId) ?? null;
|
|
175
197
|
if (provider === null) {
|
|
176
|
-
const valid = reg
|
|
198
|
+
const valid = reg?.getProviderAddonIds(capName) ?? [];
|
|
177
199
|
throw new Error(`Capability "${capName}" has no provider with addonId "${addonId}". ` +
|
|
178
200
|
`Registered: ${valid.length > 0 ? valid.join(', ') : '(none)'}`);
|
|
179
201
|
}
|
|
@@ -349,6 +349,14 @@ class MoleculerService {
|
|
|
349
349
|
return false;
|
|
350
350
|
return cap_router_runtime_js_1.COLLECTION_ARRAY_METHODS.get(capName)?.includes(method) === true;
|
|
351
351
|
},
|
|
352
|
+
// Same story for an explicit `{ addonId }` selector: the sibling
|
|
353
|
+
// short-circuit picks the FIRST-registered child, which is precisely
|
|
354
|
+
// what the selector exists to override. `onUnownedCall` then resolves
|
|
355
|
+
// the named provider via `callPinnedCollection`. Shares `addonPinOf`
|
|
356
|
+
// with it — the bypass and the routing must never disagree about what
|
|
357
|
+
// counts as a pin, or the call is bounced out of the sibling path and
|
|
358
|
+
// then routed by first-provider anyway.
|
|
359
|
+
isAddonPinnedCall: (capName, method, args) => (0, cap_router_runtime_js_1.addonPinOf)(this.capabilityService.getRegistry(), capName, method, args) !== null,
|
|
352
360
|
// Bound every UDS cap call by the cap's own declared timeout, falling
|
|
353
361
|
// back to the channel default. Same resolver the REMOTE plane uses
|
|
354
362
|
// below, so a method that survives 16 minutes across nodes survives it
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@camstack/server",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.85",
|
|
4
4
|
"private": false,
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"@camstack/addon-post-analysis": "1.2.56",
|
|
44
44
|
"@camstack/sdk": "1.2.11",
|
|
45
45
|
"@camstack/shm-ring": "1.1.9",
|
|
46
|
-
"@camstack/system": "1.2.
|
|
46
|
+
"@camstack/system": "1.2.72",
|
|
47
47
|
"@camstack/types": "1.2.55",
|
|
48
48
|
"@camstack/ui-library": "1.2.38",
|
|
49
49
|
"@fastify/compress": "^9.0.0",
|