@@ -6,50 +6,70 @@ import {
66 detectPackageManager ,
77 devInstallCommand ,
88 isPackageInstalled ,
9+ prodInstallCommand ,
910} from '../utils.js'
1011
12+ const STACK_PACKAGE = '@cipherstash/stack'
1113const FORGE_PACKAGE = '@cipherstash/stack-forge'
1214
15+ /**
16+ * Installs a package if not already present.
17+ * Returns true if installed (or already was), false if skipped or failed.
18+ */
19+ async function installIfNeeded (
20+ packageName : string ,
21+ buildCommand : ( pm : ReturnType < typeof detectPackageManager > , pkg : string ) => string ,
22+ depLabel : string ,
23+ ) : Promise < boolean > {
24+ if ( isPackageInstalled ( packageName ) ) {
25+ p . log . success ( `${ packageName } is already installed.` )
26+ return true
27+ }
28+
29+ const pm = detectPackageManager ( )
30+ const cmd = buildCommand ( pm , packageName )
31+
32+ const install = await p . confirm ( {
33+ message : `Install ${ packageName } as a ${ depLabel } dependency? (${ cmd } )` ,
34+ } )
35+
36+ if ( p . isCancel ( install ) ) throw new CancelledError ( )
37+
38+ if ( ! install ) {
39+ p . log . info ( `Skipping ${ packageName } installation.` )
40+ p . note (
41+ `You can install it manually later:\n ${ cmd } ` ,
42+ 'Manual Installation' ,
43+ )
44+ return false
45+ }
46+
47+ const s = p . spinner ( )
48+ s . start ( `Installing ${ packageName } ...` )
49+
50+ try {
51+ execSync ( cmd , { cwd : process . cwd ( ) , stdio : 'pipe' } )
52+ s . stop ( `${ packageName } installed successfully` )
53+ return true
54+ } catch ( err ) {
55+ const message = err instanceof Error ? err . message : String ( err )
56+ s . stop ( `${ packageName } installation failed` )
57+ p . log . error ( message )
58+ p . note ( `You can install it manually:\n ${ cmd } ` , 'Manual Installation' )
59+ return false
60+ }
61+ }
62+
1363export const installForgeStep : InitStep = {
1464 id : 'install-forge' ,
15- name : 'Install stack-forge ' ,
65+ name : 'Install stack dependencies ' ,
1666 async run ( state : InitState , _provider : InitProvider ) : Promise < InitState > {
17- if ( isPackageInstalled ( FORGE_PACKAGE ) ) {
18- p . log . success ( `${ FORGE_PACKAGE } is already installed.` )
19- return { ...state , forgeInstalled : true }
20- }
21-
22- const pm = detectPackageManager ( )
23- const cmd = devInstallCommand ( pm , FORGE_PACKAGE )
24-
25- const install = await p . confirm ( {
26- message : `Install ${ FORGE_PACKAGE } as a dev dependency? (${ cmd } )` ,
27- } )
28-
29- if ( p . isCancel ( install ) ) throw new CancelledError ( )
30-
31- if ( ! install ) {
32- p . log . info ( `Skipping ${ FORGE_PACKAGE } installation.` )
33- p . note (
34- `You can install it manually later:\n ${ cmd } ` ,
35- 'Manual Installation' ,
36- )
37- return { ...state , forgeInstalled : false }
38- }
39-
40- const s = p . spinner ( )
41- s . start ( `Installing ${ FORGE_PACKAGE } ...` )
42-
43- try {
44- execSync ( cmd , { cwd : process . cwd ( ) , stdio : 'pipe' } )
45- s . stop ( `${ FORGE_PACKAGE } installed successfully` )
46- return { ...state , forgeInstalled : true }
47- } catch ( err ) {
48- const message = err instanceof Error ? err . message : String ( err )
49- s . stop ( `${ FORGE_PACKAGE } installation failed` )
50- p . log . error ( message )
51- p . note ( `You can install it manually:\n ${ cmd } ` , 'Manual Installation' )
52- return { ...state , forgeInstalled : false }
53- }
67+ // Install @cipherstash /stack as a production dependency
68+ const stackInstalled = await installIfNeeded ( STACK_PACKAGE , prodInstallCommand , 'production' )
69+
70+ // Install @cipherstash /stack-forge as a dev dependency
71+ const forgeInstalled = await installIfNeeded ( FORGE_PACKAGE , devInstallCommand , 'dev' )
72+
73+ return { ...state , forgeInstalled, stackInstalled }
5474 } ,
5575}
0 commit comments