@sanity/tsdown-config 0.28.4 → 0.28.6
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.
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cssNodeCompatPlugin-B_ndKoRv.mjs","names":[],"sources":["../src/cssNodeCompatPlugin.ts"],"sourcesContent":["import path from 'node:path'\nimport {\n createConditionalCssExport,\n createCssExport,\n cssShimDtsFileName,\n cssShimDtsSource,\n cssShimFileName,\n cssShimSource,\n insertCssExport,\n resolveCssExportOptions,\n type CssExportsOptions,\n} from '@sanity/vanilla-extract-tsdown-plugin'\nimport type {ResolvedConfig, TsdownPlugin, UserConfig} from 'tsdown'\n\n/**\n * Matches the module ids `@tsdown/css` treats as stylesheets, so this plugin can tell which\n * chunks pulled CSS in without reaching into `@tsdown/css`'s own bookkeeping.\n */\nconst RE_CSS_LANG = /\\.(css|less|sass|scss|styl|stylus)(?:$|\\?)/\n/** Matches `?inline` CSS imports, which `@tsdown/css` inlines into JS instead of extracting. */\nconst RE_CSS_INLINE = /[?&]inline\\b/\n/** Matches rendered `.d.ts`/`.d.mts`/`.d.cts` chunk file names. */\nconst RE_DTS = /\\.d\\.[cm]?ts$/\n/** Matches the emitted CSS assets whose shims and exports this plugin maintains. */\nconst RE_CSS_ASSET = /\\.css$/\n\n/** `index.mjs` -> `index.css`, the naming `@tsdown/css` uses when `css.splitting` is on. */\nfunction toCssFileName(jsFileName: string): string {\n return jsFileName.replace(/(?:\\.module)?(\\.[cm]?js)$/, '.css')\n}\n\n/**\n * The `@tsdown/css` options this plugin needs to mirror. Kept structural so the plugin does not\n * have to import `@tsdown/css` (an optional peer dependency) for its types.\n */\nexport interface CssNodeCompatPluginOptions {\n /** `css.fileName`, the merged CSS file name when `css.splitting` is off. */\n fileName?: string | undefined\n /** `css.splitting`, which switches CSS output from one merged file to one file per chunk. */\n splitting?: boolean | undefined\n /** Prepend an import of the CSS to entry chunks that use it. */\n inject?: boolean | undefined\n /** Publish the CSS files as export subpaths, optionally with the Node-safe shim. */\n exports?: boolean | CssExportsOptions | undefined\n}\n\n/**\n * A tsdown plugin that gives `@tsdown/css` output the same conditional CSS export pattern\n * `@sanity/vanilla-extract-tsdown-plugin` gives vanilla-extract output.\n *\n * `@tsdown/css` compiles CSS but has no node-shim concept: its only `inject` is a relative\n * `import \"./style.css\"`, which throws in every runtime that cannot load `.css` files. For each\n * CSS file `@tsdown/css` emits, this plugin instead:\n *\n * - emits a no-op JS shim (`style.css` -> `style-css.js`) and its `style-css.d.ts` declaration,\n * - writes the `\"./style.css\"` export to `package.json` (and `publishConfig.exports`) through\n * tsdown's `exports` feature, conditional with `nodeCompat` so `browser`/`style` resolve to\n * the stylesheet while `node`/`default` resolve to the shim, and\n * - prepends the self-referential `import \"<pkg>/style.css\"` to entry chunks that use the CSS,\n * replacing `@tsdown/css`'s relative injection.\n *\n * @internal\n */\nexport function cssNodeCompatPlugin(options: CssNodeCompatPluginOptions = {}): TsdownPlugin {\n const {inject, exports: exportsCss, nodeCompat} = resolveCssExportOptions(options)\n const splitting = options.splitting ?? false\n const mergedFileName = options.fileName ?? 'style.css'\n\n /**\n * The ids of the stylesheet modules in the build, mirroring `@tsdown/css`'s own `styles` map\n * so a chunk's CSS usage can be detected without depending on it. Hosts run one build per\n * output format with a shared plugin instance, so the set is append-only.\n */\n const cssModuleIds = new Set<string>()\n /** The package name, for the self-referential CSS import. */\n let packageName: string | undefined\n\n /** The CSS file an entry chunk's own styles are emitted to. */\n const cssFileNameFor = (chunkFileName: string): string =>\n splitting ? toCssFileName(chunkFileName) : mergedFileName\n\n return {\n name: 'sanity-css-node-compat',\n\n // Injection prepends the import through rolldown's native MagicString\n // (`meta.magicString`), which keeps sourcemaps intact.\n options(inputOptions) {\n if (!inject) return undefined\n return {\n ...inputOptions,\n experimental: {...inputOptions.experimental, nativeMagicString: true},\n }\n },\n\n // Record the stylesheet modules without transforming them: `@tsdown/css`'s own `transform`\n // hooks do the compiling, and returning `undefined` here leaves their result untouched.\n transform: {\n filter: {id: RE_CSS_LANG},\n handler(_code, id) {\n if (!RE_CSS_INLINE.test(id)) cssModuleIds.add(id)\n return undefined\n },\n },\n\n // With `exports`, write the `./<cssFileName>` exports to `package.json` (and, through\n // tsdown, to `publishConfig.exports`) by composing into `exports.customExports` before the\n // config is resolved. tsdown's `exports` feature is opt-in, so nothing is written when it\n // is not enabled. Only the merged mode has a statically known file name; with `splitting`\n // the file names follow the chunk names, so those exports are left to the host (which is\n // what `@sanity/pkg-utils` does for its `.css` export subpaths).\n tsdownConfig(config: UserConfig) {\n if (!exportsCss || splitting) return undefined\n const exportsOption = config.exports\n if (!exportsOption) return undefined\n\n // Normalize the `boolean | CIOption | object` forms of the `exports` option into the\n // object form, preserving the enabled-ness (`true` and bare CI conditions mean enabled)\n const exportsOptions: Extract<NonNullable<UserConfig['exports']>, object> = exportsOption ===\n true\n ? {}\n : typeof exportsOption === 'string'\n ? {enabled: exportsOption}\n : exportsOption\n\n const configOutDir = config.outDir ?? 'dist'\n const cssExport = nodeCompat\n ? createConditionalCssExport(mergedFileName, configOutDir)\n : createCssExport(mergedFileName, configOutDir)\n const previousCustomExports = exportsOptions.customExports\n exportsOptions.customExports = async (exportsMap, context) => {\n // Apply a pre-existing `customExports` first (both its function and record forms,\n // mirroring how tsdown itself applies them), then insert the CSS export\n const base =\n typeof previousCustomExports === 'function'\n ? await previousCustomExports(exportsMap, context)\n : previousCustomExports\n ? {...exportsMap, ...previousCustomExports}\n : exportsMap\n // Only declare the export when the build actually emitted the CSS file. A package can\n // enable the pipeline (or have it enabled for it) without any JS-imported CSS, and an\n // export pointing at a file nobody produced is worse than no export at all.\n const emitted = Object.values(context.chunks).some((chunks) =>\n chunks.some((chunk) => chunk.type === 'asset' && chunk.fileName === mergedFileName),\n )\n return emitted ? insertCssExport(base, `./${mergedFileName}`, cssExport) : base\n }\n config.exports = exportsOptions\n return undefined\n },\n\n tsdownConfigResolved(config: ResolvedConfig) {\n packageName = config.pkg?.name\n },\n\n // Inject the CSS import into entry chunks that use CSS: relative by default (like\n // `css.inject` in `@tsdown/css`), or the self-referential bare specifier when the CSS file\n // is published as an export subpath.\n renderChunk(code, chunk, outputOptions, meta) {\n if (!inject || cssModuleIds.size === 0) return undefined\n // The `.d` name / `.d.ts` file checks skip the chunks of tsdown's d.ts passes - they\n // never contain styles.\n if (!chunk.isEntry || chunk.name.endsWith('.d') || RE_DTS.test(chunk.fileName))\n return undefined\n const {format} = outputOptions\n if (format !== 'es' && format !== 'cjs') return undefined\n // In merged mode every stylesheet lands in the same file, so a chunk that reaches CSS\n // through an imported chunk still needs the import. With `splitting` each chunk's CSS\n // goes to its own file, so only the chunk's own modules count - the same condition\n // `@tsdown/css` uses for its relative injection.\n const hasStyles = splitting\n ? chunk.moduleIds.some((id) => cssModuleIds.has(id))\n : chunkHasStyles(chunk, meta.chunks, cssModuleIds)\n if (!hasStyles) return undefined\n\n const cssFileName = cssFileNameFor(chunk.fileName)\n const specifier = JSON.stringify(\n exportsCss\n ? `${resolvePackageName()}/${cssFileName}`\n : relativeImportPath(chunk.fileName, cssFileName),\n )\n const statement = format === 'cjs' ? `require(${specifier});\\n` : `import ${specifier};\\n`\n\n const {magicString} = meta\n if (magicString) {\n magicString.prepend(statement)\n return magicString\n }\n // Fallback when another `options` hook disabled `experimental.nativeMagicString`: the\n // import is still injected, but the chunk's sourcemap can't be adjusted for it.\n if (outputOptions.sourcemap) {\n this.warn(\n `[sanity-css-node-compat] rolldown's native magic-string is unavailable, so the CSS import injected into \"${chunk.fileName}\" shifts its sourcemap by one line.`,\n )\n }\n return {code: statement + code}\n },\n\n // Emit a no-op JS shim and its declaration file next to every CSS file `@tsdown/css`\n // emitted, for the `node`/`default` and `types` conditions of the export to point at.\n // `order: 'post'` is required: tsdown registers the `@tsdown/css` output plugins after the\n // user plugins, so the CSS assets only exist in the bundle once they have run.\n generateBundle: {\n order: 'post',\n handler(_outputOptions, bundle) {\n if (!nodeCompat) return\n const cssFileNames = Object.values(bundle)\n .filter((asset) => asset.type === 'asset' && RE_CSS_ASSET.test(asset.fileName))\n .map((asset) => asset.fileName)\n\n for (const cssFileName of cssFileNames) {\n const shimFileName = cssShimFileName(cssFileName)\n // Another plugin (`@sanity/vanilla-extract-rolldown-plugin` for `bundle.css`) may\n // already own this CSS file and have emitted its shims.\n if (bundle[shimFileName]) continue\n this.emitFile({\n type: 'asset',\n fileName: shimFileName,\n source: cssShimSource(cssFileName),\n })\n this.emitFile({\n type: 'asset',\n fileName: cssShimDtsFileName(cssFileName),\n source: cssShimDtsSource(cssFileName),\n })\n }\n },\n },\n }\n\n function resolvePackageName(): string {\n if (!packageName) {\n throw new Error(\n `[sanity-css-node-compat] Unable to resolve the package name from package.json, which is required by \\`css.exports\\` for the self-referential CSS import. Disable \\`css.exports\\` (or \\`css.inject\\`) to wire up the CSS import yourself.`,\n )\n }\n return packageName\n }\n}\n\n/** The relative import path from a chunk to a CSS file, like the `css.inject` in `@tsdown/css`. */\nfunction relativeImportPath(chunkFileName: string, cssFileName: string): string {\n const relativePath = path.posix.relative(path.posix.dirname(chunkFileName), cssFileName)\n return relativePath.startsWith('.') ? relativePath : `./${relativePath}`\n}\n\n/** Whether a chunk (or any chunk it imports, transitively) contains stylesheet modules. */\nfunction chunkHasStyles(\n chunk: {fileName: string; moduleIds: string[]; imports: string[]; dynamicImports: string[]},\n chunks: Record<\n string,\n {fileName: string; moduleIds: string[]; imports: string[]; dynamicImports: string[]}\n >,\n cssModuleIds: ReadonlySet<string>,\n): boolean {\n const seen = new Set<string>()\n const queue = [chunk]\n for (let current = queue.pop(); current; current = queue.pop()) {\n if (seen.has(current.fileName)) continue\n seen.add(current.fileName)\n if (current.moduleIds.some((id) => cssModuleIds.has(id))) return true\n for (const imported of [...current.imports, ...current.dynamicImports]) {\n const importedChunk = chunks[imported]\n if (importedChunk) queue.push(importedChunk)\n }\n }\n return false\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"cssNodeCompatPlugin-B_ndKoRv.mjs","names":[],"sources":["../src/cssNodeCompatPlugin.ts"],"sourcesContent":["import path from 'node:path'\nimport {\n createConditionalCssExport,\n createCssExport,\n cssShimDtsFileName,\n cssShimDtsSource,\n cssShimFileName,\n cssShimSource,\n insertCssExport,\n resolveCssExportOptions,\n type CssExportsOptions,\n} from '@sanity/vanilla-extract-tsdown-plugin'\nimport type {ResolvedConfig, TsdownPlugin, UserConfig} from 'tsdown'\n\n/**\n * Matches the module ids `@tsdown/css` treats as stylesheets, so this plugin can tell which\n * chunks pulled CSS in without reaching into `@tsdown/css`'s own bookkeeping.\n */\nconst RE_CSS_LANG = /\\.(css|less|sass|scss|styl|stylus)(?:$|\\?)/\n/** Matches `?inline` CSS imports, which `@tsdown/css` inlines into JS instead of extracting. */\nconst RE_CSS_INLINE = /[?&]inline\\b/\n/** Matches rendered `.d.ts`/`.d.mts`/`.d.cts` chunk file names. */\nconst RE_DTS = /\\.d\\.[cm]?ts$/\n/** Matches the emitted CSS assets whose shims and exports this plugin maintains. */\nconst RE_CSS_ASSET = /\\.css$/\n\n/** `index.mjs` -> `index.css`, the naming `@tsdown/css` uses when `css.splitting` is on. */\nfunction toCssFileName(jsFileName: string): string {\n return jsFileName.replace(/(?:\\.module)?(\\.[cm]?js)$/, '.css')\n}\n\n/**\n * The `@tsdown/css` options this plugin needs to mirror. Kept structural so the plugin does not\n * have to import `@tsdown/css` (an optional peer dependency) for its types.\n */\nexport interface CssNodeCompatPluginOptions {\n /** `css.fileName`, the merged CSS file name when `css.splitting` is off. */\n fileName?: string | undefined\n /** `css.splitting`, which switches CSS output from one merged file to one file per chunk. */\n splitting?: boolean | undefined\n /** Prepend an import of the CSS to entry chunks that use it. */\n inject?: boolean | undefined\n /** Publish the CSS files as export subpaths, optionally with the Node-safe shim. */\n exports?: boolean | CssExportsOptions | undefined\n}\n\n/**\n * A tsdown plugin that gives `@tsdown/css` output the same conditional CSS export pattern\n * `@sanity/vanilla-extract-tsdown-plugin` gives vanilla-extract output.\n *\n * `@tsdown/css` compiles CSS but has no node-shim concept: its only `inject` is a relative\n * `import \"./style.css\"`, which throws in every runtime that cannot load `.css` files. For each\n * CSS file `@tsdown/css` emits, this plugin instead:\n *\n * - emits a no-op JS shim (`style.css` -> `style-css.js`) and its `style-css.d.ts` declaration,\n * - writes the `\"./style.css\"` export to `package.json` (and `publishConfig.exports`) through\n * tsdown's `exports` feature, conditional with `nodeCompat` so `browser`/`style` resolve to\n * the stylesheet while `node`/`default` resolve to the shim, and\n * - prepends the self-referential `import \"<pkg>/style.css\"` to entry chunks that use the CSS,\n * replacing `@tsdown/css`'s relative injection.\n *\n * @internal\n */\nexport function cssNodeCompatPlugin(options: CssNodeCompatPluginOptions = {}): TsdownPlugin {\n const {inject, exports: exportsCss, nodeCompat} = resolveCssExportOptions(options)\n const splitting = options.splitting ?? false\n const mergedFileName = options.fileName ?? 'style.css'\n\n /**\n * The ids of the stylesheet modules in the build, mirroring `@tsdown/css`'s own `styles` map\n * so a chunk's CSS usage can be detected without depending on it. Hosts run one build per\n * output format with a shared plugin instance, so the set is append-only.\n */\n const cssModuleIds = new Set<string>()\n /** The package name, for the self-referential CSS import. */\n let packageName: string | undefined\n\n /** The CSS file an entry chunk's own styles are emitted to. */\n const cssFileNameFor = (chunkFileName: string): string =>\n splitting ? toCssFileName(chunkFileName) : mergedFileName\n\n return {\n name: 'sanity-css-node-compat',\n\n // Injection prepends the import through rolldown's native MagicString\n // (`meta.magicString`), which keeps sourcemaps intact.\n options(inputOptions) {\n if (!inject) return undefined\n return {\n ...inputOptions,\n experimental: {...inputOptions.experimental, nativeMagicString: true},\n }\n },\n\n // Record the stylesheet modules without transforming them: `@tsdown/css`'s own `transform`\n // hooks do the compiling, and returning `undefined` here leaves their result untouched.\n transform: {\n filter: {id: RE_CSS_LANG},\n handler(_code, id) {\n if (!RE_CSS_INLINE.test(id)) cssModuleIds.add(id)\n return undefined\n },\n },\n\n // With `exports`, write the `./<cssFileName>` exports to `package.json` (and, through\n // tsdown, to `publishConfig.exports`) by composing into `exports.customExports` before the\n // config is resolved. tsdown's `exports` feature is opt-in, so nothing is written when it\n // is not enabled. Only the merged mode has a statically known file name; with `splitting`\n // the file names follow the chunk names, so those exports are left to the host (which is\n // what `@sanity/pkg-utils` does for its `.css` export subpaths).\n tsdownConfig(config: UserConfig) {\n if (!exportsCss || splitting) return undefined\n const exportsOption = config.exports\n if (!exportsOption) return undefined\n\n // Normalize the `boolean | CIOption | object` forms of the `exports` option into the\n // object form, preserving the enabled-ness (`true` and bare CI conditions mean enabled)\n const exportsOptions: Extract<NonNullable<UserConfig['exports']>, object> = exportsOption ===\n true\n ? {}\n : typeof exportsOption === 'string'\n ? {enabled: exportsOption}\n : exportsOption\n\n const configOutDir = config.outDir ?? 'dist'\n const cssExport = nodeCompat\n ? createConditionalCssExport(mergedFileName, configOutDir)\n : createCssExport(mergedFileName, configOutDir)\n const previousCustomExports = exportsOptions.customExports\n exportsOptions.customExports = async (exportsMap, context) => {\n // Apply a pre-existing `customExports` first (both its function and record forms,\n // mirroring how tsdown itself applies them), then insert the CSS export\n const base =\n typeof previousCustomExports === 'function'\n ? await previousCustomExports(exportsMap, context)\n : previousCustomExports\n ? {...exportsMap, ...previousCustomExports}\n : exportsMap\n // Only declare the export when the build actually emitted the CSS file. A package can\n // enable the pipeline (or have it enabled for it) without any JS-imported CSS, and an\n // export pointing at a file nobody produced is worse than no export at all.\n const emitted = Object.values(context.chunks).some((chunks) =>\n chunks.some((chunk) => chunk.type === 'asset' && chunk.fileName === mergedFileName),\n )\n return emitted ? insertCssExport(base, `./${mergedFileName}`, cssExport) : base\n }\n config.exports = exportsOptions\n return undefined\n },\n\n tsdownConfigResolved(config: ResolvedConfig) {\n packageName = config.pkg?.name\n },\n\n // Inject the CSS import into entry chunks that use CSS: relative by default (like\n // `css.inject` in `@tsdown/css`), or the self-referential bare specifier when the CSS file\n // is published as an export subpath.\n renderChunk(code, chunk, outputOptions, meta) {\n if (!inject || cssModuleIds.size === 0) return undefined\n // The `.d` name / `.d.ts` file checks skip the chunks of tsdown's d.ts passes - they\n // never contain styles.\n if (!chunk.isEntry || chunk.name.endsWith('.d') || RE_DTS.test(chunk.fileName))\n return undefined\n const {format} = outputOptions\n if (format !== 'es' && format !== 'cjs') return undefined\n // In merged mode every stylesheet lands in the same file, so a chunk that reaches CSS\n // through an imported chunk still needs the import. With `splitting` each chunk's CSS\n // goes to its own file, so only the chunk's own modules count - the same condition\n // `@tsdown/css` uses for its relative injection.\n const hasStyles = splitting\n ? chunk.moduleIds.some((id) => cssModuleIds.has(id))\n : chunkHasStyles(chunk, meta.chunks, cssModuleIds)\n if (!hasStyles) return undefined\n\n const cssFileName = cssFileNameFor(chunk.fileName)\n const specifier = JSON.stringify(\n exportsCss\n ? `${resolvePackageName()}/${cssFileName}`\n : relativeImportPath(chunk.fileName, cssFileName),\n )\n const statement = format === 'cjs' ? `require(${specifier});\\n` : `import ${specifier};\\n`\n\n const {magicString} = meta\n if (magicString) {\n magicString.prepend(statement)\n return magicString\n }\n // Fallback when another `options` hook disabled `experimental.nativeMagicString`: the\n // import is still injected, but the chunk's sourcemap can't be adjusted for it.\n if (outputOptions.sourcemap) {\n this.warn(\n `[sanity-css-node-compat] rolldown's native magic-string is unavailable, so the CSS import injected into \"${chunk.fileName}\" shifts its sourcemap by one line.`,\n )\n }\n return {code: statement + code}\n },\n\n // Emit a no-op JS shim and its declaration file next to every CSS file `@tsdown/css`\n // emitted, for the `node`/`default` and `types` conditions of the export to point at.\n // `order: 'post'` is required: tsdown registers the `@tsdown/css` output plugins after the\n // user plugins, so the CSS assets only exist in the bundle once they have run.\n generateBundle: {\n order: 'post',\n handler(_outputOptions, bundle) {\n if (!nodeCompat) return\n const cssFileNames = Object.values(bundle)\n .filter((asset) => asset.type === 'asset' && RE_CSS_ASSET.test(asset.fileName))\n .map((asset) => asset.fileName)\n\n for (const cssFileName of cssFileNames) {\n const shimFileName = cssShimFileName(cssFileName)\n // Another plugin (`@sanity/vanilla-extract-rolldown-plugin` for `bundle.css`) may\n // already own this CSS file and have emitted its shims.\n if (bundle[shimFileName]) continue\n this.emitFile({\n type: 'asset',\n fileName: shimFileName,\n source: cssShimSource(cssFileName),\n })\n this.emitFile({\n type: 'asset',\n fileName: cssShimDtsFileName(cssFileName),\n source: cssShimDtsSource(cssFileName),\n })\n }\n },\n },\n }\n\n function resolvePackageName(): string {\n if (!packageName) {\n throw new Error(\n `[sanity-css-node-compat] Unable to resolve the package name from package.json, which is required by \\`css.exports\\` for the self-referential CSS import. Disable \\`css.exports\\` (or \\`css.inject\\`) to wire up the CSS import yourself.`,\n )\n }\n return packageName\n }\n}\n\n/** The relative import path from a chunk to a CSS file, like the `css.inject` in `@tsdown/css`. */\nfunction relativeImportPath(chunkFileName: string, cssFileName: string): string {\n const relativePath = path.posix.relative(path.posix.dirname(chunkFileName), cssFileName)\n return relativePath.startsWith('.') ? relativePath : `./${relativePath}`\n}\n\n/** Whether a chunk (or any chunk it imports, transitively) contains stylesheet modules. */\nfunction chunkHasStyles(\n chunk: {fileName: string; moduleIds: string[]; imports: string[]; dynamicImports: string[]},\n chunks: Record<\n string,\n {fileName: string; moduleIds: string[]; imports: string[]; dynamicImports: string[]}\n >,\n cssModuleIds: ReadonlySet<string>,\n): boolean {\n const seen = new Set<string>()\n const queue = [chunk]\n for (let current = queue.pop(); current; current = queue.pop()) {\n if (seen.has(current.fileName)) continue\n seen.add(current.fileName)\n if (current.moduleIds.some((id) => cssModuleIds.has(id))) return true\n for (const imported of [...current.imports, ...current.dynamicImports]) {\n const importedChunk = chunks[imported]\n if (importedChunk) queue.push(importedChunk)\n }\n }\n return false\n}\n"],"mappings":"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"}
|
package/dist/tsdoc.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tsdoc.mjs","names":["\"default\""],"sources":["../src/tsdoc/createApiExtractorConfig.ts","../src/tsdoc/createTSDocConfig.ts","../src/tsdoc/getExtractMessagesConfig.ts","../src/tsdoc/synthesizedNamespaces.ts","../src/tsdoc/checkTsdoc.ts"],"sourcesContent":["import path from 'node:path'\nimport type {IConfigFile, IExtractorMessagesConfig} from '@microsoft/api-extractor'\n\n/** @internal */\nexport function createApiExtractorConfig(options: {\n bundledPackages?: string[]\n distPath: string\n exportPath: string\n filePath: string\n messages: IExtractorMessagesConfig\n projectFolder: string\n mainEntryPointFilePath: string\n /**\n * Only `compilerOptions.paths` is read: when present, API Extractor gets an override that\n * clears `paths` so self-referencing package imports resolve through `node_modules` instead.\n */\n tsconfig: {options: {paths?: unknown}}\n tsconfigPath: string\n}): IConfigFile {\n const {\n bundledPackages,\n distPath,\n exportPath,\n filePath,\n messages,\n projectFolder,\n mainEntryPointFilePath,\n tsconfig,\n tsconfigPath,\n } = options\n\n return {\n apiReport: {\n enabled: false,\n reportFileName: '<unscopedPackageName>.api.md',\n },\n bundledPackages,\n\n // If `paths` are used for self-referencing imports (e.g. the module is named `sanity`, and the `sanity/structure` export is also importing from `sanity/router`),\n compiler: tsconfig.options.paths\n ? {\n overrideTsconfig: {\n extends: tsconfigPath,\n compilerOptions: {\n // An empty object replaces whatever is in the original tsconfig file\n paths: {},\n },\n },\n }\n : {tsconfigFilePath: tsconfigPath},\n\n docModel: {\n enabled: false,\n apiJsonFilePath: path.resolve(distPath, `${exportPath}.api.json`),\n },\n dtsRollup: {\n // Types come from tsdown; this check only runs API Extractor's TSDoc/release-tag rules\n enabled: false,\n untrimmedFilePath: path.resolve(distPath, filePath),\n },\n tsdocMetadata: {\n enabled: false,\n },\n messages,\n mainEntryPointFilePath,\n projectFolder,\n }\n}\n","import {readFile} from 'node:fs/promises'\nimport {createRequire} from 'node:module'\nimport {TSDocConfigFile} from '@microsoft/tsdoc-config'\nimport {parse} from 'jsonc-parser'\nimport type {PackageTsdocCustomTag} from './types.ts'\n\nconst require = createRequire(import.meta.url)\n\n/** @internal */\nexport async function createTSDocConfig(opts: {\n customTags: PackageTsdocCustomTag[]\n}): Promise<TSDocConfigFile | undefined> {\n const {customTags} = opts\n\n if (customTags.length === 0) {\n return undefined\n }\n\n const tsDocBaseBuf = await readFile(\n require.resolve('@microsoft/api-extractor/extends/tsdoc-base.json'),\n )\n\n // Include the definitions that are required for API Extractor\n // extends: ['@microsoft/api-extractor/extends/tsdoc-base.json'],\n const tsDocBaseConfig = parse(tsDocBaseBuf.toString())\n\n // Define custom tags and specify how they should be parsed\n const tagDefinitions = (tsDocBaseConfig.tagDefinitions || []).concat(\n customTags.map((t) => ({\n tagName: `@${t.name}`,\n syntaxKind: t.syntaxKind,\n allowMultiple: t.allowMultiple,\n })),\n )\n\n // Indicate that custom tags are supported by your tooling.\n // (Without this, warnings may be reported saying that a tag is unsupported.)\n const supportForTags = {...tsDocBaseConfig.supportForTags}\n\n for (const customTag of customTags) {\n supportForTags[`@${customTag.name}`] = true\n }\n\n return TSDocConfigFile.loadFromObject({\n ...tsDocBaseConfig,\n noStandardTags: false,\n tagDefinitions,\n supportForTags,\n })\n}\n","import {ExtractorLogLevel, type IExtractorMessagesConfig} from '@microsoft/api-extractor'\nimport type {PackageTsdocOptions, PackageTsdocRuleLevel} from './types.ts'\n\nconst LOG_LEVELS: Record<PackageTsdocRuleLevel, ExtractorLogLevel> = {\n error: ExtractorLogLevel.Error,\n info: ExtractorLogLevel.Info,\n off: ExtractorLogLevel.None,\n warn: ExtractorLogLevel.Warning,\n}\n\n/** @internal */\nexport function getExtractMessagesConfig(options: {\n rules: PackageTsdocOptions['rules']\n disabled?: boolean\n}): IExtractorMessagesConfig {\n const {rules, disabled = false} = options\n\n function ruleToLogLevel(\n key: keyof NonNullable<PackageTsdocOptions['rules']>,\n defaultLevel?: ExtractorLogLevel,\n ) {\n const r = rules?.[key]\n\n return r ? LOG_LEVELS[r] : defaultLevel || ExtractorLogLevel.Warning\n }\n\n return {\n compilerMessageReporting: {\n default: {\n logLevel: disabled ? ExtractorLogLevel.None : ExtractorLogLevel.Warning,\n },\n },\n\n extractorMessageReporting: disabled\n ? {\n default: {\n logLevel: ExtractorLogLevel.None,\n addToApiReportFile: false,\n },\n }\n : {\n 'default': {\n logLevel: ExtractorLogLevel.Warning,\n addToApiReportFile: false,\n },\n\n 'ae-forgotten-export': {\n /**\n * This is hardcoded to `none` as it's no longer needed since TypeScript 5.5 https://github.com/microsoft/TypeScript/issues/42873\n * It's hardcoded to `none` since supported by API Extractor when using `module: 'Preserve'` doesn't support it well since `@microsoft/api-extractor` v7.49.0, which upgraded from TS 5.4 to 5.7 internally\n */\n logLevel: ExtractorLogLevel.None,\n addToApiReportFile: false,\n },\n\n 'ae-incompatible-release-tags': {\n logLevel: ruleToLogLevel('ae-incompatible-release-tags', ExtractorLogLevel.Error),\n addToApiReportFile: false,\n },\n\n 'ae-internal-missing-underscore': {\n logLevel: ruleToLogLevel('ae-internal-missing-underscore'),\n addToApiReportFile: false,\n },\n\n 'ae-missing-release-tag': {\n logLevel: ruleToLogLevel('ae-missing-release-tag', ExtractorLogLevel.Error),\n addToApiReportFile: false,\n },\n\n 'ae-wrong-input-file-type': {\n logLevel: ExtractorLogLevel.None,\n addToApiReportFile: false,\n },\n },\n\n tsdocMessageReporting: disabled\n ? {\n default: {\n logLevel: ExtractorLogLevel.None,\n addToApiReportFile: false,\n },\n }\n : {\n 'default': {\n logLevel: ExtractorLogLevel.Warning,\n addToApiReportFile: false,\n },\n\n 'tsdoc-link-tag-unescaped-text': {\n logLevel: ruleToLogLevel('tsdoc-link-tag-unescaped-text', ExtractorLogLevel.Warning),\n addToApiReportFile: false,\n },\n\n 'tsdoc-undefined-tag': {\n logLevel: ruleToLogLevel('tsdoc-undefined-tag', ExtractorLogLevel.Error),\n addToApiReportFile: false,\n },\n\n 'tsdoc-unsupported-tag': {\n logLevel: ruleToLogLevel('tsdoc-unsupported-tag', ExtractorLogLevel.None),\n addToApiReportFile: false,\n },\n },\n }\n}\n","import {existsSync, readFileSync} from 'node:fs'\nimport path from 'node:path'\n// The JS compiler API is loaded from the official `@typescript/typescript6` compat package\n// instead of the `typescript` peer dependency, as TypeScript 7 (the Go-native compiler) no longer\n// ships it\nimport ts from '@typescript/typescript6'\n\n/**\n * The exports-object identifiers of rolldown's namespace interop: `<module>_exports` (the\n * declaration bundling pass names them after the virtual declaration module, e.g. `inner.d.ts`\n * → `inner_d_exports`), with rolldown's `$<n>` suffix when deconflicting renames one.\n */\nconst RE_WRAPPER_NAME = /_exports(\\$\\d+)?$/\n\n/** Matches the relative specifiers of emitted sibling chunks (`./chunk-<hash>.js`). */\nconst RE_RELATIVE_SPECIFIER = /^\\.\\.?\\//\n\n/**\n * Finds the local names of the `declare namespace <name>_exports {…}` wrappers that the\n * declaration bundling pass (tsdown / rolldown-plugin-dts) synthesizes for namespace re-exports\n * like `export * as ns from './module'` (or `import * as ns` + `export {ns}`).\n *\n * Bundling loses the doc comment of the re-export statement, so the wrapper cannot carry a\n * release tag — there is no way to tag it from userland, and API Extractor would flag it with\n * `ae-missing-release-tag` (https://github.com/sanity-io/pkg-utils/issues/3281). Skipping it\n * matches how API Extractor treats the equivalent namespace of its own rollups (it never\n * checks those). The members re-exported through the wrapper keep their own doc comments in\n * the output; API Extractor does not flag them individually either way (only directly exported\n * declarations are consumable entities of the missing-release-tag check).\n *\n * A name only qualifies when all of these hold, so user-authored symbols that merely resemble\n * the interop naming stay checked:\n *\n * - it matches rolldown's `<module>_exports` naming (with an optional `$<n>` deconflict suffix)\n * - it is declared as a namespace — in the entry itself, or in a sibling chunk the entry\n * imports (a wrapper shared by several entries lives in the chunk that owns the module's\n * declarations)\n * - that namespace has the synthesized body shape: nothing but `export { … };` specifier lists\n * pointing at sibling declarations of the same file. A user-authored namespace declares its\n * own members (`declare namespace config_exports { const userValue: string; }`), and those\n * members are what the author tags — so it stays checked even when the bundler's\n * deconflicting hands it a wrapper-shaped name\n * - the entry does not export the name unaliased: a synthesized wrapper is always re-exported\n * under the alias of the original namespace re-export (`export { inner_d_exports as inner }`),\n * while an unaliased export (`export { foo_exports }`, `export declare namespace foo_exports`)\n * is a name the author chose — and can tag\n * @internal\n */\nexport function collectSynthesizedNamespaceWrappers(entryDtsFile: string): Set<string> {\n const entry = parseDts(entryDtsFile)\n if (!entry) return new Set()\n\n const unaliasedExports = new Set<string>()\n const wrapperShapedNames = new Set<string>()\n const chunkFiles = new Set<string>()\n\n for (const statement of entry.statements) {\n collectWrapperShapedNamespaceName(statement, wrapperShapedNames)\n\n if (ts.isExportDeclaration(statement)) {\n const {exportClause} = statement\n if (exportClause && ts.isNamedExports(exportClause)) {\n for (const element of exportClause.elements) {\n if (!element.propertyName || element.propertyName.text === element.name.text) {\n unaliasedExports.add(element.name.text)\n }\n }\n } else if (exportClause && ts.isNamespaceExport(exportClause)) {\n unaliasedExports.add(exportClause.name.text)\n }\n collectChunkFile(entryDtsFile, statement.moduleSpecifier, chunkFiles)\n } else if (ts.isImportDeclaration(statement)) {\n collectChunkFile(entryDtsFile, statement.moduleSpecifier, chunkFiles)\n } else {\n collectExportedDeclarationNames(statement, unaliasedExports)\n }\n }\n\n for (const chunkFile of chunkFiles) {\n const chunk = parseDts(chunkFile)\n if (!chunk) continue\n for (const statement of chunk.statements) {\n collectWrapperShapedNamespaceName(statement, wrapperShapedNames)\n }\n }\n\n const wrappers = new Set<string>()\n for (const name of wrapperShapedNames) {\n if (RE_WRAPPER_NAME.test(name) && !unaliasedExports.has(name)) wrappers.add(name)\n }\n return wrappers\n}\n\nfunction parseDts(filePath: string): ts.SourceFile | undefined {\n if (!existsSync(filePath)) return undefined\n return ts.createSourceFile(\n filePath,\n readFileSync(filePath, 'utf8'),\n ts.ScriptTarget.Latest,\n false,\n )\n}\n\n/**\n * Collects the name of a top-level `declare namespace <Identifier> {…}` statement whose body has\n * the shape the declaration bundling pass synthesizes: only `export { … };` specifier lists\n * naming sibling declarations of the same file, never members of its own. Every namespace\n * re-export the bundler rewrites comes out that way, whatever the re-exported module holds\n * (values, types, a default export, further namespace re-exports).\n */\nfunction collectWrapperShapedNamespaceName(statement: ts.Statement, names: Set<string>): void {\n if (\n !ts.isModuleDeclaration(statement) ||\n !ts.isIdentifier(statement.name) ||\n (statement.flags & ts.NodeFlags.Namespace) === 0\n ) {\n return\n }\n\n const {body} = statement\n if (!body || !ts.isModuleBlock(body)) return\n\n const onlyReExportsSiblings = body.statements.every(\n (member) =>\n ts.isExportDeclaration(member) &&\n !member.moduleSpecifier &&\n member.exportClause !== undefined &&\n ts.isNamedExports(member.exportClause),\n )\n if (!onlyReExportsSiblings) return\n\n names.add(statement.name.text)\n}\n\n/**\n * Collects the names a declaration with an `export` modifier exports directly, e.g.\n * `export declare namespace foo_exports {…}` — those names are user-chosen (the author can\n * tag them), unlike the alias-only re-export of a synthesized wrapper.\n */\nfunction collectExportedDeclarationNames(statement: ts.Statement, names: Set<string>): void {\n const modifiers = ts.canHaveModifiers(statement) ? ts.getModifiers(statement) : undefined\n if (!modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword)) return\n\n if (ts.isVariableStatement(statement)) {\n for (const declaration of statement.declarationList.declarations) {\n if (ts.isIdentifier(declaration.name)) names.add(declaration.name.text)\n }\n } else if (\n (ts.isFunctionDeclaration(statement) ||\n ts.isClassDeclaration(statement) ||\n ts.isInterfaceDeclaration(statement) ||\n ts.isTypeAliasDeclaration(statement) ||\n ts.isEnumDeclaration(statement)) &&\n statement.name\n ) {\n names.add(statement.name.text)\n } else if (ts.isModuleDeclaration(statement) && ts.isIdentifier(statement.name)) {\n names.add(statement.name.text)\n }\n}\n\n/**\n * Resolves the sibling chunk file a relative import/export specifier points at, mapping the\n * runtime extension to the declaration extension the chunk is emitted with on disk\n * (`./chunk.js` → `./chunk.d.ts`, like the declaration output of the bundling pass itself).\n */\nfunction collectChunkFile(\n entryDtsFile: string,\n moduleSpecifier: ts.Expression | undefined,\n files: Set<string>,\n): void {\n if (!moduleSpecifier || !ts.isStringLiteral(moduleSpecifier)) return\n const specifier = moduleSpecifier.text\n if (!RE_RELATIVE_SPECIFIER.test(specifier)) return\n const dtsFile = specifierToDtsFile(specifier)\n if (!dtsFile) return\n files.add(path.resolve(path.dirname(entryDtsFile), dtsFile))\n}\n\n/** `./chunk.js` → `./chunk.d.ts` (`.mjs` → `.d.mts`, `.cjs` → `.d.cts`). */\nfunction specifierToDtsFile(specifier: string): string | undefined {\n if (/\\.d\\.[mc]?ts$/.test(specifier)) return specifier\n if (specifier.endsWith('.mjs')) return `${specifier.slice(0, -4)}.d.mts`\n if (specifier.endsWith('.cjs')) return `${specifier.slice(0, -4)}.d.cts`\n if (specifier.endsWith('.js')) return `${specifier.slice(0, -3)}.d.ts`\n return undefined\n}\n","import {existsSync} from 'node:fs'\nimport path from 'node:path'\nimport {\n Extractor,\n ExtractorConfig,\n ExtractorLogLevel,\n type ExtractorMessage,\n} from '@microsoft/api-extractor'\n// The JS compiler API is loaded from the official `@typescript/typescript6` compat package\n// instead of the `typescript` peer dependency, as TypeScript 7 (the Go-native compiler) no longer\n// ships it\nimport ts from '@typescript/typescript6'\nimport {createApiExtractorConfig} from './createApiExtractorConfig.ts'\nimport {createTSDocConfig} from './createTSDocConfig.ts'\nimport {getExtractMessagesConfig} from './getExtractMessagesConfig.ts'\nimport {collectSynthesizedNamespaceWrappers} from './synthesizedNamespaces.ts'\nimport type {PackageTsdocOptions} from './types.ts'\n\n/** @public */\nexport interface CheckTsdocLogger {\n log: (...args: unknown[]) => void\n warn: (...args: unknown[]) => void\n error: (...args: unknown[]) => void\n}\n\n/** @public */\nexport interface CheckTsdocOptions extends PackageTsdocOptions {\n /** Package root (directory containing `package.json`). */\n cwd: string\n /**\n * Absolute paths to the entry `.d.ts` / `.d.mts` / `.d.cts` files to check.\n * JS-only entries with no declarations are skipped automatically when listed.\n */\n entryDtsFiles: string[]\n /**\n * Path to the tsconfig used for the build, relative to `cwd` or absolute.\n * @defaultValue `'tsconfig.json'`\n */\n tsconfig?: string\n /**\n * Directory of distributed files (used for API Extractor's path mapping). Defaults to the\n * common parent of `entryDtsFiles`, or `dist` under `cwd` when the list is empty.\n */\n outDir?: string\n /**\n * When provided, messages are printed through this logger. Errors throw after reporting so\n * callers (and tsdown's `build:done` hook) fail the build.\n */\n logger?: CheckTsdocLogger\n}\n\n/** @public */\nexport interface CheckTsdocResult {\n messages: ExtractorMessage[]\n errorCount: number\n warningCount: number\n}\n\n/**\n * Run `@microsoft/api-extractor` against the given entry declaration files to check that TSDoc\n * tags are valid and release tags are correct. Import from `@sanity/tsdown-config/tsdoc`.\n * @public\n */\nexport async function checkTsdoc(options: CheckTsdocOptions): Promise<CheckTsdocResult> {\n const {\n cwd,\n entryDtsFiles,\n bundledPackages,\n customTags = [],\n rules = {},\n logger,\n outDir: outDirOption,\n } = options\n\n const tsconfigPath = path.resolve(cwd, options.tsconfig || 'tsconfig.json')\n const tsconfig = loadTSConfig({cwd, tsconfigPath})\n // api-extractor needs a `compilerOptions.outDir` for its path mapping; tsdown does not, so\n // fall back to the configured outDir / dist folder when the tsconfig leaves it unset\n const outDir =\n tsconfig?.options.outDir ??\n (outDirOption ? path.resolve(cwd, outDirOption) : undefined) ??\n commonParentDir(entryDtsFiles) ??\n path.resolve(cwd, 'dist')\n\n const tsdocConfigFile = await createTSDocConfig({customTags})\n const messagesConfig = getExtractMessagesConfig({rules})\n const allMessages: ExtractorMessage[] = []\n\n for (const exportPath of entryDtsFiles) {\n if (!existsSync(exportPath)) continue\n\n // The declaration bundling pass synthesizes `declare namespace <name>_exports` wrappers\n // for namespace re-exports and loses the doc comment of the re-export statement, so the\n // wrappers can never carry a release tag — `ae-missing-release-tag` skips them.\n // https://github.com/sanity-io/pkg-utils/issues/3281\n const synthesizedWrappers = collectSynthesizedNamespaceWrappers(exportPath)\n const relativeDtsPath = path.relative(outDir, exportPath)\n const extractorConfig = ExtractorConfig.prepare({\n configObject: createApiExtractorConfig({\n bundledPackages,\n distPath: outDir,\n exportPath,\n filePath: relativeDtsPath,\n messages: messagesConfig,\n projectFolder: cwd,\n mainEntryPointFilePath: exportPath,\n tsconfig: tsconfig ?? {options: {}},\n tsconfigPath,\n }),\n configObjectFullPath: undefined,\n tsdocConfigFile,\n packageJsonFullPath: path.resolve(cwd, 'package.json'),\n })\n\n Extractor.invoke(extractorConfig, {\n localBuild: true,\n showVerboseMessages: true,\n messageCallback(message: ExtractorMessage) {\n message.handled = true\n if (isSynthesizedNamespaceWrapperMessage(message, synthesizedWrappers)) return\n allMessages.push(message)\n },\n })\n }\n\n const warnings = allMessages.filter((msg) => msg.logLevel === ExtractorLogLevel.Warning)\n const errors = allMessages.filter((msg) => msg.logLevel === ExtractorLogLevel.Error)\n\n if (logger) {\n reportMessages(cwd, logger, warnings, errors)\n }\n\n if (errors.length) {\n throw new Error(\n `TSDoc/release-tag check failed with ${errors.length} error${errors.length === 1 ? '' : 's'}`,\n )\n }\n\n return {\n messages: allMessages,\n errorCount: errors.length,\n warningCount: warnings.length,\n }\n}\n\nfunction loadTSConfig(options: {\n cwd: string\n tsconfigPath: string\n}): ReturnType<typeof ts.parseJsonConfigFileContent> | undefined {\n const {cwd, tsconfigPath} = options\n // Resolve a relative name from `cwd` (e.g. `tsconfig.dist.json`); an absolute path is kept.\n let configPath: string | undefined\n if (path.isAbsolute(tsconfigPath)) {\n configPath = tsconfigPath\n } else {\n // oxlint-disable-next-line unbound-method\n configPath = ts.findConfigFile(cwd, ts.sys.fileExists, tsconfigPath)\n }\n if (!configPath || !existsSync(configPath)) return undefined\n // oxlint-disable-next-line unbound-method\n const configFile = ts.readConfigFile(configPath, ts.sys.readFile)\n // Relative `extends`/`include`/`paths` are resolved from the tsconfig's directory, not `cwd`\n return ts.parseJsonConfigFileContent(configFile.config, ts.sys, path.dirname(configPath))\n}\n\n/** The quoted symbol name leading api-extractor's `ae-missing-release-tag` message text. */\nconst RE_MISSING_RELEASE_TAG_SYMBOL = /^\"([^\"]+)\" is part of the package's API/\n\n/**\n * Whether a message is an `ae-missing-release-tag` complaint about a namespace wrapper the\n * declaration bundling pass synthesized (which userland can never tag). The flagged symbol is\n * only identifiable through the message text: api-extractor quotes the local name of the\n * declaration, and attaches no structured properties (its source location maps through\n * `.d.ts.map` files, often landing on an unrelated source position).\n */\nfunction isSynthesizedNamespaceWrapperMessage(\n message: ExtractorMessage,\n synthesizedWrappers: Set<string>,\n): boolean {\n if (synthesizedWrappers.size === 0 || message.messageId !== 'ae-missing-release-tag') {\n return false\n }\n const symbolName = RE_MISSING_RELEASE_TAG_SYMBOL.exec(message.text)?.[1]\n return symbolName !== undefined && synthesizedWrappers.has(symbolName)\n}\n\nfunction commonParentDir(files: string[]): string | undefined {\n if (files.length === 0) return undefined\n let dir = path.dirname(files[0]!)\n for (const file of files.slice(1)) {\n while (dir !== path.dirname(dir) && !file.startsWith(dir + path.sep) && file !== dir) {\n dir = path.dirname(dir)\n }\n }\n return dir\n}\n\nfunction reportMessages(\n cwd: string,\n logger: CheckTsdocLogger,\n warnings: ExtractorMessage[],\n errors: ExtractorMessage[],\n): void {\n if (warnings.length) {\n logger.log()\n }\n\n for (const msg of warnings) {\n if (msg.messageId === 'TS6307') {\n // Ignore this warning:\n // > TS6307: <filename> is not in project file list.\n // > Projects must list all files or use an 'include' pattern.\n continue\n }\n const sourceFilePath = msg.sourceFilePath && path.relative(cwd, msg.sourceFilePath)\n logger.warn(\n `${sourceFilePath || '?'}:${msg.sourceFileLine}:${msg.sourceFileColumn} - warning ${msg.messageId}\\n${msg.text}\\n`,\n )\n }\n\n if (!warnings.length && errors.length) {\n logger.log()\n }\n\n for (const msg of errors) {\n const sourceFilePath = msg.sourceFilePath && path.relative(cwd, msg.sourceFilePath)\n logger.error(\n `${sourceFilePath || '?'}:${msg.sourceFileLine}:${msg.sourceFileColumn} - error ${msg.messageId}\\n${msg.text}\\n`,\n )\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"tsdoc.mjs","names":["\"default\""],"sources":["../src/tsdoc/createApiExtractorConfig.ts","../src/tsdoc/createTSDocConfig.ts","../src/tsdoc/getExtractMessagesConfig.ts","../src/tsdoc/synthesizedNamespaces.ts","../src/tsdoc/checkTsdoc.ts"],"sourcesContent":["import path from 'node:path'\nimport type {IConfigFile, IExtractorMessagesConfig} from '@microsoft/api-extractor'\n\n/** @internal */\nexport function createApiExtractorConfig(options: {\n bundledPackages?: string[]\n distPath: string\n exportPath: string\n filePath: string\n messages: IExtractorMessagesConfig\n projectFolder: string\n mainEntryPointFilePath: string\n /**\n * Only `compilerOptions.paths` is read: when present, API Extractor gets an override that\n * clears `paths` so self-referencing package imports resolve through `node_modules` instead.\n */\n tsconfig: {options: {paths?: unknown}}\n tsconfigPath: string\n}): IConfigFile {\n const {\n bundledPackages,\n distPath,\n exportPath,\n filePath,\n messages,\n projectFolder,\n mainEntryPointFilePath,\n tsconfig,\n tsconfigPath,\n } = options\n\n return {\n apiReport: {\n enabled: false,\n reportFileName: '<unscopedPackageName>.api.md',\n },\n bundledPackages,\n\n // If `paths` are used for self-referencing imports (e.g. the module is named `sanity`, and the `sanity/structure` export is also importing from `sanity/router`),\n compiler: tsconfig.options.paths\n ? {\n overrideTsconfig: {\n extends: tsconfigPath,\n compilerOptions: {\n // An empty object replaces whatever is in the original tsconfig file\n paths: {},\n },\n },\n }\n : {tsconfigFilePath: tsconfigPath},\n\n docModel: {\n enabled: false,\n apiJsonFilePath: path.resolve(distPath, `${exportPath}.api.json`),\n },\n dtsRollup: {\n // Types come from tsdown; this check only runs API Extractor's TSDoc/release-tag rules\n enabled: false,\n untrimmedFilePath: path.resolve(distPath, filePath),\n },\n tsdocMetadata: {\n enabled: false,\n },\n messages,\n mainEntryPointFilePath,\n projectFolder,\n }\n}\n","import {readFile} from 'node:fs/promises'\nimport {createRequire} from 'node:module'\nimport {TSDocConfigFile} from '@microsoft/tsdoc-config'\nimport {parse} from 'jsonc-parser'\nimport type {PackageTsdocCustomTag} from './types.ts'\n\nconst require = createRequire(import.meta.url)\n\n/** @internal */\nexport async function createTSDocConfig(opts: {\n customTags: PackageTsdocCustomTag[]\n}): Promise<TSDocConfigFile | undefined> {\n const {customTags} = opts\n\n if (customTags.length === 0) {\n return undefined\n }\n\n const tsDocBaseBuf = await readFile(\n require.resolve('@microsoft/api-extractor/extends/tsdoc-base.json'),\n )\n\n // Include the definitions that are required for API Extractor\n // extends: ['@microsoft/api-extractor/extends/tsdoc-base.json'],\n const tsDocBaseConfig = parse(tsDocBaseBuf.toString())\n\n // Define custom tags and specify how they should be parsed\n const tagDefinitions = (tsDocBaseConfig.tagDefinitions || []).concat(\n customTags.map((t) => ({\n tagName: `@${t.name}`,\n syntaxKind: t.syntaxKind,\n allowMultiple: t.allowMultiple,\n })),\n )\n\n // Indicate that custom tags are supported by your tooling.\n // (Without this, warnings may be reported saying that a tag is unsupported.)\n const supportForTags = {...tsDocBaseConfig.supportForTags}\n\n for (const customTag of customTags) {\n supportForTags[`@${customTag.name}`] = true\n }\n\n return TSDocConfigFile.loadFromObject({\n ...tsDocBaseConfig,\n noStandardTags: false,\n tagDefinitions,\n supportForTags,\n })\n}\n","import {ExtractorLogLevel, type IExtractorMessagesConfig} from '@microsoft/api-extractor'\nimport type {PackageTsdocOptions, PackageTsdocRuleLevel} from './types.ts'\n\nconst LOG_LEVELS: Record<PackageTsdocRuleLevel, ExtractorLogLevel> = {\n error: ExtractorLogLevel.Error,\n info: ExtractorLogLevel.Info,\n off: ExtractorLogLevel.None,\n warn: ExtractorLogLevel.Warning,\n}\n\n/** @internal */\nexport function getExtractMessagesConfig(options: {\n rules: PackageTsdocOptions['rules']\n disabled?: boolean\n}): IExtractorMessagesConfig {\n const {rules, disabled = false} = options\n\n function ruleToLogLevel(\n key: keyof NonNullable<PackageTsdocOptions['rules']>,\n defaultLevel?: ExtractorLogLevel,\n ) {\n const r = rules?.[key]\n\n return r ? LOG_LEVELS[r] : defaultLevel || ExtractorLogLevel.Warning\n }\n\n return {\n compilerMessageReporting: {\n default: {\n logLevel: disabled ? ExtractorLogLevel.None : ExtractorLogLevel.Warning,\n },\n },\n\n extractorMessageReporting: disabled\n ? {\n default: {\n logLevel: ExtractorLogLevel.None,\n addToApiReportFile: false,\n },\n }\n : {\n 'default': {\n logLevel: ExtractorLogLevel.Warning,\n addToApiReportFile: false,\n },\n\n 'ae-forgotten-export': {\n /**\n * This is hardcoded to `none` as it's no longer needed since TypeScript 5.5 https://github.com/microsoft/TypeScript/issues/42873\n * It's hardcoded to `none` since supported by API Extractor when using `module: 'Preserve'` doesn't support it well since `@microsoft/api-extractor` v7.49.0, which upgraded from TS 5.4 to 5.7 internally\n */\n logLevel: ExtractorLogLevel.None,\n addToApiReportFile: false,\n },\n\n 'ae-incompatible-release-tags': {\n logLevel: ruleToLogLevel('ae-incompatible-release-tags', ExtractorLogLevel.Error),\n addToApiReportFile: false,\n },\n\n 'ae-internal-missing-underscore': {\n logLevel: ruleToLogLevel('ae-internal-missing-underscore'),\n addToApiReportFile: false,\n },\n\n 'ae-missing-release-tag': {\n logLevel: ruleToLogLevel('ae-missing-release-tag', ExtractorLogLevel.Error),\n addToApiReportFile: false,\n },\n\n 'ae-wrong-input-file-type': {\n logLevel: ExtractorLogLevel.None,\n addToApiReportFile: false,\n },\n },\n\n tsdocMessageReporting: disabled\n ? {\n default: {\n logLevel: ExtractorLogLevel.None,\n addToApiReportFile: false,\n },\n }\n : {\n 'default': {\n logLevel: ExtractorLogLevel.Warning,\n addToApiReportFile: false,\n },\n\n 'tsdoc-link-tag-unescaped-text': {\n logLevel: ruleToLogLevel('tsdoc-link-tag-unescaped-text', ExtractorLogLevel.Warning),\n addToApiReportFile: false,\n },\n\n 'tsdoc-undefined-tag': {\n logLevel: ruleToLogLevel('tsdoc-undefined-tag', ExtractorLogLevel.Error),\n addToApiReportFile: false,\n },\n\n 'tsdoc-unsupported-tag': {\n logLevel: ruleToLogLevel('tsdoc-unsupported-tag', ExtractorLogLevel.None),\n addToApiReportFile: false,\n },\n },\n }\n}\n","import {existsSync, readFileSync} from 'node:fs'\nimport path from 'node:path'\n// The JS compiler API is loaded from the official `@typescript/typescript6` compat package\n// instead of the `typescript` peer dependency, as TypeScript 7 (the Go-native compiler) no longer\n// ships it\nimport ts from '@typescript/typescript6'\n\n/**\n * The exports-object identifiers of rolldown's namespace interop: `<module>_exports` (the\n * declaration bundling pass names them after the virtual declaration module, e.g. `inner.d.ts`\n * → `inner_d_exports`), with rolldown's `$<n>` suffix when deconflicting renames one.\n */\nconst RE_WRAPPER_NAME = /_exports(\\$\\d+)?$/\n\n/** Matches the relative specifiers of emitted sibling chunks (`./chunk-<hash>.js`). */\nconst RE_RELATIVE_SPECIFIER = /^\\.\\.?\\//\n\n/**\n * Finds the local names of the `declare namespace <name>_exports {…}` wrappers that the\n * declaration bundling pass (tsdown / rolldown-plugin-dts) synthesizes for namespace re-exports\n * like `export * as ns from './module'` (or `import * as ns` + `export {ns}`).\n *\n * Bundling loses the doc comment of the re-export statement, so the wrapper cannot carry a\n * release tag — there is no way to tag it from userland, and API Extractor would flag it with\n * `ae-missing-release-tag` (https://github.com/sanity-io/pkg-utils/issues/3281). Skipping it\n * matches how API Extractor treats the equivalent namespace of its own rollups (it never\n * checks those). The members re-exported through the wrapper keep their own doc comments in\n * the output; API Extractor does not flag them individually either way (only directly exported\n * declarations are consumable entities of the missing-release-tag check).\n *\n * A name only qualifies when all of these hold, so user-authored symbols that merely resemble\n * the interop naming stay checked:\n *\n * - it matches rolldown's `<module>_exports` naming (with an optional `$<n>` deconflict suffix)\n * - it is declared as a namespace — in the entry itself, or in a sibling chunk the entry\n * imports (a wrapper shared by several entries lives in the chunk that owns the module's\n * declarations)\n * - that namespace has the synthesized body shape: nothing but `export { … };` specifier lists\n * pointing at sibling declarations of the same file. A user-authored namespace declares its\n * own members (`declare namespace config_exports { const userValue: string; }`), and those\n * members are what the author tags — so it stays checked even when the bundler's\n * deconflicting hands it a wrapper-shaped name\n * - the entry does not export the name unaliased: a synthesized wrapper is always re-exported\n * under the alias of the original namespace re-export (`export { inner_d_exports as inner }`),\n * while an unaliased export (`export { foo_exports }`, `export declare namespace foo_exports`)\n * is a name the author chose — and can tag\n * @internal\n */\nexport function collectSynthesizedNamespaceWrappers(entryDtsFile: string): Set<string> {\n const entry = parseDts(entryDtsFile)\n if (!entry) return new Set()\n\n const unaliasedExports = new Set<string>()\n const wrapperShapedNames = new Set<string>()\n const chunkFiles = new Set<string>()\n\n for (const statement of entry.statements) {\n collectWrapperShapedNamespaceName(statement, wrapperShapedNames)\n\n if (ts.isExportDeclaration(statement)) {\n const {exportClause} = statement\n if (exportClause && ts.isNamedExports(exportClause)) {\n for (const element of exportClause.elements) {\n if (!element.propertyName || element.propertyName.text === element.name.text) {\n unaliasedExports.add(element.name.text)\n }\n }\n } else if (exportClause && ts.isNamespaceExport(exportClause)) {\n unaliasedExports.add(exportClause.name.text)\n }\n collectChunkFile(entryDtsFile, statement.moduleSpecifier, chunkFiles)\n } else if (ts.isImportDeclaration(statement)) {\n collectChunkFile(entryDtsFile, statement.moduleSpecifier, chunkFiles)\n } else {\n collectExportedDeclarationNames(statement, unaliasedExports)\n }\n }\n\n for (const chunkFile of chunkFiles) {\n const chunk = parseDts(chunkFile)\n if (!chunk) continue\n for (const statement of chunk.statements) {\n collectWrapperShapedNamespaceName(statement, wrapperShapedNames)\n }\n }\n\n const wrappers = new Set<string>()\n for (const name of wrapperShapedNames) {\n if (RE_WRAPPER_NAME.test(name) && !unaliasedExports.has(name)) wrappers.add(name)\n }\n return wrappers\n}\n\nfunction parseDts(filePath: string): ts.SourceFile | undefined {\n if (!existsSync(filePath)) return undefined\n return ts.createSourceFile(\n filePath,\n readFileSync(filePath, 'utf8'),\n ts.ScriptTarget.Latest,\n false,\n )\n}\n\n/**\n * Collects the name of a top-level `declare namespace <Identifier> {…}` statement whose body has\n * the shape the declaration bundling pass synthesizes: only `export { … };` specifier lists\n * naming sibling declarations of the same file, never members of its own. Every namespace\n * re-export the bundler rewrites comes out that way, whatever the re-exported module holds\n * (values, types, a default export, further namespace re-exports).\n */\nfunction collectWrapperShapedNamespaceName(statement: ts.Statement, names: Set<string>): void {\n if (\n !ts.isModuleDeclaration(statement) ||\n !ts.isIdentifier(statement.name) ||\n (statement.flags & ts.NodeFlags.Namespace) === 0\n ) {\n return\n }\n\n const {body} = statement\n if (!body || !ts.isModuleBlock(body)) return\n\n const onlyReExportsSiblings = body.statements.every(\n (member) =>\n ts.isExportDeclaration(member) &&\n !member.moduleSpecifier &&\n member.exportClause !== undefined &&\n ts.isNamedExports(member.exportClause),\n )\n if (!onlyReExportsSiblings) return\n\n names.add(statement.name.text)\n}\n\n/**\n * Collects the names a declaration with an `export` modifier exports directly, e.g.\n * `export declare namespace foo_exports {…}` — those names are user-chosen (the author can\n * tag them), unlike the alias-only re-export of a synthesized wrapper.\n */\nfunction collectExportedDeclarationNames(statement: ts.Statement, names: Set<string>): void {\n const modifiers = ts.canHaveModifiers(statement) ? ts.getModifiers(statement) : undefined\n if (!modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword)) return\n\n if (ts.isVariableStatement(statement)) {\n for (const declaration of statement.declarationList.declarations) {\n if (ts.isIdentifier(declaration.name)) names.add(declaration.name.text)\n }\n } else if (\n (ts.isFunctionDeclaration(statement) ||\n ts.isClassDeclaration(statement) ||\n ts.isInterfaceDeclaration(statement) ||\n ts.isTypeAliasDeclaration(statement) ||\n ts.isEnumDeclaration(statement)) &&\n statement.name\n ) {\n names.add(statement.name.text)\n } else if (ts.isModuleDeclaration(statement) && ts.isIdentifier(statement.name)) {\n names.add(statement.name.text)\n }\n}\n\n/**\n * Resolves the sibling chunk file a relative import/export specifier points at, mapping the\n * runtime extension to the declaration extension the chunk is emitted with on disk\n * (`./chunk.js` → `./chunk.d.ts`, like the declaration output of the bundling pass itself).\n */\nfunction collectChunkFile(\n entryDtsFile: string,\n moduleSpecifier: ts.Expression | undefined,\n files: Set<string>,\n): void {\n if (!moduleSpecifier || !ts.isStringLiteral(moduleSpecifier)) return\n const specifier = moduleSpecifier.text\n if (!RE_RELATIVE_SPECIFIER.test(specifier)) return\n const dtsFile = specifierToDtsFile(specifier)\n if (!dtsFile) return\n files.add(path.resolve(path.dirname(entryDtsFile), dtsFile))\n}\n\n/** `./chunk.js` → `./chunk.d.ts` (`.mjs` → `.d.mts`, `.cjs` → `.d.cts`). */\nfunction specifierToDtsFile(specifier: string): string | undefined {\n if (/\\.d\\.[mc]?ts$/.test(specifier)) return specifier\n if (specifier.endsWith('.mjs')) return `${specifier.slice(0, -4)}.d.mts`\n if (specifier.endsWith('.cjs')) return `${specifier.slice(0, -4)}.d.cts`\n if (specifier.endsWith('.js')) return `${specifier.slice(0, -3)}.d.ts`\n return undefined\n}\n","import {existsSync} from 'node:fs'\nimport path from 'node:path'\nimport {\n Extractor,\n ExtractorConfig,\n ExtractorLogLevel,\n type ExtractorMessage,\n} from '@microsoft/api-extractor'\n// The JS compiler API is loaded from the official `@typescript/typescript6` compat package\n// instead of the `typescript` peer dependency, as TypeScript 7 (the Go-native compiler) no longer\n// ships it\nimport ts from '@typescript/typescript6'\nimport {createApiExtractorConfig} from './createApiExtractorConfig.ts'\nimport {createTSDocConfig} from './createTSDocConfig.ts'\nimport {getExtractMessagesConfig} from './getExtractMessagesConfig.ts'\nimport {collectSynthesizedNamespaceWrappers} from './synthesizedNamespaces.ts'\nimport type {PackageTsdocOptions} from './types.ts'\n\n/** @public */\nexport interface CheckTsdocLogger {\n log: (...args: unknown[]) => void\n warn: (...args: unknown[]) => void\n error: (...args: unknown[]) => void\n}\n\n/** @public */\nexport interface CheckTsdocOptions extends PackageTsdocOptions {\n /** Package root (directory containing `package.json`). */\n cwd: string\n /**\n * Absolute paths to the entry `.d.ts` / `.d.mts` / `.d.cts` files to check.\n * JS-only entries with no declarations are skipped automatically when listed.\n */\n entryDtsFiles: string[]\n /**\n * Path to the tsconfig used for the build, relative to `cwd` or absolute.\n * @defaultValue `'tsconfig.json'`\n */\n tsconfig?: string\n /**\n * Directory of distributed files (used for API Extractor's path mapping). Defaults to the\n * common parent of `entryDtsFiles`, or `dist` under `cwd` when the list is empty.\n */\n outDir?: string\n /**\n * When provided, messages are printed through this logger. Errors throw after reporting so\n * callers (and tsdown's `build:done` hook) fail the build.\n */\n logger?: CheckTsdocLogger\n}\n\n/** @public */\nexport interface CheckTsdocResult {\n messages: ExtractorMessage[]\n errorCount: number\n warningCount: number\n}\n\n/**\n * Run `@microsoft/api-extractor` against the given entry declaration files to check that TSDoc\n * tags are valid and release tags are correct. Import from `@sanity/tsdown-config/tsdoc`.\n * @public\n */\nexport async function checkTsdoc(options: CheckTsdocOptions): Promise<CheckTsdocResult> {\n const {\n cwd,\n entryDtsFiles,\n bundledPackages,\n customTags = [],\n rules = {},\n logger,\n outDir: outDirOption,\n } = options\n\n const tsconfigPath = path.resolve(cwd, options.tsconfig || 'tsconfig.json')\n const tsconfig = loadTSConfig({cwd, tsconfigPath})\n // api-extractor needs a `compilerOptions.outDir` for its path mapping; tsdown does not, so\n // fall back to the configured outDir / dist folder when the tsconfig leaves it unset\n const outDir =\n tsconfig?.options.outDir ??\n (outDirOption ? path.resolve(cwd, outDirOption) : undefined) ??\n commonParentDir(entryDtsFiles) ??\n path.resolve(cwd, 'dist')\n\n const tsdocConfigFile = await createTSDocConfig({customTags})\n const messagesConfig = getExtractMessagesConfig({rules})\n const allMessages: ExtractorMessage[] = []\n\n for (const exportPath of entryDtsFiles) {\n if (!existsSync(exportPath)) continue\n\n // The declaration bundling pass synthesizes `declare namespace <name>_exports` wrappers\n // for namespace re-exports and loses the doc comment of the re-export statement, so the\n // wrappers can never carry a release tag — `ae-missing-release-tag` skips them.\n // https://github.com/sanity-io/pkg-utils/issues/3281\n const synthesizedWrappers = collectSynthesizedNamespaceWrappers(exportPath)\n const relativeDtsPath = path.relative(outDir, exportPath)\n const extractorConfig = ExtractorConfig.prepare({\n configObject: createApiExtractorConfig({\n bundledPackages,\n distPath: outDir,\n exportPath,\n filePath: relativeDtsPath,\n messages: messagesConfig,\n projectFolder: cwd,\n mainEntryPointFilePath: exportPath,\n tsconfig: tsconfig ?? {options: {}},\n tsconfigPath,\n }),\n configObjectFullPath: undefined,\n tsdocConfigFile,\n packageJsonFullPath: path.resolve(cwd, 'package.json'),\n })\n\n Extractor.invoke(extractorConfig, {\n localBuild: true,\n showVerboseMessages: true,\n messageCallback(message: ExtractorMessage) {\n message.handled = true\n if (isSynthesizedNamespaceWrapperMessage(message, synthesizedWrappers)) return\n allMessages.push(message)\n },\n })\n }\n\n const warnings = allMessages.filter((msg) => msg.logLevel === ExtractorLogLevel.Warning)\n const errors = allMessages.filter((msg) => msg.logLevel === ExtractorLogLevel.Error)\n\n if (logger) {\n reportMessages(cwd, logger, warnings, errors)\n }\n\n if (errors.length) {\n throw new Error(\n `TSDoc/release-tag check failed with ${errors.length} error${errors.length === 1 ? '' : 's'}`,\n )\n }\n\n return {\n messages: allMessages,\n errorCount: errors.length,\n warningCount: warnings.length,\n }\n}\n\nfunction loadTSConfig(options: {\n cwd: string\n tsconfigPath: string\n}): ReturnType<typeof ts.parseJsonConfigFileContent> | undefined {\n const {cwd, tsconfigPath} = options\n // Resolve a relative name from `cwd` (e.g. `tsconfig.dist.json`); an absolute path is kept.\n let configPath: string | undefined\n if (path.isAbsolute(tsconfigPath)) {\n configPath = tsconfigPath\n } else {\n // oxlint-disable-next-line unbound-method\n configPath = ts.findConfigFile(cwd, ts.sys.fileExists, tsconfigPath)\n }\n if (!configPath || !existsSync(configPath)) return undefined\n // oxlint-disable-next-line unbound-method\n const configFile = ts.readConfigFile(configPath, ts.sys.readFile)\n // Relative `extends`/`include`/`paths` are resolved from the tsconfig's directory, not `cwd`\n return ts.parseJsonConfigFileContent(configFile.config, ts.sys, path.dirname(configPath))\n}\n\n/** The quoted symbol name leading api-extractor's `ae-missing-release-tag` message text. */\nconst RE_MISSING_RELEASE_TAG_SYMBOL = /^\"([^\"]+)\" is part of the package's API/\n\n/**\n * Whether a message is an `ae-missing-release-tag` complaint about a namespace wrapper the\n * declaration bundling pass synthesized (which userland can never tag). The flagged symbol is\n * only identifiable through the message text: api-extractor quotes the local name of the\n * declaration, and attaches no structured properties (its source location maps through\n * `.d.ts.map` files, often landing on an unrelated source position).\n */\nfunction isSynthesizedNamespaceWrapperMessage(\n message: ExtractorMessage,\n synthesizedWrappers: Set<string>,\n): boolean {\n if (synthesizedWrappers.size === 0 || message.messageId !== 'ae-missing-release-tag') {\n return false\n }\n const symbolName = RE_MISSING_RELEASE_TAG_SYMBOL.exec(message.text)?.[1]\n return symbolName !== undefined && synthesizedWrappers.has(symbolName)\n}\n\nfunction commonParentDir(files: string[]): string | undefined {\n if (files.length === 0) return undefined\n let dir = path.dirname(files[0]!)\n for (const file of files.slice(1)) {\n while (dir !== path.dirname(dir) && !file.startsWith(dir + path.sep) && file !== dir) {\n dir = path.dirname(dir)\n }\n }\n return dir\n}\n\nfunction reportMessages(\n cwd: string,\n logger: CheckTsdocLogger,\n warnings: ExtractorMessage[],\n errors: ExtractorMessage[],\n): void {\n if (warnings.length) {\n logger.log()\n }\n\n for (const msg of warnings) {\n if (msg.messageId === 'TS6307') {\n // Ignore this warning:\n // > TS6307: <filename> is not in project file list.\n // > Projects must list all files or use an 'include' pattern.\n continue\n }\n const sourceFilePath = msg.sourceFilePath && path.relative(cwd, msg.sourceFilePath)\n logger.warn(\n `${sourceFilePath || '?'}:${msg.sourceFileLine}:${msg.sourceFileColumn} - warning ${msg.messageId}\\n${msg.text}\\n`,\n )\n }\n\n if (!warnings.length && errors.length) {\n logger.log()\n }\n\n for (const msg of errors) {\n const sourceFilePath = msg.sourceFilePath && path.relative(cwd, msg.sourceFilePath)\n logger.error(\n `${sourceFilePath || '?'}:${msg.sourceFileLine}:${msg.sourceFileColumn} - error ${msg.messageId}\\n${msg.text}\\n`,\n )\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sanity/tsdown-config",
|
|
3
|
-
"version": "0.28.
|
|
3
|
+
"version": "0.28.6",
|
|
4
4
|
"description": "Shared configuration for tsdown",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"sanity-io",
|
|
@@ -36,28 +36,28 @@
|
|
|
36
36
|
"dist"
|
|
37
37
|
],
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@microsoft/api-extractor": "^7.59.
|
|
39
|
+
"@microsoft/api-extractor": "^7.59.4",
|
|
40
40
|
"@microsoft/tsdoc-config": "^0.18.3",
|
|
41
41
|
"@sanity/browserslist-config": "^1.0.5",
|
|
42
|
-
"@sanity/vanilla-extract-tsdown-plugin": "^0.4.
|
|
42
|
+
"@sanity/vanilla-extract-tsdown-plugin": "^0.4.6",
|
|
43
43
|
"@typescript/typescript6": "^6.0.2",
|
|
44
|
-
"@vitejs/plugin-react": "^6.1.
|
|
44
|
+
"@vitejs/plugin-react": "^6.1.2",
|
|
45
45
|
"browserslist": "^4.29.3",
|
|
46
46
|
"jsonc-parser": "^3.3.1",
|
|
47
47
|
"lightningcss": "^1.33.0",
|
|
48
|
-
"package-manager-detector": "^1.
|
|
48
|
+
"package-manager-detector": "^1.9.0",
|
|
49
49
|
"publint": "^0.3.25",
|
|
50
|
-
"rolldown": "~1.2.
|
|
50
|
+
"rolldown": "~1.2.13"
|
|
51
51
|
},
|
|
52
52
|
"devDependencies": {
|
|
53
53
|
"@babel/core": "^7.29.7",
|
|
54
54
|
"@rolldown/plugin-babel": "^0.2.4",
|
|
55
|
-
"@sanity/pkg-utils": "^13.0.
|
|
55
|
+
"@sanity/pkg-utils": "^13.0.7",
|
|
56
56
|
"@sanity/tsconfig": "^2.2.1",
|
|
57
57
|
"@tsdown/css": "^0.23.0",
|
|
58
58
|
"@types/babel__core": "^7.20.5",
|
|
59
59
|
"babel-plugin-react-compiler": "^1.0.0",
|
|
60
|
-
"oxc-transform-react": "^0.
|
|
60
|
+
"oxc-transform-react": "^0.153.0",
|
|
61
61
|
"tinyexec": "^1.3.1",
|
|
62
62
|
"tsdown": "^0.23.0",
|
|
63
63
|
"typescript": "7.0.2",
|