# 🧱 Value Spec and Semantic Types

---

## 📌 ValueSpec（值語意規格）

```
ValueSpec = 定義某個「值」在特定情境下可呈現的語意空間

Type        → 此值採用哪些 Semantic Types（可為 scalar 或 composite）
Constraint  → 限制此值在語意上允許的內容形式（僅針對值本身，而非結構關係）
Modifier    → 控制值的存在行為（required / nullable / default）
```

```mermaid
flowchart LR
    ST["Semantic Type<br/>（值的語意原子）"]
    CT["Constraint<br/>（值域／格式限制）"]
    MD["Modifier<br/>（存在狀態修飾）"]
    ST --> VS["ValueSpec<br/>值的語意空間"]
    CT --> VS
    MD --> VS
```

### 要點

```
ValueSpec 可描述任何「值」──無論是單值（StrictNumber / UUIDString）
或複合值（StrictArray / StrictObject），皆可使用相同模型。
```

---

## Types

### Core Value Types（核心值型別）

| Code | Type Name      | Accept Input                  | Canonical | Purpose                                |
|------|----------------|-------------------------------|-----------|----------------------------------------|
| CV0  | any            | 任意值                           | any       | 最寬鬆的型別，接受任何輸入，不做轉換或限制，適用於無特定語意需求的欄位    |
| CV1  | StrictNumber   | number only                   | number    | 僅接受已為數值的輸入，不做字串轉換，適用精確運算與嚴格數字語意        |
| CV2  | LooseNumber    | number / numeric-like string  | number    | 接受 `'123'` 等可解析為數字的來源，統一轉為數字語意         |
| CV3  | StrictString   | string only                   | string    | 僅接受字串，不執行型別轉換，適用純文字輸入與字面語意             |
| CV4  | LooseString    | string/number/boolean         | string    | 吸收多種來源並轉為字串語意，用於彈性文字輸入或識別符用途           |
| CV5  | StrictBool     | true / false                  | boolean   | 僅接受布林值來源，不接受 `'true'` 等字串形式，適用邏輯語意明確場景 |
| CV6  | LooseBool      | true/false/0/1/'true'/'false' | boolean   | 接受多種可判定真假之來源，轉為布林語意，用於外部輸入與寬鬆布林處理      |
| CV7  | StrictFunction | function                      | function  | 僅接受函式作為值，表示「此值可被呼叫」，不具字串/數字語意          |

---

### Core Structural Types（容器型別）

| Code | Type Name    | Accept Input | Canonical | Purpose                                                                       |
|------|--------------|--------------|-----------|-------------------------------------------------------------------------------|
| CS1  | StrictObject | plain object | object    | 僅接受 **plain object** 作為值：必須是一般物件、不可為 `null`、不可為 array；保留鍵值結構語意（以「物件容器」為語意單位）。 |
| CS2  | StrictArray  | array        | array     | 僅接受 **array** 作為值；保留有序集合與項目序列語意（以「陣列容器」為語意單位）。                                |

---

### Semantic Types（常用語意型別）

#### C2. Temporal Types（時間語意型別）

| Code | Type Name         | Base  | Format / Meaning | Purpose / Usage         |
|------|-------------------|-------|------------------|-------------------------|
| T1   | DateTimeString    | CV3   | 一般 datetime      | 非特定格式之日期時間表示，用於 UI 常見場景 |
| T2   | ISODateTimeString | CV3   | ISO8601          | 標準化跨系統交換使用之日期時間格式       |
| T3   | DateYMDString     | CV3   | YYYY-MM-DD       | 僅日期語意，用於生日、排程、日期欄位      |
| T4   | TwDateYMDString   | CV3   | 民國年月日格式          | 台灣地區常用日期語意              |
| T5   | UnixTimestampMs   | CV1/2 | number(ms)       | 毫秒級時間戳，用於前端與計時精準需要      |
| T6   | UnixTimestampSec  | CV1/2 | number(sec)      | 秒級時間戳，用於跨語言／跨服務傳遞       |

---

#### C6. Common String Semantic Types（常用字串語意型別）

> 本章節收錄 **常用字串語意型別**，用於在 API / Domain / UI 表單中以「可讀、可溝通」的名稱表達字串格式語意。

| Code | Type Name       | Base | Conceptual Rule Form              | Meaning / Constraint        | Purpose / Usage                      |
|------|-----------------|------|-----------------------------------|-----------------------------|--------------------------------------|
| S3   | SlugString      | CV3  | `{strictString\|pattern:slug}`    | URL slug 樣式（通常為小寫英數與 `-`）   | SEO、路由、資源代號、URL path segment         |
| S4   | AlphaString     | CV3  | `{strictString\|pattern:alpha}`   | 僅英文字母（A–Z / a–z）            | 代號、縮寫、初始字母等純字母欄位                     |
| S5   | AlphaNumString  | CV4  | `{looseString\|pattern:alphanum}` | 僅英數字（A–Z / a–z / 0–9）       | ID、代碼類欄位；吸收 number/boolean 等外部輸入後再驗證 |
| M1   | EmailString     | CV3  | `{strictString\|pattern:email}`   | email 格式                    | 聯絡資訊、帳號識別、通知收件者                      |
| M2   | UrlString       | CV3  | `{strictString\|pattern:url}`     | 合法 URL（含 protocol）          | 外部連結、API endpoint、登入跳轉               |
| M3   | DomainString    | CV3  | `{strictString\|pattern:domain}`  | 合法 domain（不含 protocol/path） | DNS、網站、租戶域名識別                        |
| M4   | PhoneString     | CV3  | `{strictString\|pattern:phone}`   | 電話格式（可含區碼/分隔符）              | 聯絡資訊、客服欄位                            |
| M5   | Base64String    | CV3  | `{strictString\|pattern:base64}`  | base64 格式                   | 圖片/憑證/資料封裝、安全字串輸送                    |
| M6   | CsvString       | CV3  | `{strictString\|pattern:csv}`     | 逗號分隔字串（CSV-like）            | 批次欄位、ID 列表、匯入工具                      |
| M7   | ColorCodeString | CV3  | `{strictString\|pattern:color}`   | `#RRGGBB` / CSS 色碼          | UI 設計系統、品牌顏色、主題模式                    |

**補充說明（規格層）**

* `Conceptual Rule Form` 為「概念性展開」，用於快速閱讀與對齊 `{base|constraints}` 模型；實作可用 dedicated checker 或由 registry 展開成 pipeline。
* 若某些型別希望同時提供 strict/loose 兩種吸收策略，應以不同命名或明確標註 base（例如 `AlphaNumString` 使用 `LooseString` 作為 base，以符合外部輸入常見情境）。

---

### Domain / App-level Semantic Types（領域語意型別）

> **Domain Types** 不屬於 Core，也**不保證跨領域通用性**，它們只在特定業務 context 下有意義。  
> 它們通常由企業或應用程式自行維護 registry。

#### Taiwan-specific Types

| Code | Semantic Type                  | Base | Meaning / Usage            |
|------|--------------------------------|------|----------------------------|
| TW1  | LineIdString                   | CV3  | LINE 使用者識別 ID，用於綁定 LINE 帳號 |
| TW2  | TwTaxIdString                  | CV3  | 統一編號（臺灣企業法定識別碼）            |
| TW3  | TwMobilePhoneString            | CV3  | 手機號碼（台灣格式）                 |
| TW4  | TwLandPhoneString              | CV3  | 市話（台灣格式）                   |
| TW5  | TwNationalIdString             | CV3  | 身分證字號                      |
| TW6  | TwInvoiceDonationOrgCodeString | CV3  | 發票捐贈碼                      |
| TW7  | TwMobileInvoiceBarcodeString   | CV3  | 電子發票手機條碼                   |

#### Payment / Finance Types

| Code | Semantic Type          | Base | Meaning / Usage    |
|------|------------------------|------|--------------------|
| PAY1 | CreditCardNumberString | CV3  | 信用卡卡號              |
| PAY2 | CreditCardCvvCvcString | CV3  | 授權安全碼（背面三碼）        |
| PAY3 | CreditCardExpiryString | CV3  | 信用卡有效年月（MM/YY 等格式） |

#### Other App-level Types

| Code | Semantic Type          | Base | Meaning / Usage         |
|------|------------------------|------|-------------------------|
| APP1 | HostnameString         | CV3  | 網域名稱（不含路徑）              |
| APP2 | HostnameWithPathString | CV3  | 網域＋路徑，用於 API / redirect |

---

## Constraint（值域）

### 數字類 Constraints（Number Constraints）

| Constraint Name | Rule String 形式       | 適用 Core Type                         | 語意說明                                                              | 範例                                |
|-----------------|----------------------|--------------------------------------|-------------------------------------------------------------------|-----------------------------------|
| `int`           | `int`                | StrictNumber(CV1) / LooseNumber(CV2) | 值必須為整數（`value % 1 === 0`）                                         | `type:strictNumber\|int`          |
| `gt`            | `gt:<value>`         | StrictNumber(CV1) / LooseNumber(CV2) | `value > <value>`                                                 | `type:strictNumber\|gt:0`         |
| `gte`           | `gte:<value>`        | StrictNumber(CV1) / LooseNumber(CV2) | `value >= <value>`                                                | `type:looseNumber\|gte:10`        |
| `lt`            | `lt:<value>`         | StrictNumber(CV1) / LooseNumber(CV2) | `value < <value>`                                                 | `type:strictNumber\|lt:100`       |
| `lte`           | `lte:<value>`        | StrictNumber(CV1) / LooseNumber(CV2) | `value <= <value>`                                                | `type:looseNumber\|lte:99`        |
| `min`           | `min:<value>`        | StrictNumber(CV1) / LooseNumber(CV2) | `value >= <value>`（常用在邊界檢查）                                       | `type:strictNumber\|min:1`        |
| `max`           | `max:<value>`        | StrictNumber(CV1) / LooseNumber(CV2) | `value <= <value>`（常用在邊界檢查）                                       | `type:strictNumber\|max:100`      |
| `nonNegative`   | `nonNegative`        | StrictNumber(CV1) / LooseNumber(CV2) | `value >= 0`（不含負數）                                                | `type:looseNumber\|nonNegative`   |
| `positive`      | `positive`           | StrictNumber(CV1) / LooseNumber(CV2) | `value > 0`（不含零）                                                  | `type:strictNumber\|positive`     |
| `multipleOf`    | `multipleOf:<value>` | StrictNumber(CV1) / LooseNumber(CV2) | `value` 必須為 `<value>` 的倍數                                         | `type:strictNumber\|multipleOf:5` |
| `scale`         | `scale:<digits>`     | StrictNumber(CV1) / LooseNumber(CV2) | 限制允許的小數位數（常與 `multipleOf` 搭配）                                     | `type:looseNumber\|scale:2`       |
| `finite`        | `finite`             | StrictNumber(CV1)                    | 排除 `Infinity` / `-Infinity` / `NaN` <br>僅適用於 **canonical number** | `type:strictNumber\|finite`       |

---

### 字串類 Constraints（String Constraints）

| Constraint Name | Rule String 形式           | 適用 Core Type                         | 語意說明                                                                                                                                                         | 範例                                         |
|-----------------|--------------------------|--------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------|
| `minLength`     | `minLength:<n>`          | StrictString(CV3) / LooseString(CV4) | 字串長度必須 ≥ `<n>`                                                                                                                                               | `type:strictString\|minLength:1`           |
| `maxLength`     | `maxLength:<n>`          | StrictString(CV3) / LooseString(CV4) | 字串長度必須 ≤ `<n>`                                                                                                                                               | `type:strictString\|maxLength:20`          |
| `length`        | `length:<n>`             | StrictString(CV3) / LooseString(CV4) | 字串長度必須等於 `<n>`                                                                                                                                               | `type:strictString\|length:10`             |
| `trim`          | `trim`                   | StrictString(CV3) / LooseString(CV4) | 驗證前先做 `trim()`，用於移除前後空白以保證語意一致性                                                                                                                              | `type:strictString\|trim\|minLength:1`     |
| `lowercase`     | `lowercase`              | StrictString(CV3) / LooseString(CV4) | 內容必須為全小寫，可強制轉換或檢查                                                                                                                                            | `type:strictString\|lowercase`             |
| `uppercase`     | `uppercase`              | StrictString(CV3) / LooseString(CV4) | 內容必須為全大寫                                                                                                                                                     | `type:strictString\|uppercase`             |
| `pattern`       | `pattern:<regex>`        | StrictString(CV3) / LooseString(CV4) | 使用正規表示式檢查格式、組成或允許字元                                                                                                                                          | `type:strictString\|pattern:^[a-z0-9_-]+$` |
| `in` / `oneOf`  | `in:[a,b]` / `oneOf:[…]` | StrictString(CV3) / LooseString(CV4) | 值必須出現在白名單集合中；比較語意採 **SameValueZero**（等同 JS `Array.includes` / `Set.has`）。<br/>對 primitive 以值相等比較；對 object / array 則採 **reference equality**（非 deep compare）。 | `type:strictString\|in:[paid,cancelled]`   |
| `notIn`         | `notIn:[a,b]`            | StrictString(CV3) / LooseString(CV4) | 值不得出現在集合中                                                                                                                                                    | `type:strictString\|notIn:[deleted]`       |
| `nonNumeric`    | `nonNumeric`             | StrictString(CV3)                    | 內容不得是純數字，用於避免語意混淆（如字串 ID 與數字 ID 區別）                                                                                                                          | `type:strictString\|nonNumeric`            |

**Processing Policy**

* 這些 rules **僅做 validate，不改 canonical**

---

### 結構類 Constraints（Object / Array Constraints）

| Constraint Name  | Rule String 形式               | 適用 Core Type | 語意說明                                                                                                                                                                    | 範例                                        |
|------------------|------------------------------|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------|
| `minItems`       | `minItems:<n>`               | StrictArray  | 陣列長度必須 ≥ n                                                                                                                                                              | `type:strictArray                         |minItems:1`                 |
| `maxItems`       | `maxItems:<n>`               | StrictArray  | 陣列長度必須 ≤ n                                                                                                                                                              | `type:strictArray                         |maxItems:10`                |
| `uniqueItems`    | `uniqueItems`                | StrictArray  | 陣列元素不得重複（以 `===` 判斷）                                                                                                                                                    | `type:strictArray                         |uniqueItems`                |
| `uniqueItemsBy`  | `uniqueItemsBy:<path>`       | StrictArray  | 依指定 key/path 判斷元素唯一性，用於物件陣列去重                                                                                                                                           | `type:strictArray                         |uniqueItemsBy:id`           |
| `itemsIn`        | `itemsIn:[a,b,c]`            | StrictArray  | 陣列中的**每個元素**皆必須存在於指定集合中；比較語意採 **SameValueZero**（等同 JS `Array.includes` / `Set.has`）。<br/>對 primitive 以值相等比較；對 object / array 則採 **reference equality**（非 deep compare）。 | `type:strictArray\|itemsIn:[jpg,png,gif]` |
| `itemsPattern`   | `itemsPattern:<regex>`       | StrictArray  | 每個元素皆須符合 regex（如字串陣列的格式限制）                                                                                                                                              | `type:strictArray                         |itemsPattern:^[A-Z]+$`      |
| `itemsType`      | `itemsType:<SemanticType>`   | StrictArray  | 每個元素皆須符合指定語意型別（整合式 items 規格，而非 object nested schema）                                                                                                                    | `type:strictArray                         |itemsType:StrictNumber`     |
| `itemsValueSpec` | `itemsValueSpec:<rules>`     | StrictArray  | 指定 item 的完整 ValueSpec（比 itemsType 更細緻）                                                                                                                                  | `type:strictArray                         |itemsValueSpec:type:ID1`    |
| `minProperties`  | `minProperties:<n>`          | StrictObject | 物件 key 數量必須 ≥ n                                                                                                                                                         | `type:strictObject                        |minProperties:1`           |
| `maxProperties`  | `maxProperties:<n>`          | StrictObject | 物件 key 數量必須 ≤ n                                                                                                                                                         | `type:strictObject                        |maxProperties:5`           |
| `requiredKeys`   | `requiredKeys:[a,b,c]`       | StrictObject | 物件必須包含指定 key（補足 required 的 object 版語義）                                                                                                                                  | `type:strictObject                        |requiredKeys:[id,name]`    |
| `forbiddenKeys`  | `forbiddenKeys:[a,b,c]`      | StrictObject | 指定 key 不可出現（黑名單語義）                                                                                                                                                      | `type:strictObject                        |forbiddenKeys:[debug]`     |
| `itemTypes`      | `itemTypes:[SemanticType,…]` | StrictArray  | 陣列元素允許的語意型別集合（OR Semantic）                                                                                                                                              | `type:strictArray                         |itemTypes:[StrictString]` |

> `itemTypes` 定義與使用規範（Use Policy, 包含Schema）
> - todo: schema的部分待移動到 Schema 文件
    >

* **itemTypes + items** 不可同時存在 (todo: move to Schema) (在checkTokens階段就檢查)

> * **itemTypes 不可包含 StrictObject / StrictArray**

- 若有以上狀況
  **Compiler 行為：** report error in diagnostics
  **validator 行為：** report error in diagnostics (validator does not totally depend on compiler)

---

### ✅ 通用 Constraints（Generic Value Constraints）

| Constraint Name | Rule String 形式        | 適用 Core Type | 語意說明                         | 範例                             |
|-----------------|-----------------------|--------------|------------------------------|--------------------------------|
| `equals`        | `equals:<literal>`    | 任意           | 值必須嚴格等於 literal（使用 `===` 比較） | `equals:null`、`equals:"draft"` |
| `notEquals`     | `notEquals:<literal>` | 任意           | 值不得等於指定 literal              | `notEquals:0`                  |

> 註解
> **equals / notEquals** 檢查值是否符合某條件 → 屬於 *Constraint*，不改變值，也不處理缺席狀態。

---

## ✅ Modifiers（修飾子）

| Modifier Name | Rule String 形式      | 適用 Core Type | 語意說明                                                          | 範例                             |
|---------------|---------------------|--------------|---------------------------------------------------------------|--------------------------------|
| `nullable`    | `nullable`          | 任意           | 允許值為 `null`（不影響 required 判斷，也不表示必填）                           | `type:LooseString\|nullable`   |
| `required`    | `required`          | 任意           | 欄位必須提供值；僅拒絕 `undefined`，**不排除** `null` / `''` / `0` / `false` | `type:StrictString\|required`  |
| `default`     | `default:<literal>` | 任意           | 當值為 `undefined` 時自動補上預設值；與 required 搭配時仍需提供值                  | `type:StrictNumber\|default:0` |

> 註解
> **required / default / nullable** 改變「值是否存在」或「缺席時的行為」→ 屬於 *Modifier*，不檢查內容語意。

---

## Syntax Sugar Presets（語法糖預設）

| Name               | Expanded Rules（概念上）                                              |
|--------------------|------------------------------------------------------------------|
| `emptyString`      | `type:StrictString\| minLength:0 \| maxLength:0`                 |
| `nonEmptyString`   | `type:StrictString\|minLength:1`                                 |                  |
| `emptyObject`      | `type:StrictObject\|minProperties:0\|maxProperties:0`            |
| `emptyArray`       | `type:StrictArray\|minItems:0\|maxItems:0`                       |
| `arrayOfString`    | `type:StrictArray`, `items: { rules: 'type:StrictString' }`      |
| `arrayOfObject`    | `type:StrictArray`, `items: { rules: 'type:StrictObject' }`      |
| `arrayOfLooseInt`  | `type:StrictArray`, `items: { rules: 'type:LooseNumber\|int' }`  |
| `arrayOfStrictInt` | `type:StrictArray`, `items: { rules: 'type:StrictNumber\|int' }` |
| `arrayOfNull`      | `type:StrictArray`, `items: { rules: 'equals:null' }`            |

**Scope Note**

* **ValueSpec-level sugar**（只展開 type / constraint）
* **Schema-level sugar**（涉及 `items / properties`）

---

## Constraint Compatibility Matrix（約束適用型別矩陣）

> 本矩陣描述各 Constraint 類別可套用的 **Base Type 範圍**。
> ValueSpec Compiler 可依此檢查 Type 與 Constraint 是否相容，避免語意衝突。

| Constraint Group        | 適用 Base Types（核心型別族）              | 說明                                                            |
|-------------------------|-----------------------------------|---------------------------------------------------------------|
| **Number Constraints**  | `StrictNumber`, `LooseNumber`     | 僅適用於數字型別，如 `int`, `min`, `max`, `gte`, `scale` 等              |
| **String Constraints**  | `StrictString`, `LooseString`     | 僅適用於字串型別，如 `minLength`, `pattern`, `lowercase` 等              |
| **Boolean Constraints** | `StrictBool`, `LooseBool`         | 極少獨立 constraint，多為值域限定（通常不額外定義 pattern 類）                     |
| **Array Constraints**   | `StrictArray`（必要時 `LooseArray`）   | `minItems`, `uniqueItems`, `items`, `distinctBy` 等陣列語意        |
| **Object Constraints**  | `StrictObject`                    | `minProperties`, `maxProperties` 限定物件屬性數量                     |
| **Generic Constraints** | 任意 Base Type（依 constraint 自身定義而定） | 如 `required`, `default`, `equals`, `notEquals`, `in`, `oneOf` |

* 補充說明（Equality Semantic）：

    * `in` / `oneOf` / `itemsIn` 類約束在比對值是否存在於指定集合時，
      其相等性判斷一律採用 SameValueZero 語意（等同 JavaScript 的
      Array.includes / Set.has 行為）。

    - 對 primitive values（string / number / boolean / null / undefined）：
      以值相等進行判斷（SameValueZero，NaN 視為相等）。
    - 對 object / array：
      僅採 reference equality（同一個實例才視為相等），
      不執行 deep comparison。

  此規則為 ValueSpec 執行層的固定語意，
  不因 Base Type 或 Constraint Group 不同而改變。

---

### 🧷 要點說明

```
Type 決定值形態
Constraint 在合法形態上縮小語意空間
Compatibility Matrix 保證語意組合不自我衝突
```

例如：

| ValueSpec 組合                      | 是否合法 | 理由                        |
|-----------------------------------|:----:|---------------------------|
| `type:StrictNumber \| min:10`     |  ✔︎  | min 屬於 Number Constraints |
| `type:StrictString \| min:10`     |  ❌   | 字串不能套用數字 constraint       |
| `type:StrictArray \| pattern:/a/` |  ❌   | pattern 僅適用字串型別           |

---

## **「TypeCheck & Constraint Processing Rules」**

> cast 發生在 TypeChecker；
> constraint 只接受 canonical value；
> constraint 不再自行 `Number(value)` …


