## @e22m4u/js-data-projector JavaScript модуль для создания проекции данных на основе декларативных схем. ## Содержание - [Установка](#установка) - [Схема проекции](#схема-проекции) - [Использование](#использование) - [Применение схемы](#применение-схемы) - [Строгий режим](#строгий-режим) - [Область проекции](#область-проекции) - [Фабричные функции](#фабричные-функции) - [Именованные схемы](#именованные-схемы) - [Тесты](#тесты) - [Лицензия](#лицензия) ## Установка ```bash npm install @e22m4u/js-data-projector ``` Модуль поддерживает ESM и CommonJS стандарты. *ESM* ```js import {projectData} from '@e22m4u/js-data-projector'; ``` *CommonJS* ```js const {projectData} = require('@e22m4u/js-data-projector'); ``` ## Схема проекции Определение правил видимости полей. ```js { foo: true, // поле доступно bar: false // поле скрыто // объект настроек baz: {}, // поле доступно qux: {select: true}, // поле доступно buz: {select: false}, // поле скрыто } ``` Определение вложенной схемы. ```js { name: true, // поле "name" доступно address: { // настройки поля "address" select: true, // поле "address" доступно schema: { // вложенная схема city: true, // поле "address.city" доступно zip: false // поле "address.zip" скрыто } } } ``` Определение правил для областей проекции. ```js { password: { // настройки поля "password" select: false, // поле "password" недоступно по умолчанию scopes: { // настройки для областей проекции input: true, // поле доступно для области "input" output: false // но скрыто для области "output" } } } ``` Определение вложенной именованной схемы. ```js { name: true, // поле "name" доступно address: { // настройки поля "address" select: true, // поле "address" доступно schema: 'address' // имя вложенной схемы } } ``` ## Использование Ниже приводятся примеры использования данного модуля. ### Применение схемы Создание проекции данных с помощью схемы. ```js import {projectData} from '@e22m4u/js-data-projector'; const schema = { name: true, password: false, }; const data = { name: 'Fedor', // допускается, явное правило password: 'pass123', // исключается, явное правило extra: 10, // допускается в режиме по умолчанию }; const result = projectData(data, schema); console.log(result); // { // name: 'Fedor', // extra: 10 // } ``` Применение схемы к массиву объектов. ```js import {projectData} from '@e22m4u/js-data-projector'; const schema = { id: true, secret: false, }; const data = [ {id: 1, secret: 'A'}, {id: 2, secret: 'B'}, ]; const result = projectData(data, schema); console.log(result); // [ // {id: 1}, // {id: 2} // ] ``` Применение вложенной схемы для сложной структуры данных. ```js import {projectData} from '@e22m4u/js-data-projector'; 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(data, schema); console.log(result); // { // name: 'Fedor', // city: { // name: 'Moscow', // } // } ``` ### Строгий режим Исключение полей не указанных в схеме проекции. ```js import {projectData} from '@e22m4u/js-data-projector'; const schema = { name: true, password: false, }; const data = { name: 'Fedor', // допускается, явное правило password: 'pass123', // исключается, явное правило extra: 10, // исключается в строгом режиме }; const result = projectData(data, schema, { strict: true, // <= строгий режим }); console.log(result); // { // name: 'Fedor' // } ``` ### Область проекции Создание проекции определенной области. ```js import {projectData} from '@e22m4u/js-data-projector'; const schema = { name: true, password: { scopes: { input: true, // правило для области "input" output: false, // правило для области "output" }, }, }; const data = { name: 'Fedor', // допускается, явное правило password: 'pass123', // исключается для области "output" }; const inputData = projectData(data, schema, { scope: "input", // <= область видимости }); console.log(inputData); // { // name: 'Fedor', // password: 'pass123' // } const outputData = projectData(data, schema, { scope: "output", // <= область видимости }); console.log(outputData); // { // name: 'Fedor' // } ``` Использование сокращенных методов для работы с областями. ```js import {DataProjector} from '@e22m4u/js-data-projector'; const projector = new DataProjector(); projector.defineSchema({ name: 'user', schema: { username: true, password: { scopes: { input: true, // поле "password" доступно для области "input" output: false, // поле "password" скрыто для области "output" }, }, }, }); const data = { username: 'john_doe', password: 'secret123', } // аналог projector.project(data, 'user', {scope: "input"}) const input = projector.projectInput(data, 'user'); console.log(input); // { // username: 'john_doe', // password: 'secret123' // } // аналог projector.project(data, 'user', {scope: "output"}) const output = projector.projectOutput(data, 'user'); console.log(output); // { // username: 'john_doe' // } ``` ### Фабричные функции Использование фабрики вместо объекта схемы. ```js import {projectData} from '@e22m4u/js-data-projector'; // фабрика возвращает объект схемы const getSchema = () => { return { id: true, hiddenField: false, }; }; const data = { id: 1, hiddenField: 'secret', }; // передача функции вместо объекта const result = projectData(data, getSchema); console.log(result); // { // id: 1 // } ``` Использование фабрики во вложенной схеме. ```js import {projectData} from '@e22m4u/js-data-projector'; // фабрика для вложенных данных const getAddressSchema = () => { return { city: true, zip: false, }; }; const userSchema = { name: true, address: { schema: getAddressSchema, // <= использование фабрики }, }; const data = { name: 'Fedor', address: { city: 'Moscow', zip: 123456, }, }; const result = projectData(data, userSchema); console.log(result); // { // name: 'Fedor', // address: { // city: 'Moscow' // } // } ``` Установка аргументов вызова фабричных функций. ```js import {projectData} from '@e22m4u/js-data-projector'; // объект будет передан в параметры фабрики const logger = { log: (message) => console.log(message), }; // фабрика использует logger const getSchema = (logger) => { logger.log('Factory was invoked!'); return {name: true, secret: false}; }; const data = { name: 'John', secret: 'john123', }; const result = projectData(data, getSchema, { factoryArgs: [logger], // <= передача logger в фабрику }); // Factory was invoked! console.log(result); // { // name: 'John', // } ``` Доступ к [сервис-контейнеру](https://www.npmjs.com/package/@e22m4u/js-service) внутри фабрики. ```js import {ServiceContainer} from '@e22m4u/js-service'; import {DataProjector} from '@e22m4u/js-data-projector'; // сервис-контейнер доступен только // при использовании DataProjector const projector = new DataProjector(); // сервис-контейнер передается // первым аргументом фабрики const getSchema = (container) => { console.log(container instanceof ServiceContainer); // true return {name: true, secret: false}; } const data = { name: 'John', secret: 'john123', }; const result = projector.project(data, getSchema); console.log(result); // { // name: 'John', // } ``` ### Именованные схемы Регистрация и применение именованной схемы. ```js import {DataProjector} from '@e22m4u/js-data-projector'; const projector = new DataProjector(); // регистрация схемы projector.defineSchema({ name: 'user', // <= имя схемы schema: { id: true, username: true, email: false, }, }); const data = { id: 10, username: 'admin', email: 'admin@example.com', }; // проекция данных по зарегистрированному имени const result = projector.project(data, 'user'); console.log(result); // { // id: 10, // username: 'admin' // } ``` Использование вложенных именованных схем. ```js import {DataProjector} from '@e22m4u/js-data-projector'; const projector = new DataProjector(); // регистрация схемы "address" projector.defineSchema({ name: 'address', schema: { city: true, zip: false, }, }); // регистрация схемы "user" 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(data, 'user'); console.log(result); // { // name: 'Fedor', // address: { // city: 'Moscow' // } // } ``` Регистрация псевдонима именованной схемы. ```js import {DataProjector} from '@e22m4u/js-data-projector'; const projector = new DataProjector(); // регистрация основной схемы projector.defineSchema({ name: 'user', schema: { id: true, name: true, email: false, }, }); // регистрация псевдонима projector.defineSchema({ name: 'author', // имя псевдонима schema: 'user', // <= имя основной схемы }); const data = { id: 10, name: 'Fedor', email: 'fedor@example.com', }; // проекция данных по имени псевдонима const result = projector.project(data, 'author'); console.log(result); // { // id: 10, // name: 'Fedor' // } ``` Использование фабрики при регистрации именованной схемы. ```js import {DataProjector} from '@e22m4u/js-data-projector'; const projector = new DataProjector(); // создание фабрики const getUserSchema = () => { return { id: true, name: true, email: false, }; }; // регистрация схемы projector.defineSchema({ name: 'user', schema: getUserSchema, // <= фабрика вместо схемы }); const data = { id: 10, name: 'Fedor', email: 'fedor@example.com', }; const result = projector.project(data, 'user'); console.log(result); // { // id: 10, // name: 'Fedor' // } ``` Реализация пользовательской функции разрешения имен. ```js import {projectData} from '@e22m4u/js-data-projector'; // функция разрешения имен const nameResolver = name => { if (name === 'user') { return {id: true, name: true, password: false}; } throw new Error(`Schema "${name}" is not found!`); }; const data = { id: 1, name: 'Fedor', password: 'pass123', }; const result = projectData( data, 'user', // <= вместо схемы передается имя {nameResolver}, // <= разрешающая функция ); console.log(result); // { // id: 1, // name: 'Fedor' // } ``` ## Тесты ```bash npm run test ``` ## Лицензия MIT