use webpack for all builds
This commit is contained in:
3
packages/netlify-cms-backend-test/babel.config.js
Normal file
3
packages/netlify-cms-backend-test/babel.config.js
Normal file
@ -0,0 +1,3 @@
|
||||
const config = require('../../babel.config.js');
|
||||
|
||||
module.exports = config;
|
@ -3,28 +3,37 @@
|
||||
"description": "Development testing backend for Netlify CMS",
|
||||
"version": "2.0.0-alpha.0",
|
||||
"license": "MIT",
|
||||
"main": "dist/netlify-cms-backend-test.js",
|
||||
"keywords": [
|
||||
"netlify",
|
||||
"netlify-cms",
|
||||
"backend"
|
||||
],
|
||||
"sideEffects": false,
|
||||
"scripts": {
|
||||
"watch": "parcel watch src/*.js --out-dir . --no-cache",
|
||||
"build": "parcel build src/*.js --out-dir . --no-cache"
|
||||
"watch": "webpack -w",
|
||||
"build": "cross-env NODE_ENV=production webpack"
|
||||
},
|
||||
"dependencies": {
|
||||
"immutable": "^3.8.2",
|
||||
"lodash": "^4.17.10",
|
||||
"netlify": "^1.2.0",
|
||||
"netlify-cms-lib-util": "file:../netlify-cms-lib-util",
|
||||
"netlify-cms-ui-default": "file:../netlify-cms-ui-default",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^16.4.1",
|
||||
"react-emotion": "^9.2.6",
|
||||
"react-immutable-proptypes": "^2.1.0",
|
||||
"uuid": "^3.3.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"parcel-bundler": "^1.9.4"
|
||||
"@babel/cli": "^7.0.0-beta.54",
|
||||
"@babel/core": "^7.0.0-beta.54",
|
||||
"cross-env": "^5.2.0",
|
||||
"rollup": "^0.63.2",
|
||||
"rollup-plugin-babel": "^4.0.0-beta.7",
|
||||
"webpack": "^4.16.1",
|
||||
"webpack-cli": "^3.1.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"immutable": "^3.8.2",
|
||||
"lodash": "^4.17.10",
|
||||
"netlify-cms-lib-util": "2.0.0-alpha.0",
|
||||
"netlify-cms-ui-default": "2.0.0-alpha.0",
|
||||
"prop-types": "^15.6.2",
|
||||
"react": "^16.4.1",
|
||||
"react-emotion": "^9.2.6",
|
||||
"react-immutable-proptypes": "^2.1.0"
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import React from 'react';
|
||||
import PropTypes from 'prop-types';
|
||||
import ImmutablePropTypes from 'react-immutable-proptypes';
|
||||
import Icon from 'netlify-cms-ui-default/Icon';
|
||||
import { Icon } from 'netlify-cms-ui-default';
|
||||
|
||||
export default class AuthenticationPage extends React.Component {
|
||||
static propTypes = {
|
||||
|
225
packages/netlify-cms-backend-test/src/implementation.js
Normal file
225
packages/netlify-cms-backend-test/src/implementation.js
Normal file
@ -0,0 +1,225 @@
|
||||
import { fromJS } from 'immutable';
|
||||
import { remove, attempt, isError, take } from 'lodash';
|
||||
import uuid from 'uuid/v4';
|
||||
import { EditorialWorkflowError } from 'netlify-cms-lib-util';
|
||||
import { Cursor, CURSOR_COMPATIBILITY_SYMBOL } from 'netlify-cms-lib-util';
|
||||
import AuthenticationPage from './AuthenticationPage';
|
||||
|
||||
window.repoFiles = window.repoFiles || {};
|
||||
window.repoFilesUnpublished = window.repoFilesUnpublished || [];
|
||||
|
||||
function getFile(path) {
|
||||
const segments = path.split('/');
|
||||
let obj = window.repoFiles;
|
||||
while (obj && segments.length) {
|
||||
obj = obj[segments.shift()];
|
||||
}
|
||||
return obj || {};
|
||||
}
|
||||
|
||||
const pageSize = 10;
|
||||
|
||||
const getCursor = (collection, extension, entries, index) => {
|
||||
const count = entries.length;
|
||||
const pageCount = Math.floor(count / pageSize);
|
||||
return Cursor.create({
|
||||
actions: [
|
||||
...(index < pageCount ? ["next", "last"] : []),
|
||||
...(index > 0 ? ["prev", "first"] : []),
|
||||
],
|
||||
meta: { index, count, pageSize, pageCount },
|
||||
data: { collection, extension, index, pageCount },
|
||||
});
|
||||
};
|
||||
|
||||
const getFolderEntries = (folder, extension) => {
|
||||
return Object.keys(window.repoFiles[folder] || {})
|
||||
.filter(path => path.endsWith(`.${ extension }`))
|
||||
.map(path => ({
|
||||
file: { path: `${ folder }/${ path }` },
|
||||
data: window.repoFiles[folder][path].content,
|
||||
}))
|
||||
.reverse();
|
||||
};
|
||||
|
||||
export default class TestRepo {
|
||||
constructor(config) {
|
||||
this.config = config;
|
||||
this.assets = [];
|
||||
this.initialStatus = config.initialStatus;
|
||||
}
|
||||
|
||||
authComponent() {
|
||||
return AuthenticationPage;
|
||||
}
|
||||
|
||||
restoreUser(user) {
|
||||
return this.authenticate(user);
|
||||
}
|
||||
|
||||
authenticate() {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
logout() {
|
||||
return null;
|
||||
}
|
||||
|
||||
getToken() {
|
||||
return Promise.resolve('');
|
||||
}
|
||||
|
||||
traverseCursor(cursor, action) {
|
||||
const { collection, extension, index, pageCount } = cursor.data.toObject();
|
||||
const newIndex = (() => {
|
||||
if (action === "next") { return index + 1; }
|
||||
if (action === "prev") { return index - 1; }
|
||||
if (action === "first") { return 0; }
|
||||
if (action === "last") { return pageCount; }
|
||||
})();
|
||||
// TODO: stop assuming cursors are for collections
|
||||
const allEntries = getFolderEntries(collection.get('folder'), extension);
|
||||
const entries = allEntries.slice(newIndex * pageSize, (newIndex * pageSize) + pageSize);
|
||||
const newCursor = getCursor(collection, extension, allEntries, newIndex);
|
||||
return Promise.resolve({ entries, cursor: newCursor });
|
||||
}
|
||||
|
||||
entriesByFolder(collection, extension) {
|
||||
const folder = collection.get('folder');
|
||||
const entries = folder ? getFolderEntries(folder, extension) : [];
|
||||
const cursor = getCursor(collection, extension, entries, 0);
|
||||
const ret = take(entries, pageSize);
|
||||
ret[CURSOR_COMPATIBILITY_SYMBOL] = cursor;
|
||||
return Promise.resolve(ret);
|
||||
}
|
||||
|
||||
entriesByFiles(collection) {
|
||||
const files = collection.get('files').map(collectionFile => ({
|
||||
path: collectionFile.get('file'),
|
||||
label: collectionFile.get('label'),
|
||||
}));
|
||||
return Promise.all(files.map(file => ({
|
||||
file,
|
||||
data: getFile(file.path).content,
|
||||
})));
|
||||
}
|
||||
|
||||
getEntry(collection, slug, path) {
|
||||
return Promise.resolve({
|
||||
file: { path },
|
||||
data: getFile(path).content,
|
||||
});
|
||||
}
|
||||
|
||||
unpublishedEntries() {
|
||||
return Promise.resolve(window.repoFilesUnpublished);
|
||||
}
|
||||
|
||||
unpublishedEntry(collection, slug) {
|
||||
const entry = window.repoFilesUnpublished.find(e => (
|
||||
e.metaData.collection === collection.get('name') && e.slug === slug
|
||||
));
|
||||
if (!entry) {
|
||||
return Promise.reject(new EditorialWorkflowError('content is not under editorial workflow', true));
|
||||
}
|
||||
return Promise.resolve(entry);
|
||||
}
|
||||
|
||||
deleteUnpublishedEntry(collection, slug) {
|
||||
const unpubStore = window.repoFilesUnpublished;
|
||||
const existingEntryIndex = unpubStore.findIndex(e => (
|
||||
e.metaData.collection === collection && e.slug === slug
|
||||
));
|
||||
unpubStore.splice(existingEntryIndex, 1);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
persistEntry({ path, raw, slug }, mediaFiles = [], options = {}) {
|
||||
if (options.useWorkflow) {
|
||||
const unpubStore = window.repoFilesUnpublished;
|
||||
const existingEntryIndex = unpubStore.findIndex(e => e.file.path === path);
|
||||
if (existingEntryIndex >= 0) {
|
||||
const unpubEntry = { ...unpubStore[existingEntryIndex], data: raw };
|
||||
unpubEntry.title = options.parsedData && options.parsedData.title;
|
||||
unpubEntry.description = options.parsedData && options.parsedData.description;
|
||||
unpubStore.splice(existingEntryIndex, 1, unpubEntry);
|
||||
} else {
|
||||
const unpubEntry = {
|
||||
data: raw,
|
||||
file: {
|
||||
path,
|
||||
},
|
||||
metaData: {
|
||||
collection: options.collectionName,
|
||||
status: this.initialStatus,
|
||||
title: options.parsedData && options.parsedData.title,
|
||||
description: options.parsedData && options.parsedData.description,
|
||||
},
|
||||
slug,
|
||||
};
|
||||
unpubStore.push(unpubEntry);
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
const newEntry = options.newEntry || false;
|
||||
const folder = path.substring(0, path.lastIndexOf('/'));
|
||||
const fileName = path.substring(path.lastIndexOf('/') + 1);
|
||||
window.repoFiles[folder] = window.repoFiles[folder] || {};
|
||||
window.repoFiles[folder][fileName] = window.repoFiles[folder][fileName] || {};
|
||||
if (newEntry) {
|
||||
window.repoFiles[folder][fileName] = { content: raw };
|
||||
} else {
|
||||
window.repoFiles[folder][fileName].content = raw;
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
updateUnpublishedEntryStatus(collection, slug, newStatus) {
|
||||
const unpubStore = window.repoFilesUnpublished;
|
||||
const entryIndex = unpubStore.findIndex(e => (
|
||||
e.metaData.collection === collection && e.slug === slug
|
||||
));
|
||||
unpubStore[entryIndex].metaData.status = newStatus;
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
publishUnpublishedEntry(collection, slug) {
|
||||
const unpubStore = window.repoFilesUnpublished;
|
||||
const unpubEntryIndex = unpubStore.findIndex(e => (
|
||||
e.metaData.collection === collection && e.slug === slug
|
||||
));
|
||||
const unpubEntry = unpubStore[unpubEntryIndex];
|
||||
const entry = { raw: unpubEntry.data, slug: unpubEntry.slug, path: unpubEntry.file.path };
|
||||
unpubStore.splice(unpubEntryIndex, 1);
|
||||
return this.persistEntry(entry);
|
||||
}
|
||||
getMedia() {
|
||||
return Promise.resolve(this.assets);
|
||||
}
|
||||
|
||||
persistMedia({ fileObj }) {
|
||||
const { name, size } = fileObj;
|
||||
const objectUrl = attempt(window.URL.createObjectURL, fileObj);
|
||||
const url = isError(objectUrl) ? '' : objectUrl;
|
||||
const normalizedAsset = { id: uuid(), name, size, path: url, url };
|
||||
|
||||
this.assets.push(normalizedAsset);
|
||||
return Promise.resolve(normalizedAsset);
|
||||
}
|
||||
|
||||
deleteFile(path, commitMessage) {
|
||||
const assetIndex = this.assets.findIndex(asset => asset.path === path);
|
||||
if (assetIndex > -1) {
|
||||
this.assets.splice(assetIndex, 1);
|
||||
}
|
||||
|
||||
else {
|
||||
const folder = path.substring(0, path.lastIndexOf('/'));
|
||||
const fileName = path.substring(path.lastIndexOf('/') + 1);
|
||||
delete window.repoFiles[folder][fileName];
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
@ -1,225 +1,2 @@
|
||||
import { fromJS } from 'immutable';
|
||||
import { remove, attempt, isError, take } from 'lodash';
|
||||
import uuid from 'uuid/v4';
|
||||
import EditorialWorkflowError from 'netlify-cms-lib-util/EditorialWorkflowError';
|
||||
import Cursor, { CURSOR_COMPATIBILITY_SYMBOL } from 'netlify-cms-lib-util/Cursor'
|
||||
import AuthenticationPage from './AuthenticationPage';
|
||||
|
||||
window.repoFiles = window.repoFiles || {};
|
||||
window.repoFilesUnpublished = window.repoFilesUnpublished || [];
|
||||
|
||||
function getFile(path) {
|
||||
const segments = path.split('/');
|
||||
let obj = window.repoFiles;
|
||||
while (obj && segments.length) {
|
||||
obj = obj[segments.shift()];
|
||||
}
|
||||
return obj || {};
|
||||
}
|
||||
|
||||
const pageSize = 10;
|
||||
|
||||
const getCursor = (collection, extension, entries, index) => {
|
||||
const count = entries.length;
|
||||
const pageCount = Math.floor(count / pageSize);
|
||||
return Cursor.create({
|
||||
actions: [
|
||||
...(index < pageCount ? ["next", "last"] : []),
|
||||
...(index > 0 ? ["prev", "first"] : []),
|
||||
],
|
||||
meta: { index, count, pageSize, pageCount },
|
||||
data: { collection, extension, index, pageCount },
|
||||
});
|
||||
};
|
||||
|
||||
const getFolderEntries = (folder, extension) => {
|
||||
return Object.keys(window.repoFiles[folder] || {})
|
||||
.filter(path => path.endsWith(`.${ extension }`))
|
||||
.map(path => ({
|
||||
file: { path: `${ folder }/${ path }` },
|
||||
data: window.repoFiles[folder][path].content,
|
||||
}))
|
||||
.reverse();
|
||||
};
|
||||
|
||||
export default class TestRepo {
|
||||
constructor(config) {
|
||||
this.config = config;
|
||||
this.assets = [];
|
||||
this.initialStatus = config.initialStatus;
|
||||
}
|
||||
|
||||
authComponent() {
|
||||
return AuthenticationPage;
|
||||
}
|
||||
|
||||
restoreUser(user) {
|
||||
return this.authenticate(user);
|
||||
}
|
||||
|
||||
authenticate() {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
logout() {
|
||||
return null;
|
||||
}
|
||||
|
||||
getToken() {
|
||||
return Promise.resolve('');
|
||||
}
|
||||
|
||||
traverseCursor(cursor, action) {
|
||||
const { collection, extension, index, pageCount } = cursor.data.toObject();
|
||||
const newIndex = (() => {
|
||||
if (action === "next") { return index + 1; }
|
||||
if (action === "prev") { return index - 1; }
|
||||
if (action === "first") { return 0; }
|
||||
if (action === "last") { return pageCount; }
|
||||
})();
|
||||
// TODO: stop assuming cursors are for collections
|
||||
const allEntries = getFolderEntries(collection.get('folder'), extension);
|
||||
const entries = allEntries.slice(newIndex * pageSize, (newIndex * pageSize) + pageSize);
|
||||
const newCursor = getCursor(collection, extension, allEntries, newIndex);
|
||||
return Promise.resolve({ entries, cursor: newCursor });
|
||||
}
|
||||
|
||||
entriesByFolder(collection, extension) {
|
||||
const folder = collection.get('folder');
|
||||
const entries = folder ? getFolderEntries(folder, extension) : [];
|
||||
const cursor = getCursor(collection, extension, entries, 0);
|
||||
const ret = take(entries, pageSize);
|
||||
ret[CURSOR_COMPATIBILITY_SYMBOL] = cursor;
|
||||
return Promise.resolve(ret);
|
||||
}
|
||||
|
||||
entriesByFiles(collection) {
|
||||
const files = collection.get('files').map(collectionFile => ({
|
||||
path: collectionFile.get('file'),
|
||||
label: collectionFile.get('label'),
|
||||
}));
|
||||
return Promise.all(files.map(file => ({
|
||||
file,
|
||||
data: getFile(file.path).content,
|
||||
})));
|
||||
}
|
||||
|
||||
getEntry(collection, slug, path) {
|
||||
return Promise.resolve({
|
||||
file: { path },
|
||||
data: getFile(path).content,
|
||||
});
|
||||
}
|
||||
|
||||
unpublishedEntries() {
|
||||
return Promise.resolve(window.repoFilesUnpublished);
|
||||
}
|
||||
|
||||
unpublishedEntry(collection, slug) {
|
||||
const entry = window.repoFilesUnpublished.find(e => (
|
||||
e.metaData.collection === collection.get('name') && e.slug === slug
|
||||
));
|
||||
if (!entry) {
|
||||
return Promise.reject(new EditorialWorkflowError('content is not under editorial workflow', true));
|
||||
}
|
||||
return Promise.resolve(entry);
|
||||
}
|
||||
|
||||
deleteUnpublishedEntry(collection, slug) {
|
||||
const unpubStore = window.repoFilesUnpublished;
|
||||
const existingEntryIndex = unpubStore.findIndex(e => (
|
||||
e.metaData.collection === collection && e.slug === slug
|
||||
));
|
||||
unpubStore.splice(existingEntryIndex, 1);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
persistEntry({ path, raw, slug }, mediaFiles = [], options = {}) {
|
||||
if (options.useWorkflow) {
|
||||
const unpubStore = window.repoFilesUnpublished;
|
||||
const existingEntryIndex = unpubStore.findIndex(e => e.file.path === path);
|
||||
if (existingEntryIndex >= 0) {
|
||||
const unpubEntry = { ...unpubStore[existingEntryIndex], data: raw };
|
||||
unpubEntry.title = options.parsedData && options.parsedData.title;
|
||||
unpubEntry.description = options.parsedData && options.parsedData.description;
|
||||
unpubStore.splice(existingEntryIndex, 1, unpubEntry);
|
||||
} else {
|
||||
const unpubEntry = {
|
||||
data: raw,
|
||||
file: {
|
||||
path,
|
||||
},
|
||||
metaData: {
|
||||
collection: options.collectionName,
|
||||
status: this.initialStatus,
|
||||
title: options.parsedData && options.parsedData.title,
|
||||
description: options.parsedData && options.parsedData.description,
|
||||
},
|
||||
slug,
|
||||
};
|
||||
unpubStore.push(unpubEntry);
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
const newEntry = options.newEntry || false;
|
||||
const folder = path.substring(0, path.lastIndexOf('/'));
|
||||
const fileName = path.substring(path.lastIndexOf('/') + 1);
|
||||
window.repoFiles[folder] = window.repoFiles[folder] || {};
|
||||
window.repoFiles[folder][fileName] = window.repoFiles[folder][fileName] || {};
|
||||
if (newEntry) {
|
||||
window.repoFiles[folder][fileName] = { content: raw };
|
||||
} else {
|
||||
window.repoFiles[folder][fileName].content = raw;
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
updateUnpublishedEntryStatus(collection, slug, newStatus) {
|
||||
const unpubStore = window.repoFilesUnpublished;
|
||||
const entryIndex = unpubStore.findIndex(e => (
|
||||
e.metaData.collection === collection && e.slug === slug
|
||||
));
|
||||
unpubStore[entryIndex].metaData.status = newStatus;
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
publishUnpublishedEntry(collection, slug) {
|
||||
const unpubStore = window.repoFilesUnpublished;
|
||||
const unpubEntryIndex = unpubStore.findIndex(e => (
|
||||
e.metaData.collection === collection && e.slug === slug
|
||||
));
|
||||
const unpubEntry = unpubStore[unpubEntryIndex];
|
||||
const entry = { raw: unpubEntry.data, slug: unpubEntry.slug, path: unpubEntry.file.path };
|
||||
unpubStore.splice(unpubEntryIndex, 1);
|
||||
return this.persistEntry(entry);
|
||||
}
|
||||
getMedia() {
|
||||
return Promise.resolve(this.assets);
|
||||
}
|
||||
|
||||
persistMedia({ fileObj }) {
|
||||
const { name, size } = fileObj;
|
||||
const objectUrl = attempt(window.URL.createObjectURL, fileObj);
|
||||
const url = isError(objectUrl) ? '' : objectUrl;
|
||||
const normalizedAsset = { id: uuid(), name, size, path: url, url };
|
||||
|
||||
this.assets.push(normalizedAsset);
|
||||
return Promise.resolve(normalizedAsset);
|
||||
}
|
||||
|
||||
deleteFile(path, commitMessage) {
|
||||
const assetIndex = this.assets.findIndex(asset => asset.path === path);
|
||||
if (assetIndex > -1) {
|
||||
this.assets.splice(assetIndex, 1);
|
||||
}
|
||||
|
||||
else {
|
||||
const folder = path.substring(0, path.lastIndexOf('/'));
|
||||
const fileName = path.substring(path.lastIndexOf('/') + 1);
|
||||
delete window.repoFiles[folder][fileName];
|
||||
}
|
||||
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
||||
export TestBackend from './implementation';
|
||||
export AuthenticationPage from './AuthenticationPage';
|
||||
|
1
packages/netlify-cms-backend-test/webpack.config.js
Normal file
1
packages/netlify-cms-backend-test/webpack.config.js
Normal file
@ -0,0 +1 @@
|
||||
module.exports = require('../../webpack.config.js');
|
Reference in New Issue
Block a user