@speedkit/cli 4.17.0 → 4.18.0

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.
Files changed (52) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/README.md +75 -1
  3. package/dist/commands/browser/clean.d.ts +9 -0
  4. package/dist/commands/browser/clean.js +43 -0
  5. package/dist/commands/browser/list.d.ts +6 -0
  6. package/dist/commands/browser/list.js +29 -0
  7. package/dist/commands/browser/update.d.ts +6 -0
  8. package/dist/commands/browser/update.js +32 -0
  9. package/dist/commands/config/setup.d.ts +10 -0
  10. package/dist/commands/config/setup.js +28 -0
  11. package/dist/helpers/cli-config.d.ts +19 -0
  12. package/dist/helpers/cli-config.js +70 -4
  13. package/dist/helpers/cli-config.spec.d.ts +1 -0
  14. package/dist/helpers/cli-config.spec.js +70 -0
  15. package/dist/helpers/environment.d.ts +15 -0
  16. package/dist/helpers/environment.js +40 -0
  17. package/dist/helpers/environment.spec.d.ts +1 -0
  18. package/dist/helpers/environment.spec.js +28 -0
  19. package/dist/hooks/init/first-run.d.ts +8 -0
  20. package/dist/hooks/init/first-run.js +36 -0
  21. package/dist/services/onboarding/browser/baqend-response.d.ts +0 -5
  22. package/dist/services/onboarding/browser/baqend-response.js +0 -9
  23. package/dist/services/onboarding/file-events/file-watcher.d.ts +3 -3
  24. package/dist/services/onboarding/file-events/file-watcher.js +11 -7
  25. package/dist/services/onboarding/virtual-orestes-app/index.d.ts +7 -7
  26. package/dist/services/onboarding/virtual-orestes-app/index.js +13 -14
  27. package/dist/services/setup/browser/browser-detector.d.ts +27 -0
  28. package/dist/services/setup/browser/browser-detector.js +47 -0
  29. package/dist/services/setup/browser/browser-manager.d.ts +43 -0
  30. package/dist/services/setup/browser/browser-manager.js +101 -0
  31. package/dist/services/setup/browser/browser-setup-service.d.ts +28 -0
  32. package/dist/services/setup/browser/browser-setup-service.js +136 -0
  33. package/dist/services/setup/difftool/difftool-detector.d.ts +14 -0
  34. package/dist/services/setup/difftool/difftool-detector.js +27 -0
  35. package/dist/services/setup/difftool/difftool-setup-service.d.ts +15 -0
  36. package/dist/services/setup/difftool/difftool-setup-service.js +46 -0
  37. package/dist/services/setup/index.d.ts +10 -0
  38. package/dist/services/setup/index.js +10 -0
  39. package/dist/services/setup/os/detector-helper.d.ts +29 -0
  40. package/dist/services/setup/os/detector-helper.js +65 -0
  41. package/dist/services/setup/os/tool-registry.d.ts +38 -0
  42. package/dist/services/setup/os/tool-registry.js +194 -0
  43. package/dist/services/setup/os/tool-registry.spec.d.ts +1 -0
  44. package/dist/services/setup/os/tool-registry.spec.js +26 -0
  45. package/dist/services/setup/setup-context.d.ts +14 -0
  46. package/dist/services/setup/setup-context.js +15 -0
  47. package/dist/services/setup/setup-service-factory.d.ts +10 -0
  48. package/dist/services/setup/setup-service-factory.js +37 -0
  49. package/dist/services/setup/setup-service.d.ts +20 -0
  50. package/dist/services/setup/setup-service.js +37 -0
  51. package/oclif.manifest.json +122 -1
  52. package/package.json +1 -1
@@ -0,0 +1,10 @@
1
+ export * from "./setup-context.js";
2
+ export * from "./setup-service.js";
3
+ export * from "./setup-service-factory.js";
4
+ export * from "./browser/browser-detector.js";
5
+ export * from "./browser/browser-manager.js";
6
+ export * from "./browser/browser-setup-service.js";
7
+ export * from "./difftool/difftool-detector.js";
8
+ export * from "./difftool/difftool-setup-service.js";
9
+ export * from "./os/tool-registry.js";
10
+ export * from "./os/detector-helper.js";
@@ -0,0 +1,29 @@
1
+ import { DetectableTool, Platform } from "./tool-registry.js";
2
+ /**
3
+ * Result of locating a tool on the current system.
4
+ */
5
+ export interface DetectedTool {
6
+ id: string;
7
+ name: string;
8
+ /** absolute path to the executable/launcher that was found */
9
+ executablePath: string;
10
+ }
11
+ /**
12
+ * Resolves a launcher command on PATH, returning its absolute path or null.
13
+ * Uses `where` on Windows and `which` elsewhere.
14
+ */
15
+ export declare function resolveOnPath(command: string, platform: Platform): string | null;
16
+ /**
17
+ * Returns the first candidate path that exists on disk, after expanding
18
+ * `~`/`%VAR%` tokens, or null when none exist.
19
+ */
20
+ export declare function findExistingCandidatePath(candidates: string[], home: string, env?: NodeJS.ProcessEnv): string | null;
21
+ /**
22
+ * Detects a single tool: first via its known candidate paths (preferred, as it
23
+ * yields an absolute executable), then falling back to a PATH lookup.
24
+ */
25
+ export declare function detectTool(tool: DetectableTool, platform: Platform, home: string, env?: NodeJS.ProcessEnv): DetectedTool | null;
26
+ /**
27
+ * Detects every tool in the list, dropping the ones that are not installed.
28
+ */
29
+ export declare function detectTools(tools: DetectableTool[], platform: Platform, home: string, env?: NodeJS.ProcessEnv): DetectedTool[];
@@ -0,0 +1,65 @@
1
+ import { execFileSync } from "node:child_process";
2
+ import { existsSync } from "node:fs";
3
+ import { expandCandidatePath, } from "./tool-registry.js";
4
+ /**
5
+ * Resolves a launcher command on PATH, returning its absolute path or null.
6
+ * Uses `where` on Windows and `which` elsewhere.
7
+ */
8
+ export function resolveOnPath(command, platform) {
9
+ const finder = platform === "win32" ? "where" : "which";
10
+ try {
11
+ const output = execFileSync(finder, [command], {
12
+ stdio: ["ignore", "pipe", "ignore"],
13
+ })
14
+ .toString()
15
+ .trim();
16
+ // `where` may return multiple lines; take the first hit
17
+ const first = output.split(/\r?\n/).find((line) => line.trim().length > 0);
18
+ if (first && existsSync(first.trim())) {
19
+ return first.trim();
20
+ }
21
+ }
22
+ catch {
23
+ // not found on PATH
24
+ }
25
+ return null;
26
+ }
27
+ /**
28
+ * Returns the first candidate path that exists on disk, after expanding
29
+ * `~`/`%VAR%` tokens, or null when none exist.
30
+ */
31
+ export function findExistingCandidatePath(candidates, home, env = process.env) {
32
+ for (const candidate of candidates) {
33
+ const expanded = expandCandidatePath(candidate, home, env);
34
+ if (existsSync(expanded)) {
35
+ return expanded;
36
+ }
37
+ }
38
+ return null;
39
+ }
40
+ /**
41
+ * Detects a single tool: first via its known candidate paths (preferred, as it
42
+ * yields an absolute executable), then falling back to a PATH lookup.
43
+ */
44
+ export function detectTool(tool, platform, home, env = process.env) {
45
+ const candidatePaths = tool.paths[platform] ?? [];
46
+ const fromPath = findExistingCandidatePath(candidatePaths, home, env);
47
+ if (fromPath) {
48
+ return { id: tool.id, name: tool.name, executablePath: fromPath };
49
+ }
50
+ for (const command of tool.commands) {
51
+ const resolved = resolveOnPath(command, platform);
52
+ if (resolved) {
53
+ return { id: tool.id, name: tool.name, executablePath: resolved };
54
+ }
55
+ }
56
+ return null;
57
+ }
58
+ /**
59
+ * Detects every tool in the list, dropping the ones that are not installed.
60
+ */
61
+ export function detectTools(tools, platform, home, env = process.env) {
62
+ return tools
63
+ .map((tool) => detectTool(tool, platform, home, env))
64
+ .filter((result) => result !== null);
65
+ }
@@ -0,0 +1,38 @@
1
+ /**
2
+ * OS-specific registry of the browsers and diff/editor tools the first-run
3
+ * wizard knows how to detect. Detection strategies differ per platform, so the
4
+ * candidate executable paths and PATH launcher names are grouped by platform.
5
+ *
6
+ * This module holds only data + pure helpers; the actual filesystem probing
7
+ * lives in the browser/diff-tool detectors.
8
+ */
9
+ export type Platform = "darwin" | "win32" | "linux";
10
+ export interface DetectableTool {
11
+ /** stable identifier persisted to config, e.g. "chrome", "code" */
12
+ id: string;
13
+ /** human-readable name shown in prompts */
14
+ name: string;
15
+ /** launcher names to resolve on PATH (`which`/`where`) */
16
+ commands: string[];
17
+ /** absolute candidate paths per platform (support `~` and `%VAR%` tokens) */
18
+ paths: Partial<Record<Platform, string[]>>;
19
+ }
20
+ export interface DetectableEditor extends DetectableTool {
21
+ /**
22
+ * diff-service template for this tool, using the `$exec`/`$file1`/`$file2`
23
+ * placeholders understood by DiffService.
24
+ */
25
+ diffExecTemplate: string;
26
+ }
27
+ export declare const BROWSERS: DetectableTool[];
28
+ export declare const EDITORS: DetectableEditor[];
29
+ /**
30
+ * Normalizes an unknown platform string into one of the supported platforms.
31
+ * Falls back to "linux" for the various *nix variants Node may report.
32
+ */
33
+ export declare function normalizePlatform(platform: string): Platform;
34
+ /**
35
+ * Expands `~` (home) and Windows `%VAR%` tokens in a candidate path. Unknown
36
+ * `%VAR%` tokens are left untouched so a later existence check simply misses.
37
+ */
38
+ export declare function expandCandidatePath(raw: string, home: string, env?: NodeJS.ProcessEnv): string;
@@ -0,0 +1,194 @@
1
+ /**
2
+ * OS-specific registry of the browsers and diff/editor tools the first-run
3
+ * wizard knows how to detect. Detection strategies differ per platform, so the
4
+ * candidate executable paths and PATH launcher names are grouped by platform.
5
+ *
6
+ * This module holds only data + pure helpers; the actual filesystem probing
7
+ * lives in the browser/diff-tool detectors.
8
+ */
9
+ export const BROWSERS = [
10
+ {
11
+ id: "chrome",
12
+ name: "Google Chrome",
13
+ commands: ["google-chrome", "google-chrome-stable", "chrome"],
14
+ paths: {
15
+ darwin: ["/Applications/Google Chrome.app/Contents/MacOS/Google Chrome"],
16
+ win32: [
17
+ "%ProgramFiles%\\Google\\Chrome\\Application\\chrome.exe",
18
+ "%ProgramFiles(x86)%\\Google\\Chrome\\Application\\chrome.exe",
19
+ "%LOCALAPPDATA%\\Google\\Chrome\\Application\\chrome.exe",
20
+ ],
21
+ linux: [
22
+ "/usr/bin/google-chrome",
23
+ "/usr/bin/google-chrome-stable",
24
+ "/opt/google/chrome/chrome",
25
+ ],
26
+ },
27
+ },
28
+ {
29
+ id: "chromium",
30
+ name: "Chromium",
31
+ commands: ["chromium", "chromium-browser"],
32
+ paths: {
33
+ darwin: ["/Applications/Chromium.app/Contents/MacOS/Chromium"],
34
+ win32: ["%ProgramFiles%\\Chromium\\Application\\chrome.exe"],
35
+ linux: [
36
+ "/usr/bin/chromium",
37
+ "/usr/bin/chromium-browser",
38
+ "/snap/bin/chromium",
39
+ ],
40
+ },
41
+ },
42
+ {
43
+ id: "edge",
44
+ name: "Microsoft Edge",
45
+ commands: ["microsoft-edge", "microsoft-edge-stable", "msedge"],
46
+ paths: {
47
+ darwin: [
48
+ "/Applications/Microsoft Edge.app/Contents/MacOS/Microsoft Edge",
49
+ ],
50
+ win32: [
51
+ "%ProgramFiles(x86)%\\Microsoft\\Edge\\Application\\msedge.exe",
52
+ "%ProgramFiles%\\Microsoft\\Edge\\Application\\msedge.exe",
53
+ ],
54
+ linux: [
55
+ "/usr/bin/microsoft-edge",
56
+ "/usr/bin/microsoft-edge-stable",
57
+ "/opt/microsoft/msedge/msedge",
58
+ ],
59
+ },
60
+ },
61
+ {
62
+ id: "brave",
63
+ name: "Brave",
64
+ commands: ["brave-browser", "brave"],
65
+ paths: {
66
+ darwin: ["/Applications/Brave Browser.app/Contents/MacOS/Brave Browser"],
67
+ win32: [
68
+ "%ProgramFiles%\\BraveSoftware\\Brave-Browser\\Application\\brave.exe",
69
+ "%ProgramFiles(x86)%\\BraveSoftware\\Brave-Browser\\Application\\brave.exe",
70
+ ],
71
+ linux: [
72
+ "/usr/bin/brave-browser",
73
+ "/usr/bin/brave",
74
+ "/opt/brave.com/brave/brave",
75
+ ],
76
+ },
77
+ },
78
+ ];
79
+ export const EDITORS = [
80
+ {
81
+ id: "idea",
82
+ name: "IntelliJ IDEA",
83
+ commands: ["idea"],
84
+ diffExecTemplate: '"$exec" diff "$file1" "$file2"',
85
+ paths: {
86
+ darwin: [
87
+ "/Applications/IntelliJ IDEA.app/Contents/MacOS/idea",
88
+ "/usr/local/bin/idea",
89
+ ],
90
+ win32: ["%LOCALAPPDATA%\\JetBrains\\Toolbox\\scripts\\idea.cmd"],
91
+ linux: ["/usr/local/bin/idea", "/opt/idea/bin/idea.sh"],
92
+ },
93
+ },
94
+ {
95
+ id: "webstorm",
96
+ name: "WebStorm",
97
+ commands: ["webstorm"],
98
+ diffExecTemplate: '"$exec" diff "$file1" "$file2"',
99
+ paths: {
100
+ darwin: [
101
+ "/Applications/WebStorm.app/Contents/MacOS/webstorm",
102
+ "/usr/local/bin/webstorm",
103
+ ],
104
+ win32: ["%LOCALAPPDATA%\\JetBrains\\Toolbox\\scripts\\webstorm.cmd"],
105
+ linux: ["/usr/local/bin/webstorm", "/opt/webstorm/bin/webstorm.sh"],
106
+ },
107
+ },
108
+ {
109
+ id: "pycharm",
110
+ name: "PyCharm",
111
+ commands: ["pycharm", "charm"],
112
+ diffExecTemplate: '"$exec" diff "$file1" "$file2"',
113
+ paths: {
114
+ darwin: [
115
+ "/Applications/PyCharm.app/Contents/MacOS/pycharm",
116
+ "/usr/local/bin/charm",
117
+ ],
118
+ win32: ["%LOCALAPPDATA%\\JetBrains\\Toolbox\\scripts\\pycharm.cmd"],
119
+ linux: ["/usr/local/bin/charm", "/opt/pycharm/bin/pycharm.sh"],
120
+ },
121
+ },
122
+ {
123
+ id: "code",
124
+ name: "Visual Studio Code",
125
+ commands: ["code"],
126
+ diffExecTemplate: '"$exec" --diff "$file1" "$file2"',
127
+ paths: {
128
+ darwin: [
129
+ "/Applications/Visual Studio Code.app/Contents/Resources/app/bin/code",
130
+ "/usr/local/bin/code",
131
+ ],
132
+ win32: [
133
+ "%LOCALAPPDATA%\\Programs\\Microsoft VS Code\\bin\\code.cmd",
134
+ "%ProgramFiles%\\Microsoft VS Code\\bin\\code.cmd",
135
+ ],
136
+ linux: ["/usr/bin/code", "/usr/share/code/bin/code", "/snap/bin/code"],
137
+ },
138
+ },
139
+ {
140
+ id: "codium",
141
+ name: "VSCodium",
142
+ commands: ["codium"],
143
+ diffExecTemplate: '"$exec" --diff "$file1" "$file2"',
144
+ paths: {
145
+ darwin: [
146
+ "/Applications/VSCodium.app/Contents/Resources/app/bin/codium",
147
+ "/usr/local/bin/codium",
148
+ ],
149
+ win32: ["%LOCALAPPDATA%\\Programs\\VSCodium\\bin\\codium.cmd"],
150
+ linux: ["/usr/bin/codium", "/snap/bin/codium"],
151
+ },
152
+ },
153
+ {
154
+ id: "cursor",
155
+ name: "Cursor",
156
+ commands: ["cursor"],
157
+ diffExecTemplate: '"$exec" --diff "$file1" "$file2"',
158
+ paths: {
159
+ darwin: [
160
+ "/Applications/Cursor.app/Contents/Resources/app/bin/cursor",
161
+ "/usr/local/bin/cursor",
162
+ ],
163
+ win32: [
164
+ "%LOCALAPPDATA%\\Programs\\cursor\\resources\\app\\bin\\cursor.cmd",
165
+ ],
166
+ linux: ["/usr/bin/cursor", "/opt/cursor/bin/cursor"],
167
+ },
168
+ },
169
+ ];
170
+ /**
171
+ * Normalizes an unknown platform string into one of the supported platforms.
172
+ * Falls back to "linux" for the various *nix variants Node may report.
173
+ */
174
+ export function normalizePlatform(platform) {
175
+ if (platform === "darwin" || platform === "win32") {
176
+ return platform;
177
+ }
178
+ return "linux";
179
+ }
180
+ /**
181
+ * Expands `~` (home) and Windows `%VAR%` tokens in a candidate path. Unknown
182
+ * `%VAR%` tokens are left untouched so a later existence check simply misses.
183
+ */
184
+ export function expandCandidatePath(raw, home, env = process.env) {
185
+ let expanded = raw;
186
+ if (expanded.startsWith("~")) {
187
+ expanded = home + expanded.slice(1);
188
+ }
189
+ expanded = expanded.replaceAll(/%([^%]+)%/g, (match, name) => {
190
+ const value = env[name];
191
+ return value === undefined ? match : value;
192
+ });
193
+ return expanded;
194
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,26 @@
1
+ import { expect } from "chai";
2
+ import { describe, it } from "mocha";
3
+ import { expandCandidatePath, normalizePlatform } from "./tool-registry.js";
4
+ describe("tool-registry.normalizePlatform", () => {
5
+ it("passes through supported platforms", () => {
6
+ expect(normalizePlatform("darwin")).to.equal("darwin");
7
+ expect(normalizePlatform("win32")).to.equal("win32");
8
+ expect(normalizePlatform("linux")).to.equal("linux");
9
+ });
10
+ it("falls back to linux for other *nix variants", () => {
11
+ expect(normalizePlatform("freebsd")).to.equal("linux");
12
+ expect(normalizePlatform("openbsd")).to.equal("linux");
13
+ });
14
+ });
15
+ describe("tool-registry.expandCandidatePath", () => {
16
+ it("expands a leading ~ to the home directory", () => {
17
+ expect(expandCandidatePath("~/bin/idea", "/home/tester")).to.equal("/home/tester/bin/idea");
18
+ });
19
+ it("expands known %VAR% tokens from env", () => {
20
+ const env = { LOCALAPPDATA: "C:\\Users\\t\\AppData\\Local" };
21
+ expect(expandCandidatePath("%LOCALAPPDATA%\\Programs\\code.cmd", "C:\\Users\\t", env)).to.equal("C:\\Users\\t\\AppData\\Local\\Programs\\code.cmd");
22
+ });
23
+ it("leaves unknown %VAR% tokens untouched", () => {
24
+ expect(expandCandidatePath("%NOPE%\\x.exe", "/home", {})).to.equal("%NOPE%\\x.exe");
25
+ });
26
+ });
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Inputs for the first-run wizard. No logic.
3
+ */
4
+ export declare class SetupContext {
5
+ /** true when invoked from the npm postinstall hook */
6
+ readonly postInstall: boolean;
7
+ /** re-run even if setup was already completed */
8
+ readonly force: boolean;
9
+ constructor(
10
+ /** true when invoked from the npm postinstall hook */
11
+ postInstall?: boolean,
12
+ /** re-run even if setup was already completed */
13
+ force?: boolean);
14
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Inputs for the first-run wizard. No logic.
3
+ */
4
+ export class SetupContext {
5
+ postInstall;
6
+ force;
7
+ constructor(
8
+ /** true when invoked from the npm postinstall hook */
9
+ postInstall = false,
10
+ /** re-run even if setup was already completed */
11
+ force = false) {
12
+ this.postInstall = postInstall;
13
+ this.force = force;
14
+ }
15
+ }
@@ -0,0 +1,10 @@
1
+ import { Config } from "@oclif/core";
2
+ import { SetupContext } from "./setup-context.js";
3
+ import { SetupService } from "./setup-service.js";
4
+ export declare class SetupServiceFactory {
5
+ private readonly oclifConfig;
6
+ private readonly context;
7
+ private service?;
8
+ constructor(oclifConfig: Config, context?: SetupContext);
9
+ getService(): SetupService;
10
+ }
@@ -0,0 +1,37 @@
1
+ import { CliServiceFactory } from "../cli/index.js";
2
+ import { CliConfig } from "../../helpers/cli-config.js";
3
+ import { normalizePlatform } from "./os/tool-registry.js";
4
+ import { BrowserDetector } from "./browser/browser-detector.js";
5
+ import { BrowserManager } from "./browser/browser-manager.js";
6
+ import { BrowserSetupService } from "./browser/browser-setup-service.js";
7
+ import { DiffToolDetector } from "./difftool/difftool-detector.js";
8
+ import { DiffToolSetupService } from "./difftool/difftool-setup-service.js";
9
+ import { SetupContext } from "./setup-context.js";
10
+ import { SetupService } from "./setup-service.js";
11
+ export class SetupServiceFactory {
12
+ oclifConfig;
13
+ context;
14
+ service;
15
+ constructor(oclifConfig, context = new SetupContext()) {
16
+ this.oclifConfig = oclifConfig;
17
+ this.context = context;
18
+ }
19
+ getService() {
20
+ if (this.service instanceof SetupService) {
21
+ return this.service;
22
+ }
23
+ const cli = new CliServiceFactory().getService();
24
+ const cliConfig = new CliConfig(this.oclifConfig);
25
+ const userConfig = cliConfig.load();
26
+ const platform = normalizePlatform(this.oclifConfig.platform);
27
+ const home = this.oclifConfig.home;
28
+ const cacheDir = userConfig.tempFolder;
29
+ const browserDetector = new BrowserDetector(platform, home, cacheDir);
30
+ const browserManager = new BrowserManager(cacheDir, cli);
31
+ const browserSetup = new BrowserSetupService(cli, cliConfig, userConfig, browserDetector, browserManager);
32
+ const diffDetector = new DiffToolDetector(platform, home);
33
+ const diffSetup = new DiffToolSetupService(cli, cliConfig, userConfig, diffDetector);
34
+ this.service = new SetupService(cli, cliConfig, userConfig, browserSetup, diffSetup, this.context);
35
+ return this.service;
36
+ }
37
+ }
@@ -0,0 +1,20 @@
1
+ import { CliServiceInterface } from "../cli/index.js";
2
+ import { CliConfig, UserCliConfig } from "../../helpers/cli-config.js";
3
+ import { BrowserSetupService } from "./browser/browser-setup-service.js";
4
+ import { DiffToolSetupService } from "./difftool/difftool-setup-service.js";
5
+ import { SetupContext } from "./setup-context.js";
6
+ export declare class SetupService {
7
+ private readonly cli;
8
+ private readonly cliConfig;
9
+ private readonly userConfig;
10
+ private readonly browserSetup;
11
+ private readonly diffSetup;
12
+ private readonly context;
13
+ constructor(cli: CliServiceInterface, cliConfig: CliConfig, userConfig: UserCliConfig, browserSetup: BrowserSetupService, diffSetup: DiffToolSetupService, context: SetupContext);
14
+ /** Runs the full first-run wizard (browser + diff tool) and marks it done. */
15
+ run(): Promise<void>;
16
+ /** True when the first-run wizard has already been completed once. */
17
+ isFirstRunCompleted(): boolean;
18
+ /** Update-reminder check for the browser, used by the init hook. */
19
+ remindBrowserUpdate(): Promise<void>;
20
+ }
@@ -0,0 +1,37 @@
1
+ export class SetupService {
2
+ cli;
3
+ cliConfig;
4
+ userConfig;
5
+ browserSetup;
6
+ diffSetup;
7
+ context;
8
+ constructor(cli, cliConfig, userConfig, browserSetup, diffSetup, context) {
9
+ this.cli = cli;
10
+ this.cliConfig = cliConfig;
11
+ this.userConfig = userConfig;
12
+ this.browserSetup = browserSetup;
13
+ this.diffSetup = diffSetup;
14
+ this.context = context;
15
+ }
16
+ /** Runs the full first-run wizard (browser + diff tool) and marks it done. */
17
+ async run() {
18
+ this.cli.spacer();
19
+ this.cli.write(this.cli.style.bold("Speed Kit CLI — setup"));
20
+ this.cli.comment("Configure the browser and diff tool used for onboarding and deploys.");
21
+ this.cli.spacer();
22
+ await this.browserSetup.run();
23
+ this.cli.spacer();
24
+ await this.diffSetup.run();
25
+ this.cliConfig.save({ firstRunCompleted: true });
26
+ this.cli.spacer();
27
+ this.cli.writeSuccess("Setup complete. Re-run any time with `sk config setup`.");
28
+ }
29
+ /** True when the first-run wizard has already been completed once. */
30
+ isFirstRunCompleted() {
31
+ return Boolean(this.userConfig.firstRunCompleted) && !this.context.force;
32
+ }
33
+ /** Update-reminder check for the browser, used by the init hook. */
34
+ async remindBrowserUpdate() {
35
+ await this.browserSetup.remindIfDue();
36
+ }
37
+ }
@@ -855,6 +855,87 @@
855
855
  "fish.js"
856
856
  ]
857
857
  },
858
+ "browser:clean": {
859
+ "aliases": [],
860
+ "args": {},
861
+ "description": "Remove puppeteer-managed browser builds from the cache",
862
+ "examples": [
863
+ "$ sk browser clean",
864
+ "$ sk browser clean --all"
865
+ ],
866
+ "flags": {
867
+ "all": {
868
+ "char": "a",
869
+ "description": "Remove all cached browser builds without prompting",
870
+ "name": "all",
871
+ "allowNo": false,
872
+ "type": "boolean"
873
+ }
874
+ },
875
+ "hasDynamicHelp": false,
876
+ "hiddenAliases": [],
877
+ "id": "browser:clean",
878
+ "pluginAlias": "@speedkit/cli",
879
+ "pluginName": "@speedkit/cli",
880
+ "pluginType": "core",
881
+ "strict": true,
882
+ "enableJsonFlag": false,
883
+ "isESM": true,
884
+ "relativePath": [
885
+ "dist",
886
+ "commands",
887
+ "browser",
888
+ "clean.js"
889
+ ]
890
+ },
891
+ "browser:list": {
892
+ "aliases": [],
893
+ "args": {},
894
+ "description": "List detected system browsers and puppeteer-managed builds",
895
+ "examples": [
896
+ "$ sk browser list"
897
+ ],
898
+ "flags": {},
899
+ "hasDynamicHelp": false,
900
+ "hiddenAliases": [],
901
+ "id": "browser:list",
902
+ "pluginAlias": "@speedkit/cli",
903
+ "pluginName": "@speedkit/cli",
904
+ "pluginType": "core",
905
+ "strict": true,
906
+ "enableJsonFlag": false,
907
+ "isESM": true,
908
+ "relativePath": [
909
+ "dist",
910
+ "commands",
911
+ "browser",
912
+ "list.js"
913
+ ]
914
+ },
915
+ "browser:update": {
916
+ "aliases": [],
917
+ "args": {},
918
+ "description": "Update the puppeteer-managed browser to the latest build of its channel",
919
+ "examples": [
920
+ "$ sk browser update"
921
+ ],
922
+ "flags": {},
923
+ "hasDynamicHelp": false,
924
+ "hiddenAliases": [],
925
+ "id": "browser:update",
926
+ "pluginAlias": "@speedkit/cli",
927
+ "pluginName": "@speedkit/cli",
928
+ "pluginType": "core",
929
+ "strict": true,
930
+ "enableJsonFlag": false,
931
+ "isESM": true,
932
+ "relativePath": [
933
+ "dist",
934
+ "commands",
935
+ "browser",
936
+ "update.js"
937
+ ]
938
+ },
858
939
  "config:edit": {
859
940
  "aliases": [],
860
941
  "args": {},
@@ -878,7 +959,47 @@
878
959
  "config",
879
960
  "edit.js"
880
961
  ]
962
+ },
963
+ "config:setup": {
964
+ "aliases": [],
965
+ "args": {},
966
+ "description": "Run the Speed Kit CLI setup wizard (choose browser and diff tool)",
967
+ "examples": [
968
+ "$ sk config setup",
969
+ "$ sk config setup --force"
970
+ ],
971
+ "flags": {
972
+ "force": {
973
+ "char": "f",
974
+ "description": "Re-run even if setup was already completed",
975
+ "name": "force",
976
+ "allowNo": false,
977
+ "type": "boolean"
978
+ },
979
+ "postInstall": {
980
+ "description": "Internal flag used by the npm postinstall hook",
981
+ "hidden": true,
982
+ "name": "postInstall",
983
+ "allowNo": false,
984
+ "type": "boolean"
985
+ }
986
+ },
987
+ "hasDynamicHelp": false,
988
+ "hiddenAliases": [],
989
+ "id": "config:setup",
990
+ "pluginAlias": "@speedkit/cli",
991
+ "pluginName": "@speedkit/cli",
992
+ "pluginType": "core",
993
+ "strict": true,
994
+ "enableJsonFlag": false,
995
+ "isESM": true,
996
+ "relativePath": [
997
+ "dist",
998
+ "commands",
999
+ "config",
1000
+ "setup.js"
1001
+ ]
881
1002
  }
882
1003
  },
883
- "version": "4.17.0"
1004
+ "version": "4.18.0"
884
1005
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@speedkit/cli",
3
3
  "description": "Speed Kit CLI",
4
- "version": "4.17.0",
4
+ "version": "4.18.0",
5
5
  "author": {
6
6
  "name": "Baqend.com",
7
7
  "email": "info@baqend.com"