thepopebot 1.2.56 → 1.2.57
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 +39 -20
- package/bin/cli.js +30 -0
- package/drizzle/0000_initial.sql +52 -0
- package/drizzle/meta/0000_snapshot.json +321 -0
- package/drizzle/meta/_journal.json +13 -0
- package/lib/db/index.js +9 -67
- package/package.json +6 -2
- package/templates/.github/workflows/rebuild-event-handler.yml +0 -1
- package/templates/.github/workflows/upgrade-event-handler.yml +1 -1
- package/templates/CLAUDE.md +12 -5
package/README.md
CHANGED
|
@@ -130,55 +130,74 @@ docker compose up -d
|
|
|
130
130
|
|
|
131
131
|
---
|
|
132
132
|
|
|
133
|
-
## CLI Commands
|
|
134
|
-
|
|
135
|
-
| Command | Description |
|
|
136
|
-
|---------|-------------|
|
|
137
|
-
| `npx thepopebot init` | Scaffold a new project, or check for updated templates in an existing one |
|
|
138
|
-
| `npx thepopebot diff [file]` | List files that differ from package templates, or show the diff for a specific file |
|
|
139
|
-
| `npx thepopebot reset [file]` | List all template files, or restore a specific file (or directory) to the package default |
|
|
140
|
-
| `npm run setup` | Run the full interactive setup wizard |
|
|
141
|
-
| `npm run setup-telegram` | Reconfigure the Telegram webhook (useful when your ngrok URL changes) |
|
|
142
|
-
|
|
143
|
-
---
|
|
144
|
-
|
|
145
133
|
## Updating
|
|
146
134
|
|
|
147
|
-
|
|
135
|
+
**1. Update the package**
|
|
148
136
|
|
|
149
137
|
```bash
|
|
150
138
|
npm update thepopebot
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
**2. Scaffold and update templates**
|
|
142
|
+
|
|
143
|
+
```bash
|
|
151
144
|
npx thepopebot init
|
|
152
145
|
```
|
|
153
146
|
|
|
154
|
-
|
|
147
|
+
This scaffolds any new template files, runs `npm install`, and updates `THEPOPEBOT_VERSION` in your local `.env`.
|
|
148
|
+
|
|
149
|
+
**Managed files** — Infrastructure files tightly coupled to the package version (GitHub Actions workflows, docker-compose, event-handler Dockerfile) are **auto-updated** to match the new package version. These files must stay in your project because GitHub and Docker require them at specific paths, but they shouldn't drift from the package.
|
|
150
|
+
|
|
151
|
+
**User-editable files** — Configuration and app files you're expected to customize (`config/`, `app/`, job Dockerfile) are **never overwritten**. If they differ from the package template, `init` reports the drift so you can review at your own pace:
|
|
155
152
|
|
|
156
153
|
```
|
|
157
154
|
Updated templates available:
|
|
158
155
|
These files differ from the current package templates.
|
|
159
156
|
|
|
160
157
|
config/CRONS.json
|
|
161
|
-
.github/workflows/run-job.yml
|
|
162
158
|
|
|
163
159
|
To view differences: npx thepopebot diff <file>
|
|
164
160
|
To reset to default: npx thepopebot reset <file>
|
|
165
161
|
```
|
|
166
162
|
|
|
167
|
-
Review and accept changes at your own pace:
|
|
168
|
-
|
|
169
163
|
```bash
|
|
170
164
|
npx thepopebot diff config/CRONS.json # see what changed
|
|
171
165
|
npx thepopebot reset config/CRONS.json # accept the new template
|
|
172
166
|
```
|
|
173
167
|
|
|
174
|
-
|
|
168
|
+
If you customize managed files (e.g., adding steps to a workflow), use `--no-managed` to skip auto-updates and handle them yourself:
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
npx thepopebot init --no-managed
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
**3. Rebuild for local dev**
|
|
175
|
+
|
|
176
|
+
```bash
|
|
177
|
+
npm run build
|
|
178
|
+
```
|
|
175
179
|
|
|
176
|
-
|
|
180
|
+
**4. Commit and push**
|
|
177
181
|
|
|
178
182
|
```bash
|
|
179
|
-
|
|
183
|
+
git add -A && git commit -m "upgrade thepopebot to vX.X.X"
|
|
184
|
+
git push
|
|
180
185
|
```
|
|
181
186
|
|
|
187
|
+
Pushing to `main` triggers the `rebuild-event-handler.yml` workflow on your server. It detects the version change, runs `thepopebot init`, updates `THEPOPEBOT_VERSION` in the server's `.env`, pulls the new Docker image, restarts the container, rebuilds `.next`, and reloads PM2 — no manual `docker compose` needed.
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## CLI Commands
|
|
192
|
+
|
|
193
|
+
| Command | Description |
|
|
194
|
+
|---------|-------------|
|
|
195
|
+
| `npx thepopebot init` | Scaffold a new project, or check for updated templates in an existing one |
|
|
196
|
+
| `npx thepopebot diff [file]` | List files that differ from package templates, or show the diff for a specific file |
|
|
197
|
+
| `npx thepopebot reset [file]` | List all template files, or restore a specific file (or directory) to the package default |
|
|
198
|
+
| `npm run setup` | Run the full interactive setup wizard |
|
|
199
|
+
| `npm run setup-telegram` | Reconfigure the Telegram webhook (useful when your ngrok URL changes) |
|
|
200
|
+
|
|
182
201
|
---
|
|
183
202
|
|
|
184
203
|
## Docs
|
package/bin/cli.js
CHANGED
|
@@ -11,6 +11,20 @@ const __dirname = path.dirname(__filename);
|
|
|
11
11
|
const command = process.argv[2];
|
|
12
12
|
const args = process.argv.slice(3);
|
|
13
13
|
|
|
14
|
+
// Files tightly coupled to the package version that are auto-updated by init.
|
|
15
|
+
// These live in the user's project because GitHub/Docker require them at specific paths,
|
|
16
|
+
// but they shouldn't drift from the package version.
|
|
17
|
+
const MANAGED_PATHS = [
|
|
18
|
+
'.github/workflows/',
|
|
19
|
+
'docker/event-handler/',
|
|
20
|
+
'docker-compose.yml',
|
|
21
|
+
'.dockerignore',
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
function isManaged(relPath) {
|
|
25
|
+
return MANAGED_PATHS.some(p => relPath === p || relPath.startsWith(p));
|
|
26
|
+
}
|
|
27
|
+
|
|
14
28
|
function printUsage() {
|
|
15
29
|
console.log(`
|
|
16
30
|
Usage: thepopebot <command>
|
|
@@ -48,6 +62,7 @@ function init() {
|
|
|
48
62
|
const cwd = process.cwd();
|
|
49
63
|
const packageDir = path.join(__dirname, '..');
|
|
50
64
|
const templatesDir = path.join(packageDir, 'templates');
|
|
65
|
+
const noManaged = args.includes('--no-managed');
|
|
51
66
|
|
|
52
67
|
console.log('\nScaffolding thepopebot project...\n');
|
|
53
68
|
|
|
@@ -55,6 +70,7 @@ function init() {
|
|
|
55
70
|
const created = [];
|
|
56
71
|
const skipped = [];
|
|
57
72
|
const changed = [];
|
|
73
|
+
const updated = [];
|
|
58
74
|
|
|
59
75
|
for (const relPath of templateFiles) {
|
|
60
76
|
const src = path.join(templatesDir, relPath);
|
|
@@ -72,6 +88,12 @@ function init() {
|
|
|
72
88
|
const destContent = fs.readFileSync(dest);
|
|
73
89
|
if (srcContent.equals(destContent)) {
|
|
74
90
|
skipped.push(relPath);
|
|
91
|
+
} else if (!noManaged && isManaged(relPath)) {
|
|
92
|
+
// Managed file differs — auto-update to match package
|
|
93
|
+
fs.mkdirSync(path.dirname(dest), { recursive: true });
|
|
94
|
+
fs.copyFileSync(src, dest);
|
|
95
|
+
updated.push(relPath);
|
|
96
|
+
console.log(` Updated ${relPath}`);
|
|
75
97
|
} else {
|
|
76
98
|
changed.push(relPath);
|
|
77
99
|
console.log(` Skipped ${relPath} (already exists)`);
|
|
@@ -121,6 +143,14 @@ function init() {
|
|
|
121
143
|
}
|
|
122
144
|
}
|
|
123
145
|
|
|
146
|
+
// Report updated managed files
|
|
147
|
+
if (updated.length > 0) {
|
|
148
|
+
console.log('\n Updated managed files:');
|
|
149
|
+
for (const file of updated) {
|
|
150
|
+
console.log(` ${file}`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
124
154
|
// Report changed templates
|
|
125
155
|
if (changed.length > 0) {
|
|
126
156
|
console.log('\n Updated templates available:');
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
CREATE TABLE `chats` (
|
|
2
|
+
`id` text PRIMARY KEY NOT NULL,
|
|
3
|
+
`user_id` text NOT NULL,
|
|
4
|
+
`title` text DEFAULT 'New Chat' NOT NULL,
|
|
5
|
+
`starred` integer DEFAULT 0 NOT NULL,
|
|
6
|
+
`created_at` integer NOT NULL,
|
|
7
|
+
`updated_at` integer NOT NULL
|
|
8
|
+
);
|
|
9
|
+
--> statement-breakpoint
|
|
10
|
+
CREATE TABLE `messages` (
|
|
11
|
+
`id` text PRIMARY KEY NOT NULL,
|
|
12
|
+
`chat_id` text NOT NULL,
|
|
13
|
+
`role` text NOT NULL,
|
|
14
|
+
`content` text NOT NULL,
|
|
15
|
+
`created_at` integer NOT NULL
|
|
16
|
+
);
|
|
17
|
+
--> statement-breakpoint
|
|
18
|
+
CREATE TABLE `notifications` (
|
|
19
|
+
`id` text PRIMARY KEY NOT NULL,
|
|
20
|
+
`notification` text NOT NULL,
|
|
21
|
+
`payload` text NOT NULL,
|
|
22
|
+
`read` integer DEFAULT 0 NOT NULL,
|
|
23
|
+
`created_at` integer NOT NULL
|
|
24
|
+
);
|
|
25
|
+
--> statement-breakpoint
|
|
26
|
+
CREATE TABLE `settings` (
|
|
27
|
+
`id` text PRIMARY KEY NOT NULL,
|
|
28
|
+
`type` text NOT NULL,
|
|
29
|
+
`key` text NOT NULL,
|
|
30
|
+
`value` text NOT NULL,
|
|
31
|
+
`created_by` text,
|
|
32
|
+
`created_at` integer NOT NULL,
|
|
33
|
+
`updated_at` integer NOT NULL
|
|
34
|
+
);
|
|
35
|
+
--> statement-breakpoint
|
|
36
|
+
CREATE TABLE `subscriptions` (
|
|
37
|
+
`id` text PRIMARY KEY NOT NULL,
|
|
38
|
+
`platform` text NOT NULL,
|
|
39
|
+
`channel_id` text NOT NULL,
|
|
40
|
+
`created_at` integer NOT NULL
|
|
41
|
+
);
|
|
42
|
+
--> statement-breakpoint
|
|
43
|
+
CREATE TABLE `users` (
|
|
44
|
+
`id` text PRIMARY KEY NOT NULL,
|
|
45
|
+
`email` text NOT NULL,
|
|
46
|
+
`password_hash` text NOT NULL,
|
|
47
|
+
`role` text DEFAULT 'admin' NOT NULL,
|
|
48
|
+
`created_at` integer NOT NULL,
|
|
49
|
+
`updated_at` integer NOT NULL
|
|
50
|
+
);
|
|
51
|
+
--> statement-breakpoint
|
|
52
|
+
CREATE UNIQUE INDEX `users_email_unique` ON `users` (`email`);
|
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": "6",
|
|
3
|
+
"dialect": "sqlite",
|
|
4
|
+
"id": "3312cdb9-4f3b-4004-921b-d6598d2eb2a1",
|
|
5
|
+
"prevId": "00000000-0000-0000-0000-000000000000",
|
|
6
|
+
"tables": {
|
|
7
|
+
"chats": {
|
|
8
|
+
"name": "chats",
|
|
9
|
+
"columns": {
|
|
10
|
+
"id": {
|
|
11
|
+
"name": "id",
|
|
12
|
+
"type": "text",
|
|
13
|
+
"primaryKey": true,
|
|
14
|
+
"notNull": true,
|
|
15
|
+
"autoincrement": false
|
|
16
|
+
},
|
|
17
|
+
"user_id": {
|
|
18
|
+
"name": "user_id",
|
|
19
|
+
"type": "text",
|
|
20
|
+
"primaryKey": false,
|
|
21
|
+
"notNull": true,
|
|
22
|
+
"autoincrement": false
|
|
23
|
+
},
|
|
24
|
+
"title": {
|
|
25
|
+
"name": "title",
|
|
26
|
+
"type": "text",
|
|
27
|
+
"primaryKey": false,
|
|
28
|
+
"notNull": true,
|
|
29
|
+
"autoincrement": false,
|
|
30
|
+
"default": "'New Chat'"
|
|
31
|
+
},
|
|
32
|
+
"starred": {
|
|
33
|
+
"name": "starred",
|
|
34
|
+
"type": "integer",
|
|
35
|
+
"primaryKey": false,
|
|
36
|
+
"notNull": true,
|
|
37
|
+
"autoincrement": false,
|
|
38
|
+
"default": 0
|
|
39
|
+
},
|
|
40
|
+
"created_at": {
|
|
41
|
+
"name": "created_at",
|
|
42
|
+
"type": "integer",
|
|
43
|
+
"primaryKey": false,
|
|
44
|
+
"notNull": true,
|
|
45
|
+
"autoincrement": false
|
|
46
|
+
},
|
|
47
|
+
"updated_at": {
|
|
48
|
+
"name": "updated_at",
|
|
49
|
+
"type": "integer",
|
|
50
|
+
"primaryKey": false,
|
|
51
|
+
"notNull": true,
|
|
52
|
+
"autoincrement": false
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
"indexes": {},
|
|
56
|
+
"foreignKeys": {},
|
|
57
|
+
"compositePrimaryKeys": {},
|
|
58
|
+
"uniqueConstraints": {},
|
|
59
|
+
"checkConstraints": {}
|
|
60
|
+
},
|
|
61
|
+
"messages": {
|
|
62
|
+
"name": "messages",
|
|
63
|
+
"columns": {
|
|
64
|
+
"id": {
|
|
65
|
+
"name": "id",
|
|
66
|
+
"type": "text",
|
|
67
|
+
"primaryKey": true,
|
|
68
|
+
"notNull": true,
|
|
69
|
+
"autoincrement": false
|
|
70
|
+
},
|
|
71
|
+
"chat_id": {
|
|
72
|
+
"name": "chat_id",
|
|
73
|
+
"type": "text",
|
|
74
|
+
"primaryKey": false,
|
|
75
|
+
"notNull": true,
|
|
76
|
+
"autoincrement": false
|
|
77
|
+
},
|
|
78
|
+
"role": {
|
|
79
|
+
"name": "role",
|
|
80
|
+
"type": "text",
|
|
81
|
+
"primaryKey": false,
|
|
82
|
+
"notNull": true,
|
|
83
|
+
"autoincrement": false
|
|
84
|
+
},
|
|
85
|
+
"content": {
|
|
86
|
+
"name": "content",
|
|
87
|
+
"type": "text",
|
|
88
|
+
"primaryKey": false,
|
|
89
|
+
"notNull": true,
|
|
90
|
+
"autoincrement": false
|
|
91
|
+
},
|
|
92
|
+
"created_at": {
|
|
93
|
+
"name": "created_at",
|
|
94
|
+
"type": "integer",
|
|
95
|
+
"primaryKey": false,
|
|
96
|
+
"notNull": true,
|
|
97
|
+
"autoincrement": false
|
|
98
|
+
}
|
|
99
|
+
},
|
|
100
|
+
"indexes": {},
|
|
101
|
+
"foreignKeys": {},
|
|
102
|
+
"compositePrimaryKeys": {},
|
|
103
|
+
"uniqueConstraints": {},
|
|
104
|
+
"checkConstraints": {}
|
|
105
|
+
},
|
|
106
|
+
"notifications": {
|
|
107
|
+
"name": "notifications",
|
|
108
|
+
"columns": {
|
|
109
|
+
"id": {
|
|
110
|
+
"name": "id",
|
|
111
|
+
"type": "text",
|
|
112
|
+
"primaryKey": true,
|
|
113
|
+
"notNull": true,
|
|
114
|
+
"autoincrement": false
|
|
115
|
+
},
|
|
116
|
+
"notification": {
|
|
117
|
+
"name": "notification",
|
|
118
|
+
"type": "text",
|
|
119
|
+
"primaryKey": false,
|
|
120
|
+
"notNull": true,
|
|
121
|
+
"autoincrement": false
|
|
122
|
+
},
|
|
123
|
+
"payload": {
|
|
124
|
+
"name": "payload",
|
|
125
|
+
"type": "text",
|
|
126
|
+
"primaryKey": false,
|
|
127
|
+
"notNull": true,
|
|
128
|
+
"autoincrement": false
|
|
129
|
+
},
|
|
130
|
+
"read": {
|
|
131
|
+
"name": "read",
|
|
132
|
+
"type": "integer",
|
|
133
|
+
"primaryKey": false,
|
|
134
|
+
"notNull": true,
|
|
135
|
+
"autoincrement": false,
|
|
136
|
+
"default": 0
|
|
137
|
+
},
|
|
138
|
+
"created_at": {
|
|
139
|
+
"name": "created_at",
|
|
140
|
+
"type": "integer",
|
|
141
|
+
"primaryKey": false,
|
|
142
|
+
"notNull": true,
|
|
143
|
+
"autoincrement": false
|
|
144
|
+
}
|
|
145
|
+
},
|
|
146
|
+
"indexes": {},
|
|
147
|
+
"foreignKeys": {},
|
|
148
|
+
"compositePrimaryKeys": {},
|
|
149
|
+
"uniqueConstraints": {},
|
|
150
|
+
"checkConstraints": {}
|
|
151
|
+
},
|
|
152
|
+
"settings": {
|
|
153
|
+
"name": "settings",
|
|
154
|
+
"columns": {
|
|
155
|
+
"id": {
|
|
156
|
+
"name": "id",
|
|
157
|
+
"type": "text",
|
|
158
|
+
"primaryKey": true,
|
|
159
|
+
"notNull": true,
|
|
160
|
+
"autoincrement": false
|
|
161
|
+
},
|
|
162
|
+
"type": {
|
|
163
|
+
"name": "type",
|
|
164
|
+
"type": "text",
|
|
165
|
+
"primaryKey": false,
|
|
166
|
+
"notNull": true,
|
|
167
|
+
"autoincrement": false
|
|
168
|
+
},
|
|
169
|
+
"key": {
|
|
170
|
+
"name": "key",
|
|
171
|
+
"type": "text",
|
|
172
|
+
"primaryKey": false,
|
|
173
|
+
"notNull": true,
|
|
174
|
+
"autoincrement": false
|
|
175
|
+
},
|
|
176
|
+
"value": {
|
|
177
|
+
"name": "value",
|
|
178
|
+
"type": "text",
|
|
179
|
+
"primaryKey": false,
|
|
180
|
+
"notNull": true,
|
|
181
|
+
"autoincrement": false
|
|
182
|
+
},
|
|
183
|
+
"created_by": {
|
|
184
|
+
"name": "created_by",
|
|
185
|
+
"type": "text",
|
|
186
|
+
"primaryKey": false,
|
|
187
|
+
"notNull": false,
|
|
188
|
+
"autoincrement": false
|
|
189
|
+
},
|
|
190
|
+
"created_at": {
|
|
191
|
+
"name": "created_at",
|
|
192
|
+
"type": "integer",
|
|
193
|
+
"primaryKey": false,
|
|
194
|
+
"notNull": true,
|
|
195
|
+
"autoincrement": false
|
|
196
|
+
},
|
|
197
|
+
"updated_at": {
|
|
198
|
+
"name": "updated_at",
|
|
199
|
+
"type": "integer",
|
|
200
|
+
"primaryKey": false,
|
|
201
|
+
"notNull": true,
|
|
202
|
+
"autoincrement": false
|
|
203
|
+
}
|
|
204
|
+
},
|
|
205
|
+
"indexes": {},
|
|
206
|
+
"foreignKeys": {},
|
|
207
|
+
"compositePrimaryKeys": {},
|
|
208
|
+
"uniqueConstraints": {},
|
|
209
|
+
"checkConstraints": {}
|
|
210
|
+
},
|
|
211
|
+
"subscriptions": {
|
|
212
|
+
"name": "subscriptions",
|
|
213
|
+
"columns": {
|
|
214
|
+
"id": {
|
|
215
|
+
"name": "id",
|
|
216
|
+
"type": "text",
|
|
217
|
+
"primaryKey": true,
|
|
218
|
+
"notNull": true,
|
|
219
|
+
"autoincrement": false
|
|
220
|
+
},
|
|
221
|
+
"platform": {
|
|
222
|
+
"name": "platform",
|
|
223
|
+
"type": "text",
|
|
224
|
+
"primaryKey": false,
|
|
225
|
+
"notNull": true,
|
|
226
|
+
"autoincrement": false
|
|
227
|
+
},
|
|
228
|
+
"channel_id": {
|
|
229
|
+
"name": "channel_id",
|
|
230
|
+
"type": "text",
|
|
231
|
+
"primaryKey": false,
|
|
232
|
+
"notNull": true,
|
|
233
|
+
"autoincrement": false
|
|
234
|
+
},
|
|
235
|
+
"created_at": {
|
|
236
|
+
"name": "created_at",
|
|
237
|
+
"type": "integer",
|
|
238
|
+
"primaryKey": false,
|
|
239
|
+
"notNull": true,
|
|
240
|
+
"autoincrement": false
|
|
241
|
+
}
|
|
242
|
+
},
|
|
243
|
+
"indexes": {},
|
|
244
|
+
"foreignKeys": {},
|
|
245
|
+
"compositePrimaryKeys": {},
|
|
246
|
+
"uniqueConstraints": {},
|
|
247
|
+
"checkConstraints": {}
|
|
248
|
+
},
|
|
249
|
+
"users": {
|
|
250
|
+
"name": "users",
|
|
251
|
+
"columns": {
|
|
252
|
+
"id": {
|
|
253
|
+
"name": "id",
|
|
254
|
+
"type": "text",
|
|
255
|
+
"primaryKey": true,
|
|
256
|
+
"notNull": true,
|
|
257
|
+
"autoincrement": false
|
|
258
|
+
},
|
|
259
|
+
"email": {
|
|
260
|
+
"name": "email",
|
|
261
|
+
"type": "text",
|
|
262
|
+
"primaryKey": false,
|
|
263
|
+
"notNull": true,
|
|
264
|
+
"autoincrement": false
|
|
265
|
+
},
|
|
266
|
+
"password_hash": {
|
|
267
|
+
"name": "password_hash",
|
|
268
|
+
"type": "text",
|
|
269
|
+
"primaryKey": false,
|
|
270
|
+
"notNull": true,
|
|
271
|
+
"autoincrement": false
|
|
272
|
+
},
|
|
273
|
+
"role": {
|
|
274
|
+
"name": "role",
|
|
275
|
+
"type": "text",
|
|
276
|
+
"primaryKey": false,
|
|
277
|
+
"notNull": true,
|
|
278
|
+
"autoincrement": false,
|
|
279
|
+
"default": "'admin'"
|
|
280
|
+
},
|
|
281
|
+
"created_at": {
|
|
282
|
+
"name": "created_at",
|
|
283
|
+
"type": "integer",
|
|
284
|
+
"primaryKey": false,
|
|
285
|
+
"notNull": true,
|
|
286
|
+
"autoincrement": false
|
|
287
|
+
},
|
|
288
|
+
"updated_at": {
|
|
289
|
+
"name": "updated_at",
|
|
290
|
+
"type": "integer",
|
|
291
|
+
"primaryKey": false,
|
|
292
|
+
"notNull": true,
|
|
293
|
+
"autoincrement": false
|
|
294
|
+
}
|
|
295
|
+
},
|
|
296
|
+
"indexes": {
|
|
297
|
+
"users_email_unique": {
|
|
298
|
+
"name": "users_email_unique",
|
|
299
|
+
"columns": [
|
|
300
|
+
"email"
|
|
301
|
+
],
|
|
302
|
+
"isUnique": true
|
|
303
|
+
}
|
|
304
|
+
},
|
|
305
|
+
"foreignKeys": {},
|
|
306
|
+
"compositePrimaryKeys": {},
|
|
307
|
+
"uniqueConstraints": {},
|
|
308
|
+
"checkConstraints": {}
|
|
309
|
+
}
|
|
310
|
+
},
|
|
311
|
+
"views": {},
|
|
312
|
+
"enums": {},
|
|
313
|
+
"_meta": {
|
|
314
|
+
"schemas": {},
|
|
315
|
+
"tables": {},
|
|
316
|
+
"columns": {}
|
|
317
|
+
},
|
|
318
|
+
"internal": {
|
|
319
|
+
"indexes": {}
|
|
320
|
+
}
|
|
321
|
+
}
|
package/lib/db/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
3
4
|
import Database from 'better-sqlite3';
|
|
4
5
|
import { drizzle } from 'drizzle-orm/better-sqlite3';
|
|
6
|
+
import { migrate } from 'drizzle-orm/better-sqlite3/migrator';
|
|
5
7
|
import { thepopebotDb, dataDir } from '../paths.js';
|
|
6
8
|
import * as schema from './schema.js';
|
|
7
9
|
|
|
@@ -25,84 +27,24 @@ export function getDb() {
|
|
|
25
27
|
}
|
|
26
28
|
|
|
27
29
|
/**
|
|
28
|
-
* Initialize the database —
|
|
30
|
+
* Initialize the database — apply pending migrations.
|
|
29
31
|
* Called from instrumentation.js at server startup.
|
|
32
|
+
* Uses Drizzle Kit migrations from the package's drizzle/ folder.
|
|
30
33
|
*/
|
|
31
34
|
export function initDatabase() {
|
|
32
|
-
// Ensure data directory exists
|
|
33
35
|
if (!fs.existsSync(dataDir)) {
|
|
34
36
|
fs.mkdirSync(dataDir, { recursive: true });
|
|
35
37
|
}
|
|
36
38
|
|
|
37
39
|
const sqlite = new Database(thepopebotDb);
|
|
38
40
|
sqlite.pragma('journal_mode = WAL');
|
|
41
|
+
const db = drizzle(sqlite, { schema });
|
|
39
42
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
email TEXT NOT NULL UNIQUE,
|
|
44
|
-
password_hash TEXT NOT NULL,
|
|
45
|
-
role TEXT NOT NULL DEFAULT 'admin',
|
|
46
|
-
created_at INTEGER NOT NULL,
|
|
47
|
-
updated_at INTEGER NOT NULL
|
|
48
|
-
)
|
|
49
|
-
`);
|
|
43
|
+
// Resolve migrations folder relative to this package (not process.cwd())
|
|
44
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
45
|
+
const migrationsFolder = path.join(__dirname, '..', '..', 'drizzle');
|
|
50
46
|
|
|
51
|
-
|
|
52
|
-
CREATE TABLE IF NOT EXISTS chats (
|
|
53
|
-
id TEXT PRIMARY KEY,
|
|
54
|
-
user_id TEXT NOT NULL,
|
|
55
|
-
title TEXT NOT NULL DEFAULT 'New Chat',
|
|
56
|
-
created_at INTEGER NOT NULL,
|
|
57
|
-
updated_at INTEGER NOT NULL
|
|
58
|
-
)
|
|
59
|
-
`);
|
|
60
|
-
|
|
61
|
-
sqlite.exec(`
|
|
62
|
-
CREATE TABLE IF NOT EXISTS messages (
|
|
63
|
-
id TEXT PRIMARY KEY,
|
|
64
|
-
chat_id TEXT NOT NULL,
|
|
65
|
-
role TEXT NOT NULL,
|
|
66
|
-
content TEXT NOT NULL,
|
|
67
|
-
created_at INTEGER NOT NULL
|
|
68
|
-
)
|
|
69
|
-
`);
|
|
70
|
-
|
|
71
|
-
sqlite.exec(`
|
|
72
|
-
CREATE TABLE IF NOT EXISTS notifications (
|
|
73
|
-
id TEXT PRIMARY KEY,
|
|
74
|
-
notification TEXT NOT NULL,
|
|
75
|
-
payload TEXT NOT NULL,
|
|
76
|
-
read INTEGER NOT NULL DEFAULT 0,
|
|
77
|
-
created_at INTEGER NOT NULL
|
|
78
|
-
)
|
|
79
|
-
`);
|
|
80
|
-
|
|
81
|
-
sqlite.exec(`
|
|
82
|
-
CREATE TABLE IF NOT EXISTS subscriptions (
|
|
83
|
-
id TEXT PRIMARY KEY,
|
|
84
|
-
platform TEXT NOT NULL,
|
|
85
|
-
channel_id TEXT NOT NULL,
|
|
86
|
-
created_at INTEGER NOT NULL
|
|
87
|
-
)
|
|
88
|
-
`);
|
|
89
|
-
|
|
90
|
-
sqlite.exec(`
|
|
91
|
-
CREATE TABLE IF NOT EXISTS settings (
|
|
92
|
-
id TEXT PRIMARY KEY,
|
|
93
|
-
type TEXT NOT NULL,
|
|
94
|
-
key TEXT NOT NULL,
|
|
95
|
-
value TEXT NOT NULL,
|
|
96
|
-
created_by TEXT,
|
|
97
|
-
created_at INTEGER NOT NULL,
|
|
98
|
-
updated_at INTEGER NOT NULL
|
|
99
|
-
)
|
|
100
|
-
`);
|
|
101
|
-
|
|
102
|
-
// Migration: add starred column to chats
|
|
103
|
-
try {
|
|
104
|
-
sqlite.exec(`ALTER TABLE chats ADD COLUMN starred INTEGER NOT NULL DEFAULT 0`);
|
|
105
|
-
} catch {}
|
|
47
|
+
migrate(db, { migrationsFolder });
|
|
106
48
|
|
|
107
49
|
sqlite.close();
|
|
108
50
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "thepopebot",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.57",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Create autonomous AI agents with a two-layer architecture: Next.js Event Handler + Docker Agent.",
|
|
6
6
|
"bin": {
|
|
@@ -25,13 +25,16 @@
|
|
|
25
25
|
"api/",
|
|
26
26
|
"config/",
|
|
27
27
|
"setup/",
|
|
28
|
-
"templates/"
|
|
28
|
+
"templates/",
|
|
29
|
+
"drizzle/"
|
|
29
30
|
],
|
|
30
31
|
"scripts": {
|
|
31
32
|
"build": "esbuild lib/chat/components/*.jsx lib/chat/components/**/*.jsx --outdir=lib/chat/components --format=esm --jsx=automatic --outbase=lib/chat/components",
|
|
32
33
|
"prepublishOnly": "npm run build",
|
|
33
34
|
"local": "bash bin/local.sh",
|
|
34
35
|
"postinstall": "if [ -f bin/postinstall.js ]; then node bin/postinstall.js; fi",
|
|
36
|
+
"db:generate": "drizzle-kit generate",
|
|
37
|
+
"db:studio": "drizzle-kit studio",
|
|
35
38
|
"test": "echo \"No tests yet\" && exit 0"
|
|
36
39
|
},
|
|
37
40
|
"keywords": [
|
|
@@ -85,6 +88,7 @@
|
|
|
85
88
|
}
|
|
86
89
|
},
|
|
87
90
|
"devDependencies": {
|
|
91
|
+
"drizzle-kit": "^0.31.9",
|
|
88
92
|
"esbuild": "^0.27.3"
|
|
89
93
|
},
|
|
90
94
|
"engines": {
|
|
@@ -26,7 +26,7 @@ jobs:
|
|
|
26
26
|
git config user.name "thepopebot"
|
|
27
27
|
git config user.email "thepopebot@users.noreply.github.com"
|
|
28
28
|
|
|
29
|
-
npm install
|
|
29
|
+
npm install --omit=dev
|
|
30
30
|
OLD_VERSION=$(node -p "require(\"./node_modules/thepopebot/package.json\").version")
|
|
31
31
|
npm update thepopebot
|
|
32
32
|
NEW_VERSION=$(node -p "require(\"./node_modules/thepopebot/package.json\").version")
|
package/templates/CLAUDE.md
CHANGED
|
@@ -55,12 +55,19 @@ This is an autonomous AI agent powered by [thepopebot](https://github.com/stephe
|
|
|
55
55
|
|
|
56
56
|
### Updating thepopebot
|
|
57
57
|
|
|
58
|
-
When the package is updated via `npm update thepopebot`,
|
|
58
|
+
When the package is updated via `npm update thepopebot`, run `npx thepopebot init` to apply changes:
|
|
59
59
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
60
|
+
- **Managed files** (GitHub workflows, docker-compose, event-handler Dockerfile) are **auto-updated** to match the package version. These are infrastructure files that must stay in the project but shouldn't drift.
|
|
61
|
+
- **User-editable files** (config, app pages, job Dockerfile) are **never overwritten**. Drifted files are reported so you can review them.
|
|
62
|
+
|
|
63
|
+
```
|
|
64
|
+
1. npm update thepopebot — updates the package
|
|
65
|
+
2. npx thepopebot init — auto-updates managed files, reports drifted user files
|
|
66
|
+
3. npx thepopebot diff <file> — review what changed in a user-editable file
|
|
67
|
+
4. npx thepopebot reset <file> — accept the new template, or manually merge
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Use `npx thepopebot init --no-managed` to skip auto-updates of managed files (for power users who customize workflows).
|
|
64
71
|
|
|
65
72
|
## API Endpoints
|
|
66
73
|
|