Ask if user wants to download latest version of block on lunch of the devTool.

This commit is contained in:
roman committed 2023-08-19 18:08:39 +03:00
1 parent 51db3da072
commit 256450226b
10 files changed
+398 -10081

No files matched your search

+37
View File
@@ -265,3 +265,40 @@ export function replaceNames(content, images, uploadedImages) {
return content;
}
export async function getBlockFromCloud(blockName, blocksRegistry) {
const queryString = new URLSearchParams();
queryString.append('blockName', blockName);
queryString.append('includeDevConfig', 'true');
const response = await fetch(`${blocksRegistry}?${queryString.toString()}`);
const responseData = await response.json();
if (!responseData || !responseData.name) {
const message = "⚠️ Block not found, please contact administrator."
throw new Error(message);
}
if (responseData.statusCode && responseData.statusCode !== 200) {
const message = ["⚠️ [ERROR]", responseData.message || "Server side error."].join(' ');
throw new Error(message);
}
return responseData;
}
export async function verifyVersion(projectPath, blocksRegistry) {
const blockJson = await readJSONFile(path.join(projectPath, `block.json`));
const blockName = getBlockName(blockJson.name);
if (typeof blockJson.version === 'undefined' || !blockName.name) {
return true;
}
/*
* This block is managed on cloud.
* Let's detect the latest version.
*/
const block = await getBlockFromCloud('@' + blockJson.name, blocksRegistry);
return block.version === blockJson.version;
}
+1 -136
View File
@@ -1,136 +1 @@
window.initBlock = initBlock;
let template;
let data = {};
let reload;
// Blocks Initialization.
function initBlock(blockName = '', selector = '', cb) {
reload = function () {
document.querySelectorAll(selector).forEach((el) => cb(el));
};
reload();
}
// Data Updates Listeners.
(function () {
loadDataOptions();
listenToDataOptionsUpdates();
function listenToDataOptionsUpdates() {
window.addEventListener('message', function (event) {
const message = event.data;
const prefix = 'dataUpdate:';
if (typeof message !== "string" || !message.startsWith(prefix)) {
return;
}
try {
data = JSON.parse(message.substring(prefix.length));
updateBlock({data});
} catch (e) {
console.log('Error parsing incoming data.', e);
}
});
}
function getQueryParams() {
const urlParams = new URLSearchParams(window.location.search);
const params = {};
for (const [key, value] of urlParams) {
params[key] = value;
}
return params;
}
function loadDataOptions() {
const queryParameters = new URLSearchParams({name: getQueryParams().data || 'default'});
fetch(`/data?${queryParameters}`)
.then((response) => response.json())
.then((response) => {
data = response.data; // Update state.
updateBlock({data});
});
}
})();
// Listen to Template updates.
(function () {
initSocket();
function initSocket() {
const socket = window.io.connect();
socket.on('error', function (err) {
console.log(err);
});
// socket.on('connect', function () {
// console.log('user connected', socket.id)
// });
socket.on('templateUpdate', function (args) {
updateBlock({template: args.template});
});
}
})();
function updateBlock(args = {}) {
if (args.template) {
template = args.template; // Update state.
}
if (args.data) {
data = args.data; // Update state.
}
if (!template) {
return;
}
renderBlock(template, data || {}, document.getElementById("hbs-container"));
}
function renderBlock(templateHbs, jsonData, target) {
const template = Handlebars.compile(templateHbs);
/**
* Handlebars Helpers
*/
Handlebars.registerHelper('esc_attr', function (attr) {
return attr;
});
Handlebars.registerHelper('esc_url', function (attr) {
return attr;
});
Handlebars.registerHelper('esc_html', function (attr) {
return attr;
});
Handlebars.registerHelper('base_url', function () {
return '/';
});
let html;
try {
html = template(jsonData);
} catch (e) {
html = `<div style="max-width: 1280px; margin: 1rem auto;">
<h1 style="all: unset; font-size: 1.5rem; font-weight: bold; display: block;">Syntax Error:</h1>
<pre style="all: unset; padding: 10px 15px; background-color: #ffe6e6; border: 1px solid red; border-radius: 0.25rem; overflow: auto; display: block; white-space: pre;">${e.toString()}</pre>
</div>`;
}
target.innerHTML = html;
if (reload) {
reload();
}
}
//# sourceMappingURL=frame-index.min.js.map
let e;window.initBlock=function(e="",n="",r){t=function(){document.querySelectorAll(n).forEach((e=>r(e)))},t()};let t,n={};function r(r={}){r.template&&(e=r.template),r.data&&(n=r.data),e&&function(e,n,r){const a=Handlebars.compile(e);let o;Handlebars.registerHelper("esc_attr",(function(e){return e})),Handlebars.registerHelper("esc_url",(function(e){return e})),Handlebars.registerHelper("esc_html",(function(e){return e})),Handlebars.registerHelper("base_url",(function(){return"/"}));try{o=a(n)}catch(e){o=`<div style="max-width: 1280px; margin: 1rem auto;">\n <h1 style="all: unset; font-size: 1.5rem; font-weight: bold; display: block;">Syntax Error:</h1>\n <pre style="all: unset; padding: 10px 15px; background-color: #ffe6e6; border: 1px solid red; border-radius: 0.25rem; overflow: auto; display: block; white-space: pre;">${e.toString()}</pre>\n </div>`}r.innerHTML=o,t&&t()}(e,n||{},document.getElementById("hbs-container"))}!function(){function e(){const e=new URLSearchParams(window.location.search),t={};for(const[n,r]of e)t[n]=r;return t}!function(){const t=new URLSearchParams({name:e().data||"default"});fetch(`/data?${t}`).then((e=>e.json())).then((e=>{n=e.data,r({data:n})}))}(),window.addEventListener("message",(function(e){const t=e.data,a="dataUpdate:";if("string"==typeof t&&t.startsWith(a))try{n=JSON.parse(t.substring(a.length)),r({data:n})}catch(e){console.log("Error parsing incoming data.",e)}}))}(),function(){const e=window.io.connect();e.on("error",(function(e){console.log(e)})),e.on("templateUpdate",(function(e){r({template:e.template})}))}();
+15 -9905
View File
File diff suppressed because it is too large. Load diff
+21
View File
@@ -0,0 +1,21 @@
function e(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var n={exports:{}},t={},r=Symbol.for("react.element"),l=Symbol.for("react.portal"),a=Symbol.for("react.fragment"),o=Symbol.for("react.strict_mode"),u=Symbol.for("react.profiler"),i=Symbol.for("react.provider"),s=Symbol.for("react.context"),c=Symbol.for("react.forward_ref"),f=Symbol.for("react.suspense"),d=Symbol.for("react.memo"),p=Symbol.for("react.lazy"),m=Symbol.iterator;var h={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},g=Object.assign,v={};function y(e,n,t){this.props=e,this.context=n,this.refs=v,this.updater=t||h}function b(){}function k(e,n,t){this.props=e,this.context=n,this.refs=v,this.updater=t||h}y.prototype.isReactComponent={},y.prototype.setState=function(e,n){if("object"!=typeof e&&"function"!=typeof e&&null!=e)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,e,n,"setState")},y.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,"forceUpdate")},b.prototype=y.prototype;var w=k.prototype=new b;w.constructor=k,g(w,y.prototype),w.isPureReactComponent=!0;var S=Array.isArray,E=Object.prototype.hasOwnProperty,x={current:null},C={key:!0,ref:!0,__self:!0,__source:!0};function _(e,n,t){var l,a={},o=null,u=null;if(null!=n)for(l in void 0!==n.ref&&(u=n.ref),void 0!==n.key&&(o=""+n.key),n)E.call(n,l)&&!C.hasOwnProperty(l)&&(a[l]=n[l]);var i=arguments.length-2;if(1===i)a.children=t;else if(1<i){for(var s=Array(i),c=0;c<i;c++)s[c]=arguments[c+2];a.children=s}if(e&&e.defaultProps)for(l in i=e.defaultProps)void 0===a[l]&&(a[l]=i[l]);return{$$typeof:r,type:e,key:o,ref:u,props:a,_owner:x.current}}function P(e){return"object"==typeof e&&null!==e&&e.$$typeof===r}var N=/\/+/g;function z(e,n){return"object"==typeof e&&null!==e&&null!=e.key?function(e){var n={"=":"=0",":":"=2"};return"$"+e.replace(/[=:]/g,(function(e){return n[e]}))}(""+e.key):n.toString(36)}function T(e,n,t,a,o){var u=typeof e;"undefined"!==u&&"boolean"!==u||(e=null);var i=!1;if(null===e)i=!0;else switch(u){case"string":case"number":i=!0;break;case"object":switch(e.$$typeof){case r:case l:i=!0}}if(i)return o=o(i=e),e=""===a?"."+z(i,0):a,S(o)?(t="",null!=e&&(t=e.replace(N,"$&/")+"/"),T(o,n,t,"",(function(e){return e}))):null!=o&&(P(o)&&(o=function(e,n){return{$$typeof:r,type:e.type,key:n,ref:e.ref,props:e.props,_owner:e._owner}}(o,t+(!o.key||i&&i.key===o.key?"":(""+o.key).replace(N,"$&/")+"/")+e)),n.push(o)),1;if(i=0,a=""===a?".":a+":",S(e))for(var s=0;s<e.length;s++){var c=a+z(u=e[s],s);i+=T(u,n,t,c,o)}else if(c=function(e){return null===e||"object"!=typeof e?null:"function"==typeof(e=m&&e[m]||e["@@iterator"])?e:null}(e),"function"==typeof c)for(e=c.call(e),s=0;!(u=e.next()).done;)i+=T(u=u.value,n,t,c=a+z(u,s++),o);else if("object"===u)throw n=String(e),Error("Objects are not valid as a React child (found: "+("[object Object]"===n?"object with keys {"+Object.keys(e).join(", ")+"}":n)+"). If you meant to render a collection of children, use an array instead.");return i}function L(e,n,t){if(null==e)return e;var r=[],l=0;return T(e,r,"","",(function(e){return n.call(t,e,l++)})),r}function R(e){if(-1===e._status){var n=e._result;(n=n()).then((function(n){0!==e._status&&-1!==e._status||(e._status=1,e._result=n)}),(function(n){0!==e._status&&-1!==e._status||(e._status=2,e._result=n)})),-1===e._status&&(e._status=0,e._result=n)}if(1===e._status)return e._result.default;throw e._result}var M={current:null},F={transition:null},O={ReactCurrentDispatcher:M,ReactCurrentBatchConfig:F,ReactCurrentOwner:x};t.Children={map:L,forEach:function(e,n,t){L(e,(function(){n.apply(this,arguments)}),t)},count:function(e){var n=0;return L(e,(function(){n++})),n},toArray:function(e){return L(e,(function(e){return e}))||[]},only:function(e){if(!P(e))throw Error("React.Children.only expected to receive a single React element child.");return e}},t.Component=y,t.Fragment=a,t.Profiler=u,t.PureComponent=k,t.StrictMode=o,t.Suspense=f,t.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED=O,t.cloneElement=function(e,n,t){if(null==e)throw Error("React.cloneElement(...): The argument must be a React element, but you passed "+e+".");var l=g({},e.props),a=e.key,o=e.ref,u=e._owner;if(null!=n){if(void 0!==n.ref&&(o=n.ref,u=x.current),void 0!==n.key&&(a=""+n.key),e.type&&e.type.defaultProps)var i=e.type.defaultProps;for(s in n)E.call(n,s)&&!C.hasOwnProperty(s)&&(l[s]=void 0===n[s]&&void 0!==i?i[s]:n[s])}var s=arguments.length-2;if(1===s)l.children=t;else if(1<s){i=Array(s);for(var c=0;c<s;c++)i[c]=arguments[c+2];l.children=i}return{$$typeof:r,type:e.type,key:a,ref:o,props:l,_owner:u}},t.createContext=function(e){return(e={$$typeof:s,_currentValue:e,_currentValue2:e,_threadCount:0,Provider:null,Consumer:null,_defaultValue:null,_globalName:null}).Provider={$$typeof:i,_context:e},Line truncated
/**
* @license React
* scheduler.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
!function(e){function n(e,n){var t=e.length;e.push(n);e:for(;0<t;){var r=t-1>>>1,a=e[r];if(!(0<l(a,n)))break e;e[r]=n,e[t]=a,t=r}}function t(e){return 0===e.length?null:e[0]}function r(e){if(0===e.length)return null;var n=e[0],t=e.pop();if(t!==n){e[0]=t;e:for(var r=0,a=e.length,o=a>>>1;r<o;){var u=2*(r+1)-1,i=e[u],s=u+1,c=e[s];if(0>l(i,t))s<a&&0>l(c,i)?(e[r]=c,e[s]=t,r=s):(e[r]=i,e[u]=t,r=u);else{if(!(s<a&&0>l(c,t)))break e;e[r]=c,e[s]=t,r=s}}}return n}function l(e,n){var t=e.sortIndex-n.sortIndex;return 0!==t?t:e.id-n.id}if("object"==typeof performance&&"function"==typeof performance.now){var a=performance;e.unstable_now=function(){return a.now()}}else{var o=Date,u=o.now();e.unstable_now=function(){return o.now()-u}}var i=[],s=[],c=1,f=null,d=3,p=!1,m=!1,h=!1,g="function"==typeof setTimeout?setTimeout:null,v="function"==typeof clearTimeout?clearTimeout:null,y="undefined"!=typeof setImmediate?setImmediate:null;function b(e){for(var l=t(s);null!==l;){if(null===l.callback)r(s);else{if(!(l.startTime<=e))break;r(s),l.sortIndex=l.expirationTime,n(i,l)}l=t(s)}}function k(e){if(h=!1,b(e),!m)if(null!==t(i))m=!0,R(w);else{var n=t(s);null!==n&&M(k,n.startTime-e)}}function w(n,l){m=!1,h&&(h=!1,v(C),C=-1),p=!0;var a=d;try{for(b(l),f=t(i);null!==f&&(!(f.expirationTime>l)||n&&!N());){var o=f.callback;if("function"==typeof o){f.callback=null,d=f.priorityLevel;var u=o(f.expirationTime<=l);l=e.unstable_now(),"function"==typeof u?f.callback=u:f===t(i)&&r(i),b(l)}else r(i);f=t(i)}if(null!==f)var c=!0;else{var g=t(s);null!==g&&M(k,g.startTime-l),c=!1}return c}finally{f=null,d=a,p=!1}}"undefined"!=typeof navigator&&void 0!==navigator.scheduling&&void 0!==navigator.scheduling.isInputPending&&navigator.scheduling.isInputPending.bind(navigator.scheduling);var S,E=!1,x=null,C=-1,_=5,P=-1;function N(){return!(e.unstable_now()-P<_)}function z(){if(null!==x){var n=e.unstable_now();P=n;var t=!0;try{t=x(!0,n)}finally{t?S():(E=!1,x=null)}}else E=!1}if("function"==typeof y)S=function(){y(z)};else if("undefined"!=typeof MessageChannel){var T=new MessageChannel,L=T.port2;T.port1.onmessage=z,S=function(){L.postMessage(null)}}else S=function(){g(z,0)};function R(e){x=e,E||(E=!0,S())}function M(n,t){C=g((function(){n(e.unstable_now())}),t)}e.unstable_IdlePriority=5,e.unstable_ImmediatePriority=1,e.unstable_LowPriority=4,e.unstable_NormalPriority=3,e.unstable_Profiling=null,e.unstable_UserBlockingPriority=2,e.unstable_cancelCallback=function(e){e.callback=null},e.unstable_continueExecution=function(){m||p||(m=!0,R(w))},e.unstable_forceFrameRate=function(e){0>e||125<e?console.error("forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported"):_=0<e?Math.floor(1e3/e):5},e.unstable_getCurrentPriorityLevel=function(){return d},e.unstable_getFirstCallbackNode=function(){return t(i)},e.unstable_next=function(e){switch(d){case 1:case 2:case 3:var n=3;break;default:n=d}var t=d;d=n;try{return e()}finally{d=t}},e.unstable_pauseExecution=function(){},e.unstable_requestPaint=function(){},e.unstable_runWithPriority=function(e,n){switch(e){case 1:case 2:case 3:case 4:case 5:break;default:e=3}var t=d;d=e;try{return n()}finally{d=t}},e.unstable_scheduleCallback=function(r,l,a){var o=e.unstable_now();switch("object"==typeof a&&null!==a?a="number"==typeof(a=a.delay)&&0<a?o+a:o:a=o,r){case 1:var u=-1;break;case 2:u=250;break;case 5:u=1073741823;break;case 4:u=1e4;break;default:u=5e3}return r={id:c++,callback:l,priorityLevel:r,startTime:a,expirationTime:u=a+u,sortIndex:-1},a>o?(r.sortIndex=a,n(s,r),null===t(i)&&r===t(s)&&(h?(v(C),C=-1):h=!0,M(k,a-o))):(r.sortIndex=u,n(i,r),m||p||(m=!0,R(w))),r},e.unstable_shouldYield=N,e.unstable_wrapCallback=function(e){var n=d;return function(){var t=d;d=n;try{return e.apply(this,arguments)}finally{d=t}}}}(A),V.exports=A;
/**
* @license React
* react-dom.production.min.js
*
* Copyright (c) Facebook, Inc. and its affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/
var $=n.exports,j=V.exports;function B(e){for(var n="https://reactjs.org/docs/error-decoder.html?invariant="+e,t=1;t<arguments.length;t++)n+="&args[]="+encodeURIComponent(arguments[t]);return"Minified React error #"+e+"; visit "+n+" for the full message or use the non-minified dev environment for full errors and additional helpful warnings."}var H=new Set,W={};function Q(e,n){q(e,n),q(e+"Capture",n)}function q(e,n){for(W[e]=n,e=0;e<n.length;e++)H.add(n[e])}var K=!("undefined"==typeof window||void 0===window.document||void 0===window.document.createElement),Y=Object.prototype.hasOwnProperty,X=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,G={},Z={};function J(e,n,t,r,l,a,o){this.acceptsBooleans=2===n||3===n||4===n,this.attributeName=r,this.attributeNamespace=l,this.mustUseProperty=t,this.propertyName=e,this.type=n,this.sanitizeURL=a,this.removeEmptyString=o}var ee={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach((function(e){ee[e]=new J(e,0,!1,e,null,!1,!1)})),[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach((function(e){var n=e[0];ee[n]=new J(n,1,!1,e[1],null,!1,!1)})),["contentEditable","draggable","spellCheck","value"].forEach((function(e){ee[e]=new J(e,2,!1,e.toLowerCase(),null,!1,!1)})),["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach((function(e){ee[e]=new J(e,2,!1,e,null,!1,!1)})),"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach((function(e){ee[e]=new J(e,3,!1,e.toLowerCase(),null,!1,!1)})),["checked","multiple","muted","selected"].forEach((function(e){ee[e]=new J(e,3,!0,e,null,!1,!1)})),["capture","download"].forEach((function(e){ee[e]=new J(e,4,!1,e,null,!1,!1)})),["cols","rows","size","span"].forEach((function(e){ee[e]=new J(e,6,!1,e,null,!1,!1)})),["rowSpan","start"].forEach((function(e){ee[e]=new J(e,5,!1,e.toLowerCase(),null,!1,!1)}));var ne=/[\-:]([a-z])/g;function te(e){return e[1].toUpperCase()}function re(e,n,t,r){var l=ee.hasOwnProperty(n)?ee[n]:null;(null!==l?0!==l.type:r||!(2<n.length)||"o"!==n[0]&&"O"!==n[0]||"n"!==n[1]&&"N"!==n[1])&&(function(e,n,t,r){if(null==n||function(e,n,t,r){if(null!==t&&0===t.type)return!1;switch(typeof n){case"function":case"symbol":return!0;case"boolean":return!r&&(null!==t?!t.acceptsBooleans:"data-"!==(e=e.toLowerCase().slice(0,5))&&"aria-"!==e);default:return!1}}(e,n,t,r))return!0;if(r)return!1;if(null!==t)switch(t.type){case 3:return!n;case 4:return!1===n;case 5:return isNaN(n);case 6:return isNaN(n)||1>n}return!1}(n,t,l,r)&&(t=null),r||null===l?function(e){return!!Y.call(Z,e)||!Y.call(G,e)&&(X.test(e)?Z[e]=!0:(G[e]=!0,!1))}(n)&&(null===t?e.removeAttribute(n):e.setAttribute(n,""+t)):l.mustUseProperty?e[l.propertyName]=null===t?3!==l.type&&"":t:(n=l.attributeName,r=l.attributeNamespace,null===t?e.removeAttribute(n):(t=3===(l=l.type)||4===l&&!0===t?"":""+t,r?e.setAttributeNS(r,n,t):e.setAttribute(n,t))))}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach((function(e){var n=e.replace(ne,te);ee[n]=new J(n,1,!1,e,null,!1,!1)})),"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach((function(e){var n=e.replace(ne,te);ee[n]=new J(n,1,!1,e,"http://www.w3.org/1999/xlink",!1,!1)})),["xml:base","xml:lang","xml:space"].forEach((function(e){var n=e.replace(ne,te);ee[n]=new J(n,1,!1,e,"http://www.w3.org Line truncated
+100
View File
@@ -0,0 +1,100 @@
'use strict';
import React, {useState} from "react";
import * as ReactDOM from "react-dom/client";
function init() {
const wrapper = document.querySelector('#screen');
const root = ReactDOM.createRoot(wrapper);
const html = (<SyncScreen/>);
root.render(html);
}
function SyncScreen() {
const [loading, setLoading] = useState(null);
const [error, setError] = useState(null);
return <>
<section className="container py-5">
<h1 style={{marginBottom: '2rem'}}>Oops... Block not in sync.</h1>
{error && <p className="alert alert-danger">{error}</p>}
{loading ?
<>
{loading === 'syncing' &&
<p>Version upgrade in progress...</p>
}
<p>Please wait...</p>
</>
:
<>
<p>Your version of the block is not in sync with the cloud (not latest version).<br/>
Would you like to update it?</p>
<div className="options">
<button className="btn btn-primary" style={{marginRight: '0.5rem'}} onClick={runSyncLogic}>Yes, Update to
Latest
</button>
<button className="btn btn-secondary" onClick={ignoreVersionSync}>Ignore</button>
</div>
</>
}
</section>
</>
async function ignoreVersionSync() {
setLoading(true);
let data = {};
try {
const response = await fetch('/sync', {
method: 'POST',
body: JSON.stringify({ignore: true}),
headers: {
'Content-Type': 'application/json'
}
});
data = await response.json();
} catch (err) {
setError('Error: ' + err.message);
setLoading(false);
return;
}
if (data.status !== 200) {
setError(data.message);
setLoading(false);
return;
}
setTimeout(() => window.location.reload(), 1000);
}
async function runSyncLogic() {
setLoading('syncing');
let data = {};
try {
const response = await fetch('/sync', {method: 'POST'});
data = await response.json();
} catch (err) {
setError('Error: ' + err.message);
setLoading(false);
return;
}
if (data.status !== 200) {
setError(data.message);
setLoading(false);
return;
}
setTimeout(() => window.location.reload(), 1000);
}
}
init();
+18
View File
@@ -0,0 +1,18 @@
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Block Development Tool</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-4bw+/aepP/YC94hEpVNVgiZdgIC5+VKNBQNGCHeKRQN+PtmoHDEXuppvnDJzQIu9" crossorigin="anonymous">
</head>
<body>
<div id="screen">Loading...</div>
<script src="/socket.io/socket.io.js"></script>
<script src="/scripts/dist/sync.min.js"></script>
</body>
</html>
+100 -11
View File
@@ -9,8 +9,10 @@
"version": "1.0.28",
"license": "ISC",
"dependencies": {
"@axe-web/create-block": "^1.1.30",
"@braintree/sanitize-url": "^6.0.0",
"archiver": "^5.3.1",
"body-parser": "^1.20.2",
"browser-sync": "^2.27.9",
"config": "^3.3.7",
"escape-html": "^1.0.3",
@@ -75,6 +77,33 @@
"node": ">=6.0.0"
}
},
"node_modules/@axe-web/create-block": {
"version": "1.1.30",
"resolved": "https://registry.npmjs.org/@axe-web/create-block/-/create-block-1.1.30.tgz",
"integrity": "sha512-jTlr2b1ZBo3ArFshbTlK+ohed3cqWPfwCTAd58nTnWVTlIdPx14Eu+QvbPPqrdTWPw0gLuYUEmdd5OaE95GT1A==",
"dependencies": {
"commander": "^9.4.1",
"dotenv": "^16.0.3",
"mem-fs": "^2.2.1",
"mem-fs-editor": "^9.5.0",
"node-fetch": "^3.2.10",
"node-stream-zip": "^1.15.0"
},
"bin": {
"create-block": "create-block.js"
},
"engines": {
"node": ">=14.17.3"
}
},
"node_modules/@axe-web/create-block/node_modules/commander": {
"version": "9.5.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz",
"integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==",
"engines": {
"node": "^12.20.0 || >=14"
}
},
"node_modules/@babel/code-frame": {
"version": "7.18.6",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz",
@@ -1638,12 +1667,12 @@
}
},
"node_modules/body-parser": {
"version": "1.20.1",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
"integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==",
"version": "1.20.2",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
"integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
"dependencies": {
"bytes": "3.1.2",
"content-type": "~1.0.4",
"content-type": "~1.0.5",
"debug": "2.6.9",
"depd": "2.0.0",
"destroy": "1.2.0",
@@ -1651,7 +1680,7 @@
"iconv-lite": "0.4.24",
"on-finished": "2.4.1",
"qs": "6.11.0",
"raw-body": "2.5.1",
"raw-body": "2.5.2",
"type-is": "~1.6.18",
"unpipe": "1.0.0"
},
@@ -2449,9 +2478,9 @@
}
},
"node_modules/content-type": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
"integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
"engines": {
"node": ">= 0.6"
}
@@ -2917,6 +2946,17 @@
"url": "https://github.com/fb55/domutils?sponsor=1"
}
},
"node_modules/dotenv": {
"version": "16.3.1",
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz",
"integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/motdotla/dotenv?sponsor=1"
}
},
"node_modules/duplexify": {
"version": "3.7.1",
"resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz",
@@ -3506,6 +3546,29 @@
"node": ">=10"
}
},
"node_modules/express/node_modules/body-parser": {
"version": "1.20.1",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz",
"integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==",
"dependencies": {
"bytes": "3.1.2",
"content-type": "~1.0.4",
"debug": "2.6.9",
"depd": "2.0.0",
"destroy": "1.2.0",
"http-errors": "2.0.0",
"iconv-lite": "0.4.24",
"on-finished": "2.4.1",
"qs": "6.11.0",
"raw-body": "2.5.1",
"type-is": "~1.6.18",
"unpipe": "1.0.0"
},
"engines": {
"node": ">= 0.8",
"npm": "1.2.8000 || >= 1.4.16"
}
},
"node_modules/express/node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
@@ -3561,6 +3624,20 @@
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/express/node_modules/raw-body": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
"integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
"dependencies": {
"bytes": "3.1.2",
"http-errors": "2.0.0",
"iconv-lite": "0.4.24",
"unpipe": "1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/express/node_modules/send": {
"version": "0.18.0",
"resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
@@ -7193,6 +7270,18 @@
"integrity": "sha512-PiVXnNuFm5+iYkLBNeq5211hvO38y63T0i2KKh2KnUs3RpzJ+JtODFjkD8yjLwnDkTYF1eKXheUwdssR+NRZdg==",
"peer": true
},
"node_modules/node-stream-zip": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/node-stream-zip/-/node-stream-zip-1.15.0.tgz",
"integrity": "sha512-LN4fydt9TqhZhThkZIVQnF9cwjU3qmUH9h78Mx/K7d3VvfRqqwthLwJEUOEL0QPZ0XQmNN7be5Ggit5+4dq3Bw==",
"engines": {
"node": ">=0.12.0"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/antelle"
}
},
"node_modules/normalize-package-data": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
@@ -8010,9 +8099,9 @@
}
},
"node_modules/raw-body": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz",
"integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==",
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
"integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
"dependencies": {
"bytes": "3.1.2",
"http-errors": "2.0.0",
+6 -4
View File
@@ -7,10 +7,10 @@
"url": "https://axe-web.com/"
},
"scripts": {
"info": "NODE_ENV=development BLOCK_NAME=swiper-test MODULE_PATH= node debug.js",
"dev": "NODE_ENV=development BLOCK_NAME=swiper-test MODULE_PATH= node server.js",
"build-platform": "NODE_ENV=development BLOCK_NAME=swiper-test MODULE_PATH= node ./build.js",
"dev-dev-tool": "NODE_ENV=development rollup --config rollup.config.js --watch",
"info": "BLOCK_NAME=timeline-scroll MODULE_PATH= node debug.js",
"dev": "BLOCK_NAME=timeline-scroll MODULE_PATH= node server.js",
"build-platform": "BLOCK_NAME=timeline-scroll MODULE_PATH= node ./build.js",
"dev-dev-tool": "rollup --config rollup.config.js --watch",
"build-dev-tool": "rollup --config rollup.config.js"
},
"engines": {
@@ -19,8 +19,10 @@
"license": "ISC",
"type": "module",
"dependencies": {
"@axe-web/create-block": "^1.1.30",
"@braintree/sanitize-url": "^6.0.0",
"archiver": "^5.3.1",
"body-parser": "^1.20.2",
"browser-sync": "^2.27.9",
"config": "^3.3.7",
"escape-html": "^1.0.3",
+22
View File
@@ -47,4 +47,26 @@ export default [{
commonjs(),
!devMode && terser()
]
}, {
input: 'layouts/scripts/sync.jsx',
output: {
file: 'layouts/scripts/dist/sync.min.js',
sourcemap: devMode
},
plugins: [
nodeResolve({
extensions: [".js"],
}),
replace({
'process.env.NODE_ENV': JSON.stringify('production'),
preventAssignment: true,
}),
babel({
compact: false,
babelHelpers: 'bundled',
presets: ["@babel/preset-react"],
}),
commonjs(),
!devMode && terser()
]
}];
+78 -25
View File
@@ -31,12 +31,15 @@ import {
removeCommentsFromJs,
replaceNames,
uploadFile,
verifyVersion,
zipProject
} from "./helpers.js";
import PluginError from 'plugin-error';
import {Server} from "socket.io";
import {createServer} from 'http';
import {authtoken, connect} from "ngrok";
import {exec} from "child_process";
import bodyParser from "body-parser";
/**
* Constants
@@ -57,12 +60,21 @@ let port = 3000; // This variable is used in `*.hbs` and it will be updated once
let previewFrameUrl = `/`; // This variable is used in `*.hbs` and it will be updated once BrowserSync is ready.
let shareUrl = '';
const sessions = [];
let ignoreVersionSync = false;
let bs;
/**
* Init server
*/
const app = express();
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({extended: false}))
// parse application/json
app.use(bodyParser.json())
const httpServer = createServer(app);
initSessionsServer(httpServer);
@@ -91,7 +103,7 @@ app.set('views', path.join(modulesPath, 'layouts'));
// Routes
//
app.get('/', (req, res) => {
app.get('/', async (req, res, next) => {
const data = getBlockConfigs({modulesPath, dataFiles});
if (data.error && data.errorMessage) {
return res.send(data.errorMessage);
@@ -104,17 +116,29 @@ app.get('/', (req, res) => {
include_partial: (filesPath) => handlebarLayoutsPath(modulesPath, filesPath),
}
try {
const verifiedVersion = await verifyVersion(projectPath, blocksRegistry);
if (!verifiedVersion && !ignoreVersionSync) {
return res.render('sync', data);
}
} catch (err) {
const errorMessage = "Can't verify block version.";
console.log(errorMessage, err);
return next(new Error(errorMessage));
}
data.baseView = baseView;
data.port = `/${baseViewUrl}`;
data.previewFrameUrl = `${previewFrameUrl}/${baseViewUrl}`;
data.shareUrl = shareUrl;
if (req.headers.referer) {
// NGROK, public URL
data.shareUrl = undefined; // Link already shared.
data.previewFrameUrl = `/${baseViewUrl}`;
data.publicUrl = true;
}
// TODO: Need to review this logic, conflicts with the browsersync work after "/sync" action.
// if (req.headers.referer) {
// // NGROK, public URL
// data.shareUrl = undefined; // Link already shared.
// data.previewFrameUrl = `/${baseViewUrl}`;
// data.publicUrl = true;
// }
res.render('index', data);
});
@@ -131,23 +155,6 @@ app.get('/view/:baseView', (req, res) => {
res.render(baseView, data)
});
function getDataOfFrame(isIframe = false) {
const data = {config: getBlockConfigs({modulesPath, dataFiles})};
if (data.error && data.errorMessage) {
return data;
}
data.helpers = {
include_partial: (filesPath) => handlebarLayoutsPath(modulesPath, filesPath),
}
if (isIframe) {
data.iframeMode = true;
}
return data;
}
app.get('/publish', async (req, res) => {
const data = await readJSONFile(path.join(projectPath, `block.json`));
@@ -276,6 +283,34 @@ app.get('/data', async (req, res) => {
});
});
app.post('/sync', async (req, res) => {
const blockJson = await readJSONFile(path.join(projectPath, `block.json`));
const blockName = blockJson.name.startsWith('@') ? blockJson.name : `@${blockJson.name}`;
if (req.body['ignore']) {
ignoreVersionSync = true;
res.json({status: 200, message: 'Version upgrade is ignored.'});
return;
}
bs.pause();
// Looks like it takes time to pause the browser-sync server, so delay(setTimeout) is necessary.
setTimeout(() => {
exec(`node ./node_modules/@axe-web/create-block/create-block.js sync --source ${blockName}`, (err, stdout, stderr) => {
if (err || stderr) {
console.error('Error:', err || stderr);
res.status(500).json({status: 500, message: err || stderr});
}
console.log(stdout);
bs.resume();
res.json({status: 200, message: 'Successfully synced!'});
});
})
});
// Errors handler
app.use(handleSyntaxErrors);
@@ -320,6 +355,23 @@ function getListOfDesignPreviewFiles(jsonDataFileName, previewFiles) {
});
}
function getDataOfFrame(isIframe = false) {
const data = {config: getBlockConfigs({modulesPath, dataFiles})};
if (data.error && data.errorMessage) {
return data;
}
data.helpers = {
include_partial: (filesPath) => handlebarLayoutsPath(modulesPath, filesPath),
}
if (isIframe) {
data.iframeMode = true;
}
return data;
}
function startBrowserSync() {
return new Promise((resolve, reject) => {
const listener = httpServer.listen(0, async () => {
@@ -327,7 +379,8 @@ function startBrowserSync() {
console.log(`The web server has started on port ${PORT}`);
const bs = browserSync.create();
// BS is global variable.
bs = browserSync.create();
const files = getJSBundleFiles();
gulp.watch(files, {delay: 400}, gulp.series(['build-script-files', function (cb) {