From 51d19ffeb4aaba874fadde019f29fc9bf6f30da5 Mon Sep 17 00:00:00 2001 From: Hendrik Eeckhaut Date: Tue, 25 Jun 2024 15:05:48 +0200 Subject: [PATCH] initial draft for tlsn-plugin boilerplate template --- .gitignore | 11 ++ README.md | 57 +++++++++++ assets/icon.png | Bin 0 -> 31426 bytes config.json | 39 ++++++++ esbuild.js | 85 ++++++++++++++++ examples/twitter_dm_js/README.md | 11 ++ examples/twitter_dm_js/index.d.ts | 14 +++ examples/twitter_dm_js/index.js | 127 +++++++++++++++++++++++ examples/twitter_profile_js/index.d.ts | 15 +++ examples/twitter_profile_js/index.js | 130 ++++++++++++++++++++++++ package.json | 17 ++++ src/index.d.ts | 15 +++ src/index.ts | 133 +++++++++++++++++++++++++ tsconfig.json | 14 +++ 14 files changed, 668 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 assets/icon.png create mode 100644 config.json create mode 100644 esbuild.js create mode 100644 examples/twitter_dm_js/README.md create mode 100644 examples/twitter_dm_js/index.d.ts create mode 100644 examples/twitter_dm_js/index.js create mode 100644 examples/twitter_profile_js/index.d.ts create mode 100644 examples/twitter_profile_js/index.js create mode 100644 package.json create mode 100644 src/index.d.ts create mode 100644 src/index.ts create mode 100644 tsconfig.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4429cc0 --- /dev/null +++ b/.gitignore @@ -0,0 +1,11 @@ +/target +**/*.rs.bk +Cargo.lock +bin/ +**/node_modules +**/.DS_Store +.idea +build +tlsn/ +zip +dist/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..719b543 --- /dev/null +++ b/README.md @@ -0,0 +1,57 @@ +# Plugin Development for the TLSNotary Browser Extension + +This repository contains the boilerplate code for developing a plugin for the TLSNotary browser extension. Currently, the template includes a TypeScript-based plugin example that proves ownership of a Twitter profile. + +TLSNotary's plugin system uses [Extism](https://github.com/extism), which enables plugins in different programming languages. For more documentation, check [Extism's documentation](https://github.com/extism/js-pdk). + +## Installation of Extism-js + +1. **Download and Install Extism-js**: Begin by setting up `extism-js`, which enables you to compile and manage your plugins. Run these commands to download and install it: + + ```sh + curl -O https://raw.githubusercontent.com/extism/js-pdk/main/install.sh + sh install.sh + ``` + + This script installs the Extism JavaScript Plugin Development Kit from its GitHub repository, preparing your environment for plugin compilation. + +## Building the Twitter Profile Plugin + +To build the plugin, run: + +```sh +npm i +npm run build +``` + +This will output the wasm binary in `dist/index.wasm`. + +### Running the Twitter Plugin Example + +1. Build the `twitter_profile` plugin as explained above. +2. Build and install the `tlsn-extension` as documented in the [main README.md](../README.md). +3. [Run a local notary server](https://github.com/tlsnotary/tlsn/blob/main/notary-server/README.md), ensuring `TLS` is disabled in the [config file](https://github.com/tlsnotary/tlsn/blob/main/notary-server/config/config.yaml#L18). +4. Install the plugin: Click the **Add a Plugin (+)** button and select the `index.wasm` file you built in step 1. A **Twitter Profile** button should then appear below the default buttons. +5. Click the **Twitter Profile** button. This action opens the Twitter webpage along with a TLSNotary sidebar. +6. Follow the steps in the TLSNotary sidebar. +7. Access the TLSNotary results by clicking the **History** button in the TLSNotary extension. + +## Customize the Template + +You are now ready to develop your own plugins. + +Notarization requests take more time than regular requests, so we recommend testing the HTTPS request in Postman or Curl first. This allows you to figure out faster which cookies and headers are required. + +When you add or rename steps, make sure to update the `index.d.ts` file. + +### Custom Icon + +To use a custom icon, replace `icon.png` in the `./assets` folder. Make sure it is 320x320 pixels. You can use the following command: + +```sh +convert icon_source.png -resize 320x320! assets/icon.png +``` + +## More Examples + +Check the `examples` folder for more examples. \ No newline at end of file diff --git a/assets/icon.png b/assets/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..ba58060a7a2c97fd3912cbfe513c2cc68a730296 GIT binary patch literal 31426 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 z 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 literal 0 HcmV?d00001 diff --git a/config.json b/config.json new file mode 100644 index 0000000..1f158b8 --- /dev/null +++ b/config.json @@ -0,0 +1,39 @@ +{ + "title": "Twitter Profile", + "description": "Notarize ownership of a twitter profile", + "steps": [ + { + "title": "Visit Twitter website", + "cta": "Go to x.com", + "action": "start" + }, + { + "title": "Collect credentials", + "description": "Login to your account if you haven't already", + "cta": "Check cookies", + "action": "two" + }, + { + "title": "Notarize twitter profile", + "cta": "Notarize", + "action": "three", + "prover": true + } + ], + "hostFunctions": [ + "redirect", + "notarize" + ], + "cookies": [ + "api.x.com" + ], + "headers": [ + "api.x.com" + ], + "requests": [ + { + "url": "https: //api.x.com/1.1/account/settings.json", + "method": "GET" + } + ] +} \ No newline at end of file diff --git a/esbuild.js b/esbuild.js new file mode 100644 index 0000000..5f290ec --- /dev/null +++ b/esbuild.js @@ -0,0 +1,85 @@ +const esbuild = require('esbuild'); +const fs = require('fs'); +const path = require('path'); +const { promisify } = require('util'); +const { name } = require('./package.json'); +const { execSync } = require('child_process'); + +// Promisify fs.readFile and fs.stat for convenience +const readFileAsync = promisify(fs.readFile); +const statAsync = promisify(fs.stat); +const mkdirAsync = promisify(fs.mkdir); + +/** + * Generates a Base64 encoded icon file. + * It checks if the output file already exists and is up-to-date before generating a new one. + */ +async function generateBase64Icon() { + const iconPath = path.join(__dirname, 'assets', "icon.png"); + const outputDir = path.join(__dirname, 'dist', 'assets'); + const outputPath = path.join(outputDir, 'icon.ts'); + + try { + // Ensure the output directory exists + await mkdirAsync(outputDir, { recursive: true }); + const [iconStat, outputStat] = await Promise.all([ + statAsync(iconPath).catch(() => null), + statAsync(outputPath).catch(() => null) + ]); + + // Check if output file exists and is newer than the icon file + if (outputStat && iconStat && outputStat.mtime > iconStat.mtime) { + console.log('Base64 icon file is up-to-date.'); + return; + } + + const fileBuffer = await readFileAsync(iconPath); + const base64Icon = `data:image/png;base64,${fileBuffer.toString('base64')}`; + + const outputContent = `// This is a generated file. Do not edit directly. +// This is a Base64 encoded version of the plugin's icon ('icon.png') used in the plugin's config. +// This file is automatically generated by esBuild.js whenever the icon is changed. +// There is no need to add it to version control. + +export const icon = "${base64Icon}";\n`; + + fs.writeFileSync(outputPath, outputContent); + console.log('Base64 icon file generated successfully.'); + } catch (error) { + console.error(`Failed to generate base64 icon: ${error.message}`); + process.exit(1); + } +} + +const outputDir = 'dist'; +const entryFile = 'src/index.ts'; +const outputFile = path.join(outputDir, 'index.js'); +const outputWasm = path.join(outputDir, `${name}.tlsn.wasm`); + +async function build() { + await generateBase64Icon(); + + try { + await esbuild.build({ + entryPoints: [entryFile], + bundle: true, + outdir: outputDir, // Use outdir for directory output + sourcemap: true, + minify: false, // might want to use true for production build + format: 'cjs', // needs to be CJS for now + target: ['es2020'], // don't go over es2020 because quickjs doesn't support it + }); + + console.log('esbuild completed successfully.'); + + // Run extism-js to generate the wasm file + const extismCommand = `extism-js ${outputFile} -i src/index.d.ts -o ${outputWasm}`; + execSync(extismCommand, { stdio: 'inherit' }); + console.log('extism-js completed successfully.'); + } catch (error) { + console.error('Build process failed:', error); + process.exit(1); + } +} + +build(); \ No newline at end of file diff --git a/examples/twitter_dm_js/README.md b/examples/twitter_dm_js/README.md new file mode 100644 index 0000000..633d978 --- /dev/null +++ b/examples/twitter_dm_js/README.md @@ -0,0 +1,11 @@ +# TLSNotary TypeScript plugin demo: Prove Twitter DM + +This is a demo demo plugin for the TLSNotary browser extension in plain Javascript. + +## Building + +Build the plugin: +``` +extism-js index.js -i index.d.ts -o index.wasm +``` +This command compiles the JavaScript code in index.js into a WebAssembly module, ready for integration with the TLSNotary extension. \ No newline at end of file diff --git a/examples/twitter_dm_js/index.d.ts b/examples/twitter_dm_js/index.d.ts new file mode 100644 index 0000000..283fe08 --- /dev/null +++ b/examples/twitter_dm_js/index.d.ts @@ -0,0 +1,14 @@ +declare module 'main' { + // Extism exports take no params and return an I32 + export function start(): I32; + export function two(): I32; + export function three(): I32; + export function config(): I32; +} + +declare module 'extism:host' { + interface user { + redirect(ptr: I64): void; + notarize(ptr: I64): I64; + } +} diff --git a/examples/twitter_dm_js/index.js b/examples/twitter_dm_js/index.js new file mode 100644 index 0000000..1ef57a2 --- /dev/null +++ b/examples/twitter_dm_js/index.js @@ -0,0 +1,127 @@ +function isCorrectUrl(urlString) { + const url = new URL(urlString); + return url.hostname === 'twitter.com' || url.hostname === 'x.com'; +} + +function extractConversationId(urlString) { + const url = new URL(urlString); + + // Validate the host and path pattern + if (url.hostname === 'x.com' && /\/messages\/[0-9]+-[0-9]+$/.test(url.pathname)) { + // Extract the Conversation ID from the path + return url.pathname.split('/messages/')[1]; + } + return null; // Return null if URL is not valid or does not match the expected format +} + +function gotoUrl() { + const { redirect } = Host.getFunctions(); + const mem = Memory.fromString('https://x.com/messages'); + redirect(mem.offset); +} + +function start() { + if (!isCorrectUrl(Config.get('tabUrl'))) { + gotoUrl(); + Host.outputString(JSON.stringify(false)); + return; + } + Host.outputString(JSON.stringify(true)); +} + +function two() { + const conversation_id = extractConversationId(Config.get('tabUrl')) + const cookies = JSON.parse(Config.get('cookies'))['x.com']; + const headers = JSON.parse(Config.get('headers'))['x.com']; + // console.log("TLSN cookies"); + // console.log(JSON.stringify(cookies)); + // console.log("TLSN headers"); + // console.log(JSON.stringify(headers)); + + if ( + !conversation_id || + !cookies.auth_token || + !cookies.ct0 || + !headers['x-csrf-token'] || + !headers['authorization'] + ) { + Host.outputString(JSON.stringify(false)); + return; + } + + Host.outputString( + JSON.stringify({ + url: `https://x.com/i/api/1.1/dm/conversation/${conversation_id}.json`, + method: 'GET', + headers: { + 'x-csrf-token': headers['x-csrf-token'], + Host: 'x.com', + authorization: headers.authorization, + Cookie: `lang=en; auth_token=${cookies.auth_token}; ct0=${cookies.ct0}`, + 'Accept-Encoding': 'identity', + Connection: 'close', + }, + secretHeaders: [ + `x-csrf-token: ${headers['x-csrf-token']}`, + `cookie: lang=en; auth_token=${cookies.auth_token}; ct0=${cookies.ct0}`, + `authorization: ${headers.authorization}`, + ], + }), + ); + +} + +function three() { + const params = JSON.parse(Host.inputString()); + const { notarize } = Host.getFunctions(); + + if (!params) { + Host.outputString(JSON.stringify(false)); + } else { + const mem = Memory.fromString(JSON.stringify(params)); + const idOffset = notarize(mem.offset); + const id = Memory.find(idOffset).readString(); + Host.outputString(JSON.stringify(id)); + } +} + +function config() { + Host.outputString( + JSON.stringify({ + title: 'Twitter Messages conversation', + description: 'Notarize a Twitter Messages conversation', + icon: 'data:image/png;base64,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GHRFWHRleGlmOlBpeGVsWURpbWVuc2lvbgAzNjJg7bPfAAAALnRFWHRleGlmOlNvZnR3YXJlAEFkb2JlIFBob3Rvc2hvcCAyMS4yIChNYWNpbnRvc2gp7KPJiwAAABR0RVh0dGlmZjpJbWFnZUxlbmd0aAA3MzILSegBAAAAFHRFWHR0aWZmOkltYWdlV2lkdGgAMTI4MGs14DUAAAASdEVYdHRpZmY6T3JpZW50YXRpb24AMber/DsAAAAwdEVYdHhtcDpDcmVhdG9yVG9vbABBZG9iZSBQaG90b3Nob3AgMjEuMiAoTWFjaW50b3NoKa1d3PwAAABMdEVYdHhtcE1NOkRlcml2ZWRGcm9tAGFkb2JlOmRvY2lkOnBob3Rvc2hvcDozODllNzc4Mi0yNDFhLWI2NDYtOWU2ZC03MTZhNTJjMTgxMzh8PH40AAAAOXRFWHR4bXBNTTpEb2N1bWVudElEAHhtcC5kaWQ6NDlGMjNCRkExMzJEMTFFQkFDRTY5MUYzQ0Y4QzhEQUZe7I9yAAAAOXRFWHR4bXBNTTpJbnN0YW5jZUlEAHhtcC5paWQ6NDlGMjNCRjkxMzJEMTFFQkFDRTY5MUYzQ0Y4QzhEQUac4S47AAAARXRFWHR4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQAeG1wLmRpZDpkOWM5OWQyZS0zMTM4LTQxNjAtYjllMC1mYThlMzI4ZTY3MzLrZD4KAAAAAElFTkSuQmCC', + steps: [ + { + title: 'Visit X/Twitter Messages', + description: "Log in to your account if you haven't already", + cta: 'Go to x.com', + action: 'start', + }, + { + title: 'Open the conversation you want to notarize', + description: "Pick a short conversation (to meet current size limits)", + cta: 'Check', + action: 'two', + }, + { + title: 'Notarize conversation', + cta: 'Notarize', + action: 'three', + prover: true, + }, + ], + hostFunctions: ['redirect', 'notarize'], + cookies: ['x.com'], + headers: ['x.com'], + requests: [ + { + url: `https://x.com/i/api/1.1/dm/conversation/*.json`, + method: 'GET', + }, + ], + }), + ); +} + +module.exports = { start, config, two, three }; diff --git a/examples/twitter_profile_js/index.d.ts b/examples/twitter_profile_js/index.d.ts new file mode 100644 index 0000000..3380f1a --- /dev/null +++ b/examples/twitter_profile_js/index.d.ts @@ -0,0 +1,15 @@ +declare module 'main' { + // Extism exports take no params and return an I32 + export function start(): I32; + export function two(): I32; + export function parseTwitterResp(): I32; + export function three(): I32; + export function config(): I32; +} + +declare module 'extism:host' { + interface user { + redirect(ptr: I64): void; + notarize(ptr: I64): I64; + } +} diff --git a/examples/twitter_profile_js/index.js b/examples/twitter_profile_js/index.js new file mode 100644 index 0000000..a700905 --- /dev/null +++ b/examples/twitter_profile_js/index.js @@ -0,0 +1,130 @@ +function isValidHost(urlString) { + const url = new URL(urlString); + return url.hostname === 'twitter.com' || url.hostname === 'x.com'; +} + +function gotoTwitter() { + const { redirect } = Host.getFunctions(); + const mem = Memory.fromString('https://x.com'); + redirect(mem.offset); +} + +function start() { + if (!isValidHost(Config.get('tabUrl'))) { + gotoTwitter(); + Host.outputString(JSON.stringify(false)); + return; + } + Host.outputString(JSON.stringify(true)); +} + +function two() { + const cookies = JSON.parse(Config.get('cookies'))['api.x.com']; + const headers = JSON.parse(Config.get('headers'))['api.x.com']; + if ( + !cookies.auth_token || + !cookies.ct0 || + !headers['x-csrf-token'] || + !headers['authorization'] + ) { + Host.outputString(JSON.stringify(false)); + return; + } + + Host.outputString( + JSON.stringify({ + url: 'https://api.x.com/1.1/account/settings.json', + method: 'GET', + headers: { + 'x-twitter-client-language': 'en', + 'x-csrf-token': headers['x-csrf-token'], + Host: 'api.x.com', + authorization: headers.authorization, + Cookie: `lang=en; auth_token=${cookies.auth_token}; ct0=${cookies.ct0}`, + 'Accept-Encoding': 'identity', + Connection: 'close', + }, + secretHeaders: [ + `x-csrf-token: ${headers['x-csrf-token']}`, + `cookie: lang=en; auth_token=${cookies.auth_token}; ct0=${cookies.ct0}`, + `authorization: ${headers.authorization}`, + ], + }), + ); +} + +function parseTwitterResp() { + const bodyString = Host.inputString(); + const params = JSON.parse(bodyString); + + if (params.screen_name) { + const revealed = `"screen_name":"${params.screen_name}"`; + const selectionStart = bodyString.indexOf(revealed); + const selectionEnd = + selectionStart + revealed.length; + const secretResps = [ + bodyString.substring(0, selectionStart), + bodyString.substring(selectionEnd, bodyString.length), + ]; + Host.outputString(JSON.stringify(secretResps)); + } else { + Host.outputString(JSON.stringify(false)); + } +} + +function three() { + const params = JSON.parse(Host.inputString()); + const { notarize } = Host.getFunctions(); + + if (!params) { + Host.outputString(JSON.stringify(false)); + } else { + const mem = Memory.fromString(JSON.stringify({ + ...params, + getSecretResponse: 'parseTwitterResp', + })); + const idOffset = notarize(mem.offset); + const id = Memory.find(idOffset).readString(); + Host.outputString(JSON.stringify(id)); + } +} + +function config() { + Host.outputString( + JSON.stringify({ + title: 'Twitter Profile', + description: 'Notarize ownership of a twitter profile', + icon: 'data:image/png;base64,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', + steps: [ + { + title: 'Visit Twitter website', + cta: 'Go to x.com', + action: 'start', + }, + { + title: 'Collect credentials', + description: "Login to your account if you haven't already", + cta: 'Check cookies', + action: 'two', + }, + { + title: 'Notarize twitter profile', + cta: 'Notarize', + action: 'three', + prover: true, + }, + ], + hostFunctions: ['redirect', 'notarize'], + cookies: ['api.x.com'], + headers: ['api.x.com'], + requests: [ + { + url: 'https://api.x.com/1.1/account/settings.json', + method: 'GET', + }, + ], + }), + ); +} + +module.exports = { start, config, two, three, parseTwitterResp }; diff --git a/package.json b/package.json new file mode 100644 index 0000000..0dd8519 --- /dev/null +++ b/package.json @@ -0,0 +1,17 @@ +{ + "name": "twitter_profile", + "version": "1.0.0", + "description": "Demo TLSNotary plugin to notarize the ownership of a twitter profile", + "main": "src/index.ts", + "scripts": { + "build": "node esbuild.js" + }, + "keywords": [], + "author": "TLSNotary", + "license": "MIT", + "devDependencies": { + "@extism/js-pdk": "^1.0.1", + "esbuild": "^0.19.6", + "typescript": "^5.3.2" + } +} \ No newline at end of file diff --git a/src/index.d.ts b/src/index.d.ts new file mode 100644 index 0000000..5f7f0b9 --- /dev/null +++ b/src/index.d.ts @@ -0,0 +1,15 @@ +declare module 'main' { + // Extism exports take no params and return an I32 + export function start(): I32; + export function two(): I32; + export function parseTwitterResp(): I32; + export function three(): I32; + export function config(): I32; +} + +declare module 'extism:host' { + interface user { + redirect(ptr: I64): void; + notarize(ptr: I64): I64; + } +} diff --git a/src/index.ts b/src/index.ts new file mode 100644 index 0000000..3412f0d --- /dev/null +++ b/src/index.ts @@ -0,0 +1,133 @@ +import { icon } from '../dist/assets/icon'; +import config_json from '../config.json'; +/** + * Plugin configuration + * This configurations defines the plugin, most importantly: + * * the different steps + * * the user data (headers, cookies) it will access + * * the web requests it will query (or notarize) + */ +export function config() { + Host.outputString( + JSON.stringify({ + ...config_json, + icon: icon + }), + ); +} + +function isValidHost(urlString: string) { + const url = new URL(urlString); + return url.hostname === 'twitter.com' || url.hostname === 'x.com'; +} + +/** + * Redirect the browser window to x.com + * This uses the `redirect` host function (see index.d.ts) + */ +function gotoTwitter() { + const { redirect } = Host.getFunctions() as any; + const mem = Memory.fromString('https://x.com'); + redirect(mem.offset); +} + +/** + * Implementation of the first (start) plugin step + */ +export function start() { + if (!isValidHost(Config.get('tabUrl'))) { + gotoTwitter(); + Host.outputString(JSON.stringify(false)); + return; + } + Host.outputString(JSON.stringify(true)); +} + +/** + * Implementation of step "two". + * This step collects and validates authentication cookies and headers for 'api.x.com'. + * If all required information, it creates the request object. + * Note that the url needs to be specified in the `config` too, otherwise the request will be refused. + */ +export function two() { + const cookies = JSON.parse(Config.get('cookies'))['api.x.com']; + const headers = JSON.parse(Config.get('headers'))['api.x.com']; + if ( + !cookies.auth_token || + !cookies.ct0 || + !headers['x-csrf-token'] || + !headers['authorization'] + ) { + Host.outputString(JSON.stringify(false)); + return; + } + + Host.outputString( + JSON.stringify({ + url: 'https://api.x.com/1.1/account/settings.json', + method: 'GET', + headers: { + 'x-twitter-client-language': 'en', + 'x-csrf-token': headers['x-csrf-token'], + Host: 'api.x.com', + authorization: headers.authorization, + Cookie: `lang=en; auth_token=${cookies.auth_token}; ct0=${cookies.ct0}`, + 'Accept-Encoding': 'identity', + Connection: 'close', + }, + secretHeaders: [ + `x-csrf-token: ${headers['x-csrf-token']}`, + `cookie: lang=en; auth_token=${cookies.auth_token}; ct0=${cookies.ct0}`, + `authorization: ${headers.authorization}`, + ], + }), + ); +} + +/** + * This method is used to parse the Twitter response and specify what information is revealed (i.e. **not** redacted) + * This method is optional in the notarization request. When it is not specified nothing is redacted. + * + * In this example it locates the `screen_name` and excludes that range from the revealed response. + */ +export function parseTwitterResp() { + const bodyString = Host.inputString(); + const params = JSON.parse(bodyString); + + // console.log("params"); + // console.log(JSON.stringify(params)); + + if (params.screen_name) { + const revealed = `"screen_name":"${params.screen_name}"`; + const selectionStart = bodyString.indexOf(revealed); + const selectionEnd = + selectionStart + revealed.length; + const secretResps = [ + bodyString.substring(0, selectionStart), + bodyString.substring(selectionEnd, bodyString.length), + ]; + Host.outputString(JSON.stringify(secretResps)); + } else { + Host.outputString(JSON.stringify(false)); + } +} + +/** + * Step 3: calls the `notarize` host function + */ +export function three() { + const params = JSON.parse(Host.inputString()); + const { notarize } = Host.getFunctions() as any; + + if (!params) { + Host.outputString(JSON.stringify(false)); + } else { + const mem = Memory.fromString(JSON.stringify({ + ...params, + getSecretResponse: 'parseTwitterResp', + })); + const idOffset = notarize(mem.offset); + const id = Memory.find(idOffset).readString(); + Host.outputString(JSON.stringify(id)); + } +} diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..a59c4c1 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,14 @@ +{ + "compilerOptions": { + "lib": [], + "types": [ + "@extism/js-pdk" + ], + "noEmit": true, + "resolveJsonModule": true, + "esModuleInterop": true, + }, + "include": [ + "src/**/*" + ] +} \ No newline at end of file