@commercetools-frontend/application-cli 1.3.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.
Files changed (35) hide show
  1. package/bin/cli.js +9 -0
  2. package/cli/dist/commercetools-frontend-application-cli-cli.cjs.d.ts +2 -0
  3. package/cli/dist/commercetools-frontend-application-cli-cli.cjs.d.ts.map +1 -0
  4. package/cli/dist/commercetools-frontend-application-cli-cli.cjs.dev.js +725 -0
  5. package/cli/dist/commercetools-frontend-application-cli-cli.cjs.js +7 -0
  6. package/cli/dist/commercetools-frontend-application-cli-cli.cjs.prod.js +725 -0
  7. package/cli/dist/commercetools-frontend-application-cli-cli.esm.js +699 -0
  8. package/cli/package.json +4 -0
  9. package/dist/declarations/src/cli.d.ts +2 -0
  10. package/dist/declarations/src/commands/compile-deployments.d.ts +3 -0
  11. package/dist/declarations/src/commands/compile-menu.d.ts +3 -0
  12. package/dist/declarations/src/commands/create-version.d.ts +3 -0
  13. package/dist/declarations/src/commands/validate-menu.d.ts +5 -0
  14. package/dist/declarations/src/schema.d.ts +228 -0
  15. package/dist/declarations/src/types.d.ts +92 -0
  16. package/dist/declarations/src/utils/create-application-assets-upload-script.d.ts +3 -0
  17. package/dist/declarations/src/utils/create-application-index-upload-script.d.ts +3 -0
  18. package/dist/declarations/src/utils/get-application-directory.d.ts +2 -0
  19. package/dist/declarations/src/utils/is-ci.d.ts +2 -0
  20. package/dist/declarations/src/utils/load-dotenv-files.d.ts +5 -0
  21. package/dist/declarations/src/utils/resolve-in-application.d.ts +2 -0
  22. package/package.json +27 -9
  23. package/src/bin/cli.js +0 -100
  24. package/src/commands/compile-deployments.js +0 -283
  25. package/src/commands/compile-menu.js +0 -126
  26. package/src/commands/create-version.js +0 -43
  27. package/src/commands/validate-menu.js +0 -33
  28. package/src/commands/validate-menu.spec.js +0 -43
  29. package/src/schema.js +0 -112
  30. package/src/utils/create-application-assets-upload-script.js +0 -62
  31. package/src/utils/create-application-index-upload-script.js +0 -41
  32. package/src/utils/get-application-directory.js +0 -7
  33. package/src/utils/is-ci.js +0 -5
  34. package/src/utils/load-dotenv-files.js +0 -48
  35. 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;