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

api-donkey

v1.0.5

Published

Downloads

8

Readme

技术预期

初步建模

在初步的建模推演中,我们期望通过一个较为详细的数据结构,分别生成数据库表字段、本地数据库增删改查调用、远程数据库增删改查调用、前端请求接口这4套代码,在每一份生成文件中都包含其环境本身的环境数据,环境数据支持配置,例如生成远程数据库调用时,由于我们使用的是typeorm,并且是在nest.js中被使用,因此需要按照它的语法形式来生成,包含modules、services、controllar三份文件,每份文件有其自身的职责。

模型验证

通过参考项目中的实际用例,按照初步建模时约定的数据结构风格,尝试描述实际用例中的业务逻辑,看是否能够满足。如果满足,则可证明建模成功。在过程中需要注意隔离噪音。

数据库表字段模型

{
  uniqueID: ["uuid"],
  groupID: 0,
  uri: "",
  requestBody: ["json", "!required"],
}

// =>

class {
  @Column()
  @Generated('uuid')
  uniqueID: string;

  @Column({ default: 0 })
  groupID: number;

  @Column()
  uri: string;
}

前后设计了三种设计方案,前两种思路分别是 简化语法 和 抽象语法,第二种比第一种略微好一些,但效果仍然不能让人十分满意,因此构思了第三种方案——即针对数据库的字段场景,对类型做扩充。

我们知道,js只有7种数据类型,而能够与数据库相关的只有四种,这还是勉强把 null 算上的情况下。因此,类型种类太少,直接制约了灵活程度,我们需要用较多的信息才能够准确描述一个数据库字段。比如我们要描述一个整数类型,这用js本身的类型很难简洁地描述出来。

因此,新的语法是建立在扩充了更多类型的基础上,尽管扩充了不少类型,但对于程序员而言,是十分易懂且符合直觉的,例如我们用 int 来表示一个整数类型,它可以同时表示字段是个 number 类型并且是个整数。又例如required类型,它可以直接表示一个必填字段,但数据库的字段在大多数情况下都是必填的,因此该字段默认可以不写,只有当我们需要表达一个字段是非必填的,才会需要写 !required。是的,扩充后的类型可以支持非的逻辑。

当然,在语法设计上,它可以支持如!int表示一个非整数型的字段,但我们目前没有计划要实现这样稍显怪异的逻辑。

| 扩展的类型 | 默认值 | 描述 | | ---------- | ------ | ---------- | | uuid | 无 | 唯一id | | time | 无 | 时间戳 | | int | 无 | 整数 | | required | true | 必填 | | !required | 无 | 非必填 | | json | 无 | json字符串 |

服务层模型

{
    bulkUpdate: new Orm().save(),
    update: new Orm(':number', ':UpdateDto').update()
}

// => 

async bulkUpdate(...args) {
    return await this.repository.save(...args);
}

async update(param1: number, param2: UpdateDto) {
    return await this.repository.update(param1, param2);
}

运行时加载ts文件

为了保留尽可能多的类型信息,方便书写时校验,因此希望源文件的数据结构用ts语法书写,但编译器仅需要js信息即可,因此希望在node环境中能够直接运行编译后的ts文件,拿到导出处后的信息。

为此,期望能够实现loadTs函数,它使用 esbuild API 在运行时将ts文件编译成cjs包规范的js文件,让编译器能够直接读取导出后的内容对象(非字符串)。 请进行基本实现,最终运行 node main.js 能够调用 handle() 函数并输出 18.

请参考

$ node main.js
$ 18

最终使用了 esbuild + eval 结合的方式来实现运行时读取ts导出的内容

以 npm 包的形式运行

为了在实际工程中使用,需要将改项目改造为命令行工具,预期:

# 查看版本号
$ donkey --version

# 读取当前目录下的配置文件并生成
$ donkey run 

开发时,在本项目下运行 pnpm link --global 即可映射到全局。

运行前读取当前目录下的配置信息

在运行目录下,一般是项目的根目录,需要读取配置文件信息,配置文件名暂定为:donkey.config.js

  • 如果没有检测到该文件则不允许运行该程序。
  • 如果当前目录下没有package.json,也不允许运行该程序。
  • 一切的生成目标以配置信息为准;如果配置文件的output字段中不包含生成目标,则不允许生成。例如, output中没有angular,则不会生成angular相关的代码。同理,如果output字段不存在或为空,则不会生成任何代码。

配置暂定使用cjs包规范,配置文件中包含以下几项内容:

module.exports = {
    entry: {
        target: "./source",
        suffix: 'ts'
    },
    output: {
        angular: './output/http',
        schema: './output/entities',
        dexie: './output/dexie',
        typeorm: './output/typeorm'
    }
}

其中的文件夹路径都是相对于运行时目录。