Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: use sequelize-typescript #374

Merged
merged 16 commits into from
Mar 17, 2022
Merged
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
2 changes: 1 addition & 1 deletion .sequelizerc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
const path = require("path")

module.exports = {
config: path.resolve("./database", "config.js"),
config: path.resolve("./database", "config"),
"models-path": path.resolve("./database", "models"),
"seeders-path": path.resolve("./database", "seeders"),
"migrations-path": path.resolve("./database", "migrations"),
Expand Down
22 changes: 8 additions & 14 deletions bin/www
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ const http = require("http")

const app = require("@root/server")

const loaders = require("@loaders")

const debug = require("debug")("isomercms:server")

// Import logger
Expand Down Expand Up @@ -45,18 +43,16 @@ function onError(error) {
throw error
}

const bind = typeof port === "string" ? "Pipe " + port : "Port " + port
const bind = typeof port === "string" ? `Pipe ${port}` : `Port ${port}`
seaerchin marked this conversation as resolved.
Show resolved Hide resolved

// handle specific listen errors with friendly messages
switch (error.code) {
case "EACCES":
logger.error(bind + " requires elevated privileges")
logger.error(`${bind} requires elevated privileges`)
process.exit(1)
break
case "EADDRINUSE":
logger.error(bind + " is already in use")
logger.error(`${bind} is already in use`)
process.exit(1)
break
default:
throw error
}
Expand All @@ -68,8 +64,8 @@ function onError(error) {

function onListening() {
const addr = server.address()
const bind = typeof addr === "string" ? "pipe " + addr : "port " + addr.port
debug("Listening on " + bind)
const bind = typeof addr === "string" ? `pipe ${addr}` : `port ${addr.port}`
debug(`Listening on ${bind}`)
logger.info(`isomerCMS app listening on port ${port}`)
}

Expand All @@ -90,8 +86,6 @@ const server = http.createServer(app)
* Listen on provided port, on all network interfaces.
*/

loaders().then(() => {
server.listen(port)
server.on("error", onError)
server.on("listening", onListening)
})
server.listen(port)
server.on("error", onError)
server.on("listening", onListening)
67 changes: 30 additions & 37 deletions database/config.js
Original file line number Diff line number Diff line change
@@ -1,45 +1,38 @@
const { parse } = require("pg-connection-string")

// TODO: This came from a past project - I don't remember why I wrote this but let's explore later.
// We have to manually parse database URL because sequelize-typescript requires explicit
// connection parameters.

const { DB_URI, DB_MIN_POOL, DB_MAX_POOL } = process.env

const getDbConfig = () => {
if (!DB_URI) throw new Error("DB_URI is not defined")
const parsed = parse(DB_URI)
if (!DB_URI) throw new Error("DB_URI is not defined")
const parsed = parse(DB_URI)
const port = parsed.port ? parseInt(parsed.port, 10) : 5432

return {
// Connection settings
database: parsed.database || "isomercms_dev",
host: parsed.host || "localhost",
username: parsed.user,
password: parsed.password,
port: parsed.port || 5432,
module.exports = {
// Connection settings
database: parsed.database || "isomercms_dev",
host: parsed.host || "localhost",
username: parsed.user,
password: parsed.password,
port,

// Database settings
dialect: "postgres",
dialectOptions: {
useUTC: false,
timezone: "+08:00",
},
// Database settings
dialect: "postgres",
dialectOptions: {
useUTC: false,
timezone: "+08:00",
define: {
underscored: true,
charset: "utf8",
createdAt: "created_at",
updatedAt: "updated_at",
},
pool: {
min: DB_MIN_POOL ? parseInt(DB_MIN_POOL, 10) : 1,
max: DB_MAX_POOL ? parseInt(DB_MAX_POOL, 10) : 10,
},

// Migrations and seeders options
migrationStorage: "sequelize",
migrationStorageTableName: "sequelize_migration_data",
seederStorage: "sequelize",
seederStorageTableName: "sequelize_seed_data",
}
}

module.exports = {
...getDbConfig(),
seaerchin marked this conversation as resolved.
Show resolved Hide resolved
},
timezone: "+08:00",
define: {
underscored: true,
charset: "utf8",
createdAt: "created_at",
updatedAt: "updated_at",
},
pool: {
min: DB_MIN_POOL ? parseInt(DB_MIN_POOL, 10) : 1,
max: DB_MAX_POOL ? parseInt(DB_MAX_POOL, 10) : 10,
},
}
23 changes: 23 additions & 0 deletions database/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { Sequelize, SequelizeOptions } from "sequelize-typescript"

import sequelizeConfig from "@database/config.js"

/**
* The index argument is because the Parameters<T> type returns the parameters
* as a tuple type, so we need to index into it.
*
* This method is to allow for ease of testing, so that we can dynamically inject
* fake db models into sequelize, rather than depending upon concrete instances
* in our unit tests.
*/
export default (
models: Parameters<Sequelize["addModels"]>[0],
dbConfig?: SequelizeOptions
) => {
const sequelize = new Sequelize({
...sequelizeConfig,
...dbConfig,
} as SequelizeOptions)
sequelize.addModels(models)
return sequelize
}
39 changes: 0 additions & 39 deletions database/models/Site.js

This file was deleted.

48 changes: 48 additions & 0 deletions database/models/Site.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import {
DataType,
Column,
Model,
Table,
CreatedAt,
UpdatedAt,
BelongsToMany,
} from "sequelize-typescript"

import { SiteMember } from "./SiteMember"
import { User } from "./User"

@Table({ tableName: "sites" })
export class Site extends Model {
@Column({
autoIncrement: true,
primaryKey: true,
allowNull: false,
type: DataType.BIGINT,
})
id!: number

@Column({
allowNull: false,
type: DataType.TEXT,
})
name!: string

@Column({
allowNull: false,
type: DataType.TEXT,
})
apiTokenName!: string

@CreatedAt
createdAt!: Date

@UpdatedAt
updatedAt!: Date

@BelongsToMany(() => User, {
onUpdate: "CASCADE",
onDelete: "CASCADE",
through: () => SiteMember,
})
users!: User[]
}
20 changes: 0 additions & 20 deletions database/models/SiteMember.js

This file was deleted.

35 changes: 35 additions & 0 deletions database/models/SiteMember.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import {
Column,
CreatedAt,
DataType,
ForeignKey,
Model,
Table,
UpdatedAt,
} from "sequelize-typescript"

import { Site } from "./Site"
import { User } from "./User"

@Table({ tableName: "site_members" })
export class SiteMember extends Model {
@ForeignKey(() => User)
@Column
userId!: number

@ForeignKey(() => Site)
@Column
siteId!: string

@Column({
allowNull: false,
type: DataType.ENUM("ADMIN", "USER"),
})
role!: boolean

@CreatedAt
createdAt!: Date

@UpdatedAt
updatedAt!: Date
}
55 changes: 0 additions & 55 deletions database/models/User.js

This file was deleted.

Loading