@sanity/pkg-utils 2.0.0-beta.1 → 2.0.0-beta.3

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 (53) hide show
  1. package/dist/_chunks/{build-30149f1c.cjs → build-270096bd.cjs} +15 -7
  2. package/dist/_chunks/build-270096bd.cjs.map +1 -0
  3. package/dist/_chunks/{buildAction-7e75c8b7.cjs → buildAction-87a1a82b.cjs} +4 -4
  4. package/dist/_chunks/{buildAction-7e75c8b7.cjs.map → buildAction-87a1a82b.cjs.map} +1 -1
  5. package/dist/_chunks/{check-0f269395.cjs → check-5451f989.cjs} +28 -19
  6. package/dist/_chunks/check-5451f989.cjs.map +1 -0
  7. package/dist/_chunks/{checkAction-8b9632b6.cjs → checkAction-f67b99f8.cjs} +3 -3
  8. package/dist/_chunks/{checkAction-8b9632b6.cjs.map → checkAction-f67b99f8.cjs.map} +1 -1
  9. package/dist/_chunks/{index-db00ad50.cjs → index-a0acce24.cjs} +169 -65
  10. package/dist/_chunks/index-a0acce24.cjs.map +1 -0
  11. package/dist/_chunks/{resolveBuildContext-e938cee6.cjs → resolveBuildContext-2fe45294.cjs} +75 -52
  12. package/dist/_chunks/resolveBuildContext-2fe45294.cjs.map +1 -0
  13. package/dist/_chunks/{watch-73fd460f.cjs → watch-dbc7e975.cjs} +19 -11
  14. package/dist/_chunks/watch-dbc7e975.cjs.map +1 -0
  15. package/dist/_chunks/{watchAction-ffba41fd.cjs → watchAction-c5e16765.cjs} +4 -4
  16. package/dist/_chunks/{watchAction-ffba41fd.cjs.map → watchAction-c5e16765.cjs.map} +1 -1
  17. package/dist/cli.cjs +4 -4
  18. package/dist/index.cjs +19 -17
  19. package/dist/index.cjs.map +1 -1
  20. package/dist/index.d.ts +39 -16
  21. package/dist/index.js +505 -353
  22. package/dist/index.js.map +1 -1
  23. package/package.json +4 -4
  24. package/src/node/build.ts +16 -3
  25. package/src/node/check.ts +6 -4
  26. package/src/node/core/contexts/buildContext.ts +4 -8
  27. package/src/node/core/index.ts +0 -1
  28. package/src/node/core/pkg/index.ts +1 -0
  29. package/src/node/core/pkg/loadPkgWithReporting.ts +11 -20
  30. package/src/node/core/pkg/parseExports.ts +4 -2
  31. package/src/node/core/pkg/pkgExt.ts +38 -0
  32. package/src/node/core/pkg/validateExports.ts +4 -4
  33. package/src/node/index.ts +3 -2
  34. package/src/node/logger.ts +33 -0
  35. package/src/node/printPackageTree.ts +11 -11
  36. package/src/node/resolveBuildContext.ts +16 -26
  37. package/src/node/spinner.ts +3 -3
  38. package/src/node/tasks/dts/buildTypes.ts +7 -22
  39. package/src/node/tasks/dts/doExtract.ts +2 -2
  40. package/src/node/tasks/dts/dtsTask.ts +7 -4
  41. package/src/node/tasks/dts/printDiagnostic.ts +42 -0
  42. package/src/node/tasks/rollup/consoleSpy.ts +41 -0
  43. package/src/node/tasks/rollup/resolveRollupConfig.ts +21 -10
  44. package/src/node/tasks/rollup/rollupTask.ts +87 -51
  45. package/src/node/tasks/rollup/rollupWatchTask.ts +0 -1
  46. package/src/node/watch.ts +8 -4
  47. package/src/node/watchConfigFiles.ts +9 -8
  48. package/dist/_chunks/build-30149f1c.cjs.map +0 -1
  49. package/dist/_chunks/check-0f269395.cjs.map +0 -1
  50. package/dist/_chunks/index-db00ad50.cjs.map +0 -1
  51. package/dist/_chunks/resolveBuildContext-e938cee6.cjs.map +0 -1
  52. package/dist/_chunks/watch-73fd460f.cjs.map +0 -1
  53. package/src/node/core/constants.ts +0 -14
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "type": "module",
3
3
  "name": "@sanity/pkg-utils",
4
- "version": "2.0.0-beta.1",
4
+ "version": "2.0.0-beta.3",
5
5
  "author": "Sanity.io <hello@sanity.io>",
6
6
  "license": "MIT",
7
7
  "description": "Simple utilities for modern npm packages.",
@@ -40,8 +40,8 @@
40
40
  ],
41
41
  "scripts": {
42
42
  "build": "run-s clean build:pkg check:pkg",
43
- "build:pkg": "node --experimental-loader ./scripts/_experimental-loader.js -r esbuild-register scripts/build",
44
- "check:pkg": "node --experimental-loader ./scripts/_experimental-loader.js -r esbuild-register scripts/check",
43
+ "build:pkg": "node --loader esbuild-register/loader -r esbuild-register scripts/build",
44
+ "check:pkg": "node --loader esbuild-register/loader -r esbuild-register scripts/check",
45
45
  "check:types": "tsc --build",
46
46
  "clean": "rimraf dist test/env/__tmp__",
47
47
  "commit": "cz",
@@ -51,7 +51,7 @@
51
51
  "prepublishOnly": "pnpm run build",
52
52
  "release": "semantic-release",
53
53
  "test": "vitest run",
54
- "watch": "node --experimental-loader ./scripts/_experimental-loader.js -r esbuild-register scripts/watch"
54
+ "watch": "node --loader esbuild-register/loader -r esbuild-register scripts/watch"
55
55
  },
56
56
  "dependencies": {
57
57
  "@babel/core": "^7.20.5",
package/src/node/build.ts CHANGED
@@ -1,4 +1,5 @@
1
- import {loadConfig, loadPkgWithReporting} from './core'
1
+ import {getPkgExtMap, loadConfig, loadPkgWithReporting} from './core'
2
+ import {createLogger} from './logger'
2
3
  import {resolveBuildContext} from './resolveBuildContext'
3
4
  import {resolveBuildTasks} from './resolveBuildTasks'
4
5
  import {createSpinner} from './spinner'
@@ -30,11 +31,23 @@ export async function build(options: {
30
31
  tsconfig?: string
31
32
  }): Promise<void> {
32
33
  const {cwd, emitDeclarationOnly, strict = false, tsconfig: tsconfigOption} = options
34
+ const logger = createLogger()
33
35
 
34
- const pkg = await loadPkgWithReporting({cwd})
36
+ const pkg = await loadPkgWithReporting({cwd, logger})
35
37
  const config = await loadConfig({cwd})
38
+ const extMap = getPkgExtMap({legacyExports: config?.legacyExports ?? false})
36
39
  const tsconfig = tsconfigOption || config?.tsconfig || 'tsconfig.json'
37
- const ctx = await resolveBuildContext({config, cwd, emitDeclarationOnly, pkg, strict, tsconfig})
40
+
41
+ const ctx = await resolveBuildContext({
42
+ config,
43
+ cwd,
44
+ emitDeclarationOnly,
45
+ extMap,
46
+ logger,
47
+ pkg,
48
+ strict,
49
+ tsconfig,
50
+ })
38
51
 
39
52
  const buildTasks = resolveBuildTasks(ctx)
40
53
 
package/src/node/check.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import path from 'path'
2
2
  import esbuild, {BuildFailure} from 'esbuild'
3
- import {loadConfig, loadPkgWithReporting} from './core'
3
+ import {getPkgExtMap, loadConfig, loadPkgWithReporting} from './core'
4
+ import {createLogger} from './logger'
4
5
  import {fileExists, printPackageTree} from './printPackageTree'
5
6
  import {resolveBuildContext} from './resolveBuildContext'
6
7
 
@@ -11,12 +12,13 @@ export async function check(options: {
11
12
  tsconfig?: string
12
13
  }): Promise<void> {
13
14
  const {cwd, strict = false, tsconfig: tsconfigOption} = options
15
+ const logger = createLogger()
14
16
 
15
- const pkg = await loadPkgWithReporting({cwd})
17
+ const pkg = await loadPkgWithReporting({cwd, logger})
16
18
  const config = await loadConfig({cwd})
19
+ const extMap = getPkgExtMap({legacyExports: config?.legacyExports ?? false})
17
20
  const tsconfig = tsconfigOption || config?.tsconfig || 'tsconfig.json'
18
- const ctx = await resolveBuildContext({config, cwd, pkg, strict, tsconfig})
19
- const {logger} = ctx
21
+ const ctx = await resolveBuildContext({config, cwd, extMap, logger, pkg, strict, tsconfig})
20
22
 
21
23
  printPackageTree(ctx)
22
24
 
@@ -1,6 +1,7 @@
1
1
  import ts from 'typescript'
2
+ import {Logger} from '../../logger'
2
3
  import {PkgExports, PkgRuntime, PkgConfigOptions} from '../config'
3
- import {PackageJSON} from '../pkg'
4
+ import {PackageJSON, PkgExtMap} from '../pkg'
4
5
 
5
6
  /** @internal */
6
7
  export interface BuildFile {
@@ -15,15 +16,10 @@ export interface BuildContext {
15
16
  distPath: string
16
17
  emitDeclarationOnly: boolean
17
18
  exports: PkgExports | undefined
19
+ extMap: PkgExtMap
18
20
  external: string[]
19
21
  files: BuildFile[]
20
- logger: {
21
- log: (...args: unknown[]) => void
22
- info: (...args: unknown[]) => void
23
- warn: (...args: unknown[]) => void
24
- error: (...args: unknown[]) => void
25
- success: (...args: unknown[]) => void
26
- }
22
+ logger: Logger
27
23
  pkg: PackageJSON
28
24
  runtime: PkgRuntime
29
25
  strict: boolean
@@ -1,4 +1,3 @@
1
- export * from './constants'
2
1
  export * from './defaults'
3
2
  export * from './isRecord'
4
3
  export * from './config'
@@ -1,4 +1,5 @@
1
1
  export * from './loadPkg'
2
2
  export * from './loadPkgWithReporting'
3
3
  export * from './parseExports'
4
+ export * from './pkgExt'
4
5
  export * from './types'
@@ -1,34 +1,25 @@
1
- /* eslint-disable no-console */
2
-
3
1
  import chalk from 'chalk'
4
2
  import {ZodError} from 'zod'
3
+ import {Logger} from '../../logger'
5
4
  import {loadPkg} from './loadPkg'
6
5
  import {PackageJSON} from './types'
7
6
 
8
7
  /** @internal */
9
- export async function loadPkgWithReporting(options: {cwd: string}): Promise<PackageJSON> {
10
- try {
11
- const pkg = await loadPkg(options)
8
+ export async function loadPkgWithReporting(options: {
9
+ cwd: string
10
+ logger: Logger
11
+ }): Promise<PackageJSON> {
12
+ const {cwd, logger} = options
12
13
 
13
- if (pkg.type === 'commonjs') {
14
- console.warn(
15
- [
16
- `${chalk.yellow('warn')} `,
17
- 'Packages with `"type": "commonjs"` may not be compatible with popular bundlers like ',
18
- 'webpack and rollup, and projects such as Astro and SvelteKit. Please consider using ',
19
- '`"type": "module"` instead.',
20
- ].join('')
21
- )
22
- }
23
-
24
- return pkg
14
+ try {
15
+ return await loadPkg({cwd})
25
16
  } catch (err) {
26
17
  if (err instanceof ZodError) {
27
18
  for (const issue of err.issues) {
28
19
  if (issue.code === 'invalid_type') {
29
- console.error(
20
+ logger.error(
30
21
  [
31
- `${chalk.red('fail')} \`${formatPath(issue.path)}\` `,
22
+ `\`${formatPath(issue.path)}\` `,
32
23
  `in \`./package.json\` must be of type ${chalk.magenta(issue.expected)} `,
33
24
  `(received ${chalk.magenta(issue.received)})`,
34
25
  ].join('')
@@ -36,7 +27,7 @@ export async function loadPkgWithReporting(options: {cwd: string}): Promise<Pack
36
27
  }
37
28
  }
38
29
  } else {
39
- console.error(err)
30
+ logger.error(err)
40
31
  }
41
32
 
42
33
  process.exit(1)
@@ -1,14 +1,16 @@
1
1
  import {PkgExport} from '../config'
2
2
  import {isRecord} from '../isRecord'
3
+ import {PkgExtMap} from './pkgExt'
3
4
  import {PackageJSON} from './types'
4
5
  import {validateExports} from './validateExports'
5
6
 
6
7
  /** @internal */
7
8
  export function parseExports(options: {
9
+ extMap: PkgExtMap
8
10
  pkg: PackageJSON
9
11
  strict: boolean
10
12
  }): (PkgExport & {_path: string})[] {
11
- const {pkg, strict} = options
13
+ const {extMap, pkg, strict} = options
12
14
 
13
15
  const rootExport: PkgExport & {_path: string} = {
14
16
  _exported: true,
@@ -89,7 +91,7 @@ export function parseExports(options: {
89
91
 
90
92
  const _exports = [rootExport, ...extraExports]
91
93
 
92
- errors.push(...validateExports(_exports, {pkg}))
94
+ errors.push(...validateExports(_exports, {extMap, pkg}))
93
95
 
94
96
  if (errors.length) {
95
97
  throw new Error('\n- ' + errors.join('\n- '))
@@ -0,0 +1,38 @@
1
+ /** @internal */
2
+ export interface PkgExtMap {
3
+ commonjs: {commonjs: string; esm: string}
4
+ module: {commonjs: string; esm: string}
5
+ }
6
+
7
+ /** @internal */
8
+ export const DEFAULT_PKG_EXT_MAP: PkgExtMap = {
9
+ // pkg.type: "commonjs"
10
+ commonjs: {
11
+ commonjs: '.js',
12
+ esm: '.mjs',
13
+ },
14
+
15
+ // pkg.type: "module"
16
+ module: {
17
+ commonjs: '.cjs',
18
+ esm: '.js',
19
+ },
20
+ }
21
+
22
+ /** @internal */
23
+ export function getPkgExtMap(options: {legacyExports: boolean}): PkgExtMap {
24
+ const {legacyExports} = options
25
+
26
+ const ret = {...DEFAULT_PKG_EXT_MAP}
27
+
28
+ // Fall back to legacy file extensions for package.json with `"type": "commonjs"`
29
+ // NOTE: Not supported by Node 14+ and will be removed in a future version
30
+ if (legacyExports) {
31
+ ret['commonjs'] = {
32
+ commonjs: '.js',
33
+ esm: '.esm.js',
34
+ }
35
+ }
36
+
37
+ return ret
38
+ }
@@ -1,13 +1,13 @@
1
1
  import {PkgExport} from '../config'
2
- import {MODULE_EXT} from '../constants'
2
+ import {PkgExtMap} from './pkgExt'
3
3
  import {PackageJSON} from './types'
4
4
 
5
5
  export function validateExports(
6
6
  _exports: (PkgExport & {_path: string})[],
7
- options: {pkg: PackageJSON}
7
+ options: {extMap: PkgExtMap; pkg: PackageJSON}
8
8
  ): string[] {
9
- const {pkg} = options
10
- const ext = MODULE_EXT[pkg.type]
9
+ const {extMap, pkg} = options
10
+ const ext = extMap[pkg.type]
11
11
 
12
12
  const errors: string[] = []
13
13
 
package/src/node/index.ts CHANGED
@@ -1,6 +1,7 @@
1
+ export * from './build'
2
+ export * from './check'
1
3
  export * from './core'
4
+ export * from './logger'
2
5
  export * from './resolveBuildTasks'
3
6
  export * from './tasks'
4
- export * from './build'
5
- export * from './check'
6
7
  export * from './watch'
@@ -0,0 +1,33 @@
1
+ import chalk from 'chalk'
2
+
3
+ /** @internal */
4
+ export interface Logger {
5
+ log: (...args: unknown[]) => void
6
+ info: (...args: unknown[]) => void
7
+ warn: (...args: unknown[]) => void
8
+ error: (...args: unknown[]) => void
9
+ success: (...args: unknown[]) => void
10
+ }
11
+
12
+ /** @internal */
13
+ export function createLogger(): Logger {
14
+ return {
15
+ /* eslint-disable no-console */
16
+ log: (...args) => {
17
+ console.log(...args)
18
+ },
19
+ info: (...args) => {
20
+ console.log(chalk.blue('[info]'), ...args)
21
+ },
22
+ warn: (...args) => {
23
+ console.log(chalk.yellow('[warning]'), ...args)
24
+ },
25
+ error: (...args) => {
26
+ console.log(chalk.red('[error]'), ...args)
27
+ },
28
+ success: (...args) => {
29
+ console.log(chalk.green('[success]'), ...args)
30
+ },
31
+ /* eslint-enable no-console */
32
+ }
33
+ }
@@ -31,10 +31,12 @@ export function printPackageTree(ctx: BuildContext): void {
31
31
  logger.log(`${chalk.blue(pkg.name)}@${chalk.green(pkg.version)}`)
32
32
 
33
33
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
34
- const tree: Record<string, any> = {}
34
+ const tree: Record<string, unknown> = {type: chalk.yellow(pkg.type)}
35
35
 
36
36
  if (pkg.bin) {
37
- tree.bin = pkg.bin
37
+ tree.bin = Object.fromEntries(
38
+ Object.entries(pkg.bin).map(([name, file]) => [chalk.cyan(name), fileInfo(file)])
39
+ )
38
40
  }
39
41
 
40
42
  function fileInfo(file: string) {
@@ -44,7 +46,7 @@ export function printPackageTree(ctx: BuildContext): void {
44
46
  return `${chalk.gray(file)} ${chalk.red('does not exist')}`
45
47
  }
46
48
 
47
- return `${file} ${chalk.gray(info.size)}`
49
+ return `${chalk.yellow(file)} ${chalk.gray(info.size)}`
48
50
  }
49
51
 
50
52
  tree.exports = Object.fromEntries(
@@ -52,13 +54,13 @@ export function printPackageTree(ctx: BuildContext): void {
52
54
  .filter(([, entry]) => entry._exported)
53
55
  .map(([exportPath, entry]) => {
54
56
  const exp: Omit<PkgExport, '_exported'> = {
55
- source: entry.source,
56
57
  types: undefined,
58
+ source: fileInfo(entry.source),
57
59
  browser: undefined,
58
60
  node: undefined,
59
61
  import: undefined,
60
62
  require: undefined,
61
- default: entry.default,
63
+ default: fileInfo(entry.default),
62
64
  }
63
65
 
64
66
  if (entry.types) {
@@ -68,7 +70,7 @@ export function printPackageTree(ctx: BuildContext): void {
68
70
  }
69
71
 
70
72
  if (entry.browser) {
71
- exp.browser = {source: entry.browser.source}
73
+ exp.browser = {source: fileInfo(entry.browser.source)}
72
74
 
73
75
  if (entry.browser.import) exp.browser.import = fileInfo(entry.browser.import)
74
76
  if (entry.browser.require) exp.browser.require = fileInfo(entry.browser.require)
@@ -77,7 +79,7 @@ export function printPackageTree(ctx: BuildContext): void {
77
79
  }
78
80
 
79
81
  if (entry.node) {
80
- exp.node = {source: entry.node.source}
82
+ exp.node = {source: fileInfo(entry.node.source)}
81
83
 
82
84
  if (entry.node.import) exp.node.import = fileInfo(entry.node.import)
83
85
  if (entry.node.require) exp.node.require = fileInfo(entry.node.require)
@@ -97,11 +99,9 @@ export function printPackageTree(ctx: BuildContext): void {
97
99
  delete exp.require
98
100
  }
99
101
 
100
- exp.default = fileInfo(entry.default)
101
-
102
- return [chalk.green(path.join(pkg.name, exportPath)), exp]
102
+ return [chalk.cyan(path.join(pkg.name, exportPath)), exp]
103
103
  })
104
104
  )
105
105
 
106
- logger.log(treeify.asTree(tree, true, true))
106
+ logger.log(treeify.asTree(tree as Record<string, any>, true, true))
107
107
  }
@@ -1,5 +1,4 @@
1
1
  import path from 'path'
2
- import chalk from 'chalk'
3
2
  import {
4
3
  PkgConfigOptions,
5
4
  PkgExports,
@@ -10,44 +9,34 @@ import {
10
9
  PackageJSON,
11
10
  parseExports,
12
11
  resolveConfigProperty,
12
+ PkgExtMap,
13
13
  } from './core'
14
14
  import {findCommonDirPath, pathContains} from './core/findCommonPath'
15
+ import {Logger} from './logger'
15
16
  import {resolveBrowserslistVersions} from './resolveBrowserslistVersions'
16
17
  import {resolveBrowserTarget} from './resolveBrowserTarget'
17
18
  import {resolveNodeTarget} from './resolveNodeTarget'
18
19
 
19
- function createLogger(): BuildContext['logger'] {
20
- return {
21
- /* eslint-disable no-console */
22
- log: (...args) => {
23
- console.log(...args)
24
- },
25
- info: (...args) => {
26
- console.log(chalk.blue(' info'), ...args)
27
- },
28
- warn: (...args) => {
29
- console.log(chalk.yellow(' warn'), ...args)
30
- },
31
- error: (...args) => {
32
- console.log(chalk.red(' fail'), ...args)
33
- },
34
- success: (...args) => {
35
- console.log(chalk.green(' ok '), ...args)
36
- },
37
- /* eslint-enable no-console */
38
- }
39
- }
40
-
41
20
  export async function resolveBuildContext(options: {
42
21
  config?: PkgConfigOptions
43
22
  cwd: string
44
23
  emitDeclarationOnly?: boolean
24
+ extMap: PkgExtMap
25
+ logger: Logger
45
26
  pkg: PackageJSON
46
27
  strict: boolean
47
28
  tsconfig: string
48
29
  }): Promise<BuildContext> {
49
- const {config, cwd, emitDeclarationOnly = false, pkg, strict, tsconfig: tsconfigPath} = options
50
- const logger = createLogger()
30
+ const {
31
+ config,
32
+ cwd,
33
+ emitDeclarationOnly = false,
34
+ extMap,
35
+ logger,
36
+ pkg,
37
+ strict,
38
+ tsconfig: tsconfigPath,
39
+ } = options
51
40
  const tsconfig = await loadTSConfig({cwd, tsconfigPath})
52
41
  const targetVersions = resolveBrowserslistVersions(pkg.browserslist || DEFAULT_BROWSERSLIST_QUERY)
53
42
  const nodeTarget = resolveNodeTarget(targetVersions)
@@ -67,7 +56,7 @@ export async function resolveBuildContext(options: {
67
56
  node: nodeTarget,
68
57
  }
69
58
 
70
- const parsedExports = parseExports({pkg, strict}).reduce<PkgExports>((acc, x) => {
59
+ const parsedExports = parseExports({extMap, pkg, strict}).reduce<PkgExports>((acc, x) => {
71
60
  const {_path: exportPath, ...exportEntry} = x
72
61
 
73
62
  return {...acc, [exportPath]: exportEntry}
@@ -137,6 +126,7 @@ export async function resolveBuildContext(options: {
137
126
  emitDeclarationOnly,
138
127
  exports,
139
128
  external,
129
+ extMap,
140
130
  files: [],
141
131
  logger,
142
132
  pkg,
@@ -5,14 +5,14 @@ import chalk from 'chalk'
5
5
  export function createSpinner(msg: string): {complete: () => void; error: () => void} {
6
6
  const startTime = Date.now()
7
7
 
8
- console.log(` ${msg}`)
8
+ console.log(msg)
9
9
 
10
10
  return {
11
11
  complete: () => {
12
- console.log(`${chalk.green('ok ')} ${chalk.gray(`${Date.now() - startTime}ms`)}`)
12
+ console.log(`${chalk.green('[success]')} ${chalk.gray(`${Date.now() - startTime}ms`)}`)
13
13
  },
14
14
  error: () => {
15
- console.log(`${chalk.red(`failed`)} ${chalk.gray(`${Date.now() - startTime}ms`)}`)
15
+ console.log(`${chalk.red(`[error]`)} ${chalk.gray(`${Date.now() - startTime}ms`)}`)
16
16
  },
17
17
  }
18
18
  }
@@ -1,21 +1,16 @@
1
- /* eslint-disable no-console */
2
-
3
1
  import ts from 'typescript'
4
-
5
- export const formatHost: ts.FormatDiagnosticsHost = {
6
- getCurrentDirectory: () => ts.sys.getCurrentDirectory(),
7
- getNewLine: () => ts.sys.newLine,
8
- getCanonicalFileName: ts.sys.useCaseSensitiveFileNames ? (f) => f : (f) => f.toLowerCase(),
9
- }
2
+ import {Logger} from '../../logger'
3
+ import {printDiagnostic} from './printDiagnostic'
10
4
 
11
5
  /** @internal */
12
6
  export async function buildTypes(options: {
13
7
  cwd: string
8
+ logger: Logger
14
9
  outDir: string
15
10
  tsconfig: ts.ParsedCommandLine
16
11
  strict: boolean
17
12
  }): Promise<void> {
18
- const {outDir, tsconfig, strict = false} = options
13
+ const {cwd, logger, outDir, tsconfig, strict = false} = options
19
14
 
20
15
  const compilerOptions: ts.CompilerOptions = {
21
16
  ...tsconfig.options,
@@ -32,24 +27,14 @@ export async function buildTypes(options: {
32
27
 
33
28
  const allDiagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics)
34
29
 
35
- // TODO: improve logging
36
- allDiagnostics.forEach((diagnostic) => {
37
- if (diagnostic.file && diagnostic.start) {
38
- const {line, character} = ts.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start)
39
- const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n')
40
-
41
- console.log(`${diagnostic.file.fileName} ${line + 1}:${character + 1}\n${message}`)
42
- } else {
43
- console.log(ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'))
44
- }
45
- })
30
+ for (const diagnostic of allDiagnostics) {
31
+ printDiagnostic({cwd, logger, diagnostic})
32
+ }
46
33
 
47
34
  if (emitResult.emitSkipped) {
48
35
  const errors = allDiagnostics.filter((diag) => diag.category === ts.DiagnosticCategory.Error)
49
36
 
50
37
  if (errors.length) {
51
- console.error(ts.formatDiagnostics(errors, formatHost))
52
-
53
38
  if (strict) {
54
39
  throw new Error('failed to compile TypeScript definitions')
55
40
  }
@@ -19,7 +19,7 @@ export async function doExtract(
19
19
  ctx: BuildContext,
20
20
  task: DtsTask | DtsWatchTask
21
21
  ): Promise<DtsResult> {
22
- const {config, cwd, files, strict, ts} = ctx
22
+ const {config, cwd, files, logger, strict, ts} = ctx
23
23
 
24
24
  if (!ts.config || !ts.configPath) {
25
25
  return {type: 'dts', messages: [], results: []}
@@ -33,7 +33,7 @@ export async function doExtract(
33
33
 
34
34
  const tmpPath = path.resolve(outDir, '__tmp__')
35
35
 
36
- await buildTypes({cwd, outDir: tmpPath, strict, tsconfig: ts.config})
36
+ await buildTypes({cwd, logger, outDir: tmpPath, strict, tsconfig: ts.config})
37
37
  const messages: ExtractorMessage[] = []
38
38
 
39
39
  const results: {sourcePath: string; filePath: string}[] = []
@@ -10,10 +10,13 @@ import {DtsResult, DtsTask} from './types'
10
10
  export const dtsTask: TaskHandler<DtsTask, DtsResult> = {
11
11
  name: (_ctx, task) =>
12
12
  [
13
- `build type definitions`,
14
- ...task.entries.map(
15
- (entry) =>
16
- ` ${chalk.blue(entry.importId)}: ${entry.sourcePath} -> ${entry.targetPath}`
13
+ `Build type definitions...`,
14
+ ` entries:`,
15
+ ...task.entries.map((entry) =>
16
+ [
17
+ ` - ${chalk.cyan(entry.importId)}: `,
18
+ `${chalk.yellow(entry.sourcePath)} ${chalk.gray('→')} ${chalk.yellow(entry.targetPath)}`,
19
+ ].join('')
17
20
  ),
18
21
  ].join('\n'),
19
22
  exec: (ctx, task) => {
@@ -0,0 +1,42 @@
1
+ import path from 'path'
2
+ import chalk from 'chalk'
3
+ import ts from 'typescript'
4
+ import {Logger} from '../../logger'
5
+
6
+ export function printDiagnostic(options: {
7
+ cwd: string
8
+ logger: Logger
9
+ diagnostic: ts.Diagnostic
10
+ }): void {
11
+ const {cwd, logger, diagnostic} = options
12
+
13
+ if (diagnostic.file && diagnostic.start) {
14
+ const {line, character} = ts.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start)
15
+ const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n')
16
+
17
+ const file = path.relative(cwd, diagnostic.file.fileName)
18
+
19
+ const output = [
20
+ `${chalk.yellow(file)}:${chalk.blue(line + 1)}:${chalk.blue(character + 1)} - `,
21
+ `${chalk.gray(`TS${diagnostic.code}:`)} ${message}`,
22
+ ].join('')
23
+
24
+ if (diagnostic.category === ts.DiagnosticCategory.Error) {
25
+ logger.error(output)
26
+ }
27
+
28
+ if (diagnostic.category === ts.DiagnosticCategory.Warning) {
29
+ logger.warn(output)
30
+ }
31
+
32
+ if (diagnostic.category === ts.DiagnosticCategory.Message) {
33
+ logger.log(output)
34
+ }
35
+
36
+ if (diagnostic.category === ts.DiagnosticCategory.Suggestion) {
37
+ logger.log(output)
38
+ }
39
+ } else {
40
+ logger.log(ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'))
41
+ }
42
+ }
@@ -0,0 +1,41 @@
1
+ /* eslint-disable no-console */
2
+
3
+ export interface ConsoleSpyMsg {
4
+ type: 'log' | 'warn' | 'error'
5
+ code?: string
6
+ args: unknown[]
7
+ }
8
+
9
+ export interface ConsoleSpy {
10
+ messages: ConsoleSpyMsg[]
11
+ restore: () => void
12
+ }
13
+
14
+ export function createConsoleSpy(options: {
15
+ onRestored: (messages: ConsoleSpyMsg[]) => void
16
+ }): ConsoleSpy {
17
+ const {onRestored} = options
18
+
19
+ const original = {
20
+ log: console.log,
21
+ warn: console.warn,
22
+ error: console.error,
23
+ }
24
+
25
+ const messages: ConsoleSpyMsg[] = []
26
+
27
+ console.log = (...args: unknown[]) => messages.push({type: 'log', args})
28
+ console.warn = (...args: unknown[]) => messages.push({type: 'warn', args})
29
+ console.error = (...args: unknown[]) => messages.push({type: 'error', args})
30
+
31
+ return {
32
+ messages,
33
+ restore: () => {
34
+ console.log = original.log
35
+ console.warn = original.warn
36
+ console.error = original.error
37
+
38
+ onRestored(messages)
39
+ },
40
+ }
41
+ }