Skip to content

Commit 1dafc13

Browse files
committed
feat: Wasmify supports custom wit folder, world name, debug mode and wasm cache
closes #168
1 parent 0e96fd6 commit 1dafc13

File tree

5 files changed

+96
-76
lines changed

5 files changed

+96
-76
lines changed

packages/homestar/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@
8585
"@types/node": "^20.11.25",
8686
"@types/object-path": "^0.11.4",
8787
"execa": "^8.0.1",
88-
"homestar-runtime": "^0.2.0",
88+
"homestar-runtime": "rc",
8989
"iso-base": "^2.0.1",
9090
"kubo-rpc-client": "^3.0.4",
9191
"p-defer": "^4.0.0",

packages/homestar/src/types.ts

Lines changed: 37 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,44 @@ export type HomestarService = Service<
6161
>
6262

6363
export interface WitOptions {
64-
filePath?: string
64+
entryPoint?: string
6565
source?: string
6666
worldName: string
6767
wasiImports?: Set<string>
6868
}
69+
70+
export interface WasmifyOptions {
71+
/**
72+
* The entry point of the js module
73+
*/
74+
entryPoint: string
75+
/**
76+
* The directory to output the generated files
77+
*
78+
* @default '<cwd>'
79+
*/
80+
outDir?: string
81+
82+
/**
83+
* The name of the generated Wit World
84+
*
85+
* @default '<bundle-hash>'
86+
*/
87+
worldName?: string
88+
89+
/**
90+
* Wit dependencies directory
91+
*
92+
* NOTE: this should be the directory where you run `wit-deps` and this script maybe delete any top level .wit files not inside the deps directory
93+
*
94+
* @default '<path-to-@fission-codes/homestar-wit>'
95+
*/
96+
witPath?: string
97+
98+
/**
99+
* Componentize JS debug flag
100+
*
101+
* @default false
102+
*/
103+
debug?: boolean
104+
}

packages/homestar/src/wasmify/index.js

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
import { writeFile } from 'node:fs/promises'
2+
import fs from 'node:fs'
23
import path from 'path'
34
import { createRequire } from 'node:module'
45
import { base32 } from 'iso-base/rfc4648'
56
import * as esbuild from 'esbuild'
6-
import { deleteAsync } from 'del'
7+
import { deleteSync } from 'del'
78

89
// @ts-ignore
910
import replacePlugin from 'esbuild-plugin-replace-regex'
@@ -63,42 +64,60 @@ async function bundle(filePath) {
6364
/**
6465
* Generate wasm component from a TypeScript file
6566
*
66-
* @param {string} filePath - Path to a TypeScript file
67-
* @param {string} outDir - Path to a directory to write the Wasm component file
67+
* @param {import('../types.js').WasmifyOptions} options
6868
*/
69-
export async function build(filePath, outDir = process.cwd()) {
70-
const pkgPath = require.resolve('@fission-codes/homestar-wit')
71-
const witPath = path.join(pkgPath, '..', '..', 'wit')
72-
let witHash
69+
export async function build(options) {
70+
let {
71+
entryPoint,
72+
outDir = process.cwd(),
73+
debug = false,
74+
worldName,
75+
witPath,
76+
} = options
77+
78+
if (!witPath) {
79+
const pkgPath = require.resolve('@fission-codes/homestar-wit')
80+
witPath = path.join(pkgPath, '..', '..', 'wit')
81+
}
82+
83+
if (!worldName) {
84+
worldName = path.basename(entryPoint, path.extname(entryPoint))
85+
}
7386

7487
// Clean up any old WIT files in the wit directory
7588
// componentize process.exit(1) if it fails so we can't clean up after it
76-
await deleteAsync([`${witPath}/*.wit`], { force: true })
89+
deleteSync([`${witPath}/*.wit`], { force: true })
7790

91+
let witFile
7892
try {
79-
const { hash, src, wasiImports } = await bundle(filePath)
80-
witHash = base32.encode(hash).toLowerCase()
93+
const { hash, src, wasiImports } = await bundle(entryPoint)
94+
const witHash = base32.encode(hash).toLowerCase()
95+
const outPath = path.join(outDir, `${worldName}-${witHash}.wasm`)
96+
witFile = path.join(witPath, `${worldName}-${witHash}.wit`)
8197

82-
// TODO: check the wit hash and only componentize if it has changed
83-
const witSource = await wit({ filePath, worldName: witHash, wasiImports })
84-
const witFile = path.join(witPath, `${witHash}.wit`)
85-
await writeFile(witFile, witSource, 'utf8')
86-
const { component } = await componentize(src, {
87-
witPath,
88-
worldName: witHash,
89-
// debug: true,
90-
sourceName: filePath,
91-
})
92-
const outPath = path.join(outDir, `${witHash}.wasm`)
93-
await writeFile(outPath, component)
98+
if (!fs.existsSync(outPath)) {
99+
const witSource = await wit({
100+
entryPoint,
101+
worldName,
102+
wasiImports,
103+
})
104+
await writeFile(witFile, witSource, 'utf8')
105+
const { component } = await componentize(src, {
106+
witPath,
107+
worldName,
108+
debug,
109+
sourceName: entryPoint,
110+
})
111+
await writeFile(outPath, component)
112+
}
94113

95114
return {
96115
outPath,
97116
witHash,
98117
}
99118
} finally {
100-
if (witHash) {
101-
await deleteAsync([path.join(witPath, `${witHash}.wit`)], { force: true })
119+
if (witFile) {
120+
deleteSync([witFile], { force: true })
102121
}
103122
}
104123
}

packages/homestar/src/wasmify/wit.js

Lines changed: 1 addition & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -62,42 +62,6 @@ function witType(type, msg = '') {
6262
return 'list<u8>'
6363
}
6464

65-
if (type.text === 'Int8Array') {
66-
return 'list<s8>'
67-
}
68-
69-
if (type.text === 'Uint16Array') {
70-
return 'list<u16>'
71-
}
72-
73-
if (type.text === 'Int16Array') {
74-
return 'list<s16>'
75-
}
76-
77-
if (type.text === 'Uint32Array') {
78-
return 'list<u32>'
79-
}
80-
81-
if (type.text === 'Int32Array') {
82-
return 'list<s32>'
83-
}
84-
85-
if (type.text === 'Float32Array') {
86-
return 'list<float32>'
87-
}
88-
89-
if (type.text === 'Float64Array') {
90-
return 'list<float64>'
91-
}
92-
93-
if (type.text === 'BigUint64Array') {
94-
return 'list<u64>'
95-
}
96-
97-
if (type.text === 'BigInt64Array') {
98-
return 'list<s64>'
99-
}
100-
10165
if (type.kind === 'Array' && type.elementType) {
10266
return `list<${witType(type.elementType, msg)}>`
10367
}
@@ -133,7 +97,7 @@ function msg(name, loc, line) {
13397
* @param {import('../types').WitOptions} options
13498
*/
13599
export async function wit(options) {
136-
const { filePath, source, wasiImports, worldName } = options
100+
const { entryPoint: filePath, source, wasiImports, worldName } = options
137101

138102
/** @type {import('@ts-ast-parser/core').AnalyserResult } */
139103
let result

packages/homestar/test/wasmify.node.test.js

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ const HS1_URL = process.env.HS1_URL || 'ws://localhost:8060'
1818
const hs = new Homestar({
1919
transport: new WebsocketTransport(HS1_URL),
2020
})
21+
const outDir = temporaryDirectory()
2122

2223
test.after(() => {
2324
hs.close()
@@ -26,10 +27,10 @@ test.after(() => {
2627
test(
2728
'should wasmify',
2829
async function () {
29-
const { outPath } = await build(
30-
path.join(__dirname, 'fixtures', 'wasmify', 'hello.ts'),
31-
temporaryDirectory()
32-
)
30+
const { outPath } = await build({
31+
entryPoint: path.join(__dirname, 'fixtures', 'wasmify', 'hello.ts'),
32+
outDir,
33+
})
3334

3435
/** @type {import('p-defer').DeferredPromise<string>} */
3536
const prom = pDefer()
@@ -70,10 +71,10 @@ test(
7071
test(
7172
'should wasmify with bytes',
7273
async function () {
73-
const { outPath } = await build(
74-
path.join(__dirname, 'fixtures', 'wasmify', 'hello.ts'),
75-
temporaryDirectory()
76-
)
74+
const { outPath } = await build({
75+
entryPoint: path.join(__dirname, 'fixtures', 'wasmify', 'hello.ts'),
76+
outDir,
77+
})
7778

7879
/** @type {import('p-defer').DeferredPromise<Uint8Array>} */
7980
const prom = pDefer()
@@ -113,14 +114,14 @@ test(
113114
test(
114115
'should wasmify with wit logging',
115116
async function () {
116-
const { outPath } = await build(
117-
path.join(__dirname, 'fixtures', 'wasmify', 'wit-test.ts'),
118-
temporaryDirectory()
119-
)
117+
const { outPath } = await build({
118+
entryPoint: path.join(__dirname, 'fixtures', 'wasmify', 'wit-test.ts'),
119+
outDir,
120+
})
120121

121122
/** @type {import('p-defer').DeferredPromise<number>} */
122123
const prom = pDefer()
123-
const args = [1.1, 1.1]
124+
const args = [1, 1]
124125
const wasmCID = await addFSFileToIPFS(outPath)
125126
const workflow1 = await workflow({
126127
name: 'hash',

0 commit comments

Comments
 (0)