├── .babelrc ├── .eslintrc.js ├── .gitignore ├── .prettierignore ├── .prettierrc ├── .vscode └── settings.json ├── LICENSE ├── README.md ├── package-lock.json ├── package.json ├── src ├── compiler.ts ├── index.ts ├── parse-service-config.ts ├── types.ts ├── utils.ts ├── zeit__ncc.d.ts └── zipper.ts └── tsconfig.json /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [["@babel/preset-env", { "targets": { "node": "6.10" } }], "@babel/preset-typescript"], 3 | "plugins": [ 4 | "@babel/plugin-proposal-class-properties", 5 | "@babel/plugin-proposal-object-rest-spread", 6 | "babel-plugin-add-module-exports" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | extends: ['@jaydp17'], 3 | env: { 4 | es6: true, 5 | node: true, 6 | jest: true, 7 | }, 8 | }; 9 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # TypeScript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | yarn.lock 57 | 58 | # dotenv environment variables file 59 | .env 60 | 61 | # next.js build output 62 | .next 63 | 64 | # compiled output 65 | lib 66 | dist 67 | 68 | # IDE 69 | .idea 70 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | package.json 3 | tsconfig.json 4 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 100, 3 | "singleQuote": true, 4 | "trailingComma": "all" 5 | } 6 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "eslint.enable": true 3 | } 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Jaydeep Solanki 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # serverless-plugin-ncc 2 | 3 | A serverless plugin to use [@zeit/ncc](https://www.npmjs.com/package/@zeit/ncc) for compiling code before packaging. 4 | 5 | ## Usage 6 | 7 | ```sh 8 | npm install -D serverless-plugin-ncc @zeit/ncc 9 | ``` 10 | 11 | `@zeit/ncc` is a peer dependency, so we'll have to install it separately. 12 | 13 | Add the pluging to `serverless.yml` 14 | 15 | ```yml 16 | plugins: 17 | - serverless-plugin-ncc 18 | ``` 19 | 20 | ## How to use with TypeScript files? 21 | 22 | ```yml 23 | # serverless.yml 24 | 25 | functions: 26 | typescriptFn: 27 | # the plugin checks for src/index.ts as well as src/index.js 28 | # whichever exists is picked up 29 | handler: src/index.handler 30 | ``` 31 | 32 | ## Pass options 33 | 34 | Custom options can be passed to ncc like this: 35 | ```yml 36 | # serverless.yml 37 | 38 | custom: 39 | ncc: 40 | minify: true 41 | ``` 42 | Note that all options are currently passed directly to ncc. To view all possible options 43 | check the [ncc docs](https://github.com/zeit/ncc#programmatically-from-nodejs) 44 | 45 | ## Pass custom options per-function 46 | 47 | Passing custom options to a function is as simple as introducing a custom block under the function with your ncc config 48 | 49 | ```yml 50 | # serverless.yml 51 | 52 | functions: 53 | hello: 54 | handler: src/hello/index.hello 55 | custom: 56 | ncc: 57 | minify: false 58 | ``` 59 | 60 | ## Disable ncc per function 61 | 62 | You can pass `enabled: false` as custom config per function to disable ncc on that function 63 | 64 | ```yml 65 | # serverless.yml 66 | 67 | functions: 68 | hello: 69 | handler: src/hello/index.hello 70 | custom: 71 | ncc: 72 | enabled: false 73 | ``` 74 | 75 | ## License 76 | 77 | MIT 78 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "serverless-plugin-ncc", 3 | "description": "A serverless plugin to use @zeit/ncc for bundling", 4 | "version": "0.4.0", 5 | "author": "Jaydeep Solanki (https://jaydp.com)", 6 | "bugs": { 7 | "url": "https://github.com/jaydp17/serverless-plugin-ncc/issues" 8 | }, 9 | "dependencies": { 10 | "archiver": "3.0.0", 11 | "lodash": "^4.17.15", 12 | "make-dir": "1.3.0" 13 | }, 14 | "devDependencies": { 15 | "@babel/cli": "^7.4.4", 16 | "@babel/core": "^7.4.5", 17 | "@babel/plugin-proposal-class-properties": "^7.4.4", 18 | "@babel/plugin-proposal-object-rest-spread": "^7.4.4", 19 | "@babel/preset-env": "^7.4.5", 20 | "@babel/preset-typescript": "^7.3.3", 21 | "@jaydp17/eslint-config": "0.1.1", 22 | "@types/archiver": "^2.1.2", 23 | "@types/lodash": "^4.14.118", 24 | "@types/make-dir": "^1.0.3", 25 | "@types/node": "^10.12.27", 26 | "@types/serverless": "^1.18.0", 27 | "@zeit/ncc": "^0.15.2", 28 | "babel-plugin-add-module-exports": "^1.0.0", 29 | "eslint": "^5.9.0", 30 | "prettier": "1.15.2", 31 | "release-it": "^12.4.1" 32 | }, 33 | "files": [ 34 | "dist/**" 35 | ], 36 | "homepage": "https://github.com/jaydp17/serverless-plugin-ncc#readme", 37 | "keywords": [], 38 | "license": "MIT", 39 | "main": "dist/index.js", 40 | "peerDependencies": { 41 | "@zeit/ncc": ">=0.15.2" 42 | }, 43 | "release-it": { 44 | "github": { 45 | "release": true 46 | } 47 | }, 48 | "repository": { 49 | "type": "git", 50 | "url": "git+https://github.com/jaydp17/serverless-plugin-ncc.git" 51 | }, 52 | "scripts": { 53 | "build": "babel src -d dist --extensions '.ts,.js' --source-maps", 54 | "build:watch": "npm run build -- --watch", 55 | "format": "prettier --write '**/*.{js,json,yaml,yml,md}'", 56 | "lint": "eslint .", 57 | "prepack": "npm run build", 58 | "test": "echo \"Error: no test specified\" && exit 1" 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/compiler.ts: -------------------------------------------------------------------------------- 1 | import zeitNcc from '@zeit/ncc'; 2 | 3 | export default async function compile({ inputFilePath, ...options }: { inputFilePath: string, [key: string]: any }) { 4 | return zeitNcc(inputFilePath, { minify: false, ...options }); 5 | } 6 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { CompiledOutput } from '@zeit/ncc'; 2 | import _ from 'lodash'; 3 | import path from 'path'; 4 | import makeDir from 'make-dir'; 5 | import Serverless from 'serverless'; 6 | 7 | import compiler from './compiler'; 8 | import parseServiceConfig, { IPackagingConfig } from './parse-service-config'; 9 | import { IFileNameAndPath } from './types'; 10 | import zipper, { ZipContent } from './zipper'; 11 | 12 | export default class ServerlessPlugin { 13 | serverless: Serverless; 14 | options: Serverless.Options; 15 | hooks: { [key in string]: Function }; 16 | constructor(serverless: Serverless, options: Serverless.Options) { 17 | this.serverless = serverless; 18 | this.options = options; 19 | 20 | this.hooks = { 21 | 'before:package:createDeploymentArtifacts': this.package.bind(this), 22 | 'before:package:finalize': this.packageFinalize.bind(this), 23 | }; 24 | } 25 | 26 | packageFinalize() { 27 | this.serverless.cli.log('packageFinalize'); 28 | } 29 | 30 | async package() { 31 | this.serverless.cli.log('running ncc'); 32 | const { servicePath } = this.serverless.config; 33 | const slsService = this.serverless.service; 34 | const globalNccConfig = (slsService && slsService.custom && slsService.custom.ncc) || {}; 35 | const dotServerlessPath = path.join(servicePath, '.serverless'); 36 | await makeDir(dotServerlessPath); 37 | 38 | const packageFilesConfig = await parseServiceConfig(this.serverless); 39 | const packagingPromises = packageFilesConfig.filter(Boolean).map(async (pkg) => { 40 | const { zip, files, perFunctionNccConfig = {} } = pkg; 41 | const nccConfig = Object.assign({}, globalNccConfig, perFunctionNccConfig); 42 | // For now pass all ncc options directly to ncc. This has the benefit of testing out new 43 | // ncc releases and changes quickly. Later it would be nice to add a validation step in between. 44 | const codeCompilePromises = files.map(({ absPath }) => 45 | compiler({ inputFilePath: absPath, ...nccConfig }), 46 | ); 47 | const compiledCodes = await Promise.all(codeCompilePromises); 48 | const zipperFiles = createZipperFiles(files, compiledCodes); 49 | await zipper({ zipPath: zip.absPath, zipContents: zipperFiles }); 50 | }); 51 | setArtifacts(this.serverless, packageFilesConfig); 52 | await Promise.all(packagingPromises); 53 | return undefined; 54 | } 55 | } 56 | 57 | function createZipperFiles( 58 | files: IFileNameAndPath[], 59 | compiledCodes: CompiledOutput[], 60 | ): ZipContent[] { 61 | if (files.length !== compiledCodes.length) { 62 | throw new Error('Expecting NCC output for all files.'); 63 | } 64 | 65 | const content: ZipContent[] = []; 66 | 67 | files.forEach((file, index) => { 68 | const compilerOutput = compiledCodes[index]; 69 | 70 | content.push({ 71 | data: compilerOutput.code, 72 | // here we're replacing files with `.ts` extensions to `.js` 73 | // as the `data` in the above live will already be a compiled JS file 74 | name: file.name.replace(/.ts$/, '.js'), 75 | }); 76 | 77 | if (compilerOutput.map) { 78 | content.push({ 79 | data: compilerOutput.map, 80 | // Make sure to rename the map the same way as the compiled output. 81 | name: file.name.replace(/.ts$/, '.map.js'), 82 | }); 83 | } 84 | 85 | if (compilerOutput.assets) { 86 | // Assets are relative to the 'code' file. But because of keeping the file 87 | // structure in the zip output all assets need to be written to the same directory. 88 | // The 'lastIndexOf() + 1' makes sure to keep the trailing slash. 89 | const path = file.name.substring(0, file.name.lastIndexOf('/') + 1); 90 | 91 | Object.keys(compilerOutput.assets).forEach(assetName => { 92 | if (!Object.prototype.hasOwnProperty.call(compilerOutput.assets, assetName)) { 93 | return; 94 | } 95 | 96 | content.push({ 97 | data: compilerOutput.assets![assetName].source, 98 | name: `${path}${assetName}`, 99 | mode: compilerOutput.assets![assetName].permissions, 100 | }); 101 | }); 102 | } 103 | }); 104 | 105 | return content; 106 | } 107 | 108 | function setArtifacts(serverless: Serverless, serviceFilesConfigArr: IPackagingConfig[]) { 109 | const individually = !!_.get(serverless, 'service.package.individually'); 110 | if (!individually) { 111 | _.set(serverless, 'service.package.artifact', serviceFilesConfigArr[0].zip.absPath); 112 | } else { 113 | for (const cnf of serviceFilesConfigArr) { 114 | if (!cnf) { 115 | continue; 116 | } 117 | 118 | const { functionName, zip } = cnf; 119 | if (!functionName) { 120 | throw new Error('functionName cannot be empty when packaging individually'); 121 | } 122 | const slsFunction = serverless.service.getFunction(functionName); 123 | _.set(slsFunction, 'package.artifact', zip.absPath); 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/parse-service-config.ts: -------------------------------------------------------------------------------- 1 | import _ from 'lodash'; 2 | import path from 'path'; 3 | import { handlerToFileDetails } from './utils'; 4 | import Serverless from 'serverless'; 5 | import { ServerlessFunctionDefinition, IFileNameAndPath } from './types'; 6 | import Service from 'serverless/classes/Service'; 7 | 8 | export default function parseServiceConfig(serverless: Serverless) { 9 | const individually = !!_.get(serverless, 'service.package.individually'); 10 | if (individually) { 11 | return packageIndividually(serverless); 12 | } 13 | return packageAllTogether(serverless); 14 | } 15 | 16 | export interface IPackagingConfig { 17 | functionName?: string; 18 | zip: IFileNameAndPath; 19 | files: IFileNameAndPath[]; 20 | perFunctionNccConfig?: Service.Custom; 21 | } 22 | async function packageIndividually(serverless: Serverless): Promise { 23 | const { servicePath } = serverless.config; 24 | // @ts-ignore 25 | const functions: { [key: string]: ServerlessFunctionDefinition } = serverless.service.functions; 26 | const serviceFilesConfigArrPromises = _.map( 27 | functions, 28 | async ({ name: serviceName, handler, custom = {} }, functionName) => { 29 | if (custom && custom.ncc && custom.ncc.enabled === false) { 30 | return; 31 | } 32 | 33 | const { name: fileName, absPath: filePath } = await handlerToFileDetails( 34 | servicePath, 35 | handler, 36 | ); 37 | const zipName = `${serviceName}.zip`; 38 | const zipPath = path.join(servicePath, `.serverless/${zipName}`); 39 | return { 40 | perFunctionNccConfig: _.get(custom, 'ncc', {}), 41 | functionName, 42 | zip: { 43 | absPath: zipPath, 44 | name: zipName, 45 | }, 46 | files: [ 47 | { 48 | name: fileName, 49 | absPath: filePath, 50 | }, 51 | ], 52 | }; 53 | }, 54 | ); 55 | const serviceFilesConfigArr = await Promise.all(serviceFilesConfigArrPromises); 56 | return serviceFilesConfigArr.filter(Boolean) as IPackagingConfig[]; 57 | } 58 | 59 | async function packageAllTogether(serverless: Serverless): Promise { 60 | const { servicePath } = serverless.config; 61 | const zipName = `${serverless.service.getServiceName()}.zip`; 62 | const zipPath = path.join(servicePath, `.serverless/${zipName}`); 63 | // @ts-ignore 64 | const functions: ServerlessFunctionDefinition[] = Object.values(serverless.service.functions); 65 | const filesPromises = functions.map(async ({ handler }) => { 66 | const { name, absPath } = await handlerToFileDetails(servicePath, handler); 67 | return { name, absPath }; 68 | }); 69 | const files = await Promise.all(filesPromises); 70 | return [{ zip: { name: zipName, absPath: zipPath }, files }]; 71 | } 72 | -------------------------------------------------------------------------------- /src/types.ts: -------------------------------------------------------------------------------- 1 | import Service from 'serverless/classes/Service'; 2 | 3 | export interface ServerlessFunctionDefinition { 4 | name: string; 5 | handler: string; 6 | custom?: Service.Custom; 7 | } 8 | 9 | export interface IFileNameAndPath { 10 | name: string; 11 | absPath: string; 12 | } 13 | -------------------------------------------------------------------------------- /src/utils.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import path from 'path'; 3 | import { IFileNameAndPath } from './types'; 4 | 5 | export function doesFileExist(absFilePath: string): Promise { 6 | return new Promise(resolve => { 7 | fs.exists(absFilePath, resolve); 8 | }); 9 | } 10 | 11 | /** 12 | * Takes the serverless.yml dir as the `serviceRoot` and the handler string that we specify in serverless.yml as `handler` 13 | * @example 14 | handlerFileDetails('/home/ubuntu/backend', 'src/index.handler'); 15 | // {name: 'src/index.js', absPath: '/home/ubuntu/backend/src/index.js'} 16 | ``` 17 | */ 18 | export async function handlerToFileDetails( 19 | serviceRoot: string, 20 | handler: string, 21 | ): Promise { 22 | const lastDotIndex = handler.lastIndexOf('.'); 23 | if (!lastDotIndex) throw new Error('invalid handler name'); 24 | const fileNameWithoutExt = handler.substring(0, lastDotIndex); 25 | 26 | const tsFileName = `${fileNameWithoutExt}.ts`; 27 | const tsFilePath = path.join(serviceRoot, tsFileName); 28 | const tsFileExists = await doesFileExist(tsFilePath); 29 | if (tsFileExists) return { name: tsFileName, absPath: tsFilePath }; 30 | 31 | const jsFileName = `${fileNameWithoutExt}.js`; 32 | const jsFilePath = path.join(serviceRoot, jsFileName); 33 | return { name: jsFileName, absPath: jsFilePath }; 34 | } 35 | -------------------------------------------------------------------------------- /src/zeit__ncc.d.ts: -------------------------------------------------------------------------------- 1 | declare module '@zeit/ncc' { 2 | type Asset = { source: Buffer; permissions: number; }; 3 | export type CompiledOutput = { code: string; assets?: { [key: string]: Asset }; map?: string }; 4 | type CompilerOptions = { minify?: boolean; externals?: string[]; sourceMap?: boolean }; 5 | export default function(inputFilePath: string, options: CompilerOptions): CompiledOutput; 6 | } 7 | -------------------------------------------------------------------------------- /src/zipper.ts: -------------------------------------------------------------------------------- 1 | import fs from 'fs'; 2 | import archiver from 'archiver'; 3 | 4 | export type ZipContent = { 5 | data: string | Buffer; 6 | name: string; 7 | mode?: number; // mode represents the permissions of the file 8 | } 9 | 10 | type CreateZipOptions = { 11 | zipPath: string; 12 | zipContents: ZipContent[]; 13 | }; 14 | export default async function createZip({ zipPath, zipContents }: CreateZipOptions) { 15 | const zipStream = fs.createWriteStream(zipPath); 16 | const archive = archiver('zip', { zlib: { level: 9 } }); 17 | 18 | return new Promise((resolve, reject) => { 19 | // listen for all archive data to be written 20 | // 'close' event is fired only when a file descriptor is involved 21 | zipStream.on('close', () => { 22 | const totalBytes = archive.pointer(); 23 | console.log(`${totalBytes} total bytes`); 24 | console.log('archiver has been finalized and the output file descriptor has closed.'); 25 | resolve({ totalBytes }); 26 | }); 27 | 28 | // This event is fired when the data source is drained no matter what was the data source. 29 | // It is not part of this library but rather from the NodeJS Stream API. 30 | // @see: https://nodejs.org/api/stream.html#stream_event_end 31 | zipStream.on('end', () => { 32 | console.log('Data has been drained'); 33 | }); 34 | 35 | // good practice to catch warnings (ie stat failures and other non-blocking errors) 36 | archive.on('warning', err => { 37 | if (err.code === 'ENOENT') { 38 | // log warning 39 | } else { 40 | // throw error 41 | throw err; 42 | } 43 | }); 44 | 45 | // good practice to catch this error explicitly 46 | archive.on('error', err => { 47 | console.error('archive error', err); 48 | reject(err); 49 | }); 50 | 51 | // pipe archive data to the file 52 | archive.pipe(zipStream); 53 | 54 | for (const zipContent of zipContents) { 55 | archive.append(zipContent.data, { 56 | name: zipContent.name, 57 | mode: zipContent.mode, 58 | }); 59 | } 60 | 61 | archive.finalize(); 62 | }); 63 | } 64 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | /* Basic Options */ 4 | "target": "esnext", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017','ES2018' or 'ESNEXT'. */ 5 | "module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ 6 | // "lib": [], /* Specify library files to be included in the compilation. */ 7 | // "allowJs": true, /* Allow javascript files to be compiled. */ 8 | // "checkJs": true, /* Report errors in .js files. */ 9 | // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ 10 | // "declaration": true, /* Generates corresponding '.d.ts' file. */ 11 | // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ 12 | // "sourceMap": true, /* Generates corresponding '.map' file. */ 13 | // "outFile": "./", /* Concatenate and emit output to single file. */ 14 | // "outDir": "./", /* Redirect output structure to the directory. */ 15 | // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ 16 | // "composite": true, /* Enable project compilation */ 17 | // "removeComments": true, /* Do not emit comments to output. */ 18 | "noEmit": true, /* Do not emit outputs. */ 19 | // "importHelpers": true, /* Import emit helpers from 'tslib'. */ 20 | // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ 21 | // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ 22 | 23 | /* Strict Type-Checking Options */ 24 | "strict": true, /* Enable all strict type-checking options. */ 25 | // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ 26 | // "strictNullChecks": true, /* Enable strict null checks. */ 27 | // "strictFunctionTypes": true, /* Enable strict checking of function types. */ 28 | // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ 29 | // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ 30 | // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ 31 | // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ 32 | 33 | /* Additional Checks */ 34 | // "noUnusedLocals": true, /* Report errors on unused locals. */ 35 | // "noUnusedParameters": true, /* Report errors on unused parameters. */ 36 | // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ 37 | // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ 38 | 39 | /* Module Resolution Options */ 40 | // "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ 41 | // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ 42 | // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ 43 | // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ 44 | // "typeRoots": [], /* List of folders to include type definitions from. */ 45 | // "types": [], /* Type declaration files to be included in compilation. */ 46 | // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ 47 | "esModuleInterop": true /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ 48 | // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ 49 | 50 | /* Source Map Options */ 51 | // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ 52 | // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ 53 | // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ 54 | // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ 55 | 56 | /* Experimental Options */ 57 | // "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ 58 | // "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */ 59 | }, 60 | "include": [ 61 | "src" 62 | ] 63 | } 64 | --------------------------------------------------------------------------------