@drip-apex/sdk 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.
Files changed (227) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +46 -0
  3. package/dist/_headers +3 -0
  4. package/dist/bundle-report.json +564 -0
  5. package/dist/drip.debug.js +2 -0
  6. package/dist/drip.debug.js.map +1 -0
  7. package/dist/drip.heatmap.js +2 -0
  8. package/dist/drip.heatmap.js.map +1 -0
  9. package/dist/drip.js +2 -0
  10. package/dist/drip.js.map +1 -0
  11. package/dist/drip.live.js +2 -0
  12. package/dist/drip.live.js.map +1 -0
  13. package/dist/editor.js +480 -0
  14. package/dist/editor.js.map +7 -0
  15. package/dist/index.mjs +645 -0
  16. package/dist/index.mjs.map +7 -0
  17. package/dist/metafiles/drip.debug.meta.json +973 -0
  18. package/dist/metafiles/drip.heatmap.meta.json +918 -0
  19. package/dist/metafiles/drip.live.meta.json +918 -0
  20. package/dist/metafiles/drip.meta.json +973 -0
  21. package/dist/metafiles/editor.meta.json +321 -0
  22. package/dist/metafiles/index.meta.json +1039 -0
  23. package/dist/metafiles/index.mjs.meta.json +78 -0
  24. package/dist/react/index.js +16973 -0
  25. package/dist/react/index.js.map +7 -0
  26. package/dist/sri.json +27 -0
  27. package/dist/types/analytics.d.ts +15 -0
  28. package/dist/types/antiflicker.d.ts +14 -0
  29. package/dist/types/assignment-store.d.ts +30 -0
  30. package/dist/types/audit.d.ts +9 -0
  31. package/dist/types/bucket.d.ts +2 -0
  32. package/dist/types/bucketing-cleanup.d.ts +5 -0
  33. package/dist/types/commerce-gift.d.ts +41 -0
  34. package/dist/types/commerce-price.d.ts +22 -0
  35. package/dist/types/commerce-shipping.d.ts +28 -0
  36. package/dist/types/css.d.ts +5 -0
  37. package/dist/types/cwv.d.ts +10 -0
  38. package/dist/types/data-layer-normalize.d.ts +1 -0
  39. package/dist/types/debug.d.ts +23 -0
  40. package/dist/types/define.d.ts +87 -0
  41. package/dist/types/devtools.d.ts +32 -0
  42. package/dist/types/dom-trigger.d.ts +3 -0
  43. package/dist/types/editor/api.d.ts +37 -0
  44. package/dist/types/editor/artifacts.d.ts +15 -0
  45. package/dist/types/editor/command-runtime.d.ts +48 -0
  46. package/dist/types/editor/controller.d.ts +97 -0
  47. package/dist/types/editor/device-preview.d.ts +23 -0
  48. package/dist/types/editor/index.d.ts +9 -0
  49. package/dist/types/editor/operator.d.ts +39 -0
  50. package/dist/types/editor/picker.d.ts +23 -0
  51. package/dist/types/editor/selector.d.ts +2 -0
  52. package/dist/types/editor/types.d.ts +55 -0
  53. package/dist/types/editor/view-kit.d.ts +33 -0
  54. package/dist/types/editor/view.d.ts +5 -0
  55. package/dist/types/editor-bootstrap.d.ts +37 -0
  56. package/dist/types/exclusion-groups.d.ts +59 -0
  57. package/dist/types/exposure-signals.d.ts +7 -0
  58. package/dist/types/flags.d.ts +65 -0
  59. package/dist/types/goals.d.ts +16 -0
  60. package/dist/types/guards.d.ts +39 -0
  61. package/dist/types/handover.d.ts +10 -0
  62. package/dist/types/hash.d.ts +19 -0
  63. package/dist/types/heatmap.d.ts +8 -0
  64. package/dist/types/hideflicker.d.ts +15 -0
  65. package/dist/types/hydration.d.ts +11 -0
  66. package/dist/types/index.d.ts +144 -0
  67. package/dist/types/js.d.ts +6 -0
  68. package/dist/types/module.d.ts +4 -0
  69. package/dist/types/money.d.ts +14 -0
  70. package/dist/types/mutate.d.ts +34 -0
  71. package/dist/types/observer-mute.d.ts +3 -0
  72. package/dist/types/pii-keys.d.ts +1 -0
  73. package/dist/types/prerequisites.d.ts +12 -0
  74. package/dist/types/qa-assistant-state.d.ts +68 -0
  75. package/dist/types/qa-assistant-view.d.ts +6 -0
  76. package/dist/types/qa-assistant.d.ts +9 -0
  77. package/dist/types/qa-toolbar.d.ts +19 -0
  78. package/dist/types/react/index.d.ts +84 -0
  79. package/dist/types/reassert-sentinel.d.ts +6 -0
  80. package/dist/types/router.d.ts +9 -0
  81. package/dist/types/runtime-tools.d.ts +50 -0
  82. package/dist/types/runtime.d.ts +22 -0
  83. package/dist/types/safe-regex.d.ts +6 -0
  84. package/dist/types/sanitize.d.ts +5 -0
  85. package/dist/types/semantic.d.ts +7 -0
  86. package/dist/types/shopify-cart-events.d.ts +7 -0
  87. package/dist/types/shopify-cart.d.ts +62 -0
  88. package/dist/types/signals.d.ts +31 -0
  89. package/dist/types/surface-signals.d.ts +6 -0
  90. package/dist/types/targeting-diagnostics.d.ts +5 -0
  91. package/dist/types/targeting.d.ts +50 -0
  92. package/dist/types/test-fixtures/commerce.d.ts +12 -0
  93. package/dist/types/track.d.ts +79 -0
  94. package/dist/types/types.d.ts +859 -0
  95. package/dist/types/wait.d.ts +7 -0
  96. package/package.json +74 -0
  97. package/src/analytics.ts +146 -0
  98. package/src/antiflicker.test.ts +127 -0
  99. package/src/antiflicker.ts +147 -0
  100. package/src/assignment-store.test.ts +171 -0
  101. package/src/assignment-store.ts +208 -0
  102. package/src/audit.test.ts +17 -0
  103. package/src/audit.ts +362 -0
  104. package/src/bucket.test.ts +65 -0
  105. package/src/bucket.ts +18 -0
  106. package/src/bucketing-cleanup.test.ts +30 -0
  107. package/src/bucketing-cleanup.ts +72 -0
  108. package/src/bucketing-parity.test.ts +41 -0
  109. package/src/commerce-analytics-lifecycle.test.ts +1416 -0
  110. package/src/commerce-config-lifecycle.test.ts +274 -0
  111. package/src/commerce-epoch-lifecycle.test.ts +62 -0
  112. package/src/commerce-gift.test.ts +1293 -0
  113. package/src/commerce-gift.ts +979 -0
  114. package/src/commerce-offers-display.test.ts +154 -0
  115. package/src/commerce-price.test.ts +1145 -0
  116. package/src/commerce-price.ts +941 -0
  117. package/src/commerce-revocation-lifecycle.test.ts +78 -0
  118. package/src/commerce-shipping.test.ts +630 -0
  119. package/src/commerce-shipping.ts +447 -0
  120. package/src/config-fetch.test.ts +325 -0
  121. package/src/css.ts +54 -0
  122. package/src/cwv.test.ts +95 -0
  123. package/src/cwv.ts +129 -0
  124. package/src/data-layer-normalize.ts +21 -0
  125. package/src/debug.test.ts +83 -0
  126. package/src/debug.ts +138 -0
  127. package/src/define.test.ts +327 -0
  128. package/src/define.ts +208 -0
  129. package/src/devtools.ts +582 -0
  130. package/src/dom-trigger.test.ts +70 -0
  131. package/src/dom-trigger.ts +55 -0
  132. package/src/editor/api.test.ts +154 -0
  133. package/src/editor/api.ts +185 -0
  134. package/src/editor/artifacts.test.ts +57 -0
  135. package/src/editor/artifacts.ts +115 -0
  136. package/src/editor/command-runtime.test.ts +225 -0
  137. package/src/editor/command-runtime.ts +572 -0
  138. package/src/editor/controller.test.ts +371 -0
  139. package/src/editor/controller.ts +596 -0
  140. package/src/editor/device-preview.test.ts +60 -0
  141. package/src/editor/device-preview.ts +120 -0
  142. package/src/editor/index.test.ts +161 -0
  143. package/src/editor/index.ts +169 -0
  144. package/src/editor/operator.test.ts +148 -0
  145. package/src/editor/operator.ts +256 -0
  146. package/src/editor/picker.test.ts +58 -0
  147. package/src/editor/picker.ts +152 -0
  148. package/src/editor/selector.test.ts +44 -0
  149. package/src/editor/selector.ts +110 -0
  150. package/src/editor/types.ts +92 -0
  151. package/src/editor/view-kit.ts +162 -0
  152. package/src/editor/view.test.ts +535 -0
  153. package/src/editor/view.ts +1395 -0
  154. package/src/editor-bootstrap.test.ts +116 -0
  155. package/src/editor-bootstrap.ts +213 -0
  156. package/src/event-schema-contract.test.ts +35 -0
  157. package/src/exclusion-groups.test.ts +383 -0
  158. package/src/exclusion-groups.ts +270 -0
  159. package/src/exposure-signals.test.ts +182 -0
  160. package/src/exposure-signals.ts +110 -0
  161. package/src/flags.test.ts +322 -0
  162. package/src/flags.ts +201 -0
  163. package/src/goals.test.ts +42 -0
  164. package/src/goals.ts +200 -0
  165. package/src/guards.test.ts +249 -0
  166. package/src/guards.ts +250 -0
  167. package/src/handover-cache-order.test.ts +32 -0
  168. package/src/handover.test.ts +349 -0
  169. package/src/handover.ts +309 -0
  170. package/src/hash.ts +214 -0
  171. package/src/heatmap.test.ts +305 -0
  172. package/src/heatmap.ts +373 -0
  173. package/src/hideflicker.ts +21 -0
  174. package/src/hydration.test.ts +252 -0
  175. package/src/hydration.ts +203 -0
  176. package/src/index.ts +7513 -0
  177. package/src/init-empty.test.ts +5572 -0
  178. package/src/js.test.ts +26 -0
  179. package/src/js.ts +61 -0
  180. package/src/module.ts +50 -0
  181. package/src/money.test.ts +35 -0
  182. package/src/money.ts +53 -0
  183. package/src/mutate.test.ts +304 -0
  184. package/src/mutate.ts +469 -0
  185. package/src/observer-mute.test.ts +88 -0
  186. package/src/observer-mute.ts +45 -0
  187. package/src/page-trigger.test.ts +84 -0
  188. package/src/personalization.test.ts +68 -0
  189. package/src/pii-keys.ts +17 -0
  190. package/src/prerequisites.test.ts +39 -0
  191. package/src/prerequisites.ts +94 -0
  192. package/src/qa-assistant-state.test.ts +471 -0
  193. package/src/qa-assistant-state.ts +505 -0
  194. package/src/qa-assistant-view.test.ts +185 -0
  195. package/src/qa-assistant-view.ts +768 -0
  196. package/src/qa-assistant.ts +40 -0
  197. package/src/qa-toolbar.ts +444 -0
  198. package/src/react/index.test.tsx +177 -0
  199. package/src/react/index.tsx +252 -0
  200. package/src/reassert-sentinel.test.ts +314 -0
  201. package/src/reassert-sentinel.ts +191 -0
  202. package/src/router.test.ts +78 -0
  203. package/src/router.ts +92 -0
  204. package/src/runtime-tools.test.ts +112 -0
  205. package/src/runtime-tools.ts +403 -0
  206. package/src/runtime.test.ts +217 -0
  207. package/src/runtime.ts +268 -0
  208. package/src/safe-regex.ts +35 -0
  209. package/src/sanitize.ts +34 -0
  210. package/src/semantic.ts +245 -0
  211. package/src/shopify-cart-events.test.ts +76 -0
  212. package/src/shopify-cart-events.ts +115 -0
  213. package/src/shopify-cart.test.ts +2823 -0
  214. package/src/shopify-cart.ts +1256 -0
  215. package/src/signals.ts +226 -0
  216. package/src/surface-signals.test.ts +83 -0
  217. package/src/surface-signals.ts +165 -0
  218. package/src/targeting-diagnostics.ts +560 -0
  219. package/src/targeting.detailed.test.ts +443 -0
  220. package/src/targeting.test.ts +1054 -0
  221. package/src/targeting.ts +1024 -0
  222. package/src/test-fixtures/commerce.ts +65 -0
  223. package/src/track.test.ts +817 -0
  224. package/src/track.ts +519 -0
  225. package/src/types.ts +991 -0
  226. package/src/wait.test.ts +96 -0
  227. package/src/wait.ts +238 -0
@@ -0,0 +1,225 @@
1
+ // @vitest-environment jsdom
2
+ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
3
+ import type { EditorApi } from "./api";
4
+ import { EditorCommandExecutor, EditorCommandPoller } from "./command-runtime";
5
+ import type { EditorController } from "./controller";
6
+ import type { ClaimedEditorCommand } from "./types";
7
+
8
+ function command(
9
+ name: ClaimedEditorCommand["command"],
10
+ args: Record<string, unknown> = {},
11
+ ): ClaimedEditorCommand {
12
+ return { commandId: `command-${name}`, command: name, args, expiresAt: null };
13
+ }
14
+
15
+ function controller(origin = "https://shop.example") {
16
+ return {
17
+ session: { targetOrigin: origin },
18
+ applyCommandArtifacts: vi.fn(() => ({
19
+ ok: true,
20
+ mutationAudit: [],
21
+ generatedSelectors: [],
22
+ generatedVisibility: [],
23
+ visibleGeneratedCount: 0,
24
+ hiddenEffectVerifiedCount: 0,
25
+ networkRequired: false,
26
+ customJsDeferred: false,
27
+ })),
28
+ } as unknown as EditorController;
29
+ }
30
+
31
+ describe("EditorCommandExecutor", () => {
32
+ beforeEach(() => {
33
+ document.title = "Live store";
34
+ document.body.innerHTML = `
35
+ <h1 id="title">Original</h1>
36
+ <button data-testid="buy">Buy now</button>
37
+ <input name="email" value="customer@example.com">
38
+ <a id="account" href="/account?token=secret#orders">Account</a>
39
+ `;
40
+ history.replaceState(null, "", "/products/one?customer=42#private");
41
+ });
42
+
43
+ afterEach(() => vi.restoreAllMocks());
44
+
45
+ it("matches snapshot, interaction, and selection bridge payloads", async () => {
46
+ const click = vi.fn();
47
+ document.querySelector("button")!.addEventListener("click", click);
48
+ const executor = new EditorCommandExecutor(controller());
49
+
50
+ const snapshot = await executor.execute(command("snapshot"));
51
+ const clickResult = await executor.execute(command("click", { selector: "[data-testid='buy']" }));
52
+ const typeResult = await executor.execute(command("type", { selector: "input[name='email']", value: "new@example.com" }));
53
+ const selected = await executor.execute(command("select_element", { text: "Buy now" }));
54
+
55
+ expect(snapshot.result).toMatchObject({
56
+ ok: true,
57
+ snapshot: expect.objectContaining({ title: "Live store", headings: expect.any(Array), interactive: expect.any(Array) }),
58
+ });
59
+ expect(click).toHaveBeenCalledOnce();
60
+ expect(clickResult.result).toMatchObject({ ok: true, element: expect.objectContaining({ tag: "button" }) });
61
+ expect(typeResult.result).toMatchObject({ ok: true, valueLength: 15 });
62
+ expect(JSON.stringify(typeResult.result)).not.toContain("new@example.com");
63
+ expect((document.querySelector("input") as HTMLInputElement).value).toBe("new@example.com");
64
+ expect(selected.result).toMatchObject({
65
+ ok: true,
66
+ element: expect.objectContaining({ selector: expect.stringContaining("[data-testid=\"buy\"]") }),
67
+ });
68
+ });
69
+
70
+ it("relays structural snapshots without body text, input values, or URL secrets", async () => {
71
+ document.title = "Order for customer@example.com";
72
+ document.body.insertAdjacentHTML("beforeend", "<p>Private customer notes should not be copied wholesale.</p>");
73
+ const executor = new EditorCommandExecutor(controller());
74
+
75
+ const current = await executor.execute(command("current_url"));
76
+ const snapshot = await executor.execute(command("snapshot"));
77
+ const account = await executor.execute(command("select_element", { selector: "#account" }));
78
+ const serialized = JSON.stringify(snapshot.result);
79
+
80
+ expect(current.result).toMatchObject({
81
+ url: "http://localhost:3000/products/one",
82
+ originalUrl: "http://localhost:3000/products/one",
83
+ });
84
+ expect(snapshot.result).toMatchObject({
85
+ snapshot: expect.objectContaining({
86
+ title: "Order for [redacted]",
87
+ url: "http://localhost:3000/products/one",
88
+ bodyTextLength: expect.any(Number),
89
+ }),
90
+ });
91
+ expect(serialized).not.toContain("bodyText\":");
92
+ expect(serialized).not.toContain("customer@example.com");
93
+ expect(serialized).not.toContain("Private customer notes");
94
+ expect(account.result).toMatchObject({
95
+ element: expect.objectContaining({ href: "http://localhost:3000/account" }),
96
+ });
97
+ });
98
+
99
+ it("redacts console arguments and network resource metadata", async () => {
100
+ vi.spyOn(console, "log").mockImplementation(() => {});
101
+ const executor = new EditorCommandExecutor(controller());
102
+ executor.start();
103
+ console.log("customer@example.com +49 123 456 789 token=super-secret", {
104
+ authorization: "Bearer private-token",
105
+ endpoint: "https://api.example/orders?customer=42#receipt",
106
+ nested: { password: "hunter2" },
107
+ });
108
+ (executor as unknown as { networkLogs: Array<Record<string, unknown>> }).networkLogs.push({
109
+ url: "https://shop.example/cart.js?session=secret#response",
110
+ type: "resource",
111
+ token: "private-token",
112
+ duration: 12,
113
+ });
114
+
115
+ const consoleResult = await executor.execute(command("console_logs"));
116
+ const networkResult = await executor.execute(command("network_logs"));
117
+ const consoleJson = JSON.stringify(consoleResult.result);
118
+ const networkJson = JSON.stringify(networkResult.result);
119
+
120
+ expect(consoleJson).toContain("[redacted]");
121
+ expect(consoleJson).toContain("https://api.example/orders");
122
+ expect(consoleJson).not.toContain("customer@example.com");
123
+ expect(consoleJson).not.toContain("123 456 789");
124
+ expect(consoleJson).not.toContain("super-secret");
125
+ expect(consoleJson).not.toContain("private-token");
126
+ expect(consoleJson).not.toContain("hunter2");
127
+ expect(consoleJson).not.toContain("customer=42");
128
+ expect(networkJson).toContain("https://shop.example/cart.js");
129
+ expect(networkJson).not.toContain("session=secret");
130
+ expect(networkJson).not.toContain("private-token");
131
+ executor.stop();
132
+ });
133
+
134
+ it("rejects eval_readonly on live origins and delegates full artifacts", async () => {
135
+ const liveController = controller();
136
+ const executor = new EditorCommandExecutor(liveController);
137
+
138
+ const evaluated = await executor.execute(command("eval_readonly", { code: "document.title" }));
139
+ const artifacts = { mutations: [{ selector: "#title", action: "setText", text: "Draft" }], customCss: "", customJs: "" };
140
+ const applied = await executor.execute(command("apply_artifacts", { artifacts }));
141
+
142
+ expect(evaluated.result).toMatchObject({
143
+ ok: false,
144
+ error: expect.stringContaining("unsupported on live merchant origins"),
145
+ });
146
+ expect(liveController.applyCommandArtifacts).toHaveBeenCalledWith(artifacts);
147
+ expect(applied.result.ok).toBe(true);
148
+ });
149
+
150
+ it("uses allowlisted declarative inspection instead of JavaScript evaluation", async () => {
151
+ const executor = new EditorCommandExecutor(controller("http://localhost:3000"));
152
+ await expect(executor.execute(command("eval_readonly", { operation: "document_title" }))).resolves.toMatchObject({
153
+ result: { ok: true, operation: "document_title", result: "Live store" },
154
+ });
155
+ await expect(executor.execute(command("eval_readonly", {
156
+ operation: "element_count",
157
+ selector: "button",
158
+ }))).resolves.toMatchObject({
159
+ result: { ok: true, operation: "element_count", result: 1 },
160
+ });
161
+ await expect(executor.execute(command("eval_readonly", {
162
+ operation: "element_summary",
163
+ selector: "input",
164
+ }))).resolves.toMatchObject({
165
+ result: {
166
+ ok: true,
167
+ operation: "element_summary",
168
+ result: expect.objectContaining({ tag: "input", text: null }),
169
+ },
170
+ });
171
+ });
172
+
173
+ it("rejects executable code even for loopback sessions", async () => {
174
+ const executor = new EditorCommandExecutor(controller("http://localhost:3000"));
175
+ await expect(executor.execute(command("eval_readonly", {
176
+ code: "document.body.dataset.exfiltrated = document.querySelector('input').value",
177
+ }))).resolves.toMatchObject({
178
+ result: { ok: false, error: expect.stringContaining("JavaScript evaluation is disabled") },
179
+ });
180
+ expect(document.body.dataset.exfiltrated).toBeUndefined();
181
+ });
182
+ });
183
+
184
+ describe("EditorCommandPoller", () => {
185
+ beforeEach(() => vi.useFakeTimers());
186
+ afterEach(() => {
187
+ vi.useRealTimers();
188
+ vi.restoreAllMocks();
189
+ });
190
+
191
+ it("persists navigation completion before initiating hard navigation", async () => {
192
+ let resolveCompletion!: () => void;
193
+ const completion = new Promise<void>((resolve) => { resolveCompletion = resolve; });
194
+ const api = {
195
+ claimCommands: vi.fn()
196
+ .mockResolvedValueOnce([command("navigate", { url: "/collections/all?customer=42#private" })])
197
+ .mockResolvedValue([]),
198
+ completeCommand: vi.fn(() => completion),
199
+ } as unknown as EditorApi;
200
+ const navigate = vi.fn();
201
+ const executor = new EditorCommandExecutor(controller(), {
202
+ navigate,
203
+ reload: vi.fn(),
204
+ back: vi.fn(),
205
+ forward: vi.fn(),
206
+ });
207
+ const poller = new EditorCommandPoller(api, executor);
208
+
209
+ poller.start();
210
+ await Promise.resolve();
211
+ await Promise.resolve();
212
+ expect(api.completeCommand).toHaveBeenCalledWith("command-navigate", {
213
+ result: { ok: true, url: "https://shop.example/collections/all" },
214
+ });
215
+ expect(navigate).not.toHaveBeenCalled();
216
+
217
+ resolveCompletion();
218
+ await Promise.resolve();
219
+ await Promise.resolve();
220
+ expect(navigate).not.toHaveBeenCalled();
221
+ await vi.advanceTimersByTimeAsync(0);
222
+ expect(navigate).toHaveBeenCalledWith("https://shop.example/collections/all?customer=42#private");
223
+ poller.stop();
224
+ });
225
+ });