npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

http-api-model

v1.0.12

Published

A api Model 。一个接口模型。

Downloads

8

Readme

安装

npm install http-api-model

简要说明

对于axios的Model化封装,参考php laravel orm,希望在前端也能有类似后端的模型概念。
使用localForage 提供模型本地缓存功能。针对每次请求的参数来存储缓存数据。
使用时包后,继承 Model 开始使用。
更新
缓存配置 single 为true 时,空参数将尝试获取缓存数据。

简要示例,包含基础模型,登录模型,数据模型。通常一个class 一个文件

import {Model} from "http-api-model";
import type {AxiosResponse} from "axios";

// 假定下面是 MyBaseModel.ts 文件

// 项目基础模型
export default class MyBaseModel extends Model {
    constructor() {
        super();
        this.config({
            baseUrl: '/apiRoot',
            method: 'post'
        });
        this.cache.config({
            use: true,
            // 使用分账号缓存
            account: () => MyBaseModel.cacheAccount,
            // account:()=>MyBaseModel.loginModel?.data.account,
        })
    }

    // 静态 token 和 cacheAccount 为自行扩展实例,模型本身没有这部分。
    protected static token = '';
    // 缓存账号值,通过登录接口设置
    protected static cacheAccount = ''
    // 可以考虑挂载 登录接口。注意只放类型,避免 import 错误。
    // protected static loginModel?:Login

    // 请求前处理config ,可添加登录信息
    protected handleRequest() {
        this._config.headers = this._config.headers || {};
        this._config.headers['token'] = MyBaseModel.token
    }

    // 自行根据接口格式,判断请求时成功还是失败
    protected handleIsSuccess(r: AxiosResponse): boolean {
        return r.status === 200;
    }

    // 自行根据请求格式,获取模型数据
    protected handleResponseData(r: AxiosResponse): this['data'] {
        // 获取接口中的数据
        return r.data.returnContent;
    }

    // handleIsSuccess  false 时
    protected handleFail(r: AxiosResponse) {
        //     请求失败了,如何处理,如展示异常提示
    }

    protected handleError(e: any) {
        //请求异常处理
    }

    protected handleEnd() {
        // 相当于 Promise.finally
        // 接口结束时调用,无论失败还是异常,都会执行。
    }
}

// 假定下面是  Login.ts 文件
export default class Login extends MyBaseModel {
    constructor() {
        super();
        this.config({
            url: 'xxx/xx'
        })
    }

    // 请求参数
    query = {
        account: '',
        password: ''
    }
    // 模型数据
    data = {
        token: '',
        account: '',
        name: '',
        age: undefined as number | undefined,
        heigiht: 0,
    }

    protected handleResponseData(r: AxiosResponse): this['data'] {
        // 获取接口中的数据
        const mData = r.data.returnContent as this['data'];
        // 设置项目身份凭证
        MyBaseModel.token = mData.token;
        MyBaseModel.cacheAccount = mData.account;
        return mData;
    }
}

const login = new Login();
login.fetch()


// 假定下方是 MyUser.ts 文件

export default class MyUser extends MyBaseModel {
    constructor() {
        super();
        this.config({
            // 这个接口用get
            method: 'get',
            url: 'xxx/xx'
        })
    }

    // 请求参数
    query = {
        id: ''
    }
    // 模型数据
    data = {
        name: '',
        age: undefined as number | undefined,
        heigiht: 0,
    }

    save() {
        return new MyUserSave().setQuery(this.data).fetch()
    }
}
// 用户保存接口 和 用户详情强相关,且仅用与保存。
// 这样的接口,可以放到 MyUser 模型文件中
class MyUserSave extends MyBaseModel {
    constructor() {
        super();
        this.config({
            // 这个接口用get
            method: 'post',
            url: 'xxx/xx'
        })
    }

    // 请求参数
    query: MyUser['data'] = {
        // 这里不重复写了
    }
}


// 这里假定已登录

const user = new MyUser();
// 设置查询参数
// user.query.id = 'id1';
user.setQuery({id: 'id1'})
// 发起请求或获取缓存
user.fetch().then(v => {
    // 使用数据
    // console.log(v.data.name);
    console.log(user.data.name);
})

Model 详细内容说明

import type { AxiosRequestConfig, AxiosResponse } from "axios";
import ModelCache from "./ModelCache";
export default class Model {
    /**
     * 模型初始化。将在调用设置config时执行,若不需要设置config,请手动执行它
     * @protected
     */
    protected initModel(): void;
    /**
     * 初始的请求参数
     * @private
     */
    private initQuery;
    /**
     * 上次请求参数
     * @private
     */
    private lastQuery;
    /**
     * 初始数据
     * @private
     */
    private init;
    /**
     * 上次请求数据
     * @private
     */
    private _last;
    /**
     * 上次请求结果数据
     */
    get last(): this['data'];
    private _isSuccess;
    protected _config: AxiosRequestConfig;
    /**
     * 设置请求配置并初始化模型,应只在construct调用
     * 也应在每个 模型 construct 中调用一次  this.config({});以完成初始化
     * @param options
     */
    config(options: AxiosRequestConfig): this;
    /**
     * 获取请求配置,不太常用
     */
    config(): AxiosRequestConfig;
    /**
     * 定义请求参数
     */
    query: any;
    /**
     * 批量设置请求参数
     * @param q
     */
    setQuery(q: Partial<this['query']>): this;
    /**
     * 将参数重置回上次请求时
     */
    resetQuery(): void;
    /**
     * 重置回最初参数
     * 请在 construct 中 initModel 或 设置 config
     * 否则可能不准确
     */
    clearQuery(): void;
    /**
     * 模型数据,从接口获取的数据(或从缓存),通常为数据字典。
     * 注意,data应为普通数据类型,不能含有函数,getter setter。否则可能缓存不全或异常。
     */
    data: any;
    /**
     * 批量设置模型数据
     * @param r
     */
    setData(r: Partial<this['data']>): this;
    /**
     * 将模型数据重置回上次请求的数据
     */
    reset(): void;
    /**
     * 将数据重置回初始化
     * 请在 construct 中 initModel 或 设置 config
     * 否则可能不准确
     */
    clearData(): void;
    private updateLast;
    /**
     * 请求是否成功,仅为 true 表示请求成功 false也能是还未请求
     */
    get isSuccess(): boolean;
    /**
     * 缓存控制类
     * @protected
     */
    readonly cache: ModelCache<this>;
    private _isCache;
    /**
     * 是否是缓存数据
     */
    get isCache(): boolean;
    protected _isFail: boolean;
    /**
     * 模型获取数据,从缓存或api获取数据
     */
    fetch(): Promise<this>;
    /**
     * 缓存模型数据
     * 只会经历  handleError  handleEnd
     */
    saveCache(): Promise<this>;
    /**
     * 接口发送时需要的参数,可抛出异常,终止请求
     * 返回值说明
     * default 存在时,会忽略 params data
     * default中的值,会根据请求类型 放入 get 或 post参数
     * params 会放入 AxiosRequestConfig.params
     * data 对应 AxiosRequestConfig.data
     * @protected
     */
    protected handleTransformQuery(): {
        default?: any;
        params?: any;
        data?: any;
    };
    /**
     * 在 handleTransformQuery 后执行
     * 请求配置处理,可修改config,比如设置登录token
     * 也可在此将上传数据,转为 FormData
     * @protected
     */
    protected handleRequest(): void;
    /**
     * 请求成功时执行,
     * 数据是否正确,默认 httpCode 200状态成功 AxiosResponse.status === 200;
     * 假设 接口格式 {status:1,msg:'',content}   AxiosResponse.data.status === 1;
     * @param r
     * @protected
     */
    protected handleIsSuccess(r: AxiosResponse): boolean;
    /**
     * 数据正确时执行(handleIsSuccess true 执行)
     * 根据自己的接口规则,从AxiosResponse中返回模型数据。
     * 注意返回原始值,当心返回 Proxy 等对象或含有函数,可能会导致异常。
     * 默认返回 AxiosResponse.data
     * 举例 接口格式 {code:1,returnContent:{},msg:''},应返回 AxiosResponse.data.returnContent
     * 也可自行调整接口数据格式,如 接口 {userName:'',userAage:0}-> 模型data{name:'',age:0}
     * @param r
     * @protected
     */
    protected handleResponseData(r: AxiosResponse): this['data'];
    /**
     * 数据异常时执行(handleIsSuccess false 执行)
     * 处理接口数据状态异常
     * @param r
     * @protected
     */
    protected handleFail(r: AxiosResponse): void;
    /**
     * 请求错误处理
     * @param e
     * @protected
     */
    protected handleError(e: any): void;
    /**
     *  请求结束处理 等于 Promise.finally,无论成功失败都会执行
     *  可以进行 接口异常日志发送等操作
     * @protected
     */
    protected handleEnd(): void;
    private _loading;
    /**
     * 模型是否请求中
     */
    get loading(): boolean;
    private set loading(value);
    /**
     * 模型loading变化处理,如可控制展示 全屏 loding效果,若有需要
     * @protected
     */
    protected handleLoading(): void;
    /**
     * 模型数据是否发生变更,不传参任意检查任意变更,,传入模型数据path,检查指定变更
     * path   'a.b','a[0].a'
     * @param path
     */
    hasChanged(path?: keyof this['data'] | string): boolean;
    private relationKey;
    /**
     * @param M  类本身,该关系未建立时会关键关联,已建立直接返回关联模型
     * @protected
     */
    protected relation<T extends Model>(M: new () => T): T;
    /**
     * @param M  关联模型实例,已设置会覆盖,未设置会设置关联
     * @protected
     */
    protected relation<T extends Model>(M: T): T;
}

模型缓存配置

import localforage from "localforage";
import type Model from "./Model";
import dayjs from "dayjs";
type ModelCacheConfig = ReturnType<typeof localforage['config']> & {
    /**
     * 是否使用缓存,默认false
     */
    use: boolean;
    /**
     * 设置过期时间,默认值 () => dayjs().add(10, 'minute'); 10分钟;false 不过期。
     */
    expireDate: () => Date | dayjs.Dayjs;
    /**
     * 账号名(唯一),给定此值时,将以此作为数据库名称。可以返回登录账号的id,用户名等,但应当保证唯一,
     * 当不同用户登录时,同一个接口可能返回不同的信息。如我发布的文章。传入此参数可根据账户缓存数据。
     * 优先级  account,name。
     * 注意,登录接口,或是通用接口(不需要登录的接口),应当设置为 false。
     * 常用情况为 项目模型基类 中  account:()=>accountModel.uniName; accountModel 中 account:undefined 。
     */
    account?: false | (() => string);
    /**
     * 是否仅保留一个缓存,默认值 false。启用时,设置缓存数据前会清空当前模型的其他缓存,使其只保留一份。
     * 如登录账户应当只有一条记录
     */
    single: boolean;
    /**
     * 过期数据是否使用,默认值 false。
     * 启用时,即使缓存数据已过期也会返回并使用。同时也会请求接口更新数据和缓存。
     */
    useExpireData: boolean;
    /**
     * 模型过期自动数据清理间隔,默认值 () => dayjs().add(10, 'minute');10分钟
     */
    clearExpireInterval: () => Date | dayjs.Dayjs;
    /**
     * 应当很少能用到
     * 序列化存储缓存,变更会清空数据,默认false。当下载文件时,若需要缓存文件可能需要。当返回结果非常大时,可能需要
     */
    serializer: boolean;
};
/**
 * 模型的缓存控制
 */
export default class ModelCache<M extends Model> {
    constructor(model: M);
    private readonly model;
    private _localForage;
    get localForage(): LocalForage;
    private _config;
    /**
     * 设置如何缓存
     * @param options
     */
    config(options: Partial<ModelCacheConfig>): M;
    config(): ModelCacheConfig;
    /**
     * 根据是否序列化,拼接仓库名
     * @param serializer
     * @private
     */
    private storeName;
    private key;
    /**
     * 将 Model.query 浅层拼接为key,忽略 空置,复杂数据仅使用类型名
     * boolean 转为 01
     * @param up
     * @private
     */
    private getKey;
    private convertToKeyValueString;

    protected getItem(request: () => void): Promise<any>;

    protected setItem(val: any): Promise<unknown>;
    /**
     * 移除本条缓存,列如某个列表删除一条数据后,需要移除后重新从接口获取数据
     */
    removeItem(): Promise<unknown>;
    private expireMan;
    /**
     * 清除模型所有过期数据
     */
    clearExpire(): Promise<void>;
    private isExpire;
    /**
     * 清空本模型的所有缓存
     */
    clear(): Promise<void>;
    /**
     * 删除数据仓库(数据表)
     */
    delStore(): Promise<void>;
    /**
     * 清空数据库(注意配置的 name 同 name 会全部清理),会删除掉对应的数据库,请谨慎使用
     */
    delDatabase(): Promise<void>;
}
export {};