@voltro/plugin-saves 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.
@@ -0,0 +1,412 @@
1
+ import { SaveConflict as e, SavesError as t, savesError as n } from "./errors.js";
2
+ import { SaveHeaderSchema as r, captureSavePut as i, saveData as a, saveId as o, saveInteger as s, saveOwner as c, saveSummary as l } from "./contract.js";
3
+ import { resolveSaveValidation as u, resolveSavesOptions as d } from "./strategies.js";
4
+ import { savesHistoryTable as f, savesRequestsTable as p, savesSubjectsTable as m, savesTable as h } from "./tables.entity.js";
5
+ import { Effect as g, Result as _, Schema as v } from "effect";
6
+ import { createHash as y } from "node:crypto";
7
+ import { and as b, eq as x, queryFor as S } from "@voltro/database";
8
+ // src/service.server.ts
9
+ var C = (e) => Array.isArray(e) ? e.map(C) : e && typeof e == "object" ? Object.fromEntries(Object.keys(e).sort().map((t) => [t, C(e[t])])) : e, w = (e) => y("sha256").update(JSON.stringify(C(e))).digest("hex"), T = (e) => y("sha256").update(e).digest("hex"), E = (e, ...t) => e + w(t).slice(0, 48), D = (r) => r instanceof t || r instanceof e ? r : n("unavailable"), O = (e) => g.tryPromise({
10
+ try: e,
11
+ catch: D
12
+ }), k = (e) => {
13
+ let t = e instanceof Date ? e.getTime() : typeof e == "string" ? Date.parse(e) : e;
14
+ try {
15
+ return s(t, 0, 864e13);
16
+ } catch {
17
+ throw n("invalid_record");
18
+ }
19
+ }, A = (e) => {
20
+ try {
21
+ let t = v.decodeUnknownSync(r)({
22
+ slot: e.slot,
23
+ version: e.version,
24
+ schemaVersion: e.schemaVersion,
25
+ byteLength: e.byteLength,
26
+ checksum: e.checksum,
27
+ deviceId: e.deviceId,
28
+ clientVersion: e.clientVersion,
29
+ savedAt: k(e.savedAt),
30
+ summary: e.summary,
31
+ deletedUntil: e.deletedUntil === null ? null : k(e.deletedUntil)
32
+ });
33
+ if (t.version < 1 || t.schemaVersion < 1 || t.byteLength > 1048576 || !/^[a-f0-9]{64}$/.test(t.checksum)) throw n("invalid_record");
34
+ return o(t.slot), o(t.deviceId), o(t.clientVersion), Object.freeze({
35
+ ...t,
36
+ summary: l(t.summary)
37
+ });
38
+ } catch {
39
+ throw n("invalid_record");
40
+ }
41
+ }, j = (e) => {
42
+ let t = A(e);
43
+ if (!(e.bytes instanceof Uint8Array) || e.bytes.byteLength !== t.byteLength || T(e.bytes) !== t.checksum) throw n("invalid_record");
44
+ return Object.freeze({
45
+ ...t,
46
+ bytes: Uint8Array.from(e.bytes)
47
+ });
48
+ }, M = [
49
+ "id",
50
+ "tenantId",
51
+ "gameId",
52
+ "ownerId",
53
+ "ownerKey",
54
+ "slot",
55
+ "version",
56
+ "schemaVersion",
57
+ "byteLength",
58
+ "checksum",
59
+ "deviceId",
60
+ "clientVersion",
61
+ "savedAt",
62
+ "summary",
63
+ "deletedUntil"
64
+ ], N = (l, y, C = () => {}) => {
65
+ let k = a(y, [
66
+ "gameId",
67
+ "slots",
68
+ "maxBytes",
69
+ "historyVersions",
70
+ "maxRequests",
71
+ "deleteGraceMs",
72
+ "version",
73
+ "validator",
74
+ "schema",
75
+ "schemaVersion",
76
+ "now",
77
+ "admitWrite"
78
+ ]), N = k.admitWrite, P = Object.fromEntries(Object.entries(k).filter(([e]) => e !== "admitWrite")), F = d(P);
79
+ if (typeof N != "function" || typeof C != "function") throw n("invalid_input");
80
+ let I = (e) => E("svs_", e.tenantId, F.gameId, e.ownerId), L = (e, t) => E("sv_", I(e), t), R = (e, t, n) => E("svh_", I(e), t, n), z = (e) => b(x("tenantId", e.tenantId), x("gameId", F.gameId), x("ownerKey", I(e)), x("ownerId", e.ownerId)), B = (e, t) => {
81
+ if (e.tenantId !== t.tenantId || e.gameId !== F.gameId || e.ownerId !== t.ownerId || e.ownerKey !== I(t)) throw n("invalid_record");
82
+ }, V = (e) => {
83
+ let t = o(e);
84
+ if (!F.slots.includes(t)) throw n("not_found");
85
+ return t;
86
+ }, H = () => (C(), s(F.now(), 0, 864e13)), U = async (e) => {
87
+ C(), await l.insertIgnore(m.tableName, {
88
+ id: I(e),
89
+ tenantId: e.tenantId,
90
+ gameId: F.gameId,
91
+ ownerId: e.ownerId,
92
+ erased: !1,
93
+ admission: 0
94
+ }, { conflictColumns: ["id"] });
95
+ }, W = async (e, t, r = !1, i = !1) => {
96
+ if (C(), r && await e.updateMany(m.tableName, { admission: 0 }, { where: x("id", I(t)) }) !== 1) throw n("unavailable");
97
+ let a = (await e.query(S(m).where(x("id", I(t))).limit(1).descriptor))[0];
98
+ if (!a) return null;
99
+ if (a.id !== I(t) || a.tenantId !== t.tenantId || a.gameId !== F.gameId || a.admission !== 0 || typeof a.erased != "boolean") throw n("invalid_record");
100
+ if (a.erased) {
101
+ if (i && a.ownerId === null) return a;
102
+ throw n("erased");
103
+ }
104
+ if (a.ownerId !== t.ownerId) throw n("invalid_record");
105
+ return a;
106
+ }, G = async (e, t, r) => {
107
+ let i = (await e.query(S(h).where(x("id", L(t, r))).limit(1).descriptor))[0];
108
+ if (!i) return null;
109
+ if (B(i, t), i.slot !== r || i.id !== L(t, r)) throw n("invalid_record");
110
+ return i;
111
+ }, K = async (e, t, r, i) => {
112
+ let a = (await e.query(S(f).where(x("id", R(t, r, i))).limit(1).descriptor))[0];
113
+ if (!a) throw n("not_found");
114
+ if (B(a, t), a.slot !== r || a.version !== i) throw n("invalid_record");
115
+ return j(a);
116
+ }, q = async (e, t, i, a) => {
117
+ let o = (await e.query(S(p).where(x("id", i)).limit(1).descriptor))[0];
118
+ if (!o) return null;
119
+ if (B(o, t), o.digest !== a) throw n("request_conflict");
120
+ try {
121
+ return Object.freeze(v.decodeUnknownSync(r)(o.receipt));
122
+ } catch {
123
+ throw n("invalid_record");
124
+ }
125
+ }, J = async (e, t, r, i) => {
126
+ let a = await e.query(S(r).select(...M).where(z(t)).orderBy("id", "asc").limit(i + 1).descriptor);
127
+ if (a.length > i) throw n("limit_exceeded");
128
+ for (let e of a) B(e, t), A(e);
129
+ return a;
130
+ }, Y = (e, r) => {
131
+ let i = null;
132
+ if (F.schema) {
133
+ if (r.schemaVersion !== F.schemaVersion) throw n("invalid_save");
134
+ try {
135
+ i = v.decodeUnknownSync(v.toType(F.schema))(JSON.parse(new TextDecoder("utf-8", { fatal: !0 }).decode(r.bytes)));
136
+ } catch {
137
+ throw n("invalid_save");
138
+ }
139
+ }
140
+ try {
141
+ u(Object.freeze({
142
+ previous: e === null ? null : structuredClone(e),
143
+ proposed: structuredClone(r),
144
+ decoded: i
145
+ }), F.validator);
146
+ } catch (e) {
147
+ throw e instanceof t ? e : n("invalid_save");
148
+ }
149
+ }, X = (t, r, i) => O(async () => {
150
+ let a = w([r.kind, r.intent]), o = E("svr_", I(t), r.requestId);
151
+ await U(t);
152
+ let c = await l.transactional(async (n) => {
153
+ await W(n, t, !0);
154
+ let i = await q(n, t, o, a);
155
+ if (i) return { accepted: i };
156
+ let s = await G(n, t, r.slot), c = s ? j(s) : null;
157
+ if ((c?.version ?? 0) !== r.baseVersion) throw new e({
158
+ serverVersion: c?.version ?? 0,
159
+ server: c?.summary ?? {},
160
+ client: r.summary
161
+ });
162
+ return { previous: c };
163
+ });
164
+ if ("accepted" in c) return c.accepted;
165
+ let u = H(), d = await g.runPromise(g.result(N(I(t), u)));
166
+ if (_.isFailure(d)) throw d.failure;
167
+ let m = await i(l, c.previous, u);
168
+ return r.kind !== "remove" && Y(c.previous, m), C(), l.transactional(async (i) => {
169
+ await W(i, t, !0);
170
+ let l = await q(i, t, o, a);
171
+ if (l) return l;
172
+ let d = await G(i, t, r.slot), g = d ? j(d) : null;
173
+ if ((g?.version ?? 0) !== r.baseVersion) throw new e({
174
+ serverVersion: g?.version ?? 0,
175
+ server: g?.summary ?? {},
176
+ client: r.summary
177
+ });
178
+ if (g && c.previous && (g.checksum !== c.previous.checksum || g.deletedUntil !== c.previous.deletedUntil)) throw n("request_conflict");
179
+ if (r.kind === "rollback") {
180
+ let e = s(r.intent.version, 1);
181
+ if ((await K(i, t, r.slot, e)).checksum !== T(m.bytes)) throw n("request_conflict");
182
+ }
183
+ if ((await i.query(S(p).select("id").where(z(t)).limit(F.maxRequests + 1).descriptor)).length >= F.maxRequests) throw n("limit_exceeded");
184
+ let _ = s(r.baseVersion + 1, 1), v = r.kind === "remove" ? s(u + F.deleteGraceMs, 0, 864e13) : null, y = Object.freeze({
185
+ slot: r.slot,
186
+ version: _,
187
+ schemaVersion: m.schemaVersion,
188
+ byteLength: m.bytes.byteLength,
189
+ checksum: T(m.bytes),
190
+ deviceId: m.deviceId,
191
+ clientVersion: m.clientVersion,
192
+ savedAt: u,
193
+ summary: Object.freeze({ ...m.summary }),
194
+ deletedUntil: v
195
+ }), w = {
196
+ tenantId: t.tenantId,
197
+ gameId: F.gameId,
198
+ ownerId: t.ownerId,
199
+ ownerKey: I(t),
200
+ ...y,
201
+ bytes: Uint8Array.from(m.bytes),
202
+ savedAt: new Date(u),
203
+ deletedUntil: v === null ? null : new Date(v)
204
+ };
205
+ d ? await i.updateMany(h.tableName, w, { where: x("id", L(t, r.slot)) }) : await i.insert(h.tableName, {
206
+ id: L(t, r.slot),
207
+ ...w
208
+ }), await i.insert(f.tableName, {
209
+ id: R(t, r.slot, _),
210
+ ...w
211
+ });
212
+ let E = await i.query(S(f).select("id", "version").where(b(z(t), x("slot", r.slot))).orderBy("version", "desc").limit(102).descriptor);
213
+ if (E.length > 101) throw n("invalid_record");
214
+ for (let e of E.slice(F.historyVersions)) await i.deleteMany(f.tableName, { where: x("id", e.id) });
215
+ return await i.insert(p.tableName, {
216
+ id: o,
217
+ tenantId: t.tenantId,
218
+ gameId: F.gameId,
219
+ ownerId: t.ownerId,
220
+ ownerKey: I(t),
221
+ digest: a,
222
+ receipt: y
223
+ }), C(), y;
224
+ });
225
+ }), Z = (e) => {
226
+ let t = a(e, [
227
+ "subjectId",
228
+ "tenantId",
229
+ "kind"
230
+ ]);
231
+ if (t.kind !== "user" && t.kind !== "guest") throw n("invalid_input");
232
+ return {
233
+ tenantId: o(t.tenantId),
234
+ ownerId: o(t.subjectId)
235
+ };
236
+ }, Q = (e, t) => {
237
+ try {
238
+ return t(e());
239
+ } catch (e) {
240
+ return g.fail(D(e));
241
+ }
242
+ };
243
+ return Object.freeze({
244
+ get: (e, t) => {
245
+ try {
246
+ let n = c(e), r = V(t);
247
+ return O(() => l.transactional(async (e) => {
248
+ if (!await W(e, n)) return null;
249
+ let t = await G(e, n, r);
250
+ if (!t) return null;
251
+ let i = j(t);
252
+ return i.deletedUntil === null ? i : null;
253
+ }));
254
+ } catch (e) {
255
+ return g.fail(D(e));
256
+ }
257
+ },
258
+ list: (e) => {
259
+ try {
260
+ let t = c(e);
261
+ return O(() => l.transactional(async (e) => await W(e, t) ? (await J(e, t, h, 64)).map(A).filter((e) => e.deletedUntil === null) : []));
262
+ } catch (e) {
263
+ return g.fail(D(e));
264
+ }
265
+ },
266
+ history: (e, t) => {
267
+ try {
268
+ let n = c(e), r = V(t);
269
+ return O(() => l.transactional(async (e) => await W(e, n) ? (await J(e, n, f, 6400)).filter((e) => e.slot === r).map(A).sort((e, t) => t.version - e.version) : []));
270
+ } catch (e) {
271
+ return g.fail(D(e));
272
+ }
273
+ },
274
+ put: (e, t) => {
275
+ try {
276
+ let n = c(e), r = i(t, F.maxBytes);
277
+ V(r.slot);
278
+ let a = {
279
+ ...r,
280
+ bytes: T(r.bytes)
281
+ };
282
+ return X(n, {
283
+ kind: "put",
284
+ ...r,
285
+ intent: a
286
+ }, async () => r);
287
+ } catch (e) {
288
+ return g.fail(D(e));
289
+ }
290
+ },
291
+ rollback: (e, t) => {
292
+ try {
293
+ let r = c(e), l = a(t, [
294
+ "slot",
295
+ "requestId",
296
+ "baseVersion",
297
+ "version"
298
+ ]), u = {
299
+ slot: V(l.slot),
300
+ requestId: o(l.requestId),
301
+ baseVersion: s(l.baseVersion),
302
+ version: s(l.version, 1)
303
+ };
304
+ return X(r, {
305
+ kind: "rollback",
306
+ ...u,
307
+ summary: {},
308
+ intent: u
309
+ }, async (e, t, a) => {
310
+ if (!t || t.deletedUntil !== null && t.deletedUntil <= a) throw n("not_found");
311
+ let o = await K(e, r, u.slot, u.version);
312
+ return i({
313
+ slot: u.slot,
314
+ requestId: u.requestId,
315
+ baseVersion: u.baseVersion,
316
+ schemaVersion: o.schemaVersion,
317
+ bytes: o.bytes,
318
+ deviceId: o.deviceId,
319
+ clientVersion: o.clientVersion,
320
+ summary: o.summary
321
+ }, F.maxBytes);
322
+ });
323
+ } catch (e) {
324
+ return g.fail(D(e));
325
+ }
326
+ },
327
+ remove: (e, t) => {
328
+ try {
329
+ let r = c(e), i = a(t, [
330
+ "slot",
331
+ "requestId",
332
+ "baseVersion"
333
+ ]), l = {
334
+ slot: V(i.slot),
335
+ requestId: o(i.requestId),
336
+ baseVersion: s(i.baseVersion)
337
+ };
338
+ return X(r, {
339
+ kind: "remove",
340
+ ...l,
341
+ summary: {},
342
+ intent: l
343
+ }, async (e, t) => {
344
+ if (!t || t.deletedUntil !== null) throw n("not_found");
345
+ return {
346
+ ...l,
347
+ schemaVersion: t.schemaVersion,
348
+ bytes: t.bytes,
349
+ deviceId: t.deviceId,
350
+ clientVersion: t.clientVersion,
351
+ summary: t.summary
352
+ };
353
+ });
354
+ } catch (e) {
355
+ return g.fail(D(e));
356
+ }
357
+ },
358
+ exportSubject: (e) => Q(() => Z(e), (e) => O(() => l.transactional(async (t) => {
359
+ let r = await W(t, e, !1, !0);
360
+ if (!r || r.erased) return {
361
+ saves: [],
362
+ history: []
363
+ };
364
+ let i = await J(t, e, h, 64), a = await J(t, e, f, 6400);
365
+ if ([...i, ...a].reduce((e, t) => e + A(t).byteLength, 0) > 67108864) throw n("limit_exceeded");
366
+ let o = async (r, i) => {
367
+ let a = [];
368
+ for (let o of i) {
369
+ let i = (await t.query(S(r).where(x("id", o.id)).limit(1).descriptor))[0];
370
+ if (!i) throw n("invalid_record");
371
+ B(i, e);
372
+ let s = j(i);
373
+ a.push({
374
+ ...s,
375
+ bytes: Buffer.from(s.bytes).toString("base64")
376
+ });
377
+ }
378
+ return a;
379
+ };
380
+ return {
381
+ saves: await o(h, i),
382
+ history: await o(f, a)
383
+ };
384
+ }))),
385
+ eraseSubject: (e) => {
386
+ try {
387
+ let t = Z(e);
388
+ return O(async () => {
389
+ await U(t), await l.transactional(async (e) => {
390
+ await W(e, t, !0, !0);
391
+ for (let [r, i] of [
392
+ [h, 64],
393
+ [f, 6400],
394
+ [p, 1e5]
395
+ ]) {
396
+ let a = await e.query(S(r).select("id", "tenantId", "gameId", "ownerId", "ownerKey").where(z(t)).limit(i + 1).descriptor);
397
+ if (a.length > i) throw n("limit_exceeded");
398
+ for (let n of a) B(n, t), await e.deleteMany(r.tableName, { where: x("id", n.id) });
399
+ }
400
+ await e.updateMany(m.tableName, {
401
+ erased: !0,
402
+ ownerId: null
403
+ }, { where: x("id", I(t)) }), C();
404
+ });
405
+ });
406
+ } catch (e) {
407
+ return g.fail(D(e));
408
+ }
409
+ }
410
+ });
411
+ };
412
+ export { N as dataStoreSaves };
@@ -0,0 +1,76 @@
1
+ import { Schema } from 'effect';
2
+
3
+ /** Opaque saves convey no Wallet, Inventory, ranked-result or Room-state authority. */
4
+ export declare const defaultSaveValidator: SaveValidator;
5
+
6
+ export declare const resolveSavesOptions: (input: SavesOptions) => Readonly<{
7
+ gameId: string;
8
+ slots: readonly string[];
9
+ maxBytes: number;
10
+ historyVersions: number;
11
+ maxRequests: number;
12
+ deleteGraceMs: number;
13
+ version: string;
14
+ validator: SaveValidator;
15
+ now: () => number;
16
+ schema: Schema.Top | undefined;
17
+ schemaVersion: number | null;
18
+ }>;
19
+
20
+ export declare const resolveSaveValidation: (context: SaveValidationContext, validator?: SaveValidator) => void;
21
+
22
+ declare type SaveDocument = typeof SaveDocumentSchema.Type;
23
+
24
+ declare const SaveDocumentSchema: Schema.Struct<{
25
+ readonly bytes: Schema.Uint8ArrayFromBase64;
26
+ readonly slot: Schema.String;
27
+ readonly version: Schema.Number;
28
+ readonly schemaVersion: Schema.Number;
29
+ readonly byteLength: Schema.Number;
30
+ readonly checksum: Schema.String;
31
+ readonly deviceId: Schema.String;
32
+ readonly clientVersion: Schema.String;
33
+ readonly savedAt: Schema.Number;
34
+ readonly summary: Schema.$Record<Schema.String, Schema.Union<readonly [Schema.String, Schema.Number, Schema.Boolean, Schema.Null]>>;
35
+ readonly deletedUntil: Schema.NullOr<Schema.Number>;
36
+ }>;
37
+
38
+ declare interface SavePutIntent {
39
+ readonly slot: string;
40
+ readonly requestId: string;
41
+ readonly baseVersion: number;
42
+ readonly schemaVersion: number;
43
+ readonly bytes: Uint8Array;
44
+ readonly deviceId: string;
45
+ readonly clientVersion: string;
46
+ readonly summary: SaveSummary;
47
+ }
48
+
49
+ export declare interface SavesOptions {
50
+ /** Server configuration, never a game/owner selector from the player. */
51
+ readonly gameId: string;
52
+ readonly slots?: readonly string[];
53
+ readonly maxBytes?: number;
54
+ readonly historyVersions?: number;
55
+ readonly maxRequests?: number;
56
+ readonly deleteGraceMs?: number;
57
+ readonly version?: string;
58
+ readonly validator?: SaveValidator;
59
+ readonly schema?: Schema.Top | undefined;
60
+ readonly schemaVersion?: number | undefined;
61
+ readonly now?: (() => number) | undefined;
62
+ }
63
+
64
+ declare type SaveSummary = typeof SaveSummarySchema.Type;
65
+
66
+ declare const SaveSummarySchema: Schema.$Record<Schema.String, Schema.Union<readonly [Schema.String, Schema.Number, Schema.Boolean, Schema.Null]>>;
67
+
68
+ export declare interface SaveValidationContext {
69
+ readonly previous: SaveDocument | null;
70
+ readonly proposed: SavePutIntent;
71
+ readonly decoded: unknown;
72
+ }
73
+
74
+ export declare type SaveValidator = (context: SaveValidationContext) => boolean;
75
+
76
+ export { }
@@ -0,0 +1,47 @@
1
+ import { savesError as e } from "./errors.js";
2
+ import { saveData as t, saveId as n, saveInteger as r } from "./contract.js";
3
+ import { Schema as i } from "effect";
4
+ // src/strategies.ts
5
+ var a = () => !0, o = (t, n = a) => {
6
+ if (typeof n != "function" || n(t) !== !0) throw e("invalid_save");
7
+ }, s = (o) => {
8
+ let s = t(o, [
9
+ "gameId",
10
+ "slots",
11
+ "maxBytes",
12
+ "historyVersions",
13
+ "maxRequests",
14
+ "deleteGraceMs",
15
+ "version",
16
+ "validator",
17
+ "schema",
18
+ "schemaVersion",
19
+ "now"
20
+ ]), c = s.slots ?? ["main"];
21
+ if (!Array.isArray(c) || c.length < 1 || c.length > 64 || Reflect.ownKeys(c).length !== c.length + 1) throw e("invalid_input");
22
+ let l = [];
23
+ for (let t = 0; t < c.length; t++) {
24
+ let r = Object.getOwnPropertyDescriptor(c, String(t));
25
+ if (!r || !("value" in r)) throw e("invalid_input");
26
+ l.push(n(r.value));
27
+ }
28
+ if (new Set(l).size !== l.length) throw e("invalid_input");
29
+ let u = s.validator ?? a, d = s.now ?? Date.now, f = n(s.version ?? "default.v1");
30
+ if (typeof u != "function" || typeof d != "function" || u !== a && f === "default.v1" || s.schema !== void 0 && !i.isSchema(s.schema)) throw e("invalid_input");
31
+ let p = s.schema === void 0 ? null : r(s.schemaVersion, 1);
32
+ if (s.schema === void 0 && s.schemaVersion !== void 0) throw e("invalid_input");
33
+ return Object.freeze({
34
+ gameId: n(s.gameId),
35
+ slots: Object.freeze(l),
36
+ maxBytes: r(s.maxBytes ?? 1048576, 1, 1048576),
37
+ historyVersions: r(s.historyVersions ?? 5, 1, 100),
38
+ maxRequests: r(s.maxRequests ?? 1e4, 1, 1e5),
39
+ deleteGraceMs: r(s.deleteGraceMs ?? 6048e5, 0, 31536e6),
40
+ version: f,
41
+ validator: u,
42
+ now: d,
43
+ schema: s.schema,
44
+ schemaVersion: p
45
+ });
46
+ };
47
+ export { a as defaultSaveValidator, o as resolveSaveValidation, s as resolveSavesOptions };
@@ -0,0 +1,60 @@
1
+ import { SAVE_HISTORY_TABLE as e, SAVE_REQUEST_TABLE as t, SAVE_SUBJECT_TABLE as n, SAVE_TABLE as r } from "./contract.js";
2
+ import { boolean as i, bytes as a, id as o, integer as s, json as c, table as l, text as u, timestamp as d } from "@voltro/database";
3
+ // src/tables.entity.ts
4
+ var f = () => ({
5
+ tenantId: u().maxLength(120).externalId().sensitive("pii"),
6
+ gameId: u().maxLength(120).serverOnly(),
7
+ ownerId: u().maxLength(120).externalId().sensitive("pii"),
8
+ ownerKey: u().maxLength(64).serverOnly()
9
+ }), p = () => ({
10
+ slot: u().maxLength(120).safe(),
11
+ version: s().safe(),
12
+ schemaVersion: s().safe(),
13
+ bytes: a().sensitive("pii"),
14
+ byteLength: s().safe(),
15
+ checksum: u().maxLength(64).safe(),
16
+ deviceId: u().maxLength(120).sensitive("pii"),
17
+ clientVersion: u().maxLength(120).safe(),
18
+ savedAt: d().safe(),
19
+ summary: c().sensitive("pii"),
20
+ deletedUntil: d().nullable().serverOnly()
21
+ }), m = l(r, {
22
+ id: o({ prefix: "sv" }),
23
+ ...f(),
24
+ ...p()
25
+ }).index([
26
+ "tenantId",
27
+ "gameId",
28
+ "ownerId",
29
+ "slot"
30
+ ]), h = l(e, {
31
+ id: o({ prefix: "svh" }),
32
+ ...f(),
33
+ ...p()
34
+ }).index([
35
+ "ownerKey",
36
+ "slot",
37
+ "version"
38
+ ]), g = l(t, {
39
+ id: o({ prefix: "svr" }),
40
+ ...f(),
41
+ digest: u().maxLength(64).serverOnly(),
42
+ receipt: c().sensitive("pii")
43
+ }).index(["ownerKey"]), _ = l(n, {
44
+ id: o({ prefix: "svs" }),
45
+ tenantId: u().maxLength(120).externalId().sensitive("pii"),
46
+ gameId: u().maxLength(120).serverOnly(),
47
+ ownerId: u().maxLength(120).nullable().externalId().sensitive("pii"),
48
+ erased: i().serverOnly(),
49
+ admission: s().serverOnly()
50
+ }).index([
51
+ "tenantId",
52
+ "gameId",
53
+ "ownerId"
54
+ ]), v = [
55
+ m,
56
+ h,
57
+ g,
58
+ _
59
+ ];
60
+ export { h as savesHistoryTable, g as savesRequestsTable, _ as savesSubjectsTable, m as savesTable, v as savesTables };