1
- import 'rxjs/Rx' ;
2
1
import { Observable } from 'rxjs/Observable' ;
3
2
import { Subscriber } from 'rxjs/Subscriber' ;
4
3
import { Subject } from 'rxjs/Subject' ;
5
4
import { OpaqueToken , Inject , provide } from 'angular2/core' ;
5
+ import 'rxjs/add/operator/mergeMap'
6
+ import 'rxjs/add/operator/do'
7
+ import 'rxjs/add/operator/toArray'
8
+ import 'rxjs/add/observable/fromArray'
6
9
7
10
const IDB_SUCCESS = 'success' ;
8
11
const IDB_COMPLETE = 'complete' ;
@@ -35,17 +38,17 @@ export interface DBSchema {
35
38
export const getIDBFactory = ( ) => window . indexedDB || self . indexedDB ;
36
39
37
40
export class Database {
38
-
41
+
39
42
public changes :Subject < any > = new Subject ( ) ;
40
-
43
+
41
44
private _idb :IDBFactory ;
42
45
private _schema : DBSchema ;
43
46
44
47
constructor ( @Inject ( DatabaseBackend ) idbBackend , @Inject ( IDB_SCHEMA ) schema ) {
45
48
this . _schema = schema ;
46
49
this . _idb = idbBackend ;
47
50
}
48
-
51
+
49
52
private _upgradeDB ( observer , db :IDBDatabase ) {
50
53
for ( var storeName in this . _schema . stores ) {
51
54
if ( db . objectStoreNames . contains ( storeName ) ) {
@@ -56,17 +59,17 @@ export class Database {
56
59
observer . next ( db ) ;
57
60
observer . complete ( ) ;
58
61
}
59
-
62
+
60
63
private _createObjectStore ( db :IDBDatabase , key :string , schema :DBStore ) {
61
64
let objectStore = db . createObjectStore ( key , { autoIncrement : true } ) ;
62
65
}
63
-
66
+
64
67
open ( dbName :string , version :number = 1 , upgradeHandler ?:DBUpgradeHandler ) :Observable < IDBDatabase > {
65
68
const idb = this . _idb ;
66
- return new Observable ( ( observer :Subscriber < any > ) => {
67
-
69
+ return Observable . create ( ( observer :Subscriber < any > ) => {
70
+
68
71
const openReq = idb . open ( dbName , this . _schema . version ) ;
69
-
72
+
70
73
const onSuccess = ( event ) => {
71
74
observer . next ( event . target . result ) ;
72
75
observer . complete ( ) ;
@@ -75,90 +78,90 @@ export class Database {
75
78
console . log ( err ) ;
76
79
observer . error ( err ) ;
77
80
}
78
-
81
+
79
82
const onUpgradeNeeded = ( event ) => {
80
83
this . _upgradeDB ( observer , event . target . result ) ;
81
84
}
82
-
85
+
83
86
openReq . addEventListener ( IDB_SUCCESS , onSuccess ) ;
84
87
openReq . addEventListener ( IDB_ERROR , onError ) ;
85
88
openReq . addEventListener ( IDB_UPGRADE_NEEDED , onUpgradeNeeded ) ;
86
-
89
+
87
90
return ( ) => {
88
91
openReq . removeEventListener ( IDB_SUCCESS , onSuccess ) ;
89
92
openReq . removeEventListener ( IDB_ERROR , onError ) ;
90
93
openReq . removeEventListener ( IDB_UPGRADE_NEEDED , onUpgradeNeeded ) ;
91
94
}
92
-
95
+
93
96
} ) ;
94
97
}
95
-
98
+
96
99
deleteDatabase ( dbName :string ) {
97
100
return new Observable ( ( deletionObserver :Subscriber < any > ) => {
98
-
101
+
99
102
const deleteRequest = this . _idb . deleteDatabase ( dbName ) ;
100
-
103
+
101
104
const onSuccess = ( event ) => {
102
105
deletionObserver . next ( null ) ;
103
106
deletionObserver . complete ( ) ;
104
107
}
105
-
108
+
106
109
const onError = ( err ) => deletionObserver . error ( err ) ;
107
-
110
+
108
111
deleteRequest . addEventListener ( IDB_SUCCESS , onSuccess ) ;
109
112
deleteRequest . addEventListener ( IDB_ERROR , onError ) ;
110
-
113
+
111
114
return ( ) => {
112
115
deleteRequest . removeEventListener ( IDB_SUCCESS , onSuccess ) ;
113
116
deleteRequest . removeEventListener ( IDB_ERROR , onError ) ;
114
117
}
115
118
} )
116
119
}
117
-
120
+
118
121
insert ( storeName :string , records :any [ ] , notify :boolean = true ) {
119
122
return this . executeWrite ( storeName , 'add' , records )
120
123
. do ( payload => notify ? this . changes . next ( { type : DB_INSERT , payload } ) : ( { } ) ) ;
121
124
}
122
-
125
+
123
126
get ( storeName :string , key :any ) {
124
127
return this . open ( this . _schema . name )
125
128
. mergeMap ( db => {
126
129
return new Observable ( txnObserver => {
127
130
const txn = db . transaction ( [ storeName ] , IDB_TXN_READ ) ;
128
131
const objectStore = txn . objectStore ( storeName ) ;
129
-
132
+
130
133
const getRequest = objectStore . get ( key ) ;
131
-
134
+
132
135
const onTxnError = ( err ) => txnObserver . error ( err ) ;
133
136
const onTxnComplete = ( ) => txnObserver . complete ( ) ;
134
137
const onRecordFound = ( ev ) => txnObserver . next ( getRequest . result ) ;
135
-
138
+
136
139
txn . addEventListener ( IDB_COMPLETE , onTxnComplete ) ;
137
140
txn . addEventListener ( IDB_ERROR , onTxnError ) ;
138
-
141
+
139
142
getRequest . addEventListener ( IDB_SUCCESS , onRecordFound ) ;
140
143
getRequest . addEventListener ( IDB_ERROR , onTxnError ) ;
141
-
144
+
142
145
return ( ) => {
143
146
getRequest . removeEventListener ( IDB_SUCCESS , onRecordFound ) ;
144
147
getRequest . removeEventListener ( IDB_ERROR , onTxnError ) ;
145
148
txn . removeEventListener ( IDB_COMPLETE , onTxnComplete ) ;
146
149
txn . removeEventListener ( IDB_ERROR , onTxnError ) ;
147
150
}
148
-
151
+
149
152
} ) ;
150
153
} ) ;
151
154
}
152
-
155
+
153
156
query ( storeName :string , predicate ?:( rec :any ) => boolean ) {
154
157
return this . open ( this . _schema . name )
155
158
. mergeMap ( db => {
156
159
return new Observable ( txnObserver => {
157
160
const txn = db . transaction ( [ storeName ] , IDB_TXN_READ ) ;
158
161
const objectStore = txn . objectStore ( storeName ) ;
159
-
162
+
160
163
const getRequest = objectStore . openCursor ( ) ;
161
-
164
+
162
165
const onTxnError = ( err ) => txnObserver . error ( err ) ;
163
166
const onRecordFound = ( ev ) => {
164
167
let cursor = ev . target . result ;
@@ -178,36 +181,36 @@ export class Database {
178
181
txnObserver . complete ( ) ;
179
182
}
180
183
}
181
-
184
+
182
185
txn . addEventListener ( IDB_ERROR , onTxnError ) ;
183
-
186
+
184
187
getRequest . addEventListener ( IDB_SUCCESS , onRecordFound ) ;
185
188
getRequest . addEventListener ( IDB_ERROR , onTxnError ) ;
186
-
189
+
187
190
return ( ) => {
188
191
getRequest . removeEventListener ( IDB_SUCCESS , onRecordFound ) ;
189
192
getRequest . removeEventListener ( IDB_ERROR , onTxnError ) ;
190
193
txn . removeEventListener ( IDB_ERROR , onTxnError ) ;
191
194
}
192
-
195
+
193
196
} ) ;
194
197
} ) ;
195
198
}
196
-
199
+
197
200
executeWrite ( storeName :string , actionType :string , records :any [ ] ) {
198
201
const changes = this . changes ;
199
202
return this . open ( this . _schema . name )
200
203
. mergeMap ( db => {
201
204
return new Observable ( txnObserver => {
202
205
const txn = db . transaction ( [ storeName ] , IDB_TXN_READWRITE ) ;
203
206
const objectStore = txn . objectStore ( storeName ) ;
204
-
207
+
205
208
const onTxnError = ( err ) => txnObserver . error ( err ) ;
206
209
const onTxnComplete = ( ) => txnObserver . complete ( ) ;
207
-
210
+
208
211
txn . addEventListener ( IDB_COMPLETE , onTxnComplete ) ;
209
212
txn . addEventListener ( IDB_ERROR , onTxnError ) ;
210
-
213
+
211
214
const makeRequest = ( record ) => {
212
215
return new Observable ( reqObserver => {
213
216
let req = objectStore [ actionType ] ( record ) ;
@@ -220,11 +223,11 @@ export class Database {
220
223
} ) ;
221
224
} ) ;
222
225
}
223
-
224
- let requestSubscriber = Observable . from ( records )
226
+
227
+ let requestSubscriber = Observable . fromArray ( records )
225
228
. mergeMap ( makeRequest )
226
229
. subscribe ( txnObserver ) ;
227
-
230
+
228
231
return ( ) => {
229
232
requestSubscriber . unsubscribe ( ) ;
230
233
txn . removeEventListener ( IDB_COMPLETE , onTxnComplete ) ;
@@ -233,7 +236,7 @@ export class Database {
233
236
} ) ;
234
237
} ) ;
235
238
}
236
-
239
+
237
240
compare ( a :any , b :any ) :number {
238
241
return this . _idb . cmp ( a , b ) ;
239
242
}
0 commit comments