@ofidj/entry 3.10.1 → 3.13.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 CHANGED
@@ -26,10 +26,87 @@ renders, so there is one implementation and no hand-porting.
26
26
  npm install @ofidj/entry
27
27
  ```
28
28
 
29
- ```ts
30
- import { providerEntry, bindAgreement, acceptedAgreement } from "@ofidj/entry";
29
+ Three entry points, split by what they need to run:
30
+
31
+ | Import | Needs | What it holds |
32
+ | --------------------- | ---------------- | ------------------------------------------------------------------------------ |
33
+ | `@ofidj/entry` | nothing | **the model**: every rule, and every sentence a person is shown, as plain data |
34
+ | `@ofidj/entry/dom` | a document | one renderer of that model as HTML strings, and the helpers that drive it |
35
+ | `@ofidj/entry/window` | a browser window | the Fidj window and the answer it relays back |
36
+ | `@ofidj/entry/server` | a server | the CSP-safe OIDC interaction renderer and its shared password binding |
37
+
38
+ The root is pure — no DOM, no markup, no view layer. That is deliberate: a
39
+ screen is a **value**, so the same entry can be drawn as HTML strings, as React
40
+ components or as Vue single-file components, and none of them re-derives a rule
41
+ or re-types a sentence.
42
+
43
+ ### On React, Vue, Svelte, or a server
44
+
45
+ Take the model and render it yourself. Nothing here assumes a browser, so it
46
+ works under SSR, in a test, or in a plain Node script.
47
+
48
+ ```tsx
49
+ import {
50
+ agreementModel,
51
+ acceptance,
52
+ agreementRequired,
53
+ agreementFromRefusal,
54
+ verificationPending,
55
+ pollVerification,
56
+ signInErrorMessage,
57
+ } from "@ofidj/entry";
58
+ import { openProviderWindow } from "@ofidj/entry/window";
31
59
  import "@ofidj/entry/tokens.css";
32
60
  import "@ofidj/entry/style.css";
61
+
62
+ function Agreement({ title, agreement, onAccepted }) {
63
+ const [checked, setChecked] = useState(false);
64
+ const screen = agreementModel(title, agreement, { checked });
65
+ return (
66
+ <form
67
+ onSubmit={() =>
68
+ onAccepted(acceptance({ checked, version: screen.version }))
69
+ }
70
+ >
71
+ <h2>{screen.heading}</h2>
72
+ <p className="signin-lead">{screen.lead}</p>
73
+ <p className="fineprint">{screen.versionLabel}</p>
74
+ <div className="agreement-text" tabIndex={0}>
75
+ {screen.text}
76
+ </div>
77
+ <label className="agreement-choice">
78
+ <input
79
+ type="checkbox"
80
+ checked={checked}
81
+ onChange={(e) => setChecked(e.target.checked)}
82
+ />
83
+ <span>{screen.checkboxLabel}</span>
84
+ </label>
85
+ <button className="primary" disabled={screen.submitDisabled}>
86
+ {screen.submitLabel}
87
+ </button>
88
+ </form>
89
+ );
90
+ }
91
+ ```
92
+
93
+ `acceptance()` is the rule `@ofidj/entry/dom` applies to a checkbox, asked of
94
+ your own state instead: a tick is evidence only if it was live and only if it
95
+ names the version that was displayed. Both callers have to get the same answer,
96
+ or the evidence means different things depending on who collected it.
97
+
98
+ Authentication itself is not here — that is `@ofidj/node`. This package is the
99
+ screens and the flow around them.
100
+
101
+ ### On a shell that builds pages out of strings
102
+
103
+ ```ts
104
+ import { agreementRequired, agreementFromRefusal } from "@ofidj/entry";
105
+ import {
106
+ agreementScreen,
107
+ bindAgreementScreen,
108
+ acceptedAgreement,
109
+ } from "@ofidj/entry/dom";
33
110
  ```
34
111
 
35
112
  `tokens.css` defines every colour, family and radius the product paints with;
@@ -39,24 +116,83 @@ prefix.
39
116
 
40
117
  ## What is here, and what is not
41
118
 
42
- Moved, and covered by characterization tests in `test/`:
119
+ | Module | What it holds |
120
+ | -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------- |
121
+ | `model.ts` | the refusals and what they mean, the acceptance rule, and a model per screen: entry, agreement, verification wait, account, credentials |
122
+ | `remembered.ts` | the address this browser remembers, and forgetting it |
123
+ | `dom.ts` | the HTML renderer, password/agreement bindings, the folding form, the `fidj@<version>` badge |
124
+ | `provider-window.ts` | the Fidj window and the answer it relays back |
125
+ | `tokens.css`, `fonts.css`, `style.css` | the design system |
126
+
127
+ Two tests hold the split, and they are the reason it stays true. One exercises
128
+ every model function in a file that never loads jsdom and never defines `window`
129
+ or `document`. The other asserts the HTML renderer says **what the model says**
130
+ and invents nothing — because a sentence able to drift between the two is a
131
+ React app and a generated app telling the same person different things, which is
132
+ the failure this package exists to end.
133
+
134
+ Generated shells may own transport-specific form actions and page composition,
135
+ but they do not own reusable entry components. Credential, signup, recovery and
136
+ agreement markup rules and their browser bindings live here. When a shell
137
+ replaces markup dynamically, it binds the newly rendered component through this
138
+ package rather than reimplementing its behavior locally.
43
139
 
44
- | Module | What it holds |
45
- | -------------------------------------- | ------------------------------------------------------------------------------------------------------------------ |
46
- | `service-agreement.ts` | the agreement block and its loading, `providerEntry`'s three shapes, the remembered address, sign-in error wording |
47
- | `provider-window.ts` | the Fidj window and the answer it relays back |
48
- | `version.ts` | the `fidj@<version>` badge |
49
- | `tokens.css`, `fonts.css`, `style.css` | the design system |
140
+ ## The entry flow
50
141
 
51
- Still in `generator-fidj`'s template, and next to move: the screens inside
52
- `content.ts` — the sign-in entry, `#/forgot`, `#/reset`, `#/verify`, `#/account`
53
- and the Fidj-hosted OIDC interaction page. They import `app.config.json`
54
- directly, so they move behind a config argument rather than verbatim.
142
+ [The workspace README](../README.md#entry-one-flow-the-same-everywhere) defines
143
+ it; this package implements it, so every surface gets the same one.
144
+
145
+ ```ts
146
+ import {
147
+ pollVerification, // the wait ends by itself when the link is opened
148
+ agreementRequired, // was this refusal "you owe this app its agreement"?
149
+ agreementFromRefusal, // ...and the agreement it refused with
150
+ verificationPending, // was it "nobody has proved this address yet"?
151
+ credentialsModel, // email, password, two buttons, nothing gated
152
+ verificationWaitModel, // the wait a new account owes its address
153
+ agreementModel, // the second screen, and when its submit is live
154
+ } from "@ofidj/entry";
155
+ import {
156
+ credentialFields,
157
+ verificationWait,
158
+ agreementScreen,
159
+ bindAgreementScreen,
160
+ } from "@ofidj/entry/dom"; // ...the same screens, as markup
161
+ ```
55
162
 
56
- **The generator has not switched over yet.** Its template still carries its own
57
- copies and builds from them, so a change made here reaches nobody until that
58
- lands. `test/no-drift-from-the-generator.test.mjs` fails while the two disagree,
59
- and is deleted in the same change that deletes the generator's copies.
163
+ **The API decides, not the screen.** Call `login`, and when it refuses with
164
+ `409 agreement_required`, show the agreement screen. A screen that decided for
165
+ itself
166
+ would have to know which version the account already accepted, which is the
167
+ API's to know — and an owner publishing a new version is what makes the
168
+ question owed again.
169
+
170
+ **Read the agreement off the refusal.** `agreementFromRefusal` returns the
171
+ version and text the API compared against, from `FidjError.details`. Fetching it
172
+ again with `GET /apps/:appId` usually gives the same answer and occasionally
173
+ not: an owner who publishes between the refusal and the refetch would have
174
+ somebody accept text the API is about to call stale. It needs `@ofidj/node`
175
+ 3.10.2 or later, where `login` stopped rebuilding its error from
176
+ `err.toString()` and losing the body; against an older SDK it returns `null` and
177
+ the caller falls back to fetching.
178
+
179
+ **The wait is not a screen.** `verificationWait` returns a block to put _under_
180
+ the credential form, which stays where it is. That is what keeps a mistyped
181
+ address correctable: the field is still there, still filled in — correcting it
182
+ and creating the account again is the repair, and it reads as one because
183
+ nothing moved.
184
+
185
+ **`pollVerification` treats a failed check as no answer.** A browser that lost
186
+ its connection has learned nothing about the address, so the wait continues
187
+ rather than reporting anything.
188
+
189
+ ### What went with the old arrangement
190
+
191
+ `agreementMarkup` and `bindAgreement` are gone. They put the checkbox beside the
192
+ credentials and gated the submit on whether the agreement had _loaded_, ticked or
193
+ not; the generated shells both render the two screens now, so nothing called
194
+ them. `agreementScreen` and `bindAgreementScreen` replace them, and the tick is
195
+ what opens the door.
60
196
 
61
197
  ## Release
62
198
 
package/dom.d.ts ADDED
@@ -0,0 +1,28 @@
1
+ import { type AccountState, type SigninShape, type VerificationState } from "./index.js";
2
+ export declare const escape: (value: unknown) => string;
3
+ export declare function masthead(logo: string, title: string): string;
4
+ export declare function highlightCells(entries?: Array<{
5
+ heading: string;
6
+ body: string;
7
+ }>): string;
8
+ export declare function badgeStrip(entries?: string[]): string;
9
+ export declare function credentialFields(state: {
10
+ email: string;
11
+ password: string;
12
+ }): string;
13
+ export declare function bindPasswordReveal(root: ParentNode): void;
14
+ export declare function accountForm(route: string, state: AccountState): string;
15
+ export declare function returnNotice(asking: string): string;
16
+ export declare function providerEntry(title: string, appId: string, credentials: string, isFidjItself?: boolean, shape?: SigninShape): string;
17
+ export declare function agreementScreen(title: string, agreement: {
18
+ version?: string;
19
+ text?: string;
20
+ }, href: string): string;
21
+ export declare function verificationWait(state: VerificationState): string;
22
+ export declare function acceptedAgreement(form: HTMLFormElement): {
23
+ termsAccepted: boolean;
24
+ termsVersion: string;
25
+ } | null;
26
+ export declare function bindAgreementScreen(form: HTMLFormElement | null): void;
27
+ export declare function showEmailEntry(open: boolean, focus?: boolean): void;
28
+ export declare function showVersionBadge(version: string, apiEndpoint?: string): void;
package/dom.js ADDED
@@ -0,0 +1,251 @@
1
+ // The entry, as markup and as behaviour.
2
+ //
3
+ // One renderer of the model in `@ofidj/entry`, for the shells that build pages
4
+ // out of strings. Every sentence on these screens comes from the model rather
5
+ // than from here — that is the property worth keeping, because it is what makes
6
+ // a React or Vue app render the *same* entry instead of a similar one.
7
+ //
8
+ // What stayed out of the model is the shell that holds the screens: the sign-in
9
+ // screen nests signin-trust inside its inner div and the interaction screen
10
+ // makes it a sibling, so a single shell builder would have had to change one of
11
+ // them. That is a decision, not a move.
12
+ import { accountModel, agreementModel, credentialsModel, providerEntryModel, returnNoticeModel, signInHint, verificationWaitModel, } from "./index.js";
13
+ export const escape = (value) => String(value ?? "").replace(/[&<>"']/g, (char) => ({ "&": "&amp;", "<": "&lt;", ">": "&gt;", '"': "&quot;", "'": "&#39;" })[char]);
14
+ const attribute = (name, value) => value === undefined || value === false || value === ""
15
+ ? ""
16
+ : ` ${name}="${escape(value)}"`;
17
+ const button = (control, extraClass = "") => {
18
+ const classes = [
19
+ control.kind === "primary"
20
+ ? "primary"
21
+ : control.kind === "secondary"
22
+ ? "secondary"
23
+ : "quiet",
24
+ extraClass,
25
+ ]
26
+ .filter(Boolean)
27
+ .join(" ");
28
+ // A control the entry's own form posts is a submit; one that only changes
29
+ // what is on screen is not, and saying so is what keeps a disclosure from
30
+ // opening a second window.
31
+ const type = control.name ? "submit" : "button";
32
+ return `<button class="${classes}" type="${type}"${attribute("id", control.name ? "" : control.id)}${attribute("name", control.name)}${attribute("value", control.value)}>${escape(control.label)}</button>`;
33
+ };
34
+ // The app's own mark beside its own name, decorative because the name is right
35
+ // there: every shell opens with this.
36
+ export function masthead(logo, title) {
37
+ return `<header class="signin-masthead"><img class="app-mark" src="${escape(logo)}" alt=""><strong>${escape(title)}</strong></header>`;
38
+ }
39
+ export function highlightCells(entries) {
40
+ if (!entries?.length)
41
+ return "";
42
+ return `<div class="signin-highlights">${entries
43
+ .map((entry, index) => `<article><p class="eyebrow">${String(index + 1).padStart(2, "0")}</p><h2>${escape(entry.heading)}</h2><p>${escape(entry.body)}</p></article>`)
44
+ .join("")}</div>`;
45
+ }
46
+ export function badgeStrip(entries) {
47
+ if (!entries?.length)
48
+ return "";
49
+ return `<footer class="signin-badges">${entries
50
+ .map((entry) => `<span>${escape(entry)}</span>`)
51
+ .join("")}</footer>`;
52
+ }
53
+ export function credentialFields(state) {
54
+ const model = credentialsModel(state);
55
+ return (`<label for="email">${escape(model.email.label)}</label><input id="email" type="email" value="${escape(model.email.value)}" placeholder="${escape(model.email.placeholder)}" autocomplete="username">` +
56
+ `<div class="field-head"><label for="password">${escape(model.password.label)}</label><a href="${escape(model.forgot.href)}">${escape(model.forgot.label)}</a></div>` +
57
+ `<div class="password-field"><input id="password" type="password" value="${escape(model.password.value)}" placeholder="${escape(model.password.placeholder)}" autocomplete="current-password"><button type="button" id="reveal" aria-controls="password">${escape(model.reveal.label)}</button></div>` +
58
+ `<button class="primary" type="submit" name="entry" value="credentials">${escape(model.submit.label)}</button>` +
59
+ `<button class="secondary" type="submit" name="signup" value="true">${escape(model.signup.label)}</button>`);
60
+ }
61
+ export function bindPasswordReveal(root) {
62
+ root
63
+ .querySelectorAll("button[aria-controls]")
64
+ .forEach((button) => {
65
+ const fieldId = button.getAttribute("aria-controls");
66
+ const field = fieldId
67
+ ? root.querySelector(`#${fieldId}`)
68
+ : null;
69
+ if (!field || field.type !== "password")
70
+ return;
71
+ button.onclick = () => {
72
+ const hidden = field.type === "password";
73
+ field.type = hidden ? "text" : "password";
74
+ button.textContent = hidden ? "Hide" : "Show";
75
+ };
76
+ });
77
+ }
78
+ // The four account screens, drawn from the model that decides which of them has
79
+ // a form to show.
80
+ export function accountForm(route, state) {
81
+ const model = accountModel(route, state);
82
+ const fields = model.fields
83
+ .map((field) => {
84
+ const input = `<input id="${escape(field.id)}" type="${escape(field.type)}"${attribute("autocomplete", field.autocomplete)}${attribute("minlength", field.minlength)}${field.required ? " required" : ""}>`;
85
+ return `<label for="${escape(field.id)}">${escape(field.label)}</label>${field.type === "password" ? `<div class="password-field">${input}<button type="button" aria-controls="${escape(field.id)}">Show</button></div>` : input}`;
86
+ })
87
+ .join("");
88
+ const form = model.submitLabel
89
+ ? `<form id="recovery">${fields}${model.hint ? `<p>${escape(model.hint)}</p>` : ""}<button class="primary">${escape(model.submitLabel)}</button></form>`
90
+ : "";
91
+ const alternative = model.alternative
92
+ ? `${model.alternative.text ? `<p>${escape(model.alternative.text)}</p>` : ""}${model.alternative.href ? `<a href="${escape(model.alternative.href)}">${escape(model.alternative.label)}</a>` : ""}`
93
+ : "";
94
+ if (route === "forgot" || route === "reset" || route === "verify")
95
+ return `<h2>${escape(model.heading)}</h2><p>${escape(model.intro)}</p>${form}${alternative}`;
96
+ // My account keeps its own shape: an identity line, a status the page
97
+ // refreshes in place, and the controls that act on it.
98
+ return (`<h2>${escape(model.heading)}</h2>` +
99
+ `<p class="account-identity">Signed in as <strong>${escape(state.accountEmail)}</strong></p>` +
100
+ `<p>${escape(model.intro)}</p>` +
101
+ `<p id="verification-status">${escape(model.status)}</p>` +
102
+ model.extras
103
+ .map((control) => `<button id="${escape(control.id)}">${escape(control.label)}</button>`)
104
+ .join("") +
105
+ `<p><a href="${escape(model.alternative.href)}">${escape(model.alternative.label)}</a></p>`);
106
+ }
107
+ export function returnNotice(asking) {
108
+ return `<p class="signin-return" role="note">${escape(returnNoticeModel(asking))}</p>`;
109
+ }
110
+ // The entry every app that delegates to the provider renders. The shape logic
111
+ // lives in the model; what is here is the markup and the one browser fact the
112
+ // model refuses to reach for itself — what this browser remembers.
113
+ export function providerEntry(title, appId, credentials, isFidjItself = false, shape = "button") {
114
+ const model = providerEntryModel({
115
+ title,
116
+ hint: signInHint(appId),
117
+ isFidjItself,
118
+ shape,
119
+ hasCredentials: Boolean(credentials),
120
+ });
121
+ const lead = `<p class="signin-lead">${escape(model.lead)}</p>`;
122
+ if (!model.door)
123
+ return lead + credentials;
124
+ const door = button(model.door, "fidj-entry");
125
+ const forget = model.forget
126
+ ? `<button type="button" id="${escape(model.forget.id)}" class="quiet">${escape(model.forget.label)}</button>`
127
+ : "";
128
+ if (!model.disclosure)
129
+ return lead + door + forget;
130
+ // Both doors. The app's own one is a second thought for the person who wants
131
+ // it, which is what a disclosure is for: it costs one click and takes nothing
132
+ // away, where a second button of equal weight cost everybody a decision.
133
+ return (lead +
134
+ door +
135
+ forget +
136
+ `<div class="signin-alternate"><button type="button" id="use-email" class="signin-toggle" aria-expanded="${model.disclosure.expanded}" aria-controls="${escape(model.disclosure.controls)}"><span class="signin-toggle-label">${escape(model.disclosure.label)}<span class="caret" aria-hidden="true"></span></span></button>
137
+ <div id="${escape(model.disclosure.controls)}" hidden>${credentials}</div></div>`);
138
+ }
139
+ // Screen three, drawn. The version travels on the checkbox so that what is
140
+ // recorded is what was displayed.
141
+ export function agreementScreen(title, agreement, href) {
142
+ const model = agreementModel(title, agreement);
143
+ return `<h2>${escape(model.heading)}</h2>
144
+ <p class="signin-lead">${escape(model.lead)}</p>
145
+ <div class="agreement-text" tabindex="0">${escape(model.text)}</div>
146
+ <label class="agreement-choice"><input id="service-agreement" type="checkbox" required aria-required="true" data-version="${escape(model.version)}"><span>I accept the <a class="agreement-document" href="${escape(href)}" target="fidj-agreement" rel="noopener">service agreement · ${escape(model.versionLabel)} ↗</a></span></label>
147
+ <button class="primary" type="submit"${model.submitDisabled ? " disabled" : ""}>${escape(model.submitLabel)}</button>`;
148
+ }
149
+ // Screen two, drawn under the form that started it.
150
+ export function verificationWait(state) {
151
+ const model = verificationWaitModel(state);
152
+ const notice = model.notice
153
+ ? model.notice.kind === "error"
154
+ ? `<p role="alert" class="error">${escape(model.notice.text)}</p>`
155
+ : `<p class="fineprint">${escape(model.notice.text)}</p>`
156
+ : "";
157
+ return `<div class="verification-wait">
158
+ <p role="status"><span class="spinner" aria-hidden="true"></span>${escape(model.status)} <strong>${escape(model.email)}</strong>.</p>
159
+ <p class="fineprint">${escape(model.fineprint)}</p>
160
+ ${notice}
161
+ <button type="button" id="resend-verification">${escape(model.resendLabel)}</button>
162
+ </div>`;
163
+ }
164
+ // ---------------------------------------------------------------------------
165
+ // Reading and driving a real document
166
+ // ---------------------------------------------------------------------------
167
+ // The acceptance, read off the form that collected it. The rule it applies is
168
+ // `acceptance()` in the model; what is here is where the three facts are found.
169
+ export function acceptedAgreement(form) {
170
+ const checkbox = form.querySelector("#service-agreement");
171
+ if (!checkbox?.checked || checkbox.disabled || !checkbox.dataset.version)
172
+ return null;
173
+ return { termsAccepted: true, termsVersion: checkbox.dataset.version };
174
+ }
175
+ // The tick is what opens the door, and unticking closes it again. This is the
176
+ // rule generator-fidj's README always claimed and its code never had:
177
+ // bindAgreement gated on whether the agreement had *loaded*, which is the right
178
+ // rule for a checkbox standing beside a password and the wrong one for a screen
179
+ // that exists only to collect it.
180
+ export function bindAgreementScreen(form) {
181
+ if (!form)
182
+ return;
183
+ const checkbox = form.querySelector("#service-agreement");
184
+ if (!checkbox)
185
+ return;
186
+ const submits = form.querySelectorAll('button[type="submit"]');
187
+ const update = () => submits.forEach((element) => {
188
+ element.disabled = !checkbox.checked;
189
+ });
190
+ checkbox.addEventListener("change", update);
191
+ const agreementLink = form.querySelector(".agreement-document");
192
+ agreementLink?.addEventListener("click", (event) => {
193
+ event.preventDefault();
194
+ window.open(agreementLink.href, "fidj-agreement", "popup,width=640,height=720,left=40,top=40,noopener");
195
+ });
196
+ update();
197
+ }
198
+ // Opening the app's own form takes the space the Fidj door was using.
199
+ //
200
+ // The two are alternatives, not a list, and watching one fold away as the other
201
+ // arrives is what says so — where a form appearing underneath a button that is
202
+ // still there reads as "and also". The toggle stays put through both states, so
203
+ // it ends up labelling whichever one is on screen: a caret pointing down at a
204
+ // form that is not here yet, and up at the one it would put away.
205
+ export function showEmailEntry(open, focus = false) {
206
+ const fields = document.getElementById("email-entry");
207
+ const toggle = document.getElementById("use-email");
208
+ if (!fields || !toggle)
209
+ return;
210
+ toggle.setAttribute("aria-expanded", String(open));
211
+ fields.hidden = !open;
212
+ const forget = document.getElementById("forget-hint");
213
+ if (forget)
214
+ forget.hidden = open;
215
+ const door = document.querySelector(".fidj-entry");
216
+ if (door) {
217
+ door.classList.toggle("is-folded", open);
218
+ // Out of the tab order and out of the accessibility tree the moment it
219
+ // starts leaving: something mid-fold is not something to press, and an
220
+ // animation is not what decides that.
221
+ if (open)
222
+ door.setAttribute("aria-hidden", "true");
223
+ else
224
+ door.removeAttribute("aria-hidden");
225
+ door.tabIndex = open ? -1 : 0;
226
+ }
227
+ if (open && focus)
228
+ document.getElementById("email")?.focus();
229
+ }
230
+ export function showVersionBadge(version, apiEndpoint) {
231
+ if (!/^\d+\.\d+\.\d+(-[\w.]+)?$/.test(version || ""))
232
+ return;
233
+ const badge = document.createElement("div");
234
+ badge.className = "fidj-version";
235
+ badge.setAttribute("aria-label", `Fidj version ${version}`);
236
+ badge.textContent = `fidj@${version}`;
237
+ document.body.append(badge);
238
+ if (apiEndpoint) {
239
+ void fetch(`${apiEndpoint.replace(/\/$/, "")}/status`)
240
+ .then((response) => (response.ok ? response.json() : null))
241
+ .then((status) => {
242
+ const apiVersion = status?.version || status?.built;
243
+ if (!apiVersion)
244
+ return;
245
+ badge.textContent = `fidj@${version} · API ${apiVersion}`;
246
+ badge.setAttribute("aria-label", `Fidj version ${version}, API version ${apiVersion}`);
247
+ })
248
+ .catch(() => undefined);
249
+ }
250
+ }
251
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZG9tLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2RvbS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSx5Q0FBeUM7QUFDekMsRUFBRTtBQUNGLCtFQUErRTtBQUMvRSw4RUFBOEU7QUFDOUUsZ0ZBQWdGO0FBQ2hGLHVFQUF1RTtBQUN2RSxFQUFFO0FBQ0YsZ0ZBQWdGO0FBQ2hGLDRFQUE0RTtBQUM1RSxnRkFBZ0Y7QUFDaEYsd0NBQXdDO0FBRXhDLE9BQU8sRUFDTCxZQUFZLEVBQ1osY0FBYyxFQUNkLGdCQUFnQixFQUNoQixrQkFBa0IsRUFDbEIsaUJBQWlCLEVBQ2pCLFVBQVUsRUFDVixxQkFBcUIsR0FLdEIsTUFBTSxZQUFZLENBQUM7QUFFcEIsTUFBTSxDQUFDLE1BQU0sTUFBTSxHQUFHLENBQUMsS0FBYyxFQUFFLEVBQUUsQ0FDdkMsTUFBTSxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUMsQ0FBQyxPQUFPLENBQ3pCLFVBQVUsRUFDVixDQUFDLElBQUksRUFBRSxFQUFFLENBQ1AsQ0FBQyxFQUFFLEdBQUcsRUFBRSxPQUFPLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQ3ZFLElBQUksQ0FDSixDQUNMLENBQUM7QUFFSixNQUFNLFNBQVMsR0FBRyxDQUFDLElBQVksRUFBRSxLQUFpQyxFQUFFLEVBQUUsQ0FDcEUsS0FBSyxLQUFLLFNBQVMsSUFBSSxLQUFLLEtBQUssS0FBSyxJQUFJLEtBQUssS0FBSyxFQUFFO0lBQ3BELENBQUMsQ0FBQyxFQUFFO0lBQ0osQ0FBQyxDQUFDLElBQUksSUFBSSxLQUFLLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDO0FBRXBDLE1BQU0sTUFBTSxHQUFHLENBQUMsT0FBcUIsRUFBRSxVQUFVLEdBQUcsRUFBRSxFQUFFLEVBQUU7SUFDeEQsTUFBTSxPQUFPLEdBQUc7UUFDZCxPQUFPLENBQUMsSUFBSSxLQUFLLFNBQVM7WUFDeEIsQ0FBQyxDQUFDLFNBQVM7WUFDWCxDQUFDLENBQUMsT0FBTyxDQUFDLElBQUksS0FBSyxXQUFXO2dCQUM1QixDQUFDLENBQUMsV0FBVztnQkFDYixDQUFDLENBQUMsT0FBTztRQUNiLFVBQVU7S0FDWDtTQUNFLE1BQU0sQ0FBQyxPQUFPLENBQUM7U0FDZixJQUFJLENBQUMsR0FBRyxDQUFDLENBQUM7SUFDYiwwRUFBMEU7SUFDMUUsMEVBQTBFO0lBQzFFLDJCQUEyQjtJQUMzQixNQUFNLElBQUksR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQztJQUNoRCxPQUFPLGtCQUFrQixPQUFPLFdBQVcsSUFBSSxJQUFJLFNBQVMsQ0FBQyxJQUFJLEVBQUUsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLEdBQUcsU0FBUyxDQUFDLE1BQU0sRUFBRSxPQUFPLENBQUMsSUFBSSxDQUFDLEdBQUcsU0FBUyxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsS0FBSyxDQUFDLElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDO0FBQy9NLENBQUMsQ0FBQztBQUVGLCtFQUErRTtBQUMvRSxzQ0FBc0M7QUFDdEMsTUFBTSxVQUFVLFFBQVEsQ0FBQyxJQUFZLEVBQUUsS0FBYTtJQUNsRCxPQUFPLDhEQUE4RCxNQUFNLENBQUMsSUFBSSxDQUFDLG9CQUFvQixNQUFNLENBQUMsS0FBSyxDQUFDLG9CQUFvQixDQUFDO0FBQ3pJLENBQUM7QUFFRCxNQUFNLFVBQVUsY0FBYyxDQUM1QixPQUFrRDtJQUVsRCxJQUFJLENBQUMsT0FBTyxFQUFFLE1BQU07UUFBRSxPQUFPLEVBQUUsQ0FBQztJQUNoQyxPQUFPLGtDQUFrQyxPQUFPO1NBQzdDLEdBQUcsQ0FDRixDQUFDLEtBQUssRUFBRSxLQUFLLEVBQUUsRUFBRSxDQUNmLCtCQUErQixNQUFNLENBQUMsS0FBSyxHQUFHLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLEVBQUUsR0FBRyxDQUFDLFdBQVcsTUFBTSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsV0FBVyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsQ0FDako7U0FDQSxJQUFJLENBQUMsRUFBRSxDQUFDLFFBQVEsQ0FBQztBQUN0QixDQUFDO0FBRUQsTUFBTSxVQUFVLFVBQVUsQ0FBQyxPQUFrQjtJQUMzQyxJQUFJLENBQUMsT0FBTyxFQUFFLE1BQU07UUFBRSxPQUFPLEVBQUUsQ0FBQztJQUNoQyxPQUFPLGlDQUFpQyxPQUFPO1NBQzVDLEdBQUcsQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFLENBQUMsU0FBUyxNQUFNLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQztTQUMvQyxJQUFJLENBQUMsRUFBRSxDQUFDLFdBQVcsQ0FBQztBQUN6QixDQUFDO0FBRUQsTUFBTSxVQUFVLGdCQUFnQixDQUFDLEtBQTBDO0lBQ3pFLE1BQU0sS0FBSyxHQUFHLGdCQUFnQixDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQ3RDLE9BQU8sQ0FDTCxzQkFBc0IsTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLGlEQUFpRCxNQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsa0JBQWtCLE1BQU0sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyw0QkFBNEI7UUFDdE0saURBQWlELE1BQU0sQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxvQkFBb0IsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEtBQUssTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFlBQVk7UUFDckssMkVBQTJFLE1BQU0sQ0FBQyxLQUFLLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxrQkFBa0IsTUFBTSxDQUFDLEtBQUssQ0FBQyxRQUFRLENBQUMsV0FBVyxDQUFDLGdHQUFnRyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsaUJBQWlCO1FBQ3RTLDBFQUEwRSxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsV0FBVztRQUMvRyxzRUFBc0UsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FDNUcsQ0FBQztBQUNKLENBQUM7QUFFRCxNQUFNLFVBQVUsa0JBQWtCLENBQUMsSUFBZ0I7SUFDakQsSUFBSTtTQUNELGdCQUFnQixDQUFvQix1QkFBdUIsQ0FBQztTQUM1RCxPQUFPLENBQUMsQ0FBQyxNQUFNLEVBQUUsRUFBRTtRQUNsQixNQUFNLE9BQU8sR0FBRyxNQUFNLENBQUMsWUFBWSxDQUFDLGVBQWUsQ0FBQyxDQUFDO1FBQ3JELE1BQU0sS0FBSyxHQUFHLE9BQU87WUFDbkIsQ0FBQyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQW1CLElBQUksT0FBTyxFQUFFLENBQUM7WUFDckQsQ0FBQyxDQUFDLElBQUksQ0FBQztRQUNULElBQUksQ0FBQyxLQUFLLElBQUksS0FBSyxDQUFDLElBQUksS0FBSyxVQUFVO1lBQUUsT0FBTztRQUNoRCxNQUFNLENBQUMsT0FBTyxHQUFHLEdBQUcsRUFBRTtZQUNwQixNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsSUFBSSxLQUFLLFVBQVUsQ0FBQztZQUN6QyxLQUFLLENBQUMsSUFBSSxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUM7WUFDMUMsTUFBTSxDQUFDLFdBQVcsR0FBRyxNQUFNLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDO1FBQ2hELENBQUMsQ0FBQztJQUNKLENBQUMsQ0FBQyxDQUFDO0FBQ1AsQ0FBQztBQUVELGdGQUFnRjtBQUNoRixrQkFBa0I7QUFDbEIsTUFBTSxVQUFVLFdBQVcsQ0FBQyxLQUFhLEVBQUUsS0FBbUI7SUFDNUQsTUFBTSxLQUFLLEdBQUcsWUFBWSxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsQ0FBQztJQUN6QyxNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsTUFBTTtTQUN4QixHQUFHLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRTtRQUNiLE1BQU0sS0FBSyxHQUFHLGNBQWMsTUFBTSxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsV0FBVyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQyxJQUFJLFNBQVMsQ0FBQyxjQUFjLEVBQUUsS0FBSyxDQUFDLFlBQVksQ0FBQyxHQUFHLFNBQVMsQ0FBQyxXQUFXLEVBQUUsS0FBSyxDQUFDLFNBQVMsQ0FBQyxHQUFHLEtBQUssQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsRUFBRSxHQUFHLENBQUM7UUFDNU0sT0FBTyxlQUFlLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLEtBQUssTUFBTSxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUMsV0FBVyxLQUFLLENBQUMsSUFBSSxLQUFLLFVBQVUsQ0FBQyxDQUFDLENBQUMsK0JBQStCLEtBQUssd0NBQXdDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLHVCQUF1QixDQUFDLENBQUMsQ0FBQyxLQUFLLEVBQUUsQ0FBQztJQUNyTyxDQUFDLENBQUM7U0FDRCxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUM7SUFDWixNQUFNLElBQUksR0FBRyxLQUFLLENBQUMsV0FBVztRQUM1QixDQUFDLENBQUMsdUJBQXVCLE1BQU0sR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxNQUFNLE1BQU0sQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSwyQkFBMkIsTUFBTSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsa0JBQWtCO1FBQ3hKLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDUCxNQUFNLFdBQVcsR0FBRyxLQUFLLENBQUMsV0FBVztRQUNuQyxDQUFDLENBQUMsR0FBRyxLQUFLLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsTUFBTSxNQUFNLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLEdBQUcsS0FBSyxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLFlBQVksTUFBTSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLEtBQUssTUFBTSxDQUFDLEtBQUssQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFO1FBQ3BNLENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDUCxJQUFJLEtBQUssS0FBSyxRQUFRLElBQUksS0FBSyxLQUFLLE9BQU8sSUFBSSxLQUFLLEtBQUssUUFBUTtRQUMvRCxPQUFPLE9BQU8sTUFBTSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsV0FBVyxNQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxPQUFPLElBQUksR0FBRyxXQUFXLEVBQUUsQ0FBQztJQUMvRixzRUFBc0U7SUFDdEUsdURBQXVEO0lBQ3ZELE9BQU8sQ0FDTCxPQUFPLE1BQU0sQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLE9BQU87UUFDbkMsb0RBQW9ELE1BQU0sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLGVBQWU7UUFDN0YsTUFBTSxNQUFNLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxNQUFNO1FBQy9CLCtCQUErQixNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxNQUFNO1FBQ3pELEtBQUssQ0FBQyxNQUFNO2FBQ1QsR0FBRyxDQUNGLENBQUMsT0FBTyxFQUFFLEVBQUUsQ0FDVixlQUFlLE1BQU0sQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLEtBQUssTUFBTSxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUN6RTthQUNBLElBQUksQ0FBQyxFQUFFLENBQUM7UUFDWCxlQUFlLE1BQU0sQ0FBQyxLQUFLLENBQUMsV0FBWSxDQUFDLElBQUksQ0FBQyxLQUFLLE1BQU0sQ0FBQyxLQUFLLENBQUMsV0FBWSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQzlGLENBQUM7QUFDSixDQUFDO0FBRUQsTUFBTSxVQUFVLFlBQVksQ0FBQyxNQUFjO0lBQ3pDLE9BQU8sd0NBQXdDLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxNQUFNLENBQUMsQ0FBQyxNQUFNLENBQUM7QUFDekYsQ0FBQztBQUVELDhFQUE4RTtBQUM5RSw4RUFBOEU7QUFDOUUsbUVBQW1FO0FBQ25FLE1BQU0sVUFBVSxhQUFhLENBQzNCLEtBQWEsRUFDYixLQUFhLEVBQ2IsV0FBbUIsRUFDbkIsWUFBWSxHQUFHLEtBQUssRUFDcEIsUUFBcUIsUUFBUTtJQUU3QixNQUFNLEtBQUssR0FBRyxrQkFBa0IsQ0FBQztRQUMvQixLQUFLO1FBQ0wsSUFBSSxFQUFFLFVBQVUsQ0FBQyxLQUFLLENBQUM7UUFDdkIsWUFBWTtRQUNaLEtBQUs7UUFDTCxjQUFjLEVBQUUsT0FBTyxDQUFDLFdBQVcsQ0FBQztLQUNyQyxDQUFDLENBQUM7SUFDSCxNQUFNLElBQUksR0FBRywwQkFBMEIsTUFBTSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDO0lBQ2hFLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSTtRQUFFLE9BQU8sSUFBSSxHQUFHLFdBQVcsQ0FBQztJQUMzQyxNQUFNLElBQUksR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksRUFBRSxZQUFZLENBQUMsQ0FBQztJQUM5QyxNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsTUFBTTtRQUN6QixDQUFDLENBQUMsNkJBQTZCLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxtQkFBbUIsTUFBTSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFdBQVc7UUFDOUcsQ0FBQyxDQUFDLEVBQUUsQ0FBQztJQUNQLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBVTtRQUFFLE9BQU8sSUFBSSxHQUFHLElBQUksR0FBRyxNQUFNLENBQUM7SUFDbkQsNkVBQTZFO0lBQzdFLDhFQUE4RTtJQUM5RSx5RUFBeUU7SUFDekUsT0FBTyxDQUNMLElBQUk7UUFDSixJQUFJO1FBQ0osTUFBTTtRQUNOLDJHQUEyRyxLQUFLLENBQUMsVUFBVSxDQUFDLFFBQVEsb0JBQW9CLE1BQU0sQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyx1Q0FBdUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDO2FBQ3JQLE1BQU0sQ0FBQyxLQUFLLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxZQUFZLFdBQVcsY0FBYyxDQUNoRixDQUFDO0FBQ0osQ0FBQztBQUVELDJFQUEyRTtBQUMzRSxrQ0FBa0M7QUFDbEMsTUFBTSxVQUFVLGVBQWUsQ0FDN0IsS0FBYSxFQUNiLFNBQThDLEVBQzlDLElBQVk7SUFFWixNQUFNLEtBQUssR0FBRyxjQUFjLENBQUMsS0FBSyxFQUFFLFNBQVMsQ0FBQyxDQUFDO0lBQy9DLE9BQU8sT0FBTyxNQUFNLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQzsyQkFDVixNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQzs2Q0FDQSxNQUFNLENBQUMsS0FBSyxDQUFDLElBQUksQ0FBQzs4SEFDK0QsTUFBTSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsNERBQTRELE1BQU0sQ0FBQyxJQUFJLENBQUMsZ0VBQWdFLE1BQU0sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDO3lDQUM1USxLQUFLLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLEVBQUUsSUFBSSxNQUFNLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQyxXQUFXLENBQUM7QUFDekgsQ0FBQztBQUVELG9EQUFvRDtBQUNwRCxNQUFNLFVBQVUsZ0JBQWdCLENBQUMsS0FBd0I7SUFDdkQsTUFBTSxLQUFLLEdBQUcscUJBQXFCLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDM0MsTUFBTSxNQUFNLEdBQUcsS0FBSyxDQUFDLE1BQU07UUFDekIsQ0FBQyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsSUFBSSxLQUFLLE9BQU87WUFDN0IsQ0FBQyxDQUFDLGlDQUFpQyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsTUFBTTtZQUNsRSxDQUFDLENBQUMsd0JBQXdCLE1BQU0sQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNO1FBQzNELENBQUMsQ0FBQyxFQUFFLENBQUM7SUFDUCxPQUFPO3FFQUM0RCxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxZQUFZLE1BQU0sQ0FBQyxLQUFLLENBQUMsS0FBSyxDQUFDO3lCQUMvRixNQUFNLENBQUMsS0FBSyxDQUFDLFNBQVMsQ0FBQztJQUM1QyxNQUFNO21EQUN5QyxNQUFNLENBQUMsS0FBSyxDQUFDLFdBQVcsQ0FBQztTQUNuRSxDQUFDO0FBQ1YsQ0FBQztBQUVELDhFQUE4RTtBQUM5RSxzQ0FBc0M7QUFDdEMsOEVBQThFO0FBRTlFLDhFQUE4RTtBQUM5RSxnRkFBZ0Y7QUFDaEYsTUFBTSxVQUFVLGlCQUFpQixDQUFDLElBQXFCO0lBQ3JELE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQW1CLG9CQUFvQixDQUFDLENBQUM7SUFDNUUsSUFBSSxDQUFDLFFBQVEsRUFBRSxPQUFPLElBQUksUUFBUSxDQUFDLFFBQVEsSUFBSSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsT0FBTztRQUN0RSxPQUFPLElBQUksQ0FBQztJQUNkLE9BQU8sRUFBRSxhQUFhLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxRQUFRLENBQUMsT0FBTyxDQUFDLE9BQU8sRUFBRSxDQUFDO0FBQ3pFLENBQUM7QUFFRCw4RUFBOEU7QUFDOUUsc0VBQXNFO0FBQ3RFLGdGQUFnRjtBQUNoRixnRkFBZ0Y7QUFDaEYsa0NBQWtDO0FBQ2xDLE1BQU0sVUFBVSxtQkFBbUIsQ0FBQyxJQUE0QjtJQUM5RCxJQUFJLENBQUMsSUFBSTtRQUFFLE9BQU87SUFDbEIsTUFBTSxRQUFRLEdBQUcsSUFBSSxDQUFDLGFBQWEsQ0FBbUIsb0JBQW9CLENBQUMsQ0FBQztJQUM1RSxJQUFJLENBQUMsUUFBUTtRQUFFLE9BQU87SUFDdEIsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLGdCQUFnQixDQUNuQyx1QkFBdUIsQ0FDeEIsQ0FBQztJQUNGLE1BQU0sTUFBTSxHQUFHLEdBQUcsRUFBRSxDQUNsQixPQUFPLENBQUMsT0FBTyxDQUFDLENBQUMsT0FBTyxFQUFFLEVBQUU7UUFDMUIsT0FBTyxDQUFDLFFBQVEsR0FBRyxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUM7SUFDdkMsQ0FBQyxDQUFDLENBQUM7SUFDTCxRQUFRLENBQUMsZ0JBQWdCLENBQUMsUUFBUSxFQUFFLE1BQU0sQ0FBQyxDQUFDO0lBQzVDLE1BQU0sYUFBYSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQ3RDLHFCQUFxQixDQUN0QixDQUFDO0lBQ0YsYUFBYSxFQUFFLGdCQUFnQixDQUFDLE9BQU8sRUFBRSxDQUFDLEtBQUssRUFBRSxFQUFFO1FBQ2pELEtBQUssQ0FBQyxjQUFjLEVBQUUsQ0FBQztRQUN2QixNQUFNLENBQUMsSUFBSSxDQUNULGFBQWEsQ0FBQyxJQUFJLEVBQ2xCLGdCQUFnQixFQUNoQixvREFBb0QsQ0FDckQsQ0FBQztJQUNKLENBQUMsQ0FBQyxDQUFDO0lBQ0gsTUFBTSxFQUFFLENBQUM7QUFDWCxDQUFDO0FBRUQsc0VBQXNFO0FBQ3RFLEVBQUU7QUFDRixnRkFBZ0Y7QUFDaEYsK0VBQStFO0FBQy9FLGdGQUFnRjtBQUNoRiw4RUFBOEU7QUFDOUUsa0VBQWtFO0FBQ2xFLE1BQU0sVUFBVSxjQUFjLENBQUMsSUFBYSxFQUFFLEtBQUssR0FBRyxLQUFLO0lBQ3pELE1BQU0sTUFBTSxHQUFHLFFBQVEsQ0FBQyxjQUFjLENBQUMsYUFBYSxDQUFDLENBQUM7SUFDdEQsTUFBTSxNQUFNLEdBQUcsUUFBUSxDQUFDLGNBQWMsQ0FBQyxXQUFXLENBQUMsQ0FBQztJQUNwRCxJQUFJLENBQUMsTUFBTSxJQUFJLENBQUMsTUFBTTtRQUFFLE9BQU87SUFDL0IsTUFBTSxDQUFDLFlBQVksQ0FBQyxlQUFlLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUM7SUFDbkQsTUFBTSxDQUFDLE1BQU0sR0FBRyxDQUFDLElBQUksQ0FBQztJQUN0QixNQUFNLE1BQU0sR0FBRyxRQUFRLENBQUMsY0FBYyxDQUFDLGFBQWEsQ0FBQyxDQUFDO0lBQ3RELElBQUksTUFBTTtRQUFFLE1BQU0sQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDO0lBQ2pDLE1BQU0sSUFBSSxHQUFHLFFBQVEsQ0FBQyxhQUFhLENBQW9CLGFBQWEsQ0FBQyxDQUFDO0lBQ3RFLElBQUksSUFBSSxFQUFFLENBQUM7UUFDVCxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxXQUFXLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFDekMsdUVBQXVFO1FBQ3ZFLHVFQUF1RTtRQUN2RSxzQ0FBc0M7UUFDdEMsSUFBSSxJQUFJO1lBQUUsSUFBSSxDQUFDLFlBQVksQ0FBQyxhQUFhLEVBQUUsTUFBTSxDQUFDLENBQUM7O1lBQzlDLElBQUksQ0FBQyxlQUFlLENBQUMsYUFBYSxDQUFDLENBQUM7UUFDekMsSUFBSSxDQUFDLFFBQVEsR0FBRyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUM7SUFDaEMsQ0FBQztJQUNELElBQUksSUFBSSxJQUFJLEtBQUs7UUFBRSxRQUFRLENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxFQUFFLEtBQUssRUFBRSxDQUFDO0FBQy9ELENBQUM7QUFFRCxNQUFNLFVBQVUsZ0JBQWdCLENBQUMsT0FBZSxFQUFFLFdBQW9CO0lBQ3BFLElBQUksQ0FBQywyQkFBMkIsQ0FBQyxJQUFJLENBQUMsT0FBTyxJQUFJLEVBQUUsQ0FBQztRQUFFLE9BQU87SUFDN0QsTUFBTSxLQUFLLEdBQUcsUUFBUSxDQUFDLGFBQWEsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUM1QyxLQUFLLENBQUMsU0FBUyxHQUFHLGNBQWMsQ0FBQztJQUNqQyxLQUFLLENBQUMsWUFBWSxDQUFDLFlBQVksRUFBRSxnQkFBZ0IsT0FBTyxFQUFFLENBQUMsQ0FBQztJQUM1RCxLQUFLLENBQUMsV0FBVyxHQUFHLFFBQVEsT0FBTyxFQUFFLENBQUM7SUFDdEMsUUFBUSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUM7SUFDNUIsSUFBSSxXQUFXLEVBQUUsQ0FBQztRQUNoQixLQUFLLEtBQUssQ0FBQyxHQUFHLFdBQVcsQ0FBQyxPQUFPLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxTQUFTLENBQUM7YUFDbkQsSUFBSSxDQUFDLENBQUMsUUFBUSxFQUFFLEVBQUUsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7YUFDMUQsSUFBSSxDQUFDLENBQUMsTUFBTSxFQUFFLEVBQUU7WUFDZixNQUFNLFVBQVUsR0FBRyxNQUFNLEVBQUUsT0FBTyxJQUFJLE1BQU0sRUFBRSxLQUFLLENBQUM7WUFDcEQsSUFBSSxDQUFDLFVBQVU7Z0JBQUUsT0FBTztZQUN4QixLQUFLLENBQUMsV0FBVyxHQUFHLFFBQVEsT0FBTyxVQUFVLFVBQVUsRUFBRSxDQUFDO1lBQzFELEtBQUssQ0FBQyxZQUFZLENBQ2hCLFlBQVksRUFDWixnQkFBZ0IsT0FBTyxpQkFBaUIsVUFBVSxFQUFFLENBQ3JELENBQUM7UUFDSixDQUFDLENBQUM7YUFDRCxLQUFLLENBQUMsR0FBRyxFQUFFLENBQUMsU0FBUyxDQUFDLENBQUM7SUFDNUIsQ0FBQztBQUNILENBQUMifQ==
package/index.d.ts CHANGED
@@ -1,4 +1,2 @@
1
- export { agreementMarkup, acceptedAgreement, signInErrorMessage, bindAgreement, providerEntry, signInHint, rememberSignIn, forgetSignIn, showEmailEntry, type SigninShape, } from "./service-agreement.js";
2
- export { openProviderWindow, relayProviderAnswer, type ProviderWindow, } from "./provider-window.js";
3
- export { showVersionBadge } from "./version.js";
4
- export { escape, masthead, highlightCells, badgeStrip, credentialFields, accountForm, returnNotice, type AccountState, } from "./screens.js";
1
+ export { agreementRequired, agreementFromRefusal, verificationPending, signInErrorMessage, acceptance, providerEntryModel, agreementModel, verificationWaitModel, accountModel, credentialsModel, returnNoticeModel, pollVerification, type SigninShape, type EntryControl, type ProviderEntryModel, type AgreementModel, type VerificationState, type VerificationWaitModel, type AccountState, type AccountField, type AccountModel, type CredentialsModel, } from "./model.js";
2
+ export { signInHint, rememberSignIn, forgetSignIn } from "./remembered.js";
package/index.js CHANGED
@@ -1,12 +1,16 @@
1
- // The Fidj entry, in one place.
1
+ // The Fidj entry: the rules, and every sentence a person is shown.
2
2
  //
3
- // Everything here was lifted verbatim out of generator-fidj's template, where
4
- // it could only ship by being generated. It is a package now so that the
5
- // console can import the same screens a generated app renders, instead of the
6
- // two being kept in step by hand — which is how the service agreement ended up
7
- // existing in four copies that no test could diff.
8
- export { agreementMarkup, acceptedAgreement, signInErrorMessage, bindAgreement, providerEntry, signInHint, rememberSignIn, forgetSignIn, showEmailEntry, } from "./service-agreement.js";
9
- export { openProviderWindow, relayProviderAnswer, } from "./provider-window.js";
10
- export { showVersionBadge } from "./version.js";
11
- export { escape, masthead, highlightCells, badgeStrip, credentialFields, accountForm, returnNotice, } from "./screens.js";
12
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsZ0NBQWdDO0FBQ2hDLEVBQUU7QUFDRiw4RUFBOEU7QUFDOUUseUVBQXlFO0FBQ3pFLDhFQUE4RTtBQUM5RSwrRUFBK0U7QUFDL0UsbURBQW1EO0FBQ25ELE9BQU8sRUFDTCxlQUFlLEVBQ2YsaUJBQWlCLEVBQ2pCLGtCQUFrQixFQUNsQixhQUFhLEVBQ2IsYUFBYSxFQUNiLFVBQVUsRUFDVixjQUFjLEVBQ2QsWUFBWSxFQUNaLGNBQWMsR0FFZixNQUFNLHdCQUF3QixDQUFDO0FBQ2hDLE9BQU8sRUFDTCxrQkFBa0IsRUFDbEIsbUJBQW1CLEdBRXBCLE1BQU0sc0JBQXNCLENBQUM7QUFDOUIsT0FBTyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sY0FBYyxDQUFDO0FBQ2hELE9BQU8sRUFDTCxNQUFNLEVBQ04sUUFBUSxFQUNSLGNBQWMsRUFDZCxVQUFVLEVBQ1YsZ0JBQWdCLEVBQ2hCLFdBQVcsRUFDWCxZQUFZLEdBRWIsTUFBTSxjQUFjLENBQUMifQ==
3
+ // This root is pure. No DOM, no markup, no view layer — a screen is a value, so
4
+ // the same entry can be drawn as HTML strings, as React components or as Vue
5
+ // single-file components without any of them re-deriving a rule or re-typing a
6
+ // sentence. That is what the package is for: these screens used to live only in
7
+ // generator-fidj's template, where shipping them meant generating an app, and
8
+ // the alternative — keeping a second copy in step by hand — is what produced
9
+ // four versions of the service agreement that no test could diff.
10
+ //
11
+ // Two subpaths carry what cannot be pure:
12
+ // @ofidj/entry/dom the HTML renderer and the helpers that drive a document
13
+ // @ofidj/entry/window the Fidj window and the answer it relays back
14
+ export { agreementRequired, agreementFromRefusal, verificationPending, signInErrorMessage, acceptance, providerEntryModel, agreementModel, verificationWaitModel, accountModel, credentialsModel, returnNoticeModel, pollVerification, } from "./model.js";
15
+ export { signInHint, rememberSignIn, forgetSignIn } from "./remembered.js";
16
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsbUVBQW1FO0FBQ25FLEVBQUU7QUFDRixnRkFBZ0Y7QUFDaEYsNkVBQTZFO0FBQzdFLCtFQUErRTtBQUMvRSxnRkFBZ0Y7QUFDaEYsOEVBQThFO0FBQzlFLDZFQUE2RTtBQUM3RSxrRUFBa0U7QUFDbEUsRUFBRTtBQUNGLDBDQUEwQztBQUMxQyxpRkFBaUY7QUFDakYsdUVBQXVFO0FBQ3ZFLE9BQU8sRUFDTCxpQkFBaUIsRUFDakIsb0JBQW9CLEVBQ3BCLG1CQUFtQixFQUNuQixrQkFBa0IsRUFDbEIsVUFBVSxFQUNWLGtCQUFrQixFQUNsQixjQUFjLEVBQ2QscUJBQXFCLEVBQ3JCLFlBQVksRUFDWixnQkFBZ0IsRUFDaEIsaUJBQWlCLEVBQ2pCLGdCQUFnQixHQVdqQixNQUFNLFlBQVksQ0FBQztBQUNwQixPQUFPLEVBQUUsVUFBVSxFQUFFLGNBQWMsRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQyJ9