millas 0.1.0
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/LICENSE +21 -0
- package/README.md +137 -0
- package/bin/millas.js +6 -0
- package/package.json +56 -0
- package/src/admin/Admin.js +617 -0
- package/src/admin/index.js +13 -0
- package/src/admin/resources/AdminResource.js +317 -0
- package/src/auth/Auth.js +254 -0
- package/src/auth/AuthController.js +188 -0
- package/src/auth/AuthMiddleware.js +67 -0
- package/src/auth/Hasher.js +51 -0
- package/src/auth/JwtDriver.js +74 -0
- package/src/auth/RoleMiddleware.js +44 -0
- package/src/cache/Cache.js +231 -0
- package/src/cache/drivers/FileDriver.js +152 -0
- package/src/cache/drivers/MemoryDriver.js +158 -0
- package/src/cache/drivers/NullDriver.js +27 -0
- package/src/cache/index.js +8 -0
- package/src/cli.js +27 -0
- package/src/commands/make.js +61 -0
- package/src/commands/migrate.js +174 -0
- package/src/commands/new.js +50 -0
- package/src/commands/queue.js +92 -0
- package/src/commands/route.js +93 -0
- package/src/commands/serve.js +50 -0
- package/src/container/Application.js +177 -0
- package/src/container/Container.js +281 -0
- package/src/container/index.js +13 -0
- package/src/controller/Controller.js +367 -0
- package/src/errors/HttpError.js +29 -0
- package/src/events/Event.js +39 -0
- package/src/events/EventEmitter.js +151 -0
- package/src/events/Listener.js +46 -0
- package/src/events/index.js +15 -0
- package/src/index.js +93 -0
- package/src/mail/Mail.js +210 -0
- package/src/mail/MailMessage.js +196 -0
- package/src/mail/TemplateEngine.js +150 -0
- package/src/mail/drivers/LogDriver.js +36 -0
- package/src/mail/drivers/MailgunDriver.js +84 -0
- package/src/mail/drivers/SendGridDriver.js +97 -0
- package/src/mail/drivers/SmtpDriver.js +67 -0
- package/src/mail/index.js +19 -0
- package/src/middleware/AuthMiddleware.js +46 -0
- package/src/middleware/CorsMiddleware.js +59 -0
- package/src/middleware/LogMiddleware.js +61 -0
- package/src/middleware/Middleware.js +36 -0
- package/src/middleware/MiddlewarePipeline.js +94 -0
- package/src/middleware/ThrottleMiddleware.js +61 -0
- package/src/orm/drivers/DatabaseManager.js +135 -0
- package/src/orm/fields/index.js +132 -0
- package/src/orm/index.js +19 -0
- package/src/orm/migration/MigrationRunner.js +216 -0
- package/src/orm/migration/ModelInspector.js +338 -0
- package/src/orm/migration/SchemaBuilder.js +173 -0
- package/src/orm/model/Model.js +371 -0
- package/src/orm/query/QueryBuilder.js +197 -0
- package/src/providers/AdminServiceProvider.js +40 -0
- package/src/providers/AuthServiceProvider.js +53 -0
- package/src/providers/CacheStorageServiceProvider.js +71 -0
- package/src/providers/DatabaseServiceProvider.js +45 -0
- package/src/providers/EventServiceProvider.js +34 -0
- package/src/providers/MailServiceProvider.js +51 -0
- package/src/providers/ProviderRegistry.js +82 -0
- package/src/providers/QueueServiceProvider.js +52 -0
- package/src/providers/ServiceProvider.js +45 -0
- package/src/queue/Job.js +135 -0
- package/src/queue/Queue.js +147 -0
- package/src/queue/drivers/DatabaseDriver.js +194 -0
- package/src/queue/drivers/SyncDriver.js +72 -0
- package/src/queue/index.js +16 -0
- package/src/queue/workers/QueueWorker.js +140 -0
- package/src/router/MiddlewareRegistry.js +82 -0
- package/src/router/Route.js +255 -0
- package/src/router/RouteGroup.js +19 -0
- package/src/router/RouteRegistry.js +55 -0
- package/src/router/Router.js +138 -0
- package/src/router/index.js +15 -0
- package/src/scaffold/generator.js +34 -0
- package/src/scaffold/maker.js +272 -0
- package/src/scaffold/templates.js +350 -0
- package/src/storage/Storage.js +170 -0
- package/src/storage/drivers/LocalDriver.js +215 -0
- package/src/storage/index.js +6 -0
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs-extra');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
// ─── Helpers ──────────────────────────────────────────────────────────────────
|
|
7
|
+
|
|
8
|
+
function resolveAppPath(...segments) {
|
|
9
|
+
return path.resolve(process.cwd(), ...segments);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
function timestamp() {
|
|
13
|
+
return new Date().toISOString().replace(/[-T:.Z]/g, '').slice(0, 14);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function pascalCase(str) {
|
|
17
|
+
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
async function write(filePath, content) {
|
|
21
|
+
await fs.ensureDir(path.dirname(filePath));
|
|
22
|
+
if (await fs.pathExists(filePath)) {
|
|
23
|
+
throw new Error(`File already exists: ${filePath}`);
|
|
24
|
+
}
|
|
25
|
+
await fs.writeFile(filePath, content, 'utf8');
|
|
26
|
+
return filePath;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// ─── Generators ───────────────────────────────────────────────────────────────
|
|
30
|
+
|
|
31
|
+
async function makeController(name, options = {}) {
|
|
32
|
+
const className = pascalCase(name.endsWith('Controller') ? name : `${name}Controller`);
|
|
33
|
+
const filePath = resolveAppPath('app/controllers', `${className}.js`);
|
|
34
|
+
|
|
35
|
+
const resource = options.resource;
|
|
36
|
+
|
|
37
|
+
const content = resource
|
|
38
|
+
? `'use strict';
|
|
39
|
+
|
|
40
|
+
const { Controller } = require('millas/src');
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* ${className}
|
|
44
|
+
*
|
|
45
|
+
* Resource controller — handles CRUD operations.
|
|
46
|
+
*/
|
|
47
|
+
class ${className} extends Controller {
|
|
48
|
+
/** GET /${name.toLowerCase()}s */
|
|
49
|
+
async index(req, res) {
|
|
50
|
+
return this.ok(res, { data: [] });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/** GET /${name.toLowerCase()}s/:id */
|
|
54
|
+
async show(req, res) {
|
|
55
|
+
const id = this.param(req, 'id');
|
|
56
|
+
return this.ok(res, { data: { id } });
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/** POST /${name.toLowerCase()}s */
|
|
60
|
+
async store(req, res) {
|
|
61
|
+
const data = await this.validate(req, {
|
|
62
|
+
// 'name': 'required|string|max:255',
|
|
63
|
+
});
|
|
64
|
+
return this.created(res, { data });
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** PUT /${name.toLowerCase()}s/:id */
|
|
68
|
+
async update(req, res) {
|
|
69
|
+
const id = this.param(req, 'id');
|
|
70
|
+
const data = this.except(req, ['id']);
|
|
71
|
+
return this.ok(res, { data: { id, ...data } });
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/** DELETE /${name.toLowerCase()}s/:id */
|
|
75
|
+
async destroy(req, res) {
|
|
76
|
+
return this.noContent(res);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
module.exports = ${className};
|
|
81
|
+
`
|
|
82
|
+
: `'use strict';
|
|
83
|
+
|
|
84
|
+
const { Controller } = require('millas/src');
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* ${className}
|
|
88
|
+
*/
|
|
89
|
+
class ${className} extends Controller {
|
|
90
|
+
async index(req, res) {
|
|
91
|
+
return this.ok(res, { message: 'Hello from ${className}' });
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
module.exports = ${className};
|
|
96
|
+
`;
|
|
97
|
+
|
|
98
|
+
return write(filePath, content);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
async function makeModel(name, options = {}) {
|
|
102
|
+
const className = pascalCase(name);
|
|
103
|
+
const tableName = name.toLowerCase() + 's';
|
|
104
|
+
const filePath = resolveAppPath('app/models', `${className}.js`);
|
|
105
|
+
|
|
106
|
+
const content = `'use strict';
|
|
107
|
+
|
|
108
|
+
const { Model, fields } = require('millas/src');
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* ${className} Model
|
|
112
|
+
*
|
|
113
|
+
* Represents the "${tableName}" table.
|
|
114
|
+
* Run: millas makemigrations — to generate the migration.
|
|
115
|
+
* Run: millas migrate — to apply it.
|
|
116
|
+
*/
|
|
117
|
+
class ${className} extends Model {
|
|
118
|
+
static table = '${tableName}';
|
|
119
|
+
|
|
120
|
+
static fields = {
|
|
121
|
+
id: fields.id(),
|
|
122
|
+
created_at: fields.timestamp(),
|
|
123
|
+
updated_at: fields.timestamp(),
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
module.exports = ${className};
|
|
128
|
+
`;
|
|
129
|
+
|
|
130
|
+
const result = await write(filePath, content);
|
|
131
|
+
|
|
132
|
+
if (options.migration) {
|
|
133
|
+
await makeMigration(`create_${tableName}_table`);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
return result;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
async function makeMiddleware(name) {
|
|
140
|
+
const className = pascalCase(name.endsWith('Middleware') ? name : `${name}Middleware`);
|
|
141
|
+
const filePath = resolveAppPath('app/middleware', `${className}.js`);
|
|
142
|
+
|
|
143
|
+
const content = `'use strict';
|
|
144
|
+
|
|
145
|
+
const { Middleware } = require('millas/src');
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* ${className}
|
|
149
|
+
*
|
|
150
|
+
* Usage:
|
|
151
|
+
* 1. Register in bootstrap/app.js:
|
|
152
|
+
* middlewareRegistry.register('${name.toLowerCase()}', ${className});
|
|
153
|
+
*
|
|
154
|
+
* 2. Apply to routes:
|
|
155
|
+
* Route.middleware(['${name.toLowerCase()}']).group(() => { ... });
|
|
156
|
+
*/
|
|
157
|
+
class ${className} extends Middleware {
|
|
158
|
+
/**
|
|
159
|
+
* Handle the incoming request.
|
|
160
|
+
* Call next() to continue, or return a response to halt the chain.
|
|
161
|
+
*/
|
|
162
|
+
async handle(req, res, next) {
|
|
163
|
+
// Your middleware logic here
|
|
164
|
+
|
|
165
|
+
next();
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
module.exports = ${className};
|
|
170
|
+
`;
|
|
171
|
+
|
|
172
|
+
return write(filePath, content);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
async function makeService(name) {
|
|
176
|
+
const className = pascalCase(name.endsWith('Service') ? name : `${name}Service`);
|
|
177
|
+
const filePath = resolveAppPath('app/services', `${className}.js`);
|
|
178
|
+
|
|
179
|
+
const content = `'use strict';
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* ${className}
|
|
183
|
+
*
|
|
184
|
+
* Business logic service.
|
|
185
|
+
* Register in AppServiceProvider:
|
|
186
|
+
* container.bind('${className}', ${className});
|
|
187
|
+
*/
|
|
188
|
+
class ${className} {
|
|
189
|
+
constructor() {
|
|
190
|
+
// Inject dependencies here (Phase 4)
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
module.exports = ${className};
|
|
195
|
+
`;
|
|
196
|
+
|
|
197
|
+
return write(filePath, content);
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
async function makeJob(name) {
|
|
201
|
+
const className = pascalCase(name.endsWith('Job') ? name : `${name}Job`);
|
|
202
|
+
const filePath = resolveAppPath('app/jobs', `${className}.js`);
|
|
203
|
+
|
|
204
|
+
const content = `'use strict';
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* ${className}
|
|
208
|
+
*
|
|
209
|
+
* Background job — dispatched via:
|
|
210
|
+
* dispatch(new ${className}(payload))
|
|
211
|
+
*
|
|
212
|
+
* Phase 9: Queue system will process this job.
|
|
213
|
+
*/
|
|
214
|
+
class ${className} {
|
|
215
|
+
constructor(payload = {}) {
|
|
216
|
+
this.payload = payload;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Execute the job.
|
|
221
|
+
*/
|
|
222
|
+
async handle() {
|
|
223
|
+
// Your job logic here
|
|
224
|
+
console.log('${className} running with:', this.payload);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
module.exports = ${className};
|
|
229
|
+
`;
|
|
230
|
+
|
|
231
|
+
return write(filePath, content);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
async function makeMigration(name) {
|
|
235
|
+
const fileName = `${timestamp()}_${name}.js`;
|
|
236
|
+
const filePath = resolveAppPath('database/migrations', fileName);
|
|
237
|
+
|
|
238
|
+
const content = `'use strict';
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Migration: ${name}
|
|
242
|
+
*/
|
|
243
|
+
module.exports = {
|
|
244
|
+
async up(db) {
|
|
245
|
+
// Write your migration here
|
|
246
|
+
// Example:
|
|
247
|
+
// await db.schema.createTable('users', (table) => {
|
|
248
|
+
// table.id();
|
|
249
|
+
// table.string('name');
|
|
250
|
+
// table.string('email').unique();
|
|
251
|
+
// table.timestamps();
|
|
252
|
+
// });
|
|
253
|
+
},
|
|
254
|
+
|
|
255
|
+
async down(db) {
|
|
256
|
+
// Rollback logic here
|
|
257
|
+
// await db.schema.dropTableIfExists('users');
|
|
258
|
+
},
|
|
259
|
+
};
|
|
260
|
+
`;
|
|
261
|
+
|
|
262
|
+
return write(filePath, content);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
module.exports = {
|
|
266
|
+
makeController,
|
|
267
|
+
makeModel,
|
|
268
|
+
makeMiddleware,
|
|
269
|
+
makeService,
|
|
270
|
+
makeJob,
|
|
271
|
+
makeMigration,
|
|
272
|
+
};
|
|
@@ -0,0 +1,350 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
function getProjectFiles(projectName) {
|
|
4
|
+
return {
|
|
5
|
+
|
|
6
|
+
// ─── package.json ─────────────────────────────────────────────
|
|
7
|
+
'package.json': JSON.stringify({
|
|
8
|
+
name: projectName,
|
|
9
|
+
version: '1.0.0',
|
|
10
|
+
description: `A Millas application`,
|
|
11
|
+
main: 'bootstrap/app.js',
|
|
12
|
+
scripts: {
|
|
13
|
+
start: 'node bootstrap/app.js',
|
|
14
|
+
dev: 'millas serve',
|
|
15
|
+
},
|
|
16
|
+
dependencies: {
|
|
17
|
+
express: '^4.18.2',
|
|
18
|
+
dotenv: '^16.0.3',
|
|
19
|
+
},
|
|
20
|
+
}, null, 2),
|
|
21
|
+
|
|
22
|
+
// ─── .env ─────────────────────────────────────────────────────
|
|
23
|
+
'.env': `APP_NAME=${projectName}
|
|
24
|
+
APP_ENV=development
|
|
25
|
+
APP_PORT=3000
|
|
26
|
+
APP_KEY=
|
|
27
|
+
|
|
28
|
+
DB_CONNECTION=sqlite
|
|
29
|
+
DB_HOST=127.0.0.1
|
|
30
|
+
DB_PORT=3306
|
|
31
|
+
DB_DATABASE=database/database.sqlite
|
|
32
|
+
DB_USERNAME=root
|
|
33
|
+
DB_PASSWORD=
|
|
34
|
+
|
|
35
|
+
MAIL_DRIVER=smtp
|
|
36
|
+
MAIL_HOST=smtp.mailtrap.io
|
|
37
|
+
MAIL_PORT=2525
|
|
38
|
+
MAIL_USERNAME=
|
|
39
|
+
MAIL_PASSWORD=
|
|
40
|
+
|
|
41
|
+
QUEUE_DRIVER=sync
|
|
42
|
+
|
|
43
|
+
CACHE_DRIVER=memory
|
|
44
|
+
`,
|
|
45
|
+
|
|
46
|
+
// ─── .env.example ─────────────────────────────────────────────
|
|
47
|
+
'.env.example': `APP_NAME=${projectName}
|
|
48
|
+
APP_ENV=development
|
|
49
|
+
APP_PORT=3000
|
|
50
|
+
APP_KEY=
|
|
51
|
+
|
|
52
|
+
DB_CONNECTION=sqlite
|
|
53
|
+
DB_HOST=127.0.0.1
|
|
54
|
+
DB_PORT=3306
|
|
55
|
+
DB_DATABASE=database/database.sqlite
|
|
56
|
+
DB_USERNAME=root
|
|
57
|
+
DB_PASSWORD=
|
|
58
|
+
`,
|
|
59
|
+
|
|
60
|
+
// ─── .gitignore ───────────────────────────────────────────────
|
|
61
|
+
'.gitignore': `node_modules/
|
|
62
|
+
.env
|
|
63
|
+
storage/logs/*.log
|
|
64
|
+
storage/uploads/*
|
|
65
|
+
!storage/uploads/.gitkeep
|
|
66
|
+
database/database.sqlite
|
|
67
|
+
`,
|
|
68
|
+
|
|
69
|
+
// ─── millas.config.js ─────────────────────────────────────────
|
|
70
|
+
'millas.config.js': `'use strict';
|
|
71
|
+
|
|
72
|
+
module.exports = {
|
|
73
|
+
/*
|
|
74
|
+
|--------------------------------------------------------------------------
|
|
75
|
+
| Millas Framework Configuration
|
|
76
|
+
|--------------------------------------------------------------------------
|
|
77
|
+
*/
|
|
78
|
+
providers: [
|
|
79
|
+
'./providers/AppServiceProvider',
|
|
80
|
+
],
|
|
81
|
+
};
|
|
82
|
+
`,
|
|
83
|
+
|
|
84
|
+
// ─── bootstrap/app.js ─────────────────────────────────────────
|
|
85
|
+
'bootstrap/app.js': `'use strict';
|
|
86
|
+
|
|
87
|
+
require('dotenv').config();
|
|
88
|
+
|
|
89
|
+
const express = require('express');
|
|
90
|
+
const { Application } = require('millas/src');
|
|
91
|
+
const AppServiceProvider = require('../providers/AppServiceProvider');
|
|
92
|
+
|
|
93
|
+
const expressApp = express();
|
|
94
|
+
expressApp.use(express.json());
|
|
95
|
+
expressApp.use(express.urlencoded({ extended: true }));
|
|
96
|
+
|
|
97
|
+
// ── Build the Millas application kernel ─────────────────────────
|
|
98
|
+
const app = new Application(expressApp);
|
|
99
|
+
|
|
100
|
+
// ── Register service providers ──────────────────────────────────
|
|
101
|
+
app.providers([
|
|
102
|
+
AppServiceProvider,
|
|
103
|
+
// Add more providers here as you build your app
|
|
104
|
+
]);
|
|
105
|
+
|
|
106
|
+
// ── Define routes ────────────────────────────────────────────────
|
|
107
|
+
app.routes(Route => {
|
|
108
|
+
require('../routes/web')(Route);
|
|
109
|
+
require('../routes/api')(Route);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
// ── Boot + mount + listen ────────────────────────────────────────
|
|
113
|
+
(async () => {
|
|
114
|
+
await app.boot();
|
|
115
|
+
|
|
116
|
+
if (!process.env.MILLAS_ROUTE_LIST) {
|
|
117
|
+
app.mount();
|
|
118
|
+
app.listen();
|
|
119
|
+
}
|
|
120
|
+
})();
|
|
121
|
+
|
|
122
|
+
module.exports = { app, expressApp };
|
|
123
|
+
`,
|
|
124
|
+
|
|
125
|
+
// ─── routes/web.js ────────────────────────────────────────────
|
|
126
|
+
'routes/web.js': `'use strict';
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Web Routes
|
|
130
|
+
*
|
|
131
|
+
* Define your web-facing routes here using the Millas Route API.
|
|
132
|
+
*
|
|
133
|
+
* Route.get('/path', ControllerClass, 'method')
|
|
134
|
+
* Route.get('/path', (req, res) => res.json({ ... })) // closure
|
|
135
|
+
* Route.resource('/posts', PostController) // full CRUD
|
|
136
|
+
* Route.group({ prefix: '/admin', middleware: ['auth'] }, () => { ... })
|
|
137
|
+
*/
|
|
138
|
+
module.exports = function (Route) {
|
|
139
|
+
Route.get('/', (req, res) => {
|
|
140
|
+
res.json({
|
|
141
|
+
framework: 'Millas',
|
|
142
|
+
version: '0.1.0',
|
|
143
|
+
message: 'Welcome to your Millas application!',
|
|
144
|
+
docs: 'https://millas.dev/docs',
|
|
145
|
+
});
|
|
146
|
+
});
|
|
147
|
+
};
|
|
148
|
+
`,
|
|
149
|
+
|
|
150
|
+
// ─── routes/api.js ────────────────────────────────────────────
|
|
151
|
+
'routes/api.js': `'use strict';
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* API Routes
|
|
155
|
+
*
|
|
156
|
+
* All routes here are prefixed with /api.
|
|
157
|
+
* Add Route.middleware(['auth']) to protect routes.
|
|
158
|
+
*/
|
|
159
|
+
module.exports = function (Route) {
|
|
160
|
+
Route.prefix('/api').group(() => {
|
|
161
|
+
|
|
162
|
+
Route.get('/health', (req, res) => {
|
|
163
|
+
res.json({ status: 'ok', timestamp: new Date().toISOString() });
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
});
|
|
167
|
+
};
|
|
168
|
+
`,
|
|
169
|
+
|
|
170
|
+
// ─── config/app.js ────────────────────────────────────────────
|
|
171
|
+
'config/app.js': `'use strict';
|
|
172
|
+
|
|
173
|
+
module.exports = {
|
|
174
|
+
name: process.env.APP_NAME || 'Millas',
|
|
175
|
+
env: process.env.APP_ENV || 'development',
|
|
176
|
+
port: parseInt(process.env.APP_PORT, 10) || 3000,
|
|
177
|
+
key: process.env.APP_KEY || '',
|
|
178
|
+
debug: process.env.APP_ENV !== 'production',
|
|
179
|
+
timezone: 'UTC',
|
|
180
|
+
locale: 'en',
|
|
181
|
+
};
|
|
182
|
+
`,
|
|
183
|
+
|
|
184
|
+
// ─── config/database.js ───────────────────────────────────────
|
|
185
|
+
'config/database.js': `'use strict';
|
|
186
|
+
|
|
187
|
+
module.exports = {
|
|
188
|
+
default: process.env.DB_CONNECTION || 'sqlite',
|
|
189
|
+
|
|
190
|
+
connections: {
|
|
191
|
+
sqlite: {
|
|
192
|
+
driver: 'sqlite',
|
|
193
|
+
database: process.env.DB_DATABASE || 'database/database.sqlite',
|
|
194
|
+
},
|
|
195
|
+
mysql: {
|
|
196
|
+
driver: 'mysql',
|
|
197
|
+
host: process.env.DB_HOST || '127.0.0.1',
|
|
198
|
+
port: parseInt(process.env.DB_PORT, 10) || 3306,
|
|
199
|
+
database: process.env.DB_DATABASE || 'millas',
|
|
200
|
+
username: process.env.DB_USERNAME || 'root',
|
|
201
|
+
password: process.env.DB_PASSWORD || '',
|
|
202
|
+
},
|
|
203
|
+
postgres: {
|
|
204
|
+
driver: 'postgres',
|
|
205
|
+
host: process.env.DB_HOST || '127.0.0.1',
|
|
206
|
+
port: parseInt(process.env.DB_PORT, 10) || 5432,
|
|
207
|
+
database: process.env.DB_DATABASE || 'millas',
|
|
208
|
+
username: process.env.DB_USERNAME || 'postgres',
|
|
209
|
+
password: process.env.DB_PASSWORD || '',
|
|
210
|
+
},
|
|
211
|
+
},
|
|
212
|
+
};
|
|
213
|
+
`,
|
|
214
|
+
|
|
215
|
+
// ─── config/auth.js ───────────────────────────────────────────
|
|
216
|
+
'config/auth.js': `'use strict';
|
|
217
|
+
|
|
218
|
+
module.exports = {
|
|
219
|
+
default: 'jwt',
|
|
220
|
+
|
|
221
|
+
guards: {
|
|
222
|
+
jwt: {
|
|
223
|
+
driver: 'jwt',
|
|
224
|
+
secret: process.env.APP_KEY || 'change-me',
|
|
225
|
+
expiresIn: '7d',
|
|
226
|
+
},
|
|
227
|
+
session: {
|
|
228
|
+
driver: 'session',
|
|
229
|
+
},
|
|
230
|
+
},
|
|
231
|
+
|
|
232
|
+
providers: {
|
|
233
|
+
users: {
|
|
234
|
+
model: 'User',
|
|
235
|
+
},
|
|
236
|
+
},
|
|
237
|
+
|
|
238
|
+
passwordReset: {
|
|
239
|
+
expiresIn: '1h',
|
|
240
|
+
},
|
|
241
|
+
};
|
|
242
|
+
`,
|
|
243
|
+
|
|
244
|
+
// ─── config/mail.js ───────────────────────────────────────────
|
|
245
|
+
'config/mail.js': `'use strict';
|
|
246
|
+
|
|
247
|
+
module.exports = {
|
|
248
|
+
default: process.env.MAIL_DRIVER || 'smtp',
|
|
249
|
+
|
|
250
|
+
drivers: {
|
|
251
|
+
smtp: {
|
|
252
|
+
host: process.env.MAIL_HOST || 'smtp.mailtrap.io',
|
|
253
|
+
port: parseInt(process.env.MAIL_PORT, 10) || 2525,
|
|
254
|
+
username: process.env.MAIL_USERNAME || '',
|
|
255
|
+
password: process.env.MAIL_PASSWORD || '',
|
|
256
|
+
encryption: 'tls',
|
|
257
|
+
},
|
|
258
|
+
},
|
|
259
|
+
|
|
260
|
+
from: {
|
|
261
|
+
address: process.env.MAIL_FROM_ADDRESS || 'hello@millas.dev',
|
|
262
|
+
name: process.env.MAIL_FROM_NAME || 'Millas',
|
|
263
|
+
},
|
|
264
|
+
};
|
|
265
|
+
`,
|
|
266
|
+
|
|
267
|
+
// ─── providers/AppServiceProvider.js ──────────────────────────
|
|
268
|
+
'providers/AppServiceProvider.js': `'use strict';
|
|
269
|
+
|
|
270
|
+
const { ServiceProvider } = require('millas/src');
|
|
271
|
+
|
|
272
|
+
/**
|
|
273
|
+
* AppServiceProvider
|
|
274
|
+
*
|
|
275
|
+
* Register and bootstrap your application's services here.
|
|
276
|
+
*
|
|
277
|
+
* register() — bind things into the container
|
|
278
|
+
* boot() — called after all providers have registered;
|
|
279
|
+
* safe to resolve other bindings here
|
|
280
|
+
*/
|
|
281
|
+
class AppServiceProvider extends ServiceProvider {
|
|
282
|
+
register(container) {
|
|
283
|
+
// container.bind('UserService', UserService);
|
|
284
|
+
// container.singleton('Mailer', MailService);
|
|
285
|
+
// container.instance('Config', require('../config/app'));
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
async boot(container, app) {
|
|
289
|
+
// const logger = container.make('Logger');
|
|
290
|
+
// logger.info('App booted');
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
module.exports = AppServiceProvider;
|
|
295
|
+
`,
|
|
296
|
+
|
|
297
|
+
// ─── app/controllers/.gitkeep ────────────────────────────────
|
|
298
|
+
'app/controllers/.gitkeep': '',
|
|
299
|
+
'app/models/.gitkeep': '',
|
|
300
|
+
'app/services/.gitkeep': '',
|
|
301
|
+
'app/middleware/.gitkeep': '',
|
|
302
|
+
'app/jobs/.gitkeep': '',
|
|
303
|
+
|
|
304
|
+
// ─── README.md ────────────────────────────────────────────────
|
|
305
|
+
'README.md': `# ${projectName}
|
|
306
|
+
|
|
307
|
+
A [Millas](https://millas.dev) application.
|
|
308
|
+
|
|
309
|
+
## Getting Started
|
|
310
|
+
|
|
311
|
+
\`\`\`bash
|
|
312
|
+
# Start the development server
|
|
313
|
+
millas serve
|
|
314
|
+
|
|
315
|
+
# Generate a controller
|
|
316
|
+
millas make:controller UserController
|
|
317
|
+
|
|
318
|
+
# Generate a model
|
|
319
|
+
millas make:model User
|
|
320
|
+
|
|
321
|
+
# Run migrations
|
|
322
|
+
millas migrate
|
|
323
|
+
\`\`\`
|
|
324
|
+
|
|
325
|
+
## Project Structure
|
|
326
|
+
|
|
327
|
+
\`\`\`
|
|
328
|
+
app/
|
|
329
|
+
controllers/ # HTTP controllers
|
|
330
|
+
models/ # ORM models
|
|
331
|
+
services/ # Business logic
|
|
332
|
+
middleware/ # HTTP middleware
|
|
333
|
+
jobs/ # Background jobs
|
|
334
|
+
bootstrap/
|
|
335
|
+
app.js # Application entry point
|
|
336
|
+
config/ # Configuration files
|
|
337
|
+
database/
|
|
338
|
+
migrations/ # Database migrations
|
|
339
|
+
seeders/ # Database seeders
|
|
340
|
+
routes/
|
|
341
|
+
web.js # Web routes
|
|
342
|
+
api.js # API routes
|
|
343
|
+
storage/ # Logs, uploads
|
|
344
|
+
providers/ # Service providers
|
|
345
|
+
\`\`\`
|
|
346
|
+
`,
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
module.exports = { getProjectFiles };
|