@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/cjs/index.js
CHANGED
|
@@ -94,12 +94,22 @@ var getConstants = ({
|
|
|
94
94
|
// src/core/runtime.ts
|
|
95
95
|
var runtimeKey = /* @__PURE__ */ Symbol.for("omnizapi.connect.runtime.v1");
|
|
96
96
|
function getRuntime(host) {
|
|
97
|
+
var _a, _b, _c;
|
|
97
98
|
const target = host;
|
|
98
99
|
let runtime = target[runtimeKey];
|
|
99
100
|
if (!runtime) {
|
|
100
|
-
runtime = {
|
|
101
|
+
runtime = {
|
|
102
|
+
nativeLoginPending: false,
|
|
103
|
+
failedFacebookScripts: /* @__PURE__ */ new WeakSet(),
|
|
104
|
+
erroredFacebookScripts: /* @__PURE__ */ new WeakSet(),
|
|
105
|
+
facebookAppIds: /* @__PURE__ */ new WeakMap(),
|
|
106
|
+
facebookInitObservers: /* @__PURE__ */ new WeakMap()
|
|
107
|
+
};
|
|
101
108
|
Object.defineProperty(target, runtimeKey, { configurable: true, value: runtime });
|
|
102
109
|
}
|
|
110
|
+
(_a = runtime.facebookAppIds) != null ? _a : runtime.facebookAppIds = /* @__PURE__ */ new WeakMap();
|
|
111
|
+
(_b = runtime.facebookInitObservers) != null ? _b : runtime.facebookInitObservers = /* @__PURE__ */ new WeakMap();
|
|
112
|
+
(_c = runtime.erroredFacebookScripts) != null ? _c : runtime.erroredFacebookScripts = /* @__PURE__ */ new WeakSet();
|
|
103
113
|
return runtime;
|
|
104
114
|
}
|
|
105
115
|
|
|
@@ -107,108 +117,238 @@ function getRuntime(host) {
|
|
|
107
117
|
function isReadySdk(sdk) {
|
|
108
118
|
return !!sdk && !("__buffer" in sdk) && typeof sdk.init === "function" && typeof sdk.login === "function";
|
|
109
119
|
}
|
|
120
|
+
function observeFacebookInit(runtime, fb) {
|
|
121
|
+
var _a;
|
|
122
|
+
try {
|
|
123
|
+
const descriptor = Object.getOwnPropertyDescriptor(fb, "init");
|
|
124
|
+
const existing = runtime.facebookInitObservers.get(fb);
|
|
125
|
+
if (existing) {
|
|
126
|
+
if ((descriptor == null ? void 0 : descriptor.value) !== existing.init) throw new Error("FB.init was replaced.");
|
|
127
|
+
return existing;
|
|
128
|
+
}
|
|
129
|
+
if (!descriptor || typeof descriptor.value !== "function" || !descriptor.writable && !descriptor.configurable) {
|
|
130
|
+
throw new Error("FB.init cannot be observed.");
|
|
131
|
+
}
|
|
132
|
+
const original = descriptor.value;
|
|
133
|
+
const observer = {
|
|
134
|
+
calls: 0,
|
|
135
|
+
init: function(...args) {
|
|
136
|
+
observer.calls++;
|
|
137
|
+
runtime.facebookAppIds.delete(fb);
|
|
138
|
+
return Reflect.apply(original, this, args);
|
|
139
|
+
}
|
|
140
|
+
};
|
|
141
|
+
Object.defineProperty(fb, "init", { ...descriptor, value: observer.init });
|
|
142
|
+
if (((_a = Object.getOwnPropertyDescriptor(fb, "init")) == null ? void 0 : _a.value) !== observer.init) throw new Error("FB.init was not replaced.");
|
|
143
|
+
runtime.facebookInitObservers.set(fb, observer);
|
|
144
|
+
return observer;
|
|
145
|
+
} catch (e) {
|
|
146
|
+
runtime.facebookAppIds.delete(fb);
|
|
147
|
+
throw new OmnizapiError(
|
|
148
|
+
"INVALID_CONFIGURATION",
|
|
149
|
+
"The Meta SDK initialization cannot be observed safely. Use the popup flow or reload a fresh page."
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
function initializeFacebookSdk(host, fb, appId) {
|
|
154
|
+
var _a;
|
|
155
|
+
if (host.FB !== fb || !fb || "__buffer" in fb || typeof fb.login !== "function") {
|
|
156
|
+
throw new OmnizapiError("INVALID_CONFIGURATION", "The Meta SDK is not ready or was replaced before initialization.");
|
|
157
|
+
}
|
|
158
|
+
if (typeof appId !== "string" || !/^[0-9]+$/.test(appId)) {
|
|
159
|
+
throw new OmnizapiError("INVALID_CONFIGURATION", "A numeric Meta appId is required for native login.");
|
|
160
|
+
}
|
|
161
|
+
const runtime = getRuntime(host);
|
|
162
|
+
if (runtime.facebookAppIds.get(fb) === null && (runtime.facebookLoadUncertain || runtime.facebookLoading || typeof host.fbAsyncInit === "function")) {
|
|
163
|
+
runtime.facebookAppIds.delete(fb);
|
|
164
|
+
}
|
|
165
|
+
const initializedAppId = runtime.facebookAppIds.get(fb);
|
|
166
|
+
if (initializedAppId === void 0 || initializedAppId !== null && !runtime.facebookInitObservers.has(fb)) {
|
|
167
|
+
runtime.facebookAppIds.delete(fb);
|
|
168
|
+
throw new OmnizapiError(
|
|
169
|
+
"INVALID_CONFIGURATION",
|
|
170
|
+
"The host Meta SDK configuration is unknown. Use the popup flow or a fresh page without a host-initialized SDK for native login."
|
|
171
|
+
);
|
|
172
|
+
}
|
|
173
|
+
const observer = observeFacebookInit(runtime, fb);
|
|
174
|
+
if (initializedAppId !== null) {
|
|
175
|
+
if (initializedAppId !== appId) {
|
|
176
|
+
throw new OmnizapiError(
|
|
177
|
+
"INVALID_CONFIGURATION",
|
|
178
|
+
"The Meta SDK is already initialized for another app. Use the popup flow or reload a fresh page before changing apps."
|
|
179
|
+
);
|
|
180
|
+
}
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
const calls = observer.calls;
|
|
184
|
+
runtime.facebookAppIds.delete(fb);
|
|
185
|
+
try {
|
|
186
|
+
fb.init({ appId, version: "v25.0", autoLogAppEvents: true, xfbml: true });
|
|
187
|
+
} catch (e) {
|
|
188
|
+
throw new OmnizapiError("PROVIDER_ERROR", "The Meta SDK could not be initialized.");
|
|
189
|
+
}
|
|
190
|
+
if (observer.calls !== calls + 1 || host.FB !== fb || ((_a = Object.getOwnPropertyDescriptor(fb, "init")) == null ? void 0 : _a.value) !== observer.init) {
|
|
191
|
+
throw new OmnizapiError("INVALID_CONFIGURATION", "The Meta SDK changed during initialization. Use the popup flow or reload a fresh page.");
|
|
192
|
+
}
|
|
193
|
+
runtime.facebookAppIds.set(fb, appId);
|
|
194
|
+
}
|
|
110
195
|
function loadFacebookSdk(host, signal) {
|
|
111
196
|
if (signal.aborted) {
|
|
112
197
|
return Promise.reject(new OmnizapiError("SDK_LOAD_FAILED", "The Meta SDK load was cancelled."));
|
|
113
198
|
}
|
|
114
|
-
if (isReadySdk(host.FB)) {
|
|
115
|
-
return Promise.resolve(host.FB);
|
|
116
|
-
}
|
|
117
199
|
const runtime = getRuntime(host);
|
|
118
|
-
|
|
119
|
-
if (
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
if (!signal.aborted) runtime.failedFacebookScripts.add(script);
|
|
142
|
-
if (ownedScript) {
|
|
200
|
+
let loading = runtime.facebookLoadObserver;
|
|
201
|
+
if (!loading && isReadySdk(host.FB)) {
|
|
202
|
+
loading = { promise: Promise.resolve(host.FB), consumers: 0 };
|
|
203
|
+
}
|
|
204
|
+
if (!loading) {
|
|
205
|
+
const shared2 = {
|
|
206
|
+
consumers: 0,
|
|
207
|
+
// Register the observer and its consumers before setup can fail synchronously.
|
|
208
|
+
promise: Promise.resolve().then(() => new Promise((resolve, reject) => {
|
|
209
|
+
var _a;
|
|
210
|
+
let settled = false;
|
|
211
|
+
let script;
|
|
212
|
+
let ownedScript = false;
|
|
213
|
+
let freshSdk = false;
|
|
214
|
+
let bootstrap;
|
|
215
|
+
let previous;
|
|
216
|
+
let previousCallback;
|
|
217
|
+
const finish = (sdk, error, definitiveFailure = false) => {
|
|
218
|
+
if (settled) return;
|
|
219
|
+
settled = true;
|
|
220
|
+
clearTimeout(timer);
|
|
221
|
+
script == null ? void 0 : script.removeEventListener("load", onLoad);
|
|
222
|
+
script == null ? void 0 : script.removeEventListener("error", onError);
|
|
143
223
|
try {
|
|
144
|
-
|
|
224
|
+
if (host.fbAsyncInit === onReady) {
|
|
225
|
+
if (previous) Object.defineProperty(host, "fbAsyncInit", previous);
|
|
226
|
+
else Reflect.deleteProperty(host, "fbAsyncInit");
|
|
227
|
+
}
|
|
145
228
|
} catch (e) {
|
|
146
229
|
}
|
|
230
|
+
if (error && script) {
|
|
231
|
+
runtime.failedFacebookScripts.add(script);
|
|
232
|
+
if (definitiveFailure) runtime.erroredFacebookScripts.add(script);
|
|
233
|
+
else if (!ownedScript) runtime.facebookLoadUncertain = true;
|
|
234
|
+
if (ownedScript) {
|
|
235
|
+
try {
|
|
236
|
+
script.remove();
|
|
237
|
+
} catch (e) {
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
if (runtime.facebookLoadObserver === shared2) delete runtime.facebookLoadObserver;
|
|
242
|
+
if (sdk) resolve(sdk);
|
|
243
|
+
else reject(error);
|
|
244
|
+
};
|
|
245
|
+
const onLoad = () => {
|
|
246
|
+
var _a2;
|
|
247
|
+
if (settled) return;
|
|
248
|
+
const sdk = host.FB;
|
|
249
|
+
if (!sdk) return;
|
|
250
|
+
if ("__buffer" in sdk) bootstrap = sdk;
|
|
251
|
+
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) {
|
|
252
|
+
freshSdk = false;
|
|
253
|
+
if (runtime.facebookAppIds.get(sdk) === null) runtime.facebookAppIds.delete(sdk);
|
|
254
|
+
if (bootstrap && runtime.facebookAppIds.get(bootstrap) === null) runtime.facebookAppIds.delete(bootstrap);
|
|
255
|
+
}
|
|
256
|
+
const ready = isReadySdk(sdk);
|
|
257
|
+
if (freshSdk && runtime.facebookAppIds.get(sdk) == null) {
|
|
258
|
+
if (!ready) runtime.facebookAppIds.set(sdk, null);
|
|
259
|
+
else if (!runtime.facebookInitObservers.has(sdk)) {
|
|
260
|
+
try {
|
|
261
|
+
observeFacebookInit(runtime, sdk);
|
|
262
|
+
runtime.facebookAppIds.set(sdk, null);
|
|
263
|
+
} catch (e) {
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
if (ready) finish(sdk);
|
|
268
|
+
};
|
|
269
|
+
const onError = () => finish(void 0, new OmnizapiError("SDK_LOAD_FAILED", "The Meta SDK could not be loaded."), true);
|
|
270
|
+
const onReady = () => {
|
|
271
|
+
if (settled) return;
|
|
272
|
+
try {
|
|
273
|
+
previousCallback == null ? void 0 : previousCallback.call(host);
|
|
274
|
+
} catch (e) {
|
|
275
|
+
}
|
|
276
|
+
onLoad();
|
|
277
|
+
};
|
|
278
|
+
const timer = setTimeout(() => finish(void 0, new OmnizapiError(
|
|
279
|
+
"SDK_LOAD_FAILED",
|
|
280
|
+
"The Meta SDK load timed out."
|
|
281
|
+
)), 30 * 1e3);
|
|
282
|
+
shared2.cancelIfUnused = () => {
|
|
283
|
+
if (ownedScript && shared2.consumers === 0) {
|
|
284
|
+
finish(void 0, new OmnizapiError("SDK_LOAD_FAILED", "The Meta SDK load was cancelled."));
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
try {
|
|
288
|
+
previous = Object.getOwnPropertyDescriptor(host, "fbAsyncInit");
|
|
289
|
+
previousCallback = typeof host.fbAsyncInit === "function" ? host.fbAsyncInit : void 0;
|
|
290
|
+
const document = host.document;
|
|
291
|
+
const byId = document.getElementById("facebook-jssdk");
|
|
292
|
+
script = Array.from(document.scripts).find((candidate) => {
|
|
293
|
+
try {
|
|
294
|
+
const url = new URL(candidate.src);
|
|
295
|
+
if (url.origin !== "https://connect.facebook.net" || !/^\/[^/]+\/sdk\.js$/.test(url.pathname)) return false;
|
|
296
|
+
if (!runtime.failedFacebookScripts.has(candidate)) return true;
|
|
297
|
+
if (!runtime.erroredFacebookScripts.has(candidate)) runtime.facebookLoadUncertain = true;
|
|
298
|
+
return false;
|
|
299
|
+
} catch (e) {
|
|
300
|
+
return false;
|
|
301
|
+
}
|
|
302
|
+
});
|
|
303
|
+
if (!script) {
|
|
304
|
+
script = document.createElement("script");
|
|
305
|
+
ownedScript = true;
|
|
306
|
+
const initialSdk = host.FB;
|
|
307
|
+
if (initialSdk && "__buffer" in initialSdk) bootstrap = initialSdk;
|
|
308
|
+
freshSdk = !runtime.facebookLoadUncertain && !runtime.facebookLoading && !previousCallback && (!initialSdk || !!bootstrap && runtime.facebookAppIds.get(initialSdk) === null && ((_a = bootstrap.__buffer) == null ? void 0 : _a.opts) == null);
|
|
309
|
+
if (!byId) script.id = "facebook-jssdk";
|
|
310
|
+
script.src = "https://connect.facebook.net/en_US/sdk.js";
|
|
311
|
+
script.crossOrigin = "anonymous";
|
|
312
|
+
script.async = true;
|
|
313
|
+
script.defer = true;
|
|
314
|
+
}
|
|
315
|
+
shared2.cancelIfUnused();
|
|
316
|
+
if (settled) return;
|
|
317
|
+
Object.defineProperty(host, "fbAsyncInit", previous && !previous.configurable ? { value: onReady } : { configurable: true, enumerable: true, writable: true, value: onReady });
|
|
318
|
+
script.addEventListener("load", onLoad);
|
|
319
|
+
script.addEventListener("error", onError);
|
|
320
|
+
onLoad();
|
|
321
|
+
if (!settled && ownedScript) document.head.appendChild(script);
|
|
322
|
+
} catch (e) {
|
|
323
|
+
finish(void 0, new OmnizapiError("SDK_LOAD_FAILED", "The Meta SDK could not be loaded."));
|
|
147
324
|
}
|
|
148
|
-
}
|
|
149
|
-
if (runtime.facebookLoading === loading) delete runtime.facebookLoading;
|
|
150
|
-
if (sdk) resolve(sdk);
|
|
151
|
-
else reject(error);
|
|
325
|
+
}))
|
|
152
326
|
};
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
const
|
|
160
|
-
|
|
327
|
+
runtime.facebookLoadObserver = loading = shared2;
|
|
328
|
+
}
|
|
329
|
+
const shared = loading;
|
|
330
|
+
return new Promise((resolve, reject) => {
|
|
331
|
+
let settled = false;
|
|
332
|
+
shared.consumers++;
|
|
333
|
+
const complete = (sdk, error) => {
|
|
334
|
+
var _a;
|
|
161
335
|
if (settled) return;
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
336
|
+
settled = true;
|
|
337
|
+
signal.removeEventListener("abort", onAbort);
|
|
338
|
+
shared.consumers--;
|
|
339
|
+
if (sdk) resolve(sdk);
|
|
340
|
+
else reject(error);
|
|
341
|
+
(_a = shared.cancelIfUnused) == null ? void 0 : _a.call(shared);
|
|
167
342
|
};
|
|
168
|
-
const
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
}
|
|
178
|
-
previous = Object.getOwnPropertyDescriptor(host, "fbAsyncInit");
|
|
179
|
-
previousCallback = typeof host.fbAsyncInit === "function" ? host.fbAsyncInit : void 0;
|
|
180
|
-
Object.defineProperty(host, "fbAsyncInit", previous && !previous.configurable ? { value: onReady } : { configurable: true, enumerable: true, writable: true, value: onReady });
|
|
181
|
-
const document = host.document;
|
|
182
|
-
const byId = document.getElementById("facebook-jssdk");
|
|
183
|
-
const existingScript = (byId == null ? void 0 : byId.tagName.toLowerCase()) === "script" ? byId : void 0;
|
|
184
|
-
script = (existingScript && !runtime.failedFacebookScripts.has(existingScript) ? existingScript : void 0) || Array.from(document.scripts).find((candidate) => {
|
|
185
|
-
if (runtime.failedFacebookScripts.has(candidate)) return false;
|
|
186
|
-
try {
|
|
187
|
-
const url = new URL(candidate.src);
|
|
188
|
-
return url.origin === "https://connect.facebook.net" && /^\/[^/]+\/sdk\.js$/.test(url.pathname);
|
|
189
|
-
} catch (e) {
|
|
190
|
-
return false;
|
|
191
|
-
}
|
|
192
|
-
});
|
|
193
|
-
if (!script) {
|
|
194
|
-
script = document.createElement("script");
|
|
195
|
-
ownedScript = true;
|
|
196
|
-
if (!byId) script.id = "facebook-jssdk";
|
|
197
|
-
script.src = "https://connect.facebook.net/en_US/sdk.js";
|
|
198
|
-
script.crossOrigin = "anonymous";
|
|
199
|
-
script.async = true;
|
|
200
|
-
script.defer = true;
|
|
201
|
-
}
|
|
202
|
-
script.addEventListener("load", onLoad);
|
|
203
|
-
script.addEventListener("error", onError);
|
|
204
|
-
onLoad();
|
|
205
|
-
if (!settled && ownedScript) document.head.appendChild(script);
|
|
206
|
-
} catch (e) {
|
|
207
|
-
onError();
|
|
208
|
-
}
|
|
209
|
-
}));
|
|
210
|
-
runtime.facebookLoading = loading;
|
|
211
|
-
return loading;
|
|
343
|
+
const onAbort = () => complete(void 0, new OmnizapiError("SDK_LOAD_FAILED", "The Meta SDK load was cancelled."));
|
|
344
|
+
void shared.promise.then(
|
|
345
|
+
(sdk) => signal.aborted ? onAbort() : complete(sdk),
|
|
346
|
+
// A shared observer may belong to another module copy's OmnizapiError class.
|
|
347
|
+
(error) => complete(void 0, new OmnizapiError("SDK_LOAD_FAILED", error.message))
|
|
348
|
+
);
|
|
349
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
350
|
+
if (signal.aborted) onAbort();
|
|
351
|
+
});
|
|
212
352
|
}
|
|
213
353
|
|
|
214
354
|
// src/core/open-popup.ts
|
|
@@ -289,8 +429,8 @@ function requestJson(url, init, signal) {
|
|
|
289
429
|
else resolve(value);
|
|
290
430
|
};
|
|
291
431
|
const onAbort = () => complete(void 0, new OmnizapiError(
|
|
292
|
-
"
|
|
293
|
-
"The API request was
|
|
432
|
+
"ABORTED",
|
|
433
|
+
"The API request was aborted."
|
|
294
434
|
));
|
|
295
435
|
const timer = setTimeout(() => complete(void 0, new OmnizapiError(
|
|
296
436
|
"TIMEOUT",
|
|
@@ -347,10 +487,14 @@ var OmnizapiClientImpl = class {
|
|
|
347
487
|
frontUrl: props.frontUrl
|
|
348
488
|
});
|
|
349
489
|
}
|
|
350
|
-
async getListMessengerPages(channelId, code) {
|
|
490
|
+
async getListMessengerPages(channelId, code, signal) {
|
|
351
491
|
if (!stringOrNull(channelId) || !stringOrNull(code)) {
|
|
352
492
|
throw new OmnizapiError("INVALID_OPTIONS", "A channelId and authorization code are required.");
|
|
353
493
|
}
|
|
494
|
+
if (signal !== void 0 && (!isRecord(signal) || typeof signal.aborted !== "boolean" || typeof signal.addEventListener !== "function" || typeof signal.removeEventListener !== "function")) {
|
|
495
|
+
throw new OmnizapiError("INVALID_OPTIONS", "The abort signal is invalid.");
|
|
496
|
+
}
|
|
497
|
+
if (signal == null ? void 0 : signal.aborted) throw new OmnizapiError("ABORTED", "The API request was aborted.");
|
|
354
498
|
return requestJson(
|
|
355
499
|
new URL(`${this.constants.api}/v1/channels/${encodeChannelId(channelId)}/list-messenger-pages`),
|
|
356
500
|
{
|
|
@@ -360,7 +504,8 @@ var OmnizapiClientImpl = class {
|
|
|
360
504
|
code
|
|
361
505
|
}),
|
|
362
506
|
headers: { "Content-Type": "application/json", Authorization: this.publicKey }
|
|
363
|
-
}
|
|
507
|
+
},
|
|
508
|
+
signal
|
|
364
509
|
);
|
|
365
510
|
}
|
|
366
511
|
async connect(options) {
|
|
@@ -377,10 +522,11 @@ var OmnizapiClientImpl = class {
|
|
|
377
522
|
if (!isRecord(options)) {
|
|
378
523
|
throw new OmnizapiError("INVALID_OPTIONS", "Connection options are required.");
|
|
379
524
|
}
|
|
380
|
-
const { channelId, direct, getQRCode, timeoutMs = TOTAL_TIMEOUT_MS } = options;
|
|
381
|
-
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) {
|
|
382
|
-
throw new OmnizapiError("INVALID_OPTIONS", "Invalid channelId, direct, getQRCode or
|
|
525
|
+
const { channelId, direct, getQRCode, timeoutMs = TOTAL_TIMEOUT_MS, signal } = options;
|
|
526
|
+
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")) {
|
|
527
|
+
throw new OmnizapiError("INVALID_OPTIONS", "Invalid channelId, direct, getQRCode, timeoutMs or signal option.");
|
|
383
528
|
}
|
|
529
|
+
if (signal == null ? void 0 : signal.aborted) throw new OmnizapiError("ABORTED", "The connection was aborted.");
|
|
384
530
|
if (!channelId.trim()) return failure(channelId, null, "invalid_channel");
|
|
385
531
|
const encodedChannelId = encodeChannelId(channelId);
|
|
386
532
|
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") {
|
|
@@ -398,16 +544,28 @@ var OmnizapiClientImpl = class {
|
|
|
398
544
|
let channelType = null;
|
|
399
545
|
let redirectUri = null;
|
|
400
546
|
let popup = null;
|
|
547
|
+
let popupError;
|
|
401
548
|
let timeout;
|
|
402
549
|
let popupTimer;
|
|
403
550
|
let messageListener;
|
|
404
551
|
let nativeLoginStarted = false;
|
|
552
|
+
let callbackReceived = false;
|
|
553
|
+
const releaseNativeLogin = () => {
|
|
554
|
+
if (runtime.nativeLoginOwner === owner) {
|
|
555
|
+
runtime.nativeLoginPending = false;
|
|
556
|
+
delete runtime.nativeLoginOwner;
|
|
557
|
+
}
|
|
558
|
+
};
|
|
405
559
|
const globals = [];
|
|
406
560
|
const finish = (outcome) => {
|
|
407
561
|
if (settled) return;
|
|
408
562
|
settled = true;
|
|
409
563
|
clearTimeout(timeout);
|
|
410
564
|
clearInterval(popupTimer);
|
|
565
|
+
try {
|
|
566
|
+
signal == null ? void 0 : signal.removeEventListener("abort", onAbort);
|
|
567
|
+
} catch (e) {
|
|
568
|
+
}
|
|
411
569
|
if (messageListener) {
|
|
412
570
|
try {
|
|
413
571
|
host.removeEventListener("message", messageListener);
|
|
@@ -434,19 +592,49 @@ var OmnizapiClientImpl = class {
|
|
|
434
592
|
}
|
|
435
593
|
}
|
|
436
594
|
if (runtime.activeConnection === owner) delete runtime.activeConnection;
|
|
437
|
-
if (nativeLoginStarted && !(outcome instanceof OmnizapiError) && outcome.success) {
|
|
438
|
-
|
|
595
|
+
if (nativeLoginStarted && (callbackReceived || !(outcome instanceof OmnizapiError) && outcome.success)) {
|
|
596
|
+
releaseNativeLogin();
|
|
439
597
|
}
|
|
440
598
|
if (outcome instanceof OmnizapiError) reject(outcome);
|
|
441
599
|
else resolve(outcome);
|
|
442
600
|
};
|
|
601
|
+
const onAbort = () => finish(new OmnizapiError("ABORTED", "The connection was aborted."));
|
|
443
602
|
const isLive = () => {
|
|
603
|
+
if (!settled && (signal == null ? void 0 : signal.aborted)) onAbort();
|
|
444
604
|
if (!settled && Date.now() >= deadline) {
|
|
445
605
|
finish(new OmnizapiError("TIMEOUT", "The connection timed out."));
|
|
446
606
|
}
|
|
447
607
|
return !settled;
|
|
448
608
|
};
|
|
449
609
|
const fail = (reason) => finish(failure(channelId, channelType, reason));
|
|
610
|
+
const reservePopup = () => {
|
|
611
|
+
try {
|
|
612
|
+
const opened = openPopup("about:blank", "_blank", 600, 740);
|
|
613
|
+
if (!opened || opened === host) throw new Error("Popup unavailable");
|
|
614
|
+
if (!isLive()) {
|
|
615
|
+
opened.close();
|
|
616
|
+
return;
|
|
617
|
+
}
|
|
618
|
+
popup = opened;
|
|
619
|
+
} catch (e) {
|
|
620
|
+
throw new OmnizapiError("POPUP_BLOCKED", "The connection popup could not be opened.");
|
|
621
|
+
}
|
|
622
|
+
};
|
|
623
|
+
const watchPopup = () => {
|
|
624
|
+
if (popupTimer) return;
|
|
625
|
+
popupTimer = setInterval(() => {
|
|
626
|
+
if (!isLive()) return;
|
|
627
|
+
try {
|
|
628
|
+
if (popup == null ? void 0 : popup.closed) fail("popup_closed");
|
|
629
|
+
} catch (e) {
|
|
630
|
+
finish(new OmnizapiError("PROVIDER_ERROR", "The connection popup could not be monitored."));
|
|
631
|
+
}
|
|
632
|
+
}, 500);
|
|
633
|
+
};
|
|
634
|
+
const unwatchPopup = () => {
|
|
635
|
+
clearInterval(popupTimer);
|
|
636
|
+
popupTimer = void 0;
|
|
637
|
+
};
|
|
450
638
|
const succeed = (data) => {
|
|
451
639
|
if (!isLive() || !channelType) return;
|
|
452
640
|
finish({
|
|
@@ -465,6 +653,8 @@ var OmnizapiClientImpl = class {
|
|
|
465
653
|
};
|
|
466
654
|
try {
|
|
467
655
|
runtime.activeConnection = owner;
|
|
656
|
+
signal == null ? void 0 : signal.addEventListener("abort", onAbort, { once: true });
|
|
657
|
+
if (!isLive()) return;
|
|
468
658
|
const bytes = host.crypto.getRandomValues(new Uint8Array(16));
|
|
469
659
|
const attemptId = Array.from(bytes, (byte) => byte.toString(16).padStart(2, "0")).join("");
|
|
470
660
|
for (const [name, value] of [
|
|
@@ -480,6 +670,12 @@ var OmnizapiClientImpl = class {
|
|
|
480
670
|
"TIMEOUT",
|
|
481
671
|
"The connection timed out."
|
|
482
672
|
)), timeoutMs);
|
|
673
|
+
try {
|
|
674
|
+
reservePopup();
|
|
675
|
+
} catch (error) {
|
|
676
|
+
popupError = error instanceof OmnizapiError ? error : new OmnizapiError("POPUP_BLOCKED", "The connection popup could not be opened.");
|
|
677
|
+
}
|
|
678
|
+
if (!isLive()) return;
|
|
483
679
|
const run = async () => {
|
|
484
680
|
var _a2, _b, _c;
|
|
485
681
|
const info = await requestJson(
|
|
@@ -497,7 +693,13 @@ var OmnizapiClientImpl = class {
|
|
|
497
693
|
}
|
|
498
694
|
const middleware = info.middleware;
|
|
499
695
|
channelType = isChannelType(middleware) ? middleware : null;
|
|
500
|
-
if (currentOrigin !== frontOrigin && !allowOrigins.some((origin) =>
|
|
696
|
+
if (currentOrigin !== frontOrigin && !allowOrigins.some((origin) => {
|
|
697
|
+
try {
|
|
698
|
+
return currentOrigin === new URL(origin).origin;
|
|
699
|
+
} catch (e) {
|
|
700
|
+
return false;
|
|
701
|
+
}
|
|
702
|
+
})) {
|
|
501
703
|
fail("origin_not_allowed");
|
|
502
704
|
return;
|
|
503
705
|
}
|
|
@@ -510,26 +712,34 @@ var OmnizapiClientImpl = class {
|
|
|
510
712
|
if (channelType.startsWith("META_") && !appId || channelType === "META_WHATSAPP" && !configId) {
|
|
511
713
|
throw new OmnizapiError("INVALID_RESPONSE", "The channel provider configuration is invalid.");
|
|
512
714
|
}
|
|
513
|
-
|
|
715
|
+
const nativeWhatsApp = channelType === "META_WHATSAPP" && (direct || Boolean(info.appCustom) || currentOrigin === frontOrigin);
|
|
716
|
+
let nativeReady = false;
|
|
717
|
+
let fb;
|
|
718
|
+
if (nativeWhatsApp) {
|
|
719
|
+
unwatchPopup();
|
|
514
720
|
if (runtime.nativeLoginPending) {
|
|
515
721
|
throw new OmnizapiError(
|
|
516
722
|
"CONNECTION_IN_PROGRESS",
|
|
517
723
|
"A previous Meta login is incomplete. Reload this window before retrying a native login."
|
|
518
724
|
);
|
|
519
725
|
}
|
|
520
|
-
|
|
726
|
+
fb = await loadFacebookSdk(host, controller.signal);
|
|
521
727
|
if (!isLive()) return;
|
|
522
728
|
try {
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
729
|
+
initializeFacebookSdk(host, fb, appId);
|
|
730
|
+
nativeReady = true;
|
|
731
|
+
} catch (error) {
|
|
732
|
+
if (!(error instanceof OmnizapiError && error.code === "INVALID_CONFIGURATION")) throw error;
|
|
526
733
|
}
|
|
527
734
|
if (!isLive()) return;
|
|
735
|
+
}
|
|
736
|
+
if (nativeReady && fb) {
|
|
737
|
+
popup == null ? void 0 : popup.close();
|
|
738
|
+
popup = null;
|
|
528
739
|
let code = null;
|
|
529
740
|
let wabaId = null;
|
|
530
741
|
let phoneId = null;
|
|
531
742
|
let coexistence = false;
|
|
532
|
-
let callbackReceived = false;
|
|
533
743
|
const completeNative = () => {
|
|
534
744
|
if (!isLive() || !code || !wabaId) return;
|
|
535
745
|
succeed({ code, wabaId, phoneId, coexistence });
|
|
@@ -562,11 +772,17 @@ var OmnizapiClientImpl = class {
|
|
|
562
772
|
};
|
|
563
773
|
host.addEventListener("message", messageListener);
|
|
564
774
|
runtime.nativeLoginPending = true;
|
|
775
|
+
runtime.nativeLoginOwner = owner;
|
|
565
776
|
nativeLoginStarted = true;
|
|
566
777
|
try {
|
|
567
778
|
fb.login((response) => {
|
|
568
|
-
if (
|
|
779
|
+
if (callbackReceived) return;
|
|
569
780
|
callbackReceived = true;
|
|
781
|
+
if (settled) {
|
|
782
|
+
releaseNativeLogin();
|
|
783
|
+
return;
|
|
784
|
+
}
|
|
785
|
+
if (!isLive()) return;
|
|
570
786
|
if (!isRecord(response) || response.error) {
|
|
571
787
|
finish(new OmnizapiError("PROVIDER_ERROR", "Meta returned an invalid login response."));
|
|
572
788
|
return;
|
|
@@ -592,6 +808,8 @@ var OmnizapiClientImpl = class {
|
|
|
592
808
|
}
|
|
593
809
|
});
|
|
594
810
|
} catch (e) {
|
|
811
|
+
releaseNativeLogin();
|
|
812
|
+
nativeLoginStarted = false;
|
|
595
813
|
throw new OmnizapiError("PROVIDER_ERROR", "The Meta login could not be started.");
|
|
596
814
|
}
|
|
597
815
|
return;
|
|
@@ -618,6 +836,7 @@ var OmnizapiClientImpl = class {
|
|
|
618
836
|
} else {
|
|
619
837
|
url = new URL(`${this.constants.front}/connect/${channelType === "BOT_TELEGRAM" ? "telegram" : "whatsapp-web"}`);
|
|
620
838
|
url.searchParams.set("channelId", channelId);
|
|
839
|
+
url.searchParams.set("pk", this.publicKey);
|
|
621
840
|
}
|
|
622
841
|
if (channelType !== "META_MESSENGER" && channelType !== "META_INSTAGRAM") {
|
|
623
842
|
url.searchParams.set("attemptId", attemptId);
|
|
@@ -638,23 +857,18 @@ var OmnizapiClientImpl = class {
|
|
|
638
857
|
};
|
|
639
858
|
host.addEventListener("message", messageListener);
|
|
640
859
|
if (!isLive()) return;
|
|
860
|
+
if (popupError) throw popupError;
|
|
861
|
+
if (!popup) reservePopup();
|
|
862
|
+
if (popup == null ? void 0 : popup.closed) {
|
|
863
|
+
fail("popup_closed");
|
|
864
|
+
return;
|
|
865
|
+
}
|
|
866
|
+
watchPopup();
|
|
641
867
|
try {
|
|
642
|
-
|
|
643
|
-
if (!opened || opened === host) {
|
|
644
|
-
throw new OmnizapiError("POPUP_BLOCKED", "The connection popup was blocked.");
|
|
645
|
-
}
|
|
646
|
-
popup = opened;
|
|
868
|
+
popup == null ? void 0 : popup.location.replace(url.href);
|
|
647
869
|
} catch (e) {
|
|
648
|
-
throw new OmnizapiError("
|
|
870
|
+
throw new OmnizapiError("PROVIDER_ERROR", "The connection popup could not be navigated.");
|
|
649
871
|
}
|
|
650
|
-
popupTimer = setInterval(() => {
|
|
651
|
-
if (!isLive()) return;
|
|
652
|
-
try {
|
|
653
|
-
if (popup == null ? void 0 : popup.closed) fail("popup_closed");
|
|
654
|
-
} catch (e) {
|
|
655
|
-
finish(new OmnizapiError("PROVIDER_ERROR", "The connection popup could not be monitored."));
|
|
656
|
-
}
|
|
657
|
-
}, 500);
|
|
658
872
|
};
|
|
659
873
|
void run().catch((error) => {
|
|
660
874
|
if (!isLive()) return;
|
|
@@ -663,8 +877,8 @@ var OmnizapiClientImpl = class {
|
|
|
663
877
|
"The connection could not be completed."
|
|
664
878
|
));
|
|
665
879
|
});
|
|
666
|
-
} catch (
|
|
667
|
-
finish(new OmnizapiError("INVALID_CONFIGURATION", "The connection could not be initialized."));
|
|
880
|
+
} catch (error) {
|
|
881
|
+
finish(error instanceof OmnizapiError ? error : new OmnizapiError("INVALID_CONFIGURATION", "The connection could not be initialized."));
|
|
668
882
|
}
|
|
669
883
|
});
|
|
670
884
|
} catch (error) {
|