@difizen/libro-kernel 0.0.2-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +1 -0
- package/es/basemanager.d.ts +94 -0
- package/es/basemanager.d.ts.map +1 -0
- package/es/basemanager.js +110 -0
- package/es/contents/contents-drive.d.ts +189 -0
- package/es/contents/contents-drive.d.ts.map +1 -0
- package/es/contents/contents-drive.js +792 -0
- package/es/contents/contents-manager.d.ts +229 -0
- package/es/contents/contents-manager.d.ts.map +1 -0
- package/es/contents/contents-manager.js +551 -0
- package/es/contents/contents-module.d.ts +3 -0
- package/es/contents/contents-module.d.ts.map +1 -0
- package/es/contents/contents-module.js +4 -0
- package/es/contents/contents-protocol.d.ts +487 -0
- package/es/contents/contents-protocol.d.ts.map +1 -0
- package/es/contents/contents-protocol.js +1 -0
- package/es/contents/index.d.ts +6 -0
- package/es/contents/index.d.ts.map +1 -0
- package/es/contents/index.js +5 -0
- package/es/contents/validate.d.ts +10 -0
- package/es/contents/validate.d.ts.map +1 -0
- package/es/contents/validate.js +22 -0
- package/es/index.d.ts +10 -0
- package/es/index.d.ts.map +1 -0
- package/es/index.js +9 -0
- package/es/index.less +0 -0
- package/es/kernel/comm.d.ts +92 -0
- package/es/kernel/comm.d.ts.map +1 -0
- package/es/kernel/comm.js +216 -0
- package/es/kernel/future.d.ts +178 -0
- package/es/kernel/future.d.ts.map +1 -0
- package/es/kernel/future.js +587 -0
- package/es/kernel/index.d.ts +8 -0
- package/es/kernel/index.d.ts.map +1 -0
- package/es/kernel/index.js +8 -0
- package/es/kernel/kernel-connection.d.ts +550 -0
- package/es/kernel/kernel-connection.d.ts.map +1 -0
- package/es/kernel/kernel-connection.js +1957 -0
- package/es/kernel/kernel-module.d.ts +3 -0
- package/es/kernel/kernel-module.d.ts.map +1 -0
- package/es/kernel/kernel-module.js +32 -0
- package/es/kernel/libro-kernel-manager.d.ts +69 -0
- package/es/kernel/libro-kernel-manager.d.ts.map +1 -0
- package/es/kernel/libro-kernel-manager.js +349 -0
- package/es/kernel/libro-kernel-protocol.d.ts +675 -0
- package/es/kernel/libro-kernel-protocol.d.ts.map +1 -0
- package/es/kernel/libro-kernel-protocol.js +60 -0
- package/es/kernel/libro-kernel-utils.d.ts +95 -0
- package/es/kernel/libro-kernel-utils.d.ts.map +1 -0
- package/es/kernel/libro-kernel-utils.js +130 -0
- package/es/kernel/libro-kernel.d.ts +14 -0
- package/es/kernel/libro-kernel.d.ts.map +1 -0
- package/es/kernel/libro-kernel.js +54 -0
- package/es/kernel/messages.d.ts +845 -0
- package/es/kernel/messages.d.ts.map +1 -0
- package/es/kernel/messages.js +457 -0
- package/es/kernel/restapi.d.ts +78 -0
- package/es/kernel/restapi.d.ts.map +1 -0
- package/es/kernel/restapi.js +367 -0
- package/es/kernel/serialize.d.ts +10 -0
- package/es/kernel/serialize.d.ts.map +1 -0
- package/es/kernel/serialize.js +214 -0
- package/es/kernel/validate.d.ts +15 -0
- package/es/kernel/validate.d.ts.map +1 -0
- package/es/kernel/validate.js +125 -0
- package/es/kernelspec/index.d.ts +5 -0
- package/es/kernelspec/index.d.ts.map +1 -0
- package/es/kernelspec/index.js +4 -0
- package/es/kernelspec/kernelspec-module.d.ts +3 -0
- package/es/kernelspec/kernelspec-module.d.ts.map +1 -0
- package/es/kernelspec/kernelspec-module.js +4 -0
- package/es/kernelspec/kernelspec.d.ts +33 -0
- package/es/kernelspec/kernelspec.d.ts.map +1 -0
- package/es/kernelspec/kernelspec.js +1 -0
- package/es/kernelspec/manager.d.ts +81 -0
- package/es/kernelspec/manager.d.ts.map +1 -0
- package/es/kernelspec/manager.js +248 -0
- package/es/kernelspec/restapi.d.ts +71 -0
- package/es/kernelspec/restapi.d.ts.map +1 -0
- package/es/kernelspec/restapi.js +107 -0
- package/es/kernelspec/validate.d.ts +10 -0
- package/es/kernelspec/validate.d.ts.map +1 -0
- package/es/kernelspec/validate.js +69 -0
- package/es/libro-kernel-connection-manager.d.ts +19 -0
- package/es/libro-kernel-connection-manager.d.ts.map +1 -0
- package/es/libro-kernel-connection-manager.js +142 -0
- package/es/module.d.ts +3 -0
- package/es/module.d.ts.map +1 -0
- package/es/module.js +9 -0
- package/es/page-config.d.ts +36 -0
- package/es/page-config.d.ts.map +1 -0
- package/es/page-config.js +129 -0
- package/es/protocol.d.ts +13 -0
- package/es/protocol.d.ts.map +1 -0
- package/es/protocol.js +8 -0
- package/es/server/connection-error.d.ts +36 -0
- package/es/server/connection-error.d.ts.map +1 -0
- package/es/server/connection-error.js +109 -0
- package/es/server/index.d.ts +6 -0
- package/es/server/index.d.ts.map +1 -0
- package/es/server/index.js +5 -0
- package/es/server/server-connection-protocol.d.ts +49 -0
- package/es/server/server-connection-protocol.d.ts.map +1 -0
- package/es/server/server-connection-protocol.js +0 -0
- package/es/server/server-connection.d.ts +25 -0
- package/es/server/server-connection.d.ts.map +1 -0
- package/es/server/server-connection.js +159 -0
- package/es/server/server-manager.d.ts +22 -0
- package/es/server/server-manager.d.ts.map +1 -0
- package/es/server/server-manager.js +163 -0
- package/es/server/server-module.d.ts +3 -0
- package/es/server/server-module.d.ts.map +1 -0
- package/es/server/server-module.js +4 -0
- package/es/session/index.d.ts +5 -0
- package/es/session/index.d.ts.map +1 -0
- package/es/session/index.js +4 -0
- package/es/session/libro-session-manager.d.ts +71 -0
- package/es/session/libro-session-manager.d.ts.map +1 -0
- package/es/session/libro-session-manager.js +539 -0
- package/es/session/libro-session-protocol.d.ts +50 -0
- package/es/session/libro-session-protocol.d.ts.map +1 -0
- package/es/session/libro-session-protocol.js +21 -0
- package/es/session/libro-session.d.ts +12 -0
- package/es/session/libro-session.d.ts.map +1 -0
- package/es/session/libro-session.js +19 -0
- package/es/session/restapi.d.ts +28 -0
- package/es/session/restapi.d.ts.map +1 -0
- package/es/session/restapi.js +214 -0
- package/es/session/session-module.d.ts +3 -0
- package/es/session/session-module.d.ts.map +1 -0
- package/es/session/session-module.js +18 -0
- package/es/session/validate.d.ts +14 -0
- package/es/session/validate.d.ts.map +1 -0
- package/es/session/validate.js +37 -0
- package/es/utils.d.ts +4 -0
- package/es/utils.d.ts.map +1 -0
- package/es/utils.js +29 -0
- package/es/validate-property.d.ts +2 -0
- package/es/validate-property.d.ts.map +1 -0
- package/es/validate-property.js +35 -0
- package/package.json +62 -0
- package/src/basemanager.ts +133 -0
- package/src/contents/contents-drive.ts +495 -0
- package/src/contents/contents-manager.ts +465 -0
- package/src/contents/contents-module.ts +6 -0
- package/src/contents/contents-protocol.ts +604 -0
- package/src/contents/index.ts +5 -0
- package/src/contents/validate.ts +29 -0
- package/src/index.tsx +9 -0
- package/src/kernel/comm.ts +220 -0
- package/src/kernel/future.ts +474 -0
- package/src/kernel/index.ts +7 -0
- package/src/kernel/kernel-connection.ts +1770 -0
- package/src/kernel/kernel-module.ts +50 -0
- package/src/kernel/libro-kernel-manager.ts +199 -0
- package/src/kernel/libro-kernel-protocol.ts +858 -0
- package/src/kernel/libro-kernel-utils.ts +152 -0
- package/src/kernel/libro-kernel.ts +39 -0
- package/src/kernel/messages.ts +1104 -0
- package/src/kernel/restapi.ts +183 -0
- package/src/kernel/serialize.ts +262 -0
- package/src/kernel/validate.ts +101 -0
- package/src/kernelspec/index.ts +5 -0
- package/src/kernelspec/kernelspec-module.ts +9 -0
- package/src/kernelspec/kernelspec.ts +37 -0
- package/src/kernelspec/manager.ts +173 -0
- package/src/kernelspec/restapi.ts +104 -0
- package/src/kernelspec/validate.ts +80 -0
- package/src/libro-kernel-connection-manager.ts +73 -0
- package/src/module.ts +19 -0
- package/src/page-config.ts +106 -0
- package/src/protocol.ts +24 -0
- package/src/server/connection-error.ts +60 -0
- package/src/server/index.ts +5 -0
- package/src/server/server-connection-protocol.ts +57 -0
- package/src/server/server-connection.ts +144 -0
- package/src/server/server-manager.ts +76 -0
- package/src/server/server-module.ts +9 -0
- package/src/session/index.ts +4 -0
- package/src/session/libro-session-manager.ts +377 -0
- package/src/session/libro-session-protocol.ts +61 -0
- package/src/session/libro-session.ts +33 -0
- package/src/session/restapi.ts +126 -0
- package/src/session/session-module.ts +26 -0
- package/src/session/validate.ts +39 -0
- package/src/utils.ts +28 -0
- package/src/validate-property.ts +38 -0
|
@@ -0,0 +1,495 @@
|
|
|
1
|
+
import type { PartialJSONObject } from '@difizen/libro-common';
|
|
2
|
+
import { URL as URLUtil } from '@difizen/libro-common';
|
|
3
|
+
import type { Event as ManaEvent } from '@difizen/mana-app';
|
|
4
|
+
import { inject, singleton } from '@difizen/mana-app';
|
|
5
|
+
import { Emitter } from '@difizen/mana-app';
|
|
6
|
+
import qs from 'query-string';
|
|
7
|
+
|
|
8
|
+
import type { ISettings } from '../server/index.js';
|
|
9
|
+
import { createResponseError, ServerConnection } from '../server/index.js';
|
|
10
|
+
|
|
11
|
+
import type {
|
|
12
|
+
IContentsChangedArgs,
|
|
13
|
+
IContentsCheckpointModel,
|
|
14
|
+
IContentsCreateOptions,
|
|
15
|
+
IContentsDrive,
|
|
16
|
+
IContentsFetchOptions,
|
|
17
|
+
IContentsModel,
|
|
18
|
+
IContentsRequestOptions,
|
|
19
|
+
} from './contents-protocol.js';
|
|
20
|
+
import * as validate from './validate.js';
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* The url for the default drive service.
|
|
24
|
+
*/
|
|
25
|
+
const SERVICE_DRIVE_URL = 'api/contents';
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* The url for the file access.
|
|
29
|
+
*/
|
|
30
|
+
const FILES_URL = 'files';
|
|
31
|
+
|
|
32
|
+
function normalizeExtension(extension: string): string {
|
|
33
|
+
if (extension.length > 0 && extension.indexOf('.') !== 0) {
|
|
34
|
+
// eslint-disable-next-line no-param-reassign
|
|
35
|
+
extension = `.${extension}`;
|
|
36
|
+
}
|
|
37
|
+
return extension;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* A default implementation for an `IContentsDrive`, talking to the
|
|
41
|
+
* server using the Jupyter REST API.
|
|
42
|
+
*/
|
|
43
|
+
@singleton()
|
|
44
|
+
export class Drive implements IContentsDrive {
|
|
45
|
+
@inject(ServerConnection) serverConnection: ServerConnection;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Construct a new contents manager object.
|
|
49
|
+
*
|
|
50
|
+
* @param options - The options used to initialize the object.
|
|
51
|
+
*/
|
|
52
|
+
constructor() {
|
|
53
|
+
this.apiEndpoint = SERVICE_DRIVE_URL;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* The name of the drive, which is used at the leading
|
|
58
|
+
* component of file paths.
|
|
59
|
+
*/
|
|
60
|
+
readonly name: string;
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* A signal emitted when a file operation takes place.
|
|
64
|
+
*/
|
|
65
|
+
get fileChanged(): ManaEvent<IContentsChangedArgs> {
|
|
66
|
+
return this.fileChangedEmitter.event;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* The server settings of the drive.
|
|
71
|
+
*/
|
|
72
|
+
// readonly serverSettings: ISettings;
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Test whether the manager has been disposed.
|
|
76
|
+
*/
|
|
77
|
+
get isDisposed(): boolean {
|
|
78
|
+
return this._isDisposed;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Dispose of the resources held by the manager.
|
|
83
|
+
*/
|
|
84
|
+
dispose(): void {
|
|
85
|
+
if (this.isDisposed) {
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
this._isDisposed = true;
|
|
89
|
+
this.fileChangedEmitter.dispose();
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Get a file or directory.
|
|
94
|
+
*
|
|
95
|
+
* @param localPath: The path to the file.
|
|
96
|
+
*
|
|
97
|
+
* @param options: The options used to fetch the file.
|
|
98
|
+
*
|
|
99
|
+
* @returns A promise which resolves with the file content.
|
|
100
|
+
*
|
|
101
|
+
* Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/contents) and validates the response model.
|
|
102
|
+
*/
|
|
103
|
+
async get(
|
|
104
|
+
localPath: string,
|
|
105
|
+
options?: IContentsFetchOptions,
|
|
106
|
+
): Promise<IContentsModel> {
|
|
107
|
+
let url = this.getUrl(options?.baseUrl, localPath);
|
|
108
|
+
const settings = this._getSettings(options?.baseUrl);
|
|
109
|
+
|
|
110
|
+
if (options) {
|
|
111
|
+
// The notebook type cannot take an format option.
|
|
112
|
+
if (options.type === 'notebook') {
|
|
113
|
+
delete options.format;
|
|
114
|
+
}
|
|
115
|
+
if (options.baseUrl) {
|
|
116
|
+
delete options.baseUrl;
|
|
117
|
+
}
|
|
118
|
+
const content = options.content ? '1' : '0';
|
|
119
|
+
const params: PartialJSONObject = { ...options, content };
|
|
120
|
+
url += `?${qs.stringify(params)}`;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const response = await this.serverConnection.makeRequest(url, {}, settings);
|
|
124
|
+
if (response.status !== 200) {
|
|
125
|
+
const err = await createResponseError(response);
|
|
126
|
+
throw err;
|
|
127
|
+
}
|
|
128
|
+
const data = await response.json();
|
|
129
|
+
validate.validateContentsModel(data);
|
|
130
|
+
return data;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Get an encoded download url given a file path.
|
|
135
|
+
*
|
|
136
|
+
* @param localPath - An absolute POSIX file path on the server.
|
|
137
|
+
*
|
|
138
|
+
* #### Notes
|
|
139
|
+
* It is expected that the path contains no relative paths.
|
|
140
|
+
*
|
|
141
|
+
* The returned URL may include a query parameter.
|
|
142
|
+
*/
|
|
143
|
+
getDownloadUrl(
|
|
144
|
+
localPath: string,
|
|
145
|
+
options?: IContentsRequestOptions,
|
|
146
|
+
): Promise<string> {
|
|
147
|
+
const baseUrl = options?.baseUrl || this.serverConnection.settings.baseUrl;
|
|
148
|
+
let url = URLUtil.join(baseUrl, FILES_URL, URLUtil.encodeParts(localPath));
|
|
149
|
+
const xsrfTokenMatch = document.cookie.match('\\b_xsrf=([^;]*)\\b');
|
|
150
|
+
if (xsrfTokenMatch) {
|
|
151
|
+
const fullUrl = new URL(url);
|
|
152
|
+
fullUrl.searchParams.append('_xsrf', xsrfTokenMatch[1]);
|
|
153
|
+
url = fullUrl.toString();
|
|
154
|
+
}
|
|
155
|
+
return Promise.resolve(url);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* Create a new untitled file or directory in the specified directory path.
|
|
160
|
+
*
|
|
161
|
+
* @param options: The options used to create the file.
|
|
162
|
+
*
|
|
163
|
+
* @returns A promise which resolves with the created file content when the
|
|
164
|
+
* file is created.
|
|
165
|
+
*
|
|
166
|
+
* #### Notes
|
|
167
|
+
* Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/contents) and validates the response model.
|
|
168
|
+
*/
|
|
169
|
+
async newUntitled(options: IContentsCreateOptions = {}): Promise<IContentsModel> {
|
|
170
|
+
let body = '{}';
|
|
171
|
+
const settings = this._getSettings(options.baseUrl);
|
|
172
|
+
if (options) {
|
|
173
|
+
if (options.ext) {
|
|
174
|
+
options.ext = normalizeExtension(options.ext);
|
|
175
|
+
}
|
|
176
|
+
if (options.baseUrl) {
|
|
177
|
+
delete options.baseUrl;
|
|
178
|
+
}
|
|
179
|
+
body = JSON.stringify(options);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
const url = this.getUrl(options.baseUrl, options.path ?? '');
|
|
183
|
+
const init = {
|
|
184
|
+
method: 'POST',
|
|
185
|
+
body,
|
|
186
|
+
};
|
|
187
|
+
const response = await this.serverConnection.makeRequest(url, init, settings);
|
|
188
|
+
if (response.status !== 201) {
|
|
189
|
+
const err = await createResponseError(response);
|
|
190
|
+
throw err;
|
|
191
|
+
}
|
|
192
|
+
const data = await response.json();
|
|
193
|
+
validate.validateContentsModel(data);
|
|
194
|
+
this.fileChangedEmitter.fire({
|
|
195
|
+
type: 'new',
|
|
196
|
+
oldValue: null,
|
|
197
|
+
newValue: data,
|
|
198
|
+
});
|
|
199
|
+
return data;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/**
|
|
203
|
+
* Delete a file.
|
|
204
|
+
*
|
|
205
|
+
* @param localPath - The path to the file.
|
|
206
|
+
*
|
|
207
|
+
* @returns A promise which resolves when the file is deleted.
|
|
208
|
+
*
|
|
209
|
+
* #### Notes
|
|
210
|
+
* Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/contents).
|
|
211
|
+
*/
|
|
212
|
+
async delete(localPath: string, options?: IContentsRequestOptions): Promise<void> {
|
|
213
|
+
const url = this.getUrl(options?.baseUrl, localPath);
|
|
214
|
+
const init = { method: 'DELETE' };
|
|
215
|
+
const settings = this._getSettings(options?.baseUrl);
|
|
216
|
+
const response = await this.serverConnection.makeRequest(url, init, settings);
|
|
217
|
+
// TODO: update IPEP27 to specify errors more precisely, so
|
|
218
|
+
// that error types can be detected here with certainty.
|
|
219
|
+
if (response.status !== 204) {
|
|
220
|
+
const err = await createResponseError(response);
|
|
221
|
+
throw err;
|
|
222
|
+
}
|
|
223
|
+
this.fileChangedEmitter.fire({
|
|
224
|
+
type: 'delete',
|
|
225
|
+
oldValue: { path: localPath },
|
|
226
|
+
newValue: null,
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Rename a file or directory.
|
|
232
|
+
*
|
|
233
|
+
* @param oldLocalPath - The original file path.
|
|
234
|
+
*
|
|
235
|
+
* @param newLocalPath - The new file path.
|
|
236
|
+
*
|
|
237
|
+
* @returns A promise which resolves with the new file contents model when
|
|
238
|
+
* the file is renamed.
|
|
239
|
+
*
|
|
240
|
+
* #### Notes
|
|
241
|
+
* Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/contents) and validates the response model.
|
|
242
|
+
*/
|
|
243
|
+
async rename(
|
|
244
|
+
oldLocalPath: string,
|
|
245
|
+
newLocalPath: string,
|
|
246
|
+
options?: IContentsRequestOptions,
|
|
247
|
+
): Promise<IContentsModel> {
|
|
248
|
+
const url = this.getUrl(options?.baseUrl, oldLocalPath);
|
|
249
|
+
const init = {
|
|
250
|
+
method: 'PATCH',
|
|
251
|
+
body: JSON.stringify({ path: newLocalPath }),
|
|
252
|
+
};
|
|
253
|
+
const settings = this._getSettings(options?.baseUrl);
|
|
254
|
+
const response = await this.serverConnection.makeRequest(url, init, settings);
|
|
255
|
+
if (response.status !== 200) {
|
|
256
|
+
const err = await createResponseError(response);
|
|
257
|
+
throw err;
|
|
258
|
+
}
|
|
259
|
+
const data = await response.json();
|
|
260
|
+
validate.validateContentsModel(data);
|
|
261
|
+
this.fileChangedEmitter.fire({
|
|
262
|
+
type: 'rename',
|
|
263
|
+
oldValue: { path: oldLocalPath },
|
|
264
|
+
newValue: data,
|
|
265
|
+
});
|
|
266
|
+
return data;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
/**
|
|
270
|
+
* Save a file.
|
|
271
|
+
*
|
|
272
|
+
* @param localPath - The desired file path.
|
|
273
|
+
*
|
|
274
|
+
* @param options - Optional overrides to the model.
|
|
275
|
+
*
|
|
276
|
+
* @returns A promise which resolves with the file content model when the
|
|
277
|
+
* file is saved.
|
|
278
|
+
*
|
|
279
|
+
* #### Notes
|
|
280
|
+
* Ensure that `model.content` is populated for the file.
|
|
281
|
+
*
|
|
282
|
+
* Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/contents) and validates the response model.
|
|
283
|
+
*/
|
|
284
|
+
async save(
|
|
285
|
+
localPath: string,
|
|
286
|
+
options: Partial<IContentsModel> = {},
|
|
287
|
+
): Promise<IContentsModel> {
|
|
288
|
+
const url = this.getUrl(options.baseUrl, localPath);
|
|
289
|
+
const settings = this._getSettings(options.baseUrl);
|
|
290
|
+
|
|
291
|
+
if (options) {
|
|
292
|
+
if (options.baseUrl) {
|
|
293
|
+
delete options.baseUrl;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
const init = {
|
|
298
|
+
method: 'PUT',
|
|
299
|
+
body: JSON.stringify(options),
|
|
300
|
+
};
|
|
301
|
+
const response = await this.serverConnection.makeRequest(url, init, settings);
|
|
302
|
+
// will return 200 for an existing file and 201 for a new file
|
|
303
|
+
if (response.status !== 200 && response.status !== 201) {
|
|
304
|
+
const err = await createResponseError(response);
|
|
305
|
+
throw err;
|
|
306
|
+
}
|
|
307
|
+
const data = await response.json();
|
|
308
|
+
validate.validateContentsModel(data);
|
|
309
|
+
this.fileChangedEmitter.fire({
|
|
310
|
+
type: 'save',
|
|
311
|
+
oldValue: null,
|
|
312
|
+
newValue: data,
|
|
313
|
+
});
|
|
314
|
+
return data;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* Copy a file into a given directory.
|
|
319
|
+
*
|
|
320
|
+
* @param localPath - The original file path.
|
|
321
|
+
*
|
|
322
|
+
* @param toDir - The destination directory path.
|
|
323
|
+
*
|
|
324
|
+
* @returns A promise which resolves with the new contents model when the
|
|
325
|
+
* file is copied.
|
|
326
|
+
*
|
|
327
|
+
* #### Notes
|
|
328
|
+
* The server will select the name of the copied file.
|
|
329
|
+
*
|
|
330
|
+
* Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/contents) and validates the response model.
|
|
331
|
+
*/
|
|
332
|
+
async copy(
|
|
333
|
+
fromFile: string,
|
|
334
|
+
toDir: string,
|
|
335
|
+
options?: IContentsRequestOptions,
|
|
336
|
+
): Promise<IContentsModel> {
|
|
337
|
+
const url = this.getUrl(options?.baseUrl, toDir);
|
|
338
|
+
const init = {
|
|
339
|
+
method: 'POST',
|
|
340
|
+
body: JSON.stringify({ copy_from: fromFile }),
|
|
341
|
+
};
|
|
342
|
+
const settings = this._getSettings(options?.baseUrl);
|
|
343
|
+
const response = await this.serverConnection.makeRequest(url, init, settings);
|
|
344
|
+
if (response.status !== 201) {
|
|
345
|
+
const err = await createResponseError(response);
|
|
346
|
+
throw err;
|
|
347
|
+
}
|
|
348
|
+
const data = await response.json();
|
|
349
|
+
validate.validateContentsModel(data);
|
|
350
|
+
this.fileChangedEmitter.fire({
|
|
351
|
+
type: 'new',
|
|
352
|
+
oldValue: null,
|
|
353
|
+
newValue: data,
|
|
354
|
+
});
|
|
355
|
+
return data;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
/**
|
|
359
|
+
* Create a checkpoint for a file.
|
|
360
|
+
*
|
|
361
|
+
* @param localPath - The path of the file.
|
|
362
|
+
*
|
|
363
|
+
* @returns A promise which resolves with the new checkpoint model when the
|
|
364
|
+
* checkpoint is created.
|
|
365
|
+
*
|
|
366
|
+
* #### Notes
|
|
367
|
+
* Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/contents) and validates the response model.
|
|
368
|
+
*/
|
|
369
|
+
async createCheckpoint(
|
|
370
|
+
localPath: string,
|
|
371
|
+
options?: IContentsRequestOptions,
|
|
372
|
+
): Promise<IContentsCheckpointModel> {
|
|
373
|
+
const url = this.getUrl(options?.baseUrl, localPath, 'checkpoints');
|
|
374
|
+
const init = { method: 'POST' };
|
|
375
|
+
const settings = this._getSettings(options?.baseUrl);
|
|
376
|
+
const response = await this.serverConnection.makeRequest(url, init, settings);
|
|
377
|
+
if (response.status !== 201) {
|
|
378
|
+
const err = await createResponseError(response);
|
|
379
|
+
throw err;
|
|
380
|
+
}
|
|
381
|
+
const data = await response.json();
|
|
382
|
+
validate.validateCheckpointModel(data);
|
|
383
|
+
return data;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* List available checkpoints for a file.
|
|
388
|
+
*
|
|
389
|
+
* @param localPath - The path of the file.
|
|
390
|
+
*
|
|
391
|
+
* @returns A promise which resolves with a list of checkpoint models for
|
|
392
|
+
* the file.
|
|
393
|
+
*
|
|
394
|
+
* #### Notes
|
|
395
|
+
* Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/contents) and validates the response model.
|
|
396
|
+
*/
|
|
397
|
+
async listCheckpoints(
|
|
398
|
+
localPath: string,
|
|
399
|
+
options?: IContentsRequestOptions,
|
|
400
|
+
): Promise<IContentsCheckpointModel[]> {
|
|
401
|
+
const url = this.getUrl(options?.baseUrl, localPath, 'checkpoints');
|
|
402
|
+
const settings = this._getSettings(options?.baseUrl);
|
|
403
|
+
const response = await this.serverConnection.makeRequest(url, {}, settings);
|
|
404
|
+
if (response.status !== 200) {
|
|
405
|
+
const err = await createResponseError(response);
|
|
406
|
+
throw err;
|
|
407
|
+
}
|
|
408
|
+
const data = await response.json();
|
|
409
|
+
if (!Array.isArray(data)) {
|
|
410
|
+
throw new Error('Invalid Checkpoint list');
|
|
411
|
+
}
|
|
412
|
+
for (let i = 0; i < data.length; i++) {
|
|
413
|
+
validate.validateCheckpointModel(data[i]);
|
|
414
|
+
}
|
|
415
|
+
return data;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
/**
|
|
419
|
+
* Restore a file to a known checkpoint state.
|
|
420
|
+
*
|
|
421
|
+
* @param localPath - The path of the file.
|
|
422
|
+
*
|
|
423
|
+
* @param checkpointID - The id of the checkpoint to restore.
|
|
424
|
+
*
|
|
425
|
+
* @returns A promise which resolves when the checkpoint is restored.
|
|
426
|
+
*
|
|
427
|
+
* #### Notes
|
|
428
|
+
* Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/contents).
|
|
429
|
+
*/
|
|
430
|
+
async restoreCheckpoint(
|
|
431
|
+
localPath: string,
|
|
432
|
+
checkpointID: string,
|
|
433
|
+
options?: IContentsRequestOptions,
|
|
434
|
+
): Promise<void> {
|
|
435
|
+
const url = this.getUrl(options?.baseUrl, localPath, 'checkpoints', checkpointID);
|
|
436
|
+
const settings = this._getSettings(options?.baseUrl);
|
|
437
|
+
const init = { method: 'POST' };
|
|
438
|
+
const response = await this.serverConnection.makeRequest(url, init, settings);
|
|
439
|
+
if (response.status !== 204) {
|
|
440
|
+
const err = await createResponseError(response);
|
|
441
|
+
throw err;
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
/**
|
|
446
|
+
* Delete a checkpoint for a file.
|
|
447
|
+
*
|
|
448
|
+
* @param localPath - The path of the file.
|
|
449
|
+
*
|
|
450
|
+
* @param checkpointID - The id of the checkpoint to delete.
|
|
451
|
+
*
|
|
452
|
+
* @returns A promise which resolves when the checkpoint is deleted.
|
|
453
|
+
*
|
|
454
|
+
* #### Notes
|
|
455
|
+
* Uses the [Jupyter Notebook API](http://petstore.swagger.io/?url=https://raw.githubusercontent.com/jupyter/notebook/master/notebook/services/api/api.yaml#!/contents).
|
|
456
|
+
*/
|
|
457
|
+
async deleteCheckpoint(
|
|
458
|
+
localPath: string,
|
|
459
|
+
checkpointID: string,
|
|
460
|
+
options?: IContentsRequestOptions,
|
|
461
|
+
): Promise<void> {
|
|
462
|
+
const url = this.getUrl(options?.baseUrl, localPath, 'checkpoints', checkpointID);
|
|
463
|
+
const init = { method: 'DELETE' };
|
|
464
|
+
const settings = this._getSettings(options?.baseUrl);
|
|
465
|
+
const response = await this.serverConnection.makeRequest(url, init, settings);
|
|
466
|
+
if (response.status !== 204) {
|
|
467
|
+
const err = await createResponseError(response);
|
|
468
|
+
throw err;
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
/**
|
|
473
|
+
* Get a REST url for a file given a path.
|
|
474
|
+
*/
|
|
475
|
+
protected getUrl(base?: string, ...args: string[]): string {
|
|
476
|
+
let baseUrl = base;
|
|
477
|
+
if (!baseUrl) {
|
|
478
|
+
baseUrl = this.serverConnection.settings.baseUrl;
|
|
479
|
+
}
|
|
480
|
+
const parts = args.map((path) => URLUtil.encodeParts(path));
|
|
481
|
+
return URLUtil.join(baseUrl!, this.apiEndpoint, ...parts);
|
|
482
|
+
}
|
|
483
|
+
|
|
484
|
+
protected _getSettings(baseUrl?: string): ISettings {
|
|
485
|
+
const settings = this.serverConnection.settings;
|
|
486
|
+
if (baseUrl) {
|
|
487
|
+
return { ...settings, baseUrl };
|
|
488
|
+
}
|
|
489
|
+
return settings;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
protected apiEndpoint: string;
|
|
493
|
+
protected _isDisposed = false;
|
|
494
|
+
protected fileChangedEmitter = new Emitter<IContentsChangedArgs>();
|
|
495
|
+
}
|