@vcmap/plugin-cli 2.1.18 → 3.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
@@ -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/) 16 and npm installed on your system
21
+ You need [nodejs](https://nodejs.org/en/) 18 and npm installed on your system
22
22
  to use this tool.
23
23
 
24
24
  ## Installation
@@ -51,6 +51,33 @@ All commands have (optional) cli options. Run `vcmplugin --help` or `vcmplugin h
51
51
  For `serve` and `preview` you can alternatively define a `vcs.config.js` in your plugin's root directory.
52
52
  For more information see [here](#vcm-config-js).
53
53
 
54
+ ## Folder structure
55
+
56
+ As of v3, all plugins must follow the same rudimentary folder structure, as depicted below:
57
+
58
+ ```
59
+ -| src/
60
+ -| index.js
61
+ -| package.json
62
+ -| README.md
63
+ ```
64
+
65
+ And for TS based plugins:
66
+
67
+ ```
68
+ -| src/
69
+ -| index.ts
70
+ -| package.json
71
+ -| README.md
72
+ -| tsconfig.json
73
+ ```
74
+
75
+ It is important to, not that the entry point for _building_ the plugin (and
76
+ the file which exports the default export for the plugin interface) **MUST** be
77
+ located at `./src/index.js` or `./src/index.ts` respectively. If you have created
78
+ your plugin using any version of the `@vcmap/plugins-cli`, this will already be
79
+ the case.
80
+
54
81
  ### 1. Creating a new plugin
55
82
 
56
83
  To create a new plugin template, run the following:
@@ -62,7 +89,7 @@ vcmplugin create
62
89
  This will open a command prompt helping you to create the basic [structure of a plugin](#vc-map-plugins).
63
90
  Be sure to check out the [peer dependecy section](#about-peer-dependencies) as well.
64
91
 
65
- Optionally, in step 7 of the create-prompt you can choose an existing plugin [@vcmap/hello-world](https://www.npmjs.com/package/@vcmap/hello-world) as template.
92
+ Optionally, in the create-prompt you can choose an existing plugin [@vcmap/hello-world](https://www.npmjs.com/package/@vcmap/hello-world) as a template.
66
93
 
67
94
  ### 2. Serving a plugin for development
68
95
 
@@ -0,0 +1,25 @@
1
+ // eslint-disable-next-line import/no-extraneous-dependencies
2
+ // const sharedLib = require('eslint-config-airbnb-typescript/lib/shared.js');
3
+
4
+ module.exports = {
5
+ root: true,
6
+ extends: ['@vcsuite/eslint-config/vue-ts'],
7
+ env: {
8
+ node: true,
9
+ },
10
+ rules: {
11
+ 'no-restricted-syntax': 'off',
12
+ },
13
+ overrides: [
14
+ {
15
+ files: ['*.ts', '*.vue'],
16
+ parserOptions: {
17
+ project: ['./tsconfig.json'],
18
+ },
19
+ rules: {
20
+ '@typescript-eslint/no-non-null-assertion': 'off',
21
+ },
22
+ },
23
+ ],
24
+ ignorePatterns: ['dist/', 'node_modules/'],
25
+ };
@@ -0,0 +1,78 @@
1
+ import { VcsPlugin, VcsUiApp, PluginConfigEditor } from '@vcmap/ui';
2
+ import { name, version, mapVersion } from '../package.json';
3
+
4
+ type PluginConfig = Record<never, never>;
5
+ type PluginState = Record<never, never>;
6
+
7
+ type MyPlugin = VcsPlugin<PluginConfig, PluginState>;
8
+
9
+ export default function plugin(
10
+ config: PluginConfig,
11
+ baseUrl: string,
12
+ ): MyPlugin {
13
+ // eslint-disable-next-line no-console
14
+ console.log(config, baseUrl);
15
+ return {
16
+ get name(): string {
17
+ return name;
18
+ },
19
+ get version(): string {
20
+ return version;
21
+ },
22
+ get mapVersion(): string {
23
+ return mapVersion;
24
+ },
25
+ initialize(vcsUiApp: VcsUiApp, state?: PluginState): Promise<void> {
26
+ // eslint-disable-next-line no-console
27
+ console.log(
28
+ 'Called before loading the rest of the current context. Passed in the containing Vcs UI App ',
29
+ vcsUiApp,
30
+ state,
31
+ );
32
+ return Promise.resolve();
33
+ },
34
+ onVcsAppMounted(vcsUiApp: VcsUiApp): void {
35
+ // eslint-disable-next-line no-console
36
+ console.log(
37
+ 'Called when the root UI component is mounted and managers are ready to accept components',
38
+ vcsUiApp,
39
+ );
40
+ },
41
+ /**
42
+ * should return all default values of the configuration
43
+ */
44
+ getDefaultOptions(): PluginConfig {
45
+ return {};
46
+ },
47
+ /**
48
+ * should return the plugin's serialization excluding all default values
49
+ */
50
+ toJSON(): PluginConfig {
51
+ // eslint-disable-next-line no-console
52
+ console.log('Called when serializing this plugin instance');
53
+ return {};
54
+ },
55
+ /**
56
+ * should return the plugins state
57
+ * @param {boolean} forUrl
58
+ * @returns {PluginState}
59
+ */
60
+ getState(forUrl?: boolean): PluginState {
61
+ // eslint-disable-next-line no-console
62
+ console.log('Called when collecting state, e.g. for create link', forUrl);
63
+ return {
64
+ prop: '*',
65
+ };
66
+ },
67
+ /**
68
+ * components for configuring the plugin and/ or custom items defined by the plugin
69
+ */
70
+ getConfigEditors(): PluginConfigEditor[] {
71
+ return [];
72
+ },
73
+ destroy(): void {
74
+ // eslint-disable-next-line no-console
75
+ console.log('hook to cleanup');
76
+ },
77
+ };
78
+ }
@@ -0,0 +1,179 @@
1
+ default:
2
+ image: gitlab.virtualcitysystems.de:5050/vcsuite/devops/gitlabrunner/node:18-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
+ - deploy
12
+ - version
13
+ - publish
14
+ - deployCluster
15
+
16
+ .template: &job_definition
17
+ only:
18
+ - /^(feature-.*|hotfix-.*|main|release-.*)$/
19
+ tags:
20
+ - linux-2.0
21
+
22
+ build:
23
+ <<: *job_definition
24
+ script:
25
+ - npm ci
26
+ - npm run ensure-types
27
+ before_script:
28
+ - mkdir -p ~/.ssh
29
+ - chmod 700 ~/.ssh
30
+ - echo "$SSH_RUNNER_KEY" | tr -d '\r' > ~/.ssh/id_rsa
31
+ - chmod 600 ~/.ssh/id_rsa
32
+ - ssh-keyscan gitlab.virtualcitysystems.de >> ~/.ssh/known_hosts
33
+ - chmod 644 ~/.ssh/known_hosts
34
+ - git config user.name "Gitlab Runner"
35
+ - git config user.email "gitlab-runner@vc.systems"
36
+ stage: build
37
+
38
+ .after_build_template: &after_build_definition
39
+ <<: *job_definition
40
+ variables:
41
+ GIT_STRATEGY: none
42
+
43
+ .staging_build_template: &staging_build_template
44
+ <<: *after_build_definition
45
+ except:
46
+ variables:
47
+ - $PUBLISH
48
+
49
+ lint:
50
+ <<: *after_build_definition
51
+ stage: test
52
+ script:
53
+ - npm run lint
54
+
55
+ type-check:
56
+ <<: *after_build_definition
57
+ stage: test
58
+ script:
59
+ - npm run type-check
60
+
61
+ test:
62
+ <<: *after_build_definition
63
+ stage: test
64
+ script:
65
+ - npm run coverage -- --reporter junit --outputFile test-report.xml
66
+ coverage: '/^Statements\s*:\s*([^%]+)/'
67
+ artifacts:
68
+ reports:
69
+ junit: test-report.xml
70
+
71
+ audit:
72
+ <<: *after_build_definition
73
+ stage: test
74
+ script:
75
+ - npm audit --production --audit-level=low
76
+
77
+ buildPreview:
78
+ <<: *staging_build_template
79
+ stage: bundle
80
+ script:
81
+ - npm run buildStagingApp
82
+
83
+ bundle:
84
+ <<: *after_build_definition
85
+ stage: bundle
86
+ only:
87
+ variables:
88
+ - $PUBLISH
89
+ refs:
90
+ - /^(main|release-v.*)$/
91
+ script:
92
+ - npm run build
93
+
94
+ deployStaging:
95
+ <<: *staging_build_template
96
+ stage: deploy
97
+ environment:
98
+ name: staging/$CI_COMMIT_REF_SLUG
99
+ url: http://$CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG.stagingcluster.intern.virtualcitysystems.de
100
+ on_stop: stopEnvironment
101
+ image:
102
+ name: gcr.io/kaniko-project/executor:debug
103
+ entrypoint: ['']
104
+ script:
105
+ - /kaniko/executor --context dist/ --dockerfile build/staging/Dockerfile --destination $CI_REGISTRY_IMAGE/staging:$CI_COMMIT_REF_SLUG
106
+ before_script:
107
+ - mkdir -p /kaniko/.docker
108
+ - echo "{\"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}}" > /kaniko/.docker/config.json
109
+
110
+ stopEnvironment:
111
+ stage: deploy
112
+ variables:
113
+ GIT_STRATEGY: none
114
+ image:
115
+ name: bitnami/kubectl:latest
116
+ entrypoint: ['']
117
+ tags:
118
+ - linux-2.0
119
+ script:
120
+ - echo "Stop environment staging/$CI_COMMIT_REF_NAME"
121
+ - echo "Delete namespace on k9s $CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG"
122
+ - kubectl config use-context vcsuite/cluster-management:agent
123
+ - kubectl delete namespace $CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG
124
+ when: manual
125
+ environment:
126
+ name: staging/$CI_COMMIT_REF_SLUG
127
+ action: stop
128
+
129
+ deployStagingCluster:
130
+ stage: deployCluster
131
+ except:
132
+ variables:
133
+ - $PUBLISH
134
+ inherit:
135
+ variables: false
136
+ variables:
137
+ STAGE_BRANCH: $CI_COMMIT_REF_SLUG
138
+ STAGE_PROJECT_NAME: $CI_PROJECT_PATH_SLUG
139
+ STAGE_REGISTRY_IMAGE: $CI_REGISTRY_IMAGE
140
+ STAGE_NAMESPACE: $CI_PROJECT_PATH_SLUG-$CI_COMMIT_REF_SLUG
141
+ trigger:
142
+ project: vcsuite/devops/manifests
143
+ branch: main
144
+
145
+ version:
146
+ <<: *after_build_definition
147
+ stage: version
148
+ only:
149
+ variables:
150
+ - $PUBLISH
151
+ refs:
152
+ - /^(main|release-v.*)$/
153
+ script:
154
+ - npm version patch -m "%s [skip-ci]"
155
+ - TAG=`git describe --abbrev=0`
156
+ - echo git push git@gitlab:vcsuite/"$CI_PROJECT_PATH".git
157
+ - git push git@gitlab:"$CI_PROJECT_PATH".git $TAG
158
+ - git push git@gitlab:"$CI_PROJECT_PATH".git HEAD:$CI_COMMIT_REF_NAME
159
+ before_script:
160
+ - mkdir -p ~/.ssh
161
+ - chmod 700 ~/.ssh
162
+ - echo "$SSH_RUNNER_KEY" | tr -d '\r' > ~/.ssh/id_rsa
163
+ - chmod 600 ~/.ssh/id_rsa
164
+ - ssh-keyscan gitlab >> ~/.ssh/known_hosts
165
+ - chmod 644 ~/.ssh/known_hosts
166
+ - git config user.name "Gitlab Runner"
167
+ - git config user.email "gitlab-runner@vc.systems"
168
+
169
+ publish:
170
+ <<: *after_build_definition
171
+ stage: publish
172
+ only:
173
+ refs:
174
+ - /^(main|release-v.*)$/
175
+ variables:
176
+ - $PUBLISH
177
+ script:
178
+ - npm config set '//registry.npmjs.org/:_authToken' "${NPM_TOKEN}"
179
+ - npm publish --registry https://registry.npmjs.org --access public
@@ -0,0 +1,34 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "es2022",
4
+ "module": "es2022",
5
+ "incremental": false,
6
+ "lib": ["esnext", "dom"],
7
+ "allowJs": true,
8
+ "checkJs": false,
9
+ "declaration": false,
10
+ "rootDir": ".",
11
+ /* Strict Type-Checking Options */
12
+ "strict": true,
13
+ "noImplicitAny": true,
14
+ "strictNullChecks": true,
15
+
16
+ /* Additional Checks */
17
+ "noImplicitReturns": false,
18
+ "noUnusedLocals": true,
19
+ "noUnusedParameters": true,
20
+ "noFallthroughCasesInSwitch": false,
21
+ "noImplicitThis": false,
22
+
23
+ /* Module Resolution Options */
24
+ "baseUrl": ".",
25
+ "moduleResolution": "node",
26
+ "resolveJsonModule": true,
27
+ "esModuleInterop": true,
28
+ "preserveSymlinks": true,
29
+ "allowSyntheticDefaultImports": true,
30
+ "skipLibCheck": true
31
+ },
32
+ "exclude": ["dist/", "build/", ".tests/"],
33
+ "include": ["src/"]
34
+ }
package/cli.js CHANGED
@@ -5,6 +5,7 @@ import { create, serve, build, pack, preview, update } from './index.js';
5
5
  import { version } from './src/pluginCliHelper.js';
6
6
  import setupMapUi from './src/setupMapUi.js';
7
7
  import buildStagingApp from './src/buildStagingApp.js';
8
+ import ensureTypes from './src/ensureTypes.js';
8
9
 
9
10
  program.version(version);
10
11
 
@@ -12,6 +13,7 @@ program
12
13
  .command('create')
13
14
  .summary('create new plugin')
14
15
  .defaultOptions()
16
+ .option('-t --typescript', 'Create a plugin using typescript')
15
17
  .safeAction(create);
16
18
 
17
19
  program
@@ -67,4 +69,6 @@ program
67
69
  )
68
70
  .safeAction(update);
69
71
 
72
+ program.command('ensure-types').action(ensureTypes);
73
+
70
74
  program.parse(process.argv);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vcmap/plugin-cli",
3
- "version": "2.1.18",
3
+ "version": "3.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",
@@ -38,11 +38,11 @@
38
38
  "sass": "1.32.13",
39
39
  "semver": "^7.5.4",
40
40
  "tar": "^6.1.15",
41
- "vite": "^4.4.9",
41
+ "vite": "^4.5.2",
42
42
  "vue-template-compiler": "~2.7.14"
43
43
  },
44
44
  "peerDependencies": {
45
- "@vcmap/ui": "^5.0.1",
45
+ "@vcmap/ui": "^5.1.0",
46
46
  "vue": "~2.7.14"
47
47
  },
48
48
  "peerDependenciesMeta": {
@@ -54,12 +54,13 @@
54
54
  }
55
55
  },
56
56
  "devDependencies": {
57
- "@vcsuite/eslint-config": "^3.0.5",
57
+ "@vcsuite/eslint-config": "^3.0.6",
58
58
  "eslint": "^8.38.0"
59
59
  },
60
60
  "eslintIgnore": [
61
61
  "node_modules",
62
- "assets/tests"
62
+ "assets/tests",
63
+ "assets/index.ts"
63
64
  ],
64
65
  "eslintConfig": {
65
66
  "extends": "@vcsuite/eslint-config/node",
package/src/build.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import path from 'path';
2
- import { rm, mkdir } from 'fs/promises';
3
- import fs from 'fs';
2
+ import { rm, mkdir } from 'node:fs/promises';
3
+ import fs from 'node:fs';
4
4
  import vue2 from '@vitejs/plugin-vue2';
5
5
  import vcsOl from '@vcmap/rollup-plugin-vcs-ol';
6
6
  import { logger } from '@vcsuite/cli-logger';
7
- import { getPluginEntry, getPluginName } from './packageJsonHelpers.js';
7
+ import { getEntry, getPluginName } from './packageJsonHelpers.js';
8
8
  import { getContext } from './context.js';
9
9
  import { executeUiNpm, resolveMapUi } from './hostingHelpers.js';
10
10
 
@@ -44,14 +44,7 @@ export async function getLibraryPaths(pluginName) {
44
44
  * @returns {Promise<void>}
45
45
  */
46
46
  export default async function buildModule(options) {
47
- const entry = await getPluginEntry();
48
- if (path.relative('src', entry).startsWith('.')) {
49
- logger.warning(`detected irregular entry ${entry}`);
50
- logger.warning(
51
- 'vuetify component resolution expects source files to be within "src"',
52
- );
53
- }
54
-
47
+ const entry = await getEntry();
55
48
  const pluginName = await getPluginName();
56
49
  const libraryPaths = await getLibraryPaths(pluginName);
57
50
  const distPath = path.join(getContext(), 'dist');
package/src/create.js CHANGED
@@ -1,13 +1,19 @@
1
1
  import fs from 'fs';
2
2
  import path from 'path';
3
3
  import prompts from 'prompts';
4
- import semver from 'semver';
4
+ import { minVersion, parse, valid } 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
8
  import { DepType, installDeps, setVcMapVersion } from './packageJsonHelpers.js';
9
9
  import { updatePeerDependencies } from './update.js';
10
- import { name, version, promiseExec, getDirname } from './pluginCliHelper.js';
10
+ import {
11
+ name,
12
+ version,
13
+ promiseExec,
14
+ getDirname,
15
+ peerDependencies as cliPeerDependencies,
16
+ } from './pluginCliHelper.js';
11
17
 
12
18
  /**
13
19
  * @typedef {Object} PluginTemplateOptions
@@ -21,6 +27,7 @@ import { name, version, promiseExec, getDirname } from './pluginCliHelper.js';
21
27
  * @property {string} template
22
28
  * @property {Array<string>} peerDeps
23
29
  * @property {boolean} gitlabCi
30
+ * @property {boolean} typescript
24
31
  */
25
32
 
26
33
  /**
@@ -29,15 +36,25 @@ import { name, version, promiseExec, getDirname } from './pluginCliHelper.js';
29
36
  * @returns {Object}
30
37
  */
31
38
  function createPackageJson(options) {
39
+ const typescriptScripts = options.typescript
40
+ ? {
41
+ 'type-check': 'vue-tsc --noEmit',
42
+ 'ensure-types': 'vcmplugin ensure-types',
43
+ }
44
+ : {};
45
+ const main = options.typescript ? 'dist/index.js' : 'src/index.js';
32
46
  return {
33
47
  name: options.name,
34
48
  version: options.version,
35
49
  description: options.description,
36
50
  type: 'module',
37
- main: 'src/index.js',
51
+ main,
38
52
  scripts: Object.assign(
39
- { prepublishOnly: 'vcmplugin build' },
53
+ {
54
+ prepublishOnly: 'vcmplugin build',
55
+ },
40
56
  ...options.scripts,
57
+ typescriptScripts,
41
58
  ),
42
59
  author: options.author,
43
60
  license: options.license,
@@ -52,7 +69,7 @@ function createPackageJson(options) {
52
69
  'CHANGELOG.md',
53
70
  ],
54
71
  exports: {
55
- '.': './src/index.js',
72
+ '.': options.typescript ? 'dist/index.js' : 'src/index.js',
56
73
  './dist': './dist/index.js',
57
74
  },
58
75
  };
@@ -142,10 +159,12 @@ async function createPluginTemplate(options, pluginPath) {
142
159
  const installEsLint = options.scripts.find((script) => script.lint);
143
160
  if (installEsLint) {
144
161
  packageJson.eslintIgnore = ['node_modules', 'dist', 'plugin-assets'];
145
- packageJson.eslintConfig = {
146
- root: true,
147
- extends: '@vcsuite/eslint-config/vue',
148
- };
162
+ if (!options.typescript) {
163
+ packageJson.eslintConfig = {
164
+ root: true,
165
+ extends: '@vcsuite/eslint-config/vue',
166
+ };
167
+ }
149
168
  packageJson.prettier = '@vcsuite/eslint-config/prettier.js';
150
169
  }
151
170
 
@@ -172,9 +191,10 @@ async function createPluginTemplate(options, pluginPath) {
172
191
  logger.debug('created src directory');
173
192
  }
174
193
 
194
+ const indexFile = options.typescript ? 'index.ts' : 'index.js';
175
195
  await fs.promises.copyFile(
176
- path.join(getDirname(), '..', 'assets', 'index.js'),
177
- path.join(pluginPath, 'src', 'index.js'),
196
+ path.join(getDirname(), '..', 'assets', indexFile),
197
+ path.join(pluginPath, 'src', indexFile),
178
198
  );
179
199
  }
180
200
 
@@ -196,7 +216,11 @@ async function createPluginTemplate(options, pluginPath) {
196
216
  (obj, key) => ({ ...obj, [key]: 'latest' }),
197
217
  {},
198
218
  );
199
- await updatePeerDependencies(peerDependencies, pluginPath);
219
+ const { major, minor } = parse(
220
+ minVersion(cliPeerDependencies['@vcmap/ui']),
221
+ );
222
+ const mapVersion = `^${major}.${minor}`;
223
+ await updatePeerDependencies(peerDependencies, pluginPath, { mapVersion });
200
224
  logger.spin('installing dependencies... (this may take a while)');
201
225
  const devDeps = [`${name}@${version}`];
202
226
  if (installEsLint) {
@@ -211,6 +235,9 @@ async function createPluginTemplate(options, pluginPath) {
211
235
  'jsdom',
212
236
  );
213
237
  }
238
+ if (options.typescript) {
239
+ devDeps.push('typescript', 'vue-tsc');
240
+ }
214
241
  await installDeps(devDeps, DepType.DEV, pluginPath);
215
242
  logger.success('Installed dependencies');
216
243
  } catch (e) {
@@ -280,8 +307,11 @@ async function createPlugin(options) {
280
307
  ]);
281
308
 
282
309
  if (options.gitlabCi) {
310
+ const gitlabFile = options.typescript
311
+ ? 'ts.gitlab-ci.yml'
312
+ : '.gitlab-ci.yml';
283
313
  await fs.promises.copyFile(
284
- path.join(getDirname(), '..', 'assets', '.gitlab-ci.yml'),
314
+ path.join(getDirname(), '..', 'assets', gitlabFile),
285
315
  path.join(pluginPath, '.gitlab-ci.yml'),
286
316
  );
287
317
  await fs.promises.cp(
@@ -291,6 +321,17 @@ async function createPlugin(options) {
291
321
  );
292
322
  }
293
323
 
324
+ if (options.typescript) {
325
+ await fs.promises.copyFile(
326
+ path.join(getDirname(), '..', 'assets', 'tsconfig.json'),
327
+ path.join(pluginPath, 'tsconfig.json'),
328
+ );
329
+ await fs.promises.copyFile(
330
+ path.join(getDirname(), '..', 'assets', 'eslintrc.cjs'),
331
+ path.join(pluginPath, '.eslintrc.cjs'),
332
+ );
333
+ }
334
+
294
335
  await createPluginTemplate(options, pluginPath);
295
336
  await setVcMapVersion(pluginPath);
296
337
  logger.success(`Created plugin ${options.name}`);
@@ -367,7 +408,7 @@ export default async function create() {
367
408
  name: 'version',
368
409
  message: 'Version',
369
410
  initial: '1.0.0',
370
- validate: (value) => !!semver.valid(value),
411
+ validate: (value) => !!valid(value),
371
412
  },
372
413
  {
373
414
  type: 'text',
@@ -397,6 +438,14 @@ export default async function create() {
397
438
  value: type,
398
439
  })),
399
440
  },
441
+ {
442
+ type: 'toggle',
443
+ name: 'typescript',
444
+ message: 'Create plugin using typescript (recommended).',
445
+ initial: true,
446
+ active: 'yes',
447
+ inactive: 'no',
448
+ },
400
449
  {
401
450
  type: 'select',
402
451
  name: 'template',
@@ -404,6 +453,13 @@ export default async function create() {
404
453
  initial: 0,
405
454
  choices: templateChoices,
406
455
  },
456
+ {
457
+ type: (prev, values) => (values.typescript && prev ? 'confirm' : null),
458
+ name: 'keepTs',
459
+ message:
460
+ 'The selected template is not in typescript. You will have to manually transform it. Keep typescript?',
461
+ initial: true,
462
+ },
407
463
  {
408
464
  type: 'multiselect',
409
465
  message: 'Add the following scripts to the package.json.',
@@ -434,5 +490,9 @@ export default async function create() {
434
490
  },
435
491
  });
436
492
 
493
+ if (answers.template && answers.typescript) {
494
+ answers.typescript = !!answers.keepTs;
495
+ }
496
+
437
497
  await createPlugin(answers);
438
498
  }
@@ -0,0 +1,16 @@
1
+ import { existsSync } from 'node:fs';
2
+ import { executeUiNpm, resolveMapUi } from './hostingHelpers.js';
3
+ import { getPackageJson } from './packageJsonHelpers.js';
4
+
5
+ export default async function ensureTypes() {
6
+ const packageJson = await getPackageJson();
7
+ if (packageJson.devDependencies?.typescript) {
8
+ const indexTs = resolveMapUi('index.d.ts');
9
+
10
+ if (!existsSync(indexTs)) {
11
+ console.log('building types');
12
+ await executeUiNpm('build-types -- --skipValidation');
13
+ }
14
+ console.log('types ensured');
15
+ }
16
+ }
@@ -5,7 +5,7 @@ import fs from 'fs';
5
5
  import path from 'path';
6
6
  import { logger } from '@vcsuite/cli-logger';
7
7
  import { getContext, resolveContext } from './context.js';
8
- import { getPluginEntry, getPluginName } from './packageJsonHelpers.js';
8
+ import { getPluginName, getEntry } from './packageJsonHelpers.js';
9
9
  import { promiseExec, getDirname } from './pluginCliHelper.js';
10
10
 
11
11
  /**
@@ -119,7 +119,7 @@ export async function printVcmapUiVersion() {
119
119
  export async function reWriteAppConfig(appConfig, pluginConfig, production) {
120
120
  const name = await getPluginName();
121
121
  pluginConfig.name = name;
122
- pluginConfig.entry = production ? 'dist/index.js' : await getPluginEntry();
122
+ pluginConfig.entry = production ? 'dist/index.js' : await getEntry();
123
123
  appConfig.modules = appConfig.modules ?? [];
124
124
  appConfig.modules.forEach((config) => {
125
125
  if (Array.isArray(config.plugins)) {
@@ -3,7 +3,7 @@ import { writeFile, readFile } from 'fs/promises';
3
3
  import { parse, satisfies, validRange } from 'semver';
4
4
  import { logger } from '@vcsuite/cli-logger';
5
5
  import path from 'path';
6
- import { getContext } from './context.js';
6
+ import { getContext, resolveContext } from './context.js';
7
7
  import { promiseExec } from './pluginCliHelper.js';
8
8
 
9
9
  /** @type {Object|null} */
@@ -42,17 +42,15 @@ export async function getPluginName() {
42
42
  }
43
43
 
44
44
  /**
45
+ * Gets the entry of the package
45
46
  * @returns {Promise<string>}
46
47
  */
47
- export async function getPluginEntry() {
48
- const { main, module, type } = await getPackageJson();
49
-
50
- let entry = type === 'module' ? module : null;
51
- entry = entry || main;
52
- if (!entry) {
53
- throw new Error('Could not determine entry point');
48
+ export async function getEntry() {
49
+ const isTS = resolveContext('src', 'index.ts');
50
+ if (existsSync(isTS)) {
51
+ return 'src/index.ts';
54
52
  }
55
- return entry;
53
+ return 'src/index.js';
56
54
  }
57
55
 
58
56
  /**
@@ -17,7 +17,7 @@ export function getDirname() {
17
17
  * @type {string} version
18
18
  * @type {string} name
19
19
  */
20
- export const { version, name } = JSON.parse(
20
+ export const { version, name, peerDependencies } = JSON.parse(
21
21
  fs.readFileSync(path.join(getDirname(), '..', 'package.json')).toString(),
22
22
  );
23
23
 
package/src/update.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { logger } from '@vcsuite/cli-logger';
2
- import { valid } from 'semver';
2
+ import { validRange } from 'semver';
3
3
  import {
4
4
  checkVcMapVersion,
5
5
  DepType,
@@ -26,7 +26,7 @@ export async function updatePeerDependencies(
26
26
  pluginPath,
27
27
  options = {},
28
28
  ) {
29
- if (options.mapVersion && !valid(options.mapVersion)) {
29
+ if (options.mapVersion && !validRange(options.mapVersion)) {
30
30
  logger.error(
31
31
  `The mapVersion ${options.mapVersion} is not valid. Using 'latest' instead`,
32
32
  );