Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@logux/core

Package Overview
Dependencies
Maintainers
1
Versions
27
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@logux/core - npm Package Compare versions

Comparing version 0.5.3 to 0.6.0

headers/index.cjs

115

base-node/index.d.ts

@@ -6,4 +6,4 @@ import { Unsubscribe } from 'nanoevents'

interface Authentificator {
(nodeId: string, token: string): Promise<boolean>
interface Authentificator<H> {
(nodeId: string, token: string, headers: H | {}): Promise<boolean>
}

@@ -19,2 +19,6 @@

type EmptyHeaders = {
[key: string]: undefined
}
export interface TokenGenerator {

@@ -24,14 +28,19 @@ (): string | Promise<string>

type NodeState = 'disconnected' | 'connecting' | 'sending' | 'synchronized'
export type NodeState =
| 'disconnected'
| 'connecting'
| 'sending'
| 'synchronized'
type Message =
['error', keyof LoguxErrorOptions, any?] |
['connect', number, string, number, object?] |
['connected', number, string, [number, number], object?] |
['ping', number] |
['pong', number] |
export type Message =
| ['error', keyof LoguxErrorOptions, any?]
| ['connect', number, string, number, object?]
| ['connected', number, string, [number, number], object?]
| ['ping', number]
| ['pong', number]
// Inaccurate type until https://github.com/microsoft/TypeScript/issues/26113
['sync', number, object, object] |
['synced', number] |
['debug', 'error', string]
| ['sync', number, object, object]
| ['synced', number]
| ['debug', 'error', string]
| ['headers', object]

@@ -70,6 +79,10 @@ /**

on (
event: 'connecting' | 'connect' | 'disconnect' | 'message' | 'error',
event: 'connecting' | 'connect' | 'disconnect',
listener: () => void
): Unsubscribe
on (event: 'error', listener: (error: Error) => void): Unsubscribe
on (event: 'message', listener: (msg: Message) => void): Unsubscribe
on (event: 'disconnect', listener: (reason: string) => void): Unsubscribe
/**

@@ -92,5 +105,10 @@ * Start connection. Connection should be in disconnected state

disconnect (reason?: 'error' | 'timeout' | 'destroy'): void
/**
* Optional method to disconnect and unbind all even listeners.
*/
destroy?: () => void
}
type NodeOptions = {
export type NodeOptions<H extends object = {}> = {
/**

@@ -104,3 +122,3 @@ * Client credentials. For example, access token.

*/
auth?: Authentificator
auth?: Authentificator<H>

@@ -126,3 +144,3 @@ /**

*/
subprotocol?: string,
subprotocol?: string

@@ -155,4 +173,5 @@ /**

* @template M Meta’s type.
* @template H Remote headers type.
*/
export class BaseNode<M extends Meta = Meta> {
export class BaseNode<H extends object = {}, L extends Log = Log<Meta>> {
/**

@@ -165,3 +184,6 @@ * @param nodeId Unique current machine name.

constructor (
nodeId: string, log: Log, connection: Connection, options?: NodeOptions
nodeId: string,
log: L,
connection: Connection,
options?: NodeOptions<H>
)

@@ -210,2 +232,13 @@

/**
* Headers set by remote node.
* By default, it is an empty object.
*
* ```js
* let message = I18N_ERRORS[node.remoteHeaders.language || 'en']
* node.log.add({ type: 'error', message })
* ```
*/
remoteHeaders: H | EmptyHeaders
/**
* Minimum version of Logux protocol, which is supported.

@@ -242,3 +275,3 @@ *

*/
log: Log<M>
log: L

@@ -253,3 +286,3 @@ /**

*/
options: NodeOptions
options: NodeOptions<H>

@@ -302,2 +335,12 @@ /**

/**
* Promise for node data initial loadiging.
*/
initializing: Promise<void>
/**
* Time difference between nodes.
*/
timeFix: number
/**
* Subscribe for synchronization events. It implements nanoevents API.

@@ -312,2 +355,3 @@ * Supported events:

* * `debug`: when debug information received from remote node.
* * `headers`: headers was receive from remote node.
*

@@ -325,6 +369,18 @@ * ```js

on (
event: 'state' | 'connect' | 'error' | 'clientError' | 'debug',
event: 'state' | 'connect' | 'debug' | 'headers',
listener: () => void
): Unsubscribe
on (
event: 'error' | 'clientError',
listener: (error: Error) => void
): Unsubscribe
on (
event: 'debug',
listener: (type: 'error', data: string) => void
): Unsubscribe
on (event: 'headers', listener: (headers: H) => void): Unsubscribe
/**

@@ -340,4 +396,5 @@ * Disable throwing a error on error message and create error listener.

* @param listener The error listener.
* @returns Unbind listener from event.
*/
catch (listener: (error: LoguxError) => void): void
catch (listener: (error: LoguxError) => void): Unsubscribe

@@ -369,2 +426,16 @@ /**

destroy (): void
/**
* Set headers for current node.
*
* ```js
* if (navigator) {
* node.setLocalHeaders({ language: navigator.language })
* }
* node.connection.connect()
* ```
*
* @param headers The data object will be set as headers for current node.
*/
setLocalHeaders (headers: object): void
}

126

base-node/index.js
import { createNanoEvents } from 'nanoevents'
import {
sendConnect, sendConnected, connectMessage, connectedMessage
sendConnect,
sendConnected,
connectMessage,
connectedMessage
} from '../connect/index.js'
import {
sendSync, sendSynced, syncMessage, syncedMessage
} from '../sync/index.js'
import { sendSync, sendSynced, syncMessage, syncedMessage } from '../sync/index.js'
import { sendPing, pingMessage, pongMessage } from '../ping/index.js'
import { sendDebug, debugMessage } from '../debug/index.js'
import { sendError, errorMessage } from '../error/index.js'
import { sendHeaders, headersMessage } from '../headers/index.js'
import { LoguxError } from '../logux-error/index.js'

@@ -20,3 +22,3 @@

const BEFORE_AUTH = ['connect', 'connected', 'error', 'debug']
const BEFORE_AUTH = ['connect', 'connected', 'error', 'debug', 'headers']

@@ -42,3 +44,3 @@ async function syncMappedEvent (node, action, meta) {

class BaseNode {
constructor (nodeId, log, connection, options = { }) {
constructor (nodeId, log, connection, options = {}) {
this.remoteNodeId = undefined

@@ -49,3 +51,3 @@ this.remoteProtocol = undefined

this.minProtocol = 3
this.localProtocol = 3
this.localProtocol = 4
this.localNodeId = nodeId

@@ -67,3 +69,3 @@

this.syncing = 0
this.received = { }
this.received = {}

@@ -79,26 +81,27 @@ this.lastSent = 0

this.unbind = []
this.unbind.push(log.on('add', (action, meta) => {
this.onAdd(action, meta)
}))
this.unbind.push(connection.on('connecting', () => {
this.onConnecting()
}))
this.unbind.push(connection.on('connect', () => {
this.onConnect()
}))
this.unbind.push(connection.on('message', message => {
this.onMessage(message)
}))
this.unbind.push(connection.on('error', error => {
if (error.message === 'Wrong message format') {
this.sendError(new LoguxError('wrong-format', error.received))
this.connection.disconnect('error')
} else {
this.error(error)
}
}))
this.unbind.push(connection.on('disconnect', () => {
this.onDisconnect()
}))
this.unbind = [
log.on('add', (action, meta) => {
this.onAdd(action, meta)
}),
connection.on('connecting', () => {
this.onConnecting()
}),
connection.on('connect', () => {
this.onConnect()
}),
connection.on('message', message => {
this.onMessage(message)
}),
connection.on('error', error => {
if (error.message === 'Wrong message format') {
this.sendError(new LoguxError('wrong-format', error.received))
this.connection.disconnect('error')
} else {
this.error(error)
}
}),
connection.on('disconnect', () => {
this.onDisconnect()
})
]

@@ -108,2 +111,4 @@ this.initialized = false

this.initializing = this.initialize()
this.localHeaders = {}
this.remoteHeaders = {}
}

@@ -117,3 +122,7 @@

this.throwsError = false
this.on('error', listener)
let unbind = this.on('error', listener)
return () => {
this.throwsError = true
unbind()
}
}

@@ -146,2 +155,9 @@

setLocalHeaders (headers) {
this.localHeaders = headers
if (this.connected) {
this.sendHeaders(headers)
}
}
send (msg) {

@@ -266,11 +282,16 @@ if (!this.connected) return

if (this.options.outFilter) {
promises.push(this.options.outFilter(action, meta).then(r => {
if (r) {
return [action, meta]
} else {
return false
}
}).catch(e => {
this.error(e)
}))
promises.push(
this.options
.outFilter(action, meta)
.then(r => {
if (r) {
return [action, meta]
} else {
return false
}
})
.catch(e => {
this.error(e)
})
)
} else {

@@ -299,9 +320,13 @@ promises.push(Promise.resolve([action, meta]))

if (this.options.outMap) {
Promise.all(data.entries.map(i => {
return this.options.outMap(i[0], i[1])
})).then(changed => {
this.sendSync(data.added, changed)
}).catch(e => {
this.error(e)
})
Promise.all(
data.entries.map(i => {
return this.options.outMap(i[0], i[1])
})
)
.then(changed => {
this.sendSync(data.added, changed)
})
.catch(e => {
this.error(e)
})
} else {

@@ -374,2 +399,5 @@ this.sendSync(data.added, data.entries)

BaseNode.prototype.sendHeaders = sendHeaders
BaseNode.prototype.headersMessage = headersMessage
const DUILIANS = {

@@ -376,0 +404,0 @@ 金木水火土: '板城烧锅酒'

# Change Log
This project adheres to [Semantic Versioning](http://semver.org/).
## 0.6 ᐁ
* Use WebSocket Protocol version 4.
* Remove `reasons: string` support. It must be always an array.
* Add `parseId()` helper.
* Add headers (by Ivan Menshykov).
* Add `MemoryStore#entries`.
* Allow to pass `undefined` to `isFirstOlder()`.
* Return unbind function from `Node#catch`.
* Rename `WsConnection#WS` to `WsConnection#Class`.
* Rename `Store` type to `LogStore`.
* Fix WebSocket connectivity.
* Improve types (by Nikolay Govorov).
## 0.5.3

@@ -5,0 +18,0 @@ * Fix types.

import { BaseNode } from '../base-node'
import { Meta } from '../log'
import { Log, Meta } from '../log'

@@ -18,2 +18,5 @@ /**

*/
export class ClientNode<M extends Meta = Meta> extends BaseNode<M> { }
export class ClientNode<
H extends object = {},
L extends Log = Log<Meta>
> extends BaseNode<H, L> {}

@@ -10,3 +10,3 @@ import { BaseNode } from '../base-node/index.js'

class ClientNode extends BaseNode {
constructor (nodeId, log, connection, options = { }) {
constructor (nodeId, log, connection, options = {}) {
options = { ...DEFAULT_OPTIONS, ...options }

@@ -13,0 +13,0 @@ super(nodeId, log, connection, options)

@@ -11,3 +11,3 @@ import { LoguxError } from '../logux-error/index.js'

try {
let access = await node.options.auth(nodeId, token)
let access = await node.options.auth(nodeId, token, node.remoteHeaders)
if (access) {

@@ -40,5 +40,8 @@ node.authenticated = true

} else {
node.sendError(new LoguxError('wrong-protocol', {
supported: node.minProtocol, used: ver
}))
node.sendError(
new LoguxError('wrong-protocol', {
supported: node.minProtocol,
used: ver
})
)
node.destroy()

@@ -71,3 +74,3 @@ return false

let options = { }
let options = {}
if (this.options.token) {

@@ -86,2 +89,7 @@ if (typeof this.options.token === 'function') {

if (this.options.fixTime) this.connectSended = this.now()
if (Object.keys(this.localHeaders).length > 0) {
this.sendHeaders(this.localHeaders)
}
this.startTimeout()

@@ -99,3 +107,3 @@ this.send(message)

let options = { }
let options = {}
if (this.options.token) {

@@ -113,2 +121,6 @@ if (typeof this.options.token === 'function') {

if (Object.keys(this.localHeaders).length > 0) {
this.sendHeaders(this.localHeaders)
}
this.send(message)

@@ -119,3 +131,3 @@ }

let start = this.now()
if (!options) options = { }
if (!options) options = {}

@@ -140,3 +152,3 @@ this.remoteNodeId = nodeId

function connectedMessage (ver, nodeId, time, options) {
if (!options) options = { }
if (!options) options = {}

@@ -153,3 +165,3 @@ this.endTimeout()

let roundTrip = now - this.connectSended - authTime
this.timeFix = Math.floor(this.connectSended - time[0] + (roundTrip / 2))
this.timeFix = Math.floor(this.connectSended - time[0] + roundTrip / 2)
}

@@ -170,3 +182,6 @@

export {
sendConnect, sendConnected, connectMessage, connectedMessage
sendConnect,
sendConnected,
connectMessage,
connectedMessage
}

@@ -1,3 +0,7 @@

import { Store } from '../log'
import { LogStore } from '../log'
interface storeCreator {
(): LogStore
}
/**

@@ -17,3 +21,6 @@ * Pass all common tests for Logux store to callback.

export function eachStoreCheck (
test: (name: string, creator: () => Store) => void
test: (
name: string,
testCreator: (storeCreator: storeCreator) => () => void
) => void
): void

@@ -38,6 +38,3 @@ import assert from 'assert'

let store = factory()
await Promise.all([
checkLastAdded(store, 0),
checkLastSynced(store, 0, 0)
])
await Promise.all([checkLastAdded(store, 0), checkLastSynced(store, 0, 0)])
})

@@ -92,7 +89,7 @@

let store = factory()
await store.add({ }, { id: '1 n 0', time: 1, a: 1 })
await store.add({}, { id: '1 n 0', time: 1, a: 1 })
let result = await store.changeMeta('1 n 0', { a: 2, b: 2 })
assert.strictEqual(result, true)
await checkBoth(store, [
[{ }, { id: '1 n 0', time: 1, added: 1, a: 2, b: 2 }]
[{}, { id: '1 n 0', time: 1, added: 1, a: 2, b: 2 }]
])

@@ -120,3 +117,4 @@ })

assert.deepStrictEqual(result, [
{ type: '2' }, { id: '1 node1 1', time: 2, added: 2 }
{ type: '2' },
{ id: '1 node1 1', time: 2, added: 2 }
])

@@ -165,3 +163,3 @@ await checkBoth(store, [

])
await store.removeReason('a', { }, (action, meta) => {
await store.removeReason('a', {}, (action, meta) => {
removed.push([action, meta])

@@ -263,6 +261,6 @@ })

let store = factory()
await store.add({ }, { id: '1 n 0', time: 1, reasons: ['a'] })
await store.add({}, { id: '1 n 0', time: 1, reasons: ['a'] })
await store.removeReason('a', { maxAdded: 0 }, () => {})
await checkBoth(store, [
[{ }, { added: 1, id: '1 n 0', time: 1, reasons: ['a'] }]
[{}, { added: 1, id: '1 n 0', time: 1, reasons: ['a'] }]
])

@@ -321,5 +319,3 @@ })

assert.ok(!meta2)
await checkBoth(store, [
[{ a: 1 }, { id, time: 1, added: 1 }]
])
await checkBoth(store, [[{ a: 1 }, { id, time: 1, added: 1 }]])
})

@@ -351,20 +347,16 @@

let store = factory()
if (typeof store.clean === 'undefined') {
await Promise.resolve()
} else {
await Promise.all([
store.add({ type: 'A' }, { id: '1', time: 1 }),
store.add({ type: 'B' }, { id: '2', time: 2 }),
store.add({ type: 'C' }, { id: '3', time: 3 }),
store.add({ type: 'D' }, { id: '4', time: 4 }),
store.add({ type: 'E' }, { id: '5', time: 5 })
])
await store.clean()
let another = factory()
await Promise.all([
checkBoth(another, []),
checkLastAdded(another, 0),
checkLastSynced(another, 0, 0)
])
}
await Promise.all([
store.add({ type: 'A' }, { id: '1', time: 1 }),
store.add({ type: 'B' }, { id: '2', time: 2 }),
store.add({ type: 'C' }, { id: '3', time: 3 }),
store.add({ type: 'D' }, { id: '4', time: 4 }),
store.add({ type: 'E' }, { id: '5', time: 5 })
])
await store.clean()
let another = factory()
await Promise.all([
checkBoth(another, []),
checkLastAdded(another, 0),
checkLastSynced(another, 0, 0)
])
})

@@ -371,0 +363,0 @@ }

@@ -1,3 +0,10 @@

export { Log, ID, Action, AnyAction, Meta, Store } from './log'
export { BaseNode, Connection, TokenGenerator } from './base-node'
export {
BaseNode,
Connection,
TokenGenerator,
NodeOptions,
NodeState,
Message
} from './base-node'
export { Log, ID, Action, AnyAction, Meta, LogStore, Page } from './log'
export { LoguxError, LoguxErrorOptions } from './logux-error'

@@ -15,2 +22,3 @@ export { ServerConnection } from './server-connection'

export { TestTime } from './test-time'
export { parseId } from './parse-id'
export { TestLog } from './test-log'

@@ -14,2 +14,3 @@ import { ServerConnection } from './server-connection/index.js'

import { TestPair } from './test-pair/index.js'
import { parseId } from './parse-id/index.js'
import { Log } from './log/index.js'

@@ -31,3 +32,4 @@

TestPair,
parseId,
Log
}

@@ -19,2 +19,5 @@ import { Meta } from '..'

*/
export function isFirstOlder(firstMeta: Meta, secondMeta: Meta): boolean
export function isFirstOlder (
firstMeta: Meta | undefined,
secondMeta: Meta | undefined
): boolean
import { Connection } from '../base-node'
export class LocalConnection extends Connection {
other (): LocalConnection
}
/**

@@ -31,3 +35,3 @@ * Two paired loopback connections.

*/
left: Connection
left: LocalConnection

@@ -41,3 +45,3 @@ /**

*/
right: Connection
right: LocalConnection
}

@@ -24,3 +24,3 @@ import { Unsubscribe } from 'nanoevents'

*/
added: number,
added: number

@@ -30,3 +30,3 @@ /**

*/
time: number,
time: number

@@ -36,3 +36,3 @@ /**

*/
id: ID,
id: ID

@@ -47,3 +47,3 @@ /**

*/
subprotocol?: string,
subprotocol?: string

@@ -85,3 +85,3 @@ /**

*/
olderThan?: Meta,
olderThan?: Meta

@@ -91,3 +91,3 @@ /**

*/
youngerThan?: Meta,
youngerThan?: Meta

@@ -112,3 +112,3 @@ /**

type Page = {
export type Page = {
/**

@@ -122,3 +122,3 @@ * Pagination page.

*/
next? (): Promise<Page>
next?(): Promise<Page>
}

@@ -136,3 +136,3 @@

*/
export abstract class Store {
export abstract class LogStore {
/**

@@ -146,3 +146,3 @@ * Add action to store. Action always will have `type` property.

*/
add (action: Action, meta: Meta): Promise<Meta|false>
add (action: Action, meta: Meta): Promise<Meta | false>

@@ -168,3 +168,3 @@ /**

*/
remove (id: ID): Promise<[Action, Meta]|false>
remove (id: ID): Promise<[Action, Meta] | false>

@@ -187,3 +187,3 @@ /**

*/
byId (id: ID): Promise<[Action, Meta]|[null, null]>
byId (id: ID): Promise<[Action, Meta] | [null, null]>

@@ -199,3 +199,5 @@ /**

removeReason (
reason: string, criteria: Criteria, callback: ActionListener<Meta>
reason: string,
criteria: Criteria,
callback: ActionListener<Meta>
): Promise<void>

@@ -233,7 +235,8 @@

type LogOptions = {
type LogOptions<S extends LogStore = LogStore> = {
/**
* Store for log.
*/
store: Store,
store: S
/**

@@ -262,9 +265,14 @@ * Unique current machine name.

*/
export class Log<M extends Meta = Meta> {
export class Log<M extends Meta = Meta, S extends LogStore = LogStore> {
/**
* @param opts Log options.
*/
constructor (opts: LogOptions)
constructor (opts: LogOptions<S>)
/**
* Log store.
*/
store: S
/**
* Unique node ID. It is used in action IDs.

@@ -292,3 +300,3 @@ */

*/
add (action: Action, meta?: Partial<M>): Promise<M|false>
add (action: Action, meta?: Partial<M>): Promise<M | false>

@@ -317,3 +325,4 @@ /**

on (
event: 'preadd' | 'add' | 'clean', listener: ActionListener<M>
event: 'preadd' | 'add' | 'clean',
listener: ActionListener<M>
): Unsubscribe

@@ -349,7 +358,13 @@

*
* @param opts Iterator options.
* @param callback Function will be executed on every action.
* @returns When iteration will be finished by iterator or end of actions.
*/
each (callback: ActionIterator<M>): Promise<void>
/**
* @param opts Iterator options.
* @param callback Function will be executed on every action.
*/
each (opts: GetOptions, callback: ActionIterator<M>): Promise<void>
each (callback: ActionIterator<M>): Promise<void>

@@ -385,3 +400,3 @@ /**

*/
removeReason (reason: string, criteria: Criteria): Promise<void>
removeReason (reason: string, criteria?: Criteria): Promise<void>

@@ -401,3 +416,3 @@ /**

*/
byId (id: ID): Promise<[Action, M]|[null, null]>
byId (id: ID): Promise<[Action, M] | [null, null]>
}
import { createNanoEvents } from 'nanoevents'
class Log {
constructor (opts = { }) {
constructor (opts = {}) {
if (typeof opts.nodeId === 'undefined') {

@@ -29,3 +29,3 @@ throw new Error('Expected node ID')

async add (action, meta = { }) {
async add (action, meta = {}) {
if (typeof action.type === 'undefined') {

@@ -48,3 +48,3 @@ throw new Error('Expected "type" in action')

} else if (!Array.isArray(meta.reasons)) {
meta.reasons = [meta.reasons]
throw new Error('Expected "reasons" to be an array of strings')
}

@@ -54,3 +54,3 @@

if (typeof reason !== 'string') {
throw new Error('Expected "reasons" to be strings')
throw new Error('Expected "reasons" to be an array of strings')
}

@@ -149,3 +149,3 @@ }

removeReason (reason, criteria = { }) {
removeReason (reason, criteria = {}) {
return this.store.removeReason(reason, criteria, (action, meta) => {

@@ -152,0 +152,0 @@ this.emitter.emit('clean', action, meta)

@@ -1,10 +0,13 @@

type Versions = { supported: string, used: string }
type Versions = {
supported: string
used: string
}
export type LoguxErrorOptions = {
'timeout': number,
'bruteforce': void,
'wrong-format': string,
'wrong-protocol': Versions,
'unknown-message': string,
'wrong-credentials': void,
'timeout': number
'bruteforce': void
'wrong-format': string
'wrong-protocol': Versions
'unknown-message': string
'wrong-credentials': void
'wrong-subprotocol': Versions

@@ -37,5 +40,6 @@ }

*/
static description<
T extends keyof LoguxErrorOptions
>(type: T, options?: LoguxErrorOptions[T]): string
static description<T extends keyof LoguxErrorOptions> (
type: T,
options?: LoguxErrorOptions[T]
): string

@@ -47,3 +51,3 @@ /**

*/
constructor(type: T, options?: LoguxErrorOptions[T], received?: boolean)
constructor (type: T, options?: LoguxErrorOptions[T], received?: boolean)

@@ -50,0 +54,0 @@ /**

class LoguxError extends Error {
static describe (type, options) {
if (type === 'timeout') {
return 'A timeout was reached (' + options + 'ms)'
return 'A timeout was reached (' + options + ' ms)'
} else if (type === 'wrong-format') {

@@ -12,7 +12,11 @@ return 'Wrong message format in ' + options

} else if (type === 'wrong-protocol') {
return 'Logux supports protocols only from version ' + options.supported +
', but you use ' + options.used
return (
`Logux supports protocols only from version ${options.supported}` +
`, but you use ${options.used}`
)
} else if (type === 'wrong-subprotocol') {
return 'Only ' + options.supported + ' application subprotocols are ' +
'supported, but you use ' + options.used
return (
`Only ${options.supported} application subprotocols are ` +
`supported, but you use ${options.used}`
)
} else if (type === 'wrong-credentials') {

@@ -19,0 +23,0 @@ return 'Wrong credentials'

@@ -1,2 +0,2 @@

import { Store } from '../log'
import { LogStore, Action, Meta } from '../log'

@@ -18,2 +18,7 @@ /**

*/
export class MemoryStore extends Store { }
export class MemoryStore extends LogStore {
/**
* Actions in the store.
*/
entries: [Action, Meta][]
}

@@ -25,3 +25,3 @@ import { isFirstOlder } from '../is-first-older/index.js'

constructor () {
this.created = []
this.entries = []
this.added = []

@@ -37,3 +37,3 @@ this.lastReceived = 0

let list = this.created
let list = this.entries
for (let i = 0; i < list.length; i++) {

@@ -54,7 +54,7 @@ let [, otherMeta] = list[i]

async byId (id) {
let created = find(this.created, id)
let created = find(this.entries, id)
if (created === -1) {
return [null, null]
} else {
let [action, meta] = this.created[created]
let [action, meta] = this.entries[created]
return [action, meta]

@@ -66,8 +66,8 @@ }

if (typeof created === 'undefined') {
created = find(this.created, id)
created = find(this.entries, id)
if (created === -1) return Promise.resolve(false)
}
let entry = [this.created[created][0], this.created[created][1]]
this.created.splice(created, 1)
let entry = [this.entries[created][0], this.entries[created][1]]
this.entries.splice(created, 1)

@@ -96,3 +96,3 @@ let added = entry[1].added

if (opts.order === 'created') {
entries = this.created
entries = this.entries
} else {

@@ -105,7 +105,7 @@ entries = this.added

async changeMeta (id, diff) {
let index = find(this.created, id)
let index = find(this.entries, id)
if (index === -1) {
return false
} else {
let meta = this.created[index][1]
let meta = this.entries[index][1]
for (let key in diff) meta[key] = diff[key]

@@ -120,5 +120,5 @@ return true

if (criteria.id) {
let index = find(this.created, criteria.id)
let index = find(this.entries, criteria.id)
if (index !== -1) {
let meta = this.created[index][1]
let meta = this.entries[index][1]
let reasonPos = meta.reasons.indexOf(reason)

@@ -128,3 +128,3 @@ if (reasonPos !== -1) {

if (meta.reasons.length === 0) {
callback(this.created[index][0], meta)
callback(this.entries[index][0], meta)
this.remove(criteria.id)

@@ -135,3 +135,3 @@ }

} else {
this.created = this.created.filter(([action, meta]) => {
this.entries = this.entries.filter(([action, meta]) => {
let c = criteria

@@ -170,3 +170,3 @@

async clean () {
this.created = []
this.entries = []
this.added = []

@@ -173,0 +173,0 @@ this.lastReceived = 0

{
"name": "@logux/core",
"version": "0.5.3",
"version": "0.6.0",
"description": "Logux core components",

@@ -23,3 +23,3 @@ "keywords": [

"dependencies": {
"nanoevents": "^5.1.5"
"nanoevents": "^5.1.7"
},

@@ -66,2 +66,7 @@ "type": "module",

},
"./headers/package.json": "./headers/package.json",
"./headers": {
"require": "./headers/index.cjs",
"import": "./headers/index.js"
},
"./is-first-older/package.json": "./is-first-older/package.json",

@@ -92,2 +97,7 @@ "./is-first-older": {

},
"./parse-id/package.json": "./parse-id/package.json",
"./parse-id": {
"require": "./parse-id/index.cjs",
"import": "./parse-id/index.js"
},
"./ping/package.json": "./ping/package.json",

@@ -94,0 +104,0 @@ "./ping": {

@@ -10,3 +10,8 @@ # Logux Core [![Cult Of Martians][cult-img]][cult]

**Documentation: [logux.io]**
* **[Guide, recipes, and API](https://logux.io/)**
* **[Chat](https://gitter.im/logux/logux)** for any questions
* **[Issues](https://github.com/logux/logux/issues)**
and **[roadmap](https://github.com/logux/logux/projects/1)**
* **[Projects](https://logux.io/guide/architecture/parts/)**
inside Logux ecosystem

@@ -13,0 +18,0 @@ This repository contains Logux core components for JavaScript:

@@ -31,8 +31,12 @@ import { Connection } from '../base-node'

/**
* @param connection The connection to be reconnectable.
* @param options Reconnection options.
* Reconnection options.
*/
constructor (connection: Connection, options?: ReconnectOptions)
options: ReconnectOptions
/**
* Fails attempts since the last connected state.
*/
attempts: number
/**
* Should we reconnect connection on next connection break.

@@ -50,6 +54,22 @@ * Next `connect` call will set to `true`.

/**
* Are we in the middle of connecting.
*/
connecting: boolean
/**
* Wrapped connection.
*/
connection: Connection
/**
* @param connection The connection to be reconnectable.
* @param options Reconnection options.
*/
constructor (connection: Connection, options?: ReconnectOptions)
/**
* Unbind all listeners and disconnect. Use it if you will not need
* this class anymore.
*/
destroy (): void
destroy: () => void
}

@@ -14,3 +14,3 @@ const DEFAULT_OPTIONS = {

class Reconnect {
constructor (connection, options = { }) {
constructor (connection, options = {}) {
this.connection = connection

@@ -23,23 +23,23 @@ this.options = { ...DEFAULT_OPTIONS, ...options }

this.unbind = []
this.unbind.push(this.connection.on('message', msg => {
if (msg[0] === 'error' && FATAL_ERRORS.includes(msg[1])) {
this.reconnecting = false
this.unbind = [
this.connection.on('message', msg => {
if (msg[0] === 'error' && FATAL_ERRORS.includes(msg[1])) {
this.reconnecting = false
}
}),
this.connection.on('connecting', () => {
this.connecting = true
}),
this.connection.on('connect', () => {
this.attempts = 0
this.connecting = false
}),
this.connection.on('disconnect', () => {
this.connecting = false
if (this.reconnecting) this.reconnect()
}),
() => {
clearTimeout(this.timer)
}
}))
this.unbind.push(this.connection.on('connecting', () => {
this.connecting = true
}))
this.unbind.push(this.connection.on('connect', () => {
this.attempts = 0
this.connecting = false
}))
this.unbind.push(this.connection.on('disconnect', () => {
this.connecting = false
if (this.reconnecting) this.reconnect()
}))
this.unbind.push(() => {
clearTimeout(this.timer)
})
]

@@ -46,0 +46,0 @@ let visibility = () => {

import { Connection } from '../base-node'
import WebSocket = require('ws')
/**

@@ -18,5 +20,10 @@ * Logux connection for server WebSocket.

/**
* @param ws WebSocket instance
* WebSocket connection instance
*/
constructor (ws: object)
ws: WebSocket
/**
* @param ws WebSocket connection instance
*/
constructor (ws: WebSocket)
}

@@ -13,3 +13,3 @@ import { WsConnection } from '../ws-connection/index.js'

'ServerConnection accepts already connected WebSocket ' +
'instance and could not reconnect it'
'instance and could not reconnect it'
)

@@ -16,0 +16,0 @@ }

import { BaseNode } from '../base-node'
import { Meta } from '../log'
import { Log, Meta } from '../log'

@@ -20,2 +20,5 @@ /**

*/
export class ServerNode<M extends Meta = Meta> extends BaseNode<M> { }
export class ServerNode<
H extends object = {},
L extends Log = Log<Meta>
> extends BaseNode<H, L> {}

@@ -10,3 +10,3 @@ import { BaseNode } from '../base-node/index.js'

class ServerNode extends BaseNode {
constructor (nodeId, log, connection, options = { }) {
constructor (nodeId, log, connection, options = {}) {
options = { ...DEFAULT_OPTIONS, ...options }

@@ -13,0 +13,0 @@ super(nodeId, log, connection, options)

@@ -6,3 +6,3 @@ function sendSync (added, entries) {

for (let [action, originMeta] of entries) {
let meta = { }
let meta = {}
for (let key in originMeta) {

@@ -49,3 +49,3 @@ if (key === 'id') {

if (typeof meta.id === 'number') {
meta.id = (meta.id + this.baseTime) + ' ' + this.remoteNodeId + ' ' + 0
meta.id = meta.id + this.baseTime + ' ' + this.remoteNodeId + ' ' + 0
} else {

@@ -66,25 +66,32 @@ meta.id[0] = meta.id[0] + this.baseTime

if (this.options.inMap) {
process = process.then(([action2, meta2]) => {
return this.options.inMap(action2, meta2)
}).catch(e => {
this.error(e)
})
}
process.then(filtered => {
if (filtered && this.options.inFilter) {
return this.options.inFilter(...filtered).then(res => {
return res ? filtered : false
}).catch(e => {
process = process
.then(([action2, meta2]) => {
return this.options.inMap(action2, meta2)
})
.catch(e => {
this.error(e)
})
} else {
return filtered
}
}).then(changed => {
if (!changed) return false
if (this.received) this.received[changed[1].id] = true
return this.log.add(changed[0], changed[1])
})
}
process
.then(filtered => {
if (filtered && this.options.inFilter) {
return this.options
.inFilter(...filtered)
.then(res => {
return res ? filtered : false
})
.catch(e => {
this.error(e)
})
} else {
return filtered
}
})
.then(changed => {
if (!changed) return false
if (this.received) this.received[changed[1].id] = true
return this.log.add(changed[0], changed[1])
})
promises.push(process)

@@ -91,0 +98,0 @@ }

@@ -23,3 +23,3 @@ import { Log, Action, Meta } from '../log'

*/
export class TestLog extends Log {
export class TestLog<M extends Meta = Meta> extends Log<M> {
/**

@@ -49,3 +49,3 @@ * Return all entries (with metadata) inside log, sorted by created time.

*/
actions: Action[]
actions (): Action[]
}

@@ -5,3 +5,3 @@ import { MemoryStore } from '../memory-store/index.js'

class TestLog extends Log {
constructor (time, id, opts = { }) {
constructor (time, id, opts = {}) {
if (!opts.store) opts.store = new MemoryStore()

@@ -17,3 +17,3 @@ if (typeof opts.nodeId === 'undefined') {

entries () {
return this.store.created
return this.store.entries
}

@@ -20,0 +20,0 @@

@@ -0,3 +1,4 @@

import { BaseNode, Message } from '../base-node'
import { LocalPair } from '../local-pair'
import { BaseNode } from '../base-node'
import { TestLog } from '../test-log'

@@ -32,3 +33,3 @@ /**

*/
leftNode: BaseNode
leftNode: BaseNode<{}, TestLog>

@@ -46,3 +47,3 @@ /**

*/
rightNode: BaseNode
rightNode: BaseNode<{}, TestLog>

@@ -57,3 +58,3 @@ /**

*/
leftSent: string[][]
leftSent: Message[]

@@ -68,3 +69,3 @@ /**

*/
rightSent: string[][]
rightSent: Message[]

@@ -117,3 +118,3 @@ /**

*/
wait (receiver: 'left' | 'right'): Promise<void>
wait (receiver?: 'left' | 'right'): Promise<void>
}

@@ -7,3 +7,3 @@ import { LocalPair } from '../local-pair/index.js'

} else if (typeof obj === 'object') {
let cloned = { }
let cloned = {}
for (let i in obj) {

@@ -26,32 +26,34 @@ cloned[i] = clone(obj[i])

this.left.on('connect', () => {
this.leftEvents.push(['connect'])
if (this.waiting) this.waiting('left')
})
this.right.on('connect', () => {
this.rightEvents.push(['connect'])
if (this.waiting) this.waiting('right')
})
this.unbind = [
this.left.on('connect', () => {
this.leftEvents.push(['connect'])
if (this.waiting) this.waiting('left')
}),
this.right.on('connect', () => {
this.rightEvents.push(['connect'])
if (this.waiting) this.waiting('right')
}),
this.left.on('message', msg => {
let cloned = clone(msg)
this.rightSent.push(cloned)
this.leftEvents.push(['message', cloned])
if (this.waiting) this.waiting('left')
})
this.right.on('message', msg => {
let cloned = clone(msg)
this.leftSent.push(cloned)
this.rightEvents.push(['message', cloned])
if (this.waiting) this.waiting('right')
})
this.left.on('message', msg => {
let cloned = clone(msg)
this.rightSent.push(cloned)
this.leftEvents.push(['message', cloned])
if (this.waiting) this.waiting('left')
}),
this.right.on('message', msg => {
let cloned = clone(msg)
this.leftSent.push(cloned)
this.rightEvents.push(['message', cloned])
if (this.waiting) this.waiting('right')
}),
this.left.on('disconnect', reason => {
this.leftEvents.push(['disconnect', reason])
if (this.waiting) this.waiting('left')
})
this.right.on('disconnect', () => {
this.rightEvents.push(['disconnect'])
if (this.waiting) this.waiting('right')
})
this.left.on('disconnect', reason => {
this.leftEvents.push(['disconnect', reason])
if (this.waiting) this.waiting('left')
}),
this.right.on('disconnect', () => {
this.rightEvents.push(['disconnect'])
if (this.waiting) this.waiting('right')
})
]
}

@@ -58,0 +60,0 @@

import { TestLog } from '../test-log'
import { Store } from '../log'
import { LogStore } from '../log'

@@ -8,7 +8,7 @@ type TestLogOptions = {

*/
nodeId: string,
nodeId: string
/**
* Store for log. Will use {@link MemoryStore} by default.
*/
store: Store
store: LogStore
}

@@ -53,3 +53,3 @@

*/
static getLog (opts: TestLogOptions): TestLog
static getLog (opts?: TestLogOptions): TestLog

@@ -76,3 +76,3 @@ constructor ()

*/
nextLog (opts: TestLogOptions): TestLog
nextLog (opts?: TestLogOptions): TestLog
}

@@ -20,14 +20,26 @@ import { LoguxError } from '../logux-error/index.js'

function isTwoNumbers (value) {
return isArray(value) && value.length === 2 &&
isNumber(value[0]) && isNumber(value[1])
return (
isArray(value) &&
value.length === 2 &&
isNumber(value[0]) &&
isNumber(value[1])
)
}
function isID (value) {
return isArray(value) && value.length === 3 &&
isNumber(value[0]) && isString(value[1]) && isNumber(value[2])
return (
isArray(value) &&
value.length === 3 &&
isNumber(value[0]) &&
isString(value[1]) &&
isNumber(value[2])
)
}
function isMeta (value) {
return isObject(value) && isNumber(value.time) &&
(isNumber(value.id) || isTwoNumbers(value.id) || isID(value.id))
return (
isObject(value) &&
isNumber(value.time) &&
(isNumber(value.id) || isTwoNumbers(value.id) || isID(value.id))
)
}

@@ -37,9 +49,17 @@

connect (msg) {
return isNumber(msg[1]) && isString(msg[2]) && isNumber(msg[3]) &&
return (
isNumber(msg[1]) &&
isString(msg[2]) &&
isNumber(msg[3]) &&
(msg.length === 4 || (msg.length === 5 && isObject(msg[4])))
)
},
connected (msg) {
return isNumber(msg[1]) && isString(msg[2]) && isTwoNumbers(msg[3]) &&
return (
isNumber(msg[1]) &&
isString(msg[2]) &&
isTwoNumbers(msg[3]) &&
(msg.length === 4 || (msg.length === 5 && isObject(msg[4])))
)
},

@@ -79,10 +99,17 @@

duilian (msg) {
return (msg.length === 2) && isString(msg[1])
return msg.length === 2 && isString(msg[1])
},
debug (msg) {
return (msg.length === 3) && isString(msg[1]) &&
(msg[1] === 'error' && isString(msg[2]))
return (
msg.length === 3 &&
isString(msg[1]) &&
msg[1] === 'error' &&
isString(msg[2])
)
},
headers (msg) {
return msg.length === 2 && isObject(msg[1])
}
}

@@ -89,0 +116,0 @@

import { Connection } from '../base-node'
import WebSocket = require('ws')
/**

@@ -13,4 +15,9 @@ * Logux connection for browser WebSocket.

*/
export class WsConnection extends Connection {
export class WsConnection<WS = WebSocket> extends Connection {
/**
* WebSocket instance.
*/
ws?: WS
/**
* @param url WebSocket server URL.

@@ -20,3 +27,3 @@ * @param WS WebSocket class if you want change implementation.

*/
constructor (url: string, WS?: any, opts?: any)
constructor (url: string, Class?: any, opts?: any)
}
import { createNanoEvents } from 'nanoevents'
class WsConnection {
constructor (url, WS, opts) {
constructor (url, Class, opts) {
this.connected = false
this.emitter = createNanoEvents()
if (WS) {
this.WS = WS
if (Class) {
this.Class = Class
} else if (typeof WebSocket !== 'undefined') {
this.WS = WebSocket
this.Class = WebSocket
} else {

@@ -24,6 +24,3 @@ throw new Error('No WebSocket support')

ws.onclose = () => {
if (this.ws) {
this.connected = false
this.emitter.emit('disconnect')
}
this.onclose()
}

@@ -35,3 +32,3 @@

data = JSON.parse(event.data)
} catch (e) {
} catch {
this.error(event.data)

@@ -47,4 +44,6 @@ return

connect () {
if (this.ws) return Promise.resolve()
this.emitter.emit('connecting')
this.init(new this.WS(this.url, undefined, this.opts))
this.init(new this.Class(this.url, undefined, this.opts))

@@ -62,5 +61,5 @@ return new Promise(resolve => {

if (this.ws) {
this.ws.onclose()
this.ws.onclose = undefined
this.ws.close()
this.ws = undefined
this.onclose()
}

@@ -86,4 +85,12 @@ }

}
onclose () {
if (this.ws) {
this.connected = false
this.emitter.emit('disconnect')
this.ws = undefined
}
}
}
export { WsConnection }

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc