Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed handling github/url dependencies #1609

Merged
merged 5 commits into from
Jun 13, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,11 @@ Executes Javascript, Typescript Scripts.
<!--
### **WORK IN PROGRESS**
-->

### **WORK IN PROGRESS**

* (foxriver76) fixed issue with additional node modules which are installed from GitHub (controller v6)

### 8.5.2 (2024-06-11)

* (foxriver76) fixed issue with additional node modules when using js-controller version 6
Expand Down
26 changes: 26 additions & 0 deletions lib/nodeModulesManagement.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const { exec: execAsync } = require('promisify-child-process');

/**
* Request a module name by given url using `npm view`
*
* @param {string} url the url to the package which should be installed via npm
* @returns {Promise<string>}
*/
async function requestModuleNameByUrl(url) {
const res = await execAsync(`npm view ${url} name`, {
windowsHide: true,
encoding: 'utf8'
});

if (typeof res.stdout !== 'string') {
throw new Error(
`Could not determine module name for url "${url}". Unexpected stdout: "${res.stdout ? res.stdout.toString() : ''}"`
);
}

return res.stdout.trim();
}

module.exports = {
requestModuleNameByUrl
};
112 changes: 59 additions & 53 deletions main.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ const forbiddenMirrorLocations = [
const utils = require('@iobroker/adapter-core');
const words = require('./lib/words');
const sandBox = require('./lib/sandbox');
const { requestModuleNameByUrl } = require('./lib/nodeModulesManagement.js');
const eventObj = require('./lib/eventObj');
const Scheduler = require('./lib/scheduler');
const { targetTsLib, tsCompilerOptions, jsDeclarationCompilerOptions } = require('./lib/typescriptSettings');
Expand Down Expand Up @@ -1825,75 +1826,80 @@ async function installNpm(npmLib) {
}

async function installLibraries() {
if (adapter.config && adapter.config.libraries) {
const libraries = adapter.config.libraries.split(/[,;\s]+/);
if (!adapter.config?.libraries) {
return;
}

let installedNodeModules = [];
const keepModules = [];
const libraries = adapter.config.libraries.split(/[,;\s]+/);

// js-controller >= 6.x
if (typeof adapter.listInstalledNodeModules === 'function') {
installedNodeModules = await adapter.listInstalledNodeModules();
let installedNodeModules = [];
const keepModules = [];

adapter.log.debug(`Found installed libraries: ${JSON.stringify(installedNodeModules)}`);
}
// js-controller >= 6.x
if (typeof adapter.listInstalledNodeModules === 'function') {
installedNodeModules = await adapter.listInstalledNodeModules();

for (let lib = 0; lib < libraries.length; lib++) {
if (libraries[lib] && libraries[lib].trim()) {
libraries[lib] = libraries[lib].trim();
let depName = libraries[lib];
let version = 'latest';
adapter.log.debug(`Found installed libraries: ${JSON.stringify(installedNodeModules)}`);
}

if (depName.includes('@') && depName.lastIndexOf('@') > 0) {
const parts = depName.split('@');
version = parts.pop() ?? 'latest';
depName = parts.join('@');
}
for (const lib of libraries) {
let depName = lib;
let version = 'latest';

keepModules.push(depName);
if (depName.includes('@') && depName.lastIndexOf('@') > 0) {
const parts = depName.split('@');
version = parts.pop() ?? 'latest';
depName = parts.join('@');
}

adapter.log.debug(`Found custom dependency in config: "${depName}@${version}"`);
/** The real module name, because the dependency can be an url too */
let moduleName = depName;

if (URL.canParse(depName)) {
moduleName = await requestModuleNameByUrl(depName);
}

// js-controller >= 6.x
if (typeof adapter.installNodeModule === 'function') {
try {
const result = await adapter.installNodeModule(depName, { version });
if (result.success) {
adapter.log.debug(`Installed custom custom dependency: "${depName}@${version}"`);
keepModules.push(moduleName);

context.mods[depName] = (await adapter.importNodeModule(depName)).default;
} else {
adapter.log.warn(`Cannot install custom npm package "${libraries[lib]}"`);
}
} catch (err) {
adapter.log.warn(`Cannot install custom npm package ${libraries[lib]}: ${err}`);
}
} else if (!nodeFS.existsSync(`${__dirname}/node_modules/${depName}/package.json`)) {
// js-controller < 6.x
adapter.log.info(`Installing custom dependency (legacy mode): "${depName}@${version}"`);
adapter.log.debug(`Found custom dependency in config: "${depName}@${version}"`);

try {
await installNpm(libraries[lib]);
// js-controller >= 6.x
if (typeof adapter.installNodeModule === 'function') {
try {
const result = await adapter.installNodeModule(depName, { version });
if (result.success) {
adapter.log.debug(`Installed custom dependency: "${depName}@${version}"`);

adapter.log.info(`Installed custom npm package (legacy mode): "${libraries[lib]}"`);
} catch (err) {
adapter.log.warn(`Cannot install custom npm package "${libraries[lib]}" (legacy mode): ${err}`);
}
context.mods[depName] = (await adapter.importNodeModule(moduleName)).default;
} else {
adapter.log.warn(`Cannot install custom npm package "${lib}"`);
}
} catch (e) {
adapter.log.warn(`Cannot install custom npm package "${lib}": ${e.message}`);
}
} else if (!nodeFS.existsSync(`${__dirname}/node_modules/${depName}/package.json`)) {
// js-controller < 6.x
adapter.log.info(`Installing custom dependency (legacy mode): "${depName}@${version}"`);

try {
await installNpm(lib);
adapter.log.info(`Installed custom npm package (legacy mode): "${libraries[lib]}"`);
} catch (err) {
adapter.log.warn(`Cannot install custom npm package "${libraries[lib]}" (legacy mode): ${err}`);
}
}
}

// js-controller >= 6.x
if (typeof adapter.uninstallNodeModule === 'function') {
for (const installedNodeModule of installedNodeModules) {
if (!keepModules.includes(installedNodeModule)) {
try {
await adapter.uninstallNodeModule(installedNodeModule);
// js-controller >= 6.x
if (typeof adapter.uninstallNodeModule === 'function') {
for (const installedNodeModule of installedNodeModules) {
if (!keepModules.includes(installedNodeModule)) {
try {
await adapter.uninstallNodeModule(installedNodeModule);

adapter.log.info(`Removed custom npm package: "${installedNodeModule}"`);
} catch (err) {
adapter.log.warn(`Cannot remove custom npm package ${installedNodeModule}: ${err}`);
}
adapter.log.info(`Removed custom npm package: "${installedNodeModule}"`);
} catch (err) {
adapter.log.warn(`Cannot remove custom npm package ${installedNodeModule}: ${err}`);
}
}
}
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@
"jszip": "^3.10.1",
"node-inspect": "^2.0.0",
"node-schedule": "2.1.1",
"promisify-child-process": "^4.1.2",
"request": "^2.88.2",
"semver": "^7.6.2",
"suncalc2": "^1.8.1",
Expand Down
Loading