@abyss-project/commons-front-core 3.3.2 → 4.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{CookieConsentSettings.component-tRVw_4zH.js → CookieConsentSettings.component-B06_BnQP.js} +2703 -2118
- package/dist/auth/client/auth-bridge.d.ts +51 -0
- package/dist/auth/client/auth-client.d.ts +125 -0
- package/dist/auth/client/auth-client.spec.d.ts +1 -0
- package/dist/auth/client/capacitor-bridge.d.ts +16 -0
- package/dist/auth/client/index.d.ts +6 -0
- package/dist/auth/client/native-bridge.d.ts +53 -0
- package/dist/auth/client/native-bridge.spec.d.ts +1 -0
- package/dist/auth/client/token-storage.d.ts +31 -0
- package/dist/auth/client/web-bridge.d.ts +13 -0
- package/dist/auth/client/web-bridge.spec.d.ts +1 -0
- package/dist/auth/components/AuthFlow/AuthFlow.component.d.ts +30 -0
- package/dist/auth/components/AuthFlow/AuthFlow.component.spec.d.ts +1 -0
- package/dist/auth/components/AuthFlow/auth-flow.types.d.ts +62 -0
- package/dist/auth/components/AuthFlow/steps/CodeStep.component.d.ts +17 -0
- package/dist/auth/components/AuthFlow/steps/EmailStep.component.d.ts +22 -0
- package/dist/auth/components/AuthFlow/steps/MfaEnrollmentStep.component.d.ts +13 -0
- package/dist/auth/components/AuthFlow/steps/MfaStep.component.d.ts +20 -0
- package/dist/auth/components/AuthFlow/steps/PasskeyNudgeStep.component.d.ts +11 -0
- package/dist/auth/components/AuthFlow/steps/PasswordStep.component.d.ts +17 -0
- package/dist/auth/components/AuthFlow/steps/SignupStep.component.d.ts +24 -0
- package/dist/auth/components/AuthFlow/steps/steps.autocomplete.spec.d.ts +1 -0
- package/dist/auth/components/AuthProviderButtons/AuthProviderButtons.component.d.ts +30 -0
- package/dist/auth/components/MfaRequirementBanner/MfaRequirementBanner.component.d.ts +12 -0
- package/dist/auth/components/MfaRequirementBanner/MfaRequirementBanner.component.spec.d.ts +1 -0
- package/dist/auth/components/ReauthDialog/AuthReauthHost.component.d.ts +8 -0
- package/dist/auth/components/ReauthDialog/ReauthDialog.component.d.ts +22 -0
- package/dist/auth/components/ReauthDialog/ReauthDialog.component.spec.d.ts +1 -0
- package/dist/auth/components/SecuritySettings/SecuritySettings.component.d.ts +7 -0
- package/dist/auth/components/SecuritySettings/SecuritySettings.component.spec.d.ts +1 -0
- package/dist/auth/components/SecuritySettings/sections/EmailSection.component.d.ts +6 -0
- package/dist/auth/components/SecuritySettings/sections/PasskeysSection.component.d.ts +10 -0
- package/dist/auth/components/SecuritySettings/sections/PasswordSection.component.d.ts +9 -0
- package/dist/auth/components/SecuritySettings/sections/RecoveryCodesSection.component.d.ts +10 -0
- package/dist/auth/components/SecuritySettings/sections/SecuritySection.component.d.ts +26 -0
- package/dist/auth/components/SecuritySettings/sections/SessionsSection.component.d.ts +8 -0
- package/dist/auth/components/SecuritySettings/sections/TotpSection.component.d.ts +11 -0
- package/dist/auth/components/SecuritySettings/sections/use-section-action.hook.d.ts +9 -0
- package/dist/auth/components/index.d.ts +11 -0
- package/dist/auth/components/shared/AuthStepFrame.component.d.ts +19 -0
- package/dist/auth/components/shared/OneTimeCodeField.component.d.ts +17 -0
- package/dist/auth/components/shared/RecoveryCodesPanel.component.d.ts +12 -0
- package/dist/auth/components/shared/TotpSetupPanel.component.d.ts +14 -0
- package/dist/auth/components/shared/auth-errors.d.ts +42 -0
- package/dist/auth/components/shared/mfa-status-events.d.ts +2 -0
- package/dist/auth/components/shared/passkey-ceremonies.d.ts +17 -0
- package/dist/auth/components/shared/use-async-resource.hook.d.ts +18 -0
- package/dist/auth/components/shared/use-offline.hook.d.ts +2 -0
- package/dist/auth/components/shared/use-passkey-name.hook.d.ts +5 -0
- package/dist/auth/components/test-support/auth-sdk.mock.d.ts +57 -0
- package/dist/auth/components/test-support/auth-test-harness.d.ts +48 -0
- package/dist/auth/index.d.ts +2 -0
- package/dist/auth/react/AuthProvider.component.d.ts +15 -0
- package/dist/auth/react/AuthProvider.component.spec.d.ts +1 -0
- package/dist/auth/react/use-auth.hook.d.ts +3 -0
- package/dist/auth-client.d.ts +2 -0
- package/dist/auth-client.js +26 -0
- package/dist/auth-native.d.ts +2 -0
- package/dist/auth-native.js +84 -0
- package/dist/components/Layouts/AbyssLayoutProvider/AbyssLayoutProvider.component.d.ts +2 -3
- package/dist/components/Layouts/AbyssLayoutProvider/abyss-layout.store.d.ts +1 -1
- package/dist/components/Support/SupportTicketDetail.mobile-layout.spec.d.ts +1 -0
- package/dist/cookie-consent.js +1 -1
- package/dist/hooks/use-rich-intl.hook.d.ts +654 -4
- package/dist/{index-g_LMIl_j.js → index-B99FVtM1.js} +2 -2
- package/dist/{index-Cy5aV6-7.js → index-BAiia-Dl.js} +4 -4
- package/dist/{index-CSOs_Ccx.js → index-BI56obfe.js} +1 -1
- package/dist/{index-sAQE8yH0.js → index-BLjfAtDQ.js} +2 -2
- package/dist/{index-BHSTpRDB.js → index-BQMgvLh9.js} +4 -4
- package/dist/{index-Bb8UEu0K.js → index-BU5c0hG9.js} +3 -3
- package/dist/{index-CJghyDOF.js → index-B_rGVaUU.js} +2 -2
- package/dist/{index-nT4uFN7k.js → index-BokeagcV.js} +3 -3
- package/dist/{index-N73aWpoj.js → index-C36LEiRs.js} +2 -2
- package/dist/{index-Dn4CNQkV.js → index-C4fkwJmM.js} +2 -2
- package/dist/{index-TbU1rvxC.js → index-COBKSaJ6.js} +2 -2
- package/dist/{index-DUuSQC1S.js → index-CQcl-JnX.js} +2 -2
- package/dist/{index-BDwKynBn.js → index-Cp_oEtd_.js} +33265 -30088
- package/dist/{index-DUxqfZmd.js → index-D1vKJSB3.js} +3 -3
- package/dist/index-D7cgykJH.js +324 -0
- package/dist/{index-C2SpycHF.js → index-DA5MOwJ6.js} +2 -2
- package/dist/{index-DDBCCwMT.js → index-DAEl7d3x.js} +2 -2
- package/dist/{index-D84kdr5l.js → index-DPDhWaXC.js} +2 -2
- package/dist/{index-Hf4VgoUQ.js → index-Dy57KM7a.js} +2 -2
- package/dist/{index-BDI9bSnM.js → index-QsS__hk5.js} +3 -3
- package/dist/{index-D8hjJcQ2.js → index-cHPTPlez.js} +2 -2
- package/dist/{index-DlNShbQC.js → index-pmj-p-Pq.js} +2 -2
- package/dist/{index-DcZU8Tc4.js → index-rgzxHuXo.js} +4 -4
- package/dist/index.d.ts +1 -0
- package/dist/index.js +273 -242
- package/dist/token-storage-D3e11ePD.js +38 -0
- package/dist/translations/en.d.ts +289 -0
- package/dist/translations/fr.d.ts +289 -0
- package/dist/translations/translations-parity.spec.d.ts +1 -0
- package/dist/use-auth.hook-B_TU5W3g.js +391 -0
- package/dist/utils/billing.utils.d.ts +2 -2
- package/dist/utils/cookie.utils.d.ts +1 -1
- package/dist/utils/space-display-name.utils.d.ts +2 -2
- package/package.json +32 -10
- package/scripts/check-auth-entry-isolation.cjs +140 -0
- package/vite.config.ts +24 -1
- package/vitest.config.ts +1 -1
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
import { MfaFactorType as U, SessionPlatform as B, AbyssCore as F, Code as J, AuthResultStatus as X } from "@abyss-project/main";
|
|
2
|
+
import { browserSupportsWebAuthn as g, startRegistration as $, browserSupportsWebAuthnAutofill as V, startAuthentication as Q, WebAuthnError as Z } from "@simplewebauthn/browser";
|
|
3
|
+
import { a as c, A as d, s as ee } from "./token-storage-D3e11ePD.js";
|
|
4
|
+
import { createContext as te, useState as ne, useEffect as se, useMemo as re, useContext as oe } from "react";
|
|
5
|
+
import { jsx as ae } from "react/jsx-runtime";
|
|
6
|
+
var ie = /* @__PURE__ */ ((e) => (e.LOADING = "loading", e.ANONYMOUS = "anonymous", e.AUTHENTICATED = "authenticated", e))(ie || {}), ue = /* @__PURE__ */ ((e) => (e.PASSKEY = "passkey", e.TOTP = "totp", e.PASSWORD = "password", e.EMAIL_CODE = "email-code", e))(ue || {});
|
|
7
|
+
const le = 6e4, x = 3e4, ce = [
|
|
8
|
+
500,
|
|
9
|
+
1e3,
|
|
10
|
+
2e3
|
|
11
|
+
], de = [
|
|
12
|
+
7500,
|
|
13
|
+
15e3,
|
|
14
|
+
22500,
|
|
15
|
+
27e3
|
|
16
|
+
], G = 3e4, fe = 5e3, pe = "abyss-auth-refresh", he = 2147483647, we = "Token Expired", Ee = (e) => typeof e == "object" && e !== null && e.isAxiosError === !0, H = (e) => {
|
|
17
|
+
var r;
|
|
18
|
+
if (!Ee(e) || e.code === "ERR_CANCELED")
|
|
19
|
+
return { kind: "other" };
|
|
20
|
+
if (!e.response)
|
|
21
|
+
return { kind: "network" };
|
|
22
|
+
const s = (r = e.response.data) == null ? void 0 : r.error;
|
|
23
|
+
return {
|
|
24
|
+
kind: "http",
|
|
25
|
+
status: e.response.status,
|
|
26
|
+
code: s == null ? void 0 : s.code,
|
|
27
|
+
message: s == null ? void 0 : s.message,
|
|
28
|
+
params: s == null ? void 0 : s.params
|
|
29
|
+
};
|
|
30
|
+
}, me = /* @__PURE__ */ new Map([
|
|
31
|
+
[
|
|
32
|
+
U.TOTP,
|
|
33
|
+
"totp"
|
|
34
|
+
/* TOTP */
|
|
35
|
+
],
|
|
36
|
+
[
|
|
37
|
+
U.PASSKEY,
|
|
38
|
+
"passkey"
|
|
39
|
+
/* PASSKEY */
|
|
40
|
+
]
|
|
41
|
+
]), Ae = (e) => {
|
|
42
|
+
const s = e == null ? void 0 : e.methods;
|
|
43
|
+
return Array.isArray(s) ? {
|
|
44
|
+
methods: s.flatMap((r) => {
|
|
45
|
+
const i = me.get(r);
|
|
46
|
+
return i ? [i] : [];
|
|
47
|
+
})
|
|
48
|
+
} : {};
|
|
49
|
+
}, ye = (e) => new Promise((s) => setTimeout(s, e)), Re = () => typeof navigator > "u" || navigator.onLine !== !1, Te = () => typeof navigator > "u" ? null : navigator.locks ?? null, De = (e) => {
|
|
50
|
+
const s = e.bridge.platform === B.WEB, r = e.isOnline ?? Re;
|
|
51
|
+
let i = {
|
|
52
|
+
status: "loading"
|
|
53
|
+
/* LOADING */
|
|
54
|
+
}, a = null, n = null, E = null, y = null, _ = null, m = null, p = null, l = null, A = 0;
|
|
55
|
+
const R = /* @__PURE__ */ new Set(), T = /* @__PURE__ */ new Set(), S = (t) => {
|
|
56
|
+
i = t, R.forEach((o) => o(i));
|
|
57
|
+
}, D = (t) => {
|
|
58
|
+
a = t, e.applyToken(t), T.forEach((o) => o(t));
|
|
59
|
+
}, k = () => {
|
|
60
|
+
m && (clearTimeout(m), m = null), p && (clearTimeout(p), p = null);
|
|
61
|
+
}, K = (t) => {
|
|
62
|
+
const o = Date.parse(t);
|
|
63
|
+
if (!Number.isFinite(o))
|
|
64
|
+
return;
|
|
65
|
+
const u = Math.min(
|
|
66
|
+
Math.max(o - le - Date.now(), 0),
|
|
67
|
+
he
|
|
68
|
+
);
|
|
69
|
+
m = setTimeout(() => {
|
|
70
|
+
m = null, h.refresh();
|
|
71
|
+
}, u);
|
|
72
|
+
}, P = async (t) => {
|
|
73
|
+
var o;
|
|
74
|
+
k(), t.refreshToken && await e.storage.setRefreshToken(t.refreshToken), D(t.accessToken), n = t.user, (o = e.onPersistUser) == null || o.call(e, t.user), S({
|
|
75
|
+
status: "authenticated",
|
|
76
|
+
user: t.user,
|
|
77
|
+
mfaEnrollmentRequired: t.mfaEnrollmentRequired,
|
|
78
|
+
offline: !1
|
|
79
|
+
}), K(t.accessTokenExpiresAt);
|
|
80
|
+
}, N = async () => {
|
|
81
|
+
var t;
|
|
82
|
+
A += 1, k(), l = null, await e.storage.setRefreshToken(null), D(null), n = null, (t = e.onPersistUser) == null || t.call(e, null), S({
|
|
83
|
+
status: "anonymous"
|
|
84
|
+
/* ANONYMOUS */
|
|
85
|
+
});
|
|
86
|
+
}, j = () => {
|
|
87
|
+
if (l === null)
|
|
88
|
+
return G;
|
|
89
|
+
const t = Date.now() - l, o = de.find(
|
|
90
|
+
(u) => u > t && u < x
|
|
91
|
+
);
|
|
92
|
+
return o === void 0 ? (l = null, G) : o - t;
|
|
93
|
+
}, z = () => {
|
|
94
|
+
k();
|
|
95
|
+
const t = i.user ?? n;
|
|
96
|
+
S(
|
|
97
|
+
t ? {
|
|
98
|
+
status: "authenticated",
|
|
99
|
+
user: t,
|
|
100
|
+
mfaEnrollmentRequired: i.mfaEnrollmentRequired,
|
|
101
|
+
offline: !0
|
|
102
|
+
} : { status: "anonymous", offline: !0 }
|
|
103
|
+
), p = setTimeout(() => {
|
|
104
|
+
p = null, h.refresh();
|
|
105
|
+
}, j());
|
|
106
|
+
}, I = async () => {
|
|
107
|
+
const t = s ? null : await e.storage.getRefreshToken();
|
|
108
|
+
if (!s && !t)
|
|
109
|
+
return { kind: "revoked" };
|
|
110
|
+
if (!r())
|
|
111
|
+
return { kind: "offline" };
|
|
112
|
+
const o = Date.now(), u = new AbortController(), f = setTimeout(
|
|
113
|
+
() => u.abort(),
|
|
114
|
+
fe
|
|
115
|
+
);
|
|
116
|
+
try {
|
|
117
|
+
const w = await F.sdk.auth.refresh(
|
|
118
|
+
t ? { refreshToken: t } : void 0,
|
|
119
|
+
{ signal: u.signal }
|
|
120
|
+
);
|
|
121
|
+
return w.error ? { kind: "unreachable", sentAt: o } : { kind: "session", session: w.data };
|
|
122
|
+
} catch (w) {
|
|
123
|
+
if (u.signal.aborted)
|
|
124
|
+
return { kind: "unreachable", sentAt: o };
|
|
125
|
+
const L = H(w);
|
|
126
|
+
if (L.kind === "other")
|
|
127
|
+
throw w;
|
|
128
|
+
return L.kind === "http" && L.status === 401 ? { kind: "revoked" } : { kind: "unreachable", sentAt: o };
|
|
129
|
+
} finally {
|
|
130
|
+
clearTimeout(f);
|
|
131
|
+
}
|
|
132
|
+
}, O = async () => {
|
|
133
|
+
const t = A;
|
|
134
|
+
l !== null && Date.now() - l >= x && (l = null);
|
|
135
|
+
let o = await I();
|
|
136
|
+
const u = l === null ? ce : [];
|
|
137
|
+
for (const f of u) {
|
|
138
|
+
if (o.kind !== "unreachable" || t !== A || (l = l ?? o.sentAt, await ye(f), t !== A))
|
|
139
|
+
break;
|
|
140
|
+
o = await I();
|
|
141
|
+
}
|
|
142
|
+
if (o.kind === "unreachable" ? l = l ?? o.sentAt : o.kind !== "offline" && (l = null), t !== A) {
|
|
143
|
+
e.applyToken(a);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
switch (o.kind) {
|
|
147
|
+
case "session":
|
|
148
|
+
await P(o.session);
|
|
149
|
+
return;
|
|
150
|
+
case "revoked":
|
|
151
|
+
await N();
|
|
152
|
+
return;
|
|
153
|
+
case "offline":
|
|
154
|
+
case "unreachable":
|
|
155
|
+
z();
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
}, b = () => {
|
|
159
|
+
i.offline && (p && (clearTimeout(p), p = null), h.refresh());
|
|
160
|
+
}, M = () => {
|
|
161
|
+
document.visibilityState === "visible" && b();
|
|
162
|
+
};
|
|
163
|
+
typeof window < "u" && window.addEventListener("online", b), typeof document < "u" && document.addEventListener("visibilitychange", M);
|
|
164
|
+
const h = {
|
|
165
|
+
bridge: e.bridge,
|
|
166
|
+
state: () => i,
|
|
167
|
+
subscribe: (t) => (R.add(t), () => {
|
|
168
|
+
R.delete(t);
|
|
169
|
+
}),
|
|
170
|
+
accessToken: () => a,
|
|
171
|
+
subscribeToken: (t) => (T.add(t), t(a), () => {
|
|
172
|
+
T.delete(t);
|
|
173
|
+
}),
|
|
174
|
+
bootstrap: () => (_ || (_ = (async () => {
|
|
175
|
+
var t;
|
|
176
|
+
n = await ((t = e.restoreUser) == null ? void 0 : t.call(e)) ?? null, await h.refresh();
|
|
177
|
+
})()), _),
|
|
178
|
+
handleResult: async (t) => (t.status === X.AUTHENTICATED && await P(t.session), t),
|
|
179
|
+
refresh: () => {
|
|
180
|
+
if (!y) {
|
|
181
|
+
const t = s ? Te() : null;
|
|
182
|
+
y = (t ? t.request(pe, O) : O()).finally(() => {
|
|
183
|
+
y = null;
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
return y;
|
|
187
|
+
},
|
|
188
|
+
withAuthRetry: async (t) => {
|
|
189
|
+
const o = a;
|
|
190
|
+
try {
|
|
191
|
+
return await t();
|
|
192
|
+
} catch (u) {
|
|
193
|
+
const f = H(u);
|
|
194
|
+
if (f.kind !== "http")
|
|
195
|
+
throw u;
|
|
196
|
+
if (f.status === 401 && f.message === we) {
|
|
197
|
+
if (a === o && await h.refresh(), i.status !== "authenticated" || a === null || a === o)
|
|
198
|
+
throw u;
|
|
199
|
+
return t();
|
|
200
|
+
}
|
|
201
|
+
if (f.status === 403 && f.code === J.reauthRequired && E) {
|
|
202
|
+
if (!await E(Ae(f.params)))
|
|
203
|
+
throw u;
|
|
204
|
+
return t();
|
|
205
|
+
}
|
|
206
|
+
throw u;
|
|
207
|
+
}
|
|
208
|
+
},
|
|
209
|
+
onReauthRequired: (t) => (E = t, () => {
|
|
210
|
+
E === t && (E = null);
|
|
211
|
+
}),
|
|
212
|
+
logout: async () => {
|
|
213
|
+
try {
|
|
214
|
+
i.status === "authenticated" && a === null && await h.refresh(), a !== null && await h.withAuthRetry(() => F.sdk.auth.logout());
|
|
215
|
+
} finally {
|
|
216
|
+
await N();
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
dispose: () => {
|
|
220
|
+
k(), R.clear(), T.clear(), typeof window < "u" && window.removeEventListener("online", b), typeof document < "u" && document.removeEventListener("visibilitychange", M);
|
|
221
|
+
}
|
|
222
|
+
};
|
|
223
|
+
return h;
|
|
224
|
+
}, ke = "https://accounts.google.com/gsi/client", _e = "https://appleid.cdn-apple.com/appleauth/static/jsapi/appleid/1.0/en_US/appleid.auth.js", v = /* @__PURE__ */ new Map(), W = (e) => {
|
|
225
|
+
const s = v.get(e);
|
|
226
|
+
if (s)
|
|
227
|
+
return s;
|
|
228
|
+
const r = new Promise((i, a) => {
|
|
229
|
+
const n = document.createElement("script");
|
|
230
|
+
n.src = e, n.async = !0, n.onload = () => i(), n.onerror = () => {
|
|
231
|
+
v.delete(e), n.remove(), a(
|
|
232
|
+
new c(
|
|
233
|
+
d.FAILED,
|
|
234
|
+
`Could not load ${e}`
|
|
235
|
+
)
|
|
236
|
+
);
|
|
237
|
+
}, document.head.appendChild(n);
|
|
238
|
+
});
|
|
239
|
+
return v.set(e, r), r;
|
|
240
|
+
}, Se = [
|
|
241
|
+
"popup_closed_by_user",
|
|
242
|
+
"user_cancelled_authorize"
|
|
243
|
+
], Y = (e) => {
|
|
244
|
+
const { name: s, message: r } = e ?? {}, i = typeof r == "string" ? r : "Passkey ceremony failed";
|
|
245
|
+
return s === "NotAllowedError" || s === "AbortError" || e instanceof Z && e.code === "ERROR_CEREMONY_ABORTED" ? new c(d.CANCELLED, i, e) : new c(d.FAILED, i, e);
|
|
246
|
+
}, C = (e) => new c(
|
|
247
|
+
d.UNSUPPORTED,
|
|
248
|
+
`${e} is not supported by this browser`
|
|
249
|
+
), Pe = (e) => ({
|
|
250
|
+
platform: B.WEB,
|
|
251
|
+
passkeySupported: async () => g(),
|
|
252
|
+
getPasskey: async (s, r = !1) => {
|
|
253
|
+
if (!g())
|
|
254
|
+
throw C("WebAuthn");
|
|
255
|
+
if (r && !await V())
|
|
256
|
+
throw C("Passkey autofill");
|
|
257
|
+
try {
|
|
258
|
+
return await Q({
|
|
259
|
+
// abyss-main's options are the WebAuthn JSON this call reads (base64url binary fields).
|
|
260
|
+
optionsJSON: s,
|
|
261
|
+
useBrowserAutofill: r
|
|
262
|
+
});
|
|
263
|
+
} catch (i) {
|
|
264
|
+
throw Y(i);
|
|
265
|
+
}
|
|
266
|
+
},
|
|
267
|
+
createPasskey: async (s) => {
|
|
268
|
+
if (!g())
|
|
269
|
+
throw C("WebAuthn");
|
|
270
|
+
try {
|
|
271
|
+
return await $({
|
|
272
|
+
optionsJSON: s
|
|
273
|
+
});
|
|
274
|
+
} catch (r) {
|
|
275
|
+
throw Y(r);
|
|
276
|
+
}
|
|
277
|
+
},
|
|
278
|
+
google: async (s) => {
|
|
279
|
+
await W(ke);
|
|
280
|
+
const r = window.google;
|
|
281
|
+
if (!r)
|
|
282
|
+
throw new c(
|
|
283
|
+
d.FAILED,
|
|
284
|
+
"Google Identity Services missing"
|
|
285
|
+
);
|
|
286
|
+
return new Promise((i, a) => {
|
|
287
|
+
r.accounts.id.initialize({
|
|
288
|
+
client_id: e.googleClientId,
|
|
289
|
+
// Google copies the raw nonce into the id_token; abyss-main compares it as is.
|
|
290
|
+
nonce: s,
|
|
291
|
+
callback: (n) => {
|
|
292
|
+
if (n.credential) {
|
|
293
|
+
i({ idToken: n.credential });
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
a(
|
|
297
|
+
new c(
|
|
298
|
+
d.FAILED,
|
|
299
|
+
"Google returned no credential"
|
|
300
|
+
)
|
|
301
|
+
);
|
|
302
|
+
},
|
|
303
|
+
auto_select: !1,
|
|
304
|
+
cancel_on_tap_outside: !0,
|
|
305
|
+
use_fedcm_for_prompt: !0,
|
|
306
|
+
itp_support: !0
|
|
307
|
+
}), r.accounts.id.prompt((n) => {
|
|
308
|
+
if (n.isSkippedMoment()) {
|
|
309
|
+
a(
|
|
310
|
+
new c(
|
|
311
|
+
d.CANCELLED,
|
|
312
|
+
"Google prompt skipped"
|
|
313
|
+
)
|
|
314
|
+
);
|
|
315
|
+
return;
|
|
316
|
+
}
|
|
317
|
+
n.isDismissedMoment() && n.getDismissedReason() !== "credential_returned" && a(
|
|
318
|
+
new c(
|
|
319
|
+
d.CANCELLED,
|
|
320
|
+
"Google prompt dismissed"
|
|
321
|
+
)
|
|
322
|
+
);
|
|
323
|
+
});
|
|
324
|
+
});
|
|
325
|
+
},
|
|
326
|
+
apple: async (s) => {
|
|
327
|
+
var i;
|
|
328
|
+
await W(_e);
|
|
329
|
+
const r = window.AppleID;
|
|
330
|
+
if (!r)
|
|
331
|
+
throw new c(
|
|
332
|
+
d.FAILED,
|
|
333
|
+
"Sign in with Apple JS missing"
|
|
334
|
+
);
|
|
335
|
+
r.auth.init({
|
|
336
|
+
clientId: e.appleServiceId,
|
|
337
|
+
scope: "name email",
|
|
338
|
+
redirectURI: e.appleRedirectUri,
|
|
339
|
+
usePopup: !0,
|
|
340
|
+
// Apple carries what it is given; abyss-main compares it with SHA-256(raw nonce) in hex.
|
|
341
|
+
nonce: await ee(s)
|
|
342
|
+
});
|
|
343
|
+
try {
|
|
344
|
+
const a = await r.auth.signIn(), n = (i = a.user) == null ? void 0 : i.name;
|
|
345
|
+
return {
|
|
346
|
+
idToken: a.authorization.id_token,
|
|
347
|
+
...n != null && n.firstName ? { givenName: n.firstName } : {},
|
|
348
|
+
...n != null && n.lastName ? { familyName: n.lastName } : {}
|
|
349
|
+
};
|
|
350
|
+
} catch (a) {
|
|
351
|
+
const n = a == null ? void 0 : a.error;
|
|
352
|
+
throw typeof n == "string" && Se.includes(n) ? new c(d.CANCELLED, n, a) : new c(
|
|
353
|
+
d.FAILED,
|
|
354
|
+
typeof n == "string" ? n : "Sign in with Apple failed",
|
|
355
|
+
a
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}), q = te(null), Ne = ({ client: e, children: s }) => {
|
|
360
|
+
const [r, i] = ne(() => e.state());
|
|
361
|
+
se(() => {
|
|
362
|
+
i(e.state());
|
|
363
|
+
const n = e.subscribe(i);
|
|
364
|
+
return e.bootstrap(), n;
|
|
365
|
+
}, [e]);
|
|
366
|
+
const a = re(() => ({ state: r, client: e }), [r, e]);
|
|
367
|
+
return /* @__PURE__ */ ae(q.Provider, { value: a, children: s });
|
|
368
|
+
}, Ie = () => {
|
|
369
|
+
const e = oe(q);
|
|
370
|
+
if (!e)
|
|
371
|
+
throw new Error("useAuth() must be called inside <AuthProvider>");
|
|
372
|
+
return e;
|
|
373
|
+
};
|
|
374
|
+
export {
|
|
375
|
+
ie as A,
|
|
376
|
+
ke as G,
|
|
377
|
+
ce as L,
|
|
378
|
+
ue as R,
|
|
379
|
+
G as U,
|
|
380
|
+
le as a,
|
|
381
|
+
x as b,
|
|
382
|
+
de as c,
|
|
383
|
+
fe as d,
|
|
384
|
+
pe as e,
|
|
385
|
+
De as f,
|
|
386
|
+
_e as g,
|
|
387
|
+
Pe as h,
|
|
388
|
+
q as i,
|
|
389
|
+
Ne as j,
|
|
390
|
+
Ie as u
|
|
391
|
+
};
|
|
@@ -13,8 +13,8 @@ export declare const EUR_TRANSACTION_TYPE_COLORS: Record<EurTransactionType, str
|
|
|
13
13
|
*
|
|
14
14
|
* Exposed as an id for hosts whose intl wrapper has no `formatMessage`.
|
|
15
15
|
*/
|
|
16
|
-
export declare const getPlanNameMessageId: (planTemplate: Pick<IPlanTemplate,
|
|
17
|
-
export declare const getPlanDisplayName: (planTemplate: Pick<IPlanTemplate,
|
|
16
|
+
export declare const getPlanNameMessageId: (planTemplate: Pick<IPlanTemplate, "catalogKey" | "tier"> | null | undefined) => string;
|
|
17
|
+
export declare const getPlanDisplayName: (planTemplate: Pick<IPlanTemplate, "catalogKey" | "tier"> | null | undefined, intl: Pick<IntlShape, "formatMessage">) => string;
|
|
18
18
|
/**
|
|
19
19
|
* The interpolation values of a billing notification: its payload plus the `{planName}`,
|
|
20
20
|
* `{oldPlanName}` and `{newPlanName}` labels resolved from the plan identities it carries
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export declare const getCookie: (name: string) => string | null;
|
|
2
2
|
export declare const setCookie: (name: string, value: string, days?: number, domain?: string, options?: {
|
|
3
3
|
secure?: boolean;
|
|
4
|
-
sameSite?:
|
|
4
|
+
sameSite?: "Lax" | "Strict" | "None";
|
|
5
5
|
}) => void;
|
|
6
6
|
export declare const deleteCookie: (name: string, domain?: string) => void;
|
|
7
7
|
export declare const getOrCreatePersistentId: (cookieName: string, generateId: () => string) => string;
|
|
@@ -9,8 +9,8 @@ import { ISpace } from '@abyss-project/cloud';
|
|
|
9
9
|
* a label is missing, falls back to a generic localized wording.
|
|
10
10
|
*/
|
|
11
11
|
export type SpaceScope = 'personal' | 'perso-in-org' | 'org-common' | 'project';
|
|
12
|
-
export declare const resolveSpaceScope: (space: Pick<ISpace,
|
|
13
|
-
export declare const resolveSpaceDisplayName: (space: Pick<ISpace,
|
|
12
|
+
export declare const resolveSpaceScope: (space: Pick<ISpace, "organizationId" | "userId" | "projectId">) => SpaceScope;
|
|
13
|
+
export declare const resolveSpaceDisplayName: (space: Pick<ISpace, "organizationId" | "userId" | "projectId">, intl: IntlShape, context?: {
|
|
14
14
|
organizationName?: string;
|
|
15
15
|
projectName?: string;
|
|
16
16
|
userAlias?: string;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@abyss-project/commons-front-core",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "4.0.0",
|
|
4
4
|
"description": "Front Core package of AbyssProject",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -13,12 +13,26 @@
|
|
|
13
13
|
"./cookie-consent": {
|
|
14
14
|
"import": "./dist/cookie-consent.js",
|
|
15
15
|
"types": "./dist/cookie-consent.d.ts"
|
|
16
|
+
},
|
|
17
|
+
"./auth-native": {
|
|
18
|
+
"import": "./dist/auth-native.js",
|
|
19
|
+
"types": "./dist/auth-native.d.ts"
|
|
20
|
+
},
|
|
21
|
+
"./auth": {
|
|
22
|
+
"import": "./dist/auth-client.js",
|
|
23
|
+
"types": "./dist/auth-client.d.ts"
|
|
16
24
|
}
|
|
17
25
|
},
|
|
18
26
|
"typesVersions": {
|
|
19
27
|
"*": {
|
|
20
28
|
"cookie-consent": [
|
|
21
29
|
"./dist/cookie-consent.d.ts"
|
|
30
|
+
],
|
|
31
|
+
"auth-native": [
|
|
32
|
+
"./dist/auth-native.d.ts"
|
|
33
|
+
],
|
|
34
|
+
"auth": [
|
|
35
|
+
"./dist/auth-client.d.ts"
|
|
22
36
|
]
|
|
23
37
|
}
|
|
24
38
|
},
|
|
@@ -35,6 +49,7 @@
|
|
|
35
49
|
},
|
|
36
50
|
"homepage": "https://gitlab.com/abyss-group",
|
|
37
51
|
"peerDependencies": {
|
|
52
|
+
"@abyss-project/capacitor-auth": "^1.0.0",
|
|
38
53
|
"@dnd-kit/core": "^6.0.0",
|
|
39
54
|
"@dnd-kit/sortable": "^9.0.0",
|
|
40
55
|
"@dnd-kit/utilities": "^3.0.0",
|
|
@@ -53,7 +68,12 @@
|
|
|
53
68
|
"react-is": "^18.0.0 || ^19.0.0",
|
|
54
69
|
"react-router-dom": "^6.15.0",
|
|
55
70
|
"zustand": "^5.0.0",
|
|
56
|
-
"@abyss-project/main": "
|
|
71
|
+
"@abyss-project/main": "13.0.0"
|
|
72
|
+
},
|
|
73
|
+
"peerDependenciesMeta": {
|
|
74
|
+
"@abyss-project/capacitor-auth": {
|
|
75
|
+
"optional": true
|
|
76
|
+
}
|
|
57
77
|
},
|
|
58
78
|
"dependencies": {
|
|
59
79
|
"@abyss-project/banking": "^1.1.0",
|
|
@@ -61,7 +81,7 @@
|
|
|
61
81
|
"@abyss-project/crypt": "^1.0.9",
|
|
62
82
|
"@abyss-project/form": "^1.0.13",
|
|
63
83
|
"@abyss-project/memories": "^1.0.12",
|
|
64
|
-
"@abyss-project/monitor": "^
|
|
84
|
+
"@abyss-project/monitor": "^9.0.1",
|
|
65
85
|
"@abyss-project/spotlight": "^1.0.24",
|
|
66
86
|
"@abyss-project/storage": "^1.0.30",
|
|
67
87
|
"@capacitor/clipboard": "^7.0.1",
|
|
@@ -76,6 +96,7 @@
|
|
|
76
96
|
"@nivo/core": "^0.88.0",
|
|
77
97
|
"@nivo/line": "^0.88.0",
|
|
78
98
|
"@nivo/pie": "^0.88.0",
|
|
99
|
+
"@simplewebauthn/browser": "^13.3.0",
|
|
79
100
|
"@tanstack/react-table": "^8.21.3",
|
|
80
101
|
"axios": "^1.6.0",
|
|
81
102
|
"axios-retry": "^4.5.0",
|
|
@@ -95,7 +116,7 @@
|
|
|
95
116
|
"use-debounce": "^10.0.5",
|
|
96
117
|
"uuid": "^9.0.0",
|
|
97
118
|
"yup": "^0.32.11",
|
|
98
|
-
"@abyss-project/main": "
|
|
119
|
+
"@abyss-project/main": "13.0.0"
|
|
99
120
|
},
|
|
100
121
|
"devDependencies": {
|
|
101
122
|
"@testing-library/react": "^16.3.2",
|
|
@@ -108,11 +129,11 @@
|
|
|
108
129
|
"@types/react-animate-on-scroll": "^2.1.8",
|
|
109
130
|
"@types/react-dom": "^18.3.5",
|
|
110
131
|
"@types/uuid": "^9.0.0",
|
|
111
|
-
"@typescript-eslint/eslint-plugin": "
|
|
112
|
-
"@typescript-eslint/parser": "
|
|
132
|
+
"@typescript-eslint/eslint-plugin": "8.71.0",
|
|
133
|
+
"@typescript-eslint/parser": "8.71.0",
|
|
113
134
|
"@vitejs/plugin-react": "^4.2.0",
|
|
114
135
|
"@vitest/coverage-v8": "^2.0.0",
|
|
115
|
-
"eslint": "^
|
|
136
|
+
"eslint": "^8.57.1",
|
|
116
137
|
"eslint-config-prettier": "^8.3.0",
|
|
117
138
|
"eslint-config-standard": "^16.0.3",
|
|
118
139
|
"eslint-plugin-filenames-simple": "^0.7.0",
|
|
@@ -124,16 +145,17 @@
|
|
|
124
145
|
"jsdom": "^29.1.1",
|
|
125
146
|
"prettier": "^2.5.1",
|
|
126
147
|
"tsc-watch": "^4.6.2",
|
|
127
|
-
"typescript": "5.
|
|
148
|
+
"typescript": "5.9.3",
|
|
128
149
|
"vite": "^6.3.5",
|
|
129
150
|
"vite-plugin-dts": "^4.5.4",
|
|
130
|
-
"vitest": "^2.0.0"
|
|
151
|
+
"vitest": "^2.0.0",
|
|
152
|
+
"@abyss-project/capacitor-auth": "1.0.0"
|
|
131
153
|
},
|
|
132
154
|
"scripts": {
|
|
133
155
|
"lint": "eslint \"{src,apps,libs,test,core}/**/*.{ts,tsx}\" --fix",
|
|
134
156
|
"lint:check": "eslint \"{src,apps,libs,test,core}/**/*.{ts,tsx}\" --max-warnings 0",
|
|
135
157
|
"tsc": "tsc --noEmit",
|
|
136
|
-
"build": "vite build",
|
|
158
|
+
"build": "vite build && node scripts/check-auth-entry-isolation.cjs",
|
|
137
159
|
"dev": "vite build --watch",
|
|
138
160
|
"test": "vitest run --config vitest.config.ts",
|
|
139
161
|
"test:watch": "vitest --config vitest.config.ts"
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/* eslint-disable no-console */
|
|
3
|
+
'use strict';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* check-auth-entry-isolation.cjs — build guard for the `auth` entry (#510 task 14d).
|
|
7
|
+
*
|
|
8
|
+
* The `@abyss-project/commons-front-core/auth` entry exists so that an app's auth bootstrap
|
|
9
|
+
* module (and every test that re-imports it, e.g. after `vi.resetModules()`) never pays for the
|
|
10
|
+
* screens (`AuthFlow`, `SecuritySettings`, `ReauthDialog`…) and their dependencies (MUI, pdf.js,
|
|
11
|
+
* milkdown, nivo, react-toastify…) — the whole reason this entry exists alongside the full
|
|
12
|
+
* barrel, same as `cookie-consent` and `auth-native` already do for their own concerns.
|
|
13
|
+
*
|
|
14
|
+
* This walks `dist/auth.js` and every chunk it statically imports by a relative path (a bare
|
|
15
|
+
* specifier is a real npm dependency — react, @abyss-project/main, @simplewebauthn/browser — left
|
|
16
|
+
* alone: those are peer/externalized, not bundled here) and fails if either:
|
|
17
|
+
* - any reachable file's source mentions one of the markers below — a component or a dependency
|
|
18
|
+
* that must never show up on this entry;
|
|
19
|
+
* - the combined size of the entry and its local chunks crosses MAX_TOTAL_BYTES — the UI chunk
|
|
20
|
+
* bundled into `dist/index.js` is several MB, the real auth client chunk is under 20 KB.
|
|
21
|
+
*
|
|
22
|
+
* Exit 0: isolated. Exit 1: a chunk strayed in, the offending file(s) are printed. Exit 2: usage
|
|
23
|
+
* or tooling error (dist absent — build the package first). Run from the package's own `build`
|
|
24
|
+
* script, after `vite build`.
|
|
25
|
+
*/
|
|
26
|
+
|
|
27
|
+
const fs = require('fs');
|
|
28
|
+
const path = require('path');
|
|
29
|
+
|
|
30
|
+
const DIST_DIR = path.resolve(__dirname, '../dist');
|
|
31
|
+
// Dist filename `auth-client.js`, public subpath `./auth` (package.json `exports`) — see the
|
|
32
|
+
// `auth-client` entry comment in `vite.config.ts` for why the filenames differ.
|
|
33
|
+
const ENTRY = path.join(DIST_DIR, 'auth-client.js');
|
|
34
|
+
|
|
35
|
+
// The real auth client chunk (client/auth-bridge.ts, auth-client.ts, token-storage.ts,
|
|
36
|
+
// web-bridge.ts, react/AuthProvider.component.tsx, use-auth.hook.ts) measured under 20 KB
|
|
37
|
+
// (packages/abyss_front_core/dist/token-storage-*.js, shared with the `auth-native` entry);
|
|
38
|
+
// 100 KB leaves ample room for growth of that same code without tolerating a UI chunk (several
|
|
39
|
+
// MB) sneaking in.
|
|
40
|
+
const MAX_TOTAL_BYTES = 100 * 1024;
|
|
41
|
+
|
|
42
|
+
const FORBIDDEN_MARKERS = [
|
|
43
|
+
'@mui/',
|
|
44
|
+
'@nivo/',
|
|
45
|
+
'@milkdown/',
|
|
46
|
+
'pdfjs-dist',
|
|
47
|
+
'pdf-lib',
|
|
48
|
+
'react-toastify',
|
|
49
|
+
'react-dropzone',
|
|
50
|
+
'qrcode',
|
|
51
|
+
'@dnd-kit/',
|
|
52
|
+
'@tanstack/react-table',
|
|
53
|
+
'./components',
|
|
54
|
+
];
|
|
55
|
+
|
|
56
|
+
class UsageError extends Error {}
|
|
57
|
+
|
|
58
|
+
function localImportSpecifiers(source) {
|
|
59
|
+
const specifiers = new Set();
|
|
60
|
+
const re = /(?:import|export)\s[^'"]*?from\s*["']([^"']+)["']|import\s*["']([^"']+)["']/g;
|
|
61
|
+
let match = re.exec(source);
|
|
62
|
+
while (match !== null) {
|
|
63
|
+
const specifier = match[1] || match[2];
|
|
64
|
+
if (specifier.startsWith('.')) {
|
|
65
|
+
specifiers.add(specifier);
|
|
66
|
+
}
|
|
67
|
+
match = re.exec(source);
|
|
68
|
+
}
|
|
69
|
+
return specifiers;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function walk(entry) {
|
|
73
|
+
if (!fs.existsSync(entry)) {
|
|
74
|
+
throw new UsageError(`${entry} is missing: build the package first (\`vite build\`).`);
|
|
75
|
+
}
|
|
76
|
+
const files = new Map();
|
|
77
|
+
const queue = [entry];
|
|
78
|
+
while (queue.length > 0) {
|
|
79
|
+
const file = queue.shift();
|
|
80
|
+
if (files.has(file)) {
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
if (!fs.existsSync(file)) {
|
|
84
|
+
throw new UsageError(`${file} is missing: build the package first (\`vite build\`).`);
|
|
85
|
+
}
|
|
86
|
+
const source = fs.readFileSync(file, 'utf8');
|
|
87
|
+
files.set(file, source);
|
|
88
|
+
for (const specifier of localImportSpecifiers(source)) {
|
|
89
|
+
queue.push(path.resolve(path.dirname(file), specifier));
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return files;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function run() {
|
|
96
|
+
const files = walk(ENTRY);
|
|
97
|
+
const totalBytes = [...files.values()].reduce(
|
|
98
|
+
(sum, source) => sum + Buffer.byteLength(source, 'utf8'),
|
|
99
|
+
0,
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
const offenders = [];
|
|
103
|
+
for (const [file, source] of files) {
|
|
104
|
+
for (const marker of FORBIDDEN_MARKERS) {
|
|
105
|
+
if (source.includes(marker)) {
|
|
106
|
+
offenders.push(`${path.relative(DIST_DIR, file)} references "${marker}"`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
if (offenders.length > 0) {
|
|
111
|
+
console.error('AUTH ENTRY ISOLATION REFUSEE :');
|
|
112
|
+
for (const offender of offenders) console.error(` - ${offender}`);
|
|
113
|
+
return 1;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (totalBytes > MAX_TOTAL_BYTES) {
|
|
117
|
+
console.error(
|
|
118
|
+
`AUTH ENTRY ISOLATION REFUSEE : dist/auth.js + ses ${files.size - 1} chunk(s) local(aux) ` +
|
|
119
|
+
`pesent ${totalBytes} octets (> ${MAX_TOTAL_BYTES}) — un chunk hors du client d'auth s'est ` +
|
|
120
|
+
'glisse dans cet entry.',
|
|
121
|
+
);
|
|
122
|
+
return 1;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
console.log(
|
|
126
|
+
`AUTH ENTRY ISOLATION OK : ${files.size} fichier(s), ${totalBytes} octets, aucun marqueur UI.`,
|
|
127
|
+
);
|
|
128
|
+
return 0;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (require.main === module) {
|
|
132
|
+
try {
|
|
133
|
+
process.exit(run());
|
|
134
|
+
} catch (err) {
|
|
135
|
+
console.error(`check-auth-entry-isolation : ${err instanceof UsageError ? err.message : err.stack || err}`);
|
|
136
|
+
process.exit(2);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
module.exports = { run, localImportSpecifiers, walk };
|