Does anyone have any insight on how the require logic is implemented in the sandbox environments used for rules, hooks and custom DB scripts, and how this can be replicated locally?
The canirequire site provides snippets showing how the version should be included in the require function in order to specify a particular version of a library to use. For example, for Axios, you can use any of the following:
Alternatively you can just use require('axios'); and a version of Axios is imported, though I prefer to define this explicitly so I can feel confident the default version won’t change under me and potentially break something.
The trouble is that by default if you run the code locally (e.g. in unit tests) you’ll get an error, because if you npm install axios@0.19.2 it’ll install to node_modules/axios, not node_modules/axios@0.19.2.
I’ve tried a couple of approaches to work around the issue:
In the script, check if the client is in global and, if not, use require('axios@0.19.2') and add it to global. In unit tests I then require('axios') and set it in the global, so the require in the main script isn’t invoked.
In package.json use postinstall scripts to symlink the versioned package names with link, e.g. "axios": "link node_modules/axios@0.19.2"
These both work but both feel a bit smelly. I’ve tried installing these packages with alias names but @ can’t be used in aliases so that didn’t work. I’m guessing in the Auth0 sandbox either the packages are available at those paths, or Auth0 has overridden require.resolve or similar, but I don’t have a great deal of experience with NodeJS or NPM and have been unable to do either in a way that I’m happy with.
Does anyone have any suggestions on how this could be done more nicely?
I think you guessed it correctly in terms of what does the sandbox does by overriding requires to handle the special notation with version.
I’m unsure what’s an acceptable approach for this, but I can share my personal option about what I would likely consider if I had to do something similar. I would likely pre-process the target of the tests to replace the special notation with a version into the regular notation and then just ensure that the locally installed versions match the ones being required.
Hi @jmangelo, thanks very much for the quick response!
OK, so I’m glad to hear I’m not missing something obvious. Do you have any recommendations on what to use to do the pre-processing?
An alternative option that will be easier for me is to commit the code with require('axios') but do the replacement to require('axios@0.19.2') on upload to Auth0, as I’m already doing a number of other replacements to aid unit testing and code re-use (so I’m surprised I didn’t think of replacing this as well!).
Do you see any reason not to do it this way instead?
I think doing this processing in one way (to remove the version suffix) or the other way around (add the version suffix) should be doable. If you’re already doing some level of processing for other purposes I would just add this additional action.
The most important part would be to be sure that the tests run with same version as it is going to be used in Auth0 sandbox. In terms of recommendations of what to use to do the processing although using regular expressions is a consideration on its own, I think they could be a good approach for this and regular expressions are available in pretty much every tech stack.
Regarding the pre-processing, I wondered if you were meaning something fancy like WebPack. But yeah, regular expressions sound good, I’m already using these in Terraform when the scripts are uploaded.