@intenque/network-sdk 0.0.0-stage → 2.2.0-beta.2
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 +145 -0
- package/README.md +254 -2
- package/dist/capture/index.cjs +1 -0
- package/dist/capture/index.d.cts +57 -0
- package/dist/capture/index.d.ts +57 -0
- package/dist/capture/index.js +1 -0
- package/dist/cli/index.js +1745 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/constants-C_6Zxu_k.d.cts +20 -0
- package/dist/constants-C_6Zxu_k.d.ts +20 -0
- package/dist/react/index.cjs +3 -0
- package/dist/react/index.cjs.map +1 -0
- package/dist/react/index.d.cts +421 -0
- package/dist/react/index.d.ts +421 -0
- package/dist/react/index.js +3 -0
- package/dist/react/index.js.map +1 -0
- package/dist/server/index.cjs +2 -0
- package/dist/server/index.cjs.map +1 -0
- package/dist/server/index.d.cts +350 -0
- package/dist/server/index.d.ts +350 -0
- package/dist/server/index.js +2 -0
- package/dist/server/index.js.map +1 -0
- package/dist/styles.css +141 -0
- package/package.json +111 -4
|
@@ -0,0 +1,421 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { S as SiteChannel } from '../constants-C_6Zxu_k.cjs';
|
|
4
|
+
export { D as DEFAULT_CDN_BASE, M as MANIFEST_SCHEMA_MAJOR, a as SDK_VERSION } from '../constants-C_6Zxu_k.cjs';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Trusted root public keys — spec §4.5 (`rootPublicKeys`, "an array to allow overlap").
|
|
8
|
+
*
|
|
9
|
+
* The root private key is generated offline by the owner (`npm run keys -- root:new`) and never reaches the hub; the
|
|
10
|
+
* public JWK printed by that command is what goes here. The hub holds the same list in `MANIFEST_ROOT_PUBLIC_KEYS`
|
|
11
|
+
* and refuses to certify or sign with a key the SDK would reject.
|
|
12
|
+
*
|
|
13
|
+
* HOW PRODUCTION ROOTS ARE ADDED (release step, see docs/install-guide.md "Adding a production root"):
|
|
14
|
+
* 1. `npm run keys -- root:new --kid root-<year> --out <file>` on the owner's machine; store the private file in
|
|
15
|
+
* the password manager (+ printed backup).
|
|
16
|
+
* 2. Append `{ kid: 'root-<year>', jwk: { kty: 'EC', crv: 'P-256', x, y } }` to `rootPublicKeys` below.
|
|
17
|
+
* 3. Release an SDK **minor** (`npm version minor` / changeset); every site picks it up as an ordinary dependency
|
|
18
|
+
* bump. Removing an old root is a **major** (§4.5 "Root rotation").
|
|
19
|
+
* 4. Add the same entry to `MANIFEST_ROOT_PUBLIC_KEYS` on the hub, certify the manifest key under the new root.
|
|
20
|
+
*
|
|
21
|
+
* `rootPublicKeys` is EMPTY up to 2.2.0-beta.1: no production root exists yet (nothing is published in production). A
|
|
22
|
+
* site that does not pass `manifestRootKeys` therefore trusts no manifest and renders nothing — the correct result
|
|
23
|
+
* for an environment that has no signed content. The development root below is exported separately and is only ever
|
|
24
|
+
* referenced explicitly (`network-sdk init --root-keys …` writes it into `manifestRootKeys` of the site's
|
|
25
|
+
* `network.config.js`); it must never be merged into `rootPublicKeys`, because its private key lives on a developer
|
|
26
|
+
* machine and the dev bucket (`network-dev/v1`) is not production content.
|
|
27
|
+
*/
|
|
28
|
+
type RootPublicKey = {
|
|
29
|
+
kid: string;
|
|
30
|
+
jwk: {
|
|
31
|
+
kty: 'EC';
|
|
32
|
+
crv: 'P-256';
|
|
33
|
+
x: string;
|
|
34
|
+
y: string;
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
/** Production roots (none yet; see the file comment). */
|
|
38
|
+
declare const rootPublicKeys: readonly RootPublicKey[];
|
|
39
|
+
/**
|
|
40
|
+
* The DEVELOPMENT root (hub `.env` `MANIFEST_ROOT_PUBLIC_KEYS`, dev bucket `network-dev/v1`, kid `root-dev-a01e0d`).
|
|
41
|
+
* Public key, not a secret. Used by the test suite and by `init --root-keys` for the JCM pilot; never trusted by
|
|
42
|
+
* default.
|
|
43
|
+
*/
|
|
44
|
+
declare const DEV_ROOT_PUBLIC_KEYS: readonly RootPublicKey[];
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* `defineNetworkConfig` — spec §6.2 (the only per-site file is `src/network.config.js`) and §4.2 / §6.3 URL precedence:
|
|
48
|
+
* `config.manifestUrl ?? (config.cdnBase ?? fallback.cdnBase ?? DEFAULT_CDN_BASE) + '/' + (preview?) + 'sites/<siteKey>/manifest.json'`.
|
|
49
|
+
* It also derives `capture = { siteKey, endpoint: fallback.analytics.endpoint, consent, consentMode }` for `main.jsx`
|
|
50
|
+
* (§5.3) so nothing is assembled by hand. Release 2b review round 2: the endpoint is the fallback's whatever its
|
|
51
|
+
* `analytics.landings` says — the bundled copy is refreshed only by a site build, while §2.2 makes the switch a publish;
|
|
52
|
+
* the hub refuses a landing for a destination whose live `landings` is off (`disabled`, 0 operations). It is `null`
|
|
53
|
+
* only for a DEV build of a production-channel site whose endpoint is not a local hub (the v2.2 changelog's "SDK
|
|
54
|
+
* silent on localhost / DEV"). Pure: no DOM, no network.
|
|
55
|
+
*/
|
|
56
|
+
|
|
57
|
+
type ConsentState = 'granted' | 'denied' | null;
|
|
58
|
+
/** §6.2: the consent adapter contract, stated once. */
|
|
59
|
+
type ConsentAdapter = {
|
|
60
|
+
get: () => ConsentState;
|
|
61
|
+
};
|
|
62
|
+
type ConsentMode = 'session-default' | 'require-consent';
|
|
63
|
+
declare const THEME_SLOTS: readonly ["section", "container", "heading", "accentWord", "subheading", "grid", "card", "imageBox", "image", "placeholder", "body", "name", "meta", "description", "button", "buttonIcon"];
|
|
64
|
+
type ThemeSlot = (typeof THEME_SLOTS)[number];
|
|
65
|
+
/** §6.1 headless className slots: the site's own Tailwind classes live in the site's source. */
|
|
66
|
+
type NetworkTheme = Partial<Record<ThemeSlot, string>>;
|
|
67
|
+
type NetworkEvent = {
|
|
68
|
+
type: 'directory';
|
|
69
|
+
payload: {
|
|
70
|
+
source: string;
|
|
71
|
+
revision: number | null;
|
|
72
|
+
flags: string[];
|
|
73
|
+
};
|
|
74
|
+
} | {
|
|
75
|
+
type: 'impression';
|
|
76
|
+
payload: {
|
|
77
|
+
ids: string[];
|
|
78
|
+
revision: number | null;
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
/** `href` is the at-rest link (UTMs only): the click id never reaches the site's own tracker (§5.3). */
|
|
82
|
+
| {
|
|
83
|
+
type: 'click';
|
|
84
|
+
payload: {
|
|
85
|
+
id: string;
|
|
86
|
+
href: string;
|
|
87
|
+
via: string;
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
/** §5.1: a beacon was handed to the browser (`sent`) or could not be; `why` is the impression's send reason. */
|
|
91
|
+
| {
|
|
92
|
+
type: 'signal';
|
|
93
|
+
payload: {
|
|
94
|
+
kind: 'impression' | 'click';
|
|
95
|
+
sent: boolean;
|
|
96
|
+
why?: string;
|
|
97
|
+
};
|
|
98
|
+
};
|
|
99
|
+
type NetworkConfigInput = {
|
|
100
|
+
/** 1) per site. When omitted the SDK uses `fallback.site` and flags `sitekey_from_fallback` (§5.1). */
|
|
101
|
+
siteKey?: string | undefined;
|
|
102
|
+
/** `'preview'` → `/network/v1/preview/sites/…` on the production CDN. Default `'production'`. */
|
|
103
|
+
channel?: SiteChannel | string | undefined;
|
|
104
|
+
/** Optional override of `DEFAULT_CDN_BASE` (normally the manifest's `cdnBase` wins once loaded). */
|
|
105
|
+
cdnBase?: string | undefined;
|
|
106
|
+
/** Full override: the separate staging hub only, together with `manifestRootKeys`. */
|
|
107
|
+
manifestUrl?: string | undefined;
|
|
108
|
+
/** `src/data/network.fallback.json`, written by `network-sdk sync-fallback`; also the rollback floor. */
|
|
109
|
+
fallback?: unknown;
|
|
110
|
+
/** Staging / dev override of the compiled `rootPublicKeys` (§4.5). */
|
|
111
|
+
manifestRootKeys?: readonly RootPublicKey[] | undefined;
|
|
112
|
+
/** 2) per site adapter; omitted → treated as `null`. */
|
|
113
|
+
consent?: ConsentAdapter | undefined;
|
|
114
|
+
consentMode?: ConsentMode | undefined;
|
|
115
|
+
/** 3) per site brand classes. */
|
|
116
|
+
theme?: NetworkTheme | undefined;
|
|
117
|
+
/** Drop the `inr-*` default class names (Tailwind-only sites). */
|
|
118
|
+
unstyled?: boolean | undefined;
|
|
119
|
+
/** Defaults to true (§4.5). `false` skips the signature (schema + identity still run); development only. */
|
|
120
|
+
verifySignature?: boolean | undefined;
|
|
121
|
+
/** §4.6 insecure contexts: render the fallback unverified when `crypto.subtle` is missing in production. */
|
|
122
|
+
allowInsecureFallback?: boolean | undefined;
|
|
123
|
+
/** The site's `import.meta.env.DEV`: enables the single `console.warn` per failure and the insecure-context skip. */
|
|
124
|
+
dev?: boolean | undefined;
|
|
125
|
+
/** Mirror events into the site's own tracker (§6.3). */
|
|
126
|
+
onEvent?: ((event: NetworkEvent) => void) | undefined;
|
|
127
|
+
};
|
|
128
|
+
type CaptureConfig = {
|
|
129
|
+
siteKey: string;
|
|
130
|
+
endpoint: string | null;
|
|
131
|
+
consent: ConsentAdapter | undefined;
|
|
132
|
+
consentMode: ConsentMode;
|
|
133
|
+
};
|
|
134
|
+
type NetworkConfig = {
|
|
135
|
+
siteKey: string;
|
|
136
|
+
siteKeyFromFallback: boolean;
|
|
137
|
+
channel: SiteChannel;
|
|
138
|
+
manifestUrl: string;
|
|
139
|
+
fallback: unknown;
|
|
140
|
+
roots: readonly RootPublicKey[];
|
|
141
|
+
consent: ConsentAdapter | undefined;
|
|
142
|
+
consentMode: ConsentMode;
|
|
143
|
+
theme: NetworkTheme;
|
|
144
|
+
unstyled: boolean;
|
|
145
|
+
verifySignature: boolean;
|
|
146
|
+
allowInsecureFallback: boolean;
|
|
147
|
+
dev: boolean;
|
|
148
|
+
onEvent: ((event: NetworkEvent) => void) | undefined;
|
|
149
|
+
/** For `captureReferral(networkConfig.capture)` in `main.jsx` (§5.3). */
|
|
150
|
+
capture: CaptureConfig;
|
|
151
|
+
};
|
|
152
|
+
declare function defineNetworkConfig(input: NetworkConfigInput): NetworkConfig;
|
|
153
|
+
|
|
154
|
+
type PublicJwk$1 = {
|
|
155
|
+
kty: 'EC';
|
|
156
|
+
crv: 'P-256';
|
|
157
|
+
x: string;
|
|
158
|
+
y: string;
|
|
159
|
+
};
|
|
160
|
+
type ManifestImage = {
|
|
161
|
+
src: string;
|
|
162
|
+
src2x: string;
|
|
163
|
+
alt: string;
|
|
164
|
+
width: 640;
|
|
165
|
+
height: 360;
|
|
166
|
+
};
|
|
167
|
+
type Instrumentation = 'none' | 'landings' | 'conversions';
|
|
168
|
+
type ManifestBusiness = {
|
|
169
|
+
id: string;
|
|
170
|
+
idx: number;
|
|
171
|
+
name: string;
|
|
172
|
+
description: string;
|
|
173
|
+
url: string;
|
|
174
|
+
domain: string;
|
|
175
|
+
image: ManifestImage;
|
|
176
|
+
category: string | null;
|
|
177
|
+
location: string | null;
|
|
178
|
+
region: string | null;
|
|
179
|
+
tags: string[];
|
|
180
|
+
pinned: boolean;
|
|
181
|
+
position: number;
|
|
182
|
+
instrumentation: Instrumentation;
|
|
183
|
+
};
|
|
184
|
+
type ManifestSigner = {
|
|
185
|
+
kid: string;
|
|
186
|
+
jwk: PublicJwk$1;
|
|
187
|
+
notBefore: string;
|
|
188
|
+
notAfter: string;
|
|
189
|
+
rootKid: string;
|
|
190
|
+
rootSig: string;
|
|
191
|
+
revokedKids: string[];
|
|
192
|
+
};
|
|
193
|
+
type ManifestSig = {
|
|
194
|
+
alg: 'ES256';
|
|
195
|
+
kid: string;
|
|
196
|
+
value: string;
|
|
197
|
+
};
|
|
198
|
+
type ManifestAnalytics = {
|
|
199
|
+
enabled: boolean;
|
|
200
|
+
endpoint: string;
|
|
201
|
+
impressions: boolean;
|
|
202
|
+
clicks: boolean;
|
|
203
|
+
landings: boolean;
|
|
204
|
+
samplePermille: number;
|
|
205
|
+
token: string;
|
|
206
|
+
};
|
|
207
|
+
type ManifestLinks = {
|
|
208
|
+
utmMedium: string;
|
|
209
|
+
utmCampaign: string;
|
|
210
|
+
utmSource: string;
|
|
211
|
+
refParam: string;
|
|
212
|
+
nofollow: boolean;
|
|
213
|
+
};
|
|
214
|
+
type Manifest = {
|
|
215
|
+
schema: 2;
|
|
216
|
+
revision: number;
|
|
217
|
+
publishedAt: string;
|
|
218
|
+
site: string;
|
|
219
|
+
siteIndex: number;
|
|
220
|
+
channel: 'production' | 'preview';
|
|
221
|
+
cdnBase: string;
|
|
222
|
+
minSdkVersion: string;
|
|
223
|
+
analytics: ManifestAnalytics;
|
|
224
|
+
links: ManifestLinks;
|
|
225
|
+
section: {
|
|
226
|
+
title: string;
|
|
227
|
+
subtitle: string | null;
|
|
228
|
+
};
|
|
229
|
+
businesses: ManifestBusiness[];
|
|
230
|
+
signer: ManifestSigner;
|
|
231
|
+
sig: ManifestSig;
|
|
232
|
+
};
|
|
233
|
+
/** Returns the typed manifest, or `null` when the input is not a valid schema-2 manifest. Never throws. */
|
|
234
|
+
declare function parseManifest(input: unknown): Manifest | null;
|
|
235
|
+
|
|
236
|
+
type SendReason = 'timer' | 'click' | 'hidden' | 'pagehide';
|
|
237
|
+
type SignalKind = 'impression' | 'click';
|
|
238
|
+
/** One page view (§2.4 `pv`): the impression tracker plus the fields every click of the page view carries. */
|
|
239
|
+
type PageView = {
|
|
240
|
+
readonly pv: string;
|
|
241
|
+
/** Mount epoch ms (§2.4 `m`): the same value on the impression and every click of this `pv`. */
|
|
242
|
+
readonly m: number;
|
|
243
|
+
/** §5.1 sampling, rolled once: `1` = impressions measured for this page view. Clicks always go, with `smp: 0`. */
|
|
244
|
+
readonly smp: 0 | 1;
|
|
245
|
+
readonly hd: number;
|
|
246
|
+
/** An impression for this `pv` has been sent (survives bfcache with the heap): the click's `ip`. */
|
|
247
|
+
readonly sent: boolean;
|
|
248
|
+
/** Rendered slugs in order: `pos` on the impression items and on the click signal is the index here. */
|
|
249
|
+
setOrder(ids: readonly string[]): void;
|
|
250
|
+
/** The clicked card's position: its rendered index (the hub requires `pos < itemCount`). */
|
|
251
|
+
pos(b: ManifestBusiness): number;
|
|
252
|
+
/** Registers (or, with `null`, forgets) a card element; works before and after `start()`. Dwell is kept per slug. */
|
|
253
|
+
observe(slug: string, el: Element | null): void;
|
|
254
|
+
/** From the component's effect with the `<section>` element; honours the §5.1 prerender guard. */
|
|
255
|
+
start(section: Element | null): void;
|
|
256
|
+
/** Unmount (SPA route change): a due impression is sent first (`hidden`), then everything is detached. */
|
|
257
|
+
stop(): void;
|
|
258
|
+
/** §5.1 common payload fields, shared with the click signal (every ms / epoch value an integer). */
|
|
259
|
+
common(now: number): Record<string, unknown>;
|
|
260
|
+
post(kind: SignalKind, body: Record<string, unknown>, why?: SendReason | null): boolean;
|
|
261
|
+
/** The synchronous flush before a click signal; returns `ip` (an impression exists for this page view). */
|
|
262
|
+
flushForClick(): boolean;
|
|
263
|
+
/**
|
|
264
|
+
* Sends the impression when it is due: never when sampled out or unmeasured; the first send needs something to
|
|
265
|
+
* have been on screen; a re-send only from `hidden` / `pagehide` and only when a `seen` / `ms` / `fv` changed.
|
|
266
|
+
*/
|
|
267
|
+
flush(why: SendReason): boolean;
|
|
268
|
+
};
|
|
269
|
+
|
|
270
|
+
type DirectorySource = 'live' | 'fallback' | 'empty';
|
|
271
|
+
/** §5.1 flag vocabulary (the subset the directory path sets) plus the SDK-local `fetch_fail` / `insecure_context`. */
|
|
272
|
+
type DirectoryFlag = 'sig_fail' | 'sig_revoked' | 'rev_rollback' | 'stale_cache' | 'fallback_invalid' | 'fallback_key_expired' | 'sitekey_from_fallback' | 'sdk_outdated' | 'fetch_fail' | 'insecure_context';
|
|
273
|
+
type DirectoryState = {
|
|
274
|
+
businesses: ManifestBusiness[];
|
|
275
|
+
loading: boolean;
|
|
276
|
+
source: DirectorySource;
|
|
277
|
+
revision: number | null;
|
|
278
|
+
manifest: Manifest | null;
|
|
279
|
+
flags: DirectoryFlag[];
|
|
280
|
+
/**
|
|
281
|
+
* The revision of the live manifest rejected below the floor (`rev_rollback`) or first received stale and resolved
|
|
282
|
+
* by the reload (`stale_cache`); sent as `rr` with those flags so the hub can judge the `manifest_replay` tolerance
|
|
283
|
+
* (§4.6). `null` otherwise.
|
|
284
|
+
*/
|
|
285
|
+
rr: number | null;
|
|
286
|
+
};
|
|
287
|
+
type LoaderDeps = {
|
|
288
|
+
fetch?: typeof fetch | undefined;
|
|
289
|
+
now?: () => Date;
|
|
290
|
+
hostname?: string;
|
|
291
|
+
warn?: (message: string) => void;
|
|
292
|
+
};
|
|
293
|
+
declare function loadDirectory(config: NetworkConfig, deps?: LoaderDeps): Promise<DirectoryState>;
|
|
294
|
+
|
|
295
|
+
type ClickVia = 'click' | 'auxclick' | 'contextmenu' | 'drag';
|
|
296
|
+
type ClickButton = 0 | 1 | 2;
|
|
297
|
+
type SignalHooks = {
|
|
298
|
+
/** The section rendered these cards (the Phase 1 `impression` `onEvent` mirror, kept as is). */
|
|
299
|
+
rendered: (ids: string[]) => void;
|
|
300
|
+
/** `pointerdown`: mints the card's click id; returns the rewritten href, or `null` when clicks are off. */
|
|
301
|
+
pointerDown: (business: ManifestBusiness, href: string) => string | null;
|
|
302
|
+
/**
|
|
303
|
+
* `click` / `auxclick` / `contextmenu` / `dragstart` (or a custom card's `trackClick`): flushes the impression, sends
|
|
304
|
+
* the click signal with the id minted at pointerdown (minted now for a keyboard activation) and returns the href to
|
|
305
|
+
* navigate with (`href` itself when clicks are off).
|
|
306
|
+
*/
|
|
307
|
+
click: (business: ManifestBusiness, href: string, via: ClickVia, button: ClickButton) => string;
|
|
308
|
+
/** Card element registration for per-card viewability (ref callbacks). */
|
|
309
|
+
observe: (slug: string, el: Element | null) => void;
|
|
310
|
+
/** Rendered order: `pos` on the impression items and on the click signal. */
|
|
311
|
+
setOrder: (ids: readonly string[]) => void;
|
|
312
|
+
/** From the component's effect with the `<section>` element; the cleanup calls `stop()`. */
|
|
313
|
+
start: (section: Element | null) => void;
|
|
314
|
+
stop: () => void;
|
|
315
|
+
/** `null` when analytics is off in the manifest, nothing is loaded, or the runtime has no CSPRNG. */
|
|
316
|
+
readonly page: PageView | null;
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
declare function NetworkProvider(props: {
|
|
320
|
+
config: NetworkConfig;
|
|
321
|
+
children?: ReactNode;
|
|
322
|
+
}): react.JSX.Element;
|
|
323
|
+
|
|
324
|
+
/** Structural event type: React synthetic events and native DOM events both fit. */
|
|
325
|
+
type LinkEvent = {
|
|
326
|
+
currentTarget: unknown;
|
|
327
|
+
button?: number;
|
|
328
|
+
};
|
|
329
|
+
type NetworkLinkProps = {
|
|
330
|
+
href: string;
|
|
331
|
+
target: '_blank';
|
|
332
|
+
rel: string;
|
|
333
|
+
'aria-label': string;
|
|
334
|
+
onPointerDown: (e: LinkEvent) => void;
|
|
335
|
+
onClick: (e: LinkEvent) => void;
|
|
336
|
+
onAuxClick: (e: LinkEvent) => void;
|
|
337
|
+
onContextMenu: (e: LinkEvent) => void;
|
|
338
|
+
onDragStart: (e: LinkEvent) => void;
|
|
339
|
+
/** Release 2b review round 2: the end of the gesture starts the restore of the at-rest href. */
|
|
340
|
+
onPointerUp: (e: LinkEvent) => void;
|
|
341
|
+
onPointerCancel: (e: LinkEvent) => void;
|
|
342
|
+
onBlur: (e: LinkEvent) => void;
|
|
343
|
+
};
|
|
344
|
+
type NetworkLink = {
|
|
345
|
+
href: string;
|
|
346
|
+
linkProps: NetworkLinkProps;
|
|
347
|
+
/**
|
|
348
|
+
* For a custom control that is not an `<a {...linkProps}>`: sends the click signal (flushing the impression first)
|
|
349
|
+
* and returns the href to navigate with (`…&inr=<clickId>` when the manifest enables clicks).
|
|
350
|
+
*/
|
|
351
|
+
trackClick: (via?: ClickVia, button?: ClickButton) => string;
|
|
352
|
+
/** Ref callback for the card element: per-card viewability (`seen` / `ms` / `fv`, §5.1). Stable per card. */
|
|
353
|
+
observe: (el: Element | null) => void;
|
|
354
|
+
};
|
|
355
|
+
declare function buildHref(url: string, links: ManifestLinks, slug: string): string;
|
|
356
|
+
/** 2.0.0's second argument (`trackClick` returned its result); kept as a deprecated mirror in 2.x. */
|
|
357
|
+
type LegacyOnClick = (business: ManifestBusiness, href: string, via: string) => string;
|
|
358
|
+
declare function useNetworkLink(business: ManifestBusiness, hooks?: SignalHooks | LegacyOnClick | null): NetworkLink;
|
|
359
|
+
|
|
360
|
+
declare const HEADING_ID = "discover-businesses-heading";
|
|
361
|
+
/** `href`, `linkProps` (spread onto the card's `<a>`), `trackClick(via)` and `observe` (the card's `ref`). */
|
|
362
|
+
type RenderCardArgs = NetworkLink;
|
|
363
|
+
type DiscoverBusinessesProps = {
|
|
364
|
+
title?: string | undefined;
|
|
365
|
+
subtitle?: string | null | undefined;
|
|
366
|
+
maxItems?: number | undefined;
|
|
367
|
+
renderCard?: ((business: ManifestBusiness, args: RenderCardArgs) => ReactNode) | undefined;
|
|
368
|
+
theme?: NetworkTheme | undefined;
|
|
369
|
+
unstyled?: boolean | undefined;
|
|
370
|
+
onEvent?: ((event: NetworkEvent) => void) | undefined;
|
|
371
|
+
/** Use without `<NetworkProvider>`: pass the config directly. */
|
|
372
|
+
config?: NetworkConfig | undefined;
|
|
373
|
+
};
|
|
374
|
+
declare function DiscoverBusinesses(props: DiscoverBusinessesProps): react.JSX.Element | null;
|
|
375
|
+
|
|
376
|
+
declare function useNetworkDirectory(override?: NetworkConfig | null): DirectoryState;
|
|
377
|
+
|
|
378
|
+
declare function canonicalJson(value: unknown): string;
|
|
379
|
+
|
|
380
|
+
type PublicJwk = {
|
|
381
|
+
kty: 'EC';
|
|
382
|
+
crv: 'P-256';
|
|
383
|
+
x: string;
|
|
384
|
+
y: string;
|
|
385
|
+
};
|
|
386
|
+
|
|
387
|
+
type RootKey = {
|
|
388
|
+
kid: string;
|
|
389
|
+
jwk: PublicJwk;
|
|
390
|
+
};
|
|
391
|
+
type ManifestVerifyReason = 'malformed' | 'identity' | 'root_unknown' | 'root_sig' | 'window' | 'kid_mismatch' | 'sig' | 'revoked';
|
|
392
|
+
type ManifestVerifyResult = {
|
|
393
|
+
ok: true;
|
|
394
|
+
manifest: Manifest;
|
|
395
|
+
} | {
|
|
396
|
+
ok: false;
|
|
397
|
+
reason: ManifestVerifyReason;
|
|
398
|
+
};
|
|
399
|
+
type VerifyManifestOptions = {
|
|
400
|
+
/** Trusted root public keys (`rootPublicKeys` or `manifestRootKeys`); empty → `root_unknown`. */
|
|
401
|
+
roots: readonly RootKey[];
|
|
402
|
+
/** Must be a finite date. */
|
|
403
|
+
now: Date;
|
|
404
|
+
/** `site`, `channel` and `links.utmSource` must match. */
|
|
405
|
+
expect: {
|
|
406
|
+
site: string;
|
|
407
|
+
channel: 'production' | 'preview';
|
|
408
|
+
};
|
|
409
|
+
/** `live`: window applies and the trusted `revokedKids` is required. `fallback`: only the window is skipped. */
|
|
410
|
+
source: 'live' | 'fallback';
|
|
411
|
+
revokedKids?: readonly string[];
|
|
412
|
+
};
|
|
413
|
+
declare function verifyManifest(input: unknown, opts: VerifyManifestOptions): Promise<ManifestVerifyResult>;
|
|
414
|
+
/**
|
|
415
|
+
* The bytes entry point for a fetched manifest: refuses input over 24 KB before decoding or parsing, decodes fatal
|
|
416
|
+
* UTF-8 **keeping** a leading BOM (which then fails to parse), requires `canonicalJson(JSON.parse(raw)) === raw`
|
|
417
|
+
* (no whitespace, sorted keys, no duplicate keys, no alternative escapes), then `verifyManifest`.
|
|
418
|
+
*/
|
|
419
|
+
declare function verifyManifestBytes(raw: string | Uint8Array, opts: VerifyManifestOptions): Promise<ManifestVerifyResult>;
|
|
420
|
+
|
|
421
|
+
export { type CaptureConfig, type ClickButton, type ClickVia, type ConsentAdapter, type ConsentMode, type ConsentState, DEV_ROOT_PUBLIC_KEYS, type DirectoryFlag, type DirectorySource, type DirectoryState, DiscoverBusinesses, type DiscoverBusinessesProps, HEADING_ID, type LinkEvent, type Manifest, type ManifestBusiness, type ManifestVerifyReason, type ManifestVerifyResult, type NetworkConfig, type NetworkConfigInput, type NetworkEvent, type NetworkLink, type NetworkLinkProps, NetworkProvider, type NetworkTheme, type RenderCardArgs, type RootKey, type RootPublicKey, THEME_SLOTS, type ThemeSlot, buildHref, canonicalJson, defineNetworkConfig, loadDirectory, parseManifest, rootPublicKeys, useNetworkDirectory, useNetworkLink, verifyManifest, verifyManifestBytes };
|