deploy: current vibn theia state
Some checks failed
Playwright Tests / Playwright Tests (ubuntu-22.04, Node.js 22.x) (push) Has been cancelled
3PP License Check / 3PP License Check (11, 22.x, ubuntu-22.04) (push) Has been cancelled
Publish packages to NPM / Perform Publishing (push) Has been cancelled

Made-with: Cursor
This commit is contained in:
2026-02-27 12:01:08 -08:00
commit 8bb5110148
3782 changed files with 640947 additions and 0 deletions

View File

@@ -0,0 +1,10 @@
/** @type {import('eslint').Linter.Config} */
module.exports = {
extends: [
'../../configs/build.eslintrc.json'
],
parserOptions: {
tsconfigRootDir: __dirname,
project: 'tsconfig.json'
}
};

View File

@@ -0,0 +1,30 @@
<div align='center'>
<br />
<img src='https://raw.githubusercontent.com/eclipse-theia/theia/master/logo/theia.svg?sanitize=true' alt='theia-ext-logo' width='100px' />
<h2>ECLIPSE THEIA - REQUEST</h2>
<hr />
</div>
## Description
The `@theia/request` package is used to send proxy-aware http requests to other services.
## Additional Information
- [Theia - GitHub](https://github.com/eclipse-theia/theia)
- [Theia - Website](https://theia-ide.org/)
## License
- [Eclipse Public License 2.0](http://www.eclipse.org/legal/epl-2.0/)
- [一 (Secondary) GNU General Public License, version 2 with the GNU Classpath Exception](https://projects.eclipse.org/license/secondary-gpl-2.0-cp)
## Trademark
"Theia" is a trademark of the Eclipse Foundation
<https://www.eclipse.org/theia>

View File

@@ -0,0 +1,37 @@
{
"name": "@theia/request",
"version": "1.68.0",
"description": "Theia Proxy-Aware Request Service",
"publishConfig": {
"access": "public"
},
"license": "EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0",
"repository": {
"type": "git",
"url": "https://github.com/eclipse-theia/theia.git"
},
"bugs": {
"url": "https://github.com/eclipse-theia/theia/issues"
},
"homepage": "https://github.com/eclipse-theia/theia",
"files": [
"lib",
"src"
],
"main": "lib/index.js",
"typings": "lib/index.d.ts",
"scripts": {
"build": "theiaext build",
"clean": "theiaext clean",
"compile": "theiaext compile",
"lint": "theiaext lint",
"test": "theiaext test",
"watch": "theiaext watch"
},
"dependencies": {
"http-proxy-agent": "^5.0.0",
"https-proxy-agent": "^5.0.0",
"tslib": "^2.6.2"
},
"gitHead": "21358137e41342742707f660b8e222f940a27652"
}

View File

@@ -0,0 +1,127 @@
/********************************************************************************
* Copyright (C) 2022 TypeFox and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
********************************************************************************/
const textDecoder = typeof TextDecoder !== 'undefined' ? new TextDecoder() : undefined;
export interface Headers {
[header: string]: string;
}
export interface RequestOptions {
type?: string;
url: string;
user?: string;
password?: string;
headers?: Headers;
timeout?: number;
data?: string;
followRedirects?: number;
proxyAuthorization?: string;
}
export interface RequestContext {
url: string;
res: {
headers: Headers;
statusCode?: number;
};
/**
* Contains the data returned by the request.
*
* If the request was transferred from the backend to the frontend, the buffer has been compressed into a string. In every case the buffer is an {@link Uint8Array}.
*/
buffer: Uint8Array | string;
}
export namespace RequestContext {
export function isSuccess(context: RequestContext): boolean {
return (context.res.statusCode && context.res.statusCode >= 200 && context.res.statusCode < 300) || context.res.statusCode === 1223;
}
function hasNoContent(context: RequestContext): boolean {
return context.res.statusCode === 204;
}
export function asText(context: RequestContext): string {
if (!isSuccess(context)) {
throw new Error(`Server returned code ${context.res.statusCode}.`);
}
if (hasNoContent(context)) {
return '';
}
// Ensures that the buffer is an Uint8Array
context = decompress(context);
if (textDecoder) {
return textDecoder.decode(context.buffer as Uint8Array);
} else {
return context.buffer.toString();
}
}
export function asJson<T = {}>(context: RequestContext): T {
const str = asText(context);
try {
return JSON.parse(str);
} catch (err) {
err.message += ':\n' + str;
throw err;
}
}
/**
* Convert the buffer to base64 before sending it to the frontend.
* This reduces the amount of JSON data transferred massively.
* Does nothing if the buffer is already compressed.
*/
export function compress(context: RequestContext): RequestContext {
if (context.buffer instanceof Uint8Array && Buffer !== undefined) {
context.buffer = Buffer.from(context.buffer).toString('base64');
}
return context;
}
/**
* Decompresses a base64 buffer into a normal array buffer
* Does nothing if the buffer is not compressed.
*/
export function decompress(context: RequestContext): RequestContext {
const buffer = context.buffer;
if (typeof buffer === 'string' && typeof atob === 'function') {
context.buffer = Uint8Array.from(atob(buffer), c => c.charCodeAt(0));
}
return context;
}
}
export interface RequestConfiguration {
proxyUrl?: string;
proxyAuthorization?: string;
strictSSL?: boolean;
}
export interface RequestService {
configure(config: RequestConfiguration): Promise<void>;
request(options: RequestOptions, token?: CancellationToken): Promise<RequestContext>;
resolveProxy(url: string): Promise<string | undefined>
}
export const RequestService = Symbol('RequestService');
export const BackendRequestService = Symbol('BackendRequestService');
export const REQUEST_SERVICE_PATH = '/services/request-service';
export interface CancellationToken {
readonly isCancellationRequested: boolean;
readonly onCancellationRequested: (listener: () => void) => void;
}

View File

@@ -0,0 +1,17 @@
/********************************************************************************
* Copyright (C) 2022 TypeFox and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
********************************************************************************/
export * from './common-request-service';

View File

@@ -0,0 +1,176 @@
/********************************************************************************
* Copyright (C) 2022 TypeFox and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
********************************************************************************/
import * as http from 'http';
import * as https from 'https';
import { getProxyAgent, ProxyAgent } from './proxy';
import { Headers, RequestConfiguration, RequestContext, RequestOptions, RequestService, CancellationToken } from './common-request-service';
import { createGunzip } from 'zlib';
export interface RawRequestFunction {
(options: http.RequestOptions, callback?: (res: http.IncomingMessage) => void): http.ClientRequest;
}
export interface NodeRequestOptions extends RequestOptions {
agent?: ProxyAgent | http.Agent | https.Agent | boolean;
strictSSL?: boolean;
getRawRequest?(options: NodeRequestOptions): RawRequestFunction;
};
export class NodeRequestService implements RequestService {
protected proxyUrl?: string;
protected strictSSL?: boolean;
protected authorization?: string;
protected getNodeRequest(options: RequestOptions): RawRequestFunction {
const endpoint = new URL(options.url);
const module = endpoint.protocol === 'https:' ? https : http;
return module.request;
}
protected async getProxyUrl(url: string): Promise<string | undefined> {
return this.proxyUrl;
}
async configure(config: RequestConfiguration): Promise<void> {
if (config.proxyUrl !== undefined) {
this.proxyUrl = config.proxyUrl;
}
if (config.strictSSL !== undefined) {
this.strictSSL = config.strictSSL;
}
if (config.proxyAuthorization !== undefined) {
this.authorization = config.proxyAuthorization;
}
}
protected async processOptions(options: NodeRequestOptions): Promise<NodeRequestOptions> {
const { strictSSL } = this;
options.strictSSL = options.strictSSL ?? strictSSL;
const agent = options.agent ? options.agent : getProxyAgent(options.url || '', process.env, {
proxyUrl: await this.getProxyUrl(options.url),
strictSSL: options.strictSSL
});
options.agent = agent;
const authorization = options.proxyAuthorization || this.authorization;
if (authorization) {
options.headers = {
...(options.headers || {}),
'Proxy-Authorization': authorization
};
}
options.headers = {
'Accept-Encoding': 'gzip',
...(options.headers || {}),
};
return options;
}
request(options: NodeRequestOptions, token?: CancellationToken): Promise<RequestContext> {
return new Promise(async (resolve, reject) => {
options = await this.processOptions(options);
const endpoint = new URL(options.url);
const rawRequest = options.getRawRequest
? options.getRawRequest(options)
: this.getNodeRequest(options);
const opts: https.RequestOptions = {
hostname: endpoint.hostname,
port: endpoint.port ? parseInt(endpoint.port) : (endpoint.protocol === 'https:' ? 443 : 80),
protocol: endpoint.protocol,
path: endpoint.pathname + endpoint.search,
method: options.type || 'GET',
headers: options.headers,
agent: options.agent as https.Agent,
rejectUnauthorized: !!options.strictSSL
};
if (options.user && options.password) {
opts.auth = options.user + ':' + options.password;
}
const timeoutHandler = () => {
reject('timeout');
};
const req = rawRequest(opts, async res => {
const followRedirects = options.followRedirects ?? 3;
if (res.statusCode && res.statusCode >= 300 && res.statusCode < 400 && followRedirects > 0 && res.headers.location) {
req.off('timeout', timeoutHandler);
this.request({
...options,
url: res.headers.location,
followRedirects: followRedirects - 1
}, token).then(resolve, reject);
} else {
const chunks: Uint8Array[] = [];
const stream = res.headers['content-encoding'] === 'gzip' ? res.pipe(createGunzip()) : res;
stream.on('data', chunk => {
chunks.push(chunk);
});
stream.on('end', () => {
req.off('timeout', timeoutHandler);
const buffer = Buffer.concat(chunks);
resolve({
url: options.url,
res: {
headers: res.headers as Headers,
statusCode: res.statusCode
},
buffer
});
});
stream.on('error', err => {
reject(err);
});
}
});
req.on('error', err => {
reject(err);
});
req.on('timeout', timeoutHandler);
if (options.timeout) {
req.setTimeout(options.timeout);
}
if (options.data) {
req.write(options.data);
}
req.end();
token?.onCancellationRequested(() => {
req.destroy();
reject();
});
});
}
async resolveProxy(url: string): Promise<string | undefined> {
return undefined;
}
}

View File

@@ -0,0 +1,28 @@
/********************************************************************************
* Copyright (C) 2022 TypeFox and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
********************************************************************************/
/* note: this bogus test file is required so that
we are able to run mocha unit tests on this
package, without having any actual unit tests in it.
This way a coverage report will be generated,
showing 0% coverage, instead of no report.
This file can be removed once we have real unit
tests in place. */
describe('request package', () => {
it('should support code coverage statistics', () => true);
});

View File

@@ -0,0 +1,57 @@
/********************************************************************************
* Copyright (C) 2022 TypeFox and others.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the Eclipse
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
* with the GNU Classpath Exception which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-only WITH Classpath-exception-2.0
********************************************************************************/
import { parse as parseUrl, Url } from 'url';
import { HttpProxyAgent } from 'http-proxy-agent';
import { HttpsProxyAgent } from 'https-proxy-agent';
export type ProxyAgent = HttpProxyAgent<string> | HttpsProxyAgent<string>;
function getSystemProxyURI(requestURL: Url, env: typeof process.env): string | undefined {
if (requestURL.protocol === 'http:') {
return env.HTTP_PROXY || env.http_proxy;
} else if (requestURL.protocol === 'https:') {
return env.HTTPS_PROXY || env.https_proxy || env.HTTP_PROXY || env.http_proxy;
}
return undefined;
}
export interface ProxySettings {
proxyUrl?: string;
strictSSL?: boolean;
}
export function getProxyAgent(rawRequestURL: string, env: typeof process.env, options: ProxySettings = {}): ProxyAgent | undefined {
const requestURL = parseUrl(rawRequestURL);
const proxyURL = options.proxyUrl || getSystemProxyURI(requestURL, env);
if (!proxyURL) {
return undefined;
}
const proxyEndpoint = parseUrl(proxyURL);
if (!/^https?:$/.test(proxyEndpoint.protocol || '')) {
return undefined;
}
if (requestURL.protocol === 'http:') {
return new HttpProxyAgent(proxyURL, { rejectUnauthorized: !!options.strictSSL });
} else {
return new HttpsProxyAgent(proxyURL, { rejectUnauthorized: !!options.strictSSL });
}
}

View File

@@ -0,0 +1,12 @@
{
"extends": "../../configs/base.tsconfig",
"compilerOptions": {
"composite": true,
"rootDir": "src",
"outDir": "lib"
},
"include": [
"src"
],
"references": []
}