Recently Deno 1.01 was released. I have been experimenting with Javascript and Node.js for quite a while. However, my experiments with Typescript were very limited. Deno provides a secure runtime for both Javascript and Typescript. This article is related to my experiments with Deno and Typescript for accessing Wikidata. If you have been following some of my past works like WDProp2 or WikiProvenance3, you may have observed that both of these works were developed in vanilla Javascript without any Node.js4 module. However, given the static typing of Typescript, I want to explore it with Deno for accessing Wikidata. And the preliminary development experience went well.

Deno

Installing Deno5 was easy and it could be installed locally in the user environment.

  $ curl -fsSL https://deno.land/x/install/install.sh | sh
  ######################################################################## 100,0%##O#- #                                       ######################################################################## 100,0%
  Archive:  /home/john/.deno/bin/deno.zip
     inflating: deno
  Deno was installed successfully to /home/john/.deno/bin/deno
	  

After manually adding the deno directory to my $HOME/.bashrc, I could start working with it.

     export DENO_INSTALL="/home/john/.deno"
     export PATH="$DENO_INSTALL/bin:$PATH"
	  

To ensure that my changes are taken into consideration, I ran

     $ source $HOME/.bashrc
	  

At the time of writing, I have the following version of Deno installed.

     $ deno --version
      deno 1.1.0
      v8 8.4.300
      typescript 3.9.2
	  

My first Hello World program was written in the file hello.ts

      console.log("Hello World!")
	  

Executing it required the run option and I could see that the file was compiled and the output can be seen on the terminal.

     $ deno run hello.ts 
      Compile file:///home/john/deno/hello.ts
      Hello World! 
	  

Thus I am all set for running my Typescript programs with deno.

Wikidata

My next goal was to make use of simple SPARQL queries and get data from the Wikidata SPARQL endpoint6. For example, the following SPARQL queries would give me 10 human from Wikidata.

	  SELECT ?item {
	    ?item wdt:P31 wd:Q5
	  }
	  LIMIT 10
	  

Deno and Wikidata

Making use of Wikidata SPARQL endpoint, I first wrote the following code fetch.ts.

	
   const result = await fetch("https://query.wikidata.org/sparql?query=SELECT%20%3Fitem%20%7B%0A%20%20%3Fitem%20wdt%3AP31%20wd%3AQ5%0A%7D%0ALIMIT%2010&format=json");
   const data = await result.json();
   console.log(data.results)
	
	  

Continuing with the same style of execution as shown above, a simple deno run however gave the following errors:

     $ deno run fetch.ts
     Compile file:///home/john/deno/fetch.ts
     error: Uncaught PermissionDenied: network access to "https://query.wikidata.org/sparql?query=SELECT%20%3Fitem%20%7B%0A%20%20%3Fitem%20wdt%3AP31%20wd%3AQ5%0A%7D%0ALIMIT%2010&format=jsn", run again with the --allow-net flag
        at unwrapResponse ($deno$/ops/dispatch_json.ts:43:11)
        at Object.sendAsync ($deno$/ops/dispatch_json.ts:98:10)
        at async fetch ($deno$/web/fetch.ts:265:27)
        at async file:///home/john/contributions/deno/fetch.ts:1:16
	  

This is the interesting part of deno. Unlike node, deno requires permissions from the user to connect with the internet. Hence the option --allow-net need to be used with deno run for running the above file.

     $ deno run --allow-net fetch.ts 
      {
        bindings: [
          { item: { type: "uri", value: "http://www.wikidata.org/entity/Q23" } },
          { item: { type: "uri", value: "http://www.wikidata.org/entity/Q42" } },
          { item: { type: "uri", value: "http://www.wikidata.org/entity/Q76" } },
          { item: { type: "uri", value: "http://www.wikidata.org/entity/Q80" } },
          { item: { type: "uri", value: "http://www.wikidata.org/entity/Q91" } },
          { item: { type: "uri", value: "http://www.wikidata.org/entity/Q157" } },
          { item: { type: "uri", value: "http://www.wikidata.org/entity/Q181" } },
          { item: { type: "uri", value: "http://www.wikidata.org/entity/Q185" } },
          { item: { type: "uri", value: "http://www.wikidata.org/entity/Q186" } },
          { item: { type: "uri", value: "http://www.wikidata.org/entity/Q192" } }
        ]
      }
	  

The next goal is to make use of functions and split the logic of calling Wikidata and printing results separately. First, a function in the file wdqs.ts is created to query Wikidata and handle proper response or an error. Note that the function has been declared as asynchronous and it is also declared to be exported, i.e., it can be used in other Typescript files.

  export async function query_wikidata(query: string){
    let queryresults:object = [];
    await fetch(query)
    .then(response => {
      if (!response.ok) {
        throw new Error("Problem in obtaining a response");
      }
      return response.json();
    })
    .then(results => {
      queryresults = results.results.bindings;
    })
    .catch(error => {
      console.error('Error in calling Wikidata API', error);
    });
    return (queryresults);
  }

	  

Now, this function is imported in another file query.ts. The first line imports the function query_wikidata(). In this file, the URL of SPARQL endpoint is passed as an input. And once the result is obtained, the Wikidata identifiers of different humans are obtained.

  import {query_wikidata} from "./wdqs.ts"
  
  let promise = query_wikidata("https://query.wikidata.org/sparql?query=SELECT%20%3Fitem%20%7B%0A%20%20%3Fitem%20wdt%3AP31%20wd%3AQ5%0A%7D%0ALIMIT%2010&format=json")
  promise.then(
     (result: any) => {
       for (let row of result) {
         console.log(row.item.value)
       }
     });
	  

Finally, the new file query.ts is run using deno.

  $ deno run --allow-net query.ts 
  Compile file:///home/john/deno/query.ts
  http://www.wikidata.org/entity/Q23
  http://www.wikidata.org/entity/Q42
  http://www.wikidata.org/entity/Q76
  http://www.wikidata.org/entity/Q80
  http://www.wikidata.org/entity/Q91
  http://www.wikidata.org/entity/Q157
  http://www.wikidata.org/entity/Q181
  http://www.wikidata.org/entity/Q185
  http://www.wikidata.org/entity/Q186
  http://www.wikidata.org/entity/Q192
	  

I like how deno asks permissions from the user before running the scripts. There are flags like --allow-read or --allow-net that ensures deno does not access the local filesystem and the local environment respectively without these flags. The current way of importing functions using URLs (not discussed here) is very interesting. I would like to further explore Typescript and Deno for future Wikidata related projects.

References

  1. Deno 1.0
  2. WDProp
  3. WikiProvenance
  4. Node.js
  5. Deno
  6. Wikidata Query Service