mushroomjs v1.1.2
Install
npm install mushroomjsor
yarn add mushroomjsImport
Simple
import mushroom from "mushroomjs";Builder
import { Filter, Sort, Project } from 'mushroomjs';Full
import mushroom, {
defineAsyncResource,
defineAsyncView,
fireEvent,
createRestfulAsyncFunction,
IdType,
IMushroom,
Mushroom,
MushroomRequest,
MushroomRequestSetting,
MushroomRestfulRequest,
MushroomResponse,
MushroomResourceBase,
MushroomListResource,
MushroomFindByIdResource,
MushroomCreateResource,
MushroomBatchCreateResource,
MushroomUpdateResource,
MushroomBatchUpdateResource,
MushroomPartialUpdateResource,
MushroomDeleteResource,
MushroomBatchDeleteResource,
MushroomExtensibleResource,
MushroomError
} from 'mushroomjs';Define resource
Defination
Create a typescript defination script. Ex: api.ts
import mushroom, {
defineAsyncResource,
IMushroom,
MushroomRequest,
MushroomRequestSetting,
MushroomResourceBase,
MushroomListResource,
MushroomCountResource,
MushroomFindByIdResource,
MushroomCreateResource,
MushroomBatchCreateResource,
MushroomUpdateResource,
MushroomBatchUpdateResource,
MushroomPartialUpdateResource,
MushroomDeleteResource,
MushroomBatchDeleteResource,
MushroomListResponse,
MushroomCountResponse
} from "mushroomjs";
interface Foo {
id?: string,
x?: number,
y?: boolean
}
interface FooCustomFunctionRequest extends MushroomRequest {
params: {
f1: boolean,
f2?: string
},
body: {
a: string,
b?: number
}
}
interface FooCustomFunctionResult {
u: string,
v: number
}
interface FooCustomFunction {
customFunctionAsync(request: FooCustomFunctionRequest): Promise<MushroomResponse<FooCustomFunctionResult>>
}
interface FooViewSampleParameters {
param1: string,
param2?: number;
}
interface FooViewSampleItemResult {
v1: IdType,
v2: boolean,
v3?: number
}
interface FooViewSample {
views: {
sampleAsync(viewParams: FooViewSampleParameters, settings?: MushroomRequestSetting): Promise<MushroomResponse<FooViewSampleItemResult[]>>
}
}
defineAsyncResource<Foo>({
name: "foo",
actions: {
findMany: {
clientCache: false, // false means disabled cache
paging: "limitOffset",
includeTotal: true
},
findById: {
clientCache: true // false means disabled cache
},
createOne: {},
createMany: {},
updateOne: {},
updateMany: {},
updatePartially: {},
deleteOne: {},
deleteMany: {},
_raw_http_method_customFunction: {}
},
views: {
sample: { clientCache: true }
}
});
mushroom.$using("your absolute root API URL");
interface MushroomApi extends IMushroom {
foo: MushroomResourceBase & MushroomListResource<Foo> & MushroomCountResource, & MushroomFindByIdResource<Foo> & MushroomCreateResource<Foo> & MushroomBatchCreateResource<Foo> & MushroomUpdateResource<Foo> & MushroomBatchUpdateResource<Foo> & MushroomPartialUpdateResource<Foo> & MushroomDeleteResource & MushroomBatchDeleteResource & FooCustomFunction & FooViewSample
}
export default mushroom as MushroomApi;Usage
import mushroom from "./api"
async function example() {
await mushroom.foo.listAsync();
await mushroom.foo.getAllAsync();
await mushroom.foo.countAsync();
await mushroom.foo.findByIdAsync({id: yourId});
let newId = await mushroom.foo.createAsync(fooInstance);
let newIds = await mushroom.foo.batchCreateAsync(fooInstances);
await mushroom.foo.updateAsync(fooInstance);
await mushroom.foo.batchUpdateAsync(fooInstances);
await mushroom.foo.partialUpdateAsync(fooInstance);
await mushroom.foo.deleteAsync(id);
await mushroom.foo.batchDeleteAsync(ids);
await muuhroom.foo.customFunction({ params: {f1: true}, body: {a: 10} });
let result = await mushroom.foo.views.sample({param1: "abc", param2: 1});
}Advanced Call as prefer role
To specify the role of user, use field preferRole of second parameter. Eg:
The current user has 2 roles Admin and User, api foo.list supports both roles and Admin is in higher priority, to switch to User role, please follow this example:
mushroom.foo.listAsync(arg, {
preferRole: 'User'
});Advanced Text response and Blob response
In some special APIs, response data is not in JSON format. In this case, please do not use response.result, use response.resultAsText(): string or response.resultAsBlob(): Blob instead. Ex:
const response = await mushroom.foo.specialApiAsync(/*parameters here if any*/);
const text = response.resultAsText();Define global view
Global view defination
Create a typescript defination script. Ex: api.ts
import mushroom, {
defineAsyncView,
IMushroom,
MushroomRequestSetting
} from "mushroomjs";
interface SampleViewParameters {
param1: string,
param2?: number;
}
interface SampleViewItemResult {
v1: IdType,
v2: boolean,
v3?: number
}
interface SampleView {
sampleAsync(viewParams: SampleViewParameters, settings?: MushroomRequestSetting): Promise<MushroomResponse<SampleViewItemResult[]>>
}
defineAsyncView("sample", { clientCache: true });
mushroom.$using("your absolute root API URL");
interface MushroomApi extends IMushroom {
$view: SampleView
}
export default mushroom as MushroomApi;Global view usage
import mushroom from "./api"
async function example() {
let result = await mushroom.$views.sample({
param1: "abc",
param2: 1
});
}Event
Register event handler
import mushroom, { MushroomRestfulRequest, MushroomRequest, MushroomError } from "mushroomjs";
mushroom._on("eventName", fnEventHandler);Remove event handler
mushroom._unbindEvent("eventName"); // remove all event handlers of 'eventName' event
mushroom._unbindEvent("eventName", fnEventHandler); // remove specific event handler of 'eventName' eventReflection
mushroom._hasEvent("eventName"); // return true if eventName has handler(s)Built-in events
On request begining
mushroom._on("beginRequest", (args: {request: MushroomRestfulRequest}) => {});Affter request ended
mushroom._on("endRequest", (args: {request: MushroomRestfulRequest, response?: any, error?: MushroomError, cache?: unknown}) => {});Before sending request
mushroom._on("beforeSend", (request: MushroomRestfulRequest, rawRequest: MushroomRequest) => {});Switch to online state
mushroom._on("online", () => {});Fall to offline state
mushroom._on("offline", () => {});API URL
mushroom.$using(rootApiUrl); // set root API URL
let url = mushroom.$using(); // get current root API URLAdvanced Settings for each request
preferRole
override cache settings
To override global cache age, see Request level at Cache age
override global request timeout
To override global request timeout
mushroom.foo.listAsync(arg, {
timeout: 3000, // timeout after 3000 miliseconds or 3 seconds
});inject events for each request
mushroom.foo.listAsync(arg, {
beforeSend: (request, rawRequest) => {}
});abort request
To abort a request, use AbortController in setting. Ex:
const abortController = new AbortController();
setTimeout(() => abortController.abort(), 500);
try {
const res = await mushroom.foo.listAsync({}, {
abortController: abortController
});
console.log(res);
}
catch (e) {
console.error(e);
}Custom methods:
const abortController = new AbortController();
setTimeout(() => abortController.abort(), 500);
try {
const res = await mushroom.foo.barAsync({
settings: {
abortController: abortController
}
});
console.log(res);
}
catch (e) {
console.error(e);
}Caching
By default, mushroom js driver supports client cache for 2 methods listAsync and findByIdAsync if actions.findMany.clientCache == true, actions.findById.clientCache == true
Please see Defination at Define resource.
Mushroom js driver only supports client cache for request which is GET method.
Invalid cache
Clear resource cache
mushroom.foo.invalidCache();Clear cache by url
mushroom.$cache.invalid(url) // url: string - a RESTful url will be invalid cacheClear cache by pattern
mushroom.$cache.invalid(pattern) // pattern: RegEx - a regular expression of RESTful urls will be invalid cacheClear all cache
mushroom.$cache.invalid()Cache age
Global level
mushroom.$setting.set("request.cache.age", ms); // set global cache age value (in milisecond)Request level
let result1 = await mushroom.foo.listAsync({ }, {
cacheAge: 5000 // cache in 5 seconds
});
let result2 = await mushroom.foo.findByIdAsync({
id: "your id"
}, {
cacheAge: 10000 // cache in 10 seconds
});
let result = await mushroom.foo.customMethodAsync({ }, {
cacheAge: 15000 // cache in 15 seconds
});Settings
Setting global cache age
mushroom.$setting.set("request.cache.age", 300000); // default: 5 minutesSetting global request timeout
mushroom.$setting.set("request.timeout", timeout_in_ms); // default: undefined (mean: depending on each browser/system)Setting flags
Log generic information
mushroom.$setting.set("diagnostic.log_info", true); // default: falseWarning on slow connection
mushroom.$setting.set("diagnostic.warning_slow_connection", true); // default: falseSlow connection info will be outputed at console.
mushroom.$setting.set("diagnostic.slow_connection_milliseconds", 2000); // default: 2 secondsSlow connection if an API was requested that took more than diagnostic.slow_connection_milliseconds
Log request
mushroom.$setting.set("diagnostic.log_request", true); // default: falseLog response
mushroom.$setting.set("diagnostic.log_response", true); // default: falseLog cache hit
mushroom.$setting.set("diagnostic.log_cache_hit", true); // default: falseFor NodeJS
Required addition dependency: node-fetch
Custom extension
Custom extension defination
mushroom.$ext = mushroom.$ext || {};
mushroom.$ext.method1Async = ... // see Defination of Custom method aboveCustom extension usage
await mushroom.$ext.method1Async(1, 2, 3);Builders
Filter builder
Usage
import { Filter } from 'mushroomjs';
let filter : IBuilder;
// create filter here
mushroom.foo.listAsync({
filters: filter.build()
})eq
filter = Filter.eq("x", 10); // x=10ne
filter = Filter.ne("x", 10); // x!=10lt
filter = Filter.lt("x", 10); // x<10lte
filter = Filter.lte("x", 10); // x<=10gt
filter = Filter.gt("x", 10); // x>10gte
filter = Filter.gte("x", 10); // x>=10min
Alias of gte
filter = Filter.min("x", 10); // x>=10max
Alias of lte
filter = Filter.max("x", 10); // x<=10in
filter = Filter.in("x", [1, 2, 3]); // x:in:1,2,3nin
filter = Filter.nin("x", [1, 2, 3]); // x:nin:1,2,3all
filter = Filter.all("x", [1, 2, 3]); // x:all:1,2,3like
filter = Filter.like("x", "%abc%"); // x:like:%abc% (% will be url-encoded to %25)regex
Without options
filter = Filter.regex("x", /ab[cd]/); // x:regex:ab[cd]
filter = Filter.regex("x", "ab[cd]"); // x:regex:ab[cd]With options
filter = Filter.regex("x", /ab[cd]/i); // x:regex_i:ab[cd]
filter = Filter.regex("x", "ab[cd]", "i"); // x:regex_i:ab[cd]
filter = Filter.regex("x", /ab[cd]/m); // x:regex_m:ab[cd]
filter = Filter.regex("x", "ab[cd]", "m"); // x:regex_m:ab[cd]
filter = Filter.regex("x", /ab[cd]/im); // x:regex_im:ab[cd]
filter = Filter.regex("x", "ab[cd]", "im"); // x:regex_im:ab[cd]elementMatch
filter = Filter.elementMatch("x", [Filter.eq("y", 10), Filter.gt("z", 3)]); // x:elemMatch:y=10,z>3nelementMatch
filter = Filter.nelementMatch("x", [Filter.eq("y", 10), Filter.gt("z", 3)]); // x:nelemMatch:y=10,z>3size
filter = Filter.size("x", 4); // x:size:4isNull
filter = Filter.isNull("x"); // x:is_null:true
filter = Filter.isNull("x", false); // x:is_null:falseand
filter = Filter.and([Filter.eq("y", 10), Filter.gt("z", 3)]); // y=10&z>3
filter = Filter.and(Filter.eq("y", 10), Filter.gt("z", 3)); // y=10&z>3or
filter = Filter.or([Filter.eq("y", 10), Filter.gt("z", 3)]); // y=10|z>3
filter = Filter.or(Filter.eq("y", 10), Filter.gt("z", 3)); // y=10|z>3empty
filter = Filter.empty(); // empty stringfilter chain
filter = Filter.eq("a", 1).lt("b", 2); // a=1&b<2
filter = Filter.eq("a", 1).lt("b", 2).or(Filter.eq("c", 3).gte("d", 4)); // :and:a=1,b=2|:and:c=3,d=4
filter = Filter.eq("a", 1).lt("b", 2).and(Filter.or(Filter.eq("c", 3), Filter.gte("d", 4))); // a=1&b=2&c=3|d=4
filter = Filter.empty().eq("a", 1); // a=1toArray
filters = Filter.eq("a", 1).lt("b", 2).toArray() // [Filter.eq("a", 1), Filter.lt("b", 2)]
filters = Filter.eq("a", 1).or("b", 2).toArray() // [Filter.eq("a", 1), Filter.lt("b", 2)]
filters = Filter.elementMatch("x", [Filter.eq("a", 1), Filter.lt("b", 2)]).toArray() // [Filter.eq("a", 1), Filter.lt("b", 2)]
filters = Filter.eq("a", 1).toArray() // [Filter.eq("a", 1), Filter.lt("b", 2)]asArray
filters = Filter.eq("a", 1).lt("b", 2).asArray() // [Filter.eq("a", 1), Filter.lt("b", 2)]
filters = Filter.eq("a", 1).or("b", 2).asArray() // [Filter.eq("a", 1), Filter.lt("b", 2)]
filters = Filter.elementMatch("x", [Filter.eq("a", 1), Filter.lt("b", 2)]).asArray() // [Filter.eq("a", 1), Filter.lt("b", 2)]
filters = Filter.eq("a", 1).asArray() // ErrorSort builder
Usage
import { Sort } from 'mushroomjs';
let sort : IBuilder;
// create sort here
mushroom.foo.listAsync({
sort: sort.build()
})ascending
sort = Sort.ascending("x"); // xdescending
sort = Sort.descending("x"); // -xthenByAscending
sort = Sort.ascending("x").thenByAscending("y"); // x,ythenByDescending
sort = Sort.ascending("x").thenByDescending("y"); // x,-yProject builder
Usage
import { Project } from 'mushroomjs';
let project : IBuilder;
// create project here
mushroom.foo.listAsync({
fields: project.build()
})include
project = Project.include("x"); // x
project = Project.include("x", "y"); // x,y
project = Project.include("x").include("y"); // x,yRelease notes
1.1.1
Fix bug:
- Get wrong result when using nested
andfilter in FilterBuilder
1.1.0
New features:
- Support Typescript
- Support NodeJS
- Support Abort request
- Support softDelete
- Support
preferRolefor request - Support
channelforvn_text - Add builders (Filter, Sort, Project)
- And new settings for log actions, such as
diagnostic.log_info,diagnostic.log_cache_hit - Add new methods
countAsync,getAllAsyncfor resource - Add new methods
resultAsBlob,resultAsTextfor reponse.
Fix bugs:
- iOS: missing escape url for filter
- Missing headers which were passed in each api call time
- Wrong in some cases when call api
deleteAsyncandbatchDeleteAsync
10 months ago
8 months ago
1 year ago
1 year ago
2 years ago
2 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
4 years ago
5 years ago
5 years ago
5 years ago
6 years ago
6 years ago
6 years ago