@ensemblekit/sdk-types 0.1.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/README.md ADDED
@@ -0,0 +1,43 @@
1
+ # @ensemblekit/sdk-types
2
+
3
+ TypeScript types for the Ensemble browser SDK wire contract — the
4
+ `window.recs` command surface installed by the hosted script tag
5
+ (`{ingest-origin}/sdk/v1.js`).
6
+
7
+ Types only: no runtime, no dependencies. The SDK itself is never installed
8
+ from npm; storefronts load it via the script tag.
9
+
10
+ ## Usage
11
+
12
+ ```ts
13
+ import type {RecsCommand, RecsEventPayloads} from '@ensemblekit/sdk-types';
14
+ ```
15
+
16
+ To type `window.recs` globally, add one side-effect import (or put
17
+ `@ensemblekit/sdk-types/global` in your tsconfig `types`):
18
+
19
+ ```ts
20
+ import '@ensemblekit/sdk-types/global';
21
+
22
+ window.recs?.('track', 'product_viewed', {
23
+ productId: 'gid://shopify/Product/1',
24
+ handle: 'slim-cuff-pant',
25
+ price: 98,
26
+ currency: 'GBP',
27
+ });
28
+ ```
29
+
30
+ Naming note: the product is Ensemble; the wire-level global and command verb
31
+ are `recs` by design (the `gtag()` precedent), so type names keep the `Recs`
32
+ prefix to match `window.recs`.
33
+
34
+ ## Contract guarantee
35
+
36
+ The runtime contract is the zod schemas in the Ensemble monorepo's
37
+ `@recs/core` — what the SDK and ingest actually validate. The shapes
38
+ published here are locked to those schemas by a compile-time identity
39
+ assertion (`typetests/contract-lock.ts`); any mismatch fails the workspace
40
+ typecheck, so a release cannot drift from the wire contract.
41
+
42
+ Versioning follows the contract's schema policy: the ingest accepts schema
43
+ versions {N, N−1}, and payload-shape changes bump this package accordingly.
@@ -0,0 +1,19 @@
1
+ import { RecsCommand } from './index.js';
2
+
3
+ /**
4
+ * Optional global augmentation: `import '@ensemblekit/sdk-types/global'` (or add
5
+ * it to tsconfig `types`) to type `window.recs` without hand-declaring it.
6
+ */
7
+
8
+ declare global {
9
+ interface Window {
10
+ /**
11
+ * The Ensemble SDK global. The bootstrap snippet installs the `q` queue
12
+ * function; `/sdk/v1.js` replaces it with a live dispatcher that drains
13
+ * the queue. Absent until one of them has run.
14
+ */
15
+ recs?: RecsCommand & {
16
+ q?: unknown[];
17
+ };
18
+ }
19
+ }
@@ -0,0 +1,102 @@
1
+ /**
2
+ * Published types for the Ensemble browser SDK wire contract.
3
+ *
4
+ * The runtime contract is the zod schemas in @recs/core (what the SDK and
5
+ * ingest actually validate). The shapes below are authored — the published
6
+ * .d.ts must be dependency-free, so it can't reference zod — but drift is
7
+ * compile-time impossible: typetests/contract-lock.ts asserts identity
8
+ * against the z.infer types, and the workspace typecheck fails on any
9
+ * mismatch.
10
+ *
11
+ * Naming note: the product is Ensemble; the wire-level global and command
12
+ * verb are `recs` by design (the gtag/analytics precedent), so exported
13
+ * type names keep the Recs prefix to match `window.recs`.
14
+ */
15
+ /** Cart/order line snapshot shared by cart_viewed, cart_updated, order_completed. */
16
+ type RecsLine = {
17
+ productId: string;
18
+ variantId: string;
19
+ qty: number;
20
+ price: number;
21
+ };
22
+ type RecSlotPayload = {
23
+ slot: string;
24
+ campaignId: string;
25
+ productId: string;
26
+ position: number;
27
+ modelVersion: string;
28
+ };
29
+ /** Payload shapes for the SDK's strict event names, keyed by event name. */
30
+ type RecsEventPayloads = {
31
+ page_viewed: {
32
+ pageType: string;
33
+ path: string;
34
+ };
35
+ product_viewed: {
36
+ productId: string;
37
+ handle: string;
38
+ variantId?: string;
39
+ price: number;
40
+ currency: string;
41
+ };
42
+ collection_viewed: {
43
+ collectionHandle: string;
44
+ productIds: string[];
45
+ };
46
+ cart_viewed: {
47
+ lines: RecsLine[];
48
+ };
49
+ search_viewed: {
50
+ query: string;
51
+ productIds: string[];
52
+ };
53
+ cart_updated: {
54
+ lines: RecsLine[];
55
+ };
56
+ product_added_to_cart: {
57
+ productId: string;
58
+ variantId: string;
59
+ qty: number;
60
+ price: number;
61
+ currency: string;
62
+ };
63
+ product_removed_from_cart: {
64
+ productId: string;
65
+ variantId: string;
66
+ qty: number;
67
+ };
68
+ order_completed: {
69
+ orderId: string;
70
+ total: number;
71
+ currency: string;
72
+ lines: RecsLine[];
73
+ };
74
+ rec_impression: RecSlotPayload;
75
+ rec_clicked: RecSlotPayload;
76
+ };
77
+ /** The strict event names accepted by `recs('track', ...)`. */
78
+ type RecsEventName = keyof RecsEventPayloads;
79
+ /** Config accepted by `recs('init', ...)`. */
80
+ type RecsInitConfig = {
81
+ storeId: string;
82
+ /** Absolute URL of the ingest endpoint (POST /v1/events). Derived from the
83
+ * SDK script's own src origin when omitted. */
84
+ endpoint?: string;
85
+ redactPaths?: RegExp[];
86
+ debug?: boolean;
87
+ };
88
+ /**
89
+ * Shape of `window.recs`. Before the SDK script loads it is the bootstrap
90
+ * command queue; once `/sdk/v1.js` loads it is replaced with a live
91
+ * dispatcher that drains the queue. Both accept the same six commands.
92
+ */
93
+ interface RecsCommand {
94
+ (command: 'init', config: RecsInitConfig): void;
95
+ (command: 'consent', state: 'granted' | 'revoked'): void;
96
+ <E extends RecsEventName>(command: 'track', name: E, payload: RecsEventPayloads[E]): void;
97
+ (command: 'signal', name: string, payload: Record<string, unknown>): void;
98
+ (command: 'customer', id?: string): void;
99
+ (command: 'flush'): void;
100
+ }
101
+
102
+ export type { RecsCommand, RecsEventName, RecsEventPayloads, RecsInitConfig, RecsLine };
package/package.json ADDED
@@ -0,0 +1,32 @@
1
+ {
2
+ "name": "@ensemblekit/sdk-types",
3
+ "version": "0.1.0",
4
+ "description": "TypeScript types for the Ensemble browser SDK wire contract (the window.recs command surface)",
5
+ "type": "module",
6
+ "license": "MIT",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts"
10
+ },
11
+ "./global": {
12
+ "types": "./dist/global.d.ts"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "publishConfig": {
19
+ "access": "public"
20
+ },
21
+ "devDependencies": {
22
+ "tsup": "^8.5.1",
23
+ "typescript": "^5.6.0",
24
+ "@recs/collector": "0.0.0",
25
+ "@recs/core": "0.0.0"
26
+ },
27
+ "scripts": {
28
+ "build": "tsup src/index.ts src/global.ts --dts-only --format esm --out-dir dist && node scripts/check-self-contained.mjs",
29
+ "test": "tsc --noEmit",
30
+ "typecheck": "tsc --noEmit"
31
+ }
32
+ }