Skip to content

Instantly share code, notes, and snippets.

@Lightnet
Last active October 2, 2022 17:45
Show Gist options
  • Save Lightnet/77c1a15e917d3a19e3454e9c5c1e8c58 to your computer and use it in GitHub Desktop.
Save Lightnet/77c1a15e917d3a19e3454e9c5c1e8c58 to your computer and use it in GitHub Desktop.
SurrealDB test file. server nodejs

SurrealDB Nodejs.

surrealDB:

  • 1.0.0 beta 8
    • change to 'Content-Type': 'application/json' > 'Accept': 'application/json'
    • text to json response for better error handle checks

Test build for server in case of the browser client does work correct for testing. As long there headers and json or text for correct format for sql, sign in and sign up.

This is mixed with websocket(not added) and http request rest api to SurrealDB connection or request http for testing.

Notes:

  • Incorrect format fetch on header cause cors error.
  • If used query function on DEFINE will error and will not go to next query. Required root admin http rest api post for table setup and define for user to access table.
  • still work in progress builds.

Features:

  • simple user table setup.
  • simple to do list.
    • note delete have not work but view own todlist works.

SurealDB Symbols API:

  • $auth.id = user:randomid = table:id
  • $scope = allusers //DEFINE SCOPE allusers <- access to account permission for table actions.
  • $this = table data, ref current table data, other unknown
  • $before.alias , $after.alias <- for update, create table value field data.
  • $event <- "UPDATE","CREATE","DELETE"
DEFINE EVENT fetch_alias ON TABLE user WHEN $event = "UPDATE" AND $after.alias THEN
	http::post('http://localhost:3000/api/user', { action: $event, data: $this })
;
  • VALUE $value <- current field value
DEFINE FIELD email ON TABLE user TYPE string ASSERT is::email($value);

Check if email is verify else reject.

time::now()

Notes:

  • DEFINE format must pass else it will error or no error if not set up correctly.
//note using solidjs for testing ui.
// browser client api.
// note not update yet for 1.0.0 beta 8 should be same format for http rest api.
const [token, setToken] = createSignal('');
async function fetchRootUsers(){
let query = "SELECT * FROM user;"
let response = await fetch(`http://localhost:8000/sql`, {
method: 'POST',
headers:{
'Accept': 'application/json',
'NS': 'test', // Specify the namespace
'DB': 'test', // Specify the database
"Authorization": 'Basic ' + btoa('root'+':'+'root')
},
body: query
})
let data = await response.json();
console.log(data);
}
async function fetchSignIn(){
let response = await fetch(`http://localhost:8000/signin`, {
method: 'POST',
headers:{
'Accept': 'application/json'
},
body: JSON.stringify({
NS:'test',
DB:'test',
SC:'allusers',
email:'test@test.test',
pass:'pass'
})
})
let data = await response.json();
console.log(data);
if(data?.token){
setToken(data.token)
}
}
async function fetchSignUp(){
let response = await fetch(`http://localhost:8000/signup`, {
method: 'POST',
headers:{
'Accept': 'application/json'
},
body: JSON.stringify({
NS:'test',
DB:'test',
SC:'allusers',
email:'test@test.test',
pass:'pass'
})
})
let data = await response.json();
console.log(data);
if(data?.token){
setToken(data.token)
}
}
async function fetchTokenQuery(){
let query = `SELECT * FROM user;`;
let response = await fetch(`http://localhost:8000/sql`, {
method: 'POST',
headers:{
'Accept': 'application/json',
'Authorization': 'Bearer ' + token()
},
body: query
})
let data = await response.json();
console.log(data);
if(data?.token){
setToken(data.token)
}
}
function xmlQueryTest(){
let query = "SELECT * FROM user;"
const xmlhttp = new XMLHttpRequest();
const url='http://localhost:8000/sql';
xmlhttp.open("POST", url, true);
xmlhttp.setRequestHeader('Accept', 'application/json');
xmlhttp.setRequestHeader('NS', 'test');
xmlhttp.setRequestHeader('DB', 'test');
xmlhttp.setRequestHeader("Authorization", 'Basic ' + btoa('root'+':'+'root'));
xmlhttp.onreadystatechange = function() {//Call a function when the state changes.
console.log(xmlhttp.status)
if(xmlhttp.readyState == 4 && xmlhttp.status == 200) {
//alert(xmlhttp.responseText);
//console.log(xmlhttp.responseText);
console.log(JSON.stringify(JSON.parse(xmlhttp.responseText),null,2))
}
}
xmlhttp.send(query)
}
function xmlSignUp(){
let query = "SELECT * FROM user;"
const xmlhttp = new XMLHttpRequest();
const url='http://localhost:8000/signup';
xmlhttp.open("POST", url, true);
xmlhttp.setRequestHeader('Accept', 'application/json');
//xmlhttp.setRequestHeader('NS', 'test');
//xmlhttp.setRequestHeader('DB', 'test');
//xmlhttp.setRequestHeader("Authorization", 'Basic ' + btoa('root'+':'+'root'));
xmlhttp.onreadystatechange = function() {//Call a function when the state changes.
console.log(xmlhttp.status)
if(xmlhttp.readyState == 4 && xmlhttp.status == 200) {
//alert(xmlhttp.responseText);
console.log(xmlhttp.responseText);
setToken(JSON.parse(xmlhttp.responseText).token)
}
}
xmlhttp.send(JSON.stringify({
NS:'test',
DB:'test',
SC:'allusers',
email:'test@test.test',
pass:'pass'
}))
}
function xmlSignIn(){
let query = "SELECT * FROM user;"
const xmlhttp = new XMLHttpRequest();
const url='http://localhost:8000/signin';
xmlhttp.open("POST", url, true);
xmlhttp.setRequestHeader('Accept', 'application/json');
//xmlhttp.setRequestHeader('NS', 'test');
//xmlhttp.setRequestHeader('DB', 'test');
//xmlhttp.setRequestHeader("Authorization", 'Basic ' + btoa('root'+':'+'root'));
xmlhttp.onreadystatechange = function() {//Call a function when the state changes.
console.log(xmlhttp.status)
if(xmlhttp.readyState == 4 && xmlhttp.status == 200) {
//alert(xmlhttp.responseText);
console.log(xmlhttp.responseText);
setToken(JSON.parse(xmlhttp.responseText).token)
}
}
xmlhttp.send(JSON.stringify({
NS:'test',
DB:'test',
SC:'allusers',
email:'test@test.test',
pass:'pass'
}))
}
function xmlTokenQuery(){
let query = "SELECT * FROM user;"
const xmlhttp = new XMLHttpRequest();
const url='http://localhost:8000/sql';
xmlhttp.open("POST", url, true);
xmlhttp.setRequestHeader('Accept', 'application/json');
xmlhttp.setRequestHeader('NS', 'test');
xmlhttp.setRequestHeader('DB', 'test');
xmlhttp.setRequestHeader("Authorization", 'Bearer ' + token());
xmlhttp.onreadystatechange = function() {//Call a function when the state changes.
console.log(xmlhttp.status)
if(xmlhttp.readyState == 4 && xmlhttp.status == 200) {
//alert(xmlhttp.responseText);
//console.log(xmlhttp.responseText);
console.log(JSON.stringify(JSON.parse(xmlhttp.responseText),null,2))
}
}
xmlhttp.send(query)
}
function AxiosQueryUser(){
let query = "SELECT * FROM user;"
//console.log(btoa('root'+':'+'root'))
//delete axios.defaults.headers.common["Accept"];//might need this ???
//axios.defaults.headers.post['Content-Type'] = 'application/json';
//axios.defaults.headers.common['Authorization'] = 'Basic ' + btoa('root'+':'+'root');
axios.post('http://localhost:8000/sql', query, {
headers: {
'Accept': 'application/json',
'NS':'test',
'DB':'test',
'Authorization': 'Basic ' + btoa('root'+':'+'root')
},
transformRequest: [function (data, headers) {//this is need else error 400
// Do whatever you want to transform the data
//console.log(data)
return data;
}],
}).then(data=>{
console.log(data)
}).catch(err=>{
console.log(err)
console.log(err.code)
console.log(err.message)
})
}
function AxiosSignUp(){
axios.post('http://localhost:8000/signup', {
NS:'test',
DB:'test',
SC:'allusers',
email:'test@test.test',
pass:'pass'
}, {
headers: {
'Accept': 'application/json'
},
//transformRequest: [function (data, headers) {// not needed for signup
// Do whatever you want to transform the data
//console.log(data)
//return data;
//}],
}).then(data=>{
console.log(data)
if(data?.data?.token != null){
console.log("token found!")
setToken(data.data.token)
}
}).catch(err=>{
console.log(err)
console.log(err.code)
console.log(err.message)
})
}
function AxiosSignIn(){
axios.post('http://localhost:8000/signin', {
NS:'test',
DB:'test',
SC:'allusers',
email:'test@test.test',
pass:'pass'
}, {
headers: {
'Accept': 'application/json'
},
//transformRequest: [function (data, headers) {// not needed for signin
// Do whatever you want to transform the data
//console.log(data)
//return data;
//}],
}).then(data=>{
console.log(data)
if(data?.data?.token != null){
console.log("token found!")
setToken(data.data.token)
}
}).catch(err=>{
console.log(err)
console.log(err.code)
console.log(err.message)
})
}
function AxiosTokenQuery(){
let query = "SELECT * FROM user;"
axios.post('http://localhost:8000/sql', query, {
headers: {
'Accept': 'application/json',
'Authorization': 'Bearer ' + token()
},
transformRequest: [function (data, headers) {//need to query sql
// Do whatever you want to transform the data
//console.log(data)
return data;
}],
}).then(data=>{
console.log(data)
}).catch(err=>{
console.log(err)
console.log(err.code)
console.log(err.message)
})
}
/*
This is http request rest api test.
For server nodejs testing.
After retesting fetch api and XMLHttpRequest works.
http rest api client browser ext does work.
*/
// https://stackoverflow.com/questions/4810841/pretty-print-json-using-javascript
import nodefetch from 'node-fetch';
import crypto from 'crypto';
function textToBase64(_data){
//note this is nodejs not browser support
return Buffer.from(_data).toString('base64');
}
function base64ToText(_data){
//note this is nodejs not browser support
return Buffer.from(_data,'base64url').toString('ascii')
}
async function signIn(options){
if(!options){
options={};
}
let response = await nodefetch(`http://localhost:8000/signin`, {
method: 'POST',
//mode: 'no-cors', //dev testing...
//credentials: 'omit',
headers:{
'Accept': 'application/json'
},
body: JSON.stringify({
NS:'test',
DB:'test',
SC:'allusers',
email: options.email ||'test@test.test',
pass: options.pass || "pass"
}),
})
let data = await response.json();
//console.log(data);
return data;
}
async function signUp(options){
if(!options){
options={}
}
let response = await nodefetch(`http://localhost:8000/signup`, {
method: 'POST',
//mode: 'no-cors', //dev testing...
//credentials: 'omit',
headers:{
'Accept': 'application/json'
},
body: JSON.stringify({
NS:'test',
DB:'test',
SC:'allusers',
email: options?.email || 'test@test.test',
pass: options?.pass || "pass"
}),
})
let data = await response.json();
//console.log(data);
return data;
}
async function fetchQuerySQL(query){
let response = await nodefetch(`http://localhost:8000/sql`, {
method: 'POST',
headers:{
'Accept': 'application/json',
'NS': 'test', // Specify the namespace
'DB': 'test', // Specify the database
"Authorization": 'Basic ' + textToBase64('root'+':'+'root') ,
},
body: query,
})
//console.log(response)
let data = await response.json();
//console.log(data);
return data;
}
async function tokenQuerySQL(token, query){
let response = await nodefetch(`http://localhost:8000/sql`, {
method: 'POST',
headers:{
//'Content-Type': 'application/json',
'Accept': 'application/json',
'NS': 'test', // Specify the namespace
'DB': 'test', // Specify the database
"Authorization": 'Bearer ' + token ,
},
body: query,
})
let data = await response.json();
//console.log(data);
return data;
}
function parseUserID(_Token){
//console.log(_Token)
let userStr = _Token.split(".")[1]
//console.log("userStr")
//console.log(userStr)
//console.log(base64ToText(userStr))
return JSON.parse(base64ToText(userStr)).ID;
}
async function queryDB(){
let data;
let query;
query = `INFO FOR DB;`
data = await fetchQuerySQL(query)
//console.log(data)
console.log("SCOPE:")
console.log(data[0].result.sc)
console.log("DATABASE:")
console.log(data[0].result.tb)
}
async function setupUser(){
let data;
let query;
query =
`DEFINE TABLE user SCHEMALESS;
DEFINE INDEX idx_email ON user COLUMNS email UNIQUE;
DEFINE FIELD update ON TABLE user TYPE datetime VALUE $before OR time::now();
DEFINE FIELD created ON TABLE user TYPE datetime VALUE time::now();
`;
//query = `SELECT * FROM user;`
data = await fetchQuerySQL(query)
//console.log(data)
query = `
DEFINE SCOPE allusers
SESSION 14d
SIGNUP ( CREATE user SET email = $email, pass = crypto::argon2::generate($pass) )
SIGNIN ( SELECT * FROM user WHERE email = $email AND crypto::argon2::compare(pass, $pass) )
`;
data = await fetchQuerySQL(query)
//console.log(data)
}
async function setupToDoList(){
let data;
let query;
//query = `DEFINE TABLE todolist SCHEMALESS;`;//set up table without permission for testing. Else error no table.
//data = await fetchQuerySQL(query)
//console.log(data)
query =
`DEFINE TABLE todolist SCHEMALESS
PERMISSIONS
FOR select WHERE user = $auth.id,
FOR create, update
WHERE user = $auth.id,
FOR delete
WHERE user = $auth.id;
`;
data = await fetchQuerySQL(query)
console.log(data)
query = `
DEFINE FIELD update ON TABLE todolist TYPE datetime VALUE $before OR time::now();
DEFINE FIELD created ON TABLE todolist TYPE datetime VALUE time::now();
`;
data = await fetchQuerySQL(query)
console.log(data)
}
async function getTasks(jwt){
let query = `SELECT * FROM todolist;`
let data = await tokenQuerySQL(jwt, query)
console.log(data)
//console.log(data[0].result)
}
async function addTask(jwt, _text){
let userID = parseUserID(jwt)
console.log(userID)
let query = `CREATE todolist SET content = "${_text}", user="${userID}";`
let data = await tokenQuerySQL(jwt, query)
console.log(data[0].result)
}
async function postTaskTest(jwt){
let userID = parseUserID(jwt)
console.log("userID: ",userID)
const _text = "hello " + crypto.randomUUID();
let query = `CREATE todolist SET content = "${_text}", user="${userID}";`
let data = await tokenQuerySQL(jwt, query)
console.log(data)
}
// "table:id"
async function deleteTaskID(jwt, id){
let query = `DELETE "${id}";`
let data = await tokenQuerySQL(jwt, query)
console.log(data)
console.log(data[0].result)
}
async function setupPost(){
let data;
let query;
query =
`DEFINE TABLE post SCHEMALESS;
`;
data = await fetchQuerySQL(query)
console.log(data)
query = `
DEFINE FIELD update ON TABLE post TYPE datetime VALUE $before OR time::now();
DEFINE FIELD created ON TABLE post TYPE datetime VALUE time::now();
`;
data = await fetchQuerySQL(query)
console.log(data)
}
function jsPretty(_data){
console.log(JSON.stringify(_data,null,2 ))
}
async function mainPoint(){
//let result;
let data;
let query;
let token;
//simple set up
await setupUser();
await setupToDoList();
await queryDB();
//surrealdb 1.0.0 beta 8 format result is json
//token = await signUp({email:'test1',pass:'test'})
//data = await signIn({email:'test1',pass:'test'});
//console.log(token)
data = await signUp() // test@test.test , pass
//data = await signIn(); // test@test.test , pass
//it has return json as object
console.log(data)
if(data?.details != null && data?.details==='Authentication succeeded'){
token = data.token
//console.log(token)
}else{
new Error('Fail Auth!');
}
//let userID = parseUserID(token)
//console.log(userID)
// TASK LIST
console.log("task list")
await getTasks(token);
//console.log("add list")
// ADD TASK
//let idran = crypto.randomUUID()
//console.log(idran)
//await addTask(token, "Hello " + idran)
console.log("POST task")
await postTaskTest(token)
// DELETE TASK
//await deleteTaskID(token, 'todolist:mponzmtgsaxu3ivm6m3q')
// UPDATE TASK?
}
mainPoint();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment