Skip to content

Commit 7cdce87

Browse files
authored
Merge branch 'google:main' into main
2 parents 235170f + 2acb0f2 commit 7cdce87

13 files changed

+1609
-212
lines changed

package-lock.json

+1,277-163
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+29-20
Original file line numberDiff line numberDiff line change
@@ -41,39 +41,48 @@
4141
"scripts": {
4242
"fmt": "prettier --write .",
4343
"fmt:check": "prettier --check .",
44-
"build": "tsc --project tsconfig.prod.json",
44+
"build": "npm run build:js && npm run build:dts",
4545
"build:check": "tsc",
46+
"build:js": "node scripts/build-js.mjs --format=esm --entry=src/*.ts && npm run build:vendor",
47+
"build:vendor": "node scripts/build-js.mjs --format=esm --entry=src/vendor.ts --bundle=all --banner",
48+
"build:dts": "tsc --project tsconfig.prod.json && node scripts/build-dts.mjs",
4649
"test": "npm run build && node ./test/all.test.js",
4750
"test:types": "tsd",
48-
"coverage": "c8 --check-coverage npm test",
51+
"coverage": "c8 -x build/vendor.js -x 'test/**' -x scripts --check-coverage npm test",
4952
"mutation": "stryker run",
5053
"circular": "madge --circular src/*",
5154
"version": "cat package.json | fx .version"
5255
},
53-
"dependencies": {
54-
"@types/fs-extra": "^11.0.1",
55-
"@types/minimist": "^1.2.2",
56-
"@types/node": "^18.16.3",
57-
"@types/ps-tree": "^1.1.2",
58-
"@types/which": "^3.0.0",
59-
"chalk": "^5.2.0",
60-
"fs-extra": "^11.1.1",
61-
"fx": "*",
62-
"globby": "^13.1.4",
63-
"minimist": "^1.2.8",
64-
"node-fetch": "3.3.1",
65-
"ps-tree": "^1.2.0",
66-
"webpod": "^0",
67-
"which": "^3.0.0",
68-
"yaml": "^2.2.2"
56+
"optionalDependencies": {
57+
"@types/fs-extra": "^11.0.4",
58+
"@types/node": ">=20.11.19"
6959
},
7060
"devDependencies": {
7161
"@stryker-mutator/core": "^6.4.2",
62+
"@types/fs-extra": "^11.0.4",
63+
"@types/minimist": "^1.2.5",
64+
"@types/node": ">=20.11.19",
65+
"@types/ps-tree": "^1.1.6",
66+
"@types/which": "^3.0.3",
7267
"c8": "^7.13.0",
73-
"madge": "^6.0.0",
68+
"chalk": "^5.3.0",
69+
"dts-bundle-generator": "^9.3.1",
70+
"esbuild": "^0.20.1",
71+
"esbuild-node-externals": "^1.13.0",
72+
"esbuild-plugin-entry-chunks": "^0.1.8",
73+
"fs-extra": "^11.2.0",
74+
"fx": "*",
75+
"globby": "^14.0.1",
76+
"madge": "^6.1.0",
77+
"minimist": "^1.2.8",
78+
"node-fetch-native": "^1.6.2",
7479
"prettier": "^2.8.8",
80+
"ps-tree": "^1.2.0",
7581
"tsd": "^0.28.1",
76-
"typescript": "^5.0.4"
82+
"typescript": "^5.0.4",
83+
"webpod": "^0",
84+
"which": "^3.0.0",
85+
"yaml": "^2.3.4"
7786
},
7887
"publishConfig": {
7988
"registry": "https://wombat-dressing-room.appspot.com"

scripts/build-dts.mjs

+86
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
#!/usr/bin/env node
2+
3+
// Copyright 2024 Google LLC
4+
//
5+
// Licensed under the Apache License, Version 2.0 (the "License");
6+
// you may not use this file except in compliance with the License.
7+
// You may obtain a copy of the License at
8+
//
9+
// https://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing, software
12+
// distributed under the License is distributed on an "AS IS" BASIS,
13+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
// See the License for the specific language governing permissions and
15+
// limitations under the License.
16+
17+
import fs from 'fs/promises'
18+
import { generateDtsBundle } from 'dts-bundle-generator'
19+
import glob from 'fast-glob'
20+
21+
const entry = {
22+
filePath: './src/vendor.ts',
23+
outFile: './build/vendor.d.ts',
24+
libraries: {
25+
allowedTypesLibraries: ['node'], // args['external-types'],
26+
inlinedLibraries: [
27+
'@nodelib/fs.stat',
28+
'@nodelib/fs.scandir',
29+
'@nodelib/fs.walk',
30+
'fast-glob',
31+
'@types/jsonfile',
32+
'node-fetch-native',
33+
'chalk',
34+
'globby',
35+
'webpod',
36+
'@types/fs-extra',
37+
'@types/minimist',
38+
'@types/ps-tree',
39+
'@types/which',
40+
], // args['external-inlines'],
41+
},
42+
output: {
43+
inlineDeclareExternals: true,
44+
inlineDeclareGlobals: true,
45+
sortNodes: false,
46+
exportReferencedTypes: false, //args['export-referenced-types'],
47+
},
48+
}
49+
50+
const compilationOptions = {
51+
preferredConfigPath: './tsconfig.prod.json', // args.project,
52+
followSymlinks: true,
53+
}
54+
55+
let [result] = generateDtsBundle([entry], compilationOptions)
56+
57+
// generateDtsBundle cannot handle the circular refs on types inlining, so we need to help it manually:
58+
/*
59+
build/vendor.d.ts(163,7): error TS2456: Type alias 'Options' circularly references itself.
60+
build/vendor.d.ts(164,7): error TS2456: Type alias 'Entry' circularly references itself.
61+
build/vendor.d.ts(165,7): error TS2456: Type alias 'Task' circularly references itself.
62+
build/vendor.d.ts(166,7): error TS2456: Type alias 'Pattern' circularly references itself.
63+
build/vendor.d.ts(167,7): error TS2456: Type alias 'FileSystemAdapter' circularly references itself.
64+
build/vendor.d.ts(197,48): error TS2694: Namespace 'FastGlob' has no exported member 'FastGlobOptions
65+
*/
66+
67+
result = result
68+
.replace('type Options = Options;', 'export {Options};')
69+
.replace('type Task = Task;', 'export {Task};')
70+
.replace('type Pattern = Pattern;', 'export {Pattern};')
71+
.replace('FastGlob.FastGlobOptions', 'FastGlob.Options')
72+
.replace('type Entry =', 'export type Entry =')
73+
74+
await fs.writeFile(entry.outFile, result, 'utf8')
75+
76+
// Replaces redundant triple-slash directives
77+
for (const dts of await glob(['build/**/*.d.ts', '!build/vendor.d.ts'])) {
78+
const contents = (await fs.readFile(dts, 'utf8'))
79+
.split('\n')
80+
.filter((line) => !line.startsWith('/// <reference types'))
81+
.join('\n')
82+
83+
await fs.writeFile(dts, contents, 'utf8')
84+
}
85+
86+
process.exit(0)

scripts/build-js.mjs

+123
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
#!/usr/bin/env node
2+
3+
// Copyright 2024 Google LLC
4+
//
5+
// Licensed under the Apache License, Version 2.0 (the "License");
6+
// you may not use this file except in compliance with the License.
7+
// You may obtain a copy of the License at
8+
//
9+
// https://www.apache.org/licenses/LICENSE-2.0
10+
//
11+
// Unless required by applicable law or agreed to in writing, software
12+
// distributed under the License is distributed on an "AS IS" BASIS,
13+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
// See the License for the specific language governing permissions and
15+
// limitations under the License.
16+
17+
import path from 'node:path'
18+
import esbuild from 'esbuild'
19+
import { nodeExternalsPlugin } from 'esbuild-node-externals'
20+
import { entryChunksPlugin } from 'esbuild-plugin-entry-chunks'
21+
import minimist from 'minimist'
22+
import glob from 'fast-glob'
23+
24+
const argv = minimist(process.argv.slice(2), {
25+
default: {
26+
entry: './src/index.ts',
27+
external: 'node:*',
28+
bundle: 'src', // 'all' | 'none'
29+
license: 'eof',
30+
minify: false,
31+
sourcemap: false,
32+
format: 'cjs,esm',
33+
cwd: process.cwd(),
34+
},
35+
boolean: ['minify', 'sourcemap', 'banner'],
36+
string: ['entry', 'external', 'bundle', 'license', 'format', 'map', 'cwd'],
37+
})
38+
const {
39+
entry,
40+
external,
41+
bundle,
42+
minify,
43+
sourcemap,
44+
license,
45+
format,
46+
cwd: _cwd,
47+
} = argv
48+
49+
const plugins = []
50+
const cwd = Array.isArray(_cwd) ? _cwd[_cwd.length - 1] : _cwd
51+
const entries = entry.split(/,\s?/)
52+
const entryPoints = entry.includes('*')
53+
? await glob(entries, { absolute: false, onlyFiles: true, cwd, root: cwd })
54+
: entries.map((p) => path.relative(cwd, path.resolve(cwd, p)))
55+
56+
console.log('cwd=', cwd)
57+
console.log('entryPoints=', entryPoints)
58+
59+
const _bundle = bundle !== 'none' && !process.argv.includes('--no-bundle')
60+
const _external = _bundle ? external.split(',') : undefined // https://github.com/evanw/esbuild/issues/1466
61+
62+
if (_bundle && entryPoints.length > 1) {
63+
plugins.push(entryChunksPlugin())
64+
}
65+
66+
if (bundle === 'src') {
67+
// https://github.com/evanw/esbuild/issues/619
68+
// https://github.com/pradel/esbuild-node-externals/pull/52
69+
plugins.push(nodeExternalsPlugin())
70+
}
71+
72+
const formats = format.split(',')
73+
const banner =
74+
argv.banner && bundle === 'all'
75+
? {
76+
js: `
77+
const require = (await import("node:module")).createRequire(import.meta.url);
78+
const __filename = (await import("node:url")).fileURLToPath(import.meta.url);
79+
const __dirname = (await import("node:path")).dirname(__filename);
80+
`,
81+
}
82+
: {}
83+
84+
const esmConfig = {
85+
absWorkingDir: cwd,
86+
entryPoints,
87+
outdir: './build',
88+
bundle: _bundle,
89+
external: _external,
90+
minify,
91+
sourcemap,
92+
sourcesContent: false,
93+
platform: 'node',
94+
target: 'esnext',
95+
format: 'esm',
96+
outExtension: {
97+
// '.js': '.mjs'
98+
},
99+
plugins,
100+
legalComments: license,
101+
tsconfig: './tsconfig.json',
102+
//https://github.com/evanw/esbuild/issues/1921
103+
banner,
104+
}
105+
106+
const cjsConfig = {
107+
...esmConfig,
108+
outdir: './build',
109+
target: 'es6',
110+
format: 'cjs',
111+
banner: {},
112+
outExtension: {
113+
// '.js': '.cjs'
114+
},
115+
}
116+
117+
for (const format of formats) {
118+
const config = format === 'cjs' ? cjsConfig : esmConfig
119+
120+
await esbuild.build(config).catch(() => process.exit(1))
121+
}
122+
123+
process.exit(0)

src/cli.ts

+9-4
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,18 @@
1414
// See the License for the specific language governing permissions and
1515
// limitations under the License.
1616

17-
import fs from 'fs-extra'
18-
import minimist from 'minimist'
1917
import { createRequire } from 'node:module'
2018
import { basename, dirname, extname, join, resolve } from 'node:path'
2119
import url from 'node:url'
22-
import { updateArgv } from './goods.js'
23-
import { $, chalk, fetch, ProcessOutput } from './index.js'
20+
import {
21+
$,
22+
ProcessOutput,
23+
updateArgv,
24+
fetch,
25+
chalk,
26+
minimist,
27+
fs,
28+
} from './index.js'
2429
import { startRepl } from './repl.js'
2530
import { randomId } from './util.js'
2631
import { installDeps, parseDeps } from './deps.js'

src/core.ts

+8-4
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,13 @@ import { ChildProcess, spawn, StdioNull, StdioPipe } from 'node:child_process'
1717
import { AsyncLocalStorage, createHook } from 'node:async_hooks'
1818
import { Readable, Writable } from 'node:stream'
1919
import { inspect } from 'node:util'
20-
import { RequestInfo, RequestInit } from 'node-fetch'
21-
import chalk, { ChalkInstance } from 'chalk'
22-
import which from 'which'
20+
import {
21+
chalk,
22+
which,
23+
type ChalkInstance,
24+
RequestInfo,
25+
RequestInit,
26+
} from './vendor.js'
2327
import {
2428
Duration,
2529
errnoMessage,
@@ -39,7 +43,7 @@ export type Shell = (
3943

4044
const processCwd = Symbol('processCwd')
4145

42-
export type Options = {
46+
export interface Options {
4347
[processCwd]: string
4448
cwd?: string
4549
verbose: boolean

src/goods.ts

+14-15
Original file line numberDiff line numberDiff line change
@@ -13,22 +13,21 @@
1313
// limitations under the License.
1414

1515
import assert from 'node:assert'
16-
import * as globbyModule from 'globby'
17-
import minimist from 'minimist'
18-
import nodeFetch, { RequestInfo, RequestInit } from 'node-fetch'
1916
import { createInterface } from 'node:readline'
2017
import { $, within, ProcessOutput } from './core.js'
21-
import { Duration, isString, parseDuration } from './util.js'
22-
import chalk from 'chalk'
18+
import { type Duration, isString, parseDuration } from './util.js'
19+
import {
20+
chalk,
21+
minimist,
22+
globbyModule,
23+
GlobbyOptions,
24+
nodeFetch,
25+
RequestInfo,
26+
RequestInit,
27+
} from './vendor.js'
2328

24-
export { default as chalk } from 'chalk'
25-
export { default as fs } from 'fs-extra'
26-
export { default as which } from 'which'
27-
export { default as minimist } from 'minimist'
28-
export { default as YAML } from 'yaml'
2929
export { default as path } from 'node:path'
30-
export { default as os } from 'node:os'
31-
export { ssh } from 'webpod'
30+
export * as os from 'node:os'
3231

3332
export let argv = minimist(process.argv.slice(2))
3433
export function updateArgv(args: string[]) {
@@ -38,11 +37,11 @@ export function updateArgv(args: string[]) {
3837

3938
export const globby = Object.assign(function globby(
4039
patterns: string | readonly string[],
41-
options?: globbyModule.Options
40+
options?: GlobbyOptions
4241
) {
4342
return globbyModule.globby(patterns, options)
4443
},
45-
globbyModule)
44+
globbyModule) as (typeof globbyModule)['globby'] & typeof globbyModule
4645
export const glob = globby
4746

4847
export function sleep(duration: Duration) {
@@ -198,7 +197,7 @@ export async function spinner<T>(
198197
try {
199198
result = await callback!()
200199
} finally {
201-
clearInterval(id)
200+
clearInterval(id as NodeJS.Timeout)
202201
process.stderr.write(' '.repeat(process.stdout.columns - 1) + '\r')
203202
}
204203
return result

src/index.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ import { ProcessPromise } from './core.js'
1616

1717
export * from './core.js'
1818
export * from './goods.js'
19+
export { minimist, chalk, fs, which, YAML, ssh } from './vendor.js'
1920

20-
export { Duration, quote, quotePowerShell } from './util.js'
21+
export { type Duration, quote, quotePowerShell } from './util.js'
2122

2223
/**
2324
* @deprecated Use $.nothrow() instead.

0 commit comments

Comments
 (0)