Using deno in deveopment

Hi all, I’ve been using Deno the past few days for development in an Elm project and would like to report on my experience. In a word: Its great!!!. But first:

Deno is a runtime for JavaScript and TypeScript that is based on the V8 JavaScript engine and the Rust programming language. It was created by Ryan Dahl, original creator of Node.js, and is focused on productivity.

Below is my experience in two parts.

Part 1: Building a server

I started off using Deno to build a little server that talks to an Elm app. The code is written in typescript, though one can also use javascript. Here is the repo, which I post with following notes, caveats, and lame excuses:

  1. My first attempt using Deno, Typescript.

  2. The code in src is working, while that in src2 is a rewrite-in-progress based on a different data model.

  3. I had one issue that held me up for a day: you have to write your own OPTIONS handler. Thanks to all on Slack who helped me get through this.

  4. The server uses the Oak middleware package.

Part 2: Script runner

I’ve always preferred writing little shell scripts to manage development. That said, the script runner part of npm is really nice, despite the heavy baggage that comes with npm. Yes, node_modules, I am talking about you!

It turns out that there is another way: use velociraptor. The linked article, by velociraptor’s creator, Umberto Pepato (@umbo) explains how to install it and how to use it. In brief, you create a yaml file which is the analogue of the scripts part of package.json. Below is mine. It contains mixture of deno stuff and shell scripts. The first clause, start ... could also have been written as a single line.

start: deno run src/server.ts --allow-net --allow-env ...

You run scripts by saying, for example, vr start. Three cheers for Ryan Dahl and Umberto Pepato for creating these wonderful tools.

scripts.yaml

scripts:
  start:
    cmd: src/server.ts
    allow:
      - net
      - env
      - write
      - read
   test:
    cmd: src2/file.ts
    allow:
      - read
      - write
  ssh: ssh root@161.35.125.40
  upload: scp -r ./src root@161.35.125.40:/root/docserver
  upone: scp $1 root@161.35.125.40:/root/docserver
6 Likes

Have you tried running a compiled elm.js under Deno? I mean a headless Platform.worker program.

I did try on one project – wasn’t able to make it work. Certainly not in the obvious way of replacing node by deno in the script that runs the app.

Interesting, do you recall what error it gave?

I have managed to get an elm.js to run under 2 different javascript engines that are part of Java, so running on the JVM. These were browser programs, so I had to do a little bit of hacking to make sure things like window and document were sufficiently mocked up. If Deno can run javascript I don’t expect it would take much to get it to run an elm.js.

Below are two different error responses. In the first, I would generally say node run .... However, rep.js has

const repl = require('repl');
const fs = require('fs')

and the require('repl') might be problematic (dunno).

 $ deno run  ex/repl.js
   error: Uncaught SyntaxError: Duplicate parameter name not allowed in this context
   function eval(cmd, _, _,  callback) {
                      ^
    at file:///Users/jxxcarlson/dev/elm/projects/xmark/blockParser/repl/ex/repl.js:13:23

In the second example, which is problably not a good test, I try to run the compiled Plaftform.worker propgram directly. It was set up to communicate with repl.js, so if successful, it should not do anything useful. However, node ex/repl.js gives no errors.

Later today I will try a bare-bones example.

 $ deno run ex/main.js
Compiled in DEV mode. Follow the advice at https://elm-lang.org/0.19.1/optimize for better performance and smaller assets.
error: Uncaught TypeError: Cannot read property 'Elm' of undefined
	scope['Elm']
	     ^
    at _Platform_export (file:///Users/jxxcarlson/dev/elm/projects/xmark/blockParser/repl/ex/main.js:2342:7)
    at file:///Users/jxxcarlson/dev/elm/projects/xmark/blockParser/repl/ex/main.js:6351:1
    at file:///Users/jxxcarlson/dev/elm/projects/xmark/blockParser/repl/ex/main.js:6352:55

I have a script (although it runs in node alas) that converts elm generated javascript files into es modules:

const fs = require('fs');
const {promisify} = require('util');

const readFile = promisify(fs.readFile);
const writeFile = promisify(fs.writeFile);

(async () => {
  const elmPath = process.argv[2];

  console.log(`Making ${elmPath} into a es module...`);

  const elmEs3 = await readFile(elmPath, 'utf8');

  const elmEsm =
    '\n' +
    'const scope = {};\n' +
    elmEs3.replace('}(this));', '}(scope));') +
    'export const { Elm } = scope;\n' +
    '\n';

  await writeFile(elmPath, elmEsm);

  console.log('Finished.');
})();

I think this would fix the scope issues. (Elm uses the this === window thing to do global exports but deno runs everything as an es module so this === undefined at the module level).


Edit: maybe this (untested) works in deno

import { readFileStr, writeFileStr } from 'https://deno.land/std/fs/mod.ts';

const elmPath = Deno.args[0];

console.log(`Making ${elmPath} into a es module...`);

const elmEs3 = await readFileStr(elmPath);

const elmEsm = `
const scope = {}
${elmEs3.replace('}(this));', '}(scope));')}

export const { Elm } = scope;
`;

await writeFileStr(elmPath, elmEsm);
3 Likes

Thanks! I will definitely use this.

1 Like

This topic was automatically closed 10 days after the last reply. New replies are no longer allowed.