Schema

// @namespace Schema
import { Schema } from 'rcfm'

Custom Types

@typedef {Object} SchemaInstance
@description - DSL 解析器实例

Class Methods

.create()

创建一个 DSL 解析器实例。

// Schema.create(options)
// @param {Object} [options = {}]
// @prop {Function} [options.parseExpression] - 自定义布尔表达式运算函数,应返回布尔值。
// 当不设定时,使用默认求值逻辑,即只有当表达式结果为 true 时为真,否则为假。
// @prop {Function} [options.parseReference] - 自定义 Interpolation 解析函数,应返回解析结果。
// 当不设定时,所有 Interpolation 的解析结果均为 undefined。
// @returns {SchemaInstance}

// @example - 创建实例
const schema = Schema.create({
  parseReference (ref) {
    const students = [
      {name: 'Jerry', score: 69}, {name: 'Laura', score: 79},
      {name: 'James', score: 70}, {name: 'Tomas', score: 80}
    ]
    // 自定义 Interpolation 引用路径分割符号
    const [name, prop] = ref.split(".")
    // 自定义 Interpolation 引用路径解析逻辑
    const student = students.find((s) => s.name === name)
    return student ? student[prop] : undefined
  },
  parseExpression (exp) {
    // 自定义布尔表达式语法
    const matched = exp.match(/(\d+)\s+(.+)\s+(\d+)/)
    if (!matched) { return false }
    let [statement, scoreA, keyword, scoreB] = matched
    // 自定义布尔表达式运算逻辑
    if (keyword === 'was higher than') {
      return parseFloat(scoreA) > parseFloat(scoreB)
    } else if (keyword === 'was less than') {
      return parseFloat(scoreA) < parseFloat(scoreB)
    } else {
      throw new Error(`Unsupported keyword "${keyword}".`)
    }
  }
})

// @example - 解析 DSL
// returns - "Boys won!"
schema.parse([
  {
    when: [
      "<< Jerry.score >> was higher than << James.score >>",
      {and: "<< Laura.score >> was higher than << Tomas.score >>"}
    ],
    then: "Girls won!"
  },
  {
    when: [
      "<< James.score >> was higher than << Jerry.score >>",
      {and: "<< Tomas.score >> was higher than << Laura.score >>"}
    ],
    then: "Boys won!"
  },
  {
    else: "The two teams drew."
  }
])

Instance Methods

#parse()

解析 DSL。

// schema#parse(statement)
// @param {*} statement - 待解析的 DSL,也可以是任意数据。
// 如 statment 包含 DSL,则解析结果中 DSL 部分会被其解析结果替换。
// @returns {*} - 返回解析结果

// @example - 创建实例
const schema = Schema.create({
  parseReference (ref) {
    const students = [
      {name: 'Jerry', score: 69}, {name: 'Laura', score: 79},
      {name: 'James', score: 70}, {name: 'Tomas', score: 80}
    ]
    // 自定义 Interpolation 引用路径分割符号
    const [name, prop] = ref.split(".")
    // 自定义 Interpolation 引用路径解析逻辑
    const student = students.find((s) => s.name === name)
    return student ? student[prop] : undefined
  },
  parseExpression (exp) {
    // 自定义布尔表达式语法
    const matched = exp.match(/(\d+)\s+(.+)\s+(\d+)/)
    if (!matched) { return false }
    let [statement, scoreA, keyword, scoreB] = matched
    // 自定义布尔表达式运算逻辑
    if (keyword === 'was higher than') {
      return parseFloat(scoreA) > parseFloat(scoreB)
    } else if (keyword === 'was less than') {
      return parseFloat(scoreA) < parseFloat(scoreB)
    } else {
      throw new Error(`Unsupported keyword "${keyword}".`)
    }
  }
})

// @example - 解析 DSL
// returns - "Boys won!"
schema.parse([
  {
    when: [
      "<< Jerry.score >> was higher than << James.score >>",
      {and: "<< Laura.score >> was higher than << Tomas.score >>"}
    ],
    then: "Girls won!"
  },
  {
    when: [
      "<< James.score >> was higher than << Jerry.score >>",
      {and: "<< Tomas.score >> was higher than << Laura.score >>"}
    ],
    then: "Boys won!"
  },
  {
    else: "The two teams drew."
  }
])

#possibilities()

返回 DSL 各分支结果组成的数组。

// schema#possibilities(statement)
// @param {*} statement - ConditionStatement,也可以是任意数据
// @returns {null | Array} - 当 statement 包含 ConditionStatement 时返回数组,否则返回 null。

// @example - 获取条件分支结果
// returns - ["Girls won!", "Boys won!", "The two teams drew."]
schema.possibilities([
  100, true, false, 'hello',
  {
    when: [
      "<< Jerry.score >> was higher than << James.score >>",
      {and: "<< Laura.score >> was higher than << Tomas.score >>"}
    ],
    then: "Girls won!"
  },
  {
    when: [
      "<< James.score >> was higher than << Jerry.score >>",
      {and: "<< Tomas.score >> was higher than << Laura.score >>"}
    ],
    then: "Boys won!"
  },
  {
    else: "The two teams drew."
  }
])

// @example - 对不包含 ConditionStatement 的数据调用
// returns - null
schema.possibilities([
  100, true, false, 'hello', {name: 'jim'}, [1, 2, 3]
])

#references()

搜集 DSL 中的 Interpolation 引用路径。

// schema#references(statement, options)
// @param {*} statement
// @param {Object} [options = {}]
// @prop {boolean} [options.unique = true] - 是否过滤掉重复的路径
// @returns {Array | null}

// @example
// returns ['name', 'age', 'gender', 'address', 'hobby']
schema.references([
  {prop: 1}, {prop: true},
  {prop: {prop: [{prop: '<< name >>'}, '<< age >><< name >>']}},
  ['<< gender >>', {prop: [{prop: [{prop: '<< address >><<age>>'}]}]}],
  '<< hobby >>'
])

// @example
// returns ['name', 'age', 'name', 'gender', 'address', 'age', 'hobby']
schema.references([
  {prop: 1}, {prop: true},
  {prop: {prop: [{prop: '<< name >>'}, '<< age >><< name >>']}},
  ['<< gender >>', {prop: [{prop: [{prop: '<< address >><<age>>'}]}]}],
  '<< hobby >>'
], {unique: false})

#replace()

替换 DSL 中的 Interpolation 引用路径。

// schema#replace(statement, pairs)
// @param {*} statement
// @param {Object} pairs - 以旧引用路径为 key,新引用路径为 value 构成的对象
// @returns {*}

// @example
// returns -
// [
//   {prop: 1}, {prop: true},
//   {prop: {prop: [{prop: '<< username >>'}, '<< age >><< username >>']}},
//   ['<< gender >>', {prop: [{prop: [{prop: '<< location >><<age>>'}]}]}],
//   '<< hobby >>', 1, true, false
// ]
schema.replace([
  {prop: 1}, {prop: true},
  {prop: {prop: [{prop: '<< name >>'}, '<< age >><< name >>']}},
  ['<< gender >>', {prop: [{prop: [{prop: '<< address >><<age>>'}]}]}],
  '<< hobby >>', 1, true, false
], {name: 'username', address: 'location'})