-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #5 from jsonjoy-com/server
Server
- Loading branch information
Showing
22 changed files
with
632 additions
and
498 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
38 changes: 17 additions & 21 deletions
38
src/__demos__/json-crdt-server/routes/block/methods/get.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,42 +1,38 @@ | ||
import {ResolveType} from 'json-joy/lib/json-type'; | ||
import {BlockRef, BlockIdRef} from '../schema'; | ||
import type {RouteDeps, Router, RouterBase} from '../../types'; | ||
import type {Block, BlockId, BlockPatch} from '../schema'; | ||
|
||
export const get = | ||
({t, services}: RouteDeps) => | ||
<R extends RouterBase>(r: Router<R>) => { | ||
const Request = t.Object( | ||
t.prop('id', t.Ref<typeof BlockId>('BlockId')).options({ | ||
t.prop('id', BlockIdRef).options({ | ||
title: 'Block ID', | ||
description: 'The ID of the block to retrieve.', | ||
}), | ||
t.propOpt('history', t.bool).options({ | ||
title: 'With History', | ||
description: 'Whether to include the full history of patches in the response. Defaults to `false`.', | ||
}), | ||
); | ||
|
||
const Response = t.Object( | ||
t.prop('model', t.Ref<typeof Block>('Block')), | ||
t.propOpt('patches', t.Array(t.Ref<typeof BlockPatch>('BlockPatch'))).options({ | ||
title: 'Patches', | ||
description: 'The list of all patches.', | ||
}), | ||
); | ||
const Response = t.Object(t.prop('block', BlockRef)); | ||
|
||
const Func = t.Function(Request, Response).options({ | ||
title: 'Read Block', | ||
intro: 'Retrieves a block by ID.', | ||
description: 'Fetches a block by ID.', | ||
}); | ||
|
||
return r.prop('block.get', Func, async ({id, history}) => { | ||
const {model} = await services.blocks.get(id); | ||
const response: ResolveType<typeof Response> = {model}; | ||
if (history) { | ||
const {patches} = await services.blocks.scan(id, 0, model.seq); | ||
response.patches = patches; | ||
} | ||
return r.prop('block.get', Func, async ({id}) => { | ||
const {snapshot} = await services.blocks.get(id); | ||
const response: ResolveType<typeof Response> = { | ||
block: { | ||
id: snapshot.id, | ||
ts: snapshot.created, | ||
snapshot: { | ||
blob: snapshot.blob, | ||
cur: snapshot.seq, | ||
ts: snapshot.created, | ||
}, | ||
tip: [], | ||
}, | ||
}; | ||
return response; | ||
}); | ||
}; |
37 changes: 16 additions & 21 deletions
37
src/__demos__/json-crdt-server/routes/block/methods/listen.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,40 +1,35 @@ | ||
import {switchMap} from 'rxjs'; | ||
import {map, switchMap, tap} from 'rxjs'; | ||
import {BlockEventRef, BlockIdRef} from '../schema'; | ||
import type {RouteDeps, Router, RouterBase} from '../../types'; | ||
import type {BlockId, BlockPatch, Block} from '../schema'; | ||
|
||
export const listen = | ||
({t, services}: RouteDeps) => | ||
<R extends RouterBase>(r: Router<R>) => { | ||
const Request = t.Object( | ||
t.prop('id', t.Ref<typeof BlockId>('BlockId')).options({ | ||
t.prop('id', BlockIdRef).options({ | ||
title: 'Block ID', | ||
description: 'The ID of the block to subscribe to.', | ||
}), | ||
); | ||
|
||
const Response = t.Or( | ||
t.Tuple(t.Const('del')), | ||
t.Tuple( | ||
t.Const('upd'), | ||
t.Object( | ||
t.propOpt('model', t.Ref<typeof Block>('Block')).options({ | ||
title: 'Block', | ||
description: 'The whole block object, emitted only when the block is created.', | ||
}), | ||
t.propOpt('patches', t.Array(t.Ref<typeof BlockPatch>('BlockPatch'))).options({ | ||
title: 'Latest Patches', | ||
description: 'Patches that have been applied to the block.', | ||
}), | ||
), | ||
), | ||
); | ||
const Response = t.Object(t.prop('event', BlockEventRef)); | ||
|
||
const Func = t.Function$(Request, Response).options({ | ||
title: 'Listen for block changes', | ||
description: 'Subscribe to a block to receive updates when it changes.', | ||
description: `Subscribe to a block to receive updates when it changes.`, | ||
}); | ||
|
||
return r.prop('block.listen', Func, (req$) => { | ||
return req$.pipe(switchMap(({id}) => services.pubsub.listen$(`__block:${id}`))) as any; | ||
const response = req$.pipe( | ||
switchMap(({id}) => { | ||
return services.blocks.listen(id); | ||
}), | ||
map((event) => { | ||
return { | ||
event, | ||
}; | ||
}), | ||
); | ||
return response; | ||
}); | ||
}; |
55 changes: 41 additions & 14 deletions
55
src/__demos__/json-crdt-server/routes/block/methods/new.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,36 +1,63 @@ | ||
import { | ||
BlockIdRef, | ||
BlockPatchPartialRef, | ||
BlockPatchPartialReturnRef, | ||
BlockNewRef, | ||
NewBlockSnapshotResponseRef, | ||
} from '../schema'; | ||
import type {RouteDeps, Router, RouterBase} from '../../types'; | ||
import type {Block, BlockId, BlockPatchPartial, BlockPatchPartialReturn} from '../schema'; | ||
|
||
export const new_ = | ||
({t, services}: RouteDeps) => | ||
<R extends RouterBase>(r: Router<R>) => { | ||
const Request = t.Object( | ||
t.prop('id', t.Ref<typeof BlockId>('BlockId')).options({ | ||
t.prop('id', BlockIdRef).options({ | ||
title: 'New block ID', | ||
description: 'The ID of the new block.', | ||
description: | ||
'The ID of the new block. Must be a unique ID, if the block already exists it will return an error.', | ||
}), | ||
t.prop('patches', t.Array(t.Ref<typeof BlockPatchPartial>('BlockPatchPartial'))).options({ | ||
t.prop('patches', t.Array(BlockPatchPartialRef)).options({ | ||
title: 'Patches', | ||
description: 'The patches to apply to the document.', | ||
}), | ||
); | ||
|
||
const Response = t.Object( | ||
t.prop('model', t.Ref<typeof Block>('Block')), | ||
t.prop('patches', t.Array(t.Ref<typeof BlockPatchPartialReturn>('BlockPatchPartialReturn'))).options({ | ||
title: 'Patches', | ||
description: 'The list of all patches.', | ||
}), | ||
); | ||
const Response = t | ||
.Object( | ||
t.prop('block', BlockNewRef), | ||
t.prop('snapshot', NewBlockSnapshotResponseRef), | ||
t.prop('patches', t.Array(BlockPatchPartialReturnRef)).options({ | ||
title: 'Patches', | ||
description: 'The list of patches to apply to the newly created block.', | ||
}), | ||
) | ||
.options({ | ||
title: 'New block creation response', | ||
description: | ||
'The response object for the new block creation, contains server generated metadata without blobs supplied by the client.', | ||
}); | ||
|
||
const Func = t.Function(Request, Response).options({ | ||
title: 'Create Block', | ||
intro: 'Creates a new block or applies patches to it.', | ||
description: 'Creates a new block or applies patches to it.', | ||
intro: 'Creates a new block out of patches.', | ||
description: | ||
'Creates a new block out of supplied patches. A block starts empty with an `undefined` state, and patches are applied to it.', | ||
}); | ||
|
||
return r.prop('block.new', Func, async ({id, patches}) => { | ||
const res = await services.blocks.create(id, patches); | ||
return res; | ||
return { | ||
block: { | ||
id: res.snapshot.id, | ||
ts: res.snapshot.created, | ||
}, | ||
snapshot: { | ||
cur: res.snapshot.seq, | ||
ts: res.snapshot.created, | ||
}, | ||
patches: res.patches.map((patch) => ({ | ||
ts: patch.created, | ||
})), | ||
}; | ||
}); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.