@react-foundry/app-plop-pack 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/README.md +53 -0
- package/package.json +30 -0
- package/skel/.github/workflows/deploy.deploy.yml.hbs +32 -0
- package/skel/src/app/routes/page.htm.hbs +20 -0
- package/skel/src/app/routes/page.md.hbs +31 -0
- package/skel/src/app/routes/page.mdx.hbs +42 -0
- package/skel/src/app/routes/page.tsx.hbs +136 -0
- package/src/index.js +159 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (C) 2019-2025 Crown Copyright
|
|
4
|
+
Copyright (C) 2019-2026 Daniel A.C. Martin
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
7
|
+
this software and associated documentation files (the "Software"), to deal in
|
|
8
|
+
the Software without restriction, including without limitation the rights to
|
|
9
|
+
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
10
|
+
of the Software, and to permit persons to whom the Software is furnished to do
|
|
11
|
+
so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
React Foundry - Application plop-pack
|
|
2
|
+
=====================================
|
|
3
|
+
|
|
4
|
+
Generators for use within applications and prototypes.
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
Using this package
|
|
8
|
+
------------------
|
|
9
|
+
|
|
10
|
+
First install the package into your project:
|
|
11
|
+
|
|
12
|
+
```shell
|
|
13
|
+
npm install -D @react-foundry/app-plop-pack
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
Then use it in your `plopfile.js` as follows:
|
|
17
|
+
|
|
18
|
+
```js
|
|
19
|
+
module.exports = plop => {
|
|
20
|
+
plop.load('@react-foundry/app-plop-pack');
|
|
21
|
+
|
|
22
|
+
// ...
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
Working on this package
|
|
28
|
+
-----------------------
|
|
29
|
+
|
|
30
|
+
Before working on this package you must install its dependencies using
|
|
31
|
+
the following command:
|
|
32
|
+
|
|
33
|
+
```shell
|
|
34
|
+
pnpm install
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
### Building
|
|
39
|
+
|
|
40
|
+
Build the package by compiling the source code.
|
|
41
|
+
|
|
42
|
+
```shell
|
|
43
|
+
npm run build
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
### Clean-up
|
|
48
|
+
|
|
49
|
+
Remove any previously built files.
|
|
50
|
+
|
|
51
|
+
```shell
|
|
52
|
+
npm run clean
|
|
53
|
+
```
|
package/package.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@react-foundry/app-plop-pack",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Generators for use within applications and prototypes.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "src/index.js",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./src/index.js"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"/src",
|
|
12
|
+
"/skel"
|
|
13
|
+
],
|
|
14
|
+
"author": "Daniel A.C. Martin <npm@daniel-martin.co.uk> (http://daniel-martin.co.uk/)",
|
|
15
|
+
"license": "MIT",
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=12.0.0"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"plop": "4.0.5"
|
|
21
|
+
},
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@react-foundry/plop-pack": "^0.1.0"
|
|
24
|
+
},
|
|
25
|
+
"scripts": {
|
|
26
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
27
|
+
"build": "true",
|
|
28
|
+
"clean": "true"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
{{#if standalone}}
|
|
2
|
+
deploy-to-{{{ target }}}:
|
|
3
|
+
name: Deploy to {{{ titleCase target }}}
|
|
4
|
+
{{else}}
|
|
5
|
+
deploy-{{{ appName }}}-to-{{{ target }}}:
|
|
6
|
+
name: Deploy {{{ appName }}} to {{{ titleCase target }}}
|
|
7
|
+
{{/if}}
|
|
8
|
+
{{#if (eq target 'netlify')}}
|
|
9
|
+
if: github.event_name == 'push'
|
|
10
|
+
{{else}}
|
|
11
|
+
if: github.event_name == 'push' && github.ref == 'refs/heads/{{{ branch }}}'
|
|
12
|
+
{{/if}}
|
|
13
|
+
uses: './.github/workflows/deploy-to-{{{ target }}}.yml'
|
|
14
|
+
with:
|
|
15
|
+
{{#unless standalone}}
|
|
16
|
+
app: {{{ appName }}}
|
|
17
|
+
{{/unless}}
|
|
18
|
+
node: 12
|
|
19
|
+
{{#if (eq target 'netlify')}}
|
|
20
|
+
production-branch: {{{ branch }}}
|
|
21
|
+
{{/if}}
|
|
22
|
+
secrets:
|
|
23
|
+
CYPRESS_PROJECT_ID: $\{{ secrets.CYPRESS_PROJECT_ID }}
|
|
24
|
+
CYPRESS_RECORD_KEY: $\{{ secrets.CYPRESS_RECORD_KEY }}
|
|
25
|
+
{{#if (eq target 'netlify')}}
|
|
26
|
+
NETLIFY_AUTH_TOKEN: $\{{ secrets.{{{ authSecret }}} }}
|
|
27
|
+
NETLIFY_SITE_ID: $\{{ secrets.{{{ siteSecret }}} }}
|
|
28
|
+
{{else if (eq target 'heroku')}}
|
|
29
|
+
HEROKU_API_KEY: $\{{ secrets.{{{ authSecret }}} }}
|
|
30
|
+
HEROKU_APP_NAME: $\{{ secrets.{{{ siteSecret }}} }}
|
|
31
|
+
HEROKU_EMAIL: $\{{ secrets.{{{ usernameSecret }}} }}
|
|
32
|
+
{{/if}}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
<h1>{{ title }}</h1>
|
|
2
|
+
{{#if description}}
|
|
3
|
+
<p>{{ description }}</p>
|
|
4
|
+
{{/if}}
|
|
5
|
+
{{#if userinfo}}
|
|
6
|
+
<h1>Accessing userinfo</h1>
|
|
7
|
+
<p>Sorry, there is no way to access user info from an HTML page. You will need to use React for that.</p>
|
|
8
|
+
{{/if}}
|
|
9
|
+
{{#if query}}
|
|
10
|
+
<h1>Accessing query parameters</h1>
|
|
11
|
+
<p>Sorry, there is no way to access query parameters from an HTML page. You will need to use React for that.</p>
|
|
12
|
+
{{/if}}
|
|
13
|
+
{{#if data}}
|
|
14
|
+
<h1>Loading data form the server</h1>
|
|
15
|
+
<p>Sorry, there is no way to load data into HTML page. You will need to use React for that.</p>
|
|
16
|
+
{{/if}}
|
|
17
|
+
{{#if action}}
|
|
18
|
+
<h1>Writing data to the server</h1>
|
|
19
|
+
<p>Sorry, there is no way to write data with an HTML page. You will need to use React for that.</p>
|
|
20
|
+
{{/if}}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
{{ title }}
|
|
2
|
+
===========
|
|
3
|
+
|
|
4
|
+
{{#if description}}
|
|
5
|
+
{{ description }}
|
|
6
|
+
{{/if}}
|
|
7
|
+
|
|
8
|
+
{{#if userinfo}}
|
|
9
|
+
## Accessing userinfo
|
|
10
|
+
|
|
11
|
+
Sorry, there is no way to access user info from an HTML page. You will need to use React for that.
|
|
12
|
+
|
|
13
|
+
{{/if}}
|
|
14
|
+
{{#if query}}
|
|
15
|
+
## Accessing query parameters
|
|
16
|
+
|
|
17
|
+
Sorry, there is no way to access query parameters from an HTML page. You will need to use React for that.
|
|
18
|
+
|
|
19
|
+
{{/if}}
|
|
20
|
+
{{#if data}}
|
|
21
|
+
## Loading data form the server
|
|
22
|
+
|
|
23
|
+
Sorry, there is no way to load data into HTML page. You will need to use React for that.
|
|
24
|
+
|
|
25
|
+
{{/if}}
|
|
26
|
+
{{#if action}}
|
|
27
|
+
## Writing data to the server
|
|
28
|
+
|
|
29
|
+
Sorry, there is no way to write data with an HTML page. You will need to use React for that.
|
|
30
|
+
|
|
31
|
+
{{/if}}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { siteTitle } from '../config';
|
|
2
|
+
|
|
3
|
+
export const title = '{{{title}}}';
|
|
4
|
+
export const description = '{{{description}}}';
|
|
5
|
+
|
|
6
|
+
export function meta({}) {
|
|
7
|
+
return [
|
|
8
|
+
{ title: `${title} - ${siteTitle}` },
|
|
9
|
+
{ name: 'description', content: description },
|
|
10
|
+
{ name: 'og:title', content: title },
|
|
11
|
+
{ name: 'og:description', content: description },
|
|
12
|
+
];
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
# {title}
|
|
16
|
+
|
|
17
|
+
{description}
|
|
18
|
+
|
|
19
|
+
{{#if userinfo}}
|
|
20
|
+
## Accessing userinfo
|
|
21
|
+
|
|
22
|
+
Sorry, there is no way to access user info from an HTML page. You will need to use React for that.
|
|
23
|
+
|
|
24
|
+
{{/if}}
|
|
25
|
+
{{#if query}}
|
|
26
|
+
## Accessing query parameters
|
|
27
|
+
|
|
28
|
+
Sorry, there is no way to access query parameters from an HTML page. You will need to use React for that.
|
|
29
|
+
|
|
30
|
+
{{/if}}
|
|
31
|
+
{{#if data}}
|
|
32
|
+
## Loading data form the server
|
|
33
|
+
|
|
34
|
+
Sorry, there is no way to load data into HTML page. You will need to use React for that.
|
|
35
|
+
|
|
36
|
+
{{/if}}
|
|
37
|
+
{{#if action}}
|
|
38
|
+
## Writing data to the server
|
|
39
|
+
|
|
40
|
+
Sorry, there is no way to write data with an HTML page. You will need to use React for that.
|
|
41
|
+
|
|
42
|
+
{{/if}}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
{{#if param}}
|
|
2
|
+
import type { Route } from "./+types/{{{name}}}.${{{param}}}";
|
|
3
|
+
{{else}}
|
|
4
|
+
import type { Route } from "./+types/{{{name}}}";
|
|
5
|
+
{{/if}}
|
|
6
|
+
{{#if data}}
|
|
7
|
+
import { data } from 'react-router';
|
|
8
|
+
{{/if}}
|
|
9
|
+
{{#if query}}
|
|
10
|
+
import { useLocation } from '@react-foundry/router';
|
|
11
|
+
{{/if}}
|
|
12
|
+
{{#if userinfo}}
|
|
13
|
+
{{#if data}}
|
|
14
|
+
import { userInfoContext } from '@react-foundry/react-router-context';
|
|
15
|
+
{{/if}}
|
|
16
|
+
import { useUserInfo } from '@react-foundry/user-info';
|
|
17
|
+
{{/if}}
|
|
18
|
+
import { siteTitle } from '../config';
|
|
19
|
+
|
|
20
|
+
export const title = '{{{title}}}';
|
|
21
|
+
const description = '{{{description}}}';
|
|
22
|
+
|
|
23
|
+
export function meta({}: Route.MetaArgs) {
|
|
24
|
+
return [
|
|
25
|
+
{ title: `${title} - ${siteTitle}` },
|
|
26
|
+
{ name: 'description', content: description },
|
|
27
|
+
{ name: 'og:title', content: title },
|
|
28
|
+
{ name: 'og:description', content: description },
|
|
29
|
+
];
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
{{#if data}}
|
|
33
|
+
export async function loader({
|
|
34
|
+
{{#if userinfo}}
|
|
35
|
+
context,
|
|
36
|
+
{{/if}}
|
|
37
|
+
{{#if param}}
|
|
38
|
+
params,
|
|
39
|
+
{{/if}}
|
|
40
|
+
}: Route.LoaderArgs) {
|
|
41
|
+
let error: string = '';
|
|
42
|
+
|
|
43
|
+
const Redact = <T = unknown>(roles: string[]) => (obj: Record<string, T>) => (key: string, role: string) => {
|
|
44
|
+
if (!roles.includes(role)) {
|
|
45
|
+
error = `You do not have permission to access the property '${key}' on this object.`
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return obj[key];
|
|
49
|
+
};
|
|
50
|
+
const user = context.get(userInfoContext);
|
|
51
|
+
const redactor = Redact<string>(user?.roles || []);
|
|
52
|
+
|
|
53
|
+
// Some fake data
|
|
54
|
+
const bookData: Book[] = [
|
|
55
|
+
{
|
|
56
|
+
title: "Harry Potter and the Sorcerer's stone",
|
|
57
|
+
author: 'J.K. Rowling',
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
title: 'Jurassic Park',
|
|
61
|
+
author: 'Michael Crichton',
|
|
62
|
+
},
|
|
63
|
+
];
|
|
64
|
+
const books: Book[] = bookData.map(e => {
|
|
65
|
+
const redact = redactor(e);
|
|
66
|
+
|
|
67
|
+
return {
|
|
68
|
+
title: redact('title', 'books.title'),
|
|
69
|
+
author: redact('author', 'books.author')
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
return (
|
|
74
|
+
error
|
|
75
|
+
? data({ error }, 403)
|
|
76
|
+
: data({ books })
|
|
77
|
+
);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
{{/if}}
|
|
81
|
+
{{#if action}}
|
|
82
|
+
export async function action({
|
|
83
|
+
{{#if userinfo}}
|
|
84
|
+
context,
|
|
85
|
+
{{/if}}
|
|
86
|
+
{{#if param}}
|
|
87
|
+
params,
|
|
88
|
+
{{/if}}
|
|
89
|
+
request,
|
|
90
|
+
}: Route.ActionArgs) {
|
|
91
|
+
{{#if userinfo}}
|
|
92
|
+
const user = context.get(userInfoContext);
|
|
93
|
+
{{/if}}
|
|
94
|
+
const formData = await request.formData();
|
|
95
|
+
|
|
96
|
+
return {
|
|
97
|
+
result: !!(formData.get('feedback')),
|
|
98
|
+
formData: Object.fromEntries(formData)
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
{{/if}}
|
|
103
|
+
export default function {{{properCase title}}}({
|
|
104
|
+
{{#if action}}
|
|
105
|
+
actionData,
|
|
106
|
+
{{/if}}
|
|
107
|
+
{{#if data}}
|
|
108
|
+
loaderData,
|
|
109
|
+
{{/if}}
|
|
110
|
+
}: Route.ComponentProps) {
|
|
111
|
+
{{#if userinfo}}
|
|
112
|
+
const { displayName, name } = useUserInfo() || {};
|
|
113
|
+
const { givenName } = name || {};
|
|
114
|
+
const user = displayName || givenName || 'Guest';
|
|
115
|
+
{{/if}}
|
|
116
|
+
{{#if query}}
|
|
117
|
+
const location = useLocation();
|
|
118
|
+
const n = Number(location.query['n']) || 0;
|
|
119
|
+
{{/if}}
|
|
120
|
+
|
|
121
|
+
return (
|
|
122
|
+
<>
|
|
123
|
+
<h1>{title}</h1>
|
|
124
|
+
<p>{description}</p>
|
|
125
|
+
{{#if userinfo}}
|
|
126
|
+
<h2>Accessing user info</h2>
|
|
127
|
+
<p>Hello {user}!</p>
|
|
128
|
+
{{/if}}
|
|
129
|
+
{{#if query}}
|
|
130
|
+
<h2>Accessing query parameters</h2>
|
|
131
|
+
<p>n = {n}</p>
|
|
132
|
+
<p><a href={`/{{{ name }}}?n=${n + 1}`}>Next</a></p>
|
|
133
|
+
{{/if}}
|
|
134
|
+
</>
|
|
135
|
+
);
|
|
136
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { createRequire } from 'node:module';
|
|
2
|
+
import { dirname, resolve } from 'node:path';
|
|
3
|
+
import { fileURLToPath } from 'node:url';
|
|
4
|
+
|
|
5
|
+
const require = createRequire(import.meta.url);
|
|
6
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
|
|
8
|
+
const plopPackInternal = require.resolve('@react-foundry/plop-pack');
|
|
9
|
+
|
|
10
|
+
const id = v => v;
|
|
11
|
+
|
|
12
|
+
const longToShort = (name) => (
|
|
13
|
+
name
|
|
14
|
+
.toLowerCase()
|
|
15
|
+
.replace(/\s/g, '-')
|
|
16
|
+
);
|
|
17
|
+
|
|
18
|
+
const constantCase = (str) => (
|
|
19
|
+
str
|
|
20
|
+
.toUpperCase()
|
|
21
|
+
.replace(/[-\s]/g, '_')
|
|
22
|
+
);
|
|
23
|
+
|
|
24
|
+
const plopFunction = async (plop) => {
|
|
25
|
+
await plop.load(plopPackInternal, undefined, { actionTypes: true, generators: false, helpers: true, partials: false });
|
|
26
|
+
|
|
27
|
+
const notHtml = answers => answers.ext !== 'html';
|
|
28
|
+
|
|
29
|
+
plop.setGenerator('page', {
|
|
30
|
+
description: 'A new page on the website',
|
|
31
|
+
prompts: [
|
|
32
|
+
{
|
|
33
|
+
type: 'list',
|
|
34
|
+
name: 'ext',
|
|
35
|
+
message: 'Type of page:',
|
|
36
|
+
choices: [
|
|
37
|
+
{ value: 'htm', name: 'HTML (simple)' },
|
|
38
|
+
{ value: 'md', name: 'Markdown (simple)' },
|
|
39
|
+
{ value: 'mdx', name: 'MDX: Markdown with JSX (intermediate)' },
|
|
40
|
+
//{ value: 'rt', name: 'React template (experimental)' },
|
|
41
|
+
{ value: 'tsx', name: 'TSX (advanced)' }
|
|
42
|
+
],
|
|
43
|
+
default: 3
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
type: 'input',
|
|
47
|
+
name: 'title',
|
|
48
|
+
message: 'Title (e.g. "My page"):'
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
type: 'input',
|
|
52
|
+
name: 'name',
|
|
53
|
+
message: 'Short name (e.g. "my-page"):',
|
|
54
|
+
default: answers => longToShort(answers.title)
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
type: 'input',
|
|
58
|
+
name: 'description',
|
|
59
|
+
message: 'Description:',
|
|
60
|
+
when: notHtml
|
|
61
|
+
},
|
|
62
|
+
{
|
|
63
|
+
type: 'confirm',
|
|
64
|
+
name: 'query',
|
|
65
|
+
message: 'Include example of accessing query parameters?:',
|
|
66
|
+
default: false,
|
|
67
|
+
when: notHtml
|
|
68
|
+
}
|
|
69
|
+
],
|
|
70
|
+
actions: [
|
|
71
|
+
{
|
|
72
|
+
type: 'add',
|
|
73
|
+
path: 'src/app/routes/{{{name}}}.{{{ext}}}',
|
|
74
|
+
templateFile: '../skel/src/app/routes/page.{{{ext}}}.hbs'
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
type: 'message',
|
|
78
|
+
content: '\n\nPage created at: /{{{ name }}}\nTo modify, edit: ./src/common/pages/{{{ name }}}.{{{ ext }}}\n(You may need to refresh your browser of even restart the application in order to see it.)'
|
|
79
|
+
}
|
|
80
|
+
]
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
const pkg = require(resolve(process.cwd(), './package.json'));
|
|
84
|
+
const nameArray = pkg.name.split('/');
|
|
85
|
+
const standalone = nameArray.length === 1;
|
|
86
|
+
const appName = nameArray.pop();
|
|
87
|
+
const [ to, gitRoot, appDir, secretSuffix ] = (
|
|
88
|
+
standalone
|
|
89
|
+
? [ 'to', './', './', '' ]
|
|
90
|
+
: [`${appName}-to`, '../../', `./apps/${appName}/`, `_${constantCase(appName)}` ]
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
plop.setGenerator('deployment', {
|
|
94
|
+
description: 'A new deployment pipeline',
|
|
95
|
+
prompts: [
|
|
96
|
+
{
|
|
97
|
+
type: 'list',
|
|
98
|
+
name: 'target',
|
|
99
|
+
message: 'Where do you want to deploy?:',
|
|
100
|
+
choices: [
|
|
101
|
+
{ value: 'heroku', name: 'Heroku' },
|
|
102
|
+
{ value: 'netlify', name: 'Netlify' }
|
|
103
|
+
]
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
type: 'input',
|
|
107
|
+
name: 'branch',
|
|
108
|
+
message: 'Which branch would you like to deploy?:',
|
|
109
|
+
default: 'master'
|
|
110
|
+
},
|
|
111
|
+
{
|
|
112
|
+
type: 'input',
|
|
113
|
+
name: 'usernameSecret',
|
|
114
|
+
message: 'Which secret will contain your e-mail address as registered with Heroku?:',
|
|
115
|
+
default: 'HEROKU_EMAIL',
|
|
116
|
+
when: answers => answers.target === 'heroku'
|
|
117
|
+
},
|
|
118
|
+
{
|
|
119
|
+
type: 'input',
|
|
120
|
+
name: 'authSecret',
|
|
121
|
+
message: 'Which secret will contain your auth token / API key?:',
|
|
122
|
+
default: answers => (
|
|
123
|
+
answers.target === 'heroku'
|
|
124
|
+
? 'HEROKU_API_KEY'
|
|
125
|
+
: 'NETLIFY_AUTH_TOKEN'
|
|
126
|
+
)
|
|
127
|
+
},
|
|
128
|
+
{
|
|
129
|
+
type: 'input',
|
|
130
|
+
name: 'siteSecret',
|
|
131
|
+
message: 'Which secret will contain the site identifier?:',
|
|
132
|
+
default: answers => (
|
|
133
|
+
answers.target === 'heroku'
|
|
134
|
+
? `HEROKU_APP_NAME${secretSuffix}`
|
|
135
|
+
: `NETLIFY_SITE_ID${secretSuffix}`
|
|
136
|
+
)
|
|
137
|
+
}
|
|
138
|
+
],
|
|
139
|
+
actions: answers => {
|
|
140
|
+
answers.appDir = appDir;
|
|
141
|
+
answers.appName = appName;
|
|
142
|
+
answers.standalone = standalone;
|
|
143
|
+
const secrets = [answers.usernameSecret, answers.authSecret, answers.siteSecret].filter(id).join(', ');
|
|
144
|
+
|
|
145
|
+
return [
|
|
146
|
+
{
|
|
147
|
+
type: 'append',
|
|
148
|
+
path: `${gitRoot}.github/workflows/deploy.yml`,
|
|
149
|
+
templateFile: '../skel/.github/workflows/deploy.deploy.yml.hbs'
|
|
150
|
+
},
|
|
151
|
+
`Pipeline created; once you have set-up your secrets (${secrets}) in GitHub, your changes will be automatically deployed to ${answers.target} whenever to push to the ${answers.branch}.`
|
|
152
|
+
];
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
plop.setDefaultInclude({ actionTypes: true, generators: true, helpers: true });
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
export default plopFunction;
|