Skip to content

Commit 553e953

Browse files
authored
[add] Persist List class decorator & test cases (#18)
1 parent f33ba5a commit 553e953

File tree

10 files changed

+2582
-2524
lines changed

10 files changed

+2582
-2524
lines changed

.github/workflows/main.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ jobs:
1717
version: 9
1818
- uses: actions/setup-node@v4
1919
with:
20-
node-version: 20
20+
node-version: 22
2121
registry-url: https://registry.npmjs.org
2222
cache: pnpm
2323
- name: Install Dependencies
@@ -34,7 +34,7 @@ jobs:
3434
run: |
3535
cd wrapper/Strapi
3636
pnpm i --frozen-lockfile
37-
npm publish --access public --provenance || true
37+
npm publish || true
3838
env:
3939
NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
4040

ReadMe.md

Lines changed: 131 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ Just define your **Data models** & **Client HTTP methods**, then leave rest of t
2424
```json
2525
{
2626
"dependencies": {
27-
"koajax": "^3.0.0",
27+
"koajax": "^3.1.0",
2828
"mobx": "^6.13.5",
29-
"mobx-restful": "^2.0.0"
29+
"mobx-restful": "^2.1.0"
3030
}
3131
}
3232
```
@@ -217,10 +217,130 @@ export class MultipleRepository extends Stream<Repository>(RepositoryModel) {
217217
export default new MultipleRepository();
218218
```
219219

220-
### File Downloader
220+
### Data Persistence
221+
222+
`@persist()` & `restore()` functions give us a declarative way to save & restore data to/from [IndexedBD][11], such as these following examples:
223+
224+
#### User Session
225+
226+
```ts
227+
import { observable } from 'mobx';
228+
import { BaseModel, persist, restore, toggle } from 'mobx-restful';
229+
import { Day } from 'web-utility';
230+
231+
import { client } from './client';
232+
import { User } from './User';
233+
234+
export class SessionModel extends BaseModel {
235+
baseURI = 'session';
236+
client = client;
237+
238+
@persist({ expireIn: 15 * Day })
239+
@observable
240+
user?: User;
241+
242+
restored = restore(this, 'Session');
243+
244+
@toggle('uploading')
245+
async signIn(username: string, password: string) {
246+
const { body } = await this.client.post<User>('session', {
247+
username,
248+
password
249+
});
250+
return (this.user = body);
251+
}
252+
}
253+
254+
export default new Session();
255+
```
256+
257+
#### File Downloader
221258

222259
This module has been moved to [MobX-downloader][12] since MobX-RESTful v2.
223260

261+
#### List Cache
262+
263+
##### `model/Party/Gift.ts`
264+
265+
```ts
266+
import { ListModel, persistList } from 'mobx-restful';
267+
268+
import { Gift } from '@my-scope/service-type';
269+
270+
import { client } from './client';
271+
272+
@persistList({
273+
storeKey: ({ partyId }) => `PartyGift-${partyId}`,
274+
expireIn: 2 * Day
275+
})
276+
export class PartyGiftModel extends ListModel<Gift> {
277+
baseURI = 'party';
278+
client = client;
279+
280+
constructor(public partyId: number) {
281+
super();
282+
this.baseURI += `/${partyId}/gift`;
283+
}
284+
285+
protected async loadPage(pageIndex: number, pageSize: number) {
286+
const { body } = await this.client.get<{
287+
count: number;
288+
list: Gift[];
289+
}>(`${this.baseURI}?${buildURLData({ pageIndex, pageSize })}`);
290+
291+
return { pageData: body.list, totalCount: body.count };
292+
}
293+
}
294+
```
295+
296+
##### `page/Party/Gift.tsx`
297+
298+
This example page uses [Cell Router][13] to pass in `partyId` route parameter:
299+
300+
```tsx
301+
import { observable } from 'mobx';
302+
import { component, observer, attribute } from 'web-cell';
303+
304+
import { PartyGiftModel } from '../../model/Party/Gift';
305+
306+
@component({ tagName: 'party-gift-page' })
307+
@observer
308+
export class PartyGiftPage extends HTMLElement {
309+
@attribute
310+
@observable
311+
accessor partyId = 0;
312+
313+
@observable
314+
accessor store: PartyGiftModel | undefined;
315+
316+
async connectedCallback() {
317+
this.store = new PartyGiftModel(this.partyId);
318+
319+
await this.store.restored;
320+
// this calling will do nothing after the first loading
321+
// in list cache period
322+
await this.store.getAll();
323+
}
324+
325+
render() {
326+
const { allItem } = this.store || {};
327+
328+
return (
329+
<>
330+
<h1>Gift wall</h1>
331+
<ol>
332+
{allItem.map(({ name, price }) => (
333+
<li key={name}>
334+
{name} - {price}
335+
</li>
336+
))}
337+
</ol>
338+
</>
339+
);
340+
}
341+
}
342+
```
343+
224344
## Wrapper
225345

226346
1. [Strapi v4](https://github.com/idea2app/MobX-RESTful/blob/main/wrapper/Strapi)
@@ -233,13 +353,14 @@ This module has been moved to [MobX-downloader][12] since MobX-RESTful v2.
233353

234354
## Scaffold
235355

236-
1. Client-side Rendering (React): https://github.com/idea2app/Next-Bootstrap-ts
237-
2. Server-side Rendering (React): https://github.com/idea2app/React-MobX-Bootstrap-ts
238-
3. Cross-end App (React): https://github.com/idea2app/Taro-Vant-MobX-ts
356+
1. Client-side Rendering (React): https://github.com/idea2app/React-MobX-Bootstrap-ts
357+
2. Client-side Rendering (Vue): https://github.com/idea2app/Vue-MobX-Prime-ts
358+
3. Server-side Rendering (React): https://github.com/idea2app/Next-Bootstrap-ts
359+
4. Cross-end App (React): https://github.com/idea2app/Taro-Vant-MobX-ts
239360

240361
## Limitation
241362

242-
- [ ] [`abstract` hint of Mixin is missing][11]
363+
- [ ] [`abstract` hint of Mixin is missing][14]
243364

244365
[1]: https://mobx.js.org/
245366
[2]: https://github.com/tc39/proposal-decorators
@@ -251,5 +372,7 @@ This module has been moved to [MobX-downloader][12] since MobX-RESTful v2.
251372
[8]: https://pnpm.io/
252373
[9]: https://joyeecheung.github.io/blog/2024/03/18/require-esm-in-node-js/
253374
[10]: https://github.com/EasyWebApp/WebCell
254-
[11]: https://github.com/microsoft/TypeScript/issues/39752#issuecomment-1239810720
375+
[11]: https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API
255376
[12]: https://github.com/idea2app/MobX-downloader
377+
[13]: https://github.com/EasyWebApp/cell-router
378+
[14]: https://github.com/microsoft/TypeScript/issues/39752#issuecomment-1239810720

package.json

Lines changed: 21 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "mobx-restful",
3-
"version": "2.0.0",
3+
"version": "2.1.0",
44
"license": "LGPL-3.0",
55
"author": "[email protected]",
66
"description": "Common MobX abstract base Class & Decorator utilities for RESTful API",
@@ -27,36 +27,39 @@
2727
"module": "dist/index.esm.js",
2828
"main": "dist/index.js",
2929
"dependencies": {
30-
"@swc/helpers": "^0.5.13",
30+
"@swc/helpers": "^0.5.15",
3131
"idb-keyval": "^6.2.1",
32-
"koajax": "^3.0.3",
32+
"koajax": "^3.1.1",
3333
"regenerator-runtime": "^0.14.1",
34-
"web-utility": "^4.4.1"
34+
"web-utility": "^4.4.2"
3535
},
3636
"peerDependencies": {
3737
"mobx": ">=6.11"
3838
},
3939
"devDependencies": {
40-
"@octokit/openapi-types": "^22.2.0",
41-
"@parcel/config-default": "~2.12.0",
42-
"@parcel/packager-ts": "~2.12.0",
43-
"@parcel/transformer-typescript-tsc": "~2.12.0",
44-
"@parcel/transformer-typescript-types": "~2.12.0",
40+
"@octokit/openapi-types": "^23.0.1",
41+
"@parcel/config-default": "~2.13.3",
42+
"@parcel/packager-ts": "~2.13.3",
43+
"@parcel/transformer-typescript-tsc": "~2.13.3",
44+
"@parcel/transformer-typescript-types": "~2.13.3",
4545
"@types/jest": "^29.5.14",
46-
"@types/node": "^20.17.2",
47-
"dotenv": "^16.4.5",
48-
"husky": "^9.1.6",
46+
"@types/node": "^22.12.0",
47+
"core-js": "^3.40.0",
48+
"dotenv": "^16.4.7",
49+
"fake-indexeddb": "^6.0.0",
50+
"husky": "^9.1.7",
4951
"jest": "^29.7.0",
5052
"jest-environment-jsdom": "^29.7.0",
51-
"lint-staged": "^15.2.10",
53+
"lint-staged": "^15.4.3",
5254
"mobx": "^6.13.5",
5355
"open-cli": "^8.0.0",
54-
"parcel": "~2.12.0",
55-
"prettier": "^3.3.3",
56+
"parcel": "~2.13.3",
57+
"prettier": "^3.4.2",
5658
"ts-jest": "^29.2.5",
57-
"typedoc": "^0.26.10",
58-
"typedoc-plugin-mdn-links": "^3.3.5",
59-
"typescript": "~5.6.3"
59+
"typedoc": "^0.27.6",
60+
"typedoc-plugin-mdn-links": "^4.0.10",
61+
"typescript": "~5.7.3",
62+
"web-streams-polyfill": "^4.1.0"
6063
},
6164
"prettier": {
6265
"singleQuote": true,

0 commit comments

Comments
 (0)