build-strap 6.1.0-main.172 → 6.1.0-main.173

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "build-strap",
3
- "version": "6.1.0-main.172",
3
+ "version": "6.1.0-main.173",
4
4
  "description": "Node scripts for building things",
5
5
  "license": "MIT",
6
6
  "author": "Justin Murray <justin@murrayju.com>",
package/src/cp.js CHANGED
@@ -61,7 +61,11 @@ export async function spawn(command, args, opts) {
61
61
  }
62
62
  };
63
63
  p.on('close', handleExit);
64
- p.on('exit', handleExit);
64
+ // 'exit' can occur before the stdio streams are fully read. When we
65
+ // capture output, wait for 'close' so that no output is lost.
66
+ if (!captureOutput) {
67
+ p.on('exit', handleExit);
68
+ }
65
69
  // only fires if we failed to spawn
66
70
  p.on('error', (err) => {
67
71
  // Here we have a workaround that reverses a "feature" of cross-spawn on Windows. See:
@@ -39,7 +39,7 @@ interface DockerContainerLsOptions {
39
39
  filter?: (container: DockerContainer) => boolean;
40
40
  }
41
41
  export declare function unthrottledDockerContainerLs({ all, filter, }?: DockerContainerLsOptions): Promise<DockerContainer[]>;
42
- export declare const dockerContainerLs: (options: DockerContainerLsOptions | undefined) => Promise<DockerContainer[]> | undefined;
42
+ export declare const dockerContainerLs: typeof unthrottledDockerContainerLs;
43
43
  export declare function dockerContainerFind(search: string, options?: DockerContainerLsOptions): Promise<DockerContainer | null>;
44
44
  export declare function dockerContainerStop(id: string | string[], ignoreErrors?: boolean): Promise<void>;
45
45
  export declare function dockerContainerKill(id: string | string[], ignoreErrors?: boolean): Promise<void>;
@@ -48,7 +48,7 @@ export declare function dockerContainerRm(id: string | string[], ignoreErrors?:
48
48
  export declare function dockerContainerRestart(id: string | string[]): Promise<void>;
49
49
  export declare function dockerContainerStart(id: string | string[]): Promise<void>;
50
50
  export declare function unthrottledDockerContainerInspect(id: string | string[]): Promise<DockerContainerInspectOutput[]>;
51
- export declare const dockerContainerInspect: (id: string | string[]) => Promise<DockerContainerInspectOutput[]> | undefined;
51
+ export declare const dockerContainerInspect: typeof unthrottledDockerContainerInspect;
52
52
  interface DockerContainerRunDaemonArgs {
53
53
  cmd?: string[];
54
54
  image: string;
@@ -1,10 +1,7 @@
1
1
  import bytes from 'bytes';
2
- import { throttle } from 'lodash-es';
3
2
  import { spawn } from './cp.js';
4
3
  import { parseDockerDate } from './docker.js';
5
4
  import { buildLog, errorMessage } from './run.js';
6
- // calling this function in rapid succession can lead to errors.
7
- // prefer throttled version
8
5
  export async function unthrottledDockerContainerLs({ all, filter, } = {}) {
9
6
  return (await spawn('docker', [
10
7
  'container',
@@ -34,10 +31,10 @@ export async function unthrottledDockerContainerLs({ all, filter, } = {}) {
34
31
  exited: status.startsWith('Exited'),
35
32
  id,
36
33
  image,
37
- inspect: async () => (await dockerContainerInspect(id))?.[0],
34
+ inspect: async () => (await dockerContainerInspect(id)).at(0),
38
35
  async isRunning() {
39
36
  try {
40
- return (await this.inspect())?.State?.Running || false;
37
+ return (await this.inspect())?.State.Running || false;
41
38
  }
42
39
  catch {
43
40
  return false;
@@ -65,7 +62,10 @@ export async function unthrottledDockerContainerLs({ all, filter, } = {}) {
65
62
  status,
66
63
  stop: async (ignoreError = true) => dockerContainerStop(id, ignoreError),
67
64
  async teardown(verbose = true) {
68
- const log = (msg) => verbose && buildLog(msg);
65
+ const log = (msg) => {
66
+ if (verbose)
67
+ buildLog(msg);
68
+ };
69
69
  if (await this.isRunning()) {
70
70
  try {
71
71
  log(`Stopping container: <${this.name}>...`);
@@ -98,11 +98,10 @@ export async function unthrottledDockerContainerLs({ all, filter, } = {}) {
98
98
  })
99
99
  .filter((c) => c.id && (typeof filter === 'function' ? filter(c) : true));
100
100
  }
101
- export const dockerContainerLs = throttle(unthrottledDockerContainerLs, 500, {
102
- trailing: false,
103
- });
101
+ // The two names are the same function. Both stay exported for compatibility.
102
+ export const dockerContainerLs = unthrottledDockerContainerLs;
104
103
  export async function dockerContainerFind(search, options) {
105
- return ((await dockerContainerLs(options))?.find((c) => c.name === search ||
104
+ return ((await dockerContainerLs(options)).find((c) => c.name === search ||
106
105
  c.id.startsWith(search) ||
107
106
  c.names.includes(search)) || null);
108
107
  }
@@ -168,14 +167,13 @@ export async function dockerContainerStart(id) {
168
167
  }
169
168
  export async function unthrottledDockerContainerInspect(id) {
170
169
  const ids = Array.isArray(id) ? id : [id];
171
- return ((await spawn('docker', ['container', 'inspect', '--format', '{{json .}}', ...ids], { captureOutput: true })).output
170
+ return (await spawn('docker', ['container', 'inspect', '--format', '{{json .}}', ...ids], { captureOutput: true })).output
172
171
  .split('\n')
173
172
  .filter((line) => !!line.trim())
174
- .map((line) => JSON.parse(line.trim())) || []);
173
+ .map((line) => JSON.parse(line.trim()));
175
174
  }
176
- export const dockerContainerInspect = throttle(unthrottledDockerContainerInspect, 500, {
177
- trailing: false,
178
- });
175
+ // The two names are the same function. Both stay exported for compatibility.
176
+ export const dockerContainerInspect = unthrottledDockerContainerInspect;
179
177
  export async function dockerContainerRun({ cmd = [], image, runArgs = [], spawnOptions, }) {
180
178
  return (await spawn('docker', ['container', 'run', ...runArgs, image, ...cmd], {
181
179
  pipeOutput: true,
package/src/docker.d.ts CHANGED
@@ -5,7 +5,7 @@ export interface DockerConfig {
5
5
  }
6
6
  export declare function getDockerConfig(): DockerConfig;
7
7
  export declare const parseDockerDate: (date: string) => Date;
8
- export declare function dockerBuild(tags?: string[], buildArgs?: string[], target?: string | null, extraArgs?: string[], repo?: string, dockerFile?: string, workDir?: string): Promise<string>;
8
+ export declare function dockerBuild(tags?: string[], buildArgs?: string[], target?: string | null, extraArgs?: null | string[], repo?: string, dockerFile?: string, workDir?: string): Promise<string>;
9
9
  export declare function dockerTag(imageId: string, tags?: string[], repo?: string): Promise<void>;
10
10
  /**
11
11
  * Apply the standard convention for tagging the docker image for the project,
package/src/docker.js CHANGED
@@ -72,7 +72,8 @@ export async function dockerImages(repo = getDockerRepo(), filter = null) {
72
72
  tag,
73
73
  };
74
74
  })
75
- .filter((m) => m?.id != null && (typeof filter === 'function' ? filter(m) : true));
75
+ .filter((m) => m.id != null)
76
+ .filter((m) => (typeof filter === 'function' ? filter(m) : true));
76
77
  }
77
78
  export async function getDockerId(tag = 'latest', repo = null) {
78
79
  return (await dockerImages(repo, (m) => m.tag === tag)).map((m) => m.id)[0];
@@ -274,7 +275,7 @@ export const ensureDockerForMacConfigured = async (desiredConfig) => {
274
275
  if (!(await fs.pathExists(configPath))) {
275
276
  throw new Error('Failed to locate the Docker config file');
276
277
  }
277
- const existingConfig = await fs.readJson(configPath);
278
+ const existingConfig = (await fs.readJson(configPath));
278
279
  if (!Object.entries(desiredConfig).every(([key, value]) => existingConfig[key] === value)) {
279
280
  buildLog('Adjusting Docker config...');
280
281
  await fs.writeJson(configPath, {
@@ -13,7 +13,7 @@ interface DockerNetworkLsOptions {
13
13
  filter?: (network: DockerNetwork) => boolean;
14
14
  }
15
15
  export declare function unthrottledDockerNetworkLs({ filter, }?: DockerNetworkLsOptions): Promise<DockerNetwork[]>;
16
- export declare const dockerNetworkLs: (options?: DockerNetworkLsOptions) => Promise<DockerNetwork[]> | undefined;
16
+ export declare const dockerNetworkLs: typeof unthrottledDockerNetworkLs;
17
17
  export declare function dockerNetworkFind(networkName: string, options?: DockerNetworkLsOptions): Promise<DockerNetwork | null>;
18
18
  export interface DockerNetworkCreateOptions {
19
19
  auxAddresses?: string[];
@@ -1,8 +1,5 @@
1
- import { throttle } from 'lodash-es';
2
1
  import { spawn } from './cp.js';
3
2
  import { parseDockerDate } from './docker.js';
4
- // calling this function in rapid succession can lead to errors.
5
- // prefer throttled version
6
3
  export async function unthrottledDockerNetworkLs({ filter, } = {}) {
7
4
  return (await spawn('docker', ['network', 'ls', '--format', '{{json .}}'], {
8
5
  captureOutput: true,
@@ -25,11 +22,10 @@ export async function unthrottledDockerNetworkLs({ filter, } = {}) {
25
22
  })
26
23
  .filter((n) => n.id && (typeof filter === 'function' ? filter(n) : true));
27
24
  }
28
- export const dockerNetworkLs = throttle(unthrottledDockerNetworkLs, 500, {
29
- trailing: false,
30
- });
25
+ // The two names are the same function. Both stay exported for compatibility.
26
+ export const dockerNetworkLs = unthrottledDockerNetworkLs;
31
27
  export async function dockerNetworkFind(networkName, options) {
32
- return ((await dockerNetworkLs(options))?.find((n) => n.name === networkName || n.id === networkName) || null);
28
+ return ((await dockerNetworkLs(options)).find((n) => n.name === networkName || n.id === networkName) || null);
33
29
  }
34
30
  export async function dockerNetworkCreate(networkName, { auxAddresses = [], driver, driverOpts = {}, gateways = [], ingress, internal, ipRange, ipv6, labels = [], subnets = [], } = {}) {
35
31
  const existing = await dockerNetworkFind(networkName);
@@ -12,7 +12,7 @@ interface DockerVolumeLsOptions {
12
12
  filter?: (vol: DockerVolume) => boolean;
13
13
  }
14
14
  export declare function unthrottledDockerVolumeLs({ filter, }?: DockerVolumeLsOptions): Promise<DockerVolume[]>;
15
- export declare const dockerVolumeLs: (options?: DockerVolumeLsOptions) => undefined | Promise<DockerVolume[]>;
15
+ export declare const dockerVolumeLs: typeof unthrottledDockerVolumeLs;
16
16
  export declare function dockerVolumeFind(search: string, options?: DockerVolumeLsOptions): Promise<null | DockerVolume>;
17
17
  export interface DockerVolumeCreateOptions {
18
18
  driver?: string;
@@ -22,5 +22,5 @@ export interface DockerVolumeCreateOptions {
22
22
  export declare function dockerVolumeCreate(name: string, { driver, driverOpts, labels }?: DockerVolumeCreateOptions): Promise<null | DockerVolume>;
23
23
  export declare function dockerVolumeRm(id: string | string[], ignoreErrors?: boolean): Promise<void>;
24
24
  export declare function unthrottledDockerVolumeInspect(id: string | string[]): Promise<DockerVolumeInspectOutput[]>;
25
- export declare const dockerVolumeInspect: (id: string | string[]) => undefined | Promise<DockerVolumeInspectOutput[]>;
25
+ export declare const dockerVolumeInspect: typeof unthrottledDockerVolumeInspect;
26
26
  export {};
@@ -1,8 +1,5 @@
1
- import { throttle } from 'lodash-es';
2
1
  import { spawn } from './cp.js';
3
2
  import { errorMessage } from './run.js';
4
- // calling this function in rapid succession can lead to errors.
5
- // prefer throttled version
6
3
  export async function unthrottledDockerVolumeLs({ filter, } = {}) {
7
4
  return (await spawn('docker', ['volume', 'ls', '--format', '{{json .}}'], {
8
5
  captureOutput: true,
@@ -13,7 +10,7 @@ export async function unthrottledDockerVolumeLs({ filter, } = {}) {
13
10
  const { Driver: driver, Labels, Mountpoint: mountPoint, Name: name, Scope: scope, } = JSON.parse(line.trim());
14
11
  return {
15
12
  driver,
16
- inspect: async () => (await dockerVolumeInspect(name))?.[0] || null,
13
+ inspect: async () => (await dockerVolumeInspect(name)).at(0) || null,
17
14
  labels: Labels.split(',').map((l) => l.trim()),
18
15
  mountPoint,
19
16
  name,
@@ -23,11 +20,10 @@ export async function unthrottledDockerVolumeLs({ filter, } = {}) {
23
20
  })
24
21
  .filter((v) => v.name && (typeof filter === 'function' ? filter(v) : true));
25
22
  }
26
- export const dockerVolumeLs = throttle(unthrottledDockerVolumeLs, 500, {
27
- trailing: false,
28
- });
23
+ // The two names are the same function. Both stay exported for compatibility.
24
+ export const dockerVolumeLs = unthrottledDockerVolumeLs;
29
25
  export async function dockerVolumeFind(search, options) {
30
- return ((await dockerVolumeLs(options))?.find((v) => v.name === search || v.name.startsWith(search)) ?? null);
26
+ return ((await dockerVolumeLs(options)).find((v) => v.name === search || v.name.startsWith(search)) ?? null);
31
27
  }
32
28
  export async function dockerVolumeCreate(name, { driver, driverOpts = {}, labels = [] } = {}) {
33
29
  const existing = await dockerVolumeFind(name);
@@ -56,10 +52,13 @@ export async function dockerVolumeRm(id, ignoreErrors = true) {
56
52
  }
57
53
  }
58
54
  }
59
- // calling this function in rapid succession can lead to errors.
60
- // prefer throttled version
61
55
  export async function unthrottledDockerVolumeInspect(id) {
62
56
  const ids = Array.isArray(id) ? id : [id];
63
- return (JSON.parse((await spawn('docker', ['volume', 'inspect', '--format', '{{json .}}', ...ids], { captureOutput: true })).output.trim()) || []);
57
+ // With --format, docker writes one JSON object per line, not an array
58
+ return (await spawn('docker', ['volume', 'inspect', '--format', '{{json .}}', ...ids], { captureOutput: true })).output
59
+ .split('\n')
60
+ .filter((line) => !!line.trim())
61
+ .map((line) => JSON.parse(line.trim()));
64
62
  }
65
- export const dockerVolumeInspect = throttle(unthrottledDockerVolumeInspect, 500, { trailing: true });
63
+ // The two names are the same function. Both stay exported for compatibility.
64
+ export const dockerVolumeInspect = unthrottledDockerVolumeInspect;
@@ -12,9 +12,7 @@ import { buildLog } from './run.js';
12
12
  async function flatten(input) {
13
13
  const result = await input;
14
14
  return Array.isArray(result)
15
- ? [].concat(
16
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
17
- ...(await Promise.all(result.map(flatten))))
15
+ ? [].concat(...(await Promise.all(result.map(flatten))))
18
16
  : result;
19
17
  }
20
18
  /**
@@ -26,7 +24,7 @@ export const dockerContainerCleanup = async ({ dryRun = process.argv.includes('-
26
24
  filter: (c) => c.exited,
27
25
  });
28
26
  if (dryRun) {
29
- if (toClean) {
27
+ if (toClean.length) {
30
28
  buildLog(`Containers to delete (dry run):\n ${toClean
31
29
  .map((c) => c.id)
32
30
  .join('\n ')}`);
@@ -35,7 +33,7 @@ export const dockerContainerCleanup = async ({ dryRun = process.argv.includes('-
35
33
  buildLog('No containers to delete (dry run)');
36
34
  }
37
35
  }
38
- else if (toClean) {
36
+ else {
39
37
  await Promise.all(toClean.map(async (c) => c.rm(true)));
40
38
  }
41
39
  };
@@ -33,10 +33,10 @@ interface DockerComposeNetworkDef extends DockerNetworkCreateOptions {
33
33
  name?: string;
34
34
  }
35
35
  interface DockerCompose {
36
- networks?: Record<string, DockerComposeNetworkDef>;
36
+ networks?: Record<string, null | DockerComposeNetworkDef>;
37
37
  services?: Record<string, DockerComposeServiceDef>;
38
38
  version: string;
39
- volumes?: Record<string, DockerComposeVolumeDef>;
39
+ volumes?: Record<string, null | DockerComposeVolumeDef>;
40
40
  }
41
41
  /**
42
42
  * Parse a docker-compose.yml file into a pojo representation
@@ -84,7 +84,7 @@ const parseVolumes = async (volCfg = [], nameSuffix = '', dockerCompose = null)
84
84
  };
85
85
  const parseNetworks = async (netCfg = [], dockerCompose = null) => {
86
86
  const { networks: netMap } = await dockerComposeResolve(dockerCompose);
87
- const networks = netCfg.map((n) => netMap?.[n].name || prefixName(n));
87
+ const networks = netCfg.map((n) => netMap?.[n]?.name || prefixName(n));
88
88
  return {
89
89
  networks,
90
90
  runArgs: networks.flatMap((n) => ['--network', n]),
@@ -95,7 +95,7 @@ export const dockerComposeCreateNetworks = async (names, dockerCompose, tracker
95
95
  await Promise.all(Object.entries(networks).map(async ([key, val]) => {
96
96
  const name = val?.name || prefixName(key);
97
97
  if (names?.includes(name)) {
98
- const network = await dockerNetworkCreate(name, val);
98
+ const network = await dockerNetworkCreate(name, val ?? undefined);
99
99
  if (network) {
100
100
  tracker.networks.set(name, network);
101
101
  }
@@ -107,7 +107,7 @@ export const dockerComposeCreateVolumes = async (names, dockerCompose, tracker =
107
107
  await Promise.all(Object.entries(volumes).map(async ([key, val]) => {
108
108
  const name = val?.name || prefixName(key);
109
109
  if (!names || names.includes(name)) {
110
- const volume = await dockerVolumeCreate(name, val);
110
+ const volume = await dockerVolumeCreate(name, val ?? undefined);
111
111
  if (volume) {
112
112
  tracker.volumes.set(name, volume);
113
113
  }
@@ -413,7 +413,10 @@ export async function dockerComposeRunService(key, upOptions = {}, dockerCompose
413
413
  const upResult = await service.up(upOptions);
414
414
  const { container, ports: [{ docker: dockerPort, local: port }], urls, urls: [{ docker: dockerUrl, local: url }], } = upResult;
415
415
  const { id, image, name } = container;
416
- urls.forEach(({ local }) => local && buildLog(`<${service.name}> accessible at ${local}`));
416
+ urls.forEach(({ local }) => {
417
+ if (local)
418
+ buildLog(`<${service.name}> accessible at ${local}`);
419
+ });
417
420
  return {
418
421
  ...upResult,
419
422
  dockerPort,
package/src/maps.js CHANGED
@@ -38,6 +38,4 @@ export const filterKeys = (obj, filter = (v) => v != null) => Object.entries(obj
38
38
  * @param {Object} obj the input object
39
39
  * @returns {Object} a new object, a subset of the input
40
40
  */
41
- export const filterNullish = (obj) =>
42
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
43
- filterKeys(obj);
41
+ export const filterNullish = (obj) => filterKeys(obj);
package/src/npm.js CHANGED
@@ -8,7 +8,9 @@ import { getDefaultNpmDistTag, getVersion } from './version.js';
8
8
  export function getNpmConfig() {
9
9
  return getCfg().npm || {};
10
10
  }
11
- export const envNpmCreds = (process.env.NPM_CREDS && JSON.parse(process.env.NPM_CREDS)) || null;
11
+ export const envNpmCreds = (process.env.NPM_CREDS &&
12
+ JSON.parse(process.env.NPM_CREDS)) ||
13
+ null;
12
14
  const npmExe = (npmPath) => npmPath || (platform() === 'win32' ? 'npm.cmd' : 'npm');
13
15
  export async function npm({ args = [], npmPath, spawnOptions, } = {}) {
14
16
  // The node distribution puts npm next to the node binary.
package/src/orbstack.js CHANGED
@@ -60,7 +60,7 @@ export const ensureOrbStackConfigured = async (desiredConfig) => {
60
60
  changed = true;
61
61
  }
62
62
  else {
63
- const existingConfig = await fs.readJson(configPath);
63
+ const existingConfig = (await fs.readJson(configPath));
64
64
  const effectiveConfig = {
65
65
  ...defaultConfig,
66
66
  ...existingConfig,
package/src/pkg.d.ts CHANGED
@@ -16,7 +16,7 @@ export interface Person {
16
16
  }
17
17
  export interface PackageJson {
18
18
  author?: string | Person;
19
- buildStrap: BuildStrapConfig;
19
+ buildStrap?: BuildStrapConfig;
20
20
  contributors?: (string | Person)[];
21
21
  dependencies?: Record<string, string>;
22
22
  description?: string;
package/src/pkg.js CHANGED
@@ -15,7 +15,7 @@ export function setPkg(p) {
15
15
  const pkgNameRegex = /^(?:(@[^/]+)\/)?(.+)$/i;
16
16
  export function getPkgName(includeScope = false) {
17
17
  const pkg = getPkg();
18
- if (!(pkg.name && pkg.name.length)) {
18
+ if (!pkg.name) {
19
19
  throw new Error('Package name not found in package.json, but this is a required property!');
20
20
  }
21
21
  if (includeScope) {
@@ -38,6 +38,7 @@ export function getPkgSafeName() {
38
38
  return null;
39
39
  }
40
40
  const [, scope, name] = match;
41
+ // the scope group is optional, so it can be undefined at runtime
41
42
  const safeScope = scope?.slice(1);
42
43
  return safeScope ? `${safeScope}-${name}` : name;
43
44
  }
package/src/run.js CHANGED
@@ -17,6 +17,9 @@ export function errorMessage(err) {
17
17
  return err;
18
18
  }
19
19
  try {
20
+ // JSON.stringify returns undefined for undefined, functions and symbols,
21
+ // but the TypeScript lib types declare the return type as string only
22
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
20
23
  return JSON.stringify(err) ?? String(err);
21
24
  }
22
25
  catch {
@@ -60,6 +63,8 @@ export function buildLog(msg, timeOrOptions) {
60
63
  writeLog(`[${format(time || new Date())}] ${msg}`, stream);
61
64
  }
62
65
  export async function run(fn, ...options) {
66
+ // JavaScript callers can pass null or undefined
67
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
63
68
  if (fn == null) {
64
69
  throw new Error(`Invalid argument passed to run(${String(fn)})`);
65
70
  }