Skip to content

Commit

Permalink
refactoring; fixing readme
Browse files Browse the repository at this point in the history
  • Loading branch information
AleksandrRogov committed Jun 15, 2024
1 parent 15dbcb9 commit 408a184
Show file tree
Hide file tree
Showing 13 changed files with 627 additions and 657 deletions.
18 changes: 12 additions & 6 deletions .github/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,11 +157,16 @@ Once the web file is uploaded, it can be included in a template, a page or a for

With CDN, it is a bit easier: no need to create and upload a web file - just include the script in your template, page or a form:
```html
<script type="text/javascript" src="https://unpkg.com/[email protected].0/dist/dynamics-web-api.min.js"></script>
<script type="text/javascript" src="https://unpkg.com/[email protected].4/dist/dynamics-web-api.min.js"></script>
```

And you are good to go! DynamicsWebApi will automatically detect if the library is running on Power Pages and will supply an anti-forgery token with each request.

#### Limitations
Currently, there are some ootb limitations in the Power Pages:
1. Batch operations are not supported. Hopefully, Microsoft will add it in the future.
2. Long requests (with URL more than 2000 chars) are not supported. This is because of the 1st limitation. DynamicsWebApi will try to convert it to a Batch operation which will ultimately fail because they aren't supported.

### Node.js
To use DynamicsWebApi in Node.js install the `dynamics-web-api` package from NPM:

Expand All @@ -173,7 +178,7 @@ Then include it in your script:

```ts
//CommonJS
const DynamicsWebApi = require("dynamics-web-api");
const DynamicsWebApi = require("dynamics-web-api").DynamicsWebApi;

//ESM
import { DynamicsWebApi } from "dynamics-web-api";
Expand Down Expand Up @@ -319,14 +324,14 @@ Both `dataApi` and `searchApi` can be omitted from a configuration. Their defaul
**dataApi** properties:
| Property Name | Type | Description |
|--------|--------|--------|
| path | `String` | Optional. A path to API, default: "data". |
| version | `String` | Optional. API Version, default: "9.2". |
| path | `string` | Optional. A path to API, default: "data". |
| version | `string` | Optional. API Version, default: "9.2". |

**searchApi** properties:
| Property Name | Type | Description |
|--------|--------|--------|
| path | `String` | Optional. A path to API, default: "search". |
| version | `String` | Optional. API Version, default: "1.0". |
| path | `string` | Optional. A path to API, default: "search". |
| version | `string` | Optional. API Version, default: "1.0". |

## Request Examples

Expand Down Expand Up @@ -2523,6 +2528,7 @@ the config option "formatted" will enable developers to retrieve all information
- [X] Implement [Dataverse Search API](https://docs.microsoft.com/en-us/power-apps/developer/data-platform/webapi/relevance-search). `Added in v.2.0.0`
- [X] Allow custom headers to be passed to the request. [#151](https://github.com/AleksandrRogov/DynamicsWebApi/issues/151). `Added in v.2.1.0`
- [X] Support Microsoft Power Pages. `Added in v.2.1.0`
- [ ] Fully custom request.
Many more features to come!
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ Once the web file is uploaded, it can be included in a template, a page or a for

With CDN, it is a bit easier: no need to create and upload a web file - just include the script in your template, page or a form:
```html
<script type="text/javascript" src="https://unpkg.com/[email protected].0/dist/dynamics-web-api.min.js"></script>
<script type="text/javascript" src="https://unpkg.com/[email protected].4/dist/dynamics-web-api.min.js"></script>
```

And you are good to go! DynamicsWebApi will automatically detect if the library is running on Power Pages and will supply an anti-forgery token with each request.
Expand All @@ -77,7 +77,7 @@ Then include it in your script:

```ts
//CommonJS
const DynamicsWebApi = require("dynamics-web-api");
const DynamicsWebApi = require("dynamics-web-api").DynamicsWebApi;

//ESM
import { DynamicsWebApi } from "dynamics-web-api";
Expand Down
26 changes: 13 additions & 13 deletions src/client/RequestClient.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import type * as Core from "../types";
import { Utility } from "../utils/Utility";
import { InternalConfig } from "../utils/Config";
import { RequestUtility } from "../utils/Request";
import * as RequestUtility from "../utils/Request";
import { DynamicsWebApiError, ErrorHelper } from "../helpers/ErrorHelper";
import { Core } from "../types";
import { executeRequest } from "./helpers/executeRequest";
import { AccessToken } from "../dynamics-web-api";

const _addResponseParams = (requestId, responseParams) => {
const _addResponseParams = (requestId: string, responseParams: Record<string, any>) => {
if (_responseParseParams[requestId]) _responseParseParams[requestId].push(responseParams);
else _responseParseParams[requestId] = [responseParams];
};

const _addRequestToBatchCollection = (requestId, request) => {
const _addRequestToBatchCollection = (requestId: string, request: Core.InternalRequest) => {
if (_batchRequestCollection[requestId]) _batchRequestCollection[requestId].push(request);
else _batchRequestCollection[requestId] = [request];
};
Expand Down Expand Up @@ -106,13 +106,13 @@ export class RequestClient {
method: request.method!,
uri: url!.toString() + request.path,
data: processedData,
additionalHeaders: request.headers,
responseParams: _responseParseParams,
isAsync: request.async,
timeout: request.timeout || config.timeout,
proxy: config.proxy,
isAsync: request.async,
headers: request.headers!,
requestId: request.requestId!,
abortSignal: request.signal,
responseParams: _responseParseParams,
timeout: request.timeout || config.timeout,
});
}

Expand All @@ -133,9 +133,9 @@ export class RequestClient {
);

const result = await _runRequest(request, config);
RequestUtility.entityNames = {};
RequestUtility.setEntityNames({});
for (let i = 0; i < result.data.value.length; i++) {
RequestUtility.entityNames[result.data.value[i].LogicalName] = result.data.value[i].EntitySetName;
RequestUtility.entityNames![result.data.value[i].LogicalName] = result.data.value[i].EntitySetName;
}

return RequestUtility.findCollectionName(entityName) || entityName;
Expand Down Expand Up @@ -204,12 +204,12 @@ export class RequestClient {
//no need to make a request to web api if it's a part of batch
RequestUtility.compose(request, config);
//add response parameters to parse
_addResponseParams(request.requestId, request.responseParameters);
_addRequestToBatchCollection(request.requestId, request);
_addResponseParams(request.requestId!, request.responseParameters);
_addRequestToBatchCollection(request.requestId!, request);
}

static _clearTestData(): void {
RequestUtility.entityNames = null;
RequestUtility.setEntityNames(null);
_responseParseParams = {};
_batchRequestCollection = {};
}
Expand Down
4 changes: 2 additions & 2 deletions src/client/helpers/executeRequest.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Core } from "../../types";
import type { RequestOptions, WebApiResponse } from "../../types";

export async function executeRequest(options: Core.RequestOptions): Promise<Core.WebApiResponse> {
export async function executeRequest(options: RequestOptions): Promise<WebApiResponse> {
return global.DWA_BROWSER ? require("../xhr").executeRequest(options) : require("../http").executeRequest(options);
}
2 changes: 1 addition & 1 deletion src/client/helpers/parseResponse.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { Utility } from "../../utils/Utility";
import { ErrorHelper, DynamicsWebApiError } from "../../helpers/ErrorHelper";
import { dateReviver } from "./dateReviver";
import { Core } from "../../types";
import type * as Core from "../../types";
import { extractUuidFromUrl } from "../../helpers/Regex";

function getFormattedKeyValue(keyName: string, value: any): any[] {
Expand Down
20 changes: 10 additions & 10 deletions src/client/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import * as https from "https";
import HttpProxyAgent from "http-proxy-agent";
import HttpsProxyAgent from "https-proxy-agent";
import { Core } from "../types";
import type * as Core from "../types";
import { ErrorHelper } from "./../helpers/ErrorHelper";
import { parseResponse } from "./helpers/parseResponse";

Expand Down Expand Up @@ -57,22 +57,22 @@ function _executeRequest(
errorCallback: (error: Core.WebApiErrorResponse | Core.WebApiErrorResponse[]) => void
) {
const data = options.data;
const additionalHeaders = options.additionalHeaders;
const headers = options.headers;
const responseParams = options.responseParams;
const signal = options.abortSignal;

const headers: http.OutgoingHttpHeaders = {};
const httpHeaders: http.OutgoingHttpHeaders = {};

if (data) {
headers["Content-Type"] = additionalHeaders["Content-Type"];
headers["Content-Length"] = data.length;
httpHeaders["Content-Type"] = headers["Content-Type"];
httpHeaders["Content-Length"] = data.length;

delete additionalHeaders["Content-Type"];
delete headers["Content-Type"];
}

//set additional headers
for (let key in additionalHeaders) {
headers[key] = additionalHeaders[key];
for (let key in headers) {
httpHeaders[key] = headers[key];
}
const parsedUrl = new URL(options.uri);
const protocol = parsedUrl.protocol?.slice(0, -1) || "https";
Expand All @@ -84,7 +84,7 @@ function _executeRequest(
path: parsedUrl.pathname + parsedUrl.search,
method: options.method,
timeout: options.timeout || 0,
headers: headers,
headers: httpHeaders,
signal: signal,
};

Expand All @@ -99,7 +99,7 @@ function _executeRequest(

if (options.proxy) {
const hostHeader = new URL(options.proxy.url).host;
if (hostHeader) headers.host = hostHeader;
if (hostHeader) httpHeaders.host = hostHeader;
}

const request = protocolInterface.request(internalOptions, function (res) {
Expand Down
8 changes: 4 additions & 4 deletions src/client/xhr.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Core } from "../types";
import type * as Core from "../types";
import { ErrorHelper } from "./../helpers/ErrorHelper";
import { parseResponse } from "./helpers/parseResponse";
import { parseResponseHeaders } from "./helpers/parseResponseHeaders";
Expand All @@ -15,7 +15,7 @@ function _executeRequest(
errorCallback: (error: Core.WebApiErrorResponse | Core.WebApiErrorResponse[]) => void
) {
const data = options.data;
const additionalHeaders = options.additionalHeaders;
const headers = options.headers;
const responseParams = options.responseParams;
const signal = options.abortSignal;

Expand All @@ -35,8 +35,8 @@ function _executeRequest(
request.open(options.method, options.uri, options.isAsync || false);

//set additional headers
for (let key in additionalHeaders) {
request.setRequestHeader(key, additionalHeaders[key]);
for (let key in headers) {
request.setRequestHeader(key, headers[key]);
}

request.onreadystatechange = function () {
Expand Down
11 changes: 4 additions & 7 deletions src/dynamics-web-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import { Utility } from "./utils/Utility";
import { ErrorHelper } from "./helpers/ErrorHelper";
import { RequestClient } from "./client/RequestClient";
import type { Core } from "./types";
import type * as Core from "./types";

/**
* Microsoft Dynamics CRM Web API helper library written in JavaScript.
Expand Down Expand Up @@ -616,7 +616,7 @@ export class DynamicsWebApi {
const functionParameters = Utility.buildFunctionParameters(internalRequest.parameters);

internalRequest.method = "GET";
internalRequest._additionalUrl = functionName + functionParameters.key;
internalRequest.addPath = functionName + functionParameters.key;
internalRequest.queryParams = functionParameters.queryParams;
internalRequest._isUnboundRequest = !internalRequest.collection;
internalRequest.functionName = "callFunction";
Expand All @@ -641,7 +641,7 @@ export class DynamicsWebApi {
internalRequest.method = "POST";
internalRequest.functionName = "callAction";

internalRequest._additionalUrl = request.actionName;
internalRequest.addPath = request.actionName;
internalRequest._isUnboundRequest = !internalRequest.collection;
internalRequest.data = request.action;

Expand Down Expand Up @@ -1733,10 +1733,7 @@ export interface Config {
}

/**Header collection type */
export type HeaderCollection = {
/**key-value */
[key: string]: string;
};
export type HeaderCollection = Record<string, string>;

export interface ProxyConfig {
/**Proxy server url */
Expand Down
Loading

0 comments on commit 408a184

Please sign in to comment.