begin scaffolding for lerna
This commit is contained in:
60
packages/netlify-cms-core/src/valueObjects/AssetProxy.js
Normal file
60
packages/netlify-cms-core/src/valueObjects/AssetProxy.js
Normal file
@ -0,0 +1,60 @@
|
||||
import { resolvePath } from 'netlify-cms-lib-util';
|
||||
import { currentBackend } from "Backends/backend";
|
||||
import { getIntegrationProvider } from 'Integrations';
|
||||
import { selectIntegration } from 'Reducers';
|
||||
|
||||
let store;
|
||||
export const setStore = (storeObj) => {
|
||||
store = storeObj;
|
||||
};
|
||||
|
||||
export default function AssetProxy(value, fileObj, uploaded = false, asset) {
|
||||
const config = store.getState().config;
|
||||
this.value = value;
|
||||
this.fileObj = fileObj;
|
||||
this.uploaded = uploaded;
|
||||
this.sha = null;
|
||||
this.path = config.get('media_folder') && !uploaded ? resolvePath(value, config.get('media_folder')) : value;
|
||||
this.public_path = !uploaded ? resolvePath(value, config.get('public_folder')) : value;
|
||||
this.asset = asset;
|
||||
}
|
||||
|
||||
AssetProxy.prototype.toString = function () {
|
||||
// Use the deployed image path if we do not have a locally cached copy.
|
||||
if (this.uploaded && !this.fileObj) return this.public_path;
|
||||
try {
|
||||
return window.URL.createObjectURL(this.fileObj);
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
AssetProxy.prototype.toBase64 = function () {
|
||||
return new Promise((resolve, reject) => {
|
||||
const fr = new FileReader();
|
||||
fr.onload = (readerEvt) => {
|
||||
const binaryString = readerEvt.target.result;
|
||||
|
||||
resolve(binaryString.split('base64,')[1]);
|
||||
};
|
||||
fr.readAsDataURL(this.fileObj);
|
||||
});
|
||||
};
|
||||
|
||||
export function createAssetProxy(value, fileObj, uploaded = false, privateUpload = false) {
|
||||
const state = store.getState();
|
||||
const integration = selectIntegration(state, null, 'assetStore');
|
||||
if (integration && !uploaded) {
|
||||
const provider = integration && getIntegrationProvider(state.integrations, currentBackend(state.config).getToken, integration);
|
||||
return provider.upload(fileObj, privateUpload).then(
|
||||
response => (
|
||||
new AssetProxy(response.asset.url.replace(/^(https?):/, ''), null, true, response.asset)
|
||||
),
|
||||
error => new AssetProxy(value, fileObj, false)
|
||||
);
|
||||
} else if (privateUpload) {
|
||||
throw new Error('The Private Upload option is only avaible for Asset Store Integration');
|
||||
}
|
||||
|
||||
return Promise.resolve(new AssetProxy(value, fileObj, uploaded));
|
||||
}
|
115
packages/netlify-cms-core/src/valueObjects/Cursor.js
Normal file
115
packages/netlify-cms-core/src/valueObjects/Cursor.js
Normal file
@ -0,0 +1,115 @@
|
||||
import { fromJS, Map, Set } from "immutable";
|
||||
|
||||
const jsToMap = obj => {
|
||||
if (obj === undefined) {
|
||||
return Map();
|
||||
}
|
||||
const immutableObj = fromJS(obj);
|
||||
if (!Map.isMap(immutableObj)) {
|
||||
throw new Error("Object must be equivalent to a Map.");
|
||||
}
|
||||
return immutableObj;
|
||||
};
|
||||
|
||||
const knownMetaKeys = Set(["index", "count", "pageSize", "pageCount", "usingOldPaginationAPI"]);
|
||||
const filterUnknownMetaKeys = meta => meta.filter((v, k) => knownMetaKeys.has(k));
|
||||
|
||||
/*
|
||||
createCursorMap takes one of three signatures:
|
||||
- () -> cursor with empty actions, data, and meta
|
||||
- (cursorMap: <object/Map with optional actions, data, and meta keys>) -> cursor
|
||||
- (actions: <array/List>, data: <object/Map>, meta: <optional object/Map>) -> cursor
|
||||
*/
|
||||
const createCursorMap = (...args) => {
|
||||
const { actions, data, meta } = args.length === 1
|
||||
? jsToMap(args[0]).toObject()
|
||||
: { actions: args[0], data: args[1], meta: args[2] };
|
||||
return Map({
|
||||
// actions are a Set, rather than a List, to ensure an efficient .has
|
||||
actions: Set(actions),
|
||||
|
||||
// data and meta are Maps
|
||||
data: jsToMap(data),
|
||||
meta: jsToMap(meta).update(filterUnknownMetaKeys),
|
||||
});
|
||||
};
|
||||
|
||||
const hasAction = (cursorMap, action) => cursorMap.hasIn(["actions", action]);
|
||||
|
||||
const getActionHandlers = (cursorMap, handler) =>
|
||||
cursorMap.get("actions", Set()).toMap().map(action => handler(action));
|
||||
|
||||
// The cursor logic is entirely functional, so this class simply
|
||||
// provides a chainable interface
|
||||
export default class Cursor {
|
||||
static create(...args) {
|
||||
return new Cursor(...args);
|
||||
}
|
||||
|
||||
constructor(...args) {
|
||||
if (args[0] instanceof Cursor) {
|
||||
return args[0];
|
||||
}
|
||||
|
||||
this.store = createCursorMap(...args);
|
||||
this.actions = this.store.get("actions");
|
||||
this.data = this.store.get("data");
|
||||
this.meta = this.store.get("meta");
|
||||
}
|
||||
|
||||
updateStore(...args) {
|
||||
return new Cursor(this.store.update(...args));
|
||||
}
|
||||
updateInStore(...args) {
|
||||
return new Cursor(this.store.updateIn(...args));
|
||||
}
|
||||
|
||||
hasAction(action) {
|
||||
return hasAction(this.store, action);
|
||||
}
|
||||
addAction(action) {
|
||||
return this.updateStore("actions", actions => actions.add(action));
|
||||
}
|
||||
removeAction(action) {
|
||||
return this.updateStore("actions", actions => actions.delete(action));
|
||||
}
|
||||
setActions(actions) {
|
||||
return this.updateStore(store => store.set("actions", Set(actions)));
|
||||
}
|
||||
mergeActions(actions) {
|
||||
return this.updateStore("actions", oldActions => oldActions.union(actions));
|
||||
}
|
||||
getActionHandlers(handler) {
|
||||
return getActionHandlers(this.store, handler);
|
||||
}
|
||||
|
||||
setData(data) {
|
||||
return new Cursor(this.store.set("data", jsToMap(data)));
|
||||
}
|
||||
mergeData(data) {
|
||||
return new Cursor(this.store.mergeIn(["data"], jsToMap(data)));
|
||||
}
|
||||
wrapData(data) {
|
||||
return this.updateStore("data", oldData => jsToMap(data).set("wrapped_cursor_data", oldData));
|
||||
}
|
||||
unwrapData() {
|
||||
return [this.store.get("data").delete("wrapped_cursor_data"), this.updateStore("data", data => data.get("wrapped_cursor_data"))];
|
||||
}
|
||||
clearData() {
|
||||
return this.updateStore("data", data => Map());
|
||||
}
|
||||
|
||||
setMeta(meta) {
|
||||
return this.updateStore(store => store.set("meta", jsToMap(meta)));
|
||||
}
|
||||
mergeMeta(meta) {
|
||||
return this.updateStore(store => store.update("meta", oldMeta => oldMeta.merge(jsToMap(meta))))
|
||||
}
|
||||
}
|
||||
|
||||
// This is a temporary hack to allow cursors to be added to the
|
||||
// interface between backend.js and backends without modifying old
|
||||
// backends at all. This should be removed in favor of wrapping old
|
||||
// backends with a compatibility layer, as part of the backend API
|
||||
// refactor.
|
||||
export const CURSOR_COMPATIBILITY_SYMBOL = Symbol("cursor key for compatibility with old backends");
|
17
packages/netlify-cms-core/src/valueObjects/Entry.js
Normal file
17
packages/netlify-cms-core/src/valueObjects/Entry.js
Normal file
@ -0,0 +1,17 @@
|
||||
import { isBoolean } from "lodash";
|
||||
|
||||
export function createEntry(collection, slug = '', path = '', options = {}) {
|
||||
const returnObj = {};
|
||||
returnObj.collection = collection;
|
||||
returnObj.slug = slug;
|
||||
returnObj.path = path;
|
||||
returnObj.partial = options.partial || false;
|
||||
returnObj.raw = options.raw || '';
|
||||
returnObj.data = options.data || {};
|
||||
returnObj.label = options.label || null;
|
||||
returnObj.metaData = options.metaData || null;
|
||||
returnObj.isModification = isBoolean(options.isModification)
|
||||
? options.isModification
|
||||
: null;
|
||||
return returnObj;
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
export const API_ERROR = 'API_ERROR';
|
||||
|
||||
export default class APIError extends Error {
|
||||
constructor(message, status, api, meta={}) {
|
||||
super(message);
|
||||
this.message = message;
|
||||
this.status = status;
|
||||
this.api = api;
|
||||
this.name = API_ERROR;
|
||||
this.meta = meta;
|
||||
}
|
||||
}
|
@ -0,0 +1,10 @@
|
||||
export const EDITORIAL_WORKFLOW_ERROR = 'EDITORIAL_WORKFLOW_ERROR';
|
||||
|
||||
export default class EditorialWorkflowError extends Error {
|
||||
constructor(message, notUnderEditorialWorkflow) {
|
||||
super(message);
|
||||
this.message = message;
|
||||
this.notUnderEditorialWorkflow = notUnderEditorialWorkflow;
|
||||
this.name = EDITORIAL_WORKFLOW_ERROR;
|
||||
}
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
export { default as APIError } from './APIError';
|
||||
export { default as EditorialWorkflowError } from './EditorialWorkflowError';
|
||||
|
Reference in New Issue
Block a user