@moneypot/hub 1.15.0 → 1.16.0-dev.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.
Files changed (39) hide show
  1. package/dist/src/__generated__/gql.d.ts +2 -2
  2. package/dist/src/__generated__/gql.js +1 -1
  3. package/dist/src/__generated__/graphql.d.ts +240 -27
  4. package/dist/src/__generated__/graphql.js +30 -1
  5. package/dist/src/db/index.d.ts +1 -0
  6. package/dist/src/db/index.js +10 -2
  7. package/dist/src/db/public.d.ts +6 -10
  8. package/dist/src/db/public.js +24 -36
  9. package/dist/src/db/types.d.ts +24 -0
  10. package/dist/src/express.d.ts +1 -0
  11. package/dist/src/graphql-queries.js +4 -0
  12. package/dist/src/index.d.ts +2 -1
  13. package/dist/src/index.js +2 -1
  14. package/dist/src/pg-advisory-lock.d.ts +5 -0
  15. package/dist/src/pg-advisory-lock.js +5 -0
  16. package/dist/src/pg-versions/013-chat.sql +221 -0
  17. package/dist/src/plugins/chat/hub-chat-after-id-condition.d.ts +1 -0
  18. package/dist/src/plugins/chat/hub-chat-after-id-condition.js +15 -0
  19. package/dist/src/plugins/chat/hub-chat-create-system-message.d.ts +1 -0
  20. package/dist/src/plugins/chat/hub-chat-create-system-message.js +124 -0
  21. package/dist/src/plugins/chat/hub-chat-create-user-message.d.ts +1 -0
  22. package/dist/src/plugins/chat/hub-chat-create-user-message.js +231 -0
  23. package/dist/src/plugins/chat/hub-chat-mute-user.d.ts +1 -0
  24. package/dist/src/plugins/chat/hub-chat-mute-user.js +186 -0
  25. package/dist/src/plugins/chat/hub-chat-subscription.d.ts +14 -0
  26. package/dist/src/plugins/chat/hub-chat-subscription.js +133 -0
  27. package/dist/src/plugins/chat/hub-chat-unmute-user.d.ts +1 -0
  28. package/dist/src/plugins/chat/hub-chat-unmute-user.js +146 -0
  29. package/dist/src/plugins/hub-authenticate.js +38 -17
  30. package/dist/src/plugins/hub-create-playground-session.js +44 -13
  31. package/dist/src/plugins/hub-make-outcome-bet.js +39 -33
  32. package/dist/src/server/graphile.config.d.ts +13 -1
  33. package/dist/src/server/graphile.config.js +38 -12
  34. package/dist/src/server/index.d.ts +3 -1
  35. package/dist/src/server/index.js +3 -1
  36. package/dist/src/server/middleware/authentication.js +1 -0
  37. package/dist/src/util.d.ts +3 -0
  38. package/dist/src/util.js +9 -0
  39. package/package.json +1 -1
@@ -0,0 +1,146 @@
1
+ import { extendSchema, gql } from "postgraphile/utils";
2
+ import { context, inhibitOnNull, sideEffect } from "../../grafast.js";
3
+ import { GraphQLError } from "graphql";
4
+ import z, { object } from "zod/v4";
5
+ import { extractFirstZodErrorMessage } from "../../util.js";
6
+ import { maybeOneRow, withPgPoolTransaction, } from "../../db/index.js";
7
+ import { PgAdvisoryLock } from "../../pg-advisory-lock.js";
8
+ import { logger } from "../../logger.js";
9
+ const InputSchema = z.object({
10
+ userId: z.uuid("Invalid user ID"),
11
+ });
12
+ export const HubChatUnmuteUserPlugin = extendSchema((build) => {
13
+ const chatMuteTable = build.input.pgRegistry.pgResources.hub_chat_mute;
14
+ return {
15
+ typeDefs: gql `
16
+ input HubChatUnmuteUserInput {
17
+ userId: UUID!
18
+ }
19
+
20
+ type HubChatUnmuteUserPayload {
21
+ chatMute: HubChatMute!
22
+ }
23
+
24
+ extend type Mutation {
25
+ hubChatUnmuteUser(
26
+ input: HubChatUnmuteUserInput!
27
+ ): HubChatUnmuteUserPayload
28
+ }
29
+ `,
30
+ objects: {
31
+ Mutation: {
32
+ plans: {
33
+ hubChatUnmuteUser(_, { $input }) {
34
+ const $identity = context().get("identity");
35
+ const $superuserPool = context().get("superuserPool");
36
+ const $muteId = sideEffect([$input, $identity, $superuserPool], async ([rawInput, identity, superuserPool]) => {
37
+ if (identity?.kind !== "user") {
38
+ throw new GraphQLError("Unauthorized");
39
+ }
40
+ let input;
41
+ try {
42
+ input = InputSchema.parse(rawInput);
43
+ }
44
+ catch (e) {
45
+ if (e instanceof z.ZodError) {
46
+ throw new GraphQLError(extractFirstZodErrorMessage(e));
47
+ }
48
+ throw e;
49
+ }
50
+ const currentUserIsChatMod = await superuserPool
51
+ .query({
52
+ text: `
53
+ SELECT id, user_id
54
+ FROM hub.chat_mod
55
+ WHERE casino_id = $1 AND experience_id = $2 AND user_id = $3
56
+ `,
57
+ values: [
58
+ identity.session.casino_id,
59
+ identity.session.experience_id,
60
+ identity.session.user_id,
61
+ ],
62
+ })
63
+ .then(maybeOneRow);
64
+ if (!identity.session.is_experience_owner &&
65
+ !currentUserIsChatMod) {
66
+ throw new GraphQLError("Unauthorized");
67
+ }
68
+ const dbTargetUser = await superuserPool
69
+ .query({
70
+ text: `
71
+ SELECT id
72
+ FROM hub.user
73
+ WHERE casino_id = $1 AND id = $2
74
+ `,
75
+ values: [identity.session.casino_id, input.userId],
76
+ })
77
+ .then(maybeOneRow);
78
+ if (!dbTargetUser) {
79
+ throw new GraphQLError("User not found");
80
+ }
81
+ return withPgPoolTransaction(superuserPool, async (pgClient) => {
82
+ await PgAdvisoryLock.forChatUserAction(pgClient, {
83
+ userId: dbTargetUser.id,
84
+ experienceId: identity.session.experience_id,
85
+ casinoId: identity.session.casino_id,
86
+ });
87
+ const dbActiveMute = await pgClient
88
+ .query({
89
+ text: `
90
+ SELECT id
91
+ FROM hub.active_chat_mute
92
+ WHERE user_id = $1 AND experience_id = $2 AND casino_id = $3
93
+ `,
94
+ values: [
95
+ dbTargetUser.id,
96
+ identity.session.experience_id,
97
+ identity.session.casino_id,
98
+ ],
99
+ })
100
+ .then(maybeOneRow);
101
+ if (!dbActiveMute) {
102
+ throw new GraphQLError("User is not muted");
103
+ }
104
+ await pgClient
105
+ .query({
106
+ text: `
107
+ UPDATE hub.chat_mute
108
+ SET revoked_at = now()
109
+ WHERE user_id = $1
110
+ AND experience_id = $2
111
+ AND casino_id = $3
112
+ AND revoked_at IS NULL
113
+ `,
114
+ values: [
115
+ dbTargetUser.id,
116
+ identity.session.experience_id,
117
+ identity.session.casino_id,
118
+ ],
119
+ })
120
+ .then((res) => {
121
+ if (res.rowCount !== 1) {
122
+ logger.warn("Expected 1 chat_mute row to be revoked when unmuting user, got %s", res.rowCount);
123
+ }
124
+ });
125
+ const notifyPayload = {
126
+ type: "unmute",
127
+ user_id: dbTargetUser.id,
128
+ };
129
+ await pgClient.query({
130
+ text: `
131
+ SELECT pg_notify('hub:chat:${identity.session.experience_id}', $1::text)
132
+ `,
133
+ values: [JSON.stringify(notifyPayload)],
134
+ });
135
+ return dbActiveMute.id;
136
+ });
137
+ });
138
+ return object({
139
+ chatMute: chatMuteTable.get({ id: inhibitOnNull($muteId) }),
140
+ });
141
+ },
142
+ },
143
+ },
144
+ },
145
+ };
146
+ });
@@ -1,5 +1,5 @@
1
1
  import { GraphQLError } from "graphql";
2
- import { gql, makeExtendSchemaPlugin } from "postgraphile/utils";
2
+ import { extendSchema, gql } from "postgraphile/utils";
3
3
  import { assert } from "tsafe";
4
4
  import { GET_USER_FROM_USER_TOKEN } from "../graphql-queries.js";
5
5
  import { exactlyOneRow, maybeOneRow } from "../db/util.js";
@@ -22,7 +22,7 @@ const InputSchema = z.object({
22
22
  casinoBaseUrl: BaseUrlSchema,
23
23
  userToken: z.string().min(1, "User token required"),
24
24
  });
25
- export const HubAuthenticatePlugin = makeExtendSchemaPlugin(() => {
25
+ export const HubAuthenticatePlugin = extendSchema(() => {
26
26
  return {
27
27
  typeDefs: gql `
28
28
  input HubAuthenticateInput {
@@ -124,34 +124,52 @@ export const HubAuthenticatePlugin = makeExtendSchemaPlugin(() => {
124
124
  assert(mpUserId);
125
125
  const uname = result.user.uname;
126
126
  assert(uname);
127
- const dbUser = await pgClient
127
+ const mpExperience = result.experience;
128
+ assert(mpExperience);
129
+ assert(mpExperience.userByUserId, "Expected mpExperience.userByUserId");
130
+ const authUser = await pgClient
128
131
  .query({
129
132
  text: `
130
- INSERT INTO hub.user(casino_id, mp_user_id, uname)
131
- VALUES($1, $2, $3)
132
- ON CONFLICT (casino_id, mp_user_id) DO UPDATE
133
- SET uname = EXCLUDED.uname
134
- RETURNING id, uname
135
- `,
133
+ INSERT INTO hub.user(casino_id, mp_user_id, uname)
134
+ VALUES ($1, $2, $3)
135
+ ON CONFLICT (casino_id, mp_user_id) DO UPDATE
136
+ SET uname = EXCLUDED.uname
137
+ RETURNING id, uname
138
+ `,
136
139
  values: [casino.id, mpUserId, uname],
137
140
  })
138
141
  .then(exactlyOneRow);
139
- const userId = dbUser.id;
140
- const mpExperience = result.experience;
141
- assert(mpExperience);
142
+ const ownerUser = await pgClient
143
+ .query({
144
+ text: `
145
+ INSERT INTO hub.user(casino_id, mp_user_id, uname)
146
+ VALUES ($1, $2, $3)
147
+ ON CONFLICT (casino_id, mp_user_id) DO UPDATE
148
+ SET uname = EXCLUDED.uname
149
+ RETURNING id
150
+ `,
151
+ values: [
152
+ casino.id,
153
+ mpExperience.userByUserId.id,
154
+ mpExperience.userByUserId.uname,
155
+ ],
156
+ })
157
+ .then(exactlyOneRow);
158
+ const userId = authUser.id;
142
159
  const dbExperience = await pgClient
143
160
  .query({
144
161
  text: `
145
- INSERT INTO hub.experience(casino_id, mp_experience_id, name)
146
- VALUES($1, $2, $3)
162
+ INSERT INTO hub.experience(casino_id, mp_experience_id, name, user_id)
163
+ VALUES($1, $2, $3, $4)
147
164
  ON CONFLICT (casino_id, mp_experience_id) DO UPDATE
148
165
  SET name = EXCLUDED.name
149
- RETURNING id
166
+ RETURNING id, user_id
150
167
  `,
151
168
  values: [
152
169
  casino.id,
153
170
  mpExperience.id,
154
171
  mpExperience.name,
172
+ ownerUser.id,
155
173
  ],
156
174
  })
157
175
  .then(exactlyOneRow);
@@ -172,7 +190,7 @@ export const HubAuthenticatePlugin = makeExtendSchemaPlugin(() => {
172
190
  .then(exactlyOneRow);
173
191
  const ret = {
174
192
  userId,
175
- uname: dbUser.uname,
193
+ uname: authUser.uname,
176
194
  experienceId: dbExperience.id,
177
195
  sessionKey: dbSession.key,
178
196
  };
@@ -185,14 +203,17 @@ export const HubAuthenticatePlugin = makeExtendSchemaPlugin(() => {
185
203
  experience_id: dbExperience.id,
186
204
  session_id: dbSession.id,
187
205
  is_playground: false,
206
+ is_experience_owner: dbExperience.user_id === userId,
188
207
  },
189
208
  };
190
- context.pgSettings = {
209
+ const pgSettings = {
191
210
  "session.user_id": userId,
192
211
  "session.casino_id": casino.id,
193
212
  "session.experience_id": dbExperience.id,
194
213
  "session.session_id": dbSession.id,
214
+ "session.is_experience_owner": dbExperience.user_id === userId ? "1" : undefined,
195
215
  };
216
+ context.pgSettings = pgSettings;
196
217
  return ret;
197
218
  });
198
219
  });
@@ -4,16 +4,18 @@ import { exactlyOneRow, maybeOneRow } from "../db/util.js";
4
4
  import { constant, context, object, sideEffect } from "postgraphile/grafast";
5
5
  import { withPgPoolTransaction, } from "../db/index.js";
6
6
  import { logger } from "../logger.js";
7
- import { z } from "zod";
7
+ import { z } from "zod/v4";
8
8
  import { prettifyError } from "zod/v4";
9
9
  const InputSchema = z.object({
10
- dummy: z.string().optional(),
10
+ experienceClientId: z.uuid().optional(),
11
+ userClientId: z.uuid().optional(),
11
12
  });
12
13
  export const HubCreatePlaygroundSessionPlugin = extendSchema(() => {
13
14
  return {
14
15
  typeDefs: gql `
15
16
  input HubCreatePlaygroundSessionInput {
16
- dummy: String
17
+ experienceClientId: UUID
18
+ userClientId: UUID
17
19
  }
18
20
 
19
21
  extend type Mutation {
@@ -31,9 +33,9 @@ export const HubCreatePlaygroundSessionPlugin = extendSchema(() => {
31
33
  const $superuserPool = $context.get("superuserPool");
32
34
  const $success = sideEffect([$input, $superuserPool, $context], ([rawInput, superuserPool, context]) => {
33
35
  return withPgPoolTransaction(superuserPool, async (pgClient) => {
34
- let _input;
36
+ let input;
35
37
  try {
36
- _input = InputSchema.parse(rawInput);
38
+ input = InputSchema.parse(rawInput);
37
39
  }
38
40
  catch (e) {
39
41
  if (e instanceof z.ZodError) {
@@ -47,6 +49,7 @@ export const HubCreatePlaygroundSessionPlugin = extendSchema(() => {
47
49
  SELECT c.*
48
50
  FROM hub.casino c
49
51
  WHERE c.is_playground = true
52
+ ORDER BY c.id ASC
50
53
  LIMIT 1
51
54
  `,
52
55
  values: [],
@@ -60,28 +63,51 @@ export const HubCreatePlaygroundSessionPlugin = extendSchema(() => {
60
63
  const dbUser = await pgClient
61
64
  .query({
62
65
  text: `
63
- INSERT INTO hub.user(casino_id, mp_user_id, uname)
64
- VALUES($1, $2, $3)
65
- RETURNING id, uname, mp_user_id
66
+ with ins as (
67
+ insert into hub.user (casino_id, mp_user_id, uname, client_id)
68
+ values ($1, $2, $3, $4)
69
+ on conflict (casino_id, client_id) where client_id is not null
70
+ do nothing
71
+ returning id, uname, mp_user_id
72
+ )
73
+ select id, uname, mp_user_id from ins
74
+ union all
75
+ select id, uname, mp_user_id
76
+ from hub.user
77
+ where casino_id = $1 and client_id = $4
78
+ limit 1
66
79
  `,
67
80
  values: [
68
81
  dbPlaygroundCasino.id,
69
82
  DUMMY_MP_ID,
70
83
  randomUname,
84
+ input.userClientId ?? null,
71
85
  ],
72
86
  })
73
87
  .then(exactlyOneRow);
74
88
  const dbExperience = await pgClient
75
89
  .query({
76
90
  text: `
77
- INSERT INTO hub.experience(casino_id, mp_experience_id, name)
78
- VALUES($1, $2, $3)
79
- RETURNING id
91
+ with ins as (
92
+ insert into hub.experience (casino_id, mp_experience_id, name, client_id, user_id)
93
+ values ($1, $2, $3, $4, $5)
94
+ on conflict (casino_id, client_id) where client_id is not null
95
+ do nothing
96
+ returning id, user_id
97
+ )
98
+ select id, user_id from ins
99
+ union all
100
+ select id, user_id
101
+ from hub.experience
102
+ where casino_id = $1 and client_id = $4
103
+ limit 1
80
104
  `,
81
105
  values: [
82
106
  dbPlaygroundCasino.id,
83
107
  DUMMY_MP_ID,
84
108
  `Playground Experience ${randomUname}`,
109
+ input.experienceClientId ?? null,
110
+ dbUser.id,
85
111
  ],
86
112
  })
87
113
  .then(exactlyOneRow);
@@ -89,6 +115,8 @@ export const HubCreatePlaygroundSessionPlugin = extendSchema(() => {
89
115
  text: `
90
116
  INSERT INTO hub.balance(user_id, experience_id, casino_id, currency_key, amount)
91
117
  VALUES($1, $2, $3, $4, 1000)
118
+ ON CONFLICT (user_id, experience_id, casino_id, currency_key) DO UPDATE
119
+ SET amount = 1000
92
120
  `,
93
121
  values: [
94
122
  dbUser.id,
@@ -101,7 +129,7 @@ export const HubCreatePlaygroundSessionPlugin = extendSchema(() => {
101
129
  .query({
102
130
  text: `
103
131
  INSERT INTO hub.session(casino_id, user_id, experience_id, user_token, expired_at)
104
- VALUES($1, $2, $3, $4, now() + interval '1 hour')
132
+ VALUES($1, $2, $3, $4, now() + interval '1 week')
105
133
  RETURNING id, key
106
134
  `,
107
135
  values: [
@@ -127,14 +155,17 @@ export const HubCreatePlaygroundSessionPlugin = extendSchema(() => {
127
155
  experience_id: dbExperience.id,
128
156
  session_id: dbSession.id,
129
157
  is_playground: true,
158
+ is_experience_owner: dbExperience.user_id === dbUser.id,
130
159
  },
131
160
  };
132
- context.pgSettings = {
161
+ const pgSettings = {
133
162
  "session.user_id": dbUser.id,
134
163
  "session.casino_id": dbPlaygroundCasino.id,
135
164
  "session.experience_id": dbExperience.id,
136
165
  "session.session_id": dbSession.id,
166
+ "session.is_experience_owner": dbExperience.user_id === dbUser.id ? "1" : undefined,
137
167
  };
168
+ context.pgSettings = pgSettings;
138
169
  return ret;
139
170
  });
140
171
  });
@@ -1,8 +1,8 @@
1
1
  import { access, context, object, ObjectStep, sideEffect, } from "postgraphile/grafast";
2
- import { gql, makeExtendSchemaPlugin } from "postgraphile/utils";
2
+ import { gql, extendSchema } from "postgraphile/utils";
3
3
  import * as z from "zod";
4
4
  import { GraphQLError } from "graphql";
5
- import { DbHashKind, dbLockPlayerBalanceAndHouseBankroll, exactlyOneRow, maybeOneRow, withPgPoolTransaction, } from "../db/index.js";
5
+ import { DbHashKind, dbLockHouseBankroll, dbLockPlayerBalance, exactlyOneRow, maybeOneRow, withPgPoolTransaction, } from "../db/index.js";
6
6
  import { assert } from "tsafe";
7
7
  import { dbInsertHubHash, dbLockHubHashChain, } from "../hash-chain/db-hash-chain.js";
8
8
  import { getIntermediateHash } from "../hash-chain/get-hash.js";
@@ -71,7 +71,7 @@ const BetConfigsSchema = z.record(BetKindSchema, z.object({
71
71
  export function MakeOutcomeBetPlugin({ betConfigs }) {
72
72
  BetConfigsSchema.parse(betConfigs);
73
73
  const betKinds = Object.keys(betConfigs);
74
- return makeExtendSchemaPlugin((build) => {
74
+ return extendSchema((build) => {
75
75
  const outcomeBetTable = build.input.pgRegistry.pgResources.hub_outcome_bet;
76
76
  const typeDefs = gql `
77
77
  enum BetKind {
@@ -171,14 +171,14 @@ export function MakeOutcomeBetPlugin({ betConfigs }) {
171
171
  throw new GraphQLError("Currency not found");
172
172
  }
173
173
  return withPgPoolTransaction(superuserPool, async (pgClient) => {
174
- const { dbPlayerBalance, dbHouseBankroll, found } = await dbLockPlayerBalanceAndHouseBankroll(pgClient, {
174
+ const dbPlayerBalance = await dbLockPlayerBalance(pgClient, {
175
175
  userId: session.user_id,
176
176
  casinoId: session.casino_id,
177
177
  experienceId: session.experience_id,
178
178
  currencyKey: dbCurrency.key,
179
179
  });
180
- if (!found) {
181
- throw new GraphQLError("No balance entry found for player or house");
180
+ if (!dbPlayerBalance) {
181
+ throw new GraphQLError("No balance entry found for player");
182
182
  }
183
183
  const minProfit = Math.min(...input.outcomes.map((o) => o.profit));
184
184
  const maxPlayerLoss = Math.abs(input.wager * minProfit);
@@ -194,21 +194,6 @@ export function MakeOutcomeBetPlugin({ betConfigs }) {
194
194
  }
195
195
  throw new GraphQLError("You cannot afford the worst outcome");
196
196
  }
197
- const maxProfitMultiplier = Math.max(...input.outcomes.map((o) => o.profit));
198
- const maxPotentialPayout = input.wager * maxProfitMultiplier;
199
- const riskResult = validateRisk({
200
- currency: input.currency,
201
- wager: input.wager,
202
- bankroll: dbHouseBankroll.amount,
203
- maxPotentialPayout,
204
- riskPolicy: betConfig.riskPolicy,
205
- displayUnitName: dbCurrency.display_unit_name,
206
- displayUnitScale: dbCurrency.display_unit_scale,
207
- outcomes: input.outcomes,
208
- });
209
- if (!riskResult.ok) {
210
- throw new GraphQLError(riskResult.error);
211
- }
212
197
  const dbHashChain = await dbLockHubHashChain(pgClient, {
213
198
  userId: session.user_id,
214
199
  experienceId: session.experience_id,
@@ -289,26 +274,47 @@ export function MakeOutcomeBetPlugin({ betConfigs }) {
289
274
  const outcome = input.outcomes[outcomeIdx];
290
275
  const netPlayerAmount = input.wager * outcome.profit;
291
276
  const houseBankrollDelta = -netPlayerAmount;
292
- await pgClient.query({
293
- text: `
294
- UPDATE hub.balance
295
- SET amount = amount + $1
296
- WHERE id = $2
297
- `,
298
- values: [netPlayerAmount, dbPlayerBalance.id],
277
+ const dbHouseBankroll = await dbLockHouseBankroll(pgClient, {
278
+ casinoId: session.casino_id,
279
+ currencyKey: dbCurrency.key,
299
280
  });
281
+ if (!dbHouseBankroll) {
282
+ throw new GraphQLError("No house bankroll found");
283
+ }
284
+ const maxProfitMultiplier = Math.max(...input.outcomes.map((o) => o.profit));
285
+ const maxPotentialPayout = input.wager * maxProfitMultiplier;
286
+ const riskResult = validateRisk({
287
+ currency: input.currency,
288
+ wager: input.wager,
289
+ bankroll: dbHouseBankroll.amount,
290
+ maxPotentialPayout,
291
+ riskPolicy: betConfig.riskPolicy,
292
+ displayUnitName: dbCurrency.display_unit_name,
293
+ displayUnitScale: dbCurrency.display_unit_scale,
294
+ outcomes: input.outcomes,
295
+ });
296
+ if (!riskResult.ok) {
297
+ throw new GraphQLError(riskResult.error);
298
+ }
300
299
  await pgClient.query({
301
300
  text: `
301
+ WITH balance_update AS (
302
+ UPDATE hub.balance
303
+ SET amount = amount + $1
304
+ WHERE id = $2
305
+ )
302
306
  UPDATE hub.bankroll
303
- SET amount = amount + $2,
304
- bets = bets + 1,
305
- wagered = wagered + $3
306
- WHERE id = $1
307
+ SET amount = amount + $3,
308
+ wagered = wagered + $4,
309
+ bets = bets + 1
310
+ WHERE id = $5
307
311
  `,
308
312
  values: [
309
- dbHouseBankroll.id,
313
+ netPlayerAmount,
314
+ dbPlayerBalance.id,
310
315
  houseBankrollDelta,
311
316
  input.wager,
317
+ dbHouseBankroll.id,
312
318
  ],
313
319
  });
314
320
  const immutableData = structuredClone({
@@ -8,6 +8,7 @@ export type UserSessionContext = {
8
8
  experience_id: string;
9
9
  session_id: string;
10
10
  is_playground: boolean;
11
+ is_experience_owner: boolean;
11
12
  };
12
13
  export type PluginIdentity = {
13
14
  kind: "user";
@@ -15,12 +16,23 @@ export type PluginIdentity = {
15
16
  } | {
16
17
  kind: "operator";
17
18
  };
19
+ export type OurPgSettings = {
20
+ "session.user_id": string;
21
+ "session.experience_id": string;
22
+ "session.casino_id": string;
23
+ "session.session_id": string;
24
+ "session.is_experience_owner": "1" | undefined;
25
+ } | {
26
+ "operator.api_key": string;
27
+ };
18
28
  export declare const requiredPlugins: readonly GraphileConfig.Plugin[];
19
29
  export declare const defaultPlugins: readonly GraphileConfig.Plugin[];
20
- export declare function createPreset({ plugins, exportSchemaSDLPath, extraPgSchemas, abortSignal, context, }: {
30
+ export declare function createPreset({ plugins, exportSchemaSDLPath, extraPgSchemas, abortSignal, context, enableChat, enablePlayground, }: {
21
31
  plugins: readonly GraphileConfig.Plugin[];
22
32
  exportSchemaSDLPath?: string;
23
33
  extraPgSchemas: string[];
24
34
  abortSignal: AbortSignal;
25
35
  context: ServerContext;
36
+ enableChat: boolean;
37
+ enablePlayground: boolean;
26
38
  }): GraphileConfig.Preset;
@@ -25,6 +25,13 @@ import { HubOutcomeInputNonNullFieldsPlugin } from "../plugins/hub-outcome-input
25
25
  import { HubPutAlertPlugin } from "../plugins/hub-put-alert.js";
26
26
  import { HubRevealHashChainPlugin } from "../hash-chain/plugins/hub-reveal-hash-chain.js";
27
27
  import { HubPreimageHashFieldPlugin } from "../hash-chain/plugins/hub-preimage-hash-field.js";
28
+ import { HubChatCreateUserMessagePlugin } from "../plugins/chat/hub-chat-create-user-message.js";
29
+ import { HubChatSubscriptionPlugin } from "../plugins/chat/hub-chat-subscription.js";
30
+ import { HubCreatePlaygroundSessionPlugin } from "../plugins/hub-create-playground-session.js";
31
+ import { HubChatUnmuteUserPlugin } from "../plugins/chat/hub-chat-unmute-user.js";
32
+ import { HubChatMuteUserPlugin } from "../plugins/chat/hub-chat-mute-user.js";
33
+ import { HubChatCreateSystemMessagePlugin } from "../plugins/chat/hub-chat-create-system-message.js";
34
+ import { HubChatAfterIdConditionPlugin } from "../plugins/chat/hub-chat-after-id-condition.js";
28
35
  export const requiredPlugins = [
29
36
  SmartTagsPlugin,
30
37
  IdToNodeIdPlugin,
@@ -48,7 +55,7 @@ export const defaultPlugins = [
48
55
  HubPreimageHashFieldPlugin,
49
56
  customPgOmitArchivedPlugin("deleted"),
50
57
  ];
51
- export function createPreset({ plugins, exportSchemaSDLPath, extraPgSchemas, abortSignal, context, }) {
58
+ export function createPreset({ plugins, exportSchemaSDLPath, extraPgSchemas, abortSignal, context, enableChat, enablePlayground, }) {
52
59
  if (exportSchemaSDLPath) {
53
60
  if (!exportSchemaSDLPath.startsWith("/")) {
54
61
  throw new Error("exportSchemaSDLPath must be an absolute path");
@@ -65,6 +72,12 @@ export function createPreset({ plugins, exportSchemaSDLPath, extraPgSchemas, abo
65
72
  mutablePlugins.unshift(requiredPlugin);
66
73
  }
67
74
  }
75
+ if (enablePlayground) {
76
+ mutablePlugins.push(HubCreatePlaygroundSessionPlugin);
77
+ }
78
+ if (enableChat) {
79
+ mutablePlugins.push(HubChatCreateUserMessagePlugin, HubChatCreateSystemMessagePlugin, HubChatSubscriptionPlugin, HubChatMuteUserPlugin, HubChatUnmuteUserPlugin, HubChatAfterIdConditionPlugin);
80
+ }
68
81
  const preset = {
69
82
  extends: [PostGraphileAmberPreset],
70
83
  disablePlugins: ["NodePlugin"],
@@ -116,19 +129,29 @@ export function createPreset({ plugins, exportSchemaSDLPath, extraPgSchemas, abo
116
129
  experience_id: reqIdentity.user.experience_id,
117
130
  session_id: reqIdentity.sessionId,
118
131
  is_playground: reqIdentity.isPlayground,
132
+ is_experience_owner: reqIdentity.isExperienceOwner,
119
133
  },
120
134
  };
121
135
  }
122
136
  const pgSettings = {};
137
+ let ourPgSettings;
123
138
  if (reqIdentity?.kind === "user") {
124
- pgSettings["session.user_id"] = reqIdentity.user.id;
125
- pgSettings["session.experience_id"] = reqIdentity.user.experience_id;
126
- pgSettings["session.casino_id"] = reqIdentity.user.casino_id;
127
- pgSettings["session.session_id"] = reqIdentity.sessionId;
139
+ ourPgSettings = {
140
+ "session.user_id": reqIdentity.user.id,
141
+ "session.experience_id": reqIdentity.user.experience_id,
142
+ "session.casino_id": reqIdentity.user.casino_id,
143
+ "session.session_id": reqIdentity.sessionId,
144
+ "session.is_experience_owner": reqIdentity.isExperienceOwner
145
+ ? "1"
146
+ : undefined,
147
+ };
128
148
  }
129
149
  else if (reqIdentity?.kind === "operator") {
130
- pgSettings["operator.api_key"] = reqIdentity.apiKey;
150
+ ourPgSettings = {
151
+ "operator.api_key": reqIdentity.apiKey,
152
+ };
131
153
  }
154
+ Object.assign(pgSettings, ourPgSettings);
132
155
  return {
133
156
  pgSettings,
134
157
  identity: pluginIdentity,
@@ -165,14 +188,17 @@ async function handleWebsocketContext(context, ws) {
165
188
  experience_id: result.user.experience_id,
166
189
  session_id: result.sessionId,
167
190
  is_playground: result.isPlayground,
191
+ is_experience_owner: result.isExperienceOwner,
192
+ };
193
+ const pgSettings = {
194
+ "session.user_id": result.user.id,
195
+ "session.experience_id": result.user.experience_id,
196
+ "session.casino_id": result.user.casino_id,
197
+ "session.session_id": result.sessionId,
198
+ "session.is_experience_owner": result.isExperienceOwner ? "1" : undefined,
168
199
  };
169
200
  return {
170
- pgSettings: {
171
- "session.user_id": result.user.id,
172
- "session.experience_id": result.user.experience_id,
173
- "session.casino_id": result.user.casino_id,
174
- "session.session_id": result.sessionId,
175
- },
201
+ pgSettings,
176
202
  identity: {
177
203
  kind: "user",
178
204
  session,
@@ -4,7 +4,9 @@ export type HubServer = {
4
4
  listen: () => Promise<void>;
5
5
  shutdown: () => Promise<void>;
6
6
  };
7
- export declare function createHubServer({ configureApp, plugins, exportSchemaSDLPath, extraPgSchemas, abortSignal, context, }: Pick<ServerOptions, "plugins" | "exportSchemaSDLPath" | "extraPgSchemas" | "configureApp"> & {
7
+ export declare function createHubServer({ configureApp, plugins, exportSchemaSDLPath, extraPgSchemas, abortSignal, context, enableChat, enablePlayground, }: Pick<ServerOptions, "plugins" | "exportSchemaSDLPath" | "extraPgSchemas" | "configureApp"> & {
8
8
  abortSignal: AbortSignal;
9
9
  context: ServerContext;
10
+ enableChat: boolean;
11
+ enablePlayground: boolean;
10
12
  }): HubServer;