UNPKG

@web-atoms/core-docs

Version:
609 lines 24.8 kB
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; var __param = (this && this.__param) || function (paramIndex, decorator) { return function (target, key) { decorator(target, key, paramIndex); } }; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; (function (factory) { if (typeof module === "object" && typeof module.exports === "object") { var v = factory(require, exports); if (v !== undefined) module.exports = v; } else if (typeof define === "function" && define.amd) { define(["require", "exports", "./AjaxOptions", "../../App", "../../Atom", "../../core/AtomBridge", "../../core/types", "../../di/Inject", "../../di/TypeKey", "../CacheService", "../JsonService", "./JsonError"], factory); } })(function (require, exports) { "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.BaseService = exports.ServiceParameter = exports.Cancel = exports.Patch = exports.Put = exports.Delete = exports.Get = exports.Post = exports.XmlBody = exports.BodyFormModel = exports.RawBody = exports.Body = exports.Queries = exports.Query = exports.Header = exports.Path = void 0; const AjaxOptions_1 = require("./AjaxOptions"); const App_1 = require("../../App"); const Atom_1 = require("../../Atom"); const AtomBridge_1 = require("../../core/AtomBridge"); const types_1 = require("../../core/types"); const Inject_1 = require("../../di/Inject"); const TypeKey_1 = require("../../di/TypeKey"); const CacheService_1 = require("../CacheService"); const JsonService_1 = require("../JsonService"); const JsonError_1 = require("./JsonError"); // tslint:disable-next-line function methodBuilder(method) { // tslint:disable-next-line return function (url, options) { // tslint:disable-next-line return function (target, propertyKey, descriptor) { target.methods = target.methods || {}; const a = target.methods[propertyKey]; const oldFunction = descriptor.value; // tslint:disable-next-line:typedef descriptor.value = function (...args) { if (this.testMode || Atom_1.Atom.designMode) { // tslint:disable-next-line:no-console console.log(`Test Design Mode: ${url} .. ${args.join(",")}`); const ro = oldFunction.apply(this, args); if (ro) { return ro; } } const jsCache = options ? options.jsCacheSeconds : 0; if (jsCache) { const cacheService = this.app.resolve(CacheService_1.default); const jArgs = args.map((arg) => arg instanceof types_1.CancelToken ? null : arg); const key = `${this.constructor.name}:${method}:${url}:${JSON.stringify(jArgs)}`; return cacheService.getOrCreate(key, (e) => { e.ttlSeconds = jsCache; return this.invoke(url, method, a, args, options); }); } return this.invoke(url, method, a, args, options); }; }; }; } // tslint:disable-next-line function parameterBuilder(paramName, defaultValue) { // tslint:disable-next-line return function (key) { // console.log("Declaration"); // console.log({ key:key}); // tslint:disable-next-line return function (target, propertyKey, parameterIndex) { // console.log("Instance"); // console.log({ key:key, propertyKey: propertyKey,parameterIndex: parameterIndex }); target.methods = target.methods || {}; let a = target.methods[propertyKey]; if (!a) { a = []; target.methods[propertyKey] = a; } a[parameterIndex] = new ServiceParameter(paramName, key, defaultValue); }; }; } /** * This will register Url path fragment on parameter. * * @example * * @Get("/api/products/{category}") * async getProducts( * @Path("category") category: number * ): Promise<Product[]> { * } * * @export * @function Path * @param {name} - Name of the parameter */ exports.Path = parameterBuilder("Path"); /** * This will register header on parameter. * * @example * * @Get("/api/products/{category}") * async getProducts( * @Header("x-http-auth") category: number * ): Promise<Product[]> { * } * * @export * @function Path * @param {name} - Name of the parameter */ exports.Header = parameterBuilder("Header"); /** * This will register Url query fragment on parameter. * * @example * * @Get("/api/products") * async getProducts( * @Query("category") category: number * ): Promise<Product[]> { * } * * @export * @function Query * @param {name} - Name of the parameter */ exports.Query = parameterBuilder("Query"); /** * This will register Url query fragments on parameter of type object * * @example * * @Get("/api/products") * async getProducts( * @Queries queries: { [key: string]: string | number | boolean | null } * ): Promise<Product[]> { * return null; * } */ exports.Queries = parameterBuilder("Queries")(""); /** * This will register data fragment on ajax. * * @example * * @Post("/api/products") * async getProducts( * @Query("id") id: number, * @Body product: Product * ): Promise<Product[]> { * } * * @export * @function Body */ exports.Body = parameterBuilder("Body")(""); exports.RawBody = parameterBuilder("RawBody")(""); /** * This will register data fragment on ajax in old formModel way. * * @example * * @Post("/api/products") * async getProducts( * @Query("id") id: number, * @BodyFormModel product: Product * ): Promise<Product[]> { * } * * @export * @function BodyFormModel */ exports.BodyFormModel = parameterBuilder("BodyFormModel")(""); exports.XmlBody = parameterBuilder("XmlBody")(""); /** * Http Post method * @example * * @Post("/api/products") * async saveProduct( * @Body product: Product * ): Promise<Product> { * } * * @export * @function Post * @param {url} - Url for the operation */ exports.Post = methodBuilder("Post"); /** * Http Get Method * * @example * * @Get("/api/products/{category}") * async getProducts( * @Path("category") category?:string * ): Promise<Product[]> { * } * * @export * @function Body */ exports.Get = methodBuilder("Get"); /** * Http Delete method * @example * * @Delete("/api/products") * async deleteProduct( * @Body product: Product * ): Promise<Product> { * } * * @export * @function Delete * @param {url} - Url for the operation */ exports.Delete = methodBuilder("Delete"); /** * Http Put method * @example * * @Put("/api/products") * async saveProduct( * @Body product: Product * ): Promise<Product> { * } * * @export * @function Put * @param {url} - Url for the operation */ exports.Put = methodBuilder("Put"); /** * Http Patch method * @example * * @Patch("/api/products") * async saveProduct( * @Body product: any * ): Promise<Product> { * } * * @export * @function Patch * @param {url} - Url for the operation */ exports.Patch = methodBuilder("Patch"); /** * Cancellation token * @example * * @Put("/api/products") * async saveProduct( * @Body product: Product * @Cancel cancel: CancelToken * ): Promise<Product> { * } * * @export * @function Put * @param {url} - Url for the operation */ function Cancel(target, propertyKey, parameterIndex) { if (!target.methods) { target.methods = {}; } let a = target.methods[propertyKey]; if (!a) { a = []; target.methods[propertyKey] = a; } a[parameterIndex] = new ServiceParameter("cancel", ""); } exports.Cancel = Cancel; class ServiceParameter { constructor(type, key, defaultValue) { this.type = type; this.key = key; this.defaultValue = defaultValue; this.type = type.toLowerCase(); this.key = key; } } exports.ServiceParameter = ServiceParameter; function BaseUrl(baseUrl) { return (target) => { const key = TypeKey_1.TypeKey.get(target); BaseService.baseUrls[key] = baseUrl; }; } exports.default = BaseUrl; const globalNS = (typeof global !== "undefined") ? global : window; if (!globalNS.XMLHttpRequest) { // tslint:disable-next-line: no-var-requires globalNS.XMLHttpRequest = require("xmlhttprequest").XMLHttpRequest; } /** * * * @export * @class BaseService */ let BaseService = class BaseService { constructor(app, jsonService) { this.app = app; this.jsonService = jsonService; this.testMode = false; this.showProgress = true; this.showError = false; // bs this.methods = {}; this.methodReturns = {}; this.jsonOptions = null; this.headers = null; this.jsonOptions = Object.assign({}, this.jsonService.options); } encodeData(o) { o.dataType = "application/json"; o.data = this.jsonService.stringify(o.data, this.jsonOptions); o.contentType = "application/json"; return o; } sendResult(result, error) { return new Promise((resolve, reject) => { if (error) { setTimeout(() => { reject(error); }, 1); return; } setTimeout(() => { resolve(result); }, 1); }); } invoke(url, method, bag, values, methodOptions) { return __awaiter(this, void 0, void 0, function* () { if (this.baseUrl === undefined) { let p = Object.getPrototypeOf(this); while (p) { const t = TypeKey_1.TypeKey.get(p.constructor || p); const bu = BaseService.baseUrls[t]; if (bu) { this.baseUrl = bu; break; } p = Object.getPrototypeOf(p); } if (this.baseUrl === undefined) { this.baseUrl = null; } } if (this.baseUrl) { if (!/^\//.test(url)) { url = `${this.baseUrl}${url}`; } } const busyIndicator = this.showProgress ? (this.app.createBusyIndicator()) : null; try { url = UMD.resolvePath(url); let options = new AjaxOptions_1.AjaxOptions(); options.method = method; if (methodOptions) { options.headers = methodOptions.headers; options.dataType = methodOptions.accept; } const methodHeaders = (options.headers = options.headers || {}); const headers = this.headers ? (Object.assign(Object.assign({}, this.headers), methodHeaders)) : methodHeaders; // this is necessary to support IsAjaxRequest in ASP.NET MVC if (!headers["X-Requested-With"]) { headers["X-Requested-With"] = "XMLHttpRequest"; } options.dataType = options.dataType || "application/json"; const jsonOptions = Object.assign(Object.assign({}, this.jsonOptions), (methodOptions ? methodOptions.jsonOptions : {})); if (bag) { for (let i = 0; i < bag.length; i++) { const p = bag[i]; const vi = values[i]; const v = vi === undefined ? p.defaultValue : vi; if (v instanceof types_1.CancelToken) { options.cancel = v; continue; } switch (p.type) { case "path": if (v === undefined) { continue; } const vs = v + ""; const replacer = `{${p.key}}`; url = url.split(replacer).join(vs); break; case "query": if (v === undefined) { continue; } if (url.indexOf("?") === -1) { url += "?"; } if (!/(\&|\?)$/.test(url)) { url += "&"; } url += `${encodeURIComponent(p.key)}=${encodeURIComponent(v)}`; break; case "queries": if (url.indexOf("?") === -1) { url += "?"; } if (!/(\&|\?)$/.test(url)) { url += "&"; } for (const key in v) { if (v.hasOwnProperty(key)) { const element = v[key]; if (element !== undefined) { url += `${encodeURIComponent(key)}=${encodeURIComponent(element)}&`; } } } break; case "body": options.data = v; options = this.encodeData(options); break; case "bodyformmodel": options.data = v; break; case "rawbody": options.data = v; break; case "xmlbody": options.contentType = "text/xml"; options.data = v; break; case "cancel": options.cancel = v; break; case "header": if (v === undefined) { continue; } headers[p.key] = v; break; } } } options.url = url; const xhr = yield this.ajax(url, options); if (/json/i.test(xhr.responseType)) { const text = xhr.responseText; const response = this.jsonService.parse(text, jsonOptions); if (xhr.status >= 400) { throw new JsonError_1.default(typeof response === "string" ? response : (response.exceptionMessage || response.message || text || "Json Server Error"), response); } if (methodOptions && methodOptions.returnHeaders) { return { headers: this.parseHeaders(xhr.responseHeaders), value: response }; } return response; } if (xhr.status >= 400) { throw new Error(xhr.responseText || "Server Error"); } if (methodOptions && methodOptions.returnHeaders) { return { headers: this.parseHeaders(xhr.responseHeaders), value: xhr.responseText }; } return xhr.responseText; } finally { if (busyIndicator) { busyIndicator.dispose(); } } }); } parseHeaders(headers) { if (typeof headers === "object") { return headers; } return (headers || "") .split("\n") .reduce((pv, c) => { const cv = c.split(":"); pv[cv[0]] = (cv[1] || "").trim(); return pv; }, {}); } ajax(url, options) { return __awaiter(this, void 0, void 0, function* () { // return new CancellablePromise(); url = url || options.url; // no longer needed, watch must provide functionality of waiting and cancelling // await Atom.delay(1, options.cancel); if (options.cancel && options.cancel.cancelled) { throw new Error("cancelled"); } if (AtomBridge_1.AtomBridge.instance.ajax) { return yield new Promise((resolve, reject) => { AtomBridge_1.AtomBridge.instance.ajax(url, options, (r) => { resolve(options); }, (e) => { reject(e); }, null); }); } const xhr = new XMLHttpRequest(); return yield new Promise((resolve, reject) => { if (options.cancel && options.cancel.cancelled) { reject(options.cancel.cancelled); return; } if (options.cancel) { options.cancel.registerForCancel((r) => { xhr.abort(); reject(r); return; }); } xhr.onreadystatechange = (e) => { if (xhr.readyState === XMLHttpRequest.DONE) { options.status = xhr.status; options.responseText = xhr.responseText; // options.responseHeaders = (xhr.getAllResponseHeaders()) // .split("\n") // .map((s) => s.trim().split(":")) // .reduce((pv, cv) => pv[cv[0]] = cv[1], {}); options.responseHeaders = xhr.getAllResponseHeaders(); const ct = xhr.getResponseHeader("content-type"); options.responseType = ct || xhr.responseType; resolve(options); } }; xhr.open(options.method, url, true); if (options.dataType) { xhr.setRequestHeader("accept", options.dataType); } if (options.contentType) { xhr.setRequestHeader("content-type", options.contentType); } const h = options.headers; if (h) { for (const key in h) { if (h.hasOwnProperty(key)) { const element = h[key]; xhr.setRequestHeader(key, element.toString()); } } } try { xhr.send(options.data); } catch (e) { options.status = xhr.status; options.responseText = xhr.responseText; // options.responseHeaders = (xhr.getAllResponseHeaders()) // .split("\n") // .map((s) => s.trim().split(":")) // .reduce((pv, cv) => pv[cv[0]] = cv[1], {}); options.responseHeaders = xhr.getAllResponseHeaders(); const ct = xhr.getResponseHeader("content-type"); options.responseType = ct || xhr.responseType; resolve(options); } }); }); } }; BaseService.baseUrls = {}; BaseService = __decorate([ __param(0, Inject_1.Inject), __param(1, Inject_1.Inject), __metadata("design:paramtypes", [App_1.App, JsonService_1.JsonService]) ], BaseService); exports.BaseService = BaseService; }); //# sourceMappingURL=RestService.js.map