From ed9735e49ba295e29c259846c9956c1003f4f585 Mon Sep 17 00:00:00 2001 From: Dan Gebhardt Date: Fri, 2 Jul 2021 12:37:30 -0400 Subject: [PATCH] Allow for explicit "singular" requests (queries / transforms) `Query#expressions` now accepts either a single expression or an array of expressions. Likewise, `Transform#operations` now accepts either a single operation or an array of operations. This allows more explicit control over the form in which results will be returned. Data will always be returned in an array when an array is used to express expressions / operations. --- packages/@orbit/data/src/query.ts | 20 ++- packages/@orbit/data/src/transform.ts | 12 +- packages/@orbit/data/test/query-test.ts | 45 ++--- .../test/source-interfaces/pullable-test.ts | 24 +-- .../test/source-interfaces/queryable-test.ts | 30 ++-- .../test/source-interfaces/syncable-test.ts | 33 ++-- .../test/source-interfaces/updatable-test.ts | 21 +-- packages/@orbit/data/test/transform-test.ts | 2 +- .../@orbit/indexeddb/src/indexeddb-source.ts | 30 ++-- .../test/indexeddb-cache-update-test.ts | 25 ++- .../test/indexeddb-source-pullable-test.ts | 13 +- .../test/indexeddb-source-queryable-test.ts | 9 +- .../@orbit/jsonapi/src/lib/query-requests.ts | 4 +- .../jsonapi/src/lib/transform-requests.ts | 125 +++++++------- .../test/jsonapi-source-pullable-test.ts | 139 +++++++++------- .../test/jsonapi-source-pushable-test.ts | 13 +- .../test/jsonapi-source-updatable-test.ts | 15 +- ...ce-with-legacy-serializer-settings-test.ts | 157 ++++++++++-------- .../local-storage/src/local-storage-cache.ts | 1 - .../local-storage/src/local-storage-source.ts | 30 ++-- .../test/local-storage-cache-update-test.ts | 29 ++-- .../local-storage-source-pullable-test.ts | 20 ++- .../local-storage-source-queryable-test.ts | 16 +- .../local-storage-source-updatable-test.ts | 2 +- packages/@orbit/memory/src/memory-source.ts | 26 +-- .../@orbit/memory/test/memory-cache-test.ts | 27 ++- .../memory/test/memory-cache-update-test.ts | 29 ++-- .../test/memory-source-queryable-test.ts | 9 +- .../record-cache/src/async-record-cache.ts | 68 +++++--- .../record-cache/src/live-query/live-query.ts | 4 +- .../record-cache/src/sync-record-cache.ts | 65 +++++--- .../test/async-record-cache-query-test.ts | 8 +- .../test/async-record-cache-update-test.ts | 29 ++-- .../test/sync-record-cache-query-test.ts | 8 +- .../test/sync-record-cache-update-test.ts | 29 ++-- packages/@orbit/records/src/record-query.ts | 4 +- .../@orbit/records/src/record-transform.ts | 4 +- 37 files changed, 593 insertions(+), 532 deletions(-) diff --git a/packages/@orbit/data/src/query.ts b/packages/@orbit/data/src/query.ts index e1b050abd..3daa47fd3 100644 --- a/packages/@orbit/data/src/query.ts +++ b/packages/@orbit/data/src/query.ts @@ -5,10 +5,14 @@ import { QueryExpression } from './query-expression'; /** * Queries are used to extract data from a source. + * + * Each query's `expressions` must be a query expression or an array of + * expressions. This distinction allows for a clear distinction between queries + * that return singular vs. arrayed results. */ export interface Query { id: string; - expressions: QE[]; + expressions: QE | QE[]; options?: RequestOptions; } @@ -51,7 +55,7 @@ export function buildQuery( ); } else { let query = queryOrExpressions as Query; - let expressions: QE[]; + let expressions: QE | QE[]; let options: RequestOptions | undefined; let id: string; @@ -73,13 +77,13 @@ export function buildQuery( } else { if (Array.isArray(queryOrExpressions)) { expressions = []; - for (let queryOrExpression of queryOrExpressions) { - expressions.push(toQueryExpression(queryOrExpression)); + for (let qe of queryOrExpressions) { + expressions.push(toQueryExpression(qe)); } } else { - expressions = [ - toQueryExpression(queryOrExpressions as QE | QueryTerm) - ]; + expressions = toQueryExpression( + queryOrExpressions as QE | QueryTerm + ); } options = queryOptions; id = queryId ?? Orbit.uuid(); @@ -109,5 +113,5 @@ export function isQuery< QE extends QueryExpression = QueryExpression, QB = unknown >(query: QueryOrExpressions): query is Query { - return Array.isArray((query as Query).expressions); + return (query as Query).expressions !== undefined; } diff --git a/packages/@orbit/data/src/transform.ts b/packages/@orbit/data/src/transform.ts index 7d18ddec2..f1e4568b7 100644 --- a/packages/@orbit/data/src/transform.ts +++ b/packages/@orbit/data/src/transform.ts @@ -21,7 +21,7 @@ export type TransformOrOperations = */ export interface Transform { id: string; - operations: O[]; + operations: O | O[]; options?: RequestOptions; } @@ -55,7 +55,7 @@ export function buildTransform( ); } else { let transform = transformOrOperations as Transform; - let operations: O[]; + let operations: O | O[]; let options: RequestOptions | undefined; let id: string; @@ -77,11 +77,11 @@ export function buildTransform( } else { if (Array.isArray(transformOrOperations)) { operations = []; - for (let transformOrOperation of transformOrOperations) { - operations.push(toOperation(transformOrOperation)); + for (let o of transformOrOperations) { + operations.push(toOperation(o)); } } else { - operations = [toOperation(transformOrOperations as O)]; + operations = toOperation(transformOrOperations as O); } options = transformOptions; id = transformId ?? Orbit.uuid(); @@ -110,5 +110,5 @@ function isOperationTerm( function isTransform( transform: TransformOrOperations ): transform is Transform { - return Array.isArray((transform as Transform).operations); + return (transform as Transform).operations !== undefined; } diff --git a/packages/@orbit/data/test/query-test.ts b/packages/@orbit/data/test/query-test.ts index d799e0f2c..13d4934ce 100644 --- a/packages/@orbit/data/test/query-test.ts +++ b/packages/@orbit/data/test/query-test.ts @@ -39,9 +39,9 @@ module('buildQuery', function () { assert.strictEqual(query.id, 'abc123', 'id was populated'); assert.strictEqual( - query.expressions[0], + query.expressions, expression, - 'expression was populated' + 'expressions was populated' ); assert.strictEqual(query.options, options, 'options was populated'); }); @@ -53,13 +53,13 @@ module('buildQuery', function () { }; let expressions = [expression]; let options = { sources: { jsonapi: { include: 'comments' } } }; - let query = buildQuery(expression, options, 'abc123'); + let query = buildQuery(expressions, options, 'abc123'); assert.strictEqual(query.id, 'abc123', 'id was populated'); assert.deepEqual( query.expressions, expressions, - 'expression was populated' + 'expressions was populated' ); assert.strictEqual(query.options, options, 'options was populated'); }); @@ -76,8 +76,8 @@ module('buildQuery', function () { assert.strictEqual(query.id, 'abc123', 'id was populated'); assert.deepEqual( query.expressions, - [{ op: 'findRecords', type: 'planet' }], - 'expression was populated' + { op: 'findRecords', type: 'planet' }, + 'expressions was populated' ); assert.strictEqual(query.options, options, 'options was populated'); }); @@ -108,7 +108,7 @@ module('buildQuery', function () { { op: 'findRecords', type: 'planet' }, { op: 'findRecords', type: 'moon' } ], - 'expression was populated' + 'expressions was populated' ); assert.strictEqual(query.options, options, 'options was populated'); }); @@ -131,12 +131,10 @@ module('buildQuery', function () { let query2 = buildQuery(query1, { a: '2', b: '2' }, '2'); assert.notStrictEqual(query1, query2); assert.deepEqual(query2, { - expressions: [ - { - op: 'findRecords', - type: 'planet' - } - ], + expressions: { + op: 'findRecords', + type: 'planet' + }, options: { a: '2', b: '2', @@ -160,8 +158,8 @@ module('buildQuery', function () { ); assert.deepEqual( query.expressions, - [expression], - 'expression was populated' + expression, + 'expressions was populated' ); }); @@ -173,9 +171,9 @@ module('buildQuery', function () { let queryFactory = new QueryTerm(expression); let query = buildQuery(queryFactory); assert.strictEqual( - query.expressions[0], + query.expressions, expression, - 'expression was populated' + 'expressions was populated' ); }); @@ -189,15 +187,8 @@ module('buildQuery', function () { type: 'moon' }; let query = buildQuery([expression1, expression2]); - assert.strictEqual( - query.expressions[0], - expression1, - 'expression1 was populated' - ); - assert.strictEqual( - query.expressions[1], - expression2, - 'expression2 was populated' - ); + let qe = query.expressions as RecordQueryExpression[]; + assert.strictEqual(qe[0], expression1, 'expression1 was populated'); + assert.strictEqual(qe[1], expression2, 'expression2 was populated'); }); }); diff --git a/packages/@orbit/data/test/source-interfaces/pullable-test.ts b/packages/@orbit/data/test/source-interfaces/pullable-test.ts index b476c6a68..61a761c20 100644 --- a/packages/@orbit/data/test/source-interfaces/pullable-test.ts +++ b/packages/@orbit/data/test/source-interfaces/pullable-test.ts @@ -96,7 +96,7 @@ module('@pullable', function (hooks) { source._pull = async function (query) { assert.equal(++order, 1, 'action performed after willPull'); - assert.strictEqual(query.expressions[0], qe, 'query object matches'); + assert.strictEqual(query.expressions, qe, 'query object matches'); return fullResponse; }; @@ -116,7 +116,7 @@ module('@pullable', function (hooks) { 2, 'pull triggered after action performed successfully' ); - assert.strictEqual(query.expressions[0], qe, 'query matches'); + assert.strictEqual(query.expressions, qe, 'query matches'); assert.strictEqual(result, fullResponse, 'result matches'); }); @@ -162,7 +162,7 @@ module('@pullable', function (hooks) { source._pull = async function (query) { assert.equal(++order, 4, 'action performed after willPull'); - assert.strictEqual(query.expressions[0], qe, 'query object matches'); + assert.strictEqual(query.expressions, qe, 'query object matches'); return fullResponse; }; @@ -182,7 +182,7 @@ module('@pullable', function (hooks) { 5, 'pull triggered after action performed successfully' ); - assert.strictEqual(query.expressions[0], qe, 'query matches'); + assert.strictEqual(query.expressions, qe, 'query matches'); assert.strictEqual(result, fullResponse, 'result matches'); }); @@ -226,7 +226,7 @@ module('@pullable', function (hooks) { 3, 'pullFail triggered after an unsuccessful beforePull' ); - assert.strictEqual(query.expressions[0], qe, 'query matches'); + assert.strictEqual(query.expressions, qe, 'query matches'); assert.equal(error, ':(', 'error matches'); }); @@ -246,7 +246,7 @@ module('@pullable', function (hooks) { source._pull = function (query) { assert.equal(++order, 1, 'action performed after willPull'); - assert.strictEqual(query.expressions[0], qe, 'query object matches'); + assert.strictEqual(query.expressions, qe, 'query object matches'); return Promise.reject(':('); }; @@ -256,7 +256,7 @@ module('@pullable', function (hooks) { source.on('pullFail', (query, error) => { assert.equal(++order, 2, 'pullFail triggered after an unsuccessful pull'); - assert.strictEqual(query.expressions[0], qe, 'query matches'); + assert.strictEqual(query.expressions, qe, 'query matches'); assert.equal(error, ':(', 'error matches'); }); @@ -385,7 +385,7 @@ module('@pullable', function (hooks) { source._pull = async function (query) { assert.equal(++order, 1, 'action performed after beforeQuery'); - assert.strictEqual(query.expressions[0], qe, 'query object matches'); + assert.strictEqual(query.expressions, qe, 'query object matches'); return fullResponse; }; @@ -395,7 +395,7 @@ module('@pullable', function (hooks) { 2, 'pull triggered after action performed successfully' ); - assert.strictEqual(query.expressions[0], qe, 'query matches'); + assert.strictEqual(query.expressions, qe, 'query matches'); assert.deepEqual(result, fullResponse, 'result matches'); }); @@ -444,14 +444,14 @@ module('@pullable', function (hooks) { source.on('beforePull', async (query) => { assert.equal(++order, 1, 'beforePull triggered first'); - assert.strictEqual(query.expressions[0], qe, 'beforePull: query matches'); + assert.strictEqual(query.expressions, qe, 'beforePull: query matches'); return ['remote', { details: details1 }]; }); source._pull = async function (query) { assert.equal(++order, 2, 'action performed after beforeQuery'); - assert.strictEqual(query.expressions[0], qe, '_pull: query matches'); + assert.strictEqual(query.expressions, qe, '_pull: query matches'); return { transforms: transforms1, details: details1 @@ -464,7 +464,7 @@ module('@pullable', function (hooks) { 3, 'pull triggered after action performed successfully' ); - assert.strictEqual(query.expressions[0], qe, 'pull: query matches'); + assert.strictEqual(query.expressions, qe, 'pull: query matches'); assert.deepEqual(result, expectedResult, 'pull: result matches'); }); diff --git a/packages/@orbit/data/test/source-interfaces/queryable-test.ts b/packages/@orbit/data/test/source-interfaces/queryable-test.ts index edb35055a..795cbd3ca 100644 --- a/packages/@orbit/data/test/source-interfaces/queryable-test.ts +++ b/packages/@orbit/data/test/source-interfaces/queryable-test.ts @@ -90,7 +90,7 @@ module('@queryable', function (hooks) { source._query = async function (query) { assert.equal(++order, 1, 'action performed after beforeQuery'); - assert.strictEqual(query.expressions[0], qe, 'query object matches'); + assert.strictEqual(query.expressions, qe, 'query object matches'); return fullResponse; }; @@ -100,7 +100,7 @@ module('@queryable', function (hooks) { 2, 'query triggered after action performed successfully' ); - assert.strictEqual(query.expressions[0], qe, 'query matches'); + assert.strictEqual(query.expressions, qe, 'query matches'); assert.strictEqual(result, fullResponse, 'result matches'); }); @@ -121,7 +121,7 @@ module('@queryable', function (hooks) { source._query = async function (query) { assert.equal(++order, 1, 'action performed after beforeQuery'); - assert.strictEqual(query.expressions[0], qe, 'query object matches'); + assert.strictEqual(query.expressions, qe, 'query object matches'); return fullResponse; }; @@ -131,7 +131,7 @@ module('@queryable', function (hooks) { 2, 'query triggered after action performed successfully' ); - assert.strictEqual(query.expressions[0], qe, 'query matches'); + assert.strictEqual(query.expressions, qe, 'query matches'); assert.equal(result, fullResponse, 'result matches'); }); @@ -157,7 +157,7 @@ module('@queryable', function (hooks) { source._query = async function (query) { assert.equal(++order, 1, 'action performed after beforeQuery'); - assert.strictEqual(query.expressions[0], qe, 'query object matches'); + assert.strictEqual(query.expressions, qe, 'query object matches'); return fullResponse; }; @@ -167,7 +167,7 @@ module('@queryable', function (hooks) { 2, 'query triggered after action performed successfully' ); - assert.strictEqual(query.expressions[0], qe, 'query matches'); + assert.strictEqual(query.expressions, qe, 'query matches'); assert.deepEqual(result, fullResponse, 'result matches'); }); @@ -185,7 +185,7 @@ module('@queryable', function (hooks) { source._query = function (query) { assert.equal(++order, 1, 'action performed after beforeQuery'); - assert.strictEqual(query.expressions[0], qe, 'query object matches'); + assert.strictEqual(query.expressions, qe, 'query object matches'); return Promise.reject(':('); }; @@ -199,7 +199,7 @@ module('@queryable', function (hooks) { 2, 'queryFail triggered after an unsuccessful query' ); - assert.strictEqual(query.expressions[0], qe, 'query matches'); + assert.strictEqual(query.expressions, qe, 'query matches'); assert.equal(error, ':(', 'error matches'); }); @@ -403,7 +403,7 @@ module('@queryable', function (hooks) { ]; source._query = async function (query) { assert.equal(++order, 1, 'action performed after beforeQuery'); - assert.strictEqual(query.expressions[0], qe, 'query object matches'); + assert.strictEqual(query.expressions, qe, 'query object matches'); return { data: result1 }; }; @@ -413,7 +413,7 @@ module('@queryable', function (hooks) { 2, 'query triggered after action performed successfully' ); - assert.strictEqual(query.expressions[0], qe, 'query matches'); + assert.strictEqual(query.expressions, qe, 'query matches'); assert.deepEqual(result, { data: result1 }, 'result matches'); }); @@ -452,18 +452,14 @@ module('@queryable', function (hooks) { source.on('beforeQuery', async (query) => { assert.equal(++order, 1, 'beforeQuery triggered first'); - assert.strictEqual( - query.expressions[0], - qe, - 'beforeQuery: query matches' - ); + assert.strictEqual(query.expressions, qe, 'beforeQuery: query matches'); return ['remote', { details: details1 }]; }); source._query = async function (query) { assert.equal(++order, 2, 'action performed after beforeQuery'); - assert.strictEqual(query.expressions[0], qe, '_query: query matches'); + assert.strictEqual(query.expressions, qe, '_query: query matches'); return { data: data1, details: details1 }; }; @@ -473,7 +469,7 @@ module('@queryable', function (hooks) { 3, 'query triggered after action performed successfully' ); - assert.strictEqual(query.expressions[0], qe, 'query: query matches'); + assert.strictEqual(query.expressions, qe, 'query: query matches'); assert.deepEqual(result, expectedResult, 'result matches'); }); diff --git a/packages/@orbit/data/test/source-interfaces/syncable-test.ts b/packages/@orbit/data/test/source-interfaces/syncable-test.ts index 823058e14..6e426d81f 100644 --- a/packages/@orbit/data/test/source-interfaces/syncable-test.ts +++ b/packages/@orbit/data/test/source-interfaces/syncable-test.ts @@ -106,7 +106,7 @@ module('@syncable', function (hooks) { }); test('#sync can accept a transform builder function, create a transform, and call internal method `_sync`', async function (assert) { - assert.expect(4); + assert.expect(2); const earth = { type: 'planet', id: 'earth' }; const jupiter = { type: 'planet', id: 'jupiter' }; @@ -115,26 +115,19 @@ module('@syncable', function (hooks) { source._sync = async function (transform: Transform) { order++; if (order === 1) { - assert.strictEqual( - transform.operations.length, - 2, - 'transform passed to _sync with correct operations count' - ); - assert.deepEqual( - transform.operations[0], - { - op: 'addRecord', - record: earth - }, - 'expected operation' - ); assert.deepEqual( - transform.operations[1], - { - op: 'addRecord', - record: jupiter - }, - 'expected operation' + transform.operations as RecordOperation[], + [ + { + op: 'addRecord', + record: earth + }, + { + op: 'addRecord', + record: jupiter + } + ], + 'transform passed to _sync with correct data' ); } else { assert.ok(false, 'unexpected'); diff --git a/packages/@orbit/data/test/source-interfaces/updatable-test.ts b/packages/@orbit/data/test/source-interfaces/updatable-test.ts index 5fbbdf9b0..05a108551 100644 --- a/packages/@orbit/data/test/source-interfaces/updatable-test.ts +++ b/packages/@orbit/data/test/source-interfaces/updatable-test.ts @@ -137,24 +137,21 @@ module('@updatable', function (hooks) { }); test('#update can accept a transform builder function', async function (assert) { - assert.expect(3); + assert.expect(2); const earth = { type: 'planet', id: 'earth' }; const fullResponse = { data: earth, transforms: [] }; source._update = async function (transform: Transform) { - assert.strictEqual( - transform.operations.length, - 1, - 'transform passed to _update with correct operations count' - ); assert.deepEqual( - transform.operations[0], - { - op: 'addRecord', - record: earth - }, - 'expected operation' + transform.operations as RecordOperation[], + [ + { + op: 'addRecord', + record: earth + } + ], + 'transform passed to _update with correct operations' ); return fullResponse; }; diff --git a/packages/@orbit/data/test/transform-test.ts b/packages/@orbit/data/test/transform-test.ts index b070233ac..d115d1a76 100644 --- a/packages/@orbit/data/test/transform-test.ts +++ b/packages/@orbit/data/test/transform-test.ts @@ -142,7 +142,7 @@ module('buildTransform', function () { ); assert.deepEqual( transform.operations, - [operation], + operation, 'operations was populated' ); }); diff --git a/packages/@orbit/indexeddb/src/indexeddb-source.ts b/packages/@orbit/indexeddb/src/indexeddb-source.ts index 564b79b40..edd10a87b 100644 --- a/packages/@orbit/indexeddb/src/indexeddb-source.ts +++ b/packages/@orbit/indexeddb/src/indexeddb-source.ts @@ -212,7 +212,12 @@ export class IndexedDBSource< } if (hints?.data) { - if (transform.operations.length > 1 && Array.isArray(hints.data)) { + if (Array.isArray(transform.operations)) { + assert( + 'IndexedDBSource#update: `hints.data` must be an array if `transform.operations` is an array', + Array.isArray(hints.data) + ); + const responseData = []; const hintsData = hints.data as RecordOperationResult[]; for (let h of hintsData) { @@ -225,11 +230,7 @@ export class IndexedDBSource< ); } } else if (results) { - if (transform.operations.length === 1 && Array.isArray(results)) { - response.data = results[0]; - } else { - response.data = results; - } + response.data = results; } if (hints?.details) { @@ -251,7 +252,12 @@ export class IndexedDBSource< if (hints?.data) { response = {}; - if (query.expressions.length > 1 && Array.isArray(hints.data)) { + if (Array.isArray(query.expressions)) { + assert( + 'IndexedDBSource#query: `hints.data` must be an array if `query.expressions` is an array', + Array.isArray(hints.data) + ); + const responseData = []; const hintsData = hints.data as RecordQueryExpressionResult[]; for (let h of hintsData) { @@ -305,15 +311,15 @@ export class IndexedDBSource< const results = await this._cache.query(query); - if (query.expressions.length === 1) { - operations = this._operationsFromQueryResult( - results as RecordQueryExpressionResult - ); - } else { + if (Array.isArray(query.expressions)) { operations = []; for (let result of results as RecordQueryExpressionResult[]) { operations.push(...this._operationsFromQueryResult(result)); } + } else { + operations = this._operationsFromQueryResult( + results as RecordQueryExpressionResult + ); } fullResponse.transforms = [buildTransform(operations)]; diff --git a/packages/@orbit/indexeddb/test/indexeddb-cache-update-test.ts b/packages/@orbit/indexeddb/test/indexeddb-cache-update-test.ts index 1ed1f1ead..516ceafce 100644 --- a/packages/@orbit/indexeddb/test/indexeddb-cache-update-test.ts +++ b/packages/@orbit/indexeddb/test/indexeddb-cache-update-test.ts @@ -992,13 +992,12 @@ module('IndexedDBCache - update', function (hooks) { ]); let result = await cache.update( - (t) => [ + (t) => t.updateRecord({ type: 'planet', id: '1', attributes: { classification: 'terrestrial' } - }) - ], + }), { fullResponse: true } ); @@ -1072,21 +1071,20 @@ module('IndexedDBCache - update', function (hooks) { test('#update can replace related records but only if they are different', async function (assert) { const tb = cache.transformBuilder; - await cache.update((t) => [ + await cache.update((t) => t.addRecord({ type: 'planet', id: '1', attributes: { name: 'Earth' }, relationships: { moons: { data: [{ type: 'moon', id: 'm1' }] } } }) - ]); + ); let result = await cache.update( - (t) => [ + (t) => t.replaceRelatedRecords({ type: 'planet', id: '1' }, 'moons', [ { type: 'moon', id: 'm1' } - ]) - ], + ]), { fullResponse: true } ); @@ -1233,7 +1231,7 @@ module('IndexedDBCache - update', function (hooks) { relationships: { moons: { data: [{ type: 'moon', id: 'm2' }] } } }; - let result = await cache.update([tb.addRecord(earth)], { + let result = await cache.update(tb.addRecord(earth), { fullResponse: true }); @@ -1292,7 +1290,7 @@ module('IndexedDBCache - update', function (hooks) { 'addRecord full response is correct' ); - result = await cache.update([tb.updateRecord(jupiter)], { + result = await cache.update(tb.updateRecord(jupiter), { fullResponse: true }); @@ -1376,7 +1374,7 @@ module('IndexedDBCache - update', function (hooks) { const tb = cache.transformBuilder; let result = await cache.update( - (t) => [t.addRecord({ id: '1', type: 'planet' })], + (t) => t.addRecord({ id: '1', type: 'planet' }), { fullResponse: true } ); @@ -1413,15 +1411,14 @@ module('IndexedDBCache - update', function (hooks) { ); result = await cache.update( - (t) => [ + (t) => t.updateRecord({ id: '1', type: 'planet', relationships: { moons: { data: [] } } - }) - ], + }), { fullResponse: true } ); diff --git a/packages/@orbit/indexeddb/test/indexeddb-source-pullable-test.ts b/packages/@orbit/indexeddb/test/indexeddb-source-pullable-test.ts index e7e661b52..74421b534 100644 --- a/packages/@orbit/indexeddb/test/indexeddb-source-pullable-test.ts +++ b/packages/@orbit/indexeddb/test/indexeddb-source-pullable-test.ts @@ -2,6 +2,7 @@ import { AddRecordOperation, InitializedRecord, RecordKeyMap, + RecordOperation, RecordSchema, RecordTransform } from '@orbit/records'; @@ -120,7 +121,7 @@ module('IndexedDBSource - pullable', function (hooks) { assert.equal(transforms.length, 1, 'one transform returned'); assert.deepEqual( - transforms[0].operations.map((o) => o.op), + (transforms[0].operations as RecordOperation[]).map((o) => o.op), ['updateRecord', 'updateRecord', 'updateRecord'], 'operations match expectations' ); @@ -186,12 +187,12 @@ module('IndexedDBSource - pullable', function (hooks) { 'log contains transform' ); assert.deepEqual( - transforms[0].operations.map((o) => o.op), + (transforms[0].operations as RecordOperation[]).map((o) => o.op), ['updateRecord', 'updateRecord'], 'operations match expectations' ); assert.deepEqual( - transforms[0].operations.map( + (transforms[0].operations as RecordOperation[]).map( (o) => (o as AddRecordOperation)?.record?.type ), ['planet', 'planet'], @@ -244,12 +245,12 @@ module('IndexedDBSource - pullable', function (hooks) { 'log contains transform' ); assert.deepEqual( - transforms[0].operations.map((o) => o.op), + (transforms[0].operations as RecordOperation[]).map((o) => o.op), ['updateRecord', 'updateRecord'], 'operations match expectations' ); assert.deepEqual( - transforms[0].operations.map( + (transforms[0].operations as RecordOperation[]).map( (o) => (o as AddRecordOperation).record.type ), ['planet', 'moon'], @@ -308,7 +309,7 @@ module('IndexedDBSource - pullable', function (hooks) { 'log contains transform' ); assert.deepEqual( - transforms[0].operations.map((o) => o.op), + (transforms[0].operations as RecordOperation[]).map((o) => o.op), ['updateRecord'], 'operations match expectations' ); diff --git a/packages/@orbit/indexeddb/test/indexeddb-source-queryable-test.ts b/packages/@orbit/indexeddb/test/indexeddb-source-queryable-test.ts index a03f84837..486bbf3fa 100644 --- a/packages/@orbit/indexeddb/test/indexeddb-source-queryable-test.ts +++ b/packages/@orbit/indexeddb/test/indexeddb-source-queryable-test.ts @@ -107,9 +107,7 @@ module('IndexedDBSource - queryable', function (hooks) { }; source.on('beforeQuery', (query: RecordQuery, hints: any) => { - if (query.expressions[0].op === 'findRecord') { - hints.data = jupiter2; - } + hints.data = jupiter2; }); await source.cache.update((t) => t.addRecord(jupiter2)); @@ -149,10 +147,7 @@ module('IndexedDBSource - queryable', function (hooks) { }; source.on('beforeQuery', (query: RecordQuery, hints: any) => { - if ( - query.expressions[0].op === 'findRecords' && - query.options?.sources?.remote.customFilter === 'distantPlanets' - ) { + if (query.options?.sources?.remote.customFilter === 'distantPlanets') { hints.data = [ { type: 'planet', id: 'uranus' }, { type: 'planet', id: 'jupiter' } diff --git a/packages/@orbit/jsonapi/src/lib/query-requests.ts b/packages/@orbit/jsonapi/src/lib/query-requests.ts index 5ee19a3cd..3a46437ae 100644 --- a/packages/@orbit/jsonapi/src/lib/query-requests.ts +++ b/packages/@orbit/jsonapi/src/lib/query-requests.ts @@ -1,4 +1,4 @@ -import { Dict } from '@orbit/utils'; +import { Dict, toArray } from '@orbit/utils'; import { RecordQuery, AddToRelatedRecordsOperation, @@ -78,7 +78,7 @@ export function getQueryRequests( ): RecordQueryRequest[] { const requests: RecordQueryRequest[] = []; - for (let expression of query.expressions) { + for (let expression of toArray(query.expressions)) { let request = ExpressionToRequestMap[expression.op]( expression as RecordQueryExpression, requestProcessor diff --git a/packages/@orbit/jsonapi/src/lib/transform-requests.ts b/packages/@orbit/jsonapi/src/lib/transform-requests.ts index 118baf22d..f8182bb00 100644 --- a/packages/@orbit/jsonapi/src/lib/transform-requests.ts +++ b/packages/@orbit/jsonapi/src/lib/transform-requests.ts @@ -1,4 +1,4 @@ -import { clone, deepSet, Dict } from '@orbit/utils'; +import { clone, deepSet, Dict, toArray } from '@orbit/utils'; import { cloneRecordIdentity, equalRecordIdentities, @@ -317,80 +317,75 @@ export function getTransformRequests( transform: RecordTransform ): RecordTransformRequest[] { const requests: RecordTransformRequest[] = []; - let prevRequest: RecordTransformRequest | null; - - (transform.operations as RecordOperation[]).forEach( - (operation: RecordOperation) => { - let request; - let newRequestNeeded = true; - - if ( - prevRequest && - equalRecordIdentities(prevRequest.record, operation.record) + let prevRequest: RecordTransformRequest | null = null; + + for (let operation of toArray(transform.operations)) { + let request; + let newRequestNeeded = true; + + if ( + prevRequest && + equalRecordIdentities(prevRequest.record, operation.record) + ) { + if (operation.op === 'removeRecord') { + newRequestNeeded = false; + + if (prevRequest.op !== 'removeRecord') { + prevRequest = null; + requests.pop(); + } + } else if ( + prevRequest.op === 'addRecord' || + prevRequest.op === 'updateRecord' ) { - if (operation.op === 'removeRecord') { + if (operation.op === 'replaceAttribute') { newRequestNeeded = false; - - if (prevRequest.op !== 'removeRecord') { - prevRequest = null; - requests.pop(); - } - } else if ( - prevRequest.op === 'addRecord' || - prevRequest.op === 'updateRecord' - ) { - if (operation.op === 'replaceAttribute') { - newRequestNeeded = false; - replaceRecordAttribute( - prevRequest.record, - operation.attribute, - operation.value - ); - } else if (operation.op === 'replaceRelatedRecord') { - newRequestNeeded = false; - replaceRecordHasOne( - prevRequest.record, - operation.relationship, - operation.relatedRecord as RecordIdentity - ); - } else if (operation.op === 'replaceRelatedRecords') { - newRequestNeeded = false; - replaceRecordHasMany( - prevRequest.record, - operation.relationship, - operation.relatedRecords - ); - } - } else if ( - prevRequest.op === 'addToRelatedRecords' && - operation.op === 'addToRelatedRecords' && - (prevRequest as AddToRelatedRecordsRequest).relationship === - operation.relationship - ) { + replaceRecordAttribute( + prevRequest.record, + operation.attribute, + operation.value + ); + } else if (operation.op === 'replaceRelatedRecord') { + newRequestNeeded = false; + replaceRecordHasOne( + prevRequest.record, + operation.relationship, + operation.relatedRecord as RecordIdentity + ); + } else if (operation.op === 'replaceRelatedRecords') { newRequestNeeded = false; - (prevRequest as AddToRelatedRecordsRequest).relatedRecords.push( - cloneRecordIdentity(operation.relatedRecord) + replaceRecordHasMany( + prevRequest.record, + operation.relationship, + operation.relatedRecords ); } + } else if ( + prevRequest.op === 'addToRelatedRecords' && + operation.op === 'addToRelatedRecords' && + (prevRequest as AddToRelatedRecordsRequest).relationship === + operation.relationship + ) { + newRequestNeeded = false; + (prevRequest as AddToRelatedRecordsRequest).relatedRecords.push( + cloneRecordIdentity(operation.relatedRecord) + ); } + } - if (newRequestNeeded) { - request = OperationToRequestMap[operation.op](operation); - } + if (newRequestNeeded) { + request = OperationToRequestMap[operation.op](operation); + } - if (request) { - let options = requestProcessor.customRequestOptions( - transform, - operation - ); - if (options) { - request.options = options; - } - requests.push(request); - prevRequest = request; + if (request) { + let options = requestProcessor.customRequestOptions(transform, operation); + if (options) { + request.options = options; } + requests.push(request); + prevRequest = request; } - ); + } return requests; } diff --git a/packages/@orbit/jsonapi/test/jsonapi-source-pullable-test.ts b/packages/@orbit/jsonapi/test/jsonapi-source-pullable-test.ts index 456344bca..7a4dcae9d 100644 --- a/packages/@orbit/jsonapi/test/jsonapi-source-pullable-test.ts +++ b/packages/@orbit/jsonapi/test/jsonapi-source-pullable-test.ts @@ -12,6 +12,7 @@ import { } from '@orbit/records'; import * as sinon from 'sinon'; import { SinonStub } from 'sinon'; +import { toArray } from '@orbit/utils'; import { JSONAPIResourceIdentitySerializer, JSONAPIResourceSerializer, @@ -83,11 +84,11 @@ module('JSONAPISource - pullable', function (hooks) { 'log contains transform' ); assert.deepEqual( - transforms[0].operations.map((o) => o.op), + toArray(transforms[0].operations).map((o) => o.op), ['updateRecord'] ); assert.deepEqual( - transforms[0].operations.map( + toArray(transforms[0].operations).map( (o) => (o as UpdateRecordOperation).record.attributes?.name ), ['Jupiter'] @@ -289,11 +290,11 @@ module('JSONAPISource - pullable', function (hooks) { 'log contains transform' ); assert.deepEqual( - transforms[0].operations.map((o) => o.op), + toArray(transforms[0].operations).map((o) => o.op), ['updateRecord', 'updateRecord', 'updateRecord'] ); assert.deepEqual( - transforms[0].operations.map( + toArray(transforms[0].operations).map( (o) => (o as UpdateRecordOperation).record.attributes?.name ), ['Jupiter', 'Earth', 'Saturn'] @@ -350,11 +351,11 @@ module('JSONAPISource - pullable', function (hooks) { assert.equal(transforms.length, 1, 'one transform returned'); assert.deepEqual( - transforms[0].operations.map((o) => o.op), + toArray(transforms[0].operations).map((o) => o.op), ['updateRecord'] ); assert.deepEqual( - transforms[0].operations.map( + toArray(transforms[0].operations).map( (o) => (o as UpdateRecordOperation).record.attributes?.name ), ['Earth'] @@ -404,11 +405,11 @@ module('JSONAPISource - pullable', function (hooks) { 'log contains transform' ); assert.deepEqual( - transforms[0].operations.map((o) => o.op), + toArray(transforms[0].operations).map((o) => o.op), ['updateRecord'] ); assert.deepEqual( - transforms[0].operations.map( + toArray(transforms[0].operations).map( (o) => (o as UpdateRecordOperation).record.attributes?.name ), ['Earth'] @@ -453,11 +454,11 @@ module('JSONAPISource - pullable', function (hooks) { 'log contains transform' ); assert.deepEqual( - transforms[0].operations.map((o) => o.op), + toArray(transforms[0].operations).map((o) => o.op), ['updateRecord'] ); assert.deepEqual( - transforms[0].operations.map( + toArray(transforms[0].operations).map( (o) => (o as UpdateRecordOperation).record.attributes?.name ), ['Moon'] @@ -525,11 +526,11 @@ module('JSONAPISource - pullable', function (hooks) { 'log contains transform' ); assert.deepEqual( - transforms[0].operations.map((o) => o.op), + toArray(transforms[0].operations).map((o) => o.op), ['updateRecord', 'updateRecord', 'updateRecord'] ); assert.deepEqual( - transforms[0].operations.map( + toArray(transforms[0].operations).map( (o) => (o as UpdateRecordOperation).record.attributes?.name ), ['Moon', 'Phobos', 'Deimos'] @@ -587,11 +588,11 @@ module('JSONAPISource - pullable', function (hooks) { 'log contains transform' ); assert.deepEqual( - transforms[0].operations.map((o) => o.op), + toArray(transforms[0].operations).map((o) => o.op), ['updateRecord'] ); assert.deepEqual( - transforms[0].operations.map( + toArray(transforms[0].operations).map( (o) => (o as UpdateRecordOperation).record.attributes?.name ), ['Mars'] @@ -637,11 +638,11 @@ module('JSONAPISource - pullable', function (hooks) { 'log contains transform' ); assert.deepEqual( - transforms[0].operations.map((o) => o.op), + toArray(transforms[0].operations).map((o) => o.op), ['updateRecord', 'updateRecord', 'updateRecord'] ); assert.deepEqual( - transforms[0].operations.map( + toArray(transforms[0].operations).map( (o) => (o as UpdateRecordOperation).record.attributes?.name ), ['Earth', 'Jupiter', 'Saturn'] @@ -687,11 +688,11 @@ module('JSONAPISource - pullable', function (hooks) { 'log contains transform' ); assert.deepEqual( - transforms[0].operations.map((o) => o.op), + toArray(transforms[0].operations).map((o) => o.op), ['updateRecord', 'updateRecord', 'updateRecord'] ); assert.deepEqual( - transforms[0].operations.map( + toArray(transforms[0].operations).map( (o) => (o as UpdateRecordOperation).record.attributes?.name ), ['Saturn', 'Jupiter', 'Earth'] @@ -749,11 +750,11 @@ module('JSONAPISource - pullable', function (hooks) { 'log contains transform' ); assert.deepEqual( - transforms[0].operations.map((o) => o.op), + toArray(transforms[0].operations).map((o) => o.op), ['updateRecord', 'updateRecord', 'updateRecord'] ); assert.deepEqual( - transforms[0].operations.map( + toArray(transforms[0].operations).map( (o) => (o as UpdateRecordOperation).record.attributes?.name ), ['Jupiter', 'Saturn', 'Earth'] @@ -803,11 +804,11 @@ module('JSONAPISource - pullable', function (hooks) { 'log contains transform' ); assert.deepEqual( - transforms[0].operations.map((o) => o.op), + toArray(transforms[0].operations).map((o) => o.op), ['updateRecord', 'updateRecord', 'updateRecord'] ); assert.deepEqual( - transforms[0].operations.map( + toArray(transforms[0].operations).map( (o) => (o as UpdateRecordOperation).record.attributes?.name ), ['Jupiter', 'Earth', 'Saturn'] @@ -867,12 +868,14 @@ module('JSONAPISource - pullable', function (hooks) { source.transformLog.contains(transforms[0].id), 'log contains transform' ); + + const ops = transforms[0].operations as RecordOperation[]; assert.deepEqual( - transforms[0].operations.map((o) => o.op), + ops.map((o) => o.op), ['updateRecord', 'addToRelatedRecords'] ); - let op1 = transforms[0].operations[0] as UpdateRecordOperation; + let op1 = ops[0] as UpdateRecordOperation; assert.equal(op1.record.attributes?.name, 'Earth'); @@ -924,12 +927,14 @@ module('JSONAPISource - pullable', function (hooks) { source.transformLog.contains(transforms[0].id), 'log contains transform' ); + + const ops = transforms[0].operations as RecordOperation[]; assert.deepEqual( - transforms[0].operations.map((o) => o.op), + ops.map((o) => o.op), ['updateRecord', 'addToRelatedRecords'] ); - let op1 = transforms[0].operations[0] as UpdateRecordOperation; + let op1 = ops[0] as UpdateRecordOperation; assert.equal(op1.record.attributes?.name, 'Earth'); @@ -980,12 +985,14 @@ module('JSONAPISource - pullable', function (hooks) { source.transformLog.contains(transforms[0].id), 'log contains transform' ); + + const ops = transforms[0].operations as RecordOperation[]; assert.deepEqual( - transforms[0].operations.map((o) => o.op), + ops.map((o) => o.op), ['updateRecord', 'addToRelatedRecords'] ); - let op1 = transforms[0].operations[0] as UpdateRecordOperation; + let op1 = ops[0] as UpdateRecordOperation; assert.equal(op1.record.attributes?.name, 'Moon'); @@ -1055,8 +1062,10 @@ module('JSONAPISource - pullable', function (hooks) { source.transformLog.contains(transforms[0].id), 'log contains transform' ); + + const ops = transforms[0].operations as RecordOperation[]; assert.deepEqual( - transforms[0].operations.map((o) => o.op), + ops.map((o) => o.op), [ 'updateRecord', 'updateRecord', @@ -1067,9 +1076,9 @@ module('JSONAPISource - pullable', function (hooks) { ] ); - let op1 = transforms[0].operations[0] as UpdateRecordOperation; - let op2 = transforms[0].operations[1] as UpdateRecordOperation; - let op3 = transforms[0].operations[2] as UpdateRecordOperation; + let op1 = ops[0] as UpdateRecordOperation; + let op2 = ops[1] as UpdateRecordOperation; + let op3 = ops[2] as UpdateRecordOperation; assert.deepEqual( [op1, op2, op3].map((o) => o.record.attributes?.name), @@ -1132,12 +1141,14 @@ module('JSONAPISource - pullable', function (hooks) { source.transformLog.contains(transforms[0].id), 'log contains transform' ); + + const ops = transforms[0].operations as RecordOperation[]; assert.deepEqual( - transforms[0].operations.map((o) => o.op), + ops.map((o) => o.op), ['updateRecord', 'addToRelatedRecords'] ); - let op1 = transforms[0].operations[0] as UpdateRecordOperation; + let op1 = ops[0] as UpdateRecordOperation; assert.equal(op1.record.attributes?.name, 'Mars'); @@ -1185,8 +1196,10 @@ module('JSONAPISource - pullable', function (hooks) { source.transformLog.contains(transforms[0].id), 'log contains transform' ); + + const ops = transforms[0].operations as RecordOperation[]; assert.deepEqual( - transforms[0].operations.map((o) => o.op), + ops.map((o) => o.op), [ 'updateRecord', 'updateRecord', @@ -1197,9 +1210,9 @@ module('JSONAPISource - pullable', function (hooks) { ] ); - let op1 = transforms[0].operations[0] as UpdateRecordOperation; - let op2 = transforms[0].operations[1] as UpdateRecordOperation; - let op3 = transforms[0].operations[2] as UpdateRecordOperation; + let op1 = ops[0] as UpdateRecordOperation; + let op2 = ops[1] as UpdateRecordOperation; + let op3 = ops[2] as UpdateRecordOperation; assert.deepEqual( [op1, op2, op3].map((o) => o.record.attributes?.name), @@ -1250,8 +1263,10 @@ module('JSONAPISource - pullable', function (hooks) { source.transformLog.contains(transforms[0].id), 'log contains transform' ); + + const ops = transforms[0].operations as RecordOperation[]; assert.deepEqual( - transforms[0].operations.map((o) => o.op), + ops.map((o) => o.op), [ 'updateRecord', 'updateRecord', @@ -1262,9 +1277,9 @@ module('JSONAPISource - pullable', function (hooks) { ] ); - let op1 = transforms[0].operations[0] as UpdateRecordOperation; - let op2 = transforms[0].operations[1] as UpdateRecordOperation; - let op3 = transforms[0].operations[2] as UpdateRecordOperation; + let op1 = ops[0] as UpdateRecordOperation; + let op2 = ops[1] as UpdateRecordOperation; + let op3 = ops[2] as UpdateRecordOperation; assert.deepEqual( [op1, op2, op3].map((o) => o.record.attributes?.name), @@ -1331,8 +1346,10 @@ module('JSONAPISource - pullable', function (hooks) { source.transformLog.contains(transforms[0].id), 'log contains transform' ); + + const ops = transforms[0].operations as RecordOperation[]; assert.deepEqual( - transforms[0].operations.map((o) => o.op), + ops.map((o) => o.op), [ 'updateRecord', 'updateRecord', @@ -1343,9 +1360,9 @@ module('JSONAPISource - pullable', function (hooks) { ] ); - let op1 = transforms[0].operations[0] as UpdateRecordOperation; - let op2 = transforms[0].operations[1] as UpdateRecordOperation; - let op3 = transforms[0].operations[2] as UpdateRecordOperation; + let op1 = ops[0] as UpdateRecordOperation; + let op2 = ops[1] as UpdateRecordOperation; + let op3 = ops[2] as UpdateRecordOperation; assert.deepEqual( [op1, op2, op3].map((o) => o.record.attributes?.name), @@ -1402,8 +1419,10 @@ module('JSONAPISource - pullable', function (hooks) { source.transformLog.contains(transforms[0].id), 'log contains transform' ); + + const ops = transforms[0].operations as RecordOperation[]; assert.deepEqual( - transforms[0].operations.map((o) => o.op), + ops.map((o) => o.op), [ 'updateRecord', 'updateRecord', @@ -1414,9 +1433,9 @@ module('JSONAPISource - pullable', function (hooks) { ] ); - let op1 = transforms[0].operations[0] as UpdateRecordOperation; - let op2 = transforms[0].operations[1] as UpdateRecordOperation; - let op3 = transforms[0].operations[2] as UpdateRecordOperation; + let op1 = ops[0] as UpdateRecordOperation; + let op2 = ops[1] as UpdateRecordOperation; + let op3 = ops[2] as UpdateRecordOperation; assert.deepEqual( [op1, op2, op3].map((o) => o.record.attributes?.name), @@ -1573,15 +1592,17 @@ module('JSONAPISource - pullable', function (hooks) { source.transformLog.contains(transforms[0].id), 'log contains transform' ); + + const ops = transforms[0].operations as RecordOperation[]; assert.deepEqual( - transforms[0].operations.map((o) => o.op), + ops.map((o) => o.op), ['updateRecord', 'replaceRelatedRecords'] ); - const op1 = transforms[0].operations[0] as UpdateRecordOperation; + const op1 = ops[0] as UpdateRecordOperation; assert.equal(op1.record.attributes?.name, 'Io'); - const op2 = transforms[0].operations[1] as ReplaceRelatedRecordsOperation; + const op2 = ops[1] as ReplaceRelatedRecordsOperation; assert.equal(op2.record.id, planet.id); assert.equal(op2.relationship, 'moons'); assert.deepEqual( @@ -1671,11 +1692,11 @@ module('JSONAPISource - pullable', function (hooks) { assert.equal(transforms.length, 1, 'one transform returned'); assert.deepEqual( - transforms[0].operations.map((o) => o.op), + toArray(transforms[0].operations).map((o) => o.op), ['updateRecord', 'updateRecord'] ); assert.deepEqual( - transforms[0].operations.map( + toArray(transforms[0].operations).map( (o) => (o as UpdateRecordOperation).record.attributes?.name ), ['Jupiter', 'Earth'] @@ -1726,22 +1747,22 @@ module('JSONAPISource - pullable', function (hooks) { assert.equal(transforms.length, 2, 'two transforms returned'); assert.deepEqual( - transforms[0].operations.map((o) => o.op), + toArray(transforms[0].operations).map((o) => o.op), ['updateRecord', 'updateRecord'] ); assert.deepEqual( - transforms[0].operations.map( + toArray(transforms[0].operations).map( (o) => (o as UpdateRecordOperation).record.attributes?.name ), ['Jupiter', 'Earth'] ); assert.deepEqual( - transforms[1].operations.map((o) => o.op), + toArray(transforms[1].operations).map((o) => o.op), ['updateRecord', 'updateRecord'] ); assert.deepEqual( - transforms[1].operations.map( + toArray(transforms[1].operations).map( (o) => (o as UpdateRecordOperation).record.attributes?.name ), ['Io', 'Europa'] diff --git a/packages/@orbit/jsonapi/test/jsonapi-source-pushable-test.ts b/packages/@orbit/jsonapi/test/jsonapi-source-pushable-test.ts index c2db675b9..eb50747a8 100644 --- a/packages/@orbit/jsonapi/test/jsonapi-source-pushable-test.ts +++ b/packages/@orbit/jsonapi/test/jsonapi-source-pushable-test.ts @@ -14,6 +14,7 @@ import { RecordTransform, UpdateRecordOperation } from '@orbit/records'; +import { toArray } from '@orbit/utils'; import * as sinon from 'sinon'; import { SinonStub } from 'sinon'; import { JSONAPIResourceSerializer } from '../src'; @@ -90,7 +91,7 @@ module('JSONAPISource - pushable', function (hooks) { if (transformCount === 1) { assert.deepEqual( transform.operations, - [addPlanetOp], + addPlanetOp, 'transform event initially returns add-record op' ); } else if (transformCount === 2) { @@ -220,7 +221,7 @@ module('JSONAPISource - pushable', function (hooks) { if (transformCount === 1) { assert.deepEqual( transform.operations, - [addPlanetOp], + addPlanetOp, 'transform event initially returns add-record op' ); } else if (transformCount === 2) { @@ -231,7 +232,7 @@ module('JSONAPISource - pushable', function (hooks) { 'transform event then returns add-remote-id op' ); } else if (transformCount === 3) { - let operationsWithoutId = transform.operations.map((op) => { + let operationsWithoutId = toArray(transform.operations).map((op) => { let clonedOp = Object.assign({}, op) as RecordOperation; delete (clonedOp as any).record.id; return clonedOp; @@ -363,7 +364,7 @@ module('JSONAPISource - pushable', function (hooks) { if (transformCount === 1) { assert.deepEqual( transform.operations, - [replacePlanetOp], + replacePlanetOp, 'transform event initially returns replace-record op' ); } @@ -486,7 +487,7 @@ module('JSONAPISource - pushable', function (hooks) { )) as RecordTransform[]; assert.deepEqual( - transforms[1].operations.map((o) => o.op), + toArray(transforms[1].operations).map((o) => o.op), ['replaceAttribute', 'replaceKey'] ); const ops = transforms[1].operations as ReplaceKeyOperation[]; @@ -1021,7 +1022,7 @@ module('JSONAPISource - pushable', function (hooks) { if (transformCount === 1) { assert.deepEqual( transform.operations, - [addPlanetOp], + addPlanetOp, 'transform event initially returns add-record op' ); } diff --git a/packages/@orbit/jsonapi/test/jsonapi-source-updatable-test.ts b/packages/@orbit/jsonapi/test/jsonapi-source-updatable-test.ts index 85b306d7a..c1bc01431 100644 --- a/packages/@orbit/jsonapi/test/jsonapi-source-updatable-test.ts +++ b/packages/@orbit/jsonapi/test/jsonapi-source-updatable-test.ts @@ -9,6 +9,7 @@ import { AddRecordOperation, UpdateRecordOperation } from '@orbit/records'; +import { toArray } from '@orbit/utils'; import * as sinon from 'sinon'; import { SinonStub } from 'sinon'; import { JSONAPIResourceSerializer } from '../src'; @@ -85,7 +86,7 @@ module('JSONAPISource - updatable', function (hooks) { if (transformCount === 1) { assert.deepEqual( transform.operations, - [addPlanetOp], + addPlanetOp, 'transform event initially returns add-record op' ); } else if (transformCount === 2) { @@ -186,7 +187,7 @@ module('JSONAPISource - updatable', function (hooks) { if (transformCount === 1) { assert.deepEqual( transform.operations, - [addPlanetOp], + addPlanetOp, 'transform event initially returns add-record op' ); } else if (transformCount === 2) { @@ -197,7 +198,7 @@ module('JSONAPISource - updatable', function (hooks) { 'transform event then returns add-remote-id op' ); } else if (transformCount === 3) { - let operationsWithoutId = transform.operations.map((op) => { + let operationsWithoutId = toArray(transform.operations).map((op) => { let clonedOp = Object.assign({}, op) as RecordOperation; delete (clonedOp as any).record.id; return clonedOp; @@ -294,7 +295,7 @@ module('JSONAPISource - updatable', function (hooks) { if (transformCount === 1) { assert.deepEqual( transform.operations, - [replacePlanetOp], + replacePlanetOp, 'transform event initially returns replace-record op' ); } @@ -422,11 +423,13 @@ module('JSONAPISource - updatable', function (hooks) { ); assert.deepEqual( - transforms[1].operations.map((o) => o.op), + toArray(transforms[1].operations).map((o) => o.op), ['replaceAttribute', 'replaceKey'] ); assert.deepEqual( - transforms[1].operations.map((o) => (o as ReplaceKeyOperation).value), + toArray(transforms[1].operations).map( + (o) => (o as ReplaceKeyOperation).value + ), ['Mars', 'remote-id-123'] ); assert.deepEqual(data, { diff --git a/packages/@orbit/jsonapi/test/jsonapi-source-with-legacy-serializer-settings-test.ts b/packages/@orbit/jsonapi/test/jsonapi-source-with-legacy-serializer-settings-test.ts index f2484cf5a..2070bfeef 100644 --- a/packages/@orbit/jsonapi/test/jsonapi-source-with-legacy-serializer-settings-test.ts +++ b/packages/@orbit/jsonapi/test/jsonapi-source-with-legacy-serializer-settings-test.ts @@ -19,6 +19,7 @@ import { ReplaceRelatedRecordsOperation, RecordTransform } from '@orbit/records'; +import { toArray } from '@orbit/utils'; import { jsonapiResponse } from './support/jsonapi'; import { JSONAPISource } from '../src/jsonapi-source'; import { Resource, ResourceDocument } from '../src/resource-document'; @@ -249,7 +250,7 @@ module('JSONAPISource with legacy serialization settings', function () { if (transformCount === 1) { assert.deepEqual( transform.operations, - [addPlanetOp], + addPlanetOp, 'transform event initially returns add-record op' ); } else if (transformCount === 2) { @@ -379,7 +380,7 @@ module('JSONAPISource with legacy serialization settings', function () { if (transformCount === 1) { assert.deepEqual( transform.operations, - [addPlanetOp], + addPlanetOp, 'transform event initially returns add-record op' ); } else if (transformCount === 2) { @@ -390,7 +391,7 @@ module('JSONAPISource with legacy serialization settings', function () { 'transform event then returns add-remote-id op' ); } else if (transformCount === 3) { - let operationsWithoutId = transform.operations.map((op) => { + let operationsWithoutId = toArray(transform.operations).map((op) => { let clonedOp = Object.assign({}, op) as RecordOperation; delete (clonedOp as any).record.id; return clonedOp; @@ -522,7 +523,7 @@ module('JSONAPISource with legacy serialization settings', function () { if (transformCount === 1) { assert.deepEqual( transform.operations, - [replacePlanetOp], + replacePlanetOp, 'transform event initially returns replace-record op' ); } @@ -645,11 +646,13 @@ module('JSONAPISource with legacy serialization settings', function () { )) as RecordTransform[]; assert.deepEqual( - transforms[1].operations.map((o) => o.op), + toArray(transforms[1].operations).map((o) => o.op), ['replaceAttribute', 'replaceKey'] ); assert.deepEqual( - transforms[1].operations.map((o) => (o as ReplaceKeyOperation).value), + toArray(transforms[1].operations).map( + (o) => (o as ReplaceKeyOperation).value + ), ['Mars', 'remote-id-123'] ); }); @@ -1180,7 +1183,7 @@ module('JSONAPISource with legacy serialization settings', function () { if (transformCount === 1) { assert.deepEqual( transform.operations, - [addPlanetOp], + addPlanetOp, 'transform event initially returns add-record op' ); } else if (transformCount === 2) { @@ -1281,7 +1284,7 @@ module('JSONAPISource with legacy serialization settings', function () { if (transformCount === 1) { assert.deepEqual( transform.operations, - [addPlanetOp], + addPlanetOp, 'transform event initially returns add-record op' ); } else if (transformCount === 2) { @@ -1292,7 +1295,7 @@ module('JSONAPISource with legacy serialization settings', function () { 'transform event then returns add-remote-id op' ); } else if (transformCount === 3) { - let operationsWithoutId = transform.operations.map((op) => { + let operationsWithoutId = toArray(transform.operations).map((op) => { let clonedOp = Object.assign({}, op) as RecordOperation; delete (clonedOp as any).record.id; return clonedOp; @@ -1389,7 +1392,7 @@ module('JSONAPISource with legacy serialization settings', function () { if (transformCount === 1) { assert.deepEqual( transform.operations, - [replacePlanetOp], + replacePlanetOp, 'transform event initially returns replace-record op' ); } @@ -1517,11 +1520,13 @@ module('JSONAPISource with legacy serialization settings', function () { ); assert.deepEqual( - transforms[1].operations.map((o) => o.op), + toArray(transforms[1].operations).map((o) => o.op), ['replaceAttribute', 'replaceKey'] ); assert.deepEqual( - transforms[1].operations.map((o) => (o as ReplaceKeyOperation).value), + toArray(transforms[1].operations).map( + (o) => (o as ReplaceKeyOperation).value + ), ['Mars', 'remote-id-123'] ); assert.deepEqual(data, { @@ -2058,11 +2063,11 @@ module('JSONAPISource with legacy serialization settings', function () { 'log contains transform' ); assert.deepEqual( - transforms[0].operations.map((o) => o.op), + toArray(transforms[0].operations).map((o) => o.op), ['updateRecord'] ); assert.deepEqual( - transforms[0].operations.map( + toArray(transforms[0].operations).map( (o) => (o as UpdateRecordOperation).record.attributes?.name ), ['Jupiter'] @@ -2264,11 +2269,11 @@ module('JSONAPISource with legacy serialization settings', function () { 'log contains transform' ); assert.deepEqual( - transforms[0].operations.map((o) => o.op), + toArray(transforms[0].operations).map((o) => o.op), ['updateRecord', 'updateRecord', 'updateRecord'] ); assert.deepEqual( - transforms[0].operations.map( + toArray(transforms[0].operations).map( (o) => (o as UpdateRecordOperation).record.attributes?.name ), ['Jupiter', 'Earth', 'Saturn'] @@ -2325,11 +2330,11 @@ module('JSONAPISource with legacy serialization settings', function () { assert.equal(transforms.length, 1, 'one transform returned'); assert.deepEqual( - transforms[0].operations.map((o) => o.op), + toArray(transforms[0].operations).map((o) => o.op), ['updateRecord'] ); assert.deepEqual( - transforms[0].operations.map( + toArray(transforms[0].operations).map( (o) => (o as UpdateRecordOperation).record.attributes?.name ), ['Earth'] @@ -2379,11 +2384,11 @@ module('JSONAPISource with legacy serialization settings', function () { 'log contains transform' ); assert.deepEqual( - transforms[0].operations.map((o) => o.op), + toArray(transforms[0].operations).map((o) => o.op), ['updateRecord'] ); assert.deepEqual( - transforms[0].operations.map( + toArray(transforms[0].operations).map( (o) => (o as UpdateRecordOperation).record.attributes?.name ), ['Earth'] @@ -2428,11 +2433,11 @@ module('JSONAPISource with legacy serialization settings', function () { 'log contains transform' ); assert.deepEqual( - transforms[0].operations.map((o) => o.op), + toArray(transforms[0].operations).map((o) => o.op), ['updateRecord'] ); assert.deepEqual( - transforms[0].operations.map( + toArray(transforms[0].operations).map( (o) => (o as UpdateRecordOperation).record.attributes?.name ), ['Moon'] @@ -2500,11 +2505,11 @@ module('JSONAPISource with legacy serialization settings', function () { 'log contains transform' ); assert.deepEqual( - transforms[0].operations.map((o) => o.op), + toArray(transforms[0].operations).map((o) => o.op), ['updateRecord', 'updateRecord', 'updateRecord'] ); assert.deepEqual( - transforms[0].operations.map( + toArray(transforms[0].operations).map( (o) => (o as UpdateRecordOperation).record.attributes?.name ), ['Moon', 'Phobos', 'Deimos'] @@ -2562,11 +2567,11 @@ module('JSONAPISource with legacy serialization settings', function () { 'log contains transform' ); assert.deepEqual( - transforms[0].operations.map((o) => o.op), + toArray(transforms[0].operations).map((o) => o.op), ['updateRecord'] ); assert.deepEqual( - transforms[0].operations.map( + toArray(transforms[0].operations).map( (o) => (o as UpdateRecordOperation).record.attributes?.name ), ['Mars'] @@ -2612,11 +2617,11 @@ module('JSONAPISource with legacy serialization settings', function () { 'log contains transform' ); assert.deepEqual( - transforms[0].operations.map((o) => o.op), + toArray(transforms[0].operations).map((o) => o.op), ['updateRecord', 'updateRecord', 'updateRecord'] ); assert.deepEqual( - transforms[0].operations.map( + toArray(transforms[0].operations).map( (o) => (o as UpdateRecordOperation).record.attributes?.name ), ['Earth', 'Jupiter', 'Saturn'] @@ -2662,11 +2667,11 @@ module('JSONAPISource with legacy serialization settings', function () { 'log contains transform' ); assert.deepEqual( - transforms[0].operations.map((o) => o.op), + toArray(transforms[0].operations).map((o) => o.op), ['updateRecord', 'updateRecord', 'updateRecord'] ); assert.deepEqual( - transforms[0].operations.map( + toArray(transforms[0].operations).map( (o) => (o as UpdateRecordOperation).record.attributes?.name ), ['Saturn', 'Jupiter', 'Earth'] @@ -2724,11 +2729,11 @@ module('JSONAPISource with legacy serialization settings', function () { 'log contains transform' ); assert.deepEqual( - transforms[0].operations.map((o) => o.op), + toArray(transforms[0].operations).map((o) => o.op), ['updateRecord', 'updateRecord', 'updateRecord'] ); assert.deepEqual( - transforms[0].operations.map( + toArray(transforms[0].operations).map( (o) => (o as UpdateRecordOperation).record.attributes?.name ), ['Jupiter', 'Saturn', 'Earth'] @@ -2778,11 +2783,11 @@ module('JSONAPISource with legacy serialization settings', function () { 'log contains transform' ); assert.deepEqual( - transforms[0].operations.map((o) => o.op), + toArray(transforms[0].operations).map((o) => o.op), ['updateRecord', 'updateRecord', 'updateRecord'] ); assert.deepEqual( - transforms[0].operations.map( + toArray(transforms[0].operations).map( (o) => (o as UpdateRecordOperation).record.attributes?.name ), ['Jupiter', 'Earth', 'Saturn'] @@ -2842,12 +2847,14 @@ module('JSONAPISource with legacy serialization settings', function () { source.transformLog.contains(transforms[0].id), 'log contains transform' ); + + const ops = transforms[0].operations as RecordOperation[]; assert.deepEqual( - transforms[0].operations.map((o) => o.op), + ops.map((o) => o.op), ['updateRecord', 'addToRelatedRecords'] ); - let op1 = transforms[0].operations[0] as UpdateRecordOperation; + const op1 = ops[0] as UpdateRecordOperation; assert.equal(op1.record.attributes?.name, 'Earth'); @@ -2899,12 +2906,14 @@ module('JSONAPISource with legacy serialization settings', function () { source.transformLog.contains(transforms[0].id), 'log contains transform' ); + + const ops = transforms[0].operations as RecordOperation[]; assert.deepEqual( - transforms[0].operations.map((o) => o.op), + ops.map((o) => o.op), ['updateRecord', 'addToRelatedRecords'] ); - let op1 = transforms[0].operations[0] as UpdateRecordOperation; + const op1 = ops[0] as UpdateRecordOperation; assert.equal(op1.record.attributes?.name, 'Earth'); @@ -2955,12 +2964,14 @@ module('JSONAPISource with legacy serialization settings', function () { source.transformLog.contains(transforms[0].id), 'log contains transform' ); + + const ops = transforms[0].operations as RecordOperation[]; assert.deepEqual( - transforms[0].operations.map((o) => o.op), + ops.map((o) => o.op), ['updateRecord', 'addToRelatedRecords'] ); - let op1 = transforms[0].operations[0] as UpdateRecordOperation; + const op1 = ops[0] as UpdateRecordOperation; assert.equal(op1.record.attributes?.name, 'Moon'); @@ -3030,8 +3041,10 @@ module('JSONAPISource with legacy serialization settings', function () { source.transformLog.contains(transforms[0].id), 'log contains transform' ); + + const ops = transforms[0].operations as RecordOperation[]; assert.deepEqual( - transforms[0].operations.map((o) => o.op), + ops.map((o) => o.op), [ 'updateRecord', 'updateRecord', @@ -3042,9 +3055,9 @@ module('JSONAPISource with legacy serialization settings', function () { ] ); - let op1 = transforms[0].operations[0] as UpdateRecordOperation; - let op2 = transforms[0].operations[1] as UpdateRecordOperation; - let op3 = transforms[0].operations[2] as UpdateRecordOperation; + let op1 = ops[0] as UpdateRecordOperation; + let op2 = ops[1] as UpdateRecordOperation; + let op3 = ops[2] as UpdateRecordOperation; assert.deepEqual( [op1, op2, op3].map((o) => o.record.attributes?.name), @@ -3107,12 +3120,14 @@ module('JSONAPISource with legacy serialization settings', function () { source.transformLog.contains(transforms[0].id), 'log contains transform' ); + + const ops = transforms[0].operations as RecordOperation[]; assert.deepEqual( - transforms[0].operations.map((o) => o.op), + ops.map((o) => o.op), ['updateRecord', 'addToRelatedRecords'] ); - let op1 = transforms[0].operations[0] as UpdateRecordOperation; + const op1 = ops[0] as UpdateRecordOperation; assert.equal(op1.record.attributes?.name, 'Mars'); @@ -3160,8 +3175,10 @@ module('JSONAPISource with legacy serialization settings', function () { source.transformLog.contains(transforms[0].id), 'log contains transform' ); + + const ops = transforms[0].operations as RecordOperation[]; assert.deepEqual( - transforms[0].operations.map((o) => o.op), + ops.map((o) => o.op), [ 'updateRecord', 'updateRecord', @@ -3172,9 +3189,9 @@ module('JSONAPISource with legacy serialization settings', function () { ] ); - let op1 = transforms[0].operations[0] as UpdateRecordOperation; - let op2 = transforms[0].operations[1] as UpdateRecordOperation; - let op3 = transforms[0].operations[2] as UpdateRecordOperation; + let op1 = ops[0] as UpdateRecordOperation; + let op2 = ops[1] as UpdateRecordOperation; + let op3 = ops[2] as UpdateRecordOperation; assert.deepEqual( [op1, op2, op3].map((o) => o.record.attributes?.name), @@ -3225,8 +3242,10 @@ module('JSONAPISource with legacy serialization settings', function () { source.transformLog.contains(transforms[0].id), 'log contains transform' ); + + const ops = transforms[0].operations as RecordOperation[]; assert.deepEqual( - transforms[0].operations.map((o) => o.op), + ops.map((o) => o.op), [ 'updateRecord', 'updateRecord', @@ -3237,9 +3256,9 @@ module('JSONAPISource with legacy serialization settings', function () { ] ); - let op1 = transforms[0].operations[0] as UpdateRecordOperation; - let op2 = transforms[0].operations[1] as UpdateRecordOperation; - let op3 = transforms[0].operations[2] as UpdateRecordOperation; + let op1 = ops[0] as UpdateRecordOperation; + let op2 = ops[1] as UpdateRecordOperation; + let op3 = ops[2] as UpdateRecordOperation; assert.deepEqual( [op1, op2, op3].map((o) => o.record.attributes?.name), @@ -3306,8 +3325,10 @@ module('JSONAPISource with legacy serialization settings', function () { source.transformLog.contains(transforms[0].id), 'log contains transform' ); + + const ops = transforms[0].operations as RecordOperation[]; assert.deepEqual( - transforms[0].operations.map((o) => o.op), + ops.map((o) => o.op), [ 'updateRecord', 'updateRecord', @@ -3318,9 +3339,9 @@ module('JSONAPISource with legacy serialization settings', function () { ] ); - let op1 = transforms[0].operations[0] as UpdateRecordOperation; - let op2 = transforms[0].operations[1] as UpdateRecordOperation; - let op3 = transforms[0].operations[2] as UpdateRecordOperation; + let op1 = ops[0] as UpdateRecordOperation; + let op2 = ops[1] as UpdateRecordOperation; + let op3 = ops[2] as UpdateRecordOperation; assert.deepEqual( [op1, op2, op3].map((o) => o.record.attributes?.name), @@ -3377,8 +3398,10 @@ module('JSONAPISource with legacy serialization settings', function () { source.transformLog.contains(transforms[0].id), 'log contains transform' ); + + const ops = transforms[0].operations as RecordOperation[]; assert.deepEqual( - transforms[0].operations.map((o) => o.op), + ops.map((o) => o.op), [ 'updateRecord', 'updateRecord', @@ -3389,9 +3412,9 @@ module('JSONAPISource with legacy serialization settings', function () { ] ); - let op1 = transforms[0].operations[0] as UpdateRecordOperation; - let op2 = transforms[0].operations[1] as UpdateRecordOperation; - let op3 = transforms[0].operations[2] as UpdateRecordOperation; + let op1 = ops[0] as UpdateRecordOperation; + let op2 = ops[1] as UpdateRecordOperation; + let op3 = ops[2] as UpdateRecordOperation; assert.deepEqual( [op1, op2, op3].map((o) => o.record.attributes?.name), @@ -3548,15 +3571,17 @@ module('JSONAPISource with legacy serialization settings', function () { source.transformLog.contains(transforms[0].id), 'log contains transform' ); + + const ops = transforms[0].operations as RecordOperation[]; assert.deepEqual( - transforms[0].operations.map((o) => o.op), + ops.map((o) => o.op), ['updateRecord', 'replaceRelatedRecords'] ); - const op1 = transforms[0].operations[0] as UpdateRecordOperation; + const op1 = ops[0] as UpdateRecordOperation; assert.equal(op1.record.attributes?.name, 'Io'); - const op2 = transforms[0].operations[1] as ReplaceRelatedRecordsOperation; + const op2 = ops[1] as ReplaceRelatedRecordsOperation; assert.equal(op2.record.id, planet.id); assert.equal(op2.relationship, 'moons'); assert.deepEqual( @@ -5144,7 +5169,7 @@ module('JSONAPISource with legacy serialization settings', function () { if (transformCount === 1) { assert.deepEqual( transform.operations, - [addPlanetOp], + addPlanetOp, 'transform event initially returns add-record op' ); } diff --git a/packages/@orbit/local-storage/src/local-storage-cache.ts b/packages/@orbit/local-storage/src/local-storage-cache.ts index 475db49c0..ed39d72bc 100644 --- a/packages/@orbit/local-storage/src/local-storage-cache.ts +++ b/packages/@orbit/local-storage/src/local-storage-cache.ts @@ -1,4 +1,3 @@ -/* eslint-disable valid-jsdoc */ import { Orbit } from '@orbit/core'; import { InitializedRecord, diff --git a/packages/@orbit/local-storage/src/local-storage-source.ts b/packages/@orbit/local-storage/src/local-storage-source.ts index ce5685222..db28f92de 100644 --- a/packages/@orbit/local-storage/src/local-storage-source.ts +++ b/packages/@orbit/local-storage/src/local-storage-source.ts @@ -215,7 +215,12 @@ export class LocalStorageSource< } if (hints?.data) { - if (transform.operations.length > 1 && Array.isArray(hints.data)) { + if (Array.isArray(transform.operations)) { + assert( + 'LocalStorageSource#update: `hints.data` must be an array if `transform.operations` is an array', + Array.isArray(hints.data) + ); + response.data = (hints.data as RecordOperationResult[]).map((h) => this._retrieveOperationResult(h) ); @@ -225,11 +230,7 @@ export class LocalStorageSource< ); } } else if (results) { - if (transform.operations.length === 1 && Array.isArray(results)) { - response.data = results[0]; - } else { - response.data = results; - } + response.data = results; } if (hints?.details) { @@ -251,7 +252,12 @@ export class LocalStorageSource< if (hints?.data) { response = {}; - if (query.expressions.length > 1 && Array.isArray(hints.data)) { + if (Array.isArray(query.expressions)) { + assert( + 'LocalStorageSource#query: `hints.data` must be an array if `query.expressions` is an array', + Array.isArray(hints.data) + ); + response.data = (hints.data as RecordQueryExpressionResult[]).map((h) => this._retrieveQueryExpressionResult(h) ); @@ -302,15 +308,15 @@ export class LocalStorageSource< const results = this._cache.query(query); - if (query.expressions.length === 1) { - operations = this._operationsFromQueryResult( - results as RecordQueryExpressionResult - ); - } else { + if (Array.isArray(query.expressions)) { operations = []; for (let result of results as RecordQueryExpressionResult[]) { operations.push(...this._operationsFromQueryResult(result)); } + } else { + operations = this._operationsFromQueryResult( + results as RecordQueryExpressionResult + ); } fullResponse.transforms = [buildTransform(operations)]; diff --git a/packages/@orbit/local-storage/test/local-storage-cache-update-test.ts b/packages/@orbit/local-storage/test/local-storage-cache-update-test.ts index 45b3eb11b..f5c3a5930 100644 --- a/packages/@orbit/local-storage/test/local-storage-cache-update-test.ts +++ b/packages/@orbit/local-storage/test/local-storage-cache-update-test.ts @@ -1226,23 +1226,22 @@ module('LocalStorageCache - update', function (hooks) { cache = new LocalStorageCache({ schema, keyMap }); const tb = cache.transformBuilder; - cache.update((t) => [ + cache.update((t) => t.addRecord({ type: 'planet', id: '1', attributes: { name: 'Earth' }, relationships: { moons: { data: [{ type: 'moon', id: 'm1' }] } } }) - ]); + ); let result = cache.update( - (t) => [ + (t) => t.updateRecord({ type: 'planet', id: '1', attributes: { classification: 'terrestrial' } - }) - ], + }), { fullResponse: true } ); @@ -1317,21 +1316,20 @@ module('LocalStorageCache - update', function (hooks) { cache = new LocalStorageCache({ schema, keyMap }); const tb = cache.transformBuilder; - cache.update((t) => [ + cache.update((t) => t.addRecord({ type: 'planet', id: '1', attributes: { name: 'Earth' }, relationships: { moons: { data: [{ type: 'moon', id: 'm1' }] } } }) - ]); + ); let result = cache.update( - (t) => [ + (t) => t.replaceRelatedRecords({ type: 'planet', id: '1' }, 'moons', [ { type: 'moon', id: 'm1' } - ]) - ], + ]), { fullResponse: true } ); @@ -1467,7 +1465,7 @@ module('LocalStorageCache - update', function (hooks) { relationships: { moons: { data: [{ type: 'moon', id: 'm2' }] } } }; - let result = cache.update([tb.addRecord(earth)], { + let result = cache.update(tb.addRecord(earth), { fullResponse: true }); @@ -1522,7 +1520,7 @@ module('LocalStorageCache - update', function (hooks) { 'addRecord full response is correct' ); - result = cache.update([tb.updateRecord(jupiter)], { + result = cache.update(tb.updateRecord(jupiter), { fullResponse: true }); @@ -1607,7 +1605,7 @@ module('LocalStorageCache - update', function (hooks) { const tb = cache.transformBuilder; let result = cache.update( - (t) => [t.addRecord({ id: '1', type: 'planet' })], + (t) => t.addRecord({ id: '1', type: 'planet' }), { fullResponse: true } ); @@ -1644,15 +1642,14 @@ module('LocalStorageCache - update', function (hooks) { ); result = cache.update( - (t) => [ + (t) => t.updateRecord({ id: '1', type: 'planet', relationships: { moons: { data: [] } } - }) - ], + }), { fullResponse: true } ); diff --git a/packages/@orbit/local-storage/test/local-storage-source-pullable-test.ts b/packages/@orbit/local-storage/test/local-storage-source-pullable-test.ts index f13c8554c..39186a117 100644 --- a/packages/@orbit/local-storage/test/local-storage-source-pullable-test.ts +++ b/packages/@orbit/local-storage/test/local-storage-source-pullable-test.ts @@ -3,6 +3,7 @@ import { AddRecordOperation, InitializedRecord, RecordKeyMap, + RecordOperation, RecordSchema, RecordTransform } from '@orbit/records'; @@ -112,8 +113,9 @@ module('LocalStorageSource - pullable', function (hooks) { source.transformLog.contains(transforms[0].id), 'log contains transform' ); + assert.deepEqual( - transforms[0].operations.map((o) => o.op), + (transforms[0].operations as RecordOperation[]).map((o) => o.op), ['updateRecord', 'updateRecord', 'updateRecord'], 'operations match expectations' ); @@ -185,7 +187,7 @@ module('LocalStorageSource - pullable', function (hooks) { 'log contains transform' ); assert.deepEqual( - transforms[0].operations.map((o) => o.op), + (transforms[0].operations as RecordOperation[]).map((o) => o.op), ['updateRecord', 'updateRecord'], 'operations match expectations' ); @@ -236,12 +238,12 @@ module('LocalStorageSource - pullable', function (hooks) { 'log contains transform' ); assert.deepEqual( - transforms[0].operations.map((o) => o.op), + (transforms[0].operations as RecordOperation[]).map((o) => o.op), ['updateRecord', 'updateRecord'], 'operations match expectations' ); assert.deepEqual( - transforms[0].operations.map( + (transforms[0].operations as RecordOperation[]).map( (o) => (o as AddRecordOperation)?.record?.type ), ['planet', 'moon'], @@ -302,8 +304,8 @@ module('LocalStorageSource - pullable', function (hooks) { 'log contains transform' ); assert.deepEqual( - transforms[0].operations.map((o) => o.op), - ['updateRecord'], + (transforms[0].operations as RecordOperation[])[0].op, + 'updateRecord', 'operations match expectations' ); assert.equal( @@ -329,6 +331,10 @@ module('LocalStorageSource - pullable', function (hooks) { source.transformLog.contains(transforms[0].id), 'log contains transform' ); - assert.equal(transforms[0].operations.length, 0, 'no operations returned'); + assert.equal( + (transforms[0].operations as RecordOperation[]).length, + 0, + 'no operations returned' + ); }); }); diff --git a/packages/@orbit/local-storage/test/local-storage-source-queryable-test.ts b/packages/@orbit/local-storage/test/local-storage-source-queryable-test.ts index a9eecceb7..54b7e8dec 100644 --- a/packages/@orbit/local-storage/test/local-storage-source-queryable-test.ts +++ b/packages/@orbit/local-storage/test/local-storage-source-queryable-test.ts @@ -3,6 +3,7 @@ import { InitializedRecord, RecordKeyMap, RecordQuery, + RecordQueryExpression, RecordSchema } from '@orbit/records'; import { LocalStorageSource } from '../src/local-storage-source'; @@ -84,7 +85,7 @@ module('LocalStorageSource - queryable', function (hooks) { attributes: { name: 'Jupiter', classification: 'gas giant' } }; - source.cache.patch((t) => t.addRecord(jupiter)); + source.cache.update((t) => t.addRecord(jupiter)); assert.equal( source.cache.getRecordsSync('planet').length, @@ -111,12 +112,10 @@ module('LocalStorageSource - queryable', function (hooks) { }; source.on('beforeQuery', (query: RecordQuery, hints: any) => { - if (query.expressions[0].op === 'findRecord') { - hints.data = jupiter2; - } + hints.data = jupiter2; }); - source.cache.patch((t) => t.addRecord(jupiter2)); + source.cache.update((t) => t.addRecord(jupiter2)); assert.equal( source.cache.getRecordsSync('planet').length, @@ -155,10 +154,7 @@ module('LocalStorageSource - queryable', function (hooks) { }; source.on('beforeQuery', (query: RecordQuery, hints: any) => { - if ( - query.expressions[0].op === 'findRecords' && - query.options?.sources?.remote.customFilter === 'distantPlanets' - ) { + if (query.options?.sources?.remote.customFilter === 'distantPlanets') { hints.data = [ { type: 'planet', id: 'uranus' }, { type: 'planet', id: 'jupiter' } @@ -166,7 +162,7 @@ module('LocalStorageSource - queryable', function (hooks) { } }); - source.cache.patch((t) => [ + source.cache.update((t) => [ t.addRecord(jupiter), t.addRecord(earth), t.addRecord(uranus) diff --git a/packages/@orbit/local-storage/test/local-storage-source-updatable-test.ts b/packages/@orbit/local-storage/test/local-storage-source-updatable-test.ts index 82aaa6146..d17619c0c 100644 --- a/packages/@orbit/local-storage/test/local-storage-source-updatable-test.ts +++ b/packages/@orbit/local-storage/test/local-storage-source-updatable-test.ts @@ -248,7 +248,7 @@ module('LocalStorageSource - updatable', function (hooks) { attributes: { name: 'Earth' } }; - source.cache.patch((t) => t.addRecord(earth)); + source.cache.update((t) => t.addRecord(earth)); source.on('beforeUpdate', (transform: RecordTransform, hints: any) => { if (transform?.options?.customizeResults) { diff --git a/packages/@orbit/memory/src/memory-source.ts b/packages/@orbit/memory/src/memory-source.ts index 51495be24..d0689df89 100644 --- a/packages/@orbit/memory/src/memory-source.ts +++ b/packages/@orbit/memory/src/memory-source.ts @@ -28,14 +28,14 @@ import { RecordTransformResult, RecordUpdatable } from '@orbit/records'; -import { Dict } from '@orbit/utils'; +import { Dict, toArray } from '@orbit/utils'; import { MemoryCache, MemoryCacheClass, MemoryCacheSettings } from './memory-cache'; -const { deprecate } = Orbit; +const { assert, deprecate } = Orbit; export interface MemorySourceSettings< QO extends RequestOptions = RecordSourceQueryOptions, @@ -189,7 +189,12 @@ export class MemorySource< } if (hints?.data) { - if (transform.operations.length > 1 && Array.isArray(hints.data)) { + if (Array.isArray(transform.operations)) { + assert( + 'MemorySource#update: `hints.data` must be an array if `transform.operations` is an array', + Array.isArray(hints.data) + ); + response.data = (hints.data as RecordOperationResult[]).map((h) => this._retrieveOperationResult(h) ); @@ -199,11 +204,7 @@ export class MemorySource< ); } } else if (results) { - if (transform.operations.length === 1 && Array.isArray(results)) { - response.data = results[0]; - } else { - response.data = results; - } + response.data = results; } if (hints?.details) { @@ -225,7 +226,12 @@ export class MemorySource< if (hints?.data) { response = {}; - if (query.expressions.length > 1 && Array.isArray(hints.data)) { + if (Array.isArray(query.expressions)) { + assert( + 'MemorySource#query: `hints.data` must be an array if `query.expressions` is an array', + Array.isArray(hints.data) + ); + response.data = (hints.data as RecordQueryExpressionResult[]).map((h) => this._retrieveQueryExpressionResult(h) ); @@ -330,7 +336,7 @@ export class MemorySource< let ops: RecordOperation[] = []; transforms.forEach((t) => { - Array.prototype.push.apply(ops, t.operations); + Array.prototype.push.apply(ops, toArray(t.operations)); }); if (coalesce !== false) { diff --git a/packages/@orbit/memory/test/memory-cache-test.ts b/packages/@orbit/memory/test/memory-cache-test.ts index d2fdd5481..0df3a0415 100644 --- a/packages/@orbit/memory/test/memory-cache-test.ts +++ b/packages/@orbit/memory/test/memory-cache-test.ts @@ -975,23 +975,22 @@ module('MemoryCache', function (hooks) { let cache = new MemoryCache({ schema, keyMap }); const tb = cache.transformBuilder; - cache.update((t) => [ + cache.update((t) => t.addRecord({ type: 'planet', id: '1', attributes: { name: 'Earth' }, relationships: { moons: { data: [{ type: 'moon', id: 'm1' }] } } }) - ]); + ); let result = cache.update( - (t) => [ + (t) => t.updateRecord({ type: 'planet', id: '1', attributes: { classification: 'terrestrial' } - }) - ], + }), { fullResponse: true } ); @@ -1066,21 +1065,20 @@ module('MemoryCache', function (hooks) { let cache = new MemoryCache({ schema, keyMap }); const tb = cache.transformBuilder; - cache.update((t) => [ + cache.update((t) => t.addRecord({ type: 'planet', id: '1', attributes: { name: 'Earth' }, relationships: { moons: { data: [{ type: 'moon', id: 'm1' }] } } }) - ]); + ); let result = cache.update( - (t) => [ + (t) => t.replaceRelatedRecords({ type: 'planet', id: '1' }, 'moons', [ { type: 'moon', id: 'm1' } - ]) - ], + ]), { fullResponse: true } ); @@ -1098,11 +1096,10 @@ module('MemoryCache', function (hooks) { ); result = cache.update( - (t) => [ + (t) => t.replaceRelatedRecords({ type: 'planet', id: '1' }, 'moons', [ { type: 'moon', id: 'm2' } - ]) - ], + ]), { fullResponse: true } ); @@ -1209,7 +1206,7 @@ module('MemoryCache', function (hooks) { relationships: { moons: { data: [{ type: 'moon', id: 'm2' }] } } }; - let result = cache.update([tb.addRecord(earth)], { fullResponse: true }); + let result = cache.update(tb.addRecord(earth), { fullResponse: true }); assert.deepEqual(result, { data: earth, @@ -1259,7 +1256,7 @@ module('MemoryCache', function (hooks) { } }); - result = cache.update([tb.updateRecord(jupiter)], { fullResponse: true }); + result = cache.update(tb.updateRecord(jupiter), { fullResponse: true }); assert.deepEqual(result, { data: jupiter, diff --git a/packages/@orbit/memory/test/memory-cache-update-test.ts b/packages/@orbit/memory/test/memory-cache-update-test.ts index a12e142a5..44b39daac 100644 --- a/packages/@orbit/memory/test/memory-cache-update-test.ts +++ b/packages/@orbit/memory/test/memory-cache-update-test.ts @@ -1222,23 +1222,22 @@ module('MemoryCache - update', function (hooks) { const cache = new MemoryCache({ schema, keyMap }); const tb = cache.transformBuilder; - cache.update((t) => [ + cache.update((t) => t.addRecord({ type: 'planet', id: '1', attributes: { name: 'Earth' }, relationships: { moons: { data: [{ type: 'moon', id: 'm1' }] } } }) - ]); + ); let result = cache.update( - (t) => [ + (t) => t.updateRecord({ type: 'planet', id: '1', attributes: { classification: 'terrestrial' } - }) - ], + }), { fullResponse: true } ); @@ -1313,21 +1312,20 @@ module('MemoryCache - update', function (hooks) { const cache = new MemoryCache({ schema, keyMap }); const tb = cache.transformBuilder; - cache.update((t) => [ + cache.update((t) => t.addRecord({ type: 'planet', id: '1', attributes: { name: 'Earth' }, relationships: { moons: { data: [{ type: 'moon', id: 'm1' }] } } }) - ]); + ); let result = cache.update( - (t) => [ + (t) => t.replaceRelatedRecords({ type: 'planet', id: '1' }, 'moons', [ { type: 'moon', id: 'm1' } - ]) - ], + ]), { fullResponse: true } ); @@ -1463,7 +1461,7 @@ module('MemoryCache - update', function (hooks) { relationships: { moons: { data: [{ type: 'moon', id: 'm2' }] } } }; - let result = cache.update([tb.addRecord(earth)], { + let result = cache.update(tb.addRecord(earth), { fullResponse: true }); @@ -1518,7 +1516,7 @@ module('MemoryCache - update', function (hooks) { 'addRecord full response is correct' ); - result = cache.update([tb.updateRecord(jupiter)], { + result = cache.update(tb.updateRecord(jupiter), { fullResponse: true }); @@ -1603,7 +1601,7 @@ module('MemoryCache - update', function (hooks) { const tb = cache.transformBuilder; let result = cache.update( - (t) => [t.addRecord({ id: '1', type: 'planet' })], + (t) => t.addRecord({ id: '1', type: 'planet' }), { fullResponse: true } ); @@ -1640,15 +1638,14 @@ module('MemoryCache - update', function (hooks) { ); result = cache.update( - (t) => [ + (t) => t.updateRecord({ id: '1', type: 'planet', relationships: { moons: { data: [] } } - }) - ], + }), { fullResponse: true } ); diff --git a/packages/@orbit/memory/test/memory-source-queryable-test.ts b/packages/@orbit/memory/test/memory-source-queryable-test.ts index ad1998faa..e199797bf 100644 --- a/packages/@orbit/memory/test/memory-source-queryable-test.ts +++ b/packages/@orbit/memory/test/memory-source-queryable-test.ts @@ -105,9 +105,7 @@ module('MemorySource - queryable', function (hooks) { }; source.on('beforeQuery', (query: RecordQuery, hints: any) => { - if (query.expressions[0].op === 'findRecord') { - hints.data = jupiter2; - } + hints.data = jupiter2; }); source.cache.patch((t) => t.addRecord(jupiter2)); @@ -149,10 +147,7 @@ module('MemorySource - queryable', function (hooks) { }; source.on('beforeQuery', (query: RecordQuery, hints: any) => { - if ( - query.expressions[0].op === 'findRecords' && - query.options?.sources?.remote.customFilter === 'distantPlanets' - ) { + if (query.options?.sources?.remote.customFilter === 'distantPlanets') { hints.data = [ { type: 'planet', id: 'uranus' }, { type: 'planet', id: 'jupiter' } diff --git a/packages/@orbit/record-cache/src/async-record-cache.ts b/packages/@orbit/record-cache/src/async-record-cache.ts index 66dbd2386..b4e06f7e8 100644 --- a/packages/@orbit/record-cache/src/async-record-cache.ts +++ b/packages/@orbit/record-cache/src/async-record-cache.ts @@ -21,7 +21,6 @@ import { RecordQuery, RecordQueryBuilder, RecordQueryExpression, - RecordQueryExpressionResult, RecordQueryResult, recordsReferencedByOperations, RecordTransform, @@ -29,7 +28,7 @@ import { RecordTransformBuilderFunc, RecordTransformResult } from '@orbit/records'; -import { deepGet, Dict } from '@orbit/utils'; +import { deepGet, Dict, toArray } from '@orbit/utils'; import { AsyncOperationProcessor, AsyncOperationProcessorClass @@ -375,24 +374,36 @@ export abstract class AsyncRecordCache< // eslint-disable-next-line @typescript-eslint/no-unused-vars options?: QO ): Promise> { - const results: RecordQueryExpressionResult[] = []; - - for (let expression of query.expressions) { + let data; + + if (Array.isArray(query.expressions)) { + data = []; + for (let expression of query.expressions) { + const queryOperator = this.getQueryOperator(expression.op); + if (!queryOperator) { + throw new Error(`Unable to find query operator: ${expression.op}`); + } + data.push( + await queryOperator( + this, + expression, + this.getQueryOptions(query, expression) + ) + ); + } + } else { + const expression = query.expressions as RecordQueryExpression; const queryOperator = this.getQueryOperator(expression.op); if (!queryOperator) { throw new Error(`Unable to find query operator: ${expression.op}`); } - results.push( - await queryOperator( - this, - expression, - this.getQueryOptions(query, expression) - ) + data = await queryOperator( + this, + expression, + this.getQueryOptions(query, expression) ); } - const data = query.expressions.length === 1 ? results[0] : results; - return { data: data as RequestData }; } @@ -448,17 +459,26 @@ export abstract class AsyncRecordCache< }; } - await this._applyTransformOperations( - transform, - transform.operations, - response, - true - ); let data: RecordTransformResult; - if (transform.operations.length === 1 && Array.isArray(response.data)) { - data = response.data[0]; - } else { + + if (Array.isArray(transform.operations)) { + await this._applyTransformOperations( + transform, + transform.operations, + response, + true + ); data = response.data; + } else { + await this._applyTransformOperation( + transform, + transform.operations, + response, + true + ); + if (Array.isArray(response.data)) { + data = response.data[0]; + } } if (options?.fullResponse) { @@ -491,7 +511,9 @@ export abstract class AsyncRecordCache< ): Promise { const buffer = this._getTransformBuffer(); - const records = recordsReferencedByOperations(transform.operations); + const records = recordsReferencedByOperations( + toArray(transform.operations) + ); const inverseRelationships = await this.getInverseRelationshipsAsync( records ); diff --git a/packages/@orbit/record-cache/src/live-query/live-query.ts b/packages/@orbit/record-cache/src/live-query/live-query.ts index 4d10c48da..285be19c4 100644 --- a/packages/@orbit/record-cache/src/live-query/live-query.ts +++ b/packages/@orbit/record-cache/src/live-query/live-query.ts @@ -54,7 +54,7 @@ export abstract class LiveQuery { constructor(settings: LiveQuerySettings) { assert( 'Only single expression queries are supported on LiveQuery', - settings.query.expressions.length === 1 + !Array.isArray(settings.query.expressions) ); this.debounce = settings.debounce; this._query = settings.query; @@ -62,7 +62,7 @@ export abstract class LiveQuery { operationRelevantForQuery(operation: RecordOperation): boolean { const change = recordOperationChange(operation); - const expression = this._query.expressions[0]; + const expression = this._query.expressions as RecordQueryExpression; return this.queryExpressionRelevantForChange(expression, change); } diff --git a/packages/@orbit/record-cache/src/sync-record-cache.ts b/packages/@orbit/record-cache/src/sync-record-cache.ts index c0a54df3f..6b3d2efa6 100644 --- a/packages/@orbit/record-cache/src/sync-record-cache.ts +++ b/packages/@orbit/record-cache/src/sync-record-cache.ts @@ -19,7 +19,6 @@ import { RecordQuery, RecordQueryBuilder, RecordQueryExpression, - RecordQueryExpressionResult, RecordQueryResult, recordsReferencedByOperations, RecordTransform, @@ -29,7 +28,7 @@ import { SyncRecordQueryable, SyncRecordUpdatable } from '@orbit/records'; -import { deepGet, Dict } from '@orbit/utils'; +import { deepGet, Dict, toArray } from '@orbit/utils'; import { SyncLiveQuery } from './live-query/sync-live-query'; import { SyncCacheIntegrityProcessor } from './operation-processors/sync-cache-integrity-processor'; import { SyncSchemaConsistencyProcessor } from './operation-processors/sync-schema-consistency-processor'; @@ -355,20 +354,36 @@ export abstract class SyncRecordCache< // eslint-disable-next-line @typescript-eslint/no-unused-vars options?: QO ): FullResponse { - const results: RecordQueryExpressionResult[] = []; - - for (let expression of query.expressions) { + let data; + + if (Array.isArray(query.expressions)) { + data = []; + for (let expression of query.expressions) { + const queryOperator = this.getQueryOperator(expression.op); + if (!queryOperator) { + throw new Error(`Unable to find query operator: ${expression.op}`); + } + data.push( + queryOperator( + this, + expression, + this.getQueryOptions(query, expression) + ) + ); + } + } else { + const expression = query.expressions as RecordQueryExpression; const queryOperator = this.getQueryOperator(expression.op); if (!queryOperator) { throw new Error(`Unable to find query operator: ${expression.op}`); } - results.push( - queryOperator(this, expression, this.getQueryOptions(query, expression)) + data = queryOperator( + this, + expression, + this.getQueryOptions(query, expression) ); } - const data = query.expressions.length === 1 ? results[0] : results; - return { data: data as RequestData }; } @@ -422,18 +437,26 @@ export abstract class SyncRecordCache< }; } - this._applyTransformOperations( - transform, - transform.operations, - response, - true - ); - let data: RecordTransformResult; - if (transform.operations.length === 1 && Array.isArray(response.data)) { - data = response.data[0]; - } else { + + if (Array.isArray(transform.operations)) { + this._applyTransformOperations( + transform, + transform.operations, + response, + true + ); data = response.data; + } else { + this._applyTransformOperation( + transform, + transform.operations, + response, + true + ); + if (Array.isArray(response.data)) { + data = response.data[0]; + } } if (options?.fullResponse) { @@ -466,7 +489,9 @@ export abstract class SyncRecordCache< ): RecordTransformBuffer { const buffer = this._getTransformBuffer(); - const records = recordsReferencedByOperations(transform.operations); + const records = recordsReferencedByOperations( + toArray(transform.operations) + ); const inverseRelationships = this.getInverseRelationshipsSync(records); const relatedRecords = inverseRelationships.map((ir) => ir.record); Array.prototype.push.apply(records, relatedRecords); diff --git a/packages/@orbit/record-cache/test/async-record-cache-query-test.ts b/packages/@orbit/record-cache/test/async-record-cache-query-test.ts index d5ff032fd..e07171e47 100644 --- a/packages/@orbit/record-cache/test/async-record-cache-query-test.ts +++ b/packages/@orbit/record-cache/test/async-record-cache-query-test.ts @@ -31,16 +31,16 @@ module('AsyncRecordCache - query', function (hooks) { } }; - const updatedRecord = await cache.update((t) => [ + const updatedRecord = await cache.update((t) => t.addRecord(jupiter) - ]); + ); const foundRecord = await cache.query((q) => q.findRecord({ type: 'planet', id: 'jupiter' }) ); - assert.strictEqual(updatedRecord, jupiter); - assert.strictEqual(foundRecord, jupiter); + assert.strictEqual(updatedRecord, jupiter, 'updated record is correct'); + assert.strictEqual(foundRecord, jupiter, 'found record is correct'); }); test('#query can retrieve multiple expressions', async function (assert) { diff --git a/packages/@orbit/record-cache/test/async-record-cache-update-test.ts b/packages/@orbit/record-cache/test/async-record-cache-update-test.ts index da217b478..fe7bc9d00 100644 --- a/packages/@orbit/record-cache/test/async-record-cache-update-test.ts +++ b/packages/@orbit/record-cache/test/async-record-cache-update-test.ts @@ -975,23 +975,22 @@ module('AsyncRecordCache - update', function (hooks) { test('#update merges records when "replacing" and will not stomp on attributes and relationships that are not replaced', async function (assert) { const tb = cache.transformBuilder; - await cache.update((t) => [ + await cache.update((t) => t.addRecord({ type: 'planet', id: '1', attributes: { name: 'Earth' }, relationships: { moons: { data: [{ type: 'moon', id: 'm1' }] } } }) - ]); + ); let result = await cache.update( - (t) => [ + (t) => t.updateRecord({ type: 'planet', id: '1', attributes: { classification: 'terrestrial' } - }) - ], + }), { fullResponse: true } ); @@ -1065,21 +1064,20 @@ module('AsyncRecordCache - update', function (hooks) { test('#update can replace related records but only if they are different', async function (assert) { const tb = cache.transformBuilder; - await cache.update((t) => [ + await cache.update((t) => t.addRecord({ type: 'planet', id: '1', attributes: { name: 'Earth' }, relationships: { moons: { data: [{ type: 'moon', id: 'm1' }] } } }) - ]); + ); let result = await cache.update( - (t) => [ + (t) => t.replaceRelatedRecords({ type: 'planet', id: '1' }, 'moons', [ { type: 'moon', id: 'm1' } - ]) - ], + ]), { fullResponse: true } ); @@ -1226,7 +1224,7 @@ module('AsyncRecordCache - update', function (hooks) { relationships: { moons: { data: [{ type: 'moon', id: 'm2' }] } } }; - let result = await cache.update([tb.addRecord(earth)], { + let result = await cache.update(tb.addRecord(earth), { fullResponse: true }); @@ -1285,7 +1283,7 @@ module('AsyncRecordCache - update', function (hooks) { 'addRecord full response is correct' ); - result = await cache.update([tb.updateRecord(jupiter)], { + result = await cache.update(tb.updateRecord(jupiter), { fullResponse: true }); @@ -1369,7 +1367,7 @@ module('AsyncRecordCache - update', function (hooks) { const tb = cache.transformBuilder; let result = await cache.update( - (t) => [t.addRecord({ id: '1', type: 'planet' })], + (t) => t.addRecord({ id: '1', type: 'planet' }), { fullResponse: true } ); @@ -1406,15 +1404,14 @@ module('AsyncRecordCache - update', function (hooks) { ); result = await cache.update( - (t) => [ + (t) => t.updateRecord({ id: '1', type: 'planet', relationships: { moons: { data: [] } } - }) - ], + }), { fullResponse: true } ); diff --git a/packages/@orbit/record-cache/test/sync-record-cache-query-test.ts b/packages/@orbit/record-cache/test/sync-record-cache-query-test.ts index 15186c6fb..7e888e29d 100644 --- a/packages/@orbit/record-cache/test/sync-record-cache-query-test.ts +++ b/packages/@orbit/record-cache/test/sync-record-cache-query-test.ts @@ -31,16 +31,16 @@ module('SyncRecordCache - query', function (hooks) { } }; - const updatedRecord = cache.update((t) => [ + const updatedRecord = cache.update((t) => t.addRecord(jupiter) - ]); + ); const foundRecord = cache.query((q) => q.findRecord({ type: 'planet', id: 'jupiter' }) ); - assert.strictEqual(updatedRecord, jupiter); - assert.strictEqual(foundRecord, jupiter); + assert.strictEqual(updatedRecord, jupiter, 'updated record is correct'); + assert.strictEqual(foundRecord, jupiter, 'found record is correct'); }); test('#query can retrieve multiple expressions', function (assert) { diff --git a/packages/@orbit/record-cache/test/sync-record-cache-update-test.ts b/packages/@orbit/record-cache/test/sync-record-cache-update-test.ts index 86fc2d006..118a971b5 100644 --- a/packages/@orbit/record-cache/test/sync-record-cache-update-test.ts +++ b/packages/@orbit/record-cache/test/sync-record-cache-update-test.ts @@ -1222,23 +1222,22 @@ module('SyncRecordCache', function (hooks) { const cache = new ExampleSyncRecordCache({ schema, keyMap }); const tb = cache.transformBuilder; - cache.update((t) => [ + cache.update((t) => t.addRecord({ type: 'planet', id: '1', attributes: { name: 'Earth' }, relationships: { moons: { data: [{ type: 'moon', id: 'm1' }] } } }) - ]); + ); let result = cache.update( - (t) => [ + (t) => t.updateRecord({ type: 'planet', id: '1', attributes: { classification: 'terrestrial' } - }) - ], + }), { fullResponse: true } ); @@ -1313,21 +1312,20 @@ module('SyncRecordCache', function (hooks) { const cache = new ExampleSyncRecordCache({ schema, keyMap }); const tb = cache.transformBuilder; - cache.update((t) => [ + cache.update((t) => t.addRecord({ type: 'planet', id: '1', attributes: { name: 'Earth' }, relationships: { moons: { data: [{ type: 'moon', id: 'm1' }] } } }) - ]); + ); let result = cache.update( - (t) => [ + (t) => t.replaceRelatedRecords({ type: 'planet', id: '1' }, 'moons', [ { type: 'moon', id: 'm1' } - ]) - ], + ]), { fullResponse: true } ); @@ -1463,7 +1461,7 @@ module('SyncRecordCache', function (hooks) { relationships: { moons: { data: [{ type: 'moon', id: 'm2' }] } } }; - let result = cache.update([tb.addRecord(earth)], { + let result = cache.update(tb.addRecord(earth), { fullResponse: true }); @@ -1518,7 +1516,7 @@ module('SyncRecordCache', function (hooks) { 'addRecord full response is correct' ); - result = cache.update([tb.updateRecord(jupiter)], { + result = cache.update(tb.updateRecord(jupiter), { fullResponse: true }); @@ -1603,7 +1601,7 @@ module('SyncRecordCache', function (hooks) { const tb = cache.transformBuilder; let result = cache.update( - (t) => [t.addRecord({ id: '1', type: 'planet' })], + (t) => t.addRecord({ id: '1', type: 'planet' }), { fullResponse: true } ); @@ -1640,15 +1638,14 @@ module('SyncRecordCache', function (hooks) { ); result = cache.update( - (t) => [ + (t) => t.updateRecord({ id: '1', type: 'planet', relationships: { moons: { data: [] } } - }) - ], + }), { fullResponse: true } ); diff --git a/packages/@orbit/records/src/record-query.ts b/packages/@orbit/records/src/record-query.ts index 348d72d92..9df6ea9ae 100644 --- a/packages/@orbit/records/src/record-query.ts +++ b/packages/@orbit/records/src/record-query.ts @@ -5,9 +5,7 @@ import { RecordQueryExpressionResult } from './record-query-expression'; -export interface RecordQuery extends Query { - expressions: RecordQueryExpression[]; -} +export type RecordQuery = Query; export type RecordQueryResult = | RecordQueryExpressionResult diff --git a/packages/@orbit/records/src/record-transform.ts b/packages/@orbit/records/src/record-transform.ts index 01b1e66ce..92fc5de60 100644 --- a/packages/@orbit/records/src/record-transform.ts +++ b/packages/@orbit/records/src/record-transform.ts @@ -2,9 +2,7 @@ import { RecordOperation, RecordOperationResult } from './record-operation'; import { InitializedRecord } from './record'; import { Transform } from '@orbit/data'; -export interface RecordTransform extends Transform { - operations: RecordOperation[]; -} +export type RecordTransform = Transform; export type RecordTransformResult = | RecordOperationResult