@mochabug/adapt-core
v2.0.0-beta.10
Published
Cross-platform core client library for Adapt automation platform
Readme
@mochabug/adapt-core
Headless client for Adapt automations. No UI — just the automation lifecycle.
TypeScript consumers need TypeScript 5.7 or newer for the generic typed arrays used in the public declarations.
The package does not impose a Node.js engine version. Its transports support
Connect 2.x, including 2.0; applications can retain compatible versions rather
than being forced onto a newer transport's Node.js requirement. The Node.js
requirement of @connectrpc/connect-node still applies when installing that transport.
npm install @mochabug/adapt-coreCDN (ESM — from @mochabug/adapt-web):
<script type="module">
import { createAdaptClient, createConnectClient } from 'https://cdn.mochabug.com/adapt/web/__VERSION__/adapt-core.min.js';
const client = createAdaptClient(createConnectClient({ id: 'YOUR_ID' }), 'YOUR_ID');
</script>Quick start
Browser
import { createConnectClient } from "@mochabug/adapt-core/connect";
import { createAdaptClient } from "@mochabug/adapt-core";
const client = createAdaptClient(
createConnectClient({ id: "my-automation" }),
"my-automation",
);
const { sessionToken } = await client.run({
onSession: (session) => console.log("Status:", session.status),
onOutput: (output) => console.log("Output:", output.data),
onUrl: (url) => console.log("URL:", url.url),
onError: (error) => console.error("Error:", error),
});Node.js
import { createGrpcClient } from "@mochabug/adapt-core/grpc";
import { createAdaptClient } from "@mochabug/adapt-core";
const client = createAdaptClient(
createGrpcClient(),
"my-automation",
);Configuration
import { configure } from "@mochabug/adapt-core";
configure({
url: "https://adapt.mochabugapis.com",
});Production is the default. Use https://adapt-dev.mochabugapis.com for staging.
url is an absolute HTTP(S) origin: a trailing slash is normalized, while paths,
credentials, queries and fragments are rejected without changing configuration.
configure({}) preserves the current value; resetConfig() restores production.
Configuration applies to newly created transports.
Both transports use this origin. Browser Connect uses the automation-scoped
/v1/automations/{id}/mochabugapis.adapt.automations.v1.AutomationService/…
route; native gRPC uses /mochabugapis.adapt.automations.v1.AutomationService/…
over HTTP/2. createGrpcClient accepts GrpcClientOptions for transport tuning;
the origin is set only through configure. Plugin execution URLs come directly
from the API and must not be reconstructed from the API origin.
Run an automation
run() starts a session and subscribes to real-time updates in a single RPC call.
Calling unsubscribe() before run() or runInherit() receives its session
token rejects the pending call with ConnectError code Canceled.
const { sessionToken, expiresAt } = await client.run({
challengeToken, // proof-of-work token (if required)
transmitter: "start", // optional starting transmitter
signals: { // optional input signals
query: "hello",
file: { mimeType: "application/pdf", data: pdfBytes, filename: "doc.pdf" },
},
authToken, // for protected automations
onSession: (s) => { /* { status, fork? } */ },
onOutput: (o) => { /* { vertex, fork, data, created } */ },
onUrl: (u) => { /* { url, vertex, done, stopped, created, token, fork, source, retentionPolicy } */ },
onError: (e) => { /* non-retriable stream error */ },
});URL retentionPolicy is forwarded in streams and readUrls(): retain, recycle,
or close with optional timeoutSeconds. The headless client stops its stream on
terminal session status; rendered content can remain mounted independently. The
web and Electron clients use the URL policy to control its lifetime.
Inherit a session
const { sessionToken } = await client.runInherit(parentToken, {
onSession: (s) => {},
onOutput: (o) => {},
});Start without subscribing
const { sessionToken, expiresAt } = await client.start({
challengeToken,
transmitter: "start",
signals: { input: "data" },
});
await client.subscribe(sessionToken, {
onSession: (s) => {},
onOutput: (o) => {},
});
await client.stop(sessionToken);
await client.unsubscribe();Read data
const session = await client.getSession(sessionToken);
const { outputs, nextPageCursor } = await client.readOutput(sessionToken, {
pageSize: 100,
vertex: "output-vertex",
});
// Continue reading with the UUID cursor from the preceding response.
if (nextPageCursor) {
await client.readOutput(sessionToken, { newerThan: nextPageCursor });
}
const { urls } = await client.readUrls(sessionToken, {
pageSize: 50,
});Headless + Cap (ESM)
Load the headless client and Cap widget together for proof-of-work in non-UI scenarios:
<div id="cap-container"></div>
<script type="module">
import { createAdaptClient, createConnectClient } from 'https://cdn.mochabug.com/adapt/web/__VERSION__/adapt-core.min.js';
import { Cap } from 'https://cdn.mochabug.com/adapt/web/__VERSION__/adapt-web.cap.min.js';
const client = createAdaptClient(
createConnectClient({ id: "my-automation" }),
"my-automation"
);
// Show Cap widget, then run with the token
const cap = new Cap({
container: "cap-container",
automationId: "my-automation",
client: createConnectClient({ id: "my-automation" }),
onSolve: function (token) {
client.run({ challengeToken: token });
},
});
</script>Error handling
import { ConnectError, Code } from "@mochabug/adapt-core";
try {
await client.run();
} catch (e) {
if (e instanceof ConnectError) {
console.error(e.code, e.message); // e.g. Code.NotFound
}
}Retriable errors (network failures, server overload) are retried automatically with exponential backoff. Non-retriable errors (NotFound, PermissionDenied, Unauthenticated, InvalidArgument, FailedPrecondition, ResourceExhausted) are thrown immediately.
Entry points
| Export | Description |
|--------|-------------|
| @mochabug/adapt-core | Client, types, configuration |
| @mochabug/adapt-core/connect | createConnectClient — browser transport |
| @mochabug/adapt-core/grpc | createGrpcClient — Node.js transport |
License
ISC © mochabug AB
