Skip to content

Copy node_modules folder when symlink fails #24

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions src/deploy-builder.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import * as path from 'path'
import * as fs from 'fs-p'

export class DeployBuilder {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like that you pulled out this complexity to a separate file but I don't think that the name is intuitive and it doesn't need to be a class.

I'd suggest you export a function called symlink instead of a class and use all of the functions outside of the scope of a class.

Does that make sense to you? :)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure. It does :)
The purpose of this class is to prepare the deployment. It just happens that I refactored a little piece of it. I intended to put all the deployment part on it.
What do you think? Should I complete the refactoring or keep it in the monolite way?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's great that you're splitting it up into multiple functions, I just think they don't need to live inside a class.

build(buildFolder: string) {
const buildPath = path.resolve(buildFolder)

if (this.isNodeModulesAbsent(buildPath)) {
this.createNodeModulesFolder(buildPath)
}
}

private isNodeModulesAbsent(buildPath: string): boolean {
return !fs.existsSync(path.join(buildPath, 'node_modules'))
}

private createNodeModulesFolder(buildPath: string) {
try {
fs.symlinkSync(path.resolve('node_modules'), path.join(buildPath, 'node_modules'))
} catch (error) {
this.copyIfMissingSymlinkPermission(buildPath, error)
}
}

private copyIfMissingSymlinkPermission(buildPath: string, error: SymlinkException) {
if (this.isMissingSymlinkPermission(error)) {
fs.copySync(path.resolve('node_modules'), path.join(buildPath, 'node_modules'))
} else {
throw error
}
}

private isMissingSymlinkPermission(error: SymlinkException): boolean {
// Generally happens when no admin rights with UAC enabled on Windows.
return error.code === 'EPERM' && error.errno === -4048
}
}

export interface SymlinkException {
code: string
errno: number
}
11 changes: 6 additions & 5 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import * as fs from 'fs-p'
import * as _ from 'lodash'
import * as globby from 'globby'

import { DeployBuilder } from './deploy-builder'
import { ServerlessOptions, ServerlessInstance, ServerlessFunction } from './types'
import * as typescript from './typescript'

Expand All @@ -11,7 +12,6 @@ const serverlessFolder = '.serverless'
const buildFolder = '.build'

class ServerlessPlugin {

private originalServicePath: string
private originalFunctions: { [key: string]: ServerlessFunction } | {}

Expand All @@ -20,6 +20,8 @@ class ServerlessPlugin {
commands: { [key: string]: any }
hooks: { [key: string]: Function }

private deployBuilder: DeployBuilder

constructor(serverless: ServerlessInstance, options: ServerlessOptions) {
this.serverless = serverless
this.options = options
Expand Down Expand Up @@ -56,6 +58,8 @@ class ServerlessPlugin {
},
},
}

this.deployBuilder = new DeployBuilder()
}

async beforeCreateDeploymentArtifacts(type: string): Promise<void> {
Expand Down Expand Up @@ -86,10 +90,7 @@ class ServerlessPlugin {

await typescript.run(tsFileNames, tsconfig)

// include node_modules into build
if (!fs.existsSync(path.resolve(path.join(buildFolder, 'node_modules')))) {
fs.symlinkSync(path.resolve('node_modules'), path.resolve(path.join(buildFolder, 'node_modules')))
}
this.deployBuilder.build(buildFolder)

// include any "extras" from the "include" section
if (this.serverless.service.package.include && this.serverless.service.package.include.length > 0) {
Expand Down