Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

New query language #60

Open
brillout opened this issue Oct 14, 2020 · 0 comments
Open

New query language #60

brillout opened this issue Oct 14, 2020 · 0 comments
Labels
enhancement New feature or request experimental May never see the light vision The future

Comments

@brillout
Copy link
Owner

This would be a new project entirely independent but compatible with Wildcard.

This is ambitious and I'm not sure if/when I'll finish this.

In case you ask yourself why this is necessary in the context of Wildcard: it's basically for large scale applications that need to decouple the development of several frontends from the backend development. For most users, Wildcard alone is enough.

A preview:

// Browser-side

// Note how we only depend on Wildcard here.
import { server } from '@wildcard-api/client';

// The query syntax is JSON-like.
const posts = await server.query({
  _table: 'posts',
  authorId: {
    _table: 'users',
    id: '*',
    username: 'brillout',
  },
  title: '*',
  content: '*',
});
assert(posts[0].title==='Introducing a new query language');
assert(posts[0].content.startsWith(
  'When GraphQL was announced I was super excited but after the honeymoon'
));

// Similarly for upserting data
await server.query({
  _table: 'posts',
  authorId: 'brillout',
  title: 'NQL + Wildcard = <3',
  content: 'WIP',
});

// There is a field with '*' => data retrieval
// No field with '*' => data mutation

Resolvers + Wildcard integration

const { server } = require('@wildcard-api/server');
const { resolveQuery, addResolver } = require('nql');

server.query = async function(query) {
  const { data } = await resolveQuery(query);
  return data;
};

// One resolver per table for data retrieval
addResolver('posts', async (selectFields, filterFields) => {
  // A trick is that `filterFields[fieldName]` is always an array.
  // This solves the N+1 problem!
  assert(!filterFields.id || filterFields.id.constructor === Array);

  // (No SQL injection, everything is sanitized.)
  const res = await db.sql([
    `SELECT ${selectFields.join(', ')} FROM posts`,
    // Do this for every `key in filterFields`.
    `WHERE id IN (`${filterFields.id.map(id => `'${id}'`).join(', ')})`,
  ].join(' '));

  return res;
});

// One resolver per table is enough for any graph-like query.
// With no N+1 problem.

With "object-level permissions":

const { server } = require('@wildcard-api/server');
const { resolveQuery, addPermissions } = require('nql');

server.query = async function(query) {
  // We need the context for permissions
  const context = this;
  const { data, permissionDenied } = await resolveQuery(query, context);
  if (permissionDenied) {
    return { permissionDenied };
  } else {
    return { data };
  }
};

// We define permissions programmatically.
// This is simple and powerful.
addPermissions('read', ({object, context}) => {
  const { isAdmin } = context.user;
  // Admins can read everything
  if (isAdmin) {
    return true;
  }

  // Anyone can read everything from the `posts` table
  if (object._table==='posts') {
    return true;
  }

  // Fine grained permission: anyone can read everything from
  // the `users` table except for the `password` field.
  if (object._table === 'users') {
    if (object.password) {
      return false;
    } else {
      return true;
    }
  }

  // Anything else is forbidden
  return false;
});

addPermissions('write', ({object, context}) => {
  // Same than above but for mutation
});
@brillout brillout added enhancement New feature or request vision The future labels Oct 14, 2020
@brillout brillout added the experimental May never see the light label Oct 15, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request experimental May never see the light vision The future
Projects
None yet
Development

No branches or pull requests

1 participant