(isDev: boolean)
| 11 | const fsPromises = fs.promises; |
| 12 | |
| 13 | export async function scanSystemExtensions(isDev: boolean): Promise<IExtension[]> { |
| 14 | const extensionPath = isDev ? './extensions' : './resources/extensions'; |
| 15 | |
| 16 | const result = new Map<string, IExtension>(); |
| 17 | |
| 18 | await fsPromises.readdir(extensionPath) |
| 19 | .then(filenames => { |
| 20 | // Each folder inside is an Extension |
| 21 | return Promise.all(filenames.map(async filename => { |
| 22 | // Make sure it is a folder or symlink folder |
| 23 | const stats = await fs.promises.stat(path.join(extensionPath, filename)); |
| 24 | if (!stats.isDirectory()) { return; } |
| 25 | // Read Manifest |
| 26 | const manifestPath = path.join(extensionPath, filename, 'package.json'); |
| 27 | return fsPromises.stat(manifestPath) |
| 28 | .then(async (stats) => { |
| 29 | // Manifest file (package.json) exists, continue loading extension |
| 30 | if (stats.isFile()) { |
| 31 | await fsPromises.access(manifestPath); |
| 32 | const ext = await parseExtension(manifestPath, ExtensionType.User); |
| 33 | if (result.get(ext.id) !== undefined) { |
| 34 | // An Extension with the same id has been registered earlier, latest read survives |
| 35 | log.warn('Extensions', `Overriding Extension ${ext.id} with extension at "${path.join(extensionPath, filename)}"`); |
| 36 | } |
| 37 | result.set(ext.id, ext); |
| 38 | } |
| 39 | }) |
| 40 | .catch(err => log.error('Extensions', `Error loading User extension at "${filename}"\n${err}`)); |
| 41 | })); |
| 42 | }) |
| 43 | .catch(() => { |
| 44 | log.warn('Launcher', 'Failed to read System Extensions folder. This may be expected behaviour.'); |
| 45 | }); |
| 46 | |
| 47 | // Convert the map to an array and return |
| 48 | const r: IExtension[] = []; |
| 49 | result.forEach((ext) => { |
| 50 | log.debug('Extensions', `System Extension Scanned "${ext.manifest.displayName || ext.manifest.name}" (${ext.id})`); |
| 51 | r.push(ext); |
| 52 | }); |
| 53 | return r; |
| 54 | } |
| 55 | |
| 56 | // Hacky way to prevent loading extensions that have been replaced with system extensions |
| 57 | const UNSUPPORTED_EXTENSION_IDS = [ |
no test coverage detected