@superfaceai/one-sdk
Advanced tools
Comparing version 3.0.0-beta.22 to 3.0.0-beta.23
@@ -1,3 +0,3 @@ | ||
import type { SecurityValuesMap } from './security.js'; | ||
import { AppContext, FileSystem, Network, Persistence, TextCoder, Timers, WasiContext } from './interfaces.js'; | ||
import type { SecurityValuesMap } from "./security.js"; | ||
import { AppContext, FileSystem, Network, Persistence, TextCoder, Timers, WasiContext } from "./interfaces.js"; | ||
export declare class App extends AppContext { | ||
@@ -4,0 +4,0 @@ private readonly textCoder; |
@@ -1,4 +0,4 @@ | ||
import { AppContext } from './interfaces.js'; | ||
import { PerformError, UnexpectedError, UninitializedError, ValidationError, WasiErrno, WasiError } from './error.js'; | ||
import { AsyncMutex, Asyncify, HandleMap, ReadableStreamAdapter, sf_host } from './lib/index.js'; | ||
import { AppContext, } from "./interfaces.js"; | ||
import { PerformError, UnexpectedError, UninitializedError, ValidationError, WasiErrno, WasiError, } from "./error.js"; | ||
import { AsyncMutex, Asyncify, HandleMap, ReadableStreamAdapter, sf_host, } from "./lib/index.js"; | ||
function headersToMultimap(headers) { | ||
@@ -31,3 +31,3 @@ const result = {}; | ||
timeout: options.metricsTimeout ?? 1000, | ||
handle: 0 | ||
handle: 0, | ||
}; | ||
@@ -49,3 +49,3 @@ } | ||
if (this.module === undefined) { | ||
throw new UnexpectedError('CoreNotLoaded', 'Call loadCore or loadCoreModule first.'); | ||
throw new UnexpectedError("CoreNotLoaded", "Call loadCore or loadCoreModule first."); | ||
} | ||
@@ -58,12 +58,12 @@ if (this.core === undefined) { | ||
asyncify, | ||
setupFn: this.wrapExport(asyncify.wrapExport(instance.exports['oneclient_core_setup'])), | ||
teardownFn: this.wrapExport(asyncify.wrapExport(instance.exports['oneclient_core_teardown'])), | ||
performFn: this.wrapExport(asyncify.wrapExport(instance.exports['oneclient_core_perform'])), | ||
setupFn: this.wrapExport(asyncify.wrapExport(instance.exports["oneclient_core_setup"])), | ||
teardownFn: this.wrapExport(asyncify.wrapExport(instance.exports["oneclient_core_teardown"])), | ||
performFn: this.wrapExport(asyncify.wrapExport(instance.exports["oneclient_core_perform"])), | ||
// if we fail during getting metrics, we want to skip dumping metrics but still attempt to create developer dump | ||
getMetricsFn: this.wrapExport(instance.exports['oneclient_core_get_metrics']), | ||
clearMetricsFn: this.wrapExport(instance.exports['oneclient_core_clear_metrics']), | ||
getMetricsFn: this.wrapExport(instance.exports["oneclient_core_get_metrics"]), | ||
clearMetricsFn: this.wrapExport(instance.exports["oneclient_core_clear_metrics"]), | ||
// if we fail during getting developer dump, we want to skip recursing, so we don't attempt to dump anything | ||
getDeveloperDumpFn: this.wrapExport(instance.exports['oneclient_core_get_developer_dump']) | ||
getDeveloperDumpFn: this.wrapExport(instance.exports["oneclient_core_get_developer_dump"]), | ||
}); | ||
return this.core.withLock(core => core.setupFn()); | ||
return this.core.withLock((core) => core.setupFn()); | ||
} | ||
@@ -74,3 +74,3 @@ } | ||
await this.sendMetrics(); | ||
return this.core.withLock(core => core.teardownFn()); | ||
return this.core.withLock((core) => core.teardownFn()); | ||
// TODO: should there be a this.core = undefined here? | ||
@@ -85,3 +85,11 @@ } | ||
return this.core.withLock(async (core) => { | ||
this.performState = { profileUrl, providerUrl, mapUrl, usecase, input, parameters, security }; | ||
this.performState = { | ||
profileUrl, | ||
providerUrl, | ||
mapUrl, | ||
usecase, | ||
input, | ||
parameters, | ||
security, | ||
}; | ||
await core.performFn(); | ||
@@ -101,5 +109,5 @@ const state = this.performState; | ||
switch (message.kind) { | ||
case 'perform-input': | ||
case "perform-input": | ||
return { | ||
kind: 'ok', | ||
kind: "ok", | ||
profile_url: this.performState.profileUrl, | ||
@@ -113,9 +121,9 @@ provider_url: this.performState.providerUrl, | ||
}; | ||
case 'perform-output-result': | ||
case "perform-output-result": | ||
this.performState.result = message.result; | ||
return { kind: 'ok' }; | ||
case 'perform-output-error': | ||
return { kind: "ok" }; | ||
case "perform-output-error": | ||
this.performState.error = new PerformError(message.error); | ||
return { kind: 'ok' }; | ||
case 'perform-output-exception': | ||
return { kind: "ok" }; | ||
case "perform-output-exception": | ||
if (message.exception.error_code === "InputValidationError") { | ||
@@ -127,4 +135,4 @@ this.performState.exception = new ValidationError(message.exception.message); | ||
} | ||
return { kind: 'ok' }; | ||
case 'file-open': { | ||
return { kind: "ok" }; | ||
case "file-open": { | ||
try { | ||
@@ -137,3 +145,3 @@ const file_handle = await this.fileSystem.open(message.path, { | ||
write: message.write, | ||
read: message.read | ||
read: message.read, | ||
}); | ||
@@ -143,11 +151,11 @@ const handle = this.streams.insert({ | ||
write: this.fileSystem.write.bind(this.fileSystem, file_handle), | ||
close: this.fileSystem.close.bind(this.fileSystem, file_handle) | ||
close: this.fileSystem.close.bind(this.fileSystem, file_handle), | ||
}); | ||
return { kind: 'ok', stream: handle }; | ||
return { kind: "ok", stream: handle }; | ||
} | ||
catch (error) { | ||
return { kind: 'err', errno: error.errno }; | ||
return { kind: "err", errno: error.errno }; | ||
} | ||
} | ||
case 'http-call': { | ||
case "http-call": { | ||
const requestInit = { | ||
@@ -162,20 +170,33 @@ method: message.method, | ||
const request = this.network.fetch(message.url, requestInit); | ||
return { kind: 'ok', handle: this.requests.insert(request) }; | ||
return { kind: "ok", handle: this.requests.insert(request) }; | ||
} | ||
catch (error) { | ||
return { kind: 'err', error_code: error.name, message: error.message }; | ||
return { | ||
kind: "err", | ||
error_code: error.name, | ||
message: error.message, | ||
}; | ||
} | ||
} | ||
case 'http-call-head': { | ||
case "http-call-head": { | ||
try { | ||
const response = await this.requests.remove(message.handle); | ||
const bodyStream = new ReadableStreamAdapter(response.body); | ||
return { kind: 'ok', status: response.status, headers: headersToMultimap(response.headers), body_stream: this.streams.insert(bodyStream) }; | ||
return { | ||
kind: "ok", | ||
status: response.status, | ||
headers: headersToMultimap(response.headers), | ||
body_stream: this.streams.insert(bodyStream), | ||
}; | ||
} | ||
catch (error) { | ||
return { kind: 'err', error_code: error.name, message: error.message }; | ||
return { | ||
kind: "err", | ||
error_code: error.name, | ||
message: error.message, | ||
}; | ||
} | ||
} | ||
default: | ||
return { 'kind': 'err', 'error': `Unknown message ${message['kind']}` }; | ||
return { kind: "err", error: `Unknown message ${message["kind"]}` }; | ||
} | ||
@@ -207,3 +228,3 @@ } | ||
wasi_snapshot_preview1: wasi.wasiImport, | ||
...sf_host.link(this, this.textCoder, asyncify) | ||
...sf_host.link(this, this.textCoder, asyncify), | ||
}; | ||
@@ -217,6 +238,6 @@ } | ||
catch (err) { | ||
let errName = 'UnexpectedError'; | ||
let errName = "UnexpectedError"; | ||
let errMessage = `${err}`; | ||
if (err instanceof WebAssembly.RuntimeError) { | ||
errName = 'WebAssemblyRuntimeError'; | ||
errName = "WebAssemblyRuntimeError"; | ||
errMessage = err.stack ?? err.message; | ||
@@ -267,4 +288,4 @@ } | ||
// event length without the null byte | ||
const eventLength = buffer.findIndex(b => b === 0); | ||
events.push(this.textCoder.decodeUtf8(buffer.subarray(0, eventLength))); | ||
const eventLength = buffer.findIndex((b) => b === 0); | ||
events.push(this.textCoder.decodeUtf8(buffer.subarray(0, eventLength).buffer)); | ||
buffer = buffer.subarray(eventLength + 1); | ||
@@ -271,0 +292,0 @@ } |
@@ -20,3 +20,3 @@ export declare abstract class AppBase { | ||
decodeUtf8(buffer: ArrayBufferLike): string; | ||
encodeUtf8(string: string): ArrayBuffer; | ||
encodeUtf8(string: string): Uint8Array; | ||
} |
@@ -1,4 +0,4 @@ | ||
import { SecurityValuesMap } from './common/index.js'; | ||
export { PerformError, UnexpectedError, ValidationError } from './common/index.js'; | ||
export { fetchErrorToHostError, systemErrorToWasiError } from './error.js'; | ||
import { SecurityValuesMap } from "./common/index.js"; | ||
export { PerformError, UnexpectedError, ValidationError, } from "./common/index.js"; | ||
export { fetchErrorToHostError, systemErrorToWasiError } from "./error.js"; | ||
export type ClientOptions = { | ||
@@ -5,0 +5,0 @@ /** |
@@ -1,15 +0,15 @@ | ||
import fs from 'node:fs/promises'; | ||
import { readFileSync } from 'node:fs'; | ||
import { resolve as resolvePath } from 'node:path'; | ||
import process from 'node:process'; | ||
import { WASI } from 'node:wasi'; | ||
import { AsyncMutex } from './common/lib/index.js'; | ||
import { App, HandleMap, UnexpectedError, WasiErrno, WasiError } from './common/index.js'; | ||
import { fetchErrorToHostError, systemErrorToWasiError } from './error.js'; | ||
import { fileURLToPath } from 'node:url'; | ||
import fs from "node:fs/promises"; | ||
import { readFileSync } from "node:fs"; | ||
import { resolve as resolvePath } from "node:path"; | ||
import process from "node:process"; | ||
import { WASI } from "node:wasi"; | ||
import { AsyncMutex } from "./common/lib/index.js"; | ||
import { App, HandleMap, UnexpectedError, WasiErrno, WasiError, } from "./common/index.js"; | ||
import { fetchErrorToHostError, systemErrorToWasiError } from "./error.js"; | ||
import { fileURLToPath } from "node:url"; | ||
function coreWasmPath() { | ||
// use new URL constructor to get webpack to bundle the asset and non-bundled code to work correctly in all contexts | ||
const url = new URL('../assets/core-async.wasm', import.meta.url); | ||
const url = new URL("../assets/core-async.wasm", import.meta.url); | ||
let path = url.pathname; | ||
if (path.charAt(0) !== '/') { | ||
if (path.charAt(0) !== "/") { | ||
// when bundled with webpack (in nextjs at least), we get an invalid URL here where only the pathname is filled in | ||
@@ -23,5 +23,5 @@ // this pathname is additionally relative, so we must resolve it | ||
} | ||
export { PerformError, UnexpectedError, ValidationError } from './common/index.js'; | ||
export { fetchErrorToHostError, systemErrorToWasiError } from './error.js'; | ||
const ASSETS_FOLDER = 'superface'; | ||
export { PerformError, UnexpectedError, ValidationError, } from "./common/index.js"; | ||
export { fetchErrorToHostError, systemErrorToWasiError } from "./error.js"; | ||
const ASSETS_FOLDER = "superface"; | ||
class NodeTextCoder { | ||
@@ -53,5 +53,5 @@ constructor() { | ||
async open(path, options) { | ||
let flags = ''; | ||
let flags = ""; | ||
if (options.createNew === true) { | ||
flags += 'x'; | ||
flags += "x"; | ||
} | ||
@@ -62,12 +62,12 @@ else if (options.create === true) { | ||
if (options.truncate === true) { | ||
flags += 'w'; | ||
flags += "w"; | ||
} | ||
else if (options.append === true) { | ||
flags += 'a'; | ||
flags += "a"; | ||
} | ||
else if (options.write === true) { | ||
flags += '+'; | ||
flags += "+"; | ||
} | ||
else if (options.read === true) { | ||
flags += 'r'; | ||
flags += "r"; | ||
} | ||
@@ -144,10 +144,7 @@ try { | ||
this.userAgent = userAgent; | ||
if (superfaceApiUrl === false) { | ||
this.insightsUrl = false; | ||
if (superfaceApiUrl === undefined) { | ||
this.insightsUrl = "https://superface.ai/insights/sdk_event"; | ||
} | ||
else if (superfaceApiUrl === undefined) { | ||
this.insightsUrl = 'https://superface.ai/insights/sdk_event'; | ||
} | ||
else { | ||
this.insightsUrl = `${superfaceApiUrl}/insights/sdk_event`; | ||
this.insightsUrl = false; | ||
} | ||
@@ -160,21 +157,24 @@ } | ||
const headers = { | ||
'content-type': 'application/json', | ||
"content-type": "application/json", | ||
}; | ||
if (this.token !== undefined) { | ||
headers['authorization'] = `SUPERFACE-SDK-TOKEN ${this.token}`; | ||
headers["authorization"] = `SUPERFACE-SDK-TOKEN ${this.token}`; | ||
} | ||
if (this.userAgent !== undefined) { | ||
headers['user-agent'] = this.userAgent; | ||
headers["user-agent"] = this.userAgent; | ||
} | ||
await fetch(`${this.insightsUrl}/batch`, { | ||
method: 'POST', | ||
body: '[' + events.join(',') + ']', | ||
headers | ||
}).catch(err => console.error("Failed to send metrics", err)); | ||
method: "POST", | ||
body: "[" + events.join(",") + "]", | ||
headers, | ||
}).catch((err) => console.error("Failed to send metrics", err)); | ||
} | ||
async persistDeveloperDump(events) { | ||
const timestamp = new Date().toISOString().replaceAll(':', '-').replaceAll('.', '-'); | ||
const timestamp = new Date() | ||
.toISOString() | ||
.replaceAll(":", "-") | ||
.replaceAll(".", "-"); | ||
const fileName = `onesdk_devlog_dump_${timestamp}.txt`; | ||
// TOOD: where to create the dump? | ||
await fs.writeFile(fileName, events.join('')); | ||
await fs.writeFile(fileName, events.join("")); | ||
} | ||
@@ -189,3 +189,5 @@ } | ||
} | ||
this.pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), { encoding: 'utf8' })); | ||
this.pkg = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), { | ||
encoding: "utf8", | ||
})); | ||
this.readyState = new AsyncMutex({ ready: false }); | ||
@@ -198,6 +200,6 @@ this.fileSystem = new NodeFileSystem(); | ||
timers: new NodeTimers(), | ||
persistence: new NodePersistence(options.token, options.superfaceApiUrl, this.userAgent) | ||
persistence: new NodePersistence(options.token, options.superfaceApiUrl, this.userAgent), | ||
}, { metricsTimeout: 1000, userAgent: this.userAgent }); | ||
if (options.onBeforeExitHook !== false) { | ||
process.once('beforeExit', async () => { | ||
process.once("beforeExit", async () => { | ||
await this.destroy(); | ||
@@ -216,4 +218,5 @@ }); | ||
ONESDK_DEFAULT_USERAGENT: this.userAgent, | ||
...process.env | ||
}, version: 'preview1' | ||
...process.env, | ||
}, | ||
version: "preview1", | ||
})); // TODO: node typings do not include version https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/types/node/wasi.d.ts#L68-L110 | ||
@@ -241,3 +244,4 @@ readyState.ready = true; | ||
catch (err) { | ||
if (err instanceof UnexpectedError && (err.name === 'WebAssemblyRuntimeError')) { | ||
if (err instanceof UnexpectedError && | ||
err.name === "WebAssemblyRuntimeError") { | ||
await this.destroy(); | ||
@@ -250,8 +254,8 @@ await this.init(); | ||
async resolveProfileUrl(profile) { | ||
const resolvedProfile = profile.replace(/\//g, '.'); | ||
const resolvedProfile = profile.replace(/\//g, "."); | ||
let path = resolvePath(this.assetsPath, `${resolvedProfile}.profile.ts`); | ||
// migration from Comlink to TypeScript profiles | ||
const pathComlink = resolvePath(this.assetsPath, `${resolvedProfile}.profile`); | ||
if (!(await this.fileSystem.exists(path)) | ||
&& (await this.fileSystem.exists(pathComlink))) { | ||
if (!(await this.fileSystem.exists(path)) && | ||
(await this.fileSystem.exists(pathComlink))) { | ||
path = pathComlink; | ||
@@ -262,3 +266,3 @@ } | ||
async resolveMapUrl(profile, provider) { | ||
const resolvedProfile = profile.replace(/\//g, '.'); | ||
const resolvedProfile = profile.replace(/\//g, "."); | ||
const path = resolvePath(this.assetsPath, `${resolvedProfile}.${provider}.map.js`); | ||
@@ -327,5 +331,5 @@ return `file://${path}`; | ||
async perform(input, options) { | ||
return await this.internal.perform(this.profile.name, options.provider, this.name, input, options?.parameters, options?.security); | ||
return (await this.internal.perform(this.profile.name, options.provider, this.name, input, options?.parameters, options?.security)); | ||
} | ||
} | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "@superfaceai/one-sdk", | ||
"version": "3.0.0-beta.22", | ||
"version": "3.0.0-beta.23", | ||
"exports": { | ||
@@ -16,3 +16,3 @@ ".": "./dist/index.js", | ||
"@types/jest": "^29.5.2", | ||
"@types/node": "^20.3.3", | ||
"@types/node": "^22.12.0", | ||
"jest": "^29.5.0", | ||
@@ -19,0 +19,0 @@ "rimraf": "^5.0.1", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
5220749
1608