@voltro/plugin-leaderboards 0.0.0-stage → 0.88.0

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 (67) hide show
  1. package/CHANGELOG.md +24492 -0
  2. package/LICENSE +61 -0
  3. package/README.md +1087 -2
  4. package/SECURITY.md +56 -0
  5. package/THIRD-PARTY-NOTICES.md +5603 -0
  6. package/dist/administration.js +4 -0
  7. package/dist/bracketAdmission.js +293 -0
  8. package/dist/bracketAdmissionPolicy.js +21 -0
  9. package/dist/bracketInstallation.js +132 -0
  10. package/dist/bracketMatchPorts.js +4 -0
  11. package/dist/bracketMatches.js +545 -0
  12. package/dist/brackets.d.ts +149 -0
  13. package/dist/brackets.js +378 -0
  14. package/dist/bucketStore.js +92 -0
  15. package/dist/buckets.js +8 -0
  16. package/dist/errors.d.ts +13 -0
  17. package/dist/errors.js +16 -0
  18. package/dist/glicko2.js +71 -0
  19. package/dist/index.d.ts +1208 -0
  20. package/dist/index.js +15 -0
  21. package/dist/inspect.js +83 -0
  22. package/dist/json.js +38 -0
  23. package/dist/leaderboard.d.ts +49 -0
  24. package/dist/leaderboard.js +56 -0
  25. package/dist/leagueSchedule.js +39 -0
  26. package/dist/leagues.js +30 -0
  27. package/dist/openskill.js +73 -0
  28. package/dist/plugin.js +337 -0
  29. package/dist/portLifetime.js +66 -0
  30. package/dist/ports.d.ts +294 -0
  31. package/dist/ports.js +6 -0
  32. package/dist/rankQuery.js +23 -0
  33. package/dist/ranking.d.ts +42 -0
  34. package/dist/ranking.js +70 -0
  35. package/dist/rating.d.ts +103 -0
  36. package/dist/rating.js +49 -0
  37. package/dist/ratingPools.js +133 -0
  38. package/dist/ratingStore.js +333 -0
  39. package/dist/ratingStrategies.js +107 -0
  40. package/dist/records.d.ts +116 -0
  41. package/dist/records.js +87 -0
  42. package/dist/rpc.d.ts +321 -0
  43. package/dist/rpc.js +305 -0
  44. package/dist/score.d.ts +13 -0
  45. package/dist/score.js +26 -0
  46. package/dist/server.d.ts +1477 -0
  47. package/dist/server.js +17 -0
  48. package/dist/service.js +948 -0
  49. package/dist/subjectFences.js +43 -0
  50. package/dist/tables.entity.js +187 -0
  51. package/dist/testing.d.ts +872 -0
  52. package/dist/testing.js +367 -0
  53. package/dist/tournament-app/tournament.advance.workflow.server.tsx +3 -0
  54. package/dist/tournament-app/tournament.advance.workflow.tsx +12 -0
  55. package/dist/tournament-app/tournament.stage.workflow.server.tsx +3 -0
  56. package/dist/tournament-app/tournament.stage.workflow.tsx +10 -0
  57. package/dist/tournamentInstallation.js +167 -0
  58. package/dist/tournamentPrizes.js +33 -0
  59. package/dist/tournamentStage.js +150 -0
  60. package/dist/tournamentStagePorts.js +4 -0
  61. package/dist/tournamentWorkflow.js +100 -0
  62. package/dist/tournamentWorkflowSchemas.js +53 -0
  63. package/dist/tournaments.d.ts +32 -0
  64. package/dist/tournaments.js +20 -0
  65. package/dist/web.d.ts +175 -0
  66. package/dist/web.js +16 -0
  67. package/package.json +113 -4
@@ -0,0 +1,948 @@
1
+ import { LeaderboardError as e, leaderboardError as t } from "./errors.js";
2
+ import { defineLeaderboard as n, leaderboardIdentifier as r } from "./leaderboard.js";
3
+ import { defineLeague as i, leagueMovements as a } from "./leagues.js";
4
+ import { canonicalLeaderboardJson as o, captureLeaderboardJson as s } from "./json.js";
5
+ import { applyScore as c, scoreString as l, scoreValue as u } from "./score.js";
6
+ import { resolveRatingPools as d } from "./ratingPools.js";
7
+ import { LeaderboardPeriodSchema as f, LeaderboardRecordSchema as p, LeaderboardTournamentEntrySchema as m, LeaderboardTournamentStatusSchema as h } from "./records.js";
8
+ import { defineTournament as g } from "./tournaments.js";
9
+ import { resolveRatingStrategies as _ } from "./ratingStrategies.js";
10
+ import { leaderboardBoardsTable as v, leaderboardBucketAssignmentsTable as y, leaderboardLeagueMembersTable as b, leaderboardLeagueRollsTable as x, leaderboardPeriodsTable as S, leaderboardRecordsTable as C, leaderboardSubjectsTable as w, leaderboardSubmissionsTable as T, leaderboardTournamentEntriesTable as E, leaderboardTournamentsTable as D } from "./tables.entity.js";
11
+ import { makeRatingStore as ee } from "./ratingStore.js";
12
+ import { defaultLeaderboardTiebreak as te, defaultPeriodSummary as ne, leaderboardAround as re, rankLeaderboardRecords as ie } from "./ranking.js";
13
+ import { defaultLeaderboardBucketAssign as O } from "./buckets.js";
14
+ import { makeBucketStore as ae } from "./bucketStore.js";
15
+ import { makeLeaderboardSubjectFences as oe } from "./subjectFences.js";
16
+ import { admitLeaderboardRankOrder as se, defaultLeaderboardRankQuery as ce } from "./rankQuery.js";
17
+ import { Cron as le, Effect as k, Result as ue, Schema as A } from "effect";
18
+ import { createHash as de } from "node:crypto";
19
+ import { and as j, eq as M, gt as fe, queryFor as N } from "@voltro/database";
20
+ // src/service.ts
21
+ var pe = () => k.void, P = (n) => n instanceof e ? n : t("unavailable"), F = (e) => k.tryPromise({
22
+ try: e,
23
+ catch: P
24
+ }), I = (e) => de("sha256").update(o(e)).digest("hex"), L = (e, t) => e + I(t).slice(0, 56), R = (e) => {
25
+ let n = e instanceof Date ? e.getTime() : typeof e == "string" ? Date.parse(e) : typeof e == "number" ? e : NaN;
26
+ if (!Number.isSafeInteger(n) || n < 0) throw t("unavailable");
27
+ return n;
28
+ }, z = (e) => A.decodeUnknownSync(p)(structuredClone({
29
+ id: e.id,
30
+ board: e.board,
31
+ periodId: e.periodId,
32
+ ownerId: e.ownerId,
33
+ score: l(e.score),
34
+ subscore: l(e.subscore),
35
+ numSubmits: e.numSubmits,
36
+ metadata: e.metadata,
37
+ updatedAt: R(e.updatedAt),
38
+ bucket: e.bucket
39
+ })), me = (e, n) => {
40
+ if (e.reset === void 0) return null;
41
+ let r = le.parse(e.reset.cron, e.reset.timezone);
42
+ if (ue.isFailure(r)) throw t("invalid_board");
43
+ let i = le.next(r.success, new Date(n)), a = i.getTime();
44
+ if (!Number.isSafeInteger(a) || a <= n || a > 864e13) throw t("unavailable");
45
+ return i;
46
+ }, he = (e) => {
47
+ if (!e || !Array.isArray(e.boards) || e.boards.length > 256) throw t("invalid_board");
48
+ let a = Array.from(e.boards, (e) => {
49
+ if (!e || typeof e != "object") throw t("invalid_board");
50
+ return n({
51
+ name: e.name,
52
+ sort: e.sort,
53
+ operator: e.operator,
54
+ metadata: e.metadata,
55
+ maxRankRecords: e.maxRankRecords,
56
+ maxPageSize: e.maxPageSize,
57
+ submit: e.submit,
58
+ ...e.reset === void 0 ? {} : { reset: e.reset },
59
+ ...e.buckets === void 0 ? {} : { buckets: e.buckets }
60
+ });
61
+ });
62
+ if (new Set(a.map((e) => e.name)).size !== e.boards.length) throw t("invalid_board");
63
+ if (e.tournaments !== void 0 && (!Array.isArray(e.tournaments) || e.tournaments.length > 256)) throw t("invalid_input");
64
+ let o = Array.from(e.tournaments ?? [], (e) => {
65
+ if (!e || e.kind !== "tournament" || e.format !== "time-window") throw t("invalid_input");
66
+ return g(e);
67
+ });
68
+ if (new Set(o.map((e) => e.name)).size !== o.length || new Set(o.map((e) => e.board)).size !== o.length || o.some((e) => !a.some((t) => t.name === e.board))) throw t("invalid_input");
69
+ for (let e of o) {
70
+ let n = me(a.find((t) => t.name === e.board), e.startsAt);
71
+ if (n !== null && e.endsAt > n.getTime()) throw t("invalid_input");
72
+ }
73
+ if (e.leagues !== void 0 && (!Array.isArray(e.leagues) || e.leagues.length > 64)) throw t("invalid_input");
74
+ let c = Array.from(e.leagues ?? [], (e) => i(e)), l = c.flatMap((e) => e.divisions);
75
+ if (new Set(c.map((e) => e.name)).size !== c.length || new Set(l).size !== l.length || l.some((e) => {
76
+ let t = a.find((t) => t.name === e);
77
+ return !t || t.buckets !== void 0;
78
+ }) || e.allowedServices !== void 0 && (!Array.isArray(e.allowedServices) || e.allowedServices.length > 256)) throw t("invalid_input");
79
+ let u = s(e.ratingPools ?? [], 65536);
80
+ d(u);
81
+ let f = _(e.ratingStrategies), p = new Set(e.allowedServices ?? []);
82
+ if (p.size > 256 || [...p].some((e) => !r(e))) throw t("invalid_input");
83
+ let m = e.validate ?? pe, h = e.now ?? Date.now, v = e.tiebreak, y = e.rankQuery ?? ce, b = e.bucketAssign ?? O, x = e.periodSummary ?? ne, S = e.maxPeriodRows ?? 1e4, C = e.maxSummaryBytes ?? 16384, w = e.maxMetadataBytes ?? 16384, T = e.maxExportRows ?? 1e4, E = e.maxSubmissionsPerOwner ?? 1e4, D = e.bucketStrategyVersion ?? "voltro:bucket:1";
84
+ if (!r(D) || b !== O && (e.bucketStrategyVersion === void 0 || D.startsWith("voltro:")) || b === O && D !== "voltro:bucket:1" || typeof m != "function" || typeof h != "function" || typeof y != "function" || typeof b != "function" || v !== void 0 && typeof v != "function" || !Number.isSafeInteger(w) || w < 1 || w > 65536 || !Number.isSafeInteger(T) || T < 1 || T > 1e5 || !Number.isSafeInteger(E) || E < 1 || E > T || typeof x != "function" || !Number.isSafeInteger(S) || S < 1 || S > 1e5 || !Number.isSafeInteger(C) || C < 1 || C > 65536) throw t("invalid_input");
85
+ return Object.freeze({
86
+ boards: Object.freeze(a),
87
+ tournaments: Object.freeze(o),
88
+ leagues: Object.freeze(c),
89
+ ratingPools: u,
90
+ ratingStrategies: f,
91
+ allowedServices: Object.freeze([...p]),
92
+ validate: m,
93
+ now: h,
94
+ maxMetadataBytes: w,
95
+ maxExportRows: T,
96
+ maxSubmissionsPerOwner: E,
97
+ periodSummary: x,
98
+ maxPeriodRows: S,
99
+ maxSummaryBytes: C,
100
+ rankQuery: y,
101
+ bucketAssign: b,
102
+ bucketStrategyVersion: D,
103
+ ...v === void 0 ? {} : { tiebreak: v }
104
+ });
105
+ }, ge = (n, i) => {
106
+ let g = he(i), ne = new Map(g.boards.map((e) => [e.name, e])), O = new Map(g.tournaments.map((e) => [e.name, e])), ce = new Map(g.tournaments.map((e) => [e.board, e])), le = new Set(g.allowedServices), de = g.validate, pe = g.now, ge = g.tiebreak, _e = g.maxMetadataBytes, B = g.maxExportRows, ve = g.maxSubmissionsPerOwner, ye = g.maxPeriodRows, be = g.maxSummaryBytes, xe = g.periodSummary, Se = g.rankQuery, V = () => {
107
+ let e = pe();
108
+ if (!Number.isSafeInteger(e) || e < 0 || e > 864e13) throw t("unavailable");
109
+ return e;
110
+ }, H = (e) => {
111
+ let n = ne.get(e);
112
+ if (!n) throw t("not_found");
113
+ return n;
114
+ }, U = (e) => e?.type === "system" || e?.type === "service" && le.has(e.service), W = (e) => {
115
+ if (!e || e.type !== "user" || !r(e.id) || !r(e.tenantId)) throw t("forbidden");
116
+ return e.tenantId;
117
+ }, { seedSubject: G, subjectFence: K } = oe(n), q = ee(n, d(g.ratingPools), {
118
+ seedSubject: G,
119
+ subjectFence: K,
120
+ machine: U,
121
+ now: V,
122
+ key: L,
123
+ hash: I,
124
+ maxRows: B,
125
+ strategies: _(g.ratingStrategies)
126
+ }), Ce = ae({
127
+ key: L,
128
+ hash: I,
129
+ assign: g.bucketAssign
130
+ }), J = (e) => ({
131
+ sort: e.sort,
132
+ operator: e.operator,
133
+ reset: e.reset ?? null,
134
+ buckets: e.buckets ?? null,
135
+ bucketStrategyVersion: e.buckets === void 0 ? null : g.bucketStrategyVersion,
136
+ tournament: ce.get(e.name) ?? null
137
+ }), Y = async (e, t) => {
138
+ let r = L("lbb_", [e, t.name]), i = L("lbp_", [
139
+ e,
140
+ t.name,
141
+ "initial"
142
+ ]), a = J(t);
143
+ try {
144
+ await n.insertIgnore(v.tableName, {
145
+ id: r,
146
+ tenantId: e,
147
+ name: t.name,
148
+ periodId: i,
149
+ config: a,
150
+ admission: 0,
151
+ updatedAt: new Date(V())
152
+ }, { conflictColumns: ["id"] });
153
+ } catch (e) {
154
+ if (!(await n.query(N(v).where(M("id", r)).limit(1).descriptor))[0]) throw e;
155
+ }
156
+ }, we = async (e, n, r) => {
157
+ let i = L("lbb_", [n, r.name]);
158
+ if (await e.updateMany(v.tableName, { admission: 0 }, { where: M("id", i) }) !== 1) throw t("unavailable");
159
+ let a = (await e.query(N(v).where(M("id", i)).limit(1).descriptor))[0];
160
+ if (!a || a.tenantId !== n || a.name !== r.name || o(a.config) !== o(J(r))) throw t("conflict");
161
+ return a;
162
+ }, X = async (e, n, r, i) => {
163
+ let a = await e.query(N(n).where(j(M("tenantId", r), M("ownerId", i))).orderBy("id", "asc").limit(B + 1).descriptor);
164
+ if (a.length > B) throw t("limit_exceeded");
165
+ if (a.some((e) => e.tenantId !== r || e.ownerId !== i)) throw t("unavailable");
166
+ return a;
167
+ }, Z = async (e, r, i = n, a, s) => {
168
+ let c = (await i.query(N(v).where(M("id", L("lbb_", [e, r.name]))).limit(1).descriptor))[0];
169
+ if (!c) return [];
170
+ if (c.tenantId !== e || c.name !== r.name || typeof c.periodId != "string") throw t("unavailable");
171
+ if (o(c.config) !== o(J(r))) throw t("conflict");
172
+ let l = await i.query(N(C).where(j(M("tenantId", e), M("board", r.name), M("periodId", a ?? c.periodId), ...s === void 0 ? [] : [M("bucket", s)])).limit(r.maxRankRecords + 1).descriptor);
173
+ if (l.length > r.maxRankRecords) throw t("limit_exceeded");
174
+ let u = l.map((n) => {
175
+ if (n.tenantId !== e || n.board !== r.name || n.periodId !== (a ?? c.periodId) || s !== void 0 && n.bucket !== s) throw t("unavailable");
176
+ return {
177
+ ...z(n),
178
+ tenantId: e
179
+ };
180
+ }), d = new Map(u.map((e) => [e.id, e])), f = Object.freeze(u.map((t) => Object.freeze({
181
+ id: t.id,
182
+ tenantId: e,
183
+ board: t.board,
184
+ periodId: t.periodId,
185
+ ownerId: t.ownerId,
186
+ score: t.score,
187
+ subscore: t.subscore,
188
+ updatedAt: t.updatedAt
189
+ }))), p = Object.freeze({
190
+ tenantId: e,
191
+ board: r.name,
192
+ periodId: a ?? c.periodId,
193
+ sort: r.sort,
194
+ maxRecords: r.maxRankRecords,
195
+ records: f,
196
+ bucketId: s ?? null,
197
+ tiebreak: ge ?? te,
198
+ query: i.query.bind(i)
199
+ }), m = await k.runPromise(k.result(k.suspend(() => Se(p))));
200
+ if (ue.isFailure(m)) throw m.failure;
201
+ return se(m.success, f).map((e, t) => {
202
+ let n = d.get(e);
203
+ return {
204
+ ...z({
205
+ ...n,
206
+ updatedAt: new Date(n.updatedAt)
207
+ }),
208
+ rank: t + 1
209
+ };
210
+ });
211
+ }, Te = async (e, r, i) => {
212
+ if (i.buckets === void 0) return Z(e, i);
213
+ let a = (await n.query(N(v).where(M("id", L("lbb_", [e, i.name]))).limit(1).descriptor))[0];
214
+ if (!a) return [];
215
+ if (a.tenantId !== e || a.name !== i.name || typeof a.periodId != "string") throw t("unavailable");
216
+ if (o(a.config) !== o(J(i))) throw t("conflict");
217
+ let s = await Ce.readOwn(n, e, i.name, a.periodId, r);
218
+ return s ? Z(e, i, n, a.periodId, String(s.bucket)) : [];
219
+ }, Q = async (e, n, r) => {
220
+ let i = await e.query(N(S).where(r === void 0 ? M("tenantId", n) : j(M("tenantId", n), M("board", r))).orderBy("startsAt", "desc").orderBy("id", "asc").limit(ye + 1).descriptor);
221
+ if (i.length > ye) throw t("limit_exceeded");
222
+ if (i.some((e) => e.tenantId !== n || r !== void 0 && e.board !== r)) throw t("unavailable");
223
+ return i;
224
+ }, $ = (e, n, r, i) => {
225
+ let a = s(e, be);
226
+ if (!a || typeof a != "object" || Array.isArray(a)) throw t("unavailable");
227
+ let c = a;
228
+ if (Object.keys(c).length !== 2 || !Number.isSafeInteger(c.participants) || Number(c.participants) < 0 || Number(c.participants) > 1e5 || !Array.isArray(c.top) || c.top.length > 1e3 || c.top.length > Number(c.participants)) throw t("unavailable");
229
+ let l = /* @__PURE__ */ new Set(), u = /* @__PURE__ */ new Set(), d = /* @__PURE__ */ new Set();
230
+ for (let e of c.top) {
231
+ let a = ie([e], { maxRecords: 1 })[0];
232
+ if (n !== void 0 && a.tenantId !== n || r !== void 0 && a.board !== r || i !== void 0 && a.periodId !== i || !Number.isSafeInteger(e.rank) || e.rank < 1 || e.rank > Number(c.participants) || l.has(a.ownerId) || u.has(a.id) || d.has(e.rank) || o(e) !== o({
233
+ ...a,
234
+ rank: e.rank
235
+ })) throw t("unavailable");
236
+ l.add(a.ownerId), u.add(a.id), d.add(e.rank);
237
+ }
238
+ return a;
239
+ }, Ee = (e) => {
240
+ let n = Object.freeze(e.map((e) => Object.freeze({ ...e }))), r = new Map(n.map((e) => [e.id, e])), i;
241
+ try {
242
+ i = $(xe(n));
243
+ } catch (e) {
244
+ throw P(e);
245
+ }
246
+ if (i.participants !== e.length || i.top.some((e) => o(e) !== o(r.get(e.id)))) throw t("invalid_record");
247
+ return i;
248
+ }, De = async (e, n) => {
249
+ let r = await e.query(N(v).where(M("tenantId", n)).orderBy("id", "asc").limit(B + 1).descriptor);
250
+ if (r.length > B) throw t("limit_exceeded");
251
+ for (let i of r) if (i.tenantId !== n || await e.updateMany(v.tableName, { admission: 0 }, { where: j(M("id", String(i.id)), M("tenantId", n)) }) !== 1) throw t("unavailable");
252
+ }, Oe = (e, t) => A.decodeUnknownSync(m)({
253
+ tournament: t,
254
+ joinedAt: R(e.joinedAt),
255
+ attemptsLeft: e.attemptsLeft
256
+ }), ke = async (e, n, r, i, a = !1) => {
257
+ let s = L("lbt_", [n, r.name]);
258
+ if (!(await e.query(N(D).where(M("id", s)).limit(1).descriptor))[0]) {
259
+ let o = V();
260
+ if (o < r.startsAt || o >= r.endsAt && !a) throw t("forbidden");
261
+ if ((await e.query(N(C).where(j(M("tenantId", n), M("board", r.board), M("periodId", String(i.periodId)))).limit(1).descriptor)).length > 0) throw t("conflict");
262
+ await e.insertIgnore(S.tableName, {
263
+ id: String(i.periodId),
264
+ tenantId: n,
265
+ board: r.board,
266
+ startsAt: new Date(r.startsAt),
267
+ endsAt: me(H(r.board), r.startsAt),
268
+ state: "active",
269
+ summary: {},
270
+ previousPeriodId: null,
271
+ requestKey: null
272
+ }, { conflictColumns: ["id"] }), await e.insert(D.tableName, {
273
+ id: s,
274
+ tenantId: n,
275
+ name: r.name,
276
+ board: r.board,
277
+ periodId: String(i.periodId),
278
+ config: r,
279
+ admission: 0,
280
+ numEntries: 0
281
+ });
282
+ }
283
+ if (await e.updateMany(D.tableName, { admission: 0 }, { where: M("id", s) }) !== 1) throw t("unavailable");
284
+ let c = (await e.query(N(D).where(M("id", s)).limit(1).descriptor))[0];
285
+ if (!c || c.tenantId !== n || c.name !== r.name || c.board !== r.board || o(c.config) !== o(r) || !Number.isSafeInteger(c.numEntries) || Number(c.numEntries) < 0 || Number(c.numEntries) > r.maxEntries) throw t("conflict");
286
+ return c;
287
+ }, Ae = async (e, n, r, i) => {
288
+ let a = (await e.query(N(E).where(M("id", L("lbe_", [
289
+ n,
290
+ String(i.id),
291
+ r
292
+ ]))).limit(1).descriptor))[0];
293
+ if (a && (a.tenantId !== n || a.ownerId !== r || a.tournamentId !== i.id)) throw t("unavailable");
294
+ return a;
295
+ }, je = (e, n, r, i) => {
296
+ if (i < e.startsAt || i >= e.endsAt || n.periodId !== r.periodId) throw t("forbidden");
297
+ }, Me = async (e, n, r, i, a, o) => {
298
+ if (Number(a.numEntries) >= i.maxEntries) throw t("limit_exceeded");
299
+ let s = await e.insert(E.tableName, {
300
+ id: L("lbe_", [
301
+ n,
302
+ String(a.id),
303
+ r
304
+ ]),
305
+ tenantId: n,
306
+ tournamentId: String(a.id),
307
+ ownerId: r,
308
+ joinedAt: new Date(o),
309
+ attemptsLeft: i.attemptsPerEntry
310
+ });
311
+ if (!s || !await e.update(D.tableName, String(a.id), { numEntries: Number(a.numEntries) + 1 })) throw t("unavailable");
312
+ return s;
313
+ }, Ne = async (e, n) => {
314
+ let r = await e.query(N(D).where(M("tenantId", n)).orderBy("id", "asc").limit(B + 1).descriptor);
315
+ if (r.length > B) throw t("limit_exceeded");
316
+ for (let i of r) if (i.tenantId !== n || await e.updateMany(D.tableName, { admission: 0 }, { where: j(M("id", String(i.id)), M("tenantId", n)) }) !== 1) throw t("unavailable");
317
+ let i = [];
318
+ for (let a of r) {
319
+ let r = (await e.query(N(D).where(M("id", String(a.id))).limit(1).descriptor))[0];
320
+ if (!r || r.tenantId !== n) throw t("unavailable");
321
+ i.push(r);
322
+ }
323
+ return i;
324
+ }, Pe = (e, i) => {
325
+ let a, o;
326
+ try {
327
+ if (!U(e)) throw t("forbidden");
328
+ if (!i || ![
329
+ i.tenantId,
330
+ i.board,
331
+ i.requestId,
332
+ i.expectedPeriodId
333
+ ].every(r) || !Number.isSafeInteger(i.closedAt) || i.closedAt < 0 || i.closedAt > V()) throw t("invalid_input");
334
+ o = H(i.board), a = Object.freeze({
335
+ tenantId: i.tenantId,
336
+ board: i.board,
337
+ requestId: i.requestId,
338
+ expectedPeriodId: i.expectedPeriodId,
339
+ closedAt: i.closedAt
340
+ });
341
+ } catch (e) {
342
+ return k.fail(P(e));
343
+ }
344
+ return F(async () => (await Y(a.tenantId, o), n.transactional(async (e) => {
345
+ let n = await we(e, a.tenantId, o), r = L("lbp_", [
346
+ a.tenantId,
347
+ a.board,
348
+ a.requestId
349
+ ]), i = I(a);
350
+ if (r === a.expectedPeriodId) throw t("conflict");
351
+ let s = (await e.query(N(S).where(M("id", r)).limit(1).descriptor))[0];
352
+ if (s) {
353
+ if (s.tenantId !== a.tenantId || s.board !== a.board || s.requestKey !== i || s.previousPeriodId !== a.expectedPeriodId || R(s.startsAt) !== a.closedAt) throw t("conflict");
354
+ let n = (await e.query(N(S).where(M("id", a.expectedPeriodId)).limit(1).descriptor))[0];
355
+ if (!n || n.tenantId !== a.tenantId || n.board !== a.board || R(n.endsAt) !== a.closedAt || !["closed", "archived"].includes(String(n.state))) throw t("unavailable");
356
+ return {
357
+ closedPeriodId: a.expectedPeriodId,
358
+ activePeriodId: r,
359
+ closedAt: a.closedAt,
360
+ summary: $(n.summary, a.tenantId, a.board, a.expectedPeriodId)
361
+ };
362
+ }
363
+ if (n.periodId !== a.expectedPeriodId) throw t("conflict");
364
+ let c = await Q(e, a.tenantId, a.board);
365
+ if (c.length >= ye) throw t("limit_exceeded");
366
+ let l = c.find((e) => e.id === a.expectedPeriodId);
367
+ if (!l || l.state !== "active" || R(l.startsAt) > a.closedAt || l.endsAt !== null && R(l.endsAt) < a.closedAt) throw t("conflict");
368
+ let u = (await Z(a.tenantId, o, e, a.expectedPeriodId)).map((e) => ({
369
+ id: e.id,
370
+ tenantId: a.tenantId,
371
+ board: e.board,
372
+ periodId: e.periodId,
373
+ ownerId: e.ownerId,
374
+ score: e.score,
375
+ subscore: e.subscore,
376
+ updatedAt: e.updatedAt,
377
+ rank: e.rank
378
+ }));
379
+ if (u.some((e) => e.updatedAt > a.closedAt)) throw t("conflict");
380
+ let d = Ee(u);
381
+ if (!await e.update(S.tableName, a.expectedPeriodId, {
382
+ endsAt: new Date(a.closedAt),
383
+ state: "closed",
384
+ summary: d
385
+ }) || (await e.insert(S.tableName, {
386
+ id: r,
387
+ tenantId: a.tenantId,
388
+ board: a.board,
389
+ startsAt: new Date(a.closedAt),
390
+ endsAt: me(o, a.closedAt),
391
+ state: "active",
392
+ summary: {},
393
+ previousPeriodId: a.expectedPeriodId,
394
+ requestKey: i
395
+ }), !await e.update(v.tableName, String(n.id), {
396
+ periodId: r,
397
+ updatedAt: new Date(a.closedAt)
398
+ }))) throw t("unavailable");
399
+ if (o.reset !== void 0) {
400
+ let n = (await Q(e, a.tenantId, a.board)).filter((e) => e.state === "closed");
401
+ for (let r of n.slice(o.reset.keepHistory)) if (!await e.update(S.tableName, String(r.id), { state: "archived" })) throw t("unavailable");
402
+ }
403
+ return {
404
+ closedPeriodId: a.expectedPeriodId,
405
+ activePeriodId: r,
406
+ closedAt: a.closedAt,
407
+ summary: d
408
+ };
409
+ })));
410
+ }, Fe = new Map((g.leagues ?? []).map((e) => [e.name, e])), Ie = (e) => {
411
+ let n = typeof e == "string" ? Fe.get(e) : void 0;
412
+ if (!n) throw t("not_found");
413
+ return n;
414
+ }, Le = (e, t, n) => L("lblm_", [
415
+ e,
416
+ t,
417
+ n
418
+ ]);
419
+ return {
420
+ assignLeague: (e, i) => {
421
+ let a;
422
+ try {
423
+ if (!U(e)) throw t("forbidden");
424
+ if (!i || ![i.tenantId, i.ownerId].every(r) || !Ie(i.league).divisions.includes(i.division)) throw t("invalid_input");
425
+ a = Object.freeze({
426
+ tenantId: i.tenantId,
427
+ league: i.league,
428
+ ownerId: i.ownerId,
429
+ division: i.division
430
+ });
431
+ } catch (e) {
432
+ return k.fail(P(e));
433
+ }
434
+ return F(async () => (await G(a.tenantId, a.ownerId), n.transactional(async (e) => {
435
+ await K(e, a.tenantId, a.ownerId);
436
+ let t = Le(a.tenantId, a.league, a.ownerId), n = new Date(V());
437
+ return await e.insertIgnore(b.tableName, {
438
+ id: t,
439
+ tenantId: a.tenantId,
440
+ league: a.league,
441
+ ownerId: a.ownerId,
442
+ division: a.division,
443
+ updatedAt: n
444
+ }, { conflictColumns: ["id"] }), await e.update(b.tableName, t, {
445
+ division: a.division,
446
+ updatedAt: n
447
+ }), {
448
+ league: a.league,
449
+ division: a.division
450
+ };
451
+ })));
452
+ },
453
+ myLeague: (e, i) => {
454
+ let a, o, s;
455
+ try {
456
+ if (s = Ie(i), a = W(e), typeof e.id != "string" || !r(e.id)) throw t("forbidden");
457
+ o = e.id;
458
+ } catch (e) {
459
+ return k.fail(P(e));
460
+ }
461
+ return F(async () => {
462
+ let e = (await n.query(N(b).where(M("id", Le(a, s.name, o))).limit(1).descriptor))[0];
463
+ if (e && (e.tenantId !== a || e.ownerId !== o || !s.divisions.includes(String(e.division)))) throw t("unavailable");
464
+ return e ? {
465
+ league: s.name,
466
+ division: String(e.division),
467
+ assigned: !0
468
+ } : {
469
+ league: s.name,
470
+ division: s.divisions.at(-1),
471
+ assigned: !1
472
+ };
473
+ });
474
+ },
475
+ rollLeague: (e, i) => {
476
+ let o, s;
477
+ try {
478
+ if (!U(e)) throw t("forbidden");
479
+ if (!i || ![i.tenantId, i.requestId].every(r)) throw t("invalid_input");
480
+ s = Ie(i.league), o = Object.freeze({
481
+ tenantId: i.tenantId,
482
+ league: i.league,
483
+ requestId: i.requestId,
484
+ closedAt: i.closedAt
485
+ });
486
+ } catch (e) {
487
+ return k.fail(P(e));
488
+ }
489
+ return k.gen(function* () {
490
+ let r = [];
491
+ for (let t of s.divisions) {
492
+ let i = H(t), a = o.requestId + ":" + t, s = L("lbp_", [
493
+ o.tenantId,
494
+ t,
495
+ a
496
+ ]), c = yield* F(async () => (await Y(o.tenantId, i), (await n.query(N(S).where(M("id", s)).limit(1).descriptor))[0])), l = c ? String(c.previousPeriodId) : yield* F(async () => {
497
+ let e = String((await n.query(N(v).where(M("id", L("lbb_", [o.tenantId, t]))).limit(1).descriptor))[0]?.periodId ?? ""), r = Math.min(V(), o.closedAt);
498
+ return await n.insertIgnore(S.tableName, {
499
+ id: e,
500
+ tenantId: o.tenantId,
501
+ board: t,
502
+ startsAt: new Date(r),
503
+ endsAt: me(i, r),
504
+ state: "active",
505
+ summary: {},
506
+ previousPeriodId: null,
507
+ requestKey: null
508
+ }, { conflictColumns: ["id"] }), e;
509
+ }), u = yield* Pe(e, {
510
+ tenantId: o.tenantId,
511
+ board: t,
512
+ requestId: a,
513
+ expectedPeriodId: l,
514
+ closedAt: o.closedAt
515
+ });
516
+ r.push({
517
+ division: t,
518
+ closedPeriodId: u.closedPeriodId,
519
+ activePeriodId: u.activePeriodId
520
+ });
521
+ }
522
+ return yield* F(async () => n.transactional(async (e) => {
523
+ let n = L("lblr_", [
524
+ o.tenantId,
525
+ s.name,
526
+ o.requestId
527
+ ]), i = (await e.query(N(x).where(M("id", n)).forUpdate().limit(1).descriptor))[0];
528
+ if (i) {
529
+ if (i.tenantId !== o.tenantId || i.league !== s.name || !Array.isArray(i.movements)) throw t("unavailable");
530
+ return {
531
+ divisions: Object.freeze(r),
532
+ movements: Object.freeze(i.movements)
533
+ };
534
+ }
535
+ let c = [];
536
+ for (let n of r) {
537
+ let r = await e.query(N(b).where(j(M("tenantId", o.tenantId), M("league", s.name), M("division", n.division))).limit((g.maxExportRows ?? 1e4) + 1).descriptor);
538
+ if (r.length > (g.maxExportRows ?? 1e4)) throw t("limit_exceeded");
539
+ let i = await Z(o.tenantId, H(n.division), e, n.closedPeriodId), a = new Map(i.map((e) => [e.ownerId, e.rank])), l = r.map((e) => String(e.ownerId)).sort((e, t) => (a.get(e) ?? 2 ** 53 - 1) - (a.get(t) ?? 2 ** 53 - 1) || (e < t ? -1 : +(e > t)));
540
+ c.push({
541
+ division: n.division,
542
+ owners: l
543
+ });
544
+ }
545
+ let l = a(s, c), u = new Date(o.closedAt);
546
+ for (let n of l) if (await e.updateMany(b.tableName, {
547
+ division: n.to,
548
+ updatedAt: u
549
+ }, { where: j(M("id", Le(o.tenantId, s.name, n.ownerId)), M("division", n.from)) }) !== 1) throw t("conflict");
550
+ return await e.insert(x.tableName, {
551
+ id: n,
552
+ tenantId: o.tenantId,
553
+ league: s.name,
554
+ movements: l,
555
+ at: u
556
+ }), {
557
+ divisions: Object.freeze(r),
558
+ movements: l
559
+ };
560
+ }));
561
+ });
562
+ },
563
+ leagueTenants: (e, i) => {
564
+ let a, o, s;
565
+ try {
566
+ if (!U(e)) throw t("forbidden");
567
+ if (!i || !Number.isSafeInteger(i.limit) || i.limit < 1 || i.limit > 1e3 || i.after != null && !r(i.after)) throw t("invalid_input");
568
+ a = Ie(i.league), o = i.after ?? null, s = i.limit;
569
+ } catch (e) {
570
+ return k.fail(P(e));
571
+ }
572
+ return F(async () => {
573
+ let e = [], t = o;
574
+ for (; e.length <= s;) {
575
+ let r = (await n.query(N(b).where(t === null ? M("league", a.name) : j(M("league", a.name), fe("tenantId", t))).orderBy("tenantId", "asc").limit(1).descriptor))[0];
576
+ if (!r) break;
577
+ t = String(r.tenantId), e.push(t);
578
+ }
579
+ return {
580
+ tenants: Object.freeze(e.slice(0, s)),
581
+ next: e.length > s ? e[s - 1] : null
582
+ };
583
+ });
584
+ },
585
+ prepareRatingMatch: q.prepareRatingMatch,
586
+ applyRatingMatch: q.applyRatingMatch,
587
+ myRating: q.myRating,
588
+ pendingRatingMatches: q.pendingRatingMatches,
589
+ closeTournament: (e, i) => {
590
+ let a, o, s;
591
+ try {
592
+ if (!U(e)) throw t("forbidden");
593
+ if (!i || ![
594
+ i.tenantId,
595
+ i.tournament,
596
+ i.requestId
597
+ ].every(r)) throw t("invalid_input");
598
+ let n = O.get(i.tournament);
599
+ if (!n) throw t("not_found");
600
+ if (o = n, V() < n.endsAt) throw t("forbidden");
601
+ s = structuredClone(e), a = Object.freeze({
602
+ tenantId: i.tenantId,
603
+ tournament: i.tournament,
604
+ requestId: i.requestId
605
+ });
606
+ } catch (e) {
607
+ return k.fail(P(e));
608
+ }
609
+ return F(async () => {
610
+ let e = H(o.board);
611
+ await Y(a.tenantId, e);
612
+ let r = await n.transactional(async (n) => {
613
+ if (V() < o.endsAt) throw t("forbidden");
614
+ let r = await we(n, a.tenantId, e), i = await ke(n, a.tenantId, o, r, !0);
615
+ return String(i.periodId);
616
+ }), i = await k.runPromise(k.result(Pe(s, {
617
+ tenantId: a.tenantId,
618
+ board: o.board,
619
+ requestId: "ltc_" + I([
620
+ a.tenantId,
621
+ a.tournament,
622
+ a.requestId
623
+ ]),
624
+ expectedPeriodId: r,
625
+ closedAt: o.endsAt
626
+ })));
627
+ if (ue.isFailure(i)) throw i.failure;
628
+ return i.success;
629
+ });
630
+ },
631
+ joinTournament: (e, r) => {
632
+ let i, a, o, s;
633
+ try {
634
+ i = W(e), a = e.id;
635
+ let n = O.get(r);
636
+ if (!n) throw t("not_found");
637
+ o = n, s = H(n.board);
638
+ } catch (e) {
639
+ return k.fail(P(e));
640
+ }
641
+ return F(async () => (await G(i, a), await Y(i, s), n.transactional(async (e) => {
642
+ await K(e, i, a);
643
+ let t = await we(e, i, s), n = await ke(e, i, o, t), r = await Ae(e, i, a, n);
644
+ if (r) return Oe(r, o.name);
645
+ let c = V();
646
+ return je(o, n, t, c), Oe(await Me(e, i, a, o, n, c), o.name);
647
+ })));
648
+ },
649
+ tournamentStatus: (e, r) => {
650
+ let i, a, s;
651
+ try {
652
+ i = W(e), a = e.id;
653
+ let n = O.get(r);
654
+ if (!n) throw t("not_found");
655
+ s = n;
656
+ } catch (e) {
657
+ return k.fail(P(e));
658
+ }
659
+ return F(async () => {
660
+ let e = (await n.query(N(D).where(M("id", L("lbt_", [i, s.name]))).limit(1).descriptor))[0];
661
+ if (e && (e.tenantId !== i || e.name !== s.name || o(e.config) !== o(s))) throw t("conflict");
662
+ let r = (await n.query(N(v).where(M("id", L("lbb_", [i, s.board]))).limit(1).descriptor))[0];
663
+ if (r && (r.tenantId !== i || r.name !== s.board)) throw t("unavailable");
664
+ if (r && o(r.config) !== o(J(H(s.board)))) throw t("conflict");
665
+ let c = e === void 0 ? void 0 : await Ae(n, i, a, e), l = V();
666
+ return A.decodeUnknownSync(h)({
667
+ tournament: s.name,
668
+ board: s.board,
669
+ startsAt: s.startsAt,
670
+ endsAt: s.endsAt,
671
+ observedAt: l,
672
+ joinRequired: s.joinRequired,
673
+ state: l < s.startsAt ? "upcoming" : l >= s.endsAt || e && e.periodId !== r?.periodId ? "ended" : "open",
674
+ entry: c === void 0 ? null : Oe(c, s.name)
675
+ });
676
+ });
677
+ },
678
+ rollPeriod: Pe,
679
+ history: (e, r, i = 12) => {
680
+ let a, o;
681
+ try {
682
+ if (a = W(e), o = H(r), !Number.isSafeInteger(i) || i < 1 || i > ye) throw t("invalid_input");
683
+ } catch (e) {
684
+ return k.fail(P(e));
685
+ }
686
+ return F(async () => (await Q(n, a, o.name)).slice(0, i).map((e) => A.decodeUnknownSync(f)({
687
+ id: String(e.id),
688
+ board: String(e.board),
689
+ startsAt: R(e.startsAt),
690
+ endsAt: e.endsAt === null ? null : R(e.endsAt),
691
+ state: String(e.state),
692
+ summary: e.state === "active" ? null : $(e.summary, a, o.name, String(e.id))
693
+ })));
694
+ },
695
+ submit: (i, a) => {
696
+ let d, f;
697
+ try {
698
+ if (!U(i)) throw t("forbidden");
699
+ if (!a || ![
700
+ a.tenantId,
701
+ a.board,
702
+ a.ownerId,
703
+ a.submissionId
704
+ ].every(r) || a.roomId !== void 0 && !r(a.roomId) || a.matchId !== void 0 && !r(a.matchId) || a.tournamentId !== void 0 && !r(a.tournamentId) || (f = H(a.board), a.bucketSkill !== void 0 && (!Number.isFinite(a.bucketSkill) || Math.abs(a.bucketSkill) > 1e9) || a.bucketCohort !== void 0 && !r(a.bucketCohort) || f.buckets?.assign === "skill" && a.bucketSkill === void 0 || f.buckets?.assign === "cohort" && a.bucketCohort === void 0 || f.buckets?.assign !== "skill" && a.bucketSkill !== void 0 || f.buckets?.assign !== "cohort" && a.bucketCohort !== void 0)) throw t("invalid_input");
705
+ let e = ce.get(a.board);
706
+ if (e === void 0 ? a.tournamentId !== void 0 : a.tournamentId !== e.name) throw t("invalid_input");
707
+ let n = s(a.metadata, _e);
708
+ if (!n || typeof n != "object" || Array.isArray(n)) throw t("invalid_input");
709
+ let c = A.decodeUnknownSync(f.metadata, { onExcessProperty: "error" })(n);
710
+ if (o(n) !== o(c)) throw t("invalid_input");
711
+ d = Object.freeze({
712
+ tenantId: a.tenantId,
713
+ board: a.board,
714
+ ownerId: a.ownerId,
715
+ submissionId: a.submissionId,
716
+ score: l(a.score),
717
+ subscore: l(a.subscore ?? "0"),
718
+ metadata: n,
719
+ ...a.roomId === void 0 ? {} : { roomId: a.roomId },
720
+ ...a.matchId === void 0 ? {} : { matchId: a.matchId },
721
+ ...a.tournamentId === void 0 ? {} : { tournamentId: a.tournamentId },
722
+ ...a.bucketSkill === void 0 ? {} : { bucketSkill: a.bucketSkill },
723
+ ...a.bucketCohort === void 0 ? {} : { bucketCohort: a.bucketCohort }
724
+ });
725
+ } catch (n) {
726
+ return k.fail(n instanceof e ? n : t("invalid_input"));
727
+ }
728
+ return F(async () => (await G(d.tenantId, d.ownerId), await Y(d.tenantId, f), n.transactional(async (e) => {
729
+ await K(e, d.tenantId, d.ownerId);
730
+ let n = await we(e, d.tenantId, f), r = L("lbs_", [
731
+ d.tenantId,
732
+ d.board,
733
+ d.ownerId,
734
+ d.submissionId
735
+ ]), i = I(d), a = (await e.query(N(T).where(M("id", r)).limit(1).descriptor))[0];
736
+ if (a) {
737
+ if (a.tenantId !== d.tenantId || a.ownerId !== d.ownerId || a.board !== d.board || a.requestKey !== i) throw t("conflict");
738
+ return A.decodeUnknownSync(p)(structuredClone(a.record));
739
+ }
740
+ if ((await X(e, T, d.tenantId, d.ownerId)).length >= ve) throw t("limit_exceeded");
741
+ let o = String(n.periodId), s = L("lbr_", [
742
+ d.tenantId,
743
+ d.board,
744
+ o,
745
+ d.ownerId
746
+ ]), l = V(), m = ce.get(d.board), h;
747
+ if (m !== void 0) {
748
+ let r = await ke(e, d.tenantId, m, n);
749
+ if (je(m, r, n, l), h = await Ae(e, d.tenantId, d.ownerId, r), h === void 0) {
750
+ if (m.joinRequired) throw t("forbidden");
751
+ h = await Me(e, d.tenantId, d.ownerId, m, r, l);
752
+ }
753
+ if (!Number.isSafeInteger(h.attemptsLeft) || Number(h.attemptsLeft) < 1 || Number(h.attemptsLeft) > m.attemptsPerEntry) throw t("limit_exceeded");
754
+ }
755
+ let g = (await e.query(N(C).where(M("id", s)).limit(1).descriptor))[0];
756
+ if (g && (g.tenantId !== d.tenantId || g.ownerId !== d.ownerId || g.board !== d.board || g.periodId !== o)) throw t("unavailable");
757
+ let _ = g ? z(g) : null;
758
+ if (_ && _.numSubmits >= 2147483647) throw t("overflow");
759
+ await e.insertIgnore(S.tableName, {
760
+ id: o,
761
+ tenantId: d.tenantId,
762
+ board: d.board,
763
+ startsAt: new Date(l),
764
+ endsAt: me(f, l),
765
+ state: "active",
766
+ summary: {},
767
+ previousPeriodId: null,
768
+ requestKey: null
769
+ }, { conflictColumns: ["id"] });
770
+ let y = (await e.query(N(S).where(M("id", o)).limit(1).descriptor))[0];
771
+ if (!y || y.tenantId !== d.tenantId || y.board !== d.board || y.state !== "active" || R(y.startsAt) > l || y.endsAt !== null && l >= R(y.endsAt)) throw t("conflict");
772
+ let b = await k.runPromise(k.result(k.suspend(() => de(d, _, e)).pipe(k.catchDefect(() => k.fail(t("unavailable"))))));
773
+ if (ue.isFailure(b)) throw b.failure;
774
+ let x = await Ce.admit(e, f, d, o, l);
775
+ if (_ && _.bucket !== x) throw t("unavailable");
776
+ let w = c(_?.score ?? null, d.score, f.operator, f.sort), D = f.operator === "best" && _ !== null && (u(d.score) !== u(w) || w === _.score && u(d.subscore) <= u(_.subscore)), ee = {
777
+ score: w,
778
+ subscore: D ? _.subscore : d.subscore,
779
+ bucket: x,
780
+ numSubmits: (_?.numSubmits ?? 0) + 1,
781
+ metadata: D ? _.metadata : d.metadata,
782
+ updatedAt: new Date(D ? _.updatedAt : l)
783
+ }, te = g ? await e.update(C.tableName, s, ee) : await e.insert(C.tableName, {
784
+ id: s,
785
+ tenantId: d.tenantId,
786
+ board: d.board,
787
+ periodId: o,
788
+ ownerId: d.ownerId,
789
+ ...ee
790
+ });
791
+ if (!te) throw t("unavailable");
792
+ let ne = z(te);
793
+ if (h !== void 0 && !await e.update(E.tableName, String(h.id), { attemptsLeft: Number(h.attemptsLeft) - 1 })) throw t("unavailable");
794
+ return await e.insert(T.tableName, {
795
+ id: r,
796
+ tenantId: d.tenantId,
797
+ board: d.board,
798
+ periodId: o,
799
+ ownerId: d.ownerId,
800
+ requestKey: i,
801
+ record: ne,
802
+ roomId: d.roomId ?? null,
803
+ matchId: d.matchId ?? null,
804
+ tournamentId: d.tournamentId ?? null,
805
+ at: new Date(l)
806
+ }), await e.update(v.tableName, String(n.id), { updatedAt: new Date(l) }), ne;
807
+ })));
808
+ },
809
+ top: (e, n, r = 10, i = "global") => {
810
+ let a, o;
811
+ try {
812
+ if (a = W(e), o = H(n), !Number.isSafeInteger(r) || r < 1 || r > o.maxPageSize || !["global", "bucket"].includes(i)) throw t("invalid_input");
813
+ } catch (e) {
814
+ return k.fail(P(e));
815
+ }
816
+ let s = e.id;
817
+ return F(async () => (i === "global" ? await Z(a, o) : await Te(a, s, o)).slice(0, r));
818
+ },
819
+ me: (e, t) => {
820
+ let n, r, i;
821
+ try {
822
+ n = W(e), r = e.id, i = H(t);
823
+ } catch (e) {
824
+ return k.fail(P(e));
825
+ }
826
+ return F(async () => (await Te(n, r, i)).find((e) => e.ownerId === r) ?? null);
827
+ },
828
+ around: (e, n, r = 5) => {
829
+ let i, a, o;
830
+ try {
831
+ if (i = W(e), a = e.id, o = H(n), !Number.isSafeInteger(r) || r < 0 || r * 2 + 1 > o.maxPageSize) throw t("invalid_input");
832
+ } catch (e) {
833
+ return k.fail(P(e));
834
+ }
835
+ return F(async () => {
836
+ let e = await Te(i, a, o), t = re(e.map((e) => ({
837
+ ...e,
838
+ tenantId: i
839
+ })), a, r), n = new Set(t.map((e) => e.id));
840
+ return e.filter((e) => n.has(e.id));
841
+ });
842
+ },
843
+ exportSubject: (e) => {
844
+ let i, a;
845
+ try {
846
+ if (!e || !r(e.tenantId) || !r(e.subjectId) || !["user", "guest"].includes(e.kind)) throw t("invalid_input");
847
+ i = e.tenantId, a = e.subjectId;
848
+ } catch (e) {
849
+ return k.fail(P(e));
850
+ }
851
+ return F(async () => (await G(i, a), n.transactional(async (e) => {
852
+ await K(e, i, a, !0), await De(e, i);
853
+ let n = await Ne(e, i);
854
+ await q.privacyFences(e, i);
855
+ let r = await q.exportInTransaction(e, i, a), o = await X(e, C, i, a), s = await X(e, T, i, a), c = await X(e, E, i, a), l = await X(e, y, i, a), u = await X(e, b, i, a), d = await e.query(N(x).where(M("tenantId", i)).limit(B + 1).descriptor);
856
+ if (d.length > B) throw t("limit_exceeded");
857
+ let f = (await Q(e, i)).filter((e) => e.state !== "active").flatMap((e) => $(e.summary, i, String(e.board), String(e.id)).top.filter((e) => e.ownerId === a).map((t) => ({
858
+ periodId: String(e.id),
859
+ board: String(e.board),
860
+ startsAt: R(e.startsAt),
861
+ endsAt: R(e.endsAt),
862
+ record: t
863
+ })));
864
+ return {
865
+ ...r,
866
+ records: o.map(z),
867
+ submissions: s.map((e) => ({
868
+ id: e.id,
869
+ board: e.board,
870
+ periodId: e.periodId,
871
+ record: A.decodeUnknownSync(p)(structuredClone(e.record)),
872
+ roomId: e.roomId,
873
+ matchId: e.matchId,
874
+ tournamentId: e.tournamentId,
875
+ at: R(e.at)
876
+ })),
877
+ bucketAssignments: l.map((e) => ({
878
+ board: e.board,
879
+ periodId: e.periodId,
880
+ bucket: e.bucket,
881
+ group: e.group,
882
+ assignedAt: R(e.assignedAt)
883
+ })),
884
+ leagues: u.map((e) => ({
885
+ league: e.league,
886
+ division: e.division,
887
+ updatedAt: R(e.updatedAt)
888
+ })),
889
+ leagueMoves: d.flatMap((e) => (Array.isArray(e.movements) ? e.movements : []).filter((e) => e.ownerId === a).map((t) => ({
890
+ league: e.league,
891
+ from: t.from,
892
+ to: t.to,
893
+ at: R(e.at)
894
+ }))),
895
+ periodSummaries: f,
896
+ tournamentEntries: c.map((e) => {
897
+ let r = n.find((t) => t.id === e.tournamentId);
898
+ if (!r) throw t("unavailable");
899
+ return Oe(e, String(r.name));
900
+ })
901
+ };
902
+ })));
903
+ },
904
+ eraseSubject: (e) => {
905
+ let i, a;
906
+ try {
907
+ if (!e || !r(e.tenantId) || !r(e.subjectId) || !["user", "guest"].includes(e.kind)) throw t("invalid_input");
908
+ i = e.tenantId, a = e.subjectId;
909
+ } catch (e) {
910
+ return k.fail(P(e));
911
+ }
912
+ return F(async () => (await G(i, a), n.transactional(async (e) => {
913
+ let n = await K(e, i, a, !0);
914
+ await De(e, i);
915
+ let r = await Ne(e, i);
916
+ await q.privacyFences(e, i), await q.eraseInTransaction(e, i, a);
917
+ let o = await X(e, C, i, a), s = await X(e, T, i, a), c = await X(e, E, i, a), l = (await Q(e, i)).filter((e) => e.state !== "active").map((e) => ({
918
+ row: e,
919
+ summary: $(e.summary, i, String(e.board), String(e.id))
920
+ }));
921
+ for (let { row: n, summary: r } of l) if (r.top.some((e) => e.ownerId === a) && !await e.update(S.tableName, String(n.id), { summary: {
922
+ ...r,
923
+ top: r.top.filter((e) => e.ownerId !== a)
924
+ } })) throw t("unavailable");
925
+ for (let t of s) await e.delete(T.tableName, String(t.id));
926
+ for (let t of o) await e.delete(C.tableName, String(t.id));
927
+ for (let t of await X(e, y, i, a)) await e.delete(y.tableName, String(t.id));
928
+ for (let t of await X(e, b, i, a)) await e.delete(b.tableName, String(t.id));
929
+ let u = await e.query(N(x).where(M("tenantId", i)).limit(B + 1).descriptor);
930
+ if (u.length > B) throw t("limit_exceeded");
931
+ for (let t of u) {
932
+ let n = Array.isArray(t.movements) ? t.movements : [];
933
+ n.some((e) => e.ownerId === a) && await e.update(x.tableName, String(t.id), { movements: n.filter((e) => e.ownerId !== a) });
934
+ }
935
+ for (let n of c) {
936
+ let i = r.find((e) => e.id === n.tournamentId);
937
+ if (!i || !Number.isSafeInteger(i.numEntries) || Number(i.numEntries) < 1 || !await e.update(D.tableName, String(i.id), { numEntries: Number(i.numEntries) - 1 })) throw t("unavailable");
938
+ await e.delete(E.tableName, String(n.id));
939
+ }
940
+ await e.update(w.tableName, String(n.id), {
941
+ subjectId: null,
942
+ erased: !0
943
+ });
944
+ })));
945
+ }
946
+ };
947
+ };
948
+ export { pe as acceptLeaderboardSubmission, ge as dataStoreLeaderboards, he as resolveLeaderboardStoreOptions };