@codifycli/plugin-core 1.1.0-beta9 → 1.2.1-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.
Files changed (87) hide show
  1. package/dist/common/apply-notes.d.ts +5 -0
  2. package/dist/common/apply-notes.js +10 -0
  3. package/dist/common/errors.d.ts +2 -1
  4. package/dist/common/errors.js +3 -1
  5. package/dist/index.d.ts +1 -0
  6. package/dist/index.js +1 -0
  7. package/dist/messages/handlers.js +24 -15
  8. package/dist/messages/sender.d.ts +1 -0
  9. package/dist/messages/sender.js +12 -0
  10. package/dist/plan/change-set.d.ts +1 -0
  11. package/dist/plan/change-set.js +13 -3
  12. package/dist/plugin/plugin.d.ts +7 -2
  13. package/dist/plugin/plugin.js +14 -7
  14. package/dist/pty/background-pty.d.ts +1 -0
  15. package/dist/pty/background-pty.js +3 -0
  16. package/dist/pty/index.d.ts +3 -1
  17. package/dist/pty/index.js +5 -2
  18. package/dist/pty/seqeuntial-pty.d.ts +4 -0
  19. package/dist/pty/seqeuntial-pty.js +18 -3
  20. package/dist/resource/parsed-resource-settings.js +1 -1
  21. package/dist/utils/file-utils.js +8 -2
  22. package/dist/utils/functions.js +3 -2
  23. package/dist/utils/index.js +15 -1
  24. package/package.json +3 -3
  25. package/src/common/apply-notes.ts +12 -0
  26. package/src/common/errors.ts +3 -1
  27. package/src/index.ts +1 -0
  28. package/src/messages/handlers.ts +24 -16
  29. package/src/messages/sender.ts +21 -1
  30. package/src/plan/change-set.test.ts +46 -0
  31. package/src/plan/change-set.ts +11 -3
  32. package/src/plugin/plugin.ts +22 -8
  33. package/src/pty/background-pty.ts +4 -0
  34. package/src/pty/index.ts +8 -2
  35. package/src/pty/seqeuntial-pty.ts +21 -3
  36. package/src/resource/parsed-resource-settings.ts +1 -1
  37. package/src/utils/file-utils.ts +7 -2
  38. package/src/utils/functions.ts +3 -2
  39. package/src/utils/index.ts +18 -1
  40. package/src/utils/internal-utils.test.ts +1 -0
  41. package/.claude/settings.local.json +0 -5
  42. package/dist/bin/build.d.ts +0 -1
  43. package/dist/bin/build.js +0 -80
  44. package/dist/bin/deploy-plugin.d.ts +0 -2
  45. package/dist/bin/deploy-plugin.js +0 -8
  46. package/dist/entities/change-set.d.ts +0 -24
  47. package/dist/entities/change-set.js +0 -152
  48. package/dist/entities/errors.d.ts +0 -4
  49. package/dist/entities/errors.js +0 -7
  50. package/dist/entities/plan-types.d.ts +0 -25
  51. package/dist/entities/plan-types.js +0 -1
  52. package/dist/entities/plan.d.ts +0 -15
  53. package/dist/entities/plan.js +0 -127
  54. package/dist/entities/plugin.d.ts +0 -16
  55. package/dist/entities/plugin.js +0 -80
  56. package/dist/entities/resource-options.d.ts +0 -31
  57. package/dist/entities/resource-options.js +0 -76
  58. package/dist/entities/resource-types.d.ts +0 -11
  59. package/dist/entities/resource-types.js +0 -1
  60. package/dist/entities/resource.d.ts +0 -42
  61. package/dist/entities/resource.js +0 -303
  62. package/dist/entities/stateful-parameter.d.ts +0 -29
  63. package/dist/entities/stateful-parameter.js +0 -46
  64. package/dist/entities/transform-parameter.d.ts +0 -4
  65. package/dist/entities/transform-parameter.js +0 -2
  66. package/dist/pty/vitest.config.d.ts +0 -2
  67. package/dist/pty/vitest.config.js +0 -11
  68. package/dist/resource/stateful-parameter.d.ts +0 -165
  69. package/dist/resource/stateful-parameter.js +0 -94
  70. package/dist/scripts/deploy.d.ts +0 -1
  71. package/dist/scripts/deploy.js +0 -2
  72. package/dist/test.d.ts +0 -1
  73. package/dist/test.js +0 -5
  74. package/dist/utils/codify-spawn.d.ts +0 -29
  75. package/dist/utils/codify-spawn.js +0 -136
  76. package/dist/utils/internal-utils.d.ts +0 -12
  77. package/dist/utils/internal-utils.js +0 -74
  78. package/dist/utils/load-resources.d.ts +0 -1
  79. package/dist/utils/load-resources.js +0 -46
  80. package/dist/utils/package-json-utils.d.ts +0 -12
  81. package/dist/utils/package-json-utils.js +0 -34
  82. package/dist/utils/spawn-2.d.ts +0 -5
  83. package/dist/utils/spawn-2.js +0 -7
  84. package/dist/utils/spawn.d.ts +0 -29
  85. package/dist/utils/spawn.js +0 -124
  86. package/dist/utils/utils.d.ts +0 -18
  87. package/dist/utils/utils.js +0 -86
package/dist/test.js DELETED
@@ -1,5 +0,0 @@
1
- import { SequentialPty } from './pty/seqeuntial-pty.js';
2
- import { VerbosityLevel } from './utils/verbosity-level.js';
3
- VerbosityLevel.set(1);
4
- const $ = new SequentialPty();
5
- await $.spawn('sudo ls', { interactive: true });
@@ -1,29 +0,0 @@
1
- import { SpawnOptions } from 'node:child_process';
2
- export declare enum SpawnStatus {
3
- SUCCESS = "success",
4
- ERROR = "error"
5
- }
6
- export interface SpawnResult {
7
- status: SpawnStatus;
8
- data: string;
9
- }
10
- type CodifySpawnOptions = {
11
- cwd?: string;
12
- throws?: boolean;
13
- requiresRoot?: boolean;
14
- requestsTTY?: 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 codifySpawn(cmd: string, opts?: CodifySpawnOptions): Promise<SpawnResult>;
28
- export declare function isDebug(): boolean;
29
- export {};
@@ -1,136 +0,0 @@
1
- import { Ajv } from 'ajv';
2
- import { MessageCmd, SudoRequestResponseDataSchema } from 'codify-schemas';
3
- import { nanoid } from 'nanoid';
4
- import { spawn } from 'node:child_process';
5
- import stripAnsi from 'strip-ansi';
6
- import { VerbosityLevel } from './utils.js';
7
- import { SudoError } from '../errors.js';
8
- const ajv = new Ajv({
9
- strict: true,
10
- });
11
- const validateSudoRequestResponse = ajv.compile(SudoRequestResponseDataSchema);
12
- export var SpawnStatus;
13
- (function (SpawnStatus) {
14
- SpawnStatus["SUCCESS"] = "success";
15
- SpawnStatus["ERROR"] = "error";
16
- })(SpawnStatus || (SpawnStatus = {}));
17
- /**
18
- *
19
- * @param cmd Command to run. Ex: `rm -rf`
20
- * @param opts Standard options for node spawn. Additional argument:
21
- * throws determines if a shell will throw a JS error. Defaults to true
22
- *
23
- * @see promiseSpawn
24
- * @see spawn
25
- *
26
- * @returns SpawnResult { status: SUCCESS | ERROR; data: string }
27
- */
28
- export async function codifySpawn(cmd, opts) {
29
- const throws = opts?.throws ?? true;
30
- console.log(`Running command: ${cmd}` + (opts?.cwd ? `(${opts?.cwd})` : ''));
31
- try {
32
- // TODO: Need to benchmark the effects of using sh vs zsh for shell.
33
- // Seems like zsh shells run slower
34
- const result = await (opts?.requiresRoot
35
- ? externalSpawnWithSudo(cmd, opts)
36
- : internalSpawn(cmd, opts ?? {}));
37
- if (result.status !== SpawnStatus.SUCCESS) {
38
- throw new Error(result.data);
39
- }
40
- return result;
41
- }
42
- catch (error) {
43
- if (isDebug()) {
44
- console.error(`CodifySpawn error for command ${cmd}`, error);
45
- }
46
- // @ts-ignore
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: String(error),
62
- };
63
- }
64
- }
65
- async function internalSpawn(cmd, opts) {
66
- return new Promise((resolve) => {
67
- const output = [];
68
- // If TERM_PROGRAM=Apple_Terminal is set then ANSI escape characters may be included
69
- // in the response.
70
- const env = { ...process.env, ...opts.env, TERM_PROGRAM: 'codify', COMMAND_MODE: 'unix2003', COLORTERM: 'truecolor' };
71
- const shell = getDefaultShell();
72
- const rcFile = shell === 'zsh' ? '~/.zshrc' : '~/.bashrc';
73
- // Source start up shells to emulate a users environment vs. a non-interactive non-login shell script
74
- // Ignore all stdin
75
- // If tty is requested then we'll need to sleep 1 to avoid race conditions. This is because if the terminal updates async after the tty message is
76
- // displayed then it'll disappear. By adding sleep 1 it'll allow ink.js to finish all the updates before the tty message is shown
77
- const _process = spawn(`source ${rcFile}; ${opts.requestsTTY ? 'sleep 1;' : ''}${cmd}`, [], {
78
- ...opts,
79
- stdio: ['ignore', 'pipe', 'pipe'],
80
- shell,
81
- env
82
- });
83
- const { stdout, stderr, stdin } = _process;
84
- stdout.setEncoding('utf8');
85
- stderr.setEncoding('utf8');
86
- stdout.on('data', (data) => {
87
- output.push(data.toString());
88
- });
89
- stderr.on('data', (data) => {
90
- output.push(data.toString());
91
- });
92
- _process.on('error', (data) => { });
93
- // please node that this is not a full replacement for 'inherit'
94
- // the child process can and will detect if stdout is a pty and change output based on it
95
- // the terminal context is lost & ansi information (coloring) etc will be lost
96
- if (stdout && stderr && VerbosityLevel.get() > 0) {
97
- stdout.pipe(process.stdout);
98
- stderr.pipe(process.stderr);
99
- }
100
- _process.on('close', (code) => {
101
- resolve({
102
- status: code === 0 ? SpawnStatus.SUCCESS : SpawnStatus.ERROR,
103
- data: stripAnsi(output.join('\n')),
104
- });
105
- });
106
- });
107
- }
108
- async function externalSpawnWithSudo(cmd, opts) {
109
- return new Promise((resolve) => {
110
- const requestId = nanoid(8);
111
- const listener = (data) => {
112
- if (data.requestId === requestId) {
113
- process.removeListener('message', listener);
114
- if (!validateSudoRequestResponse(data.data)) {
115
- throw new Error(`Invalid response for sudo request: ${JSON.stringify(validateSudoRequestResponse.errors, null, 2)}`);
116
- }
117
- resolve(data.data);
118
- }
119
- };
120
- process.on('message', listener);
121
- process.send({
122
- cmd: MessageCmd.SUDO_REQUEST,
123
- data: {
124
- command: cmd,
125
- options: opts ?? {},
126
- },
127
- requestId
128
- });
129
- });
130
- }
131
- export function isDebug() {
132
- return process.env.DEBUG != null && process.env.DEBUG.includes('codify'); // TODO: replace with debug library
133
- }
134
- function getDefaultShell() {
135
- return process.platform === 'darwin' ? 'zsh' : 'bash';
136
- }
@@ -1,12 +0,0 @@
1
- import { ResourceConfig, StringIndexedObject } from 'codify-schemas';
2
- export declare function splitUserConfig<T extends StringIndexedObject>(config: ResourceConfig & T): {
3
- parameters: T;
4
- coreParameters: ResourceConfig;
5
- };
6
- export declare function setsEqual(set1: Set<unknown>, set2: Set<unknown>): boolean;
7
- export declare function untildify(pathWithTilde: string): string;
8
- export declare function tildify(pathWithTilde: string): string;
9
- export declare function resolvePathWithVariables(pathWithVariables: string): string;
10
- export declare function addVariablesToPath(pathWithoutVariables: string): string;
11
- export declare function unhome(pathWithHome: string): string;
12
- export declare function areArraysEqual(isElementEqual: ((desired: unknown, current: unknown) => boolean) | undefined, desired: unknown, current: unknown): boolean;
@@ -1,74 +0,0 @@
1
- import os from 'node:os';
2
- import path from 'node:path';
3
- export function splitUserConfig(config) {
4
- const coreParameters = {
5
- type: config.type,
6
- ...(config.name ? { name: config.name } : {}),
7
- ...(config.dependsOn ? { dependsOn: config.dependsOn } : {}),
8
- };
9
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
10
- const { type, name, dependsOn, ...parameters } = config;
11
- return {
12
- parameters: parameters,
13
- coreParameters,
14
- };
15
- }
16
- export function setsEqual(set1, set2) {
17
- return set1.size === set2.size && [...set1].every((v) => set2.has(v));
18
- }
19
- const homeDirectory = os.homedir();
20
- export function untildify(pathWithTilde) {
21
- return homeDirectory ? pathWithTilde.replace(/^~(?=$|\/|\\)/, homeDirectory) : pathWithTilde;
22
- }
23
- export function tildify(pathWithTilde) {
24
- return homeDirectory ? pathWithTilde.replace(homeDirectory, '~') : pathWithTilde;
25
- }
26
- export function resolvePathWithVariables(pathWithVariables) {
27
- // @ts-expect-error Ignore this for now
28
- return pathWithVariables.replace(/\$([A-Z_]+[A-Z0-9_]*)|\${([A-Z0-9_]*)}/ig, (_, a, b) => process.env[a || b]);
29
- }
30
- export function addVariablesToPath(pathWithoutVariables) {
31
- let result = pathWithoutVariables;
32
- for (const [key, value] of Object.entries(process.env)) {
33
- if (!value || !path.isAbsolute(value) || value === '/' || key === 'HOME' || key === 'PATH' || key === 'SHELL' || key === 'PWD') {
34
- continue;
35
- }
36
- result = result.replaceAll(value, `$${key}`);
37
- }
38
- return result;
39
- }
40
- export function unhome(pathWithHome) {
41
- return pathWithHome.includes('$HOME') ? pathWithHome.replaceAll('$HOME', os.homedir()) : pathWithHome;
42
- }
43
- export function areArraysEqual(isElementEqual, desired, current) {
44
- if (!desired || !current) {
45
- return false;
46
- }
47
- if (!Array.isArray(desired) || !Array.isArray(current)) {
48
- throw new Error(`A non-array value:
49
-
50
- Desired: ${JSON.stringify(desired, null, 2)}
51
-
52
- Current: ${JSON.stringify(desired, null, 2)}
53
-
54
- Was provided even though type array was specified.
55
- `);
56
- }
57
- if (desired.length !== current.length) {
58
- return false;
59
- }
60
- const desiredCopy = [...desired];
61
- const currentCopy = [...current];
62
- // Algorithm for to check equality between two un-ordered; un-hashable arrays using
63
- // an isElementEqual method. Time: O(n^2)
64
- for (let counter = desiredCopy.length - 1; counter >= 0; counter--) {
65
- const idx = currentCopy.findIndex((e2) => (isElementEqual
66
- ?? ((a, b) => a === b))(desiredCopy[counter], e2));
67
- if (idx === -1) {
68
- return false;
69
- }
70
- desiredCopy.splice(counter, 1);
71
- currentCopy.splice(idx, 1);
72
- }
73
- return currentCopy.length === 0;
74
- }
@@ -1 +0,0 @@
1
- export declare const listAllResources: (root?: string) => Promise<string[]>;
@@ -1,46 +0,0 @@
1
- import fs from 'node:fs/promises';
2
- import path from 'node:path';
3
- import * as url from 'node:url';
4
- export const listAllResources = async (root = path.join(path.dirname(url.fileURLToPath(import.meta.url)), '..', '..', '..', '..')) => {
5
- console.log('Dirname', root);
6
- const resourcesPath = path.join(root, 'src', 'resources');
7
- const resourceDir = await fs.readdir(resourcesPath);
8
- const dedupSet = new Set();
9
- const result = new Set();
10
- for (const folder of resourceDir) {
11
- if (await fs.stat(path.join(resourcesPath, folder)).then(s => s.isDirectory()).catch(() => false)) {
12
- for (const folderContents of await fs.readdir(path.join(resourcesPath, folder))) {
13
- const isDirectory = await fs.stat(path.join(resourcesPath, folder, folderContents)).then(s => s.isDirectory());
14
- // console.log(folderContents, isDirectory);
15
- if (isDirectory) {
16
- for (const innerContents of await fs.readdir(path.join(resourcesPath, folder, folderContents))) {
17
- if (!dedupSet.has(path.join(resourcesPath, folder, folderContents))) {
18
- dedupSet.add(path.join(resourcesPath, folder, folderContents));
19
- addResourceFromDir(path.join(resourcesPath, folder, folderContents), result);
20
- }
21
- }
22
- }
23
- else {
24
- if (!dedupSet.has(path.join(resourcesPath, folder))) {
25
- dedupSet.add(path.join(resourcesPath, folder));
26
- addResourceFromDir(path.join(resourcesPath, folder), result);
27
- }
28
- }
29
- }
30
- }
31
- else {
32
- throw new Error('Only directories are allowed in resources folder');
33
- }
34
- }
35
- return [...result];
36
- };
37
- function addResourceFromDir(dir, result) {
38
- try {
39
- const resourceFile = path.resolve(path.join(dir, 'resource.ts'));
40
- if (!(fs.stat(resourceFile).then((s) => s.isFile())).catch(() => false)) {
41
- return;
42
- }
43
- result.add(resourceFile);
44
- }
45
- catch { }
46
- }
@@ -1,12 +0,0 @@
1
- /**
2
- * Find the nearest package.json starting from a directory and walking upward.
3
- * @param {string} startDir - Directory to start searching from
4
- * @returns {string|null} Absolute path to package.json or null if not found
5
- */
6
- export declare function findNearestPackageJson(startDir?: string): string | null;
7
- /**
8
- * Read and parse the nearest package.json
9
- * @param {string} startDir
10
- * @returns {object|null}
11
- */
12
- export declare function readNearestPackageJson(startDir?: string): any;
@@ -1,34 +0,0 @@
1
- import * as fs from 'node:fs';
2
- import path from 'node:path';
3
- /**
4
- * Find the nearest package.json starting from a directory and walking upward.
5
- * @param {string} startDir - Directory to start searching from
6
- * @returns {string|null} Absolute path to package.json or null if not found
7
- */
8
- export function findNearestPackageJson(startDir = process.cwd()) {
9
- let currentDir = path.resolve(startDir);
10
- while (true) {
11
- const pkgPath = path.join(currentDir, "package.json");
12
- if (fs.existsSync(pkgPath)) {
13
- return pkgPath;
14
- }
15
- const parentDir = path.dirname(currentDir);
16
- if (parentDir === currentDir) {
17
- // Reached filesystem root
18
- return null;
19
- }
20
- currentDir = parentDir;
21
- }
22
- }
23
- /**
24
- * Read and parse the nearest package.json
25
- * @param {string} startDir
26
- * @returns {object|null}
27
- */
28
- export function readNearestPackageJson(startDir = process.cwd()) {
29
- const pkgPath = findNearestPackageJson(startDir);
30
- if (!pkgPath)
31
- return null;
32
- const contents = fs.readFileSync(pkgPath, 'utf8');
33
- return JSON.parse(contents);
34
- }
@@ -1,5 +0,0 @@
1
- import { Shell } from 'zx';
2
- export declare class ShellContext implements Shell {
3
- zx: Shell;
4
- static create(): ShellContext;
5
- }
@@ -1,7 +0,0 @@
1
- import { $ } from 'zx';
2
- export class ShellContext {
3
- zx = $({ shell: true });
4
- static create() {
5
- return new ShellContext();
6
- }
7
- }
@@ -1,29 +0,0 @@
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 {};
@@ -1,124 +0,0 @@
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
- }
@@ -1,18 +0,0 @@
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;
@@ -1,86 +0,0 @@
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
- }