Security News
Research
Data Theft Repackaged: A Case Study in Malicious Wrapper Packages on npm
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
jupyterlab-extension-builder
Advanced tools
Tools for building JupyterLab extensions
A JupyterLab extension provides additional, optional functionality to JupyterLab's built-in capabilities. An extension is a module that provides one or more plugins to the JupyterLab application. To streamline third-party development of extensions, this library provides a build script for generating third party extension JavaScript bundles.
Simple extensions can be created by using the buildExtension
function
with the default options. More advanced extensions may require additional
configuration such as custom loaders or WebPack plugins.
A video tutorial walkthrough for building JupyterLab extensions can be found on YouTube.
Prerequisites
npm install --save jupyterlab-extension-builder
Prerequisites
git clone https://github.com/jupyter/jupyterlab-extension-builder.git
cd jupyterlab-extension-builder
npm install
npm run build
npm run clean
npm run build
Three major usage steps include:
jupyter labextension
The full API docs can be found here.
A simple extension entry point that exposes a single application plugin could look like:
module.exports = [{
id: 'my-cool-extension',
activate: function(app) {
console.log(app.commands);
}
}];
The extension entry point must be a CommonJS module where the default
export is an array of plugin objects. If writing in ES6 format use the
export default [ ... ];
syntax.
Build the above example using the following script:
var buildExtension = require('jupyterlab-extension-builder').buildExtension;
buildExtension({
name: 'my-cool-extension',
entry: './index.js',
outputDir: './build'
});
The name
is a string that will be used for the output filename. The entry
is the module that exports a plugin definition or array of plugin definitions. The outputDir
is the directory in which the generated plugin bundle, manifest, and related files will be stored.
Several optional arguments are also available; see the options at the bottom of the builder.ts file.
In this case the builder script will create the following files in the build directory:
my-cool-extension.bundle.js
my-cool-extension.js.manifest
Other extensions may produce additional files in the build directory
depending on the complexity of extension. The two files above,
my-cool-extension.js
and my-cool-extension.js.manifest
,
are used by the JupyterLab server to determine the entry point file(s) and
entry point module(s) for the extension. The extension must also be registered, using the command jupyter labextension
, in order to be added to
the JupyterLab application. See the documentation for labextension
The extension bundles are created using WebPack, and the modules produced by WebPack are modified to use JupyterLab's custom module registration and loading mechanism.
JupyterLab's custom module registration and loading mechanism uses a define
function that registers modules by name, where the name contains the package
name, version number, and the full path to the module. For example,
'phosphor@0.6.1/lib/ui/widget.js'
. Within a define
function, a required
module is referenced by package name, semver range, and the full path to the
module. For example, require('phosphor@^0.6.0/lib/ui/tabpanel.js')
.
By using a semver range, JupyterLab can perform client-side deduplication of
modules, where the registered module that maximally satisfies a semver range
is the one returned by the require
function call. This also enables us to
perform server-side deduplication of modules prior to serving the bundles,
and the client-side lookup will still load the correct modules.
Reasons to deduplicate code include:
instanceof()
on an object to determine if it is the same class (a technique used by phosphor's drag-drop mechanism)jupyter-js-services
.All client-side require()
calls are synchronous, which means that the
bundles containing the define()
modules must be loaded prior to using
any of the bundles' functions. The loader provides an ensureBundle()
function to load a particular bundle or bundles prior to calling require()
on
a module.
A completely custom WebPack configuration may be needed if there is a case
where the buildExtension
function is not sufficient to build the extension.
If a custom WebPack configuration is needed, the JupyterLabPlugin
must be
used as part of the WebPack config to ensure proper handling of module
definition and requires.
FAQs
Tools for building JupyterLab extensions
We found that jupyterlab-extension-builder demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 3 open source maintainers collaborating on the project.
Did you know?
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.
Security News
Research
The Socket Research Team breaks down a malicious wrapper package that uses obfuscation to harvest credentials and exfiltrate sensitive data.
Research
Security News
Attackers used a malicious npm package typosquatting a popular ESLint plugin to steal sensitive data, execute commands, and exploit developer systems.
Security News
The Ultralytics' PyPI Package was compromised four times in one weekend through GitHub Actions cache poisoning and failure to rotate previously compromised API tokens.