Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ Open the Command Palette (`Cmd+Shift+P` or `Ctrl+Shift+P`) and type `Deepnote` t
| `Deepnote: Set API Token` | Save a Deepnote API token for syncing and publishing |
| `Deepnote: Clear API Token` | Remove the saved Deepnote API token |
| `Deepnote: Sync with Deepnote Cloud` | Sync a local folder with your Deepnote workspace |
| `Deepnote: Publish App…` | Publish a folder, such as an app's build output, as a Deepnote app |
| `Notebook: Select Notebook Kernel` | Select or switch kernels within your notebook |
| `Notebook: Change Cell Language` | Change the language of the cell currently in focus |
| `Deepnote: Enable Snapshots` | Enable snapshot mode for the current workspace |
Expand Down Expand Up @@ -94,6 +95,20 @@ Known limitations:
- After a sync updates an open notebook, the editor can save the notebook again, and the next sync can then push that project or report a conflict for it.
- A folder reached through a symbolic link or junction is checked by its path in the workspace, not by its target, so a link into another synced folder is not refused.

### Publishing apps

Run `Deepnote: Publish App…` from the Command Palette, or right-click a folder in the file explorer and choose `Publish App…`. It uploads the folder to a Deepnote project as an app, then shows the app URL with "Open" and "Copy".

- The folder is published as it is. Build your app first, then publish its build output folder, such as `dist/`.
- Each file of the folder replaces the app file at the same path in Deepnote. Files you delete from the folder are not deleted in Deepnote and stay published; delete them in Deepnote.
- When the folder is inside a synced project, the app goes to that project. Otherwise you choose a project of your Deepnote workspace.
- You also choose whether the app can call the Deepnote API. With API access, the app calls Deepnote with a short-lived token scoped to the viewer, never your personal token.
- The choices are remembered per folder, so publishing the folder again asks only for one confirmation, with "Change Settings…" to choose again.
- Publishing uses `DEEPNOTE_TOKEN` from a `.env` file in a synced folder above the app folder, or else the token saved with `Deepnote: Set API Token`. A folder that contains a `.env` or `.env.*` file cannot be published, because every published file is public.
- Publishing into a synced folder does not start while a sync or another such publish is in progress.
- For a folder inside a synced project, when app files changed in Deepnote since the last sync or publish, publishing asks first. "Force" overwrites them in Deepnote. "Sync First" syncs the whole synced folder with the working files of every project, which downloads Deepnote's versions of the app files into the synced project's `.files/_deepnote_static` folder, so you can merge them into your app and publish again. A project with a working file over 100 MiB fails to sync this way. A folder outside a synced project overwrites app files changed in Deepnote without asking.
- Publishing needs a trusted workspace and the desktop app.

### Database integrations

Configure database connections for SQL blocks:
Expand Down
12 changes: 12 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,13 @@
"icon": "$(sync)",
"enablement": "isWorkspaceTrusted && !deepnote.webExtension"
},
{
"command": "deepnote.publishApp",
"title": "%deepnote.commands.publishApp.title%",
"category": "Deepnote",
"icon": "$(rocket)",
"enablement": "isWorkspaceTrusted && !deepnote.webExtension"
},
{
"command": "deepnote.newProject",
"title": "%deepnote.commands.newProject.title%",
Expand Down Expand Up @@ -1249,6 +1256,11 @@
"when": "resourceExtname == .ipynb && isWorkspaceTrusted",
"command": "deepnote.importnotebookfile",
"group": "Deepnote"
},
{
"when": "explorerResourceIsFolder && isWorkspaceTrusted && !deepnote.webExtension",
"command": "deepnote.publishApp",
"group": "Deepnote"
}
],
"commandPalette": [
Expand Down
1 change: 1 addition & 0 deletions package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -262,6 +262,7 @@
"deepnote.commands.setApiToken.title": "Set API Token",
"deepnote.commands.clearApiToken.title": "Clear API Token",
"deepnote.commands.syncWithDeepnoteCloud.title": "Sync with Deepnote Cloud",
"deepnote.commands.publishApp.title": "Publish App…",
"deepnote.commands.newProject.title": "New Project",
"deepnote.commands.importNotebook.title": "Import Notebook",
"deepnote.commands.importJupyterNotebook.title": "Import Jupyter Notebook",
Expand Down
4 changes: 3 additions & 1 deletion src/commands.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { PythonEnvironment } from './platform/pythonEnvironments/info';
import { Channel } from './platform/common/application/types';
import { IJupyterVariable } from './kernels/variables/types';
import { IShowDataViewerFromVariablePanel } from './messageTypes';
import { SyncWithDeepnoteCloudTarget } from './notebooks/deepnote/cloud/types';

export type CommandIds = keyof ICommandNameArgumentTypeMapping;

Expand Down Expand Up @@ -209,5 +210,6 @@ export interface ICommandNameArgumentTypeMapping {
[DSCommands.OpenInDeepnote]: [];
[DSCommands.SetApiToken]: [Uri | undefined];
[DSCommands.ClearApiToken]: [];
[DSCommands.SyncWithDeepnoteCloud]: [];
[DSCommands.SyncWithDeepnoteCloud]: [SyncWithDeepnoteCloudTarget | undefined];
[DSCommands.PublishApp]: [Uri | undefined];
}
21 changes: 21 additions & 0 deletions src/notebooks/deepnote/cloud/deepnoteCloudOperationLock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { injectable } from 'inversify';
import { Disposable } from 'vscode';

import { IDeepnoteCloudOperationLock } from './types';

@injectable()
export class DeepnoteCloudOperationLock implements IDeepnoteCloudOperationLock {
private held = false;

public tryAcquire(): Disposable | undefined {
if (this.held) {
return undefined;
}

this.held = true;

return new Disposable(() => {
this.held = false;
});
}
}
Loading
Loading