@book000/pixivts-db-mysql 0.56.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 (2) hide show
  1. package/README.md +118 -0
  2. package/package.json +63 -0
package/README.md ADDED
@@ -0,0 +1,118 @@
1
+ # @book000/pixivts-db-mysql
2
+
3
+ MySQL response recorder for [`@book000/pixivts`](https://www.npmjs.com/package/@book000/pixivts).
4
+
5
+ Persists every pixiv API response to a MySQL database using [Drizzle ORM](https://orm.drizzle.team/).
6
+
7
+ ## Installation
8
+
9
+ ```shell
10
+ npm install @book000/pixivts-db-mysql
11
+ # or
12
+ pnpm add @book000/pixivts-db-mysql
13
+ # or
14
+ yarn add @book000/pixivts-db-mysql
15
+ ```
16
+
17
+ **Peer dependency**: `@book000/pixivts`
18
+
19
+ ## Usage
20
+
21
+ ```typescript
22
+ import { PixivClient } from '@book000/pixivts'
23
+ import { createResponseRecorder } from '@book000/pixivts-db-mysql'
24
+
25
+ // Create the recorder (connects to MySQL and optionally bootstraps the schema)
26
+ const { interceptor, db, close } = await createResponseRecorder({
27
+ host: 'localhost',
28
+ port: 3306,
29
+ user: 'pixiv',
30
+ password: 'secret',
31
+ database: 'pixivts',
32
+ bootstrap: true, // run CREATE TABLE IF NOT EXISTS on first use
33
+ })
34
+
35
+ // Pass the interceptor to PixivClient
36
+ const client = await PixivClient.of(process.env.PIXIV_REFRESH_TOKEN!, {
37
+ onResponse: interceptor,
38
+ })
39
+
40
+ // Every API call is now recorded to MySQL automatically
41
+ const result = await client.illusts.detail({ illustId: 12345 })
42
+
43
+ // Close the pool when done
44
+ await close()
45
+ ```
46
+
47
+ ### Connection Options
48
+
49
+ Connection options can be passed explicitly or fall back to environment variables:
50
+
51
+ | Option | Env var | Default |
52
+ |---|---|---|
53
+ | `host` | `RESPONSE_DB_HOSTNAME` | `localhost` |
54
+ | `port` | `RESPONSE_DB_PORT` | `3306` |
55
+ | `user` | `RESPONSE_DB_USERNAME` | — |
56
+ | `password` | `RESPONSE_DB_PASSWORD` | — |
57
+ | `database` | `RESPONSE_DB_DATABASE` | — |
58
+ | `bootstrap` | — | `false` |
59
+
60
+ ### Query Helpers
61
+
62
+ ```typescript
63
+ import {
64
+ createResponseRecorder,
65
+ getResponses,
66
+ getResponseCount,
67
+ getEndpoints,
68
+ } from '@book000/pixivts-db-mysql'
69
+
70
+ const { db, close } = await createResponseRecorder({ bootstrap: true })
71
+
72
+ // Get responses with pagination (last 90 days)
73
+ const rows = await getResponses(db, { endpoint: '/v1/illust/detail' }, { page: 1, limit: 50 })
74
+
75
+ // Count matching records
76
+ const count = await getResponseCount(db, { statusCode: 200 })
77
+
78
+ // List all unique endpoints with counts
79
+ const endpoints = await getEndpoints(db)
80
+ // [{ method: 'GET', endpoint: '/v1/illust/detail', statusCode: 200, count: 142 }, ...]
81
+
82
+ await close()
83
+ ```
84
+
85
+ ### Schema
86
+
87
+ The `responses` table stores one row per API call:
88
+
89
+ | Column | Type | Nullable | Description |
90
+ |---|---|---|---|
91
+ | `id` | `INT AUTO_INCREMENT` | NO | Primary key |
92
+ | `method` | `VARCHAR(10)` | NO | HTTP method |
93
+ | `endpoint` | `VARCHAR(255)` | NO | API path |
94
+ | `url` | `TEXT` | YES | Full request URL |
95
+ | `url_hash` | `VARCHAR(255)` | NO | SHA-256 hex of URL (for deduplication) |
96
+ | `request_headers` | `LONGTEXT` | YES | Serialised request headers (JSON) |
97
+ | `request_body` | `LONGTEXT` | YES | Request body (null for GET) |
98
+ | `response_type` | `VARCHAR(10)` | NO | Response content type (`"JSON"` or `"TEXT"`) |
99
+ | `status_code` | `INT` | NO | HTTP status code |
100
+ | `response_headers` | `LONGTEXT` | YES | Serialised response headers (JSON) |
101
+ | `response_body` | `LONGTEXT` | NO | Raw response body |
102
+ | `created_at` | `DATETIME(3)` | NO | Timestamp (millisecond precision) |
103
+
104
+ Duplicate rows (same method + endpoint + statusCode + createdAt + urlHash) are silently ignored via `ON DUPLICATE KEY UPDATE`.
105
+
106
+ ## Database Migration
107
+
108
+ To generate a Drizzle migration file, run from the `packages/db-mysql` directory:
109
+
110
+ ```shell
111
+ pnpm drizzle-kit generate
112
+ ```
113
+
114
+ Alternatively, set `bootstrap: true` in `createResponseRecorder()` to run `CREATE TABLE IF NOT EXISTS` automatically.
115
+
116
+ ## License
117
+
118
+ This project is licensed under the [MIT License](../../LICENSE)
package/package.json ADDED
@@ -0,0 +1,63 @@
1
+ {
2
+ "name": "@book000/pixivts-db-mysql",
3
+ "version": "0.56.0",
4
+ "description": "MySQL response recorder for @book000/pixivts (Drizzle ORM)",
5
+ "keywords": [
6
+ "pixiv",
7
+ "typescript",
8
+ "mysql",
9
+ "drizzle"
10
+ ],
11
+ "homepage": "https://www.npmjs.com/package/@book000/pixivts-db-mysql",
12
+ "bugs": {
13
+ "url": "https://github.com/book000/pixivts/issues"
14
+ },
15
+ "license": "MIT",
16
+ "author": "Tomachi <tomachi@tomacheese.com>",
17
+ "repository": {
18
+ "type": "git",
19
+ "url": "git+https://github.com/book000/pixivts.git",
20
+ "directory": "packages/db-mysql"
21
+ },
22
+ "type": "module",
23
+ "files": [
24
+ "dist"
25
+ ],
26
+ "main": "./dist/index.cjs",
27
+ "module": "./dist/index.js",
28
+ "types": "./dist/index.d.ts",
29
+ "exports": {
30
+ ".": {
31
+ "import": {
32
+ "types": "./dist/index.d.ts",
33
+ "default": "./dist/index.js"
34
+ },
35
+ "require": {
36
+ "types": "./dist/index.d.cts",
37
+ "default": "./dist/index.cjs"
38
+ }
39
+ }
40
+ },
41
+ "dependencies": {
42
+ "drizzle-orm": "0.38.4",
43
+ "mysql2": "3.22.5"
44
+ },
45
+ "peerDependencies": {
46
+ "@book000/pixivts": "workspace:*"
47
+ },
48
+ "devDependencies": {
49
+ "@types/node": "24.13.2",
50
+ "@vitest/coverage-v8": "3.2.4",
51
+ "drizzle-kit": "0.29.1",
52
+ "tsup": "8.5.0",
53
+ "typescript": "6.0.3",
54
+ "vitest": "3.2.4"
55
+ },
56
+ "scripts": {
57
+ "build": "tsup",
58
+ "clean": "rimraf dist",
59
+ "lint": "tsc --noEmit",
60
+ "fix": "echo 'no fix needed'",
61
+ "test:integration": "vitest run --config vitest.integration.config.ts"
62
+ }
63
+ }