Giter Site home page Giter Site logo

surrealdb / surrealdb.js Goto Github PK

View Code? Open in Web Editor NEW
251.0 19.0 42.0 225 KB

SurrealDB driver for JavaScript

Home Page: https://surrealdb.com

License: Apache License 2.0

TypeScript 100.00%
surreal surrealdb database database-connector javascript-library javascript-module realtime-database iot-database deno deno-library deno-module javascript

surrealdb.js's Introduction

surrealdb.js

The official SurrealDB library for JavaScript.

Quickstart-Guide

Install

Deno

Import it with

import Surreal from "https://deno.land/x/surrealdb/mod.ts";

Note you should set a version in the url! For example https://deno.land/x/[email protected]/mod.ts

NodeJS, or browser with a bundler

For NodeJS or a browser with bundler (for example: rollup, vite, or webpack) you can just: install the npm package:

npm i surrealdb.js
# or with yarn
yarn add surrealdb.js
# or with pnpm
pnpm i surrealdb.js

then, just import it with:

import Surreal from "surrealdb.js";

or when you use CommonJS

const { Surreal } = require("surrealdb.js");

CDN for Browser

For fast prototyping we provide a browser-ready bundle. You can import it with

import Surreal from "https://unpkg.com/surrealdb.js";
// or
import Surreal from "https://cdn.jsdelivr.net/npm/surrealdb.js";

NOTE: this bundle is not optimized for production! So don't use it in production!

Getting started

Here you have a simple example!

This example uses top level await wich is available in deno, node >= 14.8, modern browsers (https://caniuse.com/mdn-javascript_operators_await_top_level).

import { Surreal, RecordId, Table } from "surrealdb.js";

const db = new Surreal();

// Connect to the database
await db.connect("http://127.0.0.1:8000/rpc");

// Signin as a namespace, database, or root user
await db.signin({
	username: "root",
	password: "root",
});

// Select a specific namespace / database
await db.use({ 
	namespace: "test", 
	database: "test" 
});

// Create a new person with a random id
let created = await db.create("person", {
	title: "Founder & CEO",
	name: {
		first: "Tobie",
		last: "Morgan Hitchcock",
	},
	marketing: true,
});

// Update a person record with a specific id
let updated = await db.merge(new RecordId('person', 'jaime'), {
	marketing: true,
});

// Select all people records
let people = await db.select("person");

// Perform a custom advanced query
let groups = await db.query(
	"SELECT marketing, count() FROM $tb GROUP BY marketing",
	{
		tb: new Table("person"),
	},
);

More informations

The docs of this libary are located at https://surrealdb.com/docs/integration/libraries/javascript

Contribution notes

Local setup

This is a Deno project, not NodeJS. For example, this means import paths include the .ts file extension. However, to also support other JavaScript environments, a build has been added to create a npm package that works for NodeJS, Bun, browsers with bundlers.

Supported environments

Requirements

  • Deno
  • SurrealDB (for testing)

Build for all supported environments

For Deno, no build is needed. For all other environments run

deno task build.

Formatting

deno fmt

Linting

deno lint

Run tests

deno test --allow-net --allow-run --trace-leaks

PRs

Before you commit, please format and lint your code accordingly to check for errors, and ensure all tests still pass

Local setup

For local development the Deno extension for VSCode is helpful (hint: local Deno installation required).

Directory structure

  • ./mod.ts is the deno entypoint. This is just a reexport of ./src/index.ts
  • ./deno.json include settings for linting, formatting and testing.
  • ./compile.ts include the build script for the npm package.
  • ./src includes all source code. ./src/index.ts is the main entrypoint.
  • ./npm is build by ./compile.ts and includes the generated npm package.
  • ./tests includes all test files.

surrealdb.js's People

Contributors

aessedai avatar bdombro avatar chooks22 avatar karolskolasinski avatar kearfy avatar koba-ninkigumi avatar macjuul avatar martinschaer avatar mathe42 avatar meppu avatar moresdavidewayan avatar naisofly avatar nipodemos avatar oberbeck avatar oliver-oloughlin avatar pgilbertschmitt avatar sasial-dev avatar tai-kun avatar tobiemh avatar welpie21 avatar yutaura avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

surrealdb.js's Issues

update should not replace whole record

When updating a record using the update(id, newData) function I would expect that the database only modifies and appends the fields that are also present in the newData object.
Currently the whole record gets replaced with newData

When used in tests I get "leaking async ops"

Specifically this is what I'm having:

error: AssertionError: Test case is leaking async ops.

 - 1 async operation to sleep for a duration was started in this test, but never completed. This is often caused by not cancelling a `setTimeout` or `setInterval` call.
 - 1 async operation to receive the next message on a WebSocket was started in this test, but never completed. This is often caused by not closing a `WebSocket` or `WebSocketStream`.

I'm calling db.close() in the afterAll callback and I can confirm that the db.close() executes however it still lefts some async ops not finished.

feat: browser cdn build

Add a build file that can be directly importet into the browser without a bundler.

This will allow an better experience for fast prototyping

db.create does not throw an error if a string contains '\n', it just hangs

I'm trying to import 17652 rows from SQL Server to SurrealDB to make some tests.
I wrote a small nodejs script that connects to SQL Server, reads the contents of a table and then calls db.create for each row (maybe a bulk insert method in the future? :D)

After exactly 9360 rows, every time I tested it, the script just hangs on a db.create and never returns.
I'm using the standard docker container version of SurrealDB running on Docker Desktop.

import sql from "mssql";
import Surreal from "surrealdb.js";
import _ from "lodash";

async function main() {
    const db = new Surreal("http://localhost:8000/rpc");

    const config = {
        server: "###",
        user: "###",
        password: "###",
        database: "###",
        options: {
            encrypt: false,
        },
    };

    console.log("Connecting to SQL Server...");
    await sql.connect(config);

    console.log("Connecting to SurrealDB...");
    await db.signin({
        user: "###",
        pass: "###",
    });
    await db.use("test", "test");

    console.log("Reading rows from the Table...");
    const result = await sql.query`SELECT * FROM <tableName>`;

    for (const row of result.recordset) {
        await db.create(
            "item:" + row.Id,
            row
        );
    }
    await sql.close();
    db.close();

    console.log("DONE!");
}

main();

The script is pretty simple as shown above.
After it hangs, selecting from SurrealDB shows that exactly 9360 rows where created, on a total of 17652 to be created.

SELECT count() FROM task GROUP BY ALL;
[
	{
		"time": "107.4225ms",
		"status": "OK",
		"result": [
			{
				"count": 9360
			}
		]
	}
]

Am I doing something wrong?

Thanks!

How to bulk insert from JS client?

Today the SurrealQL query language supports multiple-insert in a single statement as follows:

INSERT INTO company (name, founded) VALUES ('Acme Inc.', '1967-05-03'), ('Apple Inc.', '1976-04-01');

However, the JS client currently only provides db.create(), which supports a single record at at a time.

What is the best way to bulk insert when using the JS (Deno / Node / Bun) client? Should one use the raw db.query() command? If so, what is the expected syntax?

Compatibility check on connect

Switching from beta 8 to beta 9 caused a lot of trouble which made me think that it might be nice if the library had some type of compatibility check when connecting to the server.

update repository/contributor docs

In #19 we discuss how to document the usage of this library.
In addition, we should also have some documentation for this repository. Here, I am thinking about

  • repo structure
  • requirements
  • build/dev instructions
  • note on supported environments

I believe this is especially needed as we are mixing Deno, NodeJS, etc. in a project which is quite unusual.

Example node script didn't run

Quite new to node but when I ran the example script, I got this error

const db = new Surreal('http://127.0.0.1:8000/rpc');
           ^

TypeError: Surreal is not a constructor
    at Object.<anonymous> (/Users/andrewthomas/Repos/scraper-mk-2/app.js:3:12)
    at Module._compile (node:internal/modules/cjs/loader:1119:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1173:10)
    at Module.load (node:internal/modules/cjs/loader:997:32)
    at Module._load (node:internal/modules/cjs/loader:838:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
    at node:internal/main/run_main_module:18:47

Got it working by accessing the default explicitly like this:

const db = new Surreal.default('http://127.0.0.1:8000/rpc');

test: add basic tests

Currently we are heavily refactoring the codebase and brought together the deno/JS/NodeJS code base.

From here on it makes sense to add basic code coverage to assure nothing breaks with new changes.

Decisions to make:

  • Unit Test framework

strict typing internals

Each request is an object (SurrealQL object) which needs
1.  id field (random id, no necessary length, just a string)
2. method field (a string)
3. params field (an array of values)...

method can be... ping info use signup signin authenticate invalidate authenticate kill live let set query select create update change modify delete

params is an array with different requirements depending on the method...

ping empty array (ping is just used to keep connection open over some proxies - maybe set a poller to call this every 30 seconds or so)...
info empty array (used to get the current $auth object of the currently authenticated user - I'll explain better in due course)
use array with two string values [NS, DB],
    NS if set (and not undefined) will set the NAMESPACE
    DB if set (and not undefined) will set the DATABASE
signup takes one value which is an object (can accept any keys in the object)
signin takes one value which is an object (can accept any keys in the object)
authenticate takes one value which is a string (a JWT token)
invalidate empty array
kill takes one value which is a string (specifically a uuid)
live takes one value which is a string (the name of a table)
let takes two values, the first a string (the param name), the second any value (treated like JSON)
set alias for let
query takes two values, the first a string (SurrealQL query text), the second an object with any keys (parameters to be used in the sql query)
        returns an array of query results, each with an array of records (because you can send multiple statements in a single query)
select takes one value (the name of a table or a record id)
        returns an array of records (it takes just the first query resultset)
create takes two values, the first is the name of a table or a record id, the second is either undefined or an object (the record content)
        returns an array of records (it takes just the first query resultset)
update takes two values, the first is the name of a table or a record id, the second is either undefined or an object (the record content)
        returns an array of records (it takes just the first query resultset)
change takes two values, the first is the name of a table or a record id, the second is either undefined or an object (the record content)
        returns an array of records (it takes just the first query resultset)
modify takes two values, the first is the name of a table or a record id, the second is an array of JSONPatch objects to apply to the records
        returns an array of record DIFFS after thenchanges were made (it takes just the first query resultset)
delete takes one value,  the name of a table or a record id
        returns an array of records (which will be empty)

source: https://discord.com/channels/902568124350599239/1013527402674139268/1021058706080813166

mocha test hangs after calling close()

Here is a quick test file that hangs with mocha. I ran the "why-is-node-running" library at one point and I think the output from that suggests the websocket is not closing.

import { expect } from "chai";
import surreal from "surrealdb.js";

describe.only("database tests", () => {
  describe("surreal", () => {
    let dbi;
    before(async () => {
      dbi = new surreal("http://localhost:8000/rpc");
      await dbi.signin({
        user: "root",
        pass: "root"
      });
  
      await dbi.use("test", "test");
    });

    after(async () => {
      await dbi.query(`delete foo`);
      dbi.close();
    });

    it("should create something", async () => {
      const res = await dbi.query(`create foo:stuff set a=1, b="two";`);
      expect(res?.[0]?.result?.[0].b).to.equal("two");
    });
  })
});

Here's the output from "why-is-node-running"

There are 3 handle(s) keeping the process running

# DNSCHANNEL
/Users/thomasesposito/Desktop/stuff/chain-blocks/server/node_modules/ws/lib/websocket.js:1015                     - return net.connect(options);
/Users/thomasesposito/Desktop/stuff/chain-blocks/server/node_modules/ws/lib/websocket.js:841                      - req = websocket._req = request(opts);
/Users/thomasesposito/Desktop/stuff/chain-blocks/server/node_modules/ws/lib/websocket.js:85                       - initAsClient(this, address, protocols, options);
file:///Users/thomasesposito/Desktop/stuff/chain-blocks/server/node_modules/surrealdb.js/src/classes/socket.js:40
file:///Users/thomasesposito/Desktop/stuff/chain-blocks/server/node_modules/surrealdb.js/src/index.js:158
file:///Users/thomasesposito/Desktop/stuff/chain-blocks/server/node_modules/surrealdb.js/src/index.js:79
file:///Users/thomasesposito/Desktop/stuff/chain-blocks/server/test/sanity.mjs:10
/Users/thomasesposito/Desktop/stuff/chain-blocks/server/node_modules/mocha/lib/runnable.js:366                    - var result = fn.call(ctx);
/Users/thomasesposito/Desktop/stuff/chain-blocks/server/node_modules/mocha/lib/runnable.js:354                    - callFn(this.fn);
/Users/thomasesposito/Desktop/stuff/chain-blocks/server/node_modules/mocha/lib/runner.js:498                      - hook.run(function cbHookRun(err) {
/Users/thomasesposito/Desktop/stuff/chain-blocks/server/node_modules/mocha/lib/runner.js:559                      - next(0);

# Timeout
file:///Users/thomasesposito/Desktop/stuff/chain-blocks/server/node_modules/surrealdb.js/src/classes/pinger.js:12
file:///Users/thomasesposito/Desktop/stuff/chain-blocks/server/node_modules/surrealdb.js/src/index.js:115
file:///Users/thomasesposito/Desktop/stuff/chain-blocks/server/node_modules/surrealdb.js/src/classes/emitter.js:31
file:///Users/thomasesposito/Desktop/stuff/chain-blocks/server/node_modules/surrealdb.js/src/classes/emitter.js:30
file:///Users/thomasesposito/Desktop/stuff/chain-blocks/server/node_modules/surrealdb.js/src/classes/socket.js:59
/Users/thomasesposito/Desktop/stuff/chain-blocks/server/node_modules/ws/lib/event-target.js:227                    - listener.call(this, event);
/Users/thomasesposito/Desktop/stuff/chain-blocks/server/node_modules/ws/lib/websocket.js:237                       - this.emit('open');
/Users/thomasesposito/Desktop/stuff/chain-blocks/server/node_modules/ws/lib/websocket.js:983                       - websocket.setSocket(socket, head, {

# Timeout
file:///Users/thomasesposito/Desktop/stuff/chain-blocks/server/test/utils.mjs:1
file:///Users/thomasesposito/Desktop/stuff/chain-blocks/server/test/utils.mjs:1
file:///Users/thomasesposito/Desktop/stuff/chain-blocks/server/test/sanity.mjs:22

I ran an identical test with the postgres client which showed similar behavior if the close call was omitted.

SSL/TLS connection not work

Surreal.Instance.connect(RPC).then(() =>
  Surreal.Instance.signin({
    user: USER,
    pass: PASS,
  }).then(
    Surreal.Instance.use(NAMESPACE, DATABASE).then(
      () => {
        console.log("connected")
        IS_DATABASE_CONNECTED = true
      }
    ).catch(er => console.log(er))
  ).catch(er => console.log(er))
).catch(er => console.log(er));

I use the same data I use in surrealist but this connection not work. No errors givven.

.query() return strange type

Hi everyone!
I wondered about the type that the query function returns (<Proxy>).

For example, the select function returns the Array type as expected so you can simply assign it to a variable as in the following example:
зображення

But if I use the query function, it returns Proxy type, so you have to do the following data manipulation:
зображення

Is it a bug or expected behaviour?
Thanks for any reply!

Versions:
OS: macOS Ventura 13.1
Firefox: 111.0.1
Vue: 3.2.47
surrealdb.js: 0.6.0

PERMISSION doesn't work with selecting a single id

I'm using the permissions feature like

DEFINE TABLE media SCHEMALESS  
PERMISSIONS
  FOR select, update, delete WHERE user_email = $auth.email, 
  FOR create NONE;
;

I can correctly select all media with this

  let media = await db.select("media");

however selecting a particular media that exists fails

  let medium = await db.select(`${params.id}`);
RecordError: Record not found: media:01GR6XTHC4ASPSW4VQ00KN2ME1

even though that record is included in the all media selected.

For now I can just get all media and filter by id with js as a workaround. Maybe I misunderstood something, but I expected this to work.
Let me know if anything

(I'm running surrealdb from latest master commit and using the latest released version of the js lib).

Question: How can I use multiple sessions at the same time

I'm using Oak (Deno) to create a simple API with user authentication and I've stumbled across a certain scenario:

  1. User1 makes a request. This triggers a middleware to authenticate that user with the db. Part of the request is an action that takes some time (for example upload some files or wait for a timeout). After that action the database should update the user record (or perform any query that needs User1's authentication)
  2. Log in User2 within the time it takes for the action from (2) to complete. This changes the authenticated state of the db object to User2
  3. User1's action completes, but the query fails because it now tries to perform the query of User1 using the Authentication of User2

I'm sure that I'm missing some fundamental part of how this should work. The main question is: How can I use a different session for each request so that every surreal session uses their own authentication and can't be mixed up?

I could of course create new surreal objects that instantiate their own connections every time ofc. But that seems really counter intuitive and most importantly: very slow.

Hope you can help!

javascript

no types. if only it was written in typescript in the first place

Change Types on create / change methods to generic

Hi guys,

On create / change methods, the expected type is Record<string, unknown> & T;

image

But at the end the key type don't matter as we do a JSON.stringify on the object before sending it through web socket
image

Due the typing, it throws errors when passing class instances on create / change methods:

image
image

I think if we just leave the the type to be T it should fix those issues.

workflows: release script

@tobiemh asked if we can have a automatic npm publish script when a new tag is pushed. (see #24 (comment))

This issue is to discuss this. There are 2 options:

  1. Only have run npm publish on new tag
  2. Have a full worflow described as below for it.

You would trigger it manualy like in grafik
grafik

You choose what type of release you want and klick "run". The action will do (in this order):

  1. Calculate new version (depending if this is a major, minor or patch)
  2. Update package.json and commit
  3. Install npm dependencies
  4. Run npm run build
  5. Run npm run publish
  6. Add a tag with calculated version and push version

Stateless Websocket Client

Right now each client created through this SDK is opening a stateful websocket connection to SurrealDb where you need to login or switch the namespace/db before performing any operation.

await db.signin({...})
await db.use('test', 'test');

This works well in a situation where the connection is created from multiple devices, or you need real-time data, but seems to add a bit of overhead in a backend server situation (eg. API) where you need to handle multiple concurrent connections across different users, namespaces or databases. Each combination will require a new client to be opened, cached and closed server side, resulting in a lot of overhead. Essentially a single server will have hundreds, if not thusands, of websocket connections opened to the same SurrealDb instance.
Maybe this could be solved by allowing to override the user/namespace/db on each specific SQL request.

Right now I'm working around this by creating a custom Typescript SDK based on the REST interface of Surrealdb, but wanted to be sure that I'm not missing something here or if it is already possible with the current websocket connection.

Thanks

Insufficient documentation

Hi,

I would like to the the SurrealDB and I'm following the steps on the site but it doesn't work and I don't find information what's wrong.

I've started the server with docker run --name surrealdb -d -p 8000:8000 surrealdb/surrealdb:latest start as it's mentioned in the install page.
I've copied the Node.js example code from here but when I start it gives error:

ERROR r [AuthenticationError]: There was a problem with authentication
    at c.Ye (D:\Work\tmp\surrealdb-demo\node_modules\surrealdb.js\dist\lib\index.cjs:1:69967)
    at c.<anonymous> (D:\Work\tmp\surrealdb-demo\node_modules\surrealdb.js\dist\lib\index.cjs:1:66686)
    at c.r (D:\Work\tmp\surrealdb-demo\node_modules\surrealdb.js\dist\lib\index.cjs:1:52384)
    at D:\Work\tmp\surrealdb-demo\node_modules\surrealdb.js\dist\lib\index.cjs:1:52586
    at Array.forEach (<anonymous>)
    at c.value (D:\Work\tmp\surrealdb-demo\node_modules\surrealdb.js\dist\lib\index.cjs:1:52563)
    at s.<anonymous> (D:\Work\tmp\surrealdb-demo\node_modules\surrealdb.js\dist\lib\index.cjs:1:65324)
    at D:\Work\tmp\surrealdb-demo\node_modules\surrealdb.js\dist\lib\index.cjs:1:52586
    at Array.forEach (<anonymous>)
    at s.value (D:\Work\tmp\surrealdb-demo\node_modules\surrealdb.js\dist\lib\index.cjs:1:52563)

I think the problem is that, the container started without user/pass, but the example code use root for them, but if I skip them, in db.signin I've got the same problem. If I skip the whole signin I've got

ERROR Error: There was a problem with the database: The table does not exist

Surreal.wait() should return an error if ws connection is reset by the client.

Multiple components and pages are using single client websocket connection on my app. if a browser event (like refresh or back) resets the client connection, we get a hard typeerror from surreal.wait() function

TypeError: Cannot read properties of undefined (reading 'ready')
at Surreal.wait (index.ts:257:14)

let DB = new Surreal()
await DB.connect("http://localhost:8000/rpc")

await DB.signin ({user: "root", pass: "xxxx"})

await DB.use("test","test")

let info = await DB.query("INFO FOR DB;")

console.log (info)

DB = new Surreal() //To simulate browser refresh - other client events which may reset the connection from the client.

info = await DB.query("INFO FOR DB;")

console.log(info) // this statement dumps with `typeError

Can not import SurrealDB from browser

Trying to import surrealdb script directly from the browser fails:

<script src="node_modules/surrealdb.js/esm/index.js" type="module"> </script>
gives
Uncaught TypeError: The specifier “isomorphic-ws” was a bare specifier, but was not remapped to anything. Relative module specifiers must start with “./”, “../” or “/”.

<script src="node_modules/surrealdb.js/script/index.js"></script>
gives
Uncaught ReferenceError: exports is not defined

How should I go about this?

Bug: Deno - db.select() is not working as intended when passed an Id

Describe the bug

The documentation for the Deno library suggests that db.select(thing) can be used with either a table or specific record, however when passing a record Id it always fails with the following error:

RecordError: Record not found: department:40r67eog7lini8rorbr5
    at Surreal.#output (https://deno.land/x/[email protected]/src/index.ts:694:9)
    at Surreal.<anonymous> (https://deno.land/x/[email protected]/src/index.ts:442:19)
    at Surreal.f (https://deno.land/x/[email protected]/src/classes/emitter.ts:26:9)
    at https://deno.land/x/[email protected]/src/classes/emitter.ts:33:10
    at Array.forEach (<anonymous>)
    at Surreal.emit (https://deno.land/x/[email protected]/src/classes/emitter.ts:32:20)
    at Socket.<anonymous> (https://deno.land/x/[email protected]/src/index.ts:222:17)
    at https://deno.land/x/[email protected]/src/classes/emitter.ts:33:10
    at Array.forEach (<anonymous>)
    at Socket.emit (https://deno.land/x/[email protected]/src/classes/emitter.ts:32:20)

I have also tried running the RPC commands directly on the server using Insomnia which behaves as expected returning the single record when an Id is used as the parameter for select.

There is also a workaround using db.query() but its a bit clunkier.

Steps to reproduce

  1. Create and configure db instance:

SurrealDbmanager.ts

export class SurrealDbManager{
    public static instance: Surreal;

    private constructor() {}

    public static async SetupDb(url: string): Promise<Surreal> {
        try {
            console.log("Setting up db");
            this.instance = new Surreal(url);
            
            await this.instance.signin({
                user: 'root',
                pass: 'root',
            });
    
            await this.instance.use('opsys', 'dashboard')
            return this.instance;
        } catch (error) {
            logger.error(error);
            throw error;
        }
    }

}

index.ts
export const db = await SurrealDbManager.SetupDb('http://10.88.10.27:8000/rpc');

  1. Call Create() and make note of the generated id.
  2. Call GetAll() and confirm the new record exists.
  3. Attempt to retrieve the single record with GetById() using the id of the newly created record

DepartmentRepository.ts

import { db } from "../index.ts";
import { Department } from "../db/models/Department.ts";

export class DepartmentRepository{
    static async GetAll(): Promise<Department[]>{ 
        const departments = await db.select<Department>("departments");
        return departments;
    }

    static async GetById(id: string): Promise<Department>{
        const department = await db.select<Department>(id);
        return department[0];
    }

    static async Create(department: Department): Promise<Department> {
        const newDepartmentRecord = await db.create<Department>(
          'departments',
         department,
        );
        console.log(newDepartmentRecord);
        return newDepartmentRecord;
      }
      
}

Expected behaviour

db.select() should be returning the single record with the specified Id rather than generating an error.

SurrealDB version

1.0.0-beta.9+20230402.5eafebd for linux on x86_64

Contact Details

Is there an existing issue for this?

  • I have searched the existing issues

Code of Conduct

  • I agree to follow this project's Code of Conduct

unable to delete by id

I have a schema as follows:

#!/bin/bash

# See: https://gist.githubusercontent.com/koakh/fbbc37cde630bedcf57acfd4d6a6956b/raw/ec0d25ce0dba9b729f4e8d379149e4b99cced7bc/gistfile1.txt

. .env
. .env.local

DATA="DEFINE TABLE user SCHEMAFULL
  PERMISSIONS 
    FOR select FULL,
    FOR update WHERE id = \$auth.id, 
    FOR create, delete NONE;
DEFINE FIELD email ON user TYPE string;
DEFINE FIELD phone ON user TYPE string;
DEFINE FIELD username ON user TYPE string;
DEFINE FIELD createdAt ON user TYPE datetime;
DEFINE FIELD updatedAt ON user TYPE datetime;
DEFINE FIELD loggedInAt ON user TYPE datetime;
DEFINE FIELD password ON user TYPE string PERMISSIONS NONE;
DEFINE FIELD settings ON user TYPE object;
DEFINE FIELD settings.location ON user TYPE geometry (point);
DEFINE FIELD settings.timezone ON user TYPE string;
DEFINE FIELD settings.languages ON user TYPE array;
DEFINE FIELD settings.languages.* ON user TYPE string;
DEFINE FIELD settings.offset ON user TYPE string;
DEFINE FIELD verify ON user TYPE object;
DEFINE FIELD verify.email ON user TYPE object;
DEFINE FIELD verify.email.code ON user TYPE string;
DEFINE FIELD verify.email.expiration ON user TYPE datetime;
DEFINE FIELD verify.email.status ON user TYPE string;
DEFINE FIELD verify.phone ON user TYPE object;
DEFINE FIELD verify.phone.code ON user TYPE string;
DEFINE FIELD verify.phone.expiration ON user TYPE datetime;
DEFINE FIELD verify.phone.status ON user TYPE string;
DEFINE INDEX idx_email ON user COLUMNS email UNIQUE;
DEFINE INDEX idx_username ON user COLUMNS username UNIQUE;
"

curl -k -L -s --compressed POST \
	--header "Accept: application/json" \
	--header "NS: ${DB_NS}" \
	--header "DB: ${DB_DB}" \
	--user "root:root" \
	--data "${DATA}" \
	${DB_SQL_URL}


DATA="DEFINE SCOPE allusers
  -- the JWT session will be valid for 14 days
  SESSION 14d
  -- The optional SIGNUP clause will be run when calling the signup method for this scope
  -- It is designed to create or add a new record to the database.
  -- If set, it needs to return a record or a record id
  -- The variables can be passed in to the signin method
  SIGNUP ( CREATE user SET username = \$username, email = \$email, phone = \$phone, password = crypto::argon2::generate(\$password), createdAt = \$createdAt, updatedAt = \$updatedAt )
  -- The optional SIGNIN clause will be run when calling the signin method for this scope
  -- It is designed to check if a record exists in the database.
  -- If set, it needs to return a record or a record id
  -- The variables can be passed in to the signin method
  SIGNIN ( SELECT * FROM user WHERE email = \$email AND crypto::argon2::compare(password, \$password) )
  -- this optional clause will be run when calling the signup method for this scope
"

curl -k -L -s --compressed POST \
	--header "Accept: application/json" \
	--header "NS: ${DB_NS}" \
	--header "DB: ${DB_DB}" \
	--user "root:root" \
	--data "${DATA}" \
	${DB_SQL_URL}

and gigs as follows:

#!/bin/bash

. .env
. .env.local

DATA="DEFINE TABLE gigs SCHEMALESS
  PERMISSIONS 
    FOR select FULL,
    FOR create WHERE \$scope = \"allusers\",
	FOR update WHERE createdBy = \$auth.id,
	FOR delete WHERE createdBy = \$auth.id;
"
# 	-- FOR select WHERE \$scope = \"allusers\" -- limit to only users in db

curl -k -L -s --compressed POST \
	--header "Accept: application/json" \
	--header "NS: ${DB_NS}" \
	--header "DB: ${DB_DB}" \
	--user "root:root" \
	--data "${DATA}" \
	${DB_SQL_URL}

The problem is db.delete(id) doesn't work and neither does db.query(DELETE ${id}).

No errors or warnings. Just doesn't get deleted. It happens on all my projects. I believe this was fixed in this repo but there has never been a new release and its been about 3-4 months now.

Can you release surrealdb.js more frequently for us who would like to continue to use surrealdb?

I cannot recommend using this database framework if you cannot delete.

comment last merged 👍 thanks for TS

iv been trying last merged with typescript and get this observations:

  • i think should update "version": "0.3.1" to 0.3.2 maybe?
  • at package.json i have to change export types as:
    { ..., "types": "./dist/types/index.d.ts", ... }
    to avoid msg at import * from 'surrealdb.js' // error: Cannot find module 'surrealdb.js' or its corresponding type declarations.

its not easy to understand the use flow (for me)
iv been using like this at server side (nextjs api)

import Surreal from 'surrealdb.js';

const db = new Surreal('https://surreal...:8000/rpc');

try {
      await sdb.use('test', 'test');

      await sdb.signin({
        user: 'root',
        pass: 'root',
      })

      const r = await sdb.query('INFO FOR DB;');
      console.log(r) // successful 
} catch (e) { ... }

my question is,, thats ok?

what about authentication?
how to setup auth?
how about tokens?

ty in advance!

Authentication Error in NodeJS Integration

I have recently come across SurrealDB, and installed it.

After adding to path, I started the server using surreal start --log trace --user root --pass root


 .d8888b.                                             888 8888888b.  888888b.
d88P  Y88b                                            888 888  'Y88b 888  '88b
Y88b.                                                 888 888    888 888  .88P
 'Y888b.   888  888 888d888 888d888  .d88b.   8888b.  888 888    888 8888888K.
    'Y88b. 888  888 888P'   888P'   d8P  Y8b     '88b 888 888    888 888  'Y88b
      '888 888  888 888     888     88888888 .d888888 888 888    888 888    888
Y88b  d88P Y88b 888 888     888     Y8b.     888  888 888 888  .d88P 888   d88P
 'Y8888P'   'Y88888 888     888      'Y8888  'Y888888 888 8888888P'  8888888P'


[2022-09-27 17:37:44] INFO  surrealdb::iam Root authentication is enabled
[2022-09-27 17:37:44] INFO  surrealdb::iam Root username is 'root'
[2022-09-27 17:37:44] INFO  surrealdb::dbs Database strict mode is disabled
[2022-09-27 17:37:44] INFO  surrealdb::kvs Starting kvs store in memory
[2022-09-27 17:37:44] INFO  surrealdb::kvs Started kvs store in memory
[2022-09-27 17:37:44] INFO  surrealdb::net Starting web server on 0.0.0.0:8000
[2022-09-27 17:37:44] INFO  surrealdb::net Started web server on 0.0.0.0:8000

In my NodeJS app, I have the following code (adapted from your docs):

import Surreal from 'surrealdb.js';
const db = new Surreal('http://localhost:8000/rpc');

async function main() {
	try {

		// Signin as a namespace, database, or root user
		await db.signin({
			user: 'root',
			pass: 'root',
            		NS: 'practice',
            		DB: 'buybig'
		});
        	console.log('y');

		// Select a specific namespace / database
		// await db.use('practice', 'buybig');

		console.log(await db.select('users'));

	} catch (e) {
		console.error('ERROR', e);
	}
}

main();

I am getting this error:

ERROR AuthenticationError: There was a problem with authentication
    at Surreal._Surreal_signin (file:///C:/Users/jaide/OneDrive/Documents/Projects/HTMLProject/buybig/node_modules/surrealdb.js/esm/index.js:416:23)    at Surreal.<anonymous> (file:///C:/Users/jaide/OneDrive/Documents/Projects/HTMLProject/buybig/node_modules/surrealdb.js/esm/index.js:225:111)   
    at Surreal.f (file:///C:/Users/jaide/OneDrive/Documents/Projects/HTMLProject/buybig/node_modules/surrealdb.js/esm/classes/emitter.js:28:18)     
    at file:///C:/Users/jaide/OneDrive/Documents/Projects/HTMLProject/buybig/node_modules/surrealdb.js/esm/classes/emitter.js:34:22
    at Array.forEach (<anonymous>)
    at Surreal.emit (file:///C:/Users/jaide/OneDrive/Documents/Projects/HTMLProject/buybig/node_modules/surrealdb.js/esm/classes/emitter.js:33:67)  
    at Socket.<anonymous> (file:///C:/Users/jaide/OneDrive/Documents/Projects/HTMLProject/buybig/node_modules/surrealdb.js/esm/index.js:126:29)     
    at file:///C:/Users/jaide/OneDrive/Documents/Projects/HTMLProject/buybig/node_modules/surrealdb.js/esm/classes/emitter.js:34:22
    at Array.forEach (<anonymous>)
    at Socket.emit (file:///C:/Users/jaide/OneDrive/Documents/Projects/HTMLProject/buybig/node_modules/surrealdb.js/esm/classes/emitter.js:33:67)   
^C

And this in my SurrealDB logs:

[2022-09-27 18:06:04] INFO  surreal::web 127.0.0.1:64675 GET /rpc HTTP/1.1 101 "-" 68.7µs

Accessing database through VSCode's Thunder Client and SurrealDB cli tool works flawlessly.

Any help is appreciated.

Environment:

  • OS: Windows 10

TypeError: Surreal is not a constructor

I tried const {Surreal} = require("surrealdb.js") too.

Code:

const Surreal = require("surrealdb.js");
const db = new Surreal("http://127.0.0.1:8000/rpc");

async function main() {
  try {
    await db.signin({
      NS: "test",
      DB: "test",
      SC: "user",
      user: "[email protected]",
      pass: "my-secret-password",
    });
  } catch (e) {
    console.error("ERROR", e);
  }
}

main();

Error:

const db = new Surreal("http://127.0.0.1:8000/rpc");
           ^

TypeError: Surreal is not a constructor
    at Object.<anonymous> (/home/jub0t/Downloads/surrealdb-benchmark/index.js:2:12)
    at Module._compile (node:internal/modules/cjs/loader:1159:14)
    at Module._extensions..js (node:internal/modules/cjs/loader:1213:10)
    at Module.load (node:internal/modules/cjs/loader:1037:32)
    at Module._load (node:internal/modules/cjs/loader:878:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
    at node:internal/main/run_main_module:23:47

Edit:
Node version: v18.12.0

Type of `db.query()` is confusing

db.query returns Promise<Result<T>[]>. This means that every object in the array has .result and or .error.

Why isn't the returned type Promise<Result<T[]>>? This would make it easier to check for occurred errors since you wouldn't have to check every single object you get back.

Would also make it much easier to pass the array of objects to another function / API response since you would need to loop over the array and push all the .result object into a new array first.

When SurrealDB encounters a fatal error, it's impossible to know where it failed at (in my own code)

As you see from the logs below, we see a stack trace, but nowhere does my own code appear in that. I can't see which of my functions caused this error, and thus, locating the source of this error is more difficult than it should be.

sourceress-bot-1  | file:///app/node_modules/surrealdb.js/src/index.ts:625
sourceress-bot-1  |                     return reject(new Error(res.error.message));
sourceress-bot-1  |                  ^
sourceress-bot-1  | Error: There was a problem with the database: Specify some SQL code to execute
sourceress-bot-1  |     at Surreal._Surreal_result (file:///app/node_modules/surrealdb.js/src/index.ts:625:18)
sourceress-bot-1  |     at Surreal.<anonymous> (file:///app/node_modules/surrealdb.js/src/index.ts:424:27)
sourceress-bot-1  |     at Surreal.f (file:///app/node_modules/surrealdb.js/src/classes/emitter.ts:26:9)
sourceress-bot-1  |     at file:///app/node_modules/surrealdb.js/src/classes/emitter.ts:33:10
sourceress-bot-1  |     at Array.forEach (<anonymous>)
sourceress-bot-1  |     at Surreal.emit (file:///app/node_modules/surrealdb.js/src/classes/emitter.ts:32:20)
sourceress-bot-1  |     at Socket.<anonymous> (file:///app/node_modules/surrealdb.js/src/index.ts:222:17)
sourceress-bot-1  |     at file:///app/node_modules/surrealdb.js/src/classes/emitter.ts:33:10
sourceress-bot-1  |     at Array.forEach (<anonymous>)
sourceress-bot-1  |     at Socket.emit (file:///app/node_modules/surrealdb.js/src/classes/emitter.ts:32:20)

Surreal.create returns an array when the id is randomly generated

import Surreal from "https://deno.land/x/surrealdb/mod.ts";

const db = new Surreal(URL);
const result = await db.create("person", {
	title: "Founder & CEO",
	name: {
		first: "Tobie",
		last: "Morgan Hitchcock",
	},
	marketing: true,
	identifier: Math.random().toString(36).substr(2, 10),
});

result should contain an object representing the newly created record.
An array of objects containing a single object is returned instead.

Code example using variables throws parse error

This snippet is documented here: https://surrealdb.com/docs/surrealql/parameters

let people = await db.query("SELECT * FROM article WHERE status IN $status", {
  status: ["live", "draft"],
});

It does not seem to work however:
Error: There was a problem with the database: Parse error on line 1 at character 35 when parsing 'IN $status'

Environment:

> deno --version
deno 1.23.2 (release, x86_64-pc-windows-msvc)
v8 10.4.132.8
typescript 4.7.2
> surreal version
surreal 1.0.0-beta.7 for windows on x86_64

Empty table should return empy array instead of an error

Currently the client returns an error, if there are no entries in a table.

  let all = await db.select("products");
  console.log("all", JSON.stringify(all, null, 2));

throws

file:///home/user/Projects/bestproductinsight-com/scripts/node_modules/.pnpm/[email protected]/node_modules/surrealdb.js/esm/index.js:414
    throw new error(errormessage);
          ^

RecordError: Record not found: 3
    at Surreal._Surreal_outputHandler (file:///home/user/Projects/bestproductinsight-com/scripts/node_modules/.pnpm/[email protected]/node_modules/surrealdb.js/esm/index.js:414:11)
    at Surreal.select (file:///home/user/Projects/bestproductinsight-com/scripts/node_modules/.pnpm/[email protected]/node_modules/surrealdb.js/esm/index.js:317:94)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async file:///home/user/Projects/bestproductinsight-com/scripts/generate-content/test-db.js:46:13

The query equivalent works as expected.

  let all = await db.query("SELECT * FROM products;");
  console.log("all", JSON.stringify(all, null, 2));

returns

all [
  {
    "result": [],
    "status": "OK",
    "time": "92.23µs"
  }
]

Exporting surrealdb dependent funcs not working

When i import my file called database.ts that contains all my functions that use the surrealDB.js
library it does not work as excepted meaning it the functions do not work at all when called from my index.ts. They do not return any error aswell. I resolved this issue by including all the code from my database.ts into my index.ts which solved my issue. I was told by Alexander Fridriksson#0480 this could be a Async issue. Please let me know what you need from me that could help solve this issue

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.