The TypeScript (Deno) Connector allows a running connector to be inferred from a TypeScript file (optionally with dependencies).
Useful Links:
- TypeScript Deno Connector on the NDC Hub
- TypeScript Deno Connector on deno.com
- Hasura V3 Documentation
- Hasura CLI
- CLI Connector Plugin
- Hasura VSCode Extension
- Deno
- Native Data Connector Specification
- TypeScript NDC SDK
The connector runs in the following manner:
- TypeScript sources are assembled (with
index.ts
acting as your interface definition) - Dependencies are fetched
- Inference is performed and made available via the
/schema
endpoint - Functions are served via the connector protocol
Note: The Deno runtime is used and this connector assumes that dependencies are specified in accordance with Deno conventions.
It is recommended that you:
- Install the Hasura3 CLI
- Log in via the CLI
- Install the connector plugin
- Install VSCode
- Install the Hasura VSCode Extension
- Optionally install Deno
- Optionally install the VSCode Deno Extension
The last item is currently required for access to the Hasura DDN in order to deploy and manage V3 projects.
Once the Hasura DDN is generally available this will no longer be required.
Your functions should be organised into a directory with one file acting as the entrypoint.
An example TypeScript entrypoint:
// functions/index.ts
import { Hash, encode } from "https://deno.land/x/[email protected]/mod.ts";
export function make_bad_password_hash(pw: string): string {
return new Hash("md5").digest(encode(pw)).hex();
}
/**
* Returns the github bio for the userid provided
*
* @param username Username of the user who's bio will be fetched.
* @returns The github bio for the requested user.
* @pure This function should only query data without making modifications
*/
export async function get_github_profile_description(username: string): Promise<string> {
const foo = await fetch(`https://api.github.com/users/${username}`);
const response = await foo.json();
return response.bio;
}
export function make_array(): Array<string> {
return ['this', 'is', 'an', 'array']
}
type MyObjectType = {'foo': string, 'baz': Boolean}
export function make_object(): MyObjectType {
return { 'foo': 'bar', 'baz': true}
}
export function make_object_array(): Array<MyObjectType> {
return [make_object(), make_object()]
}
/**
* @pure
*/
export function has_optional_args(a: string, b?: string) {
if(b) {
return `Two args: ${a} ${b}`;
} else {
return `One arg: ${a}`;
}
}
Top level exported function definitions with pure
tag will be made available as functions,
and others as procedures, which will become queries and mutations respectively.
- Return types are inferred
- Parameters are inferred and named after their input parameter names.
- Simple scalar, array, and object types should be supported
- Exceptions can be thrown
- Optional parameters will become optional arguments
Limitations:
The(vendoring is now automatic by default)deno vendor
step must be run by hand for local development- Functions can be sync, or async, but
Promise
's can't be nested - All numbers are exported as
Float
s - Unrecognised types will become opaque scalars, for example: union types.
- Optional object fields are not currently supported
- Functions can be executed via both the
/query
and/mutation
endpoints - Conflicting type names in dependencies will be namespaced with their relative path
- Generic type parameters will be treated as scalars when referenced
- Importing multiple versions of the same package using Deno
npm:
package specifiers does not work properly with type inference (only a single version of the package is imported)
Please file an issue for any problems you encounter during usage of this connector.
While you can deploy your functions and have errors returned in the hasura3 connector
logs,
local development will reward you with much more rapid feedback.
In order to develop your functions locally the following is the recommended practice:
- Have a
./functions/
directory in your project - Create your functions in an
index.ts
file inside the./functions/
directory - Create a development config for your connector in
./config.json
:
{
"functions": "./functions/index.ts",
"vendor": "./vendor",
"schemaMode": "INFER"
}
- Make sure to .gitignore your computed
vendor
files. - Start the connector
deno run -A --watch=./functions --check https://deno.land/x/hasura_typescript_connector/mod.ts serve --configuration ./config.json
- (Optionally) Add a test-suite for your functions. See Deno Testing Basics.
You can also perform local development with rapid feedback by using the Docker container instead
of deno run
. You don't need a config.json
in this case.
- Have a
./functions/
directory in your project - Create your functions in an
index.ts
file inside the./functions/
directory - Start the connector using Docker:
docker run -it --rm -v ./functions:/functions/src -p 8080:8080 -e WATCH=1 ghcr.io/hasura/ndc-typescript-deno:latest
The configuration object has the following properties:
functions (string): Location of your functions entrypoint
vendor (string): Location of dependencies vendor folder (optional)
preVendor (boolean): Perform vendoring prior to inference in a sub-process (default: true)
schemaMode (string): INFER the schema from your functions, or READ it from a file. (default: INFER)
schemaLocation (string): Location of your schema file. schemaMode=READ reads the file (required), schemaMode=INFER writes the file (optional)
NOTE: When deploying the connector with the connector create
command your config is currently replaced with:
{
"functions": "/functions/src/index.ts",
"vendor": "/functions/vendor",
"schemaMode": "READ",
"schemaLocation": "/functions/schema.json"
}
This means that your functions volume will have to be mounted to /functions/src
.
You will need:
- V3 CLI (With Logged in Session)
- Connector Plugin
- (Optionally) A value to use with
SERVICE_TOKEN_SECRET
- a typescript sources directory. E.g.
--volume ./my_functions_directory:/functions
Create the connector:
hasura3 connector create my-cool-connector:v1 \
--github-repo-url https://github.com/hasura/ndc-typescript-deno/tree/main \
--config-file <(echo '{}') \
--volume ./functions:/functions \
--env SERVICE_TOKEN_SECRET=MY-SERVICE-TOKEN # (optional)
Note: Even though you can use the "main" branch to deploy the latest connector features, see the Hasura Connector Hub for verified release tags
Monitor the deployment status by name - This will indicate in-progress, complete, or failed status:
hasura3 connector status my-cool-connector:v1
List all your connectors with their deployed URLs:
hasura3 connector list
View logs from your running connector:
hasura3 connector logs my-cool-connector:v1
This connector is intended to be used with Hasura v3 projects.
Find the URL of your connector once deployed:
hasura3 connector list
my-cool-connector:v1 https://connector-9XXX7-hyc5v23h6a-ue.a.run.app active
In order to use the connector once deployed you will first want to reference the connector in your project metadata:
kind: "AuthConfig"
allowRoleEmulationFor: "admin"
webhook:
mode: "POST"
webhookUrl: "https://auth.pro.hasura.io/webhook/ddn?role=admin"
---
kind: DataConnector
version: v1
definition:
name: my_connector
url:
singleUrl: 'https://connector-9XXX7-hyc5v23h6a-ue.a.run.app'
If you have the Hasura VSCode Extension installed you can run the following code actions:
Hasura: Refresh data source
Hasura: Track all collections / functions ...
This will integrate your connector into your Hasura project which can then be deployed or updated using the Hasura3 CLI:
hasura3 cloud build create --project-id my-project-id --metadata-file metadata.hml
If you don't wish to have your connector publically accessible then you must set a service token by specifying the SERVICE_TOKEN_SECRET
environment variable when creating your connector:
--env SERVICE_TOKEN_SECRET=SUPER_SECRET_TOKEN_XXX123
Your Hasura project metadata must then set a matching bearer token:
kind: DataConnector
version: v1
definition:
name: my_connector
url:
singleUrl: 'https://connector-9XXX7-hyc5v23h6a-ue.a.run.app'
headers:
Authorization:
value: "Bearer SUPER_SECRET_TOKEN_XXX123"
While you can specify the token inline as above, it is recommended to use the Hasura secrets functionality for this purpose:
kind: DataConnector
version: v1
definition:
name: my_connector
url:
singleUrl: 'https://connector-9XXX7-hyc5v23h6a-ue.a.run.app'
headers:
Authorization:
valueFromSecret: BEARER_TOKEN_SECRET
NOTE: This secret should contain the Bearer
prefix.
Errors may arise from any of the following:
- Dependency errors in your functions
- Type errors in your functions
- Implementation errors in your functions
- Invalid connector configuration
- Invalid project metadata
- Connector Deployment Failure
- Misconfigured project authentication
- Misconfigured service authentication
- Insufficient query permissions
- Invalid queries
- Unanticipated bug in connector implementation
For a bottom-up debugging approach:
- First check your functions:
- Run
deno check
on your functions to determine if there are any obvious errors - Write a
deno test
harness to ensure that your functions are correctly implemented
- Run
- Then check your connector:
- Check that the connector deployed successfully with
hasura3 connector status my-cool-connector:v1
- Check the build/runtime logs of your connector with
hasura3 connector logs my-cool-connector:v1
- Check that the connector deployed successfully with
- Then check your project:
- Ensure that your metadata and project build were successful
- Then check end-to-end integration:
- Run test queries and view the connector logs to ensure that your queries are propagating correctly
For contribution to this connector you will want to have the following dependencies:
In order to perform local development on this codebase:
- Check out the repository:
git clone https://github.com/hasura/ndc-typescript-deno.git
- This assumes that you will be testing against function in
./functions
- Serve your functions with
deno run -A --watch=./functions --check ./src/mod.ts serve --configuration <(echo '{"functions": "./functions/index.ts", "vendor": "./vendor", "schemaMode": "INFER"}')
- The connector should now be running on localhost:8100 and respond to any changes to the your functions and the connector source
- Use the
hasura3
tunnel commands to reference this connector from a Hasura Cloud project
If you are fixing a bug, then please consider adding a test case to ./src/test/data
.
The documentation and community will help you troubleshoot most issues. If you have encountered a bug or need to get in touch with us, you can contact us using one of the following channels:
- Support & feedback: Discord
- Issue & bug tracking: GitHub issues
- Follow product updates: @HasuraHQ
- Talk to us on our website chat