From 3962e061f6d60459b57e8194692f158707836abc Mon Sep 17 00:00:00 2001 From: Michael Gerzabek Date: Wed, 27 Sep 2023 05:26:53 +0200 Subject: [PATCH] Split backend service templates --- README.md | 4 +++- templates/backend-bidi/README.md | 9 ++++++++ templates/backend-bidi/backend-module.ts | 16 ++++++++++++++ templates/backend-bidi/contribution.ts | 22 +++++++++++++++++++ templates/backend-bidi/frontend-module.ts | 22 +++++++++++++++++++ .../hello-backend-with-client-service.ts | 18 +++++++++++++++ templates/backend-bidi/protocol.ts | 12 ++++++++++ templates/backend-uni/README.md | 9 ++++++++ templates/backend-uni/backend-module.ts | 13 +++++++++++ templates/backend-uni/contribution.ts | 22 +++++++++++++++++++ templates/backend-uni/frontend-module.ts | 14 ++++++++++++ .../backend-uni/hello-backend-service.ts | 9 ++++++++ templates/backend-uni/protocol.ts | 6 +++++ 13 files changed, 175 insertions(+), 1 deletion(-) create mode 100644 templates/backend-bidi/README.md create mode 100644 templates/backend-bidi/backend-module.ts create mode 100644 templates/backend-bidi/contribution.ts create mode 100644 templates/backend-bidi/frontend-module.ts create mode 100644 templates/backend-bidi/hello-backend-with-client-service.ts create mode 100644 templates/backend-bidi/protocol.ts create mode 100644 templates/backend-uni/README.md create mode 100644 templates/backend-uni/backend-module.ts create mode 100644 templates/backend-uni/contribution.ts create mode 100644 templates/backend-uni/frontend-module.ts create mode 100644 templates/backend-uni/hello-backend-service.ts create mode 100644 templates/backend-uni/protocol.ts diff --git a/README.md b/README.md index 0602555..177dd7a 100644 --- a/README.md +++ b/README.md @@ -50,7 +50,9 @@ yo theia-extension --help | `labelprovider` | Creates a simple extension which adds a custom label (with icon) for .my files | [readme](https://github.com/eclipse-theia/generator-theia-extension/blob/master/templates/labelprovider/README.md) | | `tree-editor` | Creates a tree editor extension | [readme](https://github.com/eclipse-theia/generator-theia-extension/blob/master/templates/tree-editor/README.md) | | `empty` | Creates a simple, minimal extension | [readme](https://github.com/eclipse-theia/generator-theia-extension/blob/master/templates/empty/README.md) | -| `backend` | Creates a backend communication extension | [readme](https://github.com/eclipse-theia/generator-theia-extension/blob/master/templates/backend/README.md) | +| `backend` | Creates a unidirectional backend communication extension | [readme](https://github.com/eclipse-theia/generator-theia-extension/blob/master/templates/backend/README.md) | +| `backend-uni` | Creates a unidirectional backend communication extension | [readme](https://github.com/eclipse-theia/generator-theia-extension/blob/master/templates/backend-uni/README.md) | +| `backend-bidi` | Creates a bidrectional backend communication extension | [readme](https://github.com/eclipse-theia/generator-theia-extension/blob/master/templates/backend-bidi/README.md) | | `diagram-editor` | Creates a diagram editor extension | [readme](https://github.com/eclipse-glsp/glsp-examples/blob/master/README.md) | diff --git a/templates/backend-bidi/README.md b/templates/backend-bidi/README.md new file mode 100644 index 0000000..1de86e1 --- /dev/null +++ b/templates/backend-bidi/README.md @@ -0,0 +1,9 @@ +# Backend Communication Example + +The example extension demonstrates how to communicate bidirectional with backend services. +It contains the `HelloBackendWithClientService`, that issues a greeting but the name parameter is not directly passed by the client. Instead, the backend services retrieves the name to say "Hello" to from the client again (`BackendClient`). This example shows how to implement call backs from the backend to the client. +Further, the example contributes one command to trigger the backend call. + +## How to use the backend communication example + +In the running application, trigger the command "Say hello on the backend with a callback to the client" via the command palette (F1 => "Say Hello"). A message will be printed out on the console from where you launched the application. diff --git a/templates/backend-bidi/backend-module.ts b/templates/backend-bidi/backend-module.ts new file mode 100644 index 0000000..b802e02 --- /dev/null +++ b/templates/backend-bidi/backend-module.ts @@ -0,0 +1,16 @@ +import { ConnectionHandler, RpcConnectionHandler } from '@theia/core'; +import { ContainerModule } from '@theia/core/shared/inversify'; +import { BackendClient, HelloBackendWithClientService, HELLO_BACKEND_WITH_CLIENT_PATH } from '../common/protocol'; +import { HelloBackendWithClientServiceImpl } from './hello-backend-with-client-service'; + +export default new ContainerModule(bind => { + bind(HelloBackendWithClientService).to(HelloBackendWithClientServiceImpl).inSingletonScope() + bind(ConnectionHandler).toDynamicValue(ctx => + new RpcConnectionHandler(HELLO_BACKEND_WITH_CLIENT_PATH, client => { + const server = ctx.container.get(HelloBackendWithClientService); + server.setClient(client); + client.onDidCloseConnection(() => server.dispose()); + return server; + }) + ).inSingletonScope(); +}); diff --git a/templates/backend-bidi/contribution.ts b/templates/backend-bidi/contribution.ts new file mode 100644 index 0000000..4085448 --- /dev/null +++ b/templates/backend-bidi/contribution.ts @@ -0,0 +1,22 @@ +import { Command, CommandContribution, CommandRegistry} from '@theia/core/lib/common'; +import { inject, injectable } from '@theia/core/shared/inversify'; +import { HelloBackendWithClientService } from '../common/protocol'; + +const SayHelloViaBackendCommandWithCallBack: Command = { + id: 'sayHelloOnBackendWithCallBack.command', + label: 'Say hello on the backend with a callback to the client', +}; + +@injectable() +export class <%= params.extensionPrefix %>CommandContribution implements CommandContribution { + + constructor( + @inject(HelloBackendWithClientService) private readonly helloBackendWithClientService: HelloBackendWithClientService, + ) { } + + registerCommands(registry: CommandRegistry): void { + registry.registerCommand(SayHelloViaBackendCommandWithCallBack, { + execute: () => this.helloBackendWithClientService.greet().then(r => console.log(r)) + }); + } +} diff --git a/templates/backend-bidi/frontend-module.ts b/templates/backend-bidi/frontend-module.ts new file mode 100644 index 0000000..103b57f --- /dev/null +++ b/templates/backend-bidi/frontend-module.ts @@ -0,0 +1,22 @@ +import { CommandContribution} from '@theia/core'; +import { WebSocketConnectionProvider } from '@theia/core/lib/browser'; +import { ContainerModule, injectable } from '@theia/core/shared/inversify'; +import { BackendClient, HelloBackendWithClientService, 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(HelloBackendWithClientService).toDynamicValue(ctx => { + const connection = ctx.container.get(WebSocketConnectionProvider); + const backendClient: BackendClient = ctx.container.get(BackendClient); + return connection.createProxy(HELLO_BACKEND_WITH_CLIENT_PATH, backendClient); + }).inSingletonScope(); +}); + +@injectable() +class BackendClientImpl implements BackendClient { + getName(): Promise { + return new Promise(resolve => resolve('Client')); + } +} diff --git a/templates/backend-bidi/hello-backend-with-client-service.ts b/templates/backend-bidi/hello-backend-with-client-service.ts new file mode 100644 index 0000000..aba944a --- /dev/null +++ b/templates/backend-bidi/hello-backend-with-client-service.ts @@ -0,0 +1,18 @@ +import { injectable } from '@theia/core/shared/inversify'; +import { BackendClient, HelloBackendWithClientService } from '../common/protocol'; + +@injectable() +export class HelloBackendWithClientServiceImpl implements HelloBackendWithClientService { + private client?: BackendClient; + greet(): Promise { + return new Promise((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; + } +} diff --git a/templates/backend-bidi/protocol.ts b/templates/backend-bidi/protocol.ts new file mode 100644 index 0000000..c770357 --- /dev/null +++ b/templates/backend-bidi/protocol.ts @@ -0,0 +1,12 @@ +import { RpcServer } from '@theia/core/lib/common/messaging'; + +export const HelloBackendWithClientService = Symbol('BackendWithClient'); +export const HELLO_BACKEND_WITH_CLIENT_PATH = '/services/withClient'; + +export interface HelloBackendWithClientService extends RpcServer { + greet(): Promise +} +export const BackendClient = Symbol('BackendClient'); +export interface BackendClient { + getName(): Promise; +} diff --git a/templates/backend-uni/README.md b/templates/backend-uni/README.md new file mode 100644 index 0000000..9bdb9e1 --- /dev/null +++ b/templates/backend-uni/README.md @@ -0,0 +1,9 @@ +# Backend Communication Example + +The example extension demonstrates how to communicate with backend services. +It contains the `HelloBackendService`, that can be called by the client to create a "Hello World" string. The client provides a name as a parameter, and the server returns the name prefixed with "Hello" (ex: "World" as a parameter returns "Hello World"). +Further, the example contributes one command to trigger the backend call. + +## How to use the backend communication example + +In the running application, trigger the command "Say hello on the backend" via the command palette (F1 => "Say Hello"). A message will be printed out on the console from where you launched the application. diff --git a/templates/backend-uni/backend-module.ts b/templates/backend-uni/backend-module.ts new file mode 100644 index 0000000..260a6ee --- /dev/null +++ b/templates/backend-uni/backend-module.ts @@ -0,0 +1,13 @@ +import { ConnectionHandler, RpcConnectionHandler } from '@theia/core'; +import { ContainerModule } from '@theia/core/shared/inversify'; +import { HelloBackendService, HELLO_BACKEND_PATH } from '../common/protocol'; +import { HelloBackendServiceImpl } from './hello-backend-service'; + +export default new ContainerModule(bind => { + bind(HelloBackendService).to(HelloBackendServiceImpl).inSingletonScope() + bind(ConnectionHandler).toDynamicValue(ctx => + new RpcConnectionHandler(HELLO_BACKEND_PATH, () => { + return ctx.container.get(HelloBackendService); + }) + ).inSingletonScope(); +}); diff --git a/templates/backend-uni/contribution.ts b/templates/backend-uni/contribution.ts new file mode 100644 index 0000000..c266a7e --- /dev/null +++ b/templates/backend-uni/contribution.ts @@ -0,0 +1,22 @@ +import { Command, CommandContribution, CommandRegistry} from '@theia/core/lib/common'; +import { inject, injectable } from '@theia/core/shared/inversify'; +import { HelloBackendService } from '../common/protocol'; + +const SayHelloViaBackendCommand: Command = { + id: 'sayHelloOnBackend.command', + label: 'Say hello on the backend', +}; + +@injectable() +export class <%= params.extensionPrefix %>CommandContribution implements CommandContribution { + + constructor( + @inject(HelloBackendService) private readonly helloBackendService: HelloBackendService, + ) { } + + registerCommands(registry: CommandRegistry): void { + registry.registerCommand(SayHelloViaBackendCommand, { + execute: () => this.helloBackendService.sayHelloTo('World').then(r => console.log(r)) + }); + } +} diff --git a/templates/backend-uni/frontend-module.ts b/templates/backend-uni/frontend-module.ts new file mode 100644 index 0000000..460d009 --- /dev/null +++ b/templates/backend-uni/frontend-module.ts @@ -0,0 +1,14 @@ +import { CommandContribution} from '@theia/core'; +import { WebSocketConnectionProvider } from '@theia/core/lib/browser'; +import { ContainerModule } from '@theia/core/shared/inversify'; +import { HelloBackendService, HELLO_BACKEND_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(HelloBackendService).toDynamicValue(ctx => { + const connection = ctx.container.get(WebSocketConnectionProvider); + return connection.createProxy(HELLO_BACKEND_PATH); + }).inSingletonScope(); +}); diff --git a/templates/backend-uni/hello-backend-service.ts b/templates/backend-uni/hello-backend-service.ts new file mode 100644 index 0000000..51dfc10 --- /dev/null +++ b/templates/backend-uni/hello-backend-service.ts @@ -0,0 +1,9 @@ +import { injectable } from '@theia/core/shared/inversify'; +import { HelloBackendService } from '../common/protocol'; + +@injectable() +export class HelloBackendServiceImpl implements HelloBackendService { + sayHelloTo(name: string): Promise { + return new Promise(resolve => resolve('Hello ' + name)); + } +} diff --git a/templates/backend-uni/protocol.ts b/templates/backend-uni/protocol.ts new file mode 100644 index 0000000..f2d9a2c --- /dev/null +++ b/templates/backend-uni/protocol.ts @@ -0,0 +1,6 @@ +export const HelloBackendService = Symbol('HelloBackendService'); +export const HELLO_BACKEND_PATH = '/services/helloBackend'; + +export interface HelloBackendService { + sayHelloTo(name: string): Promise +}