@commercetools-frontend/application-cli 1.4.0 → 1.5.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/bin/cli.js +9 -0
- package/cli/dist/commercetools-frontend-application-cli-cli.cjs.d.ts +2 -0
- package/cli/dist/commercetools-frontend-application-cli-cli.cjs.d.ts.map +1 -0
- package/cli/dist/commercetools-frontend-application-cli-cli.cjs.dev.js +725 -0
- package/cli/dist/commercetools-frontend-application-cli-cli.cjs.js +7 -0
- package/cli/dist/commercetools-frontend-application-cli-cli.cjs.prod.js +725 -0
- package/cli/dist/commercetools-frontend-application-cli-cli.esm.js +699 -0
- package/cli/package.json +4 -0
- package/dist/declarations/src/cli.d.ts +2 -0
- package/dist/declarations/src/commands/compile-deployments.d.ts +3 -0
- package/dist/declarations/src/commands/compile-menu.d.ts +3 -0
- package/dist/declarations/src/commands/create-version.d.ts +3 -0
- package/dist/declarations/src/commands/validate-menu.d.ts +5 -0
- package/dist/declarations/src/schema.d.ts +228 -0
- package/dist/declarations/src/types.d.ts +92 -0
- package/dist/declarations/src/utils/create-application-assets-upload-script.d.ts +3 -0
- package/dist/declarations/src/utils/create-application-index-upload-script.d.ts +3 -0
- package/dist/declarations/src/utils/get-application-directory.d.ts +2 -0
- package/dist/declarations/src/utils/is-ci.d.ts +2 -0
- package/dist/declarations/src/utils/load-dotenv-files.d.ts +5 -0
- package/dist/declarations/src/utils/resolve-in-application.d.ts +2 -0
- package/package.json +27 -9
- package/src/bin/cli.js +0 -100
- package/src/commands/compile-deployments.js +0 -283
- package/src/commands/compile-menu.js +0 -126
- package/src/commands/create-version.js +0 -43
- package/src/commands/validate-menu.js +0 -33
- package/src/commands/validate-menu.spec.js +0 -43
- package/src/schema.js +0 -112
- package/src/utils/create-application-assets-upload-script.js +0 -62
- package/src/utils/create-application-index-upload-script.js +0 -41
- package/src/utils/get-application-directory.js +0 -7
- package/src/utils/is-ci.js +0 -5
- package/src/utils/load-dotenv-files.js +0 -48
- package/src/utils/resolve-in-application.js +0 -8
|
@@ -0,0 +1,725 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var cac = require('cac');
|
|
6
|
+
var _Object$keys = require('@babel/runtime-corejs3/core-js-stable/object/keys');
|
|
7
|
+
var _Object$getOwnPropertySymbols = require('@babel/runtime-corejs3/core-js-stable/object/get-own-property-symbols');
|
|
8
|
+
var _Object$getOwnPropertyDescriptor = require('@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptor');
|
|
9
|
+
var _forEachInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/for-each');
|
|
10
|
+
var _Object$getOwnPropertyDescriptors = require('@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptors');
|
|
11
|
+
var _Object$defineProperties = require('@babel/runtime-corejs3/core-js-stable/object/define-properties');
|
|
12
|
+
var _Object$defineProperty = require('@babel/runtime-corejs3/core-js-stable/object/define-property');
|
|
13
|
+
var _slicedToArray = require('@babel/runtime-corejs3/helpers/slicedToArray');
|
|
14
|
+
var _defineProperty = require('@babel/runtime-corejs3/helpers/defineProperty');
|
|
15
|
+
var _filterInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/filter');
|
|
16
|
+
var _concatInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/concat');
|
|
17
|
+
var _mapInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/map');
|
|
18
|
+
var _Object$entries = require('@babel/runtime-corejs3/core-js-stable/object/entries');
|
|
19
|
+
var fs = require('fs');
|
|
20
|
+
var path = require('path');
|
|
21
|
+
var listr2 = require('listr2');
|
|
22
|
+
var execa = require('execa');
|
|
23
|
+
var cosmiconfig = require('cosmiconfig');
|
|
24
|
+
var findRoot = require('@manypkg/find-root');
|
|
25
|
+
var dotenv = require('dotenv');
|
|
26
|
+
var _findInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/find');
|
|
27
|
+
var _JSON$stringify = require('@babel/runtime-corejs3/core-js-stable/json/stringify');
|
|
28
|
+
var applicationConfig = require('@commercetools-frontend/application-config');
|
|
29
|
+
var _sliceInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/slice');
|
|
30
|
+
var fetch = require('node-fetch');
|
|
31
|
+
var jsonschema = require('jsonschema');
|
|
32
|
+
|
|
33
|
+
function _interopDefault (e) { return e && e.__esModule ? e : { 'default': e }; }
|
|
34
|
+
|
|
35
|
+
var _Object$keys__default = /*#__PURE__*/_interopDefault(_Object$keys);
|
|
36
|
+
var _Object$getOwnPropertySymbols__default = /*#__PURE__*/_interopDefault(_Object$getOwnPropertySymbols);
|
|
37
|
+
var _Object$getOwnPropertyDescriptor__default = /*#__PURE__*/_interopDefault(_Object$getOwnPropertyDescriptor);
|
|
38
|
+
var _forEachInstanceProperty__default = /*#__PURE__*/_interopDefault(_forEachInstanceProperty);
|
|
39
|
+
var _Object$getOwnPropertyDescriptors__default = /*#__PURE__*/_interopDefault(_Object$getOwnPropertyDescriptors);
|
|
40
|
+
var _Object$defineProperties__default = /*#__PURE__*/_interopDefault(_Object$defineProperties);
|
|
41
|
+
var _Object$defineProperty__default = /*#__PURE__*/_interopDefault(_Object$defineProperty);
|
|
42
|
+
var _filterInstanceProperty__default = /*#__PURE__*/_interopDefault(_filterInstanceProperty);
|
|
43
|
+
var _concatInstanceProperty__default = /*#__PURE__*/_interopDefault(_concatInstanceProperty);
|
|
44
|
+
var _mapInstanceProperty__default = /*#__PURE__*/_interopDefault(_mapInstanceProperty);
|
|
45
|
+
var _Object$entries__default = /*#__PURE__*/_interopDefault(_Object$entries);
|
|
46
|
+
var fs__default = /*#__PURE__*/_interopDefault(fs);
|
|
47
|
+
var path__default = /*#__PURE__*/_interopDefault(path);
|
|
48
|
+
var execa__default = /*#__PURE__*/_interopDefault(execa);
|
|
49
|
+
var dotenv__default = /*#__PURE__*/_interopDefault(dotenv);
|
|
50
|
+
var _findInstanceProperty__default = /*#__PURE__*/_interopDefault(_findInstanceProperty);
|
|
51
|
+
var _JSON$stringify__default = /*#__PURE__*/_interopDefault(_JSON$stringify);
|
|
52
|
+
var _sliceInstanceProperty__default = /*#__PURE__*/_interopDefault(_sliceInstanceProperty);
|
|
53
|
+
var fetch__default = /*#__PURE__*/_interopDefault(fetch);
|
|
54
|
+
|
|
55
|
+
function getApplicationDirectory(cwd) {
|
|
56
|
+
return fs__default["default"].realpathSync(cwd);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function resolveInApplication(relativePath, cwd) {
|
|
60
|
+
return path__default["default"].resolve(getApplicationDirectory(cwd), relativePath);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function isCI() {
|
|
64
|
+
// @ts-expect-error The env is sometimes overwritten by code to a boolean
|
|
65
|
+
return process.env.CI === true || process.env.CI === 'true';
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function createApplicationIndexUploadScript(_ref) {
|
|
69
|
+
var _context, _context2, _context3, _context4, _context5, _context6, _context7, _context8, _context9, _context10;
|
|
70
|
+
let packageManagerName = _ref.packageManagerName,
|
|
71
|
+
bucketUrl = _ref.bucketUrl,
|
|
72
|
+
cdnUrl = _ref.cdnUrl,
|
|
73
|
+
cloudEnvironment = _ref.cloudEnvironment,
|
|
74
|
+
buildRevision = _ref.buildRevision,
|
|
75
|
+
buildNumber = _ref.buildNumber,
|
|
76
|
+
applicationIndexOutFile = _ref.applicationIndexOutFile;
|
|
77
|
+
const uploadScriptContent = _concatInstanceProperty__default["default"](_context = _concatInstanceProperty__default["default"](_context2 = _concatInstanceProperty__default["default"](_context3 = _concatInstanceProperty__default["default"](_context4 = _concatInstanceProperty__default["default"](_context5 = _concatInstanceProperty__default["default"](_context6 = _concatInstanceProperty__default["default"](_context7 = _concatInstanceProperty__default["default"](_context8 = _concatInstanceProperty__default["default"](_context9 = _concatInstanceProperty__default["default"](_context10 = "#!/usr/bin/env bash\n\nset -e\n\necho \"Uploading compiled ".concat(applicationIndexOutFile, " to bucket ")).call(_context10, bucketUrl, "\"\ngsutil \\\n-h \"Content-Type: text/html\" \\\n-h \"Cache-Control: public, max-age=0, no-transform\" \\\ncp -z html \\\n\"$(dirname \"$0\")/")).call(_context9, applicationIndexOutFile, "\" \\\n\"")).call(_context8, bucketUrl, "/\"\n\necho \"Creating version.json and uploading it to bucket ")).call(_context7, bucketUrl, "\"\n\nNODE_ENV=production ")).call(_context6, packageManagerName, " application-cli create-version \\\n --version-url=")).call(_context5, cdnUrl, "/")).call(_context4, cloudEnvironment, "/version.json \\\n --build-revision=")).call(_context3, buildRevision, " \\\n --build-number=")).call(_context2, buildNumber, " \\\n --out-file=$(dirname \"$0\")/version.json\n\ngsutil \\\n-h \"Content-Type: application/json\" \\\n-h \"Cache-Control: private, max-age=0, no-transform\" \\\ncp -z json \\\n\"$(dirname \"$0\")/version.json\" \\\n\"")).call(_context, bucketUrl, "/\"\n");
|
|
78
|
+
return uploadScriptContent;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function createApplicationAssetsUploadScript(_ref) {
|
|
82
|
+
var _context, _context2, _context3, _context4, _context5, _context6;
|
|
83
|
+
let bucketUrl = _ref.bucketUrl,
|
|
84
|
+
assetsPath = _ref.assetsPath,
|
|
85
|
+
skipMenu = _ref.skipMenu;
|
|
86
|
+
const uploadScriptContent = _concatInstanceProperty__default["default"](_context = _concatInstanceProperty__default["default"](_context2 = _concatInstanceProperty__default["default"](_context3 = _concatInstanceProperty__default["default"](_context4 = _concatInstanceProperty__default["default"](_context5 = _concatInstanceProperty__default["default"](_context6 = "#!/usr/bin/env bash\n\nset -e\n\n# NOTES:\n# https://cloud.google.com/storage/docs/gsutil/commands/cp#options\n# 1. The '-z' option triggers compressing the assets before\n# uploading them and sets the 'Content-Encoding' to 'gzip'.\n# 2. The 'Accept-encoding: gzip' is set automatically by the 'gsutils'.\n# 3. The 'max-age' is set to 1 year which is considered the maximum\n# \"valid\" lifetime of an asset to be cached.\n# 5. The '-n' will skip uploading existing files and prevents them to\n# be overwritten\necho \"Uploading static assets to bucket ".concat(bucketUrl, "\"\n\ngsutil -m \\\n -h \"Cache-Control: public, max-age=31536000, no-transform\" \\\n cp -z js,css \\\n -n \\\n ")).call(_context6, assetsPath, "/public/{*.css,*.js,*.js.map,*.png,*.html,robots.txt} \\\n \"")).call(_context5, bucketUrl, "\"\n\nif ")).call(_context4, skipMenu, "; then\n echo \"Skipping menu.json upload\"\nelse\n echo \"Uploading menu.json to bucket ")).call(_context3, bucketUrl, "\"\n # NOTE: somehow the 'cache-control:private' doesn't work.\n # I mean, the file is uploaded with the correct metadata but when I fetch\n # the file the response contains the header\n # 'cache-control: public, max-age=31536000, no-transform', even though the\n # documentation clearly states that by marking the header as 'private' will\n # disable the cache (for publicly readable objects).\n # https://cloud.google.com/storage/docs/gsutil/addlhelp/WorkingWithObjectMetadata#cache-control\n # However, I found out that, by requesting the file with any RANDOM\n # query parameter, will instruct the storage to return a 'fresh' object\n # (without any cache control).\n # Unofficial source: https://stackoverflow.com/a/49052895\n # This seems to be the 'easiest' option to 'disable' the cache for public\n # objects. Other alternative approaces are:\n # * make the object private with some simple ACL (private objects are not cached)\n # * suffix the file name with e.g. the git SHA, so we have different files\n # for each upload ('index.html.template-${CIRCLE_SHA1}'). The server knows\n # the git SHA on runtime and can get the correct file when it starts.\n # * find out why the 'private' cache control does not work\n gsutil \\\n -h \"Content-Type: application/json\" \\\n -h \"Cache-Control: private, max-age=0, no-transform\" \\\n cp -z json \\\n ")).call(_context2, assetsPath, "/menu.json \\\n ")).call(_context, bucketUrl, "\nfi\n");
|
|
87
|
+
return uploadScriptContent;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function ownKeys$3(object, enumerableOnly) { var keys = _Object$keys__default["default"](object); if (_Object$getOwnPropertySymbols__default["default"]) { var symbols = _Object$getOwnPropertySymbols__default["default"](object); enumerableOnly && (symbols = _filterInstanceProperty__default["default"](symbols).call(symbols, function (sym) { return _Object$getOwnPropertyDescriptor__default["default"](object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
91
|
+
function _objectSpread$3(target) { for (var i = 1; i < arguments.length; i++) { var _context2, _context3; var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? _forEachInstanceProperty__default["default"](_context2 = ownKeys$3(Object(source), !0)).call(_context2, function (key) { _defineProperty(target, key, source[key]); }) : _Object$getOwnPropertyDescriptors__default["default"] ? _Object$defineProperties__default["default"](target, _Object$getOwnPropertyDescriptors__default["default"](source)) : _forEachInstanceProperty__default["default"](_context3 = ownKeys$3(Object(source))).call(_context3, function (key) { _Object$defineProperty__default["default"](target, key, _Object$getOwnPropertyDescriptor__default["default"](source, key)); }); } return target; }
|
|
92
|
+
function loadDotenvFiles(_ref) {
|
|
93
|
+
let dotenvPath = _ref.dotenvPath,
|
|
94
|
+
cloudEnvironment = _ref.cloudEnvironment;
|
|
95
|
+
// No path requested, skip.
|
|
96
|
+
if (!dotenvPath) {
|
|
97
|
+
return {};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Check if the given path exists.
|
|
101
|
+
if (!fs__default["default"].existsSync(dotenvPath)) {
|
|
102
|
+
throw new Error("The dotenv folder path does not exist: \"".concat(dotenvPath, "\"."));
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Load the environment values
|
|
106
|
+
const sharedDotenvFile = '.env.production';
|
|
107
|
+
const cloudDotenvFile = ".env.".concat(cloudEnvironment);
|
|
108
|
+
|
|
109
|
+
// The shared dotenv file across environments is optional
|
|
110
|
+
const sharedProductionEnvironment = dotenv__default["default"].config({
|
|
111
|
+
encoding: 'utf8',
|
|
112
|
+
path: path__default["default"].join(dotenvPath, sharedDotenvFile)
|
|
113
|
+
});
|
|
114
|
+
const cloudSpecificProductionEnvironment = dotenv__default["default"].config({
|
|
115
|
+
encoding: 'utf8',
|
|
116
|
+
path: path__default["default"].join(dotenvPath, cloudDotenvFile)
|
|
117
|
+
});
|
|
118
|
+
if (cloudSpecificProductionEnvironment.error) {
|
|
119
|
+
var _context;
|
|
120
|
+
throw new Error(_concatInstanceProperty__default["default"](_context = "Failed loading '".concat(cloudDotenvFile, "' in '")).call(_context, dotenvPath, "'. Make sure it exists."));
|
|
121
|
+
}
|
|
122
|
+
if (sharedProductionEnvironment.error) {
|
|
123
|
+
throw new Error("Failed loading '".concat(sharedDotenvFile, "' in '").concat(dotenvPath, "'. Make sure it exists."));
|
|
124
|
+
}
|
|
125
|
+
return _objectSpread$3(_objectSpread$3({}, sharedProductionEnvironment.parsed), cloudSpecificProductionEnvironment.parsed);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function ownKeys$2(object, enumerableOnly) { var keys = _Object$keys__default["default"](object); if (_Object$getOwnPropertySymbols__default["default"]) { var symbols = _Object$getOwnPropertySymbols__default["default"](object); enumerableOnly && (symbols = _filterInstanceProperty__default["default"](symbols).call(symbols, function (sym) { return _Object$getOwnPropertyDescriptor__default["default"](object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
129
|
+
function _objectSpread$2(target) { for (var i = 1; i < arguments.length; i++) { var _context8, _context9; var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? _forEachInstanceProperty__default["default"](_context8 = ownKeys$2(Object(source), !0)).call(_context8, function (key) { _defineProperty(target, key, source[key]); }) : _Object$getOwnPropertyDescriptors__default["default"] ? _Object$defineProperties__default["default"](target, _Object$getOwnPropertyDescriptors__default["default"](source)) : _forEachInstanceProperty__default["default"](_context9 = ownKeys$2(Object(source))).call(_context9, function (key) { _Object$defineProperty__default["default"](target, key, _Object$getOwnPropertyDescriptor__default["default"](source, key)); }); } return target; }
|
|
130
|
+
const buckedConfigExplorer = cosmiconfig.cosmiconfig('google-storage-buckets');
|
|
131
|
+
function writeUploadScriptFile(_ref) {
|
|
132
|
+
let fileName = _ref.fileName,
|
|
133
|
+
fileContent = _ref.fileContent,
|
|
134
|
+
filePath = _ref.filePath;
|
|
135
|
+
fs__default["default"].writeFileSync(path__default["default"].join(filePath, fileName), fileContent, {
|
|
136
|
+
// Make the script executable
|
|
137
|
+
mode: 0o755,
|
|
138
|
+
encoding: 'utf8'
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
function getBucketNamespace(prNumber) {
|
|
142
|
+
if (!prNumber) return;
|
|
143
|
+
if (prNumber === 'merchant-center-preview') return prNumber;
|
|
144
|
+
return "mc-".concat(prNumber);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Construct the storage bucket URL for the specific application and cloud environment.
|
|
149
|
+
*
|
|
150
|
+
* 1. Static assets are uploaded to `:bucketRegion/:prNumber?/:applicationName`
|
|
151
|
+
* 2. The application index is uploaded to `:bucketRegion/:prNumber?/:applicationName/:cloudEnvironment`
|
|
152
|
+
*
|
|
153
|
+
* This allows all cloud environments sharing the same static assets while each application's index
|
|
154
|
+
* is uploaded with different headers (e.g. CSP rules).
|
|
155
|
+
*/
|
|
156
|
+
|
|
157
|
+
function getApplicationAssetsBucketUrl(_ref2) {
|
|
158
|
+
var _context;
|
|
159
|
+
let bucketRegion = _ref2.bucketRegion,
|
|
160
|
+
prNumber = _ref2.prNumber,
|
|
161
|
+
applicationName = _ref2.applicationName;
|
|
162
|
+
const applicationAssetsBucketUrl = _filterInstanceProperty__default["default"](_context = ["gs://".concat(bucketRegion), getBucketNamespace(prNumber), applicationName]).call(_context, Boolean);
|
|
163
|
+
return applicationAssetsBucketUrl.join('/');
|
|
164
|
+
}
|
|
165
|
+
function getApplicationIndexBucketUrl(_ref3) {
|
|
166
|
+
var _context2;
|
|
167
|
+
let bucketRegion = _ref3.bucketRegion,
|
|
168
|
+
prNumber = _ref3.prNumber,
|
|
169
|
+
applicationName = _ref3.applicationName,
|
|
170
|
+
cloudEnvironment = _ref3.cloudEnvironment;
|
|
171
|
+
const applicationAssetsBucketUrl = getApplicationAssetsBucketUrl({
|
|
172
|
+
bucketRegion,
|
|
173
|
+
prNumber,
|
|
174
|
+
applicationName
|
|
175
|
+
});
|
|
176
|
+
const applicationIndexBucketUrl = _concatInstanceProperty__default["default"](_context2 = "".concat(applicationAssetsBucketUrl, "/")).call(_context2, cloudEnvironment);
|
|
177
|
+
return applicationIndexBucketUrl;
|
|
178
|
+
}
|
|
179
|
+
function getCdnUrl(_ref4) {
|
|
180
|
+
var _context3;
|
|
181
|
+
let bucketRegion = _ref4.bucketRegion,
|
|
182
|
+
prNumber = _ref4.prNumber,
|
|
183
|
+
applicationName = _ref4.applicationName;
|
|
184
|
+
return _filterInstanceProperty__default["default"](_context3 = ["https://storage.googleapis.com/".concat(bucketRegion), getBucketNamespace(prNumber), applicationName]).call(_context3, Boolean).join('/');
|
|
185
|
+
}
|
|
186
|
+
async function compileApplicationAssets(_ref5) {
|
|
187
|
+
var _context4, _context5;
|
|
188
|
+
let cliFlags = _ref5.cliFlags,
|
|
189
|
+
bucketRegion = _ref5.bucketRegion,
|
|
190
|
+
paths = _ref5.paths;
|
|
191
|
+
const applicationAssetsUploadScriptContent = createApplicationAssetsUploadScript({
|
|
192
|
+
bucketUrl: getApplicationAssetsBucketUrl({
|
|
193
|
+
bucketRegion,
|
|
194
|
+
prNumber: cliFlags.prNumber,
|
|
195
|
+
applicationName: cliFlags.applicationName
|
|
196
|
+
}),
|
|
197
|
+
assetsPath: paths.assetsPath,
|
|
198
|
+
skipMenu: cliFlags.skipMenu
|
|
199
|
+
});
|
|
200
|
+
const parsedApplicationAssetsUploadScriptFile = path__default["default"].parse(cliFlags.applicationAssetsUploadScriptOutFile);
|
|
201
|
+
const applicationAssetsUploadScriptFileName = _concatInstanceProperty__default["default"](_context4 = _concatInstanceProperty__default["default"](_context5 = "".concat(parsedApplicationAssetsUploadScriptFile.name, "-")).call(_context5, bucketRegion)).call(_context4, parsedApplicationAssetsUploadScriptFile.ext);
|
|
202
|
+
writeUploadScriptFile({
|
|
203
|
+
fileName: applicationAssetsUploadScriptFileName,
|
|
204
|
+
fileContent: applicationAssetsUploadScriptContent,
|
|
205
|
+
filePath: paths.deploymentsPath
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
async function compileEnvironmentApplicationIndexes(_ref6) {
|
|
209
|
+
let cliFlags = _ref6.cliFlags,
|
|
210
|
+
paths = _ref6.paths,
|
|
211
|
+
bucketRegion = _ref6.bucketRegion,
|
|
212
|
+
cloudEnvironment = _ref6.cloudEnvironment;
|
|
213
|
+
const cloudEnvironmentDeploymentPath = path__default["default"].join(paths.deploymentsPath, cloudEnvironment);
|
|
214
|
+
// Ensure the folder exists
|
|
215
|
+
const createDeploymentsFolderResult = await execa__default["default"]('mkdir', ['-p', cloudEnvironmentDeploymentPath], {
|
|
216
|
+
encoding: 'utf8'
|
|
217
|
+
});
|
|
218
|
+
if (createDeploymentsFolderResult.failed) {
|
|
219
|
+
throw new Error(createDeploymentsFolderResult.stderr);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// Construct the proper CDN URL for the specific application
|
|
223
|
+
const cdnUrl = getCdnUrl({
|
|
224
|
+
bucketRegion,
|
|
225
|
+
prNumber: cliFlags.prNumber,
|
|
226
|
+
applicationName: cliFlags.applicationName
|
|
227
|
+
});
|
|
228
|
+
const environmentVariablesForCompilation = _objectSpread$2(_objectSpread$2(_objectSpread$2(_objectSpread$2({}, loadDotenvFiles({
|
|
229
|
+
dotenvPath: paths.dotenvPath,
|
|
230
|
+
cloudEnvironment
|
|
231
|
+
})), {}, {
|
|
232
|
+
// The trailing slash is important to indicate to the CSP directive that all the resources
|
|
233
|
+
// under that path should be allowed.
|
|
234
|
+
MC_CDN_URL: "".concat(cdnUrl, "/")
|
|
235
|
+
}, cliFlags.mcUrl ? {
|
|
236
|
+
MC_URL: cliFlags.mcUrl
|
|
237
|
+
} : {}), cliFlags.mcApiUrl ? {
|
|
238
|
+
MC_API_URL: cliFlags.mcApiUrl
|
|
239
|
+
} : {}), {}, {
|
|
240
|
+
// Will be used by the Application Kit for Sentry and exposed on `window.app.revision`.
|
|
241
|
+
REVISION: cliFlags.buildRevision
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
/// Sentry and GTM is disabled on branch deployments
|
|
245
|
+
if (cliFlags.prNumber) {
|
|
246
|
+
// @ts-expect-error The env is sometimes overwritten by code to a boolean
|
|
247
|
+
process.env.TRACKING_SENTRY = null;
|
|
248
|
+
// @ts-expect-error The env is sometimes overwritten by code to a boolean
|
|
249
|
+
process.env.TRACKING_GTM = null;
|
|
250
|
+
// @ts-expect-error
|
|
251
|
+
environmentVariablesForCompilation.TRACKING_SENTRY = null;
|
|
252
|
+
// @ts-expect-error
|
|
253
|
+
environmentVariablesForCompilation.TRACKING_GTM = null;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Compile the application using the loaded environment values
|
|
257
|
+
const compileResult = await execa__default["default"]('mc-scripts', ['compile-html'], {
|
|
258
|
+
encoding: 'utf8',
|
|
259
|
+
preferLocal: true,
|
|
260
|
+
extendEnv: true,
|
|
261
|
+
env: environmentVariablesForCompilation
|
|
262
|
+
});
|
|
263
|
+
if (compileResult.failed) {
|
|
264
|
+
throw new Error(compileResult.stderr);
|
|
265
|
+
}
|
|
266
|
+
const applicationIndexUploadScriptContent = createApplicationIndexUploadScript({
|
|
267
|
+
packageManagerName: cliFlags.packageManagerName,
|
|
268
|
+
bucketUrl: getApplicationIndexBucketUrl({
|
|
269
|
+
bucketRegion,
|
|
270
|
+
prNumber: cliFlags.prNumber,
|
|
271
|
+
applicationName: cliFlags.applicationName,
|
|
272
|
+
cloudEnvironment
|
|
273
|
+
}),
|
|
274
|
+
cdnUrl,
|
|
275
|
+
cloudEnvironment,
|
|
276
|
+
buildRevision: cliFlags.buildRevision,
|
|
277
|
+
buildNumber: cliFlags.buildNumber,
|
|
278
|
+
applicationIndexOutFile: cliFlags.applicationIndexOutFile
|
|
279
|
+
});
|
|
280
|
+
// Generate bash scripts to run the `gsutil` upload command.
|
|
281
|
+
|
|
282
|
+
writeUploadScriptFile({
|
|
283
|
+
fileName: cliFlags.applicationIndexUploadScriptOutFile,
|
|
284
|
+
fileContent: applicationIndexUploadScriptContent,
|
|
285
|
+
filePath: cloudEnvironmentDeploymentPath
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
// Move the compiled `index.html` to the deployments folder of the related cloud environment.
|
|
289
|
+
|
|
290
|
+
const moveResult = await execa__default["default"]('mv', [path__default["default"].join(paths.publicAssetsPath, 'index.html'), path__default["default"].join(cloudEnvironmentDeploymentPath, cliFlags.applicationIndexOutFile)]);
|
|
291
|
+
if (moveResult.failed) {
|
|
292
|
+
throw new Error(moveResult.stderr);
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
async function command$3(cliFlags, cwd) {
|
|
296
|
+
var _context6;
|
|
297
|
+
let cloudEnvironmentsGroupedByBucketRegions;
|
|
298
|
+
try {
|
|
299
|
+
// This is the list of the supported cloud environments and their related bucket location.
|
|
300
|
+
cloudEnvironmentsGroupedByBucketRegions = await buckedConfigExplorer.search();
|
|
301
|
+
} catch (e) {
|
|
302
|
+
throw new Error('Failed loading a Google Bucket configuration. Create a cosmiconfig for `google-storage-buckets` for example `google-storage-buckets.config.cjs`.');
|
|
303
|
+
}
|
|
304
|
+
if (!cloudEnvironmentsGroupedByBucketRegions) {
|
|
305
|
+
throw new Error('Failed loading a Google Bucket configuration');
|
|
306
|
+
}
|
|
307
|
+
const applicationDirectory = getApplicationDirectory(cwd);
|
|
308
|
+
let assetsPath;
|
|
309
|
+
if (cliFlags.ciAssetsRootPath && isCI()) {
|
|
310
|
+
assetsPath = applicationDirectory.replace('/home/circleci/', cliFlags.ciAssetsRootPath);
|
|
311
|
+
} else {
|
|
312
|
+
assetsPath = applicationDirectory;
|
|
313
|
+
}
|
|
314
|
+
const monorepoRoot = findRoot.findRootSync(cwd);
|
|
315
|
+
const paths = {
|
|
316
|
+
publicAssetsPath: resolveInApplication('public', cwd),
|
|
317
|
+
deploymentsPath: resolveInApplication('deployments', cwd),
|
|
318
|
+
dotenvPath: cliFlags.dotenvFolder && path__default["default"].join(monorepoRoot.rootDir, cliFlags.dotenvFolder),
|
|
319
|
+
assetsPath
|
|
320
|
+
};
|
|
321
|
+
const taskList = new listr2.Listr(_mapInstanceProperty__default["default"](_context6 = _Object$entries__default["default"](cloudEnvironmentsGroupedByBucketRegions.config)).call(_context6, _ref7 => {
|
|
322
|
+
let _ref8 = _slicedToArray(_ref7, 2),
|
|
323
|
+
bucketRegion = _ref8[0],
|
|
324
|
+
cloudEnvironments = _ref8[1];
|
|
325
|
+
return {
|
|
326
|
+
title: "Compiling application for bucket ".concat(bucketRegion),
|
|
327
|
+
task: () => {
|
|
328
|
+
var _context7;
|
|
329
|
+
return new listr2.Listr(_concatInstanceProperty__default["default"](_context7 = _mapInstanceProperty__default["default"](cloudEnvironments).call(cloudEnvironments, cloudEnvironment => ({
|
|
330
|
+
title: "Compiling ".concat(cloudEnvironment, " application index"),
|
|
331
|
+
task: () => compileEnvironmentApplicationIndexes({
|
|
332
|
+
cliFlags,
|
|
333
|
+
paths,
|
|
334
|
+
bucketRegion,
|
|
335
|
+
cloudEnvironment
|
|
336
|
+
})
|
|
337
|
+
}))).call(_context7, {
|
|
338
|
+
title: "Compiling application assets",
|
|
339
|
+
task: () => compileApplicationAssets({
|
|
340
|
+
cliFlags,
|
|
341
|
+
bucketRegion,
|
|
342
|
+
paths
|
|
343
|
+
})
|
|
344
|
+
}));
|
|
345
|
+
}
|
|
346
|
+
};
|
|
347
|
+
}), {
|
|
348
|
+
renderer: isCI() ? 'verbose' : 'default'
|
|
349
|
+
});
|
|
350
|
+
await taskList.run();
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
function ownKeys$1(object, enumerableOnly) { var keys = _Object$keys__default["default"](object); if (_Object$getOwnPropertySymbols__default["default"]) { var symbols = _Object$getOwnPropertySymbols__default["default"](object); enumerableOnly && (symbols = _filterInstanceProperty__default["default"](symbols).call(symbols, function (sym) { return _Object$getOwnPropertyDescriptor__default["default"](object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
354
|
+
function _objectSpread$1(target) { for (var i = 1; i < arguments.length; i++) { var _context2, _context3; var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? _forEachInstanceProperty__default["default"](_context2 = ownKeys$1(Object(source), !0)).call(_context2, function (key) { _defineProperty(target, key, source[key]); }) : _Object$getOwnPropertyDescriptors__default["default"] ? _Object$defineProperties__default["default"](target, _Object$getOwnPropertyDescriptors__default["default"](source)) : _forEachInstanceProperty__default["default"](_context3 = ownKeys$1(Object(source))).call(_context3, function (key) { _Object$defineProperty__default["default"](target, key, _Object$getOwnPropertyDescriptor__default["default"](source, key)); }); } return target; }
|
|
355
|
+
|
|
356
|
+
// The menu links are only parsed from the config in development mode.
|
|
357
|
+
process.env.NODE_ENV = 'development';
|
|
358
|
+
const supportedLocales = ['en', 'de', 'es', 'fr-FR', 'zh-CN', 'ja'];
|
|
359
|
+
const mapLabelAllLocalesWithDefaults = (labelAllLocales, defaultLabel) => {
|
|
360
|
+
let mappedLabelAllLocales = labelAllLocales;
|
|
361
|
+
if (defaultLabel) {
|
|
362
|
+
// Map all supported locales with the given localized labels.
|
|
363
|
+
// If a locale is not defined in the config, we use the `default` label as the value.
|
|
364
|
+
// This is only needed for development as we're trying to map two different schemas.
|
|
365
|
+
mappedLabelAllLocales = _mapInstanceProperty__default["default"](supportedLocales).call(supportedLocales, supportedLocale => {
|
|
366
|
+
const existingField = _findInstanceProperty__default["default"](labelAllLocales).call(labelAllLocales, field => field.locale === supportedLocale);
|
|
367
|
+
if (existingField) return existingField;
|
|
368
|
+
return {
|
|
369
|
+
locale: supportedLocale,
|
|
370
|
+
value: defaultLabel
|
|
371
|
+
};
|
|
372
|
+
});
|
|
373
|
+
}
|
|
374
|
+
return mappedLabelAllLocales;
|
|
375
|
+
};
|
|
376
|
+
|
|
377
|
+
/**
|
|
378
|
+
* Transform menu links defined in the `custom-application-config.json` to the format
|
|
379
|
+
* used by the HTTP Proxy GraphQL API.
|
|
380
|
+
*/
|
|
381
|
+
|
|
382
|
+
const mapApplicationMenuConfigToGraqhQLMenuJson = config => {
|
|
383
|
+
var _ref, _config$env$__DEVELOP, _config$env$__DEVELOP2, _menuLinks$featureTog, _menuLinks$menuVisibi, _menuLinks$actionRigh, _menuLinks$dataFences, _context, _menuLinks$shouldRend;
|
|
384
|
+
const entryPointUriPath = config.env.entryPointUriPath;
|
|
385
|
+
|
|
386
|
+
// @ts-expect-error: the `accountLinks` is not explicitly typed as it's only used by the account app.
|
|
387
|
+
const accountLinks = (_ref = (_config$env$__DEVELOP = config.env.__DEVELOPMENT__) === null || _config$env$__DEVELOP === void 0 ? void 0 : _config$env$__DEVELOP.accountLinks) !== null && _ref !== void 0 ? _ref : [];
|
|
388
|
+
if (accountLinks.length > 0) {
|
|
389
|
+
return _mapInstanceProperty__default["default"](accountLinks).call(accountLinks, menuLink => {
|
|
390
|
+
var _menuLink$permissions, _menuLink$featureTogg;
|
|
391
|
+
return {
|
|
392
|
+
key: menuLink.uriPath,
|
|
393
|
+
uriPath: menuLink.uriPath,
|
|
394
|
+
labelAllLocales: mapLabelAllLocalesWithDefaults(menuLink.labelAllLocales, menuLink.defaultLabel),
|
|
395
|
+
permissions: (_menuLink$permissions = menuLink.permissions) !== null && _menuLink$permissions !== void 0 ? _menuLink$permissions : [],
|
|
396
|
+
// @ts-ignore: not defined in schema, as it's only used internally.
|
|
397
|
+
featureToggle: (_menuLink$featureTogg = menuLink.featureToggle) !== null && _menuLink$featureTogg !== void 0 ? _menuLink$featureTogg : null
|
|
398
|
+
};
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
const menuLinks = (_config$env$__DEVELOP2 = config.env.__DEVELOPMENT__) === null || _config$env$__DEVELOP2 === void 0 ? void 0 : _config$env$__DEVELOP2.menuLinks;
|
|
402
|
+
return {
|
|
403
|
+
key: entryPointUriPath,
|
|
404
|
+
uriPath: entryPointUriPath,
|
|
405
|
+
icon: menuLinks.icon,
|
|
406
|
+
labelAllLocales: mapLabelAllLocalesWithDefaults(menuLinks === null || menuLinks === void 0 ? void 0 : menuLinks.labelAllLocales, menuLinks === null || menuLinks === void 0 ? void 0 : menuLinks.defaultLabel),
|
|
407
|
+
permissions: menuLinks.permissions,
|
|
408
|
+
// @ts-ignore: not defined in schema, as it's only used internally.
|
|
409
|
+
featureToggle: (_menuLinks$featureTog = menuLinks.featureToggle) !== null && _menuLinks$featureTog !== void 0 ? _menuLinks$featureTog : null,
|
|
410
|
+
// @ts-ignore: not defined in schema, as it's only used internally.
|
|
411
|
+
menuVisibility: (_menuLinks$menuVisibi = menuLinks.menuVisibility) !== null && _menuLinks$menuVisibi !== void 0 ? _menuLinks$menuVisibi : null,
|
|
412
|
+
// @ts-ignore: not defined in schema, as it's only used internally.
|
|
413
|
+
actionRights: (_menuLinks$actionRigh = menuLinks.actionRights) !== null && _menuLinks$actionRigh !== void 0 ? _menuLinks$actionRigh : null,
|
|
414
|
+
// @ts-ignore: not defined in schema, as it's only used internally.
|
|
415
|
+
dataFences: (_menuLinks$dataFences = menuLinks.dataFences) !== null && _menuLinks$dataFences !== void 0 ? _menuLinks$dataFences : null,
|
|
416
|
+
submenu: _mapInstanceProperty__default["default"](_context = menuLinks.submenuLinks).call(_context, submenuLink => {
|
|
417
|
+
var _submenuLink$featureT, _submenuLink$menuVisi, _submenuLink$actionRi, _submenuLink$dataFenc;
|
|
418
|
+
return {
|
|
419
|
+
key: submenuLink.uriPath.replace('/', '-'),
|
|
420
|
+
uriPath: submenuLink.uriPath,
|
|
421
|
+
labelAllLocales: mapLabelAllLocalesWithDefaults(submenuLink.labelAllLocales, submenuLink.defaultLabel),
|
|
422
|
+
permissions: submenuLink.permissions,
|
|
423
|
+
// @ts-ignore: not defined in schema, as it's only used internally.
|
|
424
|
+
featureToggle: (_submenuLink$featureT = submenuLink.featureToggle) !== null && _submenuLink$featureT !== void 0 ? _submenuLink$featureT : null,
|
|
425
|
+
// @ts-ignore: not defined in schema, as it's only used internally.
|
|
426
|
+
menuVisibility: (_submenuLink$menuVisi = submenuLink.menuVisibility) !== null && _submenuLink$menuVisi !== void 0 ? _submenuLink$menuVisi : null,
|
|
427
|
+
// @ts-ignore: not defined in schema, as it's only used internally.
|
|
428
|
+
actionRights: (_submenuLink$actionRi = submenuLink.actionRights) !== null && _submenuLink$actionRi !== void 0 ? _submenuLink$actionRi : null,
|
|
429
|
+
// @ts-ignore: not defined in schema, as it's only used internally.
|
|
430
|
+
dataFences: (_submenuLink$dataFenc = submenuLink.dataFences) !== null && _submenuLink$dataFenc !== void 0 ? _submenuLink$dataFenc : null
|
|
431
|
+
};
|
|
432
|
+
}),
|
|
433
|
+
// @ts-ignore: not defined in schema, as it's only used internally.
|
|
434
|
+
shouldRenderDivider: (_menuLinks$shouldRend = menuLinks.shouldRenderDivider) !== null && _menuLinks$shouldRend !== void 0 ? _menuLinks$shouldRend : false
|
|
435
|
+
};
|
|
436
|
+
};
|
|
437
|
+
async function command$2(cliFlags, cwd) {
|
|
438
|
+
const applicationDirectory = getApplicationDirectory(cwd);
|
|
439
|
+
const monorepoRoot = findRoot.findRootSync(cwd);
|
|
440
|
+
const dotenvPath = cliFlags.dotenvFolder && path__default["default"].join(monorepoRoot.rootDir, cliFlags.dotenvFolder);
|
|
441
|
+
const processEnv = _objectSpread$1(_objectSpread$1({}, loadDotenvFiles({
|
|
442
|
+
dotenvPath,
|
|
443
|
+
// The env itself is not important for the menu. However, the application config
|
|
444
|
+
// uses environment placeholders and therefore we need to provide the variables for it.
|
|
445
|
+
cloudEnvironment: 'ctp-gcp-staging'
|
|
446
|
+
})), {}, {
|
|
447
|
+
// Again, make sure that the environment is "development", otherwise
|
|
448
|
+
// the menu config won't be available.
|
|
449
|
+
NODE_ENV: 'development',
|
|
450
|
+
MC_APP_ENV: 'development',
|
|
451
|
+
// Something random, just to have environment variable defined.
|
|
452
|
+
REVISION: '123'
|
|
453
|
+
});
|
|
454
|
+
const applicationRuntimeConfig = applicationConfig.processConfig({
|
|
455
|
+
disableCache: true,
|
|
456
|
+
applicationPath: applicationDirectory,
|
|
457
|
+
processEnv
|
|
458
|
+
});
|
|
459
|
+
const applicationMenu = mapApplicationMenuConfigToGraqhQLMenuJson(applicationRuntimeConfig);
|
|
460
|
+
const formattedJson = _JSON$stringify__default["default"](applicationMenu, null, 2);
|
|
461
|
+
fs__default["default"].writeFileSync(path__default["default"].join(applicationDirectory, 'menu.json'), formattedJson, {
|
|
462
|
+
encoding: 'utf8'
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
async function command$1(cliFlags) {
|
|
467
|
+
const numberOfRollbacks = cliFlags.rollbacks - 1;
|
|
468
|
+
let nextRollbacks;
|
|
469
|
+
try {
|
|
470
|
+
var _context, _context2;
|
|
471
|
+
// The last build's JSON becomes the first rollback
|
|
472
|
+
// while all previous rollbacks remain but are sliced.
|
|
473
|
+
const lastVersionResponse = await fetch__default["default"](cliFlags.versionUrl);
|
|
474
|
+
const lastVersionJson = await lastVersionResponse.json();
|
|
475
|
+
const previousBuild = lastVersionJson && {
|
|
476
|
+
buildNumber: lastVersionJson.buildNumber,
|
|
477
|
+
revision: lastVersionJson.revision,
|
|
478
|
+
deployedAt: lastVersionJson.deployedAt
|
|
479
|
+
};
|
|
480
|
+
nextRollbacks = _sliceInstanceProperty__default["default"](_context = _filterInstanceProperty__default["default"](_context2 = [previousBuild, ...lastVersionJson.rollbacks]).call(_context2, Boolean)).call(_context, 0, numberOfRollbacks);
|
|
481
|
+
} catch (error) {
|
|
482
|
+
nextRollbacks = [];
|
|
483
|
+
}
|
|
484
|
+
const nextBuild = {
|
|
485
|
+
buildNumber: cliFlags.buildNumber,
|
|
486
|
+
revision: cliFlags.buildRevision,
|
|
487
|
+
deployedAt: new Date().toISOString(),
|
|
488
|
+
rollbacks: nextRollbacks
|
|
489
|
+
};
|
|
490
|
+
const formattedJson = _JSON$stringify__default["default"](nextBuild, null, 2);
|
|
491
|
+
// Logging to stdout which is from where it will be picked
|
|
492
|
+
// up by the caller (a bash script).
|
|
493
|
+
if (cliFlags.outFile) {
|
|
494
|
+
fs__default["default"].writeFileSync(cliFlags.outFile, formattedJson, {
|
|
495
|
+
encoding: 'utf8'
|
|
496
|
+
});
|
|
497
|
+
} else {
|
|
498
|
+
console.log(formattedJson);
|
|
499
|
+
}
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
function ownKeys(object, enumerableOnly) { var keys = _Object$keys__default["default"](object); if (_Object$getOwnPropertySymbols__default["default"]) { var symbols = _Object$getOwnPropertySymbols__default["default"](object); enumerableOnly && (symbols = _filterInstanceProperty__default["default"](symbols).call(symbols, function (sym) { return _Object$getOwnPropertyDescriptor__default["default"](object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
|
|
503
|
+
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var _context, _context2; var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? _forEachInstanceProperty__default["default"](_context = ownKeys(Object(source), !0)).call(_context, function (key) { _defineProperty(target, key, source[key]); }) : _Object$getOwnPropertyDescriptors__default["default"] ? _Object$defineProperties__default["default"](target, _Object$getOwnPropertyDescriptors__default["default"](source)) : _forEachInstanceProperty__default["default"](_context2 = ownKeys(Object(source))).call(_context2, function (key) { _Object$defineProperty__default["default"](target, key, _Object$getOwnPropertyDescriptor__default["default"](source, key)); }); } return target; }
|
|
504
|
+
const baseMenuProperties = {
|
|
505
|
+
key: {
|
|
506
|
+
type: 'string'
|
|
507
|
+
},
|
|
508
|
+
uriPath: {
|
|
509
|
+
type: 'string'
|
|
510
|
+
},
|
|
511
|
+
icon: {
|
|
512
|
+
type: 'string'
|
|
513
|
+
},
|
|
514
|
+
featureToggle: {
|
|
515
|
+
type: ['string', 'null']
|
|
516
|
+
},
|
|
517
|
+
labelAllLocales: {
|
|
518
|
+
type: 'array',
|
|
519
|
+
items: [{
|
|
520
|
+
type: 'object',
|
|
521
|
+
properties: {
|
|
522
|
+
locale: {
|
|
523
|
+
type: 'string'
|
|
524
|
+
},
|
|
525
|
+
value: {
|
|
526
|
+
type: 'string'
|
|
527
|
+
}
|
|
528
|
+
},
|
|
529
|
+
required: ['locale', 'value']
|
|
530
|
+
}]
|
|
531
|
+
},
|
|
532
|
+
menuVisibility: {
|
|
533
|
+
type: ['string', 'null']
|
|
534
|
+
},
|
|
535
|
+
permissions: {
|
|
536
|
+
type: 'array',
|
|
537
|
+
items: {
|
|
538
|
+
type: 'string'
|
|
539
|
+
}
|
|
540
|
+
},
|
|
541
|
+
dataFences: {
|
|
542
|
+
type: ['array', 'null'],
|
|
543
|
+
items: [{
|
|
544
|
+
type: ['object'],
|
|
545
|
+
properties: {
|
|
546
|
+
group: {
|
|
547
|
+
type: 'string'
|
|
548
|
+
},
|
|
549
|
+
name: {
|
|
550
|
+
type: 'string'
|
|
551
|
+
},
|
|
552
|
+
type: {
|
|
553
|
+
type: 'string'
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
}]
|
|
557
|
+
},
|
|
558
|
+
actionRights: {
|
|
559
|
+
type: ['array', 'null'],
|
|
560
|
+
items: [{
|
|
561
|
+
type: ['object'],
|
|
562
|
+
properties: {
|
|
563
|
+
group: {
|
|
564
|
+
type: 'string'
|
|
565
|
+
},
|
|
566
|
+
name: {
|
|
567
|
+
type: 'string'
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
}]
|
|
571
|
+
}
|
|
572
|
+
};
|
|
573
|
+
const navbarMenuSchema = {
|
|
574
|
+
$schema: 'https://json-schema.org/draft/2020-12/schema',
|
|
575
|
+
// "$id":""
|
|
576
|
+
title: 'NavbarMenu',
|
|
577
|
+
type: 'object',
|
|
578
|
+
properties: _objectSpread(_objectSpread({}, baseMenuProperties), {}, {
|
|
579
|
+
submenu: {
|
|
580
|
+
type: 'array',
|
|
581
|
+
items: [{
|
|
582
|
+
type: 'object',
|
|
583
|
+
properties: baseMenuProperties
|
|
584
|
+
}]
|
|
585
|
+
}
|
|
586
|
+
}),
|
|
587
|
+
required: ['icon', 'key', 'labelAllLocales', 'permissions', 'submenu', 'uriPath']
|
|
588
|
+
};
|
|
589
|
+
const appbarMenuSchema = {
|
|
590
|
+
$schema: 'https://json-schema.org/draft/2020-12/schema',
|
|
591
|
+
// "$id":""
|
|
592
|
+
title: 'AppbarMenu',
|
|
593
|
+
type: 'array',
|
|
594
|
+
items: [{
|
|
595
|
+
type: 'object',
|
|
596
|
+
properties: baseMenuProperties,
|
|
597
|
+
required: ['key', 'labelAllLocales', 'permissions', 'uriPath']
|
|
598
|
+
}]
|
|
599
|
+
};
|
|
600
|
+
|
|
601
|
+
function validateMenu(menuJson) {
|
|
602
|
+
let schema = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : navbarMenuSchema;
|
|
603
|
+
const validator = new jsonschema.Validator();
|
|
604
|
+
const result = validator.validate(menuJson, schema);
|
|
605
|
+
if (result.valid) {
|
|
606
|
+
return menuJson;
|
|
607
|
+
} else {
|
|
608
|
+
throw new Error('menu.json validation failed\n' + result.errors);
|
|
609
|
+
}
|
|
610
|
+
}
|
|
611
|
+
async function command(cliFlags) {
|
|
612
|
+
const menuJsonPath = cliFlags.inputFile;
|
|
613
|
+
const isAppbarMenu = cliFlags.navigation === 'top';
|
|
614
|
+
if (!menuJsonPath) throw new Error("--input-file cannot be empty. please provide the path of compiled menu.json");
|
|
615
|
+
if (!fs__default["default"].existsSync(menuJsonPath)) throw new Error("The menu.json file doesn't exist: ".concat(menuJsonPath));
|
|
616
|
+
const menuJson = fs__default["default"].readFileSync(menuJsonPath, 'utf-8');
|
|
617
|
+
return validateMenu(JSON.parse(menuJson), isAppbarMenu ? appbarMenuSchema : navbarMenuSchema);
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
var pkgJson = {
|
|
621
|
+
name: "@commercetools-frontend/application-cli",
|
|
622
|
+
version: "1.5.0",
|
|
623
|
+
description: "Internal CLI to manage Merchant Center application deployments across various environments.",
|
|
624
|
+
keywords: [
|
|
625
|
+
"commercetools",
|
|
626
|
+
"cli",
|
|
627
|
+
"custom-application"
|
|
628
|
+
],
|
|
629
|
+
license: "MIT",
|
|
630
|
+
main: "dist/commercetools-frontend-application-cli.cjs.js",
|
|
631
|
+
module: "dist/commercetools-frontend-application-cli.esm.js",
|
|
632
|
+
bin: "bin/cli.js",
|
|
633
|
+
files: [
|
|
634
|
+
"cli",
|
|
635
|
+
"dist",
|
|
636
|
+
"package.json",
|
|
637
|
+
"LICENSE",
|
|
638
|
+
"README.md"
|
|
639
|
+
],
|
|
640
|
+
scripts: {
|
|
641
|
+
typecheck: "tsc --noEmit"
|
|
642
|
+
},
|
|
643
|
+
dependencies: {
|
|
644
|
+
"@babel/core": "^7.21.0",
|
|
645
|
+
"@babel/runtime": "^7.21.0",
|
|
646
|
+
"@babel/runtime-corejs3": "^7.21.0",
|
|
647
|
+
"@commercetools-frontend/application-config": "22.2.1",
|
|
648
|
+
"@commercetools-frontend/constants": "22.2.1",
|
|
649
|
+
"@manypkg/find-root": "2.1.0",
|
|
650
|
+
cac: "^6.7.14",
|
|
651
|
+
cosmiconfig: "8.1.3",
|
|
652
|
+
dotenv: "16.0.3",
|
|
653
|
+
execa: "5.1.1",
|
|
654
|
+
jsonschema: "^1.4.1",
|
|
655
|
+
listr2: "^6.4.2",
|
|
656
|
+
"node-fetch": "2.6.9"
|
|
657
|
+
},
|
|
658
|
+
devDependencies: {
|
|
659
|
+
"@tsconfig/node18": "1.0.3",
|
|
660
|
+
"@types/node": "18.15.12",
|
|
661
|
+
"@types/node-fetch": "2.6.3",
|
|
662
|
+
typescript: "^4.9.5"
|
|
663
|
+
},
|
|
664
|
+
engines: {
|
|
665
|
+
node: ">=14",
|
|
666
|
+
npm: ">=6"
|
|
667
|
+
},
|
|
668
|
+
publishConfig: {
|
|
669
|
+
access: "public"
|
|
670
|
+
},
|
|
671
|
+
preconstruct: {
|
|
672
|
+
entrypoints: [
|
|
673
|
+
"./cli.ts"
|
|
674
|
+
]
|
|
675
|
+
}
|
|
676
|
+
};
|
|
677
|
+
|
|
678
|
+
const cli = cac.cac('application-cli');
|
|
679
|
+
const cwd = process.cwd();
|
|
680
|
+
const run = async () => {
|
|
681
|
+
cli.option('--build-revision [git-sha]', '(optional) The git commit SHA which is being built.', {
|
|
682
|
+
default: process.env.CIRCLE_SHA1
|
|
683
|
+
}).option('--build-number [string]', '(optional) A number of the build on the Continuous Integration system.', {
|
|
684
|
+
default: process.env.CIRCLE_BUILD_NUM
|
|
685
|
+
}).option('--package-manager-name [string]', '(optional) Name of the binary of the used package manager (e.g. pnpm).', {
|
|
686
|
+
default: 'yarn'
|
|
687
|
+
});
|
|
688
|
+
|
|
689
|
+
// Default command
|
|
690
|
+
cli.command('').usage('\n\n Compile deployments and menus and create versions for MC applications').action(cli.outputHelp);
|
|
691
|
+
const usageCompileDeployment = 'Compile the deployments for an application for all environments.';
|
|
692
|
+
cli.command('compile-deployments', usageCompileDeployment).usage("compile-deployments \n\n ".concat(usageCompileDeployment)).option('--application-name <string>', '(required) The name of the application being compiled for example application-products.').option('--dotenv-folder [string]', '(optional) The path to a folder containing a dotenv file ".env.production" and a cloud-environment specific dotenv file (for example ".env.gcp-production-eu"). Those values are parsed and merged together to be used by the `mc-scripts compile-html` command.').option('--pr-number [string]', '(optional) A pull request number determining a scoped storage bucket for the deployment. Please use it carefully.').option('--mc-url [string]', '(optional) The MC URL of the deployment. This is usually inferred from the env file and overwrites the value. Please use it carefully.').option('--mc-api-url [string]', '(optional) The MC API URL of the deployment. This is usually inferred from the env file and overwrites the value. Please use it carefully.').option('--application-index-out-file [path]', '(optional) The name of the application index file.', {
|
|
693
|
+
default: 'application.html'
|
|
694
|
+
}).option('--application-index-upload-script-out-file [path]', '(optional) The name of the the application index upload script file.', {
|
|
695
|
+
default: 'upload-index.sh'
|
|
696
|
+
}).option('--application-assets-upload-script-out-file [path]', '(optional) The name of the the assets upload script file.', {
|
|
697
|
+
default: 'upload-assets.sh'
|
|
698
|
+
}).option('--ci-assets-root-path [path]', '(optional) A replacement value for the scripts root path only used on CI (e.g. "--ci-assets-root-path=/root/") used in generated scripts.').option('--skip-menu', '(optional) If provided, it will skip uploading the `menu.json`.', {
|
|
699
|
+
default: false
|
|
700
|
+
}).action(async options => {
|
|
701
|
+
await command$3(options, cwd);
|
|
702
|
+
});
|
|
703
|
+
const usageCompileMenu = 'Compile the menu links of an application into a `menu.json`. This is only required for internal applications';
|
|
704
|
+
cli.command('compile-menu', usageCompileMenu).usage("compile-menu \n\n ".concat(usageCompileMenu)).option('--dotenv-folder [string]', '(optional) The path to a folder containing a dotenv file `.env.production` and a cloud-environment specific dotenv file (for example `.env.gcp-production-eu`). Those values are parsed and merged together to be used by the application config.').action(async options => {
|
|
705
|
+
await command$2(options, cwd);
|
|
706
|
+
});
|
|
707
|
+
const usageValidateMenu = 'Validate compiled `menu.json` file';
|
|
708
|
+
cli.command('validate-menu', usageValidateMenu).usage("validate-menu \n\n ".concat(usageValidateMenu)).option('--input-file <path>', '(required) The path to the `menu.json` file to be validated.').option('--navigation [string]', '(optional) Location of the menu navigation. Possible values are `top`.').action(async options => {
|
|
709
|
+
await command(options);
|
|
710
|
+
});
|
|
711
|
+
const usageCreateVersion = 'Output a JSON string about the information in the `version.json` for a deployment, including the updated list of rollbacks.';
|
|
712
|
+
cli.command('create-version', usageCreateVersion).usage("create-version \n\n ".concat(usageCreateVersion)).option('--version-url <url>', "(required) The path of an application's current `version.json` within the storage bucket.").option('--rollbacks [int]', '(optional) The number of max rollbacks to keep', {
|
|
713
|
+
default: 15
|
|
714
|
+
}).option('--out-file [path]', '(optional) The path to the file where to write the JSON. If not specified, the JSON is printed to stdout.').action(async options => {
|
|
715
|
+
await command$1(options);
|
|
716
|
+
});
|
|
717
|
+
cli.help();
|
|
718
|
+
cli.version(pkgJson.version);
|
|
719
|
+
cli.parse(process.argv, {
|
|
720
|
+
run: false
|
|
721
|
+
});
|
|
722
|
+
await cli.runMatchedCommand();
|
|
723
|
+
};
|
|
724
|
+
|
|
725
|
+
exports.run = run;
|