Skip to content

Commit

Permalink
feat: Adds remote wasm support
Browse files Browse the repository at this point in the history
  • Loading branch information
jakobo committed Nov 25, 2024
1 parent da62c57 commit 3099420
Show file tree
Hide file tree
Showing 27 changed files with 1,605 additions and 677 deletions.
5 changes: 5 additions & 0 deletions .changeset/eleven-icons-develop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@taskless/loader": patch
---

(💥 BREAKING) Adds support for remote wasm files - In order to avoid inlining a ton of WebAssembly in the configuration and manifest files, Taskless now supports remote loading of Wasm files. This both improves the load time of applications and makes it easier to bring your own Wasm files to Taskless.
2 changes: 1 addition & 1 deletion .xo-config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module.exports = {
prettier: true,
space: true,
nodeVersion: false,
ignore: ["vendor/**"],
ignore: ["src/__generated__/**"],
rules: {
"@typescript-eslint/naming-convention": "off",
"@typescript-eslint/no-floating-promises": "off",
Expand Down
100 changes: 96 additions & 4 deletions examples/basic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,107 @@
* variable, this request will show up in your Taskless console, including
* any Packs you've configured. Otherwise, basic information is logged to the
* console, confirming the request was made.
*
* The below code is designed to simulate a running application, generating
* a variety of API calls with different responses.
*/

console.log(
"Reminder: Taskless drain will hold this script open. Either call process.exit() or use CTRL+C to exit."
);

console.log("Making a fetch to example.com (200)");
const resp = await fetch("https://example.com");
// set up handlers for sigint and sigkill that process.exit
process.on("SIGINT", () => {
process.exit();
});

process.on("SIGTERM", () => {
process.exit();
});

type APICall = () => Promise<void>;

// created simulated data for popular APIs
const APIs: APICall[] = [
async () => {
const resp = await fetch("http://colormind.io/api/", {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({ model: "default" }),
});
// console.log(`Colormind.io: Got ${resp.status}`);
},
async () => {
const resp = await fetch(
"https://poetrydb.org/title/Ozymandias/lines.json",
{
method: "GET",
}
);
// console.log(`PoetryDB (Ozymandias): Got ${resp.status}`);
},
async () => {
const resp = await fetch(
"https://goweather.herokuapp.com/weather/San%20Francisco",
{
method: "GET",
}
);
// console.log(`Weather in SF: Got ${resp.status}`);
},
async () => {
const resp = await fetch(
"http://www.7timer.info/bin/api.pl?lon=113.17&lat=23.09&product=astro&output=xml",
{
method: "GET",
}
);
// console.log(`7Timer API to 113.17 23.09: Got ${resp.status}`);
},
async () => {
const resp = await fetch("https://api.github.com/orgs/taskless/repos", {
headers: {
accept: "application/vnd.github+json",
"x-github-api-version": "2022-11-28",
},
});
// console.log(`GitHub API call: Got ${resp.status}`);
},
async () => {
const resp = await fetch("https://slack-status.com/api/v2.0.0/current");
// console.log(`Slack /current: Got ${resp.status}`);

const authResp = await fetch("https://slack.com/api/auth.test", {
method: "POST",
});
// console.log(`Slack Auth Test: Got ${authResp.status}`);
},
async () => {
const resp = await fetch("https://example.com");
// console.log(`Example.com page scrape: Got ${resp.status}`);
},
];

const run = async () => {
// select between 30% and 60% of the APIs in the APIs collection to test
const count = Math.floor(
Math.random() * (APIs.length * 0.3) + APIs.length * 0.3
);
// add those APIs to a set if they're unique
const selected = new Set<APICall>();
while (selected.size < count) {
const intended = APIs[Math.floor(Math.random() * APIs.length)];
if (!selected.has(intended)) {
selected.add(intended);
}
}

await Promise.all(Array.from(selected).map((api) => api()));

console.log("Example: Got", resp.status);
// call run() again between 300ms and 2200ms
setTimeout(run, Math.floor(Math.random() * 1900 + 300));
};

export {};
run();
61 changes: 35 additions & 26 deletions examples/programatic.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { readFileSync } from "fs";
import { resolve } from "path";
import { packageDirectorySync } from "pkg-dir";

// import { taskless } from "@taskless/core";
import { taskless } from "../src/core.js";
import { taskless, type Manifest } from "../src/core.js";

/**
* pnpm tsx --import="./examples/programatic.ts" examples/basic.ts
Expand All @@ -11,34 +15,39 @@ import { taskless } from "../src/core.js";
* TASKLESS_API_KEY environment variable, this request will show up in your
* Taskless console, including any additional Packs you've configured via
* taskless.io.
*
* Instead of using Taskless' loader, you're using your own.
*/

const pack = /* yaml */ `
# Sample YAML pack that captures some additional telemetry data
# This is included in @taskless/core normally, along with additional functionality
pack: 1
name: "@taskless/example"
version: "1.0.0"
description: Basic telemetry
sends:
durationMs:
type: "number"
description: "The duration of the request in milliseconds"
status:
type: "number"
description: "The status code of the request"
rules:
- matches: "https://.+"
hooks:
pre: |
context.set("start", now())
post: |
taskless.capture("durationMs", now() - context.get("start"))
taskless.capture("status", response.getStatus())
`;
const file = readFileSync(
resolve(
packageDirectorySync()!,
"./wasm/0191e2e7-8da6-7558-915d-4a2ecc82472b.wasm"
)
);

const manifest: Manifest = {
schema: "pre1",
name: "@taskless/example",
version: "1.0.0",
description: "Basic telemetry example, showing a programatic manifest",
capture: {
durationMs: {
type: "number",
description: "The duration of the request in milliseconds",
},
status: {
type: "number",
description: "The status code of the request",
},
},
permissions: {
domains: [".+"], // runs on all domains
},
};

const t = taskless(process.env.TASKLESS_API_KEY);
t.add(pack);
await t.load();
t.add(manifest, file);
t.load();

export {};
12 changes: 7 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,16 @@
"src",
"README.md",
"LICENSE",
"package.json"
"package.json",
"wasm"
],
"dependencies": {
"@extism/extism": "2.0.0-rc9",
"fets": "^0.8.2",
"msw": "^2.3.5",
"ts-dedent": "^2.2.0",
"pkg-dir": "^8.0.0",
"uint8array-extras": "^1.4.0",
"uuid": "^10.0.0",
"yaml": "^2.6.0"
"uuid": "^10.0.0"
},
"devDependencies": {
"@changesets/cli": "^2.27.7",
Expand All @@ -65,9 +65,11 @@
"get-port": "^7.1.0",
"hono": "^4.6.3",
"husky": "^9.0.11",
"json-schema-to-typescript": "^15.0.3",
"lint-staged": "^15.2.4",
"mkdirp": "^3.0.1",
"prettier": "^3.2.5",
"shx": "^0.3.4",
"rimraf": "^6.0.1",
"syncpack": "^12.3.2",
"tsx": "^4.16.5",
"type-fest": "^4.23.0",
Expand Down
Loading

0 comments on commit 3099420

Please sign in to comment.