@polterware/polter 0.0.0 → 0.1.1
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/dist/api.js +45 -0
- package/dist/chunk-EB76TTZL.js +0 -0
- package/dist/chunk-TWWRDI3Q.js +1488 -0
- package/dist/index.js +2989 -952
- package/dist/mcp.js +13965 -0
- package/package.json +6 -4
|
@@ -0,0 +1,1488 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __export = (target, all) => {
|
|
3
|
+
for (var name in all)
|
|
4
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
// src/data/commands/supabase.ts
|
|
8
|
+
var supabaseCommands = [
|
|
9
|
+
// Quick Start
|
|
10
|
+
{
|
|
11
|
+
id: "supabase:bootstrap",
|
|
12
|
+
tool: "supabase",
|
|
13
|
+
base: ["bootstrap"],
|
|
14
|
+
label: "bootstrap",
|
|
15
|
+
hint: "Bootstrap from a starter template"
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
id: "supabase:init",
|
|
19
|
+
tool: "supabase",
|
|
20
|
+
base: ["init"],
|
|
21
|
+
label: "init",
|
|
22
|
+
hint: "Initialize a local project"
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
id: "supabase:login",
|
|
26
|
+
tool: "supabase",
|
|
27
|
+
base: ["login"],
|
|
28
|
+
label: "login",
|
|
29
|
+
hint: "Authenticate with access token"
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
id: "supabase:logout",
|
|
33
|
+
tool: "supabase",
|
|
34
|
+
base: ["logout"],
|
|
35
|
+
label: "logout",
|
|
36
|
+
hint: "Remove local auth token"
|
|
37
|
+
},
|
|
38
|
+
// Local Dev
|
|
39
|
+
{
|
|
40
|
+
id: "supabase:start",
|
|
41
|
+
tool: "supabase",
|
|
42
|
+
base: ["start"],
|
|
43
|
+
label: "start",
|
|
44
|
+
hint: "Start local Supabase containers"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
id: "supabase:stop",
|
|
48
|
+
tool: "supabase",
|
|
49
|
+
base: ["stop"],
|
|
50
|
+
label: "stop",
|
|
51
|
+
hint: "Stop local Supabase containers"
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
id: "supabase:status",
|
|
55
|
+
tool: "supabase",
|
|
56
|
+
base: ["status"],
|
|
57
|
+
label: "status",
|
|
58
|
+
hint: "Show container status"
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
id: "supabase:db",
|
|
62
|
+
tool: "supabase",
|
|
63
|
+
base: ["db"],
|
|
64
|
+
label: "db",
|
|
65
|
+
hint: "Manage Postgres databases",
|
|
66
|
+
suggestedArgs: [
|
|
67
|
+
{ value: "pull", label: "pull", hint: "Pull schema from remote", args: ["pull"] },
|
|
68
|
+
{ value: "push", label: "push", hint: "Push local migrations", args: ["push"] },
|
|
69
|
+
{ value: "reset", label: "reset", hint: "Reset local database", args: ["reset"] },
|
|
70
|
+
{ value: "dump", label: "dump", hint: "Dump schema/data", args: ["dump"] },
|
|
71
|
+
{ value: "diff", label: "diff", hint: "Show migration diff", args: ["diff"] },
|
|
72
|
+
{ value: "lint", label: "lint", hint: "Lint SQL migrations", args: ["lint"] }
|
|
73
|
+
]
|
|
74
|
+
},
|
|
75
|
+
{
|
|
76
|
+
id: "supabase:migration",
|
|
77
|
+
tool: "supabase",
|
|
78
|
+
base: ["migration"],
|
|
79
|
+
label: "migration",
|
|
80
|
+
hint: "Manage migration scripts",
|
|
81
|
+
suggestedArgs: [
|
|
82
|
+
{ value: "new", label: "new <name>", hint: "Create migration file", args: ["new"] },
|
|
83
|
+
{ value: "up", label: "up", hint: "Apply pending migrations", args: ["up"] },
|
|
84
|
+
{ value: "down", label: "down", hint: "Rollback last migration", args: ["down"] },
|
|
85
|
+
{ value: "list", label: "list", hint: "List local migrations", args: ["list"] },
|
|
86
|
+
{ value: "repair", label: "repair", hint: "Repair migration history", args: ["repair"] },
|
|
87
|
+
{ value: "fetch", label: "fetch", hint: "Fetch migration history", args: ["fetch"] }
|
|
88
|
+
]
|
|
89
|
+
},
|
|
90
|
+
{
|
|
91
|
+
id: "supabase:seed",
|
|
92
|
+
tool: "supabase",
|
|
93
|
+
base: ["seed"],
|
|
94
|
+
label: "seed",
|
|
95
|
+
hint: "Seed from config.toml",
|
|
96
|
+
suggestedArgs: [
|
|
97
|
+
{ value: "run", label: "run", hint: "Run configured seed file", args: ["run"] }
|
|
98
|
+
]
|
|
99
|
+
},
|
|
100
|
+
{
|
|
101
|
+
id: "supabase:test",
|
|
102
|
+
tool: "supabase",
|
|
103
|
+
base: ["test"],
|
|
104
|
+
label: "test",
|
|
105
|
+
hint: "Run tests on local stack"
|
|
106
|
+
},
|
|
107
|
+
// Inspect & Generate
|
|
108
|
+
{
|
|
109
|
+
id: "supabase:inspect",
|
|
110
|
+
tool: "supabase",
|
|
111
|
+
base: ["inspect"],
|
|
112
|
+
label: "inspect",
|
|
113
|
+
hint: "Inspect project resources"
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
id: "supabase:gen",
|
|
117
|
+
tool: "supabase",
|
|
118
|
+
base: ["gen"],
|
|
119
|
+
label: "gen",
|
|
120
|
+
hint: "Run code generation tools"
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
id: "supabase:services",
|
|
124
|
+
tool: "supabase",
|
|
125
|
+
base: ["services"],
|
|
126
|
+
label: "services",
|
|
127
|
+
hint: "Show service versions"
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
id: "supabase:link",
|
|
131
|
+
tool: "supabase",
|
|
132
|
+
base: ["link"],
|
|
133
|
+
label: "link",
|
|
134
|
+
hint: "Link to remote project"
|
|
135
|
+
},
|
|
136
|
+
{
|
|
137
|
+
id: "supabase:unlink",
|
|
138
|
+
tool: "supabase",
|
|
139
|
+
base: ["unlink"],
|
|
140
|
+
label: "unlink",
|
|
141
|
+
hint: "Unlink remote project"
|
|
142
|
+
},
|
|
143
|
+
// Cloud Management
|
|
144
|
+
{
|
|
145
|
+
id: "supabase:projects",
|
|
146
|
+
tool: "supabase",
|
|
147
|
+
base: ["projects"],
|
|
148
|
+
label: "projects",
|
|
149
|
+
hint: "Manage Supabase projects",
|
|
150
|
+
suggestedArgs: [
|
|
151
|
+
{ value: "list", label: "list", hint: "List projects", args: ["list"] },
|
|
152
|
+
{ value: "create", label: "create", hint: "Create project", args: ["create"] },
|
|
153
|
+
{ value: "delete", label: "delete", hint: "Delete project", args: ["delete"] }
|
|
154
|
+
]
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
id: "supabase:functions",
|
|
158
|
+
tool: "supabase",
|
|
159
|
+
base: ["functions"],
|
|
160
|
+
label: "functions",
|
|
161
|
+
hint: "Manage Edge Functions",
|
|
162
|
+
suggestedArgs: [
|
|
163
|
+
{ value: "list", label: "list", hint: "List functions", args: ["list"] },
|
|
164
|
+
{ value: "new", label: "new <name>", hint: "Create a function", args: ["new"] },
|
|
165
|
+
{ value: "serve", label: "serve", hint: "Serve functions locally", args: ["serve"] },
|
|
166
|
+
{ value: "deploy", label: "deploy <name>", hint: "Deploy function", args: ["deploy"] },
|
|
167
|
+
{ value: "delete", label: "delete <name>", hint: "Delete function", args: ["delete"] }
|
|
168
|
+
]
|
|
169
|
+
},
|
|
170
|
+
{
|
|
171
|
+
id: "supabase:secrets",
|
|
172
|
+
tool: "supabase",
|
|
173
|
+
base: ["secrets"],
|
|
174
|
+
label: "secrets",
|
|
175
|
+
hint: "Manage project secrets"
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
id: "supabase:config",
|
|
179
|
+
tool: "supabase",
|
|
180
|
+
base: ["config"],
|
|
181
|
+
label: "config",
|
|
182
|
+
hint: "Manage project configuration"
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
id: "supabase:storage",
|
|
186
|
+
tool: "supabase",
|
|
187
|
+
base: ["storage"],
|
|
188
|
+
label: "storage",
|
|
189
|
+
hint: "Manage Storage objects",
|
|
190
|
+
suggestedArgs: [
|
|
191
|
+
{ value: "ls", label: "ls", hint: "List storage objects", args: ["ls"] },
|
|
192
|
+
{ value: "cp", label: "cp", hint: "Copy storage object", args: ["cp"] },
|
|
193
|
+
{ value: "mv", label: "mv", hint: "Move storage object", args: ["mv"] },
|
|
194
|
+
{ value: "rm", label: "rm", hint: "Remove storage object", args: ["rm"] }
|
|
195
|
+
]
|
|
196
|
+
},
|
|
197
|
+
// Networking & Security
|
|
198
|
+
{
|
|
199
|
+
id: "supabase:domains",
|
|
200
|
+
tool: "supabase",
|
|
201
|
+
base: ["domains"],
|
|
202
|
+
label: "domains",
|
|
203
|
+
hint: "Manage custom domains"
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
id: "supabase:ssl-enforcement",
|
|
207
|
+
tool: "supabase",
|
|
208
|
+
base: ["ssl-enforcement"],
|
|
209
|
+
label: "ssl-enforcement",
|
|
210
|
+
hint: "Manage SSL config"
|
|
211
|
+
},
|
|
212
|
+
{
|
|
213
|
+
id: "supabase:network-bans",
|
|
214
|
+
tool: "supabase",
|
|
215
|
+
base: ["network-bans"],
|
|
216
|
+
label: "network-bans",
|
|
217
|
+
hint: "Manage network bans"
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
id: "supabase:network-restrictions",
|
|
221
|
+
tool: "supabase",
|
|
222
|
+
base: ["network-restrictions"],
|
|
223
|
+
label: "network-restrictions",
|
|
224
|
+
hint: "Manage network restrictions"
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
id: "supabase:vanity-subdomains",
|
|
228
|
+
tool: "supabase",
|
|
229
|
+
base: ["vanity-subdomains"],
|
|
230
|
+
label: "vanity-subdomains",
|
|
231
|
+
hint: "Manage vanity subdomains"
|
|
232
|
+
},
|
|
233
|
+
{
|
|
234
|
+
id: "supabase:encryption",
|
|
235
|
+
tool: "supabase",
|
|
236
|
+
base: ["encryption"],
|
|
237
|
+
label: "encryption",
|
|
238
|
+
hint: "Manage encryption keys"
|
|
239
|
+
},
|
|
240
|
+
// Organizations & Admin
|
|
241
|
+
{
|
|
242
|
+
id: "supabase:orgs",
|
|
243
|
+
tool: "supabase",
|
|
244
|
+
base: ["orgs"],
|
|
245
|
+
label: "orgs",
|
|
246
|
+
hint: "Manage organizations",
|
|
247
|
+
suggestedArgs: [
|
|
248
|
+
{ value: "list", label: "list", hint: "List organizations", args: ["list"] },
|
|
249
|
+
{ value: "create", label: "create", hint: "Create organization", args: ["create"] }
|
|
250
|
+
]
|
|
251
|
+
},
|
|
252
|
+
{
|
|
253
|
+
id: "supabase:sso",
|
|
254
|
+
tool: "supabase",
|
|
255
|
+
base: ["sso"],
|
|
256
|
+
label: "sso",
|
|
257
|
+
hint: "Manage Single Sign-On"
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
id: "supabase:branches",
|
|
261
|
+
tool: "supabase",
|
|
262
|
+
base: ["branches"],
|
|
263
|
+
label: "branches",
|
|
264
|
+
hint: "Manage preview branches"
|
|
265
|
+
},
|
|
266
|
+
{
|
|
267
|
+
id: "supabase:backups",
|
|
268
|
+
tool: "supabase",
|
|
269
|
+
base: ["backups"],
|
|
270
|
+
label: "backups",
|
|
271
|
+
hint: "Manage physical backups",
|
|
272
|
+
suggestedArgs: [
|
|
273
|
+
{ value: "list", label: "list", hint: "List backups", args: ["list"] },
|
|
274
|
+
{ value: "download", label: "download", hint: "Download backup", args: ["download"] }
|
|
275
|
+
]
|
|
276
|
+
},
|
|
277
|
+
{
|
|
278
|
+
id: "supabase:snippets",
|
|
279
|
+
tool: "supabase",
|
|
280
|
+
base: ["snippets"],
|
|
281
|
+
label: "snippets",
|
|
282
|
+
hint: "Manage SQL snippets",
|
|
283
|
+
suggestedArgs: [
|
|
284
|
+
{ value: "list", label: "list", hint: "List SQL snippets", args: ["list"] },
|
|
285
|
+
{ value: "create", label: "create", hint: "Create SQL snippet", args: ["create"] },
|
|
286
|
+
{ value: "delete", label: "delete", hint: "Delete SQL snippet", args: ["delete"] }
|
|
287
|
+
]
|
|
288
|
+
},
|
|
289
|
+
{
|
|
290
|
+
id: "supabase:postgres-config",
|
|
291
|
+
tool: "supabase",
|
|
292
|
+
base: ["postgres-config"],
|
|
293
|
+
label: "postgres-config",
|
|
294
|
+
hint: "Manage Postgres config"
|
|
295
|
+
},
|
|
296
|
+
// Utilities
|
|
297
|
+
{
|
|
298
|
+
id: "supabase:completion",
|
|
299
|
+
tool: "supabase",
|
|
300
|
+
base: ["completion"],
|
|
301
|
+
label: "completion",
|
|
302
|
+
hint: "Generate shell completion script"
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
id: "supabase:help",
|
|
306
|
+
tool: "supabase",
|
|
307
|
+
base: ["help"],
|
|
308
|
+
label: "help",
|
|
309
|
+
hint: "Help about any command"
|
|
310
|
+
}
|
|
311
|
+
];
|
|
312
|
+
|
|
313
|
+
// src/data/commands/gh.ts
|
|
314
|
+
var ghCommands = [
|
|
315
|
+
// Repository
|
|
316
|
+
{
|
|
317
|
+
id: "gh:repo:clone",
|
|
318
|
+
tool: "gh",
|
|
319
|
+
base: ["repo", "clone"],
|
|
320
|
+
label: "repo clone",
|
|
321
|
+
hint: "Clone a repository"
|
|
322
|
+
},
|
|
323
|
+
{
|
|
324
|
+
id: "gh:repo:create",
|
|
325
|
+
tool: "gh",
|
|
326
|
+
base: ["repo", "create"],
|
|
327
|
+
label: "repo create",
|
|
328
|
+
hint: "Create a new repository"
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
id: "gh:repo:view",
|
|
332
|
+
tool: "gh",
|
|
333
|
+
base: ["repo", "view"],
|
|
334
|
+
label: "repo view",
|
|
335
|
+
hint: "View repository details"
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
id: "gh:repo:list",
|
|
339
|
+
tool: "gh",
|
|
340
|
+
base: ["repo", "list"],
|
|
341
|
+
label: "repo list",
|
|
342
|
+
hint: "List your repositories"
|
|
343
|
+
},
|
|
344
|
+
// Pull Requests
|
|
345
|
+
{
|
|
346
|
+
id: "gh:pr:create",
|
|
347
|
+
tool: "gh",
|
|
348
|
+
base: ["pr", "create"],
|
|
349
|
+
label: "pr create",
|
|
350
|
+
hint: "Create a pull request"
|
|
351
|
+
},
|
|
352
|
+
{
|
|
353
|
+
id: "gh:pr:list",
|
|
354
|
+
tool: "gh",
|
|
355
|
+
base: ["pr", "list"],
|
|
356
|
+
label: "pr list",
|
|
357
|
+
hint: "List pull requests"
|
|
358
|
+
},
|
|
359
|
+
{
|
|
360
|
+
id: "gh:pr:view",
|
|
361
|
+
tool: "gh",
|
|
362
|
+
base: ["pr", "view"],
|
|
363
|
+
label: "pr view",
|
|
364
|
+
hint: "View a pull request"
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
id: "gh:pr:merge",
|
|
368
|
+
tool: "gh",
|
|
369
|
+
base: ["pr", "merge"],
|
|
370
|
+
label: "pr merge",
|
|
371
|
+
hint: "Merge a pull request"
|
|
372
|
+
},
|
|
373
|
+
{
|
|
374
|
+
id: "gh:pr:checkout",
|
|
375
|
+
tool: "gh",
|
|
376
|
+
base: ["pr", "checkout"],
|
|
377
|
+
label: "pr checkout",
|
|
378
|
+
hint: "Check out a pull request"
|
|
379
|
+
},
|
|
380
|
+
// Issues
|
|
381
|
+
{
|
|
382
|
+
id: "gh:issue:create",
|
|
383
|
+
tool: "gh",
|
|
384
|
+
base: ["issue", "create"],
|
|
385
|
+
label: "issue create",
|
|
386
|
+
hint: "Create an issue"
|
|
387
|
+
},
|
|
388
|
+
{
|
|
389
|
+
id: "gh:issue:list",
|
|
390
|
+
tool: "gh",
|
|
391
|
+
base: ["issue", "list"],
|
|
392
|
+
label: "issue list",
|
|
393
|
+
hint: "List issues"
|
|
394
|
+
},
|
|
395
|
+
{
|
|
396
|
+
id: "gh:issue:view",
|
|
397
|
+
tool: "gh",
|
|
398
|
+
base: ["issue", "view"],
|
|
399
|
+
label: "issue view",
|
|
400
|
+
hint: "View an issue"
|
|
401
|
+
},
|
|
402
|
+
{
|
|
403
|
+
id: "gh:issue:close",
|
|
404
|
+
tool: "gh",
|
|
405
|
+
base: ["issue", "close"],
|
|
406
|
+
label: "issue close",
|
|
407
|
+
hint: "Close an issue"
|
|
408
|
+
},
|
|
409
|
+
// Workflows & Runs
|
|
410
|
+
{
|
|
411
|
+
id: "gh:workflow:list",
|
|
412
|
+
tool: "gh",
|
|
413
|
+
base: ["workflow", "list"],
|
|
414
|
+
label: "workflow list",
|
|
415
|
+
hint: "List workflows"
|
|
416
|
+
},
|
|
417
|
+
{
|
|
418
|
+
id: "gh:workflow:run",
|
|
419
|
+
tool: "gh",
|
|
420
|
+
base: ["workflow", "run"],
|
|
421
|
+
label: "workflow run",
|
|
422
|
+
hint: "Run a workflow"
|
|
423
|
+
},
|
|
424
|
+
{
|
|
425
|
+
id: "gh:workflow:view",
|
|
426
|
+
tool: "gh",
|
|
427
|
+
base: ["workflow", "view"],
|
|
428
|
+
label: "workflow view",
|
|
429
|
+
hint: "View a workflow"
|
|
430
|
+
},
|
|
431
|
+
{
|
|
432
|
+
id: "gh:run:list",
|
|
433
|
+
tool: "gh",
|
|
434
|
+
base: ["run", "list"],
|
|
435
|
+
label: "run list",
|
|
436
|
+
hint: "List workflow runs"
|
|
437
|
+
},
|
|
438
|
+
{
|
|
439
|
+
id: "gh:run:view",
|
|
440
|
+
tool: "gh",
|
|
441
|
+
base: ["run", "view"],
|
|
442
|
+
label: "run view",
|
|
443
|
+
hint: "View a workflow run"
|
|
444
|
+
},
|
|
445
|
+
{
|
|
446
|
+
id: "gh:run:watch",
|
|
447
|
+
tool: "gh",
|
|
448
|
+
base: ["run", "watch"],
|
|
449
|
+
label: "run watch",
|
|
450
|
+
hint: "Watch a workflow run"
|
|
451
|
+
},
|
|
452
|
+
// Releases
|
|
453
|
+
{
|
|
454
|
+
id: "gh:release:create",
|
|
455
|
+
tool: "gh",
|
|
456
|
+
base: ["release", "create"],
|
|
457
|
+
label: "release create",
|
|
458
|
+
hint: "Create a release"
|
|
459
|
+
},
|
|
460
|
+
{
|
|
461
|
+
id: "gh:release:list",
|
|
462
|
+
tool: "gh",
|
|
463
|
+
base: ["release", "list"],
|
|
464
|
+
label: "release list",
|
|
465
|
+
hint: "List releases"
|
|
466
|
+
},
|
|
467
|
+
{
|
|
468
|
+
id: "gh:release:view",
|
|
469
|
+
tool: "gh",
|
|
470
|
+
base: ["release", "view"],
|
|
471
|
+
label: "release view",
|
|
472
|
+
hint: "View a release"
|
|
473
|
+
},
|
|
474
|
+
// Auth
|
|
475
|
+
{
|
|
476
|
+
id: "gh:auth:login",
|
|
477
|
+
tool: "gh",
|
|
478
|
+
base: ["auth", "login"],
|
|
479
|
+
label: "auth login",
|
|
480
|
+
hint: "Log in to GitHub"
|
|
481
|
+
},
|
|
482
|
+
{
|
|
483
|
+
id: "gh:auth:status",
|
|
484
|
+
tool: "gh",
|
|
485
|
+
base: ["auth", "status"],
|
|
486
|
+
label: "auth status",
|
|
487
|
+
hint: "View auth status"
|
|
488
|
+
}
|
|
489
|
+
];
|
|
490
|
+
|
|
491
|
+
// src/data/commands/vercel.ts
|
|
492
|
+
var vercelCommands = [
|
|
493
|
+
// Deploy
|
|
494
|
+
{
|
|
495
|
+
id: "vercel:deploy",
|
|
496
|
+
tool: "vercel",
|
|
497
|
+
base: ["deploy"],
|
|
498
|
+
label: "deploy",
|
|
499
|
+
hint: "Deploy to Vercel"
|
|
500
|
+
},
|
|
501
|
+
{
|
|
502
|
+
id: "vercel:deploy:prod",
|
|
503
|
+
tool: "vercel",
|
|
504
|
+
base: ["deploy", "--prod"],
|
|
505
|
+
label: "deploy --prod",
|
|
506
|
+
hint: "Deploy to production"
|
|
507
|
+
},
|
|
508
|
+
{
|
|
509
|
+
id: "vercel:promote",
|
|
510
|
+
tool: "vercel",
|
|
511
|
+
base: ["promote"],
|
|
512
|
+
label: "promote",
|
|
513
|
+
hint: "Promote a deployment"
|
|
514
|
+
},
|
|
515
|
+
{
|
|
516
|
+
id: "vercel:rollback",
|
|
517
|
+
tool: "vercel",
|
|
518
|
+
base: ["rollback"],
|
|
519
|
+
label: "rollback",
|
|
520
|
+
hint: "Rollback to previous deployment"
|
|
521
|
+
},
|
|
522
|
+
// Domains
|
|
523
|
+
{
|
|
524
|
+
id: "vercel:domains:list",
|
|
525
|
+
tool: "vercel",
|
|
526
|
+
base: ["domains", "ls"],
|
|
527
|
+
label: "domains ls",
|
|
528
|
+
hint: "List domains"
|
|
529
|
+
},
|
|
530
|
+
{
|
|
531
|
+
id: "vercel:domains:add",
|
|
532
|
+
tool: "vercel",
|
|
533
|
+
base: ["domains", "add"],
|
|
534
|
+
label: "domains add",
|
|
535
|
+
hint: "Add a domain"
|
|
536
|
+
},
|
|
537
|
+
{
|
|
538
|
+
id: "vercel:domains:rm",
|
|
539
|
+
tool: "vercel",
|
|
540
|
+
base: ["domains", "rm"],
|
|
541
|
+
label: "domains rm",
|
|
542
|
+
hint: "Remove a domain"
|
|
543
|
+
},
|
|
544
|
+
// Environment Variables
|
|
545
|
+
{
|
|
546
|
+
id: "vercel:env:ls",
|
|
547
|
+
tool: "vercel",
|
|
548
|
+
base: ["env", "ls"],
|
|
549
|
+
label: "env ls",
|
|
550
|
+
hint: "List environment variables"
|
|
551
|
+
},
|
|
552
|
+
{
|
|
553
|
+
id: "vercel:env:add",
|
|
554
|
+
tool: "vercel",
|
|
555
|
+
base: ["env", "add"],
|
|
556
|
+
label: "env add",
|
|
557
|
+
hint: "Add an environment variable"
|
|
558
|
+
},
|
|
559
|
+
{
|
|
560
|
+
id: "vercel:env:rm",
|
|
561
|
+
tool: "vercel",
|
|
562
|
+
base: ["env", "rm"],
|
|
563
|
+
label: "env rm",
|
|
564
|
+
hint: "Remove an environment variable"
|
|
565
|
+
},
|
|
566
|
+
{
|
|
567
|
+
id: "vercel:env:pull",
|
|
568
|
+
tool: "vercel",
|
|
569
|
+
base: ["env", "pull"],
|
|
570
|
+
label: "env pull",
|
|
571
|
+
hint: "Pull env vars to .env file"
|
|
572
|
+
},
|
|
573
|
+
// Project
|
|
574
|
+
{
|
|
575
|
+
id: "vercel:project:ls",
|
|
576
|
+
tool: "vercel",
|
|
577
|
+
base: ["project", "ls"],
|
|
578
|
+
label: "project ls",
|
|
579
|
+
hint: "List projects"
|
|
580
|
+
},
|
|
581
|
+
{
|
|
582
|
+
id: "vercel:project:add",
|
|
583
|
+
tool: "vercel",
|
|
584
|
+
base: ["project", "add"],
|
|
585
|
+
label: "project add",
|
|
586
|
+
hint: "Add a project"
|
|
587
|
+
},
|
|
588
|
+
{
|
|
589
|
+
id: "vercel:project:rm",
|
|
590
|
+
tool: "vercel",
|
|
591
|
+
base: ["project", "rm"],
|
|
592
|
+
label: "project rm",
|
|
593
|
+
hint: "Remove a project"
|
|
594
|
+
},
|
|
595
|
+
// Setup
|
|
596
|
+
{
|
|
597
|
+
id: "vercel:link",
|
|
598
|
+
tool: "vercel",
|
|
599
|
+
base: ["link"],
|
|
600
|
+
label: "link",
|
|
601
|
+
hint: "Link to a Vercel project"
|
|
602
|
+
},
|
|
603
|
+
{
|
|
604
|
+
id: "vercel:login",
|
|
605
|
+
tool: "vercel",
|
|
606
|
+
base: ["login"],
|
|
607
|
+
label: "login",
|
|
608
|
+
hint: "Log in to Vercel"
|
|
609
|
+
},
|
|
610
|
+
{
|
|
611
|
+
id: "vercel:whoami",
|
|
612
|
+
tool: "vercel",
|
|
613
|
+
base: ["whoami"],
|
|
614
|
+
label: "whoami",
|
|
615
|
+
hint: "Show current user"
|
|
616
|
+
},
|
|
617
|
+
// Logs & Inspect
|
|
618
|
+
{
|
|
619
|
+
id: "vercel:logs",
|
|
620
|
+
tool: "vercel",
|
|
621
|
+
base: ["logs"],
|
|
622
|
+
label: "logs",
|
|
623
|
+
hint: "View deployment logs"
|
|
624
|
+
},
|
|
625
|
+
{
|
|
626
|
+
id: "vercel:inspect",
|
|
627
|
+
tool: "vercel",
|
|
628
|
+
base: ["inspect"],
|
|
629
|
+
label: "inspect",
|
|
630
|
+
hint: "Inspect a deployment"
|
|
631
|
+
},
|
|
632
|
+
{
|
|
633
|
+
id: "vercel:ls",
|
|
634
|
+
tool: "vercel",
|
|
635
|
+
base: ["ls"],
|
|
636
|
+
label: "ls",
|
|
637
|
+
hint: "List deployments"
|
|
638
|
+
}
|
|
639
|
+
];
|
|
640
|
+
|
|
641
|
+
// src/data/commands/pulumi.ts
|
|
642
|
+
var pulumiCommands = [
|
|
643
|
+
// Stack Management
|
|
644
|
+
{ id: "pulumi:stack:ls", tool: "pulumi", base: ["stack", "ls"], label: "stack ls", hint: "List stacks" },
|
|
645
|
+
{ id: "pulumi:stack:select", tool: "pulumi", base: ["stack", "select"], label: "stack select", hint: "Switch to a stack" },
|
|
646
|
+
{ id: "pulumi:stack:init", tool: "pulumi", base: ["stack", "init"], label: "stack init", hint: "Create a new stack" },
|
|
647
|
+
{ id: "pulumi:stack:rm", tool: "pulumi", base: ["stack", "rm"], label: "stack rm", hint: "Remove a stack" },
|
|
648
|
+
{ id: "pulumi:stack:output", tool: "pulumi", base: ["stack", "output"], label: "stack output", hint: "Show stack outputs" },
|
|
649
|
+
// Core Operations
|
|
650
|
+
{ id: "pulumi:up", tool: "pulumi", base: ["up"], label: "up", hint: "Deploy infrastructure changes" },
|
|
651
|
+
{ id: "pulumi:preview", tool: "pulumi", base: ["preview"], label: "preview", hint: "Preview changes before deploying" },
|
|
652
|
+
{ id: "pulumi:destroy", tool: "pulumi", base: ["destroy"], label: "destroy", hint: "Tear down all resources" },
|
|
653
|
+
{ id: "pulumi:refresh", tool: "pulumi", base: ["refresh"], label: "refresh", hint: "Refresh state from cloud provider" },
|
|
654
|
+
// Config
|
|
655
|
+
{ id: "pulumi:config:set", tool: "pulumi", base: ["config", "set"], label: "config set", hint: "Set a config value" },
|
|
656
|
+
{ id: "pulumi:config:get", tool: "pulumi", base: ["config", "get"], label: "config get", hint: "Get a config value" },
|
|
657
|
+
{ id: "pulumi:config:ls", tool: "pulumi", base: ["config"], label: "config", hint: "List config key-value pairs" },
|
|
658
|
+
// Import & State
|
|
659
|
+
{ id: "pulumi:import", tool: "pulumi", base: ["import"], label: "import", hint: "Import existing resources" },
|
|
660
|
+
{ id: "pulumi:state:delete", tool: "pulumi", base: ["state", "delete"], label: "state delete", hint: "Remove resource from state" },
|
|
661
|
+
// Auth & Setup
|
|
662
|
+
{ id: "pulumi:login", tool: "pulumi", base: ["login"], label: "login", hint: "Log in to Pulumi Cloud" },
|
|
663
|
+
{ id: "pulumi:whoami", tool: "pulumi", base: ["whoami"], label: "whoami", hint: "Show current user" },
|
|
664
|
+
{ id: "pulumi:new", tool: "pulumi", base: ["new"], label: "new", hint: "Create a new project from template" },
|
|
665
|
+
// Editor-backed commands
|
|
666
|
+
{ id: "pulumi:edit:config", tool: "pulumi", base: ["__editor__"], label: "edit config", hint: "Open Pulumi.yaml in editor", editorTarget: "config" },
|
|
667
|
+
{ id: "pulumi:edit:code", tool: "pulumi", base: ["__editor__"], label: "edit code", hint: "Open IaC source file in editor", editorTarget: "code" }
|
|
668
|
+
];
|
|
669
|
+
|
|
670
|
+
// src/data/commands/index.ts
|
|
671
|
+
var allCommands = [
|
|
672
|
+
...supabaseCommands,
|
|
673
|
+
...ghCommands,
|
|
674
|
+
...vercelCommands,
|
|
675
|
+
...pulumiCommands
|
|
676
|
+
];
|
|
677
|
+
var commandById = new Map(allCommands.map((cmd) => [cmd.id, cmd]));
|
|
678
|
+
var commandByValue = new Map(
|
|
679
|
+
allCommands.map((cmd) => [getCommandValue(cmd), cmd])
|
|
680
|
+
);
|
|
681
|
+
function getCommandById(id) {
|
|
682
|
+
return commandById.get(id);
|
|
683
|
+
}
|
|
684
|
+
function getCommandsByTool(tool) {
|
|
685
|
+
return allCommands.filter((cmd) => cmd.tool === tool);
|
|
686
|
+
}
|
|
687
|
+
function getCommandValue(cmd) {
|
|
688
|
+
if (cmd.tool === "supabase") {
|
|
689
|
+
return cmd.base.join(" ");
|
|
690
|
+
}
|
|
691
|
+
return `${cmd.tool}:${cmd.base.join(" ")}`;
|
|
692
|
+
}
|
|
693
|
+
function findCommandByValue(value) {
|
|
694
|
+
const byId = commandById.get(value);
|
|
695
|
+
if (byId) return byId;
|
|
696
|
+
return commandByValue.get(value);
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
// src/data/features.ts
|
|
700
|
+
function pick(ids) {
|
|
701
|
+
const idSet = new Set(ids);
|
|
702
|
+
return [...supabaseCommands, ...ghCommands, ...vercelCommands, ...pulumiCommands].filter(
|
|
703
|
+
(cmd) => idSet.has(cmd.id)
|
|
704
|
+
);
|
|
705
|
+
}
|
|
706
|
+
var features = [
|
|
707
|
+
{
|
|
708
|
+
id: "database",
|
|
709
|
+
icon: "\u{1F5C4}",
|
|
710
|
+
label: "Database",
|
|
711
|
+
commands: pick([
|
|
712
|
+
"supabase:db",
|
|
713
|
+
"supabase:migration",
|
|
714
|
+
"supabase:seed",
|
|
715
|
+
"supabase:inspect"
|
|
716
|
+
])
|
|
717
|
+
},
|
|
718
|
+
{
|
|
719
|
+
id: "functions",
|
|
720
|
+
icon: "\u26A1",
|
|
721
|
+
label: "Functions",
|
|
722
|
+
commands: pick([
|
|
723
|
+
"supabase:functions"
|
|
724
|
+
])
|
|
725
|
+
},
|
|
726
|
+
{
|
|
727
|
+
id: "deploy",
|
|
728
|
+
icon: "\u{1F680}",
|
|
729
|
+
label: "Deploy",
|
|
730
|
+
commands: pick([
|
|
731
|
+
"supabase:db",
|
|
732
|
+
"supabase:functions",
|
|
733
|
+
"vercel:deploy",
|
|
734
|
+
"vercel:deploy:prod",
|
|
735
|
+
"vercel:promote",
|
|
736
|
+
"vercel:rollback",
|
|
737
|
+
"pulumi:up",
|
|
738
|
+
"pulumi:preview"
|
|
739
|
+
])
|
|
740
|
+
},
|
|
741
|
+
{
|
|
742
|
+
id: "repo",
|
|
743
|
+
icon: "\u{1F4E6}",
|
|
744
|
+
label: "Repo",
|
|
745
|
+
commands: pick([
|
|
746
|
+
"gh:repo:clone",
|
|
747
|
+
"gh:repo:create",
|
|
748
|
+
"gh:repo:view",
|
|
749
|
+
"gh:repo:list",
|
|
750
|
+
"gh:pr:create",
|
|
751
|
+
"gh:pr:list",
|
|
752
|
+
"gh:pr:view",
|
|
753
|
+
"gh:pr:merge",
|
|
754
|
+
"gh:pr:checkout",
|
|
755
|
+
"gh:issue:create",
|
|
756
|
+
"gh:issue:list",
|
|
757
|
+
"gh:issue:view",
|
|
758
|
+
"gh:issue:close",
|
|
759
|
+
"gh:release:create",
|
|
760
|
+
"gh:release:list",
|
|
761
|
+
"gh:release:view"
|
|
762
|
+
])
|
|
763
|
+
},
|
|
764
|
+
{
|
|
765
|
+
id: "cicd",
|
|
766
|
+
icon: "\u{1F504}",
|
|
767
|
+
label: "CI/CD",
|
|
768
|
+
commands: pick([
|
|
769
|
+
"vercel:env:ls",
|
|
770
|
+
"vercel:env:add",
|
|
771
|
+
"vercel:env:rm",
|
|
772
|
+
"vercel:env:pull",
|
|
773
|
+
"gh:workflow:list",
|
|
774
|
+
"gh:workflow:run",
|
|
775
|
+
"gh:workflow:view",
|
|
776
|
+
"gh:run:list",
|
|
777
|
+
"gh:run:view",
|
|
778
|
+
"gh:run:watch",
|
|
779
|
+
"pulumi:preview",
|
|
780
|
+
"pulumi:up"
|
|
781
|
+
])
|
|
782
|
+
},
|
|
783
|
+
{
|
|
784
|
+
id: "auth-storage",
|
|
785
|
+
icon: "\u{1F510}",
|
|
786
|
+
label: "Auth & Storage",
|
|
787
|
+
commands: pick([
|
|
788
|
+
"supabase:storage",
|
|
789
|
+
"supabase:secrets",
|
|
790
|
+
"supabase:sso"
|
|
791
|
+
])
|
|
792
|
+
},
|
|
793
|
+
{
|
|
794
|
+
id: "networking",
|
|
795
|
+
icon: "\u{1F310}",
|
|
796
|
+
label: "Networking",
|
|
797
|
+
commands: pick([
|
|
798
|
+
"supabase:domains",
|
|
799
|
+
"supabase:ssl-enforcement",
|
|
800
|
+
"supabase:network-bans",
|
|
801
|
+
"supabase:network-restrictions",
|
|
802
|
+
"supabase:vanity-subdomains",
|
|
803
|
+
"supabase:encryption",
|
|
804
|
+
"vercel:domains:list",
|
|
805
|
+
"vercel:domains:add",
|
|
806
|
+
"vercel:domains:rm"
|
|
807
|
+
])
|
|
808
|
+
},
|
|
809
|
+
{
|
|
810
|
+
id: "infrastructure",
|
|
811
|
+
icon: "\u{1F3D7}",
|
|
812
|
+
label: "Infrastructure",
|
|
813
|
+
commands: pick([
|
|
814
|
+
"pulumi:up",
|
|
815
|
+
"pulumi:preview",
|
|
816
|
+
"pulumi:destroy",
|
|
817
|
+
"pulumi:refresh",
|
|
818
|
+
"pulumi:stack:ls",
|
|
819
|
+
"pulumi:stack:select",
|
|
820
|
+
"pulumi:stack:init",
|
|
821
|
+
"pulumi:config:set",
|
|
822
|
+
"pulumi:config:get",
|
|
823
|
+
"pulumi:config:ls",
|
|
824
|
+
"pulumi:import",
|
|
825
|
+
"pulumi:state:delete",
|
|
826
|
+
"pulumi:edit:config",
|
|
827
|
+
"pulumi:edit:code"
|
|
828
|
+
])
|
|
829
|
+
},
|
|
830
|
+
{
|
|
831
|
+
id: "setup",
|
|
832
|
+
icon: "\u2699\uFE0F",
|
|
833
|
+
label: "Setup",
|
|
834
|
+
commands: pick([
|
|
835
|
+
"supabase:init",
|
|
836
|
+
"supabase:link",
|
|
837
|
+
"supabase:login",
|
|
838
|
+
"vercel:link",
|
|
839
|
+
"vercel:login",
|
|
840
|
+
"gh:auth:login",
|
|
841
|
+
"gh:auth:status",
|
|
842
|
+
"pulumi:login",
|
|
843
|
+
"pulumi:whoami",
|
|
844
|
+
"pulumi:new"
|
|
845
|
+
])
|
|
846
|
+
}
|
|
847
|
+
];
|
|
848
|
+
var featureById = new Map(features.map((f) => [f.id, f]));
|
|
849
|
+
function getFeatureById(id) {
|
|
850
|
+
return featureById.get(id);
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
// src/data/flags.ts
|
|
854
|
+
var globalFlags = [
|
|
855
|
+
{ value: "--debug", label: "--debug", hint: "Output debug logs to stderr" },
|
|
856
|
+
{ value: "--yes", label: "--yes", hint: "Answer yes to all prompts" },
|
|
857
|
+
{
|
|
858
|
+
value: "--create-ticket",
|
|
859
|
+
label: "--create-ticket",
|
|
860
|
+
hint: "Create support ticket on error"
|
|
861
|
+
},
|
|
862
|
+
{
|
|
863
|
+
value: "--experimental",
|
|
864
|
+
label: "--experimental",
|
|
865
|
+
hint: "Enable experimental features"
|
|
866
|
+
}
|
|
867
|
+
];
|
|
868
|
+
var toolFlags = {
|
|
869
|
+
supabase: globalFlags,
|
|
870
|
+
gh: [],
|
|
871
|
+
vercel: [
|
|
872
|
+
{ value: "--yes", label: "--yes", hint: "Skip confirmation prompts" },
|
|
873
|
+
{ value: "--debug", label: "--debug", hint: "Debug mode" }
|
|
874
|
+
],
|
|
875
|
+
pulumi: [
|
|
876
|
+
{ value: "--yes", label: "--yes", hint: "Skip confirmation prompts" },
|
|
877
|
+
{ value: "--debug", label: "--debug", hint: "Debug mode" },
|
|
878
|
+
{ value: "--stack", label: "--stack", hint: "Target a specific stack" }
|
|
879
|
+
]
|
|
880
|
+
};
|
|
881
|
+
function getFlagsForTool(toolId) {
|
|
882
|
+
return toolFlags[toolId] ?? globalFlags;
|
|
883
|
+
}
|
|
884
|
+
|
|
885
|
+
// src/lib/runner.ts
|
|
886
|
+
import { spawn } from "child_process";
|
|
887
|
+
import { existsSync } from "fs";
|
|
888
|
+
import { delimiter, dirname, join, resolve } from "path";
|
|
889
|
+
function getSupabaseBinaryCandidates() {
|
|
890
|
+
if (process.platform === "win32") {
|
|
891
|
+
return ["supabase.cmd", "supabase.exe", "supabase"];
|
|
892
|
+
}
|
|
893
|
+
return ["supabase"];
|
|
894
|
+
}
|
|
895
|
+
function hasLocalSupabaseBinary(binDir) {
|
|
896
|
+
return getSupabaseBinaryCandidates().some(
|
|
897
|
+
(candidate) => existsSync(join(binDir, candidate))
|
|
898
|
+
);
|
|
899
|
+
}
|
|
900
|
+
function getPathEnvKey(env) {
|
|
901
|
+
return Object.keys(env).find((key) => key.toLowerCase() === "path") ?? "PATH";
|
|
902
|
+
}
|
|
903
|
+
function findLocalSupabaseBinDir(startDir = process.cwd()) {
|
|
904
|
+
let currentDir = resolve(startDir);
|
|
905
|
+
while (true) {
|
|
906
|
+
const binDir = join(currentDir, "node_modules", ".bin");
|
|
907
|
+
if (hasLocalSupabaseBinary(binDir)) {
|
|
908
|
+
return binDir;
|
|
909
|
+
}
|
|
910
|
+
const parentDir = dirname(currentDir);
|
|
911
|
+
if (parentDir === currentDir) {
|
|
912
|
+
return void 0;
|
|
913
|
+
}
|
|
914
|
+
currentDir = parentDir;
|
|
915
|
+
}
|
|
916
|
+
}
|
|
917
|
+
function resolveSupabaseCommand(startDir = process.cwd(), env = process.env) {
|
|
918
|
+
const localBinDir = findLocalSupabaseBinDir(startDir);
|
|
919
|
+
if (!localBinDir) {
|
|
920
|
+
return {
|
|
921
|
+
command: "supabase",
|
|
922
|
+
env: { ...env },
|
|
923
|
+
source: "path"
|
|
924
|
+
};
|
|
925
|
+
}
|
|
926
|
+
const pathKey = getPathEnvKey(env);
|
|
927
|
+
const currentPath = env[pathKey];
|
|
928
|
+
return {
|
|
929
|
+
command: "supabase",
|
|
930
|
+
env: {
|
|
931
|
+
...env,
|
|
932
|
+
[pathKey]: currentPath ? `${localBinDir}${delimiter}${currentPath}` : localBinDir
|
|
933
|
+
},
|
|
934
|
+
source: "repository",
|
|
935
|
+
localBinDir
|
|
936
|
+
};
|
|
937
|
+
}
|
|
938
|
+
async function runCommand(execution, args, cwd = process.cwd(), options) {
|
|
939
|
+
return new Promise((resolve3) => {
|
|
940
|
+
let stdout = "";
|
|
941
|
+
let stderr = "";
|
|
942
|
+
const resolvedExecution = typeof execution === "string" ? { command: execution } : execution;
|
|
943
|
+
const child = spawn(resolvedExecution.command, args, {
|
|
944
|
+
cwd,
|
|
945
|
+
env: resolvedExecution.env,
|
|
946
|
+
shell: true,
|
|
947
|
+
stdio: ["inherit", "pipe", "pipe"]
|
|
948
|
+
});
|
|
949
|
+
child.stdout?.on("data", (data) => {
|
|
950
|
+
const text = data.toString();
|
|
951
|
+
stdout += text;
|
|
952
|
+
if (!options?.quiet) process.stdout.write(text);
|
|
953
|
+
});
|
|
954
|
+
child.stderr?.on("data", (data) => {
|
|
955
|
+
const text = data.toString();
|
|
956
|
+
stderr += text;
|
|
957
|
+
if (!options?.quiet) process.stderr.write(text);
|
|
958
|
+
});
|
|
959
|
+
child.on("error", (err) => {
|
|
960
|
+
resolve3({
|
|
961
|
+
exitCode: null,
|
|
962
|
+
signal: null,
|
|
963
|
+
stdout,
|
|
964
|
+
stderr,
|
|
965
|
+
spawnError: err.message
|
|
966
|
+
});
|
|
967
|
+
});
|
|
968
|
+
child.on("exit", (code, signal) => {
|
|
969
|
+
resolve3({ exitCode: code, signal, stdout, stderr });
|
|
970
|
+
});
|
|
971
|
+
});
|
|
972
|
+
}
|
|
973
|
+
async function runSupabaseCommand(args, cwd = process.cwd()) {
|
|
974
|
+
return runCommand(resolveSupabaseCommand(cwd), args, cwd);
|
|
975
|
+
}
|
|
976
|
+
|
|
977
|
+
// src/lib/system.ts
|
|
978
|
+
import { execSync } from "child_process";
|
|
979
|
+
function commandExists(command) {
|
|
980
|
+
try {
|
|
981
|
+
execSync(`command -v ${command}`, { stdio: "ignore" });
|
|
982
|
+
return true;
|
|
983
|
+
} catch {
|
|
984
|
+
return false;
|
|
985
|
+
}
|
|
986
|
+
}
|
|
987
|
+
function execCapture(command) {
|
|
988
|
+
return execSync(command, {
|
|
989
|
+
encoding: "utf-8",
|
|
990
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
991
|
+
}).trim();
|
|
992
|
+
}
|
|
993
|
+
|
|
994
|
+
// src/lib/toolResolver.ts
|
|
995
|
+
function resolveToolCommand(toolId, cwd = process.cwd()) {
|
|
996
|
+
if (toolId === "supabase") {
|
|
997
|
+
const resolved = resolveSupabaseCommand(cwd);
|
|
998
|
+
return {
|
|
999
|
+
command: resolved.command,
|
|
1000
|
+
env: resolved.env,
|
|
1001
|
+
source: resolved.source
|
|
1002
|
+
};
|
|
1003
|
+
}
|
|
1004
|
+
const command = toolId;
|
|
1005
|
+
if (!commandExists(command)) {
|
|
1006
|
+
return { command, source: "not-found" };
|
|
1007
|
+
}
|
|
1008
|
+
return { command, env: { ...process.env }, source: "path" };
|
|
1009
|
+
}
|
|
1010
|
+
function getToolVersion(toolId) {
|
|
1011
|
+
try {
|
|
1012
|
+
switch (toolId) {
|
|
1013
|
+
case "supabase":
|
|
1014
|
+
return execCapture("supabase --version").replace(/^supabase\s+/i, "");
|
|
1015
|
+
case "gh":
|
|
1016
|
+
return execCapture("gh --version").split("\n")[0]?.replace(/^gh\s+version\s+/i, "").split(" ")[0];
|
|
1017
|
+
case "vercel":
|
|
1018
|
+
return execCapture("vercel --version").split("\n")[0]?.trim();
|
|
1019
|
+
case "pulumi":
|
|
1020
|
+
return execCapture("pulumi version").replace(/^v/, "");
|
|
1021
|
+
default:
|
|
1022
|
+
return void 0;
|
|
1023
|
+
}
|
|
1024
|
+
} catch {
|
|
1025
|
+
return void 0;
|
|
1026
|
+
}
|
|
1027
|
+
}
|
|
1028
|
+
var toolInfoCache = /* @__PURE__ */ new Map();
|
|
1029
|
+
function getToolInfo(toolId) {
|
|
1030
|
+
const cached = toolInfoCache.get(toolId);
|
|
1031
|
+
if (cached) return cached;
|
|
1032
|
+
const labels = {
|
|
1033
|
+
supabase: "Supabase CLI",
|
|
1034
|
+
gh: "GitHub CLI",
|
|
1035
|
+
vercel: "Vercel CLI",
|
|
1036
|
+
pulumi: "Pulumi CLI"
|
|
1037
|
+
};
|
|
1038
|
+
const installed = commandExists(toolId === "supabase" ? "supabase" : toolId);
|
|
1039
|
+
const version = installed ? getToolVersion(toolId) : void 0;
|
|
1040
|
+
const info = {
|
|
1041
|
+
id: toolId,
|
|
1042
|
+
label: labels[toolId],
|
|
1043
|
+
installed,
|
|
1044
|
+
version
|
|
1045
|
+
};
|
|
1046
|
+
toolInfoCache.set(toolId, info);
|
|
1047
|
+
return info;
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
// src/pipeline/engine.ts
|
|
1051
|
+
async function executePipeline(pipeline, onProgress, cwd = process.cwd()) {
|
|
1052
|
+
const stepResults = pipeline.steps.map((step) => ({
|
|
1053
|
+
step,
|
|
1054
|
+
status: "pending"
|
|
1055
|
+
}));
|
|
1056
|
+
let aborted = false;
|
|
1057
|
+
for (let i = 0; i < pipeline.steps.length; i++) {
|
|
1058
|
+
const step = pipeline.steps[i];
|
|
1059
|
+
if (aborted) {
|
|
1060
|
+
stepResults[i] = { step, status: "skipped" };
|
|
1061
|
+
onProgress({ stepResults: [...stepResults], currentStepIndex: i, done: false });
|
|
1062
|
+
continue;
|
|
1063
|
+
}
|
|
1064
|
+
stepResults[i] = { step, status: "running" };
|
|
1065
|
+
onProgress({ stepResults: [...stepResults], currentStepIndex: i, done: false });
|
|
1066
|
+
const cmdDef = getCommandById(step.commandId);
|
|
1067
|
+
const toolId = cmdDef?.tool ?? "supabase";
|
|
1068
|
+
const resolved = resolveToolCommand(toolId, cwd);
|
|
1069
|
+
const baseArgs = cmdDef?.base ?? [];
|
|
1070
|
+
const allArgs = [...baseArgs, ...step.args, ...step.flags];
|
|
1071
|
+
const result = await runCommand(
|
|
1072
|
+
{ command: resolved.command, env: resolved.env },
|
|
1073
|
+
allArgs,
|
|
1074
|
+
cwd
|
|
1075
|
+
);
|
|
1076
|
+
const success = !result.spawnError && result.exitCode === 0;
|
|
1077
|
+
stepResults[i] = {
|
|
1078
|
+
step,
|
|
1079
|
+
status: success ? "success" : "error",
|
|
1080
|
+
result
|
|
1081
|
+
};
|
|
1082
|
+
if (!success && !step.continueOnError) {
|
|
1083
|
+
aborted = true;
|
|
1084
|
+
}
|
|
1085
|
+
onProgress({ stepResults: [...stepResults], currentStepIndex: i, done: false });
|
|
1086
|
+
}
|
|
1087
|
+
onProgress({
|
|
1088
|
+
stepResults: [...stepResults],
|
|
1089
|
+
currentStepIndex: pipeline.steps.length - 1,
|
|
1090
|
+
done: true
|
|
1091
|
+
});
|
|
1092
|
+
return stepResults;
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
// src/config/projectConfig.ts
|
|
1096
|
+
import { existsSync as existsSync3, readFileSync, writeFileSync, mkdirSync } from "fs";
|
|
1097
|
+
import { join as join3 } from "path";
|
|
1098
|
+
|
|
1099
|
+
// src/lib/packageRoot.ts
|
|
1100
|
+
import { existsSync as existsSync2 } from "fs";
|
|
1101
|
+
import { dirname as dirname2, join as join2, resolve as resolve2 } from "path";
|
|
1102
|
+
var rootCache = /* @__PURE__ */ new Map();
|
|
1103
|
+
function findNearestPackageRoot(startDir = process.cwd()) {
|
|
1104
|
+
const resolvedStart = resolve2(startDir);
|
|
1105
|
+
if (rootCache.has(resolvedStart)) return rootCache.get(resolvedStart);
|
|
1106
|
+
let currentDir = resolvedStart;
|
|
1107
|
+
while (true) {
|
|
1108
|
+
if (existsSync2(join2(currentDir, "package.json"))) {
|
|
1109
|
+
rootCache.set(resolvedStart, currentDir);
|
|
1110
|
+
return currentDir;
|
|
1111
|
+
}
|
|
1112
|
+
const parentDir = dirname2(currentDir);
|
|
1113
|
+
if (parentDir === currentDir) {
|
|
1114
|
+
rootCache.set(resolvedStart, void 0);
|
|
1115
|
+
return void 0;
|
|
1116
|
+
}
|
|
1117
|
+
currentDir = parentDir;
|
|
1118
|
+
}
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
// src/config/projectConfig.ts
|
|
1122
|
+
var CONFIG_DIR = ".polter";
|
|
1123
|
+
var CONFIG_FILE = "config.json";
|
|
1124
|
+
function defaultConfig() {
|
|
1125
|
+
return {
|
|
1126
|
+
version: 1,
|
|
1127
|
+
tools: {},
|
|
1128
|
+
pipelines: []
|
|
1129
|
+
};
|
|
1130
|
+
}
|
|
1131
|
+
function getProjectConfigPath(startDir) {
|
|
1132
|
+
const root = findNearestPackageRoot(startDir);
|
|
1133
|
+
if (!root) return void 0;
|
|
1134
|
+
const dir = join3(root, CONFIG_DIR);
|
|
1135
|
+
return { dir, file: join3(dir, CONFIG_FILE) };
|
|
1136
|
+
}
|
|
1137
|
+
function readProjectConfig(startDir) {
|
|
1138
|
+
const paths = getProjectConfigPath(startDir);
|
|
1139
|
+
if (!paths) return void 0;
|
|
1140
|
+
if (!existsSync3(paths.file)) return void 0;
|
|
1141
|
+
try {
|
|
1142
|
+
const raw = readFileSync(paths.file, "utf-8");
|
|
1143
|
+
return JSON.parse(raw);
|
|
1144
|
+
} catch {
|
|
1145
|
+
return void 0;
|
|
1146
|
+
}
|
|
1147
|
+
}
|
|
1148
|
+
function writeProjectConfig(config2, startDir) {
|
|
1149
|
+
const paths = getProjectConfigPath(startDir);
|
|
1150
|
+
if (!paths) return false;
|
|
1151
|
+
mkdirSync(paths.dir, { recursive: true });
|
|
1152
|
+
writeFileSync(paths.file, JSON.stringify(config2, null, 2) + "\n", "utf-8");
|
|
1153
|
+
return true;
|
|
1154
|
+
}
|
|
1155
|
+
function getOrCreateProjectConfig(startDir) {
|
|
1156
|
+
return readProjectConfig(startDir) ?? defaultConfig();
|
|
1157
|
+
}
|
|
1158
|
+
function getProjectPipelines(startDir) {
|
|
1159
|
+
const config2 = readProjectConfig(startDir);
|
|
1160
|
+
return config2?.pipelines ?? [];
|
|
1161
|
+
}
|
|
1162
|
+
function saveProjectPipeline(pipeline, startDir) {
|
|
1163
|
+
const config2 = getOrCreateProjectConfig(startDir);
|
|
1164
|
+
const idx = config2.pipelines.findIndex((p) => p.id === pipeline.id);
|
|
1165
|
+
if (idx >= 0) {
|
|
1166
|
+
config2.pipelines[idx] = pipeline;
|
|
1167
|
+
} else {
|
|
1168
|
+
config2.pipelines.push(pipeline);
|
|
1169
|
+
}
|
|
1170
|
+
return writeProjectConfig(config2, startDir);
|
|
1171
|
+
}
|
|
1172
|
+
function deleteProjectPipeline(pipelineId, startDir) {
|
|
1173
|
+
const config2 = getOrCreateProjectConfig(startDir);
|
|
1174
|
+
config2.pipelines = config2.pipelines.filter((p) => p.id !== pipelineId);
|
|
1175
|
+
return writeProjectConfig(config2, startDir);
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
// src/config/store.ts
|
|
1179
|
+
import Conf from "conf";
|
|
1180
|
+
var config = new Conf({
|
|
1181
|
+
projectName: process.env.NODE_ENV === "test" ? "polter-test" : "polter"
|
|
1182
|
+
});
|
|
1183
|
+
var GLOBAL_PIPELINES_KEY = "globalPipelinesV1";
|
|
1184
|
+
function getGlobalPipelines() {
|
|
1185
|
+
if (!config.has(GLOBAL_PIPELINES_KEY)) {
|
|
1186
|
+
config.set(GLOBAL_PIPELINES_KEY, []);
|
|
1187
|
+
}
|
|
1188
|
+
return config.get(GLOBAL_PIPELINES_KEY) || [];
|
|
1189
|
+
}
|
|
1190
|
+
function saveGlobalPipeline(pipeline) {
|
|
1191
|
+
const pipelines = getGlobalPipelines();
|
|
1192
|
+
const idx = pipelines.findIndex((p) => p.id === pipeline.id);
|
|
1193
|
+
if (idx >= 0) {
|
|
1194
|
+
pipelines[idx] = pipeline;
|
|
1195
|
+
} else {
|
|
1196
|
+
pipelines.push(pipeline);
|
|
1197
|
+
}
|
|
1198
|
+
config.set(GLOBAL_PIPELINES_KEY, pipelines);
|
|
1199
|
+
}
|
|
1200
|
+
function deleteGlobalPipeline(pipelineId) {
|
|
1201
|
+
const pipelines = getGlobalPipelines().filter((p) => p.id !== pipelineId);
|
|
1202
|
+
config.set(GLOBAL_PIPELINES_KEY, pipelines);
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
// src/pipeline/storage.ts
|
|
1206
|
+
function getAllPipelines(startDir) {
|
|
1207
|
+
const projectPipelines = getProjectPipelines(startDir).map((p) => ({
|
|
1208
|
+
...p,
|
|
1209
|
+
source: "project"
|
|
1210
|
+
}));
|
|
1211
|
+
const globalPipelines = getGlobalPipelines().map((p) => ({
|
|
1212
|
+
...p,
|
|
1213
|
+
source: "global"
|
|
1214
|
+
}));
|
|
1215
|
+
const seen = new Set(projectPipelines.map((p) => p.id));
|
|
1216
|
+
const merged = [
|
|
1217
|
+
...projectPipelines,
|
|
1218
|
+
...globalPipelines.filter((p) => !seen.has(p.id))
|
|
1219
|
+
];
|
|
1220
|
+
return merged;
|
|
1221
|
+
}
|
|
1222
|
+
function savePipeline(pipeline, source, startDir) {
|
|
1223
|
+
if (source === "project") {
|
|
1224
|
+
saveProjectPipeline(pipeline, startDir);
|
|
1225
|
+
} else {
|
|
1226
|
+
saveGlobalPipeline(pipeline);
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
function deletePipeline(pipelineId, source, startDir) {
|
|
1230
|
+
if (source === "project") {
|
|
1231
|
+
deleteProjectPipeline(pipelineId, startDir);
|
|
1232
|
+
} else {
|
|
1233
|
+
deleteGlobalPipeline(pipelineId);
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
function findPipelineByName(name, startDir) {
|
|
1237
|
+
return getAllPipelines(startDir).find((p) => p.name === name);
|
|
1238
|
+
}
|
|
1239
|
+
|
|
1240
|
+
// src/declarative/parser.ts
|
|
1241
|
+
import { existsSync as existsSync4, readFileSync as readFileSync2 } from "fs";
|
|
1242
|
+
import { join as join4 } from "path";
|
|
1243
|
+
var YAML_FILE = "polter.yaml";
|
|
1244
|
+
function parseSimpleYaml(content) {
|
|
1245
|
+
const lines = content.split("\n");
|
|
1246
|
+
const result = {};
|
|
1247
|
+
const stack = [
|
|
1248
|
+
{ obj: result, indent: -1 }
|
|
1249
|
+
];
|
|
1250
|
+
for (let i = 0; i < lines.length; i++) {
|
|
1251
|
+
const line = lines[i];
|
|
1252
|
+
const trimmed = line.replace(/\s+$/, "");
|
|
1253
|
+
if (!trimmed || trimmed.match(/^\s*#/)) continue;
|
|
1254
|
+
const indent = line.search(/\S/);
|
|
1255
|
+
if (indent < 0) continue;
|
|
1256
|
+
while (stack.length > 1 && stack[stack.length - 1].indent >= indent) {
|
|
1257
|
+
stack.pop();
|
|
1258
|
+
}
|
|
1259
|
+
const current = stack[stack.length - 1].obj;
|
|
1260
|
+
const content_ = trimmed.trim();
|
|
1261
|
+
if (content_.startsWith("- ")) {
|
|
1262
|
+
const parentKey = Object.keys(current).pop();
|
|
1263
|
+
if (parentKey) {
|
|
1264
|
+
const arr = current[parentKey];
|
|
1265
|
+
if (Array.isArray(arr)) {
|
|
1266
|
+
const val = content_.slice(2).trim();
|
|
1267
|
+
const colonIdx2 = val.indexOf(":");
|
|
1268
|
+
if (colonIdx2 > 0 && !val.startsWith('"') && !val.startsWith("'")) {
|
|
1269
|
+
const key = val.slice(0, colonIdx2).trim();
|
|
1270
|
+
const rest = val.slice(colonIdx2 + 1).trim();
|
|
1271
|
+
const obj = { [key]: parseValue(rest) };
|
|
1272
|
+
arr.push(obj);
|
|
1273
|
+
stack.push({ obj, indent: indent + 2 });
|
|
1274
|
+
} else {
|
|
1275
|
+
arr.push(parseValue(val));
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
1278
|
+
}
|
|
1279
|
+
continue;
|
|
1280
|
+
}
|
|
1281
|
+
const colonIdx = content_.indexOf(":");
|
|
1282
|
+
if (colonIdx > 0) {
|
|
1283
|
+
const key = content_.slice(0, colonIdx).trim();
|
|
1284
|
+
const rest = content_.slice(colonIdx + 1).trim();
|
|
1285
|
+
if (rest === "" || rest === "|" || rest === ">") {
|
|
1286
|
+
const nextLine = lines[i + 1];
|
|
1287
|
+
const nextTrimmed = nextLine?.trim();
|
|
1288
|
+
if (nextTrimmed?.startsWith("- ")) {
|
|
1289
|
+
current[key] = [];
|
|
1290
|
+
} else {
|
|
1291
|
+
const nested = {};
|
|
1292
|
+
current[key] = nested;
|
|
1293
|
+
stack.push({ obj: nested, indent });
|
|
1294
|
+
}
|
|
1295
|
+
} else {
|
|
1296
|
+
current[key] = parseValue(rest);
|
|
1297
|
+
}
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
return result;
|
|
1301
|
+
}
|
|
1302
|
+
function parseValue(raw) {
|
|
1303
|
+
if (!raw) return "";
|
|
1304
|
+
if (raw.startsWith('"') && raw.endsWith('"') || raw.startsWith("'") && raw.endsWith("'")) {
|
|
1305
|
+
return raw.slice(1, -1);
|
|
1306
|
+
}
|
|
1307
|
+
if (raw === "true") return true;
|
|
1308
|
+
if (raw === "false") return false;
|
|
1309
|
+
const num = Number(raw);
|
|
1310
|
+
if (!isNaN(num) && raw !== "") return num;
|
|
1311
|
+
return raw;
|
|
1312
|
+
}
|
|
1313
|
+
function findPolterYaml(startDir = process.cwd()) {
|
|
1314
|
+
const filePath = join4(startDir, YAML_FILE);
|
|
1315
|
+
return existsSync4(filePath) ? filePath : void 0;
|
|
1316
|
+
}
|
|
1317
|
+
function parsePolterYaml(startDir = process.cwd()) {
|
|
1318
|
+
const filePath = findPolterYaml(startDir);
|
|
1319
|
+
if (!filePath) return void 0;
|
|
1320
|
+
const content = readFileSync2(filePath, "utf-8");
|
|
1321
|
+
const raw = parseSimpleYaml(content);
|
|
1322
|
+
return raw;
|
|
1323
|
+
}
|
|
1324
|
+
|
|
1325
|
+
// src/declarative/status.ts
|
|
1326
|
+
import { execSync as execSync2 } from "child_process";
|
|
1327
|
+
function safeExec(cmd) {
|
|
1328
|
+
try {
|
|
1329
|
+
return execSync2(cmd, { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
1330
|
+
} catch {
|
|
1331
|
+
return void 0;
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
function getCurrentStatus(cwd = process.cwd()) {
|
|
1335
|
+
const result = {};
|
|
1336
|
+
if (commandExists("supabase")) {
|
|
1337
|
+
const linked = safeExec(`cd "${cwd}" && supabase projects list 2>/dev/null`) !== void 0;
|
|
1338
|
+
result.supabase = {
|
|
1339
|
+
linked,
|
|
1340
|
+
projectRef: void 0,
|
|
1341
|
+
functions: []
|
|
1342
|
+
};
|
|
1343
|
+
const functionsOutput = safeExec(`cd "${cwd}" && supabase functions list 2>/dev/null`);
|
|
1344
|
+
if (functionsOutput) {
|
|
1345
|
+
result.supabase.functions = functionsOutput.split("\n").filter((line) => line.trim() && !line.startsWith("\u2502") && !line.startsWith("\u250C")).slice(1);
|
|
1346
|
+
}
|
|
1347
|
+
}
|
|
1348
|
+
if (commandExists("vercel")) {
|
|
1349
|
+
const whoami = safeExec("vercel whoami 2>/dev/null");
|
|
1350
|
+
result.vercel = {
|
|
1351
|
+
linked: !!whoami,
|
|
1352
|
+
projectId: void 0
|
|
1353
|
+
};
|
|
1354
|
+
}
|
|
1355
|
+
if (commandExists("gh")) {
|
|
1356
|
+
const authStatus = safeExec("gh auth status 2>&1");
|
|
1357
|
+
const authenticated = authStatus?.includes("Logged in") ?? false;
|
|
1358
|
+
const repoOutput = safeExec(`cd "${cwd}" && gh repo view --json nameWithOwner -q .nameWithOwner 2>/dev/null`);
|
|
1359
|
+
result.github = {
|
|
1360
|
+
repo: repoOutput || void 0,
|
|
1361
|
+
authenticated
|
|
1362
|
+
};
|
|
1363
|
+
}
|
|
1364
|
+
return result;
|
|
1365
|
+
}
|
|
1366
|
+
|
|
1367
|
+
// src/declarative/planner.ts
|
|
1368
|
+
function planChanges(desired, cwd = process.cwd()) {
|
|
1369
|
+
const current = getCurrentStatus(cwd);
|
|
1370
|
+
const actions = [];
|
|
1371
|
+
if (desired.supabase?.functions) {
|
|
1372
|
+
const currentFunctions = new Set(current.supabase?.functions ?? []);
|
|
1373
|
+
for (const fn of desired.supabase.functions) {
|
|
1374
|
+
if (!currentFunctions.has(fn.name)) {
|
|
1375
|
+
const args = ["functions", "deploy", fn.name];
|
|
1376
|
+
if (fn.verify_jwt === false) {
|
|
1377
|
+
args.push("--no-verify-jwt");
|
|
1378
|
+
}
|
|
1379
|
+
actions.push({
|
|
1380
|
+
tool: "supabase",
|
|
1381
|
+
action: "create",
|
|
1382
|
+
resource: `function:${fn.name}`,
|
|
1383
|
+
description: `Deploy function "${fn.name}"`,
|
|
1384
|
+
args
|
|
1385
|
+
});
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
}
|
|
1389
|
+
if (desired.supabase?.secrets) {
|
|
1390
|
+
for (const secret of desired.supabase.secrets) {
|
|
1391
|
+
actions.push({
|
|
1392
|
+
tool: "supabase",
|
|
1393
|
+
action: "update",
|
|
1394
|
+
resource: `secret:${secret}`,
|
|
1395
|
+
description: `Ensure secret "${secret}" is set`,
|
|
1396
|
+
args: ["secrets", "set", secret]
|
|
1397
|
+
});
|
|
1398
|
+
}
|
|
1399
|
+
}
|
|
1400
|
+
if (desired.vercel?.domains) {
|
|
1401
|
+
for (const domain of desired.vercel.domains) {
|
|
1402
|
+
actions.push({
|
|
1403
|
+
tool: "vercel",
|
|
1404
|
+
action: "create",
|
|
1405
|
+
resource: `domain:${domain}`,
|
|
1406
|
+
description: `Add domain "${domain}"`,
|
|
1407
|
+
args: ["domains", "add", domain]
|
|
1408
|
+
});
|
|
1409
|
+
}
|
|
1410
|
+
}
|
|
1411
|
+
if (desired.vercel?.env) {
|
|
1412
|
+
for (const [env, vars] of Object.entries(desired.vercel.env)) {
|
|
1413
|
+
for (const [key, value] of Object.entries(vars)) {
|
|
1414
|
+
actions.push({
|
|
1415
|
+
tool: "vercel",
|
|
1416
|
+
action: "update",
|
|
1417
|
+
resource: `env:${env}:${key}`,
|
|
1418
|
+
description: `Set env var "${key}" for ${env}`,
|
|
1419
|
+
args: ["env", "add", key, env]
|
|
1420
|
+
});
|
|
1421
|
+
}
|
|
1422
|
+
}
|
|
1423
|
+
}
|
|
1424
|
+
if (desired.github?.secrets) {
|
|
1425
|
+
for (const secret of desired.github.secrets) {
|
|
1426
|
+
actions.push({
|
|
1427
|
+
tool: "gh",
|
|
1428
|
+
action: "update",
|
|
1429
|
+
resource: `secret:${secret}`,
|
|
1430
|
+
description: `Ensure GitHub secret "${secret}" is set`,
|
|
1431
|
+
args: ["secret", "set", secret]
|
|
1432
|
+
});
|
|
1433
|
+
}
|
|
1434
|
+
}
|
|
1435
|
+
return {
|
|
1436
|
+
actions,
|
|
1437
|
+
noChanges: actions.length === 0
|
|
1438
|
+
};
|
|
1439
|
+
}
|
|
1440
|
+
|
|
1441
|
+
// src/declarative/applier.ts
|
|
1442
|
+
async function applyActions(actions, cwd = process.cwd(), onProgress) {
|
|
1443
|
+
const results = [];
|
|
1444
|
+
for (let i = 0; i < actions.length; i++) {
|
|
1445
|
+
const action = actions[i];
|
|
1446
|
+
onProgress?.(i, actions.length, action);
|
|
1447
|
+
const resolved = resolveToolCommand(action.tool, cwd);
|
|
1448
|
+
const result = await runCommand(
|
|
1449
|
+
{ command: resolved.command, env: resolved.env },
|
|
1450
|
+
action.args,
|
|
1451
|
+
cwd
|
|
1452
|
+
);
|
|
1453
|
+
const success = !result.spawnError && result.exitCode === 0;
|
|
1454
|
+
results.push({ action, success, result });
|
|
1455
|
+
}
|
|
1456
|
+
return results;
|
|
1457
|
+
}
|
|
1458
|
+
|
|
1459
|
+
export {
|
|
1460
|
+
__export,
|
|
1461
|
+
allCommands,
|
|
1462
|
+
getCommandById,
|
|
1463
|
+
getCommandsByTool,
|
|
1464
|
+
getCommandValue,
|
|
1465
|
+
findCommandByValue,
|
|
1466
|
+
features,
|
|
1467
|
+
getFeatureById,
|
|
1468
|
+
toolFlags,
|
|
1469
|
+
getFlagsForTool,
|
|
1470
|
+
runCommand,
|
|
1471
|
+
runSupabaseCommand,
|
|
1472
|
+
commandExists,
|
|
1473
|
+
resolveToolCommand,
|
|
1474
|
+
getToolInfo,
|
|
1475
|
+
executePipeline,
|
|
1476
|
+
findNearestPackageRoot,
|
|
1477
|
+
getProjectConfigPath,
|
|
1478
|
+
writeProjectConfig,
|
|
1479
|
+
getOrCreateProjectConfig,
|
|
1480
|
+
getAllPipelines,
|
|
1481
|
+
savePipeline,
|
|
1482
|
+
deletePipeline,
|
|
1483
|
+
findPipelineByName,
|
|
1484
|
+
parsePolterYaml,
|
|
1485
|
+
getCurrentStatus,
|
|
1486
|
+
planChanges,
|
|
1487
|
+
applyActions
|
|
1488
|
+
};
|