improve builds
This commit is contained in:
parent
4a01d2289c
commit
dc1f41d2d8
@ -20,11 +20,7 @@
|
|||||||
"semaphore": "^1.1.0"
|
"semaphore": "^1.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/cli": "^7.0.0-beta.54",
|
|
||||||
"@babel/core": "^7.0.0-beta.54",
|
|
||||||
"cross-env": "^5.2.0",
|
"cross-env": "^5.2.0",
|
||||||
"rollup": "^0.63.2",
|
|
||||||
"rollup-plugin-babel": "^4.0.0-beta.7",
|
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.16.1",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.1.0"
|
||||||
},
|
},
|
||||||
|
@ -14,13 +14,14 @@
|
|||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"watch": "webpack -w",
|
"watch": "webpack -w",
|
||||||
"build": "webpack"
|
"build": "cross-env NODE_ENV=production webpack"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"gotrue-js": "^0.9.22",
|
"gotrue-js": "^0.9.22",
|
||||||
"jwt-decode": "^2.2.0"
|
"jwt-decode": "^2.2.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.16.1",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.1.0"
|
||||||
},
|
},
|
||||||
|
@ -13,13 +13,14 @@
|
|||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"watch": "webpack -w",
|
"watch": "webpack -w",
|
||||||
"build": "webpack"
|
"build": "cross-env NODE_ENV=production webpack"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"js-base64": "^2.4.8",
|
"js-base64": "^2.4.8",
|
||||||
"semaphore": "^1.1.0"
|
"semaphore": "^1.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.16.1",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.1.0"
|
||||||
},
|
},
|
||||||
|
@ -13,13 +13,14 @@
|
|||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"watch": "webpack -w",
|
"watch": "webpack -w",
|
||||||
"build": "webpack"
|
"build": "cross-env NODE_ENV=production webpack"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"js-base64": "^2.4.8",
|
"js-base64": "^2.4.8",
|
||||||
"semaphore": "^1.1.0"
|
"semaphore": "^1.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.16.1",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.1.0"
|
||||||
},
|
},
|
||||||
|
@ -12,12 +12,13 @@
|
|||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"watch": "webpack -w",
|
"watch": "webpack -w",
|
||||||
"build": "webpack"
|
"build": "cross-env NODE_ENV=production webpack"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"uuid": "^3.3.2"
|
"uuid": "^3.3.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.16.1",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.1.0"
|
||||||
},
|
},
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"watch": "webpack-dev-server --hot --open",
|
"watch": "webpack-dev-server --hot --open",
|
||||||
"build": "webpack"
|
"build": "cross-env NODE_ENV=production webpack"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"netlify",
|
"netlify",
|
||||||
@ -66,6 +66,7 @@
|
|||||||
"what-input": "^5.0.3"
|
"what-input": "^5.0.3"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"cross-env": "^5.2.0",
|
||||||
"css-loader": "^1.0.0",
|
"css-loader": "^1.0.0",
|
||||||
"friendly-errors-webpack-plugin": "^1.7.0",
|
"friendly-errors-webpack-plugin": "^1.7.0",
|
||||||
"to-string-loader": "^1.1.5",
|
"to-string-loader": "^1.1.5",
|
||||||
|
@ -13,9 +13,10 @@
|
|||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"watch": "webpack -w",
|
"watch": "webpack -w",
|
||||||
"build": "webpack"
|
"build": "cross-env NODE_ENV=production webpack"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.16.1",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.1.0"
|
||||||
},
|
},
|
||||||
|
@ -14,12 +14,13 @@
|
|||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"watch": "webpack -w",
|
"watch": "webpack -w",
|
||||||
"build": "webpack"
|
"build": "cross-env NODE_ENV=production webpack"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"uuid": "^3.1.0"
|
"uuid": "^3.1.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.16.1",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.1.0"
|
||||||
},
|
},
|
||||||
|
@ -10,12 +10,13 @@
|
|||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"watch": "webpack -w",
|
"watch": "webpack -w",
|
||||||
"build": "webpack"
|
"build": "cross-env NODE_ENV=production webpack"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"localforage": "^1.4.2"
|
"localforage": "^1.4.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.16.1",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.1.0"
|
||||||
},
|
},
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"watch": "webpack -w",
|
"watch": "webpack -w",
|
||||||
"build": "webpack"
|
"build": "cross-env NODE_ENV=production webpack"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react-aria-menubutton": "^5.1.0",
|
"react-aria-menubutton": "^5.1.0",
|
||||||
@ -18,6 +18,7 @@
|
|||||||
"react-transition-group": "^2.2.1"
|
"react-transition-group": "^2.2.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.16.1",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.1.0"
|
||||||
},
|
},
|
||||||
|
@ -13,9 +13,10 @@
|
|||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"watch": "webpack -w",
|
"watch": "webpack -w",
|
||||||
"build": "webpack"
|
"build": "cross-env NODE_ENV=production webpack"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.16.1",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.1.0"
|
||||||
},
|
},
|
||||||
|
@ -14,12 +14,13 @@
|
|||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"watch": "webpack -w",
|
"watch": "webpack -w",
|
||||||
"build": "webpack"
|
"build": "cross-env NODE_ENV=production webpack"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react-datetime": "^2.11.0"
|
"react-datetime": "^2.11.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"cross-env": "^5.2.0",
|
||||||
"css-loader": "^1.0.0",
|
"css-loader": "^1.0.0",
|
||||||
"to-string-loader": "^1.1.5",
|
"to-string-loader": "^1.1.5",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.16.1",
|
||||||
|
@ -15,12 +15,13 @@
|
|||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"watch": "webpack -w",
|
"watch": "webpack -w",
|
||||||
"build": "webpack"
|
"build": "cross-env NODE_ENV=production webpack"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"netlify-cms-widget-date": "^2.0.0-alpha.0"
|
"netlify-cms-widget-date": "^2.0.0-alpha.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.16.1",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.1.0"
|
||||||
},
|
},
|
||||||
|
@ -15,12 +15,13 @@
|
|||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"watch": "webpack -w",
|
"watch": "webpack -w",
|
||||||
"build": "webpack"
|
"build": "cross-env NODE_ENV=production webpack"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"uuid": "^3.3.2"
|
"uuid": "^3.3.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.16.1",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.1.0"
|
||||||
},
|
},
|
||||||
|
@ -15,12 +15,13 @@
|
|||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"watch": "webpack -w",
|
"watch": "webpack -w",
|
||||||
"build": "webpack"
|
"build": "cross-env NODE_ENV=production webpack"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"netlify-cms-widget-file": "^2.0.0-alpha.0"
|
"netlify-cms-widget-file": "^2.0.0-alpha.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.16.1",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.1.0"
|
||||||
},
|
},
|
||||||
|
@ -14,13 +14,14 @@
|
|||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"watch": "webpack -w",
|
"watch": "webpack -w",
|
||||||
"build": "webpack"
|
"build": "cross-env NODE_ENV=production webpack"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"netlify-cms-widget-object": "^2.0.0-alpha.0",
|
"netlify-cms-widget-object": "^2.0.0-alpha.0",
|
||||||
"react-sortable-hoc": "^0.6.8"
|
"react-sortable-hoc": "^0.6.8"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.16.1",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.1.0"
|
||||||
},
|
},
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"watch": "webpack -w",
|
"watch": "webpack -w",
|
||||||
"build": "webpack"
|
"build": "cross-env NODE_ENV=production webpack"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"is-hotkey": "^0.1.1",
|
"is-hotkey": "^0.1.1",
|
||||||
@ -37,6 +37,7 @@
|
|||||||
"unist-util-visit-parents": "^1.1.1"
|
"unist-util-visit-parents": "^1.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.16.1",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.1.0"
|
||||||
},
|
},
|
||||||
|
@ -13,9 +13,10 @@
|
|||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"watch": "webpack -w",
|
"watch": "webpack -w",
|
||||||
"build": "webpack"
|
"build": "cross-env NODE_ENV=production webpack"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.16.1",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.1.0"
|
||||||
},
|
},
|
||||||
|
@ -15,9 +15,10 @@
|
|||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"watch": "webpack -w",
|
"watch": "webpack -w",
|
||||||
"build": "webpack"
|
"build": "cross-env NODE_ENV=production webpack"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.16.1",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.1.0"
|
||||||
},
|
},
|
||||||
|
@ -14,12 +14,13 @@
|
|||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"watch": "webpack -w",
|
"watch": "webpack -w",
|
||||||
"build": "webpack"
|
"build": "cross-env NODE_ENV=production webpack"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react-autosuggest": "^9.3.2"
|
"react-autosuggest": "^9.3.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.16.1",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.1.0"
|
||||||
},
|
},
|
||||||
|
@ -15,9 +15,10 @@
|
|||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"watch": "webpack -w",
|
"watch": "webpack -w",
|
||||||
"build": "webpack"
|
"build": "cross-env NODE_ENV=production webpack"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.16.1",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.1.0"
|
||||||
},
|
},
|
||||||
|
@ -13,9 +13,10 @@
|
|||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"watch": "webpack -w",
|
"watch": "webpack -w",
|
||||||
"build": "webpack"
|
"build": "cross-env NODE_ENV=production webpack"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.16.1",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.1.0"
|
||||||
},
|
},
|
||||||
|
@ -16,12 +16,13 @@
|
|||||||
"sideEffects": false,
|
"sideEffects": false,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"watch": "webpack -w",
|
"watch": "webpack -w",
|
||||||
"build": "webpack"
|
"build": "cross-env NODE_ENV=production webpack"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"react-textarea-autosize": "^5.2.0"
|
"react-textarea-autosize": "^5.2.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.16.1",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.1.0"
|
||||||
},
|
},
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
"version": "2.0.0-alpha.0",
|
"version": "2.0.0-alpha.0",
|
||||||
"main": "dist/netlify-cms.js",
|
"main": "dist/netlify-cms.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "webpack"
|
"build": "cross-env NODE_ENV=production webpack"
|
||||||
},
|
},
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"netlify",
|
"netlify",
|
||||||
@ -38,6 +38,7 @@
|
|||||||
"netlify-cms-widget-text": "2.0.0-alpha.0"
|
"netlify-cms-widget-text": "2.0.0-alpha.0"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"cross-env": "^5.2.0",
|
||||||
"webpack": "^4.16.1",
|
"webpack": "^4.16.1",
|
||||||
"webpack-cli": "^3.1.0"
|
"webpack-cli": "^3.1.0"
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,6 @@ import { GitLabBackend } from 'netlify-cms-backend-gitlab/src';
|
|||||||
import { GitGatewayBackend } from 'netlify-cms-backend-git-gateway/src';
|
import { GitGatewayBackend } from 'netlify-cms-backend-git-gateway/src';
|
||||||
import { TestBackend } from 'netlify-cms-backend-test/src';
|
import { TestBackend } from 'netlify-cms-backend-test/src';
|
||||||
|
|
||||||
console.log(cms);
|
|
||||||
const { registerBackend } = cms;
|
const { registerBackend } = cms;
|
||||||
|
|
||||||
registerBackend('git-gateway', GitGatewayBackend);
|
registerBackend('git-gateway', GitGatewayBackend);
|
||||||
|
@ -25,7 +25,12 @@ const rules = () => ({
|
|||||||
|
|
||||||
const plugins = () => {
|
const plugins = () => {
|
||||||
return {
|
return {
|
||||||
friendlyErrors: () => new FriendlyErrorsWebpackPlugin()
|
define: () => new webpack.DefinePlugin({
|
||||||
|
NETLIFY_CMS_VERSION: `${pkg.version}${isProduction ? '' : '-dev'}`,
|
||||||
|
}),
|
||||||
|
ignoreEsprima: () => new webpack.IgnorePlugin(/^esprima$/, /js-yaml/),
|
||||||
|
ignoreMomentOptionalDeps: () => new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
|
||||||
|
friendlyErrors: () => new FriendlyErrorsWebpackPlugin(),
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,150 +0,0 @@
|
|||||||
import { flow } from "lodash";
|
|
||||||
import LocalForage from "Lib/LocalForage";
|
|
||||||
import unsentRequest from "Lib/unsentRequest";
|
|
||||||
import { responseParser } from "Lib/backendHelper";
|
|
||||||
import { then } from "Lib/promiseHelper";
|
|
||||||
import { basename } from "Lib/pathHelper";
|
|
||||||
import AssetProxy from "ValueObjects/AssetProxy";
|
|
||||||
import Cursor from "ValueObjects/Cursor";
|
|
||||||
import { APIError } from "ValueObjects/errors";
|
|
||||||
|
|
||||||
export default class API {
|
|
||||||
constructor(config) {
|
|
||||||
this.api_root = config.api_root || "https://api.bitbucket.org/2.0";
|
|
||||||
this.branch = config.branch || "master";
|
|
||||||
this.repo = config.repo || "";
|
|
||||||
this.requestFunction = config.requestFunction || unsentRequest.performRequest;
|
|
||||||
// Allow overriding this.hasWriteAccess
|
|
||||||
this.hasWriteAccess = config.hasWriteAccess || this.hasWriteAccess;
|
|
||||||
this.repoURL = this.repo ? `/repositories/${ this.repo }` : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
buildRequest = req => flow([
|
|
||||||
unsentRequest.withRoot(this.api_root),
|
|
||||||
unsentRequest.withTimestamp,
|
|
||||||
])(req);
|
|
||||||
|
|
||||||
request = req => flow([
|
|
||||||
this.buildRequest,
|
|
||||||
this.requestFunction,
|
|
||||||
p => p.catch(err => Promise.reject(new APIError(err.message, null, "BitBucket"))),
|
|
||||||
])(req);
|
|
||||||
|
|
||||||
requestJSON = req => flow([
|
|
||||||
unsentRequest.withDefaultHeaders({ "Content-Type": "application/json" }),
|
|
||||||
this.request,
|
|
||||||
then(responseParser({ format: "json" })),
|
|
||||||
p => p.catch(err => Promise.reject(new APIError(err.message, null, "BitBucket"))),
|
|
||||||
])(req);
|
|
||||||
requestText = req => flow([
|
|
||||||
unsentRequest.withDefaultHeaders({ "Content-Type": "text/plain" }),
|
|
||||||
this.request,
|
|
||||||
then(responseParser({ format: "text" })),
|
|
||||||
p => p.catch(err => Promise.reject(new APIError(err.message, null, "BitBucket"))),
|
|
||||||
])(req);
|
|
||||||
|
|
||||||
user = () => this.request("/user");
|
|
||||||
hasWriteAccess = user => this.request(this.repoURL).then(res => res.ok);
|
|
||||||
|
|
||||||
isFile = ({ type }) => type === "commit_file";
|
|
||||||
processFile = file => ({
|
|
||||||
...file,
|
|
||||||
name: basename(file.path),
|
|
||||||
download_url: file.links.self.href,
|
|
||||||
|
|
||||||
// BitBucket does not return file SHAs, but it does give us the
|
|
||||||
// commit SHA. Since the commit SHA will change if any files do,
|
|
||||||
// we can construct an ID using the commit SHA and the file path
|
|
||||||
// that will help with caching (though not as well as a normal
|
|
||||||
// SHA, since it will change even if the individual file itself
|
|
||||||
// doesn't.)
|
|
||||||
...(file.commit && file.commit.hash
|
|
||||||
? { id: `${ file.commit.hash }/${ file.path }` }
|
|
||||||
: {}),
|
|
||||||
});
|
|
||||||
processFiles = files => files.filter(this.isFile).map(this.processFile);
|
|
||||||
|
|
||||||
readFile = async (path, sha, { ref = this.branch, parseText = true } = {}) => {
|
|
||||||
const cacheKey = parseText ? `bb.${ sha }` : `bb.${ sha }.blob`;
|
|
||||||
const cachedFile = sha ? await LocalForage.getItem(cacheKey) : null;
|
|
||||||
if (cachedFile) { return cachedFile; }
|
|
||||||
const result = await this.request({
|
|
||||||
url: `${ this.repoURL }/src/${ ref }/${ path }`,
|
|
||||||
cache: "no-store",
|
|
||||||
}).then(parseText ? responseParser({ format: "text" }) : responseParser({ format: "blob" }));
|
|
||||||
if (sha) { LocalForage.setItem(cacheKey, result); }
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
getEntriesAndCursor = jsonResponse => {
|
|
||||||
const { size: count, page: index, pagelen: pageSize, next, previous: prev, values: entries } = jsonResponse;
|
|
||||||
const pageCount = (pageSize && count) ? Math.ceil(count / pageSize) : undefined;
|
|
||||||
return {
|
|
||||||
entries,
|
|
||||||
cursor: Cursor.create({
|
|
||||||
actions: [...(next ? ["next"] : []), ...(prev ? ["prev"] : [])],
|
|
||||||
meta: { index, count, pageSize, pageCount },
|
|
||||||
data: { links: { next, prev } },
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
listFiles = async path => {
|
|
||||||
const { entries, cursor } = await flow([
|
|
||||||
// sort files by filename ascending
|
|
||||||
unsentRequest.withParams({ sort: "-path" }),
|
|
||||||
this.requestJSON,
|
|
||||||
then(this.getEntriesAndCursor),
|
|
||||||
])(`${ this.repoURL }/src/${ this.branch }/${ path }`);
|
|
||||||
return { entries: this.processFiles(entries), cursor };
|
|
||||||
}
|
|
||||||
|
|
||||||
traverseCursor = async (cursor, action) => flow([
|
|
||||||
this.requestJSON,
|
|
||||||
then(this.getEntriesAndCursor),
|
|
||||||
then(({ cursor: newCursor, entries }) => ({ cursor: newCursor, entries: this.processFiles(entries) })),
|
|
||||||
])(cursor.data.getIn(["links", action]));
|
|
||||||
|
|
||||||
listAllFiles = async path => {
|
|
||||||
const { cursor: initialCursor, entries: initialEntries } = await this.listFiles(path);
|
|
||||||
const entries = [...initialEntries];
|
|
||||||
let currentCursor = initialCursor;
|
|
||||||
while (currentCursor && currentCursor.actions.has("next")) {
|
|
||||||
const { cursor: newCursor, entries: newEntries } = await this.traverseCursor(currentCursor, "next");
|
|
||||||
entries.push(...newEntries);
|
|
||||||
currentCursor = newCursor;
|
|
||||||
}
|
|
||||||
return this.processFiles(entries);
|
|
||||||
};
|
|
||||||
|
|
||||||
uploadBlob = async item => {
|
|
||||||
const contentBase64 = await (item instanceof AssetProxy ? item.toBase64() : Promise.resolve(item.raw));
|
|
||||||
const formData = new FormData();
|
|
||||||
formData.append(item.path, contentBase64);
|
|
||||||
|
|
||||||
return flow([
|
|
||||||
unsentRequest.withMethod("POST"),
|
|
||||||
unsentRequest.withBody(formData),
|
|
||||||
this.request,
|
|
||||||
then(() => ({ ...item, uploaded: true })),
|
|
||||||
])(`${ this.repoURL }/src`);
|
|
||||||
};
|
|
||||||
|
|
||||||
persistFiles = (files, { commitMessage, newEntry }) => Promise.all(
|
|
||||||
files.filter(({ uploaded }) => !uploaded).map(this.uploadBlob)
|
|
||||||
);
|
|
||||||
|
|
||||||
deleteFile = (path, message, options={}) => {
|
|
||||||
const branch = options.branch || this.branch;
|
|
||||||
const body = new FormData();
|
|
||||||
body.append('files', path);
|
|
||||||
if (message && message !== "") {
|
|
||||||
body.append("message", message);
|
|
||||||
}
|
|
||||||
return flow([
|
|
||||||
unsentRequest.withMethod("POST"),
|
|
||||||
unsentRequest.withBody(body),
|
|
||||||
this.request,
|
|
||||||
])(`${ this.repoURL }/src`);
|
|
||||||
};
|
|
||||||
}
|
|
@ -1,50 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import Authenticator from 'Lib/netlify-auth';
|
|
||||||
import { Icon } from 'UI';
|
|
||||||
|
|
||||||
export default class AuthenticationPage extends React.Component {
|
|
||||||
static propTypes = {
|
|
||||||
onLogin: PropTypes.func.isRequired,
|
|
||||||
inProgress: PropTypes.bool,
|
|
||||||
};
|
|
||||||
|
|
||||||
state = {};
|
|
||||||
|
|
||||||
handleLogin = (e) => {
|
|
||||||
e.preventDefault();
|
|
||||||
const cfg = {
|
|
||||||
base_url: this.props.base_url,
|
|
||||||
site_id: (document.location.host.split(':')[0] === 'localhost') ? 'cms.netlify.com' : this.props.site_id,
|
|
||||||
auth_endpoint: this.props.authEndpoint,
|
|
||||||
};
|
|
||||||
const auth = new Authenticator(cfg);
|
|
||||||
|
|
||||||
auth.authenticate({ provider: 'bitbucket', scope: 'repo' }, (err, data) => {
|
|
||||||
if (err) {
|
|
||||||
this.setState({ loginError: err.toString() });
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.props.onLogin(data);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
|
||||||
const { loginError } = this.state;
|
|
||||||
const { inProgress } = this.props;
|
|
||||||
|
|
||||||
return (
|
|
||||||
<section className="nc-githubAuthenticationPage-root">
|
|
||||||
<Icon className="nc-githubAuthenticationPage-logo" size="500px" type="netlify-cms"/>
|
|
||||||
{loginError && <p>{loginError}</p>}
|
|
||||||
<button
|
|
||||||
className="nc-githubAuthenticationPage-button"
|
|
||||||
disabled={inProgress}
|
|
||||||
onClick={this.handleLogin}
|
|
||||||
>
|
|
||||||
<Icon type="bitbucket" /> {inProgress ? "Logging in..." : "Login with Bitbucket"}
|
|
||||||
</button>
|
|
||||||
</section>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,222 +0,0 @@
|
|||||||
import semaphore from "semaphore";
|
|
||||||
import { flow, trimStart } from "lodash";
|
|
||||||
import { EDITORIAL_WORKFLOW } from "Constants/publishModes";
|
|
||||||
import { CURSOR_COMPATIBILITY_SYMBOL } from "ValueObjects/Cursor";
|
|
||||||
import { filterByPropExtension } from "Lib/backendHelper";
|
|
||||||
import { resolvePromiseProperties, then } from "Lib/promiseHelper";
|
|
||||||
import unsentRequest from "Lib/unsentRequest";
|
|
||||||
import AuthenticationPage from "./AuthenticationPage";
|
|
||||||
import Authenticator from 'Lib/netlify-auth';
|
|
||||||
import API from "./API";
|
|
||||||
|
|
||||||
const MAX_CONCURRENT_DOWNLOADS = 10;
|
|
||||||
|
|
||||||
// Implementation wrapper class
|
|
||||||
export default class Bitbucket {
|
|
||||||
constructor(config, options={}) {
|
|
||||||
this.config = config;
|
|
||||||
this.options = {
|
|
||||||
proxied: false,
|
|
||||||
API: null,
|
|
||||||
updateUserCredentials: async () => null,
|
|
||||||
...options,
|
|
||||||
};
|
|
||||||
|
|
||||||
if (config.getIn(["publish_mode"]) === EDITORIAL_WORKFLOW) {
|
|
||||||
throw new Error("The BitBucket backend does not support the Editorial Workflow.");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.options.proxied && !config.getIn(["backend", "repo"], false)) {
|
|
||||||
throw new Error("The BitBucket backend needs a \"repo\ in the backend configuration.");
|
|
||||||
}
|
|
||||||
|
|
||||||
this.api = this.options.API || null;
|
|
||||||
|
|
||||||
this.updateUserCredentials = this.options.updateUserCredentials;
|
|
||||||
|
|
||||||
this.repo = config.getIn(["backend", "repo"], "");
|
|
||||||
this.branch = config.getIn(["backend", "branch"], "master");
|
|
||||||
this.api_root = config.getIn(["backend", "api_root"], "https://api.bitbucket.org/2.0");
|
|
||||||
this.base_url = config.get("base_url");
|
|
||||||
this.site_id = config.get("site_id");
|
|
||||||
this.token = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
authComponent() {
|
|
||||||
return AuthenticationPage;
|
|
||||||
}
|
|
||||||
|
|
||||||
setUser(user) {
|
|
||||||
this.token = user.token;
|
|
||||||
this.api = new API({ requestFunction: this.apiRequestFunction, branch: this.branch, repo: this.repo });
|
|
||||||
}
|
|
||||||
|
|
||||||
restoreUser(user) {
|
|
||||||
return this.authenticate(user);
|
|
||||||
}
|
|
||||||
|
|
||||||
authenticate(state) {
|
|
||||||
this.token = state.token;
|
|
||||||
this.refreshToken = state.refresh_token;
|
|
||||||
this.api = new API({ requestFunction: this.apiRequestFunction, branch: this.branch, repo: this.repo, api_root: this.api_root });
|
|
||||||
|
|
||||||
return this.api.user().then(user =>
|
|
||||||
this.api.hasWriteAccess(user).then(isCollab => {
|
|
||||||
if (!isCollab) throw new Error("Your BitBucker user account does not have access to this repo.");
|
|
||||||
return Object.assign({}, user, { token: state.token, refresh_token: state.refresh_token });
|
|
||||||
})
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
getRefreshedAccessToken() {
|
|
||||||
if (this.refreshedTokenPromise) {
|
|
||||||
return this.refreshedTokenPromise;
|
|
||||||
}
|
|
||||||
|
|
||||||
// instantiating a new Authenticator on each refresh isn't ideal,
|
|
||||||
if (!this.auth) {
|
|
||||||
const cfg = {
|
|
||||||
base_url: this.base_url,
|
|
||||||
site_id: this.site_id,
|
|
||||||
};
|
|
||||||
this.authenticator = new Authenticator(cfg);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.refreshedTokenPromise = this.authenticator.refresh({ provider: "bitbucket", refresh_token: this.refreshToken })
|
|
||||||
.then(({ token, refresh_token }) => {
|
|
||||||
this.token = token;
|
|
||||||
this.refreshToken = refresh_token;
|
|
||||||
this.refreshedTokenPromise = undefined;
|
|
||||||
this.updateUserCredentials({ token, refresh_token });
|
|
||||||
return token;
|
|
||||||
});
|
|
||||||
|
|
||||||
return this.refreshedTokenPromise;
|
|
||||||
}
|
|
||||||
|
|
||||||
logout() {
|
|
||||||
this.token = null;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
getToken() {
|
|
||||||
if (this.refreshedTokenPromise) {
|
|
||||||
return this.refreshedTokenPromise;
|
|
||||||
}
|
|
||||||
|
|
||||||
return Promise.resolve(this.token);
|
|
||||||
}
|
|
||||||
|
|
||||||
apiRequestFunction = async req => {
|
|
||||||
const token = this.refreshedTokenPromise ? await this.refreshedTokenPromise : this.token;
|
|
||||||
return flow([
|
|
||||||
unsentRequest.withHeaders({ Authorization: `Bearer ${ token }` }),
|
|
||||||
unsentRequest.performRequest,
|
|
||||||
then(async res => {
|
|
||||||
if (res.status === 401) {
|
|
||||||
const json = (await res.json().catch(() => null));
|
|
||||||
if (json && json.type === "error" && /^access token expired/i.test(json.error.message)) {
|
|
||||||
const newToken = await this.getRefreshedAccessToken();
|
|
||||||
const reqWithNewToken = unsentRequest.withHeaders({ Authorization: `Bearer ${ newToken }` }, req);
|
|
||||||
return unsentRequest.performRequest(reqWithNewToken);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}),
|
|
||||||
])(req);
|
|
||||||
};
|
|
||||||
|
|
||||||
entriesByFolder(collection, extension) {
|
|
||||||
const listPromise = this.api.listFiles(collection.get("folder"));
|
|
||||||
return resolvePromiseProperties({
|
|
||||||
files: listPromise
|
|
||||||
.then(({ entries }) => entries)
|
|
||||||
.then(filterByPropExtension(extension, "path"))
|
|
||||||
.then(this.fetchFiles),
|
|
||||||
cursor: listPromise.then(({ cursor }) => cursor),
|
|
||||||
}).then(({ files, cursor }) => {
|
|
||||||
files[CURSOR_COMPATIBILITY_SYMBOL] = cursor;
|
|
||||||
return files;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
allEntriesByFolder(collection, extension) {
|
|
||||||
return this.api.listAllFiles(collection.get("folder"))
|
|
||||||
.then(filterByPropExtension(extension, "path"))
|
|
||||||
.then(this.fetchFiles);
|
|
||||||
}
|
|
||||||
|
|
||||||
entriesByFiles(collection) {
|
|
||||||
const files = collection.get("files").map(collectionFile => ({
|
|
||||||
path: collectionFile.get("file"),
|
|
||||||
label: collectionFile.get("label"),
|
|
||||||
}));
|
|
||||||
return this.fetchFiles(files);
|
|
||||||
}
|
|
||||||
|
|
||||||
fetchFiles = (files) => {
|
|
||||||
const sem = semaphore(MAX_CONCURRENT_DOWNLOADS);
|
|
||||||
const promises = [];
|
|
||||||
files.forEach((file) => {
|
|
||||||
promises.push(new Promise((resolve, reject) => (
|
|
||||||
sem.take(() => this.api.readFile(file.path, file.id).then((data) => {
|
|
||||||
resolve({ file, data });
|
|
||||||
sem.leave();
|
|
||||||
}).catch((error = true) => {
|
|
||||||
sem.leave();
|
|
||||||
console.error(`failed to load file from BitBucket: ${ file.path }`);
|
|
||||||
resolve({ error });
|
|
||||||
}))
|
|
||||||
)));
|
|
||||||
});
|
|
||||||
return Promise.all(promises)
|
|
||||||
.then(loadedEntries => loadedEntries.filter(loadedEntry => !loadedEntry.error));
|
|
||||||
}
|
|
||||||
|
|
||||||
getEntry(collection, slug, path) {
|
|
||||||
return this.api.readFile(path).then(data => ({
|
|
||||||
file: { path },
|
|
||||||
data,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
getMedia() {
|
|
||||||
const sem = semaphore(MAX_CONCURRENT_DOWNLOADS);
|
|
||||||
|
|
||||||
return this.api.listAllFiles(this.config.get("media_folder"))
|
|
||||||
.then(files => files.map(({ id, name, download_url, path }) => {
|
|
||||||
const getBlobPromise = () => new Promise((resolve, reject) =>
|
|
||||||
sem.take(() =>
|
|
||||||
this.api.readFile(path, id, { parseText: false })
|
|
||||||
.then(resolve, reject)
|
|
||||||
.finally(() => sem.leave())
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
return { id, name, getBlobPromise, url: download_url, path };
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
|
|
||||||
persistEntry(entry, mediaFiles, options = {}) {
|
|
||||||
return this.api.persistFiles([entry], options);
|
|
||||||
}
|
|
||||||
|
|
||||||
async persistMedia(mediaFile, options = {}) {
|
|
||||||
await this.api.persistFiles([mediaFile], options);
|
|
||||||
const { value, path, fileObj } = mediaFile;
|
|
||||||
const getBlobPromise = () => Promise.resolve(fileObj);
|
|
||||||
return { name: value, size: fileObj.size, getBlobPromise, path: trimStart(path, '/k') };
|
|
||||||
}
|
|
||||||
|
|
||||||
deleteFile(path, commitMessage, options) {
|
|
||||||
return this.api.deleteFile(path, commitMessage, options);
|
|
||||||
}
|
|
||||||
|
|
||||||
traverseCursor(cursor, action) {
|
|
||||||
return this.api.traverseCursor(cursor, action)
|
|
||||||
.then(async ({ entries, cursor: newCursor }) => ({
|
|
||||||
entries: await Promise.all(entries.map(file => this.api.readFile(file.path, file.id).then(data => ({ file, data })))),
|
|
||||||
cursor: newCursor,
|
|
||||||
}));
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
x
Reference in New Issue
Block a user