@deadragdoll/tellymcp 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example.client +93 -0
- package/.env.example.gateway +120 -0
- package/CHANGELOG.md +155 -0
- package/LICENSE +21 -0
- package/README-ru.md +338 -0
- package/README.md +1262 -0
- package/STANDALONE-ru.md +266 -0
- package/STANDALONE.md +266 -0
- package/TOOLS.md +1296 -0
- package/config/templates/env.both.template +83 -0
- package/config/templates/env.client.template +60 -0
- package/config/templates/env.gateway.template +82 -0
- package/dist/cli.js +636 -0
- package/dist/index.js +17 -0
- package/dist/lib/logfeed/store.js +52 -0
- package/dist/lib/middlewares/tracer.js +172 -0
- package/dist/lib/mixins/db.js +267 -0
- package/dist/lib/mixins/logfeed.js +34 -0
- package/dist/lib/mixins/session.errors.js +142 -0
- package/dist/lib/moleculer.js +2 -0
- package/dist/lib/trace.js +147 -0
- package/dist/lib/traceContext.js +116 -0
- package/dist/moleculer.config.js +274 -0
- package/dist/services/features/telegram-mcp/approval.service.js +33 -0
- package/dist/services/features/telegram-mcp/browser.service.js +42 -0
- package/dist/services/features/telegram-mcp/collaboration.service.js +53 -0
- package/dist/services/features/telegram-mcp/ensuredb.service.js +337 -0
- package/dist/services/features/telegram-mcp/gateway-delivery.service.js +378 -0
- package/dist/services/features/telegram-mcp/gateway-loopback.js +10 -0
- package/dist/services/features/telegram-mcp/gateway-rmq.service.js +294 -0
- package/dist/services/features/telegram-mcp/gateway-socket.service.js +1463 -0
- package/dist/services/features/telegram-mcp/gateway.service.js +1141 -0
- package/dist/services/features/telegram-mcp/inbox.service.js +33 -0
- package/dist/services/features/telegram-mcp/mcp-http.service.js +76 -0
- package/dist/services/features/telegram-mcp/mcp-server.service.js +127 -0
- package/dist/services/features/telegram-mcp/notify.service.js +33 -0
- package/dist/services/features/telegram-mcp/pair.service.js +33 -0
- package/dist/services/features/telegram-mcp/runtime.service.js +36 -0
- package/dist/services/features/telegram-mcp/session-context.service.js +33 -0
- package/dist/services/features/telegram-mcp/src/app/bootstrap/runtime.js +103 -0
- package/dist/services/features/telegram-mcp/src/app/config/env.js +317 -0
- package/dist/services/features/telegram-mcp/src/app/http.js +774 -0
- package/dist/services/features/telegram-mcp/src/app/index.js +2 -0
- package/dist/services/features/telegram-mcp/src/app/providers/mcp/server.js +13 -0
- package/dist/services/features/telegram-mcp/src/app/providers/redis/client.js +18 -0
- package/dist/services/features/telegram-mcp/src/app/webapp/assets.js +740 -0
- package/dist/services/features/telegram-mcp/src/app/webapp/auth.js +267 -0
- package/dist/services/features/telegram-mcp/src/app/webapp/relay.js +69 -0
- package/dist/services/features/telegram-mcp/src/app/webapp/tmux.js +9 -0
- package/dist/services/features/telegram-mcp/src/entities/auth/model/types.js +2 -0
- package/dist/services/features/telegram-mcp/src/entities/browser/model/types.js +2 -0
- package/dist/services/features/telegram-mcp/src/entities/collaboration/model/types.js +2 -0
- package/dist/services/features/telegram-mcp/src/entities/inbox/model/types.js +2 -0
- package/dist/services/features/telegram-mcp/src/entities/request/model/schema.js +545 -0
- package/dist/services/features/telegram-mcp/src/entities/request/model/types.js +2 -0
- package/dist/services/features/telegram-mcp/src/entities/session/model/types.js +2 -0
- package/dist/services/features/telegram-mcp/src/features/ask-user/model/askUserTelegram.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserClearLogsTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserClickTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserCloseTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserComputedStyleTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserConsoleTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserDomTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserErrorsTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserFillTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserNetworkFailuresTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserOpenTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserPressTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserReloadTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserScreenshotTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserService.js +689 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserWaitForTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/browser/model/browserWaitForUrlTool.js +28 -0
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/backend.js +2 -0
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/collaborationService.js +26 -0
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/localCollaborationBackend.js +390 -0
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerFileService.js +102 -0
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerFileTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/collaboration/model/sendPartnerNoteTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/distributed-client/model/gatewayCollaborationBackend.js +69 -0
- package/dist/services/features/telegram-mcp/src/features/distributed-gateway/model/gatewayHttpService.js +657 -0
- package/dist/services/features/telegram-mcp/src/features/distributed-gateway/model/gatewayReplyResolution.js +17 -0
- package/dist/services/features/telegram-mcp/src/features/inbox/model/deleteTelegramInboxMessageTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/inbox/model/getTelegramInboxCountTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/inbox/model/getTelegramInboxTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/inbox/model/inboxService.js +77 -0
- package/dist/services/features/telegram-mcp/src/features/notify/model/notifyService.js +93 -0
- package/dist/services/features/telegram-mcp/src/features/notify/model/notifyTelegramTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/pair-session/model/clearSessionPairingTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/pair-session/model/createSessionPairCodeTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/pair-session/model/generatePairCode.js +202 -0
- package/dist/services/features/telegram-mcp/src/features/session-context/model/clearSessionContextTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/session-context/model/getSessionContextTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/session-context/model/getTmuxTargetTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/session-context/model/renameSessionTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/session-context/model/sessionContextService.js +409 -0
- package/dist/services/features/telegram-mcp/src/features/session-context/model/setSessionContextTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/session-context/model/setTmuxTargetTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/features/tools-sync/model/refreshToolsMarkdownService.js +123 -0
- package/dist/services/features/telegram-mcp/src/features/tools-sync/model/refreshToolsMarkdownTool.js +33 -0
- package/dist/services/features/telegram-mcp/src/processes/human-approval/model/orchestrator.js +243 -0
- package/dist/services/features/telegram-mcp/src/shared/api/storage/contract.js +2 -0
- package/dist/services/features/telegram-mcp/src/shared/api/tool-registry/registry.js +8 -0
- package/dist/services/features/telegram-mcp/src/shared/api/tool-registry/types.js +2 -0
- package/dist/services/features/telegram-mcp/src/shared/api/transport/contract.js +2 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/object-storage/minioExchangeStore.js +86 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/redis/stateStore.js +436 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/collabSemantics.js +21 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/collabUi.js +87 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/messageFormat.js +60 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/proxyFetch.js +46 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/telegram/transport.js +6534 -0
- package/dist/services/features/telegram-mcp/src/shared/integrations/tmux/client.js +280 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/ids/ids.js +34 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/logger/logger.js +68 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/project-identity/projectIdentity.js +223 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/redact-secrets/redactSecrets.js +22 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/truncate/truncate.js +12 -0
- package/dist/services/features/telegram-mcp/src/shared/lib/version/versionHandshake.js +124 -0
- package/dist/services/features/telegram-mcp/src/shared/types/common.js +2 -0
- package/dist/services/features/telegram-mcp/standalone-http.service.js +113 -0
- package/dist/services/features/telegram-mcp/tools-sync.service.js +33 -0
- package/package.json +110 -0
- package/scripts/postinstall.js +60 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.logFeedStore = exports.stringifyLogArgs = void 0;
|
|
4
|
+
const node_events_1 = require("node:events");
|
|
5
|
+
const node_util_1 = require("node:util");
|
|
6
|
+
const DEFAULT_BUFFER_SIZE = +(process.env.LOGFEED_BUFFER_SIZE || 500);
|
|
7
|
+
const ANSI_PATTERN = /\u001b\[.*?m/g;
|
|
8
|
+
class LogFeedStore extends node_events_1.EventEmitter {
|
|
9
|
+
buffer = [];
|
|
10
|
+
maxSize;
|
|
11
|
+
seq = 0;
|
|
12
|
+
constructor(maxSize = DEFAULT_BUFFER_SIZE) {
|
|
13
|
+
super();
|
|
14
|
+
this.maxSize = Number.isFinite(maxSize) && maxSize > 0 ? maxSize : DEFAULT_BUFFER_SIZE;
|
|
15
|
+
}
|
|
16
|
+
push(entry) {
|
|
17
|
+
const nextSeq = ++this.seq;
|
|
18
|
+
const item = {
|
|
19
|
+
id: `${entry.ts}-${nextSeq}`,
|
|
20
|
+
seq: nextSeq,
|
|
21
|
+
...entry,
|
|
22
|
+
};
|
|
23
|
+
this.buffer.push(item);
|
|
24
|
+
if (this.buffer.length > this.maxSize) {
|
|
25
|
+
this.buffer.splice(0, this.buffer.length - this.maxSize);
|
|
26
|
+
}
|
|
27
|
+
this.emit("entry", item);
|
|
28
|
+
return item;
|
|
29
|
+
}
|
|
30
|
+
list(limit = 200) {
|
|
31
|
+
const normalizedLimit = Number.isFinite(limit) && limit > 0 ? Math.min(limit, this.maxSize) : 200;
|
|
32
|
+
return this.buffer.slice(-normalizedLimit);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const stringifyLogArgs = (args) => args
|
|
36
|
+
.map(arg => {
|
|
37
|
+
if (arg == null) {
|
|
38
|
+
return "<null>";
|
|
39
|
+
}
|
|
40
|
+
if (typeof arg === "string") {
|
|
41
|
+
return arg.replace(ANSI_PATTERN, "");
|
|
42
|
+
}
|
|
43
|
+
return `\r\n${(0, node_util_1.inspect)(arg, {
|
|
44
|
+
showHidden: false,
|
|
45
|
+
depth: 4,
|
|
46
|
+
compact: false,
|
|
47
|
+
breakLength: Number.POSITIVE_INFINITY,
|
|
48
|
+
})}`;
|
|
49
|
+
})
|
|
50
|
+
.join(" ");
|
|
51
|
+
exports.stringifyLogArgs = stringifyLogArgs;
|
|
52
|
+
exports.logFeedStore = new LogFeedStore();
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createTracerMiddleware = void 0;
|
|
4
|
+
const traceContext_1 = require("../traceContext");
|
|
5
|
+
const trace_1 = require("../trace");
|
|
6
|
+
const shouldSkipTrace = (actionName, ctx) => Boolean(ctx?.meta?.$traceInternal ||
|
|
7
|
+
!actionName ||
|
|
8
|
+
actionName === "context" ||
|
|
9
|
+
actionName === "graphql.publish" ||
|
|
10
|
+
(actionName === "rest" && ctx?.params?.req?.url === "/api/graphql"));
|
|
11
|
+
const createTracerMiddleware = () => {
|
|
12
|
+
let broker = null;
|
|
13
|
+
const resolveTracer = (action) => {
|
|
14
|
+
const rawName = String(action?.rawName || action?.name || "");
|
|
15
|
+
if (action?.tracer)
|
|
16
|
+
return { tracer: action.tracer, source: "action.tracer" };
|
|
17
|
+
if (action?.schema?.tracer)
|
|
18
|
+
return { tracer: action.schema.tracer, source: "action.schema.tracer" };
|
|
19
|
+
if (action?.service?.schema?.actions?.[rawName]?.tracer) {
|
|
20
|
+
return {
|
|
21
|
+
tracer: action.service.schema.actions[rawName].tracer,
|
|
22
|
+
source: "service.schema.actions[rawName].tracer",
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
return {};
|
|
26
|
+
};
|
|
27
|
+
const callTrace = async (ctx, actionName, params, silent = false) => {
|
|
28
|
+
if (!broker) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
try {
|
|
32
|
+
return await broker.call(actionName, params, {
|
|
33
|
+
requestID: ctx.requestID,
|
|
34
|
+
meta: {
|
|
35
|
+
user: ctx.meta?.user,
|
|
36
|
+
$traceInternal: true,
|
|
37
|
+
},
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
if (!silent) {
|
|
42
|
+
broker.logger.warn("Tracer call failed", {
|
|
43
|
+
actionName,
|
|
44
|
+
sourceAction: ctx.action?.name || null,
|
|
45
|
+
error: error instanceof Error ? error.message : String(error),
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
return {
|
|
52
|
+
created(localBroker) {
|
|
53
|
+
broker = localBroker;
|
|
54
|
+
},
|
|
55
|
+
localAction(next, action) {
|
|
56
|
+
const actionName = String(action?.rawName || action?.name || "");
|
|
57
|
+
const serviceName = String(action?.service?.name || "");
|
|
58
|
+
return async function traceAction(ctx) {
|
|
59
|
+
if (serviceName === "trace" || shouldSkipTrace(actionName, ctx)) {
|
|
60
|
+
return next(ctx);
|
|
61
|
+
}
|
|
62
|
+
const resolvedTracer = resolveTracer(ctx?.action || action);
|
|
63
|
+
const tracer = resolvedTracer.tracer;
|
|
64
|
+
let traceMeta = null;
|
|
65
|
+
const startSessionName = tracer?.startSession;
|
|
66
|
+
const tracerTag = tracer?.tag;
|
|
67
|
+
const shouldStartRootSession = Boolean(startSessionName);
|
|
68
|
+
if (!shouldStartRootSession) {
|
|
69
|
+
traceMeta = await (0, traceContext_1.loadTraceContext)();
|
|
70
|
+
}
|
|
71
|
+
let startedSession = false;
|
|
72
|
+
if (shouldStartRootSession) {
|
|
73
|
+
await (0, traceContext_1.deleteTraceContext)().catch(() => null);
|
|
74
|
+
const session = (await callTrace(ctx, "trace.startSession", {
|
|
75
|
+
name: startSessionName,
|
|
76
|
+
tag: tracerTag || null,
|
|
77
|
+
source: actionName,
|
|
78
|
+
meta: (0, trace_1.sanitizeTraceValue)({
|
|
79
|
+
action: actionName,
|
|
80
|
+
params: ctx.params,
|
|
81
|
+
}),
|
|
82
|
+
}, false));
|
|
83
|
+
if (session?.session_id) {
|
|
84
|
+
traceMeta = {
|
|
85
|
+
sessionId: String(session.session_id),
|
|
86
|
+
name: startSessionName ?? null,
|
|
87
|
+
tag: tracerTag || null,
|
|
88
|
+
rootAction: actionName,
|
|
89
|
+
startedBy: actionName,
|
|
90
|
+
};
|
|
91
|
+
await (0, traceContext_1.saveTraceContext)(traceMeta);
|
|
92
|
+
startedSession = true;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
const sessionId = String(traceMeta?.sessionId || "").trim();
|
|
96
|
+
const hasSession = Boolean(sessionId);
|
|
97
|
+
const startedAt = Date.now();
|
|
98
|
+
if (hasSession) {
|
|
99
|
+
await (0, traceContext_1.touchTraceContext)().catch(() => null);
|
|
100
|
+
await callTrace(ctx, "trace.log", {
|
|
101
|
+
session_id: sessionId,
|
|
102
|
+
level: (0, trace_1.normalizeTraceLevel)(tracer?.level || "debug"),
|
|
103
|
+
action: actionName,
|
|
104
|
+
state: "started",
|
|
105
|
+
marker: tracer?.marker || null,
|
|
106
|
+
step: tracer?.step || "action",
|
|
107
|
+
message: actionName,
|
|
108
|
+
data: (0, trace_1.buildTraceStartData)(ctx, actionName, tracer, startedSession),
|
|
109
|
+
}, false);
|
|
110
|
+
}
|
|
111
|
+
try {
|
|
112
|
+
const result = await next(ctx);
|
|
113
|
+
const durationMs = Date.now() - startedAt;
|
|
114
|
+
if (hasSession) {
|
|
115
|
+
await callTrace(ctx, "trace.log", {
|
|
116
|
+
session_id: sessionId,
|
|
117
|
+
level: (0, trace_1.normalizeTraceLevel)(tracer?.level || "debug"),
|
|
118
|
+
action: actionName,
|
|
119
|
+
state: "succeeded",
|
|
120
|
+
marker: tracer?.marker || null,
|
|
121
|
+
step: tracer?.step || "action",
|
|
122
|
+
message: actionName,
|
|
123
|
+
data: (0, trace_1.buildTraceSuccessData)(ctx, actionName, result, durationMs, tracer),
|
|
124
|
+
}, false);
|
|
125
|
+
if (tracer?.stopSession) {
|
|
126
|
+
await callTrace(ctx, "trace.endSession", {
|
|
127
|
+
session_id: sessionId,
|
|
128
|
+
status: "succeeded",
|
|
129
|
+
summary: `${actionName} completed`,
|
|
130
|
+
meta: (0, trace_1.sanitizeTraceValue)({
|
|
131
|
+
action: actionName,
|
|
132
|
+
durationMs,
|
|
133
|
+
}),
|
|
134
|
+
}, false);
|
|
135
|
+
await (0, traceContext_1.deleteTraceContext)();
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
return result;
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
const durationMs = Date.now() - startedAt;
|
|
142
|
+
if (hasSession) {
|
|
143
|
+
await callTrace(ctx, "trace.log", {
|
|
144
|
+
session_id: sessionId,
|
|
145
|
+
level: "error",
|
|
146
|
+
action: actionName,
|
|
147
|
+
state: "failed",
|
|
148
|
+
marker: tracer?.marker || null,
|
|
149
|
+
step: tracer?.step || "action",
|
|
150
|
+
message: actionName,
|
|
151
|
+
data: (0, trace_1.buildTraceErrorData)(ctx, actionName, error, durationMs, tracer),
|
|
152
|
+
}, false);
|
|
153
|
+
if (tracer?.stopSession || startedSession) {
|
|
154
|
+
await callTrace(ctx, "trace.endSession", {
|
|
155
|
+
session_id: sessionId,
|
|
156
|
+
status: "failed",
|
|
157
|
+
summary: error instanceof Error ? error.message : `Action failed: ${actionName}`,
|
|
158
|
+
meta: (0, trace_1.sanitizeTraceValue)({
|
|
159
|
+
action: actionName,
|
|
160
|
+
durationMs,
|
|
161
|
+
}),
|
|
162
|
+
}, false);
|
|
163
|
+
await (0, traceContext_1.deleteTraceContext)();
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
throw error;
|
|
167
|
+
}
|
|
168
|
+
};
|
|
169
|
+
},
|
|
170
|
+
};
|
|
171
|
+
};
|
|
172
|
+
exports.createTracerMiddleware = createTracerMiddleware;
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.DBMixin = void 0;
|
|
7
|
+
/* eslint-disable @typescript-eslint/no-namespace */
|
|
8
|
+
const knex_1 = __importDefault(require("knex"));
|
|
9
|
+
const paginate = (q, pagination) => {
|
|
10
|
+
if (!pagination)
|
|
11
|
+
return q.then(items => ({ items }));
|
|
12
|
+
return q
|
|
13
|
+
.clone()
|
|
14
|
+
.clearSelect()
|
|
15
|
+
.clearOrder()
|
|
16
|
+
.count("*")
|
|
17
|
+
.first()
|
|
18
|
+
.then(({ count: total }) => {
|
|
19
|
+
if (pagination?.limit)
|
|
20
|
+
q.limit(pagination.limit);
|
|
21
|
+
if (pagination?.offset)
|
|
22
|
+
q.offset(pagination.offset);
|
|
23
|
+
return q.then(items => ({
|
|
24
|
+
pagination: {
|
|
25
|
+
total: +total,
|
|
26
|
+
...pagination,
|
|
27
|
+
},
|
|
28
|
+
items,
|
|
29
|
+
}));
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
const filter = (q, flt) => {
|
|
33
|
+
const create = (f, p) => {
|
|
34
|
+
if (f.operator.toLocaleUpperCase() === "IN") {
|
|
35
|
+
q.whereIn(f.column, f.values);
|
|
36
|
+
}
|
|
37
|
+
else if (p) {
|
|
38
|
+
console.log("P", p);
|
|
39
|
+
p.andWhere(f.column, f.operator, f.value);
|
|
40
|
+
}
|
|
41
|
+
else
|
|
42
|
+
q.orWhere(f.column, f.operator, f.value);
|
|
43
|
+
if (f.and) {
|
|
44
|
+
f.and.forEach((af) => create(af, q));
|
|
45
|
+
}
|
|
46
|
+
return q;
|
|
47
|
+
};
|
|
48
|
+
if (!flt)
|
|
49
|
+
return q;
|
|
50
|
+
flt.forEach(f => create(f));
|
|
51
|
+
return q;
|
|
52
|
+
};
|
|
53
|
+
const orderBy = (q, sort) => {
|
|
54
|
+
const orders = sort
|
|
55
|
+
.map(({ column, order, nulls }) => {
|
|
56
|
+
return `"${column}" ${order} ${nulls || ""}`;
|
|
57
|
+
})
|
|
58
|
+
.join(",");
|
|
59
|
+
q.orderByRaw(orders);
|
|
60
|
+
};
|
|
61
|
+
knex_1.default.QueryBuilder.extend("dataView", function (dataView) {
|
|
62
|
+
if (dataView?.filter)
|
|
63
|
+
filter(this, dataView.filter);
|
|
64
|
+
if (dataView?.sort)
|
|
65
|
+
orderBy(this, dataView.sort);
|
|
66
|
+
return paginate(this, dataView?.pagination);
|
|
67
|
+
});
|
|
68
|
+
const DBConfig = {
|
|
69
|
+
host: process.env.DB_HOST || "localhost",
|
|
70
|
+
port: Number(process.env.DB_PORT || 5432),
|
|
71
|
+
user: process.env.DB_USER || "",
|
|
72
|
+
password: process.env.DB_PASSWORD || "",
|
|
73
|
+
database: process.env.DB_NAME || "",
|
|
74
|
+
};
|
|
75
|
+
const DB_ENABLED = Boolean(process.env.DB_HOST?.trim());
|
|
76
|
+
const createNoopPromise = (value) => Promise.resolve(value);
|
|
77
|
+
const createNoopQueryBuilder = (state = {}) => {
|
|
78
|
+
const target = function noopQueryBuilder() {
|
|
79
|
+
return createNoopQueryBuilder(state);
|
|
80
|
+
};
|
|
81
|
+
const proxy = new Proxy(target, {
|
|
82
|
+
apply() {
|
|
83
|
+
return createNoopQueryBuilder(state);
|
|
84
|
+
},
|
|
85
|
+
get(_obj, prop) {
|
|
86
|
+
if (prop === "then") {
|
|
87
|
+
return createNoopPromise([]).then.bind(createNoopPromise([]));
|
|
88
|
+
}
|
|
89
|
+
if (prop === "catch") {
|
|
90
|
+
return createNoopPromise([]).catch.bind(createNoopPromise([]));
|
|
91
|
+
}
|
|
92
|
+
if (prop === "finally") {
|
|
93
|
+
return createNoopPromise([]).finally.bind(createNoopPromise([]));
|
|
94
|
+
}
|
|
95
|
+
if (prop === "first") {
|
|
96
|
+
return () => createNoopPromise(state.countMode ? { count: 0 } : null);
|
|
97
|
+
}
|
|
98
|
+
if (prop === "pluck") {
|
|
99
|
+
return () => createNoopPromise([]);
|
|
100
|
+
}
|
|
101
|
+
if (prop === "insert" ||
|
|
102
|
+
prop === "update" ||
|
|
103
|
+
prop === "delete" ||
|
|
104
|
+
prop === "del" ||
|
|
105
|
+
prop === "increment" ||
|
|
106
|
+
prop === "decrement") {
|
|
107
|
+
return () => createNoopQueryBuilder(state);
|
|
108
|
+
}
|
|
109
|
+
if (prop === "count") {
|
|
110
|
+
return () => createNoopQueryBuilder({ ...state, countMode: true });
|
|
111
|
+
}
|
|
112
|
+
if (prop === "clone" ||
|
|
113
|
+
prop === "clearSelect" ||
|
|
114
|
+
prop === "clearOrder" ||
|
|
115
|
+
prop === "select" ||
|
|
116
|
+
prop === "from" ||
|
|
117
|
+
prop === "table" ||
|
|
118
|
+
prop === "withSchema" ||
|
|
119
|
+
prop === "where" ||
|
|
120
|
+
prop === "andWhere" ||
|
|
121
|
+
prop === "orWhere" ||
|
|
122
|
+
prop === "whereIn" ||
|
|
123
|
+
prop === "whereNotIn" ||
|
|
124
|
+
prop === "whereNull" ||
|
|
125
|
+
prop === "whereNotNull" ||
|
|
126
|
+
prop === "leftJoin" ||
|
|
127
|
+
prop === "rightJoin" ||
|
|
128
|
+
prop === "join" ||
|
|
129
|
+
prop === "groupBy" ||
|
|
130
|
+
prop === "having" ||
|
|
131
|
+
prop === "orderBy" ||
|
|
132
|
+
prop === "orderByRaw" ||
|
|
133
|
+
prop === "limit" ||
|
|
134
|
+
prop === "offset" ||
|
|
135
|
+
prop === "transacting" ||
|
|
136
|
+
prop === "onConflict" ||
|
|
137
|
+
prop === "merge" ||
|
|
138
|
+
prop === "returning" ||
|
|
139
|
+
prop === "modify" ||
|
|
140
|
+
prop === "column" ||
|
|
141
|
+
prop === "union" ||
|
|
142
|
+
prop === "unionAll" ||
|
|
143
|
+
prop === "forUpdate" ||
|
|
144
|
+
prop === "forShare") {
|
|
145
|
+
return () => createNoopQueryBuilder(state);
|
|
146
|
+
}
|
|
147
|
+
return createNoopQueryBuilder(state);
|
|
148
|
+
},
|
|
149
|
+
});
|
|
150
|
+
return proxy;
|
|
151
|
+
};
|
|
152
|
+
const createNoopSchema = () => {
|
|
153
|
+
const schemaTarget = {};
|
|
154
|
+
return new Proxy(schemaTarget, {
|
|
155
|
+
get(_obj, prop) {
|
|
156
|
+
if (prop === "hasTable") {
|
|
157
|
+
return () => Promise.resolve(false);
|
|
158
|
+
}
|
|
159
|
+
if (prop === "withSchema" ||
|
|
160
|
+
prop === "createTable" ||
|
|
161
|
+
prop === "alterTable" ||
|
|
162
|
+
prop === "dropTable" ||
|
|
163
|
+
prop === "dropTableIfExists" ||
|
|
164
|
+
prop === "createSchema" ||
|
|
165
|
+
prop === "createSchemaIfNotExists") {
|
|
166
|
+
return () => createNoopSchema();
|
|
167
|
+
}
|
|
168
|
+
if (prop === "then") {
|
|
169
|
+
return Promise.resolve(undefined).then.bind(Promise.resolve(undefined));
|
|
170
|
+
}
|
|
171
|
+
if (prop === "catch") {
|
|
172
|
+
return Promise.resolve(undefined).catch.bind(Promise.resolve(undefined));
|
|
173
|
+
}
|
|
174
|
+
if (prop === "finally") {
|
|
175
|
+
return Promise.resolve(undefined).finally.bind(Promise.resolve(undefined));
|
|
176
|
+
}
|
|
177
|
+
return () => createNoopSchema();
|
|
178
|
+
},
|
|
179
|
+
});
|
|
180
|
+
};
|
|
181
|
+
const createNoopKnex = () => {
|
|
182
|
+
const queryBuilder = createNoopQueryBuilder();
|
|
183
|
+
const schema = createNoopSchema();
|
|
184
|
+
const rawResult = {
|
|
185
|
+
rows: [],
|
|
186
|
+
rowCount: 0,
|
|
187
|
+
command: "NOOP",
|
|
188
|
+
};
|
|
189
|
+
const target = function noopKnex() {
|
|
190
|
+
return createNoopQueryBuilder();
|
|
191
|
+
};
|
|
192
|
+
const proxy = new Proxy(target, {
|
|
193
|
+
apply() {
|
|
194
|
+
return createNoopQueryBuilder();
|
|
195
|
+
},
|
|
196
|
+
get(_obj, prop) {
|
|
197
|
+
if (prop === "schema") {
|
|
198
|
+
return schema;
|
|
199
|
+
}
|
|
200
|
+
if (prop === "fn") {
|
|
201
|
+
return {
|
|
202
|
+
now: () => new Date(),
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
if (prop === "raw") {
|
|
206
|
+
return async () => rawResult;
|
|
207
|
+
}
|
|
208
|
+
if (prop === "destroy") {
|
|
209
|
+
return async () => undefined;
|
|
210
|
+
}
|
|
211
|
+
if (prop === "transaction") {
|
|
212
|
+
return async (handler) => {
|
|
213
|
+
if (typeof handler === "function") {
|
|
214
|
+
return handler(proxy);
|
|
215
|
+
}
|
|
216
|
+
return proxy;
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
if (prop === "withSchema" || prop === "table") {
|
|
220
|
+
return () => createNoopQueryBuilder();
|
|
221
|
+
}
|
|
222
|
+
if (prop === "queryBuilder") {
|
|
223
|
+
return () => createNoopQueryBuilder();
|
|
224
|
+
}
|
|
225
|
+
return queryBuilder[prop] ?? createNoopQueryBuilder();
|
|
226
|
+
},
|
|
227
|
+
});
|
|
228
|
+
return proxy;
|
|
229
|
+
};
|
|
230
|
+
const DBMixin = {
|
|
231
|
+
name: "DBMixin",
|
|
232
|
+
created() {
|
|
233
|
+
if (!DB_ENABLED) {
|
|
234
|
+
this.logger?.warn?.("DBMixin: DB_HOST is not set, using no-op database stub");
|
|
235
|
+
this.db = createNoopKnex();
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
this.db = (0, knex_1.default)({
|
|
239
|
+
debug: Boolean(process.env.PG_DEBUG),
|
|
240
|
+
client: "pg",
|
|
241
|
+
connection: {
|
|
242
|
+
...DBConfig,
|
|
243
|
+
},
|
|
244
|
+
pool: {
|
|
245
|
+
min: 1,
|
|
246
|
+
max: 64,
|
|
247
|
+
// acquireTimeoutMillis: 1000 * 60 * 60,
|
|
248
|
+
propagateCreateError: false,
|
|
249
|
+
afterCreate: (con, callback) => {
|
|
250
|
+
con.on("error", (err) => {
|
|
251
|
+
console.error("[KNEX-ERROR]", err);
|
|
252
|
+
});
|
|
253
|
+
con.on("notice", function (msg) {
|
|
254
|
+
console.warn(`[DB] ${msg.name}/${msg.severity}:`, msg.message);
|
|
255
|
+
// console.warn(`[PG]`, msg.message);
|
|
256
|
+
});
|
|
257
|
+
con.query('SET time zone "Europe/Moscow"', (err) => {
|
|
258
|
+
if (err)
|
|
259
|
+
console.error("QUERY", err);
|
|
260
|
+
callback(err, con);
|
|
261
|
+
});
|
|
262
|
+
},
|
|
263
|
+
},
|
|
264
|
+
});
|
|
265
|
+
},
|
|
266
|
+
};
|
|
267
|
+
exports.DBMixin = DBMixin;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LogFeedLogger = void 0;
|
|
4
|
+
/* eslint-disable no-control-regex */
|
|
5
|
+
const moleculer_1 = require("moleculer");
|
|
6
|
+
const store_1 = require("../logfeed/store");
|
|
7
|
+
const LEVELS = ["fatal", "error", "warn", "info", "debug", "trace"];
|
|
8
|
+
class LogFeedLogger extends moleculer_1.Loggers.Base {
|
|
9
|
+
getLogHandler(bindings) {
|
|
10
|
+
const level = bindings ? this.getLogLevel?.(bindings.mod) : null;
|
|
11
|
+
if (!level)
|
|
12
|
+
return null;
|
|
13
|
+
const levelIdx = LEVELS.indexOf(level);
|
|
14
|
+
return (type, args) => {
|
|
15
|
+
const typeIdx = LEVELS.indexOf(type);
|
|
16
|
+
if (typeIdx > levelIdx || !args?.length)
|
|
17
|
+
return;
|
|
18
|
+
const message = (0, store_1.stringifyLogArgs)(args);
|
|
19
|
+
if (message.includes("graphql.publish")) {
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
store_1.logFeedStore.push({
|
|
23
|
+
ts: Date.now(),
|
|
24
|
+
level: type,
|
|
25
|
+
module: bindings?.mod?.toUpperCase?.() || null,
|
|
26
|
+
nodeID: bindings?.nodeID || null,
|
|
27
|
+
namespace: bindings?.ns || null,
|
|
28
|
+
svc: bindings?.svc || null,
|
|
29
|
+
message,
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
exports.LogFeedLogger = LogFeedLogger;
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.PlaygroundDisabledError = exports.SessionIdleTimeoutExceededError = exports.TokenInvalidError = exports.TokenNotFoundError = exports.SessionTokenSignatureInvalidError = exports.SessionTokenInvalidFormatError = exports.SessionTokenMismatchError = exports.SessionTokenNotFoundError = exports.SessionTokenRevokedError = exports.SessionTokenNotActiveError = exports.SessionTokenExpiredError = exports.SessionTokenInvalidError = exports.SessionValidationError = exports.SessionRefreshError = exports.SessionMaxLifetimeExceededError = exports.SessionStealedError = exports.SessionInvalidError = exports.SessionExpiredError = exports.SessionNotFoundError = exports.ForbiddenError = exports.UnauthorizedError = exports.BackendError = void 0;
|
|
4
|
+
const graphql_1 = require("graphql");
|
|
5
|
+
class BackendError extends graphql_1.GraphQLError {
|
|
6
|
+
constructor(message, code, type, data) {
|
|
7
|
+
super(message, {
|
|
8
|
+
extensions: {
|
|
9
|
+
code: code,
|
|
10
|
+
type: type || code,
|
|
11
|
+
data,
|
|
12
|
+
},
|
|
13
|
+
});
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
exports.BackendError = BackendError;
|
|
17
|
+
class UnauthorizedError extends BackendError {
|
|
18
|
+
constructor(message = "Unauthorized", data) {
|
|
19
|
+
super(message, 401, "UNAUTHORIZED", data);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
exports.UnauthorizedError = UnauthorizedError;
|
|
23
|
+
class ForbiddenError extends BackendError {
|
|
24
|
+
constructor(message = "Forbidden", data) {
|
|
25
|
+
super(message, 403, "FORBIDDEN", data);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.ForbiddenError = ForbiddenError;
|
|
29
|
+
class SessionNotFoundError extends BackendError {
|
|
30
|
+
constructor(message = "Session not found", data) {
|
|
31
|
+
super(message, 401, "SESSION_NOT_FOUND", data);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
exports.SessionNotFoundError = SessionNotFoundError;
|
|
35
|
+
class SessionExpiredError extends BackendError {
|
|
36
|
+
constructor(message = "Session expired", data) {
|
|
37
|
+
super(message, 401, "SESSION_EXPIRED", data);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
exports.SessionExpiredError = SessionExpiredError;
|
|
41
|
+
class SessionInvalidError extends BackendError {
|
|
42
|
+
constructor(message = "Session invalid", data) {
|
|
43
|
+
super(message, 401, "SESSION_INVALID", data);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
exports.SessionInvalidError = SessionInvalidError;
|
|
47
|
+
class SessionStealedError extends BackendError {
|
|
48
|
+
constructor(message = "Session stealed", data) {
|
|
49
|
+
super(message, 401, "SESSION_STEALED", data);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
exports.SessionStealedError = SessionStealedError;
|
|
53
|
+
class SessionMaxLifetimeExceededError extends BackendError {
|
|
54
|
+
constructor(message = "Session max lifetime exceeded", data) {
|
|
55
|
+
super(message, 401, "SESSION_MAX_LIFETIME_EXCEEDED", data);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
exports.SessionMaxLifetimeExceededError = SessionMaxLifetimeExceededError;
|
|
59
|
+
class SessionRefreshError extends BackendError {
|
|
60
|
+
constructor(message = "Session refresh failed", data) {
|
|
61
|
+
super(message, 401, "SESSION_REFRESH_FAILED", data);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
exports.SessionRefreshError = SessionRefreshError;
|
|
65
|
+
class SessionValidationError extends BackendError {
|
|
66
|
+
constructor(message = "Session validation failed", data) {
|
|
67
|
+
super(message, 401, "SESSION_VALIDATION_FAILED", data);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
exports.SessionValidationError = SessionValidationError;
|
|
71
|
+
class SessionTokenInvalidError extends BackendError {
|
|
72
|
+
constructor(message = "Session token invalid", data) {
|
|
73
|
+
super(message, 401, "SESSION_TOKEN_INVALID", data);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
exports.SessionTokenInvalidError = SessionTokenInvalidError;
|
|
77
|
+
class SessionTokenExpiredError extends BackendError {
|
|
78
|
+
constructor(message = "Session token expired", data) {
|
|
79
|
+
super(message, 401, "SESSION_TOKEN_EXPIRED", data);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
exports.SessionTokenExpiredError = SessionTokenExpiredError;
|
|
83
|
+
class SessionTokenNotActiveError extends BackendError {
|
|
84
|
+
constructor(message = "Session token not active", data) {
|
|
85
|
+
super(message, 401, "SESSION_TOKEN_NOT_ACTIVE", data);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
exports.SessionTokenNotActiveError = SessionTokenNotActiveError;
|
|
89
|
+
class SessionTokenRevokedError extends BackendError {
|
|
90
|
+
constructor(message = "Session token revoked", data) {
|
|
91
|
+
super(message, 401, "SESSION_TOKEN_REVOKED", data);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
exports.SessionTokenRevokedError = SessionTokenRevokedError;
|
|
95
|
+
class SessionTokenNotFoundError extends BackendError {
|
|
96
|
+
constructor(message = "Session token not found", data) {
|
|
97
|
+
super(message, 401, "SESSION_TOKEN_NOT_FOUND", data);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
exports.SessionTokenNotFoundError = SessionTokenNotFoundError;
|
|
101
|
+
class SessionTokenMismatchError extends BackendError {
|
|
102
|
+
constructor(message = "Session token mismatch", data) {
|
|
103
|
+
super(message, 401, "SESSION_TOKEN_MISMATCH", data);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
exports.SessionTokenMismatchError = SessionTokenMismatchError;
|
|
107
|
+
class SessionTokenInvalidFormatError extends BackendError {
|
|
108
|
+
constructor(message = "Session token invalid format", data) {
|
|
109
|
+
super(message, 401, "SESSION_TOKEN_INVALID_FORMAT", data);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
exports.SessionTokenInvalidFormatError = SessionTokenInvalidFormatError;
|
|
113
|
+
class SessionTokenSignatureInvalidError extends BackendError {
|
|
114
|
+
constructor(message = "Session token signature invalid", data) {
|
|
115
|
+
super(message, 401, "SESSION_TOKEN_SIGNATURE_INVALID", data);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
exports.SessionTokenSignatureInvalidError = SessionTokenSignatureInvalidError;
|
|
119
|
+
class TokenNotFoundError extends BackendError {
|
|
120
|
+
constructor(message = "Token not found", data) {
|
|
121
|
+
super(message, 401, "TOKEN_NOT_FOUND", data);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
exports.TokenNotFoundError = TokenNotFoundError;
|
|
125
|
+
class TokenInvalidError extends BackendError {
|
|
126
|
+
constructor(message = "Token invalid", data) {
|
|
127
|
+
super(message, 401, "TOKEN_INVALID", data);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
exports.TokenInvalidError = TokenInvalidError;
|
|
131
|
+
class SessionIdleTimeoutExceededError extends BackendError {
|
|
132
|
+
constructor(message = "Session idle timeout exceeded", data) {
|
|
133
|
+
super(message, 401, "SESSION_IDLE_TIMEOUT_EXCEEDED", data);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
exports.SessionIdleTimeoutExceededError = SessionIdleTimeoutExceededError;
|
|
137
|
+
class PlaygroundDisabledError extends BackendError {
|
|
138
|
+
constructor(message = "Playground disabled", data) {
|
|
139
|
+
super(message, 403, "PLAYGROUND_DISABLED", data);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
exports.PlaygroundDisabledError = PlaygroundDisabledError;
|