launch-ih 1.0.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 (68) hide show
  1. package/README.md +117 -0
  2. package/dist/browser.d.ts +20 -0
  3. package/dist/browser.js +86 -0
  4. package/dist/browser.js.map +1 -0
  5. package/dist/cli/commands/draft.command.d.ts +10 -0
  6. package/dist/cli/commands/draft.command.js +32 -0
  7. package/dist/cli/commands/draft.command.js.map +1 -0
  8. package/dist/cli/commands/history.command.d.ts +9 -0
  9. package/dist/cli/commands/history.command.js +30 -0
  10. package/dist/cli/commands/history.command.js.map +1 -0
  11. package/dist/cli/commands/login.command.d.ts +10 -0
  12. package/dist/cli/commands/login.command.js +64 -0
  13. package/dist/cli/commands/login.command.js.map +1 -0
  14. package/dist/cli/commands/new.command.d.ts +17 -0
  15. package/dist/cli/commands/new.command.js +151 -0
  16. package/dist/cli/commands/new.command.js.map +1 -0
  17. package/dist/cli/commands/preview.command.d.ts +13 -0
  18. package/dist/cli/commands/preview.command.js +48 -0
  19. package/dist/cli/commands/preview.command.js.map +1 -0
  20. package/dist/cli/commands/publish.command.d.ts +12 -0
  21. package/dist/cli/commands/publish.command.js +70 -0
  22. package/dist/cli/commands/publish.command.js.map +1 -0
  23. package/dist/cli/commands/status.command.d.ts +9 -0
  24. package/dist/cli/commands/status.command.js +47 -0
  25. package/dist/cli/commands/status.command.js.map +1 -0
  26. package/dist/cli/index.d.ts +2 -0
  27. package/dist/cli/index.js +168 -0
  28. package/dist/cli/index.js.map +1 -0
  29. package/dist/cli/ui/editor.d.ts +1 -0
  30. package/dist/cli/ui/editor.js +39 -0
  31. package/dist/cli/ui/editor.js.map +1 -0
  32. package/dist/cli/ui/output.d.ts +23 -0
  33. package/dist/cli/ui/output.js +96 -0
  34. package/dist/cli/ui/output.js.map +1 -0
  35. package/dist/cli/ui/prompts.d.ts +11 -0
  36. package/dist/cli/ui/prompts.js +28 -0
  37. package/dist/cli/ui/prompts.js.map +1 -0
  38. package/dist/cli/utils/errors.d.ts +20 -0
  39. package/dist/cli/utils/errors.js +48 -0
  40. package/dist/cli/utils/errors.js.map +1 -0
  41. package/dist/cli/utils/session-helpers.d.ts +4 -0
  42. package/dist/cli/utils/session-helpers.js +37 -0
  43. package/dist/cli/utils/session-helpers.js.map +1 -0
  44. package/dist/cli.d.ts +2 -0
  45. package/dist/cli.js +6 -0
  46. package/dist/cli.js.map +1 -0
  47. package/dist/env.d.ts +10 -0
  48. package/dist/env.js +27 -0
  49. package/dist/env.js.map +1 -0
  50. package/dist/ih-auth.d.ts +32 -0
  51. package/dist/ih-auth.js +240 -0
  52. package/dist/ih-auth.js.map +1 -0
  53. package/dist/ih-poster.d.ts +21 -0
  54. package/dist/ih-poster.js +217 -0
  55. package/dist/ih-poster.js.map +1 -0
  56. package/dist/launch-workflow.d.ts +17 -0
  57. package/dist/launch-workflow.js +80 -0
  58. package/dist/launch-workflow.js.map +1 -0
  59. package/dist/post-drafter.d.ts +6 -0
  60. package/dist/post-drafter.js +103 -0
  61. package/dist/post-drafter.js.map +1 -0
  62. package/dist/types.d.ts +55 -0
  63. package/dist/types.js +5 -0
  64. package/dist/types.js.map +1 -0
  65. package/dist/utils.d.ts +21 -0
  66. package/dist/utils.js +54 -0
  67. package/dist/utils.js.map +1 -0
  68. package/package.json +52 -0
@@ -0,0 +1,12 @@
1
+ import { CliResponse } from '../../types.js';
2
+ export interface PublishOptions {
3
+ json?: boolean;
4
+ yes?: boolean;
5
+ session?: string;
6
+ headful?: boolean;
7
+ }
8
+ export declare function handlePublish(opts: PublishOptions): Promise<CliResponse<{
9
+ sessionId: string;
10
+ postUrl: string | null;
11
+ screenshotPath?: string;
12
+ }>>;
@@ -0,0 +1,70 @@
1
+ import { loadConfig } from '../../env.js';
2
+ import { launchStealthBrowser } from '../../browser.js';
3
+ import { loadCookies } from '../../ih-auth.js';
4
+ import { postToIH } from '../../ih-poster.js';
5
+ import { updateSession } from '../../launch-workflow.js';
6
+ import { promptConfirm } from '../ui/prompts.js';
7
+ import { resolveSession, assertState, assertHasDraft } from '../utils/session-helpers.js';
8
+ export async function handlePublish(opts) {
9
+ const session = resolveSession(opts.session);
10
+ assertState(session, 'awaiting_approval');
11
+ const draft = assertHasDraft(session);
12
+ const config = loadConfig();
13
+ // Confirmation prompt (skip with --yes)
14
+ if (!opts.yes) {
15
+ const confirmed = await promptConfirm(`Publish "${draft.title}" to Indie Hackers? This cannot be undone.`, false);
16
+ if (!confirmed) {
17
+ return { success: false, data: null, error: 'Publish cancelled by user' };
18
+ }
19
+ }
20
+ updateSession(session, { status: 'posting' });
21
+ try {
22
+ const { browser, context } = await launchStealthBrowser(!opts.headful, config.browserSlowMo);
23
+ try {
24
+ await loadCookies(context, config.cookiePath);
25
+ const result = await postToIH(context, draft, config);
26
+ if (result.success) {
27
+ updateSession(session, { status: 'done', postResult: result });
28
+ }
29
+ else {
30
+ updateSession(session, { status: 'failed', postResult: result });
31
+ }
32
+ if (!result.success) {
33
+ return {
34
+ success: false,
35
+ data: null,
36
+ error: result.error || 'Publishing failed',
37
+ };
38
+ }
39
+ return {
40
+ success: true,
41
+ data: {
42
+ sessionId: session.sessionId,
43
+ postUrl: result.postUrl,
44
+ screenshotPath: result.screenshotPath,
45
+ },
46
+ error: null,
47
+ };
48
+ }
49
+ finally {
50
+ await browser.close().catch(() => { });
51
+ }
52
+ }
53
+ catch (err) {
54
+ const failedResult = {
55
+ success: false,
56
+ postUrl: null,
57
+ title: draft.title,
58
+ timestamp: new Date().toISOString(),
59
+ error: err instanceof Error ? err.message : String(err),
60
+ dryRun: false,
61
+ };
62
+ updateSession(session, { status: 'failed', postResult: failedResult });
63
+ return {
64
+ success: false,
65
+ data: null,
66
+ error: `Publishing failed: ${err instanceof Error ? err.message : String(err)}`,
67
+ };
68
+ }
69
+ }
70
+ //# sourceMappingURL=publish.command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"publish.command.js","sourceRoot":"","sources":["../../../src/cli/commands/publish.command.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import { CliResponse, LaunchSession } from '../../types.js';
2
+ export interface StatusOptions {
3
+ json?: boolean;
4
+ session?: string;
5
+ }
6
+ export declare function handleStatus(opts: StatusOptions): Promise<CliResponse<{
7
+ session: LaunchSession | null;
8
+ nextStep: string | null;
9
+ }>>;
@@ -0,0 +1,47 @@
1
+ // ============================================================
2
+ // LAUNCH — ih status Command (non-browser CLI)
3
+ // ============================================================
4
+ // Displays the current session status and the recommended
5
+ // next action.
6
+ // ============================================================
7
+ import { resolveSession } from '../utils/session-helpers.js';
8
+ import { SessionNotFoundError } from '../utils/errors.js';
9
+ const NEXT_STEP_MAP = {
10
+ drafting: "Run 'launch draft' to generate a post draft",
11
+ awaiting_approval: "Run 'launch preview' or 'launch publish'",
12
+ posting: "Post in progress. Run 'launch status' again.",
13
+ done: "Launch complete! Run 'launch history' to view all launches.",
14
+ failed: "Launch failed. Run 'launch draft' to retry.",
15
+ };
16
+ export async function handleStatus(opts) {
17
+ try {
18
+ let session;
19
+ try {
20
+ session = resolveSession(opts.session);
21
+ }
22
+ catch (err) {
23
+ if (err instanceof SessionNotFoundError) {
24
+ return {
25
+ success: true,
26
+ data: {
27
+ session: null,
28
+ nextStep: "Run 'launch new' to start",
29
+ },
30
+ error: null,
31
+ };
32
+ }
33
+ throw err;
34
+ }
35
+ const nextStep = NEXT_STEP_MAP[session.status] || null;
36
+ return {
37
+ success: true,
38
+ data: { session, nextStep },
39
+ error: null,
40
+ };
41
+ }
42
+ catch (err) {
43
+ const message = err instanceof Error ? err.message : String(err);
44
+ return { success: false, data: null, error: message };
45
+ }
46
+ }
47
+ //# sourceMappingURL=status.command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.command.js","sourceRoot":"","sources":["../../../src/cli/commands/status.command.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,+CAA+C;AAC/C,+DAA+D;AAC/D,0DAA0D;AAC1D,eAAe;AACf,+DAA+D;AAG/D,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAC;AAO1D,MAAM,aAAa,GAA4C;IAC7D,QAAQ,EAAE,6CAA6C;IACvD,iBAAiB,EAAE,0CAA0C;IAC7D,OAAO,EAAE,8CAA8C;IACvD,IAAI,EAAE,6DAA6D;IACnE,MAAM,EAAE,6CAA6C;CACtD,CAAC;AAEF,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,IAAmB;IAEnB,IAAI,CAAC;QACH,IAAI,OAAsB,CAAC;QAE3B,IAAI,CAAC;YACH,OAAO,GAAG,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACzC,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,oBAAoB,EAAE,CAAC;gBACxC,OAAO;oBACL,OAAO,EAAE,IAAI;oBACb,IAAI,EAAE;wBACJ,OAAO,EAAE,IAAI;wBACb,QAAQ,EAAE,2BAA2B;qBACtC;oBACD,KAAK,EAAE,IAAI;iBACZ,CAAC;YACJ,CAAC;YACD,MAAM,GAAG,CAAC;QACZ,CAAC;QAED,MAAM,QAAQ,GAAG,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC;QAEvD,OAAO;YACL,OAAO,EAAE,IAAI;YACb,IAAI,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE;YAC3B,KAAK,EAAE,IAAI;SACZ,CAAC;IACJ,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;IACxD,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -0,0 +1,168 @@
1
+ #!/usr/bin/env node
2
+ // ============================================================
3
+ // LAUNCH CLI — Commander entry point
4
+ // ============================================================
5
+ import { Command } from 'commander';
6
+ import { Output } from './ui/output.js';
7
+ import { handleLogin } from './commands/login.command.js';
8
+ import { handleNew } from './commands/new.command.js';
9
+ import { handleDraft } from './commands/draft.command.js';
10
+ import { handlePreview } from './commands/preview.command.js';
11
+ import { handlePublish } from './commands/publish.command.js';
12
+ import { handleHistory } from './commands/history.command.js';
13
+ import { handleStatus } from './commands/status.command.js';
14
+ const program = new Command();
15
+ program
16
+ .name('launch')
17
+ .description('Ship your product to Indie Hackers from the terminal')
18
+ .version('1.0.0')
19
+ .option('--json', 'output JSON instead of formatted terminal output');
20
+ // ── login ──────────────────────────────────────────────
21
+ program
22
+ .command('login')
23
+ .description('Log into Indie Hackers and save session')
24
+ .option('--yes', 'skip interactive prompts')
25
+ .action(async (opts) => {
26
+ const json = program.getOptionValue('json') ?? false;
27
+ const out = new Output(json);
28
+ try {
29
+ const res = await handleLogin({ ...opts, json });
30
+ out.result(res);
31
+ if (!res.success)
32
+ process.exit(1);
33
+ }
34
+ catch (err) {
35
+ out.result({ success: false, data: null, error: err instanceof Error ? err.message : String(err) });
36
+ process.exit(1);
37
+ }
38
+ });
39
+ // ── new ────────────────────────────────────────────────
40
+ program
41
+ .command('new')
42
+ .description('Create a new product launch session')
43
+ .option('--yes', 'skip confirmation prompts')
44
+ .option('--name <name>', 'product name')
45
+ .option('--tagline <tagline>', 'product tagline')
46
+ .option('--problem <problem>', 'problem it solves')
47
+ .option('--features <features>', 'comma-separated features')
48
+ .option('--link <url>', 'product URL')
49
+ .option('--audience <audience>', 'target audience')
50
+ .option('--stage <stage>', 'stage: pre-launch | just-launched | growing')
51
+ .option('--resume', 'resume existing drafting session')
52
+ .action(async (opts) => {
53
+ const json = program.getOptionValue('json') ?? false;
54
+ const out = new Output(json);
55
+ try {
56
+ const res = await handleNew({ ...opts, json });
57
+ out.result(res);
58
+ if (!res.success)
59
+ process.exit(1);
60
+ }
61
+ catch (err) {
62
+ out.result({ success: false, data: null, error: err instanceof Error ? err.message : String(err) });
63
+ process.exit(1);
64
+ }
65
+ });
66
+ // ── draft ──────────────────────────────────────────────
67
+ program
68
+ .command('draft')
69
+ .description('Generate or edit a post draft')
70
+ .option('--yes', 'skip editor prompt')
71
+ .option('--session <id>', 'session ID')
72
+ .action(async (opts) => {
73
+ const json = program.getOptionValue('json') ?? false;
74
+ const out = new Output(json);
75
+ try {
76
+ const res = await handleDraft({ ...opts, json });
77
+ out.result(res);
78
+ if (!res.success)
79
+ process.exit(1);
80
+ }
81
+ catch (err) {
82
+ out.result({ success: false, data: null, error: err instanceof Error ? err.message : String(err) });
83
+ process.exit(1);
84
+ }
85
+ });
86
+ // ── preview ────────────────────────────────────────────
87
+ program
88
+ .command('preview')
89
+ .description('Dry-run preview: fill IH form and screenshot')
90
+ .option('--yes', 'skip prompts')
91
+ .option('--session <id>', 'session ID')
92
+ .option('--headful', 'run browser in visible mode')
93
+ .action(async (opts) => {
94
+ const json = program.getOptionValue('json') ?? false;
95
+ const out = new Output(json);
96
+ try {
97
+ const res = await handlePreview({ ...opts, json });
98
+ out.result(res);
99
+ if (!res.success)
100
+ process.exit(1);
101
+ }
102
+ catch (err) {
103
+ out.result({ success: false, data: null, error: err instanceof Error ? err.message : String(err) });
104
+ process.exit(1);
105
+ }
106
+ });
107
+ // ── publish ────────────────────────────────────────────
108
+ program
109
+ .command('publish')
110
+ .description('Submit the approved draft to Indie Hackers')
111
+ .option('--yes', 'skip confirmation')
112
+ .option('--session <id>', 'session ID')
113
+ .option('--headful', 'run browser in visible mode')
114
+ .action(async (opts) => {
115
+ const json = program.getOptionValue('json') ?? false;
116
+ const out = new Output(json);
117
+ try {
118
+ const res = await handlePublish({ ...opts, json });
119
+ out.result(res);
120
+ if (!res.success)
121
+ process.exit(1);
122
+ }
123
+ catch (err) {
124
+ out.result({ success: false, data: null, error: err instanceof Error ? err.message : String(err) });
125
+ process.exit(1);
126
+ }
127
+ });
128
+ // ── history ────────────────────────────────────────────
129
+ program
130
+ .command('history')
131
+ .description('View past launch sessions')
132
+ .option('--limit <n>', 'max results (0 = all)', '10')
133
+ .action(async (opts) => {
134
+ const json = program.getOptionValue('json') ?? false;
135
+ const out = new Output(json);
136
+ try {
137
+ const res = await handleHistory({ ...opts, json, limit: parseInt(opts.limit, 10) });
138
+ out.result(res);
139
+ if (!res.success)
140
+ process.exit(1);
141
+ }
142
+ catch (err) {
143
+ out.result({ success: false, data: null, error: err instanceof Error ? err.message : String(err) });
144
+ process.exit(1);
145
+ }
146
+ });
147
+ // ── status ─────────────────────────────────────────────
148
+ program
149
+ .command('status')
150
+ .description('Show current session state and next steps')
151
+ .option('--session <id>', 'session ID')
152
+ .action(async (opts) => {
153
+ const json = program.getOptionValue('json') ?? false;
154
+ const out = new Output(json);
155
+ try {
156
+ const res = await handleStatus({ ...opts, json });
157
+ out.result(res);
158
+ if (!res.success)
159
+ process.exit(1);
160
+ }
161
+ catch (err) {
162
+ out.result({ success: false, data: null, error: err instanceof Error ? err.message : String(err) });
163
+ process.exit(1);
164
+ }
165
+ });
166
+ // ── Parse ──────────────────────────────────────────────
167
+ program.parse(process.argv);
168
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function editInEditor(initialContent: string): Promise<string | null>;
@@ -0,0 +1,39 @@
1
+ // ============================================================
2
+ // LAUNCH — External Editor Integration
3
+ // ============================================================
4
+ import { spawnSync } from 'child_process';
5
+ import { writeFileSync, readFileSync, unlinkSync } from 'fs';
6
+ import { tmpdir } from 'os';
7
+ import { join } from 'path';
8
+ import { randomUUID } from 'crypto';
9
+ export async function editInEditor(initialContent) {
10
+ const tmpPath = join(tmpdir(), `launch-draft-${randomUUID()}.md`);
11
+ try {
12
+ writeFileSync(tmpPath, initialContent, 'utf-8');
13
+ const editor = process.env.EDITOR || (process.platform === 'win32' ? 'notepad' : 'vim');
14
+ try {
15
+ const result = spawnSync(editor, [tmpPath], { stdio: 'inherit', timeout: 300000 });
16
+ if (result.error)
17
+ throw result.error;
18
+ if (result.status !== 0)
19
+ throw new Error(`Editor exited with code ${result.status}`);
20
+ }
21
+ catch {
22
+ return null;
23
+ }
24
+ const newContent = readFileSync(tmpPath, 'utf-8');
25
+ if (newContent === initialContent) {
26
+ return null;
27
+ }
28
+ return newContent;
29
+ }
30
+ finally {
31
+ try {
32
+ unlinkSync(tmpPath);
33
+ }
34
+ catch {
35
+ // Cleanup failure — ignore
36
+ }
37
+ }
38
+ }
39
+ //# sourceMappingURL=editor.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"editor.js","sourceRoot":"","sources":["../../../src/cli/ui/editor.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,uCAAuC;AACvC,+DAA+D;AAE/D,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAC7D,OAAO,EAAE,MAAM,EAAE,MAAM,IAAI,CAAC;AAC5B,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEpC,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,cAAsB;IACvD,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,EAAE,EAAE,gBAAgB,UAAU,EAAE,KAAK,CAAC,CAAC;IAElE,IAAI,CAAC;QACH,aAAa,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC;QAEhD,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAExF,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC;YACnF,IAAI,MAAM,CAAC,KAAK;gBAAE,MAAM,MAAM,CAAC,KAAK,CAAC;YACrC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC;gBAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QACvF,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,UAAU,GAAG,YAAY,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QAElD,IAAI,UAAU,KAAK,cAAc,EAAE,CAAC;YAClC,OAAO,IAAI,CAAC;QACd,CAAC;QAED,OAAO,UAAU,CAAC;IACpB,CAAC;YAAS,CAAC;QACT,IAAI,CAAC;YACH,UAAU,CAAC,OAAO,CAAC,CAAC;QACtB,CAAC;QAAC,MAAM,CAAC;YACP,2BAA2B;QAC7B,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,23 @@
1
+ import { CliResponse } from '../../types.js';
2
+ export declare class Output {
3
+ private jsonMode;
4
+ constructor(jsonMode: boolean);
5
+ result<T>(response: CliResponse<T>): void;
6
+ success(msg: string): void;
7
+ error(msg: string): void;
8
+ info(msg: string): void;
9
+ command(msg: string): void;
10
+ label(key: string, value: string): void;
11
+ table(headers: string[], rows: string[][]): void;
12
+ divider(): void;
13
+ card(sections: {
14
+ label: string;
15
+ value: string;
16
+ color?: (s: string) => string;
17
+ }[]): void;
18
+ spinner(text: string): {
19
+ start: () => void;
20
+ succeed: (msg?: string) => void;
21
+ fail: (msg?: string) => void;
22
+ };
23
+ }
@@ -0,0 +1,96 @@
1
+ // ============================================================
2
+ // LAUNCH — CLI Output / Terminal Formatting
3
+ // ============================================================
4
+ import chalk from 'chalk';
5
+ import ora from 'ora';
6
+ export class Output {
7
+ jsonMode;
8
+ constructor(jsonMode) {
9
+ this.jsonMode = jsonMode;
10
+ }
11
+ result(response) {
12
+ if (this.jsonMode) {
13
+ console.log(JSON.stringify(response));
14
+ return;
15
+ }
16
+ if (response.success) {
17
+ this.success(String(response.data ?? 'Done'));
18
+ }
19
+ else {
20
+ this.error(response.error ?? 'Unknown error');
21
+ }
22
+ }
23
+ success(msg) {
24
+ if (this.jsonMode)
25
+ return;
26
+ console.log(chalk.green(`✓ ${msg}`));
27
+ }
28
+ error(msg) {
29
+ if (this.jsonMode)
30
+ return;
31
+ console.log(chalk.red(`✗ ${msg}`));
32
+ }
33
+ info(msg) {
34
+ if (this.jsonMode)
35
+ return;
36
+ console.log(chalk.yellow(msg));
37
+ }
38
+ command(msg) {
39
+ if (this.jsonMode)
40
+ return;
41
+ console.log(chalk.cyan(msg));
42
+ }
43
+ label(key, value) {
44
+ if (this.jsonMode)
45
+ return;
46
+ console.log(`${chalk.cyan(key)}: ${value}`);
47
+ }
48
+ table(headers, rows) {
49
+ if (this.jsonMode)
50
+ return;
51
+ if (rows.length === 0)
52
+ return;
53
+ const colCount = headers.length;
54
+ const widths = headers.map((h, i) => {
55
+ const maxData = rows.reduce((m, r) => Math.max(m, (r[i] ?? '').length), 0);
56
+ return Math.max(h.length, maxData);
57
+ });
58
+ const pad = (s, w) => s + ' '.repeat(Math.max(0, w - s.length));
59
+ const headerLine = headers.map((h, i) => chalk.bold(pad(h, widths[i]))).join(' ');
60
+ console.log(headerLine);
61
+ console.log(chalk.dim('─'.repeat(headerLine.length)));
62
+ for (const row of rows) {
63
+ const line = row.map((cell, i) => pad(cell, widths[i])).join(' ');
64
+ console.log(line);
65
+ }
66
+ }
67
+ divider() {
68
+ if (this.jsonMode)
69
+ return;
70
+ console.log(chalk.dim('──────'));
71
+ }
72
+ card(sections) {
73
+ if (this.jsonMode)
74
+ return;
75
+ for (const s of sections) {
76
+ const value = s.color ? s.color(s.value) : s.value;
77
+ console.log(`${chalk.cyan(s.label)}: ${value}`);
78
+ }
79
+ }
80
+ spinner(text) {
81
+ if (this.jsonMode) {
82
+ return {
83
+ start: () => { },
84
+ succeed: () => { },
85
+ fail: () => { },
86
+ };
87
+ }
88
+ const s = ora(text);
89
+ return {
90
+ start: () => s.start(),
91
+ succeed: (msg) => s.succeed(msg),
92
+ fail: (msg) => s.fail(msg),
93
+ };
94
+ }
95
+ }
96
+ //# sourceMappingURL=output.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output.js","sourceRoot":"","sources":["../../../src/cli/ui/output.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export declare function promptText(message: string, opts?: {
2
+ default?: string;
3
+ validate?: (v: string) => true | string;
4
+ }): Promise<string>;
5
+ export declare function promptPassword(message: string): Promise<string>;
6
+ export declare function promptSelect<T extends string>(message: string, choices: {
7
+ name: string;
8
+ value: T;
9
+ }[]): Promise<T>;
10
+ export declare function promptConfirm(message: string, defaultYes?: boolean): Promise<boolean>;
11
+ export declare function promptMultiInput(message: string, addLabel?: string): Promise<string[]>;
@@ -0,0 +1,28 @@
1
+ // ============================================================
2
+ // LAUNCH — CLI Prompt Wrappers
3
+ // ============================================================
4
+ import { input, password, select, confirm } from '@inquirer/prompts';
5
+ export async function promptText(message, opts) {
6
+ return input({ message, default: opts?.default, validate: opts?.validate });
7
+ }
8
+ export async function promptPassword(message) {
9
+ return password({ message });
10
+ }
11
+ export async function promptSelect(message, choices) {
12
+ return select({ message, choices });
13
+ }
14
+ export async function promptConfirm(message, defaultYes) {
15
+ return confirm({ message, default: defaultYes });
16
+ }
17
+ export async function promptMultiInput(message, addLabel) {
18
+ const entries = [];
19
+ while (true) {
20
+ const label = entries.length === 0 ? message : (addLabel ?? message);
21
+ const result = await promptText(label);
22
+ if (!result)
23
+ break;
24
+ entries.push(result);
25
+ }
26
+ return entries;
27
+ }
28
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../../../src/cli/ui/prompts.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,+BAA+B;AAC/B,+DAA+D;AAE/D,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAErE,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,OAAe,EACf,IAAoE;IAEpE,OAAO,KAAK,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAAe;IAClD,OAAO,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,OAAe,EACf,OAAqC;IAErC,OAAO,MAAM,CAAI,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,OAAe,EAAE,UAAoB;IACvE,OAAO,OAAO,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAAC;AACnD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,OAAe,EAAE,QAAiB;IACvE,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,OAAO,IAAI,EAAE,CAAC;QACZ,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,QAAQ,IAAI,OAAO,CAAC,CAAC;QACrE,MAAM,MAAM,GAAG,MAAM,UAAU,CAAC,KAAK,CAAC,CAAC;QACvC,IAAI,CAAC,MAAM;YAAE,MAAM;QACnB,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACvB,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,20 @@
1
+ export declare class CliError extends Error {
2
+ code: string;
3
+ constructor(message: string, code: string);
4
+ }
5
+ export declare class SessionNotFoundError extends CliError {
6
+ constructor(sessionId?: string);
7
+ }
8
+ export declare class WrongSessionStateError extends CliError {
9
+ constructor(expected: string[], actual: string);
10
+ }
11
+ export declare class InvalidSessionIdError extends CliError {
12
+ constructor(sessionId: string);
13
+ }
14
+ export declare class CorruptedSessionError extends CliError {
15
+ readonly sessionId: string;
16
+ constructor(sessionId: string, innerError: string);
17
+ }
18
+ export declare class NoDraftError extends CliError {
19
+ constructor();
20
+ }
@@ -0,0 +1,48 @@
1
+ // ============================================================
2
+ // LAUNCH — CLI Error Classes
3
+ // ============================================================
4
+ export class CliError extends Error {
5
+ code;
6
+ constructor(message, code) {
7
+ super(message);
8
+ this.code = code;
9
+ this.name = 'CliError';
10
+ }
11
+ }
12
+ export class SessionNotFoundError extends CliError {
13
+ constructor(sessionId) {
14
+ const message = sessionId
15
+ ? `Session '${sessionId}' not found.`
16
+ : "No launch session found. Run 'launch new' to start one.";
17
+ super(message, 'SESSION_NOT_FOUND');
18
+ this.name = 'SessionNotFoundError';
19
+ }
20
+ }
21
+ export class WrongSessionStateError extends CliError {
22
+ constructor(expected, actual) {
23
+ const message = `Session is in '${actual}' state. Expected: ${expected.join(', ')}`;
24
+ super(message, 'WRONG_SESSION_STATE');
25
+ this.name = 'WrongSessionStateError';
26
+ }
27
+ }
28
+ export class InvalidSessionIdError extends CliError {
29
+ constructor(sessionId) {
30
+ super(`Invalid session ID format: '${sessionId}'. Expected UUID v4.`, 'INVALID_SESSION_ID');
31
+ this.name = 'InvalidSessionIdError';
32
+ }
33
+ }
34
+ export class CorruptedSessionError extends CliError {
35
+ sessionId;
36
+ constructor(sessionId, innerError) {
37
+ super(`Session file for '${sessionId}' is corrupted: ${innerError}`, 'CORRUPTED_SESSION');
38
+ this.name = 'CorruptedSessionError';
39
+ this.sessionId = sessionId;
40
+ }
41
+ }
42
+ export class NoDraftError extends CliError {
43
+ constructor() {
44
+ super("No draft in this session. Run 'launch draft' first.", 'NO_DRAFT');
45
+ this.name = 'NoDraftError';
46
+ }
47
+ }
48
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../../src/cli/utils/errors.ts"],"names":[],"mappings":"AAAA,+DAA+D;AAC/D,6BAA6B;AAC7B,+DAA+D;AAE/D,MAAM,OAAO,QAAS,SAAQ,KAAK;IACG;IAApC,YAAY,OAAe,EAAS,IAAY;QAC9C,KAAK,CAAC,OAAO,CAAC,CAAC;QADmB,SAAI,GAAJ,IAAI,CAAQ;QAE9C,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;IACzB,CAAC;CACF;AAED,MAAM,OAAO,oBAAqB,SAAQ,QAAQ;IAChD,YAAY,SAAkB;QAC5B,MAAM,OAAO,GAAG,SAAS;YACvB,CAAC,CAAC,YAAY,SAAS,cAAc;YACrC,CAAC,CAAC,yDAAyD,CAAC;QAC9D,KAAK,CAAC,OAAO,EAAE,mBAAmB,CAAC,CAAC;QACpC,IAAI,CAAC,IAAI,GAAG,sBAAsB,CAAC;IACrC,CAAC;CACF;AAED,MAAM,OAAO,sBAAuB,SAAQ,QAAQ;IAClD,YAAY,QAAkB,EAAE,MAAc;QAC5C,MAAM,OAAO,GAAG,kBAAkB,MAAM,sBAAsB,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACpF,KAAK,CAAC,OAAO,EAAE,qBAAqB,CAAC,CAAC;QACtC,IAAI,CAAC,IAAI,GAAG,wBAAwB,CAAC;IACvC,CAAC;CACF;AAED,MAAM,OAAO,qBAAsB,SAAQ,QAAQ;IACjD,YAAY,SAAiB;QAC3B,KAAK,CAAC,+BAA+B,SAAS,sBAAsB,EAAE,oBAAoB,CAAC,CAAC;QAC5F,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;IACtC,CAAC;CACF;AAED,MAAM,OAAO,qBAAsB,SAAQ,QAAQ;IACjC,SAAS,CAAS;IAElC,YAAY,SAAiB,EAAE,UAAkB;QAC/C,KAAK,CAAC,qBAAqB,SAAS,mBAAmB,UAAU,EAAE,EAAE,mBAAmB,CAAC,CAAC;QAC1F,IAAI,CAAC,IAAI,GAAG,uBAAuB,CAAC;QACpC,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;CACF;AAED,MAAM,OAAO,YAAa,SAAQ,QAAQ;IACxC;QACE,KAAK,CAAC,qDAAqD,EAAE,UAAU,CAAC,CAAC;QACzE,IAAI,CAAC,IAAI,GAAG,cAAc,CAAC;IAC7B,CAAC;CACF"}
@@ -0,0 +1,4 @@
1
+ import { LaunchSession, LaunchStatus, IHPostDraft } from '../../types.js';
2
+ export declare function resolveSession(sessionId?: string): LaunchSession;
3
+ export declare function assertState(session: LaunchSession, ...expected: LaunchStatus[]): void;
4
+ export declare function assertHasDraft(session: LaunchSession): IHPostDraft;