Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion src/models/data-fabric/entities.constants.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { EntityFieldDataType, EntityType, FieldDisplayType } from "./entities.types";
import { EntityClass, EntityFieldDataType, EntityType, FieldDisplayType } from "./entities.types";
import {
EntityClassId,
EntitySchemaFieldMapping,
SqlFieldType,
EntityFieldConstraint,
Expand Down Expand Up @@ -162,3 +163,13 @@ export const EntityFieldTypeMap: Record<SqlFieldType, EntityFieldDataType> = {
[SqlFieldType.MULTILINE]: EntityFieldDataType.MULTILINE_TEXT,
[SqlFieldType.MULTILINE_MAX]: EntityFieldDataType.MULTILINE_MAX,
};

/**
* Maps the user-facing {@link EntityClass} to the numeric `entityClassId` the v3
* create endpoint expects. Only the two user-creatable classes are listed; any other
* value is rejected by `create()`.
*/
export const EntityClassToIdMap: Partial<Record<EntityClass, EntityClassId>> = {
[EntityClass.Native]: EntityClassId.Native,
[EntityClass.Federated]: EntityClassId.Federated,
};
33 changes: 32 additions & 1 deletion src/models/data-fabric/entities.internal-types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
import { EntityType, FieldDisplayType, EntityRecord, ReferenceType, SqlType } from './entities.types';
import { EntityType, FieldDisplayType, EntityRecord, ReferenceType, SqlType, EntityUpdateByIdOptions } from './entities.types';

/**
* Numeric v3 entity-class discriminator sent on create as
* `entityDefinition.entityClassId`. Wire-format counterpart of {@link EntityClass};
* internal — consumers pass {@link EntityClass} and the SDK translates via `EntityClassToIdMap`.
*/
export enum EntityClassId {
/** Native entity — data fully stored and managed within UiPath */
Native = 9,
/** Federated entity — unified read-only view across UiPath and external sources */
Federated = 10,
}

/**
* Write-side payload shape for creating a new field in a schema upsert call.
Expand Down Expand Up @@ -65,6 +77,25 @@ export interface EntityJoinPayload {
on: { left: string; right: string };
}

/** Wire-ready Federated parts produced by `buildFederatedUpsertParts`. */
export interface FederatedUpsertParts {
externalFields: Array<Record<string, unknown>>;
sourceJoinConditionDetails?: Array<Record<string, unknown>>;
entityClassId?: number;
}

/** The Federated source/join delta fields of `EntityUpdateByIdOptions`. */
export type FederatedUpdateDeltas = Pick<
EntityUpdateByIdOptions,
| 'addExternalSources'
| 'removeExternalSources'
| 'addFieldsToSource'
| 'removeFieldsFromSource'
| 'updateExternalFieldMapping'
| 'addSourceJoins'
| 'updateSourceJoin'
>;

/**
* Names of the per-field SQL constraint properties (i.e. the contents of `sqlType`
* excluding its `name`). Used internally to validate user-supplied constraints
Expand Down
57 changes: 54 additions & 3 deletions src/models/data-fabric/entities.models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -983,7 +983,7 @@ export interface EntityServiceModel {
* @returns Promise resolving to the ID of the created entity
* @example
* ```typescript
* import { Entities } from '@uipath/uipath-typescript/entities';
* import { Entities, EntityClass, DataDirectionType, EntityFieldDataType, JoinType } from '@uipath/uipath-typescript/entities';
*
* const entities = new Entities(sdk);
*
Expand Down Expand Up @@ -1016,6 +1016,26 @@ export interface EntityServiceModel {
* // referenceFolderKey omitted → SDK looks up the target at tenant scope
* },
* ], { folderKey: "<sourceFolderKey>" });
*
* // Federated entity — a read-only view over external and/or native sources.
* // Native columns stay empty ([]); the schema comes from `externalFields`.
* await entities.create("<entityName>", [], {
* entityClass: EntityClass.Federated,

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 conventions, @example blocks must be self-contained and copy-pasteable — every named type they reference needs to appear in the import statement. The import at the top of this block (earlier in the same ```typescript fence) is:

import { Entities } from '@uipath/uipath-typescript/entities';

This PR introduces EntityClass (here) and DataDirectionType (used a few lines below) without adding them to that import. EntityFieldDataType was also already missing pre-PR. The import should become:

import { Entities, EntityClass, DataDirectionType, EntityFieldDataType } from '@uipath/uipath-typescript/entities';

The same issue applies to the updateById example block, which uses DataDirectionType.ReadOnly and JoinType.LeftJoin in the new Federated examples but has no import statement at all in that block.

* externalFields: [{
* externalConnectionDetail: {
* connectionId: "<connectionId>", connectorKey: "<connectorKey>", connectorName: "<connectorName>",
* elementInstanceId: 0, folderKey: "<folderKey>",
* },
* externalObjectDetail: { externalObjectName: "<objectName>", primaryKey: "<primaryKeyField>", isPrimarySource: true, method: "<operationsCatalogJson>" },
* fields: [{
* field: { name: "<internalFieldName>", type: EntityFieldDataType.STRING },
* externalFieldMappingDetail: { externalFieldName: "<externalFieldName>", directionType: DataDirectionType.ReadOnly },
* }],
* }],
* // Multi-source: add more entries to `externalFields` and join them:
* // sourceJoinConditionDetails: [{ sourceObjectName: "<objectName>", sourceJoinField: "<externalFieldName>",
* // joinType: JoinType.LeftJoin, relatedSourceObjectName: "<relatedObjectName>", relatedSourceJoinField: "<relatedExternalFieldName>" }],
* });
* ```
* @experimental
*/
Expand Down Expand Up @@ -1045,12 +1065,20 @@ export interface EntityServiceModel {
* metadata fields (`displayName`, `description`, `isRbacEnabled`). Each group is applied
* only when the corresponding fields are provided.
*
* For **Federated** entities, pass source/join deltas instead: `addExternalSources`,
* `removeExternalSources` (also removes that source's joins), `addFieldsToSource`,
* `removeFieldsFromSource`, `updateExternalFieldMapping`, `addSourceJoins`, and
* `updateSourceJoin`. `addFieldsToSource` maps a field that already exists on the source
* (a native entity's column or a connector field); it does not create the underlying field.
*
* @param id - UUID of the entity to update
* @param options - Changes to apply ({@link EntityUpdateByIdOptions}). At least one of `addFields`, `removeFields`, `updateFields`, `displayName`, `description`, or `isRbacEnabled` must be provided — calling with no options, `{}`, or only `folderKey` throws a `ValidationError`. Field names passed in `addFields[].name` and `removeFields[].name` must be camelCase — start with a letter, letters and numbers only; the Data Fabric backend rejects underscores in field names. The `folderKey` property is **experimental**.
* @param options - Changes to apply ({@link EntityUpdateByIdOptions}). At least one of `addFields`, `removeFields`, `updateFields`, `displayName`, `description`, `isRbacEnabled`, or a federated source/join delta (`addExternalSources`, `removeExternalSources`, `addFieldsToSource`, `removeFieldsFromSource`, `updateExternalFieldMapping`, `addSourceJoins`, `updateSourceJoin`) must be provided — calling with no options, `{}`, or only `folderKey` throws a `ValidationError`. Field names passed in `addFields[].name` and `removeFields[].name` must be camelCase — start with a letter, letters and numbers only; the Data Fabric backend rejects underscores in field names. The `folderKey` property is **experimental**.
Comment thread
niket0503 marked this conversation as resolved.
* @returns Promise resolving when the update is complete
*
* @example
* ```typescript
* import { Entities, EntityFieldDataType, DataDirectionType, JoinType } from '@uipath/uipath-typescript/entities';
*
* // Schema-only: add a field and remove another
* await entities.updateById(<id>, {
* addFields: [{ name: "notes", type: EntityFieldDataType.MULTILINE_TEXT }],
Expand Down Expand Up @@ -1085,6 +1113,29 @@ export interface EntityServiceModel {
* folderKey: "<folderKey>",
* addFields: [{ name: "notes", type: EntityFieldDataType.MULTILINE_TEXT }],
* });
*
* // Federated: add a source joined to the existing graph
* await entities.updateById(<id>, {
* addExternalSources: [{
* externalConnectionDetail: { connectionId: "<connectionId>", elementInstanceId: 0, connectorKey: "<connectorKey>", connectorName: "<connectorName>" },
* externalObjectDetail: { externalObjectName: "<relatedObjectName>", primaryKey: "<primaryKeyField>", method: "<operationsCatalogJson>" },
* fields: [{ field: { name: "<internalFieldName>", type: EntityFieldDataType.STRING }, externalFieldMappingDetail: { externalFieldName: "<externalFieldName>", directionType: DataDirectionType.ReadOnly } }],
* }],
* addSourceJoins: [{ sourceObjectName: "<objectName>", sourceJoinField: "<externalFieldName>", relatedSourceObjectName: "<relatedObjectName>", relatedSourceJoinField: "<relatedExternalFieldName>", joinType: JoinType.LeftJoin }],
* });
*
* // Federated: add a field to an existing source (maps a field that already exists on it)
* await entities.updateById(<id>, {
* addFieldsToSource: [{ sourceObjectName: "<objectName>", fields: [{ field: { name: "<internalFieldName>", type: EntityFieldDataType.STRING }, externalFieldMappingDetail: { externalFieldName: "<externalFieldName>", directionType: DataDirectionType.ReadOnly } }] }],
* });
*
* // Federated: change an existing join in place
* await entities.updateById(<id>, {
* updateSourceJoin: [{ sourceObjectName: "<objectName>", relatedSourceObjectName: "<relatedObjectName>", sourceJoinField: "<externalFieldName>" }],
* });
*
* // Federated: remove a source (its joins are removed automatically)
* await entities.updateById(<id>, { removeExternalSources: ["<relatedObjectName>"] });
* ```
* @experimental
*/
Expand Down Expand Up @@ -1385,7 +1436,7 @@ export interface EntityMethods {
/**
* Updates this entity — schema and/or metadata.
*
* @param options - Changes to apply ({@link EntityUpdateByIdOptions}). At least one of `addFields`, `removeFields`, `updateFields`, `displayName`, `description`, or `isRbacEnabled` must be provided — calling with no options, `{}`, or only `folderKey` throws a `ValidationError`. Field names passed in `addFields[].name` and `removeFields[].name` must be camelCase — start with a letter, letters and numbers only; the Data Fabric backend rejects underscores in field names. The `folderKey` property is **experimental**.
* @param options - Changes to apply ({@link EntityUpdateByIdOptions}). At least one of `addFields`, `removeFields`, `updateFields`, `displayName`, `description`, `isRbacEnabled`, or a federated source/join delta (`addExternalSources`, `removeExternalSources`, `addFieldsToSource`, `removeFieldsFromSource`, `updateExternalFieldMapping`, `addSourceJoins`, `updateSourceJoin`) must be provided — calling with no options, `{}`, or only `folderKey` throws a `ValidationError`. Field names passed in `addFields[].name` and `removeFields[].name` must be camelCase — start with a letter, letters and numbers only; the Data Fabric backend rejects underscores in field names. The `folderKey` property is **experimental**.
* @returns Promise resolving when the update is complete
* @example
* ```typescript
Expand Down
Loading
Loading