Skip to content

Commit

Permalink
Initial
Browse files Browse the repository at this point in the history
  • Loading branch information
DBoroujerdi committed Dec 16, 2020
0 parents commit fe28468
Show file tree
Hide file tree
Showing 9 changed files with 3,291 additions and 0 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
*.log
node_modules/
.idea/
bundles/
15 changes: 15 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
"name": "yarn-plugin-serverless-packer",
"main": "./sources/index.ts",
"dependencies": {
"@types/node": "^12.0.0",
"@yarnpkg/builder": "^2.1.2",
"@yarnpkg/core": "^2.3.0",
"clipanion": "^2.6.2",
"micromatch": "^4.0.2",
"typescript": "4.1.0-beta"
},
"scripts": {
"build": "builder build plugin"
}
}
109 changes: 109 additions & 0 deletions sources/commands/packLambda.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import {CommandContext, Configuration, Project, StreamReport} from "@yarnpkg/core";
import {getLibzipSync} from "@yarnpkg/libzip"
import {Filename, ppath, ZipFS, statUtils} from "@yarnpkg/fslib";
import {WorkspaceRequiredError} from "@yarnpkg/cli";
import {Command, Usage} from "clipanion";

import {addFilesToZip, getLambdaSrcFiles, addPackagesToZip} from "../utils";
import fileHash from "../fileHash";

export default class PackageLambdaCommand extends Command<CommandContext> {

@Command.String('-o,--out', {description: "Create the zip at a specified path"})
out?: string;

@Command.String('-s,--src-dir', {description: "Location of lambda src"})
srcDir?: string;

@Command.Boolean('--deps-only', {description: "Only package dependencies"})
depsOnly = false;

// @Command.Boolean('--ignore-mtime', {description: ""})

@Command.Boolean('--json', {description: `Format the output as an NDJSON stream`})
json: boolean = false;

static usage: Usage = Command.Usage({
description: `generate a lambda zip from the active workspace`,
details: `
This command will turn the active workspace into a compressed zip suitable for publishing to AWS. The archive will by default be stored at the root of the workspace (\`lambda.zip\`).
`,
examples: [
[
'Create a zip from the active workspace',
'yarn packageLambda',
],
[
'Define a different name of the output zip',
'yarn packageLambda --out output.zip',
],
[
'Package lambda source compiled with Typescript',
'yarn packageLambda --out lambda.zip --src-dir dist/'
],
[
'Only package the dependencies in the zip - useful for layers only containing node_modules',
'yarn packageLambda --deps-only --out layer.zip'
]
],
});

@Command.Path('packageLambda')
async execute() {
const configuration = await Configuration.find(this.context.cwd, this.context.plugins);
const {project, workspace} = await Project.find(configuration, this.context.cwd);

const target = typeof this.out !== 'undefined'
? ppath.resolve(this.context.cwd, this.out as Filename)
: ppath.resolve(workspace.cwd, 'lambda.zip' as Filename);

const srcPath = typeof this.srcDir !== 'undefined'
? ppath.resolve(this.context.cwd, this.srcDir as Filename)
: workspace.cwd;

if (!workspace)
throw new WorkspaceRequiredError(project.cwd, this.context.cwd);

await project.restoreInstallState();

const pkg = project.storedPackages.get(workspace.anchoredLocator.locatorHash);

if (!pkg)
throw new Error(`Assertion failed: The package should have been registered`);

const libzip = getLibzipSync();

const outputZip = new ZipFS(target, {create: true, libzip, level: 'mixed', stats: statUtils.makeDefaultStats()});

const report = await StreamReport.start({
configuration,
stdout: this.context.stdout,
json: this.json,
}, async report => {
report.reportJson({workspace: workspace.cwd, src: srcPath});

if (!this.depsOnly) {
const files = await getLambdaSrcFiles(srcPath, workspace);

for (const file of files) {
report.reportInfo(null, file);
report.reportJson({src: file});
}

await addFilesToZip(srcPath, files, outputZip)
}

await addPackagesToZip(outputZip, workspace, project, configuration, report);

outputZip.saveAndClose();

const outputZipHash = await fileHash(outputZip.getRealPath());

report.reportInfo(null, `sha256: ${outputZipHash}`);
report.reportJson({hash: outputZipHash});
});

return report.exitCode();
}
}

20 changes: 20 additions & 0 deletions sources/fileHash.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import * as crypto from "crypto";
import * as fs from "fs";

export default function fileHash(filename, algorithm = 'sha256'): Promise<string> {
return new Promise((resolve, reject) => {
const shasum = crypto.createHash(algorithm);
try {
let s = fs.createReadStream(filename)
s.on('data', function (data) {
shasum.update(data)
})
s.on('end', function () {
const hash = shasum.digest('hex')
return resolve(hash);
})
} catch (error) {
return reject('calc fail');
}
});
}
28 changes: 28 additions & 0 deletions sources/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import {
Hooks as CoreHooks,
Plugin,
Workspace,
} from '@yarnpkg/core';
import PackageLambdaCommand from "./commands/packLambda";

export interface Hooks {
beforeWorkspacePacking?: (
workspace: Workspace,
rawManifest: object,
) => Promise<void>|void;
}

const beforeWorkspacePacking = (workspace: Workspace, rawManifest: any) => {
console.log("hooking into beforeWorkspacePacking")
}

const plugin: Plugin<CoreHooks & Hooks> = {
hooks: {
beforeWorkspacePacking
},
commands: [
PackageLambdaCommand,
],
};

export default plugin;
2 changes: 2 additions & 0 deletions sources/types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@

declare module "pnpapi"
Loading

0 comments on commit fe28468

Please sign in to comment.