@takaro/db 0.3.3 → 0.4.3

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 (36) hide show
  1. package/dist/migrations/sql/20250726000000-discord-role-sync.d.ts +4 -0
  2. package/dist/migrations/sql/20250726000000-discord-role-sync.d.ts.map +1 -0
  3. package/dist/migrations/sql/20250726000000-discord-role-sync.js +13 -0
  4. package/dist/migrations/sql/20250726000000-discord-role-sync.js.map +1 -0
  5. package/dist/migrations/sql/20250727092719-add-quality-to-inventory.d.ts +4 -0
  6. package/dist/migrations/sql/20250727092719-add-quality-to-inventory.d.ts.map +1 -0
  7. package/dist/migrations/sql/20250727092719-add-quality-to-inventory.js +11 -0
  8. package/dist/migrations/sql/20250727092719-add-quality-to-inventory.js.map +1 -0
  9. package/dist/migrations/sql/20250802124307-add-playeriphistory-composite-index.d.ts +4 -0
  10. package/dist/migrations/sql/20250802124307-add-playeriphistory-composite-index.d.ts.map +1 -0
  11. package/dist/migrations/sql/20250802124307-add-playeriphistory-composite-index.js +11 -0
  12. package/dist/migrations/sql/20250802124307-add-playeriphistory-composite-index.js.map +1 -0
  13. package/dist/migrations/sql/20250809122020-add-player-name-history.d.ts +4 -0
  14. package/dist/migrations/sql/20250809122020-add-player-name-history.d.ts.map +1 -0
  15. package/dist/migrations/sql/20250809122020-add-player-name-history.js +26 -0
  16. package/dist/migrations/sql/20250809122020-add-player-name-history.js.map +1 -0
  17. package/dist/migrations/sql/20250812163648-add-kpi-performance-indexes.d.ts +4 -0
  18. package/dist/migrations/sql/20250812163648-add-kpi-performance-indexes.d.ts.map +1 -0
  19. package/dist/migrations/sql/20250812163648-add-kpi-performance-indexes.js +17 -0
  20. package/dist/migrations/sql/20250812163648-add-kpi-performance-indexes.js.map +1 -0
  21. package/dist/migrations/sql/20250814163747-shop-order-cascade-delete.d.ts +4 -0
  22. package/dist/migrations/sql/20250814163747-shop-order-cascade-delete.d.ts.map +1 -0
  23. package/dist/migrations/sql/20250814163747-shop-order-cascade-delete.js +23 -0
  24. package/dist/migrations/sql/20250814163747-shop-order-cascade-delete.js.map +1 -0
  25. package/dist/migrations/sql/20250815120000-optimize-shop-analytics-indexes.d.ts +4 -0
  26. package/dist/migrations/sql/20250815120000-optimize-shop-analytics-indexes.d.ts.map +1 -0
  27. package/dist/migrations/sql/20250815120000-optimize-shop-analytics-indexes.js +40 -0
  28. package/dist/migrations/sql/20250815120000-optimize-shop-analytics-indexes.js.map +1 -0
  29. package/package.json +1 -1
  30. package/src/migrations/sql/20250726000000-discord-role-sync.ts +15 -0
  31. package/src/migrations/sql/20250727092719-add-quality-to-inventory.ts +13 -0
  32. package/src/migrations/sql/20250802124307-add-playeriphistory-composite-index.ts +13 -0
  33. package/src/migrations/sql/20250809122020-add-player-name-history.ts +31 -0
  34. package/src/migrations/sql/20250812163648-add-kpi-performance-indexes.ts +20 -0
  35. package/src/migrations/sql/20250814163747-shop-order-cascade-delete.ts +27 -0
  36. package/src/migrations/sql/20250815120000-optimize-shop-analytics-indexes.ts +46 -0
@@ -0,0 +1,4 @@
1
+ import { Knex } from 'knex';
2
+ export declare function up(knex: Knex): Promise<void>;
3
+ export declare function down(knex: Knex): Promise<void>;
4
+ //# sourceMappingURL=20250726000000-discord-role-sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"20250726000000-discord-role-sync.d.ts","sourceRoot":"","sources":["../../../src/migrations/sql/20250726000000-discord-role-sync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,wBAAsB,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAMlD;AAED,wBAAsB,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAIpD"}
@@ -0,0 +1,13 @@
1
+ export async function up(knex) {
2
+ // Add linkedDiscordRoleId to roles table
3
+ await knex.schema.alterTable('roles', (table) => {
4
+ table.string('linkedDiscordRoleId').nullable();
5
+ table.index('linkedDiscordRoleId');
6
+ });
7
+ }
8
+ export async function down(knex) {
9
+ await knex.schema.alterTable('roles', (table) => {
10
+ table.dropColumn('linkedDiscordRoleId');
11
+ });
12
+ }
13
+ //# sourceMappingURL=20250726000000-discord-role-sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"20250726000000-discord-role-sync.js","sourceRoot":"","sources":["../../../src/migrations/sql/20250726000000-discord-role-sync.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,KAAK,UAAU,EAAE,CAAC,IAAU;IACjC,yCAAyC;IACzC,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;QAC9C,KAAK,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAC,QAAQ,EAAE,CAAC;QAC/C,KAAK,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,IAAU;IACnC,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;QAC9C,KAAK,CAAC,UAAU,CAAC,qBAAqB,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { Knex } from 'knex';
2
+ export declare function up(knex: Knex): Promise<void>;
3
+ export declare function down(knex: Knex): Promise<void>;
4
+ //# sourceMappingURL=20250727092719-add-quality-to-inventory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"20250727092719-add-quality-to-inventory.d.ts","sourceRoot":"","sources":["../../../src/migrations/sql/20250727092719-add-quality-to-inventory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,wBAAsB,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAIlD;AAED,wBAAsB,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAIpD"}
@@ -0,0 +1,11 @@
1
+ export async function up(knex) {
2
+ await knex.schema.alterTable('playerInventoryHistory', (table) => {
3
+ table.string('quality').nullable();
4
+ });
5
+ }
6
+ export async function down(knex) {
7
+ await knex.schema.alterTable('playerInventoryHistory', (table) => {
8
+ table.dropColumn('quality');
9
+ });
10
+ }
11
+ //# sourceMappingURL=20250727092719-add-quality-to-inventory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"20250727092719-add-quality-to-inventory.js","sourceRoot":"","sources":["../../../src/migrations/sql/20250727092719-add-quality-to-inventory.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,KAAK,UAAU,EAAE,CAAC,IAAU;IACjC,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,wBAAwB,EAAE,CAAC,KAAK,EAAE,EAAE;QAC/D,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,QAAQ,EAAE,CAAC;IACrC,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,IAAU;IACnC,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,wBAAwB,EAAE,CAAC,KAAK,EAAE,EAAE;QAC/D,KAAK,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;IAC9B,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { Knex } from 'knex';
2
+ export declare function up(knex: Knex): Promise<void>;
3
+ export declare function down(knex: Knex): Promise<void>;
4
+ //# sourceMappingURL=20250802124307-add-playeriphistory-composite-index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"20250802124307-add-playeriphistory-composite-index.d.ts","sourceRoot":"","sources":["../../../src/migrations/sql/20250802124307-add-playeriphistory-composite-index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,wBAAsB,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAIlD;AAED,wBAAsB,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAIpD"}
@@ -0,0 +1,11 @@
1
+ export async function up(knex) {
2
+ await knex.schema.alterTable('playerIpHistory', (table) => {
3
+ table.index(['domain', 'playerId', 'createdAt'], 'idx_playeriphistory_domain_playerid_createdat');
4
+ });
5
+ }
6
+ export async function down(knex) {
7
+ await knex.schema.alterTable('playerIpHistory', (table) => {
8
+ table.dropIndex([], 'idx_playeriphistory_domain_playerid_createdat');
9
+ });
10
+ }
11
+ //# sourceMappingURL=20250802124307-add-playeriphistory-composite-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"20250802124307-add-playeriphistory-composite-index.js","sourceRoot":"","sources":["../../../src/migrations/sql/20250802124307-add-playeriphistory-composite-index.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,KAAK,UAAU,EAAE,CAAC,IAAU;IACjC,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC,KAAK,EAAE,EAAE;QACxD,KAAK,CAAC,KAAK,CAAC,CAAC,QAAQ,EAAE,UAAU,EAAE,WAAW,CAAC,EAAE,+CAA+C,CAAC,CAAC;IACpG,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,IAAU;IACnC,MAAM,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,iBAAiB,EAAE,CAAC,KAAK,EAAE,EAAE;QACxD,KAAK,CAAC,SAAS,CAAC,EAAE,EAAE,+CAA+C,CAAC,CAAC;IACvE,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { Knex } from 'knex';
2
+ export declare function up(knex: Knex): Promise<void>;
3
+ export declare function down(knex: Knex): Promise<void>;
4
+ //# sourceMappingURL=20250809122020-add-player-name-history.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"20250809122020-add-player-name-history.d.ts","sourceRoot":"","sources":["../../../src/migrations/sql/20250809122020-add-player-name-history.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,wBAAsB,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAalD;AAED,wBAAsB,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAapD"}
@@ -0,0 +1,26 @@
1
+ export async function up(knex) {
2
+ await knex.schema.createTable('playerNameHistory', (table) => {
3
+ table.uuid('id').primary().defaultTo(knex.raw('gen_random_uuid ()'));
4
+ table.timestamps(true, true, true);
5
+ table.string('domain').references('domains.id').onDelete('CASCADE').notNullable();
6
+ table.uuid('playerId').references('players.id').onDelete('CASCADE').notNullable();
7
+ table.uuid('gameServerId').references('gameservers.id').onDelete('SET NULL').nullable();
8
+ table.string('name').notNullable();
9
+ // Indexes for performance
10
+ table.index(['playerId', 'createdAt'], 'idx_player_name_history_player_created');
11
+ table.index('name', 'idx_player_name_history_name');
12
+ });
13
+ }
14
+ export async function down(knex) {
15
+ // Update players table with latest name from history before dropping
16
+ const latestNames = await knex('playerNameHistory')
17
+ .select('playerId', 'name')
18
+ .distinctOn('playerId')
19
+ .orderBy('playerId')
20
+ .orderBy('createdAt', 'desc');
21
+ for (const record of latestNames) {
22
+ await knex('players').where('id', record.playerId).update({ name: record.name });
23
+ }
24
+ await knex.schema.dropTable('playerNameHistory');
25
+ }
26
+ //# sourceMappingURL=20250809122020-add-player-name-history.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"20250809122020-add-player-name-history.js","sourceRoot":"","sources":["../../../src/migrations/sql/20250809122020-add-player-name-history.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,KAAK,UAAU,EAAE,CAAC,IAAU;IACjC,MAAM,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,mBAAmB,EAAE,CAAC,KAAK,EAAE,EAAE;QAC3D,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC,CAAC;QACrE,KAAK,CAAC,UAAU,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;QACnC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAC;QAClF,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,WAAW,EAAE,CAAC;QAClF,KAAK,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,QAAQ,EAAE,CAAC;QACxF,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,CAAC;QAEnC,0BAA0B;QAC1B,KAAK,CAAC,KAAK,CAAC,CAAC,UAAU,EAAE,WAAW,CAAC,EAAE,wCAAwC,CAAC,CAAC;QACjF,KAAK,CAAC,KAAK,CAAC,MAAM,EAAE,8BAA8B,CAAC,CAAC;IACtD,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,IAAU;IACnC,qEAAqE;IACrE,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,mBAAmB,CAAC;SAChD,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC;SAC1B,UAAU,CAAC,UAAU,CAAC;SACtB,OAAO,CAAC,UAAU,CAAC;SACnB,OAAO,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;IAEhC,KAAK,MAAM,MAAM,IAAI,WAAW,EAAE,CAAC;QACjC,MAAM,IAAI,CAAC,SAAS,CAAC,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IACnF,CAAC;IAED,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,mBAAmB,CAAC,CAAC;AACnD,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { Knex } from 'knex';
2
+ export declare function up(knex: Knex): Promise<void>;
3
+ export declare function down(knex: Knex): Promise<void>;
4
+ //# sourceMappingURL=20250812163648-add-kpi-performance-indexes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"20250812163648-add-kpi-performance-indexes.d.ts","sourceRoot":"","sources":["../../../src/migrations/sql/20250812163648-add-kpi-performance-indexes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,wBAAsB,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAYlD;AAED,wBAAsB,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAGpD"}
@@ -0,0 +1,17 @@
1
+ export async function up(knex) {
2
+ // Add index for playerOnGameServer activity queries (DAU/WAU/MAU)
3
+ await knex.schema.raw(`
4
+ CREATE INDEX IF NOT EXISTS idx_pog_domain_lastseen
5
+ ON "playerOnGameServer"(domain, "lastSeen" DESC)
6
+ `);
7
+ // Add index for user activity queries
8
+ await knex.schema.raw(`
9
+ CREATE INDEX IF NOT EXISTS idx_users_domain_lastseen
10
+ ON users(domain, "lastSeen" DESC)
11
+ `);
12
+ }
13
+ export async function down(knex) {
14
+ await knex.schema.raw('DROP INDEX IF EXISTS idx_pog_domain_lastseen');
15
+ await knex.schema.raw('DROP INDEX IF EXISTS idx_users_domain_lastseen');
16
+ }
17
+ //# sourceMappingURL=20250812163648-add-kpi-performance-indexes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"20250812163648-add-kpi-performance-indexes.js","sourceRoot":"","sources":["../../../src/migrations/sql/20250812163648-add-kpi-performance-indexes.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,KAAK,UAAU,EAAE,CAAC,IAAU;IACjC,kEAAkE;IAClE,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC;;;GAGrB,CAAC,CAAC;IAEH,sCAAsC;IACtC,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC;;;GAGrB,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,IAAU;IACnC,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;IACtE,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,gDAAgD,CAAC,CAAC;AAC1E,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { Knex } from 'knex';
2
+ export declare function up(knex: Knex): Promise<void>;
3
+ export declare function down(knex: Knex): Promise<void>;
4
+ //# sourceMappingURL=20250814163747-shop-order-cascade-delete.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"20250814163747-shop-order-cascade-delete.d.ts","sourceRoot":"","sources":["../../../src/migrations/sql/20250814163747-shop-order-cascade-delete.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,wBAAsB,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAWlD;AAED,wBAAsB,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAWpD"}
@@ -0,0 +1,23 @@
1
+ export async function up(knex) {
2
+ await knex.raw(`
3
+ ALTER TABLE "shopOrder"
4
+ DROP CONSTRAINT IF EXISTS shoporder_playerid_foreign;
5
+ `);
6
+ await knex.raw(`
7
+ ALTER TABLE "shopOrder"
8
+ ADD CONSTRAINT shoporder_playerid_foreign
9
+ FOREIGN KEY ("playerId") REFERENCES players(id) ON DELETE CASCADE;
10
+ `);
11
+ }
12
+ export async function down(knex) {
13
+ await knex.raw(`
14
+ ALTER TABLE "shopOrder"
15
+ DROP CONSTRAINT IF EXISTS shoporder_playerid_foreign;
16
+ `);
17
+ await knex.raw(`
18
+ ALTER TABLE "shopOrder"
19
+ ADD CONSTRAINT shoporder_playerid_foreign
20
+ FOREIGN KEY ("playerId") REFERENCES players(id) ON DELETE NO ACTION;
21
+ `);
22
+ }
23
+ //# sourceMappingURL=20250814163747-shop-order-cascade-delete.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"20250814163747-shop-order-cascade-delete.js","sourceRoot":"","sources":["../../../src/migrations/sql/20250814163747-shop-order-cascade-delete.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,KAAK,UAAU,EAAE,CAAC,IAAU;IACjC,MAAM,IAAI,CAAC,GAAG,CAAC;;;GAGd,CAAC,CAAC;IAEH,MAAM,IAAI,CAAC,GAAG,CAAC;;;;GAId,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,IAAU;IACnC,MAAM,IAAI,CAAC,GAAG,CAAC;;;GAGd,CAAC,CAAC;IAEH,MAAM,IAAI,CAAC,GAAG,CAAC;;;;GAId,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,4 @@
1
+ import { Knex } from 'knex';
2
+ export declare function up(knex: Knex): Promise<void>;
3
+ export declare function down(knex: Knex): Promise<void>;
4
+ //# sourceMappingURL=20250815120000-optimize-shop-analytics-indexes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"20250815120000-optimize-shop-analytics-indexes.d.ts","sourceRoot":"","sources":["../../../src/migrations/sql/20250815120000-optimize-shop-analytics-indexes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,wBAAsB,EAAE,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAmClD;AAED,wBAAsB,IAAI,CAAC,IAAI,EAAE,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAMpD"}
@@ -0,0 +1,40 @@
1
+ export async function up(knex) {
2
+ // Index for filtering orders by domain, status, and date range
3
+ await knex.raw(`
4
+ CREATE INDEX IF NOT EXISTS idx_shoporder_analytics
5
+ ON "shopOrder" (domain, status, "createdAt")
6
+ WHERE status IN ('COMPLETED', 'PAID')
7
+ `);
8
+ // Index for joining orders with listings and filtering by date
9
+ await knex.raw(`
10
+ CREATE INDEX IF NOT EXISTS idx_shoporder_listing_date
11
+ ON "shopOrder" ("listingId", "createdAt")
12
+ WHERE status IN ('COMPLETED', 'PAID')
13
+ `);
14
+ // Index for customer analytics (unique players)
15
+ await knex.raw(`
16
+ CREATE INDEX IF NOT EXISTS idx_shoporder_player_analytics
17
+ ON "shopOrder" (domain, "playerId", "createdAt")
18
+ WHERE status IN ('COMPLETED', 'PAID')
19
+ `);
20
+ // Composite index for shop listings to speed up joins
21
+ await knex.raw(`
22
+ CREATE INDEX IF NOT EXISTS idx_shoplisting_composite
23
+ ON "shopListing" (id, "gameServerId", price)
24
+ WHERE "deletedAt" IS NULL AND draft = false
25
+ `);
26
+ // Index for filtering listings by game server and active status
27
+ await knex.raw(`
28
+ CREATE INDEX IF NOT EXISTS idx_shoplisting_active
29
+ ON "shopListing" (domain, "gameServerId")
30
+ WHERE "deletedAt" IS NULL AND draft = false
31
+ `);
32
+ }
33
+ export async function down(knex) {
34
+ await knex.raw('DROP INDEX IF EXISTS idx_shoporder_analytics');
35
+ await knex.raw('DROP INDEX IF EXISTS idx_shoporder_listing_date');
36
+ await knex.raw('DROP INDEX IF EXISTS idx_shoporder_player_analytics');
37
+ await knex.raw('DROP INDEX IF EXISTS idx_shoplisting_composite');
38
+ await knex.raw('DROP INDEX IF EXISTS idx_shoplisting_active');
39
+ }
40
+ //# sourceMappingURL=20250815120000-optimize-shop-analytics-indexes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"20250815120000-optimize-shop-analytics-indexes.js","sourceRoot":"","sources":["../../../src/migrations/sql/20250815120000-optimize-shop-analytics-indexes.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,KAAK,UAAU,EAAE,CAAC,IAAU;IACjC,+DAA+D;IAC/D,MAAM,IAAI,CAAC,GAAG,CAAC;;;;GAId,CAAC,CAAC;IAEH,+DAA+D;IAC/D,MAAM,IAAI,CAAC,GAAG,CAAC;;;;GAId,CAAC,CAAC;IAEH,gDAAgD;IAChD,MAAM,IAAI,CAAC,GAAG,CAAC;;;;GAId,CAAC,CAAC;IAEH,sDAAsD;IACtD,MAAM,IAAI,CAAC,GAAG,CAAC;;;;GAId,CAAC,CAAC;IAEH,gEAAgE;IAChE,MAAM,IAAI,CAAC,GAAG,CAAC;;;;GAId,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,IAAU;IACnC,MAAM,IAAI,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;IAC/D,MAAM,IAAI,CAAC,GAAG,CAAC,iDAAiD,CAAC,CAAC;IAClE,MAAM,IAAI,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAC;IACtE,MAAM,IAAI,CAAC,GAAG,CAAC,gDAAgD,CAAC,CAAC;IACjE,MAAM,IAAI,CAAC,GAAG,CAAC,6CAA6C,CAAC,CAAC;AAChE,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@takaro/db",
3
- "version": "0.3.3",
3
+ "version": "0.4.3",
4
4
  "description": "An opinionated data layer",
5
5
  "main": "dist/main.js",
6
6
  "types": "dist/main.d.ts",
@@ -0,0 +1,15 @@
1
+ import { Knex } from 'knex';
2
+
3
+ export async function up(knex: Knex): Promise<void> {
4
+ // Add linkedDiscordRoleId to roles table
5
+ await knex.schema.alterTable('roles', (table) => {
6
+ table.string('linkedDiscordRoleId').nullable();
7
+ table.index('linkedDiscordRoleId');
8
+ });
9
+ }
10
+
11
+ export async function down(knex: Knex): Promise<void> {
12
+ await knex.schema.alterTable('roles', (table) => {
13
+ table.dropColumn('linkedDiscordRoleId');
14
+ });
15
+ }
@@ -0,0 +1,13 @@
1
+ import { Knex } from 'knex';
2
+
3
+ export async function up(knex: Knex): Promise<void> {
4
+ await knex.schema.alterTable('playerInventoryHistory', (table) => {
5
+ table.string('quality').nullable();
6
+ });
7
+ }
8
+
9
+ export async function down(knex: Knex): Promise<void> {
10
+ await knex.schema.alterTable('playerInventoryHistory', (table) => {
11
+ table.dropColumn('quality');
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('playerIpHistory', (table) => {
5
+ table.index(['domain', 'playerId', 'createdAt'], 'idx_playeriphistory_domain_playerid_createdat');
6
+ });
7
+ }
8
+
9
+ export async function down(knex: Knex): Promise<void> {
10
+ await knex.schema.alterTable('playerIpHistory', (table) => {
11
+ table.dropIndex([], 'idx_playeriphistory_domain_playerid_createdat');
12
+ });
13
+ }
@@ -0,0 +1,31 @@
1
+ import { Knex } from 'knex';
2
+
3
+ export async function up(knex: Knex): Promise<void> {
4
+ await knex.schema.createTable('playerNameHistory', (table) => {
5
+ table.uuid('id').primary().defaultTo(knex.raw('gen_random_uuid ()'));
6
+ table.timestamps(true, true, true);
7
+ table.string('domain').references('domains.id').onDelete('CASCADE').notNullable();
8
+ table.uuid('playerId').references('players.id').onDelete('CASCADE').notNullable();
9
+ table.uuid('gameServerId').references('gameservers.id').onDelete('SET NULL').nullable();
10
+ table.string('name').notNullable();
11
+
12
+ // Indexes for performance
13
+ table.index(['playerId', 'createdAt'], 'idx_player_name_history_player_created');
14
+ table.index('name', 'idx_player_name_history_name');
15
+ });
16
+ }
17
+
18
+ export async function down(knex: Knex): Promise<void> {
19
+ // Update players table with latest name from history before dropping
20
+ const latestNames = await knex('playerNameHistory')
21
+ .select('playerId', 'name')
22
+ .distinctOn('playerId')
23
+ .orderBy('playerId')
24
+ .orderBy('createdAt', 'desc');
25
+
26
+ for (const record of latestNames) {
27
+ await knex('players').where('id', record.playerId).update({ name: record.name });
28
+ }
29
+
30
+ await knex.schema.dropTable('playerNameHistory');
31
+ }
@@ -0,0 +1,20 @@
1
+ import { Knex } from 'knex';
2
+
3
+ export async function up(knex: Knex): Promise<void> {
4
+ // Add index for playerOnGameServer activity queries (DAU/WAU/MAU)
5
+ await knex.schema.raw(`
6
+ CREATE INDEX IF NOT EXISTS idx_pog_domain_lastseen
7
+ ON "playerOnGameServer"(domain, "lastSeen" DESC)
8
+ `);
9
+
10
+ // Add index for user activity queries
11
+ await knex.schema.raw(`
12
+ CREATE INDEX IF NOT EXISTS idx_users_domain_lastseen
13
+ ON users(domain, "lastSeen" DESC)
14
+ `);
15
+ }
16
+
17
+ export async function down(knex: Knex): Promise<void> {
18
+ await knex.schema.raw('DROP INDEX IF EXISTS idx_pog_domain_lastseen');
19
+ await knex.schema.raw('DROP INDEX IF EXISTS idx_users_domain_lastseen');
20
+ }
@@ -0,0 +1,27 @@
1
+ import { Knex } from 'knex';
2
+
3
+ export async function up(knex: Knex): Promise<void> {
4
+ await knex.raw(`
5
+ ALTER TABLE "shopOrder"
6
+ DROP CONSTRAINT IF EXISTS shoporder_playerid_foreign;
7
+ `);
8
+
9
+ await knex.raw(`
10
+ ALTER TABLE "shopOrder"
11
+ ADD CONSTRAINT shoporder_playerid_foreign
12
+ FOREIGN KEY ("playerId") REFERENCES players(id) ON DELETE CASCADE;
13
+ `);
14
+ }
15
+
16
+ export async function down(knex: Knex): Promise<void> {
17
+ await knex.raw(`
18
+ ALTER TABLE "shopOrder"
19
+ DROP CONSTRAINT IF EXISTS shoporder_playerid_foreign;
20
+ `);
21
+
22
+ await knex.raw(`
23
+ ALTER TABLE "shopOrder"
24
+ ADD CONSTRAINT shoporder_playerid_foreign
25
+ FOREIGN KEY ("playerId") REFERENCES players(id) ON DELETE NO ACTION;
26
+ `);
27
+ }
@@ -0,0 +1,46 @@
1
+ import { Knex } from 'knex';
2
+
3
+ export async function up(knex: Knex): Promise<void> {
4
+ // Index for filtering orders by domain, status, and date range
5
+ await knex.raw(`
6
+ CREATE INDEX IF NOT EXISTS idx_shoporder_analytics
7
+ ON "shopOrder" (domain, status, "createdAt")
8
+ WHERE status IN ('COMPLETED', 'PAID')
9
+ `);
10
+
11
+ // Index for joining orders with listings and filtering by date
12
+ await knex.raw(`
13
+ CREATE INDEX IF NOT EXISTS idx_shoporder_listing_date
14
+ ON "shopOrder" ("listingId", "createdAt")
15
+ WHERE status IN ('COMPLETED', 'PAID')
16
+ `);
17
+
18
+ // Index for customer analytics (unique players)
19
+ await knex.raw(`
20
+ CREATE INDEX IF NOT EXISTS idx_shoporder_player_analytics
21
+ ON "shopOrder" (domain, "playerId", "createdAt")
22
+ WHERE status IN ('COMPLETED', 'PAID')
23
+ `);
24
+
25
+ // Composite index for shop listings to speed up joins
26
+ await knex.raw(`
27
+ CREATE INDEX IF NOT EXISTS idx_shoplisting_composite
28
+ ON "shopListing" (id, "gameServerId", price)
29
+ WHERE "deletedAt" IS NULL AND draft = false
30
+ `);
31
+
32
+ // Index for filtering listings by game server and active status
33
+ await knex.raw(`
34
+ CREATE INDEX IF NOT EXISTS idx_shoplisting_active
35
+ ON "shopListing" (domain, "gameServerId")
36
+ WHERE "deletedAt" IS NULL AND draft = false
37
+ `);
38
+ }
39
+
40
+ export async function down(knex: Knex): Promise<void> {
41
+ await knex.raw('DROP INDEX IF EXISTS idx_shoporder_analytics');
42
+ await knex.raw('DROP INDEX IF EXISTS idx_shoporder_listing_date');
43
+ await knex.raw('DROP INDEX IF EXISTS idx_shoporder_player_analytics');
44
+ await knex.raw('DROP INDEX IF EXISTS idx_shoplisting_composite');
45
+ await knex.raw('DROP INDEX IF EXISTS idx_shoplisting_active');
46
+ }