Giter Site home page Giter Site logo

dgraph-js's Introduction

dgraph-js npm version Build Status Coverage Status

Official Dgraph client implementation for JavaScript (Node.js v6 and above), using gRPC.

Use Discuss Issues for reporting issues about this repository.

Looking for browser support? Check out dgraph-js-http.

This client follows the Dgraph Go client closely.

Before using this client, we highly recommend that you go through docs.dgraph.io, and understand how to run and work with Dgraph.

Table of contents

Install

Install using npm:

npm install dgraph-js @grpc/grpc-js --save
# If you are using Typescript, you might also need:
# npm install @types/google-protobuf @types/protobufjs --save-dev

or yarn:

yarn add dgraph-js @grpc/grpc-js
# If you are using Typescript, you might also need:
# yarn add @types/google-protobuf @types/protobufjs --dev

Supported Versions

Depending on the version of Dgraph that you are connecting to, you will have to use a different version of this client.

Dgraph version dgraph-js version
1.0.X 1.X.Y
1.1.X 2.X.Y
20.03.0 20.03.0
21.03.0 21.03.0

Note: Only API breakage from v1.X.Y to v2.X.Y is in the function DgraphClient.newTxn().mutate(). This function returns a messages.Assigned type in v1.X but a messages.Response type in v2.X.

Quickstart

Build and run the simple project in the examples folder, which contains an end-to-end example of using the Dgraph JavaScript client. Follow the instructions in the README of that project.

Using a Client

Creating a Client

A DgraphClient object can be initialised by passing it a list of DgraphClientStub clients as variadic arguments. Connecting to multiple Dgraph servers in the same cluster allows for better distribution of workload.

The following code snippet shows just one connection.

const dgraph = require("dgraph-js");
const grpc = require("@grpc/grpc-js");

const clientStub = new dgraph.DgraphClientStub(
  // addr: optional, default: "localhost:9080"
  "localhost:9080",
  // credentials: optional, default: grpc.credentials.createInsecure()
  grpc.credentials.createInsecure(),
);
const dgraphClient = new dgraph.DgraphClient(clientStub);

To facilitate debugging, debug mode can be enabled for a client.

Multi-tenancy

In multi-tenancy environments, dgraph-js provides a new method loginIntoNamespace(), which will allow the users to login to a specific namespace.

In order to create a JavaScript client, and make the client login into namespace 123:

const dgraphClientStub = new dgraph.DgraphClientStub("localhost:9080");
await dgraphClientStub.loginIntoNamespace("groot", "password", 123); // where 123 is the namespaceId 

In the example above, the client logs into namespace 123 using username groot and password password. Once logged in, the client can perform all the operations allowed to the groot user of namespace 123.

Creating a Client for Dgraph Cloud Endpoint

If you want to connect to Dgraph running on your Dgraph Cloud instance, then all you need is the URL of your Dgraph Cloud endpoint and the API key. You can get a client using them as follows:

const dgraph = require("dgraph-js");

const clientStub = dgraph.clientStubFromCloudEndpoint(
  "https://frozen-mango.eu-central-1.aws.cloud.dgraph.io/graphql",
  "<api-key>"
);
const dgraphClient = new dgraph.DgraphClient(clientStub);

Note: the clientStubFromSlashGraphQLEndpoint method is deprecated and will be removed in the next release. Instead use clientStubFromCloudEndpoint method.

Altering the Database

To set the schema, create an Operation object, set the schema and pass it to DgraphClient#alter(Operation) method.

const schema = "name: string @index(exact) .";
const op = new dgraph.Operation();
op.setSchema(schema);
await dgraphClient.alter(op);

Starting Dgraph version 20.03.0, indexes can be computed in the background. You can set setRunInBackground field of the Operation object to true before passing it to the DgraphClient#alter(Operation) method. You can find more details here.

const schema = "name: string @index(exact) .";
const op = new dgraph.Operation();
op.setSchema(schema);
op.setRunInBackground(true);
await dgraphClient.alter(op);

NOTE: Many of the examples here use the await keyword which requires async/await support which is available on Node.js >= v7.6.0. For prior versions, the expressions following await can be used just like normal Promise:

dgraphClient.alter(op)
    .then(function(result) { ... }, function(err) { ... })

Operation contains other fields as well, including drop predicate and drop all. Drop all is useful if you wish to discard all the data, and start from a clean slate, without bringing the instance down.

// Drop all data including schema from the Dgraph instance. This is useful
// for small examples such as this, since it puts Dgraph into a clean
// state.
const op = new dgraph.Operation();
op.setDropAll(true);
await dgraphClient.alter(op);

Creating a Transaction

To create a transaction, call DgraphClient#newTxn() method, which returns a new Txn object. This operation incurs no network overhead.

It is good practise to call Txn#discard() in a finally block after running the transaction. Calling Txn#discard() after Txn#commit() is a no-op and you can call Txn#discard() multiple times with no additional side-effects.

const txn = dgraphClient.newTxn();
try {
  // Do something here
  // ...
} finally {
  await txn.discard();
  // ...
}

To create a read-only transaction, set readOnly boolean to true while calling DgraphClient#newTxn() method. Read-only transactions cannot contain mutations and trying to call Txn#mutate() or Txn#commit() will result in an error. Calling Txn.Discard() will be a no-op.

You can optionally set the bestEffort boolean to true. This may yield improved latencies in read-bound workloads where linearizable reads are not strictly needed.

const txn = dgraphClient.newTxn({
  readOnly: true,
  bestEffort: false
});
// ...
const res = await txn.queryWithVars(query, vars);

Running a Mutation

Txn#mutate(Mutation) runs a mutation. It takes in a Mutation object, which provides two main ways to set data: JSON and RDF N-Quad. You can choose whichever way is convenient.

We define a person object to represent a person and use it in a Mutation object.

// Create data.
const p = {
    name: "Alice",
};

// Run mutation.
const mu = new dgraph.Mutation();
mu.setSetJson(p);
await txn.mutate(mu);

For a more complete example with multiple fields and relationships, look at the simple project in the examples folder.

Sometimes, you only want to commit a mutation, without querying anything further. In such cases, you can use Mutation#setCommitNow(true) to indicate that the mutation must be immediately committed.

Mutation#setIgnoreIndexConflict(true) can be applied on a Mutation object to not run conflict detection over the index, which would decrease the number of transaction conflicts and aborts. However, this would come at the cost of potentially inconsistent upsert operations.

Mutation can be run using txn.doRequest as well.

const mu = new dgraph.Mutation();
mu.setSetJson(p);

const req = new dgraph.Request();
req.setCommitNow(true);
req.setMutationsList([mu]);

await txn.doRequest(req);

Running a Query

You can run a query by calling Txn#query(string). You will need to pass in a GraphQL+- query string. If you want to pass an additional map of any variables that you might want to set in the query, call Txn#queryWithVars(string, object) with the variables object as the second argument.

The response would contain the method Response#getJSON(), which returns the response JSON.

Let’s run the following query with a variable $a:

query all($a: string) {
  all(func: eq(name, $a))
  {
    name
  }
}

Run the query, deserialize the result from Uint8Array (or base64) encoded JSON and print it out:

// Run query.
const query = `query all($a: string) {
  all(func: eq(name, $a))
  {
    name
  }
}`;
const vars = { $a: "Alice" };
const res = await dgraphClient.newTxn().queryWithVars(query, vars);
const ppl = res.getJson();

// Print results.
console.log(`Number of people named "Alice": ${ppl.all.length}`);
ppl.all.forEach((person) => console.log(person.name));

This should print:

Number of people named "Alice": 1
Alice

You can also use txn.doRequest function to run the query.

const req = new dgraph.Request();
const vars = req.getVarsMap();
vars.set("$a", "Alice");
req.setQuery(query);

const res = await txn.doRequest(req);
console.log(JSON.stringify(res.getJson()));

Running an Upsert: Query + Mutation

The txn.doRequest function allows you to run upserts consisting of one query and one mutation. Query variables could be defined and can then be used in the mutation. You can also use the txn.doRequest function to perform just a query or a mutation.

To know more about upsert, we highly recommend going through the docs at https://docs.dgraph.io/mutations/#upsert-block.

const query = `
  query {
      user as var(func: eq(email, "[email protected]"))
  }`

const mu = new dgraph.Mutation();
mu.setSetNquads(`uid(user) <email> "[email protected]" .`);

const req = new dgraph.Request();
req.setQuery(query);
req.setMutationsList([mu]);
req.setCommitNow(true);

// Upsert: If wrong_email found, update the existing data
// or else perform a new mutation.
await dgraphClient.newTxn().doRequest(req);

Running a Conditional Upsert

The upsert block allows specifying a conditional mutation block using an @if directive. The mutation is executed only when the specified condition is true. If the condition is false, the mutation is silently ignored.

See more about Conditional Upsert Here.

const query = `
  query {
      user as var(func: eq(email, "[email protected]"))
  }`

const mu = new dgraph.Mutation();
mu.setSetNquads(`uid(user) <email> "[email protected]" .`);
mu.setCond(`@if(eq(len(user), 1))`);

const req = new dgraph.Request();
req.setQuery(query);
req.addMutations(mu);
req.setCommitNow(true);

await dgraphClient.newTxn().doRequest(req);

Committing a Transaction

A transaction can be committed using the Txn#commit() method. If your transaction consisted solely of calls to Txn#query or Txn#queryWithVars, and no calls to Txn#mutate, then calling Txn#commit() is not necessary.

An error will be returned if other transactions running concurrently modify the same data that was modified in this transaction. It is up to the user to retry transactions when they fail.

const txn = dgraphClient.newTxn();
try {
  // ...
  // Perform any number of queries and mutations
  // ...
  // and finally...
  await txn.commit();
} catch (e) {
  if (e === dgraph.ERR_ABORTED) {
    // Retry or handle exception.
  } else {
    throw e;
  }
} finally {
  // Clean up. Calling this after txn.commit() is a no-op
  // and hence safe.
  await txn.discard();
}

Cleanup Resources

To cleanup resources, you have to call DgraphClientStub#close() individually for all the instances of DgraphClientStub.

const SERVER_ADDR = "localhost:9080";
const SERVER_CREDENTIALS = grpc.credentials.createInsecure();

// Create instances of DgraphClientStub.
const stub1 = new dgraph.DgraphClientStub(SERVER_ADDR, SERVER_CREDENTIALS);
const stub2 = new dgraph.DgraphClientStub(SERVER_ADDR, SERVER_CREDENTIALS);

// Create an instance of DgraphClient.
const dgraphClient = new dgraph.DgraphClient(stub1, stub2);

// ...
// Use dgraphClient
// ...

// Cleanup resources by closing all client stubs.
stub1.close();
stub2.close();

Debug mode

Debug mode can be used to print helpful debug messages while performing alters, queries and mutations. It can be set using theDgraphClient#setDebugMode(boolean?) method.

// Create a client.
const dgraphClient = new dgraph.DgraphClient(...);

// Enable debug mode.
dgraphClient.setDebugMode(true);
// OR simply dgraphClient.setDebugMode();

// Disable debug mode.
dgraphClient.setDebugMode(false);

Setting Metadata Headers

Metadata headers such as authentication tokens can be set through the context of gRPC methods. Below is an example of how to set a header named "auth-token".

// The following piece of code shows how one can set metadata with
// auth-token, to allow Alter operation, if the server requires it.

var meta = new grpc.Metadata();
meta.add('auth-token', 'mySuperSecret');

await dgraphClient.alter(op, meta);

Examples

  • simple: Quickstart example of using dgraph-js.
  • tls: Example of using dgraph-js with a Dgraph cluster secured with TLS.

Development

Building the source

npm run build

If you have made changes to the proto/api.proto file, you need need to regenerate the source files generated by Protocol Buffer tools. To do that, install the Protocol Buffer Compiler and then run the following command:

npm run build:protos

Running tests

Make sure you have a Dgraph server running on localhost before you run this task.

npm test

dgraph-js's People

Contributors

all-seeing-code avatar bucanero avatar danielmai avatar dependabot[bot] avatar emhagman avatar gpahal avatar joshua-goldstein avatar manishrjain avatar micheldiz avatar minhaj-shakeel avatar nick-w-nick avatar ondrowan avatar prashant-shahi avatar ryanfoxtyler avatar shivaji-dgraph avatar sleto-it avatar vardhanapoorv avatar vmrajas avatar znarkus 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

dgraph-js's Issues

Please use * with delete operation for non-list type: [_predicate_]

Hello - quick question!

mu.setDeleteJson([ { 'topic.external.wikidata': null, uid: '0x9c671a' } ]);

Returns:

2 UNKNOWN: Please use * with delete operation for non-list type: [_predicate_]

The predicate topic.external.wikidata is a int, non-list.

Anything I am missing? I want to delete the predicate topic.external.wikidata for the uid specified.

Updating Data

i haven't found any way to update data via mutation. With Ratel it looks like this:

{
    set {
        <0xf9078> <password> "xyz" .
     }
 }

How to implement this with dgraph-js and json? Is there some documentation i haven't found?

Cheers

Cleaning up after performing an Operation

The Readme discusses how to perform and clean up after transactions, but only discusses how to perform operations, such as updating the schema. In production, is it necessary to clean up after operations, such as closing or discarding the Operation object? An example in the Readme would be great!

Error: Received message larger than max

We are getting an error in the JS client using grpc
“Received message larger than max (4194538 vs. 4194304)“.

I noticed that this limitation was addressed in the golang client.
dgraph-io/dgraph#396

Can we open this up on the JS client as well?

Looks like the ability to pass option to the client was added 5 days ago.
f3bde42

Wondering if I can pass an option in like this:
grpc/grpc#8098

Do these options flow through to the grpc client, or is it a different set of options?

We'd like to be able to do something like this:

  const clientStub = new DgraphClientStub(
    server, 
    credentials.createInsecure(), 
    {'grpc.max_receive_message_length': 1024 * 1024 * 1024}
  )

(updated with working config setting)

No default ES module export when using `import dgraph from "dgraph-js"`

I'm currently bundling my server project using webpack, while using babel-loader for the transpilation (set with the modules: false option so module import code is handled by webpack.

When importing dgraph-js, it throws a runtime error if I import it without star, but works fine with the star import:

import dgraph from 'dgraph-js' // ERROR in runtime
import * as dgraph from 'dgraph-js' // OK

The last time the package was published was about 6 months ago, not sure if trying again with a newer version of TypeScript would help, perhaps using the esModuleInterop: true flag?

CI Setup

  • Travis Setup
  • Appveyor Setup
  • Coverage Badge

Error parsing JSON from getData()

The code I'm running looks like

  const schema = `
    name: string @index(fulltext) .
    email: string @index(exact) .
  `;
  const op = new dgraph.Operation();
  op.setSchema(schema);
  const result = await dgraphClient.alter(op);
  return result.getData();

However, the getData() call is reporting a JSON parse error:

SyntaxError: Unexpected end of JSON input
    at JSON.parse (<anonymous>)
    at Payload.getData (/home/aryzing/workspace/anccre-server/node_modules/dgraph-js/lib/types.js:30:21)

Fetch health condition (enhancement)

Is it possible to add a fetch to the health condition of the instance?

I would like to make routine checks within my application.
Without having to turn to Prometheus / Grafana.

In my case, the Dgraph Server instance and Zero are behind an API. I do not expose them. I've tried using isomorphic-fetch but the result format is not compatible. And as I'm using Rancher, it gets tricky to keep exact internal domainname.

fetch('http://192.168.1.200:8089/health')
  .then(function(response) {
    if (response.status >= 400) {
      throw new Error('Bad response from server');
    }
    return response.json();
  })
  .then(function(response) {
    console.log(response.json());
  });

It would be possible?

Thanks.

Cheers.

[Question] Why can queryWithVars variables only be strings, not ints?

it("should ignore properties with non-string values", async () => {
const res = await client.newTxn().queryWithVars(
"query me($a: string) { me(func: eq(name, $a)) { name }}",
{
$a: 1, // non-string properties are ignored
},
);
const resJson: {
me: { name: string }[];
} = res.getJson(); // tslint:disable-line no-unsafe-any
expect(resJson.me).toHaveLength(0);
});

I have a query function that looks like this:

const getUsers = async ({ first = 50, after = '0x0' }: PaginationArgs): Promise<PageType | null | Error> => {
	const query = `query getUsers($first: number, $after: string) {
		getUsers(func: eq(type, "user"), first: $first, after: $after)  {
			${userFields}
		}
	}`
	const vars = {
		$first: first,
		$after: after
	}
	const result = await db.newTxn().queryWithVars(query, vars))
	return result
}

One issue is that this variable is simply discarded, then I get the error:
Error: 2 UNKNOWN: : strconv.ParseInt: parsing "": invalid syntax - this would be much more helpful if it said something like "Only strings are allowed as variables"

I can then get this working if I do this:

	const query = `query getUsers($first: string, $after: string) {
	// change 'number' to 'string'    ----^
	//...

	const vars = {
		$first: first.toString(),
		$after: after
	}

But then, it's just going to be parsed back to an Int internally. Why not allow for ints in the first place?

Mutations doesn't persist immediatly after calling "commit"

public async confirmaUsuarioViaUuid(uuid: string) {
        const query = `query user($id: string){
            user(func: eq(uuid, $id)) @filter(has(mUser)) {
              uid              
            }
          }`;

        const txn = this._client.newTxn();
        const res = await txn.queryWithVars(query, { $id: uuid });
        const arrUser = res.getJson().user;

        d("arr -> %O", arrUser)
        
        if (arrUser.length === 0) {
            await txn.discard()
            throw new Error("Uuid nao existe.");
        }
        const uid: string = arrUser[0].uid
        try {            
            const data = new Date();
            const p = {
                uid,
                [fieldNames.confirmado]: true,
                [fieldNames.dataAtualizacao]: data,
            };            
            const mu = new dgraph.Mutation();
            mu.setCommitNow(true);
            await mu.setSetJson(p); 
            const assigned = await txn.mutate(mu);
            d("assigned --- ")
            await txn.commit();
            // COMMIT ------------------------------------------
            d("commit --- ")
            assigned.getUidsMap().forEach((id, key) => d(`\n\n\t${key} => ${id}\n\n`));             
            return p;
        } finally {
            await txn.discard();
            d("foi --- ")
        }
    }

I am testing the above method. When I use ratel to see if the changes were persisted I can confirm they were, but my test always show the debug messages "assigned --- ", "commit --- " and "foi --- " after the test been runned. My test is not the problem since I make a call to that method and AFTER the method returns I do another cal to the function below:

public async queryUserByUuid(uuid: string): Promise<any> {
        const query = `query user($id: string){
            user(func: eq(uuid, $id)) @filter(has(mUser)) {
              uid
              uuid
              email
              confirmado
            }
          }`;
        const vars = { $id: uuid };
        const tnx = this._client.newTxn()
        const res = await tnx.queryWithVars(query, vars);
        const ppl = res.getJson();
        await tnx.discard();
        d("query --> %O", ppl.user[0]);
        return ppl.user[0];
    }

The value "confirmado" I receive after calling the second method is still undefined for a moment. If I put a setTimeout on it it returns "true" as expected. I concluded that the "commit" call on the transaction still takes some milisseconds to fully concludes but releases the method before...

Am I missing something or it is really a bug ?

Serialization type Uint8/base64 as a DgraphClientStub() option

The dgraph-js documentation qoutes: "You will need to deserialize it before you can do anything useful with it."
Since we are completely in JavaScript land when using dgraph-js, we as node/js developers only deal with JavaScript objects. Why would we then still need to imperatively do the serialization and de-serialization (Uint8/base64/JSON) in our JavaScript code. This imperative repetitive task is a great opportunity to be handled completely by dgraph-js. Data fetching libraries like axios do the same thing: you give it a JavaScript Object (axios does the JSON.stringify internally) and it returns a JavaScript Object (axios does the JSON.parse internally). Suggestion: implementing serialization type Uint8/base64 as a DgraphClientStub() option? so that dgraph-js accepts plain JavaScript Objects and returns plain JavaScript object and does the correct serialization/de-serialization intenally based on the chosen DgraphClientStub() serialization option ('Uint8' or 'base64' ) so we "don't need to deserialize it before you can do anything useful with it." ;-)

TypeError: Channel's second argument must be a ChannelCredentials

I can use it perfectly without setting the credentials for gRPC. But I do not know if that would be a problem.

const clientStub = new dgraph.DgraphClientStub(
  // addr: optional, default: "localhost:9080"
  "192.168.99.100:9080",
  // credentials: optional, default: grpc.credentials.createInsecure()//
  grpc.credentials.createInsecure()
);

Here my dependencies

"dependencies": {
   "@babel/polyfill": "7.0.0-beta.32",
   "bluebird": "^3.5.1",
   "body-parser": "^1.18.2",
   "classnames": "^2.2.5",
   "cookie-parser": "^1.4.3",
   "core-js": "^2.5.1",
   "dgraph-js": "0.9.4-beta.1",
   "dgraph-node": "^0.1.9",
   "express": "^4.16.2",
   "express-graphql": "^0.6.11",
   "express-jwt": "^5.3.0",
   "graphql": "^0.11.7",
   "history": "^4.7.2",
   "isomorphic-style-loader": "^4.0.0",
   "jsonwebtoken": "^8.1.0",
   "node-fetch": "^1.7.3",
   "normalize.css": "^7.0.0",
   "passport": "^0.4.0",
   "passport-facebook": "^2.1.1",
   "pretty-error": "^2.1.1",
   "prop-types": "^15.6.0",
   "query-string": "^5.0.1",
   "react": "^16.1.1",
   "react-dom": "^16.1.1",
   "sequelize": "^4.22.6",
   "serialize-javascript": "^1.3.0",
   "source-map-support": "^0.5.0",
   "sqlite3": "^3.1.8",
   "universal-router": "^5.0.0",
   "whatwg-fetch": "^2.0.3"
 },
 "devDependencies": {
   "@babel/core": "7.0.0-beta.32",
   "@babel/node": "7.0.0-beta.32",
   "@babel/plugin-transform-react-constant-elements": "7.0.0-beta.32",
   "@babel/plugin-transform-react-inline-elements": "7.0.0-beta.32",
   "@babel/preset-env": "7.0.0-beta.32",
   "@babel/preset-flow": "7.0.0-beta.32",
   "@babel/preset-react": "7.0.0-beta.32",
   "@babel/preset-stage-2": "7.0.0-beta.32",
   "assets-webpack-plugin": "^3.5.1",
   "autoprefixer": "^7.1.6",
   "babel-core": "^7.0.0-0",
   "babel-eslint": "^8.0.2",
   "babel-jest": "^21.2.0",
   "babel-loader": "8.0.0-beta.0",
   "babel-plugin-transform-react-remove-prop-types": "^0.4.10",
   "browser-sync": "^2.18.13",
   "chokidar": "^1.7.0",
   "css-loader": "^0.28.7",
   "enzyme": "^3.1.1",
   "eslint": "^4.11.0",
   "eslint-config-airbnb": "^16.1.0",
   "eslint-config-prettier": "^2.7.0",
   "eslint-import-resolver-node": "^0.3.1",
   "eslint-loader": "^1.9.0",
   "eslint-plugin-css-modules": "^2.7.5",
   "eslint-plugin-flowtype": "^2.39.1",
   "eslint-plugin-import": "^2.8.0",
   "eslint-plugin-jsx-a11y": "^6.0.2",
   "eslint-plugin-prettier": "^2.3.1",
   "eslint-plugin-react": "^7.4.0",
   "file-loader": "^1.1.5",
   "flow-bin": "^0.59.0",
   "front-matter": "^2.3.0",
   "glob": "^7.1.2",
   "husky": "^0.14.3",
   "identity-obj-proxy": "^3.0.0",
   "jest": "^21.2.1",
   "jscodeshift": "^0.3.32",
   "lint-staged": "^5.0.0",
   "markdown-it": "^8.4.0",
   "mkdirp": "^0.5.1",
   "null-loader": "^0.1.1",
   "pixrem": "^4.0.1",
   "pleeease-filters": "^4.0.0",
   "postcss": "^6.0.14",
   "postcss-calc": "^6.0.1",
   "postcss-color-function": "^4.0.1",
   "postcss-custom-media": "^6.0.0",
   "postcss-custom-properties": "^6.2.0",
   "postcss-custom-selectors": "^4.0.1",
   "postcss-flexbugs-fixes": "^3.2.0",
   "postcss-import": "^11.0.0",
   "postcss-loader": "^2.0.8",
   "postcss-media-minmax": "^3.0.0",
   "postcss-nested": "^2.1.2",
   "postcss-nesting": "^4.2.1",
   "postcss-pseudoelements": "^5.0.0",
   "postcss-selector-matches": "^3.0.1",
   "postcss-selector-not": "^3.0.1",
   "prettier": "^1.8.2",
   "raw-loader": "^0.5.1",
   "react-deep-force-update": "^2.1.1",
   "react-dev-utils": "^4.2.1",
   "react-error-overlay": "^3.0.0",
   "react-test-renderer": "^16.1.1",
   "rimraf": "^2.6.2",
   "stylelint": "^8.2.0",
   "stylelint-config-standard": "^17.0.0",
   "stylelint-order": "^0.7.0",
   "svg-url-loader": "^2.3.0",
   "url-loader": "^0.6.2",
   "webpack": "^3.8.1",
   "webpack-bundle-analyzer": "^2.9.1",
   "webpack-dev-middleware": "^1.12.0",
   "webpack-hot-middleware": "^2.20.0",
   "webpack-node-externals": "^1.6.0"
 }

Add txn.ts to exports from index.ts?

I noticed that src/txn.ts is not exported from index.ts (just types.ts, client.ts, clientStub.ts, and errors.ts). Was this intentional? The reason I ask is - I'm creating a typescript interface and want to reference the Txn type.

Fill in README

Follow the style of the dgraph4j README, and just replace Java code w/ Javascript code.

webpack-for-webDll ModuleNotFoundError: Module not found: Error: Can't resolve 'child_process'

This error has constantly appeared in my test and study application. I can use the application, but it generates errors of communication between services. Because the error causes the webpack to load in half. Here's some information.

Should open Port 3000, but the load is not complete opening only the 8080 via ngrok which is useless. Without the dgraph-js dependencies inside the application works fine. Can you give a light here please?

webpack-for-webDll info Generating vendor_web DLL bundle with modules:
["antd","apollo-cache-inmemory","apollo-client","apollo-fetch","apollo-fetch-upload","apollo-link","apollo-link-batch-http","apollo-link-ws","apollo-logger","bootstrap","dgraph-js","error-stack-parser","filesize","fs","graphql","graphql-auth","graphql-iso-date","graphql-tag","history","immutability-helper","jwt-decode","lodash","minilog","persistgraphql","prop-types","react","react-apollo","react-cookie","react-debounce-input","react-dom","react-dropzone","react-ga","react-helmet","react-hot-loader","react-native-web","react-redux","react-router","react-router-dom","react-router-redux","react-stripe-elements","react-transition-group","reactstrap","redux","redux-devtools-extension","redux-form","sourcemapped-stacktrace","styled-components","subscriptions-transport-ws"]

webpack-for-webDll ModuleNotFoundError: Module not found: Error: Can't resolve 'child_process' in '/Volumes/test/node_modules/detect-libc/lib'
    at factoryCallback (/Volumes/test/node_modules/webpack/lib/Compilation.js:276:40)
    at factory (/Volumes/test/node_modules/webpack/lib/NormalModuleFactory.js:235:20)
    at resolver (/Volumes/test/node_modules/webpack/lib/NormalModuleFactory.js:60:20)
    at asyncLib.parallel (/Volumes/test/node_modules/webpack/lib/NormalModuleFactory.js:127:20)
    at /Volumes/test/node_modules/async/dist/async.js:3874:9
    at /Volumes/test/node_modules/async/dist/async.js:473:16
    at iteratorCallback (/Volumes/HSierraDados/Dev-2018/GitLab/uapi/node_modules/async/dist/async.js:1048:13)
    at /Volumes/test/node_modules/async/dist/async.js:958:16
    at /Volumes/test/node_modules/async/dist/async.js:3871:13
    at resolvers.normal.resolve (/Volumes/test/node_modules/webpack/lib/NormalModuleFactory.js:119:22)spin error Error: Build error
    at webpackReporter (/Volumes/test/node_modules/spinjs/src/executor.ts:96:11)
    at reporter (/Volumes/test/node_modules/spinjs/src/executor.ts:655:50)
    at onCompiled (/Volumes/test/node_modules/webpack/lib/Compiler.js:230:19)
    at applyPluginsParallel.err (/Volumes/test/node_modules/webpack/lib/Compiler.js:500:20)
    at /Volumes/test/node_modules/tapable/lib/Tapable.js:285:11
    at _addModuleChain (/Volumes/test/node_modules/webpack/lib/Compilation.js:498:12)
    at processModuleDependencies.err (/Volumes/test/node_modules/webpack/lib/Compilation.js:474:15)
    at finalCallbackAddModuleDependencies (/Volumes/test/node_modules/webpack/lib/Compilation.js:375:12)
    at /Volumes/test/node_modules/async/dist/async.js:473:16
    at iteratorCallback (/Volumes/test/node_modules/async/dist/async.js:1048:13)
webpack-for-server Starting backend
webpack-for-server Time: 26610ms
webpack-for-server Spawning node --inspect=9229 /Volumes/test/build/server/index.js
Debugger listening on ws://127.0.0.1:9229/63cf2171-8277-44509-a88a-10bb3dd4f8ee41
For help see https://nodejs.org/en/docs/inspector
backend info API is now running on port 8080

dropAll working?

Hi! I'm new on board and trying DGraph for the first time. Really excited about it, must say! =]

I have the code below, but when I call resetDgraph, my data is still there. What I'm doing wrong here?

    __getDGraph(){
        const dgraph = require('dgraph-js')
            , grpc = require('grpc')
            , clientStub = new dgraph.DgraphClientStub()
            , client = new dgraph.DgraphClient(clientStub)
        ;

        return {
            client: client,
            dgraph: dgraph
        };
    }

    async resetDgraph(){
        try{
            let db = this.__getDGraph()
                , op = new db.dgraph.Operation()
            ;

            op.setDropAll(true);
            let r = await db.client.alter(op);

            // Retorna
            return {
                ok: r
            }

        } catch(e){
            log.erro(e, '');
        }
    }

Thanks, and kudos for the work.

Some trouble with the final query

Like below,I get a [] at last.
I tried run the query part separately, it will work and I can get the correct result, and the data was successfully insert into the database.I hope some one can help me to explain that. XD

`Created person named "Alice" with uid = 0x8e

All created nodes (map from blank node names to uids):
blank-0 => 0x8e
blank-1 => 0x8f
blank-2 => 0x90
blank-3 => 0x91

{ all: [] }
Number of people named "Alice": 0

DONE!
`

Do I need to close connections?

I have a number of scripts that all create there own connection, and I was trying to see if there was a cleanup function I need to run when I am finished with the connections and want to disconnect.

Is there a cleanup function?

Also is there a limit on connections?

I could not find answers to either of these questions, in the docs, or the code. It could be I am bad at looking.

I am planning to use DGraph via Lambda so every time a function is called it needs it's own connection, so it's important to understand any limits here.

It feel it would be worthwhile to have a cleanup/disconnect section after the "commit a transaction" section in these docs. I would consider adding this even if you don't have to cleanup/disconnect as its something I often look for an answer for when working with DB clients.

Retrieving schema?

Modifying the schema with op.setSchema ... client.alter(op) works great.

However, how can I retrieve the dgraph schema? I tried passing a query of the form:

schema {
...
}

But it doesn't return results, I assume because a schema query isn't supported by the Txn.query method?

Json parse error

Version: 1.0.2 (also applies to 1.0.3)
Dgraph version: 1.0.2

After running a query of the form via txn.query(...):

{
    classes(func: eq(<${sp.VertexType}>, "Class"), orderasc: ${sp.Name}) {
      uid: _uid_
      name: ${sp.Name}
      ...
}

Within your method Response.getJson(), the call to super.getJson() returns a string that is not valid Json:

"classes": [{"name":....

This results in a JSON parse error, "Unexpected token : in JSON at position 9"

Was there a recent change that would have changed the format of the string returned from super.getJson() so that it is missing an opening brace?

EDIT: the value returned from super.getJson() is determined to be Uint8 and gets put through the u8ToStr function.

EDIT 2: I have found that the last character returned from super.getJson() is ASCII character #26 ("SUBSTITUTE"). When I append a brace to the front of the result, and remove this "SUBSTITUTE" from the end, the string is valid JSON. So it looks like the query result may be incorrectly offset by 1 character.

existsSync in not a function

Hi there,

I created a react project app using the create-react-app CLI and installed dgraph and grpc via yarn add. And I'm currently facing an issue which it says existsSync in not a function. And when I clicked on the error, it brings me to the grpc_extension.js.

Here's the screenshot to the error: error_image. Hope to hear from you guys soon! Thank you!

Source of very high client latency?

---------------------------------------------------------
Versions:
Dgraph v1.02
dgraph-js v1.03
Windows 10 client
Ubuntu / Virtualbox Dgraph server / zero / ratel

Using this query as an example:

{ adminUsers(func: eq(VertexType, "User")) @filter(eq(IsAdministrator, "1")) { uid } }

Actual console .time() / timeEnd() in node shows 1186 ms. However, while running in debug mode, the latency reported by the server tells a different story:

"latency":{"parsingNs":11466,"processingNs":467761,"encodingNs":1090106}}

So the latency of the query on the dgraph server should be 0.011 ms + 0.467 ms + 10.9 ms = ~11ms, but latency in the code using the client is ~100x higher. When using Dgraph ratel, I see very low latency, so this problem seems to be within the JS client.

Any initial thoughts on what might be causing this? In the meantime, I'll put some more timers within the module to pinpoint where the high latency may be coming from and comment back here.

UPDATE:

I have some detailed times from the functions inside the library. I don't understand GRPC very well, but I put one time output in the request serialize function, and one time output in the response constructor function. Total query latency experienced by my app was 1032 ms, and 1009 ms of these were between the request serialize / response constructor calls. So can I conclude that this is a network latency problem for grpc on my machine?

Original query:
{
adminUsers(func: eq(VertexType, "User")) @filter(eq(IsAdministrator, "1")) {
uid
}
}

Debug messages (times added)
{"query":"{\n adminUsers(func: eq(VertexType, "User")) @filter(eq(IsAdministrator, "1")) {\n uid\n }\n }","varsMap":[],"startTs":0,"linRead":{"idsMap":[]}}
Returning from proto.api.Request.prototype.serializeBinary: 41085725 (time in ms)
in constructor proto.api.Response: 41086734 (time in ms)
(1009 MS between request serialize and response constructor)
proto.api.Response.toObject: 0.435ms

Query response:
{"json":"eyJhZG1pblVzZXJzIjpbeyJ1aWQiOiIweDNhYTE5In0seyJ1aWQiOiIweDk0Zjc4In1dfQ==","schemaList":[],"txn":{"startTs":11351,"commitTs":0,"aborted":false,"keysList":[],"linRead":{"idsMap":[[1,1013]]}},"latency":{"parsingNs":14972,"processingNs":334063,"encodingNs":1605714}}

Total query latency in my app code: 1032.438ms

UPDATE 2:

I have found that by running the application within the VirtualBox Ubuntu installation rather than accessing from Windows, the grpc latency problem goes away completely, so I'm going to consider this a grpc latency problem rather than a problem with the library. Closing the issue.

Schema query not working with .getJson()

I was just writing some tests, and I wanted to verify the schema state before running a function. So I constructed a schema query. I got the query to work, however res.getJson() does not extract the results from the response as I expected.

The results do seem to be present on the return object, and I worked out I could use res.toObject().schemaList to get them.

      const query = `
                schema {
                    type
                    index
                    reverse
                    tokenizer
                }
        ` ;
        const res = await dgraphClient.newTxn().query(query);
        const json = res.getJson() // returns and empty object
        const object = res.toObject().schemaList; // returns schema like ratel

I am not sure what is expected here. This functionality is not documented, so I just wanted to flag it with you. I feel it would be worthwhile to document it, or if it's a bug fix it so .getJson() works.

If it's just a super special query maybe you can create:

dgraphClient.newTxn().getSchema()

Unable to connect to server - 14 UNAVAILABLE: Trying to connect an http1.x server

Hi. Runing DGraph 1.0.5, dgraph-js 1.2.1 and grpc 1.12.3.

Working with everything installed until now at my own machine (Mac Air), all good, no problems. Installed a new server on a windows machine to centralize things and when I try to connect to it I got this error:

Error: 14 UNAVAILABLE: Trying to connect an http1.x server

My test function:

async test(){
        const dgraph = require("dgraph-js")
            , grpc = require("grpc")
            , clientStub = new dgraph.DgraphClientStub(
                "192.168.0.253:8080", grpc.credentials.createInsecure()
            )
            , dgraphClient = new dgraph.DgraphClient(clientStub)
        ;

        let res = await dgraphClient.newTxn().query(`
                {
                    query(func: has(__is_pessoas), first: 10){
                      uid
                      app
                      descricao
                    }
                }
            `)
            , ppl = res.getJson()
        ;
    }

If I start ratel locally on my mac and try to connect to that same address with it, it works with no problems.

To clarify: I have a dev node environment on my mac, and I'm trying to connect it to a DGraph server on a windows machine on my network, that should be like a central database for al devs, and the the error ocourrs.

Help, please?

Unable to connect to server

I am not able to connect to dgraph using dgraph-js

var clientStub = dgraph.DgraphClientStub(
   ‘127.0.0.1:9080’, // tried all other ports 5080 7080 8080
   grpc.credentials.createInsecure()
 );
var client = dgraph.DgraphClient(clientStub);

console.log(clientStub) // undefined
console.log(client) // undefined

Executed the below commands and dgraph-ratel is working fine

dgraph zero

dgraph alpha --lru_mb 2048 --zero localhost:5080

dgraph-ratel

My dgraph-ratel is connected on localhost:8080

Any idea what I have missed?

Compare Performace w/ Java client

Initial observations suggest that the Javascript client takes several times longer to run the integration tests, compared to the Java client.

We should start by doing some systematic testing, and investigate any bottlenecks that could be easily fixed

It's not possible to distinguish between errors

Since this library uses only native Error, it's hard to distinguish the reason why transaction failed. The only way at the moment is to compare error message, which is very cumbersome. I'd like to be able to do the following:

try {
    // some transaction code
} catch (e) {
    if (e instanceof errors.AbortedError) {
         // retry
    }
}

Does this make sense or is there any better way to achieve this?

Facets aren't working with setSetJson

Howdy! Unfortunately facet's are not quite working as documented.

When I try the following code:

const wellFormedFixtures = [ 
    { name: 'reprehenderit',
    description: 'Cum tempore excepturi qui numquam illo.',
    location: { name: 'libero', position: [Object] },
    entity: { name: 'maiores', contact: '813 Hayes Ports Bradleyberg' },
    source: { name: 'et', url: 'http://clay.name', aggregator: 0 },
    'location|date': new Date('2018-12-11T21:21:32.455Z'),
    url: 'http://jovanny.org',
    images: [ 'http://lorempixel.com/640/480' ] } 
]

const transaction = dgraphClient.newTxn()
let mutation = new dgraph.Mutation()
mutation.setSetJson(wellFormedFixtures)

The below query:

{
  some_events(func: allofterms(name@., "omnis")) {
    uid,
    name@.,
    location {
      uid,
     name@.,
     position {
     	expand(_all_) 
     }
    } @facets(date: date),
    entity {
     name@.
    },
    source {
    	name@.
    }
  }
}

will not include the date element. However if I manually mutate on ratel via

{
  set {
    <0x29a> <location> <0x29c> (date=2018-11-22T12:10:04.106Z) .
  }
}

it does work fine.
Can you please explain how this is intended to be used, and clarify whether this is a bug or just weirdly documented.

Cannot use same transaction for delete and set mutations

I am trying to write a transaction which deletes from a predicate of type [string], writes back to that same predicate, and then commits both at once.

I have found I'm not able to do that with the library currently. What happens is, the original edge is deleted, but the subsequent one is never written. As an example, I am trying to perform these mutations:

const txn = client.newTxn()

const mu1 = new dgraph.Mutation()
mu1.setDelNquads(`<0x11194> <property.code> * .`)
txn.mutate(mu1)

const mu2 = new dgraph.Mutation()
mu2.setSetNquads(`<0x11194> <property.code> "LDG" .`)
txn.mutate(mu2)

txn.commit()

If I create and commit two separate transactions rather than bundling, the written triple is visible. But if I keep it within one transaction, the result is no data left on the predicate.

Am I using the library correctly?

Setting deadlines/timeouts on individual calls

Would it be possible to add support for setting deadlines on individual calls with the dgraph-js client?

Perhaps the calls could take an optional options parameter? e.g.

await txn.mutate(mu, {deadline: 1516844615385})

As far as I can tell, the Dgraph Go client supports enforcing deadlines on individual calls, and from briefly looking at the Node.js gRPC implementation, it seems to support CallOptions with a deadline property too. So it should hopefully be just a matter of threading it through via the wrapper functions?

TLS connection - Error: 14 UNAVAILABLE: Connect Failed

I'm trying to set up secure GRPC connection. What have I done so far:

  • generate certs using dgraph cert
  • verify fingerprints and certs using open ssl (openssl verify -verbose -CAfile ca.crt node.crt)
  • check the connection and certs crescents with openssl s_client -connect 176.9.122.98:9080 -CAfile ca.crt
  • set up connection:
const rootCert = fs.readFileSync(path.join(__dirname, 'certs', 'ca.crt'))
const clientData = new dgraph.DgraphClientStub(
  '<my_external_machine_IP_address>:9080',
   grpc.credentials.createSsl(rootCert)
)
  • try to connect: Error: 14 UNAVAILABLE: Connect Failed

In addition i configured NGINX grpc proxy, first without SSL (works fine), then with SSL (same error as
above).

Any ideas what else to check and what can be wrong? Did anyone successfully configured dgraph-js to work with TLS?

Unable to create an edge between two existing nodes

I've just started to play around with the JS client for dgraph. Now I'd like link two nodes by a managed edge like so:

{
  set {
    <0x109> <managed> <0x108> .
  }
}

That works fine in Ratle, but fails with JS:

    const txn = dgraphClient.newTxn();

    try {
        // Add test managed reference
        let p = {
          "uid": "0x109",
          "managed": {
            "uid": "0x108"
          }
        };

        // Run mutation.
        const mu = new dgraph.Mutation();
        mu.setSetJson(p);
        txn.mutate(mu);

        // Commit transaction.
        await txn.commit();
    } finally {
        // Clean up. Calling this after txn.commit() is a no-op
        // and hence safe.
        await txn.discard();
    }

which results in:

{"setJson":"eyJ1aWQiOiIweDEwOSIsIm1hbmFnZWQiOnsidWlkIjoiMHgxMDgifX0=","deleteJson":"","setNquads":"","delNquads":"","setList":[],"delList":[],"startTs":0,"commitNow":false,"ignoreIndexConflict":false}
ERROR:  Error: Transaction has been aborted. Please retry
    at Object.<anonymous> (/home/cajus/tmp/dgraph/node_modules/dgraph-js/lib/errors.js:5:23)
    at Module._compile (module.js:660:30)
    at Object.Module._extensions..js (module.js:671:10)
    at Module.load (module.js:573:32)
    at tryModuleLoad (module.js:513:12)
    at Function.Module._load (module.js:505:3)
    at Module.require (module.js:604:17)
    at require (internal/module.js:11:18)
    at Object.<anonymous> (/home/cajus/tmp/dgraph/node_modules/dgraph-js/lib/client.js:39:16)
    at Module._compile (module.js:660:30)
Mutate response:
{"uidsMap":[],"context":{"startTs":211,"commitTs":0,"aborted":false,"keysList":["32fytna3wc2o4"],"linRead":{"idsMap":[[1,164]]}},"latency":{"parsingNs":26030,"processingNs":8052878,"encodingNs":0}}

As I'm not yet completely familiar with the client, I'm wondering what the error means - and how I can get some more information out of it than the setDebugMode(true) offers.

Calling discard() after mutations throws the error: "Transaction has been aborted, please retry." (Code 10)

Hello!

I think the client has a strange behavior when we call discard() after some mutations: it throws the following error : Transaction has been aborted. Please retry. I don't think it is useful, because if I call this method, it's precisely because I want to abort the transaction (and didn't call commit())...

In this case, I noticed that the error object has an additionnal property code with the value 10, and the following is false: e == dgraph.ERR_ABORTED.

Although the error message is the same, the error thrown when a conflict occurs during a transaction doesn't have this property code, and we can assert that: e == dgraph.ERR_ABORTED.

In my project, I currently monkey-patch the library the following way...

// Change behavior of discard.
// When calling discard() after mutations, it throws the error "10 ABORTED: Transaction has been aborted. Please retry.";
const _discard = Txn.prototype.discard;
Txn.prototype.discard = async function() {
    try {
        await _discard.apply(this, arguments);
    } catch (e) {
        if (e.code != 10) throw e;
    }
};

It is annoying because, usually, the call to discard() occurs in a finally block, so the error is not handled properly.

What do you think about this issue? Is this a desired behavior?
Thanks in advance for your answers. :)

How to specify @lang in setSetJson() object?

Hello! I cannot find this in the README.md but how do we go about passing the language for a predicate in the json object we want to mutate?

{
<0f27fd12> <label@en> "Dog" .
<0f27fd12> <label@fr> "Chien" .
}

How do basically do this with the Mutation.setSetJson(obj)'s object?

p.s. and also how to delete label@en using the setDeleteJson()?

Are there any debug options?

The Dgraph-Node version had a very useful debugging option. It returned both the query and the result with further informations.

Cheers

TLS client Authentication?

Hi,

I would like to secure my connection with TLS.
How I can setup client authentication?

Thank you.
Best regards,
Roman

Debug mode produces `\n` instead of actual newline in console

When debug mod is turned on, the console output is not properly formatted. The newlines appear as the sequence \n instead of actual newlines as shown in the following example output:

{"query":"\n      query getByName($name: string) {\n        getByName(func: anyofterms(name@., $name)) {\n          expand(_all_)\n        }\n      }\n    ","varsMap":[["name","Julia"]],"startTs":0,"linRead":{"idsMap":[]}}

Can getLatency() be made available on mutation response "Assigned" class?

getLatency() is very helpful for query operations. However, to measure performance, and separate network latency from database latency, we need to have the getLatency() function on mutation responses as well as query responses.

Can getLatency() be made available on the Assigned class as well?

How to avoid errors on rapid queries?

I'm setting up some integration tests, and coming across the "Error: Transaction has been aborted. Please retry" error. There's a function that resets the data I am mutating before and after each test. It works about 80% of the time, but otherwise is throwing the error.

If I put a short async 'sleep' delay in the beforeEach/afterEach functions, it works as expected. But, this doesn't leave me confident that my code can handle requests which might fail because they are submitted in rapid succession. Simply retrying the query once more doesn't feel good either.

Am I missing something?

Here's a simplified version of the test.

// @flow
/* eslint-disable no-undef */
import { request } from '../../../__tests__/utils'
import { sampleUser } from '../../../database/stubs/users'
import { updateUser, getUser } from '../UserModel'

const sleep = (ms) => new Promise((r) => setTimeout(r, ms))
const resetUserData = async () => {
	await updateUser(sampleUser.uid, { input: sampleUser })
}

describe('[updateViewerProfile]', () => {
	beforeAll(async () => {
		await resetUserData()
		// await sleep(100) // <-- uncommenting these two gets it working
	})
	afterAll(async () => {
		// await sleep(100) // <--
		await resetUserData()
	})

	it('should update existing data', async () => {
		const newBioLine = 'Test bio line'

		// Note: this is an actual GraphQL mutation that goes through my resolvers.
		// This is not querying dgraph directly.
		const mutation = /* GraphQL */ `
		mutation updateProfile($bioLine: String) {
			updateViewerProfile(input: {bioLine: $bioLine }) {
				username
				bioLine
			}
		}
		`
		const variables = {
			bioLine: newBioLine,
		}
		const context = { viewer: joseph }
		const result = await request(mutation, { variables, context })
		expect(result.data.updateViewerProfile.bioLine).toBe(newBioLine)
	})
})

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.