Skip to content

Commit 67b4e34

Browse files
AditiGoyalUipathclaudeSarath1018amrit-agarwal-1
authored
feat(data-fabric): add folderKey support to entities.getAll and ChoiceSets surface (#504)
* feat(data-fabric): add folderKey support to entities.getAll and ChoiceSets surface entities.getAll now accepts an optional folderKey to retrieve folder-scoped entities; the API filters exclusively (tenant scope vs folder scope are disjoint), confirmed against the live API. ChoiceSets methods all accept folderKey and forward it as the X-UIPATH-FolderKey header. Critically, insertValueById and updateValueById hard-fail on folder-scoped choice sets without the header — and their internal name resolver (resolveChoiceSetName) now scopes its getAll lookup by the same folderKey so the path stops throwing NotFoundError before the API call. Adds folder-scoped @example blocks to JSDoc on every Entities method that already supported folderKey but didn't document it, integration coverage for the new getAll filter, and a skipped folder-scoped ChoiceSets block mirroring the existing OAuth-scope-gated value-CRUD pattern. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix: address review comments — JSDoc sync, single afterAll, folderKey header tests - Sync ChoiceSetServiceModel JSDoc with service-class JSDoc on getById, deleteById, and deleteValuesById (model is the docs source of truth). - Service-class JSDoc on the same three methods updated with @param options and folder-scoped @example blocks for parity. - Consolidate folder-scoped choice-set integration cleanup into the file-level afterAll (removes the duplicate afterAll inside the describe.skip block per the rules.md convention). - Add unit tests asserting X-UIPATH-FolderKey forwarding for every choice-set method that gained folderKey support (getAll, getById, create, updateById, deleteById, insertValueById, updateValueById, deleteValuesById) and for entities.getAll, matching the pattern already used on other Entities methods. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(data-fabric): cross-folder reference support + folder-scoped integration tests Adds an opt-in `referenceFolderKey` on EntityCreateFieldOptions so callers can create entities whose RELATIONSHIP / CHOICE_SET fields point at targets in a different folder (or the tenant SYSTEM scope). The SDK assembles the minimum payload each API path needs: - Relationship targets: { id, folderId } — both come straight from caller inputs, no extra round-trip. Verified against alpha: the relationship endpoint resolves by folderId. - Choice-set targets: { id, name, folderId, entityType, entityTypeId } — the CS endpoint resolves by name, so the SDK does one GET on the target to fetch it (parallelized across fields). Verified against alpha: bare {id} or {id, folderId} both 403 with empty target name; {id, name} succeeds. Tenant marker (DATA_FABRIC_TENANT_FOLDER_ID, all-zeros) is supported as a referenceFolderKey value — the SDK looks up the target at tenant scope (no folder header) and emits folderId: '00000000-...'. Integration tests: - Folder-scoped record CRUD (insert/get/update/delete + batch variants, plus queryRecordsById) — runs in CI against DATA_FABRIC_TEST_FOLDER_ENTITY_ID + INTEGRATION_TEST_FOLDER_KEY. - Folder-scoped Choice value CRUD — describe.skip'd alongside the other schema-write blocks (requires DataFabric.Schema.Write OAuth scope); the block locates its target CS by name (`aIntegrationTestFolderScoped`) via getAll({ folderKey }) so it doesn't need a CS-ID env var. - buildDummyRecord helper now threads folderKey into getChoiceSetValues so folder-scoped ChoiceSetSingle/Multiple fields get populated correctly. Unit tests: - 3 new tests covering the new opt-in path: cross-folder relationship (no GET, embeds {id, folderId}), tenant-marker CS lookup (no folder header on the GET), folder-UUID CS lookup (sends X-UIPATH-FolderKey). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * revert: roll tests/.env.integration.example back to template Reverts the prior commit's accidental check-in of tenant-specific test config and a personal PAT into the example file. The example should only carry placeholder values; live config belongs in the gitignored .env.integration. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * ci: add DATA_FABRIC_TEST_FOLDER_ENTITY_ID to integration test config Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * refactor(data-fabric): extract ChoiceSet entityType/Id to module-level constants Replaces inline 'ChoiceSet' / 1 literals in buildReferenceMeta with the existing EntityType.ChoiceSet enum and a new ENTITY_TYPE_IDS map. Pairs the two values that travel together in reference payloads. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(data-fabric): add includeAllFolders option to entities.getAll (#509) Add an optional `includeAllFolders` flag to `EntityGetAllOptions`. When true (and no `folderKey` is provided), `getAll` lists tenant-level and folder-level entities together via the v2 entity endpoint. Existing behavior is unchanged: no flag lists only tenant entities, and a `folderKey` always wins — scoping to that single folder and ignoring `includeAllFolders`. Documents the additional `OR.Users` scope required for folder-scoped entity operations and the combined listing. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor(data-fabric): rename includeAllFolders to includeAllScopes on entities.getAll The flag returns BOTH tenant-level and folder-level entities together — "all folders" was misleading on two counts: it sounded folder-only (excluding tenant entities), and tenant isn't a "folder." "Scopes" is the right abstraction since Data Fabric entities have two scopes (tenant + folder) and the flag toggles "give me everything regardless of scope." Renames across types, service implementation, JSDoc, unit + integration tests, endpoint comment, and oauth-scopes docs. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(data-fabric): inline tenant folder UUID literal in referenceFolderKey JSDoc DATA_FABRIC_TENANT_FOLDER_ID is an internal endpoint constant not exported through the public API barrel, so users had no way to resolve the reference. Inlines the literal '00000000-0000-0000-0000-000000000000' so the JSDoc is self-contained. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * feat(data-fabric): add includeFolderChoiceSets opt-in + address Sarath PR comments ChoiceSets: - Add `includeFolderChoiceSets?: boolean` option to ChoiceSetGetAllOptions - Default tenant-only via tenant-marker header (no OR.Users required) - `includeFolderChoiceSets: true` opts into cross-scope (tenant + folder), matching the `includeAllScopes` pattern on entities - folderKey continues to scope to a single folder (always wins over the flag) Entities: - Keep `includeAllScopes` (per Sarath's merged PR) — default tenant-only via v1 endpoint; `includeAllScopes: true` uses v2 (requires OR.Users) - JSDoc rewritten to spell out the canonical 3-mode pattern Sarath PR comment fixes: - Remove self-referential `Options for {@link X}` JSDoc on options interfaces in both choicesets.types.ts and entities.types.ts - Use DATA_FABRIC_TENANT_FOLDER_ID constant in integration test - Add OR.Users note for ChoiceSets in oauth-scopes.md - Restore GET_ALL_V2 endpoint constant alongside v1 GET_ALL - Unit test coverage for all 3 modes on both services Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * refactor(data-fabric): rename entities.getAll option includeAllScopes → includeFolderEntities Parallels the choicesets-side `includeFolderChoiceSets` naming so both surfaces use clear, customer-facing flag names. "AllScopes" leaked SDK internals ("scope" is not customer vocabulary); "include folder entities" states plainly what the flag adds on top of the tenant default. Same 3-mode semantics preserved: - getAll({ includeFolderEntities: false }) → tenant only (default) - getAll({ includeFolderEntities: true }) → tenant + folders (needs OR.Users) - getAll({ includeFolderEntities: false, folderKey }) → folder only (folderKey wins) Rename across: type field, JSDoc on EntityServiceModel + service class, endpoint comment, unit tests, integration test reference, oauth-scopes.md. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * test(data-fabric): skip includeFolderEntities CI test that requires OR.Users The /api/v2/Entity endpoint backing `getAll({ includeFolderEntities: true })` requires the OR.Users OAuth scope, which the standard integration PAT does not carry — so the test 403s in CI. Mark the test with `it.skip` and a comment pointing local devs at how to enable it when running with an OR.Users-capable token, matching the schema-write `describe.skip` pattern already established in this file. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * test(data-fabric): re-enable includeFolderEntities integration test OR.Users scope is now available on the integration PAT, so the v2 endpoint backing `getAll({ includeFolderEntities: true })` no longer returns 403. Reverts the `it.skip` and keeps a one-line comment noting the scope requirement for future readers. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * fix(data-fabric): address SonarCloud issues on PR #504 - entities.ts:1266 / choicesets.ts:398: flip negated ternaries (S7735) - entities.ts:166,630 / choicesets.ts:138: drop unnecessary `{} as T` cast on the `options ?? {}` fallback (S4325) - choicesets.integration.test.ts:256,466: add post-delete getById + assertion that the deleted value IDs are no longer present (S2699 BLOCKER — tests must contain at least one assertion) Verifies the delete actually worked, not just that the call resolved. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(data-fabric): mark folder scope as experimental across Entities Folder-scoped Data Fabric is still in preview. Surface that everywhere the SDK exposes it: - Type-level: add @experimental on EntityFolderScopedOptions.folderKey, EntityGetAllOptions.includeFolderEntities, and EntityCreateFieldOptions .referenceFolderKey. TypeDoc renders these as Experimental badges in the generated reference tables. - Method-level: add a "> **Experimental:** ..." blockquote to every Entities method that documents folderKey (getAll, getById, getAllRecords, getRecordById, queryRecordsById, insertRecordById, insertRecordsById, updateRecordById, updateRecordsById, updateById, deleteRecordById, deleteRecordsById, deleteById, uploadAttachment, downloadAttachment, deleteAttachment, importRecordsById, create). - Kept JSDoc in sync between entities.models.ts (TypeDoc source of truth) and entities.ts (service class). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(data-fabric): clarify choicesets.getAll JSDoc per PR review - "Gets choice sets in the org" → "Gets choice sets in the tenant". - Default call mode is now shown as `getAll()`, not `getAll({ includeFolderChoiceSets: false })`. - Reorder call modes so `folderKey` is presented as the preferred way to scope to a folder, with `includeFolderChoiceSets` reframed as the wider tenant + folder option. Kept the JSDoc in sync between ChoiceSetServiceModel and the ChoiceSetService class. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(data-fabric): apply same JSDoc clarifications to entities.getAll Mirror the choicesets.getAll review fixes onto the entities surface: - "Gets entities in the system" → "Gets entities in the tenant". - Default call mode is now shown as `getAll()`, not `getAll({ includeFolderEntities: false })`. - Reorder call modes so `folderKey` is presented as the preferred way to scope to a folder, with `includeFolderEntities` reframed as the wider tenant + folder option. Kept JSDoc in sync between EntityServiceModel and the EntityService class. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(data-fabric): add @experimental tag to folderKey-bearing methods Every Entities and ChoiceSets method that accepts a `folderKey` option now carries the `@experimental` JSDoc tag, so TypeDoc renders an `Experimental` badge directly under the method signature in the generated reference docs — alongside the existing blockquote that calls out `folderKey` specifically as the experimental property. Choicesets also gains the "folder scope is experimental" blockquote on each affected method (entities already had it). Kept JSDoc in sync between the ServiceModel interfaces and the service-class implementations. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(data-fabric): drop OR.Users OAuth scope mentions from JSDoc Per PR feedback — remove `OR.Users` references from user-facing JSDoc on the entities and choicesets `getAll` methods and on the related option field comments. Internal code comments that explain endpoint-selection logic stay (they're not rendered in public docs). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(data-fabric): scope experimental marker to folderKey argument only Method-level `@experimental` tags and `> **Experimental:** ...` blockquotes removed from every Entities and ChoiceSets method that takes `folderKey`. The experimental marker now lives only at the argument level: - Type-level: `@experimental` JSDoc tag on the `folderKey` property (already in `EntityFolderScopedOptions`) and `includeFolderChoiceSets` (added here for parity with `includeFolderEntities`). TypeDoc renders these as `Experimental` badges on the property rows of every linked options-type page. - Method-level: each `@param options - ...` line now ends with `The \`folderKey\` property is **experimental**.` — visible directly in the rendered parameter table of every folderKey-bearing method. `updateValueById` (ChoiceSets) previously had no `@param options` line; added one so the marker reaches that method too. ServiceModel ↔ service class JSDoc kept in sync per project convention. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(data-fabric): drop OR.Users folder-scope blockquotes from oauth-scopes Removes the two leftover blockquote notes in docs/oauth-scopes.md that called out `OR.Users` for folder-scoped Entities and ChoiceSets. The remaining `OR.Users` rows in that file are unrelated (User Settings service endpoints). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * docs(data-fabric): address PR review comments Addresses outstanding Claude bot review feedback on PR #504: - Drop the `as unknown as ChoiceSetGetResponse` intermediate cast in `getById`'s `transformFn` — a single `as ChoiceSetGetResponse` is sufficient when `pascalToCamelCaseKeys()` precedes `transformData()` in the pipeline (returns `any`). - Remove the `as any` cast on the `PaginationHelpers.getAll()` return in `getById` — TypeScript infers the conditional return type correctly without it. - Use typed `EntityType.ChoiceSet` + `ENTITY_TYPE_IDS[…]` in `entities.test.ts` instead of raw `"ChoiceSet"` / `1` literals so the assertion stays in sync if the enum or type-id mapping changes. Also fixes a follow-on `entityType: 0` literal that the new enum import surfaced. - Fix the double `@track('Choicesets.GetAll')` telemetry from `resolveChoiceSetName` calling `this.getAll()`: extract an un-tracked `fetchAllChoiceSets` helper that both `getAll()` and `resolveChoiceSetName` call directly. - Extract `EntityFolderScopedOptions` into a new shared `src/models/data-fabric/data-fabric.types.ts` so `choicesets.types` no longer imports across service domains from `entities.types`. `entities.types` re-exports for backward compatibility with the public barrel. Also: reword the `folderKey` precedence note from "folderKey (when provided) always wins over this flag" to "folderKey is preferred over includeFolder{Entities,ChoiceSets} when both are set" everywhere it appears (model JSDoc, service JSDoc, type-level field JSDoc, inline implementation comments). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> * chore(data-fabric): tighten ReferenceEntityPayload.entityType + scrub OR.Users from DF source - `ReferenceEntityPayload.entityType` was typed `string`, losing type safety and autocomplete. The `EntityType` enum already covers every valid value, and the only call site (`buildReferenceMeta`) already passes `EntityType.ChoiceSet`. Narrow to `entityType?: EntityType`. - Remove the last three `OR.Users` references from Data Fabric source files (endpoint comment for `GET_ALL_V2`, inline `getAll` comment in the entity service, inline `fetchAllChoiceSets` comment). The remaining `OR.Users` mentions in the repo are unrelated SDK auth examples and the User Settings service rows in oauth-scopes.md. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com> Co-authored-by: Sarath1018 <motatisarath@gmail.com> Co-authored-by: amrit-agarwal-1 <amrit.agarwal@uipath.com>
1 parent b8d856c commit 67b4e34

17 files changed

Lines changed: 1188 additions & 181 deletions

File tree

.github/workflows/pr-checks.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ jobs:
6666
echo "data_fabric_test_entity_id=${{ secrets.UIPATH_DATA_FABRIC_TEST_ENTITY_ID_DEV || secrets.UIPATH_DATA_FABRIC_TEST_ENTITY_ID }}" >> $GITHUB_OUTPUT
6767
echo "data_fabric_test_choiceset_id=${{ secrets.UIPATH_DATA_FABRIC_TEST_CHOICESET_ID_DEV || secrets.UIPATH_DATA_FABRIC_TEST_CHOICESET_ID }}" >> $GITHUB_OUTPUT
6868
echo "data_fabric_test_attachment_field=${{ secrets.UIPATH_DATA_FABRIC_TEST_ATTACHMENT_FIELD_DEV || secrets.UIPATH_DATA_FABRIC_TEST_ATTACHMENT_FIELD }}" >> $GITHUB_OUTPUT
69+
echo "data_fabric_test_folder_entity_id=${{ secrets.UIPATH_DATA_FABRIC_TEST_FOLDER_ENTITY_ID_DEV || secrets.UIPATH_DATA_FABRIC_TEST_FOLDER_ENTITY_ID }}" >> $GITHUB_OUTPUT
6970
echo "orchestrator_attachment_id=${{ secrets.UIPATH_ORCHESTRATOR_ATTACHMENT_ID_DEV || secrets.UIPATH_ORCHESTRATOR_ATTACHMENT_ID }}" >> $GITHUB_OUTPUT
7071
echo "jobs_test_folder_id=${{ secrets.UIPATH_JOBS_TEST_FOLDER_ID_DEV || secrets.UIPATH_JOBS_TEST_FOLDER_ID }}" >> $GITHUB_OUTPUT
7172
echo "traces_test_trace_id=${{ secrets.UIPATH_TRACES_TEST_TRACE_ID_DEV || secrets.UIPATH_TRACES_TEST_TRACE_ID }}" >> $GITHUB_OUTPUT
@@ -90,6 +91,7 @@ jobs:
9091
DATA_FABRIC_TEST_ENTITY_ID=${{ steps.config.outputs.data_fabric_test_entity_id }}
9192
DATA_FABRIC_TEST_CHOICESET_ID=${{ steps.config.outputs.data_fabric_test_choiceset_id }}
9293
DATA_FABRIC_TEST_ATTACHMENT_FIELD=${{ steps.config.outputs.data_fabric_test_attachment_field }}
94+
DATA_FABRIC_TEST_FOLDER_ENTITY_ID=${{ steps.config.outputs.data_fabric_test_folder_entity_id }}
9395
ORCHESTRATOR_TEST_PROCESS_KEY=${{ steps.config.outputs.orchestrator_test_process_key }}
9496
ORCHESTRATOR_ATTACHMENT_ID=${{ steps.config.outputs.orchestrator_attachment_id }}
9597
JOBS_TEST_FOLDER_ID=${{ steps.config.outputs.jobs_test_folder_id }}

src/models/data-fabric/choicesets.models.ts

Lines changed: 51 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,16 @@
11
import {
2+
ChoiceSetGetAllOptions,
23
ChoiceSetGetAllResponse,
34
ChoiceSetGetResponse,
45
ChoiceSetGetByIdOptions,
56
ChoiceSetCreateOptions,
67
ChoiceSetUpdateOptions,
8+
ChoiceSetDeleteByIdOptions,
79
ChoiceSetValueInsertOptions,
810
ChoiceSetValueInsertResponse,
9-
ChoiceSetValueUpdateResponse
11+
ChoiceSetValueUpdateOptions,
12+
ChoiceSetValueUpdateResponse,
13+
ChoiceSetValueDeleteOptions,
1014
} from './choicesets.types';
1115
import { PaginatedResponse, NonPaginatedResponse, HasPaginationOptions } from '../../utils/pagination/types';
1216

@@ -28,33 +32,32 @@ import { PaginatedResponse, NonPaginatedResponse, HasPaginationOptions } from '.
2832
*/
2933
export interface ChoiceSetServiceModel {
3034
/**
31-
* Gets all choice sets in the org
35+
* Gets choice sets in the tenant.
3236
*
37+
* Three call modes:
38+
* - `getAll()` — default. Returns only tenant-level choice sets.
39+
* - `getAll({ folderKey: "<uuid>" })` — preferred for folder-scoped data. Returns only choice sets in that folder.
40+
* - `getAll({ includeFolderChoiceSets: true })` — returns tenant-level **and** folder-level choice sets together. `folderKey` is preferred over `includeFolderChoiceSets` when both are set.
41+
*
42+
* @param options - Optional {@link ChoiceSetGetAllOptions} (`folderKey` to list a single folder's choice sets — preferred when scoping to a folder; `includeFolderChoiceSets: true` to list tenant + folder choice sets together) The `folderKey` property is **experimental**.
3343
* @returns Promise resolving to an array of choice set metadata
3444
* {@link ChoiceSetGetAllResponse}
3545
* @example
3646
* ```typescript
37-
* // Get all choice sets
38-
* const allChoiceSets = await choicesets.getAll();
47+
* // Tenant-only (default)
48+
* const tenantChoiceSets = await choicesets.getAll();
3949
*
40-
* // Iterate through choice sets
41-
* allChoiceSets.forEach(choiceSet => {
42-
* console.log(`ChoiceSet: ${choiceSet.displayName} (${choiceSet.name})`);
43-
* console.log(`Description: ${choiceSet.description}`);
44-
* console.log(`Created by: ${choiceSet.createdBy}`);
45-
* });
50+
* // A single folder's choice sets (preferred when targeting a specific folder)
51+
* const folderChoiceSets = await choicesets.getAll({ folderKey: "<folderKey>" });
4652
*
47-
* // Find a specific choice set by name
48-
* const expenseTypes = allChoiceSets.find(cs => cs.name === 'ExpenseTypes');
53+
* // Tenant + folder choice sets together
54+
* const allChoiceSets = await choicesets.getAll({ includeFolderChoiceSets: true });
4955
*
50-
* // Check choice set details
51-
* if (expenseTypes) {
52-
* console.log(`Last updated: ${expenseTypes.updatedTime}`);
53-
* console.log(`Updated by: ${expenseTypes.updatedBy}`);
54-
* }
56+
* // Find a specific choice set by name
57+
* const expenseTypes = tenantChoiceSets.find(cs => cs.name === 'ExpenseTypes');
5558
* ```
5659
*/
57-
getAll(): Promise<ChoiceSetGetAllResponse[]>;
60+
getAll(options?: ChoiceSetGetAllOptions): Promise<ChoiceSetGetAllResponse[]>;
5861

5962
/**
6063
* Gets choice set values by choice set ID with optional pagination
@@ -64,7 +67,7 @@ export interface ChoiceSetServiceModel {
6467
* - A PaginatedResponse with navigation cursors (when any pagination parameter is provided)
6568
*
6669
* @param choiceSetId - UUID of the choice set
67-
* @param options - Pagination options
70+
* @param options - Pagination options and optional `folderKey` (omit for tenant-level choice sets) The `folderKey` property is **experimental**.
6871
* @returns Promise resolving to choice set values or paginated result
6972
* {@link ChoiceSetGetResponse}
7073
* @example
@@ -89,6 +92,9 @@ export interface ChoiceSetServiceModel {
8992
* if (page1.hasNextPage) {
9093
* const page2 = await choicesets.getById(choiceSetId, { cursor: page1.nextCursor });
9194
* }
95+
*
96+
* // Folder-scoped choice set
97+
* const folderValues = await choicesets.getById(choiceSetId, { folderKey: "<folderKey>" });
9298
* ```
9399
*/
94100
getById<T extends ChoiceSetGetByIdOptions = ChoiceSetGetByIdOptions>(
@@ -106,7 +112,7 @@ export interface ChoiceSetServiceModel {
106112
* @param name - Choice set name. Must start with a
107113
* letter, may contain only letters, numbers, and underscores, length
108114
* 3–100 characters (e.g., `"expenseTypes"`).
109-
* @param options - Optional choice-set-level settings ({@link ChoiceSetCreateOptions})
115+
* @param options - Optional choice-set-level settings ({@link ChoiceSetCreateOptions}) The `folderKey` property is **experimental**.
110116
* @returns Promise resolving to the UUID of the created choice set
111117
*
112118
* @example
@@ -131,7 +137,7 @@ export interface ChoiceSetServiceModel {
131137
* the call throws `ValidationError` if both are omitted.
132138
*
133139
* @param choiceSetId - UUID of the choice set to update
134-
* @param options - Metadata fields to change ({@link ChoiceSetUpdateOptions})
140+
* @param options - Metadata fields to change ({@link ChoiceSetUpdateOptions}) The `folderKey` property is **experimental**.
135141
* @returns Promise resolving when the update is complete
136142
*
137143
* @example
@@ -153,6 +159,7 @@ export interface ChoiceSetServiceModel {
153159
* Deletes a Data Fabric choice set and all its values.
154160
*
155161
* @param choiceSetId - UUID of the choice set to delete
162+
* @param options - Optional {@link ChoiceSetDeleteByIdOptions} — pass `folderKey` for folder-scoped choice sets; omit for tenant-level The `folderKey` property is **experimental**.
156163
* @returns Promise resolving when the choice set is deleted
157164
*
158165
* @example
@@ -162,17 +169,20 @@ export interface ChoiceSetServiceModel {
162169
* const expenseTypes = allChoiceSets.find(cs => cs.name === 'expense_types');
163170
*
164171
* await choicesets.deleteById(expenseTypes.id);
172+
*
173+
* // Folder-scoped choice set
174+
* await choicesets.deleteById(expenseTypes.id, { folderKey: "<folderKey>" });
165175
* ```
166176
* @internal
167177
*/
168-
deleteById(choiceSetId: string): Promise<void>;
178+
deleteById(choiceSetId: string, options?: ChoiceSetDeleteByIdOptions): Promise<void>;
169179

170180
/**
171181
* Inserts a single value into a choice set.
172182
*
173183
* @param choiceSetId - UUID of the parent choice set
174184
* @param name - Identifier name of the new value (e.g., `"TRAVEL"`)
175-
* @param options - Optional fields ({@link ChoiceSetValueInsertOptions})
185+
* @param options - Optional fields ({@link ChoiceSetValueInsertOptions}) The `folderKey` property is **experimental**.
176186
* @returns Promise resolving to the inserted value ({@link ChoiceSetValueInsertResponse})
177187
*
178188
* @example
@@ -185,6 +195,12 @@ export interface ChoiceSetServiceModel {
185195
* displayName: 'Travel',
186196
* });
187197
* console.log(inserted.id);
198+
*
199+
* // Folder-scoped choice set: folderKey is required on the wire
200+
* await choicesets.insertValueById(expenseTypes.id, 'TRAVEL', {
201+
* displayName: 'Travel',
202+
* folderKey: "<folderKey>",
203+
* });
188204
* ```
189205
* @internal
190206
*/
@@ -203,6 +219,7 @@ export interface ChoiceSetServiceModel {
203219
* @param choiceSetId - UUID of the parent choice set
204220
* @param valueId - UUID of the value to update
205221
* @param displayName - New human-readable display name for the value
222+
* @param options - Optional {@link ChoiceSetValueUpdateOptions} — pass `folderKey` for folder-scoped choice sets; omit for tenant-level. The `folderKey` property is **experimental**.
206223
* @returns Promise resolving to the updated value ({@link ChoiceSetValueUpdateResponse})
207224
*
208225
* @example
@@ -214,20 +231,27 @@ export interface ChoiceSetServiceModel {
214231
* const travel = values.items.find(v => v.name === 'TRAVEL');
215232
*
216233
* await choicesets.updateValueById(expenseTypes.id, travel.id, 'Business Travel');
234+
*
235+
* // Folder-scoped choice set: folderKey is required on the wire
236+
* await choicesets.updateValueById(expenseTypes.id, travel.id, 'Business Travel', {
237+
* folderKey: "<folderKey>",
238+
* });
217239
* ```
218240
* @internal
219241
*/
220242
updateValueById(
221243
choiceSetId: string,
222244
valueId: string,
223245
displayName: string,
246+
options?: ChoiceSetValueUpdateOptions,
224247
): Promise<ChoiceSetValueUpdateResponse>;
225248

226249
/**
227250
* Deletes one or more values from a choice set.
228251
*
229252
* @param choiceSetId - UUID of the parent choice set
230253
* @param valueIds - Array of value UUIDs to delete
254+
* @param options - Optional {@link ChoiceSetValueDeleteOptions} — pass `folderKey` for folder-scoped choice sets; omit for tenant-level The `folderKey` property is **experimental**.
231255
* @returns Promise resolving when the values are deleted
232256
*
233257
* @example
@@ -237,9 +261,12 @@ export interface ChoiceSetServiceModel {
237261
* const idsToDelete = values.items.slice(0, 2).map(v => v.id);
238262
*
239263
* await choicesets.deleteValuesById('<choiceSetId>', idsToDelete);
264+
*
265+
* // Folder-scoped choice set
266+
* await choicesets.deleteValuesById('<choiceSetId>', idsToDelete, { folderKey: "<folderKey>" });
240267
* ```
241268
* @internal
242269
*/
243-
deleteValuesById(choiceSetId: string, valueIds: string[]): Promise<void>;
270+
deleteValuesById(choiceSetId: string, valueIds: string[], options?: ChoiceSetValueDeleteOptions): Promise<void>;
244271
}
245272

src/models/data-fabric/choicesets.types.ts

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { PaginationOptions } from '../../utils/pagination/types';
2+
import { EntityFolderScopedOptions } from './data-fabric.types';
23

34
/**
45
* ChoiceSet Get All Response
@@ -49,44 +50,59 @@ export interface ChoiceSetGetResponse {
4950
recordOwner?: string;
5051
}
5152

53+
export interface ChoiceSetGetAllOptions extends EntityFolderScopedOptions {
54+
/**
55+
* When `true`, also returns folder-level choice sets alongside tenant ones.
56+
* Omit (or `false`, the default) to return only tenant-level choice sets.
57+
* Ignored when `folderKey` is provided — `folderKey` is preferred over `includeFolderChoiceSets` when both are set.
58+
*
59+
* @experimental Folder-scoped Data Fabric is in preview — the contract may change.
60+
*/
61+
includeFolderChoiceSets?: boolean;
62+
}
63+
5264
/**
5365
* Options for getting choice set values by choice set ID
5466
*/
55-
export type ChoiceSetGetByIdOptions = PaginationOptions;
67+
export type ChoiceSetGetByIdOptions = PaginationOptions & EntityFolderScopedOptions;
5668

5769
/**
5870
* Options for creating a new choice set
5971
*/
60-
export interface ChoiceSetCreateOptions {
72+
export interface ChoiceSetCreateOptions extends EntityFolderScopedOptions {
6173
/** Human-readable display name */
6274
displayName?: string;
6375
/** Optional choice set description */
6476
description?: string;
65-
/** UUID of the folder to place the choice set in (defaults to the tenant-level folder) */
66-
folderKey?: string;
6777
}
6878

6979
/**
7080
* Options for updating an existing choice set's metadata
7181
*/
72-
export interface ChoiceSetUpdateOptions {
82+
export interface ChoiceSetUpdateOptions extends EntityFolderScopedOptions {
7383
/** New display name for the choice set */
7484
displayName?: string;
7585
/** New description for the choice set */
7686
description?: string;
7787
}
7888

89+
export interface ChoiceSetDeleteByIdOptions extends EntityFolderScopedOptions {}
90+
7991
/**
8092
* Optional fields when inserting a single value into a choice set.
8193
*
8294
* The required `name` identifier is passed as a positional argument to
8395
* `insertValueById`.
8496
*/
85-
export interface ChoiceSetValueInsertOptions {
97+
export interface ChoiceSetValueInsertOptions extends EntityFolderScopedOptions {
8698
/** Human-readable display name */
8799
displayName?: string;
88100
}
89101

102+
export interface ChoiceSetValueUpdateOptions extends EntityFolderScopedOptions {}
103+
104+
export interface ChoiceSetValueDeleteOptions extends EntityFolderScopedOptions {}
105+
90106
/**
91107
* Response returned after inserting a choice-set value — the full value object.
92108
*/
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/**
2+
* Shared types for the Data Fabric domain — used by both Entities and ChoiceSets.
3+
* Lives here (not in either service's `*.types.ts`) to avoid cross-domain coupling
4+
* between sibling services.
5+
*/
6+
7+
/**
8+
* Common shape for every folder-scoped Data Fabric operation.
9+
* Forwarded on the wire as the `X-UIPATH-FolderKey` header.
10+
*/
11+
export interface EntityFolderScopedOptions {
12+
/**
13+
* Key identifying the folder the entity belongs to. Omit for tenant-level entities.
14+
*
15+
* @experimental Folder-scoped Data Fabric is in preview — the contract may change.
16+
*/
17+
folderKey?: string;
18+
}

src/models/data-fabric/entities.constants.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { EntityFieldDataType, FieldDisplayType } from "./entities.types";
1+
import { EntityFieldDataType, EntityType, FieldDisplayType } from "./entities.types";
22
import {
33
EntitySchemaFieldMapping,
44
SqlFieldType,
@@ -7,6 +7,15 @@ import {
77
} from "./entities.internal-types";
88
export { SqlFieldType } from "./entities.internal-types";
99

10+
/**
11+
* Numeric type IDs that pair with {@link EntityType} on reference payloads
12+
* (entityType + entityTypeId travel together in `referenceEntity` /
13+
* `referenceChoiceSet` bodies on cross-folder schema upserts).
14+
*/
15+
export const ENTITY_TYPE_IDS = {
16+
[EntityType.ChoiceSet]: 1,
17+
} as const;
18+
1019
/**
1120
* Maps fields for Entities
1221
*/

src/models/data-fabric/entities.internal-types.ts

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { FieldDisplayType, EntityRecord, ReferenceType, SqlType } from './entities.types';
1+
import { EntityType, FieldDisplayType, EntityRecord, ReferenceType, SqlType } from './entities.types';
22

33
/**
44
* Write-side payload shape for creating a new field in a schema upsert call.
@@ -20,10 +20,25 @@ export interface FieldSchemaPayload {
2020
defaultValue?: string;
2121
choiceSetId?: string;
2222
referenceType?: ReferenceType;
23-
referenceEntity?: { id: string };
23+
referenceEntity?: ReferenceEntityPayload;
24+
referenceChoiceSet?: ReferenceEntityPayload;
2425
referenceField?: { id: string };
2526
}
2627

28+
/** Body embedded in `referenceEntity` / `referenceChoiceSet` on cross-folder field payloads. */
29+
export interface ReferenceEntityPayload {
30+
id: string;
31+
name?: string;
32+
folderId?: string;
33+
entityType?: EntityType;
34+
entityTypeId?: number;
35+
}
36+
37+
export interface ResolvedReferenceMeta {
38+
referenceEntity?: ReferenceEntityPayload;
39+
referenceChoiceSet?: ReferenceEntityPayload;
40+
}
41+
2742
/**
2843
* Shape of each entry in EntitySchemaFieldTypeMap — internal only.
2944
*/

0 commit comments

Comments
 (0)