diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 371981eca6..7df1cfdf33 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -266,7 +266,7 @@ jobs: cd /home/runner/.config/azle git clone https://github.com/demergent-labs/wasmedge-quickjs cd wasmedge-quickjs - git checkout 6c81d7e6fe4b22a468beceed0ee697f4163e7ca8 + git checkout c21ff69f442998e4cda4619166e23a9bc91418be - if: ${{ needs.release-candidate-deploy.outputs.should_run_tests && matrix.os == 'ubuntu-latest' }} shell: bash -l {0} run: sudo apt-get install -y podman diff --git a/Cargo.lock b/Cargo.lock index 1ffdc7e6c4..6c64f0bfe7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1744,7 +1744,7 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasmedge_quickjs" version = "0.5.0-alpha" -source = "git+https://github.com/demergent-labs/wasmedge-quickjs?rev=6c81d7e6fe4b22a468beceed0ee697f4163e7ca8#6c81d7e6fe4b22a468beceed0ee697f4163e7ca8" +source = "git+https://github.com/demergent-labs/wasmedge-quickjs?rev=c21ff69f442998e4cda4619166e23a9bc91418be#c21ff69f442998e4cda4619166e23a9bc91418be" dependencies = [ "argparse", "encoding", diff --git a/examples/apollo_server/src/index.ts b/examples/apollo_server/src/index.ts index b8e037c185..31629d5415 100644 --- a/examples/apollo_server/src/index.ts +++ b/examples/apollo_server/src/index.ts @@ -1,6 +1,3 @@ -// TODO once we have dfx 0.16.x working reenable these tests in CI - -import { Server } from 'azle'; import { ApolloServer } from '@apollo/server'; import { expressMiddleware } from '@apollo/server/express4'; import express from 'express'; @@ -86,7 +83,7 @@ const resolvers = { } }; -export default Server(async () => { +async function init() { const app = express(); const server = new ApolloServer({ @@ -98,5 +95,7 @@ export default Server(async () => { app.use(express.json({ limit: '50mb' }), expressMiddleware(server, {})); - return app.listen(); -}); + app.listen(); +} + +init(); diff --git a/examples/audio_and_video/src/backend/server.ts b/examples/audio_and_video/src/backend/server.ts index 02fff7d547..ff196d2aab 100644 --- a/examples/audio_and_video/src/backend/server.ts +++ b/examples/audio_and_video/src/backend/server.ts @@ -1,14 +1,11 @@ -import { Server } from 'azle'; import express from 'express'; import { rangeResponse } from './range_response'; -export default Server(() => { - const app = express(); +const app = express(); - app.use('/media', rangeResponse()); +app.use('/media', rangeResponse()); - app.use(express.static('/dist')); +app.use(express.static('/dist')); - return app.listen(); -}); +app.listen(); diff --git a/examples/autoreload/test/tests.ts b/examples/autoreload/test/tests.ts index b90d87801f..68a86188ec 100644 --- a/examples/autoreload/test/tests.ts +++ b/examples/autoreload/test/tests.ts @@ -4,46 +4,37 @@ dns.setDefaultResultOrder('ipv4first'); import { Test } from 'azle/test'; import { writeFileSync } from 'fs'; -export const originalServerTs = `import { Server } from 'azle'; -import express from 'express'; +export const originalServerTs = `import express from 'express'; -export default Server(() => { const app = express(); app.get('/test', (req, res) => { res.send('test'); }); -return app.listen(); -}); +app.listen(); `; -const testChangedServerTs = `import { Server } from 'azle'; -import express from 'express'; - -export default Server(() => { - const app = express(); +const testChangedServerTs = `import express from 'express'; - app.get('/test-changed', (req, res) => { - res.send('test-changed'); - }); +const app = express(); - return app.listen(); +app.get('/test-changed', (req, res) => { + res.send('test-changed'); }); -`; -const testChangedRapidlyServerTs = `import { Server } from 'azle'; -import express from 'express'; +app.listen(); +`; -export default Server(() => { - const app = express(); +const testChangedRapidlyServerTs = `import express from 'express'; - app.get('/test-changed-rapidly', (req, res) => { - res.send('test-changed-rapidly'); - }); +const app = express(); - return app.listen(); +app.get('/test-changed-rapidly', (req, res) => { + res.send('test-changed-rapidly'); }); + +app.listen(); `; export function getTests(canisterId: string): Test[] { @@ -175,8 +166,6 @@ export function getTests(canisterId: string): Test[] { const response = await fetch(`${origin}/test`); const responseText = await response.text(); - console.log('responseText', responseText); - return { Ok: responseText === 'test' }; diff --git a/examples/ethers/src/index.ts b/examples/ethers/src/index.ts index 2a4d883a4c..d50058a3e9 100644 --- a/examples/ethers/src/index.ts +++ b/examples/ethers/src/index.ts @@ -1,52 +1,49 @@ -import { Server } from 'azle'; import { ethers } from 'ethers'; import express, { Request } from 'express'; -export default Server(() => { - const app = express(); +const app = express(); - app.get( - '/keccak256', - (req: Request, res) => { - res.send(ethers.keccak256(Buffer.from(req.query.message))); - } - ); +app.get( + '/keccak256', + (req: Request, res) => { + res.send(ethers.keccak256(Buffer.from(req.query.message))); + } +); - app.get('/wallet-from-private-key', (req, res) => { - const wallet = new ethers.Wallet( - 'afdfd9c3d2095ef696594f6cedcae59e72dcd697e2a7521b1578140422a4f890' - ); +app.get('/wallet-from-private-key', (req, res) => { + const wallet = new ethers.Wallet( + 'afdfd9c3d2095ef696594f6cedcae59e72dcd697e2a7521b1578140422a4f890' + ); - res.json({ - address: wallet.address, - publicKey: wallet.signingKey.publicKey, - privateKey: wallet.privateKey - }); + res.json({ + address: wallet.address, + publicKey: wallet.signingKey.publicKey, + privateKey: wallet.privateKey }); +}); + +// TODO this will run out of cycles until (hopefully) we move away from crypto-browserify +app.get('/wallet-from-mnemonic', (req, res) => { + const wallet = ethers.Wallet.fromPhrase( + 'indoor dish desk flag debris potato excuse depart ticket judge file exit' + ); - // TODO this will run out of cycles until (hopefully) we move away from crypto-browserify - app.get('/wallet-from-mnemonic', (req, res) => { - const wallet = ethers.Wallet.fromPhrase( - 'indoor dish desk flag debris potato excuse depart ticket judge file exit' - ); - - res.json({ - address: wallet.address, - publicKey: wallet.signingKey.publicKey, - privateKey: wallet.privateKey - }); + res.json({ + address: wallet.address, + publicKey: wallet.signingKey.publicKey, + privateKey: wallet.privateKey }); +}); - // TODO this will run out of cycles until (hopefully) we move away from crypto-browserify - app.get('/wallet-from-random', (req, res) => { - const wallet = ethers.Wallet.createRandom(); +// TODO this will run out of cycles until (hopefully) we move away from crypto-browserify +app.get('/wallet-from-random', (req, res) => { + const wallet = ethers.Wallet.createRandom(); - res.json({ - address: wallet.address, - publicKey: wallet.signingKey.publicKey, - privateKey: wallet.privateKey - }); + res.json({ + address: wallet.address, + publicKey: wallet.signingKey.publicKey, + privateKey: wallet.privateKey }); - - return app.listen(); }); + +app.listen(); diff --git a/examples/express/src/backend/index.ts b/examples/express/src/backend/index.ts index c7bdc4dca5..572ef0dc36 100644 --- a/examples/express/src/backend/index.ts +++ b/examples/express/src/backend/index.ts @@ -1,76 +1,73 @@ -import { Server } from 'azle'; import express, { Request, Response } from 'express'; import { writeFileSync, createReadStream } from 'fs'; let globalState = {}; -export default Server(() => { - writeFileSync( - '/dist/test.html', - `HTML from the filesystem` - ); +writeFileSync( + '/dist/test.html', + `HTML from the filesystem` +); - writeFileSync('/dist/test.txt', 'I have written some text to this file'); +writeFileSync('/dist/test.txt', 'I have written some text to this file'); - writeFileSync('/dist/send-file.txt', 'Does this work too?'); +writeFileSync('/dist/send-file.txt', 'Does this work too?'); - const app = express(); +const app = express(); - app.get('/res-send', (req, res) => { - res.send('Just testing res.send'); - }); +app.get('/res-send', (req, res) => { + res.send('Just testing res.send'); +}); - app.get('/res-write', (req, res) => { - res.write('Why hello there sir'); - res.end(); - }); +app.get('/res-write', (req, res) => { + res.write('Why hello there sir'); + res.end(); +}); - app.get('/file-stream', (req, res) => { - const fileStream = createReadStream('/dist/test.txt'); +app.get('/file-stream', (req, res) => { + const fileStream = createReadStream('/dist/test.txt'); - fileStream.pipe(res); - }); + fileStream.pipe(res); +}); - app.get('/global-state', (req, res) => { - res.json(globalState); - }); +app.get('/global-state', (req, res) => { + res.json(globalState); +}); - app.get('/500', (req, res) => { - res.sendStatus(500); - }); +app.get('/500', (req, res) => { + res.sendStatus(500); +}); - app.get('/send-file', (req, res) => { - res.sendFile('/dist/send-file.txt'); - }); +app.get('/send-file', (req, res) => { + res.sendFile('/dist/send-file.txt'); +}); - app.use(express.json()); +app.use(express.json()); - app.post('/global-state/post', changeGlobalState); - app.put('/global-state/put', changeGlobalState); - app.patch('/global-state/patch', changeGlobalState); +app.post('/global-state/post', changeGlobalState); +app.put('/global-state/put', changeGlobalState); +app.patch('/global-state/patch', changeGlobalState); - app.delete('/global-state/delete', (req, res) => { - globalState = {}; +app.delete('/global-state/delete', (req, res) => { + globalState = {}; - res.json(globalState); - }); + res.json(globalState); +}); - const router = express.Router(); +const router = express.Router(); - router.get('/user/:id', (req, res) => { - res.send(req.params.id); - }); +router.get('/user/:id', (req, res) => { + res.send(req.params.id); +}); - router.get('/post', (req, res) => { - res.send(req.query.id); - }); +router.get('/post', (req, res) => { + res.send(req.query.id); +}); - app.use('/router', router); +app.use('/router', router); - app.use(express.static('/dist')); +app.use(express.static('/dist')); - return app.listen(); -}); +app.listen(); function changeGlobalState(req: Request, res: Response) { globalState = req.body; diff --git a/examples/fetch_ic/src/backend/server.ts b/examples/fetch_ic/src/backend/server.ts index 2be3024f83..44b4ca2fb2 100644 --- a/examples/fetch_ic/src/backend/server.ts +++ b/examples/fetch_ic/src/backend/server.ts @@ -1,134 +1,132 @@ -import { ic, Server } from 'azle'; +import { ic } from 'azle'; import express from 'express'; -export default Server(() => { - const app = express(); +const app = express(); - app.use(express.json()); +app.use(express.json()); - app.get('/headers-array', (req, res) => { - res.setHeader('X-Azle-Response-Key-0', 'X-Azle-Response-Value-0'); - res.setHeader('X-Azle-Response-Key-1', 'X-Azle-Response-Value-1'); - res.setHeader('X-Azle-Response-Key-2', 'X-Azle-Response-Value-2'); +app.get('/headers-array', (req, res) => { + res.setHeader('X-Azle-Response-Key-0', 'X-Azle-Response-Value-0'); + res.setHeader('X-Azle-Response-Key-1', 'X-Azle-Response-Value-1'); + res.setHeader('X-Azle-Response-Key-2', 'X-Azle-Response-Value-2'); - res.json({ - whoami: ic.caller().toString(), - value: req.headers - }); + res.json({ + whoami: ic.caller().toString(), + value: req.headers }); +}); - app.get('/headers-object', (req, res) => { - res.setHeader('X-Azle-Response-Key-0', 'X-Azle-Response-Value-0'); - res.setHeader('X-Azle-Response-Key-1', 'X-Azle-Response-Value-1'); - res.setHeader('X-Azle-Response-Key-2', 'X-Azle-Response-Value-2'); +app.get('/headers-object', (req, res) => { + res.setHeader('X-Azle-Response-Key-0', 'X-Azle-Response-Value-0'); + res.setHeader('X-Azle-Response-Key-1', 'X-Azle-Response-Value-1'); + res.setHeader('X-Azle-Response-Key-2', 'X-Azle-Response-Value-2'); - res.json({ - whoami: ic.caller().toString(), - value: req.headers - }); + res.json({ + whoami: ic.caller().toString(), + value: req.headers }); +}); - app.post('/body-uint8array', (req, res) => { - res.setHeader('X-Azle-Response-Key-0', 'X-Azle-Response-Value-0'); - res.setHeader('X-Azle-Response-Key-1', 'X-Azle-Response-Value-1'); - res.setHeader('X-Azle-Response-Key-2', 'X-Azle-Response-Value-2'); +app.post('/body-uint8array', (req, res) => { + res.setHeader('X-Azle-Response-Key-0', 'X-Azle-Response-Value-0'); + res.setHeader('X-Azle-Response-Key-1', 'X-Azle-Response-Value-1'); + res.setHeader('X-Azle-Response-Key-2', 'X-Azle-Response-Value-2'); - res.json({ - whoami: ic.caller().toString(), - value: req.body - }); + res.json({ + whoami: ic.caller().toString(), + value: req.body }); +}); - app.put('/body-string', (req, res) => { - res.setHeader('X-Azle-Response-Key-0', 'X-Azle-Response-Value-0'); - res.setHeader('X-Azle-Response-Key-1', 'X-Azle-Response-Value-1'); - res.setHeader('X-Azle-Response-Key-2', 'X-Azle-Response-Value-2'); +app.put('/body-string', (req, res) => { + res.setHeader('X-Azle-Response-Key-0', 'X-Azle-Response-Value-0'); + res.setHeader('X-Azle-Response-Key-1', 'X-Azle-Response-Value-1'); + res.setHeader('X-Azle-Response-Key-2', 'X-Azle-Response-Value-2'); - res.json({ - whoami: ic.caller().toString(), - value: req.body - }); + res.json({ + whoami: ic.caller().toString(), + value: req.body }); +}); - app.patch('/body-array-buffer', (req, res) => { - res.setHeader('X-Azle-Response-Key-0', 'X-Azle-Response-Value-0'); - res.setHeader('X-Azle-Response-Key-1', 'X-Azle-Response-Value-1'); - res.setHeader('X-Azle-Response-Key-2', 'X-Azle-Response-Value-2'); +app.patch('/body-array-buffer', (req, res) => { + res.setHeader('X-Azle-Response-Key-0', 'X-Azle-Response-Value-0'); + res.setHeader('X-Azle-Response-Key-1', 'X-Azle-Response-Value-1'); + res.setHeader('X-Azle-Response-Key-2', 'X-Azle-Response-Value-2'); - res.json({ - whoami: ic.caller().toString(), - value: req.body - }); + res.json({ + whoami: ic.caller().toString(), + value: req.body }); +}); - app.delete('/body-blob', (req, res) => { - res.setHeader('X-Azle-Response-Key-0', 'X-Azle-Response-Value-0'); - res.setHeader('X-Azle-Response-Key-1', 'X-Azle-Response-Value-1'); - res.setHeader('X-Azle-Response-Key-2', 'X-Azle-Response-Value-2'); +app.delete('/body-blob', (req, res) => { + res.setHeader('X-Azle-Response-Key-0', 'X-Azle-Response-Value-0'); + res.setHeader('X-Azle-Response-Key-1', 'X-Azle-Response-Value-1'); + res.setHeader('X-Azle-Response-Key-2', 'X-Azle-Response-Value-2'); - res.json({ - whoami: ic.caller().toString(), - value: req.body - }); + res.json({ + whoami: ic.caller().toString(), + value: req.body }); +}); - app.post('/body-data-view', (req, res) => { - res.setHeader('X-Azle-Response-Key-0', 'X-Azle-Response-Value-0'); - res.setHeader('X-Azle-Response-Key-1', 'X-Azle-Response-Value-1'); - res.setHeader('X-Azle-Response-Key-2', 'X-Azle-Response-Value-2'); +app.post('/body-data-view', (req, res) => { + res.setHeader('X-Azle-Response-Key-0', 'X-Azle-Response-Value-0'); + res.setHeader('X-Azle-Response-Key-1', 'X-Azle-Response-Value-1'); + res.setHeader('X-Azle-Response-Key-2', 'X-Azle-Response-Value-2'); - res.json({ - whoami: ic.caller().toString(), - value: req.body - }); + res.json({ + whoami: ic.caller().toString(), + value: req.body }); +}); - app.get('/url-query-params-get', (req, res) => { - res.setHeader('X-Azle-Response-Key-0', 'X-Azle-Response-Value-0'); - res.setHeader('X-Azle-Response-Key-1', 'X-Azle-Response-Value-1'); - res.setHeader('X-Azle-Response-Key-2', 'X-Azle-Response-Value-2'); +app.get('/url-query-params-get', (req, res) => { + res.setHeader('X-Azle-Response-Key-0', 'X-Azle-Response-Value-0'); + res.setHeader('X-Azle-Response-Key-1', 'X-Azle-Response-Value-1'); + res.setHeader('X-Azle-Response-Key-2', 'X-Azle-Response-Value-2'); - res.json({ - whoami: ic.caller().toString(), - value: req.query - }); + res.json({ + whoami: ic.caller().toString(), + value: req.query }); +}); - app.post('/url-query-params-post', (req, res) => { - res.setHeader('X-Azle-Response-Key-0', 'X-Azle-Response-Value-0'); - res.setHeader('X-Azle-Response-Key-1', 'X-Azle-Response-Value-1'); - res.setHeader('X-Azle-Response-Key-2', 'X-Azle-Response-Value-2'); +app.post('/url-query-params-post', (req, res) => { + res.setHeader('X-Azle-Response-Key-0', 'X-Azle-Response-Value-0'); + res.setHeader('X-Azle-Response-Key-1', 'X-Azle-Response-Value-1'); + res.setHeader('X-Azle-Response-Key-2', 'X-Azle-Response-Value-2'); - res.json({ - whoami: ic.caller().toString(), - value: req.query - }); + res.json({ + whoami: ic.caller().toString(), + value: req.query }); +}); - app.get('/not-authorized-get', (_req, res) => { - res.status(401).send('Not Authorized'); - }); +app.get('/not-authorized-get', (_req, res) => { + res.status(401).send('Not Authorized'); +}); - app.post('/not-authorized-post', (_req, res) => { - res.status(401).send('Not Authorized'); - }); +app.post('/not-authorized-post', (_req, res) => { + res.status(401).send('Not Authorized'); +}); - app.head('/head', (_req, res) => { - res.setHeader('X-Azle-Response-Key-0', 'X-Azle-Response-Value-0'); - res.setHeader('X-Azle-Response-Key-1', 'X-Azle-Response-Value-1'); - res.setHeader('X-Azle-Response-Key-2', 'X-Azle-Response-Value-2'); - res.end(); - }); +app.head('/head', (_req, res) => { + res.setHeader('X-Azle-Response-Key-0', 'X-Azle-Response-Value-0'); + res.setHeader('X-Azle-Response-Key-1', 'X-Azle-Response-Value-1'); + res.setHeader('X-Azle-Response-Key-2', 'X-Azle-Response-Value-2'); + res.end(); +}); - app.options('/options', (_req, res) => { - res.setHeader( - 'X-Azle-Response-Key-Options', - 'X-Azle-Response-Value-Options' - ); - res.end(); - }); +app.options('/options', (_req, res) => { + res.setHeader( + 'X-Azle-Response-Key-Options', + 'X-Azle-Response-Value-Options' + ); + res.end(); +}); - app.use(express.static('/dist')); +app.use(express.static('/dist')); - return app.listen(); -}); +app.listen(); diff --git a/examples/file_protocol/src/backend.ts b/examples/file_protocol/src/backend.ts index e8c362d472..3e4561b693 100644 --- a/examples/file_protocol/src/backend.ts +++ b/examples/file_protocol/src/backend.ts @@ -1,50 +1,47 @@ -import { Server } from 'azle'; import express, { Request } from 'express'; -export default Server(() => { - const app = express(); - - app.use(express.json()); - - app.get( - '/read-test0', - async (req: Request, res) => { - const response = await fetch(`file://${req.query.filename}`); - const responseText = await response.text(); - - res.send(responseText); - } - ); - - app.post( - '/read-test2', - async (req: Request, res) => { - const response = await fetch(`file://${req.body.filename}`); - const responseText = await response.text(); - - res.send(responseText); - } - ); - - app.put( - '/read-test3', - async (req: Request, res) => { - const response = await fetch(`file://${req.body.filename}`); - const responseText = await response.text(); - - res.send(responseText); - } - ); - - app.patch( - '/read-test5', - async (req: Request, res) => { - const response = await fetch(`file://${req.body.filename}`); - const responseText = await response.text(); - - res.send(responseText); - } - ); - - return app.listen(); -}); +const app = express(); + +app.use(express.json()); + +app.get( + '/read-test0', + async (req: Request, res) => { + const response = await fetch(`file://${req.query.filename}`); + const responseText = await response.text(); + + res.send(responseText); + } +); + +app.post( + '/read-test2', + async (req: Request, res) => { + const response = await fetch(`file://${req.body.filename}`); + const responseText = await response.text(); + + res.send(responseText); + } +); + +app.put( + '/read-test3', + async (req: Request, res) => { + const response = await fetch(`file://${req.body.filename}`); + const responseText = await response.text(); + + res.send(responseText); + } +); + +app.patch( + '/read-test5', + async (req: Request, res) => { + const response = await fetch(`file://${req.body.filename}`); + const responseText = await response.text(); + + res.send(responseText); + } +); + +app.listen(); diff --git a/examples/fs/src/index.ts b/examples/fs/src/index.ts index 93d2a2b64c..c3c249fb77 100644 --- a/examples/fs/src/index.ts +++ b/examples/fs/src/index.ts @@ -1,4 +1,3 @@ -import { Server } from 'azle'; import express, { Request } from 'express'; import { createReadStream, @@ -12,161 +11,156 @@ import { } from 'fs'; import { mkdir, readFile, rmdir, unlink, writeFile } from 'fs/promises'; -export default Server(() => { - const app = express(); +const app = express(); - app.use(express.json()); +app.use(express.json()); - app.get( - '/read-file-sync', - (req: Request, res) => { - const contents = readFileSync(req.query.filename).toString(); +app.get( + '/read-file-sync', + (req: Request, res) => { + const contents = readFileSync(req.query.filename).toString(); - res.send(contents); - } - ); - - app.get( - '/read-file', - async (req: Request, res) => { - const contents = (await readFile(req.query.filename)).toString(); - - res.send(contents); - } - ); - - app.post( - '/write-file-sync', - (req: Request, res) => { - req.body.files.forEach(([filename, contents]) => { - writeFileSync(filename, contents); - }); - - res.send(`No. files written: ${req.body.files.length}`); - } - ); - - app.post( - '/write-file', - async (req: Request, res) => { - for (const [filename, contents] of req.body.files) { - await writeFile(filename, contents); - } - - res.send(`No. files written: ${req.body.files.length}`); - } - ); - - app.post( - '/unlink-sync', - (req: Request, res) => { - unlinkSync(req.query.filename); - - res.send(`File ${req.query.filename} deleted`); - } - ); - - app.post( - '/unlink', - async (req: Request, res) => { - await unlink(req.query.filename); + res.send(contents); + } +); - res.send(`File ${req.query.filename} deleted`); - } - ); +app.get( + '/read-file', + async (req: Request, res) => { + const contents = (await readFile(req.query.filename)).toString(); - app.post( - '/rmdir-sync', - (req: Request, res) => { - rmdirSync(req.query.dirname); - - res.send(`Directory ${req.query.dirname} deleted`); - } - ); - - app.post( - '/rmdir', - async (req: Request, res) => { - await rmdir(req.query.dirname); - - res.send(`Directory ${req.query.dirname} deleted`); - } - ); + res.send(contents); + } +); - app.post( - '/mkdir-sync', - (req: Request, res) => { - mkdirSync(req.query.dirname); - - res.send(`Directory ${req.query.dirname} created`); - } - ); - - app.post( - '/mkdir', - async (req: Request, res) => { - await mkdir(req.query.dirname); +app.post( + '/write-file-sync', + (req: Request, res) => { + req.body.files.forEach(([filename, contents]) => { + writeFileSync(filename, contents); + }); - res.send(`Directory ${req.query.dirname} created`); - } - ); + res.send(`No. files written: ${req.body.files.length}`); + } +); - app.get( - '/exists-sync', - (req: Request, res) => { - res.send(existsSync(req.query.name)); +app.post( + '/write-file', + async (req: Request, res) => { + for (const [filename, contents] of req.body.files) { + await writeFile(filename, contents); } - ); - - app.get( - '/create-read-stream-larger-than-high-water-mark-chunked', - async (req, res) => { - const fileLength = statSync('/image.jpg').size; - const chunkSize = 2_000_000; - - for (let i = 0; i < fileLength; i += chunkSize) { - const fileStream = createReadStream('/image.jpg', { - start: i, - end: i + chunkSize - 1 - }); - - for await (const data of fileStream) { - res.write(data); - } - } - - res.end(); - } - ); - - app.get( - '/create-read-stream-larger-than-high-water-mark', - async (req, res) => { - const fileStream = createReadStream('/image.jpg'); + res.send(`No. files written: ${req.body.files.length}`); + } +); + +app.post( + '/unlink-sync', + (req: Request, res) => { + unlinkSync(req.query.filename); + + res.send(`File ${req.query.filename} deleted`); + } +); + +app.post( + '/unlink', + async (req: Request, res) => { + await unlink(req.query.filename); + + res.send(`File ${req.query.filename} deleted`); + } +); + +app.post( + '/rmdir-sync', + (req: Request, res) => { + rmdirSync(req.query.dirname); + + res.send(`Directory ${req.query.dirname} deleted`); + } +); + +app.post( + '/rmdir', + async (req: Request, res) => { + await rmdir(req.query.dirname); + + res.send(`Directory ${req.query.dirname} deleted`); + } +); + +app.post( + '/mkdir-sync', + (req: Request, res) => { + mkdirSync(req.query.dirname); + + res.send(`Directory ${req.query.dirname} created`); + } +); + +app.post( + '/mkdir', + async (req: Request, res) => { + await mkdir(req.query.dirname); + + res.send(`Directory ${req.query.dirname} created`); + } +); + +app.get( + '/exists-sync', + (req: Request, res) => { + res.send(existsSync(req.query.name)); + } +); + +app.get( + '/create-read-stream-larger-than-high-water-mark-chunked', + async (req, res) => { + const fileLength = statSync('/image.jpg').size; + + const chunkSize = 2_000_000; + + for (let i = 0; i < fileLength; i += chunkSize) { + const fileStream = createReadStream('/image.jpg', { + start: i, + end: i + chunkSize - 1 + }); for await (const data of fileStream) { res.write(data); } - - res.end(); } - ); - app.get('/high-water-mark-boundary', async (req, res) => { - const fileStream = createReadStream('/image.jpg', { - start: 0, - end: 16_384 - }); + res.end(); + } +); - let chunk = Buffer.from([]); +app.get('/create-read-stream-larger-than-high-water-mark', async (req, res) => { + const fileStream = createReadStream('/image.jpg'); - for await (const data of fileStream) { - chunk = data; - } + for await (const data of fileStream) { + res.write(data); + } - res.send(chunk.length.toString()); + res.end(); +}); + +app.get('/high-water-mark-boundary', async (req, res) => { + const fileStream = createReadStream('/image.jpg', { + start: 0, + end: 16_384 }); - return app.listen(); + let chunk = Buffer.from([]); + + for await (const data of fileStream) { + chunk = data; + } + + res.send(chunk.length.toString()); }); + +app.listen(); diff --git a/examples/hello_world/src/backend/index.ts b/examples/hello_world/src/backend/index.ts index 1e3c4a987e..25c9c79575 100644 --- a/examples/hello_world/src/backend/index.ts +++ b/examples/hello_world/src/backend/index.ts @@ -1,26 +1,23 @@ -import { Server } from 'azle'; import express, { Request } from 'express'; let db = { hello: '' }; -export default Server(() => { - const app = express(); +const app = express(); - app.use(express.json()); +app.use(express.json()); - app.get('/db', (req, res) => { - res.json(db); - }); +app.get('/db', (_req, res) => { + res.json(db); +}); - app.post('/db/update', (req: Request, res) => { - db = req.body; +app.post('/db/update', (req: Request, res) => { + db = req.body; - res.json(db); - }); + res.json(db); +}); - app.use(express.static('/dist')); +app.use(express.static('/dist')); - return app.listen(); -}); +app.listen(); diff --git a/examples/ic_evm_rpc/src/server.ts b/examples/ic_evm_rpc/src/server.ts index 46e4d9c9a5..c717d9f303 100644 --- a/examples/ic_evm_rpc/src/server.ts +++ b/examples/ic_evm_rpc/src/server.ts @@ -1,4 +1,4 @@ -import { ic, jsonStringify, Server } from 'azle'; +import { ic, jsonStringify } from 'azle'; import { ethers } from 'ethers'; import express, { Request } from 'express'; @@ -12,138 +12,133 @@ import { ecdsaPublicKey } from './tecdsa/ecdsa_public_key'; import { signWithEcdsa } from './tecdsa/sign_with_ecdsa'; import { calculateRsvForTEcdsa } from './tecdsa/calculate_rsv_for_tecdsa'; -export default Server(() => { - const app = express(); +const app = express(); - app.use(express.json()); +app.use(express.json()); - app.post('/caller-address', async (_req, res) => { - const address = ethers.computeAddress( - ethers.hexlify(await ecdsaPublicKey([ic.caller().toUint8Array()])) - ); +app.post('/caller-address', async (_req, res) => { + const address = ethers.computeAddress( + ethers.hexlify(await ecdsaPublicKey([ic.caller().toUint8Array()])) + ); - res.send(address); - }); + res.send(address); +}); - app.post('/canister-address', async (_req, res) => { - if (canisterAddress.value === null) { - canisterAddress.value = ethers.computeAddress( - ethers.hexlify(await ecdsaPublicKey([ic.id().toUint8Array()])) - ); - } +app.post('/canister-address', async (_req, res) => { + if (canisterAddress.value === null) { + canisterAddress.value = ethers.computeAddress( + ethers.hexlify(await ecdsaPublicKey([ic.id().toUint8Array()])) + ); + } - res.send(canisterAddress.value); - }); + res.send(canisterAddress.value); +}); - app.post( - '/address-balance', - async (req: Request, res) => { - const balance = await ethGetBalance(req.body.address); +app.post( + '/address-balance', + async (req: Request, res) => { + const balance = await ethGetBalance(req.body.address); + + res.send(jsonStringify(balance)); + } +); + +app.post( + '/transfer-from-sepolia-faucet-wallet', + async (req: Request, res) => { + // address: 0x9Ac70EE21bE697173b74aF64399d850038697FD3 + const wallet = new ethers.Wallet( + '0x6f784763681eb712dc16714b8ade23f6c982a5872d054059dd64d0ec4e52be33' + ); - res.send(jsonStringify(balance)); + const to = req.body.to; + const value = ethers.parseEther(req.body.value); + const maxPriorityFeePerGas = await ethMaxPriorityFeePerGas(); + const baseFeePerGas = BigInt( + (await ethFeeHistory()).Consistent?.Ok[0].baseFeePerGas[0] + ); + const maxFeePerGas = baseFeePerGas * 2n + maxPriorityFeePerGas; + const gasLimit = 21_000n; + const nonce = await ethGetTransactionCount(wallet.address); + const rawTransaction = await wallet.signTransaction({ + to, + value, + maxPriorityFeePerGas, + maxFeePerGas, + gasLimit, + nonce, + chainId + }); + + const result = await ethSendRawTransaction(rawTransaction); + + if (result.Consistent?.Ok?.Ok === null) { + res.send('transaction sent'); + } else { + res.status(500).send('transaction failed'); } - ); + } +); - app.post( - '/transfer-from-sepolia-faucet-wallet', - async (req: Request, res) => { - // address: 0x9Ac70EE21bE697173b74aF64399d850038697FD3 - const wallet = new ethers.Wallet( - '0x6f784763681eb712dc16714b8ade23f6c982a5872d054059dd64d0ec4e52be33' - ); - - const to = req.body.to; - const value = ethers.parseEther(req.body.value); - const maxPriorityFeePerGas = await ethMaxPriorityFeePerGas(); - const baseFeePerGas = BigInt( - (await ethFeeHistory()).Consistent?.Ok[0].baseFeePerGas[0] +app.post( + '/transfer-from-canister', + async (req: Request, res) => { + if (canisterAddress.value === null) { + canisterAddress.value = ethers.computeAddress( + ethers.hexlify(await ecdsaPublicKey([ic.id().toUint8Array()])) ); - const maxFeePerGas = baseFeePerGas * 2n + maxPriorityFeePerGas; - const gasLimit = 21_000n; - const nonce = await ethGetTransactionCount(wallet.address); - const rawTransaction = await wallet.signTransaction({ - to, - value, - maxPriorityFeePerGas, - maxFeePerGas, - gasLimit, - nonce, - chainId - }); - - const result = await ethSendRawTransaction(rawTransaction); - - if (result.Consistent?.Ok?.Ok === null) { - res.send('transaction sent'); - } else { - res.status(500).send('transaction failed'); - } } - ); - app.post( - '/transfer-from-canister', - async (req: Request, res) => { - if (canisterAddress.value === null) { - canisterAddress.value = ethers.computeAddress( - ethers.hexlify( - await ecdsaPublicKey([ic.id().toUint8Array()]) - ) - ); - } - - const to = req.body.to; - const value = ethers.parseEther(req.body.value); - const maxPriorityFeePerGas = await ethMaxPriorityFeePerGas(); - const baseFeePerGas = BigInt( - (await ethFeeHistory()).Consistent?.Ok[0].baseFeePerGas[0] - ); - const maxFeePerGas = baseFeePerGas * 2n + maxPriorityFeePerGas; - const gasLimit = 21_000n; - const nonce = await ethGetTransactionCount(canisterAddress.value); - - let tx = ethers.Transaction.from({ - to, - value, - maxPriorityFeePerGas, - maxFeePerGas, - gasLimit, - nonce, - chainId - }); - - const unsignedSerializedTx = tx.unsignedSerialized; - const unsignedSerializedTxHash = - ethers.keccak256(unsignedSerializedTx); - - const signedSerializedTxHash = await signWithEcdsa( - [ic.id().toUint8Array()], - ethers.getBytes(unsignedSerializedTxHash) - ); + const to = req.body.to; + const value = ethers.parseEther(req.body.value); + const maxPriorityFeePerGas = await ethMaxPriorityFeePerGas(); + const baseFeePerGas = BigInt( + (await ethFeeHistory()).Consistent?.Ok[0].baseFeePerGas[0] + ); + const maxFeePerGas = baseFeePerGas * 2n + maxPriorityFeePerGas; + const gasLimit = 21_000n; + const nonce = await ethGetTransactionCount(canisterAddress.value); + + let tx = ethers.Transaction.from({ + to, + value, + maxPriorityFeePerGas, + maxFeePerGas, + gasLimit, + nonce, + chainId + }); + + const unsignedSerializedTx = tx.unsignedSerialized; + const unsignedSerializedTxHash = ethers.keccak256(unsignedSerializedTx); + + const signedSerializedTxHash = await signWithEcdsa( + [ic.id().toUint8Array()], + ethers.getBytes(unsignedSerializedTxHash) + ); - const { r, s, v } = calculateRsvForTEcdsa( - canisterAddress.value, - unsignedSerializedTxHash, - signedSerializedTxHash - ); + const { r, s, v } = calculateRsvForTEcdsa( + canisterAddress.value, + unsignedSerializedTxHash, + signedSerializedTxHash + ); - tx.signature = { - r, - s, - v - }; + tx.signature = { + r, + s, + v + }; - const rawTransaction = tx.serialized; + const rawTransaction = tx.serialized; - const result = await ethSendRawTransaction(rawTransaction); + const result = await ethSendRawTransaction(rawTransaction); - if (result.Consistent?.Ok?.Ok === null) { - res.send('transaction sent'); - } else { - res.status(500).send('transaction failed'); - } + if (result.Consistent?.Ok?.Ok === null) { + res.send('transaction sent'); + } else { + res.status(500).send('transaction failed'); } - ); + } +); - return app.listen(); -}); +app.listen(); diff --git a/examples/internet_identity/src/backend/server.ts b/examples/internet_identity/src/backend/server.ts index 29454109d2..64527740fe 100644 --- a/examples/internet_identity/src/backend/server.ts +++ b/examples/internet_identity/src/backend/server.ts @@ -1,14 +1,12 @@ -import { ic, Server } from 'azle'; +import { ic } from 'azle'; import express from 'express'; -export default Server(() => { - const app = express(); +const app = express(); - app.get('/whoami', (req, res) => { - res.send(ic.caller().toString()); - }); +app.get('/whoami', (req, res) => { + res.send(ic.caller().toString()); +}); - app.use(express.static('/dist')); +app.use(express.static('/dist')); - return app.listen(); -}); +app.listen(); diff --git a/examples/sqlite/src/index.ts b/examples/sqlite/src/index.ts index 6277b0122a..ba1c9c9fb6 100644 --- a/examples/sqlite/src/index.ts +++ b/examples/sqlite/src/index.ts @@ -1,25 +1,22 @@ -import { Server } from 'azle'; import express from 'express'; import initSqlJs from 'sql.js/dist/sql-asm.js'; -export default Server(async () => { - const app = express(); +const app = express(); - app.post('/', async (req, res) => { - const SQL = await initSqlJs({}); +app.post('/', async (_req, res) => { + const SQL = await initSqlJs({}); - const db = new SQL.Database(); + const db = new SQL.Database(); - db.run(` - CREATE TABLE users - ( - id INTEGER PRIMARY KEY AUTOINCREMENT, - username TEXT NOT NULL UNIQUE - ); - `); + db.run(` + CREATE TABLE users + ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + username TEXT NOT NULL UNIQUE + ); + `); - res.send('Hello world'); - }); - - return app.listen(); + res.send('Hello world'); }); + +app.listen(); diff --git a/examples/tfjs/src/api.ts b/examples/tfjs/src/api.ts index 37596215fc..ae171fa2f7 100644 --- a/examples/tfjs/src/api.ts +++ b/examples/tfjs/src/api.ts @@ -1,8 +1,8 @@ -import { ic, Server } from 'azle'; +import { ic } from 'azle'; import express from 'express'; import * as tf from '@tensorflow/tfjs'; -export default Server(async () => { +async function init() { const app = express(); app.use(express.json()); @@ -29,5 +29,7 @@ export default Server(async () => { res.send('Prediction not yet implemented'); }); - return app.listen(); -}); + app.listen(); +} + +init(); diff --git a/examples/web_assembly/src/index.ts b/examples/web_assembly/src/index.ts index 973f9e683d..dae70e854f 100644 --- a/examples/web_assembly/src/index.ts +++ b/examples/web_assembly/src/index.ts @@ -1,47 +1,40 @@ -import { Server } from 'azle'; import express from 'express'; import { compile } from 'watr'; -export default Server(() => { - const app = express(); - - app.get('/', async (req, res) => { - const buffer = compile(` - ( - func (export "double") (param i32) (result i32) - (i32.mul (local.get 0) (i32.const 2)) - ) - ( - func (export "add") (param i32) (param i32) (result i32) - (i32.add (local.get 0) (local.get 1)) - ) - ( - func (export "quadruple") (param i32) (result i32) - (i32.mul (local.get 0) (i32.const 4)) - ) - `); - - const { instance } = (await WebAssembly.instantiate( - buffer.buffer - )) as any; - - const doubleResult = instance.exports.double(Number(req.query.num1)); - - const addResult = instance.exports.add( - Number(req.query.num1), - Number(req.query.num2) - ); - - const quadrupleResult = instance.exports.quadruple( - Number(req.query.num3) - ); - - res.json({ - doubleResult, - addResult, - quadrupleResult - }); +const app = express(); + +app.get('/', async (req, res) => { + const buffer = compile(` + ( + func (export "double") (param i32) (result i32) + (i32.mul (local.get 0) (i32.const 2)) + ) + ( + func (export "add") (param i32) (param i32) (result i32) + (i32.add (local.get 0) (local.get 1)) + ) + ( + func (export "quadruple") (param i32) (result i32) + (i32.mul (local.get 0) (i32.const 4)) + ) + `); + + const { instance } = (await WebAssembly.instantiate(buffer.buffer)) as any; + + const doubleResult = instance.exports.double(Number(req.query.num1)); + + const addResult = instance.exports.add( + Number(req.query.num1), + Number(req.query.num2) + ); + + const quadrupleResult = instance.exports.quadruple(Number(req.query.num3)); + + res.json({ + doubleResult, + addResult, + quadrupleResult }); - - return app.listen(); }); + +app.listen(); diff --git a/src/compiler/Dockerfile b/src/compiler/Dockerfile index c920ab596d..feef4a4b75 100644 --- a/src/compiler/Dockerfile +++ b/src/compiler/Dockerfile @@ -18,7 +18,7 @@ RUN rustup target add wasm32-wasi RUN cargo install --git https://github.com/wasm-forge/wasi2ic --rev 806c3558aad24224852a9582f018178402cb3679 # This is all on one line so that when the commit is changed Docker will rerun the clone -RUN git clone https://github.com/demergent-labs/wasmedge-quickjs && cd wasmedge-quickjs && git checkout 6c81d7e6fe4b22a468beceed0ee697f4163e7ca8 +RUN git clone https://github.com/demergent-labs/wasmedge-quickjs && cd wasmedge-quickjs && git checkout c21ff69f442998e4cda4619166e23a9bc91418be RUN mkdir /global_target_dir diff --git a/src/compiler/compile_typescript_code.ts b/src/compiler/compile_typescript_code.ts index c72a6ebbc4..2ad9a3b33e 100644 --- a/src/compiler/compile_typescript_code.ts +++ b/src/compiler/compile_typescript_code.ts @@ -11,34 +11,40 @@ export function compileTypeScriptToJavaScript( // Trying to make sure that all globalThis dependencies are defined // Before the developer imports azle on their own import 'azle'; - import { ic } from 'azle'; + import { ic, Server } from 'azle'; import { toDidString } from 'azle/src/lib/candid/did_file/to_did_string'; import { DidVisitor, getDefaultVisitorData } from 'azle/src/lib/candid/did_file/visitor'; export { Principal } from '@dfinity/principal'; export * from './${main}'; - import CanisterMethods from './${main}'; + import * as CanisterMethods from './${main}'; - export const canisterMethods = CanisterMethods(); - - globalThis.candidInfoFunction = () => { - const candidInfo = canisterMethods.getIdl([]).accept(new DidVisitor(), { - ...getDefaultVisitorData(), - isFirstService: true, - systemFuncs: canisterMethods.getSystemFunctionIdls() - }); - - return JSON.stringify({ - candid: toDidString(candidInfo), - canisterMethods: { - // TODO The spread is because canisterMethods is a function with properties - // TODO we should probably just grab the props out that we need - ...canisterMethods - } - }); - }; - - // TODO I do not know how to get the module exports yet with wasmedge_quickjs - globalThis.exports.canisterMethods = canisterMethods; + // TODO This setTimeout is here to allow asynchronous operations during canister initialization + // for Server canisters that have chosen not to use export default Server + // This seems to work no matter how many async tasks are awaited, but I am still unsure about how it will + // behave in all async situations + setTimeout(() => { + const canisterMethods = CanisterMethods.default !== undefined ? CanisterMethods.default() : Server(() => globalThis._azleNodeServer)(); + + globalThis.candidInfoFunction = () => { + const candidInfo = canisterMethods.getIdl([]).accept(new DidVisitor(), { + ...getDefaultVisitorData(), + isFirstService: true, + systemFuncs: canisterMethods.getSystemFunctionIdls() + }); + + return JSON.stringify({ + candid: toDidString(candidInfo), + canisterMethods: { + // TODO The spread is because canisterMethods is a function with properties + // TODO we should probably just grab the props out that we need + ...canisterMethods + } + }); + }; + + // TODO I do not know how to get the module exports yet with wasmedge_quickjs + globalThis.exports.canisterMethods = canisterMethods; + }); `; const bundledJavaScript = bundleFromString( diff --git a/src/compiler/rust/canister/Cargo.toml b/src/compiler/rust/canister/Cargo.toml index 6421c0fe7e..2224d0536d 100644 --- a/src/compiler/rust/canister/Cargo.toml +++ b/src/compiler/rust/canister/Cargo.toml @@ -24,5 +24,5 @@ ic-wasi-polyfill = { git = "https://github.com/wasm-forge/ic-wasi-polyfill", rev "transient", ] } -wasmedge_quickjs = { git = "https://github.com/demergent-labs/wasmedge-quickjs", rev = "6c81d7e6fe4b22a468beceed0ee697f4163e7ca8" } +wasmedge_quickjs = { git = "https://github.com/demergent-labs/wasmedge-quickjs", rev = "c21ff69f442998e4cda4619166e23a9bc91418be" } # wasmedge_quickjs = { path = "/home/wasmedge-quickjs" }