discovery-media-player 0.1.173 → 0.1.174
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/context/standalone.js +34 -2
- package/docs/HOST-CONTRACT.md +6 -0
- package/package.json +1 -1
package/context/standalone.js
CHANGED
|
@@ -118,6 +118,22 @@ function fetchBorne(cible, options = {}, delaiMs) {
|
|
|
118
118
|
*/
|
|
119
119
|
const DELAI_AUTH_MS = 5000;
|
|
120
120
|
const DELAI_ROUTE_HOTE_MS = 4000;
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* La marque d'un client, GARDÉE EN MÉMOIRE (#570). Chaque ouverture d'un lien tracé attendait un
|
|
124
|
+
* POST à l'hôte avant d'envoyer la page ; hôte lent ou en panne, chaque ouverture payait jusqu'à
|
|
125
|
+
* `DELAI_ROUTE_HOTE_MS`. Une marque change rarement, un lien s'ouvre souvent.
|
|
126
|
+
*
|
|
127
|
+
* ⚠️ LES DURÉES DISENT CE QUI RESTE VRAI DE `brands.js` : la marque est toujours résolue par
|
|
128
|
+
* l'hôte, jamais recopiée dans le lien — une charte corrigée se voit en 5 minutes au plus. Une
|
|
129
|
+
* absence (clé inconnue, hôte en panne) n'est gardée qu'une minute : assez pour ne plus payer le
|
|
130
|
+
* délai à chaque ouverture, assez peu pour qu'une marque créée entre-temps apparaisse vite.
|
|
131
|
+
* ⚠️ BORNÉE : les clés viennent des liens, donc de la base ; sans plafond, une instance qui sert
|
|
132
|
+
* beaucoup de clients garderait tout pour toujours. La plus ancienne entrée sort la première.
|
|
133
|
+
*/
|
|
134
|
+
const MARQUE_GARDEE_MS = 5 * 60_000;
|
|
135
|
+
const MARQUE_ABSENTE_MS = 60_000;
|
|
136
|
+
const MARQUES_MAX = 500;
|
|
121
137
|
const DELAI_STOCKAGE_MS = 15000;
|
|
122
138
|
const DELAI_BASE_MS = 15000;
|
|
123
139
|
|
|
@@ -431,6 +447,8 @@ function createStandaloneContext(env = process.env) {
|
|
|
431
447
|
const origins = () => storage.storageOrigins(env);
|
|
432
448
|
const hostBase = () => storage.hostFetchBase(env);
|
|
433
449
|
const root = () => storage.localRoot(env);
|
|
450
|
+
// Les marques des clients, propres à CE contexte (#570) : deux contextes ne partagent rien.
|
|
451
|
+
const marques = new Map();
|
|
434
452
|
|
|
435
453
|
return {
|
|
436
454
|
// Aucun greffon : l'assistant IA, l'intro de marque et les comptes visiteurs sont des produits
|
|
@@ -794,8 +812,22 @@ function createStandaloneContext(env = process.env) {
|
|
|
794
812
|
*/
|
|
795
813
|
async forKey(key) {
|
|
796
814
|
if (!key) return null;
|
|
797
|
-
const
|
|
798
|
-
|
|
815
|
+
const cle = String(key);
|
|
816
|
+
const gardee = marques.get(cle);
|
|
817
|
+
// Une promesse, pas une valeur : dix lecteurs qui ouvrent le même lien au même instant
|
|
818
|
+
// attendent le MÊME appel au lieu d'en lancer dix.
|
|
819
|
+
if (gardee && Date.now() - gardee.depuis < gardee.duree) return gardee.marque;
|
|
820
|
+
const entree = { depuis: Date.now(), duree: MARQUE_GARDEE_MS, marque: null };
|
|
821
|
+
entree.marque = appelHote(env.PLAYER_HOST_BRAND_URL, secret, { key: cle }, journal).then((b) => {
|
|
822
|
+
const m = b && b.logo ? { logo: String(b.logo), name: String(b.name || ""), dark: !!b.dark } : null;
|
|
823
|
+
if (!m) entree.duree = MARQUE_ABSENTE_MS;
|
|
824
|
+
return m;
|
|
825
|
+
});
|
|
826
|
+
// Réinsérée en dernier : l'ordre d'insertion de la Map est l'ordre de sortie.
|
|
827
|
+
marques.delete(cle);
|
|
828
|
+
marques.set(cle, entree);
|
|
829
|
+
if (marques.size > MARQUES_MAX) marques.delete(marques.keys().next().value);
|
|
830
|
+
return entree.marque;
|
|
799
831
|
},
|
|
800
832
|
|
|
801
833
|
title(base, qualificatif) {
|
package/docs/HOST-CONTRACT.md
CHANGED
|
@@ -842,6 +842,12 @@ The link carries a **reference**, never a copy of the logo: a tracked link lives
|
|
|
842
842
|
inbox, and a logo frozen at send time would not follow a corrected brand. `name` is not decorative
|
|
843
843
|
— it is what shows when the logo fails to load.
|
|
844
844
|
|
|
845
|
+
The standalone context **keeps each answer in memory, per process**, so that opening a link does not
|
|
846
|
+
wait on your route every time: a brand for **5 minutes**, an absence (unknown key, error, timeout)
|
|
847
|
+
for **one minute**, at most 500 keys, oldest out first. Concurrent openings of the same link share
|
|
848
|
+
one call. So a corrected brand shows within 5 minutes, and a brand created for a key that was
|
|
849
|
+
unknown shows within a minute. The link still carries only the key — nothing is frozen in it.
|
|
850
|
+
|
|
845
851
|
### 3. Serving a file the player cannot reach
|
|
846
852
|
|
|
847
853
|
If your documents sit behind an API key, the player must **never** hold it. Expose one route
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "discovery-media-player",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.174",
|
|
4
4
|
"description": "Self-hosted document viewer: per-recipient tracked links, reading analytics, live presentation. The core knows nothing about the application hosting it — everything it borrows arrives through an injected context.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pdf-viewer",
|