@magnolia/cli-jumpstart-plugin 1.1.5 → 1.2.1

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/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## 1.2.1 (2026-06-30)
4
+ * Fix jumpstart failing to download Magnolia bundles after the Nexus 3.88.0 upgrade to SQL search ([MGNLCLI-486](https://magnolia-cms.atlassian.net/browse/MGNLCLI-486))
5
+
6
+ ## 1.2.0 (2026-05-15)
7
+ * Install Magnolia CLI as a devDependency in jumpstarted projects ([MGNLCLI-440](https://magnolia-cms.atlassian.net/browse/MGNLCLI-440))
8
+ * Add resolver for US and AP nexus regions ([MGNLCLI-442](https://magnolia-cms.atlassian.net/browse/MGNLCLI-442))
9
+ * Add `--apache-tomcat` flag to override the Tomcat version ([MGNLCLI-480](https://magnolia-cms.atlassian.net/browse/MGNLCLI-480))
10
+ * Enable New UI Forms opt-in flags by default for 6.4.x jumpstart ([MGNLCLI-484](https://magnolia-cms.atlassian.net/browse/MGNLCLI-484))
11
+
3
12
  ## 1.1.5 (2025-10-02)
4
13
  * Update dependencies ([MGNLCLI-436](https://magnolia-cms.atlassian.net/browse/MGNLCLI-436))
5
14
 
@@ -22,7 +22,7 @@ import { installDependencies } from './lib/install.js';
22
22
  import path from 'path';
23
23
  import fs from 'fs-extra';
24
24
  import process from 'process';
25
- import { askForCredentials, copyDownloadedFile, handleLightModulesFolder, handleLightModulesPathInTemplate, initializeNodeProject, } from './lib/helper.js';
25
+ import { askForCredentials, copyDownloadedFile, extractMagnoliaVersion, handleLightModulesFolder, handleLightModulesPathInTemplate, initializeNodeProject, } from './lib/helper.js';
26
26
  import { compileCustomPrompts, evaluateCustomPrompts, } from './lib/extensions.js';
27
27
  import { addConfigProps } from './lib/config-helper.js';
28
28
  import { installAdditionalPlugins } from './lib/config-helper.js';
@@ -52,6 +52,7 @@ export default class JumpstartPlugin extends PluginTemplate {
52
52
  new Option('-s, --snapshot', i18nInstance.t('option-snapshot-description')),
53
53
  new Option('-t, --template <name>', i18nInstance.t('option-template-description')),
54
54
  new Option('-pt, --project-templates <source>', i18nInstance.t('option-projectTemplates-description')),
55
+ new Option('-at, --apache-tomcat <version>', i18nInstance.t('option-tomcatVersion-description')),
55
56
  ];
56
57
  }
57
58
  executePostCommands(bundle, file) {
@@ -125,7 +126,7 @@ export default class JumpstartPlugin extends PluginTemplate {
125
126
  throw new CreateError(e.message);
126
127
  }
127
128
  }
128
- yield handleLightModulesFolder();
129
+ yield handleLightModulesFolder(extractMagnoliaVersion(template.bundles));
129
130
  yield initializeNodeProject();
130
131
  if (template.plugins) {
131
132
  yield installAdditionalPlugins(template.plugins);
@@ -1,4 +1,15 @@
1
1
  import { Bundle, Credentials, PluginOptions } from '../types/types.js';
2
+ export declare const isMagnoliaBundle: (bundle: Bundle) => boolean;
3
+ export declare const getTomcatVersionLine: (magnoliaVersion: string) => string;
4
+ export declare const isVersionLine: (spec: string) => boolean;
5
+ export declare const normalizeVersionLine: (spec: string) => string;
6
+ export declare const matchesVersionLine: (version: string | undefined, line: string) => boolean;
7
+ export declare const isReleaseVersion: (version: string | undefined) => boolean;
8
+ export declare const constructMavenSearchUrl: (bundle: Bundle, options: PluginOptions, isTomcatExcluded?: boolean) => {
9
+ url: URL;
10
+ modifiedBundle: Bundle;
11
+ };
12
+ export declare const findItemFromResponse: (response: any, version?: string, versionLine?: string) => any;
2
13
  export declare const downloadBundle: (bundle: Bundle, credentials: Credentials, dest: string | undefined, options: PluginOptions, allBundles?: Bundle[], authProfiles?: Record<string, Credentials>) => Promise<string>;
3
14
  export declare const getDownloadUrl: (bundle: Bundle, credentials: Credentials, options: PluginOptions, authProfiles?: Record<string, Credentials>) => Promise<string>;
4
15
  export declare const selectTag: (url: string, credentials: Credentials) => Promise<string>;
@@ -18,7 +18,21 @@ import { CreateError, prependNumbersToChoices, } from '@magnolia/cli-helper/gene
18
18
  import { HttpsProxyAgent } from 'https-proxy-agent';
19
19
  import { HttpProxyAgent } from 'http-proxy-agent';
20
20
  let discoveredMagnoliaVersion = null;
21
- const constructMavenSearchUrl = (bundle, options, isTomcatExcluded = false) => {
21
+ export const isMagnoliaBundle = (bundle) => {
22
+ return (bundle.url.includes('maven.groupId=info.magnolia') &&
23
+ !bundle.url.includes('magnolia-tomcat-barebone'));
24
+ };
25
+ export const getTomcatVersionLine = (magnoliaVersion) => {
26
+ const [major, minor] = magnoliaVersion
27
+ .split('.')
28
+ .map((part) => parseInt(part, 10));
29
+ return major > 6 || (major === 6 && minor >= 4) ? '2' : '1';
30
+ };
31
+ export const isVersionLine = (spec) => spec.includes('*') || /^\d+(\.\d+)?$/.test(spec);
32
+ export const normalizeVersionLine = (spec) => spec.replace(/\*+$/, '').replace(/\.+$/, '');
33
+ export const matchesVersionLine = (version, line) => !!version && (version === line || version.startsWith(`${line}.`));
34
+ export const isReleaseVersion = (version) => !!version && /^\d+(\.\d+)*$/.test(version);
35
+ export const constructMavenSearchUrl = (bundle, options, isTomcatExcluded = false) => {
22
36
  const bundleCopy = Object.assign({}, bundle);
23
37
  const url = new URL(bundleCopy.url);
24
38
  url.searchParams.set('prerelease', 'false');
@@ -51,14 +65,31 @@ const constructMavenSearchUrl = (bundle, options, isTomcatExcluded = false) => {
51
65
  bundleCopy.version.toLowerCase() !== 'alpha' &&
52
66
  bundleCopy.version.toLowerCase() !== 'beta' &&
53
67
  bundleCopy.version.toLowerCase() !== 'rc') {
54
- url.searchParams.set('maven.baseVersion', options.snapshot
55
- ? bundleCopy.version + '-SNAPSHOT'
56
- : bundleCopy.version);
68
+ if (!options.snapshot && isVersionLine(bundleCopy.version)) {
69
+ const line = normalizeVersionLine(bundleCopy.version);
70
+ bundleCopy.versionLine = line;
71
+ if (line.length >= 3) {
72
+ url.searchParams.set('maven.baseVersion', `${line}*`);
73
+ }
74
+ }
75
+ else {
76
+ url.searchParams.set('maven.baseVersion', options.snapshot
77
+ ? bundleCopy.version + '-SNAPSHOT'
78
+ : bundleCopy.version);
79
+ }
57
80
  }
58
81
  }
59
82
  return { url, modifiedBundle: bundleCopy };
60
83
  };
61
- const findItemFromResponse = (response, version) => {
84
+ export const findItemFromResponse = (response, version, versionLine) => {
85
+ var _a, _b;
86
+ if (versionLine) {
87
+ return ((_b = (_a = response === null || response === void 0 ? void 0 : response.data) === null || _a === void 0 ? void 0 : _a.items) !== null && _b !== void 0 ? _b : []).find((item) => {
88
+ var _a, _b;
89
+ return matchesVersionLine((_a = item === null || item === void 0 ? void 0 : item.maven2) === null || _a === void 0 ? void 0 : _a.version, versionLine) &&
90
+ isReleaseVersion((_b = item === null || item === void 0 ? void 0 : item.maven2) === null || _b === void 0 ? void 0 : _b.version);
91
+ });
92
+ }
62
93
  let item = response.data.items[0];
63
94
  if ((version === null || version === void 0 ? void 0 : version.toLowerCase()) === 'latest') {
64
95
  item = response.data.items.find((item) => {
@@ -130,7 +161,7 @@ const fetchMavenArtifact = (bundle_1, options_1, credentials_1, ...args_1) => __
130
161
  resolvedCredentials.password) {
131
162
  authProfiles[profileKey] = resolvedCredentials;
132
163
  }
133
- const item = findItemFromResponse(response, modifiedBundle.version);
164
+ const item = findItemFromResponse(response, modifiedBundle.version, modifiedBundle.versionLine);
134
165
  return { item, modifiedBundle };
135
166
  });
136
167
  const getMagnoliaVersionFromBundle = (bundle, options, credentials, authProfiles) => __awaiter(void 0, void 0, void 0, function* () {
@@ -150,6 +181,10 @@ const modifyTomcatBundleUrl = (bundle, allBundles, credentials, options, authPro
150
181
  if (!bundle.url.includes('magnolia-tomcat-barebone')) {
151
182
  return bundle;
152
183
  }
184
+ if (options === null || options === void 0 ? void 0 : options.apacheTomcat) {
185
+ bundle.version = options.apacheTomcat;
186
+ return bundle;
187
+ }
153
188
  if (discoveredMagnoliaVersion) {
154
189
  return updateTomcatBundleUrl(bundle, discoveredMagnoliaVersion);
155
190
  }
@@ -171,21 +206,9 @@ const modifyTomcatBundleUrl = (bundle, allBundles, credentials, options, authPro
171
206
  }
172
207
  return bundle;
173
208
  });
174
- const isMagnoliaBundle = (bundle) => {
175
- return (bundle.url.includes('maven.groupId=info.magnolia') &&
176
- !bundle.url.includes('magnolia-tomcat-barebone'));
177
- };
178
209
  const updateTomcatBundleUrl = (bundle, magnoliaVersion) => {
179
- const versionParts = magnoliaVersion.split('.');
180
- const majorVersion = parseInt(versionParts[0]);
181
- const minorVersion = parseInt(versionParts[1]);
182
- let baseVersion = '1.*'; // Default for 6.3 and below
183
- if (majorVersion > 6 || (majorVersion === 6 && minorVersion >= 4)) {
184
- baseVersion = '2.*';
185
- }
186
- // Change the version only if the version isn't set in projectTemplates
187
210
  if (!bundle.url.includes('maven.baseVersion=') || bundle.version) {
188
- bundle.url = `${bundle.url}&maven.baseVersion=${baseVersion}`;
211
+ bundle.versionLine = getTomcatVersionLine(magnoliaVersion);
189
212
  }
190
213
  return bundle;
191
214
  };
@@ -198,7 +221,9 @@ export const downloadBundle = (bundle, credentials, dest, options, allBundles, a
198
221
  downloadUrl = yield selectTag(url, credentials);
199
222
  }
200
223
  else if (url.includes('https://nexus.magnolia-cms.com/service/rest/v1/search') ||
201
- url.includes('https://nexus.magnolia-cms.cn/service/rest/v1/search')) {
224
+ url.includes('https://nexus.magnolia-cms.cn/service/rest/v1/search') ||
225
+ url.includes('http://nexus.us.magnolia-cms.com/service/rest/v1/search') ||
226
+ url.includes('https://nexus.ap.magnolia-cms.com/service/rest/v1/search')) {
202
227
  logger === null || logger === void 0 ? void 0 : logger.info(i18nInstance.t('info-download-preparing', {
203
228
  url,
204
229
  }));
@@ -269,7 +294,10 @@ export const getDownloadUrl = (bundle, credentials, options, authProfiles) => __
269
294
  const { item, modifiedBundle } = yield fetchMavenArtifact(bundle, options, credentials, true, authProfiles);
270
295
  bundle.version = modifiedBundle.version;
271
296
  if (!item) {
272
- throw new Error(i18nInstance.t('error-no-artifact-available', {
297
+ const isTomcatBundle = bundle.url.includes('magnolia-tomcat-barebone');
298
+ throw new Error(i18nInstance.t(isTomcatBundle
299
+ ? 'error-no-tomcat-artifact-available'
300
+ : 'error-no-artifact-available', {
273
301
  version: bundle.version,
274
302
  }));
275
303
  }
@@ -1,5 +1,10 @@
1
1
  import { Bundle, Credentials } from '../types/types.js';
2
- export declare const handleLightModulesFolder: () => Promise<void>;
2
+ export declare const isMagnoliaSixFourVersion: (version: string | null | undefined) => boolean;
3
+ export declare const extractMagnoliaVersion: (bundles: Array<Bundle> | undefined) => string | null;
4
+ export declare const buildWebAppMagnoliaProperties: (webAppPath: string, lightModulesRelativePath: string, magnoliaVersion: string | null | undefined) => {
5
+ [key: string]: string;
6
+ };
7
+ export declare const handleLightModulesFolder: (magnoliaVersion?: string | null) => Promise<void>;
3
8
  export declare const handleLightModulesPathInTemplate: (template: any) => Promise<void>;
4
9
  export declare const findLightModulesFolder: (p: string) => Promise<unknown>;
5
10
  export declare const findWebAppsList: (apacheTomcatPath: string) => string[];
@@ -15,13 +15,43 @@ import { execa } from 'execa';
15
15
  import path from 'path';
16
16
  import fs from 'fs-extra';
17
17
  import { findExtractedApacheTomcatDir } from './extract.js';
18
+ import { isMagnoliaBundle } from './download.js';
18
19
  import walk from 'walk';
19
20
  import { i18nInstance, logger } from '../jumpstart-plugin.js';
20
21
  import inquirer from 'inquirer';
21
22
  import { CreateError } from '@magnolia/cli-helper/general-utils';
22
23
  import { getRelativePathToMGNLConfig } from '@magnolia/cli-helper';
23
24
  import chalk from 'chalk';
24
- export const handleLightModulesFolder = () => __awaiter(void 0, void 0, void 0, function* () {
25
+ export const isMagnoliaSixFourVersion = (version) => {
26
+ if (!version)
27
+ return false;
28
+ const parts = version.split('.');
29
+ return parseInt(parts[0]) === 6 && parseInt(parts[1]) === 4;
30
+ };
31
+ export const extractMagnoliaVersion = (bundles) => {
32
+ var _a;
33
+ const magnoliaBundle = (bundles || []).find(isMagnoliaBundle);
34
+ return (_a = magnoliaBundle === null || magnoliaBundle === void 0 ? void 0 : magnoliaBundle.version) !== null && _a !== void 0 ? _a : null;
35
+ };
36
+ export const buildWebAppMagnoliaProperties = (webAppPath, lightModulesRelativePath, magnoliaVersion) => {
37
+ const props = {
38
+ 'magnolia.resources.dir': '${magnolia.home}/' + lightModulesRelativePath,
39
+ 'magnolia.update.auto': 'true',
40
+ };
41
+ if (webAppPath.endsWith('magnoliaAuthor')) {
42
+ props['magnolia.develop'] = 'true';
43
+ props['magnolia.graphql.introspection.enabled'] = 'true';
44
+ props['magnolia.personalization.rest.allowVariants'] = 'true';
45
+ if (isMagnoliaSixFourVersion(magnoliaVersion)) {
46
+ props['magnolia.warp.forms.vaadin.actions'] = 'true';
47
+ props['magnolia.warp.forms.tabs.enabled'] = 'true';
48
+ props['magnolia.warp.forms.field.codeField'] = 'true';
49
+ props['magnolia.warp.forms.field.hiddenField'] = 'true';
50
+ }
51
+ }
52
+ return props;
53
+ };
54
+ export const handleLightModulesFolder = (magnoliaVersion) => __awaiter(void 0, void 0, void 0, function* () {
25
55
  // eslint-disable-next-line no-console
26
56
  console.log(chalk.cyanBright('==========================================='));
27
57
  let lightModulesPath;
@@ -59,15 +89,7 @@ export const handleLightModulesFolder = () => __awaiter(void 0, void 0, void 0,
59
89
  const lightModulesPathToMagnoliaHomeRelPath = process.platform === 'win32'
60
90
  ? path.relative(webApp, lightModulesPath).replace(/\\/g, '/')
61
91
  : path.relative(webApp, lightModulesPath);
62
- const props = {
63
- 'magnolia.resources.dir': '${magnolia.home}/' + lightModulesPathToMagnoliaHomeRelPath,
64
- 'magnolia.update.auto': 'true',
65
- };
66
- if (webApp.endsWith('magnoliaAuthor')) {
67
- props['magnolia.develop'] = 'true';
68
- props['magnolia.graphql.introspection.enabled'] = 'true';
69
- props['magnolia.personalization.rest.allowVariants'] = 'true';
70
- }
92
+ const props = buildWebAppMagnoliaProperties(webApp, lightModulesPathToMagnoliaHomeRelPath, magnoliaVersion);
71
93
  const webAppPropertiesFilePath = path.join(webApp, 'WEB-INF', 'config', 'default', 'magnolia.properties');
72
94
  editProperties(webAppPropertiesFilePath, props);
73
95
  }
@@ -164,7 +186,10 @@ export const installPackage = (packageManager, packageReference, packageName) =>
164
186
  packageName: packageName,
165
187
  }));
166
188
  try {
167
- yield execa(packageManager, [packageManager === 'npm' ? 'install' : 'add', packageReference], {
189
+ const installArgs = packageManager === 'npm'
190
+ ? ['install', '--save-dev', packageReference]
191
+ : ['add', '--dev', packageReference];
192
+ yield execa(packageManager, installArgs, {
168
193
  buffer: true,
169
194
  cwd: process.cwd(),
170
195
  });
@@ -198,7 +223,9 @@ export const askForCredentials = (bundle) => __awaiter(void 0, void 0, void 0, f
198
223
  bundle: bundle,
199
224
  }));
200
225
  if (bundle.startsWith('https://nexus.magnolia-cms.com') ||
201
- bundle.startsWith('https://nexus.magnolia-cms.cn')) {
226
+ bundle.startsWith('https://nexus.magnolia-cms.cn') ||
227
+ bundle.startsWith('http://nexus.us.magnolia-cms.com') ||
228
+ bundle.startsWith('http://nexus.ap.magnolia-cms.com')) {
202
229
  logger === null || logger === void 0 ? void 0 : logger.warn(i18nInstance.t('info-use-nexus-token'));
203
230
  }
204
231
  return inquirer.prompt([
@@ -4,6 +4,7 @@
4
4
  "option-projectTemplates-description": "specify the source to load project templates from",
5
5
  "option-magnolia-description": "set the Magnolia version; defaults to the latest stable version",
6
6
  "option-snapshot-description": "download the latest snapshot version of the specified or latest stable webapp",
7
+ "option-tomcatVersion-description": "override the Apache Tomcat version; defaults to the version determined by the Magnolia version",
7
8
 
8
9
  "info-enter-credentials": "Enter the credentials for \"{{bundle}}\"",
9
10
  "info-use-nexus-token": [
@@ -50,6 +51,7 @@
50
51
  "Please search the web on \"unable to get local issuer certificate\" for more information"
51
52
  ],
52
53
  "error-no-artifact-available": "No Magnolia bundle with version \"{{version}}\" is available",
54
+ "error-no-tomcat-artifact-available": "No Apache Tomcat (\"magnolia-tomcat-barebone\") with version \"{{version}}\" is available",
53
55
  "error-while-getting-projectTemplates": "An error occurred while getting \"projectTemplates\":",
54
56
  "error-no-projectTemplates-from-url": "Cannot fetch remote projectTemplates file located at: \"{{url}}\"; are you connected to the internet? does it point to a JSON file?",
55
57
  "error-no-projectTemplates-from-path": "Cannot read projectTemplates from a local file located at: \"{{path}}\"; is it a JSON file?",
@@ -22,7 +22,8 @@ export const handlePackageJSON = () => __awaiter(void 0, void 0, void 0, functio
22
22
  });
23
23
  export const modifyPackageJSON = (pjPath) => __awaiter(void 0, void 0, void 0, function* () {
24
24
  let pj = JSON.parse(fs.readFileSync(pjPath, 'utf8'));
25
- let isMgnlCliInstalled = (pj === null || pj === void 0 ? void 0 : pj.dependencies) && (pj === null || pj === void 0 ? void 0 : pj.dependencies['@magnolia/cli']);
25
+ let isMgnlCliInstalled = ((pj === null || pj === void 0 ? void 0 : pj.dependencies) && (pj === null || pj === void 0 ? void 0 : pj.dependencies['@magnolia/cli'])) ||
26
+ ((pj === null || pj === void 0 ? void 0 : pj.devDependencies) && (pj === null || pj === void 0 ? void 0 : pj.devDependencies['@magnolia/cli']));
26
27
  if (!isMgnlCliInstalled) {
27
28
  isMgnlCliInstalled = yield installCLI();
28
29
  if (isMgnlCliInstalled) {
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@magnolia/cli-jumpstart-plugin",
3
- "version": "1.1.5",
3
+ "version": "1.2.1",
4
4
  "description": "A plugin for Magnolia CLI to download and set up a new headless or freemarker-based project with Magnolia webapp",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {
@@ -3,6 +3,7 @@ export interface PluginOptions {
3
3
  projectTemplates: string;
4
4
  magnolia?: string;
5
5
  snapshot?: boolean;
6
+ apacheTomcat?: string;
6
7
  }
7
8
  export interface Bundle {
8
9
  url: string;
@@ -13,6 +14,7 @@ export interface Bundle {
13
14
  downloadDest?: string;
14
15
  name?: string;
15
16
  version?: string;
17
+ versionLine?: string;
16
18
  alternative: {
17
19
  groupId: string;
18
20
  artifactId: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@magnolia/cli-jumpstart-plugin",
3
- "version": "1.1.5",
3
+ "version": "1.2.1",
4
4
  "description": "A plugin for Magnolia CLI to download and set up a new headless or freemarker-based project with Magnolia webapp",
5
5
  "main": "dist/index.js",
6
6
  "scripts": {