@joymerrevent/porters-connect 0.4.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,30 @@
5
5
 
6
6
  ## [Unreleased]
7
7
 
8
+ ## [0.6.0] - 2026-07-01
9
+
10
+ ### Added
11
+
12
+ - **一括書き込み**(F-4 / ADR-0041・`CLAUDE.md`)。各データ系リソースに **`createMany`** / **`updateMany`** を追加。
13
+ - `porters.candidate.createMany([...])` / `updateMany([{ id, fields }, ...])` で複数レコードをまとめて書き込み。
14
+ - **1 リクエスト最大 200 件+約 15000 文字**に自動分割(バッチを逐次送信)。1 件で上限超過は送信前に `PortersConfigError`。
15
+ - **非アトミック**: 戻り値 **`BulkWriteResult`**(`results`=送信順の per-item `{ index, id, code, ok }`/`failed`/`hasFailures`)で
16
+ 部分成功を返します(per-item の失敗は throw しません)。リクエスト全体の失敗のみ throw(バッチ途中の失敗は既書き込み件数を hint に付与)。
17
+ - `createMany` はバッチ跨ぎで**非冪等**(全体の再実行は作成を重複させ得る)。Attachment は対象外(単件のみ)。
18
+ - 新規 export 型 `BulkWriteResult` / `BulkWriteResultItem`。
19
+
20
+ ## [0.5.0] - 2026-06-29
21
+
22
+ ### Added
23
+
24
+ - **マルチテナント面**(F-3 / ADR-0040・ADR-0008/0021)。`porters.tenant(id)` で partition(Company DB)を
25
+ 束ねたアクセサ群 `TenantScope` を返します。`porters.tenant(123).candidate.search(...)` は `partition=123`
26
+ を毎回付与し、未束ねの呼び出しは **client 既定 `partition`** を使います(解決は tenant スコープ/client 既定の 2 層)。
27
+ - スコープは data(candidate/job/client/process/resume)+ attachment + master Read(user/field/option)を露出。
28
+ `auth`(App 単位)・`partition` マスタ(発見専用・partition 非送信)・`tenant`(ネスト不可)は含みません。
29
+ - partition 別トークンが必要な場合は**テナント別 `PortersClient`** を構築(ADR-0008 案3)。
30
+ - 新規 export 型 `TenantScope`。`PortersClientOptions.partition` の JSDoc を更新(per-call 引数は設けない方針)。
31
+
8
32
  ## [0.4.0] - 2026-06-27
9
33
 
10
34
  ### Added
@@ -100,7 +124,9 @@
100
124
  [oauth-guide]: docs/guide/oauth.md
101
125
  [kac]: https://keepachangelog.com/en/1.1.0/
102
126
  [semver]: https://semver.org/
103
- [unreleased]: https://github.com/Joymerrevent/porters-connect/compare/v0.4.0...HEAD
127
+ [unreleased]: https://github.com/Joymerrevent/porters-connect/compare/v0.6.0...HEAD
128
+ [0.6.0]: https://github.com/Joymerrevent/porters-connect/compare/v0.5.0...v0.6.0
129
+ [0.5.0]: https://github.com/Joymerrevent/porters-connect/compare/v0.4.0...v0.5.0
104
130
  [0.4.0]: https://github.com/Joymerrevent/porters-connect/compare/v0.3.0...v0.4.0
105
131
  [0.3.0]: https://github.com/Joymerrevent/porters-connect/compare/v0.2.1...v0.3.0
106
132
  [0.2.1]: https://github.com/Joymerrevent/porters-connect/compare/v0.2.0...v0.2.1
package/README.md CHANGED
@@ -56,9 +56,13 @@ const porters = new PortersClient({
56
56
  host: process.env.PORTERS_HOST!, // 契約時に通知される値。ハードコード禁止
57
57
  appId: process.env.PORTERS_APP_ID!,
58
58
  appSecret: process.env.PORTERS_APP_SECRET!,
59
- partition: 123, // Partition(Company DB)Id
59
+ partition: 123, // 既定 Partition(Company DB)Id
60
60
  });
61
61
 
62
+ // 複数 partition を 1 つの App で扱う SaaS は porters.tenant(id) で束ねる
63
+ const t = porters.tenant(456);
64
+ await t.candidate.search({ condition: { P_Name: { part: "鈴木" } } }); // partition=456
65
+
62
66
  // 検索(最大 200 件/ページ)。condition は項目の Data Type ごとに型付き
63
67
  const page = await porters.candidate.search({
64
68
  condition: { P_Name: { part: "山田" } }, // テキストは part(部分一致)/ full(完全一致)
@@ -79,6 +83,8 @@ for await (const c of porters.candidate.searchAll({
79
83
  }
80
84
  ```
81
85
 
86
+ > 複数 partition を 1 つの App で扱う(マルチテナント SaaS)場合の `porters.tenant(id)` スコープ・テナント別 client・partition 発見は [マルチテナント ガイド][multi-tenancy] にまとめています。
87
+ >
82
88
  > 認証情報やホスト名は**コミットしない**でください。`.env.example` を参考に `.env` で渡します。
83
89
 
84
90
  ## 契約なしで試す(オフライン評価)
@@ -275,9 +281,16 @@ await porters.process.create({
275
281
  P_Candidate: 10001,
276
282
  P_Resume: 50,
277
283
  });
284
+
285
+ // 一括作成/更新(200 件+サイズで自動分割・部分成功を返す)
286
+ const bulk = await porters.candidate.createMany([
287
+ { P_Owner: 5, P_Name: "山田 太郎" },
288
+ { P_Owner: 5, P_Name: "鈴木 花子" },
289
+ ]);
290
+ if (bulk.hasFailures) console.warn(bulk.failed); // per-item は throw せず結果で返す
278
291
  ```
279
292
 
280
- > 1 リクエストの長さは**約 15000 文字**まで(PORTERS 仕様)。超えるとライブラリが送信前に弾きます。
293
+ > 1 リクエストの長さは**約 15000 文字**まで(PORTERS 仕様)。超えるとライブラリが送信前に弾きます。一括書き込み(`createMany` / `updateMany`)は 200 件+サイズで自動分割し、部分成功を `BulkWriteResult` で返します — 詳しくは [一括書き込み ガイド][bulk-write] を参照。
281
294
 
282
295
  ## 添付ファイル(Attachment)
283
296
 
@@ -365,6 +378,8 @@ try {
365
378
  [auth-flow]: ./docs/reference/authentication-api/README.md
366
379
  [oauth-guide]: ./docs/guide/oauth.md
367
380
  [error-handling]: ./docs/guide/error-handling.md
381
+ [multi-tenancy]: ./docs/guide/multi-tenancy.md
382
+ [bulk-write]: ./docs/guide/bulk-write.md
368
383
  [sandbox]: ./examples/offline-sandbox.ts
369
384
  [adr]: ./docs/adr/README.md
370
385
  [design]: ./docs/design/basic-design.md
package/dist/index.d.ts CHANGED
@@ -252,6 +252,28 @@ type SearchQuery<F extends FieldCatalog = FieldCatalog> = {
252
252
  start?: number;
253
253
  };
254
254
 
255
+ /** One record's outcome from a bulk write, in the position it was sent (ADR-0041 SD-2). */
256
+ type BulkWriteResultItem = {
257
+ /** 0-based index in the input array. */
258
+ index: number;
259
+ /** Assigned (create) / echoed (update) record id. Meaningful only when `ok`. */
260
+ id: number;
261
+ /** PORTERS per-item Result Code (`0` = success). */
262
+ code: number;
263
+ /** `code === 0`. */
264
+ ok: boolean;
265
+ };
266
+ /**
267
+ * The result of `createMany` / `updateMany` (ADR-0041). `results` holds every record's outcome in
268
+ * input order; `failed` is the `ok === false` subset. A per-item `code !== 0` does **not** throw —
269
+ * a bulk write mixes successes and failures — so always inspect `hasFailures` / `failed`.
270
+ */
271
+ type BulkWriteResult = {
272
+ results: BulkWriteResultItem[];
273
+ failed: BulkWriteResultItem[];
274
+ hasFailures: boolean;
275
+ };
276
+
255
277
  type WritableKeys<F extends FieldCatalog> = {
256
278
  [K in keyof F]: F[K] extends WritableDataType ? K : never;
257
279
  }[keyof F];
@@ -277,6 +299,22 @@ type Resource<F extends FieldCatalog, Req extends keyof F> = {
277
299
  create(input: CreateInput<F, Req>): Promise<number>;
278
300
  /** Update one record by id; resolves to that id. */
279
301
  update(id: number, input: UpdateInput<F>): Promise<number>;
302
+ /**
303
+ * Create many records in one call (ADR-0041 / F-4). Auto-batched to ≤200 records and under the
304
+ * request size cap. **Not atomic** — inspect the {@link BulkWriteResult}: per-record failures are
305
+ * returned (`failed` / `hasFailures`), not thrown. Only a whole-request failure throws (with the
306
+ * already-written count). Batching is non-idempotent: a full retry after a mid-run failure may
307
+ * duplicate creates. Empty input sends no request.
308
+ */
309
+ createMany(inputs: CreateInput<F, Req>[]): Promise<BulkWriteResult>;
310
+ /**
311
+ * Update many records by id in one call (ADR-0041 / F-4). Auto-batched like {@link createMany};
312
+ * per-record failures are returned in the {@link BulkWriteResult}, not thrown.
313
+ */
314
+ updateMany(items: {
315
+ id: number;
316
+ fields: UpdateInput<F>;
317
+ }[]): Promise<BulkWriteResult>;
280
318
  };
281
319
 
282
320
  declare const FIELDS$8: {
@@ -714,7 +752,11 @@ type PortersClientOptions<C extends DeclaredCatalogs = EmptyCatalog> = {
714
752
  appId?: string;
715
753
  appSecret?: string;
716
754
  scopes?: Scope[];
717
- /** Partition (Company DB) used for every call. Per-call override is not yet supported (planned — see ADR-0033). */
755
+ /**
756
+ * Default partition (Company DB) for every call. For multi-tenant routing, bind a partition
757
+ * per call with {@link PortersClient.tenant} (ADR-0040 / F-3); for a fully separated per-partition
758
+ * token, construct a dedicated client per tenant instead (ADR-0008 案3).
759
+ */
718
760
  partition?: PartitionId;
719
761
  /** Custom auth strategy; defaults to the transparent code_direct strategy. */
720
762
  auth?: TokenProvider;
@@ -729,6 +771,22 @@ type PortersClientOptions<C extends DeclaredCatalogs = EmptyCatalog> = {
729
771
  */
730
772
  fields?: DefinedFields<C>;
731
773
  };
774
+ /**
775
+ * The partition-bound resource accessors returned by {@link PortersClient.tenant} (ADR-0040 / F-3).
776
+ * Every accessor here routes to the bound tenant's partition. `auth` (App-level), the `partition`
777
+ * master (discovery — partition-less), and `tenant` itself (no nesting) are deliberately absent.
778
+ */
779
+ type TenantScope<C extends DeclaredCatalogs = EmptyCatalog> = {
780
+ readonly candidate: CandidateResource<CustomFor<C, "candidate">>;
781
+ readonly job: JobResource<CustomFor<C, "job">>;
782
+ readonly client: ClientResource<CustomFor<C, "client">>;
783
+ readonly process: ProcessResource<CustomFor<C, "process">>;
784
+ readonly resume: ResumeResource<CustomFor<C, "resume">>;
785
+ readonly attachment: AttachmentResource;
786
+ readonly user: UserResource;
787
+ readonly field: FieldResource;
788
+ readonly option: OptionResource;
789
+ };
732
790
  /**
733
791
  * Entry point of the library. Wires the default transport / auth / throttle /
734
792
  * requester and exposes namespaced resource accessors such as `candidate`
@@ -752,6 +810,16 @@ declare class PortersClient<C extends DeclaredCatalogs = EmptyCatalog> {
752
810
  readonly field: FieldResource;
753
811
  /** Master Read: a tenant's choice (option) master (ADR-0021/0022). */
754
812
  readonly option: OptionResource;
813
+ /**
814
+ * Bind a tenant's partition (Company DB) once and route every call through it — the multi-tenant
815
+ * scope (ADR-0008 案2 / renamed in ADR-0021 / implemented in ADR-0040 F-3).
816
+ * `porters.tenant(123).candidate.search(...)` sends `partition=123` without repeating it, overriding
817
+ * the client-default `partition`. Returns the partition-bound accessors (data + attachment + master
818
+ * User/Field/Option); `auth` (App-level), the `partition` master (discovery — takes no partition),
819
+ * and `tenant` itself (no nesting) are intentionally omitted. For a fully separated per-partition
820
+ * token, construct a dedicated {@link PortersClient} per tenant instead (ADR-0008 案3).
821
+ */
822
+ readonly tenant: (id: PartitionId) => TenantScope<C>;
755
823
  constructor(options: PortersClientOptions<C>);
756
824
  /** The configured API host. */
757
825
  get host(): string;
@@ -805,4 +873,4 @@ declare const bytesToBase64: (bytes: Uint8Array) => string;
805
873
  /** Decode a Base64 string back to raw bytes. */
806
874
  declare const base64ToBytes: (b64: string) => Uint8Array;
807
875
 
808
- export { type Attachment, type AttachmentCreate, type AttachmentPage, type AttachmentResource, type AttachmentSearchQuery, type AttachmentUpdate, type AuthApi, type AuthorizationUrlOptions, type Candidate, type CandidateCreateInput, type CandidatePage, type CandidateResource, type CandidateSearchQuery, type CandidateUpdateInput, type Client, type ClientCreateInput, type ClientPage, type ClientResource, type ClientSearchQuery, type ClientUpdateInput, type Condition, type CustomDataType, type DefinedFields, type ErrorCategory, type Field, type FieldBuilder, type FieldDecls, type FieldDef, type FieldPage, type FieldResource, type FieldSearchQuery, type FieldValue, type GetAccessTokenOptions, type ItemState, type Job, type JobCreateInput, type JobPage, type JobResource, type JobSearchQuery, type JobUpdateInput, type MockHandler, type MockReply, type MockTransportOptions, type Option, type OptionResource, type OptionSearchQuery, type Order, type Partition, type PartitionId, type PartitionPage, type PartitionResource, type PartitionSearchQuery, PortersAuthError, PortersClient, type PortersClientOptions, PortersConfigError, PortersError, type PortersErrorContext, type PortersErrorOptions, PortersNetworkError, PortersResourceError, type Process, type ProcessCreateInput, type ProcessPage, type ProcessResource, type ProcessSearchQuery, type ProcessUpdateInput, type ResourceType, type Resume, type ResumeCreateInput, type ResumePage, type ResumeResource, type ResumeSearchQuery, type ResumeUpdateInput, type RevokeUrlOptions, type Scope, type SearchQuery, type StoredTokens, type TokenProvider, type TokenStore, type Transport, type TransportRequest, type TransportResponse, type User, type UserPage, type UserRef, type UserResource, type UserSearchQuery, base64ToBytes, bytesToBase64, createMockTransport, defineFields };
876
+ export { type Attachment, type AttachmentCreate, type AttachmentPage, type AttachmentResource, type AttachmentSearchQuery, type AttachmentUpdate, type AuthApi, type AuthorizationUrlOptions, type BulkWriteResult, type BulkWriteResultItem, type Candidate, type CandidateCreateInput, type CandidatePage, type CandidateResource, type CandidateSearchQuery, type CandidateUpdateInput, type Client, type ClientCreateInput, type ClientPage, type ClientResource, type ClientSearchQuery, type ClientUpdateInput, type Condition, type CustomDataType, type DefinedFields, type ErrorCategory, type Field, type FieldBuilder, type FieldDecls, type FieldDef, type FieldPage, type FieldResource, type FieldSearchQuery, type FieldValue, type GetAccessTokenOptions, type ItemState, type Job, type JobCreateInput, type JobPage, type JobResource, type JobSearchQuery, type JobUpdateInput, type MockHandler, type MockReply, type MockTransportOptions, type Option, type OptionResource, type OptionSearchQuery, type Order, type Partition, type PartitionId, type PartitionPage, type PartitionResource, type PartitionSearchQuery, PortersAuthError, PortersClient, type PortersClientOptions, PortersConfigError, PortersError, type PortersErrorContext, type PortersErrorOptions, PortersNetworkError, PortersResourceError, type Process, type ProcessCreateInput, type ProcessPage, type ProcessResource, type ProcessSearchQuery, type ProcessUpdateInput, type ResourceType, type Resume, type ResumeCreateInput, type ResumePage, type ResumeResource, type ResumeSearchQuery, type ResumeUpdateInput, type RevokeUrlOptions, type Scope, type SearchQuery, type StoredTokens, type TenantScope, type TokenProvider, type TokenStore, type Transport, type TransportRequest, type TransportResponse, type User, type UserPage, type UserRef, type UserResource, type UserSearchQuery, base64ToBytes, bytesToBase64, createMockTransport, defineFields };
package/dist/index.js CHANGED
@@ -590,10 +590,9 @@ var encodeItem = (prefix, fields, item) => {
590
590
  }
591
591
  return parts.join("");
592
592
  };
593
+ var encodeWriteItem = (prefix, fields, item) => `<Item>${encodeItem(prefix, fields, item)}</Item>`;
593
594
  var buildWriteXml = (config) => {
594
- const items = config.items.map(
595
- (item) => `<Item>${encodeItem(config.prefix, config.fields, item)}</Item>`
596
- ).join("");
595
+ const items = config.items.map((item) => encodeWriteItem(config.prefix, config.fields, item)).join("");
597
596
  return `<${config.resource}>${items}</${config.resource}>`;
598
597
  };
599
598
 
@@ -780,6 +779,87 @@ var appendReadQuery = (p, q, ctx) => {
780
779
  }
781
780
  };
782
781
 
782
+ // src/resources/bulk-write.ts
783
+ var MAX_ITEMS_PER_REQUEST = 200;
784
+ var packBatches = (encoded, budget) => {
785
+ const batches = [];
786
+ let batch = [];
787
+ let length = 0;
788
+ for (const e of encoded) {
789
+ if (e.xml.length > budget) {
790
+ throw new PortersConfigError(
791
+ `a single record serializes to ${e.xml.length} characters, over the ~${budget}-character budget for one request`,
792
+ {
793
+ category: "config",
794
+ hint: "Reduce that record's field values \u2014 a bulk request (URL + body) is capped at ~15000 characters."
795
+ }
796
+ );
797
+ }
798
+ if (batch.length >= MAX_ITEMS_PER_REQUEST || length + e.xml.length > budget) {
799
+ batches.push(batch);
800
+ batch = [];
801
+ length = 0;
802
+ }
803
+ batch.push(e);
804
+ length += e.xml.length;
805
+ }
806
+ if (batch.length > 0) batches.push(batch);
807
+ return batches;
808
+ };
809
+ var batchFailure = (cause, written, resource, partition) => {
810
+ const base = cause instanceof PortersError ? cause : void 0;
811
+ return new PortersResourceError(
812
+ `bulk write failed after ${written} record(s) had already been written`,
813
+ {
814
+ category: base?.category ?? "unknown",
815
+ code: base?.code ?? null,
816
+ retryable: false,
817
+ httpStatus: base?.httpStatus,
818
+ hint: `${written} record(s) from earlier batches were already written; retry only the records from index ${written} onward (create is non-idempotent \u2014 a full retry would duplicate them).`,
819
+ context: { resource, operation: "bulkWrite", partition },
820
+ cause
821
+ }
822
+ );
823
+ };
824
+ var runBulkWrite = async (requester, target, items, idempotent) => {
825
+ const envelope = `<${target.name}></${target.name}>`.length;
826
+ const budget = MAX_REQUEST_LENGTH - target.url.length - envelope;
827
+ const encoded = items.map((item, index) => ({
828
+ index,
829
+ xml: encodeWriteItem(target.prefix, target.fields, item)
830
+ }));
831
+ const batches = packBatches(encoded, budget);
832
+ const results = [];
833
+ let written = 0;
834
+ for (const batch of batches) {
835
+ const body = `<${target.name}>${batch.map((e) => e.xml).join("")}</${target.name}>`;
836
+ let parsed;
837
+ try {
838
+ parsed = await requester.request(
839
+ { method: "POST", url: target.url, headers: {}, body },
840
+ parseWriteResult,
841
+ { write: true, idempotent }
842
+ );
843
+ } catch (cause) {
844
+ if (written === 0) throw cause;
845
+ throw batchFailure(cause, written, target.name, target.partition);
846
+ }
847
+ if (parsed.length !== batch.length) {
848
+ throw new PortersResourceError(
849
+ `bulk write response returned ${parsed.length} result(s) for ${batch.length} record(s)`,
850
+ { category: "unknown", context: { resource: target.name } }
851
+ );
852
+ }
853
+ batch.forEach((e, i) => {
854
+ const { id, code } = parsed[i];
855
+ results.push({ index: e.index, id, code, ok: code === 0 });
856
+ });
857
+ written += batch.length;
858
+ }
859
+ const failed = results.filter((r) => !r.ok);
860
+ return { results, failed, hasFailures: failed.length > 0 };
861
+ };
862
+
783
863
  // src/resources/resource.ts
784
864
  var USER_SUBFIELDS = ["P_Id", "P_Type", "P_Name", "P_Mail"];
785
865
  var defaultFieldList = (prefix, fields) => Object.entries(fields).map(
@@ -851,7 +931,25 @@ var createResource = (config, deps) => {
851
931
  );
852
932
  const create = (input) => write({ ...input, P_Id: -1 }, false);
853
933
  const update = (id, input) => write({ ...input, P_Id: id }, true);
854
- return { search, searchAll, get, create, update };
934
+ const target = {
935
+ name: config.name,
936
+ prefix: config.prefix,
937
+ fields: fieldMap,
938
+ partition: deps.partition
939
+ };
940
+ const createMany = (inputs) => runBulkWrite(
941
+ deps.requester,
942
+ { ...target, url: writeUrl() },
943
+ inputs.map((input) => ({ ...input, P_Id: -1 })),
944
+ false
945
+ );
946
+ const updateMany = (items) => runBulkWrite(
947
+ deps.requester,
948
+ { ...target, url: writeUrl() },
949
+ items.map(({ id, fields }) => ({ ...fields, P_Id: id })),
950
+ true
951
+ );
952
+ return { search, searchAll, get, create, update, createMany, updateMany };
855
953
  };
856
954
 
857
955
  // src/resources/candidate.ts
@@ -1339,6 +1437,16 @@ var PortersClient = class {
1339
1437
  field;
1340
1438
  /** Master Read: a tenant's choice (option) master (ADR-0021/0022). */
1341
1439
  option;
1440
+ /**
1441
+ * Bind a tenant's partition (Company DB) once and route every call through it — the multi-tenant
1442
+ * scope (ADR-0008 案2 / renamed in ADR-0021 / implemented in ADR-0040 F-3).
1443
+ * `porters.tenant(123).candidate.search(...)` sends `partition=123` without repeating it, overriding
1444
+ * the client-default `partition`. Returns the partition-bound accessors (data + attachment + master
1445
+ * User/Field/Option); `auth` (App-level), the `partition` master (discovery — takes no partition),
1446
+ * and `tenant` itself (no nesting) are intentionally omitted. For a fully separated per-partition
1447
+ * token, construct a dedicated {@link PortersClient} per tenant instead (ADR-0008 案3).
1448
+ */
1449
+ tenant;
1342
1450
  #host;
1343
1451
  constructor(options) {
1344
1452
  const transport = options.transport ?? createFetchTransport();
@@ -1373,22 +1481,33 @@ var PortersClient = class {
1373
1481
  backoff: expoBackoff()
1374
1482
  });
1375
1483
  this.#host = options.host;
1376
- const deps = {
1377
- requester,
1378
- host: options.host,
1379
- partition: options.partition ?? 0
1380
- };
1381
1484
  const customFor = (key) => options.fields?.[key] ?? {};
1382
- this.candidate = createCandidateResource(deps, customFor("candidate"));
1383
- this.job = createJobResource(deps, customFor("job"));
1384
- this.client = createClientResource(deps, customFor("client"));
1385
- this.process = createProcessResource(deps, customFor("process"));
1386
- this.resume = createResumeResource(deps, customFor("resume"));
1387
- this.attachment = createAttachmentResource(deps);
1485
+ const buildScope = (partition) => {
1486
+ const deps = { requester, host: options.host, partition };
1487
+ return {
1488
+ candidate: createCandidateResource(deps, customFor("candidate")),
1489
+ job: createJobResource(deps, customFor("job")),
1490
+ client: createClientResource(deps, customFor("client")),
1491
+ process: createProcessResource(deps, customFor("process")),
1492
+ resume: createResumeResource(deps, customFor("resume")),
1493
+ attachment: createAttachmentResource(deps),
1494
+ user: createUserResource(deps),
1495
+ field: createFieldResource(deps),
1496
+ option: createOptionResource(deps)
1497
+ };
1498
+ };
1499
+ this.tenant = buildScope;
1500
+ const root = buildScope(options.partition ?? 0);
1501
+ this.candidate = root.candidate;
1502
+ this.job = root.job;
1503
+ this.client = root.client;
1504
+ this.process = root.process;
1505
+ this.resume = root.resume;
1506
+ this.attachment = root.attachment;
1507
+ this.user = root.user;
1508
+ this.field = root.field;
1509
+ this.option = root.option;
1388
1510
  this.partition = createPartitionResource({ requester, host: options.host });
1389
- this.user = createUserResource(deps);
1390
- this.field = createFieldResource(deps);
1391
- this.option = createOptionResource(deps);
1392
1511
  }
1393
1512
  /** The configured API host. */
1394
1513
  get host() {