@voltro/plugin-inventory 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.
- package/CHANGELOG.md +24492 -0
- package/LICENSE +61 -0
- package/README.md +441 -2
- package/SECURITY.md +56 -0
- package/THIRD-PARTY-NOTICES.md +8333 -0
- package/dist/capture.js +52 -0
- package/dist/catalog.d.ts +63 -0
- package/dist/catalog.js +4 -0
- package/dist/cmsCatalog.d.ts +95 -0
- package/dist/cmsCatalog.js +79 -0
- package/dist/components.d.ts +247 -0
- package/dist/components.js +320 -0
- package/dist/crafting.d.ts +211 -0
- package/dist/crafting.js +192 -0
- package/dist/declarationFixtures.js +65 -0
- package/dist/errors.d.ts +14 -0
- package/dist/errors.js +21 -0
- package/dist/index.d.ts +576 -0
- package/dist/index.js +8 -0
- package/dist/inventoryPort.fixture.js +65 -0
- package/dist/inventoryPresentation.js +108 -0
- package/dist/inventoryStore.js +1575 -0
- package/dist/inventoryUiCopy.js +62 -0
- package/dist/item.d.ts +73 -0
- package/dist/item.js +104 -0
- package/dist/plugin.js +406 -0
- package/dist/port.js +4 -0
- package/dist/reservation.js +84 -0
- package/dist/rpc.d.ts +145 -0
- package/dist/rpc.js +134 -0
- package/dist/server.d.ts +816 -0
- package/dist/server.js +4 -0
- package/dist/sqlCatalog.js +184 -0
- package/dist/strategies.d.ts +64 -0
- package/dist/strategies.js +46 -0
- package/dist/systemFixtures.js +171 -0
- package/dist/tables.entity.js +163 -0
- package/dist/testing.d.ts +448 -0
- package/dist/testing.js +4 -0
- package/dist/web.d.ts +60 -0
- package/dist/web.js +6 -0
- package/package.json +104 -4
package/dist/server.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { inventoryCatalogHeadsTable as e, inventoryCatalogLocksTable as t, inventoryCatalogRevisionsTable as n, inventoryCatalogTable as r, inventoryCatalogTables as i, inventoryCatalogVersionsTable as a, inventoryItemsTable as o, inventoryLedgerTable as s, inventoryLoadoutsTable as c, inventoryOperationsTable as l, inventoryOwnedTables as u, inventoryRecipeTables as d, inventoryRecipesTable as f, inventorySubjectsTable as p, inventoryTables as m } from "./tables.entity.js";
|
|
2
|
+
import { dataStoreCatalog as h } from "./sqlCatalog.js";
|
|
3
|
+
import { dataStoreInventory as g, resolveInventoryOptions as _ } from "./inventoryStore.js";
|
|
4
|
+
export { h as dataStoreCatalog, g as dataStoreInventory, e as inventoryCatalogHeadsTable, t as inventoryCatalogLocksTable, n as inventoryCatalogRevisionsTable, r as inventoryCatalogTable, i as inventoryCatalogTables, a as inventoryCatalogVersionsTable, o as inventoryItemsTable, s as inventoryLedgerTable, c as inventoryLoadoutsTable, l as inventoryOperationsTable, u as inventoryOwnedTables, d as inventoryRecipeTables, f as inventoryRecipesTable, p as inventorySubjectsTable, m as inventoryTables, _ as resolveInventoryOptions };
|
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
import { InventoryError as e, inventoryError as t } from "./errors.js";
|
|
2
|
+
import { identifier as n, integer as r, list as i, object as a } from "./capture.js";
|
|
3
|
+
import { captureCatalogItem as o, captureItemContracts as s } from "./item.js";
|
|
4
|
+
import { inventoryCatalogHeadsTable as c, inventoryCatalogLocksTable as l, inventoryCatalogRevisionsTable as u, inventoryCatalogTable as d, inventoryCatalogVersionsTable as f } from "./tables.entity.js";
|
|
5
|
+
import { Effect as p } from "effect";
|
|
6
|
+
import { and as m, eq as h, queryFor as g } from "@voltro/database";
|
|
7
|
+
import { createHash as _ } from "node:crypto";
|
|
8
|
+
// src/sqlCatalog.ts
|
|
9
|
+
var v = (e) => {
|
|
10
|
+
let n = 0, r = (e, o) => {
|
|
11
|
+
if (++n > 3e6 || o > 32) throw t("limit_exceeded");
|
|
12
|
+
if (e === null || typeof e == "string" || typeof e == "boolean" || typeof e == "number" && Number.isFinite(e) && !Object.is(e, -0)) return e;
|
|
13
|
+
if (Array.isArray(e)) return i(e, 1e5).map((e) => r(e, o + 1));
|
|
14
|
+
let s = a(e);
|
|
15
|
+
return Object.fromEntries(Object.keys(s).sort().map((e) => [e, r(s[e], o + 1)]));
|
|
16
|
+
}, o = JSON.stringify(r(e, 0));
|
|
17
|
+
if (Buffer.byteLength(o) > 67108864) throw t("limit_exceeded");
|
|
18
|
+
return _("sha256").update(o).digest("hex");
|
|
19
|
+
}, y = (e, ...t) => e + v(t).slice(0, 56), b = (n) => p.tryPromise({
|
|
20
|
+
try: n,
|
|
21
|
+
catch: (n) => n instanceof e ? n : t("unavailable")
|
|
22
|
+
}), x = (e) => {
|
|
23
|
+
let t = a(e, [
|
|
24
|
+
"tenantId",
|
|
25
|
+
"channel",
|
|
26
|
+
"locale"
|
|
27
|
+
]);
|
|
28
|
+
return Object.freeze({
|
|
29
|
+
tenantId: n(t.tenantId),
|
|
30
|
+
channel: n(t.channel),
|
|
31
|
+
locale: n(t.locale)
|
|
32
|
+
});
|
|
33
|
+
}, S = (_, S) => {
|
|
34
|
+
let C = a(S, [
|
|
35
|
+
"items",
|
|
36
|
+
"allowedServices",
|
|
37
|
+
"maxCatalogItems",
|
|
38
|
+
"maxCatalogVersions",
|
|
39
|
+
"now"
|
|
40
|
+
]), w = s(C.items), T = new Set(i(C.allowedServices ?? [], 256).map(n)), E = r(C.maxCatalogItems ?? 1e4, 1, 1e4), D = r(C.maxCatalogVersions ?? 1e4, 1, 1e5), O = C.now ?? Date.now;
|
|
41
|
+
if (typeof O != "function") throw t("invalid_input");
|
|
42
|
+
let k = (e) => m(h("tenantId", e.tenantId), h("channel", e.channel), h("locale", e.locale)), A = (e) => y("ich_", e.tenantId, e.channel, e.locale), j = (e, n, r) => {
|
|
43
|
+
let i = o(e.definition, w);
|
|
44
|
+
if (e.tenantId !== n.tenantId || e.channel !== n.channel || e.locale !== n.locale || e.revision !== r || e.itemId !== i.id || e.id !== y("ica_", n.tenantId, n.channel, n.locale, r, i.id)) throw t("invalid_record");
|
|
45
|
+
return i;
|
|
46
|
+
};
|
|
47
|
+
return Object.freeze({
|
|
48
|
+
read: (r) => {
|
|
49
|
+
try {
|
|
50
|
+
let e = x(r);
|
|
51
|
+
return b(() => _.transactional(async (r) => {
|
|
52
|
+
let i = (await r.query(g(c).where(h("id", A(e))).limit(1).descriptor))[0];
|
|
53
|
+
if (!i) throw t("not_found");
|
|
54
|
+
if (i.tenantId !== e.tenantId || i.channel !== e.channel || i.locale !== e.locale) throw t("invalid_record");
|
|
55
|
+
let a = n(i.revision), o = (await r.query(g(u).where(h("id", y("icr_", e.tenantId, e.channel, e.locale, a))).limit(1).descriptor))[0];
|
|
56
|
+
if (!o || o.tenantId !== e.tenantId || o.channel !== e.channel || o.locale !== e.locale || o.revision !== a) throw t("invalid_record");
|
|
57
|
+
let s = await r.query(g(d).where(m(k(e), h("revision", a))).orderBy("itemId", "asc").limit(E + 1).descriptor);
|
|
58
|
+
if (s.length > E) throw t("limit_exceeded");
|
|
59
|
+
let l = Object.freeze(s.map((t) => j(t, e, a)).sort((e, t) => e.id < t.id ? -1 : +(e.id > t.id)));
|
|
60
|
+
if (new Set(l.map((e) => e.id)).size !== l.length || o.itemCount !== l.length || o.digest !== v(l)) throw t("invalid_record");
|
|
61
|
+
return Object.freeze({
|
|
62
|
+
revision: a,
|
|
63
|
+
items: l
|
|
64
|
+
});
|
|
65
|
+
}));
|
|
66
|
+
} catch (n) {
|
|
67
|
+
return p.fail(n instanceof e ? n : t("invalid_input"));
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
importSnapshot: (s, m) => {
|
|
71
|
+
try {
|
|
72
|
+
let e = structuredClone(s), p = a(m, [
|
|
73
|
+
"tenantId",
|
|
74
|
+
"channel",
|
|
75
|
+
"locale",
|
|
76
|
+
"revision",
|
|
77
|
+
"items"
|
|
78
|
+
]);
|
|
79
|
+
if (e.type !== "system" && !(e.type === "service" && T.has(e.service))) throw t("forbidden");
|
|
80
|
+
let S = x({
|
|
81
|
+
tenantId: p.tenantId,
|
|
82
|
+
channel: p.channel,
|
|
83
|
+
locale: p.locale
|
|
84
|
+
}), C = n(p.revision), k = Object.freeze(i(p.items, E).map((e) => o(e, w)).sort((e, t) => e.id < t.id ? -1 : +(e.id > t.id)));
|
|
85
|
+
if (new Set(k.map((e) => e.id)).size !== k.length) throw t("conflict");
|
|
86
|
+
let j = v(k), M = y("icl_", S.tenantId), N = y("icr_", S.tenantId, S.channel, S.locale, C), P = (e) => ({
|
|
87
|
+
id: e.id,
|
|
88
|
+
schemaVersion: e.schemaVersion,
|
|
89
|
+
kind: e.kind,
|
|
90
|
+
stackable: e.stackable,
|
|
91
|
+
maxStack: e.maxStack,
|
|
92
|
+
tradable: e.tradable,
|
|
93
|
+
equipSlot: e.equipSlot,
|
|
94
|
+
expiresAfter: e.expiresAfter
|
|
95
|
+
});
|
|
96
|
+
return b(async () => {
|
|
97
|
+
let e = r(O(), 0, 864e13);
|
|
98
|
+
try {
|
|
99
|
+
await _.insertIgnore(l.tableName, {
|
|
100
|
+
id: M,
|
|
101
|
+
tenantId: S.tenantId,
|
|
102
|
+
admission: 0
|
|
103
|
+
}, { conflictColumns: ["id"] });
|
|
104
|
+
} catch (e) {
|
|
105
|
+
if (!(await _.query(g(l).where(h("id", M)).limit(1).descriptor))[0]) throw e;
|
|
106
|
+
}
|
|
107
|
+
return _.transactional(async (n) => {
|
|
108
|
+
if (await n.updateMany(l.tableName, { admission: 0 }, { where: h("id", M) }) !== 1) throw t("unavailable");
|
|
109
|
+
if ((await n.query(g(l).where(h("id", M)).limit(1).descriptor))[0]?.tenantId !== S.tenantId) throw t("invalid_record");
|
|
110
|
+
let r = (await n.query(g(u).where(h("id", N)).limit(1).descriptor))[0];
|
|
111
|
+
if (r) {
|
|
112
|
+
if (r.tenantId !== S.tenantId || r.channel !== S.channel || r.locale !== S.locale || r.revision !== C || r.digest !== j || r.itemCount !== k.length) throw t("conflict");
|
|
113
|
+
return Object.freeze({
|
|
114
|
+
revision: C,
|
|
115
|
+
items: k
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
let i = await n.query(g(f).where(h("tenantId", S.tenantId)).orderBy("id", "asc").limit(D + 1).descriptor);
|
|
119
|
+
if (i.length > D) throw t("limit_exceeded");
|
|
120
|
+
let a = 0;
|
|
121
|
+
for (let e of k) {
|
|
122
|
+
let r = y("icv_", S.tenantId, e.id, String(e.schemaVersion)), o = i.find((e) => e.id === r);
|
|
123
|
+
if (i.some((t) => t.itemId === e.id && t.kind !== e.kind)) throw t("conflict");
|
|
124
|
+
if (o) {
|
|
125
|
+
if (o.tenantId !== S.tenantId || o.itemId !== e.id || o.schemaVersion !== e.schemaVersion || v(o.definition) !== v(P(e))) throw t("conflict");
|
|
126
|
+
} else {
|
|
127
|
+
if (i.length + ++a > D) throw t("limit_exceeded");
|
|
128
|
+
await n.insert(f.tableName, {
|
|
129
|
+
id: r,
|
|
130
|
+
tenantId: S.tenantId,
|
|
131
|
+
itemId: e.id,
|
|
132
|
+
schemaVersion: e.schemaVersion,
|
|
133
|
+
kind: e.kind,
|
|
134
|
+
definition: P(e)
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
await n.insert(d.tableName, {
|
|
138
|
+
id: y("ica_", S.tenantId, S.channel, S.locale, C, e.id),
|
|
139
|
+
tenantId: S.tenantId,
|
|
140
|
+
channel: S.channel,
|
|
141
|
+
locale: S.locale,
|
|
142
|
+
revision: C,
|
|
143
|
+
itemId: e.id,
|
|
144
|
+
definition: e
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
await n.insert(u.tableName, {
|
|
148
|
+
id: N,
|
|
149
|
+
tenantId: S.tenantId,
|
|
150
|
+
channel: S.channel,
|
|
151
|
+
locale: S.locale,
|
|
152
|
+
revision: C,
|
|
153
|
+
digest: j,
|
|
154
|
+
itemCount: k.length,
|
|
155
|
+
createdAt: new Date(e)
|
|
156
|
+
});
|
|
157
|
+
let o = A(S), s = (await n.query(g(c).where(h("id", o)).limit(1).descriptor))[0];
|
|
158
|
+
if (s) {
|
|
159
|
+
if (s.tenantId !== S.tenantId || s.channel !== S.channel || s.locale !== S.locale) throw t("invalid_record");
|
|
160
|
+
await n.update(c.tableName, o, {
|
|
161
|
+
revision: C,
|
|
162
|
+
updatedAt: new Date(e)
|
|
163
|
+
});
|
|
164
|
+
} else await n.insert(c.tableName, {
|
|
165
|
+
id: o,
|
|
166
|
+
tenantId: S.tenantId,
|
|
167
|
+
channel: S.channel,
|
|
168
|
+
locale: S.locale,
|
|
169
|
+
revision: C,
|
|
170
|
+
updatedAt: new Date(e)
|
|
171
|
+
});
|
|
172
|
+
return Object.freeze({
|
|
173
|
+
revision: C,
|
|
174
|
+
items: k
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
});
|
|
178
|
+
} catch (n) {
|
|
179
|
+
return p.fail(n instanceof e ? n : t("invalid_input"));
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
});
|
|
183
|
+
};
|
|
184
|
+
export { x as catalogScope, S as dataStoreCatalog, v as inventoryHash, b as inventoryIo, y as inventoryKey };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/** Serializable content uses a declared item's version, never a stored Schema object. */
|
|
2
|
+
declare interface CatalogItem {
|
|
3
|
+
readonly id: string;
|
|
4
|
+
readonly schemaVersion: number;
|
|
5
|
+
readonly kind: ItemKind;
|
|
6
|
+
readonly stackable: boolean;
|
|
7
|
+
readonly maxStack: number;
|
|
8
|
+
readonly tradable: boolean;
|
|
9
|
+
readonly rarity: string;
|
|
10
|
+
readonly tags: readonly string[];
|
|
11
|
+
readonly equipSlot: string | null;
|
|
12
|
+
readonly expiresAfter: number | null;
|
|
13
|
+
readonly display: {
|
|
14
|
+
readonly nameKey: string;
|
|
15
|
+
readonly icon: string | null;
|
|
16
|
+
};
|
|
17
|
+
readonly attributes: JsonValue;
|
|
18
|
+
readonly instanceDefaults: JsonValue;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export declare const defaultExpiryPolicy: ExpiryPolicy;
|
|
22
|
+
|
|
23
|
+
export declare const defaultStackPolicy: StackPolicy;
|
|
24
|
+
|
|
25
|
+
export declare interface ExpiryInput {
|
|
26
|
+
readonly item: CatalogItem;
|
|
27
|
+
readonly acquiredAt: number;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export declare type ExpiryPolicy = (input: ExpiryInput) => number | null;
|
|
31
|
+
|
|
32
|
+
declare const ITEM_KINDS: readonly ["consumable", "equipment", "cosmetic", "currencyBundle", "key", "mod"];
|
|
33
|
+
|
|
34
|
+
declare type ItemKind = typeof ITEM_KINDS[number];
|
|
35
|
+
|
|
36
|
+
declare type JsonValue = null | boolean | number | string | readonly JsonValue[] | {
|
|
37
|
+
readonly [key: string]: JsonValue;
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
export declare const resolveExpiry: (input: ExpiryInput, policy?: ExpiryPolicy) => number | null;
|
|
41
|
+
|
|
42
|
+
/** A custom policy cannot mint, discard, duplicate or exceed a stack's cap. */
|
|
43
|
+
export declare const resolveStack: (input: StackInput, policy?: StackPolicy) => StackPlan;
|
|
44
|
+
|
|
45
|
+
export declare interface StackInput {
|
|
46
|
+
readonly item: CatalogItem;
|
|
47
|
+
readonly quantity: number;
|
|
48
|
+
readonly available: readonly {
|
|
49
|
+
readonly id: string;
|
|
50
|
+
readonly quantity: number;
|
|
51
|
+
}[];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export declare interface StackPlan {
|
|
55
|
+
readonly existing: readonly {
|
|
56
|
+
readonly id: string;
|
|
57
|
+
readonly add: number;
|
|
58
|
+
}[];
|
|
59
|
+
readonly create: readonly number[];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
export declare type StackPolicy = (input: StackInput) => StackPlan;
|
|
63
|
+
|
|
64
|
+
export { }
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { inventoryError as e } from "./errors.js";
|
|
2
|
+
import { integer as t, list as n, object as r } from "./capture.js";
|
|
3
|
+
// src/strategies.ts
|
|
4
|
+
var i = (e) => {
|
|
5
|
+
let n = t(e.quantity, 1, 1e6), r = [], i = [];
|
|
6
|
+
if (e.item.stackable) for (let t of e.available) {
|
|
7
|
+
let i = Math.min(n, e.item.maxStack - t.quantity);
|
|
8
|
+
if (i > 0 && (r.push(Object.freeze({
|
|
9
|
+
id: t.id,
|
|
10
|
+
add: i
|
|
11
|
+
})), n -= i), n === 0) break;
|
|
12
|
+
}
|
|
13
|
+
for (; n > 0;) {
|
|
14
|
+
let t = Math.min(n, e.item.maxStack);
|
|
15
|
+
i.push(t), n -= t;
|
|
16
|
+
}
|
|
17
|
+
return Object.freeze({
|
|
18
|
+
existing: Object.freeze(r),
|
|
19
|
+
create: Object.freeze(i)
|
|
20
|
+
});
|
|
21
|
+
}, a = (a, o = i) => {
|
|
22
|
+
let s = Object.freeze({
|
|
23
|
+
item: a.item,
|
|
24
|
+
quantity: t(a.quantity, 1, 1e6),
|
|
25
|
+
available: Object.freeze(a.available.map((e) => Object.freeze({ ...e })))
|
|
26
|
+
}), c = r(o(s), ["existing", "create"]), l = /* @__PURE__ */ new Set(), u = n(c.existing, 1e4).map((n) => {
|
|
27
|
+
let i = r(n, ["id", "add"]), a = s.available.find((e) => e.id === i.id);
|
|
28
|
+
if (!a || l.has(a.id) || !s.item.stackable) throw e("conflict");
|
|
29
|
+
return l.add(a.id), Object.freeze({
|
|
30
|
+
id: a.id,
|
|
31
|
+
add: t(i.add, 1, s.item.maxStack - a.quantity)
|
|
32
|
+
});
|
|
33
|
+
}), d = n(c.create, 1e4).map((e) => t(e, 1, s.item.maxStack));
|
|
34
|
+
if (u.reduce((e, t) => e + t.add, 0) + d.reduce((e, t) => e + t, 0) !== s.quantity) throw e("conflict");
|
|
35
|
+
return Object.freeze({
|
|
36
|
+
existing: Object.freeze(u),
|
|
37
|
+
create: Object.freeze(d)
|
|
38
|
+
});
|
|
39
|
+
}, o = ({ item: e, acquiredAt: t }) => e.expiresAfter === null ? null : t + e.expiresAfter, s = (e, n = o) => {
|
|
40
|
+
let r = t(e.acquiredAt, 0, 864e13), i = n(Object.freeze({
|
|
41
|
+
item: e.item,
|
|
42
|
+
acquiredAt: r
|
|
43
|
+
}));
|
|
44
|
+
return i === null ? null : t(i, r + 1, 864e13);
|
|
45
|
+
};
|
|
46
|
+
export { o as defaultExpiryPolicy, i as defaultStackPolicy, s as resolveExpiry, a as resolveStack };
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import { CraftingPort as e, defaultCraftResolver as t, resolveCraftPlan as n } from "./crafting.js";
|
|
2
|
+
import { CatalogSource as r } from "./catalog.js";
|
|
3
|
+
import { defaultExpiryPolicy as i, defaultStackPolicy as a, resolveExpiry as o, resolveStack as s } from "./strategies.js";
|
|
4
|
+
import { InventoryPort as c } from "./port.js";
|
|
5
|
+
import { craftFixture as l, inventoryFixture as u } from "./declarationFixtures.js";
|
|
6
|
+
import { inventoryPortFixture as d } from "./inventoryPort.fixture.js";
|
|
7
|
+
import { Effect as f } from "effect";
|
|
8
|
+
import { systemSubject as p } from "@voltro/protocol";
|
|
9
|
+
// src/systemFixtures.ts
|
|
10
|
+
var m = u(), h = l(), g = h.at, _ = [...h.available, {
|
|
11
|
+
...h.available[0],
|
|
12
|
+
id: "fixture.second",
|
|
13
|
+
qty: 4
|
|
14
|
+
}], v = {
|
|
15
|
+
...h,
|
|
16
|
+
available: _
|
|
17
|
+
}, y = Object.freeze({
|
|
18
|
+
kind: "slot",
|
|
19
|
+
defaultImplementation: a,
|
|
20
|
+
defaultProbe: {
|
|
21
|
+
run: () => f.sync(() => s(m.stack)),
|
|
22
|
+
expected: {
|
|
23
|
+
existing: [{
|
|
24
|
+
id: "test.stack",
|
|
25
|
+
add: 2
|
|
26
|
+
}],
|
|
27
|
+
create: [10]
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
overrideProbe: {
|
|
31
|
+
run: () => f.sync(() => s(m.stack, () => ({
|
|
32
|
+
existing: [],
|
|
33
|
+
create: [6, 6]
|
|
34
|
+
}))),
|
|
35
|
+
expected: {
|
|
36
|
+
existing: [],
|
|
37
|
+
create: [6, 6]
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}), b = Object.freeze({
|
|
41
|
+
kind: "slot",
|
|
42
|
+
defaultImplementation: i,
|
|
43
|
+
defaultProbe: {
|
|
44
|
+
run: () => f.sync(() => o(m.expiry)),
|
|
45
|
+
expected: null
|
|
46
|
+
},
|
|
47
|
+
overrideProbe: {
|
|
48
|
+
run: () => f.sync(() => o(m.expiry, (e) => e.acquiredAt + 3e3)),
|
|
49
|
+
expected: m.expiry.acquiredAt + 3e3
|
|
50
|
+
}
|
|
51
|
+
}), x = Object.freeze({
|
|
52
|
+
kind: "slot",
|
|
53
|
+
defaultImplementation: t,
|
|
54
|
+
defaultProbe: {
|
|
55
|
+
run: () => f.sync(() => n(v)),
|
|
56
|
+
expected: {
|
|
57
|
+
consume: [{
|
|
58
|
+
instanceId: "fixture.potion",
|
|
59
|
+
qty: 2
|
|
60
|
+
}],
|
|
61
|
+
outputs: [{
|
|
62
|
+
itemId: "test.potion",
|
|
63
|
+
qty: 1
|
|
64
|
+
}]
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
overrideProbe: {
|
|
68
|
+
run: () => f.sync(() => n(v, () => ({
|
|
69
|
+
consume: [{
|
|
70
|
+
instanceId: "fixture.second",
|
|
71
|
+
qty: 2
|
|
72
|
+
}],
|
|
73
|
+
outputs: [{
|
|
74
|
+
itemId: "test.potion",
|
|
75
|
+
qty: 1
|
|
76
|
+
}]
|
|
77
|
+
}))),
|
|
78
|
+
expected: {
|
|
79
|
+
consume: [{
|
|
80
|
+
instanceId: "fixture.second",
|
|
81
|
+
qty: 2
|
|
82
|
+
}],
|
|
83
|
+
outputs: [{
|
|
84
|
+
itemId: "test.potion",
|
|
85
|
+
qty: 1
|
|
86
|
+
}]
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}), S = d({
|
|
90
|
+
tenantId: "fixture",
|
|
91
|
+
items: [m.item],
|
|
92
|
+
content: [m.content],
|
|
93
|
+
recipes: [h.recipe],
|
|
94
|
+
now: () => g
|
|
95
|
+
}).layer, C = S, w = S, T = Object.freeze({
|
|
96
|
+
kind: "port",
|
|
97
|
+
tag: r,
|
|
98
|
+
fakeLayer: w,
|
|
99
|
+
probe: {
|
|
100
|
+
run: () => f.scoped(f.gen(function* () {
|
|
101
|
+
let e = yield* (yield* r).read({
|
|
102
|
+
tenantId: "fixture",
|
|
103
|
+
channel: "live",
|
|
104
|
+
locale: "en"
|
|
105
|
+
});
|
|
106
|
+
return {
|
|
107
|
+
revision: e.revision,
|
|
108
|
+
items: e.items.map((e) => e.id)
|
|
109
|
+
};
|
|
110
|
+
}).pipe(f.provide(w))),
|
|
111
|
+
expected: {
|
|
112
|
+
revision: "fixture.r1",
|
|
113
|
+
items: ["test.potion"]
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}), E = p("inventory.system.fixture"), D = {
|
|
117
|
+
type: "user",
|
|
118
|
+
id: "a",
|
|
119
|
+
tenantId: "fixture",
|
|
120
|
+
kind: "guest"
|
|
121
|
+
}, O = {
|
|
122
|
+
ownerKind: "player",
|
|
123
|
+
ownerId: "a"
|
|
124
|
+
}, k = {
|
|
125
|
+
tenantId: "fixture",
|
|
126
|
+
owner: O,
|
|
127
|
+
itemId: m.item.id,
|
|
128
|
+
qty: 6,
|
|
129
|
+
requestId: "fixture.stock",
|
|
130
|
+
reason: "fixture",
|
|
131
|
+
ref: {
|
|
132
|
+
kind: "fixture",
|
|
133
|
+
id: "stock"
|
|
134
|
+
}
|
|
135
|
+
}, A = Object.freeze({
|
|
136
|
+
kind: "port",
|
|
137
|
+
tag: c,
|
|
138
|
+
fakeLayer: S,
|
|
139
|
+
probe: {
|
|
140
|
+
run: () => f.scoped(f.gen(function* () {
|
|
141
|
+
let e = yield* c;
|
|
142
|
+
return yield* e.grant(E, k), (yield* e.mine(D)).reduce((e, t) => e + t.qty, 0);
|
|
143
|
+
}).pipe(f.provide(S))),
|
|
144
|
+
expected: 6
|
|
145
|
+
}
|
|
146
|
+
}), j = Object.freeze({
|
|
147
|
+
kind: "port",
|
|
148
|
+
tag: e,
|
|
149
|
+
fakeLayer: C,
|
|
150
|
+
probe: {
|
|
151
|
+
run: () => f.scoped(f.gen(function* () {
|
|
152
|
+
let t = yield* c, n = yield* e;
|
|
153
|
+
yield* t.grant(E, k);
|
|
154
|
+
let r = {
|
|
155
|
+
tenantId: "fixture",
|
|
156
|
+
owner: O,
|
|
157
|
+
requestId: "fixture.craft",
|
|
158
|
+
recipeId: h.recipe.id
|
|
159
|
+
}, i = yield* n.craft(E, r), a = yield* n.craft(E, r);
|
|
160
|
+
return {
|
|
161
|
+
original: i.operationId === a.operationId,
|
|
162
|
+
quantity: (yield* t.mine(D)).reduce((e, t) => e + t.qty, 0)
|
|
163
|
+
};
|
|
164
|
+
}).pipe(f.provide(C))),
|
|
165
|
+
expected: {
|
|
166
|
+
original: !0,
|
|
167
|
+
quantity: 5
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
export { w as catalogFakeLayer, T as catalogSourceSystemFixture, x as craftResolverSystemFixture, C as craftingFakeLayer, j as craftingPortSystemFixture, b as expiryPolicySystemFixture, S as inventoryFakeLayer, A as inventoryPortSystemFixture, y as stackPolicySystemFixture };
|
|
@@ -0,0 +1,163 @@
|
|
|
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
|
+
// src/tables.entity.ts
|
|
3
|
+
var s = () => a().maxLength(120).externalId().sensitive("pii"), c = i("_voltro_inv_catalog_locks", {
|
|
4
|
+
id: t({ prefix: "icl" }),
|
|
5
|
+
tenantId: s(),
|
|
6
|
+
admission: n().serverOnly()
|
|
7
|
+
}), l = i("_voltro_inv_catalog_heads", {
|
|
8
|
+
id: t({ prefix: "ich" }),
|
|
9
|
+
tenantId: s(),
|
|
10
|
+
channel: a().maxLength(120).safe(),
|
|
11
|
+
locale: a().maxLength(120).safe(),
|
|
12
|
+
revision: a().maxLength(120).safe(),
|
|
13
|
+
updatedAt: o().safe()
|
|
14
|
+
}).index([
|
|
15
|
+
"tenantId",
|
|
16
|
+
"channel",
|
|
17
|
+
"locale"
|
|
18
|
+
]), u = i("_voltro_inv_catalog", {
|
|
19
|
+
id: t({ prefix: "ica" }),
|
|
20
|
+
tenantId: s(),
|
|
21
|
+
revision: a().maxLength(120).safe(),
|
|
22
|
+
channel: a().maxLength(120).safe(),
|
|
23
|
+
locale: a().maxLength(120).safe(),
|
|
24
|
+
itemId: a().maxLength(120).safe(),
|
|
25
|
+
definition: r().safe()
|
|
26
|
+
}).index([
|
|
27
|
+
"tenantId",
|
|
28
|
+
"channel",
|
|
29
|
+
"locale",
|
|
30
|
+
"revision"
|
|
31
|
+
]), d = i("_voltro_inv_catalog_versions", {
|
|
32
|
+
id: t({ prefix: "icv" }),
|
|
33
|
+
tenantId: s(),
|
|
34
|
+
itemId: a().maxLength(120).safe(),
|
|
35
|
+
schemaVersion: n().safe(),
|
|
36
|
+
kind: a().maxLength(32).safe(),
|
|
37
|
+
definition: r().safe()
|
|
38
|
+
}).index([
|
|
39
|
+
"tenantId",
|
|
40
|
+
"itemId",
|
|
41
|
+
"schemaVersion"
|
|
42
|
+
]), f = i("_voltro_inv_catalog_revisions", {
|
|
43
|
+
id: t({ prefix: "icr" }),
|
|
44
|
+
tenantId: s(),
|
|
45
|
+
revision: a().maxLength(120).safe(),
|
|
46
|
+
channel: a().maxLength(120).safe(),
|
|
47
|
+
locale: a().maxLength(120).safe(),
|
|
48
|
+
digest: a().maxLength(64).serverOnly(),
|
|
49
|
+
itemCount: n().safe(),
|
|
50
|
+
createdAt: o().safe()
|
|
51
|
+
}).index("voltro_inv_catalog_revisions_scope_idx", [
|
|
52
|
+
"tenantId",
|
|
53
|
+
"channel",
|
|
54
|
+
"locale",
|
|
55
|
+
"revision"
|
|
56
|
+
]), p = i("_voltro_inv_subjects", {
|
|
57
|
+
id: t({ prefix: "ivs" }),
|
|
58
|
+
tenantId: s(),
|
|
59
|
+
ownerKind: a().maxLength(16).oneOf(["player", "guild"]).safe(),
|
|
60
|
+
ownerId: a().maxLength(120).nullable().externalId().sensitive("pii"),
|
|
61
|
+
erased: e().serverOnly(),
|
|
62
|
+
admission: n().serverOnly(),
|
|
63
|
+
sequence: n().serverOnly()
|
|
64
|
+
}).index([
|
|
65
|
+
"tenantId",
|
|
66
|
+
"ownerKind",
|
|
67
|
+
"ownerId"
|
|
68
|
+
]), m = i("_voltro_inv_items", {
|
|
69
|
+
id: t({ prefix: "ivi" }),
|
|
70
|
+
tenantId: s(),
|
|
71
|
+
ownerKind: a().maxLength(16).oneOf(["player", "guild"]).safe(),
|
|
72
|
+
ownerId: a().maxLength(120).externalId().sensitive("pii"),
|
|
73
|
+
itemId: a().maxLength(120).safe(),
|
|
74
|
+
schemaVersion: n().safe(),
|
|
75
|
+
qty: n().safe(),
|
|
76
|
+
attributes: r().safe(),
|
|
77
|
+
acquiredAt: o().safe(),
|
|
78
|
+
expiresAt: o().nullable().safe(),
|
|
79
|
+
locked: e().safe(),
|
|
80
|
+
source: a().maxLength(120).safe()
|
|
81
|
+
}).index([
|
|
82
|
+
"tenantId",
|
|
83
|
+
"ownerKind",
|
|
84
|
+
"ownerId",
|
|
85
|
+
"itemId"
|
|
86
|
+
]), h = i("_voltro_inv_loadouts", {
|
|
87
|
+
id: t({ prefix: "ivl" }),
|
|
88
|
+
tenantId: s(),
|
|
89
|
+
ownerKind: a().maxLength(16).oneOf(["player", "guild"]).safe(),
|
|
90
|
+
ownerId: a().maxLength(120).externalId().sensitive("pii"),
|
|
91
|
+
slotSet: a().maxLength(120).safe(),
|
|
92
|
+
slot: a().maxLength(120).safe(),
|
|
93
|
+
instanceId: a().maxLength(64).safe()
|
|
94
|
+
}).index([
|
|
95
|
+
"tenantId",
|
|
96
|
+
"ownerKind",
|
|
97
|
+
"ownerId"
|
|
98
|
+
]), g = i("_voltro_inv_ledger", {
|
|
99
|
+
id: t({ prefix: "ivg" }),
|
|
100
|
+
tenantId: s(),
|
|
101
|
+
operationId: a().maxLength(64).safe(),
|
|
102
|
+
ownerKind: a().maxLength(16).oneOf(["player", "guild"]).nullable().safe(),
|
|
103
|
+
sequence: n().serverOnly(),
|
|
104
|
+
ownerId: a().maxLength(120).nullable().externalId().sensitive("pii"),
|
|
105
|
+
instanceId: a().maxLength(64).nullable().safe(),
|
|
106
|
+
itemId: a().maxLength(120).safe(),
|
|
107
|
+
delta: n().safe(),
|
|
108
|
+
reason: a().maxLength(120).safe(),
|
|
109
|
+
after: r().nullable().serverOnly(),
|
|
110
|
+
refKind: a().maxLength(120).nullable().sensitive("pii"),
|
|
111
|
+
refId: a().maxLength(120).nullable().sensitive("pii"),
|
|
112
|
+
actor: a().maxLength(120).nullable().sensitive("pii"),
|
|
113
|
+
at: o().safe()
|
|
114
|
+
}).index([
|
|
115
|
+
"tenantId",
|
|
116
|
+
"ownerKind",
|
|
117
|
+
"ownerId"
|
|
118
|
+
]).index(["tenantId", "operationId"]), _ = i("_voltro_inv_operations", {
|
|
119
|
+
id: t({ prefix: "ivo" }),
|
|
120
|
+
tenantId: s(),
|
|
121
|
+
state: a().maxLength(16).oneOf([
|
|
122
|
+
"pending",
|
|
123
|
+
"committed",
|
|
124
|
+
"erased"
|
|
125
|
+
]).serverOnly(),
|
|
126
|
+
ownerKey: a().maxLength(64).nullable().serverOnly(),
|
|
127
|
+
sequence: n().nullable().serverOnly(),
|
|
128
|
+
craft: r().nullable().serverOnly(),
|
|
129
|
+
reservation: r().nullable().serverOnly(),
|
|
130
|
+
transfer: r().nullable().serverOnly(),
|
|
131
|
+
digest: a().maxLength(64).nullable().serverOnly(),
|
|
132
|
+
receipt: r().nullable().safe(),
|
|
133
|
+
admission: n().serverOnly(),
|
|
134
|
+
createdAt: o().safe()
|
|
135
|
+
}).index(["tenantId", "ownerKey"]), v = [
|
|
136
|
+
c,
|
|
137
|
+
l,
|
|
138
|
+
u,
|
|
139
|
+
d,
|
|
140
|
+
f
|
|
141
|
+
], y = [
|
|
142
|
+
p,
|
|
143
|
+
m,
|
|
144
|
+
h,
|
|
145
|
+
g,
|
|
146
|
+
_
|
|
147
|
+
], b = i("_voltro_inv_recipes", {
|
|
148
|
+
id: t({ prefix: "ivr" }),
|
|
149
|
+
tenantId: s(),
|
|
150
|
+
recipeId: a().maxLength(120).safe(),
|
|
151
|
+
version: n().safe(),
|
|
152
|
+
definition: r().serverOnly(),
|
|
153
|
+
rulesVersion: a().maxLength(120).safe()
|
|
154
|
+
}).index([
|
|
155
|
+
"tenantId",
|
|
156
|
+
"recipeId",
|
|
157
|
+
"version"
|
|
158
|
+
]), x = [b], S = [
|
|
159
|
+
...v,
|
|
160
|
+
...y,
|
|
161
|
+
...x
|
|
162
|
+
];
|
|
163
|
+
export { l as inventoryCatalogHeadsTable, c as inventoryCatalogLocksTable, f as inventoryCatalogRevisionsTable, u as inventoryCatalogTable, v as inventoryCatalogTables, d as inventoryCatalogVersionsTable, m as inventoryItemsTable, g as inventoryLedgerTable, h as inventoryLoadoutsTable, _ as inventoryOperationsTable, y as inventoryOwnedTables, x as inventoryRecipeTables, b as inventoryRecipesTable, p as inventorySubjectsTable, S as inventoryTables };
|