Skip to content

Commit

Permalink
converted generator into an ESM package, bumped version of yeoman-gen…
Browse files Browse the repository at this point in the history
…erator to ^6.0.0

bumped typescript version to ~4.7.0 to be able to
 * set tsConfig options 'module' and 'moduleResolution' to value of 'Node16', see https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html
 * deal with the transitive dependency 'mem-fs-editor' in version 10.0.x containing function alias assignments including type argument assignments, see https://www.typescriptlang.org/docs/handbook/release-notes/typescript-4-7.html#instantiation-expressions

Signed-off-by: Christian Schneider <[email protected]>
  • Loading branch information
sailingKieler committed Dec 6, 2023
1 parent c44e654 commit ef0d095
Show file tree
Hide file tree
Showing 6 changed files with 747 additions and 2,248 deletions.
16 changes: 8 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,9 @@
"version": "0.1.36",
"engines": {
"yarn": ">=1.7.0 <2",
"node": ">=14.18.0"
"node": ">=16.7.0"
},
"type": "module",
"description": "Helps to setup the project structure for developing extensions to the Theia IDE",
"repository": {
"type": "git",
Expand All @@ -20,28 +21,27 @@
"author": "TypeFox",
"license": "EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0",
"dependencies": {
"fs-extra": "^10.0.0",
"request": "^2.88.2",
"tar": "^6.1.1",
"yeoman-generator": "^5.0.0"
"yeoman-generator": "^6.0.0"
},
"devDependencies": {
"@types/request": "^2.48.0",
"@types/tar": "^6.1.1",
"@types/mocha": "^5.2.7",
"@types/yeoman-generator": "^5.0.0",
"mocha": "^6.2.0",
"rimraf": "^3.0.0",
"typescript": "~4.5.5",
"typescript": "~4.7.0",
"yeoman-assert": "^3.1.1",
"yeoman-environment": "^3.0.0",
"yeoman-test": "^5.0.0"
"yeoman-test": "^6.0.0"
},
"files": [
"generators",
"templates"
],
"scripts": {
"prepare": "yarn run clean && yarn run build",
"clean": "rimraf lib",
"clean": "rimraf generators",
"build": "tsc",
"watch": "tsc -w",
"test": "mocha",
Expand Down
90 changes: 53 additions & 37 deletions src/app/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/

import type execa = require('execa');
import path = require('path');
import Base = require('yeoman-generator');
const request = require('request');
const tar = require('tar');
const fs = require('fs-extra');
import * as fs from 'node:fs/promises';
import * as path from 'node:path';
import * as url from 'node:url';
import request from 'request';
import tar from 'tar';
import Base, { BaseFeatures, BaseOptions } from 'yeoman-generator/typed';

const glspExamplesRepositoryTag = "generator-latest";
const backend = "backend";
Expand All @@ -40,13 +40,26 @@ enum TemplateType {
Node = 'node',
}

module.exports = class TheiaExtension extends Base {
type ExtensionOptions = {
extensionType: ExtensionType;
extensionName?: string;
browser: boolean;
electron: boolean;
standalone?: boolean;
templateType: string;
"theia-version": string;
"lerna-version": string;
githubURL: string;
params: unknown;
}

export default class TheiaExtension extends Base<BaseOptions & ExtensionOptions> {

params: {
author: string
version: string
license: string
extensionName: string
extensionName?: string
extensionType: string
templateType: string
unscopedExtensionName: string
Expand All @@ -67,13 +80,14 @@ module.exports = class TheiaExtension extends Base {
rootscripts: string
containsTests: boolean
electronMainLocation: string
backend?: boolean
};

constructor(args: string | string[], options: Base.GeneratorOptions) {
constructor(args: string | string[], options: BaseOptions & ExtensionOptions) {
// For v5 generators the '<npm|pnpm|yarn> install' task is implicitely invoked by 'yeoman-environment' since 'yeoman-environment@3', see
// https://github.com/yeoman/environment/commit/ab9582a70073203c7a6b58fb6dbf1f4eba249d48#diff-54bc5f4bd40f22e081d54b6c20bbf2523e438cf2f2716b91714a1f596e4d87cd
// since we spawn the pm processes on our own in 'install()', we need to declare that here in order to avoid errors because of concurrent runs!
super(args, options, { customInstallTask: true });
super(args, options, <BaseFeatures>{ customInstallTask: true });

this.argument('extensionName', {
type: String,
Expand Down Expand Up @@ -155,12 +169,12 @@ module.exports = class TheiaExtension extends Base {
}

path() {
this.sourceRoot(__dirname + '/../../templates');
this.sourceRoot(path.dirname(url.fileURLToPath(import.meta.url)) + '/../../templates');
}

async prompting() {
let extensionType = (this.options as any).extensionType;
const inExtensionType = (<any>Object).values(ExtensionType).includes(extensionType);
let extensionType = this.options.extensionType;
const inExtensionType = Object.values(ExtensionType).includes(extensionType);
if ((extensionType === undefined) || !inExtensionType) {
if (!(extensionType === undefined)) {
this.log(`Invalid extension type: ${extensionType}`);
Expand All @@ -179,7 +193,7 @@ module.exports = class TheiaExtension extends Base {
{ value: ExtensionType.DiagramEditor, name: 'DiagramEditor' }
]
});
(this.options as any).extensionType = answer.type;
this.options.extensionType = answer.type;

if (answer.type === ExtensionType.DiagramEditor) {
const answer = await this.prompt({
Expand All @@ -193,7 +207,7 @@ module.exports = class TheiaExtension extends Base {
});
let template = answer.backend;

(this.options as any).templateType = template;
this.options.templateType = template;

if(template === TemplateType.Java) {
this.log('\x1b[32m%s\x1b[0m', 'The template will use an EMF source model on the server and generate a Theia extension ✓')
Expand All @@ -204,22 +218,22 @@ module.exports = class TheiaExtension extends Base {
}
}

let extensionName = (this.options as any).extensionName;
let extensionName = this.options.extensionName;
// extensionName is not used within the DiagramEditor
if (!extensionName && this.options.extensionType !== ExtensionType.DiagramEditor) {
const answer = await this.prompt({
type: 'input',
name: 'name',
message: 'The extension\'s name',
default: (this.options as any).extensionType
default: this.options.extensionType
});
(this.options as any).extensionName = answer.name;
this.options.extensionName = answer.name;
}
}

configuring() {
const options = this.options as any
const extensionName = options.extensionName as string
const options = this.options
const extensionName = options.extensionName
let unscopedExtensionName = ''
let extensionPath = ''
let extensionPrefix = ''
Expand All @@ -234,7 +248,7 @@ module.exports = class TheiaExtension extends Base {
const templateType = options.templateType;
const githubURL = options.githubURL;
this.log(extensionPrefix);
this.params = {
this.params = <any>{
...options,
extensionName,
unscopedExtensionName,
Expand All @@ -245,7 +259,7 @@ module.exports = class TheiaExtension extends Base {
githubURL,
theiaVersion: options["theia-version"],
lernaVersion: options["lerna-version"],
backend: options["extensionType"] === ExtensionType.Backend,
backend: options.extensionType === ExtensionType.Backend,
electronMainLocation: this.getElectronMainLocation(options["theia-version"])
}
this.params.dependencies = '';
Expand All @@ -259,13 +273,13 @@ module.exports = class TheiaExtension extends Base {
this.params.rootscripts =`,\n "test": "cd ${this.params.extensionPath} && yarn test"`;
this.params.containsTests = true;
}
options.params = this.params
options.params = this.params // piggyback the params to options and hand them over to the child generators
if (!options.standalone && this.params.extensionType !== ExtensionType.DiagramEditor) {
if (options.browser) {
this.composeWith(require.resolve('../browser'), this.options);
this.composeWith('../browser/index.js', this.options);
}
if (options.electron) {
this.composeWith(require.resolve('../electron'), this.options);
this.composeWith('../electron/index.js', this.options);
}
}
if (options.standalone) {
Expand Down Expand Up @@ -477,7 +491,7 @@ module.exports = class TheiaExtension extends Base {

/** DiagramEditor */
if (this.params.extensionType === ExtensionType.DiagramEditor) {
const baseDir = `./glsp-examples-${glspExamplesRepositoryTag}`;
const baseDir = `glsp-examples-${glspExamplesRepositoryTag}`;
let templatePath = '';
if(this.params.templateType == TemplateType.Java) {
templatePath = '/project-templates/java-emf-theia';
Expand All @@ -487,13 +501,18 @@ module.exports = class TheiaExtension extends Base {
return;
}

return new Promise<void>((resolve) => {
request.get(`https://github.com/eclipse-glsp/glsp-examples/archive/refs/tags/${glspExamplesRepositoryTag}.tar.gz`).pipe(tar.x().on('close',() => {
fs.copy(baseDir+'/README.md', './README.md');
fs.copy(baseDir+templatePath, './').then(() => {
fs.rm(baseDir, { recursive: true });
const dest = this.destinationPath.bind(this);

return new Promise<void>((resolve, reject) => {
request.get(`https://github.com/eclipse-glsp/glsp-examples/archive/refs/tags/${glspExamplesRepositoryTag}.tar.gz`).pipe(tar.x({ cwd: dest() }).on('close', async () => {
try {
await fs.cp(dest(baseDir, 'README.md'), dest('./README.md'));
await fs.cp(dest(baseDir, templatePath), dest(), { recursive: true });
await fs.rm(dest(baseDir), { recursive: true });
resolve();
});
} catch (e) {
reject(e);
}
}));
});
}
Expand All @@ -504,9 +523,9 @@ module.exports = class TheiaExtension extends Base {
}

async install() {
if (!(this.options as any).skipInstall) {
if (!this.options.skipInstall) {
this.log('Installing dependencies');
const command: execa.ExecaChildProcess = this.spawnCommand('yarn', []);
const command = this.spawn('yarn', []);

if (this.params.extensionType == ExtensionType.DiagramEditor) {
command.on('close', (code:number) => {
Expand Down Expand Up @@ -553,6 +572,3 @@ module.exports = class TheiaExtension extends Base {
}
}
}

module.exports.ExtensionType = ExtensionType;

11 changes: 6 additions & 5 deletions src/browser/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,22 +14,23 @@
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/

import Base  = require('yeoman-generator');
import * as path from 'node:path';
import * as url from 'node:url';
import Base, { BaseOptions } from 'yeoman-generator';

module.exports = class TheiaBrowser extends Base {
export default class TheiaBrowser extends Base<BaseOptions & { params: unknown }> {

path() {
this.sourceRoot(__dirname + '/../../templates')
this.sourceRoot(path.dirname(url.fileURLToPath(import.meta.url)) + '/../../templates')
}

writing() {
const params = (this.options as any).params
this.fs.copyTpl(
this.templatePath('app-browser-package.json'),
this.destinationPath('browser-app/package.json'),
{
appMode: 'browser',
params
params: this.options.params
}
);
}
Expand Down
10 changes: 6 additions & 4 deletions src/electron/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
********************************************************************************/

import Base  = require('yeoman-generator');
import * as path from 'node:path';
import * as url from 'node:url';
import Base, { BaseOptions } from 'yeoman-generator';

module.exports = class TheiaElectron extends Base {
export default class TheiaElectron extends Base<BaseOptions & { params: unknown }> {

path() {
this.sourceRoot(__dirname + '/../../templates')
this.sourceRoot(path.dirname(url.fileURLToPath(import.meta.url)) + '/../../templates')
}

writing() {
Expand All @@ -28,7 +30,7 @@ module.exports = class TheiaElectron extends Base {
this.destinationPath('electron-app/package.json'),
{
appMode: 'electron',
params: (this.options as any).params
params: this.options.params
}
);
}
Expand Down
5 changes: 3 additions & 2 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,9 @@
"emitDecoratorMetadata": true,
"skipLibCheck": true,
"downlevelIteration": true,
"module": "commonjs",
"moduleResolution": "node",
"module": "Node16",
"moduleResolution": "Node16",
"allowSyntheticDefaultImports": false, // to force us writing proper imports of contents of third-party CommonJS modules
"target": "es6",
"lib": [
"es6",
Expand Down
Loading

0 comments on commit ef0d095

Please sign in to comment.