@raisenow/tamaro-cli 1.0.8 → 1.0.11

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/package.json CHANGED
@@ -1,19 +1,18 @@
1
1
  {
2
2
  "name": "@raisenow/tamaro-cli",
3
- "version": "1.0.8",
3
+ "version": "1.0.11",
4
4
  "author": {
5
5
  "name": "RaiseNow",
6
6
  "email": "development@raisenow.com"
7
7
  },
8
- "main": "dist/cli.js",
8
+ "type": "module",
9
9
  "scripts": {
10
10
  "prepare": "npm run build",
11
11
  "start": "npm run dev",
12
- "dev": "npm run build -- --watch --ignore-watch .idea",
13
- "build": "tsup src/cli.ts src/webpack.config.ts --format cjs",
12
+ "build": "tsup src/cli.ts src/webpack.config.ts --clean --format esm",
13
+ "build:watch": "npm run build -- --watch --ignore-watch .idea",
14
14
  "docs": "npx -y http-server . --cors -o /readme.html",
15
- "lint": "eslint .",
16
- "lint:fix": "eslint . --fix"
15
+ "lint": "eslint . --fix && prettier --write ."
17
16
  },
18
17
  "bin": "dist/cli.js",
19
18
  "engines": {
@@ -21,83 +20,75 @@
21
20
  "npm": ">=8"
22
21
  },
23
22
  "dependencies": {
24
- "@babel/cli": "^7.16.8",
25
- "@babel/core": "^7.16.12",
26
- "@babel/plugin-proposal-decorators": "^7.16.7",
23
+ "@babel/cli": "^7.17.3",
24
+ "@babel/core": "^7.17.5",
25
+ "@babel/plugin-proposal-decorators": "^7.17.2",
27
26
  "@babel/plugin-syntax-dynamic-import": "^7.8.3",
28
- "@babel/plugin-transform-runtime": "^7.16.10",
27
+ "@babel/plugin-transform-runtime": "^7.17.0",
29
28
  "@babel/preset-env": "^7.16.11",
30
29
  "@babel/preset-react": "^7.16.7",
31
30
  "@babel/preset-typescript": "^7.16.7",
32
- "@babel/runtime-corejs3": "^7.16.8",
31
+ "@babel/runtime-corejs3": "^7.17.2",
33
32
  "@pmmmwh/react-refresh-webpack-plugin": "^0.5.4",
34
- "@statoscope/webpack-plugin": "^5.20.0",
35
- "@svgr/webpack": "^6.2.0",
33
+ "@statoscope/webpack-plugin": "^5.20.1",
34
+ "@svgr/webpack": "^6.2.1",
36
35
  "@types/columnify": "^1.5.1",
37
36
  "@types/lodash": "^4.14.178",
38
- "@types/mini-css-extract-plugin": "^2.5.1",
39
- "@types/node": "^17.0.12",
37
+ "@types/node": "^17.0.21",
40
38
  "@types/node-notifier": "^8.0.2",
41
39
  "@types/resolve-bin": "^0.4.1",
42
40
  "@types/webpack-config-utils": "^2.3.1",
43
- "@typescript-eslint/eslint-plugin": "^5.10.1",
44
- "@typescript-eslint/parser": "^5.10.1",
41
+ "@typescript-eslint/eslint-plugin": "^5.12.0",
42
+ "@typescript-eslint/parser": "^5.12.0",
45
43
  "autoprefixer": "^10.4.2",
46
44
  "babel-loader": "^8.2.3",
47
45
  "babel-plugin-lodash": "^3.3.4",
48
- "boxen": "^5.1.2",
49
- "chalk": "^4.1.2",
46
+ "chalk": "^5.0.0",
50
47
  "clean-webpack-plugin": "^4.0.0",
51
- "columnify": "^1.5.4",
52
- "commander": "^8.3.0",
53
- "copy-webpack-plugin": "^10.2.1",
54
- "core-js": "^3.20.3",
55
- "css-loader": "^6.5.1",
48
+ "columnify": "^1.6.0",
49
+ "commander": "^9.0.0",
50
+ "copy-webpack-plugin": "^10.2.4",
51
+ "core-js": "^3.21.1",
52
+ "css-loader": "^6.6.0",
56
53
  "css-minimizer-webpack-plugin": "^3.4.1",
57
- "current-script-polyfill": "^1.0.0",
58
- "dotenv": "^14.3.2",
59
- "dotenv-expand": "^6.0.1",
60
- "element-closest": "^3.0.2",
61
- "escape-string-regexp": "^4.0.0",
62
- "eslint": "^8.7.0",
63
- "eslint-config-prettier": "^8.3.0",
54
+ "dotenv": "^16.0.0",
55
+ "dotenv-expand": "^8.0.1",
56
+ "escape-string-regexp": "^5.0.0",
57
+ "eslint": "^8.9.0",
58
+ "eslint-config-prettier": "^8.4.0",
64
59
  "eslint-plugin-node": "^11.1.0",
65
- "eslint-plugin-prettier": "^4.0.0",
66
60
  "eslint-plugin-promise": "^6.0.0",
67
- "eslint-webpack-plugin": "^3.1.0",
68
- "execa": "^5.1.1",
61
+ "eslint-webpack-plugin": "^3.1.1",
62
+ "execa": "^6.1.0",
69
63
  "file-loader": "^6.2.0",
70
- "fork-ts-checker-webpack-plugin": "^6.5.0",
64
+ "fork-ts-checker-webpack-plugin": "^7.2.1",
71
65
  "glob": "^7.2.0",
72
66
  "html-loader": "^3.1.0",
73
67
  "html-webpack-plugin": "^5.5.0",
74
68
  "json-loader": "^0.5.7",
75
69
  "lodash": "^4.17.21",
76
70
  "mini-css-extract-plugin": "^2.5.3",
77
- "node-notifier": "^10.0.0",
71
+ "node-notifier": "^10.0.1",
78
72
  "portfinder": "^1.0.28",
79
- "postcss": "^8.4.5",
80
- "postcss-custom-properties": "^12.1.3",
73
+ "postcss": "^8.4.6",
74
+ "postcss-custom-properties": "^12.1.4",
81
75
  "postcss-loader": "^6.2.1",
82
76
  "prettier": "^2.5.1",
83
77
  "react-refresh": "^0.11.0",
84
- "resolve-bin": "^1.0.0",
85
78
  "resolve-url-loader": "^5.0.0",
86
- "sass": "^1.49.0",
87
- "sass-loader": "^12.4.0",
79
+ "sass": "^1.49.8",
80
+ "sass-loader": "^12.6.0",
88
81
  "source-map-loader": "^3.0.1",
89
- "strip-indent": "^3.0.0",
82
+ "strip-indent": "^4.0.0",
90
83
  "style-loader": "^3.3.1",
91
- "tailwindcss": "^0.7.4",
92
84
  "tsconfig-paths-webpack-plugin": "^3.5.2",
93
- "tsup": "^5.11.11",
85
+ "tsup": "^5.11.13",
94
86
  "typescript": "^4.5.5",
95
- "unfetch": "^4.2.0",
96
87
  "url-loader": "^4.1.1",
97
- "webpack": "^5.67.0",
88
+ "webpack": "^5.69.1",
98
89
  "webpack-cli": "^4.9.2",
99
90
  "webpack-config-utils": "^2.3.1",
100
- "webpack-dev-server": "^4.7.3",
91
+ "webpack-dev-server": "^4.7.4",
101
92
  "yaml-loader": "^0.6.0"
102
93
  }
103
94
  }
package/readme.html CHANGED
@@ -40,7 +40,7 @@
40
40
  name: '@raisenow/tamaro-cli',
41
41
  // themeColor: '#537397',
42
42
  maxLevel: 2,
43
- homepage: './readme.md',
43
+ homepage: './README.md',
44
44
  coverpage: false,
45
45
  }
46
46
  </script>
package/src/cli.ts CHANGED
@@ -2,10 +2,22 @@
2
2
 
3
3
  import {createCommand} from 'commander'
4
4
  import pkg from '../package.json'
5
+ import {
6
+ DEFAULT_AWS_PROFILE,
7
+ DEFAULT_AWS_S3_EMAIL_CONFIG_BUCKET,
8
+ DEFAULT_PORT,
9
+ DEFAULT_TAG,
10
+ } from 'lib/constants'
11
+ import {logError} from 'lib/logging'
5
12
  import {dev, DevOptions} from 'commands/dev'
6
13
  import {build, BuildOptions} from 'commands/build'
7
14
  import {deploy, DeployOptions} from 'commands/deploy'
8
- import {serve} from 'commands/serve'
15
+ import {serve, ServeOptions} from 'commands/serve'
16
+ import {listDeployed, ListDeployedOptions} from 'commands/list-deployed'
17
+ import {
18
+ deployEmailConfig,
19
+ DeployEmailConfigOptions,
20
+ } from 'commands/deploy-email-config'
9
21
 
10
22
  ///////////////////////////////////////////////////////////////////////////////
11
23
 
@@ -18,7 +30,7 @@ process.on('unhandledRejection', (error) => {
18
30
 
19
31
  // Exit on ctrl+c
20
32
  process.on('SIGINT', () => {
21
- process.exit(0)
33
+ process.exit(1)
22
34
  })
23
35
 
24
36
  ///////////////////////////////////////////////////////////////////////////////
@@ -29,8 +41,15 @@ const cli = createCommand().name(pkg.name).version(pkg.version, '-v, --version')
29
41
 
30
42
  cli
31
43
  .command('dev')
32
- .description('Run dev web-server for Tamaro Core or customer configuration')
33
- .option('--local-core', 'Load Tamaro Core from localhost instead of CDN')
44
+ .description(
45
+ 'Run the local development server for Tamaro Core or a particular customer configuration',
46
+ )
47
+ .option(
48
+ '--local-core',
49
+ 'Load Tamaro Core from localhost:1234 instead of the CDN',
50
+ false,
51
+ )
52
+ .option('--port <port>', 'Web server port', `${DEFAULT_PORT}`)
34
53
  .action(async (options: DevOptions) => {
35
54
  await dev(options)
36
55
  })
@@ -38,46 +57,115 @@ cli
38
57
  cli
39
58
  .command('build')
40
59
  .description(
41
- 'Build optimised (minified) bundle of Tamaro Core or customer configuration for production',
60
+ 'Build an optimised (minified) bundle of Tamaro Core or a customer configuration',
61
+ )
62
+ .option(
63
+ '--local-core',
64
+ 'Load Tamaro Core from localhost:1234 instead of the CDN',
65
+ false,
42
66
  )
43
- .option('--local-core', 'Load Tamaro Core from localhost instead of CDN')
44
- .option('--analyze', 'Generate bundle statistics to "reports" folder')
67
+ .option('--analyze', 'Generate bundle statistics to "reports" folder', false)
68
+ .option('--serve', 'Run the generated bundle with a local web server', false)
69
+ .option('--port <port>', 'Web server port', `${DEFAULT_PORT}`)
45
70
  .option(
46
71
  '--deploy',
47
- 'Deploy Tamaro Core or customer configuration bundle to AWS',
72
+ 'Deploy Tamaro Core or a customer configuration bundle to AWS S3',
73
+ false,
74
+ )
75
+ .option(
76
+ '--tag <tag>',
77
+ 'Tag which should be used for the deployment of the bundle',
78
+ DEFAULT_TAG,
79
+ )
80
+ .option(
81
+ '--profile <profile>',
82
+ 'AWS profile which should be used for the deployment of the bundle',
83
+ DEFAULT_AWS_PROFILE,
48
84
  )
49
- .option('--serve', 'Run web-server for the bundle')
50
- .option('--tag <tag>', 'Tag which will be used for deployment of the bundle')
51
- .action(async (options: BuildOptions) => {
85
+ .action(async (options: BuildOptions & ServeOptions & DeployOptions) => {
52
86
  await build(options)
53
87
 
88
+ if (options.serve) {
89
+ await serve(options)
90
+ }
91
+
54
92
  if (options.deploy) {
55
93
  await deploy(options)
56
94
  }
95
+ })
57
96
 
58
- if (options.serve) {
59
- await serve()
60
- }
97
+ cli
98
+ .command('serve')
99
+ .description('Run a local web server for pre-built bundle')
100
+ .option('--port <port>', 'Web server port', `${DEFAULT_PORT}`)
101
+ .action(async (options: ServeOptions) => {
102
+ await serve(options)
61
103
  })
62
104
 
63
105
  cli
64
106
  .command('deploy')
65
107
  .description(
66
- 'Deploy prebuilt Tamaro Core or customer configuration bundle to AWS',
108
+ 'Deploy a pre-built Tamaro Core or customer configuration bundle to AWS S3',
109
+ )
110
+ .option(
111
+ '--tag <tag>',
112
+ 'Tag which should be used for the deployment of the bundle',
113
+ DEFAULT_TAG,
114
+ )
115
+ .option(
116
+ '--profile <profile>',
117
+ 'AWS profile which should be used for the deployment of the bundle',
118
+ DEFAULT_AWS_PROFILE,
67
119
  )
68
- .option('--tag <tag>', 'Tag which will be used for deployment of the bundle')
69
120
  .action(async (options: DeployOptions) => {
70
121
  await deploy(options)
71
122
  })
72
123
 
73
124
  cli
74
- .command('serve')
75
- .description('Run web-server for prebuilt bundle')
76
- .action(async () => {
77
- await serve()
125
+ .command('list-deployed')
126
+ .description(
127
+ 'List deployments of Tamaro Core or a particular customer configuration',
128
+ )
129
+ .option(
130
+ '--config <config>',
131
+ 'Configuration name (default: current customer configuration)',
132
+ )
133
+ .option(
134
+ '--profile <profile>',
135
+ 'AWS profile which should be used for fetching deployments',
136
+ DEFAULT_AWS_PROFILE,
137
+ )
138
+ .action(async (options: ListDeployedOptions) => {
139
+ await listDeployed(options)
140
+ })
141
+
142
+ cli
143
+ .command('deploy-email-config')
144
+ .description('Deploy a widget’s email configuration to AWS S3')
145
+ .option(
146
+ '--bucket <bucket>',
147
+ 'AWS S3 bucket where it should be deployed',
148
+ DEFAULT_AWS_S3_EMAIL_CONFIG_BUCKET,
149
+ )
150
+ .option(
151
+ '--profile <profile>',
152
+ 'AWS profile which should be used for the deployment of email configuration',
153
+ DEFAULT_AWS_PROFILE,
154
+ )
155
+ .action(async (options: DeployEmailConfigOptions) => {
156
+ await deployEmailConfig(options)
78
157
  })
79
158
 
80
159
  ///////////////////////////////////////////////////////////////////////////////
81
160
  ;(async () => {
82
- await cli.parseAsync(process.argv)
161
+ try {
162
+ await cli.parseAsync(process.argv)
163
+ } catch (error: any) {
164
+ if (error.signal === 'SIGINT' && error.signalDescription) {
165
+ logError(`\n${error.signalDescription}`)
166
+ } else {
167
+ console.log('')
168
+ logError(error.stack)
169
+ }
170
+ }
83
171
  })()
@@ -0,0 +1,99 @@
1
+ import {CORE_CONFIG_NAME} from 'lib/constants'
2
+ import {assertProfileValid} from 'lib/aws'
3
+ import {
4
+ getIfCoreFns,
5
+ getPaths,
6
+ getWidgetUuid,
7
+ resolveBin,
8
+ resolveOwn,
9
+ } from 'lib/resolve'
10
+ import {logCommand, logTitle} from 'lib/logging'
11
+ import {notify} from 'lib/notifier'
12
+ import {fail, runCommandSync} from 'lib/command'
13
+ import {DeployOptions} from 'commands/deploy'
14
+
15
+ ///////////////////////////////////////////////////////////////////////////////
16
+
17
+ export type BuildOptions = {
18
+ localCore: boolean
19
+ analyze: boolean
20
+ serve: boolean
21
+ deploy: boolean
22
+ }
23
+
24
+ ///////////////////////////////////////////////////////////////////////////////
25
+
26
+ export const build = async (
27
+ options: BuildOptions & DeployOptions,
28
+ ): Promise<void> => {
29
+ assertOptionsValid(options)
30
+
31
+ const flags = prepareFlags([], options).join(' ')
32
+ const {ifCore} = getIfCoreFns()
33
+ const paths = getPaths(ifCore)
34
+ const configName = ifCore(CORE_CONFIG_NAME, getWidgetUuid())
35
+ const title = ifCore(
36
+ 'Building optimised (minified) bundle of Tamaro Core …',
37
+ `Building optimised (minified) bundle of “${configName}” customer configuration …`,
38
+ )
39
+
40
+ const wpBin = resolveBin('webpack')
41
+ const wpConfig = resolveOwn('dist/webpack.config.js')
42
+ const cmd = `
43
+ ${wpBin}
44
+ --config ${wpConfig}
45
+ --env min
46
+ ${flags}
47
+ `
48
+
49
+ logTitle(title)
50
+ logCommand(cmd)
51
+ runCommandSync(cmd, {stdio: 'inherit'})
52
+
53
+ /////////////////////////////////////////////////////////////////////////////
54
+
55
+ logTitle(`\nBundle for “${configName}” customer configuration is done.`)
56
+ console.log(`Path: ${paths.appDist}\n`)
57
+
58
+ /////////////////////////////////////////////////////////////////////////////
59
+
60
+ process.on('exit', () => {
61
+ notify({
62
+ title: 'build',
63
+ message: `Bundle for “${configName}” customer configuration is done.`,
64
+ })
65
+ })
66
+ }
67
+
68
+ ///////////////////////////////////////////////////////////////////////////////
69
+
70
+ const assertOptionsValid = (options: BuildOptions & DeployOptions) => {
71
+ const {localCore, deploy, profile} = options
72
+ const {ifCore} = getIfCoreFns()
73
+
74
+ if (ifCore() && localCore) {
75
+ fail('Flag "--local-core" is redundant if running in Tamaro Core context.')
76
+ }
77
+
78
+ if (localCore && deploy) {
79
+ fail('Flags "--local-core" and "--deploy" must not be used together.')
80
+ }
81
+
82
+ assertProfileValid(profile)
83
+ }
84
+
85
+ ///////////////////////////////////////////////////////////////////////////////
86
+
87
+ const prepareFlags = (flags: string[], options: BuildOptions): string[] => {
88
+ const {localCore, analyze} = options
89
+
90
+ if (localCore) {
91
+ flags.push('--env localCore')
92
+ }
93
+
94
+ if (analyze) {
95
+ flags.push('--env analyze')
96
+ }
97
+
98
+ return flags
99
+ }
@@ -0,0 +1,115 @@
1
+ import {existsSync} from 'fs'
2
+ import {
3
+ assertProfileValid,
4
+ AwsOptions,
5
+ withAwsAuthenticate,
6
+ prepareFlags as prepareAwsFlags,
7
+ } from 'lib/aws'
8
+ import {logCommand, logDataTable, logTitle} from 'lib/logging'
9
+ import {getIfCoreFns, getPaths, getWidgetUuid} from 'lib/resolve'
10
+ import {notify} from 'lib/notifier'
11
+ import {fail, runCommandSync} from 'lib/command'
12
+
13
+ ///////////////////////////////////////////////////////////////////////////////
14
+
15
+ export type DeployEmailConfigOptions = AwsOptions & {
16
+ bucket: string
17
+ }
18
+
19
+ ///////////////////////////////////////////////////////////////////////////////
20
+
21
+ export const deployEmailConfig = async (
22
+ options: DeployEmailConfigOptions,
23
+ ): Promise<void> => {
24
+ const {ifCore} = getIfCoreFns()
25
+ const paths = getPaths(ifCore)
26
+ const emailConfigPath = `${paths.app}/email-config`
27
+
28
+ assertOptionsValid(options)
29
+ assertEmailConfigPathExists(emailConfigPath)
30
+ assertIsNotCore()
31
+
32
+ const flags = prepareFlags([], options).join(' ')
33
+ const {bucket} = options
34
+ const configName = getWidgetUuid()
35
+ const deployUrl = `s3://${bucket}/${configName}`
36
+
37
+ const cmd = `
38
+ aws s3 sync ${emailConfigPath} ${deployUrl}
39
+ --delete
40
+ --exact-timestamps
41
+ ${flags}
42
+ `
43
+ logTitle(
44
+ `Deploying email configuration for “${configName}” customer configuration to AWS S3 …`,
45
+ )
46
+ logCommand(cmd)
47
+
48
+ try {
49
+ withAwsAuthenticate(() => runCommandSync(cmd, {stdout: 'inherit'}), options)
50
+ } catch (error: any) {
51
+ fail(error.stderr)
52
+ }
53
+
54
+ /////////////////////////////////////////////////////////////////////////////
55
+
56
+ logTitle(
57
+ `Email configuration for “${configName}” customer configuration is deployed.`,
58
+ )
59
+ logDataTable({'Deploy URL:': deployUrl})
60
+
61
+ /////////////////////////////////////////////////////////////////////////////
62
+
63
+ process.on('exit', () => {
64
+ notify({
65
+ title: `deploy-email-config`,
66
+ message: `Email configuration for “${configName}” customer configuration is deployed.`,
67
+ })
68
+ })
69
+ }
70
+
71
+ ///////////////////////////////////////////////////////////////////////////////
72
+
73
+ const assertOptionsValid = (options: DeployEmailConfigOptions) => {
74
+ const {bucket, profile} = options
75
+
76
+ assertBucketValid(bucket)
77
+ assertProfileValid(profile)
78
+ }
79
+
80
+ ///////////////////////////////////////////////////////////////////////////////
81
+
82
+ const assertEmailConfigPathExists = (distPath: string) => {
83
+ if (!existsSync(distPath)) {
84
+ fail('Email config folder does not exists. Nothing to deploy.')
85
+ }
86
+ }
87
+
88
+ ///////////////////////////////////////////////////////////////////////////////
89
+
90
+ const assertBucketValid = (tag: string) => {
91
+ const regex = /^[a-zA-Z0-9-_]+$/
92
+
93
+ if (!regex.test(tag)) {
94
+ fail(`Flag "--bucket" has forbidden format. Allowed format: ${regex}.`)
95
+ }
96
+ }
97
+
98
+ ///////////////////////////////////////////////////////////////////////////////
99
+
100
+ const assertIsNotCore = () => {
101
+ const {ifCore} = getIfCoreFns()
102
+
103
+ if (ifCore()) {
104
+ fail('You cannot deploy widget email configuration for Tamaro Core.')
105
+ }
106
+ }
107
+
108
+ ///////////////////////////////////////////////////////////////////////////////
109
+
110
+ const prepareFlags = (
111
+ flags: string[],
112
+ options: DeployEmailConfigOptions,
113
+ ): string[] => {
114
+ return prepareAwsFlags(flags, options)
115
+ }