@joymerrevent/porters-connect 0.15.0 → 0.16.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 +102 -1
- package/README.md +3 -1
- package/dist/index.d.ts +34 -8
- package/dist/index.js +118 -104
- package/dist/index.js.map +1 -1
- package/package.json +5 -2
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,96 @@
|
|
|
5
5
|
|
|
6
6
|
## [Unreleased]
|
|
7
7
|
|
|
8
|
+
## [0.16.0] - 2026-09-15
|
|
9
|
+
|
|
10
|
+
**カスタム項目を「宣言してから使う」に揃えた版**です。**破壊的変更**(`field` が未宣言の
|
|
11
|
+
`U_` / `A_` を受け付けなくなります)を含みます。逃げ道として `rawValue` を用意しました。
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- **`rawValue`** — 宣言していない項目の値を、レコードから**そのまま**読み出します([ADR-0074][adr74])。
|
|
16
|
+
|
|
17
|
+
```ts
|
|
18
|
+
import { rawValue } from "@joymerrevent/porters-connect";
|
|
19
|
+
import type { CandidateSearchQuery } from "@joymerrevent/porters-connect";
|
|
20
|
+
|
|
21
|
+
const page = await t.candidate.search({
|
|
22
|
+
field: ["P_Name", "U_memo"] as CandidateSearchQuery["field"],
|
|
23
|
+
});
|
|
24
|
+
const memo = rawValue(page.items[0], "U_memo"); // string | null | undefined
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
応答に無ければ `undefined`、スカラでなければ(`Option` / `User` / `Image` の入れ子)`null`、
|
|
28
|
+
あれば生の文字列を返します。**変換はしません**ので、日時は PORTERS の書式
|
|
29
|
+
(`2026/09/10 12:00:00`)のままです。宣言できる項目は宣言してください — こちらは逃げ道です。
|
|
30
|
+
|
|
31
|
+
### Changed
|
|
32
|
+
|
|
33
|
+
- **(破壊的)`field` が未宣言のカスタム項目を受け付けなくなりました**([ADR-0074][adr74])。
|
|
34
|
+
カスタム項目を使う入口は 4 つ(`field` / `condition` / `order` / 書き込み)あり、**`field` だけが
|
|
35
|
+
宣言なしの `U_` / `A_` を受けていました**。しかも受け取り側の型には出ないため、
|
|
36
|
+
**要求はできるのに読めない**という非対称が残っていました。
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
await t.candidate.search({ field: ["U_memo"] });
|
|
40
|
+
// ^^^^^^^^ 型エラーになります
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
直し方は**宣言**です(`defineFields`)。項目 1 つなら 1 行で済み、テナントの項目からは
|
|
44
|
+
`generateFieldDecls` で生成できます。宣言すると綴りが検査され、値も宣言した Data Type で
|
|
45
|
+
変換されます。**実行時の挙動は変えていません** — 型を外せば送れますし、応答に知らない項目が
|
|
46
|
+
混ざっても落ちません。宣言せずに触る必要があるときは、上記の `rawValue` を使ってください。
|
|
47
|
+
|
|
48
|
+
- **(型のみ)宣言の違うクライアントを関数に渡せなくなりました**。`TenantScope<typeof fields>` は
|
|
49
|
+
その宣言のスコープだけを受け取ります。以前は型が通ってしまい、`number` と型が言う値に生の
|
|
50
|
+
文字列が入ることがありました。どの宣言でも受ける関数は `TenantScope<DeclaredCatalogs>` と
|
|
51
|
+
書けます(これまでどおり)。
|
|
52
|
+
|
|
53
|
+
- **使い方ドキュメントで、読み取りと書き込みの非対称を揃えました**。`Option` / `User` /
|
|
54
|
+
`System[Reference]` / `Image` / `Link` は Read と Write で形が違うため、同じ項目の往復に
|
|
55
|
+
読み替えが要ります。ガイドと[正典(PORTERS API の事実)][ref]の双方を、出典に突き合わせて
|
|
56
|
+
埋めました。パッケージの中身は変わりません。
|
|
57
|
+
|
|
58
|
+
- **`src/fields` が品質ゲートの対象に戻りました**([RV-44][rv44])。カバレッジとミューテーションの
|
|
59
|
+
除外リストに、プレースホルダだった頃の `src/fields/**` が残っていました。宣言 DSL と
|
|
60
|
+
テナントカタログの照合はすでに実ロジックなので、計測対象に戻し、見つかった抜けを埋めています。
|
|
61
|
+
こちらもパッケージの中身は変わりません。
|
|
62
|
+
|
|
63
|
+
## [0.15.1] - 2026-09-13
|
|
64
|
+
|
|
65
|
+
**開発・CI まわりだけの版**です。**公開されるパッケージの中身(`dist`)は 0.15.0 と同一**で、
|
|
66
|
+
公開 API・型・挙動に変更はありません(既存コードはそのまま動きます)。
|
|
67
|
+
|
|
68
|
+
### Security
|
|
69
|
+
|
|
70
|
+
- **開発用依存の既知脆弱性 5 件を解消しました**。いずれもビルド・テスト用ツールの推移依存で、
|
|
71
|
+
**利用者の実行時には入りません**(`dependencies` は `fast-xml-parser` のみ)。
|
|
72
|
+
依存の解決を `pnpm.overrides` で固定しています。
|
|
73
|
+
|
|
74
|
+
| パッケージ | 経路 | Advisory |
|
|
75
|
+
| ----------------- | --------------------------------------------- | ------------------------------------------------------- |
|
|
76
|
+
| `brace-expansion` | `@stryker-mutator/core` > `minimatch` | [GHSA-mh99-v99m-4gvg][gh1] / [GHSA-rgw5-rvv9-x895][gh2] |
|
|
77
|
+
| `smol-toml` | `markdownlint-cli2` | [GHSA-7w5x-hrqm-74c2][gh5] |
|
|
78
|
+
| `qs` | `@stryker-mutator/core` > `typed-rest-client` | [GHSA-x5fp-wj9c-mxmx][gh3] / [GHSA-4mjr-xmp4-gh2g][gh4] |
|
|
79
|
+
|
|
80
|
+
- **GitHub Actions の書き込み権限を job 単位に絞りました**。タグ作成ワークフローの既定を
|
|
81
|
+
読み取りのみにし、書き込みは実際に必要な job にだけ与えます。ワークフローが行える操作の範囲は
|
|
82
|
+
変わりません(最小権限の原則に寄せた整理です)。
|
|
83
|
+
|
|
84
|
+
### Changed
|
|
85
|
+
|
|
86
|
+
- **往復・エスケープ・分割の不変条件を property-based テストで検査するようになりました**
|
|
87
|
+
([fast-check][fastcheck])。代表値を 1 点ずつ確かめる形では境界の抜けが見えないため、
|
|
88
|
+
値を機械に選ばせて不変条件そのものを検査します。対象は 3 つです。
|
|
89
|
+
|
|
90
|
+
- 日時: PORTERS 形式 ⇄ ISO 8601 (UTC) の往復と、オフセット表記によらない UTC 正規化
|
|
91
|
+
- Write XML: エスケープ後に生の `&` `<` `>` が残らないこと、書いて読むと元の値に戻ること
|
|
92
|
+
- bulk write: 200 件と約 15000 文字の 2 つの上限を、どの入力でも同時に満たすこと
|
|
93
|
+
|
|
94
|
+
- **生成 API リファレンスの「Defined in」表記を整理しました**。継承元が依存側にある記号
|
|
95
|
+
(`Error.message` など)のパスから pnpm ストアの版つきディレクトリを落とし、
|
|
96
|
+
`@types/node/globals.d.ts:67` の形にしています。表示されるメンバーは変わりません。
|
|
97
|
+
|
|
8
98
|
## [0.15.0] - 2026-09-13
|
|
9
99
|
|
|
10
100
|
**宣言と実物のズレを黙って飲み込まなくなった版**です。**破壊的変更**(読み取りの型不一致が
|
|
@@ -702,14 +792,19 @@
|
|
|
702
792
|
[adr63]: docs/adr/0063-idempotency-guard-scope.md
|
|
703
793
|
[rv22]: docs/reviews/rv/0022-ratelimit-create-no-retry.md
|
|
704
794
|
[rv32]: docs/reviews/rv/0032-searchall-query-mutation.md
|
|
795
|
+
[rv44]: docs/reviews/rv/0044-fields-excluded-from-coverage.md
|
|
705
796
|
[write-constraints]: docs/usage/concepts/limits.md
|
|
706
797
|
[adr68]: docs/adr/0068-api-reference-tooling.md
|
|
707
798
|
[adr69]: docs/adr/0069-tenant-field-catalog-tooling.md
|
|
708
799
|
[adr73]: docs/adr/0073-throttle-sharing.md
|
|
800
|
+
[adr74]: docs/adr/0074-custom-field-declaration-required.md
|
|
709
801
|
[lv]: docs/live-verification.md
|
|
802
|
+
[ref]: docs/usage/reference/README.md
|
|
710
803
|
[kac]: https://keepachangelog.com/en/1.1.0/
|
|
711
804
|
[semver]: https://semver.org/
|
|
712
|
-
[unreleased]: https://github.com/Joymerrevent/porters-connect/compare/v0.
|
|
805
|
+
[unreleased]: https://github.com/Joymerrevent/porters-connect/compare/v0.16.0...HEAD
|
|
806
|
+
[0.16.0]: https://github.com/Joymerrevent/porters-connect/compare/v0.15.1...v0.16.0
|
|
807
|
+
[0.15.1]: https://github.com/Joymerrevent/porters-connect/compare/v0.15.0...v0.15.1
|
|
713
808
|
[0.15.0]: https://github.com/Joymerrevent/porters-connect/compare/v0.14.0...v0.15.0
|
|
714
809
|
[0.14.0]: https://github.com/Joymerrevent/porters-connect/compare/v0.13.0...v0.14.0
|
|
715
810
|
[0.13.0]: https://github.com/Joymerrevent/porters-connect/compare/v0.12.1...v0.13.0
|
|
@@ -730,3 +825,9 @@
|
|
|
730
825
|
[0.2.0]: https://github.com/Joymerrevent/porters-connect/compare/v0.1.1...v0.2.0
|
|
731
826
|
[0.1.1]: https://github.com/Joymerrevent/porters-connect/compare/v0.1.0...v0.1.1
|
|
732
827
|
[0.1.0]: https://github.com/Joymerrevent/porters-connect/releases/tag/v0.1.0
|
|
828
|
+
[gh1]: https://github.com/advisories/GHSA-mh99-v99m-4gvg
|
|
829
|
+
[gh2]: https://github.com/advisories/GHSA-rgw5-rvv9-x895
|
|
830
|
+
[gh3]: https://github.com/advisories/GHSA-x5fp-wj9c-mxmx
|
|
831
|
+
[gh4]: https://github.com/advisories/GHSA-4mjr-xmp4-gh2g
|
|
832
|
+
[gh5]: https://github.com/advisories/GHSA-7w5x-hrqm-74c2
|
|
833
|
+
[fastcheck]: https://github.com/dubzzz/fast-check
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @joymerrevent/porters-connect
|
|
2
2
|
|
|
3
|
-
[![npm version][npm-badge]][npm] [![License: MIT][mit-badge]][mit] ![Node >= 20][node-badge] [![OpenSSF Scorecard][scorecard-badge]][scorecard]
|
|
3
|
+
[![npm version][npm-badge]][npm] [![License: MIT][mit-badge]][mit] ![Node >= 20][node-badge] [![OpenSSF Scorecard][scorecard-badge]][scorecard] [![OpenSSF Best Practices][bp-badge]][bp]
|
|
4
4
|
|
|
5
5
|
PORTERS Connect API(旧 HRBC)を **TypeScript から型安全・簡単に**扱うための、
|
|
6
6
|
[Joymerrevent(ジョイメリベント)][joymerrevent] 製の **非公式(unofficial)** ラッパーです。
|
|
@@ -147,6 +147,8 @@ console.log(page.total, page.items[0]?.P_Name);
|
|
|
147
147
|
[node-badge]: https://img.shields.io/badge/node-%3E%3D20-brightgreen.svg
|
|
148
148
|
[scorecard]: https://scorecard.dev/viewer/?uri=github.com/Joymerrevent/porters-connect
|
|
149
149
|
[scorecard-badge]: https://api.scorecard.dev/projects/github.com/Joymerrevent/porters-connect/badge
|
|
150
|
+
[bp]: https://www.bestpractices.dev/projects/14611
|
|
151
|
+
[bp-badge]: https://www.bestpractices.dev/projects/14611/badge
|
|
150
152
|
[joymerrevent]: https://github.com/Joymerrevent
|
|
151
153
|
[contributing]: ./CONTRIBUTING.md
|
|
152
154
|
[security]: ./SECURITY.md
|
package/dist/index.d.ts
CHANGED
|
@@ -268,13 +268,34 @@ type FieldCatalog = Record<string, DataType | null>;
|
|
|
268
268
|
type EmptyCatalog = Record<never, never>;
|
|
269
269
|
/**
|
|
270
270
|
* A decoded record: every known field, each `DecodedValue | null`, and **optional** because a
|
|
271
|
-
* field not named in `field` is simply absent (SD-3 "simple" type — ADR-0005/0019).
|
|
272
|
-
*
|
|
273
|
-
*
|
|
271
|
+
* field not named in `field` is simply absent (SD-3 "simple" type — ADR-0005/0019). An alias the
|
|
272
|
+
* catalog does not know is not typed here — declare it with `defineFields` (ADR-0023) to get it
|
|
273
|
+
* typed and converted. At runtime such a field still passes through as a raw value; read it with
|
|
274
|
+
* {@link rawValue} (ADR-0074 D2).
|
|
274
275
|
*/
|
|
275
276
|
type ReadRecord<F extends FieldCatalog> = {
|
|
276
277
|
[K in keyof F]?: DecodedValue<F[K]> | null;
|
|
277
278
|
};
|
|
279
|
+
/**
|
|
280
|
+
* Read a field the catalog does not know (ADR-0074 D2) — the named escape hatch for a value that
|
|
281
|
+
* arrived without a declaration: through a cast in `field`, inside an expanded reference record,
|
|
282
|
+
* or because PORTERS returned a field that was not asked for.
|
|
283
|
+
*
|
|
284
|
+
* Returns what the record actually holds, unconverted:
|
|
285
|
+
*
|
|
286
|
+
* - `undefined` — the alias is not on the record (it was never returned)
|
|
287
|
+
* - `null` — it is there but not a scalar (PORTERS sends a nested node for Option / User / Image)
|
|
288
|
+
* - `string` — the raw text, exactly as PORTERS sent it
|
|
289
|
+
*
|
|
290
|
+
* **No conversion happens.** A date comes back in PORTERS' own format (`2026/09/10 12:00:00`), not
|
|
291
|
+
* ISO 8601, and a number comes back as text. Declare the field with `defineFields` to get the
|
|
292
|
+
* converted, typed value instead — this is the escape hatch, not the normal path.
|
|
293
|
+
*
|
|
294
|
+
* @example
|
|
295
|
+
* const page = await t.candidate.search({ field: ["P_Name"] });
|
|
296
|
+
* const memo = rawValue(page.items[0], "U_memo"); // string | null | undefined
|
|
297
|
+
*/
|
|
298
|
+
declare const rawValue: (record: unknown, alias: string) => string | null | undefined;
|
|
278
299
|
/**
|
|
279
300
|
* A page of decoded records: the standard Read envelope (Total / Count / Start) around whatever
|
|
280
301
|
* the item decoder produced. Parametrised by the *record* rather than the catalog because a read
|
|
@@ -288,16 +309,21 @@ type ResourcePageOf<T> = {
|
|
|
288
309
|
};
|
|
289
310
|
type ResourcePage<F extends FieldCatalog> = ResourcePageOf<ReadRecord<F>>;
|
|
290
311
|
/**
|
|
291
|
-
* What a Read `field` entry may name (ADR-0059): a catalogued alias — every
|
|
292
|
-
* plus the custom fields declared with `defineFields` (ADR-0023)
|
|
293
|
-
*
|
|
312
|
+
* What a Read `field` entry may name (ADR-0059 / ADR-0074 D1): a **catalogued** alias — every
|
|
313
|
+
* standard `P_` field plus the custom fields declared with `defineFields` (ADR-0023). An
|
|
314
|
+
* undeclared `U_`/`A_` alias is **not** accepted: `condition`, `order` and the Write inputs have
|
|
315
|
+
* always required a declaration, and ADR-0074 D1 brings `field` in line, so custom fields follow
|
|
316
|
+
* one rule — declare, then use.
|
|
294
317
|
*
|
|
295
318
|
* Aliases are **bare**: the resource's prefix (`Person.` for Candidate) is a constant the
|
|
296
319
|
* descriptor knows, so the library adds it. That makes `condition` / `order` / `field` one
|
|
297
320
|
* vocabulary and turns a typo (`P_Nmae`) or a hand-written prefix into a compile error instead of
|
|
298
321
|
* a request that quietly returns nothing.
|
|
322
|
+
*
|
|
323
|
+
* The runtime stays permissive (ADR-0074): an alias that arrives through a cast is still sent, and
|
|
324
|
+
* a response field the catalog does not know still decodes — read it with {@link rawValue}.
|
|
299
325
|
*/
|
|
300
|
-
type ReadFieldAlias<F extends FieldCatalog> =
|
|
326
|
+
type ReadFieldAlias<F extends FieldCatalog> = keyof F & string;
|
|
301
327
|
|
|
302
328
|
/**
|
|
303
329
|
* The resource a `System[Reference]` field points at, as far as expansion needs it: its alias
|
|
@@ -2801,4 +2827,4 @@ declare const bytesToBase64: (bytes: Uint8Array) => string;
|
|
|
2801
2827
|
/** Decode a Base64 string back to raw bytes. */
|
|
2802
2828
|
declare const base64ToBytes: (b64: string) => Uint8Array;
|
|
2803
2829
|
|
|
2804
|
-
export { type Activity, type ActivityCreateInput, type ActivityPage, type ActivityResource, type ActivitySearchQuery, type ActivityUpdateInput, type Attachment, type AttachmentCreate, type AttachmentPage, type AttachmentResource, type AttachmentSearchQuery, type AttachmentUpdate, type AuthApi, type AuthorizationUrlOptions, type BulkWriteResult, type BulkWriteResultItem, type Candidate, type CandidateCreateInput, type CandidatePage, type CandidateResource, type CandidateSearchQuery, type CandidateUpdateInput, type Client, type ClientCreateInput, type ClientPage, type ClientResource, type ClientSearchQuery, type ClientUpdateInput, type Condition, type Contact, type ContactCreateInput, type ContactPage, type ContactResource, type ContactSearchQuery, type ContactUpdateInput, type Contract, type ContractCreateInput, type ContractPage, type ContractResource, type ContractSearchQuery, type ContractUpdateInput, type CustomDataType, type CustomFieldResource, type CustomFor, type DeclaredCatalogs, type DefinedFields, type DepartmentRef, type ErrorCategory, type Expand, type ExpandedReadRecord, type Field, type FieldBuilder, type FieldCatalogSource, type FieldDecls, type FieldDef, type FieldPage, type FieldResource, type FieldSearchQuery, type FieldTypeMismatch, type FieldValue, type FieldVerification, type GenerateFieldDeclsOptions, type GetAccessTokenOptions, type ImageContentType, type ImageOption, type ImageReadRecord, type ImageSelectedValue, type ImageSubField, type ImageValue, type ImageWriteValue, type ItemState, type Job, type JobCreateInput, type JobPage, type JobResource, type JobSearchQuery, type JobUpdateInput, type LinkValue, type MissingField, type MockHandler, type MockReply, type MockTransportOptions, type Opportunity, type OpportunityCreateInput, type OpportunityPage, type OpportunityResource, type OpportunitySearchQuery, type OpportunityUpdateInput, type Option, type OptionResource, type OptionSearchQuery, type Order, type Partition, type PartitionId, type PartitionPage, type PartitionResource, type PartitionSearchQuery, type Phase, type PhaseAccessor, type PhaseCreateInput, type PhasePage, type PhaseResource, type PhaseSearchQuery, type PhaseUpdateInput, PortersAuthError, PortersClient, type PortersClientOptions, PortersConfigError, PortersError, type PortersErrorContext, type PortersErrorOptions, PortersNetworkError, PortersResourceError, type Process, type ProcessCreateInput, type ProcessPage, type ProcessResource, type ProcessSearchQuery, type ProcessUpdateInput, type ReadCustomCatalogOptions, type ReadFieldAlias, type Recruiter, type RecruiterCreateInput, type RecruiterPage, type RecruiterResource, type RecruiterSearchQuery, type RecruiterUpdateInput, type ReferenceMap, type ReferenceRecord, type ResourceName, type ResourcePageOf, type ResourceType, type Resume, type ResumeCreateInput, type ResumePage, type ResumeResource, type ResumeSearchQuery, type ResumeUpdateInput, type RevokeUrlOptions, type Sales, type SalesCreateInput, type SalesPage, type SalesResource, type SalesSearchQuery, type SalesUpdateInput, type Scheme, type Scope, type SearchQuery, type StoredTokens, type TenantCustomCatalog, type TenantScope, type Throttle, type ThrottleOptions, type TokenProvider, type TokenStore, type Transport, type TransportRequest, type TransportResponse, type UndeclarableField, type UndeclarableReason, type UndeclarableTenantField, type UndeclaredField, type UnverifiableResource, type User, type UserPage, type UserRef, type UserResource, type UserSearchQuery, type VerifyFieldsOptions, assertFieldsMatch, base64ToBytes, bytesToBase64, createMockTransport, createThrottle, defineFields, generateFieldDecls, readCustomCatalog, verifyFields };
|
|
2830
|
+
export { type Activity, type ActivityCreateInput, type ActivityPage, type ActivityResource, type ActivitySearchQuery, type ActivityUpdateInput, type Attachment, type AttachmentCreate, type AttachmentPage, type AttachmentResource, type AttachmentSearchQuery, type AttachmentUpdate, type AuthApi, type AuthorizationUrlOptions, type BulkWriteResult, type BulkWriteResultItem, type Candidate, type CandidateCreateInput, type CandidatePage, type CandidateResource, type CandidateSearchQuery, type CandidateUpdateInput, type Client, type ClientCreateInput, type ClientPage, type ClientResource, type ClientSearchQuery, type ClientUpdateInput, type Condition, type Contact, type ContactCreateInput, type ContactPage, type ContactResource, type ContactSearchQuery, type ContactUpdateInput, type Contract, type ContractCreateInput, type ContractPage, type ContractResource, type ContractSearchQuery, type ContractUpdateInput, type CustomDataType, type CustomFieldResource, type CustomFor, type DeclaredCatalogs, type DefinedFields, type DepartmentRef, type ErrorCategory, type Expand, type ExpandedReadRecord, type Field, type FieldBuilder, type FieldCatalogSource, type FieldDecls, type FieldDef, type FieldPage, type FieldResource, type FieldSearchQuery, type FieldTypeMismatch, type FieldValue, type FieldVerification, type GenerateFieldDeclsOptions, type GetAccessTokenOptions, type ImageContentType, type ImageOption, type ImageReadRecord, type ImageSelectedValue, type ImageSubField, type ImageValue, type ImageWriteValue, type ItemState, type Job, type JobCreateInput, type JobPage, type JobResource, type JobSearchQuery, type JobUpdateInput, type LinkValue, type MissingField, type MockHandler, type MockReply, type MockTransportOptions, type Opportunity, type OpportunityCreateInput, type OpportunityPage, type OpportunityResource, type OpportunitySearchQuery, type OpportunityUpdateInput, type Option, type OptionResource, type OptionSearchQuery, type Order, type Partition, type PartitionId, type PartitionPage, type PartitionResource, type PartitionSearchQuery, type Phase, type PhaseAccessor, type PhaseCreateInput, type PhasePage, type PhaseResource, type PhaseSearchQuery, type PhaseUpdateInput, PortersAuthError, PortersClient, type PortersClientOptions, PortersConfigError, PortersError, type PortersErrorContext, type PortersErrorOptions, PortersNetworkError, PortersResourceError, type Process, type ProcessCreateInput, type ProcessPage, type ProcessResource, type ProcessSearchQuery, type ProcessUpdateInput, type ReadCustomCatalogOptions, type ReadFieldAlias, type Recruiter, type RecruiterCreateInput, type RecruiterPage, type RecruiterResource, type RecruiterSearchQuery, type RecruiterUpdateInput, type ReferenceMap, type ReferenceRecord, type ResourceName, type ResourcePageOf, type ResourceType, type Resume, type ResumeCreateInput, type ResumePage, type ResumeResource, type ResumeSearchQuery, type ResumeUpdateInput, type RevokeUrlOptions, type Sales, type SalesCreateInput, type SalesPage, type SalesResource, type SalesSearchQuery, type SalesUpdateInput, type Scheme, type Scope, type SearchQuery, type StoredTokens, type TenantCustomCatalog, type TenantScope, type Throttle, type ThrottleOptions, type TokenProvider, type TokenStore, type Transport, type TransportRequest, type TransportResponse, type UndeclarableField, type UndeclarableReason, type UndeclarableTenantField, type UndeclaredField, type UnverifiableResource, type User, type UserPage, type UserRef, type UserResource, type UserSearchQuery, type VerifyFieldsOptions, assertFieldsMatch, base64ToBytes, bytesToBase64, createMockTransport, createThrottle, defineFields, generateFieldDecls, rawValue, readCustomCatalog, verifyFields };
|
package/dist/index.js
CHANGED
|
@@ -722,106 +722,6 @@ var isoToPortersDate = (value) => {
|
|
|
722
722
|
return `${m[1]}/${m[2]}/${m[3]}`;
|
|
723
723
|
};
|
|
724
724
|
|
|
725
|
-
// src/xml/encode.ts
|
|
726
|
-
var IMAGE_CONTENT_TYPES = [
|
|
727
|
-
"image/jpeg",
|
|
728
|
-
"image/gif",
|
|
729
|
-
"image/png",
|
|
730
|
-
"image/bmp"
|
|
731
|
-
];
|
|
732
|
-
var escapeXml = (s) => s.replace(
|
|
733
|
-
/[&<>]/g,
|
|
734
|
-
(c) => c === "&" ? "&" : c === "<" ? "<" : ">"
|
|
735
|
-
);
|
|
736
|
-
var text = (v) => typeof v === "object" && !Array.isArray(v) ? JSON.stringify(v) : String(v);
|
|
737
|
-
var scalar = (v) => escapeXml(text(v));
|
|
738
|
-
var IMAGE_SUBFIELDS = [
|
|
739
|
-
"FileName",
|
|
740
|
-
"ContentType",
|
|
741
|
-
"Content"
|
|
742
|
-
];
|
|
743
|
-
var imageInner = (value) => {
|
|
744
|
-
if (typeof value !== "object" || Array.isArray(value)) return scalar(value);
|
|
745
|
-
const parts = value;
|
|
746
|
-
return IMAGE_SUBFIELDS.filter((sub) => parts[sub] !== void 0).map((sub) => `<${sub}>${escapeXml(String(parts[sub]))}</${sub}>`).join("");
|
|
747
|
-
};
|
|
748
|
-
var invalidValue = (alias, type, value, cause) => new PortersConfigError(
|
|
749
|
-
`${alias}: cannot write ${JSON.stringify(value)} as ${type}`,
|
|
750
|
-
{
|
|
751
|
-
category: "validation",
|
|
752
|
-
hint: `${type} values are written in ISO 8601 (e.g. "2026-09-10" / "2026-09-10T12:00:00Z"); the library converts them to PORTERS' format.`,
|
|
753
|
-
// The underlying RangeError stays on `cause` rather than in the message: the message
|
|
754
|
-
// already names the field, the value and the type, which is what a reader needs.
|
|
755
|
-
context: { operation: "encode" },
|
|
756
|
-
cause
|
|
757
|
-
}
|
|
758
|
-
);
|
|
759
|
-
var converted = (alias, type, value, convert) => {
|
|
760
|
-
try {
|
|
761
|
-
return convert();
|
|
762
|
-
} catch (cause) {
|
|
763
|
-
throw invalidValue(alias, type, value, cause);
|
|
764
|
-
}
|
|
765
|
-
};
|
|
766
|
-
var encodeField = (type, value, alias) => {
|
|
767
|
-
switch (type) {
|
|
768
|
-
// Option: the selected aliases as empty child elements. Canonical input is an
|
|
769
|
-
// array (ADR-0017, symmetric with read); a lone string is wrapped as a 1-element
|
|
770
|
-
// selection (fail-safe).
|
|
771
|
-
case "Option":
|
|
772
|
-
return (Array.isArray(value) ? value : [text(value)]).map((alias2) => `<${alias2}/>`).join("");
|
|
773
|
-
// System[DateTime] (registration/update) is Write-restricted by PORTERS; we still
|
|
774
|
-
// serialize it identically — rejecting the write is the input type's job (SD-3).
|
|
775
|
-
case "DateTime":
|
|
776
|
-
case "System[DateTime]":
|
|
777
|
-
return scalar(
|
|
778
|
-
converted(alias, type, value, () => isoToPortersDateTime(text(value)))
|
|
779
|
-
);
|
|
780
|
-
// Age shares Date's wire format (`yyyy/mm/dd`): we write the birthdate.
|
|
781
|
-
case "Date":
|
|
782
|
-
case "Age":
|
|
783
|
-
return scalar(
|
|
784
|
-
converted(alias, type, value, () => isoToPortersDate(text(value)))
|
|
785
|
-
);
|
|
786
|
-
// Image: the three nested sub-elements (ADR-0064 論点3).
|
|
787
|
-
case "Image":
|
|
788
|
-
return imageInner(value);
|
|
789
|
-
// System[Id] / Number / User & System[Reference] / Link (all ID-only) / string Data Types all
|
|
790
|
-
// serialize as a scalar (the string types stay distinct labels per ADR-0016).
|
|
791
|
-
// Link の Read は 3 形の union だが、Write は ID ひとつ(`<Alias>10001</Alias>`)= User と同じ。
|
|
792
|
-
// System[Department] は静的な Write 入力から外してあるので、ここに来るのは cast 経由のみ
|
|
793
|
-
// (System[DateTime] と同じ扱い)。到達したときは User と同じくスカラとして書き出す。
|
|
794
|
-
case "Link":
|
|
795
|
-
case "System[Id]":
|
|
796
|
-
case "Number":
|
|
797
|
-
case "User":
|
|
798
|
-
case "System[Reference]":
|
|
799
|
-
case "System[Department]":
|
|
800
|
-
case "SinglelineText":
|
|
801
|
-
case "MultilineText":
|
|
802
|
-
case "Mail":
|
|
803
|
-
case "Telephone":
|
|
804
|
-
case "URL":
|
|
805
|
-
return scalar(value);
|
|
806
|
-
}
|
|
807
|
-
};
|
|
808
|
-
var encodeItem = (prefix, fields, item) => {
|
|
809
|
-
const parts = [];
|
|
810
|
-
for (const [alias, value] of Object.entries(item)) {
|
|
811
|
-
if (value === null || value === void 0) continue;
|
|
812
|
-
const type = fields.get(alias);
|
|
813
|
-
const inner = type === void 0 || type === null ? scalar(value) : encodeField(type, value, alias);
|
|
814
|
-
const tag2 = qualify(prefix, alias);
|
|
815
|
-
parts.push(`<${tag2}>${inner}</${tag2}>`);
|
|
816
|
-
}
|
|
817
|
-
return parts.join("");
|
|
818
|
-
};
|
|
819
|
-
var encodeWriteItem = (prefix, fields, item) => `<Item>${encodeItem(prefix, fields, item)}</Item>`;
|
|
820
|
-
var buildWriteXml = (config) => {
|
|
821
|
-
const items = config.items.map((item) => encodeWriteItem(config.prefix, config.fields, item)).join("");
|
|
822
|
-
return `<${config.resource}>${items}</${config.resource}>`;
|
|
823
|
-
};
|
|
824
|
-
|
|
825
725
|
// src/xml/decode.ts
|
|
826
726
|
var bareTag = (key) => key.includes(".") ? key.slice(key.indexOf(".") + 1) : key;
|
|
827
727
|
var pickPrefixed = (obj, prefix, key) => asString(obj[`${prefix}.${key}`]) ?? asString(obj[key]);
|
|
@@ -900,7 +800,7 @@ var mismatch = (alias, type, wants) => new PortersResourceError(
|
|
|
900
800
|
context: { operation: "decode" }
|
|
901
801
|
}
|
|
902
802
|
);
|
|
903
|
-
var
|
|
803
|
+
var converted = (alias, type, value, convert) => {
|
|
904
804
|
try {
|
|
905
805
|
return convert();
|
|
906
806
|
} catch (cause) {
|
|
@@ -954,7 +854,7 @@ var decodeField = (type, raw, alias) => {
|
|
|
954
854
|
// format; System[DateTime] is Write-restricted, but that is a write-time concern.
|
|
955
855
|
case "DateTime":
|
|
956
856
|
case "System[DateTime]":
|
|
957
|
-
return
|
|
857
|
+
return converted(
|
|
958
858
|
alias,
|
|
959
859
|
scalarType,
|
|
960
860
|
value,
|
|
@@ -964,7 +864,7 @@ var decodeField = (type, raw, alias) => {
|
|
|
964
864
|
// and derives the age in its UI, so the faithful value is the date itself.
|
|
965
865
|
case "Date":
|
|
966
866
|
case "Age":
|
|
967
|
-
return
|
|
867
|
+
return converted(alias, scalarType, value, () => portersDateToIso(value));
|
|
968
868
|
}
|
|
969
869
|
};
|
|
970
870
|
var decodeReferenceRecord = (raw, types) => {
|
|
@@ -984,6 +884,12 @@ var decodeReferenceRecord = (raw, types) => {
|
|
|
984
884
|
};
|
|
985
885
|
|
|
986
886
|
// src/resources/read-core.ts
|
|
887
|
+
var rawValue = (record, alias) => {
|
|
888
|
+
const rec = asRecord(record);
|
|
889
|
+
if (rec === void 0 || !(alias in rec)) return void 0;
|
|
890
|
+
const value = rec[alias];
|
|
891
|
+
return typeof value === "string" ? value : null;
|
|
892
|
+
};
|
|
987
893
|
var bareAlias = (key) => key.includes(".") ? key.slice(key.indexOf(".") + 1) : key;
|
|
988
894
|
var USER_SUBFIELDS = ["P_Id", "P_Type", "P_Name", "P_Mail"];
|
|
989
895
|
var readFieldEntry = (prefix, alias, type) => type === "User" ? `${qualify(prefix, alias)}(${USER_SUBFIELDS.map((s) => `User.${s}`).join(",")})` : qualify(prefix, alias);
|
|
@@ -1053,6 +959,106 @@ var paginateOnce = async function* (prepare) {
|
|
|
1053
959
|
yield* paginate(prepare());
|
|
1054
960
|
};
|
|
1055
961
|
|
|
962
|
+
// src/xml/encode.ts
|
|
963
|
+
var IMAGE_CONTENT_TYPES = [
|
|
964
|
+
"image/jpeg",
|
|
965
|
+
"image/gif",
|
|
966
|
+
"image/png",
|
|
967
|
+
"image/bmp"
|
|
968
|
+
];
|
|
969
|
+
var escapeXml = (s) => s.replace(
|
|
970
|
+
/[&<>]/g,
|
|
971
|
+
(c) => c === "&" ? "&" : c === "<" ? "<" : ">"
|
|
972
|
+
);
|
|
973
|
+
var text = (v) => typeof v === "object" && !Array.isArray(v) ? JSON.stringify(v) : String(v);
|
|
974
|
+
var scalar = (v) => escapeXml(text(v));
|
|
975
|
+
var IMAGE_SUBFIELDS = [
|
|
976
|
+
"FileName",
|
|
977
|
+
"ContentType",
|
|
978
|
+
"Content"
|
|
979
|
+
];
|
|
980
|
+
var imageInner = (value) => {
|
|
981
|
+
if (typeof value !== "object" || Array.isArray(value)) return scalar(value);
|
|
982
|
+
const parts = value;
|
|
983
|
+
return IMAGE_SUBFIELDS.filter((sub) => parts[sub] !== void 0).map((sub) => `<${sub}>${escapeXml(String(parts[sub]))}</${sub}>`).join("");
|
|
984
|
+
};
|
|
985
|
+
var invalidValue = (alias, type, value, cause) => new PortersConfigError(
|
|
986
|
+
`${alias}: cannot write ${JSON.stringify(value)} as ${type}`,
|
|
987
|
+
{
|
|
988
|
+
category: "validation",
|
|
989
|
+
hint: `${type} values are written in ISO 8601 (e.g. "2026-09-10" / "2026-09-10T12:00:00Z"); the library converts them to PORTERS' format.`,
|
|
990
|
+
// The underlying RangeError stays on `cause` rather than in the message: the message
|
|
991
|
+
// already names the field, the value and the type, which is what a reader needs.
|
|
992
|
+
context: { operation: "encode" },
|
|
993
|
+
cause
|
|
994
|
+
}
|
|
995
|
+
);
|
|
996
|
+
var converted2 = (alias, type, value, convert) => {
|
|
997
|
+
try {
|
|
998
|
+
return convert();
|
|
999
|
+
} catch (cause) {
|
|
1000
|
+
throw invalidValue(alias, type, value, cause);
|
|
1001
|
+
}
|
|
1002
|
+
};
|
|
1003
|
+
var encodeField = (type, value, alias) => {
|
|
1004
|
+
switch (type) {
|
|
1005
|
+
// Option: the selected aliases as empty child elements. Canonical input is an
|
|
1006
|
+
// array (ADR-0017, symmetric with read); a lone string is wrapped as a 1-element
|
|
1007
|
+
// selection (fail-safe).
|
|
1008
|
+
case "Option":
|
|
1009
|
+
return (Array.isArray(value) ? value : [text(value)]).map((alias2) => `<${alias2}/>`).join("");
|
|
1010
|
+
// System[DateTime] (registration/update) is Write-restricted by PORTERS; we still
|
|
1011
|
+
// serialize it identically — rejecting the write is the input type's job (SD-3).
|
|
1012
|
+
case "DateTime":
|
|
1013
|
+
case "System[DateTime]":
|
|
1014
|
+
return scalar(
|
|
1015
|
+
converted2(alias, type, value, () => isoToPortersDateTime(text(value)))
|
|
1016
|
+
);
|
|
1017
|
+
// Age shares Date's wire format (`yyyy/mm/dd`): we write the birthdate.
|
|
1018
|
+
case "Date":
|
|
1019
|
+
case "Age":
|
|
1020
|
+
return scalar(
|
|
1021
|
+
converted2(alias, type, value, () => isoToPortersDate(text(value)))
|
|
1022
|
+
);
|
|
1023
|
+
// Image: the three nested sub-elements (ADR-0064 論点3).
|
|
1024
|
+
case "Image":
|
|
1025
|
+
return imageInner(value);
|
|
1026
|
+
// System[Id] / Number / User & System[Reference] / Link (all ID-only) / string Data Types all
|
|
1027
|
+
// serialize as a scalar (the string types stay distinct labels per ADR-0016).
|
|
1028
|
+
// Link の Read は 3 形の union だが、Write は ID ひとつ(`<Alias>10001</Alias>`)= User と同じ。
|
|
1029
|
+
// System[Department] は静的な Write 入力から外してあるので、ここに来るのは cast 経由のみ
|
|
1030
|
+
// (System[DateTime] と同じ扱い)。到達したときは User と同じくスカラとして書き出す。
|
|
1031
|
+
case "Link":
|
|
1032
|
+
case "System[Id]":
|
|
1033
|
+
case "Number":
|
|
1034
|
+
case "User":
|
|
1035
|
+
case "System[Reference]":
|
|
1036
|
+
case "System[Department]":
|
|
1037
|
+
case "SinglelineText":
|
|
1038
|
+
case "MultilineText":
|
|
1039
|
+
case "Mail":
|
|
1040
|
+
case "Telephone":
|
|
1041
|
+
case "URL":
|
|
1042
|
+
return scalar(value);
|
|
1043
|
+
}
|
|
1044
|
+
};
|
|
1045
|
+
var encodeItem = (prefix, fields, item) => {
|
|
1046
|
+
const parts = [];
|
|
1047
|
+
for (const [alias, value] of Object.entries(item)) {
|
|
1048
|
+
if (value === null || value === void 0) continue;
|
|
1049
|
+
const type = fields.get(alias);
|
|
1050
|
+
const inner = type === void 0 || type === null ? scalar(value) : encodeField(type, value, alias);
|
|
1051
|
+
const tag2 = qualify(prefix, alias);
|
|
1052
|
+
parts.push(`<${tag2}>${inner}</${tag2}>`);
|
|
1053
|
+
}
|
|
1054
|
+
return parts.join("");
|
|
1055
|
+
};
|
|
1056
|
+
var encodeWriteItem = (prefix, fields, item) => `<Item>${encodeItem(prefix, fields, item)}</Item>`;
|
|
1057
|
+
var buildWriteXml = (config) => {
|
|
1058
|
+
const items = config.items.map((item) => encodeWriteItem(config.prefix, config.fields, item)).join("");
|
|
1059
|
+
return `<${config.resource}>${items}</${config.resource}>`;
|
|
1060
|
+
};
|
|
1061
|
+
|
|
1056
1062
|
// src/resources/query.ts
|
|
1057
1063
|
var KEYWORDS_MAX_CHARS = 100;
|
|
1058
1064
|
var DELETED_CONDITION_FIELDS = /* @__PURE__ */ new Set([
|
|
@@ -2698,6 +2704,7 @@ var CUSTOM_ALIAS = /^[UA]_/;
|
|
|
2698
2704
|
var classify = (alias, fieldType) => {
|
|
2699
2705
|
if (fieldType === null) {
|
|
2700
2706
|
return {
|
|
2707
|
+
// Stryker disable next-line StringLiteral: equivalent — the caller only tests for "declarable", so any other tag routes the same way
|
|
2701
2708
|
kind: "undeclarable",
|
|
2702
2709
|
entry: { alias, fieldType, reason: "unknown-field-type" }
|
|
2703
2710
|
};
|
|
@@ -2706,18 +2713,21 @@ var classify = (alias, fieldType) => {
|
|
|
2706
2713
|
const dataType = dataTypeOfFieldType(fieldType);
|
|
2707
2714
|
if (dataType === void 0) {
|
|
2708
2715
|
return {
|
|
2716
|
+
// Stryker disable next-line StringLiteral: equivalent — the caller only tests for "declarable", so any other tag routes the same way
|
|
2709
2717
|
kind: "undeclarable",
|
|
2710
2718
|
entry: { alias, fieldType, reason: "unknown-field-type" }
|
|
2711
2719
|
};
|
|
2712
2720
|
}
|
|
2713
2721
|
if (dataType === null) {
|
|
2714
2722
|
return {
|
|
2723
|
+
// Stryker disable next-line StringLiteral: equivalent — the caller only tests for "declarable", so any other tag routes the same way
|
|
2715
2724
|
kind: "undeclarable",
|
|
2716
2725
|
entry: { alias, fieldType, label, reason: "no-data-type" }
|
|
2717
2726
|
};
|
|
2718
2727
|
}
|
|
2719
2728
|
if (!isDeclarable(dataType)) {
|
|
2720
2729
|
return {
|
|
2730
|
+
// Stryker disable next-line StringLiteral: equivalent — the caller only tests for "declarable", so any other tag routes the same way
|
|
2721
2731
|
kind: "undeclarable",
|
|
2722
2732
|
entry: { alias, fieldType, label, reason: "not-declarable" }
|
|
2723
2733
|
};
|
|
@@ -2772,7 +2782,10 @@ var undeclarableNote = (entry) => {
|
|
|
2772
2782
|
};
|
|
2773
2783
|
var resourceBlock = (catalog, includeNames) => {
|
|
2774
2784
|
const entries = Object.entries(catalog.fields).sort(
|
|
2775
|
-
([a], [b]) =>
|
|
2785
|
+
([a], [b]) => (
|
|
2786
|
+
// Stryker disable next-line EqualityOperator: equivalent — object keys are unique, so the tie branch cannot occur
|
|
2787
|
+
a < b ? -1 : 1
|
|
2788
|
+
)
|
|
2776
2789
|
);
|
|
2777
2790
|
const declarations = entries.map(([alias, dataType]) => {
|
|
2778
2791
|
const name = includeNames ? catalog.names[alias] : void 0;
|
|
@@ -2909,6 +2922,7 @@ export {
|
|
|
2909
2922
|
createThrottle,
|
|
2910
2923
|
defineFields,
|
|
2911
2924
|
generateFieldDecls,
|
|
2925
|
+
rawValue,
|
|
2912
2926
|
readCustomCatalog,
|
|
2913
2927
|
verifyFields
|
|
2914
2928
|
};
|