Skip to content

Commit

Permalink
optimizations and refactoring; moving js tests to ts
Browse files Browse the repository at this point in the history
  • Loading branch information
AleksandrRogov committed Sep 8, 2024
1 parent 5ce02d3 commit a9df87a
Show file tree
Hide file tree
Showing 11 changed files with 613 additions and 487 deletions.
13 changes: 7 additions & 6 deletions .github/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,7 @@ data | `Object` or `ArrayBuffer` / `Buffer` (for node.js) | `create`, `update`,
duplicateDetection | `boolean` | `create`, `update`, `upsert` | **D365 Web API v9+** Boolean that enables duplicate detection. [More Info](https://docs.microsoft.com/en-us/dynamics365/customer-engagement/developer/webapi/update-delete-entities-using-web-api#check-for-duplicate-records)
expand | `Expand[]` | `retrieve`, `retrieveMultiple`, `create`, `update`, `upsert` | An array of `Expand` Objects (described below the table) representing the $expand OData System Query Option value to control which related records are also returned.
fetchXml | `string` | `fetch`, `fetchAll` | Property that sets FetchXML - a proprietary query language that provides capabilities to perform aggregation.
fieldName | `string` | `uploadFile`, `downloadFile`, `deleteRequest` | **D365 Web API v9.1+** Use this option to specify the name of the file attribute in Dynamics 365. [More Info](https://docs.microsoft.com/en-us/powerapps/developer/common-data-service/file-attributes)
fieldName | `string` | `uploadFile`, `downloadFile`, `deleteRecord` | **D365 Web API v9.1+. Deprecated, use `property` instead** Use this option to specify the name of the file attribute in Dynamics 365. [More Info](https://docs.microsoft.com/en-us/powerapps/developer/common-data-service/file-attributes)
fileName | `string` | `uploadFile` | **D365 Web API v9.1+** Specifies the name of the file
filter | String | `retrieve`, `retrieveMultiple`, `retrieveAll`, `callFunction` | Use the $filter system query option to set criteria for which entities will be returned.
functionName | `string` | `callFunction` | **Deprecated from v2.1.3** Use `name` instead. Name of a D365 Web Api function.
Expand All @@ -382,6 +382,7 @@ pageNumber | `number` | `fetch` | Sets a page number for Fetch XML request ONLY!
pagingCookie | `string` | `fetch` | Sets a paging cookie for Fetch XML request ONLY!
parameters | `Object` | `callFunction` | Function's input parameters. Example: `{ param1: "test", param2: 3 }`.
partitionId | `string` | `create`, `update`, `upsert`, `delete`, `retrieve`, `retrieveMultiple` | Sets a unique partition key value of a logical partition for non-relational custom entity data stored in NoSql tables of Azure heterogenous storage. [More Info](https://docs.microsoft.com/en-us/power-apps/developer/data-platform/webapi/azure-storage-partitioning)
property | `string` | `uploadFile`, `downloadFile`, `deleteRecord` | `v2.1.6+` **D365 Web API v9.1+.** Use this option to specify the name of the column or of the file attribute in Dynamics 365. [More Info](https://docs.microsoft.com/en-us/powerapps/developer/common-data-service/file-attributes)
queryParams | `string[]` | All | Custom query parameters. Can also be used to set the [parameter aliases](https://docs.microsoft.com/en-us/power-apps/developer/data-platform/webapi/query-data-web-api#use-parameter-aliases-with-system-query-options) for "$filter" and "$orderBy". **Important!** These parameters ARE NOT URI encoded!
returnRepresentation | `boolean` | `create`, `update`, `upsert` | Sets Prefer header request with value "return=representation". Use this property to return just created or updated entity in a single request.
savedQuery | `string` | `retrieve` | A String representing the GUID value of the saved query.
Expand Down Expand Up @@ -542,7 +543,7 @@ else{
const request: DynamicsWebApi.DeleteRequest = {
key: leadId,
collection: "leads",
fieldName: "subject"
property: "subject"
}

await dynamicsWebApi.deleteRecord(request);
Expand Down Expand Up @@ -2130,7 +2131,7 @@ fr.onload = function(){
dynamicsWebApi.uploadFile({
collection: "dwa_filestorages",
key: "00000000-0000-0000-0000-000000000001",
fieldName: "dwa_file",
property: "dwa_file",
fileName: fileName,
data: fileData
}).then(function(){
Expand All @@ -2151,7 +2152,7 @@ fs.readFile(filename, (err, data) => {
dynamicsWebApi.uploadFile({
collection: "dwa_filestorages",
key: "00000000-0000-0000-0000-000000000001",
fieldName: "dwa_file",
property: "dwa_file",
fileName: filename
data: data,
}).then(function() {
Expand All @@ -2168,7 +2169,7 @@ fs.readFile(filename, (err, data) => {
const donwloadResponse = await dynamicsWebApi.downloadFile({
collection: "dwa_filestorages",
key: "00000000-0000-0000-0000-000000000001",
fieldName: "dwa_file"
property: "dwa_file"
});

//Uint8Array for browser and Buffer for Node.js
Expand All @@ -2183,7 +2184,7 @@ const fileSize = donwloadResponse.fileSize;
const isDeleted = await dynamicsWebApi.deleteRecord({
collection: "dwa_filestorages",
key: "00000000-0000-0000-0000-000000000001",
fieldName: "dwa_file"
property: "dwa_file"
});
```
Expand Down
27 changes: 21 additions & 6 deletions src/dynamics-web-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1258,7 +1258,7 @@ export interface CreateRequest<T = any> extends CRUDRequest {
expand?: Expand[];
/**Sets Prefer header with value "odata.include-annotations=" and the specified annotation.Annotations provide additional information about lookups, options sets and other complex attribute types. */
includeAnnotations?: string;
/**A String representing the name of a single - valued navigation property.Useful when needed to retrieve information about a related record in a single request. */
/**A String representing the name of a single - valued navigation property. Useful when needed to retrieve information about a related record in a single request. */
navigationProperty?: string;
/**A String representing navigation property's Primary Key (GUID) or Alternate Key(s). (For example, to retrieve Attribute Metadata). */
navigationPropertyKey?: string;
Expand Down Expand Up @@ -1293,7 +1293,7 @@ export interface UpdateRequestBase<T = any> extends CRUDRequest {
contentId?: string;
/**Casts the AttributeMetadata to a specific type. (Used in requests to Attribute Metadata). */
metadataAttributeType?: string;
/**A String representing the name of a single - valued navigation property.Useful when needed to retrieve information about a related record in a single request. */
/**A String representing the name of a single - valued navigation property. Useful when needed to retrieve information about a related record in a single request. */
navigationProperty?: string;
/**A String representing navigation property's Primary Key (GUID) or Alternate Key(s). (For example, to retrieve Attribute Metadata). */
navigationPropertyKey?: string;
Expand Down Expand Up @@ -1335,8 +1335,13 @@ export interface DeleteRequest extends CRUDRequest {
ifmatch?: string;
/**BATCH REQUESTS ONLY! Sets Content-ID header or references request in a Change Set. */
contentId?: string;
/**Field name that needs to be cleared (for example File Field) */
/**
* Field name that needs to be cleared (for example File Field)
* @deprecated Use "property".
*/
fieldName?: string;
/**Single property that needs to be cleared (including the File property) */
property?: string;
}

export interface RetrieveRequest extends CRUDRequest {
Expand All @@ -1352,7 +1357,7 @@ export interface RetrieveRequest extends CRUDRequest {
includeAnnotations?: string;
/**Casts the AttributeMetadata to a specific type. (Used in requests to Attribute Metadata). */
metadataAttributeType?: string;
/**A String representing the name of a single - valued navigation property.Useful when needed to retrieve information about a related record in a single request. */
/**A String representing the name of a single - valued navigation property. Useful when needed to retrieve information about a related record in a single request. */
navigationProperty?: string;
/**A String representing navigation property's Primary Key (GUID) or Alternate Key(s). (For example, to retrieve Attribute Metadata). */
navigationPropertyKey?: string;
Expand Down Expand Up @@ -1619,12 +1624,22 @@ export interface UploadRequest extends CRUDRequest {
data: Uint8Array | Buffer;
/**Name of the file */
fileName: string;
/**File Field Name */
/**The name of File Column (field) */
property?: string;
/**
* File Field Name
* @deprecated Use "property".
*/
fieldName: string;
}

export interface DownloadRequest extends CRUDRequest {
/**File Field Name */
/**The name of File Column (field) */
property?: string;
/**
* File Field Name
* @deprecated Use "property".
*/
fieldName: string;
}

Expand Down
34 changes: 30 additions & 4 deletions src/helpers/Regex.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,42 @@
const uuid = "[0-9A-F]{8}[-]?([0-9A-F]{4}[-]?){3}[0-9A-F]{12}";
const uuid = "[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}";

const uuidRegExp = new RegExp(uuid, "i");
const extractUuidRegExp = new RegExp("^{?(" + uuid + ")}?$", "i");
const extractUuidFromUrlRegExp = new RegExp("(" + uuid + ")\\)$", "i");
//global here is fine because the state is reset inside string.replace function
const removeBracketsFromGuidReg = new RegExp(`{(${uuid})}`, "g");

export function isUuid(value: string): boolean {
const match = new RegExp(uuid, "i").exec(value);
const match = uuidRegExp.exec(value);
return !!match;
}

export function extractUuid(value: string): string | null {
const match = new RegExp("^{?(" + uuid + ")}?$", "i").exec(value);
const match = extractUuidRegExp.exec(value);
return match ? match[1] : null;
}

export function extractUuidFromUrl(url: string): string | null {
const match = new RegExp("(" + uuid + ")\\)$", "i").exec(url);
const match = extractUuidFromUrlRegExp.exec(url);
return match ? match[1] : null;
}

export function removeCurlyBracketsFromUuid(value: string): string {
return value.replace(removeBracketsFromGuidReg, (_match, p1) => p1);
}

export function safelyRemoveCurlyBracketsFromUrl(url: string): string {
//todo: in future I will need to replace this with a negative lookbehind and lookahead

// Split the filter string by quotation marks
const parts = url.split(/(["'].*?["'])/);
return parts
.map((part, index) => {
// Only process parts that are not within quotes
if (index % 2 === 0) {
return removeCurlyBracketsFromUuid(part);
}
return part;
})
.join("");
}
11 changes: 7 additions & 4 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,9 @@ export interface InternalRequest {
/**Sets If-Match header value that enables to use conditional retrieval or optimistic concurrency in applicable requests.*/
ifmatch?: string;
/**Sets Prefer header with value "odata.include-annotations=" and the specified annotation.Annotations provide additional information about lookups, options sets and other complex attribute types. */
includeAnnotations?: string;
includeAnnotations?: string | null;
/**Sets Prefer header request with value "return=representation".Use this property to return just created or updated entity in a single request. */
returnRepresentation?: boolean;
returnRepresentation?: boolean | null;
/**Prefer header values */
prefer?: string | string[];
/**An Array(of Strings) representing the $select OData System Query Option to control which attributes will be returned. */
Expand All @@ -95,21 +95,24 @@ export interface InternalRequest {
/**Boolean that sets the $count system query option with a value of true to include a count of entities that match the filter criteria up to 5000(per page).Do not use $top with $count! */
count?: boolean;
/**Sets the odata.maxpagesize preference value to request the number of entities returned in the response. */
maxPageSize?: number;
maxPageSize?: number | null;
/**An Array(of string) representing the order in which items are returned using the $orderby system query option.Use the asc or desc suffix to specify ascending or descending order respectively.The default is ascending if the suffix isn't applied. */
orderBy?: string[];
/**Limit the number of results returned by using the $top system query option.Do not use $top with $count! */
top?: number;
/**Sets Prefer header with value 'odata.track-changes' to request that a delta link be returned which can subsequently be used to retrieve entity changes. */
trackChanges?: boolean;
/**v.1.7.0+ Web API v9.1+ only! Use this option to specify the name of the file attribute in Dynamics 365. */
/**v.1.7.0+ Web API v9.1+ only! Use this option to specify the name of the file attribute in Dynamics 365.
* @deprecated use property
*/
fieldName?: string;
/**v.1.7.0+ Web API v9.1+ only! Specifies the name of the file */
fileName?: string;
/**v.1.7.7+ A unique partition key value of a logical partition for non-relational custom entity data stored in NoSql tables of Azure heterogenous storage. */
partitionId?: string;
/**v.1.7.7+ Additional query parameters that either have not been implemented yet or they are parameter aliases for "$filter" and "$orderBy". Important! These parameters ARE NOT URI encoded! */
queryParams?: string[];
property?: string;
contentRange?: string;
url?: string;
parameters?: Record<string, any>;
Expand Down
Loading

0 comments on commit a9df87a

Please sign in to comment.