diff --git a/src/Serverless.d.ts b/src/Serverless.d.ts index ec7d7049..0d8de942 100644 --- a/src/Serverless.d.ts +++ b/src/Serverless.d.ts @@ -1,4 +1,5 @@ declare namespace Serverless { + interface Instance { cli: { log(str: string): void @@ -8,17 +9,7 @@ declare namespace Serverless { servicePath: string } - service: { - provider: { - name: string - } - functions: { - [key: string]: Serverless.Function - } - package: Serverless.Package - getAllFunctions(): string[] - } - + service: Service pluginManager: PluginManager } @@ -31,6 +22,7 @@ declare namespace Serverless { interface Function { handler: string package: Serverless.Package + runtime?: string } interface Package { @@ -40,6 +32,18 @@ declare namespace Serverless { individually?: boolean } + type FunctionMap = Record + + interface Service { + provider: { + name: string + runtime?: string + } + functions: FunctionMap + package: Serverless.Package + getAllFunctions(): string[] + } + interface PluginManager { spawn(command: string): Promise } diff --git a/src/index.ts b/src/index.ts index a249ce58..baa655e5 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,7 @@ import * as path from 'path' import * as fs from 'fs-extra' import * as _ from 'lodash' -import * as globby from 'globby' +import globby from 'globby' import * as typescript from './typescript' import { watchFiles } from './watchFiles' @@ -9,7 +9,7 @@ import { watchFiles } from './watchFiles' const SERVERLESS_FOLDER = '.serverless' const BUILD_FOLDER = '.build' -export class TypeScriptPlugin { +class TypeScriptPlugin { private originalServicePath: string private isWatching: boolean @@ -79,13 +79,16 @@ export class TypeScriptPlugin { const { options } = this const { service } = this.serverless - if (options.function) { - return { - [options.function]: service.functions[this.options.function] - } - } + const allFunctions = options.function ? { + [options.function]: service.functions[this.options.function] + } : service.functions - return service.functions + // Ensure we only handle runtimes that support Typescript + return _.pickBy(allFunctions, ({runtime}) => { + const resolvedRuntime = runtime || service.provider.runtime + // If runtime is not specified on the function or provider, default to previous behaviour + return resolvedRuntime === undefined ? true : resolvedRuntime.match(/^node/) + }) } get rootFileNames() { @@ -234,7 +237,7 @@ export class TypeScriptPlugin { } if (service.package.individually) { - const functionNames = service.getAllFunctions() + const functionNames = Object.keys(this.functions) functionNames.forEach(name => { service.functions[name].package.artifact = path.join( this.originalServicePath, @@ -275,4 +278,4 @@ export class TypeScriptPlugin { } } -module.exports = TypeScriptPlugin +export = TypeScriptPlugin \ No newline at end of file diff --git a/tests/index.functions.test.ts b/tests/index.functions.test.ts new file mode 100644 index 00000000..46535612 --- /dev/null +++ b/tests/index.functions.test.ts @@ -0,0 +1,110 @@ +import TypeScriptPlugin from '../src' + +const createInstance = (functions: Serverless.FunctionMap, globalRuntime?: string): Serverless.Instance => ({ + cli: { + log: jest.fn() + }, + config: { + servicePath: 'servicePath' + }, + service: { + provider: { + name: 'aws', + runtime: globalRuntime + }, + package: { + individually: true, + include: [], + exclude: [] + }, + functions, + getAllFunctions: jest.fn() + }, + pluginManager: { + spawn: jest.fn() + } +}) + +describe('functions', () => { + const functions: Serverless.FunctionMap = { + hello: { + handler: 'tests/assets/hello.handler', + package: { + include: [], + exclude: [] + } + }, + world: { + handler: 'tests/assets/world.handler', + runtime: 'nodejs12.x', + package: { + include: [], + exclude: [] + }, + }, + js: { + handler: 'tests/assets/jsfile.create', + package: { + include: [], + exclude: [] + } + }, + notActuallyTypescript: { + handler: 'tests/assets/jsfile.create', + package: { + include: [], + exclude: [] + }, + runtime: 'go1.x' + }, + } + + describe('when the provider runtime is Node', () => { + it('can get filter out non node based functions', () => { + const slsInstance = createInstance(functions, 'nodejs10.x') + const plugin = new TypeScriptPlugin(slsInstance, {}) + + expect( + Object.values(plugin.functions).map(fn => fn.handler), + ).toEqual( + [ + 'tests/assets/hello.handler', + 'tests/assets/world.handler', + 'tests/assets/jsfile.create', + ], + ) + }) + }) + + describe('when the provider runtime is not Node', () => { + it('can get filter out non node based functions', () => { + const slsInstance = createInstance(functions, 'python2.7') + const plugin = new TypeScriptPlugin(slsInstance, {}) + + expect( + Object.values(plugin.functions).map(fn => fn.handler), + ).toEqual( + [ + 'tests/assets/world.handler', + ], + ) + }) + }) + + describe('when the provider runtime is undefined', () => { + it('can get filter out non node based functions', () => { + const slsInstance = createInstance(functions) + const plugin = new TypeScriptPlugin(slsInstance, {}) + + expect( + Object.values(plugin.functions).map(fn => fn.handler), + ).toEqual( + [ + 'tests/assets/hello.handler', + 'tests/assets/world.handler', + 'tests/assets/jsfile.create', + ], + ) + }) + }) +}) diff --git a/tests/typescript.extractFileName.test.ts b/tests/typescript.extractFileName.test.ts deleted file mode 100644 index 82fac1d8..00000000 --- a/tests/typescript.extractFileName.test.ts +++ /dev/null @@ -1,50 +0,0 @@ -import {extractFileNames} from '../src/typescript' -import * as path from 'path' - -const functions: { [key: string]: Serverless.Function } = { - hello: { - handler: 'tests/assets/hello.handler', - package: { - include: [], - exclude: [] - } - }, - world: { - handler: 'tests/assets/world.handler', - package: { - include: [], - exclude: [] - } - }, - js: { - handler: 'tests/assets/jsfile.create', - package: { - include: [], - exclude: [] - } - }, -} - -describe('extractFileName', () => { - it('get function filenames from serverless service for a non-google provider', () => { - expect( - extractFileNames(process.cwd(), 'aws', functions), - ).toEqual( - [ - 'tests/assets/hello.ts', - 'tests/assets/world.ts', - 'tests/assets/jsfile.js', - ], - ) - }) - - it('get function filename from serverless service for a google provider', () => { - expect( - extractFileNames(path.join(process.cwd(), 'example'), 'google') - ).toEqual( - [ - 'handler.ts' - ] - ) - }) -}) diff --git a/tsconfig.json b/tsconfig.json index 4eb97c5d..b4bb3452 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -4,7 +4,8 @@ "rootDir": ".", "target": "es6", "sourceMap": true, - "outDir": "dist" + "outDir": "dist", + "esModuleInterop": true }, "exclude": [ "node_modules" diff --git a/yarn.lock b/yarn.lock index 735f988f..8b0ac5d8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3456,9 +3456,9 @@ type-check@~0.3.2: prelude-ls "~1.1.2" typescript@^3.4.1: - version "3.4.1" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.4.1.tgz#b6691be11a881ffa9a05765a205cb7383f3b63c6" - integrity sha512-3NSMb2VzDQm8oBTLH6Nj55VVtUEpe/rgkIzMir0qVoLyjDZlnMBva0U6vDiV3IH+sl/Yu6oP5QwsAQtHPmDd2Q== + version "3.7.5" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.7.5.tgz#0692e21f65fd4108b9330238aac11dd2e177a1ae" + integrity sha512-/P5lkRXkWHNAbcJIiHPfRoKqyd7bsyCma1hZNUGfn20qm64T6ZBlrzprymeu918H+mB/0rIg2gGK/BXkhhYgBw== uglify-js@^3.1.4: version "3.5.2"