@madgex/fert 5.0.3 → 5.0.5
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/README.md +21 -12
- package/bin/cli.js +9 -27
- package/bin/commands/_service-command-bootstrap.js +12 -52
- package/bin/commands/build-tasks/build-tokens.js +8 -22
- package/bin/commands/build-tasks/bundle-entry.js +1 -4
- package/bin/commands/build.js +1 -0
- package/bin/commands/configs.js +17 -53
- package/bin/commands/dev-server.js +5 -14
- package/bin/commands/init.js +27 -117
- package/bin/commands/publish-tasks/asset-store-uploader.js +2 -5
- package/bin/commands/publish.js +10 -30
- package/bin/utils/configs.js +55 -95
- package/bin/utils/cpid-lookup.js +2 -2
- package/bin/utils/cpid-matches-git-remote.js +5 -10
- package/bin/utils/getSchemaMeta.js +1 -1
- package/bin/utils/index.js +14 -25
- package/bin/utils/lookup-cf-distribution-ids.js +2 -7
- package/bin/utils/resolve-external-assets.js +6 -15
- package/constants.js +3 -17
- package/package.json +17 -26
- package/repo-template/fert.config.js +3 -0
- package/repo-template/package.json +22 -0
- package/{repo-templates/template-basic → repo-template/services/jobseekers-frontend}/brand.json +6 -3
- package/repo-template/services/jobseekers-frontend/fert.service.config.js +7 -0
- package/repo-template/services/jobseekers-frontend/public/icons/user.svg +4 -0
- package/repo-template/services/jobseekers-frontend/public/images/favicon.ico +0 -0
- package/repo-template/services/jobseekers-frontend/public/images/fred.jpeg +0 -0
- package/repo-template/services/jobseekers-frontend/src/css/styles.scss +1152 -0
- package/repo-template/services/jobseekers-frontend/src/index.js +9 -0
- package/repo-template/services/jobseekers-frontend/src/js/recruiter-link.js +25 -0
- package/{repo-templates/template-bigworkbag → repo-template/services/jobseekers-frontend}/templates/context/footer-nav.njk +26 -26
- package/{repo-templates/template-bigworkbag → repo-template/services/jobseekers-frontend}/templates/context/main-nav.njk +40 -31
- package/{repo-templates/template-bigworkbag → repo-template/services/jobseekers-frontend}/templates/context/user-nav.njk +16 -16
- package/repo-template/services/jobseekers-frontend/templates/footer.njk +20 -0
- package/repo-template/services/jobseekers-frontend/templates/header.njk +74 -0
- package/repo-template/services/jobseekers-frontend/templates/includes/footer-nav.njk +15 -0
- package/repo-template/services/jobseekers-frontend/templates/includes/main-nav.njk +19 -0
- package/repo-template/services/jobseekers-frontend/templates/includes/user-nav/authenticated.njk +34 -0
- package/repo-template/services/jobseekers-frontend/templates/includes/user-nav/unauthenticated.njk +9 -0
- package/{repo-templates/template-bigworkbag → repo-template/services/jobseekers-frontend}/templates/translations/en.njk +1 -0
- package/server/index.js +2 -3
- package/server/plugins/hapi-vite.js +4 -2
- package/server/routes/views.js +1 -0
- package/server/view-manager.js +2 -5
- package/.prettierrc.js +0 -8
- package/bin/commands/configs.test.js +0 -182
- package/bin/utils/configs.test.js +0 -53
- package/bin/utils/persistent-cache-with-ttl.test.js +0 -42
- package/bin/utils/resolve-external-assets.test.js +0 -98
- package/delivery/jenkinsfile +0 -93
- package/eslint.config.mjs +0 -53
- package/repo-templates/globals/fert.config.js +0 -9
- package/repo-templates/template-basic/_gitignore +0 -6
- package/repo-templates/template-basic/package.json +0 -13
- package/repo-templates/template-basic/public/favicon.ico +0 -0
- package/repo-templates/template-basic/src/css/styles.scss +0 -11
- package/repo-templates/template-basic/src/index.js +0 -3
- package/repo-templates/template-basic/templates/footer.njk +0 -14
- package/repo-templates/template-basic/templates/header.njk +0 -14
- package/repo-templates/template-bigworkbag/_gitignore +0 -6
- package/repo-templates/template-bigworkbag/brand.json +0 -21
- package/repo-templates/template-bigworkbag/package.json +0 -13
- package/repo-templates/template-bigworkbag/public/favicon.ico +0 -0
- package/repo-templates/template-bigworkbag/public/fonts/mdgx-icons.eot +0 -0
- package/repo-templates/template-bigworkbag/public/fonts/mdgx-icons.svg +0 -71
- package/repo-templates/template-bigworkbag/public/fonts/mdgx-icons.ttf +0 -0
- package/repo-templates/template-bigworkbag/public/fonts/mdgx-icons.woff +0 -0
- package/repo-templates/template-bigworkbag/public/fonts/my-font.woff +0 -1
- package/repo-templates/template-bigworkbag/public/images/logo.png +0 -0
- package/repo-templates/template-bigworkbag/public/images/user-menu-pointer.svg +0 -4
- package/repo-templates/template-bigworkbag/src/css/breakpoints.scss +0 -17
- package/repo-templates/template-bigworkbag/src/css/clicky-menu.scss +0 -52
- package/repo-templates/template-bigworkbag/src/css/desktop-main-nav.scss +0 -25
- package/repo-templates/template-bigworkbag/src/css/desktop-user-nav.scss +0 -127
- package/repo-templates/template-bigworkbag/src/css/footer.scss +0 -77
- package/repo-templates/template-bigworkbag/src/css/header-top.scss +0 -29
- package/repo-templates/template-bigworkbag/src/css/leaderboard-ad.scss +0 -22
- package/repo-templates/template-bigworkbag/src/css/mobile-main-nav.scss +0 -68
- package/repo-templates/template-bigworkbag/src/css/mobile-user-nav.scss +0 -49
- package/repo-templates/template-bigworkbag/src/css/reset.scss +0 -91
- package/repo-templates/template-bigworkbag/src/css/styles.scss +0 -18
- package/repo-templates/template-bigworkbag/src/css/top-bar.scss +0 -13
- package/repo-templates/template-bigworkbag/src/css/typography.scss +0 -20
- package/repo-templates/template-bigworkbag/src/css/util.scss +0 -28
- package/repo-templates/template-bigworkbag/src/css/variables.scss +0 -9
- package/repo-templates/template-bigworkbag/src/index.js +0 -3
- package/repo-templates/template-bigworkbag/src/js/clicky-menus.js +0 -178
- package/repo-templates/template-bigworkbag/src/js/no-js.js +0 -10
- package/repo-templates/template-bigworkbag/templates/footer.njk +0 -68
- package/repo-templates/template-bigworkbag/templates/header.njk +0 -54
- package/repo-templates/template-bigworkbag/templates/includes/desktop-main-nav-items.njk +0 -18
- package/repo-templates/template-bigworkbag/templates/includes/desktop-user-nav/loggedin-items.njk +0 -28
- package/repo-templates/template-bigworkbag/templates/includes/desktop-user-nav/loggedout-items.njk +0 -9
- package/repo-templates/template-bigworkbag/templates/includes/desktop-user-nav/submenu-items.njk +0 -18
- package/repo-templates/template-bigworkbag/templates/includes/desktop-user-nav/user-nav.njk +0 -24
- package/repo-templates/template-bigworkbag/templates/includes/dev-console-context.njk +0 -7
- package/repo-templates/template-bigworkbag/templates/includes/mobile-main-nav-items.njk +0 -25
- package/repo-templates/template-bigworkbag/templates/includes/mobile-user-nav/loggedin-items.njk +0 -33
- package/repo-templates/template-bigworkbag/templates/includes/mobile-user-nav/loggedout-items.njk +0 -16
- package/repo-templates/template-bigworkbag/templates/includes/mobile-user-nav/user-nav.njk +0 -24
- package/repo-templates/template-bigworkbag/templates/svgs/arrow-down.svg +0 -3
- package/repo-templates/template-bigworkbag/templates/svgs/arrow-left.svg +0 -3
- package/repo-templates/template-bigworkbag/templates/svgs/arrow-right.svg +0 -3
- package/repo-templates/template-bigworkbag/templates/svgs/arrow-up.svg +0 -3
- package/repo-templates/template-bigworkbag/templates/svgs/cart.svg +0 -3
- package/repo-templates/template-bigworkbag/templates/svgs/facebook.svg +0 -3
- package/repo-templates/template-bigworkbag/templates/svgs/linkedin.svg +0 -3
- package/repo-templates/template-bigworkbag/templates/svgs/profile.svg +0 -5
- package/repo-templates/template-bigworkbag/templates/svgs/star-filled.svg +0 -3
- package/repo-templates/template-bigworkbag/templates/svgs/star-outline.svg +0 -3
- package/repo-templates/template-bigworkbag/templates/svgs/twitter.svg +0 -3
- package/repo-templates/template-bigworkbag/templates/svgs/youtube.svg +0 -3
- /package/{repo-templates/globals → repo-template}/jenkinsfile +0 -0
- /package/{repo-templates/template-basic → repo-template/services/jobseekers-frontend}/public/fonts/mdgx-icons.eot +0 -0
- /package/{repo-templates/template-basic → repo-template/services/jobseekers-frontend}/public/fonts/mdgx-icons.svg +0 -0
- /package/{repo-templates/template-basic → repo-template/services/jobseekers-frontend}/public/fonts/mdgx-icons.ttf +0 -0
- /package/{repo-templates/template-basic → repo-template/services/jobseekers-frontend}/public/fonts/mdgx-icons.woff +0 -0
- /package/{repo-templates/template-basic → repo-template/services/jobseekers-frontend}/public/fonts/my-font.woff +0 -0
- /package/{repo-templates/template-basic → repo-template/services/jobseekers-frontend}/public/images/logo.png +0 -0
- /package/{repo-templates/template-bigworkbag → repo-template/services/jobseekers-frontend}/templates/translations/da.njk +0 -0
- /package/{repo-templates/template-bigworkbag → repo-template/services/jobseekers-frontend}/templates/translations/de.njk +0 -0
- /package/{repo-templates/template-bigworkbag → repo-template/services/jobseekers-frontend}/templates/translations/es.njk +0 -0
- /package/{repo-templates/template-bigworkbag → repo-template/services/jobseekers-frontend}/templates/translations/fr.njk +0 -0
- /package/{repo-templates/template-bigworkbag → repo-template/services/jobseekers-frontend}/templates/translations/nb.njk +0 -0
- /package/{repo-templates/template-bigworkbag → repo-template/services/jobseekers-frontend}/templates/translations/nl.njk +0 -0
- /package/{repo-templates/template-bigworkbag → repo-template/services/jobseekers-frontend}/templates/translations/sv.njk +0 -0
- /package/{repo-templates/template-bigworkbag → repo-template/services/jobseekers-frontend}/templates/translations/zh-cn.njk +0 -0
package/bin/commands/init.js
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
/* eslint-disable no-unreachable */
|
|
2
1
|
const path = require('node:path');
|
|
3
2
|
const fs = require('node:fs');
|
|
4
3
|
const chalk = require('chalk');
|
|
@@ -6,20 +5,17 @@ const prompts = require('prompts');
|
|
|
6
5
|
const uuidValidator = require('uuid-validate');
|
|
7
6
|
const ora = require('ora');
|
|
8
7
|
const { cpidLookup } = require('../utils/cpid-lookup');
|
|
8
|
+
const fertPackageJSON = require('../../package.json');
|
|
9
9
|
|
|
10
10
|
const { isEmptyDir, formatTargetDir, emptyDir } = require('../utils/index');
|
|
11
|
-
const {
|
|
11
|
+
const { FERT_CONFIG_FILENAME } = require('../../constants');
|
|
12
12
|
|
|
13
13
|
const cwd = process.cwd();
|
|
14
|
-
const templateList = TEMPLATES.map((i) => i.name);
|
|
15
14
|
|
|
16
15
|
module.exports = async (root, options = {}) => {
|
|
17
|
-
throw new Error('TODO: init new monorepo template');
|
|
18
16
|
const defaultProjectName = 'madgex-{cpid}';
|
|
19
17
|
const argTargetDir = root ? formatTargetDir(root) : null;
|
|
20
|
-
const
|
|
21
|
-
const argClientPropertyId =
|
|
22
|
-
options.cpid && uuidValidator(options.cpid) ? options.cpid : false;
|
|
18
|
+
const argClientPropertyId = options.cpid && uuidValidator(options.cpid) ? options.cpid : false;
|
|
23
19
|
|
|
24
20
|
let targetDir = argTargetDir || path.join(cwd, defaultProjectName);
|
|
25
21
|
let result;
|
|
@@ -32,47 +28,22 @@ module.exports = async (root, options = {}) => {
|
|
|
32
28
|
name: 'cpid',
|
|
33
29
|
message: 'clientPropertyId:',
|
|
34
30
|
validate: (cpid) =>
|
|
35
|
-
uuidValidator(cpid)
|
|
36
|
-
? true
|
|
37
|
-
: `Invalid UUID, ensure the correct clientPropertyId is entered`,
|
|
31
|
+
uuidValidator(cpid) ? true : `Invalid UUID, ensure the correct clientPropertyId is entered`,
|
|
38
32
|
},
|
|
39
33
|
{
|
|
40
34
|
type: argTargetDir ? null : 'text',
|
|
41
35
|
name: 'projectName',
|
|
42
36
|
message: 'Project name:',
|
|
43
|
-
initial: (prev) =>
|
|
44
|
-
defaultProjectName.replace('{cpid}', prev || argClientPropertyId),
|
|
37
|
+
initial: (prev) => defaultProjectName.replace('{cpid}', prev || argClientPropertyId),
|
|
45
38
|
onState: (state) => {
|
|
46
39
|
targetDir = formatTargetDir(state.value) || defaultProjectName;
|
|
47
40
|
},
|
|
48
41
|
},
|
|
49
42
|
{
|
|
50
|
-
type:
|
|
51
|
-
argTemplate && templateList.includes(argTemplate) ? null : 'select',
|
|
52
|
-
name: 'template',
|
|
53
|
-
message:
|
|
54
|
-
typeof argTemplate === 'string' &&
|
|
55
|
-
!templateList.includes(argTemplate)
|
|
56
|
-
? `"${argTemplate}" isn't a valid template. Please choose from below: `
|
|
57
|
-
: 'Select a template:',
|
|
58
|
-
initial: 0,
|
|
59
|
-
choices: TEMPLATES.map((i) => {
|
|
60
|
-
return {
|
|
61
|
-
title: i.display,
|
|
62
|
-
value: i.name,
|
|
63
|
-
};
|
|
64
|
-
}),
|
|
65
|
-
},
|
|
66
|
-
{
|
|
67
|
-
type: () =>
|
|
68
|
-
!fs.existsSync(targetDir) || isEmptyDir(targetDir)
|
|
69
|
-
? null
|
|
70
|
-
: 'confirm',
|
|
43
|
+
type: () => (!fs.existsSync(targetDir) || isEmptyDir(targetDir) ? null : 'confirm'),
|
|
71
44
|
name: 'overwrite',
|
|
72
45
|
message: () =>
|
|
73
|
-
(targetDir === '.'
|
|
74
|
-
? 'Current directory'
|
|
75
|
-
: `Target directory "${targetDir}"`) +
|
|
46
|
+
(targetDir === '.' ? 'Current directory' : `Target directory "${targetDir}"`) +
|
|
76
47
|
` is not empty. Remove existing files and continue?`,
|
|
77
48
|
},
|
|
78
49
|
{
|
|
@@ -89,32 +60,24 @@ module.exports = async (root, options = {}) => {
|
|
|
89
60
|
onCancel: () => {
|
|
90
61
|
throw new Error(chalk.red('✖') + ' Operation cancelled');
|
|
91
62
|
},
|
|
92
|
-
}
|
|
63
|
+
},
|
|
93
64
|
);
|
|
94
65
|
} catch (cancelled) {
|
|
95
66
|
console.log(cancelled.message);
|
|
96
67
|
return;
|
|
97
68
|
}
|
|
98
69
|
|
|
99
|
-
const { overwrite,
|
|
100
|
-
const templateName = template || argTemplate;
|
|
70
|
+
const { overwrite, cpid } = result;
|
|
101
71
|
const clientPropertyId = cpid || argClientPropertyId;
|
|
102
72
|
const outDir = targetDir;
|
|
103
73
|
|
|
104
|
-
const spinner = ora(
|
|
105
|
-
`Looking up clientPropertyId: ${chalk.yellow(clientPropertyId)}`
|
|
106
|
-
).start();
|
|
74
|
+
const spinner = ora(`Looking up clientPropertyId: ${chalk.yellow(clientPropertyId)}`).start();
|
|
107
75
|
let clientProperties;
|
|
108
76
|
try {
|
|
109
77
|
clientProperties = await cpidLookup(clientPropertyId, options);
|
|
110
|
-
spinner.succeed(
|
|
111
|
-
`Looking up clientPropertyId: ${chalk.green(clientPropertyId)}`
|
|
112
|
-
);
|
|
78
|
+
spinner.succeed(`Looking up clientPropertyId: ${chalk.green(clientPropertyId)}`);
|
|
113
79
|
} catch (err) {
|
|
114
|
-
spinner.fail(
|
|
115
|
-
`Unable to find client details for '${chalk.red(clientPropertyId)}':`,
|
|
116
|
-
err.message
|
|
117
|
-
);
|
|
80
|
+
spinner.fail(`Unable to find client details for '${chalk.red(clientPropertyId)}':`, err.message);
|
|
118
81
|
|
|
119
82
|
return;
|
|
120
83
|
}
|
|
@@ -127,83 +90,30 @@ module.exports = async (root, options = {}) => {
|
|
|
127
90
|
|
|
128
91
|
console.log(`\nScaffolding project in ${chalk.bold(outDir)}…`);
|
|
129
92
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
`globals`
|
|
134
|
-
);
|
|
135
|
-
const templateDir = path.resolve(
|
|
136
|
-
__dirname,
|
|
137
|
-
'../../repo-templates',
|
|
138
|
-
`template-${templateName}`
|
|
139
|
-
);
|
|
140
|
-
|
|
141
|
-
const renameFiles = {
|
|
142
|
-
_gitignore: '.gitignore',
|
|
143
|
-
};
|
|
144
|
-
|
|
145
|
-
function copy(src, dest) {
|
|
146
|
-
const stat = fs.statSync(src);
|
|
147
|
-
if (stat.isDirectory()) {
|
|
148
|
-
copyDir(src, dest);
|
|
149
|
-
} else {
|
|
150
|
-
fs.copyFileSync(src, dest);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
function copyDir(srcDir, destDir) {
|
|
155
|
-
fs.mkdirSync(destDir, { recursive: true });
|
|
156
|
-
for (const file of fs.readdirSync(srcDir)) {
|
|
157
|
-
const srcFile = path.resolve(srcDir, file);
|
|
158
|
-
const destFile = path.resolve(destDir, file);
|
|
159
|
-
copy(srcFile, destFile);
|
|
160
|
-
}
|
|
161
|
-
}
|
|
93
|
+
// copy boilerplate to output dir
|
|
94
|
+
const templateDir = path.resolve(__dirname, '../../repo-template');
|
|
95
|
+
fs.cpSync(templateDir, outDir, { recursive: true });
|
|
162
96
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
if (content) {
|
|
166
|
-
fs.writeFileSync(targetPath, content);
|
|
167
|
-
} else {
|
|
168
|
-
copy(path.join(templateDir, file), targetPath);
|
|
169
|
-
}
|
|
170
|
-
};
|
|
171
|
-
|
|
172
|
-
copy(templateGlobalsDir, outDir);
|
|
173
|
-
|
|
174
|
-
const files = fs.readdirSync(templateDir);
|
|
175
|
-
for (const file of files.filter((f) => f !== 'package.json')) {
|
|
176
|
-
write(file);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// create package.json
|
|
180
|
-
const pkg = JSON.parse(
|
|
181
|
-
fs.readFileSync(path.join(templateDir, 'package.json'), 'utf-8')
|
|
182
|
-
);
|
|
97
|
+
// Update new package.json
|
|
98
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(outDir, 'package.json'), 'utf-8'));
|
|
183
99
|
pkg.name = `madgex-${clientPropertyId}`;
|
|
100
|
+
pkg.devDependencies['@madgex/fert'] = `^${fertPackageJSON.version}`;
|
|
184
101
|
pkg.description = `Branding repo for ${clientProperties.brandName}`;
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
);
|
|
192
|
-
|
|
193
|
-
FERT_CONFIG_FILENAME,
|
|
194
|
-
fertConfigJs.replace(/{CPID}/gi, clientPropertyId)
|
|
195
|
-
);
|
|
102
|
+
pkg.repository.url = `git+https://github.com/wiley/madgex-${clientPropertyId}.git`;
|
|
103
|
+
pkg.homepage = `https://github.com/wiley/madgex-${clientPropertyId}#readme`;
|
|
104
|
+
fs.writeFileSync(path.join(outDir, 'package.json'), JSON.stringify(pkg, null, 2) + '\n');
|
|
105
|
+
|
|
106
|
+
// Update fert.config.js
|
|
107
|
+
const fertConfigPath = path.join(outDir, FERT_CONFIG_FILENAME);
|
|
108
|
+
const fertConfigJs = fs.readFileSync(fertConfigPath, 'utf-8');
|
|
109
|
+
fs.writeFileSync(fertConfigPath, fertConfigJs.replace(/{CPID}/gi, clientPropertyId));
|
|
196
110
|
|
|
197
111
|
const cdProjectName = path.relative(cwd, outDir);
|
|
198
112
|
|
|
199
113
|
console.log(`\nDone. Now run:\n`);
|
|
200
114
|
|
|
201
115
|
if (cdProjectName && root !== cwd) {
|
|
202
|
-
console.log(
|
|
203
|
-
` cd ${
|
|
204
|
-
cdProjectName.includes(' ') ? `"${cdProjectName}"` : cdProjectName
|
|
205
|
-
}`
|
|
206
|
-
);
|
|
116
|
+
console.log(` cd ${cdProjectName.includes(' ') ? `"${cdProjectName}"` : cdProjectName}`);
|
|
207
117
|
}
|
|
208
118
|
|
|
209
119
|
console.log(` npm install`);
|
|
@@ -19,10 +19,7 @@ module.exports = class AssetStoreUploader {
|
|
|
19
19
|
}
|
|
20
20
|
|
|
21
21
|
buildAbsolutePath(relativePath, ...parts) {
|
|
22
|
-
return new URL(
|
|
23
|
-
path.posix.join(this.basePath, relativePath, ...parts),
|
|
24
|
-
this.apiUrl
|
|
25
|
-
);
|
|
22
|
+
return new URL(path.posix.join(this.basePath, relativePath, ...parts), this.apiUrl);
|
|
26
23
|
}
|
|
27
24
|
|
|
28
25
|
async upload(file, dest) {
|
|
@@ -106,7 +103,7 @@ module.exports = class AssetStoreUploader {
|
|
|
106
103
|
log.info(
|
|
107
104
|
`CloudFront cache invalidation sent for the following paths${
|
|
108
105
|
distributionId ? ` (distribution id: ${distributionId})` : ''
|
|
109
|
-
}:\n${JSON.stringify(paths)}\n
|
|
106
|
+
}:\n${JSON.stringify(paths)}\n`,
|
|
110
107
|
);
|
|
111
108
|
}
|
|
112
109
|
// Returns array of all files in provided directory (recursive)
|
package/bin/commands/publish.js
CHANGED
|
@@ -5,9 +5,7 @@ const { resolveConfig } = require('../utils');
|
|
|
5
5
|
const { log } = require('../utils/logging');
|
|
6
6
|
const getAwsParam = require('./publish-tasks/get-aws-parameter');
|
|
7
7
|
const AssetStoreUploader = require('./publish-tasks/asset-store-uploader');
|
|
8
|
-
const {
|
|
9
|
-
getCloudFrontDistributionsForDomain,
|
|
10
|
-
} = require('../utils/lookup-cf-distribution-ids');
|
|
8
|
+
const { getCloudFrontDistributionsForDomain } = require('../utils/lookup-cf-distribution-ids');
|
|
11
9
|
const {
|
|
12
10
|
ASSET_STORE_API,
|
|
13
11
|
AWS_PARAM_NAME,
|
|
@@ -23,13 +21,12 @@ module.exports = async (options) => {
|
|
|
23
21
|
|
|
24
22
|
// handle legacy options
|
|
25
23
|
if (options.target === 'prod') {
|
|
24
|
+
// eslint-disable-next-line no-param-reassign
|
|
26
25
|
options.target = 'production';
|
|
27
26
|
}
|
|
28
27
|
|
|
29
28
|
if (!validTargets.includes(options.target)) {
|
|
30
|
-
throw Error(
|
|
31
|
-
`Missing or invalid --target option. Choose from [${validTargets}]`
|
|
32
|
-
);
|
|
29
|
+
throw Error(`Missing or invalid --target option. Choose from [${validTargets}]`);
|
|
33
30
|
}
|
|
34
31
|
|
|
35
32
|
if (options.dryRun) {
|
|
@@ -46,29 +43,18 @@ module.exports = async (options) => {
|
|
|
46
43
|
const apiUrl = Hoek.reachTemplate(templateCtx, ASSET_STORE_API);
|
|
47
44
|
const remoteBasePath = Hoek.reachTemplate(templateCtx, REMOTE_UPLOAD_BASE);
|
|
48
45
|
const apiKeyParamPath = Hoek.reachTemplate(templateCtx, AWS_PARAM_NAME);
|
|
49
|
-
const assetStoreInvPath = Hoek.reachTemplate(
|
|
50
|
-
|
|
51
|
-
ASSET_STORE_INVALIDATION_PATH
|
|
52
|
-
);
|
|
53
|
-
const brandedSiteInvPath = Hoek.reachTemplate(
|
|
54
|
-
templateCtx,
|
|
55
|
-
BRANDED_SITE_INVALIDATION_PATH
|
|
56
|
-
);
|
|
46
|
+
const assetStoreInvPath = Hoek.reachTemplate(templateCtx, ASSET_STORE_INVALIDATION_PATH);
|
|
47
|
+
const brandedSiteInvPath = Hoek.reachTemplate(templateCtx, BRANDED_SITE_INVALIDATION_PATH);
|
|
57
48
|
|
|
58
49
|
const apiKey = await getAwsParam(apiKeyParamPath);
|
|
59
50
|
|
|
60
51
|
const siteUrl = new URL(fertConfig.config.JobseekerSiteWebSitePath);
|
|
61
|
-
const clientCloudFrontDists = await getCloudFrontDistributionsForDomain(
|
|
62
|
-
siteUrl.hostname,
|
|
63
|
-
options
|
|
64
|
-
);
|
|
52
|
+
const clientCloudFrontDists = await getCloudFrontDistributionsForDomain(siteUrl.hostname, options);
|
|
65
53
|
|
|
66
54
|
log.info(
|
|
67
55
|
`\nPublishing ${chalk.cyan(localDir)} to ${chalk.green.bold(
|
|
68
|
-
options.target
|
|
69
|
-
)} for ${chalk.green(fertConfig.client.brandName)} ${chalk.dim(
|
|
70
|
-
`(${fertConfig.clientPropertyId})`
|
|
71
|
-
)}\n`
|
|
56
|
+
options.target,
|
|
57
|
+
)} for ${chalk.green(fertConfig.client.brandName)} ${chalk.dim(`(${fertConfig.clientPropertyId})`)}\n`,
|
|
72
58
|
);
|
|
73
59
|
|
|
74
60
|
try {
|
|
@@ -84,9 +70,7 @@ module.exports = async (options) => {
|
|
|
84
70
|
uploadResult = await assetStore.uploadDir(localDir);
|
|
85
71
|
}
|
|
86
72
|
|
|
87
|
-
log.success(
|
|
88
|
-
`Publish complete in ${((uploadResult?.duration || 1) / 1000).toFixed(0)}s\n`
|
|
89
|
-
);
|
|
73
|
+
log.success(`Publish complete in ${((uploadResult?.duration || 1) / 1000).toFixed(0)}s\n`);
|
|
90
74
|
|
|
91
75
|
// invalidate cloudfront cache
|
|
92
76
|
await assetStore.invalidatePaths([assetStoreInvPath]);
|
|
@@ -95,11 +79,7 @@ module.exports = async (options) => {
|
|
|
95
79
|
await assetStore.invalidatePaths([brandedSiteInvPath], dist.id);
|
|
96
80
|
}
|
|
97
81
|
|
|
98
|
-
log.info(
|
|
99
|
-
`\nNote cloudfront invalidations may take upto ${chalk.yellow(
|
|
100
|
-
'30 seconds'
|
|
101
|
-
)} to complete.\n`
|
|
102
|
-
);
|
|
82
|
+
log.info(`\nNote cloudfront invalidations may take upto ${chalk.yellow('30 seconds')} to complete.\n`);
|
|
103
83
|
} catch (error) {
|
|
104
84
|
log.error('An error occurred during the publish process', error);
|
|
105
85
|
}
|
package/bin/utils/configs.js
CHANGED
|
@@ -16,11 +16,7 @@ const { CONFIG_DIR } = require('../../constants');
|
|
|
16
16
|
* @returns {Promise<void>} - Returns a promise that resolves if all configurations are valid.
|
|
17
17
|
* @throws {Error} - Throws an error if any configuration is invalid.
|
|
18
18
|
*/
|
|
19
|
-
const validateLocalConfigs = async ({
|
|
20
|
-
workingDir,
|
|
21
|
-
clientPropertyId,
|
|
22
|
-
throwable = true,
|
|
23
|
-
}) => {
|
|
19
|
+
const validateLocalConfigs = async ({ workingDir, clientPropertyId, throwable = true }) => {
|
|
24
20
|
Hoek.assert(clientPropertyId, 'clientPropertyId is required');
|
|
25
21
|
Hoek.assert(workingDir, 'workingDir is required');
|
|
26
22
|
|
|
@@ -36,55 +32,44 @@ const validateLocalConfigs = async ({
|
|
|
36
32
|
});
|
|
37
33
|
const localConfigs = loadLocalConfigs(workingDir);
|
|
38
34
|
|
|
39
|
-
const validationPromises = Object.keys(localConfigs).map(
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const isSchemaReadOnly = api._isSchemaReadOnly(schema);
|
|
35
|
+
const validationPromises = Object.keys(localConfigs).map(async (configName) => {
|
|
36
|
+
try {
|
|
37
|
+
const schema = api.getSchema(configName);
|
|
38
|
+
const isSchemaReadOnly = api._isSchemaReadOnly(schema);
|
|
44
39
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
);
|
|
49
|
-
}
|
|
40
|
+
if (isSchemaReadOnly) {
|
|
41
|
+
throw Error(`You're trying to set values on a read-only (usually V5) config schema: ${configName}`);
|
|
42
|
+
}
|
|
50
43
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
);
|
|
57
|
-
}
|
|
44
|
+
// check the entire config against the config validation
|
|
45
|
+
const { error } = schema.validate(localConfigs[configName].data);
|
|
46
|
+
if (error) {
|
|
47
|
+
throw new Error(`Config invalid: ${chalk.bold(localConfigs[configName].path)} - ${error.message}`);
|
|
48
|
+
}
|
|
58
49
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
`You're trying to set a read-only key on a config schema: ${configName}/${key}`
|
|
66
|
-
);
|
|
67
|
-
}
|
|
50
|
+
// validate all keys individually against the schema keys to ensure we're not trying to set any read-only keys
|
|
51
|
+
const config = localConfigs[configName].data;
|
|
52
|
+
for (const key in config) {
|
|
53
|
+
const keySchema = schema.extract(key);
|
|
54
|
+
if (api._isSchemaReadOnly(keySchema)) {
|
|
55
|
+
throw new Error(`You're trying to set a read-only key on a config schema: ${configName}/${key}`);
|
|
68
56
|
}
|
|
57
|
+
}
|
|
69
58
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
59
|
+
log.success(`Config validated:`, chalk.bold(configName));
|
|
60
|
+
} catch (err) {
|
|
61
|
+
log.error(err.message);
|
|
73
62
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
}
|
|
63
|
+
if (throwable) {
|
|
64
|
+
throw err;
|
|
77
65
|
}
|
|
78
66
|
}
|
|
79
|
-
);
|
|
67
|
+
});
|
|
80
68
|
|
|
81
69
|
await Promise.all(validationPromises);
|
|
82
70
|
};
|
|
83
71
|
|
|
84
|
-
const getConfigAPI = async ({
|
|
85
|
-
clientPropertyId,
|
|
86
|
-
environment = 'production',
|
|
87
|
-
} = {}) => {
|
|
72
|
+
const getConfigAPI = async ({ clientPropertyId, environment = 'production' } = {}) => {
|
|
88
73
|
const { ConfigAPI } = await import('@madgex/config-api-sdk');
|
|
89
74
|
|
|
90
75
|
const api = new ConfigAPI({
|
|
@@ -143,11 +128,7 @@ const loadLocalConfigs = (workingDir) => {
|
|
|
143
128
|
*
|
|
144
129
|
* @returns {Promise<boolean>} - Returns a promise that resolves to true if the update is successful.
|
|
145
130
|
*/
|
|
146
|
-
const updateProjectConfigs = async ({
|
|
147
|
-
clientPropertyId,
|
|
148
|
-
workingDir,
|
|
149
|
-
environment = 'production',
|
|
150
|
-
} = {}) => {
|
|
131
|
+
const updateProjectConfigs = async ({ clientPropertyId, workingDir, environment = 'production' } = {}) => {
|
|
151
132
|
Hoek.assert(clientPropertyId, 'clientPropertyId is required');
|
|
152
133
|
Hoek.assert(workingDir, 'workingDir is required');
|
|
153
134
|
|
|
@@ -174,7 +155,7 @@ const updateProjectConfigs = async ({
|
|
|
174
155
|
const { host } = new URL(api.options.apiUrl);
|
|
175
156
|
log.info(``);
|
|
176
157
|
log.info(`Project configs applied to ${chalk.bold(host)}`);
|
|
177
|
-
return
|
|
158
|
+
return;
|
|
178
159
|
} catch (error) {
|
|
179
160
|
log.info(``);
|
|
180
161
|
log.error('Failed to apply project configs', error);
|
|
@@ -186,48 +167,37 @@ const collateConfigs = (api, localConfigs) => {
|
|
|
186
167
|
const toRemove = {};
|
|
187
168
|
const toSet = {};
|
|
188
169
|
|
|
189
|
-
Object.entries(localConfigs).forEach(
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
const isSchemaReadOnly = api._isSchemaReadOnly(schema);
|
|
170
|
+
Object.entries(localConfigs).forEach(([configName, { data: config = {} } = {}]) => {
|
|
171
|
+
const schema = api.getSchema(configName);
|
|
172
|
+
const isSchemaReadOnly = api._isSchemaReadOnly(schema);
|
|
193
173
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
174
|
+
if (isSchemaReadOnly) {
|
|
175
|
+
log.warn(`Skipping read-only schema: ${configName}`);
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
198
178
|
|
|
199
|
-
|
|
179
|
+
const configDefault = api._getDefaultConfig(configName);
|
|
200
180
|
|
|
201
|
-
|
|
202
|
-
configDefault,
|
|
203
|
-
config
|
|
204
|
-
);
|
|
181
|
+
const unsetKeysWithDefaults = getUnsetKeysWithDefaults(configDefault, config);
|
|
205
182
|
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
}
|
|
183
|
+
// remove any keys that are read-only from the unset keys collection
|
|
184
|
+
// we don't want to be deleting those!
|
|
185
|
+
for (const key in unsetKeysWithDefaults) {
|
|
186
|
+
if (api._isSchemaReadOnly(schema.extract(key))) {
|
|
187
|
+
delete unsetKeysWithDefaults[key];
|
|
212
188
|
}
|
|
213
|
-
|
|
214
|
-
toRemove[configName] = Object.keys(unsetKeysWithDefaults);
|
|
215
|
-
toSet[configName] = config;
|
|
216
189
|
}
|
|
217
|
-
|
|
190
|
+
|
|
191
|
+
toRemove[configName] = Object.keys(unsetKeysWithDefaults);
|
|
192
|
+
toSet[configName] = config;
|
|
193
|
+
});
|
|
218
194
|
|
|
219
195
|
return { toRemove, toSet };
|
|
220
196
|
};
|
|
221
197
|
|
|
222
198
|
const getUnsetKeysWithDefaults = (defaults = {}, config = {}) => {
|
|
223
|
-
Hoek.assert(
|
|
224
|
-
|
|
225
|
-
'defaults must be an object'
|
|
226
|
-
);
|
|
227
|
-
Hoek.assert(
|
|
228
|
-
typeof config === 'object' && config !== null,
|
|
229
|
-
'config must be an object'
|
|
230
|
-
);
|
|
199
|
+
Hoek.assert(typeof defaults === 'object' && defaults !== null, 'defaults must be an object');
|
|
200
|
+
Hoek.assert(typeof config === 'object' && config !== null, 'config must be an object');
|
|
231
201
|
|
|
232
202
|
const diff = {};
|
|
233
203
|
for (const key in defaults) {
|
|
@@ -243,17 +213,12 @@ const removeConfigs = async (api, toRemove) => {
|
|
|
243
213
|
keys.map(async (key) => {
|
|
244
214
|
try {
|
|
245
215
|
await api.deleteConfig(configName, key);
|
|
246
|
-
log.success(
|
|
247
|
-
`Successfully removed ${chalk.bold(key)} from ${chalk.bold(configName)}`
|
|
248
|
-
);
|
|
216
|
+
log.success(`Successfully removed ${chalk.bold(key)} from ${chalk.bold(configName)}`);
|
|
249
217
|
} catch (error) {
|
|
250
|
-
log.error(
|
|
251
|
-
`Failed to remove ${chalk.bold(key)} from ${chalk.bold(configName)}:`,
|
|
252
|
-
error
|
|
253
|
-
);
|
|
218
|
+
log.error(`Failed to remove ${chalk.bold(key)} from ${chalk.bold(configName)}:`, error);
|
|
254
219
|
throw error;
|
|
255
220
|
}
|
|
256
|
-
})
|
|
221
|
+
}),
|
|
257
222
|
);
|
|
258
223
|
|
|
259
224
|
return Promise.all(operations);
|
|
@@ -264,17 +229,12 @@ const setConfigs = async (api, toSet) => {
|
|
|
264
229
|
Object.entries(config).map(async ([key, value]) => {
|
|
265
230
|
try {
|
|
266
231
|
await api.setConfig(configName, key, value);
|
|
267
|
-
log.success(
|
|
268
|
-
`Successfully set ${chalk.bold(key)} in ${chalk.bold(configName)}`
|
|
269
|
-
);
|
|
232
|
+
log.success(`Successfully set ${chalk.bold(key)} in ${chalk.bold(configName)}`);
|
|
270
233
|
} catch (error) {
|
|
271
|
-
log.error(
|
|
272
|
-
`Failed to set ${chalk.bold(key)} in ${chalk.bold(configName)}:`,
|
|
273
|
-
error
|
|
274
|
-
);
|
|
234
|
+
log.error(`Failed to set ${chalk.bold(key)} in ${chalk.bold(configName)}:`, error);
|
|
275
235
|
throw error;
|
|
276
236
|
}
|
|
277
|
-
})
|
|
237
|
+
}),
|
|
278
238
|
);
|
|
279
239
|
|
|
280
240
|
return Promise.all(operations);
|
package/bin/utils/cpid-lookup.js
CHANGED
|
@@ -19,8 +19,8 @@ exports.doCpidLookup = async (clientPropertyId) => {
|
|
|
19
19
|
.catch((error) => {
|
|
20
20
|
log.error(
|
|
21
21
|
`Unable to lookup CPID [${chalk.yellow(
|
|
22
|
-
clientPropertyId
|
|
23
|
-
)}] from ${chalk.cyan(API_URL)}: ${chalk.redBright(error.message)}\n
|
|
22
|
+
clientPropertyId,
|
|
23
|
+
)}] from ${chalk.cyan(API_URL)}: ${chalk.redBright(error.message)}\n`,
|
|
24
24
|
);
|
|
25
25
|
|
|
26
26
|
throw Error(error.message);
|
|
@@ -26,10 +26,7 @@ exports.cpIdMatchesGitRemote = async (fertConfig) => {
|
|
|
26
26
|
baseDir: fertConfig.workingDir,
|
|
27
27
|
};
|
|
28
28
|
const git = simpleGit(simpleGitOptions);
|
|
29
|
-
Hoek.assert(
|
|
30
|
-
await git.checkIsRepo(),
|
|
31
|
-
`detected fert config in${fertConfigDir}, but it is not a git repository`
|
|
32
|
-
);
|
|
29
|
+
Hoek.assert(await git.checkIsRepo(), `detected fert config in${fertConfigDir}, but it is not a git repository`);
|
|
33
30
|
|
|
34
31
|
// Validate that the CPID in the fert config matches the CPID in the git remote URL
|
|
35
32
|
try {
|
|
@@ -38,22 +35,20 @@ exports.cpIdMatchesGitRemote = async (fertConfig) => {
|
|
|
38
35
|
const repo = parts[parts.length - 1].trim();
|
|
39
36
|
const remoteUrlCpid = repo.split('madgex-')[1].trim().replace('.git', '');
|
|
40
37
|
|
|
41
|
-
if (remoteUrlCpid
|
|
38
|
+
if (remoteUrlCpid === fertConfig.clientPropertyId) {
|
|
42
39
|
return true;
|
|
43
40
|
}
|
|
44
41
|
|
|
45
42
|
// Big ugly console message for high visibility.
|
|
46
43
|
console.log(
|
|
47
44
|
dedent`
|
|
48
|
-
${chalk.bgRed.bold(
|
|
49
|
-
'💀 💀 💀 Client Property IDs do not match! 💀 💀 💀 '
|
|
50
|
-
)}
|
|
45
|
+
${chalk.bgRed.bold('💀 💀 💀 Client Property IDs do not match! 💀 💀 💀 ')}
|
|
51
46
|
${chalk.red('CPID from fert.config.js:')} ${fertConfig.clientPropertyId}
|
|
52
47
|
${chalk.red('CPID from Git remote URL:')} ${remoteUrlCpid}
|
|
53
48
|
${chalk.bgYellow.bold(
|
|
54
|
-
'🤓 Please ensure that the Client Property Id from the fert.config.js and the git remote match 🧐 '
|
|
49
|
+
'🤓 Please ensure that the Client Property Id from the fert.config.js and the git remote match 🧐 ',
|
|
55
50
|
)}\n
|
|
56
|
-
|
|
51
|
+
`,
|
|
57
52
|
);
|
|
58
53
|
} catch (error) {
|
|
59
54
|
console.log(error);
|