JavaScript модуль для работы с проекцией данных

e22m4u 5915490121 chore: bumps version to 0.0.6 4 дней назад
.husky 22b5a33b5f chore: initial commit 2 недель назад
dist ed7a276a50 feat: adds DataProjector 4 дней назад
src ed7a276a50 feat: adds DataProjector 4 дней назад
.c8rc 22b5a33b5f chore: initial commit 2 недель назад
.commitlintrc 22b5a33b5f chore: initial commit 2 недель назад
.editorconfig 22b5a33b5f chore: initial commit 2 недель назад
.gitignore 22b5a33b5f chore: initial commit 2 недель назад
.mocharc.json 6f15ecb1a5 refactor: improve linting 1 неделя назад
.prettierrc 22b5a33b5f chore: initial commit 2 недель назад
LICENSE 22b5a33b5f chore: initial commit 2 недель назад
README.md 42e64d7049 docs: updates README.md 4 дней назад
build-cjs.js 22b5a33b5f chore: initial commit 2 недель назад
eslint.config.js 6f15ecb1a5 refactor: improve linting 1 неделя назад
package.json 5915490121 chore: bumps version to 0.0.6 4 дней назад
tsconfig.json 6f15ecb1a5 refactor: improve linting 1 неделя назад

README.md

@e22m4u/js-data-projection

JavaScript модуль для работы с проекцией данных.

Модуль использует схемы для определения правил видимости полей данных. Поддерживается вложенность, функции-фабрики, именованные схемы, области проекции и строгий режим.

Содержание

Установка

npm install @e22m4u/js-data-projection

Использование

Модуль экспортирует функцию projectData для создания проекций и класс DataProjector с возможностью регистрации и применения именованных схем.

Создание проекции

Схема проекции описывает настройки видимости для каждого поля. Логические значения определяют видимость поля. Поля, отсутствующие в схеме, остаются в результате по умолчанию.

import {projectData} from '@e22m4u/js-data-projection';

const schema = {
  name: true,
  password: false,
};

const data = {
  name: 'Fedor',       // будет доступно, явное правило
  password: 'pass123', // будет исключено, явное правило
  extra: 10,           // будет доступно в режиме по умолчанию
};

const result = projectData(schema, data);
console.log(result);
// {
//   name: 'Fedor',
//   extra: 10
// }

Проекция массива

Если входные данные представляют собой массив, то проекция применяется к каждому элементу рекурсивно. Структура результата соответствует исходному массиву.

import {projectData} from '@e22m4u/js-data-projection';

const schema = {
  id: true,
  secret: false,
};

const data = [
  {id: 1, secret: 'A'},
  {id: 2, secret: 'B'},
];

const result = projectData(schema, data);
console.log(result);
// [
//   {id: 1},
//   {id: 2}
// ]

Строгий режим

Строгий режим исключает из результата все поля, не описанные в схеме явно. Поведение регулируется опцией strict. Данный режим позволяет гарантировать отсутствие лишних данных в результате.

import {projectData} from '@e22m4u/js-data-projection';

const schema = {
  name: true,
  password: false,
};

const data = {
  name: 'Fedor',       // будет доступно, явное правило
  password: 'pass123', // будет исключено, явное правило
  extra: 10,           // будет исключено в строгом режиме
};

const result = projectData(schema, data, {
  strict: true, // <= строгий режим
});
console.log(result);
// {
//   name: 'Fedor'
// }

Вложенные схемы

Вложенные объекты обрабатываются с помощью свойства schema в настройках поля. Данное свойство позволяет определять правила видимости для вложенных структур данных.

import {projectData} from '@e22m4u/js-data-projection';

const schema = {
  id: false,
  name: true,
  city: {
    select: true, // правило видимости поля city
    schema: {     // вложенная схема
      id: false,
      name: true,
    },
  },
};

const data = {
  id: 10,             // будет скрыто, явное правило
  name: 'Fedor',
  city: {
    id: 20,           // будет скрыто, явное правило
    name: 'Moscow',
  },
};

const result = projectData(schema, data);
console.log(result);
// {
//   name: 'Fedor',
//   city: {
//     name: 'Moscow',
//   }
// }

Область проекции

Правила видимости полей могут зависеть от области проекции. Свойство scopes определяет специфичные правила для разных контекстов, передаваемых через опцию scope.

import {projectData} from '@e22m4u/js-data-projection';

const schema = {
  name: true,
  password: {
    scopes: {
      input: true,   // правило для области 'input'
      output: false, // правило для области 'output'
    },
  },
};

const data = {
  name: 'Fedor',       // будет доступно, явное правило
  password: 'pass123', // будет доступно в зависимости от области
};

const inputData = projectData(schema, data, {
  scope: 'input', // <= область проекции
});
console.log(inputData);
// {
//   name: 'Fedor',
//   password: 'pass123'
// }

const outputData = projectData(schema, data, {
  scope: 'output', // <= область проекции
});
console.log(outputData);
// {
//   name: 'Fedor'
// }

Модуль экспортирует объект констант с именами часто используемых областей проекции.

import {ProjectionScope} from '@e22m4u/js-data-projection';

console.log(ProjectionScope);
// {
//   INPUT: 'input',
//   OUTPUT: 'output'
// }

projectData(schema, data, {
  scope: ProjectionScope.INPUT,
});

Фабричные функции

Вместо статической схемы можно передать фабричную функцию, которая вернет объект схемы. Это полезно, если схему необходимо генерировать динамически или переиспользовать логику создания схем.

import {projectData} from '@e22m4u/js-data-projection';

// фабрика возвращает объект схемы
const getSchema = () => {
  return {
    id: true,
    hiddenField: false,
  };
};

const data = {
  id: 1,
  hiddenField: 'secret',
};

// передача функции вместо объекта
const result = projectData(getSchema, data);
console.log(result);
// {
//   id: 1
// }

Фабрики также поддерживаются во вложенных структурах. Свойство schema может принимать функцию, возвращающую схему для вложенного объекта.

import {projectData} from '@e22m4u/js-data-projection';

// фабрика для вложенных данных
const getAddressSchema = () => ({
  city: true,
  zip: false,
});

const userSchema = {
  name: true,
  address: {
    schema: getAddressSchema, // <= использование фабрики
  },
};

const data = {
  name: 'Fedor',
  address: {
    city: 'Moscow',
    zip: 123456,
  },
};

const result = projectData(userSchema, data);
console.log(result);
// {
//   name: 'Fedor',
//   address: {
//     city: 'Moscow'
//   }
// }

Регистрация именованных схем

Класс DataProjector позволяет сохранять схемы во внутреннем реестре для их последующего использования по имени. Это удобно для переиспользования схем в разных частях приложения.

import {DataProjector} from '@e22m4u/js-data-projection';

const projector = new DataProjector();

projector.defineSchema({
  name: 'user',
  schema: {
    id: true,
    name: true,
    password: false,
  },
});

Зарегистрированные схемы могут ссылаться друг на друга, что позволяет компоновать сложные схемы из более простых. В примере ниже схема user использует схему address как вложенную.

import {DataProjector} from '@e22m4u/js-data-projection';

const projector = new DataProjector();

projector.defineSchema({
  name: 'address',
  schema: {
    city: true,
    zip: false,
  },
});

projector.defineSchema({
  name: 'user',
  schema: {
    name: true,
    address: {
      select: true,      // видимость поля address
      schema: 'address', // <= вложенная схема
    },
  },
});

Применение именованных схем

В данном примере вместо передачи объекта схемы используется предварительно зарегистрированное имя publicUser. Проектор находит соответствующее определение в своем реестре и применяет его к исходным данным.

import {DataProjector} from '@e22m4u/js-data-projection';

const projector = new DataProjector();

projector.defineSchema({
  name: 'publicUser',
  schema: {
    id: true,
    username: true,
    email: false,
  },
});

const data = {
  id: 10,
  username: 'admin',
  email: 'admin@example.com',
};

// проекция данных по имени схемы
const result = projector.project('publicUser', data);
console.log(result);
// {
//   id: 10,
//   username: 'admin'
// }

Проектор автоматически разрешает зависимости между схемами. Если в схеме указана ссылка на другую именованную схему, проектор найдет её в реестре и применит к вложенным данным.

import {DataProjector} from '@e22m4u/js-data-projection';

const projector = new DataProjector();

projector.defineSchema({
  name: 'address',
  schema: {
    city: true,
    zip: false,
  },
});

projector.defineSchema({
  name: 'user',
  schema: {
    name: true,
    address: {
      select: true,      // видимость поля address
      schema: 'address', // <= имя вложенной схемы
    },
  },
});

const data = {
  name: 'Fedor',
  address: {
    city: 'Moscow',
    zip: 123456,
  },
};

const result = projector.project('user', data);
console.log(result);
// {
//   name: 'Fedor',
//   address: {
//     city: 'Moscow'
//   }
// }

Ручное разрешение имен

Для ручного разрешения имен используется опция resolver функции projectData. В опцию передается функция, которая принимает имя схемы и должна вернуть соответствующий ей объект схемы.

import {projectData} from '@e22m4u/js-data-projection';

// функция для разрешения имен
const resolver = key => {
  if (key === 'user') {
    return {id: true, name: true, password: false};
  }
  throw new Error(`Schema "${key}" is not found!`);
};

const data = {
  id: 1,
  name: 'Fedor',
  password: 'pass123',
};

const result = projectData(
  'user', // <= вместо схемы передается имя
  data,
  {resolver}, // <= разрешающая функция
);
console.log(result);
// {
//   id: 1,
//   name: 'Fedor'
// }

Функция projectData

Функция создает проекцию данных на основе переданного объекта схемы. Принимает исходные данные и дополнительные опции для управления режимом строгости и областью видимости.

Сигнатура вызова:

projectData(schemaOrFactory, data, [options])

schemaOrFactory

Тип: object | Function | string

Определяет правила проекции. Принимает:

  • object: объект схемы проекции;
  • Function: фабрика, возвращающая схему (или имя схемы);
  • string: имя для поиска схемы через функцию resolver;

data

Тип: object | object[] | any

Исходные данные для проекции.

options (необязательно)

Тип: object

Объект с дополнительными настройками:

  • strict?: boolean: включает строгий режим;
  • scope?: string: имя активной области проекции;
  • resolver?: Function: функция для получения схемы по имени;

Возвращаемое значение:

Функция возвращает новую структуру, соответствующую исходным данным. Если передан объект, результатом будет его копия, содержащая свойства, разрешенные правилами схемы с учетом вложенности, строгого режима и активной области проекции.

Для массивов возвращается новый список, к каждому элементу которого рекурсивно применена схема проекции. Примитивные значения возвращаются без изменений.

Класс DataProjector

Для централизованного управления схемами и удобной работы в рамках сервис-ориентированной архитектуры модуль предоставляет класс DataProjector. Он позволяет регистрировать именованные схемы в реестре и применять их по имени без необходимости вручную передавать функцию resolver при каждом вызове.

Создание экземпляра:

import {DataProjector} from '@e22m4u/js-data-projection';

const projector = new DataProjector();

Метод defineSchema

Регистрирует новую схему в реестре проектора. Метод принимает объект определения, содержащий уникальное имя схемы и правила проекции. Возвращает текущий экземпляр DataProjector, что позволяет использовать цепочки вызовов.

Сигнатура вызова:

defineSchema(schemaDef)

schemaDef

Тип: {name: string, schema: object}

Объект определения схемы, связывающий название схемы с правилами проекции.

  • name: string: название новой схемы;
  • schema: object: объект схемы проекции;

Возвращаемое значение:

Текущий экземпляр DataProjector.

Метод project

Выполняет проекцию данных, используя возможности внутреннего реестра схем. Метод работает аналогично функции projectData, но автоматически предоставляет механизм разрешения имен (resolver), связанный с добавленными ранее схемами. Это позволяет передавать в качестве первого аргумента строковое имя зарегистрированной схемы без необходимости указывать функцию resolver в опциях вручную.

Сигнатура вызова:

project(schemaOrFactory, data, [options])

schemaOrFactory

Тип: object | Function | string

Определяет правила проекции. Принимает:

  • object: объект схемы проекции;
  • Function: фабрика, возвращающая схему (или имя схемы);
  • string: зарегистрированное имя схемы;

data

Тип: object | object[] | any

Исходные данные для проекции.

options (необязательно)

Тип: object

Объект с дополнительными настройками:

  • strict?: boolean: включает строгий режим;
  • scope?: string: имя активной области проекции;

Возвращаемое значение:

Метод возвращает проекцию исходных данных в соответствии с переданной схемой и настройками.

Тесты

npm run test

Лицензия

MIT