@sanity/pkg-utils 11.0.17 → 12.0.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 (71) hide show
  1. package/MIGRATE.md +152 -0
  2. package/README.md +114 -55
  3. package/dist/buildAction-D-M3KYyN.js +146 -0
  4. package/dist/buildAction-D-M3KYyN.js.map +1 -0
  5. package/dist/checkAction-B8M5CP3j.js +141 -0
  6. package/dist/checkAction-B8M5CP3j.js.map +1 -0
  7. package/dist/cli.js +22 -28
  8. package/dist/cli.js.map +1 -1
  9. package/dist/createApiExtractorConfig-CJoZqw8e.js +30 -0
  10. package/dist/createApiExtractorConfig-CJoZqw8e.js.map +1 -0
  11. package/dist/createTSDocConfig-ylfirNWP.js +25 -0
  12. package/dist/createTSDocConfig-ylfirNWP.js.map +1 -0
  13. package/dist/getExtractMessagesConfig-CXljwFbQ.js +75 -0
  14. package/dist/getExtractMessagesConfig-CXljwFbQ.js.map +1 -0
  15. package/dist/handleError-83GwKIFM.js +40 -0
  16. package/dist/handleError-83GwKIFM.js.map +1 -0
  17. package/dist/index.d.ts +141 -195
  18. package/dist/index.d.ts.map +1 -1
  19. package/dist/index.js +203 -11
  20. package/dist/index.js.map +1 -1
  21. package/dist/initAction-CmOO8eod.js +618 -0
  22. package/dist/initAction-CmOO8eod.js.map +1 -0
  23. package/dist/printExtractMessages-DyaYtByp.js +33 -0
  24. package/dist/printExtractMessages-DyaYtByp.js.map +1 -0
  25. package/dist/resolveBuildContext-CbwvYKj1.js +714 -0
  26. package/dist/resolveBuildContext-CbwvYKj1.js.map +1 -0
  27. package/dist/resolveTsdownConfig-CGE_7cMM.js +283 -0
  28. package/dist/resolveTsdownConfig-CGE_7cMM.js.map +1 -0
  29. package/dist/spinner-DAHe7SuT.js +15 -0
  30. package/dist/spinner-DAHe7SuT.js.map +1 -0
  31. package/dist/watchAction-BQG5_hhl.js +179 -0
  32. package/dist/watchAction-BQG5_hhl.js.map +1 -0
  33. package/dist/watchConfigFiles-AGBDblwf.js +43 -0
  34. package/dist/watchConfigFiles-AGBDblwf.js.map +1 -0
  35. package/package.json +12 -26
  36. package/dist/_chunks-es/buildAction.js +0 -195
  37. package/dist/_chunks-es/buildAction.js.map +0 -1
  38. package/dist/_chunks-es/checkAction.js +0 -198
  39. package/dist/_chunks-es/checkAction.js.map +0 -1
  40. package/dist/_chunks-es/createApiExtractorConfig.js +0 -52
  41. package/dist/_chunks-es/createApiExtractorConfig.js.map +0 -1
  42. package/dist/_chunks-es/createTSDocConfig.js +0 -31
  43. package/dist/_chunks-es/createTSDocConfig.js.map +0 -1
  44. package/dist/_chunks-es/defaults.js +0 -36
  45. package/dist/_chunks-es/defaults.js.map +0 -1
  46. package/dist/_chunks-es/define.js +0 -7
  47. package/dist/_chunks-es/define.js.map +0 -1
  48. package/dist/_chunks-es/extractModuleBlocks.js +0 -48
  49. package/dist/_chunks-es/extractModuleBlocks.js.map +0 -1
  50. package/dist/_chunks-es/fileExists.js +0 -12
  51. package/dist/_chunks-es/fileExists.js.map +0 -1
  52. package/dist/_chunks-es/getExtractMessagesConfig.js +0 -83
  53. package/dist/_chunks-es/getExtractMessagesConfig.js.map +0 -1
  54. package/dist/_chunks-es/handleError.js +0 -32
  55. package/dist/_chunks-es/handleError.js.map +0 -1
  56. package/dist/_chunks-es/index.js +0 -825
  57. package/dist/_chunks-es/index.js.map +0 -1
  58. package/dist/_chunks-es/initAction.js +0 -654
  59. package/dist/_chunks-es/initAction.js.map +0 -1
  60. package/dist/_chunks-es/printExtractMessages.js +0 -44
  61. package/dist/_chunks-es/printExtractMessages.js.map +0 -1
  62. package/dist/_chunks-es/resolveBuildContext.js +0 -717
  63. package/dist/_chunks-es/resolveBuildContext.js.map +0 -1
  64. package/dist/_chunks-es/resolveRolldownConfig.js +0 -117
  65. package/dist/_chunks-es/resolveRolldownConfig.js.map +0 -1
  66. package/dist/_chunks-es/spinner.js +0 -16
  67. package/dist/_chunks-es/spinner.js.map +0 -1
  68. package/dist/_chunks-es/watchAction.js +0 -160
  69. package/dist/_chunks-es/watchAction.js.map +0 -1
  70. package/dist/_chunks-es/watchConfigFiles.js +0 -49
  71. package/dist/_chunks-es/watchConfigFiles.js.map +0 -1
package/MIGRATE.md ADDED
@@ -0,0 +1,152 @@
1
+ # Migrating to `@sanity/pkg-utils` v12
2
+
3
+ v12 replaced the rollup/rolldown build stack with [`tsdown`](https://tsdown.dev) +
4
+ [`@sanity/tsdown-config`](https://github.com/sanity-io/pkg-utils/tree/main/packages/@sanity/tsdown-config#readme).
5
+
6
+ Most packages need **no changes**. If your `package.config.ts` uses a removed option, the build
7
+ stops with an error that contains these same migration instructions (skipped when
8
+ `NODE_ENV=production`, or with `legacyChecks: false`).
9
+
10
+ ## TL;DR
11
+
12
+ | v11 | v12 |
13
+ | ----------------------------------- | ------------------------------------------------------------------- |
14
+ | `dts: 'rolldown'` | delete it (it's the default now) |
15
+ | `dts: 'api-extractor'` | delete it (types come from tsdown) |
16
+ | `tsgo: true` | `dts: {tsgo: true}` |
17
+ | `babel: {reactCompiler: true}` | `reactCompiler: true` |
18
+ | `reactCompilerOptions: {...}` | `reactCompiler: {...}` |
19
+ | `babel: {styledComponents: true}` | `styledComponents: true` |
20
+ | `babel: {plugins: [...]}` | `plugins` + [`@rolldown/plugin-babel`](#custom-babel-plugins) |
21
+ | `rollup: {vanillaExtract: true}` | `vanillaExtract: true` |
22
+ | `rollup: {plugins: [...]}` | `plugins: [...]` |
23
+ | `rollup: {optimizeLodash: ...}` | removed — see [lodash](#lodash) |
24
+ | `extract: {enabled: false}` | `tsdoc: false` |
25
+ | `extract: {rules, customTags}` | `tsdoc: {rules, customTags}` |
26
+ | `extract: {bundledPackages: [...]}` | `deps: {alwaysBundle: [...]}` — see [type inlining](#type-inlining) |
27
+ | `external: [...]` | `deps: {neverBundle: [...]}` (deprecated, still works) |
28
+ | `external: (prev) => prev.filter()` | `deps: {alwaysBundle: [...]}` (deprecated, still works) |
29
+ | `jsx`, `jsxFactory`, … | `tsconfig.json` `compilerOptions.jsx` and friends |
30
+ | `process.env.PKG_FORMAT` | [`package.json#imports` conditions](#pkg_format-and-pkg_runtime) |
31
+ | `process.env.PKG_RUNTIME` | [`package.json#imports` conditions](#pkg_format-and-pkg_runtime) |
32
+ | `process.env.PKG_FILE_PATH` | [`import.meta.url`](#pkg_file_path) |
33
+ | `pkg build --clean` | delete it (cleaning is on by default; `--no-clean` skips it) |
34
+
35
+ Other behavior changes:
36
+
37
+ - **Node 20 is no longer supported for running builds**: `engines.node` is
38
+ `^22.18.0 || >=24.11.0` (tsdown's requirement). The published output is unaffected.
39
+ - **Shared chunks are content-hashed** (`_chunks-[format]` folders are gone), so a chunk can
40
+ never take an entry's filename ([sanity-io/ui#2262](https://github.com/sanity-io/ui/issues/2262)).
41
+ - **`pkg check` runs [publint](https://publint.dev)** on the packed package (with
42
+ `publishConfig` applied) instead of the esbuild resolution checks. Fix what it reports — it
43
+ lints what consumers actually install.
44
+ - **Builds keep `exports` in sync**: the map is regenerated from the build (with the
45
+ `source`-condition development pattern and a `source`-less `publishConfig.exports`), including
46
+ in CI — so environments that set `CI=true` without meaning "skip package.json" still behave.
47
+ - `tsdown.config.*` files are **never** loaded by `pkg build` — `package.config.ts` is the only
48
+ config source. For customization beyond the config surface, use `tsdown` +
49
+ `@sanity/tsdown-config` directly.
50
+
51
+ ## `PKG_FORMAT` and `PKG_RUNTIME`
52
+
53
+ The `process.env.PKG_FORMAT` and `process.env.PKG_RUNTIME` build-time constants are gone
54
+ (`process.env.PKG_VERSION` remains). Use
55
+ [conditional `package.json#imports`](https://nodejs.org/api/packages.html#imports) instead —
56
+ they express the same thing with more precision, and conditions compose (`require` vs `import`,
57
+ `node`/`browser`/`worker`, `deno`/`bun`, `react-server`, …).
58
+
59
+ ### Per-platform code, resolved at build time (replaces `PKG_RUNTIME`)
60
+
61
+ Give each platform its own file; every build of the waterfall inlines the matching condition
62
+ (the `browser`/`node` variant builds pick their files, everything else gets `default`):
63
+
64
+ ```json
65
+ {
66
+ "imports": {
67
+ "#env": {
68
+ "browser": "./src/env.browser.ts",
69
+ "node": "./src/env.node.ts",
70
+ "default": "./src/env.default.ts"
71
+ }
72
+ }
73
+ }
74
+ ```
75
+
76
+ ```ts
77
+ // src/index.ts
78
+ export {env} from '#env'
79
+ ```
80
+
81
+ ### Per-format (or per-runtime) code, resolved at load time (replaces `PKG_FORMAT`)
82
+
83
+ Bundled code can't branch per output format at build time — one module graph feeds both
84
+ formats. Point the import map at two small **shipped** files and keep the specifier external,
85
+ so Node (and consumers' bundlers) resolve it when the package loads:
86
+
87
+ ```json
88
+ {
89
+ "imports": {
90
+ "#format": {
91
+ "require": "./format.cjs",
92
+ "default": "./format.mjs"
93
+ }
94
+ },
95
+ "files": ["dist", "format.cjs", "format.mjs"]
96
+ }
97
+ ```
98
+
99
+ ```ts
100
+ // package.config.ts — keep `#…` specifiers external
101
+ export default defineConfig({
102
+ deps: {neverBundle: [/^#/]},
103
+ })
104
+ ```
105
+
106
+ ## `PKG_FILE_PATH`
107
+
108
+ Use `import.meta.url` — it works in both output formats (the CJS output rewrites it to
109
+ `require("url").pathToFileURL(__filename).href`):
110
+
111
+ ```ts
112
+ import {fileURLToPath} from 'node:url'
113
+
114
+ const filePath = fileURLToPath(import.meta.url)
115
+ ```
116
+
117
+ ## Custom Babel plugins
118
+
119
+ Install [`@rolldown/plugin-babel`](https://www.npmjs.com/package/@rolldown/plugin-babel) in
120
+ your package and pass it through `plugins`:
121
+
122
+ ```ts
123
+ import pluginBabel from '@rolldown/plugin-babel'
124
+ import {defineConfig} from '@sanity/pkg-utils'
125
+
126
+ export default defineConfig({
127
+ plugins: [await pluginBabel({plugins: ['babel-plugin-example']})],
128
+ })
129
+ ```
130
+
131
+ (`styledComponents` no longer needs Babel at all — it uses oxc's native port, so
132
+ `babel-plugin-styled-components` can be uninstalled.)
133
+
134
+ ## Type inlining
135
+
136
+ Type inlining follows the bundling decisions now:
137
+
138
+ - imported `devDependencies` are inlined automatically (JS **and** types),
139
+ - `deps: {alwaysBundle: [...]}` force-inlines a `dependency`/`peerDependency` (JS **and** types).
140
+
141
+ Inlining only the _types_ of an external dependency (the v11 `extract.bundledPackages` pattern)
142
+ has no successor.
143
+
144
+ Note tsdown's matching semantics: strings match exactly (or as globs), so covering subpath
145
+ imports takes a pattern like `/^@scope\/name(\/|$)/`.
146
+
147
+ ## lodash
148
+
149
+ The lodash import optimization is gone, including the implicit auto-enable when `lodash` was a
150
+ dependency. Preferably drop lodash altogether (see [e18e.dev](https://e18e.dev) for
151
+ replacements like [`es-toolkit`](https://es-toolkit.dev)), or import from `lodash-es`, which
152
+ tree-shakes in consumers without build-time rewriting.
package/README.md CHANGED
@@ -28,6 +28,28 @@ pkg-utils watch
28
28
 
29
29
  Run `pkg-utils -h` for more information on CLI usage.
30
30
 
31
+ ## How it works
32
+
33
+ Since v12, `@sanity/pkg-utils` composes [`tsdown`](https://tsdown.dev) and
34
+ [`@sanity/tsdown-config`](https://github.com/sanity-io/pkg-utils/tree/main/packages/@sanity/tsdown-config#readme):
35
+ the hand-written `exports` map in `package.json` stays the input that decides what gets built, and
36
+ for every platform (the default build, plus one extra build per `browser`/`node` exports condition)
37
+ pkg-utils resolves a config from `@sanity/tsdown-config`, layers its own opinions over it
38
+ (browserslist-driven syntax targets, build-time constants, exports reconciliation), and runs
39
+ tsdown's programmatic `build()`.
40
+
41
+ `tsdown.config.*` files are never loaded — `package.config.ts` is the only configuration source of
42
+ `pkg build`. For customizations beyond the options below, use `tsdown` +
43
+ `@sanity/tsdown-config` directly instead.
44
+
45
+ Builds regenerate the `exports` map from the build (with `source` conditions for development, and
46
+ a `source`-less `publishConfig.exports` for publishing) and keep it in sync — including in CI —
47
+ so environments that set `CI=true` without meaning "skip package.json" still behave correctly.
48
+ For conditional entries, generated conditions are materialized in both maps, then the authored
49
+ subpath and condition order of each map is preserved independently on later builds. Plain-string
50
+ entries keep their compact shape. This lets you reorder conditions directly in `package.json`;
51
+ earlier matching conditions take precedence over later ones.
52
+
31
53
  ## Configuration
32
54
 
33
55
  `@sanity/pkg-utils` reads most of its configuration from `package.json`. But sometimes you need more
@@ -40,7 +62,7 @@ control. You may then add a configuration file named `package.config.ts` (or `.m
40
62
  import {defineConfig} from '@sanity/pkg-utils'
41
63
 
42
64
  export default defineConfig({
43
- extract: {
65
+ tsdoc: {
44
66
  rules: {
45
67
  // do not require internal members to be prefixed with `_`
46
68
  'ae-internal-missing-underscore': 'off',
@@ -62,12 +84,35 @@ export default defineConfig({
62
84
  An array of entry points to bundle. This is useful if you want to bundle something that should not
63
85
  be exported by the package, e.g. CLI scripts or Node.js workers.
64
86
 
87
+ #### `clean`
88
+
89
+ - Type: `boolean | string[]`
90
+ - Default: `true`
91
+
92
+ tsdown's [`clean` option](https://tsdown.dev/options/cleaning), passed through as-is. Cleaning is
93
+ on by default: `true` cleans the `dist` folder before the build, `false` skips cleaning, and a
94
+ `string[]` replaces the default with the listed paths/globs — include `dist` when you still want it
95
+ cleaned alongside other folders (e.g. `clean: ['dist', 'coverage']` replaces a
96
+ `"clean": "rimraf dist coverage"` script). `pkg build --no-clean` skips cleaning for a single run.
97
+
65
98
  #### `define`
66
99
 
67
100
  - Type: `Record<string, string | number | boolean | null | undefined>`
68
101
  - Default: `{}`
69
102
 
70
- An object defining globals within the package.
103
+ An object defining globals within the package. `process.env.PKG_VERSION` is always defined,
104
+ replaced with the package's `version` (overridable with a `PKG_VERSION` environment variable).
105
+
106
+ #### `deps`
107
+
108
+ - Type: `UserConfig['deps']`
109
+ - Default: `undefined`
110
+
111
+ tsdown's [`deps` option](https://tsdown.dev/options/dependencies), passed through as-is:
112
+ `neverBundle` marks dependencies as external, `alwaysBundle` forces a dependency to be inlined
113
+ (types included — type inlining follows the bundling decisions). Note tsdown's matching semantics:
114
+ strings match exactly (or as globs), so covering subpath imports takes a pattern like
115
+ `/^@scope\/name(\/|$)/`.
71
116
 
72
117
  #### `dist`
73
118
 
@@ -76,78 +121,56 @@ An object defining globals within the package.
76
121
 
77
122
  The path to the directory to which bundle and chunk files should be written.
78
123
 
79
- #### `exports`
80
-
81
- - Type: `PkgConfigProperty<PkgExports>`
82
- - Default: the value of `"exports"` in `package.json`
83
-
84
- Override or modify the value of the `exports` before it’s parsed internally.
124
+ #### `dts`
85
125
 
86
- #### `extract`
87
-
88
- - Type:
89
- ```ts
90
- {
91
- rules?: {
92
- 'ae-incompatible-release-tags'?: PkgRuleLevel
93
- 'ae-internal-missing-underscore'?: PkgRuleLevel
94
- 'ae-missing-release-tag'?: PkgRuleLevel
95
- }
96
- }
97
- ```
126
+ - Type: `false | DtsOptions`
98
127
  - Default: `undefined`
99
128
 
100
- Configure the level of reporting of [API Extractor](https://api-extractor.com/) (which is used to bundle the
101
- type definitions, as well as lint the TSDoc of the package).
102
-
103
- #### `external`
104
-
105
- - Type: `string[]`
106
- - Default: `[]`
107
-
108
- Packages to exclude from bundles.
109
-
110
- #### `jsx`
111
-
112
- - Type: `'transform' | 'preserve' | 'automatic'`
113
- - Default: `'automatic'`
114
-
115
- Strategy for bundling JSX.
116
-
117
- #### `jsxFactory`
118
-
119
- - Type: `string`
120
- - Default: `'createElement'`
121
-
122
- The name of the function that creates JSX elements.
129
+ tsdown's [`dts` options](https://tsdown.dev/options/dts), passed through as-is (an object, or
130
+ `false` to skip generating `.d.ts` files entirely). For example `dts: {tsgo: true}` selects the
131
+ Go-native TypeScript compiler for type generation.
123
132
 
124
- #### `jsxFragment`
133
+ #### `exports`
125
134
 
126
- - Type: `string`
127
- - Default: `'Fragment'`
135
+ - Type: `PkgConfigProperty<PkgExports>`
136
+ - Default: the value of `"exports"` in `package.json`
128
137
 
129
- The name of JSX fragment elements.
138
+ Override or modify the value of the `exports` before it’s parsed internally.
130
139
 
131
- #### `jsxImportSource`
140
+ #### `legacyChecks`
132
141
 
133
- - Type: `string`
134
- - Default: `'react'`
142
+ - Type: `boolean`
143
+ - Default: `process.env.NODE_ENV !== 'production'`
135
144
 
136
- The name of the library from which to import JSX factory and fragment names.
145
+ Gates the migration checks for options that were removed or deprecated in v12 (they throw helpful
146
+ errors with migration instructions). On by default outside production builds, where migration
147
+ mistakes surface during development; skipped when `NODE_ENV=production`.
137
148
 
138
149
  #### `minify`
139
150
 
140
151
  - Type: `boolean`
141
152
  - Default: `false`
142
153
 
143
- Whether to minify the bundled JavaScript.
154
+ Whether to fully minify the bundled JavaScript (identifier mangling and whitespace removal
155
+ included). The output is always compressed (constant folding, dead code elimination) with
156
+ function/class names preserved.
144
157
 
145
- #### `rollup.plugins`
158
+ #### `plugins`
146
159
 
147
- - Type: `PkgConfigProperty<RollupPlugin[]>`
160
+ - Type: `UserConfig['plugins']`
148
161
  - Default: `[]`
149
162
 
150
- Rollup plugins to load when bundling.
163
+ Extra [rolldown plugins](https://tsdown.dev/advanced/plugins), appended after the plugins
164
+ pkg-utils sets up. Most Rollup plugins are also compatible.
165
+
166
+ #### `reactCompiler`
167
+
168
+ - Type: `boolean | ReactCompilerOptions`
169
+ - Default: `false`
170
+
171
+ Runs `babel-plugin-react-compiler` (which must be installed) on the source files before they are
172
+ bundled, so published components are memoized automatically. Pass `true` for the defaults, or an
173
+ options object to configure the compiler (e.g. `{target: '18'}`).
151
174
 
152
175
  #### `runtime`
153
176
 
@@ -170,6 +193,14 @@ Whether to include source map files.
170
193
 
171
194
  The path to the directory in which source code is located.
172
195
 
196
+ #### `styledComponents`
197
+
198
+ - Type: `boolean | StyledComponentsOptions`
199
+ - Default: `false`
200
+
201
+ Applies the `styled-components` transform (`displayName`, `componentId`, CSS minification, etc)
202
+ using oxc's native port of `babel-plugin-styled-components` — no Babel dependencies required.
203
+
173
204
  #### `tsconfig`
174
205
 
175
206
  - Type: `string`
@@ -177,6 +208,34 @@ The path to the directory in which source code is located.
177
208
 
178
209
  The path to the TypeScript configuration file.
179
210
 
211
+ #### `tsdoc`
212
+
213
+ - Type: `false | {customTags?: TSDocCustomTag[]; rules?: {...}}`
214
+ - Default: `undefined` (enabled)
215
+
216
+ Runs [API Extractor](https://api-extractor.com/) during `pkg check` to check that TSDoc tags are
217
+ valid and release tags are correct. Set `tsdoc: false` to disable it.
218
+
219
+ #### `vanillaExtract`
220
+
221
+ - Type: `boolean | PackageVanillaExtractOptions`
222
+ - Default: `false`
223
+
224
+ Extracts the CSS from [vanilla-extract](https://vanilla-extract.style) `.css.ts` files into
225
+ `dist/bundle.css` (minified and lowered with `lightningcss`), injects the self-referential
226
+ `import "<pkg>/bundle.css"`, emits a no-op `bundle-css.js` shim for runtimes that cannot import
227
+ `.css` files, and writes the conditional `"./bundle.css"` export to `package.json`.
228
+
229
+ ## Migrating to v12
230
+
231
+ v12 replaced the rollup/rolldown build stack with `tsdown` + `@sanity/tsdown-config`. Most
232
+ packages need no changes; removed options throw an error with migration instructions when set
233
+ (gated by [`legacyChecks`](#legacychecks)), and deprecated options keep working with a warning.
234
+
235
+ See [MIGRATE.md](./MIGRATE.md) for the full guide — including how
236
+ [conditional `package.json#imports`](https://nodejs.org/api/packages.html#imports) replace the
237
+ removed `PKG_FORMAT`/`PKG_RUNTIME` constants, and `import.meta.url` replaces `PKG_FILE_PATH`.
238
+
180
239
  ## License
181
240
 
182
241
  MIT
@@ -0,0 +1,146 @@
1
+ import { n as createLogger, r as isRecord, t as handleError } from "./handleError-83GwKIFM.js";
2
+ import { a as loadPkgWithReporting, o as loadConfig, t as resolveBuildContext } from "./resolveBuildContext-CbwvYKj1.js";
3
+ import { t as createSpinner } from "./spinner-DAHe7SuT.js";
4
+ import { n as resolveTsdownBuilds, t as resolveTsdownConfig } from "./resolveTsdownConfig-CGE_7cMM.js";
5
+ import { existsSync, readFileSync, rmSync, writeFileSync } from "node:fs";
6
+ import path from "node:path";
7
+ import { up } from "empathic/package";
8
+ import { build } from "tsdown";
9
+ const RE_TS_SOURCE = /\.[cm]?tsx?$/;
10
+ /**
11
+ * Build the distribution files of a npm package.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * import {build} from '@sanity/pkg-utils'
16
+ *
17
+ * build({
18
+ * cwd: process.cwd(),
19
+ * tsconfig: 'tsconfig.dist.json,
20
+ * }).then(() => {
21
+ * console.log('successfully built')
22
+ * }).catch((err) => {
23
+ * console.log(`build error: ${err.message}`)
24
+ * })
25
+ * ```
26
+ *
27
+ * @public
28
+ */
29
+ async function build$1(options) {
30
+ let { cwd, emitDeclarationOnly, strict = !1, tsconfig: tsconfigOption, clean = !0, quiet = !1 } = options, logger = createLogger(quiet), pkgPath = up({ cwd });
31
+ if (!pkgPath) throw Error("no package.json found", { cause: { cwd } });
32
+ let config = await loadConfig({
33
+ cwd,
34
+ pkgPath
35
+ }), { parseStrictOptions } = await import("./resolveBuildContext-CbwvYKj1.js").then((n) => n.n), strictOptions = parseStrictOptions(config?.strictOptions ?? {}), pkg = await loadPkgWithReporting({
36
+ pkgPath,
37
+ logger,
38
+ strict,
39
+ strictOptions
40
+ }), tsconfig = tsconfigOption || config?.tsconfig || "tsconfig.json", ctx = await resolveBuildContext({
41
+ config,
42
+ cwd,
43
+ emitDeclarationOnly,
44
+ logger,
45
+ pkg,
46
+ strict,
47
+ tsconfig
48
+ });
49
+ warnAboutTsdownConfigFiles(cwd, logger);
50
+ let builds = resolveTsdownBuilds(ctx), first = !0;
51
+ for (let buildDef of builds) {
52
+ if (ctx.emitDeclarationOnly && !buildDef.entries.some((entry) => RE_TS_SOURCE.test(entry.source))) continue;
53
+ let taskName = buildTaskName(buildDef), spinner = createSpinner(taskName, quiet);
54
+ try {
55
+ let inlineConfig = await resolveTsdownConfig(ctx, buildDef, { clean: first && clean });
56
+ first = !1;
57
+ let bundles = await build(inlineConfig);
58
+ ctx.emitDeclarationOnly && removeNonDeclarationOutputs(bundles), buildDef.canonical && restoreAuthoredTypes(ctx), spinner.complete(), ctx.logger.log(), printBuildOutputs(ctx, bundles), ctx.logger.log();
59
+ } catch (err) {
60
+ if (spinner.error(), err instanceof Error) {
61
+ let RE_CWD = new RegExp(escapeRegExp(cwd), "g");
62
+ ctx.logger.error((err.stack || err.message).replace(RE_CWD, ".")), ctx.logger.log();
63
+ }
64
+ process.exit(1);
65
+ }
66
+ }
67
+ }
68
+ function buildTaskName(buildDef) {
69
+ let formats = Array.from(new Set(buildDef.entries.flatMap((entry) => entry.formats)));
70
+ return `build ${buildDef.key} (${formats.join(", ") || "types"})`;
71
+ }
72
+ const RE_DTS_OUTPUT = /\.d\.[mc]?ts(\.map)?$/;
73
+ /** Removes every emitted file that is not a declaration file (or its sourcemap). */
74
+ function removeNonDeclarationOutputs(bundles) {
75
+ for (let bundle of bundles) for (let chunk of bundle.chunks) RE_DTS_OUTPUT.test(chunk.fileName) || (rmSync(path.join(chunk.outDir, chunk.fileName), { force: !0 }), rmSync(path.join(chunk.outDir, `${chunk.fileName}.map`), { force: !0 }));
76
+ }
77
+ /**
78
+ * Prints `<pkg>: <source> → <output>` for every entry chunk (JS and `.d.ts`) that tsdown
79
+ * emitted, mirroring the per-file output of previous majors.
80
+ */
81
+ function printBuildOutputs(ctx, bundles) {
82
+ let { cwd, logger, pkg } = ctx, lines = /* @__PURE__ */ new Set();
83
+ for (let bundle of bundles) for (let chunk of bundle.chunks) {
84
+ if (chunk.type !== "chunk" || !chunk.isEntry || !chunk.facadeModuleId || ctx.emitDeclarationOnly && !RE_DTS_OUTPUT.test(chunk.fileName)) continue;
85
+ let source = `./${path.relative(cwd, chunk.facadeModuleId).replaceAll("\\", "/").replace(/\.d\.([mc]?)ts$/, ".$1ts")}`, output = `./${path.relative(cwd, path.join(chunk.outDir, chunk.fileName)).replaceAll("\\", "/")}`;
86
+ lines.add(`${pkg.name}: ${source} \u2192 ${output}`);
87
+ }
88
+ for (let line of Array.from(lines).toSorted()) logger.log(line);
89
+ }
90
+ /**
91
+ * tsdown's exports generation rewrites the top-level `types` field alongside `main`/`module`
92
+ * when the `legacy` fields are maintained, preferring the CJS declarations (`.d.cts`) for
93
+ * dual-format packages. The hand-written value is authoritative here (the Sanity convention
94
+ * points `types` at the ESM `.d.ts`), so it is restored after the canonical build.
95
+ */
96
+ function restoreAuthoredTypes(ctx) {
97
+ let authoredTypes = ctx.pkg.types;
98
+ if (!authoredTypes) return;
99
+ let pkgPath = path.resolve(ctx.cwd, "package.json"), text;
100
+ try {
101
+ text = readFileSync(pkgPath, "utf8");
102
+ } catch {
103
+ return;
104
+ }
105
+ let json = JSON.parse(text);
106
+ if (!isRecord(json) || json.types === authoredTypes) return;
107
+ json.types = authoredTypes;
108
+ let indent = /^([ \t]+)\S/m.exec(text)?.[1] ?? 2, output = JSON.stringify(json, null, indent);
109
+ text.endsWith("\n") && (output += "\n"), writeFileSync(pkgPath, output, "utf8");
110
+ }
111
+ /**
112
+ * pkg-utils owns its own experience: `tsdown.config.*` files are never loaded in pkg-utils
113
+ * mode (`package.config.ts` is the sole config source), so their presence is worth a warning.
114
+ */
115
+ function warnAboutTsdownConfigFiles(cwd, logger) {
116
+ let found = [
117
+ "tsdown.config.ts",
118
+ "tsdown.config.mts",
119
+ "tsdown.config.cts",
120
+ "tsdown.config.js",
121
+ "tsdown.config.mjs",
122
+ "tsdown.config.cjs",
123
+ "tsdown.config.json"
124
+ ].find((candidate) => existsSync(path.resolve(cwd, candidate)));
125
+ found && logger.warn(`found \`${found}\`, which @sanity/pkg-utils does not load — \`package.config.ts\` is the only config source of \`pkg build\`. Either migrate the package fully to tsdown (and drop @sanity/pkg-utils), or move the configuration into \`package.config.ts\`.`);
126
+ }
127
+ function escapeRegExp(value) {
128
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
129
+ }
130
+ async function buildAction(options) {
131
+ try {
132
+ await build$1({
133
+ cwd: process.cwd(),
134
+ emitDeclarationOnly: options.emitDeclarationOnly,
135
+ strict: options.strict,
136
+ tsconfig: options.tsconfig,
137
+ clean: options.clean,
138
+ quiet: options.quiet
139
+ });
140
+ } catch (err) {
141
+ handleError(err);
142
+ }
143
+ }
144
+ export { buildAction };
145
+
146
+ //# sourceMappingURL=buildAction-D-M3KYyN.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buildAction-D-M3KYyN.js","names":["build","findPkgPath","tsdownBuild","build"],"sources":["../src/node/build.ts","../src/cli/buildAction.ts"],"sourcesContent":["import {existsSync, readFileSync, rmSync, writeFileSync} from 'node:fs'\nimport path from 'node:path'\nimport {up as findPkgPath} from 'empathic/package'\nimport {build as tsdownBuild, type TsdownBundle} from 'tsdown'\nimport {loadConfig} from './core/config/loadConfig.ts'\nimport {isRecord} from './core/isRecord.ts'\nimport {loadPkgWithReporting} from './core/pkg/loadPkgWithReporting.ts'\nimport {createLogger, type Logger} from './logger.ts'\nimport {resolveBuildContext} from './resolveBuildContext.ts'\nimport {createSpinner} from './spinner.ts'\nimport {\n resolveTsdownBuilds,\n type TsdownBuild as TsdownBuildDef,\n} from './tasks/tsdown/resolveTsdownBuilds.ts'\nimport {resolveTsdownConfig} from './tasks/tsdown/resolveTsdownConfig.ts'\n\nconst RE_TS_SOURCE = /\\.[cm]?tsx?$/\n\n/**\n * Build the distribution files of a npm package.\n *\n * @example\n * ```ts\n * import {build} from '@sanity/pkg-utils'\n *\n * build({\n * cwd: process.cwd(),\n * tsconfig: 'tsconfig.dist.json,\n * }).then(() => {\n * console.log('successfully built')\n * }).catch((err) => {\n * console.log(`build error: ${err.message}`)\n * })\n * ```\n *\n * @public\n */\nexport async function build(options: {\n cwd: string\n emitDeclarationOnly?: boolean\n strict?: boolean\n tsconfig?: string\n clean?: boolean\n quiet?: boolean\n}): Promise<void> {\n const {\n cwd,\n emitDeclarationOnly,\n strict = false,\n tsconfig: tsconfigOption,\n // `--no-clean` skips cleaning for this run; `true` (the CLI default — `--clean` still\n // parses as a no-op for v11 compatibility) defers to the `clean` config option\n clean = true,\n quiet = false,\n } = options\n const logger = createLogger(quiet)\n\n const pkgPath = findPkgPath({cwd})\n if (!pkgPath) {\n throw new Error('no package.json found', {cause: {cwd}})\n }\n const config = await loadConfig({cwd, pkgPath})\n\n const {parseStrictOptions} = await import('./strict.ts')\n const strictOptions = parseStrictOptions(config?.strictOptions ?? {})\n const pkg = await loadPkgWithReporting({pkgPath, logger, strict, strictOptions})\n\n const tsconfig = tsconfigOption || config?.tsconfig || 'tsconfig.json'\n\n const ctx = await resolveBuildContext({\n config,\n cwd,\n emitDeclarationOnly,\n logger,\n pkg,\n strict,\n tsconfig,\n })\n\n warnAboutTsdownConfigFiles(cwd, logger)\n\n const builds = resolveTsdownBuilds(ctx)\n\n let first = true\n for (const buildDef of builds) {\n // A types-only run skips builds without TypeScript sources entirely\n if (\n ctx.emitDeclarationOnly &&\n !buildDef.entries.some((entry) => RE_TS_SOURCE.test(entry.source))\n ) {\n continue\n }\n\n const taskName = buildTaskName(buildDef)\n const spinner = createSpinner(taskName, quiet)\n\n try {\n const inlineConfig = await resolveTsdownConfig(ctx, buildDef, {clean: first && clean})\n first = false\n\n const bundles = await tsdownBuild(inlineConfig)\n\n if (ctx.emitDeclarationOnly) {\n // `dts.emitDtsOnly` suppresses the JS chunks of the ES pass, but the CJS pass emits\n // its JS regardless (only its extra dts pass runs the dts plugin) — a types-only\n // build removes everything that is not a declaration file\n removeNonDeclarationOutputs(bundles)\n }\n\n if (buildDef.canonical) {\n restoreAuthoredTypes(ctx)\n }\n\n spinner.complete()\n ctx.logger.log()\n\n printBuildOutputs(ctx, bundles)\n ctx.logger.log()\n } catch (err) {\n spinner.error()\n\n if (err instanceof Error) {\n const RE_CWD = new RegExp(escapeRegExp(cwd), 'g')\n\n ctx.logger.error((err.stack || err.message).replace(RE_CWD, '.'))\n ctx.logger.log()\n }\n\n process.exit(1)\n }\n }\n}\n\nfunction buildTaskName(buildDef: TsdownBuildDef): string {\n const formats = Array.from(new Set(buildDef.entries.flatMap((entry) => entry.formats)))\n return `build ${buildDef.key} (${formats.join(', ') || 'types'})`\n}\n\nconst RE_DTS_OUTPUT = /\\.d\\.[mc]?ts(\\.map)?$/\n\n/** Removes every emitted file that is not a declaration file (or its sourcemap). */\nfunction removeNonDeclarationOutputs(bundles: TsdownBundle[]): void {\n for (const bundle of bundles) {\n for (const chunk of bundle.chunks) {\n if (RE_DTS_OUTPUT.test(chunk.fileName)) continue\n rmSync(path.join(chunk.outDir, chunk.fileName), {force: true})\n rmSync(path.join(chunk.outDir, `${chunk.fileName}.map`), {force: true})\n }\n }\n}\n\n/**\n * Prints `<pkg>: <source> → <output>` for every entry chunk (JS and `.d.ts`) that tsdown\n * emitted, mirroring the per-file output of previous majors.\n */\nfunction printBuildOutputs(\n ctx: {cwd: string; emitDeclarationOnly: boolean; logger: Logger; pkg: {name: string}},\n bundles: TsdownBundle[],\n): void {\n const {cwd, logger, pkg} = ctx\n const lines = new Set<string>()\n\n for (const bundle of bundles) {\n for (const chunk of bundle.chunks) {\n if (chunk.type !== 'chunk' || !chunk.isEntry || !chunk.facadeModuleId) continue\n if (ctx.emitDeclarationOnly && !RE_DTS_OUTPUT.test(chunk.fileName)) continue\n const source = `./${path\n .relative(cwd, chunk.facadeModuleId)\n .replaceAll('\\\\', '/')\n // the dts chunks facade the fake `.d.ts` module ids of rolldown-plugin-dts; print the\n // actual `.ts` source instead\n .replace(/\\.d\\.([mc]?)ts$/, '.$1ts')}`\n const output = `./${path\n .relative(cwd, path.join(chunk.outDir, chunk.fileName))\n .replaceAll('\\\\', '/')}`\n lines.add(`${pkg.name}: ${source} \\u2192 ${output}`)\n }\n }\n\n for (const line of Array.from(lines).toSorted()) {\n logger.log(line)\n }\n}\n\n/**\n * tsdown's exports generation rewrites the top-level `types` field alongside `main`/`module`\n * when the `legacy` fields are maintained, preferring the CJS declarations (`.d.cts`) for\n * dual-format packages. The hand-written value is authoritative here (the Sanity convention\n * points `types` at the ESM `.d.ts`), so it is restored after the canonical build.\n */\nfunction restoreAuthoredTypes(ctx: {cwd: string; pkg: {types?: string | undefined}}): void {\n const authoredTypes = ctx.pkg.types\n if (!authoredTypes) return\n\n const pkgPath = path.resolve(ctx.cwd, 'package.json')\n let text: string\n try {\n text = readFileSync(pkgPath, 'utf8')\n } catch {\n return\n }\n const json: unknown = JSON.parse(text)\n if (!isRecord(json) || json['types'] === authoredTypes) return\n json['types'] = authoredTypes\n\n const indent = /^([ \\t]+)\\S/m.exec(text)?.[1] ?? 2\n let output = JSON.stringify(json, null, indent)\n if (text.endsWith('\\n')) output += '\\n'\n writeFileSync(pkgPath, output, 'utf8')\n}\n\n/**\n * pkg-utils owns its own experience: `tsdown.config.*` files are never loaded in pkg-utils\n * mode (`package.config.ts` is the sole config source), so their presence is worth a warning.\n */\nfunction warnAboutTsdownConfigFiles(cwd: string, logger: Logger): void {\n const candidates = [\n 'tsdown.config.ts',\n 'tsdown.config.mts',\n 'tsdown.config.cts',\n 'tsdown.config.js',\n 'tsdown.config.mjs',\n 'tsdown.config.cjs',\n 'tsdown.config.json',\n ]\n const found = candidates.find((candidate) => existsSync(path.resolve(cwd, candidate)))\n if (found) {\n logger.warn(\n `found \\`${found}\\`, which @sanity/pkg-utils does not load — \\`package.config.ts\\` is the only config source of \\`pkg build\\`. Either migrate the package fully to tsdown (and drop @sanity/pkg-utils), or move the configuration into \\`package.config.ts\\`.`,\n )\n }\n}\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&')\n}\n","import {build} from '../node/build.ts'\nimport {handleError} from './handleError.ts'\n\nexport async function buildAction(options: {\n emitDeclarationOnly?: boolean\n strict?: boolean\n tsconfig?: string\n clean?: boolean\n quiet?: boolean\n}): Promise<void> {\n try {\n await build({\n cwd: process.cwd(),\n emitDeclarationOnly: options.emitDeclarationOnly,\n strict: options.strict,\n tsconfig: options.tsconfig,\n clean: options.clean,\n quiet: options.quiet,\n })\n } catch (err) {\n handleError(err)\n }\n}\n"],"mappings":"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"}