@notabene/javascript-sdk 1.34.0 → 2.0.0-next.10
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 +113 -231
- package/dist/notabene.cjs +1 -0
- package/dist/notabene.d.ts +780 -0
- package/dist/notabene.js +173 -0
- package/dist/tsdoc-metadata.json +11 -0
- package/package.json +38 -59
- package/src/__tests__/notabene.test.ts +159 -0
- package/src/arbitraries.ts +13 -0
- package/src/components/EmbeddedComponent.ts +185 -0
- package/src/components/__tests__/EmbeddedComponent.test.ts +160 -0
- package/src/ivms/types.ts +71 -28
- package/src/notabene.ts +155 -287
- package/src/types.ts +434 -67
- package/src/utils/MessageEventManager.ts +54 -0
- package/src/utils/__tests__/MessageEventManager.test.ts +95 -0
- package/src/utils/arbitraries.ts +26 -0
- package/src/utils/caip.ts +16 -0
- package/src/utils/urls.ts +15 -0
- package/.editorconfig +0 -10
- package/.envrc.template +0 -1
- package/.eslintignore +0 -3
- package/.eslintrc.js +0 -13
- package/.gitlab-ci.yml +0 -74
- package/.husky/commit-msg +0 -4
- package/.husky/pre-commit +0 -4
- package/.husky/pre-push +0 -4
- package/.nvmrc +0 -1
- package/.prettierrc +0 -4
- package/.releaserc.json +0 -16
- package/.tool-versions +0 -3
- package/.vscode/extensions.json +0 -7
- package/.vscode/settings.json +0 -11
- package/CODEOWNERS +0 -1
- package/dist/es/index.js +0 -1
- package/dist/lib/index.js +0 -376
- package/jest.config.js +0 -5
- package/public/index.html +0 -93
- package/public/js/.gitkeep +0 -0
- package/src/lib/index.ts +0 -2
- package/src/module/index.ts +0 -10
- package/src/zoidComponentProps.ts +0 -81
- package/tsconfig.json +0 -18
package/dist/notabene.js
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
var d = Object.defineProperty;
|
|
2
|
+
var c = (r, e, t) => e in r ? d(r, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : r[e] = t;
|
|
3
|
+
var n = (r, e, t) => c(r, typeof e != "symbol" ? e + "" : e, t);
|
|
4
|
+
var a = /* @__PURE__ */ ((r) => (r.COMPLETE = "complete", r.RESIZE = "resize", r.RESULT = "result", r.READY = "ready", r.INVALID = "invalid", r.MODAL = "openModal", r.ERROR = "error", r.CLOSE = "closeModal", r.CANCEL = "cancel", r))(a || {}), l = /* @__PURE__ */ ((r) => (r.UPDATE = "update", r.REQUEST_RESPONSE = "requestResponse", r))(l || {});
|
|
5
|
+
class m {
|
|
6
|
+
constructor() {
|
|
7
|
+
n(this, "listeners", /* @__PURE__ */ new Map());
|
|
8
|
+
n(this, "port");
|
|
9
|
+
this.handleMessage = this.handleMessage.bind(this);
|
|
10
|
+
}
|
|
11
|
+
setPort(e) {
|
|
12
|
+
this.port = e, this.port.onmessage = this.handleMessage, this.port.start();
|
|
13
|
+
}
|
|
14
|
+
on(e, t) {
|
|
15
|
+
this.listeners.has(e) || this.listeners.set(e, /* @__PURE__ */ new Set()), this.listeners.get(e).add(t);
|
|
16
|
+
}
|
|
17
|
+
off(e, t) {
|
|
18
|
+
const s = this.listeners.get(e);
|
|
19
|
+
s && (s.delete(t), s.size === 0 && this.listeners.delete(e));
|
|
20
|
+
}
|
|
21
|
+
handleMessage(e) {
|
|
22
|
+
console.log("received message", e.data);
|
|
23
|
+
const t = e.data;
|
|
24
|
+
if (typeof t == "object" && t !== null && "type" in t) {
|
|
25
|
+
const s = t.type, o = this.listeners.get(s);
|
|
26
|
+
o && o.forEach((i) => i(t));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
// Method to send messages through the port
|
|
30
|
+
send(e) {
|
|
31
|
+
this.port && this.port.postMessage(e);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
class u {
|
|
35
|
+
// private popup?: HTMLElement;
|
|
36
|
+
constructor(e, t) {
|
|
37
|
+
n(this, "_url");
|
|
38
|
+
n(this, "_value");
|
|
39
|
+
n(this, "_errors", []);
|
|
40
|
+
n(this, "iframe");
|
|
41
|
+
n(this, "eventManager");
|
|
42
|
+
n(this, "ready", !1);
|
|
43
|
+
n(this, "modal");
|
|
44
|
+
this._url = e, this._value = t, this.eventManager = new m(), this.on(a.INVALID, (s) => {
|
|
45
|
+
s.type === a.INVALID && (this._errors = s.errors, this._value = s.value);
|
|
46
|
+
}), this.on(a.RESIZE, (s) => {
|
|
47
|
+
s.type === a.RESIZE && this.iframe && (this.iframe.style.height = `${s.height}px`);
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
get url() {
|
|
51
|
+
return this._url;
|
|
52
|
+
}
|
|
53
|
+
get value() {
|
|
54
|
+
return this._value;
|
|
55
|
+
}
|
|
56
|
+
get errors() {
|
|
57
|
+
return this._errors;
|
|
58
|
+
}
|
|
59
|
+
open() {
|
|
60
|
+
document.location.href = this.url;
|
|
61
|
+
}
|
|
62
|
+
mount(e) {
|
|
63
|
+
const t = document.querySelector(e);
|
|
64
|
+
if (!t) throw new Error(`parentID ${e} not found`);
|
|
65
|
+
this.embed(t);
|
|
66
|
+
}
|
|
67
|
+
embed(e) {
|
|
68
|
+
var t, s;
|
|
69
|
+
this.iframe = document.createElement("iframe"), this.iframe.src = this.url, this.iframe.style.width = "100%", this.iframe.style.height = "100px", this.iframe.style.border = "none", this.iframe.style.overflow = "hidden", this.iframe.setAttribute("allowtransparency", "true"), this.iframe.style.backgroundColor = "transparent", e.appendChild(this.iframe), window.addEventListener("message", (o) => {
|
|
70
|
+
var i, h;
|
|
71
|
+
o.source === ((i = this.iframe) == null ? void 0 : i.contentWindow) && (console.log("received message from iframe", o.data), (h = this.eventManager) == null || h.setPort(o.ports[0]), this.ready = !0);
|
|
72
|
+
}), (s = (t = this.iframe) == null ? void 0 : t.contentWindow) == null || s.focus();
|
|
73
|
+
}
|
|
74
|
+
send(e) {
|
|
75
|
+
this.eventManager.send(e);
|
|
76
|
+
}
|
|
77
|
+
on(e, t) {
|
|
78
|
+
this.eventManager.on(e, t);
|
|
79
|
+
}
|
|
80
|
+
off(e, t) {
|
|
81
|
+
this.eventManager.off(e, t);
|
|
82
|
+
}
|
|
83
|
+
update(e) {
|
|
84
|
+
this._value = e, this.send({ type: l.UPDATE, value: e });
|
|
85
|
+
}
|
|
86
|
+
completion() {
|
|
87
|
+
return new Promise((e, t) => {
|
|
88
|
+
this.closeModal(), this.on(a.COMPLETE, (s) => {
|
|
89
|
+
e(s.response);
|
|
90
|
+
}), this.on("error", (s) => {
|
|
91
|
+
t(new Error(s.message));
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
// popup(): void {
|
|
96
|
+
// this.popup = document.createElement('div');
|
|
97
|
+
// this.popup.style;
|
|
98
|
+
// }
|
|
99
|
+
openModal() {
|
|
100
|
+
this.modal && this.closeModal(), this.modal = document.createElement("dialog"), document.body.appendChild(this.modal), this.embed(this.modal), this.on(a.CANCEL, () => {
|
|
101
|
+
this.closeModal();
|
|
102
|
+
}), this.on(a.CLOSE, () => {
|
|
103
|
+
this.closeModal();
|
|
104
|
+
}), this.on(a.COMPLETE, () => {
|
|
105
|
+
this.closeModal();
|
|
106
|
+
}), this.modal.showModal(), this.modal.addEventListener("click", () => {
|
|
107
|
+
this.closeModal();
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
closeModal() {
|
|
111
|
+
var e;
|
|
112
|
+
this.modal && (console.log("closeModal"), (e = this.modal) == null || e.close(), this.modal.remove(), this.modal = void 0);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function f(r) {
|
|
116
|
+
return Object.entries(r).map(([e, t]) => {
|
|
117
|
+
if (!(e && t)) return;
|
|
118
|
+
const s = encodeURIComponent(e), o = encodeURIComponent(
|
|
119
|
+
typeof t == "object" ? JSON.stringify(t) : t
|
|
120
|
+
);
|
|
121
|
+
return `${s}=${o}`;
|
|
122
|
+
}).filter((e) => !!e).join("&");
|
|
123
|
+
}
|
|
124
|
+
class E {
|
|
125
|
+
constructor(e) {
|
|
126
|
+
n(this, "nodeUrl");
|
|
127
|
+
n(this, "authToken");
|
|
128
|
+
n(this, "uxUrl");
|
|
129
|
+
n(this, "theme");
|
|
130
|
+
n(this, "locale");
|
|
131
|
+
this.uxUrl = e.uxUrl || "https://connect.notabene.id", this.nodeUrl = e.nodeUrl, this.authToken = e.authToken, this.theme = e.theme, this.locale = e.locale;
|
|
132
|
+
}
|
|
133
|
+
componentUrl(e, t, s, o) {
|
|
134
|
+
const i = new URL(this.uxUrl);
|
|
135
|
+
i.pathname = e;
|
|
136
|
+
const h = f({
|
|
137
|
+
authToken: this.authToken,
|
|
138
|
+
value: t,
|
|
139
|
+
configuration: s
|
|
140
|
+
});
|
|
141
|
+
return i.hash = h, this.nodeUrl && i.searchParams.set("nodeUrl", this.nodeUrl), this.theme && i.searchParams.set("theme", JSON.stringify(this.theme)), this.locale && i.searchParams.set("locale", this.locale), o && (o.callback && i.searchParams.set("callback_url", o.callback), o.redirectUri && i.searchParams.set("redirect_uri", o.redirectUri)), i.toString();
|
|
142
|
+
}
|
|
143
|
+
createComponent(e, t, s, o) {
|
|
144
|
+
return new u(
|
|
145
|
+
this.componentUrl(e, t, s, o),
|
|
146
|
+
t
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
createWithdrawalAssist(e, t, s) {
|
|
150
|
+
return this.createComponent("withdrawal-assist", e, t, s);
|
|
151
|
+
}
|
|
152
|
+
createDepositAssist(e, t, s) {
|
|
153
|
+
return this.createComponent("deposit-assist", e, t, s);
|
|
154
|
+
}
|
|
155
|
+
createConnect(e, t, s) {
|
|
156
|
+
return this.createComponent("connect", e, t, s);
|
|
157
|
+
}
|
|
158
|
+
createDepositRequest(e, t, s) {
|
|
159
|
+
return this.createComponent("deposit-request", e, t, s);
|
|
160
|
+
}
|
|
161
|
+
decodeFragmentToObject(e) {
|
|
162
|
+
return e.slice(1).split("&").reduce(
|
|
163
|
+
(s, o) => {
|
|
164
|
+
const [i, h] = o.split("=");
|
|
165
|
+
return s[decodeURIComponent(i)] = decodeURIComponent(h), s;
|
|
166
|
+
},
|
|
167
|
+
{}
|
|
168
|
+
);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
export {
|
|
172
|
+
E as default
|
|
173
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// This file is read by tools that parse documentation comments conforming to the TSDoc standard.
|
|
2
|
+
// It should be published with your NPM package. It should not be tracked by Git.
|
|
3
|
+
{
|
|
4
|
+
"tsdocVersion": "0.12",
|
|
5
|
+
"toolPackages": [
|
|
6
|
+
{
|
|
7
|
+
"packageName": "@microsoft/api-extractor",
|
|
8
|
+
"packageVersion": "7.47.7"
|
|
9
|
+
}
|
|
10
|
+
]
|
|
11
|
+
}
|
package/package.json
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@notabene/javascript-sdk",
|
|
3
|
+
"type": "module",
|
|
3
4
|
"description": "JavaScript SDK for Notabene",
|
|
4
5
|
"homepage": "https://gitlab.com/notabene/open-source/javascript-sdk",
|
|
5
6
|
"repository": {
|
|
@@ -8,74 +9,56 @@
|
|
|
8
9
|
},
|
|
9
10
|
"author": "Notabene <developers@notabene.id>",
|
|
10
11
|
"license": "MIT",
|
|
11
|
-
"version": "
|
|
12
|
-
"
|
|
13
|
-
"
|
|
12
|
+
"version": "2.0.0-next.10",
|
|
13
|
+
"source": "src/notabene.ts",
|
|
14
|
+
"main": "dist/notabene.js",
|
|
15
|
+
"types": "dist/notabene.d.ts",
|
|
14
16
|
"browserslist": "> 0.5%, last 2 versions, not dead",
|
|
15
|
-
"
|
|
16
|
-
"
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
},
|
|
22
|
-
"lib": {
|
|
23
|
-
"source": "src/lib/index.ts",
|
|
24
|
-
"isLibrary": true,
|
|
25
|
-
"context": "node",
|
|
26
|
-
"outputFormat": "commonjs"
|
|
27
|
-
}
|
|
28
|
-
},
|
|
29
|
-
"publishConfig": {
|
|
30
|
-
"access": "public"
|
|
31
|
-
},
|
|
32
|
-
"alias": {
|
|
33
|
-
"process": false,
|
|
34
|
-
"buffer": false
|
|
35
|
-
},
|
|
17
|
+
"files": [
|
|
18
|
+
"dist",
|
|
19
|
+
"src",
|
|
20
|
+
"package.json",
|
|
21
|
+
"README.md"
|
|
22
|
+
],
|
|
36
23
|
"scripts": {
|
|
37
24
|
"prepare": "husky install",
|
|
25
|
+
"dev": "vite",
|
|
26
|
+
"preview": "vite preview",
|
|
38
27
|
"watch": "parcel watch",
|
|
39
|
-
"dev": "sirv --dev --port 3002 public",
|
|
40
28
|
"build:dev": "yarn build && yarn dev",
|
|
41
|
-
"build": "
|
|
42
|
-
"build
|
|
43
|
-
"build:compile": "parcel build --no-source-maps && cp dist/es/index.js public/js/notabene.js",
|
|
29
|
+
"build:clean": "rimraf dist/ ts-out",
|
|
30
|
+
"build": "vite build && tsc && api-extractor run",
|
|
44
31
|
"lint": "eslint .",
|
|
45
|
-
"test": "
|
|
46
|
-
"release": "semantic-release"
|
|
32
|
+
"test": "vitest",
|
|
33
|
+
"release": "semantic-release",
|
|
34
|
+
"publish": "yarn build && npm publish --tag next"
|
|
47
35
|
},
|
|
48
36
|
"devDependencies": {
|
|
49
|
-
"@commitlint/cli": "^
|
|
50
|
-
"@commitlint/config-conventional": "^
|
|
51
|
-
"@
|
|
52
|
-
"@
|
|
37
|
+
"@commitlint/cli": "^19.4.0",
|
|
38
|
+
"@commitlint/config-conventional": "^19.2.2",
|
|
39
|
+
"@eslint/js": "^9.7.0",
|
|
40
|
+
"@fast-check/vitest": "^0.1.2",
|
|
41
|
+
"@microsoft/api-extractor": "^7.47.7",
|
|
53
42
|
"@semantic-release/git": "^10.0.1",
|
|
54
43
|
"@semantic-release/gitlab": "^9.3.0",
|
|
55
44
|
"@semantic-release/npm": "^9.0.1",
|
|
56
|
-
"@
|
|
57
|
-
"@typescript-eslint/
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"eslint": "^
|
|
61
|
-
"
|
|
62
|
-
"
|
|
63
|
-
"eslint-plugin-import": "^2.25.4",
|
|
64
|
-
"eslint-plugin-node": "^11.1.0",
|
|
65
|
-
"eslint-plugin-prettier": "^4.0.0",
|
|
66
|
-
"eslint-plugin-promise": "^6.0.0",
|
|
45
|
+
"@typescript-eslint/eslint-plugin": "^8.2.0",
|
|
46
|
+
"@typescript-eslint/parser": "^8.2.0",
|
|
47
|
+
"eslint": "^9.9.0",
|
|
48
|
+
"eslint-config-prettier": "^9.1.0",
|
|
49
|
+
"eslint-plugin-prettier": "^5.2.1",
|
|
50
|
+
"fast-check": "^3.20.0",
|
|
51
|
+
"globals": "^15.8.0",
|
|
67
52
|
"husky": "^7.0.4",
|
|
68
|
-
"jest": "^28.1.0",
|
|
69
53
|
"lint-staged": "^12.3.4",
|
|
70
54
|
"organize-imports-cli": "^0.9.0",
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
-
"
|
|
74
|
-
"
|
|
75
|
-
"
|
|
76
|
-
"
|
|
77
|
-
"
|
|
78
|
-
"typescript": "^4.7.2"
|
|
55
|
+
"prettier": "^3.3.3",
|
|
56
|
+
"rimraf": "^6.0.1",
|
|
57
|
+
"semantic-release": "^24.1.0",
|
|
58
|
+
"typescript": "^5.5.4",
|
|
59
|
+
"typescript-eslint": "^8.2.0",
|
|
60
|
+
"vite": "^5.4.2",
|
|
61
|
+
"vitest": "^2.0.5"
|
|
79
62
|
},
|
|
80
63
|
"lint-staged": {
|
|
81
64
|
"*.ts": [
|
|
@@ -87,9 +70,5 @@
|
|
|
87
70
|
"extends": [
|
|
88
71
|
"@commitlint/config-conventional"
|
|
89
72
|
]
|
|
90
|
-
},
|
|
91
|
-
"dependencies": {
|
|
92
|
-
"jsx-pragmatic": "^2.0.22",
|
|
93
|
-
"zoid": "^9.0.86"
|
|
94
73
|
}
|
|
95
|
-
}
|
|
74
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { fc, test } from '@fast-check/vitest';
|
|
2
|
+
import { describe } from 'vitest';
|
|
3
|
+
import { abitraryCallbackOptions, arbitraryComponent } from '../arbitraries';
|
|
4
|
+
import Notabene from '../notabene';
|
|
5
|
+
import { arbitraryLocale } from '../utils/arbitraries';
|
|
6
|
+
|
|
7
|
+
describe('Notabene', () => {
|
|
8
|
+
describe('defaults', () => {
|
|
9
|
+
test.prop([
|
|
10
|
+
fc.string({ minLength: 3 }),
|
|
11
|
+
fc.webUrl(),
|
|
12
|
+
arbitraryComponent(),
|
|
13
|
+
fc.object(),
|
|
14
|
+
])(
|
|
15
|
+
'Should set the correct values',
|
|
16
|
+
(authToken, nodeUrl, component, value) => {
|
|
17
|
+
const notabene = new Notabene({
|
|
18
|
+
nodeUrl,
|
|
19
|
+
authToken,
|
|
20
|
+
});
|
|
21
|
+
const url = new URL(notabene.componentUrl(component, value));
|
|
22
|
+
return (
|
|
23
|
+
url.hash ===
|
|
24
|
+
`#authToken=${encodeURIComponent(authToken)}&value=${encodeURIComponent(JSON.stringify(value))}` &&
|
|
25
|
+
url.searchParams.get('nodeUrl') === nodeUrl &&
|
|
26
|
+
url.pathname === `/${component}`
|
|
27
|
+
);
|
|
28
|
+
},
|
|
29
|
+
);
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
describe('locale', () => {
|
|
33
|
+
test.prop([
|
|
34
|
+
fc.string({ minLength: 3 }),
|
|
35
|
+
fc.webUrl(),
|
|
36
|
+
arbitraryComponent(),
|
|
37
|
+
fc.object(),
|
|
38
|
+
arbitraryLocale(),
|
|
39
|
+
])(
|
|
40
|
+
'Should set the correct values',
|
|
41
|
+
(authToken, nodeUrl, component, value, locale) => {
|
|
42
|
+
const notabene = new Notabene({
|
|
43
|
+
nodeUrl,
|
|
44
|
+
authToken,
|
|
45
|
+
locale,
|
|
46
|
+
});
|
|
47
|
+
const url = new URL(notabene.componentUrl(component, value));
|
|
48
|
+
return (
|
|
49
|
+
url.hash ===
|
|
50
|
+
`#authToken=${encodeURIComponent(authToken)}&value=${encodeURIComponent(JSON.stringify(value))}` &&
|
|
51
|
+
url.searchParams.get('nodeUrl') === nodeUrl &&
|
|
52
|
+
url.searchParams.get('locale') === locale &&
|
|
53
|
+
url.pathname === `/${component}`
|
|
54
|
+
);
|
|
55
|
+
},
|
|
56
|
+
);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
describe('minimal', () => {
|
|
60
|
+
test.prop([arbitraryComponent(), fc.object()])(
|
|
61
|
+
'Should set the correct values',
|
|
62
|
+
(component, value) => {
|
|
63
|
+
const notabene = new Notabene({});
|
|
64
|
+
const url = new URL(notabene.componentUrl(component, value));
|
|
65
|
+
return (
|
|
66
|
+
url.hash === `#value=${encodeURIComponent(JSON.stringify(value))}` &&
|
|
67
|
+
url.hostname === 'connect.notabene.id' &&
|
|
68
|
+
url.pathname === `/${component}`
|
|
69
|
+
);
|
|
70
|
+
},
|
|
71
|
+
);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
describe('with uxUrl', () => {
|
|
75
|
+
test.prop([
|
|
76
|
+
fc.string({ minLength: 3 }),
|
|
77
|
+
fc.webUrl(),
|
|
78
|
+
arbitraryComponent(),
|
|
79
|
+
fc.webAuthority(),
|
|
80
|
+
fc.object(),
|
|
81
|
+
])(
|
|
82
|
+
'Should set the correct values',
|
|
83
|
+
(authToken, nodeUrl, component, uxAuthority, value) => {
|
|
84
|
+
const notabene = new Notabene({
|
|
85
|
+
nodeUrl,
|
|
86
|
+
authToken,
|
|
87
|
+
uxUrl: `https://${uxAuthority}`,
|
|
88
|
+
});
|
|
89
|
+
const url = new URL(notabene.componentUrl(component, value));
|
|
90
|
+
const [domain, port] = uxAuthority.split(':');
|
|
91
|
+
return (
|
|
92
|
+
url.hostname === domain &&
|
|
93
|
+
url.port === (port || '') &&
|
|
94
|
+
url.hash ===
|
|
95
|
+
`#authToken=${encodeURIComponent(authToken)}&value=${encodeURIComponent(JSON.stringify(value))}` &&
|
|
96
|
+
url.searchParams.get('nodeUrl') === nodeUrl &&
|
|
97
|
+
url.pathname === `/${component}`
|
|
98
|
+
);
|
|
99
|
+
},
|
|
100
|
+
);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
describe('with value and configuration', () => {
|
|
104
|
+
test.prop([
|
|
105
|
+
fc.string({ minLength: 3 }),
|
|
106
|
+
fc.webUrl(),
|
|
107
|
+
arbitraryComponent(),
|
|
108
|
+
fc.object(),
|
|
109
|
+
fc.object(),
|
|
110
|
+
])(
|
|
111
|
+
'Should set the correct values',
|
|
112
|
+
(authToken, nodeUrl, component, value, configuration) => {
|
|
113
|
+
const notabene = new Notabene({
|
|
114
|
+
nodeUrl,
|
|
115
|
+
authToken,
|
|
116
|
+
});
|
|
117
|
+
const url = new URL(
|
|
118
|
+
notabene.componentUrl(component, value, configuration),
|
|
119
|
+
);
|
|
120
|
+
return (
|
|
121
|
+
url.hash ===
|
|
122
|
+
`#authToken=${encodeURIComponent(authToken)}&value=${encodeURIComponent(JSON.stringify(value))}&configuration=${encodeURIComponent(JSON.stringify(configuration))}` &&
|
|
123
|
+
url.searchParams.get('nodeUrl') === nodeUrl &&
|
|
124
|
+
url.pathname === `/${component}`
|
|
125
|
+
);
|
|
126
|
+
},
|
|
127
|
+
);
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
describe('with value and configuration', () => {
|
|
131
|
+
test.prop([
|
|
132
|
+
fc.string({ minLength: 3 }),
|
|
133
|
+
fc.webUrl(),
|
|
134
|
+
arbitraryComponent(),
|
|
135
|
+
fc.object(),
|
|
136
|
+
fc.object(),
|
|
137
|
+
abitraryCallbackOptions(),
|
|
138
|
+
])(
|
|
139
|
+
'Should set the correct values',
|
|
140
|
+
(authToken, nodeUrl, component, value, configuration, callbacks) => {
|
|
141
|
+
const notabene = new Notabene({
|
|
142
|
+
nodeUrl,
|
|
143
|
+
authToken,
|
|
144
|
+
});
|
|
145
|
+
const url = new URL(
|
|
146
|
+
notabene.componentUrl(component, value, configuration, callbacks),
|
|
147
|
+
);
|
|
148
|
+
return (
|
|
149
|
+
url.hash ===
|
|
150
|
+
`#authToken=${encodeURIComponent(authToken)}&value=${encodeURIComponent(JSON.stringify(value))}&configuration=${encodeURIComponent(JSON.stringify(configuration))}` &&
|
|
151
|
+
url.searchParams.get('nodeUrl') === nodeUrl &&
|
|
152
|
+
url.pathname === `/${component}` &&
|
|
153
|
+
url.searchParams.get('callback_url') === callbacks.callback &&
|
|
154
|
+
url.searchParams.get('redirect_uri') === callbacks.redirectUri
|
|
155
|
+
);
|
|
156
|
+
},
|
|
157
|
+
);
|
|
158
|
+
});
|
|
159
|
+
});
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import fc from 'fast-check';
|
|
2
|
+
import { CallbackOptions } from './types';
|
|
3
|
+
|
|
4
|
+
const COMPONENT_MATCHER = /^[a-z0-9-_]+$/;
|
|
5
|
+
// Arbitraries
|
|
6
|
+
export const arbitraryComponent = (): fc.Arbitrary<string> =>
|
|
7
|
+
fc.stringMatching(COMPONENT_MATCHER);
|
|
8
|
+
|
|
9
|
+
export const abitraryCallbackOptions = (): fc.Arbitrary<CallbackOptions> =>
|
|
10
|
+
fc.record({
|
|
11
|
+
callback: fc.webUrl(),
|
|
12
|
+
redirectUri: fc.webUrl(),
|
|
13
|
+
});
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CMType,
|
|
3
|
+
HMType,
|
|
4
|
+
HostMessage,
|
|
5
|
+
Transaction,
|
|
6
|
+
TransactionResponse,
|
|
7
|
+
ValidationError,
|
|
8
|
+
} from '../types';
|
|
9
|
+
import {
|
|
10
|
+
MessageCallback,
|
|
11
|
+
MessageEventManager,
|
|
12
|
+
} from '../utils/MessageEventManager';
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* An embedded Notabene component
|
|
16
|
+
* @public
|
|
17
|
+
*/
|
|
18
|
+
export default class EmbeddedComponent {
|
|
19
|
+
private _url: string;
|
|
20
|
+
private _value: Partial<Transaction>;
|
|
21
|
+
private _errors: ValidationError[] = [];
|
|
22
|
+
|
|
23
|
+
private iframe?: HTMLIFrameElement;
|
|
24
|
+
private eventManager: MessageEventManager;
|
|
25
|
+
private ready = false;
|
|
26
|
+
private modal?: HTMLDialogElement;
|
|
27
|
+
// private popup?: HTMLElement;
|
|
28
|
+
|
|
29
|
+
constructor(url: string, value: Partial<Transaction>) {
|
|
30
|
+
this._url = url;
|
|
31
|
+
this._value = value;
|
|
32
|
+
this.eventManager = new MessageEventManager();
|
|
33
|
+
this.on(CMType.INVALID, (message) => {
|
|
34
|
+
if (message.type === CMType.INVALID) {
|
|
35
|
+
this._errors = message.errors;
|
|
36
|
+
this._value = message.value as Transaction;
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
this.on(CMType.RESIZE, (message) => {
|
|
40
|
+
if (message.type === CMType.RESIZE) {
|
|
41
|
+
if (this.iframe) this.iframe.style.height = `${message.height}px`;
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public get url(): string {
|
|
47
|
+
return this._url;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
public get value(): Partial<Transaction> {
|
|
51
|
+
return this._value;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
public get errors(): ValidationError[] {
|
|
55
|
+
return this._errors;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
public open() {
|
|
59
|
+
document.location.href = this.url;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
mount(parentId: string) {
|
|
63
|
+
const parent = document.querySelector(parentId);
|
|
64
|
+
if (!parent) throw new Error(`parentID ${parentId} not found`);
|
|
65
|
+
this.embed(parent);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
embed(parent: Element) {
|
|
69
|
+
this.iframe = document.createElement('iframe');
|
|
70
|
+
this.iframe.src = this.url;
|
|
71
|
+
this.iframe.style.width = '100%';
|
|
72
|
+
this.iframe.style.height = '100px';
|
|
73
|
+
this.iframe.style.border = 'none';
|
|
74
|
+
this.iframe.style.overflow = 'hidden';
|
|
75
|
+
this.iframe.setAttribute('allowtransparency', 'true');
|
|
76
|
+
this.iframe.style.backgroundColor = 'transparent';
|
|
77
|
+
parent.appendChild(this.iframe);
|
|
78
|
+
|
|
79
|
+
window.addEventListener('message', (event: MessageEvent) => {
|
|
80
|
+
if (event.source !== this.iframe?.contentWindow) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
console.log('received message from iframe', event.data);
|
|
84
|
+
this.eventManager?.setPort(event.ports[0]);
|
|
85
|
+
this.ready = true;
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
this.iframe?.contentWindow?.focus();
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
send(message: HostMessage): void {
|
|
92
|
+
this.eventManager.send(message);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
on(messageType: string, callback: MessageCallback): void {
|
|
96
|
+
this.eventManager.on(messageType, callback);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
off(messageType: string, callback: MessageCallback): void {
|
|
100
|
+
this.eventManager.off(messageType, callback);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
update(value: Partial<Transaction>) {
|
|
104
|
+
this._value = value;
|
|
105
|
+
this.send({ type: HMType.UPDATE, value });
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
completion(): Promise<TransactionResponse> {
|
|
109
|
+
return new Promise((resolve, reject) => {
|
|
110
|
+
this.closeModal();
|
|
111
|
+
this.on(CMType.COMPLETE, (message) => {
|
|
112
|
+
resolve((message as any).response);
|
|
113
|
+
});
|
|
114
|
+
this.on('error', (message) => {
|
|
115
|
+
reject(new Error((message as any).message));
|
|
116
|
+
});
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
// popup(): void {
|
|
121
|
+
// this.popup = document.createElement('div');
|
|
122
|
+
// this.popup.style;
|
|
123
|
+
// }
|
|
124
|
+
|
|
125
|
+
openModal(): void {
|
|
126
|
+
if (this.modal) {
|
|
127
|
+
this.closeModal();
|
|
128
|
+
}
|
|
129
|
+
this.modal = document.createElement('dialog');
|
|
130
|
+
// this.modal.style.maxWidth = '600px';
|
|
131
|
+
// this.modal.style.border = 'none !important';
|
|
132
|
+
// this.modal.style.background = 'transparent';
|
|
133
|
+
// this.modal.style.flexDirection = 'column';
|
|
134
|
+
// this.modal.style.alignItems = 'end';
|
|
135
|
+
// const close = document.createElement('button');
|
|
136
|
+
// close.innerText = 'X';
|
|
137
|
+
// close.style.fontSize = '1rem';
|
|
138
|
+
// close.style.padding = '0.25rem 0.5rem';
|
|
139
|
+
// close.style.display = 'block';
|
|
140
|
+
// close.style.background = 'white';
|
|
141
|
+
// close.style.color = '#aaa';
|
|
142
|
+
// close.style.border = '#aaa';
|
|
143
|
+
// close.addEventListener('click', () => this.closeModal());
|
|
144
|
+
// this.modal.appendChild(close);
|
|
145
|
+
// this.modal.css;
|
|
146
|
+
// this.modal.style.position = 'fixed';
|
|
147
|
+
// this.modal.style.bottom = '0';
|
|
148
|
+
// this.modal.style.left = '0';
|
|
149
|
+
// this.modal.style.right = '0';
|
|
150
|
+
// this.modal.style.top = '0';
|
|
151
|
+
// this.modal.style.left = '0';
|
|
152
|
+
// this.modal.style.width = '100%';
|
|
153
|
+
// this.modal.style.height = '100%';
|
|
154
|
+
// this.modal.style.backgroundColor = 'transparent';
|
|
155
|
+
// this.modal.style.display = 'flex';
|
|
156
|
+
// this.modal.style.justifyContent = 'center';
|
|
157
|
+
// this.modal.style.alignItems = 'center';
|
|
158
|
+
document.body.appendChild(this.modal);
|
|
159
|
+
this.embed(this.modal);
|
|
160
|
+
this.on(CMType.CANCEL, () => {
|
|
161
|
+
this.closeModal();
|
|
162
|
+
});
|
|
163
|
+
this.on(CMType.CLOSE, () => {
|
|
164
|
+
this.closeModal();
|
|
165
|
+
});
|
|
166
|
+
this.on(CMType.COMPLETE, () => {
|
|
167
|
+
this.closeModal();
|
|
168
|
+
});
|
|
169
|
+
|
|
170
|
+
this.modal.showModal();
|
|
171
|
+
this.modal.addEventListener('click', () => {
|
|
172
|
+
// console.log('click');
|
|
173
|
+
this.closeModal();
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
private closeModal(): void {
|
|
178
|
+
if (this.modal) {
|
|
179
|
+
console.log('closeModal');
|
|
180
|
+
this.modal?.close();
|
|
181
|
+
this.modal.remove();
|
|
182
|
+
this.modal = undefined;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|