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,168 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * HttpAdapter
5
+ *
6
+ * Abstract interface between the Millas kernel and any underlying HTTP engine.
7
+ * The kernel never imports Express (or Fastify, or Hono) directly — it only
8
+ * calls the methods defined here.
9
+ *
10
+ * To add a new HTTP engine, create a class that extends HttpAdapter and
11
+ * implements every method. The kernel works unchanged.
12
+ *
13
+ * ── Implemented by ───────────────────────────────────────────────────────────
14
+ *
15
+ * ExpressAdapter (default, ships with Millas)
16
+ * FastifyAdapter (future)
17
+ * HonoAdapter (future)
18
+ *
19
+ * ── Lifecycle ────────────────────────────────────────────────────────────────
20
+ *
21
+ * 1. adapter.applyBodyParsers() — JSON + urlencoded
22
+ * 2. adapter.applyMiddleware(fn) — any raw adapter-level middleware
23
+ * 3. adapter.mountRoute(verb, path, handlers) — register app routes
24
+ * 4. adapter.mountWelcome(handler) — optional dev welcome page
25
+ * 5. adapter.mountNotFound() — 404 handler
26
+ * 6. adapter.mountErrorHandler() — global error handler
27
+ * 7. await adapter.listen(port, host) — start accepting connections
28
+ * 8. adapter.close() — graceful shutdown
29
+ */
30
+ class HttpAdapter {
31
+
32
+ // ── Setup ──────────────────────────────────────────────────────────────────
33
+
34
+ /**
35
+ * Apply JSON + urlencoded body parsers.
36
+ * Called once during bootstrap, before any routes are mounted.
37
+ */
38
+ applyBodyParsers() {
39
+ throw new Error(`${this.constructor.name} must implement applyBodyParsers()`);
40
+ }
41
+
42
+ /**
43
+ * Apply a single raw middleware function at the adapter level.
44
+ * Used for things like helmet(), compression() that are engine-specific.
45
+ *
46
+ * @param {Function} fn — adapter-native middleware function
47
+ */
48
+ applyMiddleware(fn) {
49
+ throw new Error(`${this.constructor.name} must implement applyMiddleware(fn)`);
50
+ }
51
+
52
+ // ── Route mounting ─────────────────────────────────────────────────────────
53
+
54
+ /**
55
+ * Register a route handler.
56
+ *
57
+ * @param {string} verb — 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS'
58
+ * @param {string} path — e.g. '/users/:id'
59
+ * @param {Function[]} handlers — [middleware..., terminalHandler]
60
+ * Each handler is a Millas kernel handler
61
+ * (expressReq, expressRes, expressNext) already
62
+ * converted by the adapter's wrapKernelHandler().
63
+ */
64
+ mountRoute(verb, path, handlers) {
65
+ throw new Error(`${this.constructor.name} must implement mountRoute(verb, path, handlers)`);
66
+ }
67
+
68
+ /**
69
+ * Mount the dev welcome page for GET /.
70
+ * Only called when no user route covers GET /.
71
+ *
72
+ * @param {Function} handler — adapter-native handler function
73
+ */
74
+ mountWelcome(handler) {
75
+ throw new Error(`${this.constructor.name} must implement mountWelcome(handler)`);
76
+ }
77
+
78
+ /**
79
+ * Mount the 404 fallback handler.
80
+ * Must be called AFTER all routes and mountWelcome().
81
+ */
82
+ mountNotFound() {
83
+ throw new Error(`${this.constructor.name} must implement mountNotFound()`);
84
+ }
85
+
86
+ /**
87
+ * Mount the global error handler.
88
+ * Must be called LAST — after mountNotFound().
89
+ */
90
+ mountErrorHandler() {
91
+ throw new Error(`${this.constructor.name} must implement mountErrorHandler()`);
92
+ }
93
+
94
+ // ── Request / Response bridge ──────────────────────────────────────────────
95
+
96
+ /**
97
+ * Wrap a Millas kernel handler function into an adapter-native handler.
98
+ *
99
+ * The kernel handler signature is:
100
+ * (millaCtx: RequestContext, trackedNext: Function) => Promise<MillasResponse>
101
+ *
102
+ * The adapter wraps this into whatever its native handler signature is,
103
+ * e.g. (req, res, next) for Express.
104
+ *
105
+ * @param {Function} kernelFn
106
+ * @param {string} displayName — for error messages
107
+ * @param {object} container — DI container
108
+ * @returns {Function} adapter-native handler
109
+ */
110
+ wrapKernelHandler(kernelFn, displayName, container) {
111
+ throw new Error(`${this.constructor.name} must implement wrapKernelHandler()`);
112
+ }
113
+
114
+ /**
115
+ * Wrap a Millas middleware instance into an adapter-native handler.
116
+ *
117
+ * @param {object} instance — Millas Middleware instance with handle(ctx, next)
118
+ * @param {object} container — DI container
119
+ * @returns {Function} adapter-native handler
120
+ */
121
+ wrapMiddleware(instance, container) {
122
+ throw new Error(`${this.constructor.name} must implement wrapMiddleware()`);
123
+ }
124
+
125
+ /**
126
+ * Dispatch a MillasResponse to the underlying engine's response object.
127
+ *
128
+ * @param {MillasResponse} response
129
+ * @param {*} nativeRes — e.g. Express res
130
+ */
131
+ dispatch(response, nativeRes) {
132
+ throw new Error(`${this.constructor.name} must implement dispatch(response, nativeRes)`);
133
+ }
134
+
135
+ // ── Server lifecycle ───────────────────────────────────────────────────────
136
+
137
+ /**
138
+ * Start listening on port/host.
139
+ * Returns a Promise that resolves once the server is bound.
140
+ *
141
+ * @param {number} port
142
+ * @param {string} host
143
+ * @returns {Promise<void>}
144
+ */
145
+ listen(port, host) {
146
+ throw new Error(`${this.constructor.name} must implement listen(port, host)`);
147
+ }
148
+
149
+ /**
150
+ * Gracefully close the server.
151
+ * Returns a Promise that resolves once all connections are drained.
152
+ *
153
+ * @returns {Promise<void>}
154
+ */
155
+ close() {
156
+ throw new Error(`${this.constructor.name} must implement close()`);
157
+ }
158
+
159
+ /**
160
+ * The name of this adapter, used in logs and error messages.
161
+ * @returns {string}
162
+ */
163
+ get name() {
164
+ return this.constructor.name;
165
+ }
166
+ }
167
+
168
+ module.exports = HttpAdapter;
@@ -0,0 +1,9 @@
1
+ 'use strict';
2
+
3
+ const HttpAdapter = require('./HttpAdapter');
4
+ const ExpressAdapter = require('./ExpressAdapter');
5
+
6
+ module.exports = {
7
+ HttpAdapter,
8
+ ExpressAdapter,
9
+ };
@@ -0,0 +1,91 @@
1
+ 'use strict';
2
+
3
+ const path = require('path');
4
+ const fs = require('fs');
5
+ const ServiceProvider = require('../providers/ServiceProvider');
6
+ const Translator = require('./Translator');
7
+
8
+ /**
9
+ * I18nServiceProvider
10
+ *
11
+ * Boots the translation system and registers the Trans singleton
12
+ * into the DI container.
13
+ *
14
+ * ── Setup in bootstrap/app.js ─────────────────────────────────────────────
15
+ *
16
+ * const { Millas } = require('millas');
17
+ * const I18nServiceProvider = require('millas/src/i18n/I18nServiceProvider');
18
+ *
19
+ * module.exports = Millas.config()
20
+ * .providers([I18nServiceProvider, AppServiceProvider])
21
+ * .create();
22
+ *
23
+ * ── config/app.js ─────────────────────────────────────────────────────────
24
+ *
25
+ * module.exports = {
26
+ * locale: 'en', // default locale
27
+ * fallback: 'en', // fallback when translation missing
28
+ * };
29
+ *
30
+ * ── lang/ directory ───────────────────────────────────────────────────────
31
+ *
32
+ * Place translation files at <basePath>/lang/:
33
+ *
34
+ * lang/
35
+ * en.js ← source language
36
+ * sw.js ← Swahili
37
+ * fr.js ← French
38
+ *
39
+ * ── Route-level locale switching ──────────────────────────────────────────
40
+ *
41
+ * Use the built-in middleware to auto-detect locale from requests:
42
+ *
43
+ * const { Trans } = require('millas/src/i18n');
44
+ * app.use(Trans.middleware());
45
+ *
46
+ * Or manually in a route:
47
+ * Trans.setLocale('sw');
48
+ */
49
+ class I18nServiceProvider extends ServiceProvider {
50
+
51
+ register(container) {
52
+ // Register the Trans singleton into the DI container
53
+ const trans = require('./index').Trans;
54
+ container.instance('trans', trans);
55
+ container.instance('Trans', trans);
56
+ container.alias('i18n', 'trans');
57
+ }
58
+
59
+ async boot(container, app) {
60
+ const basePath = container.make('basePath') || process.cwd();
61
+ const trans = container.make('trans');
62
+
63
+ // Load config/app.js for locale settings
64
+ let locale = 'en';
65
+ let fallback = 'en';
66
+ let warnMissing = process.env.NODE_ENV !== 'production';
67
+
68
+ try {
69
+ const appConfig = require(path.join(basePath, 'config/app'));
70
+ if (appConfig.locale) locale = appConfig.locale;
71
+ if (appConfig.fallback) fallback = appConfig.fallback;
72
+ } catch { /* config/app.js not found or no locale keys */ }
73
+
74
+ // Lang path: <basePath>/lang/
75
+ const langPath = path.join(basePath, 'lang');
76
+
77
+ trans.configure({ locale, fallback, langPath, warnMissing });
78
+
79
+ // Log available locales on startup in debug mode
80
+ if (process.env.DEBUG || process.env.NODE_ENV === 'development') {
81
+ const available = trans.availableLocales();
82
+ if (available.length > 0 && !(available.length === 1 && available[0] === 'en')) {
83
+ process.stdout.write(
84
+ `[i18n] Locale: ${locale} | Fallback: ${fallback} | Available: ${available.join(', ')}\n`
85
+ );
86
+ }
87
+ }
88
+ }
89
+ }
90
+
91
+ module.exports = I18nServiceProvider;