16
16
17
17
import path = require( 'path' ) ;
18
18
import Base = require( 'yeoman-generator' ) ;
19
+ const request = require ( 'request' ) ;
20
+ const tar = require ( 'tar' ) ;
21
+ const fs = require ( 'fs-extra' ) ;
22
+
23
+ const glspExamplesRepositoryTag = "generator-latest" ;
19
24
20
25
enum ExtensionType {
21
26
HelloWorld = 'hello-world' ,
22
27
Widget = 'widget' ,
23
28
LabelProvider = 'labelprovider' ,
24
29
TreeEditor = 'tree-editor' ,
25
30
Empty = 'empty' ,
26
- Backend = 'backend'
31
+ Backend = 'backend' ,
32
+ DiagramEditor = 'diagram-editor'
33
+ }
34
+
35
+ enum TemplateType {
36
+ Java = 'java' ,
37
+ Node = 'node' ,
27
38
}
28
39
29
40
module . exports = class TheiaExtension extends Base {
@@ -34,6 +45,7 @@ module.exports = class TheiaExtension extends Base {
34
45
license : string
35
46
extensionName : string
36
47
extensionType : string
48
+ templateType : string
37
49
unscopedExtensionName : string
38
50
githubURL : string
39
51
extensionPrefix : string
@@ -156,18 +168,42 @@ module.exports = class TheiaExtension extends Base {
156
168
{ value : ExtensionType . LabelProvider , name : 'LabelProvider' } ,
157
169
{ value : ExtensionType . TreeEditor , name : 'TreeEditor' } ,
158
170
{ value : ExtensionType . Backend , name : 'Backend Communication' } ,
159
- { value : ExtensionType . Empty , name : 'Empty' }
171
+ { value : ExtensionType . Empty , name : 'Empty' } ,
172
+ { value : ExtensionType . DiagramEditor , name : 'DiagramEditor' }
160
173
]
161
174
} ) ;
162
175
( this . options as any ) . extensionType = answer . type ;
176
+
177
+ if ( answer . type === ExtensionType . DiagramEditor ) {
178
+ const answer = await this . prompt ( {
179
+ type : 'list' ,
180
+ name : 'backend' ,
181
+ message : 'Which GLSP backend do you want to use, i.e. in which language do you prefer to develop your GLSP server?' ,
182
+ choices : [
183
+ { value : TemplateType . Java , name : 'Java (requires maven!)' } ,
184
+ { value : TemplateType . Node , name : 'Node (TypeScript)' } ,
185
+ ]
186
+ } ) ;
187
+ let template = answer . backend ;
188
+
189
+ ( this . options as any ) . templateType = template ;
190
+
191
+ if ( template === TemplateType . Java ) {
192
+ this . log ( '\x1b[32m%s\x1b[0m' , 'The template will use an EMF source model on the server and generate a Theia extension ✓' )
193
+ }
194
+ if ( template === TemplateType . Node ) {
195
+ this . log ( '\x1b[32m%s\x1b[0m' , 'The template will use a JSON based source model, node as a server and generate a Theia extension ✓' )
196
+ }
197
+ }
163
198
}
164
199
165
200
let extensionName = ( this . options as any ) . extensionName ;
166
- if ( ! extensionName ) {
201
+ // extensionName is not used within the DiagramEditor
202
+ if ( ! extensionName && this . options . extensionType !== ExtensionType . DiagramEditor ) {
167
203
const answer = await this . prompt ( {
168
204
type : 'input' ,
169
205
name : 'name' ,
170
- message : " The extension's name" ,
206
+ message : ' The extension\ 's name' ,
171
207
default : ( this . options as any ) . extensionType
172
208
} ) ;
173
209
( this . options as any ) . extensionName = answer . name ;
@@ -177,12 +213,18 @@ module.exports = class TheiaExtension extends Base {
177
213
configuring ( ) {
178
214
const options = this . options as any
179
215
const extensionName = options . extensionName as string
180
- const unscopedExtensionName = extensionName [ 0 ] === '@' ?
181
- extensionName . substring ( extensionName . indexOf ( '/' ) + 1 ) :
182
- extensionName ;
183
- const extensionPath = path . normalize ( unscopedExtensionName ) . replace ( '/' , '-' ) ;
184
- const extensionPrefix = extensionPath . split ( '-' ) . map ( name => this . _capitalize ( name ) ) . join ( '' ) ;
216
+ let unscopedExtensionName = ''
217
+ let extensionPath = ''
218
+ let extensionPrefix = ''
219
+ if ( extensionName ) {
220
+ unscopedExtensionName = extensionName [ 0 ] === '@' ?
221
+ extensionName . substring ( extensionName . indexOf ( '/' ) + 1 ) :
222
+ extensionName ;
223
+ extensionPath = path . normalize ( unscopedExtensionName ) . replace ( '/' , '-' ) ;
224
+ extensionPrefix = extensionPath . split ( '-' ) . map ( name => this . _capitalize ( name ) ) . join ( '' ) ;
225
+ }
185
226
const extensionType = options . extensionType ;
227
+ const templateType = options . templateType ;
186
228
const githubURL = options . githubURL ;
187
229
this . log ( extensionPrefix ) ;
188
230
this . params = {
@@ -192,6 +234,7 @@ module.exports = class TheiaExtension extends Base {
192
234
extensionPath,
193
235
extensionPrefix,
194
236
extensionType,
237
+ templateType,
195
238
githubURL,
196
239
theiaVersion : options [ "theia-version" ] ,
197
240
lernaVersion : options [ "lerna-version" ] ,
@@ -210,11 +253,13 @@ module.exports = class TheiaExtension extends Base {
210
253
this . params . containsTests = true ;
211
254
}
212
255
options . params = this . params
213
- if ( ! options . standalone ) {
214
- if ( ( options ) . browser )
256
+ if ( ! options . standalone && this . params . extensionType !== ExtensionType . DiagramEditor ) {
257
+ if ( options . browser ) {
215
258
this . composeWith ( require . resolve ( '../browser' ) , this . options ) ;
216
- if ( ( options ) . electron )
259
+ }
260
+ if ( options . electron ) {
217
261
this . composeWith ( require . resolve ( '../electron' ) , this . options ) ;
262
+ }
218
263
}
219
264
if ( options . standalone ) {
220
265
options . skipInstall = true ;
@@ -223,46 +268,48 @@ module.exports = class TheiaExtension extends Base {
223
268
}
224
269
225
270
writing ( ) {
226
- if ( ! this . options . standalone ) {
227
- /** common templates */
228
- this . fs . copyTpl (
229
- this . templatePath ( 'root-package.json' ) ,
230
- this . destinationPath ( 'package.json' ) ,
231
- { params : this . params }
232
- ) ;
271
+ if ( this . params . extensionType !== ExtensionType . DiagramEditor ) {
272
+ if ( ! this . options . standalone ) {
273
+ /** common templates */
274
+ this . fs . copyTpl (
275
+ this . templatePath ( 'root-package.json' ) ,
276
+ this . destinationPath ( 'package.json' ) ,
277
+ { params : this . params }
278
+ ) ;
279
+ this . fs . copyTpl (
280
+ this . templatePath ( 'lerna.json' ) ,
281
+ this . destinationPath ( 'lerna.json' ) ,
282
+ { params : this . params }
283
+ ) ;
284
+ this . fs . copyTpl (
285
+ this . templatePath ( 'gitignore' ) ,
286
+ this . destinationPath ( '.gitignore' ) ,
287
+ { params : this . params }
288
+ ) ;
289
+ this . fs . copyTpl (
290
+ this . templatePath ( 'README.md' ) ,
291
+ this . destinationPath ( 'README.md' ) ,
292
+ { params : this . params }
293
+ ) ;
294
+ if ( this . params . vscode ) {
295
+ this . fs . copyTpl (
296
+ this . templatePath ( 'launch.json' ) ,
297
+ this . destinationPath ( '.vscode/launch.json' ) ,
298
+ { params : this . params }
299
+ ) ;
300
+ }
301
+ }
233
302
this . fs . copyTpl (
234
- this . templatePath ( 'lerna .json' ) ,
235
- this . destinationPath ( 'lerna .json') ,
303
+ this . templatePath ( 'extension-package .json' ) ,
304
+ this . extensionPath ( 'package .json') ,
236
305
{ params : this . params }
237
306
) ;
238
307
this . fs . copyTpl (
239
- this . templatePath ( 'gitignore ' ) ,
240
- this . destinationPath ( '.gitignore ') ,
308
+ this . templatePath ( 'tsconfig.json ' ) ,
309
+ this . extensionPath ( 'tsconfig.json ') ,
241
310
{ params : this . params }
242
311
) ;
243
- this . fs . copyTpl (
244
- this . templatePath ( 'README.md' ) ,
245
- this . destinationPath ( 'README.md' ) ,
246
- { params : this . params }
247
- )
248
- if ( this . params . vscode ) {
249
- this . fs . copyTpl (
250
- this . templatePath ( 'launch.json' ) ,
251
- this . destinationPath ( '.vscode/launch.json' ) ,
252
- { params : this . params }
253
- )
254
- }
255
312
}
256
- this . fs . copyTpl (
257
- this . templatePath ( 'extension-package.json' ) ,
258
- this . extensionPath ( 'package.json' ) ,
259
- { params : this . params }
260
- ) ;
261
- this . fs . copyTpl (
262
- this . templatePath ( 'tsconfig.json' ) ,
263
- this . extensionPath ( 'tsconfig.json' ) ,
264
- { params : this . params }
265
- ) ;
266
313
267
314
/** hello-world */
268
315
if ( this . params . extensionType === ExtensionType . HelloWorld ) {
@@ -339,7 +386,7 @@ module.exports = class TheiaExtension extends Base {
339
386
this . extensionPath ( `configs/jest.config.ts` ) ,
340
387
{ params : this . params }
341
388
) ;
342
- }
389
+ }
343
390
344
391
/** backend */
345
392
if ( this . params . extensionType === ExtensionType . Backend ) {
@@ -423,6 +470,27 @@ module.exports = class TheiaExtension extends Base {
423
470
) ;
424
471
}
425
472
473
+ /** DiagramEditor */
474
+ if ( this . params . extensionType === ExtensionType . DiagramEditor ) {
475
+ const baseDir = `./glsp-examples-${ glspExamplesRepositoryTag } ` ;
476
+ let templatePath = '' ;
477
+ if ( this . params . templateType == TemplateType . Java ) {
478
+ templatePath = '/project-templates/java-emf-theia' ;
479
+ } else if ( this . params . templateType == TemplateType . Node ) {
480
+ templatePath = '/project-templates/node-json-theia' ;
481
+ } else {
482
+ return ;
483
+ }
484
+
485
+ const done = this . async ( ) ;
486
+ request . get ( `https://github.com/eclipse-glsp/glsp-examples/archive/refs/tags/${ glspExamplesRepositoryTag } .tar.gz` ) . pipe ( tar . x ( ) . on ( 'close' , ( ) => {
487
+ fs . copy ( baseDir + '/README.md' , './README.md' ) ;
488
+ fs . copy ( baseDir + templatePath , './' ) . then ( ( ) => {
489
+ fs . rm ( baseDir , { recursive : true } ) ;
490
+ done ( ) ;
491
+ } ) ;
492
+ } ) ) ;
493
+ }
426
494
}
427
495
428
496
protected extensionPath ( ...paths : string [ ] ) {
@@ -431,13 +499,31 @@ module.exports = class TheiaExtension extends Base {
431
499
432
500
install ( ) {
433
501
if ( ! ( this . options as any ) . skipInstall ) {
434
- var command = this . spawnCommand ( 'yarn' , [ ] ) ;
502
+ if ( this . params . extensionType == ExtensionType . DiagramEditor ) {
503
+ this . log ( 'Installing dependencies' ) ;
435
504
436
- command . on ( 'close' , function ( code : number ) {
437
- if ( code !== 0 ) {
438
- process . exit ( code ) ;
439
- }
440
- } )
505
+ const command = this . spawnCommand ( 'yarn' , [ ] ) ;
506
+
507
+ command . on ( 'close' , ( code :number ) => {
508
+ if ( code === 0 ) {
509
+ this . log (
510
+ '\x1b[32m%s\x1b[0m' ,
511
+ '\nThe DiagramEditor Example has been generated and all dependencies installed\n\nCheck the Readme to get started.'
512
+ ) ;
513
+ } else {
514
+ this . log ( '\x1b[31m%s\x1b[0m' , 'Command "yarn" failed. Please see above for the reported error message.' ) ;
515
+ process . exit ( code ) ;
516
+ }
517
+ } ) ;
518
+ } else {
519
+ const command = this . spawnCommand ( 'yarn' , [ ] ) ;
520
+
521
+ command . on ( 'close' , function ( code : number ) {
522
+ if ( code !== 0 ) {
523
+ process . exit ( code ) ;
524
+ }
525
+ } )
526
+ }
441
527
}
442
528
}
443
529
0 commit comments