1.1.0 • Published 6 months ago

remaq v1.1.0

Weekly downloads
-
License
MIT
Repository
github
Last release
6 months ago

remaq

npm Node.js CI

Remap data and convert to PostgreSQL select query using json/b_to_recordset.

Motivation

This package is meant for personal use to write small scripts for remapping data, and then converting the remapped data into a PostgreSQL select query.

Check out these other projects that convert to JSON:

From there, you can use this package to remap and fix issues with the data.

Installation

Install via npm:

npm install remaq
// ES6
import remaq from 'remaq';

// CommonJS
const { remaq } = require('remaq');

Install using the UMD build:

<script src="https://unpkg.com/remaq/lib/index.umd.js"></script>

UMD Minified:

<script src="https://unpkg.com/remaq/lib/index.umd.min.js"></script>
const remap = window.remaq(data);

Usage

Pass an object or an array of objects to the remaq function. This will return a Remaq object.

const remap = remaq({ name: 'John Doe' });
const remap = remaq([{ name: 'John Doe' }, { name: 'Jane Doe' }]);

Tip: For detailed typings, please see types.ts.

records()

You can access the mapped records via the records() method.

const remap = remaq({ name: 'John Doe' });
const records = remap.records();
console.log(records);
[ { name: 'John Doe' } ]

each(callback)

Set a callback function that is used when creating a record. You can return false to exclude the record from the results.

const items = [
  { name: 'John Doe' },
  { name: 'Lorem Ipsum' },
  { name: 'Jane Doe' }
];

const remap = remaq(items).each((record, value, index, data) => {
  console.log(
    '[%s] %s, %s, %s',
    index,
    record.name,
    value.name,
    items === data
  );
  return record.name !== 'Lorem Ipsum';
});

// note that the callback only triggers when getting records after it was set
const records = remap.records();
console.log('Total records:', records.length);
[0] John Doe, John Doe, true
[1] Lorem Ipsum, Lorem Ipsum, true
[2] Jane Doe, Jane Doe, true
Total records: 2

If the data passed to remaq is an object instead of an array, it will treat the object as index 0 of the iteration.

using(schema)

Set the schema to use when formatting data. This will return a new Remaq object that follows the provided schema.

const items = [
  { 'First Name': 'John', 'Last Name': 'Doe' },
  { 'First Name': 'Jane', 'Last Name': 'Doe' }
];

const remap = remaq(items).using({
  firstName: 'First Name',
  lastName: { from: 'Last Name' },
  someProperty: true
});

const records = remap.records();
console.log(records);
[
  { firstName: 'John', lastName: 'Doe', someProperty: null },
  { firstName: 'Jane', lastName: 'Doe', someProperty: null }
]

Tip: The record in the each(callback) call will use the same schema.

The schema is an object (of any property) that maps to a property from the data.

You can assign:

  • The property directly
  • A boolean value (value defaults to null)
  • A SchemaOptions object

SchemaOptions.from

Type: Any property of data (optional)

The property of data to map from.

Value in the record defaults to null if not provided.

remaq({ 'First Name': 'John Doe' }).using({
  firstName: {
    from: 'First Name'
  }
});

SchemaOptions.type

Type: string Default: 'TEXT'

The data type of the property. This value is used in getQuery(options).

remaq({ 'Total Items': 10 }).using({
  total: {
    from: 'Total Items',
    type: 'INT'
  }
});

SchemaOptions.remap

Type: { [K: keyof any]: any } (optional)

Transforms data using the object.

  • If the data is an array, each item is remapped using this object.
  • If the remapping required is complex, prefer to remap the data manually using each(callback).
const data = [{ List: ['YEs ', 'no'] }, { List: ['Yes', 'NO', 'N/A'] }];

const remap = remaq(data).using({
  options: {
    from: 'List',
    remap: {
      'YEs ': 'Yes',
      no: 'No',
      NO: 'No'
    }
  }
});

console.log(remap.records());
[ { options: [ 'Yes', 'No' ] }, { options: [ 'Yes', 'No', 'N/A' ] } ]

SchemaOptions.validate(value)

Type: (value: any) => boolean (optional)

Validate the value and throw an error if it is invalid.

Validation only occurs after the value has been remapped.

remaq({ Total: 10 }).using({
  total: {
    from: 'Total',
    validate: value => value >= 0
  }
});

schema

The schema when provided from using(schema) or the default schema.

Default schema is taken from the data:

const items = [{ 'First Name': 'John' }, { 'Last Name': 'Doe' }];

const remap = remaq(items);
console.log(remap.schema);
{ 'First Name': 'First Name', 'Last Name': 'Last Name' }

When schema is provided:

const items = [{ 'First Name': 'John' }, { 'Last Name': 'Doe' }];

const schema = {
  firstName: 'First Name',
  lastName: { from: 'Last Name' }
};

const remap = remaq(items).using(schema);

console.log('Is the same reference:', schema === remap.schema);
console.log(remap.schema);
Is the same reference: true
{ firstName: 'First Name', lastName: { from: 'Last Name' } }

getQuery(options?)

Uses the records to create a PostgreSQL select query using json/b_to_recordset. Returns an object (GetQueryResults type).

const remap = remaq(data);
const query = remap.getQuery(/* options */);

GetQueryOptions.data

Type: string (optional)

The JSON string to use.

Defaults to an escaped JSON.stringify(records}).

GetQueryOptions.alias

Type: string Default: 'tbl'

The table alias to use.

GetQueryOptions.selects

Type: string[] Default: ['*']

The selects to use.

GetQueryOptions.jsonb

Type: boolean Default: false

Set to true to use jsonb_to_recordset instead of json_to_recordset.


The GetQueryResults object contains the following properties:

GetQueryResults.raw

Type: string

The raw PostgreSQL select query.

GetQueryResults.json

Type: string

The JSON string of records (or data if provided).

GetQueryResults.columns

Type: string[]

The columns including their data type.

e.g. "name" TEXT, "value" INT

Example

Here is a full example:

import remaq from 'remaq';

const data = [
  {
    'Item ID': 'ITEM-100',
    'Total Items': 2,
    'Name of Item': "John Doe's Lorem Ipsum",
    Description: "'Lorem ipsum' dolor sit amet",
    Tags: ['Wow!', 'YEs ', 'fluffy']
  }
];

// `using()` returns a new Remaq object
const remap = remaq(data).using({
  id: 'Item ID',
  name: 'Name of Item',
  total: {
    from: 'Total Items',
    type: 'INT',
    validate: value => value >= 0
  },
  description: { from: 'Description' },
  item_tags: {
    from: 'Tags',
    type: 'tbl__tags__enum[]',
    remap: {
      'Wow!': 'good',
      'YEs ': 'yes'
    }
  },
  placeholder: true,
  empty: {
    type: 'tbl__empty__enum'
  }
});

// for each record, do something
remap.each((record, data, index, dataArray) => {
  // modify record here
  record.placeholder = `PLACEHOLDER-${index + 1}`;
  // return `false` to exclude this record from results later
});

// the same schema object passed to `using()`
const schema = remap.schema;

// get records (objects with the schema)
const records = remap.records();

// get query
const query = remap.getQuery({
  alias: 'my_table',
  selects: ['*', 'ROW_NUMBER() OVER() AS "nth"']
});

// the escaped json string
const json = query.json;

// the escaped column names with their data types
const columns = query.columns;

// the raw select query
console.log(query.raw);

Output:

SELECT *, ROW_NUMBER() OVER() AS "nth"
FROM json_to_recordset('[{"id":"ITEM-100","name":"John Doe''s Lorem Ipsum","total":2,"description":"''Lorem ipsum'' dolor sit amet","item_tags":["good","yes","fluffy"],"placeholder":"PLACEHOLDER-1","empty":null}]')
AS "my_table"("id" TEXT, "name" TEXT, "total" INT, "description" TEXT, "item_tags" tbl__tags__enum[], "placeholder" TEXT, "empty" tbl__empty__enum)

License

Licensed under the MIT License.

1.1.0

6 months ago

1.0.1

9 months ago

1.0.0

9 months ago

0.0.1

9 months ago