@tyravel/cli 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/dist/bin/tyravel.d.ts +3 -0
- package/dist/bin/tyravel.d.ts.map +1 -0
- package/dist/bin/tyravel.js +5 -0
- package/dist/bin/tyravel.js.map +1 -0
- package/dist/command.d.ts +13 -0
- package/dist/command.d.ts.map +1 -0
- package/dist/command.js +11 -0
- package/dist/command.js.map +1 -0
- package/dist/commands/auth-install.d.ts +8 -0
- package/dist/commands/auth-install.d.ts.map +1 -0
- package/dist/commands/auth-install.js +39 -0
- package/dist/commands/auth-install.js.map +1 -0
- package/dist/commands/make-controller.d.ts +8 -0
- package/dist/commands/make-controller.d.ts.map +1 -0
- package/dist/commands/make-controller.js +31 -0
- package/dist/commands/make-controller.js.map +1 -0
- package/dist/commands/make-event.d.ts +8 -0
- package/dist/commands/make-event.d.ts.map +1 -0
- package/dist/commands/make-event.js +31 -0
- package/dist/commands/make-event.js.map +1 -0
- package/dist/commands/make-job.d.ts +8 -0
- package/dist/commands/make-job.d.ts.map +1 -0
- package/dist/commands/make-job.js +32 -0
- package/dist/commands/make-job.js.map +1 -0
- package/dist/commands/make-listener.d.ts +8 -0
- package/dist/commands/make-listener.d.ts.map +1 -0
- package/dist/commands/make-listener.js +32 -0
- package/dist/commands/make-listener.js.map +1 -0
- package/dist/commands/make-migration.d.ts +8 -0
- package/dist/commands/make-migration.d.ts.map +1 -0
- package/dist/commands/make-migration.js +50 -0
- package/dist/commands/make-migration.js.map +1 -0
- package/dist/commands/make-model.d.ts +8 -0
- package/dist/commands/make-model.d.ts.map +1 -0
- package/dist/commands/make-model.js +31 -0
- package/dist/commands/make-model.js.map +1 -0
- package/dist/commands/make-provider.d.ts +8 -0
- package/dist/commands/make-provider.d.ts.map +1 -0
- package/dist/commands/make-provider.js +32 -0
- package/dist/commands/make-provider.js.map +1 -0
- package/dist/commands/make-subscriber.d.ts +8 -0
- package/dist/commands/make-subscriber.d.ts.map +1 -0
- package/dist/commands/make-subscriber.js +30 -0
- package/dist/commands/make-subscriber.js.map +1 -0
- package/dist/commands/make-test.d.ts +8 -0
- package/dist/commands/make-test.d.ts.map +1 -0
- package/dist/commands/make-test.js +24 -0
- package/dist/commands/make-test.js.map +1 -0
- package/dist/commands/make-view.d.ts +8 -0
- package/dist/commands/make-view.d.ts.map +1 -0
- package/dist/commands/make-view.js +36 -0
- package/dist/commands/make-view.js.map +1 -0
- package/dist/commands/migrate.d.ts +8 -0
- package/dist/commands/migrate.d.ts.map +1 -0
- package/dist/commands/migrate.js +32 -0
- package/dist/commands/migrate.js.map +1 -0
- package/dist/commands/new.d.ts +8 -0
- package/dist/commands/new.d.ts.map +1 -0
- package/dist/commands/new.js +57 -0
- package/dist/commands/new.js.map +1 -0
- package/dist/commands/new.test.d.ts +2 -0
- package/dist/commands/new.test.d.ts.map +1 -0
- package/dist/commands/new.test.js +28 -0
- package/dist/commands/new.test.js.map +1 -0
- package/dist/commands/queue-failed.d.ts +20 -0
- package/dist/commands/queue-failed.d.ts.map +1 -0
- package/dist/commands/queue-failed.js +143 -0
- package/dist/commands/queue-failed.js.map +1 -0
- package/dist/commands/queue-table.d.ts +8 -0
- package/dist/commands/queue-table.d.ts.map +1 -0
- package/dist/commands/queue-table.js +38 -0
- package/dist/commands/queue-table.js.map +1 -0
- package/dist/commands/queue-work.d.ts +8 -0
- package/dist/commands/queue-work.d.ts.map +1 -0
- package/dist/commands/queue-work.js +55 -0
- package/dist/commands/queue-work.js.map +1 -0
- package/dist/commands/serve.d.ts +8 -0
- package/dist/commands/serve.d.ts.map +1 -0
- package/dist/commands/serve.js +77 -0
- package/dist/commands/serve.js.map +1 -0
- package/dist/commands/version.d.ts +7 -0
- package/dist/commands/version.d.ts.map +1 -0
- package/dist/commands/version.js +16 -0
- package/dist/commands/version.js.map +1 -0
- package/dist/console.d.ts +17 -0
- package/dist/console.d.ts.map +1 -0
- package/dist/console.js +114 -0
- package/dist/console.js.map +1 -0
- package/dist/console.test.d.ts +2 -0
- package/dist/console.test.d.ts.map +1 -0
- package/dist/console.test.js +42 -0
- package/dist/console.test.js.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/kernel.d.ts +3 -0
- package/dist/kernel.d.ts.map +1 -0
- package/dist/kernel.js +44 -0
- package/dist/kernel.js.map +1 -0
- package/dist/project.d.ts +12 -0
- package/dist/project.d.ts.map +1 -0
- package/dist/project.js +34 -0
- package/dist/project.js.map +1 -0
- package/dist/project.test.d.ts +2 -0
- package/dist/project.test.d.ts.map +1 -0
- package/dist/project.test.js +24 -0
- package/dist/project.test.js.map +1 -0
- package/dist/stubs-ecosystem.d.ts +5 -0
- package/dist/stubs-ecosystem.d.ts.map +1 -0
- package/dist/stubs-ecosystem.js +79 -0
- package/dist/stubs-ecosystem.js.map +1 -0
- package/dist/stubs-testing.d.ts +3 -0
- package/dist/stubs-testing.d.ts.map +1 -0
- package/dist/stubs-testing.js +33 -0
- package/dist/stubs-testing.js.map +1 -0
- package/dist/stubs.d.ts +35 -0
- package/dist/stubs.d.ts.map +1 -0
- package/dist/stubs.js +753 -0
- package/dist/stubs.js.map +1 -0
- package/dist/utils.d.ts +9 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +70 -0
- package/dist/utils.js.map +1 -0
- package/dist/utils.test.d.ts +2 -0
- package/dist/utils.test.d.ts.map +1 -0
- package/dist/utils.test.js +13 -0
- package/dist/utils.test.js.map +1 -0
- package/package.json +42 -0
package/dist/stubs.js
ADDED
|
@@ -0,0 +1,753 @@
|
|
|
1
|
+
export function projectPackageJson(name) {
|
|
2
|
+
return JSON.stringify({
|
|
3
|
+
name,
|
|
4
|
+
private: true,
|
|
5
|
+
type: 'module',
|
|
6
|
+
scripts: {
|
|
7
|
+
dev: 'tyravel serve',
|
|
8
|
+
start: 'tyravel serve',
|
|
9
|
+
test: 'vitest run',
|
|
10
|
+
},
|
|
11
|
+
dependencies: {
|
|
12
|
+
'@tyravel/auth': '^0.1.0',
|
|
13
|
+
'@tyravel/cache': '^0.1.0',
|
|
14
|
+
'@tyravel/config': '^0.1.0',
|
|
15
|
+
'@tyravel/core': '^0.1.0',
|
|
16
|
+
'@tyravel/database': '^0.1.0',
|
|
17
|
+
'@tyravel/events': '^0.1.0',
|
|
18
|
+
'@tyravel/http': '^0.1.0',
|
|
19
|
+
'@tyravel/mail': '^0.1.0',
|
|
20
|
+
'@tyravel/notifications': '^0.1.0',
|
|
21
|
+
'@tyravel/queue': '^0.1.0',
|
|
22
|
+
'@tyravel/validation': '^0.1.0',
|
|
23
|
+
'@tyravel/views': '^0.1.0',
|
|
24
|
+
},
|
|
25
|
+
devDependencies: {
|
|
26
|
+
'@tyravel/cli': '^0.1.0',
|
|
27
|
+
'@tyravel/testing': '^0.1.0',
|
|
28
|
+
vitest: '^3.2.4',
|
|
29
|
+
},
|
|
30
|
+
}, null, 2);
|
|
31
|
+
}
|
|
32
|
+
export function projectConfig(name) {
|
|
33
|
+
return JSON.stringify({
|
|
34
|
+
name,
|
|
35
|
+
entry: 'src/main.ts',
|
|
36
|
+
serve: {
|
|
37
|
+
port: 3000,
|
|
38
|
+
hostname: '127.0.0.1',
|
|
39
|
+
},
|
|
40
|
+
}, null, 2);
|
|
41
|
+
}
|
|
42
|
+
export function mainEntry() {
|
|
43
|
+
return `import {
|
|
44
|
+
Application,
|
|
45
|
+
CacheServiceProvider,
|
|
46
|
+
ConfigServiceProvider,
|
|
47
|
+
DatabaseServiceProvider,
|
|
48
|
+
EventServiceProvider,
|
|
49
|
+
HttpKernel,
|
|
50
|
+
MailServiceProvider,
|
|
51
|
+
NotificationServiceProvider,
|
|
52
|
+
QueueServiceProvider,
|
|
53
|
+
setCacheApplication,
|
|
54
|
+
setEventApplication,
|
|
55
|
+
setMailApplication,
|
|
56
|
+
setNotificationApplication,
|
|
57
|
+
setQueueApplication,
|
|
58
|
+
setRouteApplication,
|
|
59
|
+
setViewApplication,
|
|
60
|
+
ViewServiceProvider,
|
|
61
|
+
serve,
|
|
62
|
+
} from '@tyravel/core';
|
|
63
|
+
import { AppServiceProvider } from './providers/app-service-provider.js';
|
|
64
|
+
import './routes/web.js';
|
|
65
|
+
|
|
66
|
+
const app = new Application(import.meta.dir);
|
|
67
|
+
setRouteApplication(app);
|
|
68
|
+
setViewApplication(app);
|
|
69
|
+
setQueueApplication(app);
|
|
70
|
+
setEventApplication(app);
|
|
71
|
+
setCacheApplication(app);
|
|
72
|
+
setMailApplication(app);
|
|
73
|
+
setNotificationApplication(app);
|
|
74
|
+
|
|
75
|
+
app.register(ConfigServiceProvider);
|
|
76
|
+
app.register(DatabaseServiceProvider);
|
|
77
|
+
app.register(CacheServiceProvider);
|
|
78
|
+
app.register(MailServiceProvider);
|
|
79
|
+
app.register(NotificationServiceProvider);
|
|
80
|
+
app.register(QueueServiceProvider);
|
|
81
|
+
app.register(EventServiceProvider);
|
|
82
|
+
app.register(ViewServiceProvider);
|
|
83
|
+
app.register(AppServiceProvider);
|
|
84
|
+
|
|
85
|
+
await app.boot();
|
|
86
|
+
|
|
87
|
+
const kernel = new HttpKernel(app);
|
|
88
|
+
await serve(kernel);
|
|
89
|
+
`;
|
|
90
|
+
}
|
|
91
|
+
export function appConfig(name) {
|
|
92
|
+
return `export default {
|
|
93
|
+
name: '${name}',
|
|
94
|
+
debug: true,
|
|
95
|
+
} as const;
|
|
96
|
+
`;
|
|
97
|
+
}
|
|
98
|
+
export function viewsConfig() {
|
|
99
|
+
return `export default {
|
|
100
|
+
path: 'resources/views',
|
|
101
|
+
extension: '.tyr',
|
|
102
|
+
} as const;
|
|
103
|
+
`;
|
|
104
|
+
}
|
|
105
|
+
export function databaseConfig() {
|
|
106
|
+
return `export default {
|
|
107
|
+
default: 'sqlite',
|
|
108
|
+
connections: {
|
|
109
|
+
sqlite: {
|
|
110
|
+
driver: 'sqlite',
|
|
111
|
+
database: 'database/database.sqlite',
|
|
112
|
+
},
|
|
113
|
+
postgres: {
|
|
114
|
+
driver: 'postgres',
|
|
115
|
+
host: '127.0.0.1',
|
|
116
|
+
port: 5432,
|
|
117
|
+
database: 'tyravel',
|
|
118
|
+
username: 'postgres',
|
|
119
|
+
password: '',
|
|
120
|
+
},
|
|
121
|
+
mysql: {
|
|
122
|
+
driver: 'mysql',
|
|
123
|
+
host: '127.0.0.1',
|
|
124
|
+
port: 3306,
|
|
125
|
+
database: 'tyravel',
|
|
126
|
+
username: 'root',
|
|
127
|
+
password: '',
|
|
128
|
+
},
|
|
129
|
+
},
|
|
130
|
+
} as const;
|
|
131
|
+
`;
|
|
132
|
+
}
|
|
133
|
+
export function appServiceProvider() {
|
|
134
|
+
return `import { ServiceProvider } from '@tyravel/core';
|
|
135
|
+
|
|
136
|
+
export class AppServiceProvider extends ServiceProvider {
|
|
137
|
+
override register() {
|
|
138
|
+
this.app.instance('app.name', 'Tyravel');
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
`;
|
|
142
|
+
}
|
|
143
|
+
export function webRoutes() {
|
|
144
|
+
return `import { Route } from '@tyravel/core';
|
|
145
|
+
import { Response } from '@tyravel/http';
|
|
146
|
+
|
|
147
|
+
Route.get('/', (request) =>
|
|
148
|
+
Response.json({
|
|
149
|
+
message: 'Welcome to Tyravel',
|
|
150
|
+
path: request.path,
|
|
151
|
+
}),
|
|
152
|
+
);
|
|
153
|
+
`;
|
|
154
|
+
}
|
|
155
|
+
export function controller(name) {
|
|
156
|
+
const className = `${name}Controller`;
|
|
157
|
+
return `import type { TyravelRequest } from '@tyravel/http';
|
|
158
|
+
import { Response } from '@tyravel/http';
|
|
159
|
+
|
|
160
|
+
export class ${className} {
|
|
161
|
+
index(_request: TyravelRequest) {
|
|
162
|
+
return Response.json({
|
|
163
|
+
message: '${className}@index',
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
show(request: TyravelRequest) {
|
|
168
|
+
return Response.json({
|
|
169
|
+
message: '${className}@show',
|
|
170
|
+
id: request.param('id'),
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
`;
|
|
175
|
+
}
|
|
176
|
+
export function model(name) {
|
|
177
|
+
const table = `${name.charAt(0).toLowerCase()}${name.slice(1)}s`;
|
|
178
|
+
return `import { Model } from '@tyravel/database';
|
|
179
|
+
|
|
180
|
+
export interface ${name}Attributes {
|
|
181
|
+
id: number;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export class ${name} extends Model<${name}Attributes> {
|
|
185
|
+
static override table = '${table}';
|
|
186
|
+
}
|
|
187
|
+
`;
|
|
188
|
+
}
|
|
189
|
+
export function migration(className) {
|
|
190
|
+
return `import { Migration } from '@tyravel/database';
|
|
191
|
+
import type { DatabaseConnection } from '@tyravel/database';
|
|
192
|
+
import type { SchemaBuilder } from '@tyravel/database';
|
|
193
|
+
|
|
194
|
+
export default class ${className} extends Migration {
|
|
195
|
+
override async up(_connection: DatabaseConnection, schema: SchemaBuilder) {
|
|
196
|
+
//
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
override async down(_connection: DatabaseConnection, schema: SchemaBuilder) {
|
|
200
|
+
//
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
`;
|
|
204
|
+
}
|
|
205
|
+
export function view(name) {
|
|
206
|
+
return `@layout('layouts.app')
|
|
207
|
+
|
|
208
|
+
@section('title')
|
|
209
|
+
${name}
|
|
210
|
+
@endsection
|
|
211
|
+
|
|
212
|
+
@section('content')
|
|
213
|
+
<h1>${name}</h1>
|
|
214
|
+
@endsection
|
|
215
|
+
`;
|
|
216
|
+
}
|
|
217
|
+
export function layoutView() {
|
|
218
|
+
return `<!DOCTYPE html>
|
|
219
|
+
<html lang="en">
|
|
220
|
+
<head>
|
|
221
|
+
<meta charset="utf-8">
|
|
222
|
+
<title>@yield('title', 'Tyravel')</title>
|
|
223
|
+
</head>
|
|
224
|
+
<body>
|
|
225
|
+
@yield('content')
|
|
226
|
+
</body>
|
|
227
|
+
</html>
|
|
228
|
+
`;
|
|
229
|
+
}
|
|
230
|
+
export function provider(name) {
|
|
231
|
+
const className = `${name}ServiceProvider`;
|
|
232
|
+
return `import { ServiceProvider } from '@tyravel/core';
|
|
233
|
+
|
|
234
|
+
export class ${className} extends ServiceProvider {
|
|
235
|
+
override register() {
|
|
236
|
+
//
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
override boot() {
|
|
240
|
+
//
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
`;
|
|
244
|
+
}
|
|
245
|
+
export function job(name) {
|
|
246
|
+
return `import { Job } from '@tyravel/queue';
|
|
247
|
+
|
|
248
|
+
export interface ${name}Payload {
|
|
249
|
+
//
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
export class ${name} extends Job<${name}Payload> {
|
|
253
|
+
override async handle(): Promise<void> {
|
|
254
|
+
//
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
`;
|
|
258
|
+
}
|
|
259
|
+
export function queueConfig() {
|
|
260
|
+
return `export default {
|
|
261
|
+
default: 'database',
|
|
262
|
+
connections: {
|
|
263
|
+
sync: { driver: 'sync' },
|
|
264
|
+
database: {
|
|
265
|
+
driver: 'database',
|
|
266
|
+
table: 'jobs',
|
|
267
|
+
connection: 'sqlite',
|
|
268
|
+
retryAfter: 90,
|
|
269
|
+
},
|
|
270
|
+
},
|
|
271
|
+
failed: {
|
|
272
|
+
table: 'failed_jobs',
|
|
273
|
+
},
|
|
274
|
+
} as const;
|
|
275
|
+
`;
|
|
276
|
+
}
|
|
277
|
+
export function jobsTableMigration() {
|
|
278
|
+
return `import { Migration } from '@tyravel/database';
|
|
279
|
+
import type { DatabaseConnection } from '@tyravel/database';
|
|
280
|
+
import type { SchemaBuilder } from '@tyravel/database';
|
|
281
|
+
|
|
282
|
+
export default class CreateJobsTable extends Migration {
|
|
283
|
+
override async up(_connection: DatabaseConnection, schema: SchemaBuilder) {
|
|
284
|
+
await schema.create('jobs', (table) => {
|
|
285
|
+
table.id();
|
|
286
|
+
table.string('queue');
|
|
287
|
+
table.text('payload');
|
|
288
|
+
table.integer('attempts');
|
|
289
|
+
table.integer('reserved_at').nullable();
|
|
290
|
+
table.integer('available_at');
|
|
291
|
+
table.integer('created_at');
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
override async down(_connection: DatabaseConnection, schema: SchemaBuilder) {
|
|
296
|
+
await schema.drop('jobs');
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
`;
|
|
300
|
+
}
|
|
301
|
+
export function domainEvent(name) {
|
|
302
|
+
return `import { Event } from '@tyravel/events';
|
|
303
|
+
|
|
304
|
+
export interface ${name}Payload {
|
|
305
|
+
//
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
export class ${name} extends Event<${name}Payload> {}
|
|
309
|
+
`;
|
|
310
|
+
}
|
|
311
|
+
export function eventListener(name) {
|
|
312
|
+
return `import { Listener } from '@tyravel/events';
|
|
313
|
+
import type { Event } from '@tyravel/events';
|
|
314
|
+
|
|
315
|
+
export class ${name} extends Listener<Event> {
|
|
316
|
+
override async handle(_event: Event): Promise<void> {
|
|
317
|
+
//
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
`;
|
|
321
|
+
}
|
|
322
|
+
export function eventsConfig() {
|
|
323
|
+
return `import type { EventsConfig } from '@tyravel/events';
|
|
324
|
+
|
|
325
|
+
export default {
|
|
326
|
+
listen: [],
|
|
327
|
+
subscribers: [],
|
|
328
|
+
queueConnection: 'database',
|
|
329
|
+
queue: 'default',
|
|
330
|
+
} satisfies EventsConfig;
|
|
331
|
+
`;
|
|
332
|
+
}
|
|
333
|
+
export function failedJobsTableMigration() {
|
|
334
|
+
return `import { Migration } from '@tyravel/database';
|
|
335
|
+
import type { DatabaseConnection } from '@tyravel/database';
|
|
336
|
+
import type { SchemaBuilder } from '@tyravel/database';
|
|
337
|
+
|
|
338
|
+
export default class CreateFailedJobsTable extends Migration {
|
|
339
|
+
override async up(_connection: DatabaseConnection, schema: SchemaBuilder) {
|
|
340
|
+
await schema.create('failed_jobs', (table) => {
|
|
341
|
+
table.id();
|
|
342
|
+
table.string('uuid');
|
|
343
|
+
table.string('connection');
|
|
344
|
+
table.string('queue');
|
|
345
|
+
table.text('payload');
|
|
346
|
+
table.text('exception');
|
|
347
|
+
table.integer('failed_at');
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
override async down(_connection: DatabaseConnection, schema: SchemaBuilder) {
|
|
352
|
+
await schema.drop('failed_jobs');
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
`;
|
|
356
|
+
}
|
|
357
|
+
export function eventSubscriber(name) {
|
|
358
|
+
return `import { EventSubscriber } from '@tyravel/events';
|
|
359
|
+
import type { EventDispatcher } from '@tyravel/events';
|
|
360
|
+
|
|
361
|
+
export class ${name} extends EventSubscriber {
|
|
362
|
+
subscribe(dispatcher: EventDispatcher): void {
|
|
363
|
+
// dispatcher.listen(SomeEvent, SomeListener);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
`;
|
|
367
|
+
}
|
|
368
|
+
export function authConfig() {
|
|
369
|
+
return `import type { AuthConfig } from '@tyravel/auth';
|
|
370
|
+
import { User } from '../src/models/User.js';
|
|
371
|
+
|
|
372
|
+
export default {
|
|
373
|
+
defaults: {
|
|
374
|
+
guard: 'web',
|
|
375
|
+
},
|
|
376
|
+
guards: {
|
|
377
|
+
web: {
|
|
378
|
+
driver: 'session',
|
|
379
|
+
provider: 'users',
|
|
380
|
+
},
|
|
381
|
+
api: {
|
|
382
|
+
driver: 'token',
|
|
383
|
+
provider: 'users',
|
|
384
|
+
},
|
|
385
|
+
},
|
|
386
|
+
providers: {
|
|
387
|
+
users: {
|
|
388
|
+
driver: 'eloquent',
|
|
389
|
+
model: User,
|
|
390
|
+
},
|
|
391
|
+
},
|
|
392
|
+
session: {
|
|
393
|
+
cookie: 'tyravel_session',
|
|
394
|
+
lifetimeMinutes: 120,
|
|
395
|
+
table: 'sessions',
|
|
396
|
+
connection: 'sqlite',
|
|
397
|
+
},
|
|
398
|
+
passwords: {
|
|
399
|
+
users: {
|
|
400
|
+
provider: 'users',
|
|
401
|
+
table: 'password_reset_tokens',
|
|
402
|
+
expireMinutes: 60,
|
|
403
|
+
connection: 'sqlite',
|
|
404
|
+
},
|
|
405
|
+
},
|
|
406
|
+
tokens: {
|
|
407
|
+
table: 'personal_access_tokens',
|
|
408
|
+
connection: 'sqlite',
|
|
409
|
+
},
|
|
410
|
+
oauth: {
|
|
411
|
+
accountsTable: 'oauth_accounts',
|
|
412
|
+
connection: 'sqlite',
|
|
413
|
+
providers: {
|
|
414
|
+
github: {
|
|
415
|
+
clientId: process.env.GITHUB_CLIENT_ID ?? '',
|
|
416
|
+
clientSecret: process.env.GITHUB_CLIENT_SECRET ?? '',
|
|
417
|
+
redirectUri: process.env.GITHUB_REDIRECT_URI ?? 'http://127.0.0.1:3000/auth/github/callback',
|
|
418
|
+
scopes: ['user:email'],
|
|
419
|
+
},
|
|
420
|
+
google: {
|
|
421
|
+
clientId: process.env.GOOGLE_CLIENT_ID ?? '',
|
|
422
|
+
clientSecret: process.env.GOOGLE_CLIENT_SECRET ?? '',
|
|
423
|
+
redirectUri: process.env.GOOGLE_REDIRECT_URI ?? 'http://127.0.0.1:3000/auth/google/callback',
|
|
424
|
+
},
|
|
425
|
+
},
|
|
426
|
+
},
|
|
427
|
+
policies: {},
|
|
428
|
+
} satisfies AuthConfig;
|
|
429
|
+
`;
|
|
430
|
+
}
|
|
431
|
+
export function userModel() {
|
|
432
|
+
return `import { Model } from '@tyravel/database';
|
|
433
|
+
import type { Authenticatable } from '@tyravel/auth';
|
|
434
|
+
|
|
435
|
+
export interface UserAttributes {
|
|
436
|
+
id: number;
|
|
437
|
+
name: string;
|
|
438
|
+
email: string;
|
|
439
|
+
password: string;
|
|
440
|
+
}
|
|
441
|
+
|
|
442
|
+
export class User extends Model<UserAttributes> implements Authenticatable {
|
|
443
|
+
static override table = 'users';
|
|
444
|
+
|
|
445
|
+
getAuthIdentifier(): number {
|
|
446
|
+
return Number(this.get('id'));
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
getAuthPassword(): string {
|
|
450
|
+
return String(this.get('password'));
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
`;
|
|
454
|
+
}
|
|
455
|
+
export function usersTableMigration() {
|
|
456
|
+
return `import { Migration } from '@tyravel/database';
|
|
457
|
+
import type { DatabaseConnection } from '@tyravel/database';
|
|
458
|
+
import type { SchemaBuilder } from '@tyravel/database';
|
|
459
|
+
|
|
460
|
+
export default class CreateUsersTable extends Migration {
|
|
461
|
+
override async up(_connection: DatabaseConnection, schema: SchemaBuilder) {
|
|
462
|
+
await schema.create('users', (table) => {
|
|
463
|
+
table.id();
|
|
464
|
+
table.string('name');
|
|
465
|
+
table.string('email');
|
|
466
|
+
table.string('password');
|
|
467
|
+
table.integer('created_at').nullable();
|
|
468
|
+
table.integer('updated_at').nullable();
|
|
469
|
+
});
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
override async down(_connection: DatabaseConnection, schema: SchemaBuilder) {
|
|
473
|
+
await schema.drop('users');
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
`;
|
|
477
|
+
}
|
|
478
|
+
export function sessionsTableMigration() {
|
|
479
|
+
return `import { Migration } from '@tyravel/database';
|
|
480
|
+
import type { DatabaseConnection } from '@tyravel/database';
|
|
481
|
+
import type { SchemaBuilder } from '@tyravel/database';
|
|
482
|
+
|
|
483
|
+
export default class CreateSessionsTable extends Migration {
|
|
484
|
+
override async up(_connection: DatabaseConnection, schema: SchemaBuilder) {
|
|
485
|
+
await schema.create('sessions', (table) => {
|
|
486
|
+
table.string('id', 128);
|
|
487
|
+
table.unique('id');
|
|
488
|
+
table.integer('user_id').nullable();
|
|
489
|
+
table.string('ip_address').nullable();
|
|
490
|
+
table.text('user_agent').nullable();
|
|
491
|
+
table.text('payload');
|
|
492
|
+
table.integer('last_activity');
|
|
493
|
+
});
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
override async down(_connection: DatabaseConnection, schema: SchemaBuilder) {
|
|
497
|
+
await schema.drop('sessions');
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
`;
|
|
501
|
+
}
|
|
502
|
+
export function passwordResetTokensMigration() {
|
|
503
|
+
return `import { Migration } from '@tyravel/database';
|
|
504
|
+
import type { DatabaseConnection } from '@tyravel/database';
|
|
505
|
+
import type { SchemaBuilder } from '@tyravel/database';
|
|
506
|
+
|
|
507
|
+
export default class CreatePasswordResetTokensTable extends Migration {
|
|
508
|
+
override async up(_connection: DatabaseConnection, schema: SchemaBuilder) {
|
|
509
|
+
await schema.create('password_reset_tokens', (table) => {
|
|
510
|
+
table.string('email');
|
|
511
|
+
table.string('token');
|
|
512
|
+
table.integer('created_at');
|
|
513
|
+
table.unique('email');
|
|
514
|
+
});
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
override async down(_connection: DatabaseConnection, schema: SchemaBuilder) {
|
|
518
|
+
await schema.drop('password_reset_tokens');
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
`;
|
|
522
|
+
}
|
|
523
|
+
export function personalAccessTokensMigration() {
|
|
524
|
+
return `import { Migration } from '@tyravel/database';
|
|
525
|
+
import type { DatabaseConnection } from '@tyravel/database';
|
|
526
|
+
import type { SchemaBuilder } from '@tyravel/database';
|
|
527
|
+
|
|
528
|
+
export default class CreatePersonalAccessTokensTable extends Migration {
|
|
529
|
+
override async up(_connection: DatabaseConnection, schema: SchemaBuilder) {
|
|
530
|
+
await schema.create('personal_access_tokens', (table) => {
|
|
531
|
+
table.id();
|
|
532
|
+
table.string('tokenable_type');
|
|
533
|
+
table.integer('tokenable_id');
|
|
534
|
+
table.string('name');
|
|
535
|
+
table.string('token', 64);
|
|
536
|
+
table.text('abilities').nullable();
|
|
537
|
+
table.integer('last_used_at').nullable();
|
|
538
|
+
table.integer('expires_at').nullable();
|
|
539
|
+
table.integer('created_at').nullable();
|
|
540
|
+
});
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
override async down(_connection: DatabaseConnection, schema: SchemaBuilder) {
|
|
544
|
+
await schema.drop('personal_access_tokens');
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
`;
|
|
548
|
+
}
|
|
549
|
+
export function oauthAccountsMigration() {
|
|
550
|
+
return `import { Migration } from '@tyravel/database';
|
|
551
|
+
import type { DatabaseConnection } from '@tyravel/database';
|
|
552
|
+
import type { SchemaBuilder } from '@tyravel/database';
|
|
553
|
+
|
|
554
|
+
export default class CreateOauthAccountsTable extends Migration {
|
|
555
|
+
override async up(_connection: DatabaseConnection, schema: SchemaBuilder) {
|
|
556
|
+
await schema.create('oauth_accounts', (table) => {
|
|
557
|
+
table.id();
|
|
558
|
+
table.integer('user_id');
|
|
559
|
+
table.string('provider');
|
|
560
|
+
table.string('provider_user_id');
|
|
561
|
+
table.string('email').nullable();
|
|
562
|
+
table.string('avatar').nullable();
|
|
563
|
+
table.integer('created_at').nullable();
|
|
564
|
+
table.unique(['provider', 'provider_user_id']);
|
|
565
|
+
});
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
override async down(_connection: DatabaseConnection, schema: SchemaBuilder) {
|
|
569
|
+
await schema.drop('oauth_accounts');
|
|
570
|
+
}
|
|
571
|
+
}
|
|
572
|
+
`;
|
|
573
|
+
}
|
|
574
|
+
export function postPolicyStub() {
|
|
575
|
+
return `import { Policy } from '@tyravel/auth';
|
|
576
|
+
import type { Authenticatable } from '@tyravel/auth';
|
|
577
|
+
|
|
578
|
+
export class PostPolicy extends Policy {
|
|
579
|
+
update(user: Authenticatable, _post: unknown): boolean {
|
|
580
|
+
return user.getAuthIdentifier() !== undefined;
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
`;
|
|
584
|
+
}
|
|
585
|
+
export function authController() {
|
|
586
|
+
return `import type { TyravelRequest } from '@tyravel/http';
|
|
587
|
+
import { Response } from '@tyravel/http';
|
|
588
|
+
import { Auth, Password } from '@tyravel/core';
|
|
589
|
+
import type { Application } from '@tyravel/core';
|
|
590
|
+
import { OAuthManager } from '@tyravel/auth';
|
|
591
|
+
|
|
592
|
+
export class AuthController {
|
|
593
|
+
constructor(private readonly app: Application) {}
|
|
594
|
+
|
|
595
|
+
async login(request: TyravelRequest) {
|
|
596
|
+
const body = await request.json<{ email?: string; password?: string }>();
|
|
597
|
+
await Auth.attempt({
|
|
598
|
+
email: body.email ?? '',
|
|
599
|
+
password: body.password ?? '',
|
|
600
|
+
});
|
|
601
|
+
|
|
602
|
+
return Response.json({
|
|
603
|
+
user: {
|
|
604
|
+
id: Auth.id(),
|
|
605
|
+
},
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
async logout(_request: TyravelRequest) {
|
|
610
|
+
await Auth.logout();
|
|
611
|
+
return Response.json({ message: 'Logged out.' });
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
me(request: TyravelRequest) {
|
|
615
|
+
return Response.json({
|
|
616
|
+
user: request.user,
|
|
617
|
+
});
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
async forgotPassword(request: TyravelRequest) {
|
|
621
|
+
const body = await request.json<{ email?: string }>();
|
|
622
|
+
const token = await Password.sendResetLink(body.email ?? '');
|
|
623
|
+
return Response.json({
|
|
624
|
+
message: 'Password reset link generated.',
|
|
625
|
+
token,
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
async resetPassword(request: TyravelRequest) {
|
|
630
|
+
const body = await request.json<{
|
|
631
|
+
email?: string;
|
|
632
|
+
token?: string;
|
|
633
|
+
password?: string;
|
|
634
|
+
}>();
|
|
635
|
+
await Password.reset({
|
|
636
|
+
email: body.email ?? '',
|
|
637
|
+
token: body.token ?? '',
|
|
638
|
+
password: body.password ?? '',
|
|
639
|
+
});
|
|
640
|
+
return Response.json({ message: 'Password has been reset.' });
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
async createToken(request: TyravelRequest) {
|
|
644
|
+
const body = await request.json<{ name?: string; abilities?: string[] }>();
|
|
645
|
+
const token = await Auth.createToken(body.name ?? 'api', body.abilities);
|
|
646
|
+
return Response.json({
|
|
647
|
+
name: token.name,
|
|
648
|
+
plainTextToken: token.plainTextToken,
|
|
649
|
+
abilities: token.abilities,
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
oauthRedirect(request: TyravelRequest) {
|
|
654
|
+
const provider = request.param('provider');
|
|
655
|
+
const oauth = this.app.make(OAuthManager);
|
|
656
|
+
const state = oauth.createState();
|
|
657
|
+
request.session?.put(\`oauth.\${provider}.state\`, state);
|
|
658
|
+
const url = oauth.redirectUrl(provider, state);
|
|
659
|
+
return Response.redirect(url, 302);
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
async oauthCallback(request: TyravelRequest) {
|
|
663
|
+
const provider = request.param('provider');
|
|
664
|
+
const oauth = this.app.make(OAuthManager);
|
|
665
|
+
const url = new URL(request.url);
|
|
666
|
+
const code = url.searchParams.get('code') ?? '';
|
|
667
|
+
const state = url.searchParams.get('state') ?? '';
|
|
668
|
+
const expected = request.session?.get<string>(\`oauth.\${provider}.state\`);
|
|
669
|
+
if (!expected || expected !== state) {
|
|
670
|
+
return Response.json({ message: 'Invalid OAuth state.' }, { status: 422 });
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
const profile = await oauth.handleCallback(provider, code, state);
|
|
674
|
+
const user = await oauth.findOrCreateUser(provider, profile);
|
|
675
|
+
await Auth.login(user);
|
|
676
|
+
return Response.redirect('/', 302);
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
`;
|
|
680
|
+
}
|
|
681
|
+
export function authRoutes() {
|
|
682
|
+
return `import { Route } from '@tyravel/core';
|
|
683
|
+
import { AuthController } from '../controllers/AuthController.js';
|
|
684
|
+
|
|
685
|
+
Route.middleware('guest').post('/login', [AuthController, 'login']);
|
|
686
|
+
Route.middleware('auth').post('/logout', [AuthController, 'logout']);
|
|
687
|
+
Route.middleware('auth').get('/me', [AuthController, 'me']);
|
|
688
|
+
Route.middleware('guest').post('/forgot-password', [AuthController, 'forgotPassword']);
|
|
689
|
+
Route.middleware('guest').post('/reset-password', [AuthController, 'resetPassword']);
|
|
690
|
+
Route.middleware('auth').post('/tokens', [AuthController, 'createToken']);
|
|
691
|
+
Route.middleware('guest').get('/auth/:provider/redirect', [AuthController, 'oauthRedirect']);
|
|
692
|
+
Route.middleware('guest').get('/auth/:provider/callback', [AuthController, 'oauthCallback']);
|
|
693
|
+
`;
|
|
694
|
+
}
|
|
695
|
+
export function appServiceProviderWithAuth() {
|
|
696
|
+
return `import { ServiceProvider } from '@tyravel/core';
|
|
697
|
+
import { AuthController } from '../controllers/AuthController.js';
|
|
698
|
+
|
|
699
|
+
export class AppServiceProvider extends ServiceProvider {
|
|
700
|
+
override register() {
|
|
701
|
+
this.app.instance('app.name', 'Tyravel');
|
|
702
|
+
this.app.bind(AuthController, () => new AuthController(this.app));
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
`;
|
|
706
|
+
}
|
|
707
|
+
export function mainEntryWithAuth() {
|
|
708
|
+
return `import {
|
|
709
|
+
Application,
|
|
710
|
+
AuthServiceProvider,
|
|
711
|
+
ConfigServiceProvider,
|
|
712
|
+
DatabaseServiceProvider,
|
|
713
|
+
EventServiceProvider,
|
|
714
|
+
HttpKernel,
|
|
715
|
+
QueueServiceProvider,
|
|
716
|
+
setAuthApplication,
|
|
717
|
+
setEventApplication,
|
|
718
|
+
setGateApplication,
|
|
719
|
+
setPasswordApplication,
|
|
720
|
+
setQueueApplication,
|
|
721
|
+
setRouteApplication,
|
|
722
|
+
setViewApplication,
|
|
723
|
+
ViewServiceProvider,
|
|
724
|
+
serve,
|
|
725
|
+
} from '@tyravel/core';
|
|
726
|
+
import { AppServiceProvider } from './providers/app-service-provider.js';
|
|
727
|
+
import './routes/web.js';
|
|
728
|
+
import './routes/auth.js';
|
|
729
|
+
|
|
730
|
+
const app = new Application(import.meta.dir);
|
|
731
|
+
setRouteApplication(app);
|
|
732
|
+
setViewApplication(app);
|
|
733
|
+
setQueueApplication(app);
|
|
734
|
+
setEventApplication(app);
|
|
735
|
+
setAuthApplication(app);
|
|
736
|
+
setGateApplication(app);
|
|
737
|
+
setPasswordApplication(app);
|
|
738
|
+
|
|
739
|
+
app.register(ConfigServiceProvider);
|
|
740
|
+
app.register(DatabaseServiceProvider);
|
|
741
|
+
app.register(QueueServiceProvider);
|
|
742
|
+
app.register(EventServiceProvider);
|
|
743
|
+
app.register(AuthServiceProvider);
|
|
744
|
+
app.register(ViewServiceProvider);
|
|
745
|
+
app.register(AppServiceProvider);
|
|
746
|
+
|
|
747
|
+
await app.boot();
|
|
748
|
+
|
|
749
|
+
const kernel = new HttpKernel(app);
|
|
750
|
+
await serve(kernel);
|
|
751
|
+
`;
|
|
752
|
+
}
|
|
753
|
+
//# sourceMappingURL=stubs.js.map
|