Skip to content

Commit de18109

Browse files
committed
Merge pull request DefinitelyTyped#4185 from dfahlander/master
Added dexie.d.ts
2 parents cc22b15 + 8acdd6f commit de18109

File tree

2 files changed

+576
-0
lines changed

2 files changed

+576
-0
lines changed

dexie/dexie-tests.ts

Lines changed: 256 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,256 @@
1+
/// <reference path="dexie.d.ts" />
2+
3+
import Dexie = require("Dexie");
4+
5+
module Utils {
6+
7+
export class Console {
8+
textarea: HTMLTextAreaElement;
9+
10+
constructor() {
11+
this.textarea = document.createElement('textarea');
12+
}
13+
14+
log(txt: string, type?: string) {
15+
if (type) this.textarea.value += type + " ";
16+
this.textarea.value += txt + "\n";
17+
}
18+
error = function (txt: string) {
19+
this.log(txt, "ERROR!");
20+
}
21+
}
22+
23+
}
24+
25+
module AppDb {
26+
27+
export class AppDatabase extends Dexie {
28+
29+
contacts: Dexie.Table<Contact, number>;
30+
emails: Dexie.Table<IEmailAddress, number>;
31+
phones: Dexie.Table<IPhoneNumber, number>;
32+
33+
constructor() {
34+
35+
super("MyTypeScriptAppDb");
36+
37+
var db = this;
38+
39+
//
40+
// Define tables and indexes
41+
//
42+
db.version(1).stores({
43+
contacts: '++id, first, last',
44+
emails: '++id, contactId, type, email',
45+
phones: '++id, contactId, type, phone',
46+
});
47+
48+
// Let's physically map Contact class to contacts table.
49+
// This will make it possible to call loadEmailsAndPhones()
50+
// directly on retrieved database objects.
51+
db.contacts.mapToClass(Contact);
52+
}
53+
}
54+
55+
/* Just for code completion and compilation - defines
56+
* the interface of objects stored in the emails table.
57+
*/
58+
export interface IEmailAddress {
59+
id?: number;
60+
contactId: number;
61+
type: string;
62+
email: string;
63+
}
64+
65+
/* Just for code completion and compilation - defines
66+
* the interface of objects stored in the phones table.
67+
*/
68+
export interface IPhoneNumber {
69+
id?: number;
70+
contactId: number;
71+
type: string;
72+
phone: string;
73+
}
74+
75+
/* This is a 'physical' class that is mapped to
76+
* the contacts table. We can have methods on it that
77+
* we could call on retrieved database objects.
78+
*/
79+
export class Contact {
80+
id: number;
81+
first: string;
82+
last: string;
83+
emails: IEmailAddress[];
84+
phones: IPhoneNumber[];
85+
86+
constructor(first: string, last: string, id?: number) {
87+
this.first = first;
88+
this.last = last;
89+
if (id) this.id = id;
90+
}
91+
92+
loadEmailsAndPhones() : Dexie.Promise<Contact> {
93+
return Dexie.Promise.all<any>(
94+
db.emails
95+
.where('contactId').equals(this.id)
96+
.toArray(emails => this.emails = emails)
97+
,
98+
db.phones
99+
.where('contactId').equals(this.id)
100+
.toArray(phones => this.phones = phones)
101+
102+
).then(() => this);
103+
}
104+
105+
save() {
106+
return db.transaction('rw', db.contacts, db.emails, db.phones, () => {
107+
Dexie.Promise.all(
108+
// Save existing arrays
109+
Dexie.Promise.all(this.emails.map(email => db.emails.put(email))),
110+
Dexie.Promise.all(this.phones.map(phone => db.phones.put(phone))))
111+
.then(results => {
112+
// Remove items from DB that is was not saved here:
113+
var emailIds = results[0], // array of resulting primary keys
114+
phoneIds = results[1]; // array of resulting primary keys
115+
116+
db.emails.where('contactId').equals(this.id)
117+
.and(email => emailIds.indexOf(email.id) === -1)
118+
.delete();
119+
120+
db.phones.where('contactId').equals(this.id)
121+
.and(phone => phoneIds.indexOf(phone.id) === -1)
122+
.delete();
123+
124+
// At last, save our own properties.
125+
// (Must not do put(this) because we would get
126+
// reduntant emails/phones arrays saved into db)
127+
db.contacts.put(
128+
new Contact(this.first, this.last, this.id))
129+
.then(id => this.id = id);
130+
});
131+
});
132+
}
133+
}
134+
135+
export var db = new AppDatabase();
136+
db.open();
137+
}
138+
139+
140+
import Console = Utils.Console;
141+
import db = AppDb.db;
142+
143+
document.addEventListener('DOMContentLoaded', () => {
144+
145+
// Initialize our Console widget - it will log browser window.
146+
var console = new Console();
147+
document.getElementById('consoleArea').appendChild(console.textarea);
148+
149+
// Test it:
150+
console.log("Hello world!");
151+
152+
// Make sure to never miss any unexpected error:
153+
Dexie.Promise.on.error.subscribe(e => {
154+
// Log any uncatched error:
155+
console.error(e);
156+
});
157+
158+
//
159+
// Let's clear and re-seed the database:
160+
//
161+
clearDatabase()
162+
.then(seedDatabase)
163+
.then(playALittle_add_phone_to_adam)
164+
.then(printContacts);
165+
166+
function clearDatabase() {
167+
console.log("Clearing database...");
168+
return Dexie.Promise.all(
169+
db.contacts.clear(),
170+
db.emails.clear(),
171+
db.phones.clear());
172+
}
173+
174+
function seedDatabase() {
175+
console.log("Seeding database with some contacts...");
176+
return db.transaction('rw', db.contacts, db.emails, db.phones, () => {
177+
// Populate a contact
178+
db.contacts.add(new AppDb.Contact('Arnold', 'Fitzgerald')).then(id => {
179+
// Populate some emails and phone numbers for the contact
180+
db.emails.add({ contactId: id, type: 'home', email: '[email protected]' });
181+
db.emails.add({ contactId: id, type: 'work', email: '[email protected]' });
182+
db.phones.add({ contactId: id, type: 'home', phone: '12345678' });
183+
db.phones.add({ contactId: id, type: 'work', phone: '987654321' });
184+
});
185+
186+
// ... and another one...
187+
db.contacts.add(new AppDb.Contact('Adam', 'Tensta')).then(id => {
188+
// Populate some emails and phone numbers for the contact
189+
db.emails.add({ contactId: id, type: 'home', email: '[email protected]' });
190+
db.phones.add({ contactId: id, type: 'work', phone: '88888888' });
191+
});
192+
});
193+
}
194+
195+
function playALittle_add_phone_to_adam() {
196+
// Now, just to examplify how to use the save() method as an alternative
197+
// to db.phones.add(), we will add yet another phone number
198+
// to an existing contact and then re-save it:
199+
console.log("Playing a little: adding another phone entry for Adam Tensta...");
200+
return db.contacts
201+
.where('last').equals('Tensta').first(c => c.loadEmailsAndPhones())
202+
.then(contact => {
203+
// Also add another phone number to Adam Tensta:
204+
contact.phones.push({
205+
contactId: contact.id,
206+
type: 'custom',
207+
phone: '112'
208+
});
209+
contact.save();
210+
});
211+
}
212+
213+
function printContacts() {
214+
215+
// Now we're gonna list all contacts starting with letter 'A'
216+
// and print them out.
217+
// For each contact, also resolve its collection of
218+
// phone number entries and email addresses by reverse-quering
219+
// the foreign tables.
220+
221+
// For atomicity and speed, use a single transaction for the
222+
// queries to make:
223+
db.transaction('r', [db.contacts, db.phones, db.emails], () => {
224+
225+
// Query some contacts
226+
return db.contacts
227+
.where('first').startsWithIgnoreCase('a')
228+
.sortBy('id')
229+
.then(contacts =>
230+
231+
// Resolve array properties 'emails' and 'phones'
232+
// on each and every contact:
233+
Dexie.Promise.all(
234+
contacts.map(contact =>
235+
contact.loadEmailsAndPhones()))
236+
);
237+
238+
}).then(contacts => {
239+
240+
// Print result
241+
console.log("Database contains the following contacts:");
242+
contacts.forEach(contact => {
243+
console.log(contact.id + ". " + contact.first + " " + contact.last);
244+
console.log(" Phone numbers: ");
245+
contact.phones.forEach(phone => {
246+
console.log(" " + phone.phone + "(" + phone.type + ")");
247+
});
248+
console.log(" Emails: ");
249+
contact.emails.forEach(email => {
250+
console.log(" " + email.email + "(" + email.type + ")");
251+
});
252+
});
253+
});
254+
}
255+
});
256+

0 commit comments

Comments
 (0)