Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
87 commits
Select commit Hold shift + click to select a range
dd403c7
create FUNDING.yml
liximomo Nov 28, 2022
6e0893e
doc: fix typo
liximomo Nov 28, 2022
579873d
docs: update tagline
liximomo Nov 28, 2022
cab6169
docs: add gtag
liximomo Nov 28, 2022
93d5591
docs: update description
liximomo Nov 28, 2022
f9d3707
fix: unlisten deps when destory
liximomo Nov 29, 2022
f0ca4cf
docs: fix tagline
liximomo Nov 29, 2022
02ac426
refactor: remove unused code
liximomo Nov 29, 2022
1330292
fix: store proxy cache in DraftSnapshort
liximomo Nov 29, 2022
677a292
fix: typo
liximomo Nov 29, 2022
a0fc81f
release: v0.0.1
liximomo Nov 29, 2022
e3f784e
docs: update title
liximomo Nov 29, 2022
684f9ba
docs: update describe
liximomo Nov 29, 2022
db43512
wip
liximomo Nov 29, 2022
0811abb
feat: support set & map
liximomo Nov 30, 2022
765c944
fix(set & map): fix some cases
liximomo Nov 30, 2022
59e3fda
chore: update examples
liximomo Nov 30, 2022
1e6005b
release: v0.0.2
liximomo Nov 30, 2022
b65074c
test: update snapshot
liximomo Nov 30, 2022
eb399fe
fix: types errorg
wangjinyang Dec 2, 2022
3ddb653
fix: export ModelOptions FunctionModel ObjectModel
wangjinyang Dec 2, 2022
5181784
Merge pull request #1 from wangjinyang/feat-1201-newest
liximomo Dec 2, 2022
2d1bec8
feat: export model related types
liximomo Dec 2, 2022
013e04a
release: v0.0.3
liximomo Dec 2, 2022
f496ba4
feat: support hmr
wangjinyang Dec 4, 2022
8ffc279
chore: remove useModel's useMemo
wangjinyang Dec 5, 2022
7c84b35
fix: doura init once
wangjinyang Dec 5, 2022
b4f4219
Merge pull request #2 from wangjinyang/feat-1203-hmr
liximomo Dec 5, 2022
f66b116
refactor: use __DEV__ to test dev environment
liximomo Dec 6, 2022
7a3f4d6
refacotr: minor optimizations
liximomo Dec 6, 2022
e053f5c
docs: remove name
liximomo Dec 7, 2022
26abe11
fix: eliminate updates from nested action calls
liximomo Dec 8, 2022
e5e81a4
release: v0.0.4
liximomo Dec 8, 2022
1a746f1
chore: update example
liximomo Dec 16, 2022
ca557ff
chore: init api doc
wangjinyang Dec 17, 2022
38f7337
chore(doc): add content
wangjinyang Dec 19, 2022
9b5b8f7
fix: actions should be accessed by the api parameter of selector func…
liximomo Dec 19, 2022
6a238e6
release: v0.0.5
liximomo Dec 19, 2022
0bf2e40
feat: use "useModel" to replace "useRootModel"
liximomo Dec 19, 2022
08f4ae7
release: v0.0.6
liximomo Dec 19, 2022
b2d5594
fix(type): remove depends params
liximomo Dec 19, 2022
b9d8968
chore: selector type
wangjinyang Dec 19, 2022
9e31bd9
Merge remote-tracking branch 'upstream/main' into feat-1215-docs
wangjinyang Dec 19, 2022
46c8aef
chore: adjust reat-doura content
wangjinyang Dec 19, 2022
f6178ce
chore: remove no use code
wangjinyang Dec 20, 2022
722bad0
doc: add api pages
liximomo Dec 20, 2022
63d6339
feat: make use a global api
liximomo Dec 20, 2022
79987bf
release: v0.0.7
liximomo Dec 20, 2022
057d6f1
feat: views support external params
wangjinyang Jan 24, 2023
f55c91a
fix: test error
wangjinyang Jan 24, 2023
7a1e808
chore: remove no use test
wangjinyang Jan 24, 2023
2100cef
chore: create view init fun once
wangjinyang Jan 30, 2023
56bf0dc
fix: init view outside
wangjinyang Jan 31, 2023
003a9c0
chore: get: getResult
wangjinyang Jan 31, 2023
8b75dba
Merge pull request #6 from wangjinyang/feat-0115-viewsArg
liximomo Jan 31, 2023
7aab407
chore: add benchmark
liximomo Jan 31, 2023
42d42ef
Merge pull request #7 from dourajs/performance-optimization
liximomo Jan 31, 2023
ad3068e
chore: enable eslint rules
liximomo Feb 1, 2023
0d7fb9d
fix: log and throw errors
liximomo Feb 23, 2023
f442592
fix: prevent return draft from view and public mode instances
liximomo Feb 24, 2023
cfaa330
refactor: optimize code
liximomo Feb 24, 2023
303cc5e
test(useModel): add nest case for selector
liximomo Feb 24, 2023
a71d01b
chore: config commitlint
liximomo Feb 24, 2023
b22b54c
release: v0.0.8
liximomo Feb 24, 2023
6d85459
test: non-existing props
liximomo Feb 24, 2023
38b0e28
perf: improve speed by using quickcopy conditionally
wangjinyang Mar 13, 2023
0611cd4
release: v0.0.9
liximomo Mar 13, 2023
5d1e3ef
chore: benchmark add immer
wangjinyang Mar 22, 2023
f155deb
Merge pull request #10 from wangjinyang/feat-0322-immerBenchmark
liximomo Mar 22, 2023
a74c32d
fix: value not updating due to nested actions
liximomo Mar 29, 2023
397370d
release: v0.0.10
liximomo Mar 29, 2023
d857fcb
chore: tip view not support additional parameters
wangjinyang Apr 6, 2023
99ae601
chore: fix test error
wangjinyang Apr 6, 2023
976f8d1
Merge pull request #11 from wangjinyang/feat-0406-deprecatedViewApi
liximomo Apr 6, 2023
c6aba66
fix: filter link error
wangjinyang Apr 7, 2023
f0667f4
Merge pull request #12 from wangjinyang/fix-0407-filterError
liximomo Apr 8, 2023
8196b29
release: v0.0.11
liximomo Apr 10, 2023
f727775
fix: fix reference changed without modifing it
liximomo Aug 3, 2023
9864740
fix: snapshot should not be affected by old snapshots
liximomo Aug 3, 2023
4e17fc4
Merge pull request #13 from dourajs/fix-bug
liximomo Aug 4, 2023
1d644f0
release: v0.0.12
liximomo Aug 4, 2023
67ae5e5
feat: export markRaw
liximomo Aug 24, 2023
0b9770a
release: v0.0.13
liximomo Aug 24, 2023
2ebea66
fix: createModelInstance
wangjinyang Nov 20, 2023
f33ff69
Merge pull request #14 from wangjinyang/fix-typo
liximomo Nov 21, 2023
df1e029
Create tea.yaml
liximomo Feb 23, 2024
07103d0
test: try to reproduce
liximomo Jul 3, 2024
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
15 changes: 6 additions & 9 deletions .eslintignore
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
/.git
CHANGELOG.md
package.json
packages/*/lib
**/node_modules
packages/*/dist
packages/*/esm
packages/*/node_modules
packages/*/CHANGELOG.md
docs/*/node_modules
docs/*/build
docs/*/.docusaurus
benchmark
docs
test-dts
commitlint.config.js
**/__tests__
44 changes: 30 additions & 14 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,32 @@
module.exports = {
env: {
browser: true,
es6: true,
},
extends: [
'plugin:import/warnings',
'plugin:import/typescript',
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
},
plugins: ['@typescript-eslint', 'prettier'],
env: {
browser: true,
es6: true,
node: true,
jest: true,
},
extends: [
'prettier',
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
],
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
},
plugins: ['prettier'],
rules: {
'no-unused-vars': 'off',
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
'prefer-spread': 'off',
'@typescript-eslint/no-empty-interface': 'off',
'@typescript-eslint/no-non-null-assertion': 'off',
'@typescript-eslint/no-explicit-any': 'off',
'@typescript-eslint/ban-types': 'off',
'@typescript-eslint/no-extra-semi': 'off',
'@typescript-eslint/no-this-alias': 'off',
'@typescript-eslint/no-inferrable-types': 'off',
'@typescript-eslint/explicit-module-boundary-types': 'off',
},
}
13 changes: 13 additions & 0 deletions .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# These are supported funding model platforms

github: [liximomo]
patreon: # Replace with a single Patreon username
open_collective: # Replace with a single Open Collective username
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,4 @@ dist/
temp/
packages/*/dist/
examples/*/build
benchmark.csv
4 changes: 4 additions & 0 deletions .husky/commit-msg
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

pnpm commitlint --edit $1
7 changes: 6 additions & 1 deletion .npmrc
Original file line number Diff line number Diff line change
@@ -1,2 +1,7 @@
auto-install-peers=true
strict-peer-dependencies=false
strict-peer-dependencies=false

# Using pnpm to rely on the theme-comon package will have some issues,
# it can be referd to the discussion and solution of this issue
# https://github.com/facebook/docusaurus/issues/7880.
public-hoist-pattern[]=@docusaurus/theme-common*
62 changes: 53 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,15 +30,42 @@ yarn add doura

```tsx
import { defineModel } from 'doura'
import { useModel } from 'react-doura'

const countModel = defineModel({
const todoModel = defineModel({
state: {
count: 0,
todos: [
{
id: 0,
text: 'read books',
isFinished: true,
},
],
/** @type {'all' | 'unfinished'} */
filter: 'all',
},
views: {
unfinishedTodos() {
// autocompletion! ✨
return this.todos.filter((todo) => !todo.isFinished)
},
filteredTodos() {
if (this.filter === 'unfinished') {
return this.unfinishedTodos
}
return this.todos
},
},
actions: {
inc() {
this.count += 1
// any amount of arguments, return a promise or not
setFilter(filter) {
// you can directly mutate the state
this.filter = filter
},
// action can be asynchronous
async getTodos() {
this.todos = await fetchTodos('httpds://api.example.com/todos')
}
},
})
```
Expand All @@ -48,13 +75,30 @@ const countModel = defineModel({
```tsx
import { useModel } from 'react-doura'

function Counter() {
const counter = useModel(countModel)
export function TodoApp() {
// type of `filteredTodos` and `setFilter` are inferred automatically
const { filteredTodos, setFilter } = useModel(todoModel)

return (
<div>
<h1>Count: {counter.count}</h1>
<button onClick={counter.inc}>inc</button>
<div>
<input
type="checkbox"
id="filter"
onClick={(event) =>
setFilter(event.target.checked ? 'unfinished' : 'all')
}
/>
<label htmlFor="filter">Only show unfinished</label>
</div>
<ul>
{filteredTodos.map((todo) => (
<li key={todo.id}>
<input type="checkbox" checked={todo.isFinished} />
{todo.text}
</li>
))}
</ul>
</div>
)
}
Expand All @@ -65,5 +109,5 @@ function Counter() {
Doura is greatly inspired by following excellent projects:

- [Immer](https://github.com/immerjs/immer)
- [Vuejs](https://github.com/vuejs)
- [Vue.js](https://github.com/vuejs)
- [Pinia](https://github.com/vuejs/pinia)
154 changes: 154 additions & 0 deletions benchmark/reactivity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
import fs from 'fs'
// @ts-ignore
import { Suite } from 'benchmark'
// @ts-ignore
import { parse } from 'json2csv'
import { draft, snapshot } from '../packages/doura'
import { create } from 'mutative'
import produce from 'immer'

const result = [
{
Name: 'Naive handcrafted reducer',
},
{
Name: 'Mutative',
},
{
Name: 'Immer',
},
{
Name: 'Doura',
},
]

const douraProduce = (value: any, cb: (v: any) => void) => {
const obj = draft(value as any)
cb(obj)

return snapshot(obj, obj)
}

const getData = () => {
const baseState: { arr: any[]; map: Record<string, any> } = {
arr: [],
map: {},
}

const createTestObject = () =>
Array(10 * 5)
.fill(1)
.reduce((i, _, k) => Object.assign(i, { [k]: k }), {})

baseState.arr = Array(10 ** 4 * 5)
.fill('')
.map(() => createTestObject())

Array(10 ** 3)
.fill(1)
.forEach((_, i) => {
baseState.map[i] = { i }
})
return baseState
}

let baseState: any
let i: any

const suite = new Suite()

suite
.add(
'Naive handcrafted reducer',
function () {
void {
...baseState,
arr: [...baseState.arr, i],
map: { ...baseState.map, [i]: { i } },
}
},
{
onStart: () => {
i = Math.random()
baseState = getData()
},
}
)
.add(
'Mutative',
function () {
void create(baseState, (draft) => {
draft.arr.push(i)
draft.map[i] = i
})
},
{
onStart: () => {
i = Math.random()
baseState = getData()
},
}
)
.add(
'Immer',
function () {
void produce(baseState, (draft: any) => {
draft.arr.push(i)
draft.map[i] = i
})
},
{
onStart: () => {
i = Math.random()
baseState = getData()
},
}
)
.add(
'Doura',
function () {
void douraProduce(baseState, (draft: any) => {
draft.arr.push(i)
draft.map[i] = i
})
},
{
onStart: () => {
i = Math.random()
baseState = getData()
},
}
)
.on('cycle', function (event: any) {
console.log(String(event.target))
const [name] = event.target.name.split(' - ')
const index = result.findIndex((i) => i.Name === name)
// @ts-ignore
result[index][event.target.name] = Math.round(event.target.hz)
})
.on('complete', function (this: any) {
console.log('The fastest method is ' + this.filter('fastest').map('name'))
})
.run({ async: false })

try {
// Mutative vs Immer Performance
// Measure(ops/sec) to update 50K arrays and 1K objects, bigger the better.
const fields: string[] = []
result.forEach((item) => {
fields.push(...Object.keys(item).slice(1))
})
result.forEach((item) => {
fields.forEach((field) => {
if (!(field in item)) {
;(item as any)[field] = '-'
}
})
})
const csv = parse(result, {
fields: ['Name', ...fields.reverse()],
})
fs.writeFileSync('benchmark.csv', csv)
} catch (err) {
console.error(err)
}
34 changes: 34 additions & 0 deletions commitlint.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
const { RuleConfigSeverity } = require('@commitlint/types')

/** @type {import("@commitlint/types").UserConfig} */
const Configuration = {
/*
* Resolve and load @commitlint/config-conventional from node_modules.
* Referenced packages must be installed
*/
extends: ['@commitlint/config-conventional'],
/*
* Any rules defined here will override rules from @commitlint/config-conventional
*/
rules: {
'type-enum': [
RuleConfigSeverity.Error,
'always',
[
'chore',
'ci',
'docs',
'feat',
'fix',
'perf',
'refactor',
'revert',
'style',
'test',
'release',
],
],
},
}

module.exports = Configuration
Loading