strapi-plugin-magic-mail 2.2.4 → 2.2.6
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/README.md +0 -2
- package/dist/server/index.js +1 -1
- package/dist/server/index.mjs +1 -1
- package/package.json +1 -3
- package/admin/jsconfig.json +0 -10
- package/admin/src/components/AddAccountModal.jsx +0 -1943
- package/admin/src/components/Initializer.jsx +0 -14
- package/admin/src/components/LicenseGuard.jsx +0 -475
- package/admin/src/components/PluginIcon.jsx +0 -5
- package/admin/src/hooks/useAuthRefresh.js +0 -44
- package/admin/src/hooks/useLicense.js +0 -158
- package/admin/src/index.js +0 -87
- package/admin/src/pages/Analytics.jsx +0 -762
- package/admin/src/pages/App.jsx +0 -111
- package/admin/src/pages/EmailDesigner/EditorPage.jsx +0 -1424
- package/admin/src/pages/EmailDesigner/TemplateList.jsx +0 -1807
- package/admin/src/pages/HomePage.jsx +0 -1170
- package/admin/src/pages/LicensePage.jsx +0 -430
- package/admin/src/pages/RoutingRules.jsx +0 -1141
- package/admin/src/pages/Settings.jsx +0 -603
- package/admin/src/pluginId.js +0 -3
- package/admin/src/translations/de.json +0 -71
- package/admin/src/translations/en.json +0 -70
- package/admin/src/translations/es.json +0 -71
- package/admin/src/translations/fr.json +0 -71
- package/admin/src/translations/pt.json +0 -71
- package/admin/src/utils/fetchWithRetry.js +0 -123
- package/admin/src/utils/getTranslation.js +0 -5
- package/admin/src/utils/theme.js +0 -85
- package/server/jsconfig.json +0 -10
- package/server/src/bootstrap.js +0 -157
- package/server/src/config/features.js +0 -260
- package/server/src/config/index.js +0 -9
- package/server/src/content-types/email-account/schema.json +0 -93
- package/server/src/content-types/email-event/index.js +0 -8
- package/server/src/content-types/email-event/schema.json +0 -57
- package/server/src/content-types/email-link/index.js +0 -8
- package/server/src/content-types/email-link/schema.json +0 -49
- package/server/src/content-types/email-log/index.js +0 -8
- package/server/src/content-types/email-log/schema.json +0 -106
- package/server/src/content-types/email-template/schema.json +0 -74
- package/server/src/content-types/email-template-version/schema.json +0 -60
- package/server/src/content-types/index.js +0 -33
- package/server/src/content-types/routing-rule/schema.json +0 -59
- package/server/src/controllers/accounts.js +0 -229
- package/server/src/controllers/analytics.js +0 -361
- package/server/src/controllers/controller.js +0 -26
- package/server/src/controllers/email-designer.js +0 -474
- package/server/src/controllers/index.js +0 -21
- package/server/src/controllers/license.js +0 -269
- package/server/src/controllers/oauth.js +0 -474
- package/server/src/controllers/routing-rules.js +0 -129
- package/server/src/controllers/test.js +0 -301
- package/server/src/destroy.js +0 -27
- package/server/src/index.js +0 -25
- package/server/src/middlewares/index.js +0 -3
- package/server/src/policies/index.js +0 -3
- package/server/src/register.js +0 -5
- package/server/src/routes/admin.js +0 -469
- package/server/src/routes/content-api.js +0 -37
- package/server/src/routes/index.js +0 -9
- package/server/src/services/account-manager.js +0 -329
- package/server/src/services/analytics.js +0 -512
- package/server/src/services/email-designer.js +0 -717
- package/server/src/services/email-router.js +0 -1446
- package/server/src/services/index.js +0 -17
- package/server/src/services/license-guard.js +0 -423
- package/server/src/services/oauth.js +0 -515
- package/server/src/services/service.js +0 -7
- package/server/src/utils/encryption.js +0 -81
- package/server/src/utils/logger.js +0 -84
|
@@ -1,301 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Test Controller für Template-Version Relations
|
|
3
|
-
* [SUCCESS] Migrated to strapi.documents() API (Strapi v5 Best Practice)
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
'use strict';
|
|
7
|
-
|
|
8
|
-
const EMAIL_TEMPLATE_UID = 'plugin::magic-mail.email-template';
|
|
9
|
-
const EMAIL_TEMPLATE_VERSION_UID = 'plugin::magic-mail.email-template-version';
|
|
10
|
-
|
|
11
|
-
module.exports = {
|
|
12
|
-
/**
|
|
13
|
-
* Test Template-Version Relations
|
|
14
|
-
*/
|
|
15
|
-
async testRelations(ctx) {
|
|
16
|
-
try {
|
|
17
|
-
console.log('\n' + '='.repeat(60));
|
|
18
|
-
console.log('🧪 TEST: Template ↔ Version Relations (Document Service API)');
|
|
19
|
-
console.log('='.repeat(60));
|
|
20
|
-
|
|
21
|
-
// Initialize test result variables
|
|
22
|
-
let test1Success = false;
|
|
23
|
-
let test1ReverseSuccess = false;
|
|
24
|
-
let test2Success = false;
|
|
25
|
-
let test2ReverseSuccess = false;
|
|
26
|
-
let test3a_versionCreated = false;
|
|
27
|
-
let test3a_hasTemplate = false;
|
|
28
|
-
let test3b_twoVersions = false;
|
|
29
|
-
let test3b_allHaveTemplate = false;
|
|
30
|
-
|
|
31
|
-
// ============================================================
|
|
32
|
-
// TEST 1: Version mit Template verbinden
|
|
33
|
-
// ============================================================
|
|
34
|
-
console.log('\n[TEST] TEST 1: Version → Template Verbindung\n');
|
|
35
|
-
|
|
36
|
-
// Erstelle Test-Template
|
|
37
|
-
const testTemplate = await strapi.documents(EMAIL_TEMPLATE_UID).create({
|
|
38
|
-
data: {
|
|
39
|
-
templateReferenceId: Math.floor(Math.random() * 1000000),
|
|
40
|
-
name: 'Test Template Relations',
|
|
41
|
-
subject: 'Test Subject',
|
|
42
|
-
bodyHtml: '<p>Test HTML</p>',
|
|
43
|
-
bodyText: 'Test Text',
|
|
44
|
-
category: 'custom',
|
|
45
|
-
isActive: true
|
|
46
|
-
}
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
console.log(`[SUCCESS] Template erstellt: documentId ${testTemplate.documentId}`);
|
|
50
|
-
|
|
51
|
-
// Erstelle Version mit Template-Verbindung
|
|
52
|
-
const version1 = await strapi.documents(EMAIL_TEMPLATE_VERSION_UID).create({
|
|
53
|
-
data: {
|
|
54
|
-
template: testTemplate.documentId,
|
|
55
|
-
versionNumber: 1,
|
|
56
|
-
name: 'Version 1 von Test',
|
|
57
|
-
subject: 'Test Subject V1',
|
|
58
|
-
bodyHtml: '<p>Version 1 HTML</p>',
|
|
59
|
-
bodyText: 'Version 1 Text'
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
|
|
63
|
-
console.log(`[SUCCESS] Version erstellt: documentId ${version1.documentId}, versionNumber: ${version1.versionNumber}`);
|
|
64
|
-
|
|
65
|
-
// Prüfe Version → Template
|
|
66
|
-
const versionCheck = await strapi.documents(EMAIL_TEMPLATE_VERSION_UID).findOne({
|
|
67
|
-
documentId: version1.documentId,
|
|
68
|
-
populate: ['template']
|
|
69
|
-
});
|
|
70
|
-
|
|
71
|
-
console.log('\n[CHECK] Prüfung Version → Template:');
|
|
72
|
-
test1Success = !!versionCheck.template;
|
|
73
|
-
if (test1Success) {
|
|
74
|
-
console.log(` [SUCCESS] SUCCESS: Version → Template ${versionCheck.template.documentId}`);
|
|
75
|
-
} else {
|
|
76
|
-
console.log(` [ERROR] FEHLER: Version hat KEINE Template-Verbindung!`);
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Prüfe Template → Versions
|
|
80
|
-
const templateCheck1 = await strapi.documents(EMAIL_TEMPLATE_UID).findOne({
|
|
81
|
-
documentId: testTemplate.documentId,
|
|
82
|
-
populate: ['versions']
|
|
83
|
-
});
|
|
84
|
-
|
|
85
|
-
console.log('\n[CHECK] Prüfung Template → Versions:');
|
|
86
|
-
test1ReverseSuccess = templateCheck1.versions && templateCheck1.versions.length > 0;
|
|
87
|
-
if (test1ReverseSuccess) {
|
|
88
|
-
console.log(` [SUCCESS] SUCCESS: Template hat ${templateCheck1.versions.length} Version(en)`);
|
|
89
|
-
} else {
|
|
90
|
-
console.log(` [ERROR] FEHLER: Template hat KEINE Versionen!`);
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
// ============================================================
|
|
94
|
-
// TEST 2: Nachträgliche Verbindung
|
|
95
|
-
// ============================================================
|
|
96
|
-
console.log('\n\n[TEST] TEST 2: Nachträgliche Verbindung\n');
|
|
97
|
-
|
|
98
|
-
// Version OHNE Template
|
|
99
|
-
const version2 = await strapi.documents(EMAIL_TEMPLATE_VERSION_UID).create({
|
|
100
|
-
data: {
|
|
101
|
-
versionNumber: 2,
|
|
102
|
-
name: 'Version 2 ohne Template',
|
|
103
|
-
subject: 'Test Subject V2',
|
|
104
|
-
bodyHtml: '<p>Version 2 HTML</p>',
|
|
105
|
-
bodyText: 'Version 2 Text'
|
|
106
|
-
}
|
|
107
|
-
});
|
|
108
|
-
|
|
109
|
-
console.log(`[SUCCESS] Version 2 erstellt: documentId ${version2.documentId} (ohne Template)`);
|
|
110
|
-
|
|
111
|
-
// Nachträgliche Verbindung via Version-Update
|
|
112
|
-
await strapi.documents(EMAIL_TEMPLATE_VERSION_UID).update({
|
|
113
|
-
documentId: version2.documentId,
|
|
114
|
-
data: {
|
|
115
|
-
template: testTemplate.documentId
|
|
116
|
-
}
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
console.log(`[SUCCESS] Version 2 mit Template verbunden`);
|
|
120
|
-
|
|
121
|
-
// Prüfe Verbindung
|
|
122
|
-
const templateCheck2 = await strapi.documents(EMAIL_TEMPLATE_UID).findOne({
|
|
123
|
-
documentId: testTemplate.documentId,
|
|
124
|
-
populate: ['versions']
|
|
125
|
-
});
|
|
126
|
-
|
|
127
|
-
console.log('\n[CHECK] Prüfung nach Update:');
|
|
128
|
-
test2Success = templateCheck2.versions && templateCheck2.versions.length >= 2;
|
|
129
|
-
if (test2Success) {
|
|
130
|
-
console.log(` [SUCCESS] SUCCESS: Template hat jetzt ${templateCheck2.versions.length} Versionen`);
|
|
131
|
-
} else {
|
|
132
|
-
console.log(` [ERROR] FEHLER: Template hat nur ${templateCheck2.versions?.length || 0} Version(en)!`);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
// Prüfe von Version 2 aus
|
|
136
|
-
const version2Check = await strapi.documents(EMAIL_TEMPLATE_VERSION_UID).findOne({
|
|
137
|
-
documentId: version2.documentId,
|
|
138
|
-
populate: ['template']
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
test2ReverseSuccess = !!version2Check.template;
|
|
142
|
-
if (test2ReverseSuccess) {
|
|
143
|
-
console.log(` [SUCCESS] SUCCESS: Version 2 → Template verbunden`);
|
|
144
|
-
} else {
|
|
145
|
-
console.log(` [ERROR] FEHLER: Version 2 hat KEINE Template-Verbindung!`);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
// ============================================================
|
|
149
|
-
// TEST 3: Auto-Versionierung
|
|
150
|
-
// ============================================================
|
|
151
|
-
console.log('\n\n[TEST] TEST 3: Template Update (Auto-Versionierung)\n');
|
|
152
|
-
|
|
153
|
-
const autoTemplate = await strapi.documents(EMAIL_TEMPLATE_UID).create({
|
|
154
|
-
data: {
|
|
155
|
-
templateReferenceId: Math.floor(Math.random() * 1000000),
|
|
156
|
-
name: 'Auto Version Test',
|
|
157
|
-
subject: 'Original Subject',
|
|
158
|
-
bodyHtml: '<p>Original HTML</p>',
|
|
159
|
-
bodyText: 'Original Text',
|
|
160
|
-
category: 'custom',
|
|
161
|
-
isActive: true
|
|
162
|
-
}
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
console.log(`[SUCCESS] Template erstellt: documentId ${autoTemplate.documentId}`);
|
|
166
|
-
|
|
167
|
-
// Update via email-designer Service
|
|
168
|
-
const emailDesignerService = strapi.plugin('magic-mail').service('email-designer');
|
|
169
|
-
await emailDesignerService.update(autoTemplate.documentId, {
|
|
170
|
-
subject: 'Updated Subject V1',
|
|
171
|
-
bodyHtml: '<p>Updated HTML V1</p>',
|
|
172
|
-
bodyText: 'Updated Text V1'
|
|
173
|
-
});
|
|
174
|
-
|
|
175
|
-
console.log('[SUCCESS] Template updated');
|
|
176
|
-
|
|
177
|
-
const afterFirstUpdate = await strapi.documents(EMAIL_TEMPLATE_UID).findOne({
|
|
178
|
-
documentId: autoTemplate.documentId,
|
|
179
|
-
populate: ['versions']
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
console.log('\n[CHECK] Prüfung nach 1. Update:');
|
|
183
|
-
test3a_versionCreated = afterFirstUpdate.versions && afterFirstUpdate.versions.length === 1;
|
|
184
|
-
|
|
185
|
-
if (test3a_versionCreated) {
|
|
186
|
-
console.log(` [SUCCESS] SUCCESS: Automatisch 1 Version erstellt`);
|
|
187
|
-
|
|
188
|
-
const autoVersion1 = await strapi.documents(EMAIL_TEMPLATE_VERSION_UID).findOne({
|
|
189
|
-
documentId: afterFirstUpdate.versions[0].documentId,
|
|
190
|
-
populate: ['template']
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
test3a_hasTemplate = !!autoVersion1.template;
|
|
194
|
-
if (test3a_hasTemplate) {
|
|
195
|
-
console.log(` [SUCCESS] SUCCESS: Version hat Template-Verbindung`);
|
|
196
|
-
} else {
|
|
197
|
-
console.log(` [ERROR] FEHLER: Version hat KEINE Template-Verbindung!`);
|
|
198
|
-
}
|
|
199
|
-
} else {
|
|
200
|
-
console.log(` [ERROR] FEHLER: Keine Version erstellt!`);
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
// Zweites Update
|
|
204
|
-
await emailDesignerService.update(autoTemplate.documentId, {
|
|
205
|
-
subject: 'Updated Subject V2',
|
|
206
|
-
bodyHtml: '<p>Updated HTML V2</p>',
|
|
207
|
-
bodyText: 'Updated Text V2'
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
const afterSecondUpdate = await strapi.documents(EMAIL_TEMPLATE_UID).findOne({
|
|
211
|
-
documentId: autoTemplate.documentId,
|
|
212
|
-
populate: ['versions']
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
console.log('\n[CHECK] Prüfung nach 2. Update:');
|
|
216
|
-
test3b_twoVersions = afterSecondUpdate.versions && afterSecondUpdate.versions.length === 2;
|
|
217
|
-
|
|
218
|
-
if (test3b_twoVersions) {
|
|
219
|
-
console.log(` [SUCCESS] SUCCESS: Jetzt 2 Versionen vorhanden`);
|
|
220
|
-
|
|
221
|
-
let allVersionsHaveTemplate = true;
|
|
222
|
-
for (const version of afterSecondUpdate.versions) {
|
|
223
|
-
const fullVersion = await strapi.documents(EMAIL_TEMPLATE_VERSION_UID).findOne({
|
|
224
|
-
documentId: version.documentId,
|
|
225
|
-
populate: ['template']
|
|
226
|
-
});
|
|
227
|
-
|
|
228
|
-
if (!fullVersion.template) {
|
|
229
|
-
allVersionsHaveTemplate = false;
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
test3b_allHaveTemplate = allVersionsHaveTemplate;
|
|
234
|
-
if (allVersionsHaveTemplate) {
|
|
235
|
-
console.log(` [SUCCESS] SUCCESS: Alle Versionen haben Template-Verbindung!`);
|
|
236
|
-
} else {
|
|
237
|
-
console.log(` [ERROR] FEHLER: Nicht alle Versionen haben Template-Verbindung!`);
|
|
238
|
-
}
|
|
239
|
-
} else {
|
|
240
|
-
console.log(` [ERROR] FEHLER: Falsche Anzahl Versionen!`);
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
// Cleanup Test 3
|
|
244
|
-
console.log('\n🧹 Cleanup Test 3...');
|
|
245
|
-
if (afterSecondUpdate.versions) {
|
|
246
|
-
for (const version of afterSecondUpdate.versions) {
|
|
247
|
-
await strapi.documents(EMAIL_TEMPLATE_VERSION_UID).delete({ documentId: version.documentId });
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
await strapi.documents(EMAIL_TEMPLATE_UID).delete({ documentId: autoTemplate.documentId });
|
|
251
|
-
console.log(' [SUCCESS] Test 3 Daten gelöscht');
|
|
252
|
-
|
|
253
|
-
// ============================================================
|
|
254
|
-
// Zusammenfassung
|
|
255
|
-
// ============================================================
|
|
256
|
-
console.log('\n\n' + '='.repeat(60));
|
|
257
|
-
console.log('[STATS] ZUSAMMENFASSUNG');
|
|
258
|
-
console.log('='.repeat(60));
|
|
259
|
-
|
|
260
|
-
const finalTemplate = await strapi.documents(EMAIL_TEMPLATE_UID).findOne({
|
|
261
|
-
documentId: testTemplate.documentId,
|
|
262
|
-
populate: ['versions']
|
|
263
|
-
});
|
|
264
|
-
|
|
265
|
-
console.log(`\n[INFO] Template: "${finalTemplate.name}" (documentId: ${finalTemplate.documentId})`);
|
|
266
|
-
console.log(` Anzahl Versionen: ${finalTemplate.versions?.length || 0}`);
|
|
267
|
-
|
|
268
|
-
// Cleanup
|
|
269
|
-
console.log('\n🧹 Aufräumen...');
|
|
270
|
-
await strapi.documents(EMAIL_TEMPLATE_VERSION_UID).delete({ documentId: version1.documentId });
|
|
271
|
-
await strapi.documents(EMAIL_TEMPLATE_VERSION_UID).delete({ documentId: version2.documentId });
|
|
272
|
-
await strapi.documents(EMAIL_TEMPLATE_UID).delete({ documentId: testTemplate.documentId });
|
|
273
|
-
console.log(' [SUCCESS] Alle Test-Daten gelöscht');
|
|
274
|
-
|
|
275
|
-
console.log('\n[SUCCESS] Test abgeschlossen!\n');
|
|
276
|
-
|
|
277
|
-
const allSuccess = test1Success && test1ReverseSuccess && test2Success && test2ReverseSuccess &&
|
|
278
|
-
test3a_versionCreated && test3a_hasTemplate && test3b_twoVersions && test3b_allHaveTemplate;
|
|
279
|
-
|
|
280
|
-
ctx.body = {
|
|
281
|
-
success: allSuccess,
|
|
282
|
-
message: allSuccess ? 'Alle Tests erfolgreich! [SUCCESS]' : 'Einige Tests fehlgeschlagen [ERROR]',
|
|
283
|
-
tests: {
|
|
284
|
-
test1_version_to_template: test1Success,
|
|
285
|
-
test1_template_to_version: test1ReverseSuccess,
|
|
286
|
-
test2_template_connect: test2Success,
|
|
287
|
-
test2_version_to_template: test2ReverseSuccess,
|
|
288
|
-
test3_auto_version_created: test3a_versionCreated,
|
|
289
|
-
test3_auto_version_has_template: test3a_hasTemplate,
|
|
290
|
-
test3_two_auto_versions: test3b_twoVersions,
|
|
291
|
-
test3_all_auto_versions_have_template: test3b_allHaveTemplate,
|
|
292
|
-
}
|
|
293
|
-
};
|
|
294
|
-
|
|
295
|
-
} catch (error) {
|
|
296
|
-
console.error('\n[ERROR] FEHLER:', error.message);
|
|
297
|
-
console.error(error.stack);
|
|
298
|
-
ctx.throw(500, error);
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
};
|
package/server/src/destroy.js
DELETED
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const { createLogger } = require('./utils/logger');
|
|
4
|
-
|
|
5
|
-
module.exports = ({ strapi }) => {
|
|
6
|
-
const log = createLogger(strapi);
|
|
7
|
-
|
|
8
|
-
// Cleanup intervals
|
|
9
|
-
if (global.magicMailIntervals) {
|
|
10
|
-
if (global.magicMailIntervals.hourly) {
|
|
11
|
-
clearInterval(global.magicMailIntervals.hourly);
|
|
12
|
-
log.info('Cleared hourly reset interval');
|
|
13
|
-
}
|
|
14
|
-
if (global.magicMailIntervals.daily) {
|
|
15
|
-
clearInterval(global.magicMailIntervals.daily);
|
|
16
|
-
log.info('Cleared daily reset interval');
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// Cleanup license guard ping interval
|
|
21
|
-
if (strapi.licenseGuardMagicMail && strapi.licenseGuardMagicMail.pingInterval) {
|
|
22
|
-
clearInterval(strapi.licenseGuardMagicMail.pingInterval);
|
|
23
|
-
log.info('Cleared license ping interval');
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
log.info('👋 Plugin destroyed gracefully');
|
|
27
|
-
};
|
package/server/src/index.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
const register = require('./register');
|
|
4
|
-
const bootstrap = require('./bootstrap');
|
|
5
|
-
const destroy = require('./destroy');
|
|
6
|
-
const config = require('./config');
|
|
7
|
-
const contentTypes = require('./content-types');
|
|
8
|
-
const controllers = require('./controllers');
|
|
9
|
-
const routes = require('./routes');
|
|
10
|
-
const middlewares = require('./middlewares');
|
|
11
|
-
const policies = require('./policies');
|
|
12
|
-
const services = require('./services');
|
|
13
|
-
|
|
14
|
-
module.exports = {
|
|
15
|
-
register,
|
|
16
|
-
bootstrap,
|
|
17
|
-
destroy,
|
|
18
|
-
config,
|
|
19
|
-
contentTypes,
|
|
20
|
-
controllers,
|
|
21
|
-
routes,
|
|
22
|
-
middlewares,
|
|
23
|
-
policies,
|
|
24
|
-
services,
|
|
25
|
-
};
|