@intranefr/superbackend 1.5.1 → 1.5.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.
- package/.env.example +10 -0
- package/index.js +2 -0
- package/manage.js +745 -0
- package/package.json +5 -2
- package/src/controllers/admin.controller.js +79 -6
- package/src/controllers/adminAgents.controller.js +37 -0
- package/src/controllers/adminExperiments.controller.js +200 -0
- package/src/controllers/adminLlm.controller.js +19 -0
- package/src/controllers/adminMarkdowns.controller.js +157 -0
- package/src/controllers/adminScripts.controller.js +243 -74
- package/src/controllers/adminTelegram.controller.js +72 -0
- package/src/controllers/experiments.controller.js +85 -0
- package/src/controllers/internalExperiments.controller.js +17 -0
- package/src/controllers/markdowns.controller.js +42 -0
- package/src/helpers/mongooseHelper.js +258 -0
- package/src/helpers/scriptBase.js +230 -0
- package/src/helpers/scriptRunner.js +335 -0
- package/src/middleware.js +195 -34
- package/src/models/Agent.js +105 -0
- package/src/models/AgentMessage.js +82 -0
- package/src/models/CacheEntry.js +1 -1
- package/src/models/ConsoleLog.js +1 -1
- package/src/models/Experiment.js +75 -0
- package/src/models/ExperimentAssignment.js +23 -0
- package/src/models/ExperimentEvent.js +26 -0
- package/src/models/ExperimentMetricBucket.js +30 -0
- package/src/models/GlobalSetting.js +1 -2
- package/src/models/Markdown.js +75 -0
- package/src/models/RateLimitCounter.js +1 -1
- package/src/models/ScriptDefinition.js +1 -0
- package/src/models/ScriptRun.js +8 -0
- package/src/models/TelegramBot.js +42 -0
- package/src/models/Webhook.js +2 -0
- package/src/routes/admin.routes.js +2 -0
- package/src/routes/adminAgents.routes.js +13 -0
- package/src/routes/adminConsoleManager.routes.js +1 -1
- package/src/routes/adminExperiments.routes.js +29 -0
- package/src/routes/adminLlm.routes.js +1 -0
- package/src/routes/adminMarkdowns.routes.js +16 -0
- package/src/routes/adminScripts.routes.js +4 -1
- package/src/routes/adminTelegram.routes.js +14 -0
- package/src/routes/blogInternal.routes.js +2 -2
- package/src/routes/experiments.routes.js +30 -0
- package/src/routes/internalExperiments.routes.js +15 -0
- package/src/routes/markdowns.routes.js +16 -0
- package/src/services/agent.service.js +546 -0
- package/src/services/agentHistory.service.js +345 -0
- package/src/services/agentTools.service.js +578 -0
- package/src/services/blogCronsBootstrap.service.js +7 -6
- package/src/services/consoleManager.service.js +56 -18
- package/src/services/consoleOverride.service.js +1 -0
- package/src/services/experiments.service.js +273 -0
- package/src/services/experimentsAggregation.service.js +308 -0
- package/src/services/experimentsCronsBootstrap.service.js +118 -0
- package/src/services/experimentsRetention.service.js +43 -0
- package/src/services/experimentsWs.service.js +134 -0
- package/src/services/globalSettings.service.js +15 -0
- package/src/services/jsonConfigs.service.js +24 -12
- package/src/services/llm.service.js +219 -6
- package/src/services/markdowns.service.js +522 -0
- package/src/services/scriptsRunner.service.js +514 -23
- package/src/services/telegram.service.js +130 -0
- package/src/utils/rbac/rightsRegistry.js +4 -0
- package/views/admin-agents.ejs +273 -0
- package/views/admin-coolify-deploy.ejs +8 -8
- package/views/admin-dashboard.ejs +63 -12
- package/views/admin-experiments.ejs +91 -0
- package/views/admin-markdowns.ejs +905 -0
- package/views/admin-scripts.ejs +817 -6
- package/views/admin-telegram.ejs +269 -0
- package/views/partials/dashboard/nav-items.ejs +4 -0
- package/views/partials/dashboard/palette.ejs +5 -3
- package/src/middleware/internalCronAuth.js +0 -29
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const mongoose = require('mongoose');
|
|
2
|
+
|
|
3
|
+
const experimentAssignmentSchema = new mongoose.Schema(
|
|
4
|
+
{
|
|
5
|
+
experimentId: { type: mongoose.Schema.Types.ObjectId, ref: 'Experiment', required: true, index: true },
|
|
6
|
+
organizationId: { type: mongoose.Schema.Types.ObjectId, ref: 'Organization', default: null, index: true },
|
|
7
|
+
|
|
8
|
+
subjectKey: { type: String, required: true },
|
|
9
|
+
|
|
10
|
+
variantKey: { type: String, required: true },
|
|
11
|
+
assignedAt: { type: Date, default: () => new Date() },
|
|
12
|
+
|
|
13
|
+
context: { type: mongoose.Schema.Types.Mixed, default: {} },
|
|
14
|
+
},
|
|
15
|
+
{ timestamps: true, collection: 'experiment_assignments' },
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
experimentAssignmentSchema.index({ experimentId: 1, subjectKey: 1 }, { unique: true });
|
|
19
|
+
experimentAssignmentSchema.index({ organizationId: 1, subjectKey: 1 });
|
|
20
|
+
|
|
21
|
+
module.exports =
|
|
22
|
+
mongoose.models.ExperimentAssignment ||
|
|
23
|
+
mongoose.model('ExperimentAssignment', experimentAssignmentSchema);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
const mongoose = require('mongoose');
|
|
2
|
+
|
|
3
|
+
const experimentEventSchema = new mongoose.Schema(
|
|
4
|
+
{
|
|
5
|
+
experimentId: { type: mongoose.Schema.Types.ObjectId, ref: 'Experiment', required: true, index: true },
|
|
6
|
+
organizationId: { type: mongoose.Schema.Types.ObjectId, ref: 'Organization', default: null, index: true },
|
|
7
|
+
|
|
8
|
+
subjectKey: { type: String, required: true },
|
|
9
|
+
|
|
10
|
+
variantKey: { type: String, required: true, index: true },
|
|
11
|
+
|
|
12
|
+
eventKey: { type: String, required: true, index: true },
|
|
13
|
+
value: { type: Number, default: 1 },
|
|
14
|
+
|
|
15
|
+
ts: { type: Date, required: true, index: true },
|
|
16
|
+
|
|
17
|
+
meta: { type: mongoose.Schema.Types.Mixed, default: {} },
|
|
18
|
+
},
|
|
19
|
+
{ timestamps: true, collection: 'experiment_events' },
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
experimentEventSchema.index({ experimentId: 1, ts: 1 });
|
|
23
|
+
experimentEventSchema.index({ organizationId: 1, ts: 1 });
|
|
24
|
+
experimentEventSchema.index({ experimentId: 1, eventKey: 1, ts: 1 });
|
|
25
|
+
|
|
26
|
+
module.exports = mongoose.models.ExperimentEvent || mongoose.model('ExperimentEvent', experimentEventSchema);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const mongoose = require('mongoose');
|
|
2
|
+
|
|
3
|
+
const experimentMetricBucketSchema = new mongoose.Schema(
|
|
4
|
+
{
|
|
5
|
+
experimentId: { type: mongoose.Schema.Types.ObjectId, ref: 'Experiment', required: true, index: true },
|
|
6
|
+
organizationId: { type: mongoose.Schema.Types.ObjectId, ref: 'Organization', default: null, index: true },
|
|
7
|
+
|
|
8
|
+
variantKey: { type: String, required: true, index: true },
|
|
9
|
+
metricKey: { type: String, required: true, index: true },
|
|
10
|
+
|
|
11
|
+
bucketStart: { type: Date, required: true, index: true },
|
|
12
|
+
bucketMs: { type: Number, required: true },
|
|
13
|
+
|
|
14
|
+
count: { type: Number, default: 0 },
|
|
15
|
+
sum: { type: Number, default: 0 },
|
|
16
|
+
sumSq: { type: Number, default: 0 },
|
|
17
|
+
min: { type: Number, default: null },
|
|
18
|
+
max: { type: Number, default: null },
|
|
19
|
+
},
|
|
20
|
+
{ timestamps: true, collection: 'experiment_metric_buckets' },
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
experimentMetricBucketSchema.index(
|
|
24
|
+
{ experimentId: 1, variantKey: 1, metricKey: 1, bucketStart: 1, bucketMs: 1 },
|
|
25
|
+
{ unique: true },
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
module.exports =
|
|
29
|
+
mongoose.models.ExperimentMetricBucket ||
|
|
30
|
+
mongoose.model('ExperimentMetricBucket', experimentMetricBucketSchema);
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
const mongoose = require('mongoose');
|
|
2
|
+
|
|
3
|
+
const markdownSchema = new mongoose.Schema(
|
|
4
|
+
{
|
|
5
|
+
title: {
|
|
6
|
+
type: String,
|
|
7
|
+
required: true,
|
|
8
|
+
trim: true,
|
|
9
|
+
},
|
|
10
|
+
slug: {
|
|
11
|
+
type: String,
|
|
12
|
+
required: true,
|
|
13
|
+
index: true,
|
|
14
|
+
trim: true,
|
|
15
|
+
},
|
|
16
|
+
category: {
|
|
17
|
+
type: String,
|
|
18
|
+
required: true,
|
|
19
|
+
index: true,
|
|
20
|
+
trim: true,
|
|
21
|
+
default: 'general',
|
|
22
|
+
},
|
|
23
|
+
group_code: {
|
|
24
|
+
type: String,
|
|
25
|
+
required: false,
|
|
26
|
+
index: true,
|
|
27
|
+
trim: true,
|
|
28
|
+
default: '',
|
|
29
|
+
},
|
|
30
|
+
markdownRaw: {
|
|
31
|
+
type: String,
|
|
32
|
+
required: true,
|
|
33
|
+
default: '',
|
|
34
|
+
},
|
|
35
|
+
publicEnabled: {
|
|
36
|
+
type: Boolean,
|
|
37
|
+
default: false,
|
|
38
|
+
index: true,
|
|
39
|
+
},
|
|
40
|
+
cacheTtlSeconds: {
|
|
41
|
+
type: Number,
|
|
42
|
+
default: 0,
|
|
43
|
+
},
|
|
44
|
+
status: {
|
|
45
|
+
type: String,
|
|
46
|
+
enum: ['draft', 'published', 'archived'],
|
|
47
|
+
default: 'draft',
|
|
48
|
+
index: true,
|
|
49
|
+
},
|
|
50
|
+
ownerUserId: {
|
|
51
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
52
|
+
ref: 'User',
|
|
53
|
+
index: true,
|
|
54
|
+
default: null,
|
|
55
|
+
},
|
|
56
|
+
orgId: {
|
|
57
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
58
|
+
ref: 'Organization',
|
|
59
|
+
index: true,
|
|
60
|
+
default: null,
|
|
61
|
+
},
|
|
62
|
+
},
|
|
63
|
+
{ timestamps: true },
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
// Compound unique index for fast lookups
|
|
67
|
+
markdownSchema.index({ category: 1, group_code: 1, slug: 1 }, { unique: true });
|
|
68
|
+
|
|
69
|
+
// Additional indexes for common queries
|
|
70
|
+
markdownSchema.index({ status: 1, publicEnabled: 1 });
|
|
71
|
+
markdownSchema.index({ category: 1, status: 1 });
|
|
72
|
+
markdownSchema.index({ ownerUserId: 1, createdAt: -1 });
|
|
73
|
+
markdownSchema.index({ orgId: 1, createdAt: -1 });
|
|
74
|
+
|
|
75
|
+
module.exports = mongoose.model('Markdown', markdownSchema);
|
|
@@ -8,7 +8,7 @@ const rateLimitCounterSchema = new mongoose.Schema(
|
|
|
8
8
|
|
|
9
9
|
count: { type: Number, default: 0 },
|
|
10
10
|
|
|
11
|
-
expiresAt: { type: Date, default: null
|
|
11
|
+
expiresAt: { type: Date, default: null },
|
|
12
12
|
},
|
|
13
13
|
{ timestamps: true, collection: 'rate_limit_counters' },
|
|
14
14
|
);
|
|
@@ -16,6 +16,7 @@ const scriptDefinitionSchema = new mongoose.Schema(
|
|
|
16
16
|
type: { type: String, enum: ['bash', 'node', 'browser'], required: true },
|
|
17
17
|
runner: { type: String, enum: ['host', 'vm2', 'browser'], required: true },
|
|
18
18
|
script: { type: String, required: true },
|
|
19
|
+
scriptFormat: { type: String, enum: ['string', 'base64'], default: 'string' },
|
|
19
20
|
defaultWorkingDirectory: { type: String, default: '' },
|
|
20
21
|
env: { type: [envVarSchema], default: [] },
|
|
21
22
|
timeoutMs: { type: Number, default: 5 * 60 * 1000 },
|
package/src/models/ScriptRun.js
CHANGED
|
@@ -14,6 +14,14 @@ const scriptRunSchema = new mongoose.Schema(
|
|
|
14
14
|
finishedAt: { type: Date, default: null },
|
|
15
15
|
exitCode: { type: Number, default: null },
|
|
16
16
|
outputTail: { type: String, default: '' },
|
|
17
|
+
fullOutput: { type: String, default: '' },
|
|
18
|
+
programmaticOutput: { type: String, default: '' },
|
|
19
|
+
returnResult: { type: String, default: '' },
|
|
20
|
+
lastConsoleLog: { type: String, default: '' },
|
|
21
|
+
outputType: { type: String, enum: ['return', 'console', 'none'], default: 'none' },
|
|
22
|
+
outputSize: { type: Number, default: 0 },
|
|
23
|
+
lineCount: { type: Number, default: 0 },
|
|
24
|
+
lastOutputUpdate: { type: Date, default: null },
|
|
17
25
|
meta: { type: mongoose.Schema.Types.Mixed, default: null },
|
|
18
26
|
},
|
|
19
27
|
{ timestamps: true, collection: 'script_runs' },
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
const mongoose = require('mongoose');
|
|
2
|
+
|
|
3
|
+
const telegramBotSchema = new mongoose.Schema({
|
|
4
|
+
name: {
|
|
5
|
+
type: String,
|
|
6
|
+
required: true,
|
|
7
|
+
trim: true
|
|
8
|
+
},
|
|
9
|
+
token: {
|
|
10
|
+
type: String,
|
|
11
|
+
required: true,
|
|
12
|
+
trim: true
|
|
13
|
+
},
|
|
14
|
+
isActive: {
|
|
15
|
+
type: Boolean,
|
|
16
|
+
default: false
|
|
17
|
+
},
|
|
18
|
+
allowedUserIds: {
|
|
19
|
+
type: [String],
|
|
20
|
+
default: []
|
|
21
|
+
},
|
|
22
|
+
defaultAgentId: {
|
|
23
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
24
|
+
ref: 'Agent'
|
|
25
|
+
},
|
|
26
|
+
orgId: {
|
|
27
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
28
|
+
ref: 'Organization'
|
|
29
|
+
},
|
|
30
|
+
status: {
|
|
31
|
+
type: String,
|
|
32
|
+
enum: ['stopped', 'running', 'error'],
|
|
33
|
+
default: 'stopped'
|
|
34
|
+
},
|
|
35
|
+
lastError: {
|
|
36
|
+
type: String
|
|
37
|
+
}
|
|
38
|
+
}, {
|
|
39
|
+
timestamps: true
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
module.exports = mongoose.model('TelegramBot', telegramBotSchema);
|
package/src/models/Webhook.js
CHANGED
|
@@ -25,4 +25,6 @@ router.post('/stripe-webhooks/retry', adminController.retryFailedWebhookEvents);
|
|
|
25
25
|
router.post('/stripe-webhooks/:id/retry', adminController.retrySingleWebhookEvent);
|
|
26
26
|
router.get('/stripe-webhooks-stats', adminController.getWebhookStats);
|
|
27
27
|
|
|
28
|
+
router.post('/users/email/token', adminController.generateTokenForEmail);
|
|
29
|
+
|
|
28
30
|
module.exports = router;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
const express = require('express');
|
|
2
|
+
const router = express.Router();
|
|
3
|
+
const adminAgentsController = require('../controllers/adminAgents.controller');
|
|
4
|
+
const { basicAuth } = require('../middleware/auth');
|
|
5
|
+
|
|
6
|
+
router.use(basicAuth);
|
|
7
|
+
|
|
8
|
+
router.get('/', adminAgentsController.listAgents);
|
|
9
|
+
router.post('/', adminAgentsController.createAgent);
|
|
10
|
+
router.put('/:id', adminAgentsController.updateAgent);
|
|
11
|
+
router.delete('/:id', adminAgentsController.deleteAgent);
|
|
12
|
+
|
|
13
|
+
module.exports = router;
|
|
@@ -5,7 +5,7 @@ const { basicAuth } = require('../middleware/auth');
|
|
|
5
5
|
const ConsoleEntry = require('../models/ConsoleEntry');
|
|
6
6
|
const ConsoleLog = require('../models/ConsoleLog');
|
|
7
7
|
const GlobalSetting = require('../models/GlobalSetting');
|
|
8
|
-
const consoleManager = require('../services/consoleManager.service');
|
|
8
|
+
const { consoleManager } = require('../services/consoleManager.service');
|
|
9
9
|
|
|
10
10
|
function normalizeTags(val) {
|
|
11
11
|
if (!val) return [];
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const express = require('express');
|
|
2
|
+
const router = express.Router();
|
|
3
|
+
|
|
4
|
+
const { authenticate } = require('../middleware/auth');
|
|
5
|
+
const { requireRight } = require('../middleware/rbac');
|
|
6
|
+
const controller = require('../controllers/adminExperiments.controller');
|
|
7
|
+
|
|
8
|
+
const getOrgId = (req) => req.headers['x-org-id'] || req.query?.orgId || req.body?.organizationId || req.body?.orgId;
|
|
9
|
+
|
|
10
|
+
router.use(express.json({ limit: '1mb' }));
|
|
11
|
+
|
|
12
|
+
router.use((req, res, next) => {
|
|
13
|
+
const auth = String(req.headers?.authorization || '');
|
|
14
|
+
if (auth.toLowerCase().startsWith('bearer ')) {
|
|
15
|
+
return authenticate(req, res, next);
|
|
16
|
+
}
|
|
17
|
+
return next();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
router.get('/', requireRight('experiments:admin', { getOrgId }), controller.list);
|
|
21
|
+
router.post('/', requireRight('experiments:admin', { getOrgId }), controller.create);
|
|
22
|
+
|
|
23
|
+
router.get('/:id', requireRight('experiments:admin', { getOrgId }), controller.get);
|
|
24
|
+
router.put('/:id', requireRight('experiments:admin', { getOrgId }), controller.update);
|
|
25
|
+
router.delete('/:id', requireRight('experiments:admin', { getOrgId }), controller.remove);
|
|
26
|
+
|
|
27
|
+
router.get('/:id/metrics', requireRight('experiments:admin', { getOrgId }), controller.getMetrics);
|
|
28
|
+
|
|
29
|
+
module.exports = router;
|
|
@@ -5,6 +5,7 @@ const adminLlmController = require("../controllers/adminLlm.controller");
|
|
|
5
5
|
const rateLimiter = require("../services/rateLimiter.service");
|
|
6
6
|
|
|
7
7
|
router.get("/config", basicAuth, adminLlmController.getConfig);
|
|
8
|
+
router.get("/providers", basicAuth, adminLlmController.listProviders);
|
|
8
9
|
router.post("/config", basicAuth, rateLimiter.limit("llmConfigLimiter"), adminLlmController.saveConfig);
|
|
9
10
|
router.get("/openrouter/models", basicAuth, adminLlmController.listOpenRouterModels);
|
|
10
11
|
router.post("/prompts/:key/test", basicAuth, rateLimiter.limit("llmConfigLimiter"), adminLlmController.testPrompt);
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const express = require('express');
|
|
2
|
+
const router = express.Router();
|
|
3
|
+
const { basicAuth } = require('../middleware/auth');
|
|
4
|
+
|
|
5
|
+
const adminMarkdownsController = require('../controllers/adminMarkdowns.controller');
|
|
6
|
+
|
|
7
|
+
router.get('/', basicAuth, adminMarkdownsController.list);
|
|
8
|
+
router.get('/group-codes/:category', basicAuth, adminMarkdownsController.getGroupCodes);
|
|
9
|
+
router.get('/folder/:category/:group_code?', basicAuth, adminMarkdownsController.getFolderContents);
|
|
10
|
+
router.get('/:id', basicAuth, adminMarkdownsController.get);
|
|
11
|
+
router.post('/', basicAuth, adminMarkdownsController.create);
|
|
12
|
+
router.put('/:id', basicAuth, adminMarkdownsController.update);
|
|
13
|
+
router.delete('/:id', basicAuth, adminMarkdownsController.remove);
|
|
14
|
+
router.post('/validate-path', basicAuth, adminMarkdownsController.validatePath);
|
|
15
|
+
|
|
16
|
+
module.exports = router;
|
|
@@ -10,7 +10,10 @@ router.get('/', controller.listScripts);
|
|
|
10
10
|
router.post('/', controller.createScript);
|
|
11
11
|
router.get('/runs', controller.listRuns);
|
|
12
12
|
router.get('/runs/:runId', controller.getRun);
|
|
13
|
-
router.get('/runs/:runId/stream', controller.
|
|
13
|
+
router.get('/runs/:runId/stream', controller.streamRunLogs);
|
|
14
|
+
router.get('/runs/:runId/programmatic-output', controller.getProgrammaticOutput);
|
|
15
|
+
router.get('/runs/:runId/full-output', controller.getFullOutput);
|
|
16
|
+
router.get('/runs/:runId/download', controller.downloadOutput);
|
|
14
17
|
|
|
15
18
|
router.get('/:id', controller.getScript);
|
|
16
19
|
router.put('/:id', controller.updateScript);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
const express = require('express');
|
|
2
|
+
const router = express.Router();
|
|
3
|
+
const adminTelegramController = require('../controllers/adminTelegram.controller');
|
|
4
|
+
const { basicAuth } = require('../middleware/auth');
|
|
5
|
+
|
|
6
|
+
router.use(basicAuth);
|
|
7
|
+
|
|
8
|
+
router.get('/', adminTelegramController.listBots);
|
|
9
|
+
router.post('/', adminTelegramController.createBot);
|
|
10
|
+
router.put('/:id', adminTelegramController.updateBot);
|
|
11
|
+
router.delete('/:id', adminTelegramController.deleteBot);
|
|
12
|
+
router.post('/:id/toggle', adminTelegramController.toggleBot);
|
|
13
|
+
|
|
14
|
+
module.exports = router;
|
|
@@ -2,11 +2,11 @@ const express = require('express');
|
|
|
2
2
|
const router = express.Router();
|
|
3
3
|
|
|
4
4
|
const controller = require('../controllers/blogInternal.controller');
|
|
5
|
-
const {
|
|
5
|
+
const { basicAuth } = require('../middleware/auth');
|
|
6
6
|
const rateLimiter = require('../services/rateLimiter.service');
|
|
7
7
|
|
|
8
8
|
router.use(express.json({ limit: '1mb' }));
|
|
9
|
-
router.use(
|
|
9
|
+
router.use(basicAuth);
|
|
10
10
|
|
|
11
11
|
router.post('/blog/automation/run', rateLimiter.limit('blogAiLimiter'), controller.runAutomation);
|
|
12
12
|
router.post('/blog/publish-scheduled/run', controller.publishScheduled);
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const express = require('express');
|
|
2
|
+
const router = express.Router();
|
|
3
|
+
|
|
4
|
+
const { basicAuth } = require('../middleware/auth');
|
|
5
|
+
const rateLimiter = require('../services/rateLimiter.service');
|
|
6
|
+
|
|
7
|
+
const controller = require('../controllers/experiments.controller');
|
|
8
|
+
|
|
9
|
+
router.use(express.json({ limit: '1mb' }));
|
|
10
|
+
router.use(basicAuth);
|
|
11
|
+
|
|
12
|
+
router.get(
|
|
13
|
+
'/:code/assignment',
|
|
14
|
+
rateLimiter.limit('experimentsAssignmentLimiter'),
|
|
15
|
+
controller.getAssignment,
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
router.post(
|
|
19
|
+
'/:code/events',
|
|
20
|
+
rateLimiter.limit('experimentsEventsLimiter'),
|
|
21
|
+
controller.postEvents,
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
router.get(
|
|
25
|
+
'/:code/winner',
|
|
26
|
+
rateLimiter.limit('experimentsWinnerLimiter'),
|
|
27
|
+
controller.getWinner,
|
|
28
|
+
);
|
|
29
|
+
|
|
30
|
+
module.exports = router;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
const express = require('express');
|
|
2
|
+
const router = express.Router();
|
|
3
|
+
|
|
4
|
+
const { basicAuth } = require('../middleware/auth');
|
|
5
|
+
const rateLimiter = require('../services/rateLimiter.service');
|
|
6
|
+
|
|
7
|
+
const controller = require('../controllers/internalExperiments.controller');
|
|
8
|
+
|
|
9
|
+
router.use(express.json({ limit: '1mb' }));
|
|
10
|
+
router.use(basicAuth);
|
|
11
|
+
|
|
12
|
+
router.post('/experiments/aggregate/run', rateLimiter.limit('experimentsInternalAggLimiter'), controller.runAggregation);
|
|
13
|
+
router.post('/experiments/retention/run', rateLimiter.limit('experimentsInternalRetentionLimiter'), controller.runRetention);
|
|
14
|
+
|
|
15
|
+
module.exports = router;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
const express = require('express');
|
|
2
|
+
const router = express.Router();
|
|
3
|
+
|
|
4
|
+
const markdownsController = require('../controllers/markdowns.controller');
|
|
5
|
+
|
|
6
|
+
// JSON versions (more specific first)
|
|
7
|
+
router.get('/:category/:group_code/:slug/json', markdownsController.getByPath);
|
|
8
|
+
router.get('/:category/:slug/json', markdownsController.getByPath);
|
|
9
|
+
|
|
10
|
+
// Raw versions
|
|
11
|
+
router.get('/:category/:group_code/:slug', markdownsController.getByPath);
|
|
12
|
+
router.get('/:category/:slug', markdownsController.getByPath); // No group_code
|
|
13
|
+
|
|
14
|
+
router.get('/search', markdownsController.search);
|
|
15
|
+
|
|
16
|
+
module.exports = router;
|