typing improvements, adding a new scope to packages, starting on the next-deploy CLI

This commit is contained in:
Egor 2020-07-07 01:35:47 -07:00
parent b35fa8f6d2
commit efb5cafbdf
33 changed files with 3861 additions and 6757 deletions

60
cli/deploy.ts Normal file
View file

@ -0,0 +1,60 @@
#!/usr/bin/env node
import fs from 'fs-extra';
import path from 'path';
import AwsComponent from '@next-deploy/aws-component';
const SUPPORTED_ENGINES = [
{
type: 'aws',
component: '@next-deploy/aws-component',
},
];
const DEFAULT_ENGINE = 'aws';
const DEPLOY_CONFIG_NAME = 'deploy.config.js';
(async () => {
const deployConfigPath = path.join(process.cwd(), DEPLOY_CONFIG_NAME);
const configPathExists = fs.existsSync(deployConfigPath);
if (!configPathExists) {
fs.writeFileSync(deployConfigPath, getDefaultConfigData());
}
const {
debug = false,
engine = DEFAULT_ENGINE,
...componentOptions
}: BaseDeploymentOptions = await import(deployConfigPath);
const engineIndex = SUPPORTED_ENGINES.findIndex(({ type }) => type === engine);
if (engineIndex === -1) {
throw new Error(
`Engine ${engine} is unsupported. Pick one of: ${SUPPORTED_ENGINES.map(
({ type }) => type
).join(',')}.`
);
}
const EngineComponent = await import(SUPPORTED_ENGINES[engineIndex].component);
const engineComponent = new EngineComponent.default();
if (engine === 'aws') {
await (engineComponent as AwsComponent).default(componentOptions);
}
})();
function getDefaultConfigData(): string {
return `// for configurable options visit: https://github.com/nidratech/next-deploy#options
module.exports = {
// prints helpful output during deployment
debug: false,
};
`;
}
type BaseDeploymentOptions = {
engine?: 'aws';
debug?: boolean;
};

View file

@ -1,7 +1,7 @@
{ {
"name": "next-deploy", "name": "next-deploy",
"version": "0.0.1", "version": "0.0.1",
"description": "Effortlessly deploy your Next.js application.", "description": "Effortless deployment for Next.js apps.",
"author": "Nidratech Ltd. <egor@nidratech.com>", "author": "Nidratech Ltd. <egor@nidratech.com>",
"main": "index.js", "main": "index.js",
"keywords": [ "keywords": [
@ -9,16 +9,23 @@
"deploy", "deploy",
"serverless", "serverless",
"nextjs", "nextjs",
"lambda" "lambda",
"cloudfront",
"edge"
], ],
"scripts": { "scripts": {
"test": "jest --runInBand", "test": "jest --runInBand",
"build": "lerna exec -- yarn", "build": "lerna exec -- yarn",
"test:watch": "yarn test --watch --collect-coverage=false", "test:watch": "yarn test --watch --collect-coverage=false",
"publish": "lerna publish --conventional-commits", "publish": "lerna publish --conventional-commits",
"prepublishOnly": "yarn test",
"prerelease": "lerna publish --conventional-commits --conventional-prerelease", "prerelease": "lerna publish --conventional-commits --conventional-prerelease",
"graduate": "lerna publish --conventional-commits --conventional-graduate", "graduate": "lerna publish --conventional-commits --conventional-graduate",
"lint": "eslint ." "prepare": "yarn build-self",
"build-self": "tsc -p tsconfig.build.json"
},
"bin": {
"next-deploy": "./dist/deploy.js"
}, },
"repository": { "repository": {
"type": "git", "type": "git",
@ -33,22 +40,24 @@
"@babel/plugin-proposal-class-properties": "^7.10.4", "@babel/plugin-proposal-class-properties": "^7.10.4",
"@babel/preset-env": "^7.10.4", "@babel/preset-env": "^7.10.4",
"@babel/preset-typescript": "^7.10.4", "@babel/preset-typescript": "^7.10.4",
"@next-deploy/aws-cloudfront": "link:./packages/aws-cloudfront",
"@next-deploy/aws-component": "link:./packages/aws-component",
"@next-deploy/aws-lambda-builder": "link:./packages/aws-lambda-builder",
"@types/archiver": "^3.1.0", "@types/archiver": "^3.1.0",
"@types/aws-lambda": "^8.10.57", "@types/aws-lambda": "^8.10.58",
"@types/execa": "^2.0.0", "@types/execa": "^2.0.0",
"@types/fs-extra": "^9.0.1", "@types/fs-extra": "^9.0.1",
"@types/jest": "^26.0.3", "@types/jest": "^26.0.4",
"@types/klaw": "^3.0.1", "@types/klaw": "^3.0.1",
"@types/mime-types": "^2.1.0", "@types/mime-types": "^2.1.0",
"@types/node": "^14.0.14", "@types/node": "^14.0.18",
"@types/path-to-regexp": "^1.7.0", "@types/path-to-regexp": "^1.7.0",
"@types/ramda": "^0.27.7", "@types/ramda": "^0.27.7",
"@types/react": "^16.9.41", "@types/react": "^16.9.41",
"@types/react-dom": "^16.9.8", "@types/react-dom": "^16.9.8",
"@types/webpack": "^4.41.18", "@types/webpack": "^4.41.20",
"@typescript-eslint/eslint-plugin": "^3.5.0", "@typescript-eslint/eslint-plugin": "^3.6.0",
"@typescript-eslint/parser": "^3.5.0", "@typescript-eslint/parser": "^3.6.0",
"aws-lambda-builder": "link:./packages/aws-lambda-builder",
"eslint": "^7.4.0", "eslint": "^7.4.0",
"eslint-config-prettier": "^6.11.0", "eslint-config-prettier": "^6.11.0",
"eslint-plugin-prettier": "^3.1.4", "eslint-plugin-prettier": "^3.1.4",
@ -57,7 +66,8 @@
"jest-when": "^2.7.2", "jest-when": "^2.7.2",
"lerna": "^3.22.1", "lerna": "^3.22.1",
"lint-staged": "^10.2.11", "lint-staged": "^10.2.11",
"prettier": "^2.0.5" "prettier": "^2.0.5",
"typescript": "^3.9.6"
}, },
"husky": { "husky": {
"hooks": { "hooks": {

View file

@ -1,5 +1,5 @@
{ {
"name": "aws-cloudfront", "name": "@next-deploy/aws-cloudfront",
"version": "1.0.0", "version": "1.0.0",
"license": "MIT", "license": "MIT",
"main": "serverless.js", "main": "serverless.js",

View file

@ -19,11 +19,11 @@ class CloudFrontComponent extends Component {
credentials: Credentials; credentials: Credentials;
distributionId: string; distributionId: string;
paths?: string[]; paths?: string[];
}) { }): Promise<CloudFront.CreateInvalidationResult> {
createInvalidation({ credentials, distributionId, paths }); return createInvalidation({ credentials, distributionId, paths });
} }
async default(inputs: CloudFrontInputs) { async default(inputs: CloudFrontInputs): Promise<any> {
this.context.status('Deploying'); this.context.status('Deploying');
inputs.region = inputs.region || 'us-east-1'; inputs.region = inputs.region || 'us-east-1';
@ -72,7 +72,7 @@ class CloudFrontComponent extends Component {
return this.state; return this.state;
} }
async remove() { async remove(): Promise<void> {
this.context.status('Removing'); this.context.status('Removing');
if (!this.state.id) { if (!this.state.id) {
@ -90,7 +90,6 @@ class CloudFrontComponent extends Component {
await this.save(); await this.save();
this.context.debug(`CloudFront distribution was successfully removed.`); this.context.debug(`CloudFront distribution was successfully removed.`);
return {};
} }
} }

View file

@ -19,8 +19,8 @@ type PathPatternConfig = {
type Origin = { type Origin = {
url: string; url: string;
private: boolean; private?: boolean;
pathPatterns: Record<string, PathPatternConfig>; pathPatterns?: Record<string, PathPatternConfig>;
}; };
type Credentials = { type Credentials = {

View file

@ -1,11 +1,11 @@
import fse from 'fs-extra'; import fse from 'fs-extra';
import path from 'path'; import path from 'path';
import { mockDomain } from 'aws-domain'; import { mockDomain } from '@next-deploy/aws-domain';
import { mockS3 } from '@serverless/aws-s3'; import { mockS3 } from '@serverless/aws-s3';
import { mockUpload } from 'aws-sdk'; import { mockUpload } from 'aws-sdk';
import { mockLambda, mockLambdaPublish } from 'aws-lambda'; import { mockLambda, mockLambdaPublish } from '@next-deploy/aws-lambda';
import { mockCloudFront } from 'aws-cloudfront'; import { mockCloudFront } from '@next-deploy/aws-cloudfront';
import NextjsComponent, { DEFAULT_LAMBDA_CODE_DIR, API_LAMBDA_CODE_DIR } from '../src/component'; import NextjsComponent, { DEFAULT_LAMBDA_CODE_DIR, API_LAMBDA_CODE_DIR } from '../src/component';
import { getDomains } from '../src/utils'; import { getDomains } from '../src/utils';

View file

@ -2,8 +2,8 @@ import path from 'path';
import fse from 'fs-extra'; import fse from 'fs-extra';
import { mockS3 } from '@serverless/aws-s3'; import { mockS3 } from '@serverless/aws-s3';
import { mockCloudFront, mockCreateInvalidation } from 'aws-cloudfront'; import { mockCloudFront, mockCreateInvalidation } from '@next-deploy/aws-cloudfront';
import { mockLambda, mockLambdaPublish } from 'aws-lambda'; import { mockLambda, mockLambdaPublish } from '@next-deploy/aws-lambda';
import NextjsComponent, { DEFAULT_LAMBDA_CODE_DIR, API_LAMBDA_CODE_DIR } from '../src/component'; import NextjsComponent, { DEFAULT_LAMBDA_CODE_DIR, API_LAMBDA_CODE_DIR } from '../src/component';
import { cleanupFixtureDirectory } from './test-utils'; import { cleanupFixtureDirectory } from './test-utils';

View file

@ -1,5 +1,5 @@
{ {
"name": "aws-component", "name": "@next-deploy/aws-component",
"version": "1.0.0", "version": "1.0.0",
"license": "MIT", "license": "MIT",
"main": "serverless.js", "main": "serverless.js",
@ -11,11 +11,11 @@
"dependencies": { "dependencies": {
"@serverless/aws-s3": "^4.2.0", "@serverless/aws-s3": "^4.2.0",
"@serverless/core": "^1.1.2", "@serverless/core": "^1.1.2",
"aws-cloudfront": "link:../aws-cloudfront", "@next-deploy/aws-cloudfront": "link:../aws-cloudfront",
"aws-domain": "link:../aws-domain", "@next-deploy/aws-domain": "link:../aws-domain",
"aws-lambda": "link:../aws-lambda", "@next-deploy/aws-lambda": "link:../aws-lambda",
"aws-lambda-builder": "link:../aws-lambda-builder", "@next-deploy/aws-lambda-builder": "link:../aws-lambda-builder",
"aws-s3-utils": "link:../aws-s3-utils", "@next-deploy/aws-s3-utils": "link:../aws-s3-utils",
"fs-extra": "^9.0.1" "fs-extra": "^9.0.1"
}, },
"devDependencies": { "devDependencies": {

View file

@ -2,18 +2,28 @@ import { Component } from '@serverless/core';
import { exists, readJSON } from 'fs-extra'; import { exists, readJSON } from 'fs-extra';
import { resolve, join } from 'path'; import { resolve, join } from 'path';
import Builder from 'aws-lambda-builder'; import Builder from '@next-deploy/aws-lambda-builder';
import { OriginRequestDefaultHandlerManifest as BuildManifest } from 'aws-lambda-builder/types'; import { uploadStaticAssets } from '@next-deploy/aws-s3-utils';
import { uploadStaticAssets } from 'aws-s3-utils'; import AwsCloudFront from '@next-deploy/aws-cloudfront';
import AwsCloudFront from 'aws-cloudfront';
import { getDomains } from './utils'; import { getDomains } from './utils';
import {
OriginRequestDefaultHandlerManifest as BuildManifest,
OriginRequestApiHandlerManifest,
} from '@next-deploy/aws-lambda-builder/types';
import { PathPatternConfig } from '@next-deploy/aws-cloudfront/types';
import { Origin } from '@next-deploy/aws-cloudfront/types';
import { BuildOptions, AwsComponentInputs, LambdaType, LambdaInput } from '../types'; import { BuildOptions, AwsComponentInputs, LambdaType, LambdaInput } from '../types';
export const DEFAULT_LAMBDA_CODE_DIR = '.serverless_nextjs/default-lambda'; export const DEFAULT_LAMBDA_CODE_DIR = '.serverless_nextjs/default-lambda';
export const API_LAMBDA_CODE_DIR = '.serverless_nextjs/api-lambda'; export const API_LAMBDA_CODE_DIR = '.serverless_nextjs/api-lambda';
class AwsComponent extends Component { class AwsComponent extends Component {
async default(inputs: AwsComponentInputs = {}): Promise<any> { async default(
inputs: AwsComponentInputs = {}
): Promise<{
appUrl: string;
bucketName: string;
}> {
// @ts-ignore // @ts-ignore
if (inputs.build !== false) { if (inputs.build !== false) {
await this.build(inputs); await this.build(inputs);
@ -22,7 +32,7 @@ class AwsComponent extends Component {
return this.deploy(inputs); return this.deploy(inputs);
} }
readDefaultBuildManifest(nextConfigPath: string): Promise<any> { readDefaultBuildManifest(nextConfigPath: string): Promise<BuildManifest> {
return readJSON(join(nextConfigPath, '.serverless_nextjs/default-lambda/manifest.json')); return readJSON(join(nextConfigPath, '.serverless_nextjs/default-lambda/manifest.json'));
} }
@ -104,7 +114,9 @@ class AwsComponent extends Component {
} }
} }
async readApiBuildManifest(nextConfigPath: string): Promise<any> { async readApiBuildManifest(
nextConfigPath: string
): Promise<undefined | OriginRequestApiHandlerManifest> {
const path = join(nextConfigPath, '.serverless_nextjs/api-lambda/manifest.json'); const path = join(nextConfigPath, '.serverless_nextjs/api-lambda/manifest.json');
// @ts-ignore // @ts-ignore
@ -146,7 +158,7 @@ class AwsComponent extends Component {
const nextStaticPath = inputs.nextStaticDir ? resolve(inputs.nextStaticDir) : nextConfigPath; const nextStaticPath = inputs.nextStaticDir ? resolve(inputs.nextStaticDir) : nextConfigPath;
const customCloudFrontConfig = inputs.cloudfront || {}; const customCloudFrontConfig: Record<string, any> = inputs.cloudfront || {};
const [defaultBuildManifest, apiBuildManifest] = await Promise.all([ const [defaultBuildManifest, apiBuildManifest] = await Promise.all([
this.readDefaultBuildManifest(nextConfigPath), this.readDefaultBuildManifest(nextConfigPath),
@ -155,9 +167,9 @@ class AwsComponent extends Component {
const [bucket, cloudFront, defaultEdgeLambda, apiEdgeLambda] = await Promise.all([ const [bucket, cloudFront, defaultEdgeLambda, apiEdgeLambda] = await Promise.all([
this.load('@serverless/aws-s3'), this.load('@serverless/aws-s3'),
this.load('aws-cloudfront'), this.load('@next-deploy/aws-cloudfront'),
this.load('aws-lambda', 'defaultEdgeLambda'), this.load('@next-deploy/aws-lambda', 'defaultEdgeLambda'),
this.load('aws-lambda', 'apiEdgeLambda'), this.load('@next-deploy/aws-lambda', 'apiEdgeLambda'),
]); ]);
const bucketOutputs = await bucket({ const bucketOutputs = await bucket({
@ -174,18 +186,12 @@ class AwsComponent extends Component {
publicDirectoryCache: inputs.publicDirectoryCache, publicDirectoryCache: inputs.publicDirectoryCache,
}); });
defaultBuildManifest.cloudFrontOrigins = {
staticOrigin: {
domainName: `${bucketOutputs.name}.s3.amazonaws.com`,
},
};
const bucketUrl = `http://${bucketOutputs.name}.s3.amazonaws.com`; const bucketUrl = `http://${bucketOutputs.name}.s3.amazonaws.com`;
// If origin is relative path then prepend the bucketUrl // If origin is relative path then prepend the bucketUrl
// e.g. /path => http://bucket.s3.aws.com/path // e.g. /path => http://bucket.s3.aws.com/path
const expandRelativeUrls = (origin: string | Record<string, unknown>) => { const expandRelativeUrls = (origin: string | Origin): string | Origin => {
const originUrl = typeof origin === 'string' ? origin : (origin.url as string); const originUrl = typeof origin === 'string' ? origin : origin.url;
const fullOriginUrl = originUrl.charAt(0) === '/' ? `${bucketUrl}${originUrl}` : originUrl; const fullOriginUrl = originUrl.charAt(0) === '/' ? `${bucketUrl}${originUrl}` : originUrl;
if (typeof origin === 'string') { if (typeof origin === 'string') {
@ -199,7 +205,7 @@ class AwsComponent extends Component {
}; };
// parse origins from inputs // parse origins from inputs
let inputOrigins: any[] = []; let inputOrigins: any = [];
if (inputs.cloudfront && inputs.cloudfront.origins) { if (inputs.cloudfront && inputs.cloudfront.origins) {
const origins = inputs.cloudfront.origins as string[]; const origins = inputs.cloudfront.origins as string[];
inputOrigins = origins.map(expandRelativeUrls); inputOrigins = origins.map(expandRelativeUrls);
@ -311,12 +317,11 @@ class AwsComponent extends Component {
const defaultEdgeLambdaPublishOutputs = await defaultEdgeLambda.publishVersion(); const defaultEdgeLambdaPublishOutputs = await defaultEdgeLambda.publishVersion();
let defaultCloudfrontInputs; let defaultCloudfrontInputs = {} as Partial<PathPatternConfig>;
if (inputs.cloudfront && inputs.cloudfront.defaults) { if (inputs.cloudfront && inputs.cloudfront.defaults) {
defaultCloudfrontInputs = inputs.cloudfront.defaults; defaultCloudfrontInputs = inputs.cloudfront.defaults;
delete inputs.cloudfront.defaults; delete inputs.cloudfront.defaults;
} else {
defaultCloudfrontInputs = {};
} }
// validate that the custom config paths match generated paths in the manifest // validate that the custom config paths match generated paths in the manifest
@ -401,7 +406,7 @@ class AwsComponent extends Component {
const { domain, subdomain } = getDomains(inputs.domain); const { domain, subdomain } = getDomains(inputs.domain);
if (domain && subdomain) { if (domain && subdomain) {
const domainComponent = await this.load('aws-domain'); const domainComponent = await this.load('@next-deploy/aws-domain');
const domainOutputs = await domainComponent({ const domainOutputs = await domainComponent({
privateZone: false, privateZone: false,
domain, domain,
@ -423,8 +428,8 @@ class AwsComponent extends Component {
async remove(): Promise<void> { async remove(): Promise<void> {
const [bucket, cloudfront, domain] = await Promise.all([ const [bucket, cloudfront, domain] = await Promise.all([
this.load('@serverless/aws-s3'), this.load('@serverless/aws-s3'),
this.load('aws-cloudfront'), this.load('@next-deploy/aws-cloudfront'),
this.load('aws-domain'), this.load('@next-deploy/aws-domain'),
]); ]);
await Promise.all([bucket.remove(), cloudfront.remove(), domain.remove()]); await Promise.all([bucket.remove(), cloudfront.remove(), domain.remove()]);

View file

@ -1,4 +1,5 @@
import { PublicDirectoryCache } from 'aws-s3-utils/types'; import { PublicDirectoryCache } from '@next-deploy/aws-s3-utils/types';
import { CloudFrontInputs } from '@next-deploy/aws-cloudfront/types';
type AwsComponentInputs = { type AwsComponentInputs = {
build?: BuildOptions; // TODO: figure out a way to properly type this as "BuildOptions | boolean" doesn't work correctly build?: BuildOptions; // TODO: figure out a way to properly type this as "BuildOptions | boolean" doesn't work correctly
@ -15,11 +16,9 @@ type AwsComponentInputs = {
policy?: string; policy?: string;
domain?: string | string[]; domain?: string | string[];
domainType?: DomainType; domainType?: DomainType;
cloudfront?: CloudfrontOptions; cloudfront?: CloudFrontInputs;
}; };
type CloudfrontOptions = Record<string, any>;
type DomainType = 'www' | 'apex' | 'both'; type DomainType = 'www' | 'apex' | 'both';
type BuildOptions = { type BuildOptions = {

View file

@ -1008,6 +1008,26 @@
call-me-maybe "^1.0.1" call-me-maybe "^1.0.1"
glob-to-regexp "^0.3.0" glob-to-regexp "^0.3.0"
"@next-deploy/aws-cloudfront@link:../aws-cloudfront":
version "0.0.0"
uid ""
"@next-deploy/aws-domain@link:../aws-domain":
version "0.0.0"
uid ""
"@next-deploy/aws-lambda-builder@link:../aws-lambda-builder":
version "0.0.0"
uid ""
"@next-deploy/aws-lambda@link:../aws-lambda":
version "0.0.0"
uid ""
"@next-deploy/aws-s3-utils@link:../aws-s3-utils":
version "0.0.0"
uid ""
"@next/react-dev-overlay@9.4.4": "@next/react-dev-overlay@9.4.4":
version "9.4.4" version "9.4.4"
resolved "https://registry.yarnpkg.com/@next/react-dev-overlay/-/react-dev-overlay-9.4.4.tgz#4ae03ac839ff022b3ce5c695bd24b179d4ef459d" resolved "https://registry.yarnpkg.com/@next/react-dev-overlay/-/react-dev-overlay-9.4.4.tgz#4ae03ac839ff022b3ce5c695bd24b179d4ef459d"
@ -1650,30 +1670,6 @@ atob@^2.1.2:
resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9" resolved "https://registry.yarnpkg.com/atob/-/atob-2.1.2.tgz#6d9517eb9e030d2436666651e86bd9f6f13533c9"
integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg== integrity sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==
"aws-cloudfront@link:../aws-cloudfront":
version "0.0.0"
uid ""
"aws-component@link:.":
version "0.0.0"
uid ""
"aws-domain@link:../aws-domain":
version "0.0.0"
uid ""
"aws-lambda-builder@link:../aws-lambda-builder":
version "0.0.0"
uid ""
"aws-lambda@link:../aws-lambda":
version "0.0.0"
uid ""
"aws-s3-utils@link:../aws-s3-utils":
version "0.0.0"
uid ""
aws-sdk@^2.387.0, aws-sdk@^2.488.0, aws-sdk@^2.709.0: aws-sdk@^2.387.0, aws-sdk@^2.488.0, aws-sdk@^2.709.0:
version "2.709.0" version "2.709.0"
resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.709.0.tgz#33b0c0fe8b9420c65610545394be047ac2d93c8f" resolved "https://registry.yarnpkg.com/aws-sdk/-/aws-sdk-2.709.0.tgz#33b0c0fe8b9420c65610545394be047ac2d93c8f"

View file

@ -1,5 +1,5 @@
{ {
"name": "aws-domain", "name": "@next-deploy/aws-domain",
"version": "1.0.0", "version": "1.0.0",
"license": "MIT", "license": "MIT",
"main": "serverless.js", "main": "serverless.js",
@ -10,7 +10,6 @@
}, },
"dependencies": { "dependencies": {
"@serverless/core": "^1.1.2", "@serverless/core": "^1.1.2",
"aws-component": "link:../aws-component",
"aws-sdk": "^2.709.0" "aws-sdk": "^2.709.0"
}, },
"devDependencies": { "devDependencies": {

View file

@ -151,7 +151,7 @@ class DomainComponent extends Component {
return outputs; return outputs;
} }
async remove() { async remove(): Promise<void> {
this.context.status('Deploying'); this.context.status('Deploying');
if (!this.state.domain) { if (!this.state.domain) {
@ -193,8 +193,6 @@ class DomainComponent extends Component {
} }
this.state = {}; this.state = {};
await this.save(); await this.save();
return {};
} }
} }

View file

@ -1,7 +1,8 @@
import { Route53, ACM, CloudFront } from 'aws-sdk'; import { Route53, ACM, CloudFront } from 'aws-sdk';
import { utils } from '@serverless/core'; import { utils } from '@serverless/core';
import { DomainType } from 'aws-component/types'; import { PathPatternConfig } from '@next-deploy/aws-cloudfront/types';
import { DomainType } from '@next-deploy/aws-component/types';
import { AwsDomainInputs, Credentials, SubDomain } from '../types'; import { AwsDomainInputs, Credentials, SubDomain } from '../types';
const DEFAULT_MINIMUM_PROTOCOL_VERSION = 'TLSv1.2_2018'; const DEFAULT_MINIMUM_PROTOCOL_VERSION = 'TLSv1.2_2018';
@ -68,7 +69,7 @@ export const getDomainHostedZoneId = async (
route53: Route53, route53: Route53,
domain: string, domain: string,
privateZone: boolean privateZone: boolean
) => { ): Promise<string> => {
const hostedZonesRes = await route53.listHostedZonesByName().promise(); const hostedZonesRes = await route53.listHostedZonesByName().promise();
const hostedZone = hostedZonesRes.HostedZones.find( const hostedZone = hostedZonesRes.HostedZones.find(
@ -89,7 +90,10 @@ export const getDomainHostedZoneId = async (
* Describe Certificate By Arn * Describe Certificate By Arn
* - Describe an AWS ACM Certificate by its ARN * - Describe an AWS ACM Certificate by its ARN
*/ */
export const describeCertificateByArn = async (acm: ACM, certificateArn: string) => { export const describeCertificateByArn = async (
acm: ACM,
certificateArn: string
): Promise<ACM.CertificateDetail | null> => {
const certificate = await acm.describeCertificate({ CertificateArn: certificateArn }).promise(); const certificate = await acm.describeCertificate({ CertificateArn: certificateArn }).promise();
return certificate && certificate.Certificate ? certificate.Certificate : null; return certificate && certificate.Certificate ? certificate.Certificate : null;
}; };
@ -98,7 +102,10 @@ export const describeCertificateByArn = async (acm: ACM, certificateArn: string)
* Get Certificate Arn By Domain * Get Certificate Arn By Domain
* - Gets an AWS ACM Certificate by a specified domain or return null * - Gets an AWS ACM Certificate by a specified domain or return null
*/ */
export const getCertificateArnByDomain = async (acm: ACM, domain: string) => { export const getCertificateArnByDomain = async (
acm: ACM,
domain: string
): Promise<string | null> => {
const listRes = await acm.listCertificates().promise(); const listRes = await acm.listCertificates().promise();
if (!listRes.CertificateSummaryList) { if (!listRes.CertificateSummaryList) {
@ -160,10 +167,9 @@ export const validateCertificate = async (
certificate: ACM.CertificateDetail, certificate: ACM.CertificateDetail,
domain: string, domain: string,
domainHostedZoneId: string domainHostedZoneId: string
) => { ): Promise<void> => {
let readinessCheckCount = 16; let readinessCheckCount = 16;
let statusCheckCount = 16; let statusCheckCount = 16;
let validationResourceRecord: ACM.ResourceRecord;
/** /**
* Check Readiness * Check Readiness
@ -197,7 +203,7 @@ export const validateCertificate = async (
return await checkReadiness(); return await checkReadiness();
}; };
validationResourceRecord = await checkReadiness(); const validationResourceRecord = await checkReadiness();
const checkRecordsParams = { const checkRecordsParams = {
HostedZoneId: domainHostedZoneId, HostedZoneId: domainHostedZoneId,
@ -320,7 +326,7 @@ export const removeCloudFrontDomainDnsRecords = async (
domain: string, domain: string,
domainHostedZoneId: string, domainHostedZoneId: string,
distributionUrl: string distributionUrl: string
) => { ): Promise<void> => {
const params = { const params = {
HostedZoneId: domainHostedZoneId, HostedZoneId: domainHostedZoneId,
ChangeBatch: { ChangeBatch: {
@ -357,8 +363,12 @@ export const addDomainToCloudfrontDistribution = async (
subdomain: SubDomain, subdomain: SubDomain,
certificateArn: string, certificateArn: string,
domainType: DomainType, domainType: DomainType,
defaultCloudfrontInputs: any defaultCloudfrontInputs: Partial<PathPatternConfig>
) => { ): Promise<{
id?: string;
arn?: string;
url?: string;
}> => {
const distributionConfigResponse = await cf const distributionConfigResponse = await cf
.getDistributionConfig({ Id: subdomain.distributionId }) .getDistributionConfig({ Id: subdomain.distributionId })
.promise(); .promise();
@ -416,7 +426,11 @@ export const addDomainToCloudfrontDistribution = async (
export const removeDomainFromCloudFrontDistribution = async ( export const removeDomainFromCloudFrontDistribution = async (
cf: CloudFront, cf: CloudFront,
subdomain: SubDomain subdomain: SubDomain
) => { ): Promise<{
id?: string;
arn?: string;
url?: string;
}> => {
const distributionConfigResponse = await cf const distributionConfigResponse = await cf
.getDistributionConfig({ Id: subdomain.distributionId }) .getDistributionConfig({ Id: subdomain.distributionId })
.promise(); .promise();

View file

@ -1,11 +1,12 @@
import { DomainType } from 'aws-component/types'; import { DomainType } from '@next-deploy/aws-component/types';
import { PathPatternConfig } from '@next-deploy/aws-cloudfront/types';
type AwsDomainInputs = { type AwsDomainInputs = {
domain: string; domain: string;
region?: string; region?: string;
privateZone?: boolean; privateZone?: boolean;
domainType?: DomainType; domainType?: DomainType;
defaultCloudfrontInputs?: any; defaultCloudfrontInputs?: Partial<PathPatternConfig>;
subdomains: SubDomain[]; subdomains: SubDomain[];
}; };

File diff suppressed because it is too large Load diff

View file

@ -36,7 +36,7 @@ describe('Serverless Trace With Dynamic Import', () => {
expect(nodeModules).toEqual(['@sls-next', 'next']); expect(nodeModules).toEqual(['@sls-next', 'next']);
const slsNextNodeModules = await readdir(path.join(outputDir, 'api-lambda/node_modules')); const slsNextNodeModules = await readdir(path.join(outputDir, 'api-lambda/node_modules'));
expect(slsNextNodeModules).toContain('next-aws-cloudfront'); expect(slsNextNodeModules).toContain('@next-deploy/aws-lambda-builder');
}); });
it('copies dynamic chunk to default lambda artifact', async () => { it('copies dynamic chunk to default lambda artifact', async () => {

View file

@ -1,6 +1,5 @@
import path from 'path'; import path from 'path';
import { remove } from 'fs-extra'; import { remove } from 'fs-extra';
import { CloudFrontOrigin } from 'aws-lambda';
import { OriginRequestEvent } from '../types'; import { OriginRequestEvent } from '../types';
export const cleanupDir = (dir: string): Promise<void> => { export const cleanupDir = (dir: string): Promise<void> => {

View file

@ -1,5 +1,5 @@
{ {
"name": "aws-lambda-builder", "name": "@next-deploy/aws-lambda-builder",
"version": "1.0.0", "version": "1.0.0",
"license": "MIT", "license": "MIT",
"main": "dist/index.js", "main": "dist/index.js",

View file

@ -114,8 +114,6 @@ class Builder {
} }
async buildDefaultLambda(buildManifest: OriginRequestDefaultHandlerManifest): Promise<void[]> { async buildDefaultLambda(buildManifest: OriginRequestDefaultHandlerManifest): Promise<void[]> {
let copyTraces: Promise<void>[] = [];
const ignoreAppAndDocumentPages = (page: string): boolean => { const ignoreAppAndDocumentPages = (page: string): boolean => {
const basename = path.basename(page); const basename = path.basename(page);
return basename !== '_app.js' && basename !== '_document.js'; return basename !== '_app.js' && basename !== '_document.js';
@ -134,7 +132,11 @@ class Builder {
base: process.cwd(), base: process.cwd(),
}); });
copyTraces = this.copyLambdaHandlerDependencies(fileList, reasons, DEFAULT_LAMBDA_CODE_DIR); const copyTraces = this.copyLambdaHandlerDependencies(
fileList,
reasons,
DEFAULT_LAMBDA_CODE_DIR
);
return Promise.all([ return Promise.all([
...copyTraces, ...copyTraces,

View file

@ -198,7 +198,7 @@ const handler = ({
return true; return true;
}; };
let gz = isGzipSupported(headers); const gz = isGzipSupported(headers);
const responsePromise = new Promise<CloudFrontResultResponse>((resolve) => { const responsePromise = new Promise<CloudFrontResultResponse>((resolve) => {
res.end = (text: any) => { res.end = (text: any) => {

View file

@ -1,6 +1,8 @@
import fs from 'fs-extra'; import fs from 'fs-extra';
import path from 'path'; import path from 'path';
import { CreateServerlessConfigResult } from '../../types';
function getCustomData(importName: string, target: string): string { function getCustomData(importName: string, target: string): string {
return ` return `
module.exports = function(...args) { module.exports = function(...args) {
@ -32,10 +34,6 @@ function getDefaultData(target: string): string {
return `module.exports = { target: '${target}' };`; return `module.exports = { target: '${target}' };`;
} }
type CreateServerlessConfigResult = {
restoreUserConfig: () => Promise<void>;
};
export default async function createServerlessConfig( export default async function createServerlessConfig(
workPath: string, workPath: string,
entryPath: string entryPath: string

View file

@ -4,7 +4,7 @@ import path from 'path';
const getAllFilesRecursively = (dirPath: string, arrayOfFiles: string[]): string[] => { const getAllFilesRecursively = (dirPath: string, arrayOfFiles: string[]): string[] => {
const files = fs.readdirSync(dirPath); const files = fs.readdirSync(dirPath);
files.forEach(function (file) { files.forEach((file) => {
if (fs.statSync(dirPath + path.sep + file).isDirectory()) { if (fs.statSync(dirPath + path.sep + file).isDirectory()) {
arrayOfFiles = getAllFilesRecursively(path.join(dirPath, file), arrayOfFiles); arrayOfFiles = getAllFilesRecursively(path.join(dirPath, file), arrayOfFiles);
} else { } else {

View file

@ -73,3 +73,7 @@ type BuildOptions = {
cwd?: string; cwd?: string;
cmd?: string; cmd?: string;
}; };
type CreateServerlessConfigResult = {
restoreUserConfig: () => Promise<void>;
};

View file

@ -1,5 +1,5 @@
{ {
"name": "aws-lambda", "name": "@next-deploy/aws-lambda",
"version": "1.0.0", "version": "1.0.0",
"license": "MIT", "license": "MIT",
"main": "serverless.js", "main": "serverless.js",

View file

@ -1,5 +1,5 @@
{ {
"name": "aws-s3-utils", "name": "@next-deploy/aws-s3-utils",
"version": "1.0.0", "version": "1.0.0",
"license": "MIT", "license": "MIT",
"main": "dist/index.js", "main": "dist/index.js",

9
tsconfig.build.json Normal file
View file

@ -0,0 +1,9 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"sourceMap": false,
"removeComments": true,
"outDir": "dist"
},
"include": ["./cli/", ".d.ts"]
}

View file

@ -3,7 +3,7 @@
"resolveJsonModule": true, "resolveJsonModule": true,
"esModuleInterop": true, "esModuleInterop": true,
"declaration": true, "declaration": true,
"target": "ES2015", "target": "ES2018",
"module": "CommonJS", "module": "CommonJS",
"moduleResolution": "node", "moduleResolution": "node",
"sourceMap": true, "sourceMap": true,

3843
yarn.lock

File diff suppressed because it is too large Load diff