Sign Up for Free

RunKit +

Try any Node.js package right in your browser

This is a playground to test code. It runs a full Node.js environment and already has all of npm’s 400,000 packages pre-installed, including @thinkmill/keystone-mosql-yaml-gen with all npm packages installed. Try it out:

var keystoneMosqlYamlGen = require("@thinkmill/keystone-mosql-yaml-gen")

This service is provided by RunKit and is not affiliated with npm, Inc or the package authors.

@thinkmill/keystone-mosql-yaml-gen v2.2.4

A basic generator of MoSQL YAML config files for KeystoneJS models

MoSQL Yaml Generator for Keystone

Tools for generating a MoSQL-compatible YAML document describing the lists configured for your Keystone 4 instance. This can be useful for exporting data from a Keystone instance or streaming updates to a reporting database in near real-time.

You'll need to install MoSQL and PostgreSQL separately.

Usage

Generating the Config

const keystone = require('keystone');
const mosqlYaml = require('@thinkmill/keystone-mosql-yaml-gen');

// Create a generator instance
const yamlGenerator = new mosqlYaml.YamlGenerator(keystone);

// Extract the MoSQL YAML for your lists
const collectionsYaml = yamlGenerator.generateYaml();
console.log(collectionsYaml);

Express Endpoint

A drop-in ExpressJS endpoint is included. This can be useful if your schema is often changing; a process could be configured to periodically download an up-to-date config.

Add the endpoint to your Express app like this:

const keystone = require('keystone');
const mosqlYaml = require('@thinkmill/keystone-mosql-yaml-gen');

app.get('/api/keystoneListsYaml', mosqlYaml.createMosqlYamlEndpoint(keystone));

Alternatively, create your own endpoint:

const keystone = require('keystone');
const mosqlYaml = require('@thinkmill/keystone-mosql-yaml-gen');

const endpoint = function (req, res, next) {
    const yamlGenerator = new mosqlYaml.YamlGenerator(keystone);
    const collectionsYaml = yamlGenerator.generateYaml();

    res.set('content-disposition', `attachment; filename="${yamlGenerator.getFilename()}"`);
    res.set('content-Type', 'application/x-yaml');
    res.send(collectionsYaml);
};

Consuming the Config

The config generated describes the collections and fields to copy. It's supplied to mosql like this:

mosql -c 180502-keystone-MoSQL.yaml [--sql postgres://sql-server/sql-db] [--mongo mongodb://mongo-uri]

See the MoSQL docs for more options.

Types

Strings

Unlike other database systems, in PostgreSQL, there is no performance difference between varchar, varchar(n) and text types. We preference text.

Numbers

Numbers in JavaScript are 64-bit floating points; equivalent to PGs double precision type.

Note that for Money fields are also imported as double precision. These values should be converted to a lossless type before being manipulated (eg. numeric(20, 4) or similar).

Dates

JavaScript Date objects have no timezone information -- they're epoch-base and effectively in UTC. Importing as timestamp with time zone will maintaining the correct value while defaulting the time zone stored to UTC.

Date objects also maintain only millisecond precision (ie. 1/1,000 of a second). PostgreSQL on the other hand, defaults to microsecond precision for it's timestamp types (ie. 1/1,000,000 of a second). This tool sticks with the Postgres default but column types could later be altered to timestamp (3) with time zone without any data loss.

Passwords

Currently passwords are intentionally excluded from the dumped fields.

(TODO: Add configuration options for this)

Simple Type Mappings

Values are mapped to individual columns where possible:

Keystone TypePostgreSQL TypeNotes
datetimetimestamp with time zoneSee Dates above
datetimestamp with time zone
numberdouble precision
relationshiptextWhen many !== true
relationshiptext arrayWhen many === true
selecttext
texttext
booleanboolean
codetext
emailtext
htmltext
markdowntext
textareatext
moneydouble precisionSee Numbers above
geopointdouble precision array
textarraytext array

Complex Type Mappings

Some of the more complex, multi-value types are mapped to multiple columns:

name Type

Keystone FieldColumn NamePostgreSQL Type
(key).first(key)_firsttext
(key).last(key)_lasttext

location Type

Keystone FieldColumn NamePostgreSQL Type
(key).street1(key)_street1text
(key).street2(key)_street2text
(key).name(key)_building_nametext
(key).shop(key)_shoptext
(key).number(key)_numbertext
(key).state(key)_statetext
(key).postcode(key)_postcodetext
(key).suburb(key)_suburbtext
(key).geo(key)_geodouble precision array

s3file Type

Keystone FieldColumn NamePostgreSQL Type
(key).filename(key)_filenametext
(key).originalname(key)_originalnametext
(key).path(key)_pathtext
(key).size(key)_sizeint
(key).filetype(key)_filetypetext
(key).url(key)_urltext

cloudinaryimage Type

Keystone FieldColumn NamePostgreSQL Type
(key).public_id(key)_public_idtext
(key).version(key)_versionint
(key).signature(key)_signaturetext
(key).width(key)_widthint
(key).height(key)_heightint
(key).format(key)_formattext
(key).resource_type(key)_resource_typetext
(key).url(key)_urltext
(key).secure_url(key)_secure_urltext

Naming

Column names are forced to lowercase and restricted to the character set [a-zA-Z0-9_]. Any whitespace, hyphens or stops are replaced with underscores.

(TODO: Add configuration options for this)


Developed by John Molomby at Thinkmill for Keystone.js.

RunKit is a free, in-browser JavaScript dev environment for prototyping Node.js code, with every npm package installed. Sign up to share your code.
Sign Up for Free