最近把项目中的 sequelize 由 4.38.0 升级到了 5.8.7,以下是升级记录

本文地址: shanyue.tech/post/sequel…

01 删包

从 package.json 中删掉 sequelize 以及 @types/sequelize

02 过文档

大致过一遍官方升级文档 docs.sequelizejs.com/manual/upgr…

03 npm install

由于官方提供了 typescript 的支持,不需要在安装 @types/sequelize

npm install sequelize
复制代码

04 tsc

由于使用了 typescript 编译,解决问题。

$ tsc
...
Found 1361 errors.
复制代码

05 new Sequelize

从数据库初始化入手,解决一些 Sequelize 实例化时的类型问题

06 AnyModel & AnyPropModel & Sequelize.define

由于 sequelizetype 此时由官方维护,重新定义了 Model 等类型。

虽然目前官方已经支持了对 Model 的 typescript 支持,但是为了更小幅度的升级,仍然使用 Sequelize.define

以后将 AnyPropModel 逐渐替换为 UserModel 等真实的 Model。

根据文档,对 Model 以及 Sequelize.define 做以下更改。

class AnyPropModel extends Model {[key: string]: any;
}export type AnyModel = typeof Model & {new (values?: any, options?: BuildOptions): AnyPropModel;
}export type Models = Record<string, AnyModel>;const UserModel = <AnyModel>sequelize.define('MyDefineModel', {id: {primaryKey: true,type: DataTypes.INTEGER.UNSIGNED,}
});
复制代码

更改之后再次编译.

$ tsc
Found 898 errors.
复制代码

07 归并与分类,逐个击破

对 typescript 编译出来的错误信息进行格式化并做统计,以下为格式化数据,抽出 { file, code, message }

本来也想抽出 lines,没有成功...

$ tsc | grep 'error TS' | jq -R -c -s 'split("\n") | map(capture("(?<file>.+): error (?<code>.+): (?<message>.+)")) | .[]' > build.jsonl
$ head -3 build.jsonl
{"file":"bin/demo.ts(278,23)","code":"TS2351","message":"Cannot use 'new' with an expression whose type lacks a call or construct signature."}
{"file":"src/helpers/one.ts(36,23)","code":"TS2576","message":"Property 'literal' is a static member of type 'Sequelize'"}
{"file":"src/helpers/two.ts(188,24)","code":"TS2576","message":"Property 'fn' is a static member of type 'Sequelize'"}复制代码

根据格式化信息,对相同 code 的错误进行分类,先解决错误率最高的五类

$ cat build.jsonl | jq -s 'group_by(.code) | map({count: length, code: .[0].code, message: .[0].message}) | sort_by(.count) | .[]'
{"count": 41,"code": "TS6133","message": "'DataTypes' is declared but its value is never read."
}
{"count": 53,"code": "TS2339","message": "Property 'id' does not exist on type 'object'."
}
{"count": 82,"code": "TS2709","message": "Cannot use namespace 'DataTypes' as a type."
}
{"count": 94,"code": "TS7006","message": "Parameter 'e' implicitly has an 'any' type."
}
{"count": 142,"code": "TS2576","message": "Property 'col' is a static member of type 'Sequelize'"
}
{"count": 335,"code": "TS2531","message": "Object is possibly 'null'."
}
复制代码

08 TS2576: Sequelize.prototype -> Sequelize

"Property 'col' is a static member of type 'Sequelize'"
"Property 'literal' is a static member of type 'Sequelize'"
"Property 'or' is a static member of type 'Sequelize'"
复制代码

根据文档 docs.sequelizejs.com/manual/upgr…

Sequelize 示例上的很多方法变成了 static method.

借助 VS Code 与其内置的命令行工具,输入命令 tsc | grep 2576 可以更快解决问题:

  1. tsc | grep 2576 提供所有的此类问题与行号
  2. VS Code 可以根据行号快速定位

但不管怎么说,这还是一个体力活......

09 TS2339 Model 的废弃方法

Property 'findById' does not exist on type 'AnyModel'.
Property 'find' does not exist on type 'AnyModel'.
Property 'id' does not exist on type 'AnyPropModel | null'.
Property 'LOCK' does not exist on type 'Transaction'.
复制代码

这个在升级文档中也提到过 docs.sequelizejs.com/manual/upgr…

至于替换也是一个体力活,再次编译

Found 753 errors.

10 TS2531 Object is possibly 'null'

$ tsc | grep 2531 | wc406
复制代码

再次统计下此问题的个数,比刚才统计时多了一百多

我们总是在不停地解决 Bug 的过程中引入新的 Bug。在解决旧 Bug 的过程中总有产生新 Bug 的风险

findById 更改之后有更多的问题显现出来,是因为没有对返回的数据做不存在断言处理,如下例所示

const user = await models.user.findOne()
// 此时 user 可能不存在,可能报错
const id = user.id
复制代码

在解决问题之前,我先分析下原因

使用 rejectOnEmpty 来修正它,他能保证数据一定存在

const user = await models.User.findOne({rejectOnEmpty: true
})
复制代码

接下来就是体力活了:

  1. tsc | grep 2531 提供所有的此类问题与行号
  2. VS Code 根据行号快速定位
  3. gd vim 的 Go to Def 可以快速定位到出问题的变量定义处
  4. "0p 使用 vim 把 rejectOnEmpty 至于0号寄存器,快速粘贴
  5. == vim 进行格式化

再次编译:

Found 335 errors.

11 migration

TS2709: Cannot use namespace 'DataTypes' as a type
复制代码

这都是在 migration 文件中的内容,既然数据库迁移脚本已经执行过了,它其实也没多大用处了,我觉得不改也可以了...

另外,migration 这种数据库迁移脚本是不是可以单独从项目中抽出来,有两个原因

  1. 它是一次性脚本
  2. 一个数据库有可能对应多个后端应用
import { QueryInterface, DataTypes } from 'sequelize'export const up = async function (queryInterface: QueryInterface, Sequelize: DataTypes) {}
复制代码

全局替换

Sequelize: DataTypes -> sequelize: typeof Sequelize

Found 216 errors.

12 implicitly any

TS7006 Parameter 'item' implicitly has an 'any' type.
复制代码

解决后再次编译

Found 185 errors.

13 使用 sed 批量替换 Op

// 替换前
where.count = { $lte: 10 }
where.count['$lte'] = 10
where.count.$lte = 10// 替换后
where.count = { [Op.lte]: 10 }
where.count[Op.lte] = 10
where.count[Op.lte] = 10
复制代码

写一段 sed 脚本来批量替换

再次编译

Found 412 errors.

14 补充 Op

以上错误的原因过多是因为批量替换成 Op 后提示 Op 不存在

import { Op } from 'sequelize'
复制代码

15 再次统计

$ tsc | grep 'error TS' | jq -R -s 'split("\n") | map(capture("(?<file>.+): error (?<code>.+): (?<message>.+)")) | group_by(.code) | map({count: length, code: .[0].code, message: .[0].message}) | sort_by(.count) | .[]'{"count": 12,"code": "TS2684","message": "The 'this' context of type 'typeof Model' is not assignable to method's 'this' of type '(new () => Model<{}, {}>) & typeof Model'."
}
{"count": 14,"code": "TS2322","message": "Type 'true' is not assignable to type 'false'."
}
{"count": 18,"code": "TS2694","message": "Namespace '\"/Users/shanyue/backend/node_modules/sequelize/types/index\"' has no exported member 'AnyFindOptions'."
}
{"count": 20,"code": "TS2532","message": "Object is possibly 'undefined'."
}
{"count": 118,"code": "TS2304","message": "Cannot find name 'Op'."
}
复制代码

都是一些小问题了,逐个解决

16 git diff

统计下修改了多少内容

$ git diff master --shortstat199 files changed, 1784 insertions(+), 1411 deletions(-)
复制代码

17 运行时问题: postgres range

以上编译时的问题解决了,最令人头疼的还是运行时问题了

这次碰到的是 postgres 的 range 这个数据类型

// 更改前
[0, 100]// 更改后
[{value: 0,inclusive: false
}, {value: 100,inclusive: true
}]
复制代码

但是如果对数据库的每个 Model 都加上 type 的话,这个问题就可以在编译时解决

18 运行时问题: undefined in where

在 where 中遇到 undefined 会抛出异常。github.com/sequelize/s…

使用 _.pickBy 过滤掉 undefined

const where = _.pickBy(data, x => x !== undefined)
复制代码

当然,如果 typescript 做的比较严格的话,这个问题也可以避免

19 运行时问题: _.assign({ [Op.ne]: 3 })

_.assign 会丢失 Symbol 属性,使用 Object.assign 代替


欢迎关注我的公众号山月行,在这里记录着我的技术成长,欢迎交流

转载于:https://juejin.im/post/5d097c6ff265da1ba25261ed

sequelize V5 升级记录相关推荐

  1. python爬虫的技能_python-爬虫技能升级记录

    ====== python-爬虫技能升级记录 ====== ===== (一)感知爬虫及爬取流程 ===== 从简单存取一个页面到 爬取到大量的定量数据,对技术要求更高,以百度百科数据爬取为入门练手项 ...

  2. 点晴免费OA系统的2017年升级记录

    点晴免费OA系统的2017年升级记录 点晴OA系统不但是永久免费,不限用户数,功能全开放,而且还提供免费客服咨询和免费升级服务,免费OA的系统升级并不是隔几个月才发布一次升级包,优化点晴OA系统不太主 ...

  3. Python3.10升级记录

    2021.10.4日,Python3.10正式版发布了,为了使用新的match语法,2021.10.8将Python3.7升级到了Python3.10,升级记录如下: 1.官方安装包: 因为不是3.X ...

  4. PlantSimulation 15.2 16.0 16.1升级记录

    PlantSimulation 15.2 16.0 16.1升级记录 Plant Simulation 16.0 中的新功能和更改功能 •我们将 JSON 添加到 SimTalk 数据类型中. 我们添 ...

  5. ApiPost V5 升级指南

    同旧版本相比,ApiPost V5 (以下简称V5)重新规划了底层架构,大大降低了内存使用率:并加入了大量新功能,用户体验也有了全新的提升.但是同旧版相比,很多使用方式有所不同,本文重点讲解以下用户升 ...

  6. MAC OS升级记录

    家里有台老MAC一直在吃灰,最近拿出来使用时发现各种软件都不能使用了,安装软件时发现系统版本比较低无法安装软件.于是就想升级系统版本,下面是升级过程的记录,以便后续再升级时查阅. 1.升级时需要使用A ...

  7. 打怪升级记录(2018-2019)

    以下都是工作生活中的记忆随笔与感悟,估计从2018年初着手写的,会持续更新...(20191218) emmmm 代码1->2级记录 1.写代码不能炫技,要怎么方便怎么清晰怎么来: 2.程序注意 ...

  8. Jetson nano/NX 部署Yolo v5过程记录

    前言 大部分过程非原创,写这篇文章主要是因为设备不同出的问题也各不相同,需要到处去找解决方法,因此我把配置过程中遇到的全部问题以及解决方法记录在此. 一.配置cuda环境 烧录jetpack时已经内置 ...

  9. 塔式服务器内存升级记录

    公司有台DELL T430塔式服务器近期需要升级内存,服务器安装了EXSI,升级步骤记录以下 1.停用虚拟机 vsphere或者vmware客户端连如服务器,关闭每个虚拟机电源 2.进入维护模式 关闭 ...

最新文章

  1. list python 转tensor_TensorFlow 中的几个关键概念:Tensor,Operation,Graph,Session
  2. 07 Java面试反射原理
  3. java 插入排序_看动画学算法之:排序-插入排序
  4. MySQL 优化原理(一)
  5. 重写ScrollView实现两个ScrollView的同步滚动显示
  6. linux 文件中搜索字符串命令 grep
  7. vue-cli新建工程后提高页面加载速度(含升级webpack4)
  8. 计算机学硕考研复试编程能力,苏州大学计算机学硕专业考研复试真题
  9. DataGrid的动态绑定问题(二)
  10. 巧妙实现表格奇偶行换色
  11. Python 算法交易实验30 退而结网7-交易策略思考
  12. 卸载mysql server_windows中彻底卸载mysql
  13. 2019杭电多校6,E.Snowy Smile(线段树维护子段和)
  14. Mysql根据汉字英文字母进行排序
  15. java pacs上传服务_有没有办法将DICOM数据发送到远程PACS服务器上的特定目录?
  16. 软考证书如何评职称?
  17. Linux 基金会成立小组支持边缘网络开发;浙江绍兴用 AI 监控厨房
  18. android手机 垃圾箱,Dumpster Pro「回收站」v3.6.386 for Android 直装解锁高级版 —— 一款不错的 Android 垃圾箱 / 回收站应用...
  19. 1分钟链圈|什么?11岁男孩竟然当上区块链公司CEO!融资33亿美元,EOS注定成史上最大ICO...
  20. python分子化学模拟_#分子模拟#MDTraj分子模拟python包(一)

热门文章

  1. ARM开发板,ARM方案定制,嵌入式产品开发,深圳瑞芯微方案商,rk3288主板,rk3399主板
  2. Wine完全使用完全指南(从初级到高级)
  3. .net控件开发之类型转换器
  4. Python从入门到精通,100天就够了!(1)——Python初体验
  5. virtualbox内部连不上问题
  6. [文章]剖析WEB 2.0
  7. 互联网江湖录2——南少林盛大
  8. [车联网安全自学篇] Android安全之Android 如何生成APP(APK)「详解」
  9. 使用Android Glide技术实现图片加载和播放视频
  10. 浅谈Go语言(6) - 函数与结构体