codify-plugin-lib 1.0.182-beta25 → 1.0.182-beta27

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.
@@ -10,8 +10,8 @@ export declare class BackgroundPty implements IPty {
10
10
  private basePty;
11
11
  private promiseQueue;
12
12
  constructor();
13
- spawn(cmd: string, options?: SpawnOptions): Promise<SpawnResult>;
14
- spawnSafe(cmd: string, options?: SpawnOptions): Promise<SpawnResult>;
13
+ spawn(cmd: string | string[], options?: SpawnOptions): Promise<SpawnResult>;
14
+ spawnSafe(cmd: string | string[], options?: SpawnOptions): Promise<SpawnResult>;
15
15
  kill(): Promise<{
16
16
  exitCode: number;
17
17
  signal?: number | undefined;
@@ -30,11 +30,12 @@ export class BackgroundPty {
30
30
  async spawn(cmd, options) {
31
31
  const spawnResult = await this.spawnSafe(cmd, options);
32
32
  if (spawnResult.status !== 'success') {
33
- throw new SpawnError(cmd, spawnResult.exitCode, spawnResult.data);
33
+ throw new SpawnError(Array.isArray(cmd) ? cmd.join('\n') : cmd, spawnResult.exitCode, spawnResult.data);
34
34
  }
35
35
  return spawnResult;
36
36
  }
37
37
  async spawnSafe(cmd, options) {
38
+ cmd = Array.isArray(cmd) ? cmd.join('\n') : cmd;
38
39
  // cid is command id
39
40
  const cid = nanoid(10);
40
41
  debugLog(cid);
@@ -36,8 +36,8 @@ export declare class SpawnError extends Error {
36
36
  constructor(cmd: string, exitCode: number, data: string);
37
37
  }
38
38
  export interface IPty {
39
- spawn(cmd: string, options?: SpawnOptions): Promise<SpawnResult>;
40
- spawnSafe(cmd: string, options?: SpawnOptions): Promise<SpawnResult>;
39
+ spawn(cmd: string | string[], options?: SpawnOptions): Promise<SpawnResult>;
40
+ spawnSafe(cmd: string | string[], options?: SpawnOptions): Promise<SpawnResult>;
41
41
  kill(): Promise<{
42
42
  exitCode: number;
43
43
  signal?: number | undefined;
@@ -6,8 +6,8 @@ import { IPty, SpawnOptions, SpawnResult } from './index.js';
6
6
  * without a tty (or even a stdin) attached so interactive commands will not work.
7
7
  */
8
8
  export declare class SequentialPty implements IPty {
9
- spawn(cmd: string, options?: SpawnOptions): Promise<SpawnResult>;
10
- spawnSafe(cmd: string, options?: SpawnOptions): Promise<SpawnResult>;
9
+ spawn(cmd: string | string[], options?: SpawnOptions): Promise<SpawnResult>;
10
+ spawnSafe(cmd: string | string[], options?: SpawnOptions): Promise<SpawnResult>;
11
11
  kill(): Promise<{
12
12
  exitCode: number;
13
13
  signal?: number | undefined;
@@ -22,11 +22,12 @@ export class SequentialPty {
22
22
  async spawn(cmd, options) {
23
23
  const spawnResult = await this.spawnSafe(cmd, options);
24
24
  if (spawnResult.status !== 'success') {
25
- throw new SpawnError(cmd, spawnResult.exitCode, spawnResult.data);
25
+ throw new SpawnError(Array.isArray(cmd) ? cmd.join('\n') : cmd, spawnResult.exitCode, spawnResult.data);
26
26
  }
27
27
  return spawnResult;
28
28
  }
29
29
  async spawnSafe(cmd, options) {
30
+ cmd = Array.isArray(cmd) ? cmd.join(' ') : cmd;
30
31
  if (cmd.includes('sudo')) {
31
32
  throw new Error('Do not directly use sudo. Use the option { requiresRoot: true } instead');
32
33
  }
@@ -34,7 +35,7 @@ export class SequentialPty {
34
35
  if (options?.stdin || options?.requiresRoot) {
35
36
  return this.externalSpawn(cmd, options);
36
37
  }
37
- console.log(`Running command: ${cmd}` + (options?.cwd ? `(${options?.cwd})` : ''));
38
+ console.log(`Running command: ${Array.isArray(cmd) ? cmd.join('\n') : cmd}` + (options?.cwd ? `(${options?.cwd})` : ''));
38
39
  return new Promise((resolve) => {
39
40
  const output = [];
40
41
  const historyIgnore = Utils.getShell() === Shell.ZSH ? { HISTORY_IGNORE: '*' } : { HISTIGNORE: '*' };
@@ -25,7 +25,6 @@ export function tildify(pathWithTilde) {
25
25
  return homeDirectory ? pathWithTilde.replace(homeDirectory, '~') : pathWithTilde;
26
26
  }
27
27
  export function resolvePathWithVariables(pathWithVariables) {
28
- // @ts-expect-error Ignore this for now
29
28
  return pathWithVariables.replace(/\$([A-Z_]+[A-Z0-9_]*)|\${([A-Z0-9_]*)}/ig, (_, a, b) => process.env[a || b]);
30
29
  }
31
30
  export function addVariablesToPath(pathWithoutVariables) {
@@ -20,6 +20,9 @@ export declare const Utils: {
20
20
  };
21
21
  isMacOS(): boolean;
22
22
  isLinux(): boolean;
23
+ isArmArch(): Promise<boolean>;
24
+ isHomebrewInstalled(): Promise<boolean>;
25
+ isRosetta2Installed(): Promise<boolean>;
23
26
  getShell(): Shell | undefined;
24
27
  getPrimaryShellRc(): string;
25
28
  getShellRcFiles(): string[];
@@ -1,6 +1,6 @@
1
1
  import os from 'node:os';
2
2
  import path from 'node:path';
3
- import { getPty } from '../pty/index.js';
3
+ import { getPty, SpawnStatus } from '../pty/index.js';
4
4
  export function isDebug() {
5
5
  return process.env.DEBUG != null && process.env.DEBUG.includes('codify'); // TODO: replace with debug library
6
6
  }
@@ -29,6 +29,29 @@ export const Utils = {
29
29
  isLinux() {
30
30
  return os.platform() === 'linux';
31
31
  },
32
+ async isArmArch() {
33
+ const $ = getPty();
34
+ if (!Utils.isMacOS()) {
35
+ // On Linux, check uname -m
36
+ const query = await $.spawn('uname -m');
37
+ return query.data.trim() === 'aarch64' || query.data.trim() === 'arm64';
38
+ }
39
+ const query = await $.spawn('sysctl -n machdep.cpu.brand_string');
40
+ return /M(\d)/.test(query.data);
41
+ },
42
+ async isHomebrewInstalled() {
43
+ const $ = getPty();
44
+ const query = await $.spawnSafe('which brew', { interactive: true });
45
+ return query.status === SpawnStatus.SUCCESS;
46
+ },
47
+ async isRosetta2Installed() {
48
+ if (!Utils.isMacOS()) {
49
+ return false;
50
+ }
51
+ const $ = getPty();
52
+ const query = await $.spawnSafe('arch -x86_64 /usr/bin/true 2> /dev/null', { interactive: true });
53
+ return query.status === SpawnStatus.SUCCESS;
54
+ },
32
55
  getShell() {
33
56
  const shell = process.env.SHELL || '';
34
57
  if (shell.endsWith('bash')) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "codify-plugin-lib",
3
- "version": "1.0.182-beta25",
3
+ "version": "1.0.182-beta27",
4
4
  "description": "Library plugin library",
5
5
  "main": "dist/index.js",
6
6
  "typings": "dist/index.d.ts",
@@ -33,17 +33,19 @@ export class BackgroundPty implements IPty {
33
33
  this.initialize();
34
34
  }
35
35
 
36
- async spawn(cmd: string, options?: SpawnOptions): Promise<SpawnResult> {
36
+ async spawn(cmd: string | string[], options?: SpawnOptions): Promise<SpawnResult> {
37
37
  const spawnResult = await this.spawnSafe(cmd, options);
38
38
 
39
39
  if (spawnResult.status !== 'success') {
40
- throw new SpawnError(cmd, spawnResult.exitCode, spawnResult.data);
40
+ throw new SpawnError(Array.isArray(cmd) ? cmd.join('\n') : cmd, spawnResult.exitCode, spawnResult.data);
41
41
  }
42
42
 
43
43
  return spawnResult;
44
44
  }
45
45
 
46
- async spawnSafe(cmd: string, options?: SpawnOptions): Promise<SpawnResult> {
46
+ async spawnSafe(cmd: string | string[], options?: SpawnOptions): Promise<SpawnResult> {
47
+ cmd = Array.isArray(cmd) ? cmd.join('\n') : cmd;
48
+
47
49
  // cid is command id
48
50
  const cid = nanoid(10);
49
51
  debugLog(cid);
package/src/pty/index.ts CHANGED
@@ -50,9 +50,9 @@ export class SpawnError extends Error {
50
50
  }
51
51
 
52
52
  export interface IPty {
53
- spawn(cmd: string, options?: SpawnOptions): Promise<SpawnResult>
53
+ spawn(cmd: string | string[], options?: SpawnOptions): Promise<SpawnResult>
54
54
 
55
- spawnSafe(cmd: string, options?: SpawnOptions): Promise<SpawnResult>
55
+ spawnSafe(cmd: string | string[], options?: SpawnOptions): Promise<SpawnResult>
56
56
 
57
57
  kill(): Promise<{ exitCode: number, signal?: number | undefined }>
58
58
  }
@@ -23,17 +23,19 @@ const validateSudoRequestResponse = ajv.compile(CommandRequestResponseDataSchema
23
23
  * without a tty (or even a stdin) attached so interactive commands will not work.
24
24
  */
25
25
  export class SequentialPty implements IPty {
26
- async spawn(cmd: string, options?: SpawnOptions): Promise<SpawnResult> {
26
+ async spawn(cmd: string | string[], options?: SpawnOptions): Promise<SpawnResult> {
27
27
  const spawnResult = await this.spawnSafe(cmd, options);
28
28
 
29
29
  if (spawnResult.status !== 'success') {
30
- throw new SpawnError(cmd, spawnResult.exitCode, spawnResult.data);
30
+ throw new SpawnError(Array.isArray(cmd) ? cmd.join('\n') : cmd, spawnResult.exitCode, spawnResult.data);
31
31
  }
32
32
 
33
33
  return spawnResult;
34
34
  }
35
35
 
36
- async spawnSafe(cmd: string, options?: SpawnOptions): Promise<SpawnResult> {
36
+ async spawnSafe(cmd: string | string[], options?: SpawnOptions): Promise<SpawnResult> {
37
+ cmd = Array.isArray(cmd) ? cmd.join(' ') : cmd;
38
+
37
39
  if (cmd.includes('sudo')) {
38
40
  throw new Error('Do not directly use sudo. Use the option { requiresRoot: true } instead')
39
41
  }
@@ -43,7 +45,7 @@ export class SequentialPty implements IPty {
43
45
  return this.externalSpawn(cmd, options);
44
46
  }
45
47
 
46
- console.log(`Running command: ${cmd}` + (options?.cwd ? `(${options?.cwd})` : ''))
48
+ console.log(`Running command: ${Array.isArray(cmd) ? cmd.join('\n') : cmd}` + (options?.cwd ? `(${options?.cwd})` : ''))
47
49
 
48
50
  return new Promise((resolve) => {
49
51
  const output: string[] = [];
@@ -36,8 +36,7 @@ export function tildify(pathWithTilde: string) {
36
36
  }
37
37
 
38
38
  export function resolvePathWithVariables(pathWithVariables: string) {
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])
39
+ return pathWithVariables.replace(/\$([A-Z_]+[A-Z0-9_]*)|\${([A-Z0-9_]*)}/ig, (_, a, b) => process.env[a || b]!)
41
40
  }
42
41
 
43
42
  export function addVariablesToPath(pathWithoutVariables: string) {
@@ -1,7 +1,8 @@
1
1
  import { OS } from 'codify-schemas';
2
2
  import os from 'node:os';
3
3
  import path from 'node:path';
4
- import { getPty } from '../pty/index.js';
4
+
5
+ import { getPty, SpawnStatus } from '../pty/index.js';
5
6
 
6
7
  export function isDebug(): boolean {
7
8
  return process.env.DEBUG != null && process.env.DEBUG.includes('codify'); // TODO: replace with debug library
@@ -41,6 +42,34 @@ export const Utils = {
41
42
  return os.platform() === 'linux';
42
43
  },
43
44
 
45
+ async isArmArch(): Promise<boolean> {
46
+ const $ = getPty();
47
+ if (!Utils.isMacOS()) {
48
+ // On Linux, check uname -m
49
+ const query = await $.spawn('uname -m');
50
+ return query.data.trim() === 'aarch64' || query.data.trim() === 'arm64';
51
+ }
52
+
53
+ const query = await $.spawn('sysctl -n machdep.cpu.brand_string');
54
+ return /M(\d)/.test(query.data);
55
+ },
56
+
57
+ async isHomebrewInstalled(): Promise<boolean> {
58
+ const $ = getPty();
59
+ const query = await $.spawnSafe('which brew', { interactive: true });
60
+ return query.status === SpawnStatus.SUCCESS;
61
+ },
62
+
63
+ async isRosetta2Installed(): Promise<boolean> {
64
+ if (!Utils.isMacOS()) {
65
+ return false;
66
+ }
67
+
68
+ const $ = getPty();
69
+ const query = await $.spawnSafe('arch -x86_64 /usr/bin/true 2> /dev/null', { interactive: true });
70
+ return query.status === SpawnStatus.SUCCESS;
71
+ },
72
+
44
73
  getShell(): Shell | undefined {
45
74
  const shell = process.env.SHELL || '';
46
75