@fails-components/jupyter-launcher 0.0.1-alpha.9 → 0.0.3

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/lib/index.d.ts CHANGED
@@ -1,59 +1,13 @@
1
1
  import { JupyterFrontEndPlugin } from '@jupyterlab/application';
2
- import { JSONObject, PartialJSONObject, Token } from '@lumino/coreutils';
3
- import { ISignal } from '@lumino/signaling';
2
+ import { JSONObject } from '@lumino/coreutils';
3
+ import { IFailsAppletSize } from './tokens';
4
+ export * from './tokens';
4
5
  export interface IScreenShotOpts {
5
6
  dpi: number;
6
7
  }
7
8
  export interface IAppletScreenshottaker {
8
9
  takeAppScreenshot: (opts: IScreenShotOpts) => Promise<Blob | undefined>;
9
10
  }
10
- interface IContentEvent {
11
- task: string;
12
- }
13
- export interface ILoadJupyterContentEvent extends IContentEvent {
14
- task: 'loadFile';
15
- fileData: object | undefined;
16
- fileName: string;
17
- }
18
- export interface ISavedJupyterContentEvent extends IContentEvent {
19
- task: 'savedFile';
20
- fileName: string;
21
- }
22
- export type IContentEventType = ILoadJupyterContentEvent | ISavedJupyterContentEvent;
23
- export interface IFailsCallbacks {
24
- callContents?: (event: IContentEventType) => Promise<any>;
25
- postMessageToFails?: (message: any, transfer?: Transferable[]) => void;
26
- }
27
- export declare const IFailsLauncherInfo: Token<IFailsLauncherInfo>;
28
- export interface IFailsLauncherInit {
29
- inLecture: boolean;
30
- selectedAppid: string | undefined;
31
- reportMetadata?: (metadata: PartialJSONObject) => void;
32
- }
33
- export interface IFailsAppletSize {
34
- appid: string;
35
- width: number;
36
- height: number;
37
- }
38
- export interface IAppletWidgetRegistry {
39
- }
40
- export interface IFailsInterceptorUpdateMessage {
41
- path: string;
42
- mime: string;
43
- state: JSONObject;
44
- }
45
- export interface IFailsLauncherInfo extends IFailsLauncherInit {
46
- inLectureChanged: ISignal<IFailsLauncherInfo, boolean>;
47
- selectedAppidChanged: ISignal<this, string | undefined>;
48
- appletSizes: {
49
- [key: string]: IFailsAppletSize;
50
- };
51
- appletSizesChanged: ISignal<this, {
52
- [key: string]: IFailsAppletSize;
53
- }>;
54
- updateMessageArrived?: ISignal<IAppletWidgetRegistry, IFailsInterceptorUpdateMessage>;
55
- remoteUpdateMessageArrived: ISignal<IFailsLauncherInfo, IFailsInterceptorUpdateMessage>;
56
- }
57
11
  export interface IReplyJupyter {
58
12
  requestId?: number;
59
13
  }
package/lib/index.js CHANGED
@@ -1,12 +1,12 @@
1
1
  import { ILabStatus } from '@jupyterlab/application';
2
2
  import { IDocumentManager } from '@jupyterlab/docmanager';
3
- import { ServerConnection } from '@jupyterlab/services';
4
- import { PageConfig, URLExt } from '@jupyterlab/coreutils';
3
+ import { ILicensesClient } from '@jupyterlab/apputils';
5
4
  import { INotebookShell } from '@jupyter-notebook/application';
6
5
  import { NotebookActions } from '@jupyterlab/notebook';
7
- import { Token } from '@lumino/coreutils';
8
6
  import { Signal } from '@lumino/signaling';
9
- export const IFailsLauncherInfo = new Token('@fails-components/jupyter-fails:IFailsLauncherInfo', 'A service to communicate with FAILS.');
7
+ import { IFailsDriveMessages } from '@fails-components/jupyter-filesystem-extension';
8
+ import { IFailsLauncherInfo } from './tokens';
9
+ export * from './tokens';
10
10
  let screenShotPatchInstalled = false;
11
11
  const installScreenShotPatches = () => {
12
12
  if (screenShotPatchInstalled) {
@@ -80,6 +80,20 @@ const installFetchPatches = ({ allowedSites = undefined, proxySites = undefined,
80
80
  headers: { 'Content-Type': 'text/plain' }
81
81
  });
82
82
  };
83
+ const oldImportScripts = globalThis.importScripts;
84
+ globalThis.importScripts = (...args) => {
85
+ const newargs = args.map(url => {
86
+ const urlObj = new URL(url, location.href);
87
+ if (allowedOrigins.includes(urlObj.origin)) {
88
+ return url;
89
+ }
90
+ if (proxySites && proxySites.includes(urlObj.origin)) {
91
+ return proxyURL + urlObj.hostname + urlObj.pathname;
92
+ }
93
+ throw new Error('Script is from blocked URL');
94
+ });
95
+ return oldImportScripts(...newargs);
96
+ };
83
97
  const oldWorker = Worker;
84
98
  const NewWorker = function (script, options) {
85
99
  const scriptURL = script instanceof URL ? script : new URL(script, location.href);
@@ -132,6 +146,20 @@ const installFetchPatches = ({ allowedSites = undefined, proxySites = undefined,
132
146
  headers: { 'Content-Type': 'text/plain' }
133
147
  });
134
148
  };
149
+ const oldImportScripts = globalThis.importScripts;
150
+ globalThis.importScripts = (...args) => {
151
+ const newargs = args.map(url => {
152
+ const urlObj = new URL(url, location.href);
153
+ if (allowedOrigins.includes(urlObj.origin)) {
154
+ return url;
155
+ }
156
+ if (proxySites && proxySites.includes(urlObj.origin)) {
157
+ return proxyURL + urlObj.hostname + urlObj.pathname;
158
+ }
159
+ throw new Error('Script is from blocked URL');
160
+ });
161
+ return oldImportScripts(...newargs);
162
+ };
135
163
  Object.defineProperty(globalThis, 'location', {
136
164
  value: new URL('${scriptURL.href}'),
137
165
  writable: false,
@@ -246,9 +274,10 @@ class FailsLauncherInfo {
246
274
  this._remoteUpdateMessageArrived.emit(message);
247
275
  }
248
276
  }
249
- function activateFailsLauncher(app, docManager, status, shell) {
277
+ function activateFailsLauncher(app, docManager, status, licenseClient, driveMessages, shell) {
250
278
  // parts taken from repl-extension
251
279
  const { /* commands, */ serviceManager, started } = app;
280
+ const sendMessageToDrive = driveMessages.sendMessage;
252
281
  Promise.all([started, serviceManager.ready]).then(async () => {
253
282
  /* commands.execute('notebook:create-new', {
254
283
  kernelId: undefined,
@@ -260,28 +289,20 @@ function activateFailsLauncher(app, docManager, status, shell) {
260
289
  const { docRegistry } = app;
261
290
  const failsLauncherInfo = new FailsLauncherInfo();
262
291
  let currentDocWidget;
263
- const serverSettings = app.serviceManager.serverSettings;
264
- const licensesUrl = URLExt.join(PageConfig.getBaseUrl(), PageConfig.getOption('licensesUrl')) +
265
- '/';
266
- // Install Messagehandler
267
- if (!window.failsCallbacks) {
268
- window.failsCallbacks = {};
269
- }
270
292
  let senderOrigin;
271
- const _failsCallbacks = window.failsCallbacks;
272
- _failsCallbacks.postMessageToFails = (message, transfer) => {
293
+ const postMessageToFails = (message, transfer) => {
273
294
  if (typeof senderOrigin !== 'undefined') {
274
295
  window.parent.postMessage(message, senderOrigin, transfer);
275
296
  }
276
297
  };
277
298
  status.dirtySignal.connect((sender, dirty) => {
278
- _failsCallbacks.postMessageToFails({
299
+ postMessageToFails({
279
300
  task: 'docDirty',
280
301
  dirty
281
302
  });
282
303
  });
283
304
  failsLauncherInfo.reportMetadata = metadata => {
284
- _failsCallbacks.postMessageToFails({
305
+ postMessageToFails({
285
306
  task: 'reportMetadata',
286
307
  metadata
287
308
  });
@@ -292,14 +313,14 @@ function activateFailsLauncher(app, docManager, status, shell) {
292
313
  }
293
314
  });
294
315
  failsLauncherInfo.appletSizesChanged.connect((sender, appletSizes) => {
295
- _failsCallbacks.postMessageToFails({
316
+ postMessageToFails({
296
317
  task: 'reportFailsAppletSizes',
297
318
  appletSizes
298
319
  });
299
320
  });
300
321
  let interceptorActivated = false;
301
322
  const sendInterceptorUpdate = (sender, message) => {
302
- _failsCallbacks.postMessageToFails({
323
+ postMessageToFails({
303
324
  task: 'sendInterceptorUpdate',
304
325
  ...message
305
326
  });
@@ -328,7 +349,7 @@ function activateFailsLauncher(app, docManager, status, shell) {
328
349
  // may be use a promise for fullfillment, e.g. pass a resolve
329
350
  // afterwards we load the file or new file into to the contexts
330
351
  // we may also send license information
331
- _failsCallbacks.callContents({
352
+ sendMessageToDrive({
332
353
  task: 'loadFile',
333
354
  fileData: loadJupyterInfo.fileData,
334
355
  fileName: loadJupyterInfo.fileName
@@ -350,7 +371,7 @@ function activateFailsLauncher(app, docManager, status, shell) {
350
371
  if (typeof currentDocWidget !== 'undefined') {
351
372
  const notebookPanel = currentDocWidget;
352
373
  notebookPanel.sessionContext.statusChanged.connect((context, status) => {
353
- _failsCallbacks.postMessageToFails({
374
+ postMessageToFails({
354
375
  task: 'reportKernelStatus',
355
376
  status
356
377
  });
@@ -370,7 +391,7 @@ function activateFailsLauncher(app, docManager, status, shell) {
370
391
  });
371
392
  }
372
393
  })
373
- .catch(error => {
394
+ .catch((error) => {
374
395
  console.log('Problem task load file', error);
375
396
  });
376
397
  }
@@ -379,7 +400,7 @@ function activateFailsLauncher(app, docManager, status, shell) {
379
400
  {
380
401
  const saveJupyter = event.data;
381
402
  if (typeof currentDocWidget === 'undefined') {
382
- _failsCallbacks.postMessageToFails({
403
+ postMessageToFails({
383
404
  requestId: event.data.requestId,
384
405
  task: 'saveJupyter',
385
406
  error: 'No document loaded'
@@ -388,7 +409,7 @@ function activateFailsLauncher(app, docManager, status, shell) {
388
409
  }
389
410
  const context = docManager.contextForWidget(currentDocWidget);
390
411
  if (typeof context === 'undefined') {
391
- _failsCallbacks.postMessageToFails({
412
+ postMessageToFails({
392
413
  requestId: event.data.requestId,
393
414
  task: 'saveJupyter',
394
415
  error: 'No document context'
@@ -397,22 +418,22 @@ function activateFailsLauncher(app, docManager, status, shell) {
397
418
  }
398
419
  context
399
420
  .save()
400
- .then(() => {
421
+ .then(async () => {
401
422
  // ok it was save to our virtual disk
402
- return _failsCallbacks.callContents({
423
+ return await sendMessageToDrive({
403
424
  task: 'savedFile',
404
425
  fileName: saveJupyter.fileName
405
426
  });
406
427
  })
407
428
  .then(({ fileData }) => {
408
- _failsCallbacks.postMessageToFails({
429
+ postMessageToFails({
409
430
  requestId: event.data.requestId,
410
431
  task: 'saveJupyter',
411
432
  fileData
412
433
  });
413
434
  })
414
435
  .catch((error) => {
415
- _failsCallbacks.postMessageToFails({
436
+ postMessageToFails({
416
437
  requestId: event.data.requestId,
417
438
  task: 'saveJupyter',
418
439
  error: error.toString()
@@ -429,7 +450,7 @@ function activateFailsLauncher(app, docManager, status, shell) {
429
450
  else {
430
451
  failsLauncherInfo.inLecture = false;
431
452
  }
432
- _failsCallbacks.postMessageToFails({
453
+ postMessageToFails({
433
454
  requestId: event.data.requestId,
434
455
  task: 'activateApp'
435
456
  });
@@ -440,7 +461,7 @@ function activateFailsLauncher(app, docManager, status, shell) {
440
461
  const screenshotApp = event.data;
441
462
  const notebookPanel = currentDocWidget;
442
463
  if (!(typeof notebookPanel['takeAppScreenshot'] === 'function')) {
443
- _failsCallbacks.postMessageToFails({
464
+ postMessageToFails({
444
465
  requestId: event.data.requestId,
445
466
  task: 'screenshotApp',
446
467
  error: 'Take App Screenshot unsupported'
@@ -450,17 +471,16 @@ function activateFailsLauncher(app, docManager, status, shell) {
450
471
  screenShotTaker
451
472
  .takeAppScreenshot({ dpi: screenshotApp.dpi })
452
473
  .then(async (screenshot) => {
453
- var _a, _b;
454
474
  if (screenshot) {
455
475
  const data = await screenshot.arrayBuffer();
456
- (_a = _failsCallbacks.postMessageToFails) === null || _a === void 0 ? void 0 : _a.call(_failsCallbacks, {
476
+ postMessageToFails === null || postMessageToFails === void 0 ? void 0 : postMessageToFails({
457
477
  requestId: event.data.requestId,
458
478
  task: 'screenshotApp',
459
479
  screenshot: { data, type: screenshot.type }
460
480
  }, [data]); // TODO add transferable
461
481
  }
462
482
  else {
463
- (_b = _failsCallbacks.postMessageToFails) === null || _b === void 0 ? void 0 : _b.call(_failsCallbacks, {
483
+ postMessageToFails === null || postMessageToFails === void 0 ? void 0 : postMessageToFails({
464
484
  requestId: event.data.requestId,
465
485
  task: 'screenshotApp',
466
486
  error: 'Screenshot failed?'
@@ -469,7 +489,7 @@ function activateFailsLauncher(app, docManager, status, shell) {
469
489
  })
470
490
  .catch((error) => {
471
491
  console.log('Screenshot error', error);
472
- _failsCallbacks.postMessageToFails({
492
+ postMessageToFails({
473
493
  requestId: event.data.requestId,
474
494
  task: 'screenshotApp',
475
495
  error: error.toString()
@@ -491,7 +511,7 @@ function activateFailsLauncher(app, docManager, status, shell) {
491
511
  interceptorActivated = false;
492
512
  }
493
513
  }
494
- _failsCallbacks.postMessageToFails({
514
+ postMessageToFails({
495
515
  requestId: event.data.requestId,
496
516
  task: 'activateInterceptor'
497
517
  });
@@ -503,7 +523,7 @@ function activateFailsLauncher(app, docManager, status, shell) {
503
523
  const { path, mime, state } = receiveInterceptorUpdate;
504
524
  const launcherInfo = failsLauncherInfo;
505
525
  launcherInfo.receiveRemoteUpdateMessage({ path, mime, state });
506
- _failsCallbacks.postMessageToFails({
526
+ postMessageToFails({
507
527
  requestId: event.data.requestId,
508
528
  task: 'receiveInterceptorUpdate'
509
529
  });
@@ -512,7 +532,7 @@ function activateFailsLauncher(app, docManager, status, shell) {
512
532
  case 'restartKernelAndRerunCells':
513
533
  {
514
534
  if (typeof currentDocWidget === 'undefined') {
515
- _failsCallbacks.postMessageToFails({
535
+ postMessageToFails({
516
536
  requestId: event.data.requestId,
517
537
  task: 'restartKernelAndRerunCell',
518
538
  error: 'No document loaded'
@@ -527,14 +547,14 @@ function activateFailsLauncher(app, docManager, status, shell) {
527
547
  .restartKernel()
528
548
  .then(async () => {
529
549
  await NotebookActions.runCells(content, cells, context.sessionContext);
530
- _failsCallbacks.postMessageToFails({
550
+ postMessageToFails({
531
551
  requestId: event.data.requestId,
532
552
  task: 'restartKernelAndRerunCell',
533
553
  success: true
534
554
  });
535
555
  })
536
556
  .catch((error) => {
537
- _failsCallbacks.postMessageToFails({
557
+ postMessageToFails({
538
558
  requestId: event.data.requestId,
539
559
  task: 'restartKernelAndRerunCell',
540
560
  error: error.toString()
@@ -544,17 +564,18 @@ function activateFailsLauncher(app, docManager, status, shell) {
544
564
  break;
545
565
  case 'getLicenses':
546
566
  {
547
- ServerConnection.makeRequest(licensesUrl, {}, serverSettings)
548
- .then(async (response) => {
549
- const json = await response.json();
550
- _failsCallbacks.postMessageToFails({
567
+ // broken
568
+ licenseClient
569
+ .getBundles()
570
+ .then(async (licenses) => {
571
+ postMessageToFails({
551
572
  requestId: event.data.requestId,
552
573
  task: 'getLicenses',
553
- licenses: json
574
+ licenses
554
575
  });
555
576
  })
556
577
  .catch(error => {
557
- _failsCallbacks.postMessageToFails({
578
+ postMessageToFails({
558
579
  requestId: event.data.requestId,
559
580
  task: 'getLicenses',
560
581
  error: error.toString()
@@ -585,12 +606,17 @@ function activateFailsLauncher(app, docManager, status, shell) {
585
606
  return failsLauncherInfo;
586
607
  }
587
608
  const failsLauncher = {
588
- id: '@fails-components/jupyter-fails:launcher',
609
+ id: '@fails-components/jupyter-applet-widget:launcher',
589
610
  description: 'Configures the notebooks application over messages',
590
611
  autoStart: true,
591
612
  activate: activateFailsLauncher,
592
613
  provides: IFailsLauncherInfo,
593
- requires: [IDocumentManager, ILabStatus],
614
+ requires: [
615
+ IDocumentManager,
616
+ ILabStatus,
617
+ ILicensesClient,
618
+ IFailsDriveMessages
619
+ ],
594
620
  optional: [INotebookShell]
595
621
  };
596
622
  /**
@@ -0,0 +1,33 @@
1
+ import { Token } from '@lumino/coreutils';
2
+ import { ISignal } from '@lumino/signaling';
3
+ import { JSONObject, PartialJSONObject } from '@lumino/coreutils';
4
+ export interface IAppletWidgetRegistry {
5
+ }
6
+ export interface IFailsAppletSize {
7
+ appid: string;
8
+ width: number;
9
+ height: number;
10
+ }
11
+ export interface IFailsLauncherInit {
12
+ inLecture: boolean;
13
+ selectedAppid: string | undefined;
14
+ reportMetadata?: (metadata: PartialJSONObject) => void;
15
+ }
16
+ export interface IFailsInterceptorUpdateMessage {
17
+ path: string;
18
+ mime: string;
19
+ state: JSONObject;
20
+ }
21
+ export interface IFailsLauncherInfo extends IFailsLauncherInit {
22
+ inLectureChanged: ISignal<IFailsLauncherInfo, boolean>;
23
+ selectedAppidChanged: ISignal<this, string | undefined>;
24
+ appletSizes: {
25
+ [key: string]: IFailsAppletSize;
26
+ };
27
+ appletSizesChanged: ISignal<this, {
28
+ [key: string]: IFailsAppletSize;
29
+ }>;
30
+ updateMessageArrived?: ISignal<IAppletWidgetRegistry, IFailsInterceptorUpdateMessage>;
31
+ remoteUpdateMessageArrived: ISignal<IFailsLauncherInfo, IFailsInterceptorUpdateMessage>;
32
+ }
33
+ export declare const IFailsLauncherInfo: Token<IFailsLauncherInfo>;
package/lib/tokens.js ADDED
@@ -0,0 +1,2 @@
1
+ import { Token } from '@lumino/coreutils';
2
+ export const IFailsLauncherInfo = new Token('@fails-components/jupyter-fails:IFailsLauncherInfo', 'A service to communicate with FAILS.');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fails-components/jupyter-launcher",
3
- "version": "0.0.1-alpha.9",
3
+ "version": "0.0.3",
4
4
  "description": "A collections of plugins steering an iframe with jupyter remotely",
5
5
  "keywords": [
6
6
  "jupyter",
@@ -60,21 +60,19 @@
60
60
  "watch:labextension": "jupyter labextension watch ."
61
61
  },
62
62
  "dependencies": {
63
- "@jupyter-notebook/application": "^7.2.0",
64
- "@jupyter-widgets/jupyterlab-manager": "^5.0.11",
65
- "@jupyterlab/application": "^4.3.4",
66
- "@jupyterlab/apputils": "^4.3.4",
67
- "@jupyterlab/coreutils": "^6.3.4",
68
- "@jupyterlab/docmanager": "^4.3.4",
69
- "@jupyterlab/docregistry": "^4.3.4",
70
- "@jupyterlab/notebook": "^4.3.4",
71
- "@jupyterlite/application-extension": "^0.4.4",
72
- "@jupyterlite/contents": "^0.4.4",
73
- "@jupyterlite/server": "^0.4.4",
74
- "@jupyterlite/settings": "^0.4.4",
75
- "@lumino/coreutils": "^2.2.0",
76
- "@lumino/signaling": "^2.1.2",
77
- "@lumino/widgets": "^2.3.2",
63
+ "@fails-components/jupyter-filesystem-extension": "^0.0.3",
64
+ "@jupyter-notebook/application": "^7.4.3",
65
+ "@jupyterlab/application": "^4.4.3",
66
+ "@jupyterlab/apputils": "^4.5.3",
67
+ "@jupyterlab/docmanager": "^4.4.3",
68
+ "@jupyterlab/docregistry": "^4.4.3",
69
+ "@jupyterlab/notebook": "^4.4.3",
70
+ "@jupyterlab/services": "^7.4.3",
71
+ "@jupyterlite/application-extension": "^0.6.1",
72
+ "@jupyterlite/server": "^0.6.1",
73
+ "@lumino/coreutils": "^2.2.1",
74
+ "@lumino/signaling": "^2.1.4",
75
+ "@lumino/widgets": "^2.7.1",
78
76
  "json5": "^2.2.3"
79
77
  },
80
78
  "devDependencies": {
@@ -115,7 +113,14 @@
115
113
  "jupyterlab": {
116
114
  "extension": true,
117
115
  "outputDir": "fails_components_jupyter_launcher/labextension",
118
- "schemaDir": "schema"
116
+ "schemaDir": "schema",
117
+ "sharedPackages": {
118
+ "@fails-components/jupyter-filesystem-extension": {
119
+ "singleton": true,
120
+ "requiredVersion": "^0.0.1-alpha.18",
121
+ "import": false
122
+ }
123
+ }
119
124
  },
120
125
  "eslintIgnore": [
121
126
  "node_modules",
package/src/index.ts CHANGED
@@ -4,15 +4,23 @@ import {
4
4
  JupyterFrontEndPlugin
5
5
  } from '@jupyterlab/application';
6
6
  import { IDocumentManager } from '@jupyterlab/docmanager';
7
- import { ServerConnection, Kernel } from '@jupyterlab/services';
8
- import { PageConfig, URLExt } from '@jupyterlab/coreutils';
9
- import { ISessionContext } from '@jupyterlab/apputils';
7
+ import { Kernel } from '@jupyterlab/services';
8
+ import { ISessionContext, ILicensesClient } from '@jupyterlab/apputils';
10
9
  import { IDocumentWidget } from '@jupyterlab/docregistry';
11
10
  import { INotebookShell } from '@jupyter-notebook/application';
12
11
  import { NotebookActions, NotebookPanel } from '@jupyterlab/notebook';
13
- import { JSONObject, PartialJSONObject, Token } from '@lumino/coreutils';
12
+ import { JSONObject } from '@lumino/coreutils';
14
13
  import { ISignal, Signal } from '@lumino/signaling';
15
14
  import { Panel } from '@lumino/widgets';
15
+ import { IFailsDriveMessages } from '@fails-components/jupyter-filesystem-extension';
16
+ import {
17
+ IFailsLauncherInfo,
18
+ IFailsAppletSize,
19
+ IAppletWidgetRegistry,
20
+ IFailsInterceptorUpdateMessage
21
+ } from './tokens';
22
+
23
+ export * from './tokens';
16
24
 
17
25
  export interface IScreenShotOpts {
18
26
  dpi: number;
@@ -22,70 +30,6 @@ export interface IAppletScreenshottaker {
22
30
  takeAppScreenshot: (opts: IScreenShotOpts) => Promise<Blob | undefined>;
23
31
  }
24
32
 
25
- interface IContentEvent {
26
- task: string;
27
- }
28
-
29
- export interface ILoadJupyterContentEvent extends IContentEvent {
30
- task: 'loadFile';
31
- fileData: object | undefined;
32
- fileName: string;
33
- }
34
-
35
- export interface ISavedJupyterContentEvent extends IContentEvent {
36
- task: 'savedFile';
37
- fileName: string;
38
- }
39
-
40
- export type IContentEventType =
41
- | ILoadJupyterContentEvent
42
- | ISavedJupyterContentEvent; // use union
43
-
44
- export interface IFailsCallbacks {
45
- callContents?: (event: IContentEventType) => Promise<any>;
46
- postMessageToFails?: (message: any, transfer?: Transferable[]) => void;
47
- }
48
-
49
- export const IFailsLauncherInfo = new Token<IFailsLauncherInfo>(
50
- '@fails-components/jupyter-fails:IFailsLauncherInfo',
51
- 'A service to communicate with FAILS.'
52
- );
53
-
54
- export interface IFailsLauncherInit {
55
- inLecture: boolean;
56
- selectedAppid: string | undefined;
57
- reportMetadata?: (metadata: PartialJSONObject) => void;
58
- }
59
-
60
- export interface IFailsAppletSize {
61
- appid: string;
62
- width: number;
63
- height: number;
64
- }
65
-
66
- export interface IAppletWidgetRegistry {}
67
-
68
- export interface IFailsInterceptorUpdateMessage {
69
- path: string;
70
- mime: string;
71
- state: JSONObject;
72
- }
73
-
74
- export interface IFailsLauncherInfo extends IFailsLauncherInit {
75
- inLectureChanged: ISignal<IFailsLauncherInfo, boolean>;
76
- selectedAppidChanged: ISignal<this, string | undefined>;
77
- appletSizes: { [key: string]: IFailsAppletSize };
78
- appletSizesChanged: ISignal<this, { [key: string]: IFailsAppletSize }>;
79
- updateMessageArrived?: ISignal<
80
- IAppletWidgetRegistry,
81
- IFailsInterceptorUpdateMessage
82
- >;
83
- remoteUpdateMessageArrived: ISignal<
84
- IFailsLauncherInfo,
85
- IFailsInterceptorUpdateMessage
86
- >;
87
- }
88
-
89
33
  export interface IReplyJupyter {
90
34
  requestId?: number;
91
35
  }
@@ -283,6 +227,20 @@ const installFetchPatches = ({
283
227
  headers: { 'Content-Type': 'text/plain' }
284
228
  });
285
229
  };
230
+ const oldImportScripts = globalThis.importScripts;
231
+ globalThis.importScripts = (...args) => {
232
+ const newargs = args.map(url => {
233
+ const urlObj = new URL(url, location.href);
234
+ if (allowedOrigins.includes(urlObj.origin)) {
235
+ return url;
236
+ }
237
+ if (proxySites && proxySites.includes(urlObj.origin)) {
238
+ return proxyURL + urlObj.hostname + urlObj.pathname;
239
+ }
240
+ throw new Error('Script is from blocked URL');
241
+ });
242
+ return oldImportScripts(...newargs);
243
+ };
286
244
  const oldWorker = Worker;
287
245
  const NewWorker = function (
288
246
  script: string | URL,
@@ -339,6 +297,20 @@ const installFetchPatches = ({
339
297
  headers: { 'Content-Type': 'text/plain' }
340
298
  });
341
299
  };
300
+ const oldImportScripts = globalThis.importScripts;
301
+ globalThis.importScripts = (...args) => {
302
+ const newargs = args.map(url => {
303
+ const urlObj = new URL(url, location.href);
304
+ if (allowedOrigins.includes(urlObj.origin)) {
305
+ return url;
306
+ }
307
+ if (proxySites && proxySites.includes(urlObj.origin)) {
308
+ return proxyURL + urlObj.hostname + urlObj.pathname;
309
+ }
310
+ throw new Error('Script is from blocked URL');
311
+ });
312
+ return oldImportScripts(...newargs);
313
+ };
342
314
  Object.defineProperty(globalThis, 'location', {
343
315
  value: new URL('${scriptURL.href}'),
344
316
  writable: false,
@@ -496,10 +468,13 @@ function activateFailsLauncher(
496
468
  app: JupyterFrontEnd,
497
469
  docManager: IDocumentManager,
498
470
  status: ILabStatus,
471
+ licenseClient: ILicensesClient,
472
+ driveMessages: IFailsDriveMessages,
499
473
  shell: INotebookShell | null
500
474
  ): IFailsLauncherInfo {
501
475
  // parts taken from repl-extension
502
476
  const { /* commands, */ serviceManager, started } = app;
477
+ const sendMessageToDrive = driveMessages.sendMessage;
503
478
  Promise.all([started, serviceManager.ready]).then(async () => {
504
479
  /* commands.execute('notebook:create-new', {
505
480
  kernelId: undefined,
@@ -512,33 +487,20 @@ function activateFailsLauncher(
512
487
  const failsLauncherInfo: IFailsLauncherInfo = new FailsLauncherInfo();
513
488
  let currentDocWidget: IDocumentWidget | undefined;
514
489
 
515
- const serverSettings = app.serviceManager.serverSettings;
516
- const licensesUrl =
517
- URLExt.join(PageConfig.getBaseUrl(), PageConfig.getOption('licensesUrl')) +
518
- '/';
519
-
520
- // Install Messagehandler
521
- if (!(window as any).failsCallbacks) {
522
- (window as any).failsCallbacks = {};
523
- }
524
490
  let senderOrigin: string | undefined;
525
- const _failsCallbacks = (window as any).failsCallbacks as IFailsCallbacks;
526
- _failsCallbacks.postMessageToFails = (
527
- message: any,
528
- transfer?: Transferable[]
529
- ) => {
491
+ const postMessageToFails = (message: any, transfer?: Transferable[]) => {
530
492
  if (typeof senderOrigin !== 'undefined') {
531
493
  window.parent.postMessage(message, senderOrigin, transfer);
532
494
  }
533
495
  };
534
496
  status.dirtySignal.connect((sender, dirty) => {
535
- _failsCallbacks.postMessageToFails!({
497
+ postMessageToFails!({
536
498
  task: 'docDirty',
537
499
  dirty
538
500
  });
539
501
  });
540
502
  failsLauncherInfo.reportMetadata = metadata => {
541
- _failsCallbacks.postMessageToFails!({
503
+ postMessageToFails!({
542
504
  task: 'reportMetadata',
543
505
  metadata
544
506
  });
@@ -555,7 +517,7 @@ function activateFailsLauncher(
555
517
  sender: IFailsLauncherInfo,
556
518
  appletSizes: { [key: string]: IFailsAppletSize }
557
519
  ) => {
558
- _failsCallbacks.postMessageToFails!({
520
+ postMessageToFails!({
559
521
  task: 'reportFailsAppletSizes',
560
522
  appletSizes
561
523
  });
@@ -566,7 +528,7 @@ function activateFailsLauncher(
566
528
  sender: IAppletWidgetRegistry,
567
529
  message: IFailsInterceptorUpdateMessage
568
530
  ): void => {
569
- _failsCallbacks.postMessageToFails!({
531
+ postMessageToFails!({
570
532
  task: 'sendInterceptorUpdate',
571
533
  ...message
572
534
  });
@@ -595,7 +557,7 @@ function activateFailsLauncher(
595
557
  // may be use a promise for fullfillment, e.g. pass a resolve
596
558
  // afterwards we load the file or new file into to the contexts
597
559
  // we may also send license information
598
- _failsCallbacks.callContents!({
560
+ sendMessageToDrive({
599
561
  task: 'loadFile',
600
562
  fileData: loadJupyterInfo.fileData,
601
563
  fileName: loadJupyterInfo.fileName
@@ -625,7 +587,7 @@ function activateFailsLauncher(
625
587
  const notebookPanel = currentDocWidget as NotebookPanel;
626
588
  notebookPanel.sessionContext.statusChanged.connect(
627
589
  (context: ISessionContext, status: Kernel.Status) => {
628
- _failsCallbacks.postMessageToFails!({
590
+ postMessageToFails!({
629
591
  task: 'reportKernelStatus',
630
592
  status
631
593
  });
@@ -654,7 +616,7 @@ function activateFailsLauncher(
654
616
  );
655
617
  }
656
618
  })
657
- .catch(error => {
619
+ .catch((error: any) => {
658
620
  console.log('Problem task load file', error);
659
621
  });
660
622
  }
@@ -663,7 +625,7 @@ function activateFailsLauncher(
663
625
  {
664
626
  const saveJupyter = event.data as ISaveJupyter;
665
627
  if (typeof currentDocWidget === 'undefined') {
666
- _failsCallbacks.postMessageToFails!({
628
+ postMessageToFails!({
667
629
  requestId: event.data.requestId,
668
630
  task: 'saveJupyter',
669
631
  error: 'No document loaded'
@@ -672,7 +634,7 @@ function activateFailsLauncher(
672
634
  }
673
635
  const context = docManager.contextForWidget(currentDocWidget);
674
636
  if (typeof context === 'undefined') {
675
- _failsCallbacks.postMessageToFails!({
637
+ postMessageToFails!({
676
638
  requestId: event.data.requestId,
677
639
  task: 'saveJupyter',
678
640
  error: 'No document context'
@@ -681,22 +643,22 @@ function activateFailsLauncher(
681
643
  }
682
644
  context
683
645
  .save()
684
- .then(() => {
646
+ .then(async () => {
685
647
  // ok it was save to our virtual disk
686
- return _failsCallbacks.callContents!({
648
+ return await sendMessageToDrive({
687
649
  task: 'savedFile',
688
650
  fileName: saveJupyter.fileName
689
651
  });
690
652
  })
691
653
  .then(({ fileData }) => {
692
- _failsCallbacks.postMessageToFails!({
654
+ postMessageToFails!({
693
655
  requestId: event.data.requestId,
694
656
  task: 'saveJupyter',
695
657
  fileData
696
658
  });
697
659
  })
698
660
  .catch((error: Error) => {
699
- _failsCallbacks.postMessageToFails!({
661
+ postMessageToFails!({
700
662
  requestId: event.data.requestId,
701
663
  task: 'saveJupyter',
702
664
  error: error.toString()
@@ -712,7 +674,7 @@ function activateFailsLauncher(
712
674
  } else {
713
675
  failsLauncherInfo.inLecture = false;
714
676
  }
715
- _failsCallbacks.postMessageToFails!({
677
+ postMessageToFails!({
716
678
  requestId: event.data.requestId,
717
679
  task: 'activateApp'
718
680
  });
@@ -725,7 +687,7 @@ function activateFailsLauncher(
725
687
  if (
726
688
  !(typeof (notebookPanel as any)['takeAppScreenshot'] === 'function')
727
689
  ) {
728
- _failsCallbacks.postMessageToFails!({
690
+ postMessageToFails!({
729
691
  requestId: event.data.requestId,
730
692
  task: 'screenshotApp',
731
693
  error: 'Take App Screenshot unsupported'
@@ -738,7 +700,7 @@ function activateFailsLauncher(
738
700
  .then(async screenshot => {
739
701
  if (screenshot) {
740
702
  const data = await screenshot.arrayBuffer();
741
- _failsCallbacks.postMessageToFails?.(
703
+ postMessageToFails?.(
742
704
  {
743
705
  requestId: event.data.requestId,
744
706
  task: 'screenshotApp',
@@ -747,7 +709,7 @@ function activateFailsLauncher(
747
709
  [data]
748
710
  ); // TODO add transferable
749
711
  } else {
750
- _failsCallbacks.postMessageToFails?.({
712
+ postMessageToFails?.({
751
713
  requestId: event.data.requestId,
752
714
  task: 'screenshotApp',
753
715
  error: 'Screenshot failed?'
@@ -756,7 +718,7 @@ function activateFailsLauncher(
756
718
  })
757
719
  .catch((error: Error) => {
758
720
  console.log('Screenshot error', error);
759
- _failsCallbacks.postMessageToFails!({
721
+ postMessageToFails!({
760
722
  requestId: event.data.requestId,
761
723
  task: 'screenshotApp',
762
724
  error: error.toString()
@@ -783,7 +745,7 @@ function activateFailsLauncher(
783
745
  interceptorActivated = false;
784
746
  }
785
747
  }
786
- _failsCallbacks.postMessageToFails!({
748
+ postMessageToFails!({
787
749
  requestId: event.data.requestId,
788
750
  task: 'activateInterceptor'
789
751
  });
@@ -796,7 +758,7 @@ function activateFailsLauncher(
796
758
  const { path, mime, state } = receiveInterceptorUpdate;
797
759
  const launcherInfo = failsLauncherInfo as FailsLauncherInfo;
798
760
  launcherInfo.receiveRemoteUpdateMessage({ path, mime, state });
799
- _failsCallbacks.postMessageToFails!({
761
+ postMessageToFails!({
800
762
  requestId: event.data.requestId,
801
763
  task: 'receiveInterceptorUpdate'
802
764
  });
@@ -805,7 +767,7 @@ function activateFailsLauncher(
805
767
  case 'restartKernelAndRerunCells':
806
768
  {
807
769
  if (typeof currentDocWidget === 'undefined') {
808
- _failsCallbacks.postMessageToFails!({
770
+ postMessageToFails!({
809
771
  requestId: event.data.requestId,
810
772
  task: 'restartKernelAndRerunCell',
811
773
  error: 'No document loaded'
@@ -825,14 +787,14 @@ function activateFailsLauncher(
825
787
  cells,
826
788
  context.sessionContext
827
789
  );
828
- _failsCallbacks.postMessageToFails!({
790
+ postMessageToFails!({
829
791
  requestId: event.data.requestId,
830
792
  task: 'restartKernelAndRerunCell',
831
793
  success: true
832
794
  });
833
795
  })
834
796
  .catch((error: Error) => {
835
- _failsCallbacks.postMessageToFails!({
797
+ postMessageToFails!({
836
798
  requestId: event.data.requestId,
837
799
  task: 'restartKernelAndRerunCell',
838
800
  error: error.toString()
@@ -842,17 +804,18 @@ function activateFailsLauncher(
842
804
  break;
843
805
  case 'getLicenses':
844
806
  {
845
- ServerConnection.makeRequest(licensesUrl, {}, serverSettings)
846
- .then(async response => {
847
- const json = await response.json();
848
- _failsCallbacks.postMessageToFails!({
807
+ // broken
808
+ licenseClient
809
+ .getBundles()
810
+ .then(async licenses => {
811
+ postMessageToFails!({
849
812
  requestId: event.data.requestId,
850
813
  task: 'getLicenses',
851
- licenses: json
814
+ licenses
852
815
  });
853
816
  })
854
817
  .catch(error => {
855
- _failsCallbacks.postMessageToFails!({
818
+ postMessageToFails!({
856
819
  requestId: event.data.requestId,
857
820
  task: 'getLicenses',
858
821
  error: error.toString()
@@ -887,12 +850,17 @@ function activateFailsLauncher(
887
850
  }
888
851
 
889
852
  const failsLauncher: JupyterFrontEndPlugin<IFailsLauncherInfo> = {
890
- id: '@fails-components/jupyter-fails:launcher',
853
+ id: '@fails-components/jupyter-applet-widget:launcher',
891
854
  description: 'Configures the notebooks application over messages',
892
855
  autoStart: true,
893
856
  activate: activateFailsLauncher,
894
857
  provides: IFailsLauncherInfo,
895
- requires: [IDocumentManager, ILabStatus],
858
+ requires: [
859
+ IDocumentManager,
860
+ ILabStatus,
861
+ ILicensesClient,
862
+ IFailsDriveMessages
863
+ ],
896
864
  optional: [INotebookShell]
897
865
  };
898
866
 
@@ -901,7 +869,6 @@ const failsLauncher: JupyterFrontEndPlugin<IFailsLauncherInfo> = {
901
869
  */
902
870
  const plugins: JupyterFrontEndPlugin<any>[] = [
903
871
  // all JupyterFrontEndPlugins
904
-
905
872
  failsLauncher
906
873
  ];
907
874
 
package/src/tokens.ts ADDED
@@ -0,0 +1,43 @@
1
+ import { Token } from '@lumino/coreutils';
2
+ import { ISignal } from '@lumino/signaling';
3
+ import { JSONObject, PartialJSONObject } from '@lumino/coreutils';
4
+
5
+ export interface IAppletWidgetRegistry {}
6
+
7
+ export interface IFailsAppletSize {
8
+ appid: string;
9
+ width: number;
10
+ height: number;
11
+ }
12
+
13
+ export interface IFailsLauncherInit {
14
+ inLecture: boolean;
15
+ selectedAppid: string | undefined;
16
+ reportMetadata?: (metadata: PartialJSONObject) => void;
17
+ }
18
+
19
+ export interface IFailsInterceptorUpdateMessage {
20
+ path: string;
21
+ mime: string;
22
+ state: JSONObject;
23
+ }
24
+
25
+ export interface IFailsLauncherInfo extends IFailsLauncherInit {
26
+ inLectureChanged: ISignal<IFailsLauncherInfo, boolean>;
27
+ selectedAppidChanged: ISignal<this, string | undefined>;
28
+ appletSizes: { [key: string]: IFailsAppletSize };
29
+ appletSizesChanged: ISignal<this, { [key: string]: IFailsAppletSize }>;
30
+ updateMessageArrived?: ISignal<
31
+ IAppletWidgetRegistry,
32
+ IFailsInterceptorUpdateMessage
33
+ >;
34
+ remoteUpdateMessageArrived: ISignal<
35
+ IFailsLauncherInfo,
36
+ IFailsInterceptorUpdateMessage
37
+ >;
38
+ }
39
+
40
+ export const IFailsLauncherInfo = new Token<IFailsLauncherInfo>(
41
+ '@fails-components/jupyter-fails:IFailsLauncherInfo',
42
+ 'A service to communicate with FAILS.'
43
+ );