@gokiteam/goki-dev 0.2.0 → 0.2.2

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,24 +1,8 @@
1
1
  {
2
2
  "name": "@gokiteam/goki-dev",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Unified local development platform for Goki services",
5
5
  "type": "module",
6
- "main": "./client/dist/index.js",
7
- "types": "./client/dist/index.d.ts",
8
- "exports": {
9
- ".": {
10
- "types": "./client/dist/index.d.ts",
11
- "import": "./client/dist/index.js",
12
- "require": "./client/dist/index.js"
13
- }
14
- },
15
- "typesVersions": {
16
- "*": {
17
- ".": [
18
- "./client/dist/index.d.ts"
19
- ]
20
- }
21
- },
22
6
  "bin": {
23
7
  "goki-dev": "./bin/goki-dev.js",
24
8
  "goki-dev-mcp": "./bin/mcp-server.js",
@@ -28,7 +12,14 @@
28
12
  "bin/",
29
13
  "cli/",
30
14
  "src/",
31
- "client/dist/",
15
+ "ui/build/",
16
+ "docker-compose.yml",
17
+ "docker-compose.services.yml",
18
+ "docker-compose.dev.yml",
19
+ "Dockerfile.backend",
20
+ "Dockerfile.frontend",
21
+ "Dockerfile.dev",
22
+ "nginx.conf",
32
23
  "config.development",
33
24
  "config.test",
34
25
  "guidelines/",
@@ -40,9 +31,11 @@
40
31
  "dev:watch": "dotenv -e config.development node --watch src/Server.js",
41
32
  "dev:ui": "concurrently \"npm run dev\" \"cd ui && npm start\" --names \"backend,frontend\" --prefix-colors \"blue,green\"",
42
33
  "ui:start": "cd ui && npm start",
43
- "ui:build": "cd ui && npm run build",
44
- "build:client": "cd client && npx tsc && echo '{\"type\":\"commonjs\"}' > dist/package.json",
45
- "prepublishOnly": "npm run build:client",
34
+ "build": "cd ui && npm run build && cd ../client && npm run build",
35
+ "prepublishOnly": "npm run build",
36
+ "release": "standard-version && npm run build && npm publish && cd client && npm publish",
37
+ "release:minor": "standard-version --release-as minor && npm run build && npm publish && cd client && npm publish",
38
+ "release:major": "standard-version --release-as major && npm run build && npm publish && cd client && npm publish",
46
39
  "test": "dotenv -e config.test mocha 'tests/**/*.test.js'",
47
40
  "test:api": "dotenv -e config.test mocha 'tests/api/**/*.test.js'",
48
41
  "test:emulation": "dotenv -e config.test mocha 'tests/emulation/**/*.test.js'",
@@ -126,6 +119,7 @@
126
119
  "mqtt": "^5.15.0",
127
120
  "playwright": "^1.58.1",
128
121
  "standard": "^17.1.0",
122
+ "standard-version": "^9.5.0",
129
123
  "supertest": "^6.3.0",
130
124
  "typescript": "^5.9.3"
131
125
  },
@@ -134,5 +128,17 @@
134
128
  "mocha"
135
129
  ]
136
130
  },
131
+ "standard-version": {
132
+ "bumpFiles": [
133
+ {
134
+ "filename": "package.json",
135
+ "type": "json"
136
+ },
137
+ {
138
+ "filename": "client/package.json",
139
+ "type": "json"
140
+ }
141
+ ]
142
+ },
137
143
  "packageManager": "yarn@3.8.7+sha512.bbe7e310ff7fd20dc63b111110f96fe18192234bb0d4f10441fa6b85d2b644c8923db8fbe6d7886257ace948440ab1f83325ad02af457a1806cdc97f03d2508e"
138
144
  }
@@ -15,6 +15,13 @@ export const Controllers = {
15
15
  ctx.reply(result)
16
16
  },
17
17
 
18
+ async waitFor (ctx) {
19
+ const { traceId } = ctx.state
20
+ const { filter, timeout } = ctx.request.body
21
+ const result = await Logic.waitForTraffic({ filter, timeout, traceId })
22
+ ctx.reply(result)
23
+ },
24
+
18
25
  async clear (ctx) {
19
26
  const { traceId } = ctx.state
20
27
  const result = Logic.clear({ traceId })
@@ -1,5 +1,7 @@
1
1
  import { HttpProxy } from '../../singletons/HttpProxy.js'
2
2
 
3
+ const sleep = (ms) => new Promise(resolve => setTimeout(resolve, ms))
4
+
3
5
  export const Logic = {
4
6
  list (params) {
5
7
  const { filter, limit = 50, offset = 0, traceId } = params
@@ -19,6 +21,32 @@ export const Logic = {
19
21
  return { entry, traceId }
20
22
  },
21
23
 
24
+ async waitForTraffic (params) {
25
+ const { filter, timeout = 5000, traceId } = params
26
+ const startTime = Date.now()
27
+ const pollInterval = 100
28
+ const { pathContains, ...equalityFilter } = filter
29
+ try {
30
+ while (Date.now() - startTime < timeout) {
31
+ const { data } = HttpProxy.listTraffic({ filter: equalityFilter, limit: 50 })
32
+ if (data && data.length > 0) {
33
+ for (const entry of data) {
34
+ if (!pathContains) {
35
+ return { entry, foundAt: Date.now() - startTime, traceId }
36
+ }
37
+ if (entry.targetPath && entry.targetPath.includes(pathContains)) {
38
+ return { entry, foundAt: Date.now() - startTime, traceId }
39
+ }
40
+ }
41
+ }
42
+ await sleep(pollInterval)
43
+ }
44
+ return { status: 'error', message: 'Timeout waiting for HTTP traffic', traceId }
45
+ } catch (error) {
46
+ return { status: 'error', message: error.message, traceId }
47
+ }
48
+ },
49
+
22
50
  clear (params) {
23
51
  const { traceId } = params
24
52
  HttpProxy.clearTraffic()
@@ -5,5 +5,6 @@ export const Router = new KoaRouter({ prefix: '/v1/http-traffic' })
5
5
 
6
6
  Router.post('/list', Controllers.list)
7
7
  Router.post('/details', Controllers.details)
8
+ Router.post('/wait-for', Controllers.waitFor)
8
9
  Router.post('/clear', Controllers.clear)
9
10
  Router.post('/stats', Controllers.stats)
@@ -7,7 +7,9 @@ export const Schemas = {
7
7
  targetHost: Joi.string(),
8
8
  sourceService: Joi.string(),
9
9
  statusCode: Joi.number().integer(),
10
- traceId: Joi.string()
10
+ traceId: Joi.string(),
11
+ since: Joi.string().isoDate(),
12
+ until: Joi.string().isoDate()
11
13
  }).optional(),
12
14
  limit: Joi.number().integer().min(1).max(500).default(50),
13
15
  offset: Joi.number().integer().min(0).default(0)
@@ -17,6 +19,18 @@ export const Schemas = {
17
19
  id: Joi.string().required()
18
20
  }),
19
21
 
22
+ waitFor: Joi.object({
23
+ filter: Joi.object({
24
+ method: Joi.string().valid('GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'HEAD', 'OPTIONS'),
25
+ targetHost: Joi.string(),
26
+ sourceService: Joi.string(),
27
+ statusCode: Joi.number().integer(),
28
+ traceId: Joi.string(),
29
+ pathContains: Joi.string()
30
+ }).required(),
31
+ timeout: Joi.number().integer().min(100).max(30000).default(5000)
32
+ }),
33
+
20
34
  clear: Joi.object({}),
21
35
 
22
36
  stats: Joi.object({})
@@ -1,7 +1,7 @@
1
1
  import { execa } from 'execa'
2
2
  import fs from 'fs/promises'
3
+ import os from 'os'
3
4
  import path from 'path'
4
- import { fileURLToPath } from 'url'
5
5
  import { Logic as FirestoreLogic } from '../firestore/Logic.js'
6
6
  import { Logic as DockerLogic } from '../docker/Logic.js'
7
7
  import { Logic as PubSubLogic } from '../pubsub/Logic.js'
@@ -23,10 +23,7 @@ import {
23
23
  PUBSUB_MESSAGE_HISTORY
24
24
  } from '../../db/Tables.js'
25
25
 
26
- const __filename = fileURLToPath(import.meta.url)
27
- const __dirname = path.dirname(__filename)
28
- const PROJECT_ROOT = path.join(__dirname, '../../..')
29
- const SNAPSHOTS_DIR = path.join(PROJECT_ROOT, '.goki-dev/snapshots')
26
+ const SNAPSHOTS_DIR = path.join(os.homedir(), '.goki-dev', 'snapshots')
30
27
 
31
28
  // Ensure snapshot directories exist
32
29
  async function ensureSnapshotDirs () {
@@ -1,4 +1,6 @@
1
1
  import Moment from 'moment'
2
+ import os from 'os'
3
+ import path from 'path'
2
4
 
3
5
  const {
4
6
  NODE_ENV = 'development',
@@ -77,7 +79,7 @@ export const Application = {
77
79
  shadowSubscriptionCheckIntervalMs: parseInt(SHADOW_SUBSCRIPTION_CHECK_INTERVAL_MS) || 5000
78
80
  },
79
81
  storage: {
80
- dataDir: DATA_DIR
82
+ dataDir: DATA_DIR || path.join(os.homedir(), '.goki-dev', 'data')
81
83
  },
82
84
  redis: {
83
85
  host: REDIS_HOST || 'localhost',
@@ -5,7 +5,7 @@ export function registerHttpTrafficTools (server, apiClient) {
5
5
  'http_traffic_list',
6
6
  'List recorded HTTP traffic between microservices (captured by the dev-tools proxy)',
7
7
  {
8
- filter: z.record(z.any()).optional().describe('Optional filter criteria (method, targetHost, sourceService, statusCode, traceId)'),
8
+ filter: z.record(z.any()).optional().describe('Optional filter criteria (method, targetHost, sourceService, statusCode, traceId, since, until)'),
9
9
  limit: z.number().optional().describe('Maximum number of records to return'),
10
10
  offset: z.number().optional().describe('Number of records to skip for pagination')
11
11
  },
@@ -39,6 +39,25 @@ export function registerHttpTrafficTools (server, apiClient) {
39
39
  }
40
40
  )
41
41
 
42
+ server.tool(
43
+ 'http_traffic_wait_for',
44
+ 'Wait for an HTTP traffic entry matching the filter to appear within a timeout (polling). Useful for e2e tests.',
45
+ {
46
+ filter: z.record(z.any()).describe('Required filter criteria (method, targetHost, sourceService, statusCode, traceId, pathContains)'),
47
+ timeout: z.number().optional().describe('Timeout in ms (default: 5000, max: 30000)')
48
+ },
49
+ async ({ filter, timeout }) => {
50
+ try {
51
+ const body = { filter }
52
+ if (timeout !== undefined) body.timeout = timeout
53
+ const data = await apiClient.post('/v1/http-traffic/wait-for', body)
54
+ return { content: [{ type: 'text', text: JSON.stringify(data, null, 2) }] }
55
+ } catch (error) {
56
+ return { content: [{ type: 'text', text: `Failed to wait for HTTP traffic: ${error.message}` }], isError: true }
57
+ }
58
+ }
59
+ )
60
+
42
61
  server.tool(
43
62
  'http_traffic_clear',
44
63
  'Clear all recorded HTTP traffic',
@@ -174,7 +174,17 @@ class HttpProxyClass {
174
174
  offset
175
175
  }
176
176
  if (filter && Object.keys(filter).length > 0) {
177
- listOptions.filter = filter
177
+ const { since, until, ...equalityFilter } = filter
178
+ if (Object.keys(equalityFilter).length > 0) {
179
+ listOptions.filter = equalityFilter
180
+ }
181
+ const conditions = []
182
+ const params = []
183
+ if (since) { conditions.push('created_at >= ?'); params.push(since) }
184
+ if (until) { conditions.push('created_at <= ?'); params.push(until) }
185
+ if (conditions.length > 0) {
186
+ listOptions.rawWhere = { sql: conditions.join(' AND '), params }
187
+ }
178
188
  }
179
189
  return SqliteStore.list(HTTP_TRAFFIC, listOptions)
180
190
  }
@@ -21,10 +21,15 @@ class SqliteStoreClass {
21
21
  initialize (dbPath = null) {
22
22
  if (this.isInitialized) return
23
23
 
24
- const dataDir = Application.storage.dataDir || './data'
24
+ const dataDir = Application.storage.dataDir
25
25
  if (!fs.existsSync(dataDir)) {
26
26
  fs.mkdirSync(dataDir, { recursive: true })
27
27
  }
28
+ if (dataDir.includes('.goki-dev') && fs.existsSync('./data/dev-tools.db')) {
29
+ console.warn('[MIGRATION] Found legacy database at ./data/dev-tools.db')
30
+ console.warn(`[MIGRATION] Database now lives at ${path.join(dataDir, 'dev-tools.db')}`)
31
+ console.warn(`[MIGRATION] Copy manually: cp ./data/dev-tools.db ${path.join(dataDir, 'dev-tools.db')}`)
32
+ }
28
33
 
29
34
  const finalDbPath = dbPath || path.join(dataDir, 'dev-tools.db')
30
35
  this.db = new Database(finalDbPath)
@@ -147,8 +152,12 @@ class SqliteStoreClass {
147
152
  params.push(...where.params)
148
153
  }
149
154
 
150
- const countSql = `SELECT COUNT(*) as count FROM ${tableName}` +
151
- (params.length > 0 ? ` ${this.buildWhereClause(options.where || options.filter).sql}` : '')
155
+ if (options.rawWhere) {
156
+ sql += params.length > 0 ? ` AND ${options.rawWhere.sql}` : ` WHERE ${options.rawWhere.sql}`
157
+ params.push(...options.rawWhere.params)
158
+ }
159
+
160
+ const countSql = sql.replace(/^SELECT \* FROM/, 'SELECT COUNT(*) as count FROM')
152
161
  const totalResult = this.db.prepare(countSql).get(...params)
153
162
  const total = totalResult.count
154
163
 
@@ -0,0 +1,19 @@
1
+ FROM node:20-alpine
2
+
3
+ WORKDIR /app
4
+
5
+ # Copy package files
6
+ COPY package*.json ./
7
+
8
+ # Install dependencies
9
+ RUN npm install
10
+
11
+ # Copy config files (source files will be mounted as volumes)
12
+ COPY tailwind.config.js ./
13
+ COPY postcss.config.js ./
14
+
15
+ # Expose React dev server port
16
+ EXPOSE 9001
17
+
18
+ # Start React dev server
19
+ CMD ["npm", "start"]
@@ -1,332 +0,0 @@
1
- /**
2
- * @gokiteam/goki-dev - Main Client
3
- *
4
- * HTTP client for Goki Developer Tools
5
- */
6
- import { AxiosInstance } from 'axios';
7
- import type * as Types from './types';
8
- export interface DevToolsClientConfig {
9
- baseUrl?: string;
10
- timeout?: number;
11
- }
12
- export declare class PubSubClient {
13
- private client;
14
- constructor(client: AxiosInstance);
15
- private call;
16
- /**
17
- * Extract short topic name from a full path like 'projects/X/topics/Y' -> 'Y'
18
- */
19
- private extractTopicName;
20
- publish(params: {
21
- topic: string;
22
- message: any;
23
- attributes?: Record<string, string>;
24
- traceId?: string;
25
- }): Promise<{
26
- messageIds: string[];
27
- } & {
28
- traceId: string;
29
- }>;
30
- waitForMessage(params: Types.WaitForMessageRequest): Promise<Types.WaitForMessageResponse>;
31
- assertMessagePublished(params: Types.AssertMessagePublishedRequest): Promise<Types.AssertMessagePublishedResponse>;
32
- getMessages(params?: {
33
- filter?: Types.PubSubHistoryFilter;
34
- page?: Types.PageOptions;
35
- traceId?: string;
36
- }): Promise<{
37
- messages: Types.PubSubMessage[];
38
- total: number;
39
- } & {
40
- traceId: string;
41
- }>;
42
- searchMessages(params: {
43
- query: string;
44
- filter?: Partial<Types.PubSubHistoryFilter>;
45
- traceId?: string;
46
- }): Promise<{
47
- messages: Types.PubSubMessage[];
48
- total: number;
49
- } & {
50
- traceId: string;
51
- }>;
52
- listTopics(params?: {
53
- traceId?: string;
54
- }): Promise<{
55
- topics: Types.PubSubTopic[];
56
- total: number;
57
- } & {
58
- traceId: string;
59
- }>;
60
- createTopic(params: {
61
- topic: string;
62
- traceId?: string;
63
- }): Promise<{
64
- topic: Types.PubSubTopic;
65
- } & {
66
- traceId: string;
67
- }>;
68
- deleteTopic(params: {
69
- topic: string;
70
- traceId?: string;
71
- }): Promise<void>;
72
- }
73
- export declare class LoggingClient {
74
- private client;
75
- constructor(client: AxiosInstance);
76
- private call;
77
- getByTrace(params: {
78
- traceId: string;
79
- queryTraceId?: string;
80
- }): Promise<{
81
- traceId: string;
82
- entries: Types.LogEntry[];
83
- count: number;
84
- }>;
85
- list(params?: {
86
- filter?: Types.LogFilter;
87
- page?: Types.PageOptions;
88
- traceId?: string;
89
- }): Promise<{
90
- entries: Types.LogEntry[];
91
- total: number;
92
- } & {
93
- traceId: string;
94
- }>;
95
- clear(params?: {
96
- service?: string;
97
- traceId?: string;
98
- }): Promise<{
99
- deletedCount: number;
100
- } & {
101
- traceId: string;
102
- }>;
103
- waitForLog(params: Types.WaitForLogRequest): Promise<Types.WaitForLogResponse>;
104
- assertNoErrors(params: Types.AssertNoErrorsRequest): Promise<Types.AssertNoErrorsResponse>;
105
- }
106
- export declare class PostgresClient {
107
- private client;
108
- constructor(client: AxiosInstance);
109
- private call;
110
- query(params: Types.PostgresQueryRequest): Promise<Types.PostgresQueryResponse>;
111
- listTables(params: {
112
- database: string;
113
- schema?: string;
114
- traceId?: string;
115
- }): Promise<{
116
- tables: {
117
- name: string;
118
- rowCount: number;
119
- }[];
120
- } & {
121
- traceId: string;
122
- }>;
123
- listRows(params: {
124
- database: string;
125
- schema: string;
126
- table: string;
127
- page?: Types.PageOptions;
128
- traceId?: string;
129
- }): Promise<{
130
- rows: any[];
131
- total: number;
132
- } & {
133
- traceId: string;
134
- }>;
135
- waitForCondition(params: Types.WaitForConditionRequest & {
136
- type: 'postgres';
137
- }): Promise<Types.WaitForConditionResponse>;
138
- }
139
- export declare class RedisClient {
140
- private client;
141
- constructor(client: AxiosInstance);
142
- private call;
143
- get(params: {
144
- key: string;
145
- traceId?: string;
146
- }): Promise<Types.RedisValue>;
147
- scan(params: {
148
- pattern: string;
149
- count?: number;
150
- traceId?: string;
151
- }): Promise<{
152
- keys: Types.RedisKey[];
153
- total: number;
154
- } & {
155
- traceId: string;
156
- }>;
157
- delete(params: {
158
- key: string;
159
- traceId?: string;
160
- }): Promise<{
161
- deleted: boolean;
162
- } & {
163
- traceId: string;
164
- }>;
165
- deletePattern(params: {
166
- pattern: string;
167
- traceId?: string;
168
- }): Promise<{
169
- deletedCount: number;
170
- } & {
171
- traceId: string;
172
- }>;
173
- waitForCondition(params: Types.WaitForConditionRequest & {
174
- type: 'redis';
175
- }): Promise<Types.WaitForConditionResponse>;
176
- }
177
- export declare class FirestoreClient {
178
- private client;
179
- constructor(client: AxiosInstance);
180
- private call;
181
- /**
182
- * Parses a Firestore REST API typed value into a plain JS value.
183
- */
184
- private parseFirestoreValue;
185
- /**
186
- * Parses Firestore REST API fields object into a plain JS object.
187
- */
188
- private parseFirestoreFields;
189
- /**
190
- * Converts a raw Firestore REST API document to a clean FirestoreDocument.
191
- * Raw format: { name: "projects/.../documents/collection/id", fields: { key: { stringValue: "..." } }, ... }
192
- * Clean format: { id: "docId", data: { key: "..." } }
193
- */
194
- private parseRawDocument;
195
- getDocument(params: {
196
- collection: string;
197
- documentId: string;
198
- traceId?: string;
199
- }): Promise<{
200
- document: Types.FirestoreDocument;
201
- }>;
202
- query(params: {
203
- collection: string;
204
- where: Types.FirestoreQuery;
205
- traceId?: string;
206
- }): Promise<{
207
- documents: Types.FirestoreDocument[];
208
- }>;
209
- listDocuments(params: {
210
- collection: string;
211
- page?: Types.PageOptions;
212
- traceId?: string;
213
- }): Promise<{
214
- documents: Types.FirestoreDocument[];
215
- total: number;
216
- }>;
217
- deleteByQuery(params: Types.DeleteByQueryRequest): Promise<Types.DeleteByQueryResponse>;
218
- deleteByPrefix(params: Types.DeleteByPrefixRequest): Promise<Types.DeleteByPrefixResponse>;
219
- deleteBatch(params: Types.DeleteBatchRequest): Promise<Types.DeleteBatchResponse>;
220
- waitForCondition(params: Types.WaitForConditionRequest & {
221
- type: 'firestore';
222
- }): Promise<Types.WaitForConditionResponse>;
223
- }
224
- export declare class MqttClient {
225
- private client;
226
- constructor(client: AxiosInstance);
227
- private call;
228
- listClients(params?: {
229
- traceId?: string;
230
- }): Promise<{
231
- clients: Types.MqttClientInfo[];
232
- } & {
233
- traceId: string;
234
- }>;
235
- getMessages(params?: {
236
- filter?: {
237
- clientId?: string;
238
- topic?: string;
239
- };
240
- page?: Types.PageOptions;
241
- traceId?: string;
242
- }): Promise<{
243
- messages: Types.MqttMessage[];
244
- total: number;
245
- } & {
246
- traceId: string;
247
- }>;
248
- }
249
- export declare class DockerClient {
250
- private client;
251
- constructor(client: AxiosInstance);
252
- private call;
253
- list(params?: {
254
- traceId?: string;
255
- }): Promise<{
256
- data: Types.DockerContainer[];
257
- } & {
258
- traceId: string;
259
- }>;
260
- start(params: {
261
- containerName: string;
262
- traceId?: string;
263
- }): Promise<void>;
264
- stop(params: {
265
- containerName: string;
266
- traceId?: string;
267
- }): Promise<void>;
268
- restart(params: {
269
- containerName: string;
270
- traceId?: string;
271
- }): Promise<void>;
272
- logs(params: {
273
- containerName: string;
274
- lines?: number;
275
- traceId?: string;
276
- }): Promise<{
277
- data: string;
278
- } & {
279
- traceId: string;
280
- }>;
281
- }
282
- export declare class PlatformClient {
283
- private client;
284
- constructor(client: AxiosInstance);
285
- private call;
286
- getStats(params?: {
287
- traceId?: string;
288
- }): Promise<{
289
- stats: Types.PlatformStats;
290
- } & {
291
- traceId: string;
292
- }>;
293
- clearAll(params?: {
294
- traceId?: string;
295
- }): Promise<{
296
- cleared: Record<string, number>;
297
- } & {
298
- traceId: string;
299
- }>;
300
- clearServices(params: Types.ClearServiceDataRequest): Promise<Types.ClearServiceDataResponse>;
301
- export(params?: {
302
- traceId?: string;
303
- }): Promise<{
304
- export: Types.ExportData;
305
- } & {
306
- traceId: string;
307
- }>;
308
- }
309
- export declare class SchedulerClient {
310
- private client;
311
- constructor(client: AxiosInstance);
312
- private call;
313
- triggerTick(params?: {
314
- traceId?: string;
315
- }): Promise<Types.SchedulerTickResponse>;
316
- }
317
- export declare class DevToolsClient {
318
- private client;
319
- private baseUrl;
320
- pubsub: PubSubClient;
321
- logging: LoggingClient;
322
- postgres: PostgresClient;
323
- redis: RedisClient;
324
- firestore: FirestoreClient;
325
- mqtt: MqttClient;
326
- docker: DockerClient;
327
- platform: PlatformClient;
328
- scheduler: SchedulerClient;
329
- constructor(config?: DevToolsClientConfig);
330
- generateTraceId(prefix?: string): string;
331
- }
332
- export * from './types';