@gokiteam/goki-dev 0.2.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/README.md +478 -0
- package/bin/goki-dev.js +452 -0
- package/bin/mcp-server.js +16 -0
- package/bin/secrets-cli.js +302 -0
- package/cli/ComposeOverrideGenerator.js +226 -0
- package/cli/ComposeParser.js +73 -0
- package/cli/ConfigGenerator.js +304 -0
- package/cli/ConfigManager.js +46 -0
- package/cli/DatabaseManager.js +94 -0
- package/cli/DevToolsChecker.js +21 -0
- package/cli/DevToolsDir.js +66 -0
- package/cli/DevToolsManager.js +451 -0
- package/cli/DockerManager.js +138 -0
- package/cli/FunctionManager.js +95 -0
- package/cli/HttpProxyRewriter.js +91 -0
- package/cli/Logger.js +10 -0
- package/cli/McpConfigManager.js +123 -0
- package/cli/NgrokManager.js +431 -0
- package/cli/ProjectCLI.js +2322 -0
- package/cli/PubSubManager.js +129 -0
- package/cli/SnapshotManager.js +88 -0
- package/cli/UiFormatter.js +292 -0
- package/cli/WebhookUrlRewriter.js +32 -0
- package/cli/secrets/BiometricAuth.js +125 -0
- package/cli/secrets/SecretInjector.js +47 -0
- package/cli/secrets/SecretsConfig.js +141 -0
- package/cli/secrets/SecretsDoctor.js +384 -0
- package/cli/secrets/SecretsManager.js +255 -0
- package/client/dist/client.d.ts +332 -0
- package/client/dist/client.js +507 -0
- package/client/dist/helpers.d.ts +62 -0
- package/client/dist/helpers.js +122 -0
- package/client/dist/index.d.ts +59 -0
- package/client/dist/index.js +78 -0
- package/client/dist/package.json +1 -0
- package/client/dist/types.d.ts +280 -0
- package/client/dist/types.js +7 -0
- package/config.development +46 -0
- package/config.test +18 -0
- package/guidelines/CodingStyleGuideline.md +148 -0
- package/guidelines/CommentingGuideline.md +10 -0
- package/guidelines/HttpApiImplementationGuideline.md +137 -0
- package/guidelines/NamingGuideline.md +182 -0
- package/package.json +138 -0
- package/patterns/api/[collectionName]/Controllers.md +62 -0
- package/patterns/api/[collectionName]/Logic.md +154 -0
- package/patterns/api/[collectionName]/Permissions.md +81 -0
- package/patterns/api/[collectionName]/Router.md +83 -0
- package/patterns/api/[collectionName]/Schemas.md +197 -0
- package/patterns/configs/Patterns.md +7 -0
- package/patterns/enums/Patterns.md +24 -0
- package/patterns/errorHandling/Patterns.md +185 -0
- package/patterns/testing/Patterns.md +232 -0
- package/src/Server.js +238 -0
- package/src/api/dashboard/Controllers.js +9 -0
- package/src/api/dashboard/Logic.js +76 -0
- package/src/api/dashboard/Router.js +11 -0
- package/src/api/dashboard/Schemas.js +47 -0
- package/src/api/data/Controllers.js +26 -0
- package/src/api/data/Logic.js +188 -0
- package/src/api/data/Router.js +16 -0
- package/src/api/docker/Controllers.js +33 -0
- package/src/api/docker/Logic.js +268 -0
- package/src/api/docker/Router.js +15 -0
- package/src/api/docker/Schemas.js +80 -0
- package/src/api/docs/Controllers.js +15 -0
- package/src/api/docs/Logic.js +85 -0
- package/src/api/docs/Router.js +12 -0
- package/src/api/export/Controllers.js +30 -0
- package/src/api/export/Logic.js +143 -0
- package/src/api/export/Router.js +18 -0
- package/src/api/export/Schemas.js +104 -0
- package/src/api/firestore/Controllers.js +152 -0
- package/src/api/firestore/Logic.js +474 -0
- package/src/api/firestore/Router.js +23 -0
- package/src/api/functions/Controllers.js +261 -0
- package/src/api/functions/Logic.js +710 -0
- package/src/api/functions/Router.js +50 -0
- package/src/api/functions/Schemas.js +193 -0
- package/src/api/gateway/Controllers.js +72 -0
- package/src/api/gateway/Logic.js +74 -0
- package/src/api/gateway/Router.js +10 -0
- package/src/api/gateway/Schemas.js +19 -0
- package/src/api/health/Controllers.js +14 -0
- package/src/api/health/Logic.js +24 -0
- package/src/api/health/Router.js +12 -0
- package/src/api/httpTraffic/Controllers.js +29 -0
- package/src/api/httpTraffic/Logic.js +33 -0
- package/src/api/httpTraffic/Router.js +9 -0
- package/src/api/httpTraffic/Schemas.js +23 -0
- package/src/api/logging/Controllers.js +80 -0
- package/src/api/logging/Logic.js +461 -0
- package/src/api/logging/Router.js +24 -0
- package/src/api/logging/Schemas.js +43 -0
- package/src/api/mqtt/Controllers.js +17 -0
- package/src/api/mqtt/Logic.js +66 -0
- package/src/api/mqtt/Router.js +12 -0
- package/src/api/postgres/Controllers.js +97 -0
- package/src/api/postgres/Logic.js +221 -0
- package/src/api/postgres/Router.js +21 -0
- package/src/api/pubsub/Controllers.js +236 -0
- package/src/api/pubsub/Logic.js +732 -0
- package/src/api/pubsub/Router.js +41 -0
- package/src/api/pubsub/Schemas.js +355 -0
- package/src/api/redis/Controllers.js +63 -0
- package/src/api/redis/Logic.js +239 -0
- package/src/api/redis/Router.js +21 -0
- package/src/api/scheduler/Controllers.js +27 -0
- package/src/api/scheduler/Logic.js +49 -0
- package/src/api/scheduler/Router.js +16 -0
- package/src/api/services/Controllers.js +26 -0
- package/src/api/services/Logic.js +205 -0
- package/src/api/services/Router.js +14 -0
- package/src/api/services/Schemas.js +66 -0
- package/src/api/snapshots/Controllers.js +37 -0
- package/src/api/snapshots/Logic.js +797 -0
- package/src/api/snapshots/Router.js +15 -0
- package/src/api/snapshots/Schemas.js +23 -0
- package/src/api/webhooks/Controllers.js +49 -0
- package/src/api/webhooks/Logic.js +137 -0
- package/src/api/webhooks/Router.js +12 -0
- package/src/api/webhooks/Schemas.js +31 -0
- package/src/configs/Application.js +147 -0
- package/src/configs/Default.js +13 -0
- package/src/consumers/BlackboxLogsConsumer.js +235 -0
- package/src/consumers/DockerLogsConsumer.js +687 -0
- package/src/db/Tables.js +66 -0
- package/src/db/schemas/firestore.js +18 -0
- package/src/db/schemas/functions.js +65 -0
- package/src/db/schemas/httpTraffic.js +43 -0
- package/src/db/schemas/logging.js +74 -0
- package/src/db/schemas/migrations.js +64 -0
- package/src/db/schemas/mqtt.js +56 -0
- package/src/db/schemas/pubsub.js +90 -0
- package/src/db/schemas/pubsubRegistry.js +22 -0
- package/src/db/schemas/webhooks.js +28 -0
- package/src/emulation/awsiot/Controllers.js +91 -0
- package/src/emulation/awsiot/Logic.js +70 -0
- package/src/emulation/awsiot/Router.js +19 -0
- package/src/emulation/awsiot/Server.js +100 -0
- package/src/emulation/firestore/Server.js +136 -0
- package/src/emulation/logging/Controllers.js +212 -0
- package/src/emulation/logging/Logic.js +416 -0
- package/src/emulation/logging/Router.js +36 -0
- package/src/emulation/logging/Schemas.js +82 -0
- package/src/emulation/logging/Server.js +108 -0
- package/src/emulation/pubsub/Controllers.js +279 -0
- package/src/emulation/pubsub/DefaultTopics.js +162 -0
- package/src/emulation/pubsub/Logic.js +427 -0
- package/src/emulation/pubsub/README.md +309 -0
- package/src/emulation/pubsub/Router.js +33 -0
- package/src/emulation/pubsub/Server.js +104 -0
- package/src/emulation/pubsub/ShadowPoller.js +276 -0
- package/src/emulation/pubsub/ShadowSubscriptionManager.js +199 -0
- package/src/enums/ContainerNames.js +106 -0
- package/src/enums/ErrorReason.js +28 -0
- package/src/enums/FunctionStatuses.js +15 -0
- package/src/enums/FunctionTriggerTypes.js +15 -0
- package/src/enums/GatewayState.js +7 -0
- package/src/enums/ServiceNames.js +68 -0
- package/src/jobs/DatabaseMaintenance.js +184 -0
- package/src/jobs/MessageHistoryCleanup.js +152 -0
- package/src/mcp/ApiClient.js +25 -0
- package/src/mcp/Server.js +52 -0
- package/src/mcp/prompts/debugging.js +104 -0
- package/src/mcp/resources/platform.js +118 -0
- package/src/mcp/tools/data.js +84 -0
- package/src/mcp/tools/docker.js +166 -0
- package/src/mcp/tools/firestore.js +162 -0
- package/src/mcp/tools/functions.js +380 -0
- package/src/mcp/tools/httpTraffic.js +69 -0
- package/src/mcp/tools/logging.js +174 -0
- package/src/mcp/tools/mqtt.js +37 -0
- package/src/mcp/tools/postgres.js +130 -0
- package/src/mcp/tools/pubsub.js +316 -0
- package/src/mcp/tools/redis.js +146 -0
- package/src/mcp/tools/services.js +169 -0
- package/src/mcp/tools/snapshots.js +88 -0
- package/src/mcp/tools/webhooks.js +115 -0
- package/src/middleware/DevProxy.js +67 -0
- package/src/middleware/ErrorCatcher.js +35 -0
- package/src/middleware/HttpProxy.js +215 -0
- package/src/middleware/Reply.js +24 -0
- package/src/middleware/TraceId.js +9 -0
- package/src/middleware/WebhookProxy.js +234 -0
- package/src/protocols/mqtt/Broker.js +92 -0
- package/src/protocols/mqtt/Handlers.js +175 -0
- package/src/protocols/mqtt/PubSubBridge.js +162 -0
- package/src/protocols/mqtt/Server.js +116 -0
- package/src/runtime/FunctionRunner.js +179 -0
- package/src/services/AppGatewayService.js +582 -0
- package/src/singletons/FirestoreBroadcaster.js +367 -0
- package/src/singletons/FunctionTriggerDispatcher.js +456 -0
- package/src/singletons/FunctionsService.js +418 -0
- package/src/singletons/HttpProxy.js +224 -0
- package/src/singletons/LogBroadcaster.js +159 -0
- package/src/singletons/Logger.js +49 -0
- package/src/singletons/MemoryJsonStore.js +175 -0
- package/src/singletons/MessageBroadcaster.js +190 -0
- package/src/singletons/PostgresBroadcaster.js +367 -0
- package/src/singletons/PostgresClient.js +180 -0
- package/src/singletons/RedisClient.js +184 -0
- package/src/singletons/SqliteStore.js +480 -0
- package/src/singletons/TickService.js +151 -0
- package/src/singletons/WebhookProxy.js +223 -0
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @gokiteam/goki-dev - Client SDK
|
|
3
|
+
*
|
|
4
|
+
* HTTP client for interacting with the Goki Developer Tools platform.
|
|
5
|
+
*
|
|
6
|
+
* @example Simple usage (singleton)
|
|
7
|
+
* ```typescript
|
|
8
|
+
* import { devTools } from '@gokiteam/goki-dev'
|
|
9
|
+
*
|
|
10
|
+
* const traceId = devTools.generateTraceId('user-login-test')
|
|
11
|
+
*
|
|
12
|
+
* // Wait for message
|
|
13
|
+
* const message = await devTools.pubsub.waitForMessage({
|
|
14
|
+
* filter: {
|
|
15
|
+
* topic: 'user-events',
|
|
16
|
+
* predicate: {
|
|
17
|
+
* jsonPath: '$.event',
|
|
18
|
+
* operator: 'equals',
|
|
19
|
+
* value: 'user-login'
|
|
20
|
+
* }
|
|
21
|
+
* },
|
|
22
|
+
* timeout: 5000,
|
|
23
|
+
* traceId
|
|
24
|
+
* })
|
|
25
|
+
*
|
|
26
|
+
* // Verify logs
|
|
27
|
+
* const errors = await devTools.logging.assertNoErrors({ traceId })
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* @example Advanced usage (custom instance)
|
|
31
|
+
* ```typescript
|
|
32
|
+
* import { DevToolsClient } from '@gokiteam/goki-dev'
|
|
33
|
+
*
|
|
34
|
+
* const devTools = new DevToolsClient({
|
|
35
|
+
* baseUrl: 'http://custom-host:9000',
|
|
36
|
+
* timeout: 60000
|
|
37
|
+
* })
|
|
38
|
+
* ```
|
|
39
|
+
*/
|
|
40
|
+
export { DevToolsClient } from './client';
|
|
41
|
+
export * from './types';
|
|
42
|
+
export * from './helpers';
|
|
43
|
+
import { DevToolsClient } from './client';
|
|
44
|
+
/**
|
|
45
|
+
* Default singleton instance of DevToolsClient
|
|
46
|
+
*
|
|
47
|
+
* Configured from environment variables:
|
|
48
|
+
* - DEV_TOOLS_BASE: Base URL (default: http://localhost:9000)
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* ```typescript
|
|
52
|
+
* import { devTools } from '@gokiteam/goki-dev'
|
|
53
|
+
*
|
|
54
|
+
* const traceId = devTools.generateTraceId('test')
|
|
55
|
+
* const message = await devTools.pubsub.waitForMessage({ ... })
|
|
56
|
+
* const logs = await devTools.logging.getByTrace({ traceId })
|
|
57
|
+
* ```
|
|
58
|
+
*/
|
|
59
|
+
export declare const devTools: DevToolsClient;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @gokiteam/goki-dev - Client SDK
|
|
4
|
+
*
|
|
5
|
+
* HTTP client for interacting with the Goki Developer Tools platform.
|
|
6
|
+
*
|
|
7
|
+
* @example Simple usage (singleton)
|
|
8
|
+
* ```typescript
|
|
9
|
+
* import { devTools } from '@gokiteam/goki-dev'
|
|
10
|
+
*
|
|
11
|
+
* const traceId = devTools.generateTraceId('user-login-test')
|
|
12
|
+
*
|
|
13
|
+
* // Wait for message
|
|
14
|
+
* const message = await devTools.pubsub.waitForMessage({
|
|
15
|
+
* filter: {
|
|
16
|
+
* topic: 'user-events',
|
|
17
|
+
* predicate: {
|
|
18
|
+
* jsonPath: '$.event',
|
|
19
|
+
* operator: 'equals',
|
|
20
|
+
* value: 'user-login'
|
|
21
|
+
* }
|
|
22
|
+
* },
|
|
23
|
+
* timeout: 5000,
|
|
24
|
+
* traceId
|
|
25
|
+
* })
|
|
26
|
+
*
|
|
27
|
+
* // Verify logs
|
|
28
|
+
* const errors = await devTools.logging.assertNoErrors({ traceId })
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @example Advanced usage (custom instance)
|
|
32
|
+
* ```typescript
|
|
33
|
+
* import { DevToolsClient } from '@gokiteam/goki-dev'
|
|
34
|
+
*
|
|
35
|
+
* const devTools = new DevToolsClient({
|
|
36
|
+
* baseUrl: 'http://custom-host:9000',
|
|
37
|
+
* timeout: 60000
|
|
38
|
+
* })
|
|
39
|
+
* ```
|
|
40
|
+
*/
|
|
41
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
42
|
+
if (k2 === undefined) k2 = k;
|
|
43
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
44
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
45
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
46
|
+
}
|
|
47
|
+
Object.defineProperty(o, k2, desc);
|
|
48
|
+
}) : (function(o, m, k, k2) {
|
|
49
|
+
if (k2 === undefined) k2 = k;
|
|
50
|
+
o[k2] = m[k];
|
|
51
|
+
}));
|
|
52
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
53
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
54
|
+
};
|
|
55
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
56
|
+
exports.devTools = exports.DevToolsClient = void 0;
|
|
57
|
+
var client_1 = require("./client");
|
|
58
|
+
Object.defineProperty(exports, "DevToolsClient", { enumerable: true, get: function () { return client_1.DevToolsClient; } });
|
|
59
|
+
__exportStar(require("./types"), exports);
|
|
60
|
+
__exportStar(require("./helpers"), exports);
|
|
61
|
+
// Export default singleton instance for convenience
|
|
62
|
+
const client_2 = require("./client");
|
|
63
|
+
/**
|
|
64
|
+
* Default singleton instance of DevToolsClient
|
|
65
|
+
*
|
|
66
|
+
* Configured from environment variables:
|
|
67
|
+
* - DEV_TOOLS_BASE: Base URL (default: http://localhost:9000)
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* ```typescript
|
|
71
|
+
* import { devTools } from '@gokiteam/goki-dev'
|
|
72
|
+
*
|
|
73
|
+
* const traceId = devTools.generateTraceId('test')
|
|
74
|
+
* const message = await devTools.pubsub.waitForMessage({ ... })
|
|
75
|
+
* const logs = await devTools.logging.getByTrace({ traceId })
|
|
76
|
+
* ```
|
|
77
|
+
*/
|
|
78
|
+
exports.devTools = new client_2.DevToolsClient();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"type":"commonjs"}
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @gokiteam/goki-dev - Type Definitions
|
|
3
|
+
*
|
|
4
|
+
* TypeScript types for the Goki Developer Tools Client SDK
|
|
5
|
+
*/
|
|
6
|
+
export interface StandardResponse<T = any> {
|
|
7
|
+
success: boolean;
|
|
8
|
+
status: number;
|
|
9
|
+
message: string;
|
|
10
|
+
data: T & {
|
|
11
|
+
traceId: string;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export interface PageOptions {
|
|
15
|
+
limit?: number;
|
|
16
|
+
offset?: number;
|
|
17
|
+
}
|
|
18
|
+
export interface TimeRange {
|
|
19
|
+
start: string;
|
|
20
|
+
end: string;
|
|
21
|
+
}
|
|
22
|
+
export interface PubSubMessage {
|
|
23
|
+
id: string;
|
|
24
|
+
message_id: string;
|
|
25
|
+
data: string;
|
|
26
|
+
attributes?: Record<string, string>;
|
|
27
|
+
ordering_key?: string;
|
|
28
|
+
publish_time: string;
|
|
29
|
+
topic: string;
|
|
30
|
+
sender?: string;
|
|
31
|
+
view_count: number;
|
|
32
|
+
last_viewed_at?: number;
|
|
33
|
+
created_at: number;
|
|
34
|
+
}
|
|
35
|
+
export interface PubSubTopic {
|
|
36
|
+
name: string;
|
|
37
|
+
labels?: Record<string, string>;
|
|
38
|
+
}
|
|
39
|
+
export interface PubSubSubscription {
|
|
40
|
+
name: string;
|
|
41
|
+
topic: string;
|
|
42
|
+
ackDeadlineSeconds: number;
|
|
43
|
+
pushConfig?: Record<string, any>;
|
|
44
|
+
}
|
|
45
|
+
export interface PubSubHistoryFilter {
|
|
46
|
+
topic?: string;
|
|
47
|
+
sender?: string;
|
|
48
|
+
timeRange?: TimeRange;
|
|
49
|
+
}
|
|
50
|
+
export type LogSeverity = 'DEFAULT' | 'DEBUG' | 'INFO' | 'NOTICE' | 'WARNING' | 'ERROR' | 'CRITICAL' | 'ALERT' | 'EMERGENCY';
|
|
51
|
+
export interface LogEntry {
|
|
52
|
+
logName: string;
|
|
53
|
+
resource: {
|
|
54
|
+
type: string;
|
|
55
|
+
labels: Record<string, string>;
|
|
56
|
+
};
|
|
57
|
+
timestamp: string;
|
|
58
|
+
severity: LogSeverity;
|
|
59
|
+
textPayload?: string;
|
|
60
|
+
jsonPayload?: Record<string, any>;
|
|
61
|
+
trace?: string;
|
|
62
|
+
insertId: string;
|
|
63
|
+
}
|
|
64
|
+
export interface LogFilter {
|
|
65
|
+
service?: string;
|
|
66
|
+
severity?: LogSeverity[];
|
|
67
|
+
timeRange?: TimeRange;
|
|
68
|
+
}
|
|
69
|
+
export interface PostgresQueryRequest {
|
|
70
|
+
database: string;
|
|
71
|
+
query: string;
|
|
72
|
+
params?: any[];
|
|
73
|
+
traceId?: string;
|
|
74
|
+
}
|
|
75
|
+
export interface PostgresQueryResponse {
|
|
76
|
+
rows: any[];
|
|
77
|
+
rowCount: number;
|
|
78
|
+
traceId: string;
|
|
79
|
+
}
|
|
80
|
+
export interface RedisKey {
|
|
81
|
+
key: string;
|
|
82
|
+
type: string;
|
|
83
|
+
ttl: number;
|
|
84
|
+
}
|
|
85
|
+
export interface RedisValue {
|
|
86
|
+
key: string;
|
|
87
|
+
type: string;
|
|
88
|
+
value: string;
|
|
89
|
+
ttl: number;
|
|
90
|
+
}
|
|
91
|
+
export interface FirestoreDocument {
|
|
92
|
+
id: string;
|
|
93
|
+
data: Record<string, any>;
|
|
94
|
+
}
|
|
95
|
+
export interface FirestoreQuery {
|
|
96
|
+
field: string;
|
|
97
|
+
op: '==' | '!=' | '<' | '<=' | '>' | '>=' | 'in' | 'not-in' | 'array-contains';
|
|
98
|
+
value: any;
|
|
99
|
+
}
|
|
100
|
+
export interface FirestoreWhereClause {
|
|
101
|
+
field: string;
|
|
102
|
+
operator: '==' | '!=' | '<' | '<=' | '>' | '>=' | 'in' | 'not-in' | 'array-contains';
|
|
103
|
+
value: any;
|
|
104
|
+
}
|
|
105
|
+
export interface DeleteByQueryRequest {
|
|
106
|
+
collection: string;
|
|
107
|
+
where: FirestoreWhereClause;
|
|
108
|
+
traceId?: string;
|
|
109
|
+
}
|
|
110
|
+
export interface DeleteByQueryResponse {
|
|
111
|
+
deletedCount: number;
|
|
112
|
+
traceId: string;
|
|
113
|
+
}
|
|
114
|
+
export interface DeleteByPrefixRequest {
|
|
115
|
+
collection: string;
|
|
116
|
+
prefix: string;
|
|
117
|
+
traceId?: string;
|
|
118
|
+
}
|
|
119
|
+
export interface DeleteByPrefixResponse {
|
|
120
|
+
deletedCount: number;
|
|
121
|
+
traceId: string;
|
|
122
|
+
}
|
|
123
|
+
export interface DeleteBatchRequest {
|
|
124
|
+
collection: string;
|
|
125
|
+
documentIds: string[];
|
|
126
|
+
traceId?: string;
|
|
127
|
+
}
|
|
128
|
+
export interface DeleteBatchResponse {
|
|
129
|
+
deletedCount: number;
|
|
130
|
+
failedIds: string[];
|
|
131
|
+
traceId: string;
|
|
132
|
+
}
|
|
133
|
+
export interface MqttClientInfo {
|
|
134
|
+
clientId: string;
|
|
135
|
+
connected: boolean;
|
|
136
|
+
connectedAt: string;
|
|
137
|
+
subscriptions: string[];
|
|
138
|
+
}
|
|
139
|
+
export interface MqttMessage {
|
|
140
|
+
clientId: string;
|
|
141
|
+
topic: string;
|
|
142
|
+
payload: string;
|
|
143
|
+
qos: 0 | 1 | 2;
|
|
144
|
+
timestamp: string;
|
|
145
|
+
}
|
|
146
|
+
export interface WaitForMessageRequest {
|
|
147
|
+
filter: {
|
|
148
|
+
topic: string;
|
|
149
|
+
predicate?: {
|
|
150
|
+
jsonPath: string;
|
|
151
|
+
operator: 'equals' | 'notEquals' | 'contains' | 'greaterThan' | 'lessThan';
|
|
152
|
+
value: any;
|
|
153
|
+
};
|
|
154
|
+
sender?: string;
|
|
155
|
+
};
|
|
156
|
+
timeout?: number;
|
|
157
|
+
traceId?: string;
|
|
158
|
+
}
|
|
159
|
+
export interface WaitForMessageResponse {
|
|
160
|
+
message: PubSubMessage;
|
|
161
|
+
foundAt: number;
|
|
162
|
+
traceId: string;
|
|
163
|
+
}
|
|
164
|
+
export interface WaitForLogRequest {
|
|
165
|
+
filter: {
|
|
166
|
+
traceId?: string;
|
|
167
|
+
service?: string;
|
|
168
|
+
severity?: LogSeverity;
|
|
169
|
+
textContains?: string;
|
|
170
|
+
};
|
|
171
|
+
timeout?: number;
|
|
172
|
+
traceId?: string;
|
|
173
|
+
}
|
|
174
|
+
export interface WaitForLogResponse {
|
|
175
|
+
entry: LogEntry;
|
|
176
|
+
foundAt: number;
|
|
177
|
+
traceId: string;
|
|
178
|
+
}
|
|
179
|
+
export interface WaitForConditionRequest {
|
|
180
|
+
type: 'postgres' | 'redis' | 'firestore';
|
|
181
|
+
condition: {
|
|
182
|
+
database?: string;
|
|
183
|
+
query?: string;
|
|
184
|
+
params?: any[];
|
|
185
|
+
key?: string;
|
|
186
|
+
collection?: string;
|
|
187
|
+
documentId?: string;
|
|
188
|
+
expect: Record<string, any>;
|
|
189
|
+
};
|
|
190
|
+
timeout?: number;
|
|
191
|
+
pollInterval?: number;
|
|
192
|
+
traceId?: string;
|
|
193
|
+
}
|
|
194
|
+
export interface WaitForConditionResponse {
|
|
195
|
+
met: boolean;
|
|
196
|
+
foundAt: number;
|
|
197
|
+
actualValue?: any;
|
|
198
|
+
traceId: string;
|
|
199
|
+
}
|
|
200
|
+
export interface AssertMessagePublishedRequest {
|
|
201
|
+
filter: {
|
|
202
|
+
topic: string;
|
|
203
|
+
since?: string;
|
|
204
|
+
dataContains?: string;
|
|
205
|
+
attributesMatch?: Record<string, string>;
|
|
206
|
+
};
|
|
207
|
+
traceId?: string;
|
|
208
|
+
}
|
|
209
|
+
export interface AssertMessagePublishedResponse {
|
|
210
|
+
found: boolean;
|
|
211
|
+
count: number;
|
|
212
|
+
firstMatch?: Partial<PubSubMessage>;
|
|
213
|
+
traceId: string;
|
|
214
|
+
}
|
|
215
|
+
export interface AssertNoErrorsRequest {
|
|
216
|
+
traceId: string;
|
|
217
|
+
sinceTimestamp?: string;
|
|
218
|
+
}
|
|
219
|
+
export interface AssertNoErrorsResponse {
|
|
220
|
+
hasErrors: boolean;
|
|
221
|
+
errorCount: number;
|
|
222
|
+
criticalCount: number;
|
|
223
|
+
errors?: Partial<LogEntry>[];
|
|
224
|
+
traceId: string;
|
|
225
|
+
}
|
|
226
|
+
export interface ClearServiceDataRequest {
|
|
227
|
+
services: ('pubsub' | 'logging' | 'mqtt' | 'redis' | 'postgres' | 'firestore')[];
|
|
228
|
+
keepSystemData?: boolean;
|
|
229
|
+
traceId?: string;
|
|
230
|
+
}
|
|
231
|
+
export interface ClearServiceDataResponse {
|
|
232
|
+
cleared: Record<string, number>;
|
|
233
|
+
traceId: string;
|
|
234
|
+
}
|
|
235
|
+
export interface SchedulerTickRequest {
|
|
236
|
+
traceId?: string;
|
|
237
|
+
}
|
|
238
|
+
export interface SchedulerTickResponse {
|
|
239
|
+
tickTime: string;
|
|
240
|
+
published: boolean;
|
|
241
|
+
traceId: string;
|
|
242
|
+
}
|
|
243
|
+
export interface PlatformStats {
|
|
244
|
+
topics: number;
|
|
245
|
+
subscriptions: number;
|
|
246
|
+
messages: number;
|
|
247
|
+
logEntries: number;
|
|
248
|
+
mqttClients: number;
|
|
249
|
+
mqttMessages: number;
|
|
250
|
+
}
|
|
251
|
+
export interface ExportData {
|
|
252
|
+
pubsub: {
|
|
253
|
+
topics: PubSubTopic[];
|
|
254
|
+
subscriptions: PubSubSubscription[];
|
|
255
|
+
messages: PubSubMessage[];
|
|
256
|
+
};
|
|
257
|
+
logging: {
|
|
258
|
+
entries: LogEntry[];
|
|
259
|
+
};
|
|
260
|
+
mqtt: {
|
|
261
|
+
clients: MqttClientInfo[];
|
|
262
|
+
messages: MqttMessage[];
|
|
263
|
+
};
|
|
264
|
+
}
|
|
265
|
+
export interface DockerContainer {
|
|
266
|
+
name: string;
|
|
267
|
+
containerName: string;
|
|
268
|
+
displayName: string;
|
|
269
|
+
description: string;
|
|
270
|
+
status: 'running' | 'stopped' | 'created' | 'restarting' | 'paused' | 'unknown';
|
|
271
|
+
statusText: string;
|
|
272
|
+
uptime: string | null;
|
|
273
|
+
ports: number | null;
|
|
274
|
+
image: string;
|
|
275
|
+
capabilities: {
|
|
276
|
+
canStart: boolean;
|
|
277
|
+
canStop: boolean;
|
|
278
|
+
canRestart: boolean;
|
|
279
|
+
};
|
|
280
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
NODE_ENV=development
|
|
2
|
+
|
|
3
|
+
# Server Ports
|
|
4
|
+
WEB_UI_PORT=9000
|
|
5
|
+
LOGGING_PORT=8087
|
|
6
|
+
MQTT_PORT=8883
|
|
7
|
+
AWS_IOT_PORT=8086
|
|
8
|
+
FIRESTORE_PORT=8080
|
|
9
|
+
|
|
10
|
+
# Pub/Sub (Official Emulator)
|
|
11
|
+
PUBSUB_EMULATOR_HOST=localhost:8085
|
|
12
|
+
PUBSUB_PROJECT_ID=tipi-development
|
|
13
|
+
SHADOW_POLL_INTERVAL_MS=200
|
|
14
|
+
SHADOW_SUBSCRIPTION_CHECK_INTERVAL_MS=5000
|
|
15
|
+
|
|
16
|
+
# Firestore
|
|
17
|
+
FIRESTORE_PROJECT_ID=goki-dev-local
|
|
18
|
+
|
|
19
|
+
# Storage
|
|
20
|
+
DATA_DIR=./data
|
|
21
|
+
AUTO_FLUSH_INTERVAL_MS=5000
|
|
22
|
+
|
|
23
|
+
# Redis (for app data)
|
|
24
|
+
REDIS_HOST=localhost
|
|
25
|
+
REDIS_PORT=6379
|
|
26
|
+
|
|
27
|
+
# Redis for logs (optional - defaults to REDIS_HOST/PORT if not specified)
|
|
28
|
+
# Uncomment to use separate Redis instance for logs:
|
|
29
|
+
# REDIS_LOGS_HOST=localhost
|
|
30
|
+
# REDIS_LOGS_PORT=6380
|
|
31
|
+
|
|
32
|
+
# Postgres
|
|
33
|
+
POSTGRES_HOST=localhost
|
|
34
|
+
POSTGRES_PORT=5432
|
|
35
|
+
POSTGRES_USER=postgres
|
|
36
|
+
POSTGRES_PASSWORD=postgres
|
|
37
|
+
|
|
38
|
+
# Logging
|
|
39
|
+
LOG_LEVEL=debug
|
|
40
|
+
|
|
41
|
+
# App Gateway
|
|
42
|
+
APP_GATEWAY_PROPERTY_ID=550e8400-e29b-41d4-a716-446655440000
|
|
43
|
+
APP_GATEWAY_DEVICE_NATIVE_URL=http://localhost:3000
|
|
44
|
+
APP_GATEWAY_DEVICE_SIMULATOR_URL=http://localhost:3001
|
|
45
|
+
APP_GATEWAY_SCAN_INTERVAL_SECONDS=30
|
|
46
|
+
APP_GATEWAY_AUTO_START=true
|
package/config.test
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
NODE_ENV=test
|
|
2
|
+
|
|
3
|
+
# Server Ports
|
|
4
|
+
WEB_UI_PORT=9001
|
|
5
|
+
PUBSUB_PORT=8086
|
|
6
|
+
LOGGING_PORT=8088
|
|
7
|
+
MQTT_PORT=8884
|
|
8
|
+
|
|
9
|
+
# Storage
|
|
10
|
+
DATA_DIR=./data-test
|
|
11
|
+
AUTO_FLUSH_INTERVAL_MS=1000
|
|
12
|
+
|
|
13
|
+
# Redis
|
|
14
|
+
REDIS_HOST=localhost
|
|
15
|
+
REDIS_PORT=6380
|
|
16
|
+
|
|
17
|
+
# Logging
|
|
18
|
+
LOG_LEVEL=error
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# Coding Style
|
|
2
|
+
|
|
3
|
+
We are using [**Standard Javascript Style**](https://standardjs.com/rules.html) as the coding convention. Please read the documentation. You can find further information in this [**link**](https://github.com/standard/eslint-config-standard) as well.
|
|
4
|
+
## Guideline
|
|
5
|
+
All rules are not checked by the linter, so the developer should follow them consciously:
|
|
6
|
+
### Don't put extra empty lines and spaces
|
|
7
|
+
|
|
8
|
+
```plain
|
|
9
|
+
// Bad 😖
|
|
10
|
+
async create(ctx) {
|
|
11
|
+
const { body } = ctx.request
|
|
12
|
+
ctx.body = await SendRequest({
|
|
13
|
+
endpoint: Endpoint.base(BaseUrls.user).post('/users'),
|
|
14
|
+
body
|
|
15
|
+
})
|
|
16
|
+
},
|
|
17
|
+
|
|
18
|
+
async update(ctx) {
|
|
19
|
+
// ... some code ...
|
|
20
|
+
},
|
|
21
|
+
|
|
22
|
+
// Good 😌
|
|
23
|
+
async create (ctx) {
|
|
24
|
+
const {
|
|
25
|
+
body
|
|
26
|
+
} = ctx.request
|
|
27
|
+
|
|
28
|
+
ctx.body = await SendRequest(
|
|
29
|
+
{
|
|
30
|
+
endpoint: Endpoint.base(BaseUrls.user).post('/users'),
|
|
31
|
+
body
|
|
32
|
+
}
|
|
33
|
+
)
|
|
34
|
+
},
|
|
35
|
+
async update (ctx) {
|
|
36
|
+
// ... some code ...
|
|
37
|
+
},
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Single argument instead of multiple arguments
|
|
41
|
+
Pass a single object as an argument to your functions and destructure it.
|
|
42
|
+
|
|
43
|
+
```plain
|
|
44
|
+
// Bad 😖
|
|
45
|
+
async create (users, hostels, roles) {
|
|
46
|
+
// ... some code ...
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
// Good 😌
|
|
50
|
+
async create ({ users, hostels, roles }) {
|
|
51
|
+
// ... some code ...
|
|
52
|
+
},
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Async/await patterns
|
|
56
|
+
|
|
57
|
+
Always use async/await instead of callbacks or raw promises:
|
|
58
|
+
|
|
59
|
+
```plain
|
|
60
|
+
// Good 😌
|
|
61
|
+
async function getDevice (deviceId) {
|
|
62
|
+
const device = await Device.get(deviceId)
|
|
63
|
+
return device.mask()
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// Bad 😖
|
|
67
|
+
function getDevice (deviceId) {
|
|
68
|
+
return Device.get(deviceId).then(device => device.mask())
|
|
69
|
+
}
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### Destructuring patterns
|
|
73
|
+
|
|
74
|
+
Destructure function parameters and assignments:
|
|
75
|
+
|
|
76
|
+
```plain
|
|
77
|
+
// Good 😌
|
|
78
|
+
async function create ({ data, traceId }) {
|
|
79
|
+
const { deviceId, propertyId } = data
|
|
80
|
+
// ... logic
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// Bad 😖
|
|
84
|
+
async function create (params) {
|
|
85
|
+
const data = params.data
|
|
86
|
+
const traceId = params.traceId
|
|
87
|
+
// ... logic
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Function chaining
|
|
92
|
+
|
|
93
|
+
Chain ODM methods for cleaner code:
|
|
94
|
+
|
|
95
|
+
```plain
|
|
96
|
+
// Good 😌
|
|
97
|
+
device
|
|
98
|
+
.assign({ status: 'active' })
|
|
99
|
+
.replaceNested('settings.wifi.enabled', true)
|
|
100
|
+
|
|
101
|
+
await device.update()
|
|
102
|
+
|
|
103
|
+
// Bad 😖
|
|
104
|
+
device.assign({ status: 'active' })
|
|
105
|
+
device.replaceNested('settings.wifi.enabled', true)
|
|
106
|
+
await device.update()
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
### Functional programming
|
|
110
|
+
|
|
111
|
+
Prefer pure functions in logic layer:
|
|
112
|
+
|
|
113
|
+
```plain
|
|
114
|
+
// Good 😌 - Pure function
|
|
115
|
+
export function calculateBatteryLevel ({ voltage, capacity }) {
|
|
116
|
+
return Math.floor((voltage / capacity) * 100)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// Bad 😖 - Side effects
|
|
120
|
+
let batteryLevel = 0
|
|
121
|
+
export function calculateBatteryLevel ({ voltage, capacity }) {
|
|
122
|
+
batteryLevel = Math.floor((voltage / capacity) * 100)
|
|
123
|
+
return batteryLevel
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### No empty lines inside function bodies
|
|
128
|
+
|
|
129
|
+
```plain
|
|
130
|
+
// Good 😌
|
|
131
|
+
async function create (params) {
|
|
132
|
+
const { data, traceId } = params
|
|
133
|
+
const device = new Device(data)
|
|
134
|
+
await device.create()
|
|
135
|
+
return { device: device.mask() }
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Bad 😖
|
|
139
|
+
async function create (params) {
|
|
140
|
+
const { data, traceId } = params
|
|
141
|
+
|
|
142
|
+
const device = new Device(data)
|
|
143
|
+
|
|
144
|
+
await device.create()
|
|
145
|
+
|
|
146
|
+
return { device: device.mask() }
|
|
147
|
+
}
|
|
148
|
+
```
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Commenting
|
|
2
|
+
|
|
3
|
+
We include important notes and messages for readers in our code. Avoid adding excessive or unnecessary comments.
|
|
4
|
+
In the development phase, these tags help you to focus on the code and not forget any vital information.
|
|
5
|
+
* `TODO`: No problem, but additional code needs to be written, usually when you are skipping something.
|
|
6
|
+
* `FIXME`: This works, but it could be improved. (usually, code written in a hurry that needs rewriting).
|
|
7
|
+
* `BUG`: A logical problem exists that affects system output.
|
|
8
|
+
* `NOTE`: An important note for a specific code section.
|
|
9
|
+
|
|
10
|
+
Never use `TODO` as a general tag instead of using specific tags like `FIXME`
|