@vcmap/plugin-cli 2.1.11 → 2.1.12
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 +16 -0
- package/assets/.gitlab-ci.yml +1 -1
- package/assets/index.html +24 -22
- package/assets/index.js +20 -1
- package/assets/prettierignore +33 -0
- package/assets/tests/.eslintrc +6 -0
- package/assets/tests/sample.spec.js +15 -0
- package/assets/tests/setup.js +17 -0
- package/cli.js +8 -1
- package/package.json +10 -9
- package/src/create.js +71 -50
- package/src/packageJsonHelpers.js +72 -7
- package/src/serve.js +1 -0
- package/src/update.js +33 -7
package/README.md
CHANGED
|
@@ -291,6 +291,12 @@ configuration of the plugin as its first argument and the base URL (without the
|
|
|
291
291
|
from which the plugin was loaded as its second argument.
|
|
292
292
|
|
|
293
293
|
```typescript
|
|
294
|
+
declare type PluginConfigEditor = {
|
|
295
|
+
component: VueComponent;
|
|
296
|
+
collectionName?: string;
|
|
297
|
+
itemName?: string;
|
|
298
|
+
};
|
|
299
|
+
|
|
294
300
|
declare interface VcsPlugin<T extends Object, S extends Object> {
|
|
295
301
|
readonly name: string;
|
|
296
302
|
readonly version: string;
|
|
@@ -298,6 +304,8 @@ declare interface VcsPlugin<T extends Object, S extends Object> {
|
|
|
298
304
|
onVcsAppMounted(app: VcsUiApp): Promise<void>;
|
|
299
305
|
getState(): Promise<S>;
|
|
300
306
|
toJSON(): Promise<T>;
|
|
307
|
+
getDefaultOptions(): T;
|
|
308
|
+
getConfigEditors(): Array<PluginConfigEditor>;
|
|
301
309
|
destroy(): void;
|
|
302
310
|
}
|
|
303
311
|
|
|
@@ -307,6 +315,8 @@ declare function defaultExport<T extends Object, S extends Object>(
|
|
|
307
315
|
): VcsPlugin<T, S>;
|
|
308
316
|
```
|
|
309
317
|
|
|
318
|
+
> The function default export should not throw! Put exceptions in initialize instead.
|
|
319
|
+
|
|
310
320
|
A Simple JavaScript implementation of this interface can be seen below::
|
|
311
321
|
|
|
312
322
|
```javascript
|
|
@@ -330,9 +340,15 @@ export default function defaultExport(config, baseUrl) {
|
|
|
330
340
|
async getState() {
|
|
331
341
|
return {};
|
|
332
342
|
},
|
|
343
|
+
getDefaultOptions() {
|
|
344
|
+
return {};
|
|
345
|
+
},
|
|
333
346
|
async toJSON() {
|
|
334
347
|
return {};
|
|
335
348
|
},
|
|
349
|
+
getConfigEditors() {
|
|
350
|
+
return [];
|
|
351
|
+
},
|
|
336
352
|
destroy() {},
|
|
337
353
|
};
|
|
338
354
|
}
|
package/assets/.gitlab-ci.yml
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
default:
|
|
2
|
-
image: gitlab.virtualcitysystems.de:5050/vcsuite/devops/gitlabrunner/node:
|
|
2
|
+
image: gitlab.virtualcitysystems.de:5050/vcsuite/devops/gitlabrunner/node:18-bullseye
|
|
3
3
|
|
|
4
4
|
variables:
|
|
5
5
|
GIT_CLONE_PATH: $CI_BUILDS_DIR/$CI_PROJECT_PATH_SLUG/$CI_COMMIT_REF_SLUG
|
package/assets/index.html
CHANGED
|
@@ -1,48 +1,38 @@
|
|
|
1
1
|
<!DOCTYPE html>
|
|
2
2
|
<html class="vcs-ui" lang="en">
|
|
3
3
|
<head>
|
|
4
|
-
<
|
|
5
|
-
<meta
|
|
4
|
+
<title>VC Map</title>
|
|
5
|
+
<meta charset="utf-8">
|
|
6
|
+
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
|
6
7
|
<link
|
|
7
8
|
rel="icon"
|
|
8
9
|
type="image/png"
|
|
9
10
|
href="./assets/favicon-32.png"
|
|
10
11
|
sizes="32x32"
|
|
11
|
-
|
|
12
|
+
>
|
|
12
13
|
<link
|
|
13
14
|
rel="icon"
|
|
14
15
|
type="image/png"
|
|
15
16
|
href="./assets/favicon-128.png"
|
|
16
17
|
sizes="128x128"
|
|
17
|
-
|
|
18
|
+
>
|
|
18
19
|
<link
|
|
19
20
|
rel="icon"
|
|
20
21
|
type="image/png"
|
|
21
22
|
href="./assets/favicon-180.png"
|
|
22
23
|
sizes="180x180"
|
|
23
|
-
|
|
24
|
+
>
|
|
24
25
|
<link
|
|
25
26
|
rel="icon"
|
|
26
27
|
type="image/png"
|
|
27
28
|
href="./assets/favicon-192.png"
|
|
28
29
|
sizes="192x192"
|
|
29
|
-
|
|
30
|
-
<link rel="icon" type="image/svg+xml" href="./assets/favicon.svg"
|
|
30
|
+
>
|
|
31
|
+
<link rel="icon" type="image/svg+xml" href="./assets/favicon.svg">
|
|
31
32
|
<link
|
|
32
33
|
rel="stylesheet"
|
|
33
34
|
href="./assets/@mdi/font/css/materialdesignicons.min.css"
|
|
34
|
-
|
|
35
|
-
</head>
|
|
36
|
-
<body style="height: 100vh">
|
|
37
|
-
<noscript>
|
|
38
|
-
<strong>...</strong>
|
|
39
|
-
</noscript>
|
|
40
|
-
<div id="app">
|
|
41
|
-
<div id="loading-wrapper">
|
|
42
|
-
<div id="loading-text">LOADING</div>
|
|
43
|
-
<div id="loading-content"></div>
|
|
44
|
-
</div>
|
|
45
|
-
</div>
|
|
35
|
+
>
|
|
46
36
|
<style>
|
|
47
37
|
#loading-wrapper {
|
|
48
38
|
position: fixed;
|
|
@@ -57,7 +47,7 @@
|
|
|
57
47
|
position: absolute;
|
|
58
48
|
top: 50%;
|
|
59
49
|
left: 50%;
|
|
60
|
-
color:
|
|
50
|
+
color: grey;
|
|
61
51
|
width: 100px;
|
|
62
52
|
height: 30px;
|
|
63
53
|
margin: -7px 0 0 -45px;
|
|
@@ -78,8 +68,8 @@
|
|
|
78
68
|
|
|
79
69
|
#loading-content {
|
|
80
70
|
border: 3px solid transparent;
|
|
81
|
-
border-top-color:
|
|
82
|
-
border-bottom-color:
|
|
71
|
+
border-top-color: grey;
|
|
72
|
+
border-bottom-color: grey;
|
|
83
73
|
border-radius: 50%;
|
|
84
74
|
-webkit-animation: loader 2s linear infinite;
|
|
85
75
|
-moz-animation: loader 2s linear infinite;
|
|
@@ -101,8 +91,20 @@
|
|
|
101
91
|
}
|
|
102
92
|
}
|
|
103
93
|
</style>
|
|
94
|
+
</head>
|
|
95
|
+
<body style="height: 100vh">
|
|
96
|
+
<noscript>
|
|
97
|
+
<strong>...</strong>
|
|
98
|
+
</noscript>
|
|
99
|
+
<div id="app">
|
|
100
|
+
<div id="loading-wrapper">
|
|
101
|
+
<div id="loading-text">LOADING</div>
|
|
102
|
+
<div id="loading-content"></div>
|
|
103
|
+
</div>
|
|
104
|
+
</div>
|
|
104
105
|
<script type="module">
|
|
105
106
|
import { initAppFromAppConfig } from '@vcmap/ui';
|
|
107
|
+
|
|
106
108
|
initAppFromAppConfig('#app', 'app.config.json');
|
|
107
109
|
</script>
|
|
108
110
|
</body>
|
package/assets/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { version,
|
|
1
|
+
import { name, version, mapVersion } from '../package.json';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* @typedef {Object} PluginState
|
|
@@ -6,6 +6,7 @@ import { version, name } from '../package.json';
|
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
+
* Implementation of VcsPlugin interface. This function should not throw! Put exceptions in initialize instead.
|
|
9
10
|
* @param {T} config - the configuration of this plugin instance, passed in from the app.
|
|
10
11
|
* @param {string} baseUrl - the absolute URL from which the plugin was loaded (without filename, ending on /)
|
|
11
12
|
* @returns {import("@vcmap/ui/src/vcsUiApp").VcsPlugin<T, PluginState>}
|
|
@@ -21,6 +22,9 @@ export default function plugin(config, baseUrl) {
|
|
|
21
22
|
get version() {
|
|
22
23
|
return version;
|
|
23
24
|
},
|
|
25
|
+
get mapVersion() {
|
|
26
|
+
return mapVersion;
|
|
27
|
+
},
|
|
24
28
|
/**
|
|
25
29
|
* @param {import("@vcmap/ui").VcsUiApp} vcsUiApp
|
|
26
30
|
* @param {PluginState=} state
|
|
@@ -46,6 +50,14 @@ export default function plugin(config, baseUrl) {
|
|
|
46
50
|
);
|
|
47
51
|
},
|
|
48
52
|
/**
|
|
53
|
+
* should return all default values of the configuration
|
|
54
|
+
* @returns {T}
|
|
55
|
+
*/
|
|
56
|
+
getDefaultOptions() {
|
|
57
|
+
return {};
|
|
58
|
+
},
|
|
59
|
+
/**
|
|
60
|
+
* should return the plugin's serialization excluding all default values
|
|
49
61
|
* @returns {T}
|
|
50
62
|
*/
|
|
51
63
|
toJSON() {
|
|
@@ -65,6 +77,13 @@ export default function plugin(config, baseUrl) {
|
|
|
65
77
|
prop: '*',
|
|
66
78
|
};
|
|
67
79
|
},
|
|
80
|
+
/**
|
|
81
|
+
* components for configuring the plugin and/ or custom items defined by the plugin
|
|
82
|
+
* @returns {Array<import("@vcmap/ui").PluginConfigEditor>}
|
|
83
|
+
*/
|
|
84
|
+
getConfigEditors() {
|
|
85
|
+
return [];
|
|
86
|
+
},
|
|
68
87
|
destroy() {
|
|
69
88
|
// eslint-disable-next-line no-console
|
|
70
89
|
console.log('hook to cleanup');
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
dist/
|
|
2
|
+
plugin-assets/
|
|
3
|
+
public/
|
|
4
|
+
test-report.xml
|
|
5
|
+
|
|
6
|
+
# local env files
|
|
7
|
+
.env.local
|
|
8
|
+
.env.*.local
|
|
9
|
+
|
|
10
|
+
# Log files
|
|
11
|
+
npm-debug.log*
|
|
12
|
+
yarn-debug.log*
|
|
13
|
+
yarn-error.log*
|
|
14
|
+
pnpm-debug.log*
|
|
15
|
+
|
|
16
|
+
# Editor directories and files
|
|
17
|
+
.idea
|
|
18
|
+
.vscode
|
|
19
|
+
*.suo
|
|
20
|
+
*.ntvs*
|
|
21
|
+
*.njsproj
|
|
22
|
+
*.sln
|
|
23
|
+
*.sw?
|
|
24
|
+
|
|
25
|
+
# test output
|
|
26
|
+
.nyc_output
|
|
27
|
+
coverage
|
|
28
|
+
|
|
29
|
+
# static output
|
|
30
|
+
docs
|
|
31
|
+
|
|
32
|
+
# index.html (prettier does not take modern html 5 rules that closing tags for void elements should be avoided)
|
|
33
|
+
assets/index.html
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { describe, it, expect, beforeAll } from 'vitest';
|
|
2
|
+
import plugin from '../src/index.js';
|
|
3
|
+
import { name } from '../package.json';
|
|
4
|
+
|
|
5
|
+
describe('sample test spec', () => {
|
|
6
|
+
describe('plugin name', () => {
|
|
7
|
+
let pluginInstance;
|
|
8
|
+
beforeAll(() => {
|
|
9
|
+
pluginInstance = plugin({}, 'localhost');
|
|
10
|
+
});
|
|
11
|
+
it('should return the plugin name from the package.json', () => {
|
|
12
|
+
expect(pluginInstance.name).to.equal(name);
|
|
13
|
+
});
|
|
14
|
+
});
|
|
15
|
+
});
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/* eslint-disable import/no-extraneous-dependencies, import/first */
|
|
2
|
+
import { vi } from 'vitest';
|
|
3
|
+
|
|
4
|
+
vi.hoisted(() => {
|
|
5
|
+
global.jest = vi;
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
import ResizeObserver from 'resize-observer-polyfill';
|
|
9
|
+
|
|
10
|
+
global.ResizeObserver = ResizeObserver;
|
|
11
|
+
|
|
12
|
+
import 'jest-canvas-mock';
|
|
13
|
+
import Vue from 'vue';
|
|
14
|
+
|
|
15
|
+
Vue.config.productionTip = false;
|
|
16
|
+
|
|
17
|
+
window.CESIUM_BASE_URL = '/node_modules/@vcmap-cesium/engine/Build/';
|
package/cli.js
CHANGED
|
@@ -42,6 +42,13 @@ program.command('buildStagingApp').defaultOptions().safeAction(buildStagingApp);
|
|
|
42
42
|
|
|
43
43
|
program.command('setup-map-ui').safeAction(setupMapUi);
|
|
44
44
|
|
|
45
|
-
program
|
|
45
|
+
program
|
|
46
|
+
.command('update')
|
|
47
|
+
.defaultOptions()
|
|
48
|
+
.option(
|
|
49
|
+
'--mapVersion [semver]',
|
|
50
|
+
'an optional semver range to update to, e.g. 5.0 (Default is latest)',
|
|
51
|
+
)
|
|
52
|
+
.safeAction(update);
|
|
46
53
|
|
|
47
54
|
program.parse(process.argv);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vcmap/plugin-cli",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.12",
|
|
4
4
|
"description": "A CLI to help develop and build plugins for the VC Map",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -31,18 +31,18 @@
|
|
|
31
31
|
"dependencies": {
|
|
32
32
|
"@vcmap/rollup-plugin-vcs-ol": "^1.0.2",
|
|
33
33
|
"@vcsuite/cli-logger": "^1.0.0",
|
|
34
|
+
"@vitejs/plugin-vue2": "^2.2.0",
|
|
34
35
|
"commander": "^10.0.1",
|
|
35
36
|
"express": "^4.18.2",
|
|
36
37
|
"prompts": "^2.4.2",
|
|
37
38
|
"sass": "1.32.13",
|
|
38
|
-
"semver": "^7.5.
|
|
39
|
+
"semver": "^7.5.4",
|
|
39
40
|
"tar": "^6.1.15",
|
|
40
|
-
"vite": "^4.
|
|
41
|
-
"@vitejs/plugin-vue2": "^2.2.0",
|
|
41
|
+
"vite": "^4.4.9",
|
|
42
42
|
"vue-template-compiler": "~2.7.14"
|
|
43
43
|
},
|
|
44
44
|
"peerDependencies": {
|
|
45
|
-
"@vcmap/ui": "^5.0.0
|
|
45
|
+
"@vcmap/ui": "^5.0.0",
|
|
46
46
|
"vue": "~2.7.14"
|
|
47
47
|
},
|
|
48
48
|
"peerDependenciesMeta": {
|
|
@@ -54,11 +54,12 @@
|
|
|
54
54
|
}
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
|
-
"@vcsuite/eslint-config": "^3.0.
|
|
57
|
+
"@vcsuite/eslint-config": "^3.0.5",
|
|
58
58
|
"eslint": "^8.38.0"
|
|
59
59
|
},
|
|
60
60
|
"eslintIgnore": [
|
|
61
|
-
"node_modules"
|
|
61
|
+
"node_modules",
|
|
62
|
+
"assets/tests"
|
|
62
63
|
],
|
|
63
64
|
"eslintConfig": {
|
|
64
65
|
"extends": "@vcsuite/eslint-config/node",
|
|
@@ -78,7 +79,7 @@
|
|
|
78
79
|
},
|
|
79
80
|
"prettier": "@vcsuite/eslint-config/prettier.js",
|
|
80
81
|
"engines": {
|
|
81
|
-
"node": "^
|
|
82
|
-
"npm": "^
|
|
82
|
+
"node": "^18.12.0",
|
|
83
|
+
"npm": "^9.0.0"
|
|
83
84
|
}
|
|
84
85
|
}
|
package/src/create.js
CHANGED
|
@@ -5,7 +5,7 @@ import semver from 'semver';
|
|
|
5
5
|
import tar from 'tar';
|
|
6
6
|
import { logger } from '@vcsuite/cli-logger';
|
|
7
7
|
import { LicenseType, writeLicense } from './licenses.js';
|
|
8
|
-
import { DepType, installDeps } from './packageJsonHelpers.js';
|
|
8
|
+
import { DepType, installDeps, setVcMapVersion } from './packageJsonHelpers.js';
|
|
9
9
|
import { updatePeerDependencies } from './update.js';
|
|
10
10
|
import { name, version, promiseExec, getDirname } from './pluginCliHelper.js';
|
|
11
11
|
|
|
@@ -23,6 +23,41 @@ import { name, version, promiseExec, getDirname } from './pluginCliHelper.js';
|
|
|
23
23
|
* @property {boolean} gitlabCi
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
|
+
/**
|
|
27
|
+
*
|
|
28
|
+
* @param {PluginTemplateOptions} options
|
|
29
|
+
* @returns {Object}
|
|
30
|
+
*/
|
|
31
|
+
function createPackageJson(options) {
|
|
32
|
+
return {
|
|
33
|
+
name: options.name,
|
|
34
|
+
version: options.version,
|
|
35
|
+
description: options.description,
|
|
36
|
+
type: 'module',
|
|
37
|
+
main: 'src/index.js',
|
|
38
|
+
scripts: Object.assign(
|
|
39
|
+
{ prepublishOnly: 'vcmplugin build' },
|
|
40
|
+
...options.scripts,
|
|
41
|
+
),
|
|
42
|
+
author: options.author,
|
|
43
|
+
license: options.license,
|
|
44
|
+
dependencies: {},
|
|
45
|
+
keywords: ['vcmap', 'plugin'],
|
|
46
|
+
files: [
|
|
47
|
+
'src/',
|
|
48
|
+
'dist/',
|
|
49
|
+
'plugin-assets/',
|
|
50
|
+
'LICENSE.md',
|
|
51
|
+
'README.md',
|
|
52
|
+
'CHANGELOG.md',
|
|
53
|
+
],
|
|
54
|
+
exports: {
|
|
55
|
+
'.': './src/index.js',
|
|
56
|
+
'./dist': './dist/index.js',
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
|
|
26
61
|
/**
|
|
27
62
|
* @param {string} pluginName
|
|
28
63
|
* @param {string} pluginPath
|
|
@@ -46,7 +81,7 @@ async function downloadAndExtractPluginTar(
|
|
|
46
81
|
const extractOptions = {
|
|
47
82
|
file: tarPath,
|
|
48
83
|
cwd: pluginPath,
|
|
49
|
-
strip:
|
|
84
|
+
strip: 4,
|
|
50
85
|
};
|
|
51
86
|
if (filter) {
|
|
52
87
|
extractOptions.filter = (entryPath) =>
|
|
@@ -65,20 +100,16 @@ async function downloadAndExtractPluginTar(
|
|
|
65
100
|
* @returns {Promise<void>}
|
|
66
101
|
*/
|
|
67
102
|
async function copyPluginTemplate(options, pluginPath) {
|
|
68
|
-
await downloadAndExtractPluginTar(
|
|
103
|
+
await downloadAndExtractPluginTar('@vcmap/ui', pluginPath, [
|
|
104
|
+
path.join('plugins', options.template),
|
|
105
|
+
]);
|
|
69
106
|
|
|
70
107
|
const pluginPackageJson = JSON.parse(
|
|
71
108
|
(
|
|
72
109
|
await fs.promises.readFile(path.join(pluginPath, 'package.json'))
|
|
73
110
|
).toString(),
|
|
74
111
|
);
|
|
75
|
-
const userPackageJson =
|
|
76
|
-
name: options.name,
|
|
77
|
-
version: options.version,
|
|
78
|
-
description: options.description,
|
|
79
|
-
author: options.author,
|
|
80
|
-
license: options.license,
|
|
81
|
-
};
|
|
112
|
+
const userPackageJson = createPackageJson(options);
|
|
82
113
|
const packageJson = { ...pluginPackageJson, ...userPackageJson };
|
|
83
114
|
if (options.repository) {
|
|
84
115
|
packageJson.repository = {
|
|
@@ -93,11 +124,10 @@ async function copyPluginTemplate(options, pluginPath) {
|
|
|
93
124
|
JSON.stringify(packageJson, null, 2),
|
|
94
125
|
);
|
|
95
126
|
|
|
96
|
-
const
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
);
|
|
127
|
+
const configPath = path.join(pluginPath, 'config.json');
|
|
128
|
+
const configJson = fs.existsSync(configPath)
|
|
129
|
+
? JSON.parse((await fs.promises.readFile(configPath)).toString())
|
|
130
|
+
: {};
|
|
101
131
|
configJson.name = options.name;
|
|
102
132
|
|
|
103
133
|
const writeConfigPromise = fs.promises.writeFile(
|
|
@@ -140,33 +170,7 @@ async function createPluginTemplate(options, pluginPath) {
|
|
|
140
170
|
options.scripts.push({ coverage: 'vitest run --coverage' });
|
|
141
171
|
}
|
|
142
172
|
|
|
143
|
-
const packageJson =
|
|
144
|
-
name: options.name,
|
|
145
|
-
version: options.version,
|
|
146
|
-
description: options.description,
|
|
147
|
-
type: 'module',
|
|
148
|
-
main: 'src/index.js',
|
|
149
|
-
scripts: Object.assign(
|
|
150
|
-
{ prepublishOnly: 'vcmplugin build' },
|
|
151
|
-
...options.scripts,
|
|
152
|
-
),
|
|
153
|
-
author: options.author,
|
|
154
|
-
license: options.license,
|
|
155
|
-
dependencies: {},
|
|
156
|
-
keywords: ['vcmap', 'plugin'],
|
|
157
|
-
files: [
|
|
158
|
-
'src/',
|
|
159
|
-
'dist/',
|
|
160
|
-
'plugin-assets/',
|
|
161
|
-
'LICENSE.md',
|
|
162
|
-
'README.md',
|
|
163
|
-
'CHANGELOG.md',
|
|
164
|
-
],
|
|
165
|
-
exports: {
|
|
166
|
-
'.': './src/index.js',
|
|
167
|
-
'./dist': './dist/index.js',
|
|
168
|
-
},
|
|
169
|
-
};
|
|
173
|
+
const packageJson = createPackageJson(options);
|
|
170
174
|
|
|
171
175
|
if (options.repository) {
|
|
172
176
|
packageJson.repository = {
|
|
@@ -176,7 +180,7 @@ async function createPluginTemplate(options, pluginPath) {
|
|
|
176
180
|
|
|
177
181
|
const installEsLint = options.scripts.find((script) => script.lint);
|
|
178
182
|
if (installEsLint) {
|
|
179
|
-
packageJson.eslintIgnore = ['node_modules'];
|
|
183
|
+
packageJson.eslintIgnore = ['node_modules', 'dist', 'plugin-assets'];
|
|
180
184
|
packageJson.eslintConfig = {
|
|
181
185
|
root: true,
|
|
182
186
|
extends: '@vcsuite/eslint-config/vue',
|
|
@@ -214,10 +218,11 @@ async function createPluginTemplate(options, pluginPath) {
|
|
|
214
218
|
|
|
215
219
|
if (installVitest) {
|
|
216
220
|
logger.debug('setting up test environment');
|
|
217
|
-
await
|
|
218
|
-
'tests',
|
|
219
|
-
|
|
220
|
-
|
|
221
|
+
await fs.promises.cp(
|
|
222
|
+
path.join(getDirname(), '..', 'assets', 'tests'),
|
|
223
|
+
path.join(pluginPath, 'tests'),
|
|
224
|
+
{ recursive: true },
|
|
225
|
+
);
|
|
221
226
|
}
|
|
222
227
|
|
|
223
228
|
try {
|
|
@@ -276,7 +281,11 @@ async function createPlugin(options) {
|
|
|
276
281
|
|
|
277
282
|
const writeReadmePromise = fs.promises.writeFile(
|
|
278
283
|
path.join(pluginPath, 'README.md'),
|
|
279
|
-
[
|
|
284
|
+
[
|
|
285
|
+
`# ${options.name}`,
|
|
286
|
+
'> Part of the [VC Map Project](https://github.com/virtualcitySYSTEMS/map-ui)',
|
|
287
|
+
'describe your plugin',
|
|
288
|
+
].join('\n'),
|
|
280
289
|
);
|
|
281
290
|
|
|
282
291
|
const writeChangesPromise = fs.promises.writeFile(
|
|
@@ -289,12 +298,18 @@ async function createPlugin(options) {
|
|
|
289
298
|
path.join(pluginPath, '.gitignore'),
|
|
290
299
|
);
|
|
291
300
|
|
|
301
|
+
const copyPrettierIgnorePromise = fs.promises.copyFile(
|
|
302
|
+
path.join(getDirname(), '..', 'assets', 'prettierignore'),
|
|
303
|
+
path.join(pluginPath, '.prettierignore'),
|
|
304
|
+
);
|
|
305
|
+
|
|
292
306
|
await Promise.all([
|
|
293
307
|
writeNpmrcPromise,
|
|
294
308
|
writeReadmePromise,
|
|
295
309
|
writeChangesPromise,
|
|
296
310
|
writeLicense(options.author, options.license, pluginPath),
|
|
297
311
|
copyGitIgnorePromise,
|
|
312
|
+
copyPrettierIgnorePromise,
|
|
298
313
|
]);
|
|
299
314
|
|
|
300
315
|
if (options.gitlabCi) {
|
|
@@ -314,6 +329,7 @@ async function createPlugin(options) {
|
|
|
314
329
|
} else {
|
|
315
330
|
await createPluginTemplate(options, pluginPath);
|
|
316
331
|
}
|
|
332
|
+
await setVcMapVersion(pluginPath);
|
|
317
333
|
logger.success(`Created plugin ${options.name}`);
|
|
318
334
|
}
|
|
319
335
|
|
|
@@ -323,7 +339,12 @@ async function createPlugin(options) {
|
|
|
323
339
|
export default async function create() {
|
|
324
340
|
const templateChoices = [
|
|
325
341
|
{ title: 'no template (basic structure)', value: null },
|
|
326
|
-
{ title: 'hello-world', value: '@vcmap/hello-world' },
|
|
342
|
+
{ title: 'hello-world', value: '@vcmap-show-case/hello-world' },
|
|
343
|
+
{
|
|
344
|
+
title: 'context-menu-example',
|
|
345
|
+
value: '@vcmap-show-case/context-menu-tester',
|
|
346
|
+
},
|
|
347
|
+
{ title: 'feature-info-example', value: '@vcmap-show-case/simple-graph' },
|
|
327
348
|
// to add further templates add a choice here
|
|
328
349
|
];
|
|
329
350
|
|
|
@@ -421,7 +442,7 @@ export default async function create() {
|
|
|
421
442
|
choices: templateChoices,
|
|
422
443
|
},
|
|
423
444
|
{
|
|
424
|
-
type:
|
|
445
|
+
type: 'multiselect',
|
|
425
446
|
message: 'Add the following scripts to the package.json.',
|
|
426
447
|
name: 'scripts',
|
|
427
448
|
choices: scriptChoices,
|
|
@@ -1,22 +1,29 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { existsSync } from 'fs';
|
|
2
|
+
import { writeFile, readFile } from 'fs/promises';
|
|
3
|
+
import { parse, satisfies, validRange } from 'semver';
|
|
2
4
|
import { logger } from '@vcsuite/cli-logger';
|
|
3
|
-
import
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import { getContext } from './context.js';
|
|
4
7
|
import { promiseExec } from './pluginCliHelper.js';
|
|
5
8
|
|
|
6
9
|
/** @type {Object|null} */
|
|
7
10
|
let packageJson = null;
|
|
8
11
|
|
|
9
12
|
/**
|
|
13
|
+
* @param {string} [pluginPath]
|
|
10
14
|
* @returns {Promise<Object>}
|
|
11
15
|
*/
|
|
12
|
-
export async function getPackageJson() {
|
|
16
|
+
export async function getPackageJson(pluginPath) {
|
|
13
17
|
if (!packageJson) {
|
|
14
|
-
const packageJsonFileName =
|
|
15
|
-
|
|
18
|
+
const packageJsonFileName = path.join(
|
|
19
|
+
pluginPath || getContext(),
|
|
20
|
+
'package.json',
|
|
21
|
+
);
|
|
22
|
+
if (!existsSync(packageJsonFileName)) {
|
|
16
23
|
throw new Error('no package.json found in context');
|
|
17
24
|
}
|
|
18
25
|
|
|
19
|
-
const content = await
|
|
26
|
+
const content = await readFile(packageJsonFileName);
|
|
20
27
|
packageJson = JSON.parse(content.toString());
|
|
21
28
|
}
|
|
22
29
|
|
|
@@ -73,9 +80,67 @@ export async function installDeps(deps, type, pluginPath) {
|
|
|
73
80
|
} else if (type === DepType.DEV) {
|
|
74
81
|
save = '--save-dev';
|
|
75
82
|
}
|
|
76
|
-
const installCmd = `npm i ${save} ${deps.join(' ')}`;
|
|
83
|
+
const installCmd = `npm i ${save} ${deps.map((d) => `"${d}"`).join(' ')}`; // wrap deps with "" for windows
|
|
77
84
|
logger.debug(installCmd);
|
|
78
85
|
const { stdout, stderr } = await promiseExec(installCmd, { cwd: pluginPath });
|
|
79
86
|
logger.log(stdout);
|
|
80
87
|
logger.error(stderr);
|
|
81
88
|
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Returns the version of the used @vcmap/ui dependency
|
|
92
|
+
* @param {string} [pluginPath]
|
|
93
|
+
* @returns {Promise<string>}
|
|
94
|
+
*/
|
|
95
|
+
export async function getVcMapVersion(pluginPath) {
|
|
96
|
+
const { stdout, stderr } = await promiseExec('npm ls --json', {
|
|
97
|
+
cwd: pluginPath || getContext(),
|
|
98
|
+
});
|
|
99
|
+
logger.error(stderr);
|
|
100
|
+
const { dependencies } = JSON.parse(stdout);
|
|
101
|
+
return dependencies['@vcmap/ui'].version;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* @param {string} [pluginPath]
|
|
106
|
+
* @returns {Promise<void>}
|
|
107
|
+
*/
|
|
108
|
+
export async function setVcMapVersion(pluginPath) {
|
|
109
|
+
const mapVersion = await getVcMapVersion(pluginPath);
|
|
110
|
+
const { major, minor } = parse(mapVersion);
|
|
111
|
+
const pluginPackageJson = await getPackageJson(pluginPath);
|
|
112
|
+
|
|
113
|
+
pluginPackageJson.mapVersion = `^${major}.${minor}`;
|
|
114
|
+
logger.info(`Setting plugin mapVersion to ${pluginPackageJson.mapVersion}`);
|
|
115
|
+
await writeFile(
|
|
116
|
+
path.join(pluginPath || getContext(), 'package.json'),
|
|
117
|
+
JSON.stringify(pluginPackageJson, null, 2),
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Update the vcsMapVersion in the package.json
|
|
123
|
+
* @param {string} pluginPath
|
|
124
|
+
* @returns {Promise<void>}
|
|
125
|
+
*/
|
|
126
|
+
export async function checkVcMapVersion(pluginPath) {
|
|
127
|
+
const pluginPackageJson = await getPackageJson(pluginPath);
|
|
128
|
+
const currentUiVersion = await getVcMapVersion(pluginPath);
|
|
129
|
+
if (pluginPackageJson.mapVersion) {
|
|
130
|
+
if (!validRange(pluginPackageJson.mapVersion)) {
|
|
131
|
+
logger.error(
|
|
132
|
+
`The current mapVersion ${pluginPackageJson.mapVersion} in the package.json is not a valid range!`,
|
|
133
|
+
);
|
|
134
|
+
} else if (
|
|
135
|
+
!satisfies(currentUiVersion, pluginPackageJson.mapVersion, {
|
|
136
|
+
includePrerelease: true,
|
|
137
|
+
})
|
|
138
|
+
) {
|
|
139
|
+
logger.error(
|
|
140
|
+
'The currently installed @vcmap/ui version is not covered by the mapVersion version range in the package.json! Due to breaking changes this plugin may not work as expected. Please update dependent API, where necessary!',
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
} else {
|
|
144
|
+
await setVcMapVersion(pluginPath);
|
|
145
|
+
}
|
|
146
|
+
}
|
package/src/serve.js
CHANGED
package/src/update.js
CHANGED
|
@@ -1,18 +1,41 @@
|
|
|
1
1
|
import { logger } from '@vcsuite/cli-logger';
|
|
2
|
-
import {
|
|
2
|
+
import { valid } from 'semver';
|
|
3
|
+
import {
|
|
4
|
+
checkVcMapVersion,
|
|
5
|
+
DepType,
|
|
6
|
+
getPackageJson,
|
|
7
|
+
installDeps,
|
|
8
|
+
} from './packageJsonHelpers.js';
|
|
3
9
|
import { name, promiseExec } from './pluginCliHelper.js';
|
|
10
|
+
import { getContext } from './context.js';
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* @typedef {Object} UpdateOptions
|
|
14
|
+
* @property {string} [mapVersion] - Optional version of @vcmap/ui to update to. Default is latest
|
|
15
|
+
*/
|
|
4
16
|
|
|
5
17
|
/**
|
|
6
18
|
* Update peer dependencies of a provided packageJson with @vcmap/ui@latest peers
|
|
7
19
|
* @param {Object} pluginPeer - peerDependencies of a plugin
|
|
8
20
|
* @param {string} pluginPath
|
|
21
|
+
* @param {UpdateOptions} [options]
|
|
9
22
|
* @returns {Promise<void>}
|
|
10
23
|
*/
|
|
11
|
-
export async function updatePeerDependencies(
|
|
24
|
+
export async function updatePeerDependencies(
|
|
25
|
+
pluginPeer,
|
|
26
|
+
pluginPath,
|
|
27
|
+
options = {},
|
|
28
|
+
) {
|
|
29
|
+
if (options.mapVersion && !valid(options.mapVersion)) {
|
|
30
|
+
logger.error(
|
|
31
|
+
`The mapVersion ${options.mapVersion} is not valid. Using 'latest' instead`,
|
|
32
|
+
);
|
|
33
|
+
options.mapVersion = 'latest';
|
|
34
|
+
}
|
|
12
35
|
const { stdout, stderr } = await promiseExec('npm view @vcmap/ui --json');
|
|
13
36
|
logger.error(stderr);
|
|
14
37
|
const { name: mapName, peerDependencies: mapPeer } = JSON.parse(stdout);
|
|
15
|
-
const peerDeps = [`${mapName}
|
|
38
|
+
const peerDeps = [`${mapName}@${options.mapVersion || 'latest'}`]; // @vcmap/ui is a required peer dep and will be updated in any case
|
|
16
39
|
if (pluginPeer) {
|
|
17
40
|
const pluginPeerDeps = Object.keys(pluginPeer)
|
|
18
41
|
.filter(
|
|
@@ -41,13 +64,16 @@ async function updateCli(pluginPath) {
|
|
|
41
64
|
}
|
|
42
65
|
|
|
43
66
|
/**
|
|
44
|
-
* Updating peer dependencies to @vmap/ui
|
|
67
|
+
* Updating peer dependencies to @vmap/ui
|
|
45
68
|
* Updating @vcmap/plugin-cli
|
|
69
|
+
* @param {UpdateOptions} options
|
|
46
70
|
* @returns {Promise<void>}
|
|
47
71
|
*/
|
|
48
|
-
export default async function update() {
|
|
72
|
+
export default async function update(options) {
|
|
49
73
|
const packageJson = await getPackageJson();
|
|
50
|
-
|
|
51
|
-
await
|
|
74
|
+
const context = getContext();
|
|
75
|
+
await updatePeerDependencies(packageJson.peerDependencies, context, options);
|
|
76
|
+
await checkVcMapVersion(context);
|
|
77
|
+
await updateCli(context);
|
|
52
78
|
logger.success(`Updated plugin ${packageJson.name}`);
|
|
53
79
|
}
|