Skip to content

feat(queues): add queue item operations [PLT-104203] - #643

Open
shivendra6720 wants to merge 3 commits into
mainfrom
feat/sdk-plt-104203
Open

feat(queues): add queue item operations [PLT-104203]#643
shivendra6720 wants to merge 3 commits into
mainfrom
feat/sdk-plt-104203

Conversation

@shivendra6720

@shivendra6720 shivendra6720 commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Method Added

Layer Method Signature
Service queues.getAllItems() getAllItems<T extends QueueGetAllItemsOptions>(queueId: number, folderId: number, options?: T): Promise<T extends HasPaginationOptions<T> ? PaginatedResponse<QueueItem> : NonPaginatedResponse<QueueItem>>
Service queues.insertItemByName() insertItemByName(queueName: string, folderId: number, specificData: Record<string, QueueItemValue>, options?: QueueInsertItemOptions): Promise<QueueItem>
Bound queue.getAllItems() getAllItems<T extends QueueGetAllItemsOptions>(options?: T): Promise<T extends HasPaginationOptions<T> ? PaginatedResponse<QueueItem> : NonPaginatedResponse<QueueItem>>
Bound queue.insertItem() insertItem(specificData: Record<string, QueueItemValue>, options?: QueueInsertItemOptions): Promise<QueueItem>

Queues now attach bound methods (QueueGetResponse = RawQueueGetResponse & QueueMethods, the Jobs/Entities compose pattern). The released QueueGetResponse name and all of its fields are preserved — existing consumers keep compiling; queue objects additionally carry the two bound methods.

Endpoint Called

Method HTTP Endpoint OAuth Scope
getAllItems() GET /orchestrator_/odata/QueueItems OR.Queues or OR.Queues.Read
insertItemByName() POST /orchestrator_/odata/Queues/UiPathODataSvc.AddQueueItem OR.Queues or OR.Queues.Write
  • Extends FolderScopedService — sets the X-UIPATH-OrganizationUnitId header from folderId
  • getAllItems supports OData pagination ($top, $skip, $count), filtering, and ordering; the queue scoping filter (queueId eq N) is merged with any caller filter, and SDK field names in filter/orderby/select are rewritten to API names before the request
  • Insert payloads are typed flat: Record<string, QueueItemValue> where QueueItemValue = string | number | boolean | Date | null | undefined — nested objects/arrays are rejected at compile time; Date values are serialized to ISO-8601
  • Required params are guarded with ValidationError before any HTTP call

Example Usage

import { UiPath } from '@uipath/uipath-typescript/core';
import { Queues, QueuePriority } from '@uipath/uipath-typescript/queues';

const sdk = new UiPath(config);
await sdk.initialize();
const queues = new Queues(sdk);

// List a queue's items
const items = await queues.getAllItems(<queueId>, <folderId>);

// Failed items only, newest first
const failed = await queues.getAllItems(<queueId>, <folderId>, {
  filter: "status eq 'Failed'",
  orderby: 'createdTime desc',
  pageSize: 25
});

// Insert an item
const item = await queues.insertItemByName('<queueName>', <folderId>, {
  invoiceId: 'INV-1001',
  amount: 1520
}, {
  priority: QueuePriority.High,
  reference: 'INV-1001',
  dueDate: new Date('2026-08-15')
});

// Or operate on a queue returned by getById/getAll
const queue = await queues.getById(<queueId>, <folderId>);
const queueItems = await queue.getAllItems();
const created = await queue.insertItem({ invoiceId: 'INV-1002', amount: 300 });

API Response vs SDK Response

Transform pipeline

extract user-payload objects (SpecificContent/Output) → drop their JSON-string duplicates (SpecificData/OutputData) → pascalToCamelCaseKeystransformData(QueueItemMap)transformData(QueueProcessingErrorMap) on the nested failure object → reattach payloads verbatim as specificData/outputData

Field mapping

API Response (PascalCase) SDK Response (camelCase) Change Reason
QueueDefinitionId queueId Case + Rename names the owning queue directly
CreationTime createdTime Case + Rename standard timestamp rename
OrganizationUnitId folderId Case + Rename standard folder rename
OrganizationUnitFullyQualifiedName folderName Case + Rename standard folder rename
StartProcessing processingStartTime Case + Rename *Time suffix convention for timestamps
EndProcessing processingEndTime Case + Rename *Time suffix convention for timestamps
ProcessingException processingError Case + Rename matches SDK error-field naming; nested CreationTimecreatedTime
SpecificContent specificData Rename only user-defined payload keys are never case-converted
Output outputData Rename only user-defined payload keys are never case-converted
SpecificData / OutputData Dropped JSON-string duplicates of the payload objects
Status, ReviewStatus, Priority status, reviewStatus, priority Case only typed as QueueItemStatus / QueueItemReviewStatus / QueuePriority enums (values verified against live swagger)
all remaining fields camelCase equivalents Case only

Sample SDK Response

insertItemByName() / queue.insertItem()
{
  "id": 22905684,
  "key": "62625516-227e-41cd-8e9b-43e6be405d5d",
  "status": "New",
  "reviewStatus": "None",
  "priority": "High",
  "queueId": 346714,
  "specificData": {
    "InvoiceId": "INV-1001",
    "amountDue": 1520,
    "Vendor_Name": "Acme"
  },
  "outputData": null,
  "processingError": null,
  "progress": null,
  "reference": "SDK-REF-001",
  "createdTime": "2026-08-03T16:20:00.603Z",
  "deferDate": "2026-08-03T00:00:00Z",
  "dueDate": "2026-08-15T00:00:00Z",
  "riskSlaDate": null,
  "processingStartTime": null,
  "processingEndTime": null,
  "retryNumber": 0,
  "folderId": 756377,
  "folderName": null
}

From live E2E on alpha — note the payload keys (InvoiceId, amountDue, Vendor_Name) returned exactly as provided, with no case conversion, and folderName: null — the insert response does not populate it (listing does), hence string | null.

getAllItems() / queue.getAllItems()
{
  "items": [
    {
      "id": 22905684,
      "key": "62625516-227e-41cd-8e9b-43e6be405d5d",
      "status": "New",
      "reviewStatus": "None",
      "priority": "High",
      "queueId": 346714,
      "specificData": { "InvoiceId": "INV-1001", "amountDue": 1520, "Vendor_Name": "Acme" },
      "outputData": null,
      "processingError": null,
      "reference": "SDK-REF-001",
      "createdTime": "2026-08-03T16:20:00.603Z",
      "processingStartTime": null,
      "processingEndTime": null,
      "retryNumber": 0,
      "folderId": 756377,
      "folderName": "APPS_TestPass_Folder"
    }
  ],
  "totalCount": 1
}

Truncated to 1 item — full response pages through the queue's items.

Files

Area Files
Endpoint src/utils/constants/endpoints/orchestrator.ts (GET_ITEMS, ADD_ITEM)
Types src/models/orchestrator/queues.types.ts (RawQueueGetResponse, QueueItem, QueueItemValue, QueueInsertItemOptions, QueueProcessingError, QueuePriority/QueueItemStatus/QueueItemReviewStatus/QueueExceptionType enums)
Constants src/models/orchestrator/queues.constants.ts (QueueItemMap, QueueProcessingErrorMap)
Models src/models/orchestrator/queues.models.ts (QueueGetResponse compose type, QueueServiceModel, QueueMethods, factories)
Service src/services/orchestrator/queues/queues.ts (getAllItems, insertItemByName, module-level toQueueItem)
Unit tests tests/unit/services/orchestrator/queues.test.ts (24), tests/unit/models/orchestrator/queues.test.ts (6)
Integration tests tests/integration/shared/orchestrator/queues.integration.test.ts (10 tests × v0/v1 modes; 20/20 passing live against alpha)
Test utils tests/utils/mocks/queues.ts, tests/utils/constants/queues.ts
CI .github/workflows/coverage.yml (QUEUES_TEST_QUEUE_NAME wiring), tests/integration/config/test-config.ts, tests/.env.integration.example
Docs docs/oauth-scopes.md, docs/pagination.md, agent_docs/conventions.md

Refs PLT-104203

🤖 Auto-generated using onboarding skills

@shivendra6720
shivendra6720 requested a review from a team August 5, 2026 11:23
@UiPath UiPath deleted a comment from github-actions Bot Aug 5, 2026
Comment thread src/models/orchestrator/queues.types.ts Outdated
Comment on lines +196 to +199
/** Timestamp when processing started (set once a transaction begins) */
startProcessing: string | null;
/** Timestamp when processing ended */
endProcessing: string | null;

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.

Convention violation: all timestamp fields in SDK response types must use the *Time suffix (rule: "NEVER introduce *At suffixes … *Time suffix").

startProcessing and endProcessing are timestamps but don't carry that suffix. They need to be renamed and a mapping entry added to QueueItemMap.

Suggested change
/** Timestamp when processing started (set once a transaction begins) */
startProcessing: string | null;
/** Timestamp when processing ended */
endProcessing: string | null;
/** Timestamp when processing started (set once a transaction begins) */
startProcessingTime: string | null;
/** Timestamp when processing ended */
endProcessingTime: string | null;

In queues.constants.ts, add the renames so the pipeline produces the right names:

startProcessing: 'startProcessingTime',
endProcessing: 'endProcessingTime',

The TransactionItemResponse JSDoc (line 210) references startProcessing by name — update that too.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

check what's better and consistent with the codebase. The above one or

startProcessing: 'processingStartTime',
endProcessing:   'processingEndTime'

Comment thread src/models/orchestrator/queues.types.ts Outdated
* (the item's data cannot be processed — not retried) from
* `ApplicationException` (a transient system error — eligible for retry).
*/
type?: 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.

Convention violation: "Use enums for fixed value sets — NEVER leave raw strings/numbers."

The JSDoc documents exactly two values (BusinessException / ApplicationException). That's a fixed set — it needs an enum.

Suggested change
type?: string;
type?: QueueExceptionType;

Add the enum near the other queue enums:

/**
 * Exception category for a queue processing failure.
 */
export enum QueueExceptionType {
  /** The item's data cannot be processed and will not be retried. */
  BusinessException = 'BusinessException',
  /** A transient system error; the item is eligible for retry. */
  ApplicationException = 'ApplicationException'
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@shivendra6720 check if this can be made an enum.

@shivendra6720 shivendra6720 changed the title feat(queues): add queue item and transaction operations [PLT-104203] feat([PLT-104203]): add queue item and transaction operations Aug 5, 2026
* @returns Promise resolving to either an array of queues NonPaginatedResponse<QueueGetResponse> or a PaginatedResponse<QueueGetResponse> when pagination options are used.
* {@link QueueGetResponse}
* @returns Promise resolving to either an array of queues NonPaginatedResponse<QueueWithMethods> or a PaginatedResponse<QueueWithMethods> when pagination options are used. Each queue has methods attached for operating on its items.
* {@link QueueWithMethods}

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.

Convention violation: "{@link} placed on a standalone line after @returns renders as stray text in TypeDoc, not a clickable link." The link must be embedded inline within the sentence.

Same pattern appears on lines 79, 101, 140, 190, 215, and 252 — all need fixing.

Suggested change
* {@link QueueWithMethods}
* @returns Promise resolving to either a {@link QueueWithMethods} array (`NonPaginatedResponse`) or a `PaginatedResponse<QueueWithMethods>` when pagination options are provided. Each queue has methods attached for operating on its items.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@shivendra6720 let's keep the link inline. Check this elsewhere in the file as well.

Comment thread src/models/orchestrator/queues.types.ts Outdated
Comment on lines +217 to +222
export interface TransactionCompletionOptions {
/**
* True when the item was processed successfully; false records a failure
* (provide `processingException` with the failure details).
*/
isSuccessful: boolean;

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.

Convention violation: "{Entity}{Operation}Options — bag of optional fields … Contains only optional fields." isSuccessful: boolean is required, which disqualifies the Options suffix.

Per the rules, 1–3 required params stay positional. Since only isSuccessful is required, extract it as a positional argument and rename the bag to hold only optional fields:

// queues.types.ts
export interface TransactionCompletionRequest {
  processingException?: QueueProcessingException;
  deferDate?: Date;
  dueDate?: Date;
  outputData?: Record<string, unknown>;
  analytics?: Record<string, unknown>;
  progress?: string;
  operationId?: string;
}

The service/model signatures then become:

completeTransaction(itemId: number, folderId: number, isSuccessful: boolean, options?: TransactionCompletionRequest): Promise<OperationResponse<TransactionCompletionRequest>>;
// bound variant
completeTransaction(itemId: number, isSuccessful: boolean, options?: TransactionCompletionRequest): Promise<OperationResponse<TransactionCompletionRequest>>;

Update the service implementation, model factory delegate, JSDoc examples, and tests accordingly.

@claude

claude Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Review findings

Four CLAUDE.md convention violations across the new queue-item types:

New inline comments this run

  1. startProcessing / endProcessing field namesqueues.types.ts:196-199
    All timestamp fields must carry a *Time suffix. Both fields need renaming (startProcessingTime, endProcessingTime) plus two entries in QueueItemMap to drive the rename through the transform pipeline.

  2. QueueProcessingException.type typed as stringqueues.types.ts:132
    Orchestrator documents exactly two values (BusinessException / ApplicationException). Fixed sets must be enums — never raw strings.

  3. {@link} on a standalone line in every @returnsqueues.models.ts:36 (and lines 79, 101, 140, 190, 215, 252)
    TypeDoc renders a bare {@link} after @returns as stray text, not a clickable link. It must be embedded inline inside the @returns sentence.

  4. TransactionCompletionOptions has a required fieldqueues.types.ts:217-222
    Options types must contain only optional fields. isSuccessful: boolean is required, so it breaks the naming contract. Per convention, 1–3 required params stay positional — extract isSuccessful as a positional arg and rename the bag (e.g. TransactionCompletionRequest for the optional remainder).

Adds getAllItems and insertItemByName, and attaches queue-bound
equivalents to the objects returned by getAll/getById following the Data
Fabric entities pattern.

User-defined payload keys in specificData/outputData are preserved
exactly; the JSON-string wire forms surface as specificDataJson /
outputDataJson.

Transaction operations (startTransaction / completeTransaction) follow in
a separate PR stacked on this one.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@shivendra6720 shivendra6720 changed the title feat([PLT-104203]): add queue item and transaction operations feat(queues): add queue item operations [PLT-104203] Aug 5, 2026
@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor
PR Preview Action v1.8.1

QR code for preview link

🚀 View preview at
https://UiPath.github.io/uipath-typescript/pr-preview/pr-643/

Built to branch gh-pages at 2026-08-09 15:42 UTC.
Preview will be ready when the GitHub Pages deployment is complete.

Comment thread src/models/orchestrator/queues.types.ts Outdated
/** Current processing status */
status: QueueItemStatus;
/** Review status for failed items */
reviewStatus: 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.

Convention violation: "Use enums for fixed value sets — NEVER leave raw strings/numbers."

reviewStatus has a fixed set of values in Orchestrator (None, Approved, Rejected, RetryPending). It must be an enum, the same way QueueItemStatus was correctly enumerated in this same PR.

Suggested change
reviewStatus: string;
reviewStatus: QueueItemReviewStatus;

Add the enum alongside QueueItemStatus:

/**
 * Review status of a failed queue item.
 */
export enum QueueItemReviewStatus {
  /** No review has been assigned */
  None = 'None',
  /** Item approved after review */
  Approved = 'Approved',
  /** Item rejected after review */
  Rejected = 'Rejected',
  /** Item marked for retry after review */
  RetryPending = 'RetryPending'
}

Also update createBasicQueueItem() in the mock and ITEM_REVIEW_STATUS in test constants to use the enum value.

// arbitrary queues.
describe('Queue items and transactions', () => {
/** Resolves the dedicated test queue, throwing when preconditions are unmet. */
async function getTestQueue() {

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.

Convention violation: "Extract shared data lookups to beforeAll in integration tests — when multiple tests in a describe block need the same setup data … fetch it once in beforeAll and store in a let variable!: Type variable. Repeating getAll or equivalent calls inside each it block wastes API quota and slows the suite."

getTestQueue() is called on lines 156, 194, 223, and 239 — four redundant API calls per run. The queue doesn't change between tests; fetch it once:

describe('Queue items and transactions', () => {
  let testQueue!: QueueWithMethods;

  beforeAll(async () => {
    const { queues } = getServices();
    const config = getTestConfig();

    if (!config.folderId) {
      throw new Error('INTEGRATION_TEST_FOLDER_ID must be configured for queue item tests');
    }
    if (!config.queuesTestQueueName) {
      throw new Error('QUEUES_TEST_QUEUE_NAME must be configured for queue item tests');
    }

    const folderId = Number(config.folderId);
    const result = await queues.getAll({
      folderId,
      filter: `name eq '${config.queuesTestQueueName}'`,
    });

    if (result.items.length === 0) {
      throw new Error(
        `Queue "${config.queuesTestQueueName}" was not found in folder ${folderId} — create it before running queue item tests`
      );
    }

    testQueue = result.items[0];
  });

  it('should insert an item …', async () => {
    const item = await testQueue.insertItem(payload, options);
    // …
  });
  // … other tests use testQueue directly

Remove the async function getTestQueue() helper entirely.

@claude

claude Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Review findings

Two new CLAUDE.md convention violations in addition to the four already flagged in open threads:

  1. reviewStatus typed as stringqueues.types.ts:155
    Orchestrator's queue item review status is a fixed value set (None, Approved, Rejected, RetryPending). Must be an enum — same rule that the open thread at line 132 applies to QueueProcessingException.type.

  2. getTestQueue() called in each test body instead of beforeAllqueues.integration.test.ts:129
    The helper is called 4 times (lines 156, 194, 223, 239), making 4 redundant API calls per run. Convention requires shared data lookups to be extracted into beforeAll with a let testQueue!: QueueWithMethods variable.

@swati354
swati354 self-requested a review August 6, 2026 16:24
* `Output`) are handled separately by the service — they are excluded from
* case conversion entirely (their keys are user-defined) and reattached as
* `specificData` / `outputData`. The JSON-string wire fields are renamed to
* explicit `*Json` names so both representations stay available.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Keep inline code comments concise.

/**
* Queue metadata combined with queue-bound helper methods.
*/
export type QueueWithMethods = QueueGetResponse & QueueMethods;

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The compose type should be called QueueGetResponse, not QueueWithMethods
We can rename the raw shape in queues.types.ts to RawQueueGetResponse and define QueueGetResponse = RawQueueGetResponse & QueueMethods here.
Examples -

export type JobGetResponse = RawJobGetResponse & JobMethods;

export type EntityGetResponse = RawEntityGetResponse & EntityMethods;

* @returns Promise resolving to either an array of queues NonPaginatedResponse<QueueGetResponse> or a PaginatedResponse<QueueGetResponse> when pagination options are used.
* {@link QueueGetResponse}
* @returns Promise resolving to either an array of queues NonPaginatedResponse<QueueWithMethods> or a PaginatedResponse<QueueWithMethods> when pagination options are used. Each queue has methods attached for operating on its items.
* {@link QueueWithMethods}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

@shivendra6720 let's keep the link inline. Check this elsewhere in the file as well.

Comment on lines 80 to +85
* const queue = await queues.getById(<queueId>, <folderId>);
*
* // Operate on the queue directly via the attached methods
* const items = await queue.getAllItems();
* ```
*/

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

can we add a insertItem example as well?

Comment on lines +101 to +102
* // First, get queues with queues.getAll()
* const items = await queues.getAllItems(<queueId>, <folderId>);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Users won't use queues.getAllItems(<queueId>, <folderId>); on an array of queues returned. hence the comment above(first, get queues with queues.getAll()) is misleading.
Keep two examples, the one above after dropping the ask to fetch all queues and one which shows this method bounded to a queue returned by getById or getAll.
(keep the failed items example as is - thats fine)

Comment on lines +130 to +133
queueName: string,
folderId: number,
specificData: Record<string, unknown>,
options: QueueInsertItemOptions = {}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

check if we put validation errors for required fields. if we do, add them for both getAllItems and insertItemByName

const apiOptions = addPrefixToKeys(apiFieldOptions, ODATA_PREFIX, Object.keys(apiFieldOptions));

const response = await this.get<QueueGetResponse>(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

once we define RawQueueGetResponse, this would change to this.get<RawQueueGetResponse>

Comment on lines +162 to +169
private transformQueue(queue: object): QueueWithMethods {
const transformedQueue = transformData(
pascalToCamelCaseKeys(queue) as QueueGetResponse,
QueueMap
) as QueueGetResponse;

return createQueueWithMethods(transformedQueue, this);
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

do we need a separate method for this. It's a 2 line pipeline that I think other services write inline.

const transformJobResponse = (job: Record<string, unknown>) => {

Comment on lines +135 to +143
const itemData = camelToPascalCaseKeys({
priority: options.priority ?? QueuePriority.Normal,
reference: options.reference,
progress: options.progress,
deferDate: toIsoString(options.deferDate),
dueDate: toIsoString(options.dueDate),
riskSlaDate: toIsoString(options.riskSlaDate),
name: queueName
});

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

if its just specific fields we want to case, wouldn't it be better to

const response = await this.post<RawQueueItem>(
    QUEUE_ENDPOINTS.ADD_ITEM,
    {
      itemData: {
        Name:            queueName,
        Priority:        options.priority ?? QueuePriority.Normal,
        Reference:       options.reference,
        Progress:        options.progress,
        DeferDate:       toIsoString(options.deferDate),
        DueDate:         toIsoString(options.dueDate),
        RiskSlaDate:     toIsoString(options.riskSlaDate),
        // User-defined keys — sent exactly as provided, no case conversion
        SpecificContent: specificData,
      },
    },
    { headers: createHeaders({ [FOLDER_ID]: folderId }) },
  );

name: queueName
});

const response = await this.post<object>(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

check if we can have something like RawQueueItem. If not then even Record<string, unknown> is better than passing object.

Reworks the queue-item surface per review:

- rename QueueWithMethods -> QueueGetResponse (= RawQueueGetResponse &
  QueueMethods, the jobs/entities compose pattern) and
  QueueItemResponse -> QueueItem; the released QueueGetResponse name and
  its fields are preserved for existing consumers
- enums for fixed value sets: QueueItemReviewStatus (None/InReview/
  Verified/Retried) and QueueExceptionType (ApplicationException/
  BusinessException), both verified against the live swagger
- processingException -> processingError (QueueProcessingError), with
  the nested creationTime renamed to createdTime via
  QueueProcessingErrorMap; startProcessing/endProcessing ->
  processingStartTime/processingEndTime; folderId/folderName required
- drop the specificDataJson/outputDataJson duplicates; the payload
  objects (SpecificContent/Output) remain the single representation
- enforce flat insert payloads in the type system via QueueItemValue
  (string | number | boolean | Date | null | undefined)
- ValidationError guards on getAllItems/insertItemByName required params
- inline the queue transform (jobs pattern); module-level toQueueItem
  shared by list + insert; explicit PascalCase itemData body
- JSDoc: inline {@link} in @returns, bound-usage examples, insertItem
  example on getById, backend wording removed; factory delegates are
  async with explicit return types
- integration tests resolve the test queue once in beforeAll; unit
  tests cover the new enums, dropped fields, nested error rename, and
  validation guards

Verified: typecheck, lint, 2171 unit tests, 20/20 live integration
against alpha.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

await expect(queue.getAllItems()).rejects.toThrow('Queue ID is undefined');
expect(mockService.getAllItems).not.toHaveBeenCalled();
});

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.

Missing test for the symmetric folderId === undefined guard. createQueueMethods.getAllItems has two pre-condition checks (id === undefined and folderId === undefined), but only the first is exercised here — a regression removing the second check would go undetected.

Convention: "Test all meaningful branches for boolean-like conditions — when a method branches on param === false vs other values, add explicit tests for true, false, and undefined."

Suggested change
});
await expect(queue.getAllItems()).rejects.toThrow('Queue ID is undefined');
expect(mockService.getAllItems).not.toHaveBeenCalled();
});
it('should reject when the folder ID is undefined', async () => {
const queueData = createBasicQueue({ folderId: undefined as unknown as number });
const queue = createQueueWithMethods(queueData, mockService);
await expect(queue.getAllItems()).rejects.toThrow('Folder ID is undefined');
expect(mockService.getAllItems).not.toHaveBeenCalled();
});

@claude

claude Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

Review findings

New inline comment this run

Missing error test for folderId === undefined in queue.getAllItems() model teststests/unit/models/orchestrator/queues.test.ts:61

createQueueMethods.getAllItems has two pre-condition guards (id === undefined and folderId === undefined), but the describe block only tests the first. Removing the second guard would go undetected. Suggestion added to include the symmetric test.

Live browser E2E against alpha showed AddQueueItem returns
OrganizationUnitFullyQualifiedName as null — only the listing endpoint
populates it. QueueItem.folderName is therefore string | null, and the
insert integration test pins the null so a future API change surfaces.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@claude

claude Bot commented Aug 9, 2026

Copy link
Copy Markdown
Contributor

✅ No issues found. Checked for bugs and CLAUDE.md compliance.

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.

2 participants