implementing the github engine for gh-page deployments
This commit is contained in:
parent
1f9426f799
commit
048904c000
33 changed files with 778 additions and 503 deletions
18
.d.ts
vendored
18
.d.ts
vendored
|
|
@ -49,3 +49,21 @@ type UploadStreamOptions = {
|
||||||
ContentType?: string;
|
ContentType?: string;
|
||||||
CacheControl?: string;
|
CacheControl?: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
type BaseDeploymentOptions = {
|
||||||
|
engine?: 'aws' | 'github';
|
||||||
|
debug?: boolean;
|
||||||
|
onPreDeploy?: () => Promise<void>;
|
||||||
|
onPostDeploy?: () => Promise<void>;
|
||||||
|
onShutdown?: () => Promise<void>;
|
||||||
|
build?: BuildOptions | boolean;
|
||||||
|
nextConfigDir?: string;
|
||||||
|
domain?: string | string[];
|
||||||
|
};
|
||||||
|
|
||||||
|
type BuildOptions = {
|
||||||
|
cwd?: string;
|
||||||
|
enabled?: boolean;
|
||||||
|
cmd: string;
|
||||||
|
args: string[];
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -10,3 +10,4 @@ CODE_OF_CONDUCT.md
|
||||||
.yarnignore
|
.yarnignore
|
||||||
src
|
src
|
||||||
tsconfig.build.json
|
tsconfig.build.json
|
||||||
|
examples
|
||||||
82
README.md
82
README.md
|
|
@ -1,28 +1,40 @@
|
||||||
# Next Deploy
|
# Next Deploy
|
||||||
|
|
||||||
Effortless deployment for Next.js apps. 🚀
|
Effortless deployment for Next.js apps 🚀
|
||||||
|
|
||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
||||||
- [Getting started](#Getting-started)
|
- [Getting Started](#Getting-Started)
|
||||||
- [Background](#Background)
|
- [Background](#Background)
|
||||||
- [Configuration](#Configuration)
|
- [Configuration](#Configuration)
|
||||||
|
- [AWS](#AWS)
|
||||||
|
- [GitHub](#GitHub)
|
||||||
- [Advanced Configuration](#Advanced-Configuration)
|
- [Advanced Configuration](#Advanced-Configuration)
|
||||||
- [Options](#Configuration-Options)
|
- [CLI](#CLI)
|
||||||
|
- [Configuration Options](#Configuration-Options)
|
||||||
|
- [Base Options](#Base-Options)
|
||||||
|
- [GitHub Options](#GitHub-Options)
|
||||||
|
- [AWS Options](#AWS-Options)
|
||||||
|
- [CI/CD](#CI/CD)
|
||||||
|
|
||||||
## Getting started
|
## Getting Started
|
||||||
|
|
||||||
[Make sure your environment is configured to deploy.](#Configuration)
|
Make sure your environment is [configured to deploy](#Configuration).
|
||||||
|
|
||||||
The one-liner: `npx next-deploy`
|
Run your deployment with a one-liner:
|
||||||
|
|
||||||
You can also install locally:
|
- `npx next-deploy`
|
||||||
`yarn add --dev next-deploy`
|
|
||||||
`yarn next-deploy`
|
Optionally you can also add and run `next deploy` from your Next.js app:
|
||||||
|
|
||||||
|
- `yarn add --dev next-deploy`
|
||||||
|
- `yarn next-deploy`
|
||||||
|
|
||||||
## Background
|
## Background
|
||||||
|
|
||||||
Next Deploy started as a fork of [serverless-next.js](#https://github.com/serverless-nextjs/serverless-next.js) which itself is an orchestrator of various [serverless-components](#https://github.com/serverless-components/).
|
Next Deploy was created to deploy web applications built using the wonderful [Next.js](https://nextjs.org/) framework. It allows teams to easily integrate with our supported engines (AWS, GitHub Pages) and keep the entirety of their code in source control; from frontend, to backend, to the deployment logic.
|
||||||
|
|
||||||
|
Next Deploy started as a fork of [serverless-next.js](https://github.com/serverless-nextjs/serverless-next.js) which itself is an orchestrator of various orphaned [serverless-components](https://github.com/serverless-components/). Next Deploy was created out of a need for a better, strongly typed codebase and an ability to provide more advanced functionality without the [influence of corporate backers](https://opencollective.com/goserverless#section-contributions).
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
|
|
@ -39,31 +51,30 @@ If your account is restricted, [ensure that you have enough permissions to deplo
|
||||||
|
|
||||||
### GitHub
|
### GitHub
|
||||||
|
|
||||||
TODO
|
No specific configuration is necessary. By default, your app will be built and exported to the `gh-pages` branch.
|
||||||
|
|
||||||
## Advanced Configuration
|
### Advanced Configuration
|
||||||
|
|
||||||
The deployment configuration is to be provided through `next-deploy.config.js`, which will be automatically created for you the first time you run `next-deploy`.
|
The deployment configuration is to be provided through `next-deploy.config.js`, which will be automatically created for you the first time you run `next-deploy`.
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
module.exports = {
|
module.exports = {
|
||||||
debug: false,
|
engine: 'aws',
|
||||||
onPreDeploy: () => console.log('⚡ Starting Deployment'),
|
debug: true,
|
||||||
};
|
};
|
||||||
```
|
```
|
||||||
|
|
||||||
A more advanced configuration that sets more [configurable options](#ConfigurationOptions):
|
A more advanced configuration that sets more [configurable options](#Configuration-Options):
|
||||||
|
|
||||||
```javascript
|
```javascript
|
||||||
module.exports = {
|
module.exports = {
|
||||||
engine: 'aws',
|
engine: 'aws',
|
||||||
onPreDeploy: () => console.log('⚡ Starting Deployment ⚡'),
|
|
||||||
onShutdown: () => console.log('⛔ Interrupted ⛔'),
|
onShutdown: () => console.log('⛔ Interrupted ⛔'),
|
||||||
onPostDeploy: () => console.log('🌟 Deployment Complete 🌟'),
|
onPostDeploy: () => console.log('🌟 Deployment Complete 🌟'),
|
||||||
debug: true,
|
debug: true,
|
||||||
|
|
||||||
bucketName: 'bucket-name',
|
bucketName: 'my-bucket-name',
|
||||||
description: 'lambda-description',
|
description: 'My new lambda description.',
|
||||||
name: 'lambda-name',
|
name: 'lambda-name',
|
||||||
domain: ['foobar', 'example.com'],
|
domain: ['foobar', 'example.com'],
|
||||||
};
|
};
|
||||||
|
|
@ -71,18 +82,51 @@ module.exports = {
|
||||||
|
|
||||||
Environment variables may be substituted from `process.env` to allow for more flexibility that one would need for CI/CD.
|
Environment variables may be substituted from `process.env` to allow for more flexibility that one would need for CI/CD.
|
||||||
|
|
||||||
|
## CLI
|
||||||
|
|
||||||
|
Next Deploy comes with a `next-deploy [argument]` CLI that you can run like `npx next-deploy` or `yarn next-deploy`.
|
||||||
|
|
||||||
|
There are currently 5 supported arguments:
|
||||||
|
|
||||||
|
**Default** (default): Runs **Build** followed by **Deploy**.
|
||||||
|
|
||||||
|
**Init**: Creates the base next-deploy.config.js configuration for your project.
|
||||||
|
|
||||||
|
**Build**: Build the application for deployment.
|
||||||
|
|
||||||
|
**Deploy**: Deploy the built application.
|
||||||
|
|
||||||
|
**Remove**: Remove, or at least attempt to remove, the deployed resources. Note that some resources (such as lambda@edge lambdas need to be cleaned up manually due to a timing constraint).
|
||||||
|
|
||||||
## Configuration Options
|
## Configuration Options
|
||||||
|
|
||||||
The next-deploy config varies by the provider (engine) that you're deploying to. All configuration options are optional and come with sensible defaults.
|
The next-deploy config varies by the provider (engine) that you're deploying to. All configuration options are optional and come with sensible defaults.
|
||||||
|
|
||||||
|
### Base Options
|
||||||
|
|
||||||
All engines support the basic options:
|
All engines support the basic options:
|
||||||
|
|
||||||
| Name | Type | Default | Description |
|
| Name | Type | Default | Description |
|
||||||
| :----------- | :-------------------- | :---------- | :------------------------------------------------------------------------------------------------------- |
|
| :------------ | :---------------------- | :---------- | :------------------------------------------------------------------------------------------------------- |
|
||||||
| engine | `"aws"\|"github"` | `"aws"` | The platform to deploy to. |
|
| engine | `"aws"\|"github"` | `"aws"` | The platform to deploy to. |
|
||||||
| debug | `boolean` | `false` | Print helpful messages to |
|
| debug | `boolean` | `false` | Print helpful messages to |
|
||||||
| onPreDeploy | `() => Promise<void>` | `undefined` | A callback that gets called before the deployment. |
|
| onPreDeploy | `() => Promise<void>` | `undefined` | A callback that gets called before the deployment. |
|
||||||
| onPostDeploy | `() => Promise<void>` | `undefined` | A callback that gets called after the deployment successfully finishes. |
|
| onPostDeploy | `() => Promise<void>` | `undefined` | A callback that gets called after the deployment successfully finishes. |
|
||||||
| onShutdown | `() => Promise<void>` | `undefined` | A callback that gets called after the deployment is shutdown by a INT/QUIT/TERM signal like from ctrl+c. |
|
| onShutdown | `() => Promise<void>` | `undefined` | A callback that gets called after the deployment is shutdown by a INT/QUIT/TERM signal like from ctrl+c. |
|
||||||
|
| build | `BuildOptions\|boolean` | `true` | Whether a new build should be run run or not. |
|
||||||
|
| nextConfigDir | `string` | `./` | The directory holding the `next.config.js`. |
|
||||||
|
| domain | `string\|string[]` | `null` | The domain to deploy to . |
|
||||||
|
|
||||||
|
### Github Options
|
||||||
|
|
||||||
|
| Name | Type | Default | Description |
|
||||||
|
| :------------- | :-------------------------------------------------------------- | :--------------------------------- | :--------------------------------------------------------------------------------------- |
|
||||||
|
| publishOptions | [`PublishOptions`](https://github.com/tschaub/gh-pages#options) | `{message: '...', dotfiles: true}` | The [git-hub page options](https://github.com/tschaub/gh-pages#options) to publish with. |
|
||||||
|
|
||||||
|
### AWS Options
|
||||||
|
|
||||||
|
TODO
|
||||||
|
|
||||||
|
## CI/CD
|
||||||
|
|
||||||
TODO
|
TODO
|
||||||
|
|
|
||||||
3
examples/github/README.md
Normal file
3
examples/github/README.md
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
Deployments to [GitHub Pages](#https://pages.github.com/) work strictly for static sites, but still possess most of the advantages of using Next.js such as automatic page pre-loading.
|
||||||
|
|
||||||
|
An up-to-date static-rendered implementation of https://www.nidratech.com and its deployment using Next Deploy can be found at: https://github.com/nidratech/nidratech.com
|
||||||
12
package.json
12
package.json
|
|
@ -1,7 +1,7 @@
|
||||||
{
|
{
|
||||||
"name": "next-deploy",
|
"name": "next-deploy",
|
||||||
"version": "0.1.0",
|
"version": "0.1.2",
|
||||||
"description": "Effortless deployment for Next.js apps. 🚀",
|
"description": "Effortless deployment for Next.js apps 🚀",
|
||||||
"author": "Nidratech Ltd. <egor@nidratech.com>",
|
"author": "Nidratech Ltd. <egor@nidratech.com>",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"next",
|
"next",
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
"github-pages"
|
"github-pages"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"dev": "lerna exec -- yarn build -w",
|
"dev": "lerna run --parallel build:watch",
|
||||||
"build": "lerna run build",
|
"build": "lerna run build",
|
||||||
"clean": "lerna run clean",
|
"clean": "lerna run clean",
|
||||||
"setup": "yarn && lerna exec -- yarn",
|
"setup": "yarn && lerna exec -- yarn",
|
||||||
|
|
@ -51,6 +51,7 @@
|
||||||
"execa": "^4.0.3",
|
"execa": "^4.0.3",
|
||||||
"figures": "^3.2.0",
|
"figures": "^3.2.0",
|
||||||
"fs-extra": "^9.0.1",
|
"fs-extra": "^9.0.1",
|
||||||
|
"gh-pages": "^3.1.0",
|
||||||
"globby": "^11.0.1",
|
"globby": "^11.0.1",
|
||||||
"klaw": "^3.0.0",
|
"klaw": "^3.0.0",
|
||||||
"klaw-sync": "^6.0.0",
|
"klaw-sync": "^6.0.0",
|
||||||
|
|
@ -72,13 +73,14 @@
|
||||||
"@types/aws-lambda": "^8.10.59",
|
"@types/aws-lambda": "^8.10.59",
|
||||||
"@types/execa": "^2.0.0",
|
"@types/execa": "^2.0.0",
|
||||||
"@types/fs-extra": "^9.0.1",
|
"@types/fs-extra": "^9.0.1",
|
||||||
|
"@types/gh-pages": "^3.0.0",
|
||||||
"@types/klaw": "^3.0.1",
|
"@types/klaw": "^3.0.1",
|
||||||
"@types/klaw-sync": "^6.0.0",
|
"@types/klaw-sync": "^6.0.0",
|
||||||
"@types/mime-types": "^2.1.0",
|
"@types/mime-types": "^2.1.0",
|
||||||
"@types/node": "^14.0.22",
|
"@types/node": "^14.0.22",
|
||||||
"@types/path-to-regexp": "^1.7.0",
|
"@types/path-to-regexp": "^1.7.0",
|
||||||
"@types/ramda": "^0.27.10",
|
"@types/ramda": "^0.27.11",
|
||||||
"@types/react": "^16.9.42",
|
"@types/react": "^16.9.43",
|
||||||
"@types/react-dom": "^16.9.8",
|
"@types/react-dom": "^16.9.8",
|
||||||
"@types/strip-ansi": "^5.2.1",
|
"@types/strip-ansi": "^5.2.1",
|
||||||
"@types/webpack": "^4.41.21",
|
"@types/webpack": "^4.41.21",
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "@next-deploy/aws-cloudfront",
|
"name": "@next-deploy/aws-cloudfront",
|
||||||
"version": "1.0.0",
|
"version": "0.0.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "serverless.js",
|
"main": "serverless.js",
|
||||||
"types": "dist/component.d.ts",
|
"types": "dist/component.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yarn clean && yarn compile",
|
"build": "yarn clean && yarn compile",
|
||||||
|
"build:watch": "yarn compile -w",
|
||||||
"clean": "rm -rf ./dist",
|
"clean": "rm -rf ./dist",
|
||||||
"compile": "tsc -p tsconfig.build.json"
|
"compile": "tsc -p tsconfig.build.json"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,7 @@ class CloudFrontComponent extends Component {
|
||||||
this.state = {};
|
this.state = {};
|
||||||
await this.save();
|
await this.save();
|
||||||
|
|
||||||
this.context.debug(`CloudFront distribution was successfully removed.`);
|
this.context.debug('CloudFront distribution was successfully removed.');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "@next-deploy/aws-component",
|
"name": "@next-deploy/aws-component",
|
||||||
"version": "1.0.0",
|
"version": "0.0.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "serverless.js",
|
"main": "serverless.js",
|
||||||
"types": "dist/component.d.ts",
|
"types": "dist/component.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yarn clean && yarn compile",
|
"build": "yarn clean && yarn compile",
|
||||||
|
"build:watch": "yarn compile -w",
|
||||||
"clean": "rm -rf ./dist",
|
"clean": "rm -rf ./dist",
|
||||||
"compile": "tsc -p tsconfig.build.json"
|
"compile": "tsc -p tsconfig.build.json"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -12,13 +12,7 @@ import {
|
||||||
} from '@next-deploy/aws-lambda-builder/types';
|
} from '@next-deploy/aws-lambda-builder/types';
|
||||||
import { PathPatternConfig } from '@next-deploy/aws-cloudfront/types';
|
import { PathPatternConfig } from '@next-deploy/aws-cloudfront/types';
|
||||||
import { Origin } from '@next-deploy/aws-cloudfront/types';
|
import { Origin } from '@next-deploy/aws-cloudfront/types';
|
||||||
import {
|
import { DeploymentResult, AwsComponentInputs, LambdaType, LambdaInput } from '../types';
|
||||||
DeploymentResult,
|
|
||||||
BuildOptions,
|
|
||||||
AwsComponentInputs,
|
|
||||||
LambdaType,
|
|
||||||
LambdaInput,
|
|
||||||
} from '../types';
|
|
||||||
|
|
||||||
export const BUILD_DIR = '.next-deploy-build';
|
export const BUILD_DIR = '.next-deploy-build';
|
||||||
export const DEFAULT_LAMBDA_CODE_DIR = `${BUILD_DIR}/default-lambda`;
|
export const DEFAULT_LAMBDA_CODE_DIR = `${BUILD_DIR}/default-lambda`;
|
||||||
|
|
|
||||||
12
packages/aws-component/types.d.ts
vendored
12
packages/aws-component/types.d.ts
vendored
|
|
@ -2,9 +2,7 @@ import { PublicDirectoryCache } from '@next-deploy/aws-s3/types';
|
||||||
import { CloudFrontInputs } from '@next-deploy/aws-cloudfront/types';
|
import { CloudFrontInputs } from '@next-deploy/aws-cloudfront/types';
|
||||||
import { DomainType } from '@next-deploy/aws-domain/types';
|
import { DomainType } from '@next-deploy/aws-domain/types';
|
||||||
|
|
||||||
type AwsComponentInputs = {
|
type AwsComponentInputs = BaseDeploymentOptions & {
|
||||||
build?: BuildOptions | boolean;
|
|
||||||
nextConfigDir?: string;
|
|
||||||
nextStaticDir?: string;
|
nextStaticDir?: string;
|
||||||
bucketName?: string;
|
bucketName?: string;
|
||||||
bucketRegion?: string;
|
bucketRegion?: string;
|
||||||
|
|
@ -15,18 +13,10 @@ type AwsComponentInputs = {
|
||||||
runtime?: string | { defaultLambda?: string; apiLambda?: string };
|
runtime?: string | { defaultLambda?: string; apiLambda?: string };
|
||||||
description?: string;
|
description?: string;
|
||||||
policy?: string;
|
policy?: string;
|
||||||
domain?: string | string[];
|
|
||||||
domainType?: DomainType;
|
domainType?: DomainType;
|
||||||
cloudfront?: CloudFrontInputs;
|
cloudfront?: CloudFrontInputs;
|
||||||
};
|
};
|
||||||
|
|
||||||
type BuildOptions = {
|
|
||||||
cwd?: string;
|
|
||||||
enabled?: boolean;
|
|
||||||
cmd: string;
|
|
||||||
args: string[];
|
|
||||||
};
|
|
||||||
|
|
||||||
type LambdaType = 'defaultLambda' | 'apiLambda';
|
type LambdaType = 'defaultLambda' | 'apiLambda';
|
||||||
|
|
||||||
type LambdaInput = {
|
type LambdaInput = {
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "@next-deploy/aws-domain",
|
"name": "@next-deploy/aws-domain",
|
||||||
"version": "1.0.0",
|
"version": "0.0.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "serverless.js",
|
"main": "serverless.js",
|
||||||
"types": "dist/component.d.ts",
|
"types": "dist/component.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yarn clean && yarn compile",
|
"build": "yarn clean && yarn compile",
|
||||||
|
"build:watch": "yarn compile -w",
|
||||||
"clean": "rm -rf ./dist",
|
"clean": "rm -rf ./dist",
|
||||||
"compile": "tsc -p tsconfig.build.json"
|
"compile": "tsc -p tsconfig.build.json"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "@next-deploy/aws-lambda-builder",
|
"name": "@next-deploy/aws-lambda-builder",
|
||||||
"version": "1.0.0",
|
"version": "0.0.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yarn clean && yarn compile",
|
"build": "yarn clean && yarn compile",
|
||||||
|
"build:watch": "yarn compile -w",
|
||||||
"clean": "rm -rf ./dist",
|
"clean": "rm -rf ./dist",
|
||||||
"compile": "tsc -p tsconfig.build.json"
|
"compile": "tsc -p tsconfig.build.json"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,349 +0,0 @@
|
||||||
import nodeFileTrace, { NodeFileTraceReasons } from '@zeit/node-file-trace';
|
|
||||||
import execa from 'execa';
|
|
||||||
import fse from 'fs-extra';
|
|
||||||
import path, { join } from 'path';
|
|
||||||
import { pathToRegexp } from 'path-to-regexp';
|
|
||||||
|
|
||||||
import getAllFiles from './lib/getAllFilesInDirectory';
|
|
||||||
import { getSortedRoutes } from './lib/sortedRoutes';
|
|
||||||
import {
|
|
||||||
BuildOptions,
|
|
||||||
OriginRequestDefaultHandlerManifest,
|
|
||||||
OriginRequestApiHandlerManifest,
|
|
||||||
} from '../types';
|
|
||||||
import expressifyDynamicRoute from './lib/expressifyDynamicRoute';
|
|
||||||
import createServerlessConfig from './lib/createServerlessConfig';
|
|
||||||
|
|
||||||
export const DEFAULT_LAMBDA_CODE_DIR = 'default-lambda';
|
|
||||||
export const API_LAMBDA_CODE_DIR = 'api-lambda';
|
|
||||||
|
|
||||||
const pathToPosix = (path: string): string => path.replace(/\\/g, '/');
|
|
||||||
const normalizeNodeModules = (path: string): string => path.substring(path.indexOf('node_modules'));
|
|
||||||
// Identify /[param]/ in route string
|
|
||||||
const isDynamicRoute = (route: string): boolean => /\/\[[^\/]+?\](?=\/|$)/.test(route);
|
|
||||||
const pathToRegexStr = (path: string): string =>
|
|
||||||
pathToRegexp(path)
|
|
||||||
.toString()
|
|
||||||
.replace(/\/(.*)\/\i/, '$1');
|
|
||||||
|
|
||||||
const defaultBuildOptions = {
|
|
||||||
args: [],
|
|
||||||
cwd: process.cwd(),
|
|
||||||
cmd: './node_modules/.bin/next',
|
|
||||||
};
|
|
||||||
|
|
||||||
class Builder {
|
|
||||||
nextConfigDir: string;
|
|
||||||
dotNextDir: string;
|
|
||||||
serverlessDir: string;
|
|
||||||
outputDir: string;
|
|
||||||
buildOptions: BuildOptions = defaultBuildOptions;
|
|
||||||
|
|
||||||
constructor(nextConfigDir: string, outputDir: string, buildOptions?: BuildOptions) {
|
|
||||||
this.nextConfigDir = path.resolve(nextConfigDir);
|
|
||||||
this.dotNextDir = path.join(this.nextConfigDir, '.next');
|
|
||||||
this.serverlessDir = path.join(this.dotNextDir, 'serverless');
|
|
||||||
this.outputDir = outputDir;
|
|
||||||
if (buildOptions) {
|
|
||||||
this.buildOptions = buildOptions;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async readPublicFiles(): Promise<string[]> {
|
|
||||||
const dirExists = await fse.pathExists(join(this.nextConfigDir, 'public'));
|
|
||||||
if (dirExists) {
|
|
||||||
return getAllFiles(join(this.nextConfigDir, 'public'))
|
|
||||||
.map((e) => e.replace(this.nextConfigDir, ''))
|
|
||||||
.map((e) => e.split(path.sep).slice(2).join('/'));
|
|
||||||
} else {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async readPagesManifest(): Promise<{ [key: string]: string }> {
|
|
||||||
const path = join(this.serverlessDir, 'pages-manifest.json');
|
|
||||||
const hasServerlessPageManifest = await fse.pathExists(path);
|
|
||||||
|
|
||||||
if (!hasServerlessPageManifest) {
|
|
||||||
return Promise.reject(
|
|
||||||
"pages-manifest not found. Check if `next.config.js` target is set to 'serverless'"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
const pagesManifest = await fse.readJSON(path);
|
|
||||||
const pagesManifestWithoutDynamicRoutes = Object.keys(pagesManifest).reduce(
|
|
||||||
(acc: { [key: string]: string }, route: string) => {
|
|
||||||
if (isDynamicRoute(route)) {
|
|
||||||
return acc;
|
|
||||||
}
|
|
||||||
|
|
||||||
acc[route] = pagesManifest[route];
|
|
||||||
return acc;
|
|
||||||
},
|
|
||||||
{}
|
|
||||||
);
|
|
||||||
|
|
||||||
const dynamicRoutedPages = Object.keys(pagesManifest).filter(isDynamicRoute);
|
|
||||||
const sortedDynamicRoutedPages = getSortedRoutes(dynamicRoutedPages);
|
|
||||||
const sortedPagesManifest = pagesManifestWithoutDynamicRoutes;
|
|
||||||
|
|
||||||
sortedDynamicRoutedPages.forEach((route) => {
|
|
||||||
sortedPagesManifest[route] = pagesManifest[route];
|
|
||||||
});
|
|
||||||
|
|
||||||
return sortedPagesManifest;
|
|
||||||
}
|
|
||||||
|
|
||||||
copyLambdaHandlerDependencies(
|
|
||||||
fileList: string[],
|
|
||||||
reasons: NodeFileTraceReasons,
|
|
||||||
handlerDirectory: string
|
|
||||||
): Promise<void>[] {
|
|
||||||
return (
|
|
||||||
fileList
|
|
||||||
// exclude "initial" files from lambda artifact. These are just the pages themselves which are copied over separately
|
|
||||||
.filter(
|
|
||||||
(file) => file !== 'package.json' && (!reasons[file] || reasons[file].type !== 'initial')
|
|
||||||
)
|
|
||||||
.map((filePath: string) => {
|
|
||||||
const resolvedFilePath = path.resolve(filePath);
|
|
||||||
const dst = normalizeNodeModules(path.relative(this.serverlessDir, resolvedFilePath));
|
|
||||||
return fse.copy(resolvedFilePath, join(this.outputDir, handlerDirectory, dst));
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
async buildDefaultLambda(buildManifest: OriginRequestDefaultHandlerManifest): Promise<void[]> {
|
|
||||||
const ignoreAppAndDocumentPages = (page: string): boolean => {
|
|
||||||
const basename = path.basename(page);
|
|
||||||
return basename !== '_app.js' && basename !== '_document.js';
|
|
||||||
};
|
|
||||||
|
|
||||||
const allSsrPages = [
|
|
||||||
...Object.values(buildManifest.pages.ssr.nonDynamic),
|
|
||||||
...Object.values(buildManifest.pages.ssr.dynamic).map((entry) => entry.file),
|
|
||||||
].filter(ignoreAppAndDocumentPages);
|
|
||||||
|
|
||||||
const ssrPages = Object.values(allSsrPages).map((pageFile) =>
|
|
||||||
path.join(this.serverlessDir, pageFile)
|
|
||||||
);
|
|
||||||
|
|
||||||
const { fileList, reasons } = await nodeFileTrace(ssrPages, {
|
|
||||||
base: process.cwd(),
|
|
||||||
});
|
|
||||||
|
|
||||||
const copyTraces = this.copyLambdaHandlerDependencies(
|
|
||||||
fileList,
|
|
||||||
reasons,
|
|
||||||
DEFAULT_LAMBDA_CODE_DIR
|
|
||||||
);
|
|
||||||
|
|
||||||
return Promise.all([
|
|
||||||
...copyTraces,
|
|
||||||
fse.copy(
|
|
||||||
require.resolve('@next-deploy/aws-lambda-builder/dist/default-handler.js'),
|
|
||||||
join(this.outputDir, DEFAULT_LAMBDA_CODE_DIR, 'index.js')
|
|
||||||
),
|
|
||||||
fse.copy(
|
|
||||||
require.resolve('@next-deploy/aws-lambda-builder/dist/compat.js'),
|
|
||||||
join(this.outputDir, DEFAULT_LAMBDA_CODE_DIR, 'compat.js')
|
|
||||||
),
|
|
||||||
fse.writeJson(join(this.outputDir, DEFAULT_LAMBDA_CODE_DIR, 'manifest.json'), buildManifest),
|
|
||||||
fse.copy(
|
|
||||||
join(this.serverlessDir, 'pages'),
|
|
||||||
join(this.outputDir, DEFAULT_LAMBDA_CODE_DIR, 'pages'),
|
|
||||||
{
|
|
||||||
filter: (file: string) => {
|
|
||||||
const isNotPrerenderedHTMLPage = path.extname(file) !== '.html';
|
|
||||||
const isNotStaticPropsJSONFile = path.extname(file) !== '.json';
|
|
||||||
const isNotApiPage = pathToPosix(file).indexOf('pages/api') === -1;
|
|
||||||
|
|
||||||
return isNotApiPage && isNotPrerenderedHTMLPage && isNotStaticPropsJSONFile;
|
|
||||||
},
|
|
||||||
}
|
|
||||||
),
|
|
||||||
fse.copy(
|
|
||||||
join(this.dotNextDir, 'prerender-manifest.json'),
|
|
||||||
join(this.outputDir, DEFAULT_LAMBDA_CODE_DIR, 'prerender-manifest.json')
|
|
||||||
),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
async buildApiLambda(apiBuildManifest: OriginRequestApiHandlerManifest): Promise<void[]> {
|
|
||||||
const allApiPages = [
|
|
||||||
...Object.values(apiBuildManifest.apis.nonDynamic),
|
|
||||||
...Object.values(apiBuildManifest.apis.dynamic).map((entry) => entry.file),
|
|
||||||
];
|
|
||||||
|
|
||||||
const apiPages = Object.values(allApiPages).map((pageFile) =>
|
|
||||||
path.join(this.serverlessDir, pageFile)
|
|
||||||
);
|
|
||||||
|
|
||||||
const { fileList, reasons } = await nodeFileTrace(apiPages, {
|
|
||||||
base: process.cwd(),
|
|
||||||
});
|
|
||||||
|
|
||||||
const copyTraces = this.copyLambdaHandlerDependencies(fileList, reasons, API_LAMBDA_CODE_DIR);
|
|
||||||
|
|
||||||
return Promise.all([
|
|
||||||
...copyTraces,
|
|
||||||
fse.copy(
|
|
||||||
require.resolve('@next-deploy/aws-lambda-builder/dist/api-handler.js'),
|
|
||||||
join(this.outputDir, API_LAMBDA_CODE_DIR, 'index.js')
|
|
||||||
),
|
|
||||||
fse.copy(
|
|
||||||
require.resolve('@next-deploy/aws-lambda-builder/dist/compat.js'),
|
|
||||||
join(this.outputDir, API_LAMBDA_CODE_DIR, 'compat.js')
|
|
||||||
),
|
|
||||||
fse.copy(
|
|
||||||
join(this.serverlessDir, 'pages/api'),
|
|
||||||
join(this.outputDir, API_LAMBDA_CODE_DIR, 'pages/api')
|
|
||||||
),
|
|
||||||
fse.writeJson(join(this.outputDir, API_LAMBDA_CODE_DIR, 'manifest.json'), apiBuildManifest),
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
async prepareBuildManifests(): Promise<{
|
|
||||||
defaultBuildManifest: OriginRequestDefaultHandlerManifest;
|
|
||||||
apiBuildManifest: OriginRequestApiHandlerManifest;
|
|
||||||
}> {
|
|
||||||
const pagesManifest = await this.readPagesManifest();
|
|
||||||
const buildId = await fse.readFile(path.join(this.dotNextDir, 'BUILD_ID'), 'utf-8');
|
|
||||||
const defaultBuildManifest: OriginRequestDefaultHandlerManifest = {
|
|
||||||
buildId,
|
|
||||||
pages: {
|
|
||||||
ssr: {
|
|
||||||
dynamic: {},
|
|
||||||
nonDynamic: {},
|
|
||||||
},
|
|
||||||
html: {
|
|
||||||
dynamic: {},
|
|
||||||
nonDynamic: {},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
publicFiles: {},
|
|
||||||
};
|
|
||||||
const apiBuildManifest: OriginRequestApiHandlerManifest = {
|
|
||||||
apis: {
|
|
||||||
dynamic: {},
|
|
||||||
nonDynamic: {},
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
const ssrPages = defaultBuildManifest.pages.ssr;
|
|
||||||
const htmlPages = defaultBuildManifest.pages.html;
|
|
||||||
const apiPages = apiBuildManifest.apis;
|
|
||||||
|
|
||||||
const isHtmlPage = (path: string): boolean => path.endsWith('.html');
|
|
||||||
const isApiPage = (path: string): boolean => path.startsWith('pages/api');
|
|
||||||
|
|
||||||
Object.entries(pagesManifest).forEach(([route, pageFile]) => {
|
|
||||||
const dynamicRoute = isDynamicRoute(route);
|
|
||||||
const expressRoute = dynamicRoute ? expressifyDynamicRoute(route) : null;
|
|
||||||
|
|
||||||
if (isHtmlPage(pageFile)) {
|
|
||||||
if (dynamicRoute) {
|
|
||||||
const route = expressRoute as string;
|
|
||||||
htmlPages.dynamic[route] = {
|
|
||||||
file: pageFile,
|
|
||||||
regex: pathToRegexStr(route),
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
htmlPages.nonDynamic[route] = pageFile;
|
|
||||||
}
|
|
||||||
} else if (isApiPage(pageFile)) {
|
|
||||||
if (dynamicRoute) {
|
|
||||||
const route = expressRoute as string;
|
|
||||||
apiPages.dynamic[route] = {
|
|
||||||
file: pageFile,
|
|
||||||
regex: pathToRegexStr(route),
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
apiPages.nonDynamic[route] = pageFile;
|
|
||||||
}
|
|
||||||
} else if (dynamicRoute) {
|
|
||||||
const route = expressRoute as string;
|
|
||||||
ssrPages.dynamic[route] = {
|
|
||||||
file: pageFile,
|
|
||||||
regex: pathToRegexStr(route),
|
|
||||||
};
|
|
||||||
} else {
|
|
||||||
ssrPages.nonDynamic[route] = pageFile;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const publicFiles = await this.readPublicFiles();
|
|
||||||
|
|
||||||
publicFiles.forEach((pf) => (defaultBuildManifest.publicFiles[`/${pf}`] = pf));
|
|
||||||
|
|
||||||
return {
|
|
||||||
defaultBuildManifest,
|
|
||||||
apiBuildManifest,
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
async cleanupDotNext(): Promise<void> {
|
|
||||||
const exists = await fse.pathExists(this.dotNextDir);
|
|
||||||
|
|
||||||
if (exists) {
|
|
||||||
const fileItems = await fse.readdir(this.dotNextDir);
|
|
||||||
|
|
||||||
await Promise.all(
|
|
||||||
fileItems
|
|
||||||
.filter(
|
|
||||||
(fileItem) => fileItem !== 'cache' // avoid deleting the cache folder as that would lead to slow builds!
|
|
||||||
)
|
|
||||||
.map((fileItem) => fse.remove(join(this.dotNextDir, fileItem)))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async build(debug?: (message: string) => void): Promise<void> {
|
|
||||||
const { cmd, args, cwd } = Object.assign(defaultBuildOptions, this.buildOptions);
|
|
||||||
|
|
||||||
await this.cleanupDotNext();
|
|
||||||
|
|
||||||
await fse.emptyDir(join(this.outputDir, DEFAULT_LAMBDA_CODE_DIR));
|
|
||||||
await fse.emptyDir(join(this.outputDir, API_LAMBDA_CODE_DIR));
|
|
||||||
|
|
||||||
const { restoreUserConfig } = await createServerlessConfig(cwd, path.join(this.nextConfigDir));
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (debug) {
|
|
||||||
const { stdout: nextVersion } = await execa(cmd, ['--version'], {
|
|
||||||
cwd,
|
|
||||||
});
|
|
||||||
|
|
||||||
debug(`Starting a new build with ${nextVersion}`);
|
|
||||||
|
|
||||||
console.log();
|
|
||||||
}
|
|
||||||
|
|
||||||
const subprocess = execa(cmd, args, {
|
|
||||||
cwd,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (debug && subprocess.stdout) {
|
|
||||||
subprocess.stdout.pipe(process.stdout);
|
|
||||||
}
|
|
||||||
|
|
||||||
await subprocess;
|
|
||||||
} finally {
|
|
||||||
await restoreUserConfig();
|
|
||||||
}
|
|
||||||
|
|
||||||
const { defaultBuildManifest, apiBuildManifest } = await this.prepareBuildManifests();
|
|
||||||
|
|
||||||
await this.buildDefaultLambda(defaultBuildManifest);
|
|
||||||
|
|
||||||
const hasAPIPages =
|
|
||||||
Object.keys(apiBuildManifest.apis.nonDynamic).length > 0 ||
|
|
||||||
Object.keys(apiBuildManifest.apis.dynamic).length > 0;
|
|
||||||
|
|
||||||
if (hasAPIPages) {
|
|
||||||
await this.buildApiLambda(apiBuildManifest);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default Builder;
|
|
||||||
|
|
@ -135,7 +135,7 @@ const handler = ({
|
||||||
} as CloudFrontResultResponse;
|
} as CloudFrontResultResponse;
|
||||||
|
|
||||||
const newStream = new Stream.Readable();
|
const newStream = new Stream.Readable();
|
||||||
const req = Object.assign(newStream, IncomingMessage.prototype) as IncomingMessage;
|
const req = { ...newStream, ...IncomingMessage.prototype } as IncomingMessage;
|
||||||
req.url = request.uri;
|
req.url = request.uri;
|
||||||
req.method = request.method;
|
req.method = request.method;
|
||||||
req.rawHeaders = [];
|
req.rawHeaders = [];
|
||||||
|
|
@ -179,7 +179,7 @@ const handler = ({
|
||||||
response.status = status.toString();
|
response.status = status.toString();
|
||||||
|
|
||||||
if (headers) {
|
if (headers) {
|
||||||
res.headers = Object.assign(res.headers, headers);
|
res.headers = { ...res.headers, ...headers };
|
||||||
}
|
}
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,354 @@
|
||||||
import Builder from './builder';
|
import nodeFileTrace, { NodeFileTraceReasons } from '@zeit/node-file-trace';
|
||||||
|
import execa from 'execa';
|
||||||
|
import {
|
||||||
|
emptyDir,
|
||||||
|
pathExists,
|
||||||
|
readJSON,
|
||||||
|
copy,
|
||||||
|
writeJson,
|
||||||
|
remove,
|
||||||
|
readdir,
|
||||||
|
readFile,
|
||||||
|
} from 'fs-extra';
|
||||||
|
import { join, resolve, sep, extname, relative, basename } from 'path';
|
||||||
|
import { pathToRegexp } from 'path-to-regexp';
|
||||||
|
|
||||||
|
import getAllFiles from './lib/getAllFilesInDirectory';
|
||||||
|
import { getSortedRoutes } from './lib/sortedRoutes';
|
||||||
|
import { OriginRequestDefaultHandlerManifest, OriginRequestApiHandlerManifest } from '../types';
|
||||||
|
import expressifyDynamicRoute from './lib/expressifyDynamicRoute';
|
||||||
|
import createServerlessConfig from './lib/createServerlessConfig';
|
||||||
|
|
||||||
|
export const DEFAULT_LAMBDA_CODE_DIR = 'default-lambda';
|
||||||
|
export const API_LAMBDA_CODE_DIR = 'api-lambda';
|
||||||
|
|
||||||
|
const pathToPosix = (path: string): string => path.replace(/\\/g, '/');
|
||||||
|
const normalizeNodeModules = (path: string): string => path.substring(path.indexOf('node_modules'));
|
||||||
|
// Identify /[param]/ in route string
|
||||||
|
const isDynamicRoute = (route: string): boolean => /\/\[[^\/]+?\](?=\/|$)/.test(route);
|
||||||
|
const pathToRegexStr = (path: string): string =>
|
||||||
|
pathToRegexp(path)
|
||||||
|
.toString()
|
||||||
|
.replace(/\/(.*)\/\i/, '$1');
|
||||||
|
|
||||||
|
const defaultBuildOptions = {
|
||||||
|
args: [],
|
||||||
|
cwd: process.cwd(),
|
||||||
|
cmd: './node_modules/.bin/next',
|
||||||
|
};
|
||||||
|
|
||||||
|
class Builder {
|
||||||
|
nextConfigDir: string;
|
||||||
|
dotNextDir: string;
|
||||||
|
serverlessDir: string;
|
||||||
|
outputDir: string;
|
||||||
|
buildOptions: BuildOptions = defaultBuildOptions;
|
||||||
|
|
||||||
|
constructor(nextConfigDir: string, outputDir: string, buildOptions?: BuildOptions) {
|
||||||
|
this.nextConfigDir = resolve(nextConfigDir);
|
||||||
|
this.dotNextDir = join(this.nextConfigDir, '.next');
|
||||||
|
this.serverlessDir = join(this.dotNextDir, 'serverless');
|
||||||
|
this.outputDir = outputDir;
|
||||||
|
if (buildOptions) {
|
||||||
|
this.buildOptions = buildOptions;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async readPublicFiles(): Promise<string[]> {
|
||||||
|
const dirExists = await pathExists(join(this.nextConfigDir, 'public'));
|
||||||
|
if (dirExists) {
|
||||||
|
return getAllFiles(join(this.nextConfigDir, 'public'))
|
||||||
|
.map((e) => e.replace(this.nextConfigDir, ''))
|
||||||
|
.map((e) => e.split(sep).slice(2).join('/'));
|
||||||
|
} else {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async readPagesManifest(): Promise<{ [key: string]: string }> {
|
||||||
|
const path = join(this.serverlessDir, 'pages-manifest.json');
|
||||||
|
const hasServerlessPageManifest = await pathExists(path);
|
||||||
|
|
||||||
|
if (!hasServerlessPageManifest) {
|
||||||
|
return Promise.reject(
|
||||||
|
"pages-manifest not found. Check if `next.config.js` target is set to 'serverless'"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const pagesManifest = await readJSON(path);
|
||||||
|
const pagesManifestWithoutDynamicRoutes = Object.keys(pagesManifest).reduce(
|
||||||
|
(acc: { [key: string]: string }, route: string) => {
|
||||||
|
if (isDynamicRoute(route)) {
|
||||||
|
return acc;
|
||||||
|
}
|
||||||
|
|
||||||
|
acc[route] = pagesManifest[route];
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
|
||||||
|
const dynamicRoutedPages = Object.keys(pagesManifest).filter(isDynamicRoute);
|
||||||
|
const sortedDynamicRoutedPages = getSortedRoutes(dynamicRoutedPages);
|
||||||
|
const sortedPagesManifest = pagesManifestWithoutDynamicRoutes;
|
||||||
|
|
||||||
|
sortedDynamicRoutedPages.forEach((route) => {
|
||||||
|
sortedPagesManifest[route] = pagesManifest[route];
|
||||||
|
});
|
||||||
|
|
||||||
|
return sortedPagesManifest;
|
||||||
|
}
|
||||||
|
|
||||||
|
copyLambdaHandlerDependencies(
|
||||||
|
fileList: string[],
|
||||||
|
reasons: NodeFileTraceReasons,
|
||||||
|
handlerDirectory: string
|
||||||
|
): Promise<void>[] {
|
||||||
|
return (
|
||||||
|
fileList
|
||||||
|
// exclude "initial" files from lambda artifact. These are just the pages themselves which are copied over separately
|
||||||
|
.filter(
|
||||||
|
(file) => file !== 'package.json' && (!reasons[file] || reasons[file].type !== 'initial')
|
||||||
|
)
|
||||||
|
.map((filePath: string) => {
|
||||||
|
const resolvedFilePath = resolve(filePath);
|
||||||
|
const dst = normalizeNodeModules(relative(this.serverlessDir, resolvedFilePath));
|
||||||
|
return copy(resolvedFilePath, join(this.outputDir, handlerDirectory, dst));
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
async buildDefaultLambda(buildManifest: OriginRequestDefaultHandlerManifest): Promise<void[]> {
|
||||||
|
const ignoreAppAndDocumentPages = (page: string): boolean => {
|
||||||
|
const pageBasename = basename(page);
|
||||||
|
return pageBasename !== '_app.js' && pageBasename !== '_document.js';
|
||||||
|
};
|
||||||
|
|
||||||
|
const allSsrPages = [
|
||||||
|
...Object.values(buildManifest.pages.ssr.nonDynamic),
|
||||||
|
...Object.values(buildManifest.pages.ssr.dynamic).map((entry) => entry.file),
|
||||||
|
].filter(ignoreAppAndDocumentPages);
|
||||||
|
|
||||||
|
const ssrPages = Object.values(allSsrPages).map((pageFile) =>
|
||||||
|
join(this.serverlessDir, pageFile)
|
||||||
|
);
|
||||||
|
|
||||||
|
const { fileList, reasons } = await nodeFileTrace(ssrPages, {
|
||||||
|
base: process.cwd(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const copyTraces = this.copyLambdaHandlerDependencies(
|
||||||
|
fileList,
|
||||||
|
reasons,
|
||||||
|
DEFAULT_LAMBDA_CODE_DIR
|
||||||
|
);
|
||||||
|
|
||||||
|
return Promise.all([
|
||||||
|
...copyTraces,
|
||||||
|
copy(
|
||||||
|
require.resolve('@next-deploy/aws-lambda-builder/dist/default-handler.js'),
|
||||||
|
join(this.outputDir, DEFAULT_LAMBDA_CODE_DIR, 'index.js')
|
||||||
|
),
|
||||||
|
copy(
|
||||||
|
require.resolve('@next-deploy/aws-lambda-builder/dist/compat.js'),
|
||||||
|
join(this.outputDir, DEFAULT_LAMBDA_CODE_DIR, 'compat.js')
|
||||||
|
),
|
||||||
|
writeJson(join(this.outputDir, DEFAULT_LAMBDA_CODE_DIR, 'manifest.json'), buildManifest),
|
||||||
|
copy(
|
||||||
|
join(this.serverlessDir, 'pages'),
|
||||||
|
join(this.outputDir, DEFAULT_LAMBDA_CODE_DIR, 'pages'),
|
||||||
|
{
|
||||||
|
filter: (file: string) => {
|
||||||
|
const isNotPrerenderedHTMLPage = extname(file) !== '.html';
|
||||||
|
const isNotStaticPropsJSONFile = extname(file) !== '.json';
|
||||||
|
const isNotApiPage = pathToPosix(file).indexOf('pages/api') === -1;
|
||||||
|
|
||||||
|
return isNotApiPage && isNotPrerenderedHTMLPage && isNotStaticPropsJSONFile;
|
||||||
|
},
|
||||||
|
}
|
||||||
|
),
|
||||||
|
copy(
|
||||||
|
join(this.dotNextDir, 'prerender-manifest.json'),
|
||||||
|
join(this.outputDir, DEFAULT_LAMBDA_CODE_DIR, 'prerender-manifest.json')
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
async buildApiLambda(apiBuildManifest: OriginRequestApiHandlerManifest): Promise<void[]> {
|
||||||
|
const allApiPages = [
|
||||||
|
...Object.values(apiBuildManifest.apis.nonDynamic),
|
||||||
|
...Object.values(apiBuildManifest.apis.dynamic).map((entry) => entry.file),
|
||||||
|
];
|
||||||
|
|
||||||
|
const apiPages = Object.values(allApiPages).map((pageFile) =>
|
||||||
|
join(this.serverlessDir, pageFile)
|
||||||
|
);
|
||||||
|
|
||||||
|
const { fileList, reasons } = await nodeFileTrace(apiPages, {
|
||||||
|
base: process.cwd(),
|
||||||
|
});
|
||||||
|
|
||||||
|
const copyTraces = this.copyLambdaHandlerDependencies(fileList, reasons, API_LAMBDA_CODE_DIR);
|
||||||
|
|
||||||
|
return Promise.all([
|
||||||
|
...copyTraces,
|
||||||
|
copy(
|
||||||
|
require.resolve('@next-deploy/aws-lambda-builder/dist/api-handler.js'),
|
||||||
|
join(this.outputDir, API_LAMBDA_CODE_DIR, 'index.js')
|
||||||
|
),
|
||||||
|
copy(
|
||||||
|
require.resolve('@next-deploy/aws-lambda-builder/dist/compat.js'),
|
||||||
|
join(this.outputDir, API_LAMBDA_CODE_DIR, 'compat.js')
|
||||||
|
),
|
||||||
|
copy(
|
||||||
|
join(this.serverlessDir, 'pages/api'),
|
||||||
|
join(this.outputDir, API_LAMBDA_CODE_DIR, 'pages/api')
|
||||||
|
),
|
||||||
|
writeJson(join(this.outputDir, API_LAMBDA_CODE_DIR, 'manifest.json'), apiBuildManifest),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
async prepareBuildManifests(): Promise<{
|
||||||
|
defaultBuildManifest: OriginRequestDefaultHandlerManifest;
|
||||||
|
apiBuildManifest: OriginRequestApiHandlerManifest;
|
||||||
|
}> {
|
||||||
|
const pagesManifest = await this.readPagesManifest();
|
||||||
|
const buildId = await readFile(join(this.dotNextDir, 'BUILD_ID'), 'utf-8');
|
||||||
|
const defaultBuildManifest: OriginRequestDefaultHandlerManifest = {
|
||||||
|
buildId,
|
||||||
|
pages: {
|
||||||
|
ssr: {
|
||||||
|
dynamic: {},
|
||||||
|
nonDynamic: {},
|
||||||
|
},
|
||||||
|
html: {
|
||||||
|
dynamic: {},
|
||||||
|
nonDynamic: {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
publicFiles: {},
|
||||||
|
};
|
||||||
|
const apiBuildManifest: OriginRequestApiHandlerManifest = {
|
||||||
|
apis: {
|
||||||
|
dynamic: {},
|
||||||
|
nonDynamic: {},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
const ssrPages = defaultBuildManifest.pages.ssr;
|
||||||
|
const htmlPages = defaultBuildManifest.pages.html;
|
||||||
|
const apiPages = apiBuildManifest.apis;
|
||||||
|
|
||||||
|
const isHtmlPage = (path: string): boolean => path.endsWith('.html');
|
||||||
|
const isApiPage = (path: string): boolean => path.startsWith('pages/api');
|
||||||
|
|
||||||
|
Object.entries(pagesManifest).forEach(([route, pageFile]) => {
|
||||||
|
const dynamicRoute = isDynamicRoute(route);
|
||||||
|
const expressRoute = dynamicRoute ? expressifyDynamicRoute(route) : null;
|
||||||
|
|
||||||
|
if (isHtmlPage(pageFile)) {
|
||||||
|
if (dynamicRoute) {
|
||||||
|
const route = expressRoute as string;
|
||||||
|
htmlPages.dynamic[route] = {
|
||||||
|
file: pageFile,
|
||||||
|
regex: pathToRegexStr(route),
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
htmlPages.nonDynamic[route] = pageFile;
|
||||||
|
}
|
||||||
|
} else if (isApiPage(pageFile)) {
|
||||||
|
if (dynamicRoute) {
|
||||||
|
const route = expressRoute as string;
|
||||||
|
apiPages.dynamic[route] = {
|
||||||
|
file: pageFile,
|
||||||
|
regex: pathToRegexStr(route),
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
apiPages.nonDynamic[route] = pageFile;
|
||||||
|
}
|
||||||
|
} else if (dynamicRoute) {
|
||||||
|
const route = expressRoute as string;
|
||||||
|
ssrPages.dynamic[route] = {
|
||||||
|
file: pageFile,
|
||||||
|
regex: pathToRegexStr(route),
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
ssrPages.nonDynamic[route] = pageFile;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const publicFiles = await this.readPublicFiles();
|
||||||
|
|
||||||
|
publicFiles.forEach((pf) => (defaultBuildManifest.publicFiles[`/${pf}`] = pf));
|
||||||
|
|
||||||
|
return {
|
||||||
|
defaultBuildManifest,
|
||||||
|
apiBuildManifest,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
async cleanupDotNext(): Promise<void> {
|
||||||
|
const exists = await pathExists(this.dotNextDir);
|
||||||
|
|
||||||
|
if (exists) {
|
||||||
|
const fileItems = await readdir(this.dotNextDir);
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
fileItems
|
||||||
|
.filter(
|
||||||
|
(fileItem) => fileItem !== 'cache' // avoid deleting the cache folder as that would lead to slow builds!
|
||||||
|
)
|
||||||
|
.map((fileItem) => remove(join(this.dotNextDir, fileItem)))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async build(debug?: (message: string) => void): Promise<void> {
|
||||||
|
const { cmd, args, cwd } = { ...defaultBuildOptions, ...this.buildOptions };
|
||||||
|
|
||||||
|
await this.cleanupDotNext();
|
||||||
|
|
||||||
|
await emptyDir(join(this.outputDir, DEFAULT_LAMBDA_CODE_DIR));
|
||||||
|
await emptyDir(join(this.outputDir, API_LAMBDA_CODE_DIR));
|
||||||
|
|
||||||
|
const { restoreUserConfig } = await createServerlessConfig(cwd, join(this.nextConfigDir));
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (debug) {
|
||||||
|
const { stdout: nextVersion } = await execa(cmd, ['--version'], {
|
||||||
|
cwd,
|
||||||
|
});
|
||||||
|
|
||||||
|
debug(`Starting a new build with ${nextVersion}`);
|
||||||
|
|
||||||
|
console.log();
|
||||||
|
}
|
||||||
|
|
||||||
|
const subprocess = execa(cmd, args, {
|
||||||
|
cwd,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (debug && subprocess.stdout) {
|
||||||
|
subprocess.stdout.pipe(process.stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
await subprocess;
|
||||||
|
} finally {
|
||||||
|
await restoreUserConfig();
|
||||||
|
}
|
||||||
|
|
||||||
|
const { defaultBuildManifest, apiBuildManifest } = await this.prepareBuildManifests();
|
||||||
|
|
||||||
|
await this.buildDefaultLambda(defaultBuildManifest);
|
||||||
|
|
||||||
|
const hasAPIPages =
|
||||||
|
Object.keys(apiBuildManifest.apis.nonDynamic).length > 0 ||
|
||||||
|
Object.keys(apiBuildManifest.apis.dynamic).length > 0;
|
||||||
|
|
||||||
|
if (hasAPIPages) {
|
||||||
|
await this.buildApiLambda(apiBuildManifest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export default Builder;
|
export default Builder;
|
||||||
|
|
|
||||||
|
|
@ -5,5 +5,5 @@
|
||||||
"removeComments": true,
|
"removeComments": true,
|
||||||
"outDir": "dist"
|
"outDir": "dist"
|
||||||
},
|
},
|
||||||
"include": ["./src/"]
|
"include": ["./src/", "../../.d.ts"]
|
||||||
}
|
}
|
||||||
|
|
|
||||||
6
packages/aws-lambda-builder/types.d.ts
vendored
6
packages/aws-lambda-builder/types.d.ts
vendored
|
|
@ -46,12 +46,6 @@ type OriginRequestEvent = {
|
||||||
Records: [{ cf: { request: CloudFrontRequest } }];
|
Records: [{ cf: { request: CloudFrontRequest } }];
|
||||||
};
|
};
|
||||||
|
|
||||||
type BuildOptions = {
|
|
||||||
args?: string[];
|
|
||||||
cwd?: string;
|
|
||||||
cmd?: string;
|
|
||||||
};
|
|
||||||
|
|
||||||
type CreateServerlessConfigResult = {
|
type CreateServerlessConfigResult = {
|
||||||
restoreUserConfig: () => Promise<void>;
|
restoreUserConfig: () => Promise<void>;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,15 +1,17 @@
|
||||||
{
|
{
|
||||||
"name": "@next-deploy/aws-lambda",
|
"name": "@next-deploy/aws-lambda",
|
||||||
"version": "1.0.0",
|
"version": "0.0.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "serverless.js",
|
"main": "serverless.js",
|
||||||
"types": "dist/component.d.ts",
|
"types": "dist/component.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yarn clean && yarn compile",
|
"build": "yarn clean && yarn compile",
|
||||||
|
"build:watch": "yarn compile -w",
|
||||||
"clean": "rm -rf ./dist",
|
"clean": "rm -rf ./dist",
|
||||||
"compile": "tsc -p tsconfig.build.json"
|
"compile": "tsc -p tsconfig.build.json"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@next-deploy/aws-s3": "link:../aws-s3",
|
||||||
"typescript": "^3.9.6"
|
"typescript": "^3.9.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,10 @@
|
||||||
# yarn lockfile v1
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
|
"@next-deploy/aws-s3@link:../aws-s3":
|
||||||
|
version "0.0.0"
|
||||||
|
uid ""
|
||||||
|
|
||||||
typescript@^3.9.6:
|
typescript@^3.9.6:
|
||||||
version "3.9.6"
|
version "3.9.6"
|
||||||
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.6.tgz#8f3e0198a34c3ae17091b35571d3afd31999365a"
|
resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.9.6.tgz#8f3e0198a34c3ae17091b35571d3afd31999365a"
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "@next-deploy/aws-s3",
|
"name": "@next-deploy/aws-s3",
|
||||||
"version": "1.0.0",
|
"version": "0.0.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "serverless.js",
|
"main": "serverless.js",
|
||||||
"types": "dist/component.d.ts",
|
"types": "dist/component.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yarn clean && yarn compile",
|
"build": "yarn clean && yarn compile",
|
||||||
|
"build:watch": "yarn compile -w",
|
||||||
"clean": "rm -rf ./dist",
|
"clean": "rm -rf ./dist",
|
||||||
"compile": "tsc -p tsconfig.build.json"
|
"compile": "tsc -p tsconfig.build.json"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,18 @@
|
||||||
{
|
{
|
||||||
"name": "@next-deploy/cli",
|
"name": "@next-deploy/cli",
|
||||||
"version": "1.0.0",
|
"version": "0.0.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "dist/index.js",
|
"main": "dist/index.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/index.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yarn clean && yarn compile",
|
"build": "yarn clean && yarn compile",
|
||||||
|
"build:watch": "yarn compile -w",
|
||||||
"clean": "rm -rf ./dist",
|
"clean": "rm -rf ./dist",
|
||||||
"compile": "tsc -p tsconfig.build.json"
|
"compile": "tsc -p tsconfig.build.json"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@next-deploy/aws-component": "link:../aws-component",
|
"@next-deploy/aws-component": "link:../aws-component",
|
||||||
|
"@next-deploy/github": "link:../github",
|
||||||
"typescript": "^3.9.6"
|
"typescript": "^3.9.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -11,9 +11,10 @@ export const SUPPORTED_ENGINES = [
|
||||||
export const DEFAULT_ENGINE = 'aws';
|
export const DEFAULT_ENGINE = 'aws';
|
||||||
export const DEPLOY_CONFIG_NAME = 'next-deploy.config.js';
|
export const DEPLOY_CONFIG_NAME = 'next-deploy.config.js';
|
||||||
export const METHOD_NAME_MAP = [
|
export const METHOD_NAME_MAP = [
|
||||||
{ name: 'default', action: 'Deploying' },
|
{ name: 'init' },
|
||||||
{ name: 'build', action: 'Building' },
|
{ name: 'default', action: 'Deploying', actionNoun: 'Deployment' },
|
||||||
{ name: 'deploy', action: 'Deploying' },
|
{ name: 'build', action: 'Building', actionNoun: 'Build' },
|
||||||
{ name: 'remove', action: 'Removing' },
|
{ name: 'deploy', action: 'Deploying', actionNoun: 'Deployment' },
|
||||||
|
{ name: 'remove', action: 'Removing', actionNoun: 'Removal' },
|
||||||
];
|
];
|
||||||
export const STATE_ROOT = '.next-deploy';
|
export const STATE_ROOT = '.next-deploy';
|
||||||
|
|
|
||||||
|
|
@ -192,7 +192,7 @@ class Context {
|
||||||
let content = '';
|
let content = '';
|
||||||
|
|
||||||
if (this.metrics.useTimer) {
|
if (this.metrics.useTimer) {
|
||||||
content += `${grey(this.metrics.seconds + 's')}`;
|
content += `${grey(`${this.metrics.seconds}s`)}`;
|
||||||
content += ` ${blue(figures.pointerSmall)}`;
|
content += ` ${blue(figures.pointerSmall)}`;
|
||||||
}
|
}
|
||||||
content += ` ${message}`;
|
content += ` ${message}`;
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
|
import chalk from 'chalk';
|
||||||
|
|
||||||
import { BaseDeploymentOptions } from '../types';
|
|
||||||
import { DEFAULT_ENGINE, SUPPORTED_ENGINES, METHOD_NAME_MAP, STATE_ROOT } from './config';
|
import { DEFAULT_ENGINE, SUPPORTED_ENGINES, METHOD_NAME_MAP, STATE_ROOT } from './config';
|
||||||
import Context from './context';
|
import Context from './context';
|
||||||
|
import { createBaseConfig } from './utils';
|
||||||
|
|
||||||
const deploy = async (deployConfigPath: string, methodName = 'default'): Promise<void> => {
|
const deploy = async (deployConfigPath: string, methodName = 'default'): Promise<void> => {
|
||||||
const {
|
const {
|
||||||
|
|
@ -14,26 +15,37 @@ const deploy = async (deployConfigPath: string, methodName = 'default'): Promise
|
||||||
...componentOptions
|
...componentOptions
|
||||||
}: BaseDeploymentOptions = await import(deployConfigPath);
|
}: BaseDeploymentOptions = await import(deployConfigPath);
|
||||||
const engineIndex = SUPPORTED_ENGINES.findIndex(({ type }) => type === engine);
|
const engineIndex = SUPPORTED_ENGINES.findIndex(({ type }) => type === engine);
|
||||||
|
const isInit = methodName === 'init';
|
||||||
|
|
||||||
onShutdown && handleShutDown(onShutdown);
|
onShutdown && handleShutDown(onShutdown);
|
||||||
|
|
||||||
if (engineIndex === -1) {
|
if (engineIndex === -1) {
|
||||||
throw new Error(
|
console.error(
|
||||||
`Engine ${engine} is unsupported. Pick one of: ${SUPPORTED_ENGINES.map(
|
`❌ ${chalk.red(`Unsupported engine:`)}: ${engine}\nPick one of: ${SUPPORTED_ENGINES.map(
|
||||||
({ type }) => type
|
({ type }) => type
|
||||||
).join(', ')}.`
|
).join(', ')}`
|
||||||
);
|
);
|
||||||
|
|
||||||
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
const EngineComponent = await import(SUPPORTED_ENGINES[engineIndex].component);
|
const EngineComponent = await import(SUPPORTED_ENGINES[engineIndex].component);
|
||||||
const method = METHOD_NAME_MAP.find(({ name }) => name === methodName);
|
const method = METHOD_NAME_MAP.find(({ name }) => name === methodName);
|
||||||
|
|
||||||
if (!method) {
|
if (!method) {
|
||||||
throw Error(
|
console.error(
|
||||||
`Unsupported method ${methodName}. Try one of: ${METHOD_NAME_MAP.map(({ name }) => name).join(
|
`❌ ${chalk.red(`Unsupported method:`)} ${methodName}\nPick one of: ${METHOD_NAME_MAP.map(
|
||||||
', '
|
({ name }) => name
|
||||||
)}.`
|
).join(', ')}`
|
||||||
);
|
);
|
||||||
|
|
||||||
|
process.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
createBaseConfig(deployConfigPath, isInit);
|
||||||
|
|
||||||
|
if (isInit) {
|
||||||
|
process.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const context = new Context({
|
const context = new Context({
|
||||||
|
|
@ -46,6 +58,8 @@ const deploy = async (deployConfigPath: string, methodName = 'default'): Promise
|
||||||
const component = new EngineComponent.default(undefined, context);
|
const component = new EngineComponent.default(undefined, context);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
context.log(`⚡ Starting ${method.actionNoun} ⚡`);
|
||||||
|
|
||||||
onPreDeploy && (await onPreDeploy());
|
onPreDeploy && (await onPreDeploy());
|
||||||
|
|
||||||
await component.init();
|
await component.init();
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
#!/usr/bin/env node
|
#!/usr/bin/env node
|
||||||
|
|
||||||
import fs from 'fs-extra';
|
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import minimist from 'minimist';
|
import minimist from 'minimist';
|
||||||
|
|
||||||
|
|
@ -8,21 +7,7 @@ import deploy from './deploy';
|
||||||
import { DEPLOY_CONFIG_NAME } from './config';
|
import { DEPLOY_CONFIG_NAME } from './config';
|
||||||
|
|
||||||
const deployConfigPath = path.join(process.cwd(), DEPLOY_CONFIG_NAME);
|
const deployConfigPath = path.join(process.cwd(), DEPLOY_CONFIG_NAME);
|
||||||
const configPathExists = fs.existsSync(deployConfigPath);
|
|
||||||
const args = minimist(process.argv.slice(2));
|
const args = minimist(process.argv.slice(2));
|
||||||
const method = args._[0] || undefined;
|
const method = args._[0] || undefined;
|
||||||
|
|
||||||
// create a default next-deploy config if one doesn't exist yet
|
|
||||||
if (!configPathExists) {
|
|
||||||
fs.writeFileSync(
|
|
||||||
deployConfigPath,
|
|
||||||
`// for more configurable options see: https://github.com/nidratech/next-deploy#configuration-options
|
|
||||||
module.exports = {
|
|
||||||
debug: true,
|
|
||||||
onPreDeploy: () => console.log('⚡ Starting Deployment'),
|
|
||||||
};
|
|
||||||
`
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
deploy(deployConfigPath, method);
|
deploy(deployConfigPath, method);
|
||||||
|
|
|
||||||
24
packages/cli/src/utils.ts
Normal file
24
packages/cli/src/utils.ts
Normal file
|
|
@ -0,0 +1,24 @@
|
||||||
|
import fs from 'fs-extra';
|
||||||
|
|
||||||
|
import { DEPLOY_CONFIG_NAME } from './config';
|
||||||
|
|
||||||
|
export const createBaseConfig = (deployConfigPath: string, displayWarning?: boolean) => {
|
||||||
|
const configPathExists = fs.existsSync(deployConfigPath);
|
||||||
|
|
||||||
|
if (displayWarning && configPathExists) {
|
||||||
|
console.warn(`⚠️ The ${DEPLOY_CONFIG_NAME} configuration already exists.`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// create a default next-deploy config if one doesn't exist yet
|
||||||
|
if (!configPathExists) {
|
||||||
|
fs.writeFileSync(
|
||||||
|
deployConfigPath,
|
||||||
|
`// for more configurable options see: https://github.com/nidratech/next-deploy#configuration-options
|
||||||
|
module.exports = {
|
||||||
|
engine: 'aws',
|
||||||
|
debug: true,
|
||||||
|
};
|
||||||
|
`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
10
packages/cli/types.d.ts
vendored
10
packages/cli/types.d.ts
vendored
|
|
@ -1,12 +1,4 @@
|
||||||
export type BaseDeploymentOptions = {
|
export type ContextConfig = {
|
||||||
engine?: 'aws' | 'github';
|
|
||||||
debug?: boolean;
|
|
||||||
onPreDeploy?: () => Promise<void>;
|
|
||||||
onPostDeploy?: () => Promise<void>;
|
|
||||||
onShutdown?: () => Promise<void>;
|
|
||||||
};
|
|
||||||
|
|
||||||
type ContextConfig = {
|
|
||||||
root: string;
|
root: string;
|
||||||
stateRoot: string;
|
stateRoot: string;
|
||||||
credentials?: Record<string, unknown>;
|
credentials?: Record<string, unknown>;
|
||||||
|
|
|
||||||
|
|
@ -2,27 +2,11 @@
|
||||||
# yarn lockfile v1
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
"@next-deploy/aws-cloudfront@link:../aws-cloudfront":
|
|
||||||
version "0.0.0"
|
|
||||||
uid ""
|
|
||||||
|
|
||||||
"@next-deploy/aws-component@link:../aws-component":
|
"@next-deploy/aws-component@link:../aws-component":
|
||||||
version "0.0.0"
|
version "0.0.0"
|
||||||
uid ""
|
uid ""
|
||||||
|
|
||||||
"@next-deploy/aws-domain@link:../aws-domain":
|
"@next-deploy/github@link:../github":
|
||||||
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@link:../aws-s3":
|
|
||||||
version "0.0.0"
|
version "0.0.0"
|
||||||
uid ""
|
uid ""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "@next-deploy/github",
|
"name": "@next-deploy/github",
|
||||||
"version": "1.0.0",
|
"version": "0.0.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "dist/index.js",
|
"main": "serverless.js",
|
||||||
"types": "dist/index.d.ts",
|
"types": "dist/component.d.ts",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "yarn clean && yarn compile",
|
"build": "yarn clean && yarn compile",
|
||||||
|
"build:watch": "yarn compile -w",
|
||||||
"clean": "rm -rf ./dist",
|
"clean": "rm -rf ./dist",
|
||||||
"compile": "tsc -p tsconfig.build.json"
|
"compile": "tsc -p tsconfig.build.json"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
43
packages/github/src/builder.ts
Normal file
43
packages/github/src/builder.ts
Normal file
|
|
@ -0,0 +1,43 @@
|
||||||
|
import execa from 'execa';
|
||||||
|
import { writeFileSync } from 'fs';
|
||||||
|
|
||||||
|
const NEXT_EXPORT_CMD = ['export'];
|
||||||
|
|
||||||
|
const build = async ({ cmd, cwd, args }: BuildOptions, debug?: (message: string) => void) => {
|
||||||
|
if (debug) {
|
||||||
|
const { stdout: nextVersion } = await execa(cmd, ['--version'], {
|
||||||
|
cwd,
|
||||||
|
});
|
||||||
|
|
||||||
|
debug(`Starting a new build with ${nextVersion}`);
|
||||||
|
|
||||||
|
console.log();
|
||||||
|
}
|
||||||
|
|
||||||
|
// run the build
|
||||||
|
let subprocess = execa(cmd, args, {
|
||||||
|
cwd,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (debug && subprocess.stdout) {
|
||||||
|
subprocess.stdout.pipe(process.stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
await subprocess;
|
||||||
|
|
||||||
|
// export the static assets from the build
|
||||||
|
subprocess = execa(cmd, NEXT_EXPORT_CMD, {
|
||||||
|
cwd,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (debug && subprocess.stdout) {
|
||||||
|
subprocess.stdout.pipe(process.stdout);
|
||||||
|
}
|
||||||
|
|
||||||
|
await subprocess;
|
||||||
|
|
||||||
|
// needed to be able for gh-pages to serve directories that start with _
|
||||||
|
writeFileSync('out/.nojekyll', '');
|
||||||
|
};
|
||||||
|
|
||||||
|
export default build;
|
||||||
|
|
@ -1,25 +1,106 @@
|
||||||
import { Component } from '@serverless/core';
|
import { Component } from '@serverless/core';
|
||||||
|
import { resolve } from 'path';
|
||||||
|
import { publish } from 'gh-pages';
|
||||||
|
import { emptyDir } from 'fs-extra';
|
||||||
|
import { writeFileSync } from 'fs';
|
||||||
|
|
||||||
|
import build from './builder';
|
||||||
import { GithubInputs, DeploymentResult } from '../types';
|
import { GithubInputs, DeploymentResult } from '../types';
|
||||||
|
|
||||||
class GithubComponent extends Component {
|
class GithubComponent extends Component {
|
||||||
async default(inputs: GithubInputs = {}): Promise<DeploymentResult> {
|
async default(inputs: GithubInputs = {}): Promise<DeploymentResult> {
|
||||||
|
if (inputs.build !== false) {
|
||||||
|
await this.build(inputs);
|
||||||
|
}
|
||||||
|
|
||||||
return this.deploy(inputs);
|
return this.deploy(inputs);
|
||||||
}
|
}
|
||||||
|
|
||||||
async build(inputs: GithubInputs = {}): Promise<void> {
|
async build(inputs: GithubInputs = {}): Promise<void> {
|
||||||
// TODO
|
const nextConfigPath = inputs.nextConfigDir ? resolve(inputs.nextConfigDir) : process.cwd();
|
||||||
|
const buildCwd =
|
||||||
|
typeof inputs.build === 'boolean' || typeof inputs.build === 'undefined' || !inputs.build.cwd
|
||||||
|
? nextConfigPath
|
||||||
|
: resolve(inputs.build.cwd);
|
||||||
|
const buildConfig: BuildOptions = {
|
||||||
|
enabled: inputs.build
|
||||||
|
? // @ts-ignore
|
||||||
|
inputs.build !== false && inputs.build.enabled !== false
|
||||||
|
: true,
|
||||||
|
cmd: 'node_modules/.bin/next',
|
||||||
|
args: ['build'],
|
||||||
|
...(typeof inputs.build === 'object' ? inputs.build : {}),
|
||||||
|
cwd: buildCwd,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (buildConfig.enabled) {
|
||||||
|
await build(buildConfig, this.context.instance.debugMode ? this.context.debug : undefined);
|
||||||
|
|
||||||
|
if (inputs?.domain?.length) {
|
||||||
|
const domain = getDomains(inputs.domain);
|
||||||
|
|
||||||
|
if (domain) {
|
||||||
|
writeFileSync('out/CNAME', domain);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async deploy(inputs: GithubInputs = {}): Promise<DeploymentResult> {
|
async deploy(inputs: GithubInputs = {}): Promise<DeploymentResult> {
|
||||||
// TODO
|
let outputs: DeploymentResult = {};
|
||||||
|
|
||||||
return {};
|
if (inputs?.domain?.length) {
|
||||||
|
const domain = getDomains(inputs.domain);
|
||||||
|
outputs.appUrl = `https://${domain}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
const publishPromise = new Promise((resolve, reject) => {
|
||||||
|
publish(
|
||||||
|
'out',
|
||||||
|
{ message: 'Next Deployment Update', ...inputs.publishOptions, dotfiles: true },
|
||||||
|
(err) => {
|
||||||
|
if (err) {
|
||||||
|
return reject(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
await publishPromise;
|
||||||
|
|
||||||
|
return outputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
async remove(): Promise<void> {
|
async remove(): Promise<void> {
|
||||||
// TODO
|
await emptyDir('out');
|
||||||
|
writeFileSync('out/empty', '');
|
||||||
|
|
||||||
|
const publishPromise = new Promise((resolve, reject) => {
|
||||||
|
publish('out', { message: 'Next Deployment Removal', remove: '*' }, (err) => {
|
||||||
|
if (err) {
|
||||||
|
return reject(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
await publishPromise;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function getDomains(inputDomain: string | string[]): string | undefined {
|
||||||
|
let domain;
|
||||||
|
|
||||||
|
if (typeof inputDomain === 'string') {
|
||||||
|
domain = inputDomain;
|
||||||
|
} else if (inputDomain instanceof Array) {
|
||||||
|
domain = inputDomain.join();
|
||||||
|
}
|
||||||
|
|
||||||
|
return domain;
|
||||||
|
}
|
||||||
|
|
||||||
export default GithubComponent;
|
export default GithubComponent;
|
||||||
|
|
|
||||||
10
packages/github/types.d.ts
vendored
10
packages/github/types.d.ts
vendored
|
|
@ -1,3 +1,9 @@
|
||||||
export type GithubInputs = {};
|
import { PublishOptions } from 'gh-pages';
|
||||||
|
|
||||||
type DeploymentResult = {};
|
export type GithubInputs = BaseDeploymentOptions & {
|
||||||
|
publishOptions?: PublishOptions;
|
||||||
|
};
|
||||||
|
|
||||||
|
type DeploymentResult = {
|
||||||
|
appUrl?: string;
|
||||||
|
};
|
||||||
|
|
|
||||||
129
yarn.lock
129
yarn.lock
|
|
@ -2159,6 +2159,11 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/node" "*"
|
"@types/node" "*"
|
||||||
|
|
||||||
|
"@types/gh-pages@^3.0.0":
|
||||||
|
version "3.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/@types/gh-pages/-/gh-pages-3.0.0.tgz#375b0ddd43d2d2e696880c20bb43769fdaf88929"
|
||||||
|
integrity sha512-bWEiIqN0WSUQhUZXaaCVIRXdomjQCX9mCNLo6kGSML8VuiH5DXoiNOkXmxrJyrzMQmcV67JloDksM1I3WoVHhQ==
|
||||||
|
|
||||||
"@types/glob@*", "@types/glob@^7.1.1":
|
"@types/glob@*", "@types/glob@^7.1.1":
|
||||||
version "7.1.3"
|
version "7.1.3"
|
||||||
resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.3.tgz#e6ba80f36b7daad2c685acd9266382e68985c183"
|
resolved "https://registry.yarnpkg.com/@types/glob/-/glob-7.1.3.tgz#e6ba80f36b7daad2c685acd9266382e68985c183"
|
||||||
|
|
@ -2233,10 +2238,10 @@
|
||||||
resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24"
|
resolved "https://registry.yarnpkg.com/@types/q/-/q-1.5.4.tgz#15925414e0ad2cd765bfef58842f7e26a7accb24"
|
||||||
integrity sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==
|
integrity sha512-1HcDas8SEj4z1Wc696tH56G8OlRaH/sqZOynNNB+HF0WOeXPaxTtbYzJY2oEfiUxjSKjhCKr+MvR7dCHcEelug==
|
||||||
|
|
||||||
"@types/ramda@^0.27.10":
|
"@types/ramda@^0.27.11":
|
||||||
version "0.27.10"
|
version "0.27.11"
|
||||||
resolved "https://registry.yarnpkg.com/@types/ramda/-/ramda-0.27.10.tgz#a006d24dd73fe38fac7fdfe970bfb992b9da5538"
|
resolved "https://registry.yarnpkg.com/@types/ramda/-/ramda-0.27.11.tgz#a2efedc1fecc0faa2d3530eb53cf468e219f7c51"
|
||||||
integrity sha512-7DWYf5F4XYoJIb0bsYv66iiUiHYWlfC/Y9Lx1Ha0bEEw4wi9Uv51d49mMv+T41nEbAKPNVt5XJudwFR1bMCXTw==
|
integrity sha512-pojA0+wBhjMWfwZ1tAea/OdUqZxaRQOi/vHldthrOIEPdRQdJb/hvU4yM1uHKGTT89ZZpxe43KM1sq5YGxS5lw==
|
||||||
dependencies:
|
dependencies:
|
||||||
ts-toolbelt "^6.3.3"
|
ts-toolbelt "^6.3.3"
|
||||||
|
|
||||||
|
|
@ -2247,10 +2252,10 @@
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/react" "*"
|
"@types/react" "*"
|
||||||
|
|
||||||
"@types/react@*", "@types/react@^16.9.42":
|
"@types/react@*", "@types/react@^16.9.43":
|
||||||
version "16.9.42"
|
version "16.9.43"
|
||||||
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.42.tgz#9776508d59c1867bbf9bd7f036dab007fdaa1cb7"
|
resolved "https://registry.yarnpkg.com/@types/react/-/react-16.9.43.tgz#c287f23f6189666ee3bebc2eb8d0f84bcb6cdb6b"
|
||||||
integrity sha512-iGy6HwfVfotqJ+PfRZ4eqPHPP5NdPZgQlr0lTs8EfkODRBV9cYy8QMKcC9qPCe1JrESC1Im6SrCFR6tQgg74ag==
|
integrity sha512-PxshAFcnJqIWYpJbLPriClH53Z2WlJcVZE+NP2etUtWQs2s7yIMj3/LDKZT/5CHJ/F62iyjVCDu2H3jHEXIxSg==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@types/prop-types" "*"
|
"@types/prop-types" "*"
|
||||||
csstype "^2.2.0"
|
csstype "^2.2.0"
|
||||||
|
|
@ -2866,7 +2871,7 @@ array-ify@^1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece"
|
resolved "https://registry.yarnpkg.com/array-ify/-/array-ify-1.0.0.tgz#9e528762b4a9066ad163a6962a364418e9626ece"
|
||||||
integrity sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=
|
integrity sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=
|
||||||
|
|
||||||
array-union@^1.0.2:
|
array-union@^1.0.1, array-union@^1.0.2:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39"
|
resolved "https://registry.yarnpkg.com/array-union/-/array-union-1.0.2.tgz#9a34410e4f4e3da23dea375be5be70f24778ec39"
|
||||||
integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=
|
integrity sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=
|
||||||
|
|
@ -2959,7 +2964,7 @@ async-each@^1.0.1:
|
||||||
resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf"
|
resolved "https://registry.yarnpkg.com/async-each/-/async-each-1.0.3.tgz#b727dbf87d7651602f06f4d4ac387f47d91b0cbf"
|
||||||
integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==
|
integrity sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==
|
||||||
|
|
||||||
async@^2.6.3:
|
async@^2.6.1, async@^2.6.3:
|
||||||
version "2.6.3"
|
version "2.6.3"
|
||||||
resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff"
|
resolved "https://registry.yarnpkg.com/async/-/async-2.6.3.tgz#d72625e2344a3656e3a3ad4fa749fa83299d82ff"
|
||||||
integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==
|
integrity sha512-zflvls11DCy+dQWzTW2dzuilv8Z5X/pjfmZOWba6TNIVDm+2UDaJmXSOXlasHKfNBs8oo3M0aT50fDEWfKZjXg==
|
||||||
|
|
@ -3479,9 +3484,9 @@ caniuse-api@^3.0.0:
|
||||||
lodash.uniq "^4.5.0"
|
lodash.uniq "^4.5.0"
|
||||||
|
|
||||||
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001043, caniuse-lite@^1.0.30001093:
|
caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001043, caniuse-lite@^1.0.30001093:
|
||||||
version "1.0.30001097"
|
version "1.0.30001099"
|
||||||
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001097.tgz#1129c40c9f5ee3282158da08fd915d301f4a9bd8"
|
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001099.tgz#540118fcc6842d1fde62f4ee5521d1ec6afdb40e"
|
||||||
integrity sha512-TeuSleKt/vWXaPkLVFqGDnbweYfq4IaZ6rUugFf3rWY6dlII8StUZ8Ddin0PkADfgYZ4wRqCdO2ORl4Rn5eZIA==
|
integrity sha512-sdS9A+sQTk7wKoeuZBN/YMAHVztUfVnjDi4/UV3sDE8xoh7YR12hKW+pIdB3oqKGwr9XaFL2ovfzt9w8eUI5CA==
|
||||||
|
|
||||||
caseless@~0.12.0:
|
caseless@~0.12.0:
|
||||||
version "0.12.0"
|
version "0.12.0"
|
||||||
|
|
@ -3752,7 +3757,7 @@ commander@2.19.x:
|
||||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
|
resolved "https://registry.yarnpkg.com/commander/-/commander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
|
||||||
integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==
|
integrity sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==
|
||||||
|
|
||||||
commander@^2.20.0:
|
commander@^2.18.0, commander@^2.20.0:
|
||||||
version "2.20.3"
|
version "2.20.3"
|
||||||
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
|
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
|
||||||
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
|
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
|
||||||
|
|
@ -4609,6 +4614,11 @@ elliptic@^6.0.0, elliptic@^6.5.2:
|
||||||
minimalistic-assert "^1.0.0"
|
minimalistic-assert "^1.0.0"
|
||||||
minimalistic-crypto-utils "^1.0.0"
|
minimalistic-crypto-utils "^1.0.0"
|
||||||
|
|
||||||
|
email-addresses@^3.0.1:
|
||||||
|
version "3.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/email-addresses/-/email-addresses-3.1.0.tgz#cabf7e085cbdb63008a70319a74e6136188812fb"
|
||||||
|
integrity sha512-k0/r7GrWVL32kZlGwfPNgB2Y/mMXVTq/decgLczm/j34whdaspNrZO8CnXPf1laaHxI6ptUlsnAxN+UAPw+fzg==
|
||||||
|
|
||||||
emoji-regex@^7.0.1:
|
emoji-regex@^7.0.1:
|
||||||
version "7.0.3"
|
version "7.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
|
resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-7.0.3.tgz#933a04052860c85e83c122479c4748a8e4c72156"
|
||||||
|
|
@ -5105,6 +5115,28 @@ file-uri-to-path@1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
|
resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd"
|
||||||
integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==
|
integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==
|
||||||
|
|
||||||
|
filename-reserved-regex@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/filename-reserved-regex/-/filename-reserved-regex-1.0.0.tgz#e61cf805f0de1c984567d0386dc5df50ee5af7e4"
|
||||||
|
integrity sha1-5hz4BfDeHJhFZ9A4bcXfUO5a9+Q=
|
||||||
|
|
||||||
|
filenamify-url@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/filenamify-url/-/filenamify-url-1.0.0.tgz#b32bd81319ef5863b73078bed50f46a4f7975f50"
|
||||||
|
integrity sha1-syvYExnvWGO3MHi+1Q9GpPeXX1A=
|
||||||
|
dependencies:
|
||||||
|
filenamify "^1.0.0"
|
||||||
|
humanize-url "^1.0.0"
|
||||||
|
|
||||||
|
filenamify@^1.0.0:
|
||||||
|
version "1.2.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/filenamify/-/filenamify-1.2.1.tgz#a9f2ffd11c503bed300015029272378f1f1365a5"
|
||||||
|
integrity sha1-qfL/0RxQO+0wABUCknI3jx8TZaU=
|
||||||
|
dependencies:
|
||||||
|
filename-reserved-regex "^1.0.0"
|
||||||
|
strip-outer "^1.0.0"
|
||||||
|
trim-repeated "^1.0.0"
|
||||||
|
|
||||||
fill-range@^4.0.0:
|
fill-range@^4.0.0:
|
||||||
version "4.0.0"
|
version "4.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7"
|
resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-4.0.0.tgz#d544811d428f98eb06a63dc402d2403c328c38f7"
|
||||||
|
|
@ -5122,7 +5154,7 @@ fill-range@^7.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
to-regex-range "^5.0.1"
|
to-regex-range "^5.0.1"
|
||||||
|
|
||||||
find-cache-dir@3.3.1:
|
find-cache-dir@3.3.1, find-cache-dir@^3.3.1:
|
||||||
version "3.3.1"
|
version "3.3.1"
|
||||||
resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880"
|
resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.1.tgz#89b33fad4a4670daa94f855f7fbe31d6d84fe880"
|
||||||
integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==
|
integrity sha512-t2GDMt3oGC/v+BMwzmllWDuJF/xcDtE5j/fCGbqDD7OLuJkj0cfh1YSA5VKPvwMeLFLNDBkwOKZ2X85jGLVftQ==
|
||||||
|
|
@ -5413,6 +5445,19 @@ getpass@^0.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
assert-plus "^1.0.0"
|
assert-plus "^1.0.0"
|
||||||
|
|
||||||
|
gh-pages@^3.1.0:
|
||||||
|
version "3.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/gh-pages/-/gh-pages-3.1.0.tgz#ec3ed0f6a6e3fc3d888758fa018f08191c96bd55"
|
||||||
|
integrity sha512-3b1rly9kuf3/dXsT8+ZxP0UhNLOo1CItj+3e31yUVcaph/yDsJ9RzD7JOw5o5zpBTJVQLlJAASNkUfepi9fe2w==
|
||||||
|
dependencies:
|
||||||
|
async "^2.6.1"
|
||||||
|
commander "^2.18.0"
|
||||||
|
email-addresses "^3.0.1"
|
||||||
|
filenamify-url "^1.0.0"
|
||||||
|
find-cache-dir "^3.3.1"
|
||||||
|
fs-extra "^8.1.0"
|
||||||
|
globby "^6.1.0"
|
||||||
|
|
||||||
git-raw-commits@2.0.0:
|
git-raw-commits@2.0.0:
|
||||||
version "2.0.0"
|
version "2.0.0"
|
||||||
resolved "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-2.0.0.tgz#d92addf74440c14bcc5c83ecce3fb7f8a79118b5"
|
resolved "https://registry.yarnpkg.com/git-raw-commits/-/git-raw-commits-2.0.0.tgz#d92addf74440c14bcc5c83ecce3fb7f8a79118b5"
|
||||||
|
|
@ -5487,7 +5532,7 @@ glob-to-regexp@^0.4.1:
|
||||||
resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e"
|
resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e"
|
||||||
integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==
|
integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==
|
||||||
|
|
||||||
glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
|
glob@^7.0.3, glob@^7.1.1, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
|
||||||
version "7.1.6"
|
version "7.1.6"
|
||||||
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
|
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
|
||||||
integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
|
integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
|
||||||
|
|
@ -5523,6 +5568,17 @@ globby@^11.0.1:
|
||||||
merge2 "^1.3.0"
|
merge2 "^1.3.0"
|
||||||
slash "^3.0.0"
|
slash "^3.0.0"
|
||||||
|
|
||||||
|
globby@^6.1.0:
|
||||||
|
version "6.1.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/globby/-/globby-6.1.0.tgz#f5a6d70e8395e21c858fb0489d64df02424d506c"
|
||||||
|
integrity sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=
|
||||||
|
dependencies:
|
||||||
|
array-union "^1.0.1"
|
||||||
|
glob "^7.0.3"
|
||||||
|
object-assign "^4.0.1"
|
||||||
|
pify "^2.0.0"
|
||||||
|
pinkie-promise "^2.0.0"
|
||||||
|
|
||||||
globby@^9.2.0:
|
globby@^9.2.0:
|
||||||
version "9.2.0"
|
version "9.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/globby/-/globby-9.2.0.tgz#fd029a706c703d29bdd170f4b6db3a3f7a7cb63d"
|
resolved "https://registry.yarnpkg.com/globby/-/globby-9.2.0.tgz#fd029a706c703d29bdd170f4b6db3a3f7a7cb63d"
|
||||||
|
|
@ -5767,6 +5823,14 @@ humanize-ms@^1.2.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
ms "^2.0.0"
|
ms "^2.0.0"
|
||||||
|
|
||||||
|
humanize-url@^1.0.0:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/humanize-url/-/humanize-url-1.0.1.tgz#f4ab99e0d288174ca4e1e50407c55fbae464efff"
|
||||||
|
integrity sha1-9KuZ4NKIF0yk4eUEB8VfuuRk7/8=
|
||||||
|
dependencies:
|
||||||
|
normalize-url "^1.0.0"
|
||||||
|
strip-url-auth "^1.0.0"
|
||||||
|
|
||||||
husky@^4.2.5:
|
husky@^4.2.5:
|
||||||
version "4.2.5"
|
version "4.2.5"
|
||||||
resolved "https://registry.yarnpkg.com/husky/-/husky-4.2.5.tgz#2b4f7622673a71579f901d9885ed448394b5fa36"
|
resolved "https://registry.yarnpkg.com/husky/-/husky-4.2.5.tgz#2b4f7622673a71579f901d9885ed448394b5fa36"
|
||||||
|
|
@ -7423,7 +7487,7 @@ normalize-path@^3.0.0, normalize-path@~3.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
|
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
|
||||||
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
|
integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==
|
||||||
|
|
||||||
normalize-url@1.9.1:
|
normalize-url@1.9.1, normalize-url@^1.0.0:
|
||||||
version "1.9.1"
|
version "1.9.1"
|
||||||
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c"
|
resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-1.9.1.tgz#2cc0d66b31ea23036458436e3620d85954c66c3c"
|
||||||
integrity sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=
|
integrity sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=
|
||||||
|
|
@ -9778,15 +9842,27 @@ strip-indent@^3.0.0:
|
||||||
min-indent "^1.0.0"
|
min-indent "^1.0.0"
|
||||||
|
|
||||||
strip-json-comments@^3.1.0:
|
strip-json-comments@^3.1.0:
|
||||||
version "3.1.0"
|
version "3.1.1"
|
||||||
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.0.tgz#7638d31422129ecf4457440009fba03f9f9ac180"
|
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006"
|
||||||
integrity sha512-e6/d0eBu7gHtdCqFt0xJr642LdToM5/cN4Qb9DbHjVx1CP5RyeM+zH7pbecEmDv/lBqb0QH+6Uqq75rxFPkM0w==
|
integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==
|
||||||
|
|
||||||
strip-json-comments@~2.0.1:
|
strip-json-comments@~2.0.1:
|
||||||
version "2.0.1"
|
version "2.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
|
resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a"
|
||||||
integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
|
integrity sha1-PFMZQukIwml8DsNEhYwobHygpgo=
|
||||||
|
|
||||||
|
strip-outer@^1.0.0:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/strip-outer/-/strip-outer-1.0.1.tgz#b2fd2abf6604b9d1e6013057195df836b8a9d631"
|
||||||
|
integrity sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==
|
||||||
|
dependencies:
|
||||||
|
escape-string-regexp "^1.0.2"
|
||||||
|
|
||||||
|
strip-url-auth@^1.0.0:
|
||||||
|
version "1.0.1"
|
||||||
|
resolved "https://registry.yarnpkg.com/strip-url-auth/-/strip-url-auth-1.0.1.tgz#22b0fa3a41385b33be3f331551bbb837fa0cd7ae"
|
||||||
|
integrity sha1-IrD6OkE4WzO+PzMVUbu4N/oM164=
|
||||||
|
|
||||||
strong-log-transformer@^2.0.0:
|
strong-log-transformer@^2.0.0:
|
||||||
version "2.1.0"
|
version "2.1.0"
|
||||||
resolved "https://registry.yarnpkg.com/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz#0f5ed78d325e0421ac6f90f7f10e691d6ae3ae10"
|
resolved "https://registry.yarnpkg.com/strong-log-transformer/-/strong-log-transformer-2.1.0.tgz#0f5ed78d325e0421ac6f90f7f10e691d6ae3ae10"
|
||||||
|
|
@ -10122,15 +10198,22 @@ trim-off-newlines@^1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz#9f9ba9d9efa8764c387698bcbfeb2c848f11adb3"
|
resolved "https://registry.yarnpkg.com/trim-off-newlines/-/trim-off-newlines-1.0.1.tgz#9f9ba9d9efa8764c387698bcbfeb2c848f11adb3"
|
||||||
integrity sha1-n5up2e+odkw4dpi8v+sshI8RrbM=
|
integrity sha1-n5up2e+odkw4dpi8v+sshI8RrbM=
|
||||||
|
|
||||||
|
trim-repeated@^1.0.0:
|
||||||
|
version "1.0.0"
|
||||||
|
resolved "https://registry.yarnpkg.com/trim-repeated/-/trim-repeated-1.0.0.tgz#e3646a2ea4e891312bf7eace6cfb05380bc01c21"
|
||||||
|
integrity sha1-42RqLqTokTEr9+rObPsFOAvAHCE=
|
||||||
|
dependencies:
|
||||||
|
escape-string-regexp "^1.0.2"
|
||||||
|
|
||||||
ts-pnp@^1.1.6:
|
ts-pnp@^1.1.6:
|
||||||
version "1.2.0"
|
version "1.2.0"
|
||||||
resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92"
|
resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92"
|
||||||
integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==
|
integrity sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==
|
||||||
|
|
||||||
ts-toolbelt@^6.3.3:
|
ts-toolbelt@^6.3.3:
|
||||||
version "6.10.16"
|
version "6.12.1"
|
||||||
resolved "https://registry.yarnpkg.com/ts-toolbelt/-/ts-toolbelt-6.10.16.tgz#c45bab5b5227d4ea3f120635aa5632150ad8191d"
|
resolved "https://registry.yarnpkg.com/ts-toolbelt/-/ts-toolbelt-6.12.1.tgz#bfcfaf0e1cc7416bcfc412c9340233f57a1f86c4"
|
||||||
integrity sha512-MAad9fRk8oO0WqB927LLdEkZg+Oz0nAkuyS4zTsTk4L97AjHX7GdFGUk2ABkqgo9S3V/Wkn2pd2df2GcZoayvQ==
|
integrity sha512-Y4ZMdw+CzHnzFp7yp8axTDl6G78ypeS1XcaarLoXpnW0McYR7kDLndU2tk7nIEdM99yoHjaRSbL09ULZMtN5RA==
|
||||||
|
|
||||||
tslib@^1.8.1, tslib@^1.9.0:
|
tslib@^1.8.1, tslib@^1.9.0:
|
||||||
version "1.13.0"
|
version "1.13.0"
|
||||||
|
|
|
||||||
Reference in a new issue