@raisenow/tamaro-cli 1.1.8 → 1.1.9

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.
@@ -1,131 +0,0 @@
1
- import {type DeployOptions} from 'commands/deploy'
2
- import {assertProfilesPresent, assertProfileValid, promptProfile} from 'lib/aws'
3
- import {halt, runCommandSync} from 'lib/command'
4
- import {CORE_CONFIG_NAME} from 'lib/constants'
5
- import {applyEnv, assertEnvValid} from 'lib/env'
6
- import {assertCrtExists} from 'lib/https'
7
- import {logCommand, logTitle} from 'lib/logging'
8
- import {notify} from 'lib/notifier'
9
- import {
10
- getIfCoreFns,
11
- getPaths,
12
- getWidgetUuid,
13
- resolveBin,
14
- resolveOwn,
15
- } from 'lib/resolve'
16
-
17
- ///////////////////////////////////////////////////////////////////////////////
18
-
19
- export type BuildOptions = {
20
- localCore: boolean
21
- analyze: boolean
22
- https: boolean
23
- serve: boolean
24
- deploy: boolean
25
- env?: string
26
- nolint: boolean
27
- }
28
-
29
- ///////////////////////////////////////////////////////////////////////////////
30
-
31
- export const build = async (
32
- options: BuildOptions & DeployOptions,
33
- ): Promise<void> => {
34
- const {env} = options
35
-
36
- applyEnv(env)
37
-
38
- if (options.deploy && !options.profile && !options.ci) {
39
- assertProfilesPresent()
40
- options.profile = await promptProfile()
41
- }
42
-
43
- assertOptionsValid(options)
44
-
45
- const flags = prepareFlags(options)
46
- const {ifCore} = getIfCoreFns()
47
- const paths = getPaths(ifCore)
48
- const configName = ifCore(CORE_CONFIG_NAME, getWidgetUuid())
49
- const title = ifCore(
50
- 'Building optimised (minified) bundle of Tamaro Core …',
51
- `Building optimised (minified) bundle of "${configName}" customer configuration …`,
52
- )
53
-
54
- const wpBin = resolveBin('webpack')
55
- const wpConfig = resolveOwn('dist/webpack.config.js')
56
- const cmd = `
57
- ${wpBin}
58
- --config ${wpConfig}
59
- --env min
60
- ${flags}
61
- `
62
-
63
- logTitle(title)
64
- logCommand(cmd)
65
- runCommandSync(cmd, {stdio: 'inherit'})
66
-
67
- /////////////////////////////////////////////////////////////////////////////
68
-
69
- logTitle(`\nBundle for "${configName}" customer configuration is done.`)
70
- // eslint-disable-next-line no-console
71
- console.log(`Path: ${paths.appDist}\n`)
72
-
73
- /////////////////////////////////////////////////////////////////////////////
74
-
75
- process.on('exit', () => {
76
- notify({
77
- title: 'build',
78
- message: `Bundle for "${configName}" customer configuration is done.`,
79
- })
80
- })
81
- }
82
-
83
- ///////////////////////////////////////////////////////////////////////////////
84
-
85
- const assertOptionsValid = (options: BuildOptions & DeployOptions) => {
86
- const {localCore, https, deploy, env, profile} = options
87
- const {ifCore} = getIfCoreFns()
88
-
89
- if (ifCore() && localCore) {
90
- halt('Flag "--local-core" is redundant if running in Tamaro Core context.')
91
- }
92
-
93
- if (localCore && deploy) {
94
- halt('Flags "--local-core" and "--deploy" must not be used together.')
95
- }
96
-
97
- if (https) {
98
- assertCrtExists()
99
- }
100
-
101
- if (profile) {
102
- assertProfileValid(profile)
103
- }
104
-
105
- assertEnvValid(env)
106
- }
107
-
108
- ///////////////////////////////////////////////////////////////////////////////
109
-
110
- const prepareFlags = (options: BuildOptions) => {
111
- const flags: string[] = []
112
- const {localCore, analyze, https, nolint} = options
113
-
114
- if (localCore) {
115
- flags.push('--env localCore')
116
- }
117
-
118
- if (analyze) {
119
- flags.push('--env analyze')
120
- }
121
-
122
- if (https) {
123
- flags.push('--env https')
124
- }
125
-
126
- if (nolint) {
127
- flags.push('--env nolint')
128
- }
129
-
130
- return flags.join(' ')
131
- }
@@ -1,159 +0,0 @@
1
- import {existsSync} from 'fs'
2
- // eslint-disable-next-line import/no-named-as-default
3
- import prompts from 'prompts'
4
- import {
5
- assertProfilesPresent,
6
- assertProfileValid,
7
- awsAuthenticate,
8
- type AwsOptions,
9
- prepareFlags,
10
- promptProfile,
11
- } from 'lib/aws'
12
- import {halt, runCommandSync} from 'lib/command'
13
- import {
14
- AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD,
15
- AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_STAGE,
16
- } from 'lib/constants'
17
- import {logCommand, logDataTable, logTitle} from 'lib/logging'
18
- import {notify} from 'lib/notifier'
19
- import {getIfCoreFns, getPaths, getWidgetUuid} from 'lib/resolve'
20
-
21
- ///////////////////////////////////////////////////////////////////////////////
22
-
23
- export type DeployEmailConfigOptions = AwsOptions & {
24
- bucket?: string
25
- }
26
-
27
- ///////////////////////////////////////////////////////////////////////////////
28
-
29
- export const deployEmailConfig = async (
30
- options: DeployEmailConfigOptions,
31
- ): Promise<void> => {
32
- const {ifCore} = getIfCoreFns()
33
- const paths = getPaths(ifCore)
34
- const emailConfigPath = `${paths.app}/email-config`
35
-
36
- assertIsNotCore()
37
- assertEmailConfigPathExists(emailConfigPath)
38
-
39
- if (!options.profile && !options.ci) {
40
- assertProfilesPresent()
41
- options.profile = await promptProfile()
42
- }
43
-
44
- if (!options.bucket) {
45
- options.bucket = options.ci
46
- ? AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD
47
- : await promptBucketTamaroEmailConfig()
48
- }
49
-
50
- assertOptionsValid(options)
51
- awsAuthenticate(options)
52
-
53
- const flags = prepareFlags(options)
54
- const configName = getWidgetUuid()
55
- const deployUrl = `s3://${options.bucket}/${configName}`
56
-
57
- const cmd = `
58
- aws s3 sync ${emailConfigPath} ${deployUrl}
59
- --delete
60
- --exact-timestamps
61
- ${flags}
62
- `
63
- logTitle(
64
- `Deploying email configuration for "${configName}" customer configuration to AWS S3 …`,
65
- )
66
- logCommand(cmd)
67
-
68
- try {
69
- runCommandSync(cmd, {stdout: 'inherit'})
70
- } catch (error: any) {
71
- halt(error.stderr)
72
- }
73
-
74
- /////////////////////////////////////////////////////////////////////////////
75
-
76
- logTitle(
77
- `Email configuration for "${configName}" customer configuration is deployed.`,
78
- )
79
- logDataTable({'Deploy URL:': deployUrl})
80
-
81
- /////////////////////////////////////////////////////////////////////////////
82
-
83
- process.on('exit', () => {
84
- notify({
85
- title: 'deploy-email-config',
86
- message: `Email configuration for "${configName}" customer configuration is deployed.`,
87
- })
88
- })
89
- }
90
-
91
- ///////////////////////////////////////////////////////////////////////////////
92
-
93
- const assertOptionsValid = (options: DeployEmailConfigOptions) => {
94
- const {profile, bucket} = options
95
-
96
- if (profile) {
97
- assertProfileValid(profile)
98
- }
99
-
100
- if (bucket) {
101
- assertBucketValid(bucket)
102
- }
103
- }
104
-
105
- ///////////////////////////////////////////////////////////////////////////////
106
-
107
- const assertEmailConfigPathExists = (distPath: string) => {
108
- if (!existsSync(distPath)) {
109
- halt('Email config folder does not exists. Nothing to deploy.')
110
- }
111
- }
112
-
113
- ///////////////////////////////////////////////////////////////////////////////
114
-
115
- const assertIsNotCore = () => {
116
- const {ifCore} = getIfCoreFns()
117
-
118
- if (ifCore()) {
119
- halt('You cannot deploy widget email configuration for Tamaro Core.')
120
- }
121
- }
122
-
123
- ///////////////////////////////////////////////////////////////////////////////
124
-
125
- const assertBucketValid = (bucket: string) => {
126
- const buckets = [
127
- AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_STAGE,
128
- AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD,
129
- ] as const
130
-
131
- if (!buckets.includes(bucket as any)) {
132
- halt('Invalid bucket name.')
133
- }
134
- }
135
-
136
- ///////////////////////////////////////////////////////////////////////////////
137
-
138
- const promptBucketTamaroEmailConfig = async (): Promise<string> => {
139
- const buckets = [
140
- {title: 'stage', value: AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_STAGE},
141
- {title: 'prod', value: AWS_S3_BUCKET_TAMARO_EMAIL_CONFIG_PROD},
142
- ]
143
-
144
- const {bucket} = await prompts(
145
- [
146
- {
147
- type: 'select',
148
- name: 'bucket',
149
- message: 'Select environment',
150
- choices: buckets,
151
- },
152
- ],
153
- {
154
- onCancel: () => halt(),
155
- },
156
- )
157
-
158
- return bucket
159
- }
@@ -1,164 +0,0 @@
1
- import {existsSync} from 'fs'
2
- import stripIndent from 'strip-indent'
3
- import {
4
- assertProfilesPresent,
5
- assertProfileValid,
6
- awsAuthenticate,
7
- type AwsOptions,
8
- prepareFlags,
9
- promptProfile,
10
- } from 'lib/aws'
11
- import {halt, runCommandSync} from 'lib/command'
12
- import {
13
- AWS_CLOUDFRONT_DISTRIBUTION_ID,
14
- AWS_S3_BUCKET_TAMARO,
15
- CORE_CONFIG_NAME,
16
- } from 'lib/constants'
17
- import {logCommand, logDataTable, logTitle} from 'lib/logging'
18
- import {notify} from 'lib/notifier'
19
- import {getIfCoreFns, getPaths, getWidgetUuid} from 'lib/resolve'
20
-
21
- ///////////////////////////////////////////////////////////////////////////////
22
-
23
- export type DeployOptions = AwsOptions & {
24
- tag: string
25
- }
26
-
27
- ///////////////////////////////////////////////////////////////////////////////
28
-
29
- export const deploy = async (options: DeployOptions): Promise<void> => {
30
- const {ifCore} = getIfCoreFns()
31
- const paths = getPaths(ifCore)
32
-
33
- assertDistPathExists(paths.appDist)
34
-
35
- if (!options.profile && !options.ci) {
36
- assertProfilesPresent()
37
- options.profile = await promptProfile()
38
- }
39
-
40
- assertOptionsValid(options)
41
- awsAuthenticate(options)
42
-
43
- const flags = prepareFlags(options)
44
- const {tag} = options
45
- const configName = ifCore(CORE_CONFIG_NAME, getWidgetUuid())
46
- const deployUrl = `s3://${AWS_S3_BUCKET_TAMARO}/${configName}/${tag}`
47
- const entryFilename = ifCore('index.js', 'widget.js')
48
-
49
- /**
50
- * Sync all files except entrypoint (without deleting old files)
51
- */
52
- const cmdSyncAll = `
53
- aws s3 sync ${paths.appDist} ${deployUrl}
54
- --acl public-read
55
- --exclude ${paths.appDist}/${entryFilename}
56
- --cache-control max-age=31536000
57
- ${flags}
58
- `
59
- logTitle('Deploying to AWS S3 …')
60
- logCommand(cmdSyncAll)
61
-
62
- try {
63
- runCommandSync(cmdSyncAll, {stdout: 'inherit'})
64
- } catch (error: any) {
65
- halt(error.stderr)
66
- }
67
-
68
- /**
69
- * Copy entrypoint
70
- */
71
- const cmdCpEntry = `
72
- aws s3 cp ${paths.appDist}/${entryFilename} ${deployUrl}/${entryFilename}
73
- --acl public-read
74
- --cache-control max-age=64800
75
- ${flags}
76
- `
77
- logCommand(cmdCpEntry)
78
-
79
- try {
80
- runCommandSync(cmdCpEntry, {stdout: 'inherit'})
81
- } catch (error: any) {
82
- halt(error.stderr)
83
- }
84
-
85
- /**
86
- * Invalidate cloudfront cache
87
- */
88
- const cmdInvalidateCache = `
89
- aws cloudfront create-invalidation
90
- --distribution-id ${AWS_CLOUDFRONT_DISTRIBUTION_ID}
91
- --paths /${configName}/${tag}/*
92
- ${flags}
93
- `
94
- logTitle('\nInvalidating edge cache …')
95
- logCommand(cmdInvalidateCache)
96
-
97
- try {
98
- // ignore output
99
- runCommandSync(cmdInvalidateCache)
100
- } catch (error: any) {
101
- halt(error.stderr)
102
- }
103
-
104
- /////////////////////////////////////////////////////////////////////////////
105
-
106
- const demoPage = `https://${AWS_S3_BUCKET_TAMARO}/${configName}/${tag}/index.html`
107
- const entryPoint = `https://${AWS_S3_BUCKET_TAMARO}/${configName}/${tag}/${entryFilename}`
108
-
109
- logTitle(`\nBundle for "${configName}" is deployed with tag "${tag}".`)
110
- logDataTable({
111
- 'Demo page:': demoPage,
112
- 'Entry point:': entryPoint,
113
- })
114
-
115
- /////////////////////////////////////////////////////////////////////////////
116
-
117
- process.on('exit', () => {
118
- notify({
119
- title: 'deploy',
120
- message: `
121
- Bundle for "${configName}" is deployed with tag "${tag}".
122
- Demo page: ${demoPage}
123
- Entry point: ${entryPoint}
124
- `,
125
- })
126
- })
127
- }
128
-
129
- ///////////////////////////////////////////////////////////////////////////////
130
-
131
- const assertOptionsValid = (options: DeployOptions) => {
132
- const {profile, tag} = options
133
-
134
- if (profile) {
135
- assertProfileValid(profile)
136
- }
137
-
138
- assertTagValid(tag)
139
- }
140
-
141
- ///////////////////////////////////////////////////////////////////////////////
142
-
143
- const assertDistPathExists = (distPath: string) => {
144
- if (!existsSync(distPath)) {
145
- halt(
146
- stripIndent(`
147
- Dist folder does not exists.
148
- Make sure you have built the bundle before trying to deploy it.
149
- `),
150
- )
151
- }
152
- }
153
-
154
- ///////////////////////////////////////////////////////////////////////////////
155
-
156
- const assertTagValid = (tag: string) => {
157
- const regex = /^[a-zA-Z0-9-_.]+$/
158
-
159
- if (!regex.test(tag)) {
160
- halt(
161
- `Flag "--tag" has forbidden format. Allowed format: ${regex.toString()}.`,
162
- )
163
- }
164
- }
@@ -1,88 +0,0 @@
1
- import {getPortPromise} from 'portfinder'
2
- import {halt, runCommandSync} from 'lib/command'
3
- import {applyEnv, assertEnvValid} from 'lib/env'
4
- import {assertCrtExists} from 'lib/https'
5
- import {logCommand, logTitle} from 'lib/logging'
6
- import {getIfCoreFns, resolveBin, resolveOwn} from 'lib/resolve'
7
-
8
- ///////////////////////////////////////////////////////////////////////////////
9
-
10
- export type DevOptions = {
11
- localCore: boolean
12
- https: boolean
13
- port: string
14
- env?: string
15
- nolint: boolean
16
- }
17
-
18
- ///////////////////////////////////////////////////////////////////////////////
19
-
20
- export const dev = async (options: DevOptions): Promise<void> => {
21
- const {env} = options
22
-
23
- applyEnv(env)
24
- assertOptionsValid(options)
25
-
26
- const flags = await prepareFlags(options)
27
- const {ifCore} = getIfCoreFns()
28
- const title = ifCore(
29
- 'Running dev web-server for Tamaro Core …',
30
- 'Running dev web-server for customer configuration …',
31
- )
32
- const wpBin = resolveBin('webpack')
33
- const wpConfig = resolveOwn('dist/webpack.config.js')
34
- const cmd = `
35
- ${wpBin} serve
36
- --config ${wpConfig}
37
- ${flags}
38
- `
39
-
40
- logTitle(title)
41
- logCommand(cmd)
42
- runCommandSync(cmd, {stdio: 'inherit'})
43
- }
44
-
45
- ///////////////////////////////////////////////////////////////////////////////
46
-
47
- const assertOptionsValid = (options: DevOptions) => {
48
- const {localCore, https, port, env} = options
49
- const {ifCore} = getIfCoreFns()
50
-
51
- if (ifCore() && localCore) {
52
- halt('Flag "--local-core" is redundant if running in Tamaro Core context.')
53
- }
54
-
55
- if (isNaN(Number(port))) {
56
- halt('Flag "--port" should be a number.')
57
- }
58
-
59
- if (https) {
60
- assertCrtExists()
61
- }
62
-
63
- assertEnvValid(env)
64
- }
65
-
66
- ///////////////////////////////////////////////////////////////////////////////
67
-
68
- const prepareFlags = async (options: DevOptions) => {
69
- const flags: string[] = []
70
- const {localCore, port: defaultPort, https, nolint} = options
71
- const port = await getPortPromise({port: Number(defaultPort)})
72
-
73
- if (localCore) {
74
- flags.push('--env localCore')
75
- }
76
-
77
- flags.push(`--port ${port}`)
78
-
79
- if (https) {
80
- flags.push('--env https')
81
- }
82
-
83
- if (nolint) {
84
- flags.push('--env nolint')
85
- }
86
-
87
- return flags.join(' ')
88
- }
@@ -1,117 +0,0 @@
1
- import {
2
- assertProfilesPresent,
3
- assertProfileValid,
4
- awsAuthenticate,
5
- type AwsOptions,
6
- prepareFlags,
7
- promptProfile,
8
- } from 'lib/aws'
9
- import {halt, runCommandSync} from 'lib/command'
10
- import {AWS_S3_BUCKET_TAMARO, CORE_CONFIG_NAME} from 'lib/constants'
11
- import {logCommand, logTitle} from 'lib/logging'
12
- import {getIfCoreFns, getWidgetUuid} from 'lib/resolve'
13
-
14
- ///////////////////////////////////////////////////////////////////////////////
15
-
16
- export type ListDeployedOptions = AwsOptions & {
17
- config?: string
18
- }
19
-
20
- ///////////////////////////////////////////////////////////////////////////////
21
-
22
- export const listDeployed = async (
23
- options: ListDeployedOptions,
24
- ): Promise<void> => {
25
- if (!options.profile && !options.ci) {
26
- assertProfilesPresent()
27
- options.profile = await promptProfile()
28
- }
29
-
30
- assertOptionsValid(options)
31
- awsAuthenticate(options)
32
-
33
- const flags = prepareFlags(options)
34
- const {config} = options
35
- const {ifCore} = getIfCoreFns()
36
- const configName = config ?? ifCore(CORE_CONFIG_NAME, getWidgetUuid())
37
- const title =
38
- !config && ifCore()
39
- ? `Listing deployments of Tamaro Core …`
40
- : `Listing deployments of "${configName}" customer configuration …`
41
-
42
- const deployUrl = `s3://${AWS_S3_BUCKET_TAMARO}/${configName}/`
43
- const cmd = `aws s3 ls ${deployUrl} ${flags}`
44
- let out = ''
45
-
46
- logTitle(title)
47
- logCommand(cmd)
48
-
49
- // If customer configuration folder does not exist on AWS S3,
50
- // command fails with blank stderr, so we need to handle this case.
51
- try {
52
- const result = runCommandSync(cmd)
53
- out = result.stdout as string
54
- } catch (error: any) {
55
- out = error.stdout as string
56
-
57
- if (error.stderr) {
58
- halt(error.stderr)
59
- }
60
- }
61
-
62
- const lines = out.split('\n')
63
- const tags = parseTags(lines)
64
- let text = ''
65
-
66
- if (tags.length === 0) {
67
- text = 'No deployments found.'
68
- } else {
69
- text = tags
70
- .map((tag, idx) => {
71
- // prettier-ignore
72
- return `${idx + 1}. https://${AWS_S3_BUCKET_TAMARO}/${configName}/${tag}/index.html`
73
- })
74
- .join('\n')
75
- }
76
-
77
- // eslint-disable-next-line no-console
78
- console.log(`${text}\n`)
79
- }
80
-
81
- ///////////////////////////////////////////////////////////////////////////////
82
-
83
- const assertOptionsValid = (options: ListDeployedOptions) => {
84
- const {config, profile} = options
85
-
86
- assertConfigValid(config)
87
-
88
- if (profile) {
89
- assertProfileValid(profile)
90
- }
91
- }
92
-
93
- ///////////////////////////////////////////////////////////////////////////////
94
-
95
- const assertConfigValid = (config: string | undefined) => {
96
- if (!config) {
97
- return
98
- }
99
-
100
- const regex = /^[a-zA-Z0-9-_]+$/
101
-
102
- if (!regex.test(config)) {
103
- halt(
104
- `Flag "--config" has forbidden format. Allowed format: ${regex.toString()}.`,
105
- )
106
- }
107
- }
108
-
109
- ///////////////////////////////////////////////////////////////////////////////
110
-
111
- const parseTags = (lines: string[]): string[] => {
112
- const regex = /^\s*PRE\s*/
113
-
114
- return lines
115
- .filter((line) => regex.test(line))
116
- .map((line) => line.replace(regex, '').replace(/\/$/, ''))
117
- }