@joymerrevent/porters-connect 0.6.0 → 0.6.2

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,22 @@
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [0.6.2] - 2026-07-19
9
+
10
+ ### Changed
11
+
12
+ - **サプライチェーン強靭化(CI/CD)**: 全 GitHub Actions ワークフローの `uses:` を**タグから 40 桁コミット SHA にピン留め**(版コメント付きで Dependabot が SHA+版を追従更新)。
13
+ あわせて **OpenSSF Scorecard** ワークフロー(`scorecard.yml`)を追加し、結果を code scanning(SARIF)へ+OpenSSF へ公開。いずれも **CI/リポジトリ側の変更で、公開される挙動・型には影響しません**。
14
+ - README に **OpenSSF Scorecard バッジ**を追加。
15
+
16
+ ## [0.6.1] - 2026-07-19
17
+
18
+ ### Changed
19
+
20
+ - **最低要求 `fast-xml-parser` を `^5.10.1` に引き上げ**(従来 `^5.9.2`)。5.10.1 は複数 DOCTYPE 宣言の拒否など
21
+ パース面の硬化を含みます(公開 API は不変)。あわせて内部の Prettier 3.9.5 追従整形・CI(`actions/setup-node@7`)・
22
+ 開発依存の更新を取り込み。いずれも公開される挙動・型には影響しません。
23
+
8
24
  ## [0.6.0] - 2026-07-01
9
25
 
10
26
  ### Added
@@ -124,7 +140,9 @@
124
140
  [oauth-guide]: docs/guide/oauth.md
125
141
  [kac]: https://keepachangelog.com/en/1.1.0/
126
142
  [semver]: https://semver.org/
127
- [unreleased]: https://github.com/Joymerrevent/porters-connect/compare/v0.6.0...HEAD
143
+ [unreleased]: https://github.com/Joymerrevent/porters-connect/compare/v0.6.2...HEAD
144
+ [0.6.2]: https://github.com/Joymerrevent/porters-connect/compare/v0.6.1...v0.6.2
145
+ [0.6.1]: https://github.com/Joymerrevent/porters-connect/compare/v0.6.0...v0.6.1
128
146
  [0.6.0]: https://github.com/Joymerrevent/porters-connect/compare/v0.5.0...v0.6.0
129
147
  [0.5.0]: https://github.com/Joymerrevent/porters-connect/compare/v0.4.0...v0.5.0
130
148
  [0.4.0]: https://github.com/Joymerrevent/porters-connect/compare/v0.3.0...v0.4.0
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]
3
+ [![npm version][npm-badge]][npm] [![License: MIT][mit-badge]][mit] ![Node >= 20][node-badge] [![OpenSSF Scorecard][scorecard-badge]][scorecard]
4
4
 
5
5
  PORTERS Connect API(旧 HRBC)を **TypeScript から型安全・簡単に**扱うための、
6
6
  [Joymerrevent(ジョイメリベント)][joymerrevent] 製の **非公式(unofficial)** ラッパーです。
@@ -370,6 +370,8 @@ try {
370
370
  [mit]: ./LICENSE
371
371
  [mit-badge]: https://img.shields.io/badge/License-MIT-blue.svg
372
372
  [node-badge]: https://img.shields.io/badge/node-%3E%3D20-brightgreen.svg
373
+ [scorecard]: https://scorecard.dev/viewer/?uri=github.com/Joymerrevent/porters-connect
374
+ [scorecard-badge]: https://api.scorecard.dev/projects/github.com/Joymerrevent/porters-connect/badge
373
375
  [joymerrevent]: https://github.com/Joymerrevent
374
376
  [contributing]: ./CONTRIBUTING.md
375
377
  [security]: ./SECURITY.md
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors/porters-error.ts","../src/errors/classify.ts","../src/xml/parser.ts","../src/xml/raw.ts","../src/auth/memory-store.ts","../src/auth/token-exchange.ts","../src/auth/token-provider.ts","../src/auth/auth-api.ts","../src/http/fetch-transport.ts","../src/http/mock-transport.ts","../src/http/throttle.ts","../src/http/retry.ts","../src/http/requester.ts","../src/util/datetime.ts","../src/xml/encode.ts","../src/xml/decode.ts","../src/resources/read-core.ts","../src/resources/query.ts","../src/resources/bulk-write.ts","../src/resources/resource.ts","../src/resources/candidate.ts","../src/resources/job.ts","../src/resources/client.ts","../src/resources/process.ts","../src/resources/resume.ts","../src/resources/attachment.ts","../src/resources/partition.ts","../src/resources/user.ts","../src/resources/field.ts","../src/resources/option.ts","../src/client.ts","../src/fields/define-fields.ts","../src/util/base64.ts"],"sourcesContent":["// PortersError hierarchy (ADR-0006): source-split subclasses + a cross-cutting\n// `category`. Never swallow errors; always surface a PortersError.\n\n/** Cross-cutting classification shared by every PORTERS error. */\nexport type ErrorCategory =\n | \"auth\"\n | \"permission\"\n | \"validation\"\n | \"notFound\"\n | \"conflict\"\n // 予約(現状どの分類関数も produce しない)。PORTERS はレート超過時に判別可能なコードを\n // 返さず接続を切るため、強制切断は PortersNetworkError(category \"network\")として表面化する。\n // 将来 429 相当の判別手段が得られたら配線するため型には残す(RV-3)。\n | \"rateLimit\"\n | \"transient\"\n | \"network\"\n | \"server\"\n | \"config\"\n | \"unknown\";\n\n/** Where the failing call was aimed (for self-service debugging). */\nexport type PortersErrorContext = {\n resource?: string;\n operation?: string;\n partition?: number;\n};\n\n/** Construction options for {@link PortersError}. */\nexport type PortersErrorOptions = {\n category: ErrorCategory;\n /** PORTERS raw code; `null` for network/transport failures. */\n code?: number | null;\n retryable?: boolean;\n /** Actionable hint (English by default). */\n hint?: string;\n httpStatus?: number;\n context?: PortersErrorContext;\n cause?: unknown;\n};\n\n/** Base class for every PORTERS-originated error (catch-all). */\nexport class PortersError extends Error {\n readonly category: ErrorCategory;\n readonly code: number | null;\n readonly retryable: boolean;\n readonly hint?: string;\n readonly httpStatus?: number;\n readonly context?: PortersErrorContext;\n\n constructor(message: string, options: PortersErrorOptions) {\n super(\n message,\n options.cause === undefined ? undefined : { cause: options.cause },\n );\n this.name = new.target.name;\n this.category = options.category;\n this.code = options.code ?? null;\n this.retryable = options.retryable ?? false;\n this.hint = options.hint;\n this.httpStatus = options.httpStatus;\n this.context = options.context;\n }\n}\n\n/** OAuth / Token errors. */\nexport class PortersAuthError extends PortersError {}\n\n/** Resource API errors. */\nexport class PortersResourceError extends PortersError {}\n\n/** Connection / timeout / forced rate-limit disconnect. */\nexport class PortersNetworkError extends PortersError {}\n\n/** Misconfiguration / misuse — not PORTERS-originated; thrown synchronously. */\nexport class PortersConfigError extends PortersError {}\n","// Code -> category -> retryable classification and PortersError factories\n// (ADR-0006 / result-codes.md). Unknown codes fall through to `category:\n// \"unknown\"` — never swallowed (fail-safe).\n\nimport {\n PortersAuthError,\n PortersNetworkError,\n PortersResourceError,\n type ErrorCategory,\n type PortersErrorContext,\n} from \"./porters-error\";\n\nconst RESOURCE_VALIDATION = new Set([8, 124, 126, 127, 133, 146, 500]);\n\n/** Resource API `<Code>` -> category (ADR-0006). */\nexport const resourceCategory = (code: number): ErrorCategory => {\n if (code === 9 || code === 302) return \"transient\";\n if (code === 401 || code === 402) return \"auth\";\n if (\n code === 6 ||\n code === 400 ||\n code === 403 ||\n code === 406 ||\n code === 601\n )\n return \"permission\";\n if (code === 7 || code === 404) return \"notFound\";\n if (code === 301 || code === 303 || code === 304) return \"conflict\";\n if (code === 1000) return \"server\";\n if (RESOURCE_VALIDATION.has(code) || (code >= 100 && code <= 116))\n return \"validation\";\n return \"unknown\";\n};\n\n/** Authentication API `<Error>` -> category (ADR-0006). */\nexport const authCategory = (code: number): ErrorCategory => {\n if (code === 400) return \"auth\";\n if ([401, 103, 104, 105, 106, 107, 109, 114, 117].includes(code))\n return \"auth\";\n if ([100, 101, 102, 110, 112].includes(code)) return \"validation\";\n if ([111, 115, 116, 402].includes(code)) return \"permission\";\n if (code === 108) return \"server\";\n return \"unknown\";\n};\n\nconst resourceHint = (code: number): string | undefined => {\n if (code === 403)\n return \"No data permission. Run the initial browser `code` grant for this Company DB, or check scopes.\";\n if (code === 404)\n return \"Partition not found or outside the contract period. Verify the partition id.\";\n return undefined;\n};\n\n/** Build a PortersResourceError from a Resource API `<Code>`. */\nexport const resourceError = (\n code: number,\n message: string,\n context?: PortersErrorContext,\n): PortersResourceError => {\n const category = resourceCategory(code);\n return new PortersResourceError(message, {\n category,\n code,\n retryable: category === \"transient\",\n hint: resourceHint(code),\n context,\n });\n};\n\n/** Build a PortersAuthError from an Authentication API `<Error>`. */\nexport const authError = (code: number, message: string): PortersAuthError => {\n const category = authCategory(code);\n return new PortersAuthError(message, {\n category,\n code,\n retryable: false,\n hint:\n category === \"auth\"\n ? \"Authentication failed; re-authenticate (browser `code` grant) or check app credentials.\"\n : undefined,\n });\n};\n\n/** Build a PortersNetworkError (no PORTERS code; retryable for idempotent ops). */\nexport const networkError = (\n message: string,\n cause?: unknown,\n): PortersNetworkError =>\n new PortersNetworkError(message, {\n category: \"network\",\n retryable: true,\n cause,\n });\n","// XML parsing + error routing (ADR-0011). The parser returns raw strings\n// (`parseTagValue: false`); all type coercion happens in `decode.ts`.\n\nimport { XMLParser } from \"fast-xml-parser\";\n\nimport { authError, resourceError } from \"../errors/classify\";\nimport { PortersAuthError, PortersResourceError } from \"../errors/index\";\nimport { asArray, asRecord, asString } from \"./raw\";\n\nconst parser = new XMLParser({\n ignoreAttributes: false,\n attributeNamePrefix: \"@_\",\n ignoreDeclaration: true,\n parseTagValue: false,\n parseAttributeValue: false,\n trimValues: true,\n // asArray() already normalizes a single/missing/repeated <Item> into an array,\n // so isArray is belt-and-suspenders: these mutants are equivalent (no test can\n // observe the difference once asArray() runs).\n // Stryker disable next-line ArrowFunction,ConditionalExpression,StringLiteral: equivalent — asArray() normalizes regardless\n isArray: (name) => name === \"Item\",\n});\n\n// fast-xml-parser yields raw strings; coerce an attribute/code node to an int,\n// treating a missing node as 0. The explicit `undefined` check keeps the\n// fallback observable — `Number(\"\") === 0`, so a `?? \"0\"` default would be an\n// equivalent mutant.\nconst toInt = (v: unknown): number => {\n const s = asString(v);\n return s === undefined ? 0 : Number(s);\n};\n\n/** One `<Item>`: a map of field alias -> raw node (string or nested object). */\nexport type RawItem = Record<string, unknown>;\n\nexport type ResourcePage = {\n total: number;\n count: number;\n start: number;\n items: RawItem[];\n};\n\n/**\n * Parse a Resource Read response. Reads `<Code>` first and, if non-zero, throws\n * the mapped PortersError (ADR-0006) — HTTP 200 + `<Code>≠0` is an error, not\n * data.\n */\nexport const parseResourcePage = (xml: string): ResourcePage => {\n const root = asRecord(parser.parse(xml) as unknown);\n const rootKey = root ? Object.keys(root)[0] : undefined;\n // `root` is always a record here and `root[rootKey]` is undefined exactly when\n // rootKey is, so dropping/forcing either guard collapses to the same throw.\n // Stryker disable next-line ConditionalExpression,LogicalOperator: equivalent — both branches converge on the unparseable throw\n const body = root && rootKey ? asRecord(root[rootKey]) : undefined;\n if (!body) {\n throw new PortersResourceError(\"unparseable resource response\", {\n category: \"unknown\",\n });\n }\n\n const code = toInt(body.Code);\n if (code !== 0) {\n throw resourceError(code, `resource returned code ${code}`, {\n resource: rootKey,\n });\n }\n\n return {\n total: toInt(body[\"@_Total\"]),\n count: toInt(body[\"@_Count\"]),\n start: toInt(body[\"@_Start\"]),\n items: asArray(body.Item).map((it) => asRecord(it) ?? {}),\n };\n};\n\n/** One written record's outcome: the assigned/updated `Id` and its Result `Code`. */\nexport type WriteResultItem = {\n id: number;\n code: number;\n};\n\n/**\n * Parse a Resource Write response. Unlike Read there is no root `<Code>` nor\n * Total/Count/Start: each `<Item>` carries its own `<Id>` (assigned on create /\n * echoed on update) and `<Code>` (per-item Result Code). Applying the per-item\n * code policy (throw on `!= 0`) is the accessor's job, since a bulk write mixes\n * successes and failures — see write-format.md.\n */\nexport const parseWriteResult = (xml: string): WriteResultItem[] => {\n const root = asRecord(parser.parse(xml) as unknown);\n const rootKey = root ? Object.keys(root)[0] : undefined;\n // Same equivalence as parseResourcePage: both guards converge on the throw.\n // Stryker disable next-line ConditionalExpression,LogicalOperator: equivalent — both branches converge on the unparseable throw\n const body = root && rootKey ? asRecord(root[rootKey]) : undefined;\n if (!body) {\n throw new PortersResourceError(\"unparseable write response\", {\n category: \"unknown\",\n });\n }\n\n return asArray(body.Item).map((it) => {\n const item = asRecord(it) ?? {};\n return { id: toInt(item.Id), code: toInt(item.Code) };\n });\n};\n\n/** Parsed `<Authentication>` response (OAuth `code_direct` / Token). */\nexport type AuthResponse = {\n code?: string;\n accessToken?: string;\n accessTokenExpiresIn?: number;\n refreshToken?: string;\n refreshTokenExpiresIn?: number;\n};\n\n/**\n * Parse an `<Authentication>` response. Reads `<Error>` first and, if non-zero,\n * throws the mapped PortersAuthError (ADR-0006).\n */\nexport const parseAuthentication = (xml: string): AuthResponse => {\n const root = asRecord(parser.parse(xml) as unknown);\n const body = root ? asRecord(root.Authentication) : undefined;\n if (!body) {\n throw new PortersAuthError(\"unparseable authentication response\", {\n category: \"unknown\",\n });\n }\n\n const error = toInt(body.Error);\n if (error !== 0) {\n throw authError(\n error,\n asString(body.Message) ?? `authentication error ${error}`,\n );\n }\n\n const num = (v: unknown): number | undefined => {\n const s = asString(v);\n return s === undefined ? undefined : Number(s);\n };\n return {\n code: asString(body.Code),\n accessToken: asString(body.AccessToken),\n accessTokenExpiresIn: num(body.AccessTokenExpiresIn),\n refreshToken: asString(body.RefreshToken),\n refreshTokenExpiresIn: num(body.RefreshTokenExpiresIn),\n };\n};\n","// Narrowing helpers for fast-xml-parser output. The parser is typed as `any`;\n// we launder it through `unknown` and narrow here so we never spread `any`.\n\nexport const asRecord = (v: unknown): Record<string, unknown> | undefined =>\n typeof v === \"object\" && v !== null && !Array.isArray(v)\n ? (v as Record<string, unknown>)\n : undefined;\n\nexport const asString = (v: unknown): string | undefined =>\n typeof v === \"string\" ? v : undefined;\n\n/** Normalize a node that may be missing, single, or repeated into an array. */\nexport const asArray = (v: unknown): unknown[] => {\n if (Array.isArray(v)) return v;\n return v === undefined || v === null ? [] : [v];\n};\n","import type { StoredTokens, TokenStore } from \"./types\";\n\n/** Default in-process token store (single instance; lost on restart). */\nexport const createMemoryTokenStore = (): TokenStore => {\n let tokens: StoredTokens | undefined;\n return {\n get: () => Promise.resolve(tokens),\n set: (t) => {\n tokens = t;\n return Promise.resolve();\n },\n clear: () => {\n tokens = undefined;\n return Promise.resolve();\n },\n };\n};\n","// Shared OAuth token exchange against `POST /v1/token` (ADR-0034 F-1 / ADR-0007).\n// Used by both the default transparent provider (code_direct grant) and the public\n// auth API's browser `code` exchange — they POST the same form and parse the same\n// <Authentication> envelope, so the logic lives here once. The App Secret only ever\n// rides the POST body (ADR-0034 SD-9), never a URL/log.\n\nimport { PortersAuthError } from \"../errors/index\";\nimport type { Transport } from \"../http/index\";\nimport { parseAuthentication } from \"../xml/parser\";\nimport type { StoredTokens } from \"./types\";\n\n/** Credentials + seams shared by every token exchange. */\nexport type TokenExchangeDeps = {\n host: string;\n appId: string;\n appSecret: string;\n transport: Transport;\n /** Clock for converting relative expiry (ms) to an absolute epoch (ADR-0012). */\n now: () => number;\n};\n\n/** OAuth grant kinds the Token endpoint accepts (token.md). */\nexport type TokenGrantType = \"oauth_code\" | \"refresh_token\";\n\n/**\n * Exchange an OAuth `code` (new grant) or a Refresh Token (renewal) for tokens via\n * `POST {host}/v1/token`. The relative `*ExpiresIn` (ms) is converted to an absolute\n * epoch at receipt (clock-skew tolerant — ADR-0012). Throws {@link PortersAuthError}\n * when the envelope reports an error (`<Error>≠0`, via the parser) or omits a token.\n */\nexport const exchangeToken = async (\n deps: TokenExchangeDeps,\n grantType: TokenGrantType,\n code: string,\n): Promise<StoredTokens> => {\n const body = new URLSearchParams({\n app_id: deps.appId,\n secret: deps.appSecret,\n grant_type: grantType,\n code,\n }).toString();\n const res = await deps.transport.send({\n method: \"POST\",\n url: `https://${deps.host}/v1/token`,\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body,\n });\n const a = parseAuthentication(res.body);\n if (a.accessToken === undefined || a.refreshToken === undefined) {\n throw new PortersAuthError(\"token response missing tokens\", {\n category: \"auth\",\n });\n }\n return {\n accessToken: a.accessToken,\n refreshToken: a.refreshToken,\n accessTokenExpiresAt: deps.now() + (a.accessTokenExpiresIn ?? 0),\n refreshTokenExpiresAt: deps.now() + (a.refreshTokenExpiresIn ?? 0),\n };\n};\n","// Default transparent TokenProvider (ADR-0007 / ADR-0012): code_direct -> token,\n// cache, hybrid refresh (proactive margin + on-demand), in-process single-flight.\n// Factory style per ADR-0013. Exposes internal cache/clear so the public auth API\n// (ADR-0034 F-1) can save a browser-`code` exchange and locally forget tokens.\n\nimport { PortersAuthError } from \"../errors/index\";\nimport type { Transport } from \"../http/index\";\nimport { parseAuthentication } from \"../xml/parser\";\nimport { createMemoryTokenStore } from \"./memory-store\";\nimport { exchangeToken } from \"./token-exchange\";\nimport type { StoredTokens, TokenProvider, TokenStore } from \"./types\";\n\nexport type DefaultTokenProviderOptions = {\n host: string;\n appId: string;\n appSecret: string;\n transport: Transport;\n /** Token persistence; defaults to in-memory. */\n tokenStore?: TokenStore;\n /** Refresh this many ms before expiry (proactive). Default 60s. */\n refreshMarginMs?: number;\n /** Injectable clock (tests). Default `Date.now`. */\n now?: () => number;\n};\n\n/**\n * The default provider plus internal controls used by the public auth API\n * (ADR-0034 SD-8): {@link DefaultTokenProvider.cache} saves externally-acquired\n * tokens (browser `code` exchange) to the in-memory cache + token store;\n * {@link DefaultTokenProvider.clear} forgets them (local revoke). Deliberately *not*\n * part of the public\n * {@link TokenProvider} contract — a custom strategy supplies neither.\n */\nexport type DefaultTokenProvider = TokenProvider & {\n cache(tokens: StoredTokens): Promise<void>;\n clear(): Promise<void>;\n};\n\nconst DEFAULT_MARGIN_MS = 60_000;\n\nexport const createDefaultTokenProvider = (\n opts: DefaultTokenProviderOptions,\n): DefaultTokenProvider => {\n const store = opts.tokenStore ?? createMemoryTokenStore();\n const margin = opts.refreshMarginMs ?? DEFAULT_MARGIN_MS;\n const now = opts.now ?? (() => Date.now());\n\n let cached: StoredTokens | undefined;\n let inflight: Promise<StoredTokens> | undefined;\n\n const accessValid = (t: StoredTokens | undefined): t is StoredTokens =>\n t !== undefined && now() < t.accessTokenExpiresAt - margin;\n\n const canRefresh = (t: StoredTokens | undefined): t is StoredTokens =>\n t !== undefined && now() < t.refreshTokenExpiresAt - margin;\n\n // Cache + persist freshly minted tokens so the next call (and other instances) reuse them.\n const save = async (tokens: StoredTokens): Promise<StoredTokens> => {\n cached = tokens;\n await store.set(tokens);\n return tokens;\n };\n\n const exchange = async (\n grantType: \"oauth_code\" | \"refresh_token\",\n code: string,\n ): Promise<StoredTokens> =>\n save(\n await exchangeToken(\n {\n host: opts.host,\n appId: opts.appId,\n appSecret: opts.appSecret,\n transport: opts.transport,\n now,\n },\n grantType,\n code,\n ),\n );\n\n // code_direct -> token (initial acquisition; requires prior browser grant).\n const acquire = async (): Promise<StoredTokens> => {\n const url =\n `https://${opts.host}/v1/oauth` +\n `?app_id=${encodeURIComponent(opts.appId)}&response_type=code_direct`;\n const res = await opts.transport.send({ method: \"GET\", url, headers: {} });\n const { code } = parseAuthentication(res.body);\n if (code === undefined) {\n throw new PortersAuthError(\"code_direct returned no code\", {\n category: \"auth\",\n });\n }\n return exchange(\"oauth_code\", code);\n };\n\n const renew = async (): Promise<StoredTokens> => {\n if (cached === undefined) cached = await store.get();\n if (canRefresh(cached)) {\n return exchange(\"refresh_token\", cached.refreshToken);\n }\n return acquire();\n };\n\n const ensure = (forceRefresh: boolean): Promise<StoredTokens> => {\n if (!forceRefresh && accessValid(cached)) return Promise.resolve(cached);\n return (inflight ??= renew().finally(() => {\n inflight = undefined;\n }));\n };\n\n return {\n getAccessToken: async (o) =>\n (await ensure(o?.forceRefresh ?? false)).accessToken,\n cache: async (tokens) => {\n await save(tokens);\n },\n clear: async () => {\n cached = undefined;\n await store.clear();\n },\n };\n};\n","// Public OAuth surface `porters.auth.*` (ADR-0034 F-1 / ADR-0007 SD-3/SD-6). A thin\n// facade over the active token provider: it builds the browser `code` / `remove` URLs,\n// exchanges a redirect `?code=` for tokens (saving them into the default strategy),\n// warms up / inspects the token, and locally forgets tokens. Credential- and\n// default-strategy-dependent methods fail fast with a PortersConfigError under a custom\n// auth strategy (ADR-0034 SD-7). Factory style per ADR-0013; the App Secret never leaves\n// the Token POST body (SD-9).\n\nimport { PortersConfigError } from \"../errors/index\";\nimport type { Transport } from \"../http/index\";\nimport type { Scope } from \"../types/index\";\nimport { exchangeToken } from \"./token-exchange\";\nimport type { StoredTokens, TokenProvider } from \"./types\";\n\n/** Shared options for the browser `code` / `remove` OAuth URLs (oauth.md). */\nexport type AuthorizationUrlOptions = {\n /** Registered Redirect URL the browser returns to (required for code/remove). */\n redirectUrl: string;\n /** Scopes to grant/remove; defaults to the client's configured `scopes`. */\n scopes?: Scope[];\n /** Opaque value echoed back on redirect (e.g. CSRF defense). */\n state?: string;\n};\n\n/** Options for the `remove` (de-authorization) browser URL. */\nexport type RevokeUrlOptions = AuthorizationUrlOptions;\n\n/**\n * The `porters.auth.*` surface (ADR-0007 SD-3/SD-6). The initial per-Company-DB grant\n * needs a human to open {@link AuthApi.authorizationUrl} in a browser and consent; the\n * library only builds the URL and exchanges the returned `code`. Day-to-day token\n * acquisition/refresh stays transparent (the default strategy), so most callers never\n * touch this surface.\n */\nexport type AuthApi = {\n /** Build the browser `code`-grant URL to open for the initial permission grant. */\n authorizationUrl(opts: AuthorizationUrlOptions): string;\n /**\n * Exchange a redirect `?code=` for tokens and save them into the default strategy.\n * Resolves `void` on success (tokens are stored internally — inspect via\n * {@link AuthApi.getToken}); throws on failure: {@link PortersConfigError} (missing\n * credentials / custom strategy), `PortersAuthError` (token-endpoint error or expired\n * code), or `PortersNetworkError`.\n */\n exchangeAuthorizationCode(code: string): Promise<void>;\n /**\n * Build the browser `remove`-grant URL to open for server-side de-authorization.\n * PORTERS has no server-to-server removal, so completing it stays a browser step;\n * pair with {@link AuthApi.clearTokens} to drop the local copy.\n */\n revokeUrl(opts: RevokeUrlOptions): string;\n /** Forget cached + stored tokens locally. Does not de-authorize server-side. */\n clearTokens(): Promise<void>;\n /** Acquire a token now (startup fail-fast / warm-up); throws if auth is unavailable. */\n ensureAuthenticated(): Promise<void>;\n /** Return the current valid Access Token (debug). The Refresh Token is never exposed. */\n getToken(): Promise<string>;\n};\n\n/** Internal save/forget controls, present only when the default provider is in use. */\nexport type AuthProviderControls = {\n cache(tokens: StoredTokens): Promise<void>;\n clear(): Promise<void>;\n};\n\nexport type AuthApiOptions = {\n host: string;\n appId?: string;\n appSecret?: string;\n scopes?: Scope[];\n transport: Transport;\n /** The active token provider (default or custom) backing ensure/getToken. */\n provider: TokenProvider;\n /** Present only for the default provider; absent under a custom strategy. */\n controls?: AuthProviderControls;\n /** Injectable clock (tests). Default `Date.now`. */\n now?: () => number;\n};\n\nexport const createAuthApi = (opts: AuthApiOptions): AuthApi => {\n const now = opts.now ?? (() => Date.now());\n\n const requireAppId = (): string => {\n if (!opts.appId) {\n throw new PortersConfigError(\"appId is required to build an OAuth URL\", {\n category: \"config\",\n hint: \"Set appId on PortersClient. A custom auth strategy that supplies its own tokens cannot run the browser grant.\",\n });\n }\n return opts.appId;\n };\n\n const requireDefaultStrategy = (method: string): AuthProviderControls => {\n if (opts.controls === undefined) {\n throw new PortersConfigError(\n `${method} is only available with the default auth strategy`,\n {\n category: \"config\",\n hint: \"Remove the custom `auth` strategy to let the library manage tokens, or perform this step in your own strategy.\",\n },\n );\n }\n return opts.controls;\n };\n\n const requireCredentials = (): { appId: string; appSecret: string } => {\n if (!opts.appId || !opts.appSecret) {\n throw new PortersConfigError(\n \"appId and appSecret are required to exchange an authorization code\",\n {\n category: \"config\",\n hint: \"Set appId/appSecret on PortersClient (the Token endpoint needs both).\",\n },\n );\n }\n return { appId: opts.appId, appSecret: opts.appSecret };\n };\n\n const resolveScopes = (scopes: Scope[] | undefined): Scope[] => {\n const resolved = scopes ?? opts.scopes ?? [];\n if (resolved.length === 0) {\n throw new PortersConfigError(\n \"at least one scope is required for the code/remove grant\",\n {\n category: \"config\",\n hint: \"Pass `scopes` to this call or configure `scopes` on PortersClient.\",\n },\n );\n }\n return resolved;\n };\n\n const buildOAuthUrl = (\n responseType: \"code\" | \"remove\",\n o: AuthorizationUrlOptions,\n ): string => {\n const params = new URLSearchParams({\n app_id: requireAppId(),\n redirect_url: o.redirectUrl,\n response_type: responseType,\n scope: resolveScopes(o.scopes).join(\",\"),\n });\n if (o.state !== undefined) params.set(\"state\", o.state);\n return `https://${opts.host}/v1/oauth?${params.toString()}`;\n };\n\n return {\n authorizationUrl: (o) => buildOAuthUrl(\"code\", o),\n revokeUrl: (o) => buildOAuthUrl(\"remove\", o),\n exchangeAuthorizationCode: async (code) => {\n const controls = requireDefaultStrategy(\"exchangeAuthorizationCode\");\n const { appId, appSecret } = requireCredentials();\n const tokens = await exchangeToken(\n { host: opts.host, appId, appSecret, transport: opts.transport, now },\n \"oauth_code\",\n code,\n );\n await controls.cache(tokens);\n },\n clearTokens: async () => {\n const controls = requireDefaultStrategy(\"clearTokens\");\n await controls.clear();\n },\n ensureAuthenticated: async () => {\n await opts.provider.getAccessToken();\n },\n getToken: () => opts.provider.getAccessToken(),\n };\n};\n","// Default fetch-based transport (ADR-0009). Thin: one request -> one response;\n// throttle/retry/auth live above it. Network/timeout -> PortersNetworkError.\n\nimport { PortersNetworkError } from \"../errors/index\";\nimport type { Transport } from \"./types\";\n\nexport type FetchTransportOptions = {\n timeoutMs?: number;\n /** Injectable fetch (tests / custom dispatcher). Default global fetch. */\n fetchImpl?: typeof fetch;\n};\n\nexport const createFetchTransport = (\n opts: FetchTransportOptions = {},\n): Transport => {\n const doFetch = opts.fetchImpl ?? fetch;\n const timeoutMs = opts.timeoutMs ?? 30_000;\n return {\n send: async (req) => {\n try {\n const res = await doFetch(req.url, {\n method: req.method,\n headers: req.headers,\n body: req.body,\n signal: AbortSignal.timeout(timeoutMs),\n });\n return { status: res.status, body: await res.text() };\n } catch (cause) {\n throw new PortersNetworkError(\"transport request failed\", {\n category: \"network\",\n retryable: true,\n cause,\n });\n }\n },\n };\n};\n","// Public mock transport for offline evaluation / unit tests (ADR-0024 / R-17 / R-12).\n// It targets the stable public `Transport` seam (not `fetch`), so it survives an internal\n// transport change. By default the OAuth code_direct + token endpoints are auto-answered,\n// so callers only mock resource XML; an unmocked route fails loud (fail-safe).\n\nimport { PortersConfigError } from \"../errors/index\";\nimport type { Transport, TransportRequest, TransportResponse } from \"./types\";\n\n/** A mock reply: an XML body string (HTTP 200), or an explicit status + body. */\nexport type MockReply = string | { status?: number; body: string };\n\n/**\n * Maps a request to a {@link MockReply}, or returns `undefined` for \"not mocked\". When `undefined`\n * is returned (and the request is not an auto-answered auth endpoint), the transport throws a\n * {@link PortersConfigError} naming the request, so an unmocked route surfaces instead of silently\n * returning an empty response.\n */\nexport type MockHandler = (request: TransportRequest) => MockReply | undefined;\n\n/** Options for {@link createMockTransport}. */\nexport type MockTransportOptions = {\n /**\n * Auto-answer the OAuth `code_direct` (`/v1/oauth`) and token (`/v1/token`) endpoints with valid\n * demo tokens, so callers only mock resource XML. Default `true`. Set `false` to handle the auth\n * endpoints in your own handler.\n */\n auth?: boolean;\n};\n\n// Default auth responses (mirrors the live envelope; expiry values are ms — see token-provider).\nconst AUTH_CODE_XML = `<Authentication><Code>mock-code</Code><Error>0</Error></Authentication>`;\nconst AUTH_TOKEN_XML =\n `<Authentication>` +\n `<AccessToken>mock-access-token</AccessToken><AccessTokenExpiresIn>1800000</AccessTokenExpiresIn>` +\n `<RefreshToken>mock-refresh-token</RefreshToken><RefreshTokenExpiresIn>7200000</RefreshTokenExpiresIn>` +\n `<Error>0</Error></Authentication>`;\n\nconst toResponse = (reply: MockReply): TransportResponse =>\n typeof reply === \"string\"\n ? { status: 200, body: reply }\n : { status: reply.status ?? 200, body: reply.body };\n\n// method + path だけで「どの route を足すか」は十分。既定 field を載せた Read URL の\n// クエリは長大でノイズなので落とす(不正な URL はそのまま出す=フェイルセーフ)。\nconst routeLabel = (method: string, url: string): string => {\n try {\n return `${method} ${new URL(url).pathname}`;\n } catch {\n return `${method} ${url}`;\n }\n};\n\n/**\n * Build a {@link Transport} that answers from a handler instead of the network — run the library\n * fully offline, with no PORTERS contract (R-17). Pass it as `new PortersClient({ transport })`.\n *\n * @example\n * const transport = createMockTransport((req) =>\n * req.url.includes(\"/v1/candidate\")\n * ? `<Candidate Total=\"0\" Count=\"0\" Start=\"0\"><Code>0</Code></Candidate>`\n * : undefined, // unmocked -> a clear PortersConfigError\n * );\n */\nexport const createMockTransport = (\n handler: MockHandler,\n options: MockTransportOptions = {},\n): Transport => {\n const autoAuth = options.auth ?? true;\n // Non-async on purpose: always return a Promise (resolve/reject) so an unmocked route rejects\n // rather than throwing synchronously — faithful to the Transport contract.\n return {\n send: (req) => {\n if (autoAuth && req.url.includes(\"/v1/token\")) {\n return Promise.resolve({ status: 200, body: AUTH_TOKEN_XML });\n }\n if (autoAuth && req.url.includes(\"/v1/oauth\")) {\n return Promise.resolve({ status: 200, body: AUTH_CODE_XML });\n }\n const reply = handler(req);\n if (reply === undefined) {\n return Promise.reject(\n new PortersConfigError(\n `createMockTransport: no mock response for ${routeLabel(req.method, req.url)} — add a case to your handler` +\n ` (or pass { auth: false } to mock the auth endpoints too)`,\n { category: \"config\" },\n ),\n );\n }\n return Promise.resolve(toResponse(reply));\n },\n };\n};\n","// Token-bucket throttle (ADR-0010): per-minute Read/Write limits at ~90% safety.\n// Bursts are allowed up to capacity; the average stays under the limit.\n\nconst sleep = (ms: number): Promise<void> =>\n new Promise((resolve) => setTimeout(resolve, ms));\n\nexport type Throttle = {\n take(write: boolean): Promise<void>;\n};\n\nexport type ThrottleOptions = {\n readPerMin?: number;\n writePerMin?: number;\n /** Fraction of the limit to actually use (headroom). Default 0.9. */\n safety?: number;\n now?: () => number;\n};\n\nconst makeBucket = (\n capacity: number,\n now: () => number,\n): (() => Promise<void>) => {\n const ratePerMs = capacity / 60_000;\n let tokens = capacity;\n let last = now();\n return async () => {\n for (;;) {\n const t = now();\n tokens = Math.min(capacity, tokens + (t - last) * ratePerMs);\n last = t;\n if (tokens >= 1) {\n tokens -= 1;\n return;\n }\n await sleep(Math.ceil((1 - tokens) / ratePerMs));\n }\n };\n};\n\nexport const createThrottle = (opts: ThrottleOptions = {}): Throttle => {\n const safety = opts.safety ?? 0.9;\n const now = opts.now ?? (() => Date.now());\n const read = makeBucket(Math.floor((opts.readPerMin ?? 2000) * safety), now);\n const write = makeBucket(Math.floor((opts.writePerMin ?? 500) * safety), now);\n return { take: (isWrite) => (isWrite ? write() : read()) };\n};\n","// Exponential backoff with full jitter (ADR-0010).\n\nexport type Backoff = (attempt: number) => number;\n\nexport const expoBackoff =\n (baseMs = 200, maxMs = 8_000): Backoff =>\n (attempt) =>\n Math.floor(Math.random() * Math.min(maxMs, baseMs * 2 ** attempt));\n","// Request pipeline (ADR-0009/0010/0012): throttle -> auth header -> transport,\n// with reactive token refresh (401/402) and bounded backoff retry. The\n// idempotency guard keeps non-idempotent writes (create) from double-applying.\n\nimport type { TokenProvider } from \"../auth/types\";\nimport {\n PortersConfigError,\n PortersError,\n PortersNetworkError,\n} from \"../errors/index\";\nimport type { Backoff } from \"./retry\";\nimport type { Throttle } from \"./throttle\";\nimport type { Transport, TransportRequest } from \"./types\";\n\nconst API_VERSION = \"2\";\n\n// docs/reference: keep a *whole* request under ~15000 chars (a larger payload 400s).\n// \"Whole\" is load-bearing: a write's body dominates, but a read's length lives in the\n// URL (field / condition) — and ADR-0020 makes a fieldless Read send the catalog default\n// field set, so that URL grew. A future 16KB cap is planned but undetermined — follow the\n// canonical value. Exported so the bulk-write chunker sizes each batch under the same cap\n// (ADR-0041) instead of relying on this guard to reject an oversized batch mid-run.\nexport const MAX_REQUEST_LENGTH = 15000;\n\nconst sleep = (ms: number): Promise<void> =>\n new Promise((resolve) => setTimeout(resolve, ms));\n\nconst withAuth = (\n req: TransportRequest,\n token: string,\n write: boolean,\n): TransportRequest => ({\n ...req,\n headers: {\n ...req.headers,\n \"X-porters-hrbc-oauth-token\": token,\n \"X-P-ConnectAPI-Version\": API_VERSION,\n ...(write ? { \"Content-Type\": \"application/xml; charset=UTF-8\" } : {}),\n },\n});\n\nexport type RequesterOptions = {\n transport: Transport;\n auth: TokenProvider;\n throttle: Throttle;\n backoff: Backoff;\n maxRetries?: number;\n};\n\nexport type RequestSpec = {\n /** Write (POST) uses the write throttle bucket. */\n write?: boolean;\n /** false for non-idempotent ops (create); not auto-retried on network uncertainty. */\n idempotent?: boolean;\n /** Skip the ~15000-char size guard (file uploads have their own limit; ADR-0018). */\n unboundedBody?: boolean;\n};\n\nexport type Requester = {\n request<T>(\n req: TransportRequest,\n parse: (body: string) => T,\n spec?: RequestSpec,\n ): Promise<T>;\n};\n\nexport const createRequester = (o: RequesterOptions): Requester => {\n const maxRetries = o.maxRetries ?? 3;\n\n const request = async <T>(\n req: TransportRequest,\n parse: (body: string) => T,\n spec: RequestSpec = {},\n ): Promise<T> => {\n // Eager size guard: block an oversized request before throttle / auth / transport.\n // A clear config error beats an opaque server 400, and we don't burn a throttle token\n // or a token refresh on a request that cannot succeed (fail-safe). PORTERS limits the\n // whole request, so measure URL + body: a write's body or a read's field/condition\n // query string can blow the cap (RV-5). File uploads opt out via `unboundedBody` (the\n // body has its own limit — ADR-0018; their write URL is short, so skipping is safe).\n const requestLength = req.url.length + (req.body?.length ?? 0);\n if (!spec.unboundedBody && requestLength > MAX_REQUEST_LENGTH) {\n throw new PortersConfigError(\n `request is ${requestLength} characters, over the ~${MAX_REQUEST_LENGTH}-character limit`,\n {\n category: \"config\",\n hint: \"Shorten the request: narrow a read's field/condition, or split a write into batches of 200 or fewer records (PORTERS caps a request at ~15000 characters).\",\n },\n );\n }\n const write = spec.write ?? false;\n const idempotent = spec.idempotent ?? !write;\n let authRetried = false;\n let forceRefresh = false;\n let attempt = 0;\n\n for (;;) {\n await o.throttle.take(write);\n try {\n const token = await o.auth.getAccessToken(\n forceRefresh ? { forceRefresh: true } : undefined,\n );\n forceRefresh = false;\n const res = await o.transport.send(withAuth(req, token, write));\n return parse(res.body);\n } catch (e) {\n if (!(e instanceof PortersError)) throw e;\n // reactive: token expired -> refresh once and retry (safe even for create).\n if ((e.code === 401 || e.code === 402) && !authRetried) {\n authRetried = true;\n forceRefresh = true;\n continue;\n }\n // idempotency guard: non-idempotent write + network-uncertain -> surface.\n if (e instanceof PortersNetworkError && write && !idempotent) throw e;\n // transient (9/302) / network -> bounded backoff.\n if (e.retryable && attempt < maxRetries) {\n attempt += 1;\n await sleep(o.backoff(attempt - 1));\n continue;\n }\n throw e;\n }\n }\n };\n\n return { request };\n};\n","// PORTERS datetime <-> ISO 8601 (UTC) normalization (PRD R-10 / ADR-0011).\n// DateTime `yyyy/mm/dd HH:MM:SS` (UTC) <-> ISO `...Z`\n// Date `yyyy/mm/dd` <-> date-only (no `Z`)\n// No business-timezone (e.g. JST) conversion — that is the caller's responsibility.\n\nconst DATETIME_RE = /^(\\d{4})\\/(\\d{2})\\/(\\d{2}) (\\d{2}):(\\d{2}):(\\d{2})$/;\nconst DATE_RE = /^(\\d{4})\\/(\\d{2})\\/(\\d{2})$/;\nconst ISO_DATE_RE = /^(\\d{4})-(\\d{2})-(\\d{2})/;\n\n/** PORTERS `yyyy/mm/dd HH:MM:SS` (UTC) -> ISO 8601 `...Z`. */\nexport const portersDateTimeToIso = (value: string): string => {\n const m = DATETIME_RE.exec(value);\n if (!m) throw new RangeError(`invalid PORTERS DateTime: \"${value}\"`);\n const iso = `${m[1]}-${m[2]}-${m[3]}T${m[4]}:${m[5]}:${m[6]}Z`;\n if (Number.isNaN(Date.parse(iso))) {\n throw new RangeError(`invalid PORTERS DateTime: \"${value}\"`);\n }\n return iso;\n};\n\n/** ISO 8601 (with `Z` or offset) -> PORTERS `yyyy/mm/dd HH:MM:SS` (UTC). */\nexport const isoToPortersDateTime = (value: string): string => {\n const t = Date.parse(value);\n if (Number.isNaN(t)) throw new RangeError(`invalid ISO datetime: \"${value}\"`);\n const d = new Date(t);\n const pad = (n: number): string => String(n).padStart(2, \"0\");\n return (\n `${d.getUTCFullYear()}/${pad(d.getUTCMonth() + 1)}/${pad(d.getUTCDate())} ` +\n `${pad(d.getUTCHours())}:${pad(d.getUTCMinutes())}:${pad(d.getUTCSeconds())}`\n );\n};\n\n/** PORTERS `yyyy/mm/dd` -> ISO date `yyyy-mm-dd` (no timezone). */\nexport const portersDateToIso = (value: string): string => {\n const m = DATE_RE.exec(value);\n if (!m) throw new RangeError(`invalid PORTERS Date: \"${value}\"`);\n return `${m[1]}-${m[2]}-${m[3]}`;\n};\n\n/** ISO date (or datetime) -> PORTERS `yyyy/mm/dd` (calendar date as-is, no shift). */\nexport const isoToPortersDate = (value: string): string => {\n const m = ISO_DATE_RE.exec(value);\n if (!m) throw new RangeError(`invalid ISO date: \"${value}\"`);\n return `${m[1]}/${m[2]}/${m[3]}`;\n};\n","// Data-Type-driven value encoding for Write (ADR-0011). Read and Write\n// representations are asymmetric: User/System[Reference] write the ID only, Option writes\n// `<Field><OptionAlias/></Field>`, and DateTime/Date go ISO -> PORTERS. This is the\n// mirror of decode.ts; it builds the request body so XML stays out of resources/.\n\nimport { isoToPortersDate, isoToPortersDateTime } from \"../util/datetime\";\nimport type { DataType } from \"./decode\";\n\n/**\n * A value to write. Scalars cover the string Data Types / Number / Id and the\n * ID-only User / Reference. An **Option** value is an array of selected aliases\n * (`string[]`) — symmetric with the Option read shape (ADR-0017); a lone string\n * is tolerated as a 1-element selection (fail-safe). `null` / `undefined` omits the\n * field (leaves it unchanged) — send `\"\"` to clear a string field.\n *\n * Per-field static typing (Option fields as `string[]`, etc.) is future work — the\n * precise static Write type (SD-3).\n */\nexport type WriteValue = string | number | string[] | null | undefined;\n\n/** One record to write: field alias (bare, e.g. `P_Name`) -> value. */\nexport type WriteItem = Record<string, WriteValue>;\n\n// Data Types a user may write. `System[Id]` is library-supplied (`P_Id=-1`/target id) and\n// `System[DateTime]` (registration/update) is Write-restricted by PORTERS — both are excluded\n// from the static Write input so they cannot be set (ADR-0016 promise, realized in ADR-0019).\nexport type WritableDataType = Exclude<\n DataType,\n \"System[Id]\" | \"System[DateTime]\"\n>;\n\n// Per-Data-Type write value (mirror of `encodeField`): User / System[Reference] / Number take a\n// number, Option an alias array, the rest a scalar string. Drives the static Write type (ADR-0019).\nexport type WriteValueOf<D extends DataType> = D extends\n | \"User\"\n | \"System[Reference]\"\n | \"Number\"\n ? number\n : D extends \"Option\"\n ? string[]\n : string;\n\n// Element-content escaping. Only `& < >` are significant in PCDATA; we never emit\n// attributes, so quotes are left as-is.\nconst escapeXml = (s: string): string =>\n s.replace(/[&<>]/g, (c) =>\n c === \"&\" ? \"&amp;\" : c === \"<\" ? \"&lt;\" : \"&gt;\",\n );\n\nconst scalar = (v: string | number | string[]): string => escapeXml(String(v));\n\n/** Encode one field's value into the inner XML of its element. */\nexport const encodeField = (\n type: DataType,\n value: string | number | string[],\n): string => {\n switch (type) {\n // Option: the selected aliases as empty child elements. Canonical input is an\n // array (ADR-0017, symmetric with read); a lone string is wrapped as a 1-element\n // selection (fail-safe).\n case \"Option\":\n return (Array.isArray(value) ? value : [value])\n .map((alias) => `<${alias}/>`)\n .join(\"\");\n // System[DateTime] (registration/update) is Write-restricted by PORTERS; we still\n // serialize it identically — rejecting the write is the input type's job (SD-3).\n case \"DateTime\":\n case \"System[DateTime]\":\n return scalar(isoToPortersDateTime(String(value)));\n // Age shares Date's wire format (`yyyy/mm/dd`): we write the birthdate.\n case \"Date\":\n case \"Age\":\n return scalar(isoToPortersDate(String(value)));\n // System[Id] / Number / User & System[Reference] (ID-only) / string Data Types all\n // serialize as a scalar (the string types stay distinct labels per ADR-0016).\n case \"System[Id]\":\n case \"Number\":\n case \"User\":\n case \"System[Reference]\":\n case \"SinglelineText\":\n case \"MultilineText\":\n case \"Mail\":\n case \"Telephone\":\n case \"URL\":\n return scalar(value);\n }\n};\n\n// One `<Item>…</Item>` body. Unknown aliases (custom U_/A_, no catalog entry) fall\n// back to Text — symmetric with decode's raw-string passthrough (fail-safe).\nconst encodeItem = (\n prefix: string,\n fields: ReadonlyMap<string, DataType>,\n item: WriteItem,\n): string => {\n const parts: string[] = [];\n for (const [alias, value] of Object.entries(item)) {\n // null / undefined -> omit (leave unchanged); \"\" is kept (clears a Text field).\n if (value === null || value === undefined) continue;\n const type = fields.get(alias);\n const inner = type === undefined ? scalar(value) : encodeField(type, value);\n parts.push(`<${prefix}.${alias}>${inner}</${prefix}.${alias}>`);\n }\n return parts.join(\"\");\n};\n\n/**\n * One record as its full `<Item>…</Item>` element. Exposed so the bulk-write chunker can\n * measure each record's serialized length when packing a request under the size cap (ADR-0041).\n */\nexport const encodeWriteItem = (\n prefix: string,\n fields: ReadonlyMap<string, DataType>,\n item: WriteItem,\n): string => `<Item>${encodeItem(prefix, fields, item)}</Item>`;\n\n/** Build a Write request body: `<{Resource}><Item>…</Item>…</{Resource}>`. */\nexport const buildWriteXml = (config: {\n resource: string;\n prefix: string;\n fields: ReadonlyMap<string, DataType>;\n items: WriteItem[];\n}): string => {\n const items = config.items\n .map((item) => encodeWriteItem(config.prefix, config.fields, item))\n .join(\"\");\n return `<${config.resource}>${items}</${config.resource}>`;\n};\n","// Data-Type-driven value decoding (ADR-0011). Input is the raw node (string or\n// nested object) from the parser; output is the typed value. Empty -> null.\n\nimport { portersDateToIso, portersDateTimeToIso } from \"../util/datetime\";\nimport { asRecord, asString } from \"./raw\";\n\n// Granularity = PORTERS Data Type (ADR-0016). Labels are the literal Data Type\n// strings, incl. the System family (`System[Id]` / `System[DateTime]` / `System[Reference]`).\n// Currency collapses to Number and the three Option subtypes to Option (PORTERS' own\n// Data Type does the same); the string Data Types stay distinct (room for future\n// validation / normalisation). The `System[…]` qualifier marks system-managed values\n// (auto-assigned, often Write-restricted); that lifecycle is enforced via input types,\n// not here — decoding is by value shape.\nexport type DataType =\n | \"System[Id]\"\n | \"Number\"\n | \"DateTime\"\n | \"System[DateTime]\"\n | \"Date\"\n | \"Age\"\n | \"SinglelineText\"\n | \"MultilineText\"\n | \"Mail\"\n | \"Telephone\"\n | \"URL\"\n | \"User\"\n | \"Option\"\n | \"System[Reference]\";\n\n/** A referenced User (Read is nested; Write is `User.P_Id` only). */\nexport type UserRef = {\n P_Id: number | null;\n P_Type: string | null;\n P_Name: string | null;\n P_Mail: string | null;\n};\n\n// `string[]` is the Option read value (a set of selected aliases — ADR-0017).\nexport type FieldValue = string | number | string[] | UserRef | null;\n\n// Per-Data-Type decoded value (the non-null shape). A read value is `DecodedValue<D> | null`\n// (empty -> null). Mirrors `decodeField`'s branches and drives the static resource Read type\n// (ADR-0019): id/number/reference -> number, User -> UserRef, Option -> string[], rest -> string.\nexport type DecodedValue<D extends DataType> = D extends\n | \"System[Id]\"\n | \"Number\"\n | \"System[Reference]\"\n ? number\n : D extends \"User\"\n ? UserRef\n : D extends \"Option\"\n ? string[]\n : string;\n\n// alias タグは接頭辞付き想定(例 `User.P_Id`)だが、接頭辞無しにも両対応(ADR-0011)。\n// 全 arrow(ADR-0013)=巻き上げ無しのため、ヘルパーを decodeField より前に定義する。\nconst pickPrefixed = (\n obj: Record<string, unknown>,\n prefix: string,\n key: string,\n): string | undefined =>\n asString(obj[`${prefix}.${key}`]) ?? asString(obj[key]);\n\nconst decodeUser = (raw: unknown): UserRef | null => {\n const outer = asRecord(raw);\n const user = outer ? asRecord(outer.User) : undefined;\n if (!user) return null;\n const id = pickPrefixed(user, \"User\", \"P_Id\");\n return {\n P_Id: id === undefined ? null : Number(id),\n P_Type: pickPrefixed(user, \"User\", \"P_Type\") ?? null,\n P_Name: pickPrefixed(user, \"User\", \"P_Name\") ?? null,\n P_Mail: pickPrefixed(user, \"User\", \"P_Mail\") ?? null,\n };\n};\n\n// Read: the selected leaf aliases (e.g. `<Option.P_Tokyo/>`) sit under `<OptionRoot>`.\n// PORTERS represents single/multi alike as a set, so return every selected alias verbatim\n// — incl. the `Option.` prefix (ADR-0017). None / empty -> null.\n// VERIFY(live): the `Option.` prefix and the `OptionRoot` wrapper come from the Read API\n// doc, not a live contract; we tolerate a missing wrapper. See docs/live-verification.md (LV-1, LV-2).\nconst decodeOption = (raw: unknown): string[] | null => {\n const outer = asRecord(raw);\n if (!outer) return null;\n // Aliases live under `<OptionRoot>` when present; the doc's sample omits it, so fall\n // back to the field's own children.\n const root = \"OptionRoot\" in outer ? asRecord(outer.OptionRoot) : outer;\n if (!root) return null;\n const keys = Object.keys(root);\n return keys.length > 0 ? keys : null;\n};\n\n// System[Reference] Read mirrors User: <Field><Resource>...</Resource></Field>, but the\n// inner tag varies (Client/Recruiter/...). Write is ID-only, so we decode the referenced\n// record's id — enough to round-trip. Richer reference reading is future work (SD-3).\n// NB: the label is literally `System[Reference]` (a nested record). It is NOT the\n// display-only Field-Type-16 \"Reference\" (a scalar mirror, Data Type `—`), left uncatalogued.\nconst decodeReference = (raw: unknown): number | null => {\n const outer = asRecord(raw);\n if (!outer) return null;\n // The nested resource is the first record-valued child (skip attributes / siblings,\n // which decodeUser avoids via a fixed key — here the tag varies). Read that record's\n // own `{Tag}.P_Id` (prefix-less also accepted), not just any key ending in P_Id.\n for (const [tag, value] of Object.entries(outer)) {\n const inner = asRecord(value);\n if (!inner) continue;\n const id = asString(inner[`${tag}.P_Id`]) ?? asString(inner.P_Id);\n return id === undefined ? null : Number(id);\n }\n return null;\n};\n\n/** Decode one field's raw node by its Data Type. */\nexport const decodeField = (type: DataType, raw: unknown): FieldValue => {\n // `raw === \"\"` is load-bearing (a Text \"\" must become null, not stay \"\");\n // `=== undefined` / `=== null` are defense-in-depth — every switch branch below\n // also maps them to null, so dropping either is an equivalent mutant.\n // Stryker disable next-line ConditionalExpression: see above (undefined/null are redundant with the switch)\n if (raw === \"\" || raw === undefined || raw === null) return null;\n switch (type) {\n case \"System[Id]\":\n case \"Number\": {\n // raw is neither \"\" nor non-string here (guarded above), so `s` is a\n // non-empty string or undefined — `s === \"\"` would be dead.\n const s = asString(raw);\n return s === undefined ? null : Number(s);\n }\n // String Data Types share one decode (a plain string); they stay distinct\n // labels for fidelity / future per-type validation (ADR-0016).\n case \"SinglelineText\":\n case \"MultilineText\":\n case \"Mail\":\n case \"Telephone\":\n case \"URL\":\n return asString(raw) ?? null;\n // FT-12 DateTime and the system timestamps (registration/update) share the wire\n // format; System[DateTime] is Write-restricted, but that is a write-time concern.\n case \"DateTime\":\n case \"System[DateTime]\": {\n const s = asString(raw);\n return s === undefined ? null : portersDateTimeToIso(s);\n }\n // Age shares Date's wire format (`yyyy/mm/dd`); PORTERS transmits the birthdate\n // and derives the age in its UI, so the faithful value is the date itself.\n case \"Date\":\n case \"Age\": {\n const s = asString(raw);\n return s === undefined ? null : portersDateToIso(s);\n }\n case \"User\":\n return decodeUser(raw);\n case \"Option\":\n return decodeOption(raw);\n case \"System[Reference]\":\n return decodeReference(raw);\n }\n};\n","// Shared Read internals for every resource — data (resource.ts) and master\n// (partition/user/field/option). Owns catalog typing, the catalog-driven item decoder, the\n// GET+parse+decode runner, and offset pagination. Data resources add Write on top; master\n// resources add bespoke query/URL building (ADR-0021/0022). XML stays in xml/ — this only\n// wires parse + decode together.\n\nimport type { Requester } from \"../http/requester\";\nimport {\n decodeField,\n type DataType,\n type DecodedValue,\n type FieldValue,\n} from \"../xml/decode\";\nimport { parseResourcePage, type RawItem } from \"../xml/parser\";\n\n// A field catalog: bare alias -> Data Type. Declared `as const` per resource so the static\n// Read/Write types derive from it — the catalog is the single source of truth (ADR-0019).\nexport type FieldCatalog = Record<string, DataType>;\n\n/**\n * \"No custom fields\": the intersection-identity default for the generic catalog params (ADR-0023).\n * A bare `{}` is flagged by `no-empty-object-type`; `Record<never, never>` is the same empty object,\n * lint-clean, adds no keys in `static & C`, and satisfies both `FieldCatalog` and `DeclaredCatalogs`.\n * Lives here (with `FieldCatalog`) so resources need not import from the higher-level `fields/` (RV-8).\n */\nexport type EmptyCatalog = Record<never, never>;\n\n/**\n * A decoded record: every known field, each `DecodedValue | null`, and **optional** because a\n * field not named in `field` is simply absent (SD-3 \"simple\" type — ADR-0005/0019). Custom\n * `U_`/`A_` aliases are not in the catalog, so they are not typed here (access via a cast until\n * the declaration DSL lands — ADR-0005 SD-2); at runtime they still pass through as raw values.\n */\nexport type ReadRecord<F extends FieldCatalog> = {\n [K in keyof F]?: DecodedValue<F[K]> | null;\n};\n\nexport type ResourcePage<F extends FieldCatalog> = {\n items: ReadRecord<F>[];\n total: number;\n count: number;\n start: number;\n};\n\n// `includes(\".\")` -> `includes(\"\")` is an equivalent mutant: for a dotless key,\n// slice(indexOf(\".\") + 1) is slice(0), which equals the key — same as the else.\n// Stryker disable StringLiteral\nconst bareAlias = (key: string): string =>\n key.includes(\".\") ? key.slice(key.indexOf(\".\") + 1) : key;\n// Stryker restore StringLiteral\n\n/**\n * Build a catalog-driven item decoder: known `P_` fields decode by their Data Type, unknown\n * `U_`/`A_` aliases pass through (raw string, or null when nested). `bareAlias` strips the\n * `{prefix}.` so `Person.P_Name` and `P_Name` both hit the catalog.\n */\nexport const decoderFor = <F extends FieldCatalog>(\n fields: F,\n): ((item: RawItem) => ReadRecord<F>) => {\n const fieldMap = new Map<string, DataType>(Object.entries(fields));\n return (item) => {\n const out: Record<string, FieldValue> = {};\n for (const [key, raw] of Object.entries(item)) {\n const alias = bareAlias(key);\n const type = fieldMap.get(alias);\n out[alias] = type\n ? decodeField(type, raw)\n : typeof raw === \"string\"\n ? raw\n : null;\n }\n return out as ReadRecord<F>;\n };\n};\n\n/** GET a Read URL, parse the standard envelope (Total/Count/Start + Items), decode each item. */\nexport const runRead = <F extends FieldCatalog>(\n requester: Requester,\n url: string,\n decode: (item: RawItem) => ReadRecord<F>,\n): Promise<ResourcePage<F>> =>\n requester.request({ method: \"GET\", url, headers: {} }, (body) => {\n const page = parseResourcePage(body);\n return {\n items: page.items.map(decode),\n total: page.total,\n count: page.count,\n start: page.start,\n };\n });\n\n// Read max page size (docs/reference: count 1–200). searchAll pages by this.\nconst PAGE_SIZE = 200;\n\n/**\n * Offset pagination shared by every `searchAll`. Advances by the items actually returned and\n * stops at `total` — or on an empty page (defensive against a stuck offset / infinite loop).\n * A generator can't be an arrow; a function expression still satisfies func-style:expression.\n */\nexport const paginate = async function* <T>(\n fetchPage: (\n count: number,\n start: number,\n ) => Promise<{ items: T[]; total: number }>,\n): AsyncGenerator<T> {\n let start = 0;\n for (;;) {\n const page = await fetchPage(PAGE_SIZE, start);\n for (const item of page.items) yield item;\n start += page.items.length;\n if (page.items.length === 0 || start >= page.total) return;\n }\n};\n","// Typed Read query surface (ADR-0038 / F-2): condition / order / keywords / itemstate, grounded in\n// the PORTERS Read parameter reference. The public types are Data-Type-aware — a field's allowed\n// operators and value shape derive from its catalog Data Type (ADR-0005 R-5 / ADR-0038 案1a). The\n// encoder turns a typed query into the wire params, normalising dates ISO -> PORTERS and guarding\n// the caller-side limits (keywords length, itemstate condition restriction) before send (fail-safe).\n// XML/value formatting stays in xml/; this owns only the Read query string.\n\nimport { PortersConfigError } from \"../errors\";\nimport { isoToPortersDate, isoToPortersDateTime } from \"../util/datetime\";\nimport type { DataType } from \"../xml/decode\";\nimport type { FieldCatalog } from \"./read-core\";\n\n// --- condition: per-Data-Type operator objects (reference: Read - Condition) ---\n\n/** Comparable ops for numeric Ids (System[Id]); `or` matches a set of Resource Ids (`P_Id:or=1:2`). */\ntype IdCondition = {\n gt?: number;\n ge?: number;\n eq?: number;\n le?: number;\n lt?: number;\n or?: number[];\n};\n\n/** Comparable ops for Number. */\ntype NumberCondition = {\n gt?: number;\n ge?: number;\n eq?: number;\n le?: number;\n lt?: number;\n};\n\n/** Comparable ops for date/time fields. Values are ISO 8601 (UTC `…Z`); normalised to PORTERS on send. */\ntype TemporalCondition = {\n gt?: string;\n ge?: string;\n eq?: string;\n le?: string;\n lt?: string;\n};\n\n/** Text match. `full` = exact, `part` = substring (PORTERS default). */\ntype TextCondition = {\n full?: string;\n part?: string;\n};\n\n/** Option-select match; values are option aliases (e.g. `Option.P_SE`), OR/AND-joined. */\ntype OptionCondition = {\n or?: string[];\n and?: string[];\n};\n\n/** Link/reference match by id (User / System[Reference]): `eq` one id, or OR/AND a set of ids. */\ntype ReferenceCondition = {\n eq?: number;\n or?: number[];\n and?: number[];\n};\n\n/** The condition-operator object a field of Data Type `D` accepts. */\ntype ConditionFor<D extends DataType> = D extends \"System[Id]\"\n ? IdCondition\n : D extends \"Number\"\n ? NumberCondition\n : D extends \"DateTime\" | \"System[DateTime]\" | \"Date\" | \"Age\"\n ? TemporalCondition\n : D extends\n | \"SinglelineText\"\n | \"MultilineText\"\n | \"Mail\"\n | \"Telephone\"\n | \"URL\"\n ? TextCondition\n : D extends \"Option\"\n ? OptionCondition\n : D extends \"User\" | \"System[Reference]\"\n ? ReferenceCondition\n : never;\n\n/**\n * A typed search condition over a catalog: each field maps to the operator object its Data Type\n * allows (ADR-0038 案1a). Multiple fields are AND-joined (reference). Unknown aliases / wrong\n * operators are type errors. Custom `U_`/`A_` fields are not in the catalog — condition on them via\n * a cast (the encoder passes unknown aliases through as raw scalars, like read/write).\n */\nexport type Condition<F extends FieldCatalog> = {\n [K in keyof F]?: ConditionFor<F[K]>;\n};\n\n// --- order (reference: Read - Order; only Number/Currency/Age/Date/DateTime/System are sortable) ---\n\ntype OrderableDataType =\n | \"System[Id]\"\n | \"System[DateTime]\"\n | \"Number\"\n | \"DateTime\"\n | \"Date\"\n | \"Age\";\n\ntype OrderableKeys<F extends FieldCatalog> = {\n [K in keyof F]: F[K] extends OrderableDataType ? K : never;\n}[keyof F];\n\n/**\n * Sort spec: an ordered list of `{ field: \"asc\" | \"desc\" }`, encoded in array (then key) order. Only\n * orderable Data Types (Number/Date/DateTime/Age/System) are accepted (reference).\n */\nexport type Order<F extends FieldCatalog> = Array<\n Partial<Record<OrderableKeys<F>, \"asc\" | \"desc\">>\n>;\n\n// --- itemstate (reference: 削除済みデータ取得) ---\n\n/**\n * Which delete state to read. Omitting (or `existing`) reads live data; `deleted`/`all` read deleted\n * records — the only way to read deleted data, since there is no delete API. When `deleted`/`all`,\n * condition is restricted to `P_Id` / `P_UpdateDate` / `P_UpdatedBy` and PORTERS auto-adds a\n * \"updated within 90 days\" filter (`P_UpdateDate` = the delete time, `P_UpdatedBy` = the last editor).\n */\nexport type ItemState = \"existing\" | \"deleted\" | \"all\";\n\n// --- the public query shape (moved here from resource.ts; data resources parametrise over their catalog) ---\n\nexport type SearchQuery<F extends FieldCatalog = FieldCatalog> = {\n /**\n * Output fields as prefixed aliases (e.g. `Person.P_Name`). **Omit** to fetch every catalogued\n * field by default (ADR-0020): PORTERS returns only the primary key for a fieldless request, so\n * the library sends a catalog-derived default field set instead. Pass `[]` to opt into that\n * API-native \"primary key only\" response (e.g. counting). A non-empty list is sent verbatim.\n */\n field?: string[];\n /** Typed AND-conditions; each field's operators derive from its Data Type (ADR-0038). */\n condition?: Condition<F>;\n /** Sort order; orderable Data Types only (Number/Date/DateTime/Age/System). */\n order?: Order<F>;\n /**\n * Keyword AND-search over text fields (MultilineText/SinglelineText/Mail/URL; Telephone digits\n * only). OR is not supported. Max 100 characters including commas — guarded before send.\n */\n keywords?: string[];\n /** Delete-state filter (default `existing`). `deleted`/`all` restrict `condition` — see {@link ItemState}. */\n itemstate?: ItemState;\n count?: number;\n start?: number;\n};\n\n// --- encoder (typed query -> wire params) ---\n\nconst KEYWORDS_MAX_CHARS = 100;\n// itemstate=deleted/all restricts condition to these standard fields (reference / 削除済みデータ取得).\nconst DELETED_CONDITION_FIELDS = new Set([\n \"P_Id\",\n \"P_UpdateDate\",\n \"P_UpdatedBy\",\n]);\n\n/** Output context for prefixing aliases and resolving each field's Data Type. */\ntype QueryContext = {\n prefix: string;\n fields: ReadonlyMap<string, DataType>;\n};\n\n/**\n * Serialise one condition value by the field's Data Type: dates ISO -> PORTERS, arrays (Option\n * aliases / id sets) colon-joined, everything else stringified. Unknown alias (no Data Type) ->\n * raw scalar, mirroring read/write passthrough.\n */\nconst serializeConditionValue = (\n type: DataType | undefined,\n value: unknown,\n): string => {\n if (Array.isArray(value)) return value.map(String).join(\":\");\n if (type === \"DateTime\" || type === \"System[DateTime]\") {\n return isoToPortersDateTime(String(value));\n }\n if (type === \"Date\" || type === \"Age\") return isoToPortersDate(String(value));\n return String(value);\n};\n\n// condition -> `Prefix.alias:suffix=value,...`. Throws if itemstate=deleted/all names a field\n// outside P_Id/P_UpdateDate/P_UpdatedBy (PORTERS would 400 — fail fast before send). Typed over the\n// loose catalog: `Condition<F>` is assignable in, and the encoding is purely structural.\nconst encodeCondition = (\n condition: Condition<FieldCatalog>,\n itemstate: ItemState | undefined,\n ctx: QueryContext,\n): string => {\n const restricted = itemstate === \"deleted\" || itemstate === \"all\";\n const parts: string[] = [];\n for (const [alias, ops] of Object.entries(condition)) {\n if (ops === undefined) continue;\n if (restricted && !DELETED_CONDITION_FIELDS.has(alias)) {\n throw new PortersConfigError(\n `condition field \"${alias}\" is not allowed when itemstate is \"${itemstate}\"`,\n {\n category: \"config\",\n hint: \"Deleted reads (itemstate deleted/all) accept only P_Id, P_UpdateDate, P_UpdatedBy in condition.\",\n },\n );\n }\n const type = ctx.fields.get(alias);\n for (const [suffix, value] of Object.entries(ops)) {\n if (value === undefined) continue;\n parts.push(\n `${ctx.prefix}.${alias}:${suffix}=${serializeConditionValue(type, value)}`,\n );\n }\n }\n return parts.join(\",\");\n};\n\n// order -> `Prefix.alias:dir,...` in array (then key) order. Loosely typed (Order<F> assigns in);\n// `Order<FieldCatalog>` collapses its value type, so read each spec's entries as directions.\nconst encodeOrder = (order: Order<FieldCatalog>, ctx: QueryContext): string => {\n const parts: string[] = [];\n for (const spec of order) {\n const dirs = spec as Record<string, \"asc\" | \"desc\" | undefined>;\n for (const [alias, dir] of Object.entries(dirs)) {\n if (dir === undefined) continue;\n parts.push(`${ctx.prefix}.${alias}:${dir}`);\n }\n }\n return parts.join(\",\");\n};\n\n/**\n * Set the typed Read query params (condition / order / keywords / itemstate) on `p`. Universal\n * params (partition / field / count / start) stay in `buildReadUrl`. Throws `PortersConfigError`\n * for caller-side misuse (keywords too long, itemstate-restricted condition) before any request.\n */\nexport const appendReadQuery = <F extends FieldCatalog>(\n p: URLSearchParams,\n q: SearchQuery<F>,\n ctx: QueryContext,\n): void => {\n if (q.condition) {\n const cond = encodeCondition(q.condition, q.itemstate, ctx);\n if (cond.length > 0) p.set(\"condition\", cond);\n }\n if (q.order) {\n const order = encodeOrder(q.order, ctx);\n if (order.length > 0) p.set(\"order\", order);\n }\n if (q.keywords && q.keywords.length > 0) {\n const kw = q.keywords.join(\",\");\n if (kw.length > KEYWORDS_MAX_CHARS) {\n throw new PortersConfigError(\n `keywords is ${kw.length} characters, over the ${KEYWORDS_MAX_CHARS}-character limit`,\n {\n category: \"config\",\n hint: \"Shorten keywords: PORTERS caps the keyword search at 100 characters including commas.\",\n },\n );\n }\n p.set(\"keywords\", kw);\n }\n // `existing` is the API default — omit it to keep URLs minimal (and stable vs. pre-F-2 reads).\n if (q.itemstate !== undefined && q.itemstate !== \"existing\") {\n p.set(\"itemstate\", q.itemstate);\n }\n};\n","// Bulk write (ADR-0041 / F-4): createMany / updateMany over PORTERS' multi-`<Item>` Write.\n// A single request holds up to 200 records and must stay under the ~15000-char cap, so this\n// splits the input into size- and count-bounded batches, sends them sequentially (the write\n// throttle paces them), and concatenates the per-item results in input order. A batch is NOT\n// atomic — each `<Item>` carries its own `<Code>` — so per-item failures are returned (not\n// thrown); only a whole-request failure throws. The generic factory wires this; XML stays in xml/.\n\nimport {\n PortersConfigError,\n PortersError,\n PortersResourceError,\n} from \"../errors\";\nimport { MAX_REQUEST_LENGTH, type Requester } from \"../http/requester\";\nimport type { DataType } from \"../xml/decode\";\nimport { encodeWriteItem, type WriteItem } from \"../xml/encode\";\nimport { parseWriteResult, type WriteResultItem } from \"../xml/parser\";\n\n/** PORTERS caps a Write request at 200 records; larger inputs are split into batches of 200. */\nconst MAX_ITEMS_PER_REQUEST = 200;\n\n/** One record's outcome from a bulk write, in the position it was sent (ADR-0041 SD-2). */\nexport type BulkWriteResultItem = {\n /** 0-based index in the input array. */\n index: number;\n /** Assigned (create) / echoed (update) record id. Meaningful only when `ok`. */\n id: number;\n /** PORTERS per-item Result Code (`0` = success). */\n code: number;\n /** `code === 0`. */\n ok: boolean;\n};\n\n/**\n * The result of `createMany` / `updateMany` (ADR-0041). `results` holds every record's outcome in\n * input order; `failed` is the `ok === false` subset. A per-item `code !== 0` does **not** throw —\n * a bulk write mixes successes and failures — so always inspect `hasFailures` / `failed`.\n */\nexport type BulkWriteResult = {\n results: BulkWriteResultItem[];\n failed: BulkWriteResultItem[];\n hasFailures: boolean;\n};\n\n// A record paired with its original index and pre-serialized `<Item>…</Item>` (measured for packing).\ntype Encoded = { index: number; xml: string };\n\n/**\n * Greedily pack encoded records into batches that each stay within `budget` characters (the request\n * cap minus URL + envelope overhead) and `MAX_ITEMS_PER_REQUEST` records. A single record larger than\n * `budget` cannot be sent in any batch → fail fast with a clear config error (send-time, fail-safe).\n */\nconst packBatches = (encoded: Encoded[], budget: number): Encoded[][] => {\n const batches: Encoded[][] = [];\n let batch: Encoded[] = [];\n let length = 0;\n for (const e of encoded) {\n if (e.xml.length > budget) {\n throw new PortersConfigError(\n `a single record serializes to ${e.xml.length} characters, over the ~${budget}-character budget for one request`,\n {\n category: \"config\",\n hint: \"Reduce that record's field values — a bulk request (URL + body) is capped at ~15000 characters.\",\n },\n );\n }\n // Start a new batch when the next record would breach either bound. Never reached with an empty\n // batch: on the first record `length` and `batch.length` are 0 and an over-budget record already\n // threw above, so `batch` is always non-empty here (no empty batch is ever pushed).\n if (\n batch.length >= MAX_ITEMS_PER_REQUEST ||\n length + e.xml.length > budget\n ) {\n batches.push(batch);\n batch = [];\n length = 0;\n }\n batch.push(e);\n length += e.xml.length;\n }\n if (batch.length > 0) batches.push(batch);\n return batches;\n};\n\n// A batch failed at the request level after earlier batches were already applied. Creates are\n// non-idempotent, so a blind full retry would duplicate them — surface the progress instead (SD-4).\nconst batchFailure = (\n cause: unknown,\n written: number,\n resource: string,\n partition: number,\n): PortersError => {\n const base = cause instanceof PortersError ? cause : undefined;\n return new PortersResourceError(\n `bulk write failed after ${written} record(s) had already been written`,\n {\n category: base?.category ?? \"unknown\",\n code: base?.code ?? null,\n retryable: false,\n httpStatus: base?.httpStatus,\n hint: `${written} record(s) from earlier batches were already written; retry only the records from index ${written} onward (create is non-idempotent — a full retry would duplicate them).`,\n context: { resource, operation: \"bulkWrite\", partition },\n cause,\n },\n );\n};\n\n/**\n * Execute a bulk write: split `items` into batches, POST each, and merge the per-item results.\n * `target.url` is the (short) Write URL; `idempotent` is false for create (non-idempotent), true for\n * update. Per-item `code !== 0` is returned in the result; a whole-request failure throws — with the\n * already-written count once at least one earlier batch succeeded (SD-4).\n */\nexport const runBulkWrite = async (\n requester: Requester,\n target: {\n name: string;\n prefix: string;\n fields: ReadonlyMap<string, DataType>;\n url: string;\n partition: number;\n },\n items: WriteItem[],\n idempotent: boolean,\n): Promise<BulkWriteResult> => {\n const envelope = `<${target.name}></${target.name}>`.length;\n const budget = MAX_REQUEST_LENGTH - target.url.length - envelope;\n const encoded: Encoded[] = items.map((item, index) => ({\n index,\n xml: encodeWriteItem(target.prefix, target.fields, item),\n }));\n const batches = packBatches(encoded, budget);\n\n const results: BulkWriteResultItem[] = [];\n let written = 0;\n for (const batch of batches) {\n const body = `<${target.name}>${batch.map((e) => e.xml).join(\"\")}</${target.name}>`;\n let parsed: WriteResultItem[];\n try {\n parsed = await requester.request(\n { method: \"POST\", url: target.url, headers: {}, body },\n parseWriteResult,\n { write: true, idempotent },\n );\n } catch (cause) {\n // First batch failed = nothing applied yet → surface the original error unchanged.\n if (written === 0) throw cause;\n throw batchFailure(cause, written, target.name, target.partition);\n }\n if (parsed.length !== batch.length) {\n throw new PortersResourceError(\n `bulk write response returned ${parsed.length} result(s) for ${batch.length} record(s)`,\n { category: \"unknown\", context: { resource: target.name } },\n );\n }\n batch.forEach((e, i) => {\n const { id, code } = parsed[i];\n results.push({ index: e.index, id, code, ok: code === 0 });\n });\n written += batch.length;\n }\n\n const failed = results.filter((r) => !r.ok);\n return { results, failed, hasFailures: failed.length > 0 };\n};\n","// Generic resource accessor (ADR-0004/0005/0011): the Read (search / searchAll /\n// get) + Write (create / update) shape shared by every PORTERS resource. A resource\n// module supplies its names + Data-Type catalog; this owns the wiring and keeps XML\n// out of resources/ (parse/encode live in xml/). Standard `P_` fields use the catalog;\n// custom `U_`/`A_` pass through (decode: raw string / encode: Text).\n\nimport { PortersResourceError, resourceError } from \"../errors\";\nimport type { Requester } from \"../http/requester\";\nimport type { DataType } from \"../xml/decode\";\nimport {\n buildWriteXml,\n type WritableDataType,\n type WriteItem,\n type WriteValueOf,\n} from \"../xml/encode\";\nimport { parseWriteResult } from \"../xml/parser\";\nimport {\n decoderFor,\n paginate,\n runRead,\n type FieldCatalog,\n type ReadRecord,\n type ResourcePage,\n} from \"./read-core\";\nimport { appendReadQuery, type Condition, type SearchQuery } from \"./query\";\nimport { runBulkWrite, type BulkWriteResult } from \"./bulk-write\";\n\n// Shared Read types/internals live in read-core (reused by master resources). Re-export the\n// types so the data-resource modules keep importing them from \"./resource\".\nexport type {\n EmptyCatalog,\n FieldCatalog,\n ReadRecord,\n ResourcePage,\n} from \"./read-core\";\n// Typed Read query surface (ADR-0038 / F-2). Defined in query.ts; re-exported so resource modules\n// and the public barrel keep importing the query types from \"./resource\".\nexport type { Condition, ItemState, Order, SearchQuery } from \"./query\";\n// Bulk write result (ADR-0041 / F-4). Defined in bulk-write.ts; re-exported so resource modules and\n// the public barrel keep importing the bulk types from \"./resource\".\nexport type { BulkWriteResult, BulkWriteResultItem } from \"./bulk-write\";\n\n// Writable aliases: every field whose Data Type a user may write (excludes System[Id] /\n// System[DateTime] — ADR-0016/0019).\ntype WritableKeys<F extends FieldCatalog> = {\n [K in keyof F]: F[K] extends WritableDataType ? K : never;\n}[keyof F];\n\n/**\n * Create input (ADR-0019 W2): the `requiredOnCreate` aliases are **required** (non-null); every\n * other writable field is optional (`null` omits). `P_Id` is supplied by the library — not here.\n */\nexport type CreateInput<F extends FieldCatalog, Req extends keyof F> = {\n [K in Req]: WriteValueOf<F[K]>;\n} & {\n [K in Exclude<WritableKeys<F>, Req>]?: WriteValueOf<F[K]> | null;\n};\n\n/** Update input (ADR-0019 W2): every writable field optional (`null` omits, `\"\"` clears). */\nexport type UpdateInput<F extends FieldCatalog> = {\n [K in WritableKeys<F>]?: WriteValueOf<F[K]> | null;\n};\n\n/** Static description of a resource: names + `as const` catalog + required-on-create aliases. */\nexport type ResourceConfig<\n F extends FieldCatalog,\n Req extends readonly (keyof F)[],\n> = {\n /** Root element + Write resource name, e.g. `\"Candidate\"`. */\n name: string;\n /** URL path segment, e.g. `\"candidate\"`. */\n path: string;\n /** Field alias prefix, e.g. `\"Person\"`. */\n prefix: string;\n /** Data-Type catalog (`as const`): bare alias -> Data Type. */\n fields: F;\n /** Aliases required on `create` (PORTERS new-record requirements — ADR-0019 W2). */\n requiredOnCreate: Req;\n};\n\nexport type Resource<F extends FieldCatalog, Req extends keyof F> = {\n search(query?: SearchQuery<F>): Promise<ResourcePage<F>>;\n /** Auto-paginating search: yields every matching record (200 per page). */\n searchAll(\n query?: Omit<SearchQuery<F>, \"count\" | \"start\">,\n ): AsyncIterable<ReadRecord<F>>;\n get(id: number): Promise<ReadRecord<F> | undefined>;\n /** Create one record; resolves to the newly assigned id. */\n create(input: CreateInput<F, Req>): Promise<number>;\n /** Update one record by id; resolves to that id. */\n update(id: number, input: UpdateInput<F>): Promise<number>;\n /**\n * Create many records in one call (ADR-0041 / F-4). Auto-batched to ≤200 records and under the\n * request size cap. **Not atomic** — inspect the {@link BulkWriteResult}: per-record failures are\n * returned (`failed` / `hasFailures`), not thrown. Only a whole-request failure throws (with the\n * already-written count). Batching is non-idempotent: a full retry after a mid-run failure may\n * duplicate creates. Empty input sends no request.\n */\n createMany(inputs: CreateInput<F, Req>[]): Promise<BulkWriteResult>;\n /**\n * Update many records by id in one call (ADR-0041 / F-4). Auto-batched like {@link createMany};\n * per-record failures are returned in the {@link BulkWriteResult}, not thrown.\n */\n updateMany(\n items: { id: number; fields: UpdateInput<F> }[],\n ): Promise<BulkWriteResult>;\n};\n\n// The 4 readable sub-fields of a User-type field (docs/reference: only these are returned).\nconst USER_SUBFIELDS = [\"P_Id\", \"P_Type\", \"P_Name\", \"P_Mail\"] as const;\n\n// Default Read `field` list derived from the catalog (ADR-0020, 案A+2a). PORTERS returns only\n// `{Resource}.P_Id` for a fieldless request, so a typed-record read would otherwise drop every\n// known field despite the type promising them. We send every catalog alias as `{prefix}.{alias}`,\n// expanding User to its 4 readable sub-fields and leaving System[Reference] ID-only (`()` omitted)\n// so the wire shape matches decode.ts. The API-native \"primary key only\" stays reachable via\n// `field: []` (透明化 — see SearchQuery.field).\nconst defaultFieldList = (prefix: string, fields: FieldCatalog): string[] =>\n Object.entries(fields).map(([alias, type]) =>\n type === \"User\"\n ? `${prefix}.${alias}(${USER_SUBFIELDS.map((s) => `User.${s}`).join(\",\")})`\n : `${prefix}.${alias}`,\n );\n\n/**\n * A single-Item Write response -> the assigned/updated id. A non-zero per-item Code is a\n * resource error (mapped, not swallowed); a missing result Item is unparseable. Shared by\n * the generic factory and the bespoke Attachment accessor. `path` names the error code\n * message, `name` the error context resource.\n */\nexport const firstWriteResultId = (\n body: string,\n path: string,\n name: string,\n): number => {\n const first = parseWriteResult(body)[0];\n if (first === undefined) {\n throw new PortersResourceError(\"write returned no result item\", {\n category: \"unknown\",\n });\n }\n if (first.code !== 0) {\n throw resourceError(\n first.code,\n `${path} write returned code ${first.code}`,\n {\n resource: name,\n },\n );\n }\n return first.id;\n};\n\n/**\n * Build a Read URL: `https://{host}/v1/{path}?partition=…&field=…&condition=…&order=…&keywords=…&itemstate=…&count=…&start=…`.\n * `ctx` (alias prefix + Data-Type map) drives the typed query encoding (ADR-0038): condition/order\n * prefixing, date ISO -> PORTERS, and the keyword/itemstate guards. Attachment is bespoke (no prefix\n * / no catalog) and builds its own loose URL — see attachment.ts.\n */\nexport const buildReadUrl = <F extends FieldCatalog>(\n host: string,\n partition: number,\n path: string,\n q: SearchQuery<F>,\n ctx: { prefix: string; fields: ReadonlyMap<string, DataType> },\n): string => {\n const p = new URLSearchParams();\n p.set(\"partition\", String(partition));\n if (q.field && q.field.length > 0) p.set(\"field\", q.field.join(\",\"));\n appendReadQuery(p, q, ctx);\n if (q.count !== undefined) p.set(\"count\", String(q.count));\n if (q.start !== undefined) p.set(\"start\", String(q.start));\n return `https://${host}/v1/${path}?${p.toString()}`;\n};\n\n/** Build a Write URL: `https://{host}/v1/{path}?partition=…`. */\nexport const buildWriteUrl = (\n host: string,\n partition: number,\n path: string,\n): string => `https://${host}/v1/${path}?partition=${partition}`;\n\nexport const createResource = <\n const F extends FieldCatalog,\n const Req extends readonly (keyof F)[],\n>(\n config: ResourceConfig<F, Req>,\n deps: { requester: Requester; host: string; partition: number },\n): Resource<F, Req[number]> => {\n // The catalog is `as const` for the types; encode needs a runtime lookup, decode gets its own.\n const fieldMap = new Map<string, DataType>(Object.entries(config.fields));\n const decode = decoderFor(config.fields);\n // Computed once: the default field set sent when a caller omits `field` (ADR-0020).\n const defaultFields = defaultFieldList(config.prefix, config.fields);\n\n const readUrl = (q: SearchQuery<F>): string =>\n buildReadUrl(deps.host, deps.partition, config.path, q, {\n prefix: config.prefix,\n fields: fieldMap,\n });\n\n const writeUrl = (): string =>\n buildWriteUrl(deps.host, deps.partition, config.path);\n\n const firstWriteId = (body: string): number =>\n firstWriteResultId(body, config.path, config.name);\n\n // `field` omitted -> send the catalog default; `[]` stays empty (API-native primary key\n // only); a provided list is sent verbatim (ADR-0020).\n const search = (query: SearchQuery<F> = {}): Promise<ResourcePage<F>> =>\n runRead(\n deps.requester,\n readUrl({ ...query, field: query.field ?? defaultFields }),\n decode,\n );\n\n const searchAll = (\n query: Omit<SearchQuery<F>, \"count\" | \"start\"> = {},\n ): AsyncIterable<ReadRecord<F>> =>\n paginate((count, start) => search({ ...query, count, start }));\n\n const get = async (id: number): Promise<ReadRecord<F> | undefined> => {\n // Every catalog carries `P_Id` (System[Id]); the generic `F` can't prove it statically, so\n // build the condition at runtime and let the encoder prefix it (`{prefix}.P_Id:eq=id`).\n const condition = { P_Id: { eq: id } } as unknown as Condition<F>;\n const page = await search({ condition, count: 1 });\n return page.items[0];\n };\n\n // create forces P_Id=-1 (non-idempotent: a retry would duplicate); update forces\n // the target id (idempotent: re-applying the same write is safe). Forcing P_Id\n // after the spread means a caller-supplied P_Id never overrides it.\n const write = (item: WriteItem, idempotent: boolean): Promise<number> =>\n deps.requester.request(\n {\n method: \"POST\",\n url: writeUrl(),\n headers: {},\n body: buildWriteXml({\n resource: config.name,\n prefix: config.prefix,\n fields: fieldMap,\n items: [item],\n }),\n },\n firstWriteId,\n { write: true, idempotent },\n );\n\n const create = (input: CreateInput<F, Req[number]>): Promise<number> =>\n write({ ...input, P_Id: -1 }, false);\n\n const update = (id: number, input: UpdateInput<F>): Promise<number> =>\n write({ ...input, P_Id: id }, true);\n\n // Bulk write (ADR-0041): map each input to a WriteItem with its P_Id (create = -1, update = id) —\n // mirroring single write — and hand the array to the batching executor. createMany is\n // non-idempotent (P_Id=-1), updateMany idempotent (targets ids).\n const target = {\n name: config.name,\n prefix: config.prefix,\n fields: fieldMap,\n partition: deps.partition,\n };\n const createMany = (\n inputs: CreateInput<F, Req[number]>[],\n ): Promise<BulkWriteResult> =>\n runBulkWrite(\n deps.requester,\n { ...target, url: writeUrl() },\n inputs.map((input) => ({ ...input, P_Id: -1 })),\n false,\n );\n\n const updateMany = (\n items: { id: number; fields: UpdateInput<F> }[],\n ): Promise<BulkWriteResult> =>\n runBulkWrite(\n deps.requester,\n { ...target, url: writeUrl() },\n items.map(({ id, fields }) => ({ ...fields, P_Id: id })),\n true,\n );\n\n return { search, searchAll, get, create, update, createMany, updateMany };\n};\n","// Candidate accessor (ADR-0004/0005/0011/0019): Read (search / searchAll / get) + Write\n// (create / update) over the generic resource factory. Only the Data-Type catalog and names\n// are Candidate-specific; the static Candidate / input types derive from the catalog\n// (single source of truth — ADR-0019).\n\nimport type { Requester } from \"../http/requester\";\nimport {\n createResource,\n type CreateInput,\n type EmptyCatalog,\n type FieldCatalog,\n type ReadRecord,\n type Resource,\n type ResourcePage,\n type SearchQuery,\n type UpdateInput,\n} from \"./resource\";\n\nconst FIELDS = {\n P_Id: \"System[Id]\",\n P_Owner: \"User\",\n P_RegistrationDate: \"System[DateTime]\",\n P_RegisteredBy: \"User\",\n P_UpdateDate: \"System[DateTime]\",\n P_UpdatedBy: \"User\",\n P_Phase: \"Option\",\n P_PhaseDate: \"DateTime\",\n P_Name: \"SinglelineText\",\n P_Reading: \"SinglelineText\",\n P_Mail: \"Mail\",\n P_MobileMail: \"Mail\",\n P_Telephone: \"Telephone\",\n P_Mobile: \"Telephone\",\n P_Country: \"SinglelineText\",\n P_Prefecture: \"SinglelineText\",\n P_City: \"SinglelineText\",\n P_Zipcode: \"SinglelineText\",\n} as const satisfies FieldCatalog;\n\n// Required on create per docs/reference (resources/candidate.md「新規必須」列): P_Owner。\n// (System[Id] の P_Id も新規必須だが lib が -1 を供給するため型からは除外。LV-5 は reference で確定。)\nconst REQUIRED_ON_CREATE = [\n \"P_Owner\",\n] as const satisfies readonly (keyof typeof FIELDS)[];\n\n/** A decoded Candidate: known `P_` fields, each requested field `value | null`. */\nexport type Candidate = ReadRecord<typeof FIELDS>;\nexport type CandidatePage = ResourcePage<typeof FIELDS>;\nexport type CandidateSearchQuery = SearchQuery<typeof FIELDS>;\n\n/** Fields for `create`: `P_Owner` is required; `P_Id` / system timestamps are not settable. */\nexport type CandidateCreateInput = CreateInput<\n typeof FIELDS,\n (typeof REQUIRED_ON_CREATE)[number]\n>;\n/** Fields for `update`: all optional (`null` omits, `\"\"` clears a text field). */\nexport type CandidateUpdateInput = UpdateInput<typeof FIELDS>;\n/** The Candidate accessor; `C` is the declared custom-field catalog merged on (ADR-0023). */\nexport type CandidateResource<C extends FieldCatalog = EmptyCatalog> = Resource<\n typeof FIELDS & C,\n (typeof REQUIRED_ON_CREATE)[number]\n>;\n\nexport const createCandidateResource = <C extends FieldCatalog = EmptyCatalog>(\n deps: { requester: Requester; host: string; partition: number },\n custom?: C,\n): CandidateResource<C> => {\n // Custom U_/A_ aliases never collide with P_, so the merge is exactly `typeof FIELDS & C`;\n // the cast just names that intersection (defineFields already validated aliases — ADR-0023 D7).\n const fields = { ...FIELDS, ...custom } as typeof FIELDS & C;\n return createResource(\n {\n name: \"Candidate\",\n path: \"candidate\",\n prefix: \"Person\",\n fields,\n requiredOnCreate: REQUIRED_ON_CREATE,\n },\n deps,\n );\n};\n","// Job accessor (ADR-0004/0005/0011/0019): Read (search / searchAll / get) + Write\n// (create / update) over the generic resource factory. Only the Data-Type catalog and\n// names are Job-specific. P_Client / P_Recruiter are System[Reference] (Write = ID).\n//\n// Display-only Reference fields (P_Mail, P_*Reference — they mirror a Recruiter value and\n// are not writable) are intentionally left out of the catalog: they read through as raw\n// strings. Multi-select Option read returns every selected alias as `string[]` (ADR-0017).\n// The static Job / input types derive from the catalog (ADR-0019).\n\nimport type { Requester } from \"../http/requester\";\nimport {\n createResource,\n type CreateInput,\n type EmptyCatalog,\n type FieldCatalog,\n type ReadRecord,\n type Resource,\n type ResourcePage,\n type SearchQuery,\n type UpdateInput,\n} from \"./resource\";\n\nconst FIELDS = {\n P_Id: \"System[Id]\",\n P_Owner: \"User\",\n P_Client: \"System[Reference]\",\n P_Recruiter: \"System[Reference]\",\n P_RegistrationDate: \"System[DateTime]\",\n P_RegisteredBy: \"User\",\n P_UpdateDate: \"System[DateTime]\",\n P_UpdatedBy: \"User\",\n P_Phase: \"Option\",\n P_PhaseDate: \"DateTime\",\n P_PhaseMemo: \"MultilineText\",\n P_Position: \"SinglelineText\",\n P_Publish: \"Option\",\n P_JobCategorySummary: \"MultilineText\",\n P_JobCategory: \"Option\",\n P_IndustrySummary: \"MultilineText\",\n P_Industry: \"Option\",\n P_SalarySummary: \"MultilineText\",\n P_MinSalary: \"Number\",\n P_MaxSalary: \"Number\",\n P_AreaSummary: \"MultilineText\",\n P_Area: \"Option\",\n P_PayrollsText: \"SinglelineText\",\n P_Memo: \"MultilineText\",\n P_EmploymentPeriod: \"MultilineText\",\n // \"P_WokingHours\" is the alias as published by PORTERS (source typo); keep verbatim.\n P_WokingHours: \"MultilineText\",\n P_Holidays: \"MultilineText\",\n P_Benefits: \"MultilineText\",\n P_PubliclyTraded: \"Option\",\n P_SalesAmountText: \"SinglelineText\",\n P_EstablishmentDateText: \"SinglelineText\",\n P_CapitalText: \"SinglelineText\",\n P_EmploymentType: \"Option\",\n P_ExpectedAgeReason: \"Option\",\n} as const satisfies FieldCatalog;\n\n// Required on create per docs/reference (resources/job.md「新規必須」列): P_Owner / P_Client /\n// P_Recruiter(P_Id は System[Id]=lib 供給のため除外)。LV-5 は reference で確定。\nconst REQUIRED_ON_CREATE = [\n \"P_Owner\",\n \"P_Client\",\n \"P_Recruiter\",\n] as const satisfies readonly (keyof typeof FIELDS)[];\n\n/** A decoded Job: known `P_` fields, each requested field `value | null`. */\nexport type Job = ReadRecord<typeof FIELDS>;\nexport type JobPage = ResourcePage<typeof FIELDS>;\nexport type JobSearchQuery = SearchQuery<typeof FIELDS>;\n\n/** Fields for `create`: `P_Owner` required; `P_Id` / system timestamps are not settable. */\nexport type JobCreateInput = CreateInput<\n typeof FIELDS,\n (typeof REQUIRED_ON_CREATE)[number]\n>;\n/** Fields for `update`: all optional (`null` omits, `\"\"` clears a text field). */\nexport type JobUpdateInput = UpdateInput<typeof FIELDS>;\n/** The Job accessor; `C` is the declared custom-field catalog merged on (ADR-0023). */\nexport type JobResource<C extends FieldCatalog = EmptyCatalog> = Resource<\n typeof FIELDS & C,\n (typeof REQUIRED_ON_CREATE)[number]\n>;\n\nexport const createJobResource = <C extends FieldCatalog = EmptyCatalog>(\n deps: { requester: Requester; host: string; partition: number },\n custom?: C,\n): JobResource<C> => {\n // Custom U_/A_ aliases never collide with P_, so the merge is exactly `typeof FIELDS & C`;\n // the cast just names that intersection (defineFields already validated aliases — ADR-0023 D7).\n const fields = { ...FIELDS, ...custom } as typeof FIELDS & C;\n return createResource(\n {\n name: \"Job\",\n path: \"job\",\n prefix: \"Job\",\n fields,\n requiredOnCreate: REQUIRED_ON_CREATE,\n },\n deps,\n );\n};\n","// Client accessor (ADR-0004/0005/0011/0019): Read (search / searchAll / get) + Write\n// (create / update) over the generic resource factory. Only the Data-Type catalog and\n// names are Client-specific; the static Client / input types derive from the catalog\n// (ADR-0019).\n\nimport type { Requester } from \"../http/requester\";\nimport {\n createResource,\n type CreateInput,\n type EmptyCatalog,\n type FieldCatalog,\n type ReadRecord,\n type Resource,\n type ResourcePage,\n type SearchQuery,\n type UpdateInput,\n} from \"./resource\";\n\nconst FIELDS = {\n P_Id: \"System[Id]\",\n P_Owner: \"User\",\n P_RegistrationDate: \"System[DateTime]\",\n P_RegisteredBy: \"User\",\n P_UpdateDate: \"System[DateTime]\",\n P_UpdatedBy: \"User\",\n P_Phase: \"Option\",\n P_PhaseDate: \"DateTime\",\n P_PhaseMemo: \"MultilineText\",\n P_Name: \"SinglelineText\",\n P_Memo: \"MultilineText\",\n P_Country: \"SinglelineText\",\n P_Prefecture: \"SinglelineText\",\n P_City: \"SinglelineText\",\n P_Street: \"MultilineText\",\n P_Zipcode: \"SinglelineText\",\n P_Telephone: \"Telephone\",\n P_Fax: \"Telephone\",\n} as const satisfies FieldCatalog;\n\n// Required on create per docs/reference (resources/client.md「新規必須」列): P_Owner。\n// (P_Id は System[Id]=lib 供給のため除外。LV-5 は reference で確定。)\nconst REQUIRED_ON_CREATE = [\n \"P_Owner\",\n] as const satisfies readonly (keyof typeof FIELDS)[];\n\n/** A decoded Client (company): known `P_` fields, each requested field `value | null`. */\nexport type Client = ReadRecord<typeof FIELDS>;\nexport type ClientPage = ResourcePage<typeof FIELDS>;\nexport type ClientSearchQuery = SearchQuery<typeof FIELDS>;\n\n/** Fields for `create`: `P_Owner` required; `P_Id` / system timestamps are not settable. */\nexport type ClientCreateInput = CreateInput<\n typeof FIELDS,\n (typeof REQUIRED_ON_CREATE)[number]\n>;\n/** Fields for `update`: all optional (`null` omits, `\"\"` clears a text field). */\nexport type ClientUpdateInput = UpdateInput<typeof FIELDS>;\n/** The Client accessor; `C` is the declared custom-field catalog merged on (ADR-0023). */\nexport type ClientResource<C extends FieldCatalog = EmptyCatalog> = Resource<\n typeof FIELDS & C,\n (typeof REQUIRED_ON_CREATE)[number]\n>;\n\nexport const createClientResource = <C extends FieldCatalog = EmptyCatalog>(\n deps: { requester: Requester; host: string; partition: number },\n custom?: C,\n): ClientResource<C> => {\n // Custom U_/A_ aliases never collide with P_, so the merge is exactly `typeof FIELDS & C`;\n // the cast just names that intersection (defineFields already validated aliases — ADR-0023 D7).\n const fields = { ...FIELDS, ...custom } as typeof FIELDS & C;\n return createResource(\n {\n name: \"Client\",\n path: \"client\",\n prefix: \"Client\",\n fields,\n requiredOnCreate: REQUIRED_ON_CREATE,\n },\n deps,\n );\n};\n","// Process accessor (ADR-0004/0005/0011/0019): Read (search / searchAll / get) + Write\n// (create / update) over the generic resource factory. Process is the relational\n// resource linking a Candidate to a Job; P_Client / P_Recruiter / P_Job / P_Candidate /\n// P_Resume are System[Reference] (Write = the related record's id; P_Candidate is the\n// Person id).\n//\n// Display-only Reference fields (P_JobOwner, P_Job*Reference, P_ResumeOwner,\n// P_Resume*Reference — they mirror a Job/Recruiter/Person value and are not writable) are\n// intentionally left out of the catalog: scalar mirrors read through as raw strings,\n// nested ones (e.g. P_JobOwner -> a User) read as null. Multi-select Option read returns every\n// selected alias as `string[]` (ADR-0017). The static Process / input types derive from the catalog (ADR-0019).\n\nimport type { Requester } from \"../http/requester\";\nimport {\n createResource,\n type CreateInput,\n type EmptyCatalog,\n type FieldCatalog,\n type ReadRecord,\n type Resource,\n type ResourcePage,\n type SearchQuery,\n type UpdateInput,\n} from \"./resource\";\n\nconst FIELDS = {\n P_Id: \"System[Id]\",\n P_Owner: \"User\",\n P_Client: \"System[Reference]\",\n P_Recruiter: \"System[Reference]\",\n P_Job: \"System[Reference]\",\n P_Candidate: \"System[Reference]\",\n P_Resume: \"System[Reference]\",\n P_RegistrationDate: \"System[DateTime]\",\n P_RegisteredBy: \"User\",\n P_UpdateDate: \"System[DateTime]\",\n P_UpdatedBy: \"User\",\n P_Phase: \"Option\",\n P_PhaseDate: \"DateTime\",\n P_PhaseMemo: \"MultilineText\",\n P_Close: \"Option\",\n P_CloseReason: \"Option\",\n P_ExpectedSalesAmount: \"Number\",\n P_ExpectedClosingDate: \"Date\",\n} as const satisfies FieldCatalog;\n\n// Required on create per docs/reference (resources/process.md「新規必須」列): P_Owner と関連 5 項目\n// (P_Client / P_Recruiter / P_Job / P_Candidate / P_Resume)。P_Id は System[Id]=lib 供給で除外。\n// LV-5 は reference で確定。\nconst REQUIRED_ON_CREATE = [\n \"P_Owner\",\n \"P_Client\",\n \"P_Recruiter\",\n \"P_Job\",\n \"P_Candidate\",\n \"P_Resume\",\n] as const satisfies readonly (keyof typeof FIELDS)[];\n\n/** A decoded Process (a Candidate's progress through a Job): known `P_` fields, each\n * requested field `value | null`. */\nexport type Process = ReadRecord<typeof FIELDS>;\nexport type ProcessPage = ResourcePage<typeof FIELDS>;\nexport type ProcessSearchQuery = SearchQuery<typeof FIELDS>;\n\n/** Fields for `create`: `P_Owner` required; `P_Id` / system timestamps are not settable. */\nexport type ProcessCreateInput = CreateInput<\n typeof FIELDS,\n (typeof REQUIRED_ON_CREATE)[number]\n>;\n/** Fields for `update`: all optional (`null` omits, `\"\"` clears a text field). */\nexport type ProcessUpdateInput = UpdateInput<typeof FIELDS>;\n/** The Process accessor; `C` is the declared custom-field catalog merged on (ADR-0023). */\nexport type ProcessResource<C extends FieldCatalog = EmptyCatalog> = Resource<\n typeof FIELDS & C,\n (typeof REQUIRED_ON_CREATE)[number]\n>;\n\nexport const createProcessResource = <C extends FieldCatalog = EmptyCatalog>(\n deps: { requester: Requester; host: string; partition: number },\n custom?: C,\n): ProcessResource<C> => {\n // Custom U_/A_ aliases never collide with P_, so the merge is exactly `typeof FIELDS & C`;\n // the cast just names that intersection (defineFields already validated aliases — ADR-0023 D7).\n const fields = { ...FIELDS, ...custom } as typeof FIELDS & C;\n return createResource(\n {\n name: \"Process\",\n path: \"process\",\n prefix: \"Process\",\n fields,\n requiredOnCreate: REQUIRED_ON_CREATE,\n },\n deps,\n );\n};\n","// Resume accessor (ADR-0004/0005/0011/0019): Read (search / searchAll / get) + Write\n// (create / update) over the generic resource factory. A Resume belongs to a Candidate;\n// P_Candidate is System[Reference] (Write = the Person id).\n//\n// P_DateOfBirth is the Age Data Type — catalogued as \"Age\". Its wire value is the\n// birthdate (`yyyy/mm/dd`, same as Date); PORTERS derives the displayed age in its UI.\n// Display-only Reference fields (P_Mail, P_*Reference — they mirror a Person value and are\n// not writable) are intentionally left out of the catalog: scalar mirrors read through as\n// raw strings. Multi-select Option read returns every selected alias as `string[]` (ADR-0017).\n// Image-typed custom fields (U_) are future work. The static Resume / input types derive from the catalog (ADR-0019).\n\nimport type { Requester } from \"../http/requester\";\nimport {\n createResource,\n type CreateInput,\n type EmptyCatalog,\n type FieldCatalog,\n type ReadRecord,\n type Resource,\n type ResourcePage,\n type SearchQuery,\n type UpdateInput,\n} from \"./resource\";\n\nconst FIELDS = {\n P_Id: \"System[Id]\",\n P_Owner: \"User\",\n P_Candidate: \"System[Reference]\",\n P_RegistrationDate: \"System[DateTime]\",\n P_RegisteredBy: \"User\",\n P_UpdateDate: \"System[DateTime]\",\n P_UpdatedBy: \"User\",\n P_Phase: \"Option\",\n P_PhaseDate: \"DateTime\",\n P_PhaseMemo: \"MultilineText\",\n P_Name: \"SinglelineText\",\n P_RegisterChannel: \"Option\",\n P_Memo: \"MultilineText\",\n P_CurrentStatus: \"Option\",\n P_Education: \"MultilineText\",\n P_CarrierSummary: \"MultilineText\",\n P_CurrentSalary: \"Number\",\n P_ExperiencedJobCategory: \"Option\",\n P_ExperiencedIndustry: \"Option\",\n P_ChangeJobsCount: \"Number\",\n P_Gender: \"Option\",\n P_DateOfBirth: \"Age\",\n P_ExpectEmploymentType: \"Option\",\n P_ExpectArea: \"Option\",\n P_ExpectJobCategory: \"Option\",\n P_ExpectIndustry: \"Option\",\n P_ExpectCondition: \"MultilineText\",\n P_ExpectSalary: \"Number\",\n P_DesiredHourlyRate: \"Number\",\n P_HourlyRate: \"Number\",\n} as const satisfies FieldCatalog;\n\n// Required on create per docs/reference (resources/resume.md「新規必須」列): P_Owner / P_Candidate\n// (P_Id は System[Id]=lib 供給のため除外)。LV-5 は reference で確定。\nconst REQUIRED_ON_CREATE = [\n \"P_Owner\",\n \"P_Candidate\",\n] as const satisfies readonly (keyof typeof FIELDS)[];\n\n/** A decoded Resume (a Candidate's CV / profile): known `P_` fields, each requested field\n * `value | null`. */\nexport type Resume = ReadRecord<typeof FIELDS>;\nexport type ResumePage = ResourcePage<typeof FIELDS>;\nexport type ResumeSearchQuery = SearchQuery<typeof FIELDS>;\n\n/** Fields for `create`: `P_Owner` required; `P_Id` / system timestamps are not settable. */\nexport type ResumeCreateInput = CreateInput<\n typeof FIELDS,\n (typeof REQUIRED_ON_CREATE)[number]\n>;\n/** Fields for `update`: all optional (`null` omits, `\"\"` clears a text field). */\nexport type ResumeUpdateInput = UpdateInput<typeof FIELDS>;\n/** The Resume accessor; `C` is the declared custom-field catalog merged on (ADR-0023). */\nexport type ResumeResource<C extends FieldCatalog = EmptyCatalog> = Resource<\n typeof FIELDS & C,\n (typeof REQUIRED_ON_CREATE)[number]\n>;\n\nexport const createResumeResource = <C extends FieldCatalog = EmptyCatalog>(\n deps: { requester: Requester; host: string; partition: number },\n custom?: C,\n): ResumeResource<C> => {\n // Custom U_/A_ aliases never collide with P_, so the merge is exactly `typeof FIELDS & C`;\n // the cast just names that intersection (defineFields already validated aliases — ADR-0023 D7).\n const fields = { ...FIELDS, ...custom } as typeof FIELDS & C;\n return createResource(\n {\n name: \"Resume\",\n path: \"resume\",\n prefix: \"Resume\",\n fields,\n requiredOnCreate: REQUIRED_ON_CREATE,\n },\n deps,\n );\n};\n","// Attachment accessor (ADR-0018, bespoke): Read (search / get) + Write (create / update)\n// for file attachments. Attachment is unlike the other resources — no alias prefix, fixed\n// short field names (Id / Resource / ResourceId / ContentType / FileName / Content), and\n// `Content` is the Base64 file body (up to 10MB). It does not fit the generic factory but\n// reuses the requester, parsers, and `firstWriteResultId`. Turn raw bytes into the Base64\n// `content` with `util/base64`.\n\nimport { PortersConfigError } from \"../errors\";\nimport type { Requester } from \"../http/requester\";\nimport { encodeField } from \"../xml/encode\";\nimport { parseResourcePage } from \"../xml/parser\";\nimport { asString } from \"../xml/raw\";\nimport { buildWriteUrl, firstWriteResultId } from \"./resource\";\n\n// A 10MB file is ~13.98M Base64 chars; cap the encoded Content length before send\n// (fail-safe — the ~15000-char request guard is bypassed for uploads). docs/reference.\nconst MAX_CONTENT_CHARS = 14_000_000;\n\nconst ALL_FIELDS = [\n \"Id\",\n \"Resource\",\n \"ResourceId\",\n \"ContentType\",\n \"FileName\",\n \"Content\",\n];\n\n// Default for search() when `field` is omitted (ADR-0020): metadata only — exclude the (large,\n// up to ~14MB Base64) `Content` so listing attachments doesn't download every file body. Fetch\n// `Content` explicitly via `field` or per-record via get(). Mirrors PORTERS' Image default\n// (FileName only). `field: []` still opts into the API-native primary-key-only response.\nconst DEFAULT_FIELDS = [\n \"Id\",\n \"Resource\",\n \"ResourceId\",\n \"ContentType\",\n \"FileName\",\n];\n\n/** A decoded Attachment. A field is `null` unless it was returned (see `field`). */\nexport type Attachment = {\n id: number | null;\n /** Related resource type code (see the PORTERS Resource List). */\n resource: number | null;\n /** Related record id. */\n resourceId: number | null;\n contentType: string | null;\n fileName: string | null;\n /** Base64 file body. */\n content: string | null;\n};\n\nexport type AttachmentPage = {\n items: Attachment[];\n total: number;\n count: number;\n start: number;\n};\n\nexport type AttachmentSearchQuery = {\n /**\n * Output fields. **Omit** to fetch metadata by default (Id / Resource / ResourceId /\n * ContentType / FileName) — the large Base64 `Content` is excluded so listing doesn't download\n * every file body (ADR-0020); request `[\"Content\", …]` or use `get()` for the body. Pass `[]`\n * for the API-native primary-key-only response. A non-empty list is sent verbatim.\n */\n field?: string[];\n condition?: Record<string, string>;\n count?: number;\n start?: number;\n};\n\n/** Fields for creating an Attachment. `content` is the Base64 file body. */\nexport type AttachmentCreate = {\n resource: number;\n resourceId: number;\n contentType: string;\n fileName: string;\n content: string;\n};\n\n/** Fields for updating an Attachment. `Resource` / `ResourceId` are not updatable. */\nexport type AttachmentUpdate = {\n contentType?: string;\n fileName?: string;\n content?: string;\n};\n\nexport type AttachmentResource = {\n search(query?: AttachmentSearchQuery): Promise<AttachmentPage>;\n get(id: number): Promise<Attachment | undefined>;\n /** Create an Attachment; resolves to the newly assigned id. */\n create(input: AttachmentCreate): Promise<number>;\n /** Update an Attachment by id; resolves to that id. */\n update(id: number, input: AttachmentUpdate): Promise<number>;\n};\n\n// Bespoke Read URL (ADR-0018): Attachment has no alias prefix and no Data-Type catalog, so it keeps\n// the loose `condition` (`{ \"Id:eq\": \"123\" }`) and stays off the typed data-resource builder\n// (ADR-0038). itemstate/order/keywords do not apply to Attachment.\nconst buildAttachmentReadUrl = (\n host: string,\n partition: number,\n q: AttachmentSearchQuery,\n): string => {\n const p = new URLSearchParams();\n p.set(\"partition\", String(partition));\n if (q.field && q.field.length > 0) p.set(\"field\", q.field.join(\",\"));\n if (q.condition) {\n const conds = Object.entries(q.condition).map(([k, v]) => `${k}=${v}`);\n if (conds.length > 0) p.set(\"condition\", conds.join(\",\"));\n }\n if (q.count !== undefined) p.set(\"count\", String(q.count));\n if (q.start !== undefined) p.set(\"start\", String(q.start));\n return `https://${host}/v1/attachment?${p.toString()}`;\n};\n\nconst numOrNull = (v: unknown): number | null => {\n const s = asString(v);\n return s === undefined ? null : Number(s);\n};\n\nconst decodeAttachment = (item: Record<string, unknown>): Attachment => ({\n id: numOrNull(item.Id),\n resource: numOrNull(item.Resource),\n resourceId: numOrNull(item.ResourceId),\n contentType: asString(item.ContentType) ?? null,\n fileName: asString(item.FileName) ?? null,\n content: asString(item.Content) ?? null,\n});\n\n// Bare `<Tag>value</Tag>` (Attachment has no alias prefix). encodeField escapes the value.\nconst tag = (name: string, value: string | number): string =>\n `<${name}>${encodeField(\"SinglelineText\", String(value))}</${name}>`;\n\n// Reject an over-10MB file before send (the request size guard is bypassed for uploads).\nconst guardContent = (content: string | undefined): void => {\n if (content !== undefined && content.length > MAX_CONTENT_CHARS) {\n throw new PortersConfigError(\n `attachment content is ${content.length} characters, over the ~10MB file limit`,\n { category: \"config\", hint: \"Attachment files must be 10MB or less.\" },\n );\n }\n};\n\nexport const createAttachmentResource = (deps: {\n requester: Requester;\n host: string;\n partition: number;\n}): AttachmentResource => {\n // `field` omitted -> metadata default (no Content); `[]` -> API-native primary key only;\n // a provided list is sent verbatim (ADR-0020).\n const search = (query: AttachmentSearchQuery = {}): Promise<AttachmentPage> =>\n deps.requester.request(\n {\n method: \"GET\",\n url: buildAttachmentReadUrl(deps.host, deps.partition, {\n ...query,\n field: query.field ?? DEFAULT_FIELDS,\n }),\n headers: {},\n },\n (body) => {\n const page = parseResourcePage(body);\n return {\n items: page.items.map(decodeAttachment),\n total: page.total,\n count: page.count,\n start: page.start,\n };\n },\n );\n\n // VERIFY(live): Attachment has no alias prefix; the `Id:eq` condition and requesting all\n // fields (incl. Content) are taken from the field list, not a live contract.\n // See docs/live-verification.md (LV-3, LV-4).\n const get = async (id: number): Promise<Attachment | undefined> => {\n const page = await search({\n field: ALL_FIELDS,\n condition: { \"Id:eq\": String(id) },\n count: 1,\n });\n return page.items[0];\n };\n\n const write = (inner: string, idempotent: boolean): Promise<number> =>\n deps.requester.request(\n {\n method: \"POST\",\n url: buildWriteUrl(deps.host, deps.partition, \"attachment\"),\n headers: {},\n body: `<Attachment><Item>${inner}</Item></Attachment>`,\n },\n (body) => firstWriteResultId(body, \"attachment\", \"Attachment\"),\n { write: true, idempotent, unboundedBody: true },\n );\n\n // create forces Id=-1 (non-idempotent). All fields are required.\n const create = (input: AttachmentCreate): Promise<number> => {\n guardContent(input.content);\n const inner =\n tag(\"Id\", -1) +\n tag(\"Resource\", input.resource) +\n tag(\"ResourceId\", input.resourceId) +\n tag(\"ContentType\", input.contentType) +\n tag(\"FileName\", input.fileName) +\n tag(\"Content\", input.content);\n return write(inner, false);\n };\n\n // update targets the id (idempotent). Resource / ResourceId can't change; only the\n // provided fields are sent.\n const update = (id: number, input: AttachmentUpdate): Promise<number> => {\n guardContent(input.content);\n let inner = tag(\"Id\", id);\n if (input.contentType !== undefined) {\n inner += tag(\"ContentType\", input.contentType);\n }\n if (input.fileName !== undefined) inner += tag(\"FileName\", input.fileName);\n if (input.content !== undefined) inner += tag(\"Content\", input.content);\n return write(inner, true);\n };\n\n return { search, get, create, update };\n};\n","// Partition master accessor (read-only — ADR-0021/0022). Partition Read discovers the\n// partitions an App can access. It takes neither `partition` nor `field`/`condition`, only\n// `request_type`: 1 = the accessible-partition list (works under code_direct; the default),\n// 0 = the login partition (only under the browser `code` grant — 403s under code_direct, so\n// it is not exposed; ADR-0022 D3b). No `get(id)`: the API has no id/condition filter.\n\nimport type { Requester } from \"../http/requester\";\nimport {\n decoderFor,\n paginate,\n runRead,\n type FieldCatalog,\n type ReadRecord,\n type ResourcePage,\n} from \"./read-core\";\n\nconst FIELDS = {\n P_Id: \"System[Id]\",\n P_Name: \"SinglelineText\",\n P_CompanyId: \"SinglelineText\",\n} as const satisfies FieldCatalog;\n\n/** A decoded Partition (a PORTERS contract company / Company DB). */\nexport type Partition = ReadRecord<typeof FIELDS>;\nexport type PartitionPage = ResourcePage<typeof FIELDS>;\n\n/** Partition Read query. `requestType` 1 = partitions this App can access (default). */\nexport type PartitionSearchQuery = {\n /** 1 = accessible partitions (default). 0 = login partition (browser `code` grant only). */\n requestType?: 0 | 1;\n count?: number;\n start?: number;\n};\n\nexport type PartitionResource = {\n search(query?: PartitionSearchQuery): Promise<PartitionPage>;\n /** Auto-paginating search: yields every accessible partition. */\n searchAll(\n query?: Omit<PartitionSearchQuery, \"count\" | \"start\">,\n ): AsyncIterable<Partition>;\n};\n\n// VERIFY(live): Partition Read taking no `partition` param is doc-only (every other read\n// requires it). See docs/live-verification.md (LV-8).\nconst buildUrl = (host: string, q: PartitionSearchQuery): string => {\n const p = new URLSearchParams();\n p.set(\"request_type\", String(q.requestType ?? 1));\n if (q.count !== undefined) p.set(\"count\", String(q.count));\n if (q.start !== undefined) p.set(\"start\", String(q.start));\n return `https://${host}/v1/partition?${p.toString()}`;\n};\n\nexport const createPartitionResource = (deps: {\n requester: Requester;\n host: string;\n}): PartitionResource => {\n const decode = decoderFor(FIELDS);\n const search = (query: PartitionSearchQuery = {}): Promise<PartitionPage> =>\n runRead(deps.requester, buildUrl(deps.host, query), decode);\n const searchAll = (\n query: Omit<PartitionSearchQuery, \"count\" | \"start\"> = {},\n ): AsyncIterable<Partition> =>\n paginate((count, start) => search({ ...query, count, start }));\n return { search, searchAll };\n};\n","// User master accessor (read-only — ADR-0021/0022). User Read requires `partition` and\n// `request_type` (1 = all users; 0 = the current user — under code_direct this is the App's\n// own user, i.e. self-identification). `field` defaults to the 4 readable core fields, which\n// is exactly this catalog, so we omit it unless the caller narrows. No `condition`/`get(id)`:\n// the API has no id filter. Extended HR fields (department/telephone/dates/…) are deferred —\n// their read availability/decode shape is unconfirmed (see docs/live-verification.md).\n\nimport type { Requester } from \"../http/requester\";\nimport {\n decoderFor,\n paginate,\n runRead,\n type FieldCatalog,\n type ReadRecord,\n type ResourcePage,\n} from \"./read-core\";\n\nconst FIELDS = {\n P_Id: \"System[Id]\",\n P_Type: \"Number\",\n P_Name: \"SinglelineText\",\n P_Mail: \"Mail\",\n} as const satisfies FieldCatalog;\n\n/** A decoded User (PORTERS operator). `P_Type`: 0 = standard user, 1 = system admin. */\nexport type User = ReadRecord<typeof FIELDS>;\nexport type UserPage = ResourcePage<typeof FIELDS>;\n\n/** User Read query. `requestType` 1 = all users (default); `userType` -1 = any (default). */\nexport type UserSearchQuery = {\n /** 1 = all users (default). 0 = the current user (code_direct → the App's own user). */\n requestType?: 0 | 1;\n /** -1 = any (default), 0 = system admins, 1 = standard users. */\n userType?: -1 | 0 | 1;\n /** Output fields (prefixed aliases). Omit to get the 4 core fields (this catalog). */\n field?: string[];\n count?: number;\n start?: number;\n};\n\nexport type UserResource = {\n search(query?: UserSearchQuery): Promise<UserPage>;\n /** Auto-paginating search: yields every matching user. */\n searchAll(\n query?: Omit<UserSearchQuery, \"count\" | \"start\">,\n ): AsyncIterable<User>;\n /**\n * The current API user (`request_type=0`). Under the library's default `code_direct` auth\n * this resolves to the App's own user (username = app name) — useful for self-identification.\n * Under the browser `code` grant it is the logged-in user. Resolves `undefined` if none.\n */\n current(): Promise<User | undefined>;\n};\n\nconst buildUrl = (\n host: string,\n partition: number,\n q: UserSearchQuery,\n): string => {\n const p = new URLSearchParams();\n p.set(\"partition\", String(partition));\n p.set(\"request_type\", String(q.requestType ?? 1));\n p.set(\"user_type\", String(q.userType ?? -1));\n if (q.field && q.field.length > 0) p.set(\"field\", q.field.join(\",\"));\n if (q.count !== undefined) p.set(\"count\", String(q.count));\n if (q.start !== undefined) p.set(\"start\", String(q.start));\n return `https://${host}/v1/user?${p.toString()}`;\n};\n\nexport const createUserResource = (deps: {\n requester: Requester;\n host: string;\n partition: number;\n}): UserResource => {\n const decode = decoderFor(FIELDS);\n const search = (query: UserSearchQuery = {}): Promise<UserPage> =>\n runRead(deps.requester, buildUrl(deps.host, deps.partition, query), decode);\n const searchAll = (\n query: Omit<UserSearchQuery, \"count\" | \"start\"> = {},\n ): AsyncIterable<User> =>\n paginate((count, start) => search({ ...query, count, start }));\n // VERIFY(live): code_direct + request_type=0 returning the App's own user is doc-only.\n // See docs/live-verification.md (LV-7).\n const current = async (): Promise<User | undefined> =>\n (await search({ requestType: 0, count: 1 })).items[0];\n return { search, searchAll, current };\n};\n","// Field master accessor (read-only — ADR-0021/0022). Field Read introspects a resource's\n// field catalog (standard `P_` + tenant `U_`/`A_`). It requires `partition` and `resource`\n// (a resource-type Value code), plus optional `active`. No `field`/`condition`/`get(id)`.\n// `P_ReferTo` is a nested alias (the option group for Option-type fields, the parent field for\n// Reference-type) — decoded like an Option value to the referenced alias(es) (ADR-0022).\n\nimport type { Requester } from \"../http/requester\";\nimport {\n decoderFor,\n paginate,\n runRead,\n type FieldCatalog,\n type ReadRecord,\n type ResourcePage,\n} from \"./read-core\";\n\n// Resource-type selector -> Value code (docs/reference resources-list). Master/Phase/Attachment\n// have no Value, so only the R/W data resources are selectable here.\nconst RESOURCE_VALUE = {\n candidate: 1,\n job: 3,\n client: 5,\n recruiter: 9,\n sales: 11,\n contract: 13,\n resume: 17,\n activity: 19,\n opportunity: 25,\n contact: 27,\n} as const;\n\n/** A resource whose field catalog can be read (Field Read `resource` selector). */\nexport type ResourceType = keyof typeof RESOURCE_VALUE;\n\nconst FIELDS = {\n P_Id: \"System[Id]\",\n P_Name: \"SinglelineText\",\n P_Alias: \"SinglelineText\",\n P_Type: \"Number\",\n P_Required: \"Number\",\n P_Max: \"Number\",\n P_Min: \"Number\",\n P_DecimalFraction: \"Number\",\n // Nested alias(es): the referenced option group / parent field. Reuse Option decode -> the\n // referenced alias(es) as string[] (usually one); empty -> null (ADR-0017/0022).\n // VERIFY(live): Reference-type P_ReferTo nesting is doc-only. See docs/live-verification.md (LV-6).\n P_ReferTo: \"Option\",\n P_ResourceType: \"Number\",\n} as const satisfies FieldCatalog;\n\n/** A decoded Field definition. `P_Required`: 0 = normal, 1 = required. */\nexport type Field = ReadRecord<typeof FIELDS>;\nexport type FieldPage = ResourcePage<typeof FIELDS>;\n\n/** Field Read query. `resource` selects which resource's fields to read (required). */\nexport type FieldSearchQuery = {\n resource: ResourceType;\n /** -1 = all (default), 0 = unused only, 1 = in-use only. */\n active?: -1 | 0 | 1;\n count?: number;\n start?: number;\n};\n\nexport type FieldResource = {\n search(query: FieldSearchQuery): Promise<FieldPage>;\n /** Auto-paginating search: yields every field of the resource. */\n searchAll(\n query: Omit<FieldSearchQuery, \"count\" | \"start\">,\n ): AsyncIterable<Field>;\n};\n\nconst buildUrl = (\n host: string,\n partition: number,\n q: FieldSearchQuery,\n): string => {\n const p = new URLSearchParams();\n p.set(\"partition\", String(partition));\n p.set(\"resource\", String(RESOURCE_VALUE[q.resource]));\n p.set(\"active\", String(q.active ?? -1));\n if (q.count !== undefined) p.set(\"count\", String(q.count));\n if (q.start !== undefined) p.set(\"start\", String(q.start));\n return `https://${host}/v1/field?${p.toString()}`;\n};\n\nexport const createFieldResource = (deps: {\n requester: Requester;\n host: string;\n partition: number;\n}): FieldResource => {\n const decode = decoderFor(FIELDS);\n const search = (query: FieldSearchQuery): Promise<FieldPage> =>\n runRead(deps.requester, buildUrl(deps.host, deps.partition, query), decode);\n const searchAll = (\n query: Omit<FieldSearchQuery, \"count\" | \"start\">,\n ): AsyncIterable<Field> =>\n paginate((count, start) => search({ ...query, count, start }));\n return { search, searchAll };\n};\n","// Option master accessor (read-only — ADR-0021/0022). Option Read returns a tenant's choice\n// master as a recursive tree: each <Item> nests child <Item>s under <Items>. We flatten the\n// tree depth-first into one array — every node present, parent linkage kept via `P_ParentId`\n// and ordering via `P_Order` (ADR-0021 軸3, case 3a). It requires `partition` and takes\n// `alias`/`level`/`enabled`/`count` — no `start` (no offset paging → no searchAll), no\n// `field`/`condition`/`get(id)`.\n\nimport type { Requester } from \"../http/requester\";\nimport { parseResourcePage, type RawItem } from \"../xml/parser\";\nimport { asArray, asRecord } from \"../xml/raw\";\nimport { decoderFor, type FieldCatalog, type ReadRecord } from \"./read-core\";\n\nconst FIELDS = {\n P_Id: \"System[Id]\",\n P_Name: \"SinglelineText\",\n P_Alias: \"SinglelineText\",\n P_ParentId: \"Number\",\n P_Type: \"Number\",\n P_Order: \"Number\",\n} as const satisfies FieldCatalog;\n\n/** A decoded Option (one choice). `P_ParentId` links to the parent; `P_Type` 0 = normal, 1–11 = a phase kind. */\nexport type Option = ReadRecord<typeof FIELDS>;\n\n/** Option Read query. `alias` selects a subtree root; `level` its depth (-1 all). */\nexport type OptionSearchQuery = {\n /** Root alias of the subtree to read (e.g. `Option.P_Gender`). Omit for all. */\n alias?: string;\n /** Depth: -1 all (default), 0 = siblings of `alias`, 1+ = descendants. */\n level?: number;\n /** -1 = all (default), 0 = unused only, 1 = in-use only. */\n enabled?: -1 | 0 | 1;\n count?: number;\n};\n\nexport type OptionResource = {\n /** Read options, flattened depth-first (all nodes; tree is reconstructable via `P_ParentId`). */\n search(query?: OptionSearchQuery): Promise<Option[]>;\n};\n\nconst buildUrl = (\n host: string,\n partition: number,\n q: OptionSearchQuery,\n): string => {\n const p = new URLSearchParams();\n p.set(\"partition\", String(partition));\n if (q.alias !== undefined) p.set(\"alias\", q.alias);\n if (q.level !== undefined) p.set(\"level\", String(q.level));\n if (q.enabled !== undefined) p.set(\"enabled\", String(q.enabled));\n if (q.count !== undefined) p.set(\"count\", String(q.count));\n return `https://${host}/v1/option?${p.toString()}`;\n};\n\n// Decode one node's own fields, dropping the nested `Items` collection (handled by the walk).\nconst withoutItems = (raw: RawItem): RawItem =>\n Object.fromEntries(Object.entries(raw).filter(([k]) => k !== \"Items\"));\n\nexport const createOptionResource = (deps: {\n requester: Requester;\n host: string;\n partition: number;\n}): OptionResource => {\n const decode = decoderFor(FIELDS);\n // Depth-first flatten: push each node, then recurse into its <Items><Item>… children.\n const flatten = (items: RawItem[], out: Option[]): void => {\n for (const raw of items) {\n out.push(decode(withoutItems(raw)));\n const children = asArray(asRecord(raw.Items)?.Item).map(\n (it) => asRecord(it) ?? {},\n );\n flatten(children, out);\n }\n };\n const search = (query: OptionSearchQuery = {}): Promise<Option[]> =>\n deps.requester.request(\n {\n method: \"GET\",\n url: buildUrl(deps.host, deps.partition, query),\n headers: {},\n },\n (body) => {\n const out: Option[] = [];\n flatten(parseResourcePage(body).items, out);\n return out;\n },\n );\n return { search };\n};\n","import { createAuthApi, createDefaultTokenProvider } from \"./auth\";\nimport type {\n AuthApi,\n AuthProviderControls,\n TokenProvider,\n TokenStore,\n} from \"./auth\";\nimport {\n createFetchTransport,\n createRequester,\n createThrottle,\n expoBackoff,\n} from \"./http\";\nimport type { Transport } from \"./http\";\nimport {\n createAttachmentResource,\n createCandidateResource,\n createClientResource,\n createFieldResource,\n createJobResource,\n createOptionResource,\n createPartitionResource,\n createProcessResource,\n createResumeResource,\n createUserResource,\n} from \"./resources\";\nimport type {\n AttachmentResource,\n CandidateResource,\n ClientResource,\n FieldResource,\n JobResource,\n OptionResource,\n PartitionResource,\n ProcessResource,\n ResumeResource,\n UserResource,\n} from \"./resources\";\nimport type { CustomFor, DeclaredCatalogs, DefinedFields } from \"./fields\";\nimport type { EmptyCatalog } from \"./resources/read-core\";\nimport type { PartitionId, Scope } from \"./types\";\n\n/** Options for constructing a {@link PortersClient}. `C` is inferred from `fields` (ADR-0023). */\nexport type PortersClientOptions<C extends DeclaredCatalogs = EmptyCatalog> = {\n /**\n * API host. Required and supplied via `PORTERS_HOST` — never hard-code it.\n * (A representative value lives in docs/reference.)\n */\n host: string;\n appId?: string;\n appSecret?: string;\n scopes?: Scope[];\n /**\n * Default partition (Company DB) for every call. For multi-tenant routing, bind a partition\n * per call with {@link PortersClient.tenant} (ADR-0040 / F-3); for a fully separated per-partition\n * token, construct a dedicated client per tenant instead (ADR-0008 案3).\n */\n partition?: PartitionId;\n /** Custom auth strategy; defaults to the transparent code_direct strategy. */\n auth?: TokenProvider;\n /** Token persistence; defaults to in-memory. */\n tokenStore?: TokenStore;\n /** Injectable HTTP transport; defaults to a fetch-based transport. */\n transport?: Transport;\n /**\n * Tenant custom field declarations from {@link defineFields} (ADR-0023). Each resource's\n * declared `U_`/`A_` fields are merged onto its static catalog, so they decode/encode by\n * their declared Data Type and appear typed on reads / writes. Omit for standard `P_` only.\n */\n fields?: DefinedFields<C>;\n};\n\n/**\n * The partition-bound resource accessors returned by {@link PortersClient.tenant} (ADR-0040 / F-3).\n * Every accessor here routes to the bound tenant's partition. `auth` (App-level), the `partition`\n * master (discovery — partition-less), and `tenant` itself (no nesting) are deliberately absent.\n */\nexport type TenantScope<C extends DeclaredCatalogs = EmptyCatalog> = {\n readonly candidate: CandidateResource<CustomFor<C, \"candidate\">>;\n readonly job: JobResource<CustomFor<C, \"job\">>;\n readonly client: ClientResource<CustomFor<C, \"client\">>;\n readonly process: ProcessResource<CustomFor<C, \"process\">>;\n readonly resume: ResumeResource<CustomFor<C, \"resume\">>;\n readonly attachment: AttachmentResource;\n readonly user: UserResource;\n readonly field: FieldResource;\n readonly option: OptionResource;\n};\n\n/**\n * Entry point of the library. Wires the default transport / auth / throttle /\n * requester and exposes namespaced resource accessors such as `candidate`\n * (ADR-0005).\n */\nexport class PortersClient<C extends DeclaredCatalogs = EmptyCatalog> {\n readonly candidate: CandidateResource<CustomFor<C, \"candidate\">>;\n readonly job: JobResource<CustomFor<C, \"job\">>;\n readonly client: ClientResource<CustomFor<C, \"client\">>;\n readonly process: ProcessResource<CustomFor<C, \"process\">>;\n readonly resume: ResumeResource<CustomFor<C, \"resume\">>;\n readonly attachment: AttachmentResource;\n /** OAuth surface: initial browser grant, token warm-up/inspection, local revoke (ADR-0007/0034). */\n readonly auth: AuthApi;\n /** Master Read: accessible partitions (ADR-0021/0022). */\n readonly partition: PartitionResource;\n /** Master Read: users, plus `current()` self-identification (ADR-0021/0022). */\n readonly user: UserResource;\n /** Master Read: a resource's field catalog (ADR-0021/0022). */\n readonly field: FieldResource;\n /** Master Read: a tenant's choice (option) master (ADR-0021/0022). */\n readonly option: OptionResource;\n /**\n * Bind a tenant's partition (Company DB) once and route every call through it — the multi-tenant\n * scope (ADR-0008 案2 / renamed in ADR-0021 / implemented in ADR-0040 F-3).\n * `porters.tenant(123).candidate.search(...)` sends `partition=123` without repeating it, overriding\n * the client-default `partition`. Returns the partition-bound accessors (data + attachment + master\n * User/Field/Option); `auth` (App-level), the `partition` master (discovery — takes no partition),\n * and `tenant` itself (no nesting) are intentionally omitted. For a fully separated per-partition\n * token, construct a dedicated {@link PortersClient} per tenant instead (ADR-0008 案3).\n */\n readonly tenant: (id: PartitionId) => TenantScope<C>;\n readonly #host: string;\n\n constructor(options: PortersClientOptions<C>) {\n const transport = options.transport ?? createFetchTransport();\n // Custom strategy (案3) takes over token supply; otherwise the default transparent\n // provider also exposes cache/clear controls for the auth surface (ADR-0034 SD-7/SD-8).\n let auth: TokenProvider;\n let controls: AuthProviderControls | undefined = undefined;\n if (options.auth) {\n auth = options.auth;\n } else {\n const provider = createDefaultTokenProvider({\n host: options.host,\n appId: options.appId ?? \"\",\n appSecret: options.appSecret ?? \"\",\n transport,\n tokenStore: options.tokenStore,\n });\n auth = provider;\n controls = provider;\n }\n this.auth = createAuthApi({\n host: options.host,\n appId: options.appId,\n appSecret: options.appSecret,\n scopes: options.scopes,\n transport,\n provider: auth,\n controls,\n });\n const requester = createRequester({\n transport,\n auth,\n throttle: createThrottle(),\n backoff: expoBackoff(),\n });\n this.#host = options.host;\n // The per-resource custom catalog declared via defineFields (or {} when none). Branded\n // = already validated (ADR-0023 D4), so the factory merges it without re-checking.\n const customFor = <K extends keyof DeclaredCatalogs>(\n key: K,\n ): CustomFor<C, K> => (options.fields?.[key] ?? {}) as CustomFor<C, K>;\n // Build the partition-bound accessor bundle for a given partition. The root client uses the\n // default partition; `tenant(id)` re-binds it (ADR-0040 / F-3) by re-running the same factories\n // with `partition` overridden — resources are already `deps.partition`-driven, so the factories\n // need no change. Partition Read is App-level (no partition) and built once below, not here.\n const buildScope = (partition: number): TenantScope<C> => {\n const deps = { requester, host: options.host, partition };\n return {\n candidate: createCandidateResource(deps, customFor(\"candidate\")),\n job: createJobResource(deps, customFor(\"job\")),\n client: createClientResource(deps, customFor(\"client\")),\n process: createProcessResource(deps, customFor(\"process\")),\n resume: createResumeResource(deps, customFor(\"resume\")),\n attachment: createAttachmentResource(deps),\n user: createUserResource(deps),\n field: createFieldResource(deps),\n option: createOptionResource(deps),\n };\n };\n this.tenant = buildScope;\n const root = buildScope(options.partition ?? 0);\n this.candidate = root.candidate;\n this.job = root.job;\n this.client = root.client;\n this.process = root.process;\n this.resume = root.resume;\n this.attachment = root.attachment;\n this.user = root.user;\n this.field = root.field;\n this.option = root.option;\n // Partition Read takes no `partition` param (it discovers them); App-level, not tenant-bound.\n this.partition = createPartitionResource({ requester, host: options.host });\n }\n\n /** The configured API host. */\n get host(): string {\n return this.#host;\n }\n}\n","// Custom field declaration DSL (ADR-0023, grounding ADR-0004 案H / ADR-0005 SD-2).\n// `defineFields` is the single validation boundary: a typed builder declares each\n// tenant custom field's Data Type per data resource, validation runs synchronously,\n// and the result is branded so PortersClient trusts it without re-validating. Standard\n// `P_` fields come from the static catalogs (ADR-0019); this only covers custom U_/A_.\n\nimport { PortersConfigError } from \"../errors\";\nimport type { EmptyCatalog } from \"../resources/read-core\";\nimport type { DataType } from \"../xml/decode\";\n\n/** One custom field's declared Data Type — the builder's return value (ADR-0023 D2). */\nexport type FieldDef<D extends DataType> = { readonly dataType: D };\n\n// Data Types a custom U_/A_ field may declare (ADR-0023 D3): the value-shaped types. The\n// System family (System[Id]/[DateTime]/[Reference]) is system-managed = standard territory,\n// so it is not offered; Image / Link are not modelled in DataType yet (future work).\nexport type CustomDataType =\n | \"Number\"\n | \"SinglelineText\"\n | \"MultilineText\"\n | \"Mail\"\n | \"Telephone\"\n | \"URL\"\n | \"Date\"\n | \"DateTime\"\n | \"Age\"\n | \"Option\"\n | \"User\";\n\n/** Builder passed to each resource declaration: one method per declarable Data Type. */\nexport type FieldBuilder = {\n number(): FieldDef<\"Number\">;\n singlelineText(): FieldDef<\"SinglelineText\">;\n multilineText(): FieldDef<\"MultilineText\">;\n mail(): FieldDef<\"Mail\">;\n telephone(): FieldDef<\"Telephone\">;\n url(): FieldDef<\"URL\">;\n date(): FieldDef<\"Date\">;\n dateTime(): FieldDef<\"DateTime\">;\n age(): FieldDef<\"Age\">;\n option(): FieldDef<\"Option\">;\n user(): FieldDef<\"User\">;\n};\n\n/** Data resources that accept custom fields (ADR-0023 D6). Master / Attachment are excluded. */\nexport type CustomFieldResource =\n | \"candidate\"\n | \"job\"\n | \"client\"\n | \"process\"\n | \"resume\";\n\n/** One resource's custom field declarations: alias -> {@link FieldDef}. */\nexport type ResourceDecl = Record<string, FieldDef<DataType>>;\n\n/** Declaration input: per (data) resource, a builder fn returning its custom fields. */\nexport type FieldDecls = {\n [R in CustomFieldResource]?: (f: FieldBuilder) => ResourceDecl;\n};\n\n/** A per-resource custom catalog (bare alias -> Data Type), as produced by {@link defineFields}. */\nexport type CustomCatalog = Record<string, DataType>;\n\n/** Map of (data) resource -> its custom catalog; the client merges these into the static catalogs. */\nexport type DeclaredCatalogs = {\n [R in CustomFieldResource]?: CustomCatalog;\n};\n\n// Extract the catalog (alias -> Data Type literal) from a resource's FieldDef map.\ntype CatalogOf<R extends ResourceDecl> = {\n [K in keyof R]: R[K][\"dataType\"];\n};\n\n/** The validated, branded result of {@link defineFields}, keyed by the declared resources. */\nexport type DeclaredCatalogsOf<D extends FieldDecls> = {\n [R in keyof D]: D[R] extends (f: FieldBuilder) => infer Out\n ? Out extends ResourceDecl\n ? CatalogOf<Out>\n : never\n : never;\n};\n\n// Phantom brand: marks a catalog set as already validated by defineFields (ADR-0023 D4).\n// It never exists at runtime — the value is a plain frozen object.\ndeclare const definedFieldsBrand: unique symbol;\n\n/** A validated set of custom field catalogs (branded — the client does not re-validate). */\nexport type DefinedFields<C extends DeclaredCatalogs = DeclaredCatalogs> = C & {\n readonly [definedFieldsBrand]: true;\n};\n\n/** The custom catalog declared for resource `K` (or `{}` if none) — types each accessor (ADR-0023 D1). */\nexport type CustomFor<\n C extends DeclaredCatalogs,\n K extends CustomFieldResource,\n> = K extends keyof C\n ? C[K] extends CustomCatalog\n ? C[K]\n : EmptyCatalog\n : EmptyCatalog;\n\n// 全 arrow(ADR-0013)=巻き上げ無しのため、ヘルパー → builder → defineFields の順で定義する。\nconst def = <D extends CustomDataType>(dataType: D): FieldDef<D> => ({\n dataType,\n});\n\nconst builder: FieldBuilder = {\n number: () => def(\"Number\"),\n singlelineText: () => def(\"SinglelineText\"),\n multilineText: () => def(\"MultilineText\"),\n mail: () => def(\"Mail\"),\n telephone: () => def(\"Telephone\"),\n url: () => def(\"URL\"),\n date: () => def(\"Date\"),\n dateTime: () => def(\"DateTime\"),\n age: () => def(\"Age\"),\n option: () => def(\"Option\"),\n user: () => def(\"User\"),\n};\n\n// Custom field aliases are `U_[Name]` (user-created) or `A_[Name]` (app-created) — ADR-0004.\nconst ALIAS_PATTERN = /^[UA]_/;\n\nconst KNOWN_RESOURCES: readonly CustomFieldResource[] = [\n \"candidate\",\n \"job\",\n \"client\",\n \"process\",\n \"resume\",\n];\n\n/**\n * Declare tenant-specific custom fields per data resource (ADR-0023). This is the validation\n * boundary: it throws {@link PortersConfigError} synchronously for an unknown resource key or an\n * alias that is not `U_`/`A_`-prefixed. The branded result is passed to `PortersClient({ fields })`,\n * which merges each catalog into the resource so the custom fields decode/encode by their declared\n * Data Type and appear typed on reads / writes.\n *\n * @example\n * const myFields = defineFields({\n * candidate: (f) => ({ U_score: f.number(), U_source: f.option() }),\n * });\n */\nexport const defineFields = <D extends FieldDecls>(\n decls: D,\n): DefinedFields<DeclaredCatalogsOf<D>> => {\n const catalogs: Record<string, CustomCatalog> = {};\n for (const [resource, declare] of Object.entries(decls)) {\n if (declare === undefined) continue;\n if (!KNOWN_RESOURCES.includes(resource as CustomFieldResource)) {\n throw new PortersConfigError(\n `defineFields: unknown resource \"${resource}\" (expected one of ${KNOWN_RESOURCES.join(\", \")})`,\n { category: \"config\" },\n );\n }\n const catalog: CustomCatalog = {};\n for (const [alias, fieldDef] of Object.entries(declare(builder))) {\n if (!ALIAS_PATTERN.test(alias)) {\n throw new PortersConfigError(\n `defineFields: custom field alias \"${alias}\" on \"${resource}\" must start with \"U_\" or \"A_\" (standard P_ fields are built in)`,\n { category: \"config\" },\n );\n }\n catalog[alias] = fieldDef.dataType;\n }\n catalogs[resource] = catalog;\n }\n return Object.freeze(catalogs) as DefinedFields<DeclaredCatalogsOf<D>>;\n};\n","// Opt-in binary <-> Base64 helpers for Attachment / Image content (ADR-0018). The\n// resource core takes a Base64 string; these let callers convert raw bytes without a\n// dependency. `btoa` / `atob` are globals on Node 20+ and browsers.\n\n/** Encode raw bytes to a Base64 string. */\nexport const bytesToBase64 = (bytes: Uint8Array): string => {\n // Build a Latin-1 \"binary string\" then Base64 it. O(n) string building — fine for\n // typical attachments; very large files can be encoded by the caller upstream.\n let binary = \"\";\n for (const b of bytes) binary += String.fromCharCode(b);\n return btoa(binary);\n};\n\n/** Decode a Base64 string back to raw bytes. */\nexport const base64ToBytes = (b64: string): Uint8Array =>\n Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));\n"],"mappings":"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","names":["sleep","tag","FIELDS","REQUIRED_ON_CREATE","FIELDS","REQUIRED_ON_CREATE","FIELDS","REQUIRED_ON_CREATE","FIELDS","REQUIRED_ON_CREATE","FIELDS","FIELDS","buildUrl","FIELDS","buildUrl","FIELDS","buildUrl"]}
1
+ {"version":3,"sources":["../src/errors/porters-error.ts","../src/errors/classify.ts","../src/xml/parser.ts","../src/xml/raw.ts","../src/auth/memory-store.ts","../src/auth/token-exchange.ts","../src/auth/token-provider.ts","../src/auth/auth-api.ts","../src/http/fetch-transport.ts","../src/http/mock-transport.ts","../src/http/throttle.ts","../src/http/retry.ts","../src/http/requester.ts","../src/util/datetime.ts","../src/xml/encode.ts","../src/xml/decode.ts","../src/resources/read-core.ts","../src/resources/query.ts","../src/resources/bulk-write.ts","../src/resources/resource.ts","../src/resources/candidate.ts","../src/resources/job.ts","../src/resources/client.ts","../src/resources/process.ts","../src/resources/resume.ts","../src/resources/attachment.ts","../src/resources/partition.ts","../src/resources/user.ts","../src/resources/field.ts","../src/resources/option.ts","../src/client.ts","../src/fields/define-fields.ts","../src/util/base64.ts"],"sourcesContent":["// PortersError hierarchy (ADR-0006): source-split subclasses + a cross-cutting\n// `category`. Never swallow errors; always surface a PortersError.\n\n/** Cross-cutting classification shared by every PORTERS error. */\nexport type ErrorCategory =\n | \"auth\"\n | \"permission\"\n | \"validation\"\n | \"notFound\"\n | \"conflict\"\n // 予約(現状どの分類関数も produce しない)。PORTERS はレート超過時に判別可能なコードを\n // 返さず接続を切るため、強制切断は PortersNetworkError(category \"network\")として表面化する。\n // 将来 429 相当の判別手段が得られたら配線するため型には残す(RV-3)。\n | \"rateLimit\"\n | \"transient\"\n | \"network\"\n | \"server\"\n | \"config\"\n | \"unknown\";\n\n/** Where the failing call was aimed (for self-service debugging). */\nexport type PortersErrorContext = {\n resource?: string;\n operation?: string;\n partition?: number;\n};\n\n/** Construction options for {@link PortersError}. */\nexport type PortersErrorOptions = {\n category: ErrorCategory;\n /** PORTERS raw code; `null` for network/transport failures. */\n code?: number | null;\n retryable?: boolean;\n /** Actionable hint (English by default). */\n hint?: string;\n httpStatus?: number;\n context?: PortersErrorContext;\n cause?: unknown;\n};\n\n/** Base class for every PORTERS-originated error (catch-all). */\nexport class PortersError extends Error {\n readonly category: ErrorCategory;\n readonly code: number | null;\n readonly retryable: boolean;\n readonly hint?: string;\n readonly httpStatus?: number;\n readonly context?: PortersErrorContext;\n\n constructor(message: string, options: PortersErrorOptions) {\n super(\n message,\n options.cause === undefined ? undefined : { cause: options.cause },\n );\n this.name = new.target.name;\n this.category = options.category;\n this.code = options.code ?? null;\n this.retryable = options.retryable ?? false;\n this.hint = options.hint;\n this.httpStatus = options.httpStatus;\n this.context = options.context;\n }\n}\n\n/** OAuth / Token errors. */\nexport class PortersAuthError extends PortersError {}\n\n/** Resource API errors. */\nexport class PortersResourceError extends PortersError {}\n\n/** Connection / timeout / forced rate-limit disconnect. */\nexport class PortersNetworkError extends PortersError {}\n\n/** Misconfiguration / misuse — not PORTERS-originated; thrown synchronously. */\nexport class PortersConfigError extends PortersError {}\n","// Code -> category -> retryable classification and PortersError factories\n// (ADR-0006 / result-codes.md). Unknown codes fall through to `category:\n// \"unknown\"` — never swallowed (fail-safe).\n\nimport {\n PortersAuthError,\n PortersNetworkError,\n PortersResourceError,\n type ErrorCategory,\n type PortersErrorContext,\n} from \"./porters-error\";\n\nconst RESOURCE_VALIDATION = new Set([8, 124, 126, 127, 133, 146, 500]);\n\n/** Resource API `<Code>` -> category (ADR-0006). */\nexport const resourceCategory = (code: number): ErrorCategory => {\n if (code === 9 || code === 302) return \"transient\";\n if (code === 401 || code === 402) return \"auth\";\n if (\n code === 6 ||\n code === 400 ||\n code === 403 ||\n code === 406 ||\n code === 601\n )\n return \"permission\";\n if (code === 7 || code === 404) return \"notFound\";\n if (code === 301 || code === 303 || code === 304) return \"conflict\";\n if (code === 1000) return \"server\";\n if (RESOURCE_VALIDATION.has(code) || (code >= 100 && code <= 116))\n return \"validation\";\n return \"unknown\";\n};\n\n/** Authentication API `<Error>` -> category (ADR-0006). */\nexport const authCategory = (code: number): ErrorCategory => {\n if (code === 400) return \"auth\";\n if ([401, 103, 104, 105, 106, 107, 109, 114, 117].includes(code))\n return \"auth\";\n if ([100, 101, 102, 110, 112].includes(code)) return \"validation\";\n if ([111, 115, 116, 402].includes(code)) return \"permission\";\n if (code === 108) return \"server\";\n return \"unknown\";\n};\n\nconst resourceHint = (code: number): string | undefined => {\n if (code === 403)\n return \"No data permission. Run the initial browser `code` grant for this Company DB, or check scopes.\";\n if (code === 404)\n return \"Partition not found or outside the contract period. Verify the partition id.\";\n return undefined;\n};\n\n/** Build a PortersResourceError from a Resource API `<Code>`. */\nexport const resourceError = (\n code: number,\n message: string,\n context?: PortersErrorContext,\n): PortersResourceError => {\n const category = resourceCategory(code);\n return new PortersResourceError(message, {\n category,\n code,\n retryable: category === \"transient\",\n hint: resourceHint(code),\n context,\n });\n};\n\n/** Build a PortersAuthError from an Authentication API `<Error>`. */\nexport const authError = (code: number, message: string): PortersAuthError => {\n const category = authCategory(code);\n return new PortersAuthError(message, {\n category,\n code,\n retryable: false,\n hint:\n category === \"auth\"\n ? \"Authentication failed; re-authenticate (browser `code` grant) or check app credentials.\"\n : undefined,\n });\n};\n\n/** Build a PortersNetworkError (no PORTERS code; retryable for idempotent ops). */\nexport const networkError = (\n message: string,\n cause?: unknown,\n): PortersNetworkError =>\n new PortersNetworkError(message, {\n category: \"network\",\n retryable: true,\n cause,\n });\n","// XML parsing + error routing (ADR-0011). The parser returns raw strings\n// (`parseTagValue: false`); all type coercion happens in `decode.ts`.\n\nimport { XMLParser } from \"fast-xml-parser\";\n\nimport { authError, resourceError } from \"../errors/classify\";\nimport { PortersAuthError, PortersResourceError } from \"../errors/index\";\nimport { asArray, asRecord, asString } from \"./raw\";\n\nconst parser = new XMLParser({\n ignoreAttributes: false,\n attributeNamePrefix: \"@_\",\n ignoreDeclaration: true,\n parseTagValue: false,\n parseAttributeValue: false,\n trimValues: true,\n // asArray() already normalizes a single/missing/repeated <Item> into an array,\n // so isArray is belt-and-suspenders: these mutants are equivalent (no test can\n // observe the difference once asArray() runs).\n // Stryker disable next-line ArrowFunction,ConditionalExpression,StringLiteral: equivalent — asArray() normalizes regardless\n isArray: (name) => name === \"Item\",\n});\n\n// fast-xml-parser yields raw strings; coerce an attribute/code node to an int,\n// treating a missing node as 0. The explicit `undefined` check keeps the\n// fallback observable — `Number(\"\") === 0`, so a `?? \"0\"` default would be an\n// equivalent mutant.\nconst toInt = (v: unknown): number => {\n const s = asString(v);\n return s === undefined ? 0 : Number(s);\n};\n\n/** One `<Item>`: a map of field alias -> raw node (string or nested object). */\nexport type RawItem = Record<string, unknown>;\n\nexport type ResourcePage = {\n total: number;\n count: number;\n start: number;\n items: RawItem[];\n};\n\n/**\n * Parse a Resource Read response. Reads `<Code>` first and, if non-zero, throws\n * the mapped PortersError (ADR-0006) — HTTP 200 + `<Code>≠0` is an error, not\n * data.\n */\nexport const parseResourcePage = (xml: string): ResourcePage => {\n const root = asRecord(parser.parse(xml) as unknown);\n const rootKey = root ? Object.keys(root)[0] : undefined;\n // `root` is always a record here and `root[rootKey]` is undefined exactly when\n // rootKey is, so dropping/forcing either guard collapses to the same throw.\n // Stryker disable next-line ConditionalExpression,LogicalOperator: equivalent — both branches converge on the unparseable throw\n const body = root && rootKey ? asRecord(root[rootKey]) : undefined;\n if (!body) {\n throw new PortersResourceError(\"unparseable resource response\", {\n category: \"unknown\",\n });\n }\n\n const code = toInt(body.Code);\n if (code !== 0) {\n throw resourceError(code, `resource returned code ${code}`, {\n resource: rootKey,\n });\n }\n\n return {\n total: toInt(body[\"@_Total\"]),\n count: toInt(body[\"@_Count\"]),\n start: toInt(body[\"@_Start\"]),\n items: asArray(body.Item).map((it) => asRecord(it) ?? {}),\n };\n};\n\n/** One written record's outcome: the assigned/updated `Id` and its Result `Code`. */\nexport type WriteResultItem = {\n id: number;\n code: number;\n};\n\n/**\n * Parse a Resource Write response. Unlike Read there is no root `<Code>` nor\n * Total/Count/Start: each `<Item>` carries its own `<Id>` (assigned on create /\n * echoed on update) and `<Code>` (per-item Result Code). Applying the per-item\n * code policy (throw on `!= 0`) is the accessor's job, since a bulk write mixes\n * successes and failures — see write-format.md.\n */\nexport const parseWriteResult = (xml: string): WriteResultItem[] => {\n const root = asRecord(parser.parse(xml) as unknown);\n const rootKey = root ? Object.keys(root)[0] : undefined;\n // Same equivalence as parseResourcePage: both guards converge on the throw.\n // Stryker disable next-line ConditionalExpression,LogicalOperator: equivalent — both branches converge on the unparseable throw\n const body = root && rootKey ? asRecord(root[rootKey]) : undefined;\n if (!body) {\n throw new PortersResourceError(\"unparseable write response\", {\n category: \"unknown\",\n });\n }\n\n return asArray(body.Item).map((it) => {\n const item = asRecord(it) ?? {};\n return { id: toInt(item.Id), code: toInt(item.Code) };\n });\n};\n\n/** Parsed `<Authentication>` response (OAuth `code_direct` / Token). */\nexport type AuthResponse = {\n code?: string;\n accessToken?: string;\n accessTokenExpiresIn?: number;\n refreshToken?: string;\n refreshTokenExpiresIn?: number;\n};\n\n/**\n * Parse an `<Authentication>` response. Reads `<Error>` first and, if non-zero,\n * throws the mapped PortersAuthError (ADR-0006).\n */\nexport const parseAuthentication = (xml: string): AuthResponse => {\n const root = asRecord(parser.parse(xml) as unknown);\n const body = root ? asRecord(root.Authentication) : undefined;\n if (!body) {\n throw new PortersAuthError(\"unparseable authentication response\", {\n category: \"unknown\",\n });\n }\n\n const error = toInt(body.Error);\n if (error !== 0) {\n throw authError(\n error,\n asString(body.Message) ?? `authentication error ${error}`,\n );\n }\n\n const num = (v: unknown): number | undefined => {\n const s = asString(v);\n return s === undefined ? undefined : Number(s);\n };\n return {\n code: asString(body.Code),\n accessToken: asString(body.AccessToken),\n accessTokenExpiresIn: num(body.AccessTokenExpiresIn),\n refreshToken: asString(body.RefreshToken),\n refreshTokenExpiresIn: num(body.RefreshTokenExpiresIn),\n };\n};\n","// Narrowing helpers for fast-xml-parser output. The parser is typed as `any`;\n// we launder it through `unknown` and narrow here so we never spread `any`.\n\nexport const asRecord = (v: unknown): Record<string, unknown> | undefined =>\n typeof v === \"object\" && v !== null && !Array.isArray(v)\n ? (v as Record<string, unknown>)\n : undefined;\n\nexport const asString = (v: unknown): string | undefined =>\n typeof v === \"string\" ? v : undefined;\n\n/** Normalize a node that may be missing, single, or repeated into an array. */\nexport const asArray = (v: unknown): unknown[] => {\n if (Array.isArray(v)) return v;\n return v === undefined || v === null ? [] : [v];\n};\n","import type { StoredTokens, TokenStore } from \"./types\";\n\n/** Default in-process token store (single instance; lost on restart). */\nexport const createMemoryTokenStore = (): TokenStore => {\n let tokens: StoredTokens | undefined;\n return {\n get: () => Promise.resolve(tokens),\n set: (t) => {\n tokens = t;\n return Promise.resolve();\n },\n clear: () => {\n tokens = undefined;\n return Promise.resolve();\n },\n };\n};\n","// Shared OAuth token exchange against `POST /v1/token` (ADR-0034 F-1 / ADR-0007).\n// Used by both the default transparent provider (code_direct grant) and the public\n// auth API's browser `code` exchange — they POST the same form and parse the same\n// <Authentication> envelope, so the logic lives here once. The App Secret only ever\n// rides the POST body (ADR-0034 SD-9), never a URL/log.\n\nimport { PortersAuthError } from \"../errors/index\";\nimport type { Transport } from \"../http/index\";\nimport { parseAuthentication } from \"../xml/parser\";\nimport type { StoredTokens } from \"./types\";\n\n/** Credentials + seams shared by every token exchange. */\nexport type TokenExchangeDeps = {\n host: string;\n appId: string;\n appSecret: string;\n transport: Transport;\n /** Clock for converting relative expiry (ms) to an absolute epoch (ADR-0012). */\n now: () => number;\n};\n\n/** OAuth grant kinds the Token endpoint accepts (token.md). */\nexport type TokenGrantType = \"oauth_code\" | \"refresh_token\";\n\n/**\n * Exchange an OAuth `code` (new grant) or a Refresh Token (renewal) for tokens via\n * `POST {host}/v1/token`. The relative `*ExpiresIn` (ms) is converted to an absolute\n * epoch at receipt (clock-skew tolerant — ADR-0012). Throws {@link PortersAuthError}\n * when the envelope reports an error (`<Error>≠0`, via the parser) or omits a token.\n */\nexport const exchangeToken = async (\n deps: TokenExchangeDeps,\n grantType: TokenGrantType,\n code: string,\n): Promise<StoredTokens> => {\n const body = new URLSearchParams({\n app_id: deps.appId,\n secret: deps.appSecret,\n grant_type: grantType,\n code,\n }).toString();\n const res = await deps.transport.send({\n method: \"POST\",\n url: `https://${deps.host}/v1/token`,\n headers: { \"Content-Type\": \"application/x-www-form-urlencoded\" },\n body,\n });\n const a = parseAuthentication(res.body);\n if (a.accessToken === undefined || a.refreshToken === undefined) {\n throw new PortersAuthError(\"token response missing tokens\", {\n category: \"auth\",\n });\n }\n return {\n accessToken: a.accessToken,\n refreshToken: a.refreshToken,\n accessTokenExpiresAt: deps.now() + (a.accessTokenExpiresIn ?? 0),\n refreshTokenExpiresAt: deps.now() + (a.refreshTokenExpiresIn ?? 0),\n };\n};\n","// Default transparent TokenProvider (ADR-0007 / ADR-0012): code_direct -> token,\n// cache, hybrid refresh (proactive margin + on-demand), in-process single-flight.\n// Factory style per ADR-0013. Exposes internal cache/clear so the public auth API\n// (ADR-0034 F-1) can save a browser-`code` exchange and locally forget tokens.\n\nimport { PortersAuthError } from \"../errors/index\";\nimport type { Transport } from \"../http/index\";\nimport { parseAuthentication } from \"../xml/parser\";\nimport { createMemoryTokenStore } from \"./memory-store\";\nimport { exchangeToken } from \"./token-exchange\";\nimport type { StoredTokens, TokenProvider, TokenStore } from \"./types\";\n\nexport type DefaultTokenProviderOptions = {\n host: string;\n appId: string;\n appSecret: string;\n transport: Transport;\n /** Token persistence; defaults to in-memory. */\n tokenStore?: TokenStore;\n /** Refresh this many ms before expiry (proactive). Default 60s. */\n refreshMarginMs?: number;\n /** Injectable clock (tests). Default `Date.now`. */\n now?: () => number;\n};\n\n/**\n * The default provider plus internal controls used by the public auth API\n * (ADR-0034 SD-8): {@link DefaultTokenProvider.cache} saves externally-acquired\n * tokens (browser `code` exchange) to the in-memory cache + token store;\n * {@link DefaultTokenProvider.clear} forgets them (local revoke). Deliberately *not*\n * part of the public\n * {@link TokenProvider} contract — a custom strategy supplies neither.\n */\nexport type DefaultTokenProvider = TokenProvider & {\n cache(tokens: StoredTokens): Promise<void>;\n clear(): Promise<void>;\n};\n\nconst DEFAULT_MARGIN_MS = 60_000;\n\nexport const createDefaultTokenProvider = (\n opts: DefaultTokenProviderOptions,\n): DefaultTokenProvider => {\n const store = opts.tokenStore ?? createMemoryTokenStore();\n const margin = opts.refreshMarginMs ?? DEFAULT_MARGIN_MS;\n const now = opts.now ?? (() => Date.now());\n\n let cached: StoredTokens | undefined;\n let inflight: Promise<StoredTokens> | undefined;\n\n const accessValid = (t: StoredTokens | undefined): t is StoredTokens =>\n t !== undefined && now() < t.accessTokenExpiresAt - margin;\n\n const canRefresh = (t: StoredTokens | undefined): t is StoredTokens =>\n t !== undefined && now() < t.refreshTokenExpiresAt - margin;\n\n // Cache + persist freshly minted tokens so the next call (and other instances) reuse them.\n const save = async (tokens: StoredTokens): Promise<StoredTokens> => {\n cached = tokens;\n await store.set(tokens);\n return tokens;\n };\n\n const exchange = async (\n grantType: \"oauth_code\" | \"refresh_token\",\n code: string,\n ): Promise<StoredTokens> =>\n save(\n await exchangeToken(\n {\n host: opts.host,\n appId: opts.appId,\n appSecret: opts.appSecret,\n transport: opts.transport,\n now,\n },\n grantType,\n code,\n ),\n );\n\n // code_direct -> token (initial acquisition; requires prior browser grant).\n const acquire = async (): Promise<StoredTokens> => {\n const url =\n `https://${opts.host}/v1/oauth` +\n `?app_id=${encodeURIComponent(opts.appId)}&response_type=code_direct`;\n const res = await opts.transport.send({ method: \"GET\", url, headers: {} });\n const { code } = parseAuthentication(res.body);\n if (code === undefined) {\n throw new PortersAuthError(\"code_direct returned no code\", {\n category: \"auth\",\n });\n }\n return exchange(\"oauth_code\", code);\n };\n\n const renew = async (): Promise<StoredTokens> => {\n if (cached === undefined) cached = await store.get();\n if (canRefresh(cached)) {\n return exchange(\"refresh_token\", cached.refreshToken);\n }\n return acquire();\n };\n\n const ensure = (forceRefresh: boolean): Promise<StoredTokens> => {\n if (!forceRefresh && accessValid(cached)) return Promise.resolve(cached);\n return (inflight ??= renew().finally(() => {\n inflight = undefined;\n }));\n };\n\n return {\n getAccessToken: async (o) =>\n (await ensure(o?.forceRefresh ?? false)).accessToken,\n cache: async (tokens) => {\n await save(tokens);\n },\n clear: async () => {\n cached = undefined;\n await store.clear();\n },\n };\n};\n","// Public OAuth surface `porters.auth.*` (ADR-0034 F-1 / ADR-0007 SD-3/SD-6). A thin\n// facade over the active token provider: it builds the browser `code` / `remove` URLs,\n// exchanges a redirect `?code=` for tokens (saving them into the default strategy),\n// warms up / inspects the token, and locally forgets tokens. Credential- and\n// default-strategy-dependent methods fail fast with a PortersConfigError under a custom\n// auth strategy (ADR-0034 SD-7). Factory style per ADR-0013; the App Secret never leaves\n// the Token POST body (SD-9).\n\nimport { PortersConfigError } from \"../errors/index\";\nimport type { Transport } from \"../http/index\";\nimport type { Scope } from \"../types/index\";\nimport { exchangeToken } from \"./token-exchange\";\nimport type { StoredTokens, TokenProvider } from \"./types\";\n\n/** Shared options for the browser `code` / `remove` OAuth URLs (oauth.md). */\nexport type AuthorizationUrlOptions = {\n /** Registered Redirect URL the browser returns to (required for code/remove). */\n redirectUrl: string;\n /** Scopes to grant/remove; defaults to the client's configured `scopes`. */\n scopes?: Scope[];\n /** Opaque value echoed back on redirect (e.g. CSRF defense). */\n state?: string;\n};\n\n/** Options for the `remove` (de-authorization) browser URL. */\nexport type RevokeUrlOptions = AuthorizationUrlOptions;\n\n/**\n * The `porters.auth.*` surface (ADR-0007 SD-3/SD-6). The initial per-Company-DB grant\n * needs a human to open {@link AuthApi.authorizationUrl} in a browser and consent; the\n * library only builds the URL and exchanges the returned `code`. Day-to-day token\n * acquisition/refresh stays transparent (the default strategy), so most callers never\n * touch this surface.\n */\nexport type AuthApi = {\n /** Build the browser `code`-grant URL to open for the initial permission grant. */\n authorizationUrl(opts: AuthorizationUrlOptions): string;\n /**\n * Exchange a redirect `?code=` for tokens and save them into the default strategy.\n * Resolves `void` on success (tokens are stored internally — inspect via\n * {@link AuthApi.getToken}); throws on failure: {@link PortersConfigError} (missing\n * credentials / custom strategy), `PortersAuthError` (token-endpoint error or expired\n * code), or `PortersNetworkError`.\n */\n exchangeAuthorizationCode(code: string): Promise<void>;\n /**\n * Build the browser `remove`-grant URL to open for server-side de-authorization.\n * PORTERS has no server-to-server removal, so completing it stays a browser step;\n * pair with {@link AuthApi.clearTokens} to drop the local copy.\n */\n revokeUrl(opts: RevokeUrlOptions): string;\n /** Forget cached + stored tokens locally. Does not de-authorize server-side. */\n clearTokens(): Promise<void>;\n /** Acquire a token now (startup fail-fast / warm-up); throws if auth is unavailable. */\n ensureAuthenticated(): Promise<void>;\n /** Return the current valid Access Token (debug). The Refresh Token is never exposed. */\n getToken(): Promise<string>;\n};\n\n/** Internal save/forget controls, present only when the default provider is in use. */\nexport type AuthProviderControls = {\n cache(tokens: StoredTokens): Promise<void>;\n clear(): Promise<void>;\n};\n\nexport type AuthApiOptions = {\n host: string;\n appId?: string;\n appSecret?: string;\n scopes?: Scope[];\n transport: Transport;\n /** The active token provider (default or custom) backing ensure/getToken. */\n provider: TokenProvider;\n /** Present only for the default provider; absent under a custom strategy. */\n controls?: AuthProviderControls;\n /** Injectable clock (tests). Default `Date.now`. */\n now?: () => number;\n};\n\nexport const createAuthApi = (opts: AuthApiOptions): AuthApi => {\n const now = opts.now ?? (() => Date.now());\n\n const requireAppId = (): string => {\n if (!opts.appId) {\n throw new PortersConfigError(\"appId is required to build an OAuth URL\", {\n category: \"config\",\n hint: \"Set appId on PortersClient. A custom auth strategy that supplies its own tokens cannot run the browser grant.\",\n });\n }\n return opts.appId;\n };\n\n const requireDefaultStrategy = (method: string): AuthProviderControls => {\n if (opts.controls === undefined) {\n throw new PortersConfigError(\n `${method} is only available with the default auth strategy`,\n {\n category: \"config\",\n hint: \"Remove the custom `auth` strategy to let the library manage tokens, or perform this step in your own strategy.\",\n },\n );\n }\n return opts.controls;\n };\n\n const requireCredentials = (): { appId: string; appSecret: string } => {\n if (!opts.appId || !opts.appSecret) {\n throw new PortersConfigError(\n \"appId and appSecret are required to exchange an authorization code\",\n {\n category: \"config\",\n hint: \"Set appId/appSecret on PortersClient (the Token endpoint needs both).\",\n },\n );\n }\n return { appId: opts.appId, appSecret: opts.appSecret };\n };\n\n const resolveScopes = (scopes: Scope[] | undefined): Scope[] => {\n const resolved = scopes ?? opts.scopes ?? [];\n if (resolved.length === 0) {\n throw new PortersConfigError(\n \"at least one scope is required for the code/remove grant\",\n {\n category: \"config\",\n hint: \"Pass `scopes` to this call or configure `scopes` on PortersClient.\",\n },\n );\n }\n return resolved;\n };\n\n const buildOAuthUrl = (\n responseType: \"code\" | \"remove\",\n o: AuthorizationUrlOptions,\n ): string => {\n const params = new URLSearchParams({\n app_id: requireAppId(),\n redirect_url: o.redirectUrl,\n response_type: responseType,\n scope: resolveScopes(o.scopes).join(\",\"),\n });\n if (o.state !== undefined) params.set(\"state\", o.state);\n return `https://${opts.host}/v1/oauth?${params.toString()}`;\n };\n\n return {\n authorizationUrl: (o) => buildOAuthUrl(\"code\", o),\n revokeUrl: (o) => buildOAuthUrl(\"remove\", o),\n exchangeAuthorizationCode: async (code) => {\n const controls = requireDefaultStrategy(\"exchangeAuthorizationCode\");\n const { appId, appSecret } = requireCredentials();\n const tokens = await exchangeToken(\n { host: opts.host, appId, appSecret, transport: opts.transport, now },\n \"oauth_code\",\n code,\n );\n await controls.cache(tokens);\n },\n clearTokens: async () => {\n const controls = requireDefaultStrategy(\"clearTokens\");\n await controls.clear();\n },\n ensureAuthenticated: async () => {\n await opts.provider.getAccessToken();\n },\n getToken: () => opts.provider.getAccessToken(),\n };\n};\n","// Default fetch-based transport (ADR-0009). Thin: one request -> one response;\n// throttle/retry/auth live above it. Network/timeout -> PortersNetworkError.\n\nimport { PortersNetworkError } from \"../errors/index\";\nimport type { Transport } from \"./types\";\n\nexport type FetchTransportOptions = {\n timeoutMs?: number;\n /** Injectable fetch (tests / custom dispatcher). Default global fetch. */\n fetchImpl?: typeof fetch;\n};\n\nexport const createFetchTransport = (\n opts: FetchTransportOptions = {},\n): Transport => {\n const doFetch = opts.fetchImpl ?? fetch;\n const timeoutMs = opts.timeoutMs ?? 30_000;\n return {\n send: async (req) => {\n try {\n const res = await doFetch(req.url, {\n method: req.method,\n headers: req.headers,\n body: req.body,\n signal: AbortSignal.timeout(timeoutMs),\n });\n return { status: res.status, body: await res.text() };\n } catch (cause) {\n throw new PortersNetworkError(\"transport request failed\", {\n category: \"network\",\n retryable: true,\n cause,\n });\n }\n },\n };\n};\n","// Public mock transport for offline evaluation / unit tests (ADR-0024 / R-17 / R-12).\n// It targets the stable public `Transport` seam (not `fetch`), so it survives an internal\n// transport change. By default the OAuth code_direct + token endpoints are auto-answered,\n// so callers only mock resource XML; an unmocked route fails loud (fail-safe).\n\nimport { PortersConfigError } from \"../errors/index\";\nimport type { Transport, TransportRequest, TransportResponse } from \"./types\";\n\n/** A mock reply: an XML body string (HTTP 200), or an explicit status + body. */\nexport type MockReply = string | { status?: number; body: string };\n\n/**\n * Maps a request to a {@link MockReply}, or returns `undefined` for \"not mocked\". When `undefined`\n * is returned (and the request is not an auto-answered auth endpoint), the transport throws a\n * {@link PortersConfigError} naming the request, so an unmocked route surfaces instead of silently\n * returning an empty response.\n */\nexport type MockHandler = (request: TransportRequest) => MockReply | undefined;\n\n/** Options for {@link createMockTransport}. */\nexport type MockTransportOptions = {\n /**\n * Auto-answer the OAuth `code_direct` (`/v1/oauth`) and token (`/v1/token`) endpoints with valid\n * demo tokens, so callers only mock resource XML. Default `true`. Set `false` to handle the auth\n * endpoints in your own handler.\n */\n auth?: boolean;\n};\n\n// Default auth responses (mirrors the live envelope; expiry values are ms — see token-provider).\nconst AUTH_CODE_XML = `<Authentication><Code>mock-code</Code><Error>0</Error></Authentication>`;\nconst AUTH_TOKEN_XML =\n `<Authentication>` +\n `<AccessToken>mock-access-token</AccessToken><AccessTokenExpiresIn>1800000</AccessTokenExpiresIn>` +\n `<RefreshToken>mock-refresh-token</RefreshToken><RefreshTokenExpiresIn>7200000</RefreshTokenExpiresIn>` +\n `<Error>0</Error></Authentication>`;\n\nconst toResponse = (reply: MockReply): TransportResponse =>\n typeof reply === \"string\"\n ? { status: 200, body: reply }\n : { status: reply.status ?? 200, body: reply.body };\n\n// method + path だけで「どの route を足すか」は十分。既定 field を載せた Read URL の\n// クエリは長大でノイズなので落とす(不正な URL はそのまま出す=フェイルセーフ)。\nconst routeLabel = (method: string, url: string): string => {\n try {\n return `${method} ${new URL(url).pathname}`;\n } catch {\n return `${method} ${url}`;\n }\n};\n\n/**\n * Build a {@link Transport} that answers from a handler instead of the network — run the library\n * fully offline, with no PORTERS contract (R-17). Pass it as `new PortersClient({ transport })`.\n *\n * @example\n * const transport = createMockTransport((req) =>\n * req.url.includes(\"/v1/candidate\")\n * ? `<Candidate Total=\"0\" Count=\"0\" Start=\"0\"><Code>0</Code></Candidate>`\n * : undefined, // unmocked -> a clear PortersConfigError\n * );\n */\nexport const createMockTransport = (\n handler: MockHandler,\n options: MockTransportOptions = {},\n): Transport => {\n const autoAuth = options.auth ?? true;\n // Non-async on purpose: always return a Promise (resolve/reject) so an unmocked route rejects\n // rather than throwing synchronously — faithful to the Transport contract.\n return {\n send: (req) => {\n if (autoAuth && req.url.includes(\"/v1/token\")) {\n return Promise.resolve({ status: 200, body: AUTH_TOKEN_XML });\n }\n if (autoAuth && req.url.includes(\"/v1/oauth\")) {\n return Promise.resolve({ status: 200, body: AUTH_CODE_XML });\n }\n const reply = handler(req);\n if (reply === undefined) {\n return Promise.reject(\n new PortersConfigError(\n `createMockTransport: no mock response for ${routeLabel(req.method, req.url)} — add a case to your handler` +\n ` (or pass { auth: false } to mock the auth endpoints too)`,\n { category: \"config\" },\n ),\n );\n }\n return Promise.resolve(toResponse(reply));\n },\n };\n};\n","// Token-bucket throttle (ADR-0010): per-minute Read/Write limits at ~90% safety.\n// Bursts are allowed up to capacity; the average stays under the limit.\n\nconst sleep = (ms: number): Promise<void> =>\n new Promise((resolve) => setTimeout(resolve, ms));\n\nexport type Throttle = {\n take(write: boolean): Promise<void>;\n};\n\nexport type ThrottleOptions = {\n readPerMin?: number;\n writePerMin?: number;\n /** Fraction of the limit to actually use (headroom). Default 0.9. */\n safety?: number;\n now?: () => number;\n};\n\nconst makeBucket = (\n capacity: number,\n now: () => number,\n): (() => Promise<void>) => {\n const ratePerMs = capacity / 60_000;\n let tokens = capacity;\n let last = now();\n return async () => {\n for (;;) {\n const t = now();\n tokens = Math.min(capacity, tokens + (t - last) * ratePerMs);\n last = t;\n if (tokens >= 1) {\n tokens -= 1;\n return;\n }\n await sleep(Math.ceil((1 - tokens) / ratePerMs));\n }\n };\n};\n\nexport const createThrottle = (opts: ThrottleOptions = {}): Throttle => {\n const safety = opts.safety ?? 0.9;\n const now = opts.now ?? (() => Date.now());\n const read = makeBucket(Math.floor((opts.readPerMin ?? 2000) * safety), now);\n const write = makeBucket(Math.floor((opts.writePerMin ?? 500) * safety), now);\n return { take: (isWrite) => (isWrite ? write() : read()) };\n};\n","// Exponential backoff with full jitter (ADR-0010).\n\nexport type Backoff = (attempt: number) => number;\n\nexport const expoBackoff =\n (baseMs = 200, maxMs = 8_000): Backoff =>\n (attempt) =>\n Math.floor(Math.random() * Math.min(maxMs, baseMs * 2 ** attempt));\n","// Request pipeline (ADR-0009/0010/0012): throttle -> auth header -> transport,\n// with reactive token refresh (401/402) and bounded backoff retry. The\n// idempotency guard keeps non-idempotent writes (create) from double-applying.\n\nimport type { TokenProvider } from \"../auth/types\";\nimport {\n PortersConfigError,\n PortersError,\n PortersNetworkError,\n} from \"../errors/index\";\nimport type { Backoff } from \"./retry\";\nimport type { Throttle } from \"./throttle\";\nimport type { Transport, TransportRequest } from \"./types\";\n\nconst API_VERSION = \"2\";\n\n// docs/reference: keep a *whole* request under ~15000 chars (a larger payload 400s).\n// \"Whole\" is load-bearing: a write's body dominates, but a read's length lives in the\n// URL (field / condition) — and ADR-0020 makes a fieldless Read send the catalog default\n// field set, so that URL grew. A future 16KB cap is planned but undetermined — follow the\n// canonical value. Exported so the bulk-write chunker sizes each batch under the same cap\n// (ADR-0041) instead of relying on this guard to reject an oversized batch mid-run.\nexport const MAX_REQUEST_LENGTH = 15000;\n\nconst sleep = (ms: number): Promise<void> =>\n new Promise((resolve) => setTimeout(resolve, ms));\n\nconst withAuth = (\n req: TransportRequest,\n token: string,\n write: boolean,\n): TransportRequest => ({\n ...req,\n headers: {\n ...req.headers,\n \"X-porters-hrbc-oauth-token\": token,\n \"X-P-ConnectAPI-Version\": API_VERSION,\n ...(write ? { \"Content-Type\": \"application/xml; charset=UTF-8\" } : {}),\n },\n});\n\nexport type RequesterOptions = {\n transport: Transport;\n auth: TokenProvider;\n throttle: Throttle;\n backoff: Backoff;\n maxRetries?: number;\n};\n\nexport type RequestSpec = {\n /** Write (POST) uses the write throttle bucket. */\n write?: boolean;\n /** false for non-idempotent ops (create); not auto-retried on network uncertainty. */\n idempotent?: boolean;\n /** Skip the ~15000-char size guard (file uploads have their own limit; ADR-0018). */\n unboundedBody?: boolean;\n};\n\nexport type Requester = {\n request<T>(\n req: TransportRequest,\n parse: (body: string) => T,\n spec?: RequestSpec,\n ): Promise<T>;\n};\n\nexport const createRequester = (o: RequesterOptions): Requester => {\n const maxRetries = o.maxRetries ?? 3;\n\n const request = async <T>(\n req: TransportRequest,\n parse: (body: string) => T,\n spec: RequestSpec = {},\n ): Promise<T> => {\n // Eager size guard: block an oversized request before throttle / auth / transport.\n // A clear config error beats an opaque server 400, and we don't burn a throttle token\n // or a token refresh on a request that cannot succeed (fail-safe). PORTERS limits the\n // whole request, so measure URL + body: a write's body or a read's field/condition\n // query string can blow the cap (RV-5). File uploads opt out via `unboundedBody` (the\n // body has its own limit — ADR-0018; their write URL is short, so skipping is safe).\n const requestLength = req.url.length + (req.body?.length ?? 0);\n if (!spec.unboundedBody && requestLength > MAX_REQUEST_LENGTH) {\n throw new PortersConfigError(\n `request is ${requestLength} characters, over the ~${MAX_REQUEST_LENGTH}-character limit`,\n {\n category: \"config\",\n hint: \"Shorten the request: narrow a read's field/condition, or split a write into batches of 200 or fewer records (PORTERS caps a request at ~15000 characters).\",\n },\n );\n }\n const write = spec.write ?? false;\n const idempotent = spec.idempotent ?? !write;\n let authRetried = false;\n let forceRefresh = false;\n let attempt = 0;\n\n for (;;) {\n await o.throttle.take(write);\n try {\n const token = await o.auth.getAccessToken(\n forceRefresh ? { forceRefresh: true } : undefined,\n );\n forceRefresh = false;\n const res = await o.transport.send(withAuth(req, token, write));\n return parse(res.body);\n } catch (e) {\n if (!(e instanceof PortersError)) throw e;\n // reactive: token expired -> refresh once and retry (safe even for create).\n if ((e.code === 401 || e.code === 402) && !authRetried) {\n authRetried = true;\n forceRefresh = true;\n continue;\n }\n // idempotency guard: non-idempotent write + network-uncertain -> surface.\n if (e instanceof PortersNetworkError && write && !idempotent) throw e;\n // transient (9/302) / network -> bounded backoff.\n if (e.retryable && attempt < maxRetries) {\n attempt += 1;\n await sleep(o.backoff(attempt - 1));\n continue;\n }\n throw e;\n }\n }\n };\n\n return { request };\n};\n","// PORTERS datetime <-> ISO 8601 (UTC) normalization (PRD R-10 / ADR-0011).\n// DateTime `yyyy/mm/dd HH:MM:SS` (UTC) <-> ISO `...Z`\n// Date `yyyy/mm/dd` <-> date-only (no `Z`)\n// No business-timezone (e.g. JST) conversion — that is the caller's responsibility.\n\nconst DATETIME_RE = /^(\\d{4})\\/(\\d{2})\\/(\\d{2}) (\\d{2}):(\\d{2}):(\\d{2})$/;\nconst DATE_RE = /^(\\d{4})\\/(\\d{2})\\/(\\d{2})$/;\nconst ISO_DATE_RE = /^(\\d{4})-(\\d{2})-(\\d{2})/;\n\n/** PORTERS `yyyy/mm/dd HH:MM:SS` (UTC) -> ISO 8601 `...Z`. */\nexport const portersDateTimeToIso = (value: string): string => {\n const m = DATETIME_RE.exec(value);\n if (!m) throw new RangeError(`invalid PORTERS DateTime: \"${value}\"`);\n const iso = `${m[1]}-${m[2]}-${m[3]}T${m[4]}:${m[5]}:${m[6]}Z`;\n if (Number.isNaN(Date.parse(iso))) {\n throw new RangeError(`invalid PORTERS DateTime: \"${value}\"`);\n }\n return iso;\n};\n\n/** ISO 8601 (with `Z` or offset) -> PORTERS `yyyy/mm/dd HH:MM:SS` (UTC). */\nexport const isoToPortersDateTime = (value: string): string => {\n const t = Date.parse(value);\n if (Number.isNaN(t)) throw new RangeError(`invalid ISO datetime: \"${value}\"`);\n const d = new Date(t);\n const pad = (n: number): string => String(n).padStart(2, \"0\");\n return (\n `${d.getUTCFullYear()}/${pad(d.getUTCMonth() + 1)}/${pad(d.getUTCDate())} ` +\n `${pad(d.getUTCHours())}:${pad(d.getUTCMinutes())}:${pad(d.getUTCSeconds())}`\n );\n};\n\n/** PORTERS `yyyy/mm/dd` -> ISO date `yyyy-mm-dd` (no timezone). */\nexport const portersDateToIso = (value: string): string => {\n const m = DATE_RE.exec(value);\n if (!m) throw new RangeError(`invalid PORTERS Date: \"${value}\"`);\n return `${m[1]}-${m[2]}-${m[3]}`;\n};\n\n/** ISO date (or datetime) -> PORTERS `yyyy/mm/dd` (calendar date as-is, no shift). */\nexport const isoToPortersDate = (value: string): string => {\n const m = ISO_DATE_RE.exec(value);\n if (!m) throw new RangeError(`invalid ISO date: \"${value}\"`);\n return `${m[1]}/${m[2]}/${m[3]}`;\n};\n","// Data-Type-driven value encoding for Write (ADR-0011). Read and Write\n// representations are asymmetric: User/System[Reference] write the ID only, Option writes\n// `<Field><OptionAlias/></Field>`, and DateTime/Date go ISO -> PORTERS. This is the\n// mirror of decode.ts; it builds the request body so XML stays out of resources/.\n\nimport { isoToPortersDate, isoToPortersDateTime } from \"../util/datetime\";\nimport type { DataType } from \"./decode\";\n\n/**\n * A value to write. Scalars cover the string Data Types / Number / Id and the\n * ID-only User / Reference. An **Option** value is an array of selected aliases\n * (`string[]`) — symmetric with the Option read shape (ADR-0017); a lone string\n * is tolerated as a 1-element selection (fail-safe). `null` / `undefined` omits the\n * field (leaves it unchanged) — send `\"\"` to clear a string field.\n *\n * Per-field static typing (Option fields as `string[]`, etc.) is future work — the\n * precise static Write type (SD-3).\n */\nexport type WriteValue = string | number | string[] | null | undefined;\n\n/** One record to write: field alias (bare, e.g. `P_Name`) -> value. */\nexport type WriteItem = Record<string, WriteValue>;\n\n// Data Types a user may write. `System[Id]` is library-supplied (`P_Id=-1`/target id) and\n// `System[DateTime]` (registration/update) is Write-restricted by PORTERS — both are excluded\n// from the static Write input so they cannot be set (ADR-0016 promise, realized in ADR-0019).\nexport type WritableDataType = Exclude<\n DataType,\n \"System[Id]\" | \"System[DateTime]\"\n>;\n\n// Per-Data-Type write value (mirror of `encodeField`): User / System[Reference] / Number take a\n// number, Option an alias array, the rest a scalar string. Drives the static Write type (ADR-0019).\nexport type WriteValueOf<D extends DataType> = D extends\n \"User\" | \"System[Reference]\" | \"Number\"\n ? number\n : D extends \"Option\"\n ? string[]\n : string;\n\n// Element-content escaping. Only `& < >` are significant in PCDATA; we never emit\n// attributes, so quotes are left as-is.\nconst escapeXml = (s: string): string =>\n s.replace(/[&<>]/g, (c) =>\n c === \"&\" ? \"&amp;\" : c === \"<\" ? \"&lt;\" : \"&gt;\",\n );\n\nconst scalar = (v: string | number | string[]): string => escapeXml(String(v));\n\n/** Encode one field's value into the inner XML of its element. */\nexport const encodeField = (\n type: DataType,\n value: string | number | string[],\n): string => {\n switch (type) {\n // Option: the selected aliases as empty child elements. Canonical input is an\n // array (ADR-0017, symmetric with read); a lone string is wrapped as a 1-element\n // selection (fail-safe).\n case \"Option\":\n return (Array.isArray(value) ? value : [value])\n .map((alias) => `<${alias}/>`)\n .join(\"\");\n // System[DateTime] (registration/update) is Write-restricted by PORTERS; we still\n // serialize it identically — rejecting the write is the input type's job (SD-3).\n case \"DateTime\":\n case \"System[DateTime]\":\n return scalar(isoToPortersDateTime(String(value)));\n // Age shares Date's wire format (`yyyy/mm/dd`): we write the birthdate.\n case \"Date\":\n case \"Age\":\n return scalar(isoToPortersDate(String(value)));\n // System[Id] / Number / User & System[Reference] (ID-only) / string Data Types all\n // serialize as a scalar (the string types stay distinct labels per ADR-0016).\n case \"System[Id]\":\n case \"Number\":\n case \"User\":\n case \"System[Reference]\":\n case \"SinglelineText\":\n case \"MultilineText\":\n case \"Mail\":\n case \"Telephone\":\n case \"URL\":\n return scalar(value);\n }\n};\n\n// One `<Item>…</Item>` body. Unknown aliases (custom U_/A_, no catalog entry) fall\n// back to Text — symmetric with decode's raw-string passthrough (fail-safe).\nconst encodeItem = (\n prefix: string,\n fields: ReadonlyMap<string, DataType>,\n item: WriteItem,\n): string => {\n const parts: string[] = [];\n for (const [alias, value] of Object.entries(item)) {\n // null / undefined -> omit (leave unchanged); \"\" is kept (clears a Text field).\n if (value === null || value === undefined) continue;\n const type = fields.get(alias);\n const inner = type === undefined ? scalar(value) : encodeField(type, value);\n parts.push(`<${prefix}.${alias}>${inner}</${prefix}.${alias}>`);\n }\n return parts.join(\"\");\n};\n\n/**\n * One record as its full `<Item>…</Item>` element. Exposed so the bulk-write chunker can\n * measure each record's serialized length when packing a request under the size cap (ADR-0041).\n */\nexport const encodeWriteItem = (\n prefix: string,\n fields: ReadonlyMap<string, DataType>,\n item: WriteItem,\n): string => `<Item>${encodeItem(prefix, fields, item)}</Item>`;\n\n/** Build a Write request body: `<{Resource}><Item>…</Item>…</{Resource}>`. */\nexport const buildWriteXml = (config: {\n resource: string;\n prefix: string;\n fields: ReadonlyMap<string, DataType>;\n items: WriteItem[];\n}): string => {\n const items = config.items\n .map((item) => encodeWriteItem(config.prefix, config.fields, item))\n .join(\"\");\n return `<${config.resource}>${items}</${config.resource}>`;\n};\n","// Data-Type-driven value decoding (ADR-0011). Input is the raw node (string or\n// nested object) from the parser; output is the typed value. Empty -> null.\n\nimport { portersDateToIso, portersDateTimeToIso } from \"../util/datetime\";\nimport { asRecord, asString } from \"./raw\";\n\n// Granularity = PORTERS Data Type (ADR-0016). Labels are the literal Data Type\n// strings, incl. the System family (`System[Id]` / `System[DateTime]` / `System[Reference]`).\n// Currency collapses to Number and the three Option subtypes to Option (PORTERS' own\n// Data Type does the same); the string Data Types stay distinct (room for future\n// validation / normalisation). The `System[…]` qualifier marks system-managed values\n// (auto-assigned, often Write-restricted); that lifecycle is enforced via input types,\n// not here — decoding is by value shape.\nexport type DataType =\n | \"System[Id]\"\n | \"Number\"\n | \"DateTime\"\n | \"System[DateTime]\"\n | \"Date\"\n | \"Age\"\n | \"SinglelineText\"\n | \"MultilineText\"\n | \"Mail\"\n | \"Telephone\"\n | \"URL\"\n | \"User\"\n | \"Option\"\n | \"System[Reference]\";\n\n/** A referenced User (Read is nested; Write is `User.P_Id` only). */\nexport type UserRef = {\n P_Id: number | null;\n P_Type: string | null;\n P_Name: string | null;\n P_Mail: string | null;\n};\n\n// `string[]` is the Option read value (a set of selected aliases — ADR-0017).\nexport type FieldValue = string | number | string[] | UserRef | null;\n\n// Per-Data-Type decoded value (the non-null shape). A read value is `DecodedValue<D> | null`\n// (empty -> null). Mirrors `decodeField`'s branches and drives the static resource Read type\n// (ADR-0019): id/number/reference -> number, User -> UserRef, Option -> string[], rest -> string.\nexport type DecodedValue<D extends DataType> = D extends\n \"System[Id]\" | \"Number\" | \"System[Reference]\"\n ? number\n : D extends \"User\"\n ? UserRef\n : D extends \"Option\"\n ? string[]\n : string;\n\n// alias タグは接頭辞付き想定(例 `User.P_Id`)だが、接頭辞無しにも両対応(ADR-0011)。\n// 全 arrow(ADR-0013)=巻き上げ無しのため、ヘルパーを decodeField より前に定義する。\nconst pickPrefixed = (\n obj: Record<string, unknown>,\n prefix: string,\n key: string,\n): string | undefined =>\n asString(obj[`${prefix}.${key}`]) ?? asString(obj[key]);\n\nconst decodeUser = (raw: unknown): UserRef | null => {\n const outer = asRecord(raw);\n const user = outer ? asRecord(outer.User) : undefined;\n if (!user) return null;\n const id = pickPrefixed(user, \"User\", \"P_Id\");\n return {\n P_Id: id === undefined ? null : Number(id),\n P_Type: pickPrefixed(user, \"User\", \"P_Type\") ?? null,\n P_Name: pickPrefixed(user, \"User\", \"P_Name\") ?? null,\n P_Mail: pickPrefixed(user, \"User\", \"P_Mail\") ?? null,\n };\n};\n\n// Read: the selected leaf aliases (e.g. `<Option.P_Tokyo/>`) sit under `<OptionRoot>`.\n// PORTERS represents single/multi alike as a set, so return every selected alias verbatim\n// — incl. the `Option.` prefix (ADR-0017). None / empty -> null.\n// VERIFY(live): the `Option.` prefix and the `OptionRoot` wrapper come from the Read API\n// doc, not a live contract; we tolerate a missing wrapper. See docs/live-verification.md (LV-1, LV-2).\nconst decodeOption = (raw: unknown): string[] | null => {\n const outer = asRecord(raw);\n if (!outer) return null;\n // Aliases live under `<OptionRoot>` when present; the doc's sample omits it, so fall\n // back to the field's own children.\n const root = \"OptionRoot\" in outer ? asRecord(outer.OptionRoot) : outer;\n if (!root) return null;\n const keys = Object.keys(root);\n return keys.length > 0 ? keys : null;\n};\n\n// System[Reference] Read mirrors User: <Field><Resource>...</Resource></Field>, but the\n// inner tag varies (Client/Recruiter/...). Write is ID-only, so we decode the referenced\n// record's id — enough to round-trip. Richer reference reading is future work (SD-3).\n// NB: the label is literally `System[Reference]` (a nested record). It is NOT the\n// display-only Field-Type-16 \"Reference\" (a scalar mirror, Data Type `—`), left uncatalogued.\nconst decodeReference = (raw: unknown): number | null => {\n const outer = asRecord(raw);\n if (!outer) return null;\n // The nested resource is the first record-valued child (skip attributes / siblings,\n // which decodeUser avoids via a fixed key — here the tag varies). Read that record's\n // own `{Tag}.P_Id` (prefix-less also accepted), not just any key ending in P_Id.\n for (const [tag, value] of Object.entries(outer)) {\n const inner = asRecord(value);\n if (!inner) continue;\n const id = asString(inner[`${tag}.P_Id`]) ?? asString(inner.P_Id);\n return id === undefined ? null : Number(id);\n }\n return null;\n};\n\n/** Decode one field's raw node by its Data Type. */\nexport const decodeField = (type: DataType, raw: unknown): FieldValue => {\n // `raw === \"\"` is load-bearing (a Text \"\" must become null, not stay \"\");\n // `=== undefined` / `=== null` are defense-in-depth — every switch branch below\n // also maps them to null, so dropping either is an equivalent mutant.\n // Stryker disable next-line ConditionalExpression: see above (undefined/null are redundant with the switch)\n if (raw === \"\" || raw === undefined || raw === null) return null;\n switch (type) {\n case \"System[Id]\":\n case \"Number\": {\n // raw is neither \"\" nor non-string here (guarded above), so `s` is a\n // non-empty string or undefined — `s === \"\"` would be dead.\n const s = asString(raw);\n return s === undefined ? null : Number(s);\n }\n // String Data Types share one decode (a plain string); they stay distinct\n // labels for fidelity / future per-type validation (ADR-0016).\n case \"SinglelineText\":\n case \"MultilineText\":\n case \"Mail\":\n case \"Telephone\":\n case \"URL\":\n return asString(raw) ?? null;\n // FT-12 DateTime and the system timestamps (registration/update) share the wire\n // format; System[DateTime] is Write-restricted, but that is a write-time concern.\n case \"DateTime\":\n case \"System[DateTime]\": {\n const s = asString(raw);\n return s === undefined ? null : portersDateTimeToIso(s);\n }\n // Age shares Date's wire format (`yyyy/mm/dd`); PORTERS transmits the birthdate\n // and derives the age in its UI, so the faithful value is the date itself.\n case \"Date\":\n case \"Age\": {\n const s = asString(raw);\n return s === undefined ? null : portersDateToIso(s);\n }\n case \"User\":\n return decodeUser(raw);\n case \"Option\":\n return decodeOption(raw);\n case \"System[Reference]\":\n return decodeReference(raw);\n }\n};\n","// Shared Read internals for every resource — data (resource.ts) and master\n// (partition/user/field/option). Owns catalog typing, the catalog-driven item decoder, the\n// GET+parse+decode runner, and offset pagination. Data resources add Write on top; master\n// resources add bespoke query/URL building (ADR-0021/0022). XML stays in xml/ — this only\n// wires parse + decode together.\n\nimport type { Requester } from \"../http/requester\";\nimport {\n decodeField,\n type DataType,\n type DecodedValue,\n type FieldValue,\n} from \"../xml/decode\";\nimport { parseResourcePage, type RawItem } from \"../xml/parser\";\n\n// A field catalog: bare alias -> Data Type. Declared `as const` per resource so the static\n// Read/Write types derive from it — the catalog is the single source of truth (ADR-0019).\nexport type FieldCatalog = Record<string, DataType>;\n\n/**\n * \"No custom fields\": the intersection-identity default for the generic catalog params (ADR-0023).\n * A bare `{}` is flagged by `no-empty-object-type`; `Record<never, never>` is the same empty object,\n * lint-clean, adds no keys in `static & C`, and satisfies both `FieldCatalog` and `DeclaredCatalogs`.\n * Lives here (with `FieldCatalog`) so resources need not import from the higher-level `fields/` (RV-8).\n */\nexport type EmptyCatalog = Record<never, never>;\n\n/**\n * A decoded record: every known field, each `DecodedValue | null`, and **optional** because a\n * field not named in `field` is simply absent (SD-3 \"simple\" type — ADR-0005/0019). Custom\n * `U_`/`A_` aliases are not in the catalog, so they are not typed here (access via a cast until\n * the declaration DSL lands — ADR-0005 SD-2); at runtime they still pass through as raw values.\n */\nexport type ReadRecord<F extends FieldCatalog> = {\n [K in keyof F]?: DecodedValue<F[K]> | null;\n};\n\nexport type ResourcePage<F extends FieldCatalog> = {\n items: ReadRecord<F>[];\n total: number;\n count: number;\n start: number;\n};\n\n// `includes(\".\")` -> `includes(\"\")` is an equivalent mutant: for a dotless key,\n// slice(indexOf(\".\") + 1) is slice(0), which equals the key — same as the else.\n// Stryker disable StringLiteral\nconst bareAlias = (key: string): string =>\n key.includes(\".\") ? key.slice(key.indexOf(\".\") + 1) : key;\n// Stryker restore StringLiteral\n\n/**\n * Build a catalog-driven item decoder: known `P_` fields decode by their Data Type, unknown\n * `U_`/`A_` aliases pass through (raw string, or null when nested). `bareAlias` strips the\n * `{prefix}.` so `Person.P_Name` and `P_Name` both hit the catalog.\n */\nexport const decoderFor = <F extends FieldCatalog>(\n fields: F,\n): ((item: RawItem) => ReadRecord<F>) => {\n const fieldMap = new Map<string, DataType>(Object.entries(fields));\n return (item) => {\n const out: Record<string, FieldValue> = {};\n for (const [key, raw] of Object.entries(item)) {\n const alias = bareAlias(key);\n const type = fieldMap.get(alias);\n out[alias] = type\n ? decodeField(type, raw)\n : typeof raw === \"string\"\n ? raw\n : null;\n }\n return out as ReadRecord<F>;\n };\n};\n\n/** GET a Read URL, parse the standard envelope (Total/Count/Start + Items), decode each item. */\nexport const runRead = <F extends FieldCatalog>(\n requester: Requester,\n url: string,\n decode: (item: RawItem) => ReadRecord<F>,\n): Promise<ResourcePage<F>> =>\n requester.request({ method: \"GET\", url, headers: {} }, (body) => {\n const page = parseResourcePage(body);\n return {\n items: page.items.map(decode),\n total: page.total,\n count: page.count,\n start: page.start,\n };\n });\n\n// Read max page size (docs/reference: count 1–200). searchAll pages by this.\nconst PAGE_SIZE = 200;\n\n/**\n * Offset pagination shared by every `searchAll`. Advances by the items actually returned and\n * stops at `total` — or on an empty page (defensive against a stuck offset / infinite loop).\n * A generator can't be an arrow; a function expression still satisfies func-style:expression.\n */\nexport const paginate = async function* <T>(\n fetchPage: (\n count: number,\n start: number,\n ) => Promise<{ items: T[]; total: number }>,\n): AsyncGenerator<T> {\n let start = 0;\n for (;;) {\n const page = await fetchPage(PAGE_SIZE, start);\n for (const item of page.items) yield item;\n start += page.items.length;\n if (page.items.length === 0 || start >= page.total) return;\n }\n};\n","// Typed Read query surface (ADR-0038 / F-2): condition / order / keywords / itemstate, grounded in\n// the PORTERS Read parameter reference. The public types are Data-Type-aware — a field's allowed\n// operators and value shape derive from its catalog Data Type (ADR-0005 R-5 / ADR-0038 案1a). The\n// encoder turns a typed query into the wire params, normalising dates ISO -> PORTERS and guarding\n// the caller-side limits (keywords length, itemstate condition restriction) before send (fail-safe).\n// XML/value formatting stays in xml/; this owns only the Read query string.\n\nimport { PortersConfigError } from \"../errors\";\nimport { isoToPortersDate, isoToPortersDateTime } from \"../util/datetime\";\nimport type { DataType } from \"../xml/decode\";\nimport type { FieldCatalog } from \"./read-core\";\n\n// --- condition: per-Data-Type operator objects (reference: Read - Condition) ---\n\n/** Comparable ops for numeric Ids (System[Id]); `or` matches a set of Resource Ids (`P_Id:or=1:2`). */\ntype IdCondition = {\n gt?: number;\n ge?: number;\n eq?: number;\n le?: number;\n lt?: number;\n or?: number[];\n};\n\n/** Comparable ops for Number. */\ntype NumberCondition = {\n gt?: number;\n ge?: number;\n eq?: number;\n le?: number;\n lt?: number;\n};\n\n/** Comparable ops for date/time fields. Values are ISO 8601 (UTC `…Z`); normalised to PORTERS on send. */\ntype TemporalCondition = {\n gt?: string;\n ge?: string;\n eq?: string;\n le?: string;\n lt?: string;\n};\n\n/** Text match. `full` = exact, `part` = substring (PORTERS default). */\ntype TextCondition = {\n full?: string;\n part?: string;\n};\n\n/** Option-select match; values are option aliases (e.g. `Option.P_SE`), OR/AND-joined. */\ntype OptionCondition = {\n or?: string[];\n and?: string[];\n};\n\n/** Link/reference match by id (User / System[Reference]): `eq` one id, or OR/AND a set of ids. */\ntype ReferenceCondition = {\n eq?: number;\n or?: number[];\n and?: number[];\n};\n\n/** The condition-operator object a field of Data Type `D` accepts. */\ntype ConditionFor<D extends DataType> = D extends \"System[Id]\"\n ? IdCondition\n : D extends \"Number\"\n ? NumberCondition\n : D extends \"DateTime\" | \"System[DateTime]\" | \"Date\" | \"Age\"\n ? TemporalCondition\n : D extends\n \"SinglelineText\" | \"MultilineText\" | \"Mail\" | \"Telephone\" | \"URL\"\n ? TextCondition\n : D extends \"Option\"\n ? OptionCondition\n : D extends \"User\" | \"System[Reference]\"\n ? ReferenceCondition\n : never;\n\n/**\n * A typed search condition over a catalog: each field maps to the operator object its Data Type\n * allows (ADR-0038 案1a). Multiple fields are AND-joined (reference). Unknown aliases / wrong\n * operators are type errors. Custom `U_`/`A_` fields are not in the catalog — condition on them via\n * a cast (the encoder passes unknown aliases through as raw scalars, like read/write).\n */\nexport type Condition<F extends FieldCatalog> = {\n [K in keyof F]?: ConditionFor<F[K]>;\n};\n\n// --- order (reference: Read - Order; only Number/Currency/Age/Date/DateTime/System are sortable) ---\n\ntype OrderableDataType =\n \"System[Id]\" | \"System[DateTime]\" | \"Number\" | \"DateTime\" | \"Date\" | \"Age\";\n\ntype OrderableKeys<F extends FieldCatalog> = {\n [K in keyof F]: F[K] extends OrderableDataType ? K : never;\n}[keyof F];\n\n/**\n * Sort spec: an ordered list of `{ field: \"asc\" | \"desc\" }`, encoded in array (then key) order. Only\n * orderable Data Types (Number/Date/DateTime/Age/System) are accepted (reference).\n */\nexport type Order<F extends FieldCatalog> = Array<\n Partial<Record<OrderableKeys<F>, \"asc\" | \"desc\">>\n>;\n\n// --- itemstate (reference: 削除済みデータ取得) ---\n\n/**\n * Which delete state to read. Omitting (or `existing`) reads live data; `deleted`/`all` read deleted\n * records — the only way to read deleted data, since there is no delete API. When `deleted`/`all`,\n * condition is restricted to `P_Id` / `P_UpdateDate` / `P_UpdatedBy` and PORTERS auto-adds a\n * \"updated within 90 days\" filter (`P_UpdateDate` = the delete time, `P_UpdatedBy` = the last editor).\n */\nexport type ItemState = \"existing\" | \"deleted\" | \"all\";\n\n// --- the public query shape (moved here from resource.ts; data resources parametrise over their catalog) ---\n\nexport type SearchQuery<F extends FieldCatalog = FieldCatalog> = {\n /**\n * Output fields as prefixed aliases (e.g. `Person.P_Name`). **Omit** to fetch every catalogued\n * field by default (ADR-0020): PORTERS returns only the primary key for a fieldless request, so\n * the library sends a catalog-derived default field set instead. Pass `[]` to opt into that\n * API-native \"primary key only\" response (e.g. counting). A non-empty list is sent verbatim.\n */\n field?: string[];\n /** Typed AND-conditions; each field's operators derive from its Data Type (ADR-0038). */\n condition?: Condition<F>;\n /** Sort order; orderable Data Types only (Number/Date/DateTime/Age/System). */\n order?: Order<F>;\n /**\n * Keyword AND-search over text fields (MultilineText/SinglelineText/Mail/URL; Telephone digits\n * only). OR is not supported. Max 100 characters including commas — guarded before send.\n */\n keywords?: string[];\n /** Delete-state filter (default `existing`). `deleted`/`all` restrict `condition` — see {@link ItemState}. */\n itemstate?: ItemState;\n count?: number;\n start?: number;\n};\n\n// --- encoder (typed query -> wire params) ---\n\nconst KEYWORDS_MAX_CHARS = 100;\n// itemstate=deleted/all restricts condition to these standard fields (reference / 削除済みデータ取得).\nconst DELETED_CONDITION_FIELDS = new Set([\n \"P_Id\",\n \"P_UpdateDate\",\n \"P_UpdatedBy\",\n]);\n\n/** Output context for prefixing aliases and resolving each field's Data Type. */\ntype QueryContext = {\n prefix: string;\n fields: ReadonlyMap<string, DataType>;\n};\n\n/**\n * Serialise one condition value by the field's Data Type: dates ISO -> PORTERS, arrays (Option\n * aliases / id sets) colon-joined, everything else stringified. Unknown alias (no Data Type) ->\n * raw scalar, mirroring read/write passthrough.\n */\nconst serializeConditionValue = (\n type: DataType | undefined,\n value: unknown,\n): string => {\n if (Array.isArray(value)) return value.map(String).join(\":\");\n if (type === \"DateTime\" || type === \"System[DateTime]\") {\n return isoToPortersDateTime(String(value));\n }\n if (type === \"Date\" || type === \"Age\") return isoToPortersDate(String(value));\n return String(value);\n};\n\n// condition -> `Prefix.alias:suffix=value,...`. Throws if itemstate=deleted/all names a field\n// outside P_Id/P_UpdateDate/P_UpdatedBy (PORTERS would 400 — fail fast before send). Typed over the\n// loose catalog: `Condition<F>` is assignable in, and the encoding is purely structural.\nconst encodeCondition = (\n condition: Condition<FieldCatalog>,\n itemstate: ItemState | undefined,\n ctx: QueryContext,\n): string => {\n const restricted = itemstate === \"deleted\" || itemstate === \"all\";\n const parts: string[] = [];\n for (const [alias, ops] of Object.entries(condition)) {\n if (ops === undefined) continue;\n if (restricted && !DELETED_CONDITION_FIELDS.has(alias)) {\n throw new PortersConfigError(\n `condition field \"${alias}\" is not allowed when itemstate is \"${itemstate}\"`,\n {\n category: \"config\",\n hint: \"Deleted reads (itemstate deleted/all) accept only P_Id, P_UpdateDate, P_UpdatedBy in condition.\",\n },\n );\n }\n const type = ctx.fields.get(alias);\n for (const [suffix, value] of Object.entries(ops)) {\n if (value === undefined) continue;\n parts.push(\n `${ctx.prefix}.${alias}:${suffix}=${serializeConditionValue(type, value)}`,\n );\n }\n }\n return parts.join(\",\");\n};\n\n// order -> `Prefix.alias:dir,...` in array (then key) order. Loosely typed (Order<F> assigns in);\n// `Order<FieldCatalog>` collapses its value type, so read each spec's entries as directions.\nconst encodeOrder = (order: Order<FieldCatalog>, ctx: QueryContext): string => {\n const parts: string[] = [];\n for (const spec of order) {\n const dirs = spec as Record<string, \"asc\" | \"desc\" | undefined>;\n for (const [alias, dir] of Object.entries(dirs)) {\n if (dir === undefined) continue;\n parts.push(`${ctx.prefix}.${alias}:${dir}`);\n }\n }\n return parts.join(\",\");\n};\n\n/**\n * Set the typed Read query params (condition / order / keywords / itemstate) on `p`. Universal\n * params (partition / field / count / start) stay in `buildReadUrl`. Throws `PortersConfigError`\n * for caller-side misuse (keywords too long, itemstate-restricted condition) before any request.\n */\nexport const appendReadQuery = <F extends FieldCatalog>(\n p: URLSearchParams,\n q: SearchQuery<F>,\n ctx: QueryContext,\n): void => {\n if (q.condition) {\n const cond = encodeCondition(q.condition, q.itemstate, ctx);\n if (cond.length > 0) p.set(\"condition\", cond);\n }\n if (q.order) {\n const order = encodeOrder(q.order, ctx);\n if (order.length > 0) p.set(\"order\", order);\n }\n if (q.keywords && q.keywords.length > 0) {\n const kw = q.keywords.join(\",\");\n if (kw.length > KEYWORDS_MAX_CHARS) {\n throw new PortersConfigError(\n `keywords is ${kw.length} characters, over the ${KEYWORDS_MAX_CHARS}-character limit`,\n {\n category: \"config\",\n hint: \"Shorten keywords: PORTERS caps the keyword search at 100 characters including commas.\",\n },\n );\n }\n p.set(\"keywords\", kw);\n }\n // `existing` is the API default — omit it to keep URLs minimal (and stable vs. pre-F-2 reads).\n if (q.itemstate !== undefined && q.itemstate !== \"existing\") {\n p.set(\"itemstate\", q.itemstate);\n }\n};\n","// Bulk write (ADR-0041 / F-4): createMany / updateMany over PORTERS' multi-`<Item>` Write.\n// A single request holds up to 200 records and must stay under the ~15000-char cap, so this\n// splits the input into size- and count-bounded batches, sends them sequentially (the write\n// throttle paces them), and concatenates the per-item results in input order. A batch is NOT\n// atomic — each `<Item>` carries its own `<Code>` — so per-item failures are returned (not\n// thrown); only a whole-request failure throws. The generic factory wires this; XML stays in xml/.\n\nimport {\n PortersConfigError,\n PortersError,\n PortersResourceError,\n} from \"../errors\";\nimport { MAX_REQUEST_LENGTH, type Requester } from \"../http/requester\";\nimport type { DataType } from \"../xml/decode\";\nimport { encodeWriteItem, type WriteItem } from \"../xml/encode\";\nimport { parseWriteResult, type WriteResultItem } from \"../xml/parser\";\n\n/** PORTERS caps a Write request at 200 records; larger inputs are split into batches of 200. */\nconst MAX_ITEMS_PER_REQUEST = 200;\n\n/** One record's outcome from a bulk write, in the position it was sent (ADR-0041 SD-2). */\nexport type BulkWriteResultItem = {\n /** 0-based index in the input array. */\n index: number;\n /** Assigned (create) / echoed (update) record id. Meaningful only when `ok`. */\n id: number;\n /** PORTERS per-item Result Code (`0` = success). */\n code: number;\n /** `code === 0`. */\n ok: boolean;\n};\n\n/**\n * The result of `createMany` / `updateMany` (ADR-0041). `results` holds every record's outcome in\n * input order; `failed` is the `ok === false` subset. A per-item `code !== 0` does **not** throw —\n * a bulk write mixes successes and failures — so always inspect `hasFailures` / `failed`.\n */\nexport type BulkWriteResult = {\n results: BulkWriteResultItem[];\n failed: BulkWriteResultItem[];\n hasFailures: boolean;\n};\n\n// A record paired with its original index and pre-serialized `<Item>…</Item>` (measured for packing).\ntype Encoded = { index: number; xml: string };\n\n/**\n * Greedily pack encoded records into batches that each stay within `budget` characters (the request\n * cap minus URL + envelope overhead) and `MAX_ITEMS_PER_REQUEST` records. A single record larger than\n * `budget` cannot be sent in any batch → fail fast with a clear config error (send-time, fail-safe).\n */\nconst packBatches = (encoded: Encoded[], budget: number): Encoded[][] => {\n const batches: Encoded[][] = [];\n let batch: Encoded[] = [];\n let length = 0;\n for (const e of encoded) {\n if (e.xml.length > budget) {\n throw new PortersConfigError(\n `a single record serializes to ${e.xml.length} characters, over the ~${budget}-character budget for one request`,\n {\n category: \"config\",\n hint: \"Reduce that record's field values — a bulk request (URL + body) is capped at ~15000 characters.\",\n },\n );\n }\n // Start a new batch when the next record would breach either bound. Never reached with an empty\n // batch: on the first record `length` and `batch.length` are 0 and an over-budget record already\n // threw above, so `batch` is always non-empty here (no empty batch is ever pushed).\n if (\n batch.length >= MAX_ITEMS_PER_REQUEST ||\n length + e.xml.length > budget\n ) {\n batches.push(batch);\n batch = [];\n length = 0;\n }\n batch.push(e);\n length += e.xml.length;\n }\n if (batch.length > 0) batches.push(batch);\n return batches;\n};\n\n// A batch failed at the request level after earlier batches were already applied. Creates are\n// non-idempotent, so a blind full retry would duplicate them — surface the progress instead (SD-4).\nconst batchFailure = (\n cause: unknown,\n written: number,\n resource: string,\n partition: number,\n): PortersError => {\n const base = cause instanceof PortersError ? cause : undefined;\n return new PortersResourceError(\n `bulk write failed after ${written} record(s) had already been written`,\n {\n category: base?.category ?? \"unknown\",\n code: base?.code ?? null,\n retryable: false,\n httpStatus: base?.httpStatus,\n hint: `${written} record(s) from earlier batches were already written; retry only the records from index ${written} onward (create is non-idempotent — a full retry would duplicate them).`,\n context: { resource, operation: \"bulkWrite\", partition },\n cause,\n },\n );\n};\n\n/**\n * Execute a bulk write: split `items` into batches, POST each, and merge the per-item results.\n * `target.url` is the (short) Write URL; `idempotent` is false for create (non-idempotent), true for\n * update. Per-item `code !== 0` is returned in the result; a whole-request failure throws — with the\n * already-written count once at least one earlier batch succeeded (SD-4).\n */\nexport const runBulkWrite = async (\n requester: Requester,\n target: {\n name: string;\n prefix: string;\n fields: ReadonlyMap<string, DataType>;\n url: string;\n partition: number;\n },\n items: WriteItem[],\n idempotent: boolean,\n): Promise<BulkWriteResult> => {\n const envelope = `<${target.name}></${target.name}>`.length;\n const budget = MAX_REQUEST_LENGTH - target.url.length - envelope;\n const encoded: Encoded[] = items.map((item, index) => ({\n index,\n xml: encodeWriteItem(target.prefix, target.fields, item),\n }));\n const batches = packBatches(encoded, budget);\n\n const results: BulkWriteResultItem[] = [];\n let written = 0;\n for (const batch of batches) {\n const body = `<${target.name}>${batch.map((e) => e.xml).join(\"\")}</${target.name}>`;\n let parsed: WriteResultItem[];\n try {\n parsed = await requester.request(\n { method: \"POST\", url: target.url, headers: {}, body },\n parseWriteResult,\n { write: true, idempotent },\n );\n } catch (cause) {\n // First batch failed = nothing applied yet → surface the original error unchanged.\n if (written === 0) throw cause;\n throw batchFailure(cause, written, target.name, target.partition);\n }\n if (parsed.length !== batch.length) {\n throw new PortersResourceError(\n `bulk write response returned ${parsed.length} result(s) for ${batch.length} record(s)`,\n { category: \"unknown\", context: { resource: target.name } },\n );\n }\n batch.forEach((e, i) => {\n const { id, code } = parsed[i];\n results.push({ index: e.index, id, code, ok: code === 0 });\n });\n written += batch.length;\n }\n\n const failed = results.filter((r) => !r.ok);\n return { results, failed, hasFailures: failed.length > 0 };\n};\n","// Generic resource accessor (ADR-0004/0005/0011): the Read (search / searchAll /\n// get) + Write (create / update) shape shared by every PORTERS resource. A resource\n// module supplies its names + Data-Type catalog; this owns the wiring and keeps XML\n// out of resources/ (parse/encode live in xml/). Standard `P_` fields use the catalog;\n// custom `U_`/`A_` pass through (decode: raw string / encode: Text).\n\nimport { PortersResourceError, resourceError } from \"../errors\";\nimport type { Requester } from \"../http/requester\";\nimport type { DataType } from \"../xml/decode\";\nimport {\n buildWriteXml,\n type WritableDataType,\n type WriteItem,\n type WriteValueOf,\n} from \"../xml/encode\";\nimport { parseWriteResult } from \"../xml/parser\";\nimport {\n decoderFor,\n paginate,\n runRead,\n type FieldCatalog,\n type ReadRecord,\n type ResourcePage,\n} from \"./read-core\";\nimport { appendReadQuery, type Condition, type SearchQuery } from \"./query\";\nimport { runBulkWrite, type BulkWriteResult } from \"./bulk-write\";\n\n// Shared Read types/internals live in read-core (reused by master resources). Re-export the\n// types so the data-resource modules keep importing them from \"./resource\".\nexport type {\n EmptyCatalog,\n FieldCatalog,\n ReadRecord,\n ResourcePage,\n} from \"./read-core\";\n// Typed Read query surface (ADR-0038 / F-2). Defined in query.ts; re-exported so resource modules\n// and the public barrel keep importing the query types from \"./resource\".\nexport type { Condition, ItemState, Order, SearchQuery } from \"./query\";\n// Bulk write result (ADR-0041 / F-4). Defined in bulk-write.ts; re-exported so resource modules and\n// the public barrel keep importing the bulk types from \"./resource\".\nexport type { BulkWriteResult, BulkWriteResultItem } from \"./bulk-write\";\n\n// Writable aliases: every field whose Data Type a user may write (excludes System[Id] /\n// System[DateTime] — ADR-0016/0019).\ntype WritableKeys<F extends FieldCatalog> = {\n [K in keyof F]: F[K] extends WritableDataType ? K : never;\n}[keyof F];\n\n/**\n * Create input (ADR-0019 W2): the `requiredOnCreate` aliases are **required** (non-null); every\n * other writable field is optional (`null` omits). `P_Id` is supplied by the library — not here.\n */\nexport type CreateInput<F extends FieldCatalog, Req extends keyof F> = {\n [K in Req]: WriteValueOf<F[K]>;\n} & {\n [K in Exclude<WritableKeys<F>, Req>]?: WriteValueOf<F[K]> | null;\n};\n\n/** Update input (ADR-0019 W2): every writable field optional (`null` omits, `\"\"` clears). */\nexport type UpdateInput<F extends FieldCatalog> = {\n [K in WritableKeys<F>]?: WriteValueOf<F[K]> | null;\n};\n\n/** Static description of a resource: names + `as const` catalog + required-on-create aliases. */\nexport type ResourceConfig<\n F extends FieldCatalog,\n Req extends readonly (keyof F)[],\n> = {\n /** Root element + Write resource name, e.g. `\"Candidate\"`. */\n name: string;\n /** URL path segment, e.g. `\"candidate\"`. */\n path: string;\n /** Field alias prefix, e.g. `\"Person\"`. */\n prefix: string;\n /** Data-Type catalog (`as const`): bare alias -> Data Type. */\n fields: F;\n /** Aliases required on `create` (PORTERS new-record requirements — ADR-0019 W2). */\n requiredOnCreate: Req;\n};\n\nexport type Resource<F extends FieldCatalog, Req extends keyof F> = {\n search(query?: SearchQuery<F>): Promise<ResourcePage<F>>;\n /** Auto-paginating search: yields every matching record (200 per page). */\n searchAll(\n query?: Omit<SearchQuery<F>, \"count\" | \"start\">,\n ): AsyncIterable<ReadRecord<F>>;\n get(id: number): Promise<ReadRecord<F> | undefined>;\n /** Create one record; resolves to the newly assigned id. */\n create(input: CreateInput<F, Req>): Promise<number>;\n /** Update one record by id; resolves to that id. */\n update(id: number, input: UpdateInput<F>): Promise<number>;\n /**\n * Create many records in one call (ADR-0041 / F-4). Auto-batched to ≤200 records and under the\n * request size cap. **Not atomic** — inspect the {@link BulkWriteResult}: per-record failures are\n * returned (`failed` / `hasFailures`), not thrown. Only a whole-request failure throws (with the\n * already-written count). Batching is non-idempotent: a full retry after a mid-run failure may\n * duplicate creates. Empty input sends no request.\n */\n createMany(inputs: CreateInput<F, Req>[]): Promise<BulkWriteResult>;\n /**\n * Update many records by id in one call (ADR-0041 / F-4). Auto-batched like {@link createMany};\n * per-record failures are returned in the {@link BulkWriteResult}, not thrown.\n */\n updateMany(\n items: { id: number; fields: UpdateInput<F> }[],\n ): Promise<BulkWriteResult>;\n};\n\n// The 4 readable sub-fields of a User-type field (docs/reference: only these are returned).\nconst USER_SUBFIELDS = [\"P_Id\", \"P_Type\", \"P_Name\", \"P_Mail\"] as const;\n\n// Default Read `field` list derived from the catalog (ADR-0020, 案A+2a). PORTERS returns only\n// `{Resource}.P_Id` for a fieldless request, so a typed-record read would otherwise drop every\n// known field despite the type promising them. We send every catalog alias as `{prefix}.{alias}`,\n// expanding User to its 4 readable sub-fields and leaving System[Reference] ID-only (`()` omitted)\n// so the wire shape matches decode.ts. The API-native \"primary key only\" stays reachable via\n// `field: []` (透明化 — see SearchQuery.field).\nconst defaultFieldList = (prefix: string, fields: FieldCatalog): string[] =>\n Object.entries(fields).map(([alias, type]) =>\n type === \"User\"\n ? `${prefix}.${alias}(${USER_SUBFIELDS.map((s) => `User.${s}`).join(\",\")})`\n : `${prefix}.${alias}`,\n );\n\n/**\n * A single-Item Write response -> the assigned/updated id. A non-zero per-item Code is a\n * resource error (mapped, not swallowed); a missing result Item is unparseable. Shared by\n * the generic factory and the bespoke Attachment accessor. `path` names the error code\n * message, `name` the error context resource.\n */\nexport const firstWriteResultId = (\n body: string,\n path: string,\n name: string,\n): number => {\n const first = parseWriteResult(body)[0];\n if (first === undefined) {\n throw new PortersResourceError(\"write returned no result item\", {\n category: \"unknown\",\n });\n }\n if (first.code !== 0) {\n throw resourceError(\n first.code,\n `${path} write returned code ${first.code}`,\n {\n resource: name,\n },\n );\n }\n return first.id;\n};\n\n/**\n * Build a Read URL: `https://{host}/v1/{path}?partition=…&field=…&condition=…&order=…&keywords=…&itemstate=…&count=…&start=…`.\n * `ctx` (alias prefix + Data-Type map) drives the typed query encoding (ADR-0038): condition/order\n * prefixing, date ISO -> PORTERS, and the keyword/itemstate guards. Attachment is bespoke (no prefix\n * / no catalog) and builds its own loose URL — see attachment.ts.\n */\nexport const buildReadUrl = <F extends FieldCatalog>(\n host: string,\n partition: number,\n path: string,\n q: SearchQuery<F>,\n ctx: { prefix: string; fields: ReadonlyMap<string, DataType> },\n): string => {\n const p = new URLSearchParams();\n p.set(\"partition\", String(partition));\n if (q.field && q.field.length > 0) p.set(\"field\", q.field.join(\",\"));\n appendReadQuery(p, q, ctx);\n if (q.count !== undefined) p.set(\"count\", String(q.count));\n if (q.start !== undefined) p.set(\"start\", String(q.start));\n return `https://${host}/v1/${path}?${p.toString()}`;\n};\n\n/** Build a Write URL: `https://{host}/v1/{path}?partition=…`. */\nexport const buildWriteUrl = (\n host: string,\n partition: number,\n path: string,\n): string => `https://${host}/v1/${path}?partition=${partition}`;\n\nexport const createResource = <\n const F extends FieldCatalog,\n const Req extends readonly (keyof F)[],\n>(\n config: ResourceConfig<F, Req>,\n deps: { requester: Requester; host: string; partition: number },\n): Resource<F, Req[number]> => {\n // The catalog is `as const` for the types; encode needs a runtime lookup, decode gets its own.\n const fieldMap = new Map<string, DataType>(Object.entries(config.fields));\n const decode = decoderFor(config.fields);\n // Computed once: the default field set sent when a caller omits `field` (ADR-0020).\n const defaultFields = defaultFieldList(config.prefix, config.fields);\n\n const readUrl = (q: SearchQuery<F>): string =>\n buildReadUrl(deps.host, deps.partition, config.path, q, {\n prefix: config.prefix,\n fields: fieldMap,\n });\n\n const writeUrl = (): string =>\n buildWriteUrl(deps.host, deps.partition, config.path);\n\n const firstWriteId = (body: string): number =>\n firstWriteResultId(body, config.path, config.name);\n\n // `field` omitted -> send the catalog default; `[]` stays empty (API-native primary key\n // only); a provided list is sent verbatim (ADR-0020).\n const search = (query: SearchQuery<F> = {}): Promise<ResourcePage<F>> =>\n runRead(\n deps.requester,\n readUrl({ ...query, field: query.field ?? defaultFields }),\n decode,\n );\n\n const searchAll = (\n query: Omit<SearchQuery<F>, \"count\" | \"start\"> = {},\n ): AsyncIterable<ReadRecord<F>> =>\n paginate((count, start) => search({ ...query, count, start }));\n\n const get = async (id: number): Promise<ReadRecord<F> | undefined> => {\n // Every catalog carries `P_Id` (System[Id]); the generic `F` can't prove it statically, so\n // build the condition at runtime and let the encoder prefix it (`{prefix}.P_Id:eq=id`).\n const condition = { P_Id: { eq: id } } as unknown as Condition<F>;\n const page = await search({ condition, count: 1 });\n return page.items[0];\n };\n\n // create forces P_Id=-1 (non-idempotent: a retry would duplicate); update forces\n // the target id (idempotent: re-applying the same write is safe). Forcing P_Id\n // after the spread means a caller-supplied P_Id never overrides it.\n const write = (item: WriteItem, idempotent: boolean): Promise<number> =>\n deps.requester.request(\n {\n method: \"POST\",\n url: writeUrl(),\n headers: {},\n body: buildWriteXml({\n resource: config.name,\n prefix: config.prefix,\n fields: fieldMap,\n items: [item],\n }),\n },\n firstWriteId,\n { write: true, idempotent },\n );\n\n const create = (input: CreateInput<F, Req[number]>): Promise<number> =>\n write({ ...input, P_Id: -1 }, false);\n\n const update = (id: number, input: UpdateInput<F>): Promise<number> =>\n write({ ...input, P_Id: id }, true);\n\n // Bulk write (ADR-0041): map each input to a WriteItem with its P_Id (create = -1, update = id) —\n // mirroring single write — and hand the array to the batching executor. createMany is\n // non-idempotent (P_Id=-1), updateMany idempotent (targets ids).\n const target = {\n name: config.name,\n prefix: config.prefix,\n fields: fieldMap,\n partition: deps.partition,\n };\n const createMany = (\n inputs: CreateInput<F, Req[number]>[],\n ): Promise<BulkWriteResult> =>\n runBulkWrite(\n deps.requester,\n { ...target, url: writeUrl() },\n inputs.map((input) => ({ ...input, P_Id: -1 })),\n false,\n );\n\n const updateMany = (\n items: { id: number; fields: UpdateInput<F> }[],\n ): Promise<BulkWriteResult> =>\n runBulkWrite(\n deps.requester,\n { ...target, url: writeUrl() },\n items.map(({ id, fields }) => ({ ...fields, P_Id: id })),\n true,\n );\n\n return { search, searchAll, get, create, update, createMany, updateMany };\n};\n","// Candidate accessor (ADR-0004/0005/0011/0019): Read (search / searchAll / get) + Write\n// (create / update) over the generic resource factory. Only the Data-Type catalog and names\n// are Candidate-specific; the static Candidate / input types derive from the catalog\n// (single source of truth — ADR-0019).\n\nimport type { Requester } from \"../http/requester\";\nimport {\n createResource,\n type CreateInput,\n type EmptyCatalog,\n type FieldCatalog,\n type ReadRecord,\n type Resource,\n type ResourcePage,\n type SearchQuery,\n type UpdateInput,\n} from \"./resource\";\n\nconst FIELDS = {\n P_Id: \"System[Id]\",\n P_Owner: \"User\",\n P_RegistrationDate: \"System[DateTime]\",\n P_RegisteredBy: \"User\",\n P_UpdateDate: \"System[DateTime]\",\n P_UpdatedBy: \"User\",\n P_Phase: \"Option\",\n P_PhaseDate: \"DateTime\",\n P_Name: \"SinglelineText\",\n P_Reading: \"SinglelineText\",\n P_Mail: \"Mail\",\n P_MobileMail: \"Mail\",\n P_Telephone: \"Telephone\",\n P_Mobile: \"Telephone\",\n P_Country: \"SinglelineText\",\n P_Prefecture: \"SinglelineText\",\n P_City: \"SinglelineText\",\n P_Zipcode: \"SinglelineText\",\n} as const satisfies FieldCatalog;\n\n// Required on create per docs/reference (resources/candidate.md「新規必須」列): P_Owner。\n// (System[Id] の P_Id も新規必須だが lib が -1 を供給するため型からは除外。LV-5 は reference で確定。)\nconst REQUIRED_ON_CREATE = [\n \"P_Owner\",\n] as const satisfies readonly (keyof typeof FIELDS)[];\n\n/** A decoded Candidate: known `P_` fields, each requested field `value | null`. */\nexport type Candidate = ReadRecord<typeof FIELDS>;\nexport type CandidatePage = ResourcePage<typeof FIELDS>;\nexport type CandidateSearchQuery = SearchQuery<typeof FIELDS>;\n\n/** Fields for `create`: `P_Owner` is required; `P_Id` / system timestamps are not settable. */\nexport type CandidateCreateInput = CreateInput<\n typeof FIELDS,\n (typeof REQUIRED_ON_CREATE)[number]\n>;\n/** Fields for `update`: all optional (`null` omits, `\"\"` clears a text field). */\nexport type CandidateUpdateInput = UpdateInput<typeof FIELDS>;\n/** The Candidate accessor; `C` is the declared custom-field catalog merged on (ADR-0023). */\nexport type CandidateResource<C extends FieldCatalog = EmptyCatalog> = Resource<\n typeof FIELDS & C,\n (typeof REQUIRED_ON_CREATE)[number]\n>;\n\nexport const createCandidateResource = <C extends FieldCatalog = EmptyCatalog>(\n deps: { requester: Requester; host: string; partition: number },\n custom?: C,\n): CandidateResource<C> => {\n // Custom U_/A_ aliases never collide with P_, so the merge is exactly `typeof FIELDS & C`;\n // the cast just names that intersection (defineFields already validated aliases — ADR-0023 D7).\n const fields = { ...FIELDS, ...custom } as typeof FIELDS & C;\n return createResource(\n {\n name: \"Candidate\",\n path: \"candidate\",\n prefix: \"Person\",\n fields,\n requiredOnCreate: REQUIRED_ON_CREATE,\n },\n deps,\n );\n};\n","// Job accessor (ADR-0004/0005/0011/0019): Read (search / searchAll / get) + Write\n// (create / update) over the generic resource factory. Only the Data-Type catalog and\n// names are Job-specific. P_Client / P_Recruiter are System[Reference] (Write = ID).\n//\n// Display-only Reference fields (P_Mail, P_*Reference — they mirror a Recruiter value and\n// are not writable) are intentionally left out of the catalog: they read through as raw\n// strings. Multi-select Option read returns every selected alias as `string[]` (ADR-0017).\n// The static Job / input types derive from the catalog (ADR-0019).\n\nimport type { Requester } from \"../http/requester\";\nimport {\n createResource,\n type CreateInput,\n type EmptyCatalog,\n type FieldCatalog,\n type ReadRecord,\n type Resource,\n type ResourcePage,\n type SearchQuery,\n type UpdateInput,\n} from \"./resource\";\n\nconst FIELDS = {\n P_Id: \"System[Id]\",\n P_Owner: \"User\",\n P_Client: \"System[Reference]\",\n P_Recruiter: \"System[Reference]\",\n P_RegistrationDate: \"System[DateTime]\",\n P_RegisteredBy: \"User\",\n P_UpdateDate: \"System[DateTime]\",\n P_UpdatedBy: \"User\",\n P_Phase: \"Option\",\n P_PhaseDate: \"DateTime\",\n P_PhaseMemo: \"MultilineText\",\n P_Position: \"SinglelineText\",\n P_Publish: \"Option\",\n P_JobCategorySummary: \"MultilineText\",\n P_JobCategory: \"Option\",\n P_IndustrySummary: \"MultilineText\",\n P_Industry: \"Option\",\n P_SalarySummary: \"MultilineText\",\n P_MinSalary: \"Number\",\n P_MaxSalary: \"Number\",\n P_AreaSummary: \"MultilineText\",\n P_Area: \"Option\",\n P_PayrollsText: \"SinglelineText\",\n P_Memo: \"MultilineText\",\n P_EmploymentPeriod: \"MultilineText\",\n // \"P_WokingHours\" is the alias as published by PORTERS (source typo); keep verbatim.\n P_WokingHours: \"MultilineText\",\n P_Holidays: \"MultilineText\",\n P_Benefits: \"MultilineText\",\n P_PubliclyTraded: \"Option\",\n P_SalesAmountText: \"SinglelineText\",\n P_EstablishmentDateText: \"SinglelineText\",\n P_CapitalText: \"SinglelineText\",\n P_EmploymentType: \"Option\",\n P_ExpectedAgeReason: \"Option\",\n} as const satisfies FieldCatalog;\n\n// Required on create per docs/reference (resources/job.md「新規必須」列): P_Owner / P_Client /\n// P_Recruiter(P_Id は System[Id]=lib 供給のため除外)。LV-5 は reference で確定。\nconst REQUIRED_ON_CREATE = [\n \"P_Owner\",\n \"P_Client\",\n \"P_Recruiter\",\n] as const satisfies readonly (keyof typeof FIELDS)[];\n\n/** A decoded Job: known `P_` fields, each requested field `value | null`. */\nexport type Job = ReadRecord<typeof FIELDS>;\nexport type JobPage = ResourcePage<typeof FIELDS>;\nexport type JobSearchQuery = SearchQuery<typeof FIELDS>;\n\n/** Fields for `create`: `P_Owner` required; `P_Id` / system timestamps are not settable. */\nexport type JobCreateInput = CreateInput<\n typeof FIELDS,\n (typeof REQUIRED_ON_CREATE)[number]\n>;\n/** Fields for `update`: all optional (`null` omits, `\"\"` clears a text field). */\nexport type JobUpdateInput = UpdateInput<typeof FIELDS>;\n/** The Job accessor; `C` is the declared custom-field catalog merged on (ADR-0023). */\nexport type JobResource<C extends FieldCatalog = EmptyCatalog> = Resource<\n typeof FIELDS & C,\n (typeof REQUIRED_ON_CREATE)[number]\n>;\n\nexport const createJobResource = <C extends FieldCatalog = EmptyCatalog>(\n deps: { requester: Requester; host: string; partition: number },\n custom?: C,\n): JobResource<C> => {\n // Custom U_/A_ aliases never collide with P_, so the merge is exactly `typeof FIELDS & C`;\n // the cast just names that intersection (defineFields already validated aliases — ADR-0023 D7).\n const fields = { ...FIELDS, ...custom } as typeof FIELDS & C;\n return createResource(\n {\n name: \"Job\",\n path: \"job\",\n prefix: \"Job\",\n fields,\n requiredOnCreate: REQUIRED_ON_CREATE,\n },\n deps,\n );\n};\n","// Client accessor (ADR-0004/0005/0011/0019): Read (search / searchAll / get) + Write\n// (create / update) over the generic resource factory. Only the Data-Type catalog and\n// names are Client-specific; the static Client / input types derive from the catalog\n// (ADR-0019).\n\nimport type { Requester } from \"../http/requester\";\nimport {\n createResource,\n type CreateInput,\n type EmptyCatalog,\n type FieldCatalog,\n type ReadRecord,\n type Resource,\n type ResourcePage,\n type SearchQuery,\n type UpdateInput,\n} from \"./resource\";\n\nconst FIELDS = {\n P_Id: \"System[Id]\",\n P_Owner: \"User\",\n P_RegistrationDate: \"System[DateTime]\",\n P_RegisteredBy: \"User\",\n P_UpdateDate: \"System[DateTime]\",\n P_UpdatedBy: \"User\",\n P_Phase: \"Option\",\n P_PhaseDate: \"DateTime\",\n P_PhaseMemo: \"MultilineText\",\n P_Name: \"SinglelineText\",\n P_Memo: \"MultilineText\",\n P_Country: \"SinglelineText\",\n P_Prefecture: \"SinglelineText\",\n P_City: \"SinglelineText\",\n P_Street: \"MultilineText\",\n P_Zipcode: \"SinglelineText\",\n P_Telephone: \"Telephone\",\n P_Fax: \"Telephone\",\n} as const satisfies FieldCatalog;\n\n// Required on create per docs/reference (resources/client.md「新規必須」列): P_Owner。\n// (P_Id は System[Id]=lib 供給のため除外。LV-5 は reference で確定。)\nconst REQUIRED_ON_CREATE = [\n \"P_Owner\",\n] as const satisfies readonly (keyof typeof FIELDS)[];\n\n/** A decoded Client (company): known `P_` fields, each requested field `value | null`. */\nexport type Client = ReadRecord<typeof FIELDS>;\nexport type ClientPage = ResourcePage<typeof FIELDS>;\nexport type ClientSearchQuery = SearchQuery<typeof FIELDS>;\n\n/** Fields for `create`: `P_Owner` required; `P_Id` / system timestamps are not settable. */\nexport type ClientCreateInput = CreateInput<\n typeof FIELDS,\n (typeof REQUIRED_ON_CREATE)[number]\n>;\n/** Fields for `update`: all optional (`null` omits, `\"\"` clears a text field). */\nexport type ClientUpdateInput = UpdateInput<typeof FIELDS>;\n/** The Client accessor; `C` is the declared custom-field catalog merged on (ADR-0023). */\nexport type ClientResource<C extends FieldCatalog = EmptyCatalog> = Resource<\n typeof FIELDS & C,\n (typeof REQUIRED_ON_CREATE)[number]\n>;\n\nexport const createClientResource = <C extends FieldCatalog = EmptyCatalog>(\n deps: { requester: Requester; host: string; partition: number },\n custom?: C,\n): ClientResource<C> => {\n // Custom U_/A_ aliases never collide with P_, so the merge is exactly `typeof FIELDS & C`;\n // the cast just names that intersection (defineFields already validated aliases — ADR-0023 D7).\n const fields = { ...FIELDS, ...custom } as typeof FIELDS & C;\n return createResource(\n {\n name: \"Client\",\n path: \"client\",\n prefix: \"Client\",\n fields,\n requiredOnCreate: REQUIRED_ON_CREATE,\n },\n deps,\n );\n};\n","// Process accessor (ADR-0004/0005/0011/0019): Read (search / searchAll / get) + Write\n// (create / update) over the generic resource factory. Process is the relational\n// resource linking a Candidate to a Job; P_Client / P_Recruiter / P_Job / P_Candidate /\n// P_Resume are System[Reference] (Write = the related record's id; P_Candidate is the\n// Person id).\n//\n// Display-only Reference fields (P_JobOwner, P_Job*Reference, P_ResumeOwner,\n// P_Resume*Reference — they mirror a Job/Recruiter/Person value and are not writable) are\n// intentionally left out of the catalog: scalar mirrors read through as raw strings,\n// nested ones (e.g. P_JobOwner -> a User) read as null. Multi-select Option read returns every\n// selected alias as `string[]` (ADR-0017). The static Process / input types derive from the catalog (ADR-0019).\n\nimport type { Requester } from \"../http/requester\";\nimport {\n createResource,\n type CreateInput,\n type EmptyCatalog,\n type FieldCatalog,\n type ReadRecord,\n type Resource,\n type ResourcePage,\n type SearchQuery,\n type UpdateInput,\n} from \"./resource\";\n\nconst FIELDS = {\n P_Id: \"System[Id]\",\n P_Owner: \"User\",\n P_Client: \"System[Reference]\",\n P_Recruiter: \"System[Reference]\",\n P_Job: \"System[Reference]\",\n P_Candidate: \"System[Reference]\",\n P_Resume: \"System[Reference]\",\n P_RegistrationDate: \"System[DateTime]\",\n P_RegisteredBy: \"User\",\n P_UpdateDate: \"System[DateTime]\",\n P_UpdatedBy: \"User\",\n P_Phase: \"Option\",\n P_PhaseDate: \"DateTime\",\n P_PhaseMemo: \"MultilineText\",\n P_Close: \"Option\",\n P_CloseReason: \"Option\",\n P_ExpectedSalesAmount: \"Number\",\n P_ExpectedClosingDate: \"Date\",\n} as const satisfies FieldCatalog;\n\n// Required on create per docs/reference (resources/process.md「新規必須」列): P_Owner と関連 5 項目\n// (P_Client / P_Recruiter / P_Job / P_Candidate / P_Resume)。P_Id は System[Id]=lib 供給で除外。\n// LV-5 は reference で確定。\nconst REQUIRED_ON_CREATE = [\n \"P_Owner\",\n \"P_Client\",\n \"P_Recruiter\",\n \"P_Job\",\n \"P_Candidate\",\n \"P_Resume\",\n] as const satisfies readonly (keyof typeof FIELDS)[];\n\n/** A decoded Process (a Candidate's progress through a Job): known `P_` fields, each\n * requested field `value | null`. */\nexport type Process = ReadRecord<typeof FIELDS>;\nexport type ProcessPage = ResourcePage<typeof FIELDS>;\nexport type ProcessSearchQuery = SearchQuery<typeof FIELDS>;\n\n/** Fields for `create`: `P_Owner` required; `P_Id` / system timestamps are not settable. */\nexport type ProcessCreateInput = CreateInput<\n typeof FIELDS,\n (typeof REQUIRED_ON_CREATE)[number]\n>;\n/** Fields for `update`: all optional (`null` omits, `\"\"` clears a text field). */\nexport type ProcessUpdateInput = UpdateInput<typeof FIELDS>;\n/** The Process accessor; `C` is the declared custom-field catalog merged on (ADR-0023). */\nexport type ProcessResource<C extends FieldCatalog = EmptyCatalog> = Resource<\n typeof FIELDS & C,\n (typeof REQUIRED_ON_CREATE)[number]\n>;\n\nexport const createProcessResource = <C extends FieldCatalog = EmptyCatalog>(\n deps: { requester: Requester; host: string; partition: number },\n custom?: C,\n): ProcessResource<C> => {\n // Custom U_/A_ aliases never collide with P_, so the merge is exactly `typeof FIELDS & C`;\n // the cast just names that intersection (defineFields already validated aliases — ADR-0023 D7).\n const fields = { ...FIELDS, ...custom } as typeof FIELDS & C;\n return createResource(\n {\n name: \"Process\",\n path: \"process\",\n prefix: \"Process\",\n fields,\n requiredOnCreate: REQUIRED_ON_CREATE,\n },\n deps,\n );\n};\n","// Resume accessor (ADR-0004/0005/0011/0019): Read (search / searchAll / get) + Write\n// (create / update) over the generic resource factory. A Resume belongs to a Candidate;\n// P_Candidate is System[Reference] (Write = the Person id).\n//\n// P_DateOfBirth is the Age Data Type — catalogued as \"Age\". Its wire value is the\n// birthdate (`yyyy/mm/dd`, same as Date); PORTERS derives the displayed age in its UI.\n// Display-only Reference fields (P_Mail, P_*Reference — they mirror a Person value and are\n// not writable) are intentionally left out of the catalog: scalar mirrors read through as\n// raw strings. Multi-select Option read returns every selected alias as `string[]` (ADR-0017).\n// Image-typed custom fields (U_) are future work. The static Resume / input types derive from the catalog (ADR-0019).\n\nimport type { Requester } from \"../http/requester\";\nimport {\n createResource,\n type CreateInput,\n type EmptyCatalog,\n type FieldCatalog,\n type ReadRecord,\n type Resource,\n type ResourcePage,\n type SearchQuery,\n type UpdateInput,\n} from \"./resource\";\n\nconst FIELDS = {\n P_Id: \"System[Id]\",\n P_Owner: \"User\",\n P_Candidate: \"System[Reference]\",\n P_RegistrationDate: \"System[DateTime]\",\n P_RegisteredBy: \"User\",\n P_UpdateDate: \"System[DateTime]\",\n P_UpdatedBy: \"User\",\n P_Phase: \"Option\",\n P_PhaseDate: \"DateTime\",\n P_PhaseMemo: \"MultilineText\",\n P_Name: \"SinglelineText\",\n P_RegisterChannel: \"Option\",\n P_Memo: \"MultilineText\",\n P_CurrentStatus: \"Option\",\n P_Education: \"MultilineText\",\n P_CarrierSummary: \"MultilineText\",\n P_CurrentSalary: \"Number\",\n P_ExperiencedJobCategory: \"Option\",\n P_ExperiencedIndustry: \"Option\",\n P_ChangeJobsCount: \"Number\",\n P_Gender: \"Option\",\n P_DateOfBirth: \"Age\",\n P_ExpectEmploymentType: \"Option\",\n P_ExpectArea: \"Option\",\n P_ExpectJobCategory: \"Option\",\n P_ExpectIndustry: \"Option\",\n P_ExpectCondition: \"MultilineText\",\n P_ExpectSalary: \"Number\",\n P_DesiredHourlyRate: \"Number\",\n P_HourlyRate: \"Number\",\n} as const satisfies FieldCatalog;\n\n// Required on create per docs/reference (resources/resume.md「新規必須」列): P_Owner / P_Candidate\n// (P_Id は System[Id]=lib 供給のため除外)。LV-5 は reference で確定。\nconst REQUIRED_ON_CREATE = [\n \"P_Owner\",\n \"P_Candidate\",\n] as const satisfies readonly (keyof typeof FIELDS)[];\n\n/** A decoded Resume (a Candidate's CV / profile): known `P_` fields, each requested field\n * `value | null`. */\nexport type Resume = ReadRecord<typeof FIELDS>;\nexport type ResumePage = ResourcePage<typeof FIELDS>;\nexport type ResumeSearchQuery = SearchQuery<typeof FIELDS>;\n\n/** Fields for `create`: `P_Owner` required; `P_Id` / system timestamps are not settable. */\nexport type ResumeCreateInput = CreateInput<\n typeof FIELDS,\n (typeof REQUIRED_ON_CREATE)[number]\n>;\n/** Fields for `update`: all optional (`null` omits, `\"\"` clears a text field). */\nexport type ResumeUpdateInput = UpdateInput<typeof FIELDS>;\n/** The Resume accessor; `C` is the declared custom-field catalog merged on (ADR-0023). */\nexport type ResumeResource<C extends FieldCatalog = EmptyCatalog> = Resource<\n typeof FIELDS & C,\n (typeof REQUIRED_ON_CREATE)[number]\n>;\n\nexport const createResumeResource = <C extends FieldCatalog = EmptyCatalog>(\n deps: { requester: Requester; host: string; partition: number },\n custom?: C,\n): ResumeResource<C> => {\n // Custom U_/A_ aliases never collide with P_, so the merge is exactly `typeof FIELDS & C`;\n // the cast just names that intersection (defineFields already validated aliases — ADR-0023 D7).\n const fields = { ...FIELDS, ...custom } as typeof FIELDS & C;\n return createResource(\n {\n name: \"Resume\",\n path: \"resume\",\n prefix: \"Resume\",\n fields,\n requiredOnCreate: REQUIRED_ON_CREATE,\n },\n deps,\n );\n};\n","// Attachment accessor (ADR-0018, bespoke): Read (search / get) + Write (create / update)\n// for file attachments. Attachment is unlike the other resources — no alias prefix, fixed\n// short field names (Id / Resource / ResourceId / ContentType / FileName / Content), and\n// `Content` is the Base64 file body (up to 10MB). It does not fit the generic factory but\n// reuses the requester, parsers, and `firstWriteResultId`. Turn raw bytes into the Base64\n// `content` with `util/base64`.\n\nimport { PortersConfigError } from \"../errors\";\nimport type { Requester } from \"../http/requester\";\nimport { encodeField } from \"../xml/encode\";\nimport { parseResourcePage } from \"../xml/parser\";\nimport { asString } from \"../xml/raw\";\nimport { buildWriteUrl, firstWriteResultId } from \"./resource\";\n\n// A 10MB file is ~13.98M Base64 chars; cap the encoded Content length before send\n// (fail-safe — the ~15000-char request guard is bypassed for uploads). docs/reference.\nconst MAX_CONTENT_CHARS = 14_000_000;\n\nconst ALL_FIELDS = [\n \"Id\",\n \"Resource\",\n \"ResourceId\",\n \"ContentType\",\n \"FileName\",\n \"Content\",\n];\n\n// Default for search() when `field` is omitted (ADR-0020): metadata only — exclude the (large,\n// up to ~14MB Base64) `Content` so listing attachments doesn't download every file body. Fetch\n// `Content` explicitly via `field` or per-record via get(). Mirrors PORTERS' Image default\n// (FileName only). `field: []` still opts into the API-native primary-key-only response.\nconst DEFAULT_FIELDS = [\n \"Id\",\n \"Resource\",\n \"ResourceId\",\n \"ContentType\",\n \"FileName\",\n];\n\n/** A decoded Attachment. A field is `null` unless it was returned (see `field`). */\nexport type Attachment = {\n id: number | null;\n /** Related resource type code (see the PORTERS Resource List). */\n resource: number | null;\n /** Related record id. */\n resourceId: number | null;\n contentType: string | null;\n fileName: string | null;\n /** Base64 file body. */\n content: string | null;\n};\n\nexport type AttachmentPage = {\n items: Attachment[];\n total: number;\n count: number;\n start: number;\n};\n\nexport type AttachmentSearchQuery = {\n /**\n * Output fields. **Omit** to fetch metadata by default (Id / Resource / ResourceId /\n * ContentType / FileName) — the large Base64 `Content` is excluded so listing doesn't download\n * every file body (ADR-0020); request `[\"Content\", …]` or use `get()` for the body. Pass `[]`\n * for the API-native primary-key-only response. A non-empty list is sent verbatim.\n */\n field?: string[];\n condition?: Record<string, string>;\n count?: number;\n start?: number;\n};\n\n/** Fields for creating an Attachment. `content` is the Base64 file body. */\nexport type AttachmentCreate = {\n resource: number;\n resourceId: number;\n contentType: string;\n fileName: string;\n content: string;\n};\n\n/** Fields for updating an Attachment. `Resource` / `ResourceId` are not updatable. */\nexport type AttachmentUpdate = {\n contentType?: string;\n fileName?: string;\n content?: string;\n};\n\nexport type AttachmentResource = {\n search(query?: AttachmentSearchQuery): Promise<AttachmentPage>;\n get(id: number): Promise<Attachment | undefined>;\n /** Create an Attachment; resolves to the newly assigned id. */\n create(input: AttachmentCreate): Promise<number>;\n /** Update an Attachment by id; resolves to that id. */\n update(id: number, input: AttachmentUpdate): Promise<number>;\n};\n\n// Bespoke Read URL (ADR-0018): Attachment has no alias prefix and no Data-Type catalog, so it keeps\n// the loose `condition` (`{ \"Id:eq\": \"123\" }`) and stays off the typed data-resource builder\n// (ADR-0038). itemstate/order/keywords do not apply to Attachment.\nconst buildAttachmentReadUrl = (\n host: string,\n partition: number,\n q: AttachmentSearchQuery,\n): string => {\n const p = new URLSearchParams();\n p.set(\"partition\", String(partition));\n if (q.field && q.field.length > 0) p.set(\"field\", q.field.join(\",\"));\n if (q.condition) {\n const conds = Object.entries(q.condition).map(([k, v]) => `${k}=${v}`);\n if (conds.length > 0) p.set(\"condition\", conds.join(\",\"));\n }\n if (q.count !== undefined) p.set(\"count\", String(q.count));\n if (q.start !== undefined) p.set(\"start\", String(q.start));\n return `https://${host}/v1/attachment?${p.toString()}`;\n};\n\nconst numOrNull = (v: unknown): number | null => {\n const s = asString(v);\n return s === undefined ? null : Number(s);\n};\n\nconst decodeAttachment = (item: Record<string, unknown>): Attachment => ({\n id: numOrNull(item.Id),\n resource: numOrNull(item.Resource),\n resourceId: numOrNull(item.ResourceId),\n contentType: asString(item.ContentType) ?? null,\n fileName: asString(item.FileName) ?? null,\n content: asString(item.Content) ?? null,\n});\n\n// Bare `<Tag>value</Tag>` (Attachment has no alias prefix). encodeField escapes the value.\nconst tag = (name: string, value: string | number): string =>\n `<${name}>${encodeField(\"SinglelineText\", String(value))}</${name}>`;\n\n// Reject an over-10MB file before send (the request size guard is bypassed for uploads).\nconst guardContent = (content: string | undefined): void => {\n if (content !== undefined && content.length > MAX_CONTENT_CHARS) {\n throw new PortersConfigError(\n `attachment content is ${content.length} characters, over the ~10MB file limit`,\n { category: \"config\", hint: \"Attachment files must be 10MB or less.\" },\n );\n }\n};\n\nexport const createAttachmentResource = (deps: {\n requester: Requester;\n host: string;\n partition: number;\n}): AttachmentResource => {\n // `field` omitted -> metadata default (no Content); `[]` -> API-native primary key only;\n // a provided list is sent verbatim (ADR-0020).\n const search = (query: AttachmentSearchQuery = {}): Promise<AttachmentPage> =>\n deps.requester.request(\n {\n method: \"GET\",\n url: buildAttachmentReadUrl(deps.host, deps.partition, {\n ...query,\n field: query.field ?? DEFAULT_FIELDS,\n }),\n headers: {},\n },\n (body) => {\n const page = parseResourcePage(body);\n return {\n items: page.items.map(decodeAttachment),\n total: page.total,\n count: page.count,\n start: page.start,\n };\n },\n );\n\n // VERIFY(live): Attachment has no alias prefix; the `Id:eq` condition and requesting all\n // fields (incl. Content) are taken from the field list, not a live contract.\n // See docs/live-verification.md (LV-3, LV-4).\n const get = async (id: number): Promise<Attachment | undefined> => {\n const page = await search({\n field: ALL_FIELDS,\n condition: { \"Id:eq\": String(id) },\n count: 1,\n });\n return page.items[0];\n };\n\n const write = (inner: string, idempotent: boolean): Promise<number> =>\n deps.requester.request(\n {\n method: \"POST\",\n url: buildWriteUrl(deps.host, deps.partition, \"attachment\"),\n headers: {},\n body: `<Attachment><Item>${inner}</Item></Attachment>`,\n },\n (body) => firstWriteResultId(body, \"attachment\", \"Attachment\"),\n { write: true, idempotent, unboundedBody: true },\n );\n\n // create forces Id=-1 (non-idempotent). All fields are required.\n const create = (input: AttachmentCreate): Promise<number> => {\n guardContent(input.content);\n const inner =\n tag(\"Id\", -1) +\n tag(\"Resource\", input.resource) +\n tag(\"ResourceId\", input.resourceId) +\n tag(\"ContentType\", input.contentType) +\n tag(\"FileName\", input.fileName) +\n tag(\"Content\", input.content);\n return write(inner, false);\n };\n\n // update targets the id (idempotent). Resource / ResourceId can't change; only the\n // provided fields are sent.\n const update = (id: number, input: AttachmentUpdate): Promise<number> => {\n guardContent(input.content);\n let inner = tag(\"Id\", id);\n if (input.contentType !== undefined) {\n inner += tag(\"ContentType\", input.contentType);\n }\n if (input.fileName !== undefined) inner += tag(\"FileName\", input.fileName);\n if (input.content !== undefined) inner += tag(\"Content\", input.content);\n return write(inner, true);\n };\n\n return { search, get, create, update };\n};\n","// Partition master accessor (read-only — ADR-0021/0022). Partition Read discovers the\n// partitions an App can access. It takes neither `partition` nor `field`/`condition`, only\n// `request_type`: 1 = the accessible-partition list (works under code_direct; the default),\n// 0 = the login partition (only under the browser `code` grant — 403s under code_direct, so\n// it is not exposed; ADR-0022 D3b). No `get(id)`: the API has no id/condition filter.\n\nimport type { Requester } from \"../http/requester\";\nimport {\n decoderFor,\n paginate,\n runRead,\n type FieldCatalog,\n type ReadRecord,\n type ResourcePage,\n} from \"./read-core\";\n\nconst FIELDS = {\n P_Id: \"System[Id]\",\n P_Name: \"SinglelineText\",\n P_CompanyId: \"SinglelineText\",\n} as const satisfies FieldCatalog;\n\n/** A decoded Partition (a PORTERS contract company / Company DB). */\nexport type Partition = ReadRecord<typeof FIELDS>;\nexport type PartitionPage = ResourcePage<typeof FIELDS>;\n\n/** Partition Read query. `requestType` 1 = partitions this App can access (default). */\nexport type PartitionSearchQuery = {\n /** 1 = accessible partitions (default). 0 = login partition (browser `code` grant only). */\n requestType?: 0 | 1;\n count?: number;\n start?: number;\n};\n\nexport type PartitionResource = {\n search(query?: PartitionSearchQuery): Promise<PartitionPage>;\n /** Auto-paginating search: yields every accessible partition. */\n searchAll(\n query?: Omit<PartitionSearchQuery, \"count\" | \"start\">,\n ): AsyncIterable<Partition>;\n};\n\n// VERIFY(live): Partition Read taking no `partition` param is doc-only (every other read\n// requires it). See docs/live-verification.md (LV-8).\nconst buildUrl = (host: string, q: PartitionSearchQuery): string => {\n const p = new URLSearchParams();\n p.set(\"request_type\", String(q.requestType ?? 1));\n if (q.count !== undefined) p.set(\"count\", String(q.count));\n if (q.start !== undefined) p.set(\"start\", String(q.start));\n return `https://${host}/v1/partition?${p.toString()}`;\n};\n\nexport const createPartitionResource = (deps: {\n requester: Requester;\n host: string;\n}): PartitionResource => {\n const decode = decoderFor(FIELDS);\n const search = (query: PartitionSearchQuery = {}): Promise<PartitionPage> =>\n runRead(deps.requester, buildUrl(deps.host, query), decode);\n const searchAll = (\n query: Omit<PartitionSearchQuery, \"count\" | \"start\"> = {},\n ): AsyncIterable<Partition> =>\n paginate((count, start) => search({ ...query, count, start }));\n return { search, searchAll };\n};\n","// User master accessor (read-only — ADR-0021/0022). User Read requires `partition` and\n// `request_type` (1 = all users; 0 = the current user — under code_direct this is the App's\n// own user, i.e. self-identification). `field` defaults to the 4 readable core fields, which\n// is exactly this catalog, so we omit it unless the caller narrows. No `condition`/`get(id)`:\n// the API has no id filter. Extended HR fields (department/telephone/dates/…) are deferred —\n// their read availability/decode shape is unconfirmed (see docs/live-verification.md).\n\nimport type { Requester } from \"../http/requester\";\nimport {\n decoderFor,\n paginate,\n runRead,\n type FieldCatalog,\n type ReadRecord,\n type ResourcePage,\n} from \"./read-core\";\n\nconst FIELDS = {\n P_Id: \"System[Id]\",\n P_Type: \"Number\",\n P_Name: \"SinglelineText\",\n P_Mail: \"Mail\",\n} as const satisfies FieldCatalog;\n\n/** A decoded User (PORTERS operator). `P_Type`: 0 = standard user, 1 = system admin. */\nexport type User = ReadRecord<typeof FIELDS>;\nexport type UserPage = ResourcePage<typeof FIELDS>;\n\n/** User Read query. `requestType` 1 = all users (default); `userType` -1 = any (default). */\nexport type UserSearchQuery = {\n /** 1 = all users (default). 0 = the current user (code_direct → the App's own user). */\n requestType?: 0 | 1;\n /** -1 = any (default), 0 = system admins, 1 = standard users. */\n userType?: -1 | 0 | 1;\n /** Output fields (prefixed aliases). Omit to get the 4 core fields (this catalog). */\n field?: string[];\n count?: number;\n start?: number;\n};\n\nexport type UserResource = {\n search(query?: UserSearchQuery): Promise<UserPage>;\n /** Auto-paginating search: yields every matching user. */\n searchAll(\n query?: Omit<UserSearchQuery, \"count\" | \"start\">,\n ): AsyncIterable<User>;\n /**\n * The current API user (`request_type=0`). Under the library's default `code_direct` auth\n * this resolves to the App's own user (username = app name) — useful for self-identification.\n * Under the browser `code` grant it is the logged-in user. Resolves `undefined` if none.\n */\n current(): Promise<User | undefined>;\n};\n\nconst buildUrl = (\n host: string,\n partition: number,\n q: UserSearchQuery,\n): string => {\n const p = new URLSearchParams();\n p.set(\"partition\", String(partition));\n p.set(\"request_type\", String(q.requestType ?? 1));\n p.set(\"user_type\", String(q.userType ?? -1));\n if (q.field && q.field.length > 0) p.set(\"field\", q.field.join(\",\"));\n if (q.count !== undefined) p.set(\"count\", String(q.count));\n if (q.start !== undefined) p.set(\"start\", String(q.start));\n return `https://${host}/v1/user?${p.toString()}`;\n};\n\nexport const createUserResource = (deps: {\n requester: Requester;\n host: string;\n partition: number;\n}): UserResource => {\n const decode = decoderFor(FIELDS);\n const search = (query: UserSearchQuery = {}): Promise<UserPage> =>\n runRead(deps.requester, buildUrl(deps.host, deps.partition, query), decode);\n const searchAll = (\n query: Omit<UserSearchQuery, \"count\" | \"start\"> = {},\n ): AsyncIterable<User> =>\n paginate((count, start) => search({ ...query, count, start }));\n // VERIFY(live): code_direct + request_type=0 returning the App's own user is doc-only.\n // See docs/live-verification.md (LV-7).\n const current = async (): Promise<User | undefined> =>\n (await search({ requestType: 0, count: 1 })).items[0];\n return { search, searchAll, current };\n};\n","// Field master accessor (read-only — ADR-0021/0022). Field Read introspects a resource's\n// field catalog (standard `P_` + tenant `U_`/`A_`). It requires `partition` and `resource`\n// (a resource-type Value code), plus optional `active`. No `field`/`condition`/`get(id)`.\n// `P_ReferTo` is a nested alias (the option group for Option-type fields, the parent field for\n// Reference-type) — decoded like an Option value to the referenced alias(es) (ADR-0022).\n\nimport type { Requester } from \"../http/requester\";\nimport {\n decoderFor,\n paginate,\n runRead,\n type FieldCatalog,\n type ReadRecord,\n type ResourcePage,\n} from \"./read-core\";\n\n// Resource-type selector -> Value code (docs/reference resources-list). Master/Phase/Attachment\n// have no Value, so only the R/W data resources are selectable here.\nconst RESOURCE_VALUE = {\n candidate: 1,\n job: 3,\n client: 5,\n recruiter: 9,\n sales: 11,\n contract: 13,\n resume: 17,\n activity: 19,\n opportunity: 25,\n contact: 27,\n} as const;\n\n/** A resource whose field catalog can be read (Field Read `resource` selector). */\nexport type ResourceType = keyof typeof RESOURCE_VALUE;\n\nconst FIELDS = {\n P_Id: \"System[Id]\",\n P_Name: \"SinglelineText\",\n P_Alias: \"SinglelineText\",\n P_Type: \"Number\",\n P_Required: \"Number\",\n P_Max: \"Number\",\n P_Min: \"Number\",\n P_DecimalFraction: \"Number\",\n // Nested alias(es): the referenced option group / parent field. Reuse Option decode -> the\n // referenced alias(es) as string[] (usually one); empty -> null (ADR-0017/0022).\n // VERIFY(live): Reference-type P_ReferTo nesting is doc-only. See docs/live-verification.md (LV-6).\n P_ReferTo: \"Option\",\n P_ResourceType: \"Number\",\n} as const satisfies FieldCatalog;\n\n/** A decoded Field definition. `P_Required`: 0 = normal, 1 = required. */\nexport type Field = ReadRecord<typeof FIELDS>;\nexport type FieldPage = ResourcePage<typeof FIELDS>;\n\n/** Field Read query. `resource` selects which resource's fields to read (required). */\nexport type FieldSearchQuery = {\n resource: ResourceType;\n /** -1 = all (default), 0 = unused only, 1 = in-use only. */\n active?: -1 | 0 | 1;\n count?: number;\n start?: number;\n};\n\nexport type FieldResource = {\n search(query: FieldSearchQuery): Promise<FieldPage>;\n /** Auto-paginating search: yields every field of the resource. */\n searchAll(\n query: Omit<FieldSearchQuery, \"count\" | \"start\">,\n ): AsyncIterable<Field>;\n};\n\nconst buildUrl = (\n host: string,\n partition: number,\n q: FieldSearchQuery,\n): string => {\n const p = new URLSearchParams();\n p.set(\"partition\", String(partition));\n p.set(\"resource\", String(RESOURCE_VALUE[q.resource]));\n p.set(\"active\", String(q.active ?? -1));\n if (q.count !== undefined) p.set(\"count\", String(q.count));\n if (q.start !== undefined) p.set(\"start\", String(q.start));\n return `https://${host}/v1/field?${p.toString()}`;\n};\n\nexport const createFieldResource = (deps: {\n requester: Requester;\n host: string;\n partition: number;\n}): FieldResource => {\n const decode = decoderFor(FIELDS);\n const search = (query: FieldSearchQuery): Promise<FieldPage> =>\n runRead(deps.requester, buildUrl(deps.host, deps.partition, query), decode);\n const searchAll = (\n query: Omit<FieldSearchQuery, \"count\" | \"start\">,\n ): AsyncIterable<Field> =>\n paginate((count, start) => search({ ...query, count, start }));\n return { search, searchAll };\n};\n","// Option master accessor (read-only — ADR-0021/0022). Option Read returns a tenant's choice\n// master as a recursive tree: each <Item> nests child <Item>s under <Items>. We flatten the\n// tree depth-first into one array — every node present, parent linkage kept via `P_ParentId`\n// and ordering via `P_Order` (ADR-0021 軸3, case 3a). It requires `partition` and takes\n// `alias`/`level`/`enabled`/`count` — no `start` (no offset paging → no searchAll), no\n// `field`/`condition`/`get(id)`.\n\nimport type { Requester } from \"../http/requester\";\nimport { parseResourcePage, type RawItem } from \"../xml/parser\";\nimport { asArray, asRecord } from \"../xml/raw\";\nimport { decoderFor, type FieldCatalog, type ReadRecord } from \"./read-core\";\n\nconst FIELDS = {\n P_Id: \"System[Id]\",\n P_Name: \"SinglelineText\",\n P_Alias: \"SinglelineText\",\n P_ParentId: \"Number\",\n P_Type: \"Number\",\n P_Order: \"Number\",\n} as const satisfies FieldCatalog;\n\n/** A decoded Option (one choice). `P_ParentId` links to the parent; `P_Type` 0 = normal, 1–11 = a phase kind. */\nexport type Option = ReadRecord<typeof FIELDS>;\n\n/** Option Read query. `alias` selects a subtree root; `level` its depth (-1 all). */\nexport type OptionSearchQuery = {\n /** Root alias of the subtree to read (e.g. `Option.P_Gender`). Omit for all. */\n alias?: string;\n /** Depth: -1 all (default), 0 = siblings of `alias`, 1+ = descendants. */\n level?: number;\n /** -1 = all (default), 0 = unused only, 1 = in-use only. */\n enabled?: -1 | 0 | 1;\n count?: number;\n};\n\nexport type OptionResource = {\n /** Read options, flattened depth-first (all nodes; tree is reconstructable via `P_ParentId`). */\n search(query?: OptionSearchQuery): Promise<Option[]>;\n};\n\nconst buildUrl = (\n host: string,\n partition: number,\n q: OptionSearchQuery,\n): string => {\n const p = new URLSearchParams();\n p.set(\"partition\", String(partition));\n if (q.alias !== undefined) p.set(\"alias\", q.alias);\n if (q.level !== undefined) p.set(\"level\", String(q.level));\n if (q.enabled !== undefined) p.set(\"enabled\", String(q.enabled));\n if (q.count !== undefined) p.set(\"count\", String(q.count));\n return `https://${host}/v1/option?${p.toString()}`;\n};\n\n// Decode one node's own fields, dropping the nested `Items` collection (handled by the walk).\nconst withoutItems = (raw: RawItem): RawItem =>\n Object.fromEntries(Object.entries(raw).filter(([k]) => k !== \"Items\"));\n\nexport const createOptionResource = (deps: {\n requester: Requester;\n host: string;\n partition: number;\n}): OptionResource => {\n const decode = decoderFor(FIELDS);\n // Depth-first flatten: push each node, then recurse into its <Items><Item>… children.\n const flatten = (items: RawItem[], out: Option[]): void => {\n for (const raw of items) {\n out.push(decode(withoutItems(raw)));\n const children = asArray(asRecord(raw.Items)?.Item).map(\n (it) => asRecord(it) ?? {},\n );\n flatten(children, out);\n }\n };\n const search = (query: OptionSearchQuery = {}): Promise<Option[]> =>\n deps.requester.request(\n {\n method: \"GET\",\n url: buildUrl(deps.host, deps.partition, query),\n headers: {},\n },\n (body) => {\n const out: Option[] = [];\n flatten(parseResourcePage(body).items, out);\n return out;\n },\n );\n return { search };\n};\n","import { createAuthApi, createDefaultTokenProvider } from \"./auth\";\nimport type {\n AuthApi,\n AuthProviderControls,\n TokenProvider,\n TokenStore,\n} from \"./auth\";\nimport {\n createFetchTransport,\n createRequester,\n createThrottle,\n expoBackoff,\n} from \"./http\";\nimport type { Transport } from \"./http\";\nimport {\n createAttachmentResource,\n createCandidateResource,\n createClientResource,\n createFieldResource,\n createJobResource,\n createOptionResource,\n createPartitionResource,\n createProcessResource,\n createResumeResource,\n createUserResource,\n} from \"./resources\";\nimport type {\n AttachmentResource,\n CandidateResource,\n ClientResource,\n FieldResource,\n JobResource,\n OptionResource,\n PartitionResource,\n ProcessResource,\n ResumeResource,\n UserResource,\n} from \"./resources\";\nimport type { CustomFor, DeclaredCatalogs, DefinedFields } from \"./fields\";\nimport type { EmptyCatalog } from \"./resources/read-core\";\nimport type { PartitionId, Scope } from \"./types\";\n\n/** Options for constructing a {@link PortersClient}. `C` is inferred from `fields` (ADR-0023). */\nexport type PortersClientOptions<C extends DeclaredCatalogs = EmptyCatalog> = {\n /**\n * API host. Required and supplied via `PORTERS_HOST` — never hard-code it.\n * (A representative value lives in docs/reference.)\n */\n host: string;\n appId?: string;\n appSecret?: string;\n scopes?: Scope[];\n /**\n * Default partition (Company DB) for every call. For multi-tenant routing, bind a partition\n * per call with {@link PortersClient.tenant} (ADR-0040 / F-3); for a fully separated per-partition\n * token, construct a dedicated client per tenant instead (ADR-0008 案3).\n */\n partition?: PartitionId;\n /** Custom auth strategy; defaults to the transparent code_direct strategy. */\n auth?: TokenProvider;\n /** Token persistence; defaults to in-memory. */\n tokenStore?: TokenStore;\n /** Injectable HTTP transport; defaults to a fetch-based transport. */\n transport?: Transport;\n /**\n * Tenant custom field declarations from {@link defineFields} (ADR-0023). Each resource's\n * declared `U_`/`A_` fields are merged onto its static catalog, so they decode/encode by\n * their declared Data Type and appear typed on reads / writes. Omit for standard `P_` only.\n */\n fields?: DefinedFields<C>;\n};\n\n/**\n * The partition-bound resource accessors returned by {@link PortersClient.tenant} (ADR-0040 / F-3).\n * Every accessor here routes to the bound tenant's partition. `auth` (App-level), the `partition`\n * master (discovery — partition-less), and `tenant` itself (no nesting) are deliberately absent.\n */\nexport type TenantScope<C extends DeclaredCatalogs = EmptyCatalog> = {\n readonly candidate: CandidateResource<CustomFor<C, \"candidate\">>;\n readonly job: JobResource<CustomFor<C, \"job\">>;\n readonly client: ClientResource<CustomFor<C, \"client\">>;\n readonly process: ProcessResource<CustomFor<C, \"process\">>;\n readonly resume: ResumeResource<CustomFor<C, \"resume\">>;\n readonly attachment: AttachmentResource;\n readonly user: UserResource;\n readonly field: FieldResource;\n readonly option: OptionResource;\n};\n\n/**\n * Entry point of the library. Wires the default transport / auth / throttle /\n * requester and exposes namespaced resource accessors such as `candidate`\n * (ADR-0005).\n */\nexport class PortersClient<C extends DeclaredCatalogs = EmptyCatalog> {\n readonly candidate: CandidateResource<CustomFor<C, \"candidate\">>;\n readonly job: JobResource<CustomFor<C, \"job\">>;\n readonly client: ClientResource<CustomFor<C, \"client\">>;\n readonly process: ProcessResource<CustomFor<C, \"process\">>;\n readonly resume: ResumeResource<CustomFor<C, \"resume\">>;\n readonly attachment: AttachmentResource;\n /** OAuth surface: initial browser grant, token warm-up/inspection, local revoke (ADR-0007/0034). */\n readonly auth: AuthApi;\n /** Master Read: accessible partitions (ADR-0021/0022). */\n readonly partition: PartitionResource;\n /** Master Read: users, plus `current()` self-identification (ADR-0021/0022). */\n readonly user: UserResource;\n /** Master Read: a resource's field catalog (ADR-0021/0022). */\n readonly field: FieldResource;\n /** Master Read: a tenant's choice (option) master (ADR-0021/0022). */\n readonly option: OptionResource;\n /**\n * Bind a tenant's partition (Company DB) once and route every call through it — the multi-tenant\n * scope (ADR-0008 案2 / renamed in ADR-0021 / implemented in ADR-0040 F-3).\n * `porters.tenant(123).candidate.search(...)` sends `partition=123` without repeating it, overriding\n * the client-default `partition`. Returns the partition-bound accessors (data + attachment + master\n * User/Field/Option); `auth` (App-level), the `partition` master (discovery — takes no partition),\n * and `tenant` itself (no nesting) are intentionally omitted. For a fully separated per-partition\n * token, construct a dedicated {@link PortersClient} per tenant instead (ADR-0008 案3).\n */\n readonly tenant: (id: PartitionId) => TenantScope<C>;\n readonly #host: string;\n\n constructor(options: PortersClientOptions<C>) {\n const transport = options.transport ?? createFetchTransport();\n // Custom strategy (案3) takes over token supply; otherwise the default transparent\n // provider also exposes cache/clear controls for the auth surface (ADR-0034 SD-7/SD-8).\n let auth: TokenProvider;\n let controls: AuthProviderControls | undefined = undefined;\n if (options.auth) {\n auth = options.auth;\n } else {\n const provider = createDefaultTokenProvider({\n host: options.host,\n appId: options.appId ?? \"\",\n appSecret: options.appSecret ?? \"\",\n transport,\n tokenStore: options.tokenStore,\n });\n auth = provider;\n controls = provider;\n }\n this.auth = createAuthApi({\n host: options.host,\n appId: options.appId,\n appSecret: options.appSecret,\n scopes: options.scopes,\n transport,\n provider: auth,\n controls,\n });\n const requester = createRequester({\n transport,\n auth,\n throttle: createThrottle(),\n backoff: expoBackoff(),\n });\n this.#host = options.host;\n // The per-resource custom catalog declared via defineFields (or {} when none). Branded\n // = already validated (ADR-0023 D4), so the factory merges it without re-checking.\n const customFor = <K extends keyof DeclaredCatalogs>(\n key: K,\n ): CustomFor<C, K> => (options.fields?.[key] ?? {}) as CustomFor<C, K>;\n // Build the partition-bound accessor bundle for a given partition. The root client uses the\n // default partition; `tenant(id)` re-binds it (ADR-0040 / F-3) by re-running the same factories\n // with `partition` overridden — resources are already `deps.partition`-driven, so the factories\n // need no change. Partition Read is App-level (no partition) and built once below, not here.\n const buildScope = (partition: number): TenantScope<C> => {\n const deps = { requester, host: options.host, partition };\n return {\n candidate: createCandidateResource(deps, customFor(\"candidate\")),\n job: createJobResource(deps, customFor(\"job\")),\n client: createClientResource(deps, customFor(\"client\")),\n process: createProcessResource(deps, customFor(\"process\")),\n resume: createResumeResource(deps, customFor(\"resume\")),\n attachment: createAttachmentResource(deps),\n user: createUserResource(deps),\n field: createFieldResource(deps),\n option: createOptionResource(deps),\n };\n };\n this.tenant = buildScope;\n const root = buildScope(options.partition ?? 0);\n this.candidate = root.candidate;\n this.job = root.job;\n this.client = root.client;\n this.process = root.process;\n this.resume = root.resume;\n this.attachment = root.attachment;\n this.user = root.user;\n this.field = root.field;\n this.option = root.option;\n // Partition Read takes no `partition` param (it discovers them); App-level, not tenant-bound.\n this.partition = createPartitionResource({ requester, host: options.host });\n }\n\n /** The configured API host. */\n get host(): string {\n return this.#host;\n }\n}\n","// Custom field declaration DSL (ADR-0023, grounding ADR-0004 案H / ADR-0005 SD-2).\n// `defineFields` is the single validation boundary: a typed builder declares each\n// tenant custom field's Data Type per data resource, validation runs synchronously,\n// and the result is branded so PortersClient trusts it without re-validating. Standard\n// `P_` fields come from the static catalogs (ADR-0019); this only covers custom U_/A_.\n\nimport { PortersConfigError } from \"../errors\";\nimport type { EmptyCatalog } from \"../resources/read-core\";\nimport type { DataType } from \"../xml/decode\";\n\n/** One custom field's declared Data Type — the builder's return value (ADR-0023 D2). */\nexport type FieldDef<D extends DataType> = { readonly dataType: D };\n\n// Data Types a custom U_/A_ field may declare (ADR-0023 D3): the value-shaped types. The\n// System family (System[Id]/[DateTime]/[Reference]) is system-managed = standard territory,\n// so it is not offered; Image / Link are not modelled in DataType yet (future work).\nexport type CustomDataType =\n | \"Number\"\n | \"SinglelineText\"\n | \"MultilineText\"\n | \"Mail\"\n | \"Telephone\"\n | \"URL\"\n | \"Date\"\n | \"DateTime\"\n | \"Age\"\n | \"Option\"\n | \"User\";\n\n/** Builder passed to each resource declaration: one method per declarable Data Type. */\nexport type FieldBuilder = {\n number(): FieldDef<\"Number\">;\n singlelineText(): FieldDef<\"SinglelineText\">;\n multilineText(): FieldDef<\"MultilineText\">;\n mail(): FieldDef<\"Mail\">;\n telephone(): FieldDef<\"Telephone\">;\n url(): FieldDef<\"URL\">;\n date(): FieldDef<\"Date\">;\n dateTime(): FieldDef<\"DateTime\">;\n age(): FieldDef<\"Age\">;\n option(): FieldDef<\"Option\">;\n user(): FieldDef<\"User\">;\n};\n\n/** Data resources that accept custom fields (ADR-0023 D6). Master / Attachment are excluded. */\nexport type CustomFieldResource =\n \"candidate\" | \"job\" | \"client\" | \"process\" | \"resume\";\n\n/** One resource's custom field declarations: alias -> {@link FieldDef}. */\nexport type ResourceDecl = Record<string, FieldDef<DataType>>;\n\n/** Declaration input: per (data) resource, a builder fn returning its custom fields. */\nexport type FieldDecls = {\n [R in CustomFieldResource]?: (f: FieldBuilder) => ResourceDecl;\n};\n\n/** A per-resource custom catalog (bare alias -> Data Type), as produced by {@link defineFields}. */\nexport type CustomCatalog = Record<string, DataType>;\n\n/** Map of (data) resource -> its custom catalog; the client merges these into the static catalogs. */\nexport type DeclaredCatalogs = {\n [R in CustomFieldResource]?: CustomCatalog;\n};\n\n// Extract the catalog (alias -> Data Type literal) from a resource's FieldDef map.\ntype CatalogOf<R extends ResourceDecl> = {\n [K in keyof R]: R[K][\"dataType\"];\n};\n\n/** The validated, branded result of {@link defineFields}, keyed by the declared resources. */\nexport type DeclaredCatalogsOf<D extends FieldDecls> = {\n [R in keyof D]: D[R] extends (f: FieldBuilder) => infer Out\n ? Out extends ResourceDecl\n ? CatalogOf<Out>\n : never\n : never;\n};\n\n// Phantom brand: marks a catalog set as already validated by defineFields (ADR-0023 D4).\n// It never exists at runtime — the value is a plain frozen object.\ndeclare const definedFieldsBrand: unique symbol;\n\n/** A validated set of custom field catalogs (branded — the client does not re-validate). */\nexport type DefinedFields<C extends DeclaredCatalogs = DeclaredCatalogs> = C & {\n readonly [definedFieldsBrand]: true;\n};\n\n/** The custom catalog declared for resource `K` (or `{}` if none) — types each accessor (ADR-0023 D1). */\nexport type CustomFor<\n C extends DeclaredCatalogs,\n K extends CustomFieldResource,\n> = K extends keyof C\n ? C[K] extends CustomCatalog\n ? C[K]\n : EmptyCatalog\n : EmptyCatalog;\n\n// 全 arrow(ADR-0013)=巻き上げ無しのため、ヘルパー → builder → defineFields の順で定義する。\nconst def = <D extends CustomDataType>(dataType: D): FieldDef<D> => ({\n dataType,\n});\n\nconst builder: FieldBuilder = {\n number: () => def(\"Number\"),\n singlelineText: () => def(\"SinglelineText\"),\n multilineText: () => def(\"MultilineText\"),\n mail: () => def(\"Mail\"),\n telephone: () => def(\"Telephone\"),\n url: () => def(\"URL\"),\n date: () => def(\"Date\"),\n dateTime: () => def(\"DateTime\"),\n age: () => def(\"Age\"),\n option: () => def(\"Option\"),\n user: () => def(\"User\"),\n};\n\n// Custom field aliases are `U_[Name]` (user-created) or `A_[Name]` (app-created) — ADR-0004.\nconst ALIAS_PATTERN = /^[UA]_/;\n\nconst KNOWN_RESOURCES: readonly CustomFieldResource[] = [\n \"candidate\",\n \"job\",\n \"client\",\n \"process\",\n \"resume\",\n];\n\n/**\n * Declare tenant-specific custom fields per data resource (ADR-0023). This is the validation\n * boundary: it throws {@link PortersConfigError} synchronously for an unknown resource key or an\n * alias that is not `U_`/`A_`-prefixed. The branded result is passed to `PortersClient({ fields })`,\n * which merges each catalog into the resource so the custom fields decode/encode by their declared\n * Data Type and appear typed on reads / writes.\n *\n * @example\n * const myFields = defineFields({\n * candidate: (f) => ({ U_score: f.number(), U_source: f.option() }),\n * });\n */\nexport const defineFields = <D extends FieldDecls>(\n decls: D,\n): DefinedFields<DeclaredCatalogsOf<D>> => {\n const catalogs: Record<string, CustomCatalog> = {};\n for (const [resource, declare] of Object.entries(decls)) {\n if (declare === undefined) continue;\n if (!KNOWN_RESOURCES.includes(resource as CustomFieldResource)) {\n throw new PortersConfigError(\n `defineFields: unknown resource \"${resource}\" (expected one of ${KNOWN_RESOURCES.join(\", \")})`,\n { category: \"config\" },\n );\n }\n const catalog: CustomCatalog = {};\n for (const [alias, fieldDef] of Object.entries(declare(builder))) {\n if (!ALIAS_PATTERN.test(alias)) {\n throw new PortersConfigError(\n `defineFields: custom field alias \"${alias}\" on \"${resource}\" must start with \"U_\" or \"A_\" (standard P_ fields are built in)`,\n { category: \"config\" },\n );\n }\n catalog[alias] = fieldDef.dataType;\n }\n catalogs[resource] = catalog;\n }\n return Object.freeze(catalogs) as DefinedFields<DeclaredCatalogsOf<D>>;\n};\n","// Opt-in binary <-> Base64 helpers for Attachment / Image content (ADR-0018). The\n// resource core takes a Base64 string; these let callers convert raw bytes without a\n// dependency. `btoa` / `atob` are globals on Node 20+ and browsers.\n\n/** Encode raw bytes to a Base64 string. */\nexport const bytesToBase64 = (bytes: Uint8Array): string => {\n // Build a Latin-1 \"binary string\" then Base64 it. O(n) string building — fine for\n // typical attachments; very large files can be encoded by the caller upstream.\n let binary = \"\";\n for (const b of bytes) binary += String.fromCharCode(b);\n return btoa(binary);\n};\n\n/** Decode a Base64 string back to raw bytes. */\nexport const base64ToBytes = (b64: string): Uint8Array =>\n Uint8Array.from(atob(b64), (c) => c.charCodeAt(0));\n"],"mappings":"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","names":["sleep","tag","FIELDS","REQUIRED_ON_CREATE","FIELDS","REQUIRED_ON_CREATE","FIELDS","REQUIRED_ON_CREATE","FIELDS","REQUIRED_ON_CREATE","FIELDS","FIELDS","buildUrl","FIELDS","buildUrl","FIELDS","buildUrl"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@joymerrevent/porters-connect",
3
- "version": "0.6.0",
3
+ "version": "0.6.2",
4
4
  "description": "Unofficial type-safe TypeScript wrapper for the PORTERS Connect API (formerly HRBC).",
5
5
  "keywords": [
6
6
  "porters",
@@ -86,7 +86,7 @@
86
86
  "eslint-config-prettier": "^10.1.8",
87
87
  "globals": "^17.6.0",
88
88
  "lint-staged": "^17.0.7",
89
- "markdownlint-cli2": "^0.22.1",
89
+ "markdownlint-cli2": "^0.23.1",
90
90
  "prettier": "^3.8.4",
91
91
  "publint": "^0.3.21",
92
92
  "simple-git-hooks": "^2.13.1",
@@ -97,7 +97,7 @@
97
97
  "vitest": "^4.1.9"
98
98
  },
99
99
  "dependencies": {
100
- "fast-xml-parser": "^5.9.2"
100
+ "fast-xml-parser": "^5.10.1"
101
101
  },
102
102
  "simple-git-hooks": {
103
103
  "pre-commit": "pnpm exec lint-staged",