mirror of https://github.com/artf/grapesjs.git
4 changed files with 134 additions and 126 deletions
@ -1,66 +0,0 @@ |
|||||
import { isUndefined, isFunction, isString } from 'underscore'; |
|
||||
import fetch from '../../utils/fetch'; |
|
||||
|
|
||||
export default class RemoteStorage { |
|
||||
async store(data, opts = {}) { |
|
||||
await this.request(opts.urlStore, this.__props(opts, data), opts); |
|
||||
} |
|
||||
|
|
||||
async load(opts) { |
|
||||
return await this.request(opts.urlLoad, this.__props(opts), opts); |
|
||||
} |
|
||||
|
|
||||
request(url, props = {}, opts = {}) { |
|
||||
return fetch(url, props) |
|
||||
.then(res => { |
|
||||
const result = res.text(); |
|
||||
const isOk = ((res.status / 200) | 0) === 1; |
|
||||
return isOk ? result : result.then(Promise.reject); |
|
||||
}) |
|
||||
.then(text => { |
|
||||
const parsable = text && isString(text); |
|
||||
return opts.contentTypeJson && parsable ? JSON.parse(text) : text; |
|
||||
}); |
|
||||
} |
|
||||
|
|
||||
__props(opts = {}, data) { |
|
||||
const typeJson = opts.contentTypeJson; |
|
||||
const headers = opts.headers || {}; |
|
||||
const fetchOpts = opts.fetchOptions || {}; |
|
||||
const reqHead = 'X-Requested-With'; |
|
||||
const typeHead = 'Content-Type'; |
|
||||
let body; |
|
||||
|
|
||||
if (isUndefined(headers[reqHead])) { |
|
||||
headers[reqHead] = 'XMLHttpRequest'; |
|
||||
} |
|
||||
|
|
||||
if (isUndefined(headers[typeHead]) && typeJson) { |
|
||||
headers[typeHead] = 'application/json; charset=utf-8'; |
|
||||
} |
|
||||
|
|
||||
if (data) { |
|
||||
if (typeJson) { |
|
||||
body = JSON.stringify(data); |
|
||||
} else { |
|
||||
body = new FormData(); |
|
||||
|
|
||||
for (let key in data) { |
|
||||
body.append(key, data[key]); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
const result = { |
|
||||
method: body ? 'POST' : 'GET', |
|
||||
credentials: opts.credentials, |
|
||||
headers, |
|
||||
body, |
|
||||
}; |
|
||||
|
|
||||
return { |
|
||||
...result, |
|
||||
...(isFunction(fetchOpts) ? fetchOpts(result) : fetchOpts), |
|
||||
}; |
|
||||
} |
|
||||
} |
|
||||
@ -0,0 +1,127 @@ |
|||||
|
import Editor from '../../editor'; |
||||
|
import { isUndefined, isFunction, isString } from 'underscore'; |
||||
|
import fetch from '../../utils/fetch'; |
||||
|
import IStorage, { ProjectData } from './IStorage'; |
||||
|
import { ModelFetchOptions } from 'backbone'; |
||||
|
|
||||
|
type AnyObject = Record<string, any>; |
||||
|
|
||||
|
export interface RemoteStorageConfig { |
||||
|
/** |
||||
|
* Custom headers. |
||||
|
* @default {} |
||||
|
*/ |
||||
|
headers?: AnyObject; |
||||
|
|
||||
|
/** |
||||
|
* Endpoint URL where to store data project. |
||||
|
*/ |
||||
|
urlStore?: string; |
||||
|
|
||||
|
/** |
||||
|
* Endpoint URL where to load data project. |
||||
|
*/ |
||||
|
urlLoad?: string; |
||||
|
|
||||
|
/** |
||||
|
* Use JSON contentType. |
||||
|
* @default true |
||||
|
*/ |
||||
|
contentTypeJson?: boolean; |
||||
|
|
||||
|
/** |
||||
|
* Credentials option for the fetch API. |
||||
|
* @default 'include' |
||||
|
*/ |
||||
|
credentials?: RequestCredentials; |
||||
|
|
||||
|
/** |
||||
|
* Pass custom options to fetch API (remote storage) |
||||
|
* You can pass a simple object: { someOption: 'someValue' } |
||||
|
* or a function which returns and object to add: |
||||
|
* @example |
||||
|
* fetchOptions: currentOpts => { |
||||
|
* return currentOpts.method === 'POST' ? { method: 'PATCH' } : {}; |
||||
|
* }, |
||||
|
*/ |
||||
|
fetchOptions?: string | ((opts: AnyObject) => object); |
||||
|
|
||||
|
/** |
||||
|
* The remote storage sends the project data as a body of the request. |
||||
|
* You can use this method to update the body before the store call in order to align |
||||
|
* with your API requirements. |
||||
|
* @default data => data |
||||
|
*/ |
||||
|
onStore?: (data: AnyObject, editor: Editor) => AnyObject; |
||||
|
|
||||
|
/** |
||||
|
* The remote storage loads the project data directly from the request response. |
||||
|
* You can use this method to properly extract the project data from the response. |
||||
|
* @default data => data |
||||
|
*/ |
||||
|
onLoad?: (data: AnyObject, editor: Editor) => AnyObject; |
||||
|
} |
||||
|
|
||||
|
export default class RemoteStorage implements IStorage<RemoteStorageConfig> { |
||||
|
async store(data: ProjectData, opts: RemoteStorageConfig = {}) { |
||||
|
await this.request(opts.urlStore!, this.__props(opts, data), opts); |
||||
|
} |
||||
|
|
||||
|
async load(opts: RemoteStorageConfig = {}) { |
||||
|
return await this.request(opts.urlLoad!, this.__props(opts), opts); |
||||
|
} |
||||
|
|
||||
|
request(url: string, props: RequestInit = {}, opts: RemoteStorageConfig = {}) { |
||||
|
return fetch(url, props) |
||||
|
.then((res: any) => { |
||||
|
const result = res.text(); |
||||
|
const isOk = ((res.status / 200) | 0) === 1; |
||||
|
return isOk ? result : result.then(Promise.reject); |
||||
|
}) |
||||
|
.then(text => { |
||||
|
const parsable = text && isString(text); |
||||
|
return opts.contentTypeJson && parsable ? JSON.parse(text) : text; |
||||
|
}); |
||||
|
} |
||||
|
|
||||
|
__props(opts: RemoteStorageConfig = {}, data?: ProjectData): RequestInit { |
||||
|
const typeJson = opts.contentTypeJson; |
||||
|
const headers = opts.headers || {}; |
||||
|
const fetchOpts = opts.fetchOptions || {}; |
||||
|
const reqHead = 'X-Requested-With'; |
||||
|
const typeHead = 'Content-Type'; |
||||
|
let body; |
||||
|
|
||||
|
if (isUndefined(headers[reqHead])) { |
||||
|
headers[reqHead] = 'XMLHttpRequest'; |
||||
|
} |
||||
|
|
||||
|
if (isUndefined(headers[typeHead]) && typeJson) { |
||||
|
headers[typeHead] = 'application/json; charset=utf-8'; |
||||
|
} |
||||
|
|
||||
|
if (data) { |
||||
|
if (typeJson) { |
||||
|
body = JSON.stringify(data); |
||||
|
} else { |
||||
|
body = new FormData(); |
||||
|
|
||||
|
for (let key in data) { |
||||
|
body.append(key, data[key]); |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
const result = { |
||||
|
method: body ? 'POST' : 'GET', |
||||
|
credentials: opts.credentials, |
||||
|
headers, |
||||
|
body, |
||||
|
}; |
||||
|
|
||||
|
return { |
||||
|
...result, |
||||
|
...(isFunction(fetchOpts) ? fetchOpts(result) : fetchOpts), |
||||
|
}; |
||||
|
} |
||||
|
} |
||||
Loading…
Reference in new issue