@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,91 @@
1
+ import { PlayerAchievementSchema as e } from "./rpc.js";
2
+ import { useAchievements as t } from "./web.js";
3
+ import { Schema as n } from "effect";
4
+ import { useId as r } from "react";
5
+ import { useUiStrings as i } from "@voltro/ui";
6
+ import { jsx as a, jsxs as o } from "react/jsx-runtime";
7
+ // src/achievementComponents.tsx
8
+ var s = n.decodeUnknownSync(n.Array(e), { onExcessProperty: "error" }), c = (e) => /^[A-Za-z0-9][A-Za-z0-9._:-]{0,119}$/.test(e), l = (e) => /^(0|[1-9][0-9]{0,18})$/.test(e) && BigInt(e) <= 9223372036854775807n, u = (e) => {
9
+ try {
10
+ if (!Array.isArray(e) || e.length > 256) return;
11
+ let t = s(e);
12
+ return new Set(t.map((e) => JSON.stringify([
13
+ e.achievementId,
14
+ e.version,
15
+ e.tierId
16
+ ]))).size !== t.length || t.some((e) => !c(e.achievementId) || !c(e.tierId) || !Number.isSafeInteger(e.version) || e.version < 1 || e.version > 1e6 || e.unlocked !== (e.unlockedAt !== null) || e.unlockedAt !== null && (!Number.isSafeInteger(e.unlockedAt) || e.unlockedAt < 0 || e.unlockedAt > 864e13) || !e.unlocked && e.platform !== null || e.platform !== null && Object.values(e.platform).some((e) => e !== void 0 && !c(e)) || e.progress.length < 1 || e.progress.length > 64 || e.progress.some((e) => !c(e.stat) || !l(e.value) || !l(e.target) || e.target === "0" || e.met !== BigInt(e.value) >= BigInt(e.target) || e.period === "lifetime" && e.seasonId !== null || e.period === "season" && (e.seasonId === null || !c(e.seasonId)))) ? void 0 : t;
17
+ } catch {
18
+ return;
19
+ }
20
+ };
21
+ function d({ achievement: e, title: t, locale: n }) {
22
+ let s = i().achievements, c = r(), l = u([e])?.[0];
23
+ return l ? /* @__PURE__ */ o("article", {
24
+ "data-achievement": l.achievementId,
25
+ "data-tier": l.tierId,
26
+ "data-state": l.unlocked ? "unlocked" : "locked",
27
+ "aria-labelledby": c,
28
+ children: [
29
+ /* @__PURE__ */ o("header", { children: [/* @__PURE__ */ a("h3", {
30
+ id: c,
31
+ children: t ?? l.achievementId
32
+ }), /* @__PURE__ */ o("p", { children: [
33
+ s.tier(l.tierId),
34
+ " · ",
35
+ l.unlocked ? s.unlocked : s.locked
36
+ ] })] }),
37
+ /* @__PURE__ */ a("ul", {
38
+ "data-achievement-progress": !0,
39
+ children: l.progress.map((e, t) => {
40
+ let n = BigInt(e.value), r = BigInt(e.target), i = Number((n >= r ? r : n) * 10000n / r);
41
+ return /* @__PURE__ */ o("li", { children: [/* @__PURE__ */ a("span", { children: s.progress(e.stat, e.value, e.target) }), /* @__PURE__ */ a("progress", {
42
+ "aria-label": e.stat,
43
+ "aria-valuetext": s.progress(e.stat, e.value, e.target),
44
+ value: i,
45
+ max: 1e4
46
+ })] }, t);
47
+ })
48
+ }),
49
+ l.unlockedAt === null ? null : /* @__PURE__ */ a("p", { children: /* @__PURE__ */ a("time", {
50
+ dateTime: new Date(l.unlockedAt).toISOString(),
51
+ children: s.unlockedDate(new Date(l.unlockedAt).toLocaleString(n))
52
+ }) })
53
+ ]
54
+ }) : /* @__PURE__ */ a("p", {
55
+ role: "alert",
56
+ children: s.invalid
57
+ });
58
+ }
59
+ function f({ api: e = "app", locale: n, renderTitle: r }) {
60
+ let o = i().achievements, s = t(e), c = s.data === void 0 ? void 0 : u(s.data);
61
+ return s.error === void 0 ? s.loading ? /* @__PURE__ */ a("p", {
62
+ role: "status",
63
+ children: o.loading
64
+ }) : c ? /* @__PURE__ */ a("section", {
65
+ "data-achievements": !0,
66
+ "aria-label": o.title,
67
+ children: c.length === 0 ? /* @__PURE__ */ a("p", { children: o.empty }) : /* @__PURE__ */ a("ul", { children: c.map((e) => /* @__PURE__ */ a("li", { children: /* @__PURE__ */ a(d, {
68
+ achievement: e,
69
+ title: r?.(e),
70
+ locale: n
71
+ }) }, JSON.stringify([
72
+ e.achievementId,
73
+ e.version,
74
+ e.tierId
75
+ ]))) })
76
+ }) : /* @__PURE__ */ a("p", {
77
+ role: "alert",
78
+ children: o.invalid
79
+ }) : /* @__PURE__ */ a("p", {
80
+ role: "alert",
81
+ children: o.unavailable
82
+ });
83
+ }
84
+ function p(e) {
85
+ let t = i().achievements;
86
+ return c(e.invocationScope) ? /* @__PURE__ */ a(f, { ...e }, JSON.stringify([e.api ?? "app", e.invocationScope])) : /* @__PURE__ */ a("p", {
87
+ role: "alert",
88
+ children: t.invalid
89
+ });
90
+ }
91
+ export { d as AchievementCard, p as AchievementList };
@@ -0,0 +1,602 @@
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 { admitRewardDeliveryRecord as c } from "./rewardDeliveryRecord.js";
4
+ import { questHash as l } from "./questStore.js";
5
+ import { captureAchievementPlatform as u, captureAchievementStats as d, defaultAchievementEvaluator as f, defineAchievement as p, resolveAchievementEvaluation as m } from "./achievements.js";
6
+ import { achievementDefinitionsTable as h, achievementOperationsTable as g, achievementRewardsTable as _, achievementSubjectsTable as v, achievementUnlockLedgerTable as y, achievementsTable as b } from "./achievementTables.entity.js";
7
+ import { Effect as x, Result as S } from "effect";
8
+ import { and as C, eq as w, queryFor as T } from "@voltro/database";
9
+ // src/achievementStore.ts
10
+ var E = (e) => {
11
+ let n = o(e, [
12
+ "definitions",
13
+ "source",
14
+ "allowedServices",
15
+ "maxHistoryRows",
16
+ "maxPendingRewards",
17
+ "now",
18
+ "strategies"
19
+ ]), s = Object.freeze(a(n.definitions, 128).map((e) => p(e))), c = o(n.source, ["history"]), l = o(n.strategies ?? {}, ["achievementEvaluator", "version"]), u = l.achievementEvaluator ?? f, d = n.now ?? Date.now, m = Object.freeze(a(n.allowedServices ?? [], 256).map(r));
20
+ if (s.length === 0 || new Set(s.map((e) => e.id)).size !== s.length || s.reduce((e, t) => e + t.tiers.length, 0) > 256 || typeof c.history != "function" || typeof u != "function" || typeof d != "function" || new Set(m).size !== m.length || u !== f && l.version === void 0) throw t("invalid_input");
21
+ return Object.freeze({
22
+ definitions: s,
23
+ source: Object.freeze({ history: c.history }),
24
+ allowedServices: m,
25
+ maxHistoryRows: i(n.maxHistoryRows ?? 1e4, 1, 1e5),
26
+ maxPendingRewards: i(n.maxPendingRewards ?? 4096, 1, 1e4),
27
+ now: d,
28
+ strategies: Object.freeze({
29
+ achievementEvaluator: u,
30
+ version: r(l.version ?? "default.v1")
31
+ })
32
+ });
33
+ }, D = (e, n) => {
34
+ let s = o(e, [
35
+ "version",
36
+ "throughSequence",
37
+ "initial",
38
+ "events"
39
+ ]), c = i(s.throughSequence, 0, 2147483647), l = d(s.initial), u = /* @__PURE__ */ new Set(), f = 0, p = Object.freeze(a(s.events, n).map((e) => {
40
+ let n = o(e, [
41
+ "stat",
42
+ "period",
43
+ "seasonId",
44
+ "value",
45
+ "operationId",
46
+ "sequence",
47
+ "at"
48
+ ]), a = d([{
49
+ stat: n.stat,
50
+ period: n.period,
51
+ seasonId: n.seasonId,
52
+ value: n.value
53
+ }])[0], s = i(n.sequence, f + 1, c), l = r(n.operationId);
54
+ if (u.has(l)) throw t("invalid_record");
55
+ return f = s, u.add(l), Object.freeze({
56
+ ...a,
57
+ sequence: s,
58
+ operationId: l,
59
+ at: i(n.at, 0, 864e13)
60
+ });
61
+ }));
62
+ return Object.freeze({
63
+ version: r(s.version),
64
+ throughSequence: c,
65
+ initial: l,
66
+ events: p
67
+ });
68
+ }, O = (e, ...t) => e + l(t).slice(0, 56), k = (e) => {
69
+ let n = e instanceof Date ? e.getTime() : typeof e == "string" ? Date.parse(e) : NaN;
70
+ if (!Number.isSafeInteger(n) || n < 0 || n > 864e13) throw t("invalid_record");
71
+ return n;
72
+ }, A = (n) => x.tryPromise({
73
+ try: n,
74
+ catch: (n) => n instanceof e ? n : t("unavailable")
75
+ }), j = (e) => {
76
+ if (typeof e != "string" || !/^[0-9a-f]{64}$/.test(e)) throw t("invalid_record");
77
+ return e;
78
+ }, M = (d, p) => {
79
+ let M = E(p), N = l({
80
+ definitions: M.definitions,
81
+ rules: M.strategies.version
82
+ }), P = new Set(M.allowedServices), F = new Map(M.definitions.map((e) => [e.id, e])), I = () => i(M.now(), 0, 864e13), L = (e) => {
83
+ if (e.type !== "system" && !(e.type === "service" && P.has(e.service))) throw t("forbidden");
84
+ }, R = (e, t) => O("pas_", e, t), z = (e, t) => C(w("tenantId", e), w("ownerId", t)), B = (e, t) => C(w("tenantId", e), w("ownerKey", R(e, t))), V = async (e, t) => {
85
+ try {
86
+ await d.insertIgnore(e, t, { conflictColumns: ["id"] });
87
+ } catch (n) {
88
+ if (!(await d.query({
89
+ table: e,
90
+ predicate: w("id", t.id),
91
+ order: [],
92
+ take: 1,
93
+ skip: void 0,
94
+ projection: void 0
95
+ }))[0]) throw n;
96
+ }
97
+ }, H = (e, t) => V(v.tableName, {
98
+ id: R(e, t),
99
+ tenantId: e,
100
+ ownerId: t,
101
+ erased: !1,
102
+ sequence: 0,
103
+ admission: 0,
104
+ throughSequence: 0,
105
+ sourceVersion: null,
106
+ sourceDigest: null,
107
+ configDigest: null,
108
+ view: null
109
+ }), U = (e, n, r, a = !1) => {
110
+ if (e) {
111
+ if (e.id !== R(n, r) || e.tenantId !== n || typeof e.erased != "boolean") throw t("invalid_record");
112
+ if (e.erased) {
113
+ if (a && e.ownerId === null) return;
114
+ throw t("erased");
115
+ }
116
+ if (e.ownerId !== r) throw t("invalid_record");
117
+ if (i(e.sequence, 0, 2147483647), i(e.throughSequence, 0, 2147483647), e.configDigest !== null && e.configDigest !== N) throw t("conflict");
118
+ }
119
+ }, W = async (e, n, r, i = !1) => {
120
+ if (await e.updateMany(v.tableName, { admission: 0 }, { where: w("id", R(n, r)) }) !== 1) throw t("unavailable");
121
+ let a = (await e.query(T(v).where(w("id", R(n, r))).limit(1).descriptor))[0];
122
+ if (!a) throw t("invalid_record");
123
+ return U(a, n, r, i), a;
124
+ }, G = async (e, n, r, i) => {
125
+ let a = n === _ ? M.maxPendingRewards : M.maxHistoryRows, o = await e.query(T(n).where(B(r, i)).limit(a + 1).descriptor);
126
+ if (o.length > a) throw t("limit_exceeded");
127
+ if (o.some((e) => e.tenantId !== r || e.ownerKey !== R(r, i))) throw t("invalid_record");
128
+ return o;
129
+ }, K = (e, t, n) => e.query(T(b).where(z(t, n)).limit(257).descriptor), q = (e, n, i) => {
130
+ let a = F.get(r(e)), o = a?.tiers.find((e) => e.id === r(n));
131
+ if (!a || !o || i !== a.version) throw t("conflict");
132
+ return {
133
+ definition: a,
134
+ tier: o
135
+ };
136
+ }, J = (e, t, n, r, i) => O("pau_", e, t, n, String(r), i), Y = (e) => {
137
+ let n = o(e.receipt, [
138
+ "operationId",
139
+ "throughSequence",
140
+ "unlockedIds",
141
+ "rewardsQueued",
142
+ "at"
143
+ ]), s = Object.freeze(a(n.unlockedIds, 256).map(r));
144
+ if (n.operationId !== e.id || new Set(s).size !== s.length || n.at !== k(e.at) || n.throughSequence !== e.throughSequence) throw t("invalid_record");
145
+ return Object.freeze({
146
+ operationId: r(e.id),
147
+ throughSequence: i(n.throughSequence, 0, 2147483647),
148
+ unlockedIds: s,
149
+ rewardsQueued: i(n.rewardsQueued, 0, 16384),
150
+ at: i(n.at, 0, 864e13)
151
+ });
152
+ }, X = (e) => {
153
+ let n = a(e, 256).map((e) => {
154
+ let n = o(e, [
155
+ "achievementId",
156
+ "version",
157
+ "tierId",
158
+ "unlocked",
159
+ "unlockedAt",
160
+ "progress",
161
+ "platform"
162
+ ]), { definition: c, tier: d } = q(n.achievementId, n.tierId, n.version);
163
+ if (typeof n.unlocked != "boolean" || n.unlocked !== (n.unlockedAt !== null) || !n.unlocked && n.platform !== null) throw t("invalid_record");
164
+ let p = a(n.progress, 64).map((e) => {
165
+ let n = o(e, [
166
+ "stat",
167
+ "period",
168
+ "seasonId",
169
+ "value",
170
+ "target",
171
+ "met"
172
+ ]), i = m({
173
+ kind: "statAtLeast",
174
+ stat: r(n.stat),
175
+ period: n.period,
176
+ seasonId: n.seasonId,
177
+ target: String(s(n.target))
178
+ }, [{
179
+ stat: r(n.stat),
180
+ period: n.period,
181
+ seasonId: n.seasonId,
182
+ value: String(s(n.value))
183
+ }]).progress[0];
184
+ if (i.met !== n.met) throw t("invalid_record");
185
+ return i;
186
+ }), h = f({
187
+ condition: d.condition,
188
+ stats: []
189
+ }).progress;
190
+ if (p.length !== h.length || p.some((e, t) => {
191
+ let n = h[t];
192
+ return e.stat !== n.stat || e.period !== n.period || e.seasonId !== n.seasonId || e.target !== n.target;
193
+ })) throw t("invalid_record");
194
+ let g = n.unlocked ? u(n.platform) : null;
195
+ if (g && l(g) !== l(d.platform)) throw t("invalid_record");
196
+ return Object.freeze({
197
+ achievementId: c.id,
198
+ version: c.version,
199
+ tierId: d.id,
200
+ unlocked: n.unlocked,
201
+ unlockedAt: n.unlocked ? i(n.unlockedAt, 0, 864e13) : null,
202
+ progress: Object.freeze(p),
203
+ platform: g
204
+ });
205
+ });
206
+ if (n.length !== M.definitions.reduce((e, t) => e + t.tiers.length, 0) || new Set(n.map((e) => JSON.stringify([e.achievementId, e.tierId]))).size !== n.length) throw t("invalid_record");
207
+ return Object.freeze(n);
208
+ }, Z = (e, t) => l({
209
+ version: e.version,
210
+ initial: e.initial,
211
+ throughSequence: t,
212
+ events: e.events.filter((e) => e.sequence <= t)
213
+ }), ee = (e, n) => {
214
+ let r = /* @__PURE__ */ new Map(), i = /* @__PURE__ */ new Map(), a = (e) => JSON.stringify([
215
+ e.stat,
216
+ e.period,
217
+ e.seasonId
218
+ ]);
219
+ for (let t of e.initial) r.set(a(t), t);
220
+ let o = (e, t) => {
221
+ for (let n of M.definitions) for (let a of n.tiers) {
222
+ let o = m(a.condition, [...r.values()], M.strategies.achievementEvaluator), s = JSON.stringify([n.id, a.id]);
223
+ o.met && !i.has(s) && i.set(s, {
224
+ sequence: e,
225
+ at: t,
226
+ progress: o.progress
227
+ });
228
+ }
229
+ };
230
+ o(0, n);
231
+ for (let i of e.events) {
232
+ if (i.at > n) throw t("conflict");
233
+ r.set(a(i), Object.freeze({
234
+ stat: i.stat,
235
+ period: i.period,
236
+ seasonId: i.seasonId,
237
+ value: i.value
238
+ })), o(i.sequence, i.at);
239
+ }
240
+ return {
241
+ first: i,
242
+ view: Object.freeze(M.definitions.flatMap((e) => e.tiers.map((t) => {
243
+ let n = i.get(JSON.stringify([e.id, t.id])), a = m(t.condition, [...r.values()], M.strategies.achievementEvaluator);
244
+ return Object.freeze({
245
+ achievementId: e.id,
246
+ version: e.version,
247
+ tierId: t.id,
248
+ unlocked: n !== void 0,
249
+ unlockedAt: n?.at ?? null,
250
+ progress: a.progress,
251
+ platform: n ? t.platform : null
252
+ });
253
+ })))
254
+ };
255
+ }, te = (a, s) => {
256
+ try {
257
+ let e = n(a), c = o(s, [
258
+ "tenantId",
259
+ "ownerId",
260
+ "requestId"
261
+ ]);
262
+ L(e);
263
+ let u = r(c.tenantId), f = r(c.ownerId), p = O("pao_", u, f, r(c.requestId));
264
+ return A(async () => {
265
+ await H(u, f);
266
+ let n = await d.transactional(async (e) => {
267
+ await W(e, u, f);
268
+ let n = (await G(e, g, u, f)).find((e) => e.id === p);
269
+ if (n) {
270
+ if (n.state !== "committed" || n.configDigest !== N) throw t("conflict");
271
+ return Y(n);
272
+ }
273
+ });
274
+ if (n) return n;
275
+ let r = await x.runPromise(x.result(M.source.history(e, {
276
+ tenantId: u,
277
+ ownerId: f,
278
+ limit: M.maxHistoryRows
279
+ })));
280
+ if (S.isFailure(r)) throw r.failure;
281
+ let a = D(r.success, M.maxHistoryRows), o = I(), s = Z(a, a.throughSequence), c = ee(a, o);
282
+ for (let e of M.definitions) await V(h.tableName, {
283
+ id: O("pad_", u, e.id, String(e.version)),
284
+ tenantId: u,
285
+ achievementId: e.id,
286
+ version: e.version,
287
+ config: e,
288
+ rulesVersion: M.strategies.version,
289
+ admission: 0
290
+ });
291
+ return d.transactional(async (e) => {
292
+ let n = await W(e, u, f), r = await G(e, g, u, f), d = await G(e, y, u, f), m = await G(e, _, u, f), x = r.find((e) => e.id === p);
293
+ if (x) {
294
+ if (x.state !== "committed" || x.configDigest !== N) throw t("conflict");
295
+ return Y(x);
296
+ }
297
+ if (r.length >= M.maxHistoryRows || r.length !== n.sequence) throw t(r.length >= M.maxHistoryRows ? "limit_exceeded" : "invalid_record");
298
+ if (n.sourceVersion !== null && (n.sourceVersion !== a.version || Number(n.throughSequence) > a.throughSequence || n.sourceDigest !== Z(a, Number(n.throughSequence)))) throw t("conflict");
299
+ for (let n of M.definitions) {
300
+ let r = O("pad_", u, n.id, String(n.version));
301
+ if (await e.updateMany(h.tableName, { admission: 0 }, { where: w("id", r) }) !== 1) throw t("unavailable");
302
+ let i = (await e.query(T(h).where(w("id", r)).limit(1).descriptor))[0];
303
+ if (!i || i.tenantId !== u || i.achievementId !== n.id || i.version !== n.version || i.rulesVersion !== M.strategies.version || l(i.config) !== l(n)) throw t("conflict");
304
+ }
305
+ let S = await K(e, u, f);
306
+ if (S.length !== d.length || d.some((e) => !S.some((t) => t.id === e.unlockId && t.operationId === e.operationId && k(t.unlockedAt) === k(e.unlockedAt)))) throw t("invalid_record");
307
+ let C = [], E = 0, D = c.view.map((e) => {
308
+ let t = J(u, f, e.achievementId, e.version, e.tierId), n = d.find((e) => e.unlockId === t);
309
+ return n ? Object.freeze({
310
+ ...e,
311
+ unlocked: !0,
312
+ unlockedAt: k(n.unlockedAt),
313
+ platform: q(e.achievementId, e.tierId, e.version).tier.platform
314
+ }) : e;
315
+ });
316
+ for (let n of D) {
317
+ let r = J(u, f, n.achievementId, n.version, n.tierId);
318
+ if (!n.unlocked || d.some((e) => e.unlockId === r)) continue;
319
+ let i = c.first.get(JSON.stringify([n.achievementId, n.tierId]));
320
+ if (!i) throw t("invalid_record");
321
+ let { tier: s } = q(n.achievementId, n.tierId, n.version);
322
+ if (d.length + C.length >= M.maxHistoryRows || m.length + E + s.reward.length > M.maxPendingRewards) throw t("limit_exceeded");
323
+ let l = {
324
+ id: r,
325
+ tenantId: u,
326
+ ownerId: f,
327
+ achievementId: n.achievementId,
328
+ version: n.version,
329
+ tierId: n.tierId,
330
+ unlockedAt: new Date(i.at),
331
+ sourceSequence: i.sequence,
332
+ operationId: p
333
+ };
334
+ await e.insert(b.tableName, l), await e.insert(y.tableName, {
335
+ ...l,
336
+ id: O("pal_", r),
337
+ ownerKey: R(u, f),
338
+ unlockId: r,
339
+ proof: {
340
+ sourceVersion: a.version,
341
+ sourceDigest: Z(a, i.sequence),
342
+ rulesVersion: M.strategies.version,
343
+ fulfilled: !0,
344
+ progress: i.progress
345
+ }
346
+ });
347
+ for (let [t, n] of s.reward.entries()) await e.insert(_.tableName, {
348
+ id: O("par_", r, String(t)),
349
+ tenantId: u,
350
+ ownerId: f,
351
+ ownerKey: R(u, f),
352
+ unlockId: r,
353
+ operationId: p,
354
+ reward: n,
355
+ state: "pending",
356
+ createdAt: new Date(o),
357
+ deliveredAt: null,
358
+ deliveryIntent: null,
359
+ deliveryDigest: null,
360
+ deliveryReceipt: null
361
+ });
362
+ C.push(r), E += s.reward.length;
363
+ }
364
+ let A = Object.freeze({
365
+ operationId: p,
366
+ throughSequence: a.throughSequence,
367
+ unlockedIds: Object.freeze(C),
368
+ rewardsQueued: E,
369
+ at: o
370
+ }), j = {
371
+ throughSequence: a.throughSequence,
372
+ sourceVersion: a.version,
373
+ sourceDigest: s,
374
+ configDigest: N,
375
+ view: Object.freeze(D)
376
+ }, P = i(Number(n.sequence) + 1, 1, 2147483647);
377
+ return await e.insert(g.tableName, {
378
+ id: p,
379
+ tenantId: u,
380
+ ownerKey: R(u, f),
381
+ state: "committed",
382
+ sequence: P,
383
+ ...j,
384
+ receipt: A,
385
+ at: new Date(o)
386
+ }), await e.update(v.tableName, R(u, f), {
387
+ sequence: P,
388
+ ...j
389
+ }), A;
390
+ });
391
+ });
392
+ } catch (n) {
393
+ return x.fail(n instanceof e ? n : t("invalid_input"));
394
+ }
395
+ }, ne = (i) => {
396
+ try {
397
+ let e = n(i);
398
+ if (e.type !== "user") throw t("forbidden");
399
+ let a = r(e.tenantId), o = r(e.id);
400
+ return A(() => d.transactional(async (e) => {
401
+ let t = (await e.query(T(v).where(w("id", R(a, o))).forUpdate().limit(1).descriptor))[0];
402
+ return U(t, a, o), !t || t.view === null ? Object.freeze(M.definitions.filter((e) => !e.hidden).flatMap((e) => e.tiers.map((t) => Object.freeze({
403
+ achievementId: e.id,
404
+ version: e.version,
405
+ tierId: t.id,
406
+ unlocked: !1,
407
+ unlockedAt: null,
408
+ progress: f({
409
+ condition: t.condition,
410
+ stats: []
411
+ }).progress,
412
+ platform: null
413
+ })))) : Object.freeze(X(t.view).filter((e) => e.unlocked || !F.get(e.achievementId).hidden));
414
+ }));
415
+ } catch (n) {
416
+ return x.fail(n instanceof e ? n : t("invalid_input"));
417
+ }
418
+ }, Q = (n, i) => {
419
+ try {
420
+ let e = o(n, [
421
+ "tenantId",
422
+ "subjectId",
423
+ "kind"
424
+ ]), a = r(e.tenantId), s = r(e.subjectId);
425
+ if (e.kind !== "user" && e.kind !== "guest") throw t("forbidden");
426
+ return A(async () => (await H(a, s), d.transactional(async (e) => {
427
+ await W(e, a, s, !0);
428
+ let t = await K(e, a, s), n = await G(e, y, a, s), r = await G(e, g, a, s), o = await G(e, _, a, s);
429
+ if (!i) return {
430
+ achievements: t.map((e) => ({
431
+ achievementId: e.achievementId,
432
+ version: e.version,
433
+ tierId: e.tierId,
434
+ unlockedAt: k(e.unlockedAt),
435
+ sourceSequence: e.sourceSequence
436
+ })),
437
+ history: n.map((e) => ({
438
+ achievementId: e.achievementId,
439
+ tierId: e.tierId,
440
+ proof: e.proof
441
+ })),
442
+ evaluations: r.map((e) => e.receipt),
443
+ rewards: o.map((e) => ({
444
+ reward: e.reward,
445
+ state: e.state,
446
+ deliveryIntent: e.deliveryIntent ?? null,
447
+ deliveryReceipt: e.deliveryReceipt ?? null
448
+ }))
449
+ };
450
+ await e.deleteMany(b.tableName, { where: z(a, s) }), await e.updateMany(y.tableName, {
451
+ ownerId: null,
452
+ ownerKey: null,
453
+ proof: null
454
+ }, { where: B(a, s) }), await e.updateMany(g.tableName, {
455
+ ownerKey: null,
456
+ state: "erased",
457
+ sourceVersion: null,
458
+ sourceDigest: null,
459
+ configDigest: null,
460
+ view: null,
461
+ receipt: null
462
+ }, { where: B(a, s) }), await e.updateMany(_.tableName, {
463
+ ownerId: null,
464
+ ownerKey: null,
465
+ reward: null,
466
+ state: "erased",
467
+ deliveryIntent: null,
468
+ deliveryDigest: null,
469
+ deliveryReceipt: null,
470
+ deliveredAt: null
471
+ }, { where: B(a, s) }), await e.update(v.tableName, R(a, s), {
472
+ ownerId: null,
473
+ erased: !0,
474
+ sourceVersion: null,
475
+ sourceDigest: null,
476
+ configDigest: null,
477
+ view: null
478
+ });
479
+ })));
480
+ } catch (n) {
481
+ return x.fail(n instanceof e ? n : t("invalid_input"));
482
+ }
483
+ }, $ = (a, s, u, p) => {
484
+ try {
485
+ let e = n(a);
486
+ L(e);
487
+ let m = r(s), x = r(u);
488
+ return A(async () => (await H(m, x), d.transactional(async (e) => {
489
+ let n = await W(e, m, x), a = await G(e, y, m, x), s = await G(e, g, m, x), u = await G(e, _, m, x), d = [...s].sort((e, t) => Number(e.sequence) - Number(t.sequence)), S = /* @__PURE__ */ new Map(), C = 0, E = 0;
490
+ if (d.length > 0) for (let n of M.definitions) {
491
+ let r = (await e.query(T(h).where(w("id", O("pad_", m, n.id, String(n.version)))).limit(1).descriptor))[0];
492
+ if (!r || r.tenantId !== m || r.achievementId !== n.id || r.version !== n.version || r.rulesVersion !== M.strategies.version || l(r.config) !== l(n)) throw t("conflict");
493
+ }
494
+ if (d.length !== n.sequence) throw t("invalid_record");
495
+ for (let [e, n] of d.entries()) {
496
+ if (n.sequence !== e + 1 || n.state !== "committed" || n.configDigest !== N || Number(n.throughSequence) < C) throw t("invalid_record");
497
+ C = i(n.throughSequence, 0, 2147483647), r(n.sourceVersion), j(n.sourceDigest);
498
+ let s = Y(n);
499
+ if (s.at < E || e > 0 && n.sourceVersion !== d[e - 1].sourceVersion || e > 0 && n.throughSequence === d[e - 1].throughSequence && n.sourceDigest !== d[e - 1].sourceDigest) throw t("invalid_record");
500
+ E = s.at;
501
+ let p = X(n.view), h = a.filter((e) => e.operationId === n.id), g = u.filter((e) => e.operationId === n.id);
502
+ if (h.length !== s.unlockedIds.length || g.length !== s.rewardsQueued || new Set(h.map((e) => e.unlockId)).size !== h.length) throw t("invalid_record");
503
+ let _ = 0;
504
+ for (let e of h) {
505
+ let { definition: r, tier: a } = q(e.achievementId, e.tierId, e.version), u = J(m, x, r.id, r.version, a.id), d = p.find((e) => e.achievementId === r.id && e.tierId === a.id), h = o(e.proof, [
506
+ "sourceVersion",
507
+ "sourceDigest",
508
+ "rulesVersion",
509
+ "fulfilled",
510
+ "progress"
511
+ ]);
512
+ if (S.has(u) || e.unlockId !== u || e.id !== O("pal_", u) || e.ownerId !== x || !s.unlockedIds.includes(u) || !d?.unlocked || d.unlockedAt !== k(e.unlockedAt) || k(e.unlockedAt) > s.at || h.sourceVersion !== n.sourceVersion || h.rulesVersion !== M.strategies.version || h.fulfilled !== !0) throw t("invalid_record");
513
+ j(h.sourceDigest), i(e.sourceSequence, 0, s.throughSequence);
514
+ let v = {
515
+ ...d,
516
+ progress: h.progress
517
+ }, y = p.map((e) => e === d ? v : e), b = X(y).find((e) => e.achievementId === r.id && e.tierId === a.id);
518
+ if (M.strategies.achievementEvaluator === f) {
519
+ let e = /* @__PURE__ */ new Map();
520
+ for (let n of b.progress) {
521
+ let r = JSON.stringify([
522
+ n.stat,
523
+ n.period,
524
+ n.seasonId
525
+ ]), i = e.get(r);
526
+ if (i && i.value !== n.value) throw t("invalid_record");
527
+ e.set(r, {
528
+ stat: n.stat,
529
+ period: n.period,
530
+ seasonId: n.seasonId,
531
+ value: n.value
532
+ });
533
+ }
534
+ if (!f({
535
+ condition: a.condition,
536
+ stats: [...e.values()]
537
+ }).met) throw t("invalid_record");
538
+ }
539
+ S.set(u, {
540
+ id: u,
541
+ tenantId: m,
542
+ ownerId: x,
543
+ achievementId: r.id,
544
+ version: r.version,
545
+ tierId: a.id,
546
+ unlockedAt: new Date(d.unlockedAt),
547
+ sourceSequence: e.sourceSequence,
548
+ operationId: n.id
549
+ });
550
+ for (let [e, n] of a.reward.entries()) {
551
+ let r = g.find((t) => t.id === O("par_", u, String(e)));
552
+ if (!r || r.unlockId !== u || r.ownerId !== x || l(r.reward) !== l(n) || k(r.createdAt) !== s.at || r.state !== "pending" && r.state !== "delivered" || r.state === "pending" && r.deliveredAt !== null || r.state === "delivered" && k(r.deliveredAt) < s.at) throw t("invalid_record");
553
+ c(r, "achievement", l), _++;
554
+ }
555
+ }
556
+ if (_ !== g.length || p.some((e) => {
557
+ let t = S.get(J(m, x, e.achievementId, e.version, e.tierId));
558
+ return e.unlocked !== (t !== void 0) || t !== void 0 && e.unlockedAt !== k(t.unlockedAt);
559
+ })) throw t("invalid_record");
560
+ }
561
+ if (a.length !== S.size || a.some((e) => !d.some((t) => t.id === e.operationId)) || u.some((e) => !d.some((t) => t.id === e.operationId))) throw t("invalid_record");
562
+ let D = d.at(-1), A = await K(e, m, x), P = (e) => ({
563
+ id: e.id,
564
+ achievementId: e.achievementId,
565
+ version: e.version,
566
+ tierId: e.tierId,
567
+ unlockedAt: k(e.unlockedAt),
568
+ sourceSequence: e.sourceSequence,
569
+ operationId: e.operationId
570
+ }), F = A.length === S.size && A.every((e) => S.has(String(e.id)) && l(P(e)) === l(P(S.get(String(e.id))))) && l(n.view) === l(D?.view ?? null) && n.throughSequence === (D?.throughSequence ?? 0) && n.sourceDigest === (D?.sourceDigest ?? null) && n.sourceVersion === (D?.sourceVersion ?? null) && n.configDigest === (D?.configDigest ?? null);
571
+ if (p && !F) {
572
+ await e.deleteMany(b.tableName, { where: z(m, x) });
573
+ for (let t of S.values()) await e.insert(b.tableName, t);
574
+ await e.update(v.tableName, R(m, x), {
575
+ throughSequence: D?.throughSequence ?? 0,
576
+ sourceDigest: D?.sourceDigest ?? null,
577
+ sourceVersion: D?.sourceVersion ?? null,
578
+ configDigest: D?.configDigest ?? null,
579
+ view: D?.view ?? null
580
+ });
581
+ }
582
+ return Object.freeze({
583
+ acceptedOperations: d.length,
584
+ unlocked: S.size,
585
+ rewardRows: u.length,
586
+ matches: p ? !0 : F
587
+ });
588
+ })));
589
+ } catch (n) {
590
+ return x.fail(n instanceof e ? n : t("invalid_input"));
591
+ }
592
+ };
593
+ return Object.freeze({
594
+ evaluate: te,
595
+ mine: ne,
596
+ exportSubject: (e) => Q(e, !1),
597
+ eraseSubject: (e) => x.asVoid(Q(e, !0)),
598
+ auditAchievements: (e, t, n) => $(e, t, n, !1),
599
+ rebuildAchievements: (e, t, n) => $(e, t, n, !0)
600
+ });
601
+ };
602
+ export { D as captureAchievementHistory, M as dataStoreAchievements, E as resolveAchievementOptions };