@crowdedkingdoms/crowdyjs 17.13.0-dev.1 → 18.0.0-dev.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (284) hide show
  1. package/MIGRATION.md +163 -1
  2. package/README.md +142 -146
  3. package/dist/crowdy-client.d.ts +12 -31
  4. package/dist/crowdy-client.d.ts.map +1 -1
  5. package/dist/crowdy-client.js +15 -37
  6. package/dist/crowdy-dsh/bridge.d.ts.map +1 -1
  7. package/dist/crowdy-dsh/bridge.js +3 -6
  8. package/dist/crowdy-studio/controller.d.ts +59 -57
  9. package/dist/crowdy-studio/controller.d.ts.map +1 -1
  10. package/dist/crowdy-studio/controller.js +268 -206
  11. package/dist/crowdy-studio/diagnostics.d.ts +3 -12
  12. package/dist/crowdy-studio/diagnostics.d.ts.map +1 -1
  13. package/dist/crowdy-studio/dom-shell.d.ts +2 -4
  14. package/dist/crowdy-studio/dom-shell.d.ts.map +1 -1
  15. package/dist/crowdy-studio/dom-shell.js +16 -47
  16. package/dist/crowdy-studio/embed/hud-layer.d.ts +1 -1
  17. package/dist/crowdy-studio/embed/panel.d.ts +3 -12
  18. package/dist/crowdy-studio/embed/panel.d.ts.map +1 -1
  19. package/dist/crowdy-studio/embed/panel.js +3 -6
  20. package/dist/crowdy-studio/index.d.ts +1 -3
  21. package/dist/crowdy-studio/index.d.ts.map +1 -1
  22. package/dist/crowdy-studio/index.js +0 -2
  23. package/dist/crowdy-studio/models.d.ts +3 -4
  24. package/dist/crowdy-studio/models.d.ts.map +1 -1
  25. package/dist/crowdy-studio/starter-projects.d.ts +8 -4
  26. package/dist/crowdy-studio/starter-projects.d.ts.map +1 -1
  27. package/dist/crowdy-studio/starter-projects.js +83 -100
  28. package/dist/domains/appAccess.d.ts +14 -1
  29. package/dist/domains/appAccess.d.ts.map +1 -1
  30. package/dist/domains/appAccess.js +37 -1
  31. package/dist/domains/exec.d.ts +162 -15
  32. package/dist/domains/exec.d.ts.map +1 -1
  33. package/dist/domains/exec.js +180 -18
  34. package/dist/domains/host.d.ts +3 -3
  35. package/dist/domains/host.js +3 -3
  36. package/dist/domains/marketplace.d.ts +9 -58
  37. package/dist/domains/marketplace.d.ts.map +1 -1
  38. package/dist/domains/marketplace.js +9 -106
  39. package/dist/domains/playerWallet.d.ts +6 -12
  40. package/dist/domains/playerWallet.d.ts.map +1 -1
  41. package/dist/domains/playerWallet.js +6 -21
  42. package/dist/errors.d.ts +7 -13
  43. package/dist/errors.d.ts.map +1 -1
  44. package/dist/errors.js +6 -10
  45. package/dist/generated/graphql.d.ts +1384 -7977
  46. package/dist/generated/graphql.d.ts.map +1 -1
  47. package/dist/generated/graphql.js +22 -321
  48. package/dist/grid-mods/exec-client-halves.d.ts +156 -0
  49. package/dist/grid-mods/exec-client-halves.d.ts.map +1 -0
  50. package/dist/grid-mods/exec-client-halves.js +356 -0
  51. package/dist/grid-mods/grid-host-calls.d.ts +29 -15
  52. package/dist/grid-mods/grid-host-calls.d.ts.map +1 -1
  53. package/dist/grid-mods/grid-host-calls.js +40 -44
  54. package/dist/grid-mods/index.d.ts +1 -0
  55. package/dist/grid-mods/index.d.ts.map +1 -1
  56. package/dist/grid-mods/index.js +1 -0
  57. package/dist/grid-mods/mod-runtime.d.ts +21 -6
  58. package/dist/grid-mods/mod-runtime.d.ts.map +1 -1
  59. package/dist/grid-mods/mod-runtime.js +6 -2
  60. package/dist/grid-scope.d.ts +0 -188
  61. package/dist/grid-scope.d.ts.map +1 -1
  62. package/dist/grid-scope.js +0 -69
  63. package/dist/index.d.ts +12 -18
  64. package/dist/index.d.ts.map +1 -1
  65. package/dist/index.js +11 -16
  66. package/dist/kit/actions.d.ts +5 -9
  67. package/dist/kit/actions.d.ts.map +1 -1
  68. package/dist/kit/actions.js +5 -9
  69. package/dist/kit/index.d.ts +2 -33
  70. package/dist/kit/index.d.ts.map +1 -1
  71. package/dist/kit/index.js +1 -32
  72. package/dist/kit/kit.d.ts +8 -208
  73. package/dist/kit/kit.d.ts.map +1 -1
  74. package/dist/kit/kit.js +5 -163
  75. package/dist/kit/social.d.ts +1 -3
  76. package/dist/kit/social.d.ts.map +1 -1
  77. package/dist/kit/social.js +1 -3
  78. package/dist/kit/wire.d.ts +16 -5
  79. package/dist/kit/wire.d.ts.map +1 -1
  80. package/dist/kit/wire.js +19 -5
  81. package/dist/live-coding/assets/browser-authoring-index.json +1 -1
  82. package/dist/live-coding/assets/manifest.json +1 -1
  83. package/dist/live-coding/browser-authoring-index.generated.d.ts.map +1 -1
  84. package/dist/live-coding/browser-authoring-index.generated.js +1496 -4386
  85. package/dist/live-coding/rust-analysis.d.ts.map +1 -1
  86. package/dist/live-coding/rust-analysis.js +31 -23
  87. package/dist/player-runtime/client-host-calls.d.ts +8 -0
  88. package/dist/player-runtime/client-host-calls.d.ts.map +1 -0
  89. package/dist/player-runtime/client-host-calls.js +28 -0
  90. package/dist/player-runtime/glue-runtime.d.ts +27 -10
  91. package/dist/player-runtime/glue-runtime.d.ts.map +1 -1
  92. package/dist/player-runtime/glue-runtime.js +40 -45
  93. package/dist/player-runtime/glue-sab.d.ts +2 -2
  94. package/dist/player-runtime/glue-sab.js +2 -2
  95. package/dist/player-runtime/player-code-broker.d.ts +80 -24
  96. package/dist/player-runtime/player-code-broker.d.ts.map +1 -1
  97. package/dist/player-runtime/player-code-broker.js +169 -41
  98. package/dist/player-runtime/player-glue-worker.d.ts +8 -8
  99. package/dist/player-runtime/player-glue-worker.d.ts.map +1 -1
  100. package/dist/player-runtime/player-glue-worker.js +26 -9
  101. package/dist/stores/actors.d.ts +12 -2
  102. package/dist/stores/actors.d.ts.map +1 -1
  103. package/dist/stores/actors.js +43 -18
  104. package/dist/stores/chunks.d.ts +12 -0
  105. package/dist/stores/chunks.d.ts.map +1 -1
  106. package/dist/stores/chunks.js +112 -39
  107. package/dist/stores/durable.d.ts.map +1 -1
  108. package/dist/stores/durable.js +2 -1
  109. package/dist/stores/inbox.d.ts +1 -1
  110. package/dist/stores/inbox.d.ts.map +1 -1
  111. package/dist/stores/index.d.ts +0 -11
  112. package/dist/stores/index.d.ts.map +1 -1
  113. package/dist/stores/index.js +0 -4
  114. package/dist/stores/session.d.ts +0 -2
  115. package/dist/stores/session.d.ts.map +1 -1
  116. package/package.json +1 -1
  117. package/dist/crowdy-studio/model-lint-log.d.ts +0 -76
  118. package/dist/crowdy-studio/model-lint-log.d.ts.map +0 -1
  119. package/dist/crowdy-studio/model-lint-log.js +0 -93
  120. package/dist/crowdy-studio/model-lint.d.ts +0 -61
  121. package/dist/crowdy-studio/model-lint.d.ts.map +0 -1
  122. package/dist/crowdy-studio/model-lint.js +0 -45
  123. package/dist/domains/compute.d.ts +0 -208
  124. package/dist/domains/compute.d.ts.map +0 -1
  125. package/dist/domains/compute.js +0 -274
  126. package/dist/domains/controlPlane.d.ts +0 -38
  127. package/dist/domains/controlPlane.d.ts.map +0 -1
  128. package/dist/domains/controlPlane.js +0 -43
  129. package/dist/domains/gameModel.d.ts +0 -1174
  130. package/dist/domains/gameModel.d.ts.map +0 -1
  131. package/dist/domains/gameModel.js +0 -1333
  132. package/dist/domains/playerCompute.d.ts +0 -91
  133. package/dist/domains/playerCompute.d.ts.map +0 -1
  134. package/dist/domains/playerCompute.js +0 -136
  135. package/dist/domains/playerModel.d.ts +0 -20
  136. package/dist/domains/playerModel.d.ts.map +0 -1
  137. package/dist/domains/playerModel.js +0 -54
  138. package/dist/kit/abilities.d.ts +0 -66
  139. package/dist/kit/abilities.d.ts.map +0 -1
  140. package/dist/kit/abilities.js +0 -71
  141. package/dist/kit/blueprints/combat.d.ts +0 -81
  142. package/dist/kit/blueprints/combat.d.ts.map +0 -1
  143. package/dist/kit/blueprints/combat.js +0 -357
  144. package/dist/kit/blueprints/core.d.ts +0 -222
  145. package/dist/kit/blueprints/core.d.ts.map +0 -1
  146. package/dist/kit/blueprints/core.js +0 -185
  147. package/dist/kit/blueprints/decks.d.ts +0 -50
  148. package/dist/kit/blueprints/decks.d.ts.map +0 -1
  149. package/dist/kit/blueprints/decks.js +0 -163
  150. package/dist/kit/blueprints/economy.d.ts +0 -88
  151. package/dist/kit/blueprints/economy.d.ts.map +0 -1
  152. package/dist/kit/blueprints/economy.js +0 -533
  153. package/dist/kit/blueprints/guild.d.ts +0 -51
  154. package/dist/kit/blueprints/guild.d.ts.map +0 -1
  155. package/dist/kit/blueprints/guild.js +0 -50
  156. package/dist/kit/blueprints/index.d.ts +0 -23
  157. package/dist/kit/blueprints/index.d.ts.map +0 -1
  158. package/dist/kit/blueprints/index.js +0 -22
  159. package/dist/kit/blueprints/inventory.d.ts +0 -84
  160. package/dist/kit/blueprints/inventory.d.ts.map +0 -1
  161. package/dist/kit/blueprints/inventory.js +0 -257
  162. package/dist/kit/blueprints/leaderboards.d.ts +0 -49
  163. package/dist/kit/blueprints/leaderboards.d.ts.map +0 -1
  164. package/dist/kit/blueprints/leaderboards.js +0 -126
  165. package/dist/kit/blueprints/liveops.d.ts +0 -42
  166. package/dist/kit/blueprints/liveops.d.ts.map +0 -1
  167. package/dist/kit/blueprints/liveops.js +0 -170
  168. package/dist/kit/blueprints/locks.d.ts +0 -82
  169. package/dist/kit/blueprints/locks.d.ts.map +0 -1
  170. package/dist/kit/blueprints/locks.js +0 -155
  171. package/dist/kit/blueprints/loot.d.ts +0 -90
  172. package/dist/kit/blueprints/loot.d.ts.map +0 -1
  173. package/dist/kit/blueprints/loot.js +0 -229
  174. package/dist/kit/blueprints/matches.d.ts +0 -84
  175. package/dist/kit/blueprints/matches.d.ts.map +0 -1
  176. package/dist/kit/blueprints/matches.js +0 -349
  177. package/dist/kit/blueprints/moderation.d.ts +0 -32
  178. package/dist/kit/blueprints/moderation.d.ts.map +0 -1
  179. package/dist/kit/blueprints/moderation.js +0 -140
  180. package/dist/kit/blueprints/npcs.d.ts +0 -78
  181. package/dist/kit/blueprints/npcs.d.ts.map +0 -1
  182. package/dist/kit/blueprints/npcs.js +0 -125
  183. package/dist/kit/blueprints/plots.d.ts +0 -63
  184. package/dist/kit/blueprints/plots.d.ts.map +0 -1
  185. package/dist/kit/blueprints/plots.js +0 -151
  186. package/dist/kit/blueprints/progression.d.ts +0 -68
  187. package/dist/kit/blueprints/progression.d.ts.map +0 -1
  188. package/dist/kit/blueprints/progression.js +0 -324
  189. package/dist/kit/blueprints/quests.d.ts +0 -72
  190. package/dist/kit/blueprints/quests.d.ts.map +0 -1
  191. package/dist/kit/blueprints/quests.js +0 -285
  192. package/dist/kit/blueprints/worldsim.d.ts +0 -91
  193. package/dist/kit/blueprints/worldsim.d.ts.map +0 -1
  194. package/dist/kit/blueprints/worldsim.js +0 -468
  195. package/dist/kit/combat.d.ts +0 -141
  196. package/dist/kit/combat.d.ts.map +0 -1
  197. package/dist/kit/combat.js +0 -196
  198. package/dist/kit/decks.d.ts +0 -157
  199. package/dist/kit/decks.d.ts.map +0 -1
  200. package/dist/kit/decks.js +0 -186
  201. package/dist/kit/director.d.ts +0 -88
  202. package/dist/kit/director.d.ts.map +0 -1
  203. package/dist/kit/director.js +0 -86
  204. package/dist/kit/economy.d.ts +0 -289
  205. package/dist/kit/economy.d.ts.map +0 -1
  206. package/dist/kit/economy.js +0 -427
  207. package/dist/kit/engine.d.ts +0 -48
  208. package/dist/kit/engine.d.ts.map +0 -1
  209. package/dist/kit/engine.js +0 -113
  210. package/dist/kit/features.d.ts +0 -60
  211. package/dist/kit/features.d.ts.map +0 -1
  212. package/dist/kit/features.js +0 -65
  213. package/dist/kit/instances.d.ts +0 -52
  214. package/dist/kit/instances.d.ts.map +0 -1
  215. package/dist/kit/instances.js +0 -60
  216. package/dist/kit/inventory.d.ts +0 -129
  217. package/dist/kit/inventory.d.ts.map +0 -1
  218. package/dist/kit/inventory.js +0 -200
  219. package/dist/kit/leaderboards.d.ts +0 -86
  220. package/dist/kit/leaderboards.d.ts.map +0 -1
  221. package/dist/kit/leaderboards.js +0 -133
  222. package/dist/kit/liveops.d.ts +0 -112
  223. package/dist/kit/liveops.d.ts.map +0 -1
  224. package/dist/kit/liveops.js +0 -183
  225. package/dist/kit/loot.d.ts +0 -128
  226. package/dist/kit/loot.d.ts.map +0 -1
  227. package/dist/kit/loot.js +0 -160
  228. package/dist/kit/matches.d.ts +0 -301
  229. package/dist/kit/matches.d.ts.map +0 -1
  230. package/dist/kit/matches.js +0 -458
  231. package/dist/kit/matchmaking.d.ts +0 -57
  232. package/dist/kit/matchmaking.d.ts.map +0 -1
  233. package/dist/kit/matchmaking.js +0 -59
  234. package/dist/kit/minigames.d.ts +0 -30
  235. package/dist/kit/minigames.d.ts.map +0 -1
  236. package/dist/kit/minigames.js +0 -38
  237. package/dist/kit/mobs.d.ts +0 -90
  238. package/dist/kit/mobs.d.ts.map +0 -1
  239. package/dist/kit/mobs.js +0 -98
  240. package/dist/kit/moderation.d.ts +0 -73
  241. package/dist/kit/moderation.d.ts.map +0 -1
  242. package/dist/kit/moderation.js +0 -103
  243. package/dist/kit/movement.d.ts +0 -78
  244. package/dist/kit/movement.d.ts.map +0 -1
  245. package/dist/kit/movement.js +0 -103
  246. package/dist/kit/notifications.d.ts +0 -45
  247. package/dist/kit/notifications.d.ts.map +0 -1
  248. package/dist/kit/notifications.js +0 -67
  249. package/dist/kit/npcs.d.ts +0 -226
  250. package/dist/kit/npcs.d.ts.map +0 -1
  251. package/dist/kit/npcs.js +0 -141
  252. package/dist/kit/objects.d.ts +0 -116
  253. package/dist/kit/objects.d.ts.map +0 -1
  254. package/dist/kit/objects.js +0 -119
  255. package/dist/kit/pets.d.ts +0 -85
  256. package/dist/kit/pets.d.ts.map +0 -1
  257. package/dist/kit/pets.js +0 -96
  258. package/dist/kit/plots.d.ts +0 -85
  259. package/dist/kit/plots.d.ts.map +0 -1
  260. package/dist/kit/plots.js +0 -113
  261. package/dist/kit/progression.d.ts +0 -181
  262. package/dist/kit/progression.d.ts.map +0 -1
  263. package/dist/kit/progression.js +0 -265
  264. package/dist/kit/quests.d.ts +0 -171
  265. package/dist/kit/quests.d.ts.map +0 -1
  266. package/dist/kit/quests.js +0 -237
  267. package/dist/kit/racing.d.ts +0 -85
  268. package/dist/kit/racing.d.ts.map +0 -1
  269. package/dist/kit/racing.js +0 -99
  270. package/dist/kit/shared.d.ts +0 -73
  271. package/dist/kit/shared.d.ts.map +0 -1
  272. package/dist/kit/shared.js +0 -101
  273. package/dist/kit/telemetry.d.ts +0 -66
  274. package/dist/kit/telemetry.d.ts.map +0 -1
  275. package/dist/kit/telemetry.js +0 -133
  276. package/dist/kit/territory.d.ts +0 -97
  277. package/dist/kit/territory.d.ts.map +0 -1
  278. package/dist/kit/territory.js +0 -114
  279. package/dist/kit/worldsim.d.ts +0 -263
  280. package/dist/kit/worldsim.d.ts.map +0 -1
  281. package/dist/kit/worldsim.js +0 -268
  282. package/dist/stores/model.d.ts +0 -81
  283. package/dist/stores/model.d.ts.map +0 -1
  284. package/dist/stores/model.js +0 -163
@@ -1,427 +0,0 @@
1
- import { economyCurrencyFn, economyNames, } from './blueprints/index.js';
2
- import { kitContainerProperties, kitInvoke, } from './shared.js';
3
- /**
4
- * Runtime helpers for the {@link economyBlueprint} conventions: wallets with
5
- * per-currency balances, shop purchases, escrow trades, and player market
6
- * listings. Every movement of currency or items is a single gated invoke —
7
- * balances, stock, item identity, and ownership are all verified
8
- * server-side, and a denial resolves with `success: false` (never an
9
- * exception).
10
- *
11
- * `earn` is a trusted grant: with the default blueprint authority
12
- * (`'server'`) it succeeds only for app admins — call it from studio/backend
13
- * code, or drive grants through automations instead.
14
- *
15
- * Obtained via `client.kit(appId).economy`.
16
- */
17
- export class EconomyKit {
18
- constructor(appId, gameModel, options = {}, engines) {
19
- this.appId = appId;
20
- this.gameModel = gameModel;
21
- /** Shop (admin-priced listings; atomic buys). */
22
- this.shop = {
23
- /**
24
- * Create a shop listing (admin — the type is admin-instantiable).
25
- * `maxStock` feeds the optional restock automation.
26
- */
27
- create: async (input) => {
28
- return this.gameModel.createContainer({
29
- appId: this.appId,
30
- typeName: this.names.listingType,
31
- displayName: input.displayName,
32
- properties: [
33
- { key: 'item_id', valueType: 'string', valueJson: JSON.stringify(input.itemId) },
34
- { key: 'price', valueType: 'int', valueJson: String(input.price) },
35
- { key: 'stock', valueType: 'int', valueJson: String(input.stock ?? 0) },
36
- {
37
- key: 'max_stock',
38
- valueType: 'int',
39
- valueJson: String(input.maxStock ?? input.stock ?? 0),
40
- },
41
- ...(input.properties ?? []),
42
- ],
43
- });
44
- },
45
- /** List shop listings with parsed state. */
46
- list: async () => {
47
- const containers = await this.gameModel.containers({
48
- appId: this.appId,
49
- typeName: this.names.listingType,
50
- });
51
- return Promise.all(containers.map(async (c) => {
52
- const props = await kitContainerProperties(this.gameModel, String(this.appId), c.containerId);
53
- return {
54
- containerId: c.containerId,
55
- displayName: c.displayName,
56
- itemId: String(props.item_id ?? ''),
57
- price: Number(props.price ?? 0),
58
- stock: Number(props.stock ?? 0),
59
- maxStock: Number(props.max_stock ?? 0),
60
- };
61
- }));
62
- },
63
- /**
64
- * Buy one unit: wallet debit + stock decrement + item grant into
65
- * `toStackId` (a stack of the listed item), all in one transaction.
66
- * Resolves with the wallet's remaining balance.
67
- */
68
- buy: async (input) => {
69
- return kitInvoke(this.gameModel, {
70
- appId: String(this.appId),
71
- functionName: this.names.buyListingFn,
72
- selfContainerId: input.listingId,
73
- params: { wallet_id: input.walletId, to_stack_id: input.toStackId },
74
- });
75
- },
76
- };
77
- /** Escrow trades (player↔player item swaps, atomic on accept). */
78
- this.trades = {
79
- /**
80
- * Create a trade offer to another player. The stacks named here are the
81
- * OFFERER's: `giveStackId` is the escrowed source, `receiveStackId`
82
- * receives the wanted items when the trade is accepted. The offer's
83
- * container ownership (server-assigned to the caller) is what the accept
84
- * guards trust — a forged offer over someone else's stacks can never be
85
- * accepted.
86
- */
87
- offer: async (input) => {
88
- return this.gameModel.createContainer({
89
- appId: this.appId,
90
- typeName: this.names.tradeType,
91
- displayName: input.displayName ??
92
- `Trade ${input.giveQty}x ${input.giveItemId} for ${input.wantQty}x ${input.wantItemId}`,
93
- ...(input.sessionId !== undefined ? { sessionId: input.sessionId } : {}),
94
- properties: [
95
- { key: 'to_user_id', valueType: 'int', valueJson: String(input.toUserId) },
96
- {
97
- key: 'give_stack_id',
98
- valueType: 'string',
99
- valueJson: JSON.stringify(input.giveStackId),
100
- },
101
- {
102
- key: 'receive_stack_id',
103
- valueType: 'string',
104
- valueJson: JSON.stringify(input.receiveStackId),
105
- },
106
- {
107
- key: 'give_item_id',
108
- valueType: 'string',
109
- valueJson: JSON.stringify(input.giveItemId),
110
- },
111
- { key: 'give_qty', valueType: 'int', valueJson: String(input.giveQty) },
112
- {
113
- key: 'want_item_id',
114
- valueType: 'string',
115
- valueJson: JSON.stringify(input.wantItemId),
116
- },
117
- { key: 'want_qty', valueType: 'int', valueJson: String(input.wantQty) },
118
- ],
119
- });
120
- },
121
- /**
122
- * Accept a trade as the invited player, supplying YOUR two stacks: the
123
- * one paying the wanted items and the one receiving the given items. The
124
- * offerer's stacks come from the offer record. All four quantity writes
125
- * commit atomically or not at all.
126
- */
127
- accept: async (input) => {
128
- const offer = await this.trades.get(input.offerId);
129
- return kitInvoke(this.gameModel, {
130
- appId: String(this.appId),
131
- functionName: this.names.acceptTradeFn,
132
- selfContainerId: input.offerId,
133
- params: {
134
- give_stack_id: offer.giveStackId,
135
- to_give_stack_id: input.toGiveStackId,
136
- want_stack_id: input.wantStackId,
137
- to_want_stack_id: offer.receiveStackId,
138
- },
139
- });
140
- },
141
- /** Cancel an open trade (either party may). */
142
- cancel: async (offerId) => {
143
- return kitInvoke(this.gameModel, {
144
- appId: String(this.appId),
145
- functionName: this.names.cancelTradeFn,
146
- selfContainerId: offerId,
147
- params: {},
148
- });
149
- },
150
- /** Read one trade offer with parsed state. */
151
- get: async (offerId) => {
152
- const container = await this.gameModel.container({
153
- appId: this.appId,
154
- containerId: offerId,
155
- });
156
- return this.toTrade(container.containerId, container.displayName, container.ownerUserId != null ? String(container.ownerUserId) : null);
157
- },
158
- /** List trades the user created or was invited to (open ones first). */
159
- listMine: async (userId) => {
160
- const containers = await this.gameModel.containers({
161
- appId: this.appId,
162
- typeName: this.names.tradeType,
163
- });
164
- const all = await Promise.all(containers.map((c) => this.toTrade(c.containerId, c.displayName, c.ownerUserId != null ? String(c.ownerUserId) : null)));
165
- const uid = String(userId);
166
- return all
167
- .filter((t) => t.fromUserId === uid || String(t.toUserId) === uid)
168
- .sort((a, b) => Number(b.status === 'open') - Number(a.status === 'open'));
169
- },
170
- };
171
- /** Player market (list a stack for currency; atomic purchases). */
172
- this.market = {
173
- /**
174
- * List items for sale: names YOUR escrowed source stack and the ask
175
- * price. Payment lands straight in your wallet when someone buys.
176
- */
177
- list: async (input) => {
178
- return this.gameModel.createContainer({
179
- appId: this.appId,
180
- typeName: this.names.marketType,
181
- displayName: input.displayName ?? `${input.quantity}x ${input.itemId} for ${input.price}`,
182
- ...(input.sessionId !== undefined ? { sessionId: input.sessionId } : {}),
183
- properties: [
184
- {
185
- key: 'stack_id',
186
- valueType: 'string',
187
- valueJson: JSON.stringify(input.stackId),
188
- },
189
- {
190
- key: 'item_id',
191
- valueType: 'string',
192
- valueJson: JSON.stringify(input.itemId),
193
- },
194
- { key: 'quantity', valueType: 'int', valueJson: String(input.quantity) },
195
- { key: 'price', valueType: 'int', valueJson: String(input.price) },
196
- ],
197
- });
198
- },
199
- /** Browse market listings (active ones only by default). */
200
- browse: async (options = {}) => {
201
- const containers = await this.gameModel.containers({
202
- appId: this.appId,
203
- typeName: this.names.marketType,
204
- });
205
- const all = await Promise.all(containers.map(async (c) => {
206
- const props = await kitContainerProperties(this.gameModel, String(this.appId), c.containerId);
207
- return {
208
- containerId: c.containerId,
209
- displayName: c.displayName,
210
- sellerUserId: c.ownerUserId != null ? String(c.ownerUserId) : null,
211
- stackId: String(props.stack_id ?? ''),
212
- itemId: String(props.item_id ?? ''),
213
- quantity: Number(props.quantity ?? 0),
214
- price: Number(props.price ?? 0),
215
- active: props.active === true,
216
- };
217
- }));
218
- return options.includeInactive ? all : all.filter((l) => l.active);
219
- },
220
- /**
221
- * Buy a market listing: pays the seller's wallet and transfers the items
222
- * into `toStackId` in one transaction. The seller's wallet and source
223
- * stack are resolved from the listing. Resolves with the buyer wallet's
224
- * remaining balance.
225
- */
226
- buy: async (input) => {
227
- const container = await this.gameModel.container({
228
- appId: this.appId,
229
- containerId: input.listingId,
230
- });
231
- const props = await kitContainerProperties(this.gameModel, String(this.appId), input.listingId);
232
- if (container.ownerUserId == null) {
233
- throw new Error('Market listing has no seller (unowned container)');
234
- }
235
- const sellerWallet = await this.ensureSellerWallet(String(container.ownerUserId));
236
- return kitInvoke(this.gameModel, {
237
- appId: String(this.appId),
238
- functionName: this.names.buyMarketFn,
239
- selfContainerId: input.listingId,
240
- params: {
241
- wallet_id: input.walletId,
242
- seller_wallet_id: sellerWallet,
243
- from_stack_id: String(props.stack_id ?? ''),
244
- to_stack_id: input.toStackId,
245
- },
246
- });
247
- },
248
- /** Take a listing down (seller only). */
249
- cancel: async (listingId) => {
250
- return kitInvoke(this.gameModel, {
251
- appId: String(this.appId),
252
- functionName: this.names.cancelMarketFn,
253
- selfContainerId: listingId,
254
- params: {},
255
- });
256
- },
257
- };
258
- this.typePrefix = options.typePrefix ?? '';
259
- this.names = economyNames(this.typePrefix);
260
- this.currencies = options.currencies ?? ['gold'];
261
- this.orderBook = new MarketKit(engines, options.marketModuleName ?? 'market-engine');
262
- }
263
- get defaultCurrency() {
264
- return this.currencies[0];
265
- }
266
- /**
267
- * Find the player's wallet, creating it when absent (member-instantiable;
268
- * the server assigns ownership to the caller). Sets the `owner_user_id`
269
- * mirror property the blueprint's guards read.
270
- *
271
- * @param ownerUserId - The calling player's user id (decimal string).
272
- */
273
- async ensureWallet(ownerUserId, options = {}) {
274
- const existing = await this.gameModel.containers({
275
- appId: this.appId,
276
- typeName: this.names.walletType,
277
- ...(options.sessionId !== undefined ? { sessionId: options.sessionId } : {}),
278
- });
279
- const mine = existing.find((c) => c.ownerUserId != null && String(c.ownerUserId) === String(ownerUserId));
280
- if (mine)
281
- return mine;
282
- return this.gameModel.createContainer({
283
- appId: this.appId,
284
- typeName: this.names.walletType,
285
- displayName: options.displayName ?? `Wallet ${ownerUserId}`,
286
- ...(options.sessionId !== undefined ? { sessionId: options.sessionId } : {}),
287
- properties: [
288
- { key: 'owner_user_id', valueType: 'int', valueJson: String(ownerUserId) },
289
- ],
290
- });
291
- }
292
- /** Read one currency balance (default: the blueprint's first currency). */
293
- async balance(walletId, currency) {
294
- const props = await kitContainerProperties(this.gameModel, String(this.appId), walletId);
295
- return Number(props[currency ?? this.defaultCurrency] ?? 0);
296
- }
297
- /** Read a wallet with every configured currency balance parsed. */
298
- async wallet(walletId) {
299
- const container = await this.gameModel.container({
300
- appId: this.appId,
301
- containerId: walletId,
302
- });
303
- const props = await kitContainerProperties(this.gameModel, String(this.appId), walletId);
304
- const balances = {};
305
- for (const c of this.currencies)
306
- balances[c] = Number(props[c] ?? 0);
307
- return {
308
- containerId: container.containerId,
309
- displayName: container.displayName,
310
- ownerUserId: container.ownerUserId != null ? String(container.ownerUserId) : null,
311
- balances,
312
- };
313
- }
314
- /**
315
- * Mint currency into a wallet — a **trusted** grant (default blueprint
316
- * authority: app admins only). Resolves with the new balance.
317
- */
318
- async earn(walletId, amount, currency) {
319
- return kitInvoke(this.gameModel, {
320
- appId: String(this.appId),
321
- functionName: economyCurrencyFn('earn', currency ?? this.defaultCurrency, this.typePrefix),
322
- selfContainerId: walletId,
323
- params: { amount },
324
- });
325
- }
326
- /**
327
- * Spend currency from the caller's own wallet. The server refuses to
328
- * overdraw. Resolves with the new balance.
329
- */
330
- async spend(walletId, amount, currency) {
331
- return kitInvoke(this.gameModel, {
332
- appId: String(this.appId),
333
- functionName: economyCurrencyFn('spend', currency ?? this.defaultCurrency, this.typePrefix),
334
- selfContainerId: walletId,
335
- params: { amount },
336
- });
337
- }
338
- /** Find an existing wallet container id for a user (no creation). */
339
- async ensureSellerWallet(sellerUserId) {
340
- const wallets = await this.gameModel.containers({
341
- appId: this.appId,
342
- typeName: this.names.walletType,
343
- });
344
- const wallet = wallets.find((c) => c.ownerUserId != null && String(c.ownerUserId) === sellerUserId);
345
- if (!wallet) {
346
- throw new Error(`Seller ${sellerUserId} has no ${this.names.walletType}; they must ensureWallet() before selling`);
347
- }
348
- return wallet.containerId;
349
- }
350
- async toTrade(containerId, displayName, ownerUserId) {
351
- const props = await kitContainerProperties(this.gameModel, String(this.appId), containerId);
352
- return {
353
- containerId,
354
- displayName,
355
- fromUserId: ownerUserId,
356
- toUserId: Number(props.to_user_id ?? 0),
357
- giveStackId: String(props.give_stack_id ?? ''),
358
- receiveStackId: String(props.receive_stack_id ?? ''),
359
- giveItemId: String(props.give_item_id ?? ''),
360
- giveQty: Number(props.give_qty ?? 0),
361
- wantItemId: String(props.want_item_id ?? ''),
362
- wantQty: Number(props.want_qty ?? 0),
363
- status: String(props.status ?? ''),
364
- };
365
- }
366
- }
367
- /**
368
- * Order-book market methods over the market-engine (Wave 2): price-time
369
- * priority matching with escrowed settlement. Deposits/withdrawals bridge
370
- * to the game's wallets via compute events the game layer consumes.
371
- *
372
- * Obtained via `client.kit(appId).economy.market`.
373
- */
374
- export class MarketKit {
375
- constructor(engines, moduleName) {
376
- this.engines = engines;
377
- this.moduleName = moduleName;
378
- }
379
- /** Is the market engine deployed + enabled (cached per session)? */
380
- engineAvailable() {
381
- if (!this.engines)
382
- return Promise.resolve(false);
383
- return this.engines.has(this.moduleName);
384
- }
385
- /** Move coins into your market account (escrow source for bids). */
386
- async depositCoins(amount) {
387
- return this.invoke('deposit_coins', { amount });
388
- }
389
- /** Move items into your market account (escrow source for asks). */
390
- async depositItems(item, quantity) {
391
- return this.invoke('deposit_items', { item, quantity });
392
- }
393
- /** Place a limit bid: locks coins at your limit; fills at maker price. */
394
- async bid(item, price, quantity) {
395
- return this.invoke('place', { item, side: 'buy', price, quantity });
396
- }
397
- /** Place a limit ask: locks items until filled or cancelled. */
398
- async ask(item, price, quantity) {
399
- return this.invoke('place', { item, side: 'sell', price, quantity });
400
- }
401
- /** Cancel a resting order (owner only); escrow refunds instantly. */
402
- async cancel(item, orderId) {
403
- return this.invoke('cancel', { item, orderId });
404
- }
405
- /** Book depth: best bids/asks as [price, quantity] levels. */
406
- async book(item) {
407
- return this.invoke('book', { item });
408
- }
409
- /** Your market account (settled + locked balances). */
410
- async account() {
411
- return this.invoke('account', {});
412
- }
413
- /** Withdraw settled balances back to the game layer. */
414
- async withdraw(input) {
415
- return this.invoke('withdraw', input);
416
- }
417
- async invoke(exportName, params) {
418
- if (!this.engines) {
419
- throw new Error('market engine unavailable: compute domain not wired');
420
- }
421
- const result = await this.engines.invoke(this.moduleName, exportName, params);
422
- if (!result.success) {
423
- throw new Error(`market.${exportName} failed: ${result.reason ?? 'unknown'}`);
424
- }
425
- return result.body;
426
- }
427
- }
@@ -1,48 +0,0 @@
1
- /**
2
- * Compute-engine capability detection + invoke envelope for the kit helpers.
3
- * Games deploy engines (mob-engine, world-engine, bwf-mobs, ...) as compute
4
- * modules; kit helpers probe once per module per session and route through
5
- * the engine when it is present, falling back to the model/automation path
6
- * when it is not — so the same client code works on model-only deployments.
7
- */
8
- import type { ComputeAPI } from '../domains/compute.js';
9
- /** The `{success, ...}` envelope engine invoke exports resolve with. */
10
- export interface EngineInvokeResult<T = Record<string, unknown>> {
11
- success: boolean;
12
- /** The engine's denial reason when `success` is false. */
13
- reason?: string;
14
- /** The parsed result body (includes any extra fields the export returns). */
15
- body: T & Record<string, unknown>;
16
- fuelUsed?: string;
17
- durationUs?: number;
18
- }
19
- /**
20
- * Per-session cached probe of which compute modules an app has enabled.
21
- * Obtained internally by kit helpers; share one via `kit.engines`.
22
- */
23
- export declare class EngineDetector {
24
- private readonly appId;
25
- private readonly compute;
26
- private readonly cache;
27
- constructor(appId: string, compute: ComputeAPI | undefined);
28
- /**
29
- * Is `moduleName` deployed + enabled? Cached per module for the client's
30
- * lifetime ({@link reset} to re-probe after deploys). Resolves false when
31
- * the client has no compute domain wired.
32
- */
33
- has(moduleName: string): Promise<boolean>;
34
- /** Drop cached probes (call after deploying/enabling modules). */
35
- reset(): void;
36
- /**
37
- * Invoke an engine export and parse the `{success, ...}` envelope.
38
- * Envelope failures (denials) resolve; every GraphQL-level error
39
- * (invoke-policy FORBIDDEN, the typed invoke-contract violation —
40
- * `BAD_REQUEST` "Invoke params violate ..." — a disabled module, ...) also
41
- * resolves as `{ success: false, reason }` so kit callers always get
42
- * gameplay-verdict semantics from compute invokes. Only non-GraphQL
43
- * (transport) errors throw.
44
- */
45
- invoke<T = Record<string, unknown>>(moduleName: string, exportName: string, params?: Record<string, unknown>): Promise<EngineInvokeResult<T>>;
46
- private probe;
47
- }
48
- //# sourceMappingURL=engine.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"engine.d.ts","sourceRoot":"","sources":["../../src/kit/engine.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AAExD,wEAAwE;AACxE,MAAM,WAAW,kBAAkB,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAC7D,OAAO,EAAE,OAAO,CAAC;IACjB,0DAA0D;IAC1D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,6EAA6E;IAC7E,IAAI,EAAE,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;GAGG;AACH,qBAAa,cAAc;IAIvB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAJ1B,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAuC;gBAG1C,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,UAAU,GAAG,SAAS;IAGlD;;;;OAIG;IACH,GAAG,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAUzC,kEAAkE;IAClE,KAAK,IAAI,IAAI;IAIb;;;;;;;;OAQG;IACG,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACtC,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,EAClB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC/B,OAAO,CAAC,kBAAkB,CAAC,CAAC,CAAC,CAAC;YAwCnB,KAAK;CAmBpB"}
@@ -1,113 +0,0 @@
1
- /**
2
- * Compute-engine capability detection + invoke envelope for the kit helpers.
3
- * Games deploy engines (mob-engine, world-engine, bwf-mobs, ...) as compute
4
- * modules; kit helpers probe once per module per session and route through
5
- * the engine when it is present, falling back to the model/automation path
6
- * when it is not — so the same client code works on model-only deployments.
7
- */
8
- import { CrowdyGraphQLError } from '../errors.js';
9
- /**
10
- * Per-session cached probe of which compute modules an app has enabled.
11
- * Obtained internally by kit helpers; share one via `kit.engines`.
12
- */
13
- export class EngineDetector {
14
- constructor(appId, compute) {
15
- this.appId = appId;
16
- this.compute = compute;
17
- this.cache = new Map();
18
- }
19
- /**
20
- * Is `moduleName` deployed + enabled? Cached per module for the client's
21
- * lifetime ({@link reset} to re-probe after deploys). Resolves false when
22
- * the client has no compute domain wired.
23
- */
24
- has(moduleName) {
25
- if (!this.compute)
26
- return Promise.resolve(false);
27
- let probe = this.cache.get(moduleName);
28
- if (!probe) {
29
- probe = this.probe(moduleName);
30
- this.cache.set(moduleName, probe);
31
- }
32
- return probe;
33
- }
34
- /** Drop cached probes (call after deploying/enabling modules). */
35
- reset() {
36
- this.cache.clear();
37
- }
38
- /**
39
- * Invoke an engine export and parse the `{success, ...}` envelope.
40
- * Envelope failures (denials) resolve; every GraphQL-level error
41
- * (invoke-policy FORBIDDEN, the typed invoke-contract violation —
42
- * `BAD_REQUEST` "Invoke params violate ..." — a disabled module, ...) also
43
- * resolves as `{ success: false, reason }` so kit callers always get
44
- * gameplay-verdict semantics from compute invokes. Only non-GraphQL
45
- * (transport) errors throw.
46
- */
47
- async invoke(moduleName, exportName, params) {
48
- if (!this.compute) {
49
- return {
50
- success: false,
51
- reason: 'compute domain unavailable',
52
- body: {},
53
- };
54
- }
55
- try {
56
- const result = await this.compute.invoke({
57
- appId: this.appId,
58
- moduleName,
59
- exportName,
60
- ...(params !== undefined ? { paramsJson: JSON.stringify(params) } : {}),
61
- });
62
- let body = {};
63
- try {
64
- body = JSON.parse(result.resultJson ?? '{}');
65
- }
66
- catch {
67
- body = {};
68
- }
69
- return {
70
- success: body.success !== false,
71
- reason: typeof body.reason === 'string' ? body.reason : undefined,
72
- body: body,
73
- fuelUsed: result.fuelUsed != null ? String(result.fuelUsed) : undefined,
74
- durationUs: result.durationUs != null ? Number(result.durationUs) : undefined,
75
- };
76
- }
77
- catch (error) {
78
- if (error instanceof CrowdyGraphQLError) {
79
- return {
80
- success: false,
81
- reason: error.message,
82
- body: {},
83
- };
84
- }
85
- throw error;
86
- }
87
- }
88
- async probe(moduleName) {
89
- if (!this.compute)
90
- return false;
91
- try {
92
- const module = await this.compute.module({ appId: this.appId, name: moduleName });
93
- return module != null && module.enabled === true;
94
- }
95
- catch (error) {
96
- if (!(error instanceof CrowdyGraphQLError))
97
- throw error;
98
- if (error.code !== 'FORBIDDEN')
99
- return false;
100
- }
101
- // Player tokens lack view_compute_diagnostics: probe via a status invoke
102
- // (engines all export one). Missing modules reject; denials mean present.
103
- try {
104
- const result = await this.invoke(moduleName, 'status');
105
- if (result.success)
106
- return true;
107
- return !/not found|no such module|not enabled/i.test(result.reason ?? '');
108
- }
109
- catch {
110
- return false;
111
- }
112
- }
113
- }
@@ -1,60 +0,0 @@
1
- import type { GameModelAPI } from '../domains/gameModel.js';
2
- import type { Scalars } from '../generated/graphql.js';
3
- import type { KitInvokePolicy } from './blueprints/index.js';
4
- /**
5
- * Runtime **monetization** helpers — the app feature/tier surface in shop
6
- * terms. Features are string keys (`'vip'`, `'land_owner'`, `'battle_pass'`)
7
- * defined per app and granted to **access tiers** (the management-side
8
- * `appAccess` tiers players buy/hold); any model function whose policy
9
- * carries a `tier_feature` leaf then admits only players on a granted tier.
10
- *
11
- * Gate blueprint functions by composing {@link gate} (=`featureGate`) into a
12
- * builder's `*policyExtra` option, e.g.
13
- * `plotBlueprint({ buyPolicyExtra: kit.features.gate('land_owner') })`.
14
- *
15
- * All methods require the app-admin `manage_apps` permission.
16
- *
17
- * Obtained via `client.kit(appId).features`.
18
- */
19
- export declare class FeaturesKit {
20
- private readonly appId;
21
- private readonly gameModel;
22
- constructor(appId: Scalars['BigInt']['input'], gameModel: GameModelAPI);
23
- /** Define (or re-describe) a feature key for the app. */
24
- define(featureKey: string, description?: string): Promise<{
25
- __typename?: "GmAppFeature";
26
- appId: string;
27
- featureKey: string;
28
- description: string | null;
29
- }>;
30
- /** List the app's defined feature keys. */
31
- list(): Promise<{
32
- __typename?: "GmAppFeature";
33
- appId: string;
34
- featureKey: string;
35
- description: string | null;
36
- }[]>;
37
- /** Grant a feature to an access tier (its holders pass `tier_feature` checks). */
38
- grantToTier(tierId: Scalars['BigInt']['input'], featureKey: string): Promise<{
39
- __typename?: "GmTierFeature";
40
- appId: string;
41
- tierId: string;
42
- featureKey: string;
43
- }>;
44
- /** Revoke a feature from an access tier. */
45
- revokeFromTier(tierId: Scalars['BigInt']['input'], featureKey: string): Promise<boolean>;
46
- /** List tier→feature grants (optionally for one tier). */
47
- tierFeatures(tierId?: Scalars['BigInt']['input']): Promise<{
48
- __typename?: "GmTierFeature";
49
- appId: string;
50
- tierId: string;
51
- featureKey: string;
52
- }[]>;
53
- /**
54
- * A `tier_feature` policy leaf for `feature` — pass it to any blueprint
55
- * builder's `*policyExtra` option to monetization-gate that function.
56
- * (Also exported standalone as `featureGate`.)
57
- */
58
- gate(feature: string): KitInvokePolicy;
59
- }
60
- //# sourceMappingURL=features.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"features.d.ts","sourceRoot":"","sources":["../../src/kit/features.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AAEvD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAE7D;;;;;;;;;;;;;;GAcG;AACH,qBAAa,WAAW;IAEpB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,SAAS;gBADT,KAAK,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EACjC,SAAS,EAAE,YAAY;IAG1C,yDAAyD;IACnD,MAAM,CAAC,UAAU,EAAE,MAAM,EAAE,WAAW,CAAC,EAAE,MAAM;;;;;;IAQrD,2CAA2C;IACrC,IAAI;;;;;;IAIV,kFAAkF;IAC5E,WAAW,CACf,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EAClC,UAAU,EAAE,MAAM;;;;;;IASpB,4CAA4C;IACtC,cAAc,CAClB,MAAM,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EAClC,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,OAAO,CAAC;IAQnB,0DAA0D;IACpD,YAAY,CAAC,MAAM,CAAC,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC;;;;;;IAOtD;;;;OAIG;IACH,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,eAAe;CAGvC"}