@voltro/plugin-inventory 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,63 @@
1
+ //#region src/inventoryUiCopy.ts
2
+ var e = Object.freeze({
3
+ en: Object.freeze({
4
+ inventory: "Inventory",
5
+ loading: "Loading inventory…",
6
+ unavailable: "Inventory could not be loaded. Choices will return when the connection recovers.",
7
+ empty: "No items yet.",
8
+ noMatches: "No items match these filters.",
9
+ search: "Find an item",
10
+ tag: "Item tag",
11
+ allTags: "All tags",
12
+ showAll: "Show all items",
13
+ virtualize: "Use compact list",
14
+ equipped: "Equipped",
15
+ locked: "Locked",
16
+ expired: "Expired",
17
+ unknown: "Catalog details unavailable",
18
+ select: "Select item",
19
+ loadout: "Loadout",
20
+ unequipped: "Nothing equipped",
21
+ recipes: "Recipes",
22
+ batches: "Batches",
23
+ materials: "Materials",
24
+ materialsReady: "Materials available",
25
+ materialsMissing: "Materials missing",
26
+ currencyCost: "Game currency cost",
27
+ freeCost: "No currency cost",
28
+ serverCraft: "Crafting is accepted by the game server. Available materials do not reserve items or guarantee payment.",
29
+ count: (e, t) => `${e} of ${t} items`,
30
+ quantity: (e) => `Quantity: ${e}`
31
+ }),
32
+ de: Object.freeze({
33
+ inventory: "Inventar",
34
+ loading: "Inventar wird geladen…",
35
+ unavailable: "Das Inventar konnte nicht geladen werden. Die Auswahl kehrt zurück, sobald die Verbindung wiederhergestellt ist.",
36
+ empty: "Noch keine Items.",
37
+ noMatches: "Keine Items passen zu diesen Filtern.",
38
+ search: "Item suchen",
39
+ tag: "Item-Tag",
40
+ allTags: "Alle Tags",
41
+ showAll: "Alle Items anzeigen",
42
+ virtualize: "Kompakte Liste verwenden",
43
+ equipped: "Ausgerüstet",
44
+ locked: "Gesperrt",
45
+ expired: "Abgelaufen",
46
+ unknown: "Katalogdetails fehlen",
47
+ select: "Item auswählen",
48
+ loadout: "Ausrüstung",
49
+ unequipped: "Nichts ausgerüstet",
50
+ recipes: "Rezepte",
51
+ batches: "Chargen",
52
+ materials: "Materialien",
53
+ materialsReady: "Materialien vorhanden",
54
+ materialsMissing: "Materialien fehlen",
55
+ currencyCost: "Spielwährungskosten",
56
+ freeCost: "Keine Währungskosten",
57
+ serverCraft: "Crafting wird vom Spielserver bestätigt. Vorhandene Materialien reservieren keine Items und garantieren keine Zahlung.",
58
+ count: (e, t) => `${e} von ${t} Items`,
59
+ quantity: (e) => `Anzahl: ${e}`
60
+ })
61
+ });
62
+ //#endregion
63
+ export { e as inventoryUiCopy };
package/dist/item.d.ts ADDED
@@ -0,0 +1,73 @@
1
+ import { Schema } from 'effect';
2
+
3
+ export declare const captureCatalogItem: (input: unknown, contracts: readonly ItemContract[]) => CatalogItem;
4
+
5
+ export declare const captureItemContracts: (input: readonly ItemDefinition[]) => readonly ItemContract[];
6
+
7
+ /** Serializable content uses a declared item's version, never a stored Schema object. */
8
+ export declare interface CatalogItem {
9
+ readonly id: string;
10
+ readonly schemaVersion: number;
11
+ readonly kind: ItemKind;
12
+ readonly stackable: boolean;
13
+ readonly maxStack: number;
14
+ readonly tradable: boolean;
15
+ readonly rarity: string;
16
+ readonly tags: readonly string[];
17
+ readonly equipSlot: string | null;
18
+ readonly expiresAfter: number | null;
19
+ readonly display: {
20
+ readonly nameKey: string;
21
+ readonly icon: string | null;
22
+ };
23
+ readonly attributes: JsonValue;
24
+ readonly instanceDefaults: JsonValue;
25
+ }
26
+
27
+ export declare const contractKey: (id: string, version: number) => string;
28
+
29
+ export declare const defineItem: (input: ItemDefinition) => ItemContract;
30
+
31
+ export declare const ITEM_KINDS: readonly ["consumable", "equipment", "cosmetic", "currencyBundle", "key", "mod"];
32
+
33
+ export declare const itemContent: (contract: ItemContract, attributes: unknown, instanceDefaults: unknown) => CatalogItem;
34
+
35
+ export declare interface ItemContract extends Omit<ItemDefinition, 'schemaVersion' | 'equipSlot' | 'expiresAfter' | 'display'> {
36
+ readonly schemaVersion: number;
37
+ readonly equipSlot: string | null;
38
+ readonly expiresAfter: number | null;
39
+ readonly display: {
40
+ readonly nameKey: string;
41
+ readonly icon: string | null;
42
+ };
43
+ }
44
+
45
+ export declare interface ItemDefinition {
46
+ readonly id: string;
47
+ readonly kind: ItemKind;
48
+ readonly schemaVersion?: number;
49
+ readonly stackable: boolean;
50
+ readonly maxStack: number;
51
+ readonly tradable: boolean;
52
+ readonly rarity: string;
53
+ readonly tags: readonly string[];
54
+ readonly attributes: Schema.Top;
55
+ readonly instanceAttributes: Schema.Top;
56
+ readonly equipSlot?: string | null;
57
+ /** Milliseconds; resolved on grant, never by a tick. */
58
+ readonly expiresAfter?: number | null;
59
+ readonly display: {
60
+ readonly nameKey: string;
61
+ readonly icon?: string | null;
62
+ };
63
+ }
64
+
65
+ export declare type ItemKind = typeof ITEM_KINDS[number];
66
+
67
+ declare type JsonValue = null | boolean | number | string | readonly JsonValue[] | {
68
+ readonly [key: string]: JsonValue;
69
+ };
70
+
71
+ export declare const validateInstanceAttributes: (item: Pick<CatalogItem, "id" | "schemaVersion">, contracts: readonly ItemContract[], input: unknown) => JsonValue;
72
+
73
+ export { }
package/dist/item.js ADDED
@@ -0,0 +1,105 @@
1
+ import { inventoryError as e } from "./errors.js";
2
+ import { identifier as t, integer as n, jsonData as r, list as i, object as a } from "./capture.js";
3
+ import { Schema as o } from "effect";
4
+ //#region src/item.ts
5
+ var s = [
6
+ "consumable",
7
+ "equipment",
8
+ "cosmetic",
9
+ "currencyBundle",
10
+ "key",
11
+ "mod"
12
+ ], c = (r) => {
13
+ let c = a(r, [
14
+ "id",
15
+ "kind",
16
+ "schemaVersion",
17
+ "stackable",
18
+ "maxStack",
19
+ "tradable",
20
+ "rarity",
21
+ "tags",
22
+ "attributes",
23
+ "instanceAttributes",
24
+ "equipSlot",
25
+ "expiresAfter",
26
+ "display"
27
+ ]);
28
+ if (!s.some((e) => e === c.kind) || typeof c.stackable != "boolean" || typeof c.tradable != "boolean" || !o.isSchema(c.attributes) || !o.isSchema(c.instanceAttributes)) throw e("invalid_item");
29
+ let l = n(c.maxStack, 1, 1e6);
30
+ if (!c.stackable && l !== 1) throw e("invalid_item");
31
+ let u = i(c.tags, 64).map(t);
32
+ if (new Set(u).size !== u.length) throw e("invalid_item");
33
+ let d = a(c.display, ["nameKey", "icon"]), f = d.icon ?? null;
34
+ if (f !== null && (typeof f != "string" || f.length > 512 || !/^storage:\/\/[A-Za-z0-9][A-Za-z0-9/_.-]*$/.test(f))) throw e("invalid_item");
35
+ return Object.freeze({
36
+ id: t(c.id),
37
+ kind: c.kind,
38
+ schemaVersion: n(c.schemaVersion ?? 1, 1, 1e6),
39
+ stackable: c.stackable,
40
+ maxStack: l,
41
+ tradable: c.tradable,
42
+ rarity: t(c.rarity),
43
+ tags: Object.freeze(u),
44
+ attributes: c.attributes,
45
+ instanceAttributes: c.instanceAttributes,
46
+ equipSlot: c.equipSlot === void 0 || c.equipSlot === null ? null : t(c.equipSlot),
47
+ expiresAfter: c.expiresAfter === void 0 || c.expiresAfter === null ? null : n(c.expiresAfter, 1, 31536e7),
48
+ display: Object.freeze({
49
+ nameKey: t(d.nameKey),
50
+ icon: f
51
+ })
52
+ });
53
+ }, l = (e, t) => JSON.stringify([e, t]), u = (t, n) => {
54
+ try {
55
+ let i = r(n), a = o.decodeUnknownSync(o.toType(t), { onExcessProperty: "error" })(i);
56
+ if (JSON.stringify(r(a)) !== JSON.stringify(i)) throw e("invalid_attributes");
57
+ return i;
58
+ } catch {
59
+ throw e("invalid_attributes");
60
+ }
61
+ }, d = (t) => {
62
+ let n = i(t, 1e4).map((e) => c(e));
63
+ if (new Set(n.map((e) => l(e.id, e.schemaVersion))).size !== n.length) throw e("invalid_item");
64
+ return Object.freeze(n);
65
+ }, f = (e, t, n) => Object.freeze({
66
+ id: e.id,
67
+ schemaVersion: e.schemaVersion,
68
+ kind: e.kind,
69
+ stackable: e.stackable,
70
+ maxStack: e.maxStack,
71
+ tradable: e.tradable,
72
+ rarity: e.rarity,
73
+ tags: e.tags,
74
+ equipSlot: e.equipSlot,
75
+ expiresAfter: e.expiresAfter,
76
+ display: e.display,
77
+ attributes: u(e.attributes, t),
78
+ instanceDefaults: u(e.instanceAttributes, n)
79
+ }), p = (i, o) => {
80
+ let s = a(i, [
81
+ "id",
82
+ "schemaVersion",
83
+ "kind",
84
+ "stackable",
85
+ "maxStack",
86
+ "tradable",
87
+ "rarity",
88
+ "tags",
89
+ "equipSlot",
90
+ "expiresAfter",
91
+ "display",
92
+ "attributes",
93
+ "instanceDefaults"
94
+ ]), c = t(s.id), l = n(s.schemaVersion, 1, 1e6), u = o.find((e) => e.id === c && e.schemaVersion === l);
95
+ if (!u) throw e("invalid_item");
96
+ let d = f(u, s.attributes, s.instanceDefaults);
97
+ if (JSON.stringify(r(s)) !== JSON.stringify(r(d))) throw e("conflict");
98
+ return d;
99
+ }, m = (t, n, r) => {
100
+ let i = n.find((e) => e.id === t.id && e.schemaVersion === t.schemaVersion);
101
+ if (!i) throw e("invalid_item");
102
+ return u(i.instanceAttributes, r);
103
+ };
104
+ //#endregion
105
+ export { s as ITEM_KINDS, p as captureCatalogItem, d as captureItemContracts, l as contractKey, c as defineItem, f as itemContent, m as validateInstanceAttributes };
package/dist/plugin.js ADDED
@@ -0,0 +1,407 @@
1
+ import { InventoryError as e, inventoryError as t } from "./errors.js";
2
+ import { identifier as n, integer as r, object as i } from "./capture.js";
3
+ import { CraftingPort as a, defaultCraftResolver as o, resolveCraftingOptions as s } from "./crafting.js";
4
+ import { captureItemContracts as c } from "./item.js";
5
+ import { INVENTORY_NAME as ee, inventoryCatalogDescriptor as l, inventoryEquipDescriptor as u, inventoryLoadoutDescriptor as d, inventoryMineDescriptor as f, inventoryRpcClientImports as p } from "./rpc.js";
6
+ import { captureInventoryReleaseInput as m, captureInventoryReservationTransferInput as h, captureInventoryReserveInput as g, captureInventoryReserveTransferInput as _ } from "./reservation.js";
7
+ import { CatalogSource as v } from "./catalog.js";
8
+ import { inventoryCatalogTables as y, inventoryOwnedTables as b, inventoryRecipeTables as x } from "./tables.entity.js";
9
+ import { catalogScope as te, dataStoreCatalog as S } from "./sqlCatalog.js";
10
+ import { defaultExpiryPolicy as C, defaultStackPolicy as w } from "./strategies.js";
11
+ import { dataStoreInventory as T, resolveInventoryOptions as E } from "./inventoryStore.js";
12
+ import { InventoryPort as D } from "./port.js";
13
+ import { Effect as O, Layer as k } from "effect";
14
+ import { defineLicensedGamePlugin as A } from "@voltro/plugin-licensing/gate";
15
+ //#region src/plugin.ts
16
+ var j = Object.freeze({
17
+ slots: {
18
+ stackPolicy: {
19
+ defaultExport: "defaultStackPolicy",
20
+ fixtureExport: "stackPolicySystemFixture"
21
+ },
22
+ expiryPolicy: {
23
+ defaultExport: "defaultExpiryPolicy",
24
+ fixtureExport: "expiryPolicySystemFixture"
25
+ },
26
+ craftResolver: {
27
+ defaultExport: "defaultCraftResolver",
28
+ fixtureExport: "craftResolverSystemFixture"
29
+ }
30
+ },
31
+ ports: {
32
+ inventory: {
33
+ tagExport: "InventoryPort",
34
+ fakeLayerExport: "inventoryFakeLayer",
35
+ fixtureExport: "inventoryPortSystemFixture"
36
+ },
37
+ crafting: {
38
+ tagExport: "CraftingPort",
39
+ fakeLayerExport: "craftingFakeLayer",
40
+ fixtureExport: "craftingPortSystemFixture"
41
+ },
42
+ catalogSource: {
43
+ tagExport: "CatalogSource",
44
+ fakeLayerExport: "catalogFakeLayer",
45
+ fixtureExport: "catalogSourceSystemFixture"
46
+ }
47
+ },
48
+ events: []
49
+ }), M = (j) => {
50
+ let M = i(j, [
51
+ "items",
52
+ "catalogSource",
53
+ "channel",
54
+ "locale",
55
+ "allowedServices",
56
+ "slotSets",
57
+ "maxInstances",
58
+ "maxLedgerRows",
59
+ "now",
60
+ "stackPolicy",
61
+ "expiryPolicy",
62
+ "maxCatalogItems",
63
+ "maxCatalogVersions",
64
+ "service",
65
+ "crafting"
66
+ ]), N = M.crafting === void 0 ? void 0 : s(M.crafting), P = c(M.items), F, I, L, R = !1, z = M.catalogSource === void 0 ? void 0 : i(M.catalogSource);
67
+ if (z && typeof z.read != "function") throw t("invalid_input");
68
+ let B = Object.freeze({ read: (n) => {
69
+ try {
70
+ let e = te(n);
71
+ return O.suspend(() => R ? z ? z.read.call(M.catalogSource, e) : L ? L.read(e) : O.fail(t("unavailable")) : O.fail(t("unavailable")));
72
+ } catch (n) {
73
+ return O.fail(n instanceof e ? n : t("invalid_input"));
74
+ }
75
+ } }), V = E({
76
+ items: P,
77
+ catalogSource: B,
78
+ channel: M.channel ?? "live",
79
+ locale: M.locale ?? "en",
80
+ allowedServices: M.allowedServices,
81
+ slotSets: M.slotSets,
82
+ maxInstances: M.maxInstances,
83
+ maxLedgerRows: M.maxLedgerRows,
84
+ now: M.now,
85
+ stackPolicy: M.stackPolicy,
86
+ expiryPolicy: M.expiryPolicy,
87
+ ...N === void 0 || N.service ? {} : { crafting: N }
88
+ }), H = r(M.maxCatalogItems ?? 1e4, 1, 1e4), U = r(M.maxCatalogVersions ?? 1e4, 1, 1e5), W = {
89
+ items: P,
90
+ allowedServices: V.allowedServices,
91
+ maxCatalogItems: H,
92
+ maxCatalogVersions: U,
93
+ now: V.now
94
+ }, G = M.service === void 0 ? void 0 : i(M.service), K = [
95
+ "grant",
96
+ "consume",
97
+ "mine",
98
+ "loadout",
99
+ "equip",
100
+ "expire",
101
+ "exportSubject",
102
+ "eraseSubject"
103
+ ];
104
+ if (G && K.some((e) => typeof G[e] != "function")) throw t("invalid_input");
105
+ let q = G ? Object.freeze(Object.fromEntries(K.map((e) => [e, G[e].bind(M.service)]))) : void 0;
106
+ if (N && !N.service && q) throw t("invalid_input");
107
+ let J = (e) => O.suspend(() => {
108
+ let n = q ?? I;
109
+ return R && n ? e(n) : O.fail(t("unavailable"));
110
+ }), Y = (e, n, r) => {
111
+ try {
112
+ let t = structuredClone(e), i = structuredClone(n);
113
+ return J((e) => r(e, t, i));
114
+ } catch {
115
+ return O.fail(t("invalid_input"));
116
+ }
117
+ }, X = Object.freeze({
118
+ grant: (e, t) => Y(e, t, (e, t, n) => e.grant(t, n)),
119
+ consume: (e, t) => Y(e, t, (e, t, n) => e.consume(t, n)),
120
+ mine: (e) => Y(e, null, (e, t) => e.mine(t)),
121
+ loadout: (e, t) => Y(e, t, (e, t, n) => e.loadout(t, n)),
122
+ equip: (e, t) => Y(e, t, (e, t, n) => e.equip(t, n)),
123
+ expire: (e, t) => Y(e, t, (e, t, n) => e.expire(t, n)),
124
+ exportSubject: (e) => {
125
+ try {
126
+ let t = structuredClone(e);
127
+ return J((e) => e.exportSubject(t));
128
+ } catch {
129
+ return O.fail(t("invalid_input"));
130
+ }
131
+ },
132
+ eraseSubject: (e) => {
133
+ try {
134
+ let t = structuredClone(e);
135
+ return J((e) => e.eraseSubject(t));
136
+ } catch {
137
+ return O.fail(t("invalid_input"));
138
+ }
139
+ }
140
+ }), Z = Object.freeze({
141
+ craft: (e, n) => {
142
+ try {
143
+ let r = structuredClone(e), i = structuredClone(n);
144
+ return O.suspend(() => !R || !N ? O.fail(t("unavailable")) : N.service ? N.service.craft(r, i) : I ? I.craft(r, i) : O.fail(t("unavailable")));
145
+ } catch {
146
+ return O.fail(t("invalid_input"));
147
+ }
148
+ },
149
+ recipes: (e) => {
150
+ try {
151
+ let n = structuredClone(e);
152
+ return O.suspend(() => !R || !N ? O.fail(t("unavailable")) : N.service ? N.service.recipes(n) : n.type !== "user" && n.type !== "system" && !(n.type === "service" && V.allowedServices.includes(n.service)) ? O.fail(t("forbidden")) : O.succeed(N.recipes));
153
+ } catch {
154
+ return O.fail(t("invalid_input"));
155
+ }
156
+ },
157
+ exportSubject: (e) => {
158
+ try {
159
+ let n = structuredClone(e);
160
+ return O.suspend(() => !R || !N ? O.fail(t("unavailable")) : N.service ? N.service.exportSubject(n) : X.exportSubject(n));
161
+ } catch {
162
+ return O.fail(t("invalid_input"));
163
+ }
164
+ },
165
+ eraseSubject: (e) => {
166
+ try {
167
+ let n = structuredClone(e);
168
+ return O.suspend(() => !R || !N ? O.fail(t("unavailable")) : N.service ? N.service.eraseSubject(n) : X.eraseSubject(n));
169
+ } catch {
170
+ return O.fail(t("invalid_input"));
171
+ }
172
+ }
173
+ }), ne = (r) => {
174
+ try {
175
+ let e = structuredClone(r);
176
+ if (e.type !== "user") throw t("forbidden");
177
+ return B.read({
178
+ tenantId: n(e.tenantId),
179
+ channel: V.channel,
180
+ locale: V.locale
181
+ });
182
+ } catch (n) {
183
+ return O.fail(n instanceof e ? n : t("invalid_input"));
184
+ }
185
+ }, Q = [
186
+ ...z ? [] : y,
187
+ ...q ? [] : b,
188
+ ...N && !N.service ? x : []
189
+ ], re = A({
190
+ name: ee,
191
+ description: "Versioned catalog and SQL-owned item grants, consumption and equip intentions.",
192
+ permissions: ["store:write", "inspect:read"],
193
+ services: N ? k.merge(k.merge(k.succeed(D, X), k.succeed(v, B)), k.succeed(a, Z)) : k.merge(k.succeed(D, X), k.succeed(v, B)),
194
+ routes: [
195
+ {
196
+ ...f,
197
+ execute: (e, t) => X.mine(t.request.subject)
198
+ },
199
+ {
200
+ ...d,
201
+ execute: (e, t) => X.loadout(t.request.subject, e.slotSet)
202
+ },
203
+ {
204
+ ...l,
205
+ execute: (e, t) => ne(t.request.subject)
206
+ },
207
+ {
208
+ ...u,
209
+ execute: (e, t) => X.equip(t.request.subject, e)
210
+ }
211
+ ],
212
+ rpcClientDescriptors: p,
213
+ errorSchemas: [{
214
+ schema: e,
215
+ import: {
216
+ module: "@voltro/plugin-inventory/errors",
217
+ name: "InventoryError"
218
+ }
219
+ }],
220
+ extendSchema: { tables: Q },
221
+ subjectPrivacy: {
222
+ tables: Q.map((e) => e.tableName),
223
+ kinds: ["user", "guest"]
224
+ },
225
+ bindDataStore: (e) => {
226
+ if (F !== void 0 && F !== e) throw Error("Inventory plugin instance cannot cross app stores");
227
+ F = e, z || (L = S(e, W)), q || (I = T(e, V)), R = !0;
228
+ },
229
+ onDeactivate: () => O.sync(() => {
230
+ R = !1, I = void 0, L = void 0;
231
+ }),
232
+ onExport: (e, t) => {
233
+ let n = {
234
+ subjectId: e,
235
+ tenantId: t.tenantId,
236
+ kind: t.kind
237
+ };
238
+ return N?.service ? O.gen(function* () {
239
+ return {
240
+ inventory: yield* X.exportSubject(n),
241
+ crafting: yield* Z.exportSubject(n)
242
+ };
243
+ }) : X.exportSubject(n);
244
+ },
245
+ onErase: (e, t) => {
246
+ let n = {
247
+ subjectId: e,
248
+ tenantId: t.tenantId,
249
+ kind: t.kind
250
+ };
251
+ return N?.service ? O.gen(function* () {
252
+ yield* X.eraseSubject(n), yield* Z.eraseSubject(n);
253
+ }) : X.eraseSubject(n);
254
+ },
255
+ inspectEndpoints: [{
256
+ method: "GET",
257
+ path: "/status",
258
+ scope: "process",
259
+ description: "Captured catalog/port/strategy declarations; no possession, subject or ledger data.",
260
+ handler: () => O.sync(() => ({
261
+ kind: "json",
262
+ data: {
263
+ capturedAt: (V.now ?? Date.now)(),
264
+ bound: R,
265
+ backend: q ? "custom" : "sql",
266
+ channel: V.channel,
267
+ locale: V.locale,
268
+ slots: {
269
+ catalogSource: z ? "custom" : "default",
270
+ stackPolicy: V.stackPolicy === w ? "default" : "custom",
271
+ expiryPolicy: V.expiryPolicy === C ? "default" : "custom"
272
+ },
273
+ contracts: P.map((e) => ({
274
+ id: e.id,
275
+ schemaVersion: e.schemaVersion,
276
+ kind: e.kind,
277
+ maxStack: e.maxStack,
278
+ equipSlot: e.equipSlot
279
+ })),
280
+ slotSets: Object.entries(V.slotSets).map(([e, t]) => ({
281
+ id: e,
282
+ slots: t
283
+ })),
284
+ budgets: {
285
+ instances: V.maxInstances,
286
+ ledgerRows: V.maxLedgerRows,
287
+ catalogItems: H,
288
+ catalogVersions: U
289
+ },
290
+ tableRoles: Q.map((e) => e.tableName),
291
+ craftingInstalled: N !== void 0,
292
+ craftingSystem: N ? {
293
+ backend: N.service ? "custom" : "sql",
294
+ resolver: N.craftResolver === o ? "default" : "custom",
295
+ version: N.version,
296
+ recipes: N.recipes.map((e) => ({
297
+ id: e.id,
298
+ version: e.version,
299
+ inputs: e.inputs,
300
+ outputs: e.outputs.map((e) => ({
301
+ itemId: e.itemId,
302
+ qty: e.qty
303
+ })),
304
+ maxBatches: e.maxBatches,
305
+ cost: e.cost
306
+ })),
307
+ currencyCostInstalled: N.economy !== void 0 || N.service !== void 0 && N.recipes.some((e) => e.cost !== null),
308
+ durationWorkflowInstalled: !1,
309
+ requirementsInstalled: !1,
310
+ playerCraftInstalled: !1
311
+ } : null,
312
+ tradingInstalled: !1
313
+ }
314
+ }))
315
+ }]
316
+ }), $ = (e, r, i, a) => {
317
+ try {
318
+ let o = structuredClone(e), s = n(r), c = structuredClone(i);
319
+ return O.suspend(() => R && I ? a ? I.rebuildInventory(o, s, c) : I.auditInventory(o, s, c) : O.fail(t("unavailable")));
320
+ } catch {
321
+ return O.fail(t("invalid_input"));
322
+ }
323
+ }, ie = (e, n) => {
324
+ try {
325
+ let r = structuredClone(e), i = structuredClone(n);
326
+ return O.suspend(() => R && I && !q ? I.prepareGrant(r, i) : O.fail(t("unavailable")));
327
+ } catch {
328
+ return O.fail(t("invalid_input"));
329
+ }
330
+ }, ae = (e, n) => {
331
+ try {
332
+ let r = structuredClone(e), i = structuredClone(n);
333
+ return O.suspend(() => R && I && N && !N.service && !q ? I.prepareCraft(r, i) : O.fail(t("unavailable")));
334
+ } catch {
335
+ return O.fail(t("invalid_input"));
336
+ }
337
+ }, oe = (n, r) => {
338
+ try {
339
+ let e = structuredClone(n), i = _(r);
340
+ return O.suspend(() => R && I && !q ? I.prepareReserveTransfer(e, i) : O.fail(t("unavailable")));
341
+ } catch (n) {
342
+ return O.fail(n instanceof e ? n : t("invalid_input"));
343
+ }
344
+ }, se = (e, n) => {
345
+ try {
346
+ let r = structuredClone(e), i = h(n);
347
+ return O.suspend(() => R && I && !q ? I.prepareReservationTransfer(r, i) : O.fail(t("unavailable")));
348
+ } catch {
349
+ return O.fail(t("invalid_input"));
350
+ }
351
+ }, ce = (e, n) => {
352
+ try {
353
+ let r = structuredClone(e), i = g(n);
354
+ return O.suspend(() => R && I && !q ? I.prepareReserve(r, i) : O.fail(t("unavailable")));
355
+ } catch {
356
+ return O.fail(t("invalid_input"));
357
+ }
358
+ }, le = (e, n) => {
359
+ try {
360
+ let r = structuredClone(e), i = m(n);
361
+ return O.suspend(() => R && I && !q ? I.prepareRelease(r, i) : O.fail(t("unavailable")));
362
+ } catch {
363
+ return O.fail(t("invalid_input"));
364
+ }
365
+ }, ue = (n, r) => {
366
+ try {
367
+ let e = structuredClone(n), i = m(r);
368
+ return O.suspend(() => R && I && !q ? I.reservationEvidence(e, i) : O.fail(t("unavailable")));
369
+ } catch (n) {
370
+ return O.fail(n instanceof e ? n : t("invalid_input"));
371
+ }
372
+ }, de = (e, n) => {
373
+ try {
374
+ let r = structuredClone(e), i = m(n);
375
+ return O.suspend(() => R && I && !q ? I.reservation(r, i) : O.fail(t("unavailable")));
376
+ } catch {
377
+ return O.fail(t("invalid_input"));
378
+ }
379
+ };
380
+ return {
381
+ ...re,
382
+ inventory: Object.freeze({
383
+ prepareReservationTransfer: se,
384
+ prepareReserveTransfer: oe,
385
+ prepareReserve: ce,
386
+ prepareRelease: le,
387
+ reservation: de,
388
+ reservationEvidence: ue,
389
+ prepareGrant: ie,
390
+ prepareCraft: ae,
391
+ service: () => X,
392
+ crafting: () => Z,
393
+ auditInventory: (e, t, n) => $(e, t, n, !1),
394
+ rebuildInventory: (e, t, n) => $(e, t, n, !0),
395
+ importCatalog: (e, n) => {
396
+ try {
397
+ let r = structuredClone(e), i = structuredClone(n);
398
+ return O.suspend(() => R && L ? L.importSnapshot(r, i) : O.fail(t("unavailable")));
399
+ } catch {
400
+ return O.fail(t("invalid_input"));
401
+ }
402
+ }
403
+ })
404
+ };
405
+ };
406
+ //#endregion
407
+ export { M as inventoryPlugin, j as inventorySystemContract };
package/dist/port.js ADDED
@@ -0,0 +1,5 @@
1
+ import { Context as e } from "effect";
2
+ //#region src/port.ts
3
+ var t = class extends e.Service()("@voltro/InventoryPort") {};
4
+ //#endregion
5
+ export { t as InventoryPort };