Skip to content

Commit

Permalink
Using @deephaven/jsapi-nodejs for dh downloads (155)
Browse files Browse the repository at this point in the history
  • Loading branch information
bmingles committed Nov 12, 2024
1 parent 7b23d29 commit 59de1b1
Show file tree
Hide file tree
Showing 10 changed files with 134 additions and 63 deletions.
72 changes: 22 additions & 50 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -821,6 +821,7 @@
"dependencies": {
"@deephaven-enterprise/auth-nodejs": "^1.20240723.113-beta",
"@deephaven-enterprise/query-utils": "^1.20240723.113-beta",
"@deephaven/jsapi-nodejs": "^0.97.0",
"@deephaven/require-jsapi": "file:./packages/require-jsapi",
"nanoid": "^5.0.7"
},
Expand Down
2 changes: 1 addition & 1 deletion scripts/esbuild.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ async function main() {
sourcesContent: false,
platform: 'node',
outfile: 'out/extension.js',
external: ['vscode'],
external: ['esbuild', 'vscode'],
logLevel: 'silent',
plugins: [
/* add to the end of plugins array */
Expand Down
2 changes: 1 addition & 1 deletion src/controllers/PipServerController.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import * as vscode from 'vscode';
import * as fs from 'node:fs';
import { isDhcServerRunning } from '@deephaven/require-jsapi';
import {
getPipServerUrl,
getPipStatusFilePath,
Expand All @@ -15,6 +14,7 @@ import {
PYTHON_ENV_WAIT,
} from '../common';
import { pollUntilTrue, waitFor } from '../util/promiseUtils';
import { isDhcServerRunning } from '../dh/dhc';

const logger = new Logger('PipServerController');

Expand Down
44 changes: 44 additions & 0 deletions src/dh/dhc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import type {
CoreAuthenticatedClient,
CoreUnauthenticatedClient,
} from '../types';
import { hasStatusCode, loadModules } from '@deephaven/jsapi-nodejs';

export const AUTH_HANDLER_TYPE_ANONYMOUS =
'io.deephaven.auth.AnonymousAuthenticationHandler';
Expand All @@ -19,6 +20,33 @@ export type ConnectionAndSession<TConnection, TSession> = {
session: TSession;
};

// TODO: https://github.com/deephaven/deephaven-core/issues/5911 to address the
// underlying issue of jsapi-types being unaware of `dhinternal`. Once that is
// addressed, this can be removed.
declare global {
// eslint-disable-next-line no-unused-vars
namespace dhinternal.io.deephaven.proto.ticket_pb {
export type TypedTicket = unknown;
}
}

export async function getDhc(
serverUrl: URL,
storageDir: string
): Promise<typeof DhType> {
// Download jsapi `ESM` files from DH Community server.
const coreModule = await loadModules<{ default: typeof DhType }>({
serverUrl,
serverPaths: ['jsapi/dh-core.js', 'jsapi/dh-internal.js'],
download: true,
storageDir,
sourceModuleType: 'esm',
targetModuleType: 'cjs',
});

return coreModule.default;
}

/**
* Get embed widget url for a widget.
* @param serverUrl Server URL
Expand Down Expand Up @@ -77,6 +105,22 @@ export async function initDhcSession(
return { cn, session };
}

/**
* Check if a given server is running by checking if the `dh-core.js` file is
* accessible.
* @param serverUrl
*/
export async function isDhcServerRunning(serverUrl: URL): Promise<boolean> {
try {
return await hasStatusCode(
new URL('jsapi/dh-core.js', serverUrl.toString()),
[200, 204]
);
} catch {
return false;
}
}

/**
* Login a given unauthenticated client with the given credentials.
* @param client The client to login.
Expand Down
59 changes: 58 additions & 1 deletion src/dh/dhe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import type {
TypeSpecificFields,
} from '@deephaven-enterprise/jsapi-types';
import { DraftQuery, QueryScheduler } from '@deephaven-enterprise/query-utils';
import type { AuthenticatedClient as DheAuthenticatedClient } from '@deephaven-enterprise/auth-nodejs';
import { hasStatusCode, loadModules } from '@deephaven/jsapi-nodejs';
import type {
ConsoleType,
IdeURL,
Expand All @@ -21,13 +23,37 @@ import {
INTERACTIVE_CONSOLE_QUERY_TYPE,
INTERACTIVE_CONSOLE_TEMPORARY_QUEUE_NAME,
} from '../common';
import type { AuthenticatedClient as DheAuthenticatedClient } from '@deephaven-enterprise/auth-nodejs';

export type IDraftQuery = EditableQueryInfo & {
isClientSide: boolean;
draftOwner: string;
};

declare global {
// This gets added by the DHE jsapi.
// eslint-disable-next-line no-unused-vars
const iris: DheType;
}

export async function getDhe(
serverUrl: URL,
storageDir: string
): Promise<DheType> {
polyfill();

// Download jsapi `ESM` files from DH Community server.
await loadModules({
serverUrl,
serverPaths: ['irisapi/irisapi.nocache.js'],
download: true,
storageDir,
sourceModuleType: 'cjs',
});

// DHE currently exposes the jsapi via the global `iris` object.
return iris;
}

/**
* Get credentials for a Core+ worker associated with a given DHE client.
* @param client The DHE client.
Expand Down Expand Up @@ -65,6 +91,22 @@ export async function hasInteractivePermission(
return isSuperUser || isInteractive;
}

/**
* Check if a given server is running by checking if the `irisapi/irisapi.nocache.js`
* file is accessible.
* @param serverUrl
*/
export async function isDheServerRunning(serverUrl: URL): Promise<boolean> {
try {
return await hasStatusCode(
new URL('irisapi/irisapi.nocache.js', serverUrl.toString()),
[200, 204]
);
} catch {
return false;
}
}

/**
* Create a query of type `InteractiveConsole`.
* @param tagId Unique tag id to include in the query name.
Expand Down Expand Up @@ -234,3 +276,18 @@ export async function getWorkerInfoFromQuery(
workerName,
};
}

export function polyfill(): void {
// These will eventually not be needed once JSAPI is updated to not rely on `window` and `self`.
// @ts-ignore
globalThis.self = globalThis;
// @ts-ignore
globalThis.window = globalThis;

// This is needed to mimic running in a local http browser environment when
// making requests to the server. This at least impacts websocket connections.
// Not sure if it is needed for other requests. The url is an arbitrary
// non-https url just to make it stand out in logs.
// @ts-ignore
global.window.location = new URL('http://vscode-deephaven.localhost/');
}
2 changes: 1 addition & 1 deletion src/services/DhcService.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import * as vscode from 'vscode';
import type { dh as DhcType } from '@deephaven/jsapi-types';
import { isAggregateError } from '@deephaven/require-jsapi';
import { formatTimestamp, getCombinedSelectedLinesText, Logger } from '../util';
import { initDhcSession, type ConnectionAndSession } from '../dh/dhc';
import type {
Expand All @@ -26,6 +25,7 @@ import {
} from '../common';
import { NoConsoleTypesError, parseServerError } from '../dh/errorUtils';
import { hasErrorCode } from '../util/typeUtils';
import { isAggregateError } from '@deephaven/jsapi-nodejs';

const logger = new Logger('DhcService');

Expand Down
7 changes: 2 additions & 5 deletions src/services/ServerManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@ import * as vscode from 'vscode';
import { randomUUID } from 'node:crypto';
import type { dh as DhcType } from '@deephaven/jsapi-types';
import type { AuthenticatedClient as DheAuthenticatedClient } from '@deephaven-enterprise/auth-nodejs';
import {
isDhcServerRunning,
isDheServerRunning,
} from '@deephaven/require-jsapi';
import { UnsupportedConsoleTypeError } from '../common';
import type {
ConsoleType,
Expand Down Expand Up @@ -34,7 +30,8 @@ import {
import { URLMap } from './URLMap';
import { URIMap } from './URIMap';
import { DhcService } from './DhcService';
import { getWorkerCredentials } from '../dh/dhe';
import { getWorkerCredentials, isDheServerRunning } from '../dh/dhe';
import { isDhcServerRunning } from '../dh/dhc';

const logger = new Logger('ServerManager');

Expand Down
4 changes: 2 additions & 2 deletions src/services/cache/CoreJsApiCache.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { initDhcApi } from '@deephaven/require-jsapi';
import type { dh as DhcType } from '@deephaven/jsapi-types';
import { getTempDir, urlToDirectoryName } from '../../util';
import { ByURLAsyncCache } from './ByURLAsyncCache';
import { getDhc } from '../../dh/dhc';

/**
* Cache Core jsapi instances by URL.
*/
export class CoreJsApiCache extends ByURLAsyncCache<typeof DhcType> {
constructor() {
super(async url =>
initDhcApi(url, getTempDir({ subDirectory: urlToDirectoryName(url) }))
getDhc(url, getTempDir({ subDirectory: urlToDirectoryName(url) }))
);
}
}
4 changes: 2 additions & 2 deletions src/services/cache/DheJsApiCache.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { initDheApi } from '@deephaven/require-jsapi';
import type { EnterpriseDhType as DheType } from '@deephaven-enterprise/jsapi-types';
import { getTempDir, urlToDirectoryName } from '../../util';
import { ByURLAsyncCache } from './ByURLAsyncCache';
import { getDhe } from '../../dh/dhe';

/**
* Cache DHE jsapi instances by URL.
*/
export class DheJsApiCache extends ByURLAsyncCache<DheType> {
constructor() {
super(async url =>
initDheApi(url, getTempDir({ subDirectory: urlToDirectoryName(url) }))
getDhe(url, getTempDir({ subDirectory: urlToDirectoryName(url) }))
);
}
}

0 comments on commit 59de1b1

Please sign in to comment.