@sanity/pkg-utils 6.4.1 → 6.6.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/index.d.ts CHANGED
@@ -8,6 +8,7 @@ import type {Plugin as RollupPlugin} from 'rollup'
8
8
  import {RollupWatcherEvent} from 'rollup'
9
9
  import type {TreeshakingOptions} from 'rollup'
10
10
  import ts from 'typescript'
11
+ import {z} from 'zod'
11
12
 
12
13
  /**
13
14
  * Build the distribution files of a npm package.
@@ -145,6 +146,11 @@ export declare function getExtractMessagesConfig(options: {
145
146
  rules: NonNullable<PkgConfigOptions['extract']>['rules']
146
147
  }): IExtractorMessagesConfig
147
148
 
149
+ /**
150
+ * @public
151
+ */
152
+ export declare type InferredStrictOptions = z.infer<typeof strictOptions>
153
+
148
154
  /** @public */
149
155
  export declare function init(options: {cwd: string; path: string}): Promise<void>
150
156
 
@@ -260,7 +266,9 @@ export declare interface PackageJSON {
260
266
  export declare function parseExports(options: {
261
267
  pkg: PackageJSON
262
268
  strict: boolean
269
+ strictOptions: InferredStrictOptions
263
270
  legacyExports: boolean
271
+ logger: Logger
264
272
  }): (PkgExport & {
265
273
  _path: string
266
274
  })[]
@@ -365,6 +373,10 @@ export declare interface PkgConfigOptions {
365
373
  */
366
374
  src?: string
367
375
  tsconfig?: string
376
+ /**
377
+ * Configure what checks are made when running `--strict` builds and checks
378
+ */
379
+ strictOptions?: StrictOptions
368
380
  }
369
381
 
370
382
  /** @public */
@@ -535,6 +547,90 @@ export declare interface RollupWatchTask {
535
547
  /** @internal */
536
548
  export declare const rollupWatchTask: TaskHandler<RollupWatchTask, RollupWatcherEvent>
537
549
 
550
+ /**
551
+ * @public
552
+ */
553
+ export declare interface StrictOptions {
554
+ /**
555
+ * Disallows a top level `typings` field in `package.json` if it is equal to `exports['.'].source`.
556
+ * @defaultValue 'error'
557
+ */
558
+ noPackageJsonTypings?: ToggleType
559
+ /**
560
+ * Requires specifying `sideEffects` in `package.json`.
561
+ * @defaultValue 'warn'
562
+ */
563
+ noImplicitSideEffects?: ToggleType
564
+ /**
565
+ * Requires specifying `browserslist` in `package.json`, instead of relying on it implicitly being:
566
+ * @example
567
+ * ```
568
+ * "browserslist": "extends @sanity/browserslist-config"
569
+ * ```
570
+ * @defaultValue 'warn'
571
+ */
572
+ noImplicitBrowsersList?: ToggleType
573
+ /**
574
+ * If typescript is used then `types` in `package.json` should be specified for npm listings to show the TS icon.
575
+ * @defaultValue 'error'
576
+ */
577
+ alwaysPackageJsonTypes?: ToggleType
578
+ /**
579
+ * A lot of analysis tooling requiers the `main` field to work (like bundlephobia) and so it's best practice to always include it
580
+ * @defaultValue 'error'
581
+ */
582
+ alwaysPackageJsonMain?: ToggleType
583
+ /**
584
+ * Using `.npmignore` is error prone, it's best practice to always declare `files` instead
585
+ * @defaultValue 'error'
586
+ */
587
+ alwaysPackageJsonFiles?: ToggleType
588
+ }
589
+
590
+ /**
591
+ * @public
592
+ */
593
+ export declare const strictOptions: z.ZodObject<
594
+ {
595
+ noPackageJsonTypings: z.ZodDefault<
596
+ z.ZodUnion<[z.ZodLiteral<'error'>, z.ZodLiteral<'warn'>, z.ZodLiteral<'off'>]>
597
+ >
598
+ noImplicitSideEffects: z.ZodDefault<
599
+ z.ZodUnion<[z.ZodLiteral<'error'>, z.ZodLiteral<'warn'>, z.ZodLiteral<'off'>]>
600
+ >
601
+ noImplicitBrowsersList: z.ZodDefault<
602
+ z.ZodUnion<[z.ZodLiteral<'error'>, z.ZodLiteral<'warn'>, z.ZodLiteral<'off'>]>
603
+ >
604
+ alwaysPackageJsonTypes: z.ZodDefault<
605
+ z.ZodUnion<[z.ZodLiteral<'error'>, z.ZodLiteral<'warn'>, z.ZodLiteral<'off'>]>
606
+ >
607
+ alwaysPackageJsonMain: z.ZodDefault<
608
+ z.ZodUnion<[z.ZodLiteral<'error'>, z.ZodLiteral<'warn'>, z.ZodLiteral<'off'>]>
609
+ >
610
+ alwaysPackageJsonFiles: z.ZodDefault<
611
+ z.ZodUnion<[z.ZodLiteral<'error'>, z.ZodLiteral<'warn'>, z.ZodLiteral<'off'>]>
612
+ >
613
+ },
614
+ 'strict',
615
+ z.ZodTypeAny,
616
+ {
617
+ noPackageJsonTypings: 'error' | 'warn' | 'off'
618
+ noImplicitSideEffects: 'error' | 'warn' | 'off'
619
+ noImplicitBrowsersList: 'error' | 'warn' | 'off'
620
+ alwaysPackageJsonTypes: 'error' | 'warn' | 'off'
621
+ alwaysPackageJsonMain: 'error' | 'warn' | 'off'
622
+ alwaysPackageJsonFiles: 'error' | 'warn' | 'off'
623
+ },
624
+ {
625
+ noPackageJsonTypings?: 'error' | 'warn' | 'off' | undefined
626
+ noImplicitSideEffects?: 'error' | 'warn' | 'off' | undefined
627
+ noImplicitBrowsersList?: 'error' | 'warn' | 'off' | undefined
628
+ alwaysPackageJsonTypes?: 'error' | 'warn' | 'off' | undefined
629
+ alwaysPackageJsonMain?: 'error' | 'warn' | 'off' | undefined
630
+ alwaysPackageJsonFiles?: 'error' | 'warn' | 'off' | undefined
631
+ }
632
+ >
633
+
538
634
  /** @internal */
539
635
  export declare type TaskHandler<Task, Result = void> = {
540
636
  name: (ctx: BuildContext, task: Task) => string
@@ -543,6 +639,18 @@ export declare type TaskHandler<Task, Result = void> = {
543
639
  error: (ctx: BuildContext, task: Task, error: unknown) => void
544
640
  }
545
641
 
642
+ /**
643
+ * @public
644
+ */
645
+ export declare const toggle: z.ZodUnion<
646
+ [z.ZodLiteral<'error'>, z.ZodLiteral<'warn'>, z.ZodLiteral<'off'>]
647
+ >
648
+
649
+ /**
650
+ * @public
651
+ */
652
+ export declare type ToggleType = z.infer<typeof toggle>
653
+
546
654
  /** @public */
547
655
  export declare interface TSDocCustomTag {
548
656
  name: string
package/dist/index.js CHANGED
@@ -10,6 +10,7 @@ import fs, { writeFile, readFile, readdir, lstat } from "node:fs/promises";
10
10
  import browserslist from "browserslist";
11
11
  import config from "@sanity/browserslist-config";
12
12
  import ts from "typescript";
13
+ import { errorMap } from "zod-validation-error";
13
14
  import { Observable, switchMap } from "rxjs";
14
15
  import { ExtractorConfig, Extractor } from "@microsoft/api-extractor";
15
16
  import { mkdirp } from "mkdirp";
@@ -269,8 +270,13 @@ function validateExports(_exports, options2) {
269
270
  return errors;
270
271
  }
271
272
  function parseExports(options2) {
272
- const { pkg, strict, legacyExports } = options2, type = pkg.type || "commonjs", errors = [];
273
- if (pkg.source) {
273
+ const { pkg, strict, strictOptions: strictOptions2, legacyExports, logger } = options2, type = pkg.type || "commonjs", errors = [], report = (kind, message) => {
274
+ kind === "warn" ? logger.warn(message) : errors.push(message);
275
+ };
276
+ if (!pkg.main && strict && strictOptions2.alwaysPackageJsonMain !== "off" && report(strictOptions2.alwaysPackageJsonMain, "package.json: `main` must be declared"), !Array.isArray(pkg.files) && strict && strictOptions2.alwaysPackageJsonFiles !== "off" && report(
277
+ strictOptions2.alwaysPackageJsonFiles,
278
+ "package.json: `files` should be used over `.npmignore`"
279
+ ), pkg.source) {
274
280
  if (strict && pkg.exports?.["."] && typeof pkg.exports["."] == "object" && "source" in pkg.exports["."] && pkg.exports["."].source === pkg.source)
275
281
  errors.push(
276
282
  'package.json: the "source" property can be removed, as it is equal to exports["."].source.'
@@ -345,7 +351,8 @@ function parseExports(options2) {
345
351
  - `)
346
352
  );
347
353
  const _exports = [];
348
- strict && "typings" in pkg && errors.push("package.json: `typings` should be `types`"), strict && !pkg.types && pkg.source?.endsWith(".ts") && errors.push(
354
+ strict && strictOptions2.noPackageJsonTypings !== "off" && "typings" in pkg && report(strictOptions2.noPackageJsonTypings, "package.json: `typings` should be `types`"), strict && strictOptions2.alwaysPackageJsonTypes !== "off" && !pkg.types && typeof pkg.exports?.["."] == "object" && "source" in pkg.exports["."] && pkg.exports["."].source?.endsWith(".ts") && report(
355
+ strictOptions2.alwaysPackageJsonTypes,
349
356
  "package.json: `types` must be declared for the npm listing to show as a TypeScript module."
350
357
  ), strict && !pkg.exports["./package.json"] && errors.push('package.json: `exports["./package.json"] must be declared.');
351
358
  for (const [exportPath, exportEntry] of Object.entries(pkg.exports))
@@ -520,6 +527,19 @@ function resolveNodeTarget(versions) {
520
527
  if (target.length !== 0)
521
528
  return target;
522
529
  }
530
+ const toggle = z.union([z.literal("error"), z.literal("warn"), z.literal("off")]), strictOptions = z.object({
531
+ noPackageJsonTypings: toggle.default("error"),
532
+ noImplicitSideEffects: toggle.default("warn"),
533
+ noImplicitBrowsersList: toggle.default("warn"),
534
+ alwaysPackageJsonTypes: toggle.default("error"),
535
+ alwaysPackageJsonMain: toggle.default("error"),
536
+ alwaysPackageJsonFiles: toggle.default("error")
537
+ }).strict(), validationSchema = z.object({
538
+ strictOptions: strictOptions.default({})
539
+ });
540
+ function parseStrictOptions(input) {
541
+ return validationSchema.parse({ strictOptions: input }, { errorMap }).strictOptions;
542
+ }
523
543
  async function resolveBuildContext(options2) {
524
544
  const {
525
545
  config: config2,
@@ -529,15 +549,27 @@ async function resolveBuildContext(options2) {
529
549
  pkg,
530
550
  strict,
531
551
  tsconfig: tsconfigPath
532
- } = options2, tsconfig = await loadTSConfig({ cwd, tsconfigPath });
552
+ } = options2, tsconfig = await loadTSConfig({ cwd, tsconfigPath }), strictOptions2 = parseStrictOptions(config2?.strictOptions ?? {});
533
553
  let browserslist2 = pkg.browserslist;
534
- browserslist2 || (strict && logger.warn(
535
- 'Could not detect a `browserslist` property in `package.json`, using default configuration. Add `"browserslist": "extends @sanity/browserslist-config"` to silence this warning.'
536
- ), browserslist2 = DEFAULT_BROWSERSLIST_QUERY);
554
+ if (!browserslist2) {
555
+ if (strict && strictOptions2.noImplicitBrowsersList !== "off") {
556
+ if (strictOptions2.noImplicitBrowsersList === "error")
557
+ throw new Error(
558
+ '\n- package.json: "browserslist" is missing, set it to `"browserslist": "extends @sanity/browserslist-config"`'
559
+ );
560
+ logger.warn(
561
+ 'Could not detect a `browserslist` property in `package.json`, using default configuration. Add `"browserslist": "extends @sanity/browserslist-config"` to silence this warning.'
562
+ );
563
+ }
564
+ browserslist2 = DEFAULT_BROWSERSLIST_QUERY;
565
+ }
537
566
  const targetVersions = browserslistToEsbuild(browserslist2);
538
- strict && typeof pkg.sideEffects > "u" && logger.error(
539
- 'No `sideEffects` field in `package.json`, assuming all files are side-effectful. Add `"sideEffects": true` to silence this warning. See https://webpack.js.org/guides/tree-shaking/#clarifying-tree-shaking-and-sideeffects for how to define `sideEffects`.'
540
- );
567
+ if (strict && strictOptions2.noImplicitSideEffects !== "off" && typeof pkg.sideEffects > "u") {
568
+ const msg = "package.json: `sideEffects` is missing, see https://webpack.js.org/guides/tree-shaking/#clarifying-tree-shaking-and-sideeffects for how to define `sideEffects`";
569
+ if (strictOptions2.noImplicitSideEffects === "error")
570
+ throw new Error(msg);
571
+ logger.warn(msg);
572
+ }
541
573
  const nodeTarget = resolveNodeTarget(targetVersions), webTarget = resolveBrowserTarget(targetVersions);
542
574
  if (!nodeTarget)
543
575
  throw new Error("no matching `node` target");
@@ -550,7 +582,9 @@ async function resolveBuildContext(options2) {
550
582
  }, parsedExports = parseExports({
551
583
  pkg,
552
584
  strict,
553
- legacyExports: config2?.legacyExports ?? !1
585
+ legacyExports: config2?.legacyExports ?? !1,
586
+ strictOptions: strictOptions2,
587
+ logger
554
588
  }).reduce((acc, x) => {
555
589
  const { _path: exportPath, ...exportEntry } = x;
556
590
  return { ...acc, [exportPath]: exportEntry };
@@ -21585,6 +21619,8 @@ export {
21585
21619
  rollupLegacyTask,
21586
21620
  rollupTask,
21587
21621
  rollupWatchTask,
21622
+ strictOptions,
21623
+ toggle,
21588
21624
  watch,
21589
21625
  watchTaskHandlers
21590
21626
  };