New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

amidala

Package Overview
Dependencies
Maintainers
1
Versions
7
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

amidala

Asynchronous AMD loading of CommonJS modules (no build step)

  • 1.2.2
  • npm
  • Socket score

Version published
Weekly downloads
1
decreased by-50%
Maintainers
1
Weekly downloads
 
Created
Source

Asynchronous CommonJS/AMD Loader

This module loads NPM modules (CommonJS) as AMD modules.

Unlike RequireJS, which requires a monolithic compile step and returns a single bundle, this loader loads each file separately. This makes development/debugging easier, because your modules are not all munged together.

AMD modules should still work (the CommonJS conversion aims to preserve that functionality).

Usage

// Dynamic loading - location is arbitrary
app.use('/amidala/', amd.dynamic());
<script src="/amidala/"></script>
<script>
    require('uri-templates', function (UriTemplate) {
        ...
    });
</script>

By default, the AMD loader script figures out where to load modules from by inspecting its own URL. This only works if you're loading it from a <script> tag in the page, otherwise you need to provide the .template option.

What does it do?

In the browser: the initial loading library supplies define() or require() functions, following the AMD spec. When a dependency is needed, a <script> element is added to the page that defines it.

On the server: when an AMD dependency is requested by the browser, the corresponding NPM/CommonJS dependency is located, and modified (with some small wrapper code) so that it works as an AMD module.

Security

Absolute and relative paths to modules are always disallowed.

This means that (by default) the only files this module loader will return will be from dependencies from node_modules/.

However, using the .alias option it is possible to redirect modules to another location. If you write an entry .alias that redirects to a folder, this gives users access to all suitable files in that folder, so make sure nothing sensitive is in there (even in hidden files).

Options

.loader

This is the URL at which the main loader is accessible in the browser.

If the module is loaded in a subdirectory by Express, this URL is relative to that.

// loader URL is "/amidala/loader.js"
app.use('/amidala/', amidala.dynamic({
    loader: '/loader.js'
}));

If this is not specified, then it is taken to be the root:

// loader URL is "/amidala.js"
app.use('/amidala.js', amidala.dynamic());

.template

This defines where modules are located / served from. This is passed to the client-side libary, so it is not relative to any mounted roots.

By default, the loader will guess its own URL (only works if loaded via a <script> element in the HTML source) and use that as a base:

// loader URL is "/amidala.js"
// modules are loaded from /amidala.js/...
app.use(amidala.dynamic({
    loader: '/amidala.js'
}));

If this is a string, it's interpreted as a URI Template, using the variable name:

app.use(amidala.dynamic({
    loader: '/amidala.js',
    template: '/amd-modules/{name}'
}));

If it is an object or an array, it is taken to define a URI map between module names and URIs.

app.use(amidala.dynamic({
    loader: '/amidala.js',
    template: [
        // Preserve full paths, and prevent "." from disappearing
        {'./{+module}': '/amd-local/{+module}'},
        {'{+module}': '/amd-modules/{+module}'}
    ]
}));

.alias

With this option, you can alias modules (or folders) to alternative locations, e.g.:

amd.dynamic({
    alias: {
        "ui-components": __dirname + "/ui"
    }
})

These aliases include submodules - so with the above, a call to require(['ui-components/xyz'], ...) will resolve to ..../ui/xyz instead.

You can provide an array for each alias, and it will attempt to resolve them in order:

amd.dynamic({
    alias: {
        "./": [__dirname + '/static/amd/', __dirname + '/shared']
    }
})

Aliases are checked longest-first. You can use the empty string ("") to catch all modules not otherwise matched:

amd.dynamic({
    alias: {
        "": __dirname + '/public/bower_components'
        "fs": "level-fs-browser"
    }
})

.extensions

This lets you provide a map from (lower-case) extensions to functions that assemble code from their contents. The result must contain a define() call for that module, but the module name can be implicit.

The functions take four arguments: sourceText, moduleName, moduleRelativeName, and callback. Use of callback is optional - if the function returns a string, then it will take that to be the result:

amd.dynamic({
    extensions: {
        "txt": function (sourceText) {
            return 'define([],' + JSON.stringify(sourceText) + ');';
        },
        "async-file": function (sourceText, name, relativeName, callback) {
            someAsyncOperation(function (error, code) {
                callback(error, code);
            });
        }
    }
});

If you need to resolve any relative module names, do that relative to moduleRelativeName instead.

For example, if the main entry point for a module some-module is /lib/main.js instead of /index.js, then moduleRelativeName will point to some-module/lib/main.js. This allows ./other.js to correctly resolve to /lib/other.js.

.transform

This lets you provide a function that transforms the module code before it is sent. This occurs after the conversion to AMD modules.

You can either return a transformed code string, or use the asynchronous callback:

amidala.dynamic({
    transform: function (jsCode) {
        return '/*AMD*/\n' + jsCode;
    }
});

amidala.dynamic({
    transform: function (jsCode, callback) {
        someAsyncApi(jsCode, {...}, callback);
    }
});

Enabling relative modules

Relative modules are not allowed - however, we can rewrite these modules using .alias:

amd.dynamic({
    alias: {
        "./shared": __dirname + "/shared"
    }
});

This can be useful if you don't want to mess with the global namespace (e.g. occupying the global shared module).

However (as the security note above mentions), if the target is a directory then this gives users access to all files in that directory.

FAQs

Package last updated on 17 Apr 2016

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc