millas 0.2.12-beta → 0.2.12-beta-2

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 (116) hide show
  1. package/package.json +3 -16
  2. package/src/admin/ActivityLog.js +153 -52
  3. package/src/admin/Admin.js +400 -167
  4. package/src/admin/AdminAuth.js +213 -98
  5. package/src/admin/FormGenerator.js +372 -0
  6. package/src/admin/HookRegistry.js +256 -0
  7. package/src/admin/QueryEngine.js +263 -0
  8. package/src/admin/ViewContext.js +309 -0
  9. package/src/admin/WidgetRegistry.js +406 -0
  10. package/src/admin/index.js +17 -0
  11. package/src/admin/resources/AdminResource.js +383 -97
  12. package/src/admin/static/admin.css +1341 -0
  13. package/src/admin/static/date-picker.css +157 -0
  14. package/src/admin/static/date-picker.js +316 -0
  15. package/src/admin/static/json-editor.css +649 -0
  16. package/src/admin/static/json-editor.js +1429 -0
  17. package/src/admin/static/ui.js +1044 -0
  18. package/src/admin/views/layouts/base.njk +65 -1013
  19. package/src/admin/views/pages/detail.njk +40 -16
  20. package/src/admin/views/pages/form.njk +47 -599
  21. package/src/admin/views/pages/list.njk +145 -62
  22. package/src/admin/views/partials/form-field.njk +53 -0
  23. package/src/admin/views/partials/form-footer.njk +28 -0
  24. package/src/admin/views/partials/form-readonly.njk +114 -0
  25. package/src/admin/views/partials/form-scripts.njk +476 -0
  26. package/src/admin/views/partials/form-widget.njk +296 -0
  27. package/src/admin/views/partials/json-dialog.njk +80 -0
  28. package/src/admin/views/partials/json-editor.njk +37 -0
  29. package/src/admin.zip +0 -0
  30. package/src/auth/Auth.js +31 -10
  31. package/src/auth/AuthController.js +3 -1
  32. package/src/auth/AuthUser.js +119 -0
  33. package/src/cli.js +4 -2
  34. package/src/commands/createsuperuser.js +254 -0
  35. package/src/commands/lang.js +589 -0
  36. package/src/commands/migrate.js +154 -81
  37. package/src/commands/serve.js +82 -110
  38. package/src/container/AppInitializer.js +215 -0
  39. package/src/container/Application.js +278 -253
  40. package/src/container/HttpServer.js +156 -0
  41. package/src/container/MillasApp.js +29 -279
  42. package/src/container/MillasConfig.js +192 -0
  43. package/src/core/admin.js +5 -0
  44. package/src/core/auth.js +9 -0
  45. package/src/core/db.js +9 -0
  46. package/src/core/foundation.js +59 -0
  47. package/src/core/http.js +11 -0
  48. package/src/core/lang.js +1 -0
  49. package/src/core/mail.js +6 -0
  50. package/src/core/queue.js +7 -0
  51. package/src/core/validation.js +29 -0
  52. package/src/facades/Admin.js +1 -1
  53. package/src/facades/Auth.js +22 -39
  54. package/src/facades/Cache.js +21 -10
  55. package/src/facades/Database.js +1 -1
  56. package/src/facades/Events.js +18 -17
  57. package/src/facades/Facade.js +197 -0
  58. package/src/facades/Http.js +42 -45
  59. package/src/facades/Log.js +25 -49
  60. package/src/facades/Mail.js +27 -32
  61. package/src/facades/Queue.js +22 -15
  62. package/src/facades/Storage.js +18 -10
  63. package/src/facades/Url.js +53 -0
  64. package/src/http/HttpClient.js +673 -0
  65. package/src/http/ResponseDispatcher.js +18 -111
  66. package/src/http/UrlGenerator.js +375 -0
  67. package/src/http/WelcomePage.js +273 -0
  68. package/src/http/adapters/ExpressAdapter.js +315 -0
  69. package/src/http/adapters/HttpAdapter.js +168 -0
  70. package/src/http/adapters/index.js +9 -0
  71. package/src/i18n/I18nServiceProvider.js +91 -0
  72. package/src/i18n/Translator.js +635 -0
  73. package/src/i18n/defaults.js +122 -0
  74. package/src/i18n/index.js +164 -0
  75. package/src/i18n/locales/en.js +55 -0
  76. package/src/i18n/locales/sw.js +48 -0
  77. package/src/index.js +5 -144
  78. package/src/logger/formatters/PrettyFormatter.js +103 -57
  79. package/src/logger/internal.js +2 -2
  80. package/src/logger/patchConsole.js +91 -81
  81. package/src/middleware/MiddlewareRegistry.js +62 -82
  82. package/src/migrations/system/0001_users.js +21 -0
  83. package/src/migrations/system/0002_admin_log.js +25 -0
  84. package/src/migrations/system/0003_sessions.js +23 -0
  85. package/src/orm/fields/index.js +210 -188
  86. package/src/orm/migration/DefaultValueParser.js +325 -0
  87. package/src/orm/migration/InteractiveResolver.js +191 -0
  88. package/src/orm/migration/Makemigrations.js +312 -0
  89. package/src/orm/migration/MigrationGraph.js +227 -0
  90. package/src/orm/migration/MigrationRunner.js +202 -108
  91. package/src/orm/migration/MigrationWriter.js +463 -0
  92. package/src/orm/migration/ModelInspector.js +412 -344
  93. package/src/orm/migration/ModelScanner.js +225 -0
  94. package/src/orm/migration/ProjectState.js +213 -0
  95. package/src/orm/migration/RenameDetector.js +175 -0
  96. package/src/orm/migration/SchemaBuilder.js +8 -81
  97. package/src/orm/migration/operations/base.js +57 -0
  98. package/src/orm/migration/operations/column.js +191 -0
  99. package/src/orm/migration/operations/fields.js +252 -0
  100. package/src/orm/migration/operations/index.js +55 -0
  101. package/src/orm/migration/operations/models.js +152 -0
  102. package/src/orm/migration/operations/registry.js +131 -0
  103. package/src/orm/migration/operations/special.js +51 -0
  104. package/src/orm/migration/utils.js +208 -0
  105. package/src/orm/model/Model.js +81 -13
  106. package/src/providers/AdminServiceProvider.js +66 -9
  107. package/src/providers/AuthServiceProvider.js +46 -7
  108. package/src/providers/CacheStorageServiceProvider.js +5 -3
  109. package/src/providers/DatabaseServiceProvider.js +3 -2
  110. package/src/providers/EventServiceProvider.js +2 -1
  111. package/src/providers/LogServiceProvider.js +7 -3
  112. package/src/providers/MailServiceProvider.js +4 -3
  113. package/src/providers/QueueServiceProvider.js +4 -3
  114. package/src/router/Router.js +119 -152
  115. package/src/scaffold/templates.js +83 -26
  116. package/src/facades/Validation.js +0 -69
@@ -0,0 +1,156 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * HttpServer
5
+ *
6
+ * Owns everything that belongs to the process/server layer — the things
7
+ * Express puts in bin/www that have nothing to do with your app logic:
8
+ *
9
+ * - Port normalisation and validation
10
+ * - EADDRINUSE / EACCES error handling with clear messages
11
+ * - Startup log (route count, URL, Ctrl+C hint)
12
+ * - IPC ready signal to the hot-reload proxy (millas serve)
13
+ * - Graceful shutdown on SIGTERM / SIGINT
14
+ *
15
+ * The Application kernel knows nothing about any of this.
16
+ *
17
+ * ── Usage in bootstrap/server.js ────────────────────────────────────────────
18
+ *
19
+ * const app = require('./app'); // configured Millas app, no listen()
20
+ * const server = new HttpServer(app);
21
+ * server.start();
22
+ *
23
+ * ── Advanced ─────────────────────────────────────────────────────────────────
24
+ *
25
+ * new HttpServer(app, {
26
+ * port: 4000,
27
+ * host: '0.0.0.0',
28
+ * onStart: (port, host) => console.log(`up on ${host}:${port}`),
29
+ * onShutdown: () => db.close(),
30
+ * }).start();
31
+ */
32
+ class HttpServer {
33
+ /**
34
+ * @param {import('./Application')} app — booted Millas Application instance
35
+ * @param {object} options
36
+ * @param {number} [options.port]
37
+ * @param {string} [options.host]
38
+ * @param {Function}[options.onStart] — (port, host) => void, called after listen
39
+ * @param {Function}[options.onShutdown] — async () => void, called before process.exit
40
+ */
41
+ constructor(app, options = {}) {
42
+ this._app = app;
43
+ this._options = options;
44
+ }
45
+
46
+ /**
47
+ * Resolve port, boot the server, wire signals.
48
+ * Returns a Promise that resolves once the server is listening.
49
+ */
50
+ async start() {
51
+ const port = this._resolvePort();
52
+ const host = this._options.host
53
+ || process.env.MILLAS_HOST
54
+ || process.env.HOST
55
+ || 'localhost';
56
+
57
+ // Boot providers if not already done
58
+ if (!this._app._booted) {
59
+ await this._app.boot();
60
+ }
61
+
62
+ // Mount routes + fallbacks if not already mounted
63
+ if (!this._app._router) {
64
+ this._app.mount();
65
+ }
66
+
67
+ // Start listening — may throw on EADDRINUSE / EACCES
68
+ try {
69
+ await this._app.listen(port, host);
70
+ } catch (err) {
71
+ this._handleListenError(err, port);
72
+ return; // _handleListenError always exits
73
+ }
74
+
75
+ // Notify the millas serve hot-reload proxy that we're ready
76
+ if (typeof process.send === 'function') {
77
+ process.send({type: 'ready', port});
78
+ }
79
+
80
+ // User callback
81
+ if (typeof this._options.onStart === 'function') {
82
+ this._options.onStart(port, host);
83
+ }
84
+ this._handleSignals();
85
+
86
+ }
87
+
88
+ // ── Private ────────────────────────────────────────────────────────────────
89
+
90
+ _resolvePort() {
91
+ const raw =
92
+ this._options.port ||
93
+ parseInt(process.env.MILLAS_INTERNAL_PORT, 10) ||
94
+ parseInt(process.env.APP_PORT, 10) ||
95
+ parseInt(process.env.PORT, 10) ||
96
+ 3000;
97
+
98
+ return this._normalizePort(raw);
99
+ }
100
+
101
+ _normalizePort(val) {
102
+ const n = parseInt(val, 10);
103
+ if (isNaN(n)) return val; // named pipe — pass through
104
+ if (n >= 0) return n;
105
+ return 3000;
106
+ }
107
+
108
+ _handleListenError(err, port) {
109
+ const bind = typeof port === 'string' ? `pipe ${port}` : `port ${port}`;
110
+
111
+ switch (err.code) {
112
+ case 'EACCES':
113
+ console.error(
114
+ `✖ ${bind} requires elevated privileges.\n` +
115
+ ` Try a port above 1024 or run with sudo.`
116
+ );
117
+ break;
118
+
119
+ case 'EADDRINUSE':
120
+ console.error(
121
+ `✖ ${bind} is already in use.\n` +
122
+ ` Another process is listening on that port.\n` +
123
+ ` Try: APP_PORT=3001 millas serve`
124
+ );
125
+ break;
126
+
127
+ default:
128
+ console.error(`✖ Listen error: ${err.message}`);
129
+ if (process.env.APP_DEBUG) console.error(err.stack + '\n');
130
+ }
131
+
132
+ process.exit(1);
133
+ }
134
+
135
+
136
+ _handleSignals() {
137
+ const shutdown = async (signal) => {
138
+ process.exit(0);
139
+ // process.stdout.write(`\n Shutting down (${signal})…\n`);
140
+ //
141
+ // if (typeof this._options.onShutdown === 'function') {
142
+ // try {
143
+ // await this._options.onShutdown();
144
+ // } catch {
145
+ // }
146
+ // }
147
+ //
148
+ // await this._app.shutdown(0);
149
+ };
150
+
151
+ process.once('SIGTERM', () => shutdown("SIGTERM"));
152
+ process.once('SIGINT', () => shutdown('SIGINT'));
153
+ }
154
+ }
155
+
156
+ module.exports = HttpServer;
@@ -1,299 +1,49 @@
1
1
  'use strict';
2
2
 
3
- const express = require('express');
4
- const Application = require('./Application');
3
+ const MillasConfig = require('./MillasConfig');
5
4
 
6
5
  /**
7
- * MillasApp
8
- *
9
- * A clean factory wrapper around Application that wires up Express,
10
- * core providers, routes, and the admin panel automatically.
11
- *
12
- * Reduces bootstrap/app.js from ~60 lines to ~8.
13
- *
14
- * ── Usage ───────────────────────────────────────────────────────────────────
6
+ * Millas
7
+
8
+ * ── bootstrap/app.js ────────────────────────────────────────────────────────
15
9
  *
16
- * require('dotenv').config();
17
- * const { MillasApp } = require('millas');
18
- * const AppServiceProvider = require('../providers/AppServiceProvider');
10
+ * const { Millas } = require('millas');
19
11
  *
20
- * const app = MillasApp.create()
12
+ * module.exports = Millas.config()
21
13
  * .providers([AppServiceProvider])
22
14
  * .routes(Route => {
23
15
  * require('../routes/web')(Route);
24
16
  * require('../routes/api')(Route);
25
17
  * })
26
- * .withAdmin();
27
- *
28
- * module.exports = app.start();
29
- *
30
- * ── Escape hatches ──────────────────────────────────────────────────────────
31
- *
32
- * // Access the raw Express app
33
- * app.express.use(someExpressMiddleware());
34
- *
35
- * // Access the DI container
36
- * app.container.make('db');
37
- *
38
- * // Access the underlying Application kernel
39
- * app.kernel
18
+ * .withAdmin()
19
+ * .create();
40
20
  *
41
- * ── Advanced ────────────────────────────────────────────────────────────────
21
+ * That is everything a developer writes. The rest is handled internally.
42
22
  *
43
- * MillasApp.create({
44
- * // Disable a core provider
45
- * mail: false,
46
- * queue: false,
23
+ * Millas.config() → MillasConfig (chainable, collects config only)
24
+ * .create() → MillasInstance (sealed carrier, no callable methods)
47
25
  *
48
- * // Custom admin prefix
49
- * admin: { prefix: '/cms', title: 'My CMS' },
50
- *
51
- * // Add Express middleware before routes
52
- * expressMiddleware: [cors(), helmet()],
53
- *
54
- * // Called once the app is listening
55
- * onStart: (port, host) => console.log(`Running on ${host}:${port}`),
56
- * })
26
+ * The framework's AppInitialiser receives the MillasInstance, reads its
27
+ * config, and boots the full application — adapter, kernel, providers,
28
+ * routes, admin, HTTP server — without the developer being involved.
57
29
  */
58
- class MillasApp {
59
-
60
- // ─── Factory ──────────────────────────────────────────────────────────────
61
-
62
- /**
63
- * Create a new MillasApp instance.
64
- * @param {object} [options]
65
- * @param {boolean} [options.database=true] — register DatabaseServiceProvider
66
- * @param {boolean} [options.cache=true] — register CacheServiceProvider
67
- * @param {boolean} [options.storage=true] — register StorageServiceProvider
68
- * @param {boolean} [options.mail=true] — register MailServiceProvider
69
- * @param {boolean} [options.queue=true] — register QueueServiceProvider
70
- * @param {boolean} [options.events=true] — register EventServiceProvider
71
- * @param {boolean} [options.logging=true] — register LogServiceProvider
72
- * @param {Array} [options.expressMiddleware] — Express middleware applied before routes
73
- * @param {Function}[options.onStart] — callback(port, host) after listen
74
- */
75
- static create(options = {}) {
76
- return new MillasApp(options);
77
- }
78
-
79
- constructor(options = {}) {
80
- this._options = options;
81
- this._userProviders = [];
82
- this._routesCb = null;
83
- this._adminOptions = null; // null = no admin; object/true = mount admin
84
- this._expressApp = null;
85
- this._kernel = null;
86
- this._started = false;
87
- }
88
-
89
- // ─── Fluent API ───────────────────────────────────────────────────────────
90
-
91
- /**
92
- * Register application service providers.
93
- *
94
- * .providers([AppServiceProvider, PaymentServiceProvider])
95
- */
96
- providers(list = []) {
97
- this._userProviders.push(...list);
98
- return this;
99
- }
100
-
101
- /**
102
- * Define application routes.
103
- *
104
- * .routes(Route => {
105
- * require('../routes/web')(Route);
106
- * require('../routes/api')(Route);
107
- * })
108
- */
109
- routes(callback) {
110
- this._routesCb = callback;
111
- return this;
112
- }
113
-
114
- /**
115
- * Register a named middleware alias.
116
- * Must be called before start().
117
- *
118
- * .middleware('verified', EmailVerifiedMiddleware)
119
- */
120
- middleware(alias, handler) {
121
- if (!this._pendingMiddleware) this._pendingMiddleware = [];
122
- this._pendingMiddleware.push({ alias, handler });
123
- return this;
124
- }
125
-
126
- /**
127
- * Mount the admin panel.
128
- *
129
- * .withAdmin() // default /admin
130
- * .withAdmin({ prefix: '/cms' }) // custom prefix
131
- * .withAdmin({ prefix: '/admin', auth: { users: [...] } })
132
- */
133
- withAdmin(options = {}) {
134
- this._adminOptions = options;
135
- return this;
136
- }
137
-
138
- // ─── Start ────────────────────────────────────────────────────────────────
139
-
30
+ const Millas = {
140
31
  /**
141
- * Boot all providers, mount routes, and start listening.
142
- * Returns an object with { app, expressApp, route } for module.exports.
32
+ * Start building an application config.
33
+ * Equivalent to Millas.config().configure(basePath).
143
34
  *
144
- * Safe to await if you need to run code after boot:
145
- * const { app } = await MillasApp.create()...start();
146
- */
147
- start() {
148
- // Build Express + Application kernel
149
- this._expressApp = express();
150
- this._expressApp.use(express.json());
151
- this._expressApp.use(express.urlencoded({ extended: true }));
152
-
153
- // Apply any extra Express middleware (e.g. helmet, cors)
154
- for (const mw of (this._options.expressMiddleware || [])) {
155
- this._expressApp.use(mw);
156
- }
157
-
158
- this._kernel = new Application(this._expressApp);
159
-
160
- // Register pending middleware aliases
161
- for (const { alias, handler } of (this._pendingMiddleware || [])) {
162
- this._kernel.middleware(alias, handler);
163
- }
164
-
165
- // Register core providers (auto, unless disabled)
166
- const coreProviders = this._buildCoreProviders();
167
- this._kernel.providers([...coreProviders, ...this._userProviders]);
168
-
169
- // Register routes
170
- if (this._routesCb) {
171
- this._kernel.routes(this._routesCb);
172
- }
173
-
174
- // Boot asynchronously
175
- const self = this;
176
- const boot = (async () => {
177
- await self._kernel.boot();
178
-
179
- if (!process.env.MILLAS_ROUTE_LIST) {
180
- self._kernel.mountRoutes();
181
-
182
- // Admin panel (mounted between routes and fallbacks)
183
- if (self._adminOptions !== null) {
184
- const adminOpts = typeof self._adminOptions === 'object'
185
- ? self._adminOptions
186
- : {};
187
-
188
- try {
189
- const Admin = require('../admin/Admin');
190
- if (Object.keys(adminOpts).length) {
191
- Admin.configure(adminOpts);
192
- }
193
- Admin.mount(self._expressApp);
194
- } catch (err) {
195
- process.stderr.write(`[millas] Admin mount failed: ${err.message}\n`);
196
- }
197
- }
198
-
199
- self._kernel.mountFallbacks();
200
-
201
- const onStart = self._options.onStart || null;
202
- self._kernel.listen(undefined, undefined, onStart || undefined);
203
- }
204
-
205
- self._started = true;
206
- })();
207
-
208
- // Expose the promise for testing / programmatic use
209
- this._bootPromise = boot;
210
-
211
- return this;
212
- }
213
-
214
- /**
215
- * Await the boot promise. Useful in tests or scripts.
35
+ * Usage (bootstrap/app.js):
36
+ * module.exports = Millas.configure(__dirname)
37
+ * .withAdmin()
38
+ * .routes(Route => { ... })
39
+ * .create();
216
40
  *
217
- * const app = await MillasApp.create().routes(...).start().ready();
41
+ * @param {string} basePath — pass __dirname from bootstrap/app.js
42
+ * @returns {MillasConfig}
218
43
  */
219
- async ready() {
220
- await (this._bootPromise || Promise.resolve());
221
- return this;
222
- }
223
-
224
- // ─── Escape hatches ───────────────────────────────────────────────────────
225
-
226
- /** The raw Express application instance. */
227
- get express() { return this._expressApp; }
228
-
229
- /** The underlying Application kernel (also accessible as .app for back-compat). */
230
- get kernel() { return this._kernel; }
231
- get app() { return this._kernel; }
232
-
233
- /** The DI container. */
234
- get container() { return this._kernel?._container; }
235
-
236
- /** The Route instance — used by route:list command. */
237
- get route() { return this._kernel?._route; }
238
-
239
- /**
240
- * The raw Express app — backward-compatible alias.
241
- * Allows: const { expressApp } = require('./bootstrap/app')
242
- */
243
- get expressApp() { return this._expressApp; }
244
-
245
- // ─── Internal ─────────────────────────────────────────────────────────────
246
-
247
- _buildCoreProviders() {
248
- const opts = this._options;
249
- const providers = [];
250
-
251
- // Helper — require a provider, silently skip if not found
252
- const load = (path) => {
253
- try { return require(path); } catch { return null; }
254
- };
255
-
256
- // Logging — first so all other providers can use Log
257
- if (opts.logging !== false) {
258
- const p = load('../providers/LogServiceProvider');
259
- if (p) providers.push(p);
260
- }
261
-
262
- // Database
263
- if (opts.database !== false) {
264
- const p = load('../providers/DatabaseServiceProvider');
265
- if (p) providers.push(p);
266
- }
267
-
268
- // Cache + Storage
269
- if (opts.cache !== false || opts.storage !== false) {
270
- const p = load('../providers/CacheStorageServiceProvider');
271
- if (p) {
272
- if (opts.cache !== false && p.CacheServiceProvider) providers.push(p.CacheServiceProvider);
273
- if (opts.storage !== false && p.StorageServiceProvider) providers.push(p.StorageServiceProvider);
274
- }
275
- }
276
-
277
- // Mail
278
- if (opts.mail !== false) {
279
- const p = load('../providers/MailServiceProvider');
280
- if (p) providers.push(p);
281
- }
282
-
283
- // Queue
284
- if (opts.queue !== false) {
285
- const p = load('../providers/QueueServiceProvider');
286
- if (p) providers.push(p);
287
- }
288
-
289
- // Events
290
- if (opts.events !== false) {
291
- const p = load('../providers/EventServiceProvider');
292
- if (p) providers.push(p);
293
- }
294
-
295
- return providers;
296
- }
297
- }
44
+ configure(basePath) {
45
+ return new MillasConfig().configure(basePath);
46
+ },
47
+ };
298
48
 
299
- module.exports = MillasApp;
49
+ module.exports = Millas;
@@ -0,0 +1,192 @@
1
+ 'use strict';
2
+
3
+ const AppInitializer = require("./AppInitializer");
4
+
5
+ /**
6
+ * MillasConfig
7
+ *
8
+ * A pure config collector — no side effects, no HTTP, no booting.
9
+ * Every method returns `this` for chaining.
10
+ * The chain ends with .create() which seals the config into a MillasInstance.
11
+ *
12
+ * ── Usage (bootstrap/app.js) ─────────────────────────────────────────────────
13
+ *
14
+ * const { Millas } = require('millas');
15
+ *
16
+ * module.exports = Millas.config()
17
+ * .providers([AppServiceProvider])
18
+ * .routes(Route => {
19
+ * require('../routes/web')(Route);
20
+ * require('../routes/api')(Route);
21
+ * })
22
+ * .withAdmin()
23
+ * .create();
24
+ */
25
+ class MillasConfig {
26
+ constructor() {
27
+ this._config = {
28
+ // Absolute path to the project root — passed to all providers
29
+ // so they never need to call process.cwd() at runtime.
30
+ // Set via .configure(__dirname) in bootstrap/app.js.
31
+ basePath: null,
32
+
33
+ // Service providers
34
+ providers: [],
35
+
36
+ // Route registration callback: (Route) => void
37
+ routes: null,
38
+
39
+ // Named middleware aliases: [{ alias, handler }]
40
+ middleware: [],
41
+
42
+ // Core service toggles
43
+ logging: true,
44
+ database: true,
45
+ auth: true, // AuthServiceProvider — always on by default
46
+ cache: true,
47
+ storage: true,
48
+ mail: true,
49
+ queue: true,
50
+ events: true,
51
+
52
+ // Admin panel — null means disabled, {} or options object means enabled
53
+ admin: null,
54
+
55
+ // Raw adapter-level middleware (e.g. helmet, compression)
56
+ adapterMiddleware: [],
57
+
58
+ // Lifecycle callbacks
59
+ onStart: null,
60
+ onShutdown: null,
61
+ };
62
+ }
63
+
64
+ // ── Chainable config methods ───────────────────────────────────────────────
65
+
66
+ /**
67
+ * Set the application base path. Must be the first call.
68
+ * Pass __dirname from bootstrap/app.js — Laravel style.
69
+ *
70
+ * Millas.configure(__dirname)
71
+ *
72
+ * All providers use this to locate config files, models, and routes
73
+ * without relying on process.cwd() at runtime.
74
+ *
75
+ * @param {string} basePath — absolute path to the project root
76
+ */
77
+ configure(basePath) {
78
+ this._config.basePath = basePath;
79
+ return this;
80
+ }
81
+
82
+ /**
83
+ * Register application service providers.
84
+ *
85
+ * .providers([AppServiceProvider, PaymentServiceProvider])
86
+ */
87
+ providers(list = []) {
88
+ this._config.providers.push(...list);
89
+ return this;
90
+ }
91
+
92
+ /**
93
+ * Register application routes.
94
+ *
95
+ * .routes(Route => {
96
+ * require('../routes/web')(Route);
97
+ * require('../routes/api')(Route);
98
+ * })
99
+ */
100
+ routes(callback) {
101
+ this._config.routes = callback;
102
+ return this;
103
+ }
104
+
105
+ /**
106
+ * Register a named middleware alias.
107
+ *
108
+ * .middleware('verified', EmailVerifiedMiddleware)
109
+ */
110
+ middleware(alias, handler) {
111
+ this._config.middleware.push({alias, handler});
112
+ return this;
113
+ }
114
+
115
+ /**
116
+ * Enable the admin panel.
117
+ *
118
+ * AuthServiceProvider and AdminServiceProvider are registered
119
+ * automatically — no need to add them to .providers([]).
120
+ *
121
+ * .withAdmin()
122
+ * .withAdmin({ prefix: '/cms', title: 'My CMS' })
123
+ *
124
+ * First-time setup:
125
+ * millas migrate # creates users + admin_log + sessions tables
126
+ * millas createsuperuser # creates your first admin user
127
+ */
128
+ withAdmin(options = {}) {
129
+ this._config.admin = options;
130
+ return this;
131
+ }
132
+
133
+ /**
134
+ * Disable individual core services.
135
+ *
136
+ * .disable('mail', 'queue')
137
+ */
138
+ disable(...services) {
139
+ for (const svc of services) {
140
+ if (svc in this._config) this._config[svc] = false;
141
+ }
142
+ return this;
143
+ }
144
+
145
+ /**
146
+ * Apply raw adapter-level middleware (e.g. helmet, compression).
147
+ * These are applied before any Millas routes.
148
+ *
149
+ * .use(helmet())
150
+ * .use(compression())
151
+ */
152
+ use(...fns) {
153
+ this._config.adapterMiddleware.push(...fns);
154
+ return this;
155
+ }
156
+
157
+ /**
158
+ * Called once the server is listening.
159
+ *
160
+ * .onStart((port, host) => console.log(`up on ${host}:${port}`))
161
+ */
162
+ onStart(fn) {
163
+ this._config.onStart = fn;
164
+ return this;
165
+ }
166
+
167
+ /**
168
+ * Called before graceful shutdown.
169
+ *
170
+ * .onShutdown(async () => db.close())
171
+ */
172
+ onShutdown(fn) {
173
+ this._config.onShutdown = fn;
174
+ return this;
175
+ }
176
+
177
+ // ── Terminal method ────────────────────────────────────────────────────────
178
+
179
+ /**
180
+ *
181
+ *
182
+ * module.exports = Millas.config()
183
+ * .providers([AppServiceProvider])
184
+ * .routes(...)
185
+ * .create();
186
+ */
187
+ async create() {
188
+ return (new AppInitializer(Object.freeze({...this._config}))).boot();
189
+ }
190
+ }
191
+
192
+ module.exports = MillasConfig;
@@ -0,0 +1,5 @@
1
+ // ── Admin ─────────────────────────────────────────────────────────
2
+ const {Admin, AdminResource, AdminField, AdminFilter, AdminHooks, AdminInline} = require('../admin');
3
+ module.exports = {
4
+ Admin, AdminResource, AdminField, AdminFilter, AdminHooks, AdminInline
5
+ }
@@ -0,0 +1,9 @@
1
+ const AuthUser = require("../auth/AuthUser");
2
+ const JwtDriver = require("../auth/JwtDriver");
3
+ const AuthMiddleware = require("../auth/AuthMiddleware");
4
+ const RoleMiddleware = require("../auth/RoleMiddleware");
5
+ const AuthController = require("../auth/AuthController");
6
+ module.exports = {
7
+ AuthUser, JwtDriver, AuthMiddleware, RoleMiddleware,
8
+ AuthController,
9
+ }