Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@jupyterlab/apputils-extension

Package Overview
Dependencies
Maintainers
14
Versions
388
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@jupyterlab/apputils-extension - npm Package Compare versions

Comparing version 0.17.2 to 0.18.0

317

lib/index.js

@@ -6,2 +6,10 @@ "use strict";

|----------------------------------------------------------------------------*/
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });

@@ -45,5 +53,4 @@ const application_1 = require("@jupyterlab/application");

(function (Patterns) {
Patterns.cloneState = /[?&]clone([=&]|$)/;
Patterns.loadState = /^\/workspaces\/([^?\/]+)/;
Patterns.resetOnLoad = /(\?reset|\&reset)($|&)/;
Patterns.workspace = new RegExp(`^${coreutils_1.PageConfig.getOption('workspacesUrl')}([^?\/]+)`);
})(Patterns || (Patterns = {}));

@@ -124,3 +131,3 @@ /**

const commands = app.commands;
const url = app.info.urls.themes;
const url = coreutils_1.URLExt.join(app.info.urls.base, app.info.urls.themes);
const key = themes.id;

@@ -132,2 +139,9 @@ const manager = new apputils_1.ThemeManager({ key, host, settings, splash, url });

let currentTheme;
// Set data attributes on the application shell for the current theme.
manager.themeChanged.connect((sender, args) => {
currentTheme = args.newValue;
app.shell.dataset.themeLight = String(manager.isLight(currentTheme));
app.shell.dataset.themeName = currentTheme;
commands.notifyCommandChanged(CommandIDs.changeTheme);
});
commands.addCommand(CommandIDs.changeTheme, {

@@ -144,5 +158,3 @@ label: args => {

}
currentTheme = theme;
manager.setTheme(theme);
commands.notifyCommandChanged(CommandIDs.changeTheme);
}

@@ -193,16 +205,22 @@ });

requires: [application_1.IRouter],
activate: (app, router) => {
const candidate = Private.getWorkspace(router) || '';
activate: (app, router) => __awaiter(this, void 0, void 0, function* () {
const resolver = new apputils_1.WindowResolver();
return resolver
.resolve(candidate)
.catch(reason => {
console.warn('Window resolution failed:', reason);
return Private.redirect(router);
})
.then(() => {
coreutils_1.PageConfig.setOption('workspace', resolver.name);
return resolver;
});
}
const match = router.current.path.match(Patterns.workspace);
const workspace = (match && decodeURIComponent(match[1])) || '';
const candidate = workspace
? coreutils_1.URLExt.join(coreutils_1.PageConfig.getOption('baseUrl'), coreutils_1.PageConfig.getOption('workspacesUrl'), workspace)
: app.info.defaultWorkspace;
try {
yield resolver.resolve(candidate);
}
catch (error) {
console.warn('Window resolution failed:', error);
// Return a promise that never resolves.
return new Promise(() => {
Private.redirect(router);
});
}
coreutils_1.PageConfig.setOption('workspace', resolver.name);
return resolver;
})
};

@@ -245,3 +263,3 @@ /**

commands.addCommand(CommandIDs.recoverState, {
execute: () => {
execute: ({ global }) => __awaiter(this, void 0, void 0, function* () {
const immediate = true;

@@ -251,6 +269,19 @@ const silent = true;

// will not be triggered as it causes a save state.
return state
.clear(silent)
.then(() => commands.execute(CommandIDs.saveState, { immediate }));
}
yield state.clear(silent);
// If the user explictly chooses to recover state, all of local storage
// should be cleared.
if (global) {
try {
window.localStorage.clear();
console.log('Cleared local storage');
}
catch (error) {
console.warn('Clearing local storage failed.', error);
// To give the user time to see the console warning before redirect,
// do not set the `immediate` flag.
return commands.execute(CommandIDs.saveState);
}
}
return commands.execute(CommandIDs.saveState, { immediate });
})
});

@@ -261,10 +292,6 @@ // Conflate all outstanding requests to the save state command that happen

commands.addCommand(CommandIDs.saveState, {
label: () => `Save Workspace (${Private.getWorkspace(router)})`,
isEnabled: () => !!Private.getWorkspace(router),
execute: args => {
const workspace = Private.getWorkspace(router);
if (!workspace) {
return;
}
const timeout = args.immediate ? 0 : WORKSPACE_SAVE_DEBOUNCE_INTERVAL;
label: () => `Save Workspace (${app.info.workspace})`,
execute: ({ immediate }) => {
const { workspace } = app.info;
const timeout = immediate ? 0 : WORKSPACE_SAVE_DEBOUNCE_INTERVAL;
const id = workspace;

@@ -279,3 +306,3 @@ const metadata = { id };

}
debouncer = window.setTimeout(() => {
debouncer = window.setTimeout(() => __awaiter(this, void 0, void 0, function* () {
// Prevent a race condition between the timeout and saving.

@@ -285,14 +312,12 @@ if (!conflated) {

}
state
.toJSON()
.then(data => workspaces.save(id, { data, metadata }))
.then(() => {
const data = yield state.toJSON();
try {
yield workspaces.save(id, { data, metadata });
conflated.resolve(undefined);
conflated = null;
})
.catch(reason => {
conflated.reject(reason);
conflated = null;
});
}, timeout);
}
catch (error) {
conflated.reject(error);
}
conflated = null;
}), timeout);
return conflated.promise;

@@ -305,3 +330,3 @@ }

commands.addCommand(CommandIDs.loadState, {
execute: (args) => {
execute: (args) => __awaiter(this, void 0, void 0, function* () {
// Since the command can be executed an arbitrary number of times, make

@@ -313,95 +338,68 @@ // sure it is safe to call multiple times.

const { hash, path, search } = args;
const workspace = Private.getWorkspace(router);
const { defaultWorkspace, workspace } = app.info;
const query = coreutils_1.URLExt.queryStringToObject(search || '');
const clone = query['clone'];
const source = typeof clone === 'string' ? clone : workspace;
let promise;
// If the default /lab workspace is being cloned, copy it out of local
// storage instead of making a round trip to the server because it
// does not exist on the server.
if (source === clone && source === '') {
const prefix = `${source}:${info.namespace}:`;
const mask = (key) => key.replace(prefix, '');
const contents = coreutils_1.StateDB.toJSON(prefix, mask);
resolved = true;
transform.resolve({ type: 'overwrite', contents });
promise = Promise.resolve();
const clone = typeof query['clone'] === 'string'
? query['clone'] === ''
? defaultWorkspace
: coreutils_1.URLExt.join(coreutils_1.PageConfig.getOption('baseUrl'), coreutils_1.PageConfig.getOption('workspacesUrl'), query['clone'])
: null;
const source = clone || workspace;
try {
const saved = yield workspaces.fetch(source);
// If this command is called after a reset, the state database
// will already be resolved.
if (!resolved) {
resolved = true;
transform.resolve({ type: 'overwrite', contents: saved.data });
}
}
// If there is no promise, fetch the source and overwrite the database.
promise =
promise ||
workspaces
.fetch(source)
.then(saved => {
// If this command is called after a reset, the state database
// will already be resolved.
if (!resolved) {
resolved = true;
transform.resolve({ type: 'overwrite', contents: saved.data });
}
})
.catch(reason => {
console.warn(`Fetching workspace (${workspace}) failed:`, reason);
// If the workspace does not exist, cancel the data transformation
// and save a workspace with the current user state data.
if (!resolved) {
resolved = true;
transform.resolve({ type: 'cancel', contents: null });
}
})
.then(() => {
// Any time the local state database changes, save the workspace.
if (workspace) {
state.changed.connect(listener, state);
}
});
return promise
.catch(reason => {
console.warn(`${CommandIDs.loadState} failed:`, reason);
})
.then(() => {
const immediate = true;
if (source === clone) {
// Maintain the query string parameters but remove `clone`.
delete query['clone'];
const url = path + coreutils_1.URLExt.objectToQueryString(query) + hash;
const cloned = commands
.execute(CommandIDs.saveState, { immediate })
.then(() => router.stop);
// After the state has been cloned, navigate to the URL.
cloned.then(() => {
router.navigate(url, { silent: true });
});
return cloned;
catch (error) {
console.warn(`Fetching workspace (${workspace}) failed:`, error);
// If the workspace does not exist, cancel the data transformation
// and save a workspace with the current user state data.
if (!resolved) {
resolved = true;
transform.resolve({ type: 'cancel', contents: null });
}
// After the state database has finished loading, save it.
return commands.execute(CommandIDs.saveState, { immediate });
});
}
}
// Any time the local state database changes, save the workspace.
if (workspace) {
state.changed.connect(listener, state);
}
const immediate = true;
if (source === clone) {
// Maintain the query string parameters but remove `clone`.
delete query['clone'];
const url = path + coreutils_1.URLExt.objectToQueryString(query) + hash;
const cloned = commands
.execute(CommandIDs.saveState, { immediate })
.then(() => router.stop);
// After the state has been cloned, navigate to the URL.
cloned.then(() => {
console.log(`HERE: ${url}`);
router.navigate(url, { silent: true });
});
return cloned;
}
// After the state database has finished loading, save it.
return commands.execute(CommandIDs.saveState, { immediate });
})
});
// Both the load state and clone state patterns should trigger the load
// state command if the URL matches one of them, but cloning a workspace
// outranks loading it because it is an explicit user action.
router.register({
command: CommandIDs.loadState,
pattern: Patterns.cloneState,
rank: 20 // Set loading rank at a higher priority than the default 100.
pattern: /.?/,
rank: 20 // Very high priority: 20/100.
});
router.register({
command: CommandIDs.loadState,
pattern: Patterns.loadState,
rank: 30 // Set loading rank at a higher priority than the default 100.
});
commands.addCommand(CommandIDs.reset, {
label: 'Reset Application State',
execute: () => {
commands
.execute(CommandIDs.recoverState)
.then(() => {
router.reload();
})
.catch(() => {
router.reload();
});
}
execute: () => __awaiter(this, void 0, void 0, function* () {
const global = true;
try {
yield commands.execute(CommandIDs.recoverState, { global });
}
catch (error) {
/* Ignore failures and redirect. */
}
router.reload();
})
});

@@ -454,12 +452,9 @@ commands.addCommand(CommandIDs.resetOnLoad, {

});
const fallthrough = () => {
// If the state database is still unresolved after the first URL has been
// routed, leave it intact.
if (!resolved) {
resolved = true;
transform.resolve({ type: 'cancel', contents: null });
}
router.routed.disconnect(fallthrough, state);
};
router.routed.connect(fallthrough, state);
// Clean up state database when the window unloads.
window.addEventListener('beforeunload', () => {
const silent = true;
state.clear(silent).catch(() => {
/* no-op */
});
});
return state;

@@ -487,10 +482,2 @@ }

/**
* Returns the workspace name from the URL, if it exists.
*/
function getWorkspace(router) {
const match = router.current.path.match(Patterns.loadState);
return (match && decodeURIComponent(match[1])) || '';
}
Private.getWorkspace = getWorkspace;
/**
* Create a splash element.

@@ -563,23 +550,23 @@ */

function redirect(router, warn = false) {
const form = redirect_1.createRedirectForm(warn);
const dialog = new apputils_1.Dialog({
title: 'Please use a different workspace.',
body: form,
focusNodeSelector: 'input',
buttons: [apputils_1.Dialog.okButton({ label: 'Switch Workspace' })]
});
return dialog.launch().then(result => {
return __awaiter(this, void 0, void 0, function* () {
const form = redirect_1.createRedirectForm(warn);
const dialog = new apputils_1.Dialog({
title: 'Please use a different workspace.',
body: form,
focusNodeSelector: 'input',
buttons: [apputils_1.Dialog.okButton({ label: 'Switch Workspace' })]
});
const result = yield dialog.launch();
dialog.dispose();
if (result.value) {
const url = `workspaces/${result.value}`;
// Navigate to a new workspace URL and abandon this session altogether.
router.navigate(url, { hard: true, silent: true });
// This promise will never resolve because the application navigates
// away to a new location. It only exists to satisfy the return type
// of the `redirect` function.
return new Promise(() => {
/* no-op */
});
if (!result.value) {
return redirect(router, true);
}
return redirect(router, true);
// Navigate to a new workspace URL and abandon this session altogether.
const workspaces = coreutils_1.PageConfig.getOption('workspacesUrl');
const url = coreutils_1.URLExt.join(workspaces, result.value);
router.navigate(url, { hard: true, silent: true });
// This promise will never resolve because the application navigates
// away to a new location. It only exists to satisfy the return type
// of the `redirect` function.
return new Promise(() => undefined);
});

@@ -586,0 +573,0 @@ }

@@ -26,2 +26,5 @@ "use strict";

this._palette = palette;
this._palette.title.iconClass = 'jp-PaletteIcon jp-SideBar-tabIcon';
this._palette.title.label = '';
this._palette.title.caption = 'Command Palette';
}

@@ -70,3 +73,3 @@ /**

palette.inputNode.placeholder = 'SEARCH';
shell.addToLeftArea(palette);
shell.addToLeftArea(palette, { rank: 300 });
return new Palette(palette);

@@ -73,0 +76,0 @@ }

{
"name": "@jupyterlab/apputils-extension",
"version": "0.17.2",
"version": "0.18.0",
"description": "JupyterLab - Application Utilities Extension",

@@ -35,7 +35,7 @@ "homepage": "https://github.com/jupyterlab/jupyterlab",

"dependencies": {
"@jupyterlab/application": "^0.17.2",
"@jupyterlab/apputils": "^0.17.2",
"@jupyterlab/coreutils": "^2.0.2",
"@jupyterlab/mainmenu": "^0.6.2",
"@jupyterlab/services": "^3.0.3",
"@jupyterlab/application": "^0.18.0",
"@jupyterlab/apputils": "^0.18.0",
"@jupyterlab/coreutils": "^2.1.0",
"@jupyterlab/mainmenu": "^0.7.0",
"@jupyterlab/services": "^3.1.0",
"@phosphor/commands": "^1.5.0",

@@ -42,0 +42,0 @@ "@phosphor/coreutils": "^1.3.0",

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

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