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

@jupyterlab/coreutils

Package Overview
Dependencies
Maintainers
16
Versions
367
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@jupyterlab/coreutils - npm Package Compare versions

Comparing version 3.0.0-alpha.6 to 3.0.0-alpha.7

lib/ratelimiter.d.ts

2

lib/activitymonitor.js

@@ -62,3 +62,3 @@ "use strict";

this._args = args;
this._timer = window.setTimeout(() => {
this._timer = setTimeout(() => {
this._activityStopped.emit({

@@ -65,0 +65,0 @@ sender: this._sender,

"use strict";
// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
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 });

@@ -43,6 +35,4 @@ /**

*/
list(query) {
return __awaiter(this, void 0, void 0, function* () {
throw new Error('DataConnector#list method has not been implemented.');
});
async list(query) {
throw new Error('DataConnector#list method has not been implemented.');
}

@@ -59,6 +49,4 @@ /**

*/
remove(id) {
return __awaiter(this, void 0, void 0, function* () {
throw new Error('DataConnector#remove method has not been implemented.');
});
async remove(id) {
throw new Error('DataConnector#remove method has not been implemented.');
}

@@ -77,8 +65,6 @@ /**

*/
save(id, value) {
return __awaiter(this, void 0, void 0, function* () {
throw new Error('DataConnector#save method has not been implemented.');
});
async save(id, value) {
throw new Error('DataConnector#save method has not been implemented.');
}
}
exports.DataConnector = DataConnector;

@@ -9,2 +9,3 @@ export * from './activitymonitor';

export * from './poll';
export * from './ratelimiter';
export * from './settingregistry';

@@ -14,2 +15,3 @@ export * from './statedb';

export * from './time';
export * from './tokens';
export * from './url';

@@ -15,2 +15,3 @@ "use strict";

__export(require("./poll"));
__export(require("./ratelimiter"));
__export(require("./settingregistry"));

@@ -20,2 +21,3 @@ __export(require("./statedb"));

__export(require("./time"));
__export(require("./tokens"));
__export(require("./url"));

@@ -0,1 +1,2 @@

import { IDisposable } from '@phosphor/disposable';
/**

@@ -92,1 +93,23 @@ * A generic interface for change emitter payloads.

}
/**
* A function whose invocations are rate limited and can be stopped after
* invocation before it has fired.
*
* @typeparam T - The resolved type of the underlying function. Defaults to any.
*
* @typeparam U - The rejected type of the underlying function. Defaults to any.
*/
export interface IRateLimiter<T = any, U = any> extends IDisposable {
/**
* The rate limit in milliseconds.
*/
readonly limit: number;
/**
* Invoke the rate limited function.
*/
invoke(): Promise<T>;
/**
* Stop the function if it is mid-flight.
*/
stop(): Promise<void>;
}

@@ -57,2 +57,11 @@ /**

/**
* Returns the URL converting this notebook to a certain
* format with nbconvert.
*/
function getNBConvertURL({ path, format, download }: {
path: string;
format: string;
download: boolean;
}): string;
/**
* Get the authorization token for a Jupyter application.

@@ -59,0 +68,0 @@ */

@@ -139,2 +139,15 @@ "use strict";

/**
* Returns the URL converting this notebook to a certain
* format with nbconvert.
*/
function getNBConvertURL({ path, format, download }) {
const notebookPath = url_1.URLExt.encodeParts(path);
const url = url_1.URLExt.join(getBaseUrl(), 'nbconvert', format, notebookPath);
if (download) {
return url + '?download=true';
}
return url;
}
PageConfig.getNBConvertURL = getNBConvertURL;
/**
* Get the authorization token for a Jupyter application.

@@ -141,0 +154,0 @@ */

@@ -7,8 +7,8 @@ import { IDisposable } from '@phosphor/disposable';

* @typeparam T - The resolved type of the factory's promises.
* Defaults to `any`.
*
* @typeparam U - The rejected type of the factory's promises.
* Defaults to `any`.
*
* @typeparam V - The type to extend the phases supported by a poll.
*/
export interface IPoll<T = any, U = any> {
export interface IPoll<T, U, V extends string> {
/**

@@ -33,3 +33,3 @@ * A signal emitted when the poll is disposed.

*/
readonly state: IPoll.State<T, U>;
readonly state: IPoll.State<T, U, V>;
/**

@@ -43,7 +43,7 @@ * A promise that resolves when the currently-scheduled tick completes.

*/
readonly tick: Promise<IPoll<T, U>>;
readonly tick: Promise<IPoll<T, U, V>>;
/**
* A signal emitted when the poll state changes, i.e., a new tick is scheduled.
*/
readonly ticked: ISignal<IPoll<T, U>, IPoll.State<T, U>>;
readonly ticked: ISignal<IPoll<T, U, V>, IPoll.State<T, U, V>>;
}

@@ -88,4 +88,6 @@ /**

* The phase of the poll when the current tick was scheduled.
*
* @typeparam T - A type for any additional tick phases a poll supports.
*/
type Phase = 'constructed' | 'disposed' | 'reconnected' | 'refreshed' | 'rejected' | 'resolved' | 'standby' | 'started' | 'stopped' | 'when-rejected' | 'when-resolved';
type Phase<T extends string> = T | 'constructed' | 'disposed' | 'reconnected' | 'refreshed' | 'rejected' | 'resolved' | 'standby' | 'started' | 'stopped';
/**

@@ -95,8 +97,8 @@ * Definition of poll state at any given time.

* @typeparam T - The resolved type of the factory's promises.
* Defaults to `any`.
*
* @typeparam U - The rejected type of the factory's promises.
* Defaults to `any`.
*
* @typeparam V - The type to extend the phases supported by a poll.
*/
type State<T = any, U = any> = {
type State<T, U, V extends string> = {
/**

@@ -117,3 +119,3 @@ * The number of milliseconds until the current tick resolves.

*/
readonly phase: Phase;
readonly phase: Phase<V>;
/**

@@ -134,4 +136,7 @@ * The timestamp for when this tick was scheduled.

* Defaults to `any`.
*
* @typeparam V - An optional type to extend the phases supported by a poll.
* Defaults to `standby`, which already exists in the `Phase` type.
*/
export declare class Poll<T = any, U = any> implements IDisposable, IPoll<T, U> {
export declare class Poll<T = any, U = any, V extends string = 'standby'> implements IDisposable, IPoll<T, U, V> {
/**

@@ -142,3 +147,3 @@ * Instantiate a new poll with exponential backoff in case of failure.

*/
constructor(options: Poll.IOptions<T, U>);
constructor(options: Poll.IOptions<T, U, V>);
/**

@@ -167,3 +172,3 @@ * The name of the poll.

*/
readonly state: IPoll.State<T, U>;
readonly state: IPoll.State<T, U, V>;
/**

@@ -176,3 +181,3 @@ * A promise that resolves when the poll next ticks.

*/
readonly ticked: ISignal<this, IPoll.State<T, U>>;
readonly ticked: ISignal<this, IPoll.State<T, U, V>>;
/**

@@ -186,5 +191,26 @@ * Dispose the poll.

* @returns A promise that resolves after tick is scheduled and never rejects.
*
* #### Notes
* The returned promise resolves after the tick is scheduled, but before
* the polling action is run. To wait until after the poll action executes,
* await the `poll.tick` promise: `await poll.refresh(); await poll.tick;`
*/
refresh(): Promise<void>;
/**
* Schedule the next poll tick.
*
* @param next - The next poll state data to schedule. Defaults to standby.
*
* @param next.cancel - Cancels state transition if function returns `true`.
*
* @returns A promise that resolves when the next poll state is active.
*
* #### Notes
* This method is not meant to be invoked by user code typically. It is public
* to allow poll instances to be composed into classes that schedule ticks.
*/
schedule(next?: Partial<IPoll.State<T, U, V> & {
cancel: (last: IPoll.State<T, U, V>) => boolean;
}>): Promise<void>;
/**
* Starts the poll. Schedules `started` tick if necessary.

@@ -202,18 +228,2 @@ *

/**
* Schedule the next poll tick.
*
* @param next - The next poll state data to schedule. Defaults to standby.
*
* @param next.cancel - Cancels state transition if function returns `true`.
*
* @returns A promise that resolves when the next poll state is active.
*
* #### Notes
* This method is protected to allow sub-classes to implement methods that can
* schedule poll ticks.
*/
protected schedule(next?: Partial<IPoll.State & {
cancel: (last: IPoll.State) => boolean;
}>): Promise<void>;
/**
* Execute a new poll factory promise or stand by if necessary.

@@ -241,4 +251,6 @@ */

* @typeparam U - The rejected type of the factory's promises.
*
* @typeparam V - The type to extend the phases supported by a poll.
*/
type Factory<T, U> = (state: IPoll.State<T, U>) => Promise<T>;
type Factory<T, U, V extends string> = (state: IPoll.State<T, U, V>) => Promise<T>;
/**

@@ -252,12 +264,16 @@ * Indicates when the poll switches to standby.

* @typeparam T - The resolved type of the factory's promises.
* Defaults to `any`.
*
* @typeparam U - The rejected type of the factory's promises.
* Defaults to `any`.
*
* @typeparam V - The type to extend the phases supported by a poll.
*/
interface IOptions<T = any, U = any> {
interface IOptions<T, U, V extends string> {
/**
* Whether to begin polling automatically; defaults to `true`.
*/
auto?: boolean;
/**
* A factory function that is passed a poll tick and returns a poll promise.
*/
factory: Factory<T, U>;
factory: Factory<T, U, V>;
/**

@@ -283,8 +299,8 @@ * The polling frequency parameters.

standby?: Standby | (() => boolean | Standby);
/**
* If set, a promise which must resolve (or reject) before polling begins.
*/
when?: Promise<any>;
}
/**
* An interval value that indicates the poll should tick immediately.
*/
const IMMEDIATE = 0;
/**
* Delays are 32-bit integers in many browsers so intervals need to be capped.

@@ -296,2 +312,6 @@ *

const MAX_INTERVAL = 2147483647;
/**
* An interval value that indicates the poll should never tick.
*/
const NEVER: number;
}
"use strict";
// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
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 });

@@ -16,2 +8,14 @@ const coreutils_1 = require("@phosphor/coreutils");

/**
* A function to defer an action immediately.
*/
const defer = typeof requestAnimationFrame === 'function'
? requestAnimationFrame
: setImmediate;
/**
* A function to cancel a deferred action.
*/
const cancel = typeof cancelAnimationFrame === 'function'
? cancelAnimationFrame
: clearImmediate;
/**
* A class that wraps an asynchronous function to poll at a regular interval

@@ -25,2 +29,5 @@ * with exponential increases to the interval length if the poll fails.

* Defaults to `any`.
*
* @typeparam V - An optional type to extend the phases supported by a poll.
* Defaults to `standby`, which already exists in the `Phase` type.
*/

@@ -43,23 +50,5 @@ class Poll {

this.name = options.name || Private.DEFAULT_NAME;
// Schedule poll ticks after `when` promise is settled.
(options.when || Promise.resolve())
.then(_ => {
if (this.isDisposed) {
return;
}
return this.schedule({
interval: Private.IMMEDIATE,
phase: 'when-resolved'
});
})
.catch(reason => {
if (this.isDisposed) {
return;
}
console.warn(`Poll (${this.name}) started despite rejection.`, reason);
return this.schedule({
interval: Private.IMMEDIATE,
phase: 'when-rejected'
});
});
if ('auto' in options ? options.auto : true) {
defer(() => void this.start());
}
}

@@ -88,6 +77,6 @@ /**

}
if (interval < 0 || interval > max) {
if ((interval < 0 || interval > max) && interval !== Poll.NEVER) {
throw new Error('Poll interval must be between 0 and max');
}
if (max > Poll.MAX_INTERVAL) {
if (max > Poll.MAX_INTERVAL && max !== Poll.NEVER) {
throw new Error(`Max interval must be less than ${Poll.MAX_INTERVAL}`);

@@ -150,7 +139,12 @@ }

* @returns A promise that resolves after tick is scheduled and never rejects.
*
* #### Notes
* The returned promise resolves after the tick is scheduled, but before
* the polling action is run. To wait until after the poll action executes,
* await the `poll.tick` promise: `await poll.refresh(); await poll.tick;`
*/
refresh() {
return this.schedule({
cancel: last => last.phase === 'refreshed',
interval: Private.IMMEDIATE,
cancel: ({ phase }) => phase === 'refreshed',
interval: Poll.IMMEDIATE,
phase: 'refreshed'

@@ -160,2 +154,55 @@ });

/**
* Schedule the next poll tick.
*
* @param next - The next poll state data to schedule. Defaults to standby.
*
* @param next.cancel - Cancels state transition if function returns `true`.
*
* @returns A promise that resolves when the next poll state is active.
*
* #### Notes
* This method is not meant to be invoked by user code typically. It is public
* to allow poll instances to be composed into classes that schedule ticks.
*/
async schedule(next = {}) {
if (this.isDisposed) {
return;
}
// Check if the phase transition should be canceled.
if (next.cancel && next.cancel(this.state)) {
return;
}
// Update poll state.
const last = this.state;
const pending = this._tick;
const scheduled = new coreutils_1.PromiseDelegate();
const state = Object.assign({ interval: this.frequency.interval, payload: null, phase: 'standby', timestamp: new Date().getTime() }, next);
this._state = state;
this._tick = scheduled;
// Clear the schedule if possible.
if (last.interval === Poll.IMMEDIATE) {
cancel(this._timeout);
}
else {
clearTimeout(this._timeout);
}
// Emit ticked signal, resolve pending promise, and await its settlement.
this._ticked.emit(this.state);
pending.resolve(this);
await pending.promise;
// Schedule next execution and cache its timeout handle.
const execute = () => {
if (this.isDisposed || this.tick !== scheduled.promise) {
return;
}
this._execute();
};
this._timeout =
state.interval === Poll.IMMEDIATE
? defer(execute)
: state.interval === Poll.NEVER
? -1
: setTimeout(execute, state.interval);
}
/**
* Starts the poll. Schedules `started` tick if necessary.

@@ -167,4 +214,4 @@ *

return this.schedule({
cancel: last => last.phase !== 'standby' && last.phase !== 'stopped',
interval: Private.IMMEDIATE,
cancel: ({ phase }) => phase !== 'constructed' && phase !== 'standby' && phase !== 'stopped',
interval: Poll.IMMEDIATE,
phase: 'started'

@@ -180,4 +227,4 @@ });

return this.schedule({
cancel: last => last.phase === 'stopped',
interval: Private.NEVER,
cancel: ({ phase }) => phase === 'stopped',
interval: Poll.NEVER,
phase: 'stopped'

@@ -187,63 +234,2 @@ });

/**
* Schedule the next poll tick.
*
* @param next - The next poll state data to schedule. Defaults to standby.
*
* @param next.cancel - Cancels state transition if function returns `true`.
*
* @returns A promise that resolves when the next poll state is active.
*
* #### Notes
* This method is protected to allow sub-classes to implement methods that can
* schedule poll ticks.
*/
schedule(next = {}) {
return __awaiter(this, void 0, void 0, function* () {
if (this.isDisposed) {
return;
}
// The `when` promise in the constructor options acts as a gate.
if (this.state.phase === 'constructed') {
if (next.phase !== 'when-rejected' && next.phase !== 'when-resolved') {
yield this.tick;
}
}
// Check if the phase transition should be canceled.
if (next.cancel && next.cancel(this.state)) {
return;
}
// Update poll state.
const last = this.state;
const pending = this._tick;
const scheduled = new coreutils_1.PromiseDelegate();
const state = Object.assign({ interval: this.frequency.interval, payload: null, phase: 'standby', timestamp: new Date().getTime() }, next);
this._state = state;
this._tick = scheduled;
// Clear the schedule if possible.
if (last.interval === Private.IMMEDIATE) {
cancelAnimationFrame(this._timeout);
}
else {
clearTimeout(this._timeout);
}
// Emit ticked signal, resolve pending promise, and await its settlement.
this._ticked.emit(this.state);
pending.resolve(this);
yield pending.promise;
// Schedule next execution and cache its timeout handle.
const execute = () => {
if (this.isDisposed || this.tick !== scheduled.promise) {
return;
}
this._execute();
};
this._timeout =
state.interval === Private.IMMEDIATE
? requestAnimationFrame(execute)
: state.interval === Private.NEVER
? -1
: setTimeout(execute, state.interval);
});
}
/**
* Execute a new poll factory promise or stand by if necessary.

@@ -293,2 +279,6 @@ */

/**
* An interval value that indicates the poll should tick immediately.
*/
Poll.IMMEDIATE = 0;
/**
* Delays are 32-bit integers in many browsers so intervals need to be capped.

@@ -300,2 +290,6 @@ *

Poll.MAX_INTERVAL = 2147483647;
/**
* An interval value that indicates the poll should never tick.
*/
Poll.NEVER = Infinity;
})(Poll = exports.Poll || (exports.Poll = {}));

@@ -308,10 +302,2 @@ /**

/**
* An interval value that indicates the poll should tick immediately.
*/
Private.IMMEDIATE = 0;
/**
* An interval value that indicates the poll should never tick.
*/
Private.NEVER = Infinity;
/**
* The default backoff growth rate if `backoff` is `true`.

@@ -340,3 +326,3 @@ */

Private.DEFAULT_STATE = {
interval: Private.NEVER,
interval: Poll.NEVER,
payload: null,

@@ -350,3 +336,3 @@ phase: 'constructed',

Private.DISPOSED_STATE = {
interval: Private.NEVER,
interval: Poll.NEVER,
payload: null,

@@ -380,2 +366,5 @@ phase: 'disposed',

const { backoff, interval, max } = frequency;
if (interval === Poll.NEVER) {
return interval;
}
const growth = backoff === true ? Private.DEFAULT_BACKOFF : backoff === false ? 1 : backoff;

@@ -382,0 +371,0 @@ const random = getRandomIntInclusive(interval, last.interval * growth);

@@ -1,5 +0,6 @@

import { JSONObject, JSONValue, ReadonlyJSONObject, ReadonlyJSONValue, Token } from '@phosphor/coreutils';
import { JSONObject, JSONValue, ReadonlyJSONObject, ReadonlyJSONValue } from '@phosphor/coreutils';
import { IDisposable } from '@phosphor/disposable';
import { ISignal } from '@phosphor/signaling';
import { IDataConnector } from './interfaces';
import { ISettingRegistry } from './tokens';
/**

@@ -54,264 +55,2 @@ * An implementation of a schema validator.

/**
* The setting registry token.
*/
export declare const ISettingRegistry: Token<ISettingRegistry>;
/**
* A namespace for setting registry interfaces.
*/
export declare namespace ISettingRegistry {
/**
* The primitive types available in a JSON schema.
*/
type Primitive = 'array' | 'boolean' | 'null' | 'number' | 'object' | 'string';
/**
* The settings for a specific plugin.
*/
interface IPlugin extends JSONObject {
/**
* The name of the plugin.
*/
id: string;
/**
* The collection of values for a specified plugin.
*/
data: ISettingBundle;
/**
* The raw user settings data as a string containing JSON with comments.
*/
raw: string;
/**
* The JSON schema for the plugin.
*/
schema: ISchema;
/**
* The published version of the NPM package containing the plugin.
*/
version: string;
}
/**
* A namespace for plugin functionality.
*/
namespace IPlugin {
/**
* A function that transforms a plugin object before it is consumed by the
* setting registry.
*/
type Transform = (plugin: IPlugin) => IPlugin;
/**
* The phases during which a transformation may be applied to a plugin.
*/
type Phase = 'compose' | 'fetch';
}
/**
* A minimal subset of the formal JSON Schema that describes a property.
*/
interface IProperty extends JSONObject {
/**
* The default value, if any.
*/
default?: any;
/**
* The schema description.
*/
description?: string;
/**
* The schema's child properties.
*/
properties?: {
[property: string]: IProperty;
};
/**
* The title of a property.
*/
title?: string;
/**
* The type or types of the data.
*/
type?: Primitive | Primitive[];
}
/**
* A schema type that is a minimal subset of the formal JSON Schema along with
* optional JupyterLab rendering hints.
*/
interface ISchema extends IProperty {
/**
* Whether the schema is deprecated.
*
* #### Notes
* This flag can be used by functionality that loads this plugin's settings
* from the registry. For example, the setting editor does not display a
* plugin's settings if it is set to `true`.
*/
'jupyter.lab.setting-deprecated'?: boolean;
/**
* The JupyterLab icon class hint.
*/
'jupyter.lab.setting-icon-class'?: string;
/**
* The JupyterLab icon label hint.
*/
'jupyter.lab.setting-icon-label'?: string;
/**
* A flag that indicates plugin should be transformed before being used by
* the setting registry.
*
* #### Notes
* If this value is set to `true`, the setting registry will wait until a
* transformation has been registered (by calling the `transform()` method
* of the registry) for the plugin ID before resolving `load()` promises.
* This means that if the attribute is set to `true` but no transformation
* is registered in time, calls to `load()` a plugin will eventually time
* out and reject.
*/
'jupyter.lab.transform'?: boolean;
/**
* The JupyterLab shortcuts that are creaed by a plugin's schema.
*/
'jupyter.lab.shortcuts'?: IShortcut[];
/**
* The root schema is always an object.
*/
type: 'object';
}
/**
* The setting values for a plugin.
*/
interface ISettingBundle extends JSONObject {
/**
* A composite of the user setting values and the plugin schema defaults.
*
* #### Notes
* The `composite` values will always be a superset of the `user` values.
*/
composite: JSONObject;
/**
* The user setting values.
*/
user: JSONObject;
}
/**
* An interface for manipulating the settings of a specific plugin.
*/
interface ISettings extends IDisposable {
/**
* A signal that emits when the plugin's settings have changed.
*/
readonly changed: ISignal<this, void>;
/**
* The composite of user settings and extension defaults.
*/
readonly composite: ReadonlyJSONObject;
/**
* The plugin's ID.
*/
readonly id: string;
readonly plugin: ISettingRegistry.IPlugin;
/**
* The plugin settings raw text value.
*/
readonly raw: string;
/**
* The plugin's schema.
*/
readonly schema: ISettingRegistry.ISchema;
/**
* The user settings.
*/
readonly user: ReadonlyJSONObject;
/**
* The published version of the NPM package containing these settings.
*/
readonly version: string;
/**
* Return the defaults in a commented JSON format.
*/
annotatedDefaults(): string;
/**
* Calculate the default value of a setting by iterating through the schema.
*
* @param key - The name of the setting whose default value is calculated.
*
* @returns A calculated default JSON value for a specific setting.
*/
default(key: string): JSONValue | undefined;
/**
* Get an individual setting.
*
* @param key - The name of the setting being retrieved.
*
* @returns The setting value.
*/
get(key: string): {
composite: ReadonlyJSONValue;
user: ReadonlyJSONValue;
};
/**
* Remove a single setting.
*
* @param key - The name of the setting being removed.
*
* @returns A promise that resolves when the setting is removed.
*
* #### Notes
* This function is asynchronous because it writes to the setting registry.
*/
remove(key: string): Promise<void>;
/**
* Save all of the plugin's user settings at once.
*/
save(raw: string): Promise<void>;
/**
* Set a single setting.
*
* @param key - The name of the setting being set.
*
* @param value - The value of the setting.
*
* @returns A promise that resolves when the setting has been saved.
*
* #### Notes
* This function is asynchronous because it writes to the setting registry.
*/
set(key: string, value: JSONValue): Promise<void>;
/**
* Validates raw settings with comments.
*
* @param raw - The JSON with comments string being validated.
*
* @returns A list of errors or `null` if valid.
*/
validate(raw: string): ISchemaValidator.IError[] | null;
}
/**
* An interface describing a JupyterLab keyboard shortcut.
*/
interface IShortcut extends JSONObject {
/**
* The optional arguments passed into the shortcut's command.
*/
args?: JSONObject;
/**
* The command invoked by the shortcut.
*/
command: string;
/**
* Whether a keyboard shortcut is disabled. `False` by default.
*/
disabled?: boolean;
/**
* The key combination of the shortcut.
*/
keys: string[];
/**
* The CSS selector applicable to the shortcut.
*/
selector: string;
}
}
/**
* An implementation of a setting registry.
*/
export interface ISettingRegistry extends SettingRegistry {
}
/**
* The default implementation of a schema validator.

@@ -357,3 +96,3 @@ */

*/
export declare class SettingRegistry {
export declare class SettingRegistry implements ISettingRegistry {
/**

@@ -510,3 +249,3 @@ * Create a new setting registry.

*/
readonly registry: SettingRegistry;
readonly registry: ISettingRegistry;
/**

@@ -671,3 +410,3 @@ * A signal that emits when the plugin's settings have changed.

*/
registry: SettingRegistry;
registry: ISettingRegistry;
}

@@ -674,0 +413,0 @@ }

"use strict";
// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
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());
});
};
var __importDefault = (this && this.__importDefault) || function (mod) {

@@ -24,3 +16,3 @@ return (mod && mod.__esModule) ? mod : { "default": mod };

const ajv_1 = __importDefault(require("ajv"));
const json = __importStar(require("comment-json"));
const json = __importStar(require("json5"));
const coreutils_1 = require("@phosphor/coreutils");

@@ -44,8 +36,3 @@ const disposable_1 = require("@phosphor/disposable");

const RECORD_SEPARATOR = String.fromCharCode(30);
/* tslint:disable */
/**
* The setting registry token.
*/
exports.ISettingRegistry = new coreutils_1.Token('@jupyterlab/coreutils:ISettingRegistry');
/**
* The default implementation of a schema validator.

@@ -92,4 +79,3 @@ */

try {
const strip = true;
user = json.parse(plugin.raw, null, strip);
user = json.parse(plugin.raw, null);
}

@@ -208,16 +194,14 @@ catch (error) {

*/
get(plugin, key) {
return __awaiter(this, void 0, void 0, function* () {
// Wait for data preload before allowing normal operation.
yield this._ready;
const plugins = this.plugins;
if (plugin in plugins) {
const { composite, user } = plugins[plugin].data;
return {
composite: key in composite ? copy(composite[key]) : undefined,
user: key in user ? copy(user[key]) : undefined
};
}
return this.load(plugin).then(() => this.get(plugin, key));
});
async get(plugin, key) {
// Wait for data preload before allowing normal operation.
await this._ready;
const plugins = this.plugins;
if (plugin in plugins) {
const { composite, user } = plugins[plugin].data;
return {
composite: key in composite ? copy(composite[key]) : undefined,
user: key in user ? copy(user[key]) : undefined
};
}
return this.load(plugin).then(() => this.get(plugin, key));
}

@@ -232,15 +216,13 @@ /**

*/
load(plugin) {
return __awaiter(this, void 0, void 0, function* () {
// Wait for data preload before allowing normal operation.
yield this._ready;
const plugins = this.plugins;
const registry = this;
// If the plugin exists, resolve.
if (plugin in plugins) {
return new Settings({ plugin: plugins[plugin], registry });
}
// If the plugin needs to be loaded from the data connector, fetch.
return this.reload(plugin);
});
async load(plugin) {
// Wait for data preload before allowing normal operation.
await this._ready;
const plugins = this.plugins;
const registry = this;
// If the plugin exists, resolve.
if (plugin in plugins) {
return new Settings({ plugin: plugins[plugin], registry });
}
// If the plugin needs to be loaded from the data connector, fetch.
return this.reload(plugin);
}

@@ -255,13 +237,11 @@ /**

*/
reload(plugin) {
return __awaiter(this, void 0, void 0, function* () {
// Wait for data preload before allowing normal operation.
yield this._ready;
const fetched = yield this.connector.fetch(plugin);
const plugins = this.plugins;
const registry = this;
yield this._load(yield this._transform('fetch', fetched));
this._pluginChanged.emit(plugin);
return new Settings({ plugin: plugins[plugin], registry });
});
async reload(plugin) {
// Wait for data preload before allowing normal operation.
await this._ready;
const fetched = await this.connector.fetch(plugin);
const plugins = this.plugins;
const registry = this;
await this._load(await this._transform('fetch', fetched));
this._pluginChanged.emit(plugin);
return new Settings({ plugin: plugins[plugin], registry });
}

@@ -277,17 +257,15 @@ /**

*/
remove(plugin, key) {
return __awaiter(this, void 0, void 0, function* () {
// Wait for data preload before allowing normal operation.
yield this._ready;
const plugins = this.plugins;
if (!(plugin in plugins)) {
return;
}
const raw = json.parse(plugins[plugin].raw, null, true);
// Delete both the value and any associated comment.
delete raw[key];
delete raw[`// ${key}`];
plugins[plugin].raw = Private.annotatedPlugin(plugins[plugin], raw);
return this._save(plugin);
});
async remove(plugin, key) {
// Wait for data preload before allowing normal operation.
await this._ready;
const plugins = this.plugins;
if (!(plugin in plugins)) {
return;
}
const raw = json.parse(plugins[plugin].raw, null);
// Delete both the value and any associated comment.
delete raw[key];
delete raw[`// ${key}`];
plugins[plugin].raw = Private.annotatedPlugin(plugins[plugin], raw);
return this._save(plugin);
}

@@ -306,15 +284,13 @@ /**

*/
set(plugin, key, value) {
return __awaiter(this, void 0, void 0, function* () {
// Wait for data preload before allowing normal operation.
yield this._ready;
const plugins = this.plugins;
if (!(plugin in plugins)) {
return this.load(plugin).then(() => this.set(plugin, key, value));
}
// Parse the raw JSON string removing all comments and return an object.
const raw = json.parse(plugins[plugin].raw, null, true);
plugins[plugin].raw = Private.annotatedPlugin(plugins[plugin], Object.assign({}, raw, { [key]: value }));
return this._save(plugin);
});
async set(plugin, key, value) {
// Wait for data preload before allowing normal operation.
await this._ready;
const plugins = this.plugins;
if (!(plugin in plugins)) {
return this.load(plugin).then(() => this.set(plugin, key, value));
}
// Parse the raw JSON string removing all comments and return an object.
const raw = json.parse(plugins[plugin].raw, null);
plugins[plugin].raw = Private.annotatedPlugin(plugins[plugin], Object.assign({}, raw, { [key]: value }));
return this._save(plugin);
}

@@ -361,14 +337,12 @@ /**

*/
upload(plugin, raw) {
return __awaiter(this, void 0, void 0, function* () {
// Wait for data preload before allowing normal operation.
yield this._ready;
const plugins = this.plugins;
if (!(plugin in plugins)) {
return this.load(plugin).then(() => this.upload(plugin, raw));
}
// Set the local copy.
plugins[plugin].raw = raw;
return this._save(plugin);
});
async upload(plugin, raw) {
// Wait for data preload before allowing normal operation.
await this._ready;
const plugins = this.plugins;
if (!(plugin in plugins)) {
return this.load(plugin).then(() => this.upload(plugin, raw));
}
// Set the local copy.
plugins[plugin].raw = raw;
return this._save(plugin);
}

@@ -378,22 +352,20 @@ /**

*/
_load(data) {
return __awaiter(this, void 0, void 0, function* () {
const plugin = data.id;
// Validate and preload the item.
try {
yield this._validate(data);
}
catch (errors) {
const output = [`Validating ${plugin} failed:`];
errors.forEach((error, index) => {
const { dataPath, schemaPath, keyword, message } = error;
if (dataPath || schemaPath) {
output.push(`${index} - schema @ ${schemaPath}, data @ ${dataPath}`);
}
output.push(`{${keyword}} ${message}`);
});
console.warn(output.join('\n'));
throw errors;
}
});
async _load(data) {
const plugin = data.id;
// Validate and preload the item.
try {
await this._validate(data);
}
catch (errors) {
const output = [`Validating ${plugin} failed:`];
errors.forEach((error, index) => {
const { dataPath, schemaPath, keyword, message } = error;
if (dataPath || schemaPath) {
output.push(`${index} - schema @ ${schemaPath}, data @ ${dataPath}`);
}
output.push(`{${keyword}} ${message}`);
});
console.warn(output.join('\n'));
throw errors;
}
}

@@ -403,83 +375,77 @@ /**

*/
_preload(plugins) {
return __awaiter(this, void 0, void 0, function* () {
yield Promise.all(plugins.map((plugin) => __awaiter(this, void 0, void 0, function* () {
try {
// Apply a transformation to the plugin if necessary.
yield this._load(yield this._transform('fetch', plugin));
}
catch (errors) {
/* Ignore preload errors. */
console.log('Ignored setting registry preload errors.', errors);
}
})));
});
}
/**
* Save a plugin in the registry.
*/
_save(plugin) {
return __awaiter(this, void 0, void 0, function* () {
const plugins = this.plugins;
if (!(plugin in plugins)) {
throw new Error(`${plugin} does not exist in setting registry.`);
}
async _preload(plugins) {
await Promise.all(plugins.map(async (plugin) => {
try {
yield this._validate(plugins[plugin]);
// Apply a transformation to the plugin if necessary.
await this._load(await this._transform('fetch', plugin));
}
catch (errors) {
console.warn(`${plugin} validation errors:`, errors);
throw new Error(`${plugin} failed to validate; check console.`);
/* Ignore preload errors. */
console.log('Ignored setting registry preload errors.', errors);
}
yield this.connector.save(plugin, plugins[plugin].raw);
// Fetch and reload the data to guarantee server and client are in sync.
const fetched = yield this.connector.fetch(plugin);
yield this._load(yield this._transform('fetch', fetched));
this._pluginChanged.emit(plugin);
});
}));
}
/**
* Save a plugin in the registry.
*/
async _save(plugin) {
const plugins = this.plugins;
if (!(plugin in plugins)) {
throw new Error(`${plugin} does not exist in setting registry.`);
}
try {
await this._validate(plugins[plugin]);
}
catch (errors) {
console.warn(`${plugin} validation errors:`, errors);
throw new Error(`${plugin} failed to validate; check console.`);
}
await this.connector.save(plugin, plugins[plugin].raw);
// Fetch and reload the data to guarantee server and client are in sync.
const fetched = await this.connector.fetch(plugin);
await this._load(await this._transform('fetch', fetched));
this._pluginChanged.emit(plugin);
}
/**
* Transform the plugin if necessary.
*/
_transform(phase, plugin, started = new Date().getTime()) {
return __awaiter(this, void 0, void 0, function* () {
const elapsed = new Date().getTime() - started;
const id = plugin.id;
const transformers = this._transformers;
const timeout = this._timeout;
if (!plugin.schema['jupyter.lab.transform']) {
return plugin;
async _transform(phase, plugin, started = new Date().getTime()) {
const elapsed = new Date().getTime() - started;
const id = plugin.id;
const transformers = this._transformers;
const timeout = this._timeout;
if (!plugin.schema['jupyter.lab.transform']) {
return plugin;
}
if (id in transformers) {
const transformed = transformers[id][phase].call(null, plugin);
if (transformed.id !== id) {
throw [
{
dataPath: '',
keyword: 'id',
message: 'Plugin transformations cannot change plugin IDs.',
schemaPath: ''
}
];
}
if (id in transformers) {
const transformed = transformers[id][phase].call(null, plugin);
if (transformed.id !== id) {
throw [
{
dataPath: '',
keyword: 'id',
message: 'Plugin transformations cannot change plugin IDs.',
schemaPath: ''
}
];
}
return transformed;
return transformed;
}
// If the timeout has not been exceeded, stall and try again in 250ms.
if (elapsed < timeout) {
await new Promise(resolve => {
setTimeout(() => {
resolve();
}, 250);
});
return this._transform(phase, plugin, started);
}
throw [
{
dataPath: '',
keyword: 'timeout',
message: `Transforming ${plugin.id} timed out.`,
schemaPath: ''
}
// If the timeout has not been exceeded, stall and try again in 250ms.
if (elapsed < timeout) {
yield new Promise(resolve => {
setTimeout(() => {
resolve();
}, 250);
});
return this._transform(phase, plugin, started);
}
throw [
{
dataPath: '',
keyword: 'timeout',
message: `Transforming ${plugin.id} timed out.`,
schemaPath: ''
}
];
});
];
}

@@ -489,12 +455,10 @@ /**

*/
_validate(plugin) {
return __awaiter(this, void 0, void 0, function* () {
// Validate the user data and create the composite data.
const errors = this.validator.validateData(plugin);
if (errors) {
throw errors;
}
// Apply a transformation if necessary and set the local copy.
this.plugins[plugin.id] = yield this._transform('compose', plugin);
});
async _validate(plugin) {
// Validate the user data and create the composite data.
const errors = this.validator.validateData(plugin);
if (errors) {
throw errors;
}
// Apply a transformation if necessary and set the local copy.
this.plugins[plugin.id] = await this._transform('compose', plugin);
}

@@ -501,0 +465,0 @@ }

@@ -1,35 +0,6 @@

import { ReadonlyJSONObject, ReadonlyJSONValue, Token } from '@phosphor/coreutils';
import { ReadonlyJSONObject, ReadonlyJSONValue } from '@phosphor/coreutils';
import { ISignal } from '@phosphor/signaling';
import { IDataConnector } from './interfaces';
import { IStateDB } from './tokens';
/**
* The default state database token.
*/
export declare const IStateDB: Token<IStateDB<ReadonlyJSONValue>>;
/**
* The description of a state database.
*/
export interface IStateDB<T extends ReadonlyJSONValue = ReadonlyJSONValue> extends IDataConnector<T> {
/**
* The maximum allowed length of the data after it has been serialized.
*/
readonly maxLength: number;
/**
* The namespace prefix for all state database entries.
*
* #### Notes
* This value should be set at instantiation and will only be used
* internally by a state database. That means, for example, that an
* app could have multiple, mutually exclusive state databases.
*/
readonly namespace: string;
/**
* Return a serialized copy of the state database's entire contents.
*
* @returns A promise that bears the database contents as JSON.
*/
toJSON(): Promise<{
[id: string]: T;
}>;
}
/**
* The default concrete implementation of a state database.

@@ -43,3 +14,3 @@ */

*/
constructor(options: StateDB.IOptions);
constructor(options?: StateDB.IOptions);
/**

@@ -50,18 +21,5 @@ * A signal that emits the change type any time a value changes.

/**
* The maximum allowed length of the data after it has been serialized.
*/
readonly maxLength: number;
/**
* The namespace prefix for all state database entries.
*
* #### Notes
* This value should be set at instantiation and will only be used internally
* by a state database. That means, for example, that an app could have
* multiple, mutually exclusive state databases.
*/
readonly namespace: string;
/**
* Clear the entire database.
*/
clear(silent?: boolean): Promise<void>;
clear(): Promise<void>;
/**

@@ -134,12 +92,9 @@ * Retrieve a saved bundle from the database.

*
* @returns A promise that bears the database contents as JSON.
* @returns A promise that resolves with the database contents as JSON.
*/
toJSON(): Promise<{
[id: string]: T;
readonly [id: string]: T;
}>;
/**
* Clear the entire database.
*
* #### Notes
* Unlike the public `clear` method, this method is synchronous.
*/

@@ -149,8 +104,9 @@ private _clear;

* Fetch a value from the database.
*
* #### Notes
* Unlike the public `fetch` method, this method is synchronous.
*/
private _fetch;
/**
* Fetch a list from the database.
*/
private _list;
/**
* Merge data into the state database.

@@ -165,5 +121,2 @@ */

* Remove a key in the database.
*
* #### Notes
* Unlike the public `remove` method, this method is synchronous.
*/

@@ -173,10 +126,7 @@ private _remove;

* Save a key and its value in the database.
*
* #### Notes
* Unlike the public `save` method, this method is synchronous.
*/
private _save;
private _changed;
private _connector;
private _ready;
private _window;
}

@@ -218,5 +168,5 @@ /**

/**
* The namespace prefix for all state database entries.
* Optional string key/value connector. Defaults to in-memory connector.
*/
namespace: string;
connector?: IDataConnector<string>;
/**

@@ -228,13 +178,28 @@ * An optional promise that resolves with a data transformation that is

transform?: Promise<DataTransform>;
}
/**
* An in-memory string key/value data connector.
*/
class Connector implements IDataConnector<string> {
/**
* An optional name for the application window.
*
* #### Notes
* In environments where multiple windows can instantiate a state database,
* a window name is necessary to prefix all keys that are stored within the
* local storage that is shared by all windows. In JupyterLab, this window
* name is generated by the `IWindowResolver` extension.
* Retrieve an item from the data connector.
*/
windowName?: string;
fetch(id: string): Promise<string>;
/**
* Retrieve the list of items available from the data connector.
*/
list(query?: string): Promise<{
ids: string[];
values: string[];
}>;
/**
* Remove a value using the data connector.
*/
remove(id: string): Promise<void>;
/**
* Save a value using the data connector.
*/
save(id: string, value: string): Promise<void>;
private _storage;
}
}
"use strict";
// Copyright (c) Jupyter Development Team.
// Distributed under the terms of the Modified BSD License.
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 });
const coreutils_1 = require("@phosphor/coreutils");
const signaling_1 = require("@phosphor/signaling");
/* tslint:disable */
/**
* The default state database token.
*/
exports.IStateDB = new coreutils_1.Token('@jupyterlab/coreutils:IStateDB');
/**
* The default concrete implementation of a state database.

@@ -29,11 +15,6 @@ */

*/
constructor(options) {
/**
* The maximum allowed length of the data after it has been serialized.
*/
this.maxLength = 2000;
constructor(options = {}) {
this._changed = new signaling_1.Signal(this);
const { namespace, transform, windowName } = options;
this.namespace = namespace;
this._window = windowName || '';
const { connector, transform } = options;
this._connector = connector || new StateDB.Connector();
this._ready = (transform || Promise.resolve(null)).then(transformation => {

@@ -48,10 +29,7 @@ if (!transformation) {

case 'clear':
this._clear();
return;
return this._clear();
case 'merge':
this._merge(contents || {});
return;
return this._merge(contents || {});
case 'overwrite':
this._overwrite(contents || {});
return;
return this._overwrite(contents || {});
default:

@@ -71,10 +49,5 @@ return;

*/
clear(silent = false) {
return this._ready.then(() => {
this._clear();
if (silent) {
return;
}
this._changed.emit({ id: null, type: 'clear' });
});
async clear() {
await this._ready;
await this._clear();
}

@@ -99,7 +72,5 @@ /**

*/
fetch(id) {
return __awaiter(this, void 0, void 0, function* () {
const value = yield this._ready.then(() => this._fetch(id));
return value;
});
async fetch(id) {
await this._ready;
return this._fetch(id);
}

@@ -122,8 +93,5 @@ /**

*/
list(namespace) {
return this._ready.then(() => {
const prefix = `${this._window}:${this.namespace}:`;
const mask = (key) => key.replace(prefix, '');
return Private.fetchNamespace(`${prefix}${namespace}:`, mask);
});
async list(namespace) {
await this._ready;
return this._list(namespace);
}

@@ -137,7 +105,6 @@ /**

*/
remove(id) {
return this._ready.then(() => {
this._remove(id);
this._changed.emit({ id, type: 'remove' });
});
async remove(id) {
await this._ready;
await this._remove(id);
this._changed.emit({ id, type: 'remove' });
}

@@ -160,7 +127,6 @@ /**

*/
save(id, value) {
return this._ready.then(() => {
this._save(id, value);
this._changed.emit({ id, type: 'save' });
});
async save(id, value) {
await this._ready;
await this._save(id, value);
this._changed.emit({ id, type: 'save' });
}

@@ -170,50 +136,42 @@ /**

*
* @returns A promise that bears the database contents as JSON.
* @returns A promise that resolves with the database contents as JSON.
*/
toJSON() {
return this._ready.then(() => {
const prefix = `${this._window}:${this.namespace}:`;
const mask = (key) => key.replace(prefix, '');
return Private.toJSON(prefix, mask);
});
async toJSON() {
await this._ready;
const { ids, values } = await this._list();
return values.reduce((acc, val, idx) => {
acc[ids[idx]] = val;
return acc;
}, {});
}
/**
* Clear the entire database.
*
* #### Notes
* Unlike the public `clear` method, this method is synchronous.
*/
_clear() {
const { localStorage } = window;
const prefix = `${this._window}:${this.namespace}:`;
let i = localStorage.length;
while (i) {
let key = localStorage.key(--i);
if (key && key.indexOf(prefix) === 0) {
localStorage.removeItem(key);
}
}
async _clear() {
await Promise.all((await this._list()).ids.map(id => this._remove(id)));
}
/**
* Fetch a value from the database.
*
* #### Notes
* Unlike the public `fetch` method, this method is synchronous.
*/
_fetch(id) {
const key = `${this._window}:${this.namespace}:${id}`;
const value = window.localStorage.getItem(key);
async _fetch(id) {
const value = await this._connector.fetch(id);
if (value) {
const envelope = JSON.parse(value);
return envelope.v;
return JSON.parse(value).v;
}
return undefined;
}
/**
* Fetch a list from the database.
*/
async _list(query) {
const { ids, values } = await this._connector.list(query);
return {
ids,
values: values.map(val => JSON.parse(val).v)
};
}
/**
* Merge data into the state database.
*/
_merge(contents) {
Object.keys(contents).forEach(key => {
this._save(key, contents[key]);
});
async _merge(contents) {
await Promise.all(Object.keys(contents).map(key => this._save(key, contents[key])));
}

@@ -223,89 +181,63 @@ /**

*/
_overwrite(contents) {
this._clear();
this._merge(contents);
async _overwrite(contents) {
await this._clear();
await this._merge(contents);
}
/**
* Remove a key in the database.
*
* #### Notes
* Unlike the public `remove` method, this method is synchronous.
*/
_remove(id) {
const key = `${this._window}:${this.namespace}:${id}`;
window.localStorage.removeItem(key);
async _remove(id) {
return this._connector.remove(id);
}
/**
* Save a key and its value in the database.
*
* #### Notes
* Unlike the public `save` method, this method is synchronous.
*/
_save(id, value) {
const key = `${this._window}:${this.namespace}:${id}`;
const envelope = { v: value };
const serialized = JSON.stringify(envelope);
const length = serialized.length;
const max = this.maxLength;
if (length > max) {
throw new Error(`Data length (${length}) exceeds maximum (${max})`);
}
window.localStorage.setItem(key, serialized);
async _save(id, value) {
return this._connector.save(id, JSON.stringify({ v: value }));
}
}
exports.StateDB = StateDB;
/*
* A namespace for private module data.
/**
* A namespace for StateDB statics.
*/
var Private;
(function (Private) {
(function (StateDB) {
/**
* Retrieve all the saved bundles for a given namespace in local storage.
*
* @param prefix - The namespace to retrieve.
*
* @param mask - Optional mask function to transform each key retrieved.
*
* @returns A collection of data payloads for a given prefix.
*
* #### Notes
* If there are any errors in retrieving the data, they will be logged to the
* console in order to optimistically return any extant data without failing.
* An in-memory string key/value data connector.
*/
function fetchNamespace(namespace, mask = key => key) {
const { localStorage } = window;
let ids = [];
let values = [];
let i = localStorage.length;
while (i) {
let key = localStorage.key(--i);
if (key && key.indexOf(namespace) === 0) {
let value = localStorage.getItem(key);
try {
let envelope = JSON.parse(value);
let id = mask(key);
values[ids.push(id) - 1] = envelope ? envelope.v : undefined;
class Connector {
constructor() {
this._storage = {};
}
/**
* Retrieve an item from the data connector.
*/
async fetch(id) {
return this._storage[id];
}
/**
* Retrieve the list of items available from the data connector.
*/
async list(query = '') {
return Object.keys(this._storage).reduce((acc, val) => {
if (val && val.indexOf(query) === 0) {
acc.ids.push(val);
acc.values.push(this._storage[val]);
}
catch (error) {
console.warn(error);
localStorage.removeItem(key);
}
}
return acc;
}, { ids: [], values: [] });
}
return { ids, values };
/**
* Remove a value using the data connector.
*/
async remove(id) {
delete this._storage[id];
}
/**
* Save a value using the data connector.
*/
async save(id, value) {
this._storage[id] = value;
}
}
Private.fetchNamespace = fetchNamespace;
/**
* Return a serialized copy of a namespace's contents from local storage.
*
* @returns The namespace contents as JSON.
*/
function toJSON(namespace, mask = key => key) {
const { ids, values } = fetchNamespace(namespace, mask);
return values.reduce((acc, val, idx) => {
acc[ids[idx]] = val;
return acc;
}, {});
}
Private.toJSON = toJSON;
})(Private || (Private = {}));
StateDB.Connector = Connector;
})(StateDB = exports.StateDB || (exports.StateDB = {}));

@@ -97,3 +97,3 @@ "use strict";

function objectToQueryString(value) {
const keys = Object.keys(value);
const keys = Object.keys(value).filter(key => key.length > 0);
if (!keys.length) {

@@ -120,3 +120,5 @@ return '';

const [key, value] = val.split('=');
acc[key] = decodeURIComponent(value || '');
if (key.length > 0) {
acc[key] = decodeURIComponent(value || '');
}
return acc;

@@ -123,0 +125,0 @@ }, {});

{
"name": "@jupyterlab/coreutils",
"version": "3.0.0-alpha.6",
"version": "3.0.0-alpha.7",
"description": "JupyterLab - Core Utilities",

@@ -9,2 +9,6 @@ "homepage": "https://github.com/jupyterlab/jupyterlab",

},
"repository": {
"type": "git",
"url": "https://github.com/jupyterlab/jupyterlab.git"
},
"license": "BSD-3-Clause",

@@ -23,6 +27,2 @@ "author": "Project Jupyter",

},
"repository": {
"type": "git",
"url": "https://github.com/jupyterlab/jupyterlab.git"
},
"scripts": {

@@ -40,5 +40,5 @@ "build": "tsc -b",

"ajv": "^6.5.5",
"comment-json": "^1.1.3",
"json5": "^2.1.0",
"minimist": "~1.2.0",
"moment": "~2.21.0",
"moment": "^2.24.0",
"path-posix": "~1.0.0",

@@ -48,4 +48,4 @@ "url-parse": "~1.4.3"

"devDependencies": {
"@types/comment-json": "^1.1.0",
"@types/minimist": "~1.2.0",
"@types/json5": "^0.0.30",
"@types/minimist": "^1.2.0",
"rimraf": "~2.6.2",

@@ -58,3 +58,6 @@ "typedoc": "^0.14.2",

},
"gitHead": "25152cd7c0a2d2d3d020dcd59451c236e9ecc6ab"
"jupyterlab": {
"coreDependency": true
},
"gitHead": "f8e210a027f6545b426caf4ab64c75a1e1619a44"
}
# @jupyterlab/coreutils
A JupyterLab package which provides utility functions that are widely used across many
of the `@jupyterlab` packages. This includes (among other things) functions for manipulating paths, urls, and the notebook format.
A JupyterLab package which provides utility functions that are widely used
across many of the `@jupyterlab` packages. This includes (among other things)
functions for manipulating paths, urls, and the notebook format.
This package is intended for use within both Node.js and browser environments.
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