* Commits the changes and sends the Commit to the resource's `/commit` * endpoint. Returns the new Url if succesful, throws an error if things go * wrong. If you don't pass an Agent explicitly, the default Agent of the * Store is used.
(store: Store, agent?: Agent)
| 252 | * Store is used. |
| 253 | */ |
| 254 | async save(store: Store, agent?: Agent): Promise<string> { |
| 255 | if (!agent) { |
| 256 | agent = store.getAgent(); |
| 257 | } |
| 258 | if (!agent) { |
| 259 | throw new Error('No agent has been set or passed, you cannot save.'); |
| 260 | } |
| 261 | // Cloning the CommitBuilder to prevent race conditions, and keeping a back-up of current state for when things go wrong during posting. |
| 262 | const oldCommitBuilder = this.commitBuilder.clone(); |
| 263 | this.commitBuilder = new CommitBuilder(this.getSubject()); |
| 264 | const commit = await oldCommitBuilder.sign(agent.privateKey, agent.subject); |
| 265 | // Add the signature to the list of applied ones, to prevent applying it again when the server |
| 266 | this.appliedCommitSignatures.add(commit.signature); |
| 267 | this.loading = false; |
| 268 | this.new = false; |
| 269 | // Instantly (optimistically) save for local usage |
| 270 | // Doing this early is essential for having a snappy UX in the document editor |
| 271 | store.addResource(this); |
| 272 | // TODO: Check if all required props are there |
| 273 | const endpoint = new URL(this.getSubject()).origin + `/commit`; |
| 274 | try { |
| 275 | this.commitError = null; |
| 276 | await postCommit(commit, endpoint); |
| 277 | return this.getSubject(); |
| 278 | } catch (e) { |
| 279 | // If it fails, revert to the old resource with the old CommitBuilder |
| 280 | this.commitBuilder = oldCommitBuilder; |
| 281 | this.commitError = e; |
| 282 | store.addResource(this); |
| 283 | throw e; |
| 284 | } |
| 285 | } |
| 286 | |
| 287 | /** |
| 288 | * Set a Property, Value combination and perform a validation. Will throw if |
no test coverage detected