@sanity/pkg-utils 6.4.1 → 6.5.0
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/dist/_chunks-cjs/consoleSpy.cjs +39 -11
- package/dist/_chunks-cjs/consoleSpy.cjs.map +1 -1
- package/dist/cli.cjs +1 -1
- package/dist/index.cjs +2 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +78 -0
- package/dist/index.d.ts +78 -0
- package/dist/index.js +39 -10
- package/dist/index.js.map +1 -1
- package/package.json +6 -5
- package/src/node/__snapshots__/strict.test.ts.snap +145 -0
- package/src/node/core/config/types.ts +7 -1
- package/src/node/core/pkg/parseExports.ts +15 -3
- package/src/node/index.ts +1 -0
- package/src/node/resolveBuildContext.ts +28 -8
- package/src/node/strict.test-d.ts +7 -0
- package/src/node/strict.ts +66 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sanity/pkg-utils",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.5.0",
|
|
4
4
|
"description": "Simple utilities for modern npm packages.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sanity-io",
|
|
@@ -88,7 +88,7 @@
|
|
|
88
88
|
"parse-git-config": "^3.0.0",
|
|
89
89
|
"pkg-up": "^3.1.0",
|
|
90
90
|
"prettier": "^3.2.5",
|
|
91
|
-
"prettier-plugin-packagejson": "^2.
|
|
91
|
+
"prettier-plugin-packagejson": "^2.5.0",
|
|
92
92
|
"pretty-bytes": "^5.6.0",
|
|
93
93
|
"prompts": "^2.4.2",
|
|
94
94
|
"rimraf": "^4.4.1",
|
|
@@ -97,7 +97,8 @@
|
|
|
97
97
|
"rxjs": "^7.8.1",
|
|
98
98
|
"treeify": "^1.1.0",
|
|
99
99
|
"uuid": "^9.0.1",
|
|
100
|
-
"zod": "
|
|
100
|
+
"zod": "3.22.4",
|
|
101
|
+
"zod-validation-error": "3.1.0"
|
|
101
102
|
},
|
|
102
103
|
"devDependencies": {
|
|
103
104
|
"@commitlint/cli": "^19.2.1",
|
|
@@ -133,9 +134,9 @@
|
|
|
133
134
|
"semver": "^7.6.0",
|
|
134
135
|
"ts-node": "^10.9.2",
|
|
135
136
|
"typescript": "5.4.5",
|
|
136
|
-
"vitest": "^1.
|
|
137
|
+
"vitest": "^1.5.0",
|
|
137
138
|
"vitest-github-actions-reporter": "^0.11.1",
|
|
138
|
-
"@sanity/pkg-utils": "6.
|
|
139
|
+
"@sanity/pkg-utils": "6.5.0"
|
|
139
140
|
},
|
|
140
141
|
"peerDependencies": {
|
|
141
142
|
"typescript": "5.4.x"
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
|
2
|
+
|
|
3
|
+
exports[`{'noPackageJsonTypings': 'error'}} 1`] = `
|
|
4
|
+
{
|
|
5
|
+
"noImplicitBrowsersList": "warn",
|
|
6
|
+
"noImplicitSideEffects": "warn",
|
|
7
|
+
"noPackageJsonTypings": "error",
|
|
8
|
+
}
|
|
9
|
+
`;
|
|
10
|
+
|
|
11
|
+
exports[`{'noPackageJsonTypings': 'off'}} 1`] = `
|
|
12
|
+
{
|
|
13
|
+
"noImplicitBrowsersList": "warn",
|
|
14
|
+
"noImplicitSideEffects": "warn",
|
|
15
|
+
"noPackageJsonTypings": "off",
|
|
16
|
+
}
|
|
17
|
+
`;
|
|
18
|
+
|
|
19
|
+
exports[`{'noPackageJsonTypings': 'warn'}} 1`] = `
|
|
20
|
+
{
|
|
21
|
+
"noImplicitBrowsersList": "warn",
|
|
22
|
+
"noImplicitSideEffects": "warn",
|
|
23
|
+
"noPackageJsonTypings": "warn",
|
|
24
|
+
}
|
|
25
|
+
`;
|
|
26
|
+
|
|
27
|
+
exports[`{'noPackageJsonTypings': false}} 1`] = `
|
|
28
|
+
[ZodError: [
|
|
29
|
+
{
|
|
30
|
+
"code": "invalid_union",
|
|
31
|
+
"unionErrors": [
|
|
32
|
+
{
|
|
33
|
+
"issues": [
|
|
34
|
+
{
|
|
35
|
+
"received": false,
|
|
36
|
+
"code": "invalid_literal",
|
|
37
|
+
"expected": "error",
|
|
38
|
+
"path": [
|
|
39
|
+
"strictOptions",
|
|
40
|
+
"noPackageJsonTypings"
|
|
41
|
+
],
|
|
42
|
+
"message": "Validation error: Invalid literal value, expected \\"error\\" at \\"strictOptions.noPackageJsonTypings\\""
|
|
43
|
+
}
|
|
44
|
+
],
|
|
45
|
+
"name": "ZodError"
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"issues": [
|
|
49
|
+
{
|
|
50
|
+
"received": false,
|
|
51
|
+
"code": "invalid_literal",
|
|
52
|
+
"expected": "warn",
|
|
53
|
+
"path": [
|
|
54
|
+
"strictOptions",
|
|
55
|
+
"noPackageJsonTypings"
|
|
56
|
+
],
|
|
57
|
+
"message": "Validation error: Invalid literal value, expected \\"warn\\" at \\"strictOptions.noPackageJsonTypings\\""
|
|
58
|
+
}
|
|
59
|
+
],
|
|
60
|
+
"name": "ZodError"
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
"issues": [
|
|
64
|
+
{
|
|
65
|
+
"received": false,
|
|
66
|
+
"code": "invalid_literal",
|
|
67
|
+
"expected": "off",
|
|
68
|
+
"path": [
|
|
69
|
+
"strictOptions",
|
|
70
|
+
"noPackageJsonTypings"
|
|
71
|
+
],
|
|
72
|
+
"message": "Validation error: Invalid literal value, expected \\"off\\" at \\"strictOptions.noPackageJsonTypings\\""
|
|
73
|
+
}
|
|
74
|
+
],
|
|
75
|
+
"name": "ZodError"
|
|
76
|
+
}
|
|
77
|
+
],
|
|
78
|
+
"path": [
|
|
79
|
+
"strictOptions",
|
|
80
|
+
"noPackageJsonTypings"
|
|
81
|
+
],
|
|
82
|
+
"message": "Validation error: Validation error: Invalid literal value, expected \\"error\\" at \\"strictOptions.noPackageJsonTypings\\" at \\"strictOptions.noPackageJsonTypings\\", or Validation error: Invalid literal value, expected \\"warn\\" at \\"strictOptions.noPackageJsonTypings\\" at \\"strictOptions.noPackageJsonTypings\\", or Validation error: Invalid literal value, expected \\"off\\" at \\"strictOptions.noPackageJsonTypings\\" at \\"strictOptions.noPackageJsonTypings\\""
|
|
83
|
+
}
|
|
84
|
+
]]
|
|
85
|
+
`;
|
|
86
|
+
|
|
87
|
+
exports[`{'noPackageJsonTypings': true}} 1`] = `
|
|
88
|
+
[ZodError: [
|
|
89
|
+
{
|
|
90
|
+
"code": "invalid_union",
|
|
91
|
+
"unionErrors": [
|
|
92
|
+
{
|
|
93
|
+
"issues": [
|
|
94
|
+
{
|
|
95
|
+
"received": true,
|
|
96
|
+
"code": "invalid_literal",
|
|
97
|
+
"expected": "error",
|
|
98
|
+
"path": [
|
|
99
|
+
"strictOptions",
|
|
100
|
+
"noPackageJsonTypings"
|
|
101
|
+
],
|
|
102
|
+
"message": "Validation error: Invalid literal value, expected \\"error\\" at \\"strictOptions.noPackageJsonTypings\\""
|
|
103
|
+
}
|
|
104
|
+
],
|
|
105
|
+
"name": "ZodError"
|
|
106
|
+
},
|
|
107
|
+
{
|
|
108
|
+
"issues": [
|
|
109
|
+
{
|
|
110
|
+
"received": true,
|
|
111
|
+
"code": "invalid_literal",
|
|
112
|
+
"expected": "warn",
|
|
113
|
+
"path": [
|
|
114
|
+
"strictOptions",
|
|
115
|
+
"noPackageJsonTypings"
|
|
116
|
+
],
|
|
117
|
+
"message": "Validation error: Invalid literal value, expected \\"warn\\" at \\"strictOptions.noPackageJsonTypings\\""
|
|
118
|
+
}
|
|
119
|
+
],
|
|
120
|
+
"name": "ZodError"
|
|
121
|
+
},
|
|
122
|
+
{
|
|
123
|
+
"issues": [
|
|
124
|
+
{
|
|
125
|
+
"received": true,
|
|
126
|
+
"code": "invalid_literal",
|
|
127
|
+
"expected": "off",
|
|
128
|
+
"path": [
|
|
129
|
+
"strictOptions",
|
|
130
|
+
"noPackageJsonTypings"
|
|
131
|
+
],
|
|
132
|
+
"message": "Validation error: Invalid literal value, expected \\"off\\" at \\"strictOptions.noPackageJsonTypings\\""
|
|
133
|
+
}
|
|
134
|
+
],
|
|
135
|
+
"name": "ZodError"
|
|
136
|
+
}
|
|
137
|
+
],
|
|
138
|
+
"path": [
|
|
139
|
+
"strictOptions",
|
|
140
|
+
"noPackageJsonTypings"
|
|
141
|
+
],
|
|
142
|
+
"message": "Validation error: Validation error: Invalid literal value, expected \\"error\\" at \\"strictOptions.noPackageJsonTypings\\" at \\"strictOptions.noPackageJsonTypings\\", or Validation error: Invalid literal value, expected \\"warn\\" at \\"strictOptions.noPackageJsonTypings\\" at \\"strictOptions.noPackageJsonTypings\\", or Validation error: Invalid literal value, expected \\"off\\" at \\"strictOptions.noPackageJsonTypings\\" at \\"strictOptions.noPackageJsonTypings\\""
|
|
143
|
+
}
|
|
144
|
+
]]
|
|
145
|
+
`;
|
|
@@ -2,8 +2,10 @@ import type {PluginItem as BabelPluginItem} from '@babel/core'
|
|
|
2
2
|
import type {OptimizeLodashOptions} from '@optimize-lodash/rollup-plugin'
|
|
3
3
|
import type {NormalizedOutputOptions, Plugin as RollupPlugin, TreeshakingOptions} from 'rollup'
|
|
4
4
|
|
|
5
|
+
import type {StrictOptions} from '../../strict'
|
|
6
|
+
|
|
5
7
|
// re-export
|
|
6
|
-
export type {RollupPlugin}
|
|
8
|
+
export type {RollupPlugin, StrictOptions}
|
|
7
9
|
|
|
8
10
|
/** @public */
|
|
9
11
|
export type PkgFormat = 'commonjs' | 'esm'
|
|
@@ -157,4 +159,8 @@ export interface PkgConfigOptions {
|
|
|
157
159
|
*/
|
|
158
160
|
src?: string
|
|
159
161
|
tsconfig?: string
|
|
162
|
+
/**
|
|
163
|
+
* Configure what checks are made when running `--strict` builds and checks
|
|
164
|
+
*/
|
|
165
|
+
strictOptions?: StrictOptions
|
|
160
166
|
}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type {Logger} from '../../logger'
|
|
2
|
+
import type {InferredStrictOptions} from '../../strict'
|
|
1
3
|
import {defaultEnding, fileEnding, legacyEnding} from '../../tasks/dts/getTargetPaths'
|
|
2
4
|
import type {PkgExport} from '../config'
|
|
3
5
|
import {isRecord} from '../isRecord'
|
|
@@ -9,12 +11,22 @@ import {validateExports} from './validateExports'
|
|
|
9
11
|
export function parseExports(options: {
|
|
10
12
|
pkg: PackageJSON
|
|
11
13
|
strict: boolean
|
|
14
|
+
strictOptions: InferredStrictOptions
|
|
12
15
|
legacyExports: boolean
|
|
16
|
+
logger: Logger
|
|
13
17
|
}): (PkgExport & {_path: string})[] {
|
|
14
|
-
const {pkg, strict, legacyExports} = options
|
|
18
|
+
const {pkg, strict, strictOptions, legacyExports, logger} = options
|
|
15
19
|
const type = pkg.type || 'commonjs'
|
|
16
20
|
const errors: string[] = []
|
|
17
21
|
|
|
22
|
+
const report = (kind: 'warn' | 'error', message: string) => {
|
|
23
|
+
if (kind === 'warn') {
|
|
24
|
+
logger.warn(message)
|
|
25
|
+
} else {
|
|
26
|
+
errors.push(message)
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
18
30
|
if (pkg.source) {
|
|
19
31
|
if (
|
|
20
32
|
strict &&
|
|
@@ -145,8 +157,8 @@ export function parseExports(options: {
|
|
|
145
157
|
|
|
146
158
|
// @TODO validate typesVersions when legacyExports is true
|
|
147
159
|
|
|
148
|
-
if (strict && 'typings' in pkg) {
|
|
149
|
-
|
|
160
|
+
if (strict && strictOptions.noPackageJsonTypings !== 'off' && 'typings' in pkg) {
|
|
161
|
+
report(strictOptions.noPackageJsonTypings, 'package.json: `typings` should be `types`')
|
|
150
162
|
}
|
|
151
163
|
|
|
152
164
|
if (strict && !pkg.types && pkg.source?.endsWith('.ts')) {
|
package/src/node/index.ts
CHANGED
|
@@ -17,6 +17,7 @@ import {findCommonDirPath, pathContains} from './core/findCommonPath'
|
|
|
17
17
|
import type {Logger} from './logger'
|
|
18
18
|
import {resolveBrowserTarget} from './resolveBrowserTarget'
|
|
19
19
|
import {resolveNodeTarget} from './resolveNodeTarget'
|
|
20
|
+
import {parseStrictOptions} from './strict'
|
|
20
21
|
|
|
21
22
|
export async function resolveBuildContext(options: {
|
|
22
23
|
config?: PkgConfigOptions
|
|
@@ -37,24 +38,41 @@ export async function resolveBuildContext(options: {
|
|
|
37
38
|
tsconfig: tsconfigPath,
|
|
38
39
|
} = options
|
|
39
40
|
const tsconfig = await loadTSConfig({cwd, tsconfigPath})
|
|
41
|
+
const strictOptions = parseStrictOptions(config?.strictOptions ?? {})
|
|
40
42
|
|
|
41
43
|
/* eslint-disable padding-line-between-statements */
|
|
42
44
|
let browserslist = pkg.browserslist
|
|
43
45
|
if (!browserslist) {
|
|
44
|
-
if (strict) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
if (strict && strictOptions.noImplicitBrowsersList !== 'off') {
|
|
47
|
+
if (strictOptions.noImplicitBrowsersList === 'error') {
|
|
48
|
+
throw new Error(
|
|
49
|
+
'\n- ' +
|
|
50
|
+
`package.json: "browserslist" is missing, set it to \`"browserslist": "extends @sanity/browserslist-config"\``,
|
|
51
|
+
)
|
|
52
|
+
} else {
|
|
53
|
+
logger.warn(
|
|
54
|
+
'Could not detect a `browserslist` property in `package.json`, using default configuration. Add `"browserslist": "extends @sanity/browserslist-config"` to silence this warning.',
|
|
55
|
+
)
|
|
56
|
+
}
|
|
48
57
|
}
|
|
49
58
|
browserslist = DEFAULT_BROWSERSLIST_QUERY
|
|
50
59
|
}
|
|
51
60
|
const targetVersions = browserslistToEsbuild(browserslist)
|
|
52
61
|
/* eslint-enable padding-line-between-statements */
|
|
53
62
|
|
|
54
|
-
if (
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
63
|
+
if (
|
|
64
|
+
strict &&
|
|
65
|
+
strictOptions.noImplicitSideEffects !== 'off' &&
|
|
66
|
+
typeof pkg.sideEffects === 'undefined'
|
|
67
|
+
) {
|
|
68
|
+
const msg =
|
|
69
|
+
'package.json: `sideEffects` is missing, see https://webpack.js.org/guides/tree-shaking/#clarifying-tree-shaking-and-sideeffects for how to define `sideEffects`'
|
|
70
|
+
|
|
71
|
+
if (strictOptions.noImplicitSideEffects === 'error') {
|
|
72
|
+
throw new Error(msg)
|
|
73
|
+
} else {
|
|
74
|
+
logger.warn(msg)
|
|
75
|
+
}
|
|
58
76
|
}
|
|
59
77
|
|
|
60
78
|
const nodeTarget = resolveNodeTarget(targetVersions)
|
|
@@ -78,6 +96,8 @@ export async function resolveBuildContext(options: {
|
|
|
78
96
|
pkg,
|
|
79
97
|
strict,
|
|
80
98
|
legacyExports: config?.legacyExports ?? false,
|
|
99
|
+
strictOptions,
|
|
100
|
+
logger,
|
|
81
101
|
}).reduce<PkgExports>((acc, x) => {
|
|
82
102
|
const {_path: exportPath, ...exportEntry} = x
|
|
83
103
|
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import {z} from 'zod'
|
|
2
|
+
import {errorMap} from 'zod-validation-error'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* @public
|
|
6
|
+
*/
|
|
7
|
+
export const toggle = z.union([z.literal('error'), z.literal('warn'), z.literal('off')])
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @public
|
|
11
|
+
*/
|
|
12
|
+
export type ToggleType = z.infer<typeof toggle>
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* @public
|
|
16
|
+
*/
|
|
17
|
+
export const strictOptions = z
|
|
18
|
+
.object({
|
|
19
|
+
noPackageJsonTypings: toggle.default('error'),
|
|
20
|
+
noImplicitSideEffects: toggle.default('warn'),
|
|
21
|
+
noImplicitBrowsersList: toggle.default('warn'),
|
|
22
|
+
})
|
|
23
|
+
.strict()
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* To make error message paths line up with the paths in package.config.ts the schema is hoisted into a root schema
|
|
27
|
+
* This way errors will say `Expected boolean, received string at "strict.noPackageJsonTypings"` instead of `Expected boolean, received string at "noPackageJsonTypings"`.
|
|
28
|
+
*/
|
|
29
|
+
const validationSchema = z.object({
|
|
30
|
+
strictOptions: strictOptions.default({}),
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @public
|
|
35
|
+
*/
|
|
36
|
+
export type InferredStrictOptions = z.infer<typeof strictOptions>
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @public
|
|
40
|
+
*/
|
|
41
|
+
export interface StrictOptions {
|
|
42
|
+
/**
|
|
43
|
+
* Disallows a top level `typings` field in `package.json` if it is equal to `exports['.'].source`.
|
|
44
|
+
* @defaultValue 'error'
|
|
45
|
+
*/
|
|
46
|
+
noPackageJsonTypings?: ToggleType
|
|
47
|
+
/**
|
|
48
|
+
* Requires specifying `sideEffects` in `package.json`.
|
|
49
|
+
* @defaultValue 'warn'
|
|
50
|
+
*/
|
|
51
|
+
noImplicitSideEffects?: ToggleType
|
|
52
|
+
/**
|
|
53
|
+
* Requires specifying `browserslist` in `package.json`, instead of relying on it implicitly being:
|
|
54
|
+
* @example
|
|
55
|
+
* ```
|
|
56
|
+
* "browserslist": "extends @sanity/browserslist-config"
|
|
57
|
+
* ```
|
|
58
|
+
* @defaultValue 'warn'
|
|
59
|
+
*/
|
|
60
|
+
noImplicitBrowsersList?: ToggleType
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** @internal */
|
|
64
|
+
export function parseStrictOptions(input: unknown): InferredStrictOptions {
|
|
65
|
+
return validationSchema.parse({strictOptions: input}, {errorMap}).strictOptions
|
|
66
|
+
}
|