Skip to main content

Defining Modules

Defining a Deno module comes in two parts:

  • declaration of queries and mutations in an exo file
  • implementation of the module in a TypeScript or JavaScript file

Declaring a module

You may use the @deno annotation to define a module implemented in TypeScript or JavaScript. The annotation takes a single parameter: the TypeScript or JavaScript file path.

Here is an example of a simple module implemented in TypeScript.

@deno("math.ts")
module MathModule {
@access(true)
query add(a: Int, b: Int): Int

@access(true)
query square(a: Int): Int
}

The @deno annotation of the MathModule module specifies that the module implementation is in the math.ts file. The module declares two queries: add and square. The add query takes two Int arguments and returns an Int value. The square query takes a single Int argument and returns an Int value.

Note the @access annotation on the queries. It specifies that the query is accessible to all users (by default, queries and mutations aren't accessible to anyone). You can specify a fine-grained access control using the @access annotation, as we will see later.

Implementing a module in TypeScript

For each declared query (or mutation), the corresponding TypeScript code must export a function that matches the query name. Each function must take the same arguments as the query, with each argument's type appropriately mapped to the corresponding TypeScript type. For example, if an argument or return type is Int, the TypeScript type would be number. The function must return a value that matches the return type of the query.

We don't need here, but the functions may be declared async and return a Promise if they need to perform asynchronous operations. We will explore this in more detail in the next sections.

export function add(a: number, b: number): number {
return a + b;
}

export function square(a: number): number {
return a * a;
}
Starter JavaScript/TypeScript file

When you run exo dev (or exo yolo), Exograph will generate a starter TypeScript file if it doesn't already exist. Exograph doesn't update the file if it already exists, so you must manually do so.

Once you have the above code, you can run exo dev. You can then run the add query in GraphQL Playground:

query {
add(a: 2, b: 3)
}

which should return:

{
"data": {
"add": 5
}
}

Similarly, you can run the square query:

query {
square(a: 2)
}

which should return:

{
"data": {
"square": 4
}
}

Implementing a module in JavaScript

If you choose to use JavaScript instead of TypeScript, you need to change the name of the file to math.js:

@deno("math.js")
module MathModule {
@access(true)
query add(a: Int, b: Int): Int

@access(true)
query square(a: Int): Int
}

The math.js file looks pretty much the same as the TypeScript file, except that you don't need to specify the type of the arguments or the return value.

export function add(a, b) {
return a + b;
}

export function square(a) {
return a * a;
}

You can now execute the same queries as before.