@omen.foundation/node-microservice-runtime 0.1.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/.env +13 -0
- package/dist/auth.cjs +97 -0
- package/dist/auth.d.ts +14 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +93 -0
- package/dist/auth.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +588 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/decorators.cjs +181 -0
- package/dist/decorators.d.ts +23 -0
- package/dist/decorators.d.ts.map +1 -0
- package/dist/decorators.js +155 -0
- package/dist/decorators.js.map +1 -0
- package/dist/dependency.cjs +165 -0
- package/dist/dependency.d.ts +56 -0
- package/dist/dependency.d.ts.map +1 -0
- package/dist/dependency.js +162 -0
- package/dist/dependency.js.map +1 -0
- package/dist/dev.cjs +34 -0
- package/dist/dev.d.ts +9 -0
- package/dist/dev.d.ts.map +1 -0
- package/dist/dev.js +32 -0
- package/dist/dev.js.map +1 -0
- package/dist/discovery.cjs +79 -0
- package/dist/discovery.d.ts +20 -0
- package/dist/discovery.d.ts.map +1 -0
- package/dist/discovery.js +75 -0
- package/dist/discovery.js.map +1 -0
- package/dist/docs.cjs +206 -0
- package/dist/docs.d.ts +30 -0
- package/dist/docs.d.ts.map +1 -0
- package/dist/docs.js +209 -0
- package/dist/docs.js.map +1 -0
- package/dist/env.cjs +106 -0
- package/dist/env.d.ts +4 -0
- package/dist/env.d.ts.map +1 -0
- package/dist/env.js +108 -0
- package/dist/env.js.map +1 -0
- package/dist/errors.cjs +58 -0
- package/dist/errors.d.ts +26 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +48 -0
- package/dist/errors.js.map +1 -0
- package/dist/federation.cjs +356 -0
- package/dist/federation.d.ts +108 -0
- package/dist/federation.d.ts.map +1 -0
- package/dist/federation.js +341 -0
- package/dist/federation.js.map +1 -0
- package/dist/index.cjs +42 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/inventory.cjs +361 -0
- package/dist/inventory.d.ts +116 -0
- package/dist/inventory.d.ts.map +1 -0
- package/dist/inventory.js +351 -0
- package/dist/inventory.js.map +1 -0
- package/dist/logger.cjs +62 -0
- package/dist/logger.d.ts +9 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +29 -0
- package/dist/logger.js.map +1 -0
- package/dist/message.cjs +19 -0
- package/dist/message.d.ts +5 -0
- package/dist/message.d.ts.map +1 -0
- package/dist/message.js +15 -0
- package/dist/message.js.map +1 -0
- package/dist/requester.cjs +100 -0
- package/dist/requester.d.ts +20 -0
- package/dist/requester.d.ts.map +1 -0
- package/dist/requester.js +99 -0
- package/dist/requester.js.map +1 -0
- package/dist/routing.cjs +39 -0
- package/dist/routing.d.ts +2 -0
- package/dist/routing.d.ts.map +1 -0
- package/dist/routing.js +36 -0
- package/dist/routing.js.map +1 -0
- package/dist/runtime.cjs +735 -0
- package/dist/runtime.d.ts +40 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +825 -0
- package/dist/runtime.js.map +1 -0
- package/dist/services.cjs +346 -0
- package/dist/services.d.ts +46 -0
- package/dist/services.d.ts.map +1 -0
- package/dist/services.js +343 -0
- package/dist/services.js.map +1 -0
- package/dist/storage.cjs +147 -0
- package/dist/storage.d.ts +46 -0
- package/dist/storage.d.ts.map +1 -0
- package/dist/storage.js +144 -0
- package/dist/storage.js.map +1 -0
- package/dist/types.cjs +2 -0
- package/dist/types.d.ts +108 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/urls.cjs +55 -0
- package/dist/utils/urls.d.ts +5 -0
- package/dist/utils/urls.d.ts.map +1 -0
- package/dist/utils/urls.js +50 -0
- package/dist/utils/urls.js.map +1 -0
- package/dist/websocket.cjs +142 -0
- package/dist/websocket.d.ts +33 -0
- package/dist/websocket.d.ts.map +1 -0
- package/dist/websocket.js +139 -0
- package/dist/websocket.js.map +1 -0
- package/env.sample +13 -0
- package/package.json +49 -0
- package/scripts/generate-openapi.mjs +114 -0
- package/scripts/lib/cli-utils.mjs +58 -0
- package/scripts/prepare-cjs.mjs +44 -0
- package/scripts/publish-service.mjs +1126 -0
- package/scripts/validate-service.mjs +103 -0
- package/scripts/ws-test.mjs +25 -0
- package/src/auth.ts +117 -0
- package/src/cli/index.ts +699 -0
- package/src/decorators.ts +207 -0
- package/src/dependency.ts +211 -0
- package/src/dev.ts +17 -0
- package/src/discovery.ts +88 -0
- package/src/docs.ts +262 -0
- package/src/env.ts +125 -0
- package/src/errors.ts +55 -0
- package/src/federation.ts +559 -0
- package/src/index.ts +51 -0
- package/src/inventory.ts +491 -0
- package/src/logger.ts +38 -0
- package/src/message.ts +19 -0
- package/src/requester.ts +126 -0
- package/src/routing.ts +42 -0
- package/src/runtime.ts +967 -0
- package/src/services.ts +459 -0
- package/src/storage.ts +206 -0
- package/src/types/beamable-sdk-api.d.ts +5 -0
- package/src/types.ts +117 -0
- package/src/utils/urls.ts +53 -0
- package/src/websocket.ts +170 -0
- package/tsconfig.base.json +31 -0
- package/tsconfig.build.json +10 -0
- package/tsconfig.cjs.json +16 -0
- package/tsconfig.dev.json +14 -0
|
@@ -0,0 +1,351 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
import { MissingScopesError } from './errors.js';
|
|
3
|
+
export class InventoryUpdateBuilder {
|
|
4
|
+
currencyChanges = new Map();
|
|
5
|
+
currencyPropertyUpdates = new Map();
|
|
6
|
+
newItemRequests = [];
|
|
7
|
+
deleteItemRequests = [];
|
|
8
|
+
updateItemRequests = [];
|
|
9
|
+
applyVipBonusFlag;
|
|
10
|
+
applyVipBonus(apply) {
|
|
11
|
+
this.applyVipBonusFlag = apply;
|
|
12
|
+
return this;
|
|
13
|
+
}
|
|
14
|
+
currencyChange(currencyId, delta) {
|
|
15
|
+
const normalizedId = this.normalizeId(currencyId, 'currency');
|
|
16
|
+
const current = this.currencyChanges.get(normalizedId) ?? BigInt(0);
|
|
17
|
+
const next = current + BigInt(delta);
|
|
18
|
+
if (next === BigInt(0)) {
|
|
19
|
+
this.currencyChanges.delete(normalizedId);
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
this.currencyChanges.set(normalizedId, next);
|
|
23
|
+
}
|
|
24
|
+
return this;
|
|
25
|
+
}
|
|
26
|
+
setCurrencyProperties(currencyId, properties) {
|
|
27
|
+
const normalizedId = this.normalizeId(currencyId, 'currency');
|
|
28
|
+
this.currencyPropertyUpdates.set(normalizedId, [...properties]);
|
|
29
|
+
return this;
|
|
30
|
+
}
|
|
31
|
+
addItem(contentId, properties = {}, requestId = randomUUID()) {
|
|
32
|
+
const normalizedId = this.normalizeId(contentId, 'item');
|
|
33
|
+
const itemProperties = Object.entries(properties).map(([name, value]) => ({
|
|
34
|
+
name,
|
|
35
|
+
value,
|
|
36
|
+
}));
|
|
37
|
+
this.newItemRequests.push({
|
|
38
|
+
contentId: normalizedId,
|
|
39
|
+
properties: itemProperties,
|
|
40
|
+
reqId: requestId,
|
|
41
|
+
});
|
|
42
|
+
return this;
|
|
43
|
+
}
|
|
44
|
+
deleteItem(contentId, itemId) {
|
|
45
|
+
const normalizedId = this.normalizeId(contentId, 'item');
|
|
46
|
+
this.deleteItemRequests.push({
|
|
47
|
+
contentId: normalizedId,
|
|
48
|
+
id: this.toIdentifier(itemId),
|
|
49
|
+
});
|
|
50
|
+
return this;
|
|
51
|
+
}
|
|
52
|
+
updateItem(contentId, itemId, properties) {
|
|
53
|
+
const normalizedId = this.normalizeId(contentId, 'item');
|
|
54
|
+
const normalizedProperties = Object.entries(properties).map(([name, value]) => ({
|
|
55
|
+
name,
|
|
56
|
+
value,
|
|
57
|
+
}));
|
|
58
|
+
this.updateItemRequests.push({
|
|
59
|
+
contentId: normalizedId,
|
|
60
|
+
id: this.toIdentifier(itemId),
|
|
61
|
+
properties: normalizedProperties,
|
|
62
|
+
});
|
|
63
|
+
return this;
|
|
64
|
+
}
|
|
65
|
+
merge(other) {
|
|
66
|
+
for (const [currencyId, delta] of other.currencyChanges.entries()) {
|
|
67
|
+
this.currencyChange(currencyId, delta);
|
|
68
|
+
}
|
|
69
|
+
for (const [currencyId, props] of other.currencyPropertyUpdates.entries()) {
|
|
70
|
+
this.currencyPropertyUpdates.set(currencyId, [...props]);
|
|
71
|
+
}
|
|
72
|
+
for (const item of other.newItemRequests) {
|
|
73
|
+
this.newItemRequests.push({ ...item });
|
|
74
|
+
}
|
|
75
|
+
for (const item of other.deleteItemRequests) {
|
|
76
|
+
this.deleteItemRequests.push({ ...item });
|
|
77
|
+
}
|
|
78
|
+
for (const item of other.updateItemRequests) {
|
|
79
|
+
this.updateItemRequests.push({
|
|
80
|
+
contentId: item.contentId,
|
|
81
|
+
id: this.toIdentifier(item.id),
|
|
82
|
+
properties: [...item.properties],
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
if (other.applyVipBonusFlag !== undefined) {
|
|
86
|
+
this.applyVipBonusFlag = other.applyVipBonusFlag;
|
|
87
|
+
}
|
|
88
|
+
return this;
|
|
89
|
+
}
|
|
90
|
+
isEmpty() {
|
|
91
|
+
return (this.currencyChanges.size === 0 &&
|
|
92
|
+
this.currencyPropertyUpdates.size === 0 &&
|
|
93
|
+
this.newItemRequests.length === 0 &&
|
|
94
|
+
this.deleteItemRequests.length === 0 &&
|
|
95
|
+
this.updateItemRequests.length === 0 &&
|
|
96
|
+
this.applyVipBonusFlag === undefined);
|
|
97
|
+
}
|
|
98
|
+
toRequest(options = {}) {
|
|
99
|
+
const payload = {};
|
|
100
|
+
if (options.transaction) {
|
|
101
|
+
payload.transaction = options.transaction;
|
|
102
|
+
}
|
|
103
|
+
if (this.applyVipBonusFlag !== undefined) {
|
|
104
|
+
payload.applyVipBonus = this.applyVipBonusFlag;
|
|
105
|
+
}
|
|
106
|
+
if (this.currencyChanges.size > 0) {
|
|
107
|
+
const currencies = {};
|
|
108
|
+
for (const [currencyId, delta] of this.currencyChanges.entries()) {
|
|
109
|
+
currencies[currencyId] = delta.toString();
|
|
110
|
+
}
|
|
111
|
+
payload.currencies = currencies;
|
|
112
|
+
}
|
|
113
|
+
if (this.currencyPropertyUpdates.size > 0) {
|
|
114
|
+
const currencyProperties = {};
|
|
115
|
+
for (const [currencyId, properties] of this.currencyPropertyUpdates.entries()) {
|
|
116
|
+
currencyProperties[currencyId] = properties.map((property) => ({ ...property }));
|
|
117
|
+
}
|
|
118
|
+
payload.currencyProperties = currencyProperties;
|
|
119
|
+
}
|
|
120
|
+
if (this.newItemRequests.length > 0) {
|
|
121
|
+
payload.newItems = this.newItemRequests.map((item) => ({
|
|
122
|
+
contentId: item.contentId,
|
|
123
|
+
properties: item.properties.map((property) => ({ ...property })),
|
|
124
|
+
reqId: item.reqId,
|
|
125
|
+
}));
|
|
126
|
+
}
|
|
127
|
+
if (this.deleteItemRequests.length > 0) {
|
|
128
|
+
payload.deleteItems = this.deleteItemRequests.map((item) => ({
|
|
129
|
+
contentId: item.contentId,
|
|
130
|
+
id: this.toIdentifier(item.id),
|
|
131
|
+
}));
|
|
132
|
+
}
|
|
133
|
+
if (this.updateItemRequests.length > 0) {
|
|
134
|
+
payload.updateItems = this.updateItemRequests.map((item) => ({
|
|
135
|
+
contentId: item.contentId,
|
|
136
|
+
id: this.toIdentifier(item.id),
|
|
137
|
+
properties: item.properties.map((property) => ({ ...property })),
|
|
138
|
+
}));
|
|
139
|
+
}
|
|
140
|
+
return payload;
|
|
141
|
+
}
|
|
142
|
+
normalizeId(value, kind) {
|
|
143
|
+
const trimmed = value.trim();
|
|
144
|
+
if (!trimmed) {
|
|
145
|
+
throw new Error(`Invalid ${kind} identifier: "${value}"`);
|
|
146
|
+
}
|
|
147
|
+
return trimmed;
|
|
148
|
+
}
|
|
149
|
+
toIdentifier(value) {
|
|
150
|
+
if (typeof value === 'bigint') {
|
|
151
|
+
return value.toString();
|
|
152
|
+
}
|
|
153
|
+
if (typeof value === 'number') {
|
|
154
|
+
if (!Number.isFinite(value)) {
|
|
155
|
+
throw new Error(`Invalid numeric identifier: ${value}`);
|
|
156
|
+
}
|
|
157
|
+
return Math.trunc(value).toString();
|
|
158
|
+
}
|
|
159
|
+
const trimmed = value.trim();
|
|
160
|
+
if (!trimmed) {
|
|
161
|
+
throw new Error('Identifier cannot be empty.');
|
|
162
|
+
}
|
|
163
|
+
return trimmed;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
export class InventoryService {
|
|
167
|
+
api;
|
|
168
|
+
logger;
|
|
169
|
+
userId;
|
|
170
|
+
ensureScopes;
|
|
171
|
+
constructor(dependencies) {
|
|
172
|
+
this.api = dependencies.api;
|
|
173
|
+
this.logger = dependencies.logger.child({ component: 'InventoryService' });
|
|
174
|
+
this.userId = dependencies.userId;
|
|
175
|
+
this.ensureScopes = dependencies.scopeChecker;
|
|
176
|
+
}
|
|
177
|
+
createBuilder() {
|
|
178
|
+
return new InventoryUpdateBuilder();
|
|
179
|
+
}
|
|
180
|
+
async update(builderOrCallback, options = {}) {
|
|
181
|
+
const builder = builderOrCallback instanceof InventoryUpdateBuilder ? builderOrCallback : this.createBuilder();
|
|
182
|
+
if (!(builderOrCallback instanceof InventoryUpdateBuilder)) {
|
|
183
|
+
await builderOrCallback(builder);
|
|
184
|
+
}
|
|
185
|
+
if (builder.isEmpty()) {
|
|
186
|
+
this.logger.debug('Inventory update skipped because builder produced no changes.');
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
this.ensureScopes(['server']);
|
|
190
|
+
const payload = builder.toRequest(options);
|
|
191
|
+
await this.invokeInventoryPut(payload);
|
|
192
|
+
}
|
|
193
|
+
async setCurrencies(currencyValues, transaction) {
|
|
194
|
+
this.ensureScopes(['server']);
|
|
195
|
+
const current = await this.getCurrencies(Object.keys(currencyValues));
|
|
196
|
+
const deltas = {};
|
|
197
|
+
for (const [currencyId, target] of Object.entries(currencyValues)) {
|
|
198
|
+
const currentVal = current[currencyId] ?? BigInt(0);
|
|
199
|
+
const targetValue = BigInt(target);
|
|
200
|
+
const delta = targetValue - currentVal;
|
|
201
|
+
if (delta !== BigInt(0)) {
|
|
202
|
+
deltas[currencyId] = delta;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
if (Object.keys(deltas).length === 0) {
|
|
206
|
+
this.logger.debug('No currency adjustments required; request skipped.');
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
await this.update((builder) => {
|
|
210
|
+
for (const [currencyId, delta] of Object.entries(deltas)) {
|
|
211
|
+
builder.currencyChange(currencyId, delta);
|
|
212
|
+
}
|
|
213
|
+
}, { transaction });
|
|
214
|
+
}
|
|
215
|
+
async addCurrencies(currencyDeltas, transaction) {
|
|
216
|
+
await this.update((builder) => {
|
|
217
|
+
for (const [currencyId, delta] of Object.entries(currencyDeltas)) {
|
|
218
|
+
builder.currencyChange(currencyId, delta);
|
|
219
|
+
}
|
|
220
|
+
}, { transaction });
|
|
221
|
+
}
|
|
222
|
+
async addItem(contentId, properties = {}, transaction) {
|
|
223
|
+
await this.update((builder) => {
|
|
224
|
+
builder.addItem(contentId, properties);
|
|
225
|
+
}, { transaction });
|
|
226
|
+
}
|
|
227
|
+
async deleteItem(contentId, itemId, transaction) {
|
|
228
|
+
await this.update((builder) => {
|
|
229
|
+
builder.deleteItem(contentId, itemId);
|
|
230
|
+
}, { transaction });
|
|
231
|
+
}
|
|
232
|
+
async updateItem(contentId, itemId, properties, transaction) {
|
|
233
|
+
await this.update((builder) => {
|
|
234
|
+
builder.updateItem(contentId, itemId, properties);
|
|
235
|
+
}, { transaction });
|
|
236
|
+
}
|
|
237
|
+
async setCurrencyProperties(currencyId, properties, transaction) {
|
|
238
|
+
await this.update((builder) => {
|
|
239
|
+
builder.setCurrencyProperties(currencyId, properties);
|
|
240
|
+
}, { transaction });
|
|
241
|
+
}
|
|
242
|
+
async previewCurrencyGain(currencyChanges) {
|
|
243
|
+
this.ensureScopes(['server']);
|
|
244
|
+
const payload = {
|
|
245
|
+
currencies: Object.fromEntries(Object.entries(currencyChanges).map(([currencyId, amount]) => [currencyId, BigInt(amount).toString()])),
|
|
246
|
+
};
|
|
247
|
+
const response = await this.invokePreview(payload);
|
|
248
|
+
return response;
|
|
249
|
+
}
|
|
250
|
+
async getMultipliers() {
|
|
251
|
+
this.ensureScopes(['server']);
|
|
252
|
+
const response = await this.invokeGetMultipliers();
|
|
253
|
+
return response;
|
|
254
|
+
}
|
|
255
|
+
async getInventory(scope) {
|
|
256
|
+
this.ensureScopes(['server']);
|
|
257
|
+
const response = await this.invokeGetInventory(scope);
|
|
258
|
+
return response;
|
|
259
|
+
}
|
|
260
|
+
async getCurrencies(currencyIds) {
|
|
261
|
+
const scope = Array.isArray(currencyIds) && currencyIds.length > 0 ? currencyIds.join(',') : 'currency';
|
|
262
|
+
const view = await this.getInventory(scope);
|
|
263
|
+
const result = {};
|
|
264
|
+
for (const currency of view.currencies ?? []) {
|
|
265
|
+
result[currency.id] = BigInt(currency.amount);
|
|
266
|
+
}
|
|
267
|
+
return result;
|
|
268
|
+
}
|
|
269
|
+
async sendCurrency(request) {
|
|
270
|
+
this.ensureScopes(['server']);
|
|
271
|
+
const payload = {
|
|
272
|
+
recipientPlayer: this.toIdentifier(request.recipientPlayer),
|
|
273
|
+
currencies: Object.fromEntries(Object.entries(request.currencies ?? {}).map(([currencyId, amount]) => [currencyId, BigInt(amount).toString()])),
|
|
274
|
+
transaction: request.transaction,
|
|
275
|
+
};
|
|
276
|
+
const response = this.api.inventoryPutTransferByObjectId?.(this.userId, payload);
|
|
277
|
+
if (!response || typeof response.then !== 'function') {
|
|
278
|
+
throw new Error('inventoryPutTransferByObjectId API is unavailable in the current SDK.');
|
|
279
|
+
}
|
|
280
|
+
await response;
|
|
281
|
+
}
|
|
282
|
+
async invokeInventoryPut(payload) {
|
|
283
|
+
const response = this.api.inventoryPutByObjectId?.(this.userId, payload);
|
|
284
|
+
if (!response || typeof response.then !== 'function') {
|
|
285
|
+
throw new Error('inventoryPutByObjectId API is unavailable in the current SDK.');
|
|
286
|
+
}
|
|
287
|
+
await response;
|
|
288
|
+
}
|
|
289
|
+
async invokePreview(payload) {
|
|
290
|
+
const response = this.api.inventoryPutPreviewByObjectId?.(this.userId, payload);
|
|
291
|
+
if (!response || typeof response.then !== 'function') {
|
|
292
|
+
throw new Error('inventoryPutPreviewByObjectId API is unavailable in the current SDK.');
|
|
293
|
+
}
|
|
294
|
+
const result = await response;
|
|
295
|
+
if (!result || typeof result !== 'object' || !('body' in result)) {
|
|
296
|
+
return result;
|
|
297
|
+
}
|
|
298
|
+
return result.body;
|
|
299
|
+
}
|
|
300
|
+
async invokeGetMultipliers() {
|
|
301
|
+
const response = this.api.inventoryGetMultipliersByObjectId?.(this.userId);
|
|
302
|
+
if (!response || typeof response.then !== 'function') {
|
|
303
|
+
throw new Error('inventoryGetMultipliersByObjectId API is unavailable in the current SDK.');
|
|
304
|
+
}
|
|
305
|
+
const result = await response;
|
|
306
|
+
if (!result || typeof result !== 'object' || !('body' in result)) {
|
|
307
|
+
return result;
|
|
308
|
+
}
|
|
309
|
+
return result.body;
|
|
310
|
+
}
|
|
311
|
+
async invokeGetInventory(scope) {
|
|
312
|
+
const response = this.api.inventoryGetByObjectId?.(this.userId, scope);
|
|
313
|
+
if (!response || typeof response.then !== 'function') {
|
|
314
|
+
throw new Error('inventoryGetByObjectId API is unavailable in the current SDK.');
|
|
315
|
+
}
|
|
316
|
+
const result = await response;
|
|
317
|
+
if (!result || typeof result !== 'object' || !('body' in result)) {
|
|
318
|
+
return result;
|
|
319
|
+
}
|
|
320
|
+
return result.body;
|
|
321
|
+
}
|
|
322
|
+
toIdentifier(value) {
|
|
323
|
+
if (typeof value === 'string') {
|
|
324
|
+
const trimmed = value.trim();
|
|
325
|
+
if (!trimmed) {
|
|
326
|
+
throw new Error('Identifier cannot be empty.');
|
|
327
|
+
}
|
|
328
|
+
return trimmed;
|
|
329
|
+
}
|
|
330
|
+
if (typeof value === 'number') {
|
|
331
|
+
if (!Number.isFinite(value)) {
|
|
332
|
+
throw new Error(`Invalid numeric identifier: ${value}`);
|
|
333
|
+
}
|
|
334
|
+
return Math.trunc(value).toString();
|
|
335
|
+
}
|
|
336
|
+
return value.toString();
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
export function createInventoryService(api, logger, userId, hasScopes) {
|
|
340
|
+
return new InventoryService({
|
|
341
|
+
api,
|
|
342
|
+
logger,
|
|
343
|
+
userId,
|
|
344
|
+
scopeChecker: (requiredScopes) => {
|
|
345
|
+
if (!hasScopes(requiredScopes)) {
|
|
346
|
+
throw new MissingScopesError(requiredScopes);
|
|
347
|
+
}
|
|
348
|
+
},
|
|
349
|
+
});
|
|
350
|
+
}
|
|
351
|
+
//# sourceMappingURL=inventory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inventory.js","sourceRoot":"","sources":["../src/inventory.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from 'node:crypto';\r\nimport type { Logger } from 'pino';\r\nimport type { BoundBeamApi } from './services.js';\r\nimport { MissingScopesError } from './errors.js';\r\n\r\nexport interface CurrencyProperty {\r\n name: string;\r\n value: string;\r\n}\r\n\r\ninterface ItemProperty {\r\n name: string;\r\n value: string;\r\n}\r\n\r\ninterface ItemCreateRequest {\r\n contentId: string;\r\n properties: ItemProperty[];\r\n reqId?: string;\r\n}\r\n\r\ninterface ItemDeleteRequest {\r\n contentId: string;\r\n id: string;\r\n}\r\n\r\ninterface ItemUpdateRequest {\r\n contentId: string;\r\n id: string;\r\n properties: ItemProperty[];\r\n}\r\n\r\ninterface CurrencyView {\r\n id: string;\r\n amount: string | number | bigint;\r\n}\r\n\r\nexport interface InventoryView {\r\n currencies?: CurrencyView[];\r\n}\r\n\r\nexport interface PreviewVipBonusResponse {\r\n currencies: Array<{ id: string; amount: string | number | bigint; originalAmount?: string | number | bigint }>;\r\n}\r\n\r\nexport interface MultipliersGetResponse {\r\n [key: string]: unknown;\r\n}\r\n\r\ninterface TransferRequestPayload {\r\n recipientPlayer: string;\r\n currencies?: Record<string, string>;\r\n transaction?: string;\r\n}\r\n\r\nexport interface InventoryUpdatePayload {\r\n transaction?: string;\r\n applyVipBonus?: boolean;\r\n currencies?: Record<string, string>;\r\n currencyProperties?: Record<string, CurrencyProperty[]>;\r\n newItems?: Array<ItemCreateRequest>;\r\n deleteItems?: Array<ItemDeleteRequest>;\r\n updateItems?: Array<ItemUpdateRequest>;\r\n}\r\n\r\nexport interface InventoryCurrencyChanges {\r\n [currencyId: string]: bigint;\r\n}\r\n\r\nexport interface InventoryBuilderOptions {\r\n transaction?: string;\r\n}\r\n\r\nexport class InventoryUpdateBuilder {\r\n private readonly currencyChanges: Map<string, bigint> = new Map();\r\n private readonly currencyPropertyUpdates: Map<string, CurrencyProperty[]> = new Map();\r\n private readonly newItemRequests: Array<ItemCreateRequest & { reqId: string }> = [];\r\n private readonly deleteItemRequests: ItemDeleteRequest[] = [];\r\n private readonly updateItemRequests: ItemUpdateRequest[] = [];\r\n private applyVipBonusFlag?: boolean;\r\n\r\n applyVipBonus(apply: boolean): this {\r\n this.applyVipBonusFlag = apply;\r\n return this;\r\n }\r\n\r\n currencyChange(currencyId: string, delta: bigint | number): this {\r\n const normalizedId = this.normalizeId(currencyId, 'currency');\r\n const current = this.currencyChanges.get(normalizedId) ?? BigInt(0);\r\n const next = current + BigInt(delta);\r\n if (next === BigInt(0)) {\r\n this.currencyChanges.delete(normalizedId);\r\n } else {\r\n this.currencyChanges.set(normalizedId, next);\r\n }\r\n return this;\r\n }\r\n\r\n setCurrencyProperties(currencyId: string, properties: CurrencyProperty[]): this {\r\n const normalizedId = this.normalizeId(currencyId, 'currency');\r\n this.currencyPropertyUpdates.set(normalizedId, [...properties]);\r\n return this;\r\n }\r\n\r\n addItem(contentId: string, properties: Record<string, string> = {}, requestId: string = randomUUID()): this {\r\n const normalizedId = this.normalizeId(contentId, 'item');\r\n const itemProperties = Object.entries(properties).map<ItemProperty>(([name, value]) => ({\r\n name,\r\n value,\r\n }));\r\n this.newItemRequests.push({\r\n contentId: normalizedId,\r\n properties: itemProperties,\r\n reqId: requestId,\r\n });\r\n return this;\r\n }\r\n\r\n deleteItem(contentId: string, itemId: bigint | number | string): this {\r\n const normalizedId = this.normalizeId(contentId, 'item');\r\n this.deleteItemRequests.push({\r\n contentId: normalizedId,\r\n id: this.toIdentifier(itemId),\r\n });\r\n return this;\r\n }\r\n\r\n updateItem(contentId: string, itemId: bigint | number | string, properties: Record<string, string>): this {\r\n const normalizedId = this.normalizeId(contentId, 'item');\r\n const normalizedProperties = Object.entries(properties).map<ItemProperty>(([name, value]) => ({\r\n name,\r\n value,\r\n }));\r\n this.updateItemRequests.push({\r\n contentId: normalizedId,\r\n id: this.toIdentifier(itemId),\r\n properties: normalizedProperties,\r\n });\r\n return this;\r\n }\r\n\r\n merge(other: InventoryUpdateBuilder): this {\r\n for (const [currencyId, delta] of other.currencyChanges.entries()) {\r\n this.currencyChange(currencyId, delta);\r\n }\r\n for (const [currencyId, props] of other.currencyPropertyUpdates.entries()) {\r\n this.currencyPropertyUpdates.set(currencyId, [...props]);\r\n }\r\n for (const item of other.newItemRequests) {\r\n this.newItemRequests.push({ ...item });\r\n }\r\n for (const item of other.deleteItemRequests) {\r\n this.deleteItemRequests.push({ ...item });\r\n }\r\n for (const item of other.updateItemRequests) {\r\n this.updateItemRequests.push({\r\n contentId: item.contentId,\r\n id: this.toIdentifier(item.id),\r\n properties: [...item.properties],\r\n });\r\n }\r\n if (other.applyVipBonusFlag !== undefined) {\r\n this.applyVipBonusFlag = other.applyVipBonusFlag;\r\n }\r\n return this;\r\n }\r\n\r\n isEmpty(): boolean {\r\n return (\r\n this.currencyChanges.size === 0 &&\r\n this.currencyPropertyUpdates.size === 0 &&\r\n this.newItemRequests.length === 0 &&\r\n this.deleteItemRequests.length === 0 &&\r\n this.updateItemRequests.length === 0 &&\r\n this.applyVipBonusFlag === undefined\r\n );\r\n }\r\n\r\n toRequest(options: InventoryBuilderOptions = {}): InventoryUpdatePayload {\r\n const payload: InventoryUpdatePayload = {};\r\n\r\n if (options.transaction) {\r\n payload.transaction = options.transaction;\r\n }\r\n if (this.applyVipBonusFlag !== undefined) {\r\n payload.applyVipBonus = this.applyVipBonusFlag;\r\n }\r\n if (this.currencyChanges.size > 0) {\r\n const currencies: Record<string, string> = {};\r\n for (const [currencyId, delta] of this.currencyChanges.entries()) {\r\n currencies[currencyId] = delta.toString();\r\n }\r\n payload.currencies = currencies;\r\n }\r\n if (this.currencyPropertyUpdates.size > 0) {\r\n const currencyProperties: Record<string, CurrencyProperty[]> = {};\r\n for (const [currencyId, properties] of this.currencyPropertyUpdates.entries()) {\r\n currencyProperties[currencyId] = properties.map<CurrencyProperty>((property) => ({ ...property }));\r\n }\r\n payload.currencyProperties = currencyProperties;\r\n }\r\n if (this.newItemRequests.length > 0) {\r\n payload.newItems = this.newItemRequests.map((item) => ({\r\n contentId: item.contentId,\r\n properties: item.properties.map<ItemProperty>((property) => ({ ...property })),\r\n reqId: item.reqId,\r\n }));\r\n }\r\n if (this.deleteItemRequests.length > 0) {\r\n payload.deleteItems = this.deleteItemRequests.map((item) => ({\r\n contentId: item.contentId,\r\n id: this.toIdentifier(item.id),\r\n }));\r\n }\r\n if (this.updateItemRequests.length > 0) {\r\n payload.updateItems = this.updateItemRequests.map((item) => ({\r\n contentId: item.contentId,\r\n id: this.toIdentifier(item.id),\r\n properties: item.properties.map<ItemProperty>((property) => ({ ...property })),\r\n }));\r\n }\r\n\r\n return payload;\r\n }\r\n\r\n private normalizeId(value: string, kind: 'currency' | 'item'): string {\r\n const trimmed = value.trim();\r\n if (!trimmed) {\r\n throw new Error(`Invalid ${kind} identifier: \"${value}\"`);\r\n }\r\n return trimmed;\r\n }\r\n\r\n private toIdentifier(value: bigint | number | string): string {\r\n if (typeof value === 'bigint') {\r\n return value.toString();\r\n }\r\n if (typeof value === 'number') {\r\n if (!Number.isFinite(value)) {\r\n throw new Error(`Invalid numeric identifier: ${value}`);\r\n }\r\n return Math.trunc(value).toString();\r\n }\r\n const trimmed = value.trim();\r\n if (!trimmed) {\r\n throw new Error('Identifier cannot be empty.');\r\n }\r\n return trimmed;\r\n }\r\n}\r\n\r\ninterface InventoryServiceDependencies {\r\n api: BoundBeamApi;\r\n logger: Logger;\r\n userId: string;\r\n scopeChecker: (scopes: string[]) => void;\r\n}\r\n\r\nexport class InventoryService {\r\n private readonly api: BoundBeamApi;\r\n private readonly logger: Logger;\r\n private readonly userId: string;\r\n private readonly ensureScopes: (scopes: string[]) => void;\r\n\r\n constructor(dependencies: InventoryServiceDependencies) {\r\n this.api = dependencies.api;\r\n this.logger = dependencies.logger.child({ component: 'InventoryService' });\r\n this.userId = dependencies.userId;\r\n this.ensureScopes = dependencies.scopeChecker;\r\n }\r\n\r\n createBuilder(): InventoryUpdateBuilder {\r\n return new InventoryUpdateBuilder();\r\n }\r\n\r\n async update(\r\n builderOrCallback: InventoryUpdateBuilder | ((builder: InventoryUpdateBuilder) => void | Promise<void>),\r\n options: InventoryBuilderOptions = {},\r\n ): Promise<void> {\r\n const builder = builderOrCallback instanceof InventoryUpdateBuilder ? builderOrCallback : this.createBuilder();\r\n if (!(builderOrCallback instanceof InventoryUpdateBuilder)) {\r\n await builderOrCallback(builder);\r\n }\r\n\r\n if (builder.isEmpty()) {\r\n this.logger.debug('Inventory update skipped because builder produced no changes.');\r\n return;\r\n }\r\n\r\n this.ensureScopes(['server']);\r\n const payload = builder.toRequest(options);\r\n await this.invokeInventoryPut(payload);\r\n }\r\n\r\n async setCurrencies(currencyValues: Record<string, bigint | number>, transaction?: string): Promise<void> {\r\n this.ensureScopes(['server']);\r\n const current = await this.getCurrencies(Object.keys(currencyValues));\r\n const deltas: Record<string, bigint> = {};\r\n for (const [currencyId, target] of Object.entries(currencyValues)) {\r\n const currentVal = current[currencyId] ?? BigInt(0);\r\n const targetValue = BigInt(target);\r\n const delta = targetValue - currentVal;\r\n if (delta !== BigInt(0)) {\r\n deltas[currencyId] = delta;\r\n }\r\n }\r\n\r\n if (Object.keys(deltas).length === 0) {\r\n this.logger.debug('No currency adjustments required; request skipped.');\r\n return;\r\n }\r\n\r\n await this.update((builder) => {\r\n for (const [currencyId, delta] of Object.entries(deltas)) {\r\n builder.currencyChange(currencyId, delta);\r\n }\r\n }, { transaction });\r\n }\r\n\r\n async addCurrencies(currencyDeltas: Record<string, bigint | number>, transaction?: string): Promise<void> {\r\n await this.update((builder) => {\r\n for (const [currencyId, delta] of Object.entries(currencyDeltas)) {\r\n builder.currencyChange(currencyId, delta);\r\n }\r\n }, { transaction });\r\n }\r\n\r\n async addItem(contentId: string, properties: Record<string, string> = {}, transaction?: string): Promise<void> {\r\n await this.update((builder) => {\r\n builder.addItem(contentId, properties);\r\n }, { transaction });\r\n }\r\n\r\n async deleteItem(contentId: string, itemId: bigint | number | string, transaction?: string): Promise<void> {\r\n await this.update((builder) => {\r\n builder.deleteItem(contentId, itemId);\r\n }, { transaction });\r\n }\r\n\r\n async updateItem(\r\n contentId: string,\r\n itemId: bigint | number | string,\r\n properties: Record<string, string>,\r\n transaction?: string,\r\n ): Promise<void> {\r\n await this.update((builder) => {\r\n builder.updateItem(contentId, itemId, properties);\r\n }, { transaction });\r\n }\r\n\r\n async setCurrencyProperties(\r\n currencyId: string,\r\n properties: CurrencyProperty[],\r\n transaction?: string,\r\n ): Promise<void> {\r\n await this.update((builder) => {\r\n builder.setCurrencyProperties(currencyId, properties);\r\n }, { transaction });\r\n }\r\n\r\n async previewCurrencyGain(currencyChanges: Record<string, bigint | number>): Promise<PreviewVipBonusResponse> {\r\n this.ensureScopes(['server']);\r\n const payload: InventoryUpdatePayload = {\r\n currencies: Object.fromEntries(\r\n Object.entries(currencyChanges).map(([currencyId, amount]) => [currencyId, BigInt(amount).toString()]),\r\n ),\r\n };\r\n const response = await this.invokePreview(payload);\r\n return response;\r\n }\r\n\r\n async getMultipliers(): Promise<MultipliersGetResponse> {\r\n this.ensureScopes(['server']);\r\n const response = await this.invokeGetMultipliers();\r\n return response;\r\n }\r\n\r\n async getInventory(scope?: string): Promise<InventoryView> {\r\n this.ensureScopes(['server']);\r\n const response = await this.invokeGetInventory(scope);\r\n return response;\r\n }\r\n\r\n async getCurrencies(currencyIds?: string[]): Promise<Record<string, bigint>> {\r\n const scope = Array.isArray(currencyIds) && currencyIds.length > 0 ? currencyIds.join(',') : 'currency';\r\n const view = await this.getInventory(scope);\r\n const result: Record<string, bigint> = {};\r\n for (const currency of view.currencies ?? []) {\r\n result[currency.id] = BigInt(currency.amount);\r\n }\r\n return result;\r\n }\r\n\r\n async sendCurrency(\r\n request: Omit<TransferRequestPayload, 'recipientPlayer'> & { recipientPlayer: string | number },\r\n ): Promise<void> {\r\n this.ensureScopes(['server']);\r\n const payload: TransferRequestPayload = {\r\n recipientPlayer: this.toIdentifier(request.recipientPlayer),\r\n currencies: Object.fromEntries(\r\n Object.entries(request.currencies ?? {}).map(([currencyId, amount]) => [currencyId, BigInt(amount).toString()]),\r\n ),\r\n transaction: request.transaction,\r\n };\r\n const response = this.api.inventoryPutTransferByObjectId?.(this.userId, payload);\r\n if (!response || typeof (response as Promise<unknown>).then !== 'function') {\r\n throw new Error('inventoryPutTransferByObjectId API is unavailable in the current SDK.');\r\n }\r\n await response;\r\n }\r\n\r\n private async invokeInventoryPut(payload: InventoryUpdatePayload): Promise<void> {\r\n const response = this.api.inventoryPutByObjectId?.(this.userId, payload);\r\n if (!response || typeof (response as Promise<unknown>).then !== 'function') {\r\n throw new Error('inventoryPutByObjectId API is unavailable in the current SDK.');\r\n }\r\n await response;\r\n }\r\n\r\n private async invokePreview(payload: InventoryUpdatePayload): Promise<PreviewVipBonusResponse> {\r\n const response = this.api.inventoryPutPreviewByObjectId?.(this.userId, payload);\r\n if (!response || typeof (response as Promise<unknown>).then !== 'function') {\r\n throw new Error('inventoryPutPreviewByObjectId API is unavailable in the current SDK.');\r\n }\r\n const result = await response;\r\n if (!result || typeof result !== 'object' || !('body' in result)) {\r\n return result as PreviewVipBonusResponse;\r\n }\r\n return (result as { body: PreviewVipBonusResponse }).body;\r\n }\r\n\r\n private async invokeGetMultipliers(): Promise<MultipliersGetResponse> {\r\n const response = this.api.inventoryGetMultipliersByObjectId?.(this.userId);\r\n if (!response || typeof (response as Promise<unknown>).then !== 'function') {\r\n throw new Error('inventoryGetMultipliersByObjectId API is unavailable in the current SDK.');\r\n }\r\n const result = await response;\r\n if (!result || typeof result !== 'object' || !('body' in result)) {\r\n return result as MultipliersGetResponse;\r\n }\r\n return (result as { body: MultipliersGetResponse }).body;\r\n }\r\n\r\n private async invokeGetInventory(scope?: string): Promise<InventoryView> {\r\n const response = this.api.inventoryGetByObjectId?.(this.userId, scope);\r\n if (!response || typeof (response as Promise<unknown>).then !== 'function') {\r\n throw new Error('inventoryGetByObjectId API is unavailable in the current SDK.');\r\n }\r\n const result = await response;\r\n if (!result || typeof result !== 'object' || !('body' in result)) {\r\n return result as InventoryView;\r\n }\r\n return (result as { body: InventoryView }).body;\r\n }\r\n\r\n private toIdentifier(value: string | number | bigint): string {\r\n if (typeof value === 'string') {\r\n const trimmed = value.trim();\r\n if (!trimmed) {\r\n throw new Error('Identifier cannot be empty.');\r\n }\r\n return trimmed;\r\n }\r\n if (typeof value === 'number') {\r\n if (!Number.isFinite(value)) {\r\n throw new Error(`Invalid numeric identifier: ${value}`);\r\n }\r\n return Math.trunc(value).toString();\r\n }\r\n return value.toString();\r\n }\r\n}\r\n\r\nexport function createInventoryService(\r\n api: BoundBeamApi,\r\n logger: Logger,\r\n userId: string,\r\n hasScopes: (scopes: string[]) => boolean,\r\n): InventoryService {\r\n return new InventoryService({\r\n api,\r\n logger,\r\n userId,\r\n scopeChecker: (requiredScopes: string[]) => {\r\n if (!hasScopes(requiredScopes)) {\r\n throw new MissingScopesError(requiredScopes);\r\n }\r\n },\r\n });\r\n}\r\n\r\n"]}
|
package/dist/logger.cjs
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.createLogger = createLogger;
|
|
37
|
+
const pino_1 = __importStar(require("pino"));
|
|
38
|
+
const env_js_1 = require("./env.js");
|
|
39
|
+
function createLogger(env, options = {}) {
|
|
40
|
+
var _a, _b, _c;
|
|
41
|
+
const configuredDestination = (_a = options.destinationPath) !== null && _a !== void 0 ? _a : process.env.LOG_PATH;
|
|
42
|
+
const pinoOptions = {
|
|
43
|
+
name: (_b = options.name) !== null && _b !== void 0 ? _b : 'beamable-node-runtime',
|
|
44
|
+
level: env.logLevel,
|
|
45
|
+
base: {
|
|
46
|
+
cid: env.cid,
|
|
47
|
+
pid: env.pid,
|
|
48
|
+
routingKey: (_c = env.routingKey) !== null && _c !== void 0 ? _c : null,
|
|
49
|
+
sdkVersionExecution: env.sdkVersionExecution,
|
|
50
|
+
},
|
|
51
|
+
redact: {
|
|
52
|
+
paths: ['secret', 'refreshToken'],
|
|
53
|
+
censor: '***',
|
|
54
|
+
},
|
|
55
|
+
};
|
|
56
|
+
if (!configuredDestination || configuredDestination === '-' || configuredDestination === 'stdout' || configuredDestination === 'console') {
|
|
57
|
+
return (0, pino_1.default)(pinoOptions, process.stdout);
|
|
58
|
+
}
|
|
59
|
+
const resolvedDestination = configuredDestination === 'temp' ? (0, env_js_1.ensureWritableTempDirectory)() : configuredDestination;
|
|
60
|
+
const stream = (0, pino_1.destination)({ dest: resolvedDestination, mkdir: true, append: true, sync: false });
|
|
61
|
+
return (0, pino_1.default)(pinoOptions, stream);
|
|
62
|
+
}
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type Logger } from 'pino';
|
|
2
|
+
import type { EnvironmentConfig } from './types.js';
|
|
3
|
+
interface LoggerFactoryOptions {
|
|
4
|
+
name?: string;
|
|
5
|
+
destinationPath?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function createLogger(env: EnvironmentConfig, options?: LoggerFactoryOptions): Logger;
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAa,EAAe,KAAK,MAAM,EAAsB,MAAM,MAAM,CAAC;AAE1E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEpD,UAAU,oBAAoB;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,YAAY,CAAC,GAAG,EAAE,iBAAiB,EAAE,OAAO,GAAE,oBAAyB,GAAG,MAAM,CA4B/F"}
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import pino, { destination } from 'pino';
|
|
2
|
+
import { ensureWritableTempDirectory } from './env.js';
|
|
3
|
+
export function createLogger(env, options = {}) {
|
|
4
|
+
const configuredDestination = options.destinationPath ?? process.env.LOG_PATH;
|
|
5
|
+
const pinoOptions = {
|
|
6
|
+
name: options.name ?? 'beamable-node-runtime',
|
|
7
|
+
level: env.logLevel,
|
|
8
|
+
base: {
|
|
9
|
+
cid: env.cid,
|
|
10
|
+
pid: env.pid,
|
|
11
|
+
routingKey: env.routingKey ?? null,
|
|
12
|
+
sdkVersionExecution: env.sdkVersionExecution,
|
|
13
|
+
},
|
|
14
|
+
redact: {
|
|
15
|
+
paths: ['secret', 'refreshToken'],
|
|
16
|
+
censor: '***',
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
// For deployed services, always log to stdout so container orchestrator can collect logs
|
|
20
|
+
// For local development, log to stdout unless a specific file path is provided
|
|
21
|
+
if (!configuredDestination || configuredDestination === '-' || configuredDestination === 'stdout' || configuredDestination === 'console') {
|
|
22
|
+
// Log to stdout (default pino behavior) - this is critical for container log collection
|
|
23
|
+
return pino(pinoOptions, process.stdout);
|
|
24
|
+
}
|
|
25
|
+
const resolvedDestination = configuredDestination === 'temp' ? ensureWritableTempDirectory() : configuredDestination;
|
|
26
|
+
const stream = destination({ dest: resolvedDestination, mkdir: true, append: true, sync: false });
|
|
27
|
+
return pino(pinoOptions, stream);
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,EAAE,EAAE,WAAW,EAAmC,MAAM,MAAM,CAAC;AAC1E,OAAO,EAAE,2BAA2B,EAAE,MAAM,UAAU,CAAC;AAQvD,MAAM,UAAU,YAAY,CAAC,GAAsB,EAAE,UAAgC,EAAE;IACrF,MAAM,qBAAqB,GAAG,OAAO,CAAC,eAAe,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC;IAE9E,MAAM,WAAW,GAAkB;QACjC,IAAI,EAAE,OAAO,CAAC,IAAI,IAAI,uBAAuB;QAC7C,KAAK,EAAE,GAAG,CAAC,QAAQ;QACnB,IAAI,EAAE;YACJ,GAAG,EAAE,GAAG,CAAC,GAAG;YACZ,GAAG,EAAE,GAAG,CAAC,GAAG;YACZ,UAAU,EAAE,GAAG,CAAC,UAAU,IAAI,IAAI;YAClC,mBAAmB,EAAE,GAAG,CAAC,mBAAmB;SAC7C;QACD,MAAM,EAAE;YACN,KAAK,EAAE,CAAC,QAAQ,EAAE,cAAc,CAAC;YACjC,MAAM,EAAE,KAAK;SACd;KACF,CAAC;IAEF,yFAAyF;IACzF,+EAA+E;IAC/E,IAAI,CAAC,qBAAqB,IAAI,qBAAqB,KAAK,GAAG,IAAI,qBAAqB,KAAK,QAAQ,IAAI,qBAAqB,KAAK,SAAS,EAAE,CAAC;QACzI,wFAAwF;QACxF,OAAO,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;IAC3C,CAAC;IAED,MAAM,mBAAmB,GAAG,qBAAqB,KAAK,MAAM,CAAC,CAAC,CAAC,2BAA2B,EAAE,CAAC,CAAC,CAAC,qBAAqB,CAAC;IACrH,MAAM,MAAM,GAAG,WAAW,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAClG,OAAO,IAAI,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;AACnC,CAAC","sourcesContent":["import pino, { destination, type Logger, type LoggerOptions } from 'pino';\r\nimport { ensureWritableTempDirectory } from './env.js';\r\nimport type { EnvironmentConfig } from './types.js';\r\n\r\ninterface LoggerFactoryOptions {\r\n name?: string;\r\n destinationPath?: string;\r\n}\r\n\r\nexport function createLogger(env: EnvironmentConfig, options: LoggerFactoryOptions = {}): Logger {\r\n const configuredDestination = options.destinationPath ?? process.env.LOG_PATH;\r\n\r\n const pinoOptions: LoggerOptions = {\r\n name: options.name ?? 'beamable-node-runtime',\r\n level: env.logLevel,\r\n base: {\r\n cid: env.cid,\r\n pid: env.pid,\r\n routingKey: env.routingKey ?? null,\r\n sdkVersionExecution: env.sdkVersionExecution,\r\n },\r\n redact: {\r\n paths: ['secret', 'refreshToken'],\r\n censor: '***',\r\n },\r\n };\r\n\r\n // For deployed services, always log to stdout so container orchestrator can collect logs\r\n // For local development, log to stdout unless a specific file path is provided\r\n if (!configuredDestination || configuredDestination === '-' || configuredDestination === 'stdout' || configuredDestination === 'console') {\r\n // Log to stdout (default pino behavior) - this is critical for container log collection\r\n return pino(pinoOptions, process.stdout);\r\n }\r\n\r\n const resolvedDestination = configuredDestination === 'temp' ? ensureWritableTempDirectory() : configuredDestination;\r\n const stream = destination({ dest: resolvedDestination, mkdir: true, append: true, sync: false });\r\n return pino(pinoOptions, stream);\r\n}\r\n"]}
|
package/dist/message.cjs
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.allocateRequestId = allocateRequestId;
|
|
4
|
+
exports.serializeGatewayRequest = serializeGatewayRequest;
|
|
5
|
+
exports.deserializeGatewayResponse = deserializeGatewayResponse;
|
|
6
|
+
let nextRequestId = -1;
|
|
7
|
+
function allocateRequestId() {
|
|
8
|
+
nextRequestId -= 1;
|
|
9
|
+
if (nextRequestId < -9000000000) {
|
|
10
|
+
nextRequestId = -1;
|
|
11
|
+
}
|
|
12
|
+
return nextRequestId;
|
|
13
|
+
}
|
|
14
|
+
function serializeGatewayRequest(request) {
|
|
15
|
+
return JSON.stringify(request);
|
|
16
|
+
}
|
|
17
|
+
function deserializeGatewayResponse(raw) {
|
|
18
|
+
return JSON.parse(raw);
|
|
19
|
+
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { GatewayRequest, GatewayResponse, WebsocketEventEnvelope } from './types.js';
|
|
2
|
+
export declare function allocateRequestId(): number;
|
|
3
|
+
export declare function serializeGatewayRequest(request: GatewayRequest): string;
|
|
4
|
+
export declare function deserializeGatewayResponse(raw: string): GatewayResponse | WebsocketEventEnvelope;
|
|
5
|
+
//# sourceMappingURL=message.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message.d.ts","sourceRoot":"","sources":["../src/message.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAI1F,wBAAgB,iBAAiB,IAAI,MAAM,CAM1C;AAED,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,cAAc,GAAG,MAAM,CAEvE;AAED,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,MAAM,GAAG,eAAe,GAAG,sBAAsB,CAEhG"}
|
package/dist/message.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
let nextRequestId = -1;
|
|
2
|
+
export function allocateRequestId() {
|
|
3
|
+
nextRequestId -= 1;
|
|
4
|
+
if (nextRequestId < -9_000_000_000) {
|
|
5
|
+
nextRequestId = -1;
|
|
6
|
+
}
|
|
7
|
+
return nextRequestId;
|
|
8
|
+
}
|
|
9
|
+
export function serializeGatewayRequest(request) {
|
|
10
|
+
return JSON.stringify(request);
|
|
11
|
+
}
|
|
12
|
+
export function deserializeGatewayResponse(raw) {
|
|
13
|
+
return JSON.parse(raw);
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=message.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message.js","sourceRoot":"","sources":["../src/message.ts"],"names":[],"mappings":"AAEA,IAAI,aAAa,GAAG,CAAC,CAAC,CAAC;AAEvB,MAAM,UAAU,iBAAiB;IAC/B,aAAa,IAAI,CAAC,CAAC;IACnB,IAAI,aAAa,GAAG,CAAC,aAAa,EAAE,CAAC;QACnC,aAAa,GAAG,CAAC,CAAC,CAAC;IACrB,CAAC;IACD,OAAO,aAAa,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,uBAAuB,CAAC,OAAuB;IAC7D,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,0BAA0B,CAAC,GAAW;IACpD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAA6C,CAAC;AACrE,CAAC","sourcesContent":["import type { GatewayRequest, GatewayResponse, WebsocketEventEnvelope } from './types.js';\r\n\r\nlet nextRequestId = -1;\r\n\r\nexport function allocateRequestId(): number {\r\n nextRequestId -= 1;\r\n if (nextRequestId < -9_000_000_000) {\r\n nextRequestId = -1;\r\n }\r\n return nextRequestId;\r\n}\r\n\r\nexport function serializeGatewayRequest(request: GatewayRequest): string {\r\n return JSON.stringify(request);\r\n}\r\n\r\nexport function deserializeGatewayResponse(raw: string): GatewayResponse | WebsocketEventEnvelope {\r\n return JSON.parse(raw) as GatewayResponse | WebsocketEventEnvelope;\r\n}\r\n"]}
|