@public-ui/kolibri-cli 4.0.0-rc.2 → 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.
package/dist/migrate/index.js
CHANGED
|
@@ -64,10 +64,12 @@ Target version of @public-ui/*: ${options.overwriteTargetVersion}
|
|
|
64
64
|
Source folder to migrate: ${baseDir}
|
|
65
65
|
`);
|
|
66
66
|
if (!fs_1.default.existsSync(baseDir)) {
|
|
67
|
-
|
|
67
|
+
const absolutePath = path_1.default.resolve(process.cwd(), baseDir);
|
|
68
|
+
throw (0, reuse_1.logAndCreateError)(`The specified source folder "${absolutePath}" (${baseDir}) does not exist or is inaccessible. Please check the path and try again.`);
|
|
68
69
|
}
|
|
69
70
|
if (!(0, reuse_1.hasKoliBriTags)(baseDir)) {
|
|
70
|
-
|
|
71
|
+
const absolutePath = path_1.default.resolve(process.cwd(), baseDir);
|
|
72
|
+
console.log(chalk_1.default.yellow(`No KoliBri components (web or React) found under "${absolutePath}" (${baseDir}). Check the path or your task configuration.`));
|
|
71
73
|
}
|
|
72
74
|
if (!options.ignoreGreaterVersion && semver_1.default.lt(options.overwriteTargetVersion, options.overwriteCurrentVersion)) {
|
|
73
75
|
throw (0, reuse_1.logAndCreateError)('Your current version of @public-ui/components is greater than the version of @public-ui/kolibri-cli. Please update @public-ui/kolibri-cli or force the migration with --ignore-greater-version.');
|
|
@@ -92,7 +94,6 @@ Source folder to migrate: ${baseDir}
|
|
|
92
94
|
if (options.testTasks) {
|
|
93
95
|
runner.registerTasks(test_1.testTasks);
|
|
94
96
|
}
|
|
95
|
-
let version = options.overwriteCurrentVersion;
|
|
96
97
|
/**
|
|
97
98
|
* Creates a replacer function for the package.json file.
|
|
98
99
|
* @param {string} version Version to set
|
|
@@ -109,45 +110,44 @@ Source folder to migrate: ${baseDir}
|
|
|
109
110
|
/**
|
|
110
111
|
* Sets the version of the @public-ui/* packages in the package.json file.
|
|
111
112
|
* @param {string} version Version to set
|
|
112
|
-
* @param {Function} cb Callback function
|
|
113
113
|
*/
|
|
114
|
-
function setVersionOfPublicUiPackages(version
|
|
114
|
+
function setVersionOfPublicUiPackages(version) {
|
|
115
115
|
let packageJson = (0, reuse_1.getContentOfProjectPkgJson)();
|
|
116
116
|
packageJson = packageJson.replace(/"(@public-ui\/[^"]+)":\s*"(.*)"/g, createVersionReplacer(version));
|
|
117
117
|
fs_1.default.writeFileSync(path_1.default.resolve(process.cwd(), 'package.json'), packageJson);
|
|
118
118
|
runner.setProjectVersion(version);
|
|
119
119
|
console.log(`- Update @public-ui/* to version ${version}`);
|
|
120
|
-
(0, child_process_1.exec)((0, reuse_1.getPackageManagerCommand)('install'), (err) => {
|
|
121
|
-
if (err) {
|
|
122
|
-
console.error(`exec error: ${err.message}`);
|
|
123
|
-
return;
|
|
124
|
-
}
|
|
125
|
-
cb();
|
|
126
|
-
});
|
|
127
120
|
}
|
|
128
121
|
/**
|
|
129
|
-
* Runs the task runner in
|
|
122
|
+
* Runs the task runner in batch mode with collected version steps.
|
|
130
123
|
*/
|
|
131
|
-
function
|
|
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)
|
|
132
134
|
runner.run();
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
finish();
|
|
150
|
-
}
|
|
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();
|
|
151
151
|
}
|
|
152
152
|
/**
|
|
153
153
|
* Prints the status of the task runner and the modified files.
|
|
@@ -221,7 +221,11 @@ If something is wrong, the migration can be reverted with ${chalk_1.default.ital
|
|
|
221
221
|
const status = runner.getStatus();
|
|
222
222
|
console.log(`
|
|
223
223
|
Execute ${status.total} registered tasks...`);
|
|
224
|
-
|
|
224
|
+
// Use optimized batch mode for single-pass installation
|
|
225
|
+
runMigrationBatch().catch((error) => {
|
|
226
|
+
console.error('Migration failed:', error);
|
|
227
|
+
process.exit(1);
|
|
228
|
+
});
|
|
225
229
|
});
|
|
226
230
|
});
|
|
227
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,21 +5,45 @@ 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"));
|
|
11
12
|
const reuse_1 = require("../shares/reuse");
|
|
12
13
|
const MIN_VERSION_OF_PUBLIC_UI = '1.4.2';
|
|
14
|
+
/**
|
|
15
|
+
* Displays a progress bar in the console.
|
|
16
|
+
* @param {number} current Current progress
|
|
17
|
+
* @param {number} total Total items
|
|
18
|
+
* @param {string} title Optional title
|
|
19
|
+
*/
|
|
20
|
+
function displayProgressBar(current, total, title = '') {
|
|
21
|
+
const barLength = 30;
|
|
22
|
+
const percentage = total === 0 ? 0 : (current / total) * 100;
|
|
23
|
+
const filledLength = Math.round((barLength * current) / total);
|
|
24
|
+
const emptyLength = barLength - filledLength;
|
|
25
|
+
const bar = chalk_1.default.green('█'.repeat(filledLength)) + chalk_1.default.gray('░'.repeat(emptyLength));
|
|
26
|
+
const percentStr = percentage.toFixed(0).padStart(3, ' ');
|
|
27
|
+
// Bestimme die maximale Ziffernzahl des totals
|
|
28
|
+
const totalDigits = total.toString().length;
|
|
29
|
+
const currentStr = current.toString().padStart(totalDigits, ' ');
|
|
30
|
+
const taskStr = `${currentStr}/${total}`;
|
|
31
|
+
const titleStr = title ? ` ${title}` : '';
|
|
32
|
+
process.stdout.write(`\r${bar} ${percentStr}% [${taskStr}]${titleStr}`);
|
|
33
|
+
}
|
|
13
34
|
class TaskRunner {
|
|
14
35
|
tasks = new Map();
|
|
15
36
|
baseDir = '/';
|
|
16
37
|
cliVersion = '0.0.0';
|
|
17
38
|
projectVersion = '0.0.0';
|
|
39
|
+
executionMode = 'immediate';
|
|
40
|
+
aggregatedCommands = new Map(); // taskId -> commands
|
|
18
41
|
config = {
|
|
19
42
|
migrate: {
|
|
20
43
|
tasks: {},
|
|
21
44
|
},
|
|
22
45
|
};
|
|
46
|
+
completedTasks = 0;
|
|
23
47
|
constructor(baseDir, cliVersion, projectVersion, config) {
|
|
24
48
|
this.setBaseDir(baseDir);
|
|
25
49
|
this.setCliVersion(cliVersion);
|
|
@@ -46,6 +70,12 @@ class TaskRunner {
|
|
|
46
70
|
this.projectVersion = version;
|
|
47
71
|
}
|
|
48
72
|
}
|
|
73
|
+
setExecutionMode(mode) {
|
|
74
|
+
this.executionMode = mode;
|
|
75
|
+
this.tasks.forEach((task) => {
|
|
76
|
+
task.setExecutionMode(mode);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
49
79
|
setConfig(config) {
|
|
50
80
|
if (config.migrate?.tasks) {
|
|
51
81
|
this.config.migrate.tasks = {
|
|
@@ -86,15 +116,22 @@ class TaskRunner {
|
|
|
86
116
|
}
|
|
87
117
|
else {
|
|
88
118
|
this.config.migrate.tasks[task.getIdentifier()] = true;
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
119
|
+
const isProjectVersionGreater = semver_1.default.gtr(this.projectVersion, task.getVersionRange(), {
|
|
120
|
+
includePrerelease: true,
|
|
121
|
+
});
|
|
122
|
+
const isCliVersionLower = semver_1.default.ltr(this.cliVersion, task.getVersionRange(), {
|
|
123
|
+
includePrerelease: true,
|
|
124
|
+
});
|
|
125
|
+
if (task.getStatus() === 'pending' && !isProjectVersionGreater && !isCliVersionLower) {
|
|
93
126
|
// task.setStatus('running'); only of the task is async
|
|
94
127
|
if (!this.tasks.has(task.getIdentifier())) {
|
|
95
128
|
this.registerTask(task);
|
|
96
129
|
}
|
|
97
130
|
task.run(this.baseDir);
|
|
131
|
+
// Collect commands if in batch mode
|
|
132
|
+
if (this.executionMode === 'batch') {
|
|
133
|
+
this.aggregateCommandsFromTask(task);
|
|
134
|
+
}
|
|
98
135
|
task.setStatus('done');
|
|
99
136
|
}
|
|
100
137
|
}
|
|
@@ -103,14 +140,59 @@ class TaskRunner {
|
|
|
103
140
|
taskDependencies.forEach((dependentTask) => {
|
|
104
141
|
this.dependentTaskRun(dependentTask, dependentTask.getTaskDependencies());
|
|
105
142
|
});
|
|
106
|
-
if (taskDependencies.every((dependentTask) => dependentTask.getStatus() === 'done')) {
|
|
143
|
+
if (taskDependencies.length === 0 || taskDependencies.every((dependentTask) => dependentTask.getStatus() === 'done')) {
|
|
144
|
+
displayProgressBar(this.completedTasks, this.tasks.size, task.getTitle());
|
|
107
145
|
this.runTask(task);
|
|
146
|
+
this.completedTasks++;
|
|
108
147
|
}
|
|
109
148
|
}
|
|
110
149
|
run() {
|
|
150
|
+
this.completedTasks = 0;
|
|
151
|
+
this.aggregatedCommands.clear();
|
|
152
|
+
displayProgressBar(0, this.tasks.size);
|
|
111
153
|
this.tasks.forEach((task) => {
|
|
112
154
|
this.dependentTaskRun(task, task.getTaskDependencies());
|
|
113
155
|
});
|
|
156
|
+
displayProgressBar(this.tasks.size, this.tasks.size);
|
|
157
|
+
if (this.tasks.size > 0) {
|
|
158
|
+
console.log(); // New line after progress bar
|
|
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
|
+
});
|
|
114
196
|
}
|
|
115
197
|
getPendingMinVersion() {
|
|
116
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
|
-
|
|
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
|
-
|
|
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;
|
|
@@ -47,7 +47,7 @@ function filterFilesByExt(dir, ext) {
|
|
|
47
47
|
let files = [];
|
|
48
48
|
const dirPath = path_1.default.resolve(process.cwd(), dir);
|
|
49
49
|
fs_1.default.readdirSync(dirPath).forEach((file) => {
|
|
50
|
-
const fullPath = path_1.default.resolve(
|
|
50
|
+
const fullPath = path_1.default.resolve(dirPath, file);
|
|
51
51
|
if (fs_1.default.lstatSync(fullPath).isDirectory()) {
|
|
52
52
|
files = files.concat(filterFilesByExt(fullPath, ext));
|
|
53
53
|
}
|
|
@@ -65,7 +65,8 @@ function filterFilesByExt(dir, ext) {
|
|
|
65
65
|
*/
|
|
66
66
|
function hasKoliBriTags(dir) {
|
|
67
67
|
const regexes = [types_1.WEB_TAG_REGEX, types_1.REACT_TAG_REGEX];
|
|
68
|
-
const
|
|
68
|
+
const dirPath = path_1.default.resolve(process.cwd(), dir);
|
|
69
|
+
const files = filterFilesByExt(dirPath, types_1.MARKUP_EXTENSIONS);
|
|
69
70
|
for (const file of files) {
|
|
70
71
|
let fd;
|
|
71
72
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@public-ui/kolibri-cli",
|
|
3
|
-
"version": "4.0.0-rc.
|
|
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.
|
|
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
|
-
"
|
|
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"
|