smartcomply-web-sdk 1.0.75 → 1.0.77
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/dist/esm/flow/SmartComplyFlow.d.ts +13 -0
- package/dist/esm/flow/SmartComplyFlow.d.ts.map +1 -1
- package/dist/esm/flow/SmartComplyFlow.js +113 -20
- package/dist/esm/flow/SmartComplyFlow.js.map +1 -1
- package/dist/esm/modules/liveness/liveness.d.ts.map +1 -1
- package/dist/esm/modules/liveness/liveness.js +12 -1
- package/dist/esm/modules/liveness/liveness.js.map +1 -1
- package/dist/flow/SmartComplyFlow.d.ts +13 -0
- package/dist/flow/SmartComplyFlow.d.ts.map +1 -1
- package/dist/flow/SmartComplyFlow.js +113 -20
- package/dist/flow/SmartComplyFlow.js.map +1 -1
- package/dist/modules/liveness/liveness.d.ts.map +1 -1
- package/dist/modules/liveness/liveness.js +12 -1
- package/dist/modules/liveness/liveness.js.map +1 -1
- package/dist/smartcomply.browser.js +65 -9
- package/dist/smartcomply.browser.js.map +2 -2
- package/package.json +1 -1
|
@@ -66,6 +66,7 @@ export declare class SmartComplyFlow {
|
|
|
66
66
|
private _ocrPollTimer;
|
|
67
67
|
private _uiTimeoutId;
|
|
68
68
|
private sessionExpiryTimer;
|
|
69
|
+
private sessionExpiredTimer;
|
|
69
70
|
private _pollStatusTimer;
|
|
70
71
|
private docCapture;
|
|
71
72
|
private constructor();
|
|
@@ -90,6 +91,9 @@ export declare class SmartComplyFlow {
|
|
|
90
91
|
private mount;
|
|
91
92
|
private initialize;
|
|
92
93
|
private _showExpiryWarningWhenSafe;
|
|
94
|
+
private static readonly MAX_EXPIRY_DEFERRALS;
|
|
95
|
+
private _expiryDeferrals;
|
|
96
|
+
private _enforceSessionExpiry;
|
|
93
97
|
private showStep;
|
|
94
98
|
private renderStep;
|
|
95
99
|
private renderLoading;
|
|
@@ -133,6 +137,15 @@ export declare class SmartComplyFlow {
|
|
|
133
137
|
/** Click handler that fires once and disables the button, preventing a double-tap double-dispatch. */
|
|
134
138
|
private _onceClick;
|
|
135
139
|
private isDocumentFlow;
|
|
140
|
+
/**
|
|
141
|
+
* True when the SDK Config is set to skip data/document verification
|
|
142
|
+
* entirely and only run the liveness/selfie check — no country picker,
|
|
143
|
+
* no ID-type picker, no ID-number entry or document capture. Unlike
|
|
144
|
+
* isDocumentFlow(), there's no channel-shape fallback to infer this from:
|
|
145
|
+
* a liveness-only config carries no channels at all, so the only signal
|
|
146
|
+
* is verification_type itself.
|
|
147
|
+
*/
|
|
148
|
+
private isLivenessOnlyFlow;
|
|
136
149
|
/**
|
|
137
150
|
* The "go back one step" target for a given step, if that step is
|
|
138
151
|
* navigable — shared by the header back button and the browser
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SmartComplyFlow.d.ts","sourceRoot":"","sources":["../../../src/flow/SmartComplyFlow.ts"],"names":[],"mappings":"AACA,OAAO,EAA6B,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAIxF,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAwC/C,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,IAAI,CAAC;IAC1C,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,kBAAkB,CAAC,EAAE,sBAAsB,CAAC;CAC7C;AAsRD,qBAAa,eAAe;IAC1B,OAAO,CAAC,GAAG,CAAc;IACzB,OAAO,CAAC,OAAO,CAAc;IAC7B,OAAO,CAAC,KAAK,CAAoC;IAGjD,OAAO,CAAC,OAAO,CAA+B;IAC9C,OAAO,CAAC,KAAK,CAA+B;IAC5C,OAAO,CAAC,WAAW,CAA+B;IAClD,OAAO,CAAC,WAAW,CAA+B;IAClD,OAAO,CAAC,SAAS,CAA+B;IAChD,OAAO,CAAC,SAAS,CAA+B;IAChD,OAAO,CAAC,UAAU,CAA+B;IAGjD,OAAO,CAAC,SAAS,CAA8B;IAC/C,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,eAAe,CAAc;IACrC,OAAO,CAAC,iBAAiB,CAAa;IACtC,OAAO,CAAC,qBAAqB,CAA6D;IAC1F,OAAO,CAAC,cAAc,CAAc;IACpC,OAAO,CAAC,kBAAkB,CAAc;IACxC,OAAO,CAAC,oBAAoB,CAAuC;IACnE,OAAO,CAAC,eAAe,CAA8B;IACrD,OAAO,CAAC,QAAQ,CAAc;IAC9B,OAAO,CAAC,YAAY,CAAqB;IACzC,OAAO,CAAC,gBAAgB,CAAqB;IAK7C,OAAO,CAAC,kBAAkB,CAAS;IACnC,OAAO,CAAC,eAAe,CAAuB;IAC9C,OAAO,CAAC,kBAAkB,CAAuC;IACjE,OAAO,CAAC,eAAe,CAAuB;IAC9C,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,aAAa,CAAkC;IACvD,OAAO,CAAC,eAAe,CAA6C;IACpE,OAAO,CAAC,kBAAkB,CAA6B;IACvD,OAAO,CAAC,WAAW,CAAuB;IAC1C,OAAO,CAAC,gBAAgB,CAA6B;IACrD,OAAO,CAAC,mBAAmB,CAAS;IAGpC,OAAO,CAAC,eAAe,CAAK;IAC5B,OAAO,CAAC,iBAAiB,CAAK;IAC9B,OAAO,CAAC,kBAAkB,CAAK;IAC/B,OAAO,CAAC,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAK;IAGxC,OAAO,CAAC,QAAQ,CAAc;IAC9B,OAAO,CAAC,UAAU,CAAc;IAGhC,OAAO,CAAC,QAAQ,CAAc;IAC9B,OAAO,CAAC,aAAa,CAAc;IACnC,OAAO,CAAC,UAAU,CAAc;IAChC,OAAO,CAAC,gBAAgB,CAAc;IACtC,OAAO,CAAC,aAAa,CAAkB;IACvC,OAAO,CAAC,cAAc,CAAkB;IAGxC,OAAO,CAAC,gBAAgB,CAA4B;IAGpD,OAAO,CAAC,aAAa,CAA8C;IAGnE,OAAO,CAAC,YAAY,CAA8C;IAGlE,OAAO,CAAC,kBAAkB,CAA8C;
|
|
1
|
+
{"version":3,"file":"SmartComplyFlow.d.ts","sourceRoot":"","sources":["../../../src/flow/SmartComplyFlow.ts"],"names":[],"mappings":"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"}
|
|
@@ -328,10 +328,12 @@ export class SmartComplyFlow {
|
|
|
328
328
|
this._uiTimeoutId = null;
|
|
329
329
|
// Session expiry
|
|
330
330
|
this.sessionExpiryTimer = null;
|
|
331
|
+
this.sessionExpiredTimer = null;
|
|
331
332
|
// Status polling (result screen)
|
|
332
333
|
this._pollStatusTimer = null;
|
|
333
334
|
// Components
|
|
334
335
|
this.docCapture = null;
|
|
336
|
+
this._expiryDeferrals = 0;
|
|
335
337
|
this.options = options;
|
|
336
338
|
this.sdk = new SmartComply({
|
|
337
339
|
apiKey: options.apiKey,
|
|
@@ -398,6 +400,10 @@ export class SmartComplyFlow {
|
|
|
398
400
|
clearTimeout(this.sessionExpiryTimer);
|
|
399
401
|
this.sessionExpiryTimer = null;
|
|
400
402
|
}
|
|
403
|
+
if (this.sessionExpiredTimer) {
|
|
404
|
+
clearTimeout(this.sessionExpiredTimer);
|
|
405
|
+
this.sessionExpiredTimer = null;
|
|
406
|
+
}
|
|
401
407
|
if (this._pollStatusTimer) {
|
|
402
408
|
clearTimeout(this._pollStatusTimer);
|
|
403
409
|
this._pollStatusTimer = null;
|
|
@@ -588,6 +594,15 @@ export class SmartComplyFlow {
|
|
|
588
594
|
const expiresMs = new Date(expiresAt).getTime() - Date.now();
|
|
589
595
|
const warnMs = Math.max(expiresMs - 120000, 0); // warn 2 min before
|
|
590
596
|
this.sessionExpiryTimer = setTimeout(() => this._showExpiryWarningWhenSafe(), warnMs);
|
|
597
|
+
// The warning above is advisory only and can defer indefinitely
|
|
598
|
+
// while the user sits on a camera-active step — without a hard
|
|
599
|
+
// stop, an ignored/deferred warning left the widget open against
|
|
600
|
+
// an already-expired backend session (SessionToken.expires_at,
|
|
601
|
+
// 30 min — see sdk/views.py's SessionToken.objects.create call)
|
|
602
|
+
// for as long as the host page stayed open. Force-close once the
|
|
603
|
+
// real deadline passes so the widget's lifetime never exceeds
|
|
604
|
+
// what the backend actually honors.
|
|
605
|
+
this.sessionExpiredTimer = setTimeout(() => this._enforceSessionExpiry(), Math.max(expiresMs, 0));
|
|
591
606
|
}
|
|
592
607
|
// Load config
|
|
593
608
|
this.sdkConfig = await this.sdk.initializeConfig();
|
|
@@ -621,6 +636,19 @@ export class SmartComplyFlow {
|
|
|
621
636
|
}
|
|
622
637
|
this.showErrorStep("Your session is about to expire. Please complete verification quickly or restart.");
|
|
623
638
|
}
|
|
639
|
+
_enforceSessionExpiry() {
|
|
640
|
+
if (this.isDestroyed)
|
|
641
|
+
return;
|
|
642
|
+
const cameraActiveSteps = ["document_capture", "liveness"];
|
|
643
|
+
if (cameraActiveSteps.includes(this.currentStep) &&
|
|
644
|
+
this._expiryDeferrals < SmartComplyFlow.MAX_EXPIRY_DEFERRALS) {
|
|
645
|
+
this._expiryDeferrals += 1;
|
|
646
|
+
this.sessionExpiredTimer = setTimeout(() => this._enforceSessionExpiry(), 5000);
|
|
647
|
+
return;
|
|
648
|
+
}
|
|
649
|
+
this.showErrorStep("Your session has expired. Please restart verification.");
|
|
650
|
+
this.close();
|
|
651
|
+
}
|
|
624
652
|
// ─────────────────────────────────────────────────────────────────
|
|
625
653
|
// Step rendering
|
|
626
654
|
// ─────────────────────────────────────────────────────────────────
|
|
@@ -739,7 +767,8 @@ export class SmartComplyFlow {
|
|
|
739
767
|
// ── Welcome ────────────────────────────────────────────────────
|
|
740
768
|
renderWelcome(container) {
|
|
741
769
|
container.style.cssText += "display:flex;flex-direction:column;align-items:center;text-align:center;gap:12px;";
|
|
742
|
-
const
|
|
770
|
+
const isLivenessOnly = this.isLivenessOnlyFlow();
|
|
771
|
+
const isDocFlow = isLivenessOnly ? false : this.isDocumentFlow();
|
|
743
772
|
// Icon + badge row (side by side to save vertical space)
|
|
744
773
|
const topRow = document.createElement("div");
|
|
745
774
|
topRow.style.cssText = "display:flex;flex-direction:column;align-items:center;gap:8px;";
|
|
@@ -762,7 +791,9 @@ export class SmartComplyFlow {
|
|
|
762
791
|
color:${this.theme.primary};
|
|
763
792
|
border:1px solid ${this.theme.primary}30;
|
|
764
793
|
`;
|
|
765
|
-
badge.textContent =
|
|
794
|
+
badge.textContent = isLivenessOnly
|
|
795
|
+
? "🤳 Liveness Check"
|
|
796
|
+
: isDocFlow ? "📄 Document Verification" : "🔍 Data Verification";
|
|
766
797
|
topRow.appendChild(badge);
|
|
767
798
|
container.appendChild(topRow);
|
|
768
799
|
// Title + subtitle (compact)
|
|
@@ -784,23 +815,29 @@ export class SmartComplyFlow {
|
|
|
784
815
|
color:${this.theme.textSecondary};font-size:13px;line-height:1.5;
|
|
785
816
|
margin:0 auto;max-width:300px;text-align:center;
|
|
786
817
|
`;
|
|
787
|
-
desc.textContent =
|
|
788
|
-
? "You'll need
|
|
789
|
-
:
|
|
818
|
+
desc.textContent = isLivenessOnly
|
|
819
|
+
? "You'll just need camera access. This takes about 30 seconds."
|
|
820
|
+
: isDocFlow
|
|
821
|
+
? "You'll need your document and camera access. This takes about 2 minutes."
|
|
822
|
+
: "You'll need your ID number and camera access. This takes about 2 minutes.";
|
|
790
823
|
titleWrap.appendChild(desc);
|
|
791
824
|
container.appendChild(titleWrap);
|
|
792
825
|
// Steps preview — compact rows
|
|
793
|
-
const steps =
|
|
826
|
+
const steps = isLivenessOnly
|
|
794
827
|
? [
|
|
795
|
-
{ icon: "🪪", text: "Choose your document type", sub: "Passport, National ID, Driver License" },
|
|
796
|
-
{ icon: "📷", text: "Scan your document", sub: "Upload or capture a photo of your ID" },
|
|
797
828
|
{ icon: "🤳", text: "Face check", sub: "Quick selfie to confirm it's you" },
|
|
798
829
|
]
|
|
799
|
-
:
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
830
|
+
: isDocFlow
|
|
831
|
+
? [
|
|
832
|
+
{ icon: "🪪", text: "Choose your document type", sub: "Passport, National ID, Driver License" },
|
|
833
|
+
{ icon: "📷", text: "Scan your document", sub: "Upload or capture a photo of your ID" },
|
|
834
|
+
{ icon: "🤳", text: "Face check", sub: "Quick selfie to confirm it's you" },
|
|
835
|
+
]
|
|
836
|
+
: [
|
|
837
|
+
{ icon: "🆔", text: "Choose your ID type", sub: "NIN, BVN, Voter's Card and more" },
|
|
838
|
+
{ icon: "📝", text: "Enter your ID details", sub: "Exactly as shown on your ID" },
|
|
839
|
+
{ icon: "🤳", text: "Face check", sub: "Quick selfie to confirm it's you" },
|
|
840
|
+
];
|
|
804
841
|
const stepsWrap = document.createElement("div");
|
|
805
842
|
stepsWrap.style.cssText = `
|
|
806
843
|
width:100%;display:flex;flex-direction:column;gap:0;
|
|
@@ -842,7 +879,27 @@ export class SmartComplyFlow {
|
|
|
842
879
|
// CTA
|
|
843
880
|
const btn = this.createPrimaryButton("Get Started →");
|
|
844
881
|
btn.style.cssText += "margin-top:2px;";
|
|
845
|
-
btn.addEventListener("click", () =>
|
|
882
|
+
btn.addEventListener("click", () => {
|
|
883
|
+
if (isLivenessOnly) {
|
|
884
|
+
// Liveness-only has no channels at all, so renderCountrySelect's
|
|
885
|
+
// single-country auto-skip (countries.length === 1) never fires for
|
|
886
|
+
// it — going through "country" here would render an empty,
|
|
887
|
+
// dead-end country-picker screen. Go straight to liveness instead.
|
|
888
|
+
//
|
|
889
|
+
// selectedCountry defaults to "" and is otherwise only ever set by
|
|
890
|
+
// renderCountrySelect, which this mode never visits — renderLiveness
|
|
891
|
+
// sends it as a required, non-blank `country` field, so leaving it
|
|
892
|
+
// empty would fail create() validation before the scan even starts.
|
|
893
|
+
// There's no real country to report here (no identity lookup runs
|
|
894
|
+
// in this mode), so this is a neutral placeholder, not a claim
|
|
895
|
+
// about the user's actual location.
|
|
896
|
+
this.selectedCountry = this.selectedCountry || "global";
|
|
897
|
+
this.showStep("liveness");
|
|
898
|
+
}
|
|
899
|
+
else {
|
|
900
|
+
this.showStep("country");
|
|
901
|
+
}
|
|
902
|
+
});
|
|
846
903
|
container.appendChild(btn);
|
|
847
904
|
// Plain-language line on what the camera/photo is for and what happens
|
|
848
905
|
// to it — shown before the "Get Started" tap that leads to the first
|
|
@@ -2386,6 +2443,21 @@ export class SmartComplyFlow {
|
|
|
2386
2443
|
.flatMap((ch) => ch.fields || []);
|
|
2387
2444
|
return allFields.some((f) => isUploadFieldType(f.type));
|
|
2388
2445
|
}
|
|
2446
|
+
/**
|
|
2447
|
+
* True when the SDK Config is set to skip data/document verification
|
|
2448
|
+
* entirely and only run the liveness/selfie check — no country picker,
|
|
2449
|
+
* no ID-type picker, no ID-number entry or document capture. Unlike
|
|
2450
|
+
* isDocumentFlow(), there's no channel-shape fallback to infer this from:
|
|
2451
|
+
* a liveness-only config carries no channels at all, so the only signal
|
|
2452
|
+
* is verification_type itself.
|
|
2453
|
+
*/
|
|
2454
|
+
isLivenessOnlyFlow() {
|
|
2455
|
+
const vType = this.sdkConfig?.verification_type;
|
|
2456
|
+
if (!vType)
|
|
2457
|
+
return false;
|
|
2458
|
+
const types = Array.isArray(vType) ? vType : [vType];
|
|
2459
|
+
return types.includes("liveness_only");
|
|
2460
|
+
}
|
|
2389
2461
|
/**
|
|
2390
2462
|
* The "go back one step" target for a given step, if that step is
|
|
2391
2463
|
* navigable — shared by the header back button and the browser
|
|
@@ -2402,16 +2474,28 @@ export class SmartComplyFlow {
|
|
|
2402
2474
|
document_capture: () => { this.docCapture?.destroy(); this.showStep("id_type"); },
|
|
2403
2475
|
document_confirm: () => { this.docCapture?.destroy(); this.showStep("document_capture"); },
|
|
2404
2476
|
};
|
|
2477
|
+
// liveness-only skips straight from welcome to liveness with nothing in
|
|
2478
|
+
// between — deliberately no backTargets["liveness"] entry added here,
|
|
2479
|
+
// so the back button stays hidden on that step in this mode, same as
|
|
2480
|
+
// it already is for every other mode (liveness has no back target for
|
|
2481
|
+
// document/data flows either — nothing to go back to except closing).
|
|
2405
2482
|
return backTargets[step];
|
|
2406
2483
|
}
|
|
2407
2484
|
updateProgress() {
|
|
2408
|
-
const
|
|
2485
|
+
const isLivenessOnly = this.isLivenessOnlyFlow();
|
|
2486
|
+
const isDocFlow = isLivenessOnly ? false : this.isDocumentFlow();
|
|
2409
2487
|
const countries = Object.keys(this.sdkConfig?.channels || {});
|
|
2410
2488
|
const singleCountry = countries.length <= 1;
|
|
2411
|
-
// Two-stage action steps — Stage 1: validate identity, Stage 2: liveness
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2489
|
+
// Two-stage action steps — Stage 1: validate identity, Stage 2: liveness.
|
|
2490
|
+
// Liveness-only has no Stage 1 at all — welcome goes straight to
|
|
2491
|
+
// liveness — so stage1Steps stays empty and the progress bar reflects
|
|
2492
|
+
// a genuinely single-stage flow instead of implying a step that never
|
|
2493
|
+
// happens in this mode.
|
|
2494
|
+
const stage1Steps = isLivenessOnly
|
|
2495
|
+
? []
|
|
2496
|
+
: isDocFlow
|
|
2497
|
+
? ["country", "id_type", "document_capture", "ocr_gate", "document_confirm"].filter(s => !(s === "country" && singleCountry))
|
|
2498
|
+
: ["country", "id_type", "id_input", "confirm_identity"].filter(s => !(s === "country" && singleCountry));
|
|
2415
2499
|
const stage2Steps = ["liveness"];
|
|
2416
2500
|
const allActionSteps = [...stage1Steps, ...stage2Steps];
|
|
2417
2501
|
const totalSteps = allActionSteps.length;
|
|
@@ -2423,6 +2507,8 @@ export class SmartComplyFlow {
|
|
|
2423
2507
|
this.progressBar.style.width = `${pct}%`;
|
|
2424
2508
|
}
|
|
2425
2509
|
// Stage label: "Stage 1 of 2: Verify Identity" / "Stage 2 of 2: Face Check"
|
|
2510
|
+
// — liveness-only has no Stage 1, so it just says "Face Check" with no
|
|
2511
|
+
// "of 2" framing, since there's only ever the one stage in this mode.
|
|
2426
2512
|
if (this.stepLabel) {
|
|
2427
2513
|
if (this.currentStep === "loading" || this.currentStep === "welcome") {
|
|
2428
2514
|
this.stepLabel.textContent = "";
|
|
@@ -2431,7 +2517,7 @@ export class SmartComplyFlow {
|
|
|
2431
2517
|
this.stepLabel.textContent = "Complete ✓";
|
|
2432
2518
|
}
|
|
2433
2519
|
else if (stage2Steps.includes(this.currentStep)) {
|
|
2434
|
-
this.stepLabel.textContent = "Stage 2 of 2: Face Check";
|
|
2520
|
+
this.stepLabel.textContent = isLivenessOnly ? "Face Check" : "Stage 2 of 2: Face Check";
|
|
2435
2521
|
}
|
|
2436
2522
|
else if (stage1Steps.includes(this.currentStep)) {
|
|
2437
2523
|
this.stepLabel.textContent = isDocFlow ? "Stage 1 of 2: Scan Document" : "Stage 1 of 2: Verify Identity";
|
|
@@ -2521,4 +2607,11 @@ export class SmartComplyFlow {
|
|
|
2521
2607
|
}
|
|
2522
2608
|
}
|
|
2523
2609
|
SmartComplyFlow.MAX_RETRIES = 3;
|
|
2610
|
+
// Hard stop once the backend session (SessionToken.expires_at, 30 min)
|
|
2611
|
+
// has actually passed. Deferred the same way as the warning above while
|
|
2612
|
+
// a camera is live so we don't tear down an in-progress scan, but capped
|
|
2613
|
+
// — the earlier warning already gave the user 2 minutes' notice, so
|
|
2614
|
+
// there's no reason to keep deferring past a short grace window the way
|
|
2615
|
+
// the advisory warning does.
|
|
2616
|
+
SmartComplyFlow.MAX_EXPIRY_DEFERRALS = 12; // 12 * 5s = 60s grace
|
|
2524
2617
|
//# sourceMappingURL=SmartComplyFlow.js.map
|