@askdialog/dialog-sdk 2.1.0 → 2.3.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 +17 -4
- package/dist/Dialog.d.ts +2 -8
- package/dist/Dialog.d.ts.map +1 -1
- package/dist/Dialog.js +25 -10
- package/dist/__tests__/windowAudit.spec.d.ts +2 -0
- package/dist/__tests__/windowAudit.spec.d.ts.map +1 -0
- package/dist/__tests__/windowAudit.spec.js +87 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/types/events.d.ts +32 -1
- package/dist/types/events.d.ts.map +1 -1
- package/dist/types/global.d.ts +3 -1
- package/dist/types/global.d.ts.map +1 -1
- package/dist/windowAudit.d.ts +41 -0
- package/dist/windowAudit.d.ts.map +1 -0
- package/dist/windowAudit.js +78 -0
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -338,12 +338,25 @@ client.registerAddToCartEvent({
|
|
|
338
338
|
price: '12.00' // {string} - Optional
|
|
339
339
|
});
|
|
340
340
|
|
|
341
|
+
// Checkout is order-level: call ONCE per completed order with the order total.
|
|
342
|
+
// `orderValue` is what the "Revenue generated" dashboard reads.
|
|
343
|
+
// Do NOT call this per line item — without an order total, revenue resolves to 0.
|
|
341
344
|
client.registerSubmitCheckoutEvent({
|
|
342
|
-
|
|
343
|
-
quantity: 1, // {number} - Required
|
|
344
|
-
price: '12.00', // {string} - Required
|
|
345
|
+
orderValue: 59.98, // {number} - Required - the order total
|
|
345
346
|
currency: 'EUR', // {string} - Optional
|
|
346
|
-
|
|
347
|
+
transactionId: 'OrderIdentifier', // {string} - Optional - order id, used to de-duplicate reloads
|
|
348
|
+
items: [ // {array} - Optional - line items, for product-level attribution only
|
|
349
|
+
{ productId: 'ProductIdentifier', quantity: 1, price: 29.99, variantId: 'VariantIdentifier' },
|
|
350
|
+
],
|
|
351
|
+
});
|
|
352
|
+
|
|
353
|
+
// Deprecated per-line signature — still accepted for backward compatibility,
|
|
354
|
+
// but carries no order total so revenue cannot be computed. Prefer the call above.
|
|
355
|
+
client.registerSubmitCheckoutEvent({
|
|
356
|
+
productId: 'ProductIdentifier',
|
|
357
|
+
quantity: 1,
|
|
358
|
+
price: '12.00',
|
|
359
|
+
currency: 'EUR',
|
|
347
360
|
});
|
|
348
361
|
```
|
|
349
362
|
|
package/dist/Dialog.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { DialogConstructor } from "./types/constructor";
|
|
|
2
2
|
import { Theme } from "./types/theme";
|
|
3
3
|
import { DetailedLocaleInfo } from "./utils/localization";
|
|
4
4
|
import { Suggestion } from "./types/suggestion";
|
|
5
|
-
import { GenericQuestionPayload, OpenAssistantPayload, ProductQuestionPayload } from "./types/events";
|
|
5
|
+
import { GenericQuestionPayload, LegacyCheckoutParams, OpenAssistantPayload, ProductQuestionPayload, SubmitCheckoutParams } from "./types/events";
|
|
6
6
|
import { SimplifiedProduct } from "./types/product";
|
|
7
7
|
import { EventsHandler } from "./EventsHandler";
|
|
8
8
|
import { AssistantEvent } from "./types/assistantEvent";
|
|
@@ -45,13 +45,7 @@ export declare class Dialog {
|
|
|
45
45
|
currency?: string;
|
|
46
46
|
variantId?: string;
|
|
47
47
|
}): void;
|
|
48
|
-
registerSubmitCheckoutEvent(
|
|
49
|
-
productId: string;
|
|
50
|
-
quantity: number;
|
|
51
|
-
price: string;
|
|
52
|
-
currency?: string;
|
|
53
|
-
variantId?: string;
|
|
54
|
-
}): void;
|
|
48
|
+
registerSubmitCheckoutEvent(params: SubmitCheckoutParams | LegacyCheckoutParams): void;
|
|
55
49
|
private _loadAssistant;
|
|
56
50
|
}
|
|
57
51
|
//# sourceMappingURL=Dialog.d.ts.map
|
package/dist/Dialog.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Dialog.d.ts","sourceRoot":"","sources":["../src/Dialog.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EACL,kBAAkB,EAEnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAEL,sBAAsB,EACtB,oBAAoB,EACpB,sBAAsB,
|
|
1
|
+
{"version":3,"file":"Dialog.d.ts","sourceRoot":"","sources":["../src/Dialog.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AACtC,OAAO,EACL,kBAAkB,EAEnB,MAAM,sBAAsB,CAAC;AAE9B,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAEL,sBAAsB,EACtB,oBAAoB,EACpB,oBAAoB,EACpB,sBAAsB,EACtB,oBAAoB,EACrB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGhD,OAAO,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAExD,qBAAa,MAAM;IACjB,gBAAuB,OAAO,SAAuB;IAErD,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,YAAY,CAAC,CAAS;IAE9B,OAAO,CAAC,UAAU,CAGhB;IACF,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,cAAc,CAAgB;gBAE1B,EACV,MAAM,EACN,MAAM,EACN,WAAW,EACX,SAAS,EACT,KAAK,EACL,MAAM,GACP,EAAE,iBAAiB;IAYpB,IAAW,MAAM,IAAI,MAAM,CAE1B;IACD,IAAW,KAAK,IAAI,KAAK,CAExB;IACD,IAAW,MAAM,IAAI,MAAM,CAE1B;IACD,IAAW,MAAM,IAAI,MAAM,CAE1B;IACD,IAAW,aAAa,IAAI,aAAa,CAExC;IAEM,2BAA2B,IAAI,kBAAkB,GAAG,IAAI;IAI/D,OAAO,CAAC,uBAAuB;IAkBlB,cAAc,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAK5D,aAAa,CAAC,MAAM,EAAE,oBAAoB,GAAG,IAAI;IAKjD,cAAc,IAAI,IAAI;IAItB,kBAAkB,CAAC,MAAM,EAAE,sBAAsB,GAAG,IAAI;IAIxD,kBAAkB,CAAC,MAAM,EAAE,sBAAsB,GAAG,IAAI;IAOxD,gBAAgB,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,GAAG,IAAI;IAIjE,sBAAsB,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI;IAInD,UAAU,CACf,SAAS,EAAE,MAAM,EACjB,SAAS,CAAC,EAAE,MAAM,GACjB,OAAO,CAAC,iBAAiB,CAAC;IAIhB,SAAS,CAAC,EACrB,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,KAAK,GACN,EAAE;QACD,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBV,sBAAsB,CAAC,EAC5B,SAAS,EACT,QAAQ,EACR,QAAQ,EACR,SAAS,EACT,KAAK,GACN,EAAE;QACD,SAAS,EAAE,MAAM,CAAC;QAClB,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,GAAG,IAAI;IAkBD,2BAA2B,CAChC,MAAM,EAAE,oBAAoB,GAAG,oBAAoB,GAClD,IAAI;IA0BP,OAAO,CAAC,cAAc;CA4BvB"}
|
package/dist/Dialog.js
CHANGED
|
@@ -8,6 +8,7 @@ import { DialogEvents, } from "./types/events";
|
|
|
8
8
|
import { EventsHandler } from "./EventsHandler";
|
|
9
9
|
import { loadSuggestions } from "./services/suggestions";
|
|
10
10
|
import { config } from "./config";
|
|
11
|
+
import { exposeSdkOnWindowDialog } from "./windowAudit";
|
|
11
12
|
export class Dialog {
|
|
12
13
|
static VERSION = packageJson.version;
|
|
13
14
|
_apiKey;
|
|
@@ -25,10 +26,7 @@ export class Dialog {
|
|
|
25
26
|
this._theme = { ...defaultTheme, ...theme };
|
|
26
27
|
this._userId = this._createOrRetrieveUserId(userId);
|
|
27
28
|
this._eventsHandler = new EventsHandler(locale, userId);
|
|
28
|
-
|
|
29
|
-
instance: this,
|
|
30
|
-
version: Dialog.VERSION,
|
|
31
|
-
};
|
|
29
|
+
exposeSdkOnWindowDialog(this, Dialog.VERSION);
|
|
32
30
|
this._loadAssistant();
|
|
33
31
|
}
|
|
34
32
|
get apiKey() {
|
|
@@ -115,14 +113,31 @@ export class Dialog {
|
|
|
115
113
|
currency,
|
|
116
114
|
});
|
|
117
115
|
}
|
|
118
|
-
|
|
116
|
+
// Order-level: call ONCE per completed order with the order total.
|
|
117
|
+
// `orderValue` is what the dashboard's "Revenue generated" reads — do not
|
|
118
|
+
// call this per line item (that has no total and revenue resolves to 0).
|
|
119
|
+
//
|
|
120
|
+
// The legacy per-line signature (`{ productId, quantity, price }`) is still
|
|
121
|
+
// accepted for backward compatibility so existing installs keep working
|
|
122
|
+
// after an upgrade, but it is deprecated: it carries no order total.
|
|
123
|
+
registerSubmitCheckoutEvent(params) {
|
|
124
|
+
if ("orderValue" in params) {
|
|
125
|
+
this._eventsHandler.emitExternalEvent(DialogEvents.TRACK_SUBMIT_CHECKOUT, {
|
|
126
|
+
userId: this._userId,
|
|
127
|
+
orderValue: params.orderValue,
|
|
128
|
+
currency: params.currency,
|
|
129
|
+
transactionId: params.transactionId,
|
|
130
|
+
items: params.items,
|
|
131
|
+
});
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
119
134
|
this._eventsHandler.emitExternalEvent(DialogEvents.TRACK_SUBMIT_CHECKOUT, {
|
|
120
135
|
userId: this._userId,
|
|
121
|
-
productId,
|
|
122
|
-
variantId,
|
|
123
|
-
quantity,
|
|
124
|
-
price,
|
|
125
|
-
currency,
|
|
136
|
+
productId: params.productId,
|
|
137
|
+
variantId: params.variantId,
|
|
138
|
+
quantity: params.quantity,
|
|
139
|
+
price: params.price,
|
|
140
|
+
currency: params.currency,
|
|
126
141
|
});
|
|
127
142
|
}
|
|
128
143
|
_loadAssistant() {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"windowAudit.spec.d.ts","sourceRoot":"","sources":["../../src/__tests__/windowAudit.spec.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
|
+
import { addAuditCapability, exposeSdkOnWindowDialog, registerDialogInstallation, } from "../windowAudit";
|
|
3
|
+
const globalWithWindow = globalThis;
|
|
4
|
+
const getAudit = () => globalWithWindow.window?.dialog?.audit;
|
|
5
|
+
const fakeInstance = { apiKey: "test" };
|
|
6
|
+
beforeEach(() => {
|
|
7
|
+
globalWithWindow.window = {};
|
|
8
|
+
});
|
|
9
|
+
afterEach(() => {
|
|
10
|
+
delete globalWithWindow.window;
|
|
11
|
+
vi.clearAllMocks();
|
|
12
|
+
});
|
|
13
|
+
describe("exposeSdkOnWindowDialog", () => {
|
|
14
|
+
it("exposes instance and version when window.dialog is absent", () => {
|
|
15
|
+
exposeSdkOnWindowDialog(fakeInstance, "2.1.0");
|
|
16
|
+
const dialog = globalWithWindow.window?.dialog;
|
|
17
|
+
expect(dialog?.instance).toBe(fakeInstance);
|
|
18
|
+
expect(dialog?.version).toBe("2.1.0");
|
|
19
|
+
expect(getAudit()?.methods[0]).toMatchObject({
|
|
20
|
+
method: "sdk",
|
|
21
|
+
version: "2.1.0",
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
it("preserves keys owned by GTM (setVariant/getVariant/_queue)", () => {
|
|
25
|
+
const setVariant = vi.fn();
|
|
26
|
+
const getVariant = vi.fn();
|
|
27
|
+
const queue = [["setVariant", { variantId: "VAR_1" }]];
|
|
28
|
+
globalWithWindow.window = {
|
|
29
|
+
dialog: { setVariant, getVariant, _queue: queue },
|
|
30
|
+
};
|
|
31
|
+
exposeSdkOnWindowDialog(fakeInstance, "2.1.0");
|
|
32
|
+
const dialog = globalWithWindow.window.dialog;
|
|
33
|
+
expect(dialog?.setVariant).toBe(setVariant);
|
|
34
|
+
expect(dialog?.getVariant).toBe(getVariant);
|
|
35
|
+
expect(dialog?._queue).toBe(queue);
|
|
36
|
+
expect(dialog?.instance).toBe(fakeInstance);
|
|
37
|
+
expect(getAudit()?.methods[0]).toMatchObject({
|
|
38
|
+
method: "sdk",
|
|
39
|
+
version: "2.1.0",
|
|
40
|
+
});
|
|
41
|
+
});
|
|
42
|
+
it("preserves audit entries registered by another path and warns on coexistence", () => {
|
|
43
|
+
registerDialogInstallation({ method: "gtm", source: "dialog-instant.js" });
|
|
44
|
+
exposeSdkOnWindowDialog(fakeInstance, "2.1.0");
|
|
45
|
+
const audit = getAudit();
|
|
46
|
+
expect(audit?.methods.map((entry) => entry.method)).toEqual(["gtm", "sdk"]);
|
|
47
|
+
expect(audit?.warnings).toEqual([
|
|
48
|
+
"multiple installation methods detected: gtm, sdk",
|
|
49
|
+
]);
|
|
50
|
+
});
|
|
51
|
+
it("does not duplicate the sdk entry when instantiated twice", () => {
|
|
52
|
+
exposeSdkOnWindowDialog(fakeInstance, "2.1.0");
|
|
53
|
+
exposeSdkOnWindowDialog(fakeInstance, "2.1.0");
|
|
54
|
+
expect(getAudit()?.methods).toHaveLength(1);
|
|
55
|
+
});
|
|
56
|
+
it("is a no-op without a window (SSR safety)", () => {
|
|
57
|
+
delete globalWithWindow.window;
|
|
58
|
+
expect(() => exposeSdkOnWindowDialog(fakeInstance, "2.1.0")).not.toThrow();
|
|
59
|
+
expect(() => addAuditCapability("pdp-block")).not.toThrow();
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
describe("registerDialogInstallation", () => {
|
|
63
|
+
it("only fills missing fields on re-registration of the same method", () => {
|
|
64
|
+
registerDialogInstallation({ method: "react", version: "2.0.2" });
|
|
65
|
+
registerDialogInstallation({ method: "react", version: "9.9.9" });
|
|
66
|
+
expect(getAudit()?.methods).toHaveLength(1);
|
|
67
|
+
expect(getAudit()?.methods[0]?.version).toBe("2.0.2");
|
|
68
|
+
});
|
|
69
|
+
it("fills missing nested build fields without erasing existing ones", () => {
|
|
70
|
+
registerDialogInstallation({ method: "gtm", build: { commit: "abc1234" } });
|
|
71
|
+
registerDialogInstallation({
|
|
72
|
+
method: "gtm",
|
|
73
|
+
build: { commit: "fff9999", version: "1.2.3" },
|
|
74
|
+
});
|
|
75
|
+
expect(getAudit()?.methods[0]?.build).toEqual({
|
|
76
|
+
commit: "abc1234",
|
|
77
|
+
version: "1.2.3",
|
|
78
|
+
});
|
|
79
|
+
});
|
|
80
|
+
});
|
|
81
|
+
describe("addAuditCapability", () => {
|
|
82
|
+
it("adds capabilities without duplicates", () => {
|
|
83
|
+
addAuditCapability("pdp-block");
|
|
84
|
+
addAuditCapability("pdp-block");
|
|
85
|
+
expect(getAudit()?.capabilities).toEqual(["pdp-block"]);
|
|
86
|
+
});
|
|
87
|
+
});
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,iBAAiB,CAAC;AAChC,cAAc,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,UAAU,CAAC;AACzB,cAAc,iBAAiB,CAAC;AAChC,cAAc,SAAS,CAAC;AACxB,cAAc,eAAe,CAAC"}
|
package/dist/index.js
CHANGED
package/dist/types/events.d.ts
CHANGED
|
@@ -42,7 +42,38 @@ export interface TrackEventPayload {
|
|
|
42
42
|
price?: string;
|
|
43
43
|
currency?: string;
|
|
44
44
|
}
|
|
45
|
-
export
|
|
45
|
+
export interface CheckoutLineItem {
|
|
46
|
+
productId: string;
|
|
47
|
+
variantId?: string;
|
|
48
|
+
quantity: number;
|
|
49
|
+
price?: number;
|
|
50
|
+
}
|
|
51
|
+
export interface SubmitCheckoutEventPayload {
|
|
52
|
+
userId?: string;
|
|
53
|
+
orderValue: number;
|
|
54
|
+
currency?: string;
|
|
55
|
+
transactionId?: string;
|
|
56
|
+
items?: CheckoutLineItem[];
|
|
57
|
+
}
|
|
58
|
+
export interface SubmitCheckoutParams {
|
|
59
|
+
orderValue: number;
|
|
60
|
+
currency?: string;
|
|
61
|
+
transactionId?: string;
|
|
62
|
+
items?: CheckoutLineItem[];
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* @deprecated Per-line checkout has no order total, so "Revenue generated"
|
|
66
|
+
* resolves to 0. Pass the order total via {@link SubmitCheckoutParams} instead,
|
|
67
|
+
* once per completed order.
|
|
68
|
+
*/
|
|
69
|
+
export interface LegacyCheckoutParams {
|
|
70
|
+
productId: string;
|
|
71
|
+
quantity: number;
|
|
72
|
+
price?: string;
|
|
73
|
+
currency?: string;
|
|
74
|
+
variantId?: string;
|
|
75
|
+
}
|
|
76
|
+
export type DialogEventPayload = ProductQuestionPayload | GenericQuestionPayload | DiagnosticPayload | OpenAssistantPayload | TrackEventPayload | SubmitCheckoutEventPayload;
|
|
46
77
|
export interface DialogEvent<T = DialogEventPayload> {
|
|
47
78
|
type: DialogEvents;
|
|
48
79
|
payload: T;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/types/events.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,+BAA+B,CAAC;AAEhE,oBAAY,YAAY;IACtB,cAAc,mBAAmB;IACjC,eAAe,oBAAoB;IACnC,YAAY,qBAAqB;IACjC,qBAAqB,qBAAqB;IAC1C,iBAAiB,sBAAsB;IACvC,qBAAqB,0BAA0B;CAChD;AACD,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAC;CAClB;AACD,MAAM,WAAW,sBAAuB,SAAQ,sBAAsB;IACpE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,MAAM,oBAAoB,GAAG,mBAAmB,GAAG,cAAc,CAAC;AAExE,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,UAAU,EAAE,oBAAoB,CAAC;IACjC,GAAG,EAAE,MAAM,CAAC;CACb;
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/types/events.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,+BAA+B,CAAC;AAEhE,oBAAY,YAAY;IACtB,cAAc,mBAAmB;IACjC,eAAe,oBAAoB;IACnC,YAAY,qBAAqB;IACjC,qBAAqB,qBAAqB;IAC1C,iBAAiB,sBAAsB;IACvC,qBAAqB,0BAA0B;CAChD;AACD,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAC;CAClB;AACD,MAAM,WAAW,sBAAuB,SAAQ,sBAAsB;IACpE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B;AAED,MAAM,MAAM,oBAAoB,GAAG,mBAAmB,GAAG,cAAc,CAAC;AAExE,MAAM,WAAW,iBAAiB;IAChC,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,UAAU,EAAE,oBAAoB,CAAC;IACjC,GAAG,EAAE,MAAM,CAAC;CACb;AAQD,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAKD,MAAM,WAAW,gBAAgB;IAC/B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAOD,MAAM,WAAW,0BAA0B;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,gBAAgB,EAAE,CAAC;CAC5B;AAGD,MAAM,WAAW,oBAAoB;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,gBAAgB,EAAE,CAAC;CAC5B;AAED;;;;GAIG;AACH,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,kBAAkB,GAC1B,sBAAsB,GACtB,sBAAsB,GACtB,iBAAiB,GACjB,oBAAoB,GACpB,iBAAiB,GACjB,0BAA0B,CAAC;AAE/B,MAAM,WAAW,WAAW,CAAC,CAAC,GAAG,kBAAkB;IACjD,IAAI,EAAE,YAAY,CAAC;IACnB,OAAO,EAAE,CAAC,CAAC;CACZ"}
|
package/dist/types/global.d.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { Dialog } from "../Dialog";
|
|
2
|
+
import { DialogAudit } from "../windowAudit";
|
|
2
3
|
declare global {
|
|
3
4
|
interface Window {
|
|
4
5
|
dialog?: {
|
|
5
6
|
instance?: Dialog;
|
|
6
7
|
version?: string;
|
|
7
|
-
|
|
8
|
+
audit?: DialogAudit;
|
|
9
|
+
} & Record<string, unknown>;
|
|
8
10
|
}
|
|
9
11
|
}
|
|
10
12
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"global.d.ts","sourceRoot":"","sources":["../../src/types/global.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"global.d.ts","sourceRoot":"","sources":["../../src/types/global.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACnC,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,MAAM;QAGd,MAAM,CAAC,EAAE;YACP,QAAQ,CAAC,EAAE,MAAM,CAAC;YAClB,OAAO,CAAC,EAAE,MAAM,CAAC;YACjB,KAAK,CAAC,EAAE,WAAW,CAAC;SACrB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KAC7B;CACF;AAED,OAAO,EAAE,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { Dialog } from "./Dialog";
|
|
2
|
+
/**
|
|
3
|
+
* Miniature copy of the window.dialog.audit merge helper — canonical source:
|
|
4
|
+
* dialog-ecom/packages/lib-dialog-window (contract: dialogAuditSchema in
|
|
5
|
+
* dialog-ecom's @dialog/shared-schemas). Kept in sync by hand: the surface is
|
|
6
|
+
* public and additive-only — never overwrite keys owned by other installation
|
|
7
|
+
* paths (GTM setVariant/getVariant/_queue, widget audit entries).
|
|
8
|
+
*/
|
|
9
|
+
export type DialogInstallationMethod = "shopify-extension" | "gtm" | "sdk" | "react" | "vue" | "prestashop";
|
|
10
|
+
export type DialogAuditCapability = "setVariant" | "assistant-modal" | "assistant-bar" | "pdp-block";
|
|
11
|
+
export interface DialogAuditMethodEntry {
|
|
12
|
+
method: DialogInstallationMethod;
|
|
13
|
+
version?: string;
|
|
14
|
+
build?: {
|
|
15
|
+
version?: string;
|
|
16
|
+
commit?: string;
|
|
17
|
+
};
|
|
18
|
+
source?: string;
|
|
19
|
+
registeredAt: string;
|
|
20
|
+
}
|
|
21
|
+
export interface DialogAudit {
|
|
22
|
+
methods: DialogAuditMethodEntry[];
|
|
23
|
+
context: {
|
|
24
|
+
hostname?: string;
|
|
25
|
+
platform?: string;
|
|
26
|
+
organizationSlug?: string;
|
|
27
|
+
};
|
|
28
|
+
capabilities: DialogAuditCapability[];
|
|
29
|
+
consent?: unknown;
|
|
30
|
+
warnings: string[];
|
|
31
|
+
}
|
|
32
|
+
export type DialogInstallationEntryInput = Omit<DialogAuditMethodEntry, "registeredAt">;
|
|
33
|
+
export declare const registerDialogInstallation: (entry: DialogInstallationEntryInput) => void;
|
|
34
|
+
export declare const addAuditCapability: (capability: DialogAuditCapability) => void;
|
|
35
|
+
/**
|
|
36
|
+
* Exposes the SDK on window.dialog without erasing fields owned by other
|
|
37
|
+
* installation paths (e.g. GTM's setVariant/getVariant), then registers the
|
|
38
|
+
* sdk entry in window.dialog.audit.
|
|
39
|
+
*/
|
|
40
|
+
export declare const exposeSdkOnWindowDialog: (instance: Dialog, version: string) => void;
|
|
41
|
+
//# sourceMappingURL=windowAudit.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"windowAudit.d.ts","sourceRoot":"","sources":["../src/windowAudit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,UAAU,CAAC;AAEvC;;;;;;GAMG;AACH,MAAM,MAAM,wBAAwB,GAChC,mBAAmB,GACnB,KAAK,GACL,KAAK,GACL,OAAO,GACP,KAAK,GACL,YAAY,CAAC;AAEjB,MAAM,MAAM,qBAAqB,GAC7B,YAAY,GACZ,iBAAiB,GACjB,eAAe,GACf,WAAW,CAAC;AAEhB,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,wBAAwB,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE;QAAE,OAAO,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC9C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,sBAAsB,EAAE,CAAC;IAClC,OAAO,EAAE;QACP,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,gBAAgB,CAAC,EAAE,MAAM,CAAC;KAC3B,CAAC;IACF,YAAY,EAAE,qBAAqB,EAAE,CAAC;IACtC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,MAAM,EAAE,CAAC;CACpB;AAED,MAAM,MAAM,4BAA4B,GAAG,IAAI,CAC7C,sBAAsB,EACtB,cAAc,CACf,CAAC;AAwDF,eAAO,MAAM,0BAA0B,GACrC,OAAO,4BAA4B,KAClC,IAmBF,CAAC;AAEF,eAAO,MAAM,kBAAkB,GAAI,YAAY,qBAAqB,KAAG,IAQtE,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,uBAAuB,GAClC,UAAU,MAAM,EAChB,SAAS,MAAM,KACd,IAUF,CAAC"}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
const MULTIPLE_METHODS_WARNING_PREFIX = "multiple installation methods detected:";
|
|
2
|
+
const getHost = () => typeof window === "undefined"
|
|
3
|
+
? undefined
|
|
4
|
+
: window;
|
|
5
|
+
const ensureAudit = () => {
|
|
6
|
+
const host = getHost();
|
|
7
|
+
if (host === undefined) {
|
|
8
|
+
return undefined;
|
|
9
|
+
}
|
|
10
|
+
host.dialog = host.dialog ?? {};
|
|
11
|
+
host.dialog.audit = host.dialog.audit ?? {
|
|
12
|
+
methods: [],
|
|
13
|
+
context: {},
|
|
14
|
+
capabilities: [],
|
|
15
|
+
warnings: [],
|
|
16
|
+
};
|
|
17
|
+
return host.dialog.audit;
|
|
18
|
+
};
|
|
19
|
+
const refreshCoexistenceWarning = (audit) => {
|
|
20
|
+
audit.warnings = audit.warnings.filter((warning) => !warning.startsWith(MULTIPLE_METHODS_WARNING_PREFIX));
|
|
21
|
+
if (audit.methods.length >= 2) {
|
|
22
|
+
const methods = audit.methods.map((entry) => entry.method).join(", ");
|
|
23
|
+
audit.warnings.push(`${MULTIPLE_METHODS_WARNING_PREFIX} ${methods}`);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
// First write wins per nested field: an existing partial build (e.g. commit
|
|
27
|
+
// only) never blocks a later registration from filling the missing fields.
|
|
28
|
+
const mergeBuildFields = (existing, entry) => {
|
|
29
|
+
if (entry === undefined) {
|
|
30
|
+
return existing;
|
|
31
|
+
}
|
|
32
|
+
return {
|
|
33
|
+
version: existing?.version ?? entry.version,
|
|
34
|
+
commit: existing?.commit ?? entry.commit,
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
export const registerDialogInstallation = (entry) => {
|
|
38
|
+
const audit = ensureAudit();
|
|
39
|
+
if (audit === undefined) {
|
|
40
|
+
return;
|
|
41
|
+
}
|
|
42
|
+
const existing = audit.methods.find((candidate) => candidate.method === entry.method);
|
|
43
|
+
if (existing === undefined) {
|
|
44
|
+
audit.methods.push({ ...entry, registeredAt: new Date().toISOString() });
|
|
45
|
+
refreshCoexistenceWarning(audit);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
// First write wins per field: a later registration only fills gaps and
|
|
49
|
+
// never erases what another script recorded.
|
|
50
|
+
existing.version = existing.version ?? entry.version;
|
|
51
|
+
existing.build = mergeBuildFields(existing.build, entry.build);
|
|
52
|
+
existing.source = existing.source ?? entry.source;
|
|
53
|
+
};
|
|
54
|
+
export const addAuditCapability = (capability) => {
|
|
55
|
+
const audit = ensureAudit();
|
|
56
|
+
if (audit === undefined) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (!audit.capabilities.includes(capability)) {
|
|
60
|
+
audit.capabilities.push(capability);
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Exposes the SDK on window.dialog without erasing fields owned by other
|
|
65
|
+
* installation paths (e.g. GTM's setVariant/getVariant), then registers the
|
|
66
|
+
* sdk entry in window.dialog.audit.
|
|
67
|
+
*/
|
|
68
|
+
export const exposeSdkOnWindowDialog = (instance, version) => {
|
|
69
|
+
if (typeof window === "undefined") {
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
window.dialog = {
|
|
73
|
+
...window.dialog,
|
|
74
|
+
instance,
|
|
75
|
+
version,
|
|
76
|
+
};
|
|
77
|
+
registerDialogInstallation({ method: "sdk", version });
|
|
78
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@askdialog/dialog-sdk",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.3.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Dialog SDK",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -28,7 +28,8 @@
|
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"esbuild": "^0.25.12",
|
|
30
30
|
"eslint-import-resolver-typescript": "^4.4.4",
|
|
31
|
-
"eslint-plugin-import": "^2.32.0"
|
|
31
|
+
"eslint-plugin-import": "^2.32.0",
|
|
32
|
+
"vitest": "^3.0.0"
|
|
32
33
|
},
|
|
33
34
|
"publishConfig": {
|
|
34
35
|
"access": "public"
|
|
@@ -44,6 +45,7 @@
|
|
|
44
45
|
"build:prod": "pnpm run clean && pnpm run set-config production && tsc",
|
|
45
46
|
"lint": "eslint .",
|
|
46
47
|
"lint:fix": "eslint . --fix",
|
|
48
|
+
"test": "vitest run",
|
|
47
49
|
"test-type": "tsc --noEmit",
|
|
48
50
|
"link": "pnpm link --global",
|
|
49
51
|
"unlink": "pnpm unlink",
|