@sanity/pkg-utils 6.9.3 → 6.9.4-canary.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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanity/pkg-utils",
3
- "version": "6.9.3",
3
+ "version": "6.9.4-canary.1",
4
4
  "description": "Simple utilities for modern npm packages.",
5
5
  "keywords": [
6
6
  "sanity-io",
@@ -97,7 +97,7 @@
97
97
  "outdent": "^0.8.0",
98
98
  "parse-git-config": "^3.0.0",
99
99
  "pkg-up": "^3.1.0",
100
- "prettier": "^3.3.1",
100
+ "prettier": "^3.3.2",
101
101
  "pretty-bytes": "^5.6.0",
102
102
  "prompts": "^2.4.2",
103
103
  "recast": "0.23.9",
@@ -125,8 +125,8 @@
125
125
  "@types/semver": "^7.5.8",
126
126
  "@types/treeify": "^1.0.3",
127
127
  "@types/uuid": "^9.0.8",
128
- "@typescript-eslint/eslint-plugin": "^7.12.0",
129
- "@typescript-eslint/parser": "^7.12.0",
128
+ "@typescript-eslint/eslint-plugin": "^7.13.0",
129
+ "@typescript-eslint/parser": "^7.13.0",
130
130
  "browserslist-to-esbuild": "2.1.1",
131
131
  "commitizen": "^4.3.0",
132
132
  "cpx": "^1.5.0",
@@ -146,7 +146,7 @@
146
146
  "typescript": "5.4.5",
147
147
  "vitest": "^1.6.0",
148
148
  "vitest-github-actions-reporter": "^0.11.1",
149
- "@sanity/pkg-utils": "6.9.3"
149
+ "@sanity/pkg-utils": "6.9.4-canary.1"
150
150
  },
151
151
  "peerDependencies": {
152
152
  "typescript": "5.4.x"
@@ -16,26 +16,30 @@ export type PkgRuntime = '*' | 'browser' | 'node'
16
16
  /** @public */
17
17
  export interface PkgExport {
18
18
  /** @internal */
19
- _exported?: boolean
20
- browser?: {
19
+ '_exported'?: boolean
20
+ 'browser'?: {
21
21
  source: string
22
22
  import?: string
23
23
  require?: string
24
24
  }
25
+ 'react-compiler'?: {
26
+ source?: string
27
+ default: string
28
+ }
25
29
  // electron?: {
26
30
  // node?: string
27
31
  // default?: string
28
32
  // }
29
- node?: {
33
+ 'node'?: {
30
34
  source?: string
31
35
  import?: string
32
36
  require?: string
33
37
  }
34
- types?: string
35
- source: string
36
- import?: string
37
- require?: string
38
- default: string
38
+ 'types'?: string
39
+ 'source': string
40
+ 'import'?: string
41
+ 'require'?: string
42
+ 'default': string
39
43
  }
40
44
 
41
45
  /** @public */
@@ -67,20 +71,105 @@ export interface TSDocCustomTag {
67
71
  allowMultiple?: boolean
68
72
  }
69
73
 
74
+ /**
75
+ * Until these types are on npm: https://github.com/facebook/react/blob/2ba462b665bb4691067e67db3cfbffc56959b788/compiler/packages/babel-plugin-react-compiler/src/Entrypoint/Options.ts#L34-L120
76
+ * @alpha
77
+ */
78
+ export interface ReactCompilerOptions {
79
+ logger?: ReactCompilerLogger | null
80
+
81
+ panicThreshold?: 'ALL_ERRORS' | 'CRITICAL_ERRORS' | 'NONE'
82
+
83
+ compilationMode?: 'infer' | 'syntax' | 'annotation' | 'all'
84
+
85
+ /*
86
+ * If enabled, Forget will import `useMemoCache` from the given module
87
+ * instead of `react/compiler-runtime`.
88
+ *
89
+ * ```
90
+ * // If set to "react-compiler-runtime"
91
+ * import {c as useMemoCache} from 'react-compiler-runtime';
92
+ * ```
93
+ */
94
+ runtimeModule?: string | null | undefined
95
+
96
+ /**
97
+ * By default React Compiler will skip compilation of code that suppresses the default
98
+ * React ESLint rules, since this is a strong indication that the code may be breaking React rules
99
+ * in some way.
100
+ *
101
+ * Use eslintSuppressionRules to pass a custom set of rule names: any code which suppresses the
102
+ * provided rules will skip compilation. To disable this feature (never bailout of compilation
103
+ * even if the default ESLint is suppressed), pass an empty array.
104
+ */
105
+ eslintSuppressionRules?: Array<string> | null | undefined
106
+
107
+ sources?: Array<string> | ((filename: string) => boolean) | null
108
+ }
109
+
110
+ /**
111
+ * @alpha
112
+ * Represents 'events' that may occur during compilation. Events are only
113
+ * recorded when a logger is set (through the config).
114
+ * These are the different types of events:
115
+ * CompileError:
116
+ * Forget skipped compilation of a function / file due to a known todo,
117
+ * invalid input, or compiler invariant being broken.
118
+ * CompileSuccess:
119
+ * Forget successfully compiled a function.
120
+ * PipelineError:
121
+ * Unexpected errors that occurred during compilation (e.g. failures in
122
+ * babel or other unhandled exceptions).
123
+ */
124
+ export type ReactCompilerLoggerEvent =
125
+ | {
126
+ kind: 'CompileError'
127
+ fnLoc: unknown
128
+ detail: unknown
129
+ }
130
+ | {
131
+ kind: 'CompileDiagnostic'
132
+ fnLoc: unknown
133
+ detail: unknown
134
+ }
135
+ | {
136
+ kind: 'CompileSuccess'
137
+ fnLoc: unknown
138
+ fnName: string | null
139
+ memoSlots: number
140
+ memoBlocks: number
141
+ memoValues: number
142
+ prunedMemoBlocks: number
143
+ prunedMemoValues: number
144
+ }
145
+ | {
146
+ kind: 'PipelineError'
147
+ fnLoc: unknown
148
+ data: string
149
+ }
150
+
151
+ /**
152
+ * @alpha
153
+ */
154
+ export type ReactCompilerLogger = {
155
+ logEvent: (filename: string | null, event: ReactCompilerLoggerEvent) => void
156
+ }
157
+
70
158
  /** @public */
71
159
  export interface PkgConfigOptions {
72
160
  /** @alpha */
73
161
  babel?: {
74
162
  plugins?: BabelPluginItem[] | null | undefined
75
163
  /** @alpha */
76
- reactCompiler?:
77
- | boolean
78
- | {
79
- compilationMode: 'infer' | 'annotation' | 'all'
80
- panicThreshold: 'all_errors' | 'critical_errors' | 'none'
81
- sources?: Array<string> | ((filename: string) => boolean) | null
82
- }
164
+ reactCompiler?: boolean
83
165
  }
166
+ /**
167
+ * Configure the React Compiler.
168
+ * To enable it, either:
169
+ * - set `babel.reactCompiler` to `true`
170
+ * - add a `react-compiler` export condition, before any `browser`, `require` or `import` conditions. After any `react-server` and `node` conditions
171
+ * @alpha */
172
+ reactCompilerOptions?: ReactCompilerOptions
84
173
  bundles?: PkgBundle[]
85
174
  /** @alpha */
86
175
  define?: Record<string, string | number | boolean | undefined | null>
@@ -21,25 +21,35 @@ const pkgSchema = z.object({
21
21
  z.union([
22
22
  z.custom<`./${string}.json`>((val) => /^\.\/.*\.json$/.test(val as string)),
23
23
  z.object({
24
- types: z.optional(z.string()),
25
- source: z.optional(z.string()),
26
- browser: z.optional(
24
+ 'types': z.optional(z.string()),
25
+ 'source': z.optional(z.string()),
26
+ 'browser': z.optional(
27
27
  z.object({
28
28
  source: z.string(),
29
29
  import: z.optional(z.string()),
30
30
  require: z.optional(z.string()),
31
31
  }),
32
32
  ),
33
- node: z.optional(
33
+ 'react-compiler': z.optional(
34
+ // z.union([
35
+ // @TODO add support for a string shortcut
36
+ // z.string(),
37
+ z.object({
38
+ source: z.optional(z.string()),
39
+ default: z.string(),
40
+ }),
41
+ // ]),
42
+ ),
43
+ 'node': z.optional(
34
44
  z.object({
35
45
  source: z.optional(z.string()),
36
46
  import: z.optional(z.string()),
37
47
  require: z.optional(z.string()),
38
48
  }),
39
49
  ),
40
- import: z.optional(z.string()),
41
- require: z.optional(z.string()),
42
- default: z.string(),
50
+ 'import': z.optional(z.string()),
51
+ 'require': z.optional(z.string()),
52
+ 'default': z.string(),
43
53
  }),
44
54
  z.object({
45
55
  types: z.optional(z.string()),
@@ -126,6 +126,8 @@ export async function resolveBuildContext(options: {
126
126
  exportEntry.browser?.require,
127
127
  exportEntry.node?.source && exportEntry.node.import,
128
128
  exportEntry.node?.source && exportEntry.node.require,
129
+ // @TODO implement this
130
+ // exportEntry['react-compiler']?.source && exportEntry['react-compiler']?.default,
129
131
  ].filter(Boolean) as string[]
130
132
  })
131
133
  .map((p) => path.resolve(cwd, p))
@@ -2,7 +2,14 @@ import fs from 'node:fs'
2
2
  import path from 'node:path'
3
3
 
4
4
  import type {BuildContext, PkgExport, PkgFormat, PkgRuntime} from './core'
5
- import type {BuildTask, DtsTask, RollupLegacyTask, RollupTask, RollupTaskEntry} from './tasks'
5
+ import type {
6
+ BuildTask,
7
+ DtsTask,
8
+ RollupLegacyTask,
9
+ RollupReactCompilerTask,
10
+ RollupTask,
11
+ RollupTaskEntry,
12
+ } from './tasks'
6
13
  import {fileEnding, getTargetPaths, legacyEnding} from './tasks/dts/getTargetPaths'
7
14
 
8
15
  /** @internal */
@@ -24,6 +31,13 @@ export function resolveBuildTasks(ctx: BuildContext): BuildTask[] {
24
31
 
25
32
  const rollupTasks: Record<string, RollupTask> = {}
26
33
  const rollupLegacyTasks: Record<string, RollupLegacyTask> = {}
34
+ const rollupReactCompilerTask: RollupReactCompilerTask = {
35
+ type: 'build:react-compiler',
36
+ runtime: 'browser',
37
+ format: 'esm',
38
+ entries: [],
39
+ target: target.browser,
40
+ }
27
41
 
28
42
  function addRollupTaskEntry(format: PkgFormat, runtime: PkgRuntime, entry: RollupTaskEntry) {
29
43
  const buildId = `${format}:${runtime}`
@@ -60,6 +74,10 @@ export function resolveBuildTasks(ctx: BuildContext): BuildTask[] {
60
74
  }
61
75
  }
62
76
 
77
+ function addRollupReactCompilerTaskEntry(entry: RollupTaskEntry) {
78
+ rollupReactCompilerTask.entries.push(entry)
79
+ }
80
+
63
81
  // Parse `dts` tasks
64
82
  for (const exp of exports) {
65
83
  const importId = path.join(pkg.name, exp._path)
@@ -90,6 +108,16 @@ export function resolveBuildTasks(ctx: BuildContext): BuildTask[] {
90
108
  targetPaths: getTargetPaths(pkg.type, exp.node),
91
109
  })
92
110
  }
111
+
112
+ // @TODO implement this
113
+ // if (exp['react-compiler']?.source?.endsWith('.ts')) {
114
+ // dtsTask.entries.push({
115
+ // importId,
116
+ // exportPath: exp._path,
117
+ // sourcePath: exp['react-compiler'].source,
118
+ // targetPaths: getTargetPaths(pkg.type, exp['react-compiler']),
119
+ // })
120
+ // }
93
121
  }
94
122
 
95
123
  // Handle dts tasks for bundles
@@ -168,6 +196,24 @@ export function resolveBuildTasks(ctx: BuildContext): BuildTask[] {
168
196
  })
169
197
  }
170
198
 
199
+ // Parse rollup:react-compiler tasks
200
+ for (const exp of exports) {
201
+ const output = exp['react-compiler']?.default
202
+
203
+ if (!output) continue
204
+
205
+ addRollupReactCompilerTaskEntry({
206
+ path: exp._path,
207
+ source: exp['react-compiler']?.source || exp.source,
208
+ output,
209
+ })
210
+ }
211
+
212
+ // Add react-compiler task
213
+ if (rollupReactCompilerTask.entries.length) {
214
+ tasks.push(rollupReactCompilerTask)
215
+ }
216
+
171
217
  // Create rollup bundles that legacy export files will re-export
172
218
  if (config?.legacyExports) {
173
219
  for (const exp of exports) {
@@ -63,6 +63,17 @@ export function getTargetPaths(
63
63
  )
64
64
  }
65
65
  }
66
+
67
+ if (!expOrBundle['react-compiler']?.source) {
68
+ if (expOrBundle['react-compiler']?.default) {
69
+ set.add(
70
+ expOrBundle['react-compiler'].default.replace(
71
+ fileEnding,
72
+ type === 'module' ? dtsEnding : mtsEnding,
73
+ ),
74
+ )
75
+ }
76
+ }
66
77
  }
67
78
 
68
79
  return Array.from(set)
@@ -1,5 +1,5 @@
1
1
  import {dtsTask, dtsWatchTask} from './dts'
2
- import {rollupLegacyTask, rollupTask, rollupWatchTask} from './rollup'
2
+ import {rollupLegacyTask, rollupReactCompilerTask, rollupTask, rollupWatchTask} from './rollup'
3
3
  import type {BuildTaskHandlers, WatchTaskHandlers} from './types'
4
4
 
5
5
  export * from './dts'
@@ -11,6 +11,7 @@ export const buildTaskHandlers: BuildTaskHandlers = {
11
11
  'build:dts': dtsTask,
12
12
  'build:js': rollupTask,
13
13
  'build:legacy': rollupLegacyTask,
14
+ 'build:react-compiler': rollupReactCompilerTask,
14
15
  }
15
16
 
16
17
  /** @internal */
@@ -1,3 +1,4 @@
1
1
  export * from './rollupLegacyTask'
2
+ export * from './rollupReactCompilerTask'
2
3
  export * from './rollupTask'
3
4
  export * from './rollupWatchTask'
@@ -13,7 +13,7 @@ import esbuild from 'rollup-plugin-esbuild'
13
13
 
14
14
  import {pkgExtMap as extMap} from '../../../node/core/pkg/pkgExt'
15
15
  import {type BuildContext, type PackageJSON, resolveConfigProperty} from '../../core'
16
- import type {RollupLegacyTask, RollupTask, RollupWatchTask} from '../types'
16
+ import type {RollupLegacyTask, RollupReactCompilerTask, RollupTask, RollupWatchTask} from '../types'
17
17
 
18
18
  export interface RollupConfig {
19
19
  inputOptions: InputOptions
@@ -23,11 +23,12 @@ export interface RollupConfig {
23
23
  /** @internal */
24
24
  export function resolveRollupConfig(
25
25
  ctx: BuildContext,
26
- buildTask: RollupTask | RollupLegacyTask | RollupWatchTask,
26
+ buildTask: RollupTask | RollupLegacyTask | RollupReactCompilerTask | RollupWatchTask,
27
27
  ): RollupConfig {
28
28
  const {format, runtime, target} = buildTask
29
29
  const {config, cwd, exports: _exports, external, distPath, logger, pkg, ts} = ctx
30
30
  const isLegacyExports = buildTask.type === 'build:legacy'
31
+ const isReactCompiler = buildTask.type === 'build:react-compiler'
31
32
  const outputExt = isLegacyExports ? extMap.legacy : extMap[pkg.type || 'commonjs'][format]
32
33
  const minify = config?.minify ?? false
33
34
  const outDir = path.relative(cwd, distPath)
@@ -95,22 +96,13 @@ export function resolveRollupConfig(
95
96
  }),
96
97
  commonjs(),
97
98
  json(),
98
- config?.babel?.reactCompiler &&
99
+ (isReactCompiler || config?.babel?.reactCompiler) &&
99
100
  babel({
100
101
  babelrc: false,
101
102
  presets: ['@babel/preset-typescript'],
102
103
  babelHelpers: 'bundled',
103
104
  extensions: ['.ts', '.tsx', '.js', '.jsx'],
104
- plugins: [
105
- [
106
- 'babel-plugin-react-compiler',
107
- {
108
- ...(typeof config?.babel?.reactCompiler === 'object'
109
- ? config?.babel?.reactCompiler
110
- : {}),
111
- },
112
- ],
113
- ],
105
+ plugins: [['babel-plugin-react-compiler', config?.reactCompilerOptions || {}]],
114
106
  }),
115
107
  esbuild({
116
108
  jsx: config?.jsx ?? 'automatic',
@@ -164,11 +156,13 @@ export function resolveRollupConfig(
164
156
  : resolveConfigProperty(config?.rollup?.plugins, defaultPlugins)
165
157
 
166
158
  const hashChunkFileNames = config?.rollup?.hashChunkFileNames ?? false
167
- const chunksFolder = isLegacyExports
168
- ? '_legacy'
169
- : hashChunkFileNames
170
- ? '_chunks'
171
- : '_chunks-[format]'
159
+ const chunksFolder = isReactCompiler
160
+ ? '_compiled'
161
+ : isLegacyExports
162
+ ? '_legacy'
163
+ : hashChunkFileNames
164
+ ? '_chunks'
165
+ : '_chunks-[format]'
172
166
  const chunkFileNames = `${chunksFolder}/${hashChunkFileNames ? '[name]-[hash]' : '[name]'}${outputExt}`
173
167
  const entryFileNames = isLegacyExports ? '[name].js' : `[name]${outputExt}`
174
168
 
@@ -0,0 +1,140 @@
1
+ import path from 'node:path'
2
+
3
+ import chalk from 'chalk'
4
+ import {rollup} from 'rollup'
5
+ import {Observable} from 'rxjs'
6
+
7
+ import {createConsoleSpy} from '../../consoleSpy'
8
+ import type {BuildContext} from '../../core'
9
+ import type {RollupReactCompilerTask, TaskHandler} from '../types'
10
+ import {resolveRollupConfig} from './resolveRollupConfig'
11
+
12
+ /** @internal */
13
+ export const rollupReactCompilerTask: TaskHandler<RollupReactCompilerTask> = {
14
+ name: (ctx, task) => {
15
+ const entries = task.entries.filter((e) => !e.path.includes('__$$bundle_'))
16
+
17
+ const targetLines = task.target.length
18
+ ? [' target:', ...task.target.map((t) => ` - ${chalk.yellow(t)}`)]
19
+ : []
20
+
21
+ const entriesLines = entries.length
22
+ ? [
23
+ ' entries:',
24
+ ...entries.map((e) =>
25
+ [
26
+ ' - ',
27
+ `${chalk.cyan(path.join(ctx.pkg.name, e.path))}: `,
28
+ `${chalk.yellow(e.source)} ${chalk.gray('→')} ${chalk.yellow(e.output)}`,
29
+ ].join(''),
30
+ ),
31
+ ]
32
+ : []
33
+
34
+ // @TODO list out the root level files that are generated
35
+
36
+ return ['Build react compiler exports...', ...targetLines, ...entriesLines].join('\n')
37
+ },
38
+ exec: (ctx, task) => {
39
+ return new Observable((observer) => {
40
+ execPromise(ctx, task)
41
+ .then((result) => {
42
+ observer.next(result)
43
+ observer.complete()
44
+ })
45
+ .catch((err) => observer.error(err))
46
+ })
47
+ },
48
+ complete: () => {
49
+ //
50
+ },
51
+ error: (_ctx, _task, err) => {
52
+ // eslint-disable-next-line no-console
53
+ console.error(err)
54
+ },
55
+ }
56
+
57
+ async function execPromise(ctx: BuildContext, task: RollupReactCompilerTask) {
58
+ const {distPath, files, logger} = ctx
59
+ const outDir = path.relative(ctx.cwd, distPath)
60
+
61
+ // Prevent rollup from printing directly to the console
62
+ const consoleSpy = createConsoleSpy({
63
+ onRestored: (messages) => {
64
+ for (const msg of messages) {
65
+ const text = String(msg.args[0])
66
+
67
+ if (msg.code === 'CIRCULAR_DEPENDENCY') {
68
+ continue // ignore
69
+ }
70
+
71
+ if (text.startsWith('Dynamic import can only')) {
72
+ continue // ignore
73
+ }
74
+
75
+ if (text.startsWith('Sourcemap is likely to be incorrect')) {
76
+ continue // ignore
77
+ }
78
+
79
+ if (msg.type === 'log') {
80
+ logger.info(...msg.args)
81
+ }
82
+
83
+ if (msg.type === 'warn') {
84
+ logger.warn(...msg.args)
85
+ }
86
+
87
+ if (msg.type === 'error') {
88
+ logger.error(...msg.args)
89
+ }
90
+ }
91
+ },
92
+ })
93
+
94
+ try {
95
+ const {inputOptions, outputOptions} = resolveRollupConfig(ctx, task)
96
+
97
+ // Create bundle
98
+ const bundle = await rollup({
99
+ ...inputOptions,
100
+ onwarn(warning) {
101
+ consoleSpy.messages.push({
102
+ type: 'warn',
103
+ code: warning.code,
104
+ args: [warning.message],
105
+ })
106
+ },
107
+ })
108
+
109
+ // generate output specific code in-memory
110
+ // you can call this function multiple times on the same bundle object
111
+ const {output} = await bundle.generate(outputOptions)
112
+
113
+ for (const chunkOrAsset of output) {
114
+ if (chunkOrAsset.type === 'asset') {
115
+ files.push({
116
+ type: 'asset',
117
+ path: path.resolve(outDir, chunkOrAsset.fileName),
118
+ })
119
+ } else {
120
+ files.push({
121
+ type: 'chunk',
122
+ path: path.resolve(outDir, chunkOrAsset.fileName),
123
+ })
124
+ }
125
+ }
126
+
127
+ // or write the bundle to disk
128
+ await bundle.write(outputOptions)
129
+
130
+ // closes the bundle
131
+ await bundle.close()
132
+
133
+ // Restore console
134
+ consoleSpy.restore()
135
+ } catch (err) {
136
+ // Restore console
137
+ consoleSpy.restore()
138
+ throw err
139
+ }
140
+ }
@@ -31,6 +31,15 @@ export interface RollupLegacyTask {
31
31
  target: string[]
32
32
  }
33
33
 
34
+ /** @internal */
35
+ export interface RollupReactCompilerTask {
36
+ type: 'build:react-compiler'
37
+ entries: RollupTaskEntry[]
38
+ runtime: 'browser'
39
+ format: 'esm'
40
+ target: string[]
41
+ }
42
+
34
43
  /** @internal */
35
44
  export interface RollupWatchTask {
36
45
  type: 'watch:js'
@@ -42,7 +51,7 @@ export interface RollupWatchTask {
42
51
  }
43
52
 
44
53
  /** @internal */
45
- export type BuildTask = DtsTask | RollupTask | RollupLegacyTask
54
+ export type BuildTask = DtsTask | RollupTask | RollupLegacyTask | RollupReactCompilerTask
46
55
 
47
56
  /** @internal */
48
57
  export type WatchTask = DtsWatchTask | RollupWatchTask
@@ -59,6 +68,7 @@ export type TaskHandler<Task, Result = void> = {
59
68
  export interface BuildTaskHandlers {
60
69
  'build:dts': TaskHandler<DtsTask, DtsResult>
61
70
  'build:js': TaskHandler<RollupTask>
71
+ 'build:react-compiler': TaskHandler<RollupReactCompilerTask>
62
72
  'build:legacy': TaskHandler<RollupLegacyTask>
63
73
  }
64
74