millas 0.2.12-beta-1 → 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.
- package/package.json +1 -1
- package/src/admin/ActivityLog.js +153 -52
- package/src/admin/Admin.js +400 -167
- package/src/admin/AdminAuth.js +213 -98
- package/src/admin/FormGenerator.js +372 -0
- package/src/admin/HookRegistry.js +256 -0
- package/src/admin/QueryEngine.js +263 -0
- package/src/admin/ViewContext.js +309 -0
- package/src/admin/WidgetRegistry.js +406 -0
- package/src/admin/index.js +17 -0
- package/src/admin/resources/AdminResource.js +383 -97
- package/src/admin/static/admin.css +1341 -0
- package/src/admin/static/date-picker.css +157 -0
- package/src/admin/static/date-picker.js +316 -0
- package/src/admin/static/json-editor.css +649 -0
- package/src/admin/static/json-editor.js +1429 -0
- package/src/admin/static/ui.js +1044 -0
- package/src/admin/views/layouts/base.njk +65 -1013
- package/src/admin/views/pages/detail.njk +40 -16
- package/src/admin/views/pages/form.njk +47 -599
- package/src/admin/views/pages/list.njk +145 -62
- package/src/admin/views/partials/form-field.njk +53 -0
- package/src/admin/views/partials/form-footer.njk +28 -0
- package/src/admin/views/partials/form-readonly.njk +114 -0
- package/src/admin/views/partials/form-scripts.njk +476 -0
- package/src/admin/views/partials/form-widget.njk +296 -0
- package/src/admin/views/partials/json-dialog.njk +80 -0
- package/src/admin/views/partials/json-editor.njk +37 -0
- package/src/admin.zip +0 -0
- package/src/auth/Auth.js +18 -2
- package/src/auth/AuthUser.js +65 -44
- package/src/cli.js +3 -1
- package/src/commands/createsuperuser.js +254 -0
- package/src/commands/lang.js +589 -0
- package/src/commands/migrate.js +154 -81
- package/src/commands/serve.js +1 -0
- package/src/container/AppInitializer.js +65 -8
- package/src/container/MillasApp.js +10 -3
- package/src/container/MillasConfig.js +35 -6
- package/src/core/admin.js +5 -0
- package/src/core/db.js +2 -1
- package/src/core/foundation.js +1 -9
- package/src/core/lang.js +1 -0
- package/src/i18n/I18nServiceProvider.js +91 -0
- package/src/i18n/Translator.js +635 -0
- package/src/i18n/defaults.js +122 -0
- package/src/i18n/index.js +164 -0
- package/src/i18n/locales/en.js +55 -0
- package/src/i18n/locales/sw.js +48 -0
- package/src/logger/formatters/PrettyFormatter.js +101 -65
- package/src/migrations/system/0001_users.js +21 -0
- package/src/migrations/system/0002_admin_log.js +25 -0
- package/src/migrations/system/0003_sessions.js +23 -0
- package/src/orm/fields/index.js +210 -188
- package/src/orm/migration/DefaultValueParser.js +325 -0
- package/src/orm/migration/InteractiveResolver.js +191 -0
- package/src/orm/migration/Makemigrations.js +312 -0
- package/src/orm/migration/MigrationGraph.js +227 -0
- package/src/orm/migration/MigrationRunner.js +202 -108
- package/src/orm/migration/MigrationWriter.js +463 -0
- package/src/orm/migration/ModelInspector.js +143 -74
- package/src/orm/migration/ModelScanner.js +225 -0
- package/src/orm/migration/ProjectState.js +213 -0
- package/src/orm/migration/RenameDetector.js +175 -0
- package/src/orm/migration/SchemaBuilder.js +8 -81
- package/src/orm/migration/operations/base.js +57 -0
- package/src/orm/migration/operations/column.js +191 -0
- package/src/orm/migration/operations/fields.js +252 -0
- package/src/orm/migration/operations/index.js +55 -0
- package/src/orm/migration/operations/models.js +152 -0
- package/src/orm/migration/operations/registry.js +131 -0
- package/src/orm/migration/operations/special.js +51 -0
- package/src/orm/migration/utils.js +208 -0
- package/src/orm/model/Model.js +81 -13
- package/src/providers/AdminServiceProvider.js +66 -9
- package/src/providers/AuthServiceProvider.js +40 -5
- package/src/providers/CacheStorageServiceProvider.js +2 -2
- package/src/providers/DatabaseServiceProvider.js +3 -2
- package/src/providers/LogServiceProvider.js +4 -1
- package/src/providers/MailServiceProvider.js +1 -1
- package/src/providers/QueueServiceProvider.js +1 -1
- package/src/scaffold/templates.js +77 -21
|
@@ -22,10 +22,11 @@ class AuthServiceProvider extends ServiceProvider {
|
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
async boot(container, app) {
|
|
25
|
+
const basePath = container.make('basePath') || process.cwd();
|
|
25
26
|
// Load auth config
|
|
26
27
|
let authConfig;
|
|
27
28
|
try {
|
|
28
|
-
authConfig = require(
|
|
29
|
+
authConfig = require(basePath + '/config/auth');
|
|
29
30
|
} catch {
|
|
30
31
|
authConfig = {
|
|
31
32
|
default: 'jwt',
|
|
@@ -33,12 +34,46 @@ class AuthServiceProvider extends ServiceProvider {
|
|
|
33
34
|
};
|
|
34
35
|
}
|
|
35
36
|
|
|
36
|
-
//
|
|
37
|
-
//
|
|
37
|
+
// ── Resolve the User model ──────────────────────────────────────────────
|
|
38
|
+
//
|
|
39
|
+
// Priority order (mirrors Django's AUTH_USER_MODEL pattern):
|
|
40
|
+
//
|
|
41
|
+
// 1. config/app.js → auth_user: 'User'
|
|
42
|
+
// The model name is looked up in app/models/index.js exports.
|
|
43
|
+
// This is the recommended approach — explicit and refactor-safe.
|
|
44
|
+
//
|
|
45
|
+
// 2. app/models/User.js (default export or named User export)
|
|
46
|
+
// Conventional fallback — works if auth_user is not set and
|
|
47
|
+
// the file exists at the default path.
|
|
48
|
+
//
|
|
49
|
+
// 3. Built-in AuthUser
|
|
50
|
+
// Abstract base class — no table. Used only as a last resort
|
|
51
|
+
// so Auth always has a model to work with during early dev.
|
|
52
|
+
//
|
|
38
53
|
let UserModel;
|
|
39
54
|
try {
|
|
40
|
-
|
|
41
|
-
|
|
55
|
+
// Step 1: read auth_user from config/app.js
|
|
56
|
+
let authUserName = null;
|
|
57
|
+
try {
|
|
58
|
+
const appConfig = require(basePath + '/config/app');
|
|
59
|
+
authUserName = appConfig.auth_user || null;
|
|
60
|
+
} catch { /* config/app.js missing or has no auth_user key */ }
|
|
61
|
+
|
|
62
|
+
if (authUserName) {
|
|
63
|
+
// Resolve by name from app/models/index.js
|
|
64
|
+
const modelsIndex = require(basePath + '/app/models/index');
|
|
65
|
+
const resolved = modelsIndex[authUserName];
|
|
66
|
+
if (!resolved) {
|
|
67
|
+
throw new Error(
|
|
68
|
+
`[AuthServiceProvider] auth_user: '${authUserName}' not found in app/models/index.js.\n` +
|
|
69
|
+
` Available exports: ${Object.keys(modelsIndex).join(', ')}`
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
UserModel = resolved;
|
|
73
|
+
}
|
|
74
|
+
} catch (err) {
|
|
75
|
+
if (err.message.includes('[AuthServiceProvider]')) throw err; // re-throw config errors
|
|
76
|
+
// Step 3: fall back to built-in AuthUser (abstract — no table)
|
|
42
77
|
UserModel = require('../auth/AuthUser');
|
|
43
78
|
}
|
|
44
79
|
|
|
@@ -18,7 +18,7 @@ class CacheServiceProvider extends ServiceProvider {
|
|
|
18
18
|
async boot() {
|
|
19
19
|
let cacheConfig;
|
|
20
20
|
try {
|
|
21
|
-
cacheConfig = require(process.cwd() + '/config/cache');
|
|
21
|
+
cacheConfig = require((container.make('basePath') || process.cwd()) + '/config/cache');
|
|
22
22
|
} catch {
|
|
23
23
|
cacheConfig = {
|
|
24
24
|
default: process.env.CACHE_DRIVER || 'memory',
|
|
@@ -48,7 +48,7 @@ class StorageServiceProvider extends ServiceProvider {
|
|
|
48
48
|
async boot() {
|
|
49
49
|
let storageConfig;
|
|
50
50
|
try {
|
|
51
|
-
storageConfig = require(process.cwd() + '/config/storage');
|
|
51
|
+
storageConfig = require((container.make('basePath') || process.cwd()) + '/config/storage');
|
|
52
52
|
} catch {
|
|
53
53
|
storageConfig = {
|
|
54
54
|
default: process.env.STORAGE_DRIVER || 'local',
|
|
@@ -21,10 +21,11 @@ class DatabaseServiceProvider extends ServiceProvider {
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
async boot(container) {
|
|
24
|
+
const basePath = container.make('basePath') || process.cwd();
|
|
24
25
|
// Load the database config
|
|
25
26
|
let dbConfig;
|
|
26
27
|
try {
|
|
27
|
-
dbConfig = require(
|
|
28
|
+
dbConfig = require(basePath + '/config/database');
|
|
28
29
|
} catch {
|
|
29
30
|
// Fallback for tests / programmatic use
|
|
30
31
|
dbConfig = {
|
|
@@ -42,4 +43,4 @@ class DatabaseServiceProvider extends ServiceProvider {
|
|
|
42
43
|
}
|
|
43
44
|
}
|
|
44
45
|
|
|
45
|
-
module.exports = DatabaseServiceProvider;
|
|
46
|
+
module.exports = DatabaseServiceProvider;
|
|
@@ -59,6 +59,9 @@ class LogServiceProvider extends ServiceProvider {
|
|
|
59
59
|
beforeBoot(container) {
|
|
60
60
|
let config = {};
|
|
61
61
|
try {
|
|
62
|
+
// Note: beforeBoot runs before any container bindings exist.
|
|
63
|
+
// basePath is not yet available — process.cwd() is the correct fallback here.
|
|
64
|
+
// The path will be correct as long as `millas serve` is run from project root.
|
|
62
65
|
config = require(process.cwd() + '/config/logging');
|
|
63
66
|
} catch {
|
|
64
67
|
// No config file — defaults already applied in logger/index.js
|
|
@@ -206,4 +209,4 @@ class LogServiceProvider extends ServiceProvider {
|
|
|
206
209
|
}
|
|
207
210
|
}
|
|
208
211
|
|
|
209
|
-
module.exports = LogServiceProvider;
|
|
212
|
+
module.exports = LogServiceProvider;
|
|
@@ -27,7 +27,7 @@ class MailServiceProvider extends ServiceProvider {
|
|
|
27
27
|
async boot(container) {
|
|
28
28
|
let mailConfig;
|
|
29
29
|
try {
|
|
30
|
-
mailConfig = require(process.cwd() + '/config/mail');
|
|
30
|
+
mailConfig = require((container.make('basePath') || process.cwd()) + '/config/mail');
|
|
31
31
|
} catch {
|
|
32
32
|
mailConfig = {
|
|
33
33
|
default: process.env.MAIL_DRIVER || 'log',
|
|
@@ -29,7 +29,7 @@ class QueueServiceProvider extends ServiceProvider {
|
|
|
29
29
|
async boot(container) {
|
|
30
30
|
let queueConfig;
|
|
31
31
|
try {
|
|
32
|
-
queueConfig = require(process.cwd() + '/config/queue');
|
|
32
|
+
queueConfig = require((container.make('basePath') || process.cwd()) + '/config/queue');
|
|
33
33
|
} catch {
|
|
34
34
|
queueConfig = {
|
|
35
35
|
default: process.env.QUEUE_DRIVER || 'sync',
|
|
@@ -68,21 +68,6 @@ storage/logs/*.log
|
|
|
68
68
|
storage/uploads/*
|
|
69
69
|
!storage/uploads/.gitkeep
|
|
70
70
|
database/database.sqlite
|
|
71
|
-
`,
|
|
72
|
-
|
|
73
|
-
// ─── millas.config.js ─────────────────────────────────────────
|
|
74
|
-
'millas.config.js': `'use strict';
|
|
75
|
-
|
|
76
|
-
module.exports = {
|
|
77
|
-
/*
|
|
78
|
-
|--------------------------------------------------------------------------
|
|
79
|
-
| Millas Framework Configuration
|
|
80
|
-
|--------------------------------------------------------------------------
|
|
81
|
-
*/
|
|
82
|
-
providers: [
|
|
83
|
-
'./providers/AppServiceProvider',
|
|
84
|
-
],
|
|
85
|
-
};
|
|
86
71
|
`,
|
|
87
72
|
|
|
88
73
|
// ─── bootstrap/app.js ─────────────────────────────────────────
|
|
@@ -90,16 +75,30 @@ module.exports = {
|
|
|
90
75
|
|
|
91
76
|
require('dotenv').config();
|
|
92
77
|
|
|
78
|
+
const path = require('path');
|
|
93
79
|
const { Millas } = require('millas');
|
|
94
80
|
const AppServiceProvider = require('../providers/AppServiceProvider');
|
|
95
81
|
|
|
96
|
-
|
|
97
|
-
|
|
82
|
+
/**
|
|
83
|
+
* Application configuration and bootstrap.
|
|
84
|
+
*
|
|
85
|
+
* Millas.configure(__dirname/..) sets the project root so the framework
|
|
86
|
+
* locates config files, models, and routes without guessing.
|
|
87
|
+
*
|
|
88
|
+
* Core providers (Database, Auth, Admin, Cache, Mail, Queue, Events)
|
|
89
|
+
* are wired automatically — only add your own app providers below.
|
|
90
|
+
*
|
|
91
|
+
* First-time setup:
|
|
92
|
+
* millas migrate # creates system tables (users, admin_log, sessions)
|
|
93
|
+
* millas createsuperuser # creates your first admin panel user
|
|
94
|
+
*/
|
|
95
|
+
module.exports = Millas.configure(path.join(__dirname, '..'))
|
|
96
|
+
.withAdmin()
|
|
98
97
|
.routes(Route => {
|
|
99
98
|
require('../routes/web')(Route);
|
|
100
99
|
require('../routes/api')(Route);
|
|
101
100
|
})
|
|
102
|
-
.
|
|
101
|
+
.providers([AppServiceProvider])
|
|
103
102
|
.create();
|
|
104
103
|
`,
|
|
105
104
|
|
|
@@ -153,7 +152,12 @@ module.exports = {
|
|
|
153
152
|
key: process.env.APP_KEY || '',
|
|
154
153
|
debug: process.env.APP_ENV !== 'production',
|
|
155
154
|
timezone: 'UTC',
|
|
156
|
-
locale:
|
|
155
|
+
locale: 'en',
|
|
156
|
+
fallback: 'en',
|
|
157
|
+
|
|
158
|
+
// Set use_i18n: true to enable the translation system.
|
|
159
|
+
// Then run: millas lang:publish <locale>
|
|
160
|
+
use_i18n: false,
|
|
157
161
|
};
|
|
158
162
|
`,
|
|
159
163
|
|
|
@@ -215,6 +219,50 @@ module.exports = {
|
|
|
215
219
|
expiresIn: '1h',
|
|
216
220
|
},
|
|
217
221
|
};
|
|
222
|
+
`,
|
|
223
|
+
|
|
224
|
+
// ─── config/admin.js ──────────────────────────────────────────
|
|
225
|
+
'config/admin.js': `'use strict';
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Admin Panel Configuration
|
|
229
|
+
*
|
|
230
|
+
* Credentials are read from environment variables by default.
|
|
231
|
+
* Set ADMIN_EMAIL and ADMIN_PASSWORD in your .env file, or define
|
|
232
|
+
* static users / a model here.
|
|
233
|
+
*/
|
|
234
|
+
module.exports = {
|
|
235
|
+
// URL prefix for the admin panel
|
|
236
|
+
prefix: '/admin',
|
|
237
|
+
|
|
238
|
+
// Title shown in the browser tab and sidebar
|
|
239
|
+
title: process.env.APP_NAME ? \`\${process.env.APP_NAME} Admin\` : 'Millas Admin',
|
|
240
|
+
|
|
241
|
+
auth: {
|
|
242
|
+
// ── Option 1: static user list (simple setups / local dev) ────
|
|
243
|
+
users: [
|
|
244
|
+
{
|
|
245
|
+
email: process.env.ADMIN_EMAIL || 'admin@example.com',
|
|
246
|
+
// Use a bcrypt hash in production; plain text is fine for local dev.
|
|
247
|
+
password: process.env.ADMIN_PASSWORD || 'change-me',
|
|
248
|
+
name: process.env.ADMIN_NAME || 'Admin',
|
|
249
|
+
},
|
|
250
|
+
],
|
|
251
|
+
|
|
252
|
+
// ── Option 2: model-based lookup ──────────────────────────────
|
|
253
|
+
// Uncomment and set to any Millas Model that has email + password fields.
|
|
254
|
+
// model: require('../app/models/User'),
|
|
255
|
+
|
|
256
|
+
// ── Session cookie settings ───────────────────────────────────
|
|
257
|
+
cookieName: 'millas_admin',
|
|
258
|
+
cookieMaxAge: 60 * 60 * 8, // 8 hours
|
|
259
|
+
rememberAge: 60 * 60 * 24 * 30, // 30 days ("remember me")
|
|
260
|
+
|
|
261
|
+
// ── Brute-force protection ────────────────────────────────────
|
|
262
|
+
maxAttempts: 5,
|
|
263
|
+
lockoutMinutes: 15,
|
|
264
|
+
},
|
|
265
|
+
};
|
|
218
266
|
`,
|
|
219
267
|
|
|
220
268
|
// ─── config/mail.js ───────────────────────────────────────────
|
|
@@ -264,10 +312,18 @@ class AppServiceProvider extends ServiceProvider {
|
|
|
264
312
|
}
|
|
265
313
|
|
|
266
314
|
async boot(container, app) {
|
|
267
|
-
// Register Admin resources
|
|
315
|
+
// Register Admin resources — Admin panel is auto-mounted via .withAdmin()
|
|
268
316
|
// const { Admin } = require('millas');
|
|
317
|
+
// const { AdminResource, AdminField } = require('millas');
|
|
269
318
|
// const Post = require('../app/models/Post');
|
|
270
|
-
//
|
|
319
|
+
//
|
|
320
|
+
// class PostResource extends AdminResource {
|
|
321
|
+
// static model = Post;
|
|
322
|
+
// static label = 'Posts';
|
|
323
|
+
// static searchable = ['title', 'body'];
|
|
324
|
+
// }
|
|
325
|
+
//
|
|
326
|
+
// Admin.register(PostResource);
|
|
271
327
|
}
|
|
272
328
|
}
|
|
273
329
|
|