@mokoconsulting/mcp-mokogitea-api 1.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.
Files changed (86) hide show
  1. package/.gitattributes +94 -0
  2. package/.gitmessage +9 -0
  3. package/.mokogitea/ISSUE_TEMPLATE/adr.md +110 -0
  4. package/.mokogitea/ISSUE_TEMPLATE/bug_report.md +48 -0
  5. package/.mokogitea/ISSUE_TEMPLATE/config.yml +18 -0
  6. package/.mokogitea/ISSUE_TEMPLATE/documentation.md +52 -0
  7. package/.mokogitea/ISSUE_TEMPLATE/enterprise_support.md +85 -0
  8. package/.mokogitea/ISSUE_TEMPLATE/feature_request.md +51 -0
  9. package/.mokogitea/ISSUE_TEMPLATE/firewall-request.md +190 -0
  10. package/.mokogitea/ISSUE_TEMPLATE/mcp_api_integration.md +48 -0
  11. package/.mokogitea/ISSUE_TEMPLATE/mcp_connection_issue.md +67 -0
  12. package/.mokogitea/ISSUE_TEMPLATE/mcp_tool_request.md +49 -0
  13. package/.mokogitea/ISSUE_TEMPLATE/question.md +82 -0
  14. package/.mokogitea/ISSUE_TEMPLATE/rfc.md +126 -0
  15. package/.mokogitea/ISSUE_TEMPLATE/security.md +51 -0
  16. package/.mokogitea/ISSUE_TEMPLATE/version.md +24 -0
  17. package/.mokogitea/auto-assign.yml +76 -0
  18. package/.mokogitea/auto-dev-issue.yml +207 -0
  19. package/.mokogitea/auto-release.yml +337 -0
  20. package/.mokogitea/branch-protection.yml +251 -0
  21. package/.mokogitea/changelog-validation.yml +101 -0
  22. package/.mokogitea/codeql-analysis.yml +115 -0
  23. package/.mokogitea/copilot-agent.yml +44 -0
  24. package/.mokogitea/deploy-demo.yml +734 -0
  25. package/.mokogitea/deploy-dev.yml +700 -0
  26. package/.mokogitea/enterprise-firewall-setup.yml +758 -0
  27. package/.mokogitea/manifest.xml +25 -0
  28. package/.mokogitea/mcp-auto-release.yml +278 -0
  29. package/.mokogitea/mcp-build-test.yml +65 -0
  30. package/.mokogitea/mcp-sdk-check.yml +109 -0
  31. package/.mokogitea/mcp-tool-inventory.yml +61 -0
  32. package/.mokogitea/pr-branch-check.yml +90 -0
  33. package/.mokogitea/repository-cleanup.yml +525 -0
  34. package/.mokogitea/standards-compliance.yml +2614 -0
  35. package/.mokogitea/sync-version-on-merge.yml +133 -0
  36. package/.mokogitea/workflows/auto-assign.yml +76 -0
  37. package/.mokogitea/workflows/auto-bump.yml +66 -0
  38. package/.mokogitea/workflows/auto-dev-issue.yml +207 -0
  39. package/.mokogitea/workflows/auto-release.yml +341 -0
  40. package/.mokogitea/workflows/branch-cleanup.yml +48 -0
  41. package/.mokogitea/workflows/cascade-dev.yml +10 -0
  42. package/.mokogitea/workflows/changelog-validation.yml +101 -0
  43. package/.mokogitea/workflows/ci-generic.yml +204 -0
  44. package/.mokogitea/workflows/cleanup.yml +87 -0
  45. package/.mokogitea/workflows/codeql-analysis.yml +115 -0
  46. package/.mokogitea/workflows/copilot-agent.yml +44 -0
  47. package/.mokogitea/workflows/deploy-manual.yml +126 -0
  48. package/.mokogitea/workflows/enterprise-firewall-setup.yml +758 -0
  49. package/.mokogitea/workflows/gitleaks.yml +96 -0
  50. package/.mokogitea/workflows/issue-branch.yml +73 -0
  51. package/.mokogitea/workflows/mcp-auto-release.yml +280 -0
  52. package/.mokogitea/workflows/mcp-build-test.yml +65 -0
  53. package/.mokogitea/workflows/mcp-sdk-check.yml +109 -0
  54. package/.mokogitea/workflows/mcp-tool-inventory.yml +61 -0
  55. package/.mokogitea/workflows/notify.yml +70 -0
  56. package/.mokogitea/workflows/npm-publish.yml +51 -0
  57. package/.mokogitea/workflows/pr-check.yml +508 -0
  58. package/.mokogitea/workflows/pre-release.yml +11 -0
  59. package/.mokogitea/workflows/repo-health.yml +711 -0
  60. package/.mokogitea/workflows/repository-cleanup.yml +525 -0
  61. package/.mokogitea/workflows/security-audit.yml +82 -0
  62. package/.mokogitea/workflows/standards-compliance.yml +2614 -0
  63. package/.mokogitea/workflows/sync-version-on-merge.yml +130 -0
  64. package/.mokogitea/workflows/update-server.yml +312 -0
  65. package/CHANGELOG.md +145 -0
  66. package/CLAUDE.md +43 -0
  67. package/CONTRIBUTING.md +161 -0
  68. package/README.md +286 -0
  69. package/SECURITY.md +91 -0
  70. package/automation/ci-issue-reporter.sh +237 -0
  71. package/config.example.json +13 -0
  72. package/dist/client.d.ts +15 -0
  73. package/dist/client.js +104 -0
  74. package/dist/config.d.ts +4 -0
  75. package/dist/config.js +48 -0
  76. package/dist/index.d.ts +3 -0
  77. package/dist/index.js +1119 -0
  78. package/dist/types.d.ts +20 -0
  79. package/dist/types.js +16 -0
  80. package/package.json +34 -0
  81. package/scripts/setup.mjs +40 -0
  82. package/src/client.ts +120 -0
  83. package/src/config.ts +58 -0
  84. package/src/index.ts +1712 -0
  85. package/src/types.ts +37 -0
  86. package/tsconfig.json +19 -0
@@ -0,0 +1,237 @@
1
+ #!/usr/bin/env bash
2
+ # ============================================================================
3
+ # Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
4
+ #
5
+ # SPDX-License-Identifier: GPL-3.0-or-later
6
+ #
7
+ # FILE INFORMATION
8
+ # DEFGROUP: Automation.CI
9
+ # INGROUP: moko-platform.Automation
10
+ # REPO: https://git.mokoconsulting.tech/MokoConsulting/moko-platform
11
+ # PATH: /automation/ci-issue-reporter.sh
12
+ # VERSION: 09.23.00
13
+ # BRIEF: Creates or updates a Gitea issue when a CI gate fails.
14
+ # Deduplicates by searching open issues with the "ci-auto" label
15
+ # whose title matches the gate. If a matching issue exists, a comment
16
+ # is appended instead of opening a duplicate.
17
+ # ============================================================================
18
+
19
+ set -euo pipefail
20
+
21
+ # ── Defaults ────────────────────────────────────────────────────────────────
22
+ GITEA_URL="${GITEA_URL:-https://git.mokoconsulting.tech}"
23
+ GITEA_TOKEN="${GITEA_TOKEN:-}"
24
+ REPO="${GITHUB_REPOSITORY:-}"
25
+ RUN_URL="${GITHUB_SERVER_URL:-${GITEA_URL}}/${REPO}/actions/runs/${GITHUB_RUN_ID:-0}"
26
+ LABEL_NAME="ci-auto"
27
+ LABEL_COLOR="#e11d48"
28
+
29
+ GATE=""
30
+ DETAILS=""
31
+ SEVERITY="error"
32
+ WORKFLOW=""
33
+
34
+ # ── Parse arguments ─────────────────────────────────────────────────────────
35
+ usage() {
36
+ cat <<EOF
37
+ Usage: ci-issue-reporter.sh --gate NAME --details TEXT [OPTIONS]
38
+
39
+ Required:
40
+ --gate CI gate name (e.g. "Code Quality", "Self-Health")
41
+ --details Human-readable failure description
42
+
43
+ Optional:
44
+ --severity "error" (default) or "warning"
45
+ --workflow Workflow name for the issue title
46
+ --repo owner/repo (default: \$GITHUB_REPOSITORY)
47
+ --run-url URL to the CI run (auto-detected from env)
48
+ --token Gitea API token (default: \$GITEA_TOKEN)
49
+ --url Gitea base URL (default: \$GITEA_URL)
50
+ EOF
51
+ exit 1
52
+ }
53
+
54
+ while [[ $# -gt 0 ]]; do
55
+ case "$1" in
56
+ --gate) GATE="$2"; shift 2 ;;
57
+ --details) DETAILS="$2"; shift 2 ;;
58
+ --severity) SEVERITY="$2"; shift 2 ;;
59
+ --workflow) WORKFLOW="$2"; shift 2 ;;
60
+ --repo) REPO="$2"; shift 2 ;;
61
+ --run-url) RUN_URL="$2"; shift 2 ;;
62
+ --token) GITEA_TOKEN="$2"; shift 2 ;;
63
+ --url) GITEA_URL="$2"; shift 2 ;;
64
+ -h|--help) usage ;;
65
+ *) echo "Unknown option: $1"; usage ;;
66
+ esac
67
+ done
68
+
69
+ [[ -z "$GATE" ]] && { echo "ERROR: --gate is required"; usage; }
70
+ [[ -z "$DETAILS" ]] && { echo "ERROR: --details is required"; usage; }
71
+ [[ -z "$GITEA_TOKEN" ]] && { echo "ERROR: GITEA_TOKEN not set"; exit 1; }
72
+ [[ -z "$REPO" ]] && { echo "ERROR: GITHUB_REPOSITORY not set"; exit 1; }
73
+
74
+ API="${GITEA_URL}/api/v1/repos/${REPO}"
75
+
76
+ # ── Build title ─────────────────────────────────────────────────────────────
77
+ if [[ -n "$WORKFLOW" ]]; then
78
+ TITLE="[CI] ${WORKFLOW}: ${GATE} failed"
79
+ else
80
+ TITLE="[CI] ${GATE} failed"
81
+ fi
82
+
83
+ # ── Ensure label exists ─────────────────────────────────────────────────────
84
+ ensure_label() {
85
+ local exists
86
+ exists=$(curl -sf -o /dev/null -w '%{http_code}' \
87
+ -H "Authorization: token ${GITEA_TOKEN}" \
88
+ "${API}/labels" 2>/dev/null || echo "000")
89
+
90
+ if [[ "$exists" == "200" ]]; then
91
+ # Check if label already exists
92
+ local found
93
+ found=$(curl -sf \
94
+ -H "Authorization: token ${GITEA_TOKEN}" \
95
+ "${API}/labels" 2>/dev/null \
96
+ | grep -o "\"name\":\"${LABEL_NAME}\"" || true)
97
+
98
+ if [[ -z "$found" ]]; then
99
+ curl -sf -X POST \
100
+ -H "Authorization: token ${GITEA_TOKEN}" \
101
+ -H "Content-Type: application/json" \
102
+ "${API}/labels" \
103
+ -d "{\"name\":\"${LABEL_NAME}\",\"color\":\"${LABEL_COLOR}\",\"description\":\"Auto-created by CI issue reporter\"}" \
104
+ > /dev/null 2>&1 || true
105
+ fi
106
+ fi
107
+ }
108
+
109
+ # ── Search for existing open issue ──────────────────────────────────────────
110
+ find_existing_issue() {
111
+ # URL-encode the gate name for the query
112
+ local query
113
+ query=$(printf '%s' "[CI] ${GATE}" | sed 's/ /%20/g; s/\[/%5B/g; s/\]/%5D/g')
114
+
115
+ local response
116
+ response=$(curl -sf \
117
+ -H "Authorization: token ${GITEA_TOKEN}" \
118
+ "${API}/issues?type=issues&state=open&labels=${LABEL_NAME}&q=${query}&limit=5" \
119
+ 2>/dev/null || echo "[]")
120
+
121
+ # Extract the first matching issue number
122
+ echo "$response" \
123
+ | grep -oP '"number":\s*\K[0-9]+' \
124
+ | head -1
125
+ }
126
+
127
+ # ── Build issue body ────────────────────────────────────────────────────────
128
+ build_body() {
129
+ local severity_badge
130
+ if [[ "$SEVERITY" == "error" ]]; then
131
+ severity_badge="**Severity:** Error"
132
+ else
133
+ severity_badge="**Severity:** Warning"
134
+ fi
135
+
136
+ cat <<BODY
137
+ ## CI Gate Failure: ${GATE}
138
+
139
+ ${severity_badge}
140
+ **Workflow:** ${WORKFLOW:-unknown}
141
+ **Branch:** ${GITHUB_REF_NAME:-unknown}
142
+ **Commit:** \`${GITHUB_SHA:0:8}\`
143
+ **Run:** [View CI run](${RUN_URL})
144
+
145
+ ### Details
146
+
147
+ ${DETAILS}
148
+
149
+ ### Resolution
150
+
151
+ Fix the issue described above and push a new commit. This issue will be closed automatically when the gate passes, or can be closed manually.
152
+
153
+ ---
154
+ *Auto-created by [ci-issue-reporter](${GITEA_URL}/${REPO}/src/branch/main/automation/ci-issue-reporter.sh)*
155
+ BODY
156
+ }
157
+
158
+ # ── Build comment body (for existing issues) ────────────────────────────────
159
+ build_comment() {
160
+ cat <<COMMENT
161
+ ### CI failure recurrence
162
+
163
+ **Branch:** ${GITHUB_REF_NAME:-unknown}
164
+ **Commit:** \`${GITHUB_SHA:0:8}\`
165
+ **Run:** [View CI run](${RUN_URL})
166
+
167
+ ${DETAILS}
168
+ COMMENT
169
+ }
170
+
171
+ # ── Main ────────────────────────────────────────────────────────────────────
172
+ ensure_label
173
+
174
+ EXISTING=$(find_existing_issue)
175
+
176
+ if [[ -n "$EXISTING" ]]; then
177
+ # Append comment to existing issue
178
+ COMMENT_BODY=$(build_comment)
179
+ COMMENT_JSON=$(printf '%s' "$COMMENT_BODY" | python3 -c "
180
+ import sys, json
181
+ print(json.dumps({'body': sys.stdin.read()}))" 2>/dev/null)
182
+
183
+ HTTP=$(curl -sf -o /dev/null -w '%{http_code}' -X POST \
184
+ -H "Authorization: token ${GITEA_TOKEN}" \
185
+ -H "Content-Type: application/json" \
186
+ "${API}/issues/${EXISTING}/comments" \
187
+ -d "${COMMENT_JSON}" 2>/dev/null || echo "000")
188
+
189
+ if [[ "$HTTP" == "201" ]]; then
190
+ echo "Commented on existing issue #${EXISTING}"
191
+ else
192
+ echo "WARNING: Failed to comment on issue #${EXISTING} (HTTP ${HTTP})"
193
+ fi
194
+ else
195
+ # Create new issue
196
+ ISSUE_BODY=$(build_body)
197
+ ISSUE_JSON=$(python3 -c "
198
+ import sys, json
199
+ body = sys.stdin.read()
200
+ print(json.dumps({
201
+ 'title': sys.argv[1],
202
+ 'body': body,
203
+ 'labels': []
204
+ }))" "$TITLE" <<< "$ISSUE_BODY" 2>/dev/null)
205
+
206
+ # Create the issue
207
+ RESPONSE=$(curl -sf -X POST \
208
+ -H "Authorization: token ${GITEA_TOKEN}" \
209
+ -H "Content-Type: application/json" \
210
+ "${API}/issues" \
211
+ -d "${ISSUE_JSON}" 2>/dev/null || echo "{}")
212
+
213
+ ISSUE_NUM=$(echo "$RESPONSE" | grep -oP '"number":\s*\K[0-9]+' | head -1)
214
+
215
+ if [[ -n "$ISSUE_NUM" ]]; then
216
+ # Apply label (separate call — more reliable across Gitea versions)
217
+ LABEL_ID=$(curl -sf \
218
+ -H "Authorization: token ${GITEA_TOKEN}" \
219
+ "${API}/labels" 2>/dev/null \
220
+ | grep -oP "\"id\":\s*\K[0-9]+(?=[^}]*\"name\":\s*\"${LABEL_NAME}\")" \
221
+ | head -1 || true)
222
+
223
+ if [[ -n "$LABEL_ID" ]]; then
224
+ curl -sf -X POST \
225
+ -H "Authorization: token ${GITEA_TOKEN}" \
226
+ -H "Content-Type: application/json" \
227
+ "${API}/issues/${ISSUE_NUM}/labels" \
228
+ -d "{\"labels\":[${LABEL_ID}]}" \
229
+ > /dev/null 2>&1 || true
230
+ fi
231
+
232
+ echo "Created issue #${ISSUE_NUM}: ${TITLE}"
233
+ else
234
+ echo "WARNING: Failed to create issue"
235
+ echo "Response: ${RESPONSE}"
236
+ fi
237
+ fi
@@ -0,0 +1,13 @@
1
+ {
2
+ "defaultConnection": "moko",
3
+ "connections": {
4
+ "moko": {
5
+ "baseUrl": "https://git.mokoconsulting.tech",
6
+ "token": "your-gitea-access-token"
7
+ },
8
+ "github-mirror": {
9
+ "baseUrl": "https://gitea.example.com",
10
+ "token": "your-other-token"
11
+ }
12
+ }
13
+ }
@@ -0,0 +1,15 @@
1
+ import type { GiteaConnection, ApiResponse } from './types.js';
2
+ export declare class GiteaClient {
3
+ private readonly base_url;
4
+ private readonly headers;
5
+ private readonly insecure;
6
+ constructor(conn: GiteaConnection);
7
+ get(endpoint: string, params?: Record<string, string>): Promise<ApiResponse>;
8
+ post(endpoint: string, body?: unknown): Promise<ApiResponse>;
9
+ patch(endpoint: string, body: unknown): Promise<ApiResponse>;
10
+ put(endpoint: string, body: unknown): Promise<ApiResponse>;
11
+ delete(endpoint: string, body?: unknown): Promise<ApiResponse>;
12
+ private buildUrl;
13
+ private request;
14
+ }
15
+ //# sourceMappingURL=client.d.ts.map
package/dist/client.js ADDED
@@ -0,0 +1,104 @@
1
+ /* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
2
+ *
3
+ * This file is part of a Moko Consulting project.
4
+ *
5
+ * SPDX-License-Identifier: GPL-3.0-or-later
6
+ *
7
+ * FILE INFORMATION
8
+ * DEFGROUP: gitea-api-mcp.Client
9
+ * INGROUP: gitea-api-mcp
10
+ * REPO: https://git.mokoconsulting.tech/MokoConsulting/gitea-api-mcp
11
+ * PATH: /src/client.ts
12
+ * VERSION: 01.00.00
13
+ * BRIEF: HTTP client for Gitea REST API v1
14
+ */
15
+ import * as https from 'node:https';
16
+ import * as http from 'node:http';
17
+ const API_PREFIX = '/api/v1';
18
+ const TIMEOUT_MS = 30_000;
19
+ export class GiteaClient {
20
+ base_url;
21
+ headers;
22
+ insecure;
23
+ constructor(conn) {
24
+ this.base_url = conn.baseUrl.replace(/\/+$/, '') + API_PREFIX;
25
+ this.headers = {
26
+ 'Authorization': `token ${conn.token}`,
27
+ 'Content-Type': 'application/json',
28
+ 'Accept': 'application/json',
29
+ };
30
+ this.insecure = conn.insecure ?? false;
31
+ }
32
+ async get(endpoint, params) {
33
+ return this.request(this.buildUrl(endpoint, params), 'GET');
34
+ }
35
+ async post(endpoint, body) {
36
+ return this.request(this.buildUrl(endpoint), 'POST', body);
37
+ }
38
+ async patch(endpoint, body) {
39
+ return this.request(this.buildUrl(endpoint), 'PATCH', body);
40
+ }
41
+ async put(endpoint, body) {
42
+ return this.request(this.buildUrl(endpoint), 'PUT', body);
43
+ }
44
+ async delete(endpoint, body) {
45
+ return this.request(this.buildUrl(endpoint), 'DELETE', body);
46
+ }
47
+ buildUrl(endpoint, params) {
48
+ const path = endpoint.startsWith('/') ? endpoint : `/${endpoint}`;
49
+ const url = new URL(`${this.base_url}${path}`);
50
+ if (params) {
51
+ for (const [key, value] of Object.entries(params)) {
52
+ url.searchParams.set(key, value);
53
+ }
54
+ }
55
+ return url.toString();
56
+ }
57
+ request(url, method, body) {
58
+ return new Promise((resolve, reject) => {
59
+ const parsed = new URL(url);
60
+ const is_https = parsed.protocol === 'https:';
61
+ const transport = is_https ? https : http;
62
+ const options = {
63
+ hostname: parsed.hostname,
64
+ port: parsed.port || (is_https ? 443 : 80),
65
+ path: parsed.pathname + parsed.search,
66
+ method,
67
+ headers: { ...this.headers },
68
+ timeout: TIMEOUT_MS,
69
+ };
70
+ if (this.insecure && is_https) {
71
+ options.rejectUnauthorized = false;
72
+ }
73
+ const payload = body !== undefined ? JSON.stringify(body) : undefined;
74
+ if (payload) {
75
+ options.headers['Content-Length'] = Buffer.byteLength(payload).toString();
76
+ }
77
+ const req = transport.request(options, (res) => {
78
+ const chunks = [];
79
+ res.on('data', (chunk) => chunks.push(chunk));
80
+ res.on('end', () => {
81
+ const raw = Buffer.concat(chunks).toString('utf-8');
82
+ let data;
83
+ try {
84
+ data = JSON.parse(raw);
85
+ }
86
+ catch {
87
+ data = raw;
88
+ }
89
+ resolve({ status: res.statusCode ?? 0, data });
90
+ });
91
+ });
92
+ req.on('error', (err) => reject(err));
93
+ req.on('timeout', () => {
94
+ req.destroy();
95
+ reject(new Error('Request timed out'));
96
+ });
97
+ if (payload) {
98
+ req.write(payload);
99
+ }
100
+ req.end();
101
+ });
102
+ }
103
+ }
104
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1,4 @@
1
+ import type { GiteaConfig, GiteaConnection } from './types.js';
2
+ export declare function loadConfig(): Promise<GiteaConfig>;
3
+ export declare function getConnection(config: GiteaConfig, name?: string): GiteaConnection;
4
+ //# sourceMappingURL=config.d.ts.map
package/dist/config.js ADDED
@@ -0,0 +1,48 @@
1
+ /* Copyright (C) 2026 Moko Consulting <hello@mokoconsulting.tech>
2
+ *
3
+ * This file is part of a Moko Consulting project.
4
+ *
5
+ * SPDX-License-Identifier: GPL-3.0-or-later
6
+ *
7
+ * FILE INFORMATION
8
+ * DEFGROUP: gitea-api-mcp.Config
9
+ * INGROUP: gitea-api-mcp
10
+ * REPO: https://git.mokoconsulting.tech/MokoConsulting/gitea-api-mcp
11
+ * PATH: /src/config.ts
12
+ * VERSION: 01.00.00
13
+ * BRIEF: Configuration loader for Gitea API MCP connections
14
+ */
15
+ import { readFile } from 'node:fs/promises';
16
+ import { resolve } from 'node:path';
17
+ import { homedir } from 'node:os';
18
+ const CONFIG_FILENAME = '.mcp_mokogitea.json';
19
+ export async function loadConfig() {
20
+ const config_path = process.env.GITEA_API_MCP_CONFIG
21
+ ? resolve(process.env.GITEA_API_MCP_CONFIG)
22
+ : resolve(homedir(), CONFIG_FILENAME);
23
+ try {
24
+ const raw = await readFile(config_path, 'utf-8');
25
+ const parsed = JSON.parse(raw);
26
+ if (!parsed.connections || Object.keys(parsed.connections).length === 0) {
27
+ throw new Error('No connections defined in config');
28
+ }
29
+ return {
30
+ connections: parsed.connections,
31
+ defaultConnection: parsed.defaultConnection ?? Object.keys(parsed.connections)[0],
32
+ };
33
+ }
34
+ catch (err) {
35
+ const message = err instanceof Error ? err.message : String(err);
36
+ throw new Error(`Failed to load config from ${config_path}: ${message}\n` +
37
+ `Create ${config_path} — see config.example.json for format.`);
38
+ }
39
+ }
40
+ export function getConnection(config, name) {
41
+ const key = name ?? config.defaultConnection;
42
+ const conn = config.connections[key];
43
+ if (!conn) {
44
+ throw new Error(`Connection "${key}" not found. Available: ${Object.keys(config.connections).join(', ')}`);
45
+ }
46
+ return conn;
47
+ }
48
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map