Warning
This is a work in progress, but we are currently using it in production at Siteforge to help ensure type safety in our SurrealDB queries.
Note
Currently I haven't published this as a easily installable dependency, so you will need to git clone
this repo and build it yourself.
- Clone this repo
git clone https://github.com/siteforge-io/surreal-codegen.git
- Build the binary
cargo install --path ./surreal-codegen
- Run the binary
surreal-codegen --help
Usage: surreal-codegen [OPTIONS] --dir <DIR> --schema <SCHEMA>
Options:
-d, --dir <DIR> The directory containing the Surql files
-s, --schema <SCHEMA>
-o, --output <OUTPUT> The name of the output file default of `types.ts` [default: ./types.ts]
-h, --help Print help
./schema.surql
DEFINE TABLE user SCHEMAFULL;
DEFINE FIELD email ON user TYPE string
VALUE string::lowercase($value)
ASSERT string::is::email($value);
DEFINE FIELD password ON user TYPE string
VALUE crypto::bcrypt::generate($value);
DEFINE FIELD name ON user TYPE string
VALUE string::trim($value);
DEFINE FIELD created_at ON user TYPE datetime
VALUE time::now()
READONLY;
./queries/create_user.surql
CREATE user CONTENT $user;
This wil generate a types.ts
file in the current directory, which includes all your queries, as well as some prototype and type overrides for the SurrealDB database to allow you to use the generated types in your TypeScript code.
surreal-codegen \
--schema ./schema.surql \
--dir ./queries \
--output ./queries.ts
import { TypedSurreal, CreateUserQuery } from "./queries"
const db = new TypedSurreal({
...
});
/*
Result is typed as CreateUserResult from the generated types.ts file
*/
const result = await db.typed(CreateUserQuery, {
user: {
name: "John Doe",
email: "john@doe.com",
password: "123456",
} // can also be an array of users
});
We exploit the SurrealDB casting system to infer the types of parameters, for places where they cannot be inferred from the query itself.
All you must do is add a casting annotation with the parameter name, eg:
-- Casting syntax in SurrealDB.
<string> $email;
This will allow the codegen to infer the type of $email
variable as a string
.
./queries/reset_password.surql
<record<user>> $user;
<string> $password;
UPDATE ONLY $user
SET password = $password
You can also define global parameters in a global.surql
file, which will be available to all queries in the directory, this is useful things like typing the $auth parameters available in SurrealDB across all queries.
./queries/globals.surql
<record<user>> $user;
- We only currently support SCHEMAFULL tables so far, but we are working on supporting other table types.
-
Never
-
Unknown
-
String
-
Int
-
Float
-
Datetime
-
Duration
-
Decimal
-
Bool
-
Record
-
Option
-
Array
-
Object
-
Number
-
Null
(forOption
) -
Any
-
None
-
Either
(mixed return types)
-
RETURN { foo: 1, bar: 2 }
-
WHERE foo = $bar
parameter inference -
fn::foo($bar)
parameter inference -
CREATE baz SET foo = $bar
parameter inference -
CREATE baz CONTENT { foo: $bar }
parameter inference -
CREATE baz CONTENT $foo
parameter inference -
UPDATE baz SET foo = $bar
parameter inference -
UPDATE baz CONTENT $foo
parameter inference -
UPDATE baz MERGE $foo
parameter inference -
UPDATE baz MERGE { foo: $bar }
parameter inference -
UPSERT baz SET foo = $bar
parameter inference
- All fields
- Fields
- Fields with aliases
-
FROM
targets -
VALUE
-
GROUP BY
-
GROUP ALL
-
SPLIT
fields -
FETCH
fields
-
FROM
targets -
RETURN BEFORE
-
RETURN AFTER
-
RETURN DIFF
-
RETRUN @statement_param
with$before
field access
- TODO
- TODO
-
DEFINE TABLE foo AS SELECT ... FROM bar
-
DEFINE TABLE foo AS SELECT ... FROM bar GROUP BY ...
-
DEFINE TABLE foo AS SELECT ... FROM bar GROUP ALL
-
RETURN BEFORE
-
RETURN AFTER
-
RETURN DIFF
-
RETRUN @statement_param
with$before
and$after
field access -
CONTENT { foo: $bar }
parameter inference -
CONTENT $foo
parameter inference -
SET foo = $bar
parameter inference -
MERGE $bar
parameter inference -
MERGE { foo: $bar }
parameter inference
-
RETURN BEFORE
-
RETURN AFTER
-
RETURN DIFF
-
RETRUN @statement_param
with$after
field access -
CONTENT { foo: $bar }
parameter inference -
CONTENT $foo
parameter inference -
SET foo = $bar
parameter inference
- TODO
-
foo.bar
-
foo.*
for arrays -
foo.*
for objects -
foo[0]
- edge traversal eg:
foo->bar<-baz
-
true
-
false
-
null
-
"string"
-
123
-
123.456
-
[1, 2, 3]
-
{"foo": "bar"}
-
foo == "bar"
-
foo != "bar"
-
foo < "bar"
-
foo <= "bar"
-
foo > "bar"
-
foo >= "bar"
-
SELECT
statements -
DELETE
statements -
INSERT
statements -
UPDATE
statements -
CREATE
statements -
RELATE
statements
- Custom global
$param
definitions in aglobal.surql
file-
$auth
-
$session
-
$scope
-
$input
-
$token
-
- built-in parameters
-
$this
-
$parent
-
$after
-
$before
-
- Automatic parameter inference in some cases
-
IF ELSE
-
FOR
-
CONTINUE
-
BREAK
-
RETURN
-
BEGIN
-
COMMIT
-
LET
-
ABORT
-
THROW