@automerge/automerge-repo 1.0.4 → 1.0.6

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.
@@ -80,6 +80,19 @@ export declare class DocHandle<T>//
80
80
  * @returns A set of heads representing the concurrent change that was made.
81
81
  */
82
82
  changeAt(heads: A.Heads, callback: A.ChangeFn<T>, options?: A.ChangeOptions<T>): string[] | undefined;
83
+ /** Merge another document into this document
84
+ *
85
+ * @param otherHandle - the handle of the document to merge into this one
86
+ *
87
+ * @remarks
88
+ * This is a convenience method for
89
+ * `handle.change(doc => A.merge(doc, otherHandle.docSync()))`. Any peers
90
+ * whom we are sharing changes with will be notified of the changes resulting
91
+ * from the merge.
92
+ *
93
+ * @throws if either document is not ready or if `otherHandle` is unavailable (`otherHandle.docSync() === undefined`)
94
+ */
95
+ merge(otherHandle: DocHandle<T>): void;
83
96
  unavailable(): void;
84
97
  /** `request` is called by the repo when the document is not found in storage
85
98
  * @hidden
@@ -1 +1 @@
1
- {"version":3,"file":"DocHandle.d.ts","sourceRoot":"","sources":["../src/DocHandle.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"DocHandle.d.ts","sourceRoot":"","sources":["../src/DocHandle.ts"],"names":[],"mappings":"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"}
package/dist/DocHandle.js CHANGED
@@ -309,6 +309,30 @@ export class DocHandle//
309
309
  });
310
310
  return resultHeads;
311
311
  }
312
+ /** Merge another document into this document
313
+ *
314
+ * @param otherHandle - the handle of the document to merge into this one
315
+ *
316
+ * @remarks
317
+ * This is a convenience method for
318
+ * `handle.change(doc => A.merge(doc, otherHandle.docSync()))`. Any peers
319
+ * whom we are sharing changes with will be notified of the changes resulting
320
+ * from the merge.
321
+ *
322
+ * @throws if either document is not ready or if `otherHandle` is unavailable (`otherHandle.docSync() === undefined`)
323
+ */
324
+ merge(otherHandle) {
325
+ if (!this.isReady() || !otherHandle.isReady()) {
326
+ throw new Error("Both handles must be ready to merge");
327
+ }
328
+ const mergingDoc = otherHandle.docSync();
329
+ if (!mergingDoc) {
330
+ throw new Error("The document to be merged in is null, aborting.");
331
+ }
332
+ this.update(doc => {
333
+ return A.merge(doc, mergingDoc);
334
+ });
335
+ }
312
336
  unavailable() {
313
337
  this.#machine.send(MARK_UNAVAILABLE);
314
338
  }
package/dist/Repo.d.ts CHANGED
@@ -31,6 +31,22 @@ export declare class Repo extends EventEmitter<RepoEvents> {
31
31
  * to advertise interest in the document.
32
32
  */
33
33
  create<T>(): DocHandle<T>;
34
+ /** Create a new DocHandle by cloning the history of an existing DocHandle.
35
+ *
36
+ * @param clonedHandle - The handle to clone
37
+ *
38
+ * @remarks This is a wrapper around the `clone` function in the Automerge library.
39
+ * The new `DocHandle` will have a new URL but will share history with the original,
40
+ * which means that changes made to the cloned handle can be sensibly merged back
41
+ * into the original.
42
+ *
43
+ * Any peers this `Repo` is connected to for whom `sharePolicy` returns `true` will
44
+ * be notified of the newly created DocHandle.
45
+ *
46
+ * @throws if the cloned handle is not yet ready or if
47
+ * `clonedHandle.docSync()` returns `undefined` (i.e. the handle is unavailable).
48
+ */
49
+ clone<T>(clonedHandle: DocHandle<T>): DocHandle<T>;
34
50
  /**
35
51
  * Retrieves a document by id. It gets data from the local system, but also emits a `document`
36
52
  * event to advertise interest in the document.
@@ -1 +1 @@
1
- {"version":3,"file":"Repo.d.ts","sourceRoot":"","sources":["../src/Repo.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AAEhE,OAAO,EAAE,KAAK,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AASlE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAG5C,8FAA8F;AAC9F;;;;;;GAMG;AACH,qBAAa,IAAK,SAAQ,YAAY,CAAC,UAAU,CAAC;;IAGhD,cAAc;IACd,gBAAgB,EAAE,gBAAgB,CAAA;IAClC,cAAc;IACd,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;IAGnC,sDAAsD;IACtD,cAAc;IACd,WAAW,EAAE,WAAW,CAAmB;gBAE/B,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,UAAU;IAuHjE,8CAA8C;IAC9C,IAAI,OAAO,uCAEV;IAED;;;;OAIG;IACH,MAAM,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC;IA0BzB;;;OAGG;IACH,IAAI,CAAC,CAAC;IACJ,+CAA+C;IAC/C,YAAY,EAAE,YAAY,GACzB,SAAS,CAAC,CAAC,CAAC;IAgCf,MAAM;IACJ,6CAA6C;IAC7C,EAAE,EAAE,UAAU,GAAG,YAAY;CAchC;AAED,MAAM,WAAW,UAAU;IACzB,4BAA4B;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAA;IAEf,gDAAgD;IAChD,OAAO,CAAC,EAAE,cAAc,CAAA;IAExB,oDAAoD;IACpD,OAAO,EAAE,cAAc,EAAE,CAAA;IAEzB;;;OAGG;IACH,WAAW,CAAC,EAAE,WAAW,CAAA;CAC1B;AAED;;;;;;;KAOK;AACL,MAAM,MAAM,WAAW,GAAG,CACxB,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,UAAU,KACpB,OAAO,CAAC,OAAO,CAAC,CAAA;AAGrB,MAAM,WAAW,UAAU;IACzB,+CAA+C;IAC/C,QAAQ,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,IAAI,CAAA;IACxC,6BAA6B;IAC7B,iBAAiB,EAAE,CAAC,GAAG,EAAE,qBAAqB,KAAK,IAAI,CAAA;IACvD,4FAA4F;IAC5F,sBAAsB,EAAE,CAAC,GAAG,EAAE,qBAAqB,KAAK,IAAI,CAAA;CAC7D;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,CAAA;IACtB,KAAK,EAAE,OAAO,CAAA;CACf;AAED,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,UAAU,CAAA;CACvB"}
1
+ {"version":3,"file":"Repo.d.ts","sourceRoot":"","sources":["../src/Repo.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AAChE,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAC5D,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAA;AAEhE,OAAO,EAAE,KAAK,YAAY,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,YAAY,CAAA;AASlE,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAA;AAC1C,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAG5C,8FAA8F;AAC9F;;;;;;GAMG;AACH,qBAAa,IAAK,SAAQ,YAAY,CAAC,UAAU,CAAC;;IAGhD,cAAc;IACd,gBAAgB,EAAE,gBAAgB,CAAA;IAClC,cAAc;IACd,gBAAgB,CAAC,EAAE,gBAAgB,CAAA;IAGnC,sDAAsD;IACtD,cAAc;IACd,WAAW,EAAE,WAAW,CAAmB;gBAE/B,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,EAAE,UAAU;IAuHjE,8CAA8C;IAC9C,IAAI,OAAO,uCAEV;IAED;;;;OAIG;IACH,MAAM,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC;IA0BzB;;;;;;;;;;;;;;OAcG;IACH,KAAK,CAAC,CAAC,EAAE,YAAY,EAAE,SAAS,CAAC,CAAC,CAAC;IAuBnC;;;OAGG;IACH,IAAI,CAAC,CAAC;IACJ,+CAA+C;IAC/C,YAAY,EAAE,YAAY,GACzB,SAAS,CAAC,CAAC,CAAC;IAgCf,MAAM;IACJ,6CAA6C;IAC7C,EAAE,EAAE,UAAU,GAAG,YAAY;CAchC;AAED,MAAM,WAAW,UAAU;IACzB,4BAA4B;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAA;IAEf,gDAAgD;IAChD,OAAO,CAAC,EAAE,cAAc,CAAA;IAExB,oDAAoD;IACpD,OAAO,EAAE,cAAc,EAAE,CAAA;IAEzB;;;OAGG;IACH,WAAW,CAAC,EAAE,WAAW,CAAA;CAC1B;AAED;;;;;;;KAOK;AACL,MAAM,MAAM,WAAW,GAAG,CACxB,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,UAAU,KACpB,OAAO,CAAC,OAAO,CAAC,CAAA;AAGrB,MAAM,WAAW,UAAU;IACzB,+CAA+C;IAC/C,QAAQ,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,IAAI,CAAA;IACxC,6BAA6B;IAC7B,iBAAiB,EAAE,CAAC,GAAG,EAAE,qBAAqB,KAAK,IAAI,CAAA;IACvD,4FAA4F;IAC5F,sBAAsB,EAAE,CAAC,GAAG,EAAE,qBAAqB,KAAK,IAAI,CAAA;CAC7D;AAED,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,CAAA;IACtB,KAAK,EAAE,OAAO,CAAA;CACf;AAED,MAAM,WAAW,qBAAqB;IACpC,UAAU,EAAE,UAAU,CAAA;CACvB"}
package/dist/Repo.js CHANGED
@@ -5,6 +5,7 @@ import { CollectionSynchronizer } from "./synchronizer/CollectionSynchronizer.js
5
5
  import { parseAutomergeUrl, generateAutomergeUrl, isValidAutomergeUrl, parseLegacyUUID, } from "./DocUrl.js";
6
6
  import { DocHandle } from "./DocHandle.js";
7
7
  import { EventEmitter } from "eventemitter3";
8
+ import { next as Automerge } from "@automerge/automerge";
8
9
  /** A Repo is a collection of documents with networking, syncing, and storage capabilities. */
9
10
  /** The `Repo` is the main entry point of this library
10
11
  *
@@ -156,6 +157,37 @@ export class Repo extends EventEmitter {
156
157
  this.emit("document", { handle, isNew: true });
157
158
  return handle;
158
159
  }
160
+ /** Create a new DocHandle by cloning the history of an existing DocHandle.
161
+ *
162
+ * @param clonedHandle - The handle to clone
163
+ *
164
+ * @remarks This is a wrapper around the `clone` function in the Automerge library.
165
+ * The new `DocHandle` will have a new URL but will share history with the original,
166
+ * which means that changes made to the cloned handle can be sensibly merged back
167
+ * into the original.
168
+ *
169
+ * Any peers this `Repo` is connected to for whom `sharePolicy` returns `true` will
170
+ * be notified of the newly created DocHandle.
171
+ *
172
+ * @throws if the cloned handle is not yet ready or if
173
+ * `clonedHandle.docSync()` returns `undefined` (i.e. the handle is unavailable).
174
+ */
175
+ clone(clonedHandle) {
176
+ if (!clonedHandle.isReady()) {
177
+ throw new Error(`Cloned handle is not yet in ready state.
178
+ (Try await handle.waitForReady() first.)`);
179
+ }
180
+ const sourceDoc = clonedHandle.docSync();
181
+ if (!sourceDoc) {
182
+ throw new Error("Cloned handle doesn't have a document.");
183
+ }
184
+ const handle = this.create();
185
+ handle.update((doc) => {
186
+ // we replace the document with the new cloned one
187
+ return Automerge.clone(sourceDoc);
188
+ });
189
+ return handle;
190
+ }
159
191
  /**
160
192
  * Retrieves a document by id. It gets data from the local system, but also emits a `document`
161
193
  * event to advertise interest in the document.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@automerge/automerge-repo",
3
- "version": "1.0.4",
3
+ "version": "1.0.6",
4
4
  "description": "A repository object to manage a collection of automerge documents",
5
5
  "repository": "https://github.com/automerge/automerge-repo/tree/master/packages/automerge-repo",
6
6
  "author": "Peter van Hardenberg <pvh@pvh.ca>",
@@ -65,5 +65,5 @@
65
65
  "publishConfig": {
66
66
  "access": "public"
67
67
  },
68
- "gitHead": "17fd5260f9af3e65da636fef084e8c04d6c4bed0"
68
+ "gitHead": "088696831fed48c7a8a88109acd0465222dc8522"
69
69
  }
package/src/DocHandle.ts CHANGED
@@ -28,7 +28,7 @@ import { encode } from "./helpers/cbor.js"
28
28
  * A `DocHandle` represents a document which is being managed by a {@link Repo}.
29
29
  * To obtain `DocHandle` use {@link Repo.find} or {@link Repo.create}.
30
30
  *
31
- * To modify the underlying document use either {@link DocHandle.change} or
31
+ * To modify the underlying document use either {@link DocHandle.change} or
32
32
  * {@link DocHandle.changeAt}. These methods will notify the `Repo` that some
33
33
  * change has occured and the `Repo` will save any new changes to the
34
34
  * attached {@link StorageAdapter} and send sync messages to connected peers.
@@ -321,7 +321,7 @@ export class DocHandle<T> //
321
321
  return this.#doc
322
322
  }
323
323
 
324
- /** `update` is called by the repo when we receive changes from the network
324
+ /** `update` is called by the repo when we receive changes from the network
325
325
  * @hidden
326
326
  * */
327
327
  update(callback: (doc: A.Doc<T>) => A.Doc<T>) {
@@ -373,11 +373,37 @@ export class DocHandle<T> //
373
373
  return resultHeads
374
374
  }
375
375
 
376
+ /** Merge another document into this document
377
+ *
378
+ * @param otherHandle - the handle of the document to merge into this one
379
+ *
380
+ * @remarks
381
+ * This is a convenience method for
382
+ * `handle.change(doc => A.merge(doc, otherHandle.docSync()))`. Any peers
383
+ * whom we are sharing changes with will be notified of the changes resulting
384
+ * from the merge.
385
+ *
386
+ * @throws if either document is not ready or if `otherHandle` is unavailable (`otherHandle.docSync() === undefined`)
387
+ */
388
+ merge(otherHandle: DocHandle<T>) {
389
+ if (!this.isReady() || !otherHandle.isReady()) {
390
+ throw new Error("Both handles must be ready to merge")
391
+ }
392
+ const mergingDoc = otherHandle.docSync()
393
+ if (!mergingDoc) {
394
+ throw new Error("The document to be merged in is null, aborting.")
395
+ }
396
+
397
+ this.update(doc => {
398
+ return A.merge(doc, mergingDoc)
399
+ })
400
+ }
401
+
376
402
  unavailable() {
377
403
  this.#machine.send(MARK_UNAVAILABLE)
378
404
  }
379
405
 
380
- /** `request` is called by the repo when the document is not found in storage
406
+ /** `request` is called by the repo when the document is not found in storage
381
407
  * @hidden
382
408
  * */
383
409
  request() {
package/src/Repo.ts CHANGED
@@ -15,7 +15,7 @@ import {
15
15
 
16
16
  import { DocHandle } from "./DocHandle.js"
17
17
  import { EventEmitter } from "eventemitter3"
18
- import bs58check from "bs58check"
18
+ import { next as Automerge } from "@automerge/automerge"
19
19
 
20
20
  /** A Repo is a collection of documents with networking, syncing, and storage capabilities. */
21
21
  /** The `Repo` is the main entry point of this library
@@ -193,6 +193,44 @@ export class Repo extends EventEmitter<RepoEvents> {
193
193
  return handle
194
194
  }
195
195
 
196
+ /** Create a new DocHandle by cloning the history of an existing DocHandle.
197
+ *
198
+ * @param clonedHandle - The handle to clone
199
+ *
200
+ * @remarks This is a wrapper around the `clone` function in the Automerge library.
201
+ * The new `DocHandle` will have a new URL but will share history with the original,
202
+ * which means that changes made to the cloned handle can be sensibly merged back
203
+ * into the original.
204
+ *
205
+ * Any peers this `Repo` is connected to for whom `sharePolicy` returns `true` will
206
+ * be notified of the newly created DocHandle.
207
+ *
208
+ * @throws if the cloned handle is not yet ready or if
209
+ * `clonedHandle.docSync()` returns `undefined` (i.e. the handle is unavailable).
210
+ */
211
+ clone<T>(clonedHandle: DocHandle<T>) {
212
+ if (!clonedHandle.isReady()) {
213
+ throw new Error(
214
+ `Cloned handle is not yet in ready state.
215
+ (Try await handle.waitForReady() first.)`
216
+ )
217
+ }
218
+
219
+ const sourceDoc = clonedHandle.docSync()
220
+ if (!sourceDoc) {
221
+ throw new Error("Cloned handle doesn't have a document.")
222
+ }
223
+
224
+ const handle = this.create<T>()
225
+
226
+ handle.update((doc: Automerge.Doc<T>) => {
227
+ // we replace the document with the new cloned one
228
+ return Automerge.clone(sourceDoc)
229
+ })
230
+
231
+ return handle
232
+ }
233
+
196
234
  /**
197
235
  * Retrieves a document by id. It gets data from the local system, but also emits a `document`
198
236
  * event to advertise interest in the document.
@@ -267,7 +305,7 @@ export interface RepoConfig {
267
305
  sharePolicy?: SharePolicy
268
306
  }
269
307
 
270
- /** A function that determines whether we should share a document with a peer
308
+ /** A function that determines whether we should share a document with a peer
271
309
  *
272
310
  * @remarks
273
311
  * This function is called by the {@link Repo} every time a new document is created
package/test/Repo.test.ts CHANGED
@@ -93,6 +93,65 @@ describe("Repo", () => {
93
93
  assert.equal(v?.foo, "bar")
94
94
  })
95
95
 
96
+ it("can clone a document", () => {
97
+ const { repo } = setup()
98
+ const handle = repo.create<TestDoc>()
99
+ handle.change(d => {
100
+ d.foo = "bar"
101
+ })
102
+ const handle2 = repo.clone(handle)
103
+ assert.equal(handle2.isReady(), true)
104
+ assert.notEqual(handle.documentId, handle2.documentId)
105
+ assert.deepStrictEqual(handle.docSync(), handle2.docSync())
106
+ assert.deepStrictEqual(handle2.docSync(), { foo: "bar" })
107
+ })
108
+
109
+ it("the cloned documents are distinct", () => {
110
+ const { repo } = setup()
111
+ const handle = repo.create<TestDoc>()
112
+ handle.change(d => {
113
+ d.foo = "bar"
114
+ })
115
+ const handle2 = repo.clone(handle)
116
+
117
+ handle.change(d => {
118
+ d.bar = "bif"
119
+ })
120
+ handle2.change(d => {
121
+ d.baz = "baz"
122
+ })
123
+
124
+ assert.notDeepStrictEqual(handle.docSync(), handle2.docSync())
125
+ assert.deepStrictEqual(handle.docSync(), { foo: "bar", bar: "bif" })
126
+ assert.deepStrictEqual(handle2.docSync(), { foo: "bar", baz: "baz" })
127
+ })
128
+
129
+ it("the cloned documents can merge", () => {
130
+ const { repo } = setup()
131
+ const handle = repo.create<TestDoc>()
132
+ handle.change(d => {
133
+ d.foo = "bar"
134
+ })
135
+ const handle2 = repo.clone(handle)
136
+
137
+ handle.change(d => {
138
+ d.bar = "bif"
139
+ })
140
+ handle2.change(d => {
141
+ d.baz = "baz"
142
+ })
143
+
144
+ handle.merge(handle2)
145
+
146
+ assert.deepStrictEqual(handle.docSync(), {
147
+ foo: "bar",
148
+ bar: "bif",
149
+ baz: "baz",
150
+ })
151
+ // only the one handle should be changed
152
+ assert.deepStrictEqual(handle2.docSync(), { foo: "bar", baz: "baz" })
153
+ })
154
+
96
155
  it("throws an error if we try to find a handle with an invalid AutomergeUrl", async () => {
97
156
  const { repo } = setup()
98
157
  try {
@@ -726,5 +785,51 @@ describe("Repo", () => {
726
785
  assert.deepStrictEqual(bob.message, message)
727
786
  assert.deepStrictEqual(charlie.message, message)
728
787
  })
788
+
789
+ it("notifies peers when a document is cloned", async () => {
790
+ const { bobRepo, charlieRepo } = await setupMeshNetwork()
791
+
792
+ // pause to let the network set up
793
+ await pause(50)
794
+
795
+ const handle = bobRepo.create<TestDoc>()
796
+ handle.change(d => { d.foo = "bar" })
797
+ const handle2 = bobRepo.clone(handle)
798
+
799
+ // pause to let the sync happen
800
+ await pause(50)
801
+
802
+ const charlieHandle = charlieRepo.find(handle2.url)
803
+ await charlieHandle.doc()
804
+ assert.deepStrictEqual(charlieHandle.docSync(), { foo: "bar" })
805
+ })
806
+
807
+ it("notifies peers when a document is merged", async () => {
808
+ const { bobRepo, charlieRepo } = await setupMeshNetwork()
809
+
810
+ // pause to let the network set up
811
+ await pause(50)
812
+
813
+ const handle = bobRepo.create<TestDoc>()
814
+ handle.change(d => { d.foo = "bar" })
815
+ const handle2 = bobRepo.clone(handle)
816
+
817
+ // pause to let the sync happen
818
+ await pause(50)
819
+
820
+ const charlieHandle = charlieRepo.find(handle2.url)
821
+ await charlieHandle.doc()
822
+ assert.deepStrictEqual(charlieHandle.docSync(), { foo: "bar" })
823
+
824
+ // now make a change to doc2 on bobs side and merge it into doc1
825
+ handle2.change(d => { d.foo = "baz" })
826
+ handle.merge(handle2)
827
+
828
+ // wait for the network to do it's thang
829
+ await pause(50)
830
+
831
+ await charlieHandle.doc()
832
+ assert.deepStrictEqual(charlieHandle.docSync(), { foo: "baz" })
833
+ })
729
834
  })
730
835
  })
package/test/types.ts CHANGED
@@ -1,3 +1,5 @@
1
1
  export interface TestDoc {
2
2
  foo: string
3
+ bar?: string
4
+ baz?: string
3
5
  }