@vcmap/plugin-cli 2.0.6 → 2.0.9

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,8 +8,10 @@ stages:
8
8
  - build
9
9
  - test
10
10
  - bundle
11
+ - deploy
11
12
  - version
12
13
  - publish
14
+ - deployCluster
13
15
 
14
16
  .template: &job_definition
15
17
  only:
@@ -20,7 +22,6 @@ stages:
20
22
  build:
21
23
  <<: *job_definition
22
24
  script:
23
- - npm set registry 'http://npmregistry:4873'
24
25
  - npm ci
25
26
  before_script:
26
27
  - mkdir -p ~/.ssh
@@ -38,6 +39,12 @@ build:
38
39
  variables:
39
40
  GIT_STRATEGY: none
40
41
 
42
+ .staging_build_template: &staging_build_template
43
+ <<: *after_build_definition
44
+ except:
45
+ variables:
46
+ - $PUBLISH
47
+
41
48
  lint:
42
49
  <<: *after_build_definition
43
50
  stage: test
@@ -50,12 +57,74 @@ audit:
50
57
  script:
51
58
  - npm audit --production --audit-level=low
52
59
 
60
+ buildPreview:
61
+ <<: *staging_build_template
62
+ stage: bundle
63
+ script:
64
+ - npm run buildStagingApp
65
+
53
66
  bundle:
54
67
  <<: *after_build_definition
55
68
  stage: bundle
69
+ only:
70
+ variables:
71
+ - $PUBLISH
72
+ refs:
73
+ - /^(main|release-v.*)$/
56
74
  script:
57
75
  - npm run build
58
76
 
77
+ deployStaging:
78
+ <<: *staging_build_template
79
+ stage: deploy
80
+ environment:
81
+ name: staging/$CI_COMMIT_REF_SLUG
82
+ url: http://$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG.stagingcluster.intern.virtualcitysystems.de
83
+ on_stop: stopEnvironment
84
+ image:
85
+ name: gcr.io/kaniko-project/executor:debug
86
+ entrypoint: [ "" ]
87
+ script:
88
+ - /kaniko/executor --context dist/ --dockerfile build/staging/Dockerfile --destination $CI_REGISTRY_IMAGE/staging:$CI_COMMIT_REF_SLUG
89
+ before_script:
90
+ - mkdir -p /kaniko/.docker
91
+ - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
92
+
93
+ stopEnvironment:
94
+ stage: deploy
95
+ variables:
96
+ GIT_STRATEGY: none
97
+ image:
98
+ name: bitnami/kubectl:latest
99
+ entrypoint: [""]
100
+ tags:
101
+ - linux-2.0
102
+ script:
103
+ - echo "Stop environment staging/$CI_COMMIT_REF_NAME"
104
+ - echo "Delete namespace on k9s $CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG"
105
+ - kubectl config use-context vcsuite/cluster-management:agent
106
+ - kubectl delete namespace $CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG
107
+ when: manual
108
+ environment:
109
+ name: staging/$CI_COMMIT_REF_SLUG
110
+ action: stop
111
+
112
+ deployStagingCluster:
113
+ stage: deployCluster
114
+ except:
115
+ variables:
116
+ - $PUBLISH
117
+ inherit:
118
+ variables: false
119
+ variables:
120
+ STAGE_BRANCH: $CI_COMMIT_REF_SLUG
121
+ STAGE_PROJECT_NAME: $CI_PROJECT_PATH_SLUG
122
+ STAGE_REGISTRY_IMAGE: $CI_REGISTRY_IMAGE
123
+ STAGE_NAMESPACE: $CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG
124
+ trigger:
125
+ project: vcsuite/devops/manifests
126
+ branch: main
127
+
59
128
  version:
60
129
  <<: *after_build_definition
61
130
  stage: version
@@ -89,5 +158,5 @@ publish:
89
158
  variables:
90
159
  - $PUBLISH
91
160
  script:
92
- - npm config set '//npmregistry:4873/:_authToken' "${VERDACCIO_TOKEN}"
93
- - npm publish --registry http://npmregistry:4873
161
+ - npm config set '//registry.npmjs.org/:_authToken' "${NPM_TOKEN}"
162
+ - npm publish --registry https://registry.npmjs.org --access public
@@ -0,0 +1,2 @@
1
+ FROM httpd:2-buster
2
+ COPY * /usr/local/apache2/htdocs/
@@ -19,10 +19,10 @@
19
19
  </template>
20
20
 
21
21
  <script>
22
- import { inject } from '@vue/composition-api';
22
+ import { inject } from 'vue';
23
23
  import { VcsButton } from '@vcmap/ui';
24
24
 
25
- export const windowId = 'hello_world_window_id';
25
+ export const windowId = 'hello_world_window_id_plugin-cli';
26
26
 
27
27
  export default {
28
28
  name: 'HelloWorld',
@@ -6,6 +6,7 @@ import HelloWorld, { windowId } from './helloWorld.vue';
6
6
  * @param {T} config - the configuration of this plugin instance, passed in from the app.
7
7
  * @returns {import("@vcmap/ui/src/vcsUiApp").VcsPlugin<T>}
8
8
  * @template {Object} T
9
+ * @template {Object} S
9
10
  */
10
11
  export default function(config) {
11
12
  return {
@@ -13,9 +14,10 @@ export default function(config) {
13
14
  get version() { return version; },
14
15
  /**
15
16
  * @param {import("@vcmap/ui").VcsUiApp} vcsUiApp
17
+ * @param {S=} state
16
18
  * @returns {Promise<void>}
17
19
  */
18
- initialize: async (vcsUiApp) => {
20
+ initialize: async (vcsUiApp, state) => {
19
21
  console.log('Called before loading the rest of the current context. Passed in the containing Vcs UI App ');
20
22
  },
21
23
  /**
@@ -34,22 +36,30 @@ export default function(config) {
34
36
  },
35
37
  }, name);
36
38
  },
39
+ /**
40
+ * @returns {Promise<S>}
41
+ */
42
+ getState: async () => {
43
+ console.log('Called when serializing this plugin instance');
44
+ return {};
45
+ },
37
46
  /**
38
47
  * @returns {Promise<T>}
39
48
  */
40
49
  toJSON: async () => {
41
50
  console.log('Called when serializing this plugin instance');
51
+ return {};
42
52
  },
43
53
  i18n: {
44
54
  en: {
45
55
  helloWorld: {
46
- helloWorld: 'Hello World',
56
+ helloWorld: '@vcmap/plugin-cli - Hello World',
47
57
  close: 'Close',
48
58
  },
49
59
  },
50
60
  de: {
51
61
  helloWorld: {
52
- helloWorld: 'Hallo Welt',
62
+ helloWorld: '@vcmap/plugin-cli - Hallo Welt',
53
63
  close: 'Schließen',
54
64
  },
55
65
  },
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.6",
3
+ "version": "2.0.9",
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.19.6",
38
- "vinyl-fs": "^3.0.3",
39
- "vite": "^2.9.12",
37
+ "unplugin-vue-components": "^0.21.1",
38
+ "vite": "^2.9.14",
40
39
  "vite-plugin-vue2": "^2.0.1",
41
- "vue-template-compiler": "~2.6.14"
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(),
@@ -93,5 +97,5 @@ export default async function buildModule(options) {
93
97
  },
94
98
  };
95
99
  const { buildLibrary } = await import('@vcmap/ui/build/buildHelpers.js');
96
- await buildLibrary(config, '', 'index', '', true);
100
+ await buildLibrary(config, options.outputPath ?? '', 'index', '', true);
97
101
  }
@@ -0,0 +1,60 @@
1
+ import { cp, copyFile, writeFile, rm, mkdir } from 'fs/promises';
2
+ import path from 'path';
3
+ import fs from 'fs';
4
+ import { getContext, resolveContext } 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
+ import { replaceAssets } from './pack.js';
10
+
11
+
12
+ /**
13
+ * creates production preview application in the dist folder based on the @vcmap/ui default map configuration.
14
+ * @returns {Promise<void>}
15
+ */
16
+ export default async function buildStagingApp() {
17
+ const pluginName = await getPluginName();
18
+ const distPath = path.join(getContext(), 'dist');
19
+ // Clear dist folder
20
+ await rm(distPath, { recursive: true, force: true });
21
+ await mkdir(distPath);
22
+ await setupMapUi();
23
+ const { buildPluginsForPreview } = await import('@vcmap/ui/build/buildHelpers.js');
24
+ await buildPluginsForPreview(getDefaultConfig(), true);
25
+ await mkdir(path.join(distPath, 'plugins', pluginName), { recursive: true });
26
+
27
+ await buildModule({ outputPath: `plugins/${pluginName}`, keepDistFolder: true });
28
+
29
+ // copy assets folder if exists
30
+ if (fs.existsSync(resolveContext('plugin-assets'))) {
31
+ await replaceAssets(path.join(distPath, 'plugins', pluginName, 'index.js'), pluginName);
32
+ await cp(
33
+ resolveContext('plugin-assets'),
34
+ path.join(distPath, 'plugins', pluginName, 'plugin-assets'),
35
+ { recursive: true },
36
+ );
37
+ }
38
+
39
+ await copyFile(
40
+ path.join(getContext(), 'node_modules', '@vcmap', 'ui', 'dist', 'index.html'),
41
+ path.join(distPath, 'index.html'),
42
+ );
43
+ const config = await getConfigJson();
44
+ // update Entry
45
+ const pluginConfig = config.plugins.find(p => p.name === pluginName);
46
+ if (pluginConfig) {
47
+ pluginConfig.entry = `plugins/${pluginName}/index.js`;
48
+ }
49
+ await writeFile(path.join(distPath, 'map.config.json'), JSON.stringify(config, null, 2));
50
+ await cp(
51
+ path.join(getContext(), 'node_modules', '@vcmap', 'ui', 'dist', 'assets'),
52
+ path.join(distPath, 'assets'),
53
+ { recursive: true },
54
+ );
55
+ await cp(
56
+ path.join(getContext(), 'node_modules', '@vcmap', 'ui', 'config'),
57
+ path.join(distPath, 'config'),
58
+ { recursive: true },
59
+ );
60
+ }
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: { buildStagingApp: 'vcmplugin buildStagingApp' }, selected: true },
173
172
  { title: 'lint', value: { lint: 'eslint "{src,tests}/**/*.{js,vue}"' }, selected: true },
174
173
  ];
175
174
 
@@ -177,7 +176,8 @@ export default async function create() {
177
176
  { title: '@vcmap/core', value: '@vcmap/core' },
178
177
  { title: '@vcmap/cesium', value: '@vcmap/cesium' },
179
178
  { title: 'ol', value: 'ol@~6.13.0' },
180
- { title: '@vue/composition-api', value: '@vue/composition-api@~1.4.5' },
179
+ { title: 'vue', value: 'vue@~2.7.3' },
180
+ { title: 'vuetify', value: 'vue@~2.6.7' },
181
181
  ];
182
182
 
183
183
  const questions = [
@@ -239,12 +239,6 @@ export default async function create() {
239
239
  value: type,
240
240
  })),
241
241
  },
242
- {
243
- type: 'text',
244
- name: 'registry',
245
- message: 'Set default npm registry',
246
- initial: 'https://registry.npmjs.org',
247
- },
248
242
  {
249
243
  name: 'peerDeps',
250
244
  type: 'multiselect',
@@ -252,14 +246,6 @@ export default async function create() {
252
246
  choices: peerDependencyChoices,
253
247
  hint: '- Space to select. Enter to submit',
254
248
  },
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
249
  ];
264
250
 
265
251
  const answers = await prompts(questions, { onCancel() { process.exit(0); } });
package/src/pack.js CHANGED
@@ -1,39 +1,20 @@
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';
7
- import { resolveContext, getContext } from './context.js';
6
+ import { resolveContext } from './context.js';
8
7
  import build from './build.js';
9
8
 
10
9
  /**
10
+ * @param {string} fileName
11
11
  * @param {string} name
12
12
  * @returns {Promise<void>}
13
13
  */
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
- });
14
+ export async function replaceAssets(fileName, name) {
15
+ let fileContent = await readFile(fileName, { encoding: 'utf8' });
16
+ fileContent = fileContent.replace(/\.?\/?(plugin-assets)\//g, `plugins/${name}/$1/`);
17
+ await writeFile(fileName, fileContent);
37
18
  }
38
19
 
39
20
  /**
@@ -89,7 +70,6 @@ function zip(name) {
89
70
  ['README.md'],
90
71
  ['config.json'],
91
72
  ['dist', 'index.js'],
92
- ['dist', 'style.css'],
93
73
  ].forEach((fileArray) => {
94
74
  const file = resolveContext(...fileArray);
95
75
  if (fs.existsSync(file)) {
@@ -114,7 +94,7 @@ export default async function pack() {
114
94
  const pluginName = await getPluginName();
115
95
  logger.spin(`building plugin: ${pluginName}`);
116
96
  await build({});
117
- await replaceAssets(pluginName);
97
+ await replaceAssets(resolveContext('dist', 'index.js'), pluginName);
118
98
  logger.debug('fixed asset paths');
119
99
  await ensureConfigJson();
120
100
  logger.debug('ensuring config.json');
@@ -1,2 +0,0 @@
1
- node_modules/
2
- dist/