@voltro/plugin-progression 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 (97) hide show
  1. package/CHANGELOG.md +24492 -0
  2. package/LICENSE +61 -0
  3. package/README.md +478 -2
  4. package/SECURITY.md +56 -0
  5. package/THIRD-PARTY-NOTICES.md +9841 -0
  6. package/dist/achievementComponents.js +91 -0
  7. package/dist/achievementStore.js +602 -0
  8. package/dist/achievementTables.entity.js +97 -0
  9. package/dist/achievements.d.ts +188 -0
  10. package/dist/achievements.js +204 -0
  11. package/dist/capture.js +63 -0
  12. package/dist/cmsQuests.d.ts +91 -0
  13. package/dist/cmsQuests.js +82 -0
  14. package/dist/components.d.ts +172 -0
  15. package/dist/components.js +4 -0
  16. package/dist/curve.d.ts +27 -0
  17. package/dist/curve.js +37 -0
  18. package/dist/daily.d.ts +152 -0
  19. package/dist/daily.js +125 -0
  20. package/dist/dailyStore.js +420 -0
  21. package/dist/dailySystem.fixture.js +137 -0
  22. package/dist/dailyTables.entity.js +89 -0
  23. package/dist/declarationFixtures.js +142 -0
  24. package/dist/errors.d.ts +13 -0
  25. package/dist/errors.js +19 -0
  26. package/dist/index.d.ts +1833 -0
  27. package/dist/index.js +19 -0
  28. package/dist/pass.d.ts +186 -0
  29. package/dist/pass.js +121 -0
  30. package/dist/passRules.js +95 -0
  31. package/dist/passStore.js +484 -0
  32. package/dist/passTables.entity.js +95 -0
  33. package/dist/plugin.js +1085 -0
  34. package/dist/port.js +4 -0
  35. package/dist/progressionStore.js +705 -0
  36. package/dist/questComponents.js +162 -0
  37. package/dist/questPort.d.ts +126 -0
  38. package/dist/questPort.js +4 -0
  39. package/dist/questRefresh.js +55 -0
  40. package/dist/questRefresh.server.js +125 -0
  41. package/dist/questRerollJournal.js +76 -0
  42. package/dist/questStore.js +591 -0
  43. package/dist/questTables.entity.js +116 -0
  44. package/dist/quests.d.ts +142 -0
  45. package/dist/quests.js +152 -0
  46. package/dist/rank-app/schedules/progression.dispatchRankClosures.cron.tsx +19 -0
  47. package/dist/rank-app/workflows/progression.closeRankSeason.workflow.server.tsx +10 -0
  48. package/dist/rank-app/workflows/progression.closeRankSeason.workflow.tsx +1 -0
  49. package/dist/rankClosure.d.ts +69 -0
  50. package/dist/rankClosure.js +34 -0
  51. package/dist/rankClosure.server.js +138 -0
  52. package/dist/rankClosureWorkflow.d.ts +34 -0
  53. package/dist/rankClosureWorkflow.js +15 -0
  54. package/dist/rankReader.server.js +56 -0
  55. package/dist/rankRewardParent.server.js +64 -0
  56. package/dist/rankSeasons.d.ts +144 -0
  57. package/dist/rankSeasons.js +90 -0
  58. package/dist/rankStore.js +520 -0
  59. package/dist/rankSystem.fixture.js +169 -0
  60. package/dist/rankTables.entity.js +100 -0
  61. package/dist/ranks.d.ts +167 -0
  62. package/dist/ranks.js +218 -0
  63. package/dist/resourceStore.js +463 -0
  64. package/dist/resourceTables.entity.js +88 -0
  65. package/dist/resources.d.ts +105 -0
  66. package/dist/resources.js +59 -0
  67. package/dist/reward-app/schedules/progression.dispatchRewards.cron.tsx +19 -0
  68. package/dist/reward-app/workflows/progression.deliverReward.workflow.server.tsx +10 -0
  69. package/dist/reward-app/workflows/progression.deliverReward.workflow.tsx +1 -0
  70. package/dist/reward.d.ts +27 -0
  71. package/dist/reward.js +38 -0
  72. package/dist/rewardDelivery.d.ts +163 -0
  73. package/dist/rewardDelivery.js +37 -0
  74. package/dist/rewardDelivery.server.js +429 -0
  75. package/dist/rewardDeliveryRecord.js +47 -0
  76. package/dist/rewardDeliveryWorkflow.d.ts +36 -0
  77. package/dist/rewardDeliveryWorkflow.js +15 -0
  78. package/dist/rpc.d.ts +880 -0
  79. package/dist/rpc.js +497 -0
  80. package/dist/server.d.ts +2812 -0
  81. package/dist/server.js +21 -0
  82. package/dist/stats.js +44 -0
  83. package/dist/strategies.d.ts +131 -0
  84. package/dist/strategies.js +4 -0
  85. package/dist/systemFixtures.js +473 -0
  86. package/dist/tables.entity.js +154 -0
  87. package/dist/testing.d.ts +1566 -0
  88. package/dist/testing.js +11 -0
  89. package/dist/track.js +71 -0
  90. package/dist/tutorial.d.ts +157 -0
  91. package/dist/tutorial.js +109 -0
  92. package/dist/tutorialStore.js +495 -0
  93. package/dist/tutorialSystem.fixture.js +99 -0
  94. package/dist/tutorialTables.entity.js +90 -0
  95. package/dist/web.d.ts +363 -0
  96. package/dist/web.js +6 -0
  97. package/package.json +167 -4
@@ -0,0 +1,484 @@
1
+ import { ProgressionError as e, progressionError as t } from "./errors.js";
2
+ import { captureArguments as n, identifier as r, integer as i, list as a, object as o, progressValue as s } from "./capture.js";
3
+ import { captureRewards as c } from "./reward.js";
4
+ import { capturePassState as l, claimablePassTiers as u, defaultPassCatchUp as d, defineSeasonPass as f, passInitialState as p, passTier as m, resolvePassCatchUp as h } from "./pass.js";
5
+ import { admitRewardDeliveryRecord as g } from "./rewardDeliveryRecord.js";
6
+ import { questHash as _ } from "./questStore.js";
7
+ import { applyPassIntent as v, capturePassIntent as y } from "./passRules.js";
8
+ import { passDefinitionsTable as b, passLedgerTable as x, passOperationsTable as S, passRewardsTable as C, passStatesTable as w, passSubjectsTable as T } from "./passTables.entity.js";
9
+ import { Effect as E } from "effect";
10
+ import { and as D, eq as O, queryFor as k } from "@voltro/database";
11
+ // src/passStore.ts
12
+ var A = (e) => {
13
+ let n = o(e, [
14
+ "definitions",
15
+ "allowedServices",
16
+ "now",
17
+ "maxHistoryRows",
18
+ "maxPendingRewards",
19
+ "strategies"
20
+ ]), s = o(n.strategies ?? {}, ["passCatchUp", "version"]), c = Object.freeze(a(n.definitions, 64).map((e) => f(e))), l = Object.freeze(a(n.allowedServices ?? [], 256).map(r)), u = n.now ?? Date.now, p = s.passCatchUp ?? d;
21
+ if (!c.length || new Set(c.map((e) => e.id)).size !== c.length || new Set(l).size !== l.length || typeof u != "function" || typeof p != "function" || p !== d && s.version === void 0) throw t("invalid_input");
22
+ return Object.freeze({
23
+ definitions: c,
24
+ allowedServices: l,
25
+ now: u,
26
+ maxHistoryRows: i(n.maxHistoryRows ?? 1e4, 1, 1e5),
27
+ maxPendingRewards: i(n.maxPendingRewards ?? 1e4, 1, 1e5),
28
+ strategies: Object.freeze({
29
+ passCatchUp: p,
30
+ version: r(s.version ?? "default.v1")
31
+ })
32
+ });
33
+ }, j = (e, ...t) => e + _(t).slice(0, 56), M = (e) => i(e instanceof Date ? e.getTime() : typeof e == "string" ? Date.parse(e) : NaN, 0, 864e13), N = (n) => E.tryPromise({
34
+ try: n,
35
+ catch: (n) => n instanceof e ? n : t("unavailable")
36
+ }), P = (f, P) => {
37
+ let F = A(P), I = new Map(F.definitions.map((e) => [e.id, e])), L = new Set(F.allowedServices), R = (e) => {
38
+ let n = I.get(e);
39
+ if (!n) throw t("invalid_input");
40
+ return n;
41
+ }, z = (e) => {
42
+ if (e.type !== "system" && !(e.type === "service" && L.has(e.service))) throw t("forbidden");
43
+ }, B = (e) => {
44
+ if (e.type !== "user" || !e.tenantId) throw t("forbidden");
45
+ return {
46
+ tenantId: r(e.tenantId),
47
+ ownerId: r(e.id)
48
+ };
49
+ }, V = (e, t) => j("pps_", e, t), H = (e, t) => D(O("tenantId", e), O("ownerKey", V(e, t))), U = (e, t, n) => j("ppv_", e, t, n.id, String(n.version)), W = async (e, n) => {
50
+ if ((await f.insertIgnoreWithOutcome(e.tableName, n, { conflictColumns: ["id"] })).outcome !== "inserted" && !(await f.query(k(e).where(O("id", n.id)).limit(1).descriptor))[0]) throw t("unavailable");
51
+ }, G = (e, t) => W(T, {
52
+ id: V(e, t),
53
+ tenantId: e,
54
+ ownerId: t,
55
+ erased: !1,
56
+ sequence: 0,
57
+ admission: 0
58
+ }), K = (e, n, r) => {
59
+ if (e) {
60
+ if (e.id !== V(n, r) || e.tenantId !== n || typeof e.erased != "boolean") throw t("invalid_record");
61
+ if (e.erased) throw e.ownerId === null ? t("erased") : t("invalid_record");
62
+ if (e.ownerId !== r) throw t("invalid_record");
63
+ i(e.sequence, 0, 2147483647);
64
+ }
65
+ }, q = async (e, n, r) => {
66
+ if (await e.updateMany(T.tableName, { admission: 0 }, { where: O("id", V(n, r)) }) !== 1) throw t("invalid_record");
67
+ let i = (await e.query(k(T).where(O("id", V(n, r))).limit(1).descriptor))[0];
68
+ if (K(i, n, r), !i) throw t("invalid_record");
69
+ return i;
70
+ }, J = async (e, n, r, i) => {
71
+ let a = n === C ? F.maxPendingRewards : F.maxHistoryRows, o = await e.query(k(n).where(H(r, i)).limit(a + 1).descriptor);
72
+ if (o.length > a) throw t("limit_exceeded");
73
+ if (o.some((e) => e.tenantId !== r || e.ownerKey !== V(r, i))) throw t("invalid_record");
74
+ return o;
75
+ }, Y = async (e, n, r, i) => {
76
+ let a = j("ppd_", n, r.id, String(r.version));
77
+ if (i && await e.updateMany(b.tableName, { admission: 0 }, { where: O("id", a) }) !== 1) throw t("invalid_record");
78
+ let o = (await e.query(k(b).where(O("id", a)).limit(1).descriptor))[0];
79
+ if (!o || o.tenantId !== n || o.passId !== r.id || o.version !== r.version || o.rulesVersion !== F.strategies.version || _(o.config) !== _(r)) throw t("conflict");
80
+ }, X = (e, n, r, i) => {
81
+ if (e.id !== U(n, r, i) || e.tenantId !== n || e.ownerId !== r || e.ownerKey !== V(n, r) || e.passId !== i.id || e.version !== i.version) throw t("invalid_record");
82
+ let a = l(e.state, i);
83
+ if (M(e.updatedAt) !== a.updatedAt) throw t("invalid_record");
84
+ return a;
85
+ }, Z = (e) => {
86
+ let n = o(e.receipt, [
87
+ "operationId",
88
+ "kind",
89
+ "after",
90
+ "claims",
91
+ "rewardsQueued",
92
+ "at"
93
+ ]), s = o(n.after), u = R(r(s.passId)), d = l(n.after, u);
94
+ if (e.state !== "committed" || n.operationId !== e.id || n.kind !== "xp" && n.kind !== "premium" && n.kind !== "claim" && n.kind !== "close" || n.at !== M(e.at) || n.at !== d.updatedAt) throw t("invalid_record");
95
+ let f = Object.freeze(a(n.claims, 512).map((e) => {
96
+ let n = o(e, [
97
+ "tier",
98
+ "track",
99
+ "rewards"
100
+ ]), r = i(n.tier, 1, u.tiers);
101
+ if (n.track !== "free" && n.track !== "premium" || _(n.rewards) !== _(u.tracks[n.track][r - 1])) throw t("invalid_record");
102
+ return Object.freeze({
103
+ tier: r,
104
+ track: n.track,
105
+ rewards: c(n.rewards, 64)
106
+ });
107
+ }));
108
+ if (new Set(f.map((e) => `${e.track}:${e.tier}`)).size !== f.length || n.rewardsQueued !== f.reduce((e, t) => e + t.rewards.length, 0)) throw t("invalid_record");
109
+ return Object.freeze({
110
+ operationId: r(e.id),
111
+ kind: n.kind,
112
+ after: d,
113
+ claims: f,
114
+ rewardsQueued: i(n.rewardsQueued, 0, 32768),
115
+ at: d.updatedAt
116
+ });
117
+ }, ee = async (e, n, r, i, a) => {
118
+ let o = (await e.query(k(S).where(O("id", n)).limit(1).descriptor))[0];
119
+ if (!o) return;
120
+ if (o.state === "erased") throw t("erased");
121
+ if (o.tenantId !== i || o.ownerKey !== V(i, a) || o.digest !== r) throw t("conflict");
122
+ if (o.state === "committed" && o.linkedOperationId === null) return Z(o);
123
+ if (o.state !== "replayed" || o.receipt !== null || typeof o.linkedOperationId != "string") throw t("invalid_record");
124
+ let s = (await e.query(k(S).where(O("id", o.linkedOperationId)).limit(1).descriptor))[0];
125
+ if (!s || s.tenantId !== i || s.ownerKey !== V(i, a) || s.digest !== r || s.originKey !== o.originKey || s.linkedOperationId !== null) throw t("invalid_record");
126
+ return Z(s);
127
+ }, Q = (a, c, l) => {
128
+ try {
129
+ let e = n(a), u = o(c, l === "xp" ? [
130
+ "tenantId",
131
+ "ownerId",
132
+ "passId",
133
+ "amount",
134
+ "source",
135
+ "originId",
136
+ "requestId"
137
+ ] : l === "premium" ? [
138
+ "tenantId",
139
+ "ownerId",
140
+ "passId",
141
+ "offerId",
142
+ "fulfillmentId",
143
+ "requestId"
144
+ ] : l === "claim" ? [
145
+ "passId",
146
+ "tier",
147
+ "track",
148
+ "requestId"
149
+ ] : [
150
+ "tenantId",
151
+ "ownerId",
152
+ "passId",
153
+ "requestId"
154
+ ]), { tenantId: d, ownerId: m } = l === "claim" ? B(e) : (z(e), {
155
+ tenantId: r(u.tenantId),
156
+ ownerId: r(u.ownerId)
157
+ }), g = R(r(u.passId)), E = r(u.requestId), D = l === "xp" ? y({
158
+ kind: l,
159
+ amount: String(s(u.amount)),
160
+ effectiveAmount: String(s(u.amount)),
161
+ source: u.source,
162
+ originId: u.originId
163
+ }, g) : l === "premium" ? y({
164
+ kind: l,
165
+ offerId: u.offerId,
166
+ fulfillmentId: u.fulfillmentId
167
+ }, g) : l === "claim" ? y({
168
+ kind: l,
169
+ tier: u.tier,
170
+ track: u.track
171
+ }, g) : { kind: l }, A = _({
172
+ tenantId: d,
173
+ ownerId: m,
174
+ passId: g.id,
175
+ version: g.version,
176
+ intent: D
177
+ }), M = j("ppo_", d, m, E), P = D.kind === "xp" ? [
178
+ D.kind,
179
+ D.source,
180
+ D.originId
181
+ ] : D.kind === "premium" ? [D.kind, D.fulfillmentId] : D.kind === "claim" ? [
182
+ D.kind,
183
+ D.track,
184
+ String(D.tier)
185
+ ] : [D.kind], I = j("ppk_", d, m, g.id, String(g.version), ...P);
186
+ return N(async () => {
187
+ await G(d, m);
188
+ let e = async (e) => {
189
+ await q(e, d, m);
190
+ let n = await ee(e, M, A, d, m);
191
+ if (n) return n;
192
+ let r = await J(e, S, d, m), i = r.find((e) => e.originKey === I && e.state === "committed");
193
+ if (!i) return;
194
+ if (i.digest !== A || i.linkedOperationId !== null) throw t("conflict");
195
+ let a = Z(i);
196
+ if (r.length >= F.maxHistoryRows) throw t("limit_exceeded");
197
+ return await e.insert(S.tableName, {
198
+ id: M,
199
+ tenantId: d,
200
+ ownerKey: V(d, m),
201
+ originKey: I,
202
+ state: "replayed",
203
+ linkedOperationId: a.operationId,
204
+ digest: A,
205
+ receipt: null,
206
+ at: new Date(a.at)
207
+ }), a;
208
+ }, n = await f.transactional(e);
209
+ if (n) return n;
210
+ let r = i(F.now(), 0, 864e13), a = D.kind === "xp" ? y({
211
+ ...D,
212
+ effectiveAmount: h({
213
+ pass: g,
214
+ amount: D.amount,
215
+ at: r
216
+ }, F.strategies.passCatchUp)
217
+ }, g) : D;
218
+ return await W(b, {
219
+ id: j("ppd_", d, g.id, String(g.version)),
220
+ tenantId: d,
221
+ passId: g.id,
222
+ version: g.version,
223
+ config: g,
224
+ rulesVersion: F.strategies.version,
225
+ admission: 0
226
+ }), f.transactional(async (n) => {
227
+ let o = await e(n);
228
+ if (o) return o;
229
+ let s = await q(n, d, m);
230
+ await Y(n, d, g, !0);
231
+ let c = await J(n, x, d, m), u = await J(n, S, d, m), f = await J(n, C, d, m);
232
+ if (c.length >= F.maxHistoryRows || u.length >= F.maxHistoryRows) throw t("limit_exceeded");
233
+ let h = U(d, m, g), y = (await n.query(k(w).where(O("id", h)).limit(1).descriptor))[0], b = y ? X(y, d, m, g) : p(g), E = c.filter((e) => e.passId === g.id).sort((e, t) => Number(e.sequence) - Number(t.sequence)).at(-1);
234
+ if (E && (!y || _(E.after) !== _(b)) || !E && y) throw t("invalid_record");
235
+ let D = v(g, b, a, r), N = D.claims.reduce((e, t) => e + t.rewards.length, 0);
236
+ if (f.length + N > F.maxPendingRewards) throw t("limit_exceeded");
237
+ let P = i(s.sequence, 0, 2147483646) + 1, L = Object.freeze({
238
+ operationId: M,
239
+ kind: l,
240
+ after: D.after,
241
+ claims: D.claims,
242
+ rewardsQueued: N,
243
+ at: r
244
+ });
245
+ y ? await n.update(w.tableName, h, {
246
+ state: D.after,
247
+ updatedAt: new Date(r)
248
+ }) : await n.insert(w.tableName, {
249
+ id: h,
250
+ tenantId: d,
251
+ ownerId: m,
252
+ ownerKey: V(d, m),
253
+ passId: g.id,
254
+ version: g.version,
255
+ state: D.after,
256
+ updatedAt: new Date(r)
257
+ }), await n.insert(x.tableName, {
258
+ id: j("ppl_", M),
259
+ tenantId: d,
260
+ ownerId: m,
261
+ ownerKey: V(d, m),
262
+ passId: g.id,
263
+ version: g.version,
264
+ sequence: P,
265
+ operationId: M,
266
+ intent: a,
267
+ before: b,
268
+ after: D.after,
269
+ at: new Date(r)
270
+ }), await n.insert(S.tableName, {
271
+ id: M,
272
+ tenantId: d,
273
+ ownerKey: V(d, m),
274
+ originKey: I,
275
+ state: "committed",
276
+ linkedOperationId: null,
277
+ digest: A,
278
+ receipt: L,
279
+ at: new Date(r)
280
+ });
281
+ for (let e of D.claims) for (let [t, i] of e.rewards.entries()) await n.insert(C.tableName, {
282
+ id: j("ppr_", d, m, g.id, String(g.version), e.track, String(e.tier), String(t)),
283
+ tenantId: d,
284
+ ownerId: m,
285
+ ownerKey: V(d, m),
286
+ passId: g.id,
287
+ version: g.version,
288
+ tier: e.tier,
289
+ track: e.track,
290
+ operationId: M,
291
+ reward: i,
292
+ state: "pending",
293
+ createdAt: new Date(r),
294
+ deliveredAt: null,
295
+ deliveryIntent: null,
296
+ deliveryDigest: null,
297
+ deliveryReceipt: null
298
+ });
299
+ return await n.update(T.tableName, V(d, m), { sequence: P }), L;
300
+ });
301
+ });
302
+ } catch (n) {
303
+ return E.fail(n instanceof e ? n : t("invalid_input"));
304
+ }
305
+ }, te = (r) => {
306
+ try {
307
+ let { tenantId: e, ownerId: a } = B(n(r));
308
+ return N(async () => {
309
+ let n = i(F.now(), 0, 864e13);
310
+ return f.transactional(async (r) => {
311
+ let i = (await r.query(k(T).where(O("id", V(e, a))).forUpdate().limit(1).descriptor))[0];
312
+ K(i, e, a);
313
+ let o = await J(r, w, e, a), s = await J(r, x, e, a);
314
+ return Object.freeze(F.definitions.map((r) => {
315
+ let i = o.find((e) => e.passId === r.id), c = i ? X(i, e, a, r) : p(r), l = s.filter((e) => e.passId === r.id).sort((e, t) => Number(e.sequence) - Number(t.sequence)).at(-1);
316
+ if (l && (!i || _(l.after) !== _(c)) || !l && i || i && c.updatedAt > n) throw t("invalid_record");
317
+ let d = n >= r.from && n < r.until && !c.closed;
318
+ return Object.freeze({
319
+ ...c,
320
+ tier: m(r, c.xp),
321
+ from: r.from,
322
+ until: r.until,
323
+ observedAt: n,
324
+ active: d,
325
+ premiumOffer: r.premiumOffer,
326
+ claimable: d ? u(r, c) : Object.freeze([])
327
+ });
328
+ }));
329
+ });
330
+ });
331
+ } catch (n) {
332
+ return E.fail(n instanceof e ? n : t("invalid_input"));
333
+ }
334
+ }, $ = (n, i) => {
335
+ try {
336
+ let e = o(n, [
337
+ "tenantId",
338
+ "subjectId",
339
+ "kind"
340
+ ]), a = r(e.tenantId), s = r(e.subjectId);
341
+ if (e.kind !== "user" && e.kind !== "guest") throw t("invalid_input");
342
+ return N(async () => (await G(a, s), f.transactional(async (e) => {
343
+ if (await e.updateMany(T.tableName, { admission: 0 }, { where: O("id", V(a, s)) }) !== 1) throw t("invalid_record");
344
+ let n = (await e.query(k(T).where(O("id", V(a, s))).limit(1).descriptor))[0];
345
+ if (!n || n.tenantId !== a || typeof n.erased != "boolean" || n.erased && n.ownerId !== null || !n.erased && n.ownerId !== s) throw t("invalid_record");
346
+ let r = await J(e, w, a, s), o = await J(e, x, a, s), c = await J(e, S, a, s), l = await J(e, C, a, s);
347
+ if (!i) return {
348
+ passes: r.map((e) => e.state),
349
+ history: o.map((e) => ({
350
+ intent: e.intent,
351
+ before: e.before,
352
+ after: e.after
353
+ })),
354
+ requests: c.map((e) => e.receipt),
355
+ rewards: l.map((e) => ({
356
+ reward: e.reward,
357
+ state: e.state,
358
+ deliveryIntent: e.deliveryIntent,
359
+ deliveryReceipt: e.deliveryReceipt
360
+ }))
361
+ };
362
+ await e.deleteMany(w.tableName, { where: H(a, s) }), await e.updateMany(x.tableName, {
363
+ ownerId: null,
364
+ ownerKey: null,
365
+ intent: null,
366
+ before: null,
367
+ after: null
368
+ }, { where: H(a, s) }), await e.updateMany(S.tableName, {
369
+ ownerKey: null,
370
+ originKey: null,
371
+ state: "erased",
372
+ linkedOperationId: null,
373
+ digest: null,
374
+ receipt: null
375
+ }, { where: H(a, s) }), await e.updateMany(C.tableName, {
376
+ ownerId: null,
377
+ ownerKey: null,
378
+ reward: null,
379
+ state: "erased",
380
+ deliveredAt: null,
381
+ deliveryIntent: null,
382
+ deliveryDigest: null,
383
+ deliveryReceipt: null
384
+ }, { where: H(a, s) }), await e.update(T.tableName, V(a, s), {
385
+ ownerId: null,
386
+ erased: !0
387
+ });
388
+ })));
389
+ } catch (n) {
390
+ return E.fail(n instanceof e ? n : t("invalid_input"));
391
+ }
392
+ }, ne = (i, a, o, s) => {
393
+ try {
394
+ z(n(i));
395
+ let e = r(a), c = r(o);
396
+ return N(async () => (await G(e, c), f.transactional(async (n) => {
397
+ let i = await q(n, e, c), a = await J(n, x, e, c), o = await J(n, S, e, c), l = await J(n, C, e, c), u = /* @__PURE__ */ new Map(), f = /* @__PURE__ */ new Set(), m = [...a].sort((e, t) => Number(e.sequence) - Number(t.sequence)), b = 0;
398
+ if (m.length !== i.sequence) throw t("invalid_record");
399
+ for (let [i, a] of m.entries()) {
400
+ let s = R(r(a.passId)), m = u.get(s.id) ?? p(s), x = y(a.intent, s), S = M(a.at), C = o.find((e) => e.id === a.operationId);
401
+ if (await Y(n, e, s, !1), a.sequence !== i + 1 || a.id !== j("ppl_", r(a.operationId)) || a.ownerId !== c || a.version !== s.version || _(a.before) !== _(m) || !C || C.linkedOperationId !== null || x.kind === "xp" && F.strategies.passCatchUp === d && h({
402
+ pass: s,
403
+ amount: x.amount,
404
+ at: S
405
+ }) !== x.effectiveAmount) throw t("invalid_record");
406
+ let w = x.kind === "xp" ? {
407
+ ...x,
408
+ effectiveAmount: x.amount
409
+ } : x, T = _({
410
+ tenantId: e,
411
+ ownerId: c,
412
+ passId: s.id,
413
+ version: s.version,
414
+ intent: w
415
+ }), E = x.kind === "xp" ? [
416
+ x.kind,
417
+ x.source,
418
+ x.originId
419
+ ] : x.kind === "premium" ? [x.kind, x.fulfillmentId] : x.kind === "claim" ? [
420
+ x.kind,
421
+ x.track,
422
+ String(x.tier)
423
+ ] : [x.kind], D = j("ppk_", e, c, s.id, String(s.version), ...E);
424
+ if (C.digest !== T || C.originKey !== D || f.has(D)) throw t("invalid_record");
425
+ let O = v(s, m, x, S), k = Z(C);
426
+ if (k.kind !== x.kind || _(O.after) !== _(a.after) || _(O.after) !== _(k.after) || _(O.claims) !== _(k.claims)) throw t("invalid_record");
427
+ let A = l.filter((e) => e.operationId === a.operationId);
428
+ if (A.length !== k.rewardsQueued) throw t("invalid_record");
429
+ for (let n of O.claims) for (let [r, i] of n.rewards.entries()) {
430
+ let a = A.find((t) => t.id === j("ppr_", e, c, s.id, String(s.version), n.track, String(n.tier), String(r)));
431
+ if (!a || a.ownerId !== c || a.passId !== s.id || a.version !== s.version || a.track !== n.track || a.tier !== n.tier || _(a.reward) !== _(i) || M(a.createdAt) !== S) throw t("invalid_record");
432
+ g(a, "pass", _), b++;
433
+ }
434
+ f.add(D), u.set(s.id, O.after);
435
+ }
436
+ if (b !== l.length) throw t("invalid_record");
437
+ for (let e of o) if (e.state === "replayed") {
438
+ let n = o.find((t) => t.id === e.linkedOperationId);
439
+ if (!n || n.state !== "committed" || n.linkedOperationId !== null || n.digest !== e.digest || n.originKey !== e.originKey || e.receipt !== null || M(e.at) !== M(n.at)) throw t("invalid_record");
440
+ } else if (e.state !== "committed" || !m.some((t) => t.operationId === e.id)) throw t("invalid_record");
441
+ let T = await J(n, w, e, c), E = /* @__PURE__ */ new Map();
442
+ for (let n of T) {
443
+ let i = R(r(n.passId));
444
+ if (E.has(i.id)) throw t("invalid_record");
445
+ E.set(i.id, X(n, e, c, i));
446
+ }
447
+ let D = E.size === u.size && [...u].every(([e, t]) => _(t) === _(E.get(e) ?? null));
448
+ if (s && !D) {
449
+ await n.deleteMany(w.tableName, { where: H(e, c) });
450
+ for (let [t, r] of u) await n.insert(w.tableName, {
451
+ id: U(e, c, R(t)),
452
+ tenantId: e,
453
+ ownerId: c,
454
+ ownerKey: V(e, c),
455
+ passId: t,
456
+ version: r.version,
457
+ state: r,
458
+ updatedAt: new Date(r.updatedAt)
459
+ });
460
+ }
461
+ return Object.freeze({
462
+ operations: m.length,
463
+ passes: u.size,
464
+ rewardRows: b,
465
+ matches: s ? !0 : D
466
+ });
467
+ })));
468
+ } catch (n) {
469
+ return E.fail(n instanceof e ? n : t("invalid_input"));
470
+ }
471
+ };
472
+ return Object.freeze({
473
+ applyXp: (e, t) => Q(e, t, "xp"),
474
+ grantPremium: (e, t) => Q(e, t, "premium"),
475
+ claim: (e, t) => Q(e, t, "claim"),
476
+ close: (e, t) => Q(e, t, "close"),
477
+ mine: te,
478
+ exportSubject: (e) => $(e, !1),
479
+ eraseSubject: (e) => E.asVoid($(e, !0)),
480
+ auditPasses: (e, t, n) => ne(e, t, n, !1),
481
+ rebuildPasses: (e, t, n) => ne(e, t, n, !0)
482
+ });
483
+ };
484
+ export { P as dataStoreSeasonPasses, A as resolvePassOptions };
@@ -0,0 +1,95 @@
1
+ import { boolean as e, id as t, integer as n, json as r, table as i, text as a, timestamp as o } from "@voltro/database";
2
+ // src/passTables.entity.ts
3
+ var s = () => a().maxLength(120).externalId().sensitive("pii"), c = () => a().maxLength(120).externalId().sensitive("pii"), l = () => a().maxLength(64).nullable().serverOnly(), u = i("_voltro_prog_pass_definitions", {
4
+ id: t({ prefix: "ppd" }),
5
+ tenantId: s(),
6
+ passId: a().maxLength(120).safe(),
7
+ version: n().safe(),
8
+ config: r().serverOnly(),
9
+ rulesVersion: a().maxLength(120).safe(),
10
+ admission: n().serverOnly()
11
+ }).index([
12
+ "tenantId",
13
+ "passId",
14
+ "version"
15
+ ]), d = i("_voltro_prog_pass_subjects", {
16
+ id: t({ prefix: "pps" }),
17
+ tenantId: s(),
18
+ ownerId: c().nullable(),
19
+ erased: e().serverOnly(),
20
+ sequence: n().serverOnly(),
21
+ admission: n().serverOnly()
22
+ }).index(["tenantId", "ownerId"]), f = i("_voltro_prog_pass", {
23
+ id: t({ prefix: "ppv" }),
24
+ tenantId: s(),
25
+ ownerId: c(),
26
+ ownerKey: l(),
27
+ passId: a().maxLength(120).safe(),
28
+ version: n().safe(),
29
+ state: r().serverOnly(),
30
+ updatedAt: o().safe()
31
+ }).index(["tenantId", "ownerKey"]), p = i("_voltro_prog_pass_ledger", {
32
+ id: t({ prefix: "ppl" }),
33
+ tenantId: s(),
34
+ ownerId: c().nullable(),
35
+ ownerKey: l(),
36
+ passId: a().maxLength(120).safe(),
37
+ version: n().safe(),
38
+ sequence: n().serverOnly(),
39
+ operationId: a().maxLength(64).safe(),
40
+ intent: r().nullable().serverOnly(),
41
+ before: r().nullable().serverOnly(),
42
+ after: r().nullable().serverOnly(),
43
+ at: o().safe()
44
+ }).index(["tenantId", "ownerKey"]), m = i("_voltro_prog_pass_operations", {
45
+ id: t({ prefix: "ppo" }),
46
+ tenantId: s(),
47
+ ownerKey: l(),
48
+ originKey: a().maxLength(64).nullable().serverOnly(),
49
+ state: a().maxLength(16).oneOf([
50
+ "committed",
51
+ "replayed",
52
+ "erased"
53
+ ]).serverOnly(),
54
+ linkedOperationId: a().maxLength(64).nullable().serverOnly(),
55
+ digest: a().maxLength(64).nullable().serverOnly(),
56
+ receipt: r().nullable().serverOnly(),
57
+ at: o().safe()
58
+ }).index([
59
+ "tenantId",
60
+ "ownerKey",
61
+ "originKey"
62
+ ]), h = i("_voltro_prog_pass_rewards", {
63
+ id: t({ prefix: "ppr" }),
64
+ tenantId: s(),
65
+ ownerId: c().nullable(),
66
+ ownerKey: l(),
67
+ passId: a().maxLength(120).safe(),
68
+ version: n().safe(),
69
+ tier: n().safe(),
70
+ track: a().maxLength(16).oneOf(["free", "premium"]).safe(),
71
+ operationId: a().maxLength(64).safe(),
72
+ reward: r().nullable().serverOnly(),
73
+ state: a().maxLength(16).oneOf([
74
+ "pending",
75
+ "delivered",
76
+ "erased"
77
+ ]).serverOnly(),
78
+ createdAt: o().safe(),
79
+ deliveredAt: o().nullable().safe(),
80
+ deliveryIntent: r().nullable().serverOnly(),
81
+ deliveryDigest: a().maxLength(64).nullable().serverOnly(),
82
+ deliveryReceipt: r().nullable().serverOnly()
83
+ }).index([
84
+ "tenantId",
85
+ "ownerKey",
86
+ "state"
87
+ ]), g = [
88
+ u,
89
+ d,
90
+ f,
91
+ p,
92
+ m,
93
+ h
94
+ ];
95
+ export { u as passDefinitionsTable, p as passLedgerTable, m as passOperationsTable, h as passRewardsTable, f as passStatesTable, d as passSubjectsTable, g as passTables };