@codifycli/plugin-core 1.2.2 → 1.2.3-beta.1
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/.claude/settings.local.json +13 -0
- package/dist/bin/build.d.ts +1 -0
- package/dist/bin/build.js +80 -0
- package/dist/bin/deploy-plugin.d.ts +2 -0
- package/dist/bin/deploy-plugin.js +8 -0
- package/dist/entities/change-set.d.ts +24 -0
- package/dist/entities/change-set.js +152 -0
- package/dist/entities/errors.d.ts +4 -0
- package/dist/entities/errors.js +7 -0
- package/dist/entities/plan-types.d.ts +25 -0
- package/dist/entities/plan-types.js +1 -0
- package/dist/entities/plan.d.ts +15 -0
- package/dist/entities/plan.js +127 -0
- package/dist/entities/plugin.d.ts +16 -0
- package/dist/entities/plugin.js +80 -0
- package/dist/entities/resource-options.d.ts +31 -0
- package/dist/entities/resource-options.js +76 -0
- package/dist/entities/resource-types.d.ts +11 -0
- package/dist/entities/resource-types.js +1 -0
- package/dist/entities/resource.d.ts +42 -0
- package/dist/entities/resource.js +303 -0
- package/dist/entities/stateful-parameter.d.ts +29 -0
- package/dist/entities/stateful-parameter.js +46 -0
- package/dist/entities/transform-parameter.d.ts +4 -0
- package/dist/entities/transform-parameter.js +2 -0
- package/dist/messages/sender.d.ts +1 -1
- package/dist/messages/sender.js +3 -4
- package/dist/plan/change-set.d.ts +0 -1
- package/dist/plan/change-set.js +3 -12
- package/dist/pty/background-pty.js +1 -0
- package/dist/pty/seqeuntial-pty.js +3 -1
- package/dist/pty/vitest.config.d.ts +2 -0
- package/dist/pty/vitest.config.js +11 -0
- package/dist/resource/stateful-parameter.d.ts +165 -0
- package/dist/resource/stateful-parameter.js +94 -0
- package/dist/scripts/deploy.d.ts +1 -0
- package/dist/scripts/deploy.js +2 -0
- package/dist/test.d.ts +1 -0
- package/dist/test.js +5 -0
- package/dist/utils/codify-spawn.d.ts +29 -0
- package/dist/utils/codify-spawn.js +136 -0
- package/dist/utils/file-utils.js +3 -3
- package/dist/utils/functions.js +1 -1
- package/dist/utils/internal-utils.d.ts +12 -0
- package/dist/utils/internal-utils.js +74 -0
- package/dist/utils/load-resources.d.ts +1 -0
- package/dist/utils/load-resources.js +46 -0
- package/dist/utils/package-json-utils.d.ts +12 -0
- package/dist/utils/package-json-utils.js +34 -0
- package/dist/utils/spawn-2.d.ts +5 -0
- package/dist/utils/spawn-2.js +7 -0
- package/dist/utils/spawn.d.ts +29 -0
- package/dist/utils/spawn.js +124 -0
- package/dist/utils/utils.d.ts +18 -0
- package/dist/utils/utils.js +86 -0
- package/package.json +1 -1
- package/src/messages/sender.ts +3 -4
- package/src/plan/change-set.test.ts +0 -27
- package/src/plan/change-set.ts +3 -10
- package/src/pty/background-pty.ts +1 -0
- package/src/pty/seqeuntial-pty.ts +3 -1
- package/src/utils/file-utils.ts +3 -3
- package/src/utils/functions.ts +1 -1
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
+
import { SpawnOptions } from 'node:child_process';
|
|
3
|
+
export declare enum SpawnStatus {
|
|
4
|
+
SUCCESS = "success",
|
|
5
|
+
ERROR = "error"
|
|
6
|
+
}
|
|
7
|
+
export interface SpawnResult {
|
|
8
|
+
status: SpawnStatus;
|
|
9
|
+
data: string;
|
|
10
|
+
}
|
|
11
|
+
type CodifySpawnOptions = {
|
|
12
|
+
cwd?: string;
|
|
13
|
+
throws?: boolean;
|
|
14
|
+
requiresRoot?: boolean;
|
|
15
|
+
} & Omit<SpawnOptions, 'detached' | 'shell' | 'stdio'>;
|
|
16
|
+
/**
|
|
17
|
+
*
|
|
18
|
+
* @param cmd Command to run. Ex: `rm -rf`
|
|
19
|
+
* @param opts Standard options for node spawn. Additional argument:
|
|
20
|
+
* throws determines if a shell will throw a JS error. Defaults to true
|
|
21
|
+
*
|
|
22
|
+
* @see promiseSpawn
|
|
23
|
+
* @see spawn
|
|
24
|
+
*
|
|
25
|
+
* @returns SpawnResult { status: SUCCESS | ERROR; data: string }
|
|
26
|
+
*/
|
|
27
|
+
export declare function $(cmd: string, opts?: CodifySpawnOptions): Promise<SpawnResult>;
|
|
28
|
+
export declare function isDebug(): boolean;
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { Ajv } from 'ajv';
|
|
2
|
+
import { MessageCmd, SudoRequestResponseDataSchema } from 'codify-schemas';
|
|
3
|
+
import { spawn } from 'node:child_process';
|
|
4
|
+
import { SudoError } from '../errors.js';
|
|
5
|
+
const ajv = new Ajv({
|
|
6
|
+
strict: true,
|
|
7
|
+
});
|
|
8
|
+
const validateSudoRequestResponse = ajv.compile(SudoRequestResponseDataSchema);
|
|
9
|
+
export var SpawnStatus;
|
|
10
|
+
(function (SpawnStatus) {
|
|
11
|
+
SpawnStatus["SUCCESS"] = "success";
|
|
12
|
+
SpawnStatus["ERROR"] = "error";
|
|
13
|
+
})(SpawnStatus || (SpawnStatus = {}));
|
|
14
|
+
/**
|
|
15
|
+
*
|
|
16
|
+
* @param cmd Command to run. Ex: `rm -rf`
|
|
17
|
+
* @param opts Standard options for node spawn. Additional argument:
|
|
18
|
+
* throws determines if a shell will throw a JS error. Defaults to true
|
|
19
|
+
*
|
|
20
|
+
* @see promiseSpawn
|
|
21
|
+
* @see spawn
|
|
22
|
+
*
|
|
23
|
+
* @returns SpawnResult { status: SUCCESS | ERROR; data: string }
|
|
24
|
+
*/
|
|
25
|
+
export async function $(cmd, opts) {
|
|
26
|
+
const throws = opts?.throws ?? true;
|
|
27
|
+
console.log(`Running command: ${cmd}`);
|
|
28
|
+
try {
|
|
29
|
+
// TODO: Need to benchmark the effects of using sh vs zsh for shell.
|
|
30
|
+
// Seems like zsh shells run slower
|
|
31
|
+
let result;
|
|
32
|
+
if (!opts?.requiresRoot) {
|
|
33
|
+
result = await internalSpawn(cmd, opts ?? {});
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
result = await externalSpawnWithSudo(cmd, opts);
|
|
37
|
+
}
|
|
38
|
+
if (result.status !== SpawnStatus.SUCCESS) {
|
|
39
|
+
throw new Error(result.data);
|
|
40
|
+
}
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
if (isDebug()) {
|
|
45
|
+
console.error(`CodifySpawn error for command ${cmd}`, error);
|
|
46
|
+
}
|
|
47
|
+
if (error.message?.startsWith('sudo:')) {
|
|
48
|
+
throw new SudoError(cmd);
|
|
49
|
+
}
|
|
50
|
+
if (throws) {
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
53
|
+
if (error instanceof Error) {
|
|
54
|
+
return {
|
|
55
|
+
status: SpawnStatus.ERROR,
|
|
56
|
+
data: error.message,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
return {
|
|
60
|
+
status: SpawnStatus.ERROR,
|
|
61
|
+
data: error + '',
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
async function internalSpawn(cmd, opts) {
|
|
66
|
+
return new Promise((resolve, reject) => {
|
|
67
|
+
const output = [];
|
|
68
|
+
// Source start up shells to emulate a users environment vs. a non-interactive non-login shell script
|
|
69
|
+
// Ignore all stdin
|
|
70
|
+
const _process = spawn(`source ~/.zshrc; ${cmd}`, [], {
|
|
71
|
+
...opts,
|
|
72
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
73
|
+
shell: 'zsh',
|
|
74
|
+
});
|
|
75
|
+
const { stdout, stderr, stdin } = _process;
|
|
76
|
+
stdout.setEncoding('utf8');
|
|
77
|
+
stderr.setEncoding('utf8');
|
|
78
|
+
stdout.on('data', (data) => {
|
|
79
|
+
output.push(data.toString());
|
|
80
|
+
});
|
|
81
|
+
stderr.on('data', (data) => {
|
|
82
|
+
output.push(data.toString());
|
|
83
|
+
});
|
|
84
|
+
_process.on('error', (data) => {
|
|
85
|
+
});
|
|
86
|
+
// please node that this is not a full replacement for 'inherit'
|
|
87
|
+
// the child process can and will detect if stdout is a pty and change output based on it
|
|
88
|
+
// the terminal context is lost & ansi information (coloring) etc will be lost
|
|
89
|
+
if (stdout && stderr) {
|
|
90
|
+
stdout.pipe(process.stdout);
|
|
91
|
+
stderr.pipe(process.stderr);
|
|
92
|
+
}
|
|
93
|
+
_process.on('close', (code) => {
|
|
94
|
+
resolve({
|
|
95
|
+
status: code === 0 ? SpawnStatus.SUCCESS : SpawnStatus.ERROR,
|
|
96
|
+
data: output.join('\n'),
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
async function externalSpawnWithSudo(cmd, opts) {
|
|
102
|
+
return await new Promise((resolve) => {
|
|
103
|
+
const listener = (data) => {
|
|
104
|
+
if (data.cmd === MessageCmd.SUDO_REQUEST + '_Response') {
|
|
105
|
+
process.removeListener('message', listener);
|
|
106
|
+
if (!validateSudoRequestResponse(data.data)) {
|
|
107
|
+
throw new Error(`Invalid response for sudo request: ${JSON.stringify(validateSudoRequestResponse.errors, null, 2)}`);
|
|
108
|
+
}
|
|
109
|
+
resolve(data.data);
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
process.on('message', listener);
|
|
113
|
+
process.send({
|
|
114
|
+
cmd: MessageCmd.SUDO_REQUEST,
|
|
115
|
+
data: {
|
|
116
|
+
command: cmd,
|
|
117
|
+
options: opts ?? {},
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
export function isDebug() {
|
|
123
|
+
return process.env.DEBUG != null && process.env.DEBUG.includes('codify'); // TODO: replace with debug library
|
|
124
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { ResourceConfig, StringIndexedObject } from 'codify-schemas';
|
|
2
|
+
export declare const VerbosityLevel: {
|
|
3
|
+
level: number;
|
|
4
|
+
get(): number;
|
|
5
|
+
set(level: number): void;
|
|
6
|
+
};
|
|
7
|
+
export declare function isDebug(): boolean;
|
|
8
|
+
export declare function splitUserConfig<T extends StringIndexedObject>(config: ResourceConfig & T): {
|
|
9
|
+
parameters: T;
|
|
10
|
+
coreParameters: ResourceConfig;
|
|
11
|
+
};
|
|
12
|
+
export declare function setsEqual(set1: Set<unknown>, set2: Set<unknown>): boolean;
|
|
13
|
+
export declare function untildify(pathWithTilde: string): string;
|
|
14
|
+
export declare function tildify(pathWithTilde: string): string;
|
|
15
|
+
export declare function resolvePathWithVariables(pathWithVariables: string): string;
|
|
16
|
+
export declare function addVariablesToPath(pathWithoutVariables: string): string;
|
|
17
|
+
export declare function unhome(pathWithHome: string): string;
|
|
18
|
+
export declare function areArraysEqual(isElementEqual: ((desired: unknown, current: unknown) => boolean) | undefined, desired: unknown, current: unknown): boolean;
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import os from 'node:os';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
export const VerbosityLevel = new class {
|
|
4
|
+
level = 0;
|
|
5
|
+
get() {
|
|
6
|
+
return this.level;
|
|
7
|
+
}
|
|
8
|
+
set(level) {
|
|
9
|
+
this.level = level;
|
|
10
|
+
}
|
|
11
|
+
};
|
|
12
|
+
export function isDebug() {
|
|
13
|
+
return process.env.DEBUG != null && process.env.DEBUG.includes('codify'); // TODO: replace with debug library
|
|
14
|
+
}
|
|
15
|
+
export function splitUserConfig(config) {
|
|
16
|
+
const coreParameters = {
|
|
17
|
+
type: config.type,
|
|
18
|
+
...(config.name ? { name: config.name } : {}),
|
|
19
|
+
...(config.dependsOn ? { dependsOn: config.dependsOn } : {}),
|
|
20
|
+
};
|
|
21
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
22
|
+
const { type, name, dependsOn, ...parameters } = config;
|
|
23
|
+
return {
|
|
24
|
+
parameters: parameters,
|
|
25
|
+
coreParameters,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export function setsEqual(set1, set2) {
|
|
29
|
+
return set1.size === set2.size && [...set1].every((v) => set2.has(v));
|
|
30
|
+
}
|
|
31
|
+
const homeDirectory = os.homedir();
|
|
32
|
+
export function untildify(pathWithTilde) {
|
|
33
|
+
return homeDirectory ? pathWithTilde.replace(/^~(?=$|\/|\\)/, homeDirectory) : pathWithTilde;
|
|
34
|
+
}
|
|
35
|
+
export function tildify(pathWithTilde) {
|
|
36
|
+
return homeDirectory ? pathWithTilde.replace(homeDirectory, '~') : pathWithTilde;
|
|
37
|
+
}
|
|
38
|
+
export function resolvePathWithVariables(pathWithVariables) {
|
|
39
|
+
// @ts-expect-error Ignore this for now
|
|
40
|
+
return pathWithVariables.replace(/\$([A-Z_]+[A-Z0-9_]*)|\${([A-Z0-9_]*)}/ig, (_, a, b) => process.env[a || b]);
|
|
41
|
+
}
|
|
42
|
+
export function addVariablesToPath(pathWithoutVariables) {
|
|
43
|
+
let result = pathWithoutVariables;
|
|
44
|
+
for (const [key, value] of Object.entries(process.env)) {
|
|
45
|
+
if (!value || !path.isAbsolute(value) || value === '/' || key === 'HOME' || key === 'PATH' || key === 'SHELL' || key === 'PWD') {
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
result = result.replaceAll(value, `$${key}`);
|
|
49
|
+
}
|
|
50
|
+
return result;
|
|
51
|
+
}
|
|
52
|
+
export function unhome(pathWithHome) {
|
|
53
|
+
return pathWithHome.includes('$HOME') ? pathWithHome.replaceAll('$HOME', os.homedir()) : pathWithHome;
|
|
54
|
+
}
|
|
55
|
+
export function areArraysEqual(isElementEqual, desired, current) {
|
|
56
|
+
if (!desired || !current) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
if (!Array.isArray(desired) || !Array.isArray(current)) {
|
|
60
|
+
throw new Error(`A non-array value:
|
|
61
|
+
|
|
62
|
+
Desired: ${JSON.stringify(desired, null, 2)}
|
|
63
|
+
|
|
64
|
+
Current: ${JSON.stringify(desired, null, 2)}
|
|
65
|
+
|
|
66
|
+
Was provided even though type array was specified.
|
|
67
|
+
`);
|
|
68
|
+
}
|
|
69
|
+
if (desired.length !== current.length) {
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
const desiredCopy = [...desired];
|
|
73
|
+
const currentCopy = [...current];
|
|
74
|
+
// Algorithm for to check equality between two un-ordered; un-hashable arrays using
|
|
75
|
+
// an isElementEqual method. Time: O(n^2)
|
|
76
|
+
for (let counter = desiredCopy.length - 1; counter >= 0; counter--) {
|
|
77
|
+
const idx = currentCopy.findIndex((e2) => (isElementEqual
|
|
78
|
+
?? ((a, b) => a === b))(desiredCopy[counter], e2));
|
|
79
|
+
if (idx === -1) {
|
|
80
|
+
return false;
|
|
81
|
+
}
|
|
82
|
+
desiredCopy.splice(counter, 1);
|
|
83
|
+
currentCopy.splice(idx, 1);
|
|
84
|
+
}
|
|
85
|
+
return currentCopy.length === 0;
|
|
86
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@codifycli/plugin-core",
|
|
3
|
-
"version": "1.2.
|
|
3
|
+
"version": "1.2.3-beta.1",
|
|
4
4
|
"description": "TypeScript library for building Codify plugins to manage system resources (applications, CLI tools, settings) through infrastructure-as-code",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"typings": "dist/index.d.ts",
|
package/src/messages/sender.ts
CHANGED
|
@@ -27,18 +27,17 @@ class CodifyCliSenderImpl {
|
|
|
27
27
|
})
|
|
28
28
|
}
|
|
29
29
|
|
|
30
|
-
sendApplyNote(message: string, resourceType?: string): void {
|
|
30
|
+
async sendApplyNote(message: string, resourceType?: string): Promise<void> {
|
|
31
31
|
if (!process.send || !process.connected) {
|
|
32
32
|
return;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
|
|
35
|
+
await this.sendAndWaitForResponse(<IpcMessageV2>{
|
|
36
36
|
cmd: MessageCmd.APPLY_NOTE_REQUEST,
|
|
37
37
|
data: <ApplyNoteRequestData>{
|
|
38
38
|
message,
|
|
39
39
|
...(resourceType && { resourceType }),
|
|
40
|
-
}
|
|
41
|
-
requestId: nanoid(8),
|
|
40
|
+
}
|
|
42
41
|
});
|
|
43
42
|
}
|
|
44
43
|
|
|
@@ -304,33 +304,6 @@ describe('Change set tests', () => {
|
|
|
304
304
|
expect(cs.operation).to.eq(ResourceOperation.DESTROY);
|
|
305
305
|
})
|
|
306
306
|
|
|
307
|
-
it('treats empty objects {} as no-op', () => {
|
|
308
|
-
const desired = {
|
|
309
|
-
keyboard: {},
|
|
310
|
-
dock: {},
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
const current = {
|
|
314
|
-
keyboard: {},
|
|
315
|
-
dock: {},
|
|
316
|
-
}
|
|
317
|
-
|
|
318
|
-
const cs = ChangeSet.calculateModification(desired, current);
|
|
319
|
-
expect(cs.parameterChanges.length).to.eq(0);
|
|
320
|
-
expect(cs.operation).to.eq(ResourceOperation.NOOP);
|
|
321
|
-
})
|
|
322
|
-
|
|
323
|
-
it('treats empty object {} as absent when current has no value', () => {
|
|
324
|
-
const desired = {
|
|
325
|
-
keyboard: {},
|
|
326
|
-
dock: {},
|
|
327
|
-
}
|
|
328
|
-
|
|
329
|
-
const cs = ChangeSet.calculateModification(desired, {});
|
|
330
|
-
expect(cs.parameterChanges.length).to.eq(0);
|
|
331
|
-
expect(cs.operation).to.eq(ResourceOperation.NOOP);
|
|
332
|
-
})
|
|
333
|
-
|
|
334
307
|
it('correctly determines array equality 5', () => {
|
|
335
308
|
const arrA = [{ key1: 'b' }, { key1: 'a' }, { key1: 'a' }];
|
|
336
309
|
const arrB = [{ key1: 'a' }, { key1: 'a' }, { key1: 'b' }];
|
package/src/plan/change-set.ts
CHANGED
|
@@ -154,13 +154,13 @@ export class ChangeSet<T extends StringIndexedObject> {
|
|
|
154
154
|
): ParameterChange<T>[] {
|
|
155
155
|
const parameterChangeSet = new Array<ParameterChange<T>>();
|
|
156
156
|
|
|
157
|
-
// Filter out null
|
|
157
|
+
// Filter out null and undefined values or else the diff below will not work
|
|
158
158
|
const desired = Object.fromEntries(
|
|
159
|
-
Object.entries(desiredParameters).filter(([, v]) =>
|
|
159
|
+
Object.entries(desiredParameters).filter(([, v]) => v !== null && v !== undefined)
|
|
160
160
|
) as Partial<T>
|
|
161
161
|
|
|
162
162
|
const current = Object.fromEntries(
|
|
163
|
-
Object.entries(currentParameters).filter(([, v]) =>
|
|
163
|
+
Object.entries(currentParameters).filter(([, v]) => v !== null && v !== undefined)
|
|
164
164
|
) as Partial<T>
|
|
165
165
|
|
|
166
166
|
for (const k of new Set([...Object.keys(current), ...Object.keys(desired)])) {
|
|
@@ -227,13 +227,6 @@ export class ChangeSet<T extends StringIndexedObject> {
|
|
|
227
227
|
return orderOfOperations[Math.max(indexPrev, indexNext)];
|
|
228
228
|
}
|
|
229
229
|
|
|
230
|
-
private static isAbsent(v: unknown): boolean {
|
|
231
|
-
if (v === null || v === undefined) return true;
|
|
232
|
-
if (Array.isArray(v)) return v.length === 0;
|
|
233
|
-
if (typeof v === 'object') return Object.keys(v as object).length === 0;
|
|
234
|
-
return false;
|
|
235
|
-
}
|
|
236
|
-
|
|
237
230
|
private static isSame(
|
|
238
231
|
desired: unknown,
|
|
239
232
|
current: unknown,
|
|
@@ -135,6 +135,7 @@ export class BackgroundPty implements IPty {
|
|
|
135
135
|
return new Promise(resolve => {
|
|
136
136
|
this.basePty.write(' unset PS1;\n');
|
|
137
137
|
this.basePty.write(' unset PS0;\n')
|
|
138
|
+
this.basePty.write(' unsetopt CORRECT CORRECT_ALL 2>/dev/null; true;\n')
|
|
138
139
|
this.basePty.write(' echo setup complete\\"\n')
|
|
139
140
|
|
|
140
141
|
const listener = this.basePty.onData((data: string) => {
|
|
@@ -88,7 +88,9 @@ export class SequentialPty implements IPty {
|
|
|
88
88
|
const initialCols = options?.disableWrapping ? 10_000 : process.stdout.columns ?? 80
|
|
89
89
|
const initialRows = process.stdout.rows ?? 24;
|
|
90
90
|
|
|
91
|
-
const
|
|
91
|
+
const disableAutocorrect = Utils.getShell() === Shell.ZSH ? 'unsetopt CORRECT CORRECT_ALL 2>/dev/null; ' : '';
|
|
92
|
+
const wrappedCmd = `${disableAutocorrect}${cmd}`;
|
|
93
|
+
const args = options?.interactive ? ['-i', '-c', wrappedCmd] : ['-c', wrappedCmd]
|
|
92
94
|
|
|
93
95
|
// Run the command in a pty for interactivity
|
|
94
96
|
const mPty = pty.spawn(this.getDefaultShell(), args, {
|
package/src/utils/file-utils.ts
CHANGED
|
@@ -35,7 +35,7 @@ export class FileUtils {
|
|
|
35
35
|
);
|
|
36
36
|
|
|
37
37
|
await fs.appendFile(Utils.getPrimaryShellRc(), lineToInsert)
|
|
38
|
-
CodifyCliSender.sendApplyNote(ApplyNotes.sourceShellRc());
|
|
38
|
+
await CodifyCliSender.sendApplyNote(ApplyNotes.sourceShellRc());
|
|
39
39
|
|
|
40
40
|
function addLeadingSpacer(line: string): string {
|
|
41
41
|
return line.startsWith('\n')
|
|
@@ -60,7 +60,7 @@ export class FileUtils {
|
|
|
60
60
|
${lines.join('\n')}`)
|
|
61
61
|
|
|
62
62
|
await fs.appendFile(shellRc, formattedLines)
|
|
63
|
-
CodifyCliSender.sendApplyNote(ApplyNotes.sourceShellRc());
|
|
63
|
+
await CodifyCliSender.sendApplyNote(ApplyNotes.sourceShellRc());
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
/**
|
|
@@ -85,7 +85,7 @@ ${lines.join('\n')}`)
|
|
|
85
85
|
await fs.appendFile(shellRc, `\nexport PATH=${value}:$PATH;`, { encoding: 'utf8' });
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
-
CodifyCliSender.sendApplyNote(ApplyNotes.sourceShellRc());
|
|
88
|
+
await CodifyCliSender.sendApplyNote(ApplyNotes.sourceShellRc());
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
static async removeFromFile(filePath: string, search: string): Promise<void> {
|
package/src/utils/functions.ts
CHANGED
|
@@ -43,7 +43,7 @@ export function resolvePathWithVariables(pathWithVariables: string) {
|
|
|
43
43
|
export function addVariablesToPath(pathWithoutVariables: string) {
|
|
44
44
|
let result = pathWithoutVariables;
|
|
45
45
|
for (const [key, value] of Object.entries(process.env)) {
|
|
46
|
-
if (!value || !path.isAbsolute(value) || value === '/' ||
|
|
46
|
+
if (!value || !path.isAbsolute(value) || value === '/' || key === 'HOME' || key === 'PATH' || key === 'SHELL' || key === 'PWD') {
|
|
47
47
|
continue;
|
|
48
48
|
}
|
|
49
49
|
|