@plurid/elementql-client-react
TypeScript icon, indicating that this package has built-in type declarations

0.0.0-1 • Public • Published



License: DEL

ElementQL

Query Web Elements


ElementQL is a query language specification and implementation to query a server for Web Elements source code in order to render them on the client.

Contents

Description

Current State

Consider the following Web Element which uses React

const HelloElementQL = () => {
    return React.createElement('div', null, 'Hello from ElementQL');
}

When embedded into a standard React rendering process, the HelloElementQL functional element will generate a div containing the text Hello from ElementQL.

The normal manner of sending the element to the browser is by packing it up into an Application, in a large JavaScript index.js file, which gets attached to a index.html with a script tag and then gets sent by the server to the client.

ElementQL Proposal

The manner proposed by ElementQL is to let the client request only the required elements at runtime from a server and receive only the particular element-specific module.

Usage

Server

NodeJS

Install

The NodeJS server can be installed running the command

npm install @plurid/elementql-server

or

yarn add @plurid/elementql-server
Start

The simplest ElementQL server requires only to be started, the elements will be served from the default ./elements path

// server.js
import ElementQLServer from '@plurid/elementql-server';


const server = new ElementQLServer();

server.start();

The server will then accept requests on the http://localhost:21100/elementql URL for the elements in the ./elements directory.

Elements

The ./elements directory has a structure of folders with element-specific files: .js, .jsx, .ts, .tsx, or .css. For example

.
|- server.js
|- elements
|   |- HelloElementQL
|   |   |- index.js
|   |-
|-
Options

The ElementQLServer Object can receive an options object

import {
    ElementQLServerOptions,
} from '@plurid/elementql-server';


/** defaults */
const options: ElementQLServerOptions = {
    protocol: 'https',                          /** default for production; for development: `'http'` */
    domain: '',                                 /** the domain for the server, e.g. example.com */
                                                /** will be used to resolve elements relative and library imports */
    port: 21100,

    rootDirectory: process.cwd(),
    buildDirectory: 'build',                    /** relative to the root directory */
    nodeModulesDirectory: 'node_modules',       /** relative to the root directory */
    elementqlDirectory: '.elementql',           /** relative to the build directory */
    transpilesDirectory: 'transpiles',          /** relative to the elementql directory */

    elementsDirectories: [                      /**/
        'elements',                             /** relative to the build directory */
    ],                                          /**/
    libraries: {},
    endpoint: '/elementql',
    allowOrigin: ['*'],
    allowHeaders: ['*'],
    plugins: [                                  /**/
        'minify',                               /** default for production; for development: `[]` */
    ],                                          /**/

    verbose: true,
    open: true,
    playground: false,
    playgroundEndpoint: '/playground',

    store: null,
    metadataFilename: 'metadata.json',
};
Requests

In production, an ElementQL Client is recommended. In development/testing, the requests for elements can be made using the POST method with a Content-Type header of application/json or application/elementql. For example

JSON

curl http://localhost:21100/elementql \
    -H "Content-Type: application/json" \
    -v --data '{"elements":[{"name":"HelloElementQL"}]}'

ElementQL

curl http://localhost:21100/elementql \
    -H "Content-Type: application/elementql" \
    -v --data 'elements{HelloElementQL}'
Metadata

In each element directory there can be an elementql.yaml file with metadata specific to the element

# the element name derived from the directory name will be overwrriten with `OverwriteName`
name: OverwriteName

Go

The elementql-server for Go is a go 1.14 module.

Python

Client

React

Considering the standard React application, using ElementQL involves

  • creating an elementql.yaml configuration file,
---
globals:
  react: React
  react-dom: ReactDOM
origins:
  elementql: http://localhost:21100/elementql
  application: http://localhost:8005
bootloader: './source/index.js'
entry: './app/index.js'
  • creating the service-worker,
const elementQLServiceWorker = './node_modules/@plurid/elementql/distribution/service-worker.js';


importScripts(elementQLServiceWorker);
  • creating and running the metabootloader,
const metabootloader = require('@plurid/elementql/distribution/metabootloader').default;


metabootloader();
  • creating and running useLibraries
const {
    libraries,
    useLibraries,
} = require('@plurid/elementql');



const usedLibraries = {
    react: libraries.react,
    reactDom: libraries.reactDom,
};

const buildDirectory = 'build';


useLibraries({
    libraries: usedLibraries,
    buildDirectory,
});
  • defining an ElementQL/JSON request,
  • instantiating an ElementQLClient with the URL for the ElementQL server endpoint,
  • and making the request with the useEffect, useState standard React hooks,
  • or with the useElementQL custom hook.
import React, {
    useEffect,
    useState,
} from 'react';

import ElementQLClientReact, {
    useElementQL,
} from '@plurid/elementql-client-react';



const elementQLClient = new ElementQLClientReact({
    url: 'http://localhost:21100/elementql',
});

const ElementQLJSONRequest = {
    elements: [
        {
            name: 'HelloElementQL',
        },
    ],
};


const AppWithHook: React.FC<any> = () => {
     const Elements = useElementQL(
        elementQLClient,
        ElementQLJSONRequest,
        'json',
    );

    return (
        <>
            {Elements && (
                <Elements.HelloElementQL />
            )}
        </>
    );
}


const App: React.FC<any> = () => {
    const [Elements, setElements] = useState<any>();

    useEffect(() => {
        let mounted = true;

        const fetchElements = async () => {
            const {
                status,
                Elements,
            }: any = await elementQLClient.get(
                ElementQLJSONRequest,
                'json',
            );

            if (!status || !mounted) {
                return;
            }

            setElements(Elements);
        }

        fetchElements();

        return () => {
            mounted = false;
        }
    }, []);

    return (
        <>
            {Elements && (
                <Elements.HelloElementQL />
            )}
        </>
    );
}


export default App;

Plugins

Babel

Uses Babel to transpile .js and .jsx element files.

TypeScript

Uses TypeScript to transpile .ts and .tsx element files.

Minify

Uses Terser to minify the element files.

Packages

Version

@plurid/elementql • base

Version

@plurid/elementql-client

Version

@plurid/elementql-client-reactreact client

Version

@plurid/elementql-expressexpress middleware

Version

@plurid/elementql-parser

Version

@plurid/elementql-server • NodeJS server

Version

@plurid/elementql-server • Go server

@plurid/elementql-specification • specification

@plurid/elementql-org • documentation

ElementQL Client React

Usage

import elementQLClientReact, {
    elementQL
} from '@plurid/elementql-client-react';

const elementQLClient = elementQLClientReact({
    url: 'https://api.example.com/elementql',
});

const DIV = elementQL`
    import {
        <Div>
    }
`;

// gets a React Function Component
const Div = await elementQL.get(DIV);

@plurid/elementql-client-react uses @plurid/elementql-client under the hood to inject the script/style

and returns window.elementQL.Div which is a React function component

the React component should be exported wrapped around a HoC withElementQL which will make the component available on window

ElementQL Context

import {
    ElementQL,
} from '@plurid/elementql-client-react';


const SomeProvidedElement = () => (
    <ElementQL.Provider
        elements={{
            SomeElement: () => (<div>some element</div>),
        }}
    >
        <ElementQL.Consumer>
            {(context) => {
                const SomeElement = context?.getElement('SomeElement');

                if (!SomeElement) {
                    return (<></>);
                }

                return (<SomeElement />);
            }}
        </ElementQL.Consumer>
    </ElementQL.Provider>
);

Readme

Keywords

Package Sidebar

Install

npm i @plurid/elementql-client-react

Weekly Downloads

0

Version

0.0.0-1

License

SEE LICENSE IN LICENSE

Unpacked Size

100 kB

Total Files

16

Last publish

Collaborators

  • ly3xqhl8g9