mirror of
https://github.com/molstar/molstar.git
synced 2026-06-04 13:30:24 +08:00
@@ -59,7 +59,7 @@ export async function getG3dDataBlock(ctx: PluginContext, header: G3dHeader, url
|
||||
|
||||
async function getRawData(ctx: PluginContext, urlOrData: string | Uint8Array, range: { offset: number, size: number }) {
|
||||
if (typeof urlOrData === 'string') {
|
||||
return await ctx.runTask(ctx.fetch({ url: urlOrData, headers: [['Range', `bytes=${range.offset}-${range.offset + range.size - 1}`]], type: 'binary' }));
|
||||
return await ctx.runTask(ctx.fetch({ url: urlOrData, headers: { 'Range': `bytes=${range.offset}-${range.offset + range.size - 1}` }, type: 'binary' }));
|
||||
} else {
|
||||
return urlOrData.slice(range.offset, range.offset + range.size);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
/**
|
||||
* Copyright (c) 2026 mol* contributors, licensed under MIT, See LICENSE file for more info.
|
||||
*
|
||||
* @author OpenAI Codex
|
||||
* @author Ludovic Autin <ludovic.autin@gmail.com>
|
||||
* @author Alexander Rose <alexander.rose@weirdbyte.de>
|
||||
*/
|
||||
|
||||
import { RuntimeContext } from '../../mol-task';
|
||||
@@ -20,10 +21,10 @@ describe('graphql transport', () => {
|
||||
if (!Asset.isUrl(asset)) throw new Error('expected URL asset');
|
||||
|
||||
expect(asset.url).toBe('https://example.org/graphql');
|
||||
expect(asset.headers).toEqual([
|
||||
['Content-Type', 'application/json; charset=utf-8'],
|
||||
['Accept', 'application/json']
|
||||
]);
|
||||
expect(asset.headers).toEqual({
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
'Accept': 'application/json'
|
||||
});
|
||||
expect(asset.body).toContain('"query"');
|
||||
expect(asset.body).toContain('"variables"');
|
||||
|
||||
@@ -55,10 +56,10 @@ describe('graphql transport', () => {
|
||||
url: 'https://example.org/graphql',
|
||||
type: 'json',
|
||||
body: '{"query":"{ test }"}',
|
||||
headers: [
|
||||
['Content-Type', 'application/json'],
|
||||
['Accept', 'application/json']
|
||||
]
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
'Accept': 'application/json'
|
||||
}
|
||||
}).run();
|
||||
|
||||
expect(fetchSpy).toHaveBeenCalledWith('https://example.org/graphql', {
|
||||
|
||||
@@ -17,10 +17,10 @@ type _File = File;
|
||||
type Asset = Asset.Url | Asset.File
|
||||
|
||||
namespace Asset {
|
||||
export type Url = { kind: 'url', id: UUID, url: string, title?: string, body?: string, headers?: [string, string][] }
|
||||
export type Url = { kind: 'url', id: UUID, url: string, title?: string, body?: string, headers?: Record<string, string> }
|
||||
export type File = { kind: 'file', id: UUID, name: string, file?: _File }
|
||||
|
||||
export function Url(url: string, options?: { body?: string, title?: string, headers?: [string, string][] }): Url {
|
||||
export function Url(url: string, options?: { body?: string, title?: string, headers?: Record<string, string> }): Url {
|
||||
return { kind: 'url', id: UUID.create22(), url, ...options };
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace Asset {
|
||||
return typeof url === 'string' ? url : url.url;
|
||||
}
|
||||
|
||||
export function getUrlAsset(manager: AssetManager, url: string | Url, body?: string, headers?: [string, string][]) {
|
||||
export function getUrlAsset(manager: AssetManager, url: string | Url, body?: string, headers?: Record<string, string>) {
|
||||
if (typeof url === 'string') {
|
||||
const asset = manager.tryFindUrl(url, body, headers);
|
||||
return asset || Url(url, { body, headers });
|
||||
@@ -63,13 +63,13 @@ namespace Asset {
|
||||
}
|
||||
}
|
||||
|
||||
function urlHeadersEqual(a?: [string, string][], b?: [string, string][]) {
|
||||
const aLength = a?.length ?? 0;
|
||||
const bLength = b?.length ?? 0;
|
||||
if (aLength !== bLength) return false;
|
||||
function urlHeadersEqual(a?: Record<string, string>, b?: Record<string, string>) {
|
||||
const aKeys = a ? Object.keys(a) : [];
|
||||
const bKeys = b ? Object.keys(b) : [];
|
||||
if (aKeys.length !== bKeys.length) return false;
|
||||
|
||||
for (let i = 0; i < aLength; i++) {
|
||||
if (a![i][0] !== b![i][0] || a![i][1] !== b![i][1]) return false;
|
||||
for (const key of aKeys) {
|
||||
if (a![key] !== b![key]) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -84,7 +84,7 @@ class AssetManager {
|
||||
return iterableToArray(this._assets.values());
|
||||
}
|
||||
|
||||
tryFindUrl(url: string, body?: string, headers?: [string, string][]): Asset.Url | undefined {
|
||||
tryFindUrl(url: string, body?: string, headers?: Record<string, string>): Asset.Url | undefined {
|
||||
const assets = this.assets.values();
|
||||
while (true) {
|
||||
const v = assets.next();
|
||||
|
||||
@@ -34,7 +34,7 @@ export interface AjaxGetParams<T extends DataType = 'string'> {
|
||||
url: string,
|
||||
type?: T,
|
||||
title?: string,
|
||||
headers?: [string, string][],
|
||||
headers?: Record<string, string>,
|
||||
body?: string
|
||||
}
|
||||
|
||||
@@ -250,7 +250,7 @@ function getRequestResponseType(type: DataType): XMLHttpRequestResponseType {
|
||||
}
|
||||
}
|
||||
|
||||
function ajaxGetInternal<T extends DataType>(title: string | undefined, url: string, type: T, body?: string, headers?: [string, string][]): Task<DataResponse<T>> {
|
||||
function ajaxGetInternal<T extends DataType>(title: string | undefined, url: string, type: T, body?: string, headers?: Record<string, string>): Task<DataResponse<T>> {
|
||||
if (RUNNING_IN_NODEJS) {
|
||||
if (url.startsWith('file://')) {
|
||||
return ajaxGetInternal_file_NodeJS(title, url, type, body, headers);
|
||||
@@ -265,7 +265,7 @@ function ajaxGetInternal<T extends DataType>(title: string | undefined, url: str
|
||||
|
||||
xhttp.open(body ? 'post' : 'get', url, true);
|
||||
if (headers) {
|
||||
for (const [name, value] of headers) {
|
||||
for (const [name, value] of Object.entries(headers)) {
|
||||
xhttp.setRequestHeader(name, value);
|
||||
}
|
||||
}
|
||||
@@ -311,7 +311,7 @@ function readFileAsync(filename: string): Promise<NonSharedBuffer> {
|
||||
}
|
||||
|
||||
/** Alternative implementation of ajaxGetInternal for NodeJS for file:// protocol */
|
||||
function ajaxGetInternal_file_NodeJS<T extends DataType>(title: string | undefined, url: string, type: T, body?: string, headers?: [string, string][]): Task<DataResponse<T>> {
|
||||
function ajaxGetInternal_file_NodeJS<T extends DataType>(title: string | undefined, url: string, type: T, body?: string, headers?: Record<string, string>): Task<DataResponse<T>> {
|
||||
if (!RUNNING_IN_NODEJS) throw new Error('This function should only be used when running in Node.js');
|
||||
if (!url.startsWith('file://')) throw new Error('This function is only for URLs with protocol file://');
|
||||
|
||||
@@ -327,7 +327,7 @@ function ajaxGetInternal_file_NodeJS<T extends DataType>(title: string | undefin
|
||||
}
|
||||
|
||||
/** Alternative implementation of ajaxGetInternal for NodeJS for http(s):// protocol */
|
||||
function ajaxGetInternal_http_NodeJS<T extends DataType>(title: string | undefined, url: string, type: T, body?: string, headers?: [string, string][]): Task<DataResponse<T>> {
|
||||
function ajaxGetInternal_http_NodeJS<T extends DataType>(title: string | undefined, url: string, type: T, body?: string, headers?: Record<string, string>): Task<DataResponse<T>> {
|
||||
if (!RUNNING_IN_NODEJS) throw new Error('This function should only be used when running in Node.js');
|
||||
|
||||
const aborter = new AbortController();
|
||||
@@ -337,7 +337,7 @@ function ajaxGetInternal_http_NodeJS<T extends DataType>(title: string | undefin
|
||||
signal: aborter.signal,
|
||||
method: body ? 'POST' : 'GET',
|
||||
body,
|
||||
headers: headers ? Object.fromEntries(headers) : void 0
|
||||
headers
|
||||
});
|
||||
if (!(response.status >= 200 && response.status < 400)) {
|
||||
throw new Error(`Download failed with status code ${response.status}`);
|
||||
|
||||
@@ -57,10 +57,10 @@ export class GraphQLClient {
|
||||
constructor(private url: string, private assetManager: AssetManager) { }
|
||||
|
||||
async request(ctx: RuntimeContext, query: string, variables?: Variables): Promise<Asset.Wrapper<'json'>> {
|
||||
const headers: [string, string][] = [
|
||||
['Content-Type', 'application/json; charset=utf-8'],
|
||||
['Accept', 'application/json']
|
||||
];
|
||||
const headers: Record<string, string> = {
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
'Accept': 'application/json',
|
||||
};
|
||||
const body = JSON.stringify({ query, variables }, null, 2);
|
||||
const url = Asset.getUrlAsset(this.assetManager, this.url, body, headers);
|
||||
const result = await this.assetManager.resolve(url, 'json').runInContext(ctx);
|
||||
|
||||
Reference in New Issue
Block a user