-
-
Notifications
You must be signed in to change notification settings - Fork 31
Support npm install hook scripts #36
Comments
Well in my case I'd really like to have jspm-specific scripts, because with jspm there's no need to compile my ES6 to CJS using 6to5. So, my package .json would be like the following with a jspm-specific scripts section. {
"name": "infamous",
"scripts": { // ran by npm
"postinstall": "npm run build-cjs",
"build-cjs": "./node_modules/.bin/6to5 --optional coreAliasing src --source-maps-inline --out-dir . --modules common"
},
"jspm": {
"scripts": { // ran by jspm.
"postinstall": "mv src/* ."
}
}
} You're right about not being sure if jspm should run the // package.json
{
"name": "infamous",
"scripts": {
"postinstall": "npm run build-cjs",
"build-cjs": "./node_modules/.bin/6to5 --optional coreAliasing src --source-maps-inline --out-dir . --modules common"
},
"jspm": {
"scripts": true
}
} The default value of // package.json
{
"name": "infamous",
"scripts": {
"postinstall": "npm run build-cjs",
"build-cjs": "./node_modules/.bin/6to5 --optional coreAliasing src --source-maps-inline --out-dir . --modules common"
}
} would behave the same as // package.json
{
"name": "infamous",
"scripts": {
"postinstall": "npm run build-cjs",
"build-cjs": "./node_modules/.bin/6to5 --optional coreAliasing src --source-maps-inline --out-dir . --modules common"
},
"jspm": {
"scripts": false
}
} The logic roughly: if (jspm.scripts === true) {
run_root_level_scripts();
}
else if (jspm.scripts.constructor === Object) {
run_jspm_section_scripts();
} |
Since dependencies with jspm are flat, all in a single directory, I think this flexibility would make sense because there could be scripts that fail when a |
Hmm, but also if scripts are supported in the |
This issue is only tracking the support of |
True. I believe jspm users would like the freedom to run scripts regardless of endpoint 🎉, so I'm making that point here, and then, yeah, the result would need to be implemented over jspm-cli. |
jspm/jspm#377 shows how this feature (and rough example jspm/jspm#372) combined with code-based config could be nice. |
@trusktr I've yet to see a use case this would be useful for in jspm. |
The answer is simple: for packages that don't follow npm or github specs, and need special handling. It can't be any clearer than that. SUre, I can manually run a script, but making it simply automated is not much harder, and more convenient. |
I have to manually run a bash script after |
Trying installing leaflet and using it in your browser. Can you make it run without touching jspm's auto-generated config.js and without running any scripts after |
I meant, specifically try installing |
+1 for ability to define a jspm postinstall hook. In my case, I'm using jspm to manage various UI components that include JS and/or SASS. The JS part obviously works fine, but consuming the SASS partials doesn't work because SASS doesn't have a mechanism to resolve "@[version]" in the import paths. I realize SASS could be enhanced to work better with jspm, but a postinstall hook would allow me to create a workable solution for this now so that I can continue to use (and advocate for using) jspm within my team. |
I just hit this issue. Trying to work with
For me, trying to get JSPM to anticipate this kind of use case is impossible. It feels like making your code depend on a build artefact that you use a post-install script to generate (particularly one that explicitly refers to |
This would be highly appreciated. We have a bunch of modules that uses a npm post install hook to compile |
I have just run into this while trying to use I am trying to get node-sass to work as part of the SystemJS Sass plugin I'm working on. It would obviously only used for bundling (i.e. JSPM running in a Node env), whereas in-browser use of the plugin already works using sass.js. Is there any possible overrides or workarounds to get this to work? |
@theefer I'm trying to avoid running postinstall scripts because I don't think a browser package manager should give full permissions for dependencies to the host on install for security. It would be nice to approach the Node binary problem freshly in due course as well. In the mean time, it's not an advisable best-practice, but you could use See https://github.com/systemjs/plugin-css/blob/master/css-builder.js#L4 and https://github.com/systemjs/plugin-css/blob/master/css.js#L83 for example patterns here. |
Thanks for the feedback, makes sense.
I'm not sure what you mean by this? How/when would I trigger an npm install of |
@theefer with a message similar to https://github.com/systemjs/plugin-css/blob/master/css.js#L86 to make |
Ah right that makes sense! I can't seem to get
Being stupid I reckon? :) |
No this is a bug - the node require is from the internals of the SystemJS package, when we want a require scoped to the jspm project itself. I've created jspm/jspm#916. |
Hi, I've run into this issue with kerberos. It runs a node-gyp rebuild to build the operating system specific binaries via the "install" script which doesn't execute when I do a @guybedford I know you've said:
But there are just some npm packages that won't work and weren't built to work without running the preinstall, postinstall, and install. It's commonly expected that those scripts, if present, will always run for npm packages on install. In short, I believe to fully support npm packages the above mentioned scripts should be executed. I was thinking it's ok to do it in the npm-endpoint. The on('end') event callback function for extracting the package, after download, can be used to run the install scripts. The below code works. .on('end', function() {
//Flag initialised in processPackageConfig() to indicate whether the install scripts are present
if (self._runInstallScripts) {
//Run preinstall, install, and post install scripts if present.
asp(exec)('npm install', { cwd: targetDir }).then(function() {
//Remove node modules after then install scripts have run
return asp(exec)('rm -rf node_modules', { cwd: targetDir });
}).then(function() {
resolve();
}).catch(function(error) {
reject(error);
})
}
else {
resolve();
}
}); Note the if (pjson.scripts && pjson.scripts.install) {
this._runInstallScripts = true;
} The users of jspm don't need to be in control of the scripts installing because it's default behaviour for npm packages. I'm willing to create a pull request. I hope this is helpful. |
jspm is a browser package manager, and is not trying to replace npm for server-side code execution. We will be expanding server code support more and more to cover universal javascript use cases, but supporting everything npm does is not currently a goal. |
@guybedford As shown in the diagram below, the standard implementation of the App depends on the Navi package and the Details package. These two package also depend on Map (Google). The easiest solution would be to use a Do you have any other suggestions? |
Hi @guybedford, but what we are talking about is not an explicit server feature. We need an install hook at build or install time at the command line when you run |
I still haven't heard a compelling use case for such a hook. For example I think @chauthai's post is solved nicely by peer dependencies in the 0.17 jspm. |
Nice to hear. Do you have any example or documentation about that new feature in |
I have a case 😄: Able to run EDIT: Notice this is only for |
For this use case, we need to find typings approaches in jspm based on module metadata and that don't require execution. Help paving this work is very welcome. Install hooks are a big security issue. |
I also have a use-case that has to do with typescript :) : |
I guess we could support npm-style |
Created a proposal at jspm/jspm#1899. |
@frederick, can you share your code? I need to do similar things for |
@guybedford I am working on the details and will include you to the discussion. |
@unional Yes but this is a pretty naive implementation ;-) #! /usr/bin/env node
import * as path from "path";
import * as fs from "fs";
import * as System from "systemjs";
const PROCESS_WORKING_DIR = process.cwd();
const loadSystemConfig = () => {
require(path.join(PROCESS_WORKING_DIR, "jspm.config.js"));
};
const loadTypescriptConfig = () => {
return require(path.join(PROCESS_WORKING_DIR, "tsconfig.json"));
};
const loadPackage = () => {
return require(path.join(PROCESS_WORKING_DIR, "package.json"));
};
const setTypescriptBaseUrl = (tsconfig: any, jspmPackagesDirectory: string) => {
tsconfig.compilerOptions.baseUrl = tsconfig.compilerOptions.baseUrl || path.join(".", jspmPackagesDirectory);
};
const setTypescriptPaths = (tsconfig: any, paths: any) => {
tsconfig.compilerOptions.paths = paths;
};
const saveTypescriptConfig = (tsconfig: any) => {
fs.writeFileSync(path.join(PROCESS_WORKING_DIR, "tsconfig.json"), JSON.stringify(tsconfig, null, 2));
};
const getPackageMainFile = (dependencyName: string, packagePath: string) => {
let packageMainFile;
try {
const dependencyPackage = require(packagePath);
packageMainFile = dependencyPackage.main;
} catch (error) {
console.warn(`Dependency ${dependencyName} has no main entry in its package.json`);
}
return packageMainFile;
};
const removeJsSuffix = (path) => {
if (path.endsWith(".js")) {
path = path.substring(0, path.length - 3);
}
return path;
};
const sanitizeMainPath = (mainPath: string) => {
let sanitizedMainPath = mainPath.replace("./", "");
return removeJsSuffix(sanitizedMainPath);
};
const mapSystemConfigToTypescriptConfig = () => {
loadSystemConfig();
let tsconfig = loadTypescriptConfig();
const pkg = loadPackage();
const JSPM_PACKAGES_DIRECTORY = pkg.jspm && pkg.jspm.directories && pkg.jspm.directories.packages || "jspm_packages";
const JSPM_PACKAGES_PATH = path.join(PROCESS_WORKING_DIR, JSPM_PACKAGES_DIRECTORY);
const jspmDependencies = System.map;
const jspmDependencyNames = Object.keys(jspmDependencies);
let paths = {};
jspmDependencyNames.forEach(dependencyName => {
const dependencyPath = jspmDependencies[dependencyName].replace("npm:", "npm/").replace("github:", "github/");
paths[`${dependencyName}*`] = [
`${dependencyPath}*`,
`${dependencyPath}/index`
];
const dependencyMainFile = getPackageMainFile(dependencyName, path.join(JSPM_PACKAGES_PATH, dependencyPath, "package.json"));
if (dependencyMainFile) {
paths[`${dependencyName}*`].push(path.join(dependencyPath, sanitizeMainPath(dependencyMainFile)));
}
});
setTypescriptBaseUrl(tsconfig, JSPM_PACKAGES_DIRECTORY);
setTypescriptPaths(tsconfig, paths);
saveTypescriptConfig(tsconfig);
};
mapSystemConfigToTypescriptConfig(); |
I wonder how well this will work?
The text was updated successfully, but these errors were encountered: