@skalfa/skalfa-api 1.0.0 → 1.0.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/.env.example +75 -75
- package/.github/workflows/publish.yml +7 -0
- package/CONTRIBUTING.md +45 -0
- package/LICENSE +21 -0
- package/README.md +79 -85
- package/app/app.ts +74 -85
- package/app/controllers/base.controller.ts +16 -16
- package/app/controllers/iam/auth.controller.ts +143 -143
- package/app/controllers/iam/user.controller.ts +92 -92
- package/app/jobs/crons/index.ts +8 -8
- package/app/jobs/crons/worker.cron.ts +8 -8
- package/app/jobs/queues/access-log.queue.worker.ts +32 -32
- package/app/jobs/queues/activity-log.queue.worker.ts +32 -32
- package/app/jobs/queues/auth.queue.worker.ts +9 -9
- package/app/jobs/queues/error-log.queue.worker.ts +32 -32
- package/app/jobs/queues/notification.queue.worker.ts +11 -11
- package/app/jobs/queues/worker.queue.ts +37 -37
- package/app/jobs/sockets/worker.socket.ts +2 -2
- package/app/models/iam/user.model.ts +17 -17
- package/app/outputs/mails/templates/layout.mail.stub +102 -102
- package/app/outputs/mails/templates/user-mail-token.mail.stub +28 -28
- package/app/outputs/mails/user-mail-token.mail.ts +17 -17
- package/app/outputs/notifications/example.notification.ts +10 -0
- package/app/outputs/notifications/index.ts +1 -0
- package/app/routes/base.routes.ts +25 -25
- package/barrels.json +9 -9
- package/database/da.migrations/0000_00/activity_logs.ts +27 -27
- package/database/da.migrations/0000_00/logs.ts +41 -41
- package/database/migrations/0000_00/notifications.ts +28 -0
- package/database/migrations/0000_00/storages.ts +22 -22
- package/database/migrations/0000_00/users.ts +55 -55
- package/database/seeders/user.seeder.ts +23 -23
- package/eslint.config.mjs +36 -36
- package/package.json +40 -39
|
@@ -1,41 +1,41 @@
|
|
|
1
|
-
import { DAMigration } from "@utils"
|
|
2
|
-
|
|
3
|
-
export default class CreateAccessLogsTable extends DAMigration {
|
|
4
|
-
async up() {
|
|
5
|
-
await this.createTable("access_logs",(table) => {
|
|
6
|
-
table.uuid()
|
|
7
|
-
table.string("method")
|
|
8
|
-
table.string("path")
|
|
9
|
-
table.int32("status")
|
|
10
|
-
table.int32("latency")
|
|
11
|
-
table.string("ip")
|
|
12
|
-
table.string("agent")
|
|
13
|
-
table.dateTime("at")
|
|
14
|
-
}, {
|
|
15
|
-
engine: "MergeTree",
|
|
16
|
-
orderBy: ["at"],
|
|
17
|
-
partitionBy: "toYYYYMM(at)",
|
|
18
|
-
ttl: "at + INTERVAL 30 DAY DELETE"
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
await this.createTable("error_logs",(table) => {
|
|
22
|
-
table.uuid()
|
|
23
|
-
table.string("service")
|
|
24
|
-
table.string("key")
|
|
25
|
-
table.string("feature")
|
|
26
|
-
table.string("error")
|
|
27
|
-
table.string("reference")
|
|
28
|
-
table.dateTime("at")
|
|
29
|
-
}, {
|
|
30
|
-
engine: "MergeTree",
|
|
31
|
-
orderBy: ["at"],
|
|
32
|
-
partitionBy: "toYYYYMM(at)",
|
|
33
|
-
ttl: "at + INTERVAL 30 DAY DELETE"
|
|
34
|
-
})
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
async down() {
|
|
38
|
-
await this.dropTable("access_logs")
|
|
39
|
-
await this.dropTable("error_logs")
|
|
40
|
-
}
|
|
41
|
-
}
|
|
1
|
+
import { DAMigration } from "@utils"
|
|
2
|
+
|
|
3
|
+
export default class CreateAccessLogsTable extends DAMigration {
|
|
4
|
+
async up() {
|
|
5
|
+
await this.createTable("access_logs",(table) => {
|
|
6
|
+
table.uuid()
|
|
7
|
+
table.string("method")
|
|
8
|
+
table.string("path")
|
|
9
|
+
table.int32("status")
|
|
10
|
+
table.int32("latency")
|
|
11
|
+
table.string("ip")
|
|
12
|
+
table.string("agent")
|
|
13
|
+
table.dateTime("at")
|
|
14
|
+
}, {
|
|
15
|
+
engine: "MergeTree",
|
|
16
|
+
orderBy: ["at"],
|
|
17
|
+
partitionBy: "toYYYYMM(at)",
|
|
18
|
+
ttl: "at + INTERVAL 30 DAY DELETE"
|
|
19
|
+
})
|
|
20
|
+
|
|
21
|
+
await this.createTable("error_logs",(table) => {
|
|
22
|
+
table.uuid()
|
|
23
|
+
table.string("service")
|
|
24
|
+
table.string("key")
|
|
25
|
+
table.string("feature")
|
|
26
|
+
table.string("error")
|
|
27
|
+
table.string("reference")
|
|
28
|
+
table.dateTime("at")
|
|
29
|
+
}, {
|
|
30
|
+
engine: "MergeTree",
|
|
31
|
+
orderBy: ["at"],
|
|
32
|
+
partitionBy: "toYYYYMM(at)",
|
|
33
|
+
ttl: "at + INTERVAL 30 DAY DELETE"
|
|
34
|
+
})
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
async down() {
|
|
38
|
+
await this.dropTable("access_logs")
|
|
39
|
+
await this.dropTable("error_logs")
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Knex } from 'knex'
|
|
2
|
+
|
|
3
|
+
export async function up(knex: Knex): Promise<void> {
|
|
4
|
+
await knex.schema.createTable('notifications', (table) => {
|
|
5
|
+
table.bigIncrements('id').primary()
|
|
6
|
+
table.string('title')
|
|
7
|
+
table.string('body').nullable()
|
|
8
|
+
table.string('type').nullable()
|
|
9
|
+
table.string('redirect').nullable()
|
|
10
|
+
table.json('data').nullable()
|
|
11
|
+
table.timestamps(true, true)
|
|
12
|
+
table.timestamp('deleted_at', { useTz: true }).nullable().index()
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
await knex.schema.createTable('notification_users', (table) => {
|
|
16
|
+
table.bigIncrements('id').primary()
|
|
17
|
+
table.bigInteger('user_id').nullable().index()
|
|
18
|
+
table.bigInteger('notification_id').nullable().index()
|
|
19
|
+
table.timestamps(true, true)
|
|
20
|
+
table.timestamp('canceled_at', { useTz: true }).nullable().index()
|
|
21
|
+
table.timestamp('deleted_at', { useTz: true }).nullable().index()
|
|
22
|
+
})
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export async function down(knex: Knex): Promise<void> {
|
|
26
|
+
await knex.schema.dropTableIfExists('notification_users')
|
|
27
|
+
await knex.schema.dropTableIfExists('notifications')
|
|
28
|
+
}
|
|
@@ -1,22 +1,22 @@
|
|
|
1
|
-
import type { Knex } from 'knex'
|
|
2
|
-
|
|
3
|
-
export async function up(knex: Knex): Promise<void> {
|
|
4
|
-
await knex.schema.createTable('storages', (table) => {
|
|
5
|
-
table.bigIncrements('id').primary()
|
|
6
|
-
table.bigInteger('user_id').nullable().index()
|
|
7
|
-
table.string('disk').notNullable().index()
|
|
8
|
-
table.string('path').notNullable().index()
|
|
9
|
-
table.string('filename').nullable()
|
|
10
|
-
table.string('filetype').nullable()
|
|
11
|
-
table.string('filesize').nullable()
|
|
12
|
-
table.timestamps(true, true)
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
await knex.schema.createTable('storage_permissions', (table) => {
|
|
16
|
-
table.bigIncrements('id').primary()
|
|
17
|
-
table.bigInteger('storage_id').unsigned().notNullable().index()
|
|
18
|
-
table.bigInteger('user_id').nullable().index()
|
|
19
|
-
table.bigInteger('role_id').nullable().index()
|
|
20
|
-
table.timestamps(true, true)
|
|
21
|
-
})
|
|
22
|
-
}
|
|
1
|
+
import type { Knex } from 'knex'
|
|
2
|
+
|
|
3
|
+
export async function up(knex: Knex): Promise<void> {
|
|
4
|
+
await knex.schema.createTable('storages', (table) => {
|
|
5
|
+
table.bigIncrements('id').primary()
|
|
6
|
+
table.bigInteger('user_id').nullable().index()
|
|
7
|
+
table.string('disk').notNullable().index()
|
|
8
|
+
table.string('path').notNullable().index()
|
|
9
|
+
table.string('filename').nullable()
|
|
10
|
+
table.string('filetype').nullable()
|
|
11
|
+
table.string('filesize').nullable()
|
|
12
|
+
table.timestamps(true, true)
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
await knex.schema.createTable('storage_permissions', (table) => {
|
|
16
|
+
table.bigIncrements('id').primary()
|
|
17
|
+
table.bigInteger('storage_id').unsigned().notNullable().index()
|
|
18
|
+
table.bigInteger('user_id').nullable().index()
|
|
19
|
+
table.bigInteger('role_id').nullable().index()
|
|
20
|
+
table.timestamps(true, true)
|
|
21
|
+
})
|
|
22
|
+
}
|
|
@@ -1,56 +1,56 @@
|
|
|
1
|
-
import type { Knex } from "knex"
|
|
2
|
-
|
|
3
|
-
export async function up(knex: Knex): Promise<void> {
|
|
4
|
-
await knex.schema.createTable("users", (table) => {
|
|
5
|
-
table.bigIncrements("id").primary()
|
|
6
|
-
table.string("name").notNullable()
|
|
7
|
-
table.string("email").unique().notNullable()
|
|
8
|
-
table.string("password")
|
|
9
|
-
table.string("image")
|
|
10
|
-
table.timestamp("email_verification_at")
|
|
11
|
-
table.timestamps(true, true)
|
|
12
|
-
table.softDelete()
|
|
13
|
-
})
|
|
14
|
-
|
|
15
|
-
await knex.schema.createTable("user_roles", (table) => {
|
|
16
|
-
table.bigIncrements("id").primary()
|
|
17
|
-
table.string("name").notNullable()
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
await knex.schema.createTable("user_has_user_roles", (table) => {
|
|
21
|
-
table.bigIncrements("id").primary()
|
|
22
|
-
table.foreignIdFor("users").notNullable()
|
|
23
|
-
table.foreignIdFor("user_roles").notNullable()
|
|
24
|
-
table.softDelete()
|
|
25
|
-
})
|
|
26
|
-
|
|
27
|
-
await knex.schema.createTable("user_access_tokens", (table) => {
|
|
28
|
-
table.bigIncrements("id").primary()
|
|
29
|
-
table.foreignIdFor("users").notNullable()
|
|
30
|
-
table.string("agent").index().notNullable()
|
|
31
|
-
table.string("token").unique().index().notNullable()
|
|
32
|
-
table.json("permissions").defaultTo(knex.raw(`'[]'::json`))
|
|
33
|
-
table.string("last_used_ip").nullable()
|
|
34
|
-
table.timestamp("last_used_at")
|
|
35
|
-
table.timestamp("expired_at")
|
|
36
|
-
table.timestamps(true, true)
|
|
37
|
-
table.softDelete()
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
await knex.schema.createTable("user_mail_tokens", (table) => {
|
|
41
|
-
table.bigIncrements("id").primary()
|
|
42
|
-
table.foreignIdFor("users").notNullable()
|
|
43
|
-
table.string("token").unique().notNullable()
|
|
44
|
-
table.timestamp("used_at")
|
|
45
|
-
table.timestamps(true, true)
|
|
46
|
-
table.softDelete()
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
await knex.schema.createTable("user_permissions", (table) => {
|
|
50
|
-
table.bigIncrements("id").primary()
|
|
51
|
-
table.foreignIdFor("users").notNullable()
|
|
52
|
-
table.foreignIdFor("user_roles").notNullable()
|
|
53
|
-
table.json("permissions").defaultTo(knex.raw(`'[]'::json`))
|
|
54
|
-
table.softDelete()
|
|
55
|
-
})
|
|
1
|
+
import type { Knex } from "knex"
|
|
2
|
+
|
|
3
|
+
export async function up(knex: Knex): Promise<void> {
|
|
4
|
+
await knex.schema.createTable("users", (table) => {
|
|
5
|
+
table.bigIncrements("id").primary()
|
|
6
|
+
table.string("name").notNullable()
|
|
7
|
+
table.string("email").unique().notNullable()
|
|
8
|
+
table.string("password")
|
|
9
|
+
table.string("image")
|
|
10
|
+
table.timestamp("email_verification_at")
|
|
11
|
+
table.timestamps(true, true)
|
|
12
|
+
table.softDelete()
|
|
13
|
+
})
|
|
14
|
+
|
|
15
|
+
await knex.schema.createTable("user_roles", (table) => {
|
|
16
|
+
table.bigIncrements("id").primary()
|
|
17
|
+
table.string("name").notNullable()
|
|
18
|
+
})
|
|
19
|
+
|
|
20
|
+
await knex.schema.createTable("user_has_user_roles", (table) => {
|
|
21
|
+
table.bigIncrements("id").primary()
|
|
22
|
+
table.foreignIdFor("users").notNullable()
|
|
23
|
+
table.foreignIdFor("user_roles").notNullable()
|
|
24
|
+
table.softDelete()
|
|
25
|
+
})
|
|
26
|
+
|
|
27
|
+
await knex.schema.createTable("user_access_tokens", (table) => {
|
|
28
|
+
table.bigIncrements("id").primary()
|
|
29
|
+
table.foreignIdFor("users").notNullable()
|
|
30
|
+
table.string("agent").index().notNullable()
|
|
31
|
+
table.string("token").unique().index().notNullable()
|
|
32
|
+
table.json("permissions").defaultTo(knex.raw(`'[]'::json`))
|
|
33
|
+
table.string("last_used_ip").nullable()
|
|
34
|
+
table.timestamp("last_used_at")
|
|
35
|
+
table.timestamp("expired_at")
|
|
36
|
+
table.timestamps(true, true)
|
|
37
|
+
table.softDelete()
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
await knex.schema.createTable("user_mail_tokens", (table) => {
|
|
41
|
+
table.bigIncrements("id").primary()
|
|
42
|
+
table.foreignIdFor("users").notNullable()
|
|
43
|
+
table.string("token").unique().notNullable()
|
|
44
|
+
table.timestamp("used_at")
|
|
45
|
+
table.timestamps(true, true)
|
|
46
|
+
table.softDelete()
|
|
47
|
+
})
|
|
48
|
+
|
|
49
|
+
await knex.schema.createTable("user_permissions", (table) => {
|
|
50
|
+
table.bigIncrements("id").primary()
|
|
51
|
+
table.foreignIdFor("users").notNullable()
|
|
52
|
+
table.foreignIdFor("user_roles").notNullable()
|
|
53
|
+
table.json("permissions").defaultTo(knex.raw(`'[]'::json`))
|
|
54
|
+
table.softDelete()
|
|
55
|
+
})
|
|
56
56
|
}
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
import { Role, User } from "@models";
|
|
2
|
-
import { db } from "@utils";
|
|
3
|
-
|
|
4
|
-
export default async function UserSeeder() {
|
|
5
|
-
// =========================>
|
|
6
|
-
// ## Seed the application's database
|
|
7
|
-
// =========================>
|
|
8
|
-
await (new Role).pump([
|
|
9
|
-
{"name": "Admin"},
|
|
10
|
-
{"name": "Petugas"}
|
|
11
|
-
]);
|
|
12
|
-
|
|
13
|
-
await (new User).pump([
|
|
14
|
-
{"name": "Admin", "email": "admin@skalfa.id", "password": "$2b$10$tPX5QhnM.vUEDmDpht6O4OarVyTh43NTxhkzFrNxfRijJ3uhSHcli"},
|
|
15
|
-
{"name": "Petugas", "email": "petugas@skalfa.id", "password": "$2b$10$tPX5QhnM.vUEDmDpht6O4OarVyTh43NTxhkzFrNxfRijJ3uhSHcli"}
|
|
16
|
-
]);
|
|
17
|
-
|
|
18
|
-
if (db) {
|
|
19
|
-
await db("user_has_user_roles").insert([
|
|
20
|
-
{ "user_id": 1, "user_role_id": 1 },
|
|
21
|
-
{ "user_id": 2, "user_role_id": 2 }
|
|
22
|
-
]);
|
|
23
|
-
}
|
|
1
|
+
import { Role, User } from "@models";
|
|
2
|
+
import { db } from "@utils";
|
|
3
|
+
|
|
4
|
+
export default async function UserSeeder() {
|
|
5
|
+
// =========================>
|
|
6
|
+
// ## Seed the application's database
|
|
7
|
+
// =========================>
|
|
8
|
+
await (new Role).pump([
|
|
9
|
+
{"name": "Admin"},
|
|
10
|
+
{"name": "Petugas"}
|
|
11
|
+
]);
|
|
12
|
+
|
|
13
|
+
await (new User).pump([
|
|
14
|
+
{"name": "Admin", "email": "admin@skalfa.id", "password": "$2b$10$tPX5QhnM.vUEDmDpht6O4OarVyTh43NTxhkzFrNxfRijJ3uhSHcli"},
|
|
15
|
+
{"name": "Petugas", "email": "petugas@skalfa.id", "password": "$2b$10$tPX5QhnM.vUEDmDpht6O4OarVyTh43NTxhkzFrNxfRijJ3uhSHcli"}
|
|
16
|
+
]);
|
|
17
|
+
|
|
18
|
+
if (db) {
|
|
19
|
+
await db("user_has_user_roles").insert([
|
|
20
|
+
{ "user_id": 1, "user_role_id": 1 },
|
|
21
|
+
{ "user_id": 2, "user_role_id": 2 }
|
|
22
|
+
]);
|
|
23
|
+
}
|
|
24
24
|
}
|
package/eslint.config.mjs
CHANGED
|
@@ -1,36 +1,36 @@
|
|
|
1
|
-
import { dirname } from "path";
|
|
2
|
-
import { fileURLToPath } from "url";
|
|
3
|
-
import { FlatCompat } from "@eslint/eslintrc";
|
|
4
|
-
import tsParser from "@typescript-eslint/parser"
|
|
5
|
-
import tsPlugin from "@typescript-eslint/eslint-plugin"
|
|
6
|
-
import prettier from "eslint-config-prettier";
|
|
7
|
-
|
|
8
|
-
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
-
const __dirname = dirname(__filename);
|
|
10
|
-
|
|
11
|
-
const compat = new FlatCompat({
|
|
12
|
-
baseDirectory: __dirname,
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
const eslintConfig = [
|
|
16
|
-
...compat.extends("prettier"),
|
|
17
|
-
{
|
|
18
|
-
files: ['**/*.{js,ts}'],
|
|
19
|
-
languageOptions: {
|
|
20
|
-
parser: tsParser,
|
|
21
|
-
},
|
|
22
|
-
plugins: {
|
|
23
|
-
'@typescript-eslint': tsPlugin,
|
|
24
|
-
},
|
|
25
|
-
rules: {
|
|
26
|
-
"@typescript-eslint/no-explicit-any" : 0,
|
|
27
|
-
"no-console" : 1,
|
|
28
|
-
"no-nested-ternary" : 0,
|
|
29
|
-
"@typescript-eslint/no-unused-expressions" : 0,
|
|
30
|
-
"@typescript-eslint/no-array-constructor" : 0,
|
|
31
|
-
},
|
|
32
|
-
},
|
|
33
|
-
prettier,
|
|
34
|
-
];
|
|
35
|
-
|
|
36
|
-
export default eslintConfig;
|
|
1
|
+
import { dirname } from "path";
|
|
2
|
+
import { fileURLToPath } from "url";
|
|
3
|
+
import { FlatCompat } from "@eslint/eslintrc";
|
|
4
|
+
import tsParser from "@typescript-eslint/parser"
|
|
5
|
+
import tsPlugin from "@typescript-eslint/eslint-plugin"
|
|
6
|
+
import prettier from "eslint-config-prettier";
|
|
7
|
+
|
|
8
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
9
|
+
const __dirname = dirname(__filename);
|
|
10
|
+
|
|
11
|
+
const compat = new FlatCompat({
|
|
12
|
+
baseDirectory: __dirname,
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
const eslintConfig = [
|
|
16
|
+
...compat.extends("prettier"),
|
|
17
|
+
{
|
|
18
|
+
files: ['**/*.{js,ts}'],
|
|
19
|
+
languageOptions: {
|
|
20
|
+
parser: tsParser,
|
|
21
|
+
},
|
|
22
|
+
plugins: {
|
|
23
|
+
'@typescript-eslint': tsPlugin,
|
|
24
|
+
},
|
|
25
|
+
rules: {
|
|
26
|
+
"@typescript-eslint/no-explicit-any" : 0,
|
|
27
|
+
"no-console" : 1,
|
|
28
|
+
"no-nested-ternary" : 0,
|
|
29
|
+
"@typescript-eslint/no-unused-expressions" : 0,
|
|
30
|
+
"@typescript-eslint/no-array-constructor" : 0,
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
prettier,
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
export default eslintConfig;
|
package/package.json
CHANGED
|
@@ -1,39 +1,40 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@skalfa/skalfa-api",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"scripts": {
|
|
5
|
-
"dev"
|
|
6
|
-
"watch"
|
|
7
|
-
"start"
|
|
8
|
-
"test"
|
|
9
|
-
"lint"
|
|
10
|
-
"barrels"
|
|
11
|
-
"skalfa"
|
|
12
|
-
},
|
|
13
|
-
"dependencies": {
|
|
14
|
-
"@skalfa/skalfa-api-core": "^1.0.2",
|
|
15
|
-
"@skalfa/skalfa-orm"
|
|
16
|
-
"bcrypt"
|
|
17
|
-
"dotenv"
|
|
18
|
-
"elysia"
|
|
19
|
-
"knex"
|
|
20
|
-
"pg"
|
|
21
|
-
"nodemailer"
|
|
22
|
-
"tsconfig-paths"
|
|
23
|
-
"validator"
|
|
24
|
-
"commander"
|
|
25
|
-
},
|
|
26
|
-
"devDependencies": {
|
|
27
|
-
"eslint"
|
|
28
|
-
"eslint-config-prettier"
|
|
29
|
-
"@eslint/eslintrc"
|
|
30
|
-
"@typescript-eslint/eslint-plugin"
|
|
31
|
-
"@typescript-eslint/parser"
|
|
32
|
-
"@types/bcrypt"
|
|
33
|
-
"@types/nodemailer"
|
|
34
|
-
"@types/validator"
|
|
35
|
-
"bun-types"
|
|
36
|
-
"barrelsby"
|
|
37
|
-
"concurrently"
|
|
38
|
-
}
|
|
39
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "@skalfa/skalfa-api",
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"scripts": {
|
|
5
|
+
"dev": "concurrently --raw \"bun run --watch app/app.ts\" \"bun skalfa watch:barrels\"",
|
|
6
|
+
"watch": "bun run --watch app/app.ts",
|
|
7
|
+
"start": "bun run app/app.ts",
|
|
8
|
+
"test": "bun tsc --noEmit --ignoreDeprecations 6.0",
|
|
9
|
+
"lint": "bunx eslint app/* utils/* database/*",
|
|
10
|
+
"barrels": "bun run utils/commands/skalfa.ts barrels",
|
|
11
|
+
"skalfa": "bun run utils/commands/skalfa.ts"
|
|
12
|
+
},
|
|
13
|
+
"dependencies": {
|
|
14
|
+
"@skalfa/skalfa-api-core": "^1.0.2",
|
|
15
|
+
"@skalfa/skalfa-orm": "^1.0.0",
|
|
16
|
+
"bcrypt": "^6.0.0",
|
|
17
|
+
"dotenv": "^17.2.2",
|
|
18
|
+
"elysia": "^1.2.0",
|
|
19
|
+
"knex": "^3.1.0",
|
|
20
|
+
"pg": "^8.16.3",
|
|
21
|
+
"nodemailer": "^7.0.9",
|
|
22
|
+
"tsconfig-paths": "^4.2.0",
|
|
23
|
+
"validator": "^13.15.15",
|
|
24
|
+
"commander": "^12.1.0"
|
|
25
|
+
},
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"eslint": "^10.0.0",
|
|
28
|
+
"eslint-config-prettier": "^10.1.8",
|
|
29
|
+
"@eslint/eslintrc": "eslint/eslintrc",
|
|
30
|
+
"@typescript-eslint/eslint-plugin": "^8.55.0",
|
|
31
|
+
"@typescript-eslint/parser": "^8.55.0",
|
|
32
|
+
"@types/bcrypt": "^6.0.0",
|
|
33
|
+
"@types/nodemailer": "^7.0.2",
|
|
34
|
+
"@types/validator": "^13.15.3",
|
|
35
|
+
"bun-types": "latest",
|
|
36
|
+
"barrelsby": "^2.8.1",
|
|
37
|
+
"concurrently": "^9.2.1"
|
|
38
|
+
},
|
|
39
|
+
"description": "Premium backend starter template powered by Elysia and Bun, pre-configured with modular utilities."
|
|
40
|
+
}
|