@openora/core 0.4.1-canary.152 → 0.4.1-canary.153
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/.tsbuildinfo +1 -1
- package/dist/admin-console/__tests__/backoffice.service.int.test.js +20 -3
- package/dist/admin-console/__tests__/backoffice.service.int.test.js.map +1 -1
- package/dist/audit/__tests__/map-event.test.js +46 -0
- package/dist/audit/__tests__/map-event.test.js.map +1 -1
- package/dist/audit/plugin.d.ts.map +1 -1
- package/dist/audit/plugin.js +74 -0
- package/dist/audit/plugin.js.map +1 -1
- package/dist/audit/service/audit.service.d.ts.map +1 -1
- package/dist/audit/service/audit.service.js +1 -6
- package/dist/audit/service/audit.service.js.map +1 -1
- package/dist/casino/gaming/__tests__/admin-reporting.int.test.js +20 -3
- package/dist/casino/gaming/__tests__/admin-reporting.int.test.js.map +1 -1
- package/dist/casino/gaming/__tests__/game-category.service.int.test.d.ts +2 -0
- package/dist/casino/gaming/__tests__/game-category.service.int.test.d.ts.map +1 -0
- package/dist/casino/gaming/__tests__/game-category.service.int.test.js +134 -0
- package/dist/casino/gaming/__tests__/game-category.service.int.test.js.map +1 -0
- package/dist/casino/gaming/__tests__/game-provider.service.int.test.d.ts +2 -0
- package/dist/casino/gaming/__tests__/game-provider.service.int.test.d.ts.map +1 -0
- package/dist/casino/gaming/__tests__/game-provider.service.int.test.js +274 -0
- package/dist/casino/gaming/__tests__/game-provider.service.int.test.js.map +1 -0
- package/dist/casino/gaming/__tests__/gaming-catalog-admin.router.int.test.d.ts +2 -0
- package/dist/casino/gaming/__tests__/gaming-catalog-admin.router.int.test.d.ts.map +1 -0
- package/dist/casino/gaming/__tests__/gaming-catalog-admin.router.int.test.js +174 -0
- package/dist/casino/gaming/__tests__/gaming-catalog-admin.router.int.test.js.map +1 -0
- package/dist/casino/gaming/__tests__/gaming-migration.int.test.d.ts +2 -0
- package/dist/casino/gaming/__tests__/gaming-migration.int.test.d.ts.map +1 -0
- package/dist/casino/gaming/__tests__/gaming-migration.int.test.js +171 -0
- package/dist/casino/gaming/__tests__/gaming-migration.int.test.js.map +1 -0
- package/dist/casino/gaming/__tests__/gaming.service.int.test.js +274 -13
- package/dist/casino/gaming/__tests__/gaming.service.int.test.js.map +1 -1
- package/dist/casino/gaming/contract/index.d.ts +520 -18
- package/dist/casino/gaming/contract/index.d.ts.map +1 -1
- package/dist/casino/gaming/contract/index.js +167 -4
- package/dist/casino/gaming/contract/index.js.map +1 -1
- package/dist/casino/gaming/drizzle/migrations/0005_natural_thunderbolt_ross.sql +223 -0
- package/dist/casino/gaming/drizzle/migrations/meta/0005_snapshot.json +680 -0
- package/dist/casino/gaming/drizzle/migrations/meta/_journal.json +7 -0
- package/dist/casino/gaming/plugin.d.ts.map +1 -1
- package/dist/casino/gaming/plugin.js +9 -2
- package/dist/casino/gaming/plugin.js.map +1 -1
- package/dist/casino/gaming/router/index.d.ts +372 -18
- package/dist/casino/gaming/router/index.d.ts.map +1 -1
- package/dist/casino/gaming/router/index.js +62 -6
- package/dist/casino/gaming/router/index.js.map +1 -1
- package/dist/casino/gaming/schema/index.d.ts +499 -4
- package/dist/casino/gaming/schema/index.d.ts.map +1 -1
- package/dist/casino/gaming/schema/index.js +72 -6
- package/dist/casino/gaming/schema/index.js.map +1 -1
- package/dist/casino/gaming/service/game-category.service.d.ts +109 -0
- package/dist/casino/gaming/service/game-category.service.d.ts.map +1 -0
- package/dist/casino/gaming/service/game-category.service.js +176 -0
- package/dist/casino/gaming/service/game-category.service.js.map +1 -0
- package/dist/casino/gaming/service/game-provider.service.d.ts +118 -0
- package/dist/casino/gaming/service/game-provider.service.d.ts.map +1 -0
- package/dist/casino/gaming/service/game-provider.service.js +251 -0
- package/dist/casino/gaming/service/game-provider.service.js.map +1 -0
- package/dist/casino/gaming/service/gaming.service.d.ts +122 -14
- package/dist/casino/gaming/service/gaming.service.d.ts.map +1 -1
- package/dist/casino/gaming/service/gaming.service.js +189 -23
- package/dist/casino/gaming/service/gaming.service.js.map +1 -1
- package/dist/casino/lobby/__tests__/lobby.cache.int.test.js +137 -4
- package/dist/casino/lobby/__tests__/lobby.cache.int.test.js.map +1 -1
- package/dist/casino/lobby/contract/index.d.ts +68 -8
- package/dist/casino/lobby/contract/index.d.ts.map +1 -1
- package/dist/casino/lobby/contract/index.js +4 -3
- package/dist/casino/lobby/contract/index.js.map +1 -1
- package/dist/casino/lobby/router/index.d.ts +34 -4
- package/dist/casino/lobby/router/index.d.ts.map +1 -1
- package/dist/casino/lobby/service/lobby.service.d.ts +34 -4
- package/dist/casino/lobby/service/lobby.service.d.ts.map +1 -1
- package/dist/casino/lobby/service/lobby.service.js +60 -26
- package/dist/casino/lobby/service/lobby.service.js.map +1 -1
- package/dist/casino/shared/game-catalog.d.ts +32 -0
- package/dist/casino/shared/game-catalog.d.ts.map +1 -0
- package/dist/casino/shared/game-catalog.js +67 -0
- package/dist/casino/shared/game-catalog.js.map +1 -0
- package/dist/compliance/__tests__/rg-monitoring.service.int.test.js +17 -3
- package/dist/compliance/__tests__/rg-monitoring.service.int.test.js.map +1 -1
- package/dist/compliance/__tests__/rg-self-service.int.test.js +2 -2
- package/dist/compliance/__tests__/rg-self-service.int.test.js.map +1 -1
- package/dist/contracts/__tests__/kit.test.js +21 -1
- package/dist/contracts/__tests__/kit.test.js.map +1 -1
- package/dist/contracts/kit.d.ts +3 -0
- package/dist/contracts/kit.d.ts.map +1 -1
- package/dist/contracts/kit.js +8 -0
- package/dist/contracts/kit.js.map +1 -1
- package/dist/contracts/schemas/__tests__/events.test.js +7 -0
- package/dist/contracts/schemas/__tests__/events.test.js.map +1 -1
- package/dist/contracts/schemas/__tests__/game-schemas.test.d.ts +2 -0
- package/dist/contracts/schemas/__tests__/game-schemas.test.d.ts.map +1 -0
- package/dist/contracts/schemas/__tests__/game-schemas.test.js +43 -0
- package/dist/contracts/schemas/__tests__/game-schemas.test.js.map +1 -0
- package/dist/contracts/schemas/events.d.ts +109 -0
- package/dist/contracts/schemas/events.d.ts.map +1 -1
- package/dist/contracts/schemas/events.js +86 -0
- package/dist/contracts/schemas/events.js.map +1 -1
- package/dist/contracts/schemas/game.d.ts +39 -0
- package/dist/contracts/schemas/game.d.ts.map +1 -1
- package/dist/contracts/schemas/game.js +32 -0
- package/dist/contracts/schemas/game.js.map +1 -1
- package/dist/contracts/schemas/iam.d.ts +1 -1
- package/dist/contracts/schemas/iam.js +1 -1
- package/dist/contracts/schemas/iam.js.map +1 -1
- package/dist/react/client.d.ts +2 -1
- package/dist/react/client.d.ts.map +1 -1
- package/dist/react/client.js +2 -1
- package/dist/react/client.js.map +1 -1
- package/dist/server/auth/permissions.d.ts +12 -12
- package/dist/server/auth/permissions.js +1 -1
- package/dist/server/auth/permissions.js.map +1 -1
- package/dist/server/db/__tests__/query-helpers.test.js +47 -1
- package/dist/server/db/__tests__/query-helpers.test.js.map +1 -1
- package/dist/server/db/index.d.ts +1 -1
- package/dist/server/db/index.d.ts.map +1 -1
- package/dist/server/db/index.js +1 -1
- package/dist/server/db/index.js.map +1 -1
- package/dist/server/db/query-helpers.d.ts +5 -0
- package/dist/server/db/query-helpers.d.ts.map +1 -1
- package/dist/server/db/query-helpers.js +37 -0
- package/dist/server/db/query-helpers.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gaming-catalog-admin.router.int.test.js","sourceRoot":"","sources":["../../../../src/casino/gaming/__tests__/gaming-catalog-admin.router.int.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gaming-migration.int.test.d.ts","sourceRoot":"","sources":["../../../../src/casino/gaming/__tests__/gaming-migration.int.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
|
|
2
|
+
import { readdirSync, readFileSync } from 'node:fs';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
import { sql, eq } from 'drizzle-orm';
|
|
5
|
+
import { createTestDb } from '@openora/core/testing';
|
|
6
|
+
import { game, gameCategory, gameCategoryGame, gameProvider } from '../schema/index.js';
|
|
7
|
+
let db;
|
|
8
|
+
// Matched by migration index (0003/0004/...) so later renames of the random
|
|
9
|
+
// drizzle tag suffix never break this file.
|
|
10
|
+
function migrationStatements(index) {
|
|
11
|
+
const dir = fileURLToPath(new URL('../drizzle/migrations', import.meta.url));
|
|
12
|
+
const [file] = readdirSync(dir)
|
|
13
|
+
.filter((f) => new RegExp(`^${index}_.*\\.sql$`).exec(f))
|
|
14
|
+
.sort();
|
|
15
|
+
if (!file) {
|
|
16
|
+
throw new Error(`migration ${index}_* not found`);
|
|
17
|
+
}
|
|
18
|
+
return readFileSync(`${dir}/${file}`, 'utf8')
|
|
19
|
+
.split('--> statement-breakpoint')
|
|
20
|
+
.map((s) => s.trim())
|
|
21
|
+
.filter((s) => s.length > 0);
|
|
22
|
+
}
|
|
23
|
+
async function apply(indexes) {
|
|
24
|
+
for (const index of indexes) {
|
|
25
|
+
for (const stmt of migrationStatements(index)) {
|
|
26
|
+
await db.drizzle.db.execute(sql.raw(stmt));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
async function nullability() {
|
|
31
|
+
const cols = (await db.drizzle.db.execute(sql `
|
|
32
|
+
SELECT column_name AS "name", is_nullable AS "nullable"
|
|
33
|
+
FROM information_schema.columns
|
|
34
|
+
WHERE table_name = 'game'
|
|
35
|
+
AND column_name IN ('slug', 'provider_id', 'aggregator', 'provider', 'category')`));
|
|
36
|
+
return new Map(cols.rows.map((r) => [r.name, r.nullable]));
|
|
37
|
+
}
|
|
38
|
+
beforeAll(async () => {
|
|
39
|
+
db = await createTestDb([]);
|
|
40
|
+
});
|
|
41
|
+
afterAll(async () => {
|
|
42
|
+
await db.drop();
|
|
43
|
+
});
|
|
44
|
+
describe('gaming catalog migration 0005 (real PG)', () => {
|
|
45
|
+
it('expands, backfills and enforces NOT NULL in one migration, keeping legacy columns', async () => {
|
|
46
|
+
await apply(['0000', '0001', '0002']);
|
|
47
|
+
await db.drizzle.db.execute(sql `
|
|
48
|
+
INSERT INTO "game" ("name", "provider", "category", "is_active") VALUES
|
|
49
|
+
('Roulette', 'Pragmatic Play', 'Table Games', true),
|
|
50
|
+
('Roulette', 'NetEnt', 'Slots', true),
|
|
51
|
+
('Aces', 'ACME', 'Slots', false),
|
|
52
|
+
('Kings', 'Acme', 'Slots', true)`);
|
|
53
|
+
await apply(['0003', '0004', '0005']);
|
|
54
|
+
const providers = await db.drizzle.db
|
|
55
|
+
.select({ slug: gameProvider.slug, name: gameProvider.name, isActive: gameProvider.isActive })
|
|
56
|
+
.from(gameProvider);
|
|
57
|
+
expect(providers.map((p) => p.slug).sort()).toEqual([
|
|
58
|
+
'acme',
|
|
59
|
+
'acme-2',
|
|
60
|
+
'netent',
|
|
61
|
+
'pragmatic-play',
|
|
62
|
+
]);
|
|
63
|
+
expect(providers.map((p) => p.name).sort()).toEqual([
|
|
64
|
+
'ACME',
|
|
65
|
+
'Acme',
|
|
66
|
+
'NetEnt',
|
|
67
|
+
'Pragmatic Play',
|
|
68
|
+
]);
|
|
69
|
+
expect(new Set(providers.map((p) => p.isActive))).toEqual(new Set([true]));
|
|
70
|
+
const games = await db.drizzle.db
|
|
71
|
+
.select({
|
|
72
|
+
name: game.name,
|
|
73
|
+
slug: game.slug,
|
|
74
|
+
providerId: game.providerId,
|
|
75
|
+
aggregator: game.aggregator,
|
|
76
|
+
isActive: game.isActive,
|
|
77
|
+
})
|
|
78
|
+
.from(game);
|
|
79
|
+
expect(games.map((g) => g.slug).sort()).toEqual(['aces', 'kings', 'roulette', 'roulette-2']);
|
|
80
|
+
expect(new Set(games.map((g) => g.aggregator))).toEqual(new Set(['direct']));
|
|
81
|
+
const byName = new Map(games.map((g) => [g.name, g]));
|
|
82
|
+
expect(byName.get('Aces')).toMatchObject({ isActive: false });
|
|
83
|
+
expect(byName.get('Kings')).toMatchObject({ isActive: true });
|
|
84
|
+
const providerNames = await db.drizzle.db
|
|
85
|
+
.select({ slug: game.slug, name: gameProvider.name })
|
|
86
|
+
.from(game)
|
|
87
|
+
.innerJoin(gameProvider, eq(game.providerId, gameProvider.id));
|
|
88
|
+
expect(new Map(providerNames.map((r) => [r.slug, r.name])).get('aces')).toBe('ACME');
|
|
89
|
+
const categories = await db.drizzle.db.select({ slug: gameCategory.slug }).from(gameCategory);
|
|
90
|
+
expect(categories.map((c) => c.slug).sort()).toEqual(['slots', 'table-games']);
|
|
91
|
+
const links = await db.drizzle.db.select().from(gameCategoryGame);
|
|
92
|
+
expect(links).toHaveLength(4);
|
|
93
|
+
const enforced = await nullability();
|
|
94
|
+
expect(enforced.get('slug')).toBe('NO');
|
|
95
|
+
expect(enforced.get('provider_id')).toBe('NO');
|
|
96
|
+
expect(enforced.get('aggregator')).toBe('NO');
|
|
97
|
+
// Legacy columns stay until the follow-up drop migration.
|
|
98
|
+
expect(enforced.get('provider')).toBe('YES');
|
|
99
|
+
expect(enforced.get('category')).toBe('YES');
|
|
100
|
+
});
|
|
101
|
+
it('accepts a previous-release legacy insert during a rolling deploy', async () => {
|
|
102
|
+
// Runs on the schema the previous test migrated: the old writer only knows
|
|
103
|
+
// name/provider/category, one onto a backfilled provider and one onto new names.
|
|
104
|
+
await db.drizzle.db.execute(sql `
|
|
105
|
+
INSERT INTO "game" ("name", "provider", "category", "is_active") VALUES
|
|
106
|
+
('Roulette', 'NetEnt', 'Slots', true),
|
|
107
|
+
('Crash X', 'Fresh Studio', 'Crash', true)`);
|
|
108
|
+
const rows = await db.drizzle.db
|
|
109
|
+
.select({
|
|
110
|
+
name: game.name,
|
|
111
|
+
slug: game.slug,
|
|
112
|
+
aggregator: game.aggregator,
|
|
113
|
+
providerName: gameProvider.name,
|
|
114
|
+
providerSlug: gameProvider.slug,
|
|
115
|
+
providerActive: gameProvider.isActive,
|
|
116
|
+
categorySlug: gameCategory.slug,
|
|
117
|
+
})
|
|
118
|
+
.from(game)
|
|
119
|
+
.innerJoin(gameProvider, eq(game.providerId, gameProvider.id))
|
|
120
|
+
.innerJoin(gameCategoryGame, eq(gameCategoryGame.gameId, game.id))
|
|
121
|
+
.innerJoin(gameCategory, eq(gameCategoryGame.categoryId, gameCategory.id))
|
|
122
|
+
.where(sql `${game.slug} IN ('roulette-3', 'crash-x')`);
|
|
123
|
+
expect(new Map(rows.map((r) => [r.slug, r]))).toEqual(new Map([
|
|
124
|
+
[
|
|
125
|
+
'roulette-3',
|
|
126
|
+
expect.objectContaining({
|
|
127
|
+
aggregator: 'direct',
|
|
128
|
+
providerSlug: 'netent',
|
|
129
|
+
categorySlug: 'slots',
|
|
130
|
+
}),
|
|
131
|
+
],
|
|
132
|
+
[
|
|
133
|
+
'crash-x',
|
|
134
|
+
expect.objectContaining({
|
|
135
|
+
aggregator: 'direct',
|
|
136
|
+
providerName: 'Fresh Studio',
|
|
137
|
+
providerSlug: 'fresh-studio',
|
|
138
|
+
providerActive: true,
|
|
139
|
+
categorySlug: 'crash',
|
|
140
|
+
}),
|
|
141
|
+
],
|
|
142
|
+
]));
|
|
143
|
+
const mapped = (await db.drizzle.db.execute(sql `
|
|
144
|
+
SELECT 1 FROM "game_provider_aggregator_mapping" "m"
|
|
145
|
+
JOIN "game_provider" "p" ON "p"."id" = "m"."provider_id"
|
|
146
|
+
WHERE "p"."slug" = 'fresh-studio' AND "m"."aggregator" = 'direct'`));
|
|
147
|
+
expect(mapped.rows).toHaveLength(1);
|
|
148
|
+
});
|
|
149
|
+
it('keeps the legacy triggers off the new-shape insert path', async () => {
|
|
150
|
+
const [studio] = await db.drizzle.db
|
|
151
|
+
.select({ id: gameProvider.id })
|
|
152
|
+
.from(gameProvider)
|
|
153
|
+
.where(eq(gameProvider.slug, 'netent'));
|
|
154
|
+
const [inserted] = await db.drizzle.db
|
|
155
|
+
.insert(game)
|
|
156
|
+
.values({
|
|
157
|
+
name: 'Fresh Game',
|
|
158
|
+
slug: 'custom-slug',
|
|
159
|
+
providerId: studio.id,
|
|
160
|
+
aggregator: 'hub',
|
|
161
|
+
})
|
|
162
|
+
.returning({ id: game.id, slug: game.slug, aggregator: game.aggregator });
|
|
163
|
+
expect(inserted).toMatchObject({ slug: 'custom-slug', aggregator: 'hub' });
|
|
164
|
+
const links = await db.drizzle.db
|
|
165
|
+
.select()
|
|
166
|
+
.from(gameCategoryGame)
|
|
167
|
+
.where(eq(gameCategoryGame.gameId, inserted.id));
|
|
168
|
+
expect(links).toEqual([]);
|
|
169
|
+
});
|
|
170
|
+
});
|
|
171
|
+
//# sourceMappingURL=gaming-migration.int.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gaming-migration.int.test.js","sourceRoot":"","sources":["../../../../src/casino/gaming/__tests__/gaming-migration.int.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import { describe, it, expect, vi, beforeAll, afterAll, beforeEach } from 'vitest';
|
|
2
|
+
import { randomUUID } from 'node:crypto';
|
|
2
3
|
import { eq, sql } from 'drizzle-orm';
|
|
3
4
|
import { createTestDb } from '@openora/core/testing';
|
|
4
5
|
import { migrate as migrateProfile } from '@openora/core/pam/migrate/profile';
|
|
5
|
-
import { mock, makeEventBus, makeIdentityReader } from '../../../testing/mock.js';
|
|
6
|
+
import { mock, makeEventBus, makeIdentityReader, NO_CLIENT_META } from '../../../testing/mock.js';
|
|
6
7
|
import { migrate } from '../migrate.js';
|
|
7
|
-
import { game, gameRound } from '../schema/index.js';
|
|
8
|
-
import { GamingService, GameNotFoundError, RgRestrictedError, InsufficientBalanceError, WinCreditFailedError, ExternalRoundOwnerMismatchError, } from '../service/gaming.service.js';
|
|
8
|
+
import { game, gameCategory, gameCategoryGame, gameProvider, gameProviderAggregatorMapping, gameRound, } from '../schema/index.js';
|
|
9
|
+
import { GamingService, GameAggregatorNotMappedError, GameNotFoundError, GameSlugTakenError, RgRestrictedError, InsufficientBalanceError, WinCreditFailedError, ExternalRoundOwnerMismatchError, } from '../service/gaming.service.js';
|
|
10
|
+
import { GameProviderNotFoundError } from '../service/game-provider.service.js';
|
|
11
|
+
import { GameCategoryNotFoundError } from '../service/game-category.service.js';
|
|
9
12
|
let db;
|
|
10
13
|
const noopEvents = makeEventBus();
|
|
14
|
+
const ACTOR = { actorId: '00000000-0000-4000-8000-000000000001', ...NO_CLIENT_META };
|
|
11
15
|
const eligibility = (isRestricted) => mock({ isRestricted: vi.fn().mockResolvedValue(isRestricted) });
|
|
12
16
|
const unrestricted = eligibility(false);
|
|
13
17
|
function makeWalletCommands(debitResult, creditResult = { ok: true, newBalance: '0' }) {
|
|
@@ -19,14 +23,43 @@ function makeWalletCommands(debitResult, creditResult = { ok: true, newBalance:
|
|
|
19
23
|
function makeService({ provider = mock({
|
|
20
24
|
launchGame: vi.fn().mockResolvedValue({ launchUrl: 'https://mock/play', token: 'tok' }),
|
|
21
25
|
endRound: vi.fn(),
|
|
22
|
-
}), playEligibility = unrestricted, walletCommands = makeWalletCommands({ ok: true, newBalance: '0', currency: 'USD' }), rgLimits, } = {}) {
|
|
23
|
-
return new GamingService(db.drizzle,
|
|
26
|
+
}), playEligibility = unrestricted, walletCommands = makeWalletCommands({ ok: true, newBalance: '0', currency: 'USD' }), rgLimits, events = noopEvents, } = {}) {
|
|
27
|
+
return new GamingService(db.drizzle, events, provider, playEligibility, walletCommands, makeIdentityReader(), rgLimits);
|
|
24
28
|
}
|
|
25
|
-
async function
|
|
29
|
+
async function seedProvider(overrides = {}) {
|
|
30
|
+
const [row] = await db.drizzle.db
|
|
31
|
+
.insert(gameProvider)
|
|
32
|
+
.values({ slug: `studio-${randomUUID()}`, name: 'Studio', isActive: true, ...overrides })
|
|
33
|
+
.returning();
|
|
34
|
+
await db.drizzle.db
|
|
35
|
+
.insert(gameProviderAggregatorMapping)
|
|
36
|
+
.values({ providerId: row.id, aggregator: 'direct', vendorId: row.slug });
|
|
37
|
+
return row;
|
|
38
|
+
}
|
|
39
|
+
async function seedCategory(overrides = {}) {
|
|
40
|
+
const [row] = await db.drizzle.db
|
|
41
|
+
.insert(gameCategory)
|
|
42
|
+
.values({ slug: `category-${randomUUID()}`, name: 'Slots', ...overrides })
|
|
43
|
+
.returning();
|
|
44
|
+
return row;
|
|
45
|
+
}
|
|
46
|
+
async function seedGame(overrides = {}, categoryIds) {
|
|
47
|
+
const provider = await seedProvider({ name: 'Mock Studio' });
|
|
48
|
+
const ids = categoryIds ?? [(await seedCategory()).id];
|
|
26
49
|
const [row] = await db.drizzle.db
|
|
27
50
|
.insert(game)
|
|
28
|
-
.values({
|
|
51
|
+
.values({
|
|
52
|
+
name: 'Game',
|
|
53
|
+
slug: `game-${randomUUID()}`,
|
|
54
|
+
providerId: provider.id,
|
|
55
|
+
aggregator: 'direct',
|
|
56
|
+
isActive: true,
|
|
57
|
+
...overrides,
|
|
58
|
+
})
|
|
29
59
|
.returning();
|
|
60
|
+
await db.drizzle.db
|
|
61
|
+
.insert(gameCategoryGame)
|
|
62
|
+
.values(ids.map((categoryId) => ({ gameId: row.id, categoryId })));
|
|
30
63
|
return row;
|
|
31
64
|
}
|
|
32
65
|
beforeAll(async () => {
|
|
@@ -36,22 +69,87 @@ afterAll(async () => {
|
|
|
36
69
|
await db.drop();
|
|
37
70
|
});
|
|
38
71
|
beforeEach(async () => {
|
|
39
|
-
await db.drizzle.db.execute(sql `TRUNCATE ${gameRound}, ${game} RESTART IDENTITY CASCADE`);
|
|
72
|
+
await db.drizzle.db.execute(sql `TRUNCATE ${gameRound}, ${gameCategoryGame}, ${game}, ${gameProvider}, ${gameCategory} RESTART IDENTITY CASCADE`);
|
|
40
73
|
});
|
|
41
74
|
describe('GamingService lobby (real PG)', () => {
|
|
42
|
-
it('
|
|
75
|
+
it('listGamesPublic paginates playable games ordered by name', async () => {
|
|
43
76
|
await seedGame({ name: 'Baccarat', isActive: true });
|
|
44
77
|
await seedGame({ name: 'Aces', isActive: true });
|
|
45
78
|
await seedGame({ name: 'Retired', isActive: false });
|
|
46
|
-
const
|
|
47
|
-
expect(
|
|
79
|
+
const page = await makeService().listGamesPublic({ page: 1, limit: 10 });
|
|
80
|
+
expect(page.total).toBe(2);
|
|
81
|
+
expect(page.items.map((g) => g.name)).toEqual(['Aces', 'Baccarat']);
|
|
82
|
+
});
|
|
83
|
+
it('listGamesPublic searches and filters by provider and category', async () => {
|
|
84
|
+
const p1 = await seedProvider({ slug: 'studio-one', name: 'One' });
|
|
85
|
+
const p2 = await seedProvider({ slug: 'studio-two', name: 'Two' });
|
|
86
|
+
const slots = await seedCategory({ slug: 'slots', name: 'Slots' });
|
|
87
|
+
const live = await seedCategory({ slug: 'live', name: 'Live' });
|
|
88
|
+
await seedGame({ name: 'Gates of Olympus', slug: 'gates-of-olympus', providerId: p1.id, isActive: true }, [slots.id]);
|
|
89
|
+
await seedGame({ name: 'Sweet Bonanza', slug: 'sweet-bonanza', providerId: p1.id, isActive: true }, [slots.id]);
|
|
90
|
+
await seedGame({ name: 'Crazy Time', slug: 'crazy-time', providerId: p2.id, isActive: true }, [
|
|
91
|
+
live.id,
|
|
92
|
+
slots.id,
|
|
93
|
+
]);
|
|
94
|
+
const svc = makeService();
|
|
95
|
+
expect((await svc.listGamesPublic({ page: 1, limit: 10, q: 'bonanza' })).total).toBe(1);
|
|
96
|
+
expect((await svc.listGamesPublic({ page: 1, limit: 10, providerId: p1.id })).items.map((g) => g.slug)).toEqual(['gates-of-olympus', 'sweet-bonanza']);
|
|
97
|
+
expect((await svc.listGamesPublic({ page: 1, limit: 10, categoryId: live.id })).total).toBe(1);
|
|
98
|
+
expect((await svc.listGamesPublic({ page: 1, limit: 10, categoryId: slots.id })).total).toBe(3);
|
|
99
|
+
});
|
|
100
|
+
it('hides an inactive category from public filtering while retaining admin filtering', async () => {
|
|
101
|
+
const inactive = await seedCategory({ name: 'Hidden', isActive: false });
|
|
102
|
+
const linked = await seedGame({ name: 'Linked Game' }, [inactive.id]);
|
|
103
|
+
const svc = makeService();
|
|
104
|
+
const publicResult = await svc.listGamesPublic({
|
|
105
|
+
page: 1,
|
|
106
|
+
limit: 10,
|
|
107
|
+
categoryId: inactive.id,
|
|
108
|
+
});
|
|
109
|
+
expect(publicResult).toMatchObject({ items: [], total: 0 });
|
|
110
|
+
const adminResult = await svc.listGamesAdmin({
|
|
111
|
+
page: 1,
|
|
112
|
+
limit: 10,
|
|
113
|
+
categoryId: inactive.id,
|
|
114
|
+
isActive: true,
|
|
115
|
+
});
|
|
116
|
+
expect(adminResult.items.map((item) => item.id)).toEqual([linked.id]);
|
|
117
|
+
expect(adminResult.total).toBe(1);
|
|
48
118
|
});
|
|
49
119
|
it('getGame returns the row for a known id and 404s an unknown one', async () => {
|
|
50
|
-
const
|
|
120
|
+
const table = await seedCategory({
|
|
121
|
+
slug: 'table-games',
|
|
122
|
+
name: 'Table Games',
|
|
123
|
+
translations: { de: { name: 'Tischspiele' } },
|
|
124
|
+
});
|
|
125
|
+
const blackjack = await seedCategory({ slug: 'blackjack', name: 'Blackjack', isActive: false });
|
|
126
|
+
const created = await seedGame({ name: 'Roulette' }, [table.id, blackjack.id]);
|
|
51
127
|
const svc = makeService();
|
|
52
|
-
expect(await svc.getGame(created.id)).toMatchObject({
|
|
128
|
+
expect(await svc.getGame(created.id)).toMatchObject({
|
|
129
|
+
name: 'Roulette',
|
|
130
|
+
categories: [
|
|
131
|
+
{ slug: 'blackjack', translations: {} },
|
|
132
|
+
{ slug: 'table-games', translations: { de: { name: 'Tischspiele' } } },
|
|
133
|
+
],
|
|
134
|
+
});
|
|
135
|
+
await expect(svc.getGame(created.id, { activeOnly: true })).resolves.toMatchObject({
|
|
136
|
+
categories: [{ slug: 'table-games' }],
|
|
137
|
+
});
|
|
53
138
|
await expect(svc.getGame('00000000-0000-0000-0000-000000000000')).rejects.toBeInstanceOf(GameNotFoundError);
|
|
54
139
|
});
|
|
140
|
+
it('getGame hides inactive games and deactivated providers only behind activeOnly', async () => {
|
|
141
|
+
const dark = await seedGame({ name: 'Dark', isActive: false });
|
|
142
|
+
const orphaned = await seedGame({ name: 'Orphaned' });
|
|
143
|
+
await db.drizzle.db
|
|
144
|
+
.update(gameProvider)
|
|
145
|
+
.set({ isActive: false })
|
|
146
|
+
.where(eq(gameProvider.id, orphaned.providerId));
|
|
147
|
+
const svc = makeService();
|
|
148
|
+
await expect(svc.getGame(dark.id, { activeOnly: true })).rejects.toBeInstanceOf(GameNotFoundError);
|
|
149
|
+
await expect(svc.getGame(orphaned.id, { activeOnly: true })).rejects.toBeInstanceOf(GameNotFoundError);
|
|
150
|
+
await expect(svc.getGame(dark.id)).resolves.toMatchObject({ name: 'Dark', isActive: false });
|
|
151
|
+
await expect(svc.getGame(orphaned.id)).resolves.toMatchObject({ name: 'Orphaned' });
|
|
152
|
+
});
|
|
55
153
|
});
|
|
56
154
|
const refusingLimits = () => mock({
|
|
57
155
|
checkDeposit: vi.fn(),
|
|
@@ -101,6 +199,36 @@ describe('GamingService.startRound (real PG)', () => {
|
|
|
101
199
|
await expect(svc.startRound('00000000-0000-0000-0000-000000000111', '00000000-0000-0000-0000-000000000222', 'EUR', '10')).rejects.toBeInstanceOf(GameNotFoundError);
|
|
102
200
|
expect(launchGame).not.toHaveBeenCalled();
|
|
103
201
|
});
|
|
202
|
+
it('404s an inactive game without touching the wallet or provider', async () => {
|
|
203
|
+
const created = await seedGame({ name: 'Dark', isActive: false });
|
|
204
|
+
const walletCommands = makeWalletCommands({ ok: true, newBalance: '90', currency: 'USD' });
|
|
205
|
+
const launchGame = vi.fn();
|
|
206
|
+
const svc = makeService({
|
|
207
|
+
provider: mock({ launchGame, endRound: vi.fn() }),
|
|
208
|
+
walletCommands,
|
|
209
|
+
});
|
|
210
|
+
await expect(svc.startRound('00000000-0000-0000-0000-000000000311', created.id, 'USD', '10')).rejects.toBeInstanceOf(GameNotFoundError);
|
|
211
|
+
expect(walletCommands.debit).not.toHaveBeenCalled();
|
|
212
|
+
expect(launchGame).not.toHaveBeenCalled();
|
|
213
|
+
expect(await db.drizzle.db.select().from(gameRound)).toHaveLength(0);
|
|
214
|
+
});
|
|
215
|
+
it('404s a game on a deactivated provider without touching the wallet or provider', async () => {
|
|
216
|
+
const created = await seedGame({ name: 'Orphaned' });
|
|
217
|
+
await db.drizzle.db
|
|
218
|
+
.update(gameProvider)
|
|
219
|
+
.set({ isActive: false })
|
|
220
|
+
.where(eq(gameProvider.id, created.providerId));
|
|
221
|
+
const walletCommands = makeWalletCommands({ ok: true, newBalance: '90', currency: 'USD' });
|
|
222
|
+
const launchGame = vi.fn();
|
|
223
|
+
const svc = makeService({
|
|
224
|
+
provider: mock({ launchGame, endRound: vi.fn() }),
|
|
225
|
+
walletCommands,
|
|
226
|
+
});
|
|
227
|
+
await expect(svc.startRound('00000000-0000-0000-0000-000000000312', created.id, 'USD', '10')).rejects.toBeInstanceOf(GameNotFoundError);
|
|
228
|
+
expect(walletCommands.debit).not.toHaveBeenCalled();
|
|
229
|
+
expect(launchGame).not.toHaveBeenCalled();
|
|
230
|
+
expect(await db.drizzle.db.select().from(gameRound)).toHaveLength(0);
|
|
231
|
+
});
|
|
104
232
|
it('debits the stake and persists the round on sufficient balance', async () => {
|
|
105
233
|
const created = await seedGame({ id: '00000000-0000-0000-0000-0000000000a1', name: 'Aces' });
|
|
106
234
|
const walletCommands = makeWalletCommands({ ok: true, newBalance: '90', currency: 'USD' });
|
|
@@ -141,6 +269,47 @@ describe('GamingService.startRound (real PG)', () => {
|
|
|
141
269
|
expect(await db.drizzle.db.select().from(gameRound)).toHaveLength(0);
|
|
142
270
|
});
|
|
143
271
|
});
|
|
272
|
+
describe('GamingService listGames provider gate (real PG)', () => {
|
|
273
|
+
it('separates the public playable gate from the admin game-active filter', async () => {
|
|
274
|
+
const live = await seedGame({ name: 'Live Game' });
|
|
275
|
+
const hidden = await seedGame({ name: 'Hidden Game' });
|
|
276
|
+
await db.drizzle.db
|
|
277
|
+
.update(gameProvider)
|
|
278
|
+
.set({ isActive: false })
|
|
279
|
+
.where(eq(gameProvider.id, hidden.providerId));
|
|
280
|
+
const svc = makeService();
|
|
281
|
+
const pub = await svc.listGamesPublic({ page: 1, limit: 10 });
|
|
282
|
+
expect(pub.items.map((g) => g.id)).toEqual([live.id]);
|
|
283
|
+
expect(pub.total).toBe(1);
|
|
284
|
+
const admin = await svc.listGamesAdmin({ page: 1, limit: 10, isActive: true });
|
|
285
|
+
expect(admin.total).toBe(2);
|
|
286
|
+
});
|
|
287
|
+
it('listGamesAdmin includes non-playable games and sorts by provider and game fields', async () => {
|
|
288
|
+
const alphaZulu = await seedProvider({ name: 'Alpha', slug: 'zulu' });
|
|
289
|
+
const alphaAlpha = await seedProvider({ name: 'Alpha', slug: 'alpha' });
|
|
290
|
+
const betaAlpha = await seedProvider({ name: 'Beta', slug: 'beta-alpha', isActive: false });
|
|
291
|
+
await seedGame({
|
|
292
|
+
id: '00000000-0000-4000-8000-000000000002',
|
|
293
|
+
name: 'Same',
|
|
294
|
+
providerId: alphaZulu.id,
|
|
295
|
+
});
|
|
296
|
+
await seedGame({
|
|
297
|
+
id: '00000000-0000-4000-8000-000000000001',
|
|
298
|
+
name: 'Same',
|
|
299
|
+
providerId: alphaZulu.id,
|
|
300
|
+
});
|
|
301
|
+
await seedGame({ name: 'Zulu', providerId: alphaAlpha.id });
|
|
302
|
+
await seedGame({ name: 'Aardvark', providerId: betaAlpha.id });
|
|
303
|
+
const result = await makeService().listGamesAdmin({ page: 1, limit: 10 });
|
|
304
|
+
expect(result.items.map((item) => [item.provider.name, item.provider.slug, item.name, item.id])).toEqual([
|
|
305
|
+
['Alpha', 'alpha', 'Zulu', expect.any(String)],
|
|
306
|
+
['Alpha', 'zulu', 'Same', '00000000-0000-4000-8000-000000000001'],
|
|
307
|
+
['Alpha', 'zulu', 'Same', '00000000-0000-4000-8000-000000000002'],
|
|
308
|
+
['Beta', 'beta-alpha', 'Aardvark', expect.any(String)],
|
|
309
|
+
]);
|
|
310
|
+
expect(result.total).toBe(4);
|
|
311
|
+
});
|
|
312
|
+
});
|
|
144
313
|
describe('GamingService.startRound bonus rollover completion (real PG)', () => {
|
|
145
314
|
it('emits wallet.bonus_rollover.completed once per credit the bet just completed', async () => {
|
|
146
315
|
const created = await seedGame({ id: '00000000-0000-0000-0000-0000000000a3', name: 'Aces' });
|
|
@@ -209,6 +378,98 @@ describe('GamingService.startRound bonus rollover completion (real PG)', () => {
|
|
|
209
378
|
expect(events.emit).not.toHaveBeenCalledWith('wallet.bonus_rollover.completed', expect.anything());
|
|
210
379
|
});
|
|
211
380
|
});
|
|
381
|
+
describe('GamingService updateGame (real PG)', () => {
|
|
382
|
+
const emittedTopics = (events) => events.emit.mock.calls.map(([topic]) => topic);
|
|
383
|
+
it('patches scalar fields and emits an event', async () => {
|
|
384
|
+
const created = await seedGame({ name: 'Roulette' });
|
|
385
|
+
const events = makeEventBus();
|
|
386
|
+
const svc = makeService({ events });
|
|
387
|
+
const updated = await svc.updateGame({
|
|
388
|
+
id: created.id,
|
|
389
|
+
name: 'Roulette Gold',
|
|
390
|
+
isActive: false,
|
|
391
|
+
...ACTOR,
|
|
392
|
+
});
|
|
393
|
+
expect(updated).toMatchObject({ name: 'Roulette Gold', isActive: false });
|
|
394
|
+
expect(emittedTopics(events)).toContain('gaming.game.updated');
|
|
395
|
+
});
|
|
396
|
+
it('replaces the category set, including clearing it with an empty array', async () => {
|
|
397
|
+
const table = await seedCategory({ slug: 'table-games', name: 'Table Games' });
|
|
398
|
+
const blackjack = await seedCategory({ slug: 'blackjack', name: 'Blackjack' });
|
|
399
|
+
const created = await seedGame({}, [table.id, blackjack.id]);
|
|
400
|
+
const svc = makeService();
|
|
401
|
+
const replaced = await svc.updateGame({
|
|
402
|
+
id: created.id,
|
|
403
|
+
categoryIds: [blackjack.id],
|
|
404
|
+
...ACTOR,
|
|
405
|
+
});
|
|
406
|
+
expect(replaced.categories.map((c) => c.slug)).toEqual(['blackjack']);
|
|
407
|
+
const cleared = await svc.updateGame({ id: created.id, categoryIds: [], ...ACTOR });
|
|
408
|
+
expect(cleared.categories).toEqual([]);
|
|
409
|
+
});
|
|
410
|
+
it('leaves links untouched when categoryIds is omitted', async () => {
|
|
411
|
+
const table = await seedCategory({ slug: 'table-games', name: 'Table Games' });
|
|
412
|
+
const created = await seedGame({}, [table.id]);
|
|
413
|
+
const svc = makeService();
|
|
414
|
+
const updated = await svc.updateGame({ id: created.id, name: 'Renamed', ...ACTOR });
|
|
415
|
+
expect(updated.categories.map((c) => c.slug)).toEqual(['table-games']);
|
|
416
|
+
});
|
|
417
|
+
it('reassigns the provider and validates all references', async () => {
|
|
418
|
+
const created = await seedGame();
|
|
419
|
+
const other = await seedProvider({ slug: 'other-studio', name: 'Other' });
|
|
420
|
+
const svc = makeService();
|
|
421
|
+
const updated = await svc.updateGame({
|
|
422
|
+
id: created.id,
|
|
423
|
+
providerId: other.id,
|
|
424
|
+
...ACTOR,
|
|
425
|
+
});
|
|
426
|
+
expect(updated.provider).toMatchObject({ slug: 'other-studio' });
|
|
427
|
+
await expect(svc.updateGame({
|
|
428
|
+
id: created.id,
|
|
429
|
+
providerId: '00000000-0000-4000-8000-000000000000',
|
|
430
|
+
...ACTOR,
|
|
431
|
+
})).rejects.toBeInstanceOf(GameProviderNotFoundError);
|
|
432
|
+
await expect(svc.updateGame({
|
|
433
|
+
id: created.id,
|
|
434
|
+
categoryIds: ['00000000-0000-4000-8000-000000000000'],
|
|
435
|
+
...ACTOR,
|
|
436
|
+
})).rejects.toBeInstanceOf(GameCategoryNotFoundError);
|
|
437
|
+
await expect(svc.updateGame({
|
|
438
|
+
id: '00000000-0000-4000-8000-000000000000',
|
|
439
|
+
name: 'X',
|
|
440
|
+
...ACTOR,
|
|
441
|
+
})).rejects.toBeInstanceOf(GameNotFoundError);
|
|
442
|
+
});
|
|
443
|
+
it('rejects an aggregator the target provider is not mapped on', async () => {
|
|
444
|
+
const created = await seedGame();
|
|
445
|
+
const unmapped = await seedProvider({ slug: 'unmapped-studio', name: 'Unmapped' });
|
|
446
|
+
await db.drizzle.db
|
|
447
|
+
.delete(gameProviderAggregatorMapping)
|
|
448
|
+
.where(eq(gameProviderAggregatorMapping.providerId, unmapped.id));
|
|
449
|
+
const svc = makeService();
|
|
450
|
+
await expect(svc.updateGame({ id: created.id, providerId: unmapped.id, ...ACTOR })).rejects.toBeInstanceOf(GameAggregatorNotMappedError);
|
|
451
|
+
await expect(svc.updateGame({ id: created.id, aggregator: 'everymatrix', ...ACTOR })).rejects.toBeInstanceOf(GameAggregatorNotMappedError);
|
|
452
|
+
await db.drizzle.db
|
|
453
|
+
.insert(gameProviderAggregatorMapping)
|
|
454
|
+
.values({ providerId: unmapped.id, aggregator: 'everymatrix', vendorId: 'vendor-unmapped' });
|
|
455
|
+
const moved = await svc.updateGame({
|
|
456
|
+
id: created.id,
|
|
457
|
+
providerId: unmapped.id,
|
|
458
|
+
aggregator: 'everymatrix',
|
|
459
|
+
...ACTOR,
|
|
460
|
+
});
|
|
461
|
+
expect(moved).toMatchObject({
|
|
462
|
+
provider: { slug: 'unmapped-studio' },
|
|
463
|
+
aggregator: 'everymatrix',
|
|
464
|
+
});
|
|
465
|
+
});
|
|
466
|
+
it('rejects a taken game slug', async () => {
|
|
467
|
+
const created = await seedGame({ slug: 'game-one' });
|
|
468
|
+
await seedGame({ slug: 'game-two' });
|
|
469
|
+
const svc = makeService();
|
|
470
|
+
await expect(svc.updateGame({ id: created.id, slug: 'game-two', ...ACTOR })).rejects.toBeInstanceOf(GameSlugTakenError);
|
|
471
|
+
});
|
|
472
|
+
});
|
|
212
473
|
async function seedRound(gameId, userId) {
|
|
213
474
|
const [row] = await db.drizzle.db
|
|
214
475
|
.insert(gameRound)
|