@omen.foundation/node-microservice-runtime 0.1.65 → 0.1.68

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@omen.foundation/node-microservice-runtime",
3
- "version": "0.1.65",
3
+ "version": "0.1.68",
4
4
  "description": "Beamable microservice runtime for Node.js/TypeScript services.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -14,6 +14,10 @@
14
14
  "bin": {
15
15
  "beamo-node": "./dist/cli/index.js"
16
16
  },
17
+ "files": [
18
+ "dist",
19
+ "scripts"
20
+ ],
17
21
  "scripts": {
18
22
  "clean": "rimraf dist dist-cjs",
19
23
  "build": "npm run clean && tsc -p tsconfig.build.json",
@@ -0,0 +1,72 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Script to deprecate all old versions that contain .env files
4
+ *
5
+ * Usage: node scripts/deprecate-all-versions.js
6
+ *
7
+ * This will deprecate all versions from 0.1.0 to 0.1.66
8
+ * You cannot unpublish packages older than 72 hours, so deprecation is the alternative
9
+ */
10
+
11
+ import { execSync } from 'child_process';
12
+
13
+ const PACKAGE_NAME = '@omen.foundation/node-microservice-runtime';
14
+ const DEPRECATE_MESSAGE = 'Security: This version contains exposed credentials. Use version 0.1.67 or later.';
15
+
16
+ // All versions that need to be deprecated
17
+ const VERSIONS = [
18
+ '0.1.0', '0.1.1', '0.1.2', '0.1.3', '0.1.4', '0.1.5', '0.1.6', '0.1.7', '0.1.8', '0.1.9',
19
+ '0.1.10', '0.1.11', '0.1.12', '0.1.13', '0.1.14', '0.1.15', '0.1.16', '0.1.17', '0.1.18', '0.1.19',
20
+ '0.1.20', '0.1.21', '0.1.22', '0.1.23', '0.1.24', '0.1.25', '0.1.26', '0.1.27', '0.1.28', '0.1.29',
21
+ '0.1.30', '0.1.31', '0.1.32', '0.1.33', '0.1.34', '0.1.35', '0.1.36', '0.1.37', '0.1.38', '0.1.39',
22
+ '0.1.40', '0.1.41', '0.1.42', '0.1.43', '0.1.44', '0.1.45', '0.1.46', '0.1.47', '0.1.48', '0.1.49',
23
+ '0.1.50', '0.1.51', '0.1.52', '0.1.53', '0.1.54', '0.1.55', '0.1.56', '0.1.57', '0.1.58', '0.1.59',
24
+ '0.1.60', '0.1.61', '0.1.62', '0.1.63', '0.1.64', '0.1.65', '0.1.66'
25
+ ];
26
+
27
+ console.log(`\n🚨 Deprecating ${VERSIONS.length} versions of ${PACKAGE_NAME}\n`);
28
+ console.log(`Message: "${DEPRECATE_MESSAGE}"\n`);
29
+
30
+ let successCount = 0;
31
+ let failCount = 0;
32
+ const failedVersions = [];
33
+
34
+ for (const version of VERSIONS) {
35
+ const fullPackageName = `${PACKAGE_NAME}@${version}`;
36
+
37
+ try {
38
+ console.log(`Deprecating ${fullPackageName}...`);
39
+
40
+ // Escape the message for shell
41
+ const escapedMessage = DEPRECATE_MESSAGE.replace(/'/g, "\\'").replace(/"/g, '\\"');
42
+ const command = `npm deprecate "${fullPackageName}" "${escapedMessage}"`;
43
+
44
+ execSync(command, { stdio: 'inherit' });
45
+
46
+ console.log(`āœ… Deprecated ${version}\n`);
47
+ successCount++;
48
+
49
+ // Small delay to avoid rate limiting
50
+ if (successCount % 10 === 0) {
51
+ console.log('Pausing for 2 seconds to avoid rate limiting...\n');
52
+ await new Promise(resolve => setTimeout(resolve, 2000));
53
+ }
54
+ } catch (error) {
55
+ console.error(`āŒ Failed to deprecate ${version}: ${error.message}\n`);
56
+ failCount++;
57
+ failedVersions.push(version);
58
+ }
59
+ }
60
+
61
+ console.log(`\n=== Summary ===`);
62
+ console.log(`āœ… Successfully deprecated: ${successCount} versions`);
63
+ console.log(`āŒ Failed: ${failCount} versions`);
64
+
65
+ if (failedVersions.length > 0) {
66
+ console.log(`\nFailed versions:`);
67
+ failedVersions.forEach(v => console.log(` - ${v}`));
68
+ console.log(`\nYou may need to deprecate these manually or they may already be deprecated.`);
69
+ }
70
+
71
+ console.log(`\nāš ļø Important: Rotate your Beamable SECRET immediately!`);
72
+ console.log(` All these versions contained exposed credentials.`);
package/.env DELETED
@@ -1,13 +0,0 @@
1
- # Beamable credentials
2
- CID=1890069218625633
3
- PID=DE_1934633364747296
4
- HOST=wss://api.beamable.com/socket
5
- SECRET=6a24a8a1-f9f1-4e4a-b487-a446896f9b9f
6
- # Alternatively, you can use a refresh token instead of SECRET
7
- # REFRESH_TOKEN=
8
-
9
- # Optional developer settings
10
- NAME_PREFIX=
11
- LOG_LEVEL=info
12
- WATCH_TOKEN=false
13
- BEAM_INSTANCE_COUNT=1
package/env.sample DELETED
@@ -1,13 +0,0 @@
1
- # Beamable credentials
2
- CID=1890069218625633
3
- PID=DE_1934633364747296
4
- HOST=wss://portal.beamable.com/socket
5
- SECRET=6a24a8a1-f9f1-4e4a-b487-a446896f9b9f
6
- # Alternatively, you can use a refresh token instead of SECRET
7
- # REFRESH_TOKEN=
8
-
9
- # Optional developer settings
10
- NAME_PREFIX=
11
- LOG_LEVEL=info
12
- WATCH_TOKEN=false
13
- BEAM_INSTANCE_COUNT=1
package/src/auth.ts DELETED
@@ -1,117 +0,0 @@
1
- import { createHash } from 'node:crypto';
2
- import { URL } from 'node:url';
3
- import type { EnvironmentConfig } from './types.js';
4
- import type { GatewayRequester } from './requester.js';
5
- import { AuthenticationError } from './errors.js';
6
-
7
- interface NonceResponse {
8
- nonce: string;
9
- }
10
-
11
- interface AuthResponse {
12
- result: string;
13
- }
14
-
15
- interface TokenResponse {
16
- access_token?: string;
17
- error?: string;
18
- }
19
-
20
- export class AuthManager {
21
- private readonly env: EnvironmentConfig;
22
- private readonly requester: GatewayRequester;
23
-
24
- constructor(env: EnvironmentConfig, requester: GatewayRequester) {
25
- this.env = env;
26
- this.requester = requester;
27
- }
28
-
29
- async authenticate(): Promise<void> {
30
- if (this.env.secret) {
31
- await this.authenticateWithRealmSecret();
32
- return;
33
- }
34
- if (this.env.refreshToken) {
35
- await this.authenticateWithRefreshToken();
36
- return;
37
- }
38
- throw new AuthenticationError('Neither SECRET nor REFRESH_TOKEN is configured.');
39
- }
40
-
41
- private async authenticateWithRealmSecret(): Promise<void> {
42
- const nonce = await this.requester.request<NonceResponse>('get', 'gateway/nonce');
43
- if (!nonce?.nonce) {
44
- throw new AuthenticationError('Gateway did not provide a nonce for authentication.');
45
- }
46
- const signature = this.calculateRealmSignature(this.env.secret ?? '', nonce.nonce);
47
- const body = {
48
- cid: this.env.cid,
49
- pid: this.env.pid,
50
- signature,
51
- };
52
- const response = await this.requester.request<AuthResponse>('post', 'gateway/auth', body);
53
- if (!response || response.result !== 'ok') {
54
- throw new AuthenticationError(`Realm secret authentication failed with result=${response?.result ?? 'unknown'}.`);
55
- }
56
- }
57
-
58
- private async authenticateWithRefreshToken(): Promise<void> {
59
- const accessToken = await this.exchangeRefreshToken();
60
- const body = {
61
- cid: this.env.cid,
62
- pid: this.env.pid,
63
- token: accessToken,
64
- };
65
- const response = await this.requester.request<AuthResponse>('post', 'gateway/auth', body);
66
- if (!response || response.result !== 'ok') {
67
- throw new AuthenticationError(`Refresh-token authentication failed with result=${response?.result ?? 'unknown'}.`);
68
- }
69
- }
70
-
71
- private calculateRealmSignature(secret: string, nonce: string): string {
72
- const hash = createHash('md5');
73
- hash.update(secret + nonce, 'utf8');
74
- return hash.digest('base64');
75
- }
76
-
77
- private async exchangeRefreshToken(): Promise<string> {
78
- if (!this.env.refreshToken) {
79
- throw new AuthenticationError('REFRESH_TOKEN missing.');
80
- }
81
- const baseUrl = this.hostToHttpUrl();
82
- const tokenUrl = new URL('/basic/auth/token', baseUrl).toString();
83
- const response = await fetch(tokenUrl, {
84
- method: 'POST',
85
- headers: {
86
- 'Content-Type': 'application/json',
87
- Accept: 'application/json',
88
- 'beam-scope': `${this.env.cid}.${this.env.pid}`,
89
- },
90
- body: JSON.stringify({
91
- grant_type: 'refresh_token',
92
- refresh_token: this.env.refreshToken,
93
- }),
94
- });
95
-
96
- if (!response.ok) {
97
- throw new AuthenticationError(`Failed to retrieve access token. status=${response.status}`);
98
- }
99
-
100
- const payload = (await response.json()) as TokenResponse;
101
- if (!payload.access_token) {
102
- throw new AuthenticationError(`Refresh-token exchange failed: ${payload.error ?? 'unknown error'}`);
103
- }
104
- return payload.access_token;
105
- }
106
-
107
- private hostToHttpUrl(): string {
108
- const host = this.env.host.replace(/\/socket$/, '');
109
- if (host.startsWith('wss://')) {
110
- return `https://${host.substring('wss://'.length)}`;
111
- }
112
- if (host.startsWith('ws://')) {
113
- return `http://${host.substring('ws://'.length)}`;
114
- }
115
- return host;
116
- }
117
- }