@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.
@@ -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
+ };