shsu 0.0.5 → 0.0.7
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 +32 -4
- package/bin/shsu.mjs +215 -19
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
**S**elf-**H**osted **S**upabase **U**tilities
|
|
4
4
|
|
|
5
|
-
Deploy and manage Supabase Edge Functions on Coolify-hosted Supabase.
|
|
5
|
+
Deploy and manage Supabase Edge Functions and migrations on Coolify-hosted Supabase.
|
|
6
6
|
|
|
7
7
|
## Install
|
|
8
8
|
|
|
@@ -27,17 +27,22 @@ This adds config to your `package.json`:
|
|
|
27
27
|
"shsu": {
|
|
28
28
|
"server": "root@your-coolify-server",
|
|
29
29
|
"remotePath": "/data/coolify/services/YOUR_SERVICE_ID/volumes/functions",
|
|
30
|
-
"url": "https://your-supabase.example.com"
|
|
30
|
+
"url": "https://your-supabase.example.com",
|
|
31
|
+
"edgeContainer": "edge",
|
|
32
|
+
"dbContainer": "postgres"
|
|
31
33
|
}
|
|
32
34
|
}
|
|
33
35
|
```
|
|
34
36
|
|
|
35
|
-
|
|
37
|
+
### Finding Configuration Values
|
|
36
38
|
|
|
39
|
+
**remotePath** - SSH to your server and run:
|
|
37
40
|
```bash
|
|
38
41
|
docker inspect $(docker ps -q --filter 'name=edge') | grep -A 5 "Mounts"
|
|
39
42
|
```
|
|
40
43
|
|
|
44
|
+
**Container names** - SSH to your server and run `docker ps` to list containers. Coolify names containers using the pattern `<service>-<uuid>` (e.g., `abc123-supabase-edge-functions-1`). The filter does substring matching, so `edge` matches any container with "edge" in its name.
|
|
45
|
+
|
|
41
46
|
## Usage
|
|
42
47
|
|
|
43
48
|
```bash
|
|
@@ -56,6 +61,9 @@ shsu deploy hello-world
|
|
|
56
61
|
# Deploy without restarting edge-runtime
|
|
57
62
|
shsu deploy hello-world --no-restart
|
|
58
63
|
|
|
64
|
+
# Run database migrations
|
|
65
|
+
shsu migrate
|
|
66
|
+
|
|
59
67
|
# Stream logs
|
|
60
68
|
shsu logs
|
|
61
69
|
|
|
@@ -75,6 +83,21 @@ shsu new my-function
|
|
|
75
83
|
shsu restart
|
|
76
84
|
```
|
|
77
85
|
|
|
86
|
+
## Migrations
|
|
87
|
+
|
|
88
|
+
Place SQL files in `./supabase/migrations/` (or your configured `migrationsPath`). Files are sorted alphabetically and executed in order.
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
supabase/migrations/
|
|
92
|
+
001_create_users.sql
|
|
93
|
+
002_add_email_index.sql
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Run with:
|
|
97
|
+
```bash
|
|
98
|
+
shsu migrate
|
|
99
|
+
```
|
|
100
|
+
|
|
78
101
|
## Configuration
|
|
79
102
|
|
|
80
103
|
Config is read from `package.json` "shsu" key. Environment variables override package.json values.
|
|
@@ -85,6 +108,9 @@ Config is read from `package.json` "shsu" key. Environment variables override pa
|
|
|
85
108
|
| `remotePath` / `SHSU_REMOTE_PATH` | Yes | Remote path to functions directory |
|
|
86
109
|
| `url` / `SHSU_URL` | For `invoke` | Supabase URL |
|
|
87
110
|
| `localPath` / `SHSU_LOCAL_PATH` | No | Local functions path (default: `./supabase/functions`) |
|
|
111
|
+
| `migrationsPath` / `SHSU_MIGRATIONS_PATH` | No | Local migrations path (default: `./supabase/migrations`) |
|
|
112
|
+
| `edgeContainer` / `SHSU_EDGE_CONTAINER` | No | Edge runtime container filter (default: `edge`) |
|
|
113
|
+
| `dbContainer` / `SHSU_DB_CONTAINER` | No | Database container filter (default: `postgres`) |
|
|
88
114
|
|
|
89
115
|
## MCP Server
|
|
90
116
|
|
|
@@ -136,14 +162,16 @@ Add to `.cursor/mcp.json` in your project:
|
|
|
136
162
|
}
|
|
137
163
|
```
|
|
138
164
|
|
|
139
|
-
### Available Tools
|
|
165
|
+
### Available MCP Tools
|
|
140
166
|
|
|
141
167
|
- `deploy` - Deploy edge functions
|
|
168
|
+
- `migrate` - Run database migrations
|
|
142
169
|
- `list` - List local and remote functions
|
|
143
170
|
- `invoke` - Invoke a function
|
|
144
171
|
- `restart` - Restart edge-runtime
|
|
145
172
|
- `new` - Create new function from template
|
|
146
173
|
- `config` - Show current configuration
|
|
174
|
+
- `docs` - Get setup documentation
|
|
147
175
|
|
|
148
176
|
## Releasing
|
|
149
177
|
|
package/bin/shsu.mjs
CHANGED
|
@@ -27,7 +27,10 @@ function loadConfig() {
|
|
|
27
27
|
server: process.env.SHSU_SERVER || pkgConfig.server,
|
|
28
28
|
remotePath: process.env.SHSU_REMOTE_PATH || pkgConfig.remotePath,
|
|
29
29
|
localPath: process.env.SHSU_LOCAL_PATH || pkgConfig.localPath || './supabase/functions',
|
|
30
|
+
migrationsPath: process.env.SHSU_MIGRATIONS_PATH || pkgConfig.migrationsPath || './supabase/migrations',
|
|
30
31
|
url: process.env.SHSU_URL || pkgConfig.url,
|
|
32
|
+
edgeContainer: process.env.SHSU_EDGE_CONTAINER || pkgConfig.edgeContainer || 'edge',
|
|
33
|
+
dbContainer: process.env.SHSU_DB_CONTAINER || pkgConfig.dbContainer || 'postgres',
|
|
31
34
|
};
|
|
32
35
|
}
|
|
33
36
|
|
|
@@ -85,7 +88,7 @@ function runSync(cmd) {
|
|
|
85
88
|
}
|
|
86
89
|
|
|
87
90
|
function getEdgeContainer() {
|
|
88
|
-
return runSync(`ssh ${config.server} "docker ps -q --filter 'name
|
|
91
|
+
return runSync(`ssh ${config.server} "docker ps -q --filter 'name=${config.edgeContainer}'"`);
|
|
89
92
|
}
|
|
90
93
|
|
|
91
94
|
// ─────────────────────────────────────────────────────────────
|
|
@@ -121,7 +124,7 @@ async function cmdDeploy(funcName, noRestart = false) {
|
|
|
121
124
|
info('Restarting edge-runtime...');
|
|
122
125
|
await run('ssh', [
|
|
123
126
|
config.server,
|
|
124
|
-
`docker restart $(docker ps -q --filter 'name
|
|
127
|
+
`docker restart $(docker ps -q --filter 'name=${config.edgeContainer}')`,
|
|
125
128
|
], { stdio: ['inherit', 'pipe', 'inherit'] });
|
|
126
129
|
success(`Deployed${funcName ? ` ${funcName}` : ''}`);
|
|
127
130
|
} else {
|
|
@@ -136,7 +139,7 @@ async function cmdLogs(filter, lines = 100) {
|
|
|
136
139
|
|
|
137
140
|
const sshArgs = [
|
|
138
141
|
config.server,
|
|
139
|
-
`docker logs -f $(docker ps -q --filter 'name
|
|
142
|
+
`docker logs -f $(docker ps -q --filter 'name=${config.edgeContainer}') --tail ${lines} 2>&1`,
|
|
140
143
|
];
|
|
141
144
|
|
|
142
145
|
if (filter) {
|
|
@@ -196,11 +199,62 @@ async function cmdRestart() {
|
|
|
196
199
|
info('Restarting edge-runtime...');
|
|
197
200
|
await run('ssh', [
|
|
198
201
|
config.server,
|
|
199
|
-
`docker restart $(docker ps -q --filter 'name
|
|
202
|
+
`docker restart $(docker ps -q --filter 'name=${config.edgeContainer}')`,
|
|
200
203
|
], { stdio: ['inherit', 'pipe', 'inherit'] });
|
|
201
204
|
success('Restarted');
|
|
202
205
|
}
|
|
203
206
|
|
|
207
|
+
async function cmdMigrate() {
|
|
208
|
+
requireServer();
|
|
209
|
+
|
|
210
|
+
if (!existsSync(config.migrationsPath)) {
|
|
211
|
+
error(`Migrations folder not found: ${config.migrationsPath}`);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// Get list of migration files
|
|
215
|
+
const migrations = readdirSync(config.migrationsPath)
|
|
216
|
+
.filter((f) => f.endsWith('.sql'))
|
|
217
|
+
.sort();
|
|
218
|
+
|
|
219
|
+
if (migrations.length === 0) {
|
|
220
|
+
info('No migration files found.');
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
info(`Found ${migrations.length} migration(s): ${migrations.join(', ')}`);
|
|
225
|
+
|
|
226
|
+
// Copy migrations to server
|
|
227
|
+
const remoteMigrationsPath = '/tmp/shsu-migrations';
|
|
228
|
+
info('Syncing migrations to server...');
|
|
229
|
+
await run('rsync', [
|
|
230
|
+
'-avz', '--delete',
|
|
231
|
+
`${config.migrationsPath}/`,
|
|
232
|
+
`${config.server}:${remoteMigrationsPath}/`,
|
|
233
|
+
]);
|
|
234
|
+
|
|
235
|
+
// Find the database container
|
|
236
|
+
const dbContainer = runSync(`ssh ${config.server} "docker ps -q --filter 'name=${config.dbContainer}'"`);
|
|
237
|
+
if (!dbContainer) {
|
|
238
|
+
error(`Database container not found (filter: ${config.dbContainer})`);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
// Run each migration
|
|
242
|
+
for (const migration of migrations) {
|
|
243
|
+
info(`Running ${migration}...`);
|
|
244
|
+
try {
|
|
245
|
+
await run('ssh', [
|
|
246
|
+
config.server,
|
|
247
|
+
`docker exec -i ${dbContainer} psql -U postgres -d postgres -f /tmp/shsu-migrations/${migration}`,
|
|
248
|
+
]);
|
|
249
|
+
success(`Applied ${migration}`);
|
|
250
|
+
} catch (e) {
|
|
251
|
+
error(`Failed to apply ${migration}: ${e.message}`);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
success('All migrations applied');
|
|
256
|
+
}
|
|
257
|
+
|
|
204
258
|
async function cmdNew(funcName) {
|
|
205
259
|
if (!funcName) {
|
|
206
260
|
error('Usage: shsu new <function-name>');
|
|
@@ -239,23 +293,26 @@ function cmdEnv() {
|
|
|
239
293
|
console.log(`
|
|
240
294
|
${c.yellow('Configuration (package.json "shsu" key or environment variables):')}
|
|
241
295
|
|
|
242
|
-
server
|
|
243
|
-
remotePath
|
|
244
|
-
url
|
|
245
|
-
localPath
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
SHSU_SERVER, SHSU_REMOTE_PATH, SHSU_URL, SHSU_LOCAL_PATH
|
|
296
|
+
server SSH host for your Coolify server
|
|
297
|
+
remotePath Remote path to functions directory
|
|
298
|
+
url Supabase URL (for invoke command)
|
|
299
|
+
localPath Local functions path (default: ./supabase/functions)
|
|
300
|
+
migrationsPath Local migrations path (default: ./supabase/migrations)
|
|
301
|
+
edgeContainer Edge runtime container filter (default: edge)
|
|
302
|
+
dbContainer Database container filter (default: postgres)
|
|
250
303
|
|
|
251
304
|
${c.yellow('Current values:')}
|
|
252
305
|
|
|
253
|
-
server
|
|
254
|
-
remotePath
|
|
255
|
-
url
|
|
256
|
-
localPath
|
|
306
|
+
server = ${config.server || c.dim('(not set)')}
|
|
307
|
+
remotePath = ${config.remotePath || c.dim('(not set)')}
|
|
308
|
+
url = ${config.url || c.dim('(not set)')}
|
|
309
|
+
localPath = ${config.localPath}
|
|
310
|
+
migrationsPath = ${config.migrationsPath}
|
|
311
|
+
edgeContainer = ${config.edgeContainer}
|
|
312
|
+
dbContainer = ${config.dbContainer}
|
|
257
313
|
|
|
258
314
|
${c.dim('Run "shsu init" to configure via prompts.')}
|
|
315
|
+
${c.dim('Find container names in Coolify: Services → Your Service → look for container name prefix')}
|
|
259
316
|
`);
|
|
260
317
|
}
|
|
261
318
|
|
|
@@ -285,6 +342,8 @@ async function cmdInit() {
|
|
|
285
342
|
const remotePath = await ask('Remote path to functions', config.remotePath);
|
|
286
343
|
const url = await ask('Supabase URL', config.url);
|
|
287
344
|
const localPath = await ask('Local functions path', config.localPath || './supabase/functions');
|
|
345
|
+
const edgeContainer = await ask('Edge container name filter', config.edgeContainer || 'edge');
|
|
346
|
+
const dbContainer = await ask('Database container name filter', config.dbContainer || 'postgres');
|
|
288
347
|
|
|
289
348
|
rl.close();
|
|
290
349
|
|
|
@@ -295,6 +354,8 @@ async function cmdInit() {
|
|
|
295
354
|
remotePath: remotePath || undefined,
|
|
296
355
|
url: url || undefined,
|
|
297
356
|
localPath: localPath !== './supabase/functions' ? localPath : undefined,
|
|
357
|
+
edgeContainer: edgeContainer !== 'edge' ? edgeContainer : undefined,
|
|
358
|
+
dbContainer: dbContainer !== 'postgres' ? dbContainer : undefined,
|
|
298
359
|
};
|
|
299
360
|
|
|
300
361
|
// Remove undefined values
|
|
@@ -362,6 +423,16 @@ async function cmdMcp() {
|
|
|
362
423
|
description: 'Get current shsu configuration.',
|
|
363
424
|
inputSchema: { type: 'object', properties: {} },
|
|
364
425
|
},
|
|
426
|
+
{
|
|
427
|
+
name: 'migrate',
|
|
428
|
+
description: 'Run SQL migrations on the database. Syncs migration files via rsync and executes them via psql.',
|
|
429
|
+
inputSchema: { type: 'object', properties: {} },
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
name: 'docs',
|
|
433
|
+
description: 'Get documentation on how to set up and use shsu for deploying Supabase Edge Functions.',
|
|
434
|
+
inputSchema: { type: 'object', properties: {} },
|
|
435
|
+
},
|
|
365
436
|
];
|
|
366
437
|
|
|
367
438
|
const serverInfo = {
|
|
@@ -411,7 +482,7 @@ async function cmdMcp() {
|
|
|
411
482
|
}
|
|
412
483
|
|
|
413
484
|
if (!noRestart) {
|
|
414
|
-
output += '\n' + captureExec(`ssh ${config.server} "docker restart \\$(docker ps -q --filter 'name
|
|
485
|
+
output += '\n' + captureExec(`ssh ${config.server} "docker restart \\$(docker ps -q --filter 'name=${config.edgeContainer}')"`);
|
|
415
486
|
}
|
|
416
487
|
|
|
417
488
|
return { content: [{ type: 'text', text: `Deployed${funcName ? ` ${funcName}` : ' all functions'}${noRestart ? ' (no restart)' : ''}\n\n${output}` }] };
|
|
@@ -448,7 +519,7 @@ async function cmdMcp() {
|
|
|
448
519
|
if (!config.server) {
|
|
449
520
|
return { content: [{ type: 'text', text: 'Error: server must be configured.' }] };
|
|
450
521
|
}
|
|
451
|
-
const output = captureExec(`ssh ${config.server} "docker restart \\$(docker ps -q --filter 'name
|
|
522
|
+
const output = captureExec(`ssh ${config.server} "docker restart \\$(docker ps -q --filter 'name=${config.edgeContainer}')"`);
|
|
452
523
|
return { content: [{ type: 'text', text: `Restarted edge-runtime\n\n${output}` }] };
|
|
453
524
|
}
|
|
454
525
|
|
|
@@ -487,7 +558,124 @@ async function cmdMcp() {
|
|
|
487
558
|
return {
|
|
488
559
|
content: [{
|
|
489
560
|
type: 'text',
|
|
490
|
-
text: `Current configuration:\n server: ${config.server || '(not set)'}\n remotePath: ${config.remotePath || '(not set)'}\n url: ${config.url || '(not set)'}\n localPath: ${config.localPath}`,
|
|
561
|
+
text: `Current configuration:\n server: ${config.server || '(not set)'}\n remotePath: ${config.remotePath || '(not set)'}\n url: ${config.url || '(not set)'}\n localPath: ${config.localPath}\n migrationsPath: ${config.migrationsPath}\n edgeContainer: ${config.edgeContainer}\n dbContainer: ${config.dbContainer}`,
|
|
562
|
+
}],
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
case 'migrate': {
|
|
567
|
+
if (!config.server) {
|
|
568
|
+
return { content: [{ type: 'text', text: 'Error: server must be configured.' }] };
|
|
569
|
+
}
|
|
570
|
+
if (!existsSync(config.migrationsPath)) {
|
|
571
|
+
return { content: [{ type: 'text', text: `Error: Migrations folder not found: ${config.migrationsPath}` }] };
|
|
572
|
+
}
|
|
573
|
+
const migrations = readdirSync(config.migrationsPath)
|
|
574
|
+
.filter((f) => f.endsWith('.sql'))
|
|
575
|
+
.sort();
|
|
576
|
+
if (migrations.length === 0) {
|
|
577
|
+
return { content: [{ type: 'text', text: 'No migration files found.' }] };
|
|
578
|
+
}
|
|
579
|
+
let output = `Found ${migrations.length} migration(s): ${migrations.join(', ')}\n\n`;
|
|
580
|
+
// Sync migrations
|
|
581
|
+
output += captureExec(`rsync -avz --delete "${config.migrationsPath}/" "${config.server}:/tmp/shsu-migrations/"`) + '\n';
|
|
582
|
+
// Find db container
|
|
583
|
+
const dbContainer = captureExec(`ssh ${config.server} "docker ps -q --filter 'name=${config.dbContainer}'"`);
|
|
584
|
+
if (!dbContainer) {
|
|
585
|
+
return { content: [{ type: 'text', text: `Error: Database container not found (filter: ${config.dbContainer})` }] };
|
|
586
|
+
}
|
|
587
|
+
// Run migrations
|
|
588
|
+
for (const migration of migrations) {
|
|
589
|
+
output += `\nRunning ${migration}...\n`;
|
|
590
|
+
output += captureExec(`ssh ${config.server} "docker exec -i ${dbContainer} psql -U postgres -d postgres -f /tmp/shsu-migrations/${migration}"`) + '\n';
|
|
591
|
+
}
|
|
592
|
+
output += '\nAll migrations applied.';
|
|
593
|
+
return { content: [{ type: 'text', text: output }] };
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
case 'docs': {
|
|
597
|
+
return {
|
|
598
|
+
content: [{
|
|
599
|
+
type: 'text',
|
|
600
|
+
text: `# shsu - Self-Hosted Supabase Utilities
|
|
601
|
+
|
|
602
|
+
Deploy and manage Supabase Edge Functions on Coolify-hosted Supabase.
|
|
603
|
+
|
|
604
|
+
## Project Setup
|
|
605
|
+
|
|
606
|
+
1. **Configure shsu** by adding to package.json:
|
|
607
|
+
\`\`\`json
|
|
608
|
+
{
|
|
609
|
+
"shsu": {
|
|
610
|
+
"server": "root@your-coolify-server",
|
|
611
|
+
"remotePath": "/data/coolify/services/YOUR_SERVICE_ID/volumes/functions",
|
|
612
|
+
"url": "https://your-supabase.example.com",
|
|
613
|
+
"edgeContainer": "edge",
|
|
614
|
+
"dbContainer": "postgres"
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
\`\`\`
|
|
618
|
+
|
|
619
|
+
Or run \`npx shsu init\` for interactive setup.
|
|
620
|
+
|
|
621
|
+
2. **Find configuration values** by SSH'ing to your server:
|
|
622
|
+
- Container names: \`docker ps\` (Coolify uses pattern \`<service>-<uuid>\`)
|
|
623
|
+
- Remote path: \`docker inspect $(docker ps -q --filter 'name=edge') | grep -A 5 "Mounts"\`
|
|
624
|
+
|
|
625
|
+
## Directory Structure
|
|
626
|
+
|
|
627
|
+
\`\`\`
|
|
628
|
+
your-project/
|
|
629
|
+
├── package.json # Contains shsu config
|
|
630
|
+
├── supabase/
|
|
631
|
+
│ ├── functions/ # Edge functions (default localPath)
|
|
632
|
+
│ │ ├── hello-world/
|
|
633
|
+
│ │ │ └── index.ts
|
|
634
|
+
│ │ └── another-func/
|
|
635
|
+
│ │ └── index.ts
|
|
636
|
+
│ └── migrations/ # SQL migrations (default migrationsPath)
|
|
637
|
+
│ ├── 001_create_users.sql
|
|
638
|
+
│ └── 002_add_indexes.sql
|
|
639
|
+
\`\`\`
|
|
640
|
+
|
|
641
|
+
## Configuration Options
|
|
642
|
+
|
|
643
|
+
| Key | Required | Default | Description |
|
|
644
|
+
|-----|----------|---------|-------------|
|
|
645
|
+
| server | Yes | - | SSH host (e.g., root@server.com) |
|
|
646
|
+
| remotePath | Yes | - | Remote path to functions directory |
|
|
647
|
+
| url | For invoke | - | Supabase URL |
|
|
648
|
+
| localPath | No | ./supabase/functions | Local functions path |
|
|
649
|
+
| migrationsPath | No | ./supabase/migrations | Local migrations path |
|
|
650
|
+
| edgeContainer | No | edge | Edge runtime container filter |
|
|
651
|
+
| dbContainer | No | postgres | Database container filter |
|
|
652
|
+
|
|
653
|
+
## Edge Function Template
|
|
654
|
+
|
|
655
|
+
Use \`new\` tool to create functions. Each function needs an index.ts:
|
|
656
|
+
|
|
657
|
+
\`\`\`typescript
|
|
658
|
+
Deno.serve(async (req) => {
|
|
659
|
+
const { name } = await req.json()
|
|
660
|
+
return new Response(
|
|
661
|
+
JSON.stringify({ message: \`Hello \${name}!\` }),
|
|
662
|
+
{ headers: { "Content-Type": "application/json" } }
|
|
663
|
+
)
|
|
664
|
+
})
|
|
665
|
+
\`\`\`
|
|
666
|
+
|
|
667
|
+
## Workflow
|
|
668
|
+
|
|
669
|
+
1. Create function: \`new\` tool with function name
|
|
670
|
+
2. Edit the function code in supabase/functions/<name>/index.ts
|
|
671
|
+
3. Deploy: \`deploy\` tool (syncs via rsync, restarts edge-runtime)
|
|
672
|
+
4. Test: \`invoke\` tool with JSON data
|
|
673
|
+
5. Debug: Check logs on the server
|
|
674
|
+
|
|
675
|
+
## Migrations
|
|
676
|
+
|
|
677
|
+
Place .sql files in supabase/migrations/. They execute alphabetically.
|
|
678
|
+
Use \`migrate\` tool to run all migrations via psql in the database container.`,
|
|
491
679
|
}],
|
|
492
680
|
};
|
|
493
681
|
}
|
|
@@ -559,6 +747,8 @@ ${c.yellow('Commands:')}
|
|
|
559
747
|
- With name: deploy single function
|
|
560
748
|
Options: --no-restart
|
|
561
749
|
|
|
750
|
+
migrate Run SQL migrations on database
|
|
751
|
+
|
|
562
752
|
logs [filter] Stream edge-runtime logs
|
|
563
753
|
- Optional filter string
|
|
564
754
|
|
|
@@ -578,6 +768,7 @@ ${c.yellow('Examples:')}
|
|
|
578
768
|
shsu init
|
|
579
769
|
shsu deploy
|
|
580
770
|
shsu deploy hello-world --no-restart
|
|
771
|
+
shsu migrate
|
|
581
772
|
shsu logs hello-world
|
|
582
773
|
shsu invoke hello-world '{"name":"Stefan"}'
|
|
583
774
|
shsu new my-function
|
|
@@ -617,6 +808,11 @@ async function main() {
|
|
|
617
808
|
case 'restart':
|
|
618
809
|
await cmdRestart();
|
|
619
810
|
break;
|
|
811
|
+
case 'migrate':
|
|
812
|
+
case 'migration':
|
|
813
|
+
case 'migrations':
|
|
814
|
+
await cmdMigrate();
|
|
815
|
+
break;
|
|
620
816
|
case 'new':
|
|
621
817
|
case 'create':
|
|
622
818
|
await cmdNew(args[1]);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shsu",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.7",
|
|
4
4
|
"description": "CLI for deploying and managing Supabase Edge Functions on self-hosted Supabase (Coolify, Docker Compose). Sync functions via rsync, stream logs, and invoke endpoints.",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"test": "echo \"Error: no test specified\" && exit 1"
|