Skip to content
This repository has been archived by the owner on Apr 4, 2023. It is now read-only.

Commit

Permalink
eclipse-che/che#11306 Initial Che api for Theia
Browse files Browse the repository at this point in the history
Signed-off-by: Yevhen Vydolob <yvydolob@redhat.com>
  • Loading branch information
evidolob committed Nov 28, 2018
1 parent 3996003 commit 04827a9
Show file tree
Hide file tree
Showing 23 changed files with 8,787 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
yarn-error.log
3 changes: 3 additions & 0 deletions extensions/eclipse-che-theia-plugin-ext/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
src/che.d.ts
src/che-proposed.d.ts
lib
43 changes: 43 additions & 0 deletions extensions/eclipse-che-theia-plugin-ext/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"name": "@eclipse-che/theia-plugin-ext",
"version": "1.0.0",
"description": "Theia extension",
"author": "Yevhen Vydolob",
"license": "EPL-2.0",
"keywords": [
"theia-extension",
"che"
],
"files": [
"lib",
"src"
],
"dependencies": {
"@theia/core": "next",
"@theia/plugin-ext": "next",
"@eclipse-che/workspace-client": "^0.0.1-1527159618"
},
"devDependencies": {
"rimraf": "2.6.2",
"ts-node": "5.0.1",
"typescript": "^2.9.2",
"webpack": "^4.20.2",
"webpack-cli": "^3.1.1",
"clean-webpack-plugin": "^0.1.19",
"ts-loader": "^4.1.0"
},
"scripts": {
"prepare": "yarn run clean && yarn run copy && yarn run build",
"copy": "cp ../eclipse-che-theia-plugin/src/* src",
"clean": "rimraf lib",
"build": "tsc && yarn run compileWorker",
"compileWorker": "webpack-cli --config webpack.config.js",
"watch": "tsc -w"
},
"theiaExtensions": [
{
"frontend": "lib/browser/che-frontend-module",
"backend": "lib/node/che-backend-module"
}
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/*********************************************************************
* Copyright (c) 2018 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import { MainPluginApiProvider } from '@theia/plugin-ext/lib/common/plugin-ext-api-contribution';
import { RPCProtocol } from '@theia/plugin-ext/lib/api/rpc-protocol';
import { injectable, interfaces } from 'inversify';
import { PLUGIN_RPC_CONTEXT } from '../common/che-protocol';
import { CheApiPluginMainImpl } from './che-workspace-main';

@injectable()
export class CheMainApiProvider implements MainPluginApiProvider {

initialize(rpc: RPCProtocol, container: interfaces.Container): void {
rpc.set(PLUGIN_RPC_CONTEXT.CHE_API_MAIN, new CheApiPluginMainImpl(container));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*********************************************************************
* Copyright (c) 2018 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/

import { ContainerModule } from 'inversify';
import { MainPluginApiProvider } from '@theia/plugin-ext/lib/common/plugin-ext-api-contribution';
import { CheMainApiProvider } from './che-api-main';
import { CheApiService, CheApiServicePath } from '../common/che-protocol';
import { WebSocketConnectionProvider } from '@theia/core/lib/browser';

export default new ContainerModule(bind => {
bind(CheMainApiProvider).toSelf().inSingletonScope();
bind(MainPluginApiProvider).toService(CheMainApiProvider);

bind(CheApiService).toDynamicValue(ctx => {
const provider = ctx.container.get(WebSocketConnectionProvider);
return provider.createProxy<CheApiService>(CheApiServicePath);
}).inSingletonScope();
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@

/*********************************************************************
* Copyright (c) 2018 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/

import { CheApiMain, CheApiService, Factory } from '../common/che-protocol';
import { Workspace } from '@eclipse-che/plugin';
import { interfaces } from 'inversify';

export class CheApiPluginMainImpl implements CheApiMain {

private readonly delegate: CheApiService;
constructor(container: interfaces.Container) {
this.delegate = container.get(CheApiService);
}
$currentWorkspace(): Promise<Workspace> {
return this.delegate.currentWorkspace().then(w => w, err => {
console.log(err);
return undefined!;
});
}

$getFactoryById(id: string): Promise<Factory> {
throw new Error('getFactoryById is not implemented');
}
}
174 changes: 174 additions & 0 deletions extensions/eclipse-che-theia-plugin-ext/src/common/che-protocol.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
/*********************************************************************
* Copyright (c) 2018 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/

import { ProxyIdentifier, createProxyIdentifier } from '@theia/plugin-ext/lib/api/rpc-protocol';

export interface CheApiPlugin {

}

export interface CheApiMain {
$currentWorkspace(): Promise<Workspace>;

$getFactoryById(id: string): Promise<Factory>;
}

export interface Factory {
workspace: WorkspaceConfig;
ide?: {
onAppLoaded?: {
actions?: FactoryAction[]
};
onProjectsLoaded?: {
actions?: FactoryAction[]
};
onAppClosed?: {
actions?: FactoryAction[]
};
}
}

export interface FactoryAction {
id: string,
properties?: {
name?: string,
file?: string,
greetingTitle?: string,
greetingContentUrl?: string
}
}

export interface WorkspaceConfig {
name?: string;
description?: string;
defaultEnv: string;
environments: {
[environmentName: string]: any;
};
projects: ProjectConfig[];
commands?: Command[];
links?: Link[];
}
export interface ProjectConfig {
name: string;
path: string;
description?: string;
mixins?: string[];
attributes?: { [attrName: string]: string[] };
source?: SourceStorage;
problems?: ProjectProblem;
}

export interface SourceStorage {
type: string;
location: string;
parameters: { [attrName: string]: string };
}

export interface ProjectProblem {
code: number;
message: string;
}

export interface Command {
name: string;
commandLine: string;
type: string;
attributes?: { [attrName: string]: string };
}

export interface Link {
href: string;
rel?: string;
method: string;
produces?: string;
consumes?: string;
parameters?: LinkParameter[];
requestBody?: RequestBodyDescriptor;
}

export interface Workspace {
id?: string;
config: WorkspaceConfig;
status: string | WorkspaceStatus;
namespace?: string;
temporary?: boolean;
attributes?: WorkspaceAttributes;
runtime?: Runtime;
links?: { [attrName: string]: string };
}

export type WorkspaceStatus = 'STARTING' | 'RUNNING' | 'STOPPING' | 'STOPPED';

export interface Runtime {
activeEnv: string;
machines: { [attrName: string]: Machine };
owner: string;
warnings?: Warning;
}

export interface Machine {
status: string | MachineStatus;
servers: { [attrName: string]: Server };
attributes?: { [attrName: string]: string };
}

export type MachineStatus = 'STARTING' | 'RUNNING' | 'STOPPED' | 'FAILED';

export interface Server {
url: string;
status: string | ServerStatus;
attributes?: { [attrName: string]: string };
}

export type ServerStatus = 'RUNNING' | 'STOPPED' | 'UNKNOWN';

export interface Warning {
code: number;
message: string;
}


export interface WorkspaceAttributes {
created: number;
updated?: number;
stackId?: string;
errorMessage?: string;
[propName: string]: string | number | any;
}


export interface LinkParameter {
name: string;
defaultValue?: string;
description?: string;
type: LinkParameterType;
required: boolean;
valid: string[];
}

export type LinkParameterType = 'String' | 'Number' | 'Boolean' | 'Array' | 'Object';

export interface RequestBodyDescriptor {
description: string;
}

export const PLUGIN_RPC_CONTEXT = {
CHE_API_MAIN: <ProxyIdentifier<CheApiMain>>createProxyIdentifier<CheApiMain>('CheApiMain'),
};

// Theia RPC protocol

export const CheApiServicePath = '/che-api-service';

export const CheApiService = Symbol('CheApiService');
export interface CheApiService {
currentWorkspace(): Promise<Workspace>;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*********************************************************************
* Copyright (c) 2018 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/
import { CheApiService } from '../common/che-protocol';
import { Workspace } from '@eclipse-che/plugin';
import WorkspaceClient, { IRestAPIConfig, IRemoteAPI } from '@eclipse-che/workspace-client';
import { injectable } from 'inversify';

@injectable()
export class CheApiServiceImpl implements CheApiService {
private workspaceRestAPI: IRemoteAPI | undefined;
async currentWorkspace(): Promise<Workspace> {
try {

const cheWorkspaceId = process.env.CHE_WORKSPACE_ID;
if (!cheWorkspaceId) {
return Promise.reject('Cannot find Che workspace id, environment variable "CHE_WORKSPACE_ID" is not set');
}
const wsClient = await this.getOrCreateWSClient();
if (wsClient) {
return wsClient!.getById<Workspace>(cheWorkspaceId);
}
return Promise.reject('Cannot create Che API REST Client');
} catch (e) {
console.log(e);
return Promise.reject('Cannot create Che API REST Client');
}
}

private async getOrCreateWSClient(): Promise<IRemoteAPI | undefined> {
const cheApiInternalVar = process.env.CHE_API_INTERNAL;
const cheMachineToken = process.env.CHE_MACHINE_TOKEN;

if (!cheApiInternalVar) {
return undefined;
}

if (!this.workspaceRestAPI) {
const restAPIConfig: IRestAPIConfig = {
baseUrl: cheApiInternalVar,
headers: {}
};
if (cheMachineToken) {
restAPIConfig.headers['Authorization'] = 'Bearer ' + cheMachineToken;
}

this.workspaceRestAPI = await WorkspaceClient.getRestApi(restAPIConfig);
}
return this.workspaceRestAPI;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*********************************************************************
* Copyright (c) 2018 Red Hat, Inc.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
**********************************************************************/

import { ContainerModule } from 'inversify';
import { ChePluginApiProvider } from './che-plugin-api-provider';
import { ExtPluginApiProvider } from '@theia/plugin-ext';
import { ChePluginApiContribution } from './che-plugin-script-service';
import { BackendApplicationContribution } from '@theia/core/lib/node/backend-application';
import { ConnectionHandler, JsonRpcConnectionHandler } from '@theia/core';
import { CheApiServiceImpl } from './che-api-service';
import { CheApiService, CheApiServicePath } from '../common/che-protocol';

export default new ContainerModule(bind => {
bind(ChePluginApiProvider).toSelf().inSingletonScope();
bind(Symbol.for(ExtPluginApiProvider)).toService(ChePluginApiProvider);
bind(ChePluginApiContribution).toSelf().inSingletonScope();
bind(BackendApplicationContribution).toDynamicValue(ctx => ctx.container.get(ChePluginApiContribution)).inSingletonScope();

bind(CheApiService).to(CheApiServiceImpl).inSingletonScope();
bind(ConnectionHandler).toDynamicValue(ctx =>
new JsonRpcConnectionHandler(CheApiServicePath, () =>
ctx.container.get(CheApiService)
)
).inSingletonScope();
});
Loading

0 comments on commit 04827a9

Please sign in to comment.