dsh-switchman 1.3.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.
@@ -0,0 +1,322 @@
1
+ ---
2
+ name: db-query
3
+ description: Read-only MySQL/Redis queries via built-in scripts — verify table records, cache keys/fields/TTL, and cross-store consistency. Trigger when the user asks to check or verify database data, including "run this SQL", "check the table", or any MySQL/Redis look-up. If the access address or credentials are unknown, stop and ask the user first; never search for them yourself. Refuse all writes, deletes, DDL, or TTL changes.
4
+ compatibility: Node.js 18+, npm, MySQL 5.7.8+/8.0, Redis 5+; dedicated read-only account required for shared/production environments
5
+ ---
6
+
7
+ <!-- [2026-09-05]-[full English rewrite; top rule: unknown DB access info → stop and ask, never hunt/guess]-[blocks blind or self-sourced connections] -->
8
+ <!-- [2026-09-16]-[broaden the trigger sentence: run-this-SQL / check-the-table phrasings now match too]-[natural trigger rate rises alongside the [DB] hint surfaces] -->
9
+ <!-- [2026-10-01]-[Language section: honor a [SWITCHMAN:LANG] system-prompt line over the English default]-[aligns with the host-side language-preference layer] -->
10
+ # Database Query & Verification
11
+
12
+ Safely query MySQL and Redis via built-in read-only scripts for debugging, data verification, and cache inspection.
13
+ **Core red line: this skill is read-only; every write operation is refused.**
14
+
15
+ ## Trigger guide
16
+
17
+ | Scenario | Trigger? | Notes |
18
+ |------|----------|------|
19
+ | Query MySQL records / verify field values | ✅ | Read-only verification |
20
+ | Query Redis keys/values/TTL/fields | ✅ | Read-only verification |
21
+ | Verify MySQL ↔ Redis consistency | ✅ | Read both sides, then compare |
22
+ | Inspect table structure, indexes, execution plans | ✅ | SHOW / DESCRIBE / EXPLAIN |
23
+ | Count rows, aggregate analysis | ✅ | SELECT COUNT/SUM etc. |
24
+ | Insert/update/delete records | ❌ | Refuse; suggest a read-only verification plan |
25
+ | Create/alter/migrate tables | ❌ | Refuse; out of scope |
26
+ | Change Redis TTL | ❌ | Refuse; EXPIRE is a write command |
27
+ | Flush cache / delete keys | ❌ | Refuse; offer a read-only inspection instead |
28
+ | Export data to files | ❌ | Refuse (INTO OUTFILE is blocked); query and let the user handle results |
29
+
30
+ ## Mandatory read-only rules
31
+
32
+ > **Highest priority.** Violating any item counts as a security violation.
33
+
34
+ 1. **Missing access info → stop and ask**: if the database address or credentials are unknown, stop immediately and ask the user. Never search config files/history on your own, guess, or probe hosts/ports. Without explicit access info, refuse to act rather than act blindly.
35
+ 2. **Built-in scripts only**: queries must go through `scripts/mysql-query.js` or `scripts/redis-query.js`; no fallback to `mysql` / `redis-cli` or ad-hoc code.
36
+ 3. **Never bypass the validator**: do not circumvent SQL/command safety checks by any means other than `--validate-only`.
37
+ 4. **Refuse all write requests**: on any write/modify/delete/DDL request, tell the user "this skill supports read-only verification only" and proactively offer a read-only alternative (e.g. "I can query the current value and status; you apply the change after confirming").
38
+ 5. **Confirm non-local targets first**: before connecting to any database other than `127.0.0.1` / `localhost`, confirm the target address and purpose with the user.
39
+ 6. **Read-only account in production**: production or shared environments must use a dedicated read-only MySQL account and Redis ACL user; see [references/security.md](references/security.md).
40
+
41
+ ## Environment setup
42
+
43
+ Script dependencies are installed **inside the skill directory** — the `skills/db-query` folder of the dsh-switchman bundle (reported as this skill's base directory), so they never touch your project. After the bundle is updated (e.g. its checkout is pulled or reinstalled), re-run the setup once.
44
+ Before first use, run:
45
+
46
+ ```bash
47
+ # from the skill root
48
+ bash scripts/setup.sh
49
+ ```
50
+
51
+ This checks Node.js 18+, installs `mysql2`, `redis` (node-redis v4), `dotenv` into the skill directory, and runs the built-in tests.
52
+
53
+ ## Connection config & password safety
54
+
55
+ ### Precedence
56
+
57
+ **CLI options > explicit `--env-file` > process env vars > defaults**
58
+
59
+ `--max-value-bytes` shares the env var `DB_QUERY_MAX_VALUE_BYTES` (common to MySQL/Redis).
60
+
61
+ ### MySQL env vars
62
+
63
+ | CLI option | Env var | Default | Notes |
64
+ |----------|----------|--------|------|
65
+ | `--host` | `DB_QUERY_MYSQL_HOST` | `127.0.0.1` | Host |
66
+ | `--port` | `DB_QUERY_MYSQL_PORT` | `3306` | Port |
67
+ | `--user` | `DB_QUERY_MYSQL_USER` | **(required)** | Username; no root default |
68
+ | `--password` | `DB_QUERY_MYSQL_PASSWORD` | empty | Password; prefer env vars |
69
+ | `--database` | `DB_QUERY_MYSQL_DATABASE` | empty | Database name; if empty, only queries without a default db work (`SHOW DATABASES`, `SELECT 1`, db-prefixed tables) |
70
+ | `--tls` | `DB_QUERY_MYSQL_TLS` | `false` | Enable TLS |
71
+ | `--ca-file` | `DB_QUERY_MYSQL_CA_FILE` | — | CA certificate path |
72
+ | `--connect-timeout-ms` | `DB_QUERY_MYSQL_CONNECT_TIMEOUT_MS` | `5000` | Connect timeout (max 30000) |
73
+ | `--timeout-ms` | `DB_QUERY_MYSQL_TIMEOUT_MS` | `10000` | Query timeout (max 60000) |
74
+ | `--max-rows` | `DB_QUERY_MYSQL_MAX_ROWS` | `200` | Max rows returned (max 5000) |
75
+ | `--max-value-bytes` | `DB_QUERY_MAX_VALUE_BYTES` | `4096` | Max bytes per field value |
76
+ | `--format` | `DB_QUERY_MYSQL_FORMAT` | `table` | Output format: `table` / `json` |
77
+
78
+ ### Redis env vars
79
+
80
+ | CLI option | Env var | Default | Notes |
81
+ |----------|----------|--------|------|
82
+ | `--host` | `DB_QUERY_REDIS_HOST` | `127.0.0.1` | Host |
83
+ | `--port` | `DB_QUERY_REDIS_PORT` | `6379` | Port |
84
+ | `--user` | `DB_QUERY_REDIS_USER` | `default` | Username |
85
+ | `--password` | `DB_QUERY_REDIS_PASSWORD` | empty | Password; prefer env vars |
86
+ | `--db` | `DB_QUERY_REDIS_DB` | `0` | Database number (connect option only; SELECT command is not exposed) |
87
+ | `--tls` | `DB_QUERY_REDIS_TLS` | `false` | Enable TLS |
88
+ | `--ca-file` | `DB_QUERY_REDIS_CA_FILE` | — | CA certificate path |
89
+ | `--connect-timeout-ms` | `DB_QUERY_REDIS_CONNECT_TIMEOUT_MS` | `5000` | Connect timeout (max 30000) |
90
+ | `--timeout-ms` | `DB_QUERY_REDIS_TIMEOUT_MS` | `10000` | Command timeout (max 60000) |
91
+ | `--max-items` | `DB_QUERY_REDIS_MAX_ITEMS` | `200` | Max items returned (max 5000) |
92
+ | `--max-value-bytes` | `DB_QUERY_MAX_VALUE_BYTES` | `4096` | Max bytes per value |
93
+ | `--format` | `DB_QUERY_REDIS_FORMAT` | `table` | Output format: `table` / `json` |
94
+
95
+ ### Password safety
96
+
97
+ ```bash
98
+ # ❌ Don't do this (password lands in shell history)
99
+ ./scripts/mysql-query.js --user=admin --password=secret --database=mydb 'SELECT 1'
100
+
101
+ # ✅ Recommended: env var
102
+ export DB_QUERY_MYSQL_PASSWORD=secret
103
+ ./scripts/mysql-query.js --user=admin --database=mydb 'SELECT 1'
104
+
105
+ # ✅ Recommended: env file (0600 permissions)
106
+ ./scripts/mysql-query.js --env-file=~/.db-query.env --user=admin --database=mydb 'SELECT 1'
107
+
108
+ # ✅ Recommended: same for Redis
109
+ export DB_QUERY_REDIS_PASSWORD=secret
110
+ ./scripts/redis-query.js --db=0 -- GET user:42
111
+ ```
112
+
113
+ ## Standard workflow
114
+
115
+ 1. **Confirm target and verification goal**: what to query (which table, fields, key) and why (bug investigation, deployment check, consistency). If the access address or credentials are unknown, stop and ask the user; never hunt for them yourself.
116
+ 2. **Write the narrowest query**: prefer primary-key lookups over full scans; add time ranges and LIMIT where possible.
117
+ 3. **Offline validation**: validate SQL/command syntax with `--validate-only` first to confirm it passes safety checks.
118
+ 4. **Confirm non-local targets**: any non-local database must be confirmed with the user first.
119
+ 5. **Execute**: run the script and read the output.
120
+ 6. **Check truncation/timeouts**: if results are truncated (`[TRUNCATED]` marker) or time out, refine the query and re-run.
121
+ 7. **Summarize findings and uncertainties**: state conclusions and clearly flag uncertainties (e.g. time-window inconsistencies, possible misses from truncation).
122
+
123
+ ## MySQL query guide
124
+
125
+ ### Invocation
126
+
127
+ ```bash
128
+ ./scripts/mysql-query.js [connection options] 'SELECT ...'
129
+ ./scripts/mysql-query.js [connection options] --file=/abs/path.sql
130
+ ./scripts/mysql-query.js --validate-only 'SELECT ...'
131
+ ```
132
+
133
+ ### Allowed statements
134
+
135
+ | Type | Example |
136
+ |------|------|
137
+ | `SELECT` | `SELECT id, name FROM users WHERE id = 42` |
138
+ | `WITH...SELECT` (CTE) | `WITH cte AS (SELECT ...) SELECT * FROM cte` |
139
+ | `SHOW` | `SHOW TABLES`, `SHOW CREATE TABLE users` |
140
+ | `DESCRIBE` / `DESC` | `DESCRIBE users` |
141
+ | `EXPLAIN SELECT` | `EXPLAIN SELECT * FROM users WHERE id = 42` |
142
+
143
+ > Note: `EXPLAIN ANALYZE` is **not supported** (security trade-off).
144
+
145
+ ### LIMIT & timeout rules
146
+
147
+ - Without `LIMIT` in the SQL, the script **auto-injects** a top-level `LIMIT` (default 200, adjustable via `--max-rows`, max 5000).
148
+ - With `LIMIT` present, only **plain integers** are accepted (`LIMIT ?`, `LIMIT @a`, `LIMIT 1+1` and other expressions/placeholders/variables are rejected), and the count is checked against `--max-rows`; `LIMIT offset, count` and `LIMIT n OFFSET m` validate the count part.
149
+ - Query timeout defaults to 10000ms (adjustable via `--timeout-ms`, max 60000ms).
150
+
151
+ ### Practical read-only examples
152
+
153
+ ```bash
154
+ # Connectivity test
155
+ ./scripts/mysql-query.js --user=reader --database=mydb 'SELECT 1'
156
+
157
+ # Single record by primary key
158
+ ./scripts/mysql-query.js --user=reader --database=mydb \
159
+ 'SELECT id, username, status, created_at FROM users WHERE id = 42'
160
+
161
+ # Recent records by time range
162
+ ./scripts/mysql-query.js --user=reader --database=mydb --max-rows=50 \
163
+ "SELECT id, status, updated_at FROM orders WHERE created_at >= '2024-01-01' ORDER BY created_at DESC"
164
+
165
+ # Aggregate counts
166
+ ./scripts/mysql-query.js --user=reader --database=mydb \
167
+ 'SELECT status, COUNT(*) AS cnt FROM users GROUP BY status'
168
+
169
+ # Table structure
170
+ ./scripts/mysql-query.js --user=reader --database=mydb 'DESCRIBE users'
171
+
172
+ # Execution plan
173
+ ./scripts/mysql-query.js --user=reader --database=mydb \
174
+ 'EXPLAIN SELECT * FROM orders WHERE user_id = 100'
175
+ ```
176
+
177
+ ## Redis query guide
178
+
179
+ ### Invocation
180
+
181
+ Use `--` to separate connection options from the Redis command:
182
+
183
+ ```bash
184
+ ./scripts/redis-query.js [connection options] -- <command> [args...]
185
+ ./scripts/redis-query.js --validate-only -- <command> [args...]
186
+ ```
187
+
188
+ ### Whitelist by category
189
+
190
+ | Category | Commands |
191
+ |------|------|
192
+ | **General** | PING, EXISTS, TYPE, TTL, PTTL, SCAN, KEYS†, DBSIZE, TIME |
193
+ | **String** | GET, MGET, STRLEN |
194
+ | **Hash** | HGET, HMGET, HEXISTS, HLEN, HGETALL†, HKEYS†, HVALS†, HSCAN |
195
+ | **List** | LINDEX, LLEN, LRANGE |
196
+ | **Set** | SISMEMBER, SCARD, SMEMBERS†, SSCAN |
197
+ | **ZSet** | ZCARD, ZCOUNT, ZSCORE, ZRANK, ZREVRANK, ZRANGE, ZRANGEBYSCORE, ZSCAN |
198
+ | **Server info** | INFO, CLIENT LIST, CONFIG GET† |
199
+
200
+ > † Requires `--allow-unbounded` (in production prefer SCAN over KEYS/HGETALL and other full-key commands).
201
+
202
+ ### TYPE/TTL first, then query by type
203
+
204
+ ```bash
205
+ # Step 1: confirm the key exists and check its type
206
+ ./scripts/redis-query.js -- TTL user:42
207
+ ./scripts/redis-query.js -- TYPE user:42
208
+
209
+ # Step 2: pick the command by type
210
+ # if it's a hash
211
+ ./scripts/redis-query.js -- HGET user:42 name
212
+ ./scripts/redis-query.js -- HGETALL user:42 # full dump (needs --allow-unbounded)
213
+ ./scripts/redis-query.js -- HSCAN user:42 0 COUNT 100 # safe batching
214
+
215
+ # if it's a string
216
+ ./scripts/redis-query.js -- GET user:42
217
+ ```
218
+
219
+ ### Safe per-type examples
220
+
221
+ ```bash
222
+ # Connectivity test
223
+ ./scripts/redis-query.js -- PING
224
+
225
+ # String: batch-check keys
226
+ ./scripts/redis-query.js -- MGET config:timeout config:max-retry
227
+
228
+ # Hash: batched scan
229
+ ./scripts/redis-query.js -- HSCAN session:abc123 0 COUNT 50
230
+
231
+ # List: head/tail of a queue
232
+ ./scripts/redis-query.js -- LRANGE task:queue 0 9
233
+ ./scripts/redis-query.js -- LLEN task:queue
234
+
235
+ # Set: membership check
236
+ ./scripts/redis-query.js -- SISMEMBER online:users user:42
237
+ ./scripts/redis-query.js -- SCARD online:users
238
+
239
+ # ZSet: score range
240
+ ./scripts/redis-query.js -- ZRANGEBYSCORE leaderboard 100 999 WITHSCORES
241
+ ./scripts/redis-query.js -- ZRANK leaderboard user:42
242
+
243
+ # TTL check
244
+ ./scripts/redis-query.js -- TTL cache:homepage
245
+ # -1 = no expiry, -2 = key missing, >= 0 = seconds remaining
246
+ ```
247
+
248
+ ## Cross MySQL/Redis verification
249
+
250
+ Recommended steps for consistency checks:
251
+
252
+ 1. **Get business keys from MySQL**: query the key set to verify first.
253
+ 2. **Targeted Redis lookups**: check Redis per key (or batched); avoid `KEYS *` on the whole db.
254
+ 3. **Compare differences**: compare values and TTL field by field.
255
+
256
+ ```bash
257
+ # Step 1: recently updated user IDs from MySQL
258
+ ./scripts/mysql-query.js --user=reader --database=mydb --max-rows=20 \
259
+ "SELECT id, username, updated_at FROM users WHERE updated_at > '2024-06-01'"
260
+
261
+ # Step 2: verify each in Redis
262
+ ./scripts/redis-query.js -- GET user:1001
263
+ ./scripts/redis-query.js -- TTL user:1001
264
+ ./scripts/redis-query.js -- TYPE user:1001
265
+ ```
266
+
267
+ > ⚠️ **Time-window warning**: data may change between the two reads; you **cannot claim transactional consistency**. Always state "checked at <time>; concurrent changes possible in between" in conclusions.
268
+
269
+ ## Output & error handling
270
+
271
+ ### Output format
272
+
273
+ Controlled by `--format`:
274
+
275
+ | Format | Notes |
276
+ |------|------|
277
+ | `table` | Table output, human-readable |
278
+ | `json` | JSON output, machine-readable |
279
+
280
+ ### Type conversion
281
+
282
+ - Date fields output as strings (`dateStrings` mode); no JS Date conversion.
283
+ - BIGINT / DECIMAL output as strings to avoid precision loss.
284
+ - JSON fields output as formatted strings.
285
+ - Buffer / binary fields rendered as base64 or hex strings.
286
+
287
+ ### Truncation markers
288
+
289
+ - Field values exceeding `--max-value-bytes` (default 4096) are marked `[TRUNCATED]`.
290
+ - Row counts exceeding `--max-rows` (MySQL) / `--max-items` (Redis) truncate the result set with a trailing notice.
291
+ - On truncation, refine the query and re-run; **never draw conclusions from truncated results**.
292
+
293
+ ### Error output
294
+
295
+ Errors are classified by code with sanitized messages, so failures are easy to tell apart:
296
+
297
+ - **Connection failure [code]: message** — connection/auth/handshake errors (`ECONNREFUSED`, `ER_ACCESS_DENIED_ERROR`, `WRONGPASS`, etc.) — couldn't connect.
298
+ - **Query execution error [code]: message** — SQL/command execution errors (`ER_BAD_FIELD_ERROR`(1054), `ER_PARSE_ERROR`, `WRONGTYPE`, etc.) — connected, but the SQL/command itself is wrong (bad column name, type mismatch, etc.).
299
+ - Messages are first-line only and truncated (≤200 chars), inline credentials masked (`://user:pass@host` → `://user:***@host`); passwords from connection strings or full stacks are never echoed.
300
+ - SQL/command validation failures print the concrete rejection reason (e.g. "contains comments", "contains a write operation").
301
+
302
+ > **"Connection failure" → investigate network/credentials; "query execution error" → fix the SQL/command from the message, don't chase connection issues.**
303
+
304
+ ## Post-run self-check
305
+
306
+ After every execution, verify:
307
+
308
+ - [ ] **Read-only**: SQL is SELECT/SHOW/DESCRIBE/EXPLAIN; Redis command is whitelisted.
309
+ - [ ] **Right target**: connected to the intended db/instance, not production (unless explicitly confirmed).
310
+ - [ ] **No truncation**: results not truncated (`[TRUNCATED]` marker); re-query if they were.
311
+ - [ ] **Conclusions hold**: results actually support the claim; flag any uncertainties.
312
+ - [ ] **Sensitive data**: mask as needed when reporting (phone numbers, password hashes, etc.).
313
+
314
+ ## Language
315
+
316
+ English by default; use the project's configured language when a `[SWITCHMAN:LANG]` line in the system prompt specifies one, or when the user explicitly requests it.
317
+
318
+ ## References
319
+
320
+ - [references/security.md](references/security.md) — read-only security model in depth
321
+ - [references/mysql.md](references/mysql.md) — MySQL syntax matrix & query recipes
322
+ - [references/redis.md](references/redis.md) — Redis command whitelist & query patterns
@@ -0,0 +1,251 @@
1
+ {
2
+ "name": "db-query-skill",
3
+ "version": "1.0.0",
4
+ "lockfileVersion": 3,
5
+ "requires": true,
6
+ "packages": {
7
+ "": {
8
+ "name": "db-query-skill",
9
+ "version": "1.0.0",
10
+ "dependencies": {
11
+ "dotenv": "16.6.1",
12
+ "mysql2": "3.12.0",
13
+ "redis": "4.7.1"
14
+ },
15
+ "devDependencies": {},
16
+ "engines": {
17
+ "node": ">=18"
18
+ }
19
+ },
20
+ "node_modules/@redis/bloom": {
21
+ "version": "1.2.0",
22
+ "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.2.0.tgz",
23
+ "integrity": "sha512-HG2DFjYKbpNmVXsa0keLHp/3leGJz1mjh09f2RLGGLQZzSHpkmZWuwJbAvo3QcRY8p80m5+ZdXZdYOSBLlp7Cg==",
24
+ "license": "MIT",
25
+ "peerDependencies": {
26
+ "@redis/client": "^1.0.0"
27
+ }
28
+ },
29
+ "node_modules/@redis/client": {
30
+ "version": "1.6.1",
31
+ "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.6.1.tgz",
32
+ "integrity": "sha512-/KCsg3xSlR+nCK8/8ZYSknYxvXHwubJrU82F3Lm1Fp6789VQ0/3RJKfsmRXjqfaTA++23CvC3hqmqe/2GEt6Kw==",
33
+ "license": "MIT",
34
+ "dependencies": {
35
+ "cluster-key-slot": "1.1.2",
36
+ "generic-pool": "3.9.0",
37
+ "yallist": "4.0.0"
38
+ },
39
+ "engines": {
40
+ "node": ">=14"
41
+ }
42
+ },
43
+ "node_modules/@redis/graph": {
44
+ "version": "1.1.1",
45
+ "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.1.1.tgz",
46
+ "integrity": "sha512-FEMTcTHZozZciLRl6GiiIB4zGm5z5F3F6a6FZCyrfxdKOhFlGkiAqlexWMBzCi4DcRoyiOsuLfW+cjlGWyExOw==",
47
+ "license": "MIT",
48
+ "peerDependencies": {
49
+ "@redis/client": "^1.0.0"
50
+ }
51
+ },
52
+ "node_modules/@redis/json": {
53
+ "version": "1.0.7",
54
+ "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.7.tgz",
55
+ "integrity": "sha512-6UyXfjVaTBTJtKNG4/9Z8PSpKE6XgSyEb8iwaqDcy+uKrd/DGYHTWkUdnQDyzm727V7p21WUMhsqz5oy65kPcQ==",
56
+ "license": "MIT",
57
+ "peerDependencies": {
58
+ "@redis/client": "^1.0.0"
59
+ }
60
+ },
61
+ "node_modules/@redis/search": {
62
+ "version": "1.2.0",
63
+ "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.2.0.tgz",
64
+ "integrity": "sha512-tYoDBbtqOVigEDMAcTGsRlMycIIjwMCgD8eR2t0NANeQmgK/lvxNAvYyb6bZDD4frHRhIHkJu2TBRvB0ERkOmw==",
65
+ "license": "MIT",
66
+ "peerDependencies": {
67
+ "@redis/client": "^1.0.0"
68
+ }
69
+ },
70
+ "node_modules/@redis/time-series": {
71
+ "version": "1.1.0",
72
+ "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.1.0.tgz",
73
+ "integrity": "sha512-c1Q99M5ljsIuc4YdaCwfUEXsofakb9c8+Zse2qxTadu8TalLXuAESzLvFAvNVbkmSlvlzIQOLpBCmWI9wTOt+g==",
74
+ "license": "MIT",
75
+ "peerDependencies": {
76
+ "@redis/client": "^1.0.0"
77
+ }
78
+ },
79
+ "node_modules/aws-ssl-profiles": {
80
+ "version": "1.1.2",
81
+ "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz",
82
+ "integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==",
83
+ "license": "MIT",
84
+ "engines": {
85
+ "node": ">= 6.0.0"
86
+ }
87
+ },
88
+ "node_modules/cluster-key-slot": {
89
+ "version": "1.1.2",
90
+ "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz",
91
+ "integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==",
92
+ "license": "Apache-2.0",
93
+ "engines": {
94
+ "node": ">=0.10.0"
95
+ }
96
+ },
97
+ "node_modules/denque": {
98
+ "version": "2.1.0",
99
+ "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
100
+ "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==",
101
+ "license": "Apache-2.0",
102
+ "engines": {
103
+ "node": ">=0.10"
104
+ }
105
+ },
106
+ "node_modules/dotenv": {
107
+ "version": "16.6.1",
108
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
109
+ "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==",
110
+ "license": "BSD-2-Clause",
111
+ "engines": {
112
+ "node": ">=12"
113
+ },
114
+ "funding": {
115
+ "url": "https://dotenvx.com"
116
+ }
117
+ },
118
+ "node_modules/generate-function": {
119
+ "version": "2.3.1",
120
+ "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz",
121
+ "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==",
122
+ "license": "MIT",
123
+ "dependencies": {
124
+ "is-property": "^1.0.2"
125
+ }
126
+ },
127
+ "node_modules/generic-pool": {
128
+ "version": "3.9.0",
129
+ "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz",
130
+ "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==",
131
+ "license": "MIT",
132
+ "engines": {
133
+ "node": ">= 4"
134
+ }
135
+ },
136
+ "node_modules/iconv-lite": {
137
+ "version": "0.6.3",
138
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
139
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
140
+ "license": "MIT",
141
+ "dependencies": {
142
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
143
+ },
144
+ "engines": {
145
+ "node": ">=0.10.0"
146
+ }
147
+ },
148
+ "node_modules/is-property": {
149
+ "version": "1.0.2",
150
+ "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz",
151
+ "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==",
152
+ "license": "MIT"
153
+ },
154
+ "node_modules/long": {
155
+ "version": "5.3.2",
156
+ "resolved": "https://registry.npmjs.org/long/-/long-5.3.2.tgz",
157
+ "integrity": "sha512-mNAgZ1GmyNhD7AuqnTG3/VQ26o760+ZYBPKjPvugO8+nLbYfX6TVpJPseBvopbdY+qpZ/lKUnmEc1LeZYS3QAA==",
158
+ "license": "Apache-2.0"
159
+ },
160
+ "node_modules/lru.min": {
161
+ "version": "1.1.5",
162
+ "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.5.tgz",
163
+ "integrity": "sha512-5J9ysMYUpYIg9RF2vJpy9SinEmSviFSe0GyPpCQ4L5QSkLAgeLXlTAOu2ZwWUU5m+0SBl6gUU1R1ZQB3aKypfA==",
164
+ "license": "MIT",
165
+ "engines": {
166
+ "bun": ">=1.0.0",
167
+ "deno": ">=1.30.0",
168
+ "node": ">=8.0.0"
169
+ },
170
+ "funding": {
171
+ "type": "github",
172
+ "url": "https://github.com/sponsors/wellwelwel"
173
+ }
174
+ },
175
+ "node_modules/mysql2": {
176
+ "version": "3.12.0",
177
+ "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.12.0.tgz",
178
+ "integrity": "sha512-C8fWhVysZoH63tJbX8d10IAoYCyXy4fdRFz2Ihrt9jtPILYynFEKUUzpp1U7qxzDc3tMbotvaBH+sl6bFnGZiw==",
179
+ "license": "MIT",
180
+ "dependencies": {
181
+ "aws-ssl-profiles": "^1.1.1",
182
+ "denque": "^2.1.0",
183
+ "generate-function": "^2.3.1",
184
+ "iconv-lite": "^0.6.3",
185
+ "long": "^5.2.1",
186
+ "lru.min": "^1.0.0",
187
+ "named-placeholders": "^1.1.3",
188
+ "seq-queue": "^0.0.5",
189
+ "sqlstring": "^2.3.2"
190
+ },
191
+ "engines": {
192
+ "node": ">= 8.0"
193
+ }
194
+ },
195
+ "node_modules/named-placeholders": {
196
+ "version": "1.1.6",
197
+ "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.6.tgz",
198
+ "integrity": "sha512-Tz09sEL2EEuv5fFowm419c1+a/jSMiBjI9gHxVLrVdbUkkNUUfjsVYs9pVZu5oCon/kmRh9TfLEObFtkVxmY0w==",
199
+ "license": "MIT",
200
+ "dependencies": {
201
+ "lru.min": "^1.1.0"
202
+ },
203
+ "engines": {
204
+ "node": ">=8.0.0"
205
+ }
206
+ },
207
+ "node_modules/redis": {
208
+ "version": "4.7.1",
209
+ "resolved": "https://registry.npmjs.org/redis/-/redis-4.7.1.tgz",
210
+ "integrity": "sha512-S1bJDnqLftzHXHP8JsT5II/CtHWQrASX5K96REjWjlmWKrviSOLWmM7QnRLstAWsu1VBBV1ffV6DzCvxNP0UJQ==",
211
+ "license": "MIT",
212
+ "workspaces": [
213
+ "./packages/*"
214
+ ],
215
+ "dependencies": {
216
+ "@redis/bloom": "1.2.0",
217
+ "@redis/client": "1.6.1",
218
+ "@redis/graph": "1.1.1",
219
+ "@redis/json": "1.0.7",
220
+ "@redis/search": "1.2.0",
221
+ "@redis/time-series": "1.1.0"
222
+ }
223
+ },
224
+ "node_modules/safer-buffer": {
225
+ "version": "2.1.2",
226
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
227
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
228
+ "license": "MIT"
229
+ },
230
+ "node_modules/seq-queue": {
231
+ "version": "0.0.5",
232
+ "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz",
233
+ "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q=="
234
+ },
235
+ "node_modules/sqlstring": {
236
+ "version": "2.3.3",
237
+ "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz",
238
+ "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==",
239
+ "license": "MIT",
240
+ "engines": {
241
+ "node": ">= 0.6"
242
+ }
243
+ },
244
+ "node_modules/yallist": {
245
+ "version": "4.0.0",
246
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
247
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
248
+ "license": "ISC"
249
+ }
250
+ }
251
+ }
@@ -0,0 +1,20 @@
1
+ {
2
+ "name": "db-query-skill",
3
+ "version": "1.0.0",
4
+ "private": true,
5
+ "description": "pi 技能:数据库只读查询核验(MySQL / Redis)",
6
+ "engines": {
7
+ "node": ">=18"
8
+ },
9
+ "type": "commonjs",
10
+ "scripts": {
11
+ "test": "node --test tests/*.test.js",
12
+ "setup": "bash scripts/setup.sh"
13
+ },
14
+ "dependencies": {
15
+ "dotenv": "16.6.1",
16
+ "mysql2": "3.12.0",
17
+ "redis": "4.7.1"
18
+ },
19
+ "devDependencies": {}
20
+ }