├── .gitignore ├── LICENSE ├── README.md ├── arch.png ├── build └── main.min.js ├── code └── index.js ├── index.html ├── package-lock.json ├── package.json ├── shot.png └── src ├── app.js └── ws.js /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Prakhar Srivastav 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # When FC meets websocket... 2 | 3 | Develop an instant co-editor with ONLY [133 lines of code](code/index.js). Serverless, free-tier, pay-as-your-usage, and... Did we mention it also scales? 4 | 5 | Powered by Aliyun [FunctionCompute](https://www.aliyun.com/product/fc) & [ApiGateway](https://www.aliyun.com/product/apigateway) 6 | 7 | ![img](shot.png) 8 | 9 | Demo - http://fc-public.oss-cn-hangzhou.aliyuncs.com/demo/co-edit/index.html?id=fc 10 | 11 | ### Architecture 12 | 13 | ![img](arch.png) 14 | 15 | ### Run 16 | 17 | ``` 18 | $ npm install 19 | $ npm run dist 20 | $ open index.html 21 | ``` 22 | 23 | ### Dev 24 | 25 | ``` 26 | $ npm install 27 | $ npm run watch 28 | ``` 29 | 30 | ### TODO 31 | 32 | - [ ] responsive page for mobile 33 | -------------------------------------------------------------------------------- /arch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-fc/fc-websocket/f852bf8aadbcccad5897ea4ea1368fcb04b2272a/arch.png -------------------------------------------------------------------------------- /build/main.min.js: -------------------------------------------------------------------------------- 1 | !function e(t,n,r){function o(i,s){if(!n[i]){if(!t[i]){var u="function"==typeof require&&require;if(!s&&u)return u(i,!0);if(a)return a(i,!0);var c=new Error("Cannot find module '"+i+"'");throw c.code="MODULE_NOT_FOUND",c}var l=n[i]={exports:{}};t[i][0].call(l.exports,function(e){var n=t[i][1][e];return o(n||e)},l,l.exports,e,t,n,r)}return n[i].exports}for(var a="function"==typeof require&&require,i=0;i=200&&e<300}};s.headers={common:{Accept:"application/json, text/plain, */*"}},o.forEach(["delete","get","head"],function(e){s.headers[e]={}}),o.forEach(["post","put","patch"],function(e){s.headers[e]=o.merge(i)}),t.exports=s}).call(this,e("_process"))},{"./adapters/http":2,"./adapters/xhr":2,"./helpers/normalizeHeaderName":22,"./utils":25,_process:29}],15:[function(e,t,n){"use strict";t.exports=function(e,t){return function(){for(var n=new Array(arguments.length),r=0;r>8-s%1*8)){if((n=o.charCodeAt(s+=.75))>255)throw new r;t=t<<8|n}return i}var a="ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";r.prototype=new Error,r.prototype.code=5,r.prototype.name="InvalidCharacterError",t.exports=o},{}],17:[function(e,t,n){"use strict";function r(e){return encodeURIComponent(e).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+").replace(/%5B/gi,"[").replace(/%5D/gi,"]")}var o=e("./../utils");t.exports=function(e,t,n){if(!t)return e;var a;if(n)a=n(t);else if(o.isURLSearchParams(t))a=t.toString();else{var i=[];o.forEach(t,function(e,t){null!==e&&void 0!==e&&(o.isArray(e)&&(t+="[]"),o.isArray(e)||(e=[e]),o.forEach(e,function(e){o.isDate(e)?e=e.toISOString():o.isObject(e)&&(e=JSON.stringify(e)),i.push(r(t)+"="+r(e))}))}),a=i.join("&")}return a&&(e+=(-1===e.indexOf("?")?"?":"&")+a),e}},{"./../utils":25}],18:[function(e,t,n){"use strict";t.exports=function(e,t){return t?e.replace(/\/+$/,"")+"/"+t.replace(/^\/+/,""):e}},{}],19:[function(e,t,n){"use strict";var r=e("./../utils");t.exports=r.isStandardBrowserEnv()?function(){return{write:function(e,t,n,o,a,i){var s=[];s.push(e+"="+encodeURIComponent(t)),r.isNumber(n)&&s.push("expires="+new Date(n).toGMTString()),r.isString(o)&&s.push("path="+o),r.isString(a)&&s.push("domain="+a),!0===i&&s.push("secure"),document.cookie=s.join("; ")},read:function(e){var t=document.cookie.match(new RegExp("(^|;\\s*)("+e+")=([^;]*)"));return t?decodeURIComponent(t[3]):null},remove:function(e){this.write(e,"",Date.now()-864e5)}}}():function(){return{write:function(){},read:function(){return null},remove:function(){}}}()},{"./../utils":25}],20:[function(e,t,n){"use strict";t.exports=function(e){return/^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(e)}},{}],21:[function(e,t,n){"use strict";var r=e("./../utils");t.exports=r.isStandardBrowserEnv()?function(){function e(e){var t=e;return n&&(o.setAttribute("href",t),t=o.href),o.setAttribute("href",t),{href:o.href,protocol:o.protocol?o.protocol.replace(/:$/,""):"",host:o.host,search:o.search?o.search.replace(/^\?/,""):"",hash:o.hash?o.hash.replace(/^#/,""):"",hostname:o.hostname,port:o.port,pathname:"/"===o.pathname.charAt(0)?o.pathname:"/"+o.pathname}}var t,n=/(msie|trident)/i.test(navigator.userAgent),o=document.createElement("a");return t=e(window.location.href),function(n){var o=r.isString(n)?e(n):n;return o.protocol===t.protocol&&o.host===t.host}}():function(){return function(){return!0}}()},{"./../utils":25}],22:[function(e,t,n){"use strict";var r=e("../utils");t.exports=function(e,t){r.forEach(e,function(n,r){r!==t&&r.toUpperCase()===t.toUpperCase()&&(e[t]=n,delete e[r])})}},{"../utils":25}],23:[function(e,t,n){"use strict";var r=e("./../utils");t.exports=function(e){var t,n,o,a={};return e?(r.forEach(e.split("\n"),function(e){o=e.indexOf(":"),t=r.trim(e.substr(0,o)).toLowerCase(),n=r.trim(e.substr(o+1)),t&&(a[t]=a[t]?a[t]+", "+n:n)}),a):a}},{"./../utils":25}],24:[function(e,t,n){"use strict";t.exports=function(e){return function(t){return e.apply(null,t)}}},{}],25:[function(e,t,n){"use strict";function r(e){return"[object Array]"===M.call(e)}function o(e){return"[object ArrayBuffer]"===M.call(e)}function a(e){return"undefined"!=typeof FormData&&e instanceof FormData}function i(e){return"undefined"!=typeof ArrayBuffer&&ArrayBuffer.isView?ArrayBuffer.isView(e):e&&e.buffer&&e.buffer instanceof ArrayBuffer}function s(e){return"string"==typeof e}function u(e){return"number"==typeof e}function c(e){return void 0===e}function l(e){return null!==e&&"object"==typeof e}function p(e){return"[object Date]"===M.call(e)}function d(e){return"[object File]"===M.call(e)}function f(e){return"[object Blob]"===M.call(e)}function h(e){return"[object Function]"===M.call(e)}function m(e){return l(e)&&h(e.pipe)}function v(e){return"undefined"!=typeof URLSearchParams&&e instanceof URLSearchParams}function g(e){return e.replace(/^\s*/,"").replace(/\s*$/,"")}function y(){return("undefined"==typeof navigator||"ReactNative"!==navigator.product)&&("undefined"!=typeof window&&"undefined"!=typeof document)}function E(e,t){if(null!==e&&void 0!==e)if("object"==typeof e||r(e)||(e=[e]),r(e))for(var n=0,o=e.length;n8&&b<=11),O=32,w=String.fromCharCode(O),D=d.topLevelTypes,_={beforeInput:{phasedRegistrationNames:{bubbled:y({onBeforeInput:null}),captured:y({onBeforeInputCapture:null})},dependencies:[D.topCompositionEnd,D.topKeyPress,D.topTextInput,D.topPaste]},compositionEnd:{phasedRegistrationNames:{bubbled:y({onCompositionEnd:null}),captured:y({onCompositionEndCapture:null})},dependencies:[D.topBlur,D.topCompositionEnd,D.topKeyDown,D.topKeyPress,D.topKeyUp,D.topMouseDown]},compositionStart:{phasedRegistrationNames:{bubbled:y({onCompositionStart:null}),captured:y({onCompositionStartCapture:null})},dependencies:[D.topBlur,D.topCompositionStart,D.topKeyDown,D.topKeyPress,D.topKeyUp,D.topMouseDown]},compositionUpdate:{phasedRegistrationNames:{bubbled:y({onCompositionUpdate:null}),captured:y({onCompositionUpdateCapture:null})},dependencies:[D.topBlur,D.topCompositionUpdate,D.topKeyDown,D.topKeyPress,D.topKeyUp,D.topMouseDown]}},I=!1,P=null,T={eventTypes:_,extractEvents:function(e,t,n,r){return[u(e,t,n,r),p(e,t,n,r)]}};t.exports=T},{"./EventConstants":44,"./EventPropagators":49,"./ExecutionEnvironment":50,"./FallbackCompositionState":51,"./SyntheticCompositionEvent":123,"./SyntheticInputEvent":127,"./keyOf":171}],33:[function(e,t,n){"use strict";function r(e,t){return e+t.charAt(0).toUpperCase()+t.substring(1)}var o={boxFlex:!0,boxFlexGroup:!0,columnCount:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,strokeDashoffset:!0,strokeOpacity:!0,strokeWidth:!0},a=["Webkit","ms","Moz","O"];Object.keys(o).forEach(function(e){a.forEach(function(t){o[r(t,e)]=o[e]})});var i={background:{backgroundImage:!0,backgroundPosition:!0,backgroundRepeat:!0,backgroundColor:!0},border:{borderWidth:!0,borderStyle:!0,borderColor:!0},borderBottom:{borderBottomWidth:!0,borderBottomStyle:!0,borderBottomColor:!0},borderLeft:{borderLeftWidth:!0,borderLeftStyle:!0,borderLeftColor:!0},borderRight:{borderRightWidth:!0,borderRightStyle:!0,borderRightColor:!0},borderTop:{borderTopWidth:!0,borderTopStyle:!0,borderTopColor:!0},font:{fontStyle:!0,fontVariant:!0,fontWeight:!0,fontSize:!0,lineHeight:!0,fontFamily:!0}},s={isUnitlessNumber:o,shorthandPropertyExpansions:i};t.exports=s},{}],34:[function(e,t,n){"use strict";var r=e("./CSSProperty"),o=e("./ExecutionEnvironment"),a=(e("./camelizeStyleName"),e("./dangerousStyleValue")),i=e("./hyphenateStyleName"),s=e("./memoizeStringOnly"),u=(e("./warning"),s(function(e){return i(e)})),c="cssFloat";o.canUseDOM&&void 0===document.documentElement.style.cssFloat&&(c="styleFloat");var l={createMarkupForStyles:function(e){var t="";for(var n in e)if(e.hasOwnProperty(n)){var r=e[n];null!=r&&(t+=u(n)+":",t+=a(n,r)+";")}return t||null},setValueForStyles:function(e,t){var n=e.style;for(var o in t)if(t.hasOwnProperty(o)){var i=a(o,t[o]);if("float"===o&&(o=c),i)n[o]=i;else{var s=r.shorthandPropertyExpansions[o];if(s)for(var u in s)n[u]="";else n[o]=""}}}};t.exports=l},{"./CSSProperty":33,"./ExecutionEnvironment":50,"./camelizeStyleName":138,"./dangerousStyleValue":143,"./hyphenateStyleName":163,"./memoizeStringOnly":173,"./warning":184}],35:[function(e,t,n){"use strict";function r(){this._callbacks=null,this._contexts=null}var o=e("./PooledClass"),a=e("./Object.assign"),i=e("./invariant");a(r.prototype,{enqueue:function(e,t){this._callbacks=this._callbacks||[],this._contexts=this._contexts||[],this._callbacks.push(e),this._contexts.push(t)},notifyAll:function(){var e=this._callbacks,t=this._contexts;if(e){i(e.length===t.length),this._callbacks=null,this._contexts=null;for(var n=0,r=e.length;n8));var k=!1;R.canUseDOM&&(k=M("input")&&(!("documentMode"in document)||document.documentMode>9));var A={get:function(){return N.get.call(this)},set:function(e){T=""+e,N.set.call(this,e)}},U={eventTypes:_,extractEvents:function(e,t,n,o){var a,i;if(r(t)?S?a=u:i=c:O(t)?k?a=f:(a=m,i=h):v(t)&&(a=g),a){var s=a(e,t,n);if(s){var l=x.getPooled(_.change,s,o);return C.accumulateTwoPhaseDispatches(l),l}}i&&i(e,t,n)}};t.exports=U},{"./EventConstants":44,"./EventPluginHub":46,"./EventPropagators":49,"./ExecutionEnvironment":50,"./ReactUpdates":117,"./SyntheticEvent":125,"./isEventSupported":166,"./isTextInputElement":168,"./keyOf":171}],37:[function(e,t,n){"use strict";var r=0,o={createReactRootIndex:function(){return r++}};t.exports=o},{}],38:[function(e,t,n){"use strict";function r(e,t,n){e.insertBefore(t,e.childNodes[n]||null)}var o=e("./Danger"),a=e("./ReactMultiChildUpdateTypes"),i=e("./setTextContent"),s=e("./invariant"),u={dangerouslyReplaceNodeWithMarkup:o.dangerouslyReplaceNodeWithMarkup,updateTextContent:i,processUpdates:function(e,t){for(var n,u=null,c=null,l=0;l]+)/,l={dangerouslyRenderMarkup:function(e){u(o.canUseDOM);for(var t,n={},l=0;l-1),!c.plugins[n]){i(t.extractEvents),c.plugins[n]=t;var r=t.eventTypes;for(var a in r)i(o(r[a],t,a))}}}function o(e,t,n){i(!c.eventNameDispatchConfigs.hasOwnProperty(n)),c.eventNameDispatchConfigs[n]=e;var r=e.phasedRegistrationNames;if(r){for(var o in r)if(r.hasOwnProperty(o)){var s=r[o];a(s,t,n)}return!0}return!!e.registrationName&&(a(e.registrationName,t,n),!0)}function a(e,t,n){i(!c.registrationNameModules[e]),c.registrationNameModules[e]=t,c.registrationNameDependencies[e]=t.eventTypes[n].dependencies}var i=e("./invariant"),s=null,u={},c={plugins:[],eventNameDispatchConfigs:{},registrationNameModules:{},registrationNameDependencies:{},injectEventPluginOrder:function(e){i(!s),s=Array.prototype.slice.call(e),r()},injectEventPluginsByName:function(e){var t=!1;for(var n in e)if(e.hasOwnProperty(n)){var o=e[n];u.hasOwnProperty(n)&&u[n]===o||(i(!u[n]),u[n]=o,t=!0)}t&&r()},getPluginModuleForEvent:function(e){var t=e.dispatchConfig;if(t.registrationName)return c.registrationNameModules[t.registrationName]||null;for(var n in t.phasedRegistrationNames)if(t.phasedRegistrationNames.hasOwnProperty(n)){var r=c.registrationNameModules[t.phasedRegistrationNames[n]];if(r)return r}return null},_resetEventPlugins:function(){s=null;for(var e in u)u.hasOwnProperty(e)&&delete u[e];c.plugins.length=0;var t=c.eventNameDispatchConfigs;for(var n in t)t.hasOwnProperty(n)&&delete t[n];var r=c.registrationNameModules;for(var o in r)r.hasOwnProperty(o)&&delete r[o]}};t.exports=c},{"./invariant":165}],48:[function(e,t,n){"use strict";function r(e){return e===v.topMouseUp||e===v.topTouchEnd||e===v.topTouchCancel}function o(e){return e===v.topMouseMove||e===v.topTouchMove}function a(e){return e===v.topMouseDown||e===v.topTouchStart}function i(e,t){var n=e._dispatchListeners,r=e._dispatchIDs;if(Array.isArray(n))for(var o=0;o1?1-t:void 0;return this._fallbackText=o.slice(e,s),this._fallbackText}}),o.addPoolingTo(r),t.exports=r},{"./Object.assign":56,"./PooledClass":57,"./getTextContentAccessor":160}],52:[function(e,t,n){"use strict";var r,o=e("./DOMProperty"),a=e("./ExecutionEnvironment"),i=o.injection.MUST_USE_ATTRIBUTE,s=o.injection.MUST_USE_PROPERTY,u=o.injection.HAS_BOOLEAN_VALUE,c=o.injection.HAS_SIDE_EFFECTS,l=o.injection.HAS_NUMERIC_VALUE,p=o.injection.HAS_POSITIVE_NUMERIC_VALUE,d=o.injection.HAS_OVERLOADED_BOOLEAN_VALUE;if(a.canUseDOM){var f=document.implementation;r=f&&f.hasFeature&&f.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure","1.1")}var h={isCustomAttribute:RegExp.prototype.test.bind(/^(data|aria)-[a-z_][a-z\d_.\-]*$/),Properties:{accept:null,acceptCharset:null,accessKey:null,action:null,allowFullScreen:i|u,allowTransparency:i,alt:null,async:u,autoComplete:null,autoPlay:u,cellPadding:null,cellSpacing:null,charSet:i,checked:s|u,classID:i,className:r?i:s,cols:i|p,colSpan:null,content:null,contentEditable:null,contextMenu:i,controls:s|u,coords:null,crossOrigin:null,data:null,dateTime:i,defer:u,dir:null,disabled:i|u,download:d,draggable:null,encType:null,form:i,formAction:i,formEncType:i,formMethod:i,formNoValidate:u,formTarget:i,frameBorder:i,headers:null,height:i,hidden:i|u,high:null,href:null,hrefLang:null,htmlFor:null,httpEquiv:null,icon:null,id:s,label:null,lang:null,list:i,loop:s|u,low:null,manifest:i,marginHeight:null,marginWidth:null,max:null,maxLength:i,media:i,mediaGroup:null,method:null,min:null,multiple:s|u,muted:s|u,name:null,noValidate:u,open:u,optimum:null,pattern:null,placeholder:null,poster:null,preload:null,radioGroup:null,readOnly:s|u,rel:null,required:u,role:i,rows:i|p,rowSpan:null,sandbox:null,scope:null,scoped:u,scrolling:null,seamless:i|u,selected:s|u,shape:null,size:i|p,sizes:i,span:p,spellCheck:null,src:null,srcDoc:s,srcSet:i,start:l,step:null,style:null,tabIndex:null,target:null,title:null,type:null,useMap:null,value:s|c,width:i,wmode:i,autoCapitalize:null,autoCorrect:null,itemProp:i,itemScope:i|u,itemType:i,itemID:i,itemRef:i,property:null,unselectable:i},DOMAttributeNames:{acceptCharset:"accept-charset",className:"class",htmlFor:"for",httpEquiv:"http-equiv"},DOMPropertyNames:{autoCapitalize:"autocapitalize",autoComplete:"autocomplete",autoCorrect:"autocorrect",autoFocus:"autofocus",autoPlay:"autoplay",encType:"encoding",hrefLang:"hreflang",radioGroup:"radiogroup",spellCheck:"spellcheck",srcDoc:"srcdoc",srcSet:"srcset"}};t.exports=h},{"./DOMProperty":39,"./ExecutionEnvironment":50}],53:[function(e,t,n){"use strict";function r(e){c(null==e.props.checkedLink||null==e.props.valueLink)}function o(e){r(e),c(null==e.props.value&&null==e.props.onChange)}function a(e){r(e),c(null==e.props.checked&&null==e.props.onChange)}function i(e){this.props.valueLink.requestChange(e.target.value)}function s(e){this.props.checkedLink.requestChange(e.target.checked)}var u=e("./ReactPropTypes"),c=e("./invariant"),l={button:!0,checkbox:!0,image:!0,hidden:!0,radio:!0,reset:!0,submit:!0},p={Mixin:{propTypes:{value:function(e,t,n){return!e[t]||l[e.type]||e.onChange||e.readOnly||e.disabled?null:new Error("You provided a `value` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultValue`. Otherwise, set either `onChange` or `readOnly`.")},checked:function(e,t,n){return!e[t]||e.onChange||e.readOnly||e.disabled?null:new Error("You provided a `checked` prop to a form field without an `onChange` handler. This will render a read-only field. If the field should be mutable use `defaultChecked`. Otherwise, set either `onChange` or `readOnly`.")},onChange:u.func}},getValue:function(e){return e.props.valueLink?(o(e),e.props.valueLink.value):e.props.value},getChecked:function(e){return e.props.checkedLink?(a(e),e.props.checkedLink.value):e.props.checked},getOnChange:function(e){return e.props.valueLink?(o(e),i):e.props.checkedLink?(a(e),s):e.props.onChange}};t.exports=p},{"./ReactPropTypes":108,"./invariant":165}],54:[function(e,t,n){"use strict";function r(e){e.remove()}var o=e("./ReactBrowserEventEmitter"),a=e("./accumulateInto"),i=e("./forEachAccumulated"),s=e("./invariant"),u={trapBubbledEvent:function(e,t){s(this.isMounted());var n=this.getDOMNode();s(n);var r=o.trapBubbledEvent(e,t,n);this._localEventListeners=a(this._localEventListeners,r)},componentWillUnmount:function(){this._localEventListeners&&i(this._localEventListeners,r)}};t.exports=u},{"./ReactBrowserEventEmitter":60,"./accumulateInto":135,"./forEachAccumulated":150,"./invariant":165}],55:[function(e,t,n){"use strict";var r=e("./EventConstants"),o=e("./emptyFunction"),a=r.topLevelTypes,i={eventTypes:null,extractEvents:function(e,t,n,r){if(e===a.topTouchStart){var i=r.target;i&&!i.onclick&&(i.onclick=o)}}};t.exports=i},{"./EventConstants":44,"./emptyFunction":144}],56:[function(e,t,n){"use strict";function r(e,t){if(null==e)throw new TypeError("Object.assign target cannot be null or undefined");for(var n=Object(e),r=Object.prototype.hasOwnProperty,o=1;o";return this._createOpenTagMarkupAndPutListeners(t)+this._createContentMarkup(t,n)+o},_createOpenTagMarkupAndPutListeners:function(e){var t=this._currentElement.props,n="<"+this._tag;for(var r in t)if(t.hasOwnProperty(r)){var a=t[r];if(null!=a)if(R.hasOwnProperty(r))o(this._rootNodeID,r,a,e);else{r===x&&(a&&(a=this._previousStyleCopy=m({},t.style)),a=s.createMarkupForStyles(a));var i=c.createMarkupForProperty(r,a);i&&(n+=" "+i)}}return e.renderToStaticMarkup?n+">":n+" "+c.createMarkupForID(this._rootNodeID)+">"},_createContentMarkup:function(e,t){var n="";"listing"!==this._tag&&"pre"!==this._tag&&"textarea"!==this._tag||(n="\n");var r=this._currentElement.props,o=r.dangerouslySetInnerHTML;if(null!=o){if(null!=o.__html)return n+o.__html}else{var a=b[typeof r.children]?r.children:null,i=null!=a?null:r.children;if(null!=a)return n+v(a);if(null!=i){return n+this.mountChildren(i,e,t).join("")}}return n},receiveComponent:function(e,t,n){var r=this._currentElement;this._currentElement=e,this.updateComponent(t,r,e,n)},updateComponent:function(e,t,n,o){r(this._currentElement.props),this._updateDOMProperties(t.props,e),this._updateDOMChildren(t.props,e,o)},_updateDOMProperties:function(e,t){var n,r,a,i=this._currentElement.props;for(n in e)if(!i.hasOwnProperty(n)&&e.hasOwnProperty(n))if(n===x){var s=this._previousStyleCopy;for(r in s)s.hasOwnProperty(r)&&(a=a||{},a[r]="");this._previousStyleCopy=null}else R.hasOwnProperty(n)?E(this._rootNodeID,n):(u.isStandardName[n]||u.isCustomAttribute(n))&&O.deletePropertyByID(this._rootNodeID,n);for(n in i){var c=i[n],l=n===x?this._previousStyleCopy:e[n];if(i.hasOwnProperty(n)&&c!==l)if(n===x)if(c?c=this._previousStyleCopy=m({},c):this._previousStyleCopy=null,l){for(r in l)!l.hasOwnProperty(r)||c&&c.hasOwnProperty(r)||(a=a||{},a[r]="");for(r in c)c.hasOwnProperty(r)&&l[r]!==c[r]&&(a=a||{},a[r]=c[r])}else a=c;else R.hasOwnProperty(n)?o(this._rootNodeID,n,c,t):(u.isStandardName[n]||u.isCustomAttribute(n))&&O.updatePropertyByID(this._rootNodeID,n,c)}a&&O.updateStylesByID(this._rootNodeID,a)},_updateDOMChildren:function(e,t,n){var r=this._currentElement.props,o=b[typeof e.children]?e.children:null,a=b[typeof r.children]?r.children:null,i=e.dangerouslySetInnerHTML&&e.dangerouslySetInnerHTML.__html,s=r.dangerouslySetInnerHTML&&r.dangerouslySetInnerHTML.__html,u=null!=o?null:e.children,c=null!=a?null:r.children,l=null!=o||null!=i,p=null!=a||null!=s;null!=u&&null==c?this.updateChildren(null,t,n):l&&!p&&this.updateTextContent(""),null!=a?o!==a&&this.updateTextContent(""+a):null!=s?i!==s&&O.updateInnerHTMLByID(this._rootNodeID,s):null!=c&&this.updateChildren(c,t,n)},unmountComponent:function(){this.unmountChildren(),l.deleteAllListeners(this._rootNodeID),p.unmountIDFromEnvironment(this._rootNodeID),this._rootNodeID=null}},h.measureMethods(i,"ReactDOMComponent",{mountComponent:"mountComponent",updateComponent:"updateComponent"}),m(i.prototype,i.Mixin,f.Mixin),i.injection={injectIDOperations:function(e){i.BackendIDOperations=O=e}},t.exports=i},{"./CSSPropertyOperations":34,"./DOMProperty":39,"./DOMPropertyOperations":40,"./Object.assign":56,"./ReactBrowserEventEmitter":60,"./ReactComponentBrowserEnvironment":65,"./ReactMount":100,"./ReactMultiChild":101,"./ReactPerf":105,"./escapeTextContentForBrowser":146,"./invariant":165,"./isEventSupported":166,"./keyOf":171,"./warning":184}],73:[function(e,t,n){"use strict";var r=e("./EventConstants"),o=e("./LocalEventTrapMixin"),a=e("./ReactBrowserComponentMixin"),i=e("./ReactClass"),s=e("./ReactElement"),u=s.createFactory("form"),c=i.createClass({displayName:"ReactDOMForm",tagName:"FORM",mixins:[a,o],render:function(){return u(this.props)},componentDidMount:function(){this.trapBubbledEvent(r.topLevelTypes.topReset,"reset"),this.trapBubbledEvent(r.topLevelTypes.topSubmit,"submit")}});t.exports=c},{"./EventConstants":44,"./LocalEventTrapMixin":54,"./ReactBrowserComponentMixin":59,"./ReactClass":63,"./ReactElement":87}],74:[function(e,t,n){"use strict";var r=e("./CSSPropertyOperations"),o=e("./DOMChildrenOperations"),a=e("./DOMPropertyOperations"),i=e("./ReactMount"),s=e("./ReactPerf"),u=e("./invariant"),c=e("./setInnerHTML"),l={dangerouslySetInnerHTML:"`dangerouslySetInnerHTML` must be set using `updateInnerHTMLByID()`.",style:"`style` must be set using `updateStylesByID()`."},p={updatePropertyByID:function(e,t,n){var r=i.getNode(e);u(!l.hasOwnProperty(t)),null!=n?a.setValueForProperty(r,t,n):a.deleteValueForProperty(r,t)},deletePropertyByID:function(e,t,n){var r=i.getNode(e);u(!l.hasOwnProperty(t)),a.deleteValueForProperty(r,t,n)},updateStylesByID:function(e,t){var n=i.getNode(e);r.setValueForStyles(n,t)},updateInnerHTMLByID:function(e,t){var n=i.getNode(e);c(n,t)},updateTextContentByID:function(e,t){var n=i.getNode(e);o.updateTextContent(n,t)},dangerouslyReplaceNodeWithMarkupByID:function(e,t){var n=i.getNode(e);o.dangerouslyReplaceNodeWithMarkup(n,t)},dangerouslyProcessChildrenUpdates:function(e,t){for(var n=0;n must be an array if `multiple` is true.")}else if(Array.isArray(e[t]))return new Error("The `"+t+"` prop supplied to ',""],c=[1,"","
"],l=[3,"","
"],p=[1,"",""],d={"*":[1,"?
","
"],area:[1,"",""],col:[2,"","
"],legend:[1,"
","
"],param:[1,"",""],tr:[2,"","
"],optgroup:u,option:u,caption:c,colgroup:c,tbody:c,tfoot:c,thead:c,td:l,th:l,circle:p,clipPath:p,defs:p,ellipse:p,g:p,line:p,linearGradient:p,path:p,polygon:p,polyline:p,radialGradient:p,rect:p,stop:p,text:p};t.exports=r},{"./ExecutionEnvironment":50,"./invariant":165}],158:[function(e,t,n){"use strict";function r(e){for(;e&&e.firstChild;)e=e.firstChild;return e}function o(e){for(;e;){if(e.nextSibling)return e.nextSibling;e=e.parentNode}}function a(e,t){for(var n=r(e),a=0,i=0;n;){if(3===n.nodeType){if(i=a+n.textContent.length,a<=t&&i>=t)return{node:n,offset:t-a};a=i}n=r(o(n))}}t.exports=a},{}],159:[function(e,t,n){"use strict";function r(e){return e?e.nodeType===o?e.documentElement:e.firstChild:null}var o=9;t.exports=r},{}],160:[function(e,t,n){"use strict";function r(){return!a&&o.canUseDOM&&(a="textContent"in document.documentElement?"textContent":"innerText"),a}var o=e("./ExecutionEnvironment"),a=null;t.exports=r},{"./ExecutionEnvironment":50}],161:[function(e,t,n){"use strict";function r(e){return e===window?{x:window.pageXOffset||document.documentElement.scrollLeft,y:window.pageYOffset||document.documentElement.scrollTop}:{x:e.scrollLeft,y:e.scrollTop}}t.exports=r},{}],162:[function(e,t,n){function r(e){return e.replace(o,"-$1").toLowerCase()}var o=/([A-Z])/g;t.exports=r},{}],163:[function(e,t,n){"use strict";function r(e){return o(e).replace(a,"-ms-")}var o=e("./hyphenate"),a=/^ms-/;t.exports=r},{"./hyphenate":162}],164:[function(e,t,n){"use strict";function r(e){return"function"==typeof e&&void 0!==e.prototype&&"function"==typeof e.prototype.mountComponent&&"function"==typeof e.prototype.receiveComponent}function o(e,t){var n;if(null!==e&&!1!==e||(e=i.emptyElement),"object"==typeof e){var o=e;n=t===o.type&&"string"==typeof o.type?s.createInternalComponent(o):r(o.type)?new o.type(o):new l}else"string"==typeof e||"number"==typeof e?n=s.createInstanceForText(e):c(!1);return n.construct(e),n._mountIndex=0,n._mountImage=null,n}var a=e("./ReactCompositeComponent"),i=e("./ReactEmptyComponent"),s=e("./ReactNativeComponent"),u=e("./Object.assign"),c=e("./invariant"),l=(e("./warning"),function(){});u(l.prototype,a.Mixin,{_instantiateReactComponent:o}),t.exports=o},{"./Object.assign":56,"./ReactCompositeComponent":67,"./ReactEmptyComponent":89,"./ReactNativeComponent":103,"./invariant":165,"./warning":184}],165:[function(e,t,n){"use strict";var r=function(e,t,n,r,o,a,i,s){if(!e){var u;if(void 0===t)u=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var c=[n,r,o,a,i,s],l=0;u=new Error("Invariant Violation: "+t.replace(/%s/g,function(){return c[l++]}))}throw u.framesToPop=1,u}};t.exports=r},{}],166:[function(e,t,n){"use strict";function r(e,t){if(!a.canUseDOM||t&&!("addEventListener"in document))return!1;var n="on"+e,r=n in document;if(!r){var i=document.createElement("div");i.setAttribute(n,"return;"),r="function"==typeof i[n]}return!r&&o&&"wheel"===e&&(r=document.implementation.hasFeature("Events.wheel","3.0")),r}var o,a=e("./ExecutionEnvironment");a.canUseDOM&&(o=document.implementation&&document.implementation.hasFeature&&!0!==document.implementation.hasFeature("","")),t.exports=r},{"./ExecutionEnvironment":50}],167:[function(e,t,n){function r(e){return!(!e||!("function"==typeof Node?e instanceof Node:"object"==typeof e&&"number"==typeof e.nodeType&&"string"==typeof e.nodeName))}t.exports=r},{}],168:[function(e,t,n){"use strict";function r(e){return e&&("INPUT"===e.nodeName&&o[e.type]||"TEXTAREA"===e.nodeName)}var o={color:!0,date:!0,datetime:!0,"datetime-local":!0,email:!0,month:!0,number:!0,password:!0,range:!0,search:!0,tel:!0,text:!0,time:!0,url:!0,week:!0};t.exports=r},{}],169:[function(e,t,n){function r(e){return o(e)&&3==e.nodeType}var o=e("./isNode");t.exports=r},{"./isNode":167}],170:[function(e,t,n){"use strict";var r=e("./invariant"),o=function(e){var t,n={};r(e instanceof Object&&!Array.isArray(e));for(t in e)e.hasOwnProperty(t)&&(n[t]=t);return n};t.exports=o},{"./invariant":165}],171:[function(e,t,n){var r=function(e){var t;for(t in e)if(e.hasOwnProperty(t))return t;return null};t.exports=r},{}],172:[function(e,t,n){"use strict";function r(e,t,n){if(!e)return null;var r={};for(var a in e)o.call(e,a)&&(r[a]=t.call(n,e[a],a,e));return r}var o=Object.prototype.hasOwnProperty;t.exports=r},{}],173:[function(e,t,n){"use strict";function r(e){var t={};return function(n){return t.hasOwnProperty(n)||(t[n]=e.call(this,n)),t[n]}}t.exports=r},{}],174:[function(e,t,n){"use strict";function r(e){return a(o.isValidElement(e)),e}var o=e("./ReactElement"),a=e("./invariant");t.exports=r},{"./ReactElement":87,"./invariant":165}],175:[function(e,t,n){"use strict";var r,o=e("./ExecutionEnvironment");o.canUseDOM&&(r=window.performance||window.msPerformance||window.webkitPerformance),t.exports=r||{}},{"./ExecutionEnvironment":50}],176:[function(e,t,n){var r=e("./performance");r&&r.now||(r=Date);var o=r.now.bind(r);t.exports=o},{"./performance":175}],177:[function(e,t,n){"use strict";function r(e){return'"'+o(e)+'"'}var o=e("./escapeTextContentForBrowser");t.exports=r},{"./escapeTextContentForBrowser":146}],178:[function(e,t,n){"use strict";var r=e("./ExecutionEnvironment"),o=/^[ \r\n\t\f]/,a=/<(!--|link|noscript|meta|script|style)[ \r\n\t\f\/>]/,i=function(e,t){e.innerHTML=t};if("undefined"!=typeof MSApp&&MSApp.execUnsafeLocalFunction&&(i=function(e,t){MSApp.execUnsafeLocalFunction(function(){e.innerHTML=t})}),r.canUseDOM){var s=document.createElement("div");s.innerHTML=" ",""===s.innerHTML&&(i=function(e,t){if(e.parentNode&&e.parentNode.replaceChild(e,e),o.test(t)||"<"===t[0]&&a.test(t)){e.innerHTML="\ufeff"+t;var n=e.firstChild;1===n.data.length?e.removeChild(n):n.deleteData(0,1)}else e.innerHTML=t})}t.exports=i},{"./ExecutionEnvironment":50}],179:[function(e,t,n){"use strict";var r=e("./ExecutionEnvironment"),o=e("./escapeTextContentForBrowser"),a=e("./setInnerHTML"),i=function(e,t){e.textContent=t};r.canUseDOM&&("textContent"in document.documentElement||(i=function(e,t){a(e,o(t))})),t.exports=i},{"./ExecutionEnvironment":50,"./escapeTextContentForBrowser":146,"./setInnerHTML":178}],180:[function(e,t,n){"use strict";function r(e,t){if(e===t)return!0;var n;for(n in e)if(e.hasOwnProperty(n)&&(!t.hasOwnProperty(n)||e[n]!==t[n]))return!1;for(n in t)if(t.hasOwnProperty(n)&&!e.hasOwnProperty(n))return!1;return!0}t.exports=r},{}],181:[function(e,t,n){"use strict";function r(e,t){if(null!=e&&null!=t){var n=typeof e,r=typeof t;if("string"===n||"number"===n)return"string"===r||"number"===r;if("object"===r&&e.type===t.type&&e.key===t.key){var o=e._owner===t._owner;return o}}return!1}e("./warning");t.exports=r},{"./warning":184}],182:[function(e,t,n){function r(e){ 6 | var t=e.length;if(o(!Array.isArray(e)&&("object"==typeof e||"function"==typeof e)),o("number"==typeof t),o(0===t||t-1 in e),e.hasOwnProperty)try{return Array.prototype.slice.call(e)}catch(e){}for(var n=Array(t),r=0;r=3&&(r.depth=arguments[2]),arguments.length>=4&&(r.colors=arguments[3]),m(t)?r.showHidden=t:t&&n._extend(r,t),R(r.showHidden)&&(r.showHidden=!1),R(r.depth)&&(r.depth=2),R(r.colors)&&(r.colors=!1),R(r.customInspect)&&(r.customInspect=!0),r.colors&&(r.stylize=a),u(r,e,r.depth)}function a(e,t){var n=o.styles[t];return n?"["+o.colors[n][0]+"m"+e+"["+o.colors[n][1]+"m":e}function i(e,t){return e}function s(e){var t={};return e.forEach(function(e,n){t[e]=!0}),t}function u(e,t,r){if(e.customInspect&&t&&w(t.inspect)&&t.inspect!==n.inspect&&(!t.constructor||t.constructor.prototype!==t)){var o=t.inspect(r,e);return E(o)||(o=u(e,o,r)),o}var a=c(e,t);if(a)return a;var i=Object.keys(t),m=s(i);if(e.showHidden&&(i=Object.getOwnPropertyNames(t)),O(t)&&(i.indexOf("message")>=0||i.indexOf("description")>=0))return l(t);if(0===i.length){if(w(t)){var v=t.name?": "+t.name:"";return e.stylize("[Function"+v+"]","special")}if(b(t))return e.stylize(RegExp.prototype.toString.call(t),"regexp");if(M(t))return e.stylize(Date.prototype.toString.call(t),"date");if(O(t))return l(t)}var g="",y=!1,C=["{","}"];if(h(t)&&(y=!0,C=["[","]"]),w(t)){g=" [Function"+(t.name?": "+t.name:"")+"]"}if(b(t)&&(g=" "+RegExp.prototype.toString.call(t)),M(t)&&(g=" "+Date.prototype.toUTCString.call(t)),O(t)&&(g=" "+l(t)),0===i.length&&(!y||0==t.length))return C[0]+g+C[1];if(r<0)return b(t)?e.stylize(RegExp.prototype.toString.call(t),"regexp"):e.stylize("[Object]","special");e.seen.push(t);var R;return R=y?p(e,t,r,m,i):i.map(function(n){return d(e,t,r,m,n,y)}),e.seen.pop(),f(R,g,C)}function c(e,t){if(R(t))return e.stylize("undefined","undefined");if(E(t)){var n="'"+JSON.stringify(t).replace(/^"|"$/g,"").replace(/'/g,"\\'").replace(/\\"/g,'"')+"'";return e.stylize(n,"string")}return y(t)?e.stylize(""+t,"number"):m(t)?e.stylize(""+t,"boolean"):v(t)?e.stylize("null","null"):void 0}function l(e){return"["+Error.prototype.toString.call(e)+"]"}function p(e,t,n,r,o){for(var a=[],i=0,s=t.length;i-1&&(s=a?s.split("\n").map(function(e){return" "+e}).join("\n").substr(2):"\n"+s.split("\n").map(function(e){return" "+e}).join("\n"))):s=e.stylize("[Circular]","special")),R(i)){if(a&&o.match(/^\d+$/))return s;i=JSON.stringify(""+o),i.match(/^"([a-zA-Z_][a-zA-Z_0-9]*)"$/)?(i=i.substr(1,i.length-2),i=e.stylize(i,"name")):(i=i.replace(/'/g,"\\'").replace(/\\"/g,'"').replace(/(^"|"$)/g,"'"),i=e.stylize(i,"string"))}return i+": "+s}function f(e,t,n){var r=0;return e.reduce(function(e,t){return r++,t.indexOf("\n")>=0&&r++,e+t.replace(/\u001b\[\d\d?m/g,"").length+1},0)>60?n[0]+(""===t?"":t+"\n ")+" "+e.join(",\n ")+" "+n[1]:n[0]+t+" "+e.join(", ")+" "+n[1]}function h(e){return Array.isArray(e)}function m(e){return"boolean"==typeof e}function v(e){return null===e}function g(e){return null==e}function y(e){return"number"==typeof e}function E(e){return"string"==typeof e}function C(e){return"symbol"==typeof e}function R(e){return void 0===e}function b(e){return x(e)&&"[object RegExp]"===_(e)}function x(e){return"object"==typeof e&&null!==e}function M(e){return x(e)&&"[object Date]"===_(e)}function O(e){return x(e)&&("[object Error]"===_(e)||e instanceof Error)}function w(e){return"function"==typeof e}function D(e){return null===e||"boolean"==typeof e||"number"==typeof e||"string"==typeof e||"symbol"==typeof e||void 0===e}function _(e){return Object.prototype.toString.call(e)}function I(e){return e<10?"0"+e.toString(10):e.toString(10)}function P(){var e=new Date,t=[I(e.getHours()),I(e.getMinutes()),I(e.getSeconds())].join(":");return[e.getDate(),A[e.getMonth()],t].join(" ")}function T(e,t){return Object.prototype.hasOwnProperty.call(e,t)}var N=/%[sdj%]/g;n.format=function(e){if(!E(e)){for(var t=[],n=0;n=a)return e;switch(e){case"%s":return String(r[n++]);case"%d":return Number(r[n++]);case"%j":try{return JSON.stringify(r[n++])}catch(e){return"[Circular]"}default:return e}}),s=r[n];n>>((3&t)<<3)&255;return a}}},{}],193:[function(e,t,n){function r(e,t,n){var r=t&&n||0,l=t||[];e=e||{};var p=e.node||o,d=void 0!==e.clockseq?e.clockseq:a;if(null==p||null==d){var f=i();null==p&&(p=o=[1|f[0],f[1],f[2],f[3],f[4],f[5]]),null==d&&(d=a=16383&(f[6]<<8|f[7]))}var h=void 0!==e.msecs?e.msecs:(new Date).getTime(),m=void 0!==e.nsecs?e.nsecs:c+1,v=h-u+(m-c)/1e4;if(v<0&&void 0===e.clockseq&&(d=d+1&16383),(v<0||h>u)&&void 0===e.nsecs&&(m=0),m>=1e4)throw new Error("uuid.v1(): Can't create more than 10M uuids/sec");u=h,c=m,a=d,h+=122192928e5;var g=(1e4*(268435455&h)+m)%4294967296;l[r++]=g>>>24&255,l[r++]=g>>>16&255,l[r++]=g>>>8&255,l[r++]=255&g;var y=h/4294967296*1e4&268435455;l[r++]=y>>>8&255,l[r++]=255&y,l[r++]=y>>>24&15|16,l[r++]=y>>>16&255,l[r++]=d>>>8|128,l[r++]=255&d;for(var E=0;E<6;++E)l[r+E]=p[E];return t||s(l)}var o,a,i=e("./lib/rng"),s=e("./lib/bytesToUuid"),u=0,c=0;t.exports=r},{"./lib/bytesToUuid":191,"./lib/rng":192}],194:[function(e,t,n){function r(e,t,n){var r=t&&n||0;"string"==typeof e&&(t="binary"===e?new Array(16):null,e=null),e=e||{};var i=e.random||(e.rng||o)();if(i[6]=15&i[6]|64,i[8]=63&i[8]|128,t)for(var s=0;s<16;++s)t[r+s]=i[s];return t||a(i)}var o=e("./lib/rng"),a=e("./lib/bytesToUuid");t.exports=r},{"./lib/bytesToUuid":191,"./lib/rng":192}],195:[function(e,t,n){var r=e("react"),o=e("axios");const a=e("uuid"),i=e("query-string"),s=e("util"),u=e("./ws");var c="fc@aliyun $ ",l=null,p=null,d=r.createClass({displayName:"App",getInitialState:function(){return p=a.v4().replace(/-/g,"").substr(0,8),console.log("device id:",p),l=i.parse(i.extract(window.location.href)).id,console.log("doc id:",l),u(this,l,p,"dummy",function(){},function(){}),this.offset=0,this.cmds=[],{history:[],prompt:c}},clearHistory:function(){this.setState({history:[]})},execShellCommand:function(e){var t=this;t.setState({prompt:""}),t.offset=0,t.cmds.push(e);var n=s.format("%s?docId=%s&deviceId=%s","http://tl.mofangdegisn.cn/send",l,p);o.post(n,e,{headers:{"Content-Type":"application/octet-stream"}}).then(function(e){console.log(e),t.setState({prompt:c})}).catch(function(e){var n="";n=e.response?e.response.status+" "+e.response.statusText:e.toString(),t.addHistory(n),t.setState({prompt:c})})},showWelcomeMsg:function(){this.addHistory(p+", Welcome to FunctionCompute! Have fun!")},openLink:function(e){return function(){window.open(e,"_blank")}},componentDidMount:function(){var e=this.refs.term.getDOMNode();this.showWelcomeMsg(),e.focus()},componentDidUpdate:function(){var e=document.getElementById("holder");e.scrollTop=e.scrollHeight},handleInput:function(e){switch(e.key){case"Enter":var t=this.refs.term.getDOMNode().value;if(t.replace(/\s/g,"").length<1)return;if("clear"===t)return this.state.history=[],this.showWelcomeMsg(),this.clearInput(),this.offset=0,void(this.cmds.length=0);this.addHistory(this.state.prompt+" "+t),this.execShellCommand(t),this.clearInput();break;case"ArrowUp":return 0===this.offset&&(this.lastCmd=this.refs.term.getDOMNode().value),this.refs.term.getDOMNode().value=this.cmds[this.cmds.length-++this.offset]||this.cmds[(this.offset=this.cmds.length,0)]||this.lastCmd,!1;case"ArrowDown":return this.refs.term.getDOMNode().value=this.cmds[this.cmds.length- --this.offset]||(this.offset=0,this.lastCmd),!1}},clearInput:function(){this.refs.term.getDOMNode().value=""},addHistory:function(e){var t=this.state.history.slice(0);e instanceof Array?t.push.apply(t,e):t.push(e),this.setState({history:t})},handleClick:function(){this.refs.term.getDOMNode().focus()},render:function(){var e=this.state.history.map(function(e,t){return r.createElement("p",{key:t},e)});return r.createElement("div",{className:"input-area",onClick:this.handleClick},e,r.createElement("p",null,r.createElement("span",{className:"prompt"},this.state.prompt),r.createElement("input",{type:"text",onKeyDown:this.handleInput,ref:"term"})))}}),f=r.createFactory(d);r.render(f(),document.getElementById("app"))},{"./ws":196,axios:1,"query-string":30,react:185,util:189,uuid:190}],196:[function(e,t,n){"use strict";const r=e("uuid"),o=e("util");var a=function(e,t,n,a,i,s){const u=new WebSocket("ws://tl.mofangdegisn.cn:8080");var c=new Date,l={method:"GET",host:"tl.mofangdegisn.cn:8080",querys:{docId:t,userId:a},headers:{"x-ca-websocket_api_type":["REGISTER"],"x-ca-seq":["0"],"x-ca-nonce":[r.v4().toString()],date:[c.toUTCString()],"x-ca-timestamp":[c.getTime().toString()],CA_VERSION:["1"]},path:"/r",body:""};u.onopen=function(){console.log("open:"),u.send("RG#"+n)};var p=!1,d=!1,f=!1;u.onmessage=function(t){if(console.log("data:",t.data),t.data.startsWith("NF#")){var n=JSON.parse(t.data.substr(3));return e.addHistory(o.format("%s (%s) %s","fc@aliyun $ ",n.from,decodeURIComponent(n.message.toString()))),void e.setState({prompt:"fc@aliyun $ "})}if(!f&&t.data.startsWith("RO#"))return console.log("login successfully"),s(t.data.users),p||(p=!0,u.send(JSON.stringify(l))),f=!0,setInterval(function(){u.send("H1")},15e3),void setInterval(i,5e3);if(!d){d=!0;var n=JSON.parse(t.data);return n=JSON.parse(n.body),void s(n.users)}},u.onclose=function(e){console.log("ws closed:",e)}};t.exports=a},{util:189,uuid:190}]},{},[195]); 7 | -------------------------------------------------------------------------------- /code/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const BUCKET = ''; 4 | const WORK_DIR = 'fc-chat/'; 5 | const AG_NOTIFY_URL = ''; 6 | const AG_APP_KEY = ''; 7 | const AG_APP_SECRET = ''; 8 | 9 | var co = require('co'); 10 | var OSS = require('ali-oss'); 11 | var AG = require('aliyun-api-gateway').Client; 12 | 13 | exports.register = function(event, context, callback) { 14 | console.log('event: %s', event); 15 | var evt = JSON.parse(event); 16 | 17 | var deviceId = evt['headers']['x-ca-deviceid']; 18 | var docId = evt['queryParameters']['id']; 19 | var ossClient = getOSSClient(context); 20 | 21 | var resp = { 22 | 'isBase64Encoded': 'false', 23 | 'statusCode': '200', 24 | 'body': { 25 | 'deviceId': deviceId, 26 | 'docId': docId, 27 | }, 28 | }; 29 | 30 | co(function* () { 31 | var onlineUsers = yield getOnlineUsers(ossClient, docId); 32 | console.log('online users: %j', onlineUsers); 33 | onlineUsers[deviceId] = 'online'; 34 | yield setOnlineUsers(ossClient, docId, onlineUsers); 35 | console.log('set online users: %j', onlineUsers); 36 | 37 | callback(null, resp); 38 | }).catch(function(err) { 39 | console.error(err); 40 | callback(err); 41 | }); 42 | }; 43 | 44 | exports.send = function(event, context, callback) { 45 | console.log('event: %s', event); 46 | var evt = JSON.parse(event); 47 | 48 | var deviceId = evt['queryParameters']['deviceid']; 49 | var docId = evt['queryParameters']['id']; 50 | var message = evt['queryParameters']['msg']; 51 | var agClient = new AG(AG_APP_KEY, AG_APP_SECRET); 52 | var ossClient = getOSSClient(context); 53 | 54 | var resp = { 55 | 'isBase64Encoded': 'false', 56 | 'statusCode': '200', 57 | 'body': { 58 | 'deviceId': deviceId, 59 | 'docId': docId, 60 | }, 61 | }; 62 | 63 | co(function* () { 64 | var onlineUsers = yield getOnlineUsers(ossClient, docId); 65 | console.log('online users: %j', onlineUsers); 66 | 67 | var keys = Object.keys(onlineUsers); 68 | for (let i = 0; i < keys.length; i++) { 69 | if (keys[i] != deviceId) { 70 | var succ = yield notify(agClient, keys[i], deviceId, message); 71 | if (!succ) { 72 | delete onlineUsers[keys[i]]; 73 | } 74 | } 75 | } 76 | yield setOnlineUsers(ossClient, docId, onlineUsers); 77 | callback(null, resp); 78 | }).catch(function(err) { 79 | console.error(err); 80 | callback(err); 81 | }); 82 | }; 83 | 84 | var getOnlineUsers = function* (ossClient, docId) { 85 | var usersKey = WORK_DIR + docId + '.json'; 86 | var users = {}; 87 | try { 88 | var resp = yield ossClient.get(usersKey); 89 | return JSON.parse(resp.content.toString()); 90 | } catch (err) { 91 | // pass 92 | } 93 | 94 | return users; 95 | }; 96 | 97 | var setOnlineUsers = function* (ossClient, docId, users) { 98 | var usersKey = WORK_DIR + docId + '.json'; 99 | yield ossClient.put(usersKey, new Buffer(JSON.stringify(users))); 100 | }; 101 | 102 | var notify = function* (agClient, deviceId, from, message) { 103 | try { 104 | var r = yield agClient.post(AG_NOTIFY_URL, { 105 | data: { 106 | from: from, 107 | message: message, 108 | }, 109 | headers: { 110 | 'x-ca-deviceid': deviceId, 111 | }, 112 | }); 113 | 114 | console.log('notify resp: %j', r); 115 | } catch (err) { 116 | console.log('notify error: %j', err); 117 | return false; 118 | } 119 | return true; 120 | }; 121 | 122 | var getOSSClient = function(context) { 123 | return new OSS({ 124 | accessKeyId: context.credentials.accessKeyId, 125 | accessKeySecret: context.credentials.accessKeySecret, 126 | stsToken: context.credentials.securityToken, 127 | region: 'oss-'+context.region, 128 | internal: true, 129 | secure: true, 130 | bucket: BUCKET, 131 | }); 132 | }; 133 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | fc@aliyun $ 5 | 6 | 7 | 8 | 9 | 61 | 62 | 63 | 64 | Fork me on GitHub 65 | 66 |
67 | 68 | 69 | 70 | 71 | 72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "give-me-a-shell-web", 3 | "version": "1.0.0", 4 | "description": "Give me a shell, I can...", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "watch": "watchify -t reactify ./src/app.js -o ./build/main.min.js -v", 9 | "dist": "npm run remove-dist && npm run build-standalone", 10 | "remove-dist": "rm -f build/*.js", 11 | "build-standalone": "NODE_ENV=production browserify -t reactify ./src/app.js | uglifyjs -mc > build/main.min.js" 12 | }, 13 | "author": "", 14 | "license": "MIT", 15 | "dependencies": { 16 | "axios": "^0.16.2", 17 | "babelify": "^5.0.4", 18 | "browserify": "^9.0.3", 19 | "query-string": "^5.0.1", 20 | "react": "^0.13.1", 21 | "reactify": "^1.1.0", 22 | "uglify-js": "^2.4.20", 23 | "underscore": "^1.8.3", 24 | "uuid": "^3.2.1", 25 | "watchify": "^3.1.0" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /shot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/awesome-fc/fc-websocket/f852bf8aadbcccad5897ea4ea1368fcb04b2272a/shot.png -------------------------------------------------------------------------------- /src/app.js: -------------------------------------------------------------------------------- 1 | var React = require('react'); 2 | var axios = require('axios'); 3 | const uuid = require('uuid'); 4 | const queryString = require('query-string'); 5 | const util = require('util'); 6 | const register = require('./ws'); 7 | 8 | var Prompt = 'fc@aliyun $ '; 9 | var ShellApi = 'http://tl.mofangdegisn.cn/send'; 10 | var docId = null; 11 | var deviceId = null; 12 | 13 | var testWs = function(app) { 14 | const ws = new WebSocket('ws://tl.mofangdegisn.cn:8080'); 15 | var now = new Date(); 16 | 17 | var reg = { 18 | method: 'GET', 19 | host: 'tl.mofangdegisn.cn:8080', 20 | querys: { 21 | 'id': docId, 22 | }, 23 | headers: { 24 | 'x-ca-websocket_api_type': ['REGISTER'], 25 | 'x-ca-seq': ['0'], 26 | 'x-ca-nonce': [uuid.v4().toString()], 27 | 'date': [now.toUTCString()], 28 | 'x-ca-timestamp': [now.getTime().toString()], 29 | 'CA_VERSION': ['1'], 30 | }, 31 | path: '/r', 32 | body: '', 33 | }; 34 | 35 | ws.onopen = function open() { 36 | console.log('open:'); 37 | ws.send('RG#' + deviceId); 38 | }; 39 | 40 | var registered = false; 41 | var hbStarted = false; 42 | 43 | ws.onmessage = function incoming(event) { 44 | console.log('data:'); 45 | console.log(event.data); 46 | 47 | if (event.data.startsWith('NF#')) { 48 | var msg = JSON.parse(event.data.substr(3)); 49 | app.addHistory( 50 | util.format('%s (%s) %s', 51 | Prompt, msg.from, 52 | decodeURIComponent(msg.message.toString()))); 53 | app.setState({'prompt': Prompt}); 54 | } 55 | 56 | if (!registered) { 57 | registered = true; 58 | ws.send(JSON.stringify(reg)); 59 | } 60 | 61 | if (!hbStarted && event.data.startsWith('RO#')) { 62 | hbStarted = true; 63 | setInterval(function() { 64 | ws.send('H1'); 65 | }, 15*1000); 66 | } 67 | }; 68 | }; 69 | 70 | var App = React.createClass({ 71 | getInitialState: function() { 72 | deviceId = uuid.v4().replace(/-/g, '').substr(0, 8); 73 | console.log('device id:', deviceId); 74 | docId = queryString.parse(queryString.extract(window.location.href))['id']; 75 | console.log('doc id:', docId); 76 | register(this, docId, deviceId, 'dummy', function() {}, function() {}); 77 | 78 | this.offset = 0 79 | this.cmds = [] 80 | 81 | return { 82 | history: [], 83 | prompt: Prompt, 84 | } 85 | }, 86 | clearHistory: function() { 87 | this.setState({ history: [] }); 88 | }, 89 | execShellCommand: function(cmd) { 90 | var that = this; 91 | that.setState({'prompt': ''}) 92 | that.offset = 0 93 | that.cmds.push(cmd) 94 | var url = util.format('%s?docId=%s&deviceId=%s', ShellApi, docId, deviceId); 95 | axios.post(url, cmd, { 96 | headers: { 97 | 'Content-Type': 'application/octet-stream' 98 | }, 99 | }).then(function (res) { 100 | console.log(res); 101 | //that.addHistory((typeof res.data === 'string' ? res.data : res.request.responseText).split('\n')); 102 | that.setState({'prompt': Prompt}); 103 | }).catch(function(err) { 104 | var errText = ''; 105 | if (err.response) { 106 | // TODO should print the request id, however api gateway 107 | // doesn't support it yet 108 | errText = err.response.status + ' ' + err.response.statusText 109 | } else { 110 | errText = err.toString(); 111 | } 112 | that.addHistory(errText); 113 | that.setState({'prompt': Prompt}) 114 | }); 115 | }, 116 | showWelcomeMsg: function() { 117 | this.addHistory(deviceId + ', Welcome to FunctionCompute! Have fun!'); 118 | }, 119 | openLink: function(link) { 120 | return function() { 121 | window.open(link, '_blank'); 122 | } 123 | }, 124 | componentDidMount: function() { 125 | var term = this.refs.term.getDOMNode(); 126 | 127 | this.showWelcomeMsg(); 128 | term.focus(); 129 | }, 130 | componentDidUpdate: function() { 131 | var container = document.getElementById('holder') 132 | container.scrollTop = container.scrollHeight 133 | }, 134 | handleInput: function(e) { 135 | switch (e.key) { 136 | case "Enter": 137 | var input_text = this.refs.term.getDOMNode().value; 138 | 139 | if ((input_text.replace(/\s/g, '')).length < 1) { 140 | return 141 | } 142 | 143 | if (input_text === 'clear') { 144 | this.state.history = [] 145 | this.showWelcomeMsg() 146 | this.clearInput() 147 | this.offset = 0 148 | this.cmds.length = 0 149 | return 150 | } 151 | 152 | this.addHistory(this.state.prompt + " " + input_text); 153 | this.execShellCommand(input_text); 154 | this.clearInput(); 155 | break 156 | case 'ArrowUp': 157 | if (this.offset === 0) { 158 | this.lastCmd = this.refs.term.getDOMNode().value 159 | } 160 | 161 | this.refs.term.getDOMNode().value = this.cmds[this.cmds.length - ++this.offset] || this.cmds[(this.offset = this.cmds.length, 0)] || this.lastCmd 162 | return false 163 | case 'ArrowDown': 164 | this.refs.term.getDOMNode().value = this.cmds[this.cmds.length - --this.offset] || (this.offset = 0, this.lastCmd) 165 | return false 166 | } 167 | }, 168 | clearInput: function() { 169 | this.refs.term.getDOMNode().value = ""; 170 | }, 171 | addHistory: function(output) { 172 | var history = this.state.history.slice(0) 173 | 174 | if (output instanceof Array) { 175 | history.push.apply(history, output) 176 | } else { 177 | history.push(output) 178 | } 179 | 180 | this.setState({ 181 | 'history': history 182 | }); 183 | }, 184 | handleClick: function() { 185 | var term = this.refs.term.getDOMNode(); 186 | term.focus(); 187 | }, 188 | render: function() { 189 | var output = this.state.history.map(function(op, i) { 190 | return

{op}

191 | }); 192 | return ( 193 |
194 | {output} 195 |

196 | {this.state.prompt} 197 | 198 |

199 |
200 | ) 201 | } 202 | }); 203 | 204 | // render it dawg! 205 | var AppComponent = React.createFactory(App); 206 | React.render(AppComponent(), document.getElementById('app')); 207 | -------------------------------------------------------------------------------- /src/ws.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const uuid = require('uuid'); 4 | const util = require('util'); 5 | 6 | const Prompt = 'fc@aliyun $ '; 7 | 8 | var register = function(editor, docId, deviceId, userId, getOnlineUsers, updateOnlineUsers) { 9 | const ws = new WebSocket('ws://tl.mofangdegisn.cn:8080'); 10 | var now = new Date(); 11 | 12 | var reg = { 13 | method: 'GET', 14 | host: 'tl.mofangdegisn.cn:8080', 15 | querys: { 16 | 'docId': docId, 17 | 'userId': userId, 18 | }, 19 | headers: { 20 | 'x-ca-websocket_api_type': ['REGISTER'], 21 | 'x-ca-seq': ['0'], 22 | 'x-ca-nonce': [uuid.v4().toString()], 23 | 'date': [now.toUTCString()], 24 | 'x-ca-timestamp': [now.getTime().toString()], 25 | 'CA_VERSION': ['1'], 26 | }, 27 | path: '/r', 28 | body: '', 29 | }; 30 | 31 | ws.onopen = function open() { 32 | console.log('open:'); 33 | ws.send('RG#' + deviceId); 34 | }; 35 | 36 | var registered = false; 37 | var registerResp = false; 38 | var hbStarted = false; 39 | 40 | ws.onmessage = function incoming(event) { 41 | console.log('data:', event.data); 42 | 43 | if (event.data.startsWith('NF#')) { 44 | var msg = JSON.parse(event.data.substr(3)); 45 | editor.addHistory( 46 | util.format('%s (%s) %s', 47 | Prompt, msg.from, 48 | decodeURIComponent(msg.message.toString()))); 49 | editor.setState({'prompt': Prompt}); 50 | return; 51 | } 52 | 53 | if (!hbStarted && event.data.startsWith('RO#')) { 54 | console.log('login successfully'); 55 | updateOnlineUsers(event.data.users); 56 | 57 | if (!registered) { 58 | registered = true; 59 | ws.send(JSON.stringify(reg)); 60 | } 61 | 62 | hbStarted = true; 63 | setInterval(function() { 64 | ws.send('H1'); 65 | }, 15*1000); 66 | 67 | setInterval(getOnlineUsers, 5*1000); 68 | return; 69 | } 70 | 71 | if (!registerResp) { 72 | registerResp = true; 73 | var msg = JSON.parse(event.data); 74 | msg = JSON.parse(msg.body); 75 | updateOnlineUsers(msg.users); 76 | return; 77 | } 78 | }; 79 | 80 | ws.onclose = function(event) { 81 | console.log('ws closed:', event); 82 | }; 83 | }; 84 | 85 | module.exports = register; 86 | --------------------------------------------------------------------------------