{"id":19988772,"url":"https://github.com/e22m4u/ts-data-schema","last_synced_at":"2025-08-05T15:16:30.196Z","repository":{"id":260546133,"uuid":"880355800","full_name":"e22m4u/ts-data-schema","owner":"e22m4u","description":"Валидация данных и приведение типов для TypeScript","archived":false,"fork":false,"pushed_at":"2025-04-24T01:01:12.000Z","size":208,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-24T01:23:50.611Z","etag":null,"topics":["data","schema","typescript","validation"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/e22m4u.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-10-29T15:20:06.000Z","updated_at":"2025-04-24T01:01:11.000Z","dependencies_parsed_at":"2024-11-01T00:15:56.873Z","dependency_job_id":"17324a26-54cf-4ddb-b67e-63701de95386","html_url":"https://github.com/e22m4u/ts-data-schema","commit_stats":null,"previous_names":["e22m4u/ts-data-schema"],"tags_count":12,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/e22m4u%2Fts-data-schema","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/e22m4u%2Fts-data-schema/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/e22m4u%2Fts-data-schema/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/e22m4u%2Fts-data-schema/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/e22m4u","download_url":"https://codeload.github.com/e22m4u/ts-data-schema/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252308242,"owners_count":21727154,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["data","schema","typescript","validation"],"created_at":"2024-11-13T04:44:06.115Z","updated_at":"2025-05-04T08:32:05.598Z","avatar_url":"https://github.com/e22m4u.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# @e22m4u/ts-data-schema\n\nВалидация данных и приведение типов для TypeScript.\n\n## Содержание\n\n- [Ключевые особенности](#ключевые-особенности)\n- [Схема данных](#схема-данных)\n  - [type](#type)\n  - [items](#items)\n  - [properties](#properties)\n  - [required](#required)\n  - [default](#default)\n  - [validate](#validate)\n- [Пустые значения](#пустые-значения)\n- [Декораторы](#декораторы)\n- [Примеры](#примеры)\n- [Отладка](#отладка)\n- [Тесты](#тесты)\n\n## Ключевые особенности\n- **DataValidator** - Сервис валидации со встроенной проверкой типов.\n- **DataTypeCaster** - Сервис конвертации значений согласно схеме данных.\n- **DefaultValuesApplier** - Сервис заполняющий данные значениями по-умолчанию.\n- Расширяемая архитектура, позволяющая добавлять пользовательские валидаторы и преобразователи типов.\n- Подробная отладка.\n\n## Схема данных\n\n`DataSchema` является объектом, определяющим структуру для валидации\nданных и приведения типов. Схема предоставляет гибкий способ описания\nи ограничения входящих данных. Рассмотрим определение объекта схемы.\n\n```ts\ntype DataSchema = {\n  type: DataType;\n  items?: DataSchema;\n  properties?: {[key: string]: DataSchema};\n  required?: boolean;\n  default?: unknown;\n  validate?: CallableValidator | CallableValidator[];\n};\n```\n\n#### type\n\nОпределяет тип значения с помощью констант указанных ниже.\n\n- `DataType.ANY` - принимает любой тип\n- `DataType.STRING` - строковые значения\n- `DataType.NUMBER` - числовые значения\n- `DataType.BOOLEAN` - логические значения\n- `DataType.ARRAY` - массивы\n- `DataType.OBJECT` - объекты (не экземпляры)\n\n```ts\nimport {DataType} from '@e22m4u/ts-data-schema';\n\nconst schema = {\n  type: DataSchema.STRING,\n}\n```\n\n#### items\n\nИспользуется массивами для определения схемы элементов. Это вложенный\nобъект `DataSchema`, описывающий каждый элемент массива.\n\n```ts\nconst schema = {\n  type: DataSchema.ARRAY,\n  items: {type: DataSchema.STRING},\n}\n```\n\n#### properties\n\nИспользуется объектами для определения схемы свойств. Каждое свойство\nпредставляет собой пару ключ-значение, где значением является вложенный\nобъект `DataSchema`.\n\n```ts\nconst schema = {\n  type: DataSchema.OBJECT,\n  properties: {\n    foo: {type: DataSchema.STRING},\n    bar: {type: DataSchema.NUMBER},\n  },\n}\n```\n\n#### required\n\nПараметр исключает допуск [пустых значений](#пустые-значения) для данной схемы.\n\n```ts\nconst schema = {\n  type: DataSchema.ANY,\n  required: true,\n}\n```\n\n#### default\n\nПараметр определяет значение по умолчанию на случай, если входящее значение\nявляется [пустым](#пустые-значения).\n\n```ts\nconst schema = {\n  type: DataSchema.STRING,\n  default: 'John Doe',\n}\n```\n\n#### validate\n\nПользовательская функция(и) валидации для применения дополнительных\nправил. Может быть одной функцией или массивом функций.\n\n```ts\nconst schema = {\n  type: DataSchema.ANY,\n  validate: (value: unknown) =\u003e {\n    if (typeof value !== 'string')\n      throw new Error('A string required.');\n  },\n}\n```\n\nИспользование нескольких валидаторов.\n\n```ts\nconst schema = {\n  type: DataSchema.ANY,\n  validate: [\n    myValidator1,\n    myValidator2,\n  ],\n}\n```\n\nИспользование аргументов валидатора.\n\n```ts\nimport {DataSchema} from '@e22m4u/ts-data-schema';\n// import {ServiceContainer} from '@e22m4u/js-service';\n\nfunction nonEmptyString(\n  value: unknown,\n  schema: DataSchema,\n  sourcePath?: string,\n  // services: ServiceContainer,\n) {\n  if (!value || typeof value !== 'string') {\n    if (sourcePath)\n      throw new ValidationError(\n        'Value of %v must be a non-empty String, but %v given.',\n        sourcePath,\n        value,\n      );\n    throw new ValidationError(\n      'Value must be a non-empty String, but %v given.',\n      value,\n    );\n  }\n}\n```\n\n## Пустые значения\n\nПроверка наличия полезной нагрузки выполняется встроенным модулем\n[@e22m4u/js-empty-values](https://www.npmjs.com/package/@e22m4u/js-empty-values)\n(не требует установки). Согласно спецификации модуля, разные типы данных\nимеют собственные наборы пустых значений. Эти наборы используются для определения\nналичия полезной нагрузки при проверке обязательных значений или определения\nнеобходимости использования значения по умолчанию.\n\n| константа          | тип         | пустые значения           |\n|--------------------|-------------|---------------------------|\n| `DataType.ANY`     | `'any'`     | `undefined`, `null`       |\n| `DataType.STRING`  | `'string'`  | `undefined`, `null`, `''` |\n| `DataType.NUMBER`  | `'number'`  | `undefined`, `null`, `0`  |\n| `DataType.BOOLEAN` | `'boolean'` | `undefined`, `null`       |\n| `DataType.ARRAY`   | `'array'`   | `undefined`, `null`, `[]` |\n| `DataType.OBJECT`  | `'object'`  | `undefined`, `null`, `{}` |\n\nВ первой колонке указаны константы каждого типа, которые могут быть\nиспользованы вместо строки названия типа (вторая колонка).\n\n## Декораторы\n\nДекораторы предоставляют удобный способ определения схем данных\nс использованием классов.\n\nОбщие декораторы:\n\n- `@dataSchema` - базовый декоратор для определения схемы данных\n- `@dsProperty` - декоратор для определения свойств схемы\n\nДекораторы конкретных типов данных:\n\n- `@dsAny` - для значений любого типа\n- `@dsString` - для строковых значений\n- `@dsNumber` - для числовых значений\n- `@dsBoolean` - для логических значений\n- `@dsArray` - для массивов\n- `@dsObject` - для объектов\n\n#### @dsObject\n\nДекоратор `@dsObject` определяет класс как схему объекта. Он позволяет\nгенерировать объект схемы через утилиту `getDataSchemaFromClass`.\n\n```ts\nimport {dsObject} from '@e22m4u/ts-data-schema';\nimport {getDataSchemaFromClass} from '@e22m4u/ts-data-schema';\n\n@dsObject()\nclass PostSchema {\n  // ...\n}\n\nconst postSchema = getDataSchemaFromClass(PostSchema);\nconsole.log(postSchema);\n// {\n//   \"type\": \"object\",\n//   \"properties\": { ... }\n// }\n```\n\n## Примеры\n\nПроверка простых значений.\n\n```ts\nimport {DataType} from '@e22m4u/ts-data-schema';\nimport {DataValidator} from '@e22m4u/ts-data-schema';\n\nconst validator = new DataValidator();\n\n// определение схемы\nconst schema = {\n  type: DataType.STRING,\n  // дополнительные опции\n};\n\n// валидация значения согласно схеме\nvalidator.validate('John', schema); // вернет undefined\nvalidator.validate(10, schema);     // ошибка ValidationError\n```\n\nПользовательская функция-валидатор.\n\n```ts\nimport {DataType} from '@e22m4u/ts-data-schema';\nimport {DataValidator} from '@e22m4u/ts-data-schema';\nimport {ValidationError} from '@e22m4u/ts-data-schema';\n\nconst validator = new DataValidator();\n\n// определение функции-валидатора\nfunction nonEmptyString(value) {\n  if (!value || typeof value !== 'string')\n    throw new ValidationError('Non-empty string required.');\n}\n\n// определение схемы\nconst schema = {\n  type: DataType.STRING,\n  validate: nonEmptyString, // установка вашего валидатора\n  // validate: [myValidator1, myValidator2, ...],\n};\n\n// проверка значений\nvalidator.validate('John', schema); // вернет undefined\nvalidator.validate('', schema);     // ошибка ValidationError\n```\n\nКонвертация значений согласно схеме.\n\n```ts\nimport {DataType} from '@e22m4u/ts-data-schema';\nimport {DataTypeCaster} from '@e22m4u/ts-data-schema';\n\nconst typeCaster = new DataTypeCaster();\n\n// определение схемы\nconst schema = {\n  type: DataType.NUMBER,\n  // дополнительные опции\n};\n\n// приведение типа согласно схеме,\n// или выброс ошибки TypeCastError\ntypeCaster.cast('10', schema);  // вернет 10 как number\ntypeCaster.cast('foo', schema); // ошибка TypeCastError\n\n// приведение типа согласно схеме,\n// или возврат значения без изменений\ntypeCaster.cast('10', schema, {noTypeCastError: true});  // вернет 10\ntypeCaster.cast('foo', schema, {noTypeCastError: true}); // вернет \"foo\"\n```\n\nПолучить значение по умолчанию согласно указанной схеме, если входящее\nзначение является [пустым](#пустые-значения). В противном случае возвращается\nоригинал без изменений.\n\n```ts\nimport {DataType} from '@e22m4u/ts-data-schema';\nimport {DefaultValuesApplier} from './default-values-applier';\n\nconst defaultsApplier = new DefaultValuesApplier();\n\n// определение схемы\n// числового значения\nconst schema = {\n  type: DataType.NUMBER,\n  default: 10, // \u003c- по умолчанию\n};\n\n// метод `applyDefaultValuesIfNeeded` возвращает\n// значение по умолчанию, если входящее значение\n// является пустым\nconst res1 = defaultsApplier.applyDefaultValuesIfNeeded(5, schema);\nconst res2 = defaultsApplier.applyDefaultValuesIfNeeded(0, schema);\nconst res3 = defaultsApplier.applyDefaultValuesIfNeeded(undefined, schema);\nconsole.log(res1); // 5  (без изменений)\nconsole.log(res2); // 10 (по умолчанию вместо 0)\nconsole.log(res3); // 10 (по умолчанию вместо undefined)\n```\n\nЗаполнение свойств объекта значениями по умолчанию согласно указанной\nсхеме (если свойство имеет [пустое значение](#пустые-значения)).\n\n```ts\nimport {DataType} from '@e22m4u/ts-data-schema';\nimport {DefaultValuesApplier} from './default-values-applier';\n\nconst defaultsApplier = new DefaultValuesApplier();\n\n// определене схемы объекта и значений\n// по умолчанию для каждого свойства\nconst schema = {\n  type: DataType.OBJECT,\n  properties: {\n    foo: {\n      type: DataType.STRING,\n      default: 'myDefaultValue',\n    },\n    bar: {\n      type: DataType.NUMBER,\n      default: 10,\n    },\n  },\n};\n\n// метод `applyDefaultValuesIfNeeded` по необходимости\n// устанавливает стандартные значения для каждого свойства,\n// и возвращает новый объект (не затрагивая оригинал)\nconst res = defaultsApplier.applyDefaultValuesIfNeeded(\n  {foo: null, baz: 'qux'},\n  schema,\n);\nconsole.log(res);\n// {\n//   foo: 'myDefaultValue', \u003c- значение по умолчанию вместо null\n//   bar: 10,               \u003c- значение по умолчанию (не определено)\n//   baz: 'qux'             \u003c- осталось без изменений (новое свойство)\n// }\n```\n\nИспользование декораторов для построения схемы объекта.\n\n```ts\nimport {dsNumber} from '@e22m4u/ts-data-schema';\nimport {dsObject} from '@e22m4u/ts-data-schema';\nimport {dsString} from '@e22m4u/ts-data-schema';\nimport {ClassToPlain} from '@e22m4u/ts-data-schema';\nimport {getDataSchemaFromClass} from '@e22m4u/ts-data-schema';\n\n@dsObject()\nclass AuthorSchema {\n  @dsNumber({required: true})\n  id!: number;\n\n  @dsString({validate: nonEmptyString})\n  name?: string;\n}\n\ntype Author = ClassToPlain\u003cAuthorSchema\u003e;\n// {\n//   id: string,\n//   name?: string | undefined,\n// }\n\nconst authorSchema = getDataSchemaFromClass(AuthorSchema);\nconsole.log(authorSchema);\n// {\n//   type: \"object\",\n//   properties: {\n//     id: {\n//       type: \"number\",\n//       required: true,\n//     },\n//     name: {\n//       type: \"string\",\n//       validate() {...}\n//     },\n//   },\n// }\n```\n\nПостроение схемы вложенных объектов с помощью декораторов.\n\n```ts\nimport {dsNumber} from '@e22m4u/ts-data-schema';\nimport {dsObject} from '@e22m4u/ts-data-schema';\nimport {dsString} from '@e22m4u/ts-data-schema';\nimport {ClassToPlain} from '@e22m4u/ts-data-schema';\nimport {getDataSchemaFromClass} from '@e22m4u/ts-data-schema';\n\n@dsObject()\nclass PostSchema {\n  @dsNumber({required: true})\n  id!: number;\n\n  @dsString({validate: nonEmptyString})\n  title?: string;\n\n  @dsObject(() =\u003e AuthorSchema, {required: true})\n  author!: Author;\n  // AuthorSchema и Author\n  // определены в примере выше\n}\n\ntype Post = ClassToPlain\u003cPostSchema\u003e;\n// {\n//   id: string,\n//   title?: string | undefined,\n//   author: {\n//     id: string,\n//     name?: string | undefined,\n//   }\n// }\n\nconst postSchema = getDataSchemaFromClass(PostSchema);\nconsole.log(postSchema);\n// {\n//   type: \"object\"\n//   properties: {\n//     id: {\n//       type: \"number\",\n//       required: true,\n//     },\n//     title: {\n//       type: \"string\",\n//       validate() {...},\n//     },\n//     author: {\n//       type: \"object\",\n//       required: true,\n//       properties: {\n//         id: {\n//           type: \"number\",\n//           required: true,\n//         },\n//         name: {\n//           type: \"string\",\n//           validate() {...},\n//         },\n//       },\n//     }\n//   }\n// }\n```\n\n## Отладка\n\nУстановка переменной `DEBUG` включает вывод логов.\n\n```bash\nDEBUG=tsDataSchema* npm run test\n```\n\n## Тесты\n\n```bash\nnpm run test\n```\n\n## Лицензия\n\nMIT\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fe22m4u%2Fts-data-schema","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fe22m4u%2Fts-data-schema","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fe22m4u%2Fts-data-schema/lists"}