@commercetools-frontend/create-mc-app 27.6.2 → 27.7.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/CHANGELOG.md CHANGED
@@ -1,5 +1,34 @@
1
1
  # @commercetools-frontend/create-mc-app
2
2
 
3
+ ## 27.7.0
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies []:
8
+ - @commercetools-frontend/application-config@27.7.0
9
+
10
+ ## 27.6.3
11
+
12
+ ### Patch Changes
13
+
14
+ - [#4019](https://github.com/commercetools/merchant-center-application-kit/pull/4019) [`2bf3322`](https://github.com/commercetools/merchant-center-application-kit/commit/2bf33221525be981c8a03a951bfb6387438624a6) Thanks [@misama-ct](https://github.com/misama-ct)! - Support `workspace:^` and `catalog:` specifiers when scaffolding —
15
+ previously the CLI only handled `workspace:*`, so apps generated from
16
+ the latest templates failed to install.
17
+
18
+ Scaffolded `package.json` files now pin internal
19
+ `@commercetools-frontend/*` deps with caret ranges (`^x.y.z`) instead
20
+ of exact versions. Application Kit packages release in lockstep, so a
21
+ caret range always resolves to a synchronized set of latest patches —
22
+ the lockstep invariant is preserved, and subsequent
23
+ `npm install` / `yarn install` / `pnpm install` runs pick up
24
+ patch/minor updates automatically.
25
+
26
+ `npx create-mc-app …` continues to work against any template version,
27
+ old or new.
28
+
29
+ - Updated dependencies []:
30
+ - @commercetools-frontend/application-config@27.6.3
31
+
3
32
  ## 27.6.2
4
33
 
5
34
  ### Patch Changes
@@ -9,7 +9,9 @@ var execa = require('execa');
9
9
  var semver = require('semver');
10
10
  var _Promise = require('@babel/runtime-corejs3/core-js-stable/promise');
11
11
  var _startsWithInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/starts-with');
12
+ var _Date$now = require('@babel/runtime-corejs3/core-js-stable/date/now');
12
13
  var crypto = require('node:crypto');
14
+ var os = require('node:os');
13
15
  var path = require('node:path');
14
16
  var readline = require('node:readline');
15
17
  var applicationConfig = require('@commercetools-frontend/application-config');
@@ -21,8 +23,6 @@ var fs = require('node:fs');
21
23
  var _Object$keys = require('@babel/runtime-corejs3/core-js-stable/object/keys');
22
24
  var _includesInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/includes');
23
25
  var _Object$values = require('@babel/runtime-corejs3/core-js-stable/object/values');
24
- var _Date$now = require('@babel/runtime-corejs3/core-js-stable/date/now');
25
- var os = require('node:os');
26
26
  var _Object$getOwnPropertySymbols = require('@babel/runtime-corejs3/core-js-stable/object/get-own-property-symbols');
27
27
  var _Object$getOwnPropertyDescriptor = require('@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptor');
28
28
  var _forEachInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/for-each');
@@ -31,10 +31,10 @@ var _Object$defineProperties = require('@babel/runtime-corejs3/core-js-stable/ob
31
31
  var _Object$defineProperty = require('@babel/runtime-corejs3/core-js-stable/object/define-property');
32
32
  var _defineProperty = require('@babel/runtime-corejs3/helpers/defineProperty');
33
33
  var _slicedToArray = require('@babel/runtime-corejs3/helpers/slicedToArray');
34
- var _reduceInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/reduce');
34
+ var _Map = require('@babel/runtime-corejs3/core-js-stable/map');
35
35
  var _Object$entries = require('@babel/runtime-corejs3/core-js-stable/object/entries');
36
- var _Object$assign = require('@babel/runtime-corejs3/core-js-stable/object/assign');
37
36
  var _JSON$stringify = require('@babel/runtime-corejs3/core-js-stable/json/stringify');
37
+ var yaml = require('yaml');
38
38
  var core = require('@babel/core');
39
39
  var prettier = require('prettier');
40
40
 
@@ -45,7 +45,9 @@ var execa__default = /*#__PURE__*/_interopDefault(execa);
45
45
  var semver__default = /*#__PURE__*/_interopDefault(semver);
46
46
  var _Promise__default = /*#__PURE__*/_interopDefault(_Promise);
47
47
  var _startsWithInstanceProperty__default = /*#__PURE__*/_interopDefault(_startsWithInstanceProperty);
48
+ var _Date$now__default = /*#__PURE__*/_interopDefault(_Date$now);
48
49
  var crypto__default = /*#__PURE__*/_interopDefault(crypto);
50
+ var os__default = /*#__PURE__*/_interopDefault(os);
49
51
  var path__default = /*#__PURE__*/_interopDefault(path);
50
52
  var readline__default = /*#__PURE__*/_interopDefault(readline);
51
53
  var _trimInstanceProperty__default = /*#__PURE__*/_interopDefault(_trimInstanceProperty);
@@ -56,23 +58,20 @@ var fs__default = /*#__PURE__*/_interopDefault(fs);
56
58
  var _Object$keys__default = /*#__PURE__*/_interopDefault(_Object$keys);
57
59
  var _includesInstanceProperty__default = /*#__PURE__*/_interopDefault(_includesInstanceProperty);
58
60
  var _Object$values__default = /*#__PURE__*/_interopDefault(_Object$values);
59
- var _Date$now__default = /*#__PURE__*/_interopDefault(_Date$now);
60
- var os__default = /*#__PURE__*/_interopDefault(os);
61
61
  var _Object$getOwnPropertySymbols__default = /*#__PURE__*/_interopDefault(_Object$getOwnPropertySymbols);
62
62
  var _Object$getOwnPropertyDescriptor__default = /*#__PURE__*/_interopDefault(_Object$getOwnPropertyDescriptor);
63
63
  var _forEachInstanceProperty__default = /*#__PURE__*/_interopDefault(_forEachInstanceProperty);
64
64
  var _Object$getOwnPropertyDescriptors__default = /*#__PURE__*/_interopDefault(_Object$getOwnPropertyDescriptors);
65
65
  var _Object$defineProperties__default = /*#__PURE__*/_interopDefault(_Object$defineProperties);
66
66
  var _Object$defineProperty__default = /*#__PURE__*/_interopDefault(_Object$defineProperty);
67
- var _reduceInstanceProperty__default = /*#__PURE__*/_interopDefault(_reduceInstanceProperty);
67
+ var _Map__default = /*#__PURE__*/_interopDefault(_Map);
68
68
  var _Object$entries__default = /*#__PURE__*/_interopDefault(_Object$entries);
69
- var _Object$assign__default = /*#__PURE__*/_interopDefault(_Object$assign);
70
69
  var _JSON$stringify__default = /*#__PURE__*/_interopDefault(_JSON$stringify);
71
70
  var prettier__default = /*#__PURE__*/_interopDefault(prettier);
72
71
 
73
72
  var pkgJson = {
74
73
  name: "@commercetools-frontend/create-mc-app",
75
- version: "27.6.2",
74
+ version: "27.7.0",
76
75
  description: "Create Merchant Center applications to quickly get up and running",
77
76
  bugs: "https://github.com/commercetools/merchant-center-application-kit/issues",
78
77
  repository: {
@@ -95,21 +94,22 @@ var pkgJson = {
95
94
  module: "dist/commercetools-frontend-create-mc-app.esm.js",
96
95
  bin: "./bin/cli.js",
97
96
  dependencies: {
98
- "@babel/core": "^7.22.17",
99
- "@babel/runtime": "^7.22.15",
100
- "@babel/runtime-corejs3": "^7.22.15",
101
- "@commercetools-frontend/application-config": "^27.6.2",
102
- "@types/babel__core": "^7.20.1",
103
- "@types/semver": "^7.5.1",
104
- commander: "^13.1.0",
105
- execa: "5.1.1",
106
- listr2: "5.0.8",
107
- prettier: "2.8.8",
108
- semver: "7.7.2"
97
+ "@babel/core": "catalog:build",
98
+ "@babel/runtime": "catalog:build",
99
+ "@babel/runtime-corejs3": "catalog:build",
100
+ "@commercetools-frontend/application-config": "workspace:^",
101
+ "@types/babel__core": "catalog:",
102
+ "@types/semver": "catalog:",
103
+ commander: "catalog:",
104
+ execa: "catalog:",
105
+ listr2: "catalog:",
106
+ prettier: "catalog:lint",
107
+ semver: "catalog:",
108
+ yaml: "catalog:"
109
109
  },
110
110
  devDependencies: {
111
- "@tsconfig/node22": "^22.0.0",
112
- "@types/prettier": "2.7.3"
111
+ "@tsconfig/node22": "catalog:",
112
+ "@types/prettier": "catalog:"
113
113
  },
114
114
  engines: {
115
115
  node: "18.x || 20.x || >=22.0.0"
@@ -345,12 +345,22 @@ async function processOptions(projectDirectoryName, options) {
345
345
  const initialProjectKey = await getInitialProjectKey(rl, options);
346
346
  const cloudIdentifier = await getCloudIdentifier(rl, options);
347
347
  rl.close();
348
+
349
+ // Compute the path used by `downloadTemplate` to clone the app-kit repo
350
+ // here so subsequent tasks (e.g. `updatePackageJson`) can read
351
+ // pnpm-workspace.yaml from the same checkout to resolve catalog refs.
352
+ // Branch names with `/` (`feat/foo`) would otherwise create a nested
353
+ // tmp path and break dirname/basename splits downstream — sanitize them
354
+ // into the folder name only.
355
+ const safeBranchSegment = tagOrBranchVersion.replace(/[^A-Za-z0-9._-]/g, '_');
356
+ const clonedRepositoryPath = path__default["default"].join(os__default["default"].tmpdir(), ['merchant-center-application-kit', '--', safeBranchSegment, '--', _Date$now__default["default"]().toString()].join(''));
348
357
  return {
349
358
  applicationType: options.applicationType,
350
359
  projectDirectoryName,
351
360
  projectDirectoryPath,
352
361
  templateName,
353
362
  tagOrBranchVersion,
363
+ clonedRepositoryPath,
354
364
  entryPointUriPath,
355
365
  initialProjectKey,
356
366
  cloudIdentifier,
@@ -363,9 +373,9 @@ function downloadTemplate(options) {
363
373
  return {
364
374
  title: 'Downloading template',
365
375
  task: () => {
366
- const tmpDir = os__default["default"].tmpdir();
367
- const tmpFolderNameForClonedRepository = ['merchant-center-application-kit', '--', options.tagOrBranchVersion, '--', _Date$now__default["default"]().toString()].join('');
368
- const clonedRepositoryPath = path__default["default"].join(tmpDir, tmpFolderNameForClonedRepository);
376
+ const clonedRepositoryPath = options.clonedRepositoryPath;
377
+ const tmpDir = path__default["default"].dirname(clonedRepositoryPath);
378
+ const tmpFolderNameForClonedRepository = path__default["default"].basename(clonedRepositoryPath);
369
379
  const templateFolderPath = path__default["default"].join(clonedRepositoryPath, options.applicationType === applicationTypes['custom-view'] ? 'custom-views-templates' : 'application-templates', options.templateName);
370
380
  return new listr2.Listr([{
371
381
  title: `Cloning repository using branch ${options.tagOrBranchVersion}`,
@@ -439,20 +449,120 @@ function installDependencies(options) {
439
449
  }
440
450
 
441
451
  function ownKeys(e, r) { var t = _Object$keys__default["default"](e); if (_Object$getOwnPropertySymbols__default["default"]) { var o = _Object$getOwnPropertySymbols__default["default"](e); r && (o = _filterInstanceProperty__default["default"](o).call(o, function (r) { return _Object$getOwnPropertyDescriptor__default["default"](e, r).enumerable; })), t.push.apply(t, o); } return t; }
442
- function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var _context2, _context3; var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? _forEachInstanceProperty__default["default"](_context2 = ownKeys(Object(t), !0)).call(_context2, function (r) { _defineProperty(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors__default["default"] ? _Object$defineProperties__default["default"](e, _Object$getOwnPropertyDescriptors__default["default"](t)) : _forEachInstanceProperty__default["default"](_context3 = ownKeys(Object(t))).call(_context3, function (r) { _Object$defineProperty__default["default"](e, r, _Object$getOwnPropertyDescriptor__default["default"](t, r)); }); } return e; }
443
- const replaceApplicationKitPackageVersionWith = function (releaseVersion) {
444
- var _context;
445
- let dependencies = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
446
- return _reduceInstanceProperty__default["default"](_context = _Object$entries__default["default"](dependencies)).call(_context, (updatedDependencies, _ref) => {
447
- let _ref2 = _slicedToArray(_ref, 2),
448
- dependencyName = _ref2[0],
449
- dependencyVersion = _ref2[1];
450
- const updatedVersion = dependencyVersion === 'workspace:*' ? releaseVersion : dependencyVersion;
451
- return _objectSpread(_objectSpread({}, updatedDependencies), {}, {
452
- [dependencyName]: updatedVersion
453
- });
454
- }, {});
452
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var _context, _context2; var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? _forEachInstanceProperty__default["default"](_context = ownKeys(Object(t), !0)).call(_context, function (r) { _defineProperty(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors__default["default"] ? _Object$defineProperties__default["default"](e, _Object$getOwnPropertyDescriptors__default["default"](t)) : _forEachInstanceProperty__default["default"](_context2 = ownKeys(Object(t))).call(_context2, function (r) { _Object$defineProperty__default["default"](e, r, _Object$getOwnPropertyDescriptor__default["default"](t, r)); }); } return e; }
453
+
454
+ // Catalog references in workspace package.json files point at entries in
455
+ // pnpm-workspace.yaml. They have to be flattened to concrete version
456
+ // specifiers in the scaffolded app because the scaffolded app is not part
457
+ // of any workspace.
458
+ //
459
+ // Shape: catalogName -> depName -> resolved spec. The default `catalog:`
460
+ // block is keyed as 'default' so `catalog:` and `catalog:<name>` lookups
461
+ // share one code path.
462
+
463
+ function parseCatalogs(yamlText) {
464
+ const doc = yaml.parse(yamlText) ?? {};
465
+ const out = new _Map__default["default"]();
466
+ if (doc.catalog) {
467
+ out.set('default', new _Map__default["default"](_Object$entries__default["default"](doc.catalog)));
468
+ }
469
+ for (const _ref of _Object$entries__default["default"](doc.catalogs ?? {})) {
470
+ var _ref2 = _slicedToArray(_ref, 2);
471
+ const name = _ref2[0];
472
+ const entries = _ref2[1];
473
+ out.set(name, new _Map__default["default"](_Object$entries__default["default"](entries)));
474
+ }
475
+ return out;
476
+ }
477
+
478
+ // `workspace:` specifier → rewriter that takes the release version and
479
+ // returns the concrete spec. The supported set is data, not branching
480
+ // logic — extend the table to handle new protocol additions.
481
+ const WORKSPACE_REWRITERS = {
482
+ 'workspace:*': v => v,
483
+ 'workspace:^': v => `^${v}`,
484
+ 'workspace:~': v => `~${v}`
455
485
  };
486
+
487
+ /**
488
+ * Resolve a `catalog:` / `catalog:<name>` specifier to a concrete version
489
+ * string by looking it up in the parsed `pnpm-workspace.yaml`.
490
+ *
491
+ * @throws {Error} when the named catalog does not exist in the template's
492
+ * `pnpm-workspace.yaml`, or when the catalog exists but does not declare
493
+ * an entry for `depName`. Both cases mean the scaffold cannot produce a
494
+ * valid `package.json` and is unrecoverable — let it propagate.
495
+ */
496
+ function resolveCatalogRef(spec, depName, catalogs) {
497
+ // `catalog:` and `catalog:default` both target the default block.
498
+ const name = spec === 'catalog:' || spec === 'catalog:default' ? 'default' : _sliceInstanceProperty__default["default"](spec).call(spec, 'catalog:'.length);
499
+ const block = catalogs.get(name);
500
+ if (!block) {
501
+ throw new Error(`Unable to resolve catalog reference "${spec}" for "${depName}": catalog "${name}" is not declared in the template's pnpm-workspace.yaml.`);
502
+ }
503
+ const resolved = block.get(depName);
504
+ if (!resolved) {
505
+ const where = name === 'default' ? 'the default catalog' : `catalogs.${name}`;
506
+ throw new Error(`Unable to resolve catalog reference "${spec}" for "${depName}": dep is not declared under ${where} in the template's pnpm-workspace.yaml.`);
507
+ }
508
+ return resolved;
509
+ }
510
+ function resolveSpec(depName, spec, releaseVersion, catalogs) {
511
+ const workspaceRewriter = WORKSPACE_REWRITERS[spec];
512
+ if (workspaceRewriter) return workspaceRewriter(releaseVersion);
513
+ if (_startsWithInstanceProperty__default["default"](spec).call(spec, 'catalog:')) return resolveCatalogRef(spec, depName, catalogs);
514
+ return spec;
515
+ }
516
+ function resolveDependencies() {
517
+ let dependencies = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
518
+ let releaseVersion = arguments.length > 1 ? arguments[1] : undefined;
519
+ let catalogs = arguments.length > 2 ? arguments[2] : undefined;
520
+ const out = {};
521
+ for (const _ref3 of _Object$entries__default["default"](dependencies)) {
522
+ var _ref4 = _slicedToArray(_ref3, 2);
523
+ const name = _ref4[0];
524
+ const spec = _ref4[1];
525
+ out[name] = resolveSpec(name, spec, releaseVersion, catalogs);
526
+ }
527
+ return out;
528
+ }
529
+
530
+ // Read catalogs from the cloned template repo. Older template tags predate
531
+ // catalog adoption — fall back to an empty map so the workspace-only
532
+ // rewrite path still works.
533
+ function loadCatalogsFromClone(clonedRepositoryPath) {
534
+ const workspaceYamlPath = path__default["default"].join(clonedRepositoryPath, 'pnpm-workspace.yaml');
535
+ if (!fs__default["default"].existsSync(workspaceYamlPath)) return new _Map__default["default"]();
536
+ return parseCatalogs(fs__default["default"].readFileSync(workspaceYamlPath, {
537
+ encoding: 'utf8'
538
+ }));
539
+ }
540
+ function buildUpdatedPackageJson(appPackageJson, options, releaseVersion, catalogs) {
541
+ const packageManager = getPreferredPackageManager(options);
542
+ // Flatten workspace: and catalog: specifiers into concrete versions across
543
+ // every dependency section — the scaffolded app is not part of any pnpm
544
+ // workspace and would otherwise fail to install.
545
+ const resolve = deps => resolveDependencies(deps, releaseVersion, catalogs);
546
+ return _objectSpread(_objectSpread(_objectSpread(_objectSpread({}, appPackageJson), {}, {
547
+ version: '1.0.0',
548
+ // Given the package name is derived from the `projectDirectoryName`
549
+ // the latter needs to be sanitised to have a ensure a valid package name.
550
+ // The `projectDirectoryName` should not have restrictions (e.g. no `_`)
551
+ // as a result the package name potentially needs to be altered when derived.
552
+ name: slugify(options.projectDirectoryName),
553
+ description: '',
554
+ dependencies: resolve(appPackageJson.dependencies),
555
+ devDependencies: resolve(appPackageJson.devDependencies)
556
+ }, appPackageJson.peerDependencies && {
557
+ peerDependencies: resolve(appPackageJson.peerDependencies)
558
+ }), appPackageJson.optionalDependencies && {
559
+ optionalDependencies: resolve(appPackageJson.optionalDependencies)
560
+ }), {}, {
561
+ scripts: _objectSpread(_objectSpread({}, appPackageJson.scripts), {}, {
562
+ 'start:prod:local': appPackageJson.scripts['start:prod:local'].replace('yarn', packageManager)
563
+ })
564
+ });
565
+ }
456
566
  function updatePackageJson(options, releaseVersion) {
457
567
  return {
458
568
  title: 'Updating package.json',
@@ -461,22 +571,8 @@ function updatePackageJson(options, releaseVersion) {
461
571
  const appPackageJson = JSON.parse(fs__default["default"].readFileSync(packageJsonPath, {
462
572
  encoding: 'utf8'
463
573
  }));
464
- const packageManager = getPreferredPackageManager(options);
465
- const updatedAppPackageJson = _Object$assign__default["default"]({}, appPackageJson, {
466
- version: '1.0.0',
467
- // Given the package name is derived from the `projectDirectoryName`
468
- // the latter needs to be sanitised to have a ensure a valid package name.
469
- // The `projectDirectoryName` should not have restrictions (e.g. no `_`)
470
- // as a result the package name potentially needs to be altered when derived.
471
- name: slugify(options.projectDirectoryName),
472
- description: '',
473
- // Replace the package versions with the `workspace:` syntax to the real version.
474
- dependencies: replaceApplicationKitPackageVersionWith(releaseVersion, appPackageJson.dependencies),
475
- devDependencies: replaceApplicationKitPackageVersionWith(releaseVersion, appPackageJson.devDependencies),
476
- scripts: _objectSpread(_objectSpread({}, appPackageJson.scripts), {}, {
477
- 'start:prod:local': appPackageJson.scripts['start:prod:local'].replace('yarn', packageManager)
478
- })
479
- });
574
+ const catalogs = loadCatalogsFromClone(options.clonedRepositoryPath);
575
+ const updatedAppPackageJson = buildUpdatedPackageJson(appPackageJson, options, releaseVersion, catalogs);
480
576
  fs__default["default"].writeFileSync(packageJsonPath, _JSON$stringify__default["default"](updatedAppPackageJson, null, 2) + os__default["default"].EOL, {
481
577
  encoding: 'utf8'
482
578
  });
@@ -9,7 +9,9 @@ var execa = require('execa');
9
9
  var semver = require('semver');
10
10
  var _Promise = require('@babel/runtime-corejs3/core-js-stable/promise');
11
11
  var _startsWithInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/starts-with');
12
+ var _Date$now = require('@babel/runtime-corejs3/core-js-stable/date/now');
12
13
  var crypto = require('node:crypto');
14
+ var os = require('node:os');
13
15
  var path = require('node:path');
14
16
  var readline = require('node:readline');
15
17
  var applicationConfig = require('@commercetools-frontend/application-config');
@@ -21,8 +23,6 @@ var fs = require('node:fs');
21
23
  var _Object$keys = require('@babel/runtime-corejs3/core-js-stable/object/keys');
22
24
  var _includesInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/includes');
23
25
  var _Object$values = require('@babel/runtime-corejs3/core-js-stable/object/values');
24
- var _Date$now = require('@babel/runtime-corejs3/core-js-stable/date/now');
25
- var os = require('node:os');
26
26
  var _Object$getOwnPropertySymbols = require('@babel/runtime-corejs3/core-js-stable/object/get-own-property-symbols');
27
27
  var _Object$getOwnPropertyDescriptor = require('@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptor');
28
28
  var _forEachInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/for-each');
@@ -31,10 +31,10 @@ var _Object$defineProperties = require('@babel/runtime-corejs3/core-js-stable/ob
31
31
  var _Object$defineProperty = require('@babel/runtime-corejs3/core-js-stable/object/define-property');
32
32
  var _defineProperty = require('@babel/runtime-corejs3/helpers/defineProperty');
33
33
  var _slicedToArray = require('@babel/runtime-corejs3/helpers/slicedToArray');
34
- var _reduceInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/reduce');
34
+ var _Map = require('@babel/runtime-corejs3/core-js-stable/map');
35
35
  var _Object$entries = require('@babel/runtime-corejs3/core-js-stable/object/entries');
36
- var _Object$assign = require('@babel/runtime-corejs3/core-js-stable/object/assign');
37
36
  var _JSON$stringify = require('@babel/runtime-corejs3/core-js-stable/json/stringify');
37
+ var yaml = require('yaml');
38
38
  var core = require('@babel/core');
39
39
  var prettier = require('prettier');
40
40
 
@@ -45,7 +45,9 @@ var execa__default = /*#__PURE__*/_interopDefault(execa);
45
45
  var semver__default = /*#__PURE__*/_interopDefault(semver);
46
46
  var _Promise__default = /*#__PURE__*/_interopDefault(_Promise);
47
47
  var _startsWithInstanceProperty__default = /*#__PURE__*/_interopDefault(_startsWithInstanceProperty);
48
+ var _Date$now__default = /*#__PURE__*/_interopDefault(_Date$now);
48
49
  var crypto__default = /*#__PURE__*/_interopDefault(crypto);
50
+ var os__default = /*#__PURE__*/_interopDefault(os);
49
51
  var path__default = /*#__PURE__*/_interopDefault(path);
50
52
  var readline__default = /*#__PURE__*/_interopDefault(readline);
51
53
  var _trimInstanceProperty__default = /*#__PURE__*/_interopDefault(_trimInstanceProperty);
@@ -56,23 +58,20 @@ var fs__default = /*#__PURE__*/_interopDefault(fs);
56
58
  var _Object$keys__default = /*#__PURE__*/_interopDefault(_Object$keys);
57
59
  var _includesInstanceProperty__default = /*#__PURE__*/_interopDefault(_includesInstanceProperty);
58
60
  var _Object$values__default = /*#__PURE__*/_interopDefault(_Object$values);
59
- var _Date$now__default = /*#__PURE__*/_interopDefault(_Date$now);
60
- var os__default = /*#__PURE__*/_interopDefault(os);
61
61
  var _Object$getOwnPropertySymbols__default = /*#__PURE__*/_interopDefault(_Object$getOwnPropertySymbols);
62
62
  var _Object$getOwnPropertyDescriptor__default = /*#__PURE__*/_interopDefault(_Object$getOwnPropertyDescriptor);
63
63
  var _forEachInstanceProperty__default = /*#__PURE__*/_interopDefault(_forEachInstanceProperty);
64
64
  var _Object$getOwnPropertyDescriptors__default = /*#__PURE__*/_interopDefault(_Object$getOwnPropertyDescriptors);
65
65
  var _Object$defineProperties__default = /*#__PURE__*/_interopDefault(_Object$defineProperties);
66
66
  var _Object$defineProperty__default = /*#__PURE__*/_interopDefault(_Object$defineProperty);
67
- var _reduceInstanceProperty__default = /*#__PURE__*/_interopDefault(_reduceInstanceProperty);
67
+ var _Map__default = /*#__PURE__*/_interopDefault(_Map);
68
68
  var _Object$entries__default = /*#__PURE__*/_interopDefault(_Object$entries);
69
- var _Object$assign__default = /*#__PURE__*/_interopDefault(_Object$assign);
70
69
  var _JSON$stringify__default = /*#__PURE__*/_interopDefault(_JSON$stringify);
71
70
  var prettier__default = /*#__PURE__*/_interopDefault(prettier);
72
71
 
73
72
  var pkgJson = {
74
73
  name: "@commercetools-frontend/create-mc-app",
75
- version: "27.6.2",
74
+ version: "27.7.0",
76
75
  description: "Create Merchant Center applications to quickly get up and running",
77
76
  bugs: "https://github.com/commercetools/merchant-center-application-kit/issues",
78
77
  repository: {
@@ -95,21 +94,22 @@ var pkgJson = {
95
94
  module: "dist/commercetools-frontend-create-mc-app.esm.js",
96
95
  bin: "./bin/cli.js",
97
96
  dependencies: {
98
- "@babel/core": "^7.22.17",
99
- "@babel/runtime": "^7.22.15",
100
- "@babel/runtime-corejs3": "^7.22.15",
101
- "@commercetools-frontend/application-config": "^27.6.2",
102
- "@types/babel__core": "^7.20.1",
103
- "@types/semver": "^7.5.1",
104
- commander: "^13.1.0",
105
- execa: "5.1.1",
106
- listr2: "5.0.8",
107
- prettier: "2.8.8",
108
- semver: "7.7.2"
97
+ "@babel/core": "catalog:build",
98
+ "@babel/runtime": "catalog:build",
99
+ "@babel/runtime-corejs3": "catalog:build",
100
+ "@commercetools-frontend/application-config": "workspace:^",
101
+ "@types/babel__core": "catalog:",
102
+ "@types/semver": "catalog:",
103
+ commander: "catalog:",
104
+ execa: "catalog:",
105
+ listr2: "catalog:",
106
+ prettier: "catalog:lint",
107
+ semver: "catalog:",
108
+ yaml: "catalog:"
109
109
  },
110
110
  devDependencies: {
111
- "@tsconfig/node22": "^22.0.0",
112
- "@types/prettier": "2.7.3"
111
+ "@tsconfig/node22": "catalog:",
112
+ "@types/prettier": "catalog:"
113
113
  },
114
114
  engines: {
115
115
  node: "18.x || 20.x || >=22.0.0"
@@ -345,12 +345,22 @@ async function processOptions(projectDirectoryName, options) {
345
345
  const initialProjectKey = await getInitialProjectKey(rl, options);
346
346
  const cloudIdentifier = await getCloudIdentifier(rl, options);
347
347
  rl.close();
348
+
349
+ // Compute the path used by `downloadTemplate` to clone the app-kit repo
350
+ // here so subsequent tasks (e.g. `updatePackageJson`) can read
351
+ // pnpm-workspace.yaml from the same checkout to resolve catalog refs.
352
+ // Branch names with `/` (`feat/foo`) would otherwise create a nested
353
+ // tmp path and break dirname/basename splits downstream — sanitize them
354
+ // into the folder name only.
355
+ const safeBranchSegment = tagOrBranchVersion.replace(/[^A-Za-z0-9._-]/g, '_');
356
+ const clonedRepositoryPath = path__default["default"].join(os__default["default"].tmpdir(), ['merchant-center-application-kit', '--', safeBranchSegment, '--', _Date$now__default["default"]().toString()].join(''));
348
357
  return {
349
358
  applicationType: options.applicationType,
350
359
  projectDirectoryName,
351
360
  projectDirectoryPath,
352
361
  templateName,
353
362
  tagOrBranchVersion,
363
+ clonedRepositoryPath,
354
364
  entryPointUriPath,
355
365
  initialProjectKey,
356
366
  cloudIdentifier,
@@ -363,9 +373,9 @@ function downloadTemplate(options) {
363
373
  return {
364
374
  title: 'Downloading template',
365
375
  task: () => {
366
- const tmpDir = os__default["default"].tmpdir();
367
- const tmpFolderNameForClonedRepository = ['merchant-center-application-kit', '--', options.tagOrBranchVersion, '--', _Date$now__default["default"]().toString()].join('');
368
- const clonedRepositoryPath = path__default["default"].join(tmpDir, tmpFolderNameForClonedRepository);
376
+ const clonedRepositoryPath = options.clonedRepositoryPath;
377
+ const tmpDir = path__default["default"].dirname(clonedRepositoryPath);
378
+ const tmpFolderNameForClonedRepository = path__default["default"].basename(clonedRepositoryPath);
369
379
  const templateFolderPath = path__default["default"].join(clonedRepositoryPath, options.applicationType === applicationTypes['custom-view'] ? 'custom-views-templates' : 'application-templates', options.templateName);
370
380
  return new listr2.Listr([{
371
381
  title: `Cloning repository using branch ${options.tagOrBranchVersion}`,
@@ -439,20 +449,120 @@ function installDependencies(options) {
439
449
  }
440
450
 
441
451
  function ownKeys(e, r) { var t = _Object$keys__default["default"](e); if (_Object$getOwnPropertySymbols__default["default"]) { var o = _Object$getOwnPropertySymbols__default["default"](e); r && (o = _filterInstanceProperty__default["default"](o).call(o, function (r) { return _Object$getOwnPropertyDescriptor__default["default"](e, r).enumerable; })), t.push.apply(t, o); } return t; }
442
- function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var _context2, _context3; var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? _forEachInstanceProperty__default["default"](_context2 = ownKeys(Object(t), !0)).call(_context2, function (r) { _defineProperty(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors__default["default"] ? _Object$defineProperties__default["default"](e, _Object$getOwnPropertyDescriptors__default["default"](t)) : _forEachInstanceProperty__default["default"](_context3 = ownKeys(Object(t))).call(_context3, function (r) { _Object$defineProperty__default["default"](e, r, _Object$getOwnPropertyDescriptor__default["default"](t, r)); }); } return e; }
443
- const replaceApplicationKitPackageVersionWith = function (releaseVersion) {
444
- var _context;
445
- let dependencies = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
446
- return _reduceInstanceProperty__default["default"](_context = _Object$entries__default["default"](dependencies)).call(_context, (updatedDependencies, _ref) => {
447
- let _ref2 = _slicedToArray(_ref, 2),
448
- dependencyName = _ref2[0],
449
- dependencyVersion = _ref2[1];
450
- const updatedVersion = dependencyVersion === 'workspace:*' ? releaseVersion : dependencyVersion;
451
- return _objectSpread(_objectSpread({}, updatedDependencies), {}, {
452
- [dependencyName]: updatedVersion
453
- });
454
- }, {});
452
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var _context, _context2; var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? _forEachInstanceProperty__default["default"](_context = ownKeys(Object(t), !0)).call(_context, function (r) { _defineProperty(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors__default["default"] ? _Object$defineProperties__default["default"](e, _Object$getOwnPropertyDescriptors__default["default"](t)) : _forEachInstanceProperty__default["default"](_context2 = ownKeys(Object(t))).call(_context2, function (r) { _Object$defineProperty__default["default"](e, r, _Object$getOwnPropertyDescriptor__default["default"](t, r)); }); } return e; }
453
+
454
+ // Catalog references in workspace package.json files point at entries in
455
+ // pnpm-workspace.yaml. They have to be flattened to concrete version
456
+ // specifiers in the scaffolded app because the scaffolded app is not part
457
+ // of any workspace.
458
+ //
459
+ // Shape: catalogName -> depName -> resolved spec. The default `catalog:`
460
+ // block is keyed as 'default' so `catalog:` and `catalog:<name>` lookups
461
+ // share one code path.
462
+
463
+ function parseCatalogs(yamlText) {
464
+ const doc = yaml.parse(yamlText) ?? {};
465
+ const out = new _Map__default["default"]();
466
+ if (doc.catalog) {
467
+ out.set('default', new _Map__default["default"](_Object$entries__default["default"](doc.catalog)));
468
+ }
469
+ for (const _ref of _Object$entries__default["default"](doc.catalogs ?? {})) {
470
+ var _ref2 = _slicedToArray(_ref, 2);
471
+ const name = _ref2[0];
472
+ const entries = _ref2[1];
473
+ out.set(name, new _Map__default["default"](_Object$entries__default["default"](entries)));
474
+ }
475
+ return out;
476
+ }
477
+
478
+ // `workspace:` specifier → rewriter that takes the release version and
479
+ // returns the concrete spec. The supported set is data, not branching
480
+ // logic — extend the table to handle new protocol additions.
481
+ const WORKSPACE_REWRITERS = {
482
+ 'workspace:*': v => v,
483
+ 'workspace:^': v => `^${v}`,
484
+ 'workspace:~': v => `~${v}`
455
485
  };
486
+
487
+ /**
488
+ * Resolve a `catalog:` / `catalog:<name>` specifier to a concrete version
489
+ * string by looking it up in the parsed `pnpm-workspace.yaml`.
490
+ *
491
+ * @throws {Error} when the named catalog does not exist in the template's
492
+ * `pnpm-workspace.yaml`, or when the catalog exists but does not declare
493
+ * an entry for `depName`. Both cases mean the scaffold cannot produce a
494
+ * valid `package.json` and is unrecoverable — let it propagate.
495
+ */
496
+ function resolveCatalogRef(spec, depName, catalogs) {
497
+ // `catalog:` and `catalog:default` both target the default block.
498
+ const name = spec === 'catalog:' || spec === 'catalog:default' ? 'default' : _sliceInstanceProperty__default["default"](spec).call(spec, 'catalog:'.length);
499
+ const block = catalogs.get(name);
500
+ if (!block) {
501
+ throw new Error(`Unable to resolve catalog reference "${spec}" for "${depName}": catalog "${name}" is not declared in the template's pnpm-workspace.yaml.`);
502
+ }
503
+ const resolved = block.get(depName);
504
+ if (!resolved) {
505
+ const where = name === 'default' ? 'the default catalog' : `catalogs.${name}`;
506
+ throw new Error(`Unable to resolve catalog reference "${spec}" for "${depName}": dep is not declared under ${where} in the template's pnpm-workspace.yaml.`);
507
+ }
508
+ return resolved;
509
+ }
510
+ function resolveSpec(depName, spec, releaseVersion, catalogs) {
511
+ const workspaceRewriter = WORKSPACE_REWRITERS[spec];
512
+ if (workspaceRewriter) return workspaceRewriter(releaseVersion);
513
+ if (_startsWithInstanceProperty__default["default"](spec).call(spec, 'catalog:')) return resolveCatalogRef(spec, depName, catalogs);
514
+ return spec;
515
+ }
516
+ function resolveDependencies() {
517
+ let dependencies = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
518
+ let releaseVersion = arguments.length > 1 ? arguments[1] : undefined;
519
+ let catalogs = arguments.length > 2 ? arguments[2] : undefined;
520
+ const out = {};
521
+ for (const _ref3 of _Object$entries__default["default"](dependencies)) {
522
+ var _ref4 = _slicedToArray(_ref3, 2);
523
+ const name = _ref4[0];
524
+ const spec = _ref4[1];
525
+ out[name] = resolveSpec(name, spec, releaseVersion, catalogs);
526
+ }
527
+ return out;
528
+ }
529
+
530
+ // Read catalogs from the cloned template repo. Older template tags predate
531
+ // catalog adoption — fall back to an empty map so the workspace-only
532
+ // rewrite path still works.
533
+ function loadCatalogsFromClone(clonedRepositoryPath) {
534
+ const workspaceYamlPath = path__default["default"].join(clonedRepositoryPath, 'pnpm-workspace.yaml');
535
+ if (!fs__default["default"].existsSync(workspaceYamlPath)) return new _Map__default["default"]();
536
+ return parseCatalogs(fs__default["default"].readFileSync(workspaceYamlPath, {
537
+ encoding: 'utf8'
538
+ }));
539
+ }
540
+ function buildUpdatedPackageJson(appPackageJson, options, releaseVersion, catalogs) {
541
+ const packageManager = getPreferredPackageManager(options);
542
+ // Flatten workspace: and catalog: specifiers into concrete versions across
543
+ // every dependency section — the scaffolded app is not part of any pnpm
544
+ // workspace and would otherwise fail to install.
545
+ const resolve = deps => resolveDependencies(deps, releaseVersion, catalogs);
546
+ return _objectSpread(_objectSpread(_objectSpread(_objectSpread({}, appPackageJson), {}, {
547
+ version: '1.0.0',
548
+ // Given the package name is derived from the `projectDirectoryName`
549
+ // the latter needs to be sanitised to have a ensure a valid package name.
550
+ // The `projectDirectoryName` should not have restrictions (e.g. no `_`)
551
+ // as a result the package name potentially needs to be altered when derived.
552
+ name: slugify(options.projectDirectoryName),
553
+ description: '',
554
+ dependencies: resolve(appPackageJson.dependencies),
555
+ devDependencies: resolve(appPackageJson.devDependencies)
556
+ }, appPackageJson.peerDependencies && {
557
+ peerDependencies: resolve(appPackageJson.peerDependencies)
558
+ }), appPackageJson.optionalDependencies && {
559
+ optionalDependencies: resolve(appPackageJson.optionalDependencies)
560
+ }), {}, {
561
+ scripts: _objectSpread(_objectSpread({}, appPackageJson.scripts), {}, {
562
+ 'start:prod:local': appPackageJson.scripts['start:prod:local'].replace('yarn', packageManager)
563
+ })
564
+ });
565
+ }
456
566
  function updatePackageJson(options, releaseVersion) {
457
567
  return {
458
568
  title: 'Updating package.json',
@@ -461,22 +571,8 @@ function updatePackageJson(options, releaseVersion) {
461
571
  const appPackageJson = JSON.parse(fs__default["default"].readFileSync(packageJsonPath, {
462
572
  encoding: 'utf8'
463
573
  }));
464
- const packageManager = getPreferredPackageManager(options);
465
- const updatedAppPackageJson = _Object$assign__default["default"]({}, appPackageJson, {
466
- version: '1.0.0',
467
- // Given the package name is derived from the `projectDirectoryName`
468
- // the latter needs to be sanitised to have a ensure a valid package name.
469
- // The `projectDirectoryName` should not have restrictions (e.g. no `_`)
470
- // as a result the package name potentially needs to be altered when derived.
471
- name: slugify(options.projectDirectoryName),
472
- description: '',
473
- // Replace the package versions with the `workspace:` syntax to the real version.
474
- dependencies: replaceApplicationKitPackageVersionWith(releaseVersion, appPackageJson.dependencies),
475
- devDependencies: replaceApplicationKitPackageVersionWith(releaseVersion, appPackageJson.devDependencies),
476
- scripts: _objectSpread(_objectSpread({}, appPackageJson.scripts), {}, {
477
- 'start:prod:local': appPackageJson.scripts['start:prod:local'].replace('yarn', packageManager)
478
- })
479
- });
574
+ const catalogs = loadCatalogsFromClone(options.clonedRepositoryPath);
575
+ const updatedAppPackageJson = buildUpdatedPackageJson(appPackageJson, options, releaseVersion, catalogs);
480
576
  fs__default["default"].writeFileSync(packageJsonPath, _JSON$stringify__default["default"](updatedAppPackageJson, null, 2) + os__default["default"].EOL, {
481
577
  encoding: 'utf8'
482
578
  });
@@ -5,7 +5,9 @@ import execa from 'execa';
5
5
  import semver from 'semver';
6
6
  import _Promise from '@babel/runtime-corejs3/core-js-stable/promise';
7
7
  import _startsWithInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/starts-with';
8
+ import _Date$now from '@babel/runtime-corejs3/core-js-stable/date/now';
8
9
  import crypto from 'node:crypto';
10
+ import os from 'node:os';
9
11
  import path from 'node:path';
10
12
  import readline from 'node:readline';
11
13
  import { CLOUD_IDENTIFIERS } from '@commercetools-frontend/application-config';
@@ -17,8 +19,6 @@ import fs from 'node:fs';
17
19
  import _Object$keys from '@babel/runtime-corejs3/core-js-stable/object/keys';
18
20
  import _includesInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/includes';
19
21
  import _Object$values from '@babel/runtime-corejs3/core-js-stable/object/values';
20
- import _Date$now from '@babel/runtime-corejs3/core-js-stable/date/now';
21
- import os from 'node:os';
22
22
  import _Object$getOwnPropertySymbols from '@babel/runtime-corejs3/core-js-stable/object/get-own-property-symbols';
23
23
  import _Object$getOwnPropertyDescriptor from '@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptor';
24
24
  import _forEachInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/for-each';
@@ -27,16 +27,16 @@ import _Object$defineProperties from '@babel/runtime-corejs3/core-js-stable/obje
27
27
  import _Object$defineProperty from '@babel/runtime-corejs3/core-js-stable/object/define-property';
28
28
  import _defineProperty from '@babel/runtime-corejs3/helpers/esm/defineProperty';
29
29
  import _slicedToArray from '@babel/runtime-corejs3/helpers/esm/slicedToArray';
30
- import _reduceInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/reduce';
30
+ import _Map from '@babel/runtime-corejs3/core-js-stable/map';
31
31
  import _Object$entries from '@babel/runtime-corejs3/core-js-stable/object/entries';
32
- import _Object$assign from '@babel/runtime-corejs3/core-js-stable/object/assign';
33
32
  import _JSON$stringify from '@babel/runtime-corejs3/core-js-stable/json/stringify';
33
+ import { parse } from 'yaml';
34
34
  import { transformFileSync, types } from '@babel/core';
35
35
  import prettier from 'prettier';
36
36
 
37
37
  var pkgJson = {
38
38
  name: "@commercetools-frontend/create-mc-app",
39
- version: "27.6.2",
39
+ version: "27.7.0",
40
40
  description: "Create Merchant Center applications to quickly get up and running",
41
41
  bugs: "https://github.com/commercetools/merchant-center-application-kit/issues",
42
42
  repository: {
@@ -59,21 +59,22 @@ var pkgJson = {
59
59
  module: "dist/commercetools-frontend-create-mc-app.esm.js",
60
60
  bin: "./bin/cli.js",
61
61
  dependencies: {
62
- "@babel/core": "^7.22.17",
63
- "@babel/runtime": "^7.22.15",
64
- "@babel/runtime-corejs3": "^7.22.15",
65
- "@commercetools-frontend/application-config": "^27.6.2",
66
- "@types/babel__core": "^7.20.1",
67
- "@types/semver": "^7.5.1",
68
- commander: "^13.1.0",
69
- execa: "5.1.1",
70
- listr2: "5.0.8",
71
- prettier: "2.8.8",
72
- semver: "7.7.2"
62
+ "@babel/core": "catalog:build",
63
+ "@babel/runtime": "catalog:build",
64
+ "@babel/runtime-corejs3": "catalog:build",
65
+ "@commercetools-frontend/application-config": "workspace:^",
66
+ "@types/babel__core": "catalog:",
67
+ "@types/semver": "catalog:",
68
+ commander: "catalog:",
69
+ execa: "catalog:",
70
+ listr2: "catalog:",
71
+ prettier: "catalog:lint",
72
+ semver: "catalog:",
73
+ yaml: "catalog:"
73
74
  },
74
75
  devDependencies: {
75
- "@tsconfig/node22": "^22.0.0",
76
- "@types/prettier": "2.7.3"
76
+ "@tsconfig/node22": "catalog:",
77
+ "@types/prettier": "catalog:"
77
78
  },
78
79
  engines: {
79
80
  node: "18.x || 20.x || >=22.0.0"
@@ -309,12 +310,22 @@ async function processOptions(projectDirectoryName, options) {
309
310
  const initialProjectKey = await getInitialProjectKey(rl, options);
310
311
  const cloudIdentifier = await getCloudIdentifier(rl, options);
311
312
  rl.close();
313
+
314
+ // Compute the path used by `downloadTemplate` to clone the app-kit repo
315
+ // here so subsequent tasks (e.g. `updatePackageJson`) can read
316
+ // pnpm-workspace.yaml from the same checkout to resolve catalog refs.
317
+ // Branch names with `/` (`feat/foo`) would otherwise create a nested
318
+ // tmp path and break dirname/basename splits downstream — sanitize them
319
+ // into the folder name only.
320
+ const safeBranchSegment = tagOrBranchVersion.replace(/[^A-Za-z0-9._-]/g, '_');
321
+ const clonedRepositoryPath = path.join(os.tmpdir(), ['merchant-center-application-kit', '--', safeBranchSegment, '--', _Date$now().toString()].join(''));
312
322
  return {
313
323
  applicationType: options.applicationType,
314
324
  projectDirectoryName,
315
325
  projectDirectoryPath,
316
326
  templateName,
317
327
  tagOrBranchVersion,
328
+ clonedRepositoryPath,
318
329
  entryPointUriPath,
319
330
  initialProjectKey,
320
331
  cloudIdentifier,
@@ -327,9 +338,9 @@ function downloadTemplate(options) {
327
338
  return {
328
339
  title: 'Downloading template',
329
340
  task: () => {
330
- const tmpDir = os.tmpdir();
331
- const tmpFolderNameForClonedRepository = ['merchant-center-application-kit', '--', options.tagOrBranchVersion, '--', _Date$now().toString()].join('');
332
- const clonedRepositoryPath = path.join(tmpDir, tmpFolderNameForClonedRepository);
341
+ const clonedRepositoryPath = options.clonedRepositoryPath;
342
+ const tmpDir = path.dirname(clonedRepositoryPath);
343
+ const tmpFolderNameForClonedRepository = path.basename(clonedRepositoryPath);
333
344
  const templateFolderPath = path.join(clonedRepositoryPath, options.applicationType === applicationTypes['custom-view'] ? 'custom-views-templates' : 'application-templates', options.templateName);
334
345
  return new Listr([{
335
346
  title: `Cloning repository using branch ${options.tagOrBranchVersion}`,
@@ -403,20 +414,120 @@ function installDependencies(options) {
403
414
  }
404
415
 
405
416
  function ownKeys(e, r) { var t = _Object$keys(e); if (_Object$getOwnPropertySymbols) { var o = _Object$getOwnPropertySymbols(e); r && (o = _filterInstanceProperty(o).call(o, function (r) { return _Object$getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
406
- function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var _context2, _context3; var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? _forEachInstanceProperty(_context2 = ownKeys(Object(t), !0)).call(_context2, function (r) { _defineProperty(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(e, _Object$getOwnPropertyDescriptors(t)) : _forEachInstanceProperty(_context3 = ownKeys(Object(t))).call(_context3, function (r) { _Object$defineProperty(e, r, _Object$getOwnPropertyDescriptor(t, r)); }); } return e; }
407
- const replaceApplicationKitPackageVersionWith = function (releaseVersion) {
408
- var _context;
409
- let dependencies = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
410
- return _reduceInstanceProperty(_context = _Object$entries(dependencies)).call(_context, (updatedDependencies, _ref) => {
411
- let _ref2 = _slicedToArray(_ref, 2),
412
- dependencyName = _ref2[0],
413
- dependencyVersion = _ref2[1];
414
- const updatedVersion = dependencyVersion === 'workspace:*' ? releaseVersion : dependencyVersion;
415
- return _objectSpread(_objectSpread({}, updatedDependencies), {}, {
416
- [dependencyName]: updatedVersion
417
- });
418
- }, {});
417
+ function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var _context, _context2; var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? _forEachInstanceProperty(_context = ownKeys(Object(t), !0)).call(_context, function (r) { _defineProperty(e, r, t[r]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(e, _Object$getOwnPropertyDescriptors(t)) : _forEachInstanceProperty(_context2 = ownKeys(Object(t))).call(_context2, function (r) { _Object$defineProperty(e, r, _Object$getOwnPropertyDescriptor(t, r)); }); } return e; }
418
+
419
+ // Catalog references in workspace package.json files point at entries in
420
+ // pnpm-workspace.yaml. They have to be flattened to concrete version
421
+ // specifiers in the scaffolded app because the scaffolded app is not part
422
+ // of any workspace.
423
+ //
424
+ // Shape: catalogName -> depName -> resolved spec. The default `catalog:`
425
+ // block is keyed as 'default' so `catalog:` and `catalog:<name>` lookups
426
+ // share one code path.
427
+
428
+ function parseCatalogs(yamlText) {
429
+ const doc = parse(yamlText) ?? {};
430
+ const out = new _Map();
431
+ if (doc.catalog) {
432
+ out.set('default', new _Map(_Object$entries(doc.catalog)));
433
+ }
434
+ for (const _ref of _Object$entries(doc.catalogs ?? {})) {
435
+ var _ref2 = _slicedToArray(_ref, 2);
436
+ const name = _ref2[0];
437
+ const entries = _ref2[1];
438
+ out.set(name, new _Map(_Object$entries(entries)));
439
+ }
440
+ return out;
441
+ }
442
+
443
+ // `workspace:` specifier → rewriter that takes the release version and
444
+ // returns the concrete spec. The supported set is data, not branching
445
+ // logic — extend the table to handle new protocol additions.
446
+ const WORKSPACE_REWRITERS = {
447
+ 'workspace:*': v => v,
448
+ 'workspace:^': v => `^${v}`,
449
+ 'workspace:~': v => `~${v}`
419
450
  };
451
+
452
+ /**
453
+ * Resolve a `catalog:` / `catalog:<name>` specifier to a concrete version
454
+ * string by looking it up in the parsed `pnpm-workspace.yaml`.
455
+ *
456
+ * @throws {Error} when the named catalog does not exist in the template's
457
+ * `pnpm-workspace.yaml`, or when the catalog exists but does not declare
458
+ * an entry for `depName`. Both cases mean the scaffold cannot produce a
459
+ * valid `package.json` and is unrecoverable — let it propagate.
460
+ */
461
+ function resolveCatalogRef(spec, depName, catalogs) {
462
+ // `catalog:` and `catalog:default` both target the default block.
463
+ const name = spec === 'catalog:' || spec === 'catalog:default' ? 'default' : _sliceInstanceProperty(spec).call(spec, 'catalog:'.length);
464
+ const block = catalogs.get(name);
465
+ if (!block) {
466
+ throw new Error(`Unable to resolve catalog reference "${spec}" for "${depName}": catalog "${name}" is not declared in the template's pnpm-workspace.yaml.`);
467
+ }
468
+ const resolved = block.get(depName);
469
+ if (!resolved) {
470
+ const where = name === 'default' ? 'the default catalog' : `catalogs.${name}`;
471
+ throw new Error(`Unable to resolve catalog reference "${spec}" for "${depName}": dep is not declared under ${where} in the template's pnpm-workspace.yaml.`);
472
+ }
473
+ return resolved;
474
+ }
475
+ function resolveSpec(depName, spec, releaseVersion, catalogs) {
476
+ const workspaceRewriter = WORKSPACE_REWRITERS[spec];
477
+ if (workspaceRewriter) return workspaceRewriter(releaseVersion);
478
+ if (_startsWithInstanceProperty(spec).call(spec, 'catalog:')) return resolveCatalogRef(spec, depName, catalogs);
479
+ return spec;
480
+ }
481
+ function resolveDependencies() {
482
+ let dependencies = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
483
+ let releaseVersion = arguments.length > 1 ? arguments[1] : undefined;
484
+ let catalogs = arguments.length > 2 ? arguments[2] : undefined;
485
+ const out = {};
486
+ for (const _ref3 of _Object$entries(dependencies)) {
487
+ var _ref4 = _slicedToArray(_ref3, 2);
488
+ const name = _ref4[0];
489
+ const spec = _ref4[1];
490
+ out[name] = resolveSpec(name, spec, releaseVersion, catalogs);
491
+ }
492
+ return out;
493
+ }
494
+
495
+ // Read catalogs from the cloned template repo. Older template tags predate
496
+ // catalog adoption — fall back to an empty map so the workspace-only
497
+ // rewrite path still works.
498
+ function loadCatalogsFromClone(clonedRepositoryPath) {
499
+ const workspaceYamlPath = path.join(clonedRepositoryPath, 'pnpm-workspace.yaml');
500
+ if (!fs.existsSync(workspaceYamlPath)) return new _Map();
501
+ return parseCatalogs(fs.readFileSync(workspaceYamlPath, {
502
+ encoding: 'utf8'
503
+ }));
504
+ }
505
+ function buildUpdatedPackageJson(appPackageJson, options, releaseVersion, catalogs) {
506
+ const packageManager = getPreferredPackageManager(options);
507
+ // Flatten workspace: and catalog: specifiers into concrete versions across
508
+ // every dependency section — the scaffolded app is not part of any pnpm
509
+ // workspace and would otherwise fail to install.
510
+ const resolve = deps => resolveDependencies(deps, releaseVersion, catalogs);
511
+ return _objectSpread(_objectSpread(_objectSpread(_objectSpread({}, appPackageJson), {}, {
512
+ version: '1.0.0',
513
+ // Given the package name is derived from the `projectDirectoryName`
514
+ // the latter needs to be sanitised to have a ensure a valid package name.
515
+ // The `projectDirectoryName` should not have restrictions (e.g. no `_`)
516
+ // as a result the package name potentially needs to be altered when derived.
517
+ name: slugify(options.projectDirectoryName),
518
+ description: '',
519
+ dependencies: resolve(appPackageJson.dependencies),
520
+ devDependencies: resolve(appPackageJson.devDependencies)
521
+ }, appPackageJson.peerDependencies && {
522
+ peerDependencies: resolve(appPackageJson.peerDependencies)
523
+ }), appPackageJson.optionalDependencies && {
524
+ optionalDependencies: resolve(appPackageJson.optionalDependencies)
525
+ }), {}, {
526
+ scripts: _objectSpread(_objectSpread({}, appPackageJson.scripts), {}, {
527
+ 'start:prod:local': appPackageJson.scripts['start:prod:local'].replace('yarn', packageManager)
528
+ })
529
+ });
530
+ }
420
531
  function updatePackageJson(options, releaseVersion) {
421
532
  return {
422
533
  title: 'Updating package.json',
@@ -425,22 +536,8 @@ function updatePackageJson(options, releaseVersion) {
425
536
  const appPackageJson = JSON.parse(fs.readFileSync(packageJsonPath, {
426
537
  encoding: 'utf8'
427
538
  }));
428
- const packageManager = getPreferredPackageManager(options);
429
- const updatedAppPackageJson = _Object$assign({}, appPackageJson, {
430
- version: '1.0.0',
431
- // Given the package name is derived from the `projectDirectoryName`
432
- // the latter needs to be sanitised to have a ensure a valid package name.
433
- // The `projectDirectoryName` should not have restrictions (e.g. no `_`)
434
- // as a result the package name potentially needs to be altered when derived.
435
- name: slugify(options.projectDirectoryName),
436
- description: '',
437
- // Replace the package versions with the `workspace:` syntax to the real version.
438
- dependencies: replaceApplicationKitPackageVersionWith(releaseVersion, appPackageJson.dependencies),
439
- devDependencies: replaceApplicationKitPackageVersionWith(releaseVersion, appPackageJson.devDependencies),
440
- scripts: _objectSpread(_objectSpread({}, appPackageJson.scripts), {}, {
441
- 'start:prod:local': appPackageJson.scripts['start:prod:local'].replace('yarn', packageManager)
442
- })
443
- });
539
+ const catalogs = loadCatalogsFromClone(options.clonedRepositoryPath);
540
+ const updatedAppPackageJson = buildUpdatedPackageJson(appPackageJson, options, releaseVersion, catalogs);
444
541
  fs.writeFileSync(packageJsonPath, _JSON$stringify(updatedAppPackageJson, null, 2) + os.EOL, {
445
542
  encoding: 'utf8'
446
543
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@commercetools-frontend/create-mc-app",
3
- "version": "27.6.2",
3
+ "version": "27.7.0",
4
4
  "description": "Create Merchant Center applications to quickly get up and running",
5
5
  "bugs": "https://github.com/commercetools/merchant-center-application-kit/issues",
6
6
  "repository": {
@@ -26,14 +26,15 @@
26
26
  "@babel/core": "^7.22.17",
27
27
  "@babel/runtime": "^7.22.15",
28
28
  "@babel/runtime-corejs3": "^7.22.15",
29
- "@commercetools-frontend/application-config": "^27.6.2",
30
29
  "@types/babel__core": "^7.20.1",
31
30
  "@types/semver": "^7.5.1",
32
31
  "commander": "^13.1.0",
33
32
  "execa": "5.1.1",
34
33
  "listr2": "5.0.8",
35
34
  "prettier": "2.8.8",
36
- "semver": "7.7.2"
35
+ "semver": "7.7.2",
36
+ "yaml": "^2.6.1",
37
+ "@commercetools-frontend/application-config": "^27.7.0"
37
38
  },
38
39
  "devDependencies": {
39
40
  "@tsconfig/node22": "^22.0.0",
@@ -1,4 +1,5 @@
1
1
  import crypto from 'node:crypto';
2
+ import os from 'node:os';
2
3
  import path from 'node:path';
3
4
  import readline, { type Interface } from 'node:readline';
4
5
  import { CLOUD_IDENTIFIERS } from '@commercetools-frontend/application-config';
@@ -118,12 +119,31 @@ async function processOptions(
118
119
  const cloudIdentifier = await getCloudIdentifier(rl, options);
119
120
  rl.close();
120
121
 
122
+ // Compute the path used by `downloadTemplate` to clone the app-kit repo
123
+ // here so subsequent tasks (e.g. `updatePackageJson`) can read
124
+ // pnpm-workspace.yaml from the same checkout to resolve catalog refs.
125
+ // Branch names with `/` (`feat/foo`) would otherwise create a nested
126
+ // tmp path and break dirname/basename splits downstream — sanitize them
127
+ // into the folder name only.
128
+ const safeBranchSegment = tagOrBranchVersion.replace(/[^A-Za-z0-9._-]/g, '_');
129
+ const clonedRepositoryPath = path.join(
130
+ os.tmpdir(),
131
+ [
132
+ 'merchant-center-application-kit',
133
+ '--',
134
+ safeBranchSegment,
135
+ '--',
136
+ Date.now().toString(),
137
+ ].join('')
138
+ );
139
+
121
140
  return {
122
141
  applicationType: options.applicationType,
123
142
  projectDirectoryName,
124
143
  projectDirectoryPath,
125
144
  templateName,
126
145
  tagOrBranchVersion,
146
+ clonedRepositoryPath,
127
147
  entryPointUriPath,
128
148
  initialProjectKey,
129
149
  cloudIdentifier,
@@ -1,4 +1,3 @@
1
- import os from 'node:os';
2
1
  import path from 'node:path';
3
2
  import execa from 'execa';
4
3
  import { Listr, type ListrTask } from 'listr2';
@@ -13,18 +12,10 @@ function downloadTemplate(options: TCliTaskOptions): ListrTask {
13
12
  return {
14
13
  title: 'Downloading template',
15
14
  task: () => {
16
- const tmpDir = os.tmpdir();
17
- const tmpFolderNameForClonedRepository = [
18
- 'merchant-center-application-kit',
19
- '--',
20
- options.tagOrBranchVersion,
21
- '--',
22
- Date.now().toString(),
23
- ].join('');
24
- const clonedRepositoryPath = path.join(
25
- tmpDir,
26
- tmpFolderNameForClonedRepository
27
- );
15
+ const clonedRepositoryPath = options.clonedRepositoryPath;
16
+ const tmpDir = path.dirname(clonedRepositoryPath);
17
+ const tmpFolderNameForClonedRepository =
18
+ path.basename(clonedRepositoryPath);
28
19
  const templateFolderPath = path.join(
29
20
  clonedRepositoryPath,
30
21
  options.applicationType === applicationTypes['custom-view']
@@ -2,26 +2,169 @@ import fs from 'node:fs';
2
2
  import os from 'node:os';
3
3
  import path from 'node:path';
4
4
  import type { ListrTask } from 'listr2';
5
+ import { parse as parseYaml } from 'yaml';
5
6
  import type { TCliTaskOptions } from '../types';
6
7
  import { getPreferredPackageManager, slugify } from '../utils';
7
8
 
8
- const replaceApplicationKitPackageVersionWith = (
9
+ // Catalog references in workspace package.json files point at entries in
10
+ // pnpm-workspace.yaml. They have to be flattened to concrete version
11
+ // specifiers in the scaffolded app because the scaffolded app is not part
12
+ // of any workspace.
13
+ //
14
+ // Shape: catalogName -> depName -> resolved spec. The default `catalog:`
15
+ // block is keyed as 'default' so `catalog:` and `catalog:<name>` lookups
16
+ // share one code path.
17
+ type Catalogs = Map<string, Map<string, string>>;
18
+
19
+ type WorkspaceYaml = {
20
+ catalog?: Record<string, string>;
21
+ catalogs?: Record<string, Record<string, string>>;
22
+ };
23
+
24
+ function parseCatalogs(yamlText: string): Catalogs {
25
+ const doc = (parseYaml(yamlText) ?? {}) as WorkspaceYaml;
26
+ const out: Catalogs = new Map();
27
+ if (doc.catalog) {
28
+ out.set('default', new Map(Object.entries(doc.catalog)));
29
+ }
30
+ for (const [name, entries] of Object.entries(doc.catalogs ?? {})) {
31
+ out.set(name, new Map(Object.entries(entries)));
32
+ }
33
+ return out;
34
+ }
35
+
36
+ // `workspace:` specifier → rewriter that takes the release version and
37
+ // returns the concrete spec. The supported set is data, not branching
38
+ // logic — extend the table to handle new protocol additions.
39
+ const WORKSPACE_REWRITERS: Record<string, (releaseVersion: string) => string> =
40
+ {
41
+ 'workspace:*': (v) => v,
42
+ 'workspace:^': (v) => `^${v}`,
43
+ 'workspace:~': (v) => `~${v}`,
44
+ };
45
+
46
+ /**
47
+ * Resolve a `catalog:` / `catalog:<name>` specifier to a concrete version
48
+ * string by looking it up in the parsed `pnpm-workspace.yaml`.
49
+ *
50
+ * @throws {Error} when the named catalog does not exist in the template's
51
+ * `pnpm-workspace.yaml`, or when the catalog exists but does not declare
52
+ * an entry for `depName`. Both cases mean the scaffold cannot produce a
53
+ * valid `package.json` and is unrecoverable — let it propagate.
54
+ */
55
+ function resolveCatalogRef(
56
+ spec: string,
57
+ depName: string,
58
+ catalogs: Catalogs
59
+ ): string {
60
+ // `catalog:` and `catalog:default` both target the default block.
61
+ const name =
62
+ spec === 'catalog:' || spec === 'catalog:default'
63
+ ? 'default'
64
+ : spec.slice('catalog:'.length);
65
+ const block = catalogs.get(name);
66
+ if (!block) {
67
+ throw new Error(
68
+ `Unable to resolve catalog reference "${spec}" for "${depName}": catalog "${name}" is not declared in the template's pnpm-workspace.yaml.`
69
+ );
70
+ }
71
+ const resolved = block.get(depName);
72
+ if (!resolved) {
73
+ const where =
74
+ name === 'default' ? 'the default catalog' : `catalogs.${name}`;
75
+ throw new Error(
76
+ `Unable to resolve catalog reference "${spec}" for "${depName}": dep is not declared under ${where} in the template's pnpm-workspace.yaml.`
77
+ );
78
+ }
79
+ return resolved;
80
+ }
81
+
82
+ function resolveSpec(
83
+ depName: string,
84
+ spec: string,
9
85
  releaseVersion: string,
10
- dependencies: Record<string, string> = {}
11
- ) =>
12
- Object.entries(dependencies).reduce(
13
- (updatedDependencies, [dependencyName, dependencyVersion]) => {
14
- const updatedVersion =
15
- dependencyVersion === 'workspace:*'
16
- ? releaseVersion
17
- : dependencyVersion;
18
- return {
19
- ...updatedDependencies,
20
- [dependencyName]: updatedVersion,
21
- };
22
- },
23
- {}
86
+ catalogs: Catalogs
87
+ ): string {
88
+ const workspaceRewriter = WORKSPACE_REWRITERS[spec];
89
+ if (workspaceRewriter) return workspaceRewriter(releaseVersion);
90
+ if (spec.startsWith('catalog:'))
91
+ return resolveCatalogRef(spec, depName, catalogs);
92
+ return spec;
93
+ }
94
+
95
+ function resolveDependencies(
96
+ dependencies: Record<string, string> = {},
97
+ releaseVersion: string,
98
+ catalogs: Catalogs
99
+ ): Record<string, string> {
100
+ const out: Record<string, string> = {};
101
+ for (const [name, spec] of Object.entries(dependencies)) {
102
+ out[name] = resolveSpec(name, spec, releaseVersion, catalogs);
103
+ }
104
+ return out;
105
+ }
106
+
107
+ // Read catalogs from the cloned template repo. Older template tags predate
108
+ // catalog adoption — fall back to an empty map so the workspace-only
109
+ // rewrite path still works.
110
+ function loadCatalogsFromClone(clonedRepositoryPath: string): Catalogs {
111
+ const workspaceYamlPath = path.join(
112
+ clonedRepositoryPath,
113
+ 'pnpm-workspace.yaml'
24
114
  );
115
+ if (!fs.existsSync(workspaceYamlPath)) return new Map();
116
+ return parseCatalogs(
117
+ fs.readFileSync(workspaceYamlPath, { encoding: 'utf8' })
118
+ );
119
+ }
120
+
121
+ type TAppPackageJson = {
122
+ dependencies?: Record<string, string>;
123
+ devDependencies?: Record<string, string>;
124
+ peerDependencies?: Record<string, string>;
125
+ optionalDependencies?: Record<string, string>;
126
+ scripts: Record<string, string> & { 'start:prod:local': string };
127
+ [key: string]: unknown;
128
+ };
129
+
130
+ function buildUpdatedPackageJson(
131
+ appPackageJson: TAppPackageJson,
132
+ options: TCliTaskOptions,
133
+ releaseVersion: string,
134
+ catalogs: Catalogs
135
+ ): TAppPackageJson {
136
+ const packageManager = getPreferredPackageManager(options);
137
+ // Flatten workspace: and catalog: specifiers into concrete versions across
138
+ // every dependency section — the scaffolded app is not part of any pnpm
139
+ // workspace and would otherwise fail to install.
140
+ const resolve = (deps?: Record<string, string>) =>
141
+ resolveDependencies(deps, releaseVersion, catalogs);
142
+ return {
143
+ ...appPackageJson,
144
+ version: '1.0.0',
145
+ // Given the package name is derived from the `projectDirectoryName`
146
+ // the latter needs to be sanitised to have a ensure a valid package name.
147
+ // The `projectDirectoryName` should not have restrictions (e.g. no `_`)
148
+ // as a result the package name potentially needs to be altered when derived.
149
+ name: slugify(options.projectDirectoryName),
150
+ description: '',
151
+ dependencies: resolve(appPackageJson.dependencies),
152
+ devDependencies: resolve(appPackageJson.devDependencies),
153
+ ...(appPackageJson.peerDependencies && {
154
+ peerDependencies: resolve(appPackageJson.peerDependencies),
155
+ }),
156
+ ...(appPackageJson.optionalDependencies && {
157
+ optionalDependencies: resolve(appPackageJson.optionalDependencies),
158
+ }),
159
+ scripts: {
160
+ ...appPackageJson.scripts,
161
+ 'start:prod:local': appPackageJson.scripts['start:prod:local'].replace(
162
+ 'yarn',
163
+ packageManager
164
+ ),
165
+ },
166
+ };
167
+ }
25
168
 
26
169
  function updatePackageJson(
27
170
  options: TCliTaskOptions,
@@ -37,33 +180,13 @@ function updatePackageJson(
37
180
  const appPackageJson = JSON.parse(
38
181
  fs.readFileSync(packageJsonPath, { encoding: 'utf8' })
39
182
  );
40
- const packageManager = getPreferredPackageManager(options);
41
-
42
- const updatedAppPackageJson = Object.assign({}, appPackageJson, {
43
- version: '1.0.0',
44
- // Given the package name is derived from the `projectDirectoryName`
45
- // the latter needs to be sanitised to have a ensure a valid package name.
46
- // The `projectDirectoryName` should not have restrictions (e.g. no `_`)
47
- // as a result the package name potentially needs to be altered when derived.
48
- name: slugify(options.projectDirectoryName),
49
- description: '',
50
- // Replace the package versions with the `workspace:` syntax to the real version.
51
- dependencies: replaceApplicationKitPackageVersionWith(
52
- releaseVersion,
53
- appPackageJson.dependencies
54
- ),
55
- devDependencies: replaceApplicationKitPackageVersionWith(
56
- releaseVersion,
57
- appPackageJson.devDependencies
58
- ),
59
- scripts: {
60
- ...appPackageJson.scripts,
61
- 'start:prod:local': appPackageJson.scripts[
62
- 'start:prod:local'
63
- ].replace('yarn', packageManager),
64
- },
65
- });
66
-
183
+ const catalogs = loadCatalogsFromClone(options.clonedRepositoryPath);
184
+ const updatedAppPackageJson = buildUpdatedPackageJson(
185
+ appPackageJson,
186
+ options,
187
+ releaseVersion,
188
+ catalogs
189
+ );
67
190
  fs.writeFileSync(
68
191
  packageJsonPath,
69
192
  JSON.stringify(updatedAppPackageJson, null, 2) + os.EOL,
package/src/types.ts CHANGED
@@ -26,6 +26,10 @@ export type TCliTaskOptions = {
26
26
  projectDirectoryPath: string;
27
27
  templateName: TCliCommandOptions['template'];
28
28
  tagOrBranchVersion: string;
29
+ // Absolute path to the temporary directory where the app-kit repo is
30
+ // cloned by `downloadTemplate`. Subsequent tasks read pnpm-workspace.yaml
31
+ // from here to resolve catalog references in the scaffolded package.json.
32
+ clonedRepositoryPath: string;
29
33
  entryPointUriPath?: string;
30
34
  initialProjectKey: string;
31
35
  cloudIdentifier: string;