@joymerrevent/porters-connect 0.10.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,157 @@
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [0.12.0] - 2026-08-31
9
+
10
+ **PORTERS の全リソースに対応した版**です。データ系は 6/13 から **13/13** になり、
11
+ マスタ Read 4 種と合わせて**残らず触れる**ようになりました([ADR-0060][adr60])。
12
+ 破壊的変更はありません — 既存のアクセサと型はそのままで、増えたぶんだけ足されています。
13
+
14
+ ### Added
15
+
16
+ - **Recruiter リソース**(企業担当者)の Read / Write。他のデータ系リソースと同じアクセサです。
17
+ 次の主軸「全リソース網羅 + ドキュメント充実」([ADR-0060][adr60])の 1 本目で、
18
+ 未対応は Contact / Activity / Contract / Sales / Opportunity / Phase の 6 種になりました。
19
+
20
+ ```ts
21
+ const id = await t.recruiter.create({
22
+ P_Owner: 5,
23
+ P_Client: 20001, // 新規必須(所属する企業)
24
+ P_Name: "採用 太郎",
25
+ });
26
+ const r = await t.recruiter.get(id, { expand: { P_Client: ["P_Name"] } });
27
+ ```
28
+
29
+ - カスタム項目(`U_` / `A_`)も `defineFields({ recruiter: … })` で宣言できます。
30
+ - `P_MobileMail` の Data Type は **`Telephone`** です(Candidate は `Mail`)。
31
+ リソース間で食い違いますが、PORTERS の Field List 記事どおりに写しています。
32
+
33
+ - **Contact リソース**(コンタクト)の Read / Write。**Recruiter と項目構成が同一**ですが、
34
+ PORTERS が役割で分けている別リソースなので、テーブルもカタログも独立しています。
35
+ - **Contract リソース**(契約)の Read / Write。**このリソースだけ `P_Owner` がありません**(PORTERS が
36
+ 公表していないため)。`create` に必要なのは `P_Client` だけです。`Currency` の項目
37
+ (`P_AdvancePayment` / `P_ContingentFee` / `P_ContractorFee`)は **Data Type が `Number`** なので
38
+ 数値として読み書きします。
39
+ - **Activity リソース**(アクティビティ)の Read / Write。`P_Resource`(Resource List の数値 ID)と
40
+ `P_ResourceId` の組で**任意の上位リソースに紐づきます**。参照先が実行時に決まるため
41
+ `P_ResourceId` は `expand` の対象外で、**参照先の ID として読めます**(どのリソースを指していても同じ)。
42
+ - **Opportunity リソース**(商談管理)の Read / Write。`P_Client` / `P_Recruiter` の両方を
43
+ `expand` できます。**このリソースだけ `P_Deleted` がありません** — PORTERS が公表していないため、
44
+ こちらも持たせていません(無いものを足さない)。
45
+
46
+ - **Sales リソース**(成約・売上)の Read / Write。**参照 6 項目すべてを `expand` できます**
47
+ (Client / Recruiter / Job / Contract / Candidate / Resume)。
48
+ `create` の必須は **`P_Owner` のみ**です — 参照 6 項目はリファレンスで `※`(条件付き必須)とされ、
49
+ 実際は依存の連鎖(`P_Job` → `P_Recruiter` → `P_Client` ← `P_Contract`)なので、
50
+ **ライブラリは手前で弾かず PORTERS の判定に委ねます**(詳細は新しい[書き込みの制約ガイド][write-constraints])。
51
+ - **書き込みの制約ガイド**を追加しました。**ライブラリが送信前に弾くもの**と
52
+ **PORTERS に委ねるもの**の境界、リソースごとの新規必須項目の一覧をまとめています。
53
+
54
+ - **Phase リソース**(フェーズ履歴)の Read / Write。**これで PORTERS の全リソースに対応**しました
55
+ (マスタ Read 4 種 + データ系 13 種)。Phase だけは**対象リソースを束ねてから**使います
56
+ ([ADR-0061][adr61])。
57
+
58
+ ```ts
59
+ const phases = t.phase.of("client"); // 対象は名前で指定(`of(5)` ではない)
60
+ await phases.search({ condition: { ResourceId: { eq: 20001 } } });
61
+ await phases.create({ ResourceId: 20001, Memo: "初回接触" });
62
+ ```
63
+
64
+ - **どのリソースのフェーズ履歴かを PORTERS が必ず要求する**ので、`of(...)` で 1 度だけ指定します。
65
+ 以降は他のリソースと同じ書き方で、指定漏れは**型として起こりえません**。
66
+ - 名前はアクセサと同じ綴りです。綴り間違いや、PORTERS が ID を持たないリソース(`"phase"` など)は
67
+ **コンパイルエラー**になります。
68
+ - Phase の項目は**接頭辞も `P_` も付きません**(`Id` / `Resource` / `Date` / `Memo` …)。
69
+ 主キーも `Id` です。カスタム項目と削除フラグは持ちません。
70
+
71
+ - **データ型 `System[Department]`** に対応しました(`Phase.OwnerDepartment` ほか)。
72
+ `User` と同じ形の `DepartmentRef`(`P_Id` / `P_Name`)で読めます。
73
+ **書き込みは提供しません** — PORTERS が書ける形を公表していないため、推測した形を送りません。
74
+
75
+ ### Changed
76
+
77
+ - **`Job.P_Recruiter` / `Process.P_Recruiter` を `expand` できる**ようになりました。
78
+ 参照先の Recruiter カタログが揃ったためです。展開しなければ従来どおり ID が返ります(挙動は不変)。
79
+
80
+ ## [0.11.0] - 2026-08-30
81
+
82
+ **参照先の項目を 1 往復で読めるようにし、`field` の語彙をクエリ全体と揃えた版**です。
83
+ どちらも「**要求したものが黙って返らない**」を潰す変更で、`field` に接頭辞を書かなくなる
84
+ **破壊的変更**を含みます(移行は接頭辞を消すだけ)。
85
+
86
+ ### Added
87
+
88
+ - **参照型の展開 `expand`**([ADR-0058][adr58])。`System[Reference]` の項目(`Job.P_Client` など)から
89
+ **参照先の項目そのもの**を取得できるようになりました。これまでは参照先の **ID だけ**を取り出し、
90
+ 入れ子で返ってきた残りを**黙って捨てて**いました。
91
+
92
+ ```ts
93
+ const page = await t.job.search({ expand: { P_Client: ["P_Id", "P_Name"] } });
94
+ page.items[0]?.P_Client; // { P_Id: number | null; P_Name: string | null } | null
95
+
96
+ const plain = await t.job.search();
97
+ plain.items[0]?.P_Client; // number | null(従来どおり)
98
+ ```
99
+
100
+ - **参照先の接頭辞は書きません**。`condition` / `order` / `field` と同じ素の alias で指定すると、
101
+ ライブラリが `field=Job.P_Client(Client.P_Id,Client.P_Name)` を組み立てます。
102
+ Candidate を参照するときの `Person.` も同様です。
103
+ - **`expand` を書いた項目だけ**戻り型が変わります。基底の型は `number | null` のままなので、
104
+ **参照を ID として使っているコードは無変更**です。展開しなかった参照も ID のまま返ります。
105
+ - `search` / `searchAll` / `get(id, { expand })` で使えます。`get` は第 2 引数が増えただけで、
106
+ 既存の `get(id)` はそのままです。
107
+ - 展開した alias は**素のエントリを置き換えて**送られます。同じ alias を `()` 有り・無しで 2 回送ったとき
108
+ どちらが優先されるかは PORTERS のドキュメントに記述が無いため、**そもそも送りません**。
109
+ - 展開できるのは**参照先をライブラリが実装している項目**だけです。`P_Recruiter`(Recruiter は未実装)と
110
+ カスタム項目(`U_`/`A_`)の参照型は対象外で、**従来どおり ID として読めます**。書くと型エラーです。
111
+ - `field` に `"Job.P_Client(Client.P_Id)"` のような展開文字列を書くと、送信前に
112
+ `PortersConfigError` で止まり `expand` を案内します。
113
+ - `()` の中に付ける参照先の接頭辞と入れ子の形は**実機で未確認**です
114
+ ([live-verification][lv] LV-10 / LV-16)。応答の解釈はタグ名に依存しない実装です。
115
+
116
+ - **型の export**: `Expand` / `ExpandedReadRecord` / `ReferenceMap` / `ResourcePageOf` /
117
+ `ReferenceRecord` / `ReadFieldAlias`。`FieldValue` に `ReferenceRecord`(展開された参照の値)が加わります。
118
+
119
+ ### Changed
120
+
121
+ - **(破壊的)Read の `field` は接頭辞なしの alias で書きます**([ADR-0059][adr59])。
122
+ 接頭辞はリソースごとの定数なので、**ライブラリが付けます**。
123
+
124
+ ```diff
125
+ - field: ["Person.P_Id", "Person.P_Name"]
126
+ + field: ["P_Id", "P_Name"]
127
+ ```
128
+
129
+ - 移行は**接頭辞を消すだけ**です。送られる URL は従来と同じで、変わるのは書き方と、
130
+ **どこで間違いに気づけるか**だけです。
131
+ - `condition` / `order` / `expand` はもともと素の alias を受けていたため、
132
+ **同じクエリの中で語彙が 2 つあった**状態が解消されます。
133
+ - **間違いがコンパイルエラーになります** — 綴り間違い(`P_Nmae`)・接頭辞付き(`Person.P_Name`)・
134
+ リソース名との取り違え(`Candidate.P_Name`。Candidate の接頭辞は `Person` です)・展開文字列。
135
+ これまでは型(`string[]`)でも送信前ガードでも素通りし、**PORTERS 側で黙って無視される**だけでした。
136
+ - **未宣言のカスタム項目は引き続き書けます**(`U_` / `A_` で始まる名前)。ただし `U_` 以降の綴りは
137
+ 検査できないので、よく使うものは `defineFields` で宣言してください(宣言すれば綴りも検査されます)。
138
+ - 実行時は接頭辞付きが来ても**剥がして受けます**(応答側と対称の寛容さ)。cast 経由の古い形も壊れません。
139
+ - 対象は `SearchQuery.field`(データ 5 リソース)と `UserSearchQuery.field`(マスタ User)。
140
+ **Attachment は元から接頭辞なし**なので変更ありません。`field: []`(主キーのみ)と
141
+ 省略時の既定 field([ADR-0020][adr20])の意味も変わりません。
142
+ - **pre-1.0 のため minor**([ADR-0055][adr55] と同じ扱い)。
143
+
144
+ - **明示した `field` も既定 field と同じ組み立てを通る**ようになりました。`User` 型の項目を
145
+ `field` で明示すると **4 サブ項目に展開**されます(`Job.P_Owner(User.P_Id,User.P_Type,User.P_Name,User.P_Mail)`)。
146
+ これまでは `()` 無しで送られ、PORTERS が ID を返すため、**型が `UserRef` を約束するのに実体は `null`**
147
+ になっていました。
148
+
149
+ ### Fixed
150
+
151
+ - **参照 ID の読み取りが、リソース名と alias 接頭辞の食い違いで `null` に落ちていました**。
152
+ 入れ子の**包みタグはリソース名**なのに**中の alias は接頭辞付き**で、この 2 つが異なる Candidate
153
+ (`<Candidate>` に `Person.P_Id`)では従来の照合が外れていました。**素の alias で照合**するようにしたので、
154
+ どちらの表記でも読めます。
155
+ - 影響していたのは `Process.P_Candidate` / `Resume.P_Candidate`(Candidate を参照する項目)です。
156
+ 包みタグの実際の値は**実機で未確認**([live-verification][lv] LV-10)で、フェイクサーバーは
157
+ これまで中立な包みを返していたため、テストでは露出していませんでした。
158
+
8
159
  ## [0.10.0] - 2026-08-22
9
160
 
10
161
  **partition の束ね方を 1 つに絞り、削除済みレコードを判別できるようにした版**です。
@@ -356,10 +507,17 @@
356
507
  [adr55]: docs/adr/0055-partition-binding-guard.md
357
508
  [adr56]: docs/adr/0056-deleted-flag-typing.md
358
509
  [adr57]: docs/adr/0057-itemstate-existing-explicit.md
510
+ [adr58]: docs/adr/0058-reference-expansion-read.md
511
+ [adr59]: docs/adr/0059-read-field-bare-alias.md
512
+ [adr60]: docs/adr/0060-full-resource-coverage-direction.md
513
+ [adr61]: docs/adr/0061-phase-resource-surface.md
514
+ [write-constraints]: docs/guide/write-constraints.md
359
515
  [lv]: docs/live-verification.md
360
516
  [kac]: https://keepachangelog.com/en/1.1.0/
361
517
  [semver]: https://semver.org/
362
- [unreleased]: https://github.com/Joymerrevent/porters-connect/compare/v0.10.0...HEAD
518
+ [unreleased]: https://github.com/Joymerrevent/porters-connect/compare/v0.12.0...HEAD
519
+ [0.12.0]: https://github.com/Joymerrevent/porters-connect/compare/v0.11.0...v0.12.0
520
+ [0.11.0]: https://github.com/Joymerrevent/porters-connect/compare/v0.10.0...v0.11.0
363
521
  [0.10.0]: https://github.com/Joymerrevent/porters-connect/compare/v0.9.0...v0.10.0
364
522
  [0.9.0]: https://github.com/Joymerrevent/porters-connect/compare/v0.8.0...v0.9.0
365
523
  [0.8.0]: https://github.com/Joymerrevent/porters-connect/compare/v0.7.0...v0.8.0
package/README.md CHANGED
@@ -167,26 +167,58 @@ await porters.auth.exchangeAuthorizationCode(code);
167
167
 
168
168
  すべてのデータ系リソースは同じ形のアクセサを持ちます。
169
169
 
170
- | アクセサ | リソース | メソッド |
171
- | -------------- | ------------ | ---------------------------------------------------- |
172
- | `t.candidate` | 個人連絡先 | `search` / `searchAll` / `get` / `create` / `update` |
173
- | `t.job` | JOB | `search` / `searchAll` / `get` / `create` / `update` |
174
- | `t.client` | 企業 | `search` / `searchAll` / `get` / `create` / `update` |
175
- | `t.process` | 選考プロセス | `search` / `searchAll` / `get` / `create` / `update` |
176
- | `t.resume` | レジュメ | `search` / `searchAll` / `get` / `create` / `update` |
177
- | `t.attachment` | 添付ファイル | `search` / `get` / `create` / `update` |
170
+ | アクセサ | リソース | メソッド |
171
+ | --------------- | -------------- | ---------------------------------------------------- |
172
+ | `t.candidate` | 個人連絡先 | `search` / `searchAll` / `get` / `create` / `update` |
173
+ | `t.job` | JOB | `search` / `searchAll` / `get` / `create` / `update` |
174
+ | `t.client` | 企業 | `search` / `searchAll` / `get` / `create` / `update` |
175
+ | `t.recruiter` | 企業担当者 | `search` / `searchAll` / `get` / `create` / `update` |
176
+ | `t.contact` | コンタクト | `search` / `searchAll` / `get` / `create` / `update` |
177
+ | `t.opportunity` | 商談管理 | `search` / `searchAll` / `get` / `create` / `update` |
178
+ | `t.activity` | アクティビティ | `search` / `searchAll` / `get` / `create` / `update` |
179
+ | `t.contract` | 契約 | `search` / `searchAll` / `get` / `create` / `update` |
180
+ | `t.sales` | 成約・売上 | `search` / `searchAll` / `get` / `create` / `update` |
181
+ | `t.process` | 選考プロセス | `search` / `searchAll` / `get` / `create` / `update` |
182
+ | `t.resume` | レジュメ | `search` / `searchAll` / `get` / `create` / `update` |
183
+ | `t.attachment` | 添付ファイル | `search` / `get` / `create` / `update` |
184
+
185
+ **これで PORTERS の全リソースに対応しました**(マスタ Read 4 種 + データ系 13 種)。
186
+ 方針は [ADR-0060][adr-0060]、進捗は [ロードマップ][roadmap]。
187
+
188
+ **Phase だけは対象リソースを束ねてから**使います。どのリソースのフェーズ履歴かを PORTERS が必ず要求するので、
189
+ `of(...)` で 1 度だけ指定すると、以降は他のリソースと同じ書き方になります([ADR-0061][adr-0061])。
190
+
191
+ ```ts
192
+ const phases = t.phase.of("client"); // 対象は名前で指定(`of(5)` ではない)
193
+ await phases.search({ condition: { ResourceId: { eq: 20001 } } });
194
+ await phases.create({ ResourceId: 20001, Memo: "初回接触" });
195
+ ```
196
+
197
+ | アクセサ | リソース | メソッド |
198
+ | ------------------------ | ------------ | ---------------------------------------------------- |
199
+ | `t.phase.of(リソース名)` | フェーズ履歴 | `search` / `searchAll` / `get` / `create` / `update` |
200
+
201
+ 指定できる名前はアクセサと同じ綴りです(`"candidate"` / `"job"` / `"client"` / `"recruiter"` /
202
+ `"contact"` / `"opportunity"` / `"activity"` / `"contract"` / `"sales"` / `"process"` / `"resume"`)。
203
+ 綴り間違いや、PORTERS が ID を持たないリソース(`"phase"` など)は**コンパイルエラー**になります。
178
204
 
179
205
  - `search(query?)` → `{ items, total, count, start }`(オフセット式ページング)。
180
206
  - `searchAll(query?)` → `AsyncIterable`(200 件刻みで全件 yield)。
181
- - `get(id)` → 1 件 or `undefined`。
207
+ - `get(id, options?)` → 1 件 or `undefined`(`options.expand` で参照先の項目も読めます)。
182
208
  - `create(input)` → 採番された **id(number)**。
183
209
  - `update(id, input)` → その **id**。
184
210
 
211
+ > **書き込みの制約**(新規必須の項目・条件付き必須・Phase 更新の作法・送信前に弾かれるもの)は
212
+ > [書き込みの制約ガイド][write-constraints]にまとめています。
213
+
185
214
  **検索クエリ**(`query`)の主なキー(すべて型安全。**項目の Data Type が許す演算子だけ**を受けます):
186
215
 
187
- - `field`:取得する項目(接頭辞付き alias の配列。例 `["Person.P_Id", "Person.P_Name"]`)。
216
+ - `field`:取得する項目(**接頭辞なし**の alias の配列。例 `["P_Id", "P_Name"]`。接頭辞はライブラリが付けます)。
217
+ 綴り間違いや接頭辞付きは**コンパイルエラー**になります。
188
218
  **省略するとカタログ上の全項目を既定取得**します(PORTERS は field 未指定だと主キーのみ返すため、
189
219
  ライブラリが既定 field を補います)。`field: []`(空配列)を渡すと API 仕様どおり**主キーのみ**を返します(件数取得など)。
220
+ - `expand`:参照型(`System[Reference]`)の項目について、**参照先の項目も読む**(`{ P_Client: ["P_Id", "P_Name"] }`)。
221
+ 書かなければ従来どおり**参照先の ID**が返り、**書いた項目だけ**戻り型が参照レコードに変わります。1 往復で済みます。
190
222
  - `condition`:検索条件。`{ 項目: { 演算子: 値 } }` 形式(複数項目は AND)。演算子は Data Type ごとに
191
223
  `eq`/`gt`/`ge`/`le`/`lt`(数値・日時・Id)、`part`/`full`(テキスト)、`or`/`and`(Option・参照/ユーザー型は ID)。
192
224
  **日時の値は ISO 8601(UTC `…Z`)**で渡すと PORTERS 形式へ自動変換します。
@@ -198,8 +230,9 @@ await porters.auth.exchangeAuthorizationCode(code);
198
230
  > **削除 API はありません**(PORTERS 仕様)。`delete()` メソッドは提供しません。削除済みは `itemstate: "deleted"` で読みます
199
231
  > (`condition` は `P_Id` / `P_UpdateDate` / `P_UpdatedBy` に限られ、更新日は 90 日以内)。
200
232
  >
201
- > `field` の 3 通りの意味(省略=全項目 / `[]`=主キーのみ / 明示)、Data Type ごとの演算子一覧、
202
- > 削除済み Read の制約、送信前に落ちる条件は [Read クエリ ガイド][read-query-guide] にまとめています。
233
+ > `field` の 3 通りの意味(省略=全項目 / `[]`=主キーのみ / 明示)、`expand` で展開できる項目、
234
+ > Data Type ごとの演算子一覧、削除済み Read の制約、送信前に落ちる条件は
235
+ > [Read クエリ ガイド][read-query-guide] にまとめています。
203
236
 
204
237
  ### カスタム項目(`U_` / `A_`)
205
238
 
@@ -441,8 +474,12 @@ try {
441
474
  [read-query-guide]: ./docs/guide/read-query.md
442
475
  [multi-tenancy]: ./docs/guide/multi-tenancy.md
443
476
  [bulk-write]: ./docs/guide/bulk-write.md
477
+ [write-constraints]: ./docs/guide/write-constraints.md
444
478
  [sandbox]: ./examples/offline-sandbox.ts
445
479
  [adr]: ./docs/adr/README.md
480
+ [adr-0060]: ./docs/adr/0060-full-resource-coverage-direction.md
481
+ [adr-0061]: ./docs/adr/0061-phase-resource-surface.md
482
+ [roadmap]: ./docs/roadmap.md
446
483
  [adr44]: ./docs/adr/0044-http-status-handling.md
447
484
  [adr46]: ./docs/adr/0046-guard-error-contract.md
448
485
  [adr47]: ./docs/adr/0047-access-point-scheme.md