Browse Source

docs: updates README.md

e22m4u 3 weeks ago
parent
commit
0d2ff41c68
1 changed files with 170 additions and 135 deletions
  1. 170 135
      README.md

+ 170 - 135
README.md

@@ -6,9 +6,9 @@ JavaScript модуль для работы со схемой данных.
 
 - [Установка](#установка)
 - [Схема данных](#схема-данных)
-- [Использование](#использование)
-  - [Проверка данных](#проверка-данных)
-  - [Парсинг данных](#парсинг-данных)
+- [Проверка данных](#проверка-данных)
+- [Парсинг данных](#парсинг-данных)
+- [Именованные схемы](#именованные-схемы)
 - [Пустые значения](#пустые-значения)
 - [Тесты](#тесты)
 - [Лицензия](#лицензия)
@@ -33,7 +33,7 @@ import {DataValidator} from '@e22m4u/js-data-schema';
 const {DataValidator} = require('@e22m4u/js-data-schema');
 ```
 
-### Схема данных
+## Схема данных
 
 Схема данных позволяет указать допустимый тип значения, схему элементов
 массива и схему свойств объекта. Схему можно использовать для проверки
@@ -165,127 +165,96 @@ const {DataValidator} = require('@e22m4u/js-data-schema');
 }
 ```
 
-## Использование
+## Проверка данных
 
-Ниже приводятся примеры использования различных схем.
-
-### Проверка данных
-
-Проверка типа данных.
+Модуль экспортирует сервис `DataValidator`, с помощью которого выполняется
+проверка соответствия данных указанной схеме. Пример ниже демонстрирует
+создание экземпляра сервиса и проверку примитивных значений.
 
 ```js
 import {DataValidator, DataType} from '@e22m4u/js-data-schema';
 
 const validator = new DataValidator();
-
-const schema = {
-  type: DataType.STRING, // тип данных
-};
-
-// значение "str" соответствует схеме
-validator.validate('str', schema); // OK
-
-// undefined допускается (параметр "required" не указан)
-validator.validate(undefined, schema); // OK
-
-// 10 не является строкой
-validator.validate(10, schema); // error: DataValidationError
-
-// true не является строкой
-validator.validate(true, schema); // error: DataValidationError
+const numberSchema = {type: DataType.NUMBER};
+
+// OK
+validator.validate(10, numberSchema);
+validator.validate(0, numberSchema);
+validator.validate(undefined, numberSchema);
+validator.validate(null, numberSchema);
+
+// выбросит DataValidationError
+validator.validate('str', numberSchema);
+validator.validate(true, numberSchema);
+validator.validate([1, 2, 3], numberSchema);
+validator.validate({foo: 'bar'}, numberSchema);
 ```
 
-Проверка обязательного значения.
+Каждый тип данных имеет собственный набор [пустых значений](#пустые-значения),
+которые являются допустимыми при проверке данных соответствующего типа.
+Чтобы исключить такие значения применяется параметр `required`.
 
 ```js
 import {DataValidator, DataType} from '@e22m4u/js-data-schema';
 
 const validator = new DataValidator();
 
-const schema = {
-  type: DataType.NUMBER, // тип данных
-  required: true,        // является обязательным
+const requiredNumberSchema = {
+  type: DataType.NUMBER,
+  required: true // исключает пустые значения
 };
 
-// значение 10 соответствует схеме
-validator.validate(10, schema); // OK
-
-// undefined не допускается (параметр "required")
-validator.validate(undefined, schema); // error: DataValidationError
-
-// 'str' не является числом
-validator.validate('str', schema); // error: DataValidationError
+// OK
+validator.validate(10, requiredNumberSchema);
+validator.validate(-10, requiredNumberSchema);
 
-// true не является числом
-validator.validate(true, schema); // error: DataValidationError
+// выбросит DataValidationError
+validator.validate(0, requiredNumberSchema);
+validator.validate(undefined, requiredNumberSchema);
+validator.validate(null, requiredNumberSchema);
 ```
 
-Проверка элементов массива.
-
-```js
-import {DataValidator, DataType} from '@e22m4u/js-data-schema';
+## Парсинг данных
 
-const validator = new DataValidator();
+Сервис `DataParser` спроектирован для приведения данных в соответствие
+указанной схеме. Приведение выполняется с учетом возможных ошибок
+пользовательского ввода. К примеру, если схема ожидает число, но входящие
+данные содержат другие символы, то будет выброшена ошибка.
 
-const schema = {
-  type: DataType.ARRAY, // тип данных
-  items: {
-    type: DataType.NUMBER, // тип элемента
-  },
-};
-
-// элементы массива соответствуют схеме
-validator.validate([1, 2, 3], schema); // OK
-
-// пустой массив также допускается
-validator.validate([], schema); // OK
-
-// 'str' не является массивом
-validator.validate('str', schema); // error: DataValidationError
+```js
+import {DataParser, DataType} from '@e22m4u/js-data-schema';
 
-// элементы массива не соответствуют схеме (параметр "items")
-validator.validate(['a', 'b'], schema); // error: DataValidationError
+const parser = new DataParser();
 
-// объект не является массивом
-validator.validate({foo: 'bar'}, schema); // error: DataValidationError
+parser.parse('10', {type: DataType.NUMBER});    // 10
+parser.parse('10.5', {type: DataType.NUMBER});  // 10.5
+parser.parse('10abc', {type: DataType.NUMBER}); // DataParsingError
 ```
 
-Проверка свойств объекта.
+Массивы и объекты могут быть представлены в виде *JSON*. Метод `parse`
+разбирает такие значения и выполняет их проверку. К примеру, если элементы
+массива не соответствуют определению схемы, то будет выброшена ошибка.
 
 ```js
-import {DataValidator, DataType} from '@e22m4u/js-data-schema';
+import {DataParser, DataType} from '@e22m4u/js-data-schema';
 
-const validator = new DataValidator();
+const parser = new DataParser();
 
-const schema = {
-  type: DataType.OBJECT, // тип данных
-  properties: {
-    foo: { // схема свойства "foo"
-      type: DataType.STRING, // тип свойства
-      required: true,        // является обязательным
-    },
-    bar: { // схема свойства "bar"
-      type: DataType.NUMBER, // тип свойства
-    },
+const numberListSchema = {
+  type: DataType.ARRAY,
+  items: {
+    type: DataType.NUMBER,
+    required: true, // исключает undefined, null и 0
   },
 };
 
-// свойства объекта соответствуют схеме
-validator.validate({foo: 'str', bar: 10}, schema); // OK
-
-// обязательное свойство "foo" присутствует
-validator.validate({foo: 'str'}, schema); // OK
-
-// значение свойства "foo" не является строкой
-validator.validate({foo: true}, schema); // error: DataValidationError
-
-// массив не является объектом
-validator.validate([1, 2, 3], schema); // error: DataValidationError
+parser.parse('[1, 2, 3]', numberListSchema);    // [1, 2, 3]
+parser.parse('[1, 2, null]', numberListSchema); // DataParsingError
 ```
 
-### Парсинг данных
-
-Приведение типа согласно схеме.
+Если при разборе данных значение оказалось [пустым](#пустые-значения),
+то при наличии параметра `default` используется значение по умолчанию.
+Значение данного параметра должно соответствовать схеме.
 
 ```js
 import {DataParser, DataType} from '@e22m4u/js-data-schema';
@@ -293,76 +262,142 @@ import {DataParser, DataType} from '@e22m4u/js-data-schema';
 const parser = new DataParser();
 
 const schema = {
-  type: DataType.NUMBER, // тип данных
+  type: DataType.NUMBER,
+  default: 0,
 };
 
-// приведение строки к числу
-const result = parser.parse('10', schema);
-console.log(result); // 10
-
-// строка не является числом
-parser.parse('10abc', schema); // error: DataParsingError
+parser.parse('10', schema);      // 10
+parser.parse(undefined, schema); // 0
+parser.parse('N/A', schema);     // DataParsingError
 ```
 
-Разбор JSON строки согласно схеме массива.
+## Именованные схемы
+
+Модуль экспортирует сервисы для проверки и парсинга данных. Каждый
+сервис позволяет регистрировать схемы данных по уникальному имени
+методом `defineSchema`.
 
 ```js
-import {DataParser, DataType} from '@e22m4u/js-data-schema';
+import {DataValidator, DataParser, DataType} from '@e22m4u/js-data-service';
 
+const validator = new DataValidator();
 const parser = new DataParser();
 
 const schema = {
-  type: DataType.ARRAY, // тип данных
+  type: DataType.ARRAY,
   items: {
-    type: DataType.NUMBER, // тип элемента
+    type: DataType.STRING,
+    required: true,
   },
 };
 
-// приведение строки к массиву
-const result = parser.parse('[1, 2, 3]', schema);
-console.log(result);
-// [1, 2, 3]
+validator.defineSchema({name: 'mySchema', schema});
+parser.defineSchema({name: 'mySchema', schema});
+```
+
+Регистрация может выполняться централизованно через реестр. Этого можно
+добиться используя сервис-контейнер, который обычно выступает как точка
+входа в приложение.
 
-// элементы массива не соответствуют схеме
-parser.parse('["str", true]', schema); // error: DataParsingError
+```js
+import {ServiceContainer} from '@e22m4u/js-service';
+
+import {
+  DataType,
+  DataParser,
+  DataValidator,
+  DataSchemaRegistry,
+} from '@e22m4u/js-data-service';
+
+const app = new ServiceContainer();
+const registry = app.get(DataSchemaRegistry);
+
+registry.defineSchema({
+  name: 'mySchema',
+  schema: {
+    type: DataType.ARRAY,
+    items: {
+      type: DataType.STRING,
+      required: true,
+    },
+  },
+});
+
+const validator = app.get(DataValidator);
+const parser = app.get(DataParser);
 ```
 
-Разбор JSON строки согласно схеме объекта.
+В примере выше оба сервиса используют общий реестр и знают о зарегистрированной
+схеме `mySchema`, что избавляет от необходимости синхронизации схем между ними.
+
+#### Использование именованных схем
+
+Зарегистрированное имя схемы можно использовать вместо обычной схемы. Пример
+ниже демонстрирует проверку данных с помощью именованной схемы.
 
 ```js
-import {DataParser, DataType} from '@e22m4u/js-data-schema';
+validator.defineSchema({
+  name: 'stringList',
+  schema: {
+    type: DataType.STRING,
+    required: true,
+  },
+});
 
-const parser = new DataParser();
+validator.validate(['a', 'b', 'c'], 'mySchema'); // OK
+validator.validate(['a', 'b', 10], 'mySchema'); // DataValidationError
+```
 
-const schema = {
-  type: DataType.OBJECT, // тип данных
-  properties: {
-    foo: { // схема свойства "foo"
-      type: DataType.STRING, // тип свойства
-      required: true,        // является обязательным
-    },
-    bar: { // схема свойства "bar"
-      type: DataType.NUMBER, // тип свойства
+Имена схем можно встраивать в обычные схемы. Ниже приводится пример
+использования именованной схемы для определения схемы элементов массива.
+
+```js
+parser.defineSchema({
+  name: 'user', // имя схемы
+  schema: {
+    type: DataType.OBJECT,
+    properties: {
+      name: {
+        type: DataType.STRING,
+        required: true,
+      },
+      age: {
+        type: DataType.NUMBER,
+        default: 0,
+      },
     },
   },
-};
+});
 
-// приведение строки к объекту
-const result = parser.parse(
-  '{"foo": "str", "bar": 10}',
-  schema,
-);
-console.log(result);
-// {
-//   "foo": "str",
-//   "bar": 10
-// }
+const jsonData = `[{"name": "John","age": 35},{"name": "Tommy"}]`;
 
-// обязательное свойство "foo" отсутствует
-parser.parse('{"bar": 10}', schema); // error: DataParsingError
+const users = parser.parse(jsonData, {
+  type: DataType.ARRAY,
+  items: 'user', // <= именованная схема
+});
+console.log(users);
+// [
+//   {
+//     name: 'John',
+//     age: 35
+//   },
+//   {
+//     name: 'Tommy',
+//     age: 0
+//   }
+// ]
+```
+
+Если именованная схема описывает объект, то допускается передача имени схемы
+в параметр `properties`, что позволяет переопределить остальные параметры
+зарегистрированной схемы.
 
-// значение свойства "foo" не является строкой
-parser.parse('{"foo": 10}', schema); // error: DataParsingError
+```js
+validator.validate(data, {
+  type: DataType.OBJECT,
+  properties: 'user', // имя схема вместо схемы свойств
+  required: true,     // переопределение параметра схемы "user"
+});
 ```
 
 ## Пустые значения