@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,464 @@
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 { questHash as c } from "./questStore.js";
4
+ import { captureResourceState as l, defaultResourceRegen as u, defineRegenResource as d, resolveResourceRegen as f } from "./resources.js";
5
+ import { resourceDefinitionsTable as p, resourceMovementsTable as m, resourceOperationsTable as h, resourceOriginsTable as g, resourceSubjectsTable as _, resourcesTable as v } from "./resourceTables.entity.js";
6
+ import { Effect as y } from "effect";
7
+ import { and as b, eq as x, queryFor as S } from "@voltro/database";
8
+ //#region src/resourceStore.ts
9
+ var C = (e) => {
10
+ let n = o(e, [
11
+ "definitions",
12
+ "sources",
13
+ "allowedServices",
14
+ "maxHistoryRows",
15
+ "now",
16
+ "strategies"
17
+ ]), s = Object.freeze(a(n.definitions, 64).map((e) => d(e))), c = (e, n) => {
18
+ let i = Object.freeze(a(e, n).map(r));
19
+ if (new Set(i).size !== i.length) throw t("invalid_input");
20
+ return i;
21
+ }, l = o(n.strategies ?? {}, ["regen", "version"]), f = l.regen ?? u, p = n.now ?? Date.now;
22
+ if (s.length < 1 || new Set(s.map((e) => e.id)).size !== s.length || typeof f != "function" || typeof p != "function" || f !== u && l.version === void 0) throw t("invalid_input");
23
+ return Object.freeze({
24
+ definitions: s,
25
+ sources: c(n.sources, 64),
26
+ allowedServices: c(n.allowedServices ?? [], 256),
27
+ maxHistoryRows: i(n.maxHistoryRows ?? 1e4, 1, 1e5),
28
+ now: p,
29
+ strategies: Object.freeze({
30
+ regen: f,
31
+ version: r(l.version ?? "default.v1")
32
+ })
33
+ });
34
+ }, w = (e, ...t) => e + c(t).slice(0, 56), T = (e) => {
35
+ let n = e instanceof Date ? e.getTime() : typeof e == "string" ? Date.parse(e) : NaN;
36
+ if (!Number.isSafeInteger(n) || n < 0 || n > 864e13) throw t("invalid_record");
37
+ return n;
38
+ }, E = (n) => y.tryPromise({
39
+ try: n,
40
+ catch: (n) => n instanceof e ? n : t("unavailable")
41
+ }), D = (a, u) => {
42
+ let d = C(u), D = new Map(d.definitions.map((e) => [e.id, e])), O = new Set(d.allowedServices), k = () => i(d.now(), 0, 864e13), A = (e) => {
43
+ if (e.type !== "system" && !(e.type === "service" && O.has(e.service))) throw t("forbidden");
44
+ }, j = (e, t) => w("prs_", e, t), M = (e, t) => b(x("tenantId", e), x("ownerId", t)), N = (e, t) => b(x("tenantId", e), x("ownerKey", t)), P = async (e, t) => {
45
+ try {
46
+ await a.insertIgnore(e, t, { conflictColumns: ["id"] });
47
+ } catch (n) {
48
+ if (!(await a.query({
49
+ table: e,
50
+ predicate: x("id", t.id),
51
+ order: [],
52
+ take: 1,
53
+ skip: void 0,
54
+ projection: void 0
55
+ }))[0]) throw n;
56
+ }
57
+ }, F = (e, t) => P(_.tableName, {
58
+ id: j(e, t),
59
+ tenantId: e,
60
+ ownerId: t,
61
+ erased: !1,
62
+ sequence: 0,
63
+ admission: 0
64
+ }), I = (e, n, r, a = !1) => {
65
+ if (e) {
66
+ if (e.id !== j(n, r) || e.tenantId !== n || typeof e.erased != "boolean") throw t("invalid_record");
67
+ if (e.erased) {
68
+ if (a && e.ownerId === null) return;
69
+ throw t("erased");
70
+ }
71
+ if (e.ownerId !== r) throw t("invalid_record");
72
+ i(e.sequence, 0, 2147483647);
73
+ }
74
+ }, L = async (e, n, r, i = !1) => {
75
+ let a = j(n, r);
76
+ if (await e.updateMany(_.tableName, { admission: 0 }, { where: x("id", a) }) !== 1) throw t("unavailable");
77
+ let o = (await e.query(S(_).where(x("id", a)).limit(1).descriptor))[0];
78
+ if (!o) throw t("invalid_record");
79
+ return I(o, n, r, i), o;
80
+ }, R = async (e, n, r, i) => {
81
+ let a = await e.query(S(n).where(N(r, i)).limit(d.maxHistoryRows + 1).descriptor);
82
+ if (a.length > d.maxHistoryRows) throw t("limit_exceeded");
83
+ if (a.some((e) => e.tenantId !== r || e.ownerKey !== i)) throw t("invalid_record");
84
+ return a;
85
+ }, z = async (e, n, r) => {
86
+ let i = await e.query(S(v).where(M(n, r)).limit(65).descriptor);
87
+ if (i.length > 64) throw t("limit_exceeded");
88
+ return i;
89
+ }, B = (e) => {
90
+ let n = D.get(e);
91
+ if (!n) throw t("invalid_input");
92
+ return n;
93
+ }, V = (e, n, r, i) => {
94
+ if (e.id !== w("prv_", n, r, i.id) || e.tenantId !== n || e.ownerId !== r || e.resourceId !== i.id || e.version !== i.version) throw t("invalid_record");
95
+ return l({
96
+ value: e.value,
97
+ anchorAt: T(e.anchorAt)
98
+ }, i);
99
+ }, H = (e) => {
100
+ let n = o(e.receipt, [
101
+ "operationId",
102
+ "kind",
103
+ "resourceId",
104
+ "amount",
105
+ "regenerated",
106
+ "after",
107
+ "at"
108
+ ]);
109
+ if (n.operationId !== e.id || n.kind !== "initialize" && n.kind !== "consume" && n.kind !== "grant" || n.at !== T(e.at)) throw t("invalid_record");
110
+ let a = B(r(n.resourceId)), c = l(n.after, a), u = s(n.amount), d = s(n.regenerated), f = i(n.at, c.anchorAt, 864e13);
111
+ if (n.kind === "initialize" != (u === 0n)) throw t("invalid_record");
112
+ return Object.freeze({
113
+ operationId: r(e.id),
114
+ kind: n.kind,
115
+ resourceId: a.id,
116
+ amount: String(u),
117
+ regenerated: String(d),
118
+ after: c,
119
+ at: f
120
+ });
121
+ }, U = async (e, n, r) => {
122
+ let i = w("prd_", n, r.id, String(r.version));
123
+ if (await e.updateMany(p.tableName, { admission: 0 }, { where: x("id", i) }) !== 1) throw t("unavailable");
124
+ let a = (await e.query(S(p).where(x("id", i)).limit(1).descriptor))[0];
125
+ if (!a || a.tenantId !== n || a.resourceId !== r.id || a.version !== r.version || a.rulesVersion !== d.strategies.version || c(a.config) !== c(r)) throw t("conflict");
126
+ }, W = (u, b, C) => {
127
+ try {
128
+ let e = n(b), y = o(C, [
129
+ "tenantId",
130
+ "ownerId",
131
+ "resourceId",
132
+ "requestId",
133
+ "source",
134
+ "origin",
135
+ ...u === "initialize" ? [] : ["amount"]
136
+ ]);
137
+ A(e);
138
+ let D = r(y.tenantId), O = r(y.ownerId), M = B(r(y.resourceId)), N = r(y.requestId), I = r(y.source), z = r(y.origin);
139
+ if (!d.sources.includes(I)) throw t("forbidden");
140
+ let W = u === "initialize" ? 0n : s(y.amount);
141
+ if (u !== "initialize" && W === 0n) throw t("invalid_input");
142
+ let G = j(D, O), K = w("pro_", D, O, N), q = w("prn_", D, O, M.id, u, I, z), J = c({
143
+ tenantId: D,
144
+ ownerId: O,
145
+ resourceId: M.id,
146
+ version: M.version,
147
+ kind: u,
148
+ amount: String(W),
149
+ source: I,
150
+ origin: z
151
+ });
152
+ return E(async () => {
153
+ let e = k();
154
+ return await F(D, O), await P(p.tableName, {
155
+ id: w("prd_", D, M.id, String(M.version)),
156
+ tenantId: D,
157
+ resourceId: M.id,
158
+ version: M.version,
159
+ config: M,
160
+ rulesVersion: d.strategies.version,
161
+ admission: 0
162
+ }), a.transactional(async (n) => {
163
+ let r = await L(n, D, O), a = await R(n, h, D, G), o = (e) => {
164
+ if (e.digest !== J) throw t("conflict");
165
+ if (e.state === "committed" && e.linkedOperationId === null) return H(e);
166
+ if (e.state !== "replayed" || typeof e.linkedOperationId != "string") throw t("invalid_record");
167
+ let n = a.find((t) => t.id === e.linkedOperationId);
168
+ if (!n || n.state !== "committed" || n.digest !== J || n.linkedOperationId !== null) throw t("invalid_record");
169
+ return H(n);
170
+ }, s = a.find((e) => e.id === K);
171
+ if (s) return o(s);
172
+ if (a.length >= d.maxHistoryRows) throw t("limit_exceeded");
173
+ let p = await R(n, g, D, G), y = p.find((e) => e.id === q);
174
+ if (y) {
175
+ if (y.source !== I || y.origin !== z || y.digest !== J) throw t("conflict");
176
+ let r = a.find((e) => e.id === y.operationId);
177
+ if (!r || r.state !== "committed") throw t("invalid_record");
178
+ let i = o(r);
179
+ if (e < T(r.at)) throw t("conflict");
180
+ return await n.insert(h.tableName, {
181
+ id: K,
182
+ tenantId: D,
183
+ ownerKey: G,
184
+ state: "replayed",
185
+ linkedOperationId: r.id,
186
+ digest: J,
187
+ receipt: null,
188
+ at: new Date(e)
189
+ }), i;
190
+ }
191
+ await U(n, D, M);
192
+ let b = await R(n, m, D, G);
193
+ if (b.length >= d.maxHistoryRows || p.length >= d.maxHistoryRows) throw t("limit_exceeded");
194
+ let C = w("prv_", D, O, M.id), E = (await n.query(S(v).where(x("id", C)).limit(1).descriptor))[0];
195
+ if (u === "initialize" && E) throw t("conflict");
196
+ if (b.length !== r.sequence || a.filter((e) => e.state === "committed").length !== b.length) throw t("invalid_record");
197
+ let k = E ? V(E, D, O, M) : null, A = b.filter((e) => e.resourceId === M.id).reduce((e, t) => (i(t.sequence, 1, 2147483647), !e || Number(t.sequence) > Number(e.sequence) ? t : e), void 0);
198
+ if (A && (A.version !== M.version || c(l(A.after, M)) !== c(k)) || !A && k !== null) throw t("invalid_record");
199
+ let j = k ?? {
200
+ value: M.initial,
201
+ anchorAt: e
202
+ };
203
+ if (j.anchorAt > e) throw t("conflict");
204
+ let N = f({
205
+ resource: M,
206
+ state: j,
207
+ at: e
208
+ }, d.strategies.regen), P = BigInt(N.value) - BigInt(j.value), F = BigInt(N.value);
209
+ if (u === "consume") {
210
+ if (W > F) throw t("insufficient_resource");
211
+ F -= W;
212
+ }
213
+ if (u === "grant" && (F += W, F > BigInt(M.max))) throw t("overflow");
214
+ let B = Object.freeze({
215
+ value: String(F),
216
+ anchorAt: F === BigInt(M.max) ? e : N.anchorAt
217
+ }), Y = i(Number(r.sequence) + 1, 1, 2147483647), X = Object.freeze({
218
+ operationId: K,
219
+ kind: u,
220
+ resourceId: M.id,
221
+ amount: String(W),
222
+ regenerated: String(P),
223
+ after: B,
224
+ at: e
225
+ });
226
+ return E ? await n.update(v.tableName, C, {
227
+ value: B.value,
228
+ anchorAt: new Date(B.anchorAt)
229
+ }) : await n.insert(v.tableName, {
230
+ id: C,
231
+ tenantId: D,
232
+ ownerId: O,
233
+ resourceId: M.id,
234
+ version: M.version,
235
+ value: B.value,
236
+ anchorAt: new Date(B.anchorAt)
237
+ }), await n.insert(m.tableName, {
238
+ id: w("prm_", K),
239
+ tenantId: D,
240
+ ownerId: O,
241
+ ownerKey: G,
242
+ resourceId: M.id,
243
+ version: M.version,
244
+ operationId: K,
245
+ sequence: Y,
246
+ kind: u,
247
+ amount: String(W),
248
+ regenerated: String(P),
249
+ before: k,
250
+ after: B,
251
+ source: I,
252
+ origin: z,
253
+ at: new Date(e)
254
+ }), await n.insert(h.tableName, {
255
+ id: K,
256
+ tenantId: D,
257
+ ownerKey: G,
258
+ state: "committed",
259
+ linkedOperationId: null,
260
+ digest: J,
261
+ receipt: X,
262
+ at: new Date(e)
263
+ }), await n.insert(g.tableName, {
264
+ id: q,
265
+ tenantId: D,
266
+ ownerKey: G,
267
+ operationId: K,
268
+ source: I,
269
+ origin: z,
270
+ digest: J
271
+ }), await n.update(_.tableName, G, { sequence: Y }), X;
272
+ });
273
+ });
274
+ } catch (n) {
275
+ return y.fail(n instanceof e ? n : t("invalid_input"));
276
+ }
277
+ }, G = (i) => {
278
+ try {
279
+ let e = n(i);
280
+ if (e.type !== "user") throw t("forbidden");
281
+ let o = r(e.tenantId), s = r(e.id);
282
+ return E(() => a.transactional(async (e) => {
283
+ let n = (await e.query(S(_).where(x("id", j(o, s))).forUpdate().limit(1).descriptor))[0];
284
+ I(n, o, s);
285
+ let r = await z(e, o, s), i = k();
286
+ if (!n && r.length !== 0 || r.some((e) => !D.has(String(e.resourceId)))) throw t("invalid_record");
287
+ return Object.freeze(d.definitions.map((e) => {
288
+ let n = r.find((t) => t.resourceId === e.id), a = n ? V(n, o, s, e) : {
289
+ value: e.initial,
290
+ anchorAt: i
291
+ };
292
+ if (a.anchorAt > i) throw t("conflict");
293
+ let c = f({
294
+ resource: e,
295
+ state: a,
296
+ at: i
297
+ }, d.strategies.regen), l = c.anchorAt + e.regenEveryMs;
298
+ return Object.freeze({
299
+ resourceId: e.id,
300
+ value: c.value,
301
+ max: e.max,
302
+ initialized: n !== void 0,
303
+ observedAt: i,
304
+ nextRegenAt: c.value === e.max || !n || l > 864e13 ? null : l,
305
+ ...e.refillOffer === void 0 ? {} : { refillOffer: e.refillOffer }
306
+ });
307
+ }));
308
+ }));
309
+ } catch (n) {
310
+ return y.fail(n instanceof e ? n : t("invalid_input"));
311
+ }
312
+ }, K = (n, i) => {
313
+ try {
314
+ let e = o(n, [
315
+ "tenantId",
316
+ "subjectId",
317
+ "kind"
318
+ ]), s = r(e.tenantId), c = r(e.subjectId), l = j(s, c);
319
+ if (e.kind !== "user" && e.kind !== "guest") throw t("forbidden");
320
+ return E(async () => (await F(s, c), a.transactional(async (e) => {
321
+ await L(e, s, c, !0);
322
+ let t = await z(e, s, c), n = await R(e, m, s, l);
323
+ if (await R(e, h, s, l), await R(e, g, s, l), !i) return {
324
+ resources: t.map((e) => ({
325
+ resourceId: e.resourceId,
326
+ value: String(e.value),
327
+ anchorAt: T(e.anchorAt)
328
+ })),
329
+ movements: n.map((e) => ({
330
+ resourceId: e.resourceId,
331
+ kind: e.kind,
332
+ amount: String(e.amount),
333
+ regenerated: String(e.regenerated),
334
+ before: e.before,
335
+ after: e.after,
336
+ at: T(e.at)
337
+ }))
338
+ };
339
+ await e.deleteMany(v.tableName, { where: M(s, c) }), await e.updateMany(m.tableName, {
340
+ ownerId: null,
341
+ ownerKey: null,
342
+ before: null,
343
+ after: null,
344
+ source: null,
345
+ origin: null
346
+ }, { where: N(s, l) }), await e.updateMany(h.tableName, {
347
+ ownerKey: null,
348
+ state: "erased",
349
+ linkedOperationId: null,
350
+ digest: null,
351
+ receipt: null
352
+ }, { where: N(s, l) }), await e.updateMany(g.tableName, {
353
+ ownerKey: null,
354
+ source: null,
355
+ origin: null,
356
+ digest: null
357
+ }, { where: N(s, l) }), await e.update(_.tableName, l, {
358
+ ownerId: null,
359
+ erased: !0
360
+ });
361
+ })));
362
+ } catch (n) {
363
+ return y.fail(n instanceof e ? n : t("invalid_input"));
364
+ }
365
+ }, q = (o, u, f, p) => {
366
+ try {
367
+ let e = n(o);
368
+ A(e);
369
+ let _ = r(u), y = r(f), b = j(_, y);
370
+ return E(async () => {
371
+ let e = k();
372
+ return await F(_, y), a.transactional(async (n) => {
373
+ let a = await L(n, _, y), o = await R(n, m, _, b), u = await R(n, h, _, b), f = await R(n, g, _, b), x = [...o].sort((e, t) => Number(e.sequence) - Number(t.sequence)), S = /* @__PURE__ */ new Map();
374
+ if (x.length !== a.sequence || u.filter((e) => e.state === "committed").length !== x.length || f.length !== x.length) throw t("invalid_record");
375
+ for (let [e, a] of x.entries()) {
376
+ let o = B(r(a.resourceId));
377
+ await U(n, _, o);
378
+ let p = i(a.sequence, 1, 2147483647), m = T(a.at), h = s(a.amount), g = s(a.regenerated);
379
+ if (p !== e + 1 || a.version !== o.version || a.ownerId !== y || a.id !== w("prm_", r(a.operationId))) throw t("invalid_record");
380
+ let v = a.before === null ? null : l(a.before, o), b = l(a.after, o), x = S.get(o.id);
381
+ if (c(v) !== c(x ?? null) || b.anchorAt > m || v && (v.anchorAt > m || b.anchorAt < v.anchorAt)) throw t("invalid_record");
382
+ let C = v ?? {
383
+ value: o.initial,
384
+ anchorAt: m
385
+ }, E = a.kind;
386
+ if (E !== "initialize" && E !== "consume" && E !== "grant" || E === "initialize" != (h === 0n) || E === "initialize" && x !== void 0) throw t("invalid_record");
387
+ let D = BigInt(C.value) + g;
388
+ if (D > BigInt(o.max) || D < h && E === "consume" || BigInt(b.value) !== D + (E === "grant" ? h : E === "consume" ? -h : 0n)) throw t("invalid_record");
389
+ let O = u.find((e) => e.id === a.operationId), k = r(a.source), A = r(a.origin), j = c({
390
+ tenantId: _,
391
+ ownerId: y,
392
+ resourceId: o.id,
393
+ version: o.version,
394
+ kind: E,
395
+ amount: String(h),
396
+ source: k,
397
+ origin: A
398
+ });
399
+ if (!O || O.state !== "committed" || O.linkedOperationId !== null || O.digest !== j || !d.sources.includes(k)) throw t("invalid_record");
400
+ let M = H(O), N = {
401
+ operationId: a.operationId,
402
+ kind: E,
403
+ resourceId: o.id,
404
+ amount: String(h),
405
+ regenerated: String(g),
406
+ after: b,
407
+ at: m
408
+ };
409
+ if (c(M) !== c(N)) throw t("invalid_record");
410
+ let P = f.find((e) => e.id === w("prn_", _, y, o.id, E, k, A));
411
+ if (!P || P.operationId !== a.operationId || P.source !== k || P.origin !== A || P.digest !== j) throw t("invalid_record");
412
+ S.set(o.id, b);
413
+ }
414
+ for (let e of u) if (e.state === "replayed") {
415
+ let n = u.find((t) => t.id === e.linkedOperationId);
416
+ if (!n || n.state !== "committed" || e.digest !== n.digest || e.receipt !== null || T(e.at) < T(n.at)) throw t("invalid_record");
417
+ } else if (e.state !== "committed") throw t("invalid_record");
418
+ let C = await z(n, _, y), E = /* @__PURE__ */ new Map();
419
+ for (let e of C) {
420
+ let n = B(r(e.resourceId));
421
+ if (E.has(n.id)) throw t("invalid_record");
422
+ E.set(n.id, V(e, _, y, n));
423
+ }
424
+ let D = S.size === E.size && [...S].every(([e, t]) => c(t) === c(E.get(e) ?? null));
425
+ if (p && !D) {
426
+ await n.deleteMany(v.tableName, { where: M(_, y) });
427
+ for (let [e, t] of S) {
428
+ let r = B(e);
429
+ await n.insert(v.tableName, {
430
+ id: w("prv_", _, y, e),
431
+ tenantId: _,
432
+ ownerId: y,
433
+ resourceId: e,
434
+ version: r.version,
435
+ value: t.value,
436
+ anchorAt: new Date(t.anchorAt)
437
+ });
438
+ }
439
+ }
440
+ return Object.freeze({
441
+ acceptedOperations: x.length,
442
+ resources: S.size,
443
+ matches: p ? !0 : D,
444
+ at: e
445
+ });
446
+ });
447
+ });
448
+ } catch (n) {
449
+ return y.fail(n instanceof e ? n : t("invalid_input"));
450
+ }
451
+ };
452
+ return Object.freeze({
453
+ initialize: (e, t) => W("initialize", e, t),
454
+ consume: (e, t) => W("consume", e, t),
455
+ grant: (e, t) => W("grant", e, t),
456
+ mine: G,
457
+ exportSubject: (e) => K(e, !1),
458
+ eraseSubject: (e) => y.asVoid(K(e, !0)),
459
+ auditResources: (e, t, n) => q(e, t, n, !1),
460
+ rebuildResources: (e, t, n) => q(e, t, n, !0)
461
+ });
462
+ };
463
+ //#endregion
464
+ export { D as dataStoreResources, C as resolveResourceOptions };
@@ -0,0 +1,89 @@
1
+ import { bigint as e, boolean as t, id as n, integer as r, json as i, table as a, text as o, timestamp as s } from "@voltro/database";
2
+ //#region src/resourceTables.entity.ts
3
+ var c = () => o().maxLength(120).externalId().sensitive("pii"), l = () => o().maxLength(120).externalId().sensitive("pii"), u = () => o().maxLength(64).nullable().serverOnly(), d = a("_voltro_prog_resource_definitions", {
4
+ id: n({ prefix: "prd" }),
5
+ tenantId: c(),
6
+ resourceId: o().maxLength(120).safe(),
7
+ version: r().safe(),
8
+ config: i().safe(),
9
+ rulesVersion: o().maxLength(120).safe(),
10
+ admission: r().serverOnly()
11
+ }).index("voltro_prog_resource_definitions_version_idx", [
12
+ "tenantId",
13
+ "resourceId",
14
+ "version"
15
+ ]), f = a("_voltro_prog_resource_subjects", {
16
+ id: n({ prefix: "prs" }),
17
+ tenantId: c(),
18
+ ownerId: l().nullable(),
19
+ erased: t().serverOnly(),
20
+ sequence: r().serverOnly(),
21
+ admission: r().serverOnly()
22
+ }).index(["tenantId", "ownerId"]), p = a("_voltro_prog_resources", {
23
+ id: n({ prefix: "prv" }),
24
+ tenantId: c(),
25
+ ownerId: l(),
26
+ resourceId: o().maxLength(120).safe(),
27
+ version: r().safe(),
28
+ value: e().safe(),
29
+ anchorAt: s().safe()
30
+ }).index([
31
+ "tenantId",
32
+ "ownerId",
33
+ "resourceId"
34
+ ]), m = a("_voltro_prog_resource_movements", {
35
+ id: n({ prefix: "prm" }),
36
+ tenantId: c(),
37
+ ownerId: l().nullable(),
38
+ ownerKey: u(),
39
+ resourceId: o().maxLength(120).safe(),
40
+ version: r().safe(),
41
+ operationId: o().maxLength(64).safe(),
42
+ sequence: r().serverOnly(),
43
+ kind: o().maxLength(16).oneOf([
44
+ "initialize",
45
+ "consume",
46
+ "grant"
47
+ ]).safe(),
48
+ amount: e().safe(),
49
+ regenerated: e().safe(),
50
+ before: i().nullable().serverOnly(),
51
+ after: i().nullable().serverOnly(),
52
+ source: o().maxLength(120).nullable().safe(),
53
+ origin: o().maxLength(120).nullable().sensitive("pii"),
54
+ at: s().safe()
55
+ }).index("voltro_prog_resource_movements_owner_idx", [
56
+ "tenantId",
57
+ "ownerKey",
58
+ "resourceId"
59
+ ]), h = a("_voltro_prog_resource_operations", {
60
+ id: n({ prefix: "pro" }),
61
+ tenantId: c(),
62
+ ownerKey: u(),
63
+ state: o().maxLength(16).oneOf([
64
+ "committed",
65
+ "replayed",
66
+ "erased"
67
+ ]).serverOnly(),
68
+ linkedOperationId: o().maxLength(64).nullable().serverOnly(),
69
+ digest: o().maxLength(64).nullable().serverOnly(),
70
+ receipt: i().nullable().serverOnly(),
71
+ at: s().safe()
72
+ }).index(["tenantId", "ownerKey"]), g = a("_voltro_prog_resource_origins", {
73
+ id: n({ prefix: "prn" }),
74
+ tenantId: c(),
75
+ ownerKey: u(),
76
+ operationId: o().maxLength(64).safe(),
77
+ source: o().maxLength(120).nullable().safe(),
78
+ origin: o().maxLength(120).nullable().sensitive("pii"),
79
+ digest: o().maxLength(64).nullable().serverOnly()
80
+ }).index(["tenantId", "ownerKey"]), _ = [
81
+ d,
82
+ f,
83
+ p,
84
+ m,
85
+ h,
86
+ g
87
+ ];
88
+ //#endregion
89
+ export { d as resourceDefinitionsTable, m as resourceMovementsTable, h as resourceOperationsTable, g as resourceOriginsTable, f as resourceSubjectsTable, _ as resourceTables, p as resourcesTable };
@@ -0,0 +1,105 @@
1
+ import { Context } from 'effect';
2
+ import { Effect } from 'effect';
3
+ import { PluginPrivacyTarget } from '@voltro/protocol';
4
+ import { Schema } from 'effect';
5
+ import { Subject } from '@voltro/protocol';
6
+ import { YieldableError } from 'effect/Cause';
7
+
8
+ export declare const captureResourceState: (input: unknown, resource: RegenResource) => ResourceState;
9
+
10
+ export declare const defaultResourceRegen: ResourceRegenResolver;
11
+
12
+ export declare const defineRegenResource: (input: RegenResourceDefinition | RegenResource) => RegenResource;
13
+
14
+ export declare type InitializeResourceInput = Omit<ResourceChangeInput, 'amount'>;
15
+
16
+ export declare interface PlayerResource {
17
+ readonly resourceId: string;
18
+ readonly value: string;
19
+ readonly max: string;
20
+ readonly initialized: boolean;
21
+ readonly observedAt: number;
22
+ readonly nextRegenAt: number | null;
23
+ readonly refillOffer?: string;
24
+ }
25
+
26
+ declare class ProgressionError extends ProgressionError_base {
27
+ }
28
+
29
+ declare const ProgressionError_base: Schema.Class<ProgressionError, Schema.TaggedStruct<"ProgressionError", {
30
+ readonly code: Schema.Literals<readonly ["invalid_input", "invalid_record", "invalid_curve", "invalid_reward", "invalid_track", "invalid_stat", "overflow", "insufficient_resource", "forbidden", "conflict", "erased", "not_found", "limit_exceeded", "unavailable"]>;
31
+ }>, YieldableError>;
32
+
33
+ declare type ProgressValue = string | number | bigint;
34
+
35
+ export declare interface RegenResource {
36
+ readonly id: string;
37
+ readonly version: number;
38
+ readonly max: string;
39
+ readonly initial: string;
40
+ readonly regenPer: string;
41
+ readonly regenAmount: string;
42
+ readonly regenEveryMs: number;
43
+ readonly refillOffer?: string;
44
+ }
45
+
46
+ export declare interface RegenResourceDefinition {
47
+ readonly id: string;
48
+ readonly version?: number;
49
+ readonly max: ProgressValue;
50
+ readonly initial?: ProgressValue;
51
+ readonly regenPer: string;
52
+ readonly regenAmount?: ProgressValue;
53
+ readonly refillOffer?: string;
54
+ }
55
+
56
+ export declare class RegenResourcePort extends RegenResourcePort_base {
57
+ }
58
+
59
+ declare const RegenResourcePort_base: Context.ServiceClass<RegenResourcePort, "@voltro/RegenResourcePort", RegenResourceService>;
60
+
61
+ export declare interface RegenResourceService {
62
+ readonly initialize: (subject: Subject, input: InitializeResourceInput) => Effect.Effect<ResourceReceipt, ProgressionError>;
63
+ readonly consume: (subject: Subject, input: ResourceChangeInput) => Effect.Effect<ResourceReceipt, ProgressionError>;
64
+ readonly grant: (subject: Subject, input: ResourceChangeInput) => Effect.Effect<ResourceReceipt, ProgressionError>;
65
+ readonly mine: (subject: Subject) => Effect.Effect<readonly PlayerResource[], ProgressionError>;
66
+ readonly exportSubject: (target: PluginPrivacyTarget) => Effect.Effect<unknown, ProgressionError>;
67
+ readonly eraseSubject: (target: PluginPrivacyTarget) => Effect.Effect<void, ProgressionError>;
68
+ }
69
+
70
+ export declare const resolveResourceRegen: (input: ResourceRegenContext, slot?: ResourceRegenResolver) => ResourceState;
71
+
72
+ export declare interface ResourceChangeInput {
73
+ readonly tenantId: string;
74
+ readonly ownerId: string;
75
+ readonly resourceId: string;
76
+ readonly requestId: string;
77
+ readonly source: string;
78
+ readonly origin: string;
79
+ readonly amount: ProgressValue;
80
+ }
81
+
82
+ export declare interface ResourceReceipt {
83
+ readonly operationId: string;
84
+ readonly kind: 'initialize' | 'consume' | 'grant';
85
+ readonly resourceId: string;
86
+ readonly amount: string;
87
+ readonly regenerated: string;
88
+ readonly after: ResourceState;
89
+ readonly at: number;
90
+ }
91
+
92
+ export declare interface ResourceRegenContext {
93
+ readonly resource: RegenResource;
94
+ readonly state: ResourceState;
95
+ readonly at: number;
96
+ }
97
+
98
+ export declare type ResourceRegenResolver = (input: ResourceRegenContext) => ResourceState;
99
+
100
+ export declare interface ResourceState {
101
+ readonly value: string;
102
+ readonly anchorAt: number;
103
+ }
104
+
105
+ export { }