@hxa-rn/rn-fetch-blob 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (60) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +290 -0
  3. package/harmony/fetch_blob/LICENSE +21 -0
  4. package/harmony/fetch_blob/NOTICE +33 -0
  5. package/harmony/fetch_blob/OAT.xml +38 -0
  6. package/harmony/fetch_blob/build-profile.json5 +16 -0
  7. package/harmony/fetch_blob/hvigorfile.ts +2 -0
  8. package/harmony/fetch_blob/index.ets +1 -0
  9. package/harmony/fetch_blob/oh-package.json5 +14 -0
  10. package/harmony/fetch_blob/src/main/cpp/CMakeLists.txt +15 -0
  11. package/harmony/fetch_blob/src/main/cpp/FetchBlobPackage.h +13 -0
  12. package/harmony/fetch_blob/src/main/cpp/generated/RNOH/generated/BaseFetchBlobPackage.h +72 -0
  13. package/harmony/fetch_blob/src/main/cpp/generated/RNOH/generated/turbo_modules/RNFetchBlob.cpp +55 -0
  14. package/harmony/fetch_blob/src/main/cpp/generated/RNOH/generated/turbo_modules/RNFetchBlob.h +16 -0
  15. package/harmony/fetch_blob/src/main/ets/FetchBlobTurboModulesFactory.ets +18 -0
  16. package/harmony/fetch_blob/src/main/ets/Logger.ts +40 -0
  17. package/harmony/fetch_blob/src/main/ets/RNFetchBlobConfig.ts +45 -0
  18. package/harmony/fetch_blob/src/main/ets/RNFetchBlobFS.ts +673 -0
  19. package/harmony/fetch_blob/src/main/ets/RNFetchBlobImpl.ts +246 -0
  20. package/harmony/fetch_blob/src/main/ets/RNFetchBlobReq.ts +530 -0
  21. package/harmony/fetch_blob/src/main/ets/RNFetchBlobStream.ts +169 -0
  22. package/harmony/fetch_blob/src/main/ets/RNFetchBlobTurboModule.ts +192 -0
  23. package/harmony/fetch_blob/src/main/ets/generated/index.ets +5 -0
  24. package/harmony/fetch_blob/src/main/ets/generated/ts.ts +5 -0
  25. package/harmony/fetch_blob/src/main/ets/generated/turboModules/RNFetchBlob.ts +92 -0
  26. package/harmony/fetch_blob/src/main/ets/generated/turboModules/ts.ts +5 -0
  27. package/harmony/fetch_blob/src/main/module.json5 +22 -0
  28. package/harmony/fetch_blob/src/main/resources/base/element/string.json +8 -0
  29. package/harmony/fetch_blob/src/main/resources/en_US/element/string.json +8 -0
  30. package/harmony/fetch_blob/src/main/resources/zh_CN/element/string.json +8 -0
  31. package/harmony/fetch_blob.har +0 -0
  32. package/package.json +59 -0
  33. package/src/android.js +62 -0
  34. package/src/class/RNFetchBlobFile.js +17 -0
  35. package/src/class/RNFetchBlobReadStream.js +82 -0
  36. package/src/class/RNFetchBlobSession.js +74 -0
  37. package/src/class/RNFetchBlobWriteStream.js +57 -0
  38. package/src/class/StatefulPromise.js +7 -0
  39. package/src/fs.js +432 -0
  40. package/src/index.d.ts +690 -0
  41. package/src/index.js +577 -0
  42. package/src/ios.js +54 -0
  43. package/src/json-stream.js +45 -0
  44. package/src/lib/oboe-browser.min.js +1 -0
  45. package/src/polyfill/Blob.js +362 -0
  46. package/src/polyfill/Event.js +11 -0
  47. package/src/polyfill/EventTarget.js +79 -0
  48. package/src/polyfill/Fetch.js +213 -0
  49. package/src/polyfill/File.js +27 -0
  50. package/src/polyfill/FileReader.js +90 -0
  51. package/src/polyfill/ProgressEvent.js +32 -0
  52. package/src/polyfill/XMLHttpRequest.js +446 -0
  53. package/src/polyfill/XMLHttpRequestEventTarget.js +118 -0
  54. package/src/polyfill/index.js +11 -0
  55. package/src/specs/v1/NativeRNFetchBlob.ts +85 -0
  56. package/src/types.js +64 -0
  57. package/src/utils/log.js +40 -0
  58. package/src/utils/unicode.js +7 -0
  59. package/src/utils/uri.js +28 -0
  60. package/src/utils/uuid.js +4 -0
@@ -0,0 +1 @@
1
+ !function(a,b,c,d,e,f){function g(a,b){return function(){return a.call(this,b.apply(this,arguments))}}function h(a){return function(b){return b[a]}}function i(a,b){return b.apply(f,a)}function j(a){var b=a.length-1,d=c.prototype.slice;if(0==b)return function(){return a.call(this,d.call(arguments))};if(1==b)return function(){return a.call(this,arguments[0],d.call(arguments,1))};var e=c(a.length);return function(){for(var c=0;b>c;c++)e[c]=arguments[c];return e[b]=d.call(arguments,b),a.apply(this,e)}}function k(a){return function(b,c){return a(c,b)}}function l(a,b){return function(c){return a(c)&&b(c)}}function m(){}function n(){return!0}function o(a){return function(){return a}}function p(a,b){return b&&b.constructor===a}function q(a){return a!==f}function r(a,c){return c instanceof b&&y(function(a){return a in c},a)}function s(a,b){return[a,b]}function t(a){return A(a.reduce(k(s),X))}function u(a){return w(function(a,b){return a.unshift(b),a},[],a)}function v(a,b){return b?s(a(Y(b)),v(a,Z(b))):X}function w(a,b,c){return c?a(w(a,b,Z(c)),Y(c)):b}function x(a,b,c){function d(a,c){return a?b(Y(a))?(c(Y(a)),Z(a)):s(Y(a),d(Z(a),c)):X}return d(a,c||m)}function y(a,b){return!b||a(Y(b))&&y(a,Z(b))}function z(a,b){a&&(Y(a).apply(null,b),z(Z(a),b))}function A(a){function b(a,c){return a?b(Z(a),s(Y(a),c)):c}return b(a,X)}function B(a,b){return b&&(a(Y(b))?Y(b):B(a,Z(b)))}function C(a){"use strict";function b(){var a=0;P.length>p&&(c("Max buffer length exceeded: textNode"),a=Math.max(a,P.length)),Q.length>p&&(c("Max buffer length exceeded: numberNode"),a=Math.max(a,Q.length)),O=p-a+Y}function c(a){P&&(m(P),n(),P=""),i=d(a+"\nLn: "+$+"\nCol: "+Z+"\nChr: "+j),o(N(f,f,i))}function e(){return T==s?(m({}),n(),void(S=!0)):((T!==t||0!==X)&&c("Unexpected end"),P&&(m(P),n(),P=""),void(S=!0))}function g(a){return"\r"==a||"\n"==a||" "==a||" "==a}function h(a){if(!i){if(S)return c("Cannot write after close");var d=0;for(j=a[0];j&&(k=j,j=a[d++]);)switch(Y++,"\n"==j?($++,Z=0):Z++,T){case s:if("{"===j)T=u;else if("["===j)T=w;else if(!g(j))return c("Non-whitespace before {[.");continue;case z:case u:if(g(j))continue;if(T===z)U.push(A);else{if("}"===j){m({}),n(),T=U.pop()||t;continue}U.push(v)}if('"'!==j)return c('Malformed object key should start with " ');T=y;continue;case A:case v:if(g(j))continue;if(":"===j)T===v?(U.push(v),P&&(m({}),l(P),P=""),X++):P&&(l(P),P=""),T=t;else if("}"===j)P&&(m(P),n(),P=""),n(),X--,T=U.pop()||t;else{if(","!==j)return c("Bad object");T===v&&U.push(v),P&&(m(P),n(),P=""),T=z}continue;case w:case t:if(g(j))continue;if(T===w){if(m([]),X++,T=t,"]"===j){n(),X--,T=U.pop()||t;continue}U.push(x)}if('"'===j)T=y;else if("{"===j)T=u;else if("["===j)T=w;else if("t"===j)T=B;else if("f"===j)T=E;else if("n"===j)T=I;else if("-"===j)Q+=j;else if("0"===j)Q+=j,T=M;else{if(-1==="123456789".indexOf(j))return c("Bad value");Q+=j,T=M}continue;case x:if(","===j)U.push(x),P&&(m(P),n(),P=""),T=t;else{if("]"!==j){if(g(j))continue;return c("Bad array")}P&&(m(P),n(),P=""),n(),X--,T=U.pop()||t}continue;case y:var e=d-1;a:for(;;){for(;W>0;)if(V+=j,j=a.charAt(d++),4===W?(P+=String.fromCharCode(parseInt(V,16)),W=0,e=d-1):W++,!j)break a;if('"'===j&&!R){T=U.pop()||t,P+=a.substring(e,d-1),P||(m(""),n());break}if("\\"===j&&!R&&(R=!0,P+=a.substring(e,d-1),j=a.charAt(d++),!j))break;if(R){if(R=!1,"n"===j?P+="\n":"r"===j?P+="\r":"t"===j?P+=" ":"f"===j?P+="\f":"b"===j?P+="\b":"u"===j?(W=1,V=""):P+=j,j=a.charAt(d++),e=d-1,j)continue;break}q.lastIndex=d;var f=q.exec(a);if(!f){d=a.length+1,P+=a.substring(e,d-1);break}if(d=f.index+1,j=a.charAt(f.index),!j){P+=a.substring(e,d-1);break}}continue;case B:if(!j)continue;if("r"!==j)return c("Invalid true started with t"+j);T=C;continue;case C:if(!j)continue;if("u"!==j)return c("Invalid true started with tr"+j);T=D;continue;case D:if(!j)continue;if("e"!==j)return c("Invalid true started with tru"+j);m(!0),n(),T=U.pop()||t;continue;case E:if(!j)continue;if("a"!==j)return c("Invalid false started with f"+j);T=F;continue;case F:if(!j)continue;if("l"!==j)return c("Invalid false started with fa"+j);T=G;continue;case G:if(!j)continue;if("s"!==j)return c("Invalid false started with fal"+j);T=H;continue;case H:if(!j)continue;if("e"!==j)return c("Invalid false started with fals"+j);m(!1),n(),T=U.pop()||t;continue;case I:if(!j)continue;if("u"!==j)return c("Invalid null started with n"+j);T=J;continue;case J:if(!j)continue;if("l"!==j)return c("Invalid null started with nu"+j);T=K;continue;case K:if(!j)continue;if("l"!==j)return c("Invalid null started with nul"+j);m(null),n(),T=U.pop()||t;continue;case L:if("."!==j)return c("Leading zero not followed by .");Q+=j,T=M;continue;case M:if(-1!=="0123456789".indexOf(j))Q+=j;else if("."===j){if(-1!==Q.indexOf("."))return c("Invalid number has two dots");Q+=j}else if("e"===j||"E"===j){if(-1!==Q.indexOf("e")||-1!==Q.indexOf("E"))return c("Invalid number has two exponential");Q+=j}else if("+"===j||"-"===j){if("e"!==k&&"E"!==k)return c("Invalid symbol in number");Q+=j}else Q&&(m(parseFloat(Q)),n(),Q=""),d--,T=U.pop()||t;continue;default:return c("Unknown state: "+T)}Y>=O&&b()}}var i,j,k,l=a(qb).emit,m=a(rb).emit,n=a(sb).emit,o=a(jb).emit,p=65536,q=/[\\"\n]/g,r=0,s=r++,t=r++,u=r++,v=r++,w=r++,x=r++,y=r++,z=r++,A=r++,B=r++,C=r++,D=r++,E=r++,F=r++,G=r++,H=r++,I=r++,J=r++,K=r++,L=r++,M=r,O=p,P="",Q="",R=!1,S=!1,T=s,U=[],V=null,W=0,X=0,Y=0,Z=0,$=1;a(nb).on(h),a(ob).on(e)}function D(a,b){"use strict";function c(a){return function(b){d=a(d,b)}}var d,e={};for(var f in b)a(f).on(c(b[f]),e);a(hb).on(function(a){var b,c=Y(d),e=ab(c),f=Z(d);f&&(b=bb(Y(f)),b[e]=a)}),a(ib).on(function(){var a,b=Y(d),c=ab(b),e=Z(d);e&&(a=bb(Y(e)),delete a[c])}),a(pb).on(function(){for(var c in b)a(c).un(e)})}function E(a){var b={};return a&&a.split("\r\n").forEach(function(a){var c=a.indexOf(": ");b[a.substring(0,c)]=a.substring(c+2)}),b}function F(a,b){function c(a){return{"http:":80,"https:":443}[a]}function d(b){return b.port||c(b.protocol||a.protocol)}return!!(b.protocol&&b.protocol!=a.protocol||b.host&&b.host!=a.host||b.host&&d(b)!=d(a))}function G(a){var b=/(\w+:)?(?:\/\/)([\w.-]+)?(?::(\d+))?\/?/,c=b.exec(a)||[];return{protocol:c[1]||"",host:c[2]||"",port:c[3]||""}}function H(){return new XMLHttpRequest}function I(b,c,d,e,g,h,i){"use strict";function j(){var a=c.responseText,b=a.substr(m);b&&k(b),m=V(a)}var k=b(nb).emit,l=b(jb).emit,m=0,n=!0;b(pb).on(function(){c.onreadystatechange=null,c.abort()}),"onprogress"in c&&(c.onprogress=j),c.onreadystatechange=function(){function a(){try{n&&b(mb).emit(c.status,E(c.getAllResponseHeaders())),n=!1}catch(a){}}switch(c.readyState){case 2:case 3:return a();case 4:a();var d=2==String(c.status)[0];d?(j(),b(ob).emit()):l(N(c.status,c.responseText))}};try{c.open(d,e,!0);for(var o in h)c.setRequestHeader(o,h[o]);F(a.location,G(e))||c.setRequestHeader("X-Requested-With","XMLHttpRequest"),c.withCredentials=i,c.send(g)}catch(p){a.setTimeout(T(l,N(f,f,p)),0)}}function J(a,b){return{key:a,node:b}}function K(a){function b(a,b){var d=bb(Y(a));return p(c,d)?f(a,V(d),b):a}function d(a,c){if(!a)return j(c),f(a,cb,c);var d=b(a,c),g=Z(d),h=ab(Y(d));return e(g,h,c),s(J(h,c),g)}function e(a,b,c){bb(Y(a))[b]=c}function f(a,b,c){a&&e(a,b,c);var d=s(J(b,c),a);return h(d),d}function g(a){return i(a),Z(a)||k(bb(Y(a)))}var h=a(fb).emit,i=a(gb).emit,j=a(lb).emit,k=a(kb).emit,l={};return l[rb]=d,l[sb]=g,l[qb]=f,l}function L(a,b,c){function d(a){return function(b){return b.id==a}}var e,f;return{on:function(c,d){var g={listener:c,id:d||c};return b&&b.emit(a,c,g.id),e=s(g,e),f=s(c,f),this},emit:function(){z(f,arguments)},un:function(b){var g;e=x(e,d(b),function(a){g=a}),g&&(f=x(f,function(a){return a==g.listener}),c&&c.emit(a,g.listener,g.id))},listeners:function(){return f},hasListener:function(a){var b=a?d(a):n;return q(B(b,e))}}}function M(){function a(a){return c[a]=L(a,d,e)}function b(b){return c[b]||a(b)}var c={},d=a("newListener"),e=a("removeListener");return["emit","on","un"].forEach(function(a){b[a]=j(function(c,d){i(d,b(c)[a])})}),b}function N(a,b,c){try{var d=e.parse(b)}catch(f){}return{statusCode:a,body:b,jsonBody:d,thrown:c}}function O(a,b){function c(a,b,c){var d=A(c);a(b,u(Z(v(ab,d))),u(v(bb,d)))}function d(b,d,e){var f=a(b).emit;d.on(function(a){var b=e(a);b!==!1&&c(f,bb(b),a)},b),a("removeListener").on(function(c){c==b&&(a(c).listeners()||d.un(b))})}var e={node:a(gb),path:a(fb)};a("newListener").on(function(a){var c=/(node|path):(.*)/.exec(a);if(c){var f=e[c[1]];f.hasListener(a)||d(a,f,b(c[2]))}})}function P(a,b){function c(b,c){return a(b).on(e(c),c),p}function d(a,b,c){c=c||b;var d=e(b);return a.on(function(){var b=!1;p.forget=function(){b=!0},i(arguments,d),delete p.forget,b&&a.un(c)},c),p}function e(b){return function(){try{return b.apply(p,arguments)}catch(c){a(jb).emit(N(f,f,c))}}}function g(b,c){return a(b+":"+c)}function h(a){return function(){var b=a.apply(this,arguments);q(b)&&(b==S.drop?t():u(b))}}function k(a,b,c){var e;e="node"==a?h(c):c,d(g(a,b),e,c)}function l(a,b){for(var c in b)k(a,c,b[c])}function n(a,b,c){return W(b)?k(a,b,c):l(a,b),p}var p,r=/^(node|path):./,s=a(kb),t=a(ib).emit,u=a(hb).emit,v=j(function(b,c){if(p[b])i(c,p[b]);else{var e=a(b),f=c[0];r.test(b)?d(e,f):e.on(f)}return p}),w=function(b,c,d){if("done"==b)s.un(c);else if("node"==b||"path"==b)a.un(b+":"+c,d);else{var e=c;a(b).un(e)}return p};return a(lb).on(function(a){p.root=o(a)}),a(mb).on(function(a,b){p.header=function(a){return a?b[a]:b}}),p={on:v,addListener:v,removeListener:w,emit:a.emit,node:T(n,"node"),path:T(n,"path"),done:T(d,s),start:T(c,mb),fail:a(jb).on,abort:a(pb).emit,header:m,root:m,source:b}}function Q(a,b,c,d,e){var f=M();return b&&I(f,H(),a,b,c,d,e),C(f),D(f,K(f)),O(f,db),P(f,b)}function R(a,b,c,d,f,g,h){function i(a,b){return b===!1&&(a+=-1==a.indexOf("?")?"?":"&",a+="_="+(new Date).getTime()),a}return f=f?e.parse(e.stringify(f)):{},d?W(d)||(d=e.stringify(d),f["Content-Type"]=f["Content-Type"]||"application/json"):d=null,a(c||"GET",i(b,h),d,f,g||!1)}function S(a){var b=$("resume","pause","pipe"),c=T(r,b);return a?c(a)||W(a)?R(Q,a):R(Q,a.url,a.method,a.body,a.headers,a.withCredentials,a.cached):Q()}var T=j(function(a,b){var c=b.length;return j(function(d){for(var e=0;e<d.length;e++)b[c+e]=d[e];return b.length=c+d.length,a.apply(this,b)})}),U=(j(function(a){function b(a,b){return[i(a,b)]}var c=t(a);return j(function(a){return w(b,a,c)[0]})}),j(function(a){return j(function(b){for(var c,d=0;d<V(a);d++)if(c=i(b,a[d]))return c})})),V=h("length"),W=T(p,String),X=null,Y=h(0),Z=h(1),$=j(t),_=function(){var a=function(a){return a.exec.bind(a)},b=j(function(b){return b.unshift(/^/),a(RegExp(b.map(h("source")).join("")))}),c=/(\$?)/,d=/([\w-_]+|\*)/,e=/()/,f=/\["([^"]+)"\]/,g=/\[(\d+|\*)\]/,i=/{([\w ]*?)}/,k=/(?:{([\w ]*?)})?/,l=b(c,d,k),m=b(c,f,k),n=b(c,g,k),o=b(c,e,i),p=b(/\.\./),q=b(/\./),r=b(c,/!/),s=b(/$/);return function(a){return a(U(l,m,n,o),p,q,r,s)}}(),ab=h("key"),bb=h("node"),cb={},db=_(function(a,b,c,e,f){function h(a,b){var c=b[z],d=c&&"*"!=c?function(a){return B(a)==c}:n;return l(d,a)}function i(a,b){var c=b[A];if(!c)return a;var d=T(r,t(c.split(/\W+/))),e=g(d,C);return l(e,a)}function j(a,b){var c=!!b[y];return c?l(a,Y):a}function k(a){function b(a){return B(a)!=cb}return a==n?n:l(b,g(a,Z))}function m(a){if(a==n)return n;var b=o(),c=a,d=k(function(a){return e(a)}),e=U(b,c,d);return e}function o(){return function(a){return B(a)==cb}}function p(a){return function(b){var c=a(b);return c===!0?Y(b):c}}function q(a,b,c){return w(function(a,b){return b(a,c)},b,a)}function s(a,b,c,d,e){var f=a(c);if(f){var g=q(b,d,f),h=c.substr(V(f[0]));return e(h,g)}}function u(a,b){return T(s,a,b)}function v(a,b){return b}function x(a,b){var c=a?x:v;return D(a,b,c)}var y=1,z=2,A=3,B=g(ab,Y),C=g(bb,Y),D=U(u(a,$(j,i,h,k)),u(b,$(m)),u(c,$()),u(e,$(j,o)),u(f,$(p)),function(a){throw d('"'+a+'" could not be tokenised')});return function(a){try{return x(a,n)}catch(b){throw d('Could not compile "'+a+'" because '+b.message)}}}),eb=1,fb=eb++,gb=eb++,hb=eb++,ib=eb++,jb="fail",kb=eb++,lb=eb++,mb="start",nb="data",ob="end",pb=eb++,qb=eb++,rb=eb++,sb=eb++;S.drop=function(){return S.drop},"function"==typeof define&&define.amd?define("oboe",[],function(){return S}):"object"==typeof exports?module.exports=S:a.oboe=S}(function(){try{return window}catch(a){return self}}(),Object,Array,Error,JSON);
@@ -0,0 +1,362 @@
1
+ // Copyright 2016 wkh237@github. All rights reserved.
2
+ // Use of this source code is governed by a MIT-style license that can be
3
+ // found in the LICENSE file.
4
+
5
+ import RNFetchBlob from '../index.js'
6
+ import fs from '../fs.js'
7
+ import getUUID from '../utils/uuid'
8
+ import Log from '../utils/log.js'
9
+ import EventTarget from './EventTarget'
10
+
11
+ const log = new Log('Blob')
12
+ const blobCacheDir = fs.dirs.DocumentDir + '/RNFetchBlob-blobs/'
13
+
14
+ log.disable()
15
+ // log.level(3)
16
+
17
+ /**
18
+ * A RNFetchBlob style Blob polyfill class, this is a Blob which compatible to
19
+ * Response object attain fron RNFetchBlob.fetch.
20
+ */
21
+ export default class Blob extends EventTarget {
22
+
23
+ cacheName:string;
24
+ type:string;
25
+ size:number;
26
+ isRNFetchBlobPolyfill:boolean = true;
27
+ multipartBoundary:string = null;
28
+
29
+ _ref:string = null;
30
+ _blobCreated:boolean = false;
31
+ _onCreated:Array<any> = [];
32
+ _closed:boolean = false;
33
+
34
+ /**
35
+ * Static method that remove all files in Blob cache folder.
36
+ * @nonstandard
37
+ * @return {Promise}
38
+ */
39
+ static clearCache() {
40
+ return fs.unlink(blobCacheDir).then(() => fs.mkdir(blobCacheDir))
41
+ }
42
+
43
+ static build(data:any, cType:any):Promise<Blob> {
44
+ return new Promise((resolve, reject) => {
45
+ new Blob(data, cType).onCreated(resolve)
46
+ })
47
+ }
48
+
49
+ get blobPath() {
50
+ return this._ref
51
+ }
52
+
53
+ static setLog(level:number) {
54
+ if(level === -1)
55
+ log.disable()
56
+ else
57
+ log.level(level)
58
+ }
59
+
60
+ /**
61
+ * RNFetchBlob Blob polyfill, create a Blob directly from file path, BASE64
62
+ * encoded data, and string. The conversion is done implicitly according to
63
+ * given `mime`. However, the blob creation is asynchronously, to register
64
+ * event `onCreated` is need to ensure the Blob is creadted.
65
+ * @param {any} data Content of Blob object
66
+ * @param {any} mime Content type settings of Blob object, `text/plain`
67
+ * by default
68
+ * @param {boolean} defer When this argument set to `true`, blob constructor
69
+ * will not invoke blob created event automatically.
70
+ */
71
+ constructor(data:any, cType:any, defer:boolean) {
72
+ super()
73
+ cType = cType || {}
74
+ this.cacheName = getBlobName()
75
+ this.isRNFetchBlobPolyfill = true
76
+ this.isDerived = defer
77
+ this.type = cType.type || 'text/plain'
78
+ log.verbose('Blob constructor called', 'mime', this.type, 'type', typeof data, 'length', data? data.length:0)
79
+ this._ref = blobCacheDir + this.cacheName
80
+ let p = null
81
+ if(!data)
82
+ data = ''
83
+ if(data.isRNFetchBlobPolyfill) {
84
+ log.verbose('create Blob cache file from Blob object')
85
+ let size = 0
86
+ this._ref = String(data.getRNFetchBlobRef())
87
+ let orgPath = this._ref
88
+
89
+ p = fs.exists(orgPath)
90
+ .then((exist) => {
91
+ if(exist)
92
+ return fs.writeFile(orgPath, data, 'uri')
93
+ .then((size) => Promise.resolve(size))
94
+ .catch((err) => {
95
+ throw `RNFetchBlob Blob file creation error, ${err}`
96
+ })
97
+ else
98
+ throw `could not create Blob from path ${orgPath}, file not exists`
99
+ })
100
+ }
101
+ // process FormData
102
+ else if(data instanceof FormData) {
103
+ log.verbose('create Blob cache file from FormData', data)
104
+ let boundary = `RNFetchBlob-${this.cacheName}-${Date.now()}`
105
+ this.multipartBoundary = boundary
106
+ let parts = data.getParts()
107
+ let formArray = []
108
+ if(!parts) {
109
+ p = fs.writeFile(this._ref, '', 'utf8')
110
+ }
111
+ else {
112
+ for(let i in parts) {
113
+ formArray.push('\r\n--'+boundary+'\r\n')
114
+ let part = parts[i]
115
+ for(let j in part.headers) {
116
+ formArray.push(j + ': ' +part.headers[j] + '\r\n')
117
+ }
118
+ formArray.push('\r\n')
119
+ if(part.isRNFetchBlobPolyfill)
120
+ formArray.push(part)
121
+ else
122
+ formArray.push(part.string)
123
+ }
124
+ log.verbose('FormData array', formArray)
125
+ formArray.push('\r\n--'+boundary+'--\r\n')
126
+ p = createMixedBlobData(this._ref, formArray)
127
+ }
128
+ }
129
+ // if the data is a string starts with `RNFetchBlob-file://`, append the
130
+ // Blob data from file path
131
+ else if(typeof data === 'string' && data.startsWith('RNFetchBlob-file://')) {
132
+ log.verbose('create Blob cache file from file path', data)
133
+ // set this flag so that we know this blob is a wrapper of an existing file
134
+ this._isReference = true
135
+ this._ref = String(data).replace('RNFetchBlob-file://', '')
136
+ let orgPath = this._ref
137
+ if(defer)
138
+ return
139
+ else {
140
+ p = fs.stat(orgPath)
141
+ .then((stat) => {
142
+ return Promise.resolve(stat.size)
143
+ })
144
+ }
145
+ }
146
+ // content from variable need create file
147
+ else if(typeof data === 'string') {
148
+ let encoding = 'utf8'
149
+ let mime = String(this.type)
150
+ // when content type contains application/octet* or *;base64, RNFetchBlob
151
+ // fs will treat it as BASE64 encoded string binary data
152
+ if(/(application\/octet|\;base64)/i.test(mime))
153
+ encoding = 'base64'
154
+ else
155
+ data = data.toString()
156
+ // create cache file
157
+ this.type = String(this.type).replace(/;base64/ig, '')
158
+ log.verbose('create Blob cache file from string', 'encode', encoding)
159
+ p = fs.writeFile(this._ref, data, encoding)
160
+ .then((size) => {
161
+ return Promise.resolve(size)
162
+ })
163
+
164
+ }
165
+ // TODO : ArrayBuffer support
166
+ // else if (data instanceof ArrayBuffer ) {
167
+ //
168
+ // }
169
+ // when input is an array of mixed data types, create a file cache
170
+ else if(Array.isArray(data)) {
171
+ log.verbose('create Blob cache file from mixed array', data)
172
+ p = createMixedBlobData(this._ref, data)
173
+ }
174
+ else {
175
+ data = data.toString()
176
+ p = fs.writeFile(this._ref, data, 'utf8')
177
+ .then((size) => Promise.resolve(size))
178
+ }
179
+ p && p.then((size) => {
180
+ this.size = size
181
+ this._invokeOnCreateEvent()
182
+ })
183
+ .catch((err) => {
184
+ log.error('RNFetchBlob could not create Blob : '+ this._ref, err)
185
+ })
186
+
187
+ }
188
+
189
+ /**
190
+ * Since Blob content will asynchronously write to a file during creation,
191
+ * use this method to register an event handler for Blob initialized event.
192
+ * @nonstandard
193
+ * @param {(b:Blob) => void} An event handler invoked when Blob created
194
+ * @return {Blob} The Blob object instance itself
195
+ */
196
+ onCreated(fn:() => void):Blob {
197
+ log.verbose('#register blob onCreated', this._blobCreated)
198
+ if(!this._blobCreated)
199
+ this._onCreated.push(fn)
200
+ else {
201
+ fn(this)
202
+ }
203
+ return this
204
+ }
205
+
206
+ markAsDerived() {
207
+ this._isDerived = true
208
+ }
209
+
210
+ get isDerived() {
211
+ return this._isDerived || false
212
+ }
213
+
214
+ /**
215
+ * Get file reference of the Blob object.
216
+ * @nonstandard
217
+ * @return {string} Blob file reference which can be consumed by RNFetchBlob fs
218
+ */
219
+ getRNFetchBlobRef() {
220
+ return this._ref
221
+ }
222
+
223
+ /**
224
+ * Create a Blob object which is sliced from current object
225
+ * @param {number} start Start byte number
226
+ * @param {number} end End byte number
227
+ * @param {string} contentType Optional, content type of new Blob object
228
+ * @return {Blob}
229
+ */
230
+ slice(start:?number, end:?number, contentType:?string=''):Blob {
231
+ if(this._closed)
232
+ throw 'Blob has been released.'
233
+ log.verbose('slice called', start, end, contentType)
234
+
235
+
236
+ let resPath = blobCacheDir + getBlobName()
237
+ let pass = false
238
+ log.debug('fs.slice new blob will at', resPath)
239
+ let result = new Blob(RNFetchBlob.wrap(resPath), { type : contentType }, true)
240
+ fs.exists(blobCacheDir)
241
+ .then((exist) => {
242
+ if(exist)
243
+ return Promise.resolve()
244
+ return fs.mkdir(blobCacheDir)
245
+ })
246
+ .then(() => fs.slice(this._ref, resPath, start, end))
247
+ .then((dest) => {
248
+ log.debug('fs.slice done', dest)
249
+ result._invokeOnCreateEvent()
250
+ pass = true
251
+ })
252
+ .catch((err) => {
253
+ console.warn('Blob.slice failed:', err)
254
+ pass = true
255
+ })
256
+ log.debug('slice returning new Blob')
257
+
258
+ return result
259
+ }
260
+
261
+ /**
262
+ * Read data of the Blob object, this is not standard method.
263
+ * @nonstandard
264
+ * @param {string} encoding Read data with encoding
265
+ * @return {Promise}
266
+ */
267
+ readBlob(encoding:string):Promise<any> {
268
+ if(this._closed)
269
+ throw 'Blob has been released.'
270
+ return fs.readFile(this._ref, encoding || 'utf8')
271
+ }
272
+
273
+ /**
274
+ * Release the resource of the Blob object.
275
+ * @nonstandard
276
+ * @return {Promise}
277
+ */
278
+ close() {
279
+ if(this._closed)
280
+ return Promise.reject('Blob has been released.')
281
+ this._closed = true
282
+ return fs.unlink(this._ref).catch((err) => {
283
+ console.warn(err)
284
+ })
285
+ }
286
+
287
+ safeClose() {
288
+ if(this._closed)
289
+ return Promise.reject('Blob has been released.')
290
+ this._closed = true
291
+ if(!this._isReference) {
292
+ return fs.unlink(this._ref).catch((err) => {
293
+ console.warn(err)
294
+ })
295
+ }
296
+ else {
297
+ return Promise.resolve()
298
+ }
299
+ }
300
+
301
+ _invokeOnCreateEvent() {
302
+ log.verbose('invoke create event', this._onCreated)
303
+ this._blobCreated = true
304
+ let fns = this._onCreated
305
+ for(let i in fns) {
306
+ if(typeof fns[i] === 'function') {
307
+ fns[i](this)
308
+ }
309
+ }
310
+ delete this._onCreated
311
+ }
312
+
313
+ }
314
+
315
+ /**
316
+ * Get a temp filename for Blob object
317
+ * @return {string} Temporary filename
318
+ */
319
+ function getBlobName() {
320
+ return 'blob-' + getUUID()
321
+ }
322
+
323
+ /**
324
+ * Create a file according to given array. The element in array can be a number,
325
+ * Blob, String, Array.
326
+ * @param {string} ref File path reference
327
+ * @param {Array} dataArray An array contains different types of data.
328
+ * @return {Promise}
329
+ */
330
+ function createMixedBlobData(ref, dataArray) {
331
+ // create an empty file for store blob data
332
+ let p = fs.writeFile(ref, '')
333
+ let args = []
334
+ let size = 0
335
+ for(let i in dataArray) {
336
+ let part = dataArray[i]
337
+ if(!part)
338
+ continue
339
+ if(part.isRNFetchBlobPolyfill) {
340
+ args.push([ref, part._ref, 'uri'])
341
+ }
342
+ else if(typeof part === 'string')
343
+ args.push([ref, part, 'utf8'])
344
+ // TODO : ArrayBuffer
345
+ // else if (part instanceof ArrayBuffer) {
346
+ //
347
+ // }
348
+ else if (Array.isArray(part))
349
+ args.push([ref, part, 'ascii'])
350
+ }
351
+ // start write blob data
352
+ for(let i in args) {
353
+ p = p.then(function(written){
354
+ let arg = this
355
+ if(written)
356
+ size += written
357
+ log.verbose('mixed blob write', args[i], written)
358
+ return fs.appendFile(...arg)
359
+ }.bind(args[i]))
360
+ }
361
+ return p.then(() => Promise.resolve(size))
362
+ }
@@ -0,0 +1,11 @@
1
+ // Copyright 2016 wkh237@github. All rights reserved.
2
+ // Use of this source code is governed by a MIT-style license that can be
3
+ // found in the LICENSE file.
4
+
5
+ export default class Event {
6
+
7
+ constructor() {
8
+
9
+ }
10
+
11
+ }
@@ -0,0 +1,79 @@
1
+ // Copyright 2016 wkh237@github. All rights reserved.
2
+ // Use of this source code is governed by a MIT-style license that can be
3
+ // found in the LICENSE file.
4
+
5
+ import Log from '../utils/log.js'
6
+
7
+ const log = new Log('EventTarget')
8
+
9
+ log.disable()
10
+
11
+ export default class EventTarget {
12
+
13
+ listeners : any;
14
+
15
+ constructor() {
16
+ log.info('constructor called')
17
+ this.listeners = {}
18
+ }
19
+
20
+ /**
21
+ * Add an event listener to given event type
22
+ * @param {string} type Event type string
23
+ * @param {(Event) => void} cb Event handler function
24
+ */
25
+ addEventListener(type:string, cb : () => void) {
26
+ log.info('add event listener', type, cb)
27
+ if(!(type in this.listeners)) {
28
+ this.listeners[type] = []
29
+ }
30
+ this.listeners[type].push(cb)
31
+ }
32
+
33
+ /**
34
+ * Remove an event listener
35
+ * @param {string} type Type of the event listener
36
+ * @param {()=>void} cb Event listener function.
37
+ * @return {[type]} [description]
38
+ */
39
+ removeEventListener(type:string, cb:() => void) {
40
+ log.info('remove event listener', type, cb)
41
+ if(!(type in this.listeners))
42
+ return
43
+ let handlers = this.listeners[type]
44
+ for(let i in handlers) {
45
+ if(cb === handlers[i]) {
46
+ handlers.splice(i,1)
47
+ return this.removeEventListener(type, cb)
48
+ }
49
+ }
50
+ }
51
+
52
+ /**
53
+ * Dispatch an event
54
+ * @param {string} type Event type.
55
+ * @param {Event} event Event data payload.
56
+ */
57
+ dispatchEvent(type:string,event:Event) {
58
+ log.info('dispatch event', event)
59
+ if(!(type in this.listeners))
60
+ return
61
+ let handlers = this.listeners[type]
62
+ for(let i in handlers) {
63
+ handlers[i].call(this, event)
64
+ }
65
+
66
+ }
67
+
68
+ /**
69
+ * Remove all registered listeners from this object.
70
+ * @nonstandard
71
+ * @return {[type]} [description]
72
+ */
73
+ clearEventListeners() {
74
+ for(let i in this.listeners) {
75
+ delete this.listeners[i]
76
+ }
77
+ }
78
+
79
+ }
@@ -0,0 +1,213 @@
1
+ import RNFetchBlob from '../index.js'
2
+ import Log from '../utils/log.js'
3
+ import fs from '../fs'
4
+ import unicode from '../utils/unicode'
5
+ import Blob from './Blob'
6
+
7
+ const log = new Log('FetchPolyfill')
8
+
9
+ log.disable()
10
+ // log.level(3)
11
+
12
+ export default class Fetch {
13
+
14
+ constructor(config:RNFetchBlobConfig) {
15
+ Object.assign(this, new RNFetchBlobFetchPolyfill(config))
16
+ }
17
+
18
+ }
19
+
20
+ class RNFetchBlobFetchPolyfill {
21
+
22
+ constructor(config:RNFetchBlobConfig) {
23
+ this.build = () => (url, options = {}) => {
24
+
25
+ let body = options.body
26
+ let promise = Promise.resolve()
27
+ let blobCache = null
28
+
29
+ options.headers = options.headers || {}
30
+ let ctype = options['Content-Type'] || options['content-type']
31
+ let ctypeH = options.headers['Content-Type'] || options.headers['content-type']
32
+ options.headers['Content-Type'] = ctype || ctypeH
33
+ options.headers['content-type'] = ctype || ctypeH
34
+ options.method = options.method || 'GET'
35
+ if(body) {
36
+ // When the request body is an instance of FormData, create a Blob cache
37
+ // to upload the body.
38
+ if(body instanceof FormData) {
39
+ log.verbose('convert FormData to blob body')
40
+ promise = Blob.build(body).then((b) => {
41
+ blobCache = b
42
+ options.headers['Content-Type'] = 'multipart/form-data;boundary=' + b.multipartBoundary
43
+ return Promise.resolve(RNFetchBlob.wrap(b._ref))
44
+ })
45
+ }
46
+ // When request body is a Blob, use file URI of the Blob as request body.
47
+ else if (body.isRNFetchBlobPolyfill)
48
+ promise = Promise.resolve(RNFetchBlob.wrap(body.blobPath))
49
+ else if (typeof body !== 'object' && options.headers['Content-Type'] !== 'application/json')
50
+ promise = Promise.resolve(JSON.stringify(body))
51
+ else if (typeof body !== 'string')
52
+ promise = Promise.resolve(body.toString())
53
+ // send it as-is, leave the native module decide how to send the body.
54
+ else
55
+ promise = Promise.resolve(body)
56
+ }
57
+ // task is a progress reportable and cancellable Promise, however,
58
+ // task.then is not, so we have to extend task.then with progress and
59
+ // cancel function
60
+ let progressHandler, uploadHandler, cancelHandler
61
+ let statefulPromise = promise
62
+ .then((body) => {
63
+ let task = RNFetchBlob.config(config)
64
+ .fetch(options.method, url, options.headers, body)
65
+ if(progressHandler)
66
+ task.progress(progressHandler)
67
+ if(uploadHandler)
68
+ task.uploadProgress(uploadHandler)
69
+ if(cancelHandler)
70
+ task.cancel()
71
+ return task.then((resp) => {
72
+ log.verbose('response', resp)
73
+ // release blob cache created when sending request
74
+ if(blobCache !== null && blobCache instanceof Blob)
75
+ blobCache.close()
76
+ return Promise.resolve(new RNFetchBlobFetchResponse(resp))
77
+ })
78
+ })
79
+
80
+ // extend task.then progress with report and cancelling functions
81
+ statefulPromise.progress = (fn) => {
82
+ progressHandler = fn
83
+ }
84
+ statefulPromise.uploadProgress = (fn) => {
85
+ uploadHandler = fn
86
+ }
87
+ statefulPromise.cancel = () => {
88
+ cancelHandler = true
89
+ if(task.cancel)
90
+ task.cancel()
91
+ }
92
+
93
+ return statefulPromise
94
+
95
+ }
96
+ }
97
+
98
+ }
99
+
100
+ class RNFetchBlobFetchResponse {
101
+
102
+ constructor(resp:FetchBlobResponse) {
103
+ let info = resp.info()
104
+ this.headers = info.headers
105
+ this.ok = info.status >= 200 && info.status <= 299,
106
+ this.status = info.status
107
+ this.type = 'basic'
108
+ this.bodyUsed = false
109
+ this.resp = resp
110
+ this.rnfbRespInfo = info
111
+ this.rnfbResp = resp
112
+ }
113
+
114
+ rawResp() {
115
+ return Promise.resolve(this.rnfbResp)
116
+ }
117
+
118
+ arrayBuffer(){
119
+ log.verbose('to arrayBuffer', this.rnfbRespInfo)
120
+ this.bodyUsed = true
121
+ return readArrayBuffer(this.rnfbResp, this.rnfbRespInfo)
122
+ }
123
+
124
+ text() {
125
+ log.verbose('to text', this.rnfbResp, this.rnfbRespInfo)
126
+ this.bodyUsed = true
127
+ return readText(this.rnfbResp, this.rnfbRespInfo)
128
+ }
129
+
130
+ json() {
131
+ log.verbose('to json', this.rnfbResp, this.rnfbRespInfo)
132
+ this.bodyUsed = true
133
+ return readJSON(this.rnfbResp, this.rnfbRespInfo)
134
+ }
135
+
136
+ blob() {
137
+ log.verbose('to blob', this.rnfbResp, this.rnfbRespInfo)
138
+ this.bodyUsed = true
139
+ return readBlob(this.rnfbResp, this.rnfbRespInfo)
140
+ }
141
+ }
142
+
143
+ /**
144
+ * Get response data as array.
145
+ * @param {FetchBlobResponse} resp Response data object from RNFB fetch call.
146
+ * @param {RNFetchBlobResponseInfo} info Response informations.
147
+ * @return {Promise<Array>}
148
+ */
149
+ function readArrayBuffer(resp, info):Promise<Array> {
150
+ switch (info.rnfbEncode) {
151
+ case 'path':
152
+ return resp.readFile('ascii')
153
+ break
154
+ default:
155
+ let buffer = []
156
+ let str = resp.text()
157
+ for (let i in str) {
158
+ buffer[i] = str.charCodeAt(i);
159
+ }
160
+ return Promise.resolve(buffer)
161
+ break
162
+ }
163
+ }
164
+
165
+ /**
166
+ * Get response data as string.
167
+ * @param {FetchBlobResponse} resp Response data object from RNFB fetch call.
168
+ * @param {RNFetchBlobResponseInfo} info Response informations.
169
+ * @return {Promise<string>}
170
+ */
171
+ function readText(resp, info):Promise<string> {
172
+ switch (info.rnfbEncode) {
173
+ case 'base64':
174
+ return Promise.resolve(resp.text())
175
+ break
176
+ case 'path':
177
+ return resp.text()
178
+ break
179
+ default:
180
+ return Promise.resolve(resp.text())
181
+ break
182
+ }
183
+ }
184
+
185
+
186
+ /**
187
+ * Get response data as RNFetchBlob Blob polyfill object.
188
+ * @param {FetchBlobResponse} resp Response data object from RNFB fetch call.
189
+ * @param {RNFetchBlobResponseInfo} info Response informations.
190
+ * @return {Promise<Blob>}
191
+ */
192
+ function readBlob(resp, info):Promise<Blob> {
193
+ log.verbose('readBlob', resp, info)
194
+ return resp.blob()
195
+ }
196
+
197
+ /**
198
+ * Get response data as JSON object.
199
+ * @param {FetchBlobResponse} resp Response data object from RNFB fetch call.
200
+ * @param {RNFetchBlobResponseInfo} info Response informations.
201
+ * @return {Promise<object>}
202
+ */
203
+ function readJSON(resp, info):Promise<object> {
204
+ log.verbose('readJSON', resp, info)
205
+ switch (info.rnfbEncode) {
206
+ case 'base64':
207
+ return Promise.resolve(resp.json())
208
+ case 'path':
209
+ return resp.json()
210
+ default:
211
+ return Promise.resolve(resp.json())
212
+ }
213
+ }