@vcmap/plugin-cli 2.0.5 → 2.0.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/LICENSE.md CHANGED
@@ -1,4 +1,4 @@
1
- Copyright 2021 virtualcitySYSTEMS GmbH
1
+ Copyright 2022 virtualcitySYSTEMS GmbH
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
4
4
 
package/README.md CHANGED
@@ -79,7 +79,32 @@ By default, this will launch a dev server at localhost:5005 using the @vcmap/ui
79
79
  as its base. Alternatively you can provide a URL to a hosted VC Map application
80
80
  and use said application as its base instead.
81
81
 
82
- ### 4. Building a plugin
82
+ ### 4. Building a plugin staging application
83
+
84
+ A staging application creates a full deployable VC Map in the `dist` folder with the following components.
85
+ - compiled @vcmap/ui library and all dependencies
86
+ - default @vcmap/ui configurations
87
+ - default @vcmap/ui plugins
88
+ - compiled plugin which is in development.
89
+
90
+ Building the staging application will collect all parts and will inject the plugin in development in the default
91
+ map configuration. The staging application can for example be used to deploy the App in an Apache in a postCommit
92
+ Pipeline. (See .gitlab-ci.yml for an example).
93
+ ```bash
94
+ npx vcmplugin buildStagingApp
95
+ ```
96
+ To start a webserver to serve the content of the `dist` folder call `npx vite preview`; This will start a static webserver
97
+ on the port 4173.
98
+
99
+ The Dockerfile in `build/staging/Dockerfile` can be used to create a Docker Container which serves the content of the dist folder.
100
+ ```bash
101
+ npx vcmplugin buildStagingApp
102
+ cd dist
103
+ docker build -f ../build/staging/Dockerfile -t vcmap:staging .
104
+ docker run --rm -p 5000:80 vcmap:staging
105
+ ```
106
+
107
+ ### 5. Building a plugin
83
108
 
84
109
  To build your project, run the following from within your projects root:
85
110
  ```bash
@@ -87,7 +112,7 @@ npx vcmplugin build
87
112
  ```
88
113
  This will build your application and place it in the `dist` directory.
89
114
 
90
- ### 5. Integrating a plugin in a productive VC MAP
115
+ ### 6. Integrating a plugin in a productive VC MAP
91
116
 
92
117
  To pack your project for productive use, run the following from within your projects root:
93
118
  ```bash
@@ -114,7 +139,6 @@ as peer dependencies if you use them in your plugin:
114
139
  - @vcmap/cesium
115
140
  - ol
116
141
  - vue
117
- - @vue/composition-api
118
142
  - vuetify
119
143
 
120
144
  During the build step, these libraries are automatically externalized by the vcmplugin-cli and in
@@ -185,16 +209,17 @@ Plugins must provide a function default export which returns an Object complying
185
209
  with the VC Map Plugin Interface describe below:
186
210
 
187
211
  ```typescript
188
- declare interface VcsPlugin<T extends Object> {
212
+ declare interface VcsPlugin<T extends Object, S extends Object> {
189
213
  readonly name: string;
190
214
  readonly version: string;
191
- initialize(app: VcsUiApp):void;
192
- onVcsAppMounted(app: VcsUiApp):void;
193
- toJSON():T;
215
+ initialize(app: VcsUiApp, state?: S):Promise<void>;
216
+ onVcsAppMounted(app: VcsUiApp):Promise<void>;
217
+ getState():Promise<S>;
218
+ toJSON():Promise<T>;
194
219
  destroy():void;
195
220
  }
196
221
 
197
- declare function defaultExport<T extends Object>(config: T):VcsPlugin<T>;
222
+ declare function defaultExport<T extends Object, S extends Object>(config: T):VcsPlugin<T, S>;
198
223
  ```
199
224
 
200
225
  A Simple JavaScript implementation of this interface can be seen below::
@@ -211,10 +236,11 @@ export default function defaultExport(config) {
211
236
  },
212
237
  get version() {
213
238
  return packageJSON.version;
214
- },
215
- initialize(app) {},
216
- onVcsAppMounted(app) {},
217
- toJSON() {},
239
+ },
240
+ async initialize (app, state) {},
241
+ async onVcsAppMounted(app) {},
242
+ async getState() { return {}; },
243
+ async toJSON() { return {}; },
218
244
  destroy() {},
219
245
  }
220
246
  }
@@ -8,6 +8,7 @@ stages:
8
8
  - build
9
9
  - test
10
10
  - bundle
11
+ - deploy
11
12
  - version
12
13
  - publish
13
14
 
@@ -20,7 +21,6 @@ stages:
20
21
  build:
21
22
  <<: *job_definition
22
23
  script:
23
- - npm set registry 'http://npmregistry:4873'
24
24
  - npm ci
25
25
  before_script:
26
26
  - mkdir -p ~/.ssh
@@ -38,6 +38,12 @@ build:
38
38
  variables:
39
39
  GIT_STRATEGY: none
40
40
 
41
+ .staging_build_template: &staging_build_template
42
+ <<: *after_build_definition
43
+ except:
44
+ variables:
45
+ - $PUBLISH
46
+
41
47
  lint:
42
48
  <<: *after_build_definition
43
49
  stage: test
@@ -50,12 +56,72 @@ audit:
50
56
  script:
51
57
  - npm audit --production --audit-level=low
52
58
 
59
+ buildPreview:
60
+ <<: *staging_build_template
61
+ stage: bundle
62
+ script:
63
+ - npm run buildStagingApp
64
+
53
65
  bundle:
54
66
  <<: *after_build_definition
55
67
  stage: bundle
68
+ only:
69
+ variables:
70
+ - $PUBLISH
71
+ refs:
72
+ - /^(main|release-v.*)$/
56
73
  script:
57
74
  - npm run build
58
75
 
76
+ deployStaging:
77
+ <<: *staging_build_template
78
+ stage: deploy
79
+ environment:
80
+ name: staging/$CI_COMMIT_REF_SLUG
81
+ url: http://$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG.stagingcluster.intern.virtualcitysystems.de
82
+ on_stop: stopEnvironment
83
+ image:
84
+ name: gcr.io/kaniko-project/executor:debug
85
+ entrypoint: [ "" ]
86
+ script:
87
+ - /kaniko/executor --context dist/ --dockerfile build/staging/Dockerfile --destination $CI_REGISTRY_IMAGE/staging:$CI_COMMIT_REF_SLUG
88
+ before_script:
89
+ - mkdir -p /kaniko/.docker
90
+ - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
91
+
92
+ stopEnvironment:
93
+ stage: deploy
94
+ variables:
95
+ GIT_STRATEGY: none
96
+ image:
97
+ name: bitnami/kubectl:latest
98
+ entrypoint: [""]
99
+ tags:
100
+ - linux-2.0
101
+ script:
102
+ - echo "Stop environment staging/$CI_COMMIT_REF_NAME"
103
+ - echo "Delete namespace on k9s $CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG"
104
+ - kubectl config use-context vcsuite/cluster-management:agent
105
+ - kubectl delete namespace $CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG
106
+ when: manual
107
+ environment:
108
+ name: staging/$CI_COMMIT_REF_SLUG
109
+ action: stop
110
+
111
+ deployStagingCluster:
112
+ <<: *staging_build_template
113
+ stage: deployCluster
114
+ inherit:
115
+ variables: false
116
+ variables:
117
+ STAGE_BRANCH: $CI_COMMIT_REF_SLUG
118
+ STAGE_PROJECT_NAME: $CI_PROJECT_PATH_SLUG
119
+ STAGE_REGISTRY_IMAGE: $CI_REGISTRY_IMAGE
120
+ STAGE_NAMESPACE: $CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG
121
+ trigger:
122
+ project: vcsuite/devops/manifests
123
+ branch: main
124
+
59
125
  version:
60
126
  <<: *after_build_definition
61
127
  stage: version
@@ -89,5 +155,5 @@ publish:
89
155
  variables:
90
156
  - $PUBLISH
91
157
  script:
92
- - npm config set '//npmregistry:4873/:_authToken' "${VERDACCIO_TOKEN}"
93
- - npm publish --registry http://npmregistry:4873
158
+ - npm config set '//registry.npmjs.org/:_authToken' "${NPM_TOKEN}"
159
+ - npm publish --registry https://registry.npmjs.org --access public
@@ -0,0 +1,2 @@
1
+ FROM httpd:2-buster
2
+ COPY * /usr/local/apache2/htdocs/
@@ -3,14 +3,14 @@
3
3
  <v-card class="pa-2 ma-2">
4
4
  <v-container>
5
5
  <v-row class="justify-center mb-4">
6
- <h1>Hello World</h1>
6
+ <h1>{{ $t('helloWorld.helloWorld')}}</h1>
7
7
  </v-row>
8
8
  <v-row class="justify-center">
9
9
  <VcsButton
10
10
  icon="mdi-times"
11
11
  @click="closeSelf"
12
12
  >
13
- Close Window
13
+ {{ $t('helloWorld.close')}}
14
14
  </VcsButton>
15
15
  </v-row>
16
16
  </v-container>
@@ -3,19 +3,27 @@ import { version, name } from '../package.json';
3
3
  import HelloWorld, { windowId } from './helloWorld.vue';
4
4
 
5
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}
6
+ * @param {T} config - the configuration of this plugin instance, passed in from the app.
7
+ * @returns {import("@vcmap/ui/src/vcsUiApp").VcsPlugin<T>}
8
+ * @template {Object} T
9
+ * @template {Object} S
9
10
  */
10
- export default function helloWorld(app, config) {
11
+ export default function(config) {
11
12
  return {
12
13
  get name() { return name; },
13
14
  get version() { return version; },
14
- initialize: async (vcsUiApp) => {
15
+ /**
16
+ * @param {import("@vcmap/ui").VcsUiApp} vcsUiApp
17
+ * @param {S=} state
18
+ * @returns {Promise<void>}
19
+ */
20
+ initialize: async (vcsUiApp, state) => {
15
21
  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
22
  },
23
+ /**
24
+ * @param {import("@vcmap/ui").VcsUiApp} vcsUiApp
25
+ * @returns {Promise<void>}
26
+ */
19
27
  onVcsAppMounted: async (vcsUiApp) => {
20
28
  console.log('Called when the root UI component is mounted and managers are ready to accept components');
21
29
  vcsUiApp.windowManager.add({
@@ -28,8 +36,36 @@ export default function helloWorld(app, config) {
28
36
  },
29
37
  }, name);
30
38
  },
39
+ /**
40
+ * @returns {Promise<S>}
41
+ */
42
+ getState: async () => {
43
+ console.log('Called when serializing this plugin instance');
44
+ return {};
45
+ },
46
+ /**
47
+ * @returns {Promise<T>}
48
+ */
31
49
  toJSON: async () => {
32
50
  console.log('Called when serializing this plugin instance');
51
+ return {};
52
+ },
53
+ i18n: {
54
+ en: {
55
+ helloWorld: {
56
+ helloWorld: 'Hello World',
57
+ close: 'Close',
58
+ },
59
+ },
60
+ de: {
61
+ helloWorld: {
62
+ helloWorld: 'Hallo Welt',
63
+ close: 'Schließen',
64
+ },
65
+ },
66
+ },
67
+ destroy() {
68
+ console.log('hook to cleanup');
33
69
  },
34
70
  };
35
- }
71
+ };
package/cli.js CHANGED
@@ -1,9 +1,12 @@
1
1
  #!/usr/bin/env node
2
2
  import program from 'commander';
3
3
  import './src/defaultCommand.js';
4
- import { create, serve, build, pack, preview } from './index.js';
4
+ import {
5
+ create, serve, build, pack, preview,
6
+ } from './index.js';
5
7
  import { version } from './src/create.js';
6
8
  import setupMapUi from './src/setupMapUi.js';
9
+ import buildStagingApp from './src/buildStagingApp.js';
7
10
 
8
11
  program.version(version);
9
12
 
@@ -45,6 +48,11 @@ program
45
48
  .option('--watch', 'watch file changes')
46
49
  .safeAction(build);
47
50
 
51
+ program
52
+ .command('buildStagingApp')
53
+ .defaultOptions()
54
+ .safeAction(buildStagingApp);
55
+
48
56
  program
49
57
  .command('setup-map-ui')
50
58
  .safeAction(setupMapUi);
package/index.js CHANGED
@@ -3,5 +3,6 @@ export { default as serve } from './src/serve.js';
3
3
  export { default as build } from './src/build.js';
4
4
  export { default as pack } from './src/pack.js';
5
5
  export { default as preview } from './src/preview.js';
6
+ export { default as buildStagingApp } from './src/buildStagingApp.js';
6
7
  export { default as setupMapUi } from './src/setupMapUi.js';
7
8
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vcmap/plugin-cli",
3
- "version": "2.0.5",
3
+ "version": "2.0.8",
4
4
  "description": "A CLI to help develop and build plugins for the VC Map",
5
5
  "main": "index.js",
6
6
  "type": "module",
@@ -34,15 +34,14 @@
34
34
  "prompts": "^2.4.1",
35
35
  "sass": "1.32.13",
36
36
  "semver": "^7.3.5",
37
- "unplugin-vue-components": "^0.17.21",
38
- "vinyl-fs": "^3.0.3",
39
- "vite": "^2.9.1",
40
- "vite-plugin-vue2": "^1.7.3",
41
- "vue-template-compiler": "^2.6.14"
37
+ "unplugin-vue-components": "^0.21.1",
38
+ "vite": "^2.9.14",
39
+ "vite-plugin-vue2": "^2.0.1",
40
+ "vue-template-compiler": "~2.7.3"
42
41
  },
43
42
  "peerDependencies": {
44
- "@vcmap/ui": "^5.0.0-rc.9",
45
- "vue": "^2.6.14"
43
+ "@vcmap/ui": "^5.0.0-rc.11",
44
+ "vue": "~2.7.3"
46
45
  },
47
46
  "peerDependenciesMeta": {
48
47
  "@vcmap/ui": {
package/src/build.js CHANGED
@@ -12,6 +12,8 @@ import { getContext } from './context.js';
12
12
  * @typedef {Object} BuildOptions
13
13
  * @property {boolean} [development]
14
14
  * @property {boolean} [watch]
15
+ * @property {string} [outputPath] path where the plugin should be written, relative to the dist folder, default ''
16
+ * @property {boolean} [keepDistFolder] will not clear the dist folder if set to true
15
17
  */
16
18
 
17
19
  export function getDefaultConfig() {
@@ -62,8 +64,10 @@ export default async function buildModule(options) {
62
64
  const pluginName = await getPluginName();
63
65
  const libraryPaths = await getLibraryPaths(pluginName);
64
66
  const distPath = path.join(getContext(), 'dist');
65
- await fs.rm(distPath, { recursive: true, force: true });
66
- await fs.mkdir(distPath);
67
+ if (!options.keepDistFolder) {
68
+ await fs.rm(distPath, { recursive: true, force: true });
69
+ await fs.mkdir(distPath);
70
+ }
67
71
  const external = Object.keys(libraryPaths);
68
72
  const config = {
69
73
  ...getDefaultConfig(),
@@ -82,6 +86,9 @@ export default async function buildModule(options) {
82
86
  external,
83
87
  output: {
84
88
  paths: libraryPaths,
89
+ manualChunks() { // ensure only one chunk will be created
90
+ return 'index';
91
+ },
85
92
  },
86
93
  },
87
94
  watch: options.watch ? {
@@ -90,5 +97,5 @@ export default async function buildModule(options) {
90
97
  },
91
98
  };
92
99
  const { buildLibrary } = await import('@vcmap/ui/build/buildHelpers.js');
93
- await buildLibrary(config, '', 'index', '', true);
100
+ await buildLibrary(config, options.outputPath ?? '', 'index', '', true);
94
101
  }
@@ -0,0 +1,48 @@
1
+ import fs from 'fs';
2
+ import { cp, copyFile, writeFile } from 'fs/promises';
3
+ import path from 'path';
4
+ import { getContext } from './context.js';
5
+ import { getConfigJson } from './hostingHelpers.js';
6
+ import { getPluginName } from './packageJsonHelpers.js';
7
+ import buildModule, { getDefaultConfig } from './build.js';
8
+ import setupMapUi from './setupMapUi.js';
9
+
10
+
11
+ /**
12
+ * creates production preview application in the dist folder based on the @vcmap/ui default map configuration.
13
+ * @returns {Promise<void>}
14
+ */
15
+ export default async function buildStagingApp() {
16
+ const pluginName = await getPluginName();
17
+ const distPath = path.join(getContext(), 'dist');
18
+ // Clear dist folder
19
+ await fs.rm(distPath, { recursive: true, force: true });
20
+ await fs.mkdir(distPath);
21
+ await setupMapUi();
22
+ const { buildPluginsForPreview } = await import('@vcmap/ui/build/buildHelpers.js');
23
+ await buildPluginsForPreview(getDefaultConfig(), true);
24
+ await fs.promises.mkdir(path.join(distPath, 'plugins', pluginName), { recursive: true });
25
+
26
+ await buildModule({ outputPath: `plugins/${pluginName}`, keepDistFolder: true });
27
+ await copyFile(
28
+ path.join(getContext(), 'node_modules', '@vcmap', 'ui', 'dist', 'index.html'),
29
+ path.join(distPath, 'index.html'),
30
+ );
31
+ const config = await getConfigJson();
32
+ // update Entry
33
+ const pluginConfig = config.plugins.find(p => p.name === pluginName);
34
+ if (pluginConfig) {
35
+ pluginConfig.entry = `plugins/${pluginName}/index.js`;
36
+ }
37
+ await writeFile(path.join(distPath, 'map.config.json'), JSON.stringify(config, null, 2));
38
+ await cp(
39
+ path.join(getContext(), 'node_modules', '@vcmap', 'ui', 'dist', 'assets'),
40
+ path.join(distPath, 'assets'),
41
+ { recursive: true },
42
+ );
43
+ await cp(
44
+ path.join(getContext(), 'node_modules', '@vcmap', 'ui', 'config'),
45
+ path.join(distPath, 'config'),
46
+ { recursive: true },
47
+ );
48
+ }
package/src/create.js CHANGED
@@ -19,8 +19,6 @@ export const { version, name } = JSON.parse(fs.readFileSync(path.join(getDirname
19
19
  * @property {string} author
20
20
  * @property {string} repository
21
21
  * @property {string} license
22
- * @property {string} registry
23
- * @property {boolean} addCiCd
24
22
  * @property {Array<string>} peerDeps
25
23
  */
26
24
 
@@ -100,7 +98,7 @@ async function createPluginTemplate(options) {
100
98
 
101
99
  const writeNpmrcPromise = fs.promises.writeFile(
102
100
  path.join(pluginPath, '.npmrc'),
103
- `registry=${options.registry}\n`,
101
+ 'registry=https://registry.npmjs.org\n',
104
102
  );
105
103
 
106
104
  const writeReadmePromise = fs.promises.writeFile(
@@ -170,6 +168,7 @@ export default async function create() {
170
168
  { title: 'pack', value: { pack: 'vcmplugin pack' }, selected: true },
171
169
  { title: 'start', value: { start: 'vcmplugin serve' }, selected: true },
172
170
  { title: 'preview', value: { preview: 'vcmplugin preview' }, selected: true },
171
+ { title: 'buildStagingApp', value: { preview: 'vcmplugin buildStagingApp' }, selected: true },
173
172
  { title: 'lint', value: { lint: 'eslint "{src,tests}/**/*.{js,vue}"' }, selected: true },
174
173
  ];
175
174
 
@@ -239,12 +238,6 @@ export default async function create() {
239
238
  value: type,
240
239
  })),
241
240
  },
242
- {
243
- type: 'text',
244
- name: 'registry',
245
- message: 'Set default npm registry',
246
- initial: 'https://registry.npmjs.org',
247
- },
248
241
  {
249
242
  name: 'peerDeps',
250
243
  type: 'multiselect',
@@ -252,14 +245,6 @@ export default async function create() {
252
245
  choices: peerDependencyChoices,
253
246
  hint: '- Space to select. Enter to submit',
254
247
  },
255
- {
256
- type: 'toggle',
257
- name: 'addCiCd',
258
- message: 'Add default VCS gitlab ci/cd?',
259
- initial: false,
260
- active: 'yes',
261
- inactive: 'no',
262
- },
263
248
  ];
264
249
 
265
250
  const answers = await prompts(questions, { onCancel() { process.exit(0); } });
package/src/pack.js CHANGED
@@ -1,6 +1,5 @@
1
- import { Transform } from 'stream';
2
1
  import fs from 'fs';
3
- import vinylFs from 'vinyl-fs';
2
+ import { readFile, writeFile } from 'fs/promises';
4
3
  import archiver from 'archiver';
5
4
  import { logger } from '@vcsuite/cli-logger';
6
5
  import { getPluginName } from './packageJsonHelpers.js';
@@ -11,29 +10,10 @@ import build from './build.js';
11
10
  * @param {string} name
12
11
  * @returns {Promise<void>}
13
12
  */
14
- function replaceAssets(name) {
15
- const replaceTransform = new Transform({
16
- objectMode: true,
17
- transform(data, encoding, callback) {
18
- data.contents = Buffer.from(String(data.contents)
19
- .replace(/\.?\/?(plugin-assets)\//g, `plugins/${name}/$1/`));
20
-
21
- callback(null, data);
22
- },
23
- });
24
-
25
- const context = getContext();
26
- const stream = vinylFs.src([resolveContext('dist', '*')], {
27
- cwd: context,
28
- allowEmpty: false,
29
- })
30
- .pipe(replaceTransform)
31
- .pipe(vinylFs.dest(resolveContext('dist')));
32
-
33
- return new Promise((resolve, reject) => {
34
- stream.on('finish', () => { resolve(); });
35
- stream.on('error', reject);
36
- });
13
+ async function replaceAssets(name) {
14
+ let indexJSContent = await readFile(getContext('dist', 'index.js'));
15
+ indexJSContent = indexJSContent.replace(/\.?\/?(plugin-assets)\//g, `plugins/${name}/$1/`);
16
+ await writeFile(getContext('dist', 'index.js'), indexJSContent);
37
17
  }
38
18
 
39
19
  /**
@@ -89,7 +69,6 @@ function zip(name) {
89
69
  ['README.md'],
90
70
  ['config.json'],
91
71
  ['dist', 'index.js'],
92
- ['dist', 'style.css'],
93
72
  ].forEach((fileArray) => {
94
73
  const file = resolveContext(...fileArray);
95
74
  if (fs.existsSync(file)) {
package/src/serve.js CHANGED
@@ -103,6 +103,13 @@ export default async function serve(options) {
103
103
  https: options.https,
104
104
  proxy,
105
105
  },
106
+ css: {
107
+ preprocessorOptions: {
108
+ sass: {
109
+ additionalData: "\n@import './node_modules/@vcmap/ui/src/styles/variables.scss'\n",
110
+ },
111
+ },
112
+ },
106
113
  });
107
114
 
108
115
  addMapConfigRoute(app, options.mapConfig, options.auth, options.config);
@@ -1,2 +0,0 @@
1
- node_modules/
2
- dist/