@polterware/polterbase 0.1.2
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/LICENSE +21 -0
- package/README.md +283 -0
- package/dist/index.js +225 -0
- package/package.json +55 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Polterware
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
# @polterware/polterbase
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@polterware/polterbase)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://nodejs.org/)
|
|
6
|
+
|
|
7
|
+
An optimized interactive CLI for managing Supabase CLI workflows with more speed, consistency, and discoverability.
|
|
8
|
+
|
|
9
|
+
Polterbase is a productivity layer on top of the official `supabase` CLI. Instead of memorizing command trees, you choose categories, build commands interactively, attach global flags, and pin common workflows for one-click reuse.
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- **Interactive Command Builder**: Guided flow for command + subcommand + extra args
|
|
14
|
+
- **Supabase Command Discovery**: Organized by practical categories
|
|
15
|
+
- **Global Flags Picker**: Add common global flags in one step
|
|
16
|
+
- **Pinned Commands**: Save successful command combinations for faster repetition
|
|
17
|
+
- **Custom Command Mode**: Run raw Supabase arguments like `-v` or `status -o json`
|
|
18
|
+
- **Shell Execution**: Executes your local `supabase` binary directly
|
|
19
|
+
- **TypeScript-based CLI**: Strongly typed internal implementation
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
## Installation
|
|
24
|
+
|
|
25
|
+
### Run without installing globally
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
npx @polterware/polterbase
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### Install globally
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
npm install -g @polterware/polterbase
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Then run:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
polterbase
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
`polterbase` is a global CLI tool. Do not add it to `dependencies` or `devDependencies` of app projects.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
## Requirements
|
|
48
|
+
|
|
49
|
+
- **Node.js**: `>= 18`
|
|
50
|
+
- **Supabase CLI**: installed and available in `PATH`
|
|
51
|
+
|
|
52
|
+
Check your environment:
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
node -v
|
|
56
|
+
supabase --version
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Install Supabase CLI (official docs):
|
|
60
|
+
|
|
61
|
+
- [Supabase CLI Guide](https://supabase.com/docs/guides/cli)
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Quick Reference
|
|
66
|
+
|
|
67
|
+
### Execution Model
|
|
68
|
+
|
|
69
|
+
Polterbase always executes commands as:
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
supabase <command> <extra-args> <global-flags>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Typical Flow
|
|
76
|
+
|
|
77
|
+
1. Choose a category
|
|
78
|
+
2. Choose a base command
|
|
79
|
+
3. Add optional extra args
|
|
80
|
+
4. Pick optional global flags
|
|
81
|
+
5. Confirm and execute
|
|
82
|
+
6. Optionally pin command after success
|
|
83
|
+
|
|
84
|
+
---
|
|
85
|
+
|
|
86
|
+
## Command Categories
|
|
87
|
+
|
|
88
|
+
### Quick Start
|
|
89
|
+
|
|
90
|
+
- `bootstrap` - Bootstrap a Supabase project from a starter template
|
|
91
|
+
|
|
92
|
+
### Local Development
|
|
93
|
+
|
|
94
|
+
- `db` - Manage Postgres databases
|
|
95
|
+
- `gen` - Run code generation tools
|
|
96
|
+
- `init` - Initialize a local project
|
|
97
|
+
- `inspect` - Inspect Supabase project resources
|
|
98
|
+
- `link` - Link local project to remote Supabase project
|
|
99
|
+
- `login` - Authenticate with Supabase access token
|
|
100
|
+
- `logout` - Remove local auth token
|
|
101
|
+
- `migration` - Manage migration scripts
|
|
102
|
+
- `seed` - Seed project from `supabase/config.toml`
|
|
103
|
+
- `services` - Show local service versions
|
|
104
|
+
- `start` - Start local Supabase containers
|
|
105
|
+
- `status` - Show local container status
|
|
106
|
+
- `stop` - Stop local Supabase containers
|
|
107
|
+
- `test` - Run tests against local stack
|
|
108
|
+
- `unlink` - Unlink local project
|
|
109
|
+
|
|
110
|
+
### Management APIs
|
|
111
|
+
|
|
112
|
+
- `backups`
|
|
113
|
+
- `branches`
|
|
114
|
+
- `config`
|
|
115
|
+
- `domains`
|
|
116
|
+
- `encryption`
|
|
117
|
+
- `functions`
|
|
118
|
+
- `network-bans`
|
|
119
|
+
- `network-restrictions`
|
|
120
|
+
- `orgs`
|
|
121
|
+
- `postgres-config`
|
|
122
|
+
- `projects`
|
|
123
|
+
- `secrets`
|
|
124
|
+
- `snippets`
|
|
125
|
+
- `ssl-enforcement`
|
|
126
|
+
- `sso`
|
|
127
|
+
- `storage`
|
|
128
|
+
- `vanity-subdomains`
|
|
129
|
+
|
|
130
|
+
### Additional Commands
|
|
131
|
+
|
|
132
|
+
- `completion` - Generate shell completion script
|
|
133
|
+
- `help` - Show Supabase command help
|
|
134
|
+
|
|
135
|
+
### Custom Command / Check Version
|
|
136
|
+
|
|
137
|
+
Use this mode for free-form args like:
|
|
138
|
+
|
|
139
|
+
- `-v`
|
|
140
|
+
- `status -o json`
|
|
141
|
+
- `db pull`
|
|
142
|
+
- `projects list`
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## Global Flags
|
|
147
|
+
|
|
148
|
+
Available global flags in the interactive selector:
|
|
149
|
+
|
|
150
|
+
- `--create-ticket` - Create support ticket on error
|
|
151
|
+
- `--debug` - Enable debug logs
|
|
152
|
+
- `--experimental` - Enable experimental features
|
|
153
|
+
- `--yes` - Auto-confirm prompts
|
|
154
|
+
|
|
155
|
+
---
|
|
156
|
+
|
|
157
|
+
## Pinned Commands
|
|
158
|
+
|
|
159
|
+
After a successful execution, Polterbase can pin the command for quick reuse.
|
|
160
|
+
|
|
161
|
+
Pinned items appear at the top of the main menu and can be removed via:
|
|
162
|
+
|
|
163
|
+
- `Manage Pinned Commands`
|
|
164
|
+
|
|
165
|
+
Pins are persisted locally using OS-level app config storage.
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Usage Examples
|
|
170
|
+
|
|
171
|
+
### Check Supabase CLI version
|
|
172
|
+
|
|
173
|
+
Interactive path:
|
|
174
|
+
|
|
175
|
+
1. `Custom Command / Check Version`
|
|
176
|
+
2. Input: `-v`
|
|
177
|
+
|
|
178
|
+
Executed command:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
supabase -v
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### Start local stack with debug
|
|
185
|
+
|
|
186
|
+
Interactive path:
|
|
187
|
+
|
|
188
|
+
1. `Local Development`
|
|
189
|
+
2. Command: `start`
|
|
190
|
+
3. Extra args: none
|
|
191
|
+
4. Flags: `--debug`
|
|
192
|
+
|
|
193
|
+
Executed command:
|
|
194
|
+
|
|
195
|
+
```bash
|
|
196
|
+
supabase start --debug
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### List projects
|
|
200
|
+
|
|
201
|
+
Interactive path:
|
|
202
|
+
|
|
203
|
+
1. `Management APIs`
|
|
204
|
+
2. Command: `projects`
|
|
205
|
+
3. Extra args: `list`
|
|
206
|
+
|
|
207
|
+
Executed command:
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
supabase projects list
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Run DB pull and auto-confirm prompts
|
|
214
|
+
|
|
215
|
+
Interactive path:
|
|
216
|
+
|
|
217
|
+
1. `Local Development`
|
|
218
|
+
2. Command: `db`
|
|
219
|
+
3. Extra args: `pull`
|
|
220
|
+
4. Flags: `--yes`
|
|
221
|
+
|
|
222
|
+
Executed command:
|
|
223
|
+
|
|
224
|
+
```bash
|
|
225
|
+
supabase db pull --yes
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
---
|
|
229
|
+
|
|
230
|
+
## Troubleshooting
|
|
231
|
+
|
|
232
|
+
### `supabase: command not found`
|
|
233
|
+
|
|
234
|
+
Supabase CLI is not installed or not in your `PATH`.
|
|
235
|
+
|
|
236
|
+
Fix:
|
|
237
|
+
|
|
238
|
+
1. Install Supabase CLI
|
|
239
|
+
2. Restart terminal
|
|
240
|
+
3. Run `supabase --version`
|
|
241
|
+
|
|
242
|
+
### Command exits with non-zero code
|
|
243
|
+
|
|
244
|
+
Polterbase forwards execution to Supabase CLI. Use `--debug` and re-run to inspect detailed logs.
|
|
245
|
+
|
|
246
|
+
### Pinned commands are missing
|
|
247
|
+
|
|
248
|
+
Pins are only suggested after successful runs. Confirm the pin prompt after a successful command.
|
|
249
|
+
|
|
250
|
+
### Interactive prompt did not open correctly
|
|
251
|
+
|
|
252
|
+
Ensure you are running in a terminal that supports interactive TTY prompts.
|
|
253
|
+
|
|
254
|
+
---
|
|
255
|
+
|
|
256
|
+
## Security Notes
|
|
257
|
+
|
|
258
|
+
- Polterbase executes local shell commands through your installed Supabase CLI.
|
|
259
|
+
- Keep Supabase tokens out of shared shells and CI logs.
|
|
260
|
+
- Prefer short-lived tokens and least-privileged project access.
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
264
|
+
## Contributing
|
|
265
|
+
|
|
266
|
+
1. Fork the repository
|
|
267
|
+
2. Create a feature branch
|
|
268
|
+
3. Commit changes with clear messages
|
|
269
|
+
4. Open a pull request
|
|
270
|
+
|
|
271
|
+
Repository:
|
|
272
|
+
|
|
273
|
+
- [polterware/polterbase](https://github.com/polterware/polterbase)
|
|
274
|
+
|
|
275
|
+
---
|
|
276
|
+
|
|
277
|
+
## License
|
|
278
|
+
|
|
279
|
+
MIT License - see the [LICENSE](LICENSE) file for details.
|
|
280
|
+
|
|
281
|
+
## Author
|
|
282
|
+
|
|
283
|
+
[Polterware](https://www.polterware.com)
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// src/index.ts
|
|
4
|
+
import * as p from "@clack/prompts";
|
|
5
|
+
import pc from "picocolors";
|
|
6
|
+
import { spawn } from "child_process";
|
|
7
|
+
import Conf from "conf";
|
|
8
|
+
var config = new Conf({ projectName: "polterbase" });
|
|
9
|
+
var supabaseCommands = {
|
|
10
|
+
"Quick Start": [
|
|
11
|
+
{ value: "bootstrap", label: "bootstrap - Bootstrap a Supabase project from a starter template" }
|
|
12
|
+
],
|
|
13
|
+
"Local Development": [
|
|
14
|
+
{ value: "db", label: "db - Manage Postgres databases" },
|
|
15
|
+
{ value: "gen", label: "gen - Run code generation tools" },
|
|
16
|
+
{ value: "init", label: "init - Initialize a local project" },
|
|
17
|
+
{ value: "inspect", label: "inspect - Tools to inspect your Supabase project" },
|
|
18
|
+
{ value: "link", label: "link - Link to a Supabase project" },
|
|
19
|
+
{ value: "login", label: "login - Authenticate using an access token" },
|
|
20
|
+
{ value: "logout", label: "logout - Log out and delete access tokens locally" },
|
|
21
|
+
{ value: "migration", label: "migration - Manage database migration scripts" },
|
|
22
|
+
{ value: "seed", label: "seed - Seed a Supabase project from supabase/config.toml" },
|
|
23
|
+
{ value: "services", label: "services - Show versions of all Supabase services" },
|
|
24
|
+
{ value: "start", label: "start - Start containers for Supabase local development" },
|
|
25
|
+
{ value: "status", label: "status - Show status of local Supabase containers" },
|
|
26
|
+
{ value: "stop", label: "stop - Stop all local Supabase containers" },
|
|
27
|
+
{ value: "test", label: "test - Run tests on local Supabase containers" },
|
|
28
|
+
{ value: "unlink", label: "unlink - Unlink a Supabase project" }
|
|
29
|
+
],
|
|
30
|
+
"Management APIs": [
|
|
31
|
+
{ value: "backups", label: "backups - Manage Supabase physical backups" },
|
|
32
|
+
{ value: "branches", label: "branches - Manage Supabase preview branches" },
|
|
33
|
+
{ value: "config", label: "config - Manage Supabase project configurations" },
|
|
34
|
+
{ value: "domains", label: "domains - Manage custom domain names for Supabase projects" },
|
|
35
|
+
{ value: "encryption", label: "encryption - Manage encryption keys of Supabase projects" },
|
|
36
|
+
{ value: "functions", label: "functions - Manage Supabase Edge functions" },
|
|
37
|
+
{ value: "network-bans", label: "network-bans - Manage network bans" },
|
|
38
|
+
{ value: "network-restrictions", label: "network-restrictions - Manage network restrictions" },
|
|
39
|
+
{ value: "orgs", label: "orgs - Manage Supabase organizations" },
|
|
40
|
+
{ value: "postgres-config", label: "postgres-config - Manage Postgres database config" },
|
|
41
|
+
{ value: "projects", label: "projects - Manage Supabase projects" },
|
|
42
|
+
{ value: "secrets", label: "secrets - Manage Supabase secrets" },
|
|
43
|
+
{ value: "snippets", label: "snippets - Manage Supabase SQL snippets" },
|
|
44
|
+
{ value: "ssl-enforcement", label: "ssl-enforcement - Manage SSL enforcement configuration" },
|
|
45
|
+
{ value: "sso", label: "sso - Manage Single Sign-On (SSO) authentication for projects" },
|
|
46
|
+
{ value: "storage", label: "storage - Manage Supabase Storage objects" },
|
|
47
|
+
{ value: "vanity-subdomains", label: "vanity-subdomains - Manage vanity subdomains for Supabase projects" }
|
|
48
|
+
],
|
|
49
|
+
"Additional Commands": [
|
|
50
|
+
{ value: "completion", label: "completion - Generate the autocompletion script" },
|
|
51
|
+
{ value: "help", label: "help - Help about any command" }
|
|
52
|
+
]
|
|
53
|
+
};
|
|
54
|
+
var globalFlags = [
|
|
55
|
+
{ value: "--create-ticket", label: "--create-ticket (Create support ticket on error)" },
|
|
56
|
+
{ value: "--debug", label: "--debug (Output debug logs)" },
|
|
57
|
+
{ value: "--experimental", label: "--experimental (Enable experimental features)" },
|
|
58
|
+
{ value: "--yes", label: "--yes (Answer yes to all prompts)" }
|
|
59
|
+
];
|
|
60
|
+
function getPinnedCommands() {
|
|
61
|
+
return config.get("pinnedCommands") || [];
|
|
62
|
+
}
|
|
63
|
+
function addPinnedCommand(cmd) {
|
|
64
|
+
const current = getPinnedCommands();
|
|
65
|
+
if (!current.includes(cmd)) {
|
|
66
|
+
config.set("pinnedCommands", [...current, cmd]);
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
function removePinnedCommand(cmd) {
|
|
70
|
+
const current = getPinnedCommands();
|
|
71
|
+
config.set("pinnedCommands", current.filter((c) => c !== cmd));
|
|
72
|
+
}
|
|
73
|
+
async function main() {
|
|
74
|
+
console.clear();
|
|
75
|
+
p.intro(`${pc.bgGreen(pc.black(" POLTERBASE "))} The ultimate modern CLI for Supabase`);
|
|
76
|
+
let shouldExit = false;
|
|
77
|
+
while (!shouldExit) {
|
|
78
|
+
const pinned = getPinnedCommands();
|
|
79
|
+
const mainOptions = [
|
|
80
|
+
{ value: "Quick Start", label: "Quick Start (Bootstrap templates)" },
|
|
81
|
+
{ value: "Local Development", label: "Local Development (db, init, start, etc.)" },
|
|
82
|
+
{ value: "Management APIs", label: "Management APIs (projects, secrets, domains, etc.)" },
|
|
83
|
+
{ value: "Additional Commands", label: "Additional Commands (help, completion)" },
|
|
84
|
+
{ value: "Custom", label: "Custom Command / Check Version" }
|
|
85
|
+
];
|
|
86
|
+
if (pinned.length > 0) {
|
|
87
|
+
mainOptions.unshift(
|
|
88
|
+
{ value: "MANAGE_PINS", label: pc.magenta("\u2699\uFE0F Manage Pinned Commands") },
|
|
89
|
+
...pinned.map((cmd) => ({ value: `PIN:${cmd}`, label: `${pc.cyan("\u{1F4CC}")} ${cmd}` })),
|
|
90
|
+
// @ts-ignore
|
|
91
|
+
{ value: "SEPARATOR", label: pc.dim("\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500"), disabled: true }
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
mainOptions.push({ value: "EXIT", label: pc.red("Exit Polterbase") });
|
|
95
|
+
const category = await p.select({
|
|
96
|
+
message: "What kind of Supabase command do you want to run?",
|
|
97
|
+
// @ts-ignore
|
|
98
|
+
options: mainOptions.filter((opt) => opt.value !== "SEPARATOR"),
|
|
99
|
+
maxItems: 12
|
|
100
|
+
});
|
|
101
|
+
if (p.isCancel(category) || category === "EXIT") {
|
|
102
|
+
p.cancel("See you later!");
|
|
103
|
+
process.exit(0);
|
|
104
|
+
}
|
|
105
|
+
if (category === "MANAGE_PINS") {
|
|
106
|
+
const toRemove = await p.multiselect({
|
|
107
|
+
message: "Select commands to remove from pins (Space to select):",
|
|
108
|
+
options: pinned.map((cmd) => ({ value: cmd, label: cmd })),
|
|
109
|
+
required: false
|
|
110
|
+
});
|
|
111
|
+
if (!p.isCancel(toRemove) && Array.isArray(toRemove)) {
|
|
112
|
+
toRemove.forEach((cmd) => removePinnedCommand(cmd));
|
|
113
|
+
p.log.success("Pins updated!");
|
|
114
|
+
}
|
|
115
|
+
continue;
|
|
116
|
+
}
|
|
117
|
+
let finalArgs = [];
|
|
118
|
+
let isPinnedExecution = false;
|
|
119
|
+
if (typeof category === "string" && category.startsWith("PIN:")) {
|
|
120
|
+
const cmdStr = category.replace("PIN:", "");
|
|
121
|
+
finalArgs = cmdStr.split(" ");
|
|
122
|
+
isPinnedExecution = true;
|
|
123
|
+
} else {
|
|
124
|
+
let commandValue = "";
|
|
125
|
+
if (category === "Custom") {
|
|
126
|
+
const custom = await p.text({
|
|
127
|
+
message: 'Enter your custom supabase command/flags (e.g., "-v" or "status -o json"):',
|
|
128
|
+
placeholder: "-v"
|
|
129
|
+
});
|
|
130
|
+
if (p.isCancel(custom)) continue;
|
|
131
|
+
commandValue = custom;
|
|
132
|
+
} else {
|
|
133
|
+
const options = [
|
|
134
|
+
{ value: "BACK", label: pc.yellow("\u2190 Go Back") },
|
|
135
|
+
// @ts-ignore
|
|
136
|
+
...supabaseCommands[category]
|
|
137
|
+
];
|
|
138
|
+
const command = await p.select({
|
|
139
|
+
message: `Select a command from ${category}:`,
|
|
140
|
+
options,
|
|
141
|
+
maxItems: 11
|
|
142
|
+
});
|
|
143
|
+
if (p.isCancel(command) || command === "BACK") continue;
|
|
144
|
+
const extraArgs = await p.text({
|
|
145
|
+
message: `Any additional sub-commands or arguments for "supabase ${command}"?`,
|
|
146
|
+
placeholder: 'e.g., "push", "pull", "list" (Press Enter to skip)',
|
|
147
|
+
initialValue: ""
|
|
148
|
+
});
|
|
149
|
+
if (p.isCancel(extraArgs)) continue;
|
|
150
|
+
commandValue = `${command} ${extraArgs}`.trim();
|
|
151
|
+
}
|
|
152
|
+
const selectedFlags = await p.multiselect({
|
|
153
|
+
message: "Select any global flags you want to include (Space to select, Enter to confirm):",
|
|
154
|
+
options: globalFlags,
|
|
155
|
+
required: false
|
|
156
|
+
});
|
|
157
|
+
if (p.isCancel(selectedFlags)) continue;
|
|
158
|
+
finalArgs = commandValue.split(" ").filter(Boolean);
|
|
159
|
+
if (Array.isArray(selectedFlags) && selectedFlags.length > 0) {
|
|
160
|
+
finalArgs = finalArgs.concat(selectedFlags);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
const finalCmdString = `supabase ${finalArgs.join(" ")}`;
|
|
164
|
+
const confirm2 = await p.confirm({
|
|
165
|
+
message: `Ready to execute: ${pc.cyan(finalCmdString)}. Continue?`,
|
|
166
|
+
initialValue: true
|
|
167
|
+
});
|
|
168
|
+
if (p.isCancel(confirm2)) continue;
|
|
169
|
+
if (!confirm2) {
|
|
170
|
+
const action = await p.select({
|
|
171
|
+
message: "Command cancelled. What next?",
|
|
172
|
+
options: [
|
|
173
|
+
{ value: "RETRY", label: "Try another command" },
|
|
174
|
+
{ value: "EXIT", label: "Exit" }
|
|
175
|
+
]
|
|
176
|
+
});
|
|
177
|
+
if (action === "RETRY") continue;
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
p.outro(`Executing: ${pc.cyan(finalCmdString)}`);
|
|
181
|
+
const child = spawn("supabase", finalArgs, {
|
|
182
|
+
stdio: "inherit",
|
|
183
|
+
shell: true
|
|
184
|
+
});
|
|
185
|
+
await new Promise((resolve) => {
|
|
186
|
+
child.on("error", (err) => {
|
|
187
|
+
console.error(pc.red(`Failed to start command: ${err.message}`));
|
|
188
|
+
resolve();
|
|
189
|
+
});
|
|
190
|
+
child.on("exit", (code) => {
|
|
191
|
+
if (code !== 0) {
|
|
192
|
+
console.log(pc.red(`
|
|
193
|
+
Command exited with code ${code}`));
|
|
194
|
+
} else {
|
|
195
|
+
console.log(pc.green("\nCommand finished successfully!"));
|
|
196
|
+
if (!isPinnedExecution && !getPinnedCommands().includes(finalArgs.join(" "))) {
|
|
197
|
+
setTimeout(async () => {
|
|
198
|
+
const shouldPin = await p.confirm({
|
|
199
|
+
message: pc.magenta("Pin this command for easy access next time?"),
|
|
200
|
+
initialValue: false
|
|
201
|
+
});
|
|
202
|
+
if (shouldPin && !p.isCancel(shouldPin)) {
|
|
203
|
+
addPinnedCommand(finalArgs.join(" "));
|
|
204
|
+
p.log.success("Pinned! You can find it at the top of the main menu.");
|
|
205
|
+
}
|
|
206
|
+
}, 100);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
resolve();
|
|
210
|
+
});
|
|
211
|
+
});
|
|
212
|
+
const next = await p.confirm({
|
|
213
|
+
message: "Do you want to run another command?",
|
|
214
|
+
initialValue: true
|
|
215
|
+
});
|
|
216
|
+
if (!next || p.isCancel(next)) {
|
|
217
|
+
shouldExit = true;
|
|
218
|
+
} else {
|
|
219
|
+
console.clear();
|
|
220
|
+
p.intro(`${pc.bgGreen(pc.black(" POLTERBASE "))} Continue managing your Supabase project`);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
p.outro("Thank you for using Polterbase!");
|
|
224
|
+
}
|
|
225
|
+
main().catch(console.error);
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@polterware/polterbase",
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"description": "A global CLI for managing Supabase CLI workflows.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"polterbase": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"files": [
|
|
10
|
+
"dist",
|
|
11
|
+
"README.md",
|
|
12
|
+
"LICENSE"
|
|
13
|
+
],
|
|
14
|
+
"repository": {
|
|
15
|
+
"type": "git",
|
|
16
|
+
"url": "https://github.com/polterware/polterbase.git"
|
|
17
|
+
},
|
|
18
|
+
"bugs": {
|
|
19
|
+
"url": "https://github.com/polterware/polterbase/issues"
|
|
20
|
+
},
|
|
21
|
+
"homepage": "https://github.com/polterware/polterbase#readme",
|
|
22
|
+
"publishConfig": {
|
|
23
|
+
"access": "public"
|
|
24
|
+
},
|
|
25
|
+
"preferGlobal": true,
|
|
26
|
+
"scripts": {
|
|
27
|
+
"dev": "tsup src/index.ts --watch --format esm --dts",
|
|
28
|
+
"build": "tsup src/index.ts --format esm --clean",
|
|
29
|
+
"lint": "tsc --noEmit",
|
|
30
|
+
"test": "vitest run",
|
|
31
|
+
"test:watch": "vitest"
|
|
32
|
+
},
|
|
33
|
+
"keywords": [
|
|
34
|
+
"polterware",
|
|
35
|
+
"polterbase",
|
|
36
|
+
"cli",
|
|
37
|
+
"typescript"
|
|
38
|
+
],
|
|
39
|
+
"author": "Polterware",
|
|
40
|
+
"license": "MIT",
|
|
41
|
+
"engines": {
|
|
42
|
+
"node": ">=18"
|
|
43
|
+
},
|
|
44
|
+
"dependencies": {
|
|
45
|
+
"@clack/prompts": "^1.1.0",
|
|
46
|
+
"conf": "^15.1.0",
|
|
47
|
+
"picocolors": "^1.1.1"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@types/node": "^22.13.10",
|
|
51
|
+
"tsup": "^8.3.6",
|
|
52
|
+
"typescript": "^5.8.2",
|
|
53
|
+
"vitest": "^3.0.7"
|
|
54
|
+
}
|
|
55
|
+
}
|