@polterware/polter 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/api.js CHANGED
@@ -20,7 +20,7 @@ import {
20
20
  runCommand,
21
21
  savePipeline,
22
22
  toolFlags
23
- } from "./chunk-3XNNC5AW.js";
23
+ } from "./chunk-2MXXRP4H.js";
24
24
  export {
25
25
  allCommands,
26
26
  applyActions,
@@ -131,7 +131,15 @@ var supabaseCommands = [
131
131
  tool: "supabase",
132
132
  base: ["link"],
133
133
  label: "link",
134
- hint: "Link to remote project"
134
+ hint: "Link to remote project",
135
+ suggestedArgs: [
136
+ {
137
+ value: "project-ref",
138
+ label: "--project-ref <ref>",
139
+ hint: "Link with project ref",
140
+ args: ["--project-ref"]
141
+ }
142
+ ]
135
143
  },
136
144
  {
137
145
  id: "supabase:unlink",
@@ -863,7 +871,7 @@ function getFlagsForTool(toolId) {
863
871
  }
864
872
 
865
873
  // src/lib/runner.ts
866
- import { spawn } from "child_process";
874
+ import { spawn, spawnSync } from "child_process";
867
875
  import { existsSync } from "fs";
868
876
  import { delimiter, dirname, join, resolve } from "path";
869
877
  function getSupabaseBinaryCandidates() {
@@ -953,6 +961,22 @@ async function runCommand(execution, args, cwd = process.cwd(), options) {
953
961
  });
954
962
  });
955
963
  }
964
+ function runInteractiveCommand(execution, args, cwd = process.cwd()) {
965
+ const resolved = typeof execution === "string" ? { command: execution } : execution;
966
+ const result = spawnSync(resolved.command, args, {
967
+ cwd,
968
+ env: resolved.env,
969
+ shell: true,
970
+ stdio: "inherit"
971
+ });
972
+ return {
973
+ exitCode: result.status,
974
+ signal: result.signal,
975
+ stdout: "",
976
+ stderr: "",
977
+ spawnError: result.error?.message
978
+ };
979
+ }
956
980
  async function runSupabaseCommand(args, cwd = process.cwd()) {
957
981
  return runCommand(resolveSupabaseCommand(cwd), args, cwd);
958
982
  }
@@ -1451,6 +1475,7 @@ export {
1451
1475
  toolFlags,
1452
1476
  getFlagsForTool,
1453
1477
  runCommand,
1478
+ runInteractiveCommand,
1454
1479
  runSupabaseCommand,
1455
1480
  commandExists,
1456
1481
  resolveToolCommand,
package/dist/index.js CHANGED
@@ -21,10 +21,11 @@ import {
21
21
  planChanges,
22
22
  resolveToolCommand,
23
23
  runCommand,
24
+ runInteractiveCommand,
24
25
  runSupabaseCommand,
25
26
  savePipeline,
26
27
  writeProjectConfig
27
- } from "./chunk-3XNNC5AW.js";
28
+ } from "./chunk-2MXXRP4H.js";
28
29
 
29
30
  // src/index.tsx
30
31
  import React20 from "react";
@@ -1486,7 +1487,7 @@ function FlagSelection({
1486
1487
  }
1487
1488
 
1488
1489
  // src/screens/CommandExecution.tsx
1489
- import { useState as useState11, useEffect as useEffect5 } from "react";
1490
+ import { useState as useState11, useEffect as useEffect6 } from "react";
1490
1491
  import { Box as Box13, Text as Text17 } from "ink";
1491
1492
 
1492
1493
  // src/components/Spinner.tsx
@@ -1668,6 +1669,56 @@ function useCommand(execution = "supabase", cwd = process.cwd(), options) {
1668
1669
  return { status, result, run, reset };
1669
1670
  }
1670
1671
 
1672
+ // src/hooks/useInteractiveRun.ts
1673
+ import { useCallback as useCallback3 } from "react";
1674
+ import { useStdin } from "ink";
1675
+
1676
+ // src/hooks/useFullscreen.ts
1677
+ import { useEffect as useEffect5 } from "react";
1678
+ var ENTER_ALT_SCREEN = "\x1B[?1049h";
1679
+ var LEAVE_ALT_SCREEN = "\x1B[?1049l";
1680
+ var HIDE_CURSOR = "\x1B[?25l";
1681
+ var SHOW_CURSOR = "\x1B[?25h";
1682
+ function useFullscreen() {
1683
+ useEffect5(() => {
1684
+ process.stdout.write(ENTER_ALT_SCREEN + HIDE_CURSOR);
1685
+ return () => {
1686
+ process.stdout.write(SHOW_CURSOR + LEAVE_ALT_SCREEN);
1687
+ };
1688
+ }, []);
1689
+ }
1690
+
1691
+ // src/hooks/useInteractiveRun.ts
1692
+ function useInteractiveRun() {
1693
+ const { setRawMode } = useStdin();
1694
+ const runInteractive = useCallback3(
1695
+ (tool, args, cwd) => {
1696
+ process.stdout.write(SHOW_CURSOR + LEAVE_ALT_SCREEN);
1697
+ setRawMode(false);
1698
+ process.stdout.write(`
1699
+ Running: ${tool} ${args.join(" ")}
1700
+
1701
+ `);
1702
+ const resolved = resolveToolCommand(tool, cwd);
1703
+ const result = runInteractiveCommand(
1704
+ { command: resolved.command, env: resolved.env },
1705
+ args,
1706
+ cwd
1707
+ );
1708
+ process.stdout.write(
1709
+ `
1710
+ Command exited (code ${result.exitCode ?? "?"}). Returning to Polter...
1711
+ `
1712
+ );
1713
+ setRawMode(true);
1714
+ process.stdout.write(ENTER_ALT_SCREEN + HIDE_CURSOR);
1715
+ return result;
1716
+ },
1717
+ [setRawMode]
1718
+ );
1719
+ return { runInteractive };
1720
+ }
1721
+
1671
1722
  // src/lib/clipboard.ts
1672
1723
  import { spawn, exec } from "child_process";
1673
1724
  async function copyToClipboard(text) {
@@ -1746,14 +1797,15 @@ function CommandExecution({
1746
1797
  const { status, result, run, reset } = useCommand(tool, process.cwd(), {
1747
1798
  quiet: panelMode
1748
1799
  });
1800
+ const { runInteractive } = useInteractiveRun();
1749
1801
  const cmdDisplay = `${tool} ${currentArgs.join(" ")}`;
1750
1802
  const runCommand2 = currentArgs.join(" ");
1751
- useEffect5(() => {
1803
+ useEffect6(() => {
1752
1804
  if (phase === "running" && status === "idle") {
1753
1805
  run(currentArgs);
1754
1806
  }
1755
1807
  }, [phase, status, run, currentArgs]);
1756
- useEffect5(() => {
1808
+ useEffect6(() => {
1757
1809
  if (phase === "running" && status === "success") {
1758
1810
  if (isPinnedRun(runCommand2)) {
1759
1811
  setPhase("success");
@@ -1916,6 +1968,13 @@ function CommandExecution({
1916
1968
  });
1917
1969
  }
1918
1970
  }
1971
+ if (panelMode && !result?.spawnError) {
1972
+ errorItems.push({
1973
+ value: "run-interactive",
1974
+ label: "\u{1F4BB} Run in terminal",
1975
+ hint: "Suspend TUI and run interactively"
1976
+ });
1977
+ }
1919
1978
  errorItems.push({
1920
1979
  value: "copy",
1921
1980
  label: "\u{1F4CB} Copy command to clipboard"
@@ -1967,7 +2026,7 @@ function CommandExecution({
1967
2026
  {
1968
2027
  stdout: result?.stdout,
1969
2028
  stderr: result?.stderr,
1970
- height: Math.max(3, height - 16 - (suggestions.length > 0 ? suggestions.length + 4 : 0)),
2029
+ height: Math.max(3, height - 13 - errorItems.length - (suggestions.length > 0 ? suggestions.length + 4 : 0)),
1971
2030
  isActive: false
1972
2031
  }
1973
2032
  ),
@@ -2006,6 +2065,13 @@ function CommandExecution({
2006
2065
  setPhase("running");
2007
2066
  break;
2008
2067
  }
2068
+ case "run-interactive": {
2069
+ const interactiveResult = runInteractive(tool, currentArgs);
2070
+ if (!interactiveResult.spawnError && interactiveResult.exitCode === 0) {
2071
+ setPhase("success");
2072
+ }
2073
+ break;
2074
+ }
2009
2075
  case "copy":
2010
2076
  await copyToClipboard(cmdDisplay);
2011
2077
  break;
@@ -2031,7 +2097,7 @@ function CommandExecution({
2031
2097
  }
2032
2098
 
2033
2099
  // src/screens/SelfUpdate.tsx
2034
- import { useEffect as useEffect6, useState as useState12 } from "react";
2100
+ import { useEffect as useEffect7, useState as useState12 } from "react";
2035
2101
  import { Box as Box14, Text as Text18 } from "ink";
2036
2102
  import { jsx as jsx18, jsxs as jsxs16 } from "react/jsx-runtime";
2037
2103
  var packageName = "@polterware/polter";
@@ -2061,12 +2127,12 @@ function SelfUpdate({
2061
2127
  const { status, result, run, reset } = useCommand("npm", updateCwd, {
2062
2128
  quiet: panelMode
2063
2129
  });
2064
- useEffect6(() => {
2130
+ useEffect7(() => {
2065
2131
  if (phase === "running" && status === "idle") {
2066
2132
  run(updateArgs);
2067
2133
  }
2068
2134
  }, [phase, run, status, updateArgs]);
2069
- useEffect6(() => {
2135
+ useEffect7(() => {
2070
2136
  if (phase === "running" && status === "success") {
2071
2137
  setPhase("success");
2072
2138
  }
@@ -2365,8 +2431,8 @@ import { useMemo as useMemo5, useState as useState14 } from "react";
2365
2431
  import { Box as Box16, Text as Text20 } from "ink";
2366
2432
 
2367
2433
  // src/hooks/useEditor.ts
2368
- import { useState as useState13, useCallback as useCallback3 } from "react";
2369
- import { useStdin } from "ink";
2434
+ import { useState as useState13, useCallback as useCallback4 } from "react";
2435
+ import { useStdin as useStdin2 } from "ink";
2370
2436
 
2371
2437
  // src/lib/editor.ts
2372
2438
  import { spawnSync, spawn as spawn2 } from "child_process";
@@ -2415,9 +2481,9 @@ function openInEditor(filePath) {
2415
2481
 
2416
2482
  // src/hooks/useEditor.ts
2417
2483
  function useEditor() {
2418
- const { setRawMode } = useStdin();
2484
+ const { setRawMode } = useStdin2();
2419
2485
  const [isEditing, setIsEditing] = useState13(false);
2420
- const openEditor = useCallback3(async (filePath) => {
2486
+ const openEditor = useCallback4(async (filePath) => {
2421
2487
  const editor = resolveEditor();
2422
2488
  const terminal = isTerminalEditor(editor.command);
2423
2489
  setIsEditing(true);
@@ -2956,7 +3022,7 @@ function PipelineBuilder({
2956
3022
  }
2957
3023
 
2958
3024
  // src/screens/PipelineExecution.tsx
2959
- import { useState as useState16, useEffect as useEffect7, useMemo as useMemo7 } from "react";
3025
+ import { useState as useState16, useEffect as useEffect8, useMemo as useMemo7 } from "react";
2960
3026
  import { Box as Box21, Text as Text25 } from "ink";
2961
3027
 
2962
3028
  // src/components/StepIndicator.tsx
@@ -3052,7 +3118,7 @@ function PipelineExecution({
3052
3118
  const [phase, setPhase] = useState16("running");
3053
3119
  const [progress, setProgress] = useState16(null);
3054
3120
  const [results, setResults] = useState16([]);
3055
- useEffect7(() => {
3121
+ useEffect8(() => {
3056
3122
  if (!pipeline) return;
3057
3123
  executePipeline(pipeline, (p) => {
3058
3124
  setProgress({ ...p });
@@ -3259,23 +3325,8 @@ function AppClassic() {
3259
3325
  import React19 from "react";
3260
3326
  import { Box as Box30, Text as Text33, useApp as useApp2, useInput as useInput9 } from "ink";
3261
3327
 
3262
- // src/hooks/useFullscreen.ts
3263
- import { useEffect as useEffect8 } from "react";
3264
- var ENTER_ALT_SCREEN = "\x1B[?1049h";
3265
- var LEAVE_ALT_SCREEN = "\x1B[?1049l";
3266
- var HIDE_CURSOR = "\x1B[?25l";
3267
- var SHOW_CURSOR = "\x1B[?25h";
3268
- function useFullscreen() {
3269
- useEffect8(() => {
3270
- process.stdout.write(ENTER_ALT_SCREEN + HIDE_CURSOR);
3271
- return () => {
3272
- process.stdout.write(SHOW_CURSOR + LEAVE_ALT_SCREEN);
3273
- };
3274
- }, []);
3275
- }
3276
-
3277
3328
  // src/hooks/usePanelNavigation.ts
3278
- import { useState as useState17, useCallback as useCallback4 } from "react";
3329
+ import { useState as useState17, useCallback as useCallback5 } from "react";
3279
3330
  function usePanelNavigation() {
3280
3331
  const [state, setState] = useState17({
3281
3332
  view: "pipelines",
@@ -3284,7 +3335,7 @@ function usePanelNavigation() {
3284
3335
  innerParams: {},
3285
3336
  innerStack: []
3286
3337
  });
3287
- const selectSidebarItem = useCallback4((itemId) => {
3338
+ const selectSidebarItem = useCallback5((itemId) => {
3288
3339
  const featureIds = [
3289
3340
  "database",
3290
3341
  "functions",
@@ -3325,7 +3376,7 @@ function usePanelNavigation() {
3325
3376
  });
3326
3377
  }
3327
3378
  }, [state.featureId]);
3328
- const navigateInner = useCallback4((screen, params) => {
3379
+ const navigateInner = useCallback5((screen, params) => {
3329
3380
  setState((prev) => ({
3330
3381
  ...prev,
3331
3382
  innerStack: [...prev.innerStack, { screen: prev.innerScreen, params: prev.innerParams }],
@@ -3333,7 +3384,7 @@ function usePanelNavigation() {
3333
3384
  innerParams: params ?? {}
3334
3385
  }));
3335
3386
  }, []);
3336
- const goBackInner = useCallback4(() => {
3387
+ const goBackInner = useCallback5(() => {
3337
3388
  setState((prev) => {
3338
3389
  if (prev.innerStack.length === 0) {
3339
3390
  return { ...prev, innerScreen: "home", innerParams: {} };
@@ -3348,7 +3399,7 @@ function usePanelNavigation() {
3348
3399
  };
3349
3400
  });
3350
3401
  }, []);
3351
- const goHomeInner = useCallback4(() => {
3402
+ const goHomeInner = useCallback5(() => {
3352
3403
  setState((prev) => ({
3353
3404
  ...prev,
3354
3405
  innerScreen: "home",
@@ -3356,7 +3407,7 @@ function usePanelNavigation() {
3356
3407
  innerStack: []
3357
3408
  }));
3358
3409
  }, []);
3359
- const switchViewAndNavigate = useCallback4(
3410
+ const switchViewAndNavigate = useCallback5(
3360
3411
  (view, screen, params) => {
3361
3412
  setState((prev) => ({
3362
3413
  ...prev,
@@ -3379,14 +3430,14 @@ function usePanelNavigation() {
3379
3430
  }
3380
3431
 
3381
3432
  // src/hooks/usePanelFocus.ts
3382
- import { useState as useState18, useCallback as useCallback5 } from "react";
3433
+ import { useState as useState18, useCallback as useCallback6 } from "react";
3383
3434
  function usePanelFocus() {
3384
3435
  const [focused, setFocused] = useState18("sidebar");
3385
- const toggleFocus = useCallback5(() => {
3436
+ const toggleFocus = useCallback6(() => {
3386
3437
  setFocused((prev) => prev === "sidebar" ? "main" : "sidebar");
3387
3438
  }, []);
3388
- const focusSidebar = useCallback5(() => setFocused("sidebar"), []);
3389
- const focusMain = useCallback5(() => setFocused("main"), []);
3439
+ const focusSidebar = useCallback6(() => setFocused("sidebar"), []);
3440
+ const focusMain = useCallback6(() => setFocused("main"), []);
3390
3441
  return {
3391
3442
  focused,
3392
3443
  isSidebarFocused: focused === "sidebar",
@@ -3425,13 +3476,13 @@ function useSidebarItems() {
3425
3476
  }
3426
3477
 
3427
3478
  // src/hooks/useModal.ts
3428
- import { useState as useState19, useCallback as useCallback6 } from "react";
3479
+ import { useState as useState19, useCallback as useCallback7 } from "react";
3429
3480
  function useModal() {
3430
3481
  const [state, setState] = useState19(null);
3431
- const openModal = useCallback6((content, title) => {
3482
+ const openModal = useCallback7((content, title) => {
3432
3483
  setState({ content, title });
3433
3484
  }, []);
3434
- const closeModal = useCallback6(() => {
3485
+ const closeModal = useCallback7(() => {
3435
3486
  setState(null);
3436
3487
  }, []);
3437
3488
  return {
package/dist/mcp.js CHANGED
@@ -17,7 +17,7 @@ import {
17
17
  resolveToolCommand,
18
18
  runCommand,
19
19
  savePipeline
20
- } from "./chunk-3XNNC5AW.js";
20
+ } from "./chunk-2MXXRP4H.js";
21
21
 
22
22
  // src/mcp.ts
23
23
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@polterware/polter",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "An interactive CLI for managing Supabase CLI workflows.",
5
5
  "type": "module",
6
6
  "bin": {