ngx-drupal7-services
Version:
# Angular 2+/Ionic 2+ Drupal 7 Services #### Typescript angular module for [Drupal Services 3.x](https://www.drupal.org/project/services)
1 lines • 71.7 kB
Source Map (JSON)
{"version":3,"file":"ngx-drupal7-services.mjs","sources":["../../../projects/ngx-drupal7-services/src/lib/application/drupal-constants.ts","../../../projects/ngx-drupal7-services/src/lib/main/main.service.ts","../../../projects/ngx-drupal7-services/src/lib/system/system.service.ts","../../../projects/ngx-drupal7-services/src/lib/user/user.service.ts","../../../projects/ngx-drupal7-services/src/lib/node/node.service.ts","../../../projects/ngx-drupal7-services/src/lib/file/file.service.ts","../../../projects/ngx-drupal7-services/src/lib/comment/comment.service.ts","../../../projects/ngx-drupal7-services/src/lib/taxonomy/taxonomy-term.service.ts","../../../projects/ngx-drupal7-services/src/lib/taxonomy/taxonomy-vocabulary.service.ts","../../../projects/ngx-drupal7-services/src/lib/view/view.service.ts","../../../projects/ngx-drupal7-services/src/lib/entity/entity.service.ts","../../../projects/ngx-drupal7-services/src/lib/menu/menu.service.ts","../../../projects/ngx-drupal7-services/src/lib/fboauth/fboauth.service.ts","../../../projects/ngx-drupal7-services/src/lib/push_notifications/push-notifications.service.ts","../../../projects/ngx-drupal7-services/src/lib/ngx-drupal7-services.module.ts","../../../projects/ngx-drupal7-services/src/public_api.ts","../../../projects/ngx-drupal7-services/src/ngx-drupal7-services.ts"],"sourcesContent":["\r\nimport { throwError as observableThrowError, of as observableOf, Observable } from 'rxjs';\r\nimport { Settings, SystemConnection } from '../models';\r\n\r\n/**\r\n * DrupalConstants singleton design pattern of the required settings and user connection.\r\n */\r\n\r\n// @dynamic\r\nexport class DrupalConstants {\r\n /**\r\n * Singleton instance.\r\n * didn't understand it ? Oh come on!.\r\n */\r\n private static instance: DrupalConstants;\r\n\r\n /**\r\n * private variables for set and get.\r\n */\r\n private settings: Settings;\r\n private connection: SystemConnection;\r\n\r\n constructor() { }\r\n\r\n /**\r\n * handle offline error messages\r\n * @param err (optional) the error of the http request\r\n */\r\n public handleOffline = function (err?: any): Observable<any> {\r\n if (this.settings.allowOffline) {\r\n return observableOf();\r\n }\r\n return observableThrowError(err);\r\n };\r\n\r\n static get Instance() {\r\n if (!this.instance) {\r\n this.instance = new DrupalConstants();\r\n }\r\n return this.instance;\r\n }\r\n\r\n /**\r\n * Handeling the case when user didn't implement the back-end settings and return the settings instance\r\n */\r\n static get Settings(): Settings {\r\n if (!this.Instance.settings) {\r\n throw new Error('ngx-drupal7-services: Application settings are not set, Please read README.MD file');\r\n }\r\n return this.Instance.settings;\r\n }\r\n\r\n /**\r\n * Set the settings instanse on application init.\r\n * you can also do that at the runtime, Thanks to Singleton design pattern <3 !\r\n */\r\n static set Settings(newSettings: Settings) {\r\n this.Instance.settings = newSettings;\r\n }\r\n\r\n /**\r\n * the full backend url for current user settings\r\n */\r\n static get backEndUrl(): string {\r\n const settings = this.Settings;\r\n const url = settings.apiProtocol + '://' + settings.apiHost;\r\n return settings.apiPort ? url + ':' + settings.apiPort + '/' : url + '/';\r\n }\r\n\r\n /**\r\n * Application back-end rest api url.\r\n */\r\n static get restUrl(): string {\r\n const settings = this.Settings;\r\n return this.backEndUrl + settings.apiEndPoint + '/';\r\n }\r\n\r\n /**\r\n * Updating connection instanse after login or rightaway after openning the connection\r\n */\r\n static set Connection(newConnection: SystemConnection) {\r\n this.Instance.connection = newConnection;\r\n }\r\n\r\n /**\r\n * get the connection instance\r\n */\r\n static get Connection(): SystemConnection {\r\n return this.Instance.connection;\r\n }\r\n}\r\n","\r\nimport { Injectable, Inject, PLATFORM_ID } from '@angular/core';\r\nimport { HttpClient } from '@angular/common/http';\r\nimport { Observable } from 'rxjs';\r\nimport { catchError, timeout, map } from 'rxjs/operators';\r\nimport { DrupalConstants } from '../application/drupal-constants';\r\nimport { SystemConnection } from '../models/system';\r\nimport { isPlatformServer } from '@angular/common';\r\n\r\n/**\r\n * the main service is the basic http service of all other services \"parent\" that implements all the required request.\r\n * this service will add the headers automatically for each request it self\r\n */\r\n@Injectable()\r\nexport class MainService {\r\n /**\r\n * entity type of the current service, the main service dont have anything but the other services must use it\r\n * for example \"node, comment, user, system\"\r\n */\r\n protected readonly entityType: string;\r\n\r\n /**\r\n * the main constractor of this service will inject the required services dynamically.\r\n * @param http basic http service\r\n * @param cookieService ngx-cookie service provider to save the cookies\r\n * @see https://angular.io/guide/dependency-injection\r\n * @see https://www.npmjs.com/package/ngx-cookie\r\n */\r\n constructor(protected httpClient: HttpClient, @Inject(PLATFORM_ID) private platformId: Object) { }\r\n\r\n /**\r\n * structure a full entity for drupal request\r\n * @param entity the entity to be structured\r\n * @param ignoredFields fields to be ignored just like nid or uid or title\r\n * @param fieldLabels: the label for each field just like \"{field_custom_field: 'value'}\"\r\n * @param language language of the entity\r\n */\r\n structureEntity(entity: any, ignoredFields: string[], fieldLabels?: any[], language?: string): any {\r\n Object.keys(entity).forEach((key: string, index: number) => {\r\n if (ignoredFields.indexOf(key) === -1) {\r\n let fieldLabel;\r\n if (fieldLabels[key]) {\r\n fieldLabel = fieldLabels[key];\r\n }\r\n entity[key] = this.structureField(entity[key], fieldLabel, language);\r\n }\r\n });\r\n return entity;\r\n }\r\n\r\n /**\r\n * structure the field for drupal services request\r\n * @param value the field value\r\n * @param label field label name\r\n * @param language language of the field\r\n */\r\n structureField(value: any, label: string = 'value', language?: string) {\r\n if (!language) {\r\n language = DrupalConstants.Settings.language;\r\n }\r\n const item = {};\r\n if (this.isArray(value)) {\r\n const field_array = [];\r\n for (let i = 0, l = value.length; i < l; i++) {\r\n item[label] = value[i];\r\n field_array.push(item);\r\n }\r\n return {\r\n [language]: field_array\r\n };\r\n }\r\n if (value instanceof Date) {\r\n const obj = {\r\n value: {\r\n date: `${value.getFullYear()}-${value.getMonth() + 1}-` +\r\n `${value.getDate()} ${value.getHours()}:${value.getMinutes()}:${value.getSeconds()}`\r\n }\r\n };\r\n return {\r\n [language]: [\r\n obj\r\n ]\r\n };\r\n }\r\n // field value given with label(s) already built\r\n if (typeof value === 'object') {\r\n return {\r\n [language]: [\r\n value\r\n ]\r\n };\r\n }\r\n item[label] = value;\r\n return {\r\n [language]: [\r\n item\r\n ]\r\n };\r\n }\r\n\r\n /**\r\n * a getter to return the required headers for drupal\r\n * X-CSRF-Token - application token from services/session/connect\r\n * Content-Type - the type of the request content.\r\n * Accept - forcing drupal to return the response as a json object\r\n * @return object of the headers\r\n */\r\n get options(): any {\r\n const headers = {\r\n 'Content-Type': 'application/json',\r\n 'Accept': 'application/json',\r\n };\r\n const token = this.getSavedVariable('token');\r\n if (token) {\r\n headers['X-CSRF-Token'] = token;\r\n }\r\n headers['Authentication'] = `${this.getSavedVariable('session_name')}=${this.getSavedVariable('sessid')}`;\r\n if (DrupalConstants.Settings.cookieHeader) {\r\n headers['Cookie'] = `${this.getSavedVariable('session_name')}=${this.getSavedVariable('sessid')}`;\r\n }\r\n const options = {\r\n headers: headers,\r\n withCredentials: true,\r\n reportProgress: true,\r\n };\r\n return options;\r\n }\r\n\r\n /**\r\n * getting token from drupal services module\r\n * @return http text token response\r\n */\r\n protected getToken(): Observable<string> {\r\n const options = this.options;\r\n options['responseType'] = 'text';\r\n return this.httpRequestWithConfig(\r\n this.httpClient.get(`${DrupalConstants.backEndUrl}services/session/token`, options)\r\n ).pipe(map(res => {\r\n if (!isPlatformServer(this.platformId)) {\r\n localStorage.setItem('token', res);\r\n }\r\n return res;\r\n }));\r\n }\r\n\r\n /**\r\n * Saving drupal session and token in cookies using ngx-cookie service\r\n * @param connection drupal connection\r\n */\r\n protected saveSessionToken(connection: SystemConnection): void {\r\n if (!connection.token) {\r\n connection.token = this.getSavedVariable('token');\r\n }\r\n this.removeSession();\r\n DrupalConstants.Connection = connection;\r\n if (!isPlatformServer(this.platformId)) {\r\n localStorage.setItem(connection.session_name, connection.sessid);\r\n localStorage.setItem('sessid', connection.sessid);\r\n localStorage.setItem('session_name', connection.session_name);\r\n localStorage.setItem('token', connection.token);\r\n if (connection.user && connection.user.timestamp) {\r\n localStorage.setItem('timestamp', connection.user.timestamp.toString());\r\n } else {\r\n localStorage.setItem('timestamp', Math.floor(Date.now()).toString());\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * building up the full url path for each resource and / or params\r\n * @param resource the entity resource param. ex: system/'connect', user/'login'\r\n * @return full request path after adding the entity type and resource param\r\n */\r\n protected fullRequestURL(resource?: string | number): string {\r\n let request_url = DrupalConstants.restUrl;\r\n\r\n if (this.entityType) {\r\n request_url += this.entityType;\r\n }\r\n\r\n if (resource) {\r\n if (request_url[request_url.length - 1] === '/') {\r\n request_url += resource;\r\n } else {\r\n request_url += '/' + resource;\r\n }\r\n }\r\n\r\n return request_url;\r\n }\r\n\r\n /**\r\n * adding http request configs: request timeout, error handler\r\n * @param httpObservableRequest the http Observable to request\r\n * @return Observable of the request after adding required configs\r\n */\r\n protected httpRequestWithConfig(httpObservableRequest: Observable<any>): Observable<any> {\r\n return httpObservableRequest.pipe(\r\n timeout(DrupalConstants.Settings.requestTimeout),\r\n catchError(err => DrupalConstants.Instance.handleOffline(err))\r\n );\r\n }\r\n\r\n /**\r\n * basic http get request with headers.\r\n * @param resource the entity resource param. ex: system/'connect', user/'login'\r\n * @return http json response\r\n */\r\n protected get(resource?: string | number): Observable<any> {\r\n return this.httpRequestWithConfig(\r\n this.httpClient.get(this.fullRequestURL(resource), this.options)\r\n );\r\n }\r\n\r\n /**\r\n * basic http post request with headers.\r\n * @param resource the entity resource param. ex: system/'connect', user/'login'\r\n * @param body the contenct of the request\r\n * @return http json response\r\n */\r\n protected post(body: any = {}, resource?: string | number): Observable<any> {\r\n return this.httpRequestWithConfig(\r\n this.httpClient.post(this.fullRequestURL(resource), body, this.options),\r\n );\r\n }\r\n\r\n /**\r\n * basic http put request with headers.\r\n * @param resource the entity resource param. ex: system/'connect', user/'login'\r\n * @param body the contenct of the request\r\n * @return http json response\r\n */\r\n protected put(body: any = {}, resource?: string | number): Observable<any> {\r\n return this.httpRequestWithConfig(\r\n this.httpClient.put(this.fullRequestURL(resource), body, this.options),\r\n );\r\n }\r\n\r\n /**\r\n * basic http delete request with headers.\r\n * @param resource the entity resource param. ex: system/'connect', user/'login'\r\n * @return http json response\r\n */\r\n protected delete(resource?: string | number): Observable<any> {\r\n return this.httpRequestWithConfig(\r\n this.httpClient.delete(this.fullRequestURL(resource), this.options),\r\n );\r\n }\r\n\r\n /**\r\n * Clearing drupal session after logging out\r\n */\r\n protected removeSession(): void {\r\n if (!isPlatformServer(this.platformId)) {\r\n localStorage.removeItem('token');\r\n localStorage.removeItem('timestamp');\r\n localStorage.removeItem('sessid');\r\n localStorage.removeItem('session_name');\r\n if (DrupalConstants.Connection && DrupalConstants.Connection.session_name) {\r\n localStorage.removeItem(DrupalConstants.Connection.session_name);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Checking the current connection if the connection is init and valid\r\n * @return if connection is valid\r\n */\r\n protected isConnected(): boolean {\r\n return this.getSavedVariable('token') &&\r\n this.getSavedVariable('sessid') &&\r\n this.getSavedVariable('session_name') &&\r\n !this.isConnectionExpired() ?\r\n true : false;\r\n }\r\n\r\n /**\r\n * Check if the drupal session is timedout.\r\n * @return true if the current date is less than the login date by 24 day \"drupal default session timeout is 24 day\".\r\n */\r\n protected isConnectionExpired(): boolean {\r\n const nowTS: number = Math.floor(Date.now());\r\n let sessionDays = 23;\r\n if (DrupalConstants.Settings.sessionDays) {\r\n sessionDays = DrupalConstants.Settings.sessionDays;\r\n }\r\n const dayMS = 86400000; // 1 day to ms\r\n const expirationTS: number = sessionDays * dayMS;\r\n return nowTS - +this.getSavedVariable('timestamp') < expirationTS;\r\n }\r\n\r\n /**\r\n * Serializin arguments as a string\r\n * @param options object of drupal parametars to serialize\r\n * @return string of parameters\r\n */\r\n protected getArgs(options: any): string {\r\n if (!options) {\r\n return '';\r\n }\r\n let args = '?';\r\n Object.keys(options).forEach((key, index) => {\r\n args += this.optionToString(key, options[key]);\r\n });\r\n return args;\r\n }\r\n\r\n /**\r\n * Check if variable is array of objects\r\n * @param value array to check\r\n */\r\n private isArray(value) {\r\n return Object.prototype.toString.call(value) === '[object Array]';\r\n }\r\n\r\n /**\r\n * retrive the variable from the connection object or if there is no connection yet it will return them from the cookies\r\n * this will will allow you to implement your custom connection storage, just like ionic.\r\n * because the cookies is not always available on webview apps, you may need to save the connection in sqllite\r\n * and restore them directly.\r\n * @param variableName the name of the saved variable\r\n */\r\n private getSavedVariable(variableName: string): string {\r\n\r\n if (DrupalConstants.Connection) {\r\n if (DrupalConstants.Connection[variableName]) {\r\n return DrupalConstants.Connection[variableName];\r\n } else if (DrupalConstants.Connection.user && DrupalConstants.Connection.user[variableName]) {\r\n return DrupalConstants.Connection.user[variableName];\r\n }\r\n }\r\n if (!isPlatformServer(this.platformId)) {\r\n return localStorage.getItem(variableName);\r\n }\r\n return;\r\n }\r\n\r\n /**\r\n * serializing eatch option\r\n * @param key option key\r\n * @param value option value\r\n * @return single option serilization\r\n */\r\n protected optionToString(key: string, value: any): string {\r\n if (!value) {\r\n return '';\r\n }\r\n let str = '';\r\n if (value instanceof Array) {\r\n value.forEach((element, index) => {\r\n str += `${key}[${index}]=${element}&`;\r\n });\r\n } else if (value instanceof Object) {\r\n Object.keys(value).forEach((element: string, index) => {\r\n if (value[element] instanceof Object) {\r\n str += this.serializeObject(value[element], `${key}[${element}]`);\r\n } else {\r\n str += `${key}[${element}]=${value[element]}&`;\r\n }\r\n });\r\n } else {\r\n str += `${key}=${value}&`;\r\n }\r\n return str;\r\n }\r\n\r\n /**\r\n * serializing the object keys\r\n * @param obj object to serialize\r\n */\r\n private serializeObject(obj: any, parentSerialized: string): string {\r\n let str = '';\r\n Object.keys(obj).forEach((key, index) => {\r\n const value = obj[key];\r\n if (value instanceof Object) {\r\n str += `${this.serializeObject(value, `${parentSerialized}[${key}]`)}`;\r\n } else {\r\n str += `${parentSerialized}[${key}]=${value}&`;\r\n }\r\n });\r\n return str;\r\n }\r\n\r\n}\r\n","\r\nimport { mergeMap, map } from 'rxjs/operators';\r\nimport { Injectable } from '@angular/core';\r\nimport { Observable } from 'rxjs';\r\n\r\nimport { MainService } from '../main/main.service';\r\nimport { DrupalConstants } from '../application/drupal-constants';\r\nimport { SystemConnection } from '../models/system';\r\n\r\n\r\n/**\r\n * system service for drupal\r\n * @see BACK_END/admin/structure/services/list/END_POINT/resources for more details\r\n */\r\n@Injectable()\r\nexport class SystemService extends MainService {\r\n entityType = 'system';\r\n\r\n /**\r\n * if there is already a token in the browser cookies and it is not expired it will return it\r\n * this will fetch a new token before trying to connect\r\n * @param refreshToken boolean to force the application to request new token\r\n * @return observable of the connect method\r\n * the subscription data is an object of SystemConnection interface\r\n */\r\n connect(refreshToken: boolean = false): Observable<SystemConnection> {\r\n\r\n if (this.isConnectionExpired()) {\r\n this.removeSession();\r\n }\r\n\r\n if (!DrupalConstants.Connection || !DrupalConstants.Connection.token || refreshToken) {\r\n return this.getToken().pipe(mergeMap(token => {\r\n return this.post({}, 'connect').pipe(map(connection => {\r\n connection.token = token;\r\n this.saveSessionToken(connection);\r\n return connection;\r\n }));\r\n }));\r\n }\r\n\r\n return this.post({}, 'connect').pipe(map(connection => {\r\n this.saveSessionToken(connection);\r\n return connection;\r\n }));\r\n }\r\n\r\n /**\r\n * implement get_variable resource\r\n * @param variableName the name of the variable\r\n * @return the value of the variable\r\n */\r\n getVariable(variableName: string): Observable<any[]> {\r\n return this.post({ name: variableName }, 'get_variable');\r\n }\r\n\r\n /**\r\n * implement set_variable resource\r\n * @param variableName the name of the variable\r\n * @param value the value to set for the variable\r\n * @return always null, take care of overriding old variables with same name\r\n */\r\n setVariable(variableName: string, value: any): Observable<null> {\r\n const variable = {\r\n name: variableName,\r\n value: value\r\n };\r\n return this.post(variable, 'set_variable');\r\n }\r\n\r\n /**\r\n * implement del_variable resource\r\n * @param variableName variable name to delete\r\n * @return null if variable found or not.\r\n */\r\n delVariable(variableName: string): Observable<null> {\r\n return this.post({ name: variableName }, 'del_variable');\r\n }\r\n}\r\n","\r\nimport { Injectable } from '@angular/core';\r\nimport { Observable } from 'rxjs';\r\nimport { mergeMap, map } from 'rxjs/operators';\r\n\r\nimport { MainService } from '../main/main.service';\r\nimport { SystemConnection, User, LoginCredentials, CreatedUser, PasswordReset, PasswordResetResponse } from '../models';\r\n\r\n/**\r\n * user service for drupal\r\n * @see BACK_END/admin/structure/services/list/END_POINT/resources for more details\r\n */\r\n@Injectable()\r\nexport class UserService extends MainService {\r\n entityType = 'user';\r\n\r\n /**\r\n * implement retrive resource\r\n * @param uid user id to retrive\r\n * @return user object\r\n */\r\n getUserById(uid: number): Observable<User> {\r\n return this.get(uid);\r\n }\r\n\r\n /**\r\n * implement index resource\r\n * @return array of users\r\n * Please notice that the user must have the required permission to do this action\r\n */\r\n getUsersList(): Observable<User[]> {\r\n return this.get();\r\n }\r\n\r\n /**\r\n * implement create resource\r\n * @param user user to create\r\n * @return created user details\r\n */\r\n createUser(user: User): Observable<CreatedUser> {\r\n return this.post(user);\r\n }\r\n\r\n /**\r\n * implement update resource\r\n * @param user user object to update\r\n * @return updated user object\r\n */\r\n updateUser(user: User): Observable<User> {\r\n return this.put(user, user.uid);\r\n }\r\n\r\n /**\r\n * implement delete\r\n * @param uid user id to delete\r\n * @return array of boolean, if user deleted will be true, otherwise will be false\r\n */\r\n deleteUser(uid: number): Observable<boolean[]> {\r\n return this.delete(uid);\r\n }\r\n\r\n /**\r\n * implement login resource\r\n * @param user credentials to login \"username and password\"\r\n * @return system connection that contains the session details and the user object\r\n * notice that the user login version must be of version 1.0 at the resources settions at the back-end\r\n */\r\n login(user: LoginCredentials): Observable<SystemConnection> {\r\n const observer = this.post(user, 'login');\r\n return observer.pipe(map((connection: SystemConnection) => {\r\n this.saveSessionToken(connection);\r\n return connection;\r\n }));\r\n }\r\n\r\n /**\r\n * implement logout resource\r\n * @return new token after logging out\r\n */\r\n logout(): Observable<string> {\r\n const observer = this.post({}, 'logout');\r\n return observer.pipe(mergeMap((loggedOut: boolean[]) => {\r\n if (loggedOut[0]) {\r\n this.removeSession();\r\n return this.getToken();\r\n }\r\n }));\r\n }\r\n\r\n /**\r\n * implement request_new_password resource\r\n * @param useranme the username of the user to request a new password\r\n * @return array of boolean, if the mail sent successfully will be true, otherwhise will be false.\r\n * if the server is not a mail server or if there is not mail server configuration this will always return false\r\n */\r\n requestNewPassword(useranme: string): Observable<boolean[]> {\r\n const user = {\r\n name: useranme\r\n };\r\n return this.post(user, 'request_new_password');\r\n }\r\n\r\n /**\r\n * implement user_pass_reset resource\r\n * @param passwordReset Object of the sent details to the email that contains the timestamp and the hashed password\r\n * @return response of the password reset request\r\n * this request will automatically logging the user in for only one time and will be expired after the first use.\r\n * the hashed password can be found at the drupal reset password email and you can customize it if you have token module installed\r\n */\r\n userPasswordReset(passwordReset: PasswordReset): Observable<PasswordResetResponse> {\r\n return this.post(passwordReset, 'user_pass_reset');\r\n }\r\n\r\n /**\r\n * implement register resource\r\n * @param user object to register new account\r\n * some properties is required if it is set at the account settings inside the drupal admin config\r\n * @see http://BACKEND/admin/config/people/accounts\r\n * @return created user details\r\n */\r\n registerAccount(user: User): Observable<CreatedUser> {\r\n return this.post(user, 'register');\r\n }\r\n\r\n /**\r\n * implement cancel resource\r\n * @param uid the user id to cancel\r\n * @return array of boolean, true if canceled, false otherwhise\r\n * Please notice the cancelation settings is managed at the backend\r\n * @see http://BACKEND/admin/config/people/accounts\r\n */\r\n cancelUser(uid: number): Observable<boolean[]> {\r\n return this.post({}, `${uid}/cancel`);\r\n }\r\n\r\n /**\r\n * implement password_reset resource\r\n * @param uid user id to reset his password\r\n * @return array of boolean, true if user password has been resetted, false otherwhise\r\n */\r\n passwordReset(uid: number): Observable<boolean[]> {\r\n return this.post({}, `${uid}/password_reset`);\r\n }\r\n\r\n /**\r\n * implement resend_welcome_email\r\n * @param uid user id to send the email for his account\r\n * @return array of boolean, if the mail sent successfully will be true, otherwhise will be false.\r\n * if the server is not a mail server or if there is not mail server configuration this will always return false\r\n */\r\n resendWelcomeEmail(uid: number): Observable<boolean[]> {\r\n return this.post({}, `${uid}/resend_welcome_email`);\r\n }\r\n\r\n /**\r\n * implement token\r\n */\r\n token(): Observable<string> {\r\n return this.getToken();\r\n }\r\n\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { Observable } from 'rxjs';\r\n\r\nimport { MainService } from '../main/main.service';\r\nimport { FileEntity, CommentEntity, NodeEntity, CreatedNode, FileAttach } from '../models';\r\n\r\n/**\r\n * node service for drupal\r\n * @see BACK_END/admin/structure/services/list/END_POINT/resources for more details\r\n */\r\n@Injectable()\r\nexport class NodeService extends MainService {\r\n entityType = 'node';\r\n\r\n /**\r\n * impelement index resource\r\n * @return array of nodes\r\n */\r\n getAllNodes(): Observable<NodeEntity[]> {\r\n return this.get();\r\n }\r\n\r\n /**\r\n * implement retrive resource\r\n * @param nid node id to retrive\r\n * @return object of the node entity\r\n */\r\n getNodeById(nid: number): Observable<NodeEntity> {\r\n return this.get(nid);\r\n }\r\n\r\n /**\r\n * implement create resource\r\n * @param node node entity to create\r\n * @return created node details\r\n */\r\n createNode(node: NodeEntity): Observable<CreatedNode> {\r\n return this.post(node);\r\n }\r\n\r\n /**\r\n * implement create resource\r\n * @param node node to create\r\n * @return created node details\r\n */\r\n updateNode(node: {nid: number}): Observable<CreatedNode> {\r\n return this.put(node, node.nid);\r\n }\r\n\r\n /**\r\n * implement delete resource\r\n * @param nid node id to delete\r\n * @return array true if node deleted, otherwise return false array\r\n */\r\n deleteNode(nid: number): Observable<boolean[]> {\r\n return this.delete(nid);\r\n }\r\n\r\n /**\r\n * implement files resource\r\n * @param nid node id\r\n * @return array of files that attached to that node\r\n */\r\n files(nid: number): Observable<FileEntity[]> {\r\n return this.get(`${nid}/files`);\r\n }\r\n\r\n /**\r\n * implement comments resource\r\n * @param nid node id\r\n * @return array of comments that attached to that node\r\n */\r\n comments(nid: number): Observable<CommentEntity[]> {\r\n return this.get(`${nid}/comments`);\r\n }\r\n\r\n /**\r\n * implement attach_files resource\r\n * @param nid node id\r\n * @file object contains the field details and the file to upload\r\n * @return attached file\r\n */\r\n attachFilesToNode(nid: number, file: FileAttach): Observable<FileEntity> {\r\n return this.post(file, `${nid}/attach_file`);\r\n }\r\n\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { Observable } from 'rxjs';\r\n\r\nimport { MainService } from '../main/main.service';\r\nimport { FileEntity, CreatedFile } from '../models/file';\r\n\r\n/**\r\n * file service for drupal\r\n * @see BACK_END/admin/structure/services/list/END_POINT/resources for more details\r\n */\r\n@Injectable()\r\nexport class FileService extends MainService {\r\n entityType = 'file';\r\n\r\n /**\r\n * impelement index resource\r\n * @return array of files\r\n */\r\n getAllFiles(): Observable<FileEntity[]> {\r\n return this.get();\r\n }\r\n\r\n /**\r\n * implement retrive resource\r\n * @param fid file id to retrive\r\n * @return object of the file entity\r\n */\r\n getFileById(fid: number): Observable<FileEntity> {\r\n return this.get(fid);\r\n }\r\n\r\n /**\r\n * implement create resource\r\n * @param file file entity to create\r\n * @return created file details\r\n */\r\n createFile(file: FileEntity): Observable<CreatedFile> {\r\n return this.post(file);\r\n }\r\n\r\n /**\r\n * implement delete resource\r\n * @param fid file id to delete\r\n * @return boolean array if file deleted, otherwise return false\r\n * keep in mined that you can not delete a file if it is already referenced by a node\r\n */\r\n deleteFile(fid: number): Observable<boolean[]> {\r\n return this.delete(fid);\r\n }\r\n\r\n /**\r\n * creating raw file\r\n * this require rest support for form multi data\r\n */\r\n createRaw(): Observable<boolean[]> {\r\n return this.post({}, 'create_raw');\r\n }\r\n\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { Observable } from 'rxjs';\r\n\r\nimport { MainService } from '../main/main.service';\r\nimport { CommentEntity, CreatedComment } from '../models/comment';\r\n\r\n/**\r\n * comment service for drupal\r\n * @see BACK_END/admin/structure/services/list/END_POINT/resources for more details\r\n */\r\n@Injectable()\r\nexport class CommentService extends MainService {\r\n\r\n /**\r\n * entity type is comment\r\n */\r\n entityType = 'comment';\r\n\r\n /**\r\n * implement comment index resource\r\n * @return list of comments\r\n */\r\n getAllComments(): Observable<CommentEntity[]> {\r\n return this.get();\r\n }\r\n\r\n /**\r\n * implement comment retrive method\r\n * @param cid comment id\r\n * @return drupal comment entity\r\n */\r\n getCommentById(cid: number): Observable<CommentEntity> {\r\n return this.get(cid);\r\n }\r\n\r\n /**\r\n * implement create resource\r\n * @param comment the comment to create\r\n * @return created comment details\r\n */\r\n createComment(comment: CommentEntity): Observable<CreatedComment> {\r\n return this.post(comment);\r\n }\r\n\r\n /**\r\n * implement update resource\r\n * @param comment comment to update\r\n * @return array of comment id\r\n */\r\n updateComment(comment: CommentEntity): Observable<number[]> {\r\n return this.put(comment, comment.cid);\r\n }\r\n\r\n /**\r\n * implement delete resource\r\n * @param cid comment id to delete\r\n * @return array of boolean, if comment deleted the array will will contains true\r\n */\r\n deleteComment(cid: number): Observable<boolean[]> {\r\n return this.delete(cid);\r\n }\r\n\r\n /**\r\n * implement countAll resource\r\n * @param nid host node id of the comments\r\n * @return number of comments on the node\r\n */\r\n countAllCommentsByNodeId(nid: number): Observable<number> {\r\n return this.post({nid: nid}, 'countAll');\r\n }\r\n\r\n /**\r\n * implement countNew resource.\r\n * @param nid host node id of the new comments\r\n * @return number of the new comments for the giving node id\r\n */\r\n countNewCommentsByNodeId(nid: number): Observable<number> {\r\n return this.post({nid: nid}, 'countNew');\r\n }\r\n\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { Observable } from 'rxjs';\r\n\r\nimport { MainService } from '../main/main.service';\r\nimport { NodeEntity, TaxonomyTerm } from '../models';\r\n\r\n/**\r\n * taxonomy term service for drupal\r\n * @see BACK_END/admin/structure/services/list/END_POINT/resources for more details\r\n */\r\n@Injectable()\r\nexport class TaxonomyTermService extends MainService {\r\n entityType = 'taxonomy_term';\r\n\r\n /**\r\n * implement index resource\r\n * @return array of terms\r\n */\r\n getAllTaxonomyTerms(): Observable<TaxonomyTerm[]> {\r\n return this.get();\r\n }\r\n\r\n /**\r\n * implement retrive resource\r\n * @param tid term id\r\n * @return term object\r\n */\r\n getTaxonomyTermById(tid: number): Observable<TaxonomyTerm> {\r\n return this.get(tid);\r\n }\r\n\r\n /**\r\n * implement create resource\r\n * @param taxonomyTerm the term to create\r\n * @return array number for the wight of the term\r\n */\r\n createTaxonomyTerm(taxonomyTerm: TaxonomyTerm): Observable<number[]> {\r\n return this.post(taxonomyTerm);\r\n }\r\n\r\n /**\r\n * implement update resource\r\n * @param taxonomyTerm term to update\r\n * @return array number for the wight of the term\r\n */\r\n updateTaxonomyTerm(taxonomyTerm: TaxonomyTerm): Observable<number[]> {\r\n return this.put(taxonomyTerm, taxonomyTerm.tid);\r\n }\r\n\r\n /**\r\n * implement delete resource\r\n * @param tid term id to delete\r\n * @return array of deleted term id\r\n */\r\n deleteTaxonomyTerm(tid: number): Observable<number[]> {\r\n return this.delete(tid);\r\n }\r\n\r\n /**\r\n * implement selectNodes\r\n * @param tid term id\r\n * @return array of nodes that referenced this term in one of the fields\r\n */\r\n getAllNodesForTerm(tid: number): Observable <NodeEntity[]> {\r\n return this.post({tid: tid}, 'selectNodes');\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { Observable, of } from 'rxjs';\r\n\r\nimport { MainService } from '../main/main.service';\r\nimport { TaxonomyVocabulary, TaxonomyVocabularyTree } from '../models/taxonomy-vocabulary';\r\n\r\n/**\r\n * taxonomy vocabulary service for drupal\r\n * @see BACK_END/admin/structure/services/list/END_POINT/resources for more details\r\n */\r\n@Injectable()\r\nexport class TaxonomyVocabularyService extends MainService {\r\n entityType = 'taxonomy_vocabulary';\r\n\r\n /**\r\n * implement index resource\r\n * @return array of the available vocabularies\r\n */\r\n getAllVocabularies(): Observable<TaxonomyVocabulary[]> {\r\n return this.get();\r\n }\r\n\r\n /**\r\n * implement retrive resource\r\n * @param vid vocabulary id\r\n * @return vocabulary object\r\n */\r\n getTaxonomyVocabularyById(vid: number): Observable<TaxonomyVocabulary> {\r\n return this.get(vid);\r\n }\r\n\r\n /**\r\n * implement create resource\r\n * @param taxonomyVocabulary the vocabulary to create\r\n * @return array of vocabulary id\r\n */\r\n createTaxonomyVocabulary(taxonomyVocabulary: TaxonomyVocabulary): Observable<number[]> {\r\n return this.post(taxonomyVocabulary);\r\n }\r\n\r\n /**\r\n * implement update resource\r\n * @param taxonomyVocabulary the vocabulary to update\r\n * @return array of the current vocabulary whight\r\n */\r\n updateTaxonomyVocabulary(taxonomyVocabulary: TaxonomyVocabulary): Observable<number[]> {\r\n return this.put(taxonomyVocabulary, taxonomyVocabulary.vid);\r\n }\r\n\r\n /**\r\n * implement delete resource\r\n * @param vid vocabulary id to delete\r\n * @return array of deleted vocabulary id\r\n */\r\n deleteTaxonomyVocabulary(vid: number): Observable<number[]> {\r\n return this.delete(vid);\r\n }\r\n\r\n /**\r\n * implement retrieveByMachineName resource\r\n * @param vocabularyMachineName vocabulary machine name\r\n * @return vocabulary object\r\n */\r\n getTaxonomyVocabularyByMachineName(vocabularyMachineName: string): Observable<TaxonomyVocabulary> {\r\n return this.post({machine_name: vocabularyMachineName}, 'retrieveByMachineName');\r\n }\r\n\r\n /**\r\n * implement getTree resource\r\n * @param vid vocabulary id\r\n * @return a full list of taxonomy terms inside this vocabulary as a tree structure.\r\n */\r\n getTaxonomyVocabularyTree(vid: number): Observable<TaxonomyVocabularyTree[]> {\r\n return this.post({vid: vid}, 'getTree');\r\n }\r\n\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { Observable } from 'rxjs';\r\n\r\nimport { MainService } from '../main/main.service';\r\nimport { ViewOptions } from '../models/view';\r\n\r\n/**\r\n * view service for drupal using services_views module\r\n * @see https://www.drupal.org/project/services_views\r\n */\r\n@Injectable()\r\nexport class ViewService extends MainService {\r\n entityType = 'views';\r\n\r\n /**\r\n * impelemnt retrive resource\r\n * @param viewMachineName view machine name\r\n * @param options parameters of filteration for this view\r\n * @return array of view rows OR view html code if the options format_output is 1\r\n */\r\n getView(viewMachineName: string, options?: ViewOptions): Observable<any[]> {\r\n const args = this.getArgs(options);\r\n return this.get(viewMachineName + args);\r\n }\r\n\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { Observable } from 'rxjs';\r\n\r\nimport { MainService } from '../main/main.service';\r\nimport { DrupalConstants } from '../application/drupal-constants';\r\nimport { CustomEntityOptions } from '../models/custom-entity';\r\n\r\n/**\r\n * custom entity service for drupal using services_entity module\r\n * @see https://www.drupal.org/project/services_entity\r\n */\r\n@Injectable()\r\nexport class EntityService extends MainService {\r\n /**\r\n * the entity prefix for all the entities\r\n */\r\n entityType = 'entity_';\r\n\r\n /**\r\n * getting the full entity url for the entity\r\n * @param entityMachineName entity machine name, ex: node, user\r\n * @return string of full path to resource\r\n */\r\n protected fullRequestURL(entityMachineName: string): string {\r\n let request_url = DrupalConstants.restUrl;\r\n request_url += this.entityType + entityMachineName;\r\n\r\n return request_url;\r\n }\r\n\r\n /**\r\n * implement index resource\r\n * @param entityMachineName entity machine name, ex: node, user\r\n * @param options parameter options\r\n * @return array of the required entity type.\r\n * personally suggest to create an interface for each type you want to retrive,\r\n * you can use the models in this module as a perent interfaces.\r\n */\r\n indexEntity(entityMachineName: string, options?: CustomEntityOptions): Observable<any[]> {\r\n const args = this.getArgs(options);\r\n return this.get(entityMachineName + args);\r\n }\r\n\r\n /**\r\n * implement retrive resource\r\n * @param entityMachineName entity machine name, ex: node, user\r\n * @param selector the id of the entity\r\n * @param options parameter options\r\n * @return entity object\r\n */\r\n retrieveEntity(entityMachineName: string, selector: number, options?: CustomEntityOptions): Observable<any> {\r\n const args = this.getArgs(options);\r\n return this.get(`${entityMachineName}/${selector}${args}`);\r\n }\r\n\r\n /**\r\n * implement delete resource\r\n * @param entityMachineName entity machine name, ex: node, user\r\n * @param selector the id of the entity\r\n * @return null if the entity is deleted,otherwise throws an error.\r\n */\r\n deleteEntity(entityMachineName: string, selector: number): Observable<null> {\r\n return this.delete(`${entityMachineName}/${selector}`);\r\n }\r\n\r\n /**\r\n * implement create resource\r\n * @param entityMachineName entity machine name, ex: node, user\r\n * @param entity entity object to create\r\n * @return created entity\r\n */\r\n createEntity(entityMachineName: string, entity: Object): Observable<any> {\r\n return this.post(entity, entityMachineName);\r\n }\r\n\r\n /**\r\n * implement update resource\r\n * @param entityMachineName entity machine name, ex: node, user\r\n * @param entity entity to update\r\n * @param selector entity id to update and must match the id inside the entity object\r\n * @return updated entity\r\n */\r\n updateEntity(entityMachineName: string, entity: any, selector: number): Observable<any> {\r\n return this.put(entity, `${entityMachineName}/${selector}`);\r\n }\r\n\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { Observable } from 'rxjs';\r\n\r\nimport { MainService } from '../main/main.service';\r\nimport { Menu } from '../models/menu';\r\n\r\n/**\r\n * menu service for drupal\r\n * @see https://www.drupal.org/project/services_menu for more details\r\n */\r\n@Injectable()\r\nexport class MenuService extends MainService {\r\n entityType = 'menu';\r\n\r\n /**\r\n * implement menu retrive\r\n * @param menuMachineName menu machine name\r\n * @return menu witl all children links\r\n */\r\n getMenu(menuMachineName: string): Observable<Menu> {\r\n return this.get(menuMachineName);\r\n }\r\n}\r\n","\r\nimport { Injectable } from '@angular/core';\r\nimport { Observable } from 'rxjs';\r\nimport { mergeMap, map } from 'rxjs/operators';\r\n\r\nimport { MainService } from '../main/main.service';\r\nimport { DrupalConstants } from '../application/drupal-constants';\r\nimport { SystemConnection } from '../models/system';\r\n\r\n\r\n/**\r\n * facebook oauth service\r\n * @see https://www.drupal.org/project/services_fboauth\r\n * @see BACK_END/admin/structure/services/list/END_POINT/resources for more details\r\n */\r\n@Injectable()\r\nexport class FacebookOAuthService extends MainService {\r\n entityType = 'fboauth';\r\n\r\n /**\r\n * if there is already a token in the browser cookies and it is not expired it returns\r\n * this will fetch a new token before trying to connect\r\n * @param accessToken string of the recieved access token\r\n * @return observable of the connect method\r\n * the subscription data is an object of SystemConnection interface\r\n */\r\n connect(accessToken: string): Observable<SystemConnection> {\r\n\r\n if (this.isConnectionExpired()) {\r\n this.removeSession();\r\n }\r\n\r\n const body = {\r\n access_token: accessToken\r\n };\r\n\r\n if (!DrupalConstants.Connection || !DrupalConstants.Connection.token) {\r\n return this.getToken().pipe(mergeMap(token => {\r\n return this.post(body, 'connect').pipe(mergeMap(connection => {\r\n return this.getToken().pipe(map(newToken => {\r\n connection.token = newToken;\r\n this.saveSessionToken(connection);\r\n return connection;\r\n }));\r\n }));\r\n }));\r\n }\r\n\r\n return this.post(body, 'connect').pipe(map(connection => {\r\n this.saveSessionToken(connection);\r\n return connection;\r\n }));\r\n }\r\n}\r\n","import { Injectable } from '@angular/core';\r\nimport { Observable } from 'rxjs';\r\n\r\nimport { MainService } from '../main/main.service';\r\nimport { PushNotifications, PushResponse } from '../models/push-notifications';\r\n\r\n/**\r\n * view service for drupal using push_notifications module\r\n * @see https://www.drupal.org/project/push_notifications\r\n */\r\n@Injectable()\r\nexport class PushNotificationsSerivce extends MainService {\r\n entityType = 'push_notifications';\r\n\r\n /**\r\n * create/register new device with a token\r\n * @param pushNotifications notification object to register\r\n */\r\n create(pushNotifications: PushNotifications): Observable<PushResponse> {\r\n return this.post(pushNotifications);\r\n }\r\n\r\n /**\r\n * delete a subscription by device token\r\n * @param token token of the device to be deleted\r\n */\r\n delete_push(token: string): Observable<PushResponse> {\r\n return this.delete(token);\r\n }\r\n\r\n}\r\n","/**\r\n * angular imports\r\n */\r\nimport { NgModule, APP_INITIALIZER } from '@angular/core';\r\nimport { HttpClientModule } from '@angular/common/http';\r\n/**\r\n * my imports\r\n */\r\nimport { MainService } from './main/main.service';\r\nimport { SystemService } from './system/system.service';\r\nimport { UserService } from './user/user.service';\r\nimport { NodeService } from './node/node.service';\r\nimport { FileService } from './file/file.service';\r\nimport { CommentService } from './comment/comment.service';\r\nimport { TaxonomyTermService } from './taxonomy/taxonomy-term.service';\r\nimport { TaxonomyVocabularyService } from './taxonomy/taxonomy-vocabulary.service';\r\nimport { ViewService } from './view/view.service';\r\nimport { EntityService } from './entity/entity.service';\r\nimport { MenuService } from './menu/menu.service';\r\nimport { SystemConnection } from './models/system';\r\nimport { FacebookOAuthService } from './fboauth/fboauth.service';\r\nimport { PushNotificationsSerivce } from './push_notifications/push-notifications.service';\r\n\r\n/**\r\n * implement APP_INITIALIZER\r\n * @param systemService system service to connect\r\n * @see https://gillespie59.github.io/2016/12/04/angular2-code-before-rendering.html\r\n */\r\nexport function init(systemService: SystemService): () => Promise<SystemConnection> {\r\n return () => {\r\n const connectionObservable = systemService.connect(true).toPromise();\r\n return connectionObservable;\r\n };\r\n}\r\n\r\n/**\r\n * main services module with providers\r\n * if you do not need to import all the services you need to make your own module and import the required providers only\r\n * ngx-cookie package is required\r\n * @see https://www.npmjs.com/package/ngx-cookie\r\n */\r\n// @dynamic\r\n@NgModule({\r\n imports: [\r\n HttpClientModule,\r\n ],\r\n providers: [\r\n MainService,\r\n SystemService,\r\n UserService,\r\n NodeService,\r\n FileService,\r\n CommentService,\r\n TaxonomyTermService,\r\n TaxonomyVocabularyService,\r\n ViewService,\r\n EntityService,\r\n MenuService,\r\n FacebookOAuthService,\r\n PushNotificationsSerivce,\r\n {\r\n 'provide': APP_INITIALIZER,\r\n 'useFactory': init,\r\n 'deps': [SystemService],\r\n 'multi': true\r\n }\r\n ],\r\n})\r\nexport class Drupal7ServicesModule { }\r\n/**\r\n * My English is bad and i know that\r\n * any comment enhancements are wellcome\r\n */\r\n\r\n/**\r\n* export services\r\n*/\r\nexport {\r\n MainService,\r\n SystemService,\r\n UserService,\r\n NodeService,\r\n FileService,\r\n CommentService,\r\n TaxonomyTermService,\r\n TaxonomyVocabularyService,\r\n ViewService,\r\n EntityService,\r\n MenuService,\r\n FacebookOAuthService,\r\n PushNotificationsSerivce\r\n};\r\n","/*\r\n * Public API Surface of ngx-drupal7-services\r\n */\r\n\r\nexport * from './lib/models';\r\nexport * from './lib/application/drupal-constants';\r\nexport * from './lib/ngx-drupal7-services.module';\r\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public_api';\n"],"names":["observableOf","observableThrowError"],"mappings":"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