All files / rpc-server/src/__demos__/json-crdt-server/routes/block/methods upd.ts

96.29% Statements 26/27
87.5% Branches 7/8
100% Functions 3/3
96.15% Lines 25/26

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96  4x                   4x 4x 69x 69x                                       69x                                         69x           69x 831x 831x 828x               828x 9x 9x     9x   9x 3x 3x 3x   6x 6x 6x   9x     828x 828x      
import type {ResolveType} from '@jsonjoy.com/json-type';
import {
  BlockBatchPartialRef,
  BlockBatchPartialReturnRef,
  BlockBatchRef,
  BlockCurRef,
  BlockIdRef,
  BlockSnapshotRef,
} from '../schema';
import type {RouteDeps, Router, RouterBase} from '../../types';
 
export const upd =
  ({t, services}: RouteDeps) =>
  <R extends RouterBase>(r: Router<R>) => {
    const Request = t.Object(
      t.Key('id', BlockIdRef).options({
        title: 'Document ID',
        description: 'The ID of the document to apply the patch to.',
      }),
      t.Key('batch', BlockBatchPartialRef).options({
        title: 'Batch',
        description: 'The batch of changes to apply to the document.',
      }),
      t.KeyOpt('create', t.bool).options({
        title: 'Create, if not Exists',
        description: 'If true, creates a new document if it does not exist.',
      }),
      t.KeyOpt('seq', BlockCurRef).options({
        title: 'Sequence Number',
        description:
          'The last client known sequence number. The server will return history starting from this sequence number.',
      }),
    );
 
    const Response = t.Object(
      t.Key('batch', BlockBatchPartialReturnRef).options({
        title: 'Committed Batch Parts',
        description: 'Parts of committed batch which were generated on the server.',
      }),
      t.KeyOpt(
        'pull',
        t.Object(
          t.Key('batches', t.Array(BlockBatchRef)).options({
            title: 'Batches',
            description: 'The list of batches that happened after the given sequence number.',
          }),
          t.KeyOpt('snapshot', BlockSnapshotRef).options({
            title: 'Snapshot',
            description:
              'The snapshot of the block, to which the batches can be applied to get the current state of the block.',
          }),
        ),
      ),
    );
 
    const Func = t.Function(Request, Response).options({
      title: 'Edit Block',
      intro: 'Applies patches to an existing block.',
      description: 'Applies patches to an existing document and returns the latest concurrent changes.',
    });
 
    return r.add('block.upd', Func, async ({id, batch, create, seq}) => {
      const blocks = services.blocks;
      const res = await blocks.edit(id, batch, !!create);
      const response: ResolveType<typeof Response> = {
        batch: {
          seq: res.batch.seq,
          ts: res.batch.ts,
        },
      };
      type Pull = ResolveType<typeof Response>['pull'];
      let pull: Pull;
      if (typeof seq === 'number') {
        const diff = res.batch.seq - seq;
        Iif (diff <= 1) {
          pull = {batches: []};
        } else {
          const needsSnapshot = diff > 100;
          let min: number, max: number, limit: number;
          if (needsSnapshot) {
            min = res.batch.seq - 100;
            max = res.batch.seq - 1;
            limit = max - min + 1;
          } else {
            min = seq + 1;
            max = res.batch.seq - 1;
            limit = max - min + 1;
          }
          pull = (await blocks.scan(id, needsSnapshot, min, limit)) as Pull;
        }
      }
      if (pull) response.pull = pull;
      return response;
    });
  };