@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
package/.env
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
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/dist/auth.cjs
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AuthManager = void 0;
|
|
4
|
+
const node_crypto_1 = require("node:crypto");
|
|
5
|
+
const node_url_1 = require("node:url");
|
|
6
|
+
const errors_js_1 = require("./errors.js");
|
|
7
|
+
class AuthManager {
|
|
8
|
+
constructor(env, requester) {
|
|
9
|
+
this.env = env;
|
|
10
|
+
this.requester = requester;
|
|
11
|
+
}
|
|
12
|
+
async authenticate() {
|
|
13
|
+
if (this.env.secret) {
|
|
14
|
+
await this.authenticateWithRealmSecret();
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
if (this.env.refreshToken) {
|
|
18
|
+
await this.authenticateWithRefreshToken();
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
throw new errors_js_1.AuthenticationError('Neither SECRET nor REFRESH_TOKEN is configured.');
|
|
22
|
+
}
|
|
23
|
+
async authenticateWithRealmSecret() {
|
|
24
|
+
var _a, _b;
|
|
25
|
+
const nonce = await this.requester.request('get', 'gateway/nonce');
|
|
26
|
+
if (!(nonce === null || nonce === void 0 ? void 0 : nonce.nonce)) {
|
|
27
|
+
throw new errors_js_1.AuthenticationError('Gateway did not provide a nonce for authentication.');
|
|
28
|
+
}
|
|
29
|
+
const signature = this.calculateRealmSignature((_a = this.env.secret) !== null && _a !== void 0 ? _a : '', nonce.nonce);
|
|
30
|
+
const body = {
|
|
31
|
+
cid: this.env.cid,
|
|
32
|
+
pid: this.env.pid,
|
|
33
|
+
signature,
|
|
34
|
+
};
|
|
35
|
+
const response = await this.requester.request('post', 'gateway/auth', body);
|
|
36
|
+
if (!response || response.result !== 'ok') {
|
|
37
|
+
throw new errors_js_1.AuthenticationError(`Realm secret authentication failed with result=${(_b = response === null || response === void 0 ? void 0 : response.result) !== null && _b !== void 0 ? _b : 'unknown'}.`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
async authenticateWithRefreshToken() {
|
|
41
|
+
var _a;
|
|
42
|
+
const accessToken = await this.exchangeRefreshToken();
|
|
43
|
+
const body = {
|
|
44
|
+
cid: this.env.cid,
|
|
45
|
+
pid: this.env.pid,
|
|
46
|
+
token: accessToken,
|
|
47
|
+
};
|
|
48
|
+
const response = await this.requester.request('post', 'gateway/auth', body);
|
|
49
|
+
if (!response || response.result !== 'ok') {
|
|
50
|
+
throw new errors_js_1.AuthenticationError(`Refresh-token authentication failed with result=${(_a = response === null || response === void 0 ? void 0 : response.result) !== null && _a !== void 0 ? _a : 'unknown'}.`);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
calculateRealmSignature(secret, nonce) {
|
|
54
|
+
const hash = (0, node_crypto_1.createHash)('md5');
|
|
55
|
+
hash.update(secret + nonce, 'utf8');
|
|
56
|
+
return hash.digest('base64');
|
|
57
|
+
}
|
|
58
|
+
async exchangeRefreshToken() {
|
|
59
|
+
var _a;
|
|
60
|
+
if (!this.env.refreshToken) {
|
|
61
|
+
throw new errors_js_1.AuthenticationError('REFRESH_TOKEN missing.');
|
|
62
|
+
}
|
|
63
|
+
const baseUrl = this.hostToHttpUrl();
|
|
64
|
+
const tokenUrl = new node_url_1.URL('/basic/auth/token', baseUrl).toString();
|
|
65
|
+
const response = await fetch(tokenUrl, {
|
|
66
|
+
method: 'POST',
|
|
67
|
+
headers: {
|
|
68
|
+
'Content-Type': 'application/json',
|
|
69
|
+
Accept: 'application/json',
|
|
70
|
+
'beam-scope': `${this.env.cid}.${this.env.pid}`,
|
|
71
|
+
},
|
|
72
|
+
body: JSON.stringify({
|
|
73
|
+
grant_type: 'refresh_token',
|
|
74
|
+
refresh_token: this.env.refreshToken,
|
|
75
|
+
}),
|
|
76
|
+
});
|
|
77
|
+
if (!response.ok) {
|
|
78
|
+
throw new errors_js_1.AuthenticationError(`Failed to retrieve access token. status=${response.status}`);
|
|
79
|
+
}
|
|
80
|
+
const payload = (await response.json());
|
|
81
|
+
if (!payload.access_token) {
|
|
82
|
+
throw new errors_js_1.AuthenticationError(`Refresh-token exchange failed: ${(_a = payload.error) !== null && _a !== void 0 ? _a : 'unknown error'}`);
|
|
83
|
+
}
|
|
84
|
+
return payload.access_token;
|
|
85
|
+
}
|
|
86
|
+
hostToHttpUrl() {
|
|
87
|
+
const host = this.env.host.replace(/\/socket$/, '');
|
|
88
|
+
if (host.startsWith('wss://')) {
|
|
89
|
+
return `https://${host.substring('wss://'.length)}`;
|
|
90
|
+
}
|
|
91
|
+
if (host.startsWith('ws://')) {
|
|
92
|
+
return `http://${host.substring('ws://'.length)}`;
|
|
93
|
+
}
|
|
94
|
+
return host;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
exports.AuthManager = AuthManager;
|
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { EnvironmentConfig } from './types.js';
|
|
2
|
+
import type { GatewayRequester } from './requester.js';
|
|
3
|
+
export declare class AuthManager {
|
|
4
|
+
private readonly env;
|
|
5
|
+
private readonly requester;
|
|
6
|
+
constructor(env: EnvironmentConfig, requester: GatewayRequester);
|
|
7
|
+
authenticate(): Promise<void>;
|
|
8
|
+
private authenticateWithRealmSecret;
|
|
9
|
+
private authenticateWithRefreshToken;
|
|
10
|
+
private calculateRealmSignature;
|
|
11
|
+
private exchangeRefreshToken;
|
|
12
|
+
private hostToHttpUrl;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=auth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.d.ts","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AACpD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAgBvD,qBAAa,WAAW;IACtB,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAoB;IACxC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAmB;gBAEjC,GAAG,EAAE,iBAAiB,EAAE,SAAS,EAAE,gBAAgB;IAKzD,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC;YAYrB,2BAA2B;YAiB3B,4BAA4B;IAa1C,OAAO,CAAC,uBAAuB;YAMjB,oBAAoB;IA8BlC,OAAO,CAAC,aAAa;CAUtB"}
|
package/dist/auth.js
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { URL } from 'node:url';
|
|
3
|
+
import { AuthenticationError } from './errors.js';
|
|
4
|
+
export class AuthManager {
|
|
5
|
+
env;
|
|
6
|
+
requester;
|
|
7
|
+
constructor(env, requester) {
|
|
8
|
+
this.env = env;
|
|
9
|
+
this.requester = requester;
|
|
10
|
+
}
|
|
11
|
+
async authenticate() {
|
|
12
|
+
if (this.env.secret) {
|
|
13
|
+
await this.authenticateWithRealmSecret();
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
if (this.env.refreshToken) {
|
|
17
|
+
await this.authenticateWithRefreshToken();
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
throw new AuthenticationError('Neither SECRET nor REFRESH_TOKEN is configured.');
|
|
21
|
+
}
|
|
22
|
+
async authenticateWithRealmSecret() {
|
|
23
|
+
const nonce = await this.requester.request('get', 'gateway/nonce');
|
|
24
|
+
if (!nonce?.nonce) {
|
|
25
|
+
throw new AuthenticationError('Gateway did not provide a nonce for authentication.');
|
|
26
|
+
}
|
|
27
|
+
const signature = this.calculateRealmSignature(this.env.secret ?? '', nonce.nonce);
|
|
28
|
+
const body = {
|
|
29
|
+
cid: this.env.cid,
|
|
30
|
+
pid: this.env.pid,
|
|
31
|
+
signature,
|
|
32
|
+
};
|
|
33
|
+
const response = await this.requester.request('post', 'gateway/auth', body);
|
|
34
|
+
if (!response || response.result !== 'ok') {
|
|
35
|
+
throw new AuthenticationError(`Realm secret authentication failed with result=${response?.result ?? 'unknown'}.`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
async authenticateWithRefreshToken() {
|
|
39
|
+
const accessToken = await this.exchangeRefreshToken();
|
|
40
|
+
const body = {
|
|
41
|
+
cid: this.env.cid,
|
|
42
|
+
pid: this.env.pid,
|
|
43
|
+
token: accessToken,
|
|
44
|
+
};
|
|
45
|
+
const response = await this.requester.request('post', 'gateway/auth', body);
|
|
46
|
+
if (!response || response.result !== 'ok') {
|
|
47
|
+
throw new AuthenticationError(`Refresh-token authentication failed with result=${response?.result ?? 'unknown'}.`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
calculateRealmSignature(secret, nonce) {
|
|
51
|
+
const hash = createHash('md5');
|
|
52
|
+
hash.update(secret + nonce, 'utf8');
|
|
53
|
+
return hash.digest('base64');
|
|
54
|
+
}
|
|
55
|
+
async exchangeRefreshToken() {
|
|
56
|
+
if (!this.env.refreshToken) {
|
|
57
|
+
throw new AuthenticationError('REFRESH_TOKEN missing.');
|
|
58
|
+
}
|
|
59
|
+
const baseUrl = this.hostToHttpUrl();
|
|
60
|
+
const tokenUrl = new URL('/basic/auth/token', baseUrl).toString();
|
|
61
|
+
const response = await fetch(tokenUrl, {
|
|
62
|
+
method: 'POST',
|
|
63
|
+
headers: {
|
|
64
|
+
'Content-Type': 'application/json',
|
|
65
|
+
Accept: 'application/json',
|
|
66
|
+
'beam-scope': `${this.env.cid}.${this.env.pid}`,
|
|
67
|
+
},
|
|
68
|
+
body: JSON.stringify({
|
|
69
|
+
grant_type: 'refresh_token',
|
|
70
|
+
refresh_token: this.env.refreshToken,
|
|
71
|
+
}),
|
|
72
|
+
});
|
|
73
|
+
if (!response.ok) {
|
|
74
|
+
throw new AuthenticationError(`Failed to retrieve access token. status=${response.status}`);
|
|
75
|
+
}
|
|
76
|
+
const payload = (await response.json());
|
|
77
|
+
if (!payload.access_token) {
|
|
78
|
+
throw new AuthenticationError(`Refresh-token exchange failed: ${payload.error ?? 'unknown error'}`);
|
|
79
|
+
}
|
|
80
|
+
return payload.access_token;
|
|
81
|
+
}
|
|
82
|
+
hostToHttpUrl() {
|
|
83
|
+
const host = this.env.host.replace(/\/socket$/, '');
|
|
84
|
+
if (host.startsWith('wss://')) {
|
|
85
|
+
return `https://${host.substring('wss://'.length)}`;
|
|
86
|
+
}
|
|
87
|
+
if (host.startsWith('ws://')) {
|
|
88
|
+
return `http://${host.substring('ws://'.length)}`;
|
|
89
|
+
}
|
|
90
|
+
return host;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
//# sourceMappingURL=auth.js.map
|
package/dist/auth.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth.js","sourceRoot":"","sources":["../src/auth.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from 'node:crypto';\r\nimport { URL } from 'node:url';\r\nimport type { EnvironmentConfig } from './types.js';\r\nimport type { GatewayRequester } from './requester.js';\r\nimport { AuthenticationError } from './errors.js';\r\n\r\ninterface NonceResponse {\r\n nonce: string;\r\n}\r\n\r\ninterface AuthResponse {\r\n result: string;\r\n}\r\n\r\ninterface TokenResponse {\r\n access_token?: string;\r\n error?: string;\r\n}\r\n\r\nexport class AuthManager {\r\n private readonly env: EnvironmentConfig;\r\n private readonly requester: GatewayRequester;\r\n\r\n constructor(env: EnvironmentConfig, requester: GatewayRequester) {\r\n this.env = env;\r\n this.requester = requester;\r\n }\r\n\r\n async authenticate(): Promise<void> {\r\n if (this.env.secret) {\r\n await this.authenticateWithRealmSecret();\r\n return;\r\n }\r\n if (this.env.refreshToken) {\r\n await this.authenticateWithRefreshToken();\r\n return;\r\n }\r\n throw new AuthenticationError('Neither SECRET nor REFRESH_TOKEN is configured.');\r\n }\r\n\r\n private async authenticateWithRealmSecret(): Promise<void> {\r\n const nonce = await this.requester.request<NonceResponse>('get', 'gateway/nonce');\r\n if (!nonce?.nonce) {\r\n throw new AuthenticationError('Gateway did not provide a nonce for authentication.');\r\n }\r\n const signature = this.calculateRealmSignature(this.env.secret ?? '', nonce.nonce);\r\n const body = {\r\n cid: this.env.cid,\r\n pid: this.env.pid,\r\n signature,\r\n };\r\n const response = await this.requester.request<AuthResponse>('post', 'gateway/auth', body);\r\n if (!response || response.result !== 'ok') {\r\n throw new AuthenticationError(`Realm secret authentication failed with result=${response?.result ?? 'unknown'}.`);\r\n }\r\n }\r\n\r\n private async authenticateWithRefreshToken(): Promise<void> {\r\n const accessToken = await this.exchangeRefreshToken();\r\n const body = {\r\n cid: this.env.cid,\r\n pid: this.env.pid,\r\n token: accessToken,\r\n };\r\n const response = await this.requester.request<AuthResponse>('post', 'gateway/auth', body);\r\n if (!response || response.result !== 'ok') {\r\n throw new AuthenticationError(`Refresh-token authentication failed with result=${response?.result ?? 'unknown'}.`);\r\n }\r\n }\r\n\r\n private calculateRealmSignature(secret: string, nonce: string): string {\r\n const hash = createHash('md5');\r\n hash.update(secret + nonce, 'utf8');\r\n return hash.digest('base64');\r\n }\r\n\r\n private async exchangeRefreshToken(): Promise<string> {\r\n if (!this.env.refreshToken) {\r\n throw new AuthenticationError('REFRESH_TOKEN missing.');\r\n }\r\n const baseUrl = this.hostToHttpUrl();\r\n const tokenUrl = new URL('/basic/auth/token', baseUrl).toString();\r\n const response = await fetch(tokenUrl, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n Accept: 'application/json',\r\n 'beam-scope': `${this.env.cid}.${this.env.pid}`,\r\n },\r\n body: JSON.stringify({\r\n grant_type: 'refresh_token',\r\n refresh_token: this.env.refreshToken,\r\n }),\r\n });\r\n\r\n if (!response.ok) {\r\n throw new AuthenticationError(`Failed to retrieve access token. status=${response.status}`);\r\n }\r\n\r\n const payload = (await response.json()) as TokenResponse;\r\n if (!payload.access_token) {\r\n throw new AuthenticationError(`Refresh-token exchange failed: ${payload.error ?? 'unknown error'}`);\r\n }\r\n return payload.access_token;\r\n }\r\n\r\n private hostToHttpUrl(): string {\r\n const host = this.env.host.replace(/\\/socket$/, '');\r\n if (host.startsWith('wss://')) {\r\n return `https://${host.substring('wss://'.length)}`;\r\n }\r\n if (host.startsWith('ws://')) {\r\n return `http://${host.substring('ws://'.length)}`;\r\n }\r\n return host;\r\n }\r\n}\r\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":""}
|