Skip to content

Instantly share code, notes, and snippets.

@timreichen
Last active April 17, 2022 18:59
Show Gist options
  • Save timreichen/4fe7fb0480dc408aedca4b5f8aa57e7f to your computer and use it in GitHub Desktop.
Save timreichen/4fe7fb0480dc408aedca4b5f8aa57e7f to your computer and use it in GitHub Desktop.
Deno Module Style Guide

Deno Module Style Guide

conventions for 3rd party modules (work in progess).

Table of contents

Why do we need it?

It is a bit messy at the moment. The deno landscape is growing fast and modules take all different forms and conventions. There is a style guide for deno contributions, but not on what a 3rd party module should look like.

What do we need?

  • easy to implement conventions
  • familiarity between modules
  • crossconnectivity between modules

Conventions

Basics

Typescript

Write .ts files. Avoid .js and .d.ts files.

Format

Format your code with deno fmt.

Repository

Files

Names
  • Use snake case for file names

Example:

- my_file.ts

instead of

- my-file.ts
- myFile.ts
- MyFile.ts
mod.ts
  • Have a toplevel mod.ts file that exports everything that is needed when one is to use your module

Example:

// mod.ts
export { doSomething } from "./do_something.ts"
export { doSomethingElse } from "./do_something_else.ts"
export const someConstant = "hello world"
Dependencies
deps.ts
  • Have a toplevel deps.ts file that exports external dependencies. This prevents the same url in different files and also to have an overview over the module dependencies and versions.

Example:

module
  - deps.ts
  - mod.ts
// deps.ts
export * as path from "https://deno.land/std@0.95.0/path/mod.ts";
export * as colors from "https://deno.land/std@0.95.0/fmt/colors.ts";
export * as fs from "https://deno.land/std@0.95.0/fs/mod.ts";
*_deps.ts

For more complex modules, deps files should be named [kind]_deps.ts.

Example:

module
  - deps.ts
  - mod.ts
  - test_deps.ts
// test_deps.ts
export { assertEquals } from "https://deno.land/std@0.95.0/testing/mod.ts";
Tests
  • Avoid using a test or tests directory.
test.ts

For modules with only a few files and few tests, they can be grouped together in test.ts.

Example:

module
  - mod.ts
  - test.ts
*_test.ts

For more complex modules, test files should be named [filename]_test.ts. Test files should be next to the tested file.

Example:

module
  - mod.ts
  - strategies
    - github.ts
    - github_test.ts
    - facebook.ts
    - facebook_test.ts
    - google.ts
    - google_test.ts
Installables
cli.ts

A file that is intended to be installed with deno install should be named cli.ts.

Example:

module
  - cli.ts
  - mod.ts
*_cli.ts

If There are multiple installable files in one module, the name should be [filename]_cli.ts.

Example:

module
  - do_something_cli.ts
  - do_something_else_cli.ts
  - mod.ts
Why cli.ts and not install.ts?

Because the file does not always have to be installed in order to use it. Sometimes cli.ts might just be run with deno run.

Directories

Avoid unexpressive directory names like lib, src and dist. Deno modules are different from other languages because typescript does not need to be compiled and can be imported directly into projects via url. Having an additional /src in the import url is ugly and not necessary. These directories can be replaced by directories with expressive names in almost every case.

Example:

module
  - mod.ts
  - strategies
    - github.ts
    - facebook.ts
    - google.ts
  - README.md

instead of

module
  - mod.ts
  - src
    - github.ts
    - facebook.ts
    - google.ts
  - README.md

Code

Functions

Names
  • use CamelCase
  • do not abreveate words except common javascript API abbreviations (Examples: URL, JSON, DOM, etc.)
  • choose epressive names. Most function names will start with a verb (Examples: has, filter, set, findIndex, createSpecifierMap)

Example:

function returnHelloWorld() {
  return "Hello, world"
}

instead of

function returnhelloworld() {
  return "Hello, world"
}
function return_hello_world() {
  return "Hello, world"
}
function ReturnHelloWorld() {
  return "Hello, world"
}
Parameters

Functions should have the parameter types they need. They should not do extra work that can be done outside the function like parsing, reading, type convertions etc. This makes them more flexible.

function checkFoo(object: Record<string, any>) {
  return object.foo === true
}

const jsonString = `{ foo: true }`
const parsedObject = JSON.parse(jsonString)
const valid = checkFoo(parsedObject)

instead of

function checkFoo(jsonString: string) {
  const parsedObject = JSON.parse(jsonString)
  return object.foo === true
}
const jsonString = `{ foo: true }`
const valid = checkFoo(jsonString)

Constants and variables

  • use const whenever possible. Else use let. Avoid using var.
Names
  • use camel case.

Example:

let myVariable = "good"
const myConstant = "good"

instead of

let myvariable = "bad"
let my_variable = "bad"
const My_Constant = "bad"

Classes

Names

  • Use Pascal Case

Example:

class MyClass {
}

instead of

class myclass {
}
class myClass {
}
class My_Class {
}

Crossconnectivity

If your module is used in context of another module, prefix that class with the module name and let the user set the instance themselves during the new call. This will allow better integrity between modules.

Example:

import { OakSomething } from "./something/mod.ts"
import { Application } from "https://deno.land/x/oak/mod.ts";
const app = new Application();
const something =  new OakSomething(app)

instead of

import { OakSomething } from "./functionality.ts"
import { Application } from "https://deno.land/x/oak/mod.ts";
const app = new Application();
const something =  new OakSomething( { framwork: "oak" })
app.use(something.middleware)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment