@omen.foundation/node-microservice-runtime 0.1.34 → 0.1.35

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.
@@ -1,399 +0,0 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.fetchClickHouseCredentials = fetchClickHouseCredentials;
7
- exports.getClickHouseCredentialsStatus = getClickHouseCredentialsStatus;
8
- exports.isCollectorRunning = isCollectorRunning;
9
- exports.addAuthEnvironmentVars = addAuthEnvironmentVars;
10
- exports.startCollector = startCollector;
11
- exports.getCollectorProcessStatus = getCollectorProcessStatus;
12
- exports.discoverOrStartCollector = discoverOrStartCollector;
13
- const child_process_1 = require("child_process");
14
- const fs_1 = require("fs");
15
- const path_1 = require("path");
16
- const promises_1 = require("stream/promises");
17
- const zlib_1 = require("zlib");
18
- const node_crypto_1 = require("node:crypto");
19
- const dgram_1 = __importDefault(require("dgram"));
20
- const urls_js_1 = require("./utils/urls.js");
21
- const COLLECTOR_VERSION = '1.0.1';
22
- const COLLECTOR_DOWNLOAD_BASE = `https://collectors.beamable.com/version/${COLLECTOR_VERSION}`;
23
- const DISCOVERY_PORT = parseInt(process.env.BEAM_COLLECTOR_DISCOVERY_PORT || '8688', 10);
24
- let globalCollectorProcess = null;
25
- let globalCollectorStartError = null;
26
- let globalCollectorExitCode = null;
27
- let globalCollectorStderr = [];
28
- let globalCollectorInitError = null;
29
- const DISCOVERY_DELAY = 100;
30
- const DISCOVERY_ATTEMPTS = 10;
31
- function calculateSignature(pid, secret, uriPathAndQuery, body = null, version = '1') {
32
- let dataToSign = `${secret}${pid}${version}${uriPathAndQuery}`;
33
- if (body) {
34
- dataToSign += body;
35
- }
36
- const hash = (0, node_crypto_1.createHash)('md5').update(dataToSign, 'utf8').digest('base64');
37
- return hash;
38
- }
39
- function getPathAndQuery(url) {
40
- try {
41
- const urlObj = new URL(url);
42
- return urlObj.pathname + urlObj.search;
43
- }
44
- catch {
45
- return url;
46
- }
47
- }
48
- async function fetchClickHouseCredentials(env) {
49
- const apiUrl = (0, urls_js_1.hostToHttpUrl)(env.host);
50
- const uriPath = '/api/beamo/otel/auth/writer/config';
51
- const configUrl = new URL(uriPath, apiUrl).toString();
52
- const secret = process.env.SECRET;
53
- if (!secret) {
54
- throw new Error('SECRET environment variable is required to fetch ClickHouse credentials');
55
- }
56
- const pathAndQuery = getPathAndQuery(uriPath);
57
- const signature = calculateSignature(env.pid, secret, pathAndQuery, null, '1');
58
- const headers = {
59
- 'Content-Type': 'application/json',
60
- Accept: 'application/json',
61
- 'X-BEAM-SCOPE': `${env.cid}.${env.pid}`,
62
- 'X-BEAM-SIGNATURE': signature,
63
- };
64
- const response = await fetch(configUrl, {
65
- method: 'GET',
66
- headers,
67
- });
68
- if (!response.ok) {
69
- const errorText = await response.text().catch(() => 'Unknown error');
70
- throw new Error(`Failed to fetch ClickHouse credentials from ${configUrl}: ${response.status} ${response.statusText} - ${errorText.substring(0, 200)}`);
71
- }
72
- const credentials = await response.json();
73
- if (!credentials.endpoint || !credentials.username || !credentials.password) {
74
- throw new Error('Invalid ClickHouse credentials response: missing required fields');
75
- }
76
- return credentials;
77
- }
78
- function getCollectorStoragePath() {
79
- const tempDir = process.env.TMPDIR || process.env.TMP || '/tmp';
80
- return (0, path_1.join)(tempDir, 'beam', 'collectors', COLLECTOR_VERSION);
81
- }
82
- function getCollectorBinaryName() {
83
- const platform = process.platform;
84
- const arch = process.arch;
85
- if (platform === 'linux' && arch === 'x64') {
86
- return 'collector-linux-amd64';
87
- }
88
- else if (platform === 'linux' && arch === 'arm64') {
89
- return 'collector-linux-arm64';
90
- }
91
- else if (platform === 'darwin' && arch === 'x64') {
92
- return 'collector-darwin-amd64';
93
- }
94
- else if (platform === 'darwin' && arch === 'arm64') {
95
- return 'collector-darwin-arm64';
96
- }
97
- else if (platform === 'win32' && arch === 'x64') {
98
- return 'collector-windows-amd64.exe';
99
- }
100
- throw new Error(`Unsupported platform: ${platform} ${arch}`);
101
- }
102
- async function downloadAndDecompressGzip(url, outputPath, makeExecutable = false) {
103
- let response;
104
- try {
105
- response = await fetch(url);
106
- }
107
- catch (error) {
108
- const errorMsg = error instanceof Error ? error.message : String(error);
109
- throw new Error(`Network error downloading ${url}: ${errorMsg}`);
110
- }
111
- if (!response.ok) {
112
- const errorText = await response.text().catch(() => '');
113
- throw new Error(`HTTP ${response.status} downloading ${url}: ${response.statusText}${errorText ? ` - ${errorText.substring(0, 200)}` : ''}`);
114
- }
115
- const dir = (0, path_1.dirname)(outputPath);
116
- if (!(0, fs_1.existsSync)(dir)) {
117
- (0, fs_1.mkdirSync)(dir, { recursive: true });
118
- }
119
- const gunzip = (0, zlib_1.createGunzip)();
120
- const writeStream = (0, fs_1.createWriteStream)(outputPath);
121
- await (0, promises_1.pipeline)(response.body, gunzip, writeStream);
122
- if (makeExecutable && process.platform !== 'win32') {
123
- try {
124
- (0, fs_1.chmodSync)(outputPath, 0o755);
125
- }
126
- catch (error) {
127
- console.error(`Failed to make ${outputPath} executable:`, error);
128
- }
129
- }
130
- }
131
- async function resolveCollector(allowDownload = true, logger) {
132
- const basePath = getCollectorStoragePath();
133
- const binaryName = getCollectorBinaryName();
134
- const configName = 'clickhouse-config.yaml';
135
- const binaryPath = (0, path_1.join)(basePath, binaryName);
136
- const configPath = (0, path_1.join)(basePath, configName);
137
- const itemsToDownload = [];
138
- if (!(0, fs_1.existsSync)(binaryPath) && allowDownload) {
139
- const binaryUrl = `${COLLECTOR_DOWNLOAD_BASE}/${binaryName}.gz`;
140
- itemsToDownload.push({ url: binaryUrl, path: binaryPath, executable: true });
141
- logger === null || logger === void 0 ? void 0 : logger.info(`[Collector] Will download binary from: ${binaryUrl}`);
142
- }
143
- else if ((0, fs_1.existsSync)(binaryPath)) {
144
- logger === null || logger === void 0 ? void 0 : logger.info(`[Collector] Binary found at: ${binaryPath}`);
145
- }
146
- if (!(0, fs_1.existsSync)(configPath) && allowDownload) {
147
- const configUrl = `${COLLECTOR_DOWNLOAD_BASE}/${configName}.gz`;
148
- itemsToDownload.push({ url: configUrl, path: configPath, executable: false });
149
- logger === null || logger === void 0 ? void 0 : logger.info(`[Collector] Will download config from: ${configUrl}`);
150
- }
151
- else if ((0, fs_1.existsSync)(configPath)) {
152
- logger === null || logger === void 0 ? void 0 : logger.info(`[Collector] Config found at: ${configPath}`);
153
- }
154
- for (const item of itemsToDownload) {
155
- try {
156
- logger === null || logger === void 0 ? void 0 : logger.info(`[Collector] Downloading ${item.url}...`);
157
- await downloadAndDecompressGzip(item.url, item.path, item.executable);
158
- logger === null || logger === void 0 ? void 0 : logger.info(`[Collector] Downloaded to ${item.path}`);
159
- }
160
- catch (error) {
161
- const errorMsg = error instanceof Error ? error.message : String(error);
162
- logger === null || logger === void 0 ? void 0 : logger.error(`[Collector] Failed to download ${item.url}: ${errorMsg}`);
163
- throw new Error(`Failed to download collector ${item.executable ? 'binary' : 'config'} from ${item.url}: ${errorMsg}`);
164
- }
165
- }
166
- return {
167
- binaryPath: (0, fs_1.existsSync)(binaryPath) ? binaryPath : null,
168
- configPath: (0, fs_1.existsSync)(configPath) ? configPath : null,
169
- };
170
- }
171
- function discoverCollectorViaUDP(timeoutMs = 5000) {
172
- return new Promise((resolve) => {
173
- const socket = dgram_1.default.createSocket('udp4');
174
- const discovered = [];
175
- let timeout;
176
- socket.on('message', (msg) => {
177
- try {
178
- const message = JSON.parse(msg.toString());
179
- if (message.version === COLLECTOR_VERSION && message.status === 'READY') {
180
- discovered.push(message);
181
- }
182
- }
183
- catch (error) {
184
- }
185
- });
186
- socket.on('error', () => {
187
- clearTimeout(timeout);
188
- socket.close();
189
- resolve(null);
190
- });
191
- socket.bind(() => {
192
- socket.setBroadcast(true);
193
- timeout = setTimeout(() => {
194
- socket.close();
195
- resolve(discovered.length > 0 ? discovered[0] : null);
196
- }, timeoutMs);
197
- });
198
- });
199
- }
200
- function getClickHouseCredentialsStatus() {
201
- const hasEndpoint = !!process.env.BEAM_CLICKHOUSE_ENDPOINT;
202
- const hasUsername = !!process.env.BEAM_CLICKHOUSE_USERNAME;
203
- const hasPassword = !!process.env.BEAM_CLICKHOUSE_PASSWORD;
204
- if (hasEndpoint && hasUsername && hasPassword) {
205
- return {
206
- hasEndpoint: true,
207
- hasUsername: true,
208
- hasPassword: true,
209
- source: 'environment',
210
- };
211
- }
212
- return {
213
- hasEndpoint,
214
- hasUsername,
215
- hasPassword,
216
- source: 'missing',
217
- };
218
- }
219
- async function isCollectorRunning() {
220
- try {
221
- const discovered = await discoverCollectorViaUDP(2000);
222
- if (discovered) {
223
- return {
224
- isRunning: true,
225
- isReady: discovered.status === 'READY',
226
- pid: discovered.pid,
227
- otlpEndpoint: discovered.otlpEndpoint,
228
- version: discovered.version,
229
- };
230
- }
231
- }
232
- catch (error) {
233
- }
234
- return {
235
- isRunning: false,
236
- isReady: false,
237
- pid: 0,
238
- };
239
- }
240
- function addCollectorConfigurationToEnvironment() {
241
- const defaults = {
242
- BEAM_CLICKHOUSE_PROCESSOR_TIMEOUT: '5s',
243
- BEAM_CLICKHOUSE_PROCESSOR_BATCH_SIZE: '5000',
244
- BEAM_CLICKHOUSE_EXPORTER_TIMEOUT: '5s',
245
- BEAM_CLICKHOUSE_EXPORTER_QUEUE_SIZE: '1000',
246
- BEAM_CLICKHOUSE_EXPORTER_RETRY_ENABLED: 'true',
247
- BEAM_CLICKHOUSE_EXPORTER_RETRY_INITIAL_INTERVAL: '5s',
248
- BEAM_CLICKHOUSE_EXPORTER_RETRY_MAX_INTERVAL: '30s',
249
- BEAM_CLICKHOUSE_EXPORTER_RETRY_MAX_ELAPSED_TIME: '300s',
250
- };
251
- for (const [key, defaultValue] of Object.entries(defaults)) {
252
- if (!process.env[key]) {
253
- process.env[key] = defaultValue;
254
- }
255
- }
256
- }
257
- function addAuthEnvironmentVars(endpoint, username, password) {
258
- process.env.BEAM_CLICKHOUSE_ENDPOINT = endpoint;
259
- process.env.BEAM_CLICKHOUSE_USERNAME = username;
260
- process.env.BEAM_CLICKHOUSE_PASSWORD = password;
261
- if (!process.env.BEAM_CLICKHOUSE_ENDPOINT || !process.env.BEAM_CLICKHOUSE_USERNAME || !process.env.BEAM_CLICKHOUSE_PASSWORD) {
262
- throw new Error(`Failed to set ClickHouse credentials in process.env - this should never happen in Node.js`);
263
- }
264
- }
265
- async function startCollector(logger, otlpEndpoint, env) {
266
- var _a, _b;
267
- globalCollectorStartError = null;
268
- globalCollectorInitError = null;
269
- let clickhouseEndpoint = process.env.BEAM_CLICKHOUSE_ENDPOINT;
270
- let clickhouseUsername = process.env.BEAM_CLICKHOUSE_USERNAME;
271
- let clickhousePassword = process.env.BEAM_CLICKHOUSE_PASSWORD;
272
- if ((!clickhouseEndpoint || !clickhouseUsername || !clickhousePassword) && env) {
273
- try {
274
- logger.info('[Collector] Fetching ClickHouse credentials from Beamable API...');
275
- const credentials = await fetchClickHouseCredentials(env);
276
- clickhouseEndpoint = credentials.endpoint;
277
- clickhouseUsername = credentials.username;
278
- clickhousePassword = credentials.password;
279
- addAuthEnvironmentVars(clickhouseEndpoint, clickhouseUsername, clickhousePassword);
280
- const verifyEndpoint = process.env.BEAM_CLICKHOUSE_ENDPOINT;
281
- const verifyUsername = process.env.BEAM_CLICKHOUSE_USERNAME;
282
- const verifyPassword = process.env.BEAM_CLICKHOUSE_PASSWORD;
283
- if (!verifyEndpoint || !verifyUsername || !verifyPassword) {
284
- logger.error(`[Collector] CRITICAL: Credentials were set but are missing from process.env! This should never happen.`);
285
- throw new Error('Failed to persist ClickHouse credentials in process.env');
286
- }
287
- logger.info('[Collector] ClickHouse credentials fetched from API and verified in process.env');
288
- }
289
- catch (error) {
290
- const errorMsg = `[Collector] Failed to fetch ClickHouse credentials from API: ${error instanceof Error ? error.message : String(error)}`;
291
- logger.error(errorMsg);
292
- throw new Error(errorMsg);
293
- }
294
- }
295
- if (!clickhouseEndpoint || !clickhouseUsername || !clickhousePassword) {
296
- const errorMsg = `[Collector] Required ClickHouse credentials are missing. Set BEAM_CLICKHOUSE_ENDPOINT, BEAM_CLICKHOUSE_USERNAME, and BEAM_CLICKHOUSE_PASSWORD, or ensure the API endpoint is accessible.`;
297
- logger.error(errorMsg);
298
- throw new Error(errorMsg);
299
- }
300
- logger.info('[Collector] Resolving collector binary and config...');
301
- const collectorInfo = await resolveCollector(true, logger);
302
- if (!collectorInfo.binaryPath) {
303
- logger.error('[Collector] Binary not found and download failed');
304
- throw new Error('Collector binary not found and download failed');
305
- }
306
- if (!collectorInfo.configPath) {
307
- logger.error('[Collector] Config not found and download failed');
308
- throw new Error('Collector config not found and download failed');
309
- }
310
- logger.info(`[Collector] Using binary: ${collectorInfo.binaryPath}`);
311
- logger.info(`[Collector] Using config: ${collectorInfo.configPath}`);
312
- addCollectorConfigurationToEnvironment();
313
- let localEndpoint = otlpEndpoint;
314
- if (!localEndpoint) {
315
- localEndpoint = '0.0.0.0:4318';
316
- }
317
- localEndpoint = localEndpoint.replace(/^http:\/\//, '').replace(/^https:\/\//, '');
318
- const collectorEnv = {
319
- ...process.env,
320
- BEAM_OTLP_HTTP_ENDPOINT: localEndpoint,
321
- BEAM_COLLECTOR_DISCOVERY_PORT: String(DISCOVERY_PORT),
322
- };
323
- const collectorProcess = (0, child_process_1.spawn)(collectorInfo.binaryPath, ['--config', collectorInfo.configPath], {
324
- env: collectorEnv,
325
- stdio: ['ignore', 'pipe', 'pipe'],
326
- detached: false,
327
- });
328
- globalCollectorProcess = collectorProcess;
329
- globalCollectorStartError = null;
330
- globalCollectorExitCode = null;
331
- globalCollectorStderr = [];
332
- (_a = collectorProcess.stdout) === null || _a === void 0 ? void 0 : _a.on('data', (data) => {
333
- logger.debug(`[Collector] ${data.toString().trim()}`);
334
- });
335
- (_b = collectorProcess.stderr) === null || _b === void 0 ? void 0 : _b.on('data', (data) => {
336
- const errorLine = data.toString().trim();
337
- globalCollectorStderr.push(errorLine);
338
- if (globalCollectorStderr.length > 50) {
339
- globalCollectorStderr.shift();
340
- }
341
- logger.debug(`[Collector ERR] ${errorLine}`);
342
- });
343
- collectorProcess.on('error', (err) => {
344
- globalCollectorStartError = err.message;
345
- logger.error(`[Collector] Failed to start: ${err.message}`);
346
- });
347
- collectorProcess.on('exit', (code) => {
348
- globalCollectorExitCode = code;
349
- globalCollectorProcess = null;
350
- logger.warn(`[Collector] Process exited with code ${code}`);
351
- });
352
- logger.info(`[Collector] Started with PID ${collectorProcess.pid}, endpoint: ${localEndpoint}`);
353
- return {
354
- process: collectorProcess,
355
- endpoint: `http://${localEndpoint}`,
356
- };
357
- }
358
- function getCollectorProcessStatus() {
359
- var _a;
360
- return {
361
- hasProcess: globalCollectorProcess !== null,
362
- pid: (_a = globalCollectorProcess === null || globalCollectorProcess === void 0 ? void 0 : globalCollectorProcess.pid) !== null && _a !== void 0 ? _a : null,
363
- exitCode: globalCollectorExitCode,
364
- startError: globalCollectorStartError,
365
- initError: globalCollectorInitError,
366
- stderr: [...globalCollectorStderr],
367
- };
368
- }
369
- async function discoverOrStartCollector(logger, standardOtelEnabled, env) {
370
- if (!standardOtelEnabled) {
371
- return null;
372
- }
373
- const status = await isCollectorRunning();
374
- if (status.isRunning && status.isReady && status.otlpEndpoint) {
375
- logger.info(`[Collector] Found running collector at ${status.otlpEndpoint}`);
376
- return `http://${status.otlpEndpoint}`;
377
- }
378
- try {
379
- globalCollectorInitError = null;
380
- logger.info('[Collector] Starting OpenTelemetry collector...');
381
- const { endpoint } = await startCollector(logger, undefined, env);
382
- for (let i = 0; i < DISCOVERY_ATTEMPTS; i++) {
383
- await new Promise(resolve => setTimeout(resolve, DISCOVERY_DELAY));
384
- const newStatus = await isCollectorRunning();
385
- if (newStatus.isRunning && newStatus.isReady) {
386
- logger.info(`[Collector] Collector is ready at ${newStatus.otlpEndpoint || endpoint}`);
387
- return newStatus.otlpEndpoint ? `http://${newStatus.otlpEndpoint}` : endpoint;
388
- }
389
- }
390
- logger.warn('[Collector] Collector started but not yet ready, using configured endpoint');
391
- return endpoint;
392
- }
393
- catch (err) {
394
- const errorMsg = err instanceof Error ? err.message : String(err);
395
- globalCollectorInitError = errorMsg;
396
- logger.error(`[Collector] Failed to start collector: ${errorMsg}`);
397
- return null;
398
- }
399
- }
@@ -1,181 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Microservice = Microservice;
4
- exports.Callable = Callable;
5
- exports.listRegisteredServices = listRegisteredServices;
6
- exports.getServiceOptions = getServiceOptions;
7
- exports.ClientCallable = ClientCallable;
8
- exports.ServerCallable = ServerCallable;
9
- exports.AdminCallable = AdminCallable;
10
- exports.SwaggerCategory = SwaggerCategory;
11
- exports.SwaggerTags = SwaggerTags;
12
- exports.configureServices = configureServices;
13
- exports.initializeServices = initializeServices;
14
- exports.ConfigureServices = ConfigureServices;
15
- exports.InitializeServices = InitializeServices;
16
- exports.getConfigureServicesHandlers = getConfigureServicesHandlers;
17
- exports.getInitializeServicesHandlers = getInitializeServicesHandlers;
18
- require("reflect-metadata");
19
- const SERVICE_METADATA = new Map();
20
- const PENDING_REGISTRATIONS = new Map();
21
- const SWAGGER_TAGS_METADATA_KEY = Symbol('beamable:swaggerTags');
22
- const CONFIGURE_SERVICES_METADATA = new Map();
23
- const INITIALIZE_SERVICES_METADATA = new Map();
24
- function Microservice(name, options = {}) {
25
- if (!name || !/^[A-Za-z0-9_]+$/.test(name)) {
26
- throw new Error(`Invalid microservice name "${name}". Only alphanumeric and underscore characters are allowed.`);
27
- }
28
- return function decorator(ctor) {
29
- const qualifiedName = `micro_${name}`;
30
- const entry = {
31
- name,
32
- qualifiedName,
33
- ctor,
34
- callables: new Map(),
35
- options,
36
- };
37
- SERVICE_METADATA.set(ctor, entry);
38
- const pending = PENDING_REGISTRATIONS.get(ctor);
39
- if (pending) {
40
- pending.forEach((fn) => fn(entry));
41
- PENDING_REGISTRATIONS.delete(ctor);
42
- }
43
- };
44
- }
45
- function Callable(options = {}) {
46
- return function decorator(target, propertyKey, _descriptor) {
47
- var _a;
48
- let ctorCandidate;
49
- if (typeof target === 'function') {
50
- ctorCandidate = target;
51
- }
52
- else if (target !== null && typeof target === 'object') {
53
- const obj = target;
54
- ctorCandidate = obj.constructor;
55
- }
56
- if (typeof ctorCandidate !== 'function') {
57
- throw new Error('@Callable can only be applied to methods on a class.');
58
- }
59
- const ctor = ctorCandidate;
60
- const metadataTarget = typeof target === 'function'
61
- ? target
62
- : target !== null && typeof target === 'object'
63
- ? target
64
- : undefined;
65
- if (!metadataTarget) {
66
- throw new Error('@Callable decorator received an invalid target.');
67
- }
68
- const meta = SERVICE_METADATA.get(ctor);
69
- if (!meta) {
70
- const queue = (_a = PENDING_REGISTRATIONS.get(ctor)) !== null && _a !== void 0 ? _a : [];
71
- queue.push((lateMeta) => registerCallable(lateMeta, propertyKey, options, metadataTarget));
72
- PENDING_REGISTRATIONS.set(ctor, queue);
73
- return;
74
- }
75
- registerCallable(meta, propertyKey, options, metadataTarget);
76
- };
77
- }
78
- function registerCallable(meta, propertyKey, options, metadataTarget) {
79
- var _a, _b, _c, _d, _e, _f, _g, _h;
80
- const access = (_a = options.access) !== null && _a !== void 0 ? _a : 'public';
81
- const paramTypes = Reflect.getMetadata('design:paramtypes', metadataTarget, propertyKey);
82
- const route = (_b = options.route) !== null && _b !== void 0 ? _b : propertyKey;
83
- const decoratorTags = (_c = Reflect.getMetadata(SWAGGER_TAGS_METADATA_KEY, metadataTarget, propertyKey)) !== null && _c !== void 0 ? _c : [];
84
- const combinedTags = (_d = options.tags) !== null && _d !== void 0 ? _d : decoratorTags;
85
- const tags = Array.from(new Set(combinedTags !== null && combinedTags !== void 0 ? combinedTags : []));
86
- const metadata = {
87
- route,
88
- displayName: propertyKey,
89
- requireAuth: (_e = options.requireAuth) !== null && _e !== void 0 ? _e : access !== 'public',
90
- requiredScopes: (_f = options.requiredScopes) !== null && _f !== void 0 ? _f : defaultScopesForAccess(access),
91
- useLegacySerialization: (_h = (_g = options.useLegacySerialization) !== null && _g !== void 0 ? _g : meta.options.useLegacySerialization) !== null && _h !== void 0 ? _h : false,
92
- parameterTypes: paramTypes !== null && paramTypes !== void 0 ? paramTypes : [],
93
- access,
94
- tags,
95
- };
96
- const key = route.toLowerCase();
97
- if (meta.callables.has(key)) {
98
- throw new Error(`Duplicate callable route "${route}" on ${meta.ctor.name}.`);
99
- }
100
- meta.callables.set(key, metadata);
101
- }
102
- function defaultScopesForAccess(access) {
103
- switch (access) {
104
- case 'admin':
105
- return ['admin'];
106
- case 'server':
107
- return ['server'];
108
- default:
109
- return [];
110
- }
111
- }
112
- function listRegisteredServices() {
113
- return Array.from(SERVICE_METADATA.values()).map((entry) => ({
114
- name: entry.name,
115
- qualifiedName: entry.qualifiedName,
116
- ctor: entry.ctor,
117
- callables: new Map(entry.callables),
118
- options: entry.options,
119
- }));
120
- }
121
- function getServiceOptions(ctor) {
122
- var _a;
123
- return (_a = SERVICE_METADATA.get(ctor)) === null || _a === void 0 ? void 0 : _a.options;
124
- }
125
- function ClientCallable(options = {}) {
126
- return Callable({ ...options, access: 'client', requireAuth: true });
127
- }
128
- function ServerCallable(options = {}) {
129
- return Callable({ ...options, access: 'server', requireAuth: true });
130
- }
131
- function AdminCallable(options = {}) {
132
- return Callable({ ...options, access: 'admin', requireAuth: true });
133
- }
134
- function SwaggerCategory(category) {
135
- return SwaggerTags(category);
136
- }
137
- function SwaggerTags(...tags) {
138
- return function decorator(target, propertyKey, _descriptor) {
139
- var _a;
140
- if (tags.length === 0) {
141
- return;
142
- }
143
- const current = (_a = Reflect.getMetadata(SWAGGER_TAGS_METADATA_KEY, target, propertyKey)) !== null && _a !== void 0 ? _a : [];
144
- const merged = Array.from(new Set([...current, ...tags]));
145
- Reflect.defineMetadata(SWAGGER_TAGS_METADATA_KEY, merged, target, propertyKey);
146
- };
147
- }
148
- function configureServices(target) {
149
- var _a;
150
- return (_a = CONFIGURE_SERVICES_METADATA.get(target)) !== null && _a !== void 0 ? _a : [];
151
- }
152
- function initializeServices(target) {
153
- var _a;
154
- return (_a = INITIALIZE_SERVICES_METADATA.get(target)) !== null && _a !== void 0 ? _a : [];
155
- }
156
- function ConfigureServices(target, _propertyKey, descriptor) {
157
- var _a;
158
- if (typeof descriptor.value !== 'function') {
159
- throw new Error('@ConfigureServices can only decorate static methods.');
160
- }
161
- const handlers = (_a = CONFIGURE_SERVICES_METADATA.get(target)) !== null && _a !== void 0 ? _a : [];
162
- handlers.push(descriptor.value.bind(target));
163
- CONFIGURE_SERVICES_METADATA.set(target, handlers);
164
- }
165
- function InitializeServices(target, _propertyKey, descriptor) {
166
- var _a;
167
- if (typeof descriptor.value !== 'function') {
168
- throw new Error('@InitializeServices can only decorate static methods.');
169
- }
170
- const handlers = (_a = INITIALIZE_SERVICES_METADATA.get(target)) !== null && _a !== void 0 ? _a : [];
171
- handlers.push(descriptor.value.bind(target));
172
- INITIALIZE_SERVICES_METADATA.set(target, handlers);
173
- }
174
- function getConfigureServicesHandlers(target) {
175
- var _a;
176
- return (_a = CONFIGURE_SERVICES_METADATA.get(target)) !== null && _a !== void 0 ? _a : [];
177
- }
178
- function getInitializeServicesHandlers(target) {
179
- var _a;
180
- return (_a = INITIALIZE_SERVICES_METADATA.get(target)) !== null && _a !== void 0 ? _a : [];
181
- }