@camstack/server 1.2.357 → 1.2.359

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.
@@ -17,19 +17,25 @@
17
17
  * The three rules this module implements, and nothing else:
18
18
  *
19
19
  * 1. **Fan out, per device.** An ARRAY-returning method is called on every
20
- * source the DEVICE has (`CapabilityRegistry.resolveCollectionForDevice` —
21
- * the enabled providers, minus the ones the operator switched off for this
22
- * camera through `deviceManager.setWrapperActive`, D556), and the results
23
- * are concatenated. No dedup ACROSS SOURCES, no best-source pick: a clip
24
- * held in two storages appears twice, once per source, and each row says
25
- * which (D549 decision 11 — stated there as a consequence precisely so it
26
- * is not "fixed" later). But a source is not a REGISTRATION: one addon
27
- * reaches this dispatcher as the device's native provider, as the
28
- * hub-local registration and once per agent node, and those are one
29
- * source answering three times. Each row is held once, keyed by the
30
- * identity its provider minted ({@link holdEachRowOnce}); on 592 that was
31
- * three `analytics` tick-boxes for one thing, D62's defect with the
20
+ * source the DEVICE has — its BINDINGS ({@link sourcesForDevice}), not the
21
+ * registrations — and the results are concatenated. No dedup ACROSS
22
+ * SOURCES, no best-source pick: a clip held in two storages appears twice,
23
+ * once per source, and each row says which (D549 decision 11 — stated
24
+ * there as a consequence precisely so it is not "fixed" later). A source
25
+ * is not a REGISTRATION: one addon reaches this dispatcher as the device's
26
+ * native provider, as the hub-local registration and once per agent node.
27
+ * Those three are collapsed by the binding set itself, which cannot hold
28
+ * one addon twice — never by a de-duplicator over the answer. On 592 they
29
+ * were three `analytics` tick-boxes for one thing, D62's defect with the
32
30
  * polarity reversed (D554 amended 2026-09-20).
31
+ *
32
+ * **A caller may also pin ONE source, and for `videoclips.listClips` the
33
+ * pin is REQUIRED** — in the cap's input schema, not here (D554 amended). This
34
+ * dispatcher has no notion of a DEFAULT provider and never had one: a
35
+ * collection cap's binding set is derived and plural, so an absent pin
36
+ * left the fan-out un-narrowed and bought a union. The cap's docblock
37
+ * said otherwise for a day, and device 592 answered a `limit: 3` call
38
+ * with six rows because of it.
33
39
  * 2. **One failing source never empties the others.** Every source is called
34
40
  * independently and a rejection removes only its own rows — and says so,
35
41
  * per source, with `tags: { deviceId }`. A fan-out where one throwing
@@ -74,8 +80,12 @@ const SOURCE_ADDON_FIELD = 'addonId';
74
80
  /**
75
81
  * The input field naming WHICH of a device's providers to ask. One at a time,
76
82
  * by `addonId`, never a list of source ids: the operator settled the surface
77
- * on 2026-09-20 (*"l'utilizzatore è uno solo"*). Absent means the device's
78
- * bound provider.
83
+ * on 2026-09-20 (*"l'utilizzatore è uno solo"*).
84
+ *
85
+ * An absent pin narrows NOTHING — the method fans out, which is right for
86
+ * `listSources` and was never right for `listClips`. Whether absence is
87
+ * allowed is the CAP's to say, in its input schema, and `videoclips.listClips`
88
+ * says no (D554 amended).
79
89
  */
80
90
  const PROVIDER_PIN_FIELD = 'provider';
81
91
  /** The capability whose singleton answers what a device is bound to. */
@@ -331,9 +341,9 @@ async function fanOut(sources, method, input, capName, deviceId, logger) {
331
341
  * mark the listing row that let him switch it back on. That whole half went on
332
342
  * 2026-09-20: every provider always works, and a source exists for a camera
333
343
  * because a binding put it there — so "off" is an unbound provider, not a
334
- * second store beside the binding (D556/D557 amended). Nothing here filters
335
- * any more; the filtering happened when {@link sourcesForDevice} read the
336
- * bindings.
344
+ * second store beside the binding (D554 amended, D557 amended). Nothing here
345
+ * filters any more; the filtering happened when {@link sourcesForDevice} read
346
+ * the bindings.
337
347
  */
338
348
  function finishRows(source, rows, isSourceListing) {
339
349
  if (!isSourceListing)
@@ -10769,6 +10769,22 @@ function createCapRouter_videoclips(getProvider, createRemoteProxy) {
10769
10769
  // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument
10770
10770
  return p.getClipPlayback(methodInput);
10771
10771
  }),
10772
+ readClipBytes: trpc_middleware_js_1.protectedProcedure
10773
+ .input(types_126.videoclipsCapability.methods.readClipBytes.input.loose())
10774
+ .output(types_126.videoclipsCapability.methods.readClipBytes.output)
10775
+ .query(async ({ input, ctx }) => {
10776
+ const { nodeId, ...methodInput } = input;
10777
+ const p = resolveProvider('videoclips', nodeId, () => getProvider(ctx), createRemoteProxy);
10778
+ const fn = p.readClipBytes;
10779
+ if (typeof fn !== 'function') {
10780
+ throw new server_1.TRPCError({
10781
+ code: 'NOT_IMPLEMENTED',
10782
+ message: 'Capability "videoclips" provider does not implement "readClipBytes"',
10783
+ });
10784
+ }
10785
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument
10786
+ return fn.call(p, methodInput);
10787
+ }),
10772
10788
  });
10773
10789
  }
10774
10790
  function createCapRouter_viewerUi(getProvider, createRemoteProxy) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@camstack/server",
3
- "version": "1.2.357",
3
+ "version": "1.2.359",
4
4
  "private": false,
5
5
  "files": [
6
6
  "dist",
@@ -35,18 +35,18 @@
35
35
  ]
36
36
  },
37
37
  "dependencies": {
38
- "@camstack/addon-admin-ui": "1.2.246",
39
- "@camstack/addon-agent-ui": "1.2.134",
38
+ "@camstack/addon-admin-ui": "1.2.248",
39
+ "@camstack/addon-agent-ui": "1.2.136",
40
40
  "@camstack/addon-auth": "1.2.123",
41
41
  "@camstack/addon-decoder-nodeav": "1.2.115",
42
42
  "@camstack/addon-notifiers": "1.2.119",
43
- "@camstack/addon-pipeline": "1.2.274",
44
- "@camstack/addon-pipeline-orchestrator": "1.2.232",
43
+ "@camstack/addon-pipeline": "1.2.275",
44
+ "@camstack/addon-pipeline-orchestrator": "1.2.234",
45
45
  "@camstack/addon-post-analysis": "1.2.273",
46
46
  "@camstack/sdk": "1.2.118",
47
- "@camstack/system": "1.2.278",
48
- "@camstack/types": "1.2.236",
49
- "@camstack/ui-library": "1.2.192",
47
+ "@camstack/system": "1.2.280",
48
+ "@camstack/types": "1.2.238",
49
+ "@camstack/ui-library": "1.2.194",
50
50
  "@fastify/compress": "^9.0.0",
51
51
  "@fastify/cookie": "^11.0.2",
52
52
  "@fastify/cors": "^11.2.0",