@voltro/plugin-progression 0.0.0-stage → 0.87.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 +24329 -0
  2. package/LICENSE +61 -0
  3. package/README.md +478 -2
  4. package/SECURITY.md +56 -0
  5. package/THIRD-PARTY-NOTICES.md +9189 -0
  6. package/dist/achievementComponents.js +92 -0
  7. package/dist/achievementStore.js +603 -0
  8. package/dist/achievementTables.entity.js +98 -0
  9. package/dist/achievements.d.ts +188 -0
  10. package/dist/achievements.js +205 -0
  11. package/dist/capture.js +64 -0
  12. package/dist/cmsQuests.d.ts +91 -0
  13. package/dist/cmsQuests.js +83 -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 +38 -0
  18. package/dist/daily.d.ts +152 -0
  19. package/dist/daily.js +126 -0
  20. package/dist/dailyStore.js +421 -0
  21. package/dist/dailySystem.fixture.js +138 -0
  22. package/dist/dailyTables.entity.js +90 -0
  23. package/dist/declarationFixtures.js +143 -0
  24. package/dist/errors.d.ts +13 -0
  25. package/dist/errors.js +20 -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 +122 -0
  30. package/dist/passRules.js +96 -0
  31. package/dist/passStore.js +485 -0
  32. package/dist/passTables.entity.js +96 -0
  33. package/dist/plugin.js +1086 -0
  34. package/dist/port.js +5 -0
  35. package/dist/progressionStore.js +706 -0
  36. package/dist/questComponents.js +163 -0
  37. package/dist/questPort.d.ts +126 -0
  38. package/dist/questPort.js +5 -0
  39. package/dist/questRefresh.js +56 -0
  40. package/dist/questRefresh.server.js +126 -0
  41. package/dist/questRerollJournal.js +77 -0
  42. package/dist/questStore.js +592 -0
  43. package/dist/questTables.entity.js +117 -0
  44. package/dist/quests.d.ts +142 -0
  45. package/dist/quests.js +153 -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 +35 -0
  51. package/dist/rankClosure.server.js +139 -0
  52. package/dist/rankClosureWorkflow.d.ts +34 -0
  53. package/dist/rankClosureWorkflow.js +16 -0
  54. package/dist/rankReader.server.js +57 -0
  55. package/dist/rankRewardParent.server.js +65 -0
  56. package/dist/rankSeasons.d.ts +144 -0
  57. package/dist/rankSeasons.js +91 -0
  58. package/dist/rankStore.js +521 -0
  59. package/dist/rankSystem.fixture.js +170 -0
  60. package/dist/rankTables.entity.js +101 -0
  61. package/dist/ranks.d.ts +167 -0
  62. package/dist/ranks.js +219 -0
  63. package/dist/resourceStore.js +464 -0
  64. package/dist/resourceTables.entity.js +89 -0
  65. package/dist/resources.d.ts +105 -0
  66. package/dist/resources.js +60 -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 +39 -0
  72. package/dist/rewardDelivery.d.ts +163 -0
  73. package/dist/rewardDelivery.js +38 -0
  74. package/dist/rewardDelivery.server.js +430 -0
  75. package/dist/rewardDeliveryRecord.js +48 -0
  76. package/dist/rewardDeliveryWorkflow.d.ts +36 -0
  77. package/dist/rewardDeliveryWorkflow.js +16 -0
  78. package/dist/rpc.d.ts +880 -0
  79. package/dist/rpc.js +498 -0
  80. package/dist/server.d.ts +2812 -0
  81. package/dist/server.js +21 -0
  82. package/dist/stats.js +45 -0
  83. package/dist/strategies.d.ts +131 -0
  84. package/dist/strategies.js +4 -0
  85. package/dist/systemFixtures.js +474 -0
  86. package/dist/tables.entity.js +155 -0
  87. package/dist/testing.d.ts +1566 -0
  88. package/dist/testing.js +11 -0
  89. package/dist/track.js +72 -0
  90. package/dist/tutorial.d.ts +157 -0
  91. package/dist/tutorial.js +110 -0
  92. package/dist/tutorialStore.js +496 -0
  93. package/dist/tutorialSystem.fixture.js +100 -0
  94. package/dist/tutorialTables.entity.js +91 -0
  95. package/dist/web.d.ts +363 -0
  96. package/dist/web.js +7 -0
  97. package/package.json +167 -4
@@ -0,0 +1,421 @@
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 } from "./capture.js";
3
+ import { captureDailyProfile as s, captureDailyState as c, defaultDailyClaimPolicy as l, defaultDailyWindow as u, defineLoginCalendar as d, resolveDailyClaim as f } from "./daily.js";
4
+ import { admitRewardDeliveryRecord as p } from "./rewardDeliveryRecord.js";
5
+ import { questHash as m } from "./questStore.js";
6
+ import { dailyClaimsTable as h, dailyDefinitionsTable as g, dailyOperationsTable as _, dailyRewardsTable as v, dailyStatesTable as y, dailySubjectsTable as b } from "./dailyTables.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
+ //#region src/dailyStore.ts
10
+ var E = (e) => {
11
+ let n = o(e, [
12
+ "calendars",
13
+ "profileSource",
14
+ "now",
15
+ "maxHistoryRows",
16
+ "allowedServices",
17
+ "strategies"
18
+ ]), s = o(n.profileSource), c = o(n.strategies ?? {}, ["claimPolicy", "version"]), u = Object.freeze(a(n.calendars, 64).map((e) => d(e))), f = n.now ?? Date.now, p = c.claimPolicy ?? l, m = Object.freeze(a(n.allowedServices ?? [], 256).map(r));
19
+ if (!u.length || new Set(u.map((e) => e.id)).size !== u.length || new Set(m).size !== m.length || typeof s.read != "function" || typeof f != "function" || typeof p != "function" || p !== l && c.version === void 0) throw t("invalid_input");
20
+ return Object.freeze({
21
+ calendars: u,
22
+ profileSource: Object.freeze({ read: s.read }),
23
+ now: f,
24
+ maxHistoryRows: i(n.maxHistoryRows ?? 1e4, 1, 1e5),
25
+ allowedServices: m,
26
+ strategies: Object.freeze({
27
+ claimPolicy: p,
28
+ version: r(c.version ?? "default.v1")
29
+ })
30
+ });
31
+ }, D = (e, ...t) => e + m(t).slice(0, 56), O = (e) => i(e instanceof Date ? e.getTime() : typeof e == "string" ? Date.parse(e) : NaN, 0, 864e13), k = (n) => x.tryPromise({
32
+ try: n,
33
+ catch: (n) => n instanceof e ? n : t("unavailable")
34
+ }), A = (a, d) => {
35
+ let A = E(d), j = new Map(A.calendars.map((e) => [e.id, e])), M = new Set(A.allowedServices), N = () => i(A.now(), 0, 864e13), P = (e) => {
36
+ let n = j.get(e);
37
+ if (!n) throw t("invalid_input");
38
+ return n;
39
+ }, F = (e) => {
40
+ if (e.type !== "user" || !e.tenantId) throw t("forbidden");
41
+ return {
42
+ tenantId: r(e.tenantId),
43
+ ownerId: r(e.id)
44
+ };
45
+ }, I = (e) => {
46
+ if (e.type !== "system" && !(e.type === "service" && M.has(e.service))) throw t("forbidden");
47
+ }, L = (e, t) => D("pds_", e, t), R = (e, t) => C(w("tenantId", e), w("ownerKey", L(e, t))), z = async (e, n) => {
48
+ if ((await a.insertIgnoreWithOutcome(e.tableName, n, { conflictColumns: ["id"] })).outcome !== "inserted" && !(await a.query(T(e).where(w("id", n.id)).limit(1).descriptor))[0]) throw t("unavailable");
49
+ }, B = (e, t) => z(b, {
50
+ id: L(e, t),
51
+ tenantId: e,
52
+ ownerId: t,
53
+ erased: !1,
54
+ sequence: 0,
55
+ admission: 0
56
+ }), V = (e, n, r) => {
57
+ if (e) {
58
+ if (e.id !== L(n, r) || e.tenantId !== n || typeof e.erased != "boolean") throw t("invalid_record");
59
+ if (e.erased) throw e.ownerId === null ? t("erased") : t("invalid_record");
60
+ if (e.ownerId !== r) throw t("invalid_record");
61
+ i(e.sequence, 0, 2147483647);
62
+ }
63
+ }, H = async (e, n, r) => {
64
+ if (await e.updateMany(b.tableName, { admission: 0 }, { where: w("id", L(n, r)) }) !== 1) throw t("invalid_record");
65
+ let i = (await e.query(T(b).where(w("id", L(n, r))).limit(1).descriptor))[0];
66
+ if (V(i, n, r), !i) throw t("invalid_record");
67
+ return i;
68
+ }, U = async (e, n, r, i) => {
69
+ let a = await e.query(T(n).where(R(r, i)).limit(A.maxHistoryRows + 1).descriptor);
70
+ if (a.length > A.maxHistoryRows) throw t("limit_exceeded");
71
+ if (a.some((e) => e.tenantId !== r || e.ownerKey !== L(r, i))) throw t("invalid_record");
72
+ return a;
73
+ }, W = (e, n, a) => {
74
+ let s = o(e.receipt, [
75
+ "operationId",
76
+ "claimId",
77
+ "calendarId",
78
+ "dayKey",
79
+ "after",
80
+ "rewardsQueued",
81
+ "at"
82
+ ]), l = P(r(s.calendarId)), u = c(s.after, l);
83
+ if (e.state !== "committed" || s.operationId !== e.id || s.claimId !== D("pdl_", n, a, l.id, String(l.version), String(u.dayOrdinal)) || s.dayKey !== u.dayKey || s.at !== u.at || s.at !== O(e.at) || s.rewardsQueued !== l.days[u.dayIndex].length) throw t("invalid_record");
84
+ return Object.freeze({
85
+ operationId: r(e.id),
86
+ claimId: r(s.claimId),
87
+ calendarId: l.id,
88
+ dayKey: u.dayKey,
89
+ after: u,
90
+ rewardsQueued: i(s.rewardsQueued, 0, 64),
91
+ at: u.at
92
+ });
93
+ }, G = async (e, n, r, i, a) => {
94
+ let o = (await e.query(T(_).where(w("id", n)).limit(1).descriptor))[0];
95
+ if (!o) return;
96
+ if (o.state === "erased") throw t("erased");
97
+ if (o.tenantId !== i || o.ownerKey !== L(i, a) || o.digest !== r) throw t("conflict");
98
+ if (o.state === "committed" && o.linkedOperationId === null) return W(o, i, a);
99
+ if (o.state !== "replayed" || typeof o.linkedOperationId != "string" || o.receipt !== null) throw t("invalid_record");
100
+ let s = (await e.query(T(_).where(w("id", o.linkedOperationId)).limit(1).descriptor))[0];
101
+ if (!s || s.tenantId !== i || s.ownerKey !== L(i, a) || s.digest !== r || s.linkedOperationId !== null) throw t("invalid_record");
102
+ return W(s, i, a);
103
+ }, K = async (e, t, n) => {
104
+ let r = await x.runPromise(x.result(A.profileSource.read(e, {
105
+ tenantId: t,
106
+ ownerId: n
107
+ })));
108
+ if (S.isFailure(r)) throw r.failure;
109
+ return s(r.success);
110
+ }, q = (e, n, r, i) => {
111
+ if (e.id !== D("pdv_", n, r, i.id, String(i.version)) || e.tenantId !== n || e.ownerId !== r || e.calendarId !== i.id || e.version !== i.version) throw t("invalid_record");
112
+ let a = c(e.state, i);
113
+ if (O(e.updatedAt) !== a.at) throw t("invalid_record");
114
+ return a;
115
+ }, J = (s, c) => {
116
+ try {
117
+ let e = n(s), { tenantId: l, ownerId: d } = F(e), p = o(c, ["calendarId", "requestId"]), x = P(r(p.calendarId)), S = D("pdo_", l, d, r(p.requestId)), C = m({
118
+ tenantId: l,
119
+ ownerId: d,
120
+ calendarId: x.id,
121
+ version: x.version
122
+ });
123
+ return k(async () => {
124
+ await B(l, d);
125
+ let n = await a.transactional(async (e) => (await H(e, l, d), G(e, S, C, l, d)));
126
+ if (n) return n;
127
+ let r = await K(e, l, d), o = N(), s = u({
128
+ timezone: r.timezone,
129
+ at: o
130
+ });
131
+ return await z(g, {
132
+ id: D("pdd_", l, x.id, String(x.version)),
133
+ tenantId: l,
134
+ calendarId: x.id,
135
+ version: x.version,
136
+ config: x,
137
+ rulesVersion: A.strategies.version,
138
+ admission: 0
139
+ }), a.transactional(async (e) => {
140
+ let n = await H(e, l, d), a = await G(e, S, C, l, d);
141
+ if (a) return a;
142
+ let c = await U(e, _, l, d), u = await U(e, h, l, d), p = await U(e, v, l, d);
143
+ if (c.length >= A.maxHistoryRows) throw t("limit_exceeded");
144
+ let E = D("pdd_", l, x.id, String(x.version));
145
+ if (await e.updateMany(g.tableName, { admission: 0 }, { where: w("id", E) }) !== 1) throw t("invalid_record");
146
+ let O = (await e.query(T(g).where(w("id", E)).limit(1).descriptor))[0];
147
+ if (!O || O.tenantId !== l || O.calendarId !== x.id || O.version !== x.version || O.rulesVersion !== A.strategies.version || m(O.config) !== m(x)) throw t("conflict");
148
+ let k = D("pdl_", l, d, x.id, String(x.version), String(s.dayOrdinal)), j = u.find((e) => e.id === k);
149
+ if (j) {
150
+ let n = c.find((e) => e.id === j.operationId);
151
+ if (!n || n.digest !== C) throw t("invalid_record");
152
+ let i = W(n, l, d);
153
+ if (i.after.timezone !== r.timezone) throw t("conflict");
154
+ return await e.insert(_.tableName, {
155
+ id: S,
156
+ tenantId: l,
157
+ ownerKey: L(l, d),
158
+ state: "replayed",
159
+ linkedOperationId: i.operationId,
160
+ digest: C,
161
+ receipt: null,
162
+ at: new Date(o)
163
+ }), i;
164
+ }
165
+ let M = D("pdv_", l, d, x.id, String(x.version)), N = (await e.query(T(y).where(w("id", M)).limit(1).descriptor))[0], P = N ? q(N, l, d, x) : null, F = u.filter((e) => e.calendarId === x.id).sort((e, t) => Number(e.sequence) - Number(t.sequence)).at(-1);
166
+ if (F && (!P || m(F.after) !== m(P)) || !F && P) throw t("invalid_record");
167
+ let I = f({
168
+ calendar: x,
169
+ previous: P,
170
+ window: s,
171
+ at: o
172
+ }, A.strategies.claimPolicy), R = x.days[I.dayIndex];
173
+ if (u.length >= A.maxHistoryRows || p.length + R.length > A.maxHistoryRows) throw t("limit_exceeded");
174
+ let z = i(n.sequence, 0, 2147483646) + 1, B = Object.freeze({
175
+ operationId: S,
176
+ claimId: k,
177
+ calendarId: x.id,
178
+ dayKey: I.dayKey,
179
+ after: I,
180
+ rewardsQueued: R.length,
181
+ at: o
182
+ });
183
+ N ? await e.update(y.tableName, M, {
184
+ state: I,
185
+ updatedAt: new Date(o)
186
+ }) : await e.insert(y.tableName, {
187
+ id: M,
188
+ tenantId: l,
189
+ ownerId: d,
190
+ ownerKey: L(l, d),
191
+ calendarId: x.id,
192
+ version: x.version,
193
+ state: I,
194
+ updatedAt: new Date(o)
195
+ }), await e.insert(h.tableName, {
196
+ id: k,
197
+ tenantId: l,
198
+ ownerId: d,
199
+ ownerKey: L(l, d),
200
+ calendarId: x.id,
201
+ version: x.version,
202
+ dayOrdinal: I.dayOrdinal,
203
+ dayKey: I.dayKey,
204
+ sequence: z,
205
+ operationId: S,
206
+ before: P,
207
+ after: I,
208
+ profileVersion: r.version,
209
+ at: new Date(o)
210
+ }), await e.insert(_.tableName, {
211
+ id: S,
212
+ tenantId: l,
213
+ ownerKey: L(l, d),
214
+ state: "committed",
215
+ linkedOperationId: null,
216
+ digest: C,
217
+ receipt: B,
218
+ at: new Date(o)
219
+ });
220
+ for (let [t, n] of R.entries()) await e.insert(v.tableName, {
221
+ id: D("pdr_", k, String(t)),
222
+ tenantId: l,
223
+ ownerId: d,
224
+ ownerKey: L(l, d),
225
+ claimId: k,
226
+ operationId: S,
227
+ reward: n,
228
+ state: "pending",
229
+ createdAt: new Date(o),
230
+ deliveredAt: null,
231
+ deliveryIntent: null,
232
+ deliveryDigest: null,
233
+ deliveryReceipt: null
234
+ });
235
+ return await e.update(b.tableName, L(l, d), { sequence: z }), B;
236
+ });
237
+ });
238
+ } catch (n) {
239
+ return x.fail(n instanceof e ? n : t("invalid_input"));
240
+ }
241
+ }, Y = (r) => {
242
+ try {
243
+ let e = n(r), { tenantId: i, ownerId: o } = F(e);
244
+ return k(async () => {
245
+ let n = await K(e, i, o), r = N(), s = u({
246
+ timezone: n.timezone,
247
+ at: r
248
+ });
249
+ return a.transactional(async (e) => {
250
+ let a = (await e.query(T(b).where(w("id", L(i, o))).forUpdate().limit(1).descriptor))[0];
251
+ V(a, i, o);
252
+ let c = await U(e, y, i, o), l = await U(e, h, i, o);
253
+ return Object.freeze(A.calendars.map((e) => {
254
+ let a = c.find((t) => t.calendarId === e.id), u = a ? q(a, i, o, e) : null;
255
+ if (u && (u.timezone !== n.timezone || u.at > r || u.dayOrdinal > s.dayOrdinal)) throw t("conflict");
256
+ let d = l.filter((t) => t.calendarId === e.id).sort((e, t) => Number(e.sequence) - Number(t.sequence)).at(-1);
257
+ if (d && (!u || m(d.after) !== m(u)) || !d && u) throw t("invalid_record");
258
+ let p = u?.dayOrdinal === s.dayOrdinal, h = p ? u : f({
259
+ calendar: e,
260
+ previous: u,
261
+ window: s,
262
+ at: r
263
+ }, A.strategies.claimPolicy);
264
+ return Object.freeze({
265
+ calendarId: e.id,
266
+ version: e.version,
267
+ dayKey: s.dayKey,
268
+ timezone: n.timezone,
269
+ from: s.from,
270
+ until: s.until,
271
+ observedAt: r,
272
+ claimed: p,
273
+ dayIndex: h.dayIndex,
274
+ streak: p ? h.streak : u?.streak ?? 0,
275
+ protectionRemaining: h.protectionRemaining,
276
+ reward: e.days[h.dayIndex]
277
+ });
278
+ }));
279
+ });
280
+ });
281
+ } catch (n) {
282
+ return x.fail(n instanceof e ? n : t("invalid_input"));
283
+ }
284
+ }, X = (n, i) => {
285
+ try {
286
+ let e = o(n, [
287
+ "tenantId",
288
+ "subjectId",
289
+ "kind"
290
+ ]), s = r(e.tenantId), c = r(e.subjectId);
291
+ if (e.kind !== "user" && e.kind !== "guest") throw t("invalid_input");
292
+ return k(async () => (await B(s, c), a.transactional(async (e) => {
293
+ if (await e.updateMany(b.tableName, { admission: 0 }, { where: w("id", L(s, c)) }) !== 1) throw t("invalid_record");
294
+ let n = (await e.query(T(b).where(w("id", L(s, c))).limit(1).descriptor))[0];
295
+ if (!n || n.tenantId !== s || n.id !== L(s, c) || n.erased !== !1 && n.erased !== !0 || n.erased && n.ownerId !== null || !n.erased && n.ownerId !== c) throw t("invalid_record");
296
+ let r = await U(e, y, s, c), a = await U(e, h, s, c), o = await U(e, _, s, c), l = await U(e, v, s, c);
297
+ if (!i) return {
298
+ calendars: r.map((e) => e.state),
299
+ claims: a.map((e) => ({
300
+ before: e.before,
301
+ after: e.after,
302
+ profileVersion: e.profileVersion
303
+ })),
304
+ requests: o.map((e) => e.receipt),
305
+ rewards: l.map((e) => ({
306
+ reward: e.reward,
307
+ state: e.state,
308
+ deliveryIntent: e.deliveryIntent,
309
+ deliveryReceipt: e.deliveryReceipt
310
+ }))
311
+ };
312
+ await e.deleteMany(y.tableName, { where: R(s, c) }), await e.updateMany(h.tableName, {
313
+ ownerId: null,
314
+ ownerKey: null,
315
+ before: null,
316
+ after: null,
317
+ profileVersion: null
318
+ }, { where: R(s, c) }), await e.updateMany(_.tableName, {
319
+ ownerKey: null,
320
+ state: "erased",
321
+ digest: null,
322
+ receipt: null,
323
+ linkedOperationId: null
324
+ }, { where: R(s, c) }), await e.updateMany(v.tableName, {
325
+ ownerId: null,
326
+ ownerKey: null,
327
+ reward: null,
328
+ state: "erased",
329
+ deliveredAt: null,
330
+ deliveryIntent: null,
331
+ deliveryDigest: null,
332
+ deliveryReceipt: null
333
+ }, { where: R(s, c) }), await e.update(b.tableName, L(s, c), {
334
+ ownerId: null,
335
+ erased: !0
336
+ });
337
+ })));
338
+ } catch (n) {
339
+ return x.fail(n instanceof e ? n : t("invalid_input"));
340
+ }
341
+ }, Z = (i, o, s, u) => {
342
+ try {
343
+ let e = n(i);
344
+ I(e);
345
+ let d = r(o), b = r(s);
346
+ return k(async () => (await B(d, b), a.transactional(async (e) => {
347
+ let n = await H(e, d, b), i = await U(e, h, d, b), a = await U(e, _, d, b), o = await U(e, v, d, b), s = [...i].sort((e, t) => Number(e.sequence) - Number(t.sequence)), x = /* @__PURE__ */ new Map(), S = /* @__PURE__ */ new Set(), C = 0;
348
+ if (s.length !== n.sequence) throw t("invalid_record");
349
+ for (let [n, i] of s.entries()) {
350
+ let s = P(r(i.calendarId)), u = x.get(s.id) ?? null, h = c(i.after, s), _ = (await e.query(T(g).where(w("id", D("pdd_", d, s.id, String(s.version)))).limit(1).descriptor))[0];
351
+ if (!_ || _.tenantId !== d || _.calendarId !== s.id || _.version !== s.version || _.rulesVersion !== A.strategies.version || m(_.config) !== m(s)) throw t("conflict");
352
+ let v = a.find((e) => e.id === i.operationId), y = m({
353
+ tenantId: d,
354
+ ownerId: b,
355
+ calendarId: s.id,
356
+ version: s.version
357
+ });
358
+ if (i.sequence !== n + 1 || i.ownerId !== b || i.version !== s.version || i.dayOrdinal !== h.dayOrdinal || i.dayKey !== h.dayKey || i.id !== D("pdl_", d, b, s.id, String(s.version), String(h.dayOrdinal)) || S.has(String(i.id)) || m(i.before) !== m(u) || O(i.at) !== h.at || !v || v.digest !== y || v.linkedOperationId !== null || (r(i.profileVersion), u && (u.dayOrdinal >= h.dayOrdinal || u.timezone !== h.timezone || u.until > h.from || u.at > h.at)) || A.strategies.claimPolicy === l && m(f({
359
+ calendar: s,
360
+ previous: u,
361
+ window: h,
362
+ at: h.at
363
+ })) !== m(h)) throw t("invalid_record");
364
+ let E = W(v, d, b);
365
+ if (E.claimId !== i.id || m(E.after) !== m(h)) throw t("invalid_record");
366
+ let k = o.filter((e) => e.claimId === i.id);
367
+ if (k.length !== E.rewardsQueued) throw t("invalid_record");
368
+ for (let [e, n] of s.days[h.dayIndex].entries()) {
369
+ let r = k.find((t) => t.id === D("pdr_", String(i.id), String(e)));
370
+ if (!r || r.ownerId !== b || r.operationId !== i.operationId || m(r.reward) !== m(n) || O(r.createdAt) !== h.at) throw t("invalid_record");
371
+ p(r, "daily", m), C++;
372
+ }
373
+ S.add(String(i.id)), x.set(s.id, h);
374
+ }
375
+ if (C !== o.length) throw t("invalid_record");
376
+ for (let e of a) if (e.state === "replayed") {
377
+ let n = a.find((t) => t.id === e.linkedOperationId);
378
+ if (!n || n.state !== "committed" || e.digest !== n.digest || e.receipt !== null || O(e.at) < O(n.at)) throw t("invalid_record");
379
+ } else if (e.state !== "committed" || !s.some((t) => t.operationId === e.id)) throw t("invalid_record");
380
+ let E = await U(e, y, d, b), k = /* @__PURE__ */ new Map();
381
+ for (let e of E) {
382
+ let n = P(r(e.calendarId));
383
+ if (k.has(n.id)) throw t("invalid_record");
384
+ k.set(n.id, q(e, d, b, n));
385
+ }
386
+ let j = k.size === x.size && [...x].every(([e, t]) => m(t) === m(k.get(e) ?? null));
387
+ if (u && !j) {
388
+ await e.deleteMany(y.tableName, { where: R(d, b) });
389
+ for (let [t, n] of x) await e.insert(y.tableName, {
390
+ id: D("pdv_", d, b, t, String(n.version)),
391
+ tenantId: d,
392
+ ownerId: b,
393
+ ownerKey: L(d, b),
394
+ calendarId: t,
395
+ version: n.version,
396
+ state: n,
397
+ updatedAt: new Date(n.at)
398
+ });
399
+ }
400
+ return Object.freeze({
401
+ claims: s.length,
402
+ rewardRows: C,
403
+ calendars: x.size,
404
+ matches: u ? !0 : j
405
+ });
406
+ })));
407
+ } catch (n) {
408
+ return x.fail(n instanceof e ? n : t("invalid_input"));
409
+ }
410
+ };
411
+ return Object.freeze({
412
+ claim: J,
413
+ mine: Y,
414
+ exportSubject: (e) => X(e, !1),
415
+ eraseSubject: (e) => x.asVoid(X(e, !0)),
416
+ auditDaily: (e, t, n) => Z(e, t, n, !1),
417
+ rebuildDaily: (e, t, n) => Z(e, t, n, !0)
418
+ });
419
+ };
420
+ //#endregion
421
+ export { A as dataStoreLoginCalendars, E as resolveDailyOptions };
@@ -0,0 +1,138 @@
1
+ import { grant as e } from "./reward.js";
2
+ import { DailyProfileSource as t, LoginCalendarPort as n, defaultDailyClaimPolicy as r, defaultDailyWindow as i, defineLoginCalendar as a, resolveDailyClaim as o } from "./daily.js";
3
+ import { trackDeclaration as s } from "./track.js";
4
+ import { progressionPlugin as c } from "./plugin.js";
5
+ import { progressionFixture as l } from "./declarationFixtures.js";
6
+ import { Effect as u, Layer as d } from "effect";
7
+ import { ensureTableRegistered as f } from "@voltro/database";
8
+ import { InMemoryDataStore as p } from "@voltro/runtime";
9
+ //#region src/dailySystem.fixture.ts
10
+ var m = Date.UTC(2026, 9, 10), h = l(), g = a({
11
+ id: "fixture.daily",
12
+ days: [[e("gold", 1)], [e("gold", 2)]],
13
+ streakProtection: 1
14
+ }), _ = Object.freeze({ read: () => u.succeed({
15
+ timezone: "UTC",
16
+ version: "fixture.profile"
17
+ }) }), v = {
18
+ app: {
19
+ name: "daily-port-fixture",
20
+ type: "api",
21
+ voltroVersion: "0.83.1"
22
+ },
23
+ config: {},
24
+ env: {},
25
+ logger: {
26
+ info() {},
27
+ warn() {},
28
+ error() {},
29
+ debug() {}
30
+ }
31
+ }, y = d.effectContext(u.acquireRelease(u.sync(() => c({
32
+ tracks: [s(h.track)],
33
+ stats: [{ id: "wins" }],
34
+ statSources: ["match.finished"],
35
+ now: () => m,
36
+ daily: {
37
+ calendars: [g],
38
+ profileSource: _,
39
+ now: () => m
40
+ }
41
+ })), (e) => u.suspend(() => e.onDeactivate(v))).pipe(u.tap((e) => u.gen(function* () {
42
+ e.extendSchema.tables.forEach((e) => f(e)), yield* u.promise(() => Promise.resolve(e.bindDataStore(new p())));
43
+ }).pipe(u.orDie)), u.flatMap((e) => d.build(e.services)))), b = d.succeed(t, _), x = {
44
+ type: "user",
45
+ id: "a",
46
+ tenantId: "fixture",
47
+ kind: "guest"
48
+ }, S = Object.freeze({
49
+ kind: "port",
50
+ tag: n,
51
+ fakeLayer: y,
52
+ probe: {
53
+ run: () => u.scoped(u.gen(function* () {
54
+ let e = yield* n, t = {
55
+ calendarId: g.id,
56
+ requestId: "fixture.claim"
57
+ }, r = yield* e.claim(x, t), i = yield* e.claim(x, t);
58
+ return {
59
+ original: r.operationId === i.operationId,
60
+ rewardsQueued: r.rewardsQueued,
61
+ calendars: (yield* e.mine(x)).map((e) => ({
62
+ claimed: e.claimed,
63
+ streak: e.streak,
64
+ dayIndex: e.dayIndex
65
+ }))
66
+ };
67
+ }).pipe(u.provide(y))),
68
+ expected: {
69
+ original: !0,
70
+ rewardsQueued: 1,
71
+ calendars: [{
72
+ claimed: !0,
73
+ streak: 1,
74
+ dayIndex: 0
75
+ }]
76
+ }
77
+ }
78
+ }), C = Object.freeze({
79
+ kind: "port",
80
+ tag: t,
81
+ fakeLayer: b,
82
+ probe: {
83
+ run: () => u.scoped(u.gen(function* () {
84
+ return yield* (yield* t).read(x, {
85
+ tenantId: "fixture",
86
+ ownerId: "a"
87
+ });
88
+ }).pipe(u.provide(b))),
89
+ expected: {
90
+ timezone: "UTC",
91
+ version: "fixture.profile"
92
+ }
93
+ }
94
+ }), w = Object.freeze({
95
+ calendar: g,
96
+ previous: null,
97
+ window: i({
98
+ timezone: "UTC",
99
+ at: m
100
+ }),
101
+ at: m
102
+ }), T = Object.freeze({
103
+ kind: "slot",
104
+ defaultImplementation: r,
105
+ defaultProbe: {
106
+ run: () => u.sync(() => {
107
+ let e = o(w);
108
+ return {
109
+ dayIndex: e.dayIndex,
110
+ streak: e.streak
111
+ };
112
+ }),
113
+ expected: {
114
+ dayIndex: 0,
115
+ streak: 1
116
+ }
117
+ },
118
+ overrideProbe: {
119
+ run: () => u.sync(() => {
120
+ let e = o(w, () => ({
121
+ dayIndex: 1,
122
+ streak: 5,
123
+ protectionRemaining: 0,
124
+ cycle: 0
125
+ }));
126
+ return {
127
+ dayIndex: e.dayIndex,
128
+ streak: e.streak
129
+ };
130
+ }),
131
+ expected: {
132
+ dayIndex: 1,
133
+ streak: 5
134
+ }
135
+ }
136
+ });
137
+ //#endregion
138
+ export { T as dailyClaimPolicySystemFixture, b as dailyProfileSourceFakeLayer, C as dailyProfileSourceSystemFixture, y as loginCalendarFakeLayer, S as loginCalendarPortSystemFixture };
@@ -0,0 +1,90 @@
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
+ //#region src/dailyTables.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_daily_definitions", {
4
+ id: t({ prefix: "pdd" }),
5
+ tenantId: s(),
6
+ calendarId: 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
+ "calendarId",
14
+ "version"
15
+ ]), d = i("_voltro_prog_daily_subjects", {
16
+ id: t({ prefix: "pds" }),
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_daily", {
23
+ id: t({ prefix: "pdv" }),
24
+ tenantId: s(),
25
+ ownerId: c(),
26
+ ownerKey: l(),
27
+ calendarId: a().maxLength(120).safe(),
28
+ version: n().safe(),
29
+ state: r().serverOnly(),
30
+ updatedAt: o().safe()
31
+ }).index(["tenantId", "ownerKey"]), p = i("_voltro_prog_daily_claims", {
32
+ id: t({ prefix: "pdl" }),
33
+ tenantId: s(),
34
+ ownerId: c().nullable(),
35
+ ownerKey: l(),
36
+ calendarId: a().maxLength(120).safe(),
37
+ version: n().safe(),
38
+ dayOrdinal: n().safe(),
39
+ dayKey: a().maxLength(10).safe(),
40
+ sequence: n().serverOnly(),
41
+ operationId: a().maxLength(64).safe(),
42
+ before: r().nullable().serverOnly(),
43
+ after: r().nullable().serverOnly(),
44
+ profileVersion: a().maxLength(120).nullable().serverOnly(),
45
+ at: o().safe()
46
+ }).index(["tenantId", "ownerKey"]), m = i("_voltro_prog_daily_operations", {
47
+ id: t({ prefix: "pdo" }),
48
+ tenantId: s(),
49
+ ownerKey: l(),
50
+ state: a().maxLength(16).oneOf([
51
+ "committed",
52
+ "replayed",
53
+ "erased"
54
+ ]).serverOnly(),
55
+ linkedOperationId: a().maxLength(64).nullable().serverOnly(),
56
+ digest: a().maxLength(64).nullable().serverOnly(),
57
+ receipt: r().nullable().serverOnly(),
58
+ at: o().safe()
59
+ }).index(["tenantId", "ownerKey"]), h = i("_voltro_prog_daily_rewards", {
60
+ id: t({ prefix: "pdr" }),
61
+ tenantId: s(),
62
+ ownerId: c().nullable(),
63
+ ownerKey: l(),
64
+ claimId: a().maxLength(64).safe(),
65
+ operationId: a().maxLength(64).safe(),
66
+ reward: r().nullable().serverOnly(),
67
+ state: a().maxLength(16).oneOf([
68
+ "pending",
69
+ "delivered",
70
+ "erased"
71
+ ]).serverOnly(),
72
+ createdAt: o().safe(),
73
+ deliveredAt: o().nullable().safe(),
74
+ deliveryIntent: r().nullable().serverOnly(),
75
+ deliveryDigest: a().maxLength(64).nullable().serverOnly(),
76
+ deliveryReceipt: r().nullable().serverOnly()
77
+ }).index([
78
+ "tenantId",
79
+ "ownerKey",
80
+ "state"
81
+ ]), g = [
82
+ u,
83
+ d,
84
+ f,
85
+ p,
86
+ m,
87
+ h
88
+ ];
89
+ //#endregion
90
+ export { p as dailyClaimsTable, u as dailyDefinitionsTable, m as dailyOperationsTable, h as dailyRewardsTable, f as dailyStatesTable, d as dailySubjectsTable, g as dailyTables };