├── .babelrc ├── .dockerignore ├── .gitignore ├── Dockerfile ├── README.md ├── assets └── images │ └── 2.jpeg ├── bin └── deploy.sh ├── custom.d.ts ├── dist ├── entity │ ├── Comment.js │ ├── Post.js │ └── User.js ├── migration │ ├── 1592201997493-CreateUsers.js │ ├── 1592205680555-CreatePosts.js │ ├── 1592206097026-CreateComments.js │ ├── 1592206406201-AddCreatedAtAndUpdateAt.js │ ├── 1592208800876-RenameColumns.js │ └── 1592561070934-AddUniqueUsernameToUsers.js ├── model │ └── SignIn.js └── seed.js ├── hooks ├── useForm.tsx ├── usePager.tsx └── usePosts.tsx ├── lib ├── getDatabaseConnection.tsx ├── post.tsx └── withSession.tsx ├── markdown ├── 第一篇博客.md └── 第二篇文章.md ├── migrate.patch ├── next-env.d.ts ├── next.config.js ├── nginx.conf ├── ormconfig.simple.json ├── package-lock.json ├── package.json ├── pages ├── _app.js ├── api │ ├── hello.js │ └── v1 │ │ ├── posts.tsx │ │ ├── posts │ │ └── [id].tsx │ │ ├── sessions.tsx │ │ └── users.tsx ├── index.tsx ├── posts │ ├── [id].tsx │ ├── [id] │ │ └── edit.tsx │ ├── first-post.js │ ├── index.tsx │ └── new.tsx ├── sign_in.tsx └── sign_up.tsx ├── public ├── favicon.ico ├── logo.png └── vercel.svg ├── src ├── entity │ ├── Comment.ts │ ├── Post.ts │ └── User.ts ├── migration │ ├── 1592201997493-CreateUsers.ts │ ├── 1592205680555-CreatePosts.ts │ ├── 1592206097026-CreateComments.ts │ ├── 1592206406201-AddCreatedAtAndUpdateAt.ts │ ├── 1592208800876-RenameColumns.ts │ └── 1592561070934-AddUniqueUsernameToUsers.ts ├── model │ └── SignIn.ts └── seed.ts ├── study.md ├── styles └── global.css ├── tsconfig.json └── yarn.lock /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["next/babel"], 3 | "plugins": [ 4 | [ 5 | "@babel/plugin-proposal-decorators", 6 | { 7 | "legacy": true 8 | } 9 | ] 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | /blog-data/ 3 | # dependencies 4 | /node_modules 5 | /.idea/ 6 | /.vscode/ 7 | /.pnp 8 | .pnp.js 9 | */.env.local 10 | ormconfig.json 11 | em.sh 12 | # testing 13 | /coverage 14 | 15 | # next.js 16 | /.next/ 17 | /out/ 18 | 19 | # production 20 | /build 21 | 22 | # misc 23 | .DS_Store 24 | 25 | # debug 26 | npm-debug.log* 27 | yarn-debug.log* 28 | yarn-error.log* 29 | 30 | # local env files 31 | .env.local 32 | .env.development.local 33 | .env.test.local 34 | .env.production.local 35 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM node:12 2 | WORKDIR /usr/src/app 3 | COPY package.json ./ 4 | COPY yarn.lock ./ 5 | 6 | RUN yarn install 7 | COPY . . 8 | EXPOSE 3000 9 | CMD ["yarn", "start"] 10 | 11 | # docker build -t sunnyla/node-web-app . 12 | # docker run -p 3000:3000 -d sunnyla/node-web-app 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 项目创建过程 2 | - [Next.js + TypeScript 入门之项目搭建、三种渲染方式(BSR、SSG、SSR)](https://juejin.im/post/6855917901090652174) 3 | - [TS + TypeORM 踩坑实践 (一) hello ORM](https://juejin.im/post/6857391336929263624) 4 | - [TS + TypeORM 踩坑实践 (二) 操作数据表](https://juejin.im/post/6858509402798817294) 5 | - [从 0 开始部署你的 Node 应用(Ubantu、docker、nginx)](https://juejin.im/post/6864785804066029575) 6 | 7 | # 代码使用 8 | 9 | 请下载本代码,然后用 WebStorm 或者 VSCode 打开。 10 | 11 | ## 启动数据库 12 | 13 | 如果你没有创建过数据库,请运行 14 | ```bash 15 | mkdir blog-data 16 | docker run -v "$PWD/blog-data":/var/lib/postgresql/data -p 5432:5432 -e POSTGRES_USER=blog -e POSTGRES_HOST_AUTH_METHOD=trust -d postgres:12.2 17 | 18 | 或者旧版 Windows Docker 客户端运行下面的代码 19 | 20 | docker run -v "blog-data":/var/lib/postgresql/data -p 5432:5432 -e POSTGRES_USER=blog -e POSTGRES_HOST_AUTH_METHOD=trust -d postgres:12.2 21 | ``` 22 | 23 | 如果你创建过数据库,请运行 24 | 25 | ```bash 26 | docker ps -a 27 | docker restart 容器id 28 | ``` 29 | 30 | ## 创建数据库 31 | 32 | ``` 33 | docker exec -it bash 34 | psql -U blog 35 | CREATE DATABASE blog_development ENCODING 'UTF8' LC_COLLATE 'en_US.utf8' LC_CTYPE 'en_US.utf8'; 36 | ``` 37 | 38 | ## 数据表 39 | 40 | 首先修改 ormconfig.json 中的 host,然后运行 41 | 42 | ``` 43 | yarn m:run 44 | ``` 45 | 46 | ## 开发 47 | 48 | ```bash 49 | yarn dev 50 | # or 51 | npm run dev 52 | ``` 53 | 54 | ## 部署 55 | 56 | ```bash 57 | # 执行本地脚本 58 | git push 59 | ssh blog@dev1 'bash -s' < bin/deploy.sh 60 | # 执行服务器上脚本 61 | ssh blog@dev1 'sh /home/blog/app/nextjs-blog/bin/deploy.sh' 62 | ``` 63 | 64 | ## NGINX 配置 65 | ```bash 66 | docker run --name nginx1 --network=host -v /home/blog/nginx.conf:/etc/nginx/conf.d/default.conf -v /home/blog/app/nextjs-blog/.next/static/:/usr/share/nginx/html/_next/static/ -d nginx:1.19.1 67 | ``` 68 | -------------------------------------------------------------------------------- /assets/images/2.jpeg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Maricaya/nextjs-blog/09fca2c3004d4699ec72a61fbc51a1770d923ccb/assets/images/2.jpeg -------------------------------------------------------------------------------- /bin/deploy.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | docker start 54f && 3 | cd /home/blog/app/nextjs-blog/ && 4 | git pull && 5 | yarn install --production=false && 6 | yarn build && 7 | git apply migrate.patch; 8 | yarn compile && 9 | yarn m:run && 10 | git reset --hard HEAD && 11 | docker build -t sunnyla/node-web-app . && 12 | docker kill app && 13 | docker rm app && 14 | #:--network=host 会导致端口映射失效,端口直接就是阿里云机器的端口,但这种模式比较容易理解 15 | docker run --name app --network=host -p 3000:3000 -d sunnyla/node-web-app && 16 | echo "ok!" 17 | -------------------------------------------------------------------------------- /custom.d.ts: -------------------------------------------------------------------------------- 1 | type Post = { 2 | id: string; 3 | date: string; 4 | title: string; 5 | content: string; 6 | htmlContent: string; 7 | } 8 | 9 | type User = { 10 | id: string; 11 | } 12 | -------------------------------------------------------------------------------- /dist/entity/Comment.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); 4 | 5 | Object.defineProperty(exports, "__esModule", { 6 | value: true 7 | }); 8 | exports.Comment = void 0; 9 | 10 | var _initializerDefineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/initializerDefineProperty")); 11 | 12 | var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); 13 | 14 | var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); 15 | 16 | var _applyDecoratedDescriptor2 = _interopRequireDefault(require("@babel/runtime/helpers/applyDecoratedDescriptor")); 17 | 18 | var _initializerWarningHelper2 = _interopRequireDefault(require("@babel/runtime/helpers/initializerWarningHelper")); 19 | 20 | var _typeorm = require("typeorm"); 21 | 22 | var _dec, _dec2, _dec3, _dec4, _dec5, _dec6, _dec7, _class, _class2, _descriptor, _descriptor2, _descriptor3, _descriptor4, _descriptor5, _descriptor6, _temp; 23 | 24 | var Comment = (_dec = (0, _typeorm.Entity)('comments'), _dec2 = (0, _typeorm.PrimaryGeneratedColumn)('increment'), _dec3 = (0, _typeorm.Column)('text'), _dec4 = (0, _typeorm.CreateDateColumn)(), _dec5 = (0, _typeorm.UpdateDateColumn)(), _dec6 = (0, _typeorm.ManyToOne)('User', 'comments'), _dec7 = (0, _typeorm.ManyToOne)('Post', 'comments'), _dec(_class = (_class2 = (_temp = function Comment() { 25 | (0, _classCallCheck2["default"])(this, Comment); 26 | (0, _initializerDefineProperty2["default"])(this, "id", _descriptor, this); 27 | (0, _initializerDefineProperty2["default"])(this, "content", _descriptor2, this); 28 | (0, _initializerDefineProperty2["default"])(this, "createdAt", _descriptor3, this); 29 | (0, _initializerDefineProperty2["default"])(this, "updateAt", _descriptor4, this); 30 | (0, _initializerDefineProperty2["default"])(this, "user", _descriptor5, this); 31 | (0, _initializerDefineProperty2["default"])(this, "post", _descriptor6, this); 32 | }, _temp), (_descriptor = (0, _applyDecoratedDescriptor2["default"])(_class2.prototype, "id", [_dec2], { 33 | configurable: true, 34 | enumerable: true, 35 | writable: true, 36 | initializer: null 37 | }), _descriptor2 = (0, _applyDecoratedDescriptor2["default"])(_class2.prototype, "content", [_dec3], { 38 | configurable: true, 39 | enumerable: true, 40 | writable: true, 41 | initializer: null 42 | }), _descriptor3 = (0, _applyDecoratedDescriptor2["default"])(_class2.prototype, "createdAt", [_dec4], { 43 | configurable: true, 44 | enumerable: true, 45 | writable: true, 46 | initializer: null 47 | }), _descriptor4 = (0, _applyDecoratedDescriptor2["default"])(_class2.prototype, "updateAt", [_dec5], { 48 | configurable: true, 49 | enumerable: true, 50 | writable: true, 51 | initializer: null 52 | }), _descriptor5 = (0, _applyDecoratedDescriptor2["default"])(_class2.prototype, "user", [_dec6], { 53 | configurable: true, 54 | enumerable: true, 55 | writable: true, 56 | initializer: null 57 | }), _descriptor6 = (0, _applyDecoratedDescriptor2["default"])(_class2.prototype, "post", [_dec7], { 58 | configurable: true, 59 | enumerable: true, 60 | writable: true, 61 | initializer: null 62 | })), _class2)) || _class); 63 | exports.Comment = Comment; -------------------------------------------------------------------------------- /dist/entity/Post.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); 4 | 5 | Object.defineProperty(exports, "__esModule", { 6 | value: true 7 | }); 8 | exports.Post = void 0; 9 | 10 | var _initializerDefineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/initializerDefineProperty")); 11 | 12 | var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); 13 | 14 | var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); 15 | 16 | var _applyDecoratedDescriptor2 = _interopRequireDefault(require("@babel/runtime/helpers/applyDecoratedDescriptor")); 17 | 18 | var _initializerWarningHelper2 = _interopRequireDefault(require("@babel/runtime/helpers/initializerWarningHelper")); 19 | 20 | var _typeorm = require("typeorm"); 21 | 22 | var _dec, _dec2, _dec3, _dec4, _dec5, _dec6, _dec7, _dec8, _class, _class2, _descriptor, _descriptor2, _descriptor3, _descriptor4, _descriptor5, _descriptor6, _descriptor7, _temp; 23 | 24 | var Post = (_dec = (0, _typeorm.Entity)('posts'), _dec2 = (0, _typeorm.PrimaryGeneratedColumn)('increment'), _dec3 = (0, _typeorm.Column)('varchar'), _dec4 = (0, _typeorm.Column)('text'), _dec5 = (0, _typeorm.CreateDateColumn)(), _dec6 = (0, _typeorm.UpdateDateColumn)(), _dec7 = (0, _typeorm.ManyToOne)('User', 'posts'), _dec8 = (0, _typeorm.OneToMany)('Comment', 'post'), _dec(_class = (_class2 = (_temp = function Post() { 25 | (0, _classCallCheck2["default"])(this, Post); 26 | (0, _initializerDefineProperty2["default"])(this, "id", _descriptor, this); 27 | (0, _initializerDefineProperty2["default"])(this, "title", _descriptor2, this); 28 | (0, _initializerDefineProperty2["default"])(this, "content", _descriptor3, this); 29 | (0, _defineProperty2["default"])(this, "authorId", void 0); 30 | (0, _initializerDefineProperty2["default"])(this, "createdAt", _descriptor4, this); 31 | (0, _initializerDefineProperty2["default"])(this, "updateAt", _descriptor5, this); 32 | (0, _initializerDefineProperty2["default"])(this, "author", _descriptor6, this); 33 | (0, _initializerDefineProperty2["default"])(this, "comments", _descriptor7, this); 34 | }, _temp), (_descriptor = (0, _applyDecoratedDescriptor2["default"])(_class2.prototype, "id", [_dec2], { 35 | configurable: true, 36 | enumerable: true, 37 | writable: true, 38 | initializer: null 39 | }), _descriptor2 = (0, _applyDecoratedDescriptor2["default"])(_class2.prototype, "title", [_dec3], { 40 | configurable: true, 41 | enumerable: true, 42 | writable: true, 43 | initializer: null 44 | }), _descriptor3 = (0, _applyDecoratedDescriptor2["default"])(_class2.prototype, "content", [_dec4], { 45 | configurable: true, 46 | enumerable: true, 47 | writable: true, 48 | initializer: null 49 | }), _descriptor4 = (0, _applyDecoratedDescriptor2["default"])(_class2.prototype, "createdAt", [_dec5], { 50 | configurable: true, 51 | enumerable: true, 52 | writable: true, 53 | initializer: null 54 | }), _descriptor5 = (0, _applyDecoratedDescriptor2["default"])(_class2.prototype, "updateAt", [_dec6], { 55 | configurable: true, 56 | enumerable: true, 57 | writable: true, 58 | initializer: null 59 | }), _descriptor6 = (0, _applyDecoratedDescriptor2["default"])(_class2.prototype, "author", [_dec7], { 60 | configurable: true, 61 | enumerable: true, 62 | writable: true, 63 | initializer: null 64 | }), _descriptor7 = (0, _applyDecoratedDescriptor2["default"])(_class2.prototype, "comments", [_dec8], { 65 | configurable: true, 66 | enumerable: true, 67 | writable: true, 68 | initializer: null 69 | })), _class2)) || _class); 70 | exports.Post = Post; -------------------------------------------------------------------------------- /dist/entity/User.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); 4 | 5 | Object.defineProperty(exports, "__esModule", { 6 | value: true 7 | }); 8 | exports.User = void 0; 9 | 10 | var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); 11 | 12 | var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); 13 | 14 | var _initializerDefineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/initializerDefineProperty")); 15 | 16 | var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); 17 | 18 | var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); 19 | 20 | var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); 21 | 22 | var _applyDecoratedDescriptor2 = _interopRequireDefault(require("@babel/runtime/helpers/applyDecoratedDescriptor")); 23 | 24 | var _initializerWarningHelper2 = _interopRequireDefault(require("@babel/runtime/helpers/initializerWarningHelper")); 25 | 26 | var _typeorm = require("typeorm"); 27 | 28 | var _getDatabaseConnection = require("../../lib/getDatabaseConnection"); 29 | 30 | var _md = _interopRequireDefault(require("md5")); 31 | 32 | var _lodash = _interopRequireDefault(require("lodash")); 33 | 34 | var _dec, _dec2, _dec3, _dec4, _dec5, _dec6, _dec7, _dec8, _dec9, _class, _class2, _descriptor, _descriptor2, _descriptor3, _descriptor4, _descriptor5, _descriptor6, _descriptor7, _temp; 35 | 36 | var User = (_dec = (0, _typeorm.Entity)('users'), _dec2 = (0, _typeorm.PrimaryGeneratedColumn)('increment'), _dec3 = (0, _typeorm.Column)('varchar'), _dec4 = (0, _typeorm.Column)('varchar'), _dec5 = (0, _typeorm.CreateDateColumn)(), _dec6 = (0, _typeorm.UpdateDateColumn)(), _dec7 = (0, _typeorm.OneToMany)('Post', 'author'), _dec8 = (0, _typeorm.OneToMany)('Comment', 'user'), _dec9 = (0, _typeorm.BeforeInsert)(), _dec(_class = (_class2 = (_temp = /*#__PURE__*/function () { 37 | function User() { 38 | (0, _classCallCheck2["default"])(this, User); 39 | (0, _initializerDefineProperty2["default"])(this, "id", _descriptor, this); 40 | (0, _initializerDefineProperty2["default"])(this, "username", _descriptor2, this); 41 | (0, _initializerDefineProperty2["default"])(this, "passwordDigest", _descriptor3, this); 42 | (0, _initializerDefineProperty2["default"])(this, "createdAt", _descriptor4, this); 43 | (0, _initializerDefineProperty2["default"])(this, "updateAt", _descriptor5, this); 44 | (0, _initializerDefineProperty2["default"])(this, "posts", _descriptor6, this); 45 | (0, _initializerDefineProperty2["default"])(this, "comments", _descriptor7, this); 46 | (0, _defineProperty2["default"])(this, "errors", { 47 | username: [], 48 | password: [], 49 | passwordConfirmation: [] 50 | }); 51 | (0, _defineProperty2["default"])(this, "password", void 0); 52 | (0, _defineProperty2["default"])(this, "passwordConfirmation", void 0); 53 | } 54 | 55 | (0, _createClass2["default"])(User, [{ 56 | key: "validate", 57 | value: function () { 58 | var _validate = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee() { 59 | var found; 60 | return _regenerator["default"].wrap(function _callee$(_context) { 61 | while (1) { 62 | switch (_context.prev = _context.next) { 63 | case 0: 64 | if (this.username.trim() === '') { 65 | this.errors.username.push('不能为空'); 66 | } 67 | 68 | if (!/[a-zA-Z0-9]/.test(this.username.trim())) { 69 | this.errors.username.push('格式不合法'); 70 | } 71 | 72 | if (this.username.trim().length > 42) { 73 | this.errors.username.push('太长'); 74 | } 75 | 76 | if (this.username.trim().length <= 3) { 77 | this.errors.username.push('太短'); 78 | } 79 | 80 | _context.next = 6; 81 | return (0, _getDatabaseConnection.getDatabaseConnection)(); 82 | 83 | case 6: 84 | _context.next = 8; 85 | return _context.sent.manager.find(User, { 86 | username: this.username 87 | }); 88 | 89 | case 8: 90 | found = _context.sent; 91 | 92 | if (found.length > 0) { 93 | this.errors.username.push('已存在,不能重复注册'); 94 | } 95 | 96 | if (this.password === '') { 97 | this.errors.password.push('不能为空'); 98 | } 99 | 100 | if (this.password !== this.passwordConfirmation) { 101 | this.errors.passwordConfirmation.push('密码不匹配'); 102 | } 103 | 104 | case 12: 105 | case "end": 106 | return _context.stop(); 107 | } 108 | } 109 | }, _callee, this); 110 | })); 111 | 112 | function validate() { 113 | return _validate.apply(this, arguments); 114 | } 115 | 116 | return validate; 117 | }() 118 | }, { 119 | key: "hasErrors", 120 | value: function hasErrors() { 121 | return !!Object.values(this.errors).find(function (v) { 122 | return v.length > 0; 123 | }); 124 | } 125 | }, { 126 | key: "generatePasswordDigest", 127 | value: function generatePasswordDigest() { 128 | this.passwordDigest = (0, _md["default"])(this.password); 129 | } 130 | }, { 131 | key: "toJSON", 132 | value: function toJSON() { 133 | return _lodash["default"].omit(this, ['password', 'passwordConfirmation', 'passwordDigest', 'errors']); 134 | } 135 | }]); 136 | return User; 137 | }(), _temp), (_descriptor = (0, _applyDecoratedDescriptor2["default"])(_class2.prototype, "id", [_dec2], { 138 | configurable: true, 139 | enumerable: true, 140 | writable: true, 141 | initializer: null 142 | }), _descriptor2 = (0, _applyDecoratedDescriptor2["default"])(_class2.prototype, "username", [_dec3], { 143 | configurable: true, 144 | enumerable: true, 145 | writable: true, 146 | initializer: null 147 | }), _descriptor3 = (0, _applyDecoratedDescriptor2["default"])(_class2.prototype, "passwordDigest", [_dec4], { 148 | configurable: true, 149 | enumerable: true, 150 | writable: true, 151 | initializer: null 152 | }), _descriptor4 = (0, _applyDecoratedDescriptor2["default"])(_class2.prototype, "createdAt", [_dec5], { 153 | configurable: true, 154 | enumerable: true, 155 | writable: true, 156 | initializer: null 157 | }), _descriptor5 = (0, _applyDecoratedDescriptor2["default"])(_class2.prototype, "updateAt", [_dec6], { 158 | configurable: true, 159 | enumerable: true, 160 | writable: true, 161 | initializer: null 162 | }), _descriptor6 = (0, _applyDecoratedDescriptor2["default"])(_class2.prototype, "posts", [_dec7], { 163 | configurable: true, 164 | enumerable: true, 165 | writable: true, 166 | initializer: null 167 | }), _descriptor7 = (0, _applyDecoratedDescriptor2["default"])(_class2.prototype, "comments", [_dec8], { 168 | configurable: true, 169 | enumerable: true, 170 | writable: true, 171 | initializer: null 172 | }), (0, _applyDecoratedDescriptor2["default"])(_class2.prototype, "generatePasswordDigest", [_dec9], Object.getOwnPropertyDescriptor(_class2.prototype, "generatePasswordDigest"), _class2.prototype)), _class2)) || _class); 173 | exports.User = User; -------------------------------------------------------------------------------- /dist/migration/1592201997493-CreateUsers.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); 4 | 5 | Object.defineProperty(exports, "__esModule", { 6 | value: true 7 | }); 8 | exports.CreateUsers1592201997493 = void 0; 9 | 10 | var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); 11 | 12 | var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); 13 | 14 | var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); 15 | 16 | var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); 17 | 18 | var _typeorm = require("typeorm"); 19 | 20 | var CreateUsers1592201997493 = /*#__PURE__*/function () { 21 | function CreateUsers1592201997493() { 22 | (0, _classCallCheck2["default"])(this, CreateUsers1592201997493); 23 | } 24 | 25 | (0, _createClass2["default"])(CreateUsers1592201997493, [{ 26 | key: "up", 27 | value: function () { 28 | var _up = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(queryRunner) { 29 | return _regenerator["default"].wrap(function _callee$(_context) { 30 | while (1) { 31 | switch (_context.prev = _context.next) { 32 | case 0: 33 | _context.next = 2; 34 | return queryRunner.createTable(new _typeorm.Table({ 35 | name: 'users', 36 | columns: [{ 37 | name: 'id', 38 | isGenerated: true, 39 | type: 'int', 40 | generationStrategy: 'increment', 41 | isPrimary: true 42 | }, { 43 | name: 'username', 44 | type: 'varchar' 45 | }, { 46 | name: 'passwordDigest', 47 | type: 'varchar' 48 | }] 49 | })); 50 | 51 | case 2: 52 | return _context.abrupt("return", _context.sent); 53 | 54 | case 3: 55 | case "end": 56 | return _context.stop(); 57 | } 58 | } 59 | }, _callee); 60 | })); 61 | 62 | function up(_x) { 63 | return _up.apply(this, arguments); 64 | } 65 | 66 | return up; 67 | }() 68 | }, { 69 | key: "down", 70 | value: function () { 71 | var _down = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2(queryRunner) { 72 | return _regenerator["default"].wrap(function _callee2$(_context2) { 73 | while (1) { 74 | switch (_context2.prev = _context2.next) { 75 | case 0: 76 | _context2.next = 2; 77 | return queryRunner.dropTable('users'); 78 | 79 | case 2: 80 | return _context2.abrupt("return", _context2.sent); 81 | 82 | case 3: 83 | case "end": 84 | return _context2.stop(); 85 | } 86 | } 87 | }, _callee2); 88 | })); 89 | 90 | function down(_x2) { 91 | return _down.apply(this, arguments); 92 | } 93 | 94 | return down; 95 | }() 96 | }]); 97 | return CreateUsers1592201997493; 98 | }(); 99 | 100 | exports.CreateUsers1592201997493 = CreateUsers1592201997493; -------------------------------------------------------------------------------- /dist/migration/1592205680555-CreatePosts.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); 4 | 5 | Object.defineProperty(exports, "__esModule", { 6 | value: true 7 | }); 8 | exports.CreatePosts1592205680555 = void 0; 9 | 10 | var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); 11 | 12 | var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); 13 | 14 | var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); 15 | 16 | var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); 17 | 18 | var _typeorm = require("typeorm"); 19 | 20 | var CreatePosts1592205680555 = /*#__PURE__*/function () { 21 | function CreatePosts1592205680555() { 22 | (0, _classCallCheck2["default"])(this, CreatePosts1592205680555); 23 | } 24 | 25 | (0, _createClass2["default"])(CreatePosts1592205680555, [{ 26 | key: "up", 27 | value: function () { 28 | var _up = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(queryRunner) { 29 | return _regenerator["default"].wrap(function _callee$(_context) { 30 | while (1) { 31 | switch (_context.prev = _context.next) { 32 | case 0: 33 | _context.next = 2; 34 | return queryRunner.createTable(new _typeorm.Table({ 35 | name: 'posts', 36 | columns: [{ 37 | name: 'id', 38 | isGenerated: true, 39 | type: 'int', 40 | generationStrategy: 'increment', 41 | isPrimary: true 42 | }, { 43 | name: 'title', 44 | type: 'varchar' 45 | }, { 46 | name: 'content', 47 | type: 'text' 48 | }, { 49 | name: 'author_id', 50 | type: 'int' 51 | }] 52 | })); 53 | 54 | case 2: 55 | return _context.abrupt("return", _context.sent); 56 | 57 | case 3: 58 | case "end": 59 | return _context.stop(); 60 | } 61 | } 62 | }, _callee); 63 | })); 64 | 65 | function up(_x) { 66 | return _up.apply(this, arguments); 67 | } 68 | 69 | return up; 70 | }() 71 | }, { 72 | key: "down", 73 | value: function () { 74 | var _down = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2(queryRunner) { 75 | return _regenerator["default"].wrap(function _callee2$(_context2) { 76 | while (1) { 77 | switch (_context2.prev = _context2.next) { 78 | case 0: 79 | _context2.next = 2; 80 | return queryRunner.dropTable('posts'); 81 | 82 | case 2: 83 | return _context2.abrupt("return", _context2.sent); 84 | 85 | case 3: 86 | case "end": 87 | return _context2.stop(); 88 | } 89 | } 90 | }, _callee2); 91 | })); 92 | 93 | function down(_x2) { 94 | return _down.apply(this, arguments); 95 | } 96 | 97 | return down; 98 | }() 99 | }]); 100 | return CreatePosts1592205680555; 101 | }(); 102 | 103 | exports.CreatePosts1592205680555 = CreatePosts1592205680555; -------------------------------------------------------------------------------- /dist/migration/1592206097026-CreateComments.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); 4 | 5 | Object.defineProperty(exports, "__esModule", { 6 | value: true 7 | }); 8 | exports.CreateComments1592206097026 = void 0; 9 | 10 | var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); 11 | 12 | var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); 13 | 14 | var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); 15 | 16 | var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); 17 | 18 | var _typeorm = require("typeorm"); 19 | 20 | var CreateComments1592206097026 = /*#__PURE__*/function () { 21 | function CreateComments1592206097026() { 22 | (0, _classCallCheck2["default"])(this, CreateComments1592206097026); 23 | } 24 | 25 | (0, _createClass2["default"])(CreateComments1592206097026, [{ 26 | key: "up", 27 | value: function () { 28 | var _up = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(queryRunner) { 29 | return _regenerator["default"].wrap(function _callee$(_context) { 30 | while (1) { 31 | switch (_context.prev = _context.next) { 32 | case 0: 33 | _context.next = 2; 34 | return queryRunner.createTable(new _typeorm.Table({ 35 | name: 'comments', 36 | columns: [{ 37 | name: 'id', 38 | isGenerated: true, 39 | type: 'int', 40 | generationStrategy: 'increment', 41 | isPrimary: true 42 | }, { 43 | name: 'user_id', 44 | type: 'int' 45 | }, { 46 | name: 'post_id', 47 | type: 'int' 48 | }, { 49 | name: 'content', 50 | type: 'text' 51 | }] 52 | })); 53 | 54 | case 2: 55 | return _context.abrupt("return", _context.sent); 56 | 57 | case 3: 58 | case "end": 59 | return _context.stop(); 60 | } 61 | } 62 | }, _callee); 63 | })); 64 | 65 | function up(_x) { 66 | return _up.apply(this, arguments); 67 | } 68 | 69 | return up; 70 | }() 71 | }, { 72 | key: "down", 73 | value: function () { 74 | var _down = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2(queryRunner) { 75 | return _regenerator["default"].wrap(function _callee2$(_context2) { 76 | while (1) { 77 | switch (_context2.prev = _context2.next) { 78 | case 0: 79 | _context2.next = 2; 80 | return queryRunner.dropTable('comments'); 81 | 82 | case 2: 83 | return _context2.abrupt("return", _context2.sent); 84 | 85 | case 3: 86 | case "end": 87 | return _context2.stop(); 88 | } 89 | } 90 | }, _callee2); 91 | })); 92 | 93 | function down(_x2) { 94 | return _down.apply(this, arguments); 95 | } 96 | 97 | return down; 98 | }() 99 | }]); 100 | return CreateComments1592206097026; 101 | }(); 102 | 103 | exports.CreateComments1592206097026 = CreateComments1592206097026; -------------------------------------------------------------------------------- /dist/migration/1592206406201-AddCreatedAtAndUpdateAt.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); 4 | 5 | Object.defineProperty(exports, "__esModule", { 6 | value: true 7 | }); 8 | exports.AddCreatedAtAndUpdateAt1592206406201 = void 0; 9 | 10 | var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); 11 | 12 | var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); 13 | 14 | var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); 15 | 16 | var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); 17 | 18 | var _typeorm = require("typeorm"); 19 | 20 | var AddCreatedAtAndUpdateAt1592206406201 = /*#__PURE__*/function () { 21 | function AddCreatedAtAndUpdateAt1592206406201() { 22 | (0, _classCallCheck2["default"])(this, AddCreatedAtAndUpdateAt1592206406201); 23 | } 24 | 25 | (0, _createClass2["default"])(AddCreatedAtAndUpdateAt1592206406201, [{ 26 | key: "up", 27 | value: function () { 28 | var _up = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(queryRunner) { 29 | return _regenerator["default"].wrap(function _callee$(_context) { 30 | while (1) { 31 | switch (_context.prev = _context.next) { 32 | case 0: 33 | _context.next = 2; 34 | return queryRunner.addColumns('users', [new _typeorm.TableColumn({ 35 | name: 'createdAt', 36 | type: 'time', 37 | isNullable: false, 38 | "default": 'now()' 39 | }), new _typeorm.TableColumn({ 40 | name: 'updateAt', 41 | type: 'time', 42 | isNullable: false, 43 | "default": 'now()' 44 | })]); 45 | 46 | case 2: 47 | _context.next = 4; 48 | return queryRunner.addColumns('posts', [new _typeorm.TableColumn({ 49 | name: 'createdAt', 50 | type: 'time', 51 | isNullable: false, 52 | "default": 'now()' 53 | }), new _typeorm.TableColumn({ 54 | name: 'updateAt', 55 | type: 'time', 56 | isNullable: false, 57 | "default": 'now()' 58 | })]); 59 | 60 | case 4: 61 | _context.next = 6; 62 | return queryRunner.addColumns('comments', [new _typeorm.TableColumn({ 63 | name: 'createdAt', 64 | type: 'time', 65 | isNullable: false, 66 | "default": 'now()' 67 | }), new _typeorm.TableColumn({ 68 | name: 'updateAt', 69 | type: 'time', 70 | isNullable: false, 71 | "default": 'now()' 72 | })]); 73 | 74 | case 6: 75 | case "end": 76 | return _context.stop(); 77 | } 78 | } 79 | }, _callee); 80 | })); 81 | 82 | function up(_x) { 83 | return _up.apply(this, arguments); 84 | } 85 | 86 | return up; 87 | }() 88 | }, { 89 | key: "down", 90 | value: function () { 91 | var _down = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2(queryRunner) { 92 | return _regenerator["default"].wrap(function _callee2$(_context2) { 93 | while (1) { 94 | switch (_context2.prev = _context2.next) { 95 | case 0: 96 | _context2.next = 2; 97 | return queryRunner.dropColumn('users', 'createdAt'); 98 | 99 | case 2: 100 | _context2.next = 4; 101 | return queryRunner.dropColumn('users', 'updateAt'); 102 | 103 | case 4: 104 | _context2.next = 6; 105 | return queryRunner.dropColumn('posts', 'createdAt'); 106 | 107 | case 6: 108 | _context2.next = 8; 109 | return queryRunner.dropColumn('posts', 'updateAt'); 110 | 111 | case 8: 112 | _context2.next = 10; 113 | return queryRunner.dropColumn('comments', 'createdAt'); 114 | 115 | case 10: 116 | _context2.next = 12; 117 | return queryRunner.dropColumn('comments', 'updateAt'); 118 | 119 | case 12: 120 | case "end": 121 | return _context2.stop(); 122 | } 123 | } 124 | }, _callee2); 125 | })); 126 | 127 | function down(_x2) { 128 | return _down.apply(this, arguments); 129 | } 130 | 131 | return down; 132 | }() 133 | }]); 134 | return AddCreatedAtAndUpdateAt1592206406201; 135 | }(); 136 | 137 | exports.AddCreatedAtAndUpdateAt1592206406201 = AddCreatedAtAndUpdateAt1592206406201; -------------------------------------------------------------------------------- /dist/migration/1592208800876-RenameColumns.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); 4 | 5 | Object.defineProperty(exports, "__esModule", { 6 | value: true 7 | }); 8 | exports.RenameColumns1592208800876 = void 0; 9 | 10 | var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); 11 | 12 | var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); 13 | 14 | var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); 15 | 16 | var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); 17 | 18 | var RenameColumns1592208800876 = /*#__PURE__*/function () { 19 | function RenameColumns1592208800876() { 20 | (0, _classCallCheck2["default"])(this, RenameColumns1592208800876); 21 | } 22 | 23 | (0, _createClass2["default"])(RenameColumns1592208800876, [{ 24 | key: "up", 25 | value: function () { 26 | var _up = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(queryRunner) { 27 | return _regenerator["default"].wrap(function _callee$(_context) { 28 | while (1) { 29 | switch (_context.prev = _context.next) { 30 | case 0: 31 | _context.next = 2; 32 | return queryRunner.renameColumn('posts', 'author_id', 'authorId'); 33 | 34 | case 2: 35 | _context.next = 4; 36 | return queryRunner.renameColumn('comments', 'user_id', 'userId'); 37 | 38 | case 4: 39 | _context.next = 6; 40 | return queryRunner.renameColumn('comments', 'post_id', 'postId'); 41 | 42 | case 6: 43 | case "end": 44 | return _context.stop(); 45 | } 46 | } 47 | }, _callee); 48 | })); 49 | 50 | function up(_x) { 51 | return _up.apply(this, arguments); 52 | } 53 | 54 | return up; 55 | }() 56 | }, { 57 | key: "down", 58 | value: function () { 59 | var _down = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2(queryRunner) { 60 | return _regenerator["default"].wrap(function _callee2$(_context2) { 61 | while (1) { 62 | switch (_context2.prev = _context2.next) { 63 | case 0: 64 | _context2.next = 2; 65 | return queryRunner.renameColumn('posts', 'authorId', 'author_id'); 66 | 67 | case 2: 68 | _context2.next = 4; 69 | return queryRunner.renameColumn('comments', 'userId', 'user_id'); 70 | 71 | case 4: 72 | _context2.next = 6; 73 | return queryRunner.renameColumn('comments', 'postId', 'post_id'); 74 | 75 | case 6: 76 | case "end": 77 | return _context2.stop(); 78 | } 79 | } 80 | }, _callee2); 81 | })); 82 | 83 | function down(_x2) { 84 | return _down.apply(this, arguments); 85 | } 86 | 87 | return down; 88 | }() 89 | }]); 90 | return RenameColumns1592208800876; 91 | }(); 92 | 93 | exports.RenameColumns1592208800876 = RenameColumns1592208800876; -------------------------------------------------------------------------------- /dist/migration/1592561070934-AddUniqueUsernameToUsers.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); 4 | 5 | Object.defineProperty(exports, "__esModule", { 6 | value: true 7 | }); 8 | exports.AddUniqueUsernameToUsers1592561070934 = void 0; 9 | 10 | var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); 11 | 12 | var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); 13 | 14 | var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); 15 | 16 | var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); 17 | 18 | var _typeorm = require("typeorm"); 19 | 20 | var AddUniqueUsernameToUsers1592561070934 = /*#__PURE__*/function () { 21 | function AddUniqueUsernameToUsers1592561070934() { 22 | (0, _classCallCheck2["default"])(this, AddUniqueUsernameToUsers1592561070934); 23 | } 24 | 25 | (0, _createClass2["default"])(AddUniqueUsernameToUsers1592561070934, [{ 26 | key: "up", 27 | value: function () { 28 | var _up = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(queryRunner) { 29 | return _regenerator["default"].wrap(function _callee$(_context) { 30 | while (1) { 31 | switch (_context.prev = _context.next) { 32 | case 0: 33 | _context.next = 2; 34 | return queryRunner.createIndex('users', new _typeorm.TableIndex({ 35 | name: 'users_username', 36 | columnNames: ['username'], 37 | isUnique: true 38 | })); 39 | 40 | case 2: 41 | case "end": 42 | return _context.stop(); 43 | } 44 | } 45 | }, _callee); 46 | })); 47 | 48 | function up(_x) { 49 | return _up.apply(this, arguments); 50 | } 51 | 52 | return up; 53 | }() 54 | }, { 55 | key: "down", 56 | value: function () { 57 | var _down = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee2(queryRunner) { 58 | return _regenerator["default"].wrap(function _callee2$(_context2) { 59 | while (1) { 60 | switch (_context2.prev = _context2.next) { 61 | case 0: 62 | _context2.next = 2; 63 | return queryRunner.dropIndex('users', 'users_username'); 64 | 65 | case 2: 66 | case "end": 67 | return _context2.stop(); 68 | } 69 | } 70 | }, _callee2); 71 | })); 72 | 73 | function down(_x2) { 74 | return _down.apply(this, arguments); 75 | } 76 | 77 | return down; 78 | }() 79 | }]); 80 | return AddUniqueUsernameToUsers1592561070934; 81 | }(); 82 | 83 | exports.AddUniqueUsernameToUsers1592561070934 = AddUniqueUsernameToUsers1592561070934; -------------------------------------------------------------------------------- /dist/model/SignIn.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); 4 | 5 | Object.defineProperty(exports, "__esModule", { 6 | value: true 7 | }); 8 | exports.SignIn = void 0; 9 | 10 | var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); 11 | 12 | var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); 13 | 14 | var _classCallCheck2 = _interopRequireDefault(require("@babel/runtime/helpers/classCallCheck")); 15 | 16 | var _createClass2 = _interopRequireDefault(require("@babel/runtime/helpers/createClass")); 17 | 18 | var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty")); 19 | 20 | var _getDatabaseConnection = require("../../lib/getDatabaseConnection"); 21 | 22 | var _User = require("../entity/User"); 23 | 24 | var _md = _interopRequireDefault(require("md5")); 25 | 26 | var SignIn = /*#__PURE__*/function () { 27 | function SignIn() { 28 | (0, _classCallCheck2["default"])(this, SignIn); 29 | (0, _defineProperty2["default"])(this, "username", void 0); 30 | (0, _defineProperty2["default"])(this, "password", void 0); 31 | (0, _defineProperty2["default"])(this, "user", void 0); 32 | (0, _defineProperty2["default"])(this, "errors", { 33 | username: [], 34 | password: [] 35 | }); 36 | } 37 | 38 | (0, _createClass2["default"])(SignIn, [{ 39 | key: "validate", 40 | value: function () { 41 | var _validate = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee() { 42 | var connection, user; 43 | return _regenerator["default"].wrap(function _callee$(_context) { 44 | while (1) { 45 | switch (_context.prev = _context.next) { 46 | case 0: 47 | if (this.username.trim() === '') { 48 | this.errors.username.push('请填写用户名'); 49 | } 50 | 51 | _context.next = 3; 52 | return (0, _getDatabaseConnection.getDatabaseConnection)(); 53 | 54 | case 3: 55 | connection = _context.sent; 56 | _context.next = 6; 57 | return connection.manager.findOne(_User.User, { 58 | where: { 59 | username: this.username 60 | } 61 | }); 62 | 63 | case 6: 64 | user = _context.sent; 65 | this.user = user; 66 | 67 | if (user) { 68 | if (user.passwordDigest === (0, _md["default"])(this.password)) { 69 | this.errors.password.push('密码与用户名不匹配'); 70 | } 71 | } else { 72 | this.errors.username.push('用户名不存在'); 73 | } 74 | 75 | case 9: 76 | case "end": 77 | return _context.stop(); 78 | } 79 | } 80 | }, _callee, this); 81 | })); 82 | 83 | function validate() { 84 | return _validate.apply(this, arguments); 85 | } 86 | 87 | return validate; 88 | }() 89 | }, { 90 | key: "hasErrors", 91 | value: function hasErrors() { 92 | return !!Object.values(this.errors).find(function (v) { 93 | return v.length > 0; 94 | }); 95 | } 96 | }]); 97 | return SignIn; 98 | }(); 99 | 100 | exports.SignIn = SignIn; -------------------------------------------------------------------------------- /dist/seed.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | 3 | var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); 4 | 5 | var _regenerator = _interopRequireDefault(require("@babel/runtime/regenerator")); 6 | 7 | var _asyncToGenerator2 = _interopRequireDefault(require("@babel/runtime/helpers/asyncToGenerator")); 8 | 9 | require("reflect-metadata"); 10 | 11 | var _typeorm = require("typeorm"); 12 | 13 | var _User = require("./entity/User"); 14 | 15 | var _Post = require("./entity/Post"); 16 | 17 | var _Comment = require("./entity/Comment"); 18 | 19 | (0, _typeorm.createConnection)().then( /*#__PURE__*/function () { 20 | var _ref = (0, _asyncToGenerator2["default"])( /*#__PURE__*/_regenerator["default"].mark(function _callee(connection) { 21 | var manager, u1, p1, c1; 22 | return _regenerator["default"].wrap(function _callee$(_context) { 23 | while (1) { 24 | switch (_context.prev = _context.next) { 25 | case 0: 26 | manager = connection.manager; // 创建 user1 27 | 28 | u1 = new _User.User(); 29 | u1.username = 'frank'; 30 | u1.passwordDigest = 'xxx'; 31 | _context.next = 6; 32 | return manager.save(u1); 33 | 34 | case 6: 35 | // // 创建 post 1 36 | p1 = new _Post.Post(); 37 | p1.title = 'Post 1'; 38 | p1.content = 'My First Post'; 39 | p1.author = u1; 40 | _context.next = 12; 41 | return manager.save(p1); 42 | 43 | case 12: 44 | c1 = new _Comment.Comment(); 45 | c1.user = u1; 46 | c1.post = p1; 47 | c1.content = 'Awesome!'; 48 | _context.next = 18; 49 | return manager.save(c1); 50 | 51 | case 18: 52 | _context.next = 20; 53 | return connection.close(); 54 | 55 | case 20: 56 | console.log('OK!'); 57 | 58 | case 21: 59 | case "end": 60 | return _context.stop(); 61 | } 62 | } 63 | }, _callee); 64 | })); 65 | 66 | return function (_x) { 67 | return _ref.apply(this, arguments); 68 | }; 69 | }())["catch"](function (error) { 70 | return console.log(error); 71 | }); -------------------------------------------------------------------------------- /hooks/useForm.tsx: -------------------------------------------------------------------------------- 1 | // 表示 useForm 里有一个类型,这个类型也是 initFormData 的类型 2 | // 因为不知道 T 是什么, 3 | import {ReactChild, useCallback, useState} from 'react'; 4 | import * as React from 'react'; 5 | import {AxiosResponse} from 'axios'; 6 | import cs from 'classnames'; 7 | 8 | type Field = { 9 | label: string, 10 | type: 'text' | 'password' | 'textarea', 11 | key: keyof T, 12 | className?: string 13 | }; 14 | 15 | type useFormOptions = { 16 | initFormData: T; 17 | fields: Field[]; 18 | buttons: ReactChild; 19 | submit: { 20 | request: (formData: T) => Promise>; 21 | success: () => void; 22 | } 23 | } 24 | 25 | export function useForm(options: useFormOptions) { 26 | // 非受控 27 | const {initFormData, fields, buttons, submit} = options; 28 | const [formData, setFormData] = useState(initFormData); 29 | const [errors, setErrors] = useState(() => { 30 | const e: { [k in keyof T]?: string[] } = {}; 31 | (Object.keys(initFormData) as Array) 32 | .map((key) => {e[key] = [];}); 33 | return e; 34 | }); 35 | 36 | const onChange = useCallback((key: keyof T, value: any) => { 37 | setFormData({...formData, [key]: value}); 38 | }, [formData]); 39 | 40 | const _onSubmit = useCallback((e) => { 41 | e.preventDefault(); 42 | submit.request(formData).then(() => { 43 | submit.success(); 44 | }, (error) => { 45 | if (error.response) { 46 | const response: AxiosResponse = error.response; 47 | if (response.status === 422) { 48 | setErrors(response.data); 49 | } else if (response.status === 401) { 50 | window.alert('请先登录'); 51 | window.location.href = `/sign_in?returnTo=${encodeURIComponent(window.location.pathname)}`; 52 | } 53 | } 54 | }); 55 | }, [submit, formData]); 56 | 57 | const form = ( 58 |
59 | {fields.map(field => 60 |
61 |