Namespace

flat

flat

The AdminBro Data model

Before you dive into the details of the flat helpers, let me briefly introduce the way how the database data is stored in AdminBro.

The Simple Case

On the backend all the information from DataBase tables/collections goes to {@BaseRecord#params} object. Usually, it is a {key: value} store where key is a table name, and value could be either a string, a number, or an instance of Date() etc.

On the Frontend - these values go to the corresponding RecordJSON.params property.

This is an example params property in the "simple case":

params: {
  name: 'John',
  surname: 'Doe',
  age: 28,
}

The Real World Case

In the real world:

  • databases have nested JSONB properties or Mixed Schemas
  • developers would like to send more complicated data from the Fronted to the backend as arrays.

To achieve that we "flatten" all the data before saving them to params property.

So in the real world params could look like:

params: {
  name: 'John',
  surname: 'Doe',
  age: 28,
  // nested objects
  'auth.facebook': 'some login token',
  'auth.twitter': 'twitter login token',
  // arrays
  'interests.0': 'running',
  'interests.1': 'jogging',
}

and all the data can be even nested on the deeper levels.

Why we did that?

An alternative solution would be to store an entire raw object and don't care. But there are 2 reasons why we picked this one.

1. storing selected data in the database

If you send to the ORM unflatten save request like this:

Model.save({{ auth: { facebook: 'newFacebookToken' } }})

it will override an entire auth property, so from the example above, we will lose auth.twitter.

In the second (flatten) case:

Model.save({ `auth.facebook`: 'newFacebookToken' }})

ORM should keep the value of the auth.twitter

The above is true for Mongoose adapter which is the most advanced regarding handing mixed values

2. Sending data between the Frontend and the Backend in FormData format

AdminBro allows you to upload Files from the Frontend to the Backend. The most optimal way of doing that is by using FormData. But, this requires that values for all the fields are send in [key: string]: string form. And this, as you might guess, fits perfectly to our flatten params logic.

Consequences

Flattening in AdminBro has its consequences everywhere where you use

because instead of raw object you have it's flatten version.

Also, (as mentioned) the payload send to the backed is also flattened.

There you should use helpers gathered in flat

New:
  • in version 3.3

View Source admin-bro/src/utils/flat/flat-module.ts, line 11

Members

# static constant exports.removePath

This method removes the given path from the flatten object.

Most of the time removing one path is a trivial thing but when it comes to arrays it is more complicated than just simply removing its key.

Usage


import { flat } from 'admin-bro'

// do something with flat.removePath
const paramsWithoutName = flat.removePath(otherParams, 'name.0')

Why it exists?

Take a look at this example:

having the flatten object

{
  'property.0': 'val1',
  'property.1': 'val2',
  'property.2': 'val3',
}

you want to remove property.1 path. In order to do this you will need to remove key property.1 and rename property.2 to property.1

and take a look at this example:

{
  name: 'value',
  'notPopulated.0': 'val1',
  'notPopulated.1': 'val2',
  'property.0': 'val1',
  'property.1': 'val2',
  'property.2': 'val3',
  'property.3.nested.0': 'val1',
  'property.3.nested.1': 'val2',
  'property.3.nested.2': 'val3',
  'property.3.nested.3.some': 'val3',
  'property.3.nested.4.some-other': 'val41',
  'property.4': 'val4',
  'property.5.nested.0': 'val5',
}

what should happen when you want to remove property.3.nested.3.some ?

This function solves these problems for you.

View Source admin-bro/src/utils/flat/remove-path.ts, line 14

# static flatten

Raw flatten function exported from original flat package.

View Source admin-bro/src/utils/flat/flat-module.ts, line 22

# static unflatten

Raw unflatten function exported from original flat package.

View Source admin-bro/src/utils/flat/flat-module.ts, line 27

Methods

# static filterOutParams(params, properties) → {FlattenParams}

From all keys in params it removes this passed in an argument.

Example


import flat from '@admin-bro'

const params = {
  name: 'John',
  'education.school.name': 'Harvard',
  'education.school.id': 123,
}

flat.filterOutParams(params, 'education.school')
// results to {
//   name: 'John',
// }

flat.filterOurParams(params, 'name')
// results to {
//   'education.school.name': 'Harvard',
//   'education.school.id': 123,
// }
Parameters:
Name Type Description
params FlattenParams
properties string | Array.<string>

View Source admin-bro/src/utils/flat/filter-out-params.ts, line 10

# static get(params, propertyPathopt, options) → {any}

Returns sub-property from the flatten params. When the property path is not given function returns an entire unflatten object.

Example


import flat from '@admin-bro'

const params = {
  name: 'John',
  'education.school.name': 'Harvard',
  'education.school.id': 123,
}

const data = flat.get(params, 'education.school')
// results to {
//   name: 'Harvard',
//   id: 321,
// }

// value is undefined
const data = flat.get(params)
// results to {
//   name: 'John',
//   education: {
//     school: {
//       name: 'Harvard',
//       id: 321,
//     }
//   }
// }
Parameters:
Name Type Attributes Description
params FlattenParams

flatten params from which property has to be taken

propertyPath string <optional>

name of the property

options GetOptions

options

View Source admin-bro/src/utils/flat/get.ts, line 17

when property key exists directly it returns what is inside, otherwise it tries to find any nested objects and returns them

any

# static merge(params) → {FlattenParams}

Merges params together and returns flatten result

Parameters:
Name Type Description
params any
...mergeParams Array.<any>

View Source admin-bro/src/utils/flat/merge.ts, line 12

# static selectParams(params, properties, optionsopt) → {FlattenParams}

From all keys in params it selects only those passed in arguments.

Example


import flat from '@admin-bro'

const params = {
  name: 'John',
  'education.school.name': 'Harvard',
  'education.school.id': 123,
}

flat.selectParams(params, 'education.school')
// results to {
//   'education.school.name': 'Harvard',
//   'education.school.id': 123,
// }

flat.selectParams(params, 'education.school.id', 'name')
// results to {
//   'name': 'John',
//   'education.school.id': 123,
// }
Parameters:
Name Type Attributes Description
params FlattenParams
properties string | Array.<string>
options GetOptions <optional>

View Source admin-bro/src/utils/flat/select-params.ts, line 11

# static set(params, propertyPath, valueopt) → {FlattenParams}

Updates the flatten param object with a given value. Value can be anything and, this anything will be flattened and added to params.

params is not mutated here.

Example


import flat from '@admin-bro'

const params = {
  name: 'John',
  'education.school.name': 'Harvard',
  'education.school.id': 123,
}

const data = flat.set(params, 'education.shool', {
  name: 'Yale',
  id: 321,
})
// results to data === {
//   name: 'John',
//   'education.school.name': 'Yale`,
//   'education.school.id': 321,
// }

// value is undefined
const data = flat.set(params, 'education') // results to data === { name: 'John' }
Parameters:
Name Type Attributes Description
params FlattenParams
propertyPath string
value any <optional>

if not give function will only try to remove old keys

View Source admin-bro/src/utils/flat/set.ts, line 22

# pathToParts(propertyPath, options) → {PathParts}

the Long story short this method:

  • changes: nested.nested2.normalInner
  • to ["nested", "nested.nested2", "nested.nested2.normalInner"]

So it can be used to search for the param in a FlattenParams object.

Formally it changes path in "flatten" notation, to an Array of all possible keys, which could have searched property.

When skipArrayIndexes is set to true it also it takes care of the arrays, which are separated by numbers (indexes). Then it:

  • changes: nested.0.normalInner.1
  • to: nested.normalInner

Everything because when we look for a property of a given path it can be inside a mixed property. So first, we have to find top-level mixed property, and then, step by step, find inside each of them.

Parameters:
Name Type Description
propertyPath string
options PathToPartsOptions

View Source admin-bro/src/utils/flat/path-to-parts.ts, line 11

PathParts

Type Definitions

object

# FlattenParams

Type of flatten params.

Properties:
Name Type Description
{...} FlattenValue

View Source admin-bro/src/utils/flat/flat.types.ts, line 17

Union

# FlattenValue

Available types for flatten values. This is an Union of types:

  • string
  • boolean
  • number
  • Date
  • null
  • [] (empty array)
  • {} (empty object)
  • File

View Source admin-bro/src/utils/flat/flat.types.ts, line 2

object

# GetOptions

Properties:
Name Type Attributes Description
includeAllSiblings boolean <optional>

Indicates if all the "less related" siblings should be included. This option takes care of, fetching elements in nested arrays. Let's say you have keys: nested.0.array.0 and , nested.1.array.0.. With includeAllSiblings` you will fetch all nested.N.array elements.

View Source admin-bro/src/utils/flat/flat.types.ts, line 26

object

# PathToPartsOptions

Properties:
Name Type Attributes Description
skipArrayIndexes boolean <optional>

Indicates if array indexes should be skipped from the outcome.

View Source admin-bro/src/utils/flat/path-to-parts.ts, line 30

SoftwareBrothers

Proudly built and maintained by SoftwareBrothers

Software House with a passion for both JavaScript and TypeScript.

See what we do See what we believe in

Proudly built and maintained by

SoftwareBrothers