@public-ui/kolibri-cli 4.0.0-rc.3 → 4.0.0-rc.4

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.
@@ -94,7 +94,6 @@ Source folder to migrate: ${baseDir}
94
94
  if (options.testTasks) {
95
95
  runner.registerTasks(test_1.testTasks);
96
96
  }
97
- let version = options.overwriteCurrentVersion;
98
97
  /**
99
98
  * Creates a replacer function for the package.json file.
100
99
  * @param {string} version Version to set
@@ -111,45 +110,44 @@ Source folder to migrate: ${baseDir}
111
110
  /**
112
111
  * Sets the version of the @public-ui/* packages in the package.json file.
113
112
  * @param {string} version Version to set
114
- * @param {Function} cb Callback function
115
113
  */
116
- function setVersionOfPublicUiPackages(version, cb) {
114
+ function setVersionOfPublicUiPackages(version) {
117
115
  let packageJson = (0, reuse_1.getContentOfProjectPkgJson)();
118
116
  packageJson = packageJson.replace(/"(@public-ui\/[^"]+)":\s*"(.*)"/g, createVersionReplacer(version));
119
117
  fs_1.default.writeFileSync(path_1.default.resolve(process.cwd(), 'package.json'), packageJson);
120
118
  runner.setProjectVersion(version);
121
119
  console.log(`- Update @public-ui/* to version ${version}`);
122
- (0, child_process_1.exec)((0, reuse_1.getPackageManagerCommand)('install'), (err) => {
123
- if (err) {
124
- console.error(`exec error: ${err.message}`);
125
- return;
126
- }
127
- cb();
128
- });
129
120
  }
130
121
  /**
131
- * Runs the task runner in a loop until all tasks are completed.
122
+ * Runs the task runner in batch mode with collected version steps.
132
123
  */
133
- function runLoop() {
124
+ async function runMigrationBatch() {
125
+ // Set execution mode to batch - tasks don't install immediately
126
+ runner.setExecutionMode('batch');
127
+ console.log(`\nStarting migration in batch mode...`);
128
+ // Start version is the current project version (from package.json or --overwrite-current-version)
129
+ const startVersion = options.overwriteCurrentVersion;
130
+ // Target version is --overwrite-target-version (CLI version = migration target)
131
+ const targetVersion = options.overwriteTargetVersion;
132
+ console.log(`Migration path: ${startVersion} → ${targetVersion}`);
133
+ // Run all tasks (they transform the code, not the dependencies)
134
134
  runner.run();
135
- if (version !== runner.getPendingMinVersion()) {
136
- // Tasks
137
- version = runner.getPendingMinVersion();
138
- setVersionOfPublicUiPackages(version, runLoop);
139
- }
140
- else if (semver_1.default.lt(version, options.overwriteTargetVersion)) {
141
- // CLI
142
- version = options.overwriteTargetVersion;
143
- setVersionOfPublicUiPackages(version, finish);
144
- }
145
- else if (semver_1.default.lt(version, options.overwriteCurrentVersion)) {
146
- // Components
147
- version = options.overwriteCurrentVersion;
148
- setVersionOfPublicUiPackages(version, finish);
149
- }
150
- else {
151
- finish();
152
- }
135
+ // Write final target version to package.json (only once)
136
+ setVersionOfPublicUiPackages(targetVersion);
137
+ // Install only once at the end
138
+ console.log(`\nInstalling dependencies once...`);
139
+ await new Promise((resolve, reject) => {
140
+ (0, child_process_1.exec)((0, reuse_1.getPackageManagerCommand)('install'), (err) => {
141
+ if (err) {
142
+ console.error(`exec error: ${err.message}`);
143
+ reject(err);
144
+ return;
145
+ }
146
+ resolve();
147
+ });
148
+ });
149
+ console.log(`Dependencies installed successfully.`);
150
+ finish();
153
151
  }
154
152
  /**
155
153
  * Prints the status of the task runner and the modified files.
@@ -223,7 +221,11 @@ If something is wrong, the migration can be reverted with ${chalk_1.default.ital
223
221
  const status = runner.getStatus();
224
222
  console.log(`
225
223
  Execute ${status.total} registered tasks...`);
226
- runLoop();
224
+ // Use optimized batch mode for single-pass installation
225
+ runMigrationBatch().catch((error) => {
226
+ console.error('Migration failed:', error);
227
+ process.exit(1);
228
+ });
227
229
  });
228
230
  });
229
231
  }
@@ -14,6 +14,8 @@ class AbstractTask {
14
14
  versionRange;
15
15
  taskDependencies;
16
16
  status = 'pending';
17
+ executionMode = 'immediate';
18
+ pendingExecutables = [];
17
19
  static instances = new Map();
18
20
  description;
19
21
  constructor(identifier, title, extensions, versionRange, taskDependencies = [], options = {}) {
@@ -49,5 +51,17 @@ class AbstractTask {
49
51
  getVersionRange() {
50
52
  return this.versionRange;
51
53
  }
54
+ setExecutionMode(mode) {
55
+ this.executionMode = mode;
56
+ }
57
+ getExecutionMode() {
58
+ return this.executionMode;
59
+ }
60
+ getPendingExecutables() {
61
+ return this.pendingExecutables;
62
+ }
63
+ clearPendingExecutables() {
64
+ this.pendingExecutables = [];
65
+ }
52
66
  }
53
67
  exports.AbstractTask = AbstractTask;
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.TaskRunner = void 0;
7
7
  const chalk_1 = __importDefault(require("chalk"));
8
+ const child_process_1 = require("child_process");
8
9
  const fs_1 = __importDefault(require("fs"));
9
10
  const path_1 = __importDefault(require("path"));
10
11
  const semver_1 = __importDefault(require("semver"));
@@ -35,6 +36,8 @@ class TaskRunner {
35
36
  baseDir = '/';
36
37
  cliVersion = '0.0.0';
37
38
  projectVersion = '0.0.0';
39
+ executionMode = 'immediate';
40
+ aggregatedCommands = new Map(); // taskId -> commands
38
41
  config = {
39
42
  migrate: {
40
43
  tasks: {},
@@ -67,6 +70,12 @@ class TaskRunner {
67
70
  this.projectVersion = version;
68
71
  }
69
72
  }
73
+ setExecutionMode(mode) {
74
+ this.executionMode = mode;
75
+ this.tasks.forEach((task) => {
76
+ task.setExecutionMode(mode);
77
+ });
78
+ }
70
79
  setConfig(config) {
71
80
  if (config.migrate?.tasks) {
72
81
  this.config.migrate.tasks = {
@@ -119,6 +128,10 @@ class TaskRunner {
119
128
  this.registerTask(task);
120
129
  }
121
130
  task.run(this.baseDir);
131
+ // Collect commands if in batch mode
132
+ if (this.executionMode === 'batch') {
133
+ this.aggregateCommandsFromTask(task);
134
+ }
122
135
  task.setStatus('done');
123
136
  }
124
137
  }
@@ -135,6 +148,7 @@ class TaskRunner {
135
148
  }
136
149
  run() {
137
150
  this.completedTasks = 0;
151
+ this.aggregatedCommands.clear();
138
152
  displayProgressBar(0, this.tasks.size);
139
153
  this.tasks.forEach((task) => {
140
154
  this.dependentTaskRun(task, task.getTaskDependencies());
@@ -143,6 +157,42 @@ class TaskRunner {
143
157
  if (this.tasks.size > 0) {
144
158
  console.log(); // New line after progress bar
145
159
  }
160
+ // If in batch mode, collect and execute all commands at the end
161
+ if (this.executionMode === 'batch') {
162
+ this.executeAggregatedCommands();
163
+ }
164
+ }
165
+ aggregateCommandsFromTask(task) {
166
+ // HandleDependencyTask has prepareExecutables method
167
+ if ('prepareExecutables' in task && typeof task.prepareExecutables === 'function') {
168
+ const taskWithPrepare = task;
169
+ const commands = taskWithPrepare.prepareExecutables();
170
+ if (commands.length > 0) {
171
+ this.aggregatedCommands.set(task.getIdentifier(), commands);
172
+ }
173
+ }
174
+ }
175
+ executeAggregatedCommands() {
176
+ const allCommands = [];
177
+ this.aggregatedCommands.forEach((commands) => {
178
+ allCommands.push(...commands);
179
+ });
180
+ if (allCommands.length === 0) {
181
+ return;
182
+ }
183
+ console.log('\nExecuting aggregated dependency commands...');
184
+ allCommands.forEach((command) => {
185
+ try {
186
+ console.log(` Running: ${command}`);
187
+ (0, child_process_1.execSync)(command, {
188
+ encoding: 'utf8',
189
+ stdio: 'inherit',
190
+ });
191
+ }
192
+ catch (error) {
193
+ console.warn(`Warning: Failed to execute command: ${command}`, error);
194
+ }
195
+ });
146
196
  }
147
197
  getPendingMinVersion() {
148
198
  let version = this.cliVersion;
@@ -24,26 +24,39 @@ class HandleDependencyTask extends abstract_task_1.AbstractTask {
24
24
  }
25
25
  return this.instances.get(identifier);
26
26
  }
27
- run() {
27
+ /**
28
+ * Collect dependency commands to be executed in batch mode.
29
+ * Does NOT execute immediately - returns commands for aggregation.
30
+ */
31
+ prepareExecutables() {
32
+ const commands = [];
28
33
  if (Object.keys(this.dependencies ?? {}).length > 0) {
29
34
  let command = `${(0, reuse_1.getPackageManagerCommand)(this.command)}`;
30
35
  Object.keys(this.dependencies ?? {}).forEach((dependency) => {
31
36
  command += ` ${dependency}@${this.dependencies[dependency]}`;
32
37
  });
33
- try {
34
- (0, child_process_1.execSync)(command, {
35
- encoding: 'utf8',
36
- });
37
- }
38
- catch (error) {
39
- console.warn(error);
40
- }
38
+ commands.push(command);
41
39
  }
42
40
  if (Object.keys(this.devDependencies ?? {}).length > 0) {
43
41
  let command = `${(0, reuse_1.getPackageManagerCommand)(this.command)} -D`;
44
42
  Object.keys(this.devDependencies ?? {}).forEach((dependency) => {
45
43
  command += ` ${dependency}`;
46
44
  });
45
+ commands.push(command);
46
+ }
47
+ return commands;
48
+ }
49
+ run() {
50
+ // In batch mode, commands are collected and executed later
51
+ // This method is kept for backward compatibility but does nothing
52
+ // Actual execution happens in TaskRunner with aggregated commands
53
+ }
54
+ /**
55
+ * Execute collected commands immediately (used for backward compatibility).
56
+ */
57
+ executeImmediate() {
58
+ const commands = this.prepareExecutables();
59
+ commands.forEach((command) => {
47
60
  try {
48
61
  (0, child_process_1.execSync)(command, {
49
62
  encoding: 'utf8',
@@ -52,7 +65,7 @@ class HandleDependencyTask extends abstract_task_1.AbstractTask {
52
65
  catch (error) {
53
66
  console.warn(error);
54
67
  }
55
- }
68
+ });
56
69
  }
57
70
  }
58
71
  exports.HandleDependencyTask = HandleDependencyTask;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@public-ui/kolibri-cli",
3
- "version": "4.0.0-rc.3",
3
+ "version": "4.0.0-rc.4",
4
4
  "license": "EUPL-1.2",
5
5
  "homepage": "https://public-ui.github.io",
6
6
  "repository": {
@@ -30,13 +30,12 @@
30
30
  "prettier-plugin-organize-imports": "4.3.0",
31
31
  "semver": "7.7.3",
32
32
  "typed-bem": "1.0.2",
33
- "@public-ui/components": "4.0.0-rc.3"
33
+ "@public-ui/components": "4.0.0-rc.4"
34
34
  },
35
35
  "devDependencies": {
36
36
  "@types/node": "24.10.4",
37
37
  "@typescript-eslint/eslint-plugin": "7.18.0",
38
38
  "@typescript-eslint/parser": "7.18.0",
39
- "cpy-cli": "6.0.0",
40
39
  "cross-env": "10.1.0",
41
40
  "eslint": "8.57.1",
42
41
  "eslint-config-prettier": "9.1.2",
@@ -47,7 +46,6 @@
47
46
  "knip": "5.80.0",
48
47
  "mocha": "11.7.5",
49
48
  "nodemon": "3.1.11",
50
- "rimraf": "6.1.2",
51
49
  "ts-node": "10.9.2",
52
50
  "typescript": "5.9.3"
53
51
  },
@@ -59,14 +57,12 @@
59
57
  ],
60
58
  "scripts": {
61
59
  "build": "tsc",
62
- "reset": "pnpm i @public-ui/components@1.1.7",
63
60
  "format": "prettier -c src",
64
61
  "lint": "pnpm lint:eslint && pnpm lint:tsc",
65
62
  "lint:eslint": "eslint src",
66
63
  "lint:tsc": "tsc --noemit",
67
64
  "pretest:unit": "pnpm build",
68
- "restart": "pnpm reset && pnpm start",
69
- "start": "rimraf test && cpy \"../../samples/react/src/components\" test/src && cpy \"../../samples/react/public/*.html\" test/ && ts-node src/index.ts migrate --ignore-uncommitted-changes --test-tasks test",
65
+ "start": "ts-node src/index.ts migrate --ignore-uncommitted-changes --overwrite-current-version=2.2.19-rc.0 --overwrite-target-version=4.0.0 --test-tasks ../../../test-migration",
70
66
  "test:unit": "cross-env TS_NODE_PROJECT=tsconfig.test.json mocha --require ts-node/register test/**/*.ts --no-experimental-strip-types",
71
67
  "unused": "knip",
72
68
  "watch": "nodemon --ignore package.json src/index.ts migrate --ignore-uncommitted-changes --test-tasks test"