├── .all-contributorsrc
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
└── workflows
│ ├── nodejs.yml
│ └── npm-publish.yml
├── .gitignore
├── LICENSE
├── README.md
├── renovate.json
├── screenshots
├── api-id.png
├── personal-access-token.png
├── step-1.png
└── step-2.png
└── src
├── .editorconfig
├── README.md
├── builders.json
├── collection.json
├── deploy
├── index.ts
├── schema.d.ts
└── schema.json
├── index.ts
├── interfaces.ts
├── ng-add
├── index.ts
└── schema.json
├── package.json
└── tsconfig.json
/.all-contributorsrc:
--------------------------------------------------------------------------------
1 | {
2 | "files": [
3 | "README.md"
4 | ],
5 | "imageSize": 100,
6 | "commit": false,
7 | "contributors": [
8 | {
9 | "login": "nitishk72",
10 | "name": "Nitish Kumar Singh",
11 | "avatar_url": "https://avatars2.githubusercontent.com/u/15886737?v=4",
12 | "profile": "https://www.youtube.com/c/NitishKumarSingh",
13 | "contributions": [
14 | "code"
15 | ]
16 | },
17 | {
18 | "login": "Shaikh-Ubaid",
19 | "name": "Shaikh-Ubaid",
20 | "avatar_url": "https://avatars2.githubusercontent.com/u/43722035?v=4",
21 | "profile": "https://github.com/Shaikh-Ubaid",
22 | "contributions": [
23 | "doc"
24 | ]
25 | },
26 | {
27 | "login": "iamsurajdc",
28 | "name": "Suraj Chandgude",
29 | "avatar_url": "https://avatars0.githubusercontent.com/u/32074031?v=4",
30 | "profile": "https://iamsurajdc.js.org",
31 | "contributions": [
32 | "code"
33 | ]
34 | },
35 | {
36 | "login": "santoshyadav198613",
37 | "name": "Santosh Yadav",
38 | "avatar_url": "https://avatars3.githubusercontent.com/u/11923975?v=4",
39 | "profile": "https://www.santoshyadav.dev",
40 | "contributions": [
41 | "code"
42 | ]
43 | },
44 | {
45 | "login": "alan-agius4",
46 | "name": "Alan Agius",
47 | "avatar_url": "https://avatars3.githubusercontent.com/u/17563226?v=4",
48 | "profile": "https://github.com/alan-agius4",
49 | "contributions": [
50 | "code"
51 | ]
52 | },
53 | {
54 | "login": "imranmomin",
55 | "name": "Imran Momin",
56 | "avatar_url": "https://avatars3.githubusercontent.com/u/6071075?v=4",
57 | "profile": "https://github.com/imranmomin",
58 | "contributions": [
59 | "code"
60 | ]
61 | },
62 | {
63 | "login": "BioPhoton",
64 | "name": "Michael Hladky",
65 | "avatar_url": "https://avatars1.githubusercontent.com/u/10064416?v=4",
66 | "profile": "https://github.com/BioPhoton",
67 | "contributions": [
68 | "code"
69 | ]
70 | },
71 | {
72 | "login": "NileshPatel17",
73 | "name": "Nilesh Patel",
74 | "avatar_url": "https://avatars2.githubusercontent.com/u/27020381?v=4",
75 | "profile": "https://github.com/NileshPatel17",
76 | "contributions": [
77 | "doc"
78 | ]
79 | },
80 | {
81 | "login": "joshuamorony",
82 | "name": "Josh Morony",
83 | "avatar_url": "https://avatars.githubusercontent.com/u/2578009?v=4",
84 | "profile": "https://www.joshmorony.com",
85 | "contributions": [
86 | "code"
87 | ]
88 | }
89 | ],
90 | "contributorsPerLine": 7,
91 | "projectName": "netlify-builder",
92 | "projectOwner": "ngx-builders",
93 | "repoType": "github",
94 | "repoHost": "https://github.com",
95 | "skipCi": true
96 | }
97 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 | 1. Go to '...'
16 | 2. Click on '....'
17 | 3. Scroll down to '....'
18 | 4. See error
19 |
20 | **Expected behavior**
21 | A clear and concise description of what you expected to happen.
22 |
23 | **Screenshots**
24 | If applicable, add screenshots to help explain your problem.
25 |
26 | **Desktop (please complete the following information):**
27 | - OS: [e.g. iOS]
28 | - Browser [e.g. chrome, safari]
29 | - Version [e.g. 22]
30 |
31 | **Smartphone (please complete the following information):**
32 | - Device: [e.g. iPhone6]
33 | - OS: [e.g. iOS8.1]
34 | - Browser [e.g. stock browser, safari]
35 | - Version [e.g. 22]
36 |
37 | **Additional context**
38 | Add any other context about the problem here.
39 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: ''
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Is your feature request related to a problem? Please describe.**
11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
12 |
13 | **Describe the solution you'd like**
14 | A clear and concise description of what you want to happen.
15 |
16 | **Describe alternatives you've considered**
17 | A clear and concise description of any alternative solutions or features you've considered.
18 |
19 | **Additional context**
20 | Add any other context or screenshots about the feature request here.
21 |
--------------------------------------------------------------------------------
/.github/workflows/nodejs.yml:
--------------------------------------------------------------------------------
1 | # This workflow will do a clean install of node dependencies, build the source code and run tests across different versions of node
2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
3 |
4 | name: Node.js CI
5 |
6 | on:
7 | push:
8 | branches: [ master ]
9 | pull_request:
10 | branches: [ master ]
11 |
12 | jobs:
13 | build:
14 |
15 | runs-on: ubuntu-latest
16 | defaults:
17 | run:
18 | working-directory: ./src
19 | strategy:
20 | matrix:
21 | node-version: [14.x]
22 |
23 | steps:
24 | - uses: actions/checkout@v2
25 | - name: Use Node.js ${{ matrix.node-version }}
26 | uses: actions/setup-node@v1
27 | with:
28 | node-version: ${{ matrix.node-version }}
29 | - run: npm install
30 | - run: npm run build
31 | env:
32 | CI: true
33 |
--------------------------------------------------------------------------------
/.github/workflows/npm-publish.yml:
--------------------------------------------------------------------------------
1 | # This workflow will run tests using node and then publish a package to GitHub Packages when a release is created
2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/publishing-nodejs-packages
3 |
4 | name: Node.js Package
5 |
6 | on:
7 | push:
8 | branches:
9 | - 'release/**'
10 | release:
11 | types: [created]
12 |
13 | jobs:
14 | build:
15 | runs-on: ubuntu-latest
16 | steps:
17 | - uses: actions/checkout@v2
18 | - uses: actions/setup-node@v2
19 | with:
20 | node-version: 12
21 | - run: npm install
22 |
23 | publish-npm:
24 | needs: build
25 | runs-on: ubuntu-latest
26 | defaults:
27 | run:
28 | working-directory: ./src
29 | steps:
30 | - uses: actions/checkout@v2
31 | - uses: actions/setup-node@v2
32 | with:
33 | node-version: 12
34 | registry-url: https://registry.npmjs.org/
35 | scope: '@ngx-builders'
36 | - run: npm install
37 | - run: npm run build
38 | - run: npm publish
39 | env:
40 | NODE_AUTH_TOKEN: ${{secrets.npm_token}}
41 |
42 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | *.js
2 | *.map
3 | node_modules
4 | *.js
5 | *.js.map
6 | .gitignore
7 | *.code-workspace
8 | **/package-lock.json
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2019 ngx-builders
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://www.npmjs.com/package/@netlify-builder/deploy)
2 | [](https://www.npmjs.com/package/@netlify-builder/deploy)
3 | 
4 | [](#contributors)
5 |
6 | ## **Deploy your Angular app to Netlify directly from the Angular CLI! 🚀**
7 | ### Pre-requisites
8 | - Angular project created via [Angular CLI](https://github.com/angular/angular-cli) v8.3.0 or greater.
9 |
10 | ### Steps:
11 | 1. run `ng add @netlify-builder/deploy`
12 | OR `ng add @netlify-builder/deploy --project={projectName}` to add necessary dependencies. Once, it get installed,you will be prompted to enter (a) Site Id and (b) Netlify Token
13 | 
14 | 2. run ```ng deploy``` assuming that you have [Angular CLI](https://github.com/angular/angular-cli) installed globally
15 |
16 | OR
17 |
18 | add below script to ```package.json```
19 | ```
20 | "deploy":"ng deploy"
21 | ```
22 |
23 | 
24 |
25 |
26 | # Netlify Builder demo
27 |
28 | This repository contains an example of the Angular CLI Architect API.
29 |
30 | ## Builder
31 |
32 | You can find the Architect builder in the `src` directory.
33 |
34 | ## Sample application
35 |
36 | The sample application which uses the Architect builder is available under the `builder-test` directory.
37 |
38 | ## License
39 |
40 | MIT
41 |
42 |
43 | ## Setup
44 |
45 | 1. Move to src and run the below command
46 |
47 | ```sh
48 | npm i
49 | ```
50 |
51 | 2. Run the below command to build the package
52 |
53 | ```sh
54 | npm run build
55 | ```
56 |
57 | 3. run the below command to link the package
58 |
59 | ```
60 | npm link
61 | ```
62 |
63 | ## Link to [Step by Step Guide](https://www.netlify.com/blog/2019/09/17/using-the-angular-builder-for-netlify/)
64 |
65 | ## Contributors ✨
66 |
67 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)):
68 |
69 |
70 |
71 |
72 |
87 |
88 |
89 |
90 |
91 |
92 |
93 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
94 |
--------------------------------------------------------------------------------
/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": [
3 | "config:base"
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/screenshots/api-id.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ngx-builders/netlify-builder/b915395041d61d460f3a312c1a9c7cc9a683cda2/screenshots/api-id.png
--------------------------------------------------------------------------------
/screenshots/personal-access-token.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ngx-builders/netlify-builder/b915395041d61d460f3a312c1a9c7cc9a683cda2/screenshots/personal-access-token.png
--------------------------------------------------------------------------------
/screenshots/step-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ngx-builders/netlify-builder/b915395041d61d460f3a312c1a9c7cc9a683cda2/screenshots/step-1.png
--------------------------------------------------------------------------------
/screenshots/step-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ngx-builders/netlify-builder/b915395041d61d460f3a312c1a9c7cc9a683cda2/screenshots/step-2.png
--------------------------------------------------------------------------------
/src/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = space
5 | indent_size = 4
6 | charset = utf-8
7 | trim_trailing_whitespace = false
8 | insert_final_newline = false
--------------------------------------------------------------------------------
/src/README.md:
--------------------------------------------------------------------------------
1 | [](https://travis-ci.org/nitishk72/netlify-builder)
2 | [](#contributors)
3 | # Angular CLI Deployment to netlify
4 |
5 | Deploy your Angular app to Netlify directly from the Angular CLI! 🚀
6 |
7 | ## Prerequisite
8 |
9 | You will need two things in order to get started
10 |
11 | - API ID (Site ID) : Every Netlify application has an API ID that uniquely identify the respective app. You can find it inside your project's Setting/General section.
12 | 
13 | - [Personal access tokens](https://app.netlify.com/user/applications#personal-access-tokens) : Access token gives the ability to communicate with Netlify over API and helps to push the code on Netlify.
14 | 
15 |
16 | ## Setting up this Builder
17 |
18 | ```
19 | ng add @netlify-builder/deploy
20 | OR
21 | ng add @netlify-builder/deploy --project={projectName}
22 | ```
23 |
24 | The above command will configure everything, you just need to provide API ID and Personal access tokens when it will ask you for that.
25 |
26 | ## That's it. Now, you are good to go
27 |
28 | Now, Whenever you want to deploy your angular project just run a command `ng run [YOUR_PROJECT_NAME]:deploy` and your project will be deployed with new updates.
29 |
30 |
31 | ## 📦 Options
32 |
33 | #### --configuration
34 | * __optional__
35 | * Alias: `-c`
36 | * Default: `production` (string)
37 | * Example:
38 | * `ng deploy` – Angular project is build in production mode
39 | * `ng deploy --configuration=test` – Angular project is using the configuration `test` (this configuration must exist in the `angular.json` file)
40 |
41 | A named build target, as specified in the `configurations` section of `angular.json`.
42 | Each named target is accompanied by a configuration of option defaults for that target.
43 | Same as `ng build --configuration=XXX`.
44 | This command has no effect if the option `--no-build` option is active.
45 |
46 |
47 | #### --no-build
48 | - **optional**
49 | - Default: `false` (string)
50 | - Example:
51 | - `ng deploy` – Angular project is build in production mode before the deployment
52 | - `ng deploy --no-build` – Angular project is NOT build
53 |
54 | Skip build process during deployment.
55 | This can be used when you are sure that you haven't changed anything and want to deploy with the latest artifact.
56 | This command causes the `--configuration` setting to have no effect.
57 |
58 | #### --create
59 | - **optional**
60 | - Default: `false` (string)
61 | - Example:
62 | - `ng deploy --create` – The command will create a new site if there is no site id or the site id does not exists on netlify
63 |
64 | #### --base-href
65 |
66 | - **optional**
67 | - Default: `undefined` (string)
68 | - Example:
69 | - `ng deploy` – The tag `` remains unchanged in your `index.html`
70 | - `ng deploy --base-href=/the-repositoryname/` – The tag `` is added to your `index.html`
71 |
72 | Specifies the base URL for the application being built.
73 | Same as `ng build --base-href=/XXX/`
74 |
75 | #### --with-deps
76 | - **optional**
77 | - Default: `false` (string)
78 | - Example:
79 | - `ng deploy --with-deps` – Use this flag with Nx, to build your app withDeps.
80 | ## License
81 |
82 | MIT
83 |
84 |
85 |
--------------------------------------------------------------------------------
/src/builders.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "@angular-devkit/architect/src/builders-schema.json",
3 | "builders": {
4 | "deploy": {
5 | "implementation": "./deploy",
6 | "schema": "./deploy/schema.json",
7 | "description": "Runs any command line in the operating system."
8 | }
9 | }
10 | }
--------------------------------------------------------------------------------
/src/collection.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "@angular-devkit/schematics/collection-schema.json",
3 | "schematics": {
4 | "ng-add": {
5 | "description": "A Netlify Deploy schematic.",
6 | "factory": "./ng-add/index",
7 | "schema": "./ng-add/schema.json",
8 | "aliases": [
9 | "install"
10 | ]
11 | }
12 | }
13 | }
--------------------------------------------------------------------------------
/src/deploy/index.ts:
--------------------------------------------------------------------------------
1 | import {
2 | BuilderContext,
3 | BuilderOutput,
4 | createBuilder,
5 | } from "@angular-devkit/architect";
6 | import { json } from "@angular-devkit/core";
7 | import { Schema } from "./schema";
8 | const NetlifyAPI = require("netlify");
9 |
10 | export default createBuilder(
11 | async (
12 | builderConfig: Schema,
13 | context: BuilderContext
14 | ): Promise => {
15 | context.reportStatus(`Executing deploy...`);
16 | context.logger.info(`Executing netlify deploy command ...... `);
17 |
18 | if (builderConfig.noBuild) {
19 | context.logger.info(`📦 Skipping build`);
20 | } else {
21 | const configuration = builderConfig.configuration || "production";
22 |
23 | const withDeps = {
24 | ...{ withDeps: builderConfig.withDeps },
25 | };
26 |
27 | let overrides: any = {
28 | // this is an example how to override the workspace set of options
29 | ...(builderConfig.baseHref && {
30 | baseHref: builderConfig.baseHref,
31 | }),
32 | };
33 |
34 | if (builderConfig.withDeps) {
35 | overrides = {
36 | ...(builderConfig.baseHref && {
37 | baseHref: builderConfig.baseHref,
38 | }),
39 | withDeps: builderConfig.withDeps,
40 | };
41 | }
42 |
43 | if (!context.target) {
44 | throw new Error(
45 | "Cannot build the application without a target"
46 | );
47 | }
48 |
49 | const baseHref = builderConfig.baseHref
50 | ? `Your base-href: "${builderConfig.baseHref}`
51 | : "";
52 | const buildTarget = builderConfig.buildTarget
53 | ? builderConfig.buildTarget
54 | : "build";
55 | context.logger.info(
56 | `📦 Building "${context.target.project}". Configuration: "${configuration}". Build Command: ${buildTarget}. ${baseHref}`
57 | );
58 |
59 | const build = await context.scheduleTarget(
60 | {
61 | target: buildTarget,
62 | project: context.target.project || "",
63 | configuration,
64 | },
65 | overrides as json.JsonObject
66 | );
67 |
68 | const buildResult = await build.result;
69 |
70 | if (buildResult.success !== true) {
71 | context.logger.error(`❌ Application build failed`);
72 | return {
73 | error: `❌ Application build failed`,
74 | success: false,
75 | };
76 | }
77 |
78 | context.logger.info(`✔ Build Completed`);
79 | }
80 |
81 | const netlifyToken =
82 | process.env.NETLIFY_TOKEN || builderConfig.netlifyToken;
83 | if (netlifyToken === "" || netlifyToken === undefined) {
84 | context.logger.error("🚨 Netlify Token not found !");
85 | return { success: false };
86 | }
87 |
88 | let siteId = process.env.NETLIFY_API_ID || builderConfig.siteId;
89 | if (siteId === "" || siteId === undefined) {
90 | // site id is needed if the create option is false
91 | if (builderConfig.create === false) {
92 | context.logger.error("🚨 API ID (Site ID) not found !");
93 | return { success: false };
94 | }
95 | }
96 |
97 | const client = new NetlifyAPI(netlifyToken, {
98 | userAgent: "netlify/js-client",
99 | scheme: "https",
100 | host: "api.netlify.com",
101 | pathPrefix: "/api/v1",
102 | globalParams: {},
103 | });
104 |
105 | // let check if the site exists
106 | let site;
107 | try {
108 | // only when the site id is set
109 | if (siteId) {
110 | site = await client.getSite({ site_id: siteId });
111 | }
112 | } catch (e) {
113 | switch (e.status) {
114 | case 404:
115 | context.logger.error(`❌ Site "${siteId}" : Not found`);
116 | // if the create is false - just return the error
117 | if (builderConfig.create !== true) {
118 | return {
119 | success: false,
120 | };
121 | }
122 | break;
123 | case 401:
124 | context.logger.fatal("🚨 Netlify: Unauthorized Token");
125 | return {
126 | success: false,
127 | };
128 | default:
129 | // for all other errors
130 | return {
131 | error: e.message,
132 | success: false,
133 | };
134 | }
135 | }
136 |
137 | // lets create the site
138 | if (!site && builderConfig.create) {
139 | try {
140 | context.logger.info(`Creating new site for the application`);
141 | site = await client.createSite();
142 | siteId = site.id as string;
143 | context.logger.info(
144 | `✔ Site "${site.name}" (${siteId}) created. Please update the angular.json so on the next run we can re-deploy on the same site`
145 | );
146 | } catch (e) {
147 | context.logger.error("🚨 Unable to create the site");
148 | return {
149 | error: e.message,
150 | success: false,
151 | };
152 | }
153 | }
154 |
155 | // if we still don't have the site return with error
156 | if (!site) {
157 | context.logger.error(
158 | "🚨 Unable to deploy as we don't have any context about the site"
159 | );
160 | return {
161 | error: "🚨 Unable to deploy as we don't have any context about the site",
162 | success: false,
163 | };
164 | }
165 |
166 | // lets deploy the application to the site
167 | try {
168 | context.logger.info(
169 | `Deploying project from 📂 ./${builderConfig.outputPath}`
170 | );
171 |
172 | let config = {};
173 |
174 | if (builderConfig.functionsPath) {
175 | console.log(
176 | `Deploying functions from 📂 ./${builderConfig.functionsPath}`
177 | );
178 | config = { ...config, fnDir: builderConfig.functionsPath };
179 | }
180 |
181 | const response = await client.deploy(
182 | siteId,
183 | builderConfig.outputPath,
184 | config
185 | );
186 | context.logger.info(
187 | `✔ Your updated site 🕸 is running at ${response.deploy.ssl_url}`
188 | );
189 | return { success: true };
190 | } catch (e) {
191 | context.logger.error(`❌ Deployment failed: ${e.message}`);
192 | return {
193 | error: e.message,
194 | success: false,
195 | };
196 | }
197 | }
198 | );
199 |
--------------------------------------------------------------------------------
/src/deploy/schema.d.ts:
--------------------------------------------------------------------------------
1 | export interface Schema {
2 | buildTarget?: string;
3 | configuration?: string;
4 | noBuild?: boolean;
5 | outputPath?: boolean;
6 | functionsPath?: boolean;
7 | netlifyToken?: string;
8 | siteId?: string;
9 | baseHref?: string;
10 | create?: boolean;
11 | withDeps?: boolean;
12 | }
13 |
--------------------------------------------------------------------------------
/src/deploy/schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "$id": "Schema",
3 | "title": "schema",
4 | "description": "Deployment of Angular CLI applications to Netlify",
5 | "properties": {
6 | "buildTarget": {
7 | "type": "string",
8 | "default": "build",
9 | "description": "A build target command."
10 | },
11 | "configuration": {
12 | "type": "string",
13 | "default": "production",
14 | "description": "A named build target, as specified in the `configurations` section of angular.json. Each named target is accompanied by a configuration of option defaults for that target. Same as `ng build --configuration=XXX`.",
15 | "alias": "c"
16 | },
17 | "noBuild": {
18 | "type": "boolean",
19 | "default": false,
20 | "description": "Skip build process during deployment."
21 | },
22 | "outputPath": {
23 | "type": "string",
24 | "description": "This is one of the options you can freely choose according to your needs. --- We will 'deploy' to this folder."
25 | },
26 | "functionsPath": {
27 | "type": "string",
28 | "description": "Path to the functions folder you want to deploy"
29 | },
30 | "netlifyToken": {
31 | "type": "string",
32 | "description": "Acess token give you the ability to communicate with netlify over API."
33 | },
34 | "siteId": {
35 | "type": "string",
36 | "description": "Every netlify app have a API ID which uniquly identify that app."
37 | },
38 | "baseHref": {
39 | "type": "string",
40 | "description": "This is an example how to override the workspace set of options. --- Base url for the application being built. Same as `ng build --base-href=/XXX/`."
41 | },
42 | "create": {
43 | "type": "boolean",
44 | "default": false,
45 | "description": "Creates the site if it does not exists or no site id is set"
46 | },
47 | "withDeps": {
48 | "type": "boolean",
49 | "default": false,
50 | "description": "To be used with Nx if app needs to be built with-deps"
51 | }
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | export * from './ng-add';
2 | export * from './deploy';
--------------------------------------------------------------------------------
/src/interfaces.ts:
--------------------------------------------------------------------------------
1 |
2 | export interface WorkspaceProject {
3 | projectType?: string;
4 | architect?: Record<
5 | string,
6 | { builder: string; options?: Record }
7 | >;
8 | }
9 |
10 | export interface Workspace {
11 | defaultProject?: string;
12 | projects: Record;
13 | }
14 |
--------------------------------------------------------------------------------
/src/ng-add/index.ts:
--------------------------------------------------------------------------------
1 | import { Rule, SchematicContext, SchematicsException, Tree, chain } from '@angular-devkit/schematics';
2 | import { JsonParseMode, parseJson } from '@angular-devkit/core';
3 | import { Workspace } from '../interfaces';
4 |
5 | function getWorkspace(host: Tree): { path: string; workspace: Workspace } {
6 | const possibleFiles = ['/angular.json', './angular.json'];
7 | const path = possibleFiles.find(path => host.exists(path));
8 | const configBuffer = path ? host.read(path) : undefined;
9 |
10 | if (!path || !configBuffer) {
11 | throw new SchematicsException(`Could not find angular.json`);
12 | }
13 |
14 | const content = configBuffer.toString();
15 | let workspace: Workspace;
16 |
17 | try {
18 | workspace = (parseJson(content, JsonParseMode.Loose) as {}) as Workspace;
19 | } catch (e) {
20 | throw new SchematicsException(`Could not parse angular.json: ${e.message}`);
21 | }
22 |
23 | return { path, workspace };
24 | }
25 |
26 | interface NgAddOptions {
27 | project?: string;
28 | siteID: string;
29 | netlifyToken: string;
30 | }
31 |
32 | export function netlifyBuilder(options: NgAddOptions): Rule {
33 | return (tree: Tree, _context: SchematicContext) => {
34 | // get the workspace details
35 | const { path: workspacePath, workspace } = getWorkspace(tree);
36 |
37 | // getting project name
38 | if (!options.project) {
39 | if (workspace.defaultProject) {
40 | options.project = workspace.defaultProject;
41 | } else {
42 | throw new SchematicsException(
43 | 'No Angular project selected and no default project in the workspace'
44 | );
45 | }
46 | }
47 |
48 | // Validating project name
49 | const project = workspace.projects[options.project];
50 | if (!project) {
51 | throw new SchematicsException(
52 | 'The specified Angular project is not defined in this workspace'
53 | );
54 | }
55 |
56 | // Checking if it is application
57 | if (project.projectType !== 'application') {
58 | throw new SchematicsException(
59 | `Deploy requires an Angular project type of "application" in angular.json`
60 | );
61 | }
62 |
63 | // Getting output path from Angular.json
64 | if (
65 | !project.architect ||
66 | !project.architect.build ||
67 | !project.architect.build.options ||
68 | !project.architect.build.options.outputPath
69 | ) {
70 | throw new SchematicsException(
71 | `Cannot read the output path(architect.build.options.outputPath) of the Angular project "${options.project}" in angular.json`
72 | );
73 | }
74 |
75 | // adding deploy statement for builder
76 | project.architect['deploy'] = {
77 | "builder": "@netlify-builder/deploy:deploy",
78 | "options": {
79 | "outputPath": project.architect.build.options.outputPath,
80 | "netlifyToken": options.netlifyToken,
81 | "siteId": options.siteID,
82 | }
83 | }
84 |
85 | tree.overwrite(workspacePath, JSON.stringify(workspace, null, 2));
86 | return tree;
87 | };
88 | }
89 |
90 | export default function (options: NgAddOptions): Rule {
91 | return chain([
92 | netlifyBuilder(options),
93 | ]);
94 | }
--------------------------------------------------------------------------------
/src/ng-add/schema.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "http://json-schema.org/schema",
3 | "$id": "netlify-builder-deploy-ng-add",
4 | "title": "Netlify Builder ng-add schematic",
5 | "type": "object",
6 | "properties": {
7 | "project": {
8 | "type": "string",
9 | "description": "The name of the project.",
10 | "$default": {
11 | "$source": "projectName"
12 | }
13 | },
14 | "siteID": {
15 | "type": "string",
16 | "description": "You can find the Site ID on Netlify Settings/General",
17 | "x-prompt": "API ID( Site ID ) of Netlify project (optional)"
18 | },
19 | "netlifyToken": {
20 | "type": "string",
21 | "description": "You can create a new API for free !",
22 | "x-prompt": "Personal Access Tokens of Netlify Account (required)"
23 | }
24 | },
25 | "required": ["netlifyToken"]
26 | }
27 |
--------------------------------------------------------------------------------
/src/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "@netlify-builder/deploy",
3 | "version": "5.0.0",
4 | "description": "A Netlify builder schematics for deployment",
5 | "main": "index.js",
6 | "builders": "./builders.json",
7 | "schematics": "./collection.json",
8 | "ng-add": {
9 | "save": "devDependencies"
10 | },
11 | "repository": {
12 | "type": "git",
13 | "url": "git+https://github.com/santoshyadav198613/netlify-builder.git"
14 | },
15 | "scripts": {
16 | "build": "tsc -p tsconfig.json",
17 | "test": "ts-node node_modules/jasmine/bin/jasmine command/index_spec.ts"
18 | },
19 | "keywords": [
20 | "angular",
21 | "schematics",
22 | "cli",
23 | "angular-cli",
24 | "netlify",
25 | "deploy",
26 | "ng deploy",
27 | "ng-deploy",
28 | "netlify deploy",
29 | "netlify-deploy"
30 | ],
31 | "author": "Santosh Yadav ",
32 | "contributors": [
33 | "Nitish Kumar Singh (https://nitishk72.github.io)",
34 | "Imran Momin "
35 | ],
36 | "license": "MIT",
37 | "bugs": {
38 | "url": "https://github.com/santoshyadav198613/netlify-builder/issues"
39 | },
40 | "homepage": "https://github.com/santoshyadav198613/netlify-builder#readme",
41 | "devDependencies": {
42 | "@types/jasmine": "3.7.6",
43 | "@types/node": "14.17.1",
44 | "jasmine": "3.7.0",
45 | "jasmine-node": "3.0.0",
46 | "ts-node": "10.0.0",
47 | "typescript": "4.3.2"
48 | },
49 | "dependencies": {
50 | "@angular-devkit/architect": "^0.1200.0",
51 | "@angular-devkit/core": "^12.0.0",
52 | "@angular-devkit/schematics": "^12.0.0",
53 | "netlify": "^6.1.1"
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/src/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "moduleResolution": "node",
4 | "module": "commonjs",
5 | "target": "es2015",
6 | "lib": [
7 | "es2015",
8 | "dom",
9 | "es2015.promise",
10 | "es2015.collection",
11 | "es2015.iterable"
12 | ],
13 | "strict": true,
14 | "allowSyntheticDefaultImports": true,
15 | "suppressImplicitAnyIndexErrors": true,
16 | "forceConsistentCasingInFileNames": true,
17 | "strictPropertyInitialization": false,
18 | "strictNullChecks": true,
19 | "sourceMap": true,
20 | "declaration": false,
21 | "inlineSources": true,
22 | "stripInternal": true,
23 | "skipLibCheck": true,
24 | "noImplicitAny": false,
25 | "esModuleInterop": true
26 | },
27 | "exclude": [
28 | "node_modules"
29 | ],
30 | "compileOnSave": false,
31 | "buildOnSave": false,
32 | "angularCompilerOptions": {
33 | "skipTemplateCodegen": true,
34 | "strictMetadataEmit": true,
35 | "enableSummariesForJit": false
36 | }
37 | }
--------------------------------------------------------------------------------