@omnizapi/connect 1.0.0 → 1.0.2
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/CHANGELOG.md +36 -0
- package/LICENSE +21 -0
- package/README.md +75 -27
- package/dist/cjs/index.js +338 -124
- package/dist/esm/index.mjs +338 -124
- package/dist/omnizapi.min.js +1 -1
- package/dist/types/src/core/client.d.ts +1 -1
- package/dist/types/src/core/facebook-sdk.d.ts +11 -0
- package/dist/types/src/core/runtime.d.ts +18 -0
- package/dist/types/src/types/index.d.ts +3 -2
- package/examples/angular.ts +58 -0
- package/examples/basic.ts +52 -0
- package/examples/error-handling.ts +92 -0
- package/examples/react.tsx +75 -0
- package/examples/vanilla.html +60 -0
- package/examples/vue.vue +61 -0
- package/examples/with-options.ts +70 -0
- package/package.json +12 -3
package/dist/esm/index.mjs
CHANGED
|
@@ -65,12 +65,22 @@ var getConstants = ({
|
|
|
65
65
|
// src/core/runtime.ts
|
|
66
66
|
var runtimeKey = /* @__PURE__ */ Symbol.for("omnizapi.connect.runtime.v1");
|
|
67
67
|
function getRuntime(host) {
|
|
68
|
+
var _a, _b, _c;
|
|
68
69
|
const target = host;
|
|
69
70
|
let runtime = target[runtimeKey];
|
|
70
71
|
if (!runtime) {
|
|
71
|
-
runtime = {
|
|
72
|
+
runtime = {
|
|
73
|
+
nativeLoginPending: false,
|
|
74
|
+
failedFacebookScripts: /* @__PURE__ */ new WeakSet(),
|
|
75
|
+
erroredFacebookScripts: /* @__PURE__ */ new WeakSet(),
|
|
76
|
+
facebookAppIds: /* @__PURE__ */ new WeakMap(),
|
|
77
|
+
facebookInitObservers: /* @__PURE__ */ new WeakMap()
|
|
78
|
+
};
|
|
72
79
|
Object.defineProperty(target, runtimeKey, { configurable: true, value: runtime });
|
|
73
80
|
}
|
|
81
|
+
(_a = runtime.facebookAppIds) != null ? _a : runtime.facebookAppIds = /* @__PURE__ */ new WeakMap();
|
|
82
|
+
(_b = runtime.facebookInitObservers) != null ? _b : runtime.facebookInitObservers = /* @__PURE__ */ new WeakMap();
|
|
83
|
+
(_c = runtime.erroredFacebookScripts) != null ? _c : runtime.erroredFacebookScripts = /* @__PURE__ */ new WeakSet();
|
|
74
84
|
return runtime;
|
|
75
85
|
}
|
|
76
86
|
|
|
@@ -78,108 +88,238 @@ function getRuntime(host) {
|
|
|
78
88
|
function isReadySdk(sdk) {
|
|
79
89
|
return !!sdk && !("__buffer" in sdk) && typeof sdk.init === "function" && typeof sdk.login === "function";
|
|
80
90
|
}
|
|
91
|
+
function observeFacebookInit(runtime, fb) {
|
|
92
|
+
var _a;
|
|
93
|
+
try {
|
|
94
|
+
const descriptor = Object.getOwnPropertyDescriptor(fb, "init");
|
|
95
|
+
const existing = runtime.facebookInitObservers.get(fb);
|
|
96
|
+
if (existing) {
|
|
97
|
+
if ((descriptor == null ? void 0 : descriptor.value) !== existing.init) throw new Error("FB.init was replaced.");
|
|
98
|
+
return existing;
|
|
99
|
+
}
|
|
100
|
+
if (!descriptor || typeof descriptor.value !== "function" || !descriptor.writable && !descriptor.configurable) {
|
|
101
|
+
throw new Error("FB.init cannot be observed.");
|
|
102
|
+
}
|
|
103
|
+
const original = descriptor.value;
|
|
104
|
+
const observer = {
|
|
105
|
+
calls: 0,
|
|
106
|
+
init: function(...args) {
|
|
107
|
+
observer.calls++;
|
|
108
|
+
runtime.facebookAppIds.delete(fb);
|
|
109
|
+
return Reflect.apply(original, this, args);
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
Object.defineProperty(fb, "init", { ...descriptor, value: observer.init });
|
|
113
|
+
if (((_a = Object.getOwnPropertyDescriptor(fb, "init")) == null ? void 0 : _a.value) !== observer.init) throw new Error("FB.init was not replaced.");
|
|
114
|
+
runtime.facebookInitObservers.set(fb, observer);
|
|
115
|
+
return observer;
|
|
116
|
+
} catch (e) {
|
|
117
|
+
runtime.facebookAppIds.delete(fb);
|
|
118
|
+
throw new OmnizapiError(
|
|
119
|
+
"INVALID_CONFIGURATION",
|
|
120
|
+
"The Meta SDK initialization cannot be observed safely. Use the popup flow or reload a fresh page."
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
function initializeFacebookSdk(host, fb, appId) {
|
|
125
|
+
var _a;
|
|
126
|
+
if (host.FB !== fb || !fb || "__buffer" in fb || typeof fb.login !== "function") {
|
|
127
|
+
throw new OmnizapiError("INVALID_CONFIGURATION", "The Meta SDK is not ready or was replaced before initialization.");
|
|
128
|
+
}
|
|
129
|
+
if (typeof appId !== "string" || !/^[0-9]+$/.test(appId)) {
|
|
130
|
+
throw new OmnizapiError("INVALID_CONFIGURATION", "A numeric Meta appId is required for native login.");
|
|
131
|
+
}
|
|
132
|
+
const runtime = getRuntime(host);
|
|
133
|
+
if (runtime.facebookAppIds.get(fb) === null && (runtime.facebookLoadUncertain || runtime.facebookLoading || typeof host.fbAsyncInit === "function")) {
|
|
134
|
+
runtime.facebookAppIds.delete(fb);
|
|
135
|
+
}
|
|
136
|
+
const initializedAppId = runtime.facebookAppIds.get(fb);
|
|
137
|
+
if (initializedAppId === void 0 || initializedAppId !== null && !runtime.facebookInitObservers.has(fb)) {
|
|
138
|
+
runtime.facebookAppIds.delete(fb);
|
|
139
|
+
throw new OmnizapiError(
|
|
140
|
+
"INVALID_CONFIGURATION",
|
|
141
|
+
"The host Meta SDK configuration is unknown. Use the popup flow or a fresh page without a host-initialized SDK for native login."
|
|
142
|
+
);
|
|
143
|
+
}
|
|
144
|
+
const observer = observeFacebookInit(runtime, fb);
|
|
145
|
+
if (initializedAppId !== null) {
|
|
146
|
+
if (initializedAppId !== appId) {
|
|
147
|
+
throw new OmnizapiError(
|
|
148
|
+
"INVALID_CONFIGURATION",
|
|
149
|
+
"The Meta SDK is already initialized for another app. Use the popup flow or reload a fresh page before changing apps."
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
const calls = observer.calls;
|
|
155
|
+
runtime.facebookAppIds.delete(fb);
|
|
156
|
+
try {
|
|
157
|
+
fb.init({ appId, version: "v25.0", autoLogAppEvents: true, xfbml: true });
|
|
158
|
+
} catch (e) {
|
|
159
|
+
throw new OmnizapiError("PROVIDER_ERROR", "The Meta SDK could not be initialized.");
|
|
160
|
+
}
|
|
161
|
+
if (observer.calls !== calls + 1 || host.FB !== fb || ((_a = Object.getOwnPropertyDescriptor(fb, "init")) == null ? void 0 : _a.value) !== observer.init) {
|
|
162
|
+
throw new OmnizapiError("INVALID_CONFIGURATION", "The Meta SDK changed during initialization. Use the popup flow or reload a fresh page.");
|
|
163
|
+
}
|
|
164
|
+
runtime.facebookAppIds.set(fb, appId);
|
|
165
|
+
}
|
|
81
166
|
function loadFacebookSdk(host, signal) {
|
|
82
167
|
if (signal.aborted) {
|
|
83
168
|
return Promise.reject(new OmnizapiError("SDK_LOAD_FAILED", "The Meta SDK load was cancelled."));
|
|
84
169
|
}
|
|
85
|
-
if (isReadySdk(host.FB)) {
|
|
86
|
-
return Promise.resolve(host.FB);
|
|
87
|
-
}
|
|
88
170
|
const runtime = getRuntime(host);
|
|
89
|
-
|
|
90
|
-
if (
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
if (!signal.aborted) runtime.failedFacebookScripts.add(script);
|
|
113
|
-
if (ownedScript) {
|
|
171
|
+
let loading = runtime.facebookLoadObserver;
|
|
172
|
+
if (!loading && isReadySdk(host.FB)) {
|
|
173
|
+
loading = { promise: Promise.resolve(host.FB), consumers: 0 };
|
|
174
|
+
}
|
|
175
|
+
if (!loading) {
|
|
176
|
+
const shared2 = {
|
|
177
|
+
consumers: 0,
|
|
178
|
+
// Register the observer and its consumers before setup can fail synchronously.
|
|
179
|
+
promise: Promise.resolve().then(() => new Promise((resolve, reject) => {
|
|
180
|
+
var _a;
|
|
181
|
+
let settled = false;
|
|
182
|
+
let script;
|
|
183
|
+
let ownedScript = false;
|
|
184
|
+
let freshSdk = false;
|
|
185
|
+
let bootstrap;
|
|
186
|
+
let previous;
|
|
187
|
+
let previousCallback;
|
|
188
|
+
const finish = (sdk, error, definitiveFailure = false) => {
|
|
189
|
+
if (settled) return;
|
|
190
|
+
settled = true;
|
|
191
|
+
clearTimeout(timer);
|
|
192
|
+
script == null ? void 0 : script.removeEventListener("load", onLoad);
|
|
193
|
+
script == null ? void 0 : script.removeEventListener("error", onError);
|
|
114
194
|
try {
|
|
115
|
-
|
|
195
|
+
if (host.fbAsyncInit === onReady) {
|
|
196
|
+
if (previous) Object.defineProperty(host, "fbAsyncInit", previous);
|
|
197
|
+
else Reflect.deleteProperty(host, "fbAsyncInit");
|
|
198
|
+
}
|
|
116
199
|
} catch (e) {
|
|
117
200
|
}
|
|
201
|
+
if (error && script) {
|
|
202
|
+
runtime.failedFacebookScripts.add(script);
|
|
203
|
+
if (definitiveFailure) runtime.erroredFacebookScripts.add(script);
|
|
204
|
+
else if (!ownedScript) runtime.facebookLoadUncertain = true;
|
|
205
|
+
if (ownedScript) {
|
|
206
|
+
try {
|
|
207
|
+
script.remove();
|
|
208
|
+
} catch (e) {
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
if (runtime.facebookLoadObserver === shared2) delete runtime.facebookLoadObserver;
|
|
213
|
+
if (sdk) resolve(sdk);
|
|
214
|
+
else reject(error);
|
|
215
|
+
};
|
|
216
|
+
const onLoad = () => {
|
|
217
|
+
var _a2;
|
|
218
|
+
if (settled) return;
|
|
219
|
+
const sdk = host.FB;
|
|
220
|
+
if (!sdk) return;
|
|
221
|
+
if ("__buffer" in sdk) bootstrap = sdk;
|
|
222
|
+
if (((_a2 = bootstrap == null ? void 0 : bootstrap.__buffer) == null ? void 0 : _a2.opts) != null || host.fbAsyncInit !== onReady || (script == null ? void 0 : script.onload) || runtime.facebookLoading || runtime.facebookLoadUncertain) {
|
|
223
|
+
freshSdk = false;
|
|
224
|
+
if (runtime.facebookAppIds.get(sdk) === null) runtime.facebookAppIds.delete(sdk);
|
|
225
|
+
if (bootstrap && runtime.facebookAppIds.get(bootstrap) === null) runtime.facebookAppIds.delete(bootstrap);
|
|
226
|
+
}
|
|
227
|
+
const ready = isReadySdk(sdk);
|
|
228
|
+
if (freshSdk && runtime.facebookAppIds.get(sdk) == null) {
|
|
229
|
+
if (!ready) runtime.facebookAppIds.set(sdk, null);
|
|
230
|
+
else if (!runtime.facebookInitObservers.has(sdk)) {
|
|
231
|
+
try {
|
|
232
|
+
observeFacebookInit(runtime, sdk);
|
|
233
|
+
runtime.facebookAppIds.set(sdk, null);
|
|
234
|
+
} catch (e) {
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
if (ready) finish(sdk);
|
|
239
|
+
};
|
|
240
|
+
const onError = () => finish(void 0, new OmnizapiError("SDK_LOAD_FAILED", "The Meta SDK could not be loaded."), true);
|
|
241
|
+
const onReady = () => {
|
|
242
|
+
if (settled) return;
|
|
243
|
+
try {
|
|
244
|
+
previousCallback == null ? void 0 : previousCallback.call(host);
|
|
245
|
+
} catch (e) {
|
|
246
|
+
}
|
|
247
|
+
onLoad();
|
|
248
|
+
};
|
|
249
|
+
const timer = setTimeout(() => finish(void 0, new OmnizapiError(
|
|
250
|
+
"SDK_LOAD_FAILED",
|
|
251
|
+
"The Meta SDK load timed out."
|
|
252
|
+
)), 30 * 1e3);
|
|
253
|
+
shared2.cancelIfUnused = () => {
|
|
254
|
+
if (ownedScript && shared2.consumers === 0) {
|
|
255
|
+
finish(void 0, new OmnizapiError("SDK_LOAD_FAILED", "The Meta SDK load was cancelled."));
|
|
256
|
+
}
|
|
257
|
+
};
|
|
258
|
+
try {
|
|
259
|
+
previous = Object.getOwnPropertyDescriptor(host, "fbAsyncInit");
|
|
260
|
+
previousCallback = typeof host.fbAsyncInit === "function" ? host.fbAsyncInit : void 0;
|
|
261
|
+
const document = host.document;
|
|
262
|
+
const byId = document.getElementById("facebook-jssdk");
|
|
263
|
+
script = Array.from(document.scripts).find((candidate) => {
|
|
264
|
+
try {
|
|
265
|
+
const url = new URL(candidate.src);
|
|
266
|
+
if (url.origin !== "https://connect.facebook.net" || !/^\/[^/]+\/sdk\.js$/.test(url.pathname)) return false;
|
|
267
|
+
if (!runtime.failedFacebookScripts.has(candidate)) return true;
|
|
268
|
+
if (!runtime.erroredFacebookScripts.has(candidate)) runtime.facebookLoadUncertain = true;
|
|
269
|
+
return false;
|
|
270
|
+
} catch (e) {
|
|
271
|
+
return false;
|
|
272
|
+
}
|
|
273
|
+
});
|
|
274
|
+
if (!script) {
|
|
275
|
+
script = document.createElement("script");
|
|
276
|
+
ownedScript = true;
|
|
277
|
+
const initialSdk = host.FB;
|
|
278
|
+
if (initialSdk && "__buffer" in initialSdk) bootstrap = initialSdk;
|
|
279
|
+
freshSdk = !runtime.facebookLoadUncertain && !runtime.facebookLoading && !previousCallback && (!initialSdk || !!bootstrap && runtime.facebookAppIds.get(initialSdk) === null && ((_a = bootstrap.__buffer) == null ? void 0 : _a.opts) == null);
|
|
280
|
+
if (!byId) script.id = "facebook-jssdk";
|
|
281
|
+
script.src = "https://connect.facebook.net/en_US/sdk.js";
|
|
282
|
+
script.crossOrigin = "anonymous";
|
|
283
|
+
script.async = true;
|
|
284
|
+
script.defer = true;
|
|
285
|
+
}
|
|
286
|
+
shared2.cancelIfUnused();
|
|
287
|
+
if (settled) return;
|
|
288
|
+
Object.defineProperty(host, "fbAsyncInit", previous && !previous.configurable ? { value: onReady } : { configurable: true, enumerable: true, writable: true, value: onReady });
|
|
289
|
+
script.addEventListener("load", onLoad);
|
|
290
|
+
script.addEventListener("error", onError);
|
|
291
|
+
onLoad();
|
|
292
|
+
if (!settled && ownedScript) document.head.appendChild(script);
|
|
293
|
+
} catch (e) {
|
|
294
|
+
finish(void 0, new OmnizapiError("SDK_LOAD_FAILED", "The Meta SDK could not be loaded."));
|
|
118
295
|
}
|
|
119
|
-
}
|
|
120
|
-
if (runtime.facebookLoading === loading) delete runtime.facebookLoading;
|
|
121
|
-
if (sdk) resolve(sdk);
|
|
122
|
-
else reject(error);
|
|
296
|
+
}))
|
|
123
297
|
};
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
const
|
|
131
|
-
|
|
298
|
+
runtime.facebookLoadObserver = loading = shared2;
|
|
299
|
+
}
|
|
300
|
+
const shared = loading;
|
|
301
|
+
return new Promise((resolve, reject) => {
|
|
302
|
+
let settled = false;
|
|
303
|
+
shared.consumers++;
|
|
304
|
+
const complete = (sdk, error) => {
|
|
305
|
+
var _a;
|
|
132
306
|
if (settled) return;
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
307
|
+
settled = true;
|
|
308
|
+
signal.removeEventListener("abort", onAbort);
|
|
309
|
+
shared.consumers--;
|
|
310
|
+
if (sdk) resolve(sdk);
|
|
311
|
+
else reject(error);
|
|
312
|
+
(_a = shared.cancelIfUnused) == null ? void 0 : _a.call(shared);
|
|
138
313
|
};
|
|
139
|
-
const
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
}
|
|
149
|
-
previous = Object.getOwnPropertyDescriptor(host, "fbAsyncInit");
|
|
150
|
-
previousCallback = typeof host.fbAsyncInit === "function" ? host.fbAsyncInit : void 0;
|
|
151
|
-
Object.defineProperty(host, "fbAsyncInit", previous && !previous.configurable ? { value: onReady } : { configurable: true, enumerable: true, writable: true, value: onReady });
|
|
152
|
-
const document = host.document;
|
|
153
|
-
const byId = document.getElementById("facebook-jssdk");
|
|
154
|
-
const existingScript = (byId == null ? void 0 : byId.tagName.toLowerCase()) === "script" ? byId : void 0;
|
|
155
|
-
script = (existingScript && !runtime.failedFacebookScripts.has(existingScript) ? existingScript : void 0) || Array.from(document.scripts).find((candidate) => {
|
|
156
|
-
if (runtime.failedFacebookScripts.has(candidate)) return false;
|
|
157
|
-
try {
|
|
158
|
-
const url = new URL(candidate.src);
|
|
159
|
-
return url.origin === "https://connect.facebook.net" && /^\/[^/]+\/sdk\.js$/.test(url.pathname);
|
|
160
|
-
} catch (e) {
|
|
161
|
-
return false;
|
|
162
|
-
}
|
|
163
|
-
});
|
|
164
|
-
if (!script) {
|
|
165
|
-
script = document.createElement("script");
|
|
166
|
-
ownedScript = true;
|
|
167
|
-
if (!byId) script.id = "facebook-jssdk";
|
|
168
|
-
script.src = "https://connect.facebook.net/en_US/sdk.js";
|
|
169
|
-
script.crossOrigin = "anonymous";
|
|
170
|
-
script.async = true;
|
|
171
|
-
script.defer = true;
|
|
172
|
-
}
|
|
173
|
-
script.addEventListener("load", onLoad);
|
|
174
|
-
script.addEventListener("error", onError);
|
|
175
|
-
onLoad();
|
|
176
|
-
if (!settled && ownedScript) document.head.appendChild(script);
|
|
177
|
-
} catch (e) {
|
|
178
|
-
onError();
|
|
179
|
-
}
|
|
180
|
-
}));
|
|
181
|
-
runtime.facebookLoading = loading;
|
|
182
|
-
return loading;
|
|
314
|
+
const onAbort = () => complete(void 0, new OmnizapiError("SDK_LOAD_FAILED", "The Meta SDK load was cancelled."));
|
|
315
|
+
void shared.promise.then(
|
|
316
|
+
(sdk) => signal.aborted ? onAbort() : complete(sdk),
|
|
317
|
+
// A shared observer may belong to another module copy's OmnizapiError class.
|
|
318
|
+
(error) => complete(void 0, new OmnizapiError("SDK_LOAD_FAILED", error.message))
|
|
319
|
+
);
|
|
320
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
321
|
+
if (signal.aborted) onAbort();
|
|
322
|
+
});
|
|
183
323
|
}
|
|
184
324
|
|
|
185
325
|
// src/core/open-popup.ts
|
|
@@ -260,8 +400,8 @@ function requestJson(url, init, signal) {
|
|
|
260
400
|
else resolve(value);
|
|
261
401
|
};
|
|
262
402
|
const onAbort = () => complete(void 0, new OmnizapiError(
|
|
263
|
-
"
|
|
264
|
-
"The API request was
|
|
403
|
+
"ABORTED",
|
|
404
|
+
"The API request was aborted."
|
|
265
405
|
));
|
|
266
406
|
const timer = setTimeout(() => complete(void 0, new OmnizapiError(
|
|
267
407
|
"TIMEOUT",
|
|
@@ -318,10 +458,14 @@ var OmnizapiClientImpl = class {
|
|
|
318
458
|
frontUrl: props.frontUrl
|
|
319
459
|
});
|
|
320
460
|
}
|
|
321
|
-
async getListMessengerPages(channelId, code) {
|
|
461
|
+
async getListMessengerPages(channelId, code, signal) {
|
|
322
462
|
if (!stringOrNull(channelId) || !stringOrNull(code)) {
|
|
323
463
|
throw new OmnizapiError("INVALID_OPTIONS", "A channelId and authorization code are required.");
|
|
324
464
|
}
|
|
465
|
+
if (signal !== void 0 && (!isRecord(signal) || typeof signal.aborted !== "boolean" || typeof signal.addEventListener !== "function" || typeof signal.removeEventListener !== "function")) {
|
|
466
|
+
throw new OmnizapiError("INVALID_OPTIONS", "The abort signal is invalid.");
|
|
467
|
+
}
|
|
468
|
+
if (signal == null ? void 0 : signal.aborted) throw new OmnizapiError("ABORTED", "The API request was aborted.");
|
|
325
469
|
return requestJson(
|
|
326
470
|
new URL(`${this.constants.api}/v1/channels/${encodeChannelId(channelId)}/list-messenger-pages`),
|
|
327
471
|
{
|
|
@@ -331,7 +475,8 @@ var OmnizapiClientImpl = class {
|
|
|
331
475
|
code
|
|
332
476
|
}),
|
|
333
477
|
headers: { "Content-Type": "application/json", Authorization: this.publicKey }
|
|
334
|
-
}
|
|
478
|
+
},
|
|
479
|
+
signal
|
|
335
480
|
);
|
|
336
481
|
}
|
|
337
482
|
async connect(options) {
|
|
@@ -348,10 +493,11 @@ var OmnizapiClientImpl = class {
|
|
|
348
493
|
if (!isRecord(options)) {
|
|
349
494
|
throw new OmnizapiError("INVALID_OPTIONS", "Connection options are required.");
|
|
350
495
|
}
|
|
351
|
-
const { channelId, direct, getQRCode, timeoutMs = TOTAL_TIMEOUT_MS } = options;
|
|
352
|
-
if (typeof channelId !== "string" || direct !== void 0 && typeof direct !== "boolean" || getQRCode !== void 0 && typeof getQRCode !== "function" || typeof timeoutMs !== "number" || !Number.isFinite(timeoutMs) || timeoutMs <= 0 || timeoutMs > 2147483647) {
|
|
353
|
-
throw new OmnizapiError("INVALID_OPTIONS", "Invalid channelId, direct, getQRCode or
|
|
496
|
+
const { channelId, direct, getQRCode, timeoutMs = TOTAL_TIMEOUT_MS, signal } = options;
|
|
497
|
+
if (typeof channelId !== "string" || direct !== void 0 && typeof direct !== "boolean" || getQRCode !== void 0 && typeof getQRCode !== "function" || typeof timeoutMs !== "number" || !Number.isFinite(timeoutMs) || timeoutMs <= 0 || timeoutMs > 2147483647 || signal !== void 0 && (!isRecord(signal) || typeof signal.aborted !== "boolean" || typeof signal.addEventListener !== "function" || typeof signal.removeEventListener !== "function")) {
|
|
498
|
+
throw new OmnizapiError("INVALID_OPTIONS", "Invalid channelId, direct, getQRCode, timeoutMs or signal option.");
|
|
354
499
|
}
|
|
500
|
+
if (signal == null ? void 0 : signal.aborted) throw new OmnizapiError("ABORTED", "The connection was aborted.");
|
|
355
501
|
if (!channelId.trim()) return failure(channelId, null, "invalid_channel");
|
|
356
502
|
const encodedChannelId = encodeChannelId(channelId);
|
|
357
503
|
if (typeof host.open !== "function" || typeof host.addEventListener !== "function" || typeof host.removeEventListener !== "function" || typeof host.location.origin !== "string" || typeof host.location.href !== "string" || typeof ((_a = host.crypto) == null ? void 0 : _a.getRandomValues) !== "function" || typeof AbortController !== "function" || typeof fetch !== "function") {
|
|
@@ -369,16 +515,28 @@ var OmnizapiClientImpl = class {
|
|
|
369
515
|
let channelType = null;
|
|
370
516
|
let redirectUri = null;
|
|
371
517
|
let popup = null;
|
|
518
|
+
let popupError;
|
|
372
519
|
let timeout;
|
|
373
520
|
let popupTimer;
|
|
374
521
|
let messageListener;
|
|
375
522
|
let nativeLoginStarted = false;
|
|
523
|
+
let callbackReceived = false;
|
|
524
|
+
const releaseNativeLogin = () => {
|
|
525
|
+
if (runtime.nativeLoginOwner === owner) {
|
|
526
|
+
runtime.nativeLoginPending = false;
|
|
527
|
+
delete runtime.nativeLoginOwner;
|
|
528
|
+
}
|
|
529
|
+
};
|
|
376
530
|
const globals = [];
|
|
377
531
|
const finish = (outcome) => {
|
|
378
532
|
if (settled) return;
|
|
379
533
|
settled = true;
|
|
380
534
|
clearTimeout(timeout);
|
|
381
535
|
clearInterval(popupTimer);
|
|
536
|
+
try {
|
|
537
|
+
signal == null ? void 0 : signal.removeEventListener("abort", onAbort);
|
|
538
|
+
} catch (e) {
|
|
539
|
+
}
|
|
382
540
|
if (messageListener) {
|
|
383
541
|
try {
|
|
384
542
|
host.removeEventListener("message", messageListener);
|
|
@@ -405,19 +563,49 @@ var OmnizapiClientImpl = class {
|
|
|
405
563
|
}
|
|
406
564
|
}
|
|
407
565
|
if (runtime.activeConnection === owner) delete runtime.activeConnection;
|
|
408
|
-
if (nativeLoginStarted && !(outcome instanceof OmnizapiError) && outcome.success) {
|
|
409
|
-
|
|
566
|
+
if (nativeLoginStarted && (callbackReceived || !(outcome instanceof OmnizapiError) && outcome.success)) {
|
|
567
|
+
releaseNativeLogin();
|
|
410
568
|
}
|
|
411
569
|
if (outcome instanceof OmnizapiError) reject(outcome);
|
|
412
570
|
else resolve(outcome);
|
|
413
571
|
};
|
|
572
|
+
const onAbort = () => finish(new OmnizapiError("ABORTED", "The connection was aborted."));
|
|
414
573
|
const isLive = () => {
|
|
574
|
+
if (!settled && (signal == null ? void 0 : signal.aborted)) onAbort();
|
|
415
575
|
if (!settled && Date.now() >= deadline) {
|
|
416
576
|
finish(new OmnizapiError("TIMEOUT", "The connection timed out."));
|
|
417
577
|
}
|
|
418
578
|
return !settled;
|
|
419
579
|
};
|
|
420
580
|
const fail = (reason) => finish(failure(channelId, channelType, reason));
|
|
581
|
+
const reservePopup = () => {
|
|
582
|
+
try {
|
|
583
|
+
const opened = openPopup("about:blank", "_blank", 600, 740);
|
|
584
|
+
if (!opened || opened === host) throw new Error("Popup unavailable");
|
|
585
|
+
if (!isLive()) {
|
|
586
|
+
opened.close();
|
|
587
|
+
return;
|
|
588
|
+
}
|
|
589
|
+
popup = opened;
|
|
590
|
+
} catch (e) {
|
|
591
|
+
throw new OmnizapiError("POPUP_BLOCKED", "The connection popup could not be opened.");
|
|
592
|
+
}
|
|
593
|
+
};
|
|
594
|
+
const watchPopup = () => {
|
|
595
|
+
if (popupTimer) return;
|
|
596
|
+
popupTimer = setInterval(() => {
|
|
597
|
+
if (!isLive()) return;
|
|
598
|
+
try {
|
|
599
|
+
if (popup == null ? void 0 : popup.closed) fail("popup_closed");
|
|
600
|
+
} catch (e) {
|
|
601
|
+
finish(new OmnizapiError("PROVIDER_ERROR", "The connection popup could not be monitored."));
|
|
602
|
+
}
|
|
603
|
+
}, 500);
|
|
604
|
+
};
|
|
605
|
+
const unwatchPopup = () => {
|
|
606
|
+
clearInterval(popupTimer);
|
|
607
|
+
popupTimer = void 0;
|
|
608
|
+
};
|
|
421
609
|
const succeed = (data) => {
|
|
422
610
|
if (!isLive() || !channelType) return;
|
|
423
611
|
finish({
|
|
@@ -436,6 +624,8 @@ var OmnizapiClientImpl = class {
|
|
|
436
624
|
};
|
|
437
625
|
try {
|
|
438
626
|
runtime.activeConnection = owner;
|
|
627
|
+
signal == null ? void 0 : signal.addEventListener("abort", onAbort, { once: true });
|
|
628
|
+
if (!isLive()) return;
|
|
439
629
|
const bytes = host.crypto.getRandomValues(new Uint8Array(16));
|
|
440
630
|
const attemptId = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
441
631
|
for (const [name, value] of [
|
|
@@ -451,6 +641,12 @@ var OmnizapiClientImpl = class {
|
|
|
451
641
|
"TIMEOUT",
|
|
452
642
|
"The connection timed out."
|
|
453
643
|
)), timeoutMs);
|
|
644
|
+
try {
|
|
645
|
+
reservePopup();
|
|
646
|
+
} catch (error) {
|
|
647
|
+
popupError = error instanceof OmnizapiError ? error : new OmnizapiError("POPUP_BLOCKED", "The connection popup could not be opened.");
|
|
648
|
+
}
|
|
649
|
+
if (!isLive()) return;
|
|
454
650
|
const run = async () => {
|
|
455
651
|
var _a2, _b, _c;
|
|
456
652
|
const info = await requestJson(
|
|
@@ -468,7 +664,13 @@ var OmnizapiClientImpl = class {
|
|
|
468
664
|
}
|
|
469
665
|
const middleware = info.middleware;
|
|
470
666
|
channelType = isChannelType(middleware) ? middleware : null;
|
|
471
|
-
if (currentOrigin !== frontOrigin && !allowOrigins.some((origin) =>
|
|
667
|
+
if (currentOrigin !== frontOrigin && !allowOrigins.some((origin) => {
|
|
668
|
+
try {
|
|
669
|
+
return currentOrigin === new URL(origin).origin;
|
|
670
|
+
} catch (e) {
|
|
671
|
+
return false;
|
|
672
|
+
}
|
|
673
|
+
})) {
|
|
472
674
|
fail("origin_not_allowed");
|
|
473
675
|
return;
|
|
474
676
|
}
|
|
@@ -481,26 +683,34 @@ var OmnizapiClientImpl = class {
|
|
|
481
683
|
if (channelType.startsWith("META_") && !appId || channelType === "META_WHATSAPP" && !configId) {
|
|
482
684
|
throw new OmnizapiError("INVALID_RESPONSE", "The channel provider configuration is invalid.");
|
|
483
685
|
}
|
|
484
|
-
|
|
686
|
+
const nativeWhatsApp = channelType === "META_WHATSAPP" && (direct || Boolean(info.appCustom) || currentOrigin === frontOrigin);
|
|
687
|
+
let nativeReady = false;
|
|
688
|
+
let fb;
|
|
689
|
+
if (nativeWhatsApp) {
|
|
690
|
+
unwatchPopup();
|
|
485
691
|
if (runtime.nativeLoginPending) {
|
|
486
692
|
throw new OmnizapiError(
|
|
487
693
|
"CONNECTION_IN_PROGRESS",
|
|
488
694
|
"A previous Meta login is incomplete. Reload this window before retrying a native login."
|
|
489
695
|
);
|
|
490
696
|
}
|
|
491
|
-
|
|
697
|
+
fb = await loadFacebookSdk(host, controller.signal);
|
|
492
698
|
if (!isLive()) return;
|
|
493
699
|
try {
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
700
|
+
initializeFacebookSdk(host, fb, appId);
|
|
701
|
+
nativeReady = true;
|
|
702
|
+
} catch (error) {
|
|
703
|
+
if (!(error instanceof OmnizapiError && error.code === "INVALID_CONFIGURATION")) throw error;
|
|
497
704
|
}
|
|
498
705
|
if (!isLive()) return;
|
|
706
|
+
}
|
|
707
|
+
if (nativeReady && fb) {
|
|
708
|
+
popup == null ? void 0 : popup.close();
|
|
709
|
+
popup = null;
|
|
499
710
|
let code = null;
|
|
500
711
|
let wabaId = null;
|
|
501
712
|
let phoneId = null;
|
|
502
713
|
let coexistence = false;
|
|
503
|
-
let callbackReceived = false;
|
|
504
714
|
const completeNative = () => {
|
|
505
715
|
if (!isLive() || !code || !wabaId) return;
|
|
506
716
|
succeed({ code, wabaId, phoneId, coexistence });
|
|
@@ -533,11 +743,17 @@ var OmnizapiClientImpl = class {
|
|
|
533
743
|
};
|
|
534
744
|
host.addEventListener("message", messageListener);
|
|
535
745
|
runtime.nativeLoginPending = true;
|
|
746
|
+
runtime.nativeLoginOwner = owner;
|
|
536
747
|
nativeLoginStarted = true;
|
|
537
748
|
try {
|
|
538
749
|
fb.login((response) => {
|
|
539
|
-
if (
|
|
750
|
+
if (callbackReceived) return;
|
|
540
751
|
callbackReceived = true;
|
|
752
|
+
if (settled) {
|
|
753
|
+
releaseNativeLogin();
|
|
754
|
+
return;
|
|
755
|
+
}
|
|
756
|
+
if (!isLive()) return;
|
|
541
757
|
if (!isRecord(response) || response.error) {
|
|
542
758
|
finish(new OmnizapiError("PROVIDER_ERROR", "Meta returned an invalid login response."));
|
|
543
759
|
return;
|
|
@@ -563,6 +779,8 @@ var OmnizapiClientImpl = class {
|
|
|
563
779
|
}
|
|
564
780
|
});
|
|
565
781
|
} catch (e) {
|
|
782
|
+
releaseNativeLogin();
|
|
783
|
+
nativeLoginStarted = false;
|
|
566
784
|
throw new OmnizapiError("PROVIDER_ERROR", "The Meta login could not be started.");
|
|
567
785
|
}
|
|
568
786
|
return;
|
|
@@ -589,6 +807,7 @@ var OmnizapiClientImpl = class {
|
|
|
589
807
|
} else {
|
|
590
808
|
url = new URL(`${this.constants.front}/connect/${channelType === "BOT_TELEGRAM" ? "telegram" : "whatsapp-web"}`);
|
|
591
809
|
url.searchParams.set("channelId", channelId);
|
|
810
|
+
url.searchParams.set("pk", this.publicKey);
|
|
592
811
|
}
|
|
593
812
|
if (channelType !== "META_MESSENGER" && channelType !== "META_INSTAGRAM") {
|
|
594
813
|
url.searchParams.set("attemptId", attemptId);
|
|
@@ -609,23 +828,18 @@ var OmnizapiClientImpl = class {
|
|
|
609
828
|
};
|
|
610
829
|
host.addEventListener("message", messageListener);
|
|
611
830
|
if (!isLive()) return;
|
|
831
|
+
if (popupError) throw popupError;
|
|
832
|
+
if (!popup) reservePopup();
|
|
833
|
+
if (popup == null ? void 0 : popup.closed) {
|
|
834
|
+
fail("popup_closed");
|
|
835
|
+
return;
|
|
836
|
+
}
|
|
837
|
+
watchPopup();
|
|
612
838
|
try {
|
|
613
|
-
|
|
614
|
-
if (!opened || opened === host) {
|
|
615
|
-
throw new OmnizapiError("POPUP_BLOCKED", "The connection popup was blocked.");
|
|
616
|
-
}
|
|
617
|
-
popup = opened;
|
|
839
|
+
popup == null ? void 0 : popup.location.replace(url.href);
|
|
618
840
|
} catch (e) {
|
|
619
|
-
throw new OmnizapiError("
|
|
841
|
+
throw new OmnizapiError("PROVIDER_ERROR", "The connection popup could not be navigated.");
|
|
620
842
|
}
|
|
621
|
-
popupTimer = setInterval(() => {
|
|
622
|
-
if (!isLive()) return;
|
|
623
|
-
try {
|
|
624
|
-
if (popup == null ? void 0 : popup.closed) fail("popup_closed");
|
|
625
|
-
} catch (e) {
|
|
626
|
-
finish(new OmnizapiError("PROVIDER_ERROR", "The connection popup could not be monitored."));
|
|
627
|
-
}
|
|
628
|
-
}, 500);
|
|
629
843
|
};
|
|
630
844
|
void run().catch((error) => {
|
|
631
845
|
if (!isLive()) return;
|
|
@@ -634,8 +848,8 @@ var OmnizapiClientImpl = class {
|
|
|
634
848
|
"The connection could not be completed."
|
|
635
849
|
));
|
|
636
850
|
});
|
|
637
|
-
} catch (
|
|
638
|
-
finish(new OmnizapiError("INVALID_CONFIGURATION", "The connection could not be initialized."));
|
|
851
|
+
} catch (error) {
|
|
852
|
+
finish(error instanceof OmnizapiError ? error : new OmnizapiError("INVALID_CONFIGURATION", "The connection could not be initialized."));
|
|
639
853
|
}
|
|
640
854
|
});
|
|
641
855
|
} catch (error) {
|