diff --git a/apps/simple/static/binder.html b/apps/simple/static/binder.html index d65c0d91..54774d15 100644 --- a/apps/simple/static/binder.html +++ b/apps/simple/static/binder.html @@ -1,4 +1,4 @@ - + Binder - Thebe Demo @@ -52,7 +52,7 @@

Simple plots using mybinder.org

fig, ax = plt.subplots() ax.scatter(*np.random.randn(2, 100), c=np.random.randn(100)) -ax.set(title="Wow, a pyhton plot on my webpage!") +ax.set(title="Wow, a python plot on my webpage!") diff --git a/package-lock.json b/package-lock.json index a1b7e504..cccaa246 100644 --- a/package-lock.json +++ b/package-lock.json @@ -37639,7 +37639,7 @@ "@jupyterlab/theme-light-extension": "^4.0.8", "codemirror": "5.61.1", "current-script-polyfill": "^1.0.0", - "thebe-core": "^0.4.0" + "thebe-core": "^0.4.4" }, "devDependencies": { "@babel/core": "^7.12.3", @@ -63612,7 +63612,7 @@ "puppeteer": ">=1.5.0", "source-map-loader": "^4.0.1", "style-loader": "^2.0.0", - "thebe-core": "^0.4.0", + "thebe-core": "^0.4.4", "ts-jest": "^28.0.5", "ts-loader": "^9.3.1", "url-loader": "^4.1.1", diff --git a/packages/core/src/server.ts b/packages/core/src/server.ts index e31919d8..eef1c801 100644 --- a/packages/core/src/server.ts +++ b/packages/core/src/server.ts @@ -14,7 +14,7 @@ import type { LiteServerConfig } from 'thebe-lite'; import type { IRenderMimeRegistry } from '@jupyterlab/rendermime'; import type { StatusEvent } from './events'; import { WELL_KNOWN_REPO_PROVIDERS, makeBinderUrls } from './url'; -import { getExistingServer, makeDefaultStorageKey, saveServerInfo } from './sessions'; +import { getExistingServer, saveServerInfo } from './sessions'; import { KernelManager, KernelSpecAPI, @@ -170,11 +170,8 @@ class ThebeServer implements ServerRuntime, ServerRestAPI { } async clearSavedBinderSessions() { - const url = this.sessionManager?.serverSettings?.baseUrl; - if (url) - window.localStorage.removeItem( - makeDefaultStorageKey(this.config.savedSessions.storagePrefix, url), - ); + const urls = this.makeBinderUrls(); + window.localStorage.removeItem(urls.storageKey); } /** @@ -306,11 +303,11 @@ class ThebeServer implements ServerRuntime, ServerRestAPI { async checkForSavedBinderSession() { try { - const { build } = makeBinderUrls( + const { storageKey } = makeBinderUrls( this.config, this.repoProviders ?? WELL_KNOWN_REPO_PROVIDERS, ); - return getExistingServer(this.config.savedSessions, build); + return getExistingServer(this.config.savedSessions, storageKey); } catch (err: any) { this.events.triggerError({ status: ErrorStatusEvent.error, @@ -359,7 +356,7 @@ class ThebeServer implements ServerRuntime, ServerRestAPI { // the follow function will ping the server based on the settings and only return // non-null if the server is still alive. So highly likely that the remainder of // the connection calls below, work. - const existingSettings = await getExistingServer(this.config.savedSessions, urls.build); + const existingSettings = await this.checkForSavedBinderSession(); if (existingSettings) { // Connect to the existing session const serverSettings = ServerConnection.makeSettings(existingSettings); @@ -462,7 +459,7 @@ class ThebeServer implements ServerRuntime, ServerRestAPI { }); if (this.config.savedSessions.enabled) { - saveServerInfo(this.config.savedSessions, urls.build, this.id, serverSettings); + saveServerInfo(urls.storageKey, this.id, serverSettings); console.debug( `thebe:server:connectToServerViaBinder Saved session for ${this.id} at ${urls.build}`, ); diff --git a/packages/core/src/sessions.ts b/packages/core/src/sessions.ts index 8d4a0e2e..d04048e2 100644 --- a/packages/core/src/sessions.ts +++ b/packages/core/src/sessions.ts @@ -1,18 +1,11 @@ import { KernelAPI, ServerConnection } from '@jupyterlab/services'; import type { SavedSessionInfo, SavedSessionOptions, ServerSettings } from './types'; -export function makeDefaultStorageKey(storagePrefix: string, url: string) { - const urlObj = new URL(url); - // ignore the query string and hash - return `${storagePrefix}-${urlObj.origin + urlObj.pathname}`; +export function removeServerInfo(storageKey: string) { + window.localStorage.removeItem(storageKey); } -export function removeServerInfo(savedSession: Required, url: string) { - window.localStorage.removeItem(makeDefaultStorageKey(savedSession.storagePrefix, url)); -} - -export function updateLastUsedTimestamp(savedSession: Required, url: string) { - const storageKey = makeDefaultStorageKey(savedSession.storagePrefix, url); +export function updateLastUsedTimestamp(storageKey: string) { const saved = window.localStorage.getItem(storageKey); if (!saved) return; const obj = JSON.parse(saved); @@ -20,8 +13,7 @@ export function updateLastUsedTimestamp(savedSession: Required, - url: string, + storageKey: string, id: string, serverSettings: Required, ) { @@ -29,7 +21,7 @@ export function saveServerInfo( // save the current connection url+token to reuse later const { baseUrl, token, wsUrl } = serverSettings; window.localStorage.setItem( - makeDefaultStorageKey(savedSession.storagePrefix, url), + storageKey, JSON.stringify({ id, baseUrl, @@ -46,10 +38,9 @@ export function saveServerInfo( export async function getExistingServer( savedSessionOptions: Required, - url: string, + storageKey: string, ): Promise { if (!savedSessionOptions.enabled) return null; - const storageKey = makeDefaultStorageKey(savedSessionOptions.storagePrefix, url); const storedInfoJSON = window.localStorage.getItem(storageKey); if (storedInfoJSON == null) { console.debug('thebe:getExistingServer No session saved in ', storageKey); @@ -81,7 +72,7 @@ export async function getExistingServer( } // refresh lastUsed timestamp in stored info - updateLastUsedTimestamp(savedSessionOptions, existingSettings.baseUrl); + updateLastUsedTimestamp(storageKey); console.debug( `thebe:getExistingServer Saved binder session is valid and will be reused ${existingSettings.baseUrl}`, ); @@ -119,7 +110,7 @@ export function clearAllSavedSessions(storagePrefix = 'thebe-binder') { * @param storagePrefix * @param url */ -export function clearSavedSession(storagePrefix = 'thebe-binder', url = '') { - console.debug(`thebe:clearSavedSession - removing ${makeDefaultStorageKey(storagePrefix, url)}`); - window.localStorage.removeItem(makeDefaultStorageKey(storagePrefix, url)); +export function clearSavedSession(storageKey: string) { + console.debug(`thebe:clearSavedSession - removing ${storageKey}`); + window.localStorage.removeItem(storageKey); } diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 84fea79b..b7dc488e 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -48,7 +48,7 @@ export interface RepoProviderSpec { export interface BinderUrlSet { build: string; launch: string; - storageKey?: string; + storageKey: string; } export type WellKnownRepoProvider = 'git' | 'github' | 'gitlab' | 'gist'; diff --git a/packages/core/src/url.ts b/packages/core/src/url.ts index 9795d5fd..f632a9ae 100644 --- a/packages/core/src/url.ts +++ b/packages/core/src/url.ts @@ -1,7 +1,12 @@ import type { Config } from './config'; -import { makeDefaultStorageKey } from './sessions'; import type { BinderUrlSet, RepoProviderSpec } from './types'; +export function makeDefaultStorageKey(storagePrefix: string, url: string) { + const urlObj = new URL(url); + // ignore the query string and hash + return `${storagePrefix}-${urlObj.origin + urlObj.pathname}`; +} + function makeDefaultBuildSpec(storagePrefix: string, binderUrl: string, stub: string) { const build = `${binderUrl}/build/${stub}`; const launch = `${binderUrl}/v2/${stub}`; diff --git a/packages/core/tests/sessions.spec.ts b/packages/core/tests/sessions.spec.ts index 8900bd41..02504a06 100644 --- a/packages/core/tests/sessions.spec.ts +++ b/packages/core/tests/sessions.spec.ts @@ -1,5 +1,5 @@ import { describe, test, expect } from 'vitest'; -import { makeDefaultStorageKey } from '../src/sessions'; +import { makeDefaultStorageKey } from '../src/url'; describe('session saving', () => { describe('make storage key', () => { diff --git a/packages/thebe/package.json b/packages/thebe/package.json index f78d6a83..815de59b 100644 --- a/packages/thebe/package.json +++ b/packages/thebe/package.json @@ -64,7 +64,7 @@ "@jupyter-widgets/base": "6.0.6", "@jupyter-widgets/controls": "5.0.7", "@jupyter-widgets/jupyterlab-manager": "5.0.9", - "thebe-core": "^0.4.0", + "thebe-core": "^0.4.4", "codemirror": "5.61.1", "current-script-polyfill": "^1.0.0" },