@vcmap/plugin-cli 4.0.0-rc.5 → 4.0.0

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
@@ -2,9 +2,9 @@
2
2
 
3
3
  > Part of the [VC Map Project](https://github.com/virtualcitySYSTEMS/map-ui)
4
4
 
5
- > **Note: This documentation is for version 2, compatible with the [VC Map](https://github.com/virtualcitySYSTEMS/map-ui) v5.
6
- > For documentation on version 1 compatible with VC Map v4, see [this tag](https://github.com/virtualcitySYSTEMS/map-plugin-cli/tree/v1.1.1)
7
- > and be sure to install using `npm i -g @vcmap/plugin-cli@^1.1.0`**
5
+ > Note: This documentation is for version @vcmap/ui 6.0.0, compatible with the [VC Map](https://github.com/virtualcitySYSTEMS/map-ui).
6
+ >
7
+ > [Migration Guide](https://github.com/virtualcitySYSTEMS/map-ui/blob/release-v6.0/MIGRATION_V6.md) for Plugins from @vcmap/ui 5.0.0
8
8
 
9
9
  The `@vcmap/plugin-cli` helps develop and build plugins for the **VC Map**.
10
10
 
@@ -18,7 +18,7 @@ The `@vcmap/plugin-cli` helps develop and build plugins for the **VC Map**.
18
18
 
19
19
  ## Prerequisite
20
20
 
21
- You need [nodejs](https://nodejs.org/en/) 18 and npm installed on your system
21
+ You need [nodejs](https://nodejs.org/en/) 20 and npm installed on your system
22
22
  to use this tool.
23
23
 
24
24
  ## Installation
@@ -161,21 +161,25 @@ To build your project, run the following from within your projects root:
161
161
  npx vcmplugin build
162
162
  ```
163
163
 
164
- This will build your application and place it in the `dist` directory.
164
+ This will build your plugin and place it in the `dist` directory.
165
165
 
166
166
  ### 6. Integrating a plugin in a productive VC MAP
167
167
 
168
- To pack your project for productive use, run the following from within your projects root:
168
+ To bundle your project for productive use, run the following from within your projects root:
169
169
 
170
170
  ```bash
171
- npx vcmplugin pack
171
+ npx vcmplugin bundle
172
172
  ```
173
173
 
174
- This will create a folder `dist` with a zip file containing your bundled code and assets.
175
- To use the plugin productively in a hosted map,
176
- unzip this file on your server to `{vcm-root}/plugins` and add
177
- an entry to your VC MAP `config` plugins section. This zip file can also be unzipped
178
- in the VC Publishers `plugins` public directory.
174
+ This will create a `dist` folder with your bundled code and assets.
175
+
176
+ Using the VC Publisher you can simply upload the `tar.gz` file from the dist folder within your administration "Map Plugins" tab.
177
+ Afterward you can add the plugin to your app using the app-configurator.
178
+
179
+ Without using the VC Publisher you can also deploy a plugin manually:
180
+
181
+ - Unzip the `tar.gz` on a server
182
+ - Add the plugin to a module configuration plugins section, specifying a `name` and `entry` property (path to the plugin location)
179
183
 
180
184
  ## vcm config js
181
185
 
@@ -339,22 +343,33 @@ configuration of the plugin as its first argument and the base URL (without the
339
343
  from which the plugin was loaded as its second argument.
340
344
 
341
345
  ```typescript
342
- declare type PluginConfigEditor = {
343
- component: VueComponent;
346
+ declare type PluginConfigEditorComponent<C extends Object> = VueComponent<{
347
+ getConfig(): C;
348
+ setConfig(config?: C): void;
349
+ }>;
350
+
351
+ declare type PluginConfigEditor<C extends Object> = {
352
+ component: PluginConfigEditorComponent<C>;
353
+ title?: string;
344
354
  collectionName?: string;
345
355
  itemName?: string;
356
+ infoUrlCallback?: () => string;
346
357
  };
347
358
 
348
359
  declare interface VcsPlugin<T extends Object, S extends Object> {
349
360
  readonly name: string;
350
361
  readonly version: string;
351
- initialize(app: VcsUiApp, state?: S): Promise<void>;
352
- onVcsAppMounted(app: VcsUiApp): Promise<void>;
353
- getState(): Promise<S>;
354
- toJSON(): Promise<T>;
355
- getDefaultOptions(): T;
356
- getConfigEditors(): Array<PluginConfigEditor>;
357
- destroy(): void;
362
+ readonly mapVersion: string;
363
+ i18n?: {
364
+ [x: string]: unknown;
365
+ };
366
+ initialize?: (app: VcsUiApp, state?: S) => Promise<void>;
367
+ onVcsAppMounted?: (app: VcsUiApp) => Promise<void>;
368
+ toJSON?: () => T;
369
+ getDefaultOptions?: () => T;
370
+ getState?: () => S | Promise<S>;
371
+ getConfigEditors?: () => Array<PluginConfigEditor<object>>;
372
+ destroy?: () => void;
358
373
  }
359
374
 
360
375
  declare function defaultExport<T extends Object, S extends Object>(
@@ -402,6 +417,95 @@ export default function defaultExport(config, baseUrl) {
402
417
  }
403
418
  ```
404
419
 
420
+ ### Plugin Config Editor
421
+
422
+ Part of the [plugin interface](#plugin-interface) is the option to provide one or more custom config editors.
423
+ These config editors will be used in the VC Publisher to define the configuration of a plugin or a plugin custom class, like a custom layer or feature info.
424
+ If a plugin does not provide a config editor, the JsonEditor is always used as fallback.
425
+
426
+ To provide a custom editor, the plugin has to implement a `getConfigEditors` method returning one or more editors.
427
+ A plugin config editor definition consists of
428
+
429
+ - component: The vue component providing the ui of the editor. This vue component has to extend the `AbstractConfigEditor.vue`, which can be imported from `@vcmap/ui`. The component has to provide two props: `getConfig` for getting the serialized configuration and `setConfig` to update the changed configuration.
430
+ - title: An optional title displayed in the window header of the editor and on action buttons (e.g. tooltip)
431
+ - collectionName: The collection the item belongs to. Default is `plugins` collection. For a layer config editor you would provide `layers`.
432
+ - itemName: The item the editor can be used for. Can be a name or className. Default is the plugin's name. For a layer you would provide `MyNewLayer.className`.
433
+ - infoUrlCallback: An optional function returning an url referencing help or further information regarding the config editor.
434
+
435
+ An example of plugin config editor can look like this:
436
+
437
+ ```vue
438
+ <template>
439
+ <AbstractConfigEditor @submit="apply" v-bind="{ ...$attrs, ...$props }">
440
+ <VcsFormSection heading="general" expandable :start-open="true">
441
+ <v-container class="py-0 px-1">
442
+ <v-row no-gutters>
443
+ <v-col>
444
+ <VcsLabel html-for="someProp">
445
+ {{ $t('myPlugin.someProp') }}
446
+ </VcsLabel>
447
+ </v-col>
448
+ <v-col>
449
+ <VcsTextField id="someProp" v-model="localConfig.someProp" />
450
+ </v-col>
451
+ </v-row>
452
+ </v-container>
453
+ </VcsFormSection>
454
+ </AbstractConfigEditor>
455
+ </template>
456
+
457
+ <script>
458
+ import { VContainer, VRow, VCol } from 'vuetify/components';
459
+ import {
460
+ AbstractConfigEditor,
461
+ VcsFormSection,
462
+ VcsLabel,
463
+ VcsTextField,
464
+ } from '@vcmap/ui';
465
+ import { ref } from 'vue';
466
+ import { getDefaultOptions } from '../defaultOptions.js';
467
+
468
+ export default {
469
+ name: 'MyPluginConfigEditor',
470
+ components: {
471
+ VContainer,
472
+ VRow,
473
+ VCol,
474
+ AbstractConfigEditor,
475
+ VcsFormSection,
476
+ VcsLabel,
477
+ VcsTextField,
478
+ },
479
+ props: {
480
+ getConfig: {
481
+ type: Function,
482
+ required: true,
483
+ },
484
+ setConfig: {
485
+ type: Function,
486
+ required: true,
487
+ },
488
+ },
489
+ setup(props) {
490
+ const defaultOptions = getDefaultOptions();
491
+ const config = props.getConfig();
492
+ const localConfig = ref({ ...defaultOptions, ...config });
493
+
494
+ const apply = () => {
495
+ props.setConfig(localConfig.value);
496
+ };
497
+
498
+ return {
499
+ localConfig,
500
+ apply,
501
+ };
502
+ },
503
+ };
504
+ </script>
505
+
506
+ <style scoped></style>
507
+ ```
508
+
405
509
  ### About Plugin Assets
406
510
 
407
511
  Plugin assets are considered to be static files, such as images, fonts etc. which shall be
@@ -9,18 +9,16 @@ function sleep(ms = 0): Promise<void> {
9
9
  });
10
10
  }
11
11
 
12
- type TestPluginInstance = VcsPlugin<Record<never, never>, Record<never, never>>;
12
+ type TestPluginInstance = VcsPlugin<object, object>;
13
13
 
14
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
15
- // @ts-ignore
14
+ // @ts-expect-error: not defined on global
16
15
  window.VcsPluginLoaderFunction = (
17
16
  name: string,
18
17
  module: string,
19
18
  ): {
20
19
  default: () => TestPluginInstance;
21
20
  } => ({
22
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
23
- // @ts-ignore
21
+ // @ts-expect-error: interface may not use this
24
22
  default: () => plugin({ name }, module),
25
23
  });
26
24
 
@@ -17,8 +17,7 @@ const configTest = defineConfig({
17
17
  },
18
18
  environment: 'jsdom',
19
19
  setupFiles: ['tests/setup.js'],
20
- isolate: false,
21
- threads: false,
20
+ pool: 'forks',
22
21
  },
23
22
  });
24
23
  export default configTest;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vcmap/plugin-cli",
3
- "version": "4.0.0-rc.5",
3
+ "version": "4.0.0",
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,19 +31,19 @@
31
31
  "dependencies": {
32
32
  "@vcmap/rollup-plugin-vcs-ol": "^1.0.2",
33
33
  "@vcsuite/cli-logger": "^1.0.0",
34
- "@vitejs/plugin-vue": "^5.1.3",
34
+ "@vitejs/plugin-vue": "^5.1.4",
35
35
  "commander": "^10.0.1",
36
- "express": "^4.21.0",
36
+ "express": "^4.21.1",
37
37
  "prompts": "^2.4.2",
38
- "sass": "^1.77.1",
38
+ "sass": "^1.80.2",
39
39
  "semver": "^7.5.4",
40
40
  "tar": "^7.4.3",
41
- "vite": "^5.4.3",
41
+ "vite": "^5.4.9",
42
42
  "vite-plugin-vuetify": "^2.0.4"
43
43
  },
44
44
  "peerDependencies": {
45
- "@vcmap/ui": "^6.0.0-rc.7",
46
- "vue": "~3.4.27"
45
+ "@vcmap/ui": "^6.0.0",
46
+ "vue": "~3.4.38"
47
47
  },
48
48
  "peerDependenciesMeta": {
49
49
  "@vcmap/ui": {
package/src/serve.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import fs from 'fs';
2
- import { readFile } from 'fs/promises';
2
+ import { lstat, readFile } from 'fs/promises';
3
3
  import { createServer } from 'vite';
4
4
  import vue from '@vitejs/plugin-vue';
5
5
  import express from 'express';
@@ -101,6 +101,8 @@ export default async function serve(options) {
101
101
  const mergedOptions = { ...vcmConfigJs, ...options };
102
102
 
103
103
  await printVcmapUiVersion();
104
+ const uiLStat = await lstat(resolveMapUi());
105
+
104
106
  /*
105
107
  // In case @vcmap/ui is linked via git+ssh, dist folder is not available and must be built first
106
108
  // Currently not needed, keep it here if the same problem happens again
@@ -147,6 +149,7 @@ export default async function serve(options) {
147
149
  tinyqueue: 'tinyqueue/tinyqueue.js',
148
150
  },
149
151
  dedupe: Object.keys(peerDependencies),
152
+ preserveSymlinks: uiLStat.isSymbolicLink(),
150
153
  },
151
154
  optimizeDeps: {
152
155
  exclude: [
@@ -158,6 +161,13 @@ export default async function serve(options) {
158
161
  ],
159
162
  include: optimizationIncludes,
160
163
  },
164
+ css: {
165
+ preprocessorOptions: {
166
+ scss: {
167
+ api: 'modern-compiler', // or "modern", "legacy"
168
+ },
169
+ },
170
+ },
161
171
  plugins: [vue(), createConfigJsonReloadPlugin()],
162
172
  server: {
163
173
  middlewareMode: true,