Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/loud-laws-approve.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@sanity/pkg-utils": patch
---

Fix issues uncovered by type-aware linting with oxlint
23 changes: 21 additions & 2 deletions .oxlintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,30 @@
}
},
{
"files": ["playground/**", "test/**", "packages/**/test/**"],
"files": [
"playground/**",
"test/**",
"packages/**/test/**",
"**/*.test.ts",
"**/*.test.js",
"**/*.test.tsx",
"**/*.test.jsx",
"**/test.cjs"
],
"rules": {
"eslint/no-console": "off",
"eslint/no-unused-vars": "off",
"triple-slash-reference": "off"
"triple-slash-reference": "off",
"await-thenable": "off",
"no-floating-promises": "off",
"no-unnecessary-boolean-literal-compare": "off",
"no-unnecessary-template-expression": "off",
"no-unnecessary-type-arguments": "off",
"no-unnecessary-type-assertion": "off",
"no-unsafe-enum-comparison": "off",
"no-unsafe-type-assertion": "off",
"restrict-template-expressions": "off",
"unbound-method": "off"
}
}
]
Expand Down
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
"type": "module",
"scripts": {
"build": "pnpm --filter '@sanity/pkg-utils' build",
"format": "prettier --write --cache --ignore-unknown . && oxlint --fix --quiet",
"lint": "oxlint",
"format": "prettier --write --cache --ignore-unknown . && oxlint --type-aware --fix --quiet",
"lint": "oxlint --type-aware",
"playground:build": "pnpm --filter './playground/**' build",
"playground:clean": "pnpm --filter './playground/**' --silent clean",
"playground:typecheck": "pnpm --filter './playground/**' typecheck",
Expand All @@ -19,7 +19,7 @@
"lint-staged": {
"*.{js,jsx,ts,tsx,mjs,cjs}": [
"prettier --cache --write",
"oxlint --fix --quiet"
"oxlint --type-aware --fix --quiet"
],
"*": [
"prettier --write --cache --ignore-unknown"
Expand All @@ -36,6 +36,7 @@
"lint-staged": "^16.2.6",
"npm-run-all2": "^8.0.4",
"oxlint": "^1.26.0",
"oxlint-tsgolint": "^0.5.0",
"prettier": "^3.6.2",
"rimraf": "^6.1.0",
"typescript": "catalog:"
Expand Down
3 changes: 2 additions & 1 deletion packages/@sanity/pkg-utils/src/node/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export async function build(options: {
const buildTasks = resolveBuildTasks(ctx)

for (const task of buildTasks) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- TypeScript can't infer the correct handler type from discriminated union
const handler = buildTaskHandlers[task.type] as TaskHandler<BuildTask>
const taskName = handler.name(ctx, task)

Expand All @@ -90,7 +91,7 @@ export async function build(options: {
spinner.error()

if (err instanceof Error) {
const RE_CWD = new RegExp(`${cwd}`, 'g')
const RE_CWD = new RegExp(cwd, 'g')

ctx.logger.error(err.message.replace(RE_CWD, '.'))
ctx.logger.log()
Expand Down
11 changes: 7 additions & 4 deletions packages/@sanity/pkg-utils/src/node/check.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,17 @@ export async function check(options: {

const consoleSpy = createConsoleSpy()

const checks = []
if (exportPaths.import.length) {
checkExports(exportPaths.import, {cwd, external, format: 'esm', logger})
checks.push(checkExports(exportPaths.import, {cwd, external, format: 'esm', logger}))
}

if (exportPaths.require.length) {
checkExports(exportPaths.require, {cwd, external, format: 'cjs', logger})
checks.push(checkExports(exportPaths.require, {cwd, external, format: 'cjs', logger}))
}

await Promise.all(checks)

consoleSpy.restore()
}

Expand All @@ -94,7 +97,7 @@ export async function check(options: {
spinner.error()

if (err instanceof Error) {
const RE_CWD = new RegExp(`${cwd}`, 'g')
const RE_CWD = new RegExp(cwd, 'g')

logger.error((err.stack || err.message).replace(RE_CWD, '.'))
logger.log()
Expand Down Expand Up @@ -166,7 +169,7 @@ async function checkExports(

logger.log()
} else {
logger.error(`${err}`)
logger.error(String(err))

logger.log()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export async function loadConfig(options: {cwd: string}): Promise<PkgConfigOptio

const root = path.dirname(pkgPath)

const configFile = await findConfigFile(root)
const configFile = findConfigFile(root)

if (!configFile) {
return undefined
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
import type {PkgConfigProperty, PkgConfigPropertyResolver} from './types.ts'

function isPkgConfigPropertyResolver<T>(
prop: PkgConfigProperty<T>,
): prop is PkgConfigPropertyResolver<T> {
return typeof prop === 'function'
}

/** @internal */
export function resolveConfigProperty<T>(
prop: PkgConfigProperty<T> | undefined,
initialValue: T,
): T {
if (!prop) return initialValue

if (typeof prop === 'function') {
return (prop as PkgConfigPropertyResolver<T>)(initialValue)
if (isPkgConfigPropertyResolver(prop)) {
return prop(initialValue)
}

return prop
Expand Down
9 changes: 7 additions & 2 deletions packages/@sanity/pkg-utils/src/node/core/pkg/parseExports.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ import {pkgExtMap} from './pkgExt.ts'
import type {PackageJSON} from './types.ts'
import {validateExports} from './validateExports.ts'

// Type guard to filter out falsy values
function isTruthy<T>(value: T | false | null | undefined | 0 | ''): value is T {
return Boolean(value)
}

/** @alpha */
export function parseExports(options: {
cwd: string
Expand Down Expand Up @@ -89,7 +94,7 @@ export function parseExports(options: {
}

errors.push(
...([
...[
'package.json: `exports` are missing, it should be:',
`"exports": {`,
` ".": {`,
Expand All @@ -102,7 +107,7 @@ export function parseExports(options: {
` },`,
` "./package.json": "./package.json"`,
`}`,
].filter(Boolean) as string[]),
].filter(isTruthy),
)
}
}
Expand Down
7 changes: 5 additions & 2 deletions packages/@sanity/pkg-utils/src/node/core/pkg/validatePkg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@ const pkgSchema = z.object({
exports: z.optional(
z.record(
z.union([
z.custom<`./${string}.json`>((val) => /^\.\/.*\.json$/.test(val as string)),
z.custom<`./${string}.css`>((val) => /^\.\/.*\.css$/.test(val as string)),
z.custom<`./${string}.json`>(
(val) => typeof val === 'string' && /^\.\/.*\.json$/.test(val),
),
z.custom<`./${string}.css`>((val) => typeof val === 'string' && /^\.\/.*\.css$/.test(val)),
z.object({
types: z.optional(z.string()),
source: z.optional(z.string()),
Expand Down Expand Up @@ -65,6 +67,7 @@ for (const key of pkgSchema.keyof()._def.values) {
export function validatePkg(input: unknown): PackageJSON {
const pkg = pkgSchema.parse(input)

// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Need to check raw input for typos
const invalidKey = Object.keys(input as PackageJSON).find((key) => {
const needle = key.toUpperCase()

Expand Down
4 changes: 2 additions & 2 deletions packages/@sanity/pkg-utils/src/node/core/ts/loadTSConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,13 @@ export async function loadTSConfig(options: {
}): Promise<ts.ParsedCommandLine | undefined> {
const {cwd, tsconfigPath} = options

const configPath = ts.findConfigFile(cwd, ts.sys.fileExists, tsconfigPath)
const configPath = ts.findConfigFile(cwd, (fileName) => ts.sys.fileExists(fileName), tsconfigPath)

if (!configPath) {
return undefined
}

const configFile = ts.readConfigFile(configPath, ts.sys.readFile)
const configFile = ts.readConfigFile(configPath, (path) => ts.sys.readFile(path))

return ts.parseJsonConfigFileContent(configFile.config, ts.sys, cwd)
}
12 changes: 7 additions & 5 deletions packages/@sanity/pkg-utils/src/node/printExtractMessages.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import path from 'node:path'
import type {ExtractorMessage} from '@microsoft/api-extractor'
import {ExtractorLogLevel, type ExtractorMessage} from '@microsoft/api-extractor'
import chalk from 'chalk'
import type {BuildContext} from './core/contexts/buildContext.ts'

export function printExtractMessages(ctx: BuildContext, messages: ExtractorMessage[]): void {
const {cwd, logger} = ctx

const warnings = messages.filter((msg) => msg.logLevel === 'warning')
const warnings = messages.filter((msg) => msg.logLevel === ExtractorLogLevel.Warning)

if (warnings.length) {
logger.log()
Expand All @@ -24,7 +24,7 @@ export function printExtractMessages(ctx: BuildContext, messages: ExtractorMessa

logger.log(
[
`${chalk.cyan(sourceFilePath || '?')}`,
chalk.cyan(sourceFilePath || '?'),
`:${chalk.yellow(msg.sourceFileLine)}:${chalk.yellow(msg.sourceFileColumn)}`,
` - ${chalk.yellow('warning')} ${chalk.gray(msg.messageId)}\n`,
msg.text,
Expand All @@ -33,7 +33,9 @@ export function printExtractMessages(ctx: BuildContext, messages: ExtractorMessa
)
}

const errors: ExtractorMessage[] = messages.filter((msg) => msg.logLevel === 'error')
const errors: ExtractorMessage[] = messages.filter(
(msg) => msg.logLevel === ExtractorLogLevel.Error,
)

if (!warnings.length && errors.length) {
logger.log('')
Expand All @@ -44,7 +46,7 @@ export function printExtractMessages(ctx: BuildContext, messages: ExtractorMessa

logger.log(
[
`${chalk.cyan(sourceFilePath || '?')}`,
chalk.cyan(sourceFilePath || '?'),
`:${chalk.yellow(msg.sourceFileLine)}:${chalk.yellow(msg.sourceFileColumn)}`,
` - ${chalk.red('error')} ${chalk.gray(msg.messageId)}\n`,
msg.text,
Expand Down
7 changes: 6 additions & 1 deletion packages/@sanity/pkg-utils/src/node/resolveBuildContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ import {resolveBrowserTarget} from './resolveBrowserTarget.ts'
import {resolveNodeTarget} from './resolveNodeTarget.ts'
import {parseStrictOptions} from './strict.ts'

// Type guard to filter out falsy values
function isTruthy<T>(value: T | false | null | undefined | 0 | ''): value is T {
return Boolean(value)
}

export async function resolveBuildContext(options: {
config?: PkgConfigOptions | undefined
cwd: string
Expand Down Expand Up @@ -141,7 +146,7 @@ export async function resolveBuildContext(options: {
exportEntry.browser?.require,
exportEntry.node?.source && exportEntry.node.import,
exportEntry.node?.source && exportEntry.node.require,
].filter(Boolean) as string[]
].filter(isTruthy)
})
.map((p) => path.resolve(cwd, p))

Expand Down
4 changes: 2 additions & 2 deletions packages/@sanity/pkg-utils/src/node/tasks/dts/doExtract.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import path from 'node:path'
import type {ExtractorMessage} from '@microsoft/api-extractor'
import {ExtractorLogLevel, type ExtractorMessage} from '@microsoft/api-extractor'
import {rimraf} from 'rimraf'
import type {BuildContext} from '../../core/contexts/buildContext.ts'
import {buildTypes} from './buildTypes.ts'
Expand Down Expand Up @@ -64,7 +64,7 @@ export async function doExtract(

messages.push(...result.messages)

const errors = result.messages.filter((msg) => msg.logLevel === 'error')
const errors = result.messages.filter((msg) => msg.logLevel === ExtractorLogLevel.Error)

if (errors.length > 0) {
await rimraf(tmpPath)
Expand Down
3 changes: 3 additions & 0 deletions packages/@sanity/pkg-utils/src/node/tasks/dts/dtsWatchTask.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ export const dtsWatchTask: TaskHandler<DtsWatchTask, DtsResult> = {
)

const origPostProgramCreate = host.afterProgramCreate
? (program: ts.EmitAndSemanticDiagnosticsBuilderProgram) =>
host.afterProgramCreate?.(program)
: undefined

host.afterProgramCreate = async (program) => {
origPostProgramCreate?.(program)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export async function extractModuleBlocksFromTypes({
tsOutDir: string
extractResult: ExtractorResult
}): Promise<string[]> {
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- ExtractorResult type from @microsoft/api-extractor is complex
const program = extractResult.compilerState.program as Program
const moduleBlocks: string[] = []

Expand All @@ -35,6 +36,7 @@ export async function extractModuleBlocksFromTypes({

/** @internal */
export function extractModuleBlocks(fileContent: string): string[] {
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion -- Babel parser returns any, but we know it's a File
const ast = parse(fileContent, {
parser: typeScriptParser,
}) as File
Expand Down
Loading