@ofidj/generator-fidj 3.15.0 → 3.16.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 +7 -0
- package/bin/create-fidj.cjs +5 -1
- package/generators/app/index.js +4 -0
- package/generators/app/templates/typescript/package.json +2 -2
- package/generators/app/templates/typescript/src/content.ts +38 -72
- package/generators/app/templates/typescript/src/main.ts +2 -2
- package/lib/scaffold.cjs +4 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -136,6 +136,13 @@ return them to, hands the answer back when they are done, and closes itself. A
|
|
|
136
136
|
browser that will not open one falls back to the full-page redirect. Fidj's own
|
|
137
137
|
console takes the same door for the same reason — one journey, three apps.
|
|
138
138
|
|
|
139
|
+
**The passkey (3.15.0).** Fidj's own shell leads with **Continue with a
|
|
140
|
+
passkey**, the email form under it, and shows the EU wallet door instead of the
|
|
141
|
+
"Your account, with Fidj" note. Every other app keeps its form and reaches the
|
|
142
|
+
passkey through the Fidj window: there is one relying party, Fidj's domain, so a
|
|
143
|
+
passkey cannot be asked for on another app's own page. A passkey sign-in owes the
|
|
144
|
+
same answers as a password one; the agreement is accepted with a second touch.
|
|
145
|
+
|
|
139
146
|
## Compose an existing app as a module
|
|
140
147
|
|
|
141
148
|
Build your application for the `/module/` base URL, then pass its public output to the same generator:
|
package/bin/create-fidj.cjs
CHANGED
|
@@ -24,6 +24,8 @@ try {
|
|
|
24
24
|
domain: { type: "string" },
|
|
25
25
|
module: { type: "string" },
|
|
26
26
|
"module-entry": { type: "string" },
|
|
27
|
+
"module-version": { type: "string" },
|
|
28
|
+
"module-label": { type: "string" },
|
|
27
29
|
local: { type: "boolean" },
|
|
28
30
|
replace: { type: "boolean" },
|
|
29
31
|
help: { type: "boolean" },
|
|
@@ -31,7 +33,7 @@ try {
|
|
|
31
33
|
});
|
|
32
34
|
if (values.help || positionals.length !== 1) {
|
|
33
35
|
console.log(
|
|
34
|
-
"Usage: create-fidj <directory> --app-id <fidjId> [--api-endpoint <url>] [--title <text> --welcome <text> --description <text> --content <html> --domain <hostname>] [--highlight '<heading>|<body>' ...] [--badge <text> ...] [--logo <image>] [--favicon <image>] [--module <built-directory> --module-entry <index.html#/route>] [--oidc-issuer https://api.example/oidc] [--anonymous true|false] [--signin button|inline|both] [--credentials true|false] [--local] [--replace]",
|
|
36
|
+
"Usage: create-fidj <directory> --app-id <fidjId> [--api-endpoint <url>] [--title <text> --welcome <text> --description <text> --content <html> --domain <hostname>] [--highlight '<heading>|<body>' ...] [--badge <text> ...] [--logo <image>] [--favicon <image>] [--module <built-directory> --module-entry <index.html#/route> [--module-version <x.y.z> --module-label <name>]] [--oidc-issuer https://api.example/oidc] [--anonymous true|false] [--signin button|inline|both] [--credentials true|false] [--local] [--replace]",
|
|
35
37
|
);
|
|
36
38
|
process.exitCode = values.help ? 0 : 1;
|
|
37
39
|
} else {
|
|
@@ -55,6 +57,8 @@ try {
|
|
|
55
57
|
domain: values.domain,
|
|
56
58
|
module: values.module,
|
|
57
59
|
moduleEntry: values["module-entry"],
|
|
60
|
+
moduleVersion: values["module-version"],
|
|
61
|
+
moduleLabel: values["module-label"],
|
|
58
62
|
local: values.local || process.env.FIDJ_LOCAL === "true",
|
|
59
63
|
replace: values.replace,
|
|
60
64
|
});
|
package/generators/app/index.js
CHANGED
|
@@ -20,6 +20,8 @@ const TEXT_OPTIONS = [
|
|
|
20
20
|
"domain",
|
|
21
21
|
"module",
|
|
22
22
|
"module-entry",
|
|
23
|
+
"module-version",
|
|
24
|
+
"module-label",
|
|
23
25
|
"logo",
|
|
24
26
|
"favicon",
|
|
25
27
|
];
|
|
@@ -98,6 +100,8 @@ module.exports = class extends Generator {
|
|
|
98
100
|
favicon: this.options.favicon,
|
|
99
101
|
module: this.options.module,
|
|
100
102
|
moduleEntry: this.options["module-entry"],
|
|
103
|
+
moduleVersion: this.options["module-version"],
|
|
104
|
+
moduleLabel: this.options["module-label"],
|
|
101
105
|
domain: this.options.domain,
|
|
102
106
|
sdkPath: this.options["sdk-path"] || process.env.FIDJ_SDK_DIR,
|
|
103
107
|
entryPath: this.options["entry-path"] || process.env.FIDJ_ENTRY_DIR,
|
|
@@ -15,8 +15,8 @@
|
|
|
15
15
|
"privacy:rehearse": "npm run build && node --test test/server.test.mjs"
|
|
16
16
|
},
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@ofidj/entry": "^3.
|
|
19
|
-
"@ofidj/node": "^3.
|
|
18
|
+
"@ofidj/entry": "^3.16.0",
|
|
19
|
+
"@ofidj/node": "^3.16.0"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"@types/node": "^22.0.0",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {agreementScreen, bindAgreementScreen, bindPasswordReveal, acceptedAgreement, verificationWait, providerEntry, showEmailEntry, showVersionBadge, escape, masthead, highlightCells, badgeStrip, credentialFields, accountForm,
|
|
1
|
+
import {signInErrorMessage, agreementRequired, agreementFromRefusal, verificationPending, pollVerification, rememberSignIn, forgetSignIn, signInHint, type SigninShape} from "@ofidj/entry";
|
|
2
|
+
import {agreementScreen, bindAgreementScreen, bindPasswordReveal, acceptedAgreement, verificationWait, providerEntry, showEmailEntry, showVersionBadge, escape, masthead, highlightCells, badgeStrip, credentialFields, accountForm, passkeySupported, passkeyAssertion, walletDoor, oidcInteractionMarkup, oidcInteractionStyles, bindOidcInteraction} from "@ofidj/entry/dom";
|
|
3
3
|
import {openProviderWindow, relayProviderAnswer, type ProviderWindow} from "@ofidj/entry/window";
|
|
4
4
|
import { FidjNodeService, FidjOidcClient } from "@ofidj/node";
|
|
5
5
|
import config from "../app.config.json";
|
|
@@ -8,7 +8,11 @@ import "@ofidj/entry/style.css";
|
|
|
8
8
|
const sdk = new FidjNodeService();
|
|
9
9
|
const oidc = config.oidcIssuer ? new FidjOidcClient({issuer: config.oidcIssuer, clientId: config.appId, redirectUri: window.location.origin + window.location.pathname, apiEndpoint: config.apiEndpoint, storage: sessionStorage}) : null;
|
|
10
10
|
const root = document.querySelector<HTMLDivElement>("#app")!;
|
|
11
|
-
showVersionBadge(
|
|
11
|
+
showVersionBadge(
|
|
12
|
+
config.releaseVersion,
|
|
13
|
+
config.title === "Fidj" ? config.apiEndpoint : undefined,
|
|
14
|
+
config.moduleVersion ? {name: config.moduleLabel || "module", version: config.moduleVersion} : undefined,
|
|
15
|
+
);
|
|
12
16
|
const appPath = `/me/apps/${encodeURIComponent(config.appId)}`;
|
|
13
17
|
// Passkeys (v3 P1-4): one relying party, Fidj's own domain. Only Fidj's own
|
|
14
18
|
// shell runs the ceremony on its page; every other app reaches the passkey
|
|
@@ -997,9 +1001,9 @@ function privacyBlock() {
|
|
|
997
1001
|
.join("")
|
|
998
1002
|
: "<p>No changes yet.</p>"
|
|
999
1003
|
}
|
|
1000
|
-
<button id="export">Export
|
|
1004
|
+
<button id="export">Export</button>
|
|
1001
1005
|
<p>This app stores its session in this browser. The export covers Fidj-held records for this membership. There is no separate app database in this static template.</p>
|
|
1002
|
-
${roles.includes("Owner") ? "<p>Resolve app ownership before leaving.</p>" : leaving ? '<p>Confirm departure: your membership and its Fidj-held data will be removed. Your other apps remain available.</p><button id="confirm-leave" class="danger">
|
|
1006
|
+
${roles.includes("Owner") ? "<p>Resolve app ownership before leaving.</p>" : leaving ? '<p>Confirm departure: your membership and its Fidj-held data will be removed. Your other apps remain available.</p><button id="confirm-leave" class="danger">Leave & erase</button><button id="cancel-leave">Keep my membership</button>' : '<button id="leave" class="danger">Leave & erase</button>'}
|
|
1003
1007
|
<p class="leaving"><a href="${escape(config.dashboardUrl)}/#/my" target="_blank" rel="noopener">Open Fidj to manage every app you use ↗</a><br><small>Fidj is the account provider behind ${escape(config.title)}. This opens it in a new tab; you stay signed in here.</small></p>`;
|
|
1004
1008
|
}
|
|
1005
1009
|
|
|
@@ -1024,8 +1028,9 @@ type Interaction = {
|
|
|
1024
1028
|
scopes: string[];
|
|
1025
1029
|
termsUri: string;
|
|
1026
1030
|
privacyUri: string;
|
|
1027
|
-
// The agreement's own text, so it can be read here rather than in another tab.
|
|
1028
1031
|
agreement?: {version: string; text: string} | null;
|
|
1032
|
+
// Who the consent screen recognises, as the provider names them.
|
|
1033
|
+
recognisedEmail?: string;
|
|
1029
1034
|
action: string;
|
|
1030
1035
|
};
|
|
1031
1036
|
let interactionId = "";
|
|
@@ -1119,10 +1124,6 @@ function interactionWaitNotice() {
|
|
|
1119
1124
|
|
|
1120
1125
|
function interactionScreen() {
|
|
1121
1126
|
const details = interaction!;
|
|
1122
|
-
const asking = escape(details.app.title);
|
|
1123
|
-
const notice = interactionError
|
|
1124
|
-
? `<p role="alert" class="error">${escape(refusals[interactionError] || refusals.refused)}</p>`
|
|
1125
|
-
: "";
|
|
1126
1127
|
const action = new URL(details.action, config.apiEndpoint).href;
|
|
1127
1128
|
// A refusal comes back as a redirect, so the typed address would be lost —
|
|
1128
1129
|
// and retyping an address is the part a person gets wrong twice. It is kept
|
|
@@ -1131,67 +1132,32 @@ function interactionScreen() {
|
|
|
1131
1132
|
try {
|
|
1132
1133
|
typed = sessionStorage.getItem("fidj.interaction.email") || "";
|
|
1133
1134
|
} catch {}
|
|
1134
|
-
//
|
|
1135
|
-
//
|
|
1136
|
-
//
|
|
1137
|
-
|
|
1138
|
-
//
|
|
1139
|
-
//
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
: details.
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
<form method="post" action="${escape(action)}" id="interaction">
|
|
1161
|
-
<input type="hidden" name="csrf" value="${escape(details.csrf)}">
|
|
1162
|
-
<label for="email">Email</label><input id="email" name="email" type="email" value="${escape(typed)}" autocomplete="username" required>
|
|
1163
|
-
<div class="field-head"><label for="password">Password</label><a href="${escape(config.dashboardUrl)}/#/forgot">Forgot?</a></div>
|
|
1164
|
-
<div class="password-field"><input id="password" name="password" type="password" autocomplete="current-password" required><button type="button" id="reveal" aria-controls="password">Show</button></div>
|
|
1165
|
-
<button class="primary" type="submit" name="action" value="continue">Sign in</button>
|
|
1166
|
-
<button class="secondary" type="submit" name="action" value="signup">Create a Fidj account</button>
|
|
1167
|
-
<button class="quiet" type="submit" name="action" value="cancel" formnovalidate>Cancel and go back</button>
|
|
1168
|
-
</form>`
|
|
1169
|
-
: `<h2>${itself ? "Continue to Fidj" : "Continue to " + asking}</h2>
|
|
1170
|
-
<p class="signin-lead">${itself ? "Fidj is asking for the information below. Optional privacy choices stay separate for every app, including this one." : `${asking} is asking for the information below. Optional privacy choices stay separate, and you can change them in Fidj at any time.`}</p>
|
|
1171
|
-
${returnNotice(itself ? "Fidj" : asking)}
|
|
1172
|
-
${notice}
|
|
1173
|
-
<ul class="scope-list">${details.scopes
|
|
1174
|
-
.filter((scope) => scopeMeaning[scope])
|
|
1175
|
-
.map((scope) => `<li>${escape(scopeMeaning[scope])}</li>`)
|
|
1176
|
-
.join("")}</ul>
|
|
1177
|
-
<form method="post" action="${escape(action)}" id="interaction">
|
|
1178
|
-
<input type="hidden" name="csrf" value="${escape(details.csrf)}">
|
|
1179
|
-
<label class="agreement-choice"><input type="checkbox" name="terms" value="true" required><span>${escape(agreementModel(details.app.title, {}).checkboxLabel)}</span></label>
|
|
1180
|
-
${details.agreement ? `<details class="agreement"><summary>Read service agreement</summary><p class="fineprint">Version ${escape(details.agreement.version)}</p><p>${escape(details.agreement.text)}</p></details><p class="fineprint">Required to sign in. Optional data choices stay separate.</p>` : ""}
|
|
1181
|
-
${details.termsUri ? `<p class="fineprint"><a href="${escape(details.termsUri)}" target="_blank" rel="noopener noreferrer">Service agreement</a>${details.privacyUri ? ` · <a href="${escape(details.privacyUri)}" target="_blank" rel="noopener noreferrer">Privacy notice</a>` : ""}</p>` : ""}
|
|
1182
|
-
<button class="primary" type="submit" name="action" value="continue">Allow and continue</button>
|
|
1183
|
-
<button class="quiet" type="submit" id="not-me" name="action" value="switch" formnovalidate>Not you? Sign in with another account</button>
|
|
1184
|
-
<button class="quiet" type="submit" name="action" value="cancel" formnovalidate>Cancel and go back</button>
|
|
1185
|
-
</form>`;
|
|
1186
|
-
|
|
1187
|
-
root.innerHTML = `<section class="signin-shell"><div class="signin-intro is-plain">${masthead(config.logo, config.title)}
|
|
1188
|
-
<div class="signin-identity"><h1>Your identity.<br>Your choices.</h1><p class="signin-description">One account across every app that uses Fidj, and a separate set of choices for each one.</p></div>
|
|
1189
|
-
${highlightCells(config.highlights)}</div>
|
|
1190
|
-
<div class="signin-form"><div>${body}</div>
|
|
1191
|
-
<div class="signin-trust"><p class="signin-trust-head"><img class="signin-logo" src="./fidj-logo.png" alt="Fidj"><strong>What Fidj is</strong></p><p>Fidj holds your account so each app does not have to. You can see every app you use, what it holds, and take it back — at any time.</p></div></div>
|
|
1192
|
-
${badgeStrip(config.badges)}</section>`;
|
|
1193
|
-
|
|
1194
|
-
if (element("interaction")) bindPasswordReveal(element("interaction")!);
|
|
1135
|
+
// The provider's own screen, drawn here: the same markup and the same scoped
|
|
1136
|
+
// styles as the page it serves itself. This window was opened by an app for
|
|
1137
|
+
// one question, so nothing of this front end's own sign-in page — masthead,
|
|
1138
|
+
// promises, "What Fidj is" — is drawn around it. The wait is not a refusal
|
|
1139
|
+
// and is not drawn as one: its address comes from the interaction's context,
|
|
1140
|
+
// never from the URL.
|
|
1141
|
+
const mode = details.awaiting ? "waiting" : details.prompt === "login" ? "login" : "consent";
|
|
1142
|
+
root.innerHTML = `<style>${oidcInteractionStyles}</style>${oidcInteractionMarkup({
|
|
1143
|
+
mode,
|
|
1144
|
+
appTitle: details.app.title,
|
|
1145
|
+
action,
|
|
1146
|
+
csrf: details.csrf,
|
|
1147
|
+
notice: interactionError ? refusals[interactionError] || refusals.refused : undefined,
|
|
1148
|
+
email: typed,
|
|
1149
|
+
forgotHref: `${config.dashboardUrl}/#/forgot`,
|
|
1150
|
+
waitingEmail: details.awaiting,
|
|
1151
|
+
resent: interactionResent,
|
|
1152
|
+
notYet: interactionNotYet,
|
|
1153
|
+
scopes: details.scopes.filter((scope) => scopeMeaning[scope]).map((scope) => scopeMeaning[scope]),
|
|
1154
|
+
agreement: details.agreement || undefined,
|
|
1155
|
+
// The agreement is a document read in the browser, like the privacy notice.
|
|
1156
|
+
agreementHref: details.termsUri || undefined,
|
|
1157
|
+
recognisedEmail: details.recognisedEmail || undefined,
|
|
1158
|
+
logoSrc: "./fidj-logo.png",
|
|
1159
|
+
})}`;
|
|
1160
|
+
bindOidcInteraction(root);
|
|
1195
1161
|
// Being recognised is the point, and a dead end when the person is not who
|
|
1196
1162
|
// Fidj thinks — a shared computer, a second account, somebody else's tab. So
|
|
1197
1163
|
// the screen that recognises them asks again on request. It goes back to the
|
|
@@ -1199,7 +1165,7 @@ function interactionScreen() {
|
|
|
1199
1165
|
// session doing the recognising: starting a fresh request with prompt=login
|
|
1200
1166
|
// from here asked once and left that session standing, so the back button,
|
|
1201
1167
|
// a reload, or the app's door again met the same face.
|
|
1202
|
-
|
|
1168
|
+
root.querySelector('button[value="switch"]')?.addEventListener("click", () => {
|
|
1203
1169
|
forgetSignIn(config.appId);
|
|
1204
1170
|
try {
|
|
1205
1171
|
sessionStorage.removeItem("fidj.interaction.email");
|
|
@@ -224,7 +224,7 @@ function render() {
|
|
|
224
224
|
${
|
|
225
225
|
view === "workspace"
|
|
226
226
|
? `<section class="workspace"><div><div class="section-heading"><h2>Your notes</h2><span>${notes.length} saved</span></div>${notes.length ? notes.map((note) => `<article class="card note"><small>${escape(new Date(note.createdAt).toLocaleString())}</small><h3>${escape(note.title)}</h3><p>${escape(note.body)}</p></article>`).join("") : `<article class="card empty"><span>✳</span><h3>Room for your next idea.</h3><p>Your saved notes will appear here. Only you can read your notes.</p></article>`}</div><form id="note" class="card"><p class="eyebrow">CAPTURE SOMETHING</p><h2>A fresh note</h2><p>${canWrite ? "You have permission to save notes." : "Ask your app owner for Editor access to save notes."}</p><label for="note-title">Title</label><input id="note-title" maxlength="120" required ${!canWrite ? "disabled" : ""}><label for="note-body">Your note</label><textarea id="note-body" rows="6" maxlength="5000" ${!canWrite ? "disabled" : ""}></textarea><button class="primary" type="submit" ${!canWrite ? "disabled" : ""}>Save note</button><small>Your notes are saved by this app and survive a server restart.</small></form></section>`
|
|
227
|
-
: `<section class="privacy-grid"><article class="card"><p class="eyebrow">ONLY ${escape(settings.title).toUpperCase()}</p><h2>Your choices in this app</h2><p>These preferences are independent of Fidj and your other apps.</p><div class="agreement"><strong>Service agreement</strong><span>${privacy?.consent.terms ? "Accepted" : "Not recorded"}</span>${!privacy?.consent.terms ? '<p>This starter uses a demo agreement. Accept it to record your choice.</p><button id="accept-terms">Accept demo agreement</button>' : "<p>Leaving this app withdraws its required agreement.</p>"}</div>${["analytics", "communications", "optionalData"].map((key, index) => `<label class="toggle"><span><strong>${["Analytics", "Communications", "Optional data"][index]}</strong><small>${["Help improve this app.", "Receive optional news and updates.", "Allow data beyond the essential service."][index]}</small></span><input type="checkbox" data-purpose="${key}" ${privacy?.consent[key] ? "checked" : ""}></label>`).join("")}<button id="export">Export
|
|
227
|
+
: `<section class="privacy-grid"><article class="card"><p class="eyebrow">ONLY ${escape(settings.title).toUpperCase()}</p><h2>Your choices in this app</h2><p>These preferences are independent of Fidj and your other apps.</p><div class="agreement"><strong>Service agreement</strong><span>${privacy?.consent.terms ? "Accepted" : "Not recorded"}</span>${!privacy?.consent.terms ? '<p>This starter uses a demo agreement. Accept it to record your choice.</p><button id="accept-terms">Accept demo agreement</button>' : "<p>Leaving this app withdraws its required agreement.</p>"}</div>${["analytics", "communications", "optionalData"].map((key, index) => `<label class="toggle"><span><strong>${["Analytics", "Communications", "Optional data"][index]}</strong><small>${["Help improve this app.", "Receive optional news and updates.", "Allow data beyond the essential service."][index]}</small></span><input type="checkbox" data-purpose="${key}" ${privacy?.consent[key] ? "checked" : ""}></label>`).join("")}<button id="export">Export</button></article><article class="card"><h2>Consent history</h2>${
|
|
228
228
|
privacy?.history.length
|
|
229
229
|
? privacy.history
|
|
230
230
|
.slice()
|
|
@@ -235,7 +235,7 @@ function render() {
|
|
|
235
235
|
)
|
|
236
236
|
.join("")
|
|
237
237
|
: "<p>No changes yet.</p>"
|
|
238
|
-
}<hr><h2>Leave this app</h2><p>This removes your app membership and this starter’s notes. Your Fidj account and other memberships remain.</p>${session.roles.includes("Owner") ? "<p>As the app owner, resolve ownership before leaving.</p>" : leaving ? '<div role="alertdialog" aria-labelledby="leave-title"><h3 id="leave-title">Confirm departure</h3><p>Your membership, consent and notes in this app will be removed. Your Fidj account and other apps remain available.</p><button id="confirm-leave" class="danger">
|
|
238
|
+
}<hr><h2>Leave this app</h2><p>This removes your app membership and this starter’s notes. Your Fidj account and other memberships remain.</p>${session.roles.includes("Owner") ? "<p>As the app owner, resolve ownership before leaving.</p>" : leaving ? '<div role="alertdialog" aria-labelledby="leave-title"><h3 id="leave-title">Confirm departure</h3><p>Your membership, consent and notes in this app will be removed. Your Fidj account and other apps remain available.</p><button id="confirm-leave" class="danger">Leave & erase</button><button id="cancel-leave">Keep my membership</button></div>' : '<button id="leave" class="danger">Leave & erase</button>'}<p class="fineprint">Exports here include your Fidj membership and this starter’s notes. The registered app-data handler lets Fidj export and erase these notes too. If cleanup is pending, retry from My privacy on Fidj. Minimal completion receipts are retained; backups and unregistered systems are outside this operation.</p></article></section>`
|
|
239
239
|
}`
|
|
240
240
|
}
|
|
241
241
|
<footer>Built with Fidj · One identity. Separate choices for every app.</footer></main>`;
|
package/lib/scaffold.cjs
CHANGED
|
@@ -230,6 +230,10 @@ function scaffold(destination, options) {
|
|
|
230
230
|
logo: logo ? "./brand/logo" + logo.extension : "./fidj-logo.png",
|
|
231
231
|
favicon: favicon ? "./brand/favicon" + favicon.extension : "./fidj-logo.png",
|
|
232
232
|
moduleEntry: appModule?.entry || "",
|
|
233
|
+
// A mounted module with its own patch (Fidj's console): the badge names
|
|
234
|
+
// it between the SDK and the API.
|
|
235
|
+
moduleVersion: appModule ? options.moduleVersion || "" : "",
|
|
236
|
+
moduleLabel: options.moduleLabel || "module",
|
|
233
237
|
moduleMount: null,
|
|
234
238
|
domain: options.domain,
|
|
235
239
|
};
|