Skip to content
This repository has been archived by the owner on Jun 5, 2021. It is now read-only.

Non Relative Imports #32

Open
wants to merge 45 commits into
base: master
Choose a base branch
from

Conversation

enriched
Copy link
Contributor

@enriched enriched commented Oct 24, 2018

This basically enables creating the node_modules directory in a more specific way. Instead of symlinking a node_modules folder directly it constructs a node_modules folder with all of the module folders symlinked. That allows for mixing in other modules that can be resolved using the typical node module resolution strategy.

I also added in the concept of a JsContext that wraps a rule context. I attempted to do this in a similar way to rules_go. The JsContext exposes a function js.library_info(js, attr) which exposes some common functionality for extracting common javascript attributes.

The beginnings of common sharable actions are in the internal/common/actions directory. Currently there is an action for running javascript with node, and an action for creating a source directory.


This change is Reviewable

@enriched
Copy link
Contributor Author

@fwouts I think that this is ready for some review now. There is a lot of work around having some more shared generic js Providers in internal/common/context.bzl. I thought that it would make more sense to have this generic JsLibraryInfo provider that rule attributes get sorted into. Then some additional providers that could be extracted from the JsLibraryInfo + (some additional information). The JsModuleInfo has a lot of overlap with the JsLibraryInfo but is intended to be able to define modules without being 1:1 with a rule.

examples/node-typescript-app/tsconfig.json Show resolved Hide resolved
* mr: Recursive module (add all the modules to node_modules)
* g: Generate (run the passed in script to generate source files
*
* eg. node create_source_dir.js s:file/to/symlink.
Copy link
Owner

Choose a reason for hiding this comment

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

Add --into and --from to the example?

* symlink=true (default)
*
*
* The files to be populated have flags set on them for the appropriate actions:
Copy link
Owner

Choose a reason for hiding this comment

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

This is awesome.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks! I was trying to make it fairly generic. Would love to hear what you think about the syntax of flags:some/path:some/other/path:or_a_parameter I was originally thinking of using URLs with params. But it didn't seem like it would be well suited for specifying associations between multiple paths, which is what this thing needs to do well.

Copy link
Owner

Choose a reason for hiding this comment

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

I think that should work pretty well. We should always be able to rethink this if need be at a later point.

An alternative would be to use something like a Base64-encoded JSON object or protocol buffer message, removing any issues about special characters and giving us full flexibility in the structure of the object. But that's probably overkill at this point!

Copy link
Owner

@fwouts fwouts left a comment

Choose a reason for hiding this comment

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

🚀 🎉 🎆 Amazing.

There are a few slightly unrelated changes in here (Prettier, upgrading rules_nodejs, reformatting with Buildifier, etc).

Do you mind if we split each of them into their own PR? I don't mind doing this to save you the extra work.

* r: Recurse
* rs:./some/dir/
* m: Module (put it in node_modules)
* mr: Recursive module (add all the modules to node_modules)
Copy link
Owner

Choose a reason for hiding this comment

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

What does "all the modules" mean here? This module and all its dependencies?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This should probably be mrs:./some/node_modules basically it is able to take in a node modules directory and do a 1 deep symlinking of it. It will go an additional layer down for directories that begin with "@".

Copy link
Owner

Choose a reason for hiding this comment

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

OK, do you mind updating the code comment with this info?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Pushed an update to the documentation for this.

async args => {
const { current_target, workspace_name, package_path, from, into } = args;
const sources = ensureArray(args._);
// console.log(sources);
Copy link
Owner

Choose a reason for hiding this comment

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

Remove this? (same below)

Alternatively, should we have a global DEBUG constant we can switch on/off?

@@ -0,0 +1,43 @@
load("//internal/npm_packages:rule.bzl", "NpmPackagesInfo")

def run_js(
Copy link
Owner

Choose a reason for hiding this comment

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

Thanks for this. Rules that use it look a lot better.

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 agree, I think that I have it about where I want it. I was trying to abstract over some of the Bazel specific stuff with the combination of this and the BazelAction js function. Currently the primary thing that it handles is parsing a param file if bazel decides to generate one. But would be nice in the future to have it expose the ability to be run as a bazel worker. But I haven't looked too deeply into that yet.

internal/common/context.bzl Outdated Show resolved Hide resolved
internal/common/context.bzl Outdated Show resolved Hide resolved
internal/common/context.bzl Outdated Show resolved Hide resolved
internal/common/context.bzl Outdated Show resolved Hide resolved
internal/ts_library/rule.bzl Outdated Show resolved Hide resolved
outputs = {
"compilation_src_dir": "%{name}_compilation_src",
"compiled_dir": "%{name}_compiled",
# "transpilation_src_dir": "%{name}_transpilation_src",
Copy link
Owner

Choose a reason for hiding this comment

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

Is this no longer needed?

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 don't think so, but I know that you added it in the first place because using TypeScripts fast transpilation created a shorter critical path. Not sure if there are other rules using these outputs and looks like I might find out once I get to fixing the build for this PR.

@enriched
Copy link
Contributor Author

@fwouts I definitely don't mind putting the prettier, buildifier, and updated rules_nodejs in separate PRs. I probably don't have time to do so todya, so if you can get to it sooner much appriciated 🙇

@fwouts
Copy link
Owner

fwouts commented Oct 24, 2018

@fwouts I definitely don't mind putting the prettier, buildifier, and updated rules_nodejs in separate PRs. I probably don't have time to do so todya, so if you can get to it sooner much appriciated 🙇

On it :)

Copy link
Contributor Author

@enriched enriched left a comment

Choose a reason for hiding this comment

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

Removed some of the easy to get rid of cruft

internal/common/context.bzl Outdated Show resolved Hide resolved
@fwouts
Copy link
Owner

fwouts commented Nov 21, 2018

Hey @enriched, what are the next steps to unblock this PR?

@enriched
Copy link
Contributor Author

Sorry I have been so quiet on this, ran out of time and needed to more forward but I'm hoping to wrap this one up soon.

@olegsmetanin my current understanding of the module_name attribute is that it is discovered by the module_mappings_runtime_aspect the rules_nodej implements the aspect as well but neither makes the aspect public. We could reimplement the aspect in these rules, but it seems like a strange pattern for everyone to implement an aspect that looks for module_name or module_root and assumes that is a non relative module. A better pattern would be to have a shared javascript provider as proposed in bazel-contrib/rules_nodejs#57. This PR creates some common providers that can at least be used internally to bazel-javascript.

@fwouts To unblock this I think all of the rules need to use js_context and used the shared providers defined in common:

I would also appreciate any comments you have around the architecture of these. They are modeled after the go providers:

My current thinking for what these represent for these rules:

JsLibraryInfo

Metadata that is extracted from the common js rule attributes by the js_library_info helper.

JsSourceInfo

Not sure if I actually need this one. But it is the information to create a transpilation source with the common create_source_dir action. It is intended to have information about file toplolgies and scripts that generate files in the transpilation source.

JsModuleInfo

Represents a javascript module, with the information about its transitive dependencies, the non-relative import name, and the path to the imported file/folder.

@fwouts
Copy link
Owner

fwouts commented Dec 8, 2018

Apologies @enriched, I'm just coming back from two consecutive trips. I'll try and take a look in detail tomorrow with a fresh mind.

Copy link
Owner

@fwouts fwouts left a comment

Choose a reason for hiding this comment

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

This is quite large so I'm struggling to wrap my head around it all :) But the overall structure of the providers looks reasonable to me. We can remove JsSourceInfo later if need be, but it seems like a useful abstraction for now.

In terms of making the other rules start using js_context, would you like me to try and migrate a couple to get my hands dirty?

script_args.add("--into", create_dir)
script_args.add("--from", js.package_path)

for gen_script in gen_scripts:
Copy link
Owner

Choose a reason for hiding this comment

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

This could use a few comments, what is gen_scripts?

all_dep_module_targets = all_dep_module_targets,
)

def _library_to_source_info(js, library, gen_scripts = None):
Copy link
Owner

Choose a reason for hiding this comment

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

Would you mind adding some comments about gen_scripts here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Part of this is that I am still a little unsure about what the gen_scripts signature should look like. Currently the example is internal/ts_library/gsconfig.gen.js. The file exports a function as module.exports eg(with typescript types for some added clarity):

module.exports = async (ctx: {package: string, into: string, inputs: string[] }): Promise<{path: string, body: string}[]> => {}

Copy link
Owner

Choose a reason for hiding this comment

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

OK—that looks like a good start, we can always adjust as we go later.


Args:
js: JsContext object
script_file: File object for the script to be run
Copy link
Owner

Choose a reason for hiding this comment

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

I assume this is currently missing from the args because you haven't gotten around to that part?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was removed and I forgot to remove it from the args. Now the script is not specified when creating an args object. The run_js action needs the script anyway because it needs to pass an array with the script followed by the args object.

"js",
# The source js files
"srcs",
# List of scripts to output
Copy link
Owner

Choose a reason for hiding this comment

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

This could also be a bit more specific.

internal/common/context.bzl Outdated Show resolved Hide resolved
@fwouts
Copy link
Owner

fwouts commented Jan 9, 2019

Happy new year @enriched! 🎉

I'd like to make sure we get this merged within the next month or two. Please let me know what I can do to help :)

@fwouts
Copy link
Owner

fwouts commented Apr 24, 2019

@enriched Are you planning to continue work on this PR, or should we pick it up where you left off?

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

Successfully merging this pull request may close these issues.

3 participants