@capturly/capture-sdk 2.11.3 → 2.12.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/CHANGELOG.md +65 -0
- package/dist/{chunk-CZPDQKMD.js → chunk-EH7DDMYO.js} +24 -2
- package/dist/index.js +1 -1
- package/dist/transport.d.ts +1 -0
- package/dist/transport.js +3 -1
- package/dist/types.d.ts +22 -0
- package/package.json +5 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,70 @@
|
|
|
1
1
|
# @capturly/capture-sdk
|
|
2
2
|
|
|
3
|
+
## 2.12.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#488](https://github.com/Corey-Alan-Consulting/capturly.app/pull/488) [`b4963e6`](https://github.com/Corey-Alan-Consulting/capturly.app/commit/b4963e699dd48f7d95057043dff86e0c036e510f) Thanks [@NX211](https://github.com/NX211)! - Stop pairing a studio's cover art with a capture request's own brand mark, and
|
|
8
|
+
move the two campaign notification toggles into Settings where they belong.
|
|
9
|
+
|
|
10
|
+
A capture request can set its own logo and colours; cover art has no per-request
|
|
11
|
+
override and is always the studio's. So a request branded for someone else — an
|
|
12
|
+
agency collecting for one client out of a shared studio — opened its page and
|
|
13
|
+
its invite under the studio's banner with the client's logo underneath: two
|
|
14
|
+
brands, only one of which is asking. When the mark belongs to the request, the
|
|
15
|
+
studio cover is no longer shown on either surface, and the mark leads.
|
|
16
|
+
|
|
17
|
+
Deciding that needs to know which level the mark came from, so `logoScope`
|
|
18
|
+
joins the respondent branding contract. Adding it was a compile error in the
|
|
19
|
+
mobile app, the capture SDK and the email decision table, which is what that
|
|
20
|
+
contract is for — each now records what it does with the key. The SDK surfaces
|
|
21
|
+
it on `CaptureRequestBranding` so an embedding host can make the same call about
|
|
22
|
+
its own layout; the mobile app declares it unused, having no cover art to pair.
|
|
23
|
+
|
|
24
|
+
Auto-reminders and new-video email were buttons in the header bar, which made two
|
|
25
|
+
pieces of persistent state look like two actions. They already PATCHed the same
|
|
26
|
+
endpoint the settings form uses, so they are now checkboxes in Settings and save
|
|
27
|
+
with everything else.
|
|
28
|
+
|
|
29
|
+
## 2.11.4
|
|
30
|
+
|
|
31
|
+
### Patch Changes
|
|
32
|
+
|
|
33
|
+
- [#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
|
|
34
|
+
respondent-branding payload so the next field cannot reach one client only.
|
|
35
|
+
|
|
36
|
+
Brand logos shipped to the web respondent page and stopped there. The server was
|
|
37
|
+
already serving them — `/api/campaigns/respond/view` returns the same view the
|
|
38
|
+
/c page renders — but the mobile app and the SDK each re-declare the branding
|
|
39
|
+
shape by hand to parse an untrusted body defensively, and neither picked the
|
|
40
|
+
field up. On iOS that left the studio name rendering in exactly the slot the mark
|
|
41
|
+
is meant to replace; an SDK host got a brand-coloured surface with no mark at
|
|
42
|
+
all.
|
|
43
|
+
|
|
44
|
+
Both now read `logoPath`. The mobile respond screen renders it where the wordmark
|
|
45
|
+
was, with the studio name as its accessibility label — the same substitution the
|
|
46
|
+
web page makes, for the same reason: the mark says who is asking, and a reader
|
|
47
|
+
who cannot see it still needs to know.
|
|
48
|
+
|
|
49
|
+
Nothing could have caught this. The web page is type-checked against the
|
|
50
|
+
server's own view type, so adding a branding field turns every web surface into a
|
|
51
|
+
compile error — and leaves the two hand-written parsers compiling cleanly while
|
|
52
|
+
dropping it. `RESPONDENT_BRANDING_KEYS` in @capturly/studios-client is now the
|
|
53
|
+
agreed list of what that endpoint serves, and all three sides own a test against
|
|
54
|
+
it: the server proves it serves exactly those keys, and each client proves it
|
|
55
|
+
accounts for every one. Deliberately ignoring a key is still fine — `studioSlug`
|
|
56
|
+
is ignored by both clients — but a new key now fails three tests until each
|
|
57
|
+
surface has decided.
|
|
58
|
+
|
|
59
|
+
No desktop change: branding is edited on the web by design, and the desktop has
|
|
60
|
+
no respondent surface.
|
|
61
|
+
|
|
62
|
+
`@capturly/capture-sdk` takes a patch rather than the minor its new `logoPath`
|
|
63
|
+
would suggest: it shares the repo's `fixed` version group with the desktop and
|
|
64
|
+
mobile apps, so a minor there moves the versions the store pipelines submit
|
|
65
|
+
against. `@capturly/studios-client` is outside that group and takes the minor on
|
|
66
|
+
its own.
|
|
67
|
+
|
|
3
68
|
## 2.11.3
|
|
4
69
|
|
|
5
70
|
## 2.11.2
|
|
@@ -101,6 +101,23 @@ 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 LOGO_SCOPES = { org: true, studio: true, campaign: true };
|
|
105
|
+
function brandLogoScopeOrNull(v) {
|
|
106
|
+
return typeof v === "string" && v in LOGO_SCOPES ? v : null;
|
|
107
|
+
}
|
|
108
|
+
var HANDLED_KEYS = {
|
|
109
|
+
brandAccentColor: true,
|
|
110
|
+
brandColor: true,
|
|
111
|
+
brandSecondaryColor: true,
|
|
112
|
+
coverPath: true,
|
|
113
|
+
logoPath: true,
|
|
114
|
+
logoScope: true,
|
|
115
|
+
studioName: true,
|
|
116
|
+
// Served and deliberately dropped: it addresses a Capturly studio page, which
|
|
117
|
+
// an embedding host has no reason to link to.
|
|
118
|
+
studioSlug: false
|
|
119
|
+
};
|
|
120
|
+
var BRANDING_KEYS_HANDLED = Object.keys(HANDLED_KEYS);
|
|
104
121
|
async function fetchCaptureView(args) {
|
|
105
122
|
const json = await postJson(
|
|
106
123
|
args.baseUrl,
|
|
@@ -117,13 +134,17 @@ async function fetchCaptureView(args) {
|
|
|
117
134
|
brandColor: stringOrNull(view.branding.brandColor),
|
|
118
135
|
brandSecondaryColor: stringOrNull(view.branding.brandSecondaryColor),
|
|
119
136
|
brandAccentColor: stringOrNull(view.branding.brandAccentColor),
|
|
120
|
-
coverPath: stringOrNull(view.branding.coverPath)
|
|
137
|
+
coverPath: stringOrNull(view.branding.coverPath),
|
|
138
|
+
logoPath: stringOrNull(view.branding.logoPath),
|
|
139
|
+
logoScope: brandLogoScopeOrNull(view.branding.logoScope)
|
|
121
140
|
} : {
|
|
122
141
|
studioName: "",
|
|
123
142
|
brandColor: null,
|
|
124
143
|
brandSecondaryColor: null,
|
|
125
144
|
brandAccentColor: null,
|
|
126
|
-
coverPath: null
|
|
145
|
+
coverPath: null,
|
|
146
|
+
logoPath: null,
|
|
147
|
+
logoScope: null
|
|
127
148
|
};
|
|
128
149
|
if (typeof view.maxDurationSec !== "number" || view.maxDurationSec <= 0) {
|
|
129
150
|
throw new CaptureError("unknown", "Capturly returned no recording time limit.");
|
|
@@ -271,6 +292,7 @@ async function finalizeSubmission(args) {
|
|
|
271
292
|
export {
|
|
272
293
|
isSecureTransportUrl,
|
|
273
294
|
CaptureError,
|
|
295
|
+
BRANDING_KEYS_HANDLED,
|
|
274
296
|
fetchCaptureView,
|
|
275
297
|
requestUpload,
|
|
276
298
|
uploadBlob,
|
package/dist/index.js
CHANGED
package/dist/transport.d.ts
CHANGED
|
@@ -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-
|
|
8
|
+
} from "./chunk-EH7DDMYO.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,28 @@ 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;
|
|
44
|
+
/**
|
|
45
|
+
* Which level the mark came from: `'org'`, `'studio'`, or `'campaign'`, or
|
|
46
|
+
* null when there is none.
|
|
47
|
+
*
|
|
48
|
+
* `'campaign'` means this request set its own mark, which may belong to a
|
|
49
|
+
* different brand than the studio hosting it — an agency collecting for one
|
|
50
|
+
* client out of a shared studio. `coverPath` has no such override; it is
|
|
51
|
+
* always the studio's, so Capturly serves `coverPath: null` alongside a
|
|
52
|
+
* campaign-scoped mark rather than hand every host two unrelated brands.
|
|
53
|
+
* Layout information only — there is no rule for a host to re-apply.
|
|
54
|
+
*/
|
|
55
|
+
logoScope: 'org' | 'studio' | 'campaign' | null;
|
|
34
56
|
}
|
|
35
57
|
/**
|
|
36
58
|
* 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.
|
|
3
|
+
"version": "2.12.0",
|
|
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.
|
|
59
|
-
"@capturly/
|
|
60
|
-
"@capturly/
|
|
58
|
+
"@capturly/eslint-config": "2.12.0",
|
|
59
|
+
"@capturly/recording-engine": "2.12.0",
|
|
60
|
+
"@capturly/studios-client": "0.4.0",
|
|
61
|
+
"@capturly/tsconfig": "2.12.0"
|
|
61
62
|
},
|
|
62
63
|
"scripts": {
|
|
63
64
|
"build": "pnpm clean && node build.mjs && tsc -p tsconfig.build.json --emitDeclarationOnly",
|