@encatch/event-publisher 0.0.2-beta.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 +62 -0
- package/dist/event-publisher.js +111 -0
- package/dist/event-publisher.umd.cjs +1 -0
- package/dist/index.d.ts +90 -0
- package/package.json +29 -0
package/README.md
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# @encatch/event-publisher
|
|
2
|
+
|
|
3
|
+
Internal package for publishing and subscribing to form events across the Encatch ecosystem.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
This is an internal package. Add it to your package dependencies:
|
|
8
|
+
|
|
9
|
+
```json
|
|
10
|
+
{
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@encatch/event-publisher": "workspace:*"
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
import { formEventPublisher } from '@encatch/event-publisher';
|
|
21
|
+
|
|
22
|
+
// Subscribe to form submit events
|
|
23
|
+
const unsubscribe = formEventPublisher.subscribe('form:submit', (payload) => {
|
|
24
|
+
console.log('Form submitted:', payload);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
// Subscribe with form ID filter
|
|
28
|
+
formEventPublisher.subscribe(
|
|
29
|
+
'form:submit',
|
|
30
|
+
(payload) => {
|
|
31
|
+
console.log('Specific form submitted:', payload);
|
|
32
|
+
},
|
|
33
|
+
{ formId: 'specific-form-id' }
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
// Publish an event
|
|
37
|
+
formEventPublisher.publish('form:submit', {
|
|
38
|
+
feedbackConfigurationId: 'form-id',
|
|
39
|
+
response: { /* form data */ },
|
|
40
|
+
timestamp: Date.now()
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
// Unsubscribe when done
|
|
44
|
+
unsubscribe();
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## API
|
|
48
|
+
|
|
49
|
+
### Types
|
|
50
|
+
|
|
51
|
+
- `FormEventType`: Event types ('form:view', 'form:submit', 'form:close', etc.)
|
|
52
|
+
- `FormEventPayload`: Payload types for each event
|
|
53
|
+
- `FormIdFilter`: Filter for specific form IDs
|
|
54
|
+
- `SubscriptionOptions`: Options for subscriptions
|
|
55
|
+
|
|
56
|
+
### Methods
|
|
57
|
+
|
|
58
|
+
- `publish<T>(eventType: T, payload: FormEventPayload[T], options?)`: Publish an event
|
|
59
|
+
- `subscribe<T>(eventType: T, handler: Function, options?)`: Subscribe to events
|
|
60
|
+
- `subscribeAll(handler: Function, options?)`: Subscribe to all event types
|
|
61
|
+
- `getSubscriptionCount(eventType?)`: Get active subscription count
|
|
62
|
+
- `clearSubscriptions(eventType?)`: Clear subscriptions
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
class d extends EventTarget {
|
|
2
|
+
subscriptions = /* @__PURE__ */ new Map();
|
|
3
|
+
targetOrigin = "*";
|
|
4
|
+
/**
|
|
5
|
+
* Check if a form ID matches the filter
|
|
6
|
+
*/
|
|
7
|
+
matchesFilter(s, i) {
|
|
8
|
+
return !i || i === "*" || i === null || i === void 0 ? !0 : typeof i == "string" ? s === i : Array.isArray(i) ? i.includes(s || "") : typeof i == "function" ? i(s || "") : !1;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Get form ID from payload
|
|
12
|
+
*/
|
|
13
|
+
getFormIdFromPayload(s) {
|
|
14
|
+
return s?.feedbackConfigurationId;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Publish an event to all matching subscribers
|
|
18
|
+
*/
|
|
19
|
+
publish(s, i, e) {
|
|
20
|
+
typeof window < "u" && window.dispatchEvent(
|
|
21
|
+
new CustomEvent(s, {
|
|
22
|
+
detail: i,
|
|
23
|
+
bubbles: !0
|
|
24
|
+
})
|
|
25
|
+
), e?.usePostMessage !== !1 && this.sendPostMessage(s, i);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Subscribe to form events with optional form ID filtering
|
|
29
|
+
*/
|
|
30
|
+
subscribe(s, i, e) {
|
|
31
|
+
const n = Symbol("subscription"), t = {
|
|
32
|
+
eventType: s,
|
|
33
|
+
handler: i,
|
|
34
|
+
filter: e?.formId,
|
|
35
|
+
id: n,
|
|
36
|
+
once: e?.once
|
|
37
|
+
};
|
|
38
|
+
this.subscriptions.has(s) || this.subscriptions.set(s, []), this.subscriptions.get(s).push(t);
|
|
39
|
+
const r = (o) => {
|
|
40
|
+
const c = o, u = this.getFormIdFromPayload(c.detail);
|
|
41
|
+
this.matchesFilter(u, e?.formId) && (i(c.detail), e?.once && typeof window < "u" && window.removeEventListener(s, r));
|
|
42
|
+
};
|
|
43
|
+
return typeof window < "u" && window.addEventListener(s, r), () => {
|
|
44
|
+
this.unsubscribe(n), typeof window < "u" && window.removeEventListener(s, r);
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Unsubscribe by subscription ID
|
|
49
|
+
*/
|
|
50
|
+
unsubscribe(s) {
|
|
51
|
+
for (const [i, e] of this.subscriptions.entries()) {
|
|
52
|
+
const n = e.findIndex((t) => t.id === s);
|
|
53
|
+
if (n !== -1) {
|
|
54
|
+
e.splice(n, 1), e.length === 0 && this.subscriptions.delete(i);
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Subscribe to all form events with optional filtering
|
|
61
|
+
*/
|
|
62
|
+
subscribeAll(s, i) {
|
|
63
|
+
const e = [
|
|
64
|
+
"form:view",
|
|
65
|
+
"form:submit",
|
|
66
|
+
"form:close",
|
|
67
|
+
"form:section:change",
|
|
68
|
+
"form:question:answered",
|
|
69
|
+
"form:error"
|
|
70
|
+
], n = [];
|
|
71
|
+
return e.forEach((t) => {
|
|
72
|
+
const r = this.subscribe(
|
|
73
|
+
t,
|
|
74
|
+
(o) => s(t, o),
|
|
75
|
+
i
|
|
76
|
+
);
|
|
77
|
+
n.push(r);
|
|
78
|
+
}), () => {
|
|
79
|
+
n.forEach((t) => t());
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Get active subscriptions count (for debugging)
|
|
84
|
+
*/
|
|
85
|
+
getSubscriptionCount(s) {
|
|
86
|
+
return s ? this.subscriptions.get(s)?.length || 0 : Array.from(this.subscriptions.values()).reduce((i, e) => i + e.length, 0);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Clear all subscriptions for an event type (or all events)
|
|
90
|
+
*/
|
|
91
|
+
clearSubscriptions(s) {
|
|
92
|
+
s ? this.subscriptions.delete(s) : this.subscriptions.clear();
|
|
93
|
+
}
|
|
94
|
+
sendPostMessage(s, i) {
|
|
95
|
+
const e = {
|
|
96
|
+
type: `encatch:${s}`,
|
|
97
|
+
payload: i,
|
|
98
|
+
source: "encatch-form-engine"
|
|
99
|
+
};
|
|
100
|
+
window.parent && window.parent !== window && window.parent.postMessage(e, this.targetOrigin), document.querySelectorAll("iframe").forEach((t) => {
|
|
101
|
+
t.contentWindow && t.contentWindow.postMessage(e, this.targetOrigin);
|
|
102
|
+
}), typeof window.ReactNativeWebView < "u" && window.ReactNativeWebView.postMessage(JSON.stringify({
|
|
103
|
+
action: s.replace("form:", ""),
|
|
104
|
+
data: JSON.stringify(i)
|
|
105
|
+
}));
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
const f = new d();
|
|
109
|
+
export {
|
|
110
|
+
f as formEventPublisher
|
|
111
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(o,r){typeof exports=="object"&&typeof module<"u"?r(exports):typeof define=="function"&&define.amd?define(["exports"],r):(o=typeof globalThis<"u"?globalThis:o||self,r(o.EventPublisher={}))})(this,(function(o){"use strict";class r extends EventTarget{subscriptions=new Map;targetOrigin="*";matchesFilter(e,s){return!s||s==="*"||s===null||s===void 0?!0:typeof s=="string"?e===s:Array.isArray(s)?s.includes(e||""):typeof s=="function"?s(e||""):!1}getFormIdFromPayload(e){return e?.feedbackConfigurationId}publish(e,s,i){typeof window<"u"&&window.dispatchEvent(new CustomEvent(e,{detail:s,bubbles:!0})),i?.usePostMessage!==!1&&this.sendPostMessage(e,s)}subscribe(e,s,i){const n=Symbol("subscription"),t={eventType:e,handler:s,filter:i?.formId,id:n,once:i?.once};this.subscriptions.has(e)||this.subscriptions.set(e,[]),this.subscriptions.get(e).push(t);const u=c=>{const d=c,a=this.getFormIdFromPayload(d.detail);this.matchesFilter(a,i?.formId)&&(s(d.detail),i?.once&&typeof window<"u"&&window.removeEventListener(e,u))};return typeof window<"u"&&window.addEventListener(e,u),()=>{this.unsubscribe(n),typeof window<"u"&&window.removeEventListener(e,u)}}unsubscribe(e){for(const[s,i]of this.subscriptions.entries()){const n=i.findIndex(t=>t.id===e);if(n!==-1){i.splice(n,1),i.length===0&&this.subscriptions.delete(s);break}}}subscribeAll(e,s){const i=["form:view","form:submit","form:close","form:section:change","form:question:answered","form:error"],n=[];return i.forEach(t=>{const u=this.subscribe(t,c=>e(t,c),s);n.push(u)}),()=>{n.forEach(t=>t())}}getSubscriptionCount(e){return e?this.subscriptions.get(e)?.length||0:Array.from(this.subscriptions.values()).reduce((s,i)=>s+i.length,0)}clearSubscriptions(e){e?this.subscriptions.delete(e):this.subscriptions.clear()}sendPostMessage(e,s){const i={type:`encatch:${e}`,payload:s,source:"encatch-form-engine"};window.parent&&window.parent!==window&&window.parent.postMessage(i,this.targetOrigin),document.querySelectorAll("iframe").forEach(t=>{t.contentWindow&&t.contentWindow.postMessage(i,this.targetOrigin)}),typeof window.ReactNativeWebView<"u"&&window.ReactNativeWebView.postMessage(JSON.stringify({action:e.replace("form:",""),data:JSON.stringify(s)}))}}const f=new r;o.formEventPublisher=f,Object.defineProperty(o,Symbol.toStringTag,{value:"Module"})}));
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
export declare type FormEventPayload = {
|
|
2
|
+
'form:view': {
|
|
3
|
+
feedbackConfigurationId: string;
|
|
4
|
+
feedbackIdentifier?: string;
|
|
5
|
+
timestamp: number;
|
|
6
|
+
};
|
|
7
|
+
'form:submit': {
|
|
8
|
+
feedbackConfigurationId: string;
|
|
9
|
+
feedbackIdentifier?: string;
|
|
10
|
+
response: any;
|
|
11
|
+
timestamp: number;
|
|
12
|
+
};
|
|
13
|
+
'form:close': {
|
|
14
|
+
feedbackConfigurationId?: string;
|
|
15
|
+
feedbackIdentifier?: string;
|
|
16
|
+
timestamp: number;
|
|
17
|
+
};
|
|
18
|
+
'form:section:change': {
|
|
19
|
+
feedbackConfigurationId: string;
|
|
20
|
+
sectionIndex: number;
|
|
21
|
+
sectionId: string;
|
|
22
|
+
timestamp: number;
|
|
23
|
+
};
|
|
24
|
+
'form:question:answered': {
|
|
25
|
+
feedbackConfigurationId: string;
|
|
26
|
+
questionId: string;
|
|
27
|
+
questionType: string;
|
|
28
|
+
answer: any;
|
|
29
|
+
timestamp: number;
|
|
30
|
+
};
|
|
31
|
+
'form:error': {
|
|
32
|
+
feedbackConfigurationId: string;
|
|
33
|
+
questionId?: string;
|
|
34
|
+
error: string;
|
|
35
|
+
timestamp: number;
|
|
36
|
+
};
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
declare class FormEventPublisher extends EventTarget {
|
|
40
|
+
private subscriptions;
|
|
41
|
+
private targetOrigin;
|
|
42
|
+
/**
|
|
43
|
+
* Check if a form ID matches the filter
|
|
44
|
+
*/
|
|
45
|
+
private matchesFilter;
|
|
46
|
+
/**
|
|
47
|
+
* Get form ID from payload
|
|
48
|
+
*/
|
|
49
|
+
private getFormIdFromPayload;
|
|
50
|
+
/**
|
|
51
|
+
* Publish an event to all matching subscribers
|
|
52
|
+
*/
|
|
53
|
+
publish<T extends FormEventType>(eventType: T, payload: FormEventPayload[T], options?: {
|
|
54
|
+
usePostMessage?: boolean;
|
|
55
|
+
}): void;
|
|
56
|
+
/**
|
|
57
|
+
* Subscribe to form events with optional form ID filtering
|
|
58
|
+
*/
|
|
59
|
+
subscribe<T extends FormEventType>(eventType: T, handler: (payload: FormEventPayload[T]) => void, options?: SubscriptionOptions): () => void;
|
|
60
|
+
/**
|
|
61
|
+
* Unsubscribe by subscription ID
|
|
62
|
+
*/
|
|
63
|
+
private unsubscribe;
|
|
64
|
+
/**
|
|
65
|
+
* Subscribe to all form events with optional filtering
|
|
66
|
+
*/
|
|
67
|
+
subscribeAll(handler: (eventType: FormEventType, payload: any) => void, options?: SubscriptionOptions): () => void;
|
|
68
|
+
/**
|
|
69
|
+
* Get active subscriptions count (for debugging)
|
|
70
|
+
*/
|
|
71
|
+
getSubscriptionCount(eventType?: FormEventType): number;
|
|
72
|
+
/**
|
|
73
|
+
* Clear all subscriptions for an event type (or all events)
|
|
74
|
+
*/
|
|
75
|
+
clearSubscriptions(eventType?: FormEventType): void;
|
|
76
|
+
private sendPostMessage;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export declare const formEventPublisher: FormEventPublisher;
|
|
80
|
+
|
|
81
|
+
export declare type FormEventType = 'form:view' | 'form:submit' | 'form:close' | 'form:section:change' | 'form:question:answered' | 'form:error';
|
|
82
|
+
|
|
83
|
+
export declare type FormIdFilter = string | string[] | ((formId: string) => boolean) | '*' | null | undefined;
|
|
84
|
+
|
|
85
|
+
export declare interface SubscriptionOptions {
|
|
86
|
+
formId?: FormIdFilter;
|
|
87
|
+
once?: boolean;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export { }
|
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@encatch/event-publisher",
|
|
3
|
+
"version": "0.0.2-beta.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"main": "./dist/event-publisher.umd.cjs",
|
|
6
|
+
"module": "./dist/event-publisher.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/event-publisher.js",
|
|
12
|
+
"require": "./dist/event-publisher.umd.cjs"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist"
|
|
17
|
+
],
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"@types/node": "^24.6.0",
|
|
20
|
+
"typescript": "~5.9.3",
|
|
21
|
+
"vite": "^7.1.7",
|
|
22
|
+
"vite-plugin-dts": "^4.3.0"
|
|
23
|
+
},
|
|
24
|
+
"scripts": {
|
|
25
|
+
"dev": "vite",
|
|
26
|
+
"build": "vite build && tsc --emitDeclarationOnly --declaration",
|
|
27
|
+
"clean": "rm -rf dist"
|
|
28
|
+
}
|
|
29
|
+
}
|