webspresso 0.0.97 → 0.0.99

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 (136) hide show
  1. package/.agents/ADMIN.md +163 -5
  2. package/.agents/AGENTS.md +1 -1
  3. package/.agents/ARCHITECTURE.md +10 -0
  4. package/.agents/AUTH.md +169 -0
  5. package/.agents/CLI.md +195 -1
  6. package/.agents/ORM.md +88 -4
  7. package/.agents/PLUGINS.md +221 -9
  8. package/.agents/QUEUE.md +127 -0
  9. package/.agents/ROUTING.md +127 -7
  10. package/AGENTS.md +1 -0
  11. package/bin/commands/add-esbuild.js +80 -0
  12. package/bin/commands/add-tailwind.js +76 -31
  13. package/bin/commands/analytics-prune.js +57 -0
  14. package/bin/commands/api.js +207 -15
  15. package/bin/commands/build.js +99 -0
  16. package/bin/commands/dev.js +64 -35
  17. package/bin/commands/doctor.js +26 -0
  18. package/bin/commands/email-prune.js +47 -0
  19. package/bin/commands/make-job.js +86 -0
  20. package/bin/commands/make-model.js +250 -0
  21. package/bin/commands/new.js +45 -28
  22. package/bin/commands/openapi.js +102 -0
  23. package/bin/commands/page.js +6 -3
  24. package/bin/commands/queue-prune.js +59 -0
  25. package/bin/commands/routes.js +52 -0
  26. package/bin/commands/service.js +6 -3
  27. package/bin/commands/typegen.js +106 -0
  28. package/bin/commands/upload-prune.js +79 -0
  29. package/bin/webspresso.js +22 -0
  30. package/core/applySchema.js +13 -6
  31. package/core/auth/hash.js +21 -12
  32. package/core/auth/index.js +60 -0
  33. package/core/auth/manager.js +134 -0
  34. package/core/auth/middleware.js +88 -0
  35. package/core/auth/oauth.js +517 -0
  36. package/core/auth/qrcode.js +499 -0
  37. package/core/auth/totp.js +504 -0
  38. package/core/compression/middleware.js +23 -17
  39. package/core/openapi/build-from-api-routes.js +160 -29
  40. package/core/orm/cache/fingerprint.js +15 -1
  41. package/core/orm/cache/memory-provider.js +27 -2
  42. package/core/orm/eager-loader.js +144 -10
  43. package/core/orm/index.js +20 -7
  44. package/core/orm/model.js +53 -7
  45. package/core/orm/query-builder.js +90 -4
  46. package/core/orm/repository.js +44 -3
  47. package/core/orm/search.js +213 -0
  48. package/core/queue/adapters/database.js +94 -0
  49. package/core/queue/adapters/memory.js +62 -0
  50. package/core/queue/adapters/redis.js +80 -0
  51. package/core/queue/cron.js +331 -0
  52. package/core/queue/index.js +8 -1
  53. package/core/queue/manager.js +205 -1
  54. package/core/queue/scheduler.js +359 -0
  55. package/core/sse/index.js +19 -0
  56. package/core/sse/stream.js +430 -0
  57. package/core/ssr/stream.js +11 -0
  58. package/index.d.ts +1188 -10
  59. package/index.js +88 -96
  60. package/package.json +1 -1
  61. package/plugins/admin-panel/api.js +279 -17
  62. package/plugins/admin-panel/app.js +114 -22
  63. package/plugins/admin-panel/client/parts/01-state-api-breadcrumb.js +314 -9
  64. package/plugins/admin-panel/client/parts/04-field-renderers.js +264 -67
  65. package/plugins/admin-panel/client/parts/05-rich-text-file-helpers.js +333 -36
  66. package/plugins/admin-panel/client/parts/06-login-setup-forms.js +119 -28
  67. package/plugins/admin-panel/client/parts/07-model-list.js +49 -8
  68. package/plugins/admin-panel/client/parts/08-record-list.js +248 -23
  69. package/plugins/admin-panel/client/parts/09-record-form.js +59 -12
  70. package/plugins/admin-panel/client/parts/10-export-registry.js +23 -0
  71. package/plugins/admin-panel/client/verify-spa-parts.js +2 -0
  72. package/plugins/admin-panel/core/admin-module.js +13 -7
  73. package/plugins/admin-panel/core/api-extensions.js +30 -2
  74. package/plugins/admin-panel/core/registry.js +96 -16
  75. package/plugins/admin-panel/field-renderers/file-upload.js +187 -104
  76. package/plugins/admin-panel/field-renderers/index.js +2 -0
  77. package/plugins/admin-panel/index.js +96 -0
  78. package/plugins/admin-panel/lib/login-rate-limiter.js +119 -0
  79. package/plugins/admin-panel/modules/admin-users.js +16 -1
  80. package/plugins/admin-panel/modules/bulk-actions.js +13 -5
  81. package/plugins/admin-panel/modules/custom-pages.js +492 -3
  82. package/plugins/admin-panel/modules/dashboard.js +283 -0
  83. package/plugins/admin-panel/modules/menu.js +56 -18
  84. package/plugins/admin-panel/modules/user-management.js +24 -6
  85. package/plugins/api-key/crypto.js +101 -0
  86. package/plugins/api-key/index.js +288 -0
  87. package/plugins/api-key/middleware.js +461 -0
  88. package/plugins/api-key/migration-template.js +48 -0
  89. package/plugins/api-key/model.js +50 -0
  90. package/plugins/api-key/scopes.js +125 -0
  91. package/plugins/audit-log/admin-component.js +487 -59
  92. package/plugins/audit-log/api-handlers.js +148 -0
  93. package/plugins/audit-log/index.js +153 -3
  94. package/plugins/audit-log/purge.js +60 -10
  95. package/plugins/dashboard/app.js +152 -27
  96. package/plugins/dashboard/index.js +143 -39
  97. package/plugins/dashboard/styles.js +78 -0
  98. package/plugins/data-exchange/export-xlsx.js +9 -2
  99. package/plugins/data-exchange/import.js +9 -2
  100. package/plugins/data-exchange/index.js +6 -3
  101. package/plugins/email/index.js +132 -2
  102. package/plugins/email/purge.js +60 -10
  103. package/plugins/file-manager/admin-component.js +20 -4
  104. package/plugins/file-manager/index.js +21 -4
  105. package/plugins/index.js +10 -0
  106. package/plugins/oauth/index.js +338 -0
  107. package/plugins/orm-cache-admin/index.js +4 -2
  108. package/plugins/queue/index.js +15 -0
  109. package/plugins/schema-explorer/admin-component.js +714 -0
  110. package/plugins/schema-explorer/relations-graph.js +205 -0
  111. package/plugins/schema-explorer.js +248 -69
  112. package/plugins/site-analytics/admin-component.js +23 -0
  113. package/plugins/site-analytics/api-handlers.js +42 -0
  114. package/plugins/site-analytics/index.js +147 -2
  115. package/plugins/site-analytics/purge.js +168 -0
  116. package/plugins/swagger.js +261 -13
  117. package/plugins/upload/index.js +26 -0
  118. package/plugins/upload/orphan-pruner.js +292 -0
  119. package/src/api/api-loader.js +4 -1
  120. package/src/bundle/index.js +517 -0
  121. package/src/bundle/manifest.js +165 -0
  122. package/src/dev/banner.js +296 -0
  123. package/src/dev/colors.js +70 -0
  124. package/src/dev/index.js +62 -0
  125. package/src/dev/profiler.js +354 -0
  126. package/src/dev/typegen.js +497 -0
  127. package/src/dev-reload/index.js +611 -0
  128. package/src/discovery/file-route-parser.js +44 -1
  129. package/src/discovery/scan-routes.js +2 -2
  130. package/src/file-router.js +347 -162
  131. package/src/helpers.js +967 -98
  132. package/src/njk-frontmatter.js +12 -0
  133. package/src/pages/page-loader.js +61 -11
  134. package/src/routing/cascading.js +378 -0
  135. package/src/routing/middleware-resolver.js +92 -0
  136. package/src/server.js +635 -63
@@ -29,10 +29,21 @@ const { emailPluginOptionsFromManifest } = require('./manifest');
29
29
  * @param {Object} [options.authEmails] - Auth email bridge config
30
30
  * @param {Object} [options.emailTemplates] - Precompiled templates from build manifest
31
31
  * @param {Object} [options.manifest] - Full build manifest (uses emailTemplates field)
32
+ * @param {Object|boolean} [options.retention] - Retention policy configuration (set false to disable)
33
+ * @param {number} [options.retention.days=90] - Days to retain email logs
34
+ * @param {number} [options.retention.intervalMs=86400000] - Auto-cleanup timer frequency (24h)
35
+ * @param {boolean} [options.retention.runOnStart=true] - Run initial purge shortly after startup
36
+ * @param {number} [options.retentionDays=90] - Shorthand for retention.days
37
+ * @param {number} [options.cleanupIntervalMs=86400000] - Shorthand for retention.intervalMs
38
+ * @param {boolean} [options.autoCleanup=true] - Enable automatic background cleanup
39
+ * @param {boolean} [options.cleanupOnStart=true] - Run initial purge on start
40
+ * @param {number} [options.cleanupStartDelayMs] - Delay in ms before start purge
32
41
  */
33
42
  function emailPlugin(options = {}) {
34
43
  const {
35
44
  db,
45
+ title,
46
+ adminTitle,
36
47
  transport,
37
48
  smtp,
38
49
  defaults = {},
@@ -48,6 +59,8 @@ function emailPlugin(options = {}) {
48
59
  manifest,
49
60
  } = options;
50
61
 
62
+ const pageTitle = title || adminTitle || 'Email';
63
+
51
64
  const logToDb = options.logToDb !== undefined ? options.logToDb : !!db;
52
65
  const knex = db ? (db.knex || db) : null;
53
66
 
@@ -55,6 +68,90 @@ function emailPlugin(options = {}) {
55
68
  console.warn('[email] logToDb is enabled but no db was passed — logging disabled');
56
69
  }
57
70
 
71
+ // Retention configuration
72
+ const retentionOption = options.retention;
73
+ const isRetentionDisabled =
74
+ retentionOption === false ||
75
+ (typeof retentionOption === 'object' && retentionOption.enabled === false) ||
76
+ options.retentionDays === null ||
77
+ options.retentionDays === 0 ||
78
+ !logToDb ||
79
+ !knex;
80
+
81
+ const autoCleanupEnabled =
82
+ !isRetentionDisabled &&
83
+ options.autoCleanup !== false &&
84
+ (typeof retentionOption !== 'object' || retentionOption.autoCleanup !== false);
85
+
86
+ const retentionConfig = {
87
+ enabled: !isRetentionDisabled,
88
+ autoCleanup: autoCleanupEnabled,
89
+ days: (typeof options.retentionDays === 'number' && options.retentionDays > 0)
90
+ ? options.retentionDays
91
+ : (typeof retentionOption === 'object' && retentionOption?.days ? retentionOption.days : 90),
92
+ intervalMs: (typeof options.cleanupIntervalMs === 'number' && options.cleanupIntervalMs > 0)
93
+ ? options.cleanupIntervalMs
94
+ : (typeof retentionOption === 'object' && retentionOption?.intervalMs ? retentionOption.intervalMs : 24 * 60 * 60 * 1000),
95
+ runOnStart: (typeof retentionOption === 'object' && retentionOption?.runOnStart !== undefined)
96
+ ? !!retentionOption.runOnStart
97
+ : (options.cleanupOnStart !== undefined ? !!options.cleanupOnStart : true),
98
+ };
99
+
100
+ let cleanupInterval = null;
101
+ let cleanupStartTimeout = null;
102
+
103
+ async function runCleanup() {
104
+ if (!knex) return 0;
105
+ try {
106
+ return await purgeEmailLogs(knex, {
107
+ tableName,
108
+ days: retentionConfig.days,
109
+ });
110
+ } catch (err) {
111
+ if (process.env.NODE_ENV !== 'test') {
112
+ console.warn('[email] Failed to run retention cleanup:', err.message);
113
+ }
114
+ }
115
+ }
116
+
117
+ function startCleanup(customIntervalMs) {
118
+ stopCleanup();
119
+ if (!retentionConfig.enabled || !knex) return;
120
+ if (typeof customIntervalMs === 'number' && customIntervalMs > 0) {
121
+ retentionConfig.intervalMs = customIntervalMs;
122
+ }
123
+
124
+ if (retentionConfig.runOnStart) {
125
+ const delayMs = typeof options.cleanupStartDelayMs === 'number'
126
+ ? options.cleanupStartDelayMs
127
+ : (process.env.NODE_ENV === 'test' ? 50 : 5000);
128
+ cleanupStartTimeout = setTimeout(() => {
129
+ runCleanup();
130
+ }, delayMs);
131
+ if (cleanupStartTimeout && cleanupStartTimeout.unref) {
132
+ cleanupStartTimeout.unref();
133
+ }
134
+ }
135
+
136
+ cleanupInterval = setInterval(() => {
137
+ runCleanup();
138
+ }, retentionConfig.intervalMs);
139
+ if (cleanupInterval && cleanupInterval.unref) {
140
+ cleanupInterval.unref();
141
+ }
142
+ }
143
+
144
+ function stopCleanup() {
145
+ if (cleanupStartTimeout) {
146
+ clearTimeout(cleanupStartTimeout);
147
+ cleanupStartTimeout = null;
148
+ }
149
+ if (cleanupInterval) {
150
+ clearInterval(cleanupInterval);
151
+ cleanupInterval = null;
152
+ }
153
+ }
154
+
58
155
  const registry = new TemplateRegistry();
59
156
 
60
157
  const manifestChunks = emailTemplatesOpt
@@ -81,7 +178,7 @@ function emailPlugin(options = {}) {
81
178
  return {
82
179
  name: 'email',
83
180
  version: '1.0.0',
84
- description: 'MJML + Nodemailer email sending with optional admin UI and auth integration',
181
+ description: 'MJML + Nodemailer email sending with optional admin UI, auth integration, and retention cleanup',
85
182
  dependencies: includeAdminPage ? { 'admin-panel': '*' } : {},
86
183
 
87
184
  api: {
@@ -92,13 +189,29 @@ function emailPlugin(options = {}) {
92
189
  listTemplates: () => registry.list(),
93
190
  verifyConnection: () => emailService.verifyConnection(),
94
191
  queryLogs: (filters) => emailService.queryLogs(filters),
192
+ purge: (opts = {}) => {
193
+ if (!knex) throw new Error('Database is required for purge');
194
+ return purgeEmailLogs(knex, {
195
+ tableName: opts.tableName || tableName,
196
+ days: opts.days !== undefined ? opts.days : (opts.retentionDays !== undefined ? opts.retentionDays : retentionConfig.days),
197
+ olderThan: opts.olderThan,
198
+ ...opts,
199
+ });
200
+ },
95
201
  purgeLogs: (opts = {}) => {
96
202
  if (!knex) throw new Error('Database is required for purgeLogs');
97
203
  return purgeEmailLogs(knex, {
98
204
  tableName: opts.tableName || tableName,
99
205
  olderThan: opts.olderThan,
206
+ days: opts.days !== undefined ? opts.days : (opts.retentionDays !== undefined ? opts.retentionDays : retentionConfig.days),
207
+ ...opts,
100
208
  });
101
209
  },
210
+ startCleanup,
211
+ stopCleanup,
212
+ getRetentionConfig() {
213
+ return { ...retentionConfig };
214
+ },
102
215
  getMigrationTemplate: (name) => generateEmailLogsMigration(name || tableName),
103
216
  isTransportReady: () => emailService.isTransportReady(),
104
217
  loadFromManifest: (chunks) => registry.loadFromManifest(chunks),
@@ -120,6 +233,22 @@ function emailPlugin(options = {}) {
120
233
  }
121
234
  }
122
235
  }
236
+
237
+ if (retentionConfig.enabled && autoCleanupEnabled) {
238
+ startCleanup();
239
+ }
240
+
241
+ return () => {
242
+ stopCleanup();
243
+ };
244
+ },
245
+
246
+ dispose() {
247
+ stopCleanup();
248
+ },
249
+
250
+ shutdown() {
251
+ stopCleanup();
123
252
  },
124
253
 
125
254
  onRoutesReady(ctx) {
@@ -159,10 +288,11 @@ function emailPlugin(options = {}) {
159
288
 
160
289
  adminApi.registerModule({
161
290
  id: 'email',
291
+ title: pageTitle,
162
292
 
163
293
  pages: [{
164
294
  id: 'email',
165
- title: 'Email',
295
+ title: pageTitle,
166
296
  path: '/email',
167
297
  icon: 'mail',
168
298
  component: generateEmailComponent({ apiPrefix }),
@@ -3,24 +3,74 @@
3
3
  * @module plugins/email/purge
4
4
  */
5
5
 
6
+ 'use strict';
7
+
6
8
  /**
7
9
  * @param {import('knex').Knex} knex
8
- * @param {Object} options
10
+ * @param {Object} [options={}]
9
11
  * @param {string} [options.tableName='email_logs']
10
- * @param {Date|string} options.olderThan
11
- * @returns {Promise<number>}
12
+ * @param {Date|string|number} [options.olderThan] - Rows with created_at strictly before this are removed
13
+ * @param {number} [options.days] - Number of days of email logs to keep
14
+ * @param {number} [options.retentionDays=90] - Alias for days
15
+ * @returns {Promise<number>} Deleted row count
12
16
  */
13
- async function purgeEmailLogs(knex, options) {
17
+ async function purgeEmailLogs(knex, options = {}) {
18
+ if (!knex) {
19
+ throw new Error('purgeEmailLogs requires a database (knex) instance');
20
+ }
21
+
14
22
  const tableName = options.tableName || 'email_logs';
15
- const olderThan = options.olderThan instanceof Date
16
- ? options.olderThan
17
- : new Date(options.olderThan);
18
23
 
19
- if (Number.isNaN(olderThan.getTime())) {
20
- throw new Error('purgeEmailLogs: invalid olderThan date');
24
+ let olderThan;
25
+ if (options.olderThan !== undefined) {
26
+ olderThan = options.olderThan instanceof Date
27
+ ? options.olderThan
28
+ : new Date(options.olderThan);
29
+
30
+ if (Number.isNaN(olderThan.getTime())) {
31
+ throw new Error('purgeEmailLogs: invalid olderThan date');
32
+ }
33
+ } else {
34
+ const rawDays = options.days !== undefined ? options.days : (options.retentionDays !== undefined ? options.retentionDays : 90);
35
+ const days = typeof rawDays === 'number' ? rawDays : Number(rawDays);
36
+ if (Number.isNaN(days) || days <= 0) {
37
+ throw new Error('purgeEmailLogs: days must be a positive number');
38
+ }
39
+ olderThan = new Date(Date.now() - days * 24 * 60 * 60 * 1000);
40
+ }
41
+
42
+ let hasTable = true;
43
+ if (knex.schema && typeof knex.schema.hasTable === 'function') {
44
+ try {
45
+ hasTable = await knex.schema.hasTable(tableName);
46
+ } catch {
47
+ hasTable = false;
48
+ }
49
+ }
50
+
51
+ if (!hasTable) {
52
+ return 0;
53
+ }
54
+
55
+ const client = knex?.client?.config?.client;
56
+ const isSqlite = client === 'sqlite3' || client === 'better-sqlite3';
57
+
58
+ let query = knex(tableName);
59
+ if (isSqlite) {
60
+ const iso = olderThan.toISOString();
61
+ const cutoffMs = olderThan.getTime();
62
+ query = query.where((builder) => {
63
+ builder.whereRaw(
64
+ "((typeof(created_at) = 'integer' and created_at < ?) or (typeof(created_at) = 'text' and created_at < ?))",
65
+ [cutoffMs, iso]
66
+ );
67
+ });
68
+ } else {
69
+ query = query.where('created_at', '<', olderThan);
21
70
  }
22
71
 
23
- return knex(tableName).where('created_at', '<', olderThan).delete();
72
+ const deleted = await query.delete();
73
+ return Number(deleted) || 0;
24
74
  }
25
75
 
26
76
  module.exports = {
@@ -569,30 +569,46 @@ function generateFileManagerComponent(options = {}) {
569
569
  var onSelect = opts.onSelect;
570
570
  var accept = opts.accept || '';
571
571
 
572
+ var existing = document.getElementById('file-manager-picker-modal-root');
573
+ if (existing && existing.parentNode) {
574
+ m.mount(existing, null);
575
+ existing.parentNode.removeChild(existing);
576
+ }
577
+
572
578
  var modalContainer = document.createElement('div');
573
579
  modalContainer.id = 'file-manager-picker-modal-root';
574
580
  document.body.appendChild(modalContainer);
575
581
 
576
582
  function cleanup() {
583
+ document.removeEventListener('keydown', onKeyDown);
577
584
  if (modalContainer && modalContainer.parentNode) {
578
585
  m.mount(modalContainer, null);
579
586
  modalContainer.parentNode.removeChild(modalContainer);
580
587
  }
581
588
  }
582
589
 
590
+ function onKeyDown(e) {
591
+ if (e.key === 'Escape') cleanup();
592
+ }
593
+ document.addEventListener('keydown', onKeyDown);
594
+
583
595
  var PickerModalComponent = {
584
596
  view: function() {
585
- return m('div.fixed.inset-0.bg-black/60.flex.items-center.justify-center.z-[9999].p-4.backdrop-blur-sm', [
597
+ return m('div.fixed.inset-0.bg-black/60.flex.items-center.justify-center.z-[9999].p-4.backdrop-blur-sm', {
598
+ onclick: function(e) {
599
+ if (e.target === e.currentTarget) cleanup();
600
+ }
601
+ }, [
586
602
  m('div.bg-white.dark:bg-slate-900.rounded-2xl.shadow-2xl.max-w-4xl.w-full.max-h-[90vh].flex.flex-col.overflow-hidden.border.border-gray-200.dark:border-slate-700', [
587
603
  m('div.flex.items-center.justify-between.p-4.border-b.border-gray-200.dark:border-slate-700.bg-gray-50.dark:bg-slate-800', [
588
- m('h2.text-base.font-bold.text-gray-900.dark:text-slate-100', opts.title || '📁 Ortam Kütüphanesinden Dosya Seç'),
604
+ m('h2.text-base.font-bold.text-gray-900.dark:text-slate-100', opts.title || 'Choose from Media Library'),
589
605
  m('button.text-gray-400.hover:text-gray-600.dark:hover:text-slate-200.text-xl', {
590
606
  onclick: cleanup
591
607
  }, '✕')
592
608
  ]),
593
609
  m('div.p-4.overflow-y-auto.flex-1', [
594
- m(FileManagerView(true, function(selectedUrl) {
595
- if (onSelect) onSelect(selectedUrl);
610
+ m(FileManagerView(true, function(selectedUrl, item) {
611
+ if (onSelect) onSelect(selectedUrl, item);
596
612
  cleanup();
597
613
  }, accept))
598
614
  ])
@@ -92,6 +92,26 @@ function fileManagerPlugin(options = {}) {
92
92
  return;
93
93
  }
94
94
 
95
+ const componentCode = generateFileManagerComponent({
96
+ apiPrefix,
97
+ publicBasePath,
98
+ });
99
+
100
+ // Always configure fileManager in admin settings and register client component
101
+ // so window.__openFileManagerPicker is available across all admin pages (models, records, rich-text)
102
+ if (typeof adminApi.getRegistry === 'function') {
103
+ const registry = adminApi.getRegistry();
104
+ registry.configure({
105
+ fileManager: {
106
+ enabled: true,
107
+ apiPrefix,
108
+ publicBasePath,
109
+ pageTitle,
110
+ },
111
+ });
112
+ registry.registerClientComponent('files', componentCode);
113
+ }
114
+
95
115
  adminApi.registerModule({
96
116
  id: 'files',
97
117
  pages: includePage
@@ -100,10 +120,7 @@ function fileManagerPlugin(options = {}) {
100
120
  title: pageTitle,
101
121
  path: '/files',
102
122
  icon: 'folder',
103
- component: generateFileManagerComponent({
104
- apiPrefix,
105
- publicBasePath,
106
- }),
123
+ component: componentCode,
107
124
  }]
108
125
  : [],
109
126
 
package/plugins/index.js CHANGED
@@ -7,6 +7,8 @@ module.exports = {
7
7
  get sitemapPlugin() { return require('./sitemap'); },
8
8
  get analyticsPlugin() { return require('./analytics'); },
9
9
  get dashboardPlugin() { return require('./dashboard/index'); },
10
+ get devToolbarPlugin() { return require('./dashboard/index').devToolbarPlugin; },
11
+ get devtoolsPlugin() { return require('./dashboard/index').devtoolsPlugin; },
10
12
  get schemaExplorerPlugin() { return require('./schema-explorer'); },
11
13
  get adminPanelPlugin() { return require('./admin-panel'); },
12
14
  get seoCheckerPlugin() { return require('./seo-checker'); },
@@ -14,6 +16,8 @@ module.exports = {
14
16
  get auditLogPlugin() { return require('./audit-log'); },
15
17
  get recaptchaPlugin() { return require('./recaptcha'); },
16
18
  get swaggerPlugin() { return require('./swagger'); },
19
+ get openapiPlugin() { return require('./swagger'); },
20
+ get apiDocsPlugin() { return require('./swagger'); },
17
21
  get healthCheckPlugin() { return require('./health-check'); },
18
22
  get restResourcePlugin() { return require('./rest-resources'); },
19
23
  get ormCacheAdminPlugin() { return require('./orm-cache-admin'); },
@@ -49,6 +53,12 @@ module.exports = {
49
53
  get xlsx() { return require('./xlsx').xlsx; },
50
54
  get csvPlugin() { return require('./csv').csvPlugin; },
51
55
  get csv() { return require('./csv').csv; },
56
+ get oauthPlugin() { return require('./oauth'); },
57
+ get OAuthClient() { return require('./oauth').OAuthClient; },
58
+ get OAuthError() { return require('./oauth').OAuthError; },
59
+ get createOAuthClient() { return require('./oauth').createOAuthClient; },
60
+ get apiKeyPlugin() { return require('./api-key').apiKeyPlugin; },
61
+ get createApiKeyMiddleware() { return require('./api-key').createApiKeyMiddleware; },
52
62
  };
53
63
 
54
64