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

package.json main attribute should be a string #4743

Closed
sbruno opened this issue Nov 20, 2015 · 12 comments · Fixed by #5512
Closed

package.json main attribute should be a string #4743

sbruno opened this issue Nov 20, 2015 · 12 comments · Fixed by #5512

Comments

@sbruno
Copy link
Contributor

sbruno commented Nov 20, 2015

I'm using ui-grid on a nodejs project and it is failing to do a npm publish because it expects package.json main to be a string and currently it is an array

npm verb stack TypeError: Path must be a string. Received [ './less',
npm verb stack   './ui-grid.css',
npm verb stack   './ui-grid.eot',
npm verb stack   './ui-grid.js',
npm verb stack   './ui-grid.svg',
npm verb stack   './ui-grid.ttf',
npm verb stack   './ui-grid.woff' ]
npm verb stack     at assertPath (path.js:8:11)
npm verb stack     at Object.win32.resolve (path.js:130:5)
npm verb stack     at Packer.applyIgnores (C:\Program Files\nodejs\node_modules\npm\node_modules\fstream-npm\fstream-npm.js:109:59)
npm verb stack     at Packer.<anonymous> (C:\Program Files\nodejs\node_modules\npm\node_modules\fstream-npm\node_modules\fstream-ignore\ignore.js:181:17)
npm verb stack     at Array.filter (native)
npm verb stack     at Packer.IgnoreReader.filterEntries (C:\Program Files\nodejs\node_modules\npm\node_modules\fstream-npm\node_modules\fstream-ignore\ignore.js:179:31)
npm verb stack     at Packer.<anonymous> (C:\Program Files\nodejs\node_modules\npm\node_modules\fstream-npm\node_modules\fstream-ignore\ignore.js:92:12)
npm verb stack     at Packer.<anonymous> (C:\Program Files\nodejs\node_modules\npm\node_modules\fstream-npm\node_modules\fstream-ignore\ignore.js:134:5)
npm verb stack     at C:\Program Files\nodejs\node_modules\npm\node_modules\graceful-fs\graceful-fs.js:76:16
npm verb stack     at FSReqWrap.readFileAfterClose [as oncomplete] (fs.js:380:3)

On older versions of node it was not failing probably because node is now doing some validation, but according to the docs, an array is not valid and it should be a string:
https://docs.npmjs.com/files/package.json#main

The array was added by this issue: #3673
It looks as some tool extracts information from the main property of bower.json, but it does not say anything about package.json.
Maybe package.json is generated from bower.json, but some special care should be taken for the main attribute.
I see that in the source, package.json and bower.json are different, in fact, package.json does not contain a main attribute. But when I see my module at src\web-app\bower_components\angular-ui-grid\package.json it looks like bower.json

https://github.com/angular-ui/ui-grid/blob/master/bower.json
https://github.com/angular-ui/ui-grid/blob/master/package.json

For example, bootstrap-bower have different values for main in bower.json and package.json:

https://github.com/angular-ui/bootstrap-bower/blob/master/bower.json

https://github.com/angular-ui/bootstrap-bower/blob/master/package.json

Ohh... After inspecting a bit the code, it looks as the problem is in this task, that is copying the same contents to package.json and bower.json:

fs.writeFileSync(pkgJsonFile, JSON.stringify(json, null, 2));

@oji
Copy link

oji commented Nov 20, 2015

Same here...

@imbalind
Copy link
Contributor

@sbruno do you know how we could fix this? I'm not an expert in this matter, but if you don't feel like making a PR and you can explain me what to do I'll do it

@sbruno
Copy link
Contributor Author

sbruno commented Nov 28, 2015

@imbalind I'm not an expert either...
As a workaround for my use case I just replaced the list with the string './ui-grid.js'

I think there are a couple of possibilities, but I don't know if they could have any side effect in npm packaging.

One option, since the source code already has a package.json could be to save it as is to the distribution package. The plugin.js file I mentioned, creates a new one and adds a version, but the package.json in the source already has a version. Anyway we could keep the code that saves the verision, just instead of using the json object used for generating the bower.json file use the object read from the source package.json. This is done in line 11 of plugins.js:

var pkg = require(path.resolve(projectPath, 'package.json'));

So the change could be something like this:

diff --git a/lib/grunt/plugins.js b/lib/grunt/plugins.js
index 7be0968..c25b50c 100644
--- a/lib/grunt/plugins.js
+++ b/lib/grunt/plugins.js
@@ -331,9 +331,9 @@ module.exports = function(grunt) {
     fs.writeFileSync(bowerJsonFile, JSON.stringify(json, null, 2));

     // Add version for package.json
-    json.version = currentTag;
+    pkg.version = currentTag;

-    fs.writeFileSync(pkgJsonFile, JSON.stringify(json, null, 2));
+    fs.writeFileSync(pkgJsonFile, JSON.stringify(pkg, null, 2));
   });

   // Publish release to NPM

I think that may work....

Other option could be to overwrite the main attribute of the object that is now being saved to bower.json and package json, choosing the .js file of the array, when saving it to the package.json file. Something like:

// Add version for package.json
json.version = currentTag;

///// START OF NEW CODE
// Set the right main value in package.json
json.main = GetSomehowTheJSFile(json.main)  // should return string "./ui-grid.js"
///// END OF NEW CODE

fs.writeFileSync(pkgJsonFile, JSON.stringify(json, null, 2));

This would be implementing the workaround.

sbruno added a commit to sbruno/ui-grid that referenced this issue Nov 29, 2015
The same contents saved to bower.json were being saved to package.json, generating an invalid package.json since the main attribute was an array instead of a string. Now this has been changed, and the package.json generated for distribution contains the same contents of the package.json file in the source code.

Fixes angular-ui#4743
@sbruno
Copy link
Contributor Author

sbruno commented Nov 29, 2015

@imbalind I created a PR for the first option: #4785

@logeshthedev
Copy link

@imbalind When this pull would be merged in to master?
Thanks for the fix @sbruno

@karsunke
Copy link

Is there a workaround for this? I do have the same problem.

@lpand
Copy link
Contributor

lpand commented Jan 13, 2016

+1

I managed to get through this with these lines in the package.json

"browser": {
    "angular-ui-grid": "./node_modules/angular-ui-grid/ui-grid.js"
}

@sbruno
Copy link
Contributor Author

sbruno commented Jan 13, 2016

In my case, I did a script to modify the contents of the package.json and added it to the build system.

// Hack angular-ui-grid until bug gets fixed https://github.com/angular-ui/ui-grid/issues/4743
var fs = require("fs");
var file = "web-app/bower_components/angular-ui-grid/package.json";
var contents = fs.readFileSync(file);
var json = JSON.parse(contents);
json.main = './ui-grid.js';
fs.writeFileSync(file, JSON.stringify(json, null, 4));

imbalind pushed a commit to imbalind/ui-grid that referenced this issue Jan 16, 2016
The same contents saved to bower.json were being saved to package.json, generating an invalid package.json since the main attribute was an array instead of a string. Now this has been changed, and the package.json generated for distribution contains the same contents of the package.json file in the source code.

Fixes angular-ui#4743
@JLLeitschuh
Copy link
Contributor

This broke releasing.
The fix that was merged was invalid. This broke our ability to release files.
The package.json file that we use for our project and the one for our releases are very different. We can't use the same file for these things.

@JLLeitschuh JLLeitschuh reopened this Jan 19, 2016
@Choc13
Copy link

Choc13 commented Feb 29, 2016

Would it not be possible to add an index.js file to the root of the project with the following contents:

require("./less");
require("./ui-grid.css");
require("./ui-grid.eot");
require("./ui-grid.js");
require("./ui-grid.svg");
require("./ui-grid.ttf");
require("./ui-grid.woff");
module.exports = 'ui.grid';

Then in package.json it would simply be:

"main": "./index.js",

This would be great for me as I am using webpack and typescript and it would allow me to just do an import 'angular-ui-grid'; in my app and have it load all the necessary scripts and assets. But I'm not sure if this is a general solution that will work for others using different build tools.

If those who opened this ticket think that this is a solution that will work for them then I'm happy to make the change and open the PR.

@alperg
Copy link

alperg commented Mar 10, 2016

@Choc13, I use gulp as my build tool and unfortunately your solution didn't work for me.

@cwalther
Copy link

For me, using "main": "./ui-grid.js", removing "main" altogether, or any other legal value would work, as we refer to ui-grid.js directly and nothing in our setup uses package.json (even the npm pack that trips over it probably shouldn’t even look at it, it’s just another file that goes somewhere in the package, angular-ui-grid is not being installed as a node module).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment