UNPKG

nd-common

Version:

603 lines (594 loc) 23.5 kB
import { InjectionToken, Injectable, Inject, NgModule, forwardRef } from '@angular/core'; import { HttpClient, HttpHeaders, HttpResponse } from '@angular/common/http'; import { of, throwError, Observable } from 'rxjs'; import { mergeMap, map, catchError } from 'rxjs/operators'; import { CommonService, APIVersions, NetDocumentsService, HttpMethod, CallParameters, RecentDocumentType } from 'nd-common'; import { CommonModule } from '@angular/common'; import { HttpModule } from '@angular/http'; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @record */ const ND_TOKEN_CONTROLLER = new InjectionToken('ndTokenController'); /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class RestAPIBaseService { /** * @param {?} http * @param {?} _token */ constructor(http, _token) { this.http = http; this.DEFAULT_REST_VERSION = APIVersions.two; this.tokenService = _token; } /** * This is the rest API call method. This method puts all the parameters in the correct order, * get the authorization token, and handle the call. If the initial call fails because of * 401 then the function makes the same call again after getting a new access token. * * Note: In order to actually see the call go out, you will need to observe it. This is done * by subscribing to it. Search code base for implementation examples. * * @template T * @param {?} p * @param {?=} stripResponse * @return {?} Observable<HttpResponse<any>> RxJs observable of type response, this same type should be return to the controllers caller. */ call(p, stripResponse = true) { /* Construct the URL request string */ // Append: baseUrl + api version + path p.url = this.getUrl(p.path, p.apiVersion); /* Construct the RequestOptionsArgs object */ // Set the request method (default to GET if not specified) if (p.method == null) { p.method = HttpMethod.Get; } // If the request is a GET AND queryArgs were provided then.. if (p.method == HttpMethod.Get && p.queryArgs) { // Flatten the queryArgs object into a string let /** @type {?} */ queryArgs = this.generateQueryArgs(p.queryArgs); let /** @type {?} */ appendage = "?"; // If the URL already has ? in it then.. if (p.url.indexOf(appendage) > -1) { // Change the appendage to & appendage = "&"; } // Add the queryArgs to the request URL p.url += `${appendage}${queryArgs}`; } // Create the header object with the authorization token if it doesn't already exist let /** @type {?} */ httpOptions = {}; httpOptions = { headers: this.BaseHeaders, responseType: 'json', observe: "response", body: p.body }; // Make the call return this.http.request(p.method, p.url, httpOptions).pipe(catchError((err, caught) => { // If the status is 401 then.. if (err.status == 401) { // Call RenewRat to get a new access token return this.tokenService.renew().pipe(mergeMap((token) => { this.AccessToken = token; p.init.headers = this.BaseHeaders; httpOptions["headers"] = this.BaseHeaders; return this.http.request(p.method, p.url, httpOptions); })); } else if (err.status == 304) { return of(new HttpResponse({ status: err.status })); } else { return throwError(err); } }), map((response) => { if (stripResponse) { return response.body; } else { // Returning response works just fine, but we have to cast it as `any` so the TypeScript doesn't complain. return /** @type {?} */ (response); } })); } /** * Creates a query argument string based off of the object passed in. This uses the objects labels as the argument labels. * @param {?} obj The object the query arguments will be based off. * @return {?} The query argument string (without "?") */ generateQueryArgs(obj) { let /** @type {?} */ queryArgs = ""; Object.keys(obj).forEach((key) => { let /** @type {?} */ appendage = ""; // if the query args have not set any values yet then.. if (queryArgs.length) { appendage = "&"; } let /** @type {?} */ value = obj[key]; // If the value inside the object is an array then.. if (Array.isArray(value)) { // If the value array has objects inside then.. if (typeof value[0] === "object") { value = value.map((data) => { return data.ToString(); }).join(","); } else { value = value.join(","); } } queryArgs += appendage + key + "=" + value; }); return queryArgs; } /** * Getter for the access token * @return {?} The access token stored in the classes memory. If empty returns an empty string. */ get AccessToken() { return this.tokenService.token; } /** * Setter for the access token. NOTE: This will trim any white space from the param. * @param {?} newToken The new access token for the RestAPI to use. * @return {?} */ set AccessToken(newToken) { this.tokenService.token = newToken.trim(); } /** * Gets the base url for api request. If the value has not been set, the method calls GenerateBaseUrl(), which will fill in default values. * @return {?} */ get BaseUrl() { if (!this._baseUrl) { this._baseUrl = RestAPIBaseService.GenerateBaseUrl(this.tokenService.host, this.tokenService.useHttps); } return this._baseUrl; } /** * Generates the host url need to make api calls * @param {?=} host The service where the request should be made (defaults to vault.netvoyage.com) * @param {?=} https Indicates if the request should be made via https (defaults to true) * @param {?=} api Indicates if the request should be made against the api pool (defaults to true) * @return {?} */ static GenerateBaseUrl(host = NetDocumentsService.vault, https = true, api = true) { return `${https ? "https" : "http"}://${api ? "api." : ""}${host}`; } /** * Construct the URL request string by appending: baseUrl + api version + path * @param {?} path The controller path provided by the caller. Example: /System/info/... * @param {?=} version The API version number the caller is directing to. If no number is provided the default verion is assumed. * @return {?} The url the API controller will call to. */ getUrl(path, version) { let /** @type {?} */ callUrl = this.BaseUrl; callUrl += version ? version : this.DEFAULT_REST_VERSION; callUrl += path; return callUrl; } /** * Getter for the request headers. This will add in the access token as well as the response acceptance type (JSON) * @return {?} The Http header object. */ get BaseHeaders() { return new HttpHeaders({ "Authorization": "Bearer " + this.AccessToken, "Accept": "application/json" //, }); } /** * Handle url string encoding. Ensures double encoding when necessary. * @param {?} attribute The string to be url encoded. * @return {?} */ static urlEncodeString(attribute) { if (attribute != null) { // Check if we have a string with special characters that will require us to double encode the component. if (CommonService.stringContainsAny(attribute, this.ENCODING_SUBSTRINGS)) { attribute = encodeURIComponent(attribute); } attribute = encodeURIComponent(attribute); } return attribute; } /** * Prepare an attribute value for the call to the Rest API. * Enclose in double quote marks an attribute that contains a comma or a double quote. * Replace double quote marks with pairs of double quote marks. * See the "Lookup table query" section of the Rest API documentation. * @param {?} attribute user-supplied workspace attribute needing prep and encoding * @return {?} */ static attributeQueryEncode(attribute) { if (attribute && attribute.length > 0) { // See whether the attribute contains a comma or a double quote mark. if (attribute.indexOf(",") > -1 || attribute.indexOf('"') > -1) { // Replace double quote marks with pairs of double quote marks. attribute = attribute.replace(/"/g, '\"\"'); // Provide a leading double quote mark if necessary. if (!attribute.startsWith('\"', 0)) { attribute = `\"${attribute}`; } // Provide a trailing double quote mark if necessary. if (!attribute.endsWith('\"', attribute.length)) { attribute = `${attribute}\"`; } } // Encode the attribute. attribute = encodeURIComponent(attribute); } return attribute; } /** * @param {?} envUrl * @return {?} */ static cleanEnv(envUrl) { const /** @type {?} */ envNBReg = /\/NB\d/; if (!envUrl) { return envUrl; } // If the envUrl is a ShareSpace and it is not in the form of /NB12345567890.nev then encode the envUrl if (getItemType(envUrl) == "NB" && !envNBReg.test(envUrl)) { if (envUrl.indexOf("|") < 0) envUrl += "|0"; envUrl = encodeURI(envUrl.split("|")[0]) + "|" + envUrl.split("|")[1]; } envUrl = envUrl.replace(/\//g, ":"); return envUrl; } /** * @param {?} filter * @return {?} */ static createFilterList(filter) { let /** @type {?} */ seperator = " extension eq "; return (seperator + filter.join(seperator)).trim(); } } /** * A well known array of strings that is used to determine if double encoding is needed. */ RestAPIBaseService.ENCODING_SUBSTRINGS = ["/", "&", "\\", "+", "?", "%"]; RestAPIBaseService.decorators = [ { type: Injectable }, ]; /** @nocollapse */ RestAPIBaseService.ctorParameters = () => [ { type: HttpClient }, { type: undefined, decorators: [{ type: Inject, args: [ND_TOKEN_CONTROLLER,] }] } ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class DocumentControllerService extends RestAPIBaseService { /** * @param {?} h * @param {?} _token */ constructor(h, _token) { super(h, _token); this.h = h; this.controllerUrl = "/document"; } /** * Fetches information of the specified document. * * Queryable items: * [select] A comma separated list of strings that define what data should be returned in the request. * See OptionalAttributes for a complete list of attribute flags that control what is returned. * These strings can also define the custom attributes to be returned. This is done by specifying * the custom attribute number (in string form). If any descriptions are required for the * specified custom attributes, please add a leading \"1\" to the string form of the custom attribute number. * p [id] the id of the document to fetch information on. * @param {?} p * @return {?} */ getInfo(p) { // If the caller did not provide a document id then throw an error. if (p.id == undefined) return throwError("id is required."); const /** @type {?} */ param = new CallParameters(); param.apiVersion = APIVersions.two; param.method = HttpMethod.Get; param.path = `${this.controllerUrl}/${p.id}/info`; // If the caller provided queryArgs then.. if (p.queryArgs !== undefined) { param.queryArgs = p.queryArgs; } return this.call(param); } /** * Fetches information of the specified documents. * * Queryable items: * [select] A comma separated list of strings that define what data should be returned in the request. * See OptionalAttributes for a complete list of attribute flags that control what is returned. * These strings can also define the custom attributes to be returned. This is done by specifying * the custom attribute number (in string form). If any descriptions are required for the * specified custom attributes, please add a leading \"1\" to the string form of the custom attribute number. * p - List of documents to retrieve information for. Should be a comma separated list of envelope and/or document ids. * @param {?} p * @return {?} */ getListOfDocuments(p) { // If the caller did not provide a document id then throw an error. if (p.id == undefined) return throwError("id is required."); const /** @type {?} */ param = new CallParameters(); param.apiVersion = APIVersions.two; param.method = HttpMethod.Post; param.path = `${this.controllerUrl}\/list`; param.body = `id=${p.id}&select=${p.queryArgs.select}`; param.headers = this.BaseHeaders; param.headers.append("Content-Type", "application/x-www-form-urlencoded"); return this.call(param); } /** * Get list of recent documents * @param {?} p * @param {?} documentType * @param {?=} lastModifiedDate * @return {?} */ getRecent(p, documentType, lastModifiedDate = '') { let /** @type {?} */ param = new CallParameters(); if (documentType === null || documentType === undefined) { documentType = RecentDocumentType.All; } if (p.queryArgs !== undefined) { param.queryArgs = p.queryArgs; } param.headers = !param.headers ? this.BaseHeaders : param.headers; if (lastModifiedDate) { param.headers.append("If-Modified-Since", lastModifiedDate); } else { param.headers.append("Cache-Control", 'no-cache'); param.headers.append("Pragma", 'no-cache'); param.headers.append("Expires", 'Sat, 01 Jan 2000 00:00:00 GMT'); } param.path = `${this.controllerUrl}/recent/${RecentDocumentType[documentType].toLowerCase()}`; param.method = HttpMethod.Get; param.apiVersion = APIVersions.two; return this.call(param, false); } /** * Get GrantAccessRequest appurl and error Text * @param {?} p * @return {?} */ getGrantAccessRequestInfo(p) { let /** @type {?} */ param = new CallParameters(); if (p["Id"] == undefined) throw "id is required."; else { param.path = this.controllerUrl + "/" + p["Id"] + "/grant_access_request_info"; } param.method = HttpMethod.Get; param.apiVersion = APIVersions.two; return this.call(param); } /** * Fetches information of the specified document's linked documents. * * Queryable items: * [select] A comma separated list of strings that define what data should be returned in the request. * See OptionalAttributes (SelectParameters) for a complete list of attribute flags that control what is returned. * These strings can also define the custom attributes to be returned. This is done by specifying * the custom attribute number (in string form). If any descriptions are required for the * specified custom attributes, please add a leading \"1\" to the string form of the custom attribute number. * p [id] the id of the document to fetch information on it's linked documents. * @param {?} p * @return {?} */ getLinkedDocuments(p) { // If the caller did not provide a document id then throw an error. if (p.id == undefined) { return throwError("Document getLinkedDocuments id is required."); } const /** @type {?} */ param = new CallParameters(); param.apiVersion = APIVersions.two; param.method = HttpMethod.Get; param.path = `${this.controllerUrl}\/${p.id}\/linked`; // If the caller provided queryArgs then.. if (p.queryArgs !== undefined) { param.queryArgs = p.queryArgs; } return this.call(param); } /** * Puts new version of document. * Uses first rest api. * p contains document id and IVersion as body * @param {?} p * @return {?} */ putNewVersion(p) { // If the caller did not provide a document id then throw an error. if (p.id == undefined) { return Observable.throw("Document putNewVersion id is required."); } const /** @type {?} */ param = new CallParameters(); param.apiVersion = APIVersions.one; param.method = HttpMethod.Put; param.path = `${this.controllerUrl}\/${p.id}\/new`; if (p.body != null) { param.path += "?"; if (p.body.Name != undefined) { param.path += `vername=${p.body.Name}&`; } if (p.body.Description != undefined) { param.path += `version_description=${p.body.Description}&`; } if (p.body.Official) { param.path += `official=Y`; } } return this.call(param); } /** * Check in a document * p should include: * { string } id Document id. * p may include: * { File } [file] Optional file object to check in. * { string } [extension] New file extension.Only used in conjunction with file. * { boolean } [notify] If true, email will be sent to user who checked out the document. * @param {?} p * @return {?} */ checkIn(p) { // If the caller did not provide a document id then throw an error. if (p.id == undefined) { return Observable.throw("Document checkIn id is required."); } var /** @type {?} */ actionName = "checkin"; let /** @type {?} */ param = new CallParameters(); param.apiVersion = APIVersions.one; param.method = HttpMethod.Post; param.path = `${this.controllerUrl}`; param.headers = this.BaseHeaders; if (p["file"] != undefined) { let /** @type {?} */ form = new FormData(); form.append("action", actionName); form.append("id", p.id); if (p["notify"] !== undefined) { form.append("notify", p["notify"]); } if (p["extension"] !== undefined) { form.append("extension", p["extension"]); } form.append("file", p["file"]); param.body = form; } else { param.headers.append("Content-Type", "application/x-www-form-urlencoded"); param.body = `id=${p.id}&action=${actionName}`; if (p["notify"] !== undefined) { param.body += `&notify=${p["notify"]}`; } } return this.call(param); } /** * Upload new version contents * {File} file File to upload * {string} id Document id * {string} [extension] New file extension * {string} [verName] New version name * @param {?} p * @return {?} */ putNewVersionContents(p) { // If the caller did not provide a document id then throw an error. if (p.id == undefined) { return Observable.throw("Document putFileContents id is required."); } if (p["file"] == undefined) { return Observable.throw("Document putFileContents file is required."); } if (p["extension"] == undefined) { return Observable.throw("Document putFileContents extension is required."); } let /** @type {?} */ param = new CallParameters(); param.apiVersion = APIVersions.one; param.method = HttpMethod.Put; param.path = `${this.controllerUrl}\/${p.id}\/new?`; if (p["extension"] != undefined) { param.path += `extension=${p["extension"]}`; } if (p["verName"] != undefined) { param.path += `&vername=${p["verName"]}`; } param.headers = this.BaseHeaders; let /** @type {?} */ form = new FormData(); form.append("file", p["file"]); form.append("processData", "false"); form.append("contentType", p["file"].type); param.body = form; return this.call(param); } /** * Retrieve document history * id Document id. * order Can take two values, either "none" (the default) or "chronological". If another value is used, simply apply "none". * @param {?} p * @return {?} */ getHistory(p) { // If the caller did not provide a document id then throw an error. if (p.id == undefined) { return throwError("Document getLinkedDocuments id is required."); } const /** @type {?} */ param = new CallParameters(); param.apiVersion = APIVersions.one; param.method = HttpMethod.Get; param.path = `${this.controllerUrl}\/${p.id}\/history`; // If the caller provided queryArgs then.. if (p.queryArgs !== undefined) { param.queryArgs = p.queryArgs; } return this.call(param); } } DocumentControllerService.decorators = [ { type: Injectable }, ]; /** @nocollapse */ DocumentControllerService.ctorParameters = () => [ { type: HttpClient }, { type: undefined, decorators: [{ type: Inject, args: [ND_TOKEN_CONTROLLER,] }] } ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ class ndApiModule { /** * @param {?} tokenControllerClass * @return {?} */ static forRoot(tokenControllerClass) { return { ngModule: ndApiModule, providers: [ { provide: ND_TOKEN_CONTROLLER, useExisting: forwardRef(() => tokenControllerClass) }, DocumentControllerService ] }; } } ndApiModule.decorators = [ { type: NgModule, args: [{ imports: [ CommonModule, HttpModule ] },] }, ]; /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes} checked by tsc */ /** * Generated bundle index. Do not edit. */ export { ndApiModule, DocumentControllerService, ND_TOKEN_CONTROLLER, RestAPIBaseService as ɵa }; //# sourceMappingURL=nd-common-api.js.map