diff --git a/apps/api-extractor/src/schemas/api-extractor.schema.json b/apps/api-extractor/src/schemas/api-extractor.schema.json index 20773498c59..8bd8fdaef13 100644 --- a/apps/api-extractor/src/schemas/api-extractor.schema.json +++ b/apps/api-extractor/src/schemas/api-extractor.schema.json @@ -14,7 +14,7 @@ }, "projectFolder": { - "description": "Determines the \"\" token that can be used with other config file settings. The project folder typically contains the tsconfig.json and package.json config files, but the path is user-defined. The path is resolved relative to the folder of the config file that contains the setting. The default value for \"projectFolder\" is the token \"\", which means the folder is determined using the following heuristics:\n\nIf the config/rig.json system is used (as defined by @rushstack/rig-package), then the \"\" value will be the package folder that referenced the rig.\n\nOtherwise, the \"\" value is determined by traversing parent folders, starting from the folder containing api-extractor.json, and stopping at the first folder that contains a tsconfig.json file. If a tsconfig.json file cannot be found in this way, then an error will be reported.", + "description": "Determines the \"\" token that can be used with other config file settings. The project folder typically contains the tsconfig.json and package.json config files, but the path is user-defined. The path is resolved relative to the folder of the config file that contains the setting. The default value for \"projectFolder\" is the token \"\", which means the folder is determined using the following heuristics:\n\nIf the config/rig.json system is used (as defined by `@rushstack/rig-package`), then the \"\" value will be the package folder that referenced the rig.\n\nOtherwise, the \"\" value is determined by traversing parent folders, starting from the folder containing api-extractor.json, and stopping at the first folder that contains a tsconfig.json file. If a tsconfig.json file cannot be found in this way, then an error will be reported.", "type": "string" }, @@ -85,7 +85,7 @@ }, "reportVariants": { - "description": "To support different approval requirements for different API levels, multiple \"variants\" of the API report can be generated. The \"reportVariants\" setting specifies a list of variants to be generated. If omitted, by default only the \"complete\" variant will be generated, which includes all @internal, @alpha, @beta, and @public items. Other possible variants are \"alpha\" (@alpha + @beta + @public), \"beta\" (@beta + @public), and \"public\" (@public only).", + "description": "To support different approval requirements for different API levels, multiple \"variants\" of the API report can be generated. The \"reportVariants\" setting specifies a list of variants to be generated. If omitted, by default only the \"complete\" variant will be generated, which includes all `@internal`, `@alpha`, `@beta`, and `@public` items. Other possible variants are \"alpha\" (`@alpha` + `@beta` + `@public`), \"beta\" (`@beta` + `@public`), and \"public\" (`@public` only).", "type": "array", "items": { "type": "string", @@ -109,7 +109,7 @@ }, "tagsToReport": { - "description": "Specifies a list of TSDoc tags that should be reported in the API report file for items whose documentation contains them. This can be used to include standard TSDoc tags or custom ones. Specified tag names must begin with \"@\". By default, the following tags are reported: [@sealed, @virtual, @override, @eventProperty, @deprecated]. Tags will appear in the order they are specified in this list. Note that an item's release tag will always reported; this behavior cannot be overridden.", + "description": "Specifies a list of TSDoc tags that should be reported in the API report file for items whose documentation contains them. This can be used to include standard TSDoc tags or custom ones. Specified tag names must begin with `@`. By default, the following tags are reported: [`@sealed`, `@virtual`, `@override`, `@eventProperty`, `@deprecated`]. Tags will appear in the order they are specified in this list. Note that an item's release tag will always reported; this behavior cannot be overridden.", "type": "object", "patternProperties": { "^@[^\\s]*$": { @@ -169,15 +169,15 @@ "type": "string" }, "alphaTrimmedFilePath": { - "description": "Specifies the output path for a .d.ts rollup file to be generated with trimming for an \"alpha\" release. This file will include only declarations that are marked as \"@public\", \"@beta\", or \"@alpha\". The path is resolved relative to the folder of the config file that contains the setting; to change this, prepend a folder token such as \"\".", + "description": "Specifies the output path for a .d.ts rollup file to be generated with trimming for an \"alpha\" release. This file will include only declarations that are marked as `@public`, `@beta`, or `@alpha`. The path is resolved relative to the folder of the config file that contains the setting; to change this, prepend a folder token such as \"\".", "type": "string" }, "betaTrimmedFilePath": { - "description": "Specifies the output path for a .d.ts rollup file to be generated with trimming for a \"beta\" release. This file will include only declarations that are marked as \"@public\" or \"@beta\". The path is resolved relative to the folder of the config file that contains the setting; to change this, prepend a folder token such as \"\".", + "description": "Specifies the output path for a .d.ts rollup file to be generated with trimming for a \"beta\" release. This file will include only declarations that are marked as `@public` or `@beta`. The path is resolved relative to the folder of the config file that contains the setting; to change this, prepend a folder token such as \"\".", "type": "string" }, "publicTrimmedFilePath": { - "description": "Specifies the output path for a .d.ts rollup file to be generated with trimming for a \"public\" release. This file will include only declarations that are marked as \"@public\". If the path is an empty string, then this file will not be written. The path is resolved relative to the folder of the config file that contains the setting; to change this, prepend a folder token such as \"\".", + "description": "Specifies the output path for a .d.ts rollup file to be generated with trimming for a \"public\" release. This file will include only declarations that are marked as `@public`. If the path is an empty string, then this file will not be written. The path is resolved relative to the folder of the config file that contains the setting; to change this, prepend a folder token such as \"\".", "type": "string" }, "omitTrimmingComments": { diff --git a/apps/heft/src/index.ts b/apps/heft/src/index.ts index 0c6006dfc8c..c45d9e5b9e5 100644 --- a/apps/heft/src/index.ts +++ b/apps/heft/src/index.ts @@ -46,9 +46,13 @@ export type { IHeftTaskRunIncrementalHookOptions } from './pluginFramework/HeftTaskSession'; -export type { ICopyOperation, IIncrementalCopyOperation } from './plugins/CopyFilesPlugin'; +export type { + ICopyOperation, + IIncrementalCopyOperation, + ICopyOperationBase +} from './plugins/CopyFilesPlugin'; -export type { IDeleteOperation } from './plugins/DeleteFilesPlugin'; +export type { IDeleteOperation, IDeleteOperationBase } from './plugins/DeleteFilesPlugin'; export type { IRunScript, IRunScriptOptions } from './plugins/RunScriptPlugin'; diff --git a/apps/heft/src/plugins/CopyFilesPlugin.ts b/apps/heft/src/plugins/CopyFilesPlugin.ts index 2c9d47347a1..a635782100f 100644 --- a/apps/heft/src/plugins/CopyFilesPlugin.ts +++ b/apps/heft/src/plugins/CopyFilesPlugin.ts @@ -24,6 +24,12 @@ import { tryReadBuildInfoAsync, writeBuildInfoAsync } from '../pluginFramework/IncrementalBuildInfo'; +import type { + CopyFilesHeftTaskEventOptions as ICopyFilesPluginOptions, + CopyOperationBase as ICopyOperationBase +} from '../schemas/copy-files-options.schema.json.d.ts'; + +export type { ICopyOperationBase }; /** * Used to specify a selection of files to copy from a specific source folder to one @@ -31,30 +37,7 @@ import { * * @public */ -export interface ICopyOperation extends IFileSelectionSpecifier { - /** - * Absolute paths to folders which files or folders should be copied to. - */ - destinationFolders: string[]; - - /** - * Copy only the file and discard the relative path from the source folder. - */ - flatten?: boolean; - - /** - * Hardlink files instead of copying. - * - * @remarks - * If the sourcePath is a folder, the contained directory structure will be re-created - * and all files will be individually hardlinked. This means that folders will be new - * filesystem entities and will have separate folder metadata, while the contained files - * will maintain normal hardlink behavior. This is done since folders do not have a - * cross-platform equivalent of a hardlink, and since file symlinks provide fundamentally - * different functionality in comparison to hardlinks. - */ - hardlink?: boolean; -} +export interface ICopyOperation extends IFileSelectionSpecifier, ICopyOperationBase {} /** * Used to specify a selection of files to copy from a specific source folder to one @@ -70,10 +53,6 @@ export interface IIncrementalCopyOperation extends ICopyOperation { onlyIfChanged?: boolean; } -interface ICopyFilesPluginOptions { - copyOperations: ICopyOperation[]; -} - interface ICopyDescriptor { sourcePath: string; destinationPath: string; diff --git a/apps/heft/src/plugins/DeleteFilesPlugin.ts b/apps/heft/src/plugins/DeleteFilesPlugin.ts index 73976dad8f4..bc200884d9d 100644 --- a/apps/heft/src/plugins/DeleteFilesPlugin.ts +++ b/apps/heft/src/plugins/DeleteFilesPlugin.ts @@ -15,17 +15,22 @@ import { import type { HeftConfiguration } from '../configuration/HeftConfiguration'; import type { IHeftTaskPlugin } from '../pluginFramework/IHeftPlugin'; import type { IHeftTaskSession, IHeftTaskFileOperations } from '../pluginFramework/HeftTaskSession'; +import type { + DeleteFilesHeftTaskEventOptions as IDeleteFilesPluginOptions, + DeleteOperationBase as IDeleteOperationBase +} from '../schemas/delete-files-options.schema.json.d.ts'; + +/** + * @internal + */ +export type { IDeleteOperationBase }; /** * Used to specify a selection of source files to delete from the specified source folder. * * @public */ -export interface IDeleteOperation extends IFileSelectionSpecifier {} - -interface IDeleteFilesPluginOptions { - deleteOperations: IDeleteOperation[]; -} +export interface IDeleteOperation extends IFileSelectionSpecifier, IDeleteOperationBase {} interface IGetPathsToDeleteResult { filesToDelete: Set; diff --git a/apps/heft/src/plugins/FileGlobSpecifier.ts b/apps/heft/src/plugins/FileGlobSpecifier.ts index 96d3223dd5a..da09c50e1a8 100644 --- a/apps/heft/src/plugins/FileGlobSpecifier.ts +++ b/apps/heft/src/plugins/FileGlobSpecifier.ts @@ -9,38 +9,9 @@ import glob, { type FileSystemAdapter, type Entry } from 'fast-glob'; import { Async } from '@rushstack/node-core-library'; import type { IWatchFileSystemAdapter, IWatchedFileState } from '../utilities/WatchFileSystemAdapter'; +import type { FileSelectionSpecifierBase as IFileSelectionSpecifier } from '../schemas/file-selection.schema.json.d.ts'; -/** - * Used to specify a selection of one or more files. - * - * @public - */ -export interface IFileSelectionSpecifier { - /** - * Absolute path to the target. The provided sourcePath can be to a file or a folder. If - * fileExtensions, excludeGlobs, or includeGlobs are specified, the sourcePath is assumed - * to be a folder. If it is not a folder, an error will be thrown. - */ - sourcePath?: string; - - /** - * File extensions that should be included from the source folder. Only supported when the sourcePath - * is a folder. - */ - fileExtensions?: string[]; - - /** - * Globs that should be explicitly excluded. This takes precedence over globs listed in "includeGlobs" and - * files that match the file extensions provided in "fileExtensions". Only supported when the sourcePath - * is a folder. - */ - excludeGlobs?: string[]; - - /** - * Globs that should be explicitly included. Only supported when the sourcePath is a folder. - */ - includeGlobs?: string[]; -} +export type { IFileSelectionSpecifier }; /** * A supported subset of options used when globbing files. diff --git a/apps/heft/src/plugins/RunScriptPlugin.ts b/apps/heft/src/plugins/RunScriptPlugin.ts index 6c74d9dfd56..1f8d3dfe2ee 100644 --- a/apps/heft/src/plugins/RunScriptPlugin.ts +++ b/apps/heft/src/plugins/RunScriptPlugin.ts @@ -6,11 +6,7 @@ import * as path from 'node:path'; import type { HeftConfiguration } from '../configuration/HeftConfiguration'; import type { IHeftTaskPlugin } from '../pluginFramework/IHeftPlugin'; import type { IHeftTaskSession, IHeftTaskRunHookOptions } from '../pluginFramework/HeftTaskSession'; - -interface IRunScriptPluginOptions { - scriptPath: string; - scriptOptions: Record; -} +import type { RunScriptHeftTaskEventOptions as IRunScriptPluginOptions } from '../schemas/run-script-options.schema.json.d.ts'; /** * Options provided to scripts that are run using the RunScriptPlugin. @@ -21,7 +17,7 @@ export interface IRunScriptOptions { heftTaskSession: IHeftTaskSession; heftConfiguration: HeftConfiguration; runOptions: IHeftTaskRunHookOptions; - scriptOptions: Record; + scriptOptions: Record | undefined; } /** diff --git a/apps/heft/src/plugins/SetEnvironmentVariablesPlugin.ts b/apps/heft/src/plugins/SetEnvironmentVariablesPlugin.ts index fb83903b83b..4a75e526521 100644 --- a/apps/heft/src/plugins/SetEnvironmentVariablesPlugin.ts +++ b/apps/heft/src/plugins/SetEnvironmentVariablesPlugin.ts @@ -4,12 +4,14 @@ import type { HeftConfiguration } from '../configuration/HeftConfiguration'; import type { IHeftTaskSession } from '../pluginFramework/HeftTaskSession'; import type { IHeftTaskPlugin } from '../pluginFramework/IHeftPlugin'; +import type { SetEnvironmentVariablesHeftTaskEventOptions as ISetEnvironmentVariablesPluginOptions } from '../schemas/set-environment-variables-plugin.schema.json.d.ts'; export const PLUGIN_NAME: string = 'set-environment-variables-plugin'; -export interface ISetEnvironmentVariablesPluginOptions { - environmentVariablesToSet: Record; -} +/** + * @public + */ +export type { ISetEnvironmentVariablesPluginOptions }; export default class SetEnvironmentVariablesPlugin implements IHeftTaskPlugin diff --git a/apps/heft/src/schemas/copy-files-options.schema.json b/apps/heft/src/schemas/copy-files-options.schema.json index f42d46af61c..e56ffc05517 100644 --- a/apps/heft/src/schemas/copy-files-options.schema.json +++ b/apps/heft/src/schemas/copy-files-options.schema.json @@ -1,7 +1,8 @@ { - "$schema": "http://json-schema.org/draft-04/schema#", + "$schema": "https://json-schema.org/draft/2019-09/schema", "title": "CopyFiles Heft Task Event Options", "description": "Defines configuration used by the \"copyFiles\" Heft task event.", + "x-tsdoc-release-tag": "@public", "type": "object", "additionalProperties": false, @@ -13,74 +14,68 @@ "description": "An array of copy operations to perform during the specified Heft event.", "items": { - "type": "object", - "additionalProperties": false, - "required": ["destinationFolders"], - "anyOf": [ - { "required": ["sourcePath"] }, - { "required": ["fileExtensions"] }, - { "required": ["includeGlobs"] }, - { "required": ["excludeGlobs"] } - ], - "properties": { - "sourcePath": { - "title": "Source Path", - "type": "string", - "description": "The target folder, relative to the project root. Settings such as \"includeGlobs\" and \"excludeGlobs\" will be resolved relative to this folder. If no globs or file extensions are specified, the folder will be copied. To copy a single file, set \"includeGlobs\" to an array containing the exact name of the file. If this parameter is not provided, defaults to the project root.", - "pattern": "[^\\\\]" - }, - - "destinationFolders": { - "title": "Destination Folders", - "type": "array", - "description": "One or more folders that files and folders will be copied into, relative to the project root.", - "items": { - "type": "string", - "pattern": "[^\\\\]" - } - }, + "$ref": "#/$defs/copyOperationBase" + } + } + }, - "fileExtensions": { - "title": "File Extensions", - "type": "array", - "description": "If specified, this option recursively scans all folders under \"sourcePath\" and includes any files that match the specified extensions. (If \"fileExtensions\" and \"includeGlobs\" are both specified, their selections are added together.)", - "items": { - "type": "string", - "pattern": "^\\.[A-z0-9-_.]*[A-z0-9-_]+$" - } - }, + "$defs": { + "copyOperationBase": { + "description": "Configures a copy operation for the \"copyFiles\" task event.", + "type": "object", + "additionalProperties": false, + "required": ["destinationFolders"], + "properties": { + "sourcePath": { + "type": "string", + "description": "The target folder, relative to the project root. Settings such as \"includeGlobs\" and \"excludeGlobs\" will be resolved relative to this folder. If no globs or file extensions are specified, the folder will be copied. To copy a single file, set \"includeGlobs\" to an array containing the exact name of the file. If this parameter is not provided, defaults to the project root.", + "pattern": "[^\\\\]" + }, - "excludeGlobs": { - "title": "Exclude Globs", - "type": "array", - "description": "A list of glob patterns that exclude files or folders from being copied. The paths are resolved relative to \"sourcePath\". These exclusions eliminate items that were selected by the \"includeGlobs\" or \"fileExtensions\" setting.", - "items": { - "type": "string", - "pattern": "[^\\\\]" - } - }, + "fileExtensions": { + "type": "array", + "description": "If specified, this option recursively scans all folders under \"sourcePath\" and includes any files that match the specified extensions. (If \"fileExtensions\" and \"includeGlobs\" are both specified, their selections are added together.)", + "items": { + "type": "string", + "pattern": "^\\.[A-z0-9-_.]*[A-z0-9-_]+$" + } + }, - "includeGlobs": { - "title": "Include Globs", - "type": "array", - "description": "A list of glob patterns that select files to be copied. The paths are resolved relative to \"sourcePath\".", - "items": { - "type": "string", - "pattern": "[^\\\\]" - } - }, + "excludeGlobs": { + "type": "array", + "description": "A list of glob patterns that exclude files or folders from being copied. The paths are resolved relative to \"sourcePath\". These exclusions eliminate items that were selected by the \"includeGlobs\" or \"fileExtensions\" setting.", + "items": { + "type": "string", + "pattern": "[^\\\\]" + } + }, - "flatten": { - "title": "Flatten", - "type": "boolean", - "description": "Normally, copying will preserve the path relative to \"sourcePath\" under the destination folder (e.g. if \"sourcePath\" is \"src/test\" and \"destinationFolders\" is [\"out\"], \"src/test/a/b/c.txt\" will be copied to \"out/a/b/c.txt\"). Specify \"flatten=true\" to discard path information and keep only the filename (e.g. \"out/c.txt\". If two files have the same name an error will be reported. The default value is false." - }, + "includeGlobs": { + "type": "array", + "description": "A list of glob patterns that select files to be copied. The paths are resolved relative to \"sourcePath\".", + "items": { + "type": "string", + "pattern": "[^\\\\]" + } + }, - "hardlink": { - "title": "Hardlink", - "type": "boolean", - "description": "If true, filesystem hard links will be created instead of copying the file. Depending on the operating system, this may be faster. The default value is false. NOTE: This may cause unexpected behavior if a tool modifies the link. The contained directory structure will be re-created and all files will be individually hardlinked. This means that folders will be new filesystem entities and will have separate folder metadata, while the contained files will maintain normal hardlink behavior. This is done since folders do not have a cross-platform equivalent of a hardlink, and since file symlinks provide fundamentally different functionality in comparison to hardlinks." + "destinationFolders": { + "type": "array", + "description": "One or more folders that files and folders will be copied into, relative to the project root.", + "items": { + "type": "string", + "pattern": "[^\\\\]" } + }, + + "flatten": { + "type": "boolean", + "description": "Normally, copying will preserve the path relative to \"sourcePath\" under the destination folder (e.g. if \"sourcePath\" is \"src/test\" and \"destinationFolders\" is [\"out\"], \"src/test/a/b/c.txt\" will be copied to \"out/a/b/c.txt\"). Specify \"flatten=true\" to discard path information and keep only the filename (e.g. \"out/c.txt\"). If two files have the same name an error will be reported. The default value is false." + }, + + "hardlink": { + "type": "boolean", + "description": "If true, filesystem hard links will be created instead of copying the file. Depending on the operating system, this may be faster. The default value is false. NOTE: This may cause unexpected behavior if a tool modifies the link. The contained directory structure will be re-created and all files will be individually hardlinked. This means that folders will be new filesystem entities and will have separate folder metadata, while the contained files will maintain normal hardlink behavior. This is done since folders do not have a cross-platform equivalent of a hardlink, and since file symlinks provide fundamentally different functionality in comparison to hardlinks." } } } diff --git a/apps/heft/src/schemas/delete-files-options.schema.json b/apps/heft/src/schemas/delete-files-options.schema.json index 0e6c0a9ccae..d076e7ae8bc 100644 --- a/apps/heft/src/schemas/delete-files-options.schema.json +++ b/apps/heft/src/schemas/delete-files-options.schema.json @@ -1,7 +1,8 @@ { - "$schema": "http://json-schema.org/draft-04/schema#", + "$schema": "https://json-schema.org/draft/2019-09/schema", "title": "DeleteFiles Heft Task Event Options", "description": "Defines configuration used by the \"deleteFiles\" Heft task event.", + "x-tsdoc-release-tag": "@public", "type": "object", "additionalProperties": false, @@ -13,50 +14,47 @@ "description": "An array of delete operations to perform during the specified Heft event.", "items": { - "type": "object", - "additionalProperties": false, - "anyOf": [ - { "required": ["sourcePath"] }, - { "required": ["fileExtensions"] }, - { "required": ["includeGlobs"] }, - { "required": ["excludeGlobs"] } - ], - "properties": { - "sourcePath": { - "title": "Source Path", - "type": "string", - "description": "The base folder that files will be deleted from, relative to the project root. Settings such as \"includeGlobs\" and \"excludeGlobs\" will be resolved relative to this folder. If no globs or file extensions are specified, the folder will be deleted.", - "pattern": "[^\\\\]" - }, + "$ref": "#/$defs/deleteOperationBase" + } + } + }, + + "$defs": { + "deleteOperationBase": { + "description": "Configures a delete operation for the \"deleteFiles\" task event.", + "type": "object", + "additionalProperties": false, + "properties": { + "sourcePath": { + "type": "string", + "description": "The base folder that files will be deleted from, relative to the project root. Settings such as \"includeGlobs\" and \"excludeGlobs\" will be resolved relative to this folder. If no globs or file extensions are specified, the folder will be deleted.", + "pattern": "[^\\\\]" + }, - "fileExtensions": { - "title": "File Extensions", - "type": "array", - "description": "If specified, this option recursively scans all folders under \"sourcePath\" and includes any files that match the specified extensions. (If \"fileExtensions\" and \"includeGlobs\" are both specified, their selections are added together.)", - "items": { - "type": "string", - "pattern": "^\\.[A-z0-9-_.]*[A-z0-9-_]+$" - } - }, + "fileExtensions": { + "type": "array", + "description": "If specified, this option recursively scans all folders under \"sourcePath\" and includes any files that match the specified extensions. (If \"fileExtensions\" and \"includeGlobs\" are both specified, their selections are added together.)", + "items": { + "type": "string", + "pattern": "^\\.[A-z0-9-_.]*[A-z0-9-_]+$" + } + }, - "excludeGlobs": { - "title": "Exclude Globs", - "type": "array", - "description": "A list of glob patterns that exclude files or folders from being deleted. The paths are resolved relative to \"sourcePath\". These exclusions eliminate items that were selected by the \"includeGlobs\" or \"fileExtensions\" setting.", - "items": { - "type": "string", - "pattern": "[^\\\\]" - } - }, + "excludeGlobs": { + "type": "array", + "description": "A list of glob patterns that exclude files or folders from being deleted. The paths are resolved relative to \"sourcePath\". These exclusions eliminate items that were selected by the \"includeGlobs\" or \"fileExtensions\" setting.", + "items": { + "type": "string", + "pattern": "[^\\\\]" + } + }, - "includeGlobs": { - "title": "Include Globs", - "type": "array", - "description": "A list of glob patterns that select files to be deleted. The paths are resolved relative to \"sourcePath\".", - "items": { - "type": "string", - "pattern": "[^\\\\]" - } + "includeGlobs": { + "type": "array", + "description": "A list of glob patterns that select files to be deleted. The paths are resolved relative to \"sourcePath\".", + "items": { + "type": "string", + "pattern": "[^\\\\]" } } } diff --git a/apps/heft/src/schemas/file-selection.schema.json b/apps/heft/src/schemas/file-selection.schema.json new file mode 100644 index 00000000000..1b3b2a652d2 --- /dev/null +++ b/apps/heft/src/schemas/file-selection.schema.json @@ -0,0 +1,42 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09/schema", + "title": "File Selection Specifier Base", + "description": "Used to specify a selection of one or more files.", + "x-tsdoc-release-tag": "@public", + "type": "object", + "additionalProperties": false, + "properties": { + "sourcePath": { + "type": "string", + "description": "The target folder, relative to the project root. Settings such as \"includeGlobs\" and \"excludeGlobs\" will be resolved relative to this folder. If no globs or file extensions are specified, the folder will be used as-is. If this parameter is not provided, defaults to the project root.", + "pattern": "[^\\\\]" + }, + + "fileExtensions": { + "type": "array", + "description": "If specified, this option recursively scans all folders under \"sourcePath\" and includes any files that match the specified extensions. (If \"fileExtensions\" and \"includeGlobs\" are both specified, their selections are added together.)", + "items": { + "type": "string", + "pattern": "^\\.[A-z0-9-_.]*[A-z0-9-_]+$" + } + }, + + "excludeGlobs": { + "type": "array", + "description": "A list of glob patterns that exclude files or folders from being selected. The paths are resolved relative to \"sourcePath\". These exclusions eliminate items that were selected by the \"includeGlobs\" or \"fileExtensions\" setting.", + "items": { + "type": "string", + "pattern": "[^\\\\]" + } + }, + + "includeGlobs": { + "type": "array", + "description": "A list of glob patterns that select files to be included. The paths are resolved relative to \"sourcePath\".", + "items": { + "type": "string", + "pattern": "[^\\\\]" + } + } + } +} diff --git a/apps/heft/src/schemas/heft-plugin.schema.json b/apps/heft/src/schemas/heft-plugin.schema.json index 37dd45012d7..5a73c1b66b5 100644 --- a/apps/heft/src/schemas/heft-plugin.schema.json +++ b/apps/heft/src/schemas/heft-plugin.schema.json @@ -1,18 +1,17 @@ { - "$schema": "http://json-schema.org/draft-04/schema#", - "title": "Heft Configuration", + "$schema": "https://json-schema.org/draft/2019-09/schema", + "title": "Heft Plugin Configuration", "description": "Defines configuration used by core Heft.", "type": "object", - "definitions": { + "$defs": { "anything": { "type": ["array", "boolean", "integer", "number", "object", "string"], - "items": { "$ref": "#/definitions/anything" } + "items": { "$ref": "#/$defs/anything" } }, "baseParameter": { "type": "object", - "additionalProperties": true, "required": ["parameterKind", "longName", "description"], "properties": { "parameterKind": { @@ -50,305 +49,178 @@ "title": "Choice Parameter", "description": "A command-line parameter whose argument must be chosen from a list of allowable alternatives", "type": "object", - "allOf": [ - { "$ref": "#/definitions/baseParameter" }, - { - "type": "object", - "additionalProperties": true, - "required": ["alternatives"], - "properties": { - "parameterKind": { - "enum": ["choice"] - }, - "alternatives": { - "title": "Alternatives", - "description": "A list of alternative argument values that can be chosen for this parameter.", - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": ["name", "description"], - "properties": { - "name": { - "title": "Name of Alternative", - "description": "A token that is one of the alternatives that can be used with the choice parameter, e.g. \"vanilla\" in \"--flavor vanilla\"", - "type": "string" - }, - "description": { - "title": "Description of Alternative", - "description": "A detailed description for the alternative that will be shown in the command-line help.", - "type": "string" - } - } + "unevaluatedProperties": false, + "allOf": [{ "$ref": "#/$defs/baseParameter" }], + "required": ["alternatives"], + "properties": { + "parameterKind": { + "enum": ["choice"] + }, + "alternatives": { + "title": "Alternatives", + "description": "A list of alternative argument values that can be chosen for this parameter.", + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "additionalProperties": false, + "required": ["name", "description"], + "properties": { + "name": { + "title": "Name of Alternative", + "description": "A token that is one of the alternatives that can be used with the choice parameter, e.g. \"vanilla\" in \"--flavor vanilla\"", + "type": "string" + }, + "description": { + "title": "Description of Alternative", + "description": "A detailed description for the alternative that will be shown in the command-line help.", + "type": "string" } - }, - "defaultValue": { - "title": "Default Value", - "description": "If the parameter is omitted from the command line, this value will be inserted by default", - "type": "string" } } }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "parameterKind": { "$ref": "#/definitions/anything" }, - "longName": { "$ref": "#/definitions/anything" }, - "shortName": { "$ref": "#/definitions/anything" }, - "description": { "$ref": "#/definitions/anything" }, - "required": { "$ref": "#/definitions/anything" }, - - "alternatives": { "$ref": "#/definitions/anything" }, - "defaultValue": { "$ref": "#/definitions/anything" } - } + "defaultValue": { + "title": "Default Value", + "description": "If the parameter is omitted from the command line, this value will be inserted by default", + "type": "string" } - ] + } }, "choiceListParameter": { "title": "Choice List Parameter", "description": "A command-line parameter whose arguments must be chosen from a list of allowable alternatives", "type": "object", - "allOf": [ - { "$ref": "#/definitions/baseParameter" }, - { - "type": "object", - "additionalProperties": true, - "required": ["alternatives"], - "properties": { - "parameterKind": { - "enum": ["choiceList"] - }, - "alternatives": { - "title": "Alternatives", - "description": "A list of alternative argument values that can be chosen for this parameter.", - "type": "array", - "minItems": 1, - "items": { - "type": "object", - "additionalProperties": false, - "required": ["name", "description"], - "properties": { - "name": { - "title": "Name of Alternative", - "description": "A token that is one of the alternatives that can be used with the choice parameter, e.g. \"vanilla\" in \"--flavor vanilla\"", - "type": "string" - }, - "description": { - "title": "Description of Alternative", - "description": "A detailed description for the alternative that will be shown in the command-line help.", - "type": "string" - } - } + "unevaluatedProperties": false, + "allOf": [{ "$ref": "#/$defs/baseParameter" }], + "required": ["alternatives"], + "properties": { + "parameterKind": { + "enum": ["choiceList"] + }, + "alternatives": { + "title": "Alternatives", + "description": "A list of alternative argument values that can be chosen for this parameter.", + "type": "array", + "minItems": 1, + "items": { + "type": "object", + "additionalProperties": false, + "required": ["name", "description"], + "properties": { + "name": { + "title": "Name of Alternative", + "description": "A token that is one of the alternatives that can be used with the choice parameter, e.g. \"vanilla\" in \"--flavor vanilla\"", + "type": "string" + }, + "description": { + "title": "Description of Alternative", + "description": "A detailed description for the alternative that will be shown in the command-line help.", + "type": "string" } } } - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "parameterKind": { "$ref": "#/definitions/anything" }, - "longName": { "$ref": "#/definitions/anything" }, - "shortName": { "$ref": "#/definitions/anything" }, - "description": { "$ref": "#/definitions/anything" }, - "required": { "$ref": "#/definitions/anything" }, - - "alternatives": { "$ref": "#/definitions/anything" } - } } - ] + } }, "flagParameter": { "title": "Flag Parameter", "description": "A command-line parameter whose presence acts as an on/off switch", "type": "object", - "allOf": [ - { "$ref": "#/definitions/baseParameter" }, - { - "type": "object", - "additionalProperties": true, - "properties": { - "parameterKind": { - "enum": ["flag"] - } - } - }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "parameterKind": { "$ref": "#/definitions/anything" }, - "longName": { "$ref": "#/definitions/anything" }, - "shortName": { "$ref": "#/definitions/anything" }, - "description": { "$ref": "#/definitions/anything" }, - "required": { "$ref": "#/definitions/anything" } - } + "unevaluatedProperties": false, + "allOf": [{ "$ref": "#/$defs/baseParameter" }], + "properties": { + "parameterKind": { + "enum": ["flag"] } - ] + } }, "integerParameter": { "title": "Integer Parameter", "description": "A command-line parameter whose value is interpreted as an integer", "type": "object", - "allOf": [ - { "$ref": "#/definitions/baseParameter" }, - { - "type": "object", - "additionalProperties": true, - "required": ["argumentName"], - "properties": { - "parameterKind": { - "enum": ["integer"] - }, - "argumentName": { - "title": "Argument Name", - "description": "The name of the argument for this parameter.", - "type": "string" - }, - "defaultValue": { - "title": "Default Value", - "description": "If the parameter is omitted from the command line, this value will be inserted by default", - "type": "integer" - } - } + "unevaluatedProperties": false, + "allOf": [{ "$ref": "#/$defs/baseParameter" }], + "required": ["argumentName"], + "properties": { + "parameterKind": { + "enum": ["integer"] }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "parameterKind": { "$ref": "#/definitions/anything" }, - "longName": { "$ref": "#/definitions/anything" }, - "shortName": { "$ref": "#/definitions/anything" }, - "description": { "$ref": "#/definitions/anything" }, - "required": { "$ref": "#/definitions/anything" }, - - "argumentName": { "$ref": "#/definitions/anything" }, - "defaultValue": { "$ref": "#/definitions/anything" } - } + "argumentName": { + "title": "Argument Name", + "description": "The name of the argument for this parameter.", + "type": "string" + }, + "defaultValue": { + "title": "Default Value", + "description": "If the parameter is omitted from the command line, this value will be inserted by default", + "type": "integer" } - ] + } }, "integerListParameter": { "title": "Integer List Parameter", "description": "A command-line parameter whose value is interpreted as a list of integers", "type": "object", - "allOf": [ - { "$ref": "#/definitions/baseParameter" }, - { - "type": "object", - "additionalProperties": true, - "required": ["argumentName"], - "properties": { - "parameterKind": { - "enum": ["integerList"] - }, - "argumentName": { - "title": "Argument Name", - "description": "The name of the argument for this parameter.", - "type": "string" - } - } + "unevaluatedProperties": false, + "allOf": [{ "$ref": "#/$defs/baseParameter" }], + "required": ["argumentName"], + "properties": { + "parameterKind": { + "enum": ["integerList"] }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "parameterKind": { "$ref": "#/definitions/anything" }, - "longName": { "$ref": "#/definitions/anything" }, - "shortName": { "$ref": "#/definitions/anything" }, - "description": { "$ref": "#/definitions/anything" }, - "required": { "$ref": "#/definitions/anything" }, - - "argumentName": { "$ref": "#/definitions/anything" } - } + "argumentName": { + "title": "Argument Name", + "description": "The name of the argument for this parameter.", + "type": "string" } - ] + } }, "stringParameter": { "title": "String Parameter", "description": "A command-line parameter whose value is interpreted as a string", "type": "object", - "allOf": [ - { "$ref": "#/definitions/baseParameter" }, - { - "type": "object", - "additionalProperties": true, - "required": ["argumentName"], - "properties": { - "parameterKind": { - "enum": ["string"] - }, - "argumentName": { - "title": "Argument Name", - "description": "The name of the argument for this parameter.", - "type": "string" - }, - "defaultValue": { - "title": "Default Value", - "description": "If the parameter is omitted from the command line, this value will be inserted by default", - "type": "string" - } - } + "unevaluatedProperties": false, + "allOf": [{ "$ref": "#/$defs/baseParameter" }], + "required": ["argumentName"], + "properties": { + "parameterKind": { + "enum": ["string"] }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "parameterKind": { "$ref": "#/definitions/anything" }, - "longName": { "$ref": "#/definitions/anything" }, - "shortName": { "$ref": "#/definitions/anything" }, - "description": { "$ref": "#/definitions/anything" }, - "required": { "$ref": "#/definitions/anything" }, - - "argumentName": { "$ref": "#/definitions/anything" }, - "defaultValue": { "$ref": "#/definitions/anything" } - } + "argumentName": { + "title": "Argument Name", + "description": "The name of the argument for this parameter.", + "type": "string" + }, + "defaultValue": { + "title": "Default Value", + "description": "If the parameter is omitted from the command line, this value will be inserted by default", + "type": "string" } - ] + } }, "stringListParameter": { "title": "String List Parameter", "description": "A command-line parameter whose value is interpreted as a string list", "type": "object", - "allOf": [ - { "$ref": "#/definitions/baseParameter" }, - { - "type": "object", - "additionalProperties": true, - "required": ["argumentName"], - "properties": { - "parameterKind": { - "enum": ["stringList"] - }, - "argumentName": { - "title": "Argument Name", - "description": "The name of the argument for this parameter.", - "type": "string" - } - } + "unevaluatedProperties": false, + "allOf": [{ "$ref": "#/$defs/baseParameter" }], + "required": ["argumentName"], + "properties": { + "parameterKind": { + "enum": ["stringList"] }, - { - "type": "object", - "additionalProperties": false, - "properties": { - "parameterKind": { "$ref": "#/definitions/anything" }, - "longName": { "$ref": "#/definitions/anything" }, - "shortName": { "$ref": "#/definitions/anything" }, - "description": { "$ref": "#/definitions/anything" }, - "required": { "$ref": "#/definitions/anything" }, - - "argumentName": { "$ref": "#/definitions/anything" } - } + "argumentName": { + "title": "Argument Name", + "description": "The name of the argument for this parameter.", + "type": "string" } - ] + } }, "heft-plugin-base": { @@ -391,13 +263,13 @@ "items": { "type": "object", "oneOf": [ - { "$ref": "#/definitions/flagParameter" }, - { "$ref": "#/definitions/integerParameter" }, - { "$ref": "#/definitions/integerListParameter" }, - { "$ref": "#/definitions/choiceParameter" }, - { "$ref": "#/definitions/choiceListParameter" }, - { "$ref": "#/definitions/stringParameter" }, - { "$ref": "#/definitions/stringListParameter" } + { "$ref": "#/$defs/flagParameter" }, + { "$ref": "#/$defs/integerParameter" }, + { "$ref": "#/$defs/integerListParameter" }, + { "$ref": "#/$defs/choiceParameter" }, + { "$ref": "#/$defs/choiceListParameter" }, + { "$ref": "#/$defs/stringParameter" }, + { "$ref": "#/$defs/stringListParameter" } ] } } @@ -405,11 +277,11 @@ }, "heft-lifecycle-plugin": { - "$ref": "#/definitions/heft-plugin-base" + "$ref": "#/$defs/heft-plugin-base" }, "heft-task-plugin": { - "$ref": "#/definitions/heft-plugin-base" + "$ref": "#/$defs/heft-plugin-base" } }, @@ -425,14 +297,14 @@ "title": "Lifecycle Plugins", "description": "A list of plugins that will be loaded and used for Heft lifecycle hooks.", "type": "array", - "items": { "$ref": "#/definitions/heft-lifecycle-plugin" } + "items": { "$ref": "#/$defs/heft-lifecycle-plugin" } }, "taskPlugins": { "title": "Task Plugins", "description": "A list of plugins that will be loaded and used for Heft task hooks.", "type": "array", - "items": { "$ref": "#/definitions/heft-task-plugin" } + "items": { "$ref": "#/$defs/heft-task-plugin" } } } } diff --git a/apps/heft/src/schemas/heft.schema.json b/apps/heft/src/schemas/heft.schema.json index cba91630724..26df02a6c65 100644 --- a/apps/heft/src/schemas/heft.schema.json +++ b/apps/heft/src/schemas/heft.schema.json @@ -1,13 +1,13 @@ { - "$schema": "http://json-schema.org/draft-04/schema#", + "$schema": "https://json-schema.org/draft/2019-09/schema", "title": "Heft Configuration", "description": "Defines configuration used by core Heft.", "type": "object", - "definitions": { + "$defs": { "anything": { "type": ["array", "boolean", "integer", "number", "object", "string"], - "items": { "$ref": "#/definitions/anything" } + "items": { "$ref": "#/$defs/anything" } }, "heft-plugin": { @@ -51,18 +51,11 @@ } }, - "delete-operation": { + "fileSelectionSpecifierBase": { + "description": "Used to specify a selection of one or more files.", "type": "object", - "additionalProperties": false, - "anyOf": [ - { "required": ["sourcePath"] }, - { "required": ["fileExtensions"] }, - { "required": ["includeGlobs"] }, - { "required": ["excludeGlobs"] } - ], "properties": { "sourcePath": { - "title": "Source Path", "type": "string", "description": "The target file or folder, relative to the project root. Settings such as \"includeGlobs\" and \"excludeGlobs\" will be resolved relative to this folder. If no globs or file extensions are specified, the file or folder will be deleted.", "pattern": "[^\\\\]" @@ -77,7 +70,7 @@ }, "excludeGlobs": { "type": "array", - "description": "A list of glob patterns that exclude files or folders from being copied. The paths are resolved relative to \"sourcePath\". These exclusions eliminate items that were selected by the \"includeGlobs\" or \"fileExtensions\" setting.", + "description": "A list of glob patterns that exclude files or folders from being deleted. The paths are resolved relative to \"sourcePath\". These exclusions eliminate items that were selected by the \"includeGlobs\" or \"fileExtensions\" setting.", "items": { "type": "string", "pattern": "[^\\\\]" @@ -85,13 +78,26 @@ }, "includeGlobs": { "type": "array", - "description": "A list of glob patterns that select files to be copied. The paths are resolved relative to \"sourcePath\".", + "description": "A list of glob patterns that select files to be deleted. The paths are resolved relative to \"sourcePath\".", "items": { "type": "string", "pattern": "[^\\\\]" } } } + }, + + "delete-operation": { + "type": "object", + "unevaluatedProperties": false, + "anyOf": [ + { "required": ["sourcePath"] }, + { "required": ["fileExtensions"] }, + { "required": ["includeGlobs"] }, + { "required": ["excludeGlobs"] } + ], + "allOf": [{ "$ref": "#/$defs/fileSelectionSpecifierBase" }], + "properties": {} } }, @@ -111,7 +117,7 @@ "heftPlugins": { "type": "array", "description": "List of Heft plugins that are used by a project.", - "items": { "$ref": "#/definitions/heft-plugin" } + "items": { "$ref": "#/$defs/heft-plugin" } }, "aliasesByName": { @@ -169,7 +175,7 @@ "cleanFiles": { "description": "List of delete operations to perform when cleaning at the beginning of phase execution.", "type": "array", - "items": { "$ref": "#/definitions/delete-operation" } + "items": { "$ref": "#/$defs/delete-operation" } }, "tasksByName": { @@ -183,7 +189,7 @@ "additionalProperties": false, "required": ["taskPlugin"], "properties": { - "taskPlugin": { "$ref": "#/definitions/heft-plugin" }, + "taskPlugin": { "$ref": "#/$defs/heft-plugin" }, "taskDependencies": { "type": "array", diff --git a/apps/heft/src/schemas/set-environment-variables-plugin.schema.json b/apps/heft/src/schemas/set-environment-variables-plugin.schema.json index 7ffa21d2967..9f5b3aeac8f 100644 --- a/apps/heft/src/schemas/set-environment-variables-plugin.schema.json +++ b/apps/heft/src/schemas/set-environment-variables-plugin.schema.json @@ -1,7 +1,7 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "title": "CopyFiles Heft Task Event Options", - "description": "Defines configuration used by the \"copyFiles\" Heft task event.", + "title": "SetEnvironmentVariables Heft Task Event Options", + "description": "Defines configuration used by the \"setEnvironmentVariables\" Heft task event.", "type": "object", "additionalProperties": false, diff --git a/build-tests/api-extractor-test-05/dist/tsdoc-metadata.json b/build-tests/api-extractor-test-05/dist/tsdoc-metadata.json index 35d93708271..610567002e0 100644 --- a/build-tests/api-extractor-test-05/dist/tsdoc-metadata.json +++ b/build-tests/api-extractor-test-05/dist/tsdoc-metadata.json @@ -5,7 +5,7 @@ "toolPackages": [ { "packageName": "@microsoft/api-extractor", - "packageVersion": "7.57.0" + "packageVersion": "7.57.2" } ] } diff --git a/build-tests/heft-json-schema-typings-plugin-test/config/heft.json b/build-tests/heft-json-schema-typings-plugin-test/config/heft.json index f74df35f8af..67eab084ea8 100644 --- a/build-tests/heft-json-schema-typings-plugin-test/config/heft.json +++ b/build-tests/heft-json-schema-typings-plugin-test/config/heft.json @@ -5,16 +5,16 @@ "phasesByName": { "build": { - "cleanFiles": [{ "includeGlobs": ["temp/schema-dts"] }], + "cleanFiles": [{ "includeGlobs": ["temp/schema-dts-unformatted", "temp/schema-dts-formatted"] }], "tasksByName": { - "json-schema-typings": { + "json-schema-typings-unformatted": { "taskPlugin": { "pluginPackage": "@rushstack/heft-json-schema-typings-plugin", "pluginName": "json-schema-typings-plugin", "options": { "srcFolder": "node_modules/@rushstack/node-core-library/src/test/test-data/test-schemas", - "generatedTsFolders": ["temp/schema-dts"] + "generatedTsFolders": ["temp/schema-dts-unformatted"] } } }, diff --git a/build-tests/heft-json-schema-typings-plugin-test/src/test/JsonSchemaTypingsGenerator.test.ts b/build-tests/heft-json-schema-typings-plugin-test/src/test/JsonSchemaTypingsGenerator.test.ts index 20a46ffc077..e56c8119d73 100644 --- a/build-tests/heft-json-schema-typings-plugin-test/src/test/JsonSchemaTypingsGenerator.test.ts +++ b/build-tests/heft-json-schema-typings-plugin-test/src/test/JsonSchemaTypingsGenerator.test.ts @@ -40,15 +40,15 @@ describe('json-schema-typings-plugin', () => { rootFolder = foundRootFolder; }); - it('should generate typings for JSON Schemas', async () => { + it('should generate typings for JSON Schemas (unformatted)', async () => { const folderItems: Record = await getFolderItemsAsync( - `${rootFolder}/temp/schema-dts`, + `${rootFolder}/temp/schema-dts-unformatted`, '.' ); expect(folderItems).toMatchSnapshot(); }); - it('should generate formatted typings for JSON Schemas', async () => { + it('should generate typings for JSON Schemas (formatted)', async () => { const folderItems: Record = await getFolderItemsAsync( `${rootFolder}/temp/schema-dts-formatted`, '.' diff --git a/build-tests/heft-json-schema-typings-plugin-test/src/test/__snapshots__/JsonSchemaTypingsGenerator.test.ts.snap b/build-tests/heft-json-schema-typings-plugin-test/src/test/__snapshots__/JsonSchemaTypingsGenerator.test.ts.snap index e65a7d9d88a..50ea7bb1cae 100644 --- a/build-tests/heft-json-schema-typings-plugin-test/src/test/__snapshots__/JsonSchemaTypingsGenerator.test.ts.snap +++ b/build-tests/heft-json-schema-typings-plugin-test/src/test/__snapshots__/JsonSchemaTypingsGenerator.test.ts.snap @@ -1,6 +1,6 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP -exports[`json-schema-typings-plugin should generate formatted typings for JSON Schemas 1`] = ` +exports[`json-schema-typings-plugin should generate typings for JSON Schemas (formatted) 1`] = ` Object { "./test-invalid-additional.schema.json.d.ts": "// This file was generated by a tool. Modifying it will produce unexpected behavior @@ -54,6 +54,44 @@ export interface Type2 { ", "./test-schema-draft-07.schema.json.d.ts": "// This file was generated by a tool. Modifying it will produce unexpected behavior +export interface TestSchemaFile { + exampleString: string; + exampleLink?: string; + exampleArray: string[]; + /** + * Description for exampleOneOf - this is a very long description to show in an error message + */ + exampleOneOf?: Type1 | Type2; + exampleUniqueObjectArray?: { + field2?: string; + field3?: string; + }[]; +} +/** + * Description for type1 + */ +export interface Type1 { + /** + * Description for field1 + */ + field1: string; +} +/** + * Description for type2 + */ +export interface Type2 { + /** + * Description for field2 + */ + field2: string; + /** + * Description for field3 + */ + field3: string; +} +", + "./test-schema-draft-2019-09.schema.json.d.ts": "// This file was generated by a tool. Modifying it will produce unexpected behavior + export interface TestSchemaFile { exampleString: string; exampleLink?: string; @@ -184,7 +222,7 @@ export interface TestValid { } `; -exports[`json-schema-typings-plugin should generate typings for JSON Schemas 1`] = ` +exports[`json-schema-typings-plugin should generate typings for JSON Schemas (unformatted) 1`] = ` Object { "./test-invalid-additional.schema.json.d.ts": "// This file was generated by a tool. Modifying it will produce unexpected behavior @@ -238,6 +276,44 @@ field3: string ", "./test-schema-draft-07.schema.json.d.ts": "// This file was generated by a tool. Modifying it will produce unexpected behavior +export interface TestSchemaFile { +exampleString: string +exampleLink?: string +exampleArray: string[] +/** + * Description for exampleOneOf - this is a very long description to show in an error message + */ +exampleOneOf?: (Type1 | Type2) +exampleUniqueObjectArray?: { +field2?: string +field3?: string +}[] +} +/** + * Description for type1 + */ +export interface Type1 { +/** + * Description for field1 + */ +field1: string +} +/** + * Description for type2 + */ +export interface Type2 { +/** + * Description for field2 + */ +field2: string +/** + * Description for field3 + */ +field3: string +} +", + "./test-schema-draft-2019-09.schema.json.d.ts": "// This file was generated by a tool. Modifying it will produce unexpected behavior + export interface TestSchemaFile { exampleString: string exampleLink?: string diff --git a/common/changes/@microsoft/api-extractor/use-json-schema-plugin_2026-02-22-06-11.json b/common/changes/@microsoft/api-extractor/use-json-schema-plugin_2026-02-22-06-11.json new file mode 100644 index 00000000000..752ad7dd46f --- /dev/null +++ b/common/changes/@microsoft/api-extractor/use-json-schema-plugin_2026-02-22-06-11.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@microsoft/api-extractor", + "comment": "", + "type": "none" + } + ], + "packageName": "@microsoft/api-extractor" +} \ No newline at end of file diff --git a/common/changes/@microsoft/rush/use-json-schema-plugin_2026-02-22-06-11.json b/common/changes/@microsoft/rush/use-json-schema-plugin_2026-02-22-06-11.json new file mode 100644 index 00000000000..bd7ff97cb34 --- /dev/null +++ b/common/changes/@microsoft/rush/use-json-schema-plugin_2026-02-22-06-11.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@microsoft/rush", + "comment": "", + "type": "none" + } + ], + "packageName": "@microsoft/rush" +} \ No newline at end of file diff --git a/common/changes/@rushstack/credential-cache/use-json-schema-plugin_2026-02-22-06-11.json b/common/changes/@rushstack/credential-cache/use-json-schema-plugin_2026-02-22-06-11.json new file mode 100644 index 00000000000..bce1619cc7e --- /dev/null +++ b/common/changes/@rushstack/credential-cache/use-json-schema-plugin_2026-02-22-06-11.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@rushstack/credential-cache", + "comment": "", + "type": "none" + } + ], + "packageName": "@rushstack/credential-cache" +} \ No newline at end of file diff --git a/common/changes/@rushstack/heft-api-extractor-plugin/use-json-schema-plugin_2026-02-22-06-11.json b/common/changes/@rushstack/heft-api-extractor-plugin/use-json-schema-plugin_2026-02-22-06-11.json new file mode 100644 index 00000000000..95128aed453 --- /dev/null +++ b/common/changes/@rushstack/heft-api-extractor-plugin/use-json-schema-plugin_2026-02-22-06-11.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@rushstack/heft-api-extractor-plugin", + "comment": "", + "type": "none" + } + ], + "packageName": "@rushstack/heft-api-extractor-plugin" +} \ No newline at end of file diff --git a/common/changes/@rushstack/heft-isolated-typescript-transpile-plugin/use-json-schema-plugin_2026-02-22-06-11.json b/common/changes/@rushstack/heft-isolated-typescript-transpile-plugin/use-json-schema-plugin_2026-02-22-06-11.json new file mode 100644 index 00000000000..fbd4c12b6b9 --- /dev/null +++ b/common/changes/@rushstack/heft-isolated-typescript-transpile-plugin/use-json-schema-plugin_2026-02-22-06-11.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@rushstack/heft-isolated-typescript-transpile-plugin", + "comment": "", + "type": "none" + } + ], + "packageName": "@rushstack/heft-isolated-typescript-transpile-plugin" +} \ No newline at end of file diff --git a/common/changes/@rushstack/heft-jest-plugin/use-json-schema-plugin_2026-02-22-06-11.json b/common/changes/@rushstack/heft-jest-plugin/use-json-schema-plugin_2026-02-22-06-11.json new file mode 100644 index 00000000000..8453696f39b --- /dev/null +++ b/common/changes/@rushstack/heft-jest-plugin/use-json-schema-plugin_2026-02-22-06-11.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@rushstack/heft-jest-plugin", + "comment": "", + "type": "none" + } + ], + "packageName": "@rushstack/heft-jest-plugin" +} \ No newline at end of file diff --git a/common/changes/@rushstack/heft-json-schema-typings-plugin/use-json-schema-plugin_2026-02-22-04-05.json b/common/changes/@rushstack/heft-json-schema-typings-plugin/use-json-schema-plugin_2026-02-22-04-05.json new file mode 100644 index 00000000000..e25851c29ff --- /dev/null +++ b/common/changes/@rushstack/heft-json-schema-typings-plugin/use-json-schema-plugin_2026-02-22-04-05.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@rushstack/heft-json-schema-typings-plugin", + "comment": "Fix TSDoc parse warnings caused by `@` characters in generated type definitions. The `json-schema-to-typescript` library emits JSDoc comments containing raw JSON Schema pattern values (e.g. `\"^@[^\\s]*$\"`), which TSDoc interprets as tag indicators. These values are now wrapped in backtick code spans to prevent the warnings.", + "type": "minor" + } + ], + "packageName": "@rushstack/heft-json-schema-typings-plugin" +} \ No newline at end of file diff --git a/common/changes/@rushstack/heft-lint-plugin/use-json-schema-plugin_2026-02-22-06-11.json b/common/changes/@rushstack/heft-lint-plugin/use-json-schema-plugin_2026-02-22-06-11.json new file mode 100644 index 00000000000..a259901b76f --- /dev/null +++ b/common/changes/@rushstack/heft-lint-plugin/use-json-schema-plugin_2026-02-22-06-11.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@rushstack/heft-lint-plugin", + "comment": "", + "type": "none" + } + ], + "packageName": "@rushstack/heft-lint-plugin" +} \ No newline at end of file diff --git a/common/changes/@rushstack/heft-localization-typings-plugin/use-json-schema-plugin_2026-02-22-06-11.json b/common/changes/@rushstack/heft-localization-typings-plugin/use-json-schema-plugin_2026-02-22-06-11.json new file mode 100644 index 00000000000..e3dd3971b44 --- /dev/null +++ b/common/changes/@rushstack/heft-localization-typings-plugin/use-json-schema-plugin_2026-02-22-06-11.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@rushstack/heft-localization-typings-plugin", + "comment": "", + "type": "none" + } + ], + "packageName": "@rushstack/heft-localization-typings-plugin" +} \ No newline at end of file diff --git a/common/changes/@rushstack/heft-rspack-plugin/use-json-schema-plugin_2026-02-22-06-11.json b/common/changes/@rushstack/heft-rspack-plugin/use-json-schema-plugin_2026-02-22-06-11.json new file mode 100644 index 00000000000..c002a6dc429 --- /dev/null +++ b/common/changes/@rushstack/heft-rspack-plugin/use-json-schema-plugin_2026-02-22-06-11.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@rushstack/heft-rspack-plugin", + "comment": "", + "type": "none" + } + ], + "packageName": "@rushstack/heft-rspack-plugin" +} \ No newline at end of file diff --git a/common/changes/@rushstack/heft-sass-plugin/use-json-schema-plugin_2026-02-22-06-11.json b/common/changes/@rushstack/heft-sass-plugin/use-json-schema-plugin_2026-02-22-06-11.json new file mode 100644 index 00000000000..501a07dfec7 --- /dev/null +++ b/common/changes/@rushstack/heft-sass-plugin/use-json-schema-plugin_2026-02-22-06-11.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@rushstack/heft-sass-plugin", + "comment": "", + "type": "none" + } + ], + "packageName": "@rushstack/heft-sass-plugin" +} \ No newline at end of file diff --git a/common/changes/@rushstack/heft-storybook-plugin/use-json-schema-plugin_2026-02-22-06-11.json b/common/changes/@rushstack/heft-storybook-plugin/use-json-schema-plugin_2026-02-22-06-11.json new file mode 100644 index 00000000000..a46619d0a73 --- /dev/null +++ b/common/changes/@rushstack/heft-storybook-plugin/use-json-schema-plugin_2026-02-22-06-11.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@rushstack/heft-storybook-plugin", + "comment": "", + "type": "none" + } + ], + "packageName": "@rushstack/heft-storybook-plugin" +} \ No newline at end of file diff --git a/common/changes/@rushstack/heft-typescript-plugin/use-json-schema-plugin_2026-02-22-06-11.json b/common/changes/@rushstack/heft-typescript-plugin/use-json-schema-plugin_2026-02-22-06-11.json new file mode 100644 index 00000000000..cb6f98ca14f --- /dev/null +++ b/common/changes/@rushstack/heft-typescript-plugin/use-json-schema-plugin_2026-02-22-06-11.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@rushstack/heft-typescript-plugin", + "comment": "", + "type": "none" + } + ], + "packageName": "@rushstack/heft-typescript-plugin" +} \ No newline at end of file diff --git a/common/changes/@rushstack/heft-webpack4-plugin/use-json-schema-plugin_2026-02-22-06-11.json b/common/changes/@rushstack/heft-webpack4-plugin/use-json-schema-plugin_2026-02-22-06-11.json new file mode 100644 index 00000000000..e6a91323381 --- /dev/null +++ b/common/changes/@rushstack/heft-webpack4-plugin/use-json-schema-plugin_2026-02-22-06-11.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@rushstack/heft-webpack4-plugin", + "comment": "", + "type": "none" + } + ], + "packageName": "@rushstack/heft-webpack4-plugin" +} \ No newline at end of file diff --git a/common/changes/@rushstack/heft-webpack5-plugin/use-json-schema-plugin_2026-02-22-06-11.json b/common/changes/@rushstack/heft-webpack5-plugin/use-json-schema-plugin_2026-02-22-06-11.json new file mode 100644 index 00000000000..e62ded6bf1b --- /dev/null +++ b/common/changes/@rushstack/heft-webpack5-plugin/use-json-schema-plugin_2026-02-22-06-11.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@rushstack/heft-webpack5-plugin", + "comment": "", + "type": "none" + } + ], + "packageName": "@rushstack/heft-webpack5-plugin" +} \ No newline at end of file diff --git a/common/changes/@rushstack/heft/use-json-schema-plugin_2026-02-22-06-11.json b/common/changes/@rushstack/heft/use-json-schema-plugin_2026-02-22-06-11.json new file mode 100644 index 00000000000..4da3f257a2d --- /dev/null +++ b/common/changes/@rushstack/heft/use-json-schema-plugin_2026-02-22-06-11.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@rushstack/heft", + "comment": "", + "type": "none" + } + ], + "packageName": "@rushstack/heft" +} \ No newline at end of file diff --git a/common/changes/@rushstack/node-core-library/use-json-schema-plugin_2026-02-22-02-50.json b/common/changes/@rushstack/node-core-library/use-json-schema-plugin_2026-02-22-02-50.json new file mode 100644 index 00000000000..30f25144f66 --- /dev/null +++ b/common/changes/@rushstack/node-core-library/use-json-schema-plugin_2026-02-22-02-50.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@rushstack/node-core-library", + "comment": "Add support for `draft-2019-09` JSON schemas in `JsonSchema`.", + "type": "minor" + } + ], + "packageName": "@rushstack/node-core-library" +} \ No newline at end of file diff --git a/common/changes/@rushstack/rig-package/use-json-schema-plugin_2026-02-22-06-11.json b/common/changes/@rushstack/rig-package/use-json-schema-plugin_2026-02-22-06-11.json new file mode 100644 index 00000000000..1c1df562afb --- /dev/null +++ b/common/changes/@rushstack/rig-package/use-json-schema-plugin_2026-02-22-06-11.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@rushstack/rig-package", + "comment": "", + "type": "none" + } + ], + "packageName": "@rushstack/rig-package" +} \ No newline at end of file diff --git a/common/changes/@rushstack/typings-generator/use-json-schema-plugin_2026-02-22-06-11.json b/common/changes/@rushstack/typings-generator/use-json-schema-plugin_2026-02-22-06-11.json new file mode 100644 index 00000000000..8f04a7afc26 --- /dev/null +++ b/common/changes/@rushstack/typings-generator/use-json-schema-plugin_2026-02-22-06-11.json @@ -0,0 +1,10 @@ +{ + "changes": [ + { + "packageName": "@rushstack/typings-generator", + "comment": "", + "type": "none" + } + ], + "packageName": "@rushstack/typings-generator" +} \ No newline at end of file diff --git a/common/config/rush/nonbrowser-approved-packages.json b/common/config/rush/nonbrowser-approved-packages.json index 3f6756df1a8..335c7ea116a 100644 --- a/common/config/rush/nonbrowser-approved-packages.json +++ b/common/config/rush/nonbrowser-approved-packages.json @@ -208,7 +208,7 @@ }, { "name": "@rushstack/heft-json-schema-typings-plugin", - "allowedCategories": [ "tests" ] + "allowedCategories": [ "libraries", "tests" ] }, { "name": "@rushstack/heft-lint-plugin", diff --git a/common/config/subspaces/build-tests-subspace/pnpm-lock.yaml b/common/config/subspaces/build-tests-subspace/pnpm-lock.yaml index cf41ad60f8c..334ce2cdea8 100644 --- a/common/config/subspaces/build-tests-subspace/pnpm-lock.yaml +++ b/common/config/subspaces/build-tests-subspace/pnpm-lock.yaml @@ -166,6 +166,10 @@ importers: packages: + '@apidevtools/json-schema-ref-parser@11.9.3': + resolution: {integrity: sha512-60vepv88RwcJtSHrD6MjIL6Ta3SOYbgfnkHb+ppAVK+o9mXprRtulx7VlRl3lN3bbvysAfCS7WMVfhUYemB0IQ==} + engines: {node: '>= 16'} + '@babel/code-frame@7.28.6': resolution: {integrity: sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==} engines: {node: '>=6.9.0'} @@ -422,14 +426,6 @@ packages: '@types/node': optional: true - '@isaacs/balanced-match@4.0.1': - resolution: {integrity: sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==} - engines: {node: 20 || >=22} - - '@isaacs/brace-expansion@5.0.1': - resolution: {integrity: sha512-WMz71T1JS624nWj2n2fnYAuPovhv7EUhk69R6i9dsVyzxt5eM3bjwvgk9L+APE1TRscGysAVMANkB0jh0LQZrQ==} - engines: {node: 20 || >=22} - '@isaacs/fs-minipass@4.0.1': resolution: {integrity: sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==} engines: {node: '>=18.0.0'} @@ -555,6 +551,9 @@ packages: '@jridgewell/trace-mapping@0.3.31': resolution: {integrity: sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==} + '@jsdevtools/ono@7.1.3': + resolution: {integrity: sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==} + '@jsep-plugin/assignment@1.3.0': resolution: {integrity: sha512-VVgV+CXrhbMI3aSusQyclHkenWSAm95WaiKrMxRFam3JSUiIaQjoMIw2sEs/OX4XifnqeQUN4DYbJjlA8EfktQ==} engines: {node: '>= 10.16.0'} @@ -844,7 +843,7 @@ packages: '@rushstack/heft-api-extractor-plugin@file:../../../heft-plugins/heft-api-extractor-plugin': resolution: {directory: ../../../heft-plugins/heft-api-extractor-plugin, type: directory} peerDependencies: - '@rushstack/heft': 1.2.0 + '@rushstack/heft': 1.2.2 '@rushstack/heft-config-file@file:../../../libraries/heft-config-file': resolution: {directory: ../../../libraries/heft-config-file, type: directory} @@ -853,7 +852,7 @@ packages: '@rushstack/heft-jest-plugin@file:../../../heft-plugins/heft-jest-plugin': resolution: {directory: ../../../heft-plugins/heft-jest-plugin, type: directory} peerDependencies: - '@rushstack/heft': ^1.2.0 + '@rushstack/heft': ^1.2.2 jest-environment-jsdom: ^29.5.0 jest-environment-node: ^29.5.0 peerDependenciesMeta: @@ -862,20 +861,25 @@ packages: jest-environment-node: optional: true + '@rushstack/heft-json-schema-typings-plugin@file:../../../heft-plugins/heft-json-schema-typings-plugin': + resolution: {directory: ../../../heft-plugins/heft-json-schema-typings-plugin, type: directory} + peerDependencies: + '@rushstack/heft': 1.2.2 + '@rushstack/heft-lint-plugin@file:../../../heft-plugins/heft-lint-plugin': resolution: {directory: ../../../heft-plugins/heft-lint-plugin, type: directory} peerDependencies: - '@rushstack/heft': 1.2.0 + '@rushstack/heft': 1.2.2 '@rushstack/heft-node-rig@file:../../../rigs/heft-node-rig': resolution: {directory: ../../../rigs/heft-node-rig, type: directory} peerDependencies: - '@rushstack/heft': ^1.2.0 + '@rushstack/heft': ^1.2.2 '@rushstack/heft-typescript-plugin@file:../../../heft-plugins/heft-typescript-plugin': resolution: {directory: ../../../heft-plugins/heft-typescript-plugin, type: directory} peerDependencies: - '@rushstack/heft': 1.2.0 + '@rushstack/heft': 1.2.2 '@rushstack/heft@file:../../../apps/heft': resolution: {directory: ../../../apps/heft, type: directory} @@ -955,6 +959,14 @@ packages: '@rushstack/ts-command-line@file:../../../libraries/ts-command-line': resolution: {directory: ../../../libraries/ts-command-line, type: directory} + '@rushstack/typings-generator@file:../../../libraries/typings-generator': + resolution: {directory: ../../../libraries/typings-generator, type: directory} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + '@sinclair/typebox@0.27.8': resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} @@ -1021,6 +1033,9 @@ packages: '@types/json5@0.0.29': resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} + '@types/lodash@4.17.23': + resolution: {integrity: sha512-RDvF6wTulMPjrNdCoYRC8gNR880JNGT8uB+REUpC2Ns4pRqQJhGz90wh7rgdXDPpCczF3VGktDuFGVnz8zP7HA==} + '@types/node@20.17.19': resolution: {integrity: sha512-LEwC7o1ifqg/6r2gn9Dns0f1rhK+fPFDoMiceTJ6kWmVk6bgXBI/9IOWfVan4WiAavK9pIVWdX0/e3J+eEUh5A==} @@ -1363,6 +1378,10 @@ packages: resolution: {integrity: sha512-pbnl5XzGBdrFU/wT4jqmJVPn2B6UHPBOhzMQkY/SPUPB6QtUXtmBHBIwCbXJol93mOpGMnQyP/+BB19q04xj7g==} engines: {node: '>=4'} + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + bl@4.1.0: resolution: {integrity: sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==} @@ -1456,6 +1475,10 @@ packages: chardet@2.1.1: resolution: {integrity: sha512-PsezH1rqdV9VvyNhxxOW32/d75r01NY7TQCmOqomRo15ZSOKbpTFVsfjghxo6JloQUCGnH4k1LGu0R4yCLlWQQ==} + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + chownr@3.0.0: resolution: {integrity: sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==} engines: {node: '>=18'} @@ -1917,6 +1940,15 @@ packages: fb-watchman@2.0.2: resolution: {integrity: sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==} + fdir@6.5.0: + resolution: {integrity: sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==} + engines: {node: '>=12.0.0'} + peerDependencies: + picomatch: ^3 || ^4 + peerDependenciesMeta: + picomatch: + optional: true + figures@3.0.0: resolution: {integrity: sha512-HKri+WoWoUgr83pehn/SIgLOMZ9nAWC6dcGj26RY2R4F50u4+RTUz0RCrUlOV3nKRAICW1UGzyb+kcX2qK1S/g==} engines: {node: '>=8'} @@ -2193,6 +2225,10 @@ packages: resolution: {integrity: sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==} engines: {node: '>= 0.4'} + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + is-boolean-object@1.2.2: resolution: {integrity: sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==} engines: {node: '>= 0.4'} @@ -2535,6 +2571,11 @@ packages: json-parse-even-better-errors@2.3.1: resolution: {integrity: sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==} + json-schema-to-typescript@15.0.4: + resolution: {integrity: sha512-Su9oK8DR4xCmDsLlyvadkXzX6+GGXJpbhwoLtOGArAG61dvbW4YQmSEno2y66ahpIdmLMg6YUf/QHLgiwvkrHQ==} + engines: {node: '>=16.0.0'} + hasBin: true + json-schema-traverse@0.4.1: resolution: {integrity: sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==} @@ -2683,10 +2724,6 @@ packages: resolution: {integrity: sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==} engines: {node: '>=8'} - minimatch@10.1.2: - resolution: {integrity: sha512-fu656aJ0n2kcXwsnwnv9g24tkU5uSmOlTjd6WyyaKm2Z+h1qmY6bAjrcaIxF/BslFqbZ8UBtbJi7KgQOZD2PTw==} - engines: {node: 20 || >=22} - minimatch@10.2.1: resolution: {integrity: sha512-MClCe8IL5nRRmawL6ib/eT4oLyeKMGCghibcDWK+J0hh0Q8kqSdia6BvbRMVk6mPa6WqUa5uR2oxt6C5jd533A==} engines: {node: 20 || >=22} @@ -2958,6 +2995,11 @@ packages: resolution: {integrity: sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==} engines: {node: '>= 0.8.0'} + prettier@3.8.1: + resolution: {integrity: sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==} + engines: {node: '>=14'} + hasBin: true + pretty-error@4.0.0: resolution: {integrity: sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==} @@ -3020,6 +3062,10 @@ packages: resolution: {integrity: sha512-asaikDeqAQg7JifRsZn1NJZXo9E+VwlyCfbkZhwyISinqk5zNS6266HS5kah6P0SaQKGF6SkNnZVHUzHFYxYDw==} deprecated: This functionality has been moved to @npmcli/fs + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + reflect.getprototypeof@1.0.10: resolution: {integrity: sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==} engines: {node: '>= 0.4'} @@ -3381,6 +3427,10 @@ packages: through@2.3.8: resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + tinyglobby@0.2.15: + resolution: {integrity: sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==} + engines: {node: '>=12.0.0'} + tmpl@1.0.5: resolution: {integrity: sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==} @@ -3607,6 +3657,12 @@ packages: snapshots: + '@apidevtools/json-schema-ref-parser@11.9.3': + dependencies: + '@jsdevtools/ono': 7.1.3 + '@types/json-schema': 7.0.15 + js-yaml: 4.1.1 + '@babel/code-frame@7.28.6': dependencies: '@babel/helper-validator-identifier': 7.28.5 @@ -3896,12 +3952,6 @@ snapshots: optionalDependencies: '@types/node': 20.17.19 - '@isaacs/balanced-match@4.0.1': {} - - '@isaacs/brace-expansion@5.0.1': - dependencies: - '@isaacs/balanced-match': 4.0.1 - '@isaacs/fs-minipass@4.0.1': dependencies: minipass: 7.1.2 @@ -4156,6 +4206,8 @@ snapshots: '@jridgewell/resolve-uri': 3.1.2 '@jridgewell/sourcemap-codec': 1.5.5 + '@jsdevtools/ono@7.1.3': {} + '@jsep-plugin/assignment@1.3.0(jsep@1.4.0)': dependencies: jsep: 1.4.0 @@ -4672,6 +4724,15 @@ snapshots: - supports-color - ts-node + '@rushstack/heft-json-schema-typings-plugin@file:../../../heft-plugins/heft-json-schema-typings-plugin(@rushstack/heft@file:../../../apps/heft(@types/node@20.17.19))(@types/node@20.17.19)': + dependencies: + '@rushstack/heft': file:../../../apps/heft(@types/node@20.17.19) + '@rushstack/node-core-library': file:../../../libraries/node-core-library(@types/node@20.17.19) + '@rushstack/typings-generator': file:../../../libraries/typings-generator(@types/node@20.17.19) + json-schema-to-typescript: 15.0.4 + transitivePeerDependencies: + - '@types/node' + '@rushstack/heft-lint-plugin@file:../../../heft-plugins/heft-lint-plugin(@rushstack/heft@file:../../../apps/heft(@types/node@20.17.19))(@types/node@20.17.19)': dependencies: '@rushstack/heft': file:../../../apps/heft(@types/node@20.17.19) @@ -4849,6 +4910,15 @@ snapshots: transitivePeerDependencies: - '@types/node' + '@rushstack/typings-generator@file:../../../libraries/typings-generator(@types/node@20.17.19)': + dependencies: + '@rushstack/node-core-library': file:../../../libraries/node-core-library(@types/node@20.17.19) + '@rushstack/terminal': file:../../../libraries/terminal(@types/node@20.17.19) + chokidar: 3.6.0 + fast-glob: 3.3.3 + optionalDependencies: + '@types/node': 20.17.19 + '@sinclair/typebox@0.27.8': {} '@sinclair/typebox@0.34.48': {} @@ -4927,6 +4997,8 @@ snapshots: '@types/json5@0.0.29': {} + '@types/lodash@4.17.23': {} + '@types/node@20.17.19': dependencies: undici-types: 6.19.8 @@ -5487,6 +5559,8 @@ snapshots: dependencies: is-windows: 1.0.2 + binary-extensions@2.3.0: {} + bl@4.1.0: dependencies: buffer: 5.7.1 @@ -5587,6 +5661,18 @@ snapshots: chardet@2.1.1: {} + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + chownr@3.0.0: {} chrome-trace-event@1.0.4: {} @@ -6222,6 +6308,10 @@ snapshots: dependencies: bser: 2.1.1 + fdir@6.5.0(picomatch@4.0.3): + optionalDependencies: + picomatch: 4.0.3 + figures@3.0.0: dependencies: escape-string-regexp: 1.0.5 @@ -6512,6 +6602,10 @@ snapshots: dependencies: has-bigints: 1.1.0 + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + is-boolean-object@1.2.2: dependencies: call-bound: 1.0.4 @@ -7077,6 +7171,18 @@ snapshots: json-parse-even-better-errors@2.3.1: {} + json-schema-to-typescript@15.0.4: + dependencies: + '@apidevtools/json-schema-ref-parser': 11.9.3 + '@types/json-schema': 7.0.15 + '@types/lodash': 4.17.23 + is-glob: 4.0.3 + js-yaml: 4.1.1 + lodash: 4.17.23 + minimist: 1.2.8 + prettier: 3.8.1 + tinyglobby: 0.2.15 + json-schema-traverse@0.4.1: {} json-schema-traverse@1.0.0: {} @@ -7166,6 +7272,7 @@ snapshots: '@microsoft/api-extractor': file:../../../apps/api-extractor(@types/node@20.17.19) '@rushstack/eslint-patch': file:../../../eslint/eslint-patch '@rushstack/heft': file:../../../apps/heft(@types/node@20.17.19) + '@rushstack/heft-json-schema-typings-plugin': file:../../../heft-plugins/heft-json-schema-typings-plugin(@rushstack/heft@file:../../../apps/heft(@types/node@20.17.19))(@types/node@20.17.19) '@rushstack/heft-node-rig': file:../../../rigs/heft-node-rig(@rushstack/heft@file:../../../apps/heft(@types/node@20.17.19))(@types/node@20.17.19) '@types/heft-jest': 1.0.1 '@types/node': 20.17.19 @@ -7252,10 +7359,6 @@ snapshots: mimic-fn@3.1.0: {} - minimatch@10.1.2: - dependencies: - '@isaacs/brace-expansion': 5.0.1 - minimatch@10.2.1: dependencies: brace-expansion: 5.0.2 @@ -7542,6 +7645,8 @@ snapshots: prelude-ls@1.2.1: {} + prettier@3.8.1: {} + pretty-error@4.0.0: dependencies: lodash: 4.17.23 @@ -7626,6 +7731,10 @@ snapshots: graceful-fs: 4.2.11 once: 1.4.0 + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + reflect.getprototypeof@1.0.10: dependencies: call-bind: 1.0.8 @@ -8026,6 +8135,11 @@ snapshots: through@2.3.8: {} + tinyglobby@0.2.15: + dependencies: + fdir: 6.5.0(picomatch@4.0.3) + picomatch: 4.0.3 + tmpl@1.0.5: {} to-regex-range@5.0.1: diff --git a/common/config/subspaces/build-tests-subspace/repo-state.json b/common/config/subspaces/build-tests-subspace/repo-state.json index 63190118101..4c6bad01b93 100644 --- a/common/config/subspaces/build-tests-subspace/repo-state.json +++ b/common/config/subspaces/build-tests-subspace/repo-state.json @@ -1,6 +1,6 @@ // DO NOT MODIFY THIS FILE MANUALLY BUT DO COMMIT IT. It is generated and used by Rush. { - "pnpmShrinkwrapHash": "970749d264e69bf8ff6a9fb6007b379832c9ac09", + "pnpmShrinkwrapHash": "6972816c9d6f6511a8df09c9ad08d647c6c16ff1", "preferredVersionsHash": "550b4cee0bef4e97db6c6aad726df5149d20e7d9", - "packageJsonInjectedDependenciesHash": "0124c511e290517bf309935112b2dbab981575bb" + "packageJsonInjectedDependenciesHash": "57a16de99cf9519f84d13159d3a087d48ae710d7" } diff --git a/common/config/subspaces/default/pnpm-lock.yaml b/common/config/subspaces/default/pnpm-lock.yaml index b992ec346ba..2f446ba1698 100644 --- a/common/config/subspaces/default/pnpm-lock.yaml +++ b/common/config/subspaces/default/pnpm-lock.yaml @@ -3280,12 +3280,12 @@ importers: '@rushstack/terminal': specifier: workspace:* version: link:../../libraries/terminal + decoupled-local-node-rig: + specifier: workspace:* + version: link:../../rigs/decoupled-local-node-rig eslint: specifier: ~9.37.0 version: 9.37.0 - local-node-rig: - specifier: workspace:* - version: link:../../rigs/local-node-rig ../../../heft-plugins/heft-lint-plugin: dependencies: @@ -4481,12 +4481,12 @@ importers: '@rushstack/heft': specifier: workspace:* version: link:../../apps/heft + decoupled-local-node-rig: + specifier: workspace:* + version: link:../../rigs/decoupled-local-node-rig eslint: specifier: ~9.37.0 version: 9.37.0 - local-node-rig: - specifier: workspace:* - version: link:../../rigs/local-node-rig ../../../libraries/worker-pool: devDependencies: @@ -4585,6 +4585,9 @@ importers: '@rushstack/heft': specifier: 1.2.0 version: 1.2.0(@types/node@20.17.19) + '@rushstack/heft-json-schema-typings-plugin': + specifier: 1.2.0 + version: 1.2.0(@rushstack/heft@1.2.0(@types/node@20.17.19))(@types/node@20.17.19) '@rushstack/heft-node-rig': specifier: 2.11.20 version: 2.11.20(@rushstack/heft@1.2.0(@types/node@20.17.19))(@types/node@20.17.19)(jest-environment-jsdom@29.5.0) @@ -4801,6 +4804,9 @@ importers: '@rushstack/heft': specifier: workspace:* version: link:../../apps/heft + '@rushstack/heft-json-schema-typings-plugin': + specifier: workspace:* + version: link:../../heft-plugins/heft-json-schema-typings-plugin '@rushstack/heft-node-rig': specifier: workspace:* version: link:../heft-node-rig @@ -4834,6 +4840,9 @@ importers: '@rushstack/heft': specifier: workspace:* version: link:../../apps/heft + '@rushstack/heft-json-schema-typings-plugin': + specifier: workspace:* + version: link:../../heft-plugins/heft-json-schema-typings-plugin '@rushstack/heft-web-rig': specifier: workspace:* version: link:../heft-web-rig @@ -9021,6 +9030,11 @@ packages: jest-environment-node: optional: true + '@rushstack/heft-json-schema-typings-plugin@1.2.0': + resolution: {integrity: sha512-mIJplAzTnhq4Z5TND/ZRMElrGP+8MtlACwvFBL4WfXjnbf96O5LH3m+HtEKpTGun9xuai8YWM2MY0etlcsDSPQ==} + peerDependencies: + '@rushstack/heft': 1.2.0 + '@rushstack/heft-lint-plugin@1.2.0': resolution: {integrity: sha512-Z7AxUTUHBH+MNmNAdBGTn7TawMLP5tU50hi+E9g/s0WaoHm6TD7CqrI1kPwELGZl4fnqPQHQsgkXC4P94FDDWQ==} peerDependencies: @@ -9101,6 +9115,14 @@ packages: '@rushstack/ts-command-line@5.3.0': resolution: {integrity: sha512-4hneaVxA5zPC8cwUGZtdvCUzGbW8A+b+qrBK3hYs/xO7TyWkgAMKxq/6FJY91fPG8awgmJ+s1w8GuqNXgxsTyw==} + '@rushstack/typings-generator@0.16.0': + resolution: {integrity: sha512-YH1IAbmi/XVEc/R8LwdZ2THhjzb0mdQjQVdaiH22alSryWNU6/vP6KAI5XY98iCnFyHd/tmZkIbj1StFf7pHhQ==} + peerDependencies: + '@types/node': '*' + peerDependenciesMeta: + '@types/node': + optional: true + '@rushstack/webpack-plugin-utilities@0.3.16': resolution: {integrity: sha512-0Xb0GESYEyv6Q7hzANZ8RIWa3seiJiCKBNNG83znQwMZ9l0bfnoJzZ3cYODkofoK0E8/nr4hTsn/pWKommf6Mw==} peerDependencies: @@ -24041,6 +24063,15 @@ snapshots: - supports-color - ts-node + '@rushstack/heft-json-schema-typings-plugin@1.2.0(@rushstack/heft@1.2.0(@types/node@20.17.19))(@types/node@20.17.19)': + dependencies: + '@rushstack/heft': 1.2.0(@types/node@20.17.19) + '@rushstack/node-core-library': 5.20.0(@types/node@20.17.19) + '@rushstack/typings-generator': 0.16.0(@types/node@20.17.19) + json-schema-to-typescript: 15.0.4 + transitivePeerDependencies: + - '@types/node' + '@rushstack/heft-lint-plugin@1.2.0(@rushstack/heft@1.2.0(@types/node@20.17.19))(@types/node@20.17.19)': dependencies: '@rushstack/heft': 1.2.0(@types/node@20.17.19) @@ -24252,6 +24283,15 @@ snapshots: transitivePeerDependencies: - '@types/node' + '@rushstack/typings-generator@0.16.0(@types/node@20.17.19)': + dependencies: + '@rushstack/node-core-library': 5.20.0(@types/node@20.17.19) + '@rushstack/terminal': 0.22.0(@types/node@20.17.19) + chokidar: 3.6.0 + fast-glob: 3.3.3 + optionalDependencies: + '@types/node': 20.17.19 + '@rushstack/webpack-plugin-utilities@0.3.16(@types/webpack@4.41.32)(webpack@4.47.0)': dependencies: memfs: 3.4.3 @@ -30145,7 +30185,7 @@ snapshots: eslint@8.57.1: dependencies: - '@eslint-community/eslint-utils': 4.9.1(eslint@9.37.0) + '@eslint-community/eslint-utils': 4.9.1(eslint@8.57.1) '@eslint-community/regexpp': 4.12.2 '@eslint/eslintrc': 2.1.4 '@eslint/js': 8.57.1 diff --git a/common/config/subspaces/default/repo-state.json b/common/config/subspaces/default/repo-state.json index 9b13d6b9d1a..25970caf43b 100644 --- a/common/config/subspaces/default/repo-state.json +++ b/common/config/subspaces/default/repo-state.json @@ -1,5 +1,5 @@ // DO NOT MODIFY THIS FILE MANUALLY BUT DO COMMIT IT. It is generated and used by Rush. { - "pnpmShrinkwrapHash": "425296840bc63395649600913e66041583bdc287", + "pnpmShrinkwrapHash": "07d9d2f7d978e6063fed9d72f4b58218ffdff71d", "preferredVersionsHash": "93bf435032db8da4a18734f1eaa359c12ad147c1" } diff --git a/common/reviews/api/credential-cache.api.md b/common/reviews/api/credential-cache.api.md index f6563cc246a..01e18b11f54 100644 --- a/common/reviews/api/credential-cache.api.md +++ b/common/reviews/api/credential-cache.api.md @@ -27,15 +27,20 @@ export class CredentialCache implements Disposable { } // @public (undocumented) -export interface ICredentialCacheEntry { - // (undocumented) - credential: string; - // (undocumented) - credentialMetadata?: object; +export interface ICredentialCacheEntry extends Omit { // (undocumented) expires?: Date; } +// @public +export interface ICredentialCacheEntryJson { + credential: string; + credentialMetadata?: { + [k: string]: unknown; + }; + expires: number; +} + // @public (undocumented) export interface ICredentialCacheOptions { // (undocumented) diff --git a/common/reviews/api/heft-typescript-plugin.api.md b/common/reviews/api/heft-typescript-plugin.api.md index 2e42af718cc..436c37e2d66 100644 --- a/common/reviews/api/heft-typescript-plugin.api.md +++ b/common/reviews/api/heft-typescript-plugin.api.md @@ -41,11 +41,7 @@ export interface _ICompilerCapabilities { // @beta (undocumented) export interface IEmitModuleKind { - // (undocumented) - jsExtensionOverride?: string; - // (undocumented) - moduleKind: 'commonjs' | 'amd' | 'umd' | 'system' | 'es2015' | 'esnext'; - // (undocumented) + moduleKind: "commonjs" | "amd" | "umd" | "system" | "es2015" | "esnext"; outFolderName: string; } @@ -96,25 +92,23 @@ export interface IPartialTsconfigCompilerOptions { } // @beta (undocumented) -export interface IStaticAssetsCopyConfiguration { - // (undocumented) - excludeGlobs: string[]; - // (undocumented) - fileExtensions: string[]; - // (undocumented) - includeGlobs: string[]; -} +export type IStaticAssetsCopyConfiguration = ITypeScriptConfigurationJson['staticAssetsToCopy']; -// @beta (undocumented) +// @beta export interface ITypeScriptConfigurationJson { - additionalModuleKindsToEmit?: IEmitModuleKind[] | undefined; + $schema?: string; + additionalModuleKindsToEmit?: IEmitModuleKind[]; buildProjectReferences?: boolean; - emitCjsExtensionForCommonJS?: boolean | undefined; - emitMjsExtensionForESModule?: boolean | undefined; + emitCjsExtensionForCommonJS?: boolean; + emitMjsExtensionForESModule?: boolean; + extends?: string; onlyResolveSymlinksInNodeModules?: boolean; - // (undocumented) project?: string; - staticAssetsToCopy?: IStaticAssetsCopyConfiguration; + staticAssetsToCopy?: { + fileExtensions?: string[]; + excludeGlobs?: string[]; + includeGlobs?: string[]; + }; useTranspilerWorker?: boolean; } diff --git a/common/reviews/api/heft.api.md b/common/reviews/api/heft.api.md index 96f4281126f..702d957fd6b 100644 --- a/common/reviews/api/heft.api.md +++ b/common/reviews/api/heft.api.md @@ -102,14 +102,30 @@ export class HeftConfiguration { } // @public -export interface ICopyOperation extends IFileSelectionSpecifier { +export interface ICopyOperation extends IFileSelectionSpecifier, ICopyOperationBase { +} + +// @public +export interface ICopyOperationBase { destinationFolders: string[]; + excludeGlobs?: string[]; + fileExtensions?: string[]; flatten?: boolean; hardlink?: boolean; + includeGlobs?: string[]; + sourcePath?: string; } // @public -export interface IDeleteOperation extends IFileSelectionSpecifier { +export interface IDeleteOperation extends IFileSelectionSpecifier, IDeleteOperationBase { +} + +// @public +export interface IDeleteOperationBase { + excludeGlobs?: string[]; + fileExtensions?: string[]; + includeGlobs?: string[]; + sourcePath?: string; } // @public @@ -377,7 +393,7 @@ export interface IRunScriptOptions { // (undocumented) runOptions: IHeftTaskRunHookOptions; // (undocumented) - scriptOptions: Record; + scriptOptions: Record | undefined; } // @public diff --git a/common/reviews/api/node-core-library.api.md b/common/reviews/api/node-core-library.api.md index c5b2ebe4f9b..8bee22d8cd6 100644 --- a/common/reviews/api/node-core-library.api.md +++ b/common/reviews/api/node-core-library.api.md @@ -743,7 +743,7 @@ export class JsonSchema { } // @public -export type JsonSchemaVersion = 'draft-04' | 'draft-07'; +export type JsonSchemaVersion = 'draft-04' | 'draft-07' | 'draft-2019-09'; // @public export enum JsonSyntax { diff --git a/common/reviews/api/rig-package.api.md b/common/reviews/api/rig-package.api.md index d79f609abb6..7071fe549dd 100644 --- a/common/reviews/api/rig-package.api.md +++ b/common/reviews/api/rig-package.api.md @@ -28,6 +28,7 @@ export interface IRigConfig { // @public export interface IRigConfigJson { + $schema?: string; rigPackageName: string; rigProfile?: string; } diff --git a/common/reviews/api/rush-azure-storage-build-cache-plugin.api.md b/common/reviews/api/rush-azure-storage-build-cache-plugin.api.md index 26f39c4993a..3d53aed9cc5 100644 --- a/common/reviews/api/rush-azure-storage-build-cache-plugin.api.md +++ b/common/reviews/api/rush-azure-storage-build-cache-plugin.api.md @@ -103,7 +103,9 @@ export interface IAzureStorageAuthenticationOptions extends IAzureAuthentication // @public (undocumented) export interface ICredentialResult { // (undocumented) - credentialMetadata?: object; + credentialMetadata?: { + [k: string]: unknown; + }; // (undocumented) credentialString: string; // (undocumented) diff --git a/common/reviews/api/rush-lib.api.md b/common/reviews/api/rush-lib.api.md index 1f8def84f93..c7e5aa1bc02 100644 --- a/common/reviews/api/rush-lib.api.md +++ b/common/reviews/api/rush-lib.api.md @@ -369,13 +369,12 @@ export interface ICobuildContext { runnerId: string; } -// @beta (undocumented) -export interface ICobuildJson { - // (undocumented) +// @beta +export type ICobuildJson = { + $schema?: string; cobuildFeatureEnabled: boolean; - // (undocumented) cobuildLockProvider: string; -} +}; // @beta (undocumented) export interface ICobuildLockProvider { @@ -462,6 +461,7 @@ export interface IExecutionResult { // @beta export interface IExperimentsJson { + $schema?: string; allowCobuildWithoutCache?: boolean; buildCacheWithAllowWarningsInSuccessfulBuild?: boolean; buildSkipWithAllowWarningsInSuccessfulBuild?: boolean; @@ -473,6 +473,7 @@ export interface IExperimentsJson { noChmodFieldInTarHeaderNormalization?: boolean; omitAppleDoubleFilesFromBuildCache?: boolean; omitImportersFromPreventManualShrinkwrapChanges?: boolean; + phasedCommands?: boolean; printEventHooksOutputToConsole?: boolean; rushAlerts?: boolean; useIPCScriptsInWatchMode?: boolean; diff --git a/heft-plugins/heft-api-extractor-plugin/src/ApiExtractorPlugin.ts b/heft-plugins/heft-api-extractor-plugin/src/ApiExtractorPlugin.ts index 8ab77d46808..b78c23b69a5 100644 --- a/heft-plugins/heft-api-extractor-plugin/src/ApiExtractorPlugin.ts +++ b/heft-plugins/heft-api-extractor-plugin/src/ApiExtractorPlugin.ts @@ -13,6 +13,7 @@ import type { import { invokeApiExtractorAsync } from './ApiExtractorRunner'; import apiExtractorConfigSchema from './schemas/api-extractor-task.schema.json'; +import type { APIExtractorTaskConfiguration } from './schemas/api-extractor-task.schema.json.d.ts'; // eslint-disable-next-line @rushstack/no-new-null const UNINITIALIZED: null = null; @@ -23,7 +24,7 @@ const EXTRACTOR_CONFIG_FILENAME: typeof TApiExtractor.ExtractorConfig.FILENAME = const LEGACY_EXTRACTOR_CONFIG_RELATIVE_PATH: string = `./${EXTRACTOR_CONFIG_FILENAME}`; const EXTRACTOR_CONFIG_RELATIVE_PATH: string = `./config/${EXTRACTOR_CONFIG_FILENAME}`; -const API_EXTRACTOR_CONFIG_SPECIFICATION: ConfigurationFile.IProjectConfigurationFileSpecification = +const API_EXTRACTOR_CONFIG_SPECIFICATION: ConfigurationFile.IProjectConfigurationFileSpecification = { projectRelativeFilePath: TASK_CONFIG_RELATIVE_PATH, jsonSchemaObject: apiExtractorConfigSchema @@ -34,34 +35,6 @@ export interface IApiExtractorConfigurationResult { apiExtractorConfiguration: TApiExtractor.ExtractorConfig; } -export interface IApiExtractorTaskConfiguration { - /** - * If set to true, use the project's TypeScript compiler version for API Extractor's - * analysis. API Extractor's included TypeScript compiler can generally correctly - * analyze typings generated by older compilers, and referencing the project's compiler - * can cause issues. If issues are encountered with API Extractor's included compiler, - * set this option to true. - * - * This corresponds to API Extractor's `--typescript-compiler-folder` CLI option and - * `IExtractorInvokeOptions.typescriptCompilerFolder` API option. This option defaults to false. - */ - useProjectTypescriptVersion?: boolean; - - /** - * If set to true, do a full run of api-extractor on every build. - */ - runInWatchMode?: boolean; - - /** - * Controls whether API Extractor prints a diff of the API report file if it's changed. - * If set to `"production"`, this will only be printed if Heft is run in `--production` - * mode, and if set to `"always"`, this will always be printed if the API report is changed. - * This corresponds to API Extractor's `IExtractorInvokeOptions.printApiReportDiff` API option. - * This option defaults to `"never"`. - */ - printApiReportDiff?: 'production' | 'always' | 'never'; -} - export default class ApiExtractorPlugin implements IHeftTaskPlugin { private _apiExtractor: typeof TApiExtractor | undefined; private _apiExtractorConfigurationFilePath: string | undefined | typeof UNINITIALIZED = UNINITIALIZED; diff --git a/heft-plugins/heft-isolated-typescript-transpile-plugin/heft-plugin.json b/heft-plugins/heft-isolated-typescript-transpile-plugin/heft-plugin.json index e94bf9c0815..1ada2fe4d39 100644 --- a/heft-plugins/heft-isolated-typescript-transpile-plugin/heft-plugin.json +++ b/heft-plugins/heft-isolated-typescript-transpile-plugin/heft-plugin.json @@ -5,7 +5,7 @@ { "pluginName": "swc-isolated-transpile-plugin", "entryPoint": "./lib-commonjs/SwcIsolatedTranspilePlugin", - "optionsSchema": "./lib-commonjs/schemas/swc-isolated-transpile-plugin.schema.json" + "optionsSchema": "./lib-commonjs/schemas/swc-isolated-transpile-plugin-options.schema.json" } ] } diff --git a/heft-plugins/heft-isolated-typescript-transpile-plugin/src/SwcIsolatedTranspilePlugin.ts b/heft-plugins/heft-isolated-typescript-transpile-plugin/src/SwcIsolatedTranspilePlugin.ts index 2dd940fc342..987bce82d95 100644 --- a/heft-plugins/heft-isolated-typescript-transpile-plugin/src/SwcIsolatedTranspilePlugin.ts +++ b/heft-plugins/heft-isolated-typescript-transpile-plugin/src/SwcIsolatedTranspilePlugin.ts @@ -33,19 +33,16 @@ import { _getTsconfigFilePath as getTsconfigFilePath } from '@rushstack/heft-typescript-plugin'; -import type { - ISwcIsolatedTranspileOptions, - IWorkerResult, - ITransformTask, - IEmitKind, - ITransformModulesRequestMessage -} from './types'; +import type { SwcIsolatedTranspilePluginOptions } from './schemas/swc-isolated-transpile-plugin-options.schema.json.d.ts'; +import type { IWorkerResult, ITransformTask, ITransformModulesRequestMessage } from './types'; /** * @public */ export type ModuleKind = keyof typeof TTypeScript.ModuleKind; +type IEmitKind = Required['emitKinds'][number]; + const TSC_TO_SWC_MODULE_MAP: Record = { CommonJS: 'commonjs', ES2015: 'es6', @@ -105,7 +102,9 @@ export interface ISwcIsolatedTranspilePluginAccessor { /** * @public */ -export default class SwcIsolatedTranspilePlugin implements IHeftTaskPlugin { +export default class SwcIsolatedTranspilePlugin + implements IHeftTaskPlugin +{ /** * @beta */ @@ -122,7 +121,7 @@ export default class SwcIsolatedTranspilePlugin implements IHeftTaskPlugin { const { logger } = heftSession; @@ -146,7 +145,7 @@ export default class SwcIsolatedTranspilePlugin implements IHeftTaskPlugin IWatchFileSystem) | undefined diff --git a/heft-plugins/heft-isolated-typescript-transpile-plugin/src/schemas/swc-isolated-transpile-plugin-options.schema.json b/heft-plugins/heft-isolated-typescript-transpile-plugin/src/schemas/swc-isolated-transpile-plugin-options.schema.json new file mode 100644 index 00000000000..01042dab791 --- /dev/null +++ b/heft-plugins/heft-isolated-typescript-transpile-plugin/src/schemas/swc-isolated-transpile-plugin-options.schema.json @@ -0,0 +1,77 @@ +{ + "type": "object", + "additionalProperties": false, + "properties": { + "$schema": { + "description": "Part of the JSON Schema standard, this optional keyword declares the URL of the schema that the file conforms to. Editors may download the schema and use it to perform syntax highlighting.", + "type": "string" + }, + + "extends": { + "description": "Optionally specifies another JSON config file that this file extends from. This provides a way for standard settings to be shared across multiple projects.", + "type": "string" + }, + + "tsConfigPath": { + "type": "string", + "description": "The path to the tsconfig.json file" + }, + + "emitKinds": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "required": ["outDir", "formatOverride", "targetOverride"], + "properties": { + "outDir": { + "type": "string", + "description": "The output directory for the transpiled files" + }, + + "formatOverride": { + "type": "string", + "description": "The output format for transpiled files. See type ModuleKind in TypeScript for valid values.", + "enum": [ + "None", + "CommonJS", + "AMD", + "UMD", + "System", + "ES2015", + "ES2020", + "ES2022", + "ESNext", + "Node16", + "Node18", + "NodeNext", + "Preserve" + ] + }, + + "targetOverride": { + "type": "string", + "description": "The target for transpiled files. See type ScriptTarget in TypeScript for valid values.", + "enum": [ + "ES2015", + "ES2020", + "ES2022", + "ESNext", + "ES3", + "ES5", + "ES2016", + "ES2017", + "ES2018", + "ES2019", + "ES2021", + "ES2023", + "ES2024", + "JSON", + "Latest" + ] + } + } + } + } + } +} diff --git a/heft-plugins/heft-isolated-typescript-transpile-plugin/src/schemas/swc-isolated-transpile-plugin.schema.json b/heft-plugins/heft-isolated-typescript-transpile-plugin/src/schemas/swc-isolated-transpile-plugin.schema.json deleted file mode 100644 index f87ab47a031..00000000000 --- a/heft-plugins/heft-isolated-typescript-transpile-plugin/src/schemas/swc-isolated-transpile-plugin.schema.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "type": "object", - "additionalProperties": false, - "properties": { - "tsConfigPath": { - "type": "string", - "description": "The path to the tsconfig.json file" - }, - "emitKinds": { - "type": "array", - "items": { - "type": "object", - "additionalProperties": false, - "required": ["outDir", "formatOverride", "targetOverride"], - "properties": { - "outDir": { - "type": "string", - "description": "The output directory for the transpiled files" - }, - "formatOverride": { - "type": "string", - "description": "The output format for transpiled files. See type ModuleKind in TypeScript for valid values." - }, - "targetOverride": { - "type": "string", - "description": "The target for transpiled files. See type ScriptTarget in TypeScript for valid values." - } - } - } - } - } -} diff --git a/heft-plugins/heft-isolated-typescript-transpile-plugin/src/types.ts b/heft-plugins/heft-isolated-typescript-transpile-plugin/src/types.ts index 0926fba7f7e..2ae4eba9155 100644 --- a/heft-plugins/heft-isolated-typescript-transpile-plugin/src/types.ts +++ b/heft-plugins/heft-isolated-typescript-transpile-plugin/src/types.ts @@ -1,23 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See LICENSE in the project root for license information. -import type { ModuleKind, ScriptTarget } from './SwcIsolatedTranspilePlugin'; - export interface IProjectOptions { buildFolder: string; } -export interface IEmitKind { - outDir: string; - formatOverride: ModuleKind; - targetOverride: ScriptTarget; -} - -export interface ISwcIsolatedTranspileOptions { - tsConfigPath?: string; - emitKinds?: IEmitKind[]; -} - export interface IWorkerData { buildFolderPath: string; concurrency: number; diff --git a/heft-plugins/heft-jest-plugin/heft-plugin.json b/heft-plugins/heft-jest-plugin/heft-plugin.json index 52c65540566..ae446f1f008 100644 --- a/heft-plugins/heft-jest-plugin/heft-plugin.json +++ b/heft-plugins/heft-jest-plugin/heft-plugin.json @@ -5,7 +5,7 @@ { "pluginName": "jest-plugin", "entryPoint": "./lib-commonjs/JestPlugin", - "optionsSchema": "./lib-commonjs/schemas/heft-jest-plugin.schema.json", + "optionsSchema": "./lib-commonjs/schemas/heft-jest-plugin-options.schema.json", "parameterScope": "jest", "parameters": [ diff --git a/heft-plugins/heft-jest-plugin/src/JestPlugin.ts b/heft-plugins/heft-jest-plugin/src/JestPlugin.ts index 5bf31ed257e..4935be7046f 100644 --- a/heft-plugins/heft-jest-plugin/src/JestPlugin.ts +++ b/heft-plugins/heft-jest-plugin/src/JestPlugin.ts @@ -37,6 +37,7 @@ import type { ITerminal } from '@rushstack/terminal'; import type { IHeftJestReporterOptions } from './HeftJestReporter'; import { jestResolve } from './JestUtils'; import { TerminalWritableStream } from './TerminalWritableStream'; +import type { HeftJestPluginOptionsConfiguration } from './schemas/heft-jest-plugin-options.schema.json.d.ts'; import anythingSchema from './schemas/anything.schema.json'; const jestPluginSymbol: unique symbol = Symbol('heft-jest-plugin'); @@ -90,13 +91,10 @@ interface IJestResolutionOptions { /** * Options that can be provided to the plugin. */ -export interface IJestPluginOptions { - configurationPath?: string; +export interface IJestPluginOptions extends HeftJestPluginOptionsConfiguration { debugHeftReporter?: boolean; detectOpenHandles?: boolean; disableCodeCoverage?: boolean; - disableConfigurationModuleResolution?: boolean; - enableNodeEnvManagement?: boolean; findRelatedTests?: string[]; maxWorkers?: string; passWithNoTests?: boolean; diff --git a/heft-plugins/heft-jest-plugin/src/schemas/heft-jest-plugin.schema.json b/heft-plugins/heft-jest-plugin/src/schemas/heft-jest-plugin-options.schema.json similarity index 94% rename from heft-plugins/heft-jest-plugin/src/schemas/heft-jest-plugin.schema.json rename to heft-plugins/heft-jest-plugin/src/schemas/heft-jest-plugin-options.schema.json index af5a94ddccd..b6b8ba1e307 100644 --- a/heft-plugins/heft-jest-plugin/src/schemas/heft-jest-plugin.schema.json +++ b/heft-plugins/heft-jest-plugin/src/schemas/heft-jest-plugin-options.schema.json @@ -1,7 +1,7 @@ { "$schema": "http://json-schema.org/draft-04/schema#", "title": "Heft Jest Plugin Options Configuration", - "description": "This schema describes the \"options\" field that can be specified in heft.json when loading \"@rushstack/heft-jest-plugin\".", + "description": "This schema describes the \"options\" field that can be specified in heft.json when loading `@rushstack/heft-jest-plugin`.", "type": "object", "additionalProperties": false, diff --git a/heft-plugins/heft-json-schema-typings-plugin/config/heft.json b/heft-plugins/heft-json-schema-typings-plugin/config/heft.json index 0e52387039a..8d1359f022f 100644 --- a/heft-plugins/heft-json-schema-typings-plugin/config/heft.json +++ b/heft-plugins/heft-json-schema-typings-plugin/config/heft.json @@ -1,6 +1,6 @@ { "$schema": "https://developer.microsoft.com/json-schemas/heft/v0/heft.schema.json", - "extends": "local-node-rig/profiles/default/config/heft.json", + "extends": "decoupled-local-node-rig/profiles/default/config/heft.json", "phasesByName": { "build": { diff --git a/heft-plugins/heft-json-schema-typings-plugin/config/jest.config.json b/heft-plugins/heft-json-schema-typings-plugin/config/jest.config.json index 7b2eb73199f..4b94b1ba368 100644 --- a/heft-plugins/heft-json-schema-typings-plugin/config/jest.config.json +++ b/heft-plugins/heft-json-schema-typings-plugin/config/jest.config.json @@ -1,5 +1,5 @@ { - "extends": "local-node-rig/profiles/default/config/jest.config.json", + "extends": "decoupled-local-node-rig/profiles/default/config/jest.config.json", "moduleNameMapper": { "^prettier$": "/jestMocks/prettier.js" } diff --git a/heft-plugins/heft-json-schema-typings-plugin/config/rig.json b/heft-plugins/heft-json-schema-typings-plugin/config/rig.json index 165ffb001f5..cc98dea43dd 100644 --- a/heft-plugins/heft-json-schema-typings-plugin/config/rig.json +++ b/heft-plugins/heft-json-schema-typings-plugin/config/rig.json @@ -3,5 +3,5 @@ // Documentation for this system: https://www.npmjs.com/package/@rushstack/rig-package "$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json", - "rigPackageName": "local-node-rig" + "rigPackageName": "decoupled-local-node-rig" } diff --git a/heft-plugins/heft-json-schema-typings-plugin/eslint.config.js b/heft-plugins/heft-json-schema-typings-plugin/eslint.config.js index c15e6077310..e54effd122a 100644 --- a/heft-plugins/heft-json-schema-typings-plugin/eslint.config.js +++ b/heft-plugins/heft-json-schema-typings-plugin/eslint.config.js @@ -1,8 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See LICENSE in the project root for license information. -const nodeTrustedToolProfile = require('local-node-rig/profiles/default/includes/eslint/flat/profile/node-trusted-tool'); -const friendlyLocalsMixin = require('local-node-rig/profiles/default/includes/eslint/flat/mixins/friendly-locals'); +const nodeTrustedToolProfile = require('decoupled-local-node-rig/profiles/default/includes/eslint/flat/profile/node-trusted-tool'); +const friendlyLocalsMixin = require('decoupled-local-node-rig/profiles/default/includes/eslint/flat/mixins/friendly-locals'); module.exports = [ ...nodeTrustedToolProfile, diff --git a/heft-plugins/heft-json-schema-typings-plugin/heft-plugin.json b/heft-plugins/heft-json-schema-typings-plugin/heft-plugin.json index 9d40b9828d2..69601f333cb 100644 --- a/heft-plugins/heft-json-schema-typings-plugin/heft-plugin.json +++ b/heft-plugins/heft-json-schema-typings-plugin/heft-plugin.json @@ -5,7 +5,7 @@ { "pluginName": "json-schema-typings-plugin", "entryPoint": "./lib-commonjs/JsonSchemaTypingsPlugin", - "optionsSchema": "./lib-commonjs/schemas/heft-json-schema-typings-plugin.schema.json" + "optionsSchema": "./lib-commonjs/schemas/heft-json-schema-typings-plugin-options.schema.json" } ] } diff --git a/heft-plugins/heft-json-schema-typings-plugin/package.json b/heft-plugins/heft-json-schema-typings-plugin/package.json index 0ea0582db8d..62edfb7e8a1 100644 --- a/heft-plugins/heft-json-schema-typings-plugin/package.json +++ b/heft-plugins/heft-json-schema-typings-plugin/package.json @@ -27,7 +27,7 @@ "@rushstack/heft": "workspace:*", "@rushstack/terminal": "workspace:*", "eslint": "~9.37.0", - "local-node-rig": "workspace:*" + "decoupled-local-node-rig": "workspace:*" }, "exports": { "./lib/*.schema.json": "./lib-commonjs/*.schema.json", diff --git a/heft-plugins/heft-json-schema-typings-plugin/src/JsonSchemaTypingsGenerator.ts b/heft-plugins/heft-json-schema-typings-plugin/src/JsonSchemaTypingsGenerator.ts index deb30f2742b..59f10ace9ac 100644 --- a/heft-plugins/heft-json-schema-typings-plugin/src/JsonSchemaTypingsGenerator.ts +++ b/heft-plugins/heft-json-schema-typings-plugin/src/JsonSchemaTypingsGenerator.ts @@ -60,6 +60,15 @@ export class JsonSchemaTypingsGenerator extends TypingsGenerator { format: formatWithPrettier }); + // The json-schema-to-typescript library generates JSDoc comments containing + // inline values that may include "@" characters, such as: + // via the `patternProperty` "^@[^\s]*$". + // TSDoc interprets "@" as a tag indicator, causing parse warnings. + // Wrap double-quoted values in backtick code spans to prevent this issue. + // Use " +" for the leading whitespace so this matches at any JSDoc indentation + // level (e.g. top-level " * ..." or nested " * ..."). + typings = typings.replace(/^( +\* .+`(?:patternProperty|definition)`) "([^"]+)"/gm, '$1 `"$2"`'); + // Check for an "x-tsdoc-release-tag" property in the schema (e.g. "@public" or "@beta"). // If present, inject the tag into JSDoc comments for all exported declarations. if (tsdocReleaseTag) { diff --git a/heft-plugins/heft-json-schema-typings-plugin/src/JsonSchemaTypingsPlugin.ts b/heft-plugins/heft-json-schema-typings-plugin/src/JsonSchemaTypingsPlugin.ts index 877cd041b26..3d43b06e638 100644 --- a/heft-plugins/heft-json-schema-typings-plugin/src/JsonSchemaTypingsPlugin.ts +++ b/heft-plugins/heft-json-schema-typings-plugin/src/JsonSchemaTypingsPlugin.ts @@ -11,16 +11,10 @@ import type { import type { ITerminal } from '@rushstack/terminal'; import { JsonSchemaTypingsGenerator } from './JsonSchemaTypingsGenerator'; +import type { HeftJsonSchemaTypingsPluginOptions as IJsonSchemaTypingsPluginOptions } from './schemas/heft-json-schema-typings-plugin-options.schema.json'; const PLUGIN_NAME: 'json-schema-typings-plugin' = 'json-schema-typings-plugin'; -// TODO: Replace this with usage of this plugin after this plugin is published -export interface IJsonSchemaTypingsPluginOptions { - srcFolder?: string; - generatedTsFolders?: string[]; - formatWithPrettier?: boolean; -} - export default class JsonSchemaTypingsPlugin implements IHeftTaskPlugin { /** * Generate typings for JSON Schemas. diff --git a/heft-plugins/heft-json-schema-typings-plugin/src/schemas/heft-json-schema-typings-plugin.schema.json b/heft-plugins/heft-json-schema-typings-plugin/src/schemas/heft-json-schema-typings-plugin-options.schema.json similarity index 100% rename from heft-plugins/heft-json-schema-typings-plugin/src/schemas/heft-json-schema-typings-plugin.schema.json rename to heft-plugins/heft-json-schema-typings-plugin/src/schemas/heft-json-schema-typings-plugin-options.schema.json diff --git a/heft-plugins/heft-json-schema-typings-plugin/tsconfig.json b/heft-plugins/heft-json-schema-typings-plugin/tsconfig.json index dac21d04081..1a33d17b873 100644 --- a/heft-plugins/heft-json-schema-typings-plugin/tsconfig.json +++ b/heft-plugins/heft-json-schema-typings-plugin/tsconfig.json @@ -1,3 +1,3 @@ { - "extends": "./node_modules/local-node-rig/profiles/default/tsconfig-base.json" + "extends": "./node_modules/decoupled-local-node-rig/profiles/default/tsconfig-base.json" } diff --git a/heft-plugins/heft-lint-plugin/heft-plugin.json b/heft-plugins/heft-lint-plugin/heft-plugin.json index 13c0b3f3656..cc2330a6103 100644 --- a/heft-plugins/heft-lint-plugin/heft-plugin.json +++ b/heft-plugins/heft-lint-plugin/heft-plugin.json @@ -5,7 +5,7 @@ { "pluginName": "lint-plugin", "entryPoint": "./lib-commonjs/LintPlugin", - "optionsSchema": "./lib-commonjs/schemas/heft-lint-plugin.schema.json", + "optionsSchema": "./lib-commonjs/schemas/heft-lint-plugin-options.schema.json", "parameterScope": "lint", "parameters": [ diff --git a/heft-plugins/heft-lint-plugin/src/LintPlugin.ts b/heft-plugins/heft-lint-plugin/src/LintPlugin.ts index 74a4e384d97..be6aa73b0a4 100644 --- a/heft-plugins/heft-lint-plugin/src/LintPlugin.ts +++ b/heft-plugins/heft-lint-plugin/src/LintPlugin.ts @@ -23,6 +23,7 @@ import type { LinterBase } from './LinterBase'; import { Eslint } from './Eslint'; import { Tslint } from './Tslint'; import type { IExtendedProgram, IExtendedSourceFile } from './internalTypings/TypeScriptInternals'; +import type { HeftLintPluginOptionsConfiguration } from './schemas/heft-lint-plugin-options.schema.json.d.ts'; const PLUGIN_NAME: 'lint-plugin' = 'lint-plugin'; const TYPESCRIPT_PLUGIN_PACKAGE_NAME: '@rushstack/heft-typescript-plugin' = @@ -30,11 +31,6 @@ const TYPESCRIPT_PLUGIN_PACKAGE_NAME: '@rushstack/heft-typescript-plugin' = const TYPESCRIPT_PLUGIN_NAME: typeof TypeScriptPluginName = 'typescript-plugin'; const FIX_PARAMETER_NAME: string = '--fix'; -interface ILintPluginOptions { - alwaysFix?: boolean; - sarifLogPath?: string; -} - interface ILintOptions { taskSession: IHeftTaskSession; heftConfiguration: HeftConfiguration; @@ -44,7 +40,10 @@ interface ILintOptions { changedFiles?: ReadonlySet; } -function checkFix(taskSession: IHeftTaskSession, pluginOptions?: ILintPluginOptions): boolean { +function checkFix( + taskSession: IHeftTaskSession, + pluginOptions?: HeftLintPluginOptionsConfiguration +): boolean { let fix: boolean = pluginOptions?.alwaysFix || taskSession.parameters.getFlagParameter(FIX_PARAMETER_NAME).value; if (fix && taskSession.parameters.production) { @@ -60,7 +59,7 @@ function checkFix(taskSession: IHeftTaskSession, pluginOptions?: ILintPluginOpti function getSarifLogPath( heftConfiguration: HeftConfiguration, - pluginOptions?: ILintPluginOptions + pluginOptions?: HeftLintPluginOptionsConfiguration ): string | undefined { const relativeSarifLogPath: string | undefined = pluginOptions?.sarifLogPath; const sarifLogPath: string | undefined = @@ -68,7 +67,7 @@ function getSarifLogPath( return sarifLogPath; } -export default class LintPlugin implements IHeftTaskPlugin { +export default class LintPlugin implements IHeftTaskPlugin { // These are initliazed by _initAsync private _initPromise!: Promise; private _eslintToolPath: string | undefined; @@ -79,7 +78,7 @@ export default class LintPlugin implements IHeftTaskPlugin { public apply( taskSession: IHeftTaskSession, heftConfiguration: HeftConfiguration, - pluginOptions?: ILintPluginOptions + pluginOptions?: HeftLintPluginOptionsConfiguration ): void { // Disable linting in watch mode. Some lint rules require the context of multiple files, which // may not be available in watch mode. diff --git a/heft-plugins/heft-lint-plugin/src/schemas/heft-lint-plugin.schema.json b/heft-plugins/heft-lint-plugin/src/schemas/heft-lint-plugin-options.schema.json similarity index 92% rename from heft-plugins/heft-lint-plugin/src/schemas/heft-lint-plugin.schema.json rename to heft-plugins/heft-lint-plugin/src/schemas/heft-lint-plugin-options.schema.json index 072d2c70df6..ea8d04020a2 100644 --- a/heft-plugins/heft-lint-plugin/src/schemas/heft-lint-plugin.schema.json +++ b/heft-plugins/heft-lint-plugin/src/schemas/heft-lint-plugin-options.schema.json @@ -1,7 +1,7 @@ { "$schema": "http://json-schema.org/draft-04/schema#", "title": "Heft Lint Plugin Options Configuration", - "description": "This schema describes the \"options\" field that can be specified in heft.json when loading \"@rushstack/heft-lint-plugin\".", + "description": "This schema describes the \"options\" field that can be specified in heft.json when loading `@rushstack/heft-lint-plugin`.", "type": "object", "additionalProperties": false, diff --git a/heft-plugins/heft-localization-typings-plugin/src/LocalizationTypingsPlugin.ts b/heft-plugins/heft-localization-typings-plugin/src/LocalizationTypingsPlugin.ts index 5d71f8da9a7..2e9d80e2a4e 100644 --- a/heft-plugins/heft-localization-typings-plugin/src/LocalizationTypingsPlugin.ts +++ b/heft-plugins/heft-localization-typings-plugin/src/LocalizationTypingsPlugin.ts @@ -9,40 +9,9 @@ import type { IScopedLogger, IWatchedFileState } from '@rushstack/heft'; -import { type ITypingsGeneratorOptions, TypingsGenerator } from '@rushstack/localization-utilities'; +import { TypingsGenerator } from '@rushstack/localization-utilities'; -export interface ILocalizationTypingsPluginOptions { - /** - * Source code root directory. - * Defaults to "src/". - */ - srcFolder?: string; - - /** - * Output directory for generated typings. - * Defaults to "temp/loc-ts/". - */ - generatedTsFolder?: string; - - /** - * Folders, relative to the project root, where JSON files containing only the key/string pairs should be emitted to. - * These files will be emitted as `.resx.json`, `.loc.json`, or `.resjson`, depending on the input file extension. - * The intent is that bundlers can find these files and load them to receive the original untranslated strings. - */ - trimmedJsonOutputFolders?: string[]; - - /** - * Additional folders, relative to the project root, where the generated typings should be emitted to. - */ - secondaryGeneratedTsFolders?: string[]; - - exportAsDefault?: ITypingsGeneratorOptions['exportAsDefault']; - - /** - * An array of string names to ignore when generating typings. - */ - stringNamesToIgnore?: string[]; -} +import type { HeftLocalizationTypingsPluginOptions as ILocalizationTypingsPluginOptions } from './schemas/heft-localization-typings-plugin.schema.json.d.ts'; const PLUGIN_NAME: 'localization-typings-plugin' = 'localization-typings-plugin'; diff --git a/heft-plugins/heft-localization-typings-plugin/src/schemas/heft-localization-typings-plugin.schema.json b/heft-plugins/heft-localization-typings-plugin/src/schemas/heft-localization-typings-plugin.schema.json index ae9cf8f52c3..05d3f1f0afe 100644 --- a/heft-plugins/heft-localization-typings-plugin/src/schemas/heft-localization-typings-plugin.schema.json +++ b/heft-plugins/heft-localization-typings-plugin/src/schemas/heft-localization-typings-plugin.schema.json @@ -1,5 +1,6 @@ { "$schema": "http://json-schema.org/draft-04/schema#", + "title": "Heft Localization Typings Plugin Options", "type": "object", "additionalProperties": false, diff --git a/heft-plugins/heft-rspack-plugin/heft-plugin.json b/heft-plugins/heft-rspack-plugin/heft-plugin.json index cec21c0dfc3..f230ed4f925 100644 --- a/heft-plugins/heft-rspack-plugin/heft-plugin.json +++ b/heft-plugins/heft-rspack-plugin/heft-plugin.json @@ -5,7 +5,7 @@ { "pluginName": "rspack-plugin", "entryPoint": "./lib-commonjs/RspackPlugin", - "optionsSchema": "./lib-commonjs/schemas/heft-rspack-plugin.schema.json", + "optionsSchema": "./lib-commonjs/schemas/heft-rspack-plugin-options.schema.json", "parameterScope": "rspack", "parameters": [ diff --git a/heft-plugins/heft-rspack-plugin/src/RspackConfigurationLoader.ts b/heft-plugins/heft-rspack-plugin/src/RspackConfigurationLoader.ts index 98a6d37fdcf..bc8ad12a344 100644 --- a/heft-plugins/heft-rspack-plugin/src/RspackConfigurationLoader.ts +++ b/heft-plugins/heft-rspack-plugin/src/RspackConfigurationLoader.ts @@ -9,7 +9,7 @@ import type * as TRspack from '@rspack/core'; import type { HeftConfiguration, IHeftTaskSession } from '@rushstack/heft'; import { FileSystem } from '@rushstack/node-core-library'; -import type { IRspackPluginOptions } from './RspackPlugin'; +import type { RspackPluginConfiguration as IRspackPluginOptions } from './schemas/heft-rspack-plugin-options.schema.json.d.ts'; import { type IRspackConfiguration, type IRspackConfigurationFnEnvironment, diff --git a/heft-plugins/heft-rspack-plugin/src/RspackPlugin.ts b/heft-plugins/heft-rspack-plugin/src/RspackPlugin.ts index 67546a3e345..0a8682e9b20 100644 --- a/heft-plugins/heft-rspack-plugin/src/RspackPlugin.ts +++ b/heft-plugins/heft-rspack-plugin/src/RspackPlugin.ts @@ -27,11 +27,8 @@ import { } from './shared'; import { tryLoadRspackConfigurationAsync } from './RspackConfigurationLoader'; import { type DeferredWatchFileSystem, OverrideNodeWatchFSPlugin } from './DeferredWatchFileSystem'; +import type { RspackPluginConfiguration as IRspackPluginOptions } from './schemas/heft-rspack-plugin-options.schema.json.d.ts'; -export interface IRspackPluginOptions { - devConfigurationPath?: string | undefined; - configurationPath?: string | undefined; -} const SERVE_PARAMETER_LONG_NAME: '--serve' = '--serve'; const RSPACK_PACKAGE_NAME: '@rspack/core' = '@rspack/core'; const RSPACK_DEV_SERVER_PACKAGE_NAME: '@rspack/dev-server' = '@rspack/dev-server'; @@ -426,9 +423,7 @@ export default class RspackPlugin implements IHeftTaskPlugin { + cssOutputFolders: cssOutputFolders?.map((folder) => { const folderPath: string = typeof folder === 'string' ? folder : folder.folder; const shimModuleFormat: 'commonjs' | 'esnext' | undefined = typeof folder === 'string' ? undefined : folder.shimModuleFormat; diff --git a/heft-plugins/heft-sass-plugin/src/schemas/heft-sass-plugin.schema.json b/heft-plugins/heft-sass-plugin/src/schemas/heft-sass-plugin-options.schema.json similarity index 95% rename from heft-plugins/heft-sass-plugin/src/schemas/heft-sass-plugin.schema.json rename to heft-plugins/heft-sass-plugin/src/schemas/heft-sass-plugin-options.schema.json index 0ff5b533c91..1aa5ebdf3ac 100644 --- a/heft-plugins/heft-sass-plugin/src/schemas/heft-sass-plugin.schema.json +++ b/heft-plugins/heft-sass-plugin/src/schemas/heft-sass-plugin-options.schema.json @@ -1,7 +1,7 @@ { "$schema": "http://json-schema.org/draft-04/schema#", "title": "Sass Configuration", - "description": "This schema describes the \"config/sass.json\" config file used to configure \"@rushstack/heft-jest-plugin\", and also the \"options\" field that can be specified in heft.json when loading the plugin.", + "description": "This schema describes the \"config/sass.json\" config file used to configure `@rushstack/heft-jest-plugin`, and also the \"options\" field that can be specified in heft.json when loading the plugin.", "type": "object", "additionalProperties": false, diff --git a/heft-plugins/heft-storybook-plugin/heft-plugin.json b/heft-plugins/heft-storybook-plugin/heft-plugin.json index 107eca91df2..84aea41444f 100644 --- a/heft-plugins/heft-storybook-plugin/heft-plugin.json +++ b/heft-plugins/heft-storybook-plugin/heft-plugin.json @@ -5,7 +5,7 @@ { "pluginName": "storybook-plugin", "entryPoint": "./lib-commonjs/StorybookPlugin", - "optionsSchema": "./lib-commonjs/schemas/storybook.schema.json", + "optionsSchema": "./lib-commonjs/schemas/storybook-plugin-options.schema.json", "parameterScope": "storybook", "parameters": [ diff --git a/heft-plugins/heft-storybook-plugin/src/StorybookPlugin.ts b/heft-plugins/heft-storybook-plugin/src/StorybookPlugin.ts index 4b3939ac429..8000cf53c7c 100644 --- a/heft-plugins/heft-storybook-plugin/src/StorybookPlugin.ts +++ b/heft-plugins/heft-storybook-plugin/src/StorybookPlugin.ts @@ -35,6 +35,8 @@ import type { } from '@rushstack/heft-webpack5-plugin'; import type { IRspackPluginAccessor, PluginName as RspackPluginName } from '@rushstack/heft-rspack-plugin'; +import type { HeftStorybookPluginOptionsConfiguration } from './schemas/storybook-plugin-options.schema.json.d.ts'; + const PLUGIN_NAME: 'storybook-plugin' = 'storybook-plugin'; const WEBPACK4_PLUGIN_NAME: typeof Webpack4PluginName = 'webpack4-plugin'; const WEBPACK5_PLUGIN_NAME: typeof Webpack5PluginName = 'webpack5-plugin'; @@ -72,94 +74,6 @@ interface IStorybookCliCallingConfig { packageName: string; } -/** - * Options for `StorybookPlugin`. - * - * @public - */ -export interface IStorybookPluginOptions { - /** - * Specifies an NPM package that will provide the Storybook dependencies for the project. - * - * @example - * `"storykitPackageName": "my-react-storykit"` - * - * @remarks - * - * Storybook's conventional approach is for your app project to have direct dependencies - * on NPM packages such as `@storybook/react` and `@storybook/addon-essentials`. These packages have - * heavyweight dependencies such as Babel, Webpack, and the associated loaders and plugins needed to - * build the Storybook app (which is bundled completely independently from Heft). Naively adding these - * dependencies to your app's package.json muddies the waters of two radically different toolchains, - * and is likely to lead to dependency conflicts, for example if Heft installs Webpack 5 but - * `@storybook/react` installs Webpack 4. - * - * To solve this problem, `heft-storybook-plugin` introduces the concept of a separate - * "storykit package". All of your Storybook NPM packages are moved to be dependencies of the - * storykit. Storybook's browser API unfortunately isn't separated into dedicated NPM packages, - * but instead is exported by the Node.js toolchain packages such as `@storybook/react`. For - * an even cleaner separation the storykit package can simply reexport such APIs. - */ - storykitPackageName: string; - - /** - * Specify how the Storybook CLI should be invoked. Possible values: - * - * - "storybook6": For a static build, Heft will expect the cliPackageName package - * to define a binary command named "build-storybook". For the dev server mode, - * Heft will expect to find a binary command named "start-storybook". These commands - * must be declared in the "bin" section of package.json since Heft invokes the script directly. - * The output folder will be specified using the "--output-dir" CLI parameter. - * - * - "storybook7": Heft looks for a single binary command named "sb". It will be invoked as - * "sb build" for static builds, or "sb dev" for dev server mode. - * The output folder will be specified using the "--output-dir" CLI parameter. - * - * @defaultValue `storybook7` - */ - cliCallingConvention?: `${StorybookCliVersion}`; - - /** - * Specify the NPM package that provides the CLI binary to run. - * It will be resolved from the folder of your storykit package. - * - * @defaultValue - * The default is `@storybook/cli` when `cliCallingConvention` is `storybook7` - * and `@storybook/react` when `cliCallingConvention` is `storybook6` - */ - cliPackageName?: string; - - /** - * The customized output dir for storybook static build. - * If this is empty, then it will use the storybook default output dir. - * - * @example - * If you want to change the static build output dir to staticBuildDir, then the static build output dir would be: - * - * `"staticBuildOutputFolder": "newStaticBuildDir"` - */ - staticBuildOutputFolder?: string; - - /** - * Specifies an NPM dependency name that is used as the (cwd) target for the storybook commands - * By default the plugin executes the storybook commands in the local package context, - * but for distribution purposes it can be useful to split the TS library and storybook exports into two packages. - * - * @example - * If you create a storybook app project "my-ui-storybook-library-app" for the storybook preview distribution, - * and your main UI component library is my-ui-storybook-library. - * - * Your 'app' project is able to compile the 'library' storybook preview using the CWD target: - * - * `"cwdPackageName": "my-storybook-ui-library"` - */ - cwdPackageName?: string; - /** - * Specifies whether to capture the webpack stats for the storybook build by adding the `--webpack-stats-json` CLI flag. - */ - captureWebpackStats?: boolean; -} - interface IRunStorybookOptions extends IPrepareStorybookOptions { logger: IScopedLogger; isServeMode: boolean; @@ -170,7 +84,7 @@ interface IRunStorybookOptions extends IPrepareStorybookOptions { verbose: boolean; } -interface IPrepareStorybookOptions extends IStorybookPluginOptions { +interface IPrepareStorybookOptions extends HeftStorybookPluginOptionsConfiguration { logger: IScopedLogger; taskSession: IHeftTaskSession; heftConfiguration: HeftConfiguration; @@ -216,14 +130,14 @@ const STORYBOOK_TEST_FLAG_NAME: '--storybook-test' = '--storybook-test'; const DOCS_FLAG_NAME: '--docs' = '--docs'; /** @public */ -export default class StorybookPlugin implements IHeftTaskPlugin { +export default class StorybookPlugin implements IHeftTaskPlugin { /** * Generate typings for Sass files before TypeScript compilation. */ public apply( taskSession: IHeftTaskSession, heftConfiguration: HeftConfiguration, - options: IStorybookPluginOptions + options: HeftStorybookPluginOptionsConfiguration ): void { const logger: IScopedLogger = taskSession.logger; const storybookParameter: CommandLineFlagParameter = @@ -450,7 +364,7 @@ export default class StorybookPlugin implements IHeftTaskPlugin { const { logger, resolvedModulePath, verbose, isServeMode, isTestMode, isDocsMode } = runStorybookOptions; let { workingDirectory, outputFolder } = runStorybookOptions; @@ -617,7 +531,7 @@ export default class StorybookPlugin implements IHeftTaskPlugin ({ ...emitKind, outFolderName: Path.convertToSlashes( diff --git a/heft-plugins/heft-typescript-plugin/src/TypeScriptPlugin.ts b/heft-plugins/heft-typescript-plugin/src/TypeScriptPlugin.ts index cd47dfc1b89..8065e151d41 100644 --- a/heft-plugins/heft-typescript-plugin/src/TypeScriptPlugin.ts +++ b/heft-plugins/heft-typescript-plugin/src/TypeScriptPlugin.ts @@ -23,8 +23,19 @@ import type { import { TypeScriptBuilder, type ITypeScriptBuilderConfiguration } from './TypeScriptBuilder'; import anythingSchema from './schemas/anything.schema.json'; import typescriptConfigSchema from './schemas/typescript.schema.json'; +import type { + TypeScriptBuildConfiguration as ITypeScriptConfigurationJson, + AdditionalModuleKindToEmit as IEmitModuleKind +} from './schemas/typescript.schema.json.d.ts'; import { getTsconfigFilePath } from './tsconfigLoader'; +/** + * @beta + */ +export type IStaticAssetsCopyConfiguration = ITypeScriptConfigurationJson['staticAssetsToCopy']; + +export { IEmitModuleKind, ITypeScriptConfigurationJson }; + /** * The name of the plugin, as specified in heft-plugin.json * @@ -38,75 +49,6 @@ export const PLUGIN_NAME: 'typescript-plugin' = 'typescript-plugin'; */ const CONFIG_DIR_TOKEN: '${configDir}' = '${configDir}'; -/** - * @beta - */ -export interface IEmitModuleKind { - moduleKind: 'commonjs' | 'amd' | 'umd' | 'system' | 'es2015' | 'esnext'; - outFolderName: string; - jsExtensionOverride?: string; -} - -/** - * @beta - */ -export interface IStaticAssetsCopyConfiguration { - fileExtensions: string[]; - excludeGlobs: string[]; - includeGlobs: string[]; -} - -/** - * @beta - */ -export interface ITypeScriptConfigurationJson { - /** - * If provided, emit these module kinds in addition to the modules specified in the tsconfig. - * Note that this option only applies to the main tsconfig.json configuration. - */ - additionalModuleKindsToEmit?: IEmitModuleKind[] | undefined; - - /** - * If 'true', emit CommonJS output into the TSConfig outDir with the file extension '.cjs' - */ - emitCjsExtensionForCommonJS?: boolean | undefined; - - /** - * If 'true', emit ESModule output into the TSConfig outDir with the file extension '.mjs' - */ - emitMjsExtensionForESModule?: boolean | undefined; - - /** - * If true, enable behavior analogous to the "tsc --build" command. Will build projects referenced by the main project in dependency order. - * Note that this will effectively enable \"noEmitOnError\". - */ - buildProjectReferences?: boolean; - - /** - * If true, and the tsconfig has \"isolatedModules\": true, then transpilation will happen in parallel in a worker thread. - */ - useTranspilerWorker?: boolean; - - /** - * If true, the TypeScript compiler will only resolve symlinks to their targets if the links are in a node_modules folder. - * This significantly reduces file system operations in typical usage. - */ - onlyResolveSymlinksInNodeModules?: boolean; - - /* - * Specifies the tsconfig.json file that will be used for compilation. Equivalent to the "project" argument for the 'tsc' and 'tslint' command line tools. - * - * The default value is "./tsconfig.json" - */ - project?: string; - - /** - * Configures additional file types that should be copied into the TypeScript compiler's emit folders, for example - * so that these files can be resolved by import statements. - */ - staticAssetsToCopy?: IStaticAssetsCopyConfiguration; -} - /** * @beta */ diff --git a/heft-plugins/heft-typescript-plugin/src/schemas/typescript.schema.json b/heft-plugins/heft-typescript-plugin/src/schemas/typescript.schema.json index d42ff1f0476..056dc522d66 100644 --- a/heft-plugins/heft-typescript-plugin/src/schemas/typescript.schema.json +++ b/heft-plugins/heft-typescript-plugin/src/schemas/typescript.schema.json @@ -2,10 +2,32 @@ "$schema": "http://json-schema.org/draft-04/schema#", "title": "TypeScript Build Configuration", "description": "Defines optional options for TypeScript build.", + "x-tsdoc-release-tag": "@beta", "type": "object", "additionalProperties": false, + "definitions": { + "additionalModuleKindToEmit": { + "type": "object", + "additionalProperties": false, + "properties": { + "moduleKind": { + "description": "Specifies the module format to emit. The value must be one of the module formats supported by the TypeScript compiler.", + "type": "string", + "enum": ["commonjs", "amd", "umd", "system", "es2015", "esnext"] + }, + + "outFolderName": { + "description": "Specifies the output folder name where the compiler will emit the module format. This folder name is resolved relative to the project root.", + "type": "string", + "pattern": "[^\\\\\\/]" + } + }, + "required": ["moduleKind", "outFolderName"] + } + }, + "properties": { "$schema": { "description": "Part of the JSON Schema standard, this optional keyword declares the URL of the schema that the file conforms to. Editors may download the schema and use it to perform syntax highlighting.", @@ -21,19 +43,7 @@ "type": "array", "description": "If provided, emit these module kinds in addition to the modules specified in the tsconfig. Note that this option only applies to the main tsconfig.json configuration.", "items": { - "type": "object", - "properties": { - "moduleKind": { - "type": "string", - "enum": ["commonjs", "amd", "umd", "system", "es2015", "esnext"] - }, - - "outFolderName": { - "type": "string", - "pattern": "[^\\\\\\/]" - } - }, - "required": ["moduleKind", "outFolderName"] + "$ref": "#/definitions/additionalModuleKindToEmit" } }, diff --git a/heft-plugins/heft-webpack4-plugin/heft-plugin.json b/heft-plugins/heft-webpack4-plugin/heft-plugin.json index 32f5ce328d0..ca101b5e92d 100644 --- a/heft-plugins/heft-webpack4-plugin/heft-plugin.json +++ b/heft-plugins/heft-webpack4-plugin/heft-plugin.json @@ -5,7 +5,7 @@ { "pluginName": "webpack4-plugin", "entryPoint": "./lib-commonjs/Webpack4Plugin", - "optionsSchema": "./lib-commonjs/schemas/heft-webpack4-plugin.schema.json", + "optionsSchema": "./lib-commonjs/schemas/heft-webpack4-plugin-options.schema.json", "parameterScope": "webpack4", "parameters": [ diff --git a/heft-plugins/heft-webpack4-plugin/src/Webpack4Plugin.ts b/heft-plugins/heft-webpack4-plugin/src/Webpack4Plugin.ts index 644f585c8e8..5ff4d499b52 100644 --- a/heft-plugins/heft-webpack4-plugin/src/Webpack4Plugin.ts +++ b/heft-plugins/heft-webpack4-plugin/src/Webpack4Plugin.ts @@ -30,6 +30,7 @@ import { type IWatchFileSystem, OverrideNodeWatchFSPlugin } from './DeferredWatchFileSystem'; +import type { Webpack4PluginConfiguration } from './schemas/heft-webpack4-plugin-options.schema.json.d.ts'; type ExtendedWatching = TWebpack.Watching & { resume: () => void; @@ -59,11 +60,6 @@ type ExtendedMultiCompiler = TWebpack.MultiCompiler & { watching: ExtendedMultiWatching; }; -export interface IWebpackPluginOptions { - devConfigurationPath?: string | undefined; - configurationPath?: string | undefined; -} - const SERVE_PARAMETER_LONG_NAME: '--serve' = '--serve'; const WEBPACK_PACKAGE_NAME: 'webpack' = 'webpack'; const WEBPACK_DEV_SERVER_PACKAGE_NAME: 'webpack-dev-server' = 'webpack-dev-server'; @@ -73,7 +69,7 @@ const WEBPACK_DEV_MIDDLEWARE_PACKAGE_NAME: 'webpack-dev-middleware' = 'webpack-d /** * @internal */ -export default class Webpack4Plugin implements IHeftTaskPlugin { +export default class Webpack4Plugin implements IHeftTaskPlugin { private _accessor: IWebpackPluginAccessor | undefined; private _isServeMode: boolean = false; private _webpack: typeof TWebpack | undefined; @@ -101,7 +97,7 @@ export default class Webpack4Plugin implements IHeftTaskPlugin void ): Promise { if (this._webpackConfiguration === false) { @@ -189,7 +185,7 @@ export default class Webpack4Plugin implements IHeftTaskPlugin { this._validateEnvironmentVariable(taskSession); if (taskSession.parameters.watch || this._isServeMode) { @@ -235,7 +231,7 @@ export default class Webpack4Plugin implements IHeftTaskPlugin void ): Promise { // Save a handle to the original promise, since the this-scoped promise will be replaced whenever diff --git a/heft-plugins/heft-webpack4-plugin/src/WebpackConfigurationLoader.ts b/heft-plugins/heft-webpack4-plugin/src/WebpackConfigurationLoader.ts index cd1b0c36052..7e5a6ecda94 100644 --- a/heft-plugins/heft-webpack4-plugin/src/WebpackConfigurationLoader.ts +++ b/heft-plugins/heft-webpack4-plugin/src/WebpackConfigurationLoader.ts @@ -8,7 +8,7 @@ import type * as TWebpack from 'webpack'; import { FileSystem } from '@rushstack/node-core-library'; import type { IHeftTaskSession, HeftConfiguration } from '@rushstack/heft'; -import type { IWebpackPluginOptions } from './Webpack4Plugin'; +import type { Webpack4PluginConfiguration } from './schemas/heft-webpack4-plugin-options.schema.json.d.ts'; import { PLUGIN_NAME, STAGE_LOAD_LOCAL_CONFIG, @@ -47,7 +47,7 @@ const DEFAULT_WEBPACK_DEV_CONFIG_PATH: './webpack.dev.config.js' = './webpack.de */ export async function tryLoadWebpackConfigurationAsync( options: ILoadWebpackConfigurationOptions, - pluginOptions: IWebpackPluginOptions + pluginOptions: Webpack4PluginConfiguration ): Promise { const { taskSession, hooks, _tryLoadConfigFileAsync = tryLoadWebpackConfigurationFileAsync } = options; const { logger } = taskSession; @@ -108,7 +108,7 @@ export async function tryLoadWebpackConfigurationAsync( */ export async function tryLoadWebpackConfigurationFileAsync( options: ILoadWebpackConfigurationOptions, - pluginOptions: IWebpackPluginOptions + pluginOptions: Webpack4PluginConfiguration ): Promise { // TODO: Eventually replace this custom logic with a call to this utility in in webpack-cli: // https://github.com/webpack/webpack-cli/blob/next/packages/webpack-cli/lib/groups/ConfigGroup.js diff --git a/heft-plugins/heft-webpack4-plugin/src/schemas/heft-webpack4-plugin.schema.json b/heft-plugins/heft-webpack4-plugin/src/schemas/heft-webpack4-plugin-options.schema.json similarity index 100% rename from heft-plugins/heft-webpack4-plugin/src/schemas/heft-webpack4-plugin.schema.json rename to heft-plugins/heft-webpack4-plugin/src/schemas/heft-webpack4-plugin-options.schema.json diff --git a/heft-plugins/heft-webpack5-plugin/heft-plugin.json b/heft-plugins/heft-webpack5-plugin/heft-plugin.json index 165299e71d3..cbaa3c47d4c 100644 --- a/heft-plugins/heft-webpack5-plugin/heft-plugin.json +++ b/heft-plugins/heft-webpack5-plugin/heft-plugin.json @@ -5,7 +5,7 @@ { "pluginName": "webpack5-plugin", "entryPoint": "./lib-commonjs/Webpack5Plugin", - "optionsSchema": "./lib-commonjs/schemas/heft-webpack5-plugin.schema.json", + "optionsSchema": "./lib-commonjs/schemas/heft-webpack5-plugin-options.schema.json", "parameterScope": "webpack5", "parameters": [ diff --git a/heft-plugins/heft-webpack5-plugin/src/Webpack5Plugin.ts b/heft-plugins/heft-webpack5-plugin/src/Webpack5Plugin.ts index 59bf0c4b725..87a8b622aa4 100644 --- a/heft-plugins/heft-webpack5-plugin/src/Webpack5Plugin.ts +++ b/heft-plugins/heft-webpack5-plugin/src/Webpack5Plugin.ts @@ -26,11 +26,8 @@ import { } from './shared'; import { tryLoadWebpackConfigurationAsync } from './WebpackConfigurationLoader'; import { type DeferredWatchFileSystem, OverrideNodeWatchFSPlugin } from './DeferredWatchFileSystem'; +import type { Webpack5PluginConfiguration } from './schemas/heft-webpack5-plugin-options.schema.json.d.ts'; -export interface IWebpackPluginOptions { - devConfigurationPath?: string | undefined; - configurationPath?: string | undefined; -} const SERVE_PARAMETER_LONG_NAME: '--serve' = '--serve'; const WEBPACK_PACKAGE_NAME: 'webpack' = 'webpack'; const WEBPACK_DEV_SERVER_PACKAGE_NAME: 'webpack-dev-server' = 'webpack-dev-server'; @@ -40,7 +37,7 @@ const WEBPACK_DEV_MIDDLEWARE_PACKAGE_NAME: 'webpack-dev-middleware' = 'webpack-d /** * @internal */ -export default class Webpack5Plugin implements IHeftTaskPlugin { +export default class Webpack5Plugin implements IHeftTaskPlugin { private _accessor: IWebpackPluginAccessor | undefined; private _isServeMode: boolean = false; private _webpack: typeof TWebpack | undefined; @@ -68,7 +65,7 @@ export default class Webpack5Plugin implements IHeftTaskPlugin void ): Promise { if (this._webpackConfiguration === false) { @@ -170,7 +167,7 @@ export default class Webpack5Plugin implements IHeftTaskPlugin { this._validateEnvironmentVariable(taskSession); if (taskSession.parameters.watch || this._isServeMode) { @@ -218,7 +215,7 @@ export default class Webpack5Plugin implements IHeftTaskPlugin void ): Promise { // Save a handle to the original promise, since the this-scoped promise will be replaced whenever diff --git a/heft-plugins/heft-webpack5-plugin/src/WebpackConfigurationLoader.ts b/heft-plugins/heft-webpack5-plugin/src/WebpackConfigurationLoader.ts index c8516cfbe1f..2193d0adb50 100644 --- a/heft-plugins/heft-webpack5-plugin/src/WebpackConfigurationLoader.ts +++ b/heft-plugins/heft-webpack5-plugin/src/WebpackConfigurationLoader.ts @@ -8,7 +8,7 @@ import type * as TWebpack from 'webpack'; import { FileSystem } from '@rushstack/node-core-library'; import type { IHeftTaskSession, HeftConfiguration } from '@rushstack/heft'; -import type { IWebpackPluginOptions } from './Webpack5Plugin'; +import type { Webpack5PluginConfiguration } from './schemas/heft-webpack5-plugin-options.schema.json.d.ts'; import { PLUGIN_NAME, STAGE_LOAD_LOCAL_CONFIG, @@ -47,7 +47,7 @@ const DEFAULT_WEBPACK_DEV_CONFIG_PATH: './webpack.dev.config.js' = './webpack.de */ export async function tryLoadWebpackConfigurationAsync( options: ILoadWebpackConfigurationOptions, - pluginOptions: IWebpackPluginOptions + pluginOptions: Webpack5PluginConfiguration ): Promise { const { taskSession, hooks, _tryLoadConfigFileAsync = tryLoadWebpackConfigurationFileAsync } = options; const { logger } = taskSession; @@ -108,7 +108,7 @@ export async function tryLoadWebpackConfigurationAsync( */ export async function tryLoadWebpackConfigurationFileAsync( options: ILoadWebpackConfigurationOptions, - pluginOptions: IWebpackPluginOptions + pluginOptions: Webpack5PluginConfiguration ): Promise { // TODO: Eventually replace this custom logic with a call to this utility in in webpack-cli: // https://github.com/webpack/webpack-cli/blob/next/packages/webpack-cli/lib/groups/ConfigGroup.js diff --git a/heft-plugins/heft-webpack5-plugin/src/schemas/heft-webpack5-plugin.schema.json b/heft-plugins/heft-webpack5-plugin/src/schemas/heft-webpack5-plugin-options.schema.json similarity index 100% rename from heft-plugins/heft-webpack5-plugin/src/schemas/heft-webpack5-plugin.schema.json rename to heft-plugins/heft-webpack5-plugin/src/schemas/heft-webpack5-plugin-options.schema.json diff --git a/libraries/credential-cache/src/CredentialCache.ts b/libraries/credential-cache/src/CredentialCache.ts index bac9378e7a9..255b4e5292e 100644 --- a/libraries/credential-cache/src/CredentialCache.ts +++ b/libraries/credential-cache/src/CredentialCache.ts @@ -14,6 +14,12 @@ import { } from '@rushstack/node-core-library'; import schemaJson from './schemas/credentials.schema.json'; +import type { + CredentialCache as ICredentialCacheJson, + CredentialCacheEntry as ICredentialCacheEntryJson +} from './schemas/credentials.schema.json.d.ts'; + +export type { ICredentialCacheEntryJson }; // Polyfill for node 18 Disposables.polyfillDisposeSymbols(); @@ -27,26 +33,11 @@ export const RUSH_USER_FOLDER_NAME: '.rush-user' = '.rush-user'; const DEFAULT_CACHE_FILENAME: 'credentials.json' = 'credentials.json'; const LATEST_CREDENTIALS_JSON_VERSION: string = '0.1.0'; -interface ICredentialCacheJson { - version: string; - cacheEntries: { - [credentialCacheId: string]: ICacheEntryJson; - }; -} - -interface ICacheEntryJson { - expires: number; - credential: string; - credentialMetadata?: object; -} - /** * @public */ -export interface ICredentialCacheEntry { +export interface ICredentialCacheEntry extends Omit { expires?: Date; - credential: string; - credentialMetadata?: object; } /** @@ -62,7 +53,7 @@ export interface ICredentialCacheOptions { */ export class CredentialCache implements Disposable { private readonly _cacheFilePath: string; - private readonly _cacheEntries: Map; + private readonly _cacheEntries: Map; private _modified: boolean = false; private _disposed: boolean = false; private readonly _supportsEditing: boolean; @@ -78,7 +69,9 @@ export class CredentialCache implements Disposable { } this._cacheFilePath = cacheFilePath; - this._cacheEntries = new Map(Object.entries(loadedJson?.cacheEntries || {})); + this._cacheEntries = new Map( + Object.entries(loadedJson?.cacheEntries || {}) + ); this._supportsEditing = !!lockfile; this._lockfile = lockfile; } @@ -132,7 +125,7 @@ export class CredentialCache implements Disposable { const { expires, credential, credentialMetadata } = entry; const expiresMilliseconds: number = expires?.getTime() || 0; - const existingCacheEntry: ICacheEntryJson | undefined = this._cacheEntries.get(cacheId); + const existingCacheEntry: ICredentialCacheEntryJson | undefined = this._cacheEntries.get(cacheId); if ( existingCacheEntry?.credential !== credential || existingCacheEntry?.expires !== expiresMilliseconds || @@ -150,7 +143,7 @@ export class CredentialCache implements Disposable { public tryGetCacheEntry(cacheId: string): ICredentialCacheEntry | undefined { this._validate(false); - const cacheEntry: ICacheEntryJson | undefined = this._cacheEntries.get(cacheId); + const cacheEntry: ICredentialCacheEntryJson | undefined = this._cacheEntries.get(cacheId); if (cacheEntry) { const result: ICredentialCacheEntry = { expires: cacheEntry.expires ? new Date(cacheEntry.expires) : undefined, @@ -189,7 +182,7 @@ export class CredentialCache implements Disposable { this._validate(true); if (this._modified) { - const cacheEntriesJson: { [cacheId: string]: ICacheEntryJson } = {}; + const cacheEntriesJson: { [cacheId: string]: ICredentialCacheEntryJson } = {}; for (const [cacheId, cacheEntry] of this._cacheEntries.entries()) { cacheEntriesJson[cacheId] = cacheEntry; } diff --git a/libraries/credential-cache/src/index.ts b/libraries/credential-cache/src/index.ts index 00ce0172b53..47377bdba7b 100644 --- a/libraries/credential-cache/src/index.ts +++ b/libraries/credential-cache/src/index.ts @@ -10,6 +10,7 @@ export { CredentialCache, type ICredentialCacheEntry, + type ICredentialCacheEntryJson, type ICredentialCacheOptions, RUSH_USER_FOLDER_NAME } from './CredentialCache'; diff --git a/libraries/credential-cache/src/schemas/credentials.schema.json b/libraries/credential-cache/src/schemas/credentials.schema.json index 9800b511877..d95287d4b86 100644 --- a/libraries/credential-cache/src/schemas/credentials.schema.json +++ b/libraries/credential-cache/src/schemas/credentials.schema.json @@ -1,7 +1,8 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "title": "Cache for credentials used with the Rush tool.", + "title": "Credential Cache", "description": "For use with the Rush tool, this file acts as a cache for the credentials. See http://rushjs.io for details.", + "x-tsdoc-release-tag": "@public", "type": "object", @@ -15,20 +16,30 @@ "type": "object", "patternProperties": { ".+": { - "type": "object", - "required": ["expires", "credential"], + "$ref": "#/definitions/credentialCacheEntry" + } + } + } + }, + + "definitions": { + "credentialCacheEntry": { + "type": "object", + "required": ["expires", "credential"], + "additionalProperties": false, - "properties": { - "expires": { - "type": "number" - }, - "credential": { - "type": "string" - }, - "credentialMetadata": { - "type": "object" - } - } + "properties": { + "expires": { + "description": "The expiration time of the credential, in milliseconds since the epoch.", + "type": "number" + }, + "credential": { + "description": "The credential string.", + "type": "string" + }, + "credentialMetadata": { + "description": "Additional metadata associated with the credential.", + "type": "object" } } } diff --git a/libraries/credential-cache/src/test/CredentialCache.test.ts b/libraries/credential-cache/src/test/CredentialCache.test.ts index 5bdb13c49e6..b474f184d28 100644 --- a/libraries/credential-cache/src/test/CredentialCache.test.ts +++ b/libraries/credential-cache/src/test/CredentialCache.test.ts @@ -274,7 +274,7 @@ describe(CredentialCache.name, () => { it('correctly sets credentialMetadata', async () => { const credentialId: string = 'test-credential'; const credentialValue: string = 'test-value'; - const credentialMetadata: object = { + const credentialMetadata: { [k: string]: unknown } = { a: 1, b: true }; @@ -307,11 +307,11 @@ describe(CredentialCache.name, () => { it('correctly updates credentialMetadata', async () => { const credentialId: string = 'test-credential'; const credentialValue: string = 'test-value'; - const oldCredentialMetadata: object = { + const oldCredentialMetadata: { [k: string]: unknown } = { a: 1, b: true }; - const newCredentialMetadata: object = { + const newCredentialMetadata: { [k: string]: unknown } = { c: ['a', 'b', 'c'] }; diff --git a/libraries/node-core-library/src/JsonSchema.ts b/libraries/node-core-library/src/JsonSchema.ts index a1ffdf13dfb..76590da9f62 100644 --- a/libraries/node-core-library/src/JsonSchema.ts +++ b/libraries/node-core-library/src/JsonSchema.ts @@ -5,6 +5,7 @@ import * as os from 'node:os'; import * as path from 'node:path'; import Ajv, { type Options as AjvOptions, type ErrorObject, type ValidateFunction } from 'ajv'; +import Ajv2019 from 'ajv/dist/2019'; import AjvDraft04 from 'ajv-draft-04'; import addFormats from 'ajv-formats'; @@ -44,7 +45,7 @@ interface ISchemaWithId { * https://json-schema.org/specification * @public */ -export type JsonSchemaVersion = 'draft-04' | 'draft-07'; +export type JsonSchemaVersion = 'draft-04' | 'draft-07' | 'draft-2019-09'; /** * A definition for a custom format to consider during validation. @@ -175,7 +176,8 @@ export type IJsonSchemaFromObjectOptions = IJsonSchemaLoadOptions; const JSON_SCHEMA_URL_PREFIX_BY_JSON_SCHEMA_VERSION: Map = new Map([ ['draft-04', 'http://json-schema.org/draft-04/schema'], - ['draft-07', 'http://json-schema.org/draft-07/schema'] + ['draft-07', 'http://json-schema.org/draft-07/schema'], + ['draft-2019-09', 'https://json-schema.org/draft/2019-09/schema'] ]); /** @@ -371,6 +373,11 @@ export class JsonSchema { break; } + case 'draft-2019-09': { + validator = new Ajv2019(validatorOptions); + break; + } + case 'draft-07': default: { validator = new Ajv(validatorOptions); diff --git a/libraries/node-core-library/src/test/JsonSchema.test.ts b/libraries/node-core-library/src/test/JsonSchema.test.ts index 44a482d9398..7d265a1ddde 100644 --- a/libraries/node-core-library/src/test/JsonSchema.test.ts +++ b/libraries/node-core-library/src/test/JsonSchema.test.ts @@ -7,6 +7,7 @@ import { JsonSchema, type IJsonSchemaErrorInfo } from '../JsonSchema'; const SCHEMA_PATH: string = `${__dirname}/test-data/test-schemas/test-schema.schema.json`; const DRAFT_04_SCHEMA_PATH: string = `${__dirname}/test-data/test-schemas/test-schema-draft-04.schema.json`; const DRAFT_07_SCHEMA_PATH: string = `${__dirname}/test-data/test-schemas/test-schema-draft-07.schema.json`; +const DRAFT_2019_09_SCHEMA_PATH: string = `${__dirname}/test-data/test-schemas/test-schema-draft-2019-09.schema.json`; describe(JsonSchema.name, () => { const schema: JsonSchema = JsonSchema.fromFile(SCHEMA_PATH, { @@ -57,6 +58,18 @@ describe(JsonSchema.name, () => { }); }); + test('validates a JSON file against a draft-2019-09 schema', () => { + const schemaDraft2019: JsonSchema = JsonSchema.fromFile(DRAFT_2019_09_SCHEMA_PATH); + + const jsonPath: string = `${__dirname}/test-data/test-schemas/test-valid.schema.json`; + const jsonObject: JsonObject = JsonFile.loadAndValidate(jsonPath, schemaDraft2019); + + expect(jsonObject).toMatchObject({ + exampleString: 'This is a string', + exampleArray: ['apple', 'banana', 'coconut'] + }); + }); + test('validates a JSON file using nested schemas', () => { const schemaPathChild: string = `${__dirname}/test-data/test-schemas/test-schema-nested-child.schema.json`; const schemaChild: JsonSchema = JsonSchema.fromFile(schemaPathChild); @@ -120,6 +133,22 @@ describe(JsonSchema.name, () => { }); }); + test('validates objects against a draft-2019-09 schema', () => { + const schemaDraft2019: JsonSchema = JsonSchema.fromLoadedObject({ + $schema: 'https://json-schema.org/draft/2019-09/schema#', + title: 'Test draft-2019-09 schema', + type: 'object', + properties: { + exampleString: { type: 'string' } + }, + additionalProperties: false, + required: ['exampleString'] + }); + + expect(() => schemaDraft2019.validateObject({ exampleString: 'This is a string' }, '')).not.toThrow(); + expect(() => schemaDraft2019.validateObject({} as JsonObject, '')).toThrow(); + }); + test('accepts vendor extension keywords by default', () => { const schemaWithVendorExtensions: JsonSchema = JsonSchema.fromLoadedObject( { diff --git a/libraries/node-core-library/src/test/test-data/test-schemas/test-schema-draft-2019-09.schema.json b/libraries/node-core-library/src/test/test-data/test-schemas/test-schema-draft-2019-09.schema.json new file mode 100644 index 00000000000..699cc7ac185 --- /dev/null +++ b/libraries/node-core-library/src/test/test-data/test-schemas/test-schema-draft-2019-09.schema.json @@ -0,0 +1,75 @@ +{ + "$schema": "https://json-schema.org/draft/2019-09/schema#", + "title": "Test Schema File", + "type": "object", + + "definitions": { + "type1": { + "description": "Description for type1", + "type": "object", + "properties": { + "field1": { + "description": "Description for field1", + "type": "string" + } + }, + "additionalProperties": false, + "required": ["field1"] + }, + "type2": { + "description": "Description for type2", + "type": "object", + "properties": { + "field2": { + "description": "Description for field2", + "type": "string" + }, + "field3": { + "description": "Description for field3", + "type": "string" + } + }, + "additionalProperties": false, + "required": ["field2", "field3"] + } + }, + + "properties": { + "exampleString": { + "type": "string" + }, + "exampleLink": { + "type": "string", + "format": "uri" + }, + "exampleArray": { + "type": "array", + "items": { + "type": "string" + } + }, + "exampleOneOf": { + "description": "Description for exampleOneOf - this is a very long description to show in an error message", + "type": "object", + "oneOf": [{ "$ref": "#/definitions/type1" }, { "$ref": "#/definitions/type2" }] + }, + "exampleUniqueObjectArray": { + "type": "array", + "uniqueItems": true, + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "field2": { + "type": "string" + }, + "field3": { + "type": "string" + } + } + } + } + }, + "additionalProperties": false, + "required": ["exampleString", "exampleArray"] +} diff --git a/libraries/rig-package/src/RigConfig.ts b/libraries/rig-package/src/RigConfig.ts index 31ab62e2d76..51db167974a 100644 --- a/libraries/rig-package/src/RigConfig.ts +++ b/libraries/rig-package/src/RigConfig.ts @@ -8,34 +8,14 @@ import * as nodeResolve from 'resolve'; import stripJsonComments from 'strip-json-comments'; import { Helpers } from './Helpers'; +import type { RigConfiguration as IRigConfigJson } from './schemas/rig.schema.json.d.ts'; /** * Represents the literal contents of the `config/rig.json` file. * * @public */ -export interface IRigConfigJson { - /** - * The name of the rig package to use. - * - * @remarks - * The name must be a valid NPM package name, and must end with the `-rig` suffix. - * - * Example: `example-rig` - */ - rigPackageName: string; - - /** - * Specify which rig profile to use from the rig package. - * - * @remarks - * The name must consist of lowercase alphanumeric words separated by hyphens, for example `"sample-profile"`. - * If the `"rigProfile"` is not specified, then the profile name `"default"` will be used. - * - * Example: `example-profile` - */ - rigProfile?: string; -} +export type { IRigConfigJson }; interface IRigConfigOptions { projectFolderPath: string; @@ -278,8 +258,12 @@ export class RigConfig implements IRigConfig { public static get jsonSchemaObject(): object { if (RigConfig._jsonSchemaObject === undefined) { const jsonSchemaContent: string = fs.readFileSync(RigConfig.jsonSchemaPath).toString(); - RigConfig._jsonSchemaObject = JSON.parse(jsonSchemaContent); + // Remove nonstandard fields that are not part of the JSON Schema specification + // eslint-disable-next-line @typescript-eslint/no-unused-vars + const { 'x-tsdoc-release-tag': _, ...schemaObject } = JSON.parse(jsonSchemaContent); + RigConfig._jsonSchemaObject = schemaObject; } + return RigConfig._jsonSchemaObject!; } @@ -520,6 +504,7 @@ export class RigConfig implements IRigConfig { throw new Error(`Unsupported field ${JSON.stringify(key)}`); } } + if (!json.rigPackageName) { throw new Error('Missing required field "rigPackageName"'); } diff --git a/libraries/rig-package/src/schemas/rig.schema.json b/libraries/rig-package/src/schemas/rig.schema.json index 9707e71e3da..f97246fd9a7 100644 --- a/libraries/rig-package/src/schemas/rig.schema.json +++ b/libraries/rig-package/src/schemas/rig.schema.json @@ -1,7 +1,8 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "title": "Describes the config/rig.json file", + "title": "Rig Configuration", "description": "The rig.json file is a standard for sharing project configuration in a monorepo without duplicating files", + "x-tsdoc-release-tag": "@public", "type": "object", "additionalProperties": false, diff --git a/libraries/rush-lib/scripts/copyEmptyModules.js b/libraries/rush-lib/scripts/copyEmptyModules.js index 061a03d699e..c3cc77f0337 100644 --- a/libraries/rush-lib/scripts/copyEmptyModules.js +++ b/libraries/rush-lib/scripts/copyEmptyModules.js @@ -3,7 +3,6 @@ const { FileSystem, Async, AsyncQueue } = require('@rushstack/node-core-library'); const JS_FILE_EXTENSION = '.js'; -const DTS_FILE_EXTENSION = '.d.ts'; module.exports = { runAsync: async ({ @@ -15,17 +14,16 @@ module.exports = { // We're using a Webpack plugin called `@rushstack/webpack-deep-imports-plugin` to // examine all of the modules that are imported by the entrypoints (index, and the start* scripts) // to `rush-lib` and generate stub JS files in the `lib` folder that reference the original modules - // in the webpack bundle. The plugin also copies the `.d.ts` files for those modules to the `lib` folder. + // in the webpack bundle. // // A limitation of this approach is that only modules that contain runtime code end up in the Webpack - // bundle, so only modules that contain runtime code get stubs and have their `.d.ts` files copied. This + // bundle, so only modules that contain runtime code get stubs. This // creates a problem when a `.d.ts` file references a module that doesn't have runtime code (i.e. - - // a `.d.ts` file that only contains types). + // a `.ts` file that only contains types). // // This script looks through the `lib-intermediate-esm` folder for `.js` files that were produced by the TypeScript // compiler from `.ts` files that contain no runtime code and generates stub `.js` files for them in the - // `lib` folder and copies the corresponding `.d.ts` files to the `lib`. This ensures that the `.d.ts` - // files that end up in the `lib` folder don't have any unresolved imports. This is tested by the + // `lib-commonjs` folder. This ensures that all modules have corresponding JS stubs. This is tested by the // `rush-lib-declaration-paths-test` project in the `build-tests` function stripCommentsFromJsFile(jsFileText) { @@ -44,7 +42,6 @@ module.exports = { } const jsInFolderPath = `${buildFolderPath}/lib-intermediate-esm`; - const dtsInFolderPath = `${buildFolderPath}/lib-dts`; const outCjsFolderPath = `${buildFolderPath}/lib-commonjs`; const emptyModuleBuffer = Buffer.from('module.exports = {};', 'utf8'); const folderPathQueue = new AsyncQueue([undefined]); @@ -70,15 +67,6 @@ module.exports = { await FileSystem.writeFileAsync(outJsPath, emptyModuleBuffer, { ensureFolderExists: true }); - - const relativeDtsPath = - relativeItemPath.slice(0, -JS_FILE_EXTENSION.length) + DTS_FILE_EXTENSION; - const inDtsPath = `${dtsInFolderPath}/${relativeDtsPath}`; - const outDtsPath = `${outCjsFolderPath}/${relativeDtsPath}`; - terminal.writeVerboseLine(`Copying ${inDtsPath} to ${outDtsPath}`); - // We know this is a file, don't need the redundant checks in FileSystem.copyFileAsync - const buffer = await FileSystem.readFileToBufferAsync(inDtsPath); - await FileSystem.writeFileAsync(outDtsPath, buffer, { ensureFolderExists: true }); } } } diff --git a/libraries/rush-lib/src/api/ApprovedPackagesConfiguration.ts b/libraries/rush-lib/src/api/ApprovedPackagesConfiguration.ts index e7b48f2c842..0c672b568e7 100644 --- a/libraries/rush-lib/src/api/ApprovedPackagesConfiguration.ts +++ b/libraries/rush-lib/src/api/ApprovedPackagesConfiguration.ts @@ -8,24 +8,10 @@ import { JsonFile, JsonSchema, FileSystem, NewlineKind, InternalError } from '@r import { JsonSchemaUrls } from '../logic/JsonSchemaUrls'; import schemaJson from '../schemas/approved-packages.schema.json'; import { RushConstants } from '../logic/RushConstants'; - -/** - * Part of IApprovedPackagesJson. - */ -export interface IApprovedPackagesItemJson { - name: string; - allowedCategories: string[]; -} - -/** - * This represents the JSON data structure for the "browser-approved-packages.json" - * and "nonbrowser-approved-packages.json" configuration files. See "approved-packages.schema.json" - * for documentation. - */ -export interface IApprovedPackagesJson { - $schema?: string; - packages: IApprovedPackagesItemJson[]; -} +import type { + RushApprovedPackagesConfiguration as IApprovedPackagesJson, + PackageInfo as IApprovedPackagesItemJson +} from '../schemas/approved-packages.schema.json.d.ts'; /** * An item returned by ApprovedPackagesConfiguration diff --git a/libraries/rush-lib/src/api/CobuildConfiguration.ts b/libraries/rush-lib/src/api/CobuildConfiguration.ts index d96cfc96dc2..e3228022a31 100644 --- a/libraries/rush-lib/src/api/CobuildConfiguration.ts +++ b/libraries/rush-lib/src/api/CobuildConfiguration.ts @@ -12,14 +12,12 @@ import { RushConstants } from '../logic/RushConstants'; import type { ICobuildLockProvider } from '../logic/cobuild/ICobuildLockProvider'; import type { RushConfiguration } from './RushConfiguration'; import schemaJson from '../schemas/cobuild.schema.json'; +import type { RushCobuildConfiguration as ICobuildJson } from '../schemas/cobuild.schema.json.d.ts'; /** * @beta */ -export interface ICobuildJson { - cobuildFeatureEnabled: boolean; - cobuildLockProvider: string; -} +export type { ICobuildJson }; /** * @beta diff --git a/libraries/rush-lib/src/api/CommonVersionsConfiguration.ts b/libraries/rush-lib/src/api/CommonVersionsConfiguration.ts index 0996bbc5a0f..b3839a172f9 100644 --- a/libraries/rush-lib/src/api/CommonVersionsConfiguration.ts +++ b/libraries/rush-lib/src/api/CommonVersionsConfiguration.ts @@ -19,6 +19,7 @@ import { JsonSchemaUrls } from '../logic/JsonSchemaUrls'; import type { RushConfiguration } from './RushConfiguration'; import { RushConstants } from '../logic/RushConstants'; import schemaJson from '../schemas/common-versions.schema.json'; +import type { RushCommonVersionsConfiguration as ICommonVersionsJson } from '../schemas/common-versions.schema.json.d.ts'; /** * Part of the ICommonVersionsJson structure. @@ -42,21 +43,6 @@ export declare interface ICommonVersionsJsonVersionsMap { [dependencyName: string]: string[]; } -/** - * Describes the file structure for the "common/config/rush/common-versions.json" config file. - */ -interface ICommonVersionsJson { - $schema?: string; - - preferredVersions?: ICommonVersionsJsonVersionMap; - - implicitlyPreferredVersions?: boolean; - - allowedAlternativeVersions?: ICommonVersionsJsonVersionsMap; - - ensureConsistentVersions?: boolean; -} - /** * Use this class to load and save the "common/config/rush/common-versions.json" config file. * This config file stores dependency version information that affects all projects in the repo. diff --git a/libraries/rush-lib/src/api/ExperimentsConfiguration.ts b/libraries/rush-lib/src/api/ExperimentsConfiguration.ts index f8a9ae66e34..e9976b2de08 100644 --- a/libraries/rush-lib/src/api/ExperimentsConfiguration.ts +++ b/libraries/rush-lib/src/api/ExperimentsConfiguration.ts @@ -5,138 +5,16 @@ import { JsonFile, JsonSchema, FileSystem } from '@rushstack/node-core-library'; import { Colorize } from '@rushstack/terminal'; import schemaJson from '../schemas/experiments.schema.json'; - -const GRADUATED_EXPERIMENTS: Set = new Set(['phasedCommands']); +import type { RushExperimentsConfiguration as IExperimentsJson } from '../schemas/experiments.schema.json.d.ts'; /** * This interface represents the raw experiments.json file which allows repo * maintainers to enable and disable experimental Rush features. * @beta */ -export interface IExperimentsJson { - /** - * By default, 'rush install' passes --no-prefer-frozen-lockfile to 'pnpm install'. - * Set this option to true to pass '--frozen-lockfile' instead for faster installs. - */ - usePnpmFrozenLockfileForRushInstall?: boolean; - - /** - * By default, 'rush update' passes --no-prefer-frozen-lockfile to 'pnpm install'. - * Set this option to true to pass '--prefer-frozen-lockfile' instead to minimize shrinkwrap changes. - */ - usePnpmPreferFrozenLockfileForRushUpdate?: boolean; - - /** - * By default, 'rush update' runs as a single operation. - * Set this option to true to instead update the lockfile with `--lockfile-only`, then perform a `--frozen-lockfile` install. - * Necessary when using the `afterAllResolved` hook in .pnpmfile.cjs. - */ - usePnpmLockfileOnlyThenFrozenLockfileForRushUpdate?: boolean; - - /** - * If using the 'preventManualShrinkwrapChanges' option, restricts the hash to only include the layout of external dependencies. - * Used to allow links between workspace projects or the addition/removal of references to existing dependency versions to not - * cause hash changes. - */ - omitImportersFromPreventManualShrinkwrapChanges?: boolean; - - /** - * If true, the chmod field in temporary project tar headers will not be normalized. - * This normalization can help ensure consistent tarball integrity across platforms. - */ - noChmodFieldInTarHeaderNormalization?: boolean; - - /** - * If true, build caching will respect the allowWarningsInSuccessfulBuild flag and cache builds with warnings. - * This will not replay warnings from the cached build. - */ - buildCacheWithAllowWarningsInSuccessfulBuild?: boolean; - - /** - * If true, build skipping will respect the allowWarningsInSuccessfulBuild flag and skip builds with warnings. - * This will not replay warnings from the skipped build. - */ - buildSkipWithAllowWarningsInSuccessfulBuild?: boolean; - - /** - * If true, perform a clean install after when running `rush install` or `rush update` if the - * `.npmrc` file has changed since the last install. - */ - cleanInstallAfterNpmrcChanges?: boolean; - - /** - * If true, print the outputs of shell commands defined in event hooks to the console. - */ - printEventHooksOutputToConsole?: boolean; +export type { IExperimentsJson }; - /** - * If true, Rush will not allow node_modules in the repo folder or in parent folders. - */ - forbidPhantomResolvableNodeModulesFolders?: boolean; - - /** - * (UNDER DEVELOPMENT) For certain installation problems involving peer dependencies, PNPM cannot - * correctly satisfy versioning requirements without installing duplicate copies of a package inside the - * node_modules folder. This poses a problem for "workspace:*" dependencies, as they are normally - * installed by making a symlink to the local project source folder. PNPM's "injected dependencies" - * feature provides a model for copying the local project folder into node_modules, however copying - * must occur AFTER the dependency project is built and BEFORE the consuming project starts to build. - * The "pnpm-sync" tool manages this operation; see its documentation for details. - * Enable this experiment if you want "rush" and "rushx" commands to resync injected dependencies - * by invoking "pnpm-sync" during the build. - */ - usePnpmSyncForInjectedDependencies?: boolean; - - /** - * If set to true, Rush will generate a `project-impact-graph.yaml` file in the repository root during `rush update`. - */ - generateProjectImpactGraphDuringRushUpdate?: boolean; - - /** - * If true, when running in watch mode, Rush will check for phase scripts named `_phase::ipc` and run them instead - * of `_phase:` if they exist. The created child process will be provided with an IPC channel and expected to persist - * across invocations. - */ - useIPCScriptsInWatchMode?: boolean; - - /** - * (UNDER DEVELOPMENT) The Rush alerts feature provides a way to send announcements to engineers - * working in the monorepo, by printing directly in the user's shell window when they invoke Rush commands. - * This ensures that important notices will be seen by anyone doing active development, since people often - * ignore normal discussion group messages or don't know to subscribe. - */ - rushAlerts?: boolean; - - /** - * Allow cobuilds without using the build cache to store previous execution info. When setting up - * distributed builds, Rush will allow uncacheable projects to still leverage the cobuild feature. - * This is useful when you want to speed up operations that can't (or shouldn't) be cached. - */ - allowCobuildWithoutCache?: boolean; - - /** - * By default, rush perform a full scan of the entire repository. For example, Rush runs `git status` to check for local file changes. - * When this toggle is enabled, Rush will only scan specific paths, significantly speeding up Git operations. - */ - enableSubpathScan?: boolean; - - /** - * Rush has a policy that normally requires Rush projects to specify `workspace:*` in package.json when depending - * on other projects in the workspace, unless they are explicitly declared as `decoupledLocalDependencies` - * in rush.json. Enabling this experiment will remove that requirement for dependencies belonging to a different - * subspace. This is useful for large product groups who work in separate subspaces and generally prefer to consume - * each other's packages via the NPM registry. - */ - exemptDecoupledDependenciesBetweenSubspaces?: boolean; - - /** - * If true, when running on macOS, Rush will omit AppleDouble files (`._*`) from build cache archives - * when a companion file exists in the same directory. AppleDouble files are automatically created by - * macOS to store extended attributes on filesystems that don't support them, and should generally not - * be included in the shared build cache. - */ - omitAppleDoubleFilesFromBuildCache?: boolean; -} +const GRADUATED_EXPERIMENTS: Set = new Set(['phasedCommands']); const _EXPERIMENTS_JSON_SCHEMA: JsonSchema = JsonSchema.fromLoadedObject(schemaJson); diff --git a/libraries/rush-lib/src/api/RushPluginsConfiguration.ts b/libraries/rush-lib/src/api/RushPluginsConfiguration.ts index f8d194d0ab1..47277082e08 100644 --- a/libraries/rush-lib/src/api/RushPluginsConfiguration.ts +++ b/libraries/rush-lib/src/api/RushPluginsConfiguration.ts @@ -4,6 +4,7 @@ import { FileSystem, JsonFile, JsonSchema } from '@rushstack/node-core-library'; import schemaJson from '../schemas/rush-plugins.schema.json'; +import type { RushPluginsConfiguration as IRushPluginsConfigurationJson } from '../schemas/rush-plugins.schema.json.d.ts'; /** * @internal @@ -17,10 +18,6 @@ export interface IRushPluginConfiguration extends IRushPluginConfigurationBase { autoinstallerName: string; } -interface IRushPluginsConfigurationJson { - plugins: IRushPluginConfiguration[]; -} - export class RushPluginsConfiguration { private static _jsonSchema: JsonSchema = JsonSchema.fromLoadedObject(schemaJson); diff --git a/libraries/rush-lib/src/api/RushUserConfiguration.ts b/libraries/rush-lib/src/api/RushUserConfiguration.ts index cdf767363bb..c92f81c02d2 100644 --- a/libraries/rush-lib/src/api/RushUserConfiguration.ts +++ b/libraries/rush-lib/src/api/RushUserConfiguration.ts @@ -7,10 +7,7 @@ import { FileSystem, JsonFile, JsonSchema, User } from '@rushstack/node-core-lib import { RushConstants } from '../logic/RushConstants'; import schemaJson from '../schemas/rush-user-settings.schema.json'; - -interface IRushUserSettingsJson { - buildCacheFolder?: string; -} +import type { RushUserSettings as IRushUserSettingsJson } from '../schemas/rush-user-settings.schema.json.d.ts'; /** * Rush per-user configuration data. diff --git a/libraries/rush-lib/src/api/SubspacesConfiguration.ts b/libraries/rush-lib/src/api/SubspacesConfiguration.ts index 91dbe477be3..fa7a9cfdb20 100644 --- a/libraries/rush-lib/src/api/SubspacesConfiguration.ts +++ b/libraries/rush-lib/src/api/SubspacesConfiguration.ts @@ -6,6 +6,7 @@ import { FileSystem, JsonFile, JsonSchema } from '@rushstack/node-core-library'; import type { RushConfiguration } from './RushConfiguration'; import schemaJson from '../schemas/subspaces.schema.json'; import { RushConstants } from '../logic/RushConstants'; +import type { RushSubspacesConfiguration as ISubspacesConfigurationJson } from '../schemas/subspaces.schema.json.d.ts'; /** * The allowed naming convention for subspace names. @@ -20,12 +21,7 @@ export const SPLIT_WORKSPACE_SUBSPACE_NAME_REGEXP: RegExp = /^[a-z0-9][+_\-a-z0- * This represents the JSON data structure for the "subspaces.json" configuration file. * See subspace.schema.json for documentation. */ -export interface ISubspacesConfigurationJson { - subspacesEnabled: boolean; - splitWorkspaceCompatibility?: boolean; - preventSelectingAllSubspaces?: boolean; - subspaceNames: string[]; -} +export type { ISubspacesConfigurationJson }; /** * This represents the subspace configurations for a repository, based on the "subspaces.json" diff --git a/libraries/rush-lib/src/schemas/approved-packages.schema.json b/libraries/rush-lib/src/schemas/approved-packages.schema.json index 0bced3cfed0..e12c276169b 100644 --- a/libraries/rush-lib/src/schemas/approved-packages.schema.json +++ b/libraries/rush-lib/src/schemas/approved-packages.schema.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "title": "Rush approved packages config file", + "title": "Rush Approved Packages Configuration", "description": "For use with the Rush tool, this file tracks a list of NPM packages that have been approved for usage. This schema is used by two config files browser-approved-packages.json and nonbrowser-approved-packages.jsons. See http://rushjs.io for details.", "definitions": { @@ -8,7 +8,7 @@ "type": "object", "properties": { "name": { - "description": "The name of the NPM package, e.g. \"@scope/example\"", + "description": "The name of the NPM package, e.g. `@scope/example`", "type": "string" }, "allowedCategories": { diff --git a/libraries/rush-lib/src/schemas/cobuild.schema.json b/libraries/rush-lib/src/schemas/cobuild.schema.json index 6fe630b89d8..33f405786df 100644 --- a/libraries/rush-lib/src/schemas/cobuild.schema.json +++ b/libraries/rush-lib/src/schemas/cobuild.schema.json @@ -1,7 +1,8 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "title": "Configuration for Rush's cobuild.", + "title": "Rush Cobuild Configuration", "description": "For use with the Rush tool, this file provides configuration options for cobuild feature. See http://rushjs.io for details.", + "x-tsdoc-release-tag": "@beta", "definitions": { "anything": { "type": ["array", "boolean", "integer", "number", "object", "string"], diff --git a/libraries/rush-lib/src/schemas/common-versions.schema.json b/libraries/rush-lib/src/schemas/common-versions.schema.json index 35e3de17634..bb4426197a6 100644 --- a/libraries/rush-lib/src/schemas/common-versions.schema.json +++ b/libraries/rush-lib/src/schemas/common-versions.schema.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "title": "Rush common-versions.json config file", + "title": "Rush Common Versions Configuration", "description": "For use with the Rush tool, this file manages dependency versions that affect all projects in the repo. See http://rushjs.io for details.", "type": "object", "properties": { diff --git a/libraries/rush-lib/src/schemas/custom-tips.schema.json b/libraries/rush-lib/src/schemas/custom-tips.schema.json index faa274fe091..2f9586d3015 100644 --- a/libraries/rush-lib/src/schemas/custom-tips.schema.json +++ b/libraries/rush-lib/src/schemas/custom-tips.schema.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "title": "Rush custom-tips.json config file", + "title": "Rush Custom Tips Configuration", "description": "The config file for adding tips to specific messages.", "type": "object", diff --git a/libraries/rush-lib/src/schemas/experiments.schema.json b/libraries/rush-lib/src/schemas/experiments.schema.json index 8a92fa9ee67..6a79b944f1a 100644 --- a/libraries/rush-lib/src/schemas/experiments.schema.json +++ b/libraries/rush-lib/src/schemas/experiments.schema.json @@ -1,7 +1,8 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "title": "Rush experiments.json config file", + "title": "Rush Experiments Configuration", "description": "For use with the Rush tool, this file allows repo maintainers to enable and disable experimental Rush features.", + "x-tsdoc-release-tag": "@beta", "type": "object", "properties": { @@ -79,7 +80,7 @@ "type": "boolean" }, "exemptDecoupledDependenciesBetweenSubspaces": { - "description": "Rush has a policy that normally requires Rush projects to specify `workspace:*` in package.json when depending on other projects in the workspace, unless they are explicitly declared as `decoupledLocalDependencies in rush.json. Enabling this experiment will remove that requirement for dependencies belonging to a different subspace. This is useful for large product groups who work in separate subspaces and generally prefer to consume each other's packages via the NPM registry.", + "description": "Rush has a policy that normally requires Rush projects to specify `workspace:*` in package.json when depending on other projects in the workspace, unless they are explicitly declared as `decoupledLocalDependencies` in rush.json. Enabling this experiment will remove that requirement for dependencies belonging to a different subspace. This is useful for large product groups who work in separate subspaces and generally prefer to consume each other's packages via the NPM registry.", "type": "boolean" }, "omitAppleDoubleFilesFromBuildCache": { diff --git a/libraries/rush-lib/src/schemas/pnpm-config.schema.json b/libraries/rush-lib/src/schemas/pnpm-config.schema.json index 4646fe2398e..5d218eae909 100644 --- a/libraries/rush-lib/src/schemas/pnpm-config.schema.json +++ b/libraries/rush-lib/src/schemas/pnpm-config.schema.json @@ -62,7 +62,7 @@ "description": "The \"globalOverrides\" setting provides a simple mechanism for overriding version selections for all dependencies of all projects in the monorepo workspace. The settings are copied into the `pnpm.overrides` field of the `common/temp/package.json` file that is generated by Rush during installation.\n\nOrder of precedence: `.pnpmfile.cjs` has the highest precedence, followed by `unsupportedPackageJsonSettings`, `globalPeerDependencyRules`, `globalPackageExtensions`, and `globalOverrides` has lowest precedence.\n\nPNPM documentation: https://pnpm.io/package_json#pnpmoverrides", "type": "object", "additionalProperties": { - "description": "You may specify the package the overridden dependency belongs to by separating the package selector from the dependency selector with a \">\", for example qar@1>zoo will only override the zoo dependency of qar@1, not for any other dependencies.", + "description": "You may specify the package the overridden dependency belongs to by separating the package selector from the dependency selector with a \">\", for example `qar@1>zoo` will only override the `zoo` dependency of `qar@1`, not for any other dependencies.", "type": "string" } }, @@ -206,7 +206,7 @@ }, "minimumReleaseAgeExclude": { - "description": "List of package names or patterns that are excluded from the minimumReleaseAge check. These packages will always install the newest version immediately, even if minimumReleaseAge is set. Supports glob patterns (e.g., \"@myorg/*\").\n\n(SUPPORTED ONLY IN PNPM 10.16.0 AND NEWER)\n\nPNPM documentation: https://pnpm.io/settings#minimumreleaseageexclude\n\nExample: [\"webpack\", \"react\", \"@myorg/*\"]", + "description": "List of package names or patterns that are excluded from the minimumReleaseAge check. These packages will always install the newest version immediately, even if minimumReleaseAge is set. Supports glob patterns (e.g., `@myorg/*`).\n\n(SUPPORTED ONLY IN PNPM 10.16.0 AND NEWER)\n\nPNPM documentation: https://pnpm.io/settings#minimumreleaseageexclude\n\nExample: [\"webpack\", \"react\", `@myorg/*`]", "type": "array", "items": { "description": "Package name or pattern", diff --git a/libraries/rush-lib/src/schemas/rush-plugins.schema.json b/libraries/rush-lib/src/schemas/rush-plugins.schema.json index caa4e0784ea..720f0dda7e3 100644 --- a/libraries/rush-lib/src/schemas/rush-plugins.schema.json +++ b/libraries/rush-lib/src/schemas/rush-plugins.schema.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-04/schema", - "title": "Rush rush-plugins.json config file", + "title": "Rush Plugins Configuration", "description": "This file defines plugins used by Rush", "type": "object", "required": ["plugins"], diff --git a/libraries/rush-lib/src/schemas/rush-user-settings.schema.json b/libraries/rush-lib/src/schemas/rush-user-settings.schema.json index dde6f7e06f3..a113ffed643 100644 --- a/libraries/rush-lib/src/schemas/rush-user-settings.schema.json +++ b/libraries/rush-lib/src/schemas/rush-user-settings.schema.json @@ -1,6 +1,6 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "title": "Rush per-user settings file", + "title": "Rush User Settings", "description": "For use with the Rush tool, this file stores user-specific settings options. See http://rushjs.io for details.", "type": "object", diff --git a/libraries/rush-lib/src/schemas/rush.schema.json b/libraries/rush-lib/src/schemas/rush.schema.json index dce5fcaae37..50778d45495 100644 --- a/libraries/rush-lib/src/schemas/rush.schema.json +++ b/libraries/rush-lib/src/schemas/rush.schema.json @@ -104,7 +104,7 @@ "type": "boolean" }, "resolutionStrategy": { - "description": "(Deprecated) Configures the strategy used to select versions during installation. This feature requires PNPM version 3.1 or newer. It corresponds to the \"--resolution-strategy\" command-line option for PNPM. Possible values are \"fast\" and \"fewer-dependencies\". PNPM's default is \"fast\", but this may be incompatible with certain packages, for example the \"@types\" packages from DefinitelyTyped. Rush's default is \"fewer-dependencies\", which causes PNPM to avoid installing a newer version if an already installed version can be reused; this is more similar to NPM's algorithm.", + "description": "(Deprecated) Configures the strategy used to select versions during installation. This feature requires PNPM version 3.1 or newer. It corresponds to the \"--resolution-strategy\" command-line option for PNPM. Possible values are \"fast\" and \"fewer-dependencies\". PNPM's default is \"fast\", but this may be incompatible with certain packages, for example the `@types` packages from DefinitelyTyped. Rush's default is \"fewer-dependencies\", which causes PNPM to avoid installing a newer version if an already installed version can be reused; this is more similar to NPM's algorithm.", "type": "string", "enum": ["fewer-dependencies", "fast"] }, @@ -156,7 +156,7 @@ } }, "ignoredNpmScopes": { - "description": "A list of NPM package scopes that will be excluded from review (e.g. \"@types\")", + "description": "A list of NPM package scopes that will be excluded from review (e.g. `@types`)", "type": "array", "items": { "type": "string", @@ -171,14 +171,14 @@ "type": "object", "properties": { "allowedEmailRegExps": { - "description": "A list of regular expressions describing allowable e-mail patterns for Git commits. They are case-insensitive anchored JavaScript RegExps. Example: \".*@example\\.com\"", + "description": "A list of regular expressions describing allowable e-mail patterns for Git commits. They are case-insensitive anchored JavaScript RegExps. Example: `.*@example\\.com`", "type": "array", "items": { "type": "string" } }, "sampleEmail": { - "description": "An example valid e-mail address for \"Mr. Example\" that conforms to one of the allowedEmailRegExps. Example: \"mr-example@contoso\\.com\"", + "description": "An example valid e-mail address for \"Mr. Example\" that conforms to one of the allowedEmailRegExps. Example: `mr-example@contoso\\.com`", "type": "string" }, "versionBumpCommitMessage": { @@ -249,7 +249,7 @@ "type": "boolean" }, "allowedProjectTags": { - "description": "This is an optional, but recommended, list of allowed tags that can be applied to Rush projects using the \"tags\" setting in this file. This list is useful for preventing mistakes such as misspelling, and it also provides a centralized place to document your tags. If \"allowedProjectTags\" list is not specified, then any valid tag is allowed. A tag name must be one or more words separated by hyphens or slashes, where a word may contain lowercase ASCII letters, digits, \".\", and \"@\" characters.", + "description": "This is an optional, but recommended, list of allowed tags that can be applied to Rush projects using the \"tags\" setting in this file. This list is useful for preventing mistakes such as misspelling, and it also provides a centralized place to document your tags. If \"allowedProjectTags\" list is not specified, then any valid tag is allowed. A tag name must be one or more words separated by hyphens or slashes, where a word may contain lowercase ASCII letters, digits, \".\", and `@` characters.", "type": "array", "items": { "type": "string", @@ -305,7 +305,7 @@ "type": "string" }, "tags": { - "description": "An optional set of custom tags that can be used to select this project. For example, adding \"my-custom-tag\" will allow this project to be selected by the command \"rush list --only tag:my-custom-tag\". The tag name must be one or more words separated by hyphens or slashes, where a word may contain lowercase ASCII letters, digits, \".\", and \"@\" characters.", + "description": "An optional set of custom tags that can be used to select this project. For example, adding \"my-custom-tag\" will allow this project to be selected by the command \"rush list --only tag:my-custom-tag\". The tag name must be one or more words separated by hyphens or slashes, where a word may contain lowercase ASCII letters, digits, \".\", and `@` characters.", "type": "array", "items": { "type": "string", diff --git a/libraries/rush-lib/src/schemas/subspaces.schema.json b/libraries/rush-lib/src/schemas/subspaces.schema.json index 5322a806a7b..de9bdcbae09 100644 --- a/libraries/rush-lib/src/schemas/subspaces.schema.json +++ b/libraries/rush-lib/src/schemas/subspaces.schema.json @@ -1,9 +1,11 @@ { "$schema": "http://json-schema.org/draft-04/schema#", - "title": "Rush subspace config file.", + "title": "Rush Subspaces Configuration", "description": "The configuration file for enabling the subspaces feature in rush. This is an EXPERIMENTAL feature which is not yet fully implemented. To opt into the experiment, simply toggle the 'enabled' property in this file.", "type": "object", + "required": ["subspacesEnabled", "subspaceNames"], + "properties": { "$schema": { "description": "Part of the JSON Schema standard, this optional keyword declares the URL of the schema that the file conforms to. Editors may download the schema and use it to perform syntax highlighting.", diff --git a/libraries/rush-lib/webpack.config.js b/libraries/rush-lib/webpack.config.js index 6952beba9dc..df64833e2b8 100644 --- a/libraries/rush-lib/webpack.config.js +++ b/libraries/rush-lib/webpack.config.js @@ -100,8 +100,7 @@ module.exports = () => { path: `${__dirname}/temp/build/webpack-dll/[name].json`, inFolderName: 'lib-intermediate-esm', outFolderName: 'lib-commonjs', - pathsToIgnore: ['utilities/prompts/SearchListPrompt.js'], - dTsFilesInputFolderName: 'lib-dts' + pathsToIgnore: ['utilities/prompts/SearchListPrompt.js'] }) ], { diff --git a/libraries/rush-sdk/config/heft.json b/libraries/rush-sdk/config/heft.json index 21b0acb80a3..3072d84888c 100644 --- a/libraries/rush-sdk/config/heft.json +++ b/libraries/rush-sdk/config/heft.json @@ -31,16 +31,18 @@ "sourcePath": "./node_modules/@microsoft/rush-lib/dist", "includeGlobs": ["rush-lib.d.ts"], "destinationFolders": ["dist"] + }, + { + "sourcePath": "./node_modules/@microsoft/rush-lib/lib-dts", + "destinationFolders": ["lib-dts"], + "fileExtensions": [".d.ts"], + "hardlink": true } ] } } }, - "typescript": { - "taskDependencies": ["copy-rush-lib-types"] - }, - "webpack": { "taskDependencies": ["typescript"], "taskPlugin": { @@ -49,7 +51,7 @@ }, "generate-stubs": { - "taskDependencies": ["typescript"], + "taskDependencies": ["typescript", "copy-rush-lib-types"], "taskPlugin": { "pluginPackage": "@rushstack/heft", "pluginName": "run-script-plugin", diff --git a/libraries/rush-sdk/src/generate-stubs.ts b/libraries/rush-sdk/src/generate-stubs.ts index d43b5502fec..8f110769f63 100644 --- a/libraries/rush-sdk/src/generate-stubs.ts +++ b/libraries/rush-sdk/src/generate-stubs.ts @@ -6,64 +6,52 @@ import * as path from 'node:path'; import type { IRunScriptOptions } from '@rushstack/heft'; import { Async, FileSystem, type FolderItem, Import, JsonFile, Path } from '@rushstack/node-core-library'; -interface IGenerateOptions { +interface IGenerateJsStubsOptions { parentSourcePath: string; - parentCjsTargetPath: string; - parentDtsTargetPath: string; + parentTargetPath: string; parentSrcImportPathWithSlash: string; libShimIndexPath: string; } -interface IFileTask { - type: 'dts' | 'js'; - sourcePath: string; +interface IJsStubTask { + jsSourcePath: string; targetPath: string; - srcImportPath?: string; - shimPathLiteral?: string; + srcImportPath: string; + shimPathLiteral: string; } -async function* collectFileTasksAsync(options: IGenerateOptions): AsyncGenerator { - const { - parentSourcePath, - parentCjsTargetPath, - parentDtsTargetPath, - parentSrcImportPathWithSlash, - libShimIndexPath - } = options; - const folderItems: FolderItem[] = await FileSystem.readFolderItemsAsync(options.parentSourcePath); +/** + * Walks rush-lib/lib-commonjs to collect JS stub tasks. These stubs redirect + * require() calls through the rush-sdk shim so that the actual rush-lib module + * is loaded at runtime. + */ +async function* collectJsStubTasksAsync(options: IGenerateJsStubsOptions): AsyncGenerator { + const { parentSourcePath, parentTargetPath, parentSrcImportPathWithSlash, libShimIndexPath } = options; + const folderItems: FolderItem[] = await FileSystem.readFolderItemsAsync(parentSourcePath); for (const folderItem of folderItems) { const itemName: string = folderItem.name; const sourcePath: string = `${parentSourcePath}/${itemName}`; - const cjsTargetPath: string = `${parentCjsTargetPath}/${itemName}`; - const dtsTargetPath: string = `${parentDtsTargetPath}/${itemName}`; + const targetPath: string = `${parentTargetPath}/${itemName}`; if (folderItem.isDirectory()) { // Ensure destination folder exists - await FileSystem.ensureFolderAsync(cjsTargetPath); + await FileSystem.ensureFolderAsync(targetPath); // Recursively yield tasks from subdirectory - yield* collectFileTasksAsync({ + yield* collectJsStubTasksAsync({ parentSourcePath: sourcePath, - parentCjsTargetPath: cjsTargetPath, - parentDtsTargetPath: dtsTargetPath, + parentTargetPath: targetPath, parentSrcImportPathWithSlash: parentSrcImportPathWithSlash + itemName + '/', libShimIndexPath }); - } else if (folderItem.name.endsWith('.d.ts')) { - yield { - type: 'dts', - sourcePath, - targetPath: dtsTargetPath - }; } else if (folderItem.name.endsWith('.js')) { const srcImportPath: string = parentSrcImportPathWithSlash + path.parse(folderItem.name).name; - const shimPath: string = path.relative(parentCjsTargetPath, libShimIndexPath); + const shimPath: string = path.relative(parentTargetPath, libShimIndexPath); const shimPathLiteral: string = JSON.stringify(Path.convertToSlashes(shimPath)); yield { - type: 'js', - sourcePath, - targetPath: cjsTargetPath, + jsSourcePath: sourcePath, + targetPath, srcImportPath, shimPathLiteral }; @@ -71,43 +59,36 @@ async function* collectFileTasksAsync(options: IGenerateOptions): AsyncGenerator } } -async function processFileTaskAsync(task: IFileTask): Promise { - const { type, sourcePath, targetPath, srcImportPath, shimPathLiteral } = task; - if (type === 'dts') { - await FileSystem.copyFileAsync({ - sourcePath, - destinationPath: targetPath - }); - } else { - const srcImportPathLiteral: string = JSON.stringify(srcImportPath); - - let namedExportsAssignment: string = ''; - try { - // Read the sidecar .exports.json file generated by DeepImportsPlugin to get module exports - const exportsJsonPath: string = sourcePath.slice(0, -'.js'.length) + '.exports.json'; - const { moduleExports }: { moduleExports: string[] } = await JsonFile.loadAsync(exportsJsonPath); - if (moduleExports.length > 0) { - // Assign named exports after module.exports to ensure they're properly exposed for ESM imports - namedExportsAssignment = - '\n' + moduleExports.map((exportName) => `exports.${exportName} = _m.${exportName};`).join('\n'); - } - } catch (e) { - if (!FileSystem.isNotExistError(e)) { - throw e; - } +async function processJsStubTaskAsync(task: IJsStubTask): Promise { + const { jsSourcePath, targetPath, srcImportPath, shimPathLiteral } = task; + const srcImportPathLiteral: string = JSON.stringify(srcImportPath); + + let namedExportsAssignment: string = ''; + try { + // Read the sidecar .exports.json file generated by DeepImportsPlugin to get module exports + const exportsJsonPath: string = jsSourcePath.slice(0, -'.js'.length) + '.exports.json'; + const { moduleExports }: { moduleExports: string[] } = await JsonFile.loadAsync(exportsJsonPath); + if (moduleExports.length > 0) { + // Assign named exports after module.exports to ensure they're properly exposed for ESM imports + namedExportsAssignment = + '\n' + moduleExports.map((exportName) => `exports.${exportName} = _m.${exportName};`).join('\n'); + } + } catch (e) { + if (!FileSystem.isNotExistError(e)) { + throw e; } - - await FileSystem.writeFileAsync( - targetPath, - // Example: - // ``` - // const _m = require("../../../lib-shim/index")._rushSdk_loadInternalModule("logic/policy/GitEmailPolicy"); - // module.exports = _m; - // exports.GitEmailPolicy = _m.GitEmailPolicy; - // ``` - `const _m = require(${shimPathLiteral})._rushSdk_loadInternalModule(${srcImportPathLiteral});\nmodule.exports = _m;${namedExportsAssignment}\n` - ); } + + await FileSystem.writeFileAsync( + targetPath, + // Example: + // ``` + // const _m = require("../../../lib-shim/index")._rushSdk_loadInternalModule("logic/policy/GitEmailPolicy"); + // module.exports = _m; + // exports.GitEmailPolicy = _m.GitEmailPolicy; + // ``` + `const _m = require(${shimPathLiteral})._rushSdk_loadInternalModule(${srcImportPathLiteral});\nmodule.exports = _m;${namedExportsAssignment}\n` + ); } // Entry point invoked by "runScript" action from config/heft.json @@ -126,23 +107,20 @@ export async function runAsync(options: IRunScriptOptions): Promise { }); const cjsStubsTargetPath: string = `${buildFolderPath}/lib-commonjs`; - const dtsStubsTargetPath: string = `${buildFolderPath}/lib-dts`; - terminal.writeLine( - `generate-stubs: Generating stub files under ${cjsStubsTargetPath} and ${dtsStubsTargetPath}` - ); + terminal.writeLine(`generate-stubs: Generating stub files under ${cjsStubsTargetPath}`); // Ensure the target folder exists await FileSystem.ensureFolderAsync(cjsStubsTargetPath); - // Collect and process file tasks in parallel with controlled concurrency - const tasks: AsyncGenerator = collectFileTasksAsync({ + // Generate JS stubs from rush-lib/lib-commonjs (these redirect require() through the shim) + // Note: .d.ts files are copied separately by the copy-rush-lib-types heft task from rush-lib/lib-dts + const jsTasks: AsyncGenerator = collectJsStubTasksAsync({ parentSourcePath: `${rushLibFolder}/lib-commonjs`, - parentCjsTargetPath: cjsStubsTargetPath, - parentDtsTargetPath: dtsStubsTargetPath, + parentTargetPath: cjsStubsTargetPath, parentSrcImportPathWithSlash: '', libShimIndexPath: `${buildFolderPath}/lib-shim/index.js` }); - await Async.forEachAsync(tasks, processFileTaskAsync, { concurrency: 50 }); + await Async.forEachAsync(jsTasks, processJsStubTaskAsync, { concurrency: 50 }); terminal.writeLine('generate-stubs: Completed successfully.'); } diff --git a/libraries/typings-generator/config/rig.json b/libraries/typings-generator/config/rig.json index 165ffb001f5..cc98dea43dd 100644 --- a/libraries/typings-generator/config/rig.json +++ b/libraries/typings-generator/config/rig.json @@ -3,5 +3,5 @@ // Documentation for this system: https://www.npmjs.com/package/@rushstack/rig-package "$schema": "https://developer.microsoft.com/json-schemas/rig-package/rig.schema.json", - "rigPackageName": "local-node-rig" + "rigPackageName": "decoupled-local-node-rig" } diff --git a/libraries/typings-generator/eslint.config.js b/libraries/typings-generator/eslint.config.js index c15e6077310..e54effd122a 100644 --- a/libraries/typings-generator/eslint.config.js +++ b/libraries/typings-generator/eslint.config.js @@ -1,8 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. // See LICENSE in the project root for license information. -const nodeTrustedToolProfile = require('local-node-rig/profiles/default/includes/eslint/flat/profile/node-trusted-tool'); -const friendlyLocalsMixin = require('local-node-rig/profiles/default/includes/eslint/flat/mixins/friendly-locals'); +const nodeTrustedToolProfile = require('decoupled-local-node-rig/profiles/default/includes/eslint/flat/profile/node-trusted-tool'); +const friendlyLocalsMixin = require('decoupled-local-node-rig/profiles/default/includes/eslint/flat/mixins/friendly-locals'); module.exports = [ ...nodeTrustedToolProfile, diff --git a/libraries/typings-generator/package.json b/libraries/typings-generator/package.json index 5e438eecb6d..fc0e9bf0518 100644 --- a/libraries/typings-generator/package.json +++ b/libraries/typings-generator/package.json @@ -51,8 +51,8 @@ }, "devDependencies": { "@rushstack/heft": "workspace:*", - "eslint": "~9.37.0", - "local-node-rig": "workspace:*" + "decoupled-local-node-rig": "workspace:*", + "eslint": "~9.37.0" }, "peerDependencies": { "@types/node": "*" diff --git a/libraries/typings-generator/tsconfig.json b/libraries/typings-generator/tsconfig.json index dac21d04081..1a33d17b873 100644 --- a/libraries/typings-generator/tsconfig.json +++ b/libraries/typings-generator/tsconfig.json @@ -1,3 +1,3 @@ { - "extends": "./node_modules/local-node-rig/profiles/default/tsconfig-base.json" + "extends": "./node_modules/decoupled-local-node-rig/profiles/default/tsconfig-base.json" } diff --git a/rigs/decoupled-local-node-rig/package.json b/rigs/decoupled-local-node-rig/package.json index 3d9f26bee4f..aff7b2d86f4 100644 --- a/rigs/decoupled-local-node-rig/package.json +++ b/rigs/decoupled-local-node-rig/package.json @@ -13,6 +13,7 @@ "@rushstack/eslint-config": "4.6.2", "@rushstack/eslint-patch": "1.16.0", "@rushstack/eslint-plugin": "0.23.0", + "@rushstack/heft-json-schema-typings-plugin": "1.2.0", "@rushstack/heft-node-rig": "2.11.20", "@rushstack/heft": "1.2.0", "@types/heft-jest": "1.0.1", diff --git a/rigs/decoupled-local-node-rig/profiles/default/config/heft.json b/rigs/decoupled-local-node-rig/profiles/default/config/heft.json index 77fe092ba04..f97687a9621 100644 --- a/rigs/decoupled-local-node-rig/profiles/default/config/heft.json +++ b/rigs/decoupled-local-node-rig/profiles/default/config/heft.json @@ -5,7 +5,7 @@ "phasesByName": { "build": { - "cleanFiles": [{ "includeGlobs": ["lib-esnext"] }], + "cleanFiles": [{ "includeGlobs": ["lib-esnext", "temp/schema-ts"] }], "tasksByName": { "lint": { @@ -14,6 +14,17 @@ "sarifLogPath": "temp/build/lint/lint.sarif" } } + }, + + "json-schema-typings": { + "taskPlugin": { + "pluginPackage": "@rushstack/heft-json-schema-typings-plugin", + "pluginName": "json-schema-typings-plugin", + "options": { + "generatedTsFolders": ["temp/schema-ts", "lib-dts"], + "formatWithPrettier": true + } + } } } }, diff --git a/rigs/decoupled-local-node-rig/profiles/default/tsconfig-base.json b/rigs/decoupled-local-node-rig/profiles/default/tsconfig-base.json index a70f8605252..025cbf19728 100644 --- a/rigs/decoupled-local-node-rig/profiles/default/tsconfig-base.json +++ b/rigs/decoupled-local-node-rig/profiles/default/tsconfig-base.json @@ -11,6 +11,7 @@ "outDir": "${configDir}/lib-commonjs", "declarationDir": "${configDir}/lib-dts", "rootDir": "${configDir}/src", + "rootDirs": ["${configDir}/src", "${configDir}/temp/schema-ts"], "types": ["heft-jest", "node"], "typeRoots": ["${configDir}/node_modules/@types", "../../node_modules/@types"] diff --git a/rigs/local-node-rig/package.json b/rigs/local-node-rig/package.json index 9a8256b7c26..b401b2f87b8 100644 --- a/rigs/local-node-rig/package.json +++ b/rigs/local-node-rig/package.json @@ -11,13 +11,14 @@ "dependencies": { "@microsoft/api-extractor": "workspace:*", "@rushstack/eslint-patch": "workspace:*", + "@rushstack/heft-json-schema-typings-plugin": "workspace:*", "@rushstack/heft-node-rig": "workspace:*", "@rushstack/heft": "workspace:*", "@types/heft-jest": "1.0.1", "@types/node": "20.17.19", - "local-eslint-config": "workspace:*", "eslint": "~9.37.0", "jest-junit": "12.3.0", + "local-eslint-config": "workspace:*", "typescript": "~5.8.2" } } diff --git a/rigs/local-node-rig/profiles/default/config/heft.json b/rigs/local-node-rig/profiles/default/config/heft.json index 77fe092ba04..c3f6c74be99 100644 --- a/rigs/local-node-rig/profiles/default/config/heft.json +++ b/rigs/local-node-rig/profiles/default/config/heft.json @@ -5,7 +5,7 @@ "phasesByName": { "build": { - "cleanFiles": [{ "includeGlobs": ["lib-esnext"] }], + "cleanFiles": [{ "includeGlobs": ["lib-esnext", "temp/schema-ts"] }], "tasksByName": { "lint": { @@ -14,6 +14,21 @@ "sarifLogPath": "temp/build/lint/lint.sarif" } } + }, + + "json-schema-typings": { + "taskPlugin": { + "pluginPackage": "@rushstack/heft-json-schema-typings-plugin", + "pluginName": "json-schema-typings-plugin", + "options": { + "generatedTsFolders": ["temp/schema-ts", "lib-dts"], + "formatWithPrettier": true + } + } + }, + + "typescript": { + "taskDependencies": ["json-schema-typings"] } } }, diff --git a/rigs/local-node-rig/profiles/default/tsconfig-base.json b/rigs/local-node-rig/profiles/default/tsconfig-base.json index a70f8605252..025cbf19728 100644 --- a/rigs/local-node-rig/profiles/default/tsconfig-base.json +++ b/rigs/local-node-rig/profiles/default/tsconfig-base.json @@ -11,6 +11,7 @@ "outDir": "${configDir}/lib-commonjs", "declarationDir": "${configDir}/lib-dts", "rootDir": "${configDir}/src", + "rootDirs": ["${configDir}/src", "${configDir}/temp/schema-ts"], "types": ["heft-jest", "node"], "typeRoots": ["${configDir}/node_modules/@types", "../../node_modules/@types"] diff --git a/rigs/local-web-rig/package.json b/rigs/local-web-rig/package.json index 32af5b941d0..58d5230980c 100644 --- a/rigs/local-web-rig/package.json +++ b/rigs/local-web-rig/package.json @@ -11,13 +11,14 @@ "dependencies": { "@microsoft/api-extractor": "workspace:*", "@rushstack/eslint-patch": "workspace:*", + "@rushstack/heft-json-schema-typings-plugin": "workspace:*", "@rushstack/heft-web-rig": "workspace:*", "@rushstack/heft": "workspace:*", "@types/heft-jest": "1.0.1", "@types/webpack-env": "1.18.8", - "local-eslint-config": "workspace:*", "eslint": "~9.37.0", "jest-junit": "12.3.0", + "local-eslint-config": "workspace:*", "typescript": "~5.8.2" } } diff --git a/rigs/local-web-rig/profiles/app/config/heft.json b/rigs/local-web-rig/profiles/app/config/heft.json index 1888d38a36f..18b5e9c5913 100644 --- a/rigs/local-web-rig/profiles/app/config/heft.json +++ b/rigs/local-web-rig/profiles/app/config/heft.json @@ -5,7 +5,7 @@ "phasesByName": { "build": { - "cleanFiles": [{ "includeGlobs": ["lib-dts", "lib-esm"] }], + "cleanFiles": [{ "includeGlobs": ["lib-dts", "lib-esm", "temp/schema-ts"] }], "tasksByName": { "lint": { @@ -14,6 +14,21 @@ "sarifLogPath": "temp/build/lint/lint.sarif" } } + }, + + "json-schema-typings": { + "taskPlugin": { + "pluginPackage": "@rushstack/heft-json-schema-typings-plugin", + "pluginName": "json-schema-typings-plugin", + "options": { + "generatedTsFolders": ["temp/schema-ts", "lib-dts"], + "formatWithPrettier": true + } + } + }, + + "typescript": { + "taskDependencies": ["json-schema-typings"] } } }, diff --git a/rigs/local-web-rig/profiles/app/tsconfig-base.json b/rigs/local-web-rig/profiles/app/tsconfig-base.json index e609adca759..f61d1820f6d 100644 --- a/rigs/local-web-rig/profiles/app/tsconfig-base.json +++ b/rigs/local-web-rig/profiles/app/tsconfig-base.json @@ -13,7 +13,7 @@ "outDir": "${configDir}/lib-esm", "declarationDir": "${configDir}/lib-dts", "rootDir": "${configDir}/src", - "rootDirs": ["${configDir}/src", "${configDir}/temp/sass-ts"], + "rootDirs": ["${configDir}/src", "${configDir}/temp/sass-ts", "${configDir}/temp/schema-ts"], "types": ["heft-jest", "webpack-env"], "typeRoots": ["${configDir}/node_modules/@types", "../../node_modules/@types"] diff --git a/rigs/local-web-rig/profiles/library/config/heft.json b/rigs/local-web-rig/profiles/library/config/heft.json index 541a146a9c8..91d18f13ef5 100644 --- a/rigs/local-web-rig/profiles/library/config/heft.json +++ b/rigs/local-web-rig/profiles/library/config/heft.json @@ -5,7 +5,7 @@ "phasesByName": { "build": { - "cleanFiles": [{ "includeGlobs": ["lib-dts", "lib-esm"] }], + "cleanFiles": [{ "includeGlobs": ["lib-dts", "lib-esm", "temp/schema-ts"] }], "tasksByName": { "lint": { @@ -14,6 +14,21 @@ "sarifLogPath": "temp/build/lint/lint.sarif" } } + }, + + "json-schema-typings": { + "taskPlugin": { + "pluginPackage": "@rushstack/heft-json-schema-typings-plugin", + "pluginName": "json-schema-typings-plugin", + "options": { + "generatedTsFolders": ["temp/schema-ts", "lib-dts"], + "formatWithPrettier": true + } + } + }, + + "typescript": { + "taskDependencies": ["json-schema-typings"] } } }, diff --git a/rigs/local-web-rig/profiles/library/tsconfig-base.json b/rigs/local-web-rig/profiles/library/tsconfig-base.json index eec41564e0e..de5406f3052 100644 --- a/rigs/local-web-rig/profiles/library/tsconfig-base.json +++ b/rigs/local-web-rig/profiles/library/tsconfig-base.json @@ -10,7 +10,7 @@ "outDir": "${configDir}/lib-esm", "declarationDir": "${configDir}/lib-dts", "rootDir": "${configDir}/src", - "rootDirs": ["${configDir}/src", "${configDir}/temp/sass-ts"], + "rootDirs": ["${configDir}/src", "${configDir}/temp/sass-ts", "${configDir}/temp/schema-ts"], "types": ["heft-jest", "webpack-env"], "typeRoots": ["${configDir}/node_modules/@types", "../../node_modules/@types"] diff --git a/rush-plugins/rush-azure-storage-build-cache-plugin/src/AzureAuthenticationBase.ts b/rush-plugins/rush-azure-storage-build-cache-plugin/src/AzureAuthenticationBase.ts index 2be93baa713..e85409d6bd1 100644 --- a/rush-plugins/rush-azure-storage-build-cache-plugin/src/AzureAuthenticationBase.ts +++ b/rush-plugins/rush-azure-storage-build-cache-plugin/src/AzureAuthenticationBase.ts @@ -137,7 +137,7 @@ export interface IAzureAuthenticationBaseOptions { */ export interface ICredentialResult { credentialString: string; expiresOn?: Date; - credentialMetadata?: object; + credentialMetadata?: { [k: string]: unknown }; } /** diff --git a/rush.json b/rush.json index 8d2151e9cc1..d13407943b8 100644 --- a/rush.json +++ b/rush.json @@ -1373,6 +1373,7 @@ "@rushstack/eslint-config", "@rushstack/eslint-patch", "@rushstack/eslint-plugin", + "@rushstack/heft-json-schema-typings-plugin", "@rushstack/heft-node-rig", "@rushstack/heft" ]