@takaro/db 0.0.1 → 0.0.4
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/config.d.ts +14 -0
- package/dist/config.js +12 -0
- package/dist/config.js.map +1 -1
- package/dist/knex.d.ts +3 -0
- package/dist/knex.js +1 -0
- package/dist/knex.js.map +1 -1
- package/dist/migrations/sql/20240613175009-lastseen-users-pog.d.ts +3 -0
- package/dist/migrations/sql/20240613175009-lastseen-users-pog.js +17 -0
- package/dist/migrations/sql/20240613175009-lastseen-users-pog.js.map +1 -0
- package/dist/migrations/sql/20240614143517-shop.d.ts +3 -0
- package/dist/migrations/sql/20240614143517-shop.js +29 -0
- package/dist/migrations/sql/20240614143517-shop.js.map +1 -0
- package/dist/migrations/sql/20240615145045-user-player-link.d.ts +3 -0
- package/dist/migrations/sql/20240615145045-user-player-link.js +17 -0
- package/dist/migrations/sql/20240615145045-user-player-link.js.map +1 -0
- package/dist/migrations/sql/20240622132552-fix-ip-history-fk.d.ts +3 -0
- package/dist/migrations/sql/20240622132552-fix-ip-history-fk.js +11 -0
- package/dist/migrations/sql/20240622132552-fix-ip-history-fk.js.map +1 -0
- package/dist/migrations/sql/20240626200803-player-inventory-idx.d.ts +3 -0
- package/dist/migrations/sql/20240626200803-player-inventory-idx.js +11 -0
- package/dist/migrations/sql/20240626200803-player-inventory-idx.js.map +1 -0
- package/dist/migrations/sql/20240628174914-shop-orders.d.ts +3 -0
- package/dist/migrations/sql/20240628174914-shop-orders.js +16 -0
- package/dist/migrations/sql/20240628174914-shop-orders.js.map +1 -0
- package/dist/migrations/sql/20240705140358-teleports-public-refactor.d.ts +3 -0
- package/dist/migrations/sql/20240705140358-teleports-public-refactor.js +26 -0
- package/dist/migrations/sql/20240705140358-teleports-public-refactor.js.map +1 -0
- package/dist/migrations/sql/20240710181429-events-name-idx.d.ts +3 -0
- package/dist/migrations/sql/20240710181429-events-name-idx.js +11 -0
- package/dist/migrations/sql/20240710181429-events-name-idx.js.map +1 -0
- package/dist/migrations/sql/20240711181423-shop-orders-multi-listing.d.ts +3 -0
- package/dist/migrations/sql/20240711181423-shop-orders-multi-listing.js +26 -0
- package/dist/migrations/sql/20240711181423-shop-orders-multi-listing.js.map +1 -0
- package/dist/migrations/sql/20240718150807-listing-deleted-and-draft-status.d.ts +3 -0
- package/dist/migrations/sql/20240718150807-listing-deleted-and-draft-status.js +13 -0
- package/dist/migrations/sql/20240718150807-listing-deleted-and-draft-status.js.map +1 -0
- package/dist/migrations/sql/20240720135010-acting-user-and-module.d.ts +3 -0
- package/dist/migrations/sql/20240720135010-acting-user-and-module.js +19 -0
- package/dist/migrations/sql/20240720135010-acting-user-and-module.js.map +1 -0
- package/dist/migrations/sql/20240811061243-domain-rate-limit-setting.d.ts +3 -0
- package/dist/migrations/sql/20240811061243-domain-rate-limit-setting.js +14 -0
- package/dist/migrations/sql/20240811061243-domain-rate-limit-setting.js.map +1 -0
- package/dist/queryBuilder.d.ts +8 -2
- package/dist/queryBuilder.js +38 -19
- package/dist/queryBuilder.js.map +1 -1
- package/package.json +2 -3
- package/src/__tests__/queryBuilder.integration.test.ts +7 -4
- package/src/config.ts +14 -0
- package/src/knex.ts +1 -0
- package/src/migrations/sql/20221019173729_settings.ts +2 -2
- package/src/migrations/sql/20221102190532_commands.ts +2 -2
- package/src/migrations/sql/20230308183400-persistent-variables.ts +2 -2
- package/src/migrations/sql/20230604130951-fix-hook-eventtypes.ts +1 -1
- package/src/migrations/sql/20230622192402-discord-hooks.ts +2 -2
- package/src/migrations/sql/20230712061220-roles-permissions-extension.ts +1 -1
- package/src/migrations/sql/20230921123717-count-for-permissions.ts +1 -1
- package/src/migrations/sql/20240105130846-remove-some-module-perms.ts +4 -4
- package/src/migrations/sql/20240119152426-remove-hook-check.ts +1 -1
- package/src/migrations/sql/20240121142329-move-ip-history.ts +1 -1
- package/src/migrations/sql/20240613175009-lastseen-users-pog.ts +21 -0
- package/src/migrations/sql/20240614143517-shop.ts +39 -0
- package/src/migrations/sql/20240615145045-user-player-link.ts +20 -0
- package/src/migrations/sql/20240622132552-fix-ip-history-fk.ts +13 -0
- package/src/migrations/sql/20240626200803-player-inventory-idx.ts +13 -0
- package/src/migrations/sql/20240628174914-shop-orders.ts +20 -0
- package/src/migrations/sql/20240705140358-teleports-public-refactor.ts +31 -0
- package/src/migrations/sql/20240710181429-events-name-idx.ts +13 -0
- package/src/migrations/sql/20240711181423-shop-orders-multi-listing.ts +34 -0
- package/src/migrations/sql/20240718150807-listing-deleted-and-draft-status.ts +15 -0
- package/src/migrations/sql/20240720135010-acting-user-and-module.ts +24 -0
- package/src/migrations/sql/20240811061243-domain-rate-limit-setting.ts +16 -0
- package/src/migrations/util/alterEnum.ts +1 -1
- package/src/queryBuilder.ts +60 -20
|
@@ -183,18 +183,21 @@ describe('QueryBuilder', () => {
|
|
|
183
183
|
const start = new Date();
|
|
184
184
|
await TestUserModel.query().insert({ name: 'test1' });
|
|
185
185
|
await TestUserModel.query().insert({ name: 'test2' });
|
|
186
|
-
|
|
187
186
|
const end = new Date();
|
|
188
187
|
|
|
189
188
|
// Quick hack to make the test pass
|
|
190
189
|
// Relying on times like this with an external DB is troublesome...
|
|
191
190
|
await sleep(250);
|
|
192
191
|
|
|
193
|
-
await TestUserModel.query().insert({ name: 'test3'
|
|
192
|
+
await TestUserModel.query().insert({ name: 'test3' });
|
|
194
193
|
|
|
195
194
|
const res = await new QueryBuilder<TestUserModel, TestUserModel>({
|
|
196
|
-
|
|
197
|
-
|
|
195
|
+
greaterThan: {
|
|
196
|
+
createdAt: start.toISOString(),
|
|
197
|
+
},
|
|
198
|
+
lessThan: {
|
|
199
|
+
createdAt: end.toISOString(),
|
|
200
|
+
},
|
|
198
201
|
}).build(TestUserModel.query());
|
|
199
202
|
|
|
200
203
|
expect(res.results).to.have.lengthOf(2);
|
package/src/config.ts
CHANGED
|
@@ -7,6 +7,8 @@ export interface IDbConfig extends IBaseConfig {
|
|
|
7
7
|
user: string;
|
|
8
8
|
password: string;
|
|
9
9
|
database: string;
|
|
10
|
+
ssl: boolean;
|
|
11
|
+
ca: string;
|
|
10
12
|
};
|
|
11
13
|
redis: {
|
|
12
14
|
host: string;
|
|
@@ -51,6 +53,18 @@ export const configSchema = {
|
|
|
51
53
|
default: 'postgres',
|
|
52
54
|
env: 'POSTGRES_DB',
|
|
53
55
|
},
|
|
56
|
+
ssl: {
|
|
57
|
+
doc: 'Whether to use SSL for the connection',
|
|
58
|
+
format: Boolean,
|
|
59
|
+
default: false,
|
|
60
|
+
env: 'POSTGRES_SSL',
|
|
61
|
+
},
|
|
62
|
+
ca: {
|
|
63
|
+
doc: 'The CA certificate to use for SSL connections',
|
|
64
|
+
format: String,
|
|
65
|
+
default: '',
|
|
66
|
+
env: 'POSTGRES_CA',
|
|
67
|
+
},
|
|
54
68
|
},
|
|
55
69
|
redis: {
|
|
56
70
|
host: {
|
package/src/knex.ts
CHANGED
|
@@ -18,6 +18,7 @@ export function getKnexOptions(extra: Record<string, unknown> = {}) {
|
|
|
18
18
|
user: config.get('postgres.user'),
|
|
19
19
|
password: config.get('postgres.password'),
|
|
20
20
|
database: config.get('postgres.database'),
|
|
21
|
+
ssl: config.get('postgres.ssl') ? { ca: config.get('postgres.ca') } : false,
|
|
21
22
|
},
|
|
22
23
|
...extra,
|
|
23
24
|
};
|
|
@@ -38,7 +38,7 @@ export async function up(knex: Knex): Promise<void> {
|
|
|
38
38
|
'MANAGE_PLAYERS',
|
|
39
39
|
'MANAGE_SETTINGS',
|
|
40
40
|
'READ_SETTINGS',
|
|
41
|
-
])
|
|
41
|
+
]),
|
|
42
42
|
);
|
|
43
43
|
}
|
|
44
44
|
|
|
@@ -65,6 +65,6 @@ export async function down(knex: Knex): Promise<void> {
|
|
|
65
65
|
'MANAGE_MODULES',
|
|
66
66
|
'READ_PLAYERS',
|
|
67
67
|
'MANAGE_PLAYERS',
|
|
68
|
-
])
|
|
68
|
+
]),
|
|
69
69
|
);
|
|
70
70
|
}
|
|
@@ -25,7 +25,7 @@ export async function up(knex: Knex): Promise<void> {
|
|
|
25
25
|
'READ_SETTINGS',
|
|
26
26
|
'READ_COMMANDS',
|
|
27
27
|
'MANAGE_COMMANDS',
|
|
28
|
-
])
|
|
28
|
+
]),
|
|
29
29
|
);
|
|
30
30
|
|
|
31
31
|
await knex.schema.alterTable('commands', (table) => {
|
|
@@ -61,6 +61,6 @@ export async function down(knex: Knex): Promise<void> {
|
|
|
61
61
|
'MANAGE_PLAYERS',
|
|
62
62
|
'MANAGE_SETTINGS',
|
|
63
63
|
'READ_SETTINGS',
|
|
64
|
-
])
|
|
64
|
+
]),
|
|
65
65
|
);
|
|
66
66
|
}
|
|
@@ -27,7 +27,7 @@ export async function up(knex: Knex): Promise<void> {
|
|
|
27
27
|
'MANAGE_COMMANDS',
|
|
28
28
|
'READ_VARIABLES',
|
|
29
29
|
'MANAGE_VARIABLES',
|
|
30
|
-
])
|
|
30
|
+
]),
|
|
31
31
|
);
|
|
32
32
|
|
|
33
33
|
await knex.schema.createTable('variables', (table) => {
|
|
@@ -69,6 +69,6 @@ export async function down(knex: Knex): Promise<void> {
|
|
|
69
69
|
'READ_SETTINGS',
|
|
70
70
|
'READ_COMMANDS',
|
|
71
71
|
'MANAGE_COMMANDS',
|
|
72
|
-
])
|
|
72
|
+
]),
|
|
73
73
|
);
|
|
74
74
|
}
|
|
@@ -3,7 +3,7 @@ import { formatAlterTableEnumSql } from '../util/alterEnum.js';
|
|
|
3
3
|
|
|
4
4
|
export async function up(knex: Knex): Promise<void> {
|
|
5
5
|
await knex.raw(
|
|
6
|
-
formatAlterTableEnumSql('hooks', 'eventType', ['log', 'player-connected', 'player-disconnected', 'chat-message'])
|
|
6
|
+
formatAlterTableEnumSql('hooks', 'eventType', ['log', 'player-connected', 'player-disconnected', 'chat-message']),
|
|
7
7
|
);
|
|
8
8
|
}
|
|
9
9
|
|
|
@@ -9,12 +9,12 @@ export async function up(knex: Knex): Promise<void> {
|
|
|
9
9
|
'player-disconnected',
|
|
10
10
|
'chat-message',
|
|
11
11
|
'discord-message',
|
|
12
|
-
])
|
|
12
|
+
]),
|
|
13
13
|
);
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export async function down(knex: Knex): Promise<void> {
|
|
17
17
|
await knex.raw(
|
|
18
|
-
formatAlterTableEnumSql('hooks', 'eventType', ['log', 'player-connected', 'player-disconnected', 'chat-message'])
|
|
18
|
+
formatAlterTableEnumSql('hooks', 'eventType', ['log', 'player-connected', 'player-disconnected', 'chat-message']),
|
|
19
19
|
);
|
|
20
20
|
}
|
|
@@ -20,14 +20,14 @@ export async function up(knex: Knex): Promise<void> {
|
|
|
20
20
|
const readPermissionOnRole = await knex('permissionOnRole')
|
|
21
21
|
.whereIn(
|
|
22
22
|
'permissionId',
|
|
23
|
-
readPerms.map((p) => p.id)
|
|
23
|
+
readPerms.map((p) => p.id),
|
|
24
24
|
)
|
|
25
25
|
.select('id');
|
|
26
26
|
|
|
27
27
|
const managePermissionOnRole = await knex('permissionOnRole')
|
|
28
28
|
.whereIn(
|
|
29
29
|
'permissionId',
|
|
30
|
-
managePerms.map((p) => p.id)
|
|
30
|
+
managePerms.map((p) => p.id),
|
|
31
31
|
)
|
|
32
32
|
.select('id');
|
|
33
33
|
|
|
@@ -35,7 +35,7 @@ export async function up(knex: Knex): Promise<void> {
|
|
|
35
35
|
await knex('permissionOnRole')
|
|
36
36
|
.whereIn(
|
|
37
37
|
'id',
|
|
38
|
-
readPermissionOnRole.map((p) => p.id)
|
|
38
|
+
readPermissionOnRole.map((p) => p.id),
|
|
39
39
|
)
|
|
40
40
|
.update({
|
|
41
41
|
permissionId: readModulePerm.id,
|
|
@@ -44,7 +44,7 @@ export async function up(knex: Knex): Promise<void> {
|
|
|
44
44
|
await knex('permissionOnRole')
|
|
45
45
|
.whereIn(
|
|
46
46
|
'id',
|
|
47
|
-
managePermissionOnRole.map((p) => p.id)
|
|
47
|
+
managePermissionOnRole.map((p) => p.id),
|
|
48
48
|
)
|
|
49
49
|
.update({
|
|
50
50
|
permissionId: manageModulePerm.id,
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Knex } from 'knex';
|
|
2
|
+
|
|
3
|
+
export async function up(knex: Knex): Promise<void> {
|
|
4
|
+
await knex.schema.alterTable('users', (table) => {
|
|
5
|
+
table.timestamp('lastSeen').defaultTo(knex.fn.now()).notNullable();
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
await knex.schema.alterTable('playerOnGameServer', (table) => {
|
|
9
|
+
table.timestamp('lastSeen').defaultTo(knex.fn.now()).notNullable();
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export async function down(knex: Knex): Promise<void> {
|
|
14
|
+
await knex.schema.alterTable('users', (table) => {
|
|
15
|
+
table.dropColumn('lastSeen');
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
await knex.schema.alterTable('playerOnGameServer', (table) => {
|
|
19
|
+
table.dropColumn('lastSeen');
|
|
20
|
+
});
|
|
21
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Knex } from 'knex';
|
|
2
|
+
|
|
3
|
+
export async function up(knex: Knex): Promise<void> {
|
|
4
|
+
await knex.schema.createTable('shopListing', (table) => {
|
|
5
|
+
table.timestamps(true, true, true);
|
|
6
|
+
table.uuid('id').primary().defaultTo(knex.raw('gen_random_uuid ()'));
|
|
7
|
+
table.string('domain').references('domains.id').onDelete('CASCADE').notNullable();
|
|
8
|
+
table.index('domain');
|
|
9
|
+
|
|
10
|
+
table.uuid('gameServerId').references('gameservers.id').onDelete('CASCADE').notNullable();
|
|
11
|
+
|
|
12
|
+
table.uuid('itemId').references('items.id').onDelete('CASCADE');
|
|
13
|
+
table.uuid('functionId').references('functions.id').onDelete('CASCADE');
|
|
14
|
+
|
|
15
|
+
// Either an item or a function must be set
|
|
16
|
+
table.check('("itemId" IS NOT NULL) OR ("functionId" IS NOT NULL)');
|
|
17
|
+
|
|
18
|
+
table.integer('price').notNullable();
|
|
19
|
+
|
|
20
|
+
// Price must be positive and non-zero
|
|
21
|
+
table.check('"price" > 0');
|
|
22
|
+
|
|
23
|
+
table.string('name').nullable();
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
// Listings can only be bought by users with the role
|
|
27
|
+
await knex.schema.createTable('shopListingRole', (table) => {
|
|
28
|
+
table.timestamps(true, true, true);
|
|
29
|
+
table.uuid('id').primary().defaultTo(knex.raw('gen_random_uuid ()'));
|
|
30
|
+
|
|
31
|
+
table.uuid('listingId').references('shopListing.id').onDelete('CASCADE').notNullable();
|
|
32
|
+
table.uuid('roleId').references('roles.id').onDelete('CASCADE').notNullable();
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export async function down(knex: Knex): Promise<void> {
|
|
37
|
+
await knex.schema.dropTable('shopListingRole');
|
|
38
|
+
await knex.schema.dropTable('shopListing');
|
|
39
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Knex } from 'knex';
|
|
2
|
+
|
|
3
|
+
export async function up(knex: Knex): Promise<void> {
|
|
4
|
+
// Remove users_idp_id_unique constraint
|
|
5
|
+
//idpId must be unique per domain instead
|
|
6
|
+
await knex.schema.alterTable('users', (table) => {
|
|
7
|
+
table.dropUnique(['idpid']);
|
|
8
|
+
table.unique(['idpId', 'domain']);
|
|
9
|
+
|
|
10
|
+
table.uuid('playerId').references('players.id').onDelete('SET NULL').nullable();
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export async function down(knex: Knex): Promise<void> {
|
|
15
|
+
await knex.schema.alterTable('users', (table) => {
|
|
16
|
+
table.dropUnique(['idpid', 'domain']);
|
|
17
|
+
table.unique(['idpId']);
|
|
18
|
+
table.dropColumn('playerId');
|
|
19
|
+
});
|
|
20
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Knex } from 'knex';
|
|
2
|
+
|
|
3
|
+
export async function up(knex: Knex): Promise<void> {
|
|
4
|
+
await knex.schema.alterTable('playerIpHistory', (table) => {
|
|
5
|
+
table.uuid('gameServerId').nullable().alter();
|
|
6
|
+
});
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export async function down(knex: Knex): Promise<void> {
|
|
10
|
+
await knex.schema.alterTable('playerIpHistory', (table) => {
|
|
11
|
+
table.uuid('gameServerId').notNullable().alter();
|
|
12
|
+
});
|
|
13
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Knex } from 'knex';
|
|
2
|
+
|
|
3
|
+
export async function up(knex: Knex): Promise<void> {
|
|
4
|
+
await knex.schema.alterTable('playerInventory', (table) => {
|
|
5
|
+
table.index(['playerId', 'domain']);
|
|
6
|
+
});
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export async function down(knex: Knex): Promise<void> {
|
|
10
|
+
await knex.schema.alterTable('playerInventory', (table) => {
|
|
11
|
+
table.dropIndex(['playerId', 'domain']);
|
|
12
|
+
});
|
|
13
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Knex } from 'knex';
|
|
2
|
+
|
|
3
|
+
export async function up(knex: Knex): Promise<void> {
|
|
4
|
+
await knex.schema.createTable('shopOrder', (table) => {
|
|
5
|
+
table.timestamps(true, true, true);
|
|
6
|
+
table.uuid('id').primary().defaultTo(knex.raw('gen_random_uuid ()'));
|
|
7
|
+
table.string('domain').references('domains.id').onDelete('CASCADE').notNullable();
|
|
8
|
+
table.index('domain');
|
|
9
|
+
|
|
10
|
+
table.uuid('listingId').references('shopListing.id').onDelete('CASCADE').notNullable();
|
|
11
|
+
table.uuid('userId').references('users.id').onDelete('CASCADE').notNullable();
|
|
12
|
+
|
|
13
|
+
table.integer('amount').defaultTo(1).notNullable();
|
|
14
|
+
table.enum('status', ['COMPLETED', 'PAID', 'CANCELED']).notNullable();
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export async function down(knex: Knex): Promise<void> {
|
|
19
|
+
await knex.schema.dropTable('shopOrder');
|
|
20
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Knex } from 'knex';
|
|
2
|
+
|
|
3
|
+
export async function up(knex: Knex): Promise<void> {
|
|
4
|
+
// Find all variables where key starts with 'tp_'
|
|
5
|
+
const variables = await knex('variables').select().where('key', 'like', 'tp_%');
|
|
6
|
+
|
|
7
|
+
// Reduce the list to only public teleports
|
|
8
|
+
const publicTeleports = variables.filter((variable) => {
|
|
9
|
+
try {
|
|
10
|
+
const value = JSON.parse(variable.value);
|
|
11
|
+
return value.public;
|
|
12
|
+
} catch (error) {
|
|
13
|
+
// eslint-disable-next-line no-console
|
|
14
|
+
console.warn(`Error parsing JSON for variable ${variable.key}: ${error}. Skipping.`);
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
// Change the key for all public teleports from tp_xxx to pubtp_xxx
|
|
20
|
+
await Promise.all(
|
|
21
|
+
publicTeleports.map((teleport) => {
|
|
22
|
+
return knex('variables')
|
|
23
|
+
.update({ key: `pub${teleport.key}` })
|
|
24
|
+
.where('id', teleport.id);
|
|
25
|
+
}),
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export async function down(_knex: Knex): Promise<void> {
|
|
30
|
+
// ... no down here, this is a one-way migration
|
|
31
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Knex } from 'knex';
|
|
2
|
+
|
|
3
|
+
export async function up(knex: Knex): Promise<void> {
|
|
4
|
+
await knex.schema.alterTable('events', (table) => {
|
|
5
|
+
table.index(['domain', 'eventName']);
|
|
6
|
+
});
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export async function down(knex: Knex): Promise<void> {
|
|
10
|
+
await knex.schema.alterTable('events', (table) => {
|
|
11
|
+
table.dropIndex(['domain', 'eventName']);
|
|
12
|
+
});
|
|
13
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Knex } from 'knex';
|
|
2
|
+
|
|
3
|
+
export async function up(knex: Knex): Promise<void> {
|
|
4
|
+
await knex.schema.createTable('itemOnShopListing', (table) => {
|
|
5
|
+
table.timestamps(true, true, true);
|
|
6
|
+
table.uuid('id').primary().defaultTo(knex.raw('gen_random_uuid ()'));
|
|
7
|
+
|
|
8
|
+
table.uuid('listingId').references('shopListing.id').onDelete('CASCADE').notNullable();
|
|
9
|
+
table.uuid('itemId').references('items.id').onDelete('CASCADE');
|
|
10
|
+
|
|
11
|
+
table.integer('amount').defaultTo(1).notNullable();
|
|
12
|
+
// Amount must be positive and non-zero
|
|
13
|
+
table.check('"amount" > 0');
|
|
14
|
+
|
|
15
|
+
table.string('quality').nullable();
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
await knex.schema.alterTable('shopListing', (table) => {
|
|
19
|
+
table.dropChecks('"shopListing_check"');
|
|
20
|
+
table.dropColumn('functionId');
|
|
21
|
+
table.dropColumn('itemId');
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export async function down(knex: Knex): Promise<void> {
|
|
26
|
+
await knex.schema.alterTable('shopListing', (table) => {
|
|
27
|
+
table.uuid('itemId').references('items.id').onDelete('CASCADE');
|
|
28
|
+
table.uuid('functionId').references('functions.id').onDelete('CASCADE');
|
|
29
|
+
|
|
30
|
+
table.check('("itemId" IS NOT NULL) OR ("functionId" IS NOT NULL)');
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
await knex.schema.dropTable('itemOnShopListing');
|
|
34
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { Knex } from 'knex';
|
|
2
|
+
|
|
3
|
+
export async function up(knex: Knex): Promise<void> {
|
|
4
|
+
await knex.schema.alterTable('shopListing', (table) => {
|
|
5
|
+
table.timestamp('deletedAt').nullable();
|
|
6
|
+
table.boolean('draft').defaultTo(false);
|
|
7
|
+
});
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export async function down(knex: Knex): Promise<void> {
|
|
11
|
+
await knex.schema.alterTable('shopListing', (table) => {
|
|
12
|
+
table.dropColumn('deletedAt');
|
|
13
|
+
table.dropColumn('draft');
|
|
14
|
+
});
|
|
15
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { Knex } from 'knex';
|
|
2
|
+
|
|
3
|
+
export async function up(knex: Knex): Promise<void> {
|
|
4
|
+
await knex.schema.alterTable('events', (table) => {
|
|
5
|
+
table.uuid('actingUserId').nullable();
|
|
6
|
+
table.foreign('actingUserId').references('id').inTable('users');
|
|
7
|
+
|
|
8
|
+
table.uuid('actingModuleId').nullable();
|
|
9
|
+
table.foreign('actingModuleId').references('id').inTable('modules');
|
|
10
|
+
|
|
11
|
+
table.index('actingUserId');
|
|
12
|
+
table.index('actingModuleId');
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export async function down(knex: Knex): Promise<void> {
|
|
17
|
+
await knex.schema.alterTable('events', (table) => {
|
|
18
|
+
table.dropForeign(['actingUserId']);
|
|
19
|
+
table.dropColumn('actingUserId');
|
|
20
|
+
|
|
21
|
+
table.dropForeign(['actingModuleId']);
|
|
22
|
+
table.dropColumn('actingModuleId');
|
|
23
|
+
});
|
|
24
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import ms from 'ms';
|
|
2
|
+
import { Knex } from 'knex';
|
|
3
|
+
|
|
4
|
+
export async function up(knex: Knex): Promise<void> {
|
|
5
|
+
await knex.schema.alterTable('domains', (table) => {
|
|
6
|
+
table.integer('rateLimitPoints').notNullable().defaultTo(2500);
|
|
7
|
+
table.integer('rateLimitDuration').notNullable().defaultTo(ms('15min'));
|
|
8
|
+
});
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export async function down(knex: Knex): Promise<void> {
|
|
12
|
+
await knex.schema.alterTable('domains', (table) => {
|
|
13
|
+
table.dropColumn('rateLimitPoints');
|
|
14
|
+
table.dropColumn('rateLimitDuration');
|
|
15
|
+
});
|
|
16
|
+
}
|
|
@@ -4,7 +4,7 @@ export function formatAlterTableEnumSql(tableName: string, columnName: string, e
|
|
|
4
4
|
return [
|
|
5
5
|
`ALTER TABLE "${tableName}" DROP CONSTRAINT IF EXISTS "${constraintName}";`,
|
|
6
6
|
`ALTER TABLE "${tableName}" ADD CONSTRAINT "${constraintName}" CHECK ("${columnName}" = ANY (ARRAY['${enums.join(
|
|
7
|
-
"'::text, '"
|
|
7
|
+
"'::text, '",
|
|
8
8
|
)}'::text]));`,
|
|
9
9
|
].join('\n');
|
|
10
10
|
}
|
package/src/queryBuilder.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { IsEnum, IsNumber, IsOptional, IsString } from 'class-validator';
|
|
2
|
+
import {
|
|
3
|
+
QueryBuilder as ObjectionQueryBuilder,
|
|
4
|
+
Model as ObjectionModel,
|
|
5
|
+
Page,
|
|
6
|
+
AnyQueryBuilder,
|
|
7
|
+
Expression,
|
|
8
|
+
PrimitiveValue,
|
|
9
|
+
} from 'objection';
|
|
3
10
|
|
|
4
11
|
export class ITakaroQuery<T> {
|
|
5
12
|
@IsOptional()
|
|
@@ -12,6 +19,16 @@ export class ITakaroQuery<T> {
|
|
|
12
19
|
[key in keyof T]?: unknown[] | unknown;
|
|
13
20
|
};
|
|
14
21
|
|
|
22
|
+
@IsOptional()
|
|
23
|
+
greaterThan?: {
|
|
24
|
+
[key in keyof T]?: unknown;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
@IsOptional()
|
|
28
|
+
lessThan?: {
|
|
29
|
+
[key in keyof T]?: unknown;
|
|
30
|
+
};
|
|
31
|
+
|
|
15
32
|
@IsOptional()
|
|
16
33
|
@IsNumber()
|
|
17
34
|
page?: number;
|
|
@@ -29,14 +46,6 @@ export class ITakaroQuery<T> {
|
|
|
29
46
|
@IsEnum(['asc', 'desc'])
|
|
30
47
|
sortDirection?: SortDirection;
|
|
31
48
|
|
|
32
|
-
@IsOptional()
|
|
33
|
-
@IsDateString()
|
|
34
|
-
startDate?: string;
|
|
35
|
-
|
|
36
|
-
@IsOptional()
|
|
37
|
-
@IsDateString()
|
|
38
|
-
endDate?: string;
|
|
39
|
-
|
|
40
49
|
@IsOptional()
|
|
41
50
|
@IsString({ each: true })
|
|
42
51
|
extend?: string[];
|
|
@@ -58,14 +67,9 @@ export class QueryBuilder<Model extends ObjectionModel, OutputDTO> {
|
|
|
58
67
|
|
|
59
68
|
let qry = query.page(pagination.page, pagination.limit).orderBy(sorting.sortBy, sorting.sortDirection);
|
|
60
69
|
|
|
61
|
-
if (this.query.startDate) {
|
|
62
|
-
qry = qry.where(`${tableName}.createdAt`, '>=', this.query.startDate);
|
|
63
|
-
}
|
|
64
|
-
if (this.query.endDate) {
|
|
65
|
-
qry = qry.where(`${tableName}.createdAt`, '<=', this.query.endDate);
|
|
66
|
-
}
|
|
67
|
-
|
|
68
70
|
qry = this.filters(tableName, qry);
|
|
71
|
+
qry = this.greaterThan(tableName, qry);
|
|
72
|
+
qry = this.lessThan(tableName, qry);
|
|
69
73
|
|
|
70
74
|
if (this.query.search) {
|
|
71
75
|
qry.where((builder) => {
|
|
@@ -93,15 +97,19 @@ export class QueryBuilder<Model extends ObjectionModel, OutputDTO> {
|
|
|
93
97
|
|
|
94
98
|
private filters(
|
|
95
99
|
tableName: string,
|
|
96
|
-
query: ObjectionQueryBuilder<Model, Page<Model
|
|
100
|
+
query: ObjectionQueryBuilder<Model, Page<Model>>,
|
|
97
101
|
): ObjectionQueryBuilder<Model, Page<Model>> {
|
|
98
102
|
for (const filter in this.query.filters) {
|
|
99
103
|
if (Object.prototype.hasOwnProperty.call(this.query.filters, filter)) {
|
|
100
104
|
const searchVal = this.query.filters[filter];
|
|
101
105
|
|
|
102
106
|
if (searchVal && Array.isArray(searchVal)) {
|
|
103
|
-
|
|
104
|
-
|
|
107
|
+
if (searchVal.includes(null) || searchVal.includes('null')) {
|
|
108
|
+
query.whereNull(`${tableName}.${filter}`);
|
|
109
|
+
continue;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (searchVal.length) {
|
|
105
113
|
query.whereIn(`${tableName}.${filter}`, searchVal.filter(Boolean) as unknown as AnyQueryBuilder);
|
|
106
114
|
}
|
|
107
115
|
}
|
|
@@ -111,6 +119,38 @@ export class QueryBuilder<Model extends ObjectionModel, OutputDTO> {
|
|
|
111
119
|
return query;
|
|
112
120
|
}
|
|
113
121
|
|
|
122
|
+
private greaterThan(
|
|
123
|
+
tableName: string,
|
|
124
|
+
query: ObjectionQueryBuilder<Model, Page<Model>>,
|
|
125
|
+
): ObjectionQueryBuilder<Model, Page<Model>> {
|
|
126
|
+
for (const filter in this.query.greaterThan) {
|
|
127
|
+
if (Object.prototype.hasOwnProperty.call(this.query.greaterThan, filter)) {
|
|
128
|
+
const searchVal = this.query.greaterThan[filter];
|
|
129
|
+
if (searchVal) {
|
|
130
|
+
query.where(`${tableName}.${filter}`, '>=', searchVal as unknown as Expression<PrimitiveValue>);
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
return query;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
private lessThan(
|
|
139
|
+
tableName: string,
|
|
140
|
+
query: ObjectionQueryBuilder<Model, Page<Model>>,
|
|
141
|
+
): ObjectionQueryBuilder<Model, Page<Model>> {
|
|
142
|
+
for (const filter in this.query.lessThan) {
|
|
143
|
+
if (Object.prototype.hasOwnProperty.call(this.query.lessThan, filter)) {
|
|
144
|
+
const searchVal = this.query.lessThan[filter];
|
|
145
|
+
if (searchVal) {
|
|
146
|
+
query.where(`${tableName}.${filter}`, '<=', searchVal as unknown as Expression<PrimitiveValue>);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return query;
|
|
152
|
+
}
|
|
153
|
+
|
|
114
154
|
private sorting(): { sortBy: string; sortDirection: SortDirection } {
|
|
115
155
|
if (!this.query.sortBy) {
|
|
116
156
|
return {
|