create-application-template 1.1.1 → 1.2.1
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/bin/create-application-template.js +72 -4
- package/ccrate/src/assets/favicon.ico +0 -0
- package/ccrate/src/assets/logo.svg +14 -0
- package/ccrate/src/components/App.spec.tsx +10 -0
- package/ccrate/src/components/App.tsx +46 -0
- package/ccrate/src/styles/Logo.styled.ts +21 -0
- package/ccrate/src/styles/theme.ts +12 -0
- package/ccrate/webpack/webpack.common.js +161 -0
- package/package.json +1 -1
- package/src/components/App.tsx +2 -2
- /package/src/assets/{cat.svg → logo.svg} +0 -0
|
@@ -29,10 +29,62 @@ const run = async () => {
|
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
const projectPaths = {
|
|
32
|
-
root:
|
|
33
|
-
get bin() { return
|
|
34
|
-
get
|
|
35
|
-
get
|
|
32
|
+
root: path.resolve('.', argv.name),
|
|
33
|
+
get bin() { return path.resolve(this.root, 'bin') },
|
|
34
|
+
get src() { return path.resolve(this.root, 'src') },
|
|
35
|
+
get ccrate() { return path.resolve(this.root, 'ccrate') },
|
|
36
|
+
get env() { return path.resolve(this.root, '.env') },
|
|
37
|
+
get packageJson() { return path.resolve(this.root, 'package.json') },
|
|
38
|
+
get subDirFiles() {
|
|
39
|
+
const src = path.resolve(this.root, 'src')
|
|
40
|
+
const assets = path.resolve(src, 'assets')
|
|
41
|
+
const styles = path.resolve(src, 'styles')
|
|
42
|
+
const components = path.resolve(src, 'components')
|
|
43
|
+
|
|
44
|
+
const srcDirs = {
|
|
45
|
+
assets: {
|
|
46
|
+
faviconIco: path.resolve(assets, 'favicon.ico'),
|
|
47
|
+
logoSvg: path.resolve(assets, 'logo.svg'),
|
|
48
|
+
},
|
|
49
|
+
components: {
|
|
50
|
+
appSpecTsx: path.resolve(components, 'App.spec.tsx'),
|
|
51
|
+
appTsx: path.resolve(components, 'App.tsx'),
|
|
52
|
+
},
|
|
53
|
+
styles: {
|
|
54
|
+
logoStyledTs: path.resolve(styles, 'Logo.styled.ts'),
|
|
55
|
+
themeTs: path.resolve(styles, 'theme.ts'),
|
|
56
|
+
},
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const webpackDirs = {
|
|
60
|
+
webpack: {
|
|
61
|
+
webpackCommonJs:
|
|
62
|
+
path.resolve(this.root, 'webpack', 'webpack.common.js'),
|
|
63
|
+
},
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const getCcratePaths = (obj) => {
|
|
67
|
+
return Object.entries(obj).reduce((acc, [key, value]) => {
|
|
68
|
+
if (typeof value === 'object' && value !== null) {
|
|
69
|
+
acc[key] = getCcratePaths(value)
|
|
70
|
+
} else if (typeof value === 'string') {
|
|
71
|
+
acc[key] = value
|
|
72
|
+
.replace(/\/src/g, '/ccrate/src')
|
|
73
|
+
.replace(/\/webpack\//g, '/ccrate/webpack/')
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return acc
|
|
77
|
+
}, {})
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
const paths = { ...srcDirs, ...webpackDirs }
|
|
81
|
+
|
|
82
|
+
return {
|
|
83
|
+
src: { ...paths },
|
|
84
|
+
ccrate: { ...getCcratePaths({ ...paths }),
|
|
85
|
+
},
|
|
86
|
+
}
|
|
87
|
+
},
|
|
36
88
|
}
|
|
37
89
|
|
|
38
90
|
const isNameDotCommand = (argv.name === '.')
|
|
@@ -54,8 +106,24 @@ const run = async () => {
|
|
|
54
106
|
if (packageJson.hasOwnProperty('repository')) delete packageJson.repository
|
|
55
107
|
if (packageJson.dependencies.hasOwnProperty('yargs')) delete packageJson.dependencies.yargs
|
|
56
108
|
|
|
109
|
+
if (argv.ccrate) {
|
|
110
|
+
console.info('Running CCrATE sequence...')
|
|
111
|
+
|
|
112
|
+
const { src, ccrate } = projectPaths.subDirFiles
|
|
113
|
+
|
|
114
|
+
execCommand(`cp ${ccrate.assets.faviconIco} ${src.assets.faviconIco}`)
|
|
115
|
+
execCommand(`cp ${ccrate.assets.logoSvg} ${src.assets.logoSvg}`)
|
|
116
|
+
execCommand(`cp ${ccrate.components.appSpecTsx} ${src.components.appSpecTsx}`)
|
|
117
|
+
execCommand(`cp ${ccrate.components.appTsx} ${src.components.appTsx}`)
|
|
118
|
+
execCommand(`cp ${ccrate.styles.logoStyledTs} ${src.styles.logoStyledTs}`)
|
|
119
|
+
execCommand(`cp ${ccrate.styles.themeTs} ${src.styles.themeTs}`)
|
|
120
|
+
|
|
121
|
+
execCommand(`cp ${ccrate.webpack.webpackCommonJs} ${src.webpack.webpackCommonJs}`)
|
|
122
|
+
}
|
|
123
|
+
|
|
57
124
|
execCommand(`rm ${projectPaths.packageJson}`)
|
|
58
125
|
execCommand(`rm -rf ${projectPaths.bin}`)
|
|
126
|
+
execCommand(`rm -rf ${projectPaths.ccrate}`)
|
|
59
127
|
|
|
60
128
|
try {
|
|
61
129
|
await writeFile(projectPaths.packageJson, JSON.stringify(packageJson, null, 2), {
|
|
Binary file
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
|
2
|
+
<svg fill="#e2b432" height="200px" width="200px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 512 512" xml:space="preserve">
|
|
3
|
+
<g id="SVGRepo_bgCarrier" stroke-width="0"/>
|
|
4
|
+
<g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"/>
|
|
5
|
+
<g id="SVGRepo_iconCarrier">
|
|
6
|
+
<path d="M478.13,203.97h-16.107v-3.259c0-15.747-12.811-28.558-28.558-28.558c-15.747,0-28.558,12.811-28.558,28.558v3.259 H107.092v-3.259c0-3.325-0.577-6.516-1.626-9.486l123.892-45.886c7.378,6.524,17.063,10.496,27.663,10.496 c12.869,0,24.395-5.847,32.072-15.021l60.754,26.415c1.325,0.575,2.704,0.849,4.061,0.849c3.937,0,7.688-2.294,9.359-6.135 c2.246-5.166-0.121-11.174-5.287-13.42l-59.994-26.084c0.558-2.72,0.852-5.536,0.852-8.418c0-19.541-13.473-35.995-31.617-40.559 V33.445c0-5.633-4.567-10.199-10.199-10.199c-5.633,0-10.199,4.566-10.199,10.199v48.956c0,5.633,4.566,10.199,10.199,10.199 c11.782,0,21.369,9.564,21.414,21.337l-14.288-6.212c-5.165-2.245-11.174,0.122-13.42,5.287 c-2.246,5.166,0.121,11.174,5.287,13.42l12.688,5.517c-3.363,2.199-7.371,3.489-11.68,3.489c-11.811,0-21.418-9.608-21.418-21.418 c0-5.633-4.566-10.199-10.199-10.199s-10.199,4.566-10.199,10.199c0,4.881,0.849,9.566,2.393,13.924L90.772,174.915 c-3.711-1.768-7.861-2.761-12.238-2.761c-15.747,0-28.558,12.811-28.558,28.558v3.259H33.87C15.194,203.97,0,219.342,0,238.236 v216.648c0,18.676,15.194,33.87,33.87,33.87H478.13c18.676,0,33.87-15.194,33.87-33.87V238.236 C512,219.342,496.806,203.97,478.13,203.97z M425.307,200.712c0-4.499,3.661-8.159,8.159-8.159c4.499,0,8.159,3.659,8.159,8.159 v3.259h-16.319V200.712z M70.375,200.712c0-4.499,3.66-8.159,8.159-8.159c4.499,0,8.159,3.659,8.159,8.159v3.259H70.375V200.712z M491.602,454.884c0,7.428-6.043,13.471-13.471,13.471H33.87c-7.428,0-13.471-6.043-13.471-13.471V238.236 c0-7.518,6.168-13.868,13.471-13.868H478.13c7.302,0,13.471,6.351,13.471,13.868V454.884z"/>
|
|
7
|
+
<path d="M93.323,253.238c-5.633,0-10.199,4.566-10.199,10.199v166.247c0,5.633,4.566,10.199,10.199,10.199 c5.633,0,10.199-4.566,10.199-10.199V263.437C103.522,257.804,98.956,253.238,93.323,253.238z"/>
|
|
8
|
+
<path d="M173.896,253.238c-5.633,0-10.199,4.566-10.199,10.199v166.247c0,5.633,4.566,10.199,10.199,10.199 s10.199-4.566,10.199-10.199V263.437C184.096,257.804,179.529,253.238,173.896,253.238z"/>
|
|
9
|
+
<path d="M255.49,253.238c-5.633,0-10.199,4.566-10.199,10.199v166.247c0,5.633,4.566,10.199,10.199,10.199 c5.632,0,10.199-4.566,10.199-10.199V263.437C265.689,257.804,261.122,253.238,255.49,253.238z"/>
|
|
10
|
+
<path d="M337.084,253.238c-5.632,0-10.199,4.566-10.199,10.199v166.247c0,5.633,4.567,10.199,10.199,10.199 s10.199-4.566,10.199-10.199V263.437C347.283,257.804,342.716,253.238,337.084,253.238z"/>
|
|
11
|
+
<path d="M418.677,253.238c-5.632,0-10.199,4.566-10.199,10.199v166.247c0,5.633,4.567,10.199,10.199,10.199 s10.199-4.566,10.199-10.199V263.437C428.877,257.804,424.309,253.238,418.677,253.238z"/>
|
|
12
|
+
<path d="M394.611,163.817l-7.068-3.061c-5.167-2.24-11.172,0.136-13.412,5.306c-2.239,5.169,0.137,11.174,5.306,13.412 l7.068,3.061c1.321,0.572,2.695,0.842,4.048,0.842c3.942,0,7.697-2.3,9.365-6.148C402.156,172.06,399.78,166.054,394.611,163.817z"/>
|
|
13
|
+
</g>
|
|
14
|
+
</svg>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { render, screen } from '@testing-library/react'
|
|
2
|
+
import 'jest-styled-components'
|
|
3
|
+
import { App } from './App'
|
|
4
|
+
|
|
5
|
+
test('renders title', () => {
|
|
6
|
+
render(<App />)
|
|
7
|
+
|
|
8
|
+
expect(screen).toMatchSnapshot()
|
|
9
|
+
expect(screen.getByText(/create containerized app template/i)).toBeInTheDocument()
|
|
10
|
+
})
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { FC } from 'react'
|
|
2
|
+
import { ThemeProvider } from 'styled-components'
|
|
3
|
+
import GlobalStyles from '../styles/Global'
|
|
4
|
+
import theme from '../styles/theme'
|
|
5
|
+
import * as app from '../styles/App.styled'
|
|
6
|
+
import { StyledLogo } from '../styles/Logo.styled'
|
|
7
|
+
import '../styles/env.css'
|
|
8
|
+
import logo from '../assets/logo.svg'
|
|
9
|
+
import { Counter } from './Counter'
|
|
10
|
+
|
|
11
|
+
export const App: FC = () => {
|
|
12
|
+
const TemplateLink: FC = () => {
|
|
13
|
+
return (
|
|
14
|
+
<app.StyledLink
|
|
15
|
+
href='https://www.npmjs.com/package/create-application-template'
|
|
16
|
+
rel='noreferrer'
|
|
17
|
+
target='_blank'
|
|
18
|
+
>
|
|
19
|
+
here
|
|
20
|
+
</app.StyledLink>
|
|
21
|
+
)
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<ThemeProvider theme={theme}>
|
|
26
|
+
<GlobalStyles />
|
|
27
|
+
<app.StyledContainer>
|
|
28
|
+
<app.StyledHeader>
|
|
29
|
+
<h1>Create Containerized App Template</h1>
|
|
30
|
+
<h2>An app template containerized via Docker!</h2>
|
|
31
|
+
<h2>Access the CCrATe template <TemplateLink />...</h2>
|
|
32
|
+
</app.StyledHeader>
|
|
33
|
+
<app.StyledSection>
|
|
34
|
+
<code className='card--env'>[NODE_ENV={process.env.NODE_ENV}]</code>
|
|
35
|
+
<code className='card--env'>[EXAMPLE={process.env.EXAMPLE}]</code>
|
|
36
|
+
</app.StyledSection>
|
|
37
|
+
<app.StyledSection>
|
|
38
|
+
<StyledLogo src={logo} alt='logo'/>
|
|
39
|
+
</app.StyledSection>
|
|
40
|
+
<app.StyledSection>
|
|
41
|
+
<Counter />
|
|
42
|
+
</app.StyledSection>
|
|
43
|
+
</app.StyledContainer>
|
|
44
|
+
</ThemeProvider>
|
|
45
|
+
)
|
|
46
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { styled, keyframes } from 'styled-components'
|
|
2
|
+
|
|
3
|
+
const logoAnimation = keyframes`
|
|
4
|
+
from {
|
|
5
|
+
transform: rotate(15deg);
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
to {
|
|
9
|
+
transform: rotate(-15deg);
|
|
10
|
+
}
|
|
11
|
+
`
|
|
12
|
+
|
|
13
|
+
export const StyledLogo = styled.img`
|
|
14
|
+
height: 240px;
|
|
15
|
+
pointer-events: none;
|
|
16
|
+
transform-origin: top;
|
|
17
|
+
|
|
18
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
19
|
+
animation: ${logoAnimation} 3.5s ease-in-out infinite alternate-reverse;
|
|
20
|
+
}
|
|
21
|
+
`
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
const fs = require('fs')
|
|
2
|
+
const HtmlWebpackPlugin = require('html-webpack-plugin')
|
|
3
|
+
const MiniCssExtractPlugin = require('mini-css-extract-plugin')
|
|
4
|
+
const Dotenv = require('dotenv-webpack')
|
|
5
|
+
const { WebpackManifestPlugin } = require('webpack-manifest-plugin')
|
|
6
|
+
const CopyPlugin = require('copy-webpack-plugin')
|
|
7
|
+
const env = require('./utilities/env')
|
|
8
|
+
const getPaths = require('./utilities/getPaths')
|
|
9
|
+
const createEnvironmentHash = require('./utilities/createEnvironmentHash')
|
|
10
|
+
const generateAssetManifest = require('./utilities/generateAssetManifest')
|
|
11
|
+
|
|
12
|
+
// styles regexps
|
|
13
|
+
const reCss = /\.css$/
|
|
14
|
+
const reCssModule = /\.module\.css$/
|
|
15
|
+
|
|
16
|
+
module.exports = (webpackEnv) => {
|
|
17
|
+
const { BUNDLER_ENV } = webpackEnv
|
|
18
|
+
const { INLINE_SIZE_LIMIT } = process.env
|
|
19
|
+
|
|
20
|
+
const paths = getPaths({ BUNDLER_ENV })
|
|
21
|
+
|
|
22
|
+
// NOTE it's preferable to isolate settings in appropriate
|
|
23
|
+
// files, but it's not always practical, hence "isProduction"
|
|
24
|
+
const isProduction = (BUNDLER_ENV === env.BUNDLER_ENV.prod)
|
|
25
|
+
const isDevelopment = (BUNDLER_ENV === env.BUNDLER_ENV.dev)
|
|
26
|
+
|
|
27
|
+
const styleLoaders = [
|
|
28
|
+
...(isProduction
|
|
29
|
+
? [{
|
|
30
|
+
loader: MiniCssExtractPlugin.loader,
|
|
31
|
+
options: {
|
|
32
|
+
// css is located in 'static/css', use publicPath
|
|
33
|
+
// to locate index.html directory relative to css
|
|
34
|
+
publicPath: '../../',
|
|
35
|
+
},
|
|
36
|
+
}]
|
|
37
|
+
: ['style-loader']
|
|
38
|
+
),
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
entry: paths.src.indexTsx,
|
|
43
|
+
resolve: {
|
|
44
|
+
// can now leave off extentions when importing
|
|
45
|
+
extensions: ['.tsx', '.jsx', '.ts', '.js'],
|
|
46
|
+
},
|
|
47
|
+
watchOptions: {
|
|
48
|
+
ignored: ['**/node_modules'],
|
|
49
|
+
},
|
|
50
|
+
module: {
|
|
51
|
+
rules: [
|
|
52
|
+
{
|
|
53
|
+
test: /\.(ts|js)x?$/,
|
|
54
|
+
exclude: /node_modules/,
|
|
55
|
+
use: [
|
|
56
|
+
{
|
|
57
|
+
loader: 'babel-loader',
|
|
58
|
+
options: {
|
|
59
|
+
plugins: [
|
|
60
|
+
// for use with ReactRefreshWebpackPlugin
|
|
61
|
+
isDevelopment
|
|
62
|
+
&& require.resolve('react-refresh/babel'),
|
|
63
|
+
].filter(Boolean),
|
|
64
|
+
cacheDirectory: true,
|
|
65
|
+
cacheCompression: false,
|
|
66
|
+
compact: isProduction,
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
],
|
|
70
|
+
},
|
|
71
|
+
{
|
|
72
|
+
test: reCss,
|
|
73
|
+
use: [...styleLoaders, 'css-loader'],
|
|
74
|
+
exclude: reCssModule,
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
test: reCssModule,
|
|
78
|
+
use: [
|
|
79
|
+
...styleLoaders,
|
|
80
|
+
{
|
|
81
|
+
loader: 'css-loader',
|
|
82
|
+
options: {
|
|
83
|
+
importLoaders: 1,
|
|
84
|
+
modules: true,
|
|
85
|
+
},
|
|
86
|
+
},
|
|
87
|
+
],
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
test: /\.(?:ico|gif|png|jpg|jpeg)$/i,
|
|
91
|
+
type: 'asset/resource',
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
test: /\.(woff(2)?|eot|ttf|otf|svg|)$/,
|
|
95
|
+
type: 'asset',
|
|
96
|
+
parser: {
|
|
97
|
+
dataUrlCondition: {
|
|
98
|
+
maxSize: parseInt(INLINE_SIZE_LIMIT || 10000),
|
|
99
|
+
},
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
],
|
|
103
|
+
},
|
|
104
|
+
output: {
|
|
105
|
+
path: paths.build,
|
|
106
|
+
pathinfo: isProduction ? false : true,
|
|
107
|
+
filename: paths.static.js.filenameJs,
|
|
108
|
+
chunkFilename: paths.static.js.chunkFilenameJs,
|
|
109
|
+
asyncChunks: true,
|
|
110
|
+
clean: true,
|
|
111
|
+
assetModuleFilename: paths.static.media.filenameExt,
|
|
112
|
+
publicPath: '', // public url of build, use in build/index.html
|
|
113
|
+
},
|
|
114
|
+
cache: { // used in development mode
|
|
115
|
+
type: 'filesystem',
|
|
116
|
+
version: createEnvironmentHash({ processEnv: process.env }),
|
|
117
|
+
cacheDirectory: paths.appWebpackCache,
|
|
118
|
+
store: 'pack',
|
|
119
|
+
buildDependencies: {
|
|
120
|
+
defaultWebpack: ['webpack/lib/'],
|
|
121
|
+
config: [__filename],
|
|
122
|
+
tsconfig: [paths.tsconfigJson, paths.jsconfigJson].filter(file =>
|
|
123
|
+
fs.existsSync(file)
|
|
124
|
+
),
|
|
125
|
+
},
|
|
126
|
+
},
|
|
127
|
+
plugins: [
|
|
128
|
+
new HtmlWebpackPlugin({
|
|
129
|
+
template: paths.src.indexHtml,
|
|
130
|
+
favicon: paths.src.assets.faviconIco,
|
|
131
|
+
title: 'Create Containerized App Template',
|
|
132
|
+
...(isProduction && {
|
|
133
|
+
minify: {
|
|
134
|
+
removeComments: true,
|
|
135
|
+
collapseWhitespace: true,
|
|
136
|
+
removeRedundantAttributes: true,
|
|
137
|
+
useShortDoctype: true,
|
|
138
|
+
removeEmptyAttributes: true,
|
|
139
|
+
removeStyleLinkTypeAttributes: true,
|
|
140
|
+
keepClosingSlash: true,
|
|
141
|
+
minifyJS: true,
|
|
142
|
+
minifyCSS: true,
|
|
143
|
+
minifyURLs: true,
|
|
144
|
+
},
|
|
145
|
+
}),
|
|
146
|
+
}),
|
|
147
|
+
new WebpackManifestPlugin({
|
|
148
|
+
fileName: 'asset-manifest.json',
|
|
149
|
+
publicPath: '/',
|
|
150
|
+
generate: generateAssetManifest,
|
|
151
|
+
}),
|
|
152
|
+
new CopyPlugin({
|
|
153
|
+
patterns: [{
|
|
154
|
+
from: paths.src.public,
|
|
155
|
+
to: paths.build,
|
|
156
|
+
}],
|
|
157
|
+
}),
|
|
158
|
+
new Dotenv(),
|
|
159
|
+
],
|
|
160
|
+
}
|
|
161
|
+
}
|
package/package.json
CHANGED
package/src/components/App.tsx
CHANGED
|
@@ -5,7 +5,7 @@ import theme from '../styles/theme'
|
|
|
5
5
|
import * as app from '../styles/App.styled'
|
|
6
6
|
import { StyledLogo } from '../styles/Logo.styled'
|
|
7
7
|
import '../styles/env.css'
|
|
8
|
-
import
|
|
8
|
+
import logo from '../assets/logo.svg'
|
|
9
9
|
import { Counter } from './Counter'
|
|
10
10
|
|
|
11
11
|
export const App: FC = () => {
|
|
@@ -35,7 +35,7 @@ export const App: FC = () => {
|
|
|
35
35
|
<code className='card--env'>[EXAMPLE={process.env.EXAMPLE}]</code>
|
|
36
36
|
</app.StyledSection>
|
|
37
37
|
<app.StyledSection>
|
|
38
|
-
<StyledLogo src={
|
|
38
|
+
<StyledLogo src={logo} alt='logo'/>
|
|
39
39
|
</app.StyledSection>
|
|
40
40
|
<app.StyledSection>
|
|
41
41
|
<Counter />
|
|
File without changes
|