@capturly/capture-sdk 2.11.2 → 2.11.4

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/CHANGELOG.md CHANGED
@@ -1,5 +1,46 @@
1
1
  # @capturly/capture-sdk
2
2
 
3
+ ## 2.11.4
4
+
5
+ ### Patch Changes
6
+
7
+ - [#486](https://github.com/Corey-Alan-Consulting/capturly.app/pull/486) [`52f5252`](https://github.com/Corey-Alan-Consulting/capturly.app/commit/52f5252a783bdc4c5725779ac5190ce3dd760ee9) Thanks [@NX211](https://github.com/NX211)! - Show the brand logo to respondents on iOS and in the capture SDK, and pin the
8
+ respondent-branding payload so the next field cannot reach one client only.
9
+
10
+ Brand logos shipped to the web respondent page and stopped there. The server was
11
+ already serving them — `/api/campaigns/respond/view` returns the same view the
12
+ /c page renders — but the mobile app and the SDK each re-declare the branding
13
+ shape by hand to parse an untrusted body defensively, and neither picked the
14
+ field up. On iOS that left the studio name rendering in exactly the slot the mark
15
+ is meant to replace; an SDK host got a brand-coloured surface with no mark at
16
+ all.
17
+
18
+ Both now read `logoPath`. The mobile respond screen renders it where the wordmark
19
+ was, with the studio name as its accessibility label — the same substitution the
20
+ web page makes, for the same reason: the mark says who is asking, and a reader
21
+ who cannot see it still needs to know.
22
+
23
+ Nothing could have caught this. The web page is type-checked against the
24
+ server's own view type, so adding a branding field turns every web surface into a
25
+ compile error — and leaves the two hand-written parsers compiling cleanly while
26
+ dropping it. `RESPONDENT_BRANDING_KEYS` in @capturly/studios-client is now the
27
+ agreed list of what that endpoint serves, and all three sides own a test against
28
+ it: the server proves it serves exactly those keys, and each client proves it
29
+ accounts for every one. Deliberately ignoring a key is still fine — `studioSlug`
30
+ is ignored by both clients — but a new key now fails three tests until each
31
+ surface has decided.
32
+
33
+ No desktop change: branding is edited on the web by design, and the desktop has
34
+ no respondent surface.
35
+
36
+ `@capturly/capture-sdk` takes a patch rather than the minor its new `logoPath`
37
+ would suggest: it shares the repo's `fixed` version group with the desktop and
38
+ mobile apps, so a minor there moves the versions the store pipelines submit
39
+ against. `@capturly/studios-client` is outside that group and takes the minor on
40
+ its own.
41
+
42
+ ## 2.11.3
43
+
3
44
  ## 2.11.2
4
45
 
5
46
  ## 2.11.1
@@ -101,6 +101,18 @@ function isRecord(value) {
101
101
  return value !== null && typeof value === "object" && !Array.isArray(value);
102
102
  }
103
103
  var stringOrNull = (v) => typeof v === "string" ? v : null;
104
+ var HANDLED_KEYS = {
105
+ brandAccentColor: true,
106
+ brandColor: true,
107
+ brandSecondaryColor: true,
108
+ coverPath: true,
109
+ logoPath: true,
110
+ studioName: true,
111
+ // Served and deliberately dropped: it addresses a Capturly studio page, which
112
+ // an embedding host has no reason to link to.
113
+ studioSlug: false
114
+ };
115
+ var BRANDING_KEYS_HANDLED = Object.keys(HANDLED_KEYS);
104
116
  async function fetchCaptureView(args) {
105
117
  const json = await postJson(
106
118
  args.baseUrl,
@@ -117,13 +129,15 @@ async function fetchCaptureView(args) {
117
129
  brandColor: stringOrNull(view.branding.brandColor),
118
130
  brandSecondaryColor: stringOrNull(view.branding.brandSecondaryColor),
119
131
  brandAccentColor: stringOrNull(view.branding.brandAccentColor),
120
- coverPath: stringOrNull(view.branding.coverPath)
132
+ coverPath: stringOrNull(view.branding.coverPath),
133
+ logoPath: stringOrNull(view.branding.logoPath)
121
134
  } : {
122
135
  studioName: "",
123
136
  brandColor: null,
124
137
  brandSecondaryColor: null,
125
138
  brandAccentColor: null,
126
- coverPath: null
139
+ coverPath: null,
140
+ logoPath: null
127
141
  };
128
142
  if (typeof view.maxDurationSec !== "number" || view.maxDurationSec <= 0) {
129
143
  throw new CaptureError("unknown", "Capturly returned no recording time limit.");
@@ -271,6 +285,7 @@ async function finalizeSubmission(args) {
271
285
  export {
272
286
  isSecureTransportUrl,
273
287
  CaptureError,
288
+ BRANDING_KEYS_HANDLED,
274
289
  fetchCaptureView,
275
290
  requestUpload,
276
291
  uploadBlob,
package/dist/index.js CHANGED
@@ -5,7 +5,7 @@ import {
5
5
  isSecureTransportUrl,
6
6
  requestUpload,
7
7
  uploadBlob
8
- } from "./chunk-CZPDQKMD.js";
8
+ } from "./chunk-U6XUGPHI.js";
9
9
 
10
10
  var MP4_MIME = "video/mp4;codecs=avc1.42E01E,mp4a.40.2";
11
11
  function pickMuxStrategy() {
@@ -1,6 +1,7 @@
1
1
  import { CaptureError, type CaptureAccess, type CaptureErrorCode, type CaptureRequestBranding, type CaptureRequestView } from './types.js';
2
2
  export { CaptureError };
3
3
  export type { CaptureAccess, CaptureErrorCode, CaptureRequestBranding, CaptureRequestView };
4
+ export declare const BRANDING_KEYS_HANDLED: readonly string[];
4
5
  /**
5
6
  * Fetch what the person is being asked — title, prompt, branding, release
6
7
  * text, limits, and any submission they already made. Same access, same
package/dist/transport.js CHANGED
@@ -1,11 +1,13 @@
1
1
  import {
2
+ BRANDING_KEYS_HANDLED,
2
3
  CaptureError,
3
4
  fetchCaptureView,
4
5
  finalizeSubmission,
5
6
  requestUpload,
6
7
  uploadBlob
7
- } from "./chunk-CZPDQKMD.js";
8
+ } from "./chunk-U6XUGPHI.js";
8
9
  export {
10
+ BRANDING_KEYS_HANDLED,
9
11
  CaptureError,
10
12
  fetchCaptureView,
11
13
  finalizeSubmission,
package/dist/types.d.ts CHANGED
@@ -31,6 +31,16 @@ export interface CaptureRequestBranding {
31
31
  brandAccentColor: string | null;
32
32
  /** Cover-art path under the Capturly origin, or null when unset. */
33
33
  coverPath: string | null;
34
+ /**
35
+ * Brand-mark path under the Capturly origin, already resolved through
36
+ * request → studio → organization, or null when no level has one.
37
+ *
38
+ * Render it in place of `studioName` and keep the name as the image's alt
39
+ * text: the mark says who is asking, and a reader with images blocked still
40
+ * needs to know. Served by an unauthenticated proxy, so a host page can load
41
+ * it without credentials.
42
+ */
43
+ logoPath: string | null;
34
44
  }
35
45
  /**
36
46
  * What the person is being asked, fetched with the same access the recording
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@capturly/capture-sdk",
3
- "version": "2.11.2",
3
+ "version": "2.11.4",
4
4
  "description": "Record full-quality audio and video on your user's own device, from your own product.",
5
5
  "keywords": [
6
6
  "recording",
@@ -55,9 +55,10 @@
55
55
  "esbuild": "^0.25.0",
56
56
  "typescript": "^5.4.0",
57
57
  "vitest": "^4.1.7",
58
- "@capturly/eslint-config": "2.11.2",
59
- "@capturly/recording-engine": "2.11.2",
60
- "@capturly/tsconfig": "2.11.2"
58
+ "@capturly/eslint-config": "2.11.4",
59
+ "@capturly/studios-client": "0.3.0",
60
+ "@capturly/tsconfig": "2.11.4",
61
+ "@capturly/recording-engine": "2.11.4"
61
62
  },
62
63
  "scripts": {
63
64
  "build": "pnpm clean && node build.mjs && tsc -p tsconfig.build.json --emitDeclarationOnly",