license import * as path from 'path' ; import * as ts from 'typescript' ; /**
 * The configuration block provided by the tsconfig "bazelOptions".
 * Note that all paths here are relative to the rootDir, not absolute nor
 * relative to the location containing the tsconfig file.
 */ export interface BazelOptions { /** Name of the bazel workspace where we are building. */ workspaceName : string ; /** The full bazel target that is being built, e.g. //my/pkg:library. */ target : string ; /** The bazel package, eg my/pkg */ package : string ; /** If true, convert require()s into goog.module(). */ googmodule : boolean ; /**
     * If true, emit devmode output into filename.js.
     * If false, emit prodmode output into filename.mjs.
     */ es5Mode : boolean ; /** If true, convert TypeScript code into a Closure-compatible variant. */ tsickle : boolean ; /** If true, generate externs from declarations in d.ts files. */ tsickleGenerateExterns : boolean ; /** Write generated externs to the given path. */ tsickleExternsPath : string ; /** Paths of declarations whose types must not appear in result .d.ts. */ typeBlackListPaths : string [ ] ; /** If true, emit Closure types in TypeScript->JS output. */ untyped : boolean ; /** The list of sources we're interested in (emitting and type checking). */ compilationTargetSrc : string [ ] ; /** Path to write the module dependency manifest to. */ manifest : string ; /**
     * Whether to disable strict deps check. If true the next parameter is
     * ignored.
     */ disableStrictDeps ? : boolean ; /**
     * Paths of dependencies that are allowed by strict deps, i.e. that may be
     * imported by the source files in compilationTargetSrc.
     */ allowedStrictDeps : string [ ] ; /** Write a performance trace to this path. Disabled when falsy. */ perfTracePath ? : string ; /**
     * An additional prelude to insert after the `goog.module` call,
     * e.g. with additional imports or requires.
     */ prelude : string ; /**
     * Name of the current locale if processing a locale-specific file.
     */ locale ? : string ; /**
     * A list of errors this compilation is expected to generate, in the form
     * "TS1234:regexp". If empty, compilation is expected to succeed.
     */ expectedDiagnostics : string [ ] ; /**
     * To support node_module resolution, allow TypeScript to make arbitrary
     * file system access to paths under this prefix.
     */ nodeModulesPrefix : string ; /**
     * List of regexes on file paths for which we suppress tsickle's warnings.
     */ ignoreWarningPaths : string [ ] ; /**
     * Whether to add aliases to the .d.ts files to add the exports to the
     * ಠ_ಠ.clutz namespace.
     */ addDtsClutzAliases : true ; /**
     * Whether to type check inputs that aren't srcs.  Differs from
     * --skipLibCheck, which skips all .d.ts files, even those which are
     * srcs.
     */ typeCheckDependencies : boolean ; /**
     * The maximum cache size for bazel outputs, in megabytes.
     */ maxCacheSizeMb ? : number ; /**
     * Suppress warnings about tsconfig.json properties that are overridden.
     * Currently unused, remains here for backwards compat for users who set it.
     */ suppressTsconfigOverrideWarnings : boolean ; /**
     * An explicit name for this module, given by the module_name attribute on a
     * ts_library.
     */ moduleName ? : string ; /**
     * An explicit entry point for this module, given by the module_root attribute
     * on a ts_library.
     */ moduleRoot ? : string ; /**
     * If true, indicates that this job is transpiling JS sources. If true, only
     * one file can appear in compilationTargetSrc, and either
     * transpiledJsOutputFileName or the transpiledJs*Directory options must be
     * set.
     */ isJsTranspilation ? : boolean ; /**
     * The path where the file containing the JS transpiled output should be
     * written. Ignored if isJsTranspilation is false. transpiledJsOutputFileName
     *
     */ transpiledJsOutputFileName ? : string ; /**
     * The path where transpiled JS output should be written. Ignored if
     * isJsTranspilation is false. Must not be set together with
     * transpiledJsOutputFileName.
     */ transpiledJsInputDirectory ? : string ; /**
     * The path where transpiled JS output should be written. Ignored if
     * isJsTranspilation is false. Must not be set together with
     * transpiledJsOutputFileName.
     */ transpiledJsOutputDirectory ? : string ; /**
     * Whether the user provided an implementation shim for .d.ts files in the
     * compilation unit.
     */ hasImplementation ? : boolean ; /**
     * If present, run the Angular ngtsc plugin with the given options.
     */ angularCompilerOptions ? : { [ k ] : any ; assets : string [ ] ; } ; /**
     * Override for ECMAScript target language level to use for devmode.
     *
     * This setting can be set in a user's tsconfig to override the default
     * devmode target.
     *
     * EXPERIMENTAL: This setting is experimental and may be removed in the
     * future.
     */ devmodeTargetOverride ? : string ; /**
     * Whether to type check.  Differs from typeCheckDependencies in that this
     * avoids type checking the srcs in addition to the dependencies.
     */ typeCheck : boolean ; } export interface ParsedTsConfig { options : ts . CompilerOptions ; bazelOpts : BazelOptions ; angularCompilerOptions ? : { [ k ] : unknown ; } ; files : string [ ] ; disabledTsetseRules : string [ ] ; config : { } ; } interface PluginImportWithConfig extends ts . PluginImport { [ optionName ] : string | { } ; } /**
 * The same as Node's path.resolve, however it returns a path with forward
 * slashes rather than joining the resolved path with the platform's path
 * separator.
 * Note that even path.posix.resolve('.') returns C:\Users\... with backslashes.
 */ export function resolveNormalizedPath ( ... segments ) { return path . resolve ( ... segments ) . replace ( /\\/g , '/' ) ; } param tsconfigFile return export function parseTsconfig ( tsconfigFile , host = ts . sys ) { tsconfigFile = resolveNormalizedPath ( tsconfigFile ) ; const isUndefined = ( value ) : value is undefined => value === undefined ; const readExtendedConfigFile = ( configFile , existingConfig ? ) : { config ? : any ; error ? : ts . Diagnostic ; } => { const { config , error } = ts . readConfigFile ( configFile , host . readFile ) ; if ( error ) { return { error } ; } const mergedConfig = existingConfig || config ; if ( existingConfig ) { const existingBazelOpts = existingConfig . bazelOptions || { } ; const newBazelBazelOpts = config . bazelOptions || { } ; mergedConfig . bazelOptions = { ... existingBazelOpts , disableStrictDeps : isUndefined ( existingBazelOpts . disableStrictDeps ) ? newBazelBazelOpts . disableStrictDeps : existingBazelOpts . disableStrictDeps , suppressTsconfigOverrideWarnings : isUndefined ( existingBazelOpts . suppressTsconfigOverrideWarnings ) ? newBazelBazelOpts . suppressTsconfigOverrideWarnings : existingBazelOpts . suppressTsconfigOverrideWarnings , tsickle : isUndefined ( existingBazelOpts . tsickle ) ? newBazelBazelOpts . tsickle : existingBazelOpts . tsickle , googmodule : isUndefined ( existingBazelOpts . googmodule ) ? newBazelBazelOpts . googmodule : existingBazelOpts . googmodule , devmodeTargetOverride : isUndefined ( existingBazelOpts . devmodeTargetOverride ) ? newBazelBazelOpts . devmodeTargetOverride : existingBazelOpts . devmodeTargetOverride } ; } if ( config . extends ) { let extendedConfigPath = resolveNormalizedPath ( path . dirname ( configFile ) , config . extends ) ; if ( ! extendedConfigPath . endsWith ( '.json' ) ) extendedConfigPath += '.json' ; return readExtendedConfigFile ( extendedConfigPath , mergedConfig ) ; } return { config : mergedConfig } ; } ; const { config , error } = readExtendedConfigFile ( tsconfigFile ) ; if ( error ) { return [ null , [ error ] , { target : '' } ] ; } const { options , errors , fileNames } = ts . parseJsonConfigFileContent ( config , host , path . dirname ( tsconfigFile ) ) ; const bazelOpts = config . bazelOptions || { } ; const target = bazelOpts . target ; bazelOpts . allowedStrictDeps = bazelOpts . allowedStrictDeps || [ ] ; bazelOpts . typeBlackListPaths = bazelOpts . typeBlackListPaths || [ ] ; bazelOpts . compilationTargetSrc = bazelOpts . compilationTargetSrc || [ ] ; if ( errors && errors . length ) { return [ null , errors , { target } ] ; } if ( bazelOpts . es5Mode && bazelOpts . devmodeTargetOverride ) { switch ( bazelOpts . devmodeTargetOverride . toLowerCase ( ) ) { case 'es3' : options . target = ts . ScriptTarget . ES3 ; break ; case 'es5' : options . target = ts . ScriptTarget . ES5 ; break ; case 'es2015' : options . target = ts . ScriptTarget . ES2015 ; break ; case 'es2016' : options . target = ts . ScriptTarget . ES2016 ; break ; case 'es2017' : options . target = ts . ScriptTarget . ES2017 ; break ; case 'es2018' : options . target = ts . ScriptTarget . ES2018 ; break ; case 'esnext' : options . target = ts . ScriptTarget . ESNext ; break ; default : console . error ( 'WARNING: your tsconfig.json file specifies an invalid bazelOptions.devmodeTargetOverride value of: \'${bazelOpts.devmodeTargetOverride\'' ) ; } } if ( options . rootDirs ) options . rootDirs . sort ( ( a , b ) => b . length - a . length ) ; if ( bazelOpts . googmodule ) options . module = ts . ModuleKind . CommonJS ; const files = fileNames . map ( f => path . posix . normalize ( f ) ) ; bazelOpts . compilationTargetSrc = bazelOpts . compilationTargetSrc . map ( f => resolveNormalizedPath ( options . rootDir ! , f ) ) ; bazelOpts . allowedStrictDeps = bazelOpts . allowedStrictDeps . map ( f => resolveNormalizedPath ( options . rootDir ! , f ) ) ; bazelOpts . typeBlackListPaths = bazelOpts . typeBlackListPaths . map ( f => resolveNormalizedPath ( options . rootDir ! , f ) ) ; if ( bazelOpts . nodeModulesPrefix ) { bazelOpts . nodeModulesPrefix = resolveNormalizedPath ( options . rootDir ! , bazelOpts . nodeModulesPrefix ) ; } if ( bazelOpts . angularCompilerOptions && bazelOpts . angularCompilerOptions . assets ) { bazelOpts . angularCompilerOptions . assets = bazelOpts . angularCompilerOptions . assets . map ( f => resolveNormalizedPath ( options . rootDir ! , f ) ) ; } let disabledTsetseRules = [ ] ; for ( const pluginConfig of options [ 'plugins' ] as PluginImportWithConfig [ ] || [ ] ) { if ( pluginConfig . name && pluginConfig . name === '@bazel/tsetse' ) { const disabledRules = pluginConfig [ 'disabledRules' ] ; if ( disabledRules && ! Array . isArray ( disabledRules ) ) { throw new Error ( 'Disabled tsetse rules must be an array of rule names' ) ; } disabledTsetseRules = disabledRules as string [ ] ; break ; } } return [ { options , bazelOpts , files , config , disabledTsetseRules } , null , { target } ] ; }