@voltro/plugin-saves 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.
@@ -0,0 +1,413 @@
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
+ //#region 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
+ //#endregion
413
+ 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,48 @@
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
+ //#region 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
+ //#endregion
48
+ export { a as defaultSaveValidator, o as resolveSaveValidation, s as resolveSavesOptions };
@@ -0,0 +1,61 @@
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
+ //#region 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
+ //#endregion
61
+ export { h as savesHistoryTable, g as savesRequestsTable, _ as savesSubjectsTable, m as savesTable, v as savesTables };