@aerogear/apollo-voyager-conflicts
Advanced tools
Comparing version 0.1.0-alpha to 0.2.7-rc1
@@ -0,1 +1,4 @@ | ||
import { ConflictLogger } from './ConflictLogger'; | ||
import { ConflictResolution } from './ConflictResolution'; | ||
import { ConflictResolutionStrategy } from './ConflictResolutionStrategy'; | ||
import { ObjectStateData } from './ObjectStateData'; | ||
@@ -11,11 +14,30 @@ /** | ||
* | ||
* @param serverData the data currently on the server | ||
* @param clientData the data the client wishes to perform some mutation with | ||
* @param serverState the data currently on the server | ||
* @param clientState the data the client wishes to perform some mutation with | ||
*/ | ||
hasConflict(serverData: ObjectStateData, clientData: ObjectStateData): boolean; | ||
hasConflict(serverState: ObjectStateData, clientState: ObjectStateData): boolean; | ||
/** | ||
* | ||
* @param currentObjectState the object wish you would like to progress to its next state | ||
* @param objectState the object wish you would like to progress to its next state | ||
*/ | ||
nextState(currentObjectState: ObjectStateData): ObjectStateData; | ||
nextState(objectState: ObjectStateData): ObjectStateData; | ||
/** | ||
* | ||
* @param serverState the current state of the object on the server | ||
* @param clientState the state of the object the client wishes to perform some mutation with | ||
* @param baseState the base object state that the client state is based off. | ||
*/ | ||
resolveOnClient(serverState: ObjectStateData, clientState: ObjectStateData): ConflictResolution; | ||
/** | ||
* | ||
* @param serverState the current state of the object on the server | ||
* @param clientState the state of the object the client wishes to perform some mutation with | ||
* @param baseState the base object state that the client state is based off. | ||
*/ | ||
resolveOnServer(strategy: ConflictResolutionStrategy, serverState: ObjectStateData, clientState: ObjectStateData, baseState?: ObjectStateData): Promise<ConflictResolution>; | ||
/** | ||
* Enable logging for conflict resolution package | ||
* @param logger - logger implementation | ||
*/ | ||
enableLogging(logger: ConflictLogger): void; | ||
} |
@@ -6,11 +6,11 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
__export(require("./api/ObjectConflictError")); | ||
__export(require("./api/ConflictResolution")); | ||
// State implementations | ||
__export(require("./states/VersionedObjectState")); | ||
__export(require("./states/HashObjectState")); | ||
// Strategy implementations | ||
__export(require("./strategies")); | ||
// Default API state handler | ||
var VersionedObjectState_1 = require("./states/VersionedObjectState"); | ||
exports.conflictHandler = VersionedObjectState_1.versionStateHandler; | ||
// Conflict handlers | ||
__export(require("./conflictHandlers/handleConflictOnClient")); | ||
//# sourceMappingURL=index.js.map |
@@ -0,21 +1,18 @@ | ||
import { ConflictLogger } from '../api/ConflictLogger'; | ||
import { ConflictResolution } from '../api/ConflictResolution'; | ||
import { ConflictResolutionStrategy } from '../api/ConflictResolutionStrategy'; | ||
import { ObjectState } from '../api/ObjectState'; | ||
import { ObjectStateData } from '../api/ObjectStateData'; | ||
/** | ||
* Object state manager using a hash field on object | ||
* Detects conflicts and allows moving to next state using the hash field of the object | ||
* | ||
* HashObjectState requires GraphQL types to contain hash field. | ||
* For example: | ||
* | ||
* type User { | ||
* id: ID! | ||
* hash: String | ||
* } | ||
* Object state manager using a hashing method provided by user | ||
*/ | ||
export declare class HashObjectState implements ObjectState { | ||
private hash; | ||
private logger; | ||
private hash; | ||
constructor(hashImpl: (object: any) => string); | ||
hasConflict(serverData: ObjectStateData, clientData: ObjectStateData): boolean; | ||
nextState(currentObjectState: ObjectStateData): any; | ||
resolveOnClient(serverState: ObjectStateData, clientState: ObjectStateData): ConflictResolution; | ||
resolveOnServer(strategy: ConflictResolutionStrategy, serverState: ObjectStateData, clientState: ObjectStateData, baseState?: ObjectStateData): Promise<ConflictResolution>; | ||
enableLogging(logger: ConflictLogger): void; | ||
} |
"use strict"; | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; | ||
result["default"] = mod; | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const debug = __importStar(require("debug")); | ||
const constants_1 = require("../constants"); | ||
const ConflictResolution_1 = require("../api/ConflictResolution"); | ||
/** | ||
* Object state manager using a hash field on object | ||
* Detects conflicts and allows moving to next state using the hash field of the object | ||
* | ||
* HashObjectState requires GraphQL types to contain hash field. | ||
* For example: | ||
* | ||
* type User { | ||
* id: ID! | ||
* hash: String | ||
* } | ||
* Object state manager using a hashing method provided by user | ||
*/ | ||
class HashObjectState { | ||
constructor(hashImpl) { | ||
this.logger = debug.default(constants_1.CONFLICT_LOGGER); | ||
this.hash = hashImpl; | ||
} | ||
hasConflict(serverData, clientData) { | ||
if (serverData.hash && clientData.hash) { | ||
if (serverData.hash !== clientData.hash) { | ||
this.logger(`Conflict when saving data. current: ${serverData}, client: ${clientData}`); | ||
return true; | ||
if (this.hash(serverData) !== this.hash(clientData)) { | ||
if (this.logger) { | ||
this.logger.info(`Conflict when saving data. | ||
current: ${JSON.stringify(serverData)}, | ||
client: ${JSON.stringify(clientData)}`); | ||
} | ||
return true; | ||
} | ||
@@ -39,8 +23,21 @@ return false; | ||
nextState(currentObjectState) { | ||
this.logger(`Moving object to next state, ${currentObjectState}`); | ||
currentObjectState.hash = this.hash(currentObjectState); | ||
// Hash can be calculated at any time and it is not added to object | ||
return currentObjectState; | ||
} | ||
resolveOnClient(serverState, clientState) { | ||
return new ConflictResolution_1.ConflictResolution(false, serverState, clientState); | ||
} | ||
async resolveOnServer(strategy, serverState, clientState, baseState) { | ||
let resolvedState = strategy(serverState, clientState, baseState); | ||
if (resolvedState instanceof Promise) { | ||
resolvedState = await resolvedState; | ||
} | ||
resolvedState = this.nextState(resolvedState); | ||
return new ConflictResolution_1.ConflictResolution(true, resolvedState, clientState, baseState); | ||
} | ||
enableLogging(logger) { | ||
this.logger = logger; | ||
} | ||
} | ||
exports.HashObjectState = HashObjectState; | ||
//# sourceMappingURL=HashObjectState.js.map |
@@ -0,1 +1,4 @@ | ||
import { ConflictLogger } from '../api/ConflictLogger'; | ||
import { ConflictResolution } from '../api/ConflictResolution'; | ||
import { ConflictResolutionStrategy } from '../api/ConflictResolutionStrategy'; | ||
import { ObjectState } from '../api/ObjectState'; | ||
@@ -19,2 +22,5 @@ import { ObjectStateData } from '../api/ObjectStateData'; | ||
nextState(currentObjectState: ObjectStateData): any; | ||
resolveOnClient(serverState: ObjectStateData, clientState: ObjectStateData): ConflictResolution; | ||
resolveOnServer(strategy: ConflictResolutionStrategy, serverState: ObjectStateData, clientState: ObjectStateData, baseState?: ObjectStateData): Promise<ConflictResolution>; | ||
enableLogging(logger: ConflictLogger): void; | ||
} | ||
@@ -21,0 +27,0 @@ /** |
"use strict"; | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (Object.hasOwnProperty.call(mod, k)) result[k] = mod[k]; | ||
result["default"] = mod; | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const debug = __importStar(require("debug")); | ||
const constants_1 = require("../constants"); | ||
const ConflictResolution_1 = require("../api/ConflictResolution"); | ||
/** | ||
@@ -25,19 +17,43 @@ * Object state manager using a version field | ||
class VersionedObjectState { | ||
constructor() { | ||
this.logger = debug.default(constants_1.CONFLICT_LOGGER); | ||
} | ||
hasConflict(serverData, clientData) { | ||
if (serverData.version && clientData.version) { | ||
if (serverData.version !== clientData.version) { | ||
this.logger(`Conflict when saving data. current: ${serverData}, client: ${clientData}`); | ||
if (this.logger) { | ||
this.logger.info(`Conflict when saving data. | ||
current: ${JSON.stringify(serverData)}, | ||
client: ${JSON.stringify(clientData)}`); | ||
} | ||
return true; | ||
} | ||
} | ||
else if (this.logger) { | ||
this.logger.info(`Supplied object is missing version field required to determine conflict | ||
server: ${JSON.stringify(serverData)} | ||
client: ${JSON.stringify(clientData)}`); | ||
} | ||
return false; | ||
} | ||
nextState(currentObjectState) { | ||
this.logger(`Moving object to next state, ${currentObjectState}`); | ||
if (this.logger) { | ||
this.logger.info(`Moving object to next state, | ||
${JSON.stringify(currentObjectState)}`); | ||
} | ||
currentObjectState.version = currentObjectState.version + 1; | ||
return currentObjectState; | ||
} | ||
resolveOnClient(serverState, clientState) { | ||
return new ConflictResolution_1.ConflictResolution(false, serverState, clientState); | ||
} | ||
async resolveOnServer(strategy, serverState, clientState, baseState) { | ||
let resolvedState = strategy(serverState, clientState, baseState); | ||
if (resolvedState instanceof Promise) { | ||
resolvedState = await resolvedState; | ||
} | ||
resolvedState.version = serverState.version; | ||
resolvedState = this.nextState(resolvedState); | ||
return new ConflictResolution_1.ConflictResolution(true, resolvedState, clientState, baseState); | ||
} | ||
enableLogging(logger) { | ||
this.logger = logger; | ||
} | ||
} | ||
@@ -44,0 +60,0 @@ exports.VersionedObjectState = VersionedObjectState; |
{ | ||
"name": "@aerogear/apollo-voyager-conflicts", | ||
"version": "0.1.0-alpha", | ||
"version": "0.2.7-rc1", | ||
"description": "A package to provide conflict handler framework for GraphQL server", | ||
@@ -25,3 +25,2 @@ "main": "dist/index.js", | ||
"@types/chai": "^4.1.3", | ||
"@types/debug": "0.0.31", | ||
"ava": "1.0.0-rc.2", | ||
@@ -33,5 +32,2 @@ "chai": "^4.1.2", | ||
}, | ||
"dependencies": { | ||
"debug": "^4.1.0" | ||
}, | ||
"publishConfig": { | ||
@@ -38,0 +34,0 @@ "access": "public" |
@@ -0,1 +1,4 @@ | ||
import { ConflictLogger } from './ConflictLogger' | ||
import { ConflictResolution } from './ConflictResolution' | ||
import { ConflictResolutionStrategy } from './ConflictResolutionStrategy' | ||
import { ObjectStateData } from './ObjectStateData' | ||
@@ -13,12 +16,34 @@ | ||
* | ||
* @param serverData the data currently on the server | ||
* @param clientData the data the client wishes to perform some mutation with | ||
* @param serverState the data currently on the server | ||
* @param clientState the data the client wishes to perform some mutation with | ||
*/ | ||
hasConflict(serverData: ObjectStateData, clientData: ObjectStateData): boolean | ||
hasConflict(serverState: ObjectStateData, clientState: ObjectStateData): boolean | ||
/** | ||
* | ||
* @param currentObjectState the object wish you would like to progress to its next state | ||
* @param objectState the object wish you would like to progress to its next state | ||
*/ | ||
nextState(currentObjectState: ObjectStateData): ObjectStateData | ||
nextState(objectState: ObjectStateData): ObjectStateData | ||
/** | ||
* | ||
* @param serverState the current state of the object on the server | ||
* @param clientState the state of the object the client wishes to perform some mutation with | ||
* @param baseState the base object state that the client state is based off. | ||
*/ | ||
resolveOnClient(serverState: ObjectStateData, clientState: ObjectStateData): ConflictResolution | ||
/** | ||
* | ||
* @param serverState the current state of the object on the server | ||
* @param clientState the state of the object the client wishes to perform some mutation with | ||
* @param baseState the base object state that the client state is based off. | ||
*/ | ||
resolveOnServer (strategy: ConflictResolutionStrategy, serverState: ObjectStateData, clientState: ObjectStateData, baseState?: ObjectStateData): Promise<ConflictResolution> | ||
/** | ||
* Enable logging for conflict resolution package | ||
* @param logger - logger implementation | ||
*/ | ||
enableLogging(logger: ConflictLogger): void | ||
} |
// Conflict api | ||
export * from './api/ObjectState' | ||
export * from './api/ObjectConflictError' | ||
export * from './api/ConflictResolution' | ||
export * from './api/ObjectStateData' | ||
export * from './api/ConflictLogger' | ||
@@ -9,7 +10,8 @@ // State implementations | ||
export * from './states/HashObjectState' | ||
// Strategy implementations | ||
export * from './strategies' | ||
// Default API state handler | ||
export { versionStateHandler as conflictHandler } | ||
from './states/VersionedObjectState' | ||
// Conflict handlers | ||
export * from './conflictHandlers/handleConflictOnClient' |
@@ -1,21 +0,13 @@ | ||
import * as debug from 'debug' | ||
import { ConflictLogger } from '../api/ConflictLogger' | ||
import { ConflictResolution } from '../api/ConflictResolution' | ||
import { ConflictResolutionStrategy } from '../api/ConflictResolutionStrategy' | ||
import { ObjectState } from '../api/ObjectState' | ||
import { ObjectStateData } from '../api/ObjectStateData' | ||
import { CONFLICT_LOGGER } from '../constants' | ||
/** | ||
* Object state manager using a hash field on object | ||
* Detects conflicts and allows moving to next state using the hash field of the object | ||
* | ||
* HashObjectState requires GraphQL types to contain hash field. | ||
* For example: | ||
* | ||
* type User { | ||
* id: ID! | ||
* hash: String | ||
* } | ||
* Object state manager using a hashing method provided by user | ||
*/ | ||
export class HashObjectState implements ObjectState { | ||
private logger = debug.default(CONFLICT_LOGGER) | ||
private hash: (object: any) => string | ||
private logger: ConflictLogger | undefined | ||
@@ -27,8 +19,9 @@ constructor(hashImpl: (object: any) => string) { | ||
public hasConflict(serverData: ObjectStateData, clientData: ObjectStateData) { | ||
if (serverData.hash && clientData.hash) { | ||
if (serverData.hash !== clientData.hash) { | ||
this.logger(`Conflict when saving data. current: ${serverData}, client: ${clientData}`) | ||
return true | ||
if (this.hash(serverData) !== this.hash(clientData)) { | ||
if (this.logger) { | ||
this.logger.info(`Conflict when saving data. | ||
current: ${ JSON.stringify(serverData)}, | ||
client: ${JSON.stringify(clientData)}`) | ||
} | ||
return true | ||
} | ||
@@ -39,6 +32,26 @@ return false | ||
public nextState(currentObjectState: ObjectStateData) { | ||
this.logger(`Moving object to next state, ${currentObjectState}`) | ||
currentObjectState.hash = this.hash(currentObjectState) | ||
// Hash can be calculated at any time and it is not added to object | ||
return currentObjectState | ||
} | ||
public resolveOnClient(serverState: ObjectStateData, clientState: ObjectStateData) { | ||
return new ConflictResolution(false, serverState, clientState) | ||
} | ||
public async resolveOnServer(strategy: ConflictResolutionStrategy, serverState: ObjectStateData, clientState: ObjectStateData, baseState?: ObjectStateData) { | ||
let resolvedState = strategy(serverState, clientState, baseState) | ||
if (resolvedState instanceof Promise) { | ||
resolvedState = await resolvedState | ||
} | ||
resolvedState = this.nextState(resolvedState) | ||
return new ConflictResolution(true, resolvedState, clientState, baseState) | ||
} | ||
public enableLogging(logger: ConflictLogger): void { | ||
this.logger = logger | ||
} | ||
} |
@@ -1,5 +0,6 @@ | ||
import * as debug from 'debug' | ||
import { ConflictLogger } from '../api/ConflictLogger' | ||
import { ConflictResolution } from '../api/ConflictResolution' | ||
import { ConflictResolutionStrategy } from '../api/ConflictResolutionStrategy' | ||
import { ObjectState } from '../api/ObjectState' | ||
import { ObjectStateData } from '../api/ObjectStateData' | ||
import { CONFLICT_LOGGER } from '../constants' | ||
@@ -19,3 +20,3 @@ /** | ||
export class VersionedObjectState implements ObjectState { | ||
private logger = debug.default(CONFLICT_LOGGER) | ||
private logger: ConflictLogger | undefined | ||
@@ -25,5 +26,14 @@ public hasConflict(serverData: ObjectStateData, clientData: ObjectStateData) { | ||
if (serverData.version !== clientData.version) { | ||
this.logger(`Conflict when saving data. current: ${serverData}, client: ${clientData}`) | ||
if (this.logger) { | ||
this.logger.info(`Conflict when saving data. | ||
current: ${ JSON.stringify(serverData)}, | ||
client: ${JSON.stringify(clientData)}`) | ||
} | ||
return true | ||
} | ||
} else if (this.logger) { | ||
this.logger.info( | ||
`Supplied object is missing version field required to determine conflict | ||
server: ${JSON.stringify(serverData)} | ||
client: ${JSON.stringify(clientData)}`) | ||
} | ||
@@ -34,6 +44,30 @@ return false | ||
public nextState(currentObjectState: ObjectStateData) { | ||
this.logger(`Moving object to next state, ${currentObjectState}`) | ||
if (this.logger) { | ||
this.logger.info(`Moving object to next state, | ||
${JSON.stringify(currentObjectState)}`) | ||
} | ||
currentObjectState.version = currentObjectState.version + 1 | ||
return currentObjectState | ||
} | ||
public resolveOnClient(serverState: ObjectStateData, clientState: ObjectStateData) { | ||
return new ConflictResolution(false, serverState, clientState) | ||
} | ||
public async resolveOnServer(strategy: ConflictResolutionStrategy, serverState: ObjectStateData, clientState: ObjectStateData, baseState?: ObjectStateData) { | ||
let resolvedState = strategy(serverState, clientState, baseState) | ||
if (resolvedState instanceof Promise) { | ||
resolvedState = await resolvedState | ||
} | ||
resolvedState.version = serverState.version | ||
resolvedState = this.nextState(resolvedState) | ||
return new ConflictResolution(true, resolvedState, clientState, baseState) | ||
} | ||
public enableLogging(logger: ConflictLogger): void { | ||
this.logger = logger | ||
} | ||
} | ||
@@ -40,0 +74,0 @@ |
import test from 'ava' | ||
import { VersionedObjectState } from '../src' | ||
import { VersionedObjectState, ObjectStateData } from '../src' | ||
import { ObjectConflictError } from '../src/api/ConflictResolution' | ||
import { strategies } from '../src/strategies' | ||
@@ -19,7 +21,213 @@ test('With conflict', (t) => { | ||
test('Next state ', (t) => { | ||
test('Missing version', (t) => { | ||
const objectState = new VersionedObjectState() | ||
const serverData = { name: 'AeroGear'} | ||
const clientData = { name: 'AeroGear', version: 1 } | ||
t.deepEqual(objectState.hasConflict(serverData, clientData), false) | ||
}) | ||
test('Next state ', async (t) => { | ||
const serverData = { name: 'AeroGear', version: 1 } | ||
const objectState = new VersionedObjectState() | ||
objectState.nextState(serverData) | ||
t.deepEqual(serverData.version, 2) | ||
const next = await objectState.nextState(serverData) | ||
t.deepEqual(next.version, 2) | ||
}) | ||
test('resolveOnClient returns the expected conflict payload for the client', (t) => { | ||
const serverState = { name: 'AeroGear', version: 2 } | ||
const clientState = { name: 'AeroGear Client', version: 1 } | ||
const objectState = new VersionedObjectState() | ||
const resolution = objectState.resolveOnClient(serverState, clientState) | ||
const expected = { | ||
payload: new ObjectConflictError({ | ||
serverState, | ||
clientState, | ||
resolvedOnServer: false | ||
}) | ||
} | ||
t.falsy(resolution.resolvedState) | ||
t.truthy(resolution.payload) | ||
t.deepEqual(resolution.payload, expected.payload) | ||
}) | ||
test('resolveOnServer works with the client wins strategy', async (t) => { | ||
const serverState = { name: 'AeroGear', version: 2 } | ||
const clientState = { name: 'Client', version: 1 } | ||
const objectState = new VersionedObjectState() | ||
const strategy = strategies.clientWins | ||
const resolution = await objectState.resolveOnServer(strategy, serverState, clientState) | ||
const expectedResolvedState = { | ||
name: 'Client' , | ||
version: 3 | ||
} | ||
const expected = { | ||
resolvedState: expectedResolvedState, | ||
payload: new ObjectConflictError({ | ||
serverState: expectedResolvedState, | ||
clientState, | ||
resolvedOnServer: true | ||
}) | ||
} | ||
t.truthy(resolution.resolvedState) | ||
t.truthy(resolution.payload) | ||
t.deepEqual(resolution.resolvedState, expected.resolvedState) | ||
t.deepEqual(resolution.payload, expected.payload) | ||
}) | ||
test('resolveOnServer works with the server wins strategy', async (t) => { | ||
const serverState = { name: 'AeroGear', version: 2 } | ||
const clientState = { name: 'Client', version: 1 } | ||
const objectState = new VersionedObjectState() | ||
const strategy = strategies.serverWins | ||
const resolution = await objectState.resolveOnServer(strategy, serverState, clientState) | ||
const expectedResolvedState = { | ||
name: 'AeroGear' , | ||
version: 3 | ||
} | ||
const expected = { | ||
resolvedState: expectedResolvedState, | ||
payload: new ObjectConflictError({ | ||
serverState: expectedResolvedState, | ||
clientState, | ||
resolvedOnServer: true | ||
}) | ||
} | ||
t.truthy(resolution.resolvedState) | ||
t.truthy(resolution.payload) | ||
t.deepEqual(resolution.resolvedState, expected.resolvedState) | ||
t.deepEqual(resolution.payload, expected.payload) | ||
}) | ||
test('resolveOnServer resolves the data using a custom handler', async (t) => { | ||
const serverState = { name: 'AeroGear', version: 2 } | ||
const clientState = { name: 'Client', version: 1 } | ||
const objectState = new VersionedObjectState() | ||
function customStrategy(serverState: ObjectStateData, clientState: ObjectStateData) { | ||
return { | ||
name: `${serverState.name} ${clientState.name}` | ||
} | ||
} | ||
const resolution = await objectState.resolveOnServer(customStrategy, serverState, clientState) | ||
const expectedResolvedState = { | ||
name: 'AeroGear Client' , | ||
version: 3 | ||
} | ||
const expected = { | ||
resolvedState: expectedResolvedState, | ||
payload: new ObjectConflictError({ | ||
serverState: expectedResolvedState, | ||
clientState, | ||
resolvedOnServer: true | ||
}) | ||
} | ||
t.truthy(resolution.resolvedState) | ||
t.truthy(resolution.payload) | ||
t.deepEqual(resolution.resolvedState, expected.resolvedState) | ||
t.deepEqual(resolution.payload, expected.payload) | ||
}) | ||
test('resolveOnServer applies the correct version number to resolvedState', async (t) => { | ||
const serverState = { name: 'AeroGear', version: 2 } | ||
const clientState = { name: 'Client', version: 1 } | ||
const objectState = new VersionedObjectState() | ||
function customStrategy(serverState: ObjectStateData, clientState: ObjectStateData) { | ||
return { | ||
name: `${serverState.name} ${clientState.name}`, | ||
version: 50 // this gets overwritten with the correct version | ||
} | ||
} | ||
const resolution = await objectState.resolveOnServer(customStrategy, serverState, clientState) | ||
const expectedResolvedState = { | ||
name: 'AeroGear Client' , | ||
version: 3 | ||
} | ||
const expected = { | ||
resolvedState: expectedResolvedState, | ||
payload: new ObjectConflictError({ | ||
serverState: expectedResolvedState, | ||
clientState, | ||
resolvedOnServer: true | ||
}) | ||
} | ||
t.truthy(resolution.resolvedState) | ||
t.truthy(resolution.payload) | ||
t.deepEqual(resolution.resolvedState, expected.resolvedState) | ||
t.deepEqual(resolution.payload, expected.payload) | ||
}) | ||
test('resolveOnServer resolves the data using a custom async handler', async (t) => { | ||
const serverState = { name: 'AeroGear', version: 2 } | ||
const clientState = { name: 'Client', version: 1 } | ||
const objectState = new VersionedObjectState() | ||
function customStrategy(serverState: ObjectStateData, clientState: ObjectStateData) { | ||
return new Promise((resolve, reject) => { | ||
return resolve({ | ||
name: `${serverState.name} ${clientState.name}` | ||
}) | ||
}) | ||
} | ||
const resolution = await objectState.resolveOnServer(customStrategy, serverState, clientState) | ||
const expectedResolvedState = { | ||
name: 'AeroGear Client' , | ||
version: 3 | ||
} | ||
const expected = { | ||
resolvedState: expectedResolvedState, | ||
payload: new ObjectConflictError({ | ||
serverState: expectedResolvedState, | ||
clientState, | ||
resolvedOnServer: true | ||
}) | ||
} | ||
t.truthy(resolution.resolvedState) | ||
t.truthy(resolution.payload) | ||
t.deepEqual(resolution.resolvedState, expected.resolvedState) | ||
t.deepEqual(resolution.payload, expected.payload) | ||
}) | ||
test('resolveOnServer throws if custom async strategy rejects', async (t) => { | ||
const serverState = { name: 'AeroGear', version: 2 } | ||
const clientState = { name: 'Client', version: 1 } | ||
const objectState = new VersionedObjectState() | ||
function customStrategy(serverState: ObjectStateData, clientState: ObjectStateData) { | ||
return new Promise((resolve, reject) => { | ||
return reject(new Error('an error occurred')) | ||
}) | ||
} | ||
await t.throwsAsync(async () => { | ||
await objectState.resolveOnServer(customStrategy, serverState, clientState) | ||
}) | ||
}) | ||
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
38376
0
6
41
832
2
- Removeddebug@^4.1.0
- Removeddebug@4.4.0(transitive)
- Removedms@2.1.3(transitive)