1.1.470 • Published 10 months ago

one v1.1.470

Weekly downloads
269
License
BSD-3-Clause
Repository
-
Last release
10 months ago

One logo

ONE

One is a browser side application cache. It guarantees entity uniqueness across the entire cache.

Npm Status Build Status Coverage Status

Each entity tracked for uniqueness must have a unique id. There is precisely ONE distinct entity in the cache for each unique id. Entities that do not have a unique id are still cached but not tracked for uniqueness.

Changes

  1. Complete rewrite in typescript.
  2. Fix some subtle bugs related to object structure (ie modifiying arrays would sometimes behave unpredictably based on the parent's structure).
  3. Remove the need for babel-polyfill
  4. Breaking api changes: Simplified minimal api. You really only need the commands in the table below. There are a couple of other options mostly for debugging (see the Api section for the development api list).
CommandAction
getCacheCreate or access a specific version of the cache. There can be multiple concurrent versions of the cache in case distinct versions of the same entity are needed (for example if display and edit data need to be different until a user commits changes). One.getCache('edit') would create a cache dedicated to edit operations.
putAdd an entity to the cache and make it immutable.
getRetrieve an entity from the cache. This is a fast hash map locator.
getEditGet a shallow editable version of the entity from the cache. Inner nested entities are still immutable. This is in order to make efficient use of trie structures.
evictRemove an entity from the cache. Evicts it from all parents as well.

Api

In addition to the 5 production api commands there are 4 options intended for development:

CommandAction
resetResets the cache to empty. Useful for testing.
lengthNumber of nodes in the current cache. Each node contains one atomic change to the cache so moving between nodes gives you time travelling.
sizeNumber of entities cached on the current node (the size of the node).
printProvides a printable representation of the entire cache that can be passed on to a logger. Slow. For debugging only. Do not use in production.

Usage

npm install one --save

or

yarn add one

Use it

import * as One from 'one'

// get a hold of an instance
let one = One.getCache()

// you can then use the instance to cache items
one.put(item)

// One.getCache() is a singleton so you can also do this
One.getCache().put(item)

// or if you are only using the default instance of the cache
One.put(item)

Or simply put one.min.js on your page to access the One global variable from anywhere. In this case the instance is created for you and you can access it directly.

One.put(item)

Some code

let item1 = { uid:1 }
let item2 = { uid:2, ref:item1 }

One.put(item2)

// puts all items with uid separately in the cache

One.get(item1) === undefined // false (item1 is added from item2)
item1 === One.get(item1) // true (same object)
item2.ref === One.get(1) // true

Immutable

All data is immutable. Once an item enters the cache it freezes and cannot change. This is to enable quick identity checks against immutable entities (ie React / Redux identity check).

let item = { uid:1 }
Object.isFrozen(item) // false

One.put(item);
Object.isFrozen(item) // true

let result = One.get(item)
result === item // true

If you later want to edit a reference of the object you can get an editable copy from the cache. This gives you a separate clone of the object that is now editable:

let item = { uid:1 }
One.put(item)

let editable = One.getEdit(1) // or cuid.getEditable(item1);
Object.isFrozen(editable) // false
item === editable // false

editable.text = "test"
One.put(editable)

let edited = One.get(1)
edited.text = "text" // true
Object.isFrozen(edited) // true

Important Edit clones are shallow. If you want to edit a nested child that also has a uid you must get an editable copy of the child.

const item1 = { uid:1 } // uid item cached separately
const item2 = { value: 'test' } // item has no uid - it will be cloned for edit
const item = {
  uid: 1,
  item1,
  item2
}

one.put(item)

const editable = one.getEdit(item)

Object.isFrozen(editable.item1) // true - item1 has a uid - not cloned
item1 === editable.item1 // true

Object.isFrozen(editable.item2) // false item2 has no uid - it will be cloned
item2 === editable.item2 // false

Editing an item changes all its instances in the cache:

let item = { uid:1 }
let item2 = { uid:2, child:item }

One.put(item2)

One.get(1) === item // true
One.get(2) === item2 // true

// Let's do some editing
let editable = One.getEdit(1);
editable.text = "test"
One.put(editable) // also updates item2 reference to item

let result = One.get(2)
console.log(JSON.stringify(result.item)) // {uid:1, text:"test"}

Configuration

For existing code bases the name of the uid property can be configured via a config object passed as a second argument to the .getCache() method. In order for this to work correctly the values held by the configured property must be unique across all instances.

const one = One.getCache('test', { uidName:'id' })

const item = { id:'unique_id_value' }

one.put(item)

one.get('unique_id_value') !== undefined // true (works)

Motivation

More an more applications are giving users the ability to edit data in the browser. With a normalized data model various instances of an entity can exist at the same time in different locations. This depends on how data is received from the server and added to the local model / store.

This is inconvenient because:

  • Keeping all the instances in sync can be a daunting task.
  • It can make debugging hard.
  • It requires tracking each instance and makes reasoning about data complicated.
  • It can make the application structure needlessly complex.

Redux brings a great breakthrough by putting the entire application state in one place and mutating it only via dispatched actions. But it doesn't enforce entity uniqueness. One aims to take the concept a step further by making each entity unique and immutable in a single store (cache).

Performance considerations

  • Read optimized: Yes there is a performance cost in analyzing each entity deeply to track its dependencies. One mitigates this by being read optimized. The penalty is incurred on write operations only. These happen a lot less frequently than read ops. Read ops are super fast (a simple key lookup).
  • Trie structures: Data is stored in a trie like structure. This way all entities are referenced (not copied) and minimal changes are performed on every put or getEdit operation.

Data shape

This is not currently designed to work with cyclical data. It is best for non-cyclical objects received from the server in the form of json (or other non-cyclical fomats). It might happen later if there's a need.

1.1.463

10 months ago

1.1.342

1 year ago

1.1.462

10 months ago

1.1.341

1 year ago

1.1.461

10 months ago

1.1.340

1 year ago

1.1.460

11 months ago

1.1.349

1 year ago

1.1.469

10 months ago

1.1.348

1 year ago

1.1.468

10 months ago

1.1.347

1 year ago

1.1.467

10 months ago

1.1.346

1 year ago

1.1.466

10 months ago

1.1.345

1 year ago

1.1.465

10 months ago

1.1.344

1 year ago

1.1.464

10 months ago

1.1.343

1 year ago

1.1.329

1 year ago

1.1.452

11 months ago

1.1.331

1 year ago

1.1.451

11 months ago

1.1.330

1 year ago

1.1.450

11 months ago

1.1.339

1 year ago

1.1.459

11 months ago

1.1.338

1 year ago

1.1.458

11 months ago

1.1.337

1 year ago

1.1.457

11 months ago

1.1.336

1 year ago

1.1.456

11 months ago

1.1.335

1 year ago

1.1.455

11 months ago

1.1.334

1 year ago

1.1.454

11 months ago

1.1.333

1 year ago

1.1.453

11 months ago

1.1.332

1 year ago

1.1.364

1 year ago

1.1.363

1 year ago

1.1.362

1 year ago

1.1.361

1 year ago

1.1.360

1 year ago

1.1.369

1 year ago

1.1.368

1 year ago

1.1.367

1 year ago

1.1.366

1 year ago

1.1.365

1 year ago

1.1.353

1 year ago

1.1.350

1 year ago

1.1.470

10 months ago

1.1.359

1 year ago

1.1.358

1 year ago

1.1.357

1 year ago

1.1.356

1 year ago

1.1.355

1 year ago

1.1.354

1 year ago

1.1.419

12 months ago

1.1.418

12 months ago

1.1.417

12 months ago

1.1.427

11 months ago

1.1.426

11 months ago

1.1.425

11 months ago

1.1.424

11 months ago

1.1.423

11 months ago

1.1.422

11 months ago

1.1.421

11 months ago

1.1.420

12 months ago

1.1.409

12 months ago

1.1.408

12 months ago

1.1.407

12 months ago

1.1.406

12 months ago

1.1.416

12 months ago

1.1.415

12 months ago

1.1.414

12 months ago

1.1.413

12 months ago

1.1.412

12 months ago

1.1.411

12 months ago

1.1.410

12 months ago

1.1.439

11 months ago

1.1.441

11 months ago

1.1.440

11 months ago

1.1.449

11 months ago

1.1.328

1 year ago

1.1.448

11 months ago

1.1.447

11 months ago

1.1.446

11 months ago

1.1.445

11 months ago

1.1.444

11 months ago

1.1.443

11 months ago

1.1.442

11 months ago

1.1.429

11 months ago

1.1.428

11 months ago

1.1.430

11 months ago

1.1.438

11 months ago

1.1.437

11 months ago

1.1.436

11 months ago

1.1.435

11 months ago

1.1.434

11 months ago

1.1.433

11 months ago

1.1.432

11 months ago

1.1.431

11 months ago

1.1.405

12 months ago

1.1.404

12 months ago

1.1.403

12 months ago

1.1.402

12 months ago

1.1.401

12 months ago

1.1.400

12 months ago

1.1.386

1 year ago

1.1.385

1 year ago

1.1.384

1 year ago

1.1.383

1 year ago

1.1.382

1 year ago

1.1.381

1 year ago

1.1.380

1 year ago

1.1.389

1 year ago

1.1.388

1 year ago

1.1.387

1 year ago

1.1.375

1 year ago

1.1.374

1 year ago

1.1.373

1 year ago

1.1.372

1 year ago

1.1.371

1 year ago

1.1.370

1 year ago

1.1.379

1 year ago

1.1.378

1 year ago

1.1.377

1 year ago

1.1.376

1 year ago

1.1.397

12 months ago

1.1.396

1 year ago

1.1.395

1 year ago

1.1.394

1 year ago

1.1.393

1 year ago

1.1.392

1 year ago

1.1.391

1 year ago

1.1.390

1 year ago

1.1.399

12 months ago

1.1.398

12 months ago

1.1.327

1 year ago

1.1.326

1 year ago

1.1.325

1 year ago

1.1.320

1 year ago

1.1.324

1 year ago

1.1.323

1 year ago

1.1.322

1 year ago

1.1.321

1 year ago

1.1.319

1 year ago

1.1.318

1 year ago

1.1.290

1 year ago

1.1.298

1 year ago

1.1.297

1 year ago

1.1.296

1 year ago

1.1.295

1 year ago

1.1.294

1 year ago

1.1.293

1 year ago

1.1.292

1 year ago

1.1.291

1 year ago

1.1.299

1 year ago

1.1.306

1 year ago

1.1.305

1 year ago

1.1.304

1 year ago

1.1.303

1 year ago

1.1.302

1 year ago

1.1.269

1 year ago

1.1.301

1 year ago

1.1.300

1 year ago

1.1.287

1 year ago

1.1.286

1 year ago

1.1.285

1 year ago

1.1.284

1 year ago

1.1.283

1 year ago

1.1.282

1 year ago

1.1.281

1 year ago

1.1.280

1 year ago

1.1.289

1 year ago

1.1.288

1 year ago

1.1.309

1 year ago

1.1.308

1 year ago

1.1.307

1 year ago

1.1.276

1 year ago

1.1.275

1 year ago

1.1.274

1 year ago

1.1.273

1 year ago

1.1.272

1 year ago

1.1.271

1 year ago

1.1.270

1 year ago

1.1.317

1 year ago

1.1.316

1 year ago

1.1.315

1 year ago

1.1.314

1 year ago

1.1.313

1 year ago

1.1.312

1 year ago

1.1.279

1 year ago

1.1.311

1 year ago

1.1.278

1 year ago

1.1.310

1 year ago

1.1.277

1 year ago

6.0.1

9 years ago

6.0.0

9 years ago

5.1.4

9 years ago

5.1.3

10 years ago

5.1.2

10 years ago

5.1.1

10 years ago

5.1.0

10 years ago

5.0.3

10 years ago

5.0.2

10 years ago

5.0.1

10 years ago

5.0.0

10 years ago

0.0.1-security

10 years ago

4.0.0

10 years ago

3.1.4

12 years ago

3.1.3

12 years ago

3.1.2

13 years ago

3.1.1

13 years ago

3.0.13

13 years ago

3.0.12

13 years ago

3.0.11

13 years ago

3.0.10

13 years ago

3.0.8

13 years ago

3.0.7

13 years ago

3.0.6

13 years ago

3.0.5

13 years ago

3.0.4

13 years ago

3.0.3

13 years ago

3.0.2

13 years ago

3.0.1

13 years ago

3.0.0

13 years ago

2.5.2

13 years ago

2.5.0

13 years ago

2.0.11

13 years ago

2.0.10

13 years ago

2.0.8

13 years ago

2.0.7

13 years ago

2.0.6

13 years ago

2.0.5

13 years ago

2.0.4

13 years ago

2.0.1

13 years ago

2.0.0

13 years ago

1.8.2

13 years ago

1.8.1

13 years ago

1.7.12

13 years ago

1.7.11

13 years ago

1.7.10

13 years ago

1.7.9

13 years ago

1.7.8

13 years ago

1.7.7

13 years ago

1.7.6

14 years ago

1.7.5

14 years ago

1.7.3

14 years ago

1.7.2

14 years ago

1.7.1

14 years ago

1.7.0

14 years ago

1.5.1

14 years ago

1.5.0

14 years ago

1.4.4

14 years ago

1.4.3

14 years ago

1.4.1

14 years ago

1.4.0

14 years ago

1.3.5

14 years ago

1.3.4

14 years ago

1.3.3

14 years ago

1.3.2

14 years ago

1.3.1

14 years ago

1.3.0

14 years ago

1.2.0

14 years ago

1.1.5

14 years ago

1.1.4

14 years ago

1.1.3

14 years ago

1.1.2

14 years ago

1.1.1

14 years ago

1.1.0

14 years ago

1.0.0

14 years ago