Skip to content

Commit

Permalink
Added backend communication template
Browse files Browse the repository at this point in the history
fixed #64

Signed-off-by: Jonas Helming <[email protected]>
  • Loading branch information
JonasHelming committed Jun 22, 2020
1 parent a89ddea commit eddb063
Show file tree
Hide file tree
Showing 9 changed files with 207 additions and 4 deletions.
43 changes: 40 additions & 3 deletions src/app/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ enum ExtensionType {
HelloWorld = 'hello-world',
Widget = 'widget',
LabelProvider = 'labelprovider',
Empty = 'empty'
Empty = 'empty',
Backend = 'backend'
}

module.exports = class TheiaExtension extends Base {
Expand Down Expand Up @@ -130,6 +131,7 @@ module.exports = class TheiaExtension extends Base {
{ value: ExtensionType.HelloWorld, name: 'Hello World' },
{ value: ExtensionType.Widget, name: 'Widget' },
{ value: ExtensionType.LabelProvider, name: 'LabelProvider' },
{ value: ExtensionType.Backend, name: 'Backend communication' },
{ value: ExtensionType.Empty, name: 'Empty' }
]
});
Expand Down Expand Up @@ -169,6 +171,7 @@ module.exports = class TheiaExtension extends Base {
githubURL,
theiaVersion: options["theia-version"],
lernaVersion: options["lerna-version"],
backend: options["extensionType"] === ExtensionType.Backend
}
options.params = this.params
if (!options.standalone) {
Expand All @@ -177,8 +180,8 @@ module.exports = class TheiaExtension extends Base {
if ((options).electron)
this.composeWith(require.resolve('../electron'), this.options);
}
if(options.standalone){
options.skipInstall=true;
if (options.standalone) {
options.skipInstall = true;
this.log('Please remember to add the standalone extension manually to your root package.json and to your product, e.g. in browser-app/package.json')
}
}
Expand Down Expand Up @@ -277,6 +280,40 @@ module.exports = class TheiaExtension extends Base {
);
}

/** backend */
if (this.params.extensionType === ExtensionType.Backend) {
this.fs.copyTpl(
this.templatePath('backend/frontend-module.ts'),
this.extensionPath(`src/browser/${this.params.extensionPath}-frontend-module.ts`),
{ params: this.params }
);
this.fs.copyTpl(
this.templatePath('backend/contribution.ts'),
this.extensionPath(`src/browser/${this.params.extensionPath}-contribution.ts`),
{ params: this.params }
);
this.fs.copyTpl(
this.templatePath('backend/protocol.ts'),
this.extensionPath(`src/common/protocol.ts`),
{ params: this.params }
);
this.fs.copyTpl(
this.templatePath('backend/hello-backend-service.ts'),
this.extensionPath(`src/node/hello-backend-service.ts`),
{ params: this.params }
);
this.fs.copyTpl(
this.templatePath('backend/backend-module.ts'),
this.extensionPath(`src/node/${this.params.extensionPath}-backend-module.ts`),
{ params: this.params }
);
this.fs.copyTpl(
this.templatePath('backend/hello-backend-with-client-service.ts'),
this.extensionPath(`src/node/hello-backend-with-client-service.ts`),
{ params: this.params }
);
}

/** labelprovider */
if (this.params.extensionType === ExtensionType.LabelProvider) {
this.fs.copyTpl(
Expand Down
26 changes: 26 additions & 0 deletions templates/backend/backend-module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { ConnectionHandler, JsonRpcConnectionHandler } from "@theia/core";
import { ContainerModule } from "inversify";
import { BackendClient, HelloBackendWithClientService, HelloBackendService, HELLO_BACKEND_PATH, HELLO_BACKEND_WITH_CLIENT_PATH } from "../common/protocol";
import { HelloBackendWithClientServiceImpl } from "./hello-backend-with-client-service";
import { HelloBackendServiceImpl } from "./hello-backend-service";

export default new ContainerModule(bind => {
bind(HelloBackendService).to(HelloBackendServiceImpl).inSingletonScope()
bind(ConnectionHandler).toDynamicValue(ctx =>
new JsonRpcConnectionHandler(HELLO_BACKEND_PATH, () => {
return ctx.container.get<HelloBackendService>(HelloBackendService);
})
).inSingletonScope();

bind(HelloBackendWithClientService).to(HelloBackendWithClientServiceImpl).inSingletonScope()
bind(ConnectionHandler).toDynamicValue(ctx =>
new JsonRpcConnectionHandler<BackendClient>(HELLO_BACKEND_WITH_CLIENT_PATH, client => {
const server = ctx.container.get<HelloBackendWithClientServiceImpl>(HelloBackendWithClientService);
server.setClient(client);
client.onDidCloseConnection(() => server.dispose());
return server;
})
).inSingletonScope();
});


31 changes: 31 additions & 0 deletions templates/backend/contribution.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { Command, CommandContribution, CommandRegistry} from '@theia/core/lib/common';
import { inject, injectable } from 'inversify';
import { HelloBackendWithClientService, HelloBackendService } from '../common/protocol';

const SayHelloViaBackendCommandWithCallBack: Command = {
id: 'sayHelloOnBackendWithCallBack.command',
label: 'Say hello on the backend with a callback to the client',
};

const SayHelloViaBackendCommand: Command = {
id: 'sayHelloOnBackend.command',
label: 'Say hello on the backend',
};

@injectable()
export class <%= params.extensionPrefix %>CommandContribution implements CommandContribution {

constructor(
@inject(HelloBackendWithClientService) private readonly helloBackendWithClientService: HelloBackendWithClientService,
@inject(HelloBackendService) private readonly helloBackendService: HelloBackendService,
) { }

registerCommands(registry: CommandRegistry): void {
registry.registerCommand(SayHelloViaBackendCommandWithCallBack, {
execute: () => this.helloBackendWithClientService.greet().then(r => console.log(r))
});
registry.registerCommand(SayHelloViaBackendCommand, {
execute: () => this.helloBackendService.sayHelloTo('World').then(r => console.log(r))
});
}
}
29 changes: 29 additions & 0 deletions templates/backend/frontend-module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { CommandContribution} from '@theia/core';
import { WebSocketConnectionProvider } from "@theia/core/lib/browser";
import { ContainerModule, injectable } from "inversify";
import { BackendClient, HelloBackendWithClientService, HelloBackendService, HELLO_BACKEND_PATH, HELLO_BACKEND_WITH_CLIENT_PATH } from '../common/protocol';
import { <%= params.extensionPrefix %>CommandContribution} from './<%= params.extensionPath %>-contribution';

export default new ContainerModule(bind => {
bind(CommandContribution).to(<%= params.extensionPrefix %>CommandContribution).inSingletonScope();
bind(BackendClient).to(BackendClientImpl).inSingletonScope();

bind(HelloBackendService).toDynamicValue(ctx => {
const connection = ctx.container.get(WebSocketConnectionProvider);
return connection.createProxy<HelloBackendService>(HELLO_BACKEND_PATH);
}).inSingletonScope();

bind(HelloBackendWithClientService).toDynamicValue(ctx => {
const connection = ctx.container.get(WebSocketConnectionProvider);
const backendClient: BackendClient = ctx.container.get(BackendClient);
return connection.createProxy<HelloBackendWithClientService>(HELLO_BACKEND_WITH_CLIENT_PATH, backendClient);
}).inSingletonScope();
});

@injectable()
class BackendClientImpl implements BackendClient {
getName(): Promise<string> {
return new Promise(resolve => resolve('Client'));
}

}
9 changes: 9 additions & 0 deletions templates/backend/hello-backend-service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { injectable } from "inversify";
import { HelloBackendService } from "../common/protocol";

@injectable()
export class HelloBackendServiceImpl implements HelloBackendService {
sayHelloTo(name: string): Promise<string> {
return new Promise<string>(resolve => resolve('Hello ' + name));
}
}
20 changes: 20 additions & 0 deletions templates/backend/hello-backend-with-client-service.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { injectable } from "inversify";
import { BackendClient, HelloBackendWithClientService } from "../common/protocol";

@injectable()
export class HelloBackendWithClientServiceImpl implements HelloBackendWithClientService {
private client?: BackendClient;
greet(): Promise<string> {
return new Promise<string>((resolve, reject) =>
this.client ? this.client.getName().then(greet => resolve('Hello ' + greet))
: reject('No Client'));
}
dispose(): void {
// do nothing
}
setClient(client: BackendClient): void {
this.client = client;
}


}
18 changes: 18 additions & 0 deletions templates/backend/protocol.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { JsonRpcServer } from '@theia/core/lib/common/messaging';

export const HelloBackendService = Symbol('HelloBackendService');
export const HELLO_BACKEND_PATH = '/services/helloBackend';

export interface HelloBackendService {
sayHelloTo(name: string): Promise<string>
}
export const HelloBackendWithClientService = Symbol('BackendWithClient');
export const HELLO_BACKEND_WITH_CLIENT_PATH = '/services/withClient';

export interface HelloBackendWithClientService extends JsonRpcServer<BackendClient> {
greet(): Promise<string>
}
export const BackendClient = Symbol('BackendClient');
export interface BackendClient {
getName(): Promise<string>;
}
3 changes: 2 additions & 1 deletion templates/extension-package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@
},
"theiaExtensions": [
{
"frontend": "lib/browser/<%= params.extensionPath %>-frontend-module"
"frontend": "lib/browser/<%= params.extensionPath %>-frontend-module"<% if (params.backend) { %>,
"backend": "lib/node/<%= params.extensionPath %>-backend-module"<% } %>
}
]
}
32 changes: 32 additions & 0 deletions test/generator-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,38 @@ describe('test extension generation', function () {
}
}, done);
});
it('generate the backend extension', function (done) {
const name = 'backend-template-test';
helpers.run(path.join(__dirname, '../generators/app'))
.withPrompts({
type: 'backend',
name
})
.withOptions({
skipInstall: true
})
.toPromise().then(function () {
try {
assert.file([
'package.json',
'README.md',
`${name}/src/browser/${name}-contribution.ts`,
`${name}/src/browser/${name}-frontend-module.ts`,
`${name}/src/common/protocol.ts`,
`${name}/src/node/${name}-backend-module.ts`,
`${name}/src/node/hello-backend-service.ts`,
`${name}/src/node/hello-backend-with-client-service.ts`,
]);

var body = fs.readFileSync(`${name}/package.json`, 'utf8');
var actual = JSON.parse(body);
assert.equal(actual.name, name);
done();
} catch (e) {
done(e);
}
}, done);
});

});

Expand Down

0 comments on commit eddb063

Please sign in to comment.