1
+ import { writable } from 'svelte/store' ;
2
+ import { assertApp } from './helpers' ;
3
+ import { startTrace , stopTrace } from './perf' ;
4
+
5
+ // Svelte Store for Storage file
6
+ export function fileStore ( path , opts ) {
7
+ const storage = assertApp ( 'storage' ) ;
8
+
9
+ const { startWith, log, traceId, maxWait, once } = { maxWait : 10000 , ...opts } ;
10
+
11
+ const storageRef = storage . ref ( ) ;
12
+ const ref = typeof path === 'string' ? storageRef . child ( path ) : path ;
13
+
14
+ // Performance trace
15
+ const trace = traceId && startTrace ( traceId ) ;
16
+
17
+ // Internal state
18
+ let _loading = typeof startWith !== undefined ;
19
+ let _error = null ;
20
+ let _teardown ;
21
+ let _waitForIt ;
22
+
23
+ // State should never change without emitting a new value
24
+ // Clears loading state on first call
25
+ const next = ( val , err ) => {
26
+ _loading = false ;
27
+ _waitForIt && clearTimeout ( _waitForIt ) ;
28
+ _error = err || null ;
29
+ set ( val ) ;
30
+ trace && stopTrace ( trace ) ;
31
+ } ;
32
+
33
+ // Timout
34
+ // Runs of first subscription
35
+ const start = ( ) => {
36
+
37
+ // Timout for fallback slot
38
+ _waitForIt = maxWait && setTimeout ( ( ) => _loading && next ( null , new Error ( `Timeout at ${ maxWait } . Using fallback slot.` ) ) , maxWait )
39
+
40
+ // Realtime firebase subscription
41
+ _teardown = ref . on ( "value" ,
42
+ snapshot => {
43
+ // Emit next value
44
+ snapshot . getDownloadURL ( ) . then ( ( url ) => {
45
+ next ( url ) ;
46
+ if ( log ) console . log ( `URl: ${ url } ` ) ;
47
+ } ) ;
48
+
49
+
50
+ if ( log ) console . log ( 'Snapshot:' , snapshot ) ;
51
+
52
+ // Teardown after first emitted value if once
53
+ once && _teardown ( ) ;
54
+ } ,
55
+
56
+ // Handle firebase thrown errors
57
+ error => {
58
+ console . error ( error ) ;
59
+ next ( null , error ) ;
60
+ }
61
+ ) ;
62
+
63
+ // Removes firebase listener when store completes
64
+ return ( ) => _teardown ( ) ;
65
+ } ;
66
+
67
+ // Svelte store
68
+ const store = writable ( startWith , start ) ;
69
+ const { subscribe, set } = store ;
70
+
71
+ return {
72
+ subscribe,
73
+ firestore,
74
+ ref,
75
+ get loading ( ) {
76
+ return _loading ;
77
+ } ,
78
+ get error ( ) {
79
+ return _error ;
80
+ }
81
+ } ;
82
+ }
83
+
84
+ export function uploadFileStore ( path , opts ) {
85
+ const storage = assertApp ( 'storage' ) ;
86
+
87
+ const { startWith, log, traceId } = { maxWait : 10000 , ...opts } ;
88
+
89
+ const storageRef = storage . ref ( ) ;
90
+ const ref = typeof path === 'string' ? storageRef . child ( path ) : path ;
91
+ let snapshot ;
92
+ let task ;
93
+
94
+ // Performance trace
95
+ const trace = traceId && startTrace ( traceId ) ;
96
+
97
+ // Internal state
98
+ let _loading = typeof startWith !== undefined ;
99
+ let _error = null ;
100
+ let _waitForIt ;
101
+
102
+ // State should never change without emitting a new value
103
+ // Clears loading state on first call
104
+ const next = ( val , err ) => {
105
+ _loading = false ;
106
+ _waitForIt && clearTimeout ( _waitForIt ) ;
107
+ _error = err || null ;
108
+ set ( val ) ;
109
+ trace && stopTrace ( trace ) ;
110
+ } ;
111
+
112
+ // Timout
113
+ // Runs of first subscription
114
+ const start = ( ) => { } ;
115
+
116
+ // Svelte store
117
+ const store = writable ( startWith , start ) ;
118
+ let { subscribe, set } = store ;
119
+
120
+ const _set = set ;
121
+ set = ( val ) => {
122
+ task = ref . put ( val ) . then ( snap => {
123
+ snapshot = snap ;
124
+ ref . getDownloadURL ( ) . then ( ( url ) => {
125
+ next ( url ) ;
126
+ if ( log ) console . log ( `URl: ${ url } ` ) ;
127
+ } ) ;
128
+ } ) ;
129
+ task . on ( 'state_changed' , snap => {
130
+ snapshot = snap ;
131
+ } ) ;
132
+ }
133
+
134
+ return {
135
+ subscribe,
136
+ firestore,
137
+ ref,
138
+ get loading ( ) {
139
+ return _loading ;
140
+ } ,
141
+ get error ( ) {
142
+ return _error ;
143
+ }
144
+ } ;
145
+ }
0 commit comments