@ofidj/entry 3.10.0 → 3.11.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/README.md +150 -17
- package/dom.d.ts +27 -0
- package/dom.js +224 -0
- package/index.d.ts +2 -3
- package/index.js +15 -10
- package/model.d.ts +131 -0
- package/model.js +406 -0
- package/package.json +9 -1
- package/remembered.d.ts +3 -0
- package/remembered.js +33 -0
- package/window.d.ts +1 -0
- package/window.js +7 -0
- package/service-agreement.d.ts +0 -13
- package/service-agreement.js +0 -184
- package/version.d.ts +0 -1
- package/version.js +0 -22
package/service-agreement.js
DELETED
|
@@ -1,184 +0,0 @@
|
|
|
1
|
-
export function agreementMarkup() {
|
|
2
|
-
return `<div class="signin-agreement"><label class="agreement-choice"><input id="service-agreement" type="checkbox" aria-required="true" disabled><span id="agreement-label">I accept the service agreement for this app.</span></label><button type="button" id="read-agreement" disabled>Read service agreement</button><p id="agreement-status" class="fineprint" role="status">Loading service agreement…</p><button type="button" id="retry-agreement" hidden>Retry</button></div><dialog id="agreement-dialog" aria-labelledby="agreement-heading"><h2 id="agreement-heading">Service agreement</h2><p id="agreement-version"></p><p id="agreement-text"></p><button type="button" id="close-agreement">Close agreement</button></dialog>`;
|
|
3
|
-
}
|
|
4
|
-
export function acceptedAgreement(form) {
|
|
5
|
-
const checkbox = form.querySelector("#service-agreement");
|
|
6
|
-
if (!checkbox?.checked || checkbox.disabled || !checkbox.dataset.version)
|
|
7
|
-
return null;
|
|
8
|
-
return { termsAccepted: true, termsVersion: checkbox.dataset.version };
|
|
9
|
-
}
|
|
10
|
-
export function signInErrorMessage(error) {
|
|
11
|
-
const detail = error;
|
|
12
|
-
const reason = typeof detail?.reason === "string" ? detail.reason : typeof detail?.message === "string" ? detail.message : "";
|
|
13
|
-
if (detail?.code === 429)
|
|
14
|
-
return "Too many attempts. Please wait before trying again.";
|
|
15
|
-
if (reason === "unknown-user")
|
|
16
|
-
return "We could not sign in to this account. Check the email and password.";
|
|
17
|
-
if (reason === "already exists - inconsistent request")
|
|
18
|
-
return "An account already uses this email. Check the password or sign in instead.";
|
|
19
|
-
if (/ECONNREFUSED|ENOTFOUND|ETIMEDOUT|ECONNRESET|EHOSTUNREACH|network/i.test(reason))
|
|
20
|
-
return "We cannot reach Fidj right now. Please try again.";
|
|
21
|
-
return "We could not sign in to this account. Please try again.";
|
|
22
|
-
}
|
|
23
|
-
export async function bindAgreement(form, title, endpoint, appId, checked = false) {
|
|
24
|
-
if (!form)
|
|
25
|
-
return;
|
|
26
|
-
// An app whose only door is Fidj carries no agreement block: Fidj asks for
|
|
27
|
-
// this app's agreement on the screen that names it, and records the version.
|
|
28
|
-
const checkbox = form.querySelector("#service-agreement");
|
|
29
|
-
if (!checkbox)
|
|
30
|
-
return;
|
|
31
|
-
const read = form.querySelector("#read-agreement");
|
|
32
|
-
const dialog = form.querySelector("#agreement-dialog");
|
|
33
|
-
const status = form.querySelector("#agreement-status");
|
|
34
|
-
const retry = form.querySelector("#retry-agreement");
|
|
35
|
-
// What this agreement gates is the app's own door, and only that one. The
|
|
36
|
-
// Fidj door is about to be asked the same question on the screen that names
|
|
37
|
-
// the app, where the answer is recorded with its version — so an agreement
|
|
38
|
-
// that is still loading, or that could not be loaded at all, must not be what
|
|
39
|
-
// stands between a person and the door that does not need it.
|
|
40
|
-
const gated = form.querySelector("#email-entry") || form;
|
|
41
|
-
const submitButtons = gated.querySelectorAll('button[type="submit"]');
|
|
42
|
-
const update = () => submitButtons.forEach(button => { button.disabled = checkbox.disabled; });
|
|
43
|
-
form.querySelector("#agreement-label").textContent = `I accept the service agreement for ${title}.`;
|
|
44
|
-
update();
|
|
45
|
-
checkbox.addEventListener("change", update);
|
|
46
|
-
read.addEventListener("click", () => dialog.showModal());
|
|
47
|
-
form.querySelector("#close-agreement").addEventListener("click", () => dialog.close());
|
|
48
|
-
const load = async () => {
|
|
49
|
-
retry.hidden = true;
|
|
50
|
-
status.textContent = "Loading service agreement…";
|
|
51
|
-
try {
|
|
52
|
-
const response = await fetch(`${endpoint}/apps/${encodeURIComponent(appId)}`, { signal: AbortSignal.timeout(10000) });
|
|
53
|
-
if (!response.ok)
|
|
54
|
-
throw new Error(response.status === 404 ? "missing" : "unreachable");
|
|
55
|
-
const agreement = (await response.json()).app?.agreement;
|
|
56
|
-
if (!agreement || typeof agreement.version !== "string" || !agreement.version || typeof agreement.text !== "string" || !agreement.text)
|
|
57
|
-
throw new Error("missing");
|
|
58
|
-
if (!form.isConnected)
|
|
59
|
-
return;
|
|
60
|
-
checkbox.dataset.version = agreement.version;
|
|
61
|
-
checkbox.disabled = false;
|
|
62
|
-
checkbox.checked = checked;
|
|
63
|
-
read.disabled = false;
|
|
64
|
-
dialog.querySelector("#agreement-version").textContent = `Version ${agreement.version}`;
|
|
65
|
-
dialog.querySelector("#agreement-text").textContent = agreement.text;
|
|
66
|
-
status.textContent = "Required to sign in. Optional data choices stay separate.";
|
|
67
|
-
update();
|
|
68
|
-
}
|
|
69
|
-
catch (error) {
|
|
70
|
-
if (!form.isConnected)
|
|
71
|
-
return;
|
|
72
|
-
status.textContent = error instanceof Error && error.message === "missing"
|
|
73
|
-
? "This app has no service agreement available."
|
|
74
|
-
: "We cannot reach Fidj right now. Try again.";
|
|
75
|
-
retry.hidden = false;
|
|
76
|
-
}
|
|
77
|
-
};
|
|
78
|
-
retry.addEventListener("click", load);
|
|
79
|
-
await load();
|
|
80
|
-
}
|
|
81
|
-
// The entry every app that delegates to the provider renders, in one place
|
|
82
|
-
// because both app shapes render it and they had drifted apart.
|
|
83
|
-
//
|
|
84
|
-
// "Continue with Fidj" alone borrows the grammar of an optional social login —
|
|
85
|
-
// that button always sits next to an email and a password — so on an app whose
|
|
86
|
-
// accounts *are* Fidj accounts, the missing form reads as something broken. The
|
|
87
|
-
// explanation therefore comes before the button, not as reassurance after it,
|
|
88
|
-
// and nothing presupposes an account the person may not have yet.
|
|
89
|
-
const hintKey = (appId) => "fidj.entry." + appId;
|
|
90
|
-
export function signInHint(appId) {
|
|
91
|
-
try {
|
|
92
|
-
return localStorage.getItem(hintKey(appId)) || "";
|
|
93
|
-
}
|
|
94
|
-
catch {
|
|
95
|
-
return "";
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
// Remembered on this app's own origin, about this app's own member: no
|
|
99
|
-
// cross-site question is asked, and none is answered. Signing out forgets, so a
|
|
100
|
-
// shared browser does not show the next person an address.
|
|
101
|
-
export function rememberSignIn(appId, label) {
|
|
102
|
-
try {
|
|
103
|
-
if (label)
|
|
104
|
-
localStorage.setItem(hintKey(appId), label);
|
|
105
|
-
}
|
|
106
|
-
catch { }
|
|
107
|
-
}
|
|
108
|
-
export function forgetSignIn(appId) {
|
|
109
|
-
try {
|
|
110
|
-
localStorage.removeItem(hintKey(appId));
|
|
111
|
-
}
|
|
112
|
-
catch { }
|
|
113
|
-
}
|
|
114
|
-
export function providerEntry(title, appId, credentials, isFidjItself = false, shape = "button") {
|
|
115
|
-
const escapeText = (value) => String(value ?? "").replace(/[&<>"']/g, (char) => ({ "&": "&", "<": "<", ">": ">", '"': """, "'": "'" })[char]);
|
|
116
|
-
const hint = signInHint(appId);
|
|
117
|
-
const both = shape === "both" && Boolean(credentials);
|
|
118
|
-
// The app's own form and nothing else. Nothing is folded away because there is
|
|
119
|
-
// no second way in to fold it under, and the trade-off is stated plainly:
|
|
120
|
-
// on this path it is this site that holds the password.
|
|
121
|
-
if (shape === "inline")
|
|
122
|
-
return (`<p class="signin-lead">${isFidjItself
|
|
123
|
-
? "One account across every app that uses Fidj, and a separate set of choices for each one."
|
|
124
|
-
: `${escapeText(title)} accounts are Fidj accounts. Sign in below — ${escapeText(title)} handles your password itself on this page.`}</p>` +
|
|
125
|
-
agreementMarkup() +
|
|
126
|
-
credentials);
|
|
127
|
-
const lead = hint
|
|
128
|
-
? `<p class="signin-lead">You signed in here with Fidj before. ${escapeText(title)} accounts are Fidj accounts — continue as yourself, or use another.</p>`
|
|
129
|
-
: both
|
|
130
|
-
? `<p class="signin-lead">${escapeText(title)} accounts are Fidj accounts. Fidj asks in a window of its own, so this site never sees your password.</p>`
|
|
131
|
-
: isFidjItself
|
|
132
|
-
? `<p class="signin-lead">One account across every app that uses Fidj, and a separate set of choices for each one. Fidj asks in a window of its own; this page stays where it is.</p>`
|
|
133
|
-
: `<p class="signin-lead">${escapeText(title)} accounts are Fidj accounts. You will sign in — or create yours — in a Fidj window, so this site never sees your password.</p>`;
|
|
134
|
-
// The accent is the Fidj mark, and this is the one control on the screen that
|
|
135
|
-
// is Fidj's rather than the app's. It is also the door the app would rather
|
|
136
|
-
// people took, and those two happen to want the same thing.
|
|
137
|
-
const fidj = hint
|
|
138
|
-
? `<button class="primary fidj-entry" type="submit" name="entry" value="fidj">Continue as ${escapeText(hint)}</button><button type="button" id="forget-hint" class="quiet">Use a different account</button>`
|
|
139
|
-
: `<button class="primary fidj-entry" type="submit" name="entry" value="fidj">${isFidjItself ? "Sign in" : "Sign in with Fidj"}</button>`;
|
|
140
|
-
// Fidj is the only door: it collects the agreement itself, a moment later, on
|
|
141
|
-
// the screen that names the app — and records it with its version. Collecting
|
|
142
|
-
// it here first recorded nothing and asked the same question twice.
|
|
143
|
-
if (shape !== "both" || !both)
|
|
144
|
-
return lead + fidj;
|
|
145
|
-
// Both doors. The app's own one is a second thought for the person who wants
|
|
146
|
-
// it, which is what a disclosure is for: it costs one click and takes nothing
|
|
147
|
-
// away, where a second button of equal weight cost everybody a decision.
|
|
148
|
-
return (lead +
|
|
149
|
-
fidj +
|
|
150
|
-
`<div class="signin-alternate"><button type="button" id="use-email" class="signin-toggle" aria-expanded="false" aria-controls="email-entry"><span class="signin-toggle-label">Inline form<span class="caret" aria-hidden="true"></span></span></button>
|
|
151
|
-
<div id="email-entry" hidden>${agreementMarkup()}${credentials}</div></div>`);
|
|
152
|
-
}
|
|
153
|
-
// Opening the app's own form takes the space the Fidj door was using.
|
|
154
|
-
//
|
|
155
|
-
// The two are alternatives, not a list, and watching one fold away as the other
|
|
156
|
-
// arrives is what says so — where a form appearing underneath a button that is
|
|
157
|
-
// still there reads as "and also". The toggle stays put through both states, so
|
|
158
|
-
// it ends up labelling whichever one is on screen: a caret pointing down at a
|
|
159
|
-
// form that is not here yet, and up at the one it would put away.
|
|
160
|
-
//
|
|
161
|
-
// Shared, because both app shapes render the same entry.
|
|
162
|
-
export function showEmailEntry(open, focus = false) {
|
|
163
|
-
const fields = document.getElementById("email-entry");
|
|
164
|
-
const toggle = document.getElementById("use-email");
|
|
165
|
-
if (!fields || !toggle)
|
|
166
|
-
return;
|
|
167
|
-
toggle.setAttribute("aria-expanded", String(open));
|
|
168
|
-
fields.hidden = !open;
|
|
169
|
-
const door = document.querySelector(".fidj-entry");
|
|
170
|
-
if (door) {
|
|
171
|
-
door.classList.toggle("is-folded", open);
|
|
172
|
-
// Out of the tab order and out of the accessibility tree the moment it
|
|
173
|
-
// starts leaving: something mid-fold is not something to press, and an
|
|
174
|
-
// animation is not what decides that.
|
|
175
|
-
if (open)
|
|
176
|
-
door.setAttribute("aria-hidden", "true");
|
|
177
|
-
else
|
|
178
|
-
door.removeAttribute("aria-hidden");
|
|
179
|
-
door.tabIndex = open ? -1 : 0;
|
|
180
|
-
}
|
|
181
|
-
if (open && focus)
|
|
182
|
-
document.getElementById("email")?.focus();
|
|
183
|
-
}
|
|
184
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2VydmljZS1hZ3JlZW1lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvc2VydmljZS1hZ3JlZW1lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsTUFBTSxVQUFVLGVBQWU7SUFDN0IsT0FBTyx5c0JBQXlzQixDQUFDO0FBQ250QixDQUFDO0FBRUQsTUFBTSxVQUFVLGlCQUFpQixDQUFDLElBQXFCO0lBQ3JELE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQW1CLG9CQUFvQixDQUFDLENBQUM7SUFDNUUsSUFBSSxDQUFDLFFBQVEsRUFBRSxPQUFPLElBQUksUUFBUSxDQUFDLFFBQVEsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsT0FBTztRQUFFLE9BQU8sSUFBSSxDQUFDO0lBQ3RGLE9BQU8sRUFBRSxhQUFhLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxRQUFRLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO0FBQ3pFLENBQUM7QUFFRCxNQUFNLFVBQVUsa0JBQWtCLENBQUMsS0FBYztJQUMvQyxNQUFNLE1BQU0sR0FBRyxLQUE2RCxDQUFDO0lBQzdFLE1BQU0sTUFBTSxHQUFHLE9BQU8sTUFBTSxFQUFFLE1BQU0sS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLE9BQU8sTUFBTSxFQUFFLE9BQU8sS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUM5SCxJQUFJLE1BQU0sRUFBRSxJQUFJLEtBQUssR0FBRztRQUFFLE9BQU8scURBQXFELENBQUM7SUFDdkYsSUFBSSxNQUFNLEtBQUssY0FBYztRQUFFLE9BQU8scUVBQXFFLENBQUM7SUFDNUcsSUFBSSxNQUFNLEtBQUssdUNBQXVDO1FBQUUsT0FBTyw0RUFBNEUsQ0FBQztJQUM1SSxJQUFJLG1FQUFtRSxDQUFDLElBQUks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
|
package/version.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function showVersionBadge(version: string, apiEndpoint?: string): void;
|
package/version.js
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
export function showVersionBadge(version, apiEndpoint) {
|
|
2
|
-
if (!/^\d+\.\d+\.\d+(-[\w.]+)?$/.test(version || ""))
|
|
3
|
-
return;
|
|
4
|
-
const badge = document.createElement("div");
|
|
5
|
-
badge.className = "fidj-version";
|
|
6
|
-
badge.setAttribute("aria-label", `Fidj version ${version}`);
|
|
7
|
-
badge.textContent = `fidj@${version}`;
|
|
8
|
-
document.body.append(badge);
|
|
9
|
-
if (apiEndpoint) {
|
|
10
|
-
void fetch(`${apiEndpoint.replace(/\/$/, "")}/status`)
|
|
11
|
-
.then(response => response.ok ? response.json() : null)
|
|
12
|
-
.then(status => {
|
|
13
|
-
const apiVersion = status?.version || status?.built;
|
|
14
|
-
if (!apiVersion)
|
|
15
|
-
return;
|
|
16
|
-
badge.textContent = `fidj@${version} · API ${apiVersion}`;
|
|
17
|
-
badge.setAttribute("aria-label", `Fidj version ${version}, API version ${apiVersion}`);
|
|
18
|
-
})
|
|
19
|
-
.catch(() => undefined);
|
|
20
|
-
}
|
|
21
|
-
}
|
|
22
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidmVyc2lvbi5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy92ZXJzaW9uLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE1BQU0sVUFBVSxnQkFBZ0IsQ0FBQyxPQUFlLEVBQUUsV0FBb0I7SUFDcEUsSUFBSSxDQUFDLDJCQUEyQixDQUFDLElBQUksQ0FBQyxPQUFPLElBQUksRUFBRSxDQUFDO1FBQUUsT0FBTztJQUM3RCxNQUFNLEtBQUssR0FBRyxRQUFRLENBQUMsYUFBYSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzVDLEtBQUssQ0FBQyxTQUFTLEdBQUcsY0FBYyxDQUFDO0lBQ2pDLEtBQUssQ0FBQyxZQUFZLENBQUMsWUFBWSxFQUFFLGdCQUFnQixPQUFPLEVBQUUsQ0FBQyxDQUFDO0lBQzVELEtBQUssQ0FBQyxXQUFXLEdBQUcsUUFBUSxPQUFPLEVBQUUsQ0FBQztJQUN0QyxRQUFRLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUM1QixJQUFJLFdBQVcsRUFBRSxDQUFDO1FBQ2hCLEtBQUssS0FBSyxDQUFDLEdBQUcsV0FBVyxDQUFDLE9BQU8sQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLFNBQVMsQ0FBQzthQUNuRCxJQUFJLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQzthQUN0RCxJQUFJLENBQUMsTUFBTSxDQUFDLEVBQUU7WUFDYixNQUFNLFVBQVUsR0FBRyxNQUFNLEVBQUUsT0FBTyxJQUFJLE1BQU0sRUFBRSxLQUFLLENBQUM7WUFDcEQsSUFBSSxDQUFDLFVBQVU7Z0JBQUUsT0FBTztZQUN4QixLQUFLLENBQUMsV0FBVyxHQUFHLFFBQVEsT0FBTyxVQUFVLFVBQVUsRUFBRSxDQUFDO1lBQzFELEtBQUssQ0FBQyxZQUFZLENBQUMsWUFBWSxFQUFFLGdCQUFnQixPQUFPLGlCQUFpQixVQUFVLEVBQUUsQ0FBQyxDQUFDO1FBQ3pGLENBQUMsQ0FBQzthQUNELEtBQUssQ0FBQyxHQUFHLEVBQUUsQ0FBQyxTQUFTLENBQUMsQ0FBQztJQUM1QixDQUFDO0FBQ0gsQ0FBQyJ9
|