Skip to content

Commit 8104f6b

Browse files
committed
[fix] Mixin Inherition
1 parent 947b3fb commit 8104f6b

8 files changed

Lines changed: 107 additions & 149 deletions

File tree

ReadMe.md

Lines changed: 45 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -29,17 +29,20 @@ export const client = new HTTPClient({
2929

3030
```typescript
3131
import { buildURLData } from 'web-utility';
32-
import { ListModel } from 'mobx-restful';
32+
import { NewData, ListModel } from 'mobx-restful';
3333

3434
import { client } from './client';
3535

3636
export type Repository = Record<'full_name' | 'html_url', string>;
3737

38-
export class RepositoryModel extends ListModel<Repository> {
38+
export class RepositoryModel<
39+
D extends Repository = Repository,
40+
F extends NewData<D> = NewData<D>
41+
> extends ListModel<D, F> {
3942
client = client;
4043
baseURI = 'orgs/idea2app/repos';
4144

42-
protected async loadPage(page: number, per_page: number) {
45+
async loadPage(page: number, per_page: number) {
4346
const { body } = await this.client.get<Repository[]>(
4447
`${this.baseURI}?${buildURLData({ page, per_page })}`
4548
);
@@ -92,85 +95,57 @@ export class RepositoryPage extends WebCell() {
9295

9396
### Preload List
9497

95-
#### `model/Repository.ts`
98+
#### `model/PreloadRepository.ts`
9699

97-
```diff
100+
```typescript
98101
import { buildURLData } from 'web-utility';
99-
-import { ListModel } from 'mobx-restful';
100-
+import { BufferListModel } from 'mobx-restful';
102+
import { BufferListModel } from 'mobx-restful';
101103

102-
import { client } from './client';
104+
import { RepositoryModel } from './Repository';
103105

104-
export type Repository = Record<'full_name' | 'html_url', string>;
105-
106-
-export class RepositoryModel extends ListModel<Repository> {
107-
+export class RepositoryModel extends BufferListModel<Repository>() {
108-
client = client;
109-
baseURI = 'orgs/idea2app/repos';
110-
111-
protected async loadPage(page: number, per_page: number) {
112-
const { body } = await this.client.get<Repository[]>(
113-
`${this.baseURI}?${buildURLData({ page, per_page })}`
114-
);
115-
return { pageData: body };
116-
}
117-
}
106+
export class PreloadRepositoryModel extends BufferListModel(RepositoryModel) {}
118107

119-
export default new RepositoryModel();
108+
export default new PreloadRepositoryModel();
120109
```
121110

122111
### Multiple Source List
123112

124-
#### `model/Repository.ts`
125-
126-
```diff
127-
-import { buildURLData } from 'web-utility';
128-
+import { buildURLData, mergeStream } from 'web-utility';
129-
-import { ListModel } from 'mobx-restful';
130-
+import { StreamListModel } from 'mobx-restful';
113+
#### `model/MultipleRepository.ts`
131114

132-
import { client } from './client';
133-
134-
export type Repository = Record<'full_name' | 'html_url', string>;
135-
136-
-export class RepositoryModel extends ListModel<Repository> {
137-
+export class RepositoryModel extends StreamListModel<Repository>() {
138-
client = client;
139-
- baseURI = 'orgs/idea2app/repos';
140-
141-
- protected async loadPage(page: number, per_page: number) {
142-
- const { body } = await this.client.get<Repository[]>(
143-
- `${this.baseURI}?${buildURLData({ page, per_page })}`
144-
- );
145-
- return { pageData: body };
146-
- }
147-
+ protected openStream() {
148-
+ return mergeStream(
149-
+ async function* () {
150-
+ for (let i = 1; ; i++) {
151-
+ const { body } = await client.get<Repository[]>(
152-
+ 'orgs/idea2app/repos?page=' + i
153-
+ );
154-
+ if (!body[0]) break;
155-
+
156-
+ yield* body;
157-
+ }
158-
+ },
159-
+ async function* () {
160-
+ for (let i = 1; ; i++) {
161-
+ const { body } = await client.get<Repository[]>(
162-
+ 'users/TechQuery/repos?page=' + i
163-
+ );
164-
+ if (!body[0]) break;
165-
+
166-
+ yield* body;
167-
+ }
168-
+ }
169-
+ );
170-
+ }
115+
```typescript
116+
import { buildURLData, mergeStream } from 'web-utility';
117+
import { StreamListModel } from 'mobx-restful';
118+
119+
import { Repository, RepositoryModel } from './Repository';
120+
121+
export class MultipleRepository extends StreamListModel(RepositoryModel) {
122+
openStream() {
123+
return mergeStream(
124+
async function* () {
125+
for (let i = 1; ; i++) {
126+
const { body } = await client.get<Repository[]>(
127+
'orgs/idea2app/repos?page=' + i
128+
);
129+
if (!body[0]) break;
130+
131+
yield* body;
132+
}
133+
},
134+
async function* () {
135+
for (let i = 1; ; i++) {
136+
const { body } = await client.get<Repository[]>(
137+
'users/TechQuery/repos?page=' + i
138+
);
139+
if (!body[0]) break;
140+
141+
yield* body;
142+
}
143+
}
144+
);
145+
}
171146
}
172147

173-
export default new RepositoryModel();
148+
export default new MultipleRepository();
174149
```
175150

176151
## Scaffold

package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "mobx-restful",
3-
"version": "0.6.0-rc.0",
3+
"version": "0.6.0-rc.1",
44
"license": "LGPL-3.0",
55
"author": "shiy2008@gmail.com",
66
"description": "MobX SDK for RESTful API",
@@ -27,7 +27,7 @@
2727
"module": "dist/index.esm.js",
2828
"main": "dist/index.js",
2929
"dependencies": {
30-
"@swc/helpers": "^0.4.6",
30+
"@swc/helpers": "^0.4.7",
3131
"class-validator": "^0.13.2",
3232
"koajax": "^0.8.1",
3333
"reflect-metadata": "^0.1.13",
@@ -79,7 +79,7 @@
7979
"scripts": {
8080
"prepare": "husky install",
8181
"test": "lint-staged && jest",
82-
"build": "rm -rf dist/ docs/ && typedoc source/ && parcel build",
82+
"build": "rm -rf dist/ docs/ && parcel build",
8383
"start": "typedoc source/ && open-cli docs/index.html",
8484
"prepublishOnly": "npm test && npm run build"
8585
}

pnpm-lock.yaml

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

source/Base.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ export abstract class BaseListModel<D extends DataObject> extends BaseModel {
4444
return store;
4545
}
4646

47+
@action
4748
clear() {
4849
this.currentOne = {} as D;
4950
this.validity = {};

source/List.ts

Lines changed: 21 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { Constructor, splitArray } from 'web-utility';
1+
import { splitArray } from 'web-utility';
22
import { observable, computed, action, reaction } from 'mobx';
33

4-
import { DataObject, NewData, toggle } from './utility';
4+
import { AbstractClass, DataObject, NewData, toggle } from './utility';
55
import { BaseListModel } from './Base';
66

77
export interface PageData<D extends DataObject> {
@@ -73,17 +73,13 @@ export abstract class ListModel<
7373
return this;
7474
}
7575

76-
protected abstract loadPage(
76+
abstract loadPage(
7777
pageIndex: number,
7878
pageSize: number,
7979
filter: F
8080
): Promise<PageData<D>>;
8181

82-
protected async loadNewPage(
83-
pageIndex: number,
84-
pageSize: number,
85-
filter: F
86-
) {
82+
async loadNewPage(pageIndex: number, pageSize: number, filter: F) {
8783
const { pageData, totalCount } = await this.loadPage(
8884
pageIndex,
8985
pageSize,
@@ -101,7 +97,7 @@ export abstract class ListModel<
10197
return { pageData, totalCount };
10298
}
10399

104-
protected flushPage(pageIndex: number, pageSize: number, pageData: D[]) {
100+
flushPage(pageIndex: number, pageSize: number, pageData: D[]) {
105101
this.turnTo(pageIndex, pageSize);
106102

107103
this.noMore = pageData.length < pageSize;
@@ -127,27 +123,18 @@ export abstract class ListModel<
127123
}
128124
}
129125

130-
/**
131-
* Only for Type Hint of {@link BufferListModel} mixin
132-
*
133-
* @deprecated
134-
*/
135-
export abstract class BufferList<
136-
D extends DataObject,
137-
F extends NewData<D> = NewData<D>
138-
> extends ListModel<D, F> {
139-
protected pendingList: ReturnType<ListModel<D, F>['loadPage']>[] = [];
140-
}
141-
142126
export function BufferListModel<
143127
D extends DataObject,
144-
F extends NewData<D> = NewData<D>
145-
>(): abstract new () => BufferList<D, F> {
146-
abstract class BufferListMixin extends BufferList<D, F> {
128+
F extends NewData<D> = NewData<D>,
129+
M extends AbstractClass<ListModel<D, F>> = AbstractClass<ListModel<D, F>>
130+
>(Super: M) {
131+
abstract class BufferListMixin extends Super {
132+
pendingList: ReturnType<ListModel<D, F>['loadPage']>[] = [];
133+
147134
clear() {
148135
this.pendingList = [];
149136

150-
return this;
137+
return super.clear();
151138
}
152139

153140
@toggle('downloading')
@@ -187,41 +174,24 @@ export function BufferListModel<
187174
return BufferListMixin;
188175
}
189176

190-
/**
191-
* Only for Type Hint of {@link StreamListModel} mixin
192-
*
193-
* @deprecated
194-
*/
195-
export abstract class StreamList<
177+
export function StreamListModel<
196178
D extends DataObject,
197-
F extends NewData<D> = NewData<D>
198-
> extends ListModel<D, F> {
199-
baseURI = '';
179+
F extends NewData<D> = NewData<D>,
180+
M extends AbstractClass<ListModel<D, F>> = AbstractClass<ListModel<D, F>>
181+
>(Super: M) {
182+
abstract class StreamListMixin extends Super {
183+
baseURI = '';
200184

201-
protected stream?: AsyncGenerator<D, void, D>;
202-
protected abstract openStream(filter: F): AsyncGenerator<D, void, D>;
185+
stream?: AsyncGenerator<D, void, D>;
186+
abstract openStream(filter: F): AsyncGenerator<D, void, D>;
203187

204-
protected async loadPage(pageIndex: number, pageSize: number, filter: F) {
205-
return { pageData: [] };
206-
}
207-
}
208-
209-
export function StreamListModel<
210-
D extends DataObject,
211-
F extends NewData<D> = NewData<D>
212-
>(): abstract new () => StreamList<D, F> {
213-
abstract class StreamListMixin extends StreamList<D, F> {
214188
clear() {
215189
this.stream = undefined;
216190

217191
return super.clear();
218192
}
219193

220-
protected async loadPage(
221-
pageIndex: number,
222-
pageSize: number,
223-
filter: F
224-
) {
194+
async loadPage(pageIndex: number, pageSize: number, filter: F) {
225195
const { allItems } = this,
226196
newList: D[] = [];
227197
const newCount = pageIndex * pageSize - allItems.length;

source/utility/type.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import { TypeKeys } from 'web-utility';
22
import { HTTPClient, Context } from 'koajax';
33

4+
export type AbstractClass<I> = abstract new (...data: any[]) => I;
5+
46
export type IDType = number | string;
57

68
export type DataObject = Record<string, any>;

0 commit comments

Comments
 (0)