code-web: read built-in marketplace extensions
This commit is contained in:
parent
135e5d9323
commit
d706c7089c
|
@ -20,13 +20,15 @@ const ansiColors = require('ansi-colors');
|
||||||
const extensions = require('../../build/lib/extensions');
|
const extensions = require('../../build/lib/extensions');
|
||||||
|
|
||||||
const APP_ROOT = path.join(__dirname, '..', '..');
|
const APP_ROOT = path.join(__dirname, '..', '..');
|
||||||
const EXTENSIONS_ROOT = path.join(APP_ROOT, 'extensions');
|
const BUILTIN_EXTENSIONS_ROOT = path.join(APP_ROOT, 'extensions');
|
||||||
|
const BUILTIN_MARKETPLACE_EXTENSIONS_ROOT = path.join(APP_ROOT, '.build', 'builtInExtensions');
|
||||||
const WEB_MAIN = path.join(APP_ROOT, 'src', 'vs', 'code', 'browser', 'workbench', 'workbench-dev.html');
|
const WEB_MAIN = path.join(APP_ROOT, 'src', 'vs', 'code', 'browser', 'workbench', 'workbench-dev.html');
|
||||||
|
|
||||||
const args = minimist(process.argv, {
|
const args = minimist(process.argv, {
|
||||||
boolean: [
|
boolean: [
|
||||||
'no-launch',
|
'no-launch',
|
||||||
'help'
|
'help',
|
||||||
|
'verbose'
|
||||||
],
|
],
|
||||||
string: [
|
string: [
|
||||||
'scheme',
|
'scheme',
|
||||||
|
@ -46,6 +48,7 @@ if (args.help) {
|
||||||
' --port Remote/Local port\n' +
|
' --port Remote/Local port\n' +
|
||||||
' --local_port Local port override\n' +
|
' --local_port Local port override\n' +
|
||||||
' --extension Path of an extension to include\n' +
|
' --extension Path of an extension to include\n' +
|
||||||
|
' --verbose Print out more information\n' +
|
||||||
' --help\n' +
|
' --help\n' +
|
||||||
'[Example]\n' +
|
'[Example]\n' +
|
||||||
' yarn web --scheme https --host example.com --port 8080 --local_port 30000'
|
' yarn web --scheme https --host example.com --port 8080 --local_port 30000'
|
||||||
|
@ -64,18 +67,27 @@ const readFile = (path) => util.promisify(fs.readFile)(path);
|
||||||
const readdir = (path) => util.promisify(fs.readdir)(path);
|
const readdir = (path) => util.promisify(fs.readdir)(path);
|
||||||
const readdirWithFileTypes = (path) => util.promisify(fs.readdir)(path, { withFileTypes: true });
|
const readdirWithFileTypes = (path) => util.promisify(fs.readdir)(path, { withFileTypes: true });
|
||||||
|
|
||||||
async function getBuiltInExtensionInfos(extensionsRoot) {
|
async function getBuiltInExtensionInfos() {
|
||||||
const builtinExtensions = [];
|
const extensions = [];
|
||||||
const children = await readdirWithFileTypes(extensionsRoot);
|
/** @type {Object.<string, string>} */
|
||||||
await Promise.all(children.map(async child => {
|
const locations = {};
|
||||||
if (child.isDirectory()) {
|
|
||||||
const info = await getBuiltInExtensionInfo(path.join(extensionsRoot, child.name));
|
for (const extensionsRoot of [BUILTIN_EXTENSIONS_ROOT, BUILTIN_MARKETPLACE_EXTENSIONS_ROOT]) {
|
||||||
if (info) {
|
if (await exists(extensionsRoot)) {
|
||||||
builtinExtensions.push(info);
|
const children = await readdirWithFileTypes(extensionsRoot);
|
||||||
}
|
await Promise.all(children.map(async child => {
|
||||||
|
if (child.isDirectory()) {
|
||||||
|
const extensionPath = path.join(extensionsRoot, child.name);
|
||||||
|
const info = await getBuiltInExtensionInfo(extensionPath);
|
||||||
|
if (info) {
|
||||||
|
extensions.push(info);
|
||||||
|
locations[path.basename(extensionPath)] = extensionPath;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
}));
|
}
|
||||||
return builtinExtensions;
|
return { extensions, locations };
|
||||||
}
|
}
|
||||||
|
|
||||||
async function getBuiltInExtensionInfo(extensionPath) {
|
async function getBuiltInExtensionInfo(extensionPath) {
|
||||||
|
@ -106,6 +118,8 @@ async function getBuiltInExtensionInfo(extensionPath) {
|
||||||
|
|
||||||
async function getDefaultExtensionInfos() {
|
async function getDefaultExtensionInfos() {
|
||||||
const extensions = [];
|
const extensions = [];
|
||||||
|
|
||||||
|
/** @type {Object.<string, string>} */
|
||||||
const locations = {};
|
const locations = {};
|
||||||
|
|
||||||
let extensionArg = args['extension'];
|
let extensionArg = args['extension'];
|
||||||
|
@ -166,8 +180,7 @@ async function getExtensionPackageJSON(extensionPath) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const builtInExtensionsPromise = getBuiltInExtensionInfos();
|
||||||
const builtinExtensionsPromise = getBuiltInExtensionInfos(EXTENSIONS_ROOT);
|
|
||||||
const defaultExtensionsPromise = getDefaultExtensionInfos();
|
const defaultExtensionsPromise = getDefaultExtensionInfos();
|
||||||
|
|
||||||
const mapCallbackUriToRequestId = new Map();
|
const mapCallbackUriToRequestId = new Map();
|
||||||
|
@ -201,8 +214,8 @@ const server = http.createServer((req, res) => {
|
||||||
return handleExtension(req, res, parsedUrl);
|
return handleExtension(req, res, parsedUrl);
|
||||||
}
|
}
|
||||||
if (/^\/builtin-extension\//.test(pathname)) {
|
if (/^\/builtin-extension\//.test(pathname)) {
|
||||||
// builtin extension requests
|
// built-in extension requests
|
||||||
return handleBuiltinExtension(req, res, parsedUrl);
|
return handleBuiltInExtension(req, res, parsedUrl);
|
||||||
}
|
}
|
||||||
if (pathname === '/') {
|
if (pathname === '/') {
|
||||||
// main web
|
// main web
|
||||||
|
@ -256,19 +269,10 @@ function handleStatic(req, res, parsedUrl) {
|
||||||
async function handleExtension(req, res, parsedUrl) {
|
async function handleExtension(req, res, parsedUrl) {
|
||||||
// Strip `/extension/` from the path
|
// Strip `/extension/` from the path
|
||||||
const relativePath = decodeURIComponent(parsedUrl.pathname.substr('/extension/'.length));
|
const relativePath = decodeURIComponent(parsedUrl.pathname.substr('/extension/'.length));
|
||||||
const firstSlash = relativePath.indexOf('/');
|
const filePath = getExtensionFilePath(relativePath, (await defaultExtensionsPromise).locations);
|
||||||
if (firstSlash === -1) {
|
if (!filePath) {
|
||||||
return serveError(req, res, 400, `Bad request.`);
|
return serveError(req, res, 400, `Bad request.`);
|
||||||
}
|
}
|
||||||
const extensionId = relativePath.substr(0, firstSlash);
|
|
||||||
const { locations } = await defaultExtensionsPromise;
|
|
||||||
|
|
||||||
const extensionPath = locations[extensionId];
|
|
||||||
if (!extensionPath) {
|
|
||||||
return serveError(req, res, 400, `Bad request.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
const filePath = path.join(extensionPath, relativePath.substr(firstSlash + 1));
|
|
||||||
return serveFile(req, res, filePath);
|
return serveFile(req, res, filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,10 +281,13 @@ async function handleExtension(req, res, parsedUrl) {
|
||||||
* @param {import('http').ServerResponse} res
|
* @param {import('http').ServerResponse} res
|
||||||
* @param {import('url').UrlWithParsedQuery} parsedUrl
|
* @param {import('url').UrlWithParsedQuery} parsedUrl
|
||||||
*/
|
*/
|
||||||
async function handleBuiltinExtension(req, res, parsedUrl) {
|
async function handleBuiltInExtension(req, res, parsedUrl) {
|
||||||
// Strip `/builtin-extension/` from the path
|
// Strip `/builtin-extension/` from the path
|
||||||
const relativePath = decodeURIComponent(parsedUrl.pathname.substr('/builtin-extension/'.length));
|
const relativePath = decodeURIComponent(parsedUrl.pathname.substr('/builtin-extension/'.length));
|
||||||
const filePath = path.join(EXTENSIONS_ROOT, relativePath);
|
const filePath = getExtensionFilePath(relativePath, (await builtInExtensionsPromise).locations);
|
||||||
|
if (!filePath) {
|
||||||
|
return serveError(req, res, 400, `Bad request.`);
|
||||||
|
}
|
||||||
return serveFile(req, res, filePath);
|
return serveFile(req, res, filePath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -316,18 +323,23 @@ async function handleRoot(req, res) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const builtinExtensions = await builtinExtensionsPromise;
|
const { extensions: builtInExtensions } = await builtInExtensionsPromise;
|
||||||
const { extensions } = await defaultExtensionsPromise;
|
const { extensions: staticExtensions } = await defaultExtensionsPromise;
|
||||||
|
|
||||||
|
if (args.verbose) {
|
||||||
|
fancyLog(`${ansiColors.magenta('BuiltIn extensions')}: ${builtInExtensions.map(e => path.basename(e.extensionPath)).join(', ')}`);
|
||||||
|
fancyLog(`${ansiColors.magenta('Additional extensions')}: ${staticExtensions.map(e => path.basename(e.extensionLocation.path)).join(', ') || 'None'}`);
|
||||||
|
}
|
||||||
|
|
||||||
const webConfigJSON = escapeAttribute(JSON.stringify({
|
const webConfigJSON = escapeAttribute(JSON.stringify({
|
||||||
folderUri: folderUri,
|
folderUri: folderUri,
|
||||||
staticExtensions: extensions,
|
staticExtensions,
|
||||||
builtinExtensionsServiceUrl: `${SCHEME}://${AUTHORITY}/builtin-extension`
|
builtinExtensionsServiceUrl: `${SCHEME}://${AUTHORITY}/builtin-extension`
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const data = (await readFile(WEB_MAIN)).toString()
|
const data = (await readFile(WEB_MAIN)).toString()
|
||||||
.replace('{{WORKBENCH_WEB_CONFIGURATION}}', () => webConfigJSON) // use a replace function to avoid that regexp replace patterns ($&, $0, ...) are applied
|
.replace('{{WORKBENCH_WEB_CONFIGURATION}}', () => webConfigJSON) // use a replace function to avoid that regexp replace patterns ($&, $0, ...) are applied
|
||||||
.replace('{{WORKBENCH_BUILTIN_EXTENSIONS}}', () => escapeAttribute(JSON.stringify(builtinExtensions)))
|
.replace('{{WORKBENCH_BUILTIN_EXTENSIONS}}', () => escapeAttribute(JSON.stringify(builtInExtensions)))
|
||||||
.replace('{{WEBVIEW_ENDPOINT}}', '')
|
.replace('{{WEBVIEW_ENDPOINT}}', '')
|
||||||
.replace('{{REMOTE_USER_DATA_URI}}', '');
|
.replace('{{REMOTE_USER_DATA_URI}}', '');
|
||||||
|
|
||||||
|
@ -436,6 +448,25 @@ function escapeAttribute(value) {
|
||||||
return value.replace(/"/g, '"');
|
return value.replace(/"/g, '"');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {string} relativePath
|
||||||
|
* @param {Object.<string, string>} locations
|
||||||
|
* @returns {string | undefined}
|
||||||
|
*/
|
||||||
|
function getExtensionFilePath(relativePath, locations) {
|
||||||
|
const firstSlash = relativePath.indexOf('/');
|
||||||
|
if (firstSlash === -1) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const extensionId = relativePath.substr(0, firstSlash);
|
||||||
|
|
||||||
|
const extensionPath = locations[extensionId];
|
||||||
|
if (!extensionPath) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return path.join(extensionPath, relativePath.substr(firstSlash + 1));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {import('http').IncomingMessage} req
|
* @param {import('http').IncomingMessage} req
|
||||||
* @param {import('http').ServerResponse} res
|
* @param {import('http').ServerResponse} res
|
||||||
|
|
Loading…
Reference in a new issue