# README.md — Usage Guide

## Import

```js
import SchemaEngine, { Validation, Semantic, diagnostics } from 'schema-engine/v3';
````

也可只用 default：

```js
import SchemaEngine from 'schema-engine/v3';

const { Validation, Semantic, diagnostics } = SchemaEngine;
```

---

## Validation


### types
```js
/**  
 * @typedef {'silent'|'warn'|'error'} UnknownKeyReportLevel  
 * @typedef {'silent'|'warn'|'error'} UnknownTokenPolicy  
 *  
 * @typedef {Object} SchemaValidatorOptions  
 *  
 * @property {boolean} [trackDiscarded=true]  
 * 是否追蹤被丟棄的鍵（例如未知鍵或被過濾欄位），  
 * 若為 true，validate 結果中會包含 discardedKeys。  
 *  
 * @property {boolean} [allowUnknownKeys=false]  
 * 是否允許 object 出現未在 schema 中宣告的鍵。  
 * 預設為 false（嚴格模式）。  
 *  
 * @property {UnknownKeyReportLevel} [reportUnknownKeys='silent']  
 * 當出現未知鍵時的處理等級：  
 * - 'silent'：忽略，不回報  
 * - 'warn'：加入 diagnostics 警告  
 * - 'error'：視為驗證錯誤  
 *  
 * @property {UnknownTokenPolicy} [unknownTokenPolicy='error']  
 * 當 rules 字串中出現未知 token 時的處理策略：  
 * - 'silent'：忽略  
 * - 'warn'：加入 diagnostics 警告  
 * - 'error'：直接視為 schema 錯誤  
 *  
 * @property {boolean} [debugSchema=false]  
 * 是否開啟 schema debug 模式，  
 * 用於輸出 ruleNodes、flatRules 或中間轉換資訊。  
 */  
  
  
/**  
 * @typedef {Object} SchemaValidationResult  
 *  
 * @property {boolean} valid  
 * 是否驗證通過（errors 為空時為 true）。  
 *  
 * @property {{ [flatPath: string]: string[] }} errors  
 * 驗證錯誤集合。  
 * key 為 flatPath（例如 "user.name"、"arr.0.foo"），  
 * value 為該欄位對應的錯誤訊息陣列。  
 *  
 * @property {{ [key: string]: any }} diagnostics  
 * 非致命診斷資訊集合（例如 warn 類型訊息）。  
 * 結構依實作而定，可能包含 unknownKeys、unknownTokens 等資訊。  
 *  
 * @property {any} values  
 * 經過 type 轉換與 default 處理後的最終值物件。  
 *  
 * @property {string[]} discarded  
 * 被丟棄的欄位清單（例如未知鍵或在 strict 模式下被過濾的鍵）。  
 */  
  
  
/**  
 * @typedef {Object} SchemaValidator  
 *  
 * @property {(data: any) => SchemaValidationResult } validate  
 * 執行資料驗證，回傳驗證結果。  
 *  
 * @property {() => any} getCtx  
 * 取得當前 validator 內部 context（包含 flatRules、ruleNodes、meta 等）。  
 *  
 * @property {(typeName: string) => (fn: (value: any) => any) => void} useType  
 * 註冊自訂 type plugin。  
 * 傳入 type 名稱後，回傳一個函式用於注入型別驗證邏輯。  
 */
```

#### createSchemaValidator

```js
const schema = {
  profile: {
    name: { rules: 'type:StrictString|minLength:2' },
    age: { rules: 'type:StrictNumber|int|min:0' },
  },
};

const validator = Validation.createSchemaValidator(schema,{options, plugins});

const res = validator.validate({
  profile: { name: 'Joe', age: 18 },
});
```

- array
```js
// extensions pattern schema（外層,固定結構，不管 value 內容）
const extensionsPatternSchema = {
  rules: 'type:strictObject',
  properties: {
    extensions: {
      rules: 'type:strictArray',
      items: {
        rules: 'type:strictObject',
        properties: {
          key: { rules: 'type:nonEmptyString|required' },
          ver: { rules: 'type:strictNumber|int|required|minValue:1' },
          value: { rules: 'type:strictObject|required' },
        },
      },
    },
  },
};

// const someValue = {
//   extensions: [
//     { key: 'ext1', ver: 1, value: { foo: 'bar' } },
//     { key: 'ext2', ver: 2, value: { baz: 'qux' } },
//   ],
```


#### createFlatSchemaValidator

Flat schema（rule map）範例：

```js
const flatSchema = {
  name: 'type:StrictString|minLength:2',
  age: 'type:StrictNumber|int|min:0',
};

const validator = Validation.createFlatSchemaValidator({  flatSchema options,plugins});

const res = validator.validate({
  name: 'Joe',
  age: 18,
});
```

#### createValueValidator

```js
const valueSpec = { rules: 'type:StrictNumber|int|min:0|max:100' };

const v = Validation.createValueValidator({ rules:valueSpec.rules, options, plugins });

v.validate(10);
v.validate(-1);
```

---

### Schema Examples
- oneOf / anyOf
```js

const schemaOneOf = {  
  rules: 'type:strictObject',  
  properties: {  
    value: {  
      oneOf: [  
        { rules: 'type:looseNumber|int' },  
        { rules: 'type:strictString' },  
      ],  
    },  
  },  
};

const schemaAnyOf = {  
  rules: 'type:strictObject',  
  properties: {  
    value: {  
      anyOf: [  
        { rules: 'type:looseNumber|int' },  
        { rules: 'type:strictString' },  
      ],  
    },  
  },  
};
```




## Semantic

### Semantic.checker

Boolean quick check：

```js
const { checker } = Semantic;

checker.is('EmailString', 'a@b.com');
checker.is('EmailString')('a@b.com');
```

Full CheckResult：

```js
checker.check('EmailString', 'bad-email');
checker.check('EmailString')('bad-email');
```

Existence：

```js
checker.has('EmailString');
```

### Semantic.registry

Get checker fn：

```js
const fn = Semantic.registry.getTypeChecker('EmailString');
// fn({ value }) -> CheckResult
```

List types：

```js
const list = Semantic.registry.getTypeList();
```

---

## diagnostics

### diagnostics.health.valueSpecHealthCheck

```js
const vs = { rules: 'type:StrictNumber|int|min:0|max:100' };

const report = diagnostics.health.valueSpecHealthCheck(vs);
```
