{"id":25608234,"url":"https://github.com/t2ym/schematic-class","last_synced_at":"2026-02-12T08:32:46.751Z","repository":{"id":278003746,"uuid":"934138441","full_name":"t2ym/schematic-class","owner":"t2ym","description":"JSONClass: Integrated JSON schema for JavaScript classes","archived":false,"fork":false,"pushed_at":"2025-03-06T08:06:27.000Z","size":135,"stargazers_count":0,"open_issues_count":6,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-11-27T10:26:46.023Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/t2ym.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","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":"2025-02-17T10:39:09.000Z","updated_at":"2025-03-13T09:15:20.000Z","dependencies_parsed_at":"2025-04-13T13:03:04.667Z","dependency_job_id":"0af1b9b2-556c-48d4-8858-527d83290600","html_url":"https://github.com/t2ym/schematic-class","commit_stats":null,"previous_names":["t2ym/schematic-class"],"tags_count":18,"template":false,"template_full_name":null,"purl":"pkg:github/t2ym/schematic-class","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/t2ym%2Fschematic-class","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/t2ym%2Fschematic-class/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/t2ym%2Fschematic-class/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/t2ym%2Fschematic-class/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/t2ym","download_url":"https://codeload.github.com/t2ym/schematic-class/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/t2ym%2Fschematic-class/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29361818,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-02-12T01:03:07.613Z","status":"online","status_checked_at":"2026-02-12T02:00:06.911Z","response_time":55,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":[],"created_at":"2025-02-21T20:19:40.061Z","updated_at":"2026-02-12T08:32:46.745Z","avatar_url":"https://github.com/t2ym.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![npm version](https://badge.fury.io/js/schematic-class.svg)](https://badge.fury.io/js/schematic-class)\n\n# `JSONClass` from npm `schematic-class`\n\nIntegrated JSON schema for JavaScript classes\n\n```js\nclass MyClass extends JSONClass {\n  static schema = { // ES2022 syntax\n    name: \"string\",\n    birth_date: \"BirthDay\", // string with format\n    careers: \"Career[]\", // class name as type; array of class objects\n  };\n  getAge() { ... }\n}\nMyClass.register();\n\nclass Career extends JSONClass { }\nCareer.register({ company: \"string\" }); // schema on register()\n\n(class BirthDay extends JSONClass {}).register({ // regex meta-type\n  regex: /^[0-9]{1,2}\\/[0-9]{1,2}\\/[0-9]{4}$/\n});\n\ntry {\n  let o = new MyClass({ // validation on instantiation\n    \"name\": \"John Smith\",\n    \"birth_date\": \"1/1/2001\",\n    \"careers\": [ { \"company\": \"Hello, Inc.\" } ]\n  });\n  o.careers[0] instanceof Career; // type is set\n  o.getAge(); // operation on properties\n  o.validate();\n  JSON.stringify(o); // directly stringifiable\n}\ncatch (e) {\n  if (e instanceof JSONClassError) { ... }\n}\n```\n\n## Table of Contents\n\n- [`JSONClass` from npm `schematic-class`](#jsonclass-from-npm-schematic-class)\n  - [Table of Contents](#table-of-contents)\n  - [Features](#features)\n  - [Install](#install)\n  - [Quick Demo](#quick-demo)\n    - [On Node](#on-node)\n    - [On Browser](#on-browser)\n  - [Import](#import)\n    - [Global JSONClass](#global-jsonclass)\n    - [Scoped JSONClass](#scoped-jsonclass)\n  - [API](#api)\n    - [`JSONClassFactory()` function](#jsonclassfactory-function)\n    - [`JSONClass` class](#jsonclass-class)\n      - [`static initClass(preservePropertyOrder)`](#static-initclasspreservepropertyorder)\n      - [`static register(schema = this.schema, preservePropertyOrder = undefined, conflictingKeys = keysHash(this.prototype))`](#static-registerschema--thisschema-preservepropertyorder--undefined-conflictingkeys--keyshashthisprototype)\n      - [\\[Internal\\] `static create(types, value, jsonPath)`](#internal-static-createtypes-value-jsonpath)\n      - [\\[Internal\\] `static onError(errorParameters)`](#internal-static-onerrorerrorparameters)\n      - [`constructor(initProperties = null, jsonPath = [])`](#constructorinitproperties--null-jsonpath--)\n      - [`validate(jsonPath = [])`](#validatejsonpath--)\n      - [\\[Internal\\] `keys(initProperties, jsonPath)`](#internal-keysinitproperties-jsonpath)\n      - [\\[Internal\\] `iterateProperties(initProperties, jsonPath)`](#internal-iteratepropertiesinitproperties-jsonpath)\n    - [Schema Properties](#schema-properties)\n      - [Enumerable Properties](#enumerable-properties)\n      - [Special Properties](#special-properties)\n    - [Schema Types](#schema-types)\n      - [Primitive Types](#primitive-types)\n      - [Special Types](#special-types)\n      - [Class Types](#class-types)\n      - [Meta-Types](#meta-types)\n      - [Type Operators](#type-operators)\n      - [Type Syntax](#type-syntax)\n      - [Example Types](#example-types)\n  - [Test](#test)\n  - [License](#license)\n\n## Features\n\n- Original JSON schema definitions associated with JavaScript classes\n- Properties and class objects from a JSON parsed object\n- Schema validation\n  - \"throw on the first error\" mode\n  - \"accumulate errors\" mode\n- Optional property order normalization\n- Method definition and invocation for JSON class objects\n- Scope definition for classes for JSON schema\n\n## Install\n```sh\nnpm i schematic-class\n```\n\n## Quick Demo\n\n### On Node\n\n```sh\ncd schematic-class\nnode src/jsonclass.js\n```\n\n### On Browser\n\n1. Copy jsonclass.js from [Gist](https://gist.githubusercontent.com/t2ym/1f31de2cba3a29dcf848452b7b8208be/raw/c7583e97dd77f772fc1fd3e1a2804f8dbbe3c545/jsonclass.js) or [Repo](https://raw.githubusercontent.com/t2ym/schematic-class/refs/heads/main/src/jsonclass.js) to clipboard\n2. Open a browser\n3. Open DevTools on the browser by F12\n4. Open the debugger console in DevTools\n5. Paste `jsonclass.js` content from the clipboard\n\n## Import\n\n### Global JSONClass\n\n```js\nimport { JSONClass, JSONClassError } from 'schematic-class';\n```\n```js\nconst { JSONClass, JSONClassError } = require('schematic-class');\n```\n\n### Scoped JSONClass\n\n```js\nimport { JSONClassFactory, JSONClassError } from 'schematic-class';\nconst JSONClassScope = JSONClassFactory(/* parameters */);\n```\n```js\nconst { JSONClassFactory, JSONClassError } = require('schematic-class');\nconst JSONClassScope = JSONClassFactory(/* parameters */);\n```\n\n## API\n\n### `JSONClassFactory()` function\n\n- Parameters\n  - `preservePropertyOrderDefaultValue = true` : `boolean`: `true` to preserve the order of properties as default\n  - `validateMethodName = 'validate'` : `string`: set a non-conflicting name to customize the name of `validate()` method\n  - `keysGeneratorMethodName = 'keys'` : `string`: set a non-conflicting name to customize the name of `*keys()` generator method\n\n- Return Value\n  - `JSONClass` : `class` : Each scoped `JSONClass` object is unique\n    - Reexport it to share the scoped class among different sources\n\n- Example\n```js\nconst JSONClass = JSONClassFactory(false);\n```\n\n### `JSONClass` class\n\n- The exported `JSONClass` is a singleton object\n  - while classes from `JSONClassFactory()` have different identities on each invocation\n- Scoped `JSONClass` class can be created by either\n  - `JSONClassFactory()` or\n  - `class JSONClassScope extends JSONClass {}` followed by `JSONClassScope.initClass()`\n\n#### `static initClass(preservePropertyOrder)`\n\n- Initialize the registered class inventory\n\n- Parameters\n  - `preservePropertyOrder = preservePropertyOrderDefaultValue`: `boolean`: `true` to preserve the order of properties; `false` to normalize the order as its schema definitions\n\n- Initialized Class Properties\n  - `static inventory = {}`: `object`: inventory of defined types\n    - key: `string`: type name, which is defined by the class name\n    - value: `class`: class for the type\n  - `static parsedTypes = {}`: `object`: types in schema are parsed and stored\n    - key: `string`: schema entry in string\n    - value: `Array`: parsed types in an array\n  - `static preservePropertyOrder`: `boolean` or `undefined`: handed from the parameter\n\n- Return Value\n  - `this` `JSONClass` object\n\n#### `static register(schema = this.schema, preservePropertyOrder = undefined, conflictingKeys = keysHash(this.prototype))`\n\n- Register the schema for the class and customize the `preservePropertyOrder`\n\n- Parameters\n  - `schema = this.schema`: `null-prototype object`: specify the schema for the class; defaults to `this.schema`\n  - `preservePropertyOrder`: `boolean`: customize `preservePropertyOrder` if necessary\n  - `conflictingKeys = keysHash(this.prototype)` : `null-prototype object`: specify a hash object for conflicting key names with `true` values\n    - The default value `keysHash(this.prototype)` contains properties with defined string key names in `Class.prototype` and its prototypes\n      - Typical value: \n```js\n{\n  constructor: true,\n  validate: true,\n  keys: true,\n  iterateProperties: true,\n  __defineGetter__: true,\n  __defineSetter__: true,\n  hasOwnProperty: true,\n  __lookupGetter__: true,\n  __lookupSetter__: true,\n  isPrototypeOf: true,\n  propertyIsEnumerable: true,\n  toString: true,\n  valueOf: true,\n  ['__proto__']: true,\n  toLocaleString: true\n}\n```\n- Initialized Class Properties\n  - `static conflictingKeys`: `null-prototype object`: handed from the parameter\n\n- Example\n```js\n// Schema in register() parameter\nclass MyClass extends JSONClass {\n}\nMyClass.register({\n  property: \"string\"\n});\n\n// Schema in ES2022 class property\nclass MyES2022Class extends JSONClass {\n  static schema = {\n    property: \"string\"\n  }\n}\nMyES2022Class.register();\n\n// Schema in static getter\nclass MyGetterClass extends JSONClass {\n  static get schema() {\n    return {\n      property: \"string\"\n    }\n  }\n}\n// getter is converted to the static property this.schema for performance\nMyGetterClass.register(); \n```\n\n#### [Internal] `static create(types, value, jsonPath)`\n\n- (Currently) internal method to create a typed value\n  - It recursively creates typed values in properties if necessary\n\n- Parameters\n  - `types`: `Array`: an array of candidate types in strings\n  - `value`: `value in a JSON type`: target value to create the typed value\n  - `jsonPath`: `Array`: stack of JSON property names handed by the caller\n\n- Return Value\n  - The typed object value or the primitive value\n\n#### [Internal] `static onError(errorParameters)`\n\n- (Internal) method to throw an `Error` object or accumulate errors in `jsonPath.errors`\n\n- Parameters\n  - `errorParameters`: `object`:\n    - `properties`:\n      - `jsonPath`: `Array`: stack of JSON property names handed by the caller\n      - `type`: `Array` or `string`: (the list of) expected type(s)\n      - `key`: `string`: optional property key\n      - `value`: `any`: the value to validate\n      - `message`: `string`: error message\n        - \"type mismatch\": not (one of) the expected type(s)\n        - \"unregistered type\": unknown type\n        - \"hidden property assignment\": unexpected assignment of a hidden property\n        - \"key mismatch\": not the expected key format\n        - \"invalid key type\": unknown key format type\n        - \"conflicting key\": conflicting key name such as `\"__proto__\"`\n\n#### `constructor(initProperties = null, jsonPath = [])`\n\n- Instantiate a class instance, validating the handed `initProperties` against the schema\n- It can throw `JSONClassError` on the first error when `jsonPath.errors` is not set\n\n- Parameters\n  - `initProperties = null`: `JSON object`: specify the properties for the instance\n    - `null` to initialize the object without initial properties; no validation\n  - `jsonPath = []`: `Array`: optionally set a stack of the current json property paths in strings\n    - `jsonPath.errors`: `Array`: if set as `[]`, errors are accumulated instead of throwing on the first error; the array can be inspected on return to check errors\n    - `jsonPath.recoveryMethod = \"undefined\"`: `string`: if `errors` is set, one of the following recovery methods on errors can be specified\n      - \"value\": preserve the value\n      - \"null\": replace with null\n      - \"undefined\": discard the property; this is the default\n    - `jsonPath.allowHiddenPropertyAssignment`: `boolean`: `true` to allow hidden property assignments; `false` or `undefined` to prohibit hidden property assignments\n\n- Return Value\n  - The typed class instance, whose properties are validated if `jsonPath.errors` is not set or `jsonPath.errors` is empty\n\n- Example\n```js\ntry {\n  let jsonData = JSON.parse(jsonString);\n  let obj = MyClass(jsonData);\n}\ncatch (e) {\n  if (e instanceof JSONClassError) { ... }\n}\n\nlet jsonData = JSON.parse(jsonString);\nlet jsonPath = Object.assign([], { errors: [], recoveryMethod: \"value\" });\nlet obj2 = MyClass(jsonData, jsonPath);\nif (jsonPath.errors.length \u003e 0) {\n  // some errors in validation\n}\n```\n\n#### `validate(jsonPath = [])`\n\n- Validate the `this` object against the schema\n  - Property objects are validated recursively\n  - It can throw on the first error or accumulate errors in `jsonPath.errors`\n- The method name can be customized with `JSONClassFactory()`'s second parameter `validateMethodName` to avoid possible conflict with expected property names to validate\n\n- Parameters\n  - `jsonPath = []`: `Array`: the same as that of the `constructor` parameter\n\n- Return Value\n  - `boolean`: `true` when validated; `false` when not validated\n    - If `jsonPath.errors` is not set, `true` is always returned as a `JSONErrorClass` object is thrown on the first error\n\n- Example\n```js\nlet jsonData = JSON.parse(jsonString);\nlet obj = MyClass(jsonData);\n\ntry {\n  obj.property = \"value\";\n  obj.validate();\n  // validated\n}\ncatch (e) {\n  if (e instanceof JSONClassError) { ... }\n}\n\nlet jsonPath = Object.assign([], { errors: [], recoveryMethod: \"value\" });\nobj.validate(jsonPath);\nif (jsonPath.errors.length \u003e 0) {\n  // some errors in validation\n}\n```\n\n#### [Internal] `keys(initProperties, jsonPath)`\n\n- Internal method to generate property keys for `interateProperties()`\n  - The order of generated keys is controlled by `preservePropertyOrder` class property\n- The method name can be customized with `JSONClassFactory()`'s third parameter `keysGeneratorMethodName` to avoid possible conflict with expected property names to validate\n\n- Parameters\n  - `initProperties`: `object`: the target value object to validate\n  - `initPropertiesKeys`: `Array`: the list of `initProperties` keys\n  - `jsonPath = []`: `Array`: the same as that of the `constructor` parameter\n\n- Return Value\n  - `Array`: list of keys in `string`\n\n#### [Internal] `iterateProperties(initProperties, jsonPath)`\n\n- Internal method to iterate over properties to validate and assign them\n  - Called from `constructor()`\n\n- Parameters\n  - `initProperties`: `object`: the target value object to validate\n  - `jsonPath = []`: `Array`: the same as that of the `constructor` parameter\n\n\n### Schema Properties\n\n#### Enumerable Properties\n- `any_valid_property_name`: enumerable property\n\n#### Special Properties\n- `any_valid_property_name`: hidden property\n  - Marked with `\"-\"` special type\n- `\"+\"`: additional property\n- `\"regex\"`: regex property\n  - Used in a meta-type to specify a regex pattern in the value\n- `validator(value)`: validator function\n  - Used in a meta-type to specify a callback function to validate the value\n  - Copied to `Class.validator`\n    - `this` in the function is the class, not the schema\n- `detector(value)`: detector function\n  - Used in a meta-type to specify a callback function to detect the value type\n  - Copied to `Class.detector`\n    - `this` in the function is the class, not the schema\n\n### Schema Types\n\n#### Primitive Types\n- `\"string\"`: string type\n- `\"number\"`: number type\n- `\"integer\"`: integer type\n- `\"boolean\"`: boolean type\n- `\"null\"`: null value\n- `\"object\"`: object type\n  - Usage is strongly discouraged as it just copies the reference to the value without validation\n\n#### Special Types\n- `\"undefined\"`: optional property\n  - Used with other type(s) to specify the valid type(s)\n  - For example, `\"undefined|string\"` is for an optional string property\n- `\"-\"`: hidden property\n  - Hidden properties are defined as `enumerable: false` and do not appear in `JSON.stringify()`\n- `RegExp` literal object\n  - Sepecify a regex pattern for a string property in `regex` special property\n\n#### Class Types\n- `AnyClassName`: class with schema\n  - Extends the base `JSONClass` (or a customized base class)\n\n#### Meta-Types\n- `AnyClassName`: meta-type name\n  - Extends the base `JSONClass` (or a customized base class)\n  - Has one of the following special properties in schema\n    - `\"regex\"`: regex pattern validation\n    - `validator(value)`: validator callback\n    - `detector(value)`: detector callback\n\n#### Type Operators\n- `|`: or operator\n  - Joins multiple types to check over the types in the joined order\n- `[]`: array operator\n  - Used as a postfix\n  - Specifies an `Array` value\n- `(` ... `)`: parentheses operator\n  - `|` operator between `(` and `)` has higher precedence\n    - The right parenthesis is preceded by `[]`\n      - The effect of `[]` operator is limited within the surrounding parentheses\n      - The resolved type can be an array or a non-array (TypedObject or a primitive value)\n    - Only 1 depth of parentheses is supported\n  - Examples:\n    - `(string|integer[])|Type`\n    - `TypeDetector|null|(string|TypeValidator[])`\n\n#### Type Syntax\n- No extra spaces are permitted\n- Zero or one array `[]` operator is permitted\n  - `|` operator has higher precedence than `[]` operator unless surrounded by `(` `)`\n    - If the type ends with `[]`, that means an array of all the preceding types joined by `|`\n    - `type1|...|typeN[]` - an array of items whose types are `type1`, ..., or `typeN`\n- Parentheses `(` `)` are always used for an array `[]`\n  - `(type1|...|typeN[])`\n  - `(type[])`\n\n#### Example Types\n\n- Primitive Types\n```js\nclass TypeWithPrimitives extends JSONClass {\n  static schema = {\n    string_property: \"string\",\n    number_proerpty: \"number\",\n    integer_property: \"integer\",\n    boolean_property: \"boolean\",\n    null_property: \"null\",\n    object_property: \"object\", // highly discouraged\n    \"+\": \"undefined\", // optional properties are not permitted\n  };\n}\nTypeWithPrimitives.register();\n```\n\n- Class Object Types\n```js\nclass TypeName extends JSONClass {\n  static schema = { ... };\n}\nTypeName.register();\n\nclass TypeWithObjects extends JSONClass {\n  static schema = {\n    typed_object: \"TypeName\",\n    array_property: \"TypeName[]\"\n    nullable_property: \"null|TypeName\",\n    optional_string_property: \"undefined|string\",\n    mixed_array_property: \"string|number|TypeName[]\",\n  };\n}\nTypeWithObjects.register();\n```\n\n- Meta-Types\n```js\nclass RegexFormat extends JSONClass {\n  static schema = {\n    regex: /^pattern:/\n  };\n}\nRegexFormat.register();\n\nclass NonNegativeInteger extends JSONClass {\n  static schema = {\n    validator(value) { return Number.isInteger(value) \u0026\u0026 value \u003e= 0; }\n  };\n}\nNonNegativeInteger.register();\n\nclass FormattedKeysObject extends JSONClass {\n  static schema = {\n    RegexFormat: \"TypeName\",\n  };\n}\nFormattedKeysObject.register();\n\nclass ConstrainedValueObject extends JSONClass {\n  static schema = {\n    formatted_property: \"RegexFormat\",\n    non_negative_integer: \"NonNegativeInteger\",\n  };\n}\nConstrainedValueObject.register();\n```\n\n- Variable Type Detector\n```js\n// base class\nclass BaseClass extends JSONClass {\n  static schema = {\n    type: \"string\"\n  };\n}\n// validators\nclass TypeAName extends JSONClass {\n  static schema = {\n    validator(value) { return value === \"A\"; }\n  };\n}\nclass TypeBName extends JSONClass {\n  static schema = {\n    validator(value) { return value === \"B\"; }\n  };\n}\n// derived classes\nclass TypeA extends BaseClass {\n  static schema = {\n    type: \"TypeAName\"\n    number: \"number\"\n  };\n}\nclass TypeB extends BaseClass {\n  static schema = {\n    type: \"TypeBName\"\n    string: \"string\"\n  };\n}\n// detector meta-type\nclass DerivedClassDetector extends JSONClass {\n  static schema = {\n    // any properties of any values can be used to distinguish types\n    // falsy value to report no matching type is found\n    detector(value) { return { \"A\": \"TypeA\", \"B\": \"TypeB\" }[value]; }\n  };\n}\nDerivedClassDetector.register();\n\nclass VariableTypeValueClass extends JSONClass {\n  static schema = {\n    variable_type: \"DerivedClassDetector\"\n  };\n}\nVariableTypeValueClass.register();\n\n// instantiation and validation\nlet obj = new VariableTypeValueClass({ variable_type: { type: \"A\", number: 1 } });\nobj.variable_type instanceof TypeA === true;\nobj.variable_type.type === \"A\";\n```\n\n- Hidden Properties\n```js\nclass TypeWithHiddenProperties extends JSONClass {\n  static schema = {\n    hidden_property: \"-\", // not visible in JSON.stingify()\n    hidden_property2: \"-\", // not visible in JSON.stingify()\n    string_property: \"string\",\n  };\n}\nTypeWithHiddenProperties.register();\n\nlet obj = new TypeWithHiddenProperties({ string_property: \"str\" });\nlet errorObj = new TypeWithHiddenProperties({\n    hidden_property: \"hidden value\",\n    string_property: \"str\"\n  }); // throws JSONClassError\n\nlet jsonPath = Object.assign([], { allowHiddenPropertyAssignment: true });\nlet obj2 = new TypeWithHiddenProperties({\n    hidden_property: \"hidden value\",\n    string_property: \"str\"\n  }, jsonPath); // allowed\nobj2.hidden_property2 = \"hidden value 2\";\nobj2.hidden_property === \"hidden value\";\nJSON.stringify(obj2) === `{\"string_property\":\"str\"}`;\n```\n\n- Recursive Object with Array\n```js\n(class ConditionOrState extends JSONClass {}).register({\n  regex: /^[a-zA-Z0-9_]+(:[a-zA-Z0-9_ ]+)?$/\n});\n\n(class TargetState extends JSONClass {}).register({\n  regex: /^[a-zA-Z0-9_]+$/\n});\n\nclass StateTransition extends JSONClass {\n  static schema = {\n    ConditionOrState: \"TargetState[]|StateTransition\"\n  };\n}\nStateTransition.register();\n\nnew StateTransition({\n  \"prop1:OK\": {\n    \"prop2:Rejected\": {\n      \"StateA\": [ \"StateB\", \"StateC\" ],\n      \"StateB\": [ \"StateC\" ],\n      \"default\": [ \"StateA\" ],\n    },\n    \"prop2:Accepted\": {\n      \"StateA\": [ \"StateC\" ],\n      \"default\": [ \"StateA\" ]\n    },\n    \"default\": [ \"StateY\" ]\n  },\n  \"default\": [ \"StateX\" ]\n});\n```\n\n## Test\n\n```sh\ngit clone https://github.com/t2ym/schematic-class\ncd schematic-class\nnpm i\nnpm test\ngoogle-chrome test/coverage/index.html\n```\n\n## License\n\n[BSD-2-Clause](LICENSE.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ft2ym%2Fschematic-class","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ft2ym%2Fschematic-class","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ft2ym%2Fschematic-class/lists"}