From 958ccb60c6528d0fb4c4ebe740d85050eec63060 Mon Sep 17 00:00:00 2001 From: Max Battcher Date: Mon, 2 Oct 2017 23:40:05 -0400 Subject: [PATCH] Simplify PouchDB Attachments interfaces (#20213) Make a cleaner separation between Stub attachments and non-Stub attachments (here called FullAttachment). New Attachment is then the union type of StubAttachment and FullAttachment. Renamed the previous Attachment to AttachmentData to better reflect what's it purpose is. (Would love to make it more generic, but there's not a great way to key off of `{ attachment: true, binary: true }` in the options stacks right now.) Remove PutAttachment because it now better handled by FullAttachment. Furthermore, you can db.put StubAttachments when round-tripping documents, so PutAttachment was too strict. Added simple round-trip tests to avoid that strictness problem moving forward. --- types/pouchdb-core/index.d.ts | 62 ++++++++++++++++-------- types/pouchdb-core/pouchdb-core-tests.ts | 20 ++++++++ 2 files changed, 62 insertions(+), 20 deletions(-) diff --git a/types/pouchdb-core/index.d.ts b/types/pouchdb-core/index.d.ts index bc5cb66ce9..4314644b58 100644 --- a/types/pouchdb-core/index.d.ts +++ b/types/pouchdb-core/index.d.ts @@ -107,7 +107,7 @@ declare namespace PouchDB { type AttachmentId = string; type RevisionId = string; type Availability = 'available' | 'compacted' | 'not compacted' | 'missing'; - type Attachment = string | Blob | Buffer; + type AttachmentData = string | Blob | Buffer; interface Options { ajax?: Configuration.RemoteRequesterConfiguration; @@ -178,28 +178,55 @@ declare namespace PouchDB { _attachments?: Attachments; } - interface AttachmentResponse { + /** + * Stub attachments are returned by PouchDB by default (attachments option set to false) + */ + interface StubAttachment { + /** + * Mime type of the attachment + */ content_type: string; - /** MD5 hash, starts with "md5-" prefix */ + /** + * Database digest of the attachment + */ digest: string; - /** Only present if `attachments` was `false`. */ - stub?: boolean; + /** + * Attachment is a stub + */ + stub: true; - /** Only present if `attachments` was `false`. */ - length?: number; + /** + * Length of the attachment + */ + length: number; + } + + /** + * Full attachments are used to create new attachments or returned when the attachments option + * is true. + */ + interface FullAttachment { + /** + * Mime type of the attachment + */ + content_type: string; + + /** MD5 hash, starts with "md5-" prefix; populated by PouchDB for new attachments */ + digest?: string; /** - * Only present if `attachments` was `true`. * {string} if `binary` was `false` * {Blob|Buffer} if `binary` was `true` */ - data?: Attachment; + data: AttachmentData; } + type Attachment = StubAttachment | FullAttachment; + interface Attachments { - [attachmentId: string]: AttachmentResponse; + [attachmentId: string]: Attachment; } type NewDocument = Content; @@ -217,18 +244,13 @@ declare namespace PouchDB { /** You can update an existing doc using _rev */ _rev?: RevisionId; - _attachments?: {[attachmentId: string]: PutAttachment}; + _attachments?: Attachments; }; type PutDocument = PostDocument & ChangesMeta & { _id?: DocumentId; }; - interface PutAttachment { - content_type: string; - data: Attachment; - } - interface AllDocsOptions extends Options { /** Include attachment data for each document. * @@ -725,7 +747,7 @@ declare namespace PouchDB { putAttachment(docId: Core.DocumentId, attachmentId: Core.AttachmentId, rev: Core.RevisionId, - attachment: Core.Attachment, + attachment: Core.AttachmentData, type: string, callback: Core.Callback): void; @@ -737,7 +759,7 @@ declare namespace PouchDB { putAttachment(docId: Core.DocumentId, attachmentId: Core.AttachmentId, rev: Core.RevisionId, - attachment: Core.Attachment, + attachment: Core.AttachmentData, type: string): Promise; /** @@ -747,7 +769,7 @@ declare namespace PouchDB { */ putAttachment(docId: Core.DocumentId, attachmentId: Core.AttachmentId, - attachment: Core.Attachment, + attachment: Core.AttachmentData, type: string, callback: Core.Callback): void; @@ -758,7 +780,7 @@ declare namespace PouchDB { */ putAttachment(docId: Core.DocumentId, attachmentId: Core.AttachmentId, - attachment: Core.Attachment, + attachment: Core.AttachmentData, type: string): Promise; /** Get attachment data */ diff --git a/types/pouchdb-core/pouchdb-core-tests.ts b/types/pouchdb-core/pouchdb-core-tests.ts index 95e98fb2ad..523eed7d04 100644 --- a/types/pouchdb-core/pouchdb-core-tests.ts +++ b/types/pouchdb-core/pouchdb-core-tests.ts @@ -122,6 +122,9 @@ function testBasics() { db.info((error, result) => { }); + // "Round-trippable": can put back a document from get + db.get('id').then(doc => db.put(doc)); + PouchDB.debug.enable('*'); } @@ -236,11 +239,28 @@ function heterogeneousGenericsDatabase(db: PouchDB.Database) { thud: boolean; } + // Attachment test + db.put({ + _attachments: { + ['meme.gif']: { + content_type: 'image/gif', + data: new Blob(['fake example']) + } + }, + meow: 'roar' + }); + db.allDocs({ startkey: 'cat/', endkey: 'cat/\uffff', include_docs: true }) .then(cats => { for (const row of cats.rows) { if (row.doc) { row.doc.meow; // $ExpectType string + + // Round-trip test + db.put(row.doc); + db.put(row.doc); + // Generic strictness test + db.put(row.doc); // $ExpectError } } });