begin scaffolding for lerna

This commit is contained in:
Shawn Erquhart
2018-07-03 15:47:15 -04:00
parent 26f7c38a9f
commit 768fcbaa1d
320 changed files with 50292 additions and 464 deletions

View 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));
}

View 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");

View 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;
}

View File

@ -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;
}
}

View File

@ -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;
}
}

View File

@ -0,0 +1,3 @@
export { default as APIError } from './APIError';
export { default as EditorialWorkflowError } from './EditorialWorkflowError';