@intranefr/superbackend 1.6.6 → 1.7.7

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.
Files changed (51) hide show
  1. package/.env.example +4 -0
  2. package/README.md +18 -0
  3. package/package.json +8 -2
  4. package/public/js/admin-superdemos.js +396 -0
  5. package/public/sdk/superdemos.iife.js +614 -0
  6. package/public/superdemos-qa.html +324 -0
  7. package/sdk/superdemos/browser/src/index.js +719 -0
  8. package/src/cli/agent-chat.js +369 -0
  9. package/src/cli/agent-list.js +42 -0
  10. package/src/controllers/adminAgentsChat.controller.js +172 -0
  11. package/src/controllers/adminSuperDemos.controller.js +382 -0
  12. package/src/controllers/superDemosPublic.controller.js +126 -0
  13. package/src/middleware.js +102 -19
  14. package/src/models/BlogAutomationLock.js +4 -4
  15. package/src/models/BlogPost.js +16 -16
  16. package/src/models/CacheEntry.js +17 -6
  17. package/src/models/JsonConfig.js +2 -4
  18. package/src/models/RateLimitMetricBucket.js +10 -5
  19. package/src/models/SuperDemo.js +38 -0
  20. package/src/models/SuperDemoProject.js +32 -0
  21. package/src/models/SuperDemoStep.js +27 -0
  22. package/src/routes/adminAgents.routes.js +10 -0
  23. package/src/routes/adminMarkdowns.routes.js +3 -0
  24. package/src/routes/adminSuperDemos.routes.js +31 -0
  25. package/src/routes/superDemos.routes.js +9 -0
  26. package/src/services/auditLogger.js +75 -37
  27. package/src/services/email.service.js +18 -3
  28. package/src/services/superDemosAuthoringSessions.service.js +132 -0
  29. package/src/services/superDemosWs.service.js +164 -0
  30. package/src/services/terminalsWs.service.js +35 -3
  31. package/src/utils/rbac/rightsRegistry.js +2 -0
  32. package/views/admin-agents.ejs +261 -11
  33. package/views/admin-dashboard.ejs +78 -8
  34. package/views/admin-superdemos.ejs +335 -0
  35. package/views/admin-terminals.ejs +462 -34
  36. package/views/partials/admin/agents-chat.ejs +80 -0
  37. package/views/partials/dashboard/nav-items.ejs +1 -0
  38. package/views/partials/dashboard/tab-bar.ejs +6 -0
  39. package/cookies.txt +0 -6
  40. package/cookies1.txt +0 -6
  41. package/cookies2.txt +0 -6
  42. package/cookies3.txt +0 -6
  43. package/cookies4.txt +0 -5
  44. package/cookies_old.txt +0 -5
  45. package/cookies_old_test.txt +0 -6
  46. package/cookies_super.txt +0 -5
  47. package/cookies_super_test.txt +0 -6
  48. package/cookies_test.txt +0 -6
  49. package/test-access.js +0 -63
  50. package/test-iframe-fix.html +0 -63
  51. package/test-iframe.html +0 -14
@@ -0,0 +1,324 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8" />
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>SuperDemos QA Playground</title>
7
+ <style>
8
+ body {
9
+ font-family:
10
+ Inter,
11
+ system-ui,
12
+ -apple-system,
13
+ Segoe UI,
14
+ Roboto,
15
+ sans-serif;
16
+ margin: 0;
17
+ background: #f6f7fb;
18
+ color: #111827;
19
+ }
20
+ .wrap {
21
+ max-width: 1100px;
22
+ margin: 0 auto;
23
+ padding: 20px;
24
+ }
25
+ .card {
26
+ background: #fff;
27
+ border: 1px solid #e5e7eb;
28
+ border-radius: 12px;
29
+ padding: 14px;
30
+ margin-bottom: 14px;
31
+ }
32
+ .row {
33
+ display: grid;
34
+ grid-template-columns: 1fr 1fr;
35
+ gap: 10px;
36
+ }
37
+ label {
38
+ font-size: 12px;
39
+ color: #374151;
40
+ display: block;
41
+ margin-bottom: 4px;
42
+ }
43
+ input,
44
+ textarea,
45
+ select {
46
+ width: 100%;
47
+ box-sizing: border-box;
48
+ border: 1px solid #d1d5db;
49
+ border-radius: 8px;
50
+ padding: 8px 10px;
51
+ font-size: 13px;
52
+ }
53
+ button {
54
+ border: 0;
55
+ border-radius: 8px;
56
+ padding: 9px 12px;
57
+ font-size: 13px;
58
+ cursor: pointer;
59
+ }
60
+ .btn {
61
+ background: #111827;
62
+ color: #fff;
63
+ }
64
+ .btn.secondary {
65
+ background: #e5e7eb;
66
+ color: #111827;
67
+ }
68
+ .note {
69
+ font-size: 12px;
70
+ color: #4b5563;
71
+ }
72
+ .stage {
73
+ display: grid;
74
+ grid-template-columns: 260px 1fr;
75
+ gap: 12px;
76
+ margin-top: 8px;
77
+ }
78
+ .sidebar {
79
+ background: #f9fafb;
80
+ border: 1px solid #e5e7eb;
81
+ border-radius: 10px;
82
+ padding: 10px;
83
+ }
84
+ .panel {
85
+ min-height: 460px;
86
+ background: #fff;
87
+ border: 1px solid #e5e7eb;
88
+ border-radius: 10px;
89
+ padding: 14px;
90
+ }
91
+ .fake-card {
92
+ border: 1px solid #e5e7eb;
93
+ border-radius: 10px;
94
+ padding: 12px;
95
+ margin-bottom: 10px;
96
+ }
97
+ .muted {
98
+ color: #6b7280;
99
+ font-size: 12px;
100
+ }
101
+ #log {
102
+ height: 180px;
103
+ overflow: auto;
104
+ background: #0b1220;
105
+ color: #d1e7ff;
106
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
107
+ font-size: 12px;
108
+ border-radius: 10px;
109
+ padding: 10px;
110
+ }
111
+ @media (max-width: 900px) {
112
+ .row,
113
+ .stage {
114
+ grid-template-columns: 1fr;
115
+ }
116
+ }
117
+ </style>
118
+ </head>
119
+ <body>
120
+ <div class="wrap">
121
+ <div class="card">
122
+ <h2 style="margin: 0 0 8px 0">SuperDemos QA Playground</h2>
123
+ <div class="note">
124
+ Use this page as target URL from Admin SuperDemos authoring. It also
125
+ supports live-mode playback with manual config below.
126
+ </div>
127
+ </div>
128
+
129
+ <div class="card">
130
+ <div class="row">
131
+ <div>
132
+ <label>API URL</label>
133
+ <input id="apiUrl" />
134
+ </div>
135
+ <div>
136
+ <label>Project ID</label>
137
+ <input id="projectId" placeholder="sdp_..." />
138
+ </div>
139
+ </div>
140
+ <div style="margin-top: 10px">
141
+ <label style="display: flex; align-items: center; gap: 8px; margin-bottom: 0">
142
+ <input id="force" type="checkbox" style="width: auto" />
143
+ <span>Force replay even if already seen</span>
144
+ </label>
145
+ </div>
146
+ <div class="row" style="margin-top: 10px">
147
+ <div>
148
+ <label>Project API key (private projects only)</label>
149
+ <input id="apiKey" placeholder="optional" />
150
+ </div>
151
+ <div>
152
+ <label>Mode</label>
153
+ <select id="mode">
154
+ <option value="live">live</option>
155
+ <option value="author">
156
+ author (usually auto via query params)
157
+ </option>
158
+ </select>
159
+ </div>
160
+ </div>
161
+ <div
162
+ style="display: flex; gap: 10px; margin-top: 10px; flex-wrap: wrap"
163
+ >
164
+ <button class="btn" id="btnInit">Init SuperDemos</button>
165
+ <button class="btn secondary" id="btnSave">Save config</button>
166
+ <button class="btn secondary" id="btnResetSeen">
167
+ Reset seen flags
168
+ </button>
169
+ </div>
170
+ <div class="note" style="margin-top: 8px">
171
+ Author mode is automatically enabled when URL includes
172
+ <code>sd_session</code> and <code>sd_token</code>.
173
+ </div>
174
+ </div>
175
+
176
+ <div class="card">
177
+ <div class="stage">
178
+ <aside class="sidebar">
179
+ <div class="muted">Navigation</div>
180
+ <button
181
+ id="menu-home"
182
+ class="btn secondary"
183
+ style="width: 100%; margin-top: 8px"
184
+ >
185
+ Home
186
+ </button>
187
+ <button
188
+ id="menu-billing"
189
+ class="btn secondary"
190
+ style="width: 100%; margin-top: 8px"
191
+ >
192
+ Billing
193
+ </button>
194
+ <button
195
+ id="menu-settings"
196
+ class="btn secondary"
197
+ style="width: 100%; margin-top: 8px"
198
+ >
199
+ Settings
200
+ </button>
201
+ </aside>
202
+ <main class="panel">
203
+ <h3 id="hero-title" style="margin-top: 0">Welcome to QA Product</h3>
204
+ <p id="hero-subtitle" class="muted">
205
+ This fake app contains stable selectors for SuperDemos authoring
206
+ and live playback.
207
+ </p>
208
+ <div class="fake-card" data-testid="plan-card">
209
+ <strong id="plan-name">Pro Plan</strong>
210
+ <p class="muted">
211
+ Includes unlimited projects and priority support.
212
+ </p>
213
+ <button id="upgrade-btn" class="btn">Upgrade now</button>
214
+ </div>
215
+ <div class="fake-card" data-testid="invoice-card">
216
+ <strong>Invoice #A-1024</strong>
217
+ <p class="muted">Amount due: $149</p>
218
+ <button id="pay-now-btn" class="btn secondary">Pay now</button>
219
+ </div>
220
+ <label for="coupon-input">Coupon</label>
221
+ <input id="coupon-input" placeholder="SPRING20" />
222
+ <div style="margin-top: 10px">
223
+ <button id="apply-coupon-btn" class="btn secondary">
224
+ Apply coupon
225
+ </button>
226
+ </div>
227
+ </main>
228
+ </div>
229
+ </div>
230
+
231
+ <div class="card">
232
+ <h3 style="margin-top: 0">Runtime log</h3>
233
+ <pre id="log"></pre>
234
+ </div>
235
+ </div>
236
+
237
+ <script src="/public/sdk/superdemos.iife.js"></script>
238
+ <script>
239
+ (function () {
240
+ const logEl = document.getElementById("log");
241
+ const append = (msg) => {
242
+ const line = "[" + new Date().toISOString() + "] " + msg;
243
+ logEl.textContent += line + "\n";
244
+ logEl.scrollTop = logEl.scrollHeight;
245
+ };
246
+
247
+ const defaultApiUrl = window.location.origin;
248
+ const keys = {
249
+ apiUrl: "superdemos.qa.apiUrl",
250
+ projectId: "superdemos.qa.projectId",
251
+ apiKey: "superdemos.qa.apiKey",
252
+ mode: "superdemos.qa.mode",
253
+ force: "superdemos.qa.force",
254
+ };
255
+
256
+ const apiUrlEl = document.getElementById("apiUrl");
257
+ const projectIdEl = document.getElementById("projectId");
258
+ const apiKeyEl = document.getElementById("apiKey");
259
+ const modeEl = document.getElementById("mode");
260
+ const forceEl = document.getElementById("force");
261
+
262
+ apiUrlEl.value = localStorage.getItem(keys.apiUrl) || defaultApiUrl;
263
+ projectIdEl.value = localStorage.getItem(keys.projectId) || "";
264
+ apiKeyEl.value = localStorage.getItem(keys.apiKey) || "";
265
+ modeEl.value = localStorage.getItem(keys.mode) || "live";
266
+ forceEl.checked = localStorage.getItem(keys.force) === "1";
267
+
268
+ document.getElementById("btnSave").addEventListener("click", () => {
269
+ localStorage.setItem(keys.apiUrl, apiUrlEl.value || defaultApiUrl);
270
+ localStorage.setItem(keys.projectId, projectIdEl.value || "");
271
+ localStorage.setItem(keys.apiKey, apiKeyEl.value || "");
272
+ localStorage.setItem(keys.mode, modeEl.value || "live");
273
+ localStorage.setItem(keys.force, forceEl.checked ? "1" : "0");
274
+ append("Saved config.");
275
+ });
276
+
277
+ document
278
+ .getElementById("btnResetSeen")
279
+ .addEventListener("click", () => {
280
+ const toDelete = [];
281
+ for (let i = 0; i < localStorage.length; i++) {
282
+ const k = localStorage.key(i);
283
+ if (k && k.startsWith("superdemos.seen.")) toDelete.push(k);
284
+ }
285
+ toDelete.forEach((k) => localStorage.removeItem(k));
286
+ append("Cleared seen keys: " + toDelete.length);
287
+ });
288
+
289
+ document
290
+ .getElementById("btnInit")
291
+ .addEventListener("click", async () => {
292
+ try {
293
+ append("Init requested...");
294
+ const result = await window.superDemos.init({
295
+ apiUrl: apiUrlEl.value || defaultApiUrl,
296
+ projectId: projectIdEl.value,
297
+ apiKey: apiKeyEl.value || null,
298
+ mode: modeEl.value || "live",
299
+ force: forceEl.checked,
300
+ });
301
+ append("Init result: " + JSON.stringify(result));
302
+ } catch (e) {
303
+ append("Init error: " + (e && e.message ? e.message : String(e)));
304
+ }
305
+ });
306
+
307
+ // some interactions to make QA page feel like an app
308
+ const clickLog = (id, text) => {
309
+ const el = document.getElementById(id);
310
+ if (!el) return;
311
+ el.addEventListener("click", () => append(text));
312
+ };
313
+ clickLog("upgrade-btn", "Clicked upgrade");
314
+ clickLog("pay-now-btn", "Clicked pay now");
315
+ clickLog("apply-coupon-btn", "Clicked apply coupon");
316
+ clickLog("menu-home", "Navigated Home");
317
+ clickLog("menu-billing", "Navigated Billing");
318
+ clickLog("menu-settings", "Navigated Settings");
319
+
320
+ append("QA page loaded.");
321
+ })();
322
+ </script>
323
+ </body>
324
+ </html>