2023-01-13 07:42:29 -05:00
|
|
|
'use strict'
|
|
|
|
|
|
|
|
const assert = require('check-types').assert
|
|
|
|
|
|
|
|
const AuthorList = require('./author_list')
|
|
|
|
const Change = require('./change')
|
|
|
|
const Operation = require('./operation')
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @typedef {import("./author")} Author
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* A `ChangeRequest` is a list of {@link Operation}s that the server can apply
|
|
|
|
* as a {@link Change}.
|
|
|
|
*
|
|
|
|
* If the change is marked as `untransformable`, then the server will not
|
|
|
|
* attempt to transform it if it is out of date (i.e. if the baseVersion no
|
|
|
|
* longer matches the project's latest version). For example, if the client
|
|
|
|
* needs to ensure that a metadata property is set on exactly one file, it can't
|
|
|
|
* do that reliably if there's a chance that other clients will also change the
|
|
|
|
* metadata at the same time. The expectation is that if the change is rejected,
|
|
|
|
* the client will retry on a later version.
|
|
|
|
*/
|
2023-08-22 10:48:04 -04:00
|
|
|
class ChangeRequest {
|
|
|
|
/**
|
|
|
|
* @param {number} baseVersion
|
|
|
|
* @param {Array.<Operation>} operations
|
|
|
|
* @param {boolean} [untransformable]
|
|
|
|
* @param {number[] | Author[]} [authors]
|
|
|
|
*/
|
|
|
|
constructor(baseVersion, operations, untransformable, authors) {
|
|
|
|
assert.integer(baseVersion, 'bad baseVersion')
|
|
|
|
assert.array.of.object(operations, 'bad operations')
|
|
|
|
assert.maybe.boolean(untransformable, 'ChangeRequest: bad untransformable')
|
|
|
|
// TODO remove authors once we have JWTs working --- pass as parameter to
|
|
|
|
// makeChange instead
|
|
|
|
authors = authors || []
|
2023-01-13 07:42:29 -05:00
|
|
|
|
2023-08-22 10:48:04 -04:00
|
|
|
// check all are the same type
|
|
|
|
AuthorList.assertV1(authors, 'bad authors')
|
2023-01-13 07:42:29 -05:00
|
|
|
|
2023-08-22 10:48:04 -04:00
|
|
|
this.authors = authors
|
|
|
|
this.baseVersion = baseVersion
|
|
|
|
this.operations = operations
|
|
|
|
this.untransformable = untransformable || false
|
|
|
|
}
|
2023-01-13 07:42:29 -05:00
|
|
|
|
2023-08-22 10:48:04 -04:00
|
|
|
/**
|
|
|
|
* For serialization.
|
|
|
|
*
|
|
|
|
* @return {Object}
|
|
|
|
*/
|
|
|
|
toRaw() {
|
|
|
|
function operationToRaw(operation) {
|
|
|
|
return operation.toRaw()
|
|
|
|
}
|
2023-01-13 07:42:29 -05:00
|
|
|
|
2023-08-22 10:48:04 -04:00
|
|
|
return {
|
|
|
|
baseVersion: this.baseVersion,
|
|
|
|
operations: this.operations.map(operationToRaw),
|
|
|
|
untransformable: this.untransformable,
|
|
|
|
authors: this.authors,
|
|
|
|
}
|
2023-01-13 07:42:29 -05:00
|
|
|
}
|
|
|
|
|
2023-08-22 10:48:04 -04:00
|
|
|
static fromRaw(raw) {
|
|
|
|
assert.array.of.object(raw.operations, 'bad raw.operations')
|
|
|
|
return new ChangeRequest(
|
|
|
|
raw.baseVersion,
|
|
|
|
raw.operations.map(Operation.fromRaw),
|
|
|
|
raw.untransformable,
|
|
|
|
raw.authors
|
|
|
|
)
|
2023-01-13 07:42:29 -05:00
|
|
|
}
|
|
|
|
|
2023-08-22 10:48:04 -04:00
|
|
|
getBaseVersion() {
|
|
|
|
return this.baseVersion
|
|
|
|
}
|
2023-01-13 07:42:29 -05:00
|
|
|
|
2023-08-22 10:48:04 -04:00
|
|
|
isUntransformable() {
|
|
|
|
return this.untransformable
|
|
|
|
}
|
2023-01-13 07:42:29 -05:00
|
|
|
|
2023-08-22 10:48:04 -04:00
|
|
|
makeChange(timestamp) {
|
|
|
|
return new Change(this.operations, timestamp, this.authors)
|
|
|
|
}
|
2023-01-13 07:42:29 -05:00
|
|
|
}
|
|
|
|
|
2023-08-22 10:48:04 -04:00
|
|
|
module.exports = ChangeRequest
|