Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .prettierrc
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
"tabWidth": 2,
"printWidth": 70,
"semi": false,
"singleQuote": true
"singleQuote": true,
"arrowParens": "avoid"
}
2 changes: 1 addition & 1 deletion workspaces/monolite/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
"jest": "^25.1.0",
"ts-jest": "^25.2.1",
"ts-loader": "^6.2.1",
"typescript": "^3.8.3",
"typescript": "^4.2.2",
"webpack": "^4.42.0",
"webpack-cli": "^3.3.11"
},
Expand Down
21 changes: 8 additions & 13 deletions workspaces/monolite/src/SetFluent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,39 +8,34 @@
## ## ## :##
## ## ##*/

import {
set,
Accessor,
AccessorFunction,
AccessorChain,
ValueTransformer,
} from './set'
import { AccessorChain, AccessorFunction } from 'axcessor'
import { set, Accessor, ValueTransformer } from './set'

export class SetFluent<R> {
constructor(private value: R) {}

/**
* Set subproperty value using accessor function
*/
set<T, A extends AccessorFunction<R, T>>(
set<T, A extends AccessorFunction.Safe<R>>(
accessor: A,
value: ValueTransformer<A>
value: ValueTransformer<R, A>
): this

/**
* Set subproperty value using accessor chain
*/
set<T, A extends AccessorChain>(
set<T, A extends AccessorChain.Safe<R>>(
accessor: A,
value: ValueTransformer<A>
value: ValueTransformer<R, A>
): this

/**
* Set subproperty value
*/
set<T, A extends Accessor<R, T>>(
set<T, A extends Accessor<R>>(
accessor: A,
value: ValueTransformer<A>
value: ValueTransformer<R, A>
) {
this.value = set(this.value, accessor, value)
return this
Expand Down
12 changes: 6 additions & 6 deletions workspaces/monolite/src/__tests__/SetFluent.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ it('can chain transformations', () => {

const updatedState = new SetFluent(state)
.set(
(_) => _.a.b.c,
(value) => value / 2 + 1
_ => _.a.b.c,
value => value / 2 + 1
)
.set(
(_) => _.a.d.e,
(word) => word + '!'
_ => _.a.d.e,
word => word + '!'
)
.end()

Expand All @@ -56,8 +56,8 @@ it('accepts accessor chain', () => {
}

const updatedState = new SetFluent(state)
.set(['a', 'b', 'c'], (value: any) => value / 2 + 1)
.set(['a', 'd', 'e'], (word: any) => word + '!')
.set(['a', 'b', 'c'], value => value / 2 + 1)
.set(['a', 'd', 'e'], word => word + '!')
.end()

expect(updatedState.a.b.c).toBe(22)
Expand Down
26 changes: 0 additions & 26 deletions workspaces/monolite/src/__tests__/getAccessorChain.spec.ts

This file was deleted.

104 changes: 76 additions & 28 deletions workspaces/monolite/src/__tests__/set.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,37 @@

import { set } from '../set'
import { assign } from '../assign'
import { Assert, IsExactType } from 'typebolt'
// import { Accessible, IsNullable } from 'axcessor'

it('accepts accessor chain', () => {
const tree = { b: { c: true }, d: { e: true } }
const updatedTree = set(tree, ['b', 'c'], false)
{
const tree = { b: { c: true }, d: { e: true } }
const updatedTree = set(tree, ['b', 'c'], false)

expect(updatedTree).not.toBe(tree)
expect(tree.b.c).toBe(true)
expect(updatedTree.b.c).toBe(false)
expect(updatedTree).not.toBe(tree)
expect(tree.b.c).toBe(true)
expect(updatedTree.b.c).toBe(false)
}

{
const tree = { b: { c: true }, d: { e: true } }
// @ts-expect-error `42` is not of type boolean
set(tree, ['b', 'c'], 42)

// @ts-expect-error _.b.e is not a correct path
set(tree, ['b', 'e'], true)

// @ts-expect-error _.d.c is not a correct path
set(tree, ['d', 'c'], true)
}
})

it('returns a new updated tree', () => {
const tree = { b: { c: true }, d: { e: true } }
const updatedTree = set(tree, (_) => _.b.c, false)
const updatedTree = set(tree, _ => _.b.c, false)

Assert<IsExactType<typeof tree, typeof updatedTree>>()

expect(updatedTree).not.toBe(tree)
expect(tree.b.c).toBe(true)
Expand All @@ -33,33 +51,57 @@ it('can take thunk as value', () => {
const tree = { b: { c: true } }
const updatedTree = set(
tree,
(_) => _.b.c,
(c) => !c
_ => _.b.c,
c => !c
)

Assert<IsExactType<typeof tree, typeof updatedTree>>()

expect(updatedTree).not.toBe(tree)
expect(tree.b.c).toBe(true)
expect(updatedTree.b.c).toBe(false)
})

it('returns same tree if target identity equality', () => {
// Pass the same primitive value as replacement
const tree = { a: { b: { c: 42 } } }
const updatedTree = set(tree, (_) => _.a.b.c, 42)
const tree = {
a: {
b: {
c: 42,
},
},
}

const updatedTree = set(tree, _ => _.a.b.c, 42)
Assert<IsExactType<typeof tree, typeof updatedTree>>()
expect(tree).toBe(updatedTree)

// Pass the same subtree as replacement
const tree2 = { a: { b: { c: 42 } } }
const updatedTree2 = set(tree2, (_) => _.a.b, tree2.a.b)
const tree2 = {
a: {
b: {
c: 42,
},
},
}
const updatedTree2 = set(tree2, _ => _.a.b, tree2.a.b)
Assert<IsExactType<typeof tree, typeof updatedTree>>()
expect(tree2).toBe(updatedTree2)
})

it('returns same tree if target structural equality', () => {
const tree = { a: { b: { c: 42 } } }
const updatedTree = set(tree, (_) => _.a.b, { c: 42 })
const updatedTree = set(tree, _ => _.a.b, { c: 42 })
expect(tree).toBe(updatedTree)
})

// TODO: ts-expect-error on wrong types and unsafe accessors.
// TODO: ts-expect-error on wrong types and unsafe accessors.
// TODO: ts-expect-error on wrong types and unsafe accessors.
// TODO: ts-expect-error on wrong types and unsafe accessors.
// TODO: ts-expect-error on wrong types and unsafe accessors.
// TODO: ts-expect-error on wrong types and unsafe accessors.

it('does not transform arrays to objects', () => {
const tree = {
title: 'Hello',
Expand All @@ -68,13 +110,19 @@ it('does not transform arrays to objects', () => {
{ name: 'Marvin', age: 42 },
],
}
const updatedTree = set(tree, (_) => _.subjects[0].name, 'Bobby')
const updatedTree = set(tree, _ => _.subjects[0].name, 'Bobby')

Assert<IsExactType<typeof tree, typeof updatedTree>>()

expect(updatedTree.subjects).toBeInstanceOf(Array)
expect(updatedTree.subjects.length).toBe(2)
expect(updatedTree.subjects[0].name).toBe('Bobby')
expect(updatedTree.subjects[1].name).toBe('Marvin')

const updatedTree2 = set(tree, (_) => _.subjects[1].name, 'Bobby')
const updatedTree2 = set(tree, _ => _.subjects[1].name, 'Bobby')

Assert<IsExactType<typeof updatedTree, typeof updatedTree2>>()

expect(updatedTree2.subjects).toBeInstanceOf(Array)
expect(updatedTree2.subjects.length).toBe(2)
expect(updatedTree2.subjects[0].name).toBe('John')
Expand All @@ -92,25 +140,25 @@ it('preserves the prototype of the tree', () => {
}
)

const updatedTree = set(tree, (_) => _.d.e, 4)
const updatedTree = set(tree, _ => _.d.e, 4)
expect(updatedTree.a).toBe(1)
expect(typeof updatedTree.b).toBe('object')
expect(updatedTree.b).toBe(tree.b)

const updatedTree2 = set(tree, (_) => _.d.e, 3)
const updatedTree2 = set(tree, _ => _.d.e, 3)
expect(updatedTree2).toBe(tree)
})

it('exposes fluent style api', () => {
type State = { a: { b: { c: number } } }
const state: State = { a: { b: { c: 42 } } }
// it('exposes fluent style api', () => {
// type State = { a: { b: { c: number } } }
// const state: State = { a: { b: { c: 42 } } }

const updatedState = set(state)
.set(
(_) => _.a.b.c,
(x) => x / 2 + 1
)
.end()
// const updatedState = set(state)
// .set(
// _ => _.a.b.c,
// x => x / 2 + 1
// )
// .end()

expect(updatedState.a.b.c).toBe(22)
})
// expect(updatedState.a.b.c).toBe(22)
// })
43 changes: 0 additions & 43 deletions workspaces/monolite/src/accessorChain.ts

This file was deleted.

Loading