@bejibun/core 0.1.39 → 0.1.40

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 (56) hide show
  1. package/CHANGELOG.md +34 -0
  2. package/bases/BaseController.d.ts +1 -1
  3. package/builders/RouterBuilder.d.ts +4 -0
  4. package/builders/RouterBuilder.js +24 -2
  5. package/bun.lock +12 -5
  6. package/commands/Kernel.d.ts +1 -0
  7. package/commands/Kernel.js +28 -13
  8. package/commands/{DbSeedCommand.d.ts → db/DbSeedCommand.d.ts} +2 -2
  9. package/commands/{DbSeedCommand.js → db/DbSeedCommand.js} +2 -2
  10. package/commands/maintenance/MaintenanceDownCommand.d.ts +27 -0
  11. package/commands/maintenance/MaintenanceDownCommand.js +40 -0
  12. package/commands/{MigrateFreshCommand.d.ts → migrate/MigrateFreshCommand.d.ts} +2 -2
  13. package/commands/{MigrateFreshCommand.js → migrate/MigrateFreshCommand.js} +5 -4
  14. package/commands/{MigrateLatestCommand.d.ts → migrate/MigrateLatestCommand.d.ts} +2 -2
  15. package/commands/{MigrateLatestCommand.js → migrate/MigrateLatestCommand.js} +2 -2
  16. package/commands/{MigrateRollbackCommand.d.ts → migrate/MigrateRollbackCommand.d.ts} +2 -2
  17. package/commands/{MigrateRollbackCommand.js → migrate/MigrateRollbackCommand.js} +5 -4
  18. package/commands/{MigrateStatusCommand.d.ts → migrate/MigrateStatusCommand.d.ts} +2 -2
  19. package/commands/{MigrateStatusCommand.js → migrate/MigrateStatusCommand.js} +5 -4
  20. package/config/database.js +2 -2
  21. package/facades/Router.d.ts +1 -0
  22. package/facades/Router.js +5 -14
  23. package/package.json +4 -3
  24. package/types/router.d.ts +1 -1
  25. package/src/ace.ts +0 -22
  26. package/src/bases/BaseController.ts +0 -139
  27. package/src/bases/BaseModel.ts +0 -108
  28. package/src/bases/BaseValidator.ts +0 -8
  29. package/src/bases/index.ts +0 -3
  30. package/src/bootstrap.ts +0 -5
  31. package/src/builders/ResponseBuilder.ts +0 -54
  32. package/src/builders/RouterBuilder.ts +0 -173
  33. package/src/commands/DbSeedCommand.ts +0 -57
  34. package/src/commands/Kernel.ts +0 -49
  35. package/src/commands/MigrateFreshCommand.ts +0 -76
  36. package/src/commands/MigrateLatestCommand.ts +0 -56
  37. package/src/commands/MigrateRollbackCommand.ts +0 -72
  38. package/src/commands/MigrateStatusCommand.ts +0 -64
  39. package/src/config/database.ts +0 -41
  40. package/src/exceptions/ModelNotFoundException.ts +0 -15
  41. package/src/exceptions/RouterInvalidException.ts +0 -15
  42. package/src/exceptions/ValidatorException.ts +0 -15
  43. package/src/exceptions/index.ts +0 -3
  44. package/src/facades/Response.ts +0 -15
  45. package/src/facades/Router.ts +0 -89
  46. package/src/facades/SoftDeletes.ts +0 -66
  47. package/src/facades/index.ts +0 -3
  48. package/src/index.ts +0 -5
  49. package/src/types/index.d.ts +0 -4
  50. package/src/types/middleware.d.ts +0 -7
  51. package/src/types/router.d.ts +0 -5
  52. package/src/types/validator.d.ts +0 -3
  53. package/src/types/vine.d.ts +0 -13
  54. package/src/utils/vine.ts +0 -2
  55. package/src/utils/vines/exists.ts +0 -41
  56. package/src/utils/vines/unique.ts +0 -41
@@ -1,139 +0,0 @@
1
- import {defineValue, isEmpty, isNotEmpty} from "@bejibun/utils";
2
- import {errors, VineValidator} from "@vinejs/vine";
3
- import {BunRequest} from "bun";
4
- import {DateTime} from "luxon";
5
- import ValidatorException from "@/exceptions/ValidatorException";
6
- import Response from "@/facades/Response";
7
-
8
- export default class BaseController {
9
- public async parse(request: BunRequest): Promise<Record<string, any>> {
10
- const contentType = defineValue(request.headers.get("content-type"), "");
11
- const formData = new FormData();
12
-
13
- try {
14
- if (contentType.includes("application/json")) return await request.json();
15
-
16
- for (const [key, value] of Object.entries(request.params)) {
17
- formData.append(key, value as string);
18
- }
19
-
20
- const url = new URL(request.url);
21
- for (const [key, value] of url.searchParams) {
22
- formData.append(key, value);
23
- }
24
-
25
- if (
26
- contentType.includes("multipart/form-data") ||
27
- contentType.includes("application/x-www-form-urlencoded")
28
- ) {
29
- const body = await request.formData();
30
-
31
- for (const [key, value] of body) {
32
- formData.append(key, value);
33
- }
34
- }
35
-
36
- const text = await request.text();
37
- if (isNotEmpty(text)) formData.append("text", text);
38
- } catch {
39
- // do nothing
40
- }
41
-
42
- return this.parseForm(formData);
43
- }
44
-
45
- public get response(): typeof Response {
46
- return Response;
47
- }
48
-
49
- public async validate(validator: VineValidator<any, Record<string, any> | undefined>, body: Record<string, any>): Promise<any> {
50
- try {
51
- return await validator.validate(body);
52
- } catch (error: typeof errors.E_VALIDATION_ERROR | any) {
53
- throw new ValidatorException(error.messages[0].message);
54
- }
55
- }
56
-
57
- private serialize(data: any): any {
58
- if (Array.isArray(data)) return data.map((value: any) => this.serialize(value));
59
-
60
- if (data === null || data === undefined) return null;
61
-
62
- if (data instanceof DateTime) return data.isValid ? data.toISO() : null;
63
-
64
- if (data instanceof Date) return Number.isNaN(data.getTime()) ? null : data.toISOString();
65
-
66
- if (typeof data === "object" && !(data instanceof File)) {
67
- if (Object.keys(data).length === 0) return null;
68
-
69
- const nested: Record<string, any> = {};
70
- Object.keys(data).forEach((key: string) => {
71
- nested[key] = this.serialize(data[key]);
72
- });
73
-
74
- return nested;
75
- }
76
-
77
- if (typeof data === "string") {
78
- const trimmed: string = data.trim();
79
-
80
- if (trimmed === "") return null;
81
- if (trimmed === "true") return true;
82
- if (trimmed === "false") return false;
83
-
84
- const numeric = Number(trimmed);
85
- if (!Number.isNaN(numeric) && trimmed === numeric.toString()) return numeric;
86
-
87
- return trimmed;
88
- }
89
-
90
- return data;
91
- }
92
-
93
- private parseForm(formData: FormData): Record<string, any> {
94
- const result: Record<string, any> = {};
95
-
96
- for (const [key, value] of formData.entries()) {
97
- const keys = key.replace(/]/g, "").split("[");
98
-
99
- let current: any = result;
100
-
101
- for (let i = 0; i < keys.length; i++) {
102
- const part = keys[i];
103
- const nextPart = keys[i + 1];
104
-
105
- if (i === keys.length - 1) {
106
- let convertedValue: any;
107
-
108
- if (value as unknown instanceof File) {
109
- convertedValue = value;
110
- } else if (value.trim() === "") {
111
- convertedValue = null;
112
- } else if (Number.isNaN(value)) {
113
- convertedValue = Number(value);
114
- } else if (value === "true" || value === "false") {
115
- convertedValue = value === "true";
116
- } else {
117
- try {
118
- convertedValue = JSON.parse(value);
119
- } catch {
120
- convertedValue = value;
121
- }
122
- }
123
-
124
- if (current[part] === undefined) current[part] = convertedValue;
125
- else if (Array.isArray(current[part])) current[part].push(convertedValue);
126
- else current[part] = [current[part], convertedValue];
127
- } else {
128
- const isArrayIndex = /^\d+$/.test(nextPart);
129
-
130
- if (isEmpty(current[part])) current[part] = isArrayIndex ? [] : {};
131
-
132
- current = current[part];
133
- }
134
- }
135
- }
136
-
137
- return result;
138
- }
139
- }
@@ -1,108 +0,0 @@
1
- import type {Knex} from "knex";
2
- import {defineValue, isEmpty} from "@bejibun/utils";
3
- import Str from "@bejibun/utils/facades/Str";
4
- import {DateTime} from "luxon";
5
- import {
6
- Constructor,
7
- Model,
8
- ModelOptions,
9
- PartialModelObject,
10
- QueryBuilder,
11
- QueryBuilderType,
12
- QueryContext,
13
- TransactionOrKnex
14
- } from "objection";
15
- import {relative, sep} from "path";
16
- import {fileURLToPath} from "url";
17
- import ModelNotFoundException from "@/exceptions/ModelNotFoundException";
18
- import SoftDeletes from "@/facades/SoftDeletes";
19
-
20
- export interface BaseColumns {
21
- id: bigint | number;
22
- created_at: DateTime | string;
23
- updated_at: DateTime | string;
24
- deleted_at: DateTime | string | null;
25
- }
26
-
27
- class BunQueryBuilder<M extends Model, R = M[]> extends SoftDeletes<M, R> {
28
- // @ts-ignore
29
- async update(payload: PartialModelObject<M>): Promise<QueryBuilder<M, R>> {
30
- const cloneQuery: QueryBuilder<M, R> = (this as any).clone();
31
-
32
- const beforeRows: any = await cloneQuery;
33
-
34
- if (isEmpty(beforeRows)) return defineValue(beforeRows);
35
-
36
- await super.update(payload);
37
-
38
- return cloneQuery;
39
- }
40
- }
41
-
42
- // @ts-ignore
43
- export default class BaseModel extends Model implements BaseColumns {
44
- public static tableName: string;
45
- public static idColumn: string;
46
- public static deletedColumn: string = "deleted_at";
47
-
48
- public static QueryBuilder = BunQueryBuilder;
49
-
50
- declare id: number | bigint;
51
- declare created_at: DateTime | string;
52
- declare updated_at: DateTime | string;
53
- declare deleted_at: DateTime | string | null;
54
-
55
- public static get namespace(): string {
56
- const filePath = fileURLToPath(import.meta.url);
57
- const appRoot = process.cwd();
58
- const rel = relative(appRoot, filePath);
59
- const withoutExt = rel.replace(/\.[tj]s$/, "");
60
- const namespaces = withoutExt.split(sep);
61
- namespaces.pop();
62
- namespaces.push(this.name);
63
-
64
- return namespaces.map(part => Str.toPascalCase(part)).join("/");
65
- }
66
-
67
- $beforeInsert(queryContext: QueryContext): void {
68
- const now = DateTime.now();
69
- this.created_at = now;
70
- this.updated_at = now;
71
- }
72
-
73
- $beforeUpdate(opt: ModelOptions, queryContext: QueryContext): void {
74
- this.updated_at = DateTime.now();
75
- }
76
-
77
- public static query<T extends Model>(this: Constructor<T>, trxOrKnex?: TransactionOrKnex): QueryBuilderType<T> {
78
- return super.query(trxOrKnex);
79
- };
80
-
81
- public static withTrashed<T extends Model>(this: T): QueryBuilderType<T> {
82
- return (this as any).query().withTrashed();
83
- }
84
-
85
- public static onlyTrashed<T extends Model>(this: T): QueryBuilderType<T> {
86
- return (this as any).query().onlyTrashed();
87
- }
88
-
89
- public static all<T extends Model>(this: T): QueryBuilderType<T> {
90
- return (this as any).query().select();
91
- }
92
-
93
- public static create<T extends Model>(this: T, payload: Record<string, any>): QueryBuilderType<T> {
94
- return (this as any).query().insert(payload);
95
- }
96
-
97
- public static find<T extends Model>(this: T, id: bigint | number | string): QueryBuilderType<T> {
98
- return (this as any).query().findById(id);
99
- }
100
-
101
- public static async findOrFail<T extends Model>(this: T, id: bigint | number | string): Promise<T> {
102
- const result = await (this as any).find(id);
103
-
104
- if (isEmpty(result)) throw new ModelNotFoundException(`[ModelNotFoundException]: No query results for model [${(this as any).namespace}] [${id}].`);
105
-
106
- return result;
107
- }
108
- }
@@ -1,8 +0,0 @@
1
- import vine from "@vinejs/vine";
2
- import "@/utils/vine";
3
-
4
- export default class BaseValidator {
5
- public static get validator(): typeof vine {
6
- return vine;
7
- }
8
- }
@@ -1,3 +0,0 @@
1
- export * from "@/bases/BaseController";
2
- export * from "@/bases/BaseModel";
3
- export * from "@/bases/BaseValidator";
package/src/bootstrap.ts DELETED
@@ -1,5 +0,0 @@
1
- import {Model} from "objection";
2
- import BaseModel from "@/bases/BaseModel";
3
- import {initDatabase} from "@/config/database";
4
-
5
- (BaseModel as any as typeof Model).knex(initDatabase());
@@ -1,54 +0,0 @@
1
- import Cors from "@bejibun/cors";
2
-
3
- export default class ResponseBuilder {
4
- protected data?: any;
5
- protected message: string;
6
- protected status: number;
7
-
8
- public constructor() {
9
- this.data = null;
10
- this.message = "Success";
11
- this.status = 200;
12
- }
13
-
14
- public setData(data?: any): ResponseBuilder {
15
- this.data = data;
16
-
17
- return this;
18
- }
19
-
20
- public setMessage(message: string): ResponseBuilder {
21
- this.message = message;
22
-
23
- return this;
24
- }
25
-
26
- public setStatus(status: number): ResponseBuilder {
27
- this.status = status;
28
-
29
- return this;
30
- }
31
-
32
- public send(): globalThis.Response {
33
- return globalThis.Response.json({
34
- data: this.data,
35
- message: this.message,
36
- status: this.status
37
- }, {
38
- headers: {
39
- ...Cors.init
40
- },
41
- status: this.status
42
- });
43
- }
44
-
45
- public stream(options: ResponseInit = {}): globalThis.Response {
46
- return new globalThis.Response(Bun.file(this.data), {
47
- ...options,
48
- headers: {
49
- ...Cors.init
50
- },
51
- status: this.status
52
- });
53
- }
54
- }
@@ -1,173 +0,0 @@
1
- import {isEmpty} from "@bejibun/utils";
2
- import HttpMethodEnum from "@bejibun/utils/enums/HttpMethodEnum";
3
- import path from "path";
4
- import type {IMiddleware} from "@/types/middleware";
5
- import type {HandlerType, ResourceAction, RouterGroup} from "@/types/router";
6
- import RouterInvalidException from "@/exceptions/RouterInvalidException";
7
-
8
- export interface ResourceOptions {
9
- only?: Array<ResourceAction>;
10
- except?: Array<ResourceAction>;
11
- }
12
-
13
- export default class RouterBuilder {
14
- private basePath: string = "";
15
- private middlewares: Array<IMiddleware> = [];
16
-
17
- public prefix(basePath: string): RouterBuilder {
18
- this.basePath = basePath;
19
-
20
- return this;
21
- }
22
-
23
- public middleware(...middlewares: Array<IMiddleware>): RouterBuilder {
24
- this.middlewares.push(...middlewares);
25
-
26
- return this;
27
- }
28
-
29
- public group(routes: RouterGroup | Array<RouterGroup>): RouterGroup {
30
- const routeList = Array.isArray(routes) ? routes : [routes];
31
- const newRoutes: RouterGroup = {};
32
-
33
- for (const route of routeList) {
34
- for (const path in route) {
35
- const fullPath = this.joinPaths(this.basePath, path);
36
- const routeHandlers = route[path];
37
- const wrappedHandlers: Record<string, HandlerType> = {};
38
-
39
- for (const method in routeHandlers) {
40
- let handler = routeHandlers[method];
41
-
42
- for (const middleware of this.middlewares) {
43
- handler = middleware.handle(handler);
44
- }
45
-
46
- wrappedHandlers[method] = handler;
47
- }
48
-
49
- if (isEmpty(newRoutes[fullPath])) newRoutes[fullPath] = {};
50
-
51
- Object.assign(newRoutes[fullPath], wrappedHandlers);
52
- }
53
- }
54
-
55
- return newRoutes;
56
- }
57
-
58
- public resources(controller: Record<string, HandlerType>, options?: ResourceOptions): RouterGroup {
59
- const allRoutes: Record<string, Record<string, ResourceAction>> = {
60
- "": {
61
- GET: "index",
62
- POST: "store"
63
- },
64
- ":id": {
65
- GET: "show",
66
- PUT: "update",
67
- DELETE: "destroy"
68
- }
69
- };
70
-
71
- const includedActions = this.resolveIncludedActions(options);
72
-
73
- const filteredRoutes: RouterGroup = {};
74
-
75
- for (const path in allRoutes) {
76
- const methods = allRoutes[path];
77
- const methodHandlers: Record<string, HandlerType> = {};
78
-
79
- for (const method in methods) {
80
- const action = methods[method];
81
- if (includedActions.has(action) && controller[action]) {
82
- methodHandlers[method] = controller[action];
83
- }
84
- }
85
-
86
- if (Object.keys(methodHandlers).length > 0) {
87
- filteredRoutes[path] = methodHandlers;
88
- }
89
- }
90
-
91
- return this.group(filteredRoutes);
92
- }
93
-
94
- public buildSingle(method: HttpMethodEnum, path: string, handler: string | HandlerType): RouterGroup {
95
- const cleanPath = this.joinPaths(this.basePath, path);
96
-
97
- let resolvedHandler: HandlerType = typeof handler === "string" ?
98
- this.resolveControllerString(handler) :
99
- handler;
100
-
101
- for (const middleware of this.middlewares) {
102
- resolvedHandler = middleware.handle(resolvedHandler);
103
- }
104
-
105
- return {
106
- [cleanPath]: {
107
- [method]: resolvedHandler
108
- }
109
- };
110
- }
111
-
112
- private joinPaths(base: string, path: string): string {
113
- base = base.replace(/\/+$/, "");
114
- path = path.replace(/^\/+/, "");
115
-
116
- return "/" + [base, path].filter(Boolean).join("/");
117
- }
118
-
119
- private resolveControllerString(definition: string): HandlerType {
120
- const [controllerName, methodName] = definition.split("@");
121
-
122
- if (isEmpty(controllerName) || isEmpty(methodName)) {
123
- throw new RouterInvalidException(`[RouterInvalidException]: Invalid router controller definition: ${definition}.`);
124
- }
125
-
126
- const controllerPath = path.resolve(process.cwd(), "app/controllers");
127
- const location = `${controllerPath}/${controllerName}`;
128
-
129
- let ControllerClass: any;
130
-
131
- try {
132
- ControllerClass = require(location).default;
133
- } catch {
134
- return async (...args: any[]) => {
135
- const module = await import(location);
136
- const ESMController = module.default;
137
- const instance = new ESMController();
138
-
139
- if (typeof instance[methodName] !== "function") {
140
- throw new RouterInvalidException(`[RouterInvalidException]: Method "${methodName}" not found in ${controllerName}.`);
141
- }
142
-
143
- return instance[methodName](...args);
144
- };
145
- }
146
-
147
- if (isEmpty(ControllerClass)) {
148
- throw new RouterInvalidException(`[RouterInvalidException]: Controller not found: ${controllerName}.`);
149
- }
150
-
151
- const instance = new ControllerClass();
152
-
153
- if (typeof instance[methodName] !== "function") {
154
- throw new RouterInvalidException(`[RouterInvalidException]: Method "${methodName}" not found in ${controllerName}.`);
155
- }
156
-
157
- return instance[methodName].bind(instance);
158
- }
159
-
160
- private resolveIncludedActions(options?: ResourceOptions): Set<ResourceAction> {
161
- const all: Array<ResourceAction> = ["index", "store", "show", "update", "destroy"];
162
-
163
- if (options?.only) {
164
- return new Set(options.only);
165
- }
166
-
167
- if (options?.except) {
168
- return new Set(all.filter(action => !options.except!.includes(action)));
169
- }
170
-
171
- return new Set(all);
172
- }
173
- }
@@ -1,57 +0,0 @@
1
- import Chalk from "@bejibun/logger/facades/Chalk";
2
- import ora from "ora";
3
- import path from "path";
4
- import {initDatabase} from "@/config/database";
5
-
6
- export default class DbSeedCommand {
7
- /**
8
- * The name and signature of the console command.
9
- *
10
- * @var $signature string
11
- */
12
- protected $signature: string = "db:seed";
13
-
14
- /**
15
- * The console command description.
16
- *
17
- * @var $description string
18
- */
19
- protected $description: string = "Run database seeders";
20
-
21
- /**
22
- * The options or optional flag of the console command.
23
- *
24
- * @var $options Array<Array<string>>
25
- */
26
- protected $options: Array<Array<string>> = [];
27
-
28
- /**
29
- * The arguments of the console command.
30
- *
31
- * @var $arguments Array<Array<string>>
32
- */
33
- protected $arguments: Array<Array<string>> = [];
34
-
35
- public async handle(options: any, args: Array<string>): Promise<void> {
36
- const database = initDatabase();
37
-
38
- const spinner = ora(
39
- Chalk.setValue("Seeding...")
40
- .info()
41
- .show()
42
- ).start();
43
-
44
- try {
45
- const logs = (await database.seed.run()).flat();
46
- spinner.succeed("Seeding finished");
47
-
48
- if (logs.length > 0) logs.forEach((seeder: string) => spinner.succeed(path.basename(seeder)));
49
- else spinner.succeed("No seeders were run.");
50
- } catch (error: any) {
51
- spinner.fail(`Seeding failed : ${error.message}`);
52
- } finally {
53
- await database.destroy();
54
- spinner.stop();
55
- }
56
- }
57
- }
@@ -1,49 +0,0 @@
1
- import type {Command} from "commander";
2
- import {defineValue, isEmpty} from "@bejibun/utils";
3
- import {readdirSync} from "fs";
4
- import path from "path";
5
-
6
- export default class Kernel {
7
- public static registerCommands(program: Command): void {
8
- const commandsDir = path.resolve(__dirname);
9
- const files = readdirSync(commandsDir).filter((file: string) => {
10
- return (
11
- /\.(m?js|ts)$/.test(file) &&
12
- !file.endsWith(".d.ts") &&
13
- !file.includes("Kernel")
14
- )
15
- });
16
-
17
- for (const file of files) {
18
- const modulePath = path.join(commandsDir, file);
19
- const {default: CommandClass} = require(modulePath);
20
-
21
- const instance = new CommandClass();
22
-
23
- if (isEmpty(instance.$signature) || typeof instance.handle !== "function") continue;
24
-
25
- const cmd = program
26
- .command(instance.$signature)
27
- .description(defineValue(instance.$description, ""))
28
- .action(instance.handle);
29
-
30
- if (Array.isArray(instance.$options)) {
31
- for (const option of instance.$options) {
32
- cmd.option(...(option as [string, string?, any?]));
33
- }
34
- }
35
-
36
- if (Array.isArray(instance.$arguments)) {
37
- for (const argument of instance.$arguments) {
38
- cmd.argument(...(argument as [string, string?, unknown?]));
39
- }
40
- }
41
-
42
- cmd.action(async (...args: any[]) => {
43
- const lastArg = args[args.length - 1];
44
- const options = defineValue(lastArg, {});
45
- await instance.handle(options, args.slice(0, -1));
46
- });
47
- }
48
- }
49
- }
@@ -1,76 +0,0 @@
1
- import Chalk from "@bejibun/logger/facades/Chalk";
2
- import {ask, isNotEmpty} from "@bejibun/utils";
3
- import ora from "ora";
4
- import {initDatabase} from "@/config/database";
5
-
6
- export default class MigrateFreshCommand {
7
- /**
8
- * The name and signature of the console command.
9
- *
10
- * @var $signature string
11
- */
12
- protected $signature: string = "migrate:fresh";
13
-
14
- /**
15
- * The console command description.
16
- *
17
- * @var $description string
18
- */
19
- protected $description: string = "Rollback all migrations and re-run migrations";
20
-
21
- /**
22
- * The options or optional flag of the console command.
23
- *
24
- * @var $options Array<Array<string>>
25
- */
26
- protected $options: Array<Array<string>> = [
27
- ["-f, --force", "Skip command confirmation."]
28
- ];
29
-
30
- /**
31
- * The arguments of the console command.
32
- *
33
- * @var $arguments Array<Array<string>>
34
- */
35
- protected $arguments: Array<Array<string>> = [];
36
-
37
- public async handle(options: any, args: Array<string>): Promise<void> {
38
- const database = initDatabase();
39
-
40
- const bypass = isNotEmpty(options.force);
41
-
42
- let confirm = "Y";
43
- if (!bypass) confirm = await ask(
44
- Chalk.setValue("This will DROP ALL tables and re-run ALL migrations. Are you want to continue? (Y/N): ")
45
- .inline()
46
- .error()
47
- .show()
48
- );
49
-
50
- if (confirm.toUpperCase() === "Y") {
51
- if (!bypass) console.log();
52
-
53
- const spinner = ora(
54
- Chalk.setValue("Rollback...")
55
- .info()
56
- .show()
57
- ).start();
58
-
59
- try {
60
- await database.migrate.rollback({}, true);
61
- spinner.succeed("Rolled back all migrations");
62
-
63
- const [batchNo, logs] = await database.migrate.latest();
64
- spinner.succeed(`Batch ${batchNo} finished`);
65
-
66
- if (logs.length > 0) logs.forEach((migration: string) => spinner.succeed(migration));
67
- else spinner.succeed("No migrations were run.");
68
- } catch (error: any) {
69
- spinner.fail(`Migration failed : ${error.message}`);
70
- } finally {
71
- await database.destroy();
72
- spinner.stop();
73
- }
74
- }
75
- }
76
- }