@vcmap/plugin-cli 1.0.1 → 2.0.2

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 CHANGED
@@ -1,5 +1,11 @@
1
- # @vcmplugin/plugin-cli
2
- The `vcmplugin` cli helps develop and build plugins for the **vcMAP**.
1
+ # @vcmap/plugin-cli
2
+ > Part of the [VC Map Project](https://github.com/virtualcitySYSTEMS/map-ui)
3
+
4
+ > **Note: This documentation is for version 2, compatible with the [VC Map](https://github.com/virtualcitySYSTEMS/map-ui) v5.
5
+ > For documentation on version 1 compatible with VC Map v4, see [this tag](https://github.com/virtualcitySYSTEMS/map-plugin-cli/tree/v1.1.1)
6
+ > and be sure to install using `npm i -g @vcmap/plugin-cli@^1.1.0`**
7
+
8
+ The `vcmplugin` cli helps develop and build plugins for the **VC Map**.
3
9
 
4
10
  For more information on plugin development refer to [map plugin examples](https://github.com/virtualcitySYSTEMS/map-plugin-examples),
5
11
  which provides documentations and a tutorial on plugin development.
@@ -12,7 +18,8 @@ which provides documentations and a tutorial on plugin development.
12
18
 
13
19
  ## Prerequisite
14
20
 
15
- You need [nodejs](https://nodejs.org/en/) and npm installed on your system to use this tool.
21
+ You need [nodejs](https://nodejs.org/en/) 16 and npm installed on your system
22
+ to use this tool.
16
23
 
17
24
  ## Installation
18
25
  To install in your project:
@@ -26,6 +33,15 @@ npm i -g @vcmap/plugin-cli
26
33
  ```
27
34
 
28
35
  ## Usage
36
+ You can use the following workflow to quickly develop plugins. Note, that
37
+ the `@vcmap/plugin-cli` does _not_ directly depend on `@vcmap/ui` to avoid version
38
+ conflicts in the used API within a plugin. This means, that _all_ commands
39
+ (except for the `create` command) must be executed from within an installed
40
+ plugin cli _within the plugin itself_ using npx. When using the `create`
41
+ command, the `@vcmap/plugin-cli` will automatically be installed as a devDependency in
42
+ its current major version. You can then use either the scripts defined
43
+ by the template in your package.json `npm start`, `npm run pack` etc. or `npx`
44
+ to execute CLI commands.
29
45
 
30
46
  ### 1. Creating a new plugin
31
47
 
@@ -33,62 +49,183 @@ To create a new plugin template, run the following within your projects root:
33
49
  ```
34
50
  vcmplugin create
35
51
  ```
36
- This will open a command prompt helping you to create the basic [structure of a plugin](https://github.com/virtualcitySYSTEMS/map-plugin-examples/doc/VCM_Plugin.md#2-structure-of-a-plugin).
37
-
52
+ This will open a command prompt helping you to create the basic [structure of a plugin](https://github.com/virtualcitySYSTEMS/map-plugin-examples/blob/main/doc/VCM_Plugin.md#2-structure-of-a-plugin).
53
+ Be sure to check out the [peer dependecy section](#about_peer_dependencies) as well.
38
54
 
39
55
  ### 2. Serving a plugin for development
40
56
 
41
- To serve your project, run the following within your projects root:
57
+ To serve your plugin in dev mode, run the following within your projects root:
42
58
  ```
43
- vcmplugin serve --vcm <url|directory>
59
+ npx vcmplugin serve
44
60
  ```
45
- This will launch a dev server at localhost:8080 using the specified VC MAP application as its base.
46
- You can either specify a directory or a URL to an application.
61
+ The dev mode gives you complete debug information on all integrated libraries (@vcmap/core, ol etc.)
62
+ By default this command will launch a dev server at localhost:8008 using
63
+ the @vcmap/ui peer dependency package of your plugin as its base.
64
+ You can provide an alternate map config if you wish.
47
65
 
48
- ```bash
49
- # using a directory
50
- vcmplugin serve --vcm /home/vcs/virtualcityMAP
51
- # using a URL
52
- vcmplugin serve --vcm https://berlin.virtualcitymap.de
66
+ This is the dev mode, only _your_
67
+ plugin will be served. Any other plugins in the config will be stripped. To view how
68
+ your plugin integrates with others, use the `preview` command.
69
+
70
+ ### 3. Serving a plugin for integration
71
+
72
+ To serve your plugin in preview mode, run the following within your projects root:
53
73
  ```
74
+ npx vcmplugin preview
75
+ ```
76
+
77
+ The preview mode allows you to view your plugin _in its destined environment_.
78
+ You can see how it interacts with other plugins & other customizations applied to a map.
79
+ Preview will `build` your plugin continuously and serve the production ready
80
+ code using a base application.
81
+ By default, this will launch a dev server at localhost:5005 using the @vcmap/ui package
82
+ as its base. Alternatively you can provide a URL to a hosted VC Map application
83
+ and use said application as its base instead.
54
84
 
55
- ### 3. Building a plugin
85
+ ### 4. Building a plugin
56
86
 
57
87
  To build your project, run the following from within your projects root:
58
88
  ```bash
59
- vcmplugin build
89
+ npx vcmplugin build
60
90
  ```
91
+ This will build your application and place it in the `dist` directory.
61
92
 
62
- ### 4. Integrating a plugin in a productive VC MAP
93
+ ### 5. Integrating a plugin in a productive VC MAP
63
94
 
64
95
  To pack your project for productive use, run the following from within your projects root:
65
96
  ```bash
66
- vcmplugin pack
97
+ npx vcmplugin pack
67
98
  ```
68
99
 
69
100
  This will create a folder `dist` with a zip file containing your bundled code and assets.
70
- To use the plugin productively in a hosted map, unzip this file on your server to `{vcm-root}/plugins` and add an entry to your VC MAP [config](#2-config) plugins section.
101
+ To use the plugin productively in a hosted map,
102
+ unzip this file on your server to `{vcm-root}/plugins` and add
103
+ an entry to your VC MAP [config](#2-config) plugins section. This zip file can also be unzipped
104
+ in the VC Publishers `plugins` public directory.
105
+
106
+ ## About Peer Dependencies
107
+ The @vcmap/ui uses some _very large libraries_, notably `CesiumJS`. To reduce the amount
108
+ of traffic generated for loading plugins, all large libraries (see the list below),
109
+ are _provided_ in production (instead of bundling them into every plugin). This a) guarantees
110
+ a certain amount of type safety (using the @vcsuite/check parameter assertation library for instance),
111
+ b) reduces the amount of traffic required to load an application and c) leverages browser
112
+ caching more readily.
113
+
114
+ The following libraries are provided by the @vcmap/ui in a deployed application. You should define these
115
+ as peer dependencies if you use them in your plugin:
116
+ - @vcmap/core
117
+ - @vcmap/cesium
118
+ - ol
119
+ - @vcsuite/ui-components
120
+ - vue
121
+ - @vue/composition-api
122
+ - vuetify
123
+
124
+ During the build step, these libraries are automatically externalized by the vcmplugin-cli and in
125
+ production all plugins & the map core _share_ the same cesium library.
126
+
127
+ But, to make this work, it is important to define these dependencies as _peer dependencies_ of
128
+ a plugin and _that the provided index files_ are used (over directly importing from the source file).
129
+
130
+ For instance:
131
+ ```js
132
+ import Cartesian3 from '@vcmap/cesium/Source/Core/Cartesian3.js';
133
+ ```
134
+
135
+ should be rewritten to:
136
+ ```js
137
+ import { Cartesian3 } from '@vcmap/cesium';
138
+ ```
139
+
140
+ ### What about openlayers?
141
+ openlayers provides a special case, since its modules do not provide a _flat_ namespace.
142
+ To circumvent this limitation, _the @vcmap/ui provides a flat namespaced ol.js_ and a mechanic
143
+ to rewrite openlayers imports. This is automatically applied by the `@vcmap/rollup-plugin-vcs-ol`
144
+ used by the vcmplugin-cli build step. So openlayers imports can be written as:
145
+ ```js
146
+ import Feature from 'ol/Feature.js';
147
+ ```
148
+ or
149
+ ```js
150
+ import { Feature } from 'ol';
151
+ ```
71
152
 
72
- ## Non-Global CLI & npm run
73
- If you only use the `vcmplugin-cli` as a package dependency, you must add the above scripts to
74
- the `package.json` and use `npm run` to execute:
153
+ ## VC Map Plugins
154
+ The following defines a plugin in its rough structure. If you use the `@vcmap/plugin-cli`
155
+ to create your project, a template already adhering to these specs will be created for you.
156
+ - All plugins must provide the following:
157
+ - `package.json` with name, description, version, author and dependencies.
158
+ - `config.json` with default parameters for the plugins' configuration.
159
+ - `README.md` describing the plugins' capabilities and usage.
160
+ - `src/index.js` JS entry point.
161
+ - Plugin names are defined by the plugins' package name and therefore must obey npm [package name guidelines](https://docs.npmjs.com/package-name-guidelines):
162
+ - choose a name that
163
+ - is unique
164
+ - is descriptive
165
+ - is lowercase
166
+ - is uri encode-able
167
+ - doesn't start with `.`, `_` or a digit
168
+ - doesn't contain white spaces or any special characters like `~\'!()*"`
169
+ - do not use scope `@vcmap`, since it is only to be used by official plugins provided
170
+ by virtual city systems. But you are encouraged to use your own scope.
171
+ - Plugin dependencies have to be defined in the `package.json`.
172
+ - `dependency`: all plugin specific dependencies NOT provided by the `@vcmap/ui`.
173
+ - `peerDependency`: dependencies provided by the `@vcmap/ui`,
174
+ - e.g. `@vcmap/core` or `@vcmap/ui` (see [About Peer Dependencies](#About_Peer_Dependencies) for more details)
175
+ - `devDependency`: all dependencies only required for development, e.g. `eslint`.
176
+ - Plugins can be published to NPM, but should contain both source and minified code
177
+ to allow seamless integration into the [VC Map UI](https://github.com/virtualcitySYSTEMS/map-ui) environment.
178
+ For this reason the package.json of a plugin defines two exports:
75
179
  ```json
76
180
  {
77
- "name": "plugin-name",
78
- "main": "src/index.js",
79
- "scripts": {
80
- "build": "vcmplugin build",
81
- "serve": "vcmplugin serve --vcm ./vcm"
82
- },
83
- "devDependencies": {
84
- "vcmplugin-cli": "^0.1.1"
181
+ ".": "./src/index.js",
182
+ "./dist": "./dist/index.js"
183
+ }
184
+ ```
185
+
186
+
187
+ ### Plugin Interface:
188
+ Plugins must provide a function default export which returns an Object complying
189
+ with the VC Map Plugin Interface describe below:
190
+
191
+ ```typescript
192
+ declare interface VcsPlugin<T extends Object> {
193
+ readonly name: string;
194
+ readonly version: string;
195
+ initialize(app: VcsUiApp):void;
196
+ onVcsAppMounted(app: VcsUiApp):void;
197
+ toJSON():T;
198
+ destroy():void;
199
+ }
200
+
201
+ declare function defaultExport<T extends Object>(config: T):VcsPlugin<T>;
202
+ ```
203
+
204
+ A Simple JavaScript implementation of this interface can be seen below::
205
+ ```javascript
206
+ // index.js
207
+ /**
208
+ * @param {PluginExampleConfig} config
209
+ * @returns {VcsPlugin}
210
+ */
211
+ export default function defaultExport(config) {
212
+ return {
213
+ get name() {
214
+ return packageJSON.name;
215
+ },
216
+ get version() {
217
+ return packageJSON.version;
218
+ },
219
+ initialize(app) {},
220
+ onVcsAppMounted(app) {},
221
+ toJSON() {},
222
+ destroy() {},
85
223
  }
86
224
  }
87
225
  ```
88
226
 
89
- ## Considerations
90
- The legacy case was not as strict regarding the projects `package.json`. This approach relies
91
- more heavily on a) the precense of a `package.json` and b) the validity of said package.json. For
92
- instance the plugin name is directly derived from the `name` field in the package.json as is the
93
- entry point from `main`. You can still provide `name` as a CLI argument and `src/index.js` is still
94
- used, if `main` is missing from the `package.json`. This is do to change.
227
+
228
+ ## Notes on Developing
229
+ To develop the plugin-cli, be sure to not `npm link` into plugins, since this will
230
+ throw the resolver in resolving the @vcmap/ui peer dependency from the current plugin.
231
+ Instead run `npm pack` in the plugin cli and install the tarball in the plugin directly.
@@ -0,0 +1,2 @@
1
+ node_modules/
2
+ dist/
@@ -0,0 +1,93 @@
1
+ default:
2
+ image: gitlab.virtualcitysystems.de:5050/vcsuite/devops/gitlabrunner/node:16-bullseye
3
+
4
+ variables:
5
+ GIT_CLONE_PATH: $CI_BUILDS_DIR/$CI_PROJECT_PATH_SLUG/$CI_COMMIT_REF_SLUG
6
+
7
+ stages:
8
+ - build
9
+ - test
10
+ - bundle
11
+ - version
12
+ - publish
13
+
14
+ .template: &job_definition
15
+ only:
16
+ - /^(feature-.*|hotfix-.*|main|release-.*)$/
17
+ tags:
18
+ - linux-2.0
19
+
20
+ build:
21
+ <<: *job_definition
22
+ script:
23
+ - npm set registry 'http://npmregistry:4873'
24
+ - npm ci
25
+ before_script:
26
+ - mkdir -p ~/.ssh
27
+ - chmod 700 ~/.ssh
28
+ - echo "$SSH_RUNNER_KEY" | tr -d '\r' > ~/.ssh/id_rsa
29
+ - chmod 600 ~/.ssh/id_rsa
30
+ - ssh-keyscan gitlab.virtualcitysystems.de >> ~/.ssh/known_hosts
31
+ - chmod 644 ~/.ssh/known_hosts
32
+ - git config user.name "Gitlab Runner"
33
+ - git config user.email "gitlab-runner@vc.systems"
34
+ stage: build
35
+
36
+ .after_build_template: &after_build_definition
37
+ <<: *job_definition
38
+ variables:
39
+ GIT_STRATEGY: none
40
+
41
+ lint:
42
+ <<: *after_build_definition
43
+ stage: test
44
+ script:
45
+ - npm run lint
46
+
47
+ audit:
48
+ <<: *after_build_definition
49
+ stage: test
50
+ script:
51
+ - npm audit --production --audit-level=low
52
+
53
+ bundle:
54
+ <<: *after_build_definition
55
+ stage: bundle
56
+ script:
57
+ - npm run build
58
+
59
+ version:
60
+ <<: *after_build_definition
61
+ stage: version
62
+ only:
63
+ variables:
64
+ - $PUBLISH
65
+ refs:
66
+ - /^(main|release-v.*)$/
67
+ script:
68
+ - npm version patch -m "%s [skip-ci]"
69
+ - TAG=`git describe --abbrev=0`
70
+ - echo git push git@gitlab:vcsuite/"$CI_PROJECT_PATH".git
71
+ - git push git@gitlab:vcsuite/"$CI_PROJECT_PATH".git $TAG
72
+ - git push git@gitlab:vcsuite/"$CI_PROJECT_PATH".git HEAD:$CI_COMMIT_REF_NAME
73
+ before_script:
74
+ - mkdir -p ~/.ssh
75
+ - chmod 700 ~/.ssh
76
+ - echo "$SSH_RUNNER_KEY" | tr -d '\r' > ~/.ssh/id_rsa
77
+ - chmod 600 ~/.ssh/id_rsa
78
+ - ssh-keyscan gitlab >> ~/.ssh/known_hosts
79
+ - chmod 644 ~/.ssh/known_hosts
80
+ - git config user.name "Gitlab Runner"
81
+ - git config user.email "gitlab-runner@vc.systems"
82
+
83
+ publish:
84
+ <<: *after_build_definition
85
+ stage: publish
86
+ only:
87
+ refs:
88
+ - /^(main|release-v.*)$/
89
+ variables:
90
+ - $PUBLISH
91
+ script:
92
+ - npm config set '//npmregistry:4873/:_authToken' "${VERDACCIO_TOKEN}"
93
+ - npm publish --registry http://npmregistry:4873
@@ -0,0 +1,40 @@
1
+ <template>
2
+ <v-sheet>
3
+ <v-card class="pa-2 ma-2">
4
+ <v-container>
5
+ <v-row class="justify-center mb-4">
6
+ <h1>Hello World</h1>
7
+ </v-row>
8
+ <v-row class="justify-center">
9
+ <VcsButton
10
+ icon="mdi-times"
11
+ @click="closeSelf"
12
+ >
13
+ Close Window
14
+ </VcsButton>
15
+ </v-row>
16
+ </v-container>
17
+ </v-card>
18
+ </v-sheet>
19
+ </template>
20
+
21
+ <script>
22
+ import { inject } from '@vue/composition-api';
23
+ import { VcsButton } from '@vcsuite/ui-components';
24
+
25
+ export const windowId = 'hello_world_window_id';
26
+
27
+ export default {
28
+ name: 'HelloWorld',
29
+ components: { VcsButton },
30
+ setup() {
31
+ const app = inject('vcsApp');
32
+
33
+ return {
34
+ closeSelf() {
35
+ app.windowManager.remove(windowId);
36
+ },
37
+ };
38
+ },
39
+ };
40
+ </script>
@@ -0,0 +1,35 @@
1
+ import { WindowSlot } from '@vcmap/ui';
2
+ import { version, name } from '../package.json';
3
+ import HelloWorld, { windowId } from './helloWorld.vue';
4
+
5
+ /**
6
+ * @param {VcsApp} app - the app from which this plugin is loaded.
7
+ * @param {Object} config - the configuration of this plugin instance, passed in from the app.
8
+ * @returns {VcsPlugin}
9
+ */
10
+ export default function helloWorld(app, config) {
11
+ return {
12
+ get name() { return name; },
13
+ get version() { return version; },
14
+ initialize: async (vcsUiApp) => {
15
+ console.log('Called before loading the rest of the current context. Passed in the containing Vcs UI App ');
16
+ console.log(app, config);
17
+ console.log(vcsUiApp);
18
+ },
19
+ onVcsAppMounted: async (vcsUiApp) => {
20
+ console.log('Called when the root UI component is mounted and managers are ready to accept components');
21
+ vcsUiApp.windowManager.add({
22
+ id: windowId,
23
+ component: HelloWorld,
24
+ WindowSlot: WindowSlot.DETACHED,
25
+ position: {
26
+ left: '40%',
27
+ right: '40%',
28
+ },
29
+ }, name);
30
+ },
31
+ toJSON: async () => {
32
+ console.log('Called when serializing this plugin instance');
33
+ },
34
+ };
35
+ }
@@ -0,0 +1,81 @@
1
+ <!DOCTYPE html>
2
+ <html class="vcs-ui" lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta name="viewport" content="width=device-width,initial-scale=1.0" />
6
+ <link
7
+ rel="stylesheet"
8
+ href="https://fonts.googleapis.com/css?family=Titillium+Web"
9
+ />
10
+ </head>
11
+ <body style="height: 100vH;">
12
+ <noscript>
13
+ <strong>...</strong>
14
+ </noscript>
15
+ <div id="app">
16
+ <div id="loading-wrapper">
17
+ <div id="loading-text">LOADING</div>
18
+ <div id="loading-content"></div>
19
+ </div>
20
+ </div>
21
+ <style>
22
+ #loading-wrapper {
23
+ position: fixed;
24
+ width: 100%;
25
+ height: 100%;
26
+ left: 0;
27
+ top: 0;
28
+ }
29
+
30
+ #loading-text {
31
+ display: block;
32
+ position: absolute;
33
+ top: 50%;
34
+ left: 50%;
35
+ color: #409d76;
36
+ width: 100px;
37
+ height: 30px;
38
+ margin: -7px 0 0 -45px;
39
+ text-align: center;
40
+ font-family: 'PT Sans Narrow', sans-serif;
41
+ font-size: 20px;
42
+ }
43
+
44
+ #loading-content {
45
+ display: block;
46
+ position: relative;
47
+ left: 50%;
48
+ top: 50%;
49
+ width: 170px;
50
+ height: 170px;
51
+ margin: -85px 0 0 -85px;
52
+ }
53
+
54
+ #loading-content {
55
+ border: 3px solid transparent;
56
+ border-top-color: #409d76;
57
+ border-bottom-color: #409d76;
58
+ border-radius: 50%;
59
+ -webkit-animation: loader 2s linear infinite;
60
+ -moz-animation: loader 2s linear infinite;
61
+ -o-animation: loader 2s linear infinite;
62
+ animation: loader 2s linear infinite;
63
+ }
64
+
65
+ @keyframes loader {
66
+ 0% {
67
+ -webkit-transform: rotate(0deg);
68
+ -ms-transform: rotate(0deg);
69
+ transform: rotate(0deg);
70
+ }
71
+
72
+ 100% {
73
+ -webkit-transform: rotate(360deg);
74
+ -ms-transform: rotate(360deg);
75
+ transform: rotate(360deg);
76
+ }
77
+ }
78
+ </style>
79
+ <script type="module" src="./node_modules/@vcmap/ui/start.js"></script>
80
+ </body>
81
+ </html>
package/cli.js CHANGED
@@ -1,28 +1,27 @@
1
1
  #!/usr/bin/env node
2
- const program = require('commander');
3
- require('./src/defaultCommand');
4
- const { version } = require('./package.json');
5
- const { create, serve, build, pack } = require('./index');
2
+ import program from 'commander';
3
+ import './src/defaultCommand.js';
4
+ import { create, serve, build, pack, preview } from './index.js';
5
+ import { version } from './src/create.js';
6
+ import setupMapUi from './src/setupMapUi.js';
6
7
 
7
8
  program.version(version);
8
9
 
9
10
  program
10
11
  .command('create')
11
- .action(create);
12
+ .defaultOptions()
13
+ .safeAction(create);
12
14
 
13
15
  program
14
16
  .command('pack')
15
- .defaultBuildOptions()
16
- .action(pack);
17
+ .defaultOptions()
18
+ .safeAction(pack);
17
19
 
18
20
  program
19
- .command('serve')
21
+ .command('preview')
20
22
  .defaultOptions()
21
- .option('-p, --port [port]', 'the port to listen on', /\d+/, '8080')
22
- .option('--vcm [dir]', 'the directory path or URL to a virtualcityMAP application', './vcm')
23
- .option('--index [index.html]', 'the filename of the index.html to download. only used if vcm is a hosted application', 'index.html')
24
- .option('--auth <user:password>', 'an optional auth to append to proxy requests')
25
- .option('-c, --config <config>', 'a config override to not use the default plugin config')
23
+ .defaultServeOptions()
24
+ .option('--vcm [url]', 'URL to a virtualcityMAP application', val => val.replace(/\/$/, ''))
26
25
  .option('--proxyRoute <route>', 'a route to proxy as well (e.g. if you have additional proxies on your server)', (val, prev) => {
27
26
  if (!prev) {
28
27
  return [val];
@@ -30,13 +29,24 @@ program
30
29
  prev.push(val);
31
30
  return prev;
32
31
  }, [])
33
- .action(serve);
32
+ .safeAction(preview);
33
+
34
+ program
35
+ .command('serve')
36
+ .defaultOptions()
37
+ .defaultServeOptions()
38
+ .option('--mapConfig [config]', 'an optional map config (either file or URL) to use')
39
+ .safeAction(serve);
34
40
 
35
41
  program
36
42
  .command('build')
37
- .defaultBuildOptions()
43
+ .defaultOptions()
38
44
  .option('--development', 'set mode to development')
39
45
  .option('--watch', 'watch file changes')
40
- .action(build);
46
+ .safeAction(build);
47
+
48
+ program
49
+ .command('setup-map-ui')
50
+ .safeAction(setupMapUi);
41
51
 
42
52
  program.parse(process.argv);
package/index.js CHANGED
@@ -1,12 +1,7 @@
1
- const create = require('./src/create');
2
- const serve = require('./src/serve');
3
- const build = require('./src/build');
4
- const pack = require('./src/pack');
1
+ export { default as create } from './src/create.js';
2
+ export { default as serve } from './src/serve.js';
3
+ export { default as build } from './src/build.js';
4
+ export { default as pack } from './src/pack.js';
5
+ export { default as preview } from './src/preview.js';
6
+ export { default as setupMapUi } from './src/setupMapUi.js';
5
7
 
6
-
7
- module.exports = {
8
- create,
9
- serve,
10
- build,
11
- pack,
12
- };