chore: add prettier and reformat lib

This commit is contained in:
waterplea
2022-07-24 17:53:24 +03:00
committed by Matt Hill
parent c7006e0eb2
commit 2fef1e572c
12 changed files with 2600 additions and 112 deletions

6
client/.prettierrc Normal file
View File

@@ -0,0 +1,6 @@
{
"singleQuote": true,
"semi": false,
"arrowParens": "avoid",
"trailingComma": "all"
}

View File

@@ -18,9 +18,15 @@ export interface ReplaceOperation<T> extends BaseOperation {
value: T value: T
} }
export type Operation<T> = AddOperation<T> | RemoveOperation | ReplaceOperation<T> export type Operation<T> =
| AddOperation<T>
| RemoveOperation
| ReplaceOperation<T>
export function getValueByPointer<T extends Record<string, T>> (data: T, pointer: string): any { export function getValueByPointer<T extends Record<string, T>>(
data: T,
pointer: string,
): any {
if (pointer === '/') return data if (pointer === '/') return data
try { try {
@@ -43,18 +49,19 @@ export function applyOperation<T> (
switch (op) { switch (op) {
case PatchOp.REMOVE: case PatchOp.REMOVE:
return current === undefined return current === undefined ? null : add
? null
: add
case PatchOp.REPLACE: case PatchOp.REPLACE:
case PatchOp.ADD: case PatchOp.ADD:
return current === undefined return current === undefined ? remove : replace
? remove
: replace
} }
} }
function recursiveApply<T extends Record<string, any> | any[]> (data: T, path: readonly string[], op: PatchOp, value?: any): T { function recursiveApply<T extends Record<string, any> | any[]>(
data: T,
path: readonly string[],
op: PatchOp,
value?: any,
): T {
if (!path.length) return value if (!path.length) return value
// object // object
@@ -68,7 +75,12 @@ function recursiveApply<T extends Record<string, any> | any[]> (data: T, path: r
} }
} }
function recursiveApplyObject<T extends Record<string, any>> (data: T, path: readonly string[], op: PatchOp, value?: any): T { function recursiveApplyObject<T extends Record<string, any>>(
data: T,
path: readonly string[],
op: PatchOp,
value?: any,
): T {
const updated = recursiveApply(data[path[0]], path.slice(1), op, value) const updated = recursiveApply(data[path[0]], path.slice(1), op, value)
const result = { const result = {
...data, ...data,
@@ -82,7 +94,12 @@ function recursiveApplyObject<T extends Record<string, any>> (data: T, path: rea
return result return result
} }
function recursiveApplyArray<T extends any[]> (data: T, path: readonly string[], op: PatchOp, value?: any): T { function recursiveApplyArray<T extends any[]>(
data: T,
path: readonly string[],
op: PatchOp,
value?: any,
): T {
const index = parseInt(path[0]) const index = parseInt(path[0])
const updated = recursiveApply(data[index], path.slice(1), op, value) const updated = recursiveApply(data[index], path.slice(1), op, value)
@@ -105,5 +122,3 @@ function isObject (val: any): val is Record<string, unknown> {
function jsonPathToKeyArray(path: string): string[] { function jsonPathToKeyArray(path: string): string[] {
return path.split('/').slice(1) return path.split('/').slice(1)
} }

View File

@@ -11,15 +11,19 @@ export class PatchDB<T> {
public rpcError$ = new Subject<RPCError>() public rpcError$ = new Subject<RPCError>()
public cache$ = new ReplaySubject<DBCache<T>>(1) public cache$ = new ReplaySubject<DBCache<T>>(1)
private sub = this.sources$.pipe( private sub = this.sources$
switchMap(sources => merge(...sources.map(s => s.watch$(this.store))).pipe( .pipe(
switchMap(sources =>
merge(...sources.map(s => s.watch$(this.store))).pipe(
catchError(e => { catchError(e => {
this.connectionError$.next(e) this.connectionError$.next(e)
return EMPTY return EMPTY
}), }),
)), ),
).subscribe((res) => { ),
)
.subscribe(res => {
if ('result' in res) { if ('result' in res) {
this.store.update(res.result) this.store.update(res.result)
this.cache$.next(this.store.cache) this.cache$.next(this.store.cache)

View File

@@ -8,6 +8,6 @@ export class MockSource<T> implements Source<T> {
constructor(private readonly seed: Observable<Update<T>>) {} constructor(private readonly seed: Observable<Update<T>>) {}
watch$(): Observable<RPCResponse<Update<T>>> { watch$(): Observable<RPCResponse<Update<T>>> {
return this.seed.pipe(map((result) => ({ result, jsonrpc: '2.0' }))) return this.seed.pipe(map(result => ({ result, jsonrpc: '2.0' })))
} }
} }

View File

@@ -1,5 +1,13 @@
import { BehaviorSubject, concat, from, Observable, of } from 'rxjs' import { BehaviorSubject, concat, from, Observable, of } from 'rxjs'
import { concatMap, delay, map, skip, switchMap, take, tap } from 'rxjs/operators' import {
concatMap,
delay,
map,
skip,
switchMap,
take,
tap,
} from 'rxjs/operators'
import { Store } from '../store' import { Store } from '../store'
import { Http, Update } from '../types' import { Http, Update } from '../types'
import { Source } from './source' import { Source } from './source'
@@ -10,7 +18,6 @@ export type PollConfig = {
} }
export class PollSource<T> implements Source<T> { export class PollSource<T> implements Source<T> {
constructor( constructor(
private readonly pollConfig: PollConfig, private readonly pollConfig: PollConfig,
private readonly http: Http<T>, private readonly http: Http<T>,
@@ -19,8 +26,7 @@ export class PollSource<T> implements Source<T> {
watch$(store: Store<T>): Observable<RPCResponse<Update<T>>> { watch$(store: Store<T>): Observable<RPCResponse<Update<T>>> {
const polling$ = new BehaviorSubject('') const polling$ = new BehaviorSubject('')
const updates$ = of({ }) const updates$ = of({}).pipe(
.pipe(
concatMap(_ => store.sequence$), concatMap(_ => store.sequence$),
concatMap(seq => this.http.getRevisions(seq)), concatMap(seq => this.http.getRevisions(seq)),
take(1), take(1),
@@ -43,8 +49,7 @@ export class PollSource<T> implements Source<T> {
return of(res) // takes Dump<T> and converts it into Observable<Dump<T>> return of(res) // takes Dump<T> and converts it into Observable<Dump<T>>
} }
}), }),
map(result => ({ result, map(result => ({ result, jsonrpc: '2.0' })),
jsonrpc: '2.0' })),
) )
} }
} }

View File

@@ -1,14 +1,16 @@
import { Observable } from 'rxjs' import { Observable } from 'rxjs'
import { webSocket, WebSocketSubject, WebSocketSubjectConfig } from 'rxjs/webSocket' import {
webSocket,
WebSocketSubject,
WebSocketSubjectConfig,
} from 'rxjs/webSocket'
import { Update } from '../types' import { Update } from '../types'
import { Source } from './source' import { Source } from './source'
export class WebsocketSource<T> implements Source<T> { export class WebsocketSource<T> implements Source<T> {
private websocket$: WebSocketSubject<RPCResponse<Update<T>>> | undefined private websocket$: WebSocketSubject<RPCResponse<Update<T>>> | undefined
constructor ( constructor(private readonly url: string) {}
private readonly url: string,
) { }
watch$(): Observable<RPCResponse<Update<T>>> { watch$(): Observable<RPCResponse<Update<T>>> {
const fullConfig: WebSocketSubjectConfig<RPCResponse<Update<T>>> = { const fullConfig: WebSocketSubjectConfig<RPCResponse<Update<T>>> = {

View File

@@ -24,11 +24,78 @@ export class Store<T extends { [key: string]: any }> {
watch$(): Observable<T> watch$(): Observable<T>
watch$<P1 extends keyof T>(p1: P1): Observable<NonNullable<T[P1]>> watch$<P1 extends keyof T>(p1: P1): Observable<NonNullable<T[P1]>>
watch$<P1 extends keyof T, P2 extends keyof NonNullable<T[P1]>> (p1: P1, p2: P2): Observable<NonNullable<NonNullable<T[P1]>[P2]>> watch$<P1 extends keyof T, P2 extends keyof NonNullable<T[P1]>>(
watch$<P1 extends keyof T, P2 extends keyof NonNullable<T[P1]>, P3 extends keyof NonNullable<NonNullable<T[P1]>[P2]>> (p1: P1, p2: P2, p3: P3): Observable<NonNullable<NonNullable<NonNullable<T[P1]>[P2]>[P3]>> p1: P1,
watch$<P1 extends keyof T, P2 extends keyof NonNullable<T[P1]>, P3 extends keyof NonNullable<NonNullable<T[P1]>[P2]>, P4 extends keyof NonNullable<NonNullable<NonNullable<T[P1]>[P2]>[P3]>> (p1: P1, p2: P2, p3: P3, p4: P4): Observable<NonNullable<NonNullable<NonNullable<NonNullable<T[P1]>[P2]>[P3]>[P4]>> p2: P2,
watch$<P1 extends keyof T, P2 extends keyof NonNullable<T[P1]>, P3 extends keyof NonNullable<NonNullable<T[P1]>[P2]>, P4 extends keyof NonNullable<NonNullable<NonNullable<T[P1]>[P2]>[P3]>, P5 extends keyof NonNullable<NonNullable<NonNullable<NonNullable<T[P1]>[P2]>[P3]>[P4]>> (p1: P1, p2: P2, p3: P3, p4: P4, p5: P5): Observable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<T[P1]>[P2]>[P3]>[P4]>[P5]>> ): Observable<NonNullable<NonNullable<T[P1]>[P2]>>
watch$<P1 extends keyof T, P2 extends keyof NonNullable<T[P1]>, P3 extends keyof NonNullable<NonNullable<T[P1]>[P2]>, P4 extends keyof NonNullable<NonNullable<NonNullable<T[P1]>[P2]>[P3]>, P5 extends keyof NonNullable<NonNullable<NonNullable<NonNullable<T[P1]>[P2]>[P3]>[P4]>, P6 extends keyof NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<T[P1]>[P2]>[P3]>[P4]>[P5]>> (p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6): Observable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<NonNullable<T[P1]>[P2]>[P3]>[P4]>[P5]>[P6]>> watch$<
P1 extends keyof T,
P2 extends keyof NonNullable<T[P1]>,
P3 extends keyof NonNullable<NonNullable<T[P1]>[P2]>,
>(
p1: P1,
p2: P2,
p3: P3,
): Observable<NonNullable<NonNullable<NonNullable<T[P1]>[P2]>[P3]>>
watch$<
P1 extends keyof T,
P2 extends keyof NonNullable<T[P1]>,
P3 extends keyof NonNullable<NonNullable<T[P1]>[P2]>,
P4 extends keyof NonNullable<NonNullable<NonNullable<T[P1]>[P2]>[P3]>,
>(
p1: P1,
p2: P2,
p3: P3,
p4: P4,
): Observable<
NonNullable<NonNullable<NonNullable<NonNullable<T[P1]>[P2]>[P3]>[P4]>
>
watch$<
P1 extends keyof T,
P2 extends keyof NonNullable<T[P1]>,
P3 extends keyof NonNullable<NonNullable<T[P1]>[P2]>,
P4 extends keyof NonNullable<NonNullable<NonNullable<T[P1]>[P2]>[P3]>,
P5 extends keyof NonNullable<
NonNullable<NonNullable<NonNullable<T[P1]>[P2]>[P3]>[P4]
>,
>(
p1: P1,
p2: P2,
p3: P3,
p4: P4,
p5: P5,
): Observable<
NonNullable<
NonNullable<NonNullable<NonNullable<NonNullable<T[P1]>[P2]>[P3]>[P4]>[P5]
>
>
watch$<
P1 extends keyof T,
P2 extends keyof NonNullable<T[P1]>,
P3 extends keyof NonNullable<NonNullable<T[P1]>[P2]>,
P4 extends keyof NonNullable<NonNullable<NonNullable<T[P1]>[P2]>[P3]>,
P5 extends keyof NonNullable<
NonNullable<NonNullable<NonNullable<T[P1]>[P2]>[P3]>[P4]
>,
P6 extends keyof NonNullable<
NonNullable<NonNullable<NonNullable<NonNullable<T[P1]>[P2]>[P3]>[P4]>[P5]
>,
>(
p1: P1,
p2: P2,
p3: P3,
p4: P4,
p5: P5,
p6: P6,
): Observable<
NonNullable<
NonNullable<
NonNullable<
NonNullable<NonNullable<NonNullable<T[P1]>[P2]>[P3]>[P4]
>[P5]
>[P6]
>
>
watch$(...args: (string | number)[]): Observable<any> { watch$(...args: (string | number)[]): Observable<any> {
const path = `/${args.join('/')}` const path = `/${args.join('/')}`
if (!this.watchedNodes[path]) { if (!this.watchedNodes[path]) {

View File

@@ -1,9 +1,14 @@
import { Operation } from './json-patch-lib' import { Operation } from './json-patch-lib'
// revise a collection of nodes. // revise a collection of nodes.
export type Revision = { id: number, patch: Operation<unknown>[], expireId: string | null } export type Revision = {
id: number
patch: Operation<unknown>[]
expireId: string | null
}
// dump/replace the entire store with T // dump/replace the entire store with T
export type Dump<T> = { id: number, value: T, expireId: string | null } export type Dump<T> = { id: number; value: T; expireId: string | null }
export type Update<T> = Revision | Dump<T> export type Update<T> = Revision | Dump<T>
@@ -24,6 +29,6 @@ export interface Bootstrapper<T> {
} }
export interface DBCache<T extends Record<string, any>> { export interface DBCache<T extends Record<string, any>> {
sequence: number, sequence: number
data: T data: T
} }

2397
client/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -7,7 +7,8 @@
"main": "dist/index.js", "main": "dist/index.js",
"types": "dist/index.d.ts", "types": "dist/index.d.ts",
"scripts": { "scripts": {
"build": "tsc" "build": "tsc",
"check": "tsc --noEmit --skipLibCheck"
}, },
"dependencies": { "dependencies": {
"sorted-btree": "1.5.0", "sorted-btree": "1.5.0",
@@ -19,8 +20,20 @@
"devDependencies": { "devDependencies": {
"@types/node": "16.4.13", "@types/node": "16.4.13",
"@types/uuid": "8.3.1", "@types/uuid": "8.3.1",
"husky": "^4.3.8",
"lint-staged": "^12.3.7",
"prettier": "^2.6.1",
"ts-node": "10.2.0", "ts-node": "10.2.0",
"tslint": "6.1.3", "tslint": "6.1.3",
"typescript": "4.3.5" "typescript": "4.3.5"
},
"husky": {
"hooks": {
"pre-commit": "lint-staged && npm run check"
}
},
"lint-staged": {
"**/*.{js,ts,html,md,less,json}": "prettier --write",
"*.ts": "tslint --fix"
} }
} }

View File

@@ -2,17 +2,9 @@
"rules": { "rules": {
"no-unused-variable": true, "no-unused-variable": true,
"no-unused-expression": true, "no-unused-expression": true,
"space-before-function-paren": true, "semicolon": [true, "never"],
"semicolon": [
true,
"never"
],
"no-trailing-whitespace": true, "no-trailing-whitespace": true,
"indent": [ "indent": [true, "spaces", 2],
true,
"spaces",
2
],
"whitespace": [ "whitespace": [
true, true,
"check-branch", "check-branch",
@@ -24,8 +16,7 @@
"check-type", "check-type",
"check-typecast", "check-typecast",
"check-type-operator", "check-type-operator",
"check-preblock", "check-preblock"
"check-postbrace"
], ],
"trailing-comma": [ "trailing-comma": [
true, true,
@@ -39,9 +30,6 @@
"singleline": "never" "singleline": "never"
} }
], ],
"quotemark": [ "quotemark": [true, "single"]
true,
"single"
]
} }
} }