1- import { CreatePlan , Resource , ResourceSettings } from 'codify-plugin-lib' ;
1+ import { CreatePlan , DestroyPlan , ModifyPlan , ParameterChange , Resource , ResourceSettings } from 'codify-plugin-lib' ;
22import { StringIndexedObject } from 'codify-schemas' ;
3+ import fs from 'node:fs/promises' ;
4+ import os from 'node:os' ;
5+ import path from 'node:path' ;
36
47import { SpawnStatus , codifySpawn } from '../../../utils/codify-spawn.js' ;
58import { FileUtils } from '../../../utils/file-utils.js' ;
9+ import { Utils } from '../../../utils/index.js' ;
610import Schema from './alias-schema.json' ;
711
812export interface AliasConfig extends StringIndexedObject {
@@ -16,7 +20,7 @@ export class AliasResource extends Resource<AliasConfig> {
1620 id : 'alias' ,
1721 schema : Schema ,
1822 parameterSettings : {
19- value : { canModify : true }
23+ value : { canModify : true , inputTransformation : ( input ) => Utils . shellEscape ( input ) }
2024 } ,
2125 }
2226 }
@@ -42,24 +46,103 @@ export class AliasResource extends Resource<AliasConfig> {
4246
4347 const [ name , value ] = matchedAlias . split ( '=' ) ;
4448
49+ let processedValue = value . trim ( )
50+ if ( ( processedValue . startsWith ( '\'' ) && processedValue . endsWith ( '\'' ) ) || ( processedValue . startsWith ( '"' ) && processedValue . endsWith ( '"' ) ) ) {
51+ processedValue = processedValue . slice ( 1 , - 1 )
52+ }
53+
4554 return {
4655 alias : name ,
47- value,
56+ value : processedValue ,
4857 }
4958 }
5059
5160 override async create ( plan : CreatePlan < AliasConfig > ) : Promise < void > {
61+ const zshrcPath = path . join ( os . homedir ( ) , '.zshrc' ) ;
62+
63+ if ( ! ( await FileUtils . fileExists ( zshrcPath ) ) ) {
64+ await fs . writeFile ( zshrcPath , '' , { encoding : 'utf8' } ) ;
65+ }
66+
5267 const { alias, value } = plan . desiredConfig ;
68+ const aliasString = this . aliasString ( alias , value ) ;
69+ await fs . appendFile ( zshrcPath , '\n\n' + aliasString , { encoding : 'utf8' } ) ;
70+ }
71+
72+ async modify ( pc : ParameterChange < AliasConfig > , plan : ModifyPlan < AliasConfig > ) : Promise < void > {
73+ if ( pc . name !== 'value' ) {
74+ return ;
75+ }
76+
77+ const { alias, value } = plan . currentConfig ;
78+ const aliasInfo = await this . findAlias ( alias , value ) ;
79+ if ( ! aliasInfo ) {
80+ throw new Error ( `Unable to find alias: ${ alias } on the system. Codify isn't able to search all locations on the system. Please delete the alias manually and re-run Codify.` ) ;
81+ }
82+
83+ const aliasString = this . aliasString ( alias , value ) ;
84+ const aliasStringShort = this . aliasStringShort ( alias , value ) ;
85+
86+ const lines = aliasInfo . contents
87+ . split ( / \n / )
5388
54- await FileUtils . addAliasToZshrc ( alias , value ) ;
89+ const aliasLineNum = lines
90+ . findIndex ( ( l ) => l . trim ( ) === aliasStringShort || l . trim ( ) === aliasString ) ;
91+ if ( ! aliasLineNum ) {
92+ throw new Error ( `Unable to modify Alias. Cannot find line ${ aliasString } in ${ aliasInfo . path } . Please delete the alias manually and re-run Codify.` ) ;
93+ }
94+
95+ const newAlias = this . aliasString ( plan . desiredConfig . alias , plan . desiredConfig . value ) ;
96+ lines . splice ( aliasLineNum , 1 , newAlias ) ;
97+
98+ await fs . writeFile ( lines . join ( '\n' ) , 'utf8' ) ;
99+ }
100+
101+ async destroy ( plan : DestroyPlan < AliasConfig > ) : Promise < void > {
102+ const { alias, value } = plan . currentConfig ;
103+ const aliasInfo = await this . findAlias ( alias , value ) ;
104+ if ( ! aliasInfo ) {
105+ throw new Error ( `Unable to find alias: ${ alias } on the system. Codify isn't able to search all locations on the system. Please delete the alias manually and re-run Codify.` ) ;
106+ }
107+
108+ const aliasString = this . aliasString ( alias , value ) ;
109+ const aliasStringShort = this . aliasStringShort ( alias , value ) ;
110+
111+ await FileUtils . removeLineFromFile ( aliasInfo . path , aliasString ) ;
112+ await FileUtils . removeLineFromFile ( aliasInfo . path , aliasStringShort ) ;
55113 }
56114
57- // TODO: Implement updating an alias
58- override async modify ( ) : Promise < void > {
59- throw new Error ( 'Unsupported for now. Un-able to update an alias value for now' )
115+ private async findAlias ( alias : string , value : string ) : Promise < { path : string ; contents : string ; } | null > {
116+ const paths = [
117+ path . join ( os . homedir ( ) , '.zshrc' ) ,
118+ path . join ( os . homedir ( ) , '.zprofile' ) ,
119+ path . join ( os . homedir ( ) , '.zshenv' ) ,
120+ ] ;
121+
122+ const aliasString = this . aliasString ( alias , value ) ;
123+ const aliasStringShort = this . aliasStringShort ( alias , value ) ;
124+
125+ for ( const path of paths ) {
126+ if ( await FileUtils . fileExists ( path ) ) {
127+ const fileContents = await fs . readFile ( path , 'utf8' ) ;
128+
129+ if ( fileContents . includes ( aliasString ) || fileContents . includes ( aliasStringShort ) ) {
130+ return {
131+ path,
132+ contents : fileContents ,
133+ }
134+ }
135+ }
136+ }
137+
138+ return null ;
60139 }
61140
62- // TODO: Implement destroy some time in the future
63- override async destroy ( ) : Promise < void > { }
141+ private aliasString ( alias : string , value : string ) : string {
142+ return `alias ${ alias } ='${ value } '`
143+ }
64144
145+ private aliasStringShort ( alias : string , value : string ) : string {
146+ return `alias ${ alias } =${ value } `
147+ }
65148}
0 commit comments