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,41 @@
# `@theia/re-export`
Utility package to re-export dependencies.
This is useful when you use and expose some APIs from a dependency and want
your dependent to get access to the exact same symbols as you did.
## `package.json`
You can configure how the `theia-re-export` CLI will generate re-exports
through your `package.json` file with a `theiaReExports` key:
```json
{
"theiaReExports": {
"destination": {
"export *": [
"packages that export via *"
],
"export =": [
"packages that export via ="
],
"copy": "other-package#destination"
}
}
}
```
### `transitive`
If you want to re-export packages from another package that also re-exports
its dependencies. We use this in `@theia/core` to simplify the consumption
of some optional Electron-specific dependencies.
### `export *`
Packages that export their symbols as `export const x = ...`.
### `export =`
Packages that export their symbols as a namespace like `export = ...`.

View File

@@ -0,0 +1,2 @@
#!/usr/bin/env node
require('../lib/bin-theia-re-exports.js');

View File

@@ -0,0 +1,39 @@
{
"private": true,
"name": "@theia/re-exports",
"version": "1.68.0",
"description": "Theia re-export helper functions and scripts.",
"main": "lib/index.js",
"engines": {
"node": ">= 12"
},
"files": [
"bin",
"lib",
"src"
],
"bin": {
"theia-re-exports": "bin/theia-re-exports.js"
},
"scripts": {
"afterInstall": "npm run build",
"build": "theiaext build",
"clean": "theiaext clean",
"compile": "theiaext compile",
"lint": "theiaext lint",
"test": "theiaext test",
"watch": "theiaext watch"
},
"dependencies": {
"mustache": "^4.2.0",
"semver": "^7.5.4",
"tslib": "^2.6.2",
"yargs": "^15.3.1"
},
"devDependencies": {
"@types/chai": "^4.3.0",
"@types/mocha": "^10.0.0",
"@types/mustache": "^4.1.2",
"typescript": "~5.9.3"
}
}

View File

@@ -0,0 +1,23 @@
// *****************************************************************************
// Copyright (C) 2022 Ericsson 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 { readPackageJson, parsePackageReExports } from './package-re-exports';
const packageName = process.argv[2].trim();
readPackageJson(packageName, { paths: [process.cwd()] })
.then(([packageJsonPath, packageJson]) => parsePackageReExports(packageJsonPath, packageJson))
.then(([packageRoot, reExports]) => console.log(JSON.stringify([packageRoot, reExports])));

View File

@@ -0,0 +1,160 @@
// *****************************************************************************
// Copyright (C) 2021 Ericsson 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 fs = require('fs');
import mustache = require('mustache');
import os = require('os');
import path = require('path');
import semver = require('semver');
import yargs = require('yargs');
import { parseModule } from './utility';
import { ReExport, PackageReExports } from './package-re-exports';
type EOL = '\r\n' | '\n' | '\r';
yargs
.command(
'generate [packageName]',
'Generate Theia re-exports',
cli => cli
.positional('packageName', {
type: 'string',
describe: 'Name of the package to generate the re-exports for'
}),
async ({ packageName }) => {
if (!packageName) {
packageName = JSON.parse(await readFile(path.resolve('package.json'))).name as string;
}
const packageReExports = await PackageReExports.FromPackage(packageName);
const writer = new FileWriter(findEol(await readFile(packageReExports.resolvePath('package.json'))));
await Promise.all(packageReExports.all.map(async reExport => {
const reExportPath = packageReExports.resolvePath(reExport.reExportDir, reExport.moduleName, 'index');
await writer.write(`${reExportPath}.js`, `module.exports = require('${reExport.internalImport}');\n`);
if (reExport.reExportStyle === '*') {
const content = `export * from '${reExport.internalImport}';\n`;
await writer.write(`${reExportPath}.d.ts`, content);
} else if (reExport.reExportStyle === '=') {
const content = `import ${reExport.exportNamespace} = require('${reExport.internalImport}');\nexport = ${reExport.exportNamespace};\n`;
await writer.write(`${reExportPath}.d.ts`, content);
} else {
console.warn('unexpected re-export');
}
}));
}
)
.command(
'template inputFile [packageName]',
'Evaluate mustache templates',
cli => cli
.positional('inputFile', {
type: 'string',
describe: 'File to evaluate defined using mustache template syntax',
demandOption: true
})
.positional('packageName', {
type: 'string',
describe: 'Name of the package to generate the re-exports for'
}),
async ({ inputFile, packageName }) => {
if (!packageName) {
packageName = JSON.parse(await readFile(path.resolve('package.json'))).name as string;
}
const template = await readFile(inputFile);
const packageReExports = await PackageReExports.FromPackage(packageName);
const eol = findEol(await readFile(packageReExports.resolvePath('package.json')));
// Organize `ReExport`s by `reExportsDir` then by `packageName`:
const reExportsDirectories: Record<string, Record<string, ReExport[]>> = {};
for (const reExport of packageReExports.all) {
let reExportsPackages = reExportsDirectories[reExport.reExportDir];
if (!reExportsPackages) {
reExportsPackages = reExportsDirectories[reExport.reExportDir] = {};
}
let reExports = reExportsPackages[reExport.packageName];
if (!reExports) {
reExports = reExportsPackages[reExport.packageName] = [];
}
reExports.push(reExport);
}
// Map the organized `ReExport`s into a view object for mustache:
const reExportsView: ReExportsView = {
reExportsDirectories: Object.entries(reExportsDirectories).map(([directory, reExportsPackages]) => ({
directory,
// eslint-disable-next-line @typescript-eslint/no-shadow
packages: Object.entries(reExportsPackages).map(([packageName, reExports]) => ({
packageName,
npmUrl: getNpmUrl(packageName, reExports[0].versionRange),
versionRange: reExports[0].versionRange,
modules: reExports.map(reExport => ({
moduleName: reExport.moduleName,
}))
}))
}))
};
// `console.log` replaces CRLF with LF which is problematic on Windows
process.stdout.write(convertEol(eol, mustache.render(template, reExportsView)));
}
)
.parse();
interface ReExportsView {
reExportsDirectories: Array<{
directory: string
packages: Array<{
npmUrl: string
packageName: string
modules: Array<{
moduleName: string
}>
versionRange: string
}>
}>
}
function getNpmUrl(moduleName: string, versionRange: string | null | undefined): string {
const [packageName] = parseModule(moduleName);
let url = `https://www.npmjs.com/package/${packageName}`;
// Is the range a fixed version?
const version = versionRange && semver.valid(versionRange);
if (version) {
url += `/v/${version}`;
}
return url;
}
async function readFile(filePath: string): Promise<string> {
return fs.promises.readFile(filePath, 'utf8');
}
function findEol(content: string): EOL {
const match = content.match(/\r\n?|\n/);
return (match ? match[0] : os.EOL) as EOL;
}
function convertEol(eol: EOL, content: string): string {
switch (eol) {
case '\r\n': return content.replace(/(?<!\r)\n|\r(?!\n)/g, '\r\n');
case '\n': return content.replace(/\r\n?/g, '\n');
case '\r': return content.replace(/\r?\n/g, '\r');
}
}
class FileWriter {
constructor(public eol: EOL) { }
async write(filePath: string, content: string): Promise<void> {
const dirPath = path.dirname(filePath);
await fs.promises.mkdir(dirPath, { recursive: true });
await fs.promises.writeFile(filePath, convertEol(this.eol, content));
}
}

View File

@@ -0,0 +1,18 @@
// *****************************************************************************
// Copyright (C) 2021 Ericsson 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 './utility';
export * from './package-re-exports';

View File

@@ -0,0 +1,204 @@
// *****************************************************************************
// Copyright (C) 2022 Ericsson 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 cp = require('child_process');
import fs = require('fs');
import path = require('path');
import { PackageJson, parseModule, ReExportJson } from './utility';
export async function readJson<T = unknown>(jsonPath: string): Promise<T> {
return JSON.parse(await fs.promises.readFile(jsonPath, 'utf8')) as T;
}
export async function readPackageJson(packageName: string, options?: { paths?: string[] }): Promise<[string, PackageJson]> {
const packageJsonPath = require.resolve(`${packageName}/package.json`, options);
const packageJson = await readJson<PackageJson>(packageJsonPath);
return [packageJsonPath, packageJson];
}
export async function parsePackageReExports(packageJsonPath: string, packageJson: PackageJson): Promise<[string, ReExport[]]> {
const packageRoot = path.dirname(packageJsonPath);
const { theiaReExports } = packageJson;
if (!theiaReExports) {
return [packageRoot, []];
}
const reExportsByExportDir: ReExport[][] = await Promise.all(Object.entries(theiaReExports).map(
async ([reExportDir, reExportJson]) => resolveTheiaReExports(packageJsonPath, packageJson, reExportDir, reExportJson))
);
return [packageRoot, ([] as ReExport[]).concat(...reExportsByExportDir)];
}
export async function resolveTheiaReExports(
packageJsonPath: string,
packageJson: PackageJson,
reExportDir: string,
reExportJson: ReExportJson
): Promise<ReExport[]> {
if (reExportJson.copy) {
const [packageName, dir] = reExportJson.copy.split('#', 2);
const [subPackageJsonPath, subPackageJson] = await readPackageJson(packageName, { paths: [path.dirname(packageJsonPath)] });
if (!subPackageJson.theiaReExports) {
return [];
}
const reExports = await resolveTheiaReExports(subPackageJsonPath, subPackageJson, dir, subPackageJson.theiaReExports[dir]);
return reExports.map(reExport => {
reExport.reExportDir = reExportDir;
reExport.internalImport = reExport.externalImport;
reExport.externalImport = `${packageJson.name}/${reExportDir}/${reExport.moduleName}`;
return reExport;
});
}
const reExportsStar = reExportJson['export *'] || [];
const reExportsEqual = reExportJson['export ='] || [];
return [
...reExportsStar.map<ReExportStar>(moduleName => {
const [packageName, subModuleName] = parseModule(moduleName);
return {
moduleName,
packageName,
subModuleName,
reExportStyle: '*',
reExportDir,
internalImport: moduleName,
externalImport: `${packageJson.name}/${reExportDir}/${moduleName}`,
hostPackageName: packageJson.name,
versionRange: getPackageVersionRange(packageJson, packageName)
};
}),
...reExportsEqual.map<ReExportEqual>(pattern => {
const [moduleName, exportNamespace = moduleName] = pattern.split(' as ', 2);
if (!/^[a-zA-Z_]\w/.test(exportNamespace)) {
console.warn(`"${exportNamespace}" is not a valid namespace (module: ${moduleName})`);
}
const [packageName, subModuleName] = parseModule(moduleName);
return {
moduleName,
packageName,
subModuleName,
exportNamespace,
reExportStyle: '=',
reExportDir,
internalImport: moduleName,
externalImport: `${packageJson.name}/${reExportDir}/${moduleName}`,
hostPackageName: packageJson.name,
versionRange: getPackageVersionRange(packageJson, packageName),
};
})
];
}
export function getPackageVersionRange(packageJson: PackageJson, packageName: string): string {
const range = packageJson.dependencies?.[packageName]
|| packageJson.optionalDependencies?.[packageName]
|| packageJson.peerDependencies?.[packageName];
if (!range) {
throw new Error(`package not found: ${packageName}`);
}
return range;
}
export type ReExport = ReExportStar | ReExportEqual;
export interface ReExportInfo {
/**
* The full name of the module. e.g. '@some/dep/nested/file'
*/
moduleName: string
/**
* Name of the package the re-export is from. e.g. '@some/dep' in '@some/dep/nested/file'
*/
packageName: string
/**
* Name of the file within the package. e.g. 'nested/file' in '@some/dep/nested/file'
*/
subModuleName?: string
/**
* Name/path of the directory where the re-exports should be located.
*/
reExportDir: string
/**
* Import statement used internally for the re-export.
*/
internalImport: string
/**
* Import name dependents should use externally for the re-export.
*/
externalImport: string
/**
* Name of the package that depends on the re-export.
*/
hostPackageName: string
/**
* Version range defined by the host package depending on the re-export.
*/
versionRange: string
}
export interface ReExportStar extends ReExportInfo {
reExportStyle: '*'
}
export interface ReExportEqual extends ReExportInfo {
reExportStyle: '='
/**
* Pretty name for the re-exported namespace. e.g. 'react-dom' as 'ReactDOM'
*/
exportNamespace: string
}
export class PackageReExports {
static async FromPackage(packageName: string): Promise<PackageReExports> {
const [packageJsonPath, packageJson] = await readPackageJson(packageName);
const [packageRoot, reExports] = await parsePackageReExports(packageJsonPath, packageJson);
return new PackageReExports(packageName, packageRoot, reExports);
}
static FromPackageSync(packageName: string): PackageReExports {
// Some tools (e.g. eslint) don't support async operations.
// To get around this, we can spawn a sub NodeJS process that will run the asynchronous
// logic and then synchronously wait for the serialized result on the standard output.
const scriptPath = require.resolve('./bin-package-re-exports-from-package.js');
const { stdout } = cp.spawnSync(process.platform === 'win32' ? `"${process.argv[0]}"` : process.argv[0], [...process.execArgv, scriptPath, packageName], {
env: {
ELECTRON_RUN_AS_NODE: '1'
},
encoding: 'utf8',
stdio: ['ignore', 'pipe', 'inherit'],
shell: true
});
const [packageRoot, reExports] = JSON.parse(stdout) as [string, ReExport[]];
return new PackageReExports(packageName, packageRoot, reExports);
}
constructor(
readonly packageName: string,
readonly packageRoot: string,
readonly all: readonly Readonly<ReExport>[]
) { }
findReExportByModuleName(moduleName: string): ReExport | undefined {
return this.all.find(reExport => reExport.moduleName === moduleName);
}
findReExportsByPackageName(packageName: string): ReExport[] {
return this.all.filter(reExport => reExport.packageName === packageName);
}
resolvePath(...parts: string[]): string {
return path.resolve(this.packageRoot, ...parts);
}
}

View File

@@ -0,0 +1,41 @@
// *****************************************************************************
// Copyright (C) 2022 Ericsson 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 { parseModule } from './utility';
import { expect } from 'chai';
describe('@theia/re-exports/lib/utility.js', () => {
it('parseModule', () => {
expect(parseModule('a')).length(1).members(['a']);
expect(parseModule('a/')).length(1).members(['a']);
expect(parseModule('a/b')).length(2).members(['a', 'b']);
expect(parseModule('a/b/')).length(2).members(['a', 'b']);
expect(parseModule('a/b/c/d/e/f')).length(2).members(['a', 'b/c/d/e/f']);
});
it('parseModule with namespaced package', () => {
expect(parseModule('@a/b')).length(1).members(['@a/b']);
expect(parseModule('@a/b/')).length(1).members(['@a/b']);
expect(parseModule('@a/b/c')).length(2).members(['@a/b', 'c']);
expect(parseModule('@a/b/c/')).length(2).members(['@a/b', 'c']);
expect(parseModule('@a/b/c/d/e/f')).length(2).members(['@a/b', 'c/d/e/f']);
});
it('parseModule unexpected module name/format', () => {
expect(() => parseModule('@a')).throw();
});
});

View File

@@ -0,0 +1,54 @@
// *****************************************************************************
// Copyright (C) 2021 Ericsson 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 interface PackageJson {
name: string
dependencies?: Record<string, string>
peerDependencies?: Record<string, string>
optionalDependencies?: Record<string, string>
theiaReExports?: Record<string, ReExportJson>
}
/**
* Raw re-export declaration as written in `package.json#theiaReExports[<destination>]`.
*/
export interface ReExportJson {
'export *'?: string[]
'export ='?: string[]
copy?: string
}
/**
* Examples:
* - `a` => `['a']`
* - `a/b/c/...` => `['a', 'b/c/...']`
* - `@a/b` => `['@a/b']`
* - `@a/b/c/...` => `['@a/b', 'c/...']`
*/
export function parseModule(moduleName: string): [string, string?] {
const slice = moduleName.startsWith('@') ? 2 : 1;
const split = moduleName.split('/').filter(part => part.trim().length > 0);
if (split.length < slice) {
throw new Error(`Unexpected module name/format: ${JSON.stringify(moduleName)}`);
}
const packageName = split.slice(0, slice).join('/');
if (split.length === slice) {
return [packageName];
} else {
const subModuleName = split.slice(slice).join('/');
return [packageName, subModuleName];
}
}

View File

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