@lystech/core 3.0.120 → 3.0.122
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/bin/check-routes.cjs +141 -0
- package/dist/index.d.ts +10 -0
- package/dist/lystech-core-provider.es.js +4874 -4802
- package/dist/lystech-core-provider.umd.js +148 -148
- package/package.json +4 -2
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/* =====================================================================
|
|
4
|
+
LES ROUTES DE BASE SONT-ELLES BRANCHÉES DANS CETTE APPLICATION ?
|
|
5
|
+
|
|
6
|
+
Le serveur écrit des adresses dans les courriels qu'il envoie — lien
|
|
7
|
+
d'activation d'un compte, lien de réinitialisation de mot de passe.
|
|
8
|
+
Il les construit sur le domaine de l'application CONCERNÉE, pour que
|
|
9
|
+
le client reste chez le commerçant plutôt que d'atterrir sur la
|
|
10
|
+
console d'administration.
|
|
11
|
+
|
|
12
|
+
Rien ne vérifiait que l'application savait les recevoir. Résultat vu
|
|
13
|
+
en production : un client s'inscrit, clique son lien, et tombe sur
|
|
14
|
+
une page ENTIÈREMENT BLANCHE — React Router ne trouve pas de route,
|
|
15
|
+
ne rend rien, ne dit rien. Six applications avaient le trou, et la
|
|
16
|
+
réinitialisation de mot de passe était morte partout sans que
|
|
17
|
+
personne l'ait signalé.
|
|
18
|
+
|
|
19
|
+
Ce script transforme la consigne en vérification. Il lit le code des
|
|
20
|
+
routes et dit ce qui manque.
|
|
21
|
+
|
|
22
|
+
Usage : npx @lystech/core check-routes
|
|
23
|
+
npx @lystech/core check-routes --ci (sort en erreur)
|
|
24
|
+
===================================================================== */
|
|
25
|
+
|
|
26
|
+
const fs = require("fs");
|
|
27
|
+
const path = require("path");
|
|
28
|
+
|
|
29
|
+
const CI = process.argv.includes("--ci");
|
|
30
|
+
|
|
31
|
+
/* Les adresses que le serveur peut écrire dans un courriel, et ce qui
|
|
32
|
+
suffit pour les couvrir. `lystechAuthRoutes()` les couvre toutes. */
|
|
33
|
+
const ATTENDU = [
|
|
34
|
+
{
|
|
35
|
+
nom: "Activation d'un compte",
|
|
36
|
+
/* DEUX FORMES, parce que le serveur en écrit deux. L'app Finance
|
|
37
|
+
reçoit `/activate?token=` sur son propre domaine ; toutes les
|
|
38
|
+
autres reçoivent `/account/activation/:token`. Exiger une seule
|
|
39
|
+
forme signalerait Finance à tort — et un vérificateur qui crie au
|
|
40
|
+
loup finit par ne plus être lu. */
|
|
41
|
+
motifs: [
|
|
42
|
+
/account\/activation\/:token/,
|
|
43
|
+
/lystechAuthRoutes/,
|
|
44
|
+
/path=["'`]\/activate["'`]/,
|
|
45
|
+
],
|
|
46
|
+
pourquoi:
|
|
47
|
+
"un nouveau client clique le lien de son courriel d'inscription",
|
|
48
|
+
},
|
|
49
|
+
{
|
|
50
|
+
nom: "Réinitialisation de mot de passe",
|
|
51
|
+
motifs: [
|
|
52
|
+
/account\/reset-password\/:token/,
|
|
53
|
+
/lystechAuthRoutes/,
|
|
54
|
+
/path=["'`]\/reset["'`]/,
|
|
55
|
+
],
|
|
56
|
+
pourquoi: "un client qui a oublié son mot de passe demande un lien",
|
|
57
|
+
},
|
|
58
|
+
];
|
|
59
|
+
|
|
60
|
+
const REPLI = {
|
|
61
|
+
nom: "Page de repli (route inconnue)",
|
|
62
|
+
motifs: [/path=["'`]\*["'`]/],
|
|
63
|
+
pourquoi:
|
|
64
|
+
"sans elle, une route manquante est une page blanche muette — c'est ce qui a caché le défaut pendant des mois",
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
function fichiersDeRoutes(racine) {
|
|
68
|
+
const dossier = path.join(racine, "src");
|
|
69
|
+
if (!fs.existsSync(dossier)) return [];
|
|
70
|
+
const trouves = [];
|
|
71
|
+
const visiter = (d, profondeur) => {
|
|
72
|
+
if (profondeur > 4) return;
|
|
73
|
+
for (const e of fs.readdirSync(d, { withFileTypes: true })) {
|
|
74
|
+
if (e.name === "node_modules" || e.name.startsWith(".")) continue;
|
|
75
|
+
const p = path.join(d, e.name);
|
|
76
|
+
if (e.isDirectory()) visiter(p, profondeur + 1);
|
|
77
|
+
else if (/\.(tsx|jsx)$/.test(e.name)) {
|
|
78
|
+
const texte = fs.readFileSync(p, "utf8");
|
|
79
|
+
/* On ne garde que les fichiers qui DÉCLARENT des routes : chercher
|
|
80
|
+
partout produirait des faux positifs sur de simples liens. */
|
|
81
|
+
if (texte.includes("<Routes") || texte.includes("<Route ")) {
|
|
82
|
+
trouves.push({ chemin: p, texte });
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
visiter(dossier, 0);
|
|
88
|
+
return trouves;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function main() {
|
|
92
|
+
const racine = process.cwd();
|
|
93
|
+
const nom = (() => {
|
|
94
|
+
try {
|
|
95
|
+
return JSON.parse(
|
|
96
|
+
fs.readFileSync(path.join(racine, "package.json"), "utf8"),
|
|
97
|
+
).name;
|
|
98
|
+
} catch {
|
|
99
|
+
return path.basename(racine);
|
|
100
|
+
}
|
|
101
|
+
})();
|
|
102
|
+
|
|
103
|
+
const fichiers = fichiersDeRoutes(racine);
|
|
104
|
+
if (!fichiers.length) {
|
|
105
|
+
console.log(`\n ${nom} : aucun fichier de routes trouvé — rien à vérifier.\n`);
|
|
106
|
+
return 0;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
const tout = fichiers.map((f) => f.texte).join("\n");
|
|
110
|
+
const manquants = [];
|
|
111
|
+
|
|
112
|
+
console.log(`\n ROUTES DE BASE — ${nom}`);
|
|
113
|
+
console.log(` ${fichiers.length} fichier(s) de routes lu(s)\n`);
|
|
114
|
+
|
|
115
|
+
for (const cible of [...ATTENDU, REPLI]) {
|
|
116
|
+
const ok = cible.motifs.some((m) => m.test(tout));
|
|
117
|
+
console.log(` ${ok ? "OK " : "MANQUE"} ${cible.nom}`);
|
|
118
|
+
if (!ok) {
|
|
119
|
+
console.log(` ${cible.pourquoi}`);
|
|
120
|
+
manquants.push(cible);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
if (!manquants.length) {
|
|
125
|
+
console.log("\n Tout est branché.\n");
|
|
126
|
+
return 0;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
console.log("\n À AJOUTER dans le <Routes> de l'application :\n");
|
|
130
|
+
console.log(' import { lystechAuthRoutes, LystechNotFoundPage } from "@lystech/core";');
|
|
131
|
+
console.log("");
|
|
132
|
+
console.log(" <Routes>");
|
|
133
|
+
console.log(" {lystechAuthRoutes()}");
|
|
134
|
+
console.log(" ... vos routes ...");
|
|
135
|
+
console.log(' <Route path="*" element={<LystechNotFoundPage />} />');
|
|
136
|
+
console.log(" </Routes>\n");
|
|
137
|
+
|
|
138
|
+
return CI ? 1 : 0;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
process.exit(main());
|
package/dist/index.d.ts
CHANGED
|
@@ -511,11 +511,21 @@ export declare function InstallPwaButton({ size, visible, forceVisible, text, kn
|
|
|
511
511
|
*/
|
|
512
512
|
export declare function LoadingCircle(): JSX.Element;
|
|
513
513
|
|
|
514
|
+
/** Les adresses que le serveur peut écrire dans un courriel. */
|
|
515
|
+
export declare const LYSTECH_AUTH_ROUTE_PATHS: readonly ["/account/activation/:token", "/account/reset-password/:token"];
|
|
516
|
+
|
|
514
517
|
export declare const LYSTECH_CORE_VERSION: any;
|
|
515
518
|
|
|
519
|
+
export declare function lystechAuthRoutes(): JSX.Element[];
|
|
520
|
+
|
|
516
521
|
declare function LystechCoreProvider({ children, organization, shouldRedirectAfterLogin, loginRedirectRoute, queryClient, usePushNotifications, useProgressiveWebAppFeatures, useThemeProvider, quickGoogleLoginButtonStyle, enableGoogleQuickLoginButton, showGoogleQuickLoginButton, useGoogleAutoSelect, debugMode, showAskPermissionsButtons, hideSupportButton, supportButtonVariant, onPackageUpdated, triggerOnFirstInstallPackageCallback, packageVersionStorageKey, }: Props): JSX.Element;
|
|
517
522
|
export default LystechCoreProvider;
|
|
518
523
|
|
|
524
|
+
export declare function LystechNotFoundPage({ homePath, homeLabel, }?: {
|
|
525
|
+
homePath?: string;
|
|
526
|
+
homeLabel?: string;
|
|
527
|
+
}): JSX.Element;
|
|
528
|
+
|
|
519
529
|
declare type MessageParams = {
|
|
520
530
|
type: "error" | "success" | "warning";
|
|
521
531
|
message: string;
|