@gokiteam/goki-dev-client 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/dist/client.js ADDED
@@ -0,0 +1,557 @@
1
+ "use strict";
2
+ /**
3
+ * @gokiteam/goki-dev-client - Main Client
4
+ *
5
+ * HTTP client for Goki Developer Tools
6
+ */
7
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
8
+ if (k2 === undefined) k2 = k;
9
+ var desc = Object.getOwnPropertyDescriptor(m, k);
10
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
11
+ desc = { enumerable: true, get: function() { return m[k]; } };
12
+ }
13
+ Object.defineProperty(o, k2, desc);
14
+ }) : (function(o, m, k, k2) {
15
+ if (k2 === undefined) k2 = k;
16
+ o[k2] = m[k];
17
+ }));
18
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
19
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
20
+ };
21
+ var __importDefault = (this && this.__importDefault) || function (mod) {
22
+ return (mod && mod.__esModule) ? mod : { "default": mod };
23
+ };
24
+ Object.defineProperty(exports, "__esModule", { value: true });
25
+ exports.DevToolsClient = exports.HttpTrafficClient = exports.SchedulerClient = exports.PlatformClient = exports.DockerClient = exports.MqttClient = exports.FirestoreClient = exports.RedisClient = exports.PostgresClient = exports.LoggingClient = exports.PubSubClient = void 0;
26
+ const axios_1 = __importDefault(require("axios"));
27
+ // ============================================================================
28
+ // PubSub Client
29
+ // ============================================================================
30
+ class PubSubClient {
31
+ constructor(client) {
32
+ this.client = client;
33
+ }
34
+ async call(endpoint, data = {}) {
35
+ const response = await this.client.post(endpoint, data);
36
+ return response.data;
37
+ }
38
+ /**
39
+ * Extract short topic name from a full path like 'projects/X/topics/Y' -> 'Y'
40
+ */
41
+ extractTopicName(topic) {
42
+ const match = topic.match(/^projects\/[^/]+\/topics\/(.+)$/);
43
+ return match ? match[1] : topic;
44
+ }
45
+ async publish(params) {
46
+ const result = await this.call('/v1/pubsub/messages/publish', {
47
+ topicName: this.extractTopicName(params.topic),
48
+ message: params.message,
49
+ attributes: params.attributes,
50
+ traceId: params.traceId
51
+ });
52
+ return result.data;
53
+ }
54
+ async waitForMessage(params) {
55
+ const result = await this.call('/v1/pubsub/messages/wait-for', params);
56
+ return result.data;
57
+ }
58
+ async assertMessagePublished(params) {
59
+ const result = await this.call('/v1/pubsub/messages/assert-published', params);
60
+ return result.data;
61
+ }
62
+ async getMessages(params = {}) {
63
+ const result = await this.call('/v1/pubsub/messages/history', {
64
+ filter: params.filter,
65
+ page: params.page,
66
+ traceId: params.traceId
67
+ });
68
+ return result.data;
69
+ }
70
+ async searchMessages(params) {
71
+ const result = await this.call('/v1/pubsub/messages/search', {
72
+ query: params.query,
73
+ searchIn: ['data', 'attributes'],
74
+ filter: params.filter,
75
+ traceId: params.traceId
76
+ });
77
+ return result.data;
78
+ }
79
+ async listTopics(params = {}) {
80
+ const result = await this.call('/v1/pubsub/topics/list', {
81
+ traceId: params.traceId
82
+ });
83
+ return result.data;
84
+ }
85
+ async createTopic(params) {
86
+ const result = await this.call('/v1/pubsub/topics/create', {
87
+ topicName: this.extractTopicName(params.topic),
88
+ traceId: params.traceId
89
+ });
90
+ return result.data;
91
+ }
92
+ async deleteTopic(params) {
93
+ await this.call('/v1/pubsub/topics/delete', {
94
+ topicName: this.extractTopicName(params.topic),
95
+ traceId: params.traceId
96
+ });
97
+ }
98
+ }
99
+ exports.PubSubClient = PubSubClient;
100
+ // ============================================================================
101
+ // Logging Client
102
+ // ============================================================================
103
+ class LoggingClient {
104
+ constructor(client) {
105
+ this.client = client;
106
+ }
107
+ async call(endpoint, data = {}) {
108
+ const response = await this.client.post(endpoint, data);
109
+ return response.data;
110
+ }
111
+ async getByTrace(params) {
112
+ const result = await this.call(`/v1/logging/trace/${params.traceId}`, { traceId: params.queryTraceId || `query-${params.traceId}` });
113
+ return result.data.trace;
114
+ }
115
+ async list(params = {}) {
116
+ const result = await this.call('/v1/logging/entries/list', {
117
+ filter: params.filter,
118
+ page: params.page,
119
+ traceId: params.traceId
120
+ });
121
+ return result.data;
122
+ }
123
+ async clear(params = {}) {
124
+ const result = await this.call('/v1/logging/entries/clear', {
125
+ service: params.service,
126
+ traceId: params.traceId
127
+ });
128
+ return result.data;
129
+ }
130
+ async waitForLog(params) {
131
+ const result = await this.call('/v1/logging/entries/wait-for', params);
132
+ return result.data;
133
+ }
134
+ async assertNoErrors(params) {
135
+ const result = await this.call('/v1/logging/entries/assert-no-errors', params);
136
+ return result.data;
137
+ }
138
+ }
139
+ exports.LoggingClient = LoggingClient;
140
+ // ============================================================================
141
+ // PostgreSQL Client
142
+ // ============================================================================
143
+ class PostgresClient {
144
+ constructor(client) {
145
+ this.client = client;
146
+ }
147
+ async call(endpoint, data = {}) {
148
+ const response = await this.client.post(endpoint, data);
149
+ return response.data;
150
+ }
151
+ async query(params) {
152
+ const result = await this.call('/v1/postgres/query/execute', params);
153
+ return result.data;
154
+ }
155
+ async listTables(params) {
156
+ const result = await this.call('/v1/postgres/tables/list', {
157
+ database: params.database,
158
+ schema: params.schema || 'public',
159
+ traceId: params.traceId
160
+ });
161
+ return result.data;
162
+ }
163
+ async listRows(params) {
164
+ const result = await this.call('/v1/postgres/rows/list', {
165
+ database: params.database,
166
+ schema: params.schema,
167
+ table: params.table,
168
+ page: params.page,
169
+ traceId: params.traceId
170
+ });
171
+ return result.data;
172
+ }
173
+ async waitForCondition(params) {
174
+ const result = await this.call('/v1/postgres/rows/wait-for', params);
175
+ return result.data;
176
+ }
177
+ }
178
+ exports.PostgresClient = PostgresClient;
179
+ // ============================================================================
180
+ // Redis Client
181
+ // ============================================================================
182
+ class RedisClient {
183
+ constructor(client) {
184
+ this.client = client;
185
+ }
186
+ async call(endpoint, data = {}) {
187
+ const response = await this.client.post(endpoint, data);
188
+ return response.data;
189
+ }
190
+ async get(params) {
191
+ const result = await this.call('/v1/redis/keys/get', {
192
+ key: params.key,
193
+ traceId: params.traceId
194
+ });
195
+ return result.data;
196
+ }
197
+ async scan(params) {
198
+ const result = await this.call('/v1/redis/keys/scan', {
199
+ pattern: params.pattern,
200
+ count: params.count || 100,
201
+ traceId: params.traceId
202
+ });
203
+ return result.data;
204
+ }
205
+ async delete(params) {
206
+ const result = await this.call('/v1/redis/keys/delete', {
207
+ key: params.key,
208
+ traceId: params.traceId
209
+ });
210
+ return result.data;
211
+ }
212
+ async deletePattern(params) {
213
+ const result = await this.call('/v1/redis/keys/delete-all', {
214
+ pattern: params.pattern,
215
+ traceId: params.traceId
216
+ });
217
+ return result.data;
218
+ }
219
+ async waitForCondition(params) {
220
+ const result = await this.call('/v1/redis/keys/wait-for', params);
221
+ return result.data;
222
+ }
223
+ }
224
+ exports.RedisClient = RedisClient;
225
+ // ============================================================================
226
+ // Firestore Client
227
+ // ============================================================================
228
+ class FirestoreClient {
229
+ constructor(client) {
230
+ this.client = client;
231
+ }
232
+ async call(endpoint, data = {}) {
233
+ const response = await this.client.post(endpoint, data);
234
+ return response.data;
235
+ }
236
+ /**
237
+ * Parses a Firestore REST API typed value into a plain JS value.
238
+ */
239
+ parseFirestoreValue(value) {
240
+ if (!value || typeof value !== 'object')
241
+ return value;
242
+ if (value.stringValue !== undefined)
243
+ return value.stringValue;
244
+ if (value.integerValue !== undefined)
245
+ return Number(value.integerValue);
246
+ if (value.doubleValue !== undefined)
247
+ return value.doubleValue;
248
+ if (value.booleanValue !== undefined)
249
+ return value.booleanValue;
250
+ if (value.nullValue !== undefined)
251
+ return null;
252
+ if (value.timestampValue !== undefined)
253
+ return value.timestampValue;
254
+ if (value.mapValue)
255
+ return this.parseFirestoreFields(value.mapValue.fields || {});
256
+ if (value.arrayValue)
257
+ return (value.arrayValue.values || []).map((v) => this.parseFirestoreValue(v));
258
+ if (value.geoPointValue)
259
+ return value.geoPointValue;
260
+ if (value.referenceValue !== undefined)
261
+ return value.referenceValue;
262
+ if (value.bytesValue !== undefined)
263
+ return value.bytesValue;
264
+ return value;
265
+ }
266
+ /**
267
+ * Parses Firestore REST API fields object into a plain JS object.
268
+ */
269
+ parseFirestoreFields(fields) {
270
+ const result = {};
271
+ for (const [key, value] of Object.entries(fields)) {
272
+ result[key] = this.parseFirestoreValue(value);
273
+ }
274
+ return result;
275
+ }
276
+ /**
277
+ * Converts a raw Firestore REST API document to a clean FirestoreDocument.
278
+ * Raw format: { name: "projects/.../documents/collection/id", fields: { key: { stringValue: "..." } }, ... }
279
+ * Clean format: { id: "docId", data: { key: "..." } }
280
+ */
281
+ parseRawDocument(rawDoc) {
282
+ const name = rawDoc?.name || '';
283
+ const id = name.split('/').pop() || '';
284
+ const data = rawDoc?.fields ? this.parseFirestoreFields(rawDoc.fields) : {};
285
+ return { id, data };
286
+ }
287
+ async getDocument(params) {
288
+ const result = await this.call('/v1/firestore/documents/get', {
289
+ collectionPath: params.collection,
290
+ documentId: params.documentId,
291
+ traceId: params.traceId
292
+ });
293
+ const rawDocument = result.data.document;
294
+ return { document: this.parseRawDocument(rawDocument) };
295
+ }
296
+ async query(params) {
297
+ const result = await this.call('/v1/firestore/query/execute', {
298
+ collectionPath: params.collection,
299
+ where: params.where,
300
+ traceId: params.traceId
301
+ });
302
+ const documents = (result.data.documents || []).map((doc) => this.parseRawDocument(doc));
303
+ return { documents };
304
+ }
305
+ async listDocuments(params) {
306
+ const result = await this.call('/v1/firestore/documents/list', {
307
+ collectionPath: params.collection,
308
+ page: params.page,
309
+ traceId: params.traceId
310
+ });
311
+ const documents = (result.data.documents || []).map((doc) => this.parseRawDocument(doc));
312
+ return { documents, total: result.data.total };
313
+ }
314
+ async deleteByQuery(params) {
315
+ const result = await this.call('/v1/firestore/documents/delete-by-query', {
316
+ collectionPath: params.collection,
317
+ where: params.where,
318
+ traceId: params.traceId
319
+ });
320
+ return { deletedCount: result.data.deletedCount, traceId: result.data.traceId };
321
+ }
322
+ async deleteByPrefix(params) {
323
+ const result = await this.call('/v1/firestore/documents/delete-by-prefix', {
324
+ collectionPath: params.collection,
325
+ prefix: params.prefix,
326
+ traceId: params.traceId
327
+ });
328
+ return { deletedCount: result.data.deletedCount, traceId: result.data.traceId };
329
+ }
330
+ async deleteBatch(params) {
331
+ const result = await this.call('/v1/firestore/documents/delete-batch', {
332
+ collectionPath: params.collection,
333
+ documentIds: params.documentIds,
334
+ traceId: params.traceId
335
+ });
336
+ return {
337
+ deletedCount: result.data.deletedCount,
338
+ failedIds: result.data.failedIds,
339
+ traceId: result.data.traceId
340
+ };
341
+ }
342
+ async waitForCondition(params) {
343
+ const result = await this.call('/v1/firestore/documents/wait-for', params);
344
+ return result.data;
345
+ }
346
+ }
347
+ exports.FirestoreClient = FirestoreClient;
348
+ // ============================================================================
349
+ // MQTT Client
350
+ // ============================================================================
351
+ class MqttClient {
352
+ constructor(client) {
353
+ this.client = client;
354
+ }
355
+ async call(endpoint, data = {}) {
356
+ const response = await this.client.post(endpoint, data);
357
+ return response.data;
358
+ }
359
+ async listClients(params = {}) {
360
+ const result = await this.call('/v1/mqtt/clients/list', {
361
+ traceId: params.traceId
362
+ });
363
+ return result.data;
364
+ }
365
+ async getMessages(params = {}) {
366
+ const result = await this.call('/v1/mqtt/messages/list', {
367
+ filter: params.filter,
368
+ page: params.page,
369
+ traceId: params.traceId
370
+ });
371
+ return result.data;
372
+ }
373
+ }
374
+ exports.MqttClient = MqttClient;
375
+ // ============================================================================
376
+ // Docker Client
377
+ // ============================================================================
378
+ class DockerClient {
379
+ constructor(client) {
380
+ this.client = client;
381
+ }
382
+ async call(endpoint, data = {}) {
383
+ const response = await this.client.post(endpoint, data);
384
+ return response.data;
385
+ }
386
+ async list(params = {}) {
387
+ const result = await this.call('/v1/docker/containers/list', {
388
+ traceId: params.traceId
389
+ });
390
+ return result.data;
391
+ }
392
+ async start(params) {
393
+ await this.call('/v1/docker/containers/start', {
394
+ containerName: params.containerName,
395
+ traceId: params.traceId
396
+ });
397
+ }
398
+ async stop(params) {
399
+ await this.call('/v1/docker/containers/stop', {
400
+ containerName: params.containerName,
401
+ traceId: params.traceId
402
+ });
403
+ }
404
+ async restart(params) {
405
+ await this.call('/v1/docker/containers/restart', {
406
+ containerName: params.containerName,
407
+ traceId: params.traceId
408
+ });
409
+ }
410
+ async logs(params) {
411
+ const result = await this.call('/v1/docker/containers/logs', {
412
+ containerName: params.containerName,
413
+ lines: params.lines || 100,
414
+ traceId: params.traceId
415
+ });
416
+ return result.data;
417
+ }
418
+ }
419
+ exports.DockerClient = DockerClient;
420
+ // ============================================================================
421
+ // Platform Client
422
+ // ============================================================================
423
+ class PlatformClient {
424
+ constructor(client) {
425
+ this.client = client;
426
+ }
427
+ async call(endpoint, data = {}) {
428
+ const response = await this.client.post(endpoint, data);
429
+ return response.data;
430
+ }
431
+ async getStats(params = {}) {
432
+ const result = await this.call('/v1/dashboard/stats', {
433
+ traceId: params.traceId
434
+ });
435
+ return result.data;
436
+ }
437
+ async clearAll(params = {}) {
438
+ const result = await this.call('/v1/data/clear', {
439
+ confirm: true,
440
+ traceId: params.traceId
441
+ });
442
+ return result.data;
443
+ }
444
+ async clearServices(params) {
445
+ const result = await this.call('/v1/data/clear-services', params);
446
+ return result.data;
447
+ }
448
+ async export(params = {}) {
449
+ const result = await this.call('/v1/data/export', {
450
+ traceId: params.traceId
451
+ });
452
+ return result.data;
453
+ }
454
+ }
455
+ exports.PlatformClient = PlatformClient;
456
+ // ============================================================================
457
+ // Scheduler Client
458
+ // ============================================================================
459
+ class SchedulerClient {
460
+ constructor(client) {
461
+ this.client = client;
462
+ }
463
+ async call(endpoint, data = {}) {
464
+ const response = await this.client.post(endpoint, data);
465
+ return response.data;
466
+ }
467
+ async triggerTick(params = {}) {
468
+ const result = await this.call('/v1/scheduler/tick/trigger', {
469
+ traceId: params.traceId
470
+ });
471
+ return result.data;
472
+ }
473
+ }
474
+ exports.SchedulerClient = SchedulerClient;
475
+ // ============================================================================
476
+ // HTTP Traffic Client
477
+ // ============================================================================
478
+ class HttpTrafficClient {
479
+ constructor(client) {
480
+ this.client = client;
481
+ }
482
+ async call(endpoint, data = {}) {
483
+ const response = await this.client.post(endpoint, data);
484
+ return response.data;
485
+ }
486
+ async list(params = {}) {
487
+ const result = await this.call('/v1/http-traffic/list', {
488
+ filter: params.filter,
489
+ limit: params.limit,
490
+ offset: params.offset,
491
+ traceId: params.traceId
492
+ });
493
+ return result.data;
494
+ }
495
+ async getDetails(params) {
496
+ const result = await this.call('/v1/http-traffic/details', {
497
+ id: params.id,
498
+ traceId: params.traceId
499
+ });
500
+ return result.data;
501
+ }
502
+ async clear(params = {}) {
503
+ const result = await this.call('/v1/http-traffic/clear', {
504
+ traceId: params.traceId
505
+ });
506
+ return result.data;
507
+ }
508
+ async waitFor(params) {
509
+ const result = await this.call('/v1/http-traffic/wait-for', {
510
+ filter: params.filter,
511
+ timeout: params.timeout,
512
+ traceId: params.traceId
513
+ });
514
+ return result.data;
515
+ }
516
+ async stats(params = {}) {
517
+ const result = await this.call('/v1/http-traffic/stats', {
518
+ traceId: params.traceId
519
+ });
520
+ return result.data;
521
+ }
522
+ }
523
+ exports.HttpTrafficClient = HttpTrafficClient;
524
+ // ============================================================================
525
+ // Main DevTools Client
526
+ // ============================================================================
527
+ class DevToolsClient {
528
+ constructor(config = {}) {
529
+ this.baseUrl = config.baseUrl || process.env.DEV_TOOLS_BASE || 'http://localhost:9000';
530
+ this.client = axios_1.default.create({
531
+ baseURL: this.baseUrl,
532
+ timeout: config.timeout || 30000,
533
+ headers: {
534
+ 'Content-Type': 'application/json'
535
+ }
536
+ });
537
+ this.pubsub = new PubSubClient(this.client);
538
+ this.logging = new LoggingClient(this.client);
539
+ this.postgres = new PostgresClient(this.client);
540
+ this.redis = new RedisClient(this.client);
541
+ this.firestore = new FirestoreClient(this.client);
542
+ this.mqtt = new MqttClient(this.client);
543
+ this.docker = new DockerClient(this.client);
544
+ this.platform = new PlatformClient(this.client);
545
+ this.scheduler = new SchedulerClient(this.client);
546
+ this.httpTraffic = new HttpTrafficClient(this.client);
547
+ }
548
+ // ============================================================================
549
+ // Utility Methods
550
+ // ============================================================================
551
+ generateTraceId(prefix = 'e2e') {
552
+ return `${prefix}-${Date.now()}-${Math.random().toString(36).substring(7)}`;
553
+ }
554
+ }
555
+ exports.DevToolsClient = DevToolsClient;
556
+ // Export types
557
+ __exportStar(require("./types"), exports);
@@ -0,0 +1,62 @@
1
+ /**
2
+ * @gokiteam/goki-dev - Helper Utilities
3
+ *
4
+ * Common test helpers and utilities
5
+ */
6
+ import { DevToolsClient } from './client';
7
+ import type * as Types from './types';
8
+ /**
9
+ * Wait for async operation with custom polling
10
+ */
11
+ export declare function waitFor<T>(predicate: () => Promise<T | null>, options?: {
12
+ timeout?: number;
13
+ interval?: number;
14
+ timeoutMessage?: string;
15
+ }): Promise<T>;
16
+ /**
17
+ * Sleep for specified milliseconds
18
+ */
19
+ export declare function sleep(ms: number): Promise<void>;
20
+ /**
21
+ * Verify multi-system state helper
22
+ */
23
+ export interface VerifyAcrossServicesOptions {
24
+ database?: {
25
+ database: string;
26
+ query: string;
27
+ params?: any[];
28
+ };
29
+ redis?: {
30
+ key: string;
31
+ };
32
+ pubsub?: {
33
+ filter: Types.PubSubHistoryFilter;
34
+ };
35
+ firestore?: {
36
+ collection: string;
37
+ documentId: string;
38
+ };
39
+ logging?: boolean;
40
+ }
41
+ export interface VerifyAcrossServicesResults {
42
+ database?: any[];
43
+ redis?: any;
44
+ pubsub?: Types.PubSubMessage[];
45
+ firestore?: Types.FirestoreDocument;
46
+ logs?: Types.LogEntry[];
47
+ }
48
+ export declare function verifyAcrossServices(client: DevToolsClient, traceId: string, expectations: VerifyAcrossServicesOptions): Promise<VerifyAcrossServicesResults>;
49
+ /**
50
+ * Find error logs in a trace
51
+ */
52
+ export declare function findErrorLogs(client: DevToolsClient, traceId: string): Promise<Types.LogEntry[]>;
53
+ /**
54
+ * Test suite builder
55
+ */
56
+ export interface TestContext {
57
+ client: DevToolsClient;
58
+ traceId: string;
59
+ cleanup: Array<() => Promise<void>>;
60
+ }
61
+ export declare function createTestContext(clientConfig?: import('./client').DevToolsClientConfig): Promise<TestContext>;
62
+ export declare function runTest(name: string, testFn: (ctx: TestContext) => Promise<void>, clientConfig?: import('./client').DevToolsClientConfig): Promise<void>;