Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ run
test/fixtures/apps/model-app/run/
test/fixtures/apps/ts/**/*.js
test/fixtures/apps/connection-uri/**/*.js
test/fixtures/apps/typescript/**/*.js
package-lock.json
87 changes: 86 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,25 @@ exports.sequelize = {
};
```

- In case your project is typescript and you are going to use `sequelize-typescript` instead of `sequelize`, then edit your own configurations in `conif/config.{env}.ts`


```typescript
exports.sequelize = {
Sequelize: require('sequelize-typescript'),
dialect: 'mysql', // support: mysql, mariadb, postgres, mssql
database: 'test',
host: 'localhost',
port: 3306,
username: 'root',
password: '',
// delegate: 'myModel', // load all models to `app[delegate]` and `ctx[delegate]`, default to `model`
// baseDir: 'my_model', // load all files in `app/${baseDir}` as models, default to `model`
// exclude: 'index.js', // ignore `app/${baseDir}/index.js` when load models, support glob and array
// more sequelize options
};
```

You can also use the `connection uri` to configure the connection:

```js
Expand Down Expand Up @@ -126,6 +145,7 @@ Define a model first.

> NOTE: `options.delegate` default to `model`, so `app.model` is an [Instance of Sequelize](http://docs.sequelizejs.com/class/lib/sequelize.js~Sequelize.html#instance-constructor-constructor), so you can use methods like: `app.model.sync, app.model.query ...`

- Define model in plain js fashion:
```js
// app/model/user.js

Expand Down Expand Up @@ -160,6 +180,61 @@ module.exports = app => {

```

- Define model in typescript fashion:
> Before you go this way, make sure your `tsconfig.json` contains the following:

```json
{
"compilerOptions": {
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"strictPropertyInitialization": false
}
}
```

```typescript
// app/model/user.ts

import {Column, Model, Table, DataType} from 'sequelize-typescript'

@Table({
tableName: 'user',
})
class User extends Model<User> {
@Column(DataType.STRING)
login: string

@Column(DataType.STRING(30))
name: string

@Column(DataType.STRING(32))
password: string

@Column(DataType.INTEGER)
age: number

@Column(DataType.DATE)
last_sign_in_at: Date

@Column(DataType.DATE)
created_at: Date

@Column(DataType.DATE)
updated_at: Date

static async findByLogin(login: string) {
return await this.findOne({where:{login}})
}

async logSignin() {
return await this.update({ last_sign_in_at: new Date() });
}
}

export default () => User
```

Now you can use it in your controller:

```js
Expand Down Expand Up @@ -301,7 +376,6 @@ module.exports = app => {
};
```


```js
// app/controller/post.js
class PostController extends Controller {
Expand Down Expand Up @@ -360,6 +434,17 @@ Using [sequelize-cli](https://github.com/sequelize/cli) to help manage your data

Please open an issue [here](https://github.com/eggjs/egg/issues).

## Contribution

### Run test locally
Testing needs connecting to databases, on TravisCI this is addressed by claiming `mysql` services. To run test locally, `docker` is recommended installed first, then

```shell script
sh test.sh
```

which will start a `mysql` container and create relevant databases.

## License

[MIT](LICENSE)
Expand Down
9 changes: 8 additions & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,16 @@ interface EggSequelizeOptions extends sequelize.Options {
/**
* A full database URI
* @example
* `connectionUri:"mysql://localhost:3306/database"`
* `connectionUri: "mysql://localhost:3306/database"`
*/
connectionUri?: string;

/**
* support customizing sequelize class, default to `require('sequelize')`
* @example
* `Sequelize: require('sequelize-typescript').Sequelize`
*/
Sequelize?: typeof sequelize.Sequelize;
}

interface DataSources {
Expand Down
2 changes: 1 addition & 1 deletion lib/loader.js
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ module.exports = app => {
caseStyle: 'upper',
ignore: config.exclude,
filter(model) {
if (!model || !model.sequelize) return false;
if (!model || (!model.sequelize && !model.findAll)) return false;
models.push(model);
return true;
},
Expand Down
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"dependencies": {
"@types/sequelize": "^4.27.24",
"mz-modules": "^2.1.0",
"sequelize-typescript": "^1.0.0",
"sequelize": "^6.0.0"
},
"devDependencies": {
Expand All @@ -24,7 +25,8 @@
"egg-mock": "^3.19.3",
"eslint": "^5.3.0",
"eslint-config-egg": "^7.0.0",
"mysql2": "^1.6.1"
"mysql2": "^1.6.1",
"reflect-metadata": "^0.1.13"
},
"engines": {
"node": ">=10.0.0"
Expand Down
28 changes: 28 additions & 0 deletions test.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#!/usr/bin/env bash

container_name='local-mysql'

if [ "$(docker inspect -f '{{.State.Running}}' $container_name)" = "true" ]; then
echo "$container_name is already running."
else
docker kill $container_name || echo "$container_name is already killed"
docker rm $container_name || echo "$container_name not exist"
docker run --name $container_name -e MYSQL_ALLOW_EMPTY_PASSWORD=1 -d -p 3306:3306 mysql:5.7

sleep 10
fi

# shellcheck disable=SC2016
mysql -h 127.0.0.1 -u root -e 'CREATE DATABASE IF NOT EXISTS `test`;'
mysql -h 127.0.0.1 -u root -e 'CREATE DATABASE IF NOT EXISTS `test1`;'
mysql -h 127.0.0.1 -u root -e 'CREATE DATABASE IF NOT EXISTS `test2`;'
mysql -h 127.0.0.1 -u root -e 'CREATE DATABASE IF NOT EXISTS `test3`;'
mysql -h 127.0.0.1 -u root -e 'CREATE DATABASE IF NOT EXISTS `test4`;'
# shellcheck disable=SC2016
echo 'databases is there'

npm run test-local

#!/usr/bin/env bash

#docker kill local-mysql || echo "local-mysql is already killed"
10 changes: 10 additions & 0 deletions test/fixtures/apps/typescript/app/controller/home.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { Controller } from 'egg';

export default class HomeController extends Controller {
async index() {
const { ctx } = this;
await ctx.model.Monkey.findUser();
await ctx.model.User.associate();
await ctx.model.User.test();
}
}
32 changes: 32 additions & 0 deletions test/fixtures/apps/typescript/app/model/monkey.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import {Column, DataType, Model, Table, Sequelize} from "sequelize-typescript";
import {Application} from "egg";

@Table({
tableName: 'the_monkeys'
})
class Monkey extends Model<Monkey> {
@Column({
type: DataType.STRING,
allowNull: false
})
name: string

@Column({type: DataType.INTEGER})
user_id: number

@Column(DataType.DATE)
created_at: Date

@Column(DataType.DATE)
updated_at: Date

static async findUser() {
return this.findOne({where: {id: '123'}})
}
}

export default (_: Application, sequelize: Sequelize) => {
sequelize.addModels([Monkey])

return Monkey;
}
31 changes: 31 additions & 0 deletions test/fixtures/apps/typescript/app/model/user.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import {Application} from 'egg';
import assert = require('assert');
import {Column, DataType, Model, Sequelize, Table} from "sequelize-typescript";

@Table({tableName: 'user'})
class User extends Model<User> {
@Column(DataType.STRING(3))
name: string

@Column(DataType.INTEGER)
age: number
}

export default function (app: Application, sequelize: Sequelize) {
const UserModel = class extends User {
static async associate() {
assert.ok(app.model.User);
}

static async test() {
assert(app.config);
assert(app.model.User === this);
const monkey = await app.model.Monkey.create({name: 'The Monkey'});
assert(!monkey.isNewRecord);
}
};

sequelize.addModels([UserModel])

return UserModel
}
7 changes: 7 additions & 0 deletions test/fixtures/apps/typescript/app/router.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Application } from 'egg';

export default (app: Application) => {
const { controller } = app;

app.get('/', controller.home.index);
}
41 changes: 41 additions & 0 deletions test/fixtures/apps/typescript/config/config.default.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import * as path from 'path';
import {EggAppInfo, EggAppConfig, PowerPartial} from 'egg';

export default (appInfo: EggAppInfo) => {
const config = {} as PowerPartial<EggAppConfig>;

config.keys = '123123';

config.sequelize = {
Sequelize: require('sequelize-typescript').Sequelize,
datasources: [
{
delegate: 'model',
baseDir: 'model',
database: 'test',
dialect: 'mysql',
},
{
delegate: 'sequelize',
baseDir: 'sequelize',
database: 'test1',
dialect: 'mysql',
exclude: 'Person.js',
},
{
delegate: 'subproperty.a',
baseDir: 'subproperty/a',
database: 'test2',
dialect: 'mysql',
},
{
delegate: 'subproperty.b',
baseDir: 'subproperty/b',
database: 'test3',
dialect: 'mysql',
},
]
}

return config;
}
3 changes: 3 additions & 0 deletions test/fixtures/apps/typescript/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"name": "typescript"
}
17 changes: 17 additions & 0 deletions test/fixtures/apps/typescript/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"compilerOptions": {
"strict": true,
"target": "es2017",
"module": "commonjs",
"moduleResolution": "node",
"baseUrl": "./",
"experimentalDecorators": true,
"emitDecoratorMetadata": true,
"strictPropertyInitialization": false,
"paths": {
"egg-sequelize": [
"../../../../"
]
}
}
}
16 changes: 16 additions & 0 deletions test/fixtures/apps/typescript/typings/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import 'egg';
import 'egg-sequelize';
import HomeController from '../app/controller/home';
import MonkeyModel from '../app/model/monkey';
import UserModel from '../app/model/user';

declare module 'egg' {
interface IController {
home: HomeController;
}

interface IModel {
Monkey: ReturnType<typeof MonkeyModel>;
User: ReturnType<typeof UserModel>;
}
}
Loading