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

Allow property files to be node modules that export objects #89

Merged
merged 1 commit into from
May 21, 2018

Conversation

jreichenberg
Copy link
Contributor

@jreichenberg jreichenberg commented May 17, 2018

Issue #, if available: #85

Description of changes:
Allow property files to be node modules that export js objects, in addition to JSON files.

By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.

@jreichenberg
Copy link
Contributor Author

jreichenberg commented May 17, 2018

... can now do things like this in a property file...

const myProps = {
  foo: 1
  bar: 2
};

myProps.sameAsFoo = myProps.foo;
myProps.somethingInYaml = loadYaml(...);
myProps.fromElsewhere = require('something.json');

module.exports = myProps;

@dbanksdesign
Copy link
Member

Taking a look, but at first glance this looks pretty great! Thanks!

Copy link
Member

@dbanksdesign dbanksdesign left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, just have a question on the resolve-cwd module

@@ -35,12 +36,13 @@ function combineJSON(arr, deep, collision) {
}

for (i = 0; i < files.length; i++) {
var file_content = fs.readFileSync(files[i], 'utf8');
var resolvedPath = resolveCwd(path.isAbsolute(files[i]) ? files[i] : '.' + path.sep + files[i]);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this module needed? Is there an issue with relative paths in require() on line 43?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, the node resole alg. is basically (check me on this...)

if ./some/path.js or ../some/path.js start at the module you're in
if some/path.js resolve a node_module of name some and then the file path path.js

There's no part of it really that's "start at cwd() and give me file some/path relative to that".

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could leave that up to the end user to make process.cwd() part of the glob pattern, too, I suppose.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah ok, I see now. It's a difference in how fs.readFile and require resolve the file paths, and because we are changing how we get the file contents from fs to require this is to ensue it is backwards compatible. Thank you for explanation and care to make sure this doesn't break backwards compatibility.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the traditional method is to use fs.readFileSync(__dirname + './my-file')). The __dirname global is baked into node.js - https://nodejs.org/docs/latest/api/modules.html#modules_dirname

} catch (e) {
throw new SyntaxError(files[i] + ' - failed to parse JSON: ' + e.message);
throw new SyntaxError(files[i] + ' - failed to load or parse JSON or JS Object: ' + e.message);
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I noticed one other thing here.. by wrapping the e in a SyntaxError it loses some of the details about the actual error. The message is there, but accurate file and line number go missing. Any objections to just throwing the actual e here and maybe just maybe prepending the 'failed to load or parse JSON or JS Object' boilerplate to the actual e's message? The difference:

Throw the e:

TypeError: Cannot read property 'dimension' of undefined
    at tokens (/Users/e828613/sc/manhattan/mds-tokens/src/tokens/decisions/btn/btn-primary.js:4:40)
    at Object.<anonymous> (/Users/e828613/sc/manhattan/mds-tokens/src/tokens/decisions/btn/btn-primary.js:20:4)
    at Module._compile (module.js:652:30)
    at Object.Module._extensions..js (module.js:663:10)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
    at Function.Module._load (module.js:497:3)
    at Module.require (module.js:596:17)
    at require (internal/module.js:11:18)
    at combineJSON (/Users/e828613/sc/manhattan/mds-tokens/node_modules/style-dictionary/lib/utils/combineJSON.js:43:22)

Existing (with a different but similar underlying error) doesn't have the detail in the stack...

SyntaxError: src/tokens/decisions/btn/btn-primary.js - failed to load or parse JSON or JS Object: Cannot read property 'none' of undefined
    at combineJSON (/Users/e828613/sc/manhattan/mds-tokens/node_modules/style-dictionary/lib/utils/combineJSON.js:45:13)
    at Object.extend (/Users/e828613/sc/manhattan/mds-tokens/node_modules/style-dictionary/lib/extend.js:113:17)
    at Object.<anonymous> (/Users/e828613/sc/manhattan/mds-tokens/src/dictionary-config/style-dictionary.js:8:57)
    at Module._compile (module.js:652:30)
    at Object.Module._extensions..js (module.js:663:10)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
    at Function.Module._load (module.js:497:3)
    at Function.Module.runMain (module.js:693:10)
    at startup (bootstrap_node.js:188:16)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Very good point, yes we should throw the e, but make sure the message for JSON files shows the filename. We redid the errors a few weeks ago to be more descriptive so it is easier to debug the issue, and adding the filename helps a lot (it previously just had a generic JSON error with no filename). So this fits perfectly in that theme of useful error messages.

@jreichenberg jreichenberg force-pushed the issue-85-low-busget-fix branch from b0d7f21 to 10331ae Compare May 21, 2018 19:06
} catch (e) {
throw new SyntaxError(files[i] + ' - failed to parse JSON: ' + e.message);
e.message = 'Failed to load or parse JSON or JS Object: ' + e.message;
throw e;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See my outdated comment #89 (review) for an explanation. I think JSON error handling worked fine, but for all the kinds of errors that can be made in node modules the extra error detail is helpful.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JSON error example with new... file name is in the existing e.message:

/Users/e828613/sc/manhattan/mds-tokens/node_modules/style-dictionary/lib/utils/combineJSON.js:46
      throw e;
      ^

SyntaxError: Failed to load or parse JSON or JS Object: /Users/e828613/sc/manhattan/mds-tokens/src/tokens/options/color.json: Unexpected token , in JSON at position 1816
    at JSON.parse (<anonymous>)
    at Object.Module._extensions..json (module.js:671:27)
    at Module.load (module.js:565:32)
    at tryModuleLoad (module.js:505:12)
    at Function.Module._load (module.js:497:3)
    at Module.require (module.js:596:17)
    at require (internal/module.js:11:18)
    at combineJSON (/Users/e828613/sc/manhattan/mds-tokens/node_modules/style-dictionary/lib/utils/combineJSON.js:43:22)
    at Object.extend (/Users/e828613/sc/manhattan/mds-tokens/node_modules/style-dictionary/lib/extend.js:113:17)
    at Object.<anonymous> (/Users/e828613/sc/manhattan/mds-tokens/src/dictionary-config/style-dictionary.js:1:117)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perfect, thanks!

Copy link
Member

@dbanksdesign dbanksdesign left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! :shipit:

@Dashue
Copy link

Dashue commented Apr 2, 2020

@jreichenberg @dbanksdesign Was using json files and accidentally came across this pr.
Switched over to js files and wow what a difference in maintenance and development.

I thinkg the use-case with .js files deserves a better callout on the front page documentation. Would be invaluable to fellow developers like me coming along to use it.

@dbanksdesign
Copy link
Member

@Dashue definitely! The doc site definitely needs some love, we will keep this in mind for the next iteration.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants