Skip to content

feat(orchestrator): getByName for Assets + Processes, encoded folder header, meta-tag fallback [PLT-92768]#381

Draft
deepeshrai-tech wants to merge 5 commits into
mainfrom
feat/asset-get-by-name
Draft

feat(orchestrator): getByName for Assets + Processes, encoded folder header, meta-tag fallback [PLT-92768]#381
deepeshrai-tech wants to merge 5 commits into
mainfrom
feat/asset-get-by-name

Conversation

@deepeshrai-tech

@deepeshrai-tech deepeshrai-tech commented Apr 20, 2026

Copy link
Copy Markdown
Contributor

Summary

Prerequisite SDK work for the coded-apps bindings/overwrites initiative (PLT-92768 / PLT-93599). Adds name-based resource lookup for two Orchestrator services and wires the folder-context plumbing that the runtime overwrite flow depends on.

  • assets.getByName(name, { folderPath?, folderKey? }) — OData $filter=Name eq '…' + $top=1 on the folder-scoped endpoint.
  • processes.getByName(name, { folderPath?, folderKey? }) — same shape against /odata/Releases.
  • X-UIPATH-FolderPath-Encoded replaces the raw X-UIPATH-FolderPath header (OR team's recommendation; URL-encoded transport is safer for special characters in paths). Both folderPath and folderKey are accepted simultaneously — OR's middleware prefers folderPath.
  • Init-time folder context via meta tags. The SDK now reads <meta name="uipath:folder-key"> (auto-injected by jamjam on coded-app deployments) and uses it as the default folder context when the caller doesn't pass one. Resolution chain: call-site args > new UiPath({ folderKey }) > meta tag > no folder header.
  • Input validation + better not-found errors. New utils/validation/name-validator.ts throws ValidationError with descriptive messages for non-string names, empty names, and non-string folder fields — the guard TS types can't enforce for JS callers. Not-found errors now include the folder context (path or key) to make debugging easier

Usage

import { Assets } from '@uipath/uipath-typescript/assets';
import { Processes } from '@uipath/uipath-typescript/processes';

const assets = new Assets(sdk);
const processes = new Processes(sdk);

// Call-site wins
const a = await assets.getByName('ApiKey', { folderPath: 'Shared/Finance' });
const b = await assets.getByName('ApiKey', { folderKey: 'bc2d…' });

// Folder resolved from <meta name="uipath:folder-key"> 
const c = await assets.getByName('ApiKey');

// Same semantics for processes
const p = await processes.getByName('MyProcess', { folderPath: 'Shared/Finance' });

Not-done / follow-ups

  • Unit + integration tests for getByName (this PR is a draft for visual verification first)
  • docs/oauth-scopes.md update
  • Same getByName on Buckets / Queues — tracked separately
Screen.Recording.2026-04-21.at.5.57.59.PM.mov

…[PLT-92768]

Adds assets.getByName(name, { folderPath?, folderKey? }) — resolves a single
asset by name, scoped via X-UIPATH-FolderPath / X-UIPATH-FolderKey headers
(server-side folder resolution, no client-side ID lookup needed). Either
or both may be provided; Orchestrator middleware prefers folderPath when
both are sent.

Prerequisite for the coded-apps bindings/overwrites work — SDK now has
the name-based lookup that uipath.json runtime overwrites need.

Also adds samples/asset-by-name-app — React + Vite demo of OAuth login,
folder-scoped asset listing, and getByName invocation with the JSON response
rendered in-page.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Comment thread src/models/orchestrator/assets.types.ts Outdated
Comment on lines +76 to +85
/**
* Folder path to scope the asset lookup (e.g. 'Shared/Finance').
* Mutually exclusive with folderKey.
*/
folderPath?: string;
/**
* Folder key (GUID) to scope the asset lookup.
* Mutually exclusive with folderPath.
*/
folderKey?: string;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "Mutually exclusive" wording conflicts with the implementation and the PR description.

The PR description says: "Both folderPath and folderKey are accepted; Orchestrator middleware prefers folderPath when both are sent, so the SDK passes them straight through." The getByName implementation confirms this — it calls createHeaders({ [FOLDER_PATH]: folderPath, [FOLDER_KEY]: folderKey }) and sends whatever is non-undefined.

Calling them mutually exclusive tells users one of them will be ignored or that passing both is invalid, when it's actually valid (and the server's preference behaviour is the documented tie-breaker).

Suggested replacement:

Suggested change
/**
* Folder path to scope the asset lookup (e.g. 'Shared/Finance').
* Mutually exclusive with folderKey.
*/
folderPath?: string;
/**
* Folder key (GUID) to scope the asset lookup.
* Mutually exclusive with folderPath.
*/
folderKey?: string;
export interface AssetGetByNameOptions extends BaseOptions {
/**
* Folder path to scope the asset lookup (e.g. 'Shared/Finance').
* Sent as the `X-UIPATH-FolderPath` header. When provided alongside
* `folderKey`, the server prefers `folderPath`.
*/
folderPath?: string;
/**
* Folder key (GUID) to scope the asset lookup.
* Sent as the `X-UIPATH-FolderKey` header. When provided alongside
* `folderPath`, the server prefers `folderPath`.
*/
folderKey?: string;
}

* const asset = await assets.getByName('ApiKey');
* ```
*/
@track('Assets.GetByName')

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per the post-implementation checklist in agent_docs/rules.md, every public method requires unit tests (success + error paths) and an integration test in tests/integration/shared/orchestrator/ before merging.

The "Not-done list" in the PR description calls these out explicitly — flagging here so this doesn't slip through on merge. Minimum needed:

Unit tests (tests/unit/services/orchestrator/assets.test.ts):

  • getByName returns a transformed asset when the OData response has one item
  • getByName throws NotFoundError when the value array is empty
  • getByName sends X-UIPATH-FolderPath / X-UIPATH-FolderKey headers (only those provided)
  • getByName OData-escapes single quotes in the name (Name eq 'O''Brien')

Integration test (tests/integration/shared/orchestrator/assets.test.ts):

  • getByName resolves an existing asset by name + folderPath
  • transform validation: camelCase fields present, PascalCase originals absent

name: asset.name,
folderPath: folder.fullyQualifiedName || folder.displayName,
folderKey: folder.key,
valueType: asset.valueType as unknown as string,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

as unknown as string is explicitly banned by conventions.md ("NEVER use as unknown as type casts — refactor to make types flow naturally"). Sample apps are part of the repo and set the example for SDK consumers.

asset.valueType is AssetValueType (a string enum), so it already is a string at runtime. The fix is to widen the AssetRow.valueType field type to AssetValueType (preferred, preserves autocomplete) or cast with the direct widening asset.valueType as string which TypeScript allows between a string enum and string without the double cast:

Suggested change
valueType: asset.valueType as unknown as string,
valueType: asset.valueType,

and change AssetRow.valueType from string to AssetValueType.

@claude

claude Bot commented Apr 20, 2026

Copy link
Copy Markdown
Contributor

Review summary — 3 new findings

1. Doc inaccuracy in AssetGetByNameOptions (assets.types.ts L76–85)
The JSDoc calls folderPath and folderKey mutually exclusive, but both headers are forwarded and the server simply prefers folderPath when both are present. Suggested fix is in the inline comment.

2. Missing unit and integration tests (assets.ts L147)
Required by the checklist before merging. Inline comment lists the specific cases: empty-result NotFoundError path, header forwarding, OData quote-escaping, and transform validation.

3. Banned double cast in sample code (AssetList.tsx L76)
Conventions prohibit this pattern. Since AssetValueType is a string enum, changing AssetRow.valueType to AssetValueType removes the need for any cast.

… meta-tag fallback [PLT-92768]

Builds on the assets.getByName work with parity for Processes plus three
refinements the OR team + APPS team aligned on:

- Switched folder-path header to X-UIPATH-FolderPath-Encoded (URL-encoded
  value) per OR's recommendation for safe transport of special characters.
  FOLDER_PATH constant dropped from headers.ts — encoded form only.

- Added init-time folderKey fallback. The SDK now reads
  <meta name="uipath:folder-key"> (injected automatically by jamjam on
  coded-app deployments) and uses it as the default folder context for
  getByName calls that don't pass folderPath/folderKey at the call site.
  Chain: call-site args > SDK init config > meta tag > no folder. Config
  flows through BaseConfig -> UiPathConfig -> BaseService.config so
  services can read it.

- Added input validation at the SDK boundary. New
  utils/validation/name-validator.ts rejects non-string names, empty
  names, and non-string folder fields with ValidationError carrying
  descriptive messages. Not-found errors now include the folder context
  (path or key) to help debugging. JS callers get the runtime guard that
  TS types alone can't enforce.

Sample app (asset-by-name-app) reorganized with per-resource folders:
Assets | Processes tab nav, shared GetByNameForm component, and a
Processes list + form exercising the new method. Sample's scope in
.env.example bumped to include OR.Execution.Read. A demo folder-key
meta tag added to index.html so the tier-3 fallback can be verified
in the browser without redeploying.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@deepeshrai-tech deepeshrai-tech changed the title feat(assets): add getByName with folderPath/folderKey support [PLT-92768] feat(orchestrator): getByName for Assets + Processes, encoded folder header, meta-tag fallback [PLT-92768] Apr 21, 2026
deepeshrai-tech and others added 3 commits April 27, 2026 10:43
…eader [PLT-92768]

Adds parity Buckets.getByName(name, { folderPath?, folderKey? }) following
the same shape as Assets/Processes (validator + encoded folder header +
init-time folderKey fallback).

Critical fix: the X-UIPATH-FolderPath-Encoded header was using
encodeURIComponent (URL-encoded UTF-8) — but Orchestrator decodes this
header as base64 of UTF-16 LE bytes (Encoding.Unicode in
HttpHeadersProviderExtensions.GetDecoded). The mismatch caused malformed
folder paths to be silently rejected; Assets and Processes appeared to
work because their controllers fall back to other folder-resolution
sources (cookies/query/session). Buckets controller has stricter
[RequireOrganizationUnit] enforcement which surfaced the bug.

Added utils/encoding/folder-path.ts with the correct UTF-16-LE + Base64
encoder, applied across all three services. Encoder mirrors the reference
implementation in the Orchestrator perf-test repo
(performance/framework-modules/test-utils.ts).

Sample app gains a Buckets tab with the same list + getByName pattern.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…art B2 options shape [PLT-92768]

Mirrors the refactor that landed on feat/resources-get-by-name (PR #386):

- Adds shared FolderScopedOptions to common/types.ts
- Extracts FolderScopedService.getByNameLookup<TRaw, T>() — handles
  validation, encoding, header construction, OData filter, NotFoundError —
  so each service's getByName collapses to an 8-line wrapper
- AssetGetByNameOptions / ProcessGetByNameOptions / BucketGetByNameOptions
  now extend FolderScopedOptions
- ProcessService now extends FolderScopedService (was BaseService)

processes.start refactored to the B2 options shape:

- New ProcessStartOptions extends RequestOptions with folderId/folderPath/folderKey
- start(request, options?: ProcessStartOptions) is the new preferred shape
- Legacy positional start(request, folderId: number, options?) still works —
  runtime-branched on typeof second arg, so existing callers and the 1152
  unit tests keep passing
- Folder context resolved per request: folderId → X-UIPATH-OrganizationUnitId,
  folderPath → X-UIPATH-FolderPath-Encoded, folderKey → X-UIPATH-FolderKey
- Falls back to init-time config.folderKey (uipath:folder-key meta tag) only
  when no folder context is supplied

Sample app: Processes tab now exposes two start buttons per row —
"Start (path)" and "Start (key)" — exercising each folder header
independently. Lets reviewers verify both code paths in the Network tab.

.env.example bumped to OR.Execution + OR.Jobs scopes (write access required
for processes.start).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds maestroProcesses.getByName(name, options?) and cases.getByName(name, options?) — client-side filter over getAll() because Maestro's /processes/summary endpoint has no name-based lookup or filter parameters (verified via uipcli/packages/maestro-sdk and maestro-tool).

Both methods accept { folderPath?, folderKey? } for API parity with Orchestrator services. folderPath is matched client-side against the folderName field returned by Maestro; folderKey matches folderKey. When neither is supplied, falls back to init-time folderKey (e.g. uipath:folder-key meta tag) — same chain as processes.getByName and buckets.getByName. Throws ValidationError on bad input and NotFoundError when no record matches.

Also adds Maestro processes + Cases tabs to samples/asset-by-name-app for live verification: list view, click-to-prefill row, getByName invocation with the JSON response rendered in-page.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@sonarqubecloud

Copy link
Copy Markdown

Quality Gate Failed Quality Gate failed

Failed conditions
10.8% Duplication on New Code (required ≤ 3%)
C Reliability Rating on New Code (required ≥ A)

See analysis details on SonarQube Cloud

Catch issues before they fail your Quality Gate with our IDE extension SonarQube for IDE

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant