@uipath/uipath-typescript 1.3.4 → 1.3.5

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.
@@ -515,6 +515,14 @@ interface EntityFieldBase {
515
515
  isEncrypted?: boolean;
516
516
  /** Default value for the field */
517
517
  defaultValue?: string;
518
+ /** Maximum character length for STRING fields (default: 200, range: 1–4000) and MULTILINE_TEXT fields (default: 200, range: 1–10000). */
519
+ lengthLimit?: number;
520
+ /** Maximum allowed value for numeric fields (INTEGER, BIG_INTEGER, FLOAT, DOUBLE, DECIMAL — default: 1,000,000,000,000; range: ±9,007,199,254,740,991) */
521
+ maxValue?: number;
522
+ /** Minimum allowed value for numeric fields (INTEGER, BIG_INTEGER, FLOAT, DOUBLE, DECIMAL — default: -1,000,000,000,000; range: ±9,007,199,254,740,991) */
523
+ minValue?: number;
524
+ /** Number of decimal places for DECIMAL, FLOAT, and DOUBLE fields (default: 2, range: 0–10) */
525
+ decimalPrecision?: number;
518
526
  }
519
527
  /**
520
528
  * User-facing field definition for creating or updating entity schemas
@@ -1342,6 +1350,13 @@ interface EntityServiceModel {
1342
1350
  * { fieldName: "product_name", type: EntityFieldDataType.STRING, isRequired: true, isUnique: true },
1343
1351
  * { fieldName: "price", type: EntityFieldDataType.INTEGER, defaultValue: "0" },
1344
1352
  * ], { displayName: "Product Catalog", description: "Our product catalog", isRbacEnabled: true });
1353
+ *
1354
+ * // With advanced sqlType constraints (lengthLimit, decimalPrecision, maxValue, minValue) and defaultValue
1355
+ * const ordersId = await entities.create("orders", [
1356
+ * { fieldName: "product_name", type: EntityFieldDataType.STRING, isRequired: true, isUnique: true, lengthLimit: 500 },
1357
+ * { fieldName: "price", type: EntityFieldDataType.DECIMAL, decimalPrecision: 4, maxValue: 999999, minValue: 0 },
1358
+ * { fieldName: "quantity", type: EntityFieldDataType.INTEGER, maxValue: 10000, minValue: 1, defaultValue: "0" },
1359
+ * ]);
1345
1360
  * ```
1346
1361
  * @internal
1347
1362
  */
@@ -1389,6 +1404,17 @@ interface EntityServiceModel {
1389
1404
  * updateFields: [{ id: <fieldId>, displayName: "Unit Price", isRequired: true }],
1390
1405
  * displayName: "Price Catalog",
1391
1406
  * });
1407
+ *
1408
+ * // Add a STRING/DECIMAL field with explicit advanced sqlType constraints and defaultValue
1409
+ * await entities.updateById(<id>, {
1410
+ * addFields: [
1411
+ * { fieldName: "summary", type: EntityFieldDataType.STRING, lengthLimit: 500, defaultValue: "summary" },
1412
+ * { fieldName: "amount", type: EntityFieldDataType.DECIMAL, decimalPrecision: 4, maxValue: 999999, minValue: 0 },
1413
+ * ],
1414
+ * updateFields: [
1415
+ * { id: <fieldId>, lengthLimit: 1000 },
1416
+ * ],
1417
+ * });
1392
1418
  * ```
1393
1419
  * @internal
1394
1420
  */
@@ -1578,6 +1604,14 @@ interface EntityMethods {
1578
1604
  * displayName: "Updated Name",
1579
1605
  * addFields: [{ fieldName: "notes", type: EntityFieldDataType.MULTILINE_TEXT }],
1580
1606
  * });
1607
+ *
1608
+ * // Add a STRING/DECIMAL field with explicit advanced sqlType constraints
1609
+ * await entity.update({
1610
+ * addFields: [
1611
+ * { fieldName: "summary", type: EntityFieldDataType.STRING, lengthLimit: 500, defaultValue: "string" },
1612
+ * { fieldName: "amount", type: EntityFieldDataType.DECIMAL, decimalPrecision: 4, maxValue: 999999, minValue: 0 },
1613
+ * ],
1614
+ * });
1581
1615
  * ```
1582
1616
  * @internal
1583
1617
  */
@@ -2034,6 +2068,13 @@ declare class EntityService extends BaseService implements EntityServiceModel {
2034
2068
  * { fieldName: "product_name", type: EntityFieldDataType.STRING, isRequired: true, isUnique: true },
2035
2069
  * { fieldName: "price", type: EntityFieldDataType.INTEGER, defaultValue: "0" },
2036
2070
  * ], { displayName: "Product Catalog", description: "Our product catalog", isRbacEnabled: true });
2071
+ *
2072
+ * // With advanced sqlType constraints (lengthLimit, decimalPrecision, maxValue, minValue) and defaultValue
2073
+ * const ordersId = await entities.create("orders", [
2074
+ * { fieldName: "product_name", type: EntityFieldDataType.STRING, isRequired: true, isUnique: true, lengthLimit: 500 },
2075
+ * { fieldName: "price", type: EntityFieldDataType.DECIMAL, decimalPrecision: 4, maxValue: 999999, minValue: 0 },
2076
+ * { fieldName: "quantity", type: EntityFieldDataType.INTEGER, maxValue: 10000, minValue: 1, defaultValue: "0" },
2077
+ * ]);
2037
2078
  * ```
2038
2079
  * @internal
2039
2080
  */
@@ -2085,6 +2126,17 @@ declare class EntityService extends BaseService implements EntityServiceModel {
2085
2126
  * updateFields: [{ id: "<fieldId>", displayName: "Unit Price", isRequired: true }],
2086
2127
  * displayName: "Price Catalog",
2087
2128
  * });
2129
+ *
2130
+ * // Add a STRING/DECIMAL field with explicit advanced sqlType constraints and defaultValue
2131
+ * await entities.updateById("<entityId>", {
2132
+ * addFields: [
2133
+ * { fieldName: "summary", type: EntityFieldDataType.STRING, lengthLimit: 500, defaultValue: "summary" },
2134
+ * { fieldName: "amount", type: EntityFieldDataType.DECIMAL, decimalPrecision: 4, maxValue: 999999, minValue: 0 },
2135
+ * ],
2136
+ * updateFields: [
2137
+ * { id: "<fieldId>", lengthLimit: 1000 },
2138
+ * ],
2139
+ * });
2088
2140
  * ```
2089
2141
  * @internal
2090
2142
  */
@@ -2111,6 +2163,13 @@ declare class EntityService extends BaseService implements EntityServiceModel {
2111
2163
  * @private
2112
2164
  */
2113
2165
  private mapFieldTypes;
2166
+ /**
2167
+ * Resolves an {@link EntityFieldDataType} from a field's `fieldDisplayType` and
2168
+ * raw SQL type name. Prefers `fieldDisplayType` to disambiguate types that
2169
+ * share a SQL type (FILE, CHOICE_SET_*, AUTO_NUMBER, RELATIONSHIP); falls back
2170
+ * to the SQL-type-name mapping. Returns `undefined` if neither resolves.
2171
+ */
2172
+ private tryResolveFieldDataType;
2114
2173
  /**
2115
2174
  * Transforms nested reference objects in field metadata
2116
2175
  */
@@ -2124,6 +2183,28 @@ declare class EntityService extends BaseService implements EntityServiceModel {
2124
2183
  private mapExternalFields;
2125
2184
  /** Converts a user-facing EntityCreateFieldOptions to the raw API field payload */
2126
2185
  private buildSchemaFieldPayload;
2186
+ /**
2187
+ * Derives the user-facing {@link EntityFieldDataType} for a field on the raw
2188
+ * API response. Throws if the field's `fieldDisplayType` and `sqlType.name`
2189
+ * are both unmappable.
2190
+ */
2191
+ private resolveFieldDataType;
2192
+ /**
2193
+ * Validates that the user-supplied constraint properties on a field are
2194
+ * supported by the field's data type. Throws a `ValidationError` listing
2195
+ * any unsupported properties.
2196
+ */
2197
+ private validateFieldConstraints;
2198
+ /**
2199
+ * Returns the sqlType constraint fields for a given field type.
2200
+ *
2201
+ * The API requires specific constraint properties to be set per SQL type;
2202
+ * without them the field is stored in an incomplete state, causing
2203
+ * "Field type cannot be changed" errors when the UI later tries to edit
2204
+ * advanced options. User-supplied values from `EntityCreateFieldOptions`
2205
+ * override the defaults where the type accepts overrides.
2206
+ */
2207
+ private buildSqlTypeConstraints;
2127
2208
  private static readonly RESERVED_FIELD_NAMES;
2128
2209
  private validateName;
2129
2210
  }
@@ -1927,6 +1927,20 @@ function createParams(paramsObj = {}) {
1927
1927
  return params;
1928
1928
  }
1929
1929
 
1930
+ /**
1931
+ * Names of the per-field SQL constraint properties (i.e. the contents of `sqlType`
1932
+ * excluding its `name`). Used internally to validate user-supplied constraints
1933
+ * against the set of constraints that each `EntityFieldDataType` accepts.
1934
+ *
1935
+ * Enum values match the corresponding property names on `EntityCreateFieldOptions`.
1936
+ */
1937
+ var EntityFieldConstraint;
1938
+ (function (EntityFieldConstraint) {
1939
+ EntityFieldConstraint["LengthLimit"] = "lengthLimit";
1940
+ EntityFieldConstraint["MaxValue"] = "maxValue";
1941
+ EntityFieldConstraint["MinValue"] = "minValue";
1942
+ EntityFieldConstraint["DecimalPrecision"] = "decimalPrecision";
1943
+ })(EntityFieldConstraint || (EntityFieldConstraint = {}));
1930
1944
  /**
1931
1945
  * Entity field data types (SQL types from API)
1932
1946
  */
@@ -1989,6 +2003,70 @@ const FieldDisplayTypeToDataType = {
1989
2003
  [FieldDisplayType.AutoNumber]: EntityFieldDataType.AUTO_NUMBER,
1990
2004
  [FieldDisplayType.Relationship]: EntityFieldDataType.RELATIONSHIP,
1991
2005
  };
2006
+ /**
2007
+ * Default and fixed sqlType constraint values applied when the user does not provide them.
2008
+ * The API requires these to be present on field creation — without them the field
2009
+ * is stored in an incomplete state, causing "Field type cannot be changed" errors
2010
+ * when the UI later tries to edit advanced options.
2011
+ */
2012
+ const ENTITY_FIELD_CONSTRAINT_DEFAULTS = {
2013
+ STRING_LENGTH_LIMIT: 200,
2014
+ MULTILINE_TEXT_LENGTH_LIMIT: 200,
2015
+ /** Fixed (non-overridable) length limit on DECIMAL payloads*/
2016
+ DECIMAL_LENGTH_LIMIT: 1000,
2017
+ DECIMAL_PRECISION: 2,
2018
+ /** Fixed (non-overridable) length limit for BIT (BOOLEAN) fields */
2019
+ BOOLEAN_LENGTH_LIMIT: 100,
2020
+ /** Fixed (non-overridable) length limit for DATE / DATETIMEOFFSET fields */
2021
+ DATE_LENGTH_LIMIT: 1000,
2022
+ /** Fixed (non-overridable) length limit for UNIQUEIDENTIFIER-backed FILE and RELATIONSHIP fields */
2023
+ UNIQUEIDENTIFIER_LENGTH_LIMIT: 300,
2024
+ /** Fixed (non-overridable) length limit for CHOICE_SET_MULTIPLE fields */
2025
+ CHOICE_SET_MULTIPLE_LENGTH_LIMIT: 4000,
2026
+ NUMERIC_MAX_VALUE: 1000000000000,
2027
+ NUMERIC_MIN_VALUE: -1e12,
2028
+ };
2029
+ /**
2030
+ * Per-field-type spec describing which {@link EntityFieldConstraint}s the user
2031
+ * may supply on create / update, and the inclusive value range for each.
2032
+ *
2033
+ * Source of truth: the platform's `Constants.cs` constraint table. Keys absent
2034
+ * from a type's spec are not user-configurable for that type; passing one
2035
+ * throws a `ValidationError`. Field types absent from this map (BOOLEAN, DATE,
2036
+ * DATETIME, DATETIME_WITH_TZ, FILE, RELATIONSHIP, UUID, CHOICE_SET_SINGLE,
2037
+ * CHOICE_SET_MULTIPLE, AUTO_NUMBER) accept no user-supplied constraints.
2038
+ */
2039
+ const ENTITY_FIELD_CONSTRAINT_SPEC = {
2040
+ [EntityFieldDataType.STRING]: {
2041
+ [EntityFieldConstraint.LengthLimit]: { min: 1, max: 4000 },
2042
+ },
2043
+ [EntityFieldDataType.MULTILINE_TEXT]: {
2044
+ [EntityFieldConstraint.LengthLimit]: { min: 1, max: 10000 },
2045
+ },
2046
+ [EntityFieldDataType.INTEGER]: {
2047
+ [EntityFieldConstraint.MaxValue]: { min: -Number.MAX_SAFE_INTEGER, max: Number.MAX_SAFE_INTEGER },
2048
+ [EntityFieldConstraint.MinValue]: { min: -Number.MAX_SAFE_INTEGER, max: Number.MAX_SAFE_INTEGER },
2049
+ },
2050
+ [EntityFieldDataType.BIG_INTEGER]: {
2051
+ [EntityFieldConstraint.MaxValue]: { min: -Number.MAX_SAFE_INTEGER, max: Number.MAX_SAFE_INTEGER },
2052
+ [EntityFieldConstraint.MinValue]: { min: -Number.MAX_SAFE_INTEGER, max: Number.MAX_SAFE_INTEGER },
2053
+ },
2054
+ [EntityFieldDataType.DECIMAL]: {
2055
+ [EntityFieldConstraint.MaxValue]: { min: -Number.MAX_SAFE_INTEGER, max: Number.MAX_SAFE_INTEGER },
2056
+ [EntityFieldConstraint.MinValue]: { min: -Number.MAX_SAFE_INTEGER, max: Number.MAX_SAFE_INTEGER },
2057
+ [EntityFieldConstraint.DecimalPrecision]: { min: 0, max: 10 },
2058
+ },
2059
+ [EntityFieldDataType.FLOAT]: {
2060
+ [EntityFieldConstraint.MaxValue]: { min: -Number.MAX_SAFE_INTEGER, max: Number.MAX_SAFE_INTEGER },
2061
+ [EntityFieldConstraint.MinValue]: { min: -Number.MAX_SAFE_INTEGER, max: Number.MAX_SAFE_INTEGER },
2062
+ [EntityFieldConstraint.DecimalPrecision]: { min: 0, max: 10 },
2063
+ },
2064
+ [EntityFieldDataType.DOUBLE]: {
2065
+ [EntityFieldConstraint.MaxValue]: { min: -Number.MAX_SAFE_INTEGER, max: Number.MAX_SAFE_INTEGER },
2066
+ [EntityFieldConstraint.MinValue]: { min: -Number.MAX_SAFE_INTEGER, max: Number.MAX_SAFE_INTEGER },
2067
+ [EntityFieldConstraint.DecimalPrecision]: { min: 0, max: 10 },
2068
+ },
2069
+ };
1992
2070
  /**
1993
2071
  * Maps SQL field types to friendly display names
1994
2072
  */
@@ -2013,7 +2091,7 @@ const EntityFieldTypeMap = {
2013
2091
  // Connection string placeholder that will be replaced during build
2014
2092
  const CONNECTION_STRING = "InstrumentationKey=a6efa11d-1feb-4508-9738-e13e12dcae5e;IngestionEndpoint=https://westeurope-5.in.applicationinsights.azure.com/;LiveEndpoint=https://westeurope.livediagnostics.monitor.azure.com/;ApplicationId=7c58eb1c-9581-4ba6-839e-11725848a037";
2015
2093
  // SDK Version placeholder
2016
- const SDK_VERSION = "1.3.4";
2094
+ const SDK_VERSION = "1.3.5";
2017
2095
  const VERSION = "Version";
2018
2096
  const SERVICE = "Service";
2019
2097
  const CLOUD_ORGANIZATION_NAME = "CloudOrganizationName";
@@ -2862,6 +2940,13 @@ class EntityService extends BaseService {
2862
2940
  * { fieldName: "product_name", type: EntityFieldDataType.STRING, isRequired: true, isUnique: true },
2863
2941
  * { fieldName: "price", type: EntityFieldDataType.INTEGER, defaultValue: "0" },
2864
2942
  * ], { displayName: "Product Catalog", description: "Our product catalog", isRbacEnabled: true });
2943
+ *
2944
+ * // With advanced sqlType constraints (lengthLimit, decimalPrecision, maxValue, minValue) and defaultValue
2945
+ * const ordersId = await entities.create("orders", [
2946
+ * { fieldName: "product_name", type: EntityFieldDataType.STRING, isRequired: true, isUnique: true, lengthLimit: 500 },
2947
+ * { fieldName: "price", type: EntityFieldDataType.DECIMAL, decimalPrecision: 4, maxValue: 999999, minValue: 0 },
2948
+ * { fieldName: "quantity", type: EntityFieldDataType.INTEGER, maxValue: 10000, minValue: 1, defaultValue: "0" },
2949
+ * ]);
2865
2950
  * ```
2866
2951
  * @internal
2867
2952
  */
@@ -2935,6 +3020,17 @@ class EntityService extends BaseService {
2935
3020
  * updateFields: [{ id: "<fieldId>", displayName: "Unit Price", isRequired: true }],
2936
3021
  * displayName: "Price Catalog",
2937
3022
  * });
3023
+ *
3024
+ * // Add a STRING/DECIMAL field with explicit advanced sqlType constraints and defaultValue
3025
+ * await entities.updateById("<entityId>", {
3026
+ * addFields: [
3027
+ * { fieldName: "summary", type: EntityFieldDataType.STRING, lengthLimit: 500, defaultValue: "summary" },
3028
+ * { fieldName: "amount", type: EntityFieldDataType.DECIMAL, decimalPrecision: 4, maxValue: 999999, minValue: 0 },
3029
+ * ],
3030
+ * updateFields: [
3031
+ * { id: "<fieldId>", lengthLimit: 1000 },
3032
+ * ],
3033
+ * });
2938
3034
  * ```
2939
3035
  * @internal
2940
3036
  */
@@ -2978,6 +3074,21 @@ class EntityService extends BaseService {
2978
3074
  const update = updateMap.get(f.id ?? '');
2979
3075
  if (!update)
2980
3076
  return f;
3077
+ const constraintUpdate = {
3078
+ ...(update.lengthLimit !== undefined && { lengthLimit: update.lengthLimit }),
3079
+ ...(update.maxValue !== undefined && { maxValue: update.maxValue }),
3080
+ ...(update.minValue !== undefined && { minValue: update.minValue }),
3081
+ ...(update.decimalPrecision !== undefined && { decimalPrecision: update.decimalPrecision }),
3082
+ };
3083
+ const hasConstraintUpdate = Object.keys(constraintUpdate).length > 0;
3084
+ if (hasConstraintUpdate) {
3085
+ if (!f.sqlType) {
3086
+ throw new ValidationError({
3087
+ message: `Cannot update constraints on field '${f.name}' (id: ${f.id}) — the field is missing sqlType metadata in the entity definition.`,
3088
+ });
3089
+ }
3090
+ this.validateFieldConstraints(this.resolveFieldDataType(f), update, f.name);
3091
+ }
2981
3092
  return {
2982
3093
  ...f,
2983
3094
  ...(update.displayName !== undefined && { displayName: update.displayName }),
@@ -2987,6 +3098,7 @@ class EntityService extends BaseService {
2987
3098
  ...(update.isRbacEnabled !== undefined && { isRbacEnabled: update.isRbacEnabled }),
2988
3099
  ...(update.isEncrypted !== undefined && { isEncrypted: update.isEncrypted }),
2989
3100
  ...(update.defaultValue !== undefined && { defaultValue: update.defaultValue }),
3101
+ ...(hasConstraintUpdate && f.sqlType && { sqlType: { ...f.sqlType, ...constraintUpdate } }),
2990
3102
  };
2991
3103
  });
2992
3104
  }
@@ -3036,24 +3148,27 @@ class EntityService extends BaseService {
3036
3148
  let transformedField = transformData(field, EntityMap);
3037
3149
  // Map field type: prefer fieldDisplayType for types that share SQL types (File, ChoiceSet, AutoNumber)
3038
3150
  if (transformedField.fieldDataType?.name) {
3039
- const displayTypeMapped = transformedField.fieldDisplayType
3040
- ? FieldDisplayTypeToDataType[transformedField.fieldDisplayType]
3041
- : undefined;
3042
- if (displayTypeMapped) {
3043
- transformedField.fieldDataType.name = displayTypeMapped;
3044
- }
3045
- else {
3046
- const rawSqlTypeName = field.sqlType?.name;
3047
- const mapped = rawSqlTypeName ? EntityFieldTypeMap[rawSqlTypeName] : undefined;
3048
- if (mapped) {
3049
- transformedField.fieldDataType.name = mapped;
3050
- }
3151
+ const mapped = this.tryResolveFieldDataType(transformedField.fieldDisplayType, field.sqlType?.name);
3152
+ if (mapped) {
3153
+ transformedField.fieldDataType.name = mapped;
3051
3154
  }
3052
3155
  }
3053
3156
  this.transformNestedReferences(transformedField);
3054
3157
  return transformedField;
3055
3158
  });
3056
3159
  }
3160
+ /**
3161
+ * Resolves an {@link EntityFieldDataType} from a field's `fieldDisplayType` and
3162
+ * raw SQL type name. Prefers `fieldDisplayType` to disambiguate types that
3163
+ * share a SQL type (FILE, CHOICE_SET_*, AUTO_NUMBER, RELATIONSHIP); falls back
3164
+ * to the SQL-type-name mapping. Returns `undefined` if neither resolves.
3165
+ */
3166
+ tryResolveFieldDataType(fieldDisplayType, sqlTypeName) {
3167
+ const displayMapped = fieldDisplayType ? FieldDisplayTypeToDataType[fieldDisplayType] : undefined;
3168
+ if (displayMapped)
3169
+ return displayMapped;
3170
+ return sqlTypeName ? EntityFieldTypeMap[sqlTypeName] : undefined;
3171
+ }
3057
3172
  /**
3058
3173
  * Transforms nested reference objects in field metadata
3059
3174
  */
@@ -3094,11 +3209,16 @@ class EntityService extends BaseService {
3094
3209
  /** Converts a user-facing EntityCreateFieldOptions to the raw API field payload */
3095
3210
  buildSchemaFieldPayload(field) {
3096
3211
  this.validateName(field.fieldName, 'field');
3097
- const mapping = EntitySchemaFieldTypeMap[field.type ?? EntityFieldDataType.STRING];
3212
+ const fieldType = field.type ?? EntityFieldDataType.STRING;
3213
+ this.validateFieldConstraints(fieldType, field, field.fieldName);
3214
+ const mapping = EntitySchemaFieldTypeMap[fieldType];
3098
3215
  return {
3099
3216
  name: field.fieldName,
3100
3217
  displayName: field.displayName ?? field.fieldName,
3101
- sqlType: { name: mapping.sqlTypeName },
3218
+ sqlType: {
3219
+ name: mapping.sqlTypeName,
3220
+ ...this.buildSqlTypeConstraints(fieldType, field),
3221
+ },
3102
3222
  fieldDisplayType: mapping.fieldDisplayType,
3103
3223
  description: field.description ?? '',
3104
3224
  isRequired: field.isRequired ?? false,
@@ -3111,6 +3231,107 @@ class EntityService extends BaseService {
3111
3231
  ...(field.referenceFieldName !== undefined && { referenceFieldName: field.referenceFieldName }),
3112
3232
  };
3113
3233
  }
3234
+ /**
3235
+ * Derives the user-facing {@link EntityFieldDataType} for a field on the raw
3236
+ * API response. Throws if the field's `fieldDisplayType` and `sqlType.name`
3237
+ * are both unmappable.
3238
+ */
3239
+ resolveFieldDataType(f) {
3240
+ const mapped = this.tryResolveFieldDataType(f.fieldDisplayType, f.sqlType?.name);
3241
+ if (!mapped) {
3242
+ throw new ValidationError({
3243
+ message: `Cannot determine field type for '${f.name}' (id: ${f.id}) — sqlType '${f.sqlType?.name ?? '(missing)'}' and fieldDisplayType '${f.fieldDisplayType ?? '(missing)'}' are both unrecognized.`,
3244
+ });
3245
+ }
3246
+ return mapped;
3247
+ }
3248
+ /**
3249
+ * Validates that the user-supplied constraint properties on a field are
3250
+ * supported by the field's data type. Throws a `ValidationError` listing
3251
+ * any unsupported properties.
3252
+ */
3253
+ validateFieldConstraints(type, field, fieldName) {
3254
+ const spec = ENTITY_FIELD_CONSTRAINT_SPEC[type] ?? {};
3255
+ const supported = Object.keys(spec);
3256
+ const provided = Object.values(EntityFieldConstraint).filter(name => field[name] !== undefined);
3257
+ const unsupported = provided.filter(p => !(p in spec));
3258
+ if (unsupported.length > 0) {
3259
+ const allowedDesc = supported.length > 0 ? supported.join(', ') : 'none';
3260
+ throw new ValidationError({
3261
+ message: `Field '${fieldName}' of type ${type} does not accept ${unsupported.join(', ')}. Allowed constraints for this type: ${allowedDesc}.`,
3262
+ });
3263
+ }
3264
+ // Range check: each user-supplied constraint must be within its allowed bounds.
3265
+ for (const name of provided) {
3266
+ const range = spec[name];
3267
+ const value = field[name];
3268
+ if (range && value !== undefined && (value < range.min || value > range.max)) {
3269
+ throw new ValidationError({
3270
+ message: `Field '${fieldName}' of type ${type} has ${name} ${value} out of range [${range.min}, ${range.max}].`,
3271
+ });
3272
+ }
3273
+ }
3274
+ // Cross-field check: when both bounds are user-supplied in the same call,
3275
+ // minValue must be strictly less than maxValue.
3276
+ if (field.minValue !== undefined && field.maxValue !== undefined && field.minValue >= field.maxValue) {
3277
+ throw new ValidationError({
3278
+ message: `Field '${fieldName}' of type ${type} has minValue ${field.minValue} >= maxValue ${field.maxValue}. minValue must be strictly less than maxValue.`,
3279
+ });
3280
+ }
3281
+ }
3282
+ /**
3283
+ * Returns the sqlType constraint fields for a given field type.
3284
+ *
3285
+ * The API requires specific constraint properties to be set per SQL type;
3286
+ * without them the field is stored in an incomplete state, causing
3287
+ * "Field type cannot be changed" errors when the UI later tries to edit
3288
+ * advanced options. User-supplied values from `EntityCreateFieldOptions`
3289
+ * override the defaults where the type accepts overrides.
3290
+ */
3291
+ buildSqlTypeConstraints(type, field) {
3292
+ const defaults = ENTITY_FIELD_CONSTRAINT_DEFAULTS;
3293
+ switch (type) {
3294
+ case EntityFieldDataType.STRING:
3295
+ return { lengthLimit: field.lengthLimit ?? defaults.STRING_LENGTH_LIMIT };
3296
+ case EntityFieldDataType.MULTILINE_TEXT:
3297
+ return { lengthLimit: field.lengthLimit ?? defaults.MULTILINE_TEXT_LENGTH_LIMIT };
3298
+ case EntityFieldDataType.DECIMAL:
3299
+ return {
3300
+ lengthLimit: defaults.DECIMAL_LENGTH_LIMIT,
3301
+ decimalPrecision: field.decimalPrecision ?? defaults.DECIMAL_PRECISION,
3302
+ maxValue: field.maxValue ?? defaults.NUMERIC_MAX_VALUE,
3303
+ minValue: field.minValue ?? defaults.NUMERIC_MIN_VALUE,
3304
+ };
3305
+ case EntityFieldDataType.BOOLEAN:
3306
+ return { lengthLimit: defaults.BOOLEAN_LENGTH_LIMIT };
3307
+ case EntityFieldDataType.DATE:
3308
+ case EntityFieldDataType.DATETIME_WITH_TZ:
3309
+ return { lengthLimit: defaults.DATE_LENGTH_LIMIT };
3310
+ case EntityFieldDataType.INTEGER:
3311
+ case EntityFieldDataType.BIG_INTEGER:
3312
+ return {
3313
+ maxValue: field.maxValue ?? defaults.NUMERIC_MAX_VALUE,
3314
+ minValue: field.minValue ?? defaults.NUMERIC_MIN_VALUE,
3315
+ };
3316
+ case EntityFieldDataType.FLOAT:
3317
+ case EntityFieldDataType.DOUBLE:
3318
+ return {
3319
+ decimalPrecision: field.decimalPrecision ?? defaults.DECIMAL_PRECISION,
3320
+ maxValue: field.maxValue ?? defaults.NUMERIC_MAX_VALUE,
3321
+ minValue: field.minValue ?? defaults.NUMERIC_MIN_VALUE,
3322
+ };
3323
+ case EntityFieldDataType.FILE:
3324
+ case EntityFieldDataType.RELATIONSHIP:
3325
+ // UNIQUEIDENTIFIER fixed lengthLimit (300)
3326
+ return { lengthLimit: defaults.UNIQUEIDENTIFIER_LENGTH_LIMIT };
3327
+ case EntityFieldDataType.CHOICE_SET_MULTIPLE:
3328
+ // CHOICE_SET_MULTIPLE fixed lengthLimit (4000)
3329
+ return { lengthLimit: defaults.CHOICE_SET_MULTIPLE_LENGTH_LIMIT };
3330
+ default:
3331
+ // UUID, CHOICE_SET_SINGLE, AUTO_NUMBER, DATETIME — (sqlType: { name })
3332
+ return {};
3333
+ }
3334
+ }
3114
3335
  validateName(name, context) {
3115
3336
  if (name.length < 3 || name.length > 100 || !/^[a-zA-Z]\w*$/.test(name)) {
3116
3337
  const suggestion = name.replace(/\W/g, '').replace(/^[0-9_]+/, '');
@@ -1565,7 +1565,7 @@ const FEEDBACK_ENDPOINTS = {
1565
1565
  // Connection string placeholder that will be replaced during build
1566
1566
  const CONNECTION_STRING = "InstrumentationKey=a6efa11d-1feb-4508-9738-e13e12dcae5e;IngestionEndpoint=https://westeurope-5.in.applicationinsights.azure.com/;LiveEndpoint=https://westeurope.livediagnostics.monitor.azure.com/;ApplicationId=7c58eb1c-9581-4ba6-839e-11725848a037";
1567
1567
  // SDK Version placeholder
1568
- const SDK_VERSION = "1.3.4";
1568
+ const SDK_VERSION = "1.3.5";
1569
1569
  const VERSION = "Version";
1570
1570
  const SERVICE = "Service";
1571
1571
  const CLOUD_ORGANIZATION_NAME = "CloudOrganizationName";
@@ -1563,7 +1563,7 @@ const FEEDBACK_ENDPOINTS = {
1563
1563
  // Connection string placeholder that will be replaced during build
1564
1564
  const CONNECTION_STRING = "InstrumentationKey=a6efa11d-1feb-4508-9738-e13e12dcae5e;IngestionEndpoint=https://westeurope-5.in.applicationinsights.azure.com/;LiveEndpoint=https://westeurope.livediagnostics.monitor.azure.com/;ApplicationId=7c58eb1c-9581-4ba6-839e-11725848a037";
1565
1565
  // SDK Version placeholder
1566
- const SDK_VERSION = "1.3.4";
1566
+ const SDK_VERSION = "1.3.5";
1567
1567
  const VERSION = "Version";
1568
1568
  const SERVICE = "Service";
1569
1569
  const CLOUD_ORGANIZATION_NAME = "CloudOrganizationName";