@omen.foundation/node-microservice-runtime 0.1.76 → 0.1.78

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,356 @@
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
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.BeamableServiceManager = void 0;
40
+ const pino_1 = __importDefault(require("pino"));
41
+ const beamable_sdk_1 = require("beamable-sdk");
42
+ const urls_js_1 = require("./utils/urls.js");
43
+ const inventory_js_1 = require("./inventory.js");
44
+ const storage_js_1 = require("./storage.js");
45
+ const errors_js_1 = require("./errors.js");
46
+ const RUNTIME_ENVIRONMENT_NAME = 'node-runtime';
47
+ let cachedBeamApiModule = null;
48
+ async function resolveBeamApiModule() {
49
+ if (!cachedBeamApiModule) {
50
+ const imported = await Promise.resolve().then(() => __importStar(require('beamable-sdk/api')));
51
+ cachedBeamApiModule =
52
+ imported && typeof imported === 'object' && 'default' in imported
53
+ ? imported.default
54
+ : imported;
55
+ }
56
+ return cachedBeamApiModule;
57
+ }
58
+ async function bindBeamApi(requester) {
59
+ const module = await resolveBeamApiModule();
60
+ const bound = {};
61
+ for (const key of Object.keys(module)) {
62
+ const value = module[key];
63
+ if (typeof value === 'function') {
64
+ bound[key] = (...args) => value(requester, ...args);
65
+ }
66
+ }
67
+ return bound;
68
+ }
69
+ function createFailingApi(error) {
70
+ return new Proxy({}, {
71
+ get() {
72
+ throw error;
73
+ },
74
+ });
75
+ }
76
+ class UnavailableRequester {
77
+ constructor(error) {
78
+ this.error = error;
79
+ }
80
+ async request() {
81
+ throw this.error;
82
+ }
83
+ set baseUrl(_) {
84
+ }
85
+ set defaultHeaders(_) {
86
+ }
87
+ }
88
+ class UnavailableBeamableServices {
89
+ constructor(error) {
90
+ this.error = error;
91
+ this.requesterImpl = new UnavailableRequester(this.error);
92
+ this.apiBindings = createFailingApi(this.error);
93
+ }
94
+ fail() {
95
+ throw this.error;
96
+ }
97
+ get account() {
98
+ return this.fail();
99
+ }
100
+ get announcements() {
101
+ return this.fail();
102
+ }
103
+ get auth() {
104
+ return this.fail();
105
+ }
106
+ get content() {
107
+ return this.fail();
108
+ }
109
+ get leaderboards() {
110
+ return this.fail();
111
+ }
112
+ get stats() {
113
+ return this.fail();
114
+ }
115
+ get inventory() {
116
+ return this.fail();
117
+ }
118
+ get storage() {
119
+ return this.fail();
120
+ }
121
+ get federation() {
122
+ return this.fail();
123
+ }
124
+ get api() {
125
+ return this.apiBindings;
126
+ }
127
+ get requester() {
128
+ return this.requesterImpl;
129
+ }
130
+ hasScopes(..._scopes) {
131
+ return false;
132
+ }
133
+ requireScopes(...scopes) {
134
+ throw new errors_js_1.MissingScopesError(scopes);
135
+ }
136
+ assumeUser() {
137
+ return this;
138
+ }
139
+ getLogger() {
140
+ return (0, pino_1.default)({ name: 'beamable-unavailable', level: 'info' }, process.stdout);
141
+ }
142
+ }
143
+ class BeamableServicesFacade {
144
+ constructor(manager, beamServer, userId, scopes, serviceName) {
145
+ this.manager = manager;
146
+ this.beamServer = beamServer;
147
+ this.userId = userId;
148
+ this.cache = {};
149
+ this.apiBindings = this.manager.getBoundApi();
150
+ this.storageService = this.manager.getStorageService();
151
+ this.scopes = scopes;
152
+ this.serviceName = serviceName;
153
+ this.federationRegistry = serviceName ? this.manager.getFederationRegistry(serviceName) : undefined;
154
+ this.logger = this.manager.getLogger().child({ component: 'BeamableServicesFacade', service: serviceName });
155
+ }
156
+ getOrCreate(key, factory) {
157
+ if (!this.cache[key]) {
158
+ this.cache[key] = factory();
159
+ }
160
+ return this.cache[key];
161
+ }
162
+ get account() {
163
+ return this.getOrCreate('account', () => this.beamServer.account(this.userId));
164
+ }
165
+ get announcements() {
166
+ return this.getOrCreate('announcements', () => this.beamServer.announcements(this.userId));
167
+ }
168
+ get auth() {
169
+ return this.getOrCreate('auth', () => this.beamServer.auth(this.userId));
170
+ }
171
+ get content() {
172
+ return this.getOrCreate('content', () => this.beamServer.content(this.userId));
173
+ }
174
+ get leaderboards() {
175
+ return this.getOrCreate('leaderboards', () => this.beamServer.leaderboards(this.userId));
176
+ }
177
+ get stats() {
178
+ return this.getOrCreate('stats', () => this.beamServer.stats(this.userId));
179
+ }
180
+ get inventory() {
181
+ if (!this.inventoryClient) {
182
+ this.inventoryClient = (0, inventory_js_1.createInventoryService)(this.apiBindings, this.logger.child({ component: 'InventoryClient' }), this.userId, (requiredScopes) => this.hasScopes(...requiredScopes));
183
+ }
184
+ return this.inventoryClient;
185
+ }
186
+ get storage() {
187
+ return this.storageService;
188
+ }
189
+ get federation() {
190
+ if (!this.federationRegistry) {
191
+ throw new Error(this.serviceName
192
+ ? `Federation registry is not configured for service "${this.serviceName}".`
193
+ : 'Federation registry is not configured.');
194
+ }
195
+ return this.federationRegistry;
196
+ }
197
+ get api() {
198
+ return this.apiBindings;
199
+ }
200
+ get requester() {
201
+ return this.manager.getRequester();
202
+ }
203
+ hasScopes(...requiredScopes) {
204
+ if (requiredScopes.length === 0) {
205
+ return true;
206
+ }
207
+ return requiredScopes.every((scope) => this.scopeSetHas(scope));
208
+ }
209
+ requireScopes(...requiredScopes) {
210
+ if (!this.hasScopes(...requiredScopes)) {
211
+ throw new errors_js_1.MissingScopesError(requiredScopes);
212
+ }
213
+ }
214
+ assumeUser(userId) {
215
+ return this.manager.createFacade(String(userId), new Set(this.scopes), this.serviceName);
216
+ }
217
+ getLogger() {
218
+ return this.logger;
219
+ }
220
+ scopeSetHas(scope) {
221
+ const normalized = scope.trim().toLowerCase();
222
+ if (!normalized) {
223
+ return false;
224
+ }
225
+ return this.scopes.has('*') || this.scopes.has(normalized);
226
+ }
227
+ }
228
+ class BeamableServiceManager {
229
+ constructor(env, logger) {
230
+ var _a;
231
+ this.initialized = false;
232
+ this.federationRegistries = new Map();
233
+ this.env = env;
234
+ this.logger = logger.child({ component: 'BeamableServiceManager' });
235
+ this.tokenStorage = (0, beamable_sdk_1.defaultTokenStorage)({ pid: env.pid, tag: (_a = env.routingKey) !== null && _a !== void 0 ? _a : RUNTIME_ENVIRONMENT_NAME });
236
+ }
237
+ async initialize() {
238
+ if (this.initialized) {
239
+ return;
240
+ }
241
+ this.registerEnvironment();
242
+ this.configureSharedEnvironment();
243
+ if (this.env.refreshToken) {
244
+ await this.tokenStorage.setTokenData({ refreshToken: this.env.refreshToken });
245
+ }
246
+ const useSignedRequest = Boolean(this.env.secret);
247
+ if (!useSignedRequest && !this.env.refreshToken) {
248
+ this.logger.warn('Beamable realm secret and refresh token are both missing; Beamable SDK requests may fail due to missing credentials.');
249
+ }
250
+ try {
251
+ this.beamServer = await beamable_sdk_1.BeamServer.init({
252
+ cid: this.env.cid,
253
+ pid: this.env.pid,
254
+ environment: RUNTIME_ENVIRONMENT_NAME,
255
+ useSignedRequest,
256
+ tokenStorage: this.tokenStorage,
257
+ serverEvents: { enabled: false },
258
+ });
259
+ }
260
+ catch (error) {
261
+ this.logger.error({ err: error }, 'Failed to initialize Beamable SDK. Services layer will be unavailable.');
262
+ this.beamServer = undefined;
263
+ this.initialized = false;
264
+ return;
265
+ }
266
+ this.boundApi = await bindBeamApi(this.beamServer.requester);
267
+ this.storageService = new storage_js_1.StorageService({
268
+ requester: this.beamServer.requester,
269
+ api: this.boundApi,
270
+ env: this.env,
271
+ logger: this.logger.child({ component: 'StorageService' }),
272
+ });
273
+ this.registerDefaultServices();
274
+ this.initialized = true;
275
+ this.logger.debug('Beamable SDK services initialized.');
276
+ }
277
+ createFacade(userId, scopes, serviceName) {
278
+ if (!this.initialized || !this.beamServer || !this.boundApi || !this.storageService) {
279
+ return new UnavailableBeamableServices(new Error('Beamable services are not initialized.'));
280
+ }
281
+ if (serviceName && this.beamServer.requester) {
282
+ const fullRoutingKey = `micro_${serviceName}:${this.env.routingKey}`;
283
+ beamable_sdk_1.BeamServer.env.BEAM_ROUTING_KEY = fullRoutingKey;
284
+ const scopeHeader = `${this.env.cid}.${this.env.pid}`;
285
+ this.beamServer.requester.defaultHeaders = {
286
+ ...this.beamServer.requester.defaultHeaders,
287
+ 'X-BEAM-SCOPE': scopeHeader,
288
+ 'X-BEAM-SERVICE-ROUTING-KEY': fullRoutingKey,
289
+ };
290
+ }
291
+ return new BeamableServicesFacade(this, this.beamServer, String(userId), new Set(scopes), serviceName);
292
+ }
293
+ getRequester() {
294
+ if (!this.initialized || !this.beamServer) {
295
+ return new UnavailableRequester(new Error('Beamable services are not initialized.'));
296
+ }
297
+ return this.beamServer.requester;
298
+ }
299
+ getBoundApi() {
300
+ if (!this.boundApi) {
301
+ throw new Error('Beamable bound API is not available.');
302
+ }
303
+ return this.boundApi;
304
+ }
305
+ getStorageService() {
306
+ if (!this.storageService) {
307
+ throw new Error('Storage service is not initialized.');
308
+ }
309
+ return this.storageService;
310
+ }
311
+ getLogger() {
312
+ return this.logger;
313
+ }
314
+ registerFederationRegistry(serviceName, registry) {
315
+ this.federationRegistries.set(serviceName, registry);
316
+ }
317
+ getFederationRegistry(serviceName) {
318
+ return this.federationRegistries.get(serviceName);
319
+ }
320
+ registerEnvironment() {
321
+ const apiUrl = (0, urls_js_1.hostToHttpUrl)(this.env.host);
322
+ const portalUrl = (0, urls_js_1.hostToPortalUrl)(apiUrl);
323
+ const storageUrl = (0, urls_js_1.hostToStorageUrl)(apiUrl);
324
+ const registryUrl = (0, urls_js_1.hostToMicroserviceRegistryUrl)(apiUrl);
325
+ try {
326
+ beamable_sdk_1.BeamEnvironment.register(RUNTIME_ENVIRONMENT_NAME, {
327
+ apiUrl,
328
+ portalUrl,
329
+ beamMongoExpressUrl: storageUrl,
330
+ dockerRegistryUrl: `${registryUrl}/v2/`,
331
+ });
332
+ }
333
+ catch (error) {
334
+ this.logger.debug({ err: error }, 'Beamable environment was already registered. Reusing existing configuration.');
335
+ }
336
+ }
337
+ configureSharedEnvironment() {
338
+ var _a;
339
+ if (this.env.secret) {
340
+ beamable_sdk_1.BeamServer.env.BEAM_REALM_SECRET = this.env.secret;
341
+ }
342
+ beamable_sdk_1.BeamServer.env.BEAM_ROUTING_KEY = (_a = this.env.routingKey) !== null && _a !== void 0 ? _a : '';
343
+ }
344
+ registerDefaultServices() {
345
+ if (!this.beamServer) {
346
+ return;
347
+ }
348
+ this.beamServer.use(beamable_sdk_1.AccountService);
349
+ this.beamServer.use(beamable_sdk_1.AnnouncementsService);
350
+ this.beamServer.use(beamable_sdk_1.AuthService);
351
+ this.beamServer.use(beamable_sdk_1.ContentService);
352
+ this.beamServer.use(beamable_sdk_1.LeaderboardsService);
353
+ this.beamServer.use(beamable_sdk_1.StatsService);
354
+ }
355
+ }
356
+ exports.BeamableServiceManager = BeamableServiceManager;
@@ -0,0 +1,147 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.StorageService = void 0;
4
+ exports.StorageObject = StorageObject;
5
+ exports.getStorageMetadata = getStorageMetadata;
6
+ exports.listRegisteredStorageObjects = listRegisteredStorageObjects;
7
+ const mongodb_1 = require("mongodb");
8
+ const STORAGE_OBJECT_METADATA = new Map();
9
+ function StorageObject(storageName) {
10
+ if (!storageName || !storageName.trim()) {
11
+ throw new Error('@StorageObject requires a non-empty storage name.');
12
+ }
13
+ return (target) => {
14
+ STORAGE_OBJECT_METADATA.set(target, { storageName: storageName.trim() });
15
+ };
16
+ }
17
+ function getStorageMetadata(target) {
18
+ return STORAGE_OBJECT_METADATA.get(target);
19
+ }
20
+ function listRegisteredStorageObjects() {
21
+ return Array.from(STORAGE_OBJECT_METADATA.values());
22
+ }
23
+ const CONNECTION_STRING_ENV_PREFIX = 'STORAGE_CONNSTR_';
24
+ class StorageService {
25
+ constructor(dependencies) {
26
+ this.databaseCache = new Map();
27
+ this.clientCache = new Map();
28
+ this.requester = dependencies.requester;
29
+ this.api = dependencies.api;
30
+ this.env = dependencies.env;
31
+ this.logger = dependencies.logger.child({ component: 'StorageService' });
32
+ }
33
+ async getDatabase(storageName, options = {}) {
34
+ const normalized = this.normalizeStorageName(storageName);
35
+ if (!options.useCache) {
36
+ this.databaseCache.delete(normalized);
37
+ }
38
+ const cached = this.databaseCache.get(normalized);
39
+ if (cached) {
40
+ return cached;
41
+ }
42
+ const connectionString = await this.getConnectionString(normalized);
43
+ const client = await this.getMongoClient(connectionString);
44
+ const databaseName = this.buildDatabaseName(normalized);
45
+ const database = client.db(databaseName);
46
+ this.databaseCache.set(normalized, database);
47
+ return database;
48
+ }
49
+ async getDatabaseFor(storageCtor, options = {}) {
50
+ const metadata = getStorageMetadata(storageCtor);
51
+ if (!metadata) {
52
+ throw new Error(`Storage metadata for ${storageCtor.name} not found. Did you decorate the class with @StorageObject('Name')?`);
53
+ }
54
+ return this.getDatabase(metadata.storageName, options);
55
+ }
56
+ async getCollection(storageName, options = {}) {
57
+ var _a;
58
+ const database = await this.getDatabase(storageName, options);
59
+ const collectionName = (_a = options.collectionName) === null || _a === void 0 ? void 0 : _a.trim();
60
+ if (!collectionName) {
61
+ throw new Error('Collection name must be provided when using getCollection with raw storage name.');
62
+ }
63
+ return database.collection(collectionName);
64
+ }
65
+ async getCollectionFor(storageCtor, collectionCtor, options = {}) {
66
+ var _a, _b;
67
+ const metadata = getStorageMetadata(storageCtor);
68
+ if (!metadata) {
69
+ throw new Error(`Storage metadata for ${storageCtor.name} not found. Did you decorate the class with @StorageObject('Name')?`);
70
+ }
71
+ const collectionName = (_b = (_a = options.collectionName) === null || _a === void 0 ? void 0 : _a.trim()) !== null && _b !== void 0 ? _b : collectionCtor.name;
72
+ const database = await this.getDatabase(metadata.storageName, options);
73
+ return database.collection(collectionName);
74
+ }
75
+ async getMongoClient(connectionString) {
76
+ if (this.clientCache.has(connectionString)) {
77
+ return this.clientCache.get(connectionString);
78
+ }
79
+ const client = new mongodb_1.MongoClient(connectionString, {
80
+ maxPoolSize: 20,
81
+ });
82
+ await client.connect();
83
+ this.clientCache.set(connectionString, client);
84
+ return client;
85
+ }
86
+ async getConnectionString(storageName) {
87
+ const variableName = `${CONNECTION_STRING_ENV_PREFIX}${storageName}`;
88
+ const envValue = process.env[variableName];
89
+ if (envValue && envValue.trim()) {
90
+ return envValue.trim();
91
+ }
92
+ if (this.cachedConnectionString) {
93
+ return this.cachedConnectionString;
94
+ }
95
+ const response = await this.fetchConnectionString();
96
+ if (!response.connectionString || !response.connectionString.trim()) {
97
+ throw new Error(`Connection string for storage "${storageName}" is empty.`);
98
+ }
99
+ this.cachedConnectionString = response.connectionString.trim();
100
+ return this.cachedConnectionString;
101
+ }
102
+ async fetchConnectionString() {
103
+ if (typeof this.api.beamoGetStorageConnectionBasic === 'function') {
104
+ const result = await this.api.beamoGetStorageConnectionBasic();
105
+ if (result && typeof result === 'object' && 'body' in result) {
106
+ return result.body;
107
+ }
108
+ return result;
109
+ }
110
+ this.logger.warn('beamable-sdk does not expose beamoGetStorageConnectionBasic; falling back to manual requester call.');
111
+ const response = await this.requester.request({
112
+ method: 'GET',
113
+ url: '/basic/beamo/storage/connection',
114
+ withAuth: true,
115
+ });
116
+ const body = response.body;
117
+ if (!body || typeof body.connectionString !== 'string') {
118
+ throw new Error('Failed to retrieve Beamable storage connection string.');
119
+ }
120
+ return body;
121
+ }
122
+ buildDatabaseName(storageName) {
123
+ const cid = this.sanitize(this.env.cid);
124
+ const pid = this.sanitize(this.env.pid);
125
+ const storage = this.sanitize(storageName);
126
+ return `${cid}${pid}_${storage}`;
127
+ }
128
+ sanitize(value) {
129
+ return value.replace(/[^A-Za-z0-9_]/g, '_');
130
+ }
131
+ normalizeStorageName(storageName) {
132
+ const normalized = storageName.trim();
133
+ if (!normalized) {
134
+ throw new Error('Storage name cannot be empty.');
135
+ }
136
+ return normalized;
137
+ }
138
+ async dispose() {
139
+ for (const client of this.clientCache.values()) {
140
+ await client.close();
141
+ }
142
+ this.clientCache.clear();
143
+ this.databaseCache.clear();
144
+ this.cachedConnectionString = undefined;
145
+ }
146
+ }
147
+ exports.StorageService = StorageService;
package/dist/types.cjs ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
package/dist/types.d.ts CHANGED
@@ -70,6 +70,7 @@ export interface RequestContext {
70
70
  userId: number;
71
71
  payload?: unknown;
72
72
  body?: Record<string, unknown>;
73
+ query: Record<string, string | string[]>;
73
74
  scopes: Set<string>;
74
75
  headers: Record<string, string>;
75
76
  cid: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
package/dist/types.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { Logger } from 'pino';\r\nimport type { BeamableMicroserviceServices } from './services.js';\r\nimport type { DependencyScope } from './dependency.js';\r\n\r\nexport type ServiceAccess = 'public' | 'client' | 'server' | 'admin';\r\n\r\nexport interface MicroserviceOptions {\r\n /** When true, legacy serialization is enabled for every callable unless overridden per method. */\r\n useLegacySerialization?: boolean;\r\n /** When true the runtime will skip auto-registration for Beamable events. */\r\n disableAllBeamableEvents?: boolean;\r\n}\r\n\r\nexport interface CallableOptions {\r\n /** Optional explicit route name. Defaults to the method name. */\r\n route?: string;\r\n /** Whether an authenticated user is required for invocation. */\r\n requireAuth?: boolean;\r\n /** Scopes required for the invocation. */\r\n requiredScopes?: string[];\r\n /** Override legacy serialization behaviour for this callable. */\r\n useLegacySerialization?: boolean;\r\n access?: ServiceAccess;\r\n /** Optional OpenAPI/Swagger tags to apply to the callable. */\r\n tags?: string[];\r\n}\r\n\r\nexport interface EnvironmentConfig {\r\n cid: string;\r\n pid: string;\r\n host: string;\r\n secret?: string;\r\n refreshToken?: string;\r\n routingKey?: string; // undefined for deployed services (becomes None in Scala)\r\n accountId?: number;\r\n accountEmail?: string;\r\n logLevel: string;\r\n healthPort: number;\r\n disableCustomInitializationHooks: boolean;\r\n watchToken: boolean;\r\n sdkVersionExecution: string;\r\n beamInstanceCount: number;\r\n logTruncateLimit: number;\r\n}\r\n\r\nexport interface GatewayRequest {\r\n id: number;\r\n method: string;\r\n path: string;\r\n from?: number;\r\n body?: unknown;\r\n scopes?: string[];\r\n headers?: Record<string, string>;\r\n}\r\n\r\nexport interface GatewayResponse<T = unknown> {\r\n id: number;\r\n status: number;\r\n body: T;\r\n}\r\n\r\nexport interface WebsocketEventEnvelope {\r\n id: number;\r\n status: number;\r\n path?: string;\r\n method?: string;\r\n body?: unknown;\r\n from?: number;\r\n scopes?: string[];\r\n headers?: Record<string, string>;\r\n}\r\n\r\nexport interface RequestContext {\r\n id: number;\r\n path: string;\r\n method: string;\r\n status: number;\r\n userId: number;\r\n payload?: unknown;\r\n body?: Record<string, unknown>;\r\n scopes: Set<string>;\r\n headers: Record<string, string>;\r\n cid: string;\r\n pid: string;\r\n services: BeamableMicroserviceServices;\r\n throwIfCancelled(): void;\r\n isCancelled(): boolean;\r\n hasScopes(...scopes: string[]): boolean;\r\n requireScopes(...scopes: string[]): void;\r\n provider: DependencyScope;\r\n}\r\n\r\nexport interface ServiceCallableMetadata {\r\n route: string;\r\n displayName: string;\r\n requireAuth: boolean;\r\n requiredScopes: string[];\r\n useLegacySerialization: boolean;\r\n parameterTypes: ReadonlyArray<unknown>;\r\n access: ServiceAccess;\r\n tags: string[];\r\n}\r\n\r\nexport interface ServiceDefinition {\r\n name: string;\r\n qualifiedName: string;\r\n ctor: new (...args: unknown[]) => unknown;\r\n callables: Map<string, ServiceCallableMetadata>;\r\n options?: MicroserviceOptions;\r\n}\r\n\r\nexport interface RuntimeComponents {\r\n env: EnvironmentConfig;\r\n logger: Logger;\r\n}\r\n\r\nexport type JsonValue = string | number | boolean | null | JsonValue[] | { [key: string]: JsonValue };\r\n"]}
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"","sourcesContent":["import type { Logger } from 'pino';\r\nimport type { BeamableMicroserviceServices } from './services.js';\r\nimport type { DependencyScope } from './dependency.js';\r\n\r\nexport type ServiceAccess = 'public' | 'client' | 'server' | 'admin';\r\n\r\nexport interface MicroserviceOptions {\r\n /** When true, legacy serialization is enabled for every callable unless overridden per method. */\r\n useLegacySerialization?: boolean;\r\n /** When true the runtime will skip auto-registration for Beamable events. */\r\n disableAllBeamableEvents?: boolean;\r\n}\r\n\r\nexport interface CallableOptions {\r\n /** Optional explicit route name. Defaults to the method name. */\r\n route?: string;\r\n /** Whether an authenticated user is required for invocation. */\r\n requireAuth?: boolean;\r\n /** Scopes required for the invocation. */\r\n requiredScopes?: string[];\r\n /** Override legacy serialization behaviour for this callable. */\r\n useLegacySerialization?: boolean;\r\n access?: ServiceAccess;\r\n /** Optional OpenAPI/Swagger tags to apply to the callable. */\r\n tags?: string[];\r\n}\r\n\r\nexport interface EnvironmentConfig {\r\n cid: string;\r\n pid: string;\r\n host: string;\r\n secret?: string;\r\n refreshToken?: string;\r\n routingKey?: string; // undefined for deployed services (becomes None in Scala)\r\n accountId?: number;\r\n accountEmail?: string;\r\n logLevel: string;\r\n healthPort: number;\r\n disableCustomInitializationHooks: boolean;\r\n watchToken: boolean;\r\n sdkVersionExecution: string;\r\n beamInstanceCount: number;\r\n logTruncateLimit: number;\r\n}\r\n\r\nexport interface GatewayRequest {\r\n id: number;\r\n method: string;\r\n path: string;\r\n from?: number;\r\n body?: unknown;\r\n scopes?: string[];\r\n headers?: Record<string, string>;\r\n}\r\n\r\nexport interface GatewayResponse<T = unknown> {\r\n id: number;\r\n status: number;\r\n body: T;\r\n}\r\n\r\nexport interface WebsocketEventEnvelope {\r\n id: number;\r\n status: number;\r\n path?: string;\r\n method?: string;\r\n body?: unknown;\r\n from?: number;\r\n scopes?: string[];\r\n headers?: Record<string, string>;\r\n}\r\n\r\nexport interface RequestContext {\r\n id: number;\r\n path: string;\r\n method: string;\r\n status: number;\r\n userId: number;\r\n payload?: unknown;\r\n body?: Record<string, unknown>;\r\n query: Record<string, string | string[]>;\r\n scopes: Set<string>;\r\n headers: Record<string, string>;\r\n cid: string;\r\n pid: string;\r\n services: BeamableMicroserviceServices;\r\n throwIfCancelled(): void;\r\n isCancelled(): boolean;\r\n hasScopes(...scopes: string[]): boolean;\r\n requireScopes(...scopes: string[]): void;\r\n provider: DependencyScope;\r\n}\r\n\r\nexport interface ServiceCallableMetadata {\r\n route: string;\r\n displayName: string;\r\n requireAuth: boolean;\r\n requiredScopes: string[];\r\n useLegacySerialization: boolean;\r\n parameterTypes: ReadonlyArray<unknown>;\r\n access: ServiceAccess;\r\n tags: string[];\r\n}\r\n\r\nexport interface ServiceDefinition {\r\n name: string;\r\n qualifiedName: string;\r\n ctor: new (...args: unknown[]) => unknown;\r\n callables: Map<string, ServiceCallableMetadata>;\r\n options?: MicroserviceOptions;\r\n}\r\n\r\nexport interface RuntimeComponents {\r\n env: EnvironmentConfig;\r\n logger: Logger;\r\n}\r\n\r\nexport type JsonValue = string | number | boolean | null | JsonValue[] | { [key: string]: JsonValue };\r\n"]}
@@ -0,0 +1,55 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.hostToHttpUrl = hostToHttpUrl;
4
+ exports.hostToPortalUrl = hostToPortalUrl;
5
+ exports.hostToStorageUrl = hostToStorageUrl;
6
+ exports.hostToMicroserviceRegistryUrl = hostToMicroserviceRegistryUrl;
7
+ function hostToHttpUrl(host) {
8
+ const normalized = host.replace(/\/$/, '');
9
+ if (normalized.startsWith('wss://')) {
10
+ return `https://${normalized.substring('wss://'.length).replace(/\/socket$/, '')}`;
11
+ }
12
+ if (normalized.startsWith('ws://')) {
13
+ return `http://${normalized.substring('ws://'.length).replace(/\/socket$/, '')}`;
14
+ }
15
+ return normalized.replace(/\/socket$/, '');
16
+ }
17
+ function transformApiHostname(hostname, replacement) {
18
+ let host = hostname;
19
+ if (host.startsWith('dev.')) {
20
+ host = host.replace('dev.', 'dev-');
21
+ }
22
+ if (host.startsWith('api.')) {
23
+ return host.replace('api.', `${replacement}.`);
24
+ }
25
+ if (host.startsWith('api-')) {
26
+ return host.replace('api-', `${replacement}-`);
27
+ }
28
+ const index = host.indexOf('api');
29
+ if (index >= 0) {
30
+ return `${host.slice(0, index)}${replacement}${host.slice(index + 3)}`;
31
+ }
32
+ return host;
33
+ }
34
+ function transformHost(httpHost, replacement) {
35
+ try {
36
+ const url = new URL(httpHost);
37
+ url.hostname = transformApiHostname(url.hostname, replacement);
38
+ url.pathname = '/';
39
+ url.search = '';
40
+ url.hash = '';
41
+ return url.toString().replace(/\/$/, '');
42
+ }
43
+ catch (error) {
44
+ return transformApiHostname(httpHost, replacement);
45
+ }
46
+ }
47
+ function hostToPortalUrl(httpHost) {
48
+ return transformHost(httpHost, 'portal');
49
+ }
50
+ function hostToStorageUrl(httpHost) {
51
+ return transformHost(httpHost, 'storage');
52
+ }
53
+ function hostToMicroserviceRegistryUrl(httpHost) {
54
+ return transformHost(httpHost, 'microservices');
55
+ }