@multiplayer-app/session-recorder-node 2.0.17 → 2.0.18
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 +2 -2
- package/eslint.config.js +0 -226
- package/examples/cli/package-lock.json +0 -4260
- package/examples/cli/package.json +0 -56
- package/examples/cli/src/config.ts +0 -47
- package/examples/cli/src/index.ts +0 -43
- package/examples/cli/src/opentelemetry.ts +0 -140
- package/examples/cli/tsconfig.json +0 -39
- package/examples/http-server/package-lock.json +0 -5411
- package/examples/http-server/package.json +0 -48
- package/examples/http-server/src/api.ts +0 -20
- package/examples/http-server/src/config.ts +0 -24
- package/examples/http-server/src/index.ts +0 -46
- package/examples/http-server/src/opentelemetry.ts +0 -140
- package/examples/http-server/tsconfig.json +0 -39
- package/src/config.ts +0 -5
- package/src/helper.ts +0 -13
- package/src/index.ts +0 -6
- package/src/integrations/express.ts +0 -52
- package/src/integrations/index.ts +0 -1
- package/src/services/api.service.ts +0 -230
- package/src/sessionRecorder.ts +0 -285
- package/src/types.ts +0 -27
- package/tsconfig.json +0 -38
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "http-server-exmaple",
|
|
3
|
-
"version": "1.0.0",
|
|
4
|
-
"description": "",
|
|
5
|
-
"main": "./src/index.ts",
|
|
6
|
-
"engines": {
|
|
7
|
-
"node": ">=18",
|
|
8
|
-
"npm": ">=8"
|
|
9
|
-
},
|
|
10
|
-
"scripts": {
|
|
11
|
-
"start": "node dist/index.js",
|
|
12
|
-
"dev": "nodemon --watch \"src/**\" --ext \"ts,json\" --ignore \"src/**/*.spec.ts\" --exec \"ts-node src/index.ts\"",
|
|
13
|
-
"build": "npm run clean && npm run compile",
|
|
14
|
-
"clean": "rm -rf ./dist",
|
|
15
|
-
"compile": "tsc --build --force",
|
|
16
|
-
"lint": "eslint src/**/*.ts --config ../../.eslintrc"
|
|
17
|
-
},
|
|
18
|
-
"author": "Multiplayer",
|
|
19
|
-
"dependencies": {
|
|
20
|
-
"@multiplayer-app/session-recorder-node": "1.3.37",
|
|
21
|
-
"@opentelemetry/api": "1.9.0",
|
|
22
|
-
"@opentelemetry/api-logs": "0.203.0",
|
|
23
|
-
"@opentelemetry/auto-instrumentations-node": "0.62.1",
|
|
24
|
-
"@opentelemetry/core": "2.0.1",
|
|
25
|
-
"@opentelemetry/exporter-trace-otlp-http": "0.203.0",
|
|
26
|
-
"@opentelemetry/exporter-logs-otlp-http": "0.203.0",
|
|
27
|
-
"@opentelemetry/resources": "2.0.1",
|
|
28
|
-
"@opentelemetry/sdk-logs": "0.203.0",
|
|
29
|
-
"@opentelemetry/sdk-trace-base": "2.0.1",
|
|
30
|
-
"@opentelemetry/sdk-trace-node": "2.0.1",
|
|
31
|
-
"@opentelemetry/semantic-conventions": "1.36.0",
|
|
32
|
-
"body-parser": "1.20.2",
|
|
33
|
-
"cors": "2.8.5",
|
|
34
|
-
"dotenv": "16.3.1",
|
|
35
|
-
"express": "4.18.2"
|
|
36
|
-
},
|
|
37
|
-
"devDependencies": {
|
|
38
|
-
"@types/body-parser": "1.19.2",
|
|
39
|
-
"@types/cors": "2.8.13",
|
|
40
|
-
"@types/express": "4.17.17",
|
|
41
|
-
"@types/jest": "29.5.4",
|
|
42
|
-
"@types/node": "20.5.7",
|
|
43
|
-
"eslint": "10.1.0",
|
|
44
|
-
"nodemon": "3.1.9",
|
|
45
|
-
"ts-node": "10.9.1",
|
|
46
|
-
"typescript": "5.7.3"
|
|
47
|
-
}
|
|
48
|
-
}
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import express, {
|
|
2
|
-
type Request,
|
|
3
|
-
type Response,
|
|
4
|
-
type NextFunction
|
|
5
|
-
} from 'express'
|
|
6
|
-
|
|
7
|
-
const { Router } = express
|
|
8
|
-
const router = Router()
|
|
9
|
-
|
|
10
|
-
const health = async (req: Request, res: Response, next: NextFunction) => {
|
|
11
|
-
try {
|
|
12
|
-
return res.status(200).json({})
|
|
13
|
-
} catch (err) {
|
|
14
|
-
return next(err)
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
router.route('/').get(health)
|
|
19
|
-
|
|
20
|
-
export default router
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
export const NODE_ENV = process.env.NODE_ENV || 'development'
|
|
2
|
-
export const isProduction = NODE_ENV === 'production'
|
|
3
|
-
|
|
4
|
-
export const PORT = Number(process.env.PORT || 3000)
|
|
5
|
-
export const API_PREFIX = process.env.API_PREFIX || '/v1/api'
|
|
6
|
-
|
|
7
|
-
export const LOG_LEVEL = process.env.LOG_LEVEL || (isProduction ? 'info' : 'debug')
|
|
8
|
-
|
|
9
|
-
export const COMPONENT_NAME = process.env.npm_package_name?.split('/').pop() as string || process.env.SERVICE_NAME || 'timegate'
|
|
10
|
-
export const COMPONENT_VERSION = process.env.npm_package_version || '0.0.1'
|
|
11
|
-
export const ENVIRONMENT = process.env.ENVIRONMENT || 'staging'
|
|
12
|
-
|
|
13
|
-
export const MULTIPLAYER_OTLP_KEY = process.env.MULTIPLAYER_OTLP_KEY as string
|
|
14
|
-
|
|
15
|
-
if (!MULTIPLAYER_OTLP_KEY) {
|
|
16
|
-
throw new Error('MULTIPLAYER_OTLP_KEY is not set')
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export const OTLP_TRACES_ENDPOINT = process.env.OTLP_TRACES_ENDPOINT || 'https://api.multiplayer.app/v1/traces'
|
|
20
|
-
export const OTLP_LOGS_ENDPOINT = process.env.OTLP_LOGS_ENDPOINT || 'https://api.multiplayer.app/v1/logs'
|
|
21
|
-
|
|
22
|
-
export const MULTIPLAYER_OTLP_SPAN_RATIO = process.env.MULTIPLAYER_OTLP_SPAN_RATIO
|
|
23
|
-
? Number(process.env.MULTIPLAYER_OTLP_SPAN_RATIO)
|
|
24
|
-
: 0.01
|
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
import 'dotenv/config'
|
|
2
|
-
import './opentelemetry'
|
|
3
|
-
import http from 'http'
|
|
4
|
-
import cors from 'cors'
|
|
5
|
-
import bodyParser from 'body-parser'
|
|
6
|
-
import express, {
|
|
7
|
-
type Request,
|
|
8
|
-
type Response,
|
|
9
|
-
type NextFunction,
|
|
10
|
-
} from 'express'
|
|
11
|
-
import { PORT, API_PREFIX } from './config'
|
|
12
|
-
import api from './api'
|
|
13
|
-
|
|
14
|
-
const app = express()
|
|
15
|
-
|
|
16
|
-
app.use(cors())
|
|
17
|
-
app.use(bodyParser.urlencoded({ extended: true }))
|
|
18
|
-
app.use(bodyParser.json())
|
|
19
|
-
|
|
20
|
-
app.use(API_PREFIX, api)
|
|
21
|
-
|
|
22
|
-
app.use((req: Request, res: Response, next: NextFunction) => {
|
|
23
|
-
res.status(404).send('Not found')
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
const httpServer = http.createServer(app)
|
|
27
|
-
const onReady = () => {
|
|
28
|
-
console.log(`🚀 Server ready at http://localhost:${PORT}`)
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
httpServer.listen(PORT, onReady)
|
|
32
|
-
|
|
33
|
-
const exitHandler = async (error: Error) => {
|
|
34
|
-
if (error) {
|
|
35
|
-
console.log('Server exited with error', error)
|
|
36
|
-
}
|
|
37
|
-
process.removeListener('exit', exitHandler)
|
|
38
|
-
process.exit()
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
process.on('exit', exitHandler)
|
|
42
|
-
process.on('SIGINT', exitHandler)
|
|
43
|
-
process.on('SIGTERM', exitHandler)
|
|
44
|
-
process.on('uncaughtException', (err) => {
|
|
45
|
-
console.error('uncaughtException', err)
|
|
46
|
-
})
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
import { hostname } from 'os'
|
|
2
|
-
import { node, NodeSDK } from '@opentelemetry/sdk-node'
|
|
3
|
-
import {
|
|
4
|
-
BatchSpanProcessor,
|
|
5
|
-
ParentBasedSampler,
|
|
6
|
-
} from '@opentelemetry/sdk-trace-base'
|
|
7
|
-
import {
|
|
8
|
-
getNodeAutoInstrumentations,
|
|
9
|
-
getResourceDetectors,
|
|
10
|
-
} from '@opentelemetry/auto-instrumentations-node'
|
|
11
|
-
import {
|
|
12
|
-
resourceFromAttributes,
|
|
13
|
-
detectResources,
|
|
14
|
-
} from '@opentelemetry/resources'
|
|
15
|
-
import {
|
|
16
|
-
ATTR_SERVICE_NAME,
|
|
17
|
-
ATTR_SERVICE_VERSION,
|
|
18
|
-
SEMRESATTRS_HOST_NAME,
|
|
19
|
-
SEMRESATTRS_DEPLOYMENT_ENVIRONMENT,
|
|
20
|
-
SEMRESATTRS_PROCESS_RUNTIME_VERSION,
|
|
21
|
-
SEMRESATTRS_PROCESS_PID,
|
|
22
|
-
} from '@opentelemetry/semantic-conventions'
|
|
23
|
-
import api from '@opentelemetry/api'
|
|
24
|
-
// import { OTLPTraceExporter } from "@opentelemetry/exporter-trace-otlp-http"
|
|
25
|
-
import { W3CTraceContextPropagator } from '@opentelemetry/core'
|
|
26
|
-
import {
|
|
27
|
-
SessionRecorderHttpInstrumentationHooksNode,
|
|
28
|
-
SessionRecorderTraceIdRatioBasedSampler,
|
|
29
|
-
SessionRecorderIdGenerator,
|
|
30
|
-
SessionRecorderHttpTraceExporter,
|
|
31
|
-
SessionRecorderHttpLogsExporter,
|
|
32
|
-
} from '@multiplayer-app/session-recorder-node'
|
|
33
|
-
import { LoggerProvider, BatchLogRecordProcessor } from '@opentelemetry/sdk-logs'
|
|
34
|
-
import * as apiLogs from '@opentelemetry/api-logs'
|
|
35
|
-
// import { OTLPLogExporter } from '@opentelemetry/exporter-logs-otlp-http'
|
|
36
|
-
|
|
37
|
-
import {
|
|
38
|
-
OTLP_TRACES_ENDPOINT,
|
|
39
|
-
OTLP_LOGS_ENDPOINT,
|
|
40
|
-
MULTIPLAYER_OTLP_KEY,
|
|
41
|
-
MULTIPLAYER_OTLP_SPAN_RATIO,
|
|
42
|
-
COMPONENT_NAME,
|
|
43
|
-
COMPONENT_VERSION,
|
|
44
|
-
ENVIRONMENT,
|
|
45
|
-
} from './config'
|
|
46
|
-
|
|
47
|
-
// NOTE: Update instrumentation configuration as needed
|
|
48
|
-
// For more see: https://www.npmjs.com/package/@opentelemetry/auto-instrumentations-node
|
|
49
|
-
const instrumentations = [
|
|
50
|
-
getNodeAutoInstrumentations({
|
|
51
|
-
'@opentelemetry/instrumentation-http': {
|
|
52
|
-
requestHook: SessionRecorderHttpInstrumentationHooksNode.requestHook({
|
|
53
|
-
maskHeadersList: ['X-Api-Key'],
|
|
54
|
-
maxPayloadSizeBytes: 5000,
|
|
55
|
-
schemifyDocSpanPayload: false,
|
|
56
|
-
isMaskBodyEnabled: false,
|
|
57
|
-
}),
|
|
58
|
-
responseHook: SessionRecorderHttpInstrumentationHooksNode.responseHook({
|
|
59
|
-
maskHeadersList: ['X-Api-Key'],
|
|
60
|
-
maxPayloadSizeBytes: 5000,
|
|
61
|
-
schemifyDocSpanPayload: false,
|
|
62
|
-
isMaskBodyEnabled: false,
|
|
63
|
-
}),
|
|
64
|
-
},
|
|
65
|
-
}),
|
|
66
|
-
]
|
|
67
|
-
|
|
68
|
-
const getResource = () => {
|
|
69
|
-
const resourceWithAttributes = resourceFromAttributes({
|
|
70
|
-
[ATTR_SERVICE_NAME]: COMPONENT_NAME,
|
|
71
|
-
[ATTR_SERVICE_VERSION]: COMPONENT_VERSION,
|
|
72
|
-
[SEMRESATTRS_HOST_NAME]: hostname(),
|
|
73
|
-
[SEMRESATTRS_DEPLOYMENT_ENVIRONMENT]: ENVIRONMENT,
|
|
74
|
-
[SEMRESATTRS_PROCESS_RUNTIME_VERSION]: process.version,
|
|
75
|
-
[SEMRESATTRS_PROCESS_PID]: process.pid,
|
|
76
|
-
})
|
|
77
|
-
const detectedResources = detectResources({ detectors: getResourceDetectors() })
|
|
78
|
-
const resource = resourceWithAttributes.merge(detectedResources)
|
|
79
|
-
|
|
80
|
-
return resource
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export const idGenerator = new SessionRecorderIdGenerator()
|
|
84
|
-
|
|
85
|
-
const opentelemetry = () => {
|
|
86
|
-
// const traceExporter = new OTLPTraceExporter({
|
|
87
|
-
// url: OTLP_TRACES_ENDPOINT,
|
|
88
|
-
// headers: {
|
|
89
|
-
// Authorization: MULTIPLAYER_OTLP_KEY
|
|
90
|
-
// },
|
|
91
|
-
// })
|
|
92
|
-
const traceExporter = new SessionRecorderHttpTraceExporter({
|
|
93
|
-
apiKey: MULTIPLAYER_OTLP_KEY,
|
|
94
|
-
url: OTLP_TRACES_ENDPOINT,
|
|
95
|
-
})
|
|
96
|
-
|
|
97
|
-
const resource = getResource()
|
|
98
|
-
|
|
99
|
-
const provider = new node.NodeTracerProvider({
|
|
100
|
-
resource,
|
|
101
|
-
spanProcessors: [
|
|
102
|
-
new BatchSpanProcessor(traceExporter),
|
|
103
|
-
],
|
|
104
|
-
sampler: new ParentBasedSampler({
|
|
105
|
-
root: new SessionRecorderTraceIdRatioBasedSampler(MULTIPLAYER_OTLP_SPAN_RATIO),
|
|
106
|
-
}),
|
|
107
|
-
idGenerator,
|
|
108
|
-
})
|
|
109
|
-
|
|
110
|
-
// const logExporter = new OTLPLogExporter({
|
|
111
|
-
// url: OTLP_LOGS_ENDPOINT,
|
|
112
|
-
// headers: {
|
|
113
|
-
// Authorization: MULTIPLAYER_OTLP_KEY
|
|
114
|
-
// },
|
|
115
|
-
// })
|
|
116
|
-
const logExporter = new SessionRecorderHttpLogsExporter({
|
|
117
|
-
apiKey: MULTIPLAYER_OTLP_KEY,
|
|
118
|
-
url: OTLP_LOGS_ENDPOINT,
|
|
119
|
-
})
|
|
120
|
-
const logRecordProcessor = new BatchLogRecordProcessor(logExporter)
|
|
121
|
-
|
|
122
|
-
const loggerProvider = new LoggerProvider({
|
|
123
|
-
resource,
|
|
124
|
-
processors: [logRecordProcessor],
|
|
125
|
-
})
|
|
126
|
-
|
|
127
|
-
apiLogs.logs.setGlobalLoggerProvider(loggerProvider)
|
|
128
|
-
|
|
129
|
-
provider.register()
|
|
130
|
-
api.trace.setGlobalTracerProvider(provider)
|
|
131
|
-
api.propagation.setGlobalPropagator(new W3CTraceContextPropagator())
|
|
132
|
-
|
|
133
|
-
const sdk = new NodeSDK({
|
|
134
|
-
instrumentations,
|
|
135
|
-
})
|
|
136
|
-
|
|
137
|
-
sdk.start()
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
opentelemetry()
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"declaration": true,
|
|
4
|
-
"declarationMap": true,
|
|
5
|
-
"baseUrl": ".",
|
|
6
|
-
"module": "commonjs",
|
|
7
|
-
"noImplicitAny": false,
|
|
8
|
-
"noUnusedParameters": false,
|
|
9
|
-
"allowJs": true,
|
|
10
|
-
"allowSyntheticDefaultImports": true,
|
|
11
|
-
"esModuleInterop": true,
|
|
12
|
-
"forceConsistentCasingInFileNames": true,
|
|
13
|
-
"isolatedModules": true,
|
|
14
|
-
"moduleResolution": "node",
|
|
15
|
-
"noImplicitReturns": true,
|
|
16
|
-
"noImplicitThis": true,
|
|
17
|
-
"noUnusedLocals": false,
|
|
18
|
-
"preserveConstEnums": true,
|
|
19
|
-
"removeComments": false,
|
|
20
|
-
"resolveJsonModule": true,
|
|
21
|
-
"skipLibCheck": true,
|
|
22
|
-
"sourceMap": true,
|
|
23
|
-
"types": [
|
|
24
|
-
"node"
|
|
25
|
-
],
|
|
26
|
-
"target": "ES2018",
|
|
27
|
-
"downlevelIteration": true,
|
|
28
|
-
"strict": true,
|
|
29
|
-
"composite": true,
|
|
30
|
-
"outDir": "./dist/",
|
|
31
|
-
"rootDir": "./src/",
|
|
32
|
-
"preserveSymlinks": true
|
|
33
|
-
},
|
|
34
|
-
"exclude": ["dist", "coverage", "jest.config.js", "__tests__", "migration"],
|
|
35
|
-
"references": [],
|
|
36
|
-
"ts-node": {
|
|
37
|
-
"files": true
|
|
38
|
-
}
|
|
39
|
-
}
|
package/src/config.ts
DELETED
package/src/helper.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
export const getFormattedDate = (date, options?) => {
|
|
2
|
-
return new Date(date).toLocaleDateString(
|
|
3
|
-
'en-US',
|
|
4
|
-
options || {
|
|
5
|
-
month: 'short',
|
|
6
|
-
year: 'numeric',
|
|
7
|
-
day: 'numeric',
|
|
8
|
-
hour: 'numeric',
|
|
9
|
-
minute: '2-digit',
|
|
10
|
-
second: '2-digit',
|
|
11
|
-
},
|
|
12
|
-
)
|
|
13
|
-
}
|
package/src/index.ts
DELETED
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import type * as http from 'node:http'
|
|
2
|
-
import { SessionRecorderSdk } from '@multiplayer-app/session-recorder-common'
|
|
3
|
-
|
|
4
|
-
type ExpressMiddleware = (req: http.IncomingMessage, res: http.ServerResponse, next: () => void) => void;
|
|
5
|
-
|
|
6
|
-
type ExpressErrorMiddleware = (
|
|
7
|
-
error: Error,
|
|
8
|
-
req: http.IncomingMessage,
|
|
9
|
-
res: http.ServerResponse,
|
|
10
|
-
next: (error: Error) => void,
|
|
11
|
-
) => void;
|
|
12
|
-
|
|
13
|
-
interface MiddlewareError extends Error {
|
|
14
|
-
status?: number | string;
|
|
15
|
-
statusCode?: number | string;
|
|
16
|
-
status_code?: number | string;
|
|
17
|
-
output?: {
|
|
18
|
-
statusCode?: number | string;
|
|
19
|
-
};
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
interface ExpressHandlerOptions {
|
|
23
|
-
shouldHandleError?(this: void, error: Error): boolean;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function getStatusCodeFromResponse(error: MiddlewareError): number {
|
|
27
|
-
const statusCode = error.status || error.statusCode || error.status_code || error.output?.statusCode
|
|
28
|
-
return statusCode ? parseInt(statusCode as string, 10) : 500
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/** Returns true if response code is internal server error */
|
|
32
|
-
function defaultShouldHandleError(error: Error): boolean {
|
|
33
|
-
const status = getStatusCodeFromResponse(error)
|
|
34
|
-
return status >= 500
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
export function expressErrorHandler(options?: ExpressHandlerOptions): ExpressErrorMiddleware {
|
|
38
|
-
return function multiplayerErrorMiddleware(
|
|
39
|
-
error: Error,
|
|
40
|
-
request: http.IncomingMessage,
|
|
41
|
-
res: http.ServerResponse,
|
|
42
|
-
next: (error: Error) => void,
|
|
43
|
-
): void {
|
|
44
|
-
const shouldHandleError = options?.shouldHandleError || defaultShouldHandleError
|
|
45
|
-
|
|
46
|
-
if (shouldHandleError(error)) {
|
|
47
|
-
SessionRecorderSdk.captureException(error)
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
next(error)
|
|
51
|
-
}
|
|
52
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * as express from './express'
|
|
@@ -1,230 +0,0 @@
|
|
|
1
|
-
import { MULTIPLAYER_BASE_API_URL } from '../config'
|
|
2
|
-
import { ISession } from '../types'
|
|
3
|
-
|
|
4
|
-
export interface ApiServiceConfig {
|
|
5
|
-
apiKey?: string
|
|
6
|
-
apiBaseUrl?: string
|
|
7
|
-
continuousRecording?: boolean
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
export interface StartSessionRequest {
|
|
11
|
-
name?: string
|
|
12
|
-
resourceAttributes?: Record<string, any>
|
|
13
|
-
sessionAttributes?: Record<string, any>
|
|
14
|
-
tags?: {
|
|
15
|
-
key?: string
|
|
16
|
-
value: string
|
|
17
|
-
}[]
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export interface StopSessionRequest {
|
|
21
|
-
sessionAttributes?: {
|
|
22
|
-
email?: string
|
|
23
|
-
comment?: string
|
|
24
|
-
},
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export class ApiService {
|
|
28
|
-
private config: ApiServiceConfig
|
|
29
|
-
|
|
30
|
-
constructor() {
|
|
31
|
-
this.config = {
|
|
32
|
-
apiBaseUrl: MULTIPLAYER_BASE_API_URL,
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Initialize the API service
|
|
38
|
-
* @param config - API service configuration
|
|
39
|
-
* @param config.apiKey - API key for authentication
|
|
40
|
-
* @param config.apiBaseUrl - Base URL for API endpoints (preferred)
|
|
41
|
-
* @param config.continuousRecording - Whether continuous recording is enabled
|
|
42
|
-
*/
|
|
43
|
-
public init(config: ApiServiceConfig) {
|
|
44
|
-
const { apiBaseUrl: _apiBaseUrl, ...restConfig } = config
|
|
45
|
-
|
|
46
|
-
const apiBaseUrl = _apiBaseUrl || MULTIPLAYER_BASE_API_URL
|
|
47
|
-
|
|
48
|
-
this.config = {
|
|
49
|
-
...this.config,
|
|
50
|
-
...restConfig,
|
|
51
|
-
apiBaseUrl,
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
/**
|
|
56
|
-
* Update the API service configuration
|
|
57
|
-
* @param config - Partial configuration to update
|
|
58
|
-
*/
|
|
59
|
-
public updateConfigs(config: Partial<ApiServiceConfig>) {
|
|
60
|
-
const { apiBaseUrl: _apiBaseUrl, ...restConfig } = config
|
|
61
|
-
|
|
62
|
-
const apiBaseUrl = _apiBaseUrl || MULTIPLAYER_BASE_API_URL
|
|
63
|
-
|
|
64
|
-
this.config = {
|
|
65
|
-
...this.config,
|
|
66
|
-
...restConfig,
|
|
67
|
-
apiBaseUrl,
|
|
68
|
-
}
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Get the current API base URL
|
|
73
|
-
* @returns The current API base URL
|
|
74
|
-
*/
|
|
75
|
-
public getApiBaseUrl(): string {
|
|
76
|
-
return this.config.apiBaseUrl || MULTIPLAYER_BASE_API_URL
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
/**
|
|
80
|
-
* Start a new debug session
|
|
81
|
-
* @param requestBody - Session start request data
|
|
82
|
-
* @param signal - Optional AbortSignal for request cancellation
|
|
83
|
-
*/
|
|
84
|
-
async startSession(
|
|
85
|
-
requestBody: StartSessionRequest,
|
|
86
|
-
signal?: AbortSignal,
|
|
87
|
-
): Promise<ISession> {
|
|
88
|
-
return this.makeRequest(
|
|
89
|
-
'/debug-sessions/start',
|
|
90
|
-
'POST',
|
|
91
|
-
requestBody,
|
|
92
|
-
signal,
|
|
93
|
-
)
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Stop an active debug session
|
|
98
|
-
* @param sessionId - ID of the session to stop
|
|
99
|
-
* @param requestBody - Session stop request data
|
|
100
|
-
*/
|
|
101
|
-
async stopSession(
|
|
102
|
-
sessionId: string,
|
|
103
|
-
requestBody: StopSessionRequest,
|
|
104
|
-
): Promise<any> {
|
|
105
|
-
return this.makeRequest(
|
|
106
|
-
`/debug-sessions/${sessionId}/stop`,
|
|
107
|
-
'PATCH',
|
|
108
|
-
requestBody,
|
|
109
|
-
)
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Cancel an active session
|
|
114
|
-
* @param sessionId - ID of the session to cancel
|
|
115
|
-
*/
|
|
116
|
-
async cancelSession(sessionId: string): Promise<any> {
|
|
117
|
-
return this.makeRequest(
|
|
118
|
-
`/debug-sessions/${sessionId}/cancel`,
|
|
119
|
-
'DELETE',
|
|
120
|
-
)
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* Start a new session
|
|
125
|
-
* @param requestBody - Session start request data
|
|
126
|
-
* @param signal - Optional AbortSignal for request cancellation
|
|
127
|
-
*/
|
|
128
|
-
async startContinuousSession(
|
|
129
|
-
requestBody: StartSessionRequest,
|
|
130
|
-
signal?: AbortSignal,
|
|
131
|
-
): Promise<any> {
|
|
132
|
-
return this.makeRequest(
|
|
133
|
-
'/continuous-debug-sessions/start',
|
|
134
|
-
'POST',
|
|
135
|
-
requestBody,
|
|
136
|
-
signal,
|
|
137
|
-
)
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
/**
|
|
141
|
-
* Save a continuous session
|
|
142
|
-
* @param sessionId - ID of the session to save
|
|
143
|
-
* @param requestBody - Session save request data
|
|
144
|
-
* @param signal - Optional AbortSignal for request cancellation
|
|
145
|
-
*/
|
|
146
|
-
async saveContinuousSession(
|
|
147
|
-
sessionId: string,
|
|
148
|
-
requestBody: StartSessionRequest,
|
|
149
|
-
signal?: AbortSignal,
|
|
150
|
-
): Promise<any> {
|
|
151
|
-
return this.makeRequest(
|
|
152
|
-
`/continuous-debug-sessions/${sessionId}/save`,
|
|
153
|
-
'POST',
|
|
154
|
-
requestBody,
|
|
155
|
-
signal,
|
|
156
|
-
)
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
/**
|
|
160
|
-
* Cancel an active debug session
|
|
161
|
-
* @param sessionId - ID of the session to cancel
|
|
162
|
-
*/
|
|
163
|
-
async stopContinuousSession(sessionId: string): Promise<any> {
|
|
164
|
-
return this.makeRequest(
|
|
165
|
-
`/continuous-debug-sessions/${sessionId}/cancel`,
|
|
166
|
-
'DELETE',
|
|
167
|
-
)
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
/**
|
|
171
|
-
* Check debug session should be started remotely
|
|
172
|
-
*/
|
|
173
|
-
async checkRemoteSession(
|
|
174
|
-
requestBody: StartSessionRequest,
|
|
175
|
-
signal?: AbortSignal,
|
|
176
|
-
): Promise<{ state: 'START' | 'STOP' }> {
|
|
177
|
-
return this.makeRequest(
|
|
178
|
-
'/remote-debug-session/check',
|
|
179
|
-
'POST',
|
|
180
|
-
requestBody,
|
|
181
|
-
signal,
|
|
182
|
-
)
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
/**
|
|
186
|
-
* Make a request to the session API
|
|
187
|
-
* @param path - API endpoint path (relative to the base URL)
|
|
188
|
-
* @param method - HTTP method (GET, POST, PATCH, etc.)
|
|
189
|
-
* @param body - request payload
|
|
190
|
-
* @param signal - AbortSignal to set request's signal
|
|
191
|
-
*/
|
|
192
|
-
private async makeRequest(
|
|
193
|
-
path: string,
|
|
194
|
-
method: string,
|
|
195
|
-
body?: any,
|
|
196
|
-
signal?: AbortSignal,
|
|
197
|
-
): Promise<any> {
|
|
198
|
-
const url = `${this.config.apiBaseUrl}/v0/radar${path}`
|
|
199
|
-
const params = {
|
|
200
|
-
method,
|
|
201
|
-
body: body ? JSON.stringify(body) : null,
|
|
202
|
-
headers: {
|
|
203
|
-
'Content-Type': 'application/json',
|
|
204
|
-
...(this.config.apiKey && { 'X-Api-Key': this.config.apiKey }),
|
|
205
|
-
},
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
try {
|
|
209
|
-
const response = await fetch(url, {
|
|
210
|
-
...params,
|
|
211
|
-
credentials: 'include',
|
|
212
|
-
signal,
|
|
213
|
-
})
|
|
214
|
-
|
|
215
|
-
if (!response.ok) {
|
|
216
|
-
throw new Error('Network response was not ok: ' + response.statusText)
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
if (response.status === 204) {
|
|
220
|
-
return null
|
|
221
|
-
}
|
|
222
|
-
|
|
223
|
-
return await response.json()
|
|
224
|
-
} catch (error: any) {
|
|
225
|
-
if (error?.name === 'AbortError') {
|
|
226
|
-
throw new Error('Request aborted')
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
}
|