@ofidj/generator-fidj 1.0.6 → 1.0.8
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/generators/app/templates/typescript/server/index.ts +2 -0
- package/generators/app/templates/typescript/src/content.ts +1 -1
- package/generators/app/templates/typescript/src/main.ts +1 -1
- package/generators/app/templates/typescript/src/service-agreement.ts +29 -18
- package/generators/app/templates/typescript/src/version.ts +12 -1
- package/lib/scaffold.cjs +3 -2
- package/package.json +1 -1
|
@@ -11,6 +11,7 @@ export interface Settings {
|
|
|
11
11
|
apiEndpoint: string;
|
|
12
12
|
dashboardUrl: string;
|
|
13
13
|
title: string;
|
|
14
|
+
releaseVersion: string;
|
|
14
15
|
localDemo: boolean;
|
|
15
16
|
}
|
|
16
17
|
class HttpError extends Error {
|
|
@@ -324,6 +325,7 @@ if (require.main === module) {
|
|
|
324
325
|
apiEndpoint,
|
|
325
326
|
dashboardUrl: process.env.FIDJ_DASHBOARD_URL || "https://fidj.ovh",
|
|
326
327
|
title: process.env.APP_TITLE || "My workspace",
|
|
328
|
+
releaseVersion: process.env.APP_VERSION || "",
|
|
327
329
|
localDemo:
|
|
328
330
|
process.env.LOCAL_DEMO === "true" &&
|
|
329
331
|
host === "127.0.0.1" &&
|
|
@@ -7,7 +7,7 @@ import { showVersionBadge } from "./version";
|
|
|
7
7
|
const sdk = new FidjNodeService();
|
|
8
8
|
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;
|
|
9
9
|
const root = document.querySelector<HTMLDivElement>("#app")!;
|
|
10
|
-
showVersionBadge(config.releaseVersion);
|
|
10
|
+
showVersionBadge(config.releaseVersion, config.title === "Fidj" ? config.apiEndpoint : undefined);
|
|
11
11
|
const appPath = `/me/apps/${encodeURIComponent(config.appId)}`;
|
|
12
12
|
let signedIn = false;
|
|
13
13
|
let emailVerified = false;
|
|
@@ -250,7 +250,7 @@ function render() {
|
|
|
250
250
|
async function start() {
|
|
251
251
|
try {
|
|
252
252
|
settings = await (await fetch("/api/config")).json();
|
|
253
|
-
showVersionBadge(settings.releaseVersion);
|
|
253
|
+
showVersionBadge(settings.releaseVersion, settings.title === "Fidj" ? settings.apiEndpoint : undefined);
|
|
254
254
|
await sdk.init(settings.appId, {
|
|
255
255
|
apiEndpoint: settings.apiEndpoint,
|
|
256
256
|
prod: !settings.localDemo,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
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></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>`;
|
|
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
3
|
}
|
|
4
4
|
|
|
5
5
|
export function acceptedAgreement(form: HTMLFormElement) {
|
|
@@ -24,6 +24,7 @@ export async function bindAgreement(form: HTMLFormElement | null, title: string,
|
|
|
24
24
|
const read = form.querySelector<HTMLButtonElement>("#read-agreement")!;
|
|
25
25
|
const dialog = form.querySelector<HTMLDialogElement>("#agreement-dialog")!;
|
|
26
26
|
const status = form.querySelector<HTMLElement>("#agreement-status")!;
|
|
27
|
+
const retry = form.querySelector<HTMLButtonElement>("#retry-agreement")!;
|
|
27
28
|
const submitButtons = form.querySelectorAll<HTMLButtonElement>('button[type="submit"]');
|
|
28
29
|
const update = () => submitButtons.forEach(button => { button.disabled = checkbox.disabled; });
|
|
29
30
|
form.querySelector("#agreement-label")!.textContent = `I accept the service agreement for ${title}.`;
|
|
@@ -31,21 +32,31 @@ export async function bindAgreement(form: HTMLFormElement | null, title: string,
|
|
|
31
32
|
checkbox.addEventListener("change", update);
|
|
32
33
|
read.addEventListener("click", () => dialog.showModal());
|
|
33
34
|
form.querySelector("#close-agreement")!.addEventListener("click", () => dialog.close());
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
35
|
+
const load = async () => {
|
|
36
|
+
retry.hidden = true;
|
|
37
|
+
status.textContent = "Loading service agreement…";
|
|
38
|
+
try {
|
|
39
|
+
const response = await fetch(`${endpoint}/apps/${encodeURIComponent(appId)}`, {signal: AbortSignal.timeout(10000)});
|
|
40
|
+
if (!response.ok) throw new Error(response.status === 404 ? "missing" : "unreachable");
|
|
41
|
+
const agreement = (await response.json()).app?.agreement;
|
|
42
|
+
if (!agreement || typeof agreement.version !== "string" || !agreement.version || typeof agreement.text !== "string" || !agreement.text) throw new Error("missing");
|
|
43
|
+
if (!form.isConnected) return;
|
|
44
|
+
checkbox.dataset.version = agreement.version;
|
|
45
|
+
checkbox.disabled = false;
|
|
46
|
+
checkbox.checked = checked;
|
|
47
|
+
read.disabled = false;
|
|
48
|
+
dialog.querySelector("#agreement-version")!.textContent = `Version ${agreement.version}`;
|
|
49
|
+
dialog.querySelector("#agreement-text")!.textContent = agreement.text;
|
|
50
|
+
status.textContent = "Required to sign in. Optional data choices stay separate.";
|
|
51
|
+
update();
|
|
52
|
+
} catch (error) {
|
|
53
|
+
if (!form.isConnected) return;
|
|
54
|
+
status.textContent = error instanceof Error && error.message === "missing"
|
|
55
|
+
? "This app has no service agreement available."
|
|
56
|
+
: "We cannot reach Fidj right now. Try again.";
|
|
57
|
+
retry.hidden = false;
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
retry.addEventListener("click", load);
|
|
61
|
+
await load();
|
|
51
62
|
}
|
|
@@ -1,8 +1,19 @@
|
|
|
1
|
-
export function showVersionBadge(version: string): void {
|
|
1
|
+
export function showVersionBadge(version: string, apiEndpoint?: string): void {
|
|
2
2
|
if (!/^\d{2}\.\d{2}\.\d{2}$/.test(version || "")) return;
|
|
3
3
|
const badge = document.createElement("div");
|
|
4
4
|
badge.className = "fidj-version";
|
|
5
5
|
badge.setAttribute("aria-label", `App version ${version}`);
|
|
6
6
|
badge.textContent = `v${version}`;
|
|
7
7
|
document.body.append(badge);
|
|
8
|
+
if (apiEndpoint) {
|
|
9
|
+
void fetch(`${apiEndpoint.replace(/\/$/, "")}/status`)
|
|
10
|
+
.then(response => response.ok ? response.json() : null)
|
|
11
|
+
.then(status => {
|
|
12
|
+
const apiVersion = status?.version || status?.built;
|
|
13
|
+
if (!apiVersion) return;
|
|
14
|
+
badge.textContent = `v${version} · API ${apiVersion}`;
|
|
15
|
+
badge.setAttribute("aria-label", `App version ${version}, API version ${apiVersion}`);
|
|
16
|
+
})
|
|
17
|
+
.catch(() => undefined);
|
|
18
|
+
}
|
|
8
19
|
}
|
package/lib/scaffold.cjs
CHANGED
|
@@ -126,7 +126,8 @@ function scaffold(destination, options) {
|
|
|
126
126
|
JSON.stringify(pkg, null, 2) + "\n",
|
|
127
127
|
);
|
|
128
128
|
fs.renameSync(path.join(dir, "gitignore"), path.join(dir, ".gitignore"));
|
|
129
|
-
const
|
|
129
|
+
const releaseVersion = new Date().toISOString().slice(2, 10).replaceAll("-", ".");
|
|
130
|
+
const settings = `FIDJ_APP_ID=${options.appId}\nFIDJ_API_ENDPOINT=${api.href.replace(/\/$/, "")}\nFIDJ_DASHBOARD_URL=https://fidj.ovh\nAPP_TITLE=${title}\nAPP_VERSION=${releaseVersion}\nPORT=8200\nHOST=127.0.0.1\nLOCAL_DEMO=false\nFIDJ_DATA_DIR=../.fidj-data/${name}\nFIDJ_PRIVACY_ADAPTER_KEY=\n`;
|
|
130
131
|
const localApi = options.local
|
|
131
132
|
? "http://localhost:3201/v3"
|
|
132
133
|
: api.href.replace(/\/$/, "");
|
|
@@ -136,7 +137,7 @@ function scaffold(destination, options) {
|
|
|
136
137
|
apiEndpoint: localApi,
|
|
137
138
|
dashboardUrl: options.local ? "http://localhost:4200" : "https://fidj.ovh",
|
|
138
139
|
title,
|
|
139
|
-
releaseVersion
|
|
140
|
+
releaseVersion,
|
|
140
141
|
localDemo: Boolean(options.local),
|
|
141
142
|
allowAnonymous: anonymous === true || anonymous === "true",
|
|
142
143
|
welcome: options.welcome || title,
|