From 0997f857cc9b13b6e9a3bb2624e845fb392a7785 Mon Sep 17 00:00:00 2001 From: Marcin Lewandowski Date: Mon, 2 Oct 2023 12:25:43 +0200 Subject: [PATCH] refactor(typescript): extract common TypeScript config --- config/typescript-config-carbon/.gitignore | 2 + config/typescript-config-carbon/README.md | 29 +++++ config/typescript-config-carbon/index.ts | 37 ++++++ config/typescript-config-carbon/package.json | 35 ++++++ .../tsconfig.base.json | 106 ++++++++++++++++++ config/typescript-config-carbon/tsconfig.json | 8 ++ packages/cli/package.json | 1 + .../cli/src/commands/bundle/javascript.js | 50 +-------- .../cli/src/commands/bundle/typescript.js | 57 ++-------- packages/cli/src/commands/bundle/utils.js | 62 ++++++++++ packages/icon-build-helpers/package.json | 3 +- .../src/builders/react/next/typescript.js | 37 +++--- packages/icon-helpers/package.json | 3 +- packages/icon-helpers/tsconfig.json | 102 +---------------- packages/react/package.json | 1 + packages/react/tasks/build.js | 13 ++- packages/react/tsconfig.json | 22 +--- yarn.lock | 13 +++ 18 files changed, 342 insertions(+), 239 deletions(-) create mode 100644 config/typescript-config-carbon/.gitignore create mode 100644 config/typescript-config-carbon/README.md create mode 100644 config/typescript-config-carbon/index.ts create mode 100644 config/typescript-config-carbon/package.json create mode 100644 config/typescript-config-carbon/tsconfig.base.json create mode 100644 config/typescript-config-carbon/tsconfig.json create mode 100644 packages/cli/src/commands/bundle/utils.js diff --git a/config/typescript-config-carbon/.gitignore b/config/typescript-config-carbon/.gitignore new file mode 100644 index 000000000000..d2f172d3206e --- /dev/null +++ b/config/typescript-config-carbon/.gitignore @@ -0,0 +1,2 @@ +/index.js +/index.d.ts diff --git a/config/typescript-config-carbon/README.md b/config/typescript-config-carbon/README.md new file mode 100644 index 000000000000..08215fe2d1c9 --- /dev/null +++ b/config/typescript-config-carbon/README.md @@ -0,0 +1,29 @@ +# typescript-config-carbon + +> TypeScript configuration and utilities for Carbon + +## Getting started + +To install `typescript-config-carbon` in your project, you will need to run the +following command using [npm](https://www.npmjs.com/): + +```bash +npm install -S typescript-config-carbon +``` + +If you prefer [Yarn](https://yarnpkg.com/en/), use the following command +instead: + +```bash +yarn add typescript-config-carbon +``` + +## 🙌 Contributing + +We're always looking for contributors to help us fix bugs, build new features, +or help us improve the project documentation. If you're interested, definitely +check out our [Contributing Guide](/.github/CONTRIBUTING.md)! 👀 + +## 📝 License + +Licensed under the [Apache 2.0 License](/LICENSE). diff --git a/config/typescript-config-carbon/index.ts b/config/typescript-config-carbon/index.ts new file mode 100644 index 000000000000..d046297137a1 --- /dev/null +++ b/config/typescript-config-carbon/index.ts @@ -0,0 +1,37 @@ +/** + * Copyright IBM Corp. 2023 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ +import path from 'path'; +import ts from 'typescript'; + +const tsConfigFile = path.join(__dirname, 'tsconfig.base.json'); + +export const diagnosticToMessage = (diagnostic: ts.Diagnostic) => { + const { file, messageText } = diagnostic; + const filePrefix = file ? `${file.fileName}: ` : ''; + const text = ts.flattenDiagnosticMessageText(messageText, '\n'); + return `${filePrefix}${text}`; +}; + +export const loadTsCompilerOpts = (path: string) => { + const { config, error } = ts.readConfigFile(path, ts.sys.readFile); + if (error) { + throw new Error(diagnosticToMessage(error)); + } + const opts = ts.convertCompilerOptionsFromJson(config.compilerOptions, ''); + const { errors } = opts; + if (errors.length > 0) { + errors.forEach((diagnostic) => { + console.log(diagnosticToMessage(diagnostic)); + }); + throw new Error('Base TypeScript config file errors found'); + } + return opts.options; +}; + +export const loadBaseTsCompilerOpts = () => { + return loadTsCompilerOpts(tsConfigFile); +}; diff --git a/config/typescript-config-carbon/package.json b/config/typescript-config-carbon/package.json new file mode 100644 index 000000000000..13266790a6bc --- /dev/null +++ b/config/typescript-config-carbon/package.json @@ -0,0 +1,35 @@ +{ + "name": "typescript-config-carbon", + "description": "TypeScript configuration for Carbon", + "version": "0.1.0", + "license": "Apache-2.0", + "main": "index.js", + "types": "index.d.ts", + "repository": { + "type": "git", + "url": "https://github.com/carbon-design-system/carbon.git", + "directory": "config/typescript-config-carbon" + }, + "bugs": "https://github.com/carbon-design-system/carbon/issues", + "keywords": [ + "carbon", + "carbon-design-system", + "components", + "react", + "typescript" + ], + "publishConfig": { + "access": "public", + "provenance": true + }, + "scripts": { + "clean": "rimraf index.js index.d.ts", + "build": "yarn clean && tsc" + }, + "dependencies": { + "typescript": "^4.8.4" + }, + "devDependencies": { + "rimraf": "^5.0.0" + } +} diff --git a/config/typescript-config-carbon/tsconfig.base.json b/config/typescript-config-carbon/tsconfig.base.json new file mode 100644 index 000000000000..dcbe6315f2bc --- /dev/null +++ b/config/typescript-config-carbon/tsconfig.base.json @@ -0,0 +1,106 @@ +{ + "compilerOptions": { + /* Visit https://aka.ms/tsconfig to read more about this file */ + + /* Projects */ + // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ + // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ + // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ + // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ + // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ + // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ + + /* Language and Environment */ + "target": "es6", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ + "lib": ["dom", "dom.iterable", "esnext"], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ + "jsx": "react-jsx", /* Specify what JSX code is generated. */ + // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ + // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ + // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ + // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ + // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ + // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ + // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ + // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ + // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ + + /* Modules */ + "module": "esnext", /* Specify what module code is generated. */ + // "rootDir": "./", /* Specify the root folder within your source files. */ + "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ + // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ + // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ + // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ + // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ + // "types": [], /* Specify type package names to be included without being referenced in a source file. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ + "resolveJsonModule": true, /* Enable importing .json files. */ + // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ + + /* JavaScript Support */ + "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ + // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ + // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ + + /* Emit */ + "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ + // "declarationMap": true, /* Create sourcemaps for d.ts files. */ + "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ + // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ + // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ + // "outDir": "./", /* Specify an output folder for all emitted files. */ + // "removeComments": true, /* Disable emitting comments. */ + // "noEmit": true, /* Disable emitting files from a compilation. */ + // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ + // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ + // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ + // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ + // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ + // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ + // "newLine": "crlf", /* Set the newline character for emitting files. */ + // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ + // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ + // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ + // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ + // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ + // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ + + /* Interop Constraints */ + "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ + // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ + "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ + // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ + "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ + + /* + * Type Checking + * Note: some checks are set to false since linting takes care of them + */ + "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ + // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ + // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ + // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ + // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ + // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ + // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ + "noUnusedLocals": false, /* Enable error reporting when local variables aren't read. */ + "noUnusedParameters": false, /* Raise an error when a function parameter isn't read. */ + // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ + // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ + "noFallthroughCasesInSwitch": false, /* Enable error reporting for fallthrough cases in switch statements. */ + // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ + // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ + // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ + // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ + // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ + + /* Completeness */ + // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ + "skipLibCheck": true /* Skip type checking all .d.ts files. */ + } +} diff --git a/config/typescript-config-carbon/tsconfig.json b/config/typescript-config-carbon/tsconfig.json new file mode 100644 index 000000000000..2e200d67f527 --- /dev/null +++ b/config/typescript-config-carbon/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.base.json", + "compilerOptions": { + "emitDeclarationOnly": false, + "module": "commonjs" + }, + "include": ["index.ts"] +} diff --git a/packages/cli/package.json b/packages/cli/package.json index 6a4c2be12bbc..156bbd964a23 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -51,6 +51,7 @@ "rollup": "^2.79.1", "sass": "^1.51.0", "sassdoc": "^2.7.3", + "typescript-config-carbon": "^0.1.0", "yargs": "^17.0.1" } } diff --git a/packages/cli/src/commands/bundle/javascript.js b/packages/cli/src/commands/bundle/javascript.js index 45c314a323c1..4e5875e7c24e 100644 --- a/packages/cli/src/commands/bundle/javascript.js +++ b/packages/cli/src/commands/bundle/javascript.js @@ -10,10 +10,14 @@ const { babel } = require('@rollup/plugin-babel'); const commonjs = require('@rollup/plugin-commonjs'); const { nodeResolve } = require('@rollup/plugin-node-resolve'); -const { pascalCase } = require('change-case'); const fs = require('fs-extra'); const path = require('path'); const { rollup } = require('rollup'); +const { + formatGlobals, + findPackageFolder, + formatDependenciesIntoGlobals, +} = require('./utils'); async function bundle(entrypoint, options) { const globals = options.globals ? formatGlobals(options.globals) : {}; @@ -95,48 +99,4 @@ async function bundle(entrypoint, options) { ); } -function formatGlobals(string) { - const mappings = string.split(',').map((mapping) => { - return mapping.split('='); - }); - return mappings.reduce( - (acc, [pkg, global]) => ({ - ...acc, - [pkg]: global, - }), - {} - ); -} - -function formatDependenciesIntoGlobals(dependencies) { - return Object.keys(dependencies).reduce((acc, key) => { - const parts = key.split('/').map((identifier, i) => { - if (i === 0) { - return identifier.replace(/@/, ''); - } - return identifier; - }); - - return { - ...acc, - [key]: pascalCase(parts.join(' ')), - }; - }, {}); -} - -async function findPackageFolder(entrypoint) { - let packageFolder = entrypoint; - - while (packageFolder !== '/' && path.dirname(packageFolder) !== '/') { - packageFolder = path.dirname(packageFolder); - const packageJsonPath = path.join(packageFolder, 'package.json'); - - if (await fs.pathExists(packageJsonPath)) { - break; - } - } - - return packageFolder; -} - module.exports = bundle; diff --git a/packages/cli/src/commands/bundle/typescript.js b/packages/cli/src/commands/bundle/typescript.js index 877bfed10d6a..198c42dde046 100644 --- a/packages/cli/src/commands/bundle/typescript.js +++ b/packages/cli/src/commands/bundle/typescript.js @@ -1,5 +1,5 @@ /** - * Copyright IBM Corp. 2018, 2023 + * Copyright IBM Corp. 2023 * * This source code is licensed under the Apache-2.0 license found in the * LICENSE file in the root directory of this source tree. @@ -11,10 +11,15 @@ const { babel } = require('@rollup/plugin-babel'); const commonjs = require('@rollup/plugin-commonjs'); const { nodeResolve } = require('@rollup/plugin-node-resolve'); const typescript = require('@rollup/plugin-typescript'); -const { pascalCase } = require('change-case'); const fs = require('fs-extra'); const path = require('path'); const { rollup } = require('rollup'); +const { loadBaseTsCompilerOpts } = require('typescript-config-carbon'); +const { + formatGlobals, + findPackageFolder, + formatDependenciesIntoGlobals, +} = require('./utils'); async function bundle(entrypoint, options) { const globals = options.globals ? formatGlobals(options.globals) : {}; @@ -48,6 +53,8 @@ async function bundle(entrypoint, options) { const packageJson = await fs.readJson(packageJsonPath); const { dependencies = {} } = packageJson; + const baseTsCompilerOpts = loadBaseTsCompilerOpts(); + await Promise.all( jsEntryPoints.map(async ({ outputDir, file, format }) => { const bundle = await rollup({ @@ -59,8 +66,8 @@ async function bundle(entrypoint, options) { noForceEmit: true, outputToFilesystem: false, compilerOptions: { + ...baseTsCompilerOpts, rootDir: 'src', - emitDeclarationOnly: true, outDir: outputDir, }, }), @@ -108,48 +115,4 @@ async function bundle(entrypoint, options) { ); } -function formatGlobals(string) { - const mappings = string.split(',').map((mapping) => { - return mapping.split('='); - }); - return mappings.reduce( - (acc, [pkg, global]) => ({ - ...acc, - [pkg]: global, - }), - {} - ); -} - -function formatDependenciesIntoGlobals(dependencies) { - return Object.keys(dependencies).reduce((acc, key) => { - const parts = key.split('/').map((identifier, i) => { - if (i === 0) { - return identifier.replace(/@/, ''); - } - return identifier; - }); - - return { - ...acc, - [key]: pascalCase(parts.join(' ')), - }; - }, {}); -} - -async function findPackageFolder(entrypoint) { - let packageFolder = entrypoint; - - while (packageFolder !== '/' && path.dirname(packageFolder) !== '/') { - packageFolder = path.dirname(packageFolder); - const packageJsonPath = path.join(packageFolder, 'package.json'); - - if (await fs.pathExists(packageJsonPath)) { - break; - } - } - - return packageFolder; -} - module.exports = bundle; diff --git a/packages/cli/src/commands/bundle/utils.js b/packages/cli/src/commands/bundle/utils.js new file mode 100644 index 000000000000..8ad277782871 --- /dev/null +++ b/packages/cli/src/commands/bundle/utils.js @@ -0,0 +1,62 @@ +/** + * Copyright IBM Corp. 2023 + * + * This source code is licensed under the Apache-2.0 license found in the + * LICENSE file in the root directory of this source tree. + */ + +'use strict'; + +const path = require('path'); +const fs = require('fs-extra'); +const { pascalCase } = require('change-case'); + +function formatGlobals(string) { + const mappings = string.split(',').map((mapping) => { + return mapping.split('='); + }); + return mappings.reduce( + (acc, [pkg, global]) => ({ + ...acc, + [pkg]: global, + }), + {} + ); +} + +function formatDependenciesIntoGlobals(dependencies) { + return Object.keys(dependencies).reduce((acc, key) => { + const parts = key.split('/').map((identifier, i) => { + if (i === 0) { + return identifier.replace(/@/, ''); + } + return identifier; + }); + + return { + ...acc, + [key]: pascalCase(parts.join(' ')), + }; + }, {}); +} + +async function findPackageFolder(entrypoint) { + let packageFolder = entrypoint; + + while (packageFolder !== '/' && path.dirname(packageFolder) !== '/') { + packageFolder = path.dirname(packageFolder); + const packageJsonPath = path.join(packageFolder, 'package.json'); + + if (await fs.pathExists(packageJsonPath)) { + break; + } + } + + return packageFolder; +} + +module.exports = { + formatGlobals, + formatDependenciesIntoGlobals, + findPackageFolder, +}; diff --git a/packages/icon-build-helpers/package.json b/packages/icon-build-helpers/package.json index 2317c49eb954..335437da8399 100644 --- a/packages/icon-build-helpers/package.json +++ b/packages/icon-build-helpers/package.json @@ -50,6 +50,7 @@ "rollup-plugin-strip-banner": "^3.0.0", "svg-parser": "^2.0.4", "svgo": "^1.1.1", - "svgson": "^5.2.1" + "svgson": "^5.2.1", + "typescript-config-carbon": "^0.1.0" } } diff --git a/packages/icon-build-helpers/src/builders/react/next/typescript.js b/packages/icon-build-helpers/src/builders/react/next/typescript.js index 80a74c355fde..c7716b1112b2 100644 --- a/packages/icon-build-helpers/src/builders/react/next/typescript.js +++ b/packages/icon-build-helpers/src/builders/react/next/typescript.js @@ -11,36 +11,27 @@ const fs = require('fs-extra'); const path = require('path'); const templates = require('./templates'); const ts = require('typescript'); - -/** - * TypeScript compiler options to use when producing definition files - * @type ts.CompilerOptions - */ -const tsConfig = { - target: ts.ScriptTarget.ES2015, - module: ts.ModuleKind.ESNext, - moduleResolution: ts.ModuleResolutionKind.NodeJs, - allowJs: true, - declaration: true, - emitDeclarationOnly: true, - esModuleInterop: true, - strict: true, - skipLibCheck: true, -}; +const { + diagnosticToMessage, + loadBaseTsCompilerOpts, +} = require('typescript-config-carbon'); function emitIconComponent(compileOpts) { - const options = { ...tsConfig, ...compileOpts }; + const baseOpts = loadBaseTsCompilerOpts(); + const options = { ...baseOpts, ...compileOpts }; const host = ts.createCompilerHost(options); const iconComponentPath = path.resolve(__dirname, '../components/Icon.tsx'); const program = ts.createProgram([iconComponentPath], options, host); const emitResult = program.emit(); - ts.getPreEmitDiagnostics(program) - .concat(emitResult.diagnostics) - .forEach((diagnostic) => { - console.log( - ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n') - ); + const diagnostics = ts + .getPreEmitDiagnostics(program) + .concat(emitResult.diagnostics); + if (diagnostics.length > 0) { + diagnostics.forEach((diagnostic) => { + console.log(diagnosticToMessage(diagnostic)); }); + throw new Error('Icon.tsx compilation failed'); + } } async function copyCarbonIconType(outDir) { diff --git a/packages/icon-helpers/package.json b/packages/icon-helpers/package.json index aeef566a44d0..bead5523b549 100644 --- a/packages/icon-helpers/package.json +++ b/packages/icon-helpers/package.json @@ -35,7 +35,8 @@ }, "devDependencies": { "@carbon/cli": "^11.14.0", - "rimraf": "^5.0.0" + "rimraf": "^5.0.0", + "typescript-config-carbon": "^0.1.0" }, "sideEffects": false } diff --git a/packages/icon-helpers/tsconfig.json b/packages/icon-helpers/tsconfig.json index 8296f021fc7c..289e22a627be 100644 --- a/packages/icon-helpers/tsconfig.json +++ b/packages/icon-helpers/tsconfig.json @@ -1,104 +1,4 @@ { - "compilerOptions": { - /* Visit https://aka.ms/tsconfig to read more about this file */ - - /* Projects */ - // "incremental": true, /* Save .tsbuildinfo files to allow for incremental compilation of projects. */ - // "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */ - // "tsBuildInfoFile": "./.tsbuildinfo", /* Specify the path to .tsbuildinfo incremental compilation file. */ - // "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects. */ - // "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */ - // "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */ - - /* Language and Environment */ - "target": "es6", /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */ - // "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */ - // "jsx": "preserve", /* Specify what JSX code is generated. */ - // "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */ - // "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */ - // "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h'. */ - // "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */ - // "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using 'jsx: react-jsx*'. */ - // "reactNamespace": "", /* Specify the object invoked for 'createElement'. This only applies when targeting 'react' JSX emit. */ - // "noLib": true, /* Disable including any library files, including the default lib.d.ts. */ - // "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */ - // "moduleDetection": "auto", /* Control what method is used to detect module-format JS files. */ - - /* Modules */ - "module": "esnext", /* Specify what module code is generated. */ - // "rootDir": "./", /* Specify the root folder within your source files. */ - "moduleResolution": "node", /* Specify how TypeScript looks up a file from a given module specifier. */ - // "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */ - // "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */ - // "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */ - // "typeRoots": [], /* Specify multiple folders that act like './node_modules/@types'. */ - // "types": [], /* Specify type package names to be included without being referenced in a source file. */ - // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ - // "moduleSuffixes": [], /* List of file name suffixes to search when resolving a module. */ - // "resolveJsonModule": true, /* Enable importing .json files. */ - // "noResolve": true, /* Disallow 'import's, 'require's or ''s from expanding the number of files TypeScript should add to a project. */ - - /* JavaScript Support */ - "allowJs": true, /* Allow JavaScript files to be a part of your program. Use the 'checkJS' option to get errors from these files. */ - // "checkJs": true, /* Enable error reporting in type-checked JavaScript files. */ - // "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from 'node_modules'. Only applicable with 'allowJs'. */ - - /* Emit */ - "declaration": true, /* Generate .d.ts files from TypeScript and JavaScript files in your project. */ - // "declarationMap": true, /* Create sourcemaps for d.ts files. */ - "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */ - // "sourceMap": true, /* Create source map files for emitted JavaScript files. */ - // "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If 'declaration' is true, also designates a file that bundles all .d.ts output. */ - // "outDir": "./", /* Specify an output folder for all emitted files. */ - // "removeComments": true, /* Disable emitting comments. */ - // "noEmit": true, /* Disable emitting files from a compilation. */ - // "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */ - // "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types. */ - // "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */ - // "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */ - // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */ - // "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */ - // "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */ - // "newLine": "crlf", /* Set the newline character for emitting files. */ - // "stripInternal": true, /* Disable emitting declarations that have '@internal' in their JSDoc comments. */ - // "noEmitHelpers": true, /* Disable generating custom helper functions like '__extends' in compiled output. */ - // "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */ - // "preserveConstEnums": true, /* Disable erasing 'const enum' declarations in generated code. */ - // "declarationDir": "./", /* Specify the output directory for generated declaration files. */ - // "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */ - - /* Interop Constraints */ - // "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */ - // "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */ - "esModuleInterop": true, /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables 'allowSyntheticDefaultImports' for type compatibility. */ - // "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */ - "forceConsistentCasingInFileNames": true, /* Ensure that casing is correct in imports. */ - - /* Type Checking */ - "strict": true, /* Enable all strict type-checking options. */ - // "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied 'any' type. */ - // "strictNullChecks": true, /* When type checking, take into account 'null' and 'undefined'. */ - // "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */ - // "strictBindCallApply": true, /* Check that the arguments for 'bind', 'call', and 'apply' methods match the original function. */ - // "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */ - // "noImplicitThis": true, /* Enable error reporting when 'this' is given the type 'any'. */ - // "useUnknownInCatchVariables": true, /* Default catch clause variables as 'unknown' instead of 'any'. */ - // "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */ - // "noUnusedLocals": true, /* Enable error reporting when local variables aren't read. */ - // "noUnusedParameters": true, /* Raise an error when a function parameter isn't read. */ - // "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */ - // "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */ - // "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */ - // "noUncheckedIndexedAccess": true, /* Add 'undefined' to a type when accessed using an index. */ - // "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */ - // "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type. */ - // "allowUnusedLabels": true, /* Disable error reporting for unused labels. */ - // "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */ - - /* Completeness */ - // "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */ - "skipLibCheck": true /* Skip type checking all .d.ts files. */ - }, + "extends": "typescript-config-carbon/tsconfig.base.json", "include": ["src/**/*"] } diff --git a/packages/react/package.json b/packages/react/package.json index 28a8918bf93b..cf738189eb14 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -124,6 +124,7 @@ "stream-browserify": "^3.0.0", "style-loader": "^3.3.1", "typescript": "^4.8.4", + "typescript-config-carbon": "^0.1.0", "webpack": "^5.65.0", "webpack-dev-server": "^4.7.4" }, diff --git a/packages/react/tasks/build.js b/packages/react/tasks/build.js index f156edbd1415..2e2a187cd7b6 100644 --- a/packages/react/tasks/build.js +++ b/packages/react/tasks/build.js @@ -14,6 +14,10 @@ const typescript = require('@rollup/plugin-typescript'); const path = require('path'); const { rollup } = require('rollup'); const stripBanner = require('rollup-plugin-strip-banner'); +const { + loadBaseTsCompilerOpts, + loadTsCompilerOpts, +} = require('typescript-config-carbon'); const packageJson = require('../package.json'); async function build() { @@ -117,6 +121,13 @@ const babelConfig = { extensions: ['.ts', '.tsx', '.js', '.jsx'], }; +function getTsCompilerOptions() { + const baseOpts = loadBaseTsCompilerOpts(); + const projectTsConfigPath = path.resolve(__dirname, '../tsconfig.json'); + const overrideOpts = loadTsCompilerOpts(projectTsConfigPath); + return { ...baseOpts, ...overrideOpts }; +} + function getRollupConfig(input, rootDir, outDir) { return { input, @@ -145,7 +156,7 @@ function getRollupConfig(input, rootDir, outDir) { noForceEmit: true, outputToFilesystem: false, compilerOptions: { - emitDeclarationOnly: true, + ...getTsCompilerOptions(), rootDir, outDir, }, diff --git a/packages/react/tsconfig.json b/packages/react/tsconfig.json index 8052be5d0fec..88b0679a84e9 100644 --- a/packages/react/tsconfig.json +++ b/packages/react/tsconfig.json @@ -1,26 +1,8 @@ { + "extends": "typescript-config-carbon/tsconfig.base.json", "compilerOptions": { - "target": "ES6", - "lib": ["dom", "dom.iterable", "esnext"], - "allowJs": true, - "skipLibCheck": true, - "esModuleInterop": true, - "strict": true, - "forceConsistentCasingInFileNames": true, - "module": "ESNext", - "moduleResolution": "node", - "isolatedModules": true, - "resolveJsonModule": true, - "jsx": "react-jsx", - "emitDeclarationOnly": true, - "declaration": true, - // use linting instead - "noUnusedLocals": false, - "noUnusedParameters": false, - "noFallthroughCasesInSwitch": true, // TODO: Turn back on once stricter typings for internal utitlies are complete "noImplicitAny": false }, - "include": ["src/**/*", "icons/src/index.ts"], - "exclude": ["node_modules", "build"] + "include": ["src/**/*", "icons/src/index.ts"] } diff --git a/yarn.lock b/yarn.lock index 7e404fe4d2f4..442b4e491aca 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1895,6 +1895,7 @@ __metadata: rollup: ^2.79.1 sass: ^1.51.0 sassdoc: ^2.7.3 + typescript-config-carbon: ^0.1.0 yargs: ^17.0.1 bin: carbon-cli: ./bin/carbon-cli.js @@ -2010,6 +2011,7 @@ __metadata: svg-parser: ^2.0.4 svgo: ^1.1.1 svgson: ^5.2.1 + typescript-config-carbon: ^0.1.0 languageName: unknown linkType: soft @@ -2019,6 +2021,7 @@ __metadata: dependencies: "@carbon/cli": ^11.14.0 rimraf: ^5.0.0 + typescript-config-carbon: ^0.1.0 languageName: unknown linkType: soft @@ -2205,6 +2208,7 @@ __metadata: stream-browserify: ^3.0.0 style-loader: ^3.3.1 typescript: ^4.8.4 + typescript-config-carbon: ^0.1.0 use-resize-observer: ^6.0.0 webpack: ^5.65.0 webpack-dev-server: ^4.7.4 @@ -30630,6 +30634,15 @@ __metadata: languageName: node linkType: hard +"typescript-config-carbon@^0.1.0, typescript-config-carbon@workspace:config/typescript-config-carbon": + version: 0.0.0-use.local + resolution: "typescript-config-carbon@workspace:config/typescript-config-carbon" + dependencies: + rimraf: ^5.0.0 + typescript: ^4.8.4 + languageName: unknown + linkType: soft + "typescript@npm:>=3 < 6": version: 5.1.3 resolution: "typescript@npm:5.1.3"