@public-ui/visual-tests 1.7.0-rc.7 → 1.7.0-rc.8
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/README.md +144 -23
- package/package.json +12 -17
- package/src/index.ts +33 -0
- package/src/migrate/index.ts +127 -0
- package/src/migrate/runner/abstract-task.ts +64 -0
- package/src/migrate/runner/task-runner.ts +163 -0
- package/src/migrate/runner/tasks/common/GenericRenamePropertyTask.ts +85 -0
- package/src/migrate/runner/tasks/common/LabelExpertSlot.ts +96 -0
- package/src/migrate/runner/tasks/common/RemovePropertyNameTask.ts +104 -0
- package/src/migrate/runner/tasks/common/RenamePropertyNameTask.ts +31 -0
- package/src/migrate/runner/tasks/test/index.ts +16 -0
- package/src/migrate/runner/tasks/test/test-dummy.ts +20 -0
- package/src/migrate/runner/tasks/test/test-version-1.3.ts +7 -0
- package/src/migrate/runner/tasks/test/test-version-current.ts +7 -0
- package/src/migrate/runner/tasks/test/test-version-next-2.ts +7 -0
- package/src/migrate/runner/tasks/test/test-version-next-3.ts +7 -0
- package/src/migrate/runner/tasks/test/test-version-zero.ts +7 -0
- package/src/migrate/runner/tasks/v1/abbr.ts +3 -0
- package/src/migrate/runner/tasks/v1/accordion.ts +3 -0
- package/src/migrate/runner/tasks/v1/badge.ts +6 -0
- package/src/migrate/runner/tasks/v1/breadcrumb.ts +3 -0
- package/src/migrate/runner/tasks/v1/button-link.ts +6 -0
- package/src/migrate/runner/tasks/v1/button.ts +8 -0
- package/src/migrate/runner/tasks/v1/card.ts +4 -0
- package/src/migrate/runner/tasks/v1/details.ts +3 -0
- package/src/migrate/runner/tasks/v1/icon.ts +5 -0
- package/src/migrate/runner/tasks/v1/index.ts +151 -0
- package/src/migrate/runner/tasks/v1/input-checkbox.ts +3 -0
- package/src/migrate/runner/tasks/v1/input-color.ts +3 -0
- package/src/migrate/runner/tasks/v1/input-date.ts +3 -0
- package/src/migrate/runner/tasks/v1/input-email.ts +3 -0
- package/src/migrate/runner/tasks/v1/input-number.ts +4 -0
- package/src/migrate/runner/tasks/v1/input-radio.ts +3 -0
- package/src/migrate/runner/tasks/v1/input-range.ts +3 -0
- package/src/migrate/runner/tasks/v1/input-text.ts +3 -0
- package/src/migrate/runner/tasks/v1/link-button.ts +15 -0
- package/src/migrate/runner/tasks/v1/link-group.ts +7 -0
- package/src/migrate/runner/tasks/v1/link.ts +15 -0
- package/src/migrate/runner/tasks/v1/logo.ts +3 -0
- package/src/migrate/runner/tasks/v1/modal.ts +3 -0
- package/src/migrate/runner/tasks/v1/nav.ts +7 -0
- package/src/migrate/runner/tasks/v1/pagination.ts +3 -0
- package/src/migrate/runner/tasks/v1/progress.ts +3 -0
- package/src/migrate/runner/tasks/v1/quote.ts +3 -0
- package/src/migrate/runner/tasks/v1/select.ts +4 -0
- package/src/migrate/runner/tasks/v1/skip-nav.ts +3 -0
- package/src/migrate/runner/tasks/v1/span.ts +3 -0
- package/src/migrate/runner/tasks/v1/split-button.ts +3 -0
- package/src/migrate/runner/tasks/v1/table.ts +3 -0
- package/src/migrate/runner/tasks/v1/tabs.ts +4 -0
- package/src/migrate/runner/tasks/v1/toast.ts +3 -0
- package/src/migrate/runner/tasks/v1/version.ts +3 -0
- package/src/migrate/runner/types.ts +2 -0
- package/src/migrate/shares/reuse.ts +182 -0
- package/src/migrate/types.ts +2 -0
- package/src/types.ts +23 -0
- package/dist/index.js +0 -43
- package/kolibri-visual-test.sh +0 -3
- package/playwright.config.ts +0 -59
- package/tests/theme-snapshots.spec.ts +0 -46
- package/tsconfig.json +0 -22
package/README.md
CHANGED
|
@@ -1,47 +1,168 @@
|
|
|
1
|
-
# KoliBri -
|
|
1
|
+
# KoliBri - CLI-Tools
|
|
2
2
|
|
|
3
3
|
## Motivation
|
|
4
4
|
|
|
5
|
-
The `KoliBri`
|
|
6
|
-
It takes screenshots of every component defined in the [React Sample App](https://github.com/public-ui/kolibri/tree/develop/packages/samples/react) with the theme applied and compares them to their references.
|
|
5
|
+
The `KoliBri` CLI-Tools are a collection of tools to support the development with `KoliBri` components.
|
|
7
6
|
|
|
8
7
|
## Installation
|
|
9
8
|
|
|
10
|
-
You can install the `KoliBri`
|
|
9
|
+
You can install the `KoliBri` CLI-Tools with `npm`, `pnpm` or `yarn`.
|
|
11
10
|
|
|
12
11
|
```bash
|
|
13
|
-
npm i -
|
|
14
|
-
pnpm i -
|
|
15
|
-
yarn add -
|
|
12
|
+
npm i -g @public-ui/kolibri-cli
|
|
13
|
+
pnpm i -g @public-ui/kolibri-cli
|
|
14
|
+
yarn add -g @public-ui/kolibri-cli
|
|
16
15
|
```
|
|
17
16
|
|
|
18
17
|
## Usage
|
|
19
18
|
|
|
20
|
-
|
|
19
|
+
The `KoliBri` CLI is intended to be executed in your project root directory. Use the `kolibri` command to start the CLI.
|
|
21
20
|
|
|
22
|
-
```
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
21
|
+
```bash
|
|
22
|
+
kolibri --help
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
```bash
|
|
26
|
+
,--. ,--. ,--. ,--. ,-----. ,--.
|
|
27
|
+
| .' / ,---. | | `--' | |) /_ ,--.--. `--'
|
|
28
|
+
| . ' | .-. | | | ,--. | .-. \ | .--' ,--.
|
|
29
|
+
| |\ \ | '-' | | | | | | '--' / | | | |
|
|
30
|
+
`--' `--´ `---´ `--' `--' `------´ `--' `--'
|
|
31
|
+
🚹 The accessible HTML-Standard | 👉 https://public-ui.github.io
|
|
32
|
+
|
|
33
|
+
Usage: kolibri [options] [command]
|
|
34
|
+
|
|
35
|
+
CLI for executing some helpful commands for KoliBri projects.
|
|
36
|
+
|
|
37
|
+
Options:
|
|
38
|
+
-V, --version output the version number
|
|
39
|
+
-h, --help display help for command
|
|
40
|
+
|
|
41
|
+
Commands:
|
|
42
|
+
migrate [options] <string> This command migrates KoliBri code to the current version.
|
|
43
|
+
help [command] display help for command
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Migrate
|
|
47
|
+
|
|
48
|
+
With the `migrate` command you can migrate your project to the latest version of `KoliBri`.
|
|
49
|
+
|
|
50
|
+
Actually the following migrations are available:
|
|
51
|
+
|
|
52
|
+
- Component renaming ✓
|
|
53
|
+
- Component removal ⏰
|
|
54
|
+
- Property renaming ✓
|
|
55
|
+
- Property removal ✓
|
|
56
|
+
- Property type change ⏰
|
|
57
|
+
- Logic refactoring ⏰
|
|
58
|
+
- Expert-Slot refactoring ⏰
|
|
59
|
+
- `.vscode/settings.json` add IntelliSense for HTML ⏰
|
|
60
|
+
- `.gitignore` exclude `.kolibri.migrate.json` ⏰
|
|
61
|
+
- `.tsconfig` add `@public-ui/components` to `types` array ⏰
|
|
62
|
+
|
|
63
|
+
#### How does it work?
|
|
64
|
+
|
|
65
|
+
1. The migration command will check your project for clear `git history` and the `installed version` of `KoliBri`. Now it loads all available migration tasks.
|
|
66
|
+
2. Tasks in the correct version range will be executed one by one. Otherwise they will be skipped.
|
|
67
|
+
3. After that the `package.json` will be updated with the new version of `KoliBri` and execute the `npm install` command.
|
|
68
|
+
4. If there are any pending tasks, the migration command will be executed again. Otherwise the migration is finished.
|
|
69
|
+
5. Now you can check the result and commit the changes.
|
|
70
|
+
|
|
71
|
+
> **Note:** You can reset the migration with `git reset --hard HEAD~1` or by discarding the affected files.
|
|
72
|
+
|
|
73
|
+
#### Help
|
|
74
|
+
|
|
75
|
+
```bash
|
|
76
|
+
kolibri migrate --help
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
#### Execute
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
kolibri migrate <path>
|
|
29
83
|
```
|
|
30
84
|
|
|
31
|
-
|
|
32
|
-
- `THEME_EXPERT` defines the name of the export within the the module. (e.g., `export const THEME_NAME = {/**/};`) Defaults to `default`.
|
|
85
|
+
#### Options
|
|
33
86
|
|
|
34
|
-
|
|
35
|
-
|
|
87
|
+
| Option | Description | Type | Default |
|
|
88
|
+
| ------------------------------ | ----------------------------------------- | :------------------: | :------: |
|
|
89
|
+
| `--ignore-uncommitted-changes` | Allows execution with uncommitted changes | boolean | false |
|
|
90
|
+
| `--remove-mode` | Prefix property name or delete property | `delete` \| `prefix` | `prefix` |
|
|
36
91
|
|
|
37
|
-
|
|
92
|
+
#### Configuration
|
|
38
93
|
|
|
39
|
-
|
|
94
|
+
You can configure the migration with the `.kolibri.config.json` file in your project root folder. This file will be created automatically after the first migration.
|
|
95
|
+
|
|
96
|
+
**Troubleshooting:** If you have problems with migration, you can exclude some tasks with the configuration by setting the `false` flag (see `kol-select`).
|
|
40
97
|
|
|
41
98
|
```json
|
|
42
99
|
{
|
|
43
|
-
"
|
|
44
|
-
"
|
|
100
|
+
"migrate": {
|
|
101
|
+
"tasks": {
|
|
102
|
+
"kol-abbr-rename-property-_title-to-_label": true,
|
|
103
|
+
"kol-accordion-rename-property-_heading-to-_label": true,
|
|
104
|
+
"kol-badge-rename-property-_icon-only-to-_hide-label": true,
|
|
105
|
+
"kol-badge-remove-property-_hide-label": true,
|
|
106
|
+
"kol-badge-remove-property-_icon-only": true,
|
|
107
|
+
"kol-breadcrumb-rename-property-_aria-label-to-_label": true,
|
|
108
|
+
"kol-button-link-remove-property-_aria-current": true,
|
|
109
|
+
"kol-button-link-remove-property-_aria-label": true,
|
|
110
|
+
"kol-button-link-rename-property-_icon-only-to-_hide-label": true,
|
|
111
|
+
"kol-button-remove-property-_aria-current": true,
|
|
112
|
+
"kol-button-remove-property-_aria-label": true,
|
|
113
|
+
"kol-button-rename-property-_icon-only-to-_hide-label": true,
|
|
114
|
+
"kol-card-rename-property-_heading-to-_label": true,
|
|
115
|
+
"kol-card-rename-property-_headline-to-_label": true,
|
|
116
|
+
"kol-details-rename-property-_summary-to-_label": true,
|
|
117
|
+
"kol-icon-remove-property-_part": true,
|
|
118
|
+
"kol-icon-rename-property-_aria-label-to-_label": true,
|
|
119
|
+
"kol-checkbox-rename-property-_type-to-_variant": true,
|
|
120
|
+
"kol-color-rename-property-_list-to-_suggestions": true,
|
|
121
|
+
"kol-date-rename-property-_list-to-_suggestions": true,
|
|
122
|
+
"kol-input-email-rename-property-_list-to-_suggestions": true,
|
|
123
|
+
"kol-input-number-rename-property-_list-to-_suggestions": true,
|
|
124
|
+
"kol-input-radio-rename-property-_list-to-_options": true,
|
|
125
|
+
"kol-input-range-rename-property-_list-to-_suggestions": true,
|
|
126
|
+
"kol-input-text-rename-property-_list-to-_suggestions": true,
|
|
127
|
+
"kol-link-group-rename-property-_aria-label-to-_label": true,
|
|
128
|
+
"kol-link-group-remove-property-_ordered": true,
|
|
129
|
+
"kol-nav-rename-property-_aria-label-to-_label": true,
|
|
130
|
+
"kol-nav-rename-property-_compact-to-_hide-label": true,
|
|
131
|
+
"kol-nav-remove-property-_has-compact-button": true,
|
|
132
|
+
"kol-pagination-rename-property-_count-to-_total": true,
|
|
133
|
+
"kol-progress-rename-property-_type-to-_variant": true,
|
|
134
|
+
"kol-quote-rename-property-_caption-to-_label": true,
|
|
135
|
+
"kol-select-rename-property-_height-to-_rows": false,
|
|
136
|
+
"kol-select-rename-property-_list-to-_options": false,
|
|
137
|
+
"kol-skip-nav-rename-property-_aria-label-to-_label": true,
|
|
138
|
+
"kol-span-rename-property-_icon-only-to-_hide-label": true,
|
|
139
|
+
"kol-split-button-remove-property-_aria-label": true,
|
|
140
|
+
"kol-table-rename-property-_caption-to-_label": true,
|
|
141
|
+
"kol-tabs-rename-property-_aria-label-to-_label": true,
|
|
142
|
+
"kol-tabs-rename-property-_tab-align-to-_align": true,
|
|
143
|
+
"kol-toast-rename-property-_heading-to-_label": true,
|
|
144
|
+
"kol-version-rename-property-_version-to-_label": true
|
|
145
|
+
}
|
|
45
146
|
}
|
|
46
147
|
}
|
|
47
148
|
```
|
|
149
|
+
|
|
150
|
+
## Troubleshooting
|
|
151
|
+
|
|
152
|
+
If the migration failed, you can reset the migration with `git reset --hard HEAD~1`.
|
|
153
|
+
|
|
154
|
+
Use the configuration (`.kolibri.config.json`) to exclude some tasks.
|
|
155
|
+
|
|
156
|
+
If there are multiple obsolete properties that have been migrated to just one new property, the new property may appear multiple times in the tag. You can then decide which variant to use and remove all other variants accordingly.
|
|
157
|
+
|
|
158
|
+
Maybe it can help to prepare your code in the tricky places for migration.
|
|
159
|
+
|
|
160
|
+
Please give us feedback, if you have problems with the migration: [GitHub Issues](https://github.com/public-ui/kolibri/issues/new?assignees=&labels=useful+hint&projects=&template=7_feedback.md&title=%F0%9F%92%A1+CLI%3A+)
|
|
161
|
+
|
|
162
|
+
## Dry run
|
|
163
|
+
|
|
164
|
+
You have always the possibility of a dry run. Because before the migration will be executed, you need a clean git history of you project.
|
|
165
|
+
|
|
166
|
+
After the migration you can check the result with `git status` and `git diff`.
|
|
167
|
+
|
|
168
|
+
Is anything wrong, you can reset the migration with `git reset --hard HEAD~1` or by discarding the affected files.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@public-ui/visual-tests",
|
|
3
|
-
"version": "1.7.0-rc.
|
|
3
|
+
"version": "1.7.0-rc.8",
|
|
4
4
|
"license": "EUPL-1.2",
|
|
5
5
|
"homepage": "https://public-ui.github.io",
|
|
6
6
|
"repository": "https://github.com/public-ui/kolibri",
|
|
@@ -16,36 +16,31 @@
|
|
|
16
16
|
"sideEffects": false,
|
|
17
17
|
"description": "Provides utility to run visual regression tests for themes.",
|
|
18
18
|
"scripts": {
|
|
19
|
-
"
|
|
19
|
+
"depcheck": "depcheck --ignores=@public-ui/sample-react,http-server,tslib",
|
|
20
20
|
"format": "prettier --check src",
|
|
21
|
-
"lint": "eslint src
|
|
22
|
-
"unused": "knip"
|
|
23
|
-
"prepare": "npm run build"
|
|
21
|
+
"lint": "eslint src",
|
|
22
|
+
"unused": "knip"
|
|
24
23
|
},
|
|
25
24
|
"bin": {
|
|
26
|
-
"kolibri-visual-test": "
|
|
25
|
+
"kolibri-visual-test": "src/index.js"
|
|
27
26
|
},
|
|
28
27
|
"dependencies": {
|
|
29
28
|
"@playwright/test": "1.37.1",
|
|
30
|
-
"@public-ui/sample-react": "1.7.0-rc.
|
|
29
|
+
"@public-ui/sample-react": "1.7.0-rc.8",
|
|
31
30
|
"http-server": "14.1.1",
|
|
32
|
-
"portfinder": "1.0.32"
|
|
33
|
-
"tslib": "2.6.2",
|
|
34
|
-
"typescript": "5.2.2"
|
|
31
|
+
"portfinder": "1.0.32"
|
|
35
32
|
},
|
|
36
33
|
"devDependencies": {
|
|
37
|
-
"@
|
|
38
|
-
"
|
|
34
|
+
"@babel/eslint-parser": "7.22.15",
|
|
35
|
+
"depcheck": "1.4.6",
|
|
39
36
|
"eslint": "8.49.0",
|
|
40
37
|
"eslint-plugin-no-loops": "0.3.0",
|
|
41
38
|
"knip": "2.24.0",
|
|
42
|
-
"npm-check-updates": "16.14.0",
|
|
43
39
|
"prettier": "3.0.3"
|
|
44
40
|
},
|
|
45
41
|
"files": [
|
|
46
|
-
"
|
|
47
|
-
"
|
|
48
|
-
"tests"
|
|
49
|
-
"tsconfig.json"
|
|
42
|
+
"playwright.config.js",
|
|
43
|
+
"src",
|
|
44
|
+
"tests"
|
|
50
45
|
]
|
|
51
46
|
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import gradient from 'gradient-string';
|
|
5
|
+
|
|
6
|
+
import migrate from './migrate';
|
|
7
|
+
import { getVersionOfPublicUiKoliBriCli } from './migrate/shares/reuse';
|
|
8
|
+
|
|
9
|
+
const versionOfPublicUiKoliBriCli = getVersionOfPublicUiKoliBriCli();
|
|
10
|
+
|
|
11
|
+
const banner = gradient.atlas.multiline(
|
|
12
|
+
`
|
|
13
|
+
,--. ,--. ,--. ,--. ,-----. ,--.
|
|
14
|
+
| .' / ,---. | | \`--' | |) /_ ,--.--. \`--'
|
|
15
|
+
| . ' | .-. | | | ,--. | .-. \\ | .--' ,--.
|
|
16
|
+
| |\\ \\ | '-' | | | | | | '--' / | | | |
|
|
17
|
+
\`--' \`--´ \`---´ \`--' \`--' \`------´ \`--' \`--'
|
|
18
|
+
🚹 The accessible HTML-Standard | 👉 https://public-ui.github.io | ${versionOfPublicUiKoliBriCli}
|
|
19
|
+
`,
|
|
20
|
+
{
|
|
21
|
+
interpolation: 'hsv',
|
|
22
|
+
},
|
|
23
|
+
);
|
|
24
|
+
console.log(banner);
|
|
25
|
+
|
|
26
|
+
const program = new Command();
|
|
27
|
+
|
|
28
|
+
program.name('kolibri').description('CLI for executing some helpful commands for KoliBri projects.').version(versionOfPublicUiKoliBriCli);
|
|
29
|
+
|
|
30
|
+
// Add commands
|
|
31
|
+
migrate(program);
|
|
32
|
+
|
|
33
|
+
program.parse();
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { exec } from 'child_process';
|
|
2
|
+
import { Command, Option } from 'commander';
|
|
3
|
+
import fs from 'fs';
|
|
4
|
+
import path from 'path';
|
|
5
|
+
|
|
6
|
+
import { Configuration } from '../types';
|
|
7
|
+
import { TaskRunner } from './runner/task-runner';
|
|
8
|
+
import { testTasks } from './runner/tasks/test';
|
|
9
|
+
import { v1Tasks } from './runner/tasks/v1';
|
|
10
|
+
import {
|
|
11
|
+
getContentOfProjectPkgJson,
|
|
12
|
+
getPackageManagerInstallCommand,
|
|
13
|
+
getVersionOfPublicUiComponents,
|
|
14
|
+
getVersionOfPublicUiKoliBriCli,
|
|
15
|
+
logAndCreateError,
|
|
16
|
+
MODIFIED_FILES,
|
|
17
|
+
setRemoveMode,
|
|
18
|
+
} from './shares/reuse';
|
|
19
|
+
import { REMOVE_MODE, RemoveMode } from './types';
|
|
20
|
+
|
|
21
|
+
type MigrateOption = {
|
|
22
|
+
ignoreUncommittedChanges: boolean;
|
|
23
|
+
removeMode: RemoveMode;
|
|
24
|
+
testTasks: boolean;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* This function is used to register the migrate command.
|
|
29
|
+
* @param {Command} program The program object to register the command
|
|
30
|
+
*/
|
|
31
|
+
export default function (program: Command): void {
|
|
32
|
+
program
|
|
33
|
+
.command('migrate')
|
|
34
|
+
.description('This command migrates KoliBri code to the current version.')
|
|
35
|
+
.argument('[string]', 'Source code folder to migrate', 'src')
|
|
36
|
+
.addOption(new Option('--ignore-uncommitted-changes', 'Allows execution with uncommitted changes').default(false))
|
|
37
|
+
.addOption(new Option('--remove-mode <mode>', 'Prefix property name or delete property').choices(REMOVE_MODE).default('prefix'))
|
|
38
|
+
.addOption(new Option('--test-tasks', 'Run additional test tasks').default(false).hideHelp())
|
|
39
|
+
.action((baseDir: string, options: MigrateOption) => {
|
|
40
|
+
exec('git status --porcelain', (err, stdout) => {
|
|
41
|
+
if (err) {
|
|
42
|
+
console.error(`exec error: ${err.message}`);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
if (!options.ignoreUncommittedChanges && stdout) {
|
|
47
|
+
throw logAndCreateError('There are uncommitted changes');
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
setRemoveMode(options.removeMode);
|
|
51
|
+
|
|
52
|
+
const versionOfPublicUiComponents = getVersionOfPublicUiComponents();
|
|
53
|
+
const versionOfPublicUiKoliBriCli = getVersionOfPublicUiKoliBriCli();
|
|
54
|
+
|
|
55
|
+
console.log(`
|
|
56
|
+
Current version of @public-ui/components: ${versionOfPublicUiComponents}
|
|
57
|
+
Source folder to migrate: ${baseDir}
|
|
58
|
+
`);
|
|
59
|
+
|
|
60
|
+
const configFile = path.resolve(process.cwd(), '.kolibri.config.json');
|
|
61
|
+
let config: Configuration = {};
|
|
62
|
+
if (fs.existsSync(configFile)) {
|
|
63
|
+
try {
|
|
64
|
+
config = JSON.parse(fs.readFileSync(configFile, 'utf8')) as Configuration;
|
|
65
|
+
} catch (e) {
|
|
66
|
+
// ignore
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
const runner = new TaskRunner(baseDir, versionOfPublicUiKoliBriCli, versionOfPublicUiComponents, config);
|
|
71
|
+
runner.registerTasks(v1Tasks);
|
|
72
|
+
|
|
73
|
+
if (options.testTasks) {
|
|
74
|
+
runner.registerTasks(testTasks);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
let version = versionOfPublicUiComponents;
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* Runs the task runner in a loop until all tasks are completed.
|
|
81
|
+
*/
|
|
82
|
+
function runLoop() {
|
|
83
|
+
runner.run();
|
|
84
|
+
if (version !== runner.getPendingMinVersion()) {
|
|
85
|
+
version = runner.getPendingMinVersion();
|
|
86
|
+
let packageJson = getContentOfProjectPkgJson();
|
|
87
|
+
packageJson = packageJson.replace(/"(@public-ui\/[^"]+)":\s*".*"/g, `"$1": "${version}"`);
|
|
88
|
+
fs.writeFileSync(path.resolve(process.cwd(), 'package.json'), packageJson);
|
|
89
|
+
runner.setProjectVersion(version);
|
|
90
|
+
|
|
91
|
+
console.log(`- Update @public-ui/* to version ${version}`);
|
|
92
|
+
exec(getPackageManagerInstallCommand(), (err) => {
|
|
93
|
+
if (err) {
|
|
94
|
+
console.error(`exec error: ${err.message}`);
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
runLoop();
|
|
98
|
+
});
|
|
99
|
+
} else {
|
|
100
|
+
console.log(`
|
|
101
|
+
Status of all executed Tasks:`);
|
|
102
|
+
|
|
103
|
+
const status = runner.getStatus(true);
|
|
104
|
+
fs.writeFileSync(configFile, JSON.stringify(status.config, null, 2));
|
|
105
|
+
|
|
106
|
+
console.log(`
|
|
107
|
+
Modified files: ${MODIFIED_FILES.size}`);
|
|
108
|
+
MODIFIED_FILES.forEach((file) => {
|
|
109
|
+
console.log(`- ${file}`);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
console.log(`
|
|
113
|
+
After the code migration has gone through, the code formatting may no longer be as desired. Therefore, please reformat your code afterwards if necessary.
|
|
114
|
+
|
|
115
|
+
Afterwards, it may be that functions or themes in newer major versions have changed or are no longer included. This should be checked finally and corrected manually if necessary.
|
|
116
|
+
|
|
117
|
+
Is anything wrong, you can reset the migration with "git reset --hard HEAD~1" or by discarding the affected files. For more information read the troubleshooting section in the README.`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
const status = runner.getStatus();
|
|
122
|
+
console.log(`
|
|
123
|
+
Execute ${status.total} registered tasks...`);
|
|
124
|
+
runLoop();
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import semver from 'semver';
|
|
2
|
+
|
|
3
|
+
import { FILE_EXTENSIONS, FileExtension } from '../../types';
|
|
4
|
+
import { logAndCreateError } from '../shares/reuse';
|
|
5
|
+
import { TaskStatus } from './types';
|
|
6
|
+
|
|
7
|
+
export type TaskOptions = {
|
|
8
|
+
dependentTasks?: AbstractTask[];
|
|
9
|
+
description?: string;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export abstract class AbstractTask {
|
|
13
|
+
private status: TaskStatus = 'pending';
|
|
14
|
+
|
|
15
|
+
protected static readonly instances: Map<string, AbstractTask> = new Map();
|
|
16
|
+
|
|
17
|
+
protected readonly description?: string;
|
|
18
|
+
|
|
19
|
+
protected constructor(
|
|
20
|
+
protected readonly identifier: string,
|
|
21
|
+
protected readonly title: string,
|
|
22
|
+
protected readonly extensions: FileExtension[],
|
|
23
|
+
protected readonly versionRange: string,
|
|
24
|
+
protected readonly dependentTasks: AbstractTask[] = [],
|
|
25
|
+
options: TaskOptions = {},
|
|
26
|
+
) {
|
|
27
|
+
this.description = options.description;
|
|
28
|
+
this.extensions = this.extensions.filter((ext) => FILE_EXTENSIONS.includes(ext));
|
|
29
|
+
|
|
30
|
+
if (!semver.validRange(this.versionRange)) {
|
|
31
|
+
throw logAndCreateError(`[${this.identifier}] Invalid semver range version: ${this.versionRange}`);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public getDependentTasks(): AbstractTask[] {
|
|
36
|
+
return this.dependentTasks;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
public getDescription(): string | undefined {
|
|
40
|
+
return this.description;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
public getIdentifier(): string {
|
|
44
|
+
return this.identifier;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
public setStatus(status: TaskStatus): void {
|
|
48
|
+
this.status = status;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
public getStatus(): TaskStatus {
|
|
52
|
+
return this.status;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
public getTitle(): string {
|
|
56
|
+
return this.title;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
public getVersionRange(): string {
|
|
60
|
+
return this.versionRange;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
public abstract run(baseDir: string): void;
|
|
64
|
+
}
|
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import semver from 'semver';
|
|
5
|
+
|
|
6
|
+
import { Configuration } from '../../types';
|
|
7
|
+
import { logAndCreateError } from '../shares/reuse';
|
|
8
|
+
import { AbstractTask } from './abstract-task';
|
|
9
|
+
|
|
10
|
+
export class TaskRunner {
|
|
11
|
+
private readonly tasks: Map<string, AbstractTask> = new Map();
|
|
12
|
+
private baseDir: string = '/';
|
|
13
|
+
private cliVersion: string = '0.0.0';
|
|
14
|
+
private projectVersion: string = '0.0.0';
|
|
15
|
+
private readonly config: Configuration = {
|
|
16
|
+
migrate: {
|
|
17
|
+
tasks: {},
|
|
18
|
+
},
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
public constructor(baseDir: string, cliVersion: string, projectVersion: string, config: Configuration) {
|
|
22
|
+
this.setBaseDir(baseDir);
|
|
23
|
+
this.setCliVersion(cliVersion);
|
|
24
|
+
this.setProjectVersion(projectVersion);
|
|
25
|
+
this.setConfig(config);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
private setBaseDir(baseDir: string): void {
|
|
29
|
+
if (!fs.existsSync(path.resolve(process.cwd(), baseDir))) {
|
|
30
|
+
throw logAndCreateError(`Base directory "${baseDir}" does not exist`);
|
|
31
|
+
}
|
|
32
|
+
this.baseDir = baseDir;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
private setCliVersion(version: string): void {
|
|
36
|
+
if (semver.valid(version) === null) {
|
|
37
|
+
throw logAndCreateError(`Invalid CLI version: ${version}`);
|
|
38
|
+
}
|
|
39
|
+
this.cliVersion = version;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
public setProjectVersion(version: string): void {
|
|
43
|
+
if (semver.valid(version) === null) {
|
|
44
|
+
throw logAndCreateError(`Invalid project version: ${version}`);
|
|
45
|
+
}
|
|
46
|
+
if (this.projectVersion !== version) {
|
|
47
|
+
this.projectVersion = version;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
private setConfig(config: Configuration): void {
|
|
52
|
+
if (config.migrate?.tasks) {
|
|
53
|
+
this.config.migrate!.tasks = {
|
|
54
|
+
...this.config.migrate!.tasks,
|
|
55
|
+
...config.migrate?.tasks,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
public registerTasks(tasks: AbstractTask[]): void {
|
|
61
|
+
tasks.forEach((task) => {
|
|
62
|
+
if (
|
|
63
|
+
semver.gtr(this.projectVersion, task.getVersionRange(), {
|
|
64
|
+
includePrerelease: true,
|
|
65
|
+
})
|
|
66
|
+
) {
|
|
67
|
+
console.log(
|
|
68
|
+
`Task "${task.getTitle()}" will be excluded. The current version (${
|
|
69
|
+
this.projectVersion
|
|
70
|
+
}) is greater than the task version range (${task.getVersionRange()}).`,
|
|
71
|
+
);
|
|
72
|
+
this.config.migrate!.tasks[task.getIdentifier()] = false;
|
|
73
|
+
} else {
|
|
74
|
+
this.tasks.set(task.getIdentifier(), task);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
private registerTask(task: AbstractTask): void {
|
|
80
|
+
this.registerTasks([task]);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
private runTask(task: AbstractTask): void {
|
|
84
|
+
if (this.config.migrate?.tasks[task.getIdentifier()] === false) {
|
|
85
|
+
task.setStatus('skipped');
|
|
86
|
+
} else {
|
|
87
|
+
this.config.migrate!.tasks[task.getIdentifier()] = true;
|
|
88
|
+
if (
|
|
89
|
+
task.getStatus() === 'pending' &&
|
|
90
|
+
semver.satisfies(this.projectVersion, task.getVersionRange(), {
|
|
91
|
+
includePrerelease: true,
|
|
92
|
+
})
|
|
93
|
+
) {
|
|
94
|
+
// task.setStatus('running'); only of the task is async
|
|
95
|
+
if (!this.tasks.has(task.getIdentifier())) {
|
|
96
|
+
this.registerTask(task);
|
|
97
|
+
}
|
|
98
|
+
task.run(this.baseDir);
|
|
99
|
+
task.setStatus('done');
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
private dependentTaskRun(task: AbstractTask, dependentTasks: AbstractTask[]) {
|
|
105
|
+
dependentTasks.forEach((dependentTask) => {
|
|
106
|
+
this.dependentTaskRun(dependentTask, dependentTask.getDependentTasks());
|
|
107
|
+
});
|
|
108
|
+
if (dependentTasks.every((dependentTask) => dependentTask.getStatus() === 'done')) {
|
|
109
|
+
this.runTask(task);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
public run(): void {
|
|
114
|
+
this.tasks.forEach((task) => {
|
|
115
|
+
this.dependentTaskRun(task, task.getDependentTasks());
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
public getPendingMinVersion(): string {
|
|
120
|
+
let version: string = this.cliVersion;
|
|
121
|
+
this.tasks.forEach((task) => {
|
|
122
|
+
if (task.getStatus() === 'pending') {
|
|
123
|
+
const minVersion = semver.minVersion(task.getVersionRange())?.raw ?? this.cliVersion;
|
|
124
|
+
if (semver.gt(version, minVersion)) {
|
|
125
|
+
version = minVersion;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
});
|
|
129
|
+
return version;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
public getStatus(outline = false): {
|
|
133
|
+
done: number;
|
|
134
|
+
pending: number;
|
|
135
|
+
total: number;
|
|
136
|
+
nextVersion: string | null;
|
|
137
|
+
config: Configuration;
|
|
138
|
+
} {
|
|
139
|
+
let done = 0;
|
|
140
|
+
let pending = 0;
|
|
141
|
+
this.tasks.forEach((task) => {
|
|
142
|
+
switch (task.getStatus()) {
|
|
143
|
+
case 'done':
|
|
144
|
+
done++;
|
|
145
|
+
break;
|
|
146
|
+
case 'pending':
|
|
147
|
+
pending++;
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
if (outline) {
|
|
151
|
+
const status = task.getStatus();
|
|
152
|
+
console.log(`- ${task.getTitle()}:`, status === 'done' ? chalk.green(status) : chalk.yellow(status));
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
return {
|
|
156
|
+
done: done,
|
|
157
|
+
pending: pending,
|
|
158
|
+
total: this.tasks.size,
|
|
159
|
+
nextVersion: this.getPendingMinVersion(),
|
|
160
|
+
config: this.config,
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
}
|