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: restructure collaborative server database configuration and… #433

Open
wants to merge 1 commit into
base: feature/collaborative-2-custom-server
Choose a base branch
from
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
5 changes: 0 additions & 5 deletions .yarnrc

This file was deleted.

8 changes: 8 additions & 0 deletions web/collaborative-server/.sequelizerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
const path = require('path');

module.exports = {
'config': path.resolve('src/db/config.json'),
'migrations-path': path.resolve('src/db/migrations'),
'seeders-path': path.resolve('src/db/seeders'),
'models-path': path.resolve('src/db/models')
}
12 changes: 8 additions & 4 deletions web/collaborative-server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@
"dev": "npm run clean && cross-env NODE_ENV=development tsup --watch",
"build": "npm run clean && cross-env NODE_ENV=production tsup",
"start": "cross-env NODE_ENV=production node dist/server.js",
"clean": "rimraf dist db"
"clean": "rimraf dist db",
"migration:new": "./node_modules/.bin/sequelize migration:create --name",
"migrate": "./node_modules/.bin/sequelize db:migrate",
"migrate:undo": "./node_modules/.bin/sequelize db:migrate:undo"
},
"dependencies": {
"@hocuspocus/extension-logger": "^2.14.0",
Expand All @@ -29,10 +32,11 @@
"@types/sequelize": "^4.28.20",
"@types/ws": "^8.5.13",
"cross-env": "^7.0.3",
"eslint": "^8.56.0",
"prettier": "^3.1.1",
"rimraf": "^5.0.0",
"sequelize-cli": "^6.6.2",
"tsup": "^8.0.0",
"typescript": "^5.0.0",
"eslint": "^8.56.0",
"prettier": "^3.1.1"
"typescript": "^5.0.0"
}
}
24 changes: 24 additions & 0 deletions web/collaborative-server/src/db/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
{
"development": {
"username": "postgres",
"password": "postgres",
"database": "yoopta-server",
"host": "127.0.0.1",
"port": "5433",
"dialect": "postgres"
},
"test": {
"username": "root",
"password": null,
"database": "database_test",
"host": "127.0.0.1",
"dialect": "postgres"
},
"production": {
"username": "root",
"password": null,
"database": "database_production",
"host": "127.0.0.1",
"dialect": "postgres"
}
}
4 changes: 2 additions & 2 deletions web/collaborative-server/src/db/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ export const sequelize = new Sequelize({
export async function initializeDatabase() {
try {
await sequelize.query(`
SELECT 'CREATE DATABASE yoopta_collab'
SELECT 'CREATE DATABASE ${process.env.DB_NAME || 'yoopta_collab'}'
WHERE NOT EXISTS (
SELECT FROM pg_database WHERE datname = 'yoopta_collab'
SELECT FROM pg_database WHERE datname = '${process.env.DB_NAME || 'yoopta_collab'}'
)
`);

Expand Down
18 changes: 0 additions & 18 deletions web/collaborative-server/src/db/migrations/001_initial.sql

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
'use strict';

/** @type {import('sequelize-cli').Migration} */
module.exports = {
up: async (queryInterface) => queryInterface.sequelize.query('CREATE EXTENSION IF NOT EXISTS "uuid-ossp";'),

down: async (queryInterface) => queryInterface.sequelize.query('DROP EXTENSION "uuid-ossp";'),
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
'use strict';

/** @type {import('sequelize-cli').Migration} */
module.exports = {
up: async (queryInterface, DataTypes) => {
await queryInterface.createTable('documents', {
id: {
type: DataTypes.UUID,
allowNull: false,
primaryKey: true,
defaultValue: DataTypes.literal('uuid_generate_v4()'),
},

title: {
type: DataTypes.STRING(250),
allowNull: false,
defaultValue: 'Untitled',
},

createdAt: {
type: DataTypes.DATE,
allowNull: true,
},
updatedAt: {
type: DataTypes.DATE,
allowNull: true,
},
});
},

down: (queryInterface) => queryInterface.dropTable('documents'),
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
'use strict';

/** @type {import('sequelize-cli').Migration} */
module.exports = {
up: async (queryInterface, DataTypes) => {
await queryInterface.sequelize.transaction(async (transaction) => {
await queryInterface.createTable('blocks', {
id: {
type: DataTypes.UUID,
allowNull: false,
primaryKey: true,
defaultValue: DataTypes.literal('uuid_generate_v4()'),
},
documentId: {
type: DataTypes.UUID,
allowNull: false,
references: {
model: 'documents',
key: 'id',
}
},

value: {
type: DataTypes.JSONB,
allowNull: false,
defaultValue: [],
},
type: {
type: DataTypes.STRING,
allowNull: false,
},
meta: {
type: DataTypes.JSONB,
allowNull: false,
defaultValue: {},
},

createdAt: {
type: DataTypes.DATE,
allowNull: true,
},
updatedAt: {
type: DataTypes.DATE,
allowNull: true,
},
});
});
},

down: async (queryInterface) => {
await queryInterface.sequelize.transaction(async (transaction) => {
await queryInterface.dropTable('blocks', { transaction });
});
},
};
65 changes: 11 additions & 54 deletions web/collaborative-server/src/db/models/Block.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,15 @@
// src/db/models/Block.ts
import { Model, DataTypes } from 'sequelize';
import { sequelize } from '../config';
import { Document } from './Document';
import { User } from './User';

export class Block extends Model {
public id!: string;
public document_id!: string;
public value!: any;
public meta!: any;
public documentId!: string;
public value!: any; // json []
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if we are expecting a JSON array, could we type this as Record<string, any>[], same with meta below, but just as Record<string, any>.

public type!: string;
public position!: number;
public parent_id?: string;
public created_by!: string;
public last_modified_by!: string;
public version!: number;
public readonly created_at!: Date;
public readonly updated_at!: Date;
public meta!: any; // json {}
public readonly createdAt!: Date;
public readonly updatedAt!: Date;
}

Block.init(
Expand All @@ -26,7 +19,7 @@ Block.init(
defaultValue: DataTypes.UUIDV4,
primaryKey: true,
},
document_id: {
documentId: {
type: DataTypes.UUID,
allowNull: false,
references: {
Expand All @@ -38,57 +31,21 @@ Block.init(
type: DataTypes.JSONB,
allowNull: false,
},
meta: {
type: DataTypes.JSONB,
defaultValue: {},
},
type: {
type: DataTypes.STRING,
allowNull: false,
},
position: {
type: DataTypes.INTEGER,
allowNull: false,
},
parent_id: {
type: DataTypes.UUID,
references: {
model: 'blocks',
key: 'id',
},
},
created_by: {
type: DataTypes.UUID,
allowNull: false,
references: {
model: 'users',
key: 'id',
},
},
last_modified_by: {
type: DataTypes.UUID,
allowNull: false,
references: {
model: 'users',
key: 'id',
},
},
version: {
type: DataTypes.INTEGER,
defaultValue: 1,
meta: {
type: DataTypes.JSONB,
defaultValue: {},
},
},
{
sequelize,
tableName: 'blocks',
timestamps: true,
underscored: true,
version: true,
deletedAt: false,
},
);

Block.belongsTo(Document, { foreignKey: 'document_id' });
Block.belongsTo(Block, { as: 'parent', foreignKey: 'parent_id' });
Block.hasMany(Block, { as: 'children', foreignKey: 'parent_id' });
Block.belongsTo(User, { as: 'creator', foreignKey: 'created_by' });
Block.belongsTo(User, { as: 'lastModifier', foreignKey: 'last_modified_by' });
Block.belongsTo(Document, { foreignKey: 'documentId' });
30 changes: 3 additions & 27 deletions web/collaborative-server/src/db/models/Document.ts
Original file line number Diff line number Diff line change
@@ -1,17 +1,12 @@
import { DataTypes, Model } from 'sequelize';
import { sequelize } from '../config';
import { Block } from './Block';
import { DocumentUser } from './DocumentUser';
import { User } from './User';

export class Document extends Model {
public id!: string;
public title!: string;
public ydoc_state!: Buffer;
public version!: number;
public owner_id!: string;
public readonly created_at!: Date;
public readonly updated_at!: Date;
public readonly createdAt!: Date;
public readonly updatedAt!: Date;
}

Document.init(
Expand All @@ -25,32 +20,13 @@ Document.init(
type: DataTypes.STRING,
allowNull: false,
},
ydoc_state: {
type: DataTypes.BLOB,
allowNull: false,
},
version: {
type: DataTypes.INTEGER,
defaultValue: 1,
},
owner_id: {
type: DataTypes.UUID,
allowNull: false,
references: {
model: 'users',
key: 'id',
},
},
},
{
sequelize,
tableName: 'documents',
timestamps: true,
underscored: true,
version: true,
deletedAt: false,
},
);

Document.belongsTo(User, { as: 'owner', foreignKey: 'owner_id' });
Document.hasMany(Block, { foreignKey: 'document_id' });
Document.belongsToMany(User, { through: DocumentUser, as: 'users' });
Loading