@intranefr/superbackend 1.4.3

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 (188) hide show
  1. package/.commiat +4 -0
  2. package/.env.example +47 -0
  3. package/README.md +110 -0
  4. package/index.js +94 -0
  5. package/package.json +67 -0
  6. package/public/css/styles.css +139 -0
  7. package/public/js/animations.js +41 -0
  8. package/sdk/error-tracking/browser/package.json +16 -0
  9. package/sdk/error-tracking/browser/src/core.js +270 -0
  10. package/sdk/error-tracking/browser/src/embed.js +18 -0
  11. package/sdk/error-tracking/browser/src/index.js +1 -0
  12. package/server.js +5 -0
  13. package/src/admin/endpointRegistry.js +300 -0
  14. package/src/controllers/admin.controller.js +321 -0
  15. package/src/controllers/adminAssets.controller.js +530 -0
  16. package/src/controllers/adminAssetsStorage.controller.js +260 -0
  17. package/src/controllers/adminEjsVirtual.controller.js +354 -0
  18. package/src/controllers/adminFeatureFlags.controller.js +155 -0
  19. package/src/controllers/adminHeadless.controller.js +1071 -0
  20. package/src/controllers/adminI18n.controller.js +604 -0
  21. package/src/controllers/adminJsonConfigs.controller.js +97 -0
  22. package/src/controllers/adminLlm.controller.js +273 -0
  23. package/src/controllers/adminMigration.controller.js +257 -0
  24. package/src/controllers/adminSeoConfig.controller.js +515 -0
  25. package/src/controllers/adminStats.controller.js +121 -0
  26. package/src/controllers/adminUploadNamespaces.controller.js +208 -0
  27. package/src/controllers/assets.controller.js +248 -0
  28. package/src/controllers/auth.controller.js +93 -0
  29. package/src/controllers/billing.controller.js +223 -0
  30. package/src/controllers/featureFlags.controller.js +35 -0
  31. package/src/controllers/forms.controller.js +217 -0
  32. package/src/controllers/globalSettings.controller.js +252 -0
  33. package/src/controllers/headlessCrud.controller.js +126 -0
  34. package/src/controllers/i18n.controller.js +12 -0
  35. package/src/controllers/invite.controller.js +249 -0
  36. package/src/controllers/jsonConfigs.controller.js +19 -0
  37. package/src/controllers/metrics.controller.js +149 -0
  38. package/src/controllers/notificationAdmin.controller.js +264 -0
  39. package/src/controllers/notifications.controller.js +131 -0
  40. package/src/controllers/org.controller.js +357 -0
  41. package/src/controllers/orgAdmin.controller.js +491 -0
  42. package/src/controllers/stripeAdmin.controller.js +410 -0
  43. package/src/controllers/user.controller.js +361 -0
  44. package/src/controllers/userAdmin.controller.js +277 -0
  45. package/src/controllers/waitingList.controller.js +167 -0
  46. package/src/controllers/webhook.controller.js +200 -0
  47. package/src/middleware/auth.js +66 -0
  48. package/src/middleware/errorCapture.js +170 -0
  49. package/src/middleware/headlessApiTokenAuth.js +57 -0
  50. package/src/middleware/org.js +108 -0
  51. package/src/middleware.js +901 -0
  52. package/src/models/ActionEvent.js +31 -0
  53. package/src/models/ActivityLog.js +41 -0
  54. package/src/models/Asset.js +84 -0
  55. package/src/models/AuditEvent.js +93 -0
  56. package/src/models/EmailLog.js +28 -0
  57. package/src/models/ErrorAggregate.js +72 -0
  58. package/src/models/FormSubmission.js +41 -0
  59. package/src/models/GlobalSetting.js +38 -0
  60. package/src/models/HeadlessApiToken.js +24 -0
  61. package/src/models/HeadlessModelDefinition.js +41 -0
  62. package/src/models/I18nEntry.js +77 -0
  63. package/src/models/I18nLocale.js +33 -0
  64. package/src/models/Invite.js +70 -0
  65. package/src/models/JsonConfig.js +46 -0
  66. package/src/models/Notification.js +60 -0
  67. package/src/models/Organization.js +57 -0
  68. package/src/models/OrganizationMember.js +43 -0
  69. package/src/models/StripeCatalogItem.js +77 -0
  70. package/src/models/StripeWebhookEvent.js +57 -0
  71. package/src/models/User.js +89 -0
  72. package/src/models/VirtualEjsFile.js +60 -0
  73. package/src/models/VirtualEjsFileVersion.js +43 -0
  74. package/src/models/VirtualEjsGroupChange.js +32 -0
  75. package/src/models/WaitingList.js +41 -0
  76. package/src/models/Webhook.js +63 -0
  77. package/src/models/Workflow.js +29 -0
  78. package/src/models/WorkflowExecution.js +12 -0
  79. package/src/routes/admin.routes.js +26 -0
  80. package/src/routes/adminAssets.routes.js +28 -0
  81. package/src/routes/adminAssetsStorage.routes.js +13 -0
  82. package/src/routes/adminAudit.routes.js +196 -0
  83. package/src/routes/adminEjsVirtual.routes.js +17 -0
  84. package/src/routes/adminErrors.routes.js +164 -0
  85. package/src/routes/adminFeatureFlags.routes.js +12 -0
  86. package/src/routes/adminHeadless.routes.js +38 -0
  87. package/src/routes/adminI18n.routes.js +22 -0
  88. package/src/routes/adminJsonConfigs.routes.js +15 -0
  89. package/src/routes/adminLlm.routes.js +12 -0
  90. package/src/routes/adminMigration.routes.js +81 -0
  91. package/src/routes/adminSeoConfig.routes.js +20 -0
  92. package/src/routes/adminUploadNamespaces.routes.js +13 -0
  93. package/src/routes/assets.routes.js +21 -0
  94. package/src/routes/auth.routes.js +12 -0
  95. package/src/routes/billing.routes.js +11 -0
  96. package/src/routes/errorTracking.routes.js +31 -0
  97. package/src/routes/featureFlags.routes.js +9 -0
  98. package/src/routes/forms.routes.js +9 -0
  99. package/src/routes/formsAdmin.routes.js +13 -0
  100. package/src/routes/globalSettings.routes.js +18 -0
  101. package/src/routes/headless.routes.js +15 -0
  102. package/src/routes/i18n.routes.js +8 -0
  103. package/src/routes/invite.routes.js +9 -0
  104. package/src/routes/jsonConfigs.routes.js +8 -0
  105. package/src/routes/log.routes.js +111 -0
  106. package/src/routes/metrics.routes.js +9 -0
  107. package/src/routes/notificationAdmin.routes.js +15 -0
  108. package/src/routes/notifications.routes.js +12 -0
  109. package/src/routes/org.routes.js +31 -0
  110. package/src/routes/orgAdmin.routes.js +20 -0
  111. package/src/routes/publicAssets.routes.js +7 -0
  112. package/src/routes/stripeAdmin.routes.js +20 -0
  113. package/src/routes/user.routes.js +22 -0
  114. package/src/routes/userAdmin.routes.js +15 -0
  115. package/src/routes/waitingList.routes.js +13 -0
  116. package/src/routes/waitingListAdmin.routes.js +9 -0
  117. package/src/routes/webhook.routes.js +32 -0
  118. package/src/routes/workflowWebhook.routes.js +54 -0
  119. package/src/routes/workflows.routes.js +110 -0
  120. package/src/services/assets.service.js +110 -0
  121. package/src/services/audit.service.js +62 -0
  122. package/src/services/auditLogger.js +165 -0
  123. package/src/services/ejsVirtual.service.js +614 -0
  124. package/src/services/email.service.js +351 -0
  125. package/src/services/errorLogger.js +221 -0
  126. package/src/services/featureFlags.service.js +202 -0
  127. package/src/services/forms.service.js +214 -0
  128. package/src/services/globalSettings.service.js +49 -0
  129. package/src/services/headlessApiTokens.service.js +158 -0
  130. package/src/services/headlessCrypto.service.js +31 -0
  131. package/src/services/headlessModels.service.js +356 -0
  132. package/src/services/i18n.service.js +314 -0
  133. package/src/services/i18nInferredKeys.service.js +337 -0
  134. package/src/services/jsonConfigs.service.js +392 -0
  135. package/src/services/llm.service.js +749 -0
  136. package/src/services/migration.service.js +581 -0
  137. package/src/services/migrationAssets/fsLocal.js +58 -0
  138. package/src/services/migrationAssets/index.js +134 -0
  139. package/src/services/migrationAssets/s3.js +75 -0
  140. package/src/services/migrationAssets/sftp.js +92 -0
  141. package/src/services/notification.service.js +212 -0
  142. package/src/services/objectStorage.service.js +514 -0
  143. package/src/services/seoConfig.service.js +402 -0
  144. package/src/services/storage.js +150 -0
  145. package/src/services/stripe.service.js +185 -0
  146. package/src/services/stripeHelper.service.js +264 -0
  147. package/src/services/uploadNamespaces.service.js +326 -0
  148. package/src/services/webhook.service.js +157 -0
  149. package/src/services/workflow.service.js +271 -0
  150. package/src/utils/asyncHandler.js +5 -0
  151. package/src/utils/encryption.js +80 -0
  152. package/src/utils/jwt.js +40 -0
  153. package/src/utils/orgRoles.js +156 -0
  154. package/src/utils/validation.js +26 -0
  155. package/src/utils/webhookRetry.js +93 -0
  156. package/views/admin-assets.ejs +444 -0
  157. package/views/admin-audit.ejs +283 -0
  158. package/views/admin-coolify-deploy.ejs +207 -0
  159. package/views/admin-dashboard-home.ejs +291 -0
  160. package/views/admin-dashboard.ejs +397 -0
  161. package/views/admin-ejs-virtual.ejs +280 -0
  162. package/views/admin-errors.ejs +368 -0
  163. package/views/admin-feature-flags.ejs +390 -0
  164. package/views/admin-forms.ejs +526 -0
  165. package/views/admin-global-settings.ejs +436 -0
  166. package/views/admin-headless.ejs +2020 -0
  167. package/views/admin-i18n-locales.ejs +221 -0
  168. package/views/admin-i18n.ejs +728 -0
  169. package/views/admin-json-configs.ejs +410 -0
  170. package/views/admin-llm.ejs +884 -0
  171. package/views/admin-metrics.ejs +274 -0
  172. package/views/admin-migration.ejs +814 -0
  173. package/views/admin-notifications.ejs +430 -0
  174. package/views/admin-organizations.ejs +984 -0
  175. package/views/admin-seo-config.ejs +673 -0
  176. package/views/admin-stripe-pricing.ejs +558 -0
  177. package/views/admin-test.ejs +342 -0
  178. package/views/admin-users.ejs +452 -0
  179. package/views/admin-waiting-list.ejs +547 -0
  180. package/views/admin-webhooks.ejs +329 -0
  181. package/views/admin-workflows.ejs +310 -0
  182. package/views/partials/admin-assets-script.ejs +2022 -0
  183. package/views/partials/admin-test-sidebar.ejs +14 -0
  184. package/views/partials/dashboard/nav-items.ejs +66 -0
  185. package/views/partials/dashboard/palette.ejs +63 -0
  186. package/views/partials/dashboard/sidebar.ejs +21 -0
  187. package/views/partials/dashboard/tab-bar.ejs +26 -0
  188. package/views/partials/footer.ejs +3 -0
@@ -0,0 +1,274 @@
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>Metrics Admin</title>
7
+ <script src="https://cdn.tailwindcss.com"></script>
8
+ <style>
9
+ .toast {
10
+ animation: slideIn 0.3s ease-out;
11
+ }
12
+ @keyframes slideIn {
13
+ from { transform: translateX(100%); opacity: 0; }
14
+ to { transform: translateX(0); opacity: 1; }
15
+ }
16
+ .fade-out {
17
+ animation: fadeOut 0.3s ease-out forwards;
18
+ }
19
+ @keyframes fadeOut {
20
+ from { opacity: 1; }
21
+ to { opacity: 0; }
22
+ }
23
+ </style>
24
+ </head>
25
+ <body class="bg-gray-100">
26
+ <div class="min-h-screen">
27
+ <!-- Header -->
28
+ <div class="bg-white shadow">
29
+ <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-4">
30
+ <div class="flex justify-between items-center">
31
+ <div>
32
+ <h1 class="text-2xl font-bold text-gray-900">Metrics</h1>
33
+ <p class="text-sm text-gray-600 mt-1">Impact KPIs + event tracking tester</p>
34
+ </div>
35
+ <div class="flex items-center gap-4">
36
+ </div>
37
+ </div>
38
+ </div>
39
+ </div>
40
+
41
+ <!-- Main Content -->
42
+ <div class="max-w-7xl mx-auto px-4 sm:px-6 lg:px-8 py-8">
43
+ <!-- KPI Cards -->
44
+ <div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4 mb-6">
45
+ <div class="bg-white rounded-lg shadow p-6">
46
+ <p class="text-sm text-gray-500">Active Users (month)</p>
47
+ <p id="kpi-activeUsers" class="text-3xl font-bold text-gray-900 mt-2">-</p>
48
+ </div>
49
+ <div class="bg-white rounded-lg shadow p-6">
50
+ <p class="text-sm text-gray-500">Services Consulted (month)</p>
51
+ <p id="kpi-services" class="text-3xl font-bold text-gray-900 mt-2">-</p>
52
+ </div>
53
+ <div class="bg-white rounded-lg shadow p-6">
54
+ <p class="text-sm text-gray-500">Newsletter Subscribers</p>
55
+ <p id="kpi-newsletter" class="text-3xl font-bold text-gray-900 mt-2">-</p>
56
+ </div>
57
+ <div class="bg-white rounded-lg shadow p-6">
58
+ <p class="text-sm text-gray-500">Range</p>
59
+ <p id="kpi-range" class="text-sm font-medium text-gray-900 mt-2">-</p>
60
+ </div>
61
+ </div>
62
+
63
+ <div class="flex gap-2 mb-8">
64
+ <button id="btn-refresh-impact" class="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600">Refresh Impact</button>
65
+ </div>
66
+
67
+ <!-- Track tester -->
68
+ <div class="bg-white rounded-lg shadow p-6">
69
+ <div class="flex items-start justify-between gap-4">
70
+ <div>
71
+ <h2 class="text-xl font-bold text-gray-900">Track Event</h2>
72
+ <p class="text-sm text-gray-600 mt-1">POST /api/metrics/track</p>
73
+ </div>
74
+ </div>
75
+
76
+ <form id="track-form" class="mt-6">
77
+ <div class="grid grid-cols-1 lg:grid-cols-2 gap-4">
78
+ <div>
79
+ <label class="block text-sm font-medium text-gray-700 mb-1">Action *</label>
80
+ <input id="track-action" type="text" class="w-full border rounded px-3 py-2" placeholder="e.g., service_view" required>
81
+ <p class="text-xs text-gray-500 mt-1">Tip: Impact uses action="service_view" for servicesConsulted.</p>
82
+ </div>
83
+ <div>
84
+ <label class="block text-sm font-medium text-gray-700 mb-1">JWT (optional)</label>
85
+ <textarea id="track-jwt" class="w-full border rounded px-3 py-2" rows="3" placeholder="Bearer token without 'Bearer ' prefix"></textarea>
86
+ <p class="text-xs text-gray-500 mt-1">If provided, request will include Authorization: Bearer ...</p>
87
+ </div>
88
+ </div>
89
+ <div class="mt-4">
90
+ <label class="block text-sm font-medium text-gray-700 mb-1">Meta (JSON, optional)</label>
91
+ <textarea id="track-meta" class="w-full border rounded px-3 py-2 font-mono text-sm" rows="6">{
92
+ "source": "admin",
93
+ "note": "manual test"
94
+ }</textarea>
95
+ </div>
96
+ <div class="mt-4 flex gap-2">
97
+ <button type="submit" class="bg-green-500 text-white px-4 py-2 rounded hover:bg-green-600">Send Track</button>
98
+ <button type="button" id="btn-track-clear" class="bg-gray-100 text-gray-800 px-4 py-2 rounded hover:bg-gray-200">Clear</button>
99
+ </div>
100
+ </form>
101
+
102
+ <div class="mt-6">
103
+ <h3 class="font-semibold mb-2">Response</h3>
104
+ <pre id="track-response" class="bg-gray-100 p-4 rounded overflow-auto max-h-96"></pre>
105
+ </div>
106
+ </div>
107
+ </div>
108
+ </div>
109
+
110
+ <!-- Toast Container -->
111
+ <div id="toast-container" class="fixed top-4 right-4 space-y-2 z-50"></div>
112
+
113
+ <script>
114
+ const API_BASE = window.location.origin + "<%= baseUrl %>" || window.location.origin;
115
+ const METRICS_IMPACT_PATH = '/api/metrics/impact';
116
+ const METRICS_TRACK_PATH = '/api/metrics/track';
117
+
118
+ function showToast(message, type = 'success') {
119
+ const container = document.getElementById('toast-container');
120
+ const toast = document.createElement('div');
121
+ toast.className = `toast px-6 py-4 rounded-lg shadow-lg text-white ${
122
+ type === 'success' ? 'bg-green-500' : 'bg-red-500'
123
+ }`;
124
+ toast.textContent = message;
125
+ container.appendChild(toast);
126
+
127
+ setTimeout(() => {
128
+ toast.classList.add('fade-out');
129
+ setTimeout(() => toast.remove(), 300);
130
+ }, 3000);
131
+ }
132
+
133
+ async function makeRequest(endpoint, method, body = null, requiresJWT = false) {
134
+ const headers = { 'Content-Type': 'application/json' };
135
+
136
+ if (requiresJWT) {
137
+ const token = document.getElementById('jwt-input')?.value;
138
+ if (!token) {
139
+ showToast('JWT token required', 'error');
140
+ return;
141
+ }
142
+ headers['Authorization'] = `Bearer ${token}`;
143
+ }
144
+
145
+ const options = { method, headers };
146
+ if (body) options.body = JSON.stringify(body);
147
+
148
+ try {
149
+ const response = await fetch(`${API_BASE}${endpoint}`, options);
150
+ const data = await response.json();
151
+
152
+ const responseEl = document.querySelector('#content pre#response');
153
+ if (response.ok) {
154
+ showToast('Request successful!', 'success');
155
+ if (responseEl) responseEl.textContent = JSON.stringify(data, null, 2);
156
+ } else {
157
+ showToast(data.error || 'Request failed', 'error');
158
+ if (responseEl) responseEl.textContent = JSON.stringify(data, null, 2);
159
+ }
160
+ } catch (error) {
161
+ showToast(error.message, 'error');
162
+ const responseEl = document.querySelector('#content pre#response');
163
+ if (responseEl) responseEl.textContent = error.message;
164
+ }
165
+ }
166
+
167
+ function setText(id, value) {
168
+ const el = document.getElementById(id);
169
+ if (!el) return;
170
+ el.textContent = value;
171
+ }
172
+
173
+ async function loadImpact() {
174
+ try {
175
+ const res = await fetch(`${API_BASE}${METRICS_IMPACT_PATH}`, { headers: { 'Accept': 'application/json' } });
176
+ const data = await res.json();
177
+
178
+ if (!res.ok) {
179
+ showToast(data?.error || 'Failed to load impact', 'error');
180
+ return;
181
+ }
182
+
183
+ setText('kpi-activeUsers', String(data?.activeUsers ?? '-'));
184
+ setText('kpi-services', String(data?.servicesConsulted ?? '-'));
185
+ setText('kpi-newsletter', String(data?.newsletterSubscribers ?? '-'));
186
+
187
+ const start = data?.range?.start ? new Date(data.range.start).toLocaleDateString() : '-';
188
+ const end = data?.range?.end ? new Date(data.range.end).toLocaleDateString() : '-';
189
+ setText('kpi-range', `${start} → ${end}`);
190
+ } catch (e) {
191
+ showToast(e.message || 'Failed to load impact', 'error');
192
+ }
193
+ }
194
+
195
+ function bindEvents() {
196
+ const refreshBtn = document.getElementById('btn-refresh-impact');
197
+ if (refreshBtn) refreshBtn.onclick = loadImpact;
198
+
199
+ const clearBtn = document.getElementById('btn-track-clear');
200
+ if (clearBtn) {
201
+ clearBtn.onclick = () => {
202
+ document.getElementById('track-action').value = '';
203
+ document.getElementById('track-jwt').value = '';
204
+ document.getElementById('track-meta').value = '{\n "source": "admin",\n "note": "manual test"\n}';
205
+ const out = document.getElementById('track-response');
206
+ if (out) out.textContent = '';
207
+ };
208
+ }
209
+
210
+ const form = document.getElementById('track-form');
211
+ if (form) {
212
+ form.onsubmit = async (event) => {
213
+ event.preventDefault();
214
+
215
+ const action = document.getElementById('track-action')?.value?.trim();
216
+ const jwt = document.getElementById('track-jwt')?.value?.trim();
217
+ const metaRaw = document.getElementById('track-meta')?.value;
218
+
219
+ if (!action) {
220
+ showToast('Action is required', 'error');
221
+ return;
222
+ }
223
+
224
+ let meta = null;
225
+ if (metaRaw && metaRaw.trim()) {
226
+ try {
227
+ meta = JSON.parse(metaRaw);
228
+ } catch (e) {
229
+ showToast(`Invalid meta JSON: ${e.message}`, 'error');
230
+ return;
231
+ }
232
+ }
233
+
234
+ const headers = { 'Content-Type': 'application/json', 'Accept': 'application/json' };
235
+ if (jwt) headers['Authorization'] = `Bearer ${jwt}`;
236
+
237
+ try {
238
+ const res = await fetch(`${API_BASE}${METRICS_TRACK_PATH}`, {
239
+ method: 'POST',
240
+ headers,
241
+ body: JSON.stringify({ action, meta }),
242
+ });
243
+ const data = await res.json();
244
+
245
+ const out = document.getElementById('track-response');
246
+ if (out) out.textContent = JSON.stringify(data, null, 2);
247
+
248
+ if (!res.ok) {
249
+ showToast(data?.error || 'Track failed', 'error');
250
+ return;
251
+ }
252
+
253
+ showToast('Tracked!', 'success');
254
+ loadImpact();
255
+ } catch (e) {
256
+ showToast(e.message || 'Track failed', 'error');
257
+ }
258
+ };
259
+ }
260
+ }
261
+
262
+ bindEvents();
263
+ loadImpact();
264
+ </script>
265
+ <script>
266
+ window.addEventListener("keydown", (e) => {
267
+ if ((e.ctrlKey || e.metaKey) && e.key === "k") {
268
+ e.preventDefault();
269
+ window.parent.postMessage({ type: "keydown", ctrlK: true }, "*");
270
+ }
271
+ });
272
+ </script>
273
+ </body>
274
+ </html>