Commit 917c3848 authored by Phạm Quang Bảo's avatar Phạm Quang Bảo

feat(challenge_1): design database and gen model

parents
node_modules/
.env
dist/
build/
*.log
\ No newline at end of file
const express = require('express')
const app = express()
const port = 3000
app.get('/', (req, res) => {
res.send('Hello World!')
})
app.listen(port, () => {
console.log(`Example app listening on port ${port}`)
})
const Sequelize = require('sequelize');
module.exports = function(sequelize, DataTypes) {
return sequelize.define('classes', {
id: {
type: DataTypes.UUID,
allowNull: false,
defaultValue: DataTypes.UUIDV4,
primaryKey: true
},
name: {
type: DataTypes.TEXT,
allowNull: true
},
description: {
type: DataTypes.TEXT,
allowNull: true
},
created_by: {
type: DataTypes.UUID,
allowNull: true
},
updated_by: {
type: DataTypes.UUID,
allowNull: true
},
course_id: {
type: DataTypes.UUID,
allowNull: true,
references: {
model: 'courses',
key: 'id'
}
},
status: {
type: DataTypes.STRING(50),
allowNull: true
}
}, {
sequelize,
tableName: 'classes',
schema: 'public',
timestamps: true,
indexes: [
{
name: "classes_pkey",
unique: true,
fields: [
{ name: "id" },
]
},
]
});
};
const Sequelize = require('sequelize');
module.exports = function(sequelize, DataTypes) {
return sequelize.define('courses', {
id: {
type: DataTypes.UUID,
allowNull: false,
defaultValue: DataTypes.UUIDV4,
primaryKey: true
},
name: {
type: DataTypes.TEXT,
allowNull: true
},
description: {
type: DataTypes.TEXT,
allowNull: true
},
created_by: {
type: DataTypes.UUID,
allowNull: true
},
status: {
type: DataTypes.STRING(50),
allowNull: true
}
}, {
sequelize,
tableName: 'courses',
schema: 'public',
timestamps: true,
indexes: [
{
name: "courses_pkey",
unique: true,
fields: [
{ name: "id" },
]
},
]
});
};
const Sequelize = require('sequelize');
module.exports = function(sequelize, DataTypes) {
return sequelize.define('enrollments', {
id: {
type: DataTypes.UUID,
allowNull: false,
defaultValue: DataTypes.UUIDV4,
primaryKey: true
},
user_id: {
type: DataTypes.UUID,
allowNull: true,
references: {
model: 'users',
key: 'id'
}
},
class_id: {
type: DataTypes.UUID,
allowNull: true,
references: {
model: 'classes',
key: 'id'
}
},
status: {
type: DataTypes.STRING(50),
allowNull: true
}
}, {
sequelize,
tableName: 'enrollments',
schema: 'public',
timestamps: true
});
};
var DataTypes = require("sequelize").DataTypes;
var _classes = require("./classes");
var _courses = require("./courses");
var _enrollments = require("./enrollments");
var _roles = require("./roles");
var _user_auth = require("./user_auth");
var _users = require("./users");
function initModels(sequelize) {
var classes = _classes(sequelize, DataTypes);
var courses = _courses(sequelize, DataTypes);
var enrollments = _enrollments(sequelize, DataTypes);
var roles = _roles(sequelize, DataTypes);
var user_auth = _user_auth(sequelize, DataTypes);
var users = _users(sequelize, DataTypes);
enrollments.belongsTo(classes, { as: "class", foreignKey: "class_id"});
classes.hasMany(enrollments, { as: "enrollments", foreignKey: "class_id"});
classes.belongsTo(courses, { as: "course", foreignKey: "course_id"});
courses.hasMany(classes, { as: "classes", foreignKey: "course_id"});
users.belongsTo(roles, { as: "role", foreignKey: "role_id"});
roles.hasMany(users, { as: "users", foreignKey: "role_id"});
enrollments.belongsTo(users, { as: "user", foreignKey: "user_id"});
users.hasMany(enrollments, { as: "enrollments", foreignKey: "user_id"});
user_auth.belongsTo(users, { as: "user", foreignKey: "user_id"});
users.hasMany(user_auth, { as: "user_auths", foreignKey: "user_id"});
return {
classes,
courses,
enrollments,
roles,
user_auth,
users,
};
}
module.exports = initModels;
module.exports.initModels = initModels;
module.exports.default = initModels;
const Sequelize = require('sequelize');
module.exports = function(sequelize, DataTypes) {
return sequelize.define('roles', {
id: {
type: DataTypes.UUID,
allowNull: false,
defaultValue: DataTypes.UUIDV4,
primaryKey: true
},
name: {
type: DataTypes.TEXT,
allowNull: false
},
description: {
type: DataTypes.TEXT,
allowNull: true
},
created_by: {
type: DataTypes.UUID,
allowNull: true
}
}, {
sequelize,
tableName: 'roles',
schema: 'public',
timestamps: true,
indexes: [
{
name: "roles_pkey",
unique: true,
fields: [
{ name: "id" },
]
},
]
});
};
const Sequelize = require('sequelize');
module.exports = function(sequelize, DataTypes) {
return sequelize.define('user_auth', {
id: {
type: DataTypes.UUID,
allowNull: false,
defaultValue: DataTypes.UUIDV4,
primaryKey: true
},
user_id: {
type: DataTypes.UUID,
allowNull: true,
references: {
model: 'users',
key: 'id'
}
},
password_hash: {
type: DataTypes.TEXT,
allowNull: true
}
}, {
sequelize,
tableName: 'user_auth',
schema: 'public',
timestamps: true,
indexes: [
{
name: "user_auth_pkey",
unique: true,
fields: [
{ name: "id" },
]
},
]
});
};
const Sequelize = require('sequelize');
module.exports = function(sequelize, DataTypes) {
return sequelize.define('users', {
id: {
type: DataTypes.UUID,
allowNull: false,
defaultValue: DataTypes.UUIDV4,
primaryKey: true
},
name: {
type: DataTypes.TEXT,
allowNull: false
},
date_of_birth: {
type: DataTypes.DATE,
allowNull: true
},
phone: {
type: DataTypes.TEXT,
allowNull: true
},
email: {
type: DataTypes.STRING(255),
allowNull: true
},
address: {
type: DataTypes.TEXT,
allowNull: true
},
role_id: {
type: DataTypes.UUID,
allowNull: true,
references: {
model: 'roles',
key: 'id'
}
}
}, {
sequelize,
tableName: 'users',
schema: 'public',
timestamps: true,
indexes: [
{
name: "users_pkey",
unique: true,
fields: [
{ name: "id" },
]
},
]
});
};
{
"name": "code",
"version": "1.0.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "code",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"express": "^5.2.1",
"pg": "^8.20.0",
"pg-hstore": "^2.3.4",
"sequelize": "^6.37.8",
"sequelize-auto": "^0.8.8"
}
},
"node_modules/@types/debug": {
"version": "4.1.13",
"resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.13.tgz",
"integrity": "sha512-KSVgmQmzMwPlmtljOomayoR89W4FynCAi3E8PPs7vmDVPe84hT+vGPKkJfThkmXs0x0jAaa9U8uW8bbfyS2fWw==",
"license": "MIT",
"dependencies": {
"@types/ms": "*"
}
},
"node_modules/@types/ms": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz",
"integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==",
"license": "MIT"
},
"node_modules/@types/node": {
"version": "25.7.0",
"resolved": "https://registry.npmjs.org/@types/node/-/node-25.7.0.tgz",
"integrity": "sha512-z+pdZyxE+RTQE9AcboAZCb4otwcrvgHD+GlBpPgn0emDVt0ohrTMhAwlr2Wd9nZ+nihhYFxO2pThz3C5qSu2Eg==",
"license": "MIT",
"dependencies": {
"undici-types": "~7.21.0"
}
},
"node_modules/@types/validator": {
"version": "13.15.10",
"resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.15.10.tgz",
"integrity": "sha512-T8L6i7wCuyoK8A/ZeLYt1+q0ty3Zb9+qbSSvrIVitzT3YjZqkTZ40IbRsPanlB4h1QB3JVL1SYCdR6ngtFYcuA==",
"license": "MIT"
},
"node_modules/accepts": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
"integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==",
"license": "MIT",
"dependencies": {
"mime-types": "^3.0.0",
"negotiator": "^1.0.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/body-parser": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.2.tgz",
"integrity": "sha512-oP5VkATKlNwcgvxi0vM0p/D3n2C3EReYVX+DNYs5TjZFn/oQt2j+4sVJtSMr18pdRr8wjTcBl6LoV+FUwzPmNA==",
"license": "MIT",
"dependencies": {
"bytes": "^3.1.2",
"content-type": "^1.0.5",
"debug": "^4.4.3",
"http-errors": "^2.0.0",
"iconv-lite": "^0.7.0",
"on-finished": "^2.4.1",
"qs": "^6.14.1",
"raw-body": "^3.0.1",
"type-is": "^2.0.1"
},
"engines": {
"node": ">=18"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/bytes": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
"integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/call-bind-apply-helpers": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/call-bound": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
"integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
"get-intrinsic": "^1.3.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/cliui": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
"integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
"license": "ISC",
"dependencies": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.0",
"wrap-ansi": "^7.0.0"
}
},
"node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
},
"engines": {
"node": ">=7.0.0"
}
},
"node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"license": "MIT"
},
"node_modules/content-disposition": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.1.0.tgz",
"integrity": "sha512-5jRCH9Z/+DRP7rkvY83B+yGIGX96OYdJmzngqnw2SBSxqCFPd0w2km3s5iawpGX8krnwSGmF0FW5Nhr0Hfai3g==",
"license": "MIT",
"engines": {
"node": ">=18"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/content-type": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
"integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/cookie": {
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
"integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/cookie-signature": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
"integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==",
"license": "MIT",
"engines": {
"node": ">=6.6.0"
}
},
"node_modules/debug": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"license": "MIT",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/dottie": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.7.tgz",
"integrity": "sha512-7lAK2A0b3zZr3UC5aE69CPdCFR4RHW1o2Dr74TqFykxkUCBXSRJum/yPc7g8zRHJqWKomPLHwFLLoUnn8PXXRg==",
"deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.",
"license": "MIT"
},
"node_modules/dunder-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.1",
"es-errors": "^1.3.0",
"gopd": "^1.2.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
"license": "MIT"
},
"node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
"license": "MIT"
},
"node_modules/encodeurl": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
"integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/es-define-property": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-errors": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-object-atoms": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/escalade": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
"integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
"license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
"license": "MIT"
},
"node_modules/etag": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
"integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/express": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz",
"integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==",
"license": "MIT",
"dependencies": {
"accepts": "^2.0.0",
"body-parser": "^2.2.1",
"content-disposition": "^1.0.0",
"content-type": "^1.0.5",
"cookie": "^0.7.1",
"cookie-signature": "^1.2.1",
"debug": "^4.4.0",
"depd": "^2.0.0",
"encodeurl": "^2.0.0",
"escape-html": "^1.0.3",
"etag": "^1.8.1",
"finalhandler": "^2.1.0",
"fresh": "^2.0.0",
"http-errors": "^2.0.0",
"merge-descriptors": "^2.0.0",
"mime-types": "^3.0.0",
"on-finished": "^2.4.1",
"once": "^1.4.0",
"parseurl": "^1.3.3",
"proxy-addr": "^2.0.7",
"qs": "^6.14.0",
"range-parser": "^1.2.1",
"router": "^2.2.0",
"send": "^1.1.0",
"serve-static": "^2.2.0",
"statuses": "^2.0.1",
"type-is": "^2.0.1",
"vary": "^1.1.2"
},
"engines": {
"node": ">= 18"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/finalhandler": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz",
"integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==",
"license": "MIT",
"dependencies": {
"debug": "^4.4.0",
"encodeurl": "^2.0.0",
"escape-html": "^1.0.3",
"on-finished": "^2.4.1",
"parseurl": "^1.3.3",
"statuses": "^2.0.1"
},
"engines": {
"node": ">= 18.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/forwarded": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
"integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/fresh": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz",
"integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
"license": "ISC",
"engines": {
"node": "6.* || 8.* || >= 10.*"
}
},
"node_modules/get-intrinsic": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
"license": "MIT",
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
"es-define-property": "^1.0.1",
"es-errors": "^1.3.0",
"es-object-atoms": "^1.1.1",
"function-bind": "^1.1.2",
"get-proto": "^1.0.1",
"gopd": "^1.2.0",
"has-symbols": "^1.1.0",
"hasown": "^2.0.2",
"math-intrinsics": "^1.1.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
"license": "MIT",
"dependencies": {
"dunder-proto": "^1.0.1",
"es-object-atoms": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-symbols": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/hasown": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz",
"integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==",
"license": "MIT",
"dependencies": {
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/http-errors": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
"integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==",
"license": "MIT",
"dependencies": {
"depd": "~2.0.0",
"inherits": "~2.0.4",
"setprototypeof": "~1.2.0",
"statuses": "~2.0.2",
"toidentifier": "~1.0.1"
},
"engines": {
"node": ">= 0.8"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/iconv-lite": {
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.2.tgz",
"integrity": "sha512-im9DjEDQ55s9fL4EYzOAv0yMqmMBSZp6G0VvFyTMPKWxiSBHUj9NW/qqLmXUwXrrM7AvqSlTCfvqRb0cM8yYqw==",
"license": "MIT",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3.0.0"
},
"engines": {
"node": ">=0.10.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/inflection": {
"version": "1.13.4",
"resolved": "https://registry.npmjs.org/inflection/-/inflection-1.13.4.tgz",
"integrity": "sha512-6I/HUDeYFfuNCVS3td055BaXBwKYuzw7K3ExVMStBowKo9oOAMJIXIHvdyR3iboTCp1b+1i5DSkIZTcwIktuDw==",
"engines": [
"node >= 0.4.0"
],
"license": "MIT"
},
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
"license": "ISC"
},
"node_modules/ipaddr.js": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
"license": "MIT",
"engines": {
"node": ">= 0.10"
}
},
"node_modules/is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/is-promise": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
"integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
"license": "MIT"
},
"node_modules/lodash": {
"version": "4.18.1",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz",
"integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==",
"license": "MIT"
},
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/media-typer": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz",
"integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/merge-descriptors": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz",
"integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==",
"license": "MIT",
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/mime-db": {
"version": "1.54.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
"integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime-types": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz",
"integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==",
"license": "MIT",
"dependencies": {
"mime-db": "^1.54.0"
},
"engines": {
"node": ">=18"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/mkdirp": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
"integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
"license": "MIT",
"bin": {
"mkdirp": "bin/cmd.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/moment": {
"version": "2.30.1",
"resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
"integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
"license": "MIT",
"engines": {
"node": "*"
}
},
"node_modules/moment-timezone": {
"version": "0.5.48",
"resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.48.tgz",
"integrity": "sha512-f22b8LV1gbTO2ms2j2z13MuPogNoh5UzxL3nzNAYKGraILnbGc9NEE6dyiiiLv46DGRb8A4kg8UKWLjPthxBHw==",
"license": "MIT",
"dependencies": {
"moment": "^2.29.4"
},
"engines": {
"node": "*"
}
},
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"license": "MIT"
},
"node_modules/negotiator": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz",
"integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/object-inspect": {
"version": "1.13.4",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
"integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/on-finished": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
"integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
"license": "MIT",
"dependencies": {
"ee-first": "1.1.1"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"license": "ISC",
"dependencies": {
"wrappy": "1"
}
},
"node_modules/parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/path-to-regexp": {
"version": "8.4.2",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.4.2.tgz",
"integrity": "sha512-qRcuIdP69NPm4qbACK+aDogI5CBDMi1jKe0ry5rSQJz8JVLsC7jV8XpiJjGRLLol3N+R5ihGYcrPLTno6pAdBA==",
"license": "MIT",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/pg": {
"version": "8.20.0",
"resolved": "https://registry.npmjs.org/pg/-/pg-8.20.0.tgz",
"integrity": "sha512-ldhMxz2r8fl/6QkXnBD3CR9/xg694oT6DZQ2s6c/RI28OjtSOpxnPrUCGOBJ46RCUxcWdx3p6kw/xnDHjKvaRA==",
"license": "MIT",
"dependencies": {
"pg-connection-string": "^2.12.0",
"pg-pool": "^3.13.0",
"pg-protocol": "^1.13.0",
"pg-types": "2.2.0",
"pgpass": "1.0.5"
},
"engines": {
"node": ">= 16.0.0"
},
"optionalDependencies": {
"pg-cloudflare": "^1.3.0"
},
"peerDependencies": {
"pg-native": ">=3.0.1"
},
"peerDependenciesMeta": {
"pg-native": {
"optional": true
}
}
},
"node_modules/pg-cloudflare": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.3.0.tgz",
"integrity": "sha512-6lswVVSztmHiRtD6I8hw4qP/nDm1EJbKMRhf3HCYaqud7frGysPv7FYJ5noZQdhQtN2xJnimfMtvQq21pdbzyQ==",
"license": "MIT",
"optional": true
},
"node_modules/pg-connection-string": {
"version": "2.12.0",
"resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.12.0.tgz",
"integrity": "sha512-U7qg+bpswf3Cs5xLzRqbXbQl85ng0mfSV/J0nnA31MCLgvEaAo7CIhmeyrmJpOr7o+zm0rXK+hNnT5l9RHkCkQ==",
"license": "MIT"
},
"node_modules/pg-hstore": {
"version": "2.3.4",
"resolved": "https://registry.npmjs.org/pg-hstore/-/pg-hstore-2.3.4.tgz",
"integrity": "sha512-N3SGs/Rf+xA1M2/n0JBiXFDVMzdekwLZLAO0g7mpDY9ouX+fDI7jS6kTq3JujmYbtNSJ53TJ0q4G98KVZSM4EA==",
"license": "MIT",
"dependencies": {
"underscore": "^1.13.1"
},
"engines": {
"node": ">= 0.8.x"
}
},
"node_modules/pg-int8": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
"integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==",
"license": "ISC",
"engines": {
"node": ">=4.0.0"
}
},
"node_modules/pg-pool": {
"version": "3.13.0",
"resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.13.0.tgz",
"integrity": "sha512-gB+R+Xud1gLFuRD/QgOIgGOBE2KCQPaPwkzBBGC9oG69pHTkhQeIuejVIk3/cnDyX39av2AxomQiyPT13WKHQA==",
"license": "MIT",
"peerDependencies": {
"pg": ">=8.0"
}
},
"node_modules/pg-protocol": {
"version": "1.13.0",
"resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.13.0.tgz",
"integrity": "sha512-zzdvXfS6v89r6v7OcFCHfHlyG/wvry1ALxZo4LqgUoy7W9xhBDMaqOuMiF3qEV45VqsN6rdlcehHrfDtlCPc8w==",
"license": "MIT"
},
"node_modules/pg-types": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz",
"integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==",
"license": "MIT",
"dependencies": {
"pg-int8": "1.0.1",
"postgres-array": "~2.0.0",
"postgres-bytea": "~1.0.0",
"postgres-date": "~1.0.4",
"postgres-interval": "^1.1.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/pgpass": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz",
"integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==",
"license": "MIT",
"dependencies": {
"split2": "^4.1.0"
}
},
"node_modules/postgres-array": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
"integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==",
"license": "MIT",
"engines": {
"node": ">=4"
}
},
"node_modules/postgres-bytea": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.1.tgz",
"integrity": "sha512-5+5HqXnsZPE65IJZSMkZtURARZelel2oXUEO8rH83VS/hxH5vv1uHquPg5wZs8yMAfdv971IU+kcPUczi7NVBQ==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/postgres-date": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz",
"integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/postgres-interval": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz",
"integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==",
"license": "MIT",
"dependencies": {
"xtend": "^4.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/proxy-addr": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
"integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
"license": "MIT",
"dependencies": {
"forwarded": "0.2.0",
"ipaddr.js": "1.9.1"
},
"engines": {
"node": ">= 0.10"
}
},
"node_modules/qs": {
"version": "6.15.1",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.15.1.tgz",
"integrity": "sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg==",
"license": "BSD-3-Clause",
"dependencies": {
"side-channel": "^1.1.0"
},
"engines": {
"node": ">=0.6"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/range-parser": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
"license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/raw-body": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz",
"integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==",
"license": "MIT",
"dependencies": {
"bytes": "~3.1.2",
"http-errors": "~2.0.1",
"iconv-lite": "~0.7.0",
"unpipe": "~1.0.0"
},
"engines": {
"node": ">= 0.10"
}
},
"node_modules/require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
"license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/reserved-words": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/reserved-words/-/reserved-words-0.1.2.tgz",
"integrity": "sha512-0S5SrIUJ9LfpbVl4Yzij6VipUdafHrOTzvmfazSw/jeZrZtQK303OPZW+obtkaw7jQlTQppy0UvZWm9872PbRw==",
"license": "MIT"
},
"node_modules/retry-as-promised": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-7.1.1.tgz",
"integrity": "sha512-hMD7odLOt3LkTjcif8aRZqi/hybjpLNgSk5oF5FCowfCjok6LukpN2bDX7R5wDmbgBQFn7YoBxSagmtXHaJYJw==",
"license": "MIT"
},
"node_modules/router": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz",
"integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==",
"license": "MIT",
"dependencies": {
"debug": "^4.4.0",
"depd": "^2.0.0",
"is-promise": "^4.0.0",
"parseurl": "^1.3.3",
"path-to-regexp": "^8.0.0"
},
"engines": {
"node": ">= 18"
}
},
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
"license": "MIT"
},
"node_modules/semver": {
"version": "7.8.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.8.0.tgz",
"integrity": "sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==",
"license": "ISC",
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/send": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz",
"integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==",
"license": "MIT",
"dependencies": {
"debug": "^4.4.3",
"encodeurl": "^2.0.0",
"escape-html": "^1.0.3",
"etag": "^1.8.1",
"fresh": "^2.0.0",
"http-errors": "^2.0.1",
"mime-types": "^3.0.2",
"ms": "^2.1.3",
"on-finished": "^2.4.1",
"range-parser": "^1.2.1",
"statuses": "^2.0.2"
},
"engines": {
"node": ">= 18"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/sequelize": {
"version": "6.37.8",
"resolved": "https://registry.npmjs.org/sequelize/-/sequelize-6.37.8.tgz",
"integrity": "sha512-HJ0IQFqcTsTiqbEgiuioYFMSD00TP6Cz7zoTti+zVVBwVe9fEhev9cH6WnM3XU31+ABS356durAb99ZuOthnKw==",
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/sequelize"
}
],
"license": "MIT",
"dependencies": {
"@types/debug": "^4.1.8",
"@types/validator": "^13.7.17",
"debug": "^4.3.4",
"dottie": "^2.0.6",
"inflection": "^1.13.4",
"lodash": "^4.17.21",
"moment": "^2.29.4",
"moment-timezone": "^0.5.43",
"pg-connection-string": "^2.6.1",
"retry-as-promised": "^7.0.4",
"semver": "^7.5.4",
"sequelize-pool": "^7.1.0",
"toposort-class": "^1.0.1",
"uuid": "^8.3.2",
"validator": "^13.9.0",
"wkx": "^0.5.0"
},
"engines": {
"node": ">=10.0.0"
},
"peerDependenciesMeta": {
"ibm_db": {
"optional": true
},
"mariadb": {
"optional": true
},
"mysql2": {
"optional": true
},
"oracledb": {
"optional": true
},
"pg": {
"optional": true
},
"pg-hstore": {
"optional": true
},
"snowflake-sdk": {
"optional": true
},
"sqlite3": {
"optional": true
},
"tedious": {
"optional": true
}
}
},
"node_modules/sequelize-auto": {
"version": "0.8.8",
"resolved": "https://registry.npmjs.org/sequelize-auto/-/sequelize-auto-0.8.8.tgz",
"integrity": "sha512-9o0qi2yMA86oFqcA5Nh14PnQSHP0E9WPEB4hP/NgxqdFE44Nq2u8Di5O3xmvWwXMIV6W+Q0YI/2VTLvlMJAjnQ==",
"license": "MIT",
"dependencies": {
"lodash": "^4.17.21",
"mkdirp": "^1.0.4",
"reserved-words": "^0.1.2",
"yargs": "^16.2.0"
},
"bin": {
"sequelize-auto": "bin/sequelize-auto"
},
"engines": {
"node": ">= 10"
},
"peerDependencies": {
"sequelize": ">3.30.0"
}
},
"node_modules/sequelize-pool": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/sequelize-pool/-/sequelize-pool-7.1.0.tgz",
"integrity": "sha512-G9c0qlIWQSK29pR/5U2JF5dDQeqqHRragoyahj/Nx4KOOQ3CPPfzxnfqFPCSB7x5UgjOgnZ61nSxz+fjDpRlJg==",
"license": "MIT",
"engines": {
"node": ">= 10.0.0"
}
},
"node_modules/serve-static": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz",
"integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==",
"license": "MIT",
"dependencies": {
"encodeurl": "^2.0.0",
"escape-html": "^1.0.3",
"parseurl": "^1.3.3",
"send": "^1.2.0"
},
"engines": {
"node": ">= 18"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/setprototypeof": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
"license": "ISC"
},
"node_modules/side-channel": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
"integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"object-inspect": "^1.13.3",
"side-channel-list": "^1.0.0",
"side-channel-map": "^1.0.1",
"side-channel-weakmap": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/side-channel-list": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz",
"integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==",
"license": "MIT",
"dependencies": {
"es-errors": "^1.3.0",
"object-inspect": "^1.13.4"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/side-channel-map": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
"integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.5",
"object-inspect": "^1.13.3"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/side-channel-weakmap": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
"integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
"license": "MIT",
"dependencies": {
"call-bound": "^1.0.2",
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.5",
"object-inspect": "^1.13.3",
"side-channel-map": "^1.0.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/split2": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
"integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
"license": "ISC",
"engines": {
"node": ">= 10.x"
}
},
"node_modules/statuses": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
"integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"license": "MIT",
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/strip-ansi": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"license": "MIT",
"dependencies": {
"ansi-regex": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/toidentifier": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
"license": "MIT",
"engines": {
"node": ">=0.6"
}
},
"node_modules/toposort-class": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz",
"integrity": "sha512-OsLcGGbYF3rMjPUf8oKktyvCiUxSbqMMS39m33MAjLTC1DVIH6x3WSt63/M77ihI09+Sdfk1AXvfhCEeUmC7mg==",
"license": "MIT"
},
"node_modules/type-is": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
"integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==",
"license": "MIT",
"dependencies": {
"content-type": "^1.0.5",
"media-typer": "^1.1.0",
"mime-types": "^3.0.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/underscore": {
"version": "1.13.8",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.8.tgz",
"integrity": "sha512-DXtD3ZtEQzc7M8m4cXotyHR+FAS18C64asBYY5vqZexfYryNNnDc02W4hKg3rdQuqOYas1jkseX0+nZXjTXnvQ==",
"license": "MIT"
},
"node_modules/undici-types": {
"version": "7.21.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.21.0.tgz",
"integrity": "sha512-w9IMgQrz4O0YN1LtB7K5P63vhlIOvC7opSmouCJ+ZywlPAlO9gIkJ+otk6LvGpAs2wg4econaCz3TvQ9xPoyuQ==",
"license": "MIT"
},
"node_modules/unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
"integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).",
"license": "MIT",
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/validator": {
"version": "13.15.35",
"resolved": "https://registry.npmjs.org/validator/-/validator-13.15.35.tgz",
"integrity": "sha512-TQ5pAGhd5whStmqWvYF4OjQROlmv9SMFVt37qoCBdqRffuuklWYQlCNnEs2ZaIBD1kZRNnikiZOS1eqgkar0iw==",
"license": "MIT",
"engines": {
"node": ">= 0.10"
}
},
"node_modules/vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
"integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
"license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/wkx": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/wkx/-/wkx-0.5.0.tgz",
"integrity": "sha512-Xng/d4Ichh8uN4l0FToV/258EjMGU9MGcA0HV2d9B/ZpZB3lqQm7nkOdZdm5GhKtLLhAE7PiVQwN4eN+2YJJUg==",
"license": "MIT",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/wrap-ansi": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"license": "MIT",
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"license": "ISC"
},
"node_modules/xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
"license": "MIT",
"engines": {
"node": ">=0.4"
}
},
"node_modules/y18n": {
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
"license": "ISC",
"engines": {
"node": ">=10"
}
},
"node_modules/yargs": {
"version": "16.2.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
"integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
"license": "MIT",
"dependencies": {
"cliui": "^7.0.2",
"escalade": "^3.1.1",
"get-caller-file": "^2.0.5",
"require-directory": "^2.1.1",
"string-width": "^4.2.0",
"y18n": "^5.0.5",
"yargs-parser": "^20.2.2"
},
"engines": {
"node": ">=10"
}
},
"node_modules/yargs-parser": {
"version": "20.2.9",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
"integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
"license": "ISC",
"engines": {
"node": ">=10"
}
}
}
}
{
"name": "code",
"version": "1.0.0",
"description": "",
"license": "ISC",
"author": "",
"type": "commonjs",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"dependencies": {
"express": "^5.2.1",
"pg": "^8.20.0",
"pg-hstore": "^2.3.4",
"sequelize": "^6.37.8",
"sequelize-auto": "^0.8.8"
}
}
version: '3.5'
services:
app:
container_name: db-challenge
image: postgres:17
restart: always
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: 123456
POSTGRES_DB: challenge_db
volumes:
- postgres_data:/var/lib/postgresql/data
ports:
- "2550:5432"
volumes:
postgres_data:
\ No newline at end of file
<mxfile host="app.diagrams.net" agent="5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/83.0.4103.116 Safari/537.36">
<diagram id="R2lEEEUBdFMjLlhIrx00" name="Page-1">
<mxGraphModel dx="2723" dy="958" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="850" pageHeight="1100" math="0" shadow="0" extFonts="Permanent Marker^https://fonts.googleapis.com/css?family=Permanent+Marker">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="C-vyLk0tnHw3VtMMgP7b-2" parent="1" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;" value="classes" vertex="1">
<mxGeometry height="300" width="250" x="350" y="450" as="geometry" />
</mxCell>
<mxCell id="C-vyLk0tnHw3VtMMgP7b-3" parent="C-vyLk0tnHw3VtMMgP7b-2" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" value="" vertex="1">
<mxGeometry height="30" width="250" y="30" as="geometry" />
</mxCell>
<mxCell id="C-vyLk0tnHw3VtMMgP7b-4" parent="C-vyLk0tnHw3VtMMgP7b-3" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;" value="PK" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="C-vyLk0tnHw3VtMMgP7b-5" parent="C-vyLk0tnHw3VtMMgP7b-3" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;" value="id uuid" vertex="1">
<mxGeometry height="30" width="220" x="30" as="geometry">
<mxRectangle height="30" width="220" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="C-vyLk0tnHw3VtMMgP7b-6" parent="C-vyLk0tnHw3VtMMgP7b-2" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="250" y="60" as="geometry" />
</mxCell>
<mxCell id="C-vyLk0tnHw3VtMMgP7b-7" parent="C-vyLk0tnHw3VtMMgP7b-6" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="C-vyLk0tnHw3VtMMgP7b-8" parent="C-vyLk0tnHw3VtMMgP7b-6" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;" value="name text" vertex="1">
<mxGeometry height="30" width="220" x="30" as="geometry">
<mxRectangle height="30" width="220" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="C-vyLk0tnHw3VtMMgP7b-9" parent="C-vyLk0tnHw3VtMMgP7b-2" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="250" y="90" as="geometry" />
</mxCell>
<mxCell id="C-vyLk0tnHw3VtMMgP7b-10" parent="C-vyLk0tnHw3VtMMgP7b-9" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="C-vyLk0tnHw3VtMMgP7b-11" parent="C-vyLk0tnHw3VtMMgP7b-9" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;" value="description text" vertex="1">
<mxGeometry height="30" width="220" x="30" as="geometry">
<mxRectangle height="30" width="220" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-70" parent="C-vyLk0tnHw3VtMMgP7b-2" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="250" y="120" as="geometry" />
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-71" parent="6W2G5BJYrON_X3-Y-d_I-70" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-72" parent="6W2G5BJYrON_X3-Y-d_I-70" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;" value="created_at timestamptz" vertex="1">
<mxGeometry height="30" width="220" x="30" as="geometry">
<mxRectangle height="30" width="220" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-73" parent="C-vyLk0tnHw3VtMMgP7b-2" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="250" y="150" as="geometry" />
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-74" parent="6W2G5BJYrON_X3-Y-d_I-73" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-75" parent="6W2G5BJYrON_X3-Y-d_I-73" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;" value="created_by uuid" vertex="1">
<mxGeometry height="30" width="220" x="30" as="geometry">
<mxRectangle height="30" width="220" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-76" parent="C-vyLk0tnHw3VtMMgP7b-2" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="250" y="180" as="geometry" />
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-77" parent="6W2G5BJYrON_X3-Y-d_I-76" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-78" parent="6W2G5BJYrON_X3-Y-d_I-76" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;" value="updated_at timestamptz" vertex="1">
<mxGeometry height="30" width="220" x="30" as="geometry">
<mxRectangle height="30" width="220" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-98" parent="C-vyLk0tnHw3VtMMgP7b-2" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="250" y="210" as="geometry" />
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-99" parent="6W2G5BJYrON_X3-Y-d_I-98" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-100" parent="6W2G5BJYrON_X3-Y-d_I-98" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;" value="updated_by uuid" vertex="1">
<mxGeometry height="30" width="220" x="30" as="geometry">
<mxRectangle height="30" width="220" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-101" parent="C-vyLk0tnHw3VtMMgP7b-2" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="250" y="240" as="geometry" />
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-102" parent="6W2G5BJYrON_X3-Y-d_I-101" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;" value="FK" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-103" parent="6W2G5BJYrON_X3-Y-d_I-101" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;" value="course_id uuid" vertex="1">
<mxGeometry height="30" width="220" x="30" as="geometry">
<mxRectangle height="30" width="220" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-127" parent="C-vyLk0tnHw3VtMMgP7b-2" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="250" y="270" as="geometry" />
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-128" parent="6W2G5BJYrON_X3-Y-d_I-127" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-129" parent="6W2G5BJYrON_X3-Y-d_I-127" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;" value="status varchar(50)" vertex="1">
<mxGeometry height="30" width="220" x="30" as="geometry">
<mxRectangle height="30" width="220" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="C-vyLk0tnHw3VtMMgP7b-13" parent="1" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;" value="courses" vertex="1">
<mxGeometry height="210" width="250" x="10" y="600" as="geometry" />
</mxCell>
<mxCell id="C-vyLk0tnHw3VtMMgP7b-14" parent="C-vyLk0tnHw3VtMMgP7b-13" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" value="" vertex="1">
<mxGeometry height="30" width="250" y="30" as="geometry" />
</mxCell>
<mxCell id="C-vyLk0tnHw3VtMMgP7b-15" parent="C-vyLk0tnHw3VtMMgP7b-14" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;" value="PK" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="C-vyLk0tnHw3VtMMgP7b-16" parent="C-vyLk0tnHw3VtMMgP7b-14" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;" value="id uuid" vertex="1">
<mxGeometry height="30" width="220" x="30" as="geometry">
<mxRectangle height="30" width="220" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="C-vyLk0tnHw3VtMMgP7b-17" parent="C-vyLk0tnHw3VtMMgP7b-13" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="250" y="60" as="geometry" />
</mxCell>
<mxCell id="C-vyLk0tnHw3VtMMgP7b-18" parent="C-vyLk0tnHw3VtMMgP7b-17" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="C-vyLk0tnHw3VtMMgP7b-19" parent="C-vyLk0tnHw3VtMMgP7b-17" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;" value="name text" vertex="1">
<mxGeometry height="30" width="220" x="30" as="geometry">
<mxRectangle height="30" width="220" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="C-vyLk0tnHw3VtMMgP7b-20" parent="C-vyLk0tnHw3VtMMgP7b-13" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="250" y="90" as="geometry" />
</mxCell>
<mxCell id="C-vyLk0tnHw3VtMMgP7b-21" parent="C-vyLk0tnHw3VtMMgP7b-20" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="C-vyLk0tnHw3VtMMgP7b-22" parent="C-vyLk0tnHw3VtMMgP7b-20" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;" value="description text" vertex="1">
<mxGeometry height="30" width="220" x="30" as="geometry">
<mxRectangle height="30" width="220" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-114" parent="C-vyLk0tnHw3VtMMgP7b-13" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="250" y="120" as="geometry" />
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-115" parent="6W2G5BJYrON_X3-Y-d_I-114" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-116" parent="6W2G5BJYrON_X3-Y-d_I-114" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;" value="created_at timestamptz" vertex="1">
<mxGeometry height="30" width="220" x="30" as="geometry">
<mxRectangle height="30" width="220" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-117" parent="C-vyLk0tnHw3VtMMgP7b-13" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="250" y="150" as="geometry" />
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-118" parent="6W2G5BJYrON_X3-Y-d_I-117" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-119" parent="6W2G5BJYrON_X3-Y-d_I-117" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;" value="created_by uuid" vertex="1">
<mxGeometry height="30" width="220" x="30" as="geometry">
<mxRectangle height="30" width="220" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-124" parent="C-vyLk0tnHw3VtMMgP7b-13" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="250" y="180" as="geometry" />
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-125" parent="6W2G5BJYrON_X3-Y-d_I-124" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-126" parent="6W2G5BJYrON_X3-Y-d_I-124" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;" value="status varchar(50)" vertex="1">
<mxGeometry height="30" width="220" x="30" as="geometry">
<mxRectangle height="30" width="220" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="C-vyLk0tnHw3VtMMgP7b-23" parent="1" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;" value="users" vertex="1">
<mxGeometry height="270" width="250" x="-350" y="340" as="geometry" />
</mxCell>
<mxCell id="C-vyLk0tnHw3VtMMgP7b-24" parent="C-vyLk0tnHw3VtMMgP7b-23" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" value="" vertex="1">
<mxGeometry height="30" width="250" y="30" as="geometry" />
</mxCell>
<mxCell id="C-vyLk0tnHw3VtMMgP7b-25" parent="C-vyLk0tnHw3VtMMgP7b-24" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;" value="PK" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="C-vyLk0tnHw3VtMMgP7b-26" parent="C-vyLk0tnHw3VtMMgP7b-24" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;" value="id uuid" vertex="1">
<mxGeometry height="30" width="220" x="30" as="geometry">
<mxRectangle height="30" width="220" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="C-vyLk0tnHw3VtMMgP7b-27" parent="C-vyLk0tnHw3VtMMgP7b-23" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="250" y="60" as="geometry" />
</mxCell>
<mxCell id="C-vyLk0tnHw3VtMMgP7b-28" parent="C-vyLk0tnHw3VtMMgP7b-27" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="C-vyLk0tnHw3VtMMgP7b-29" parent="C-vyLk0tnHw3VtMMgP7b-27" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;" value="name text not null" vertex="1">
<mxGeometry height="30" width="220" x="30" as="geometry">
<mxRectangle height="30" width="220" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-32" parent="C-vyLk0tnHw3VtMMgP7b-23" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="250" y="90" as="geometry" />
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-33" parent="6W2G5BJYrON_X3-Y-d_I-32" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-34" parent="6W2G5BJYrON_X3-Y-d_I-32" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;" value="date_of_birth timestamptz" vertex="1">
<mxGeometry height="30" width="220" x="30" as="geometry">
<mxRectangle height="30" width="220" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-35" parent="C-vyLk0tnHw3VtMMgP7b-23" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="250" y="120" as="geometry" />
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-36" parent="6W2G5BJYrON_X3-Y-d_I-35" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-37" parent="6W2G5BJYrON_X3-Y-d_I-35" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;" value="phone text" vertex="1">
<mxGeometry height="30" width="220" x="30" as="geometry">
<mxRectangle height="30" width="220" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-38" parent="C-vyLk0tnHw3VtMMgP7b-23" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="250" y="150" as="geometry" />
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-39" parent="6W2G5BJYrON_X3-Y-d_I-38" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-40" parent="6W2G5BJYrON_X3-Y-d_I-38" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;" value="email text" vertex="1">
<mxGeometry height="30" width="220" x="30" as="geometry">
<mxRectangle height="30" width="220" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-44" parent="C-vyLk0tnHw3VtMMgP7b-23" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="250" y="180" as="geometry" />
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-45" parent="6W2G5BJYrON_X3-Y-d_I-44" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-46" parent="6W2G5BJYrON_X3-Y-d_I-44" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;" value="address text" vertex="1">
<mxGeometry height="30" width="220" x="30" as="geometry">
<mxRectangle height="30" width="220" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-48" parent="C-vyLk0tnHw3VtMMgP7b-23" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="250" y="210" as="geometry" />
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-49" parent="6W2G5BJYrON_X3-Y-d_I-48" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;" value="FK" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-50" parent="6W2G5BJYrON_X3-Y-d_I-48" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;" value="role_id uuid" vertex="1">
<mxGeometry height="30" width="220" x="30" as="geometry">
<mxRectangle height="30" width="220" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-51" parent="C-vyLk0tnHw3VtMMgP7b-23" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="250" y="240" as="geometry" />
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-52" parent="6W2G5BJYrON_X3-Y-d_I-51" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-53" parent="6W2G5BJYrON_X3-Y-d_I-51" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;" value="created_at timestamptz" vertex="1">
<mxGeometry height="30" width="220" x="30" as="geometry">
<mxRectangle height="30" width="220" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-1" parent="1" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;" value="enrollments" vertex="1">
<mxGeometry height="150" width="250" x="10" y="320" as="geometry" />
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-2" parent="6W2G5BJYrON_X3-Y-d_I-1" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" value="" vertex="1">
<mxGeometry height="30" width="250" y="30" as="geometry" />
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-3" parent="6W2G5BJYrON_X3-Y-d_I-2" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;" value="PK" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-4" parent="6W2G5BJYrON_X3-Y-d_I-2" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;" value="id uuid" vertex="1">
<mxGeometry height="30" width="220" x="30" as="geometry">
<mxRectangle height="30" width="220" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-5" parent="6W2G5BJYrON_X3-Y-d_I-1" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="250" y="60" as="geometry" />
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-6" parent="6W2G5BJYrON_X3-Y-d_I-5" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;" value="FK1" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-7" parent="6W2G5BJYrON_X3-Y-d_I-5" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;" value="user_id uuid" vertex="1">
<mxGeometry height="30" width="220" x="30" as="geometry">
<mxRectangle height="30" width="220" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-8" parent="6W2G5BJYrON_X3-Y-d_I-1" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="250" y="90" as="geometry" />
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-9" parent="6W2G5BJYrON_X3-Y-d_I-8" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;" value="FK2" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-10" parent="6W2G5BJYrON_X3-Y-d_I-8" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;" value="class_id uuid" vertex="1">
<mxGeometry height="30" width="220" x="30" as="geometry">
<mxRectangle height="30" width="220" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-66" parent="6W2G5BJYrON_X3-Y-d_I-1" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="250" y="120" as="geometry" />
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-67" parent="6W2G5BJYrON_X3-Y-d_I-66" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-68" parent="6W2G5BJYrON_X3-Y-d_I-66" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;" value="created_at timestamptz" vertex="1">
<mxGeometry height="30" width="220" x="30" as="geometry">
<mxRectangle height="30" width="220" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-11" parent="1" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;" value="user_auth" vertex="1">
<mxGeometry height="150" width="250" x="-700" y="280" as="geometry" />
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-12" parent="6W2G5BJYrON_X3-Y-d_I-11" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" value="" vertex="1">
<mxGeometry height="30" width="250" y="30" as="geometry" />
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-13" parent="6W2G5BJYrON_X3-Y-d_I-12" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;" value="PK" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-14" parent="6W2G5BJYrON_X3-Y-d_I-12" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;" value="id uuid" vertex="1">
<mxGeometry height="30" width="220" x="30" as="geometry">
<mxRectangle height="30" width="220" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-15" parent="6W2G5BJYrON_X3-Y-d_I-11" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="250" y="60" as="geometry" />
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-16" parent="6W2G5BJYrON_X3-Y-d_I-15" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;" value="FK" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-17" parent="6W2G5BJYrON_X3-Y-d_I-15" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;" value="user_id uuid" vertex="1">
<mxGeometry height="30" width="220" x="30" as="geometry">
<mxRectangle height="30" width="220" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-18" parent="6W2G5BJYrON_X3-Y-d_I-11" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="250" y="90" as="geometry" />
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-19" parent="6W2G5BJYrON_X3-Y-d_I-18" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-20" parent="6W2G5BJYrON_X3-Y-d_I-18" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;" value="password_hash text" vertex="1">
<mxGeometry height="30" width="220" x="30" as="geometry">
<mxRectangle height="30" width="220" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-54" parent="6W2G5BJYrON_X3-Y-d_I-11" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="250" y="120" as="geometry" />
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-55" parent="6W2G5BJYrON_X3-Y-d_I-54" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-56" parent="6W2G5BJYrON_X3-Y-d_I-54" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;" value="created_at timestamptz" vertex="1">
<mxGeometry height="30" width="220" x="30" as="geometry">
<mxRectangle height="30" width="220" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-21" parent="1" style="shape=table;startSize=30;container=1;collapsible=1;childLayout=tableLayout;fixedRows=1;rowLines=0;fontStyle=1;align=center;resizeLast=1;" value="roles" vertex="1">
<mxGeometry height="180" width="250" x="-690" y="570" as="geometry" />
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-22" parent="6W2G5BJYrON_X3-Y-d_I-21" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=1;" value="" vertex="1">
<mxGeometry height="30" width="250" y="30" as="geometry" />
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-23" parent="6W2G5BJYrON_X3-Y-d_I-22" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;fontStyle=1;" value="PK" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-24" parent="6W2G5BJYrON_X3-Y-d_I-22" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;fontStyle=5;" value="id uuid" vertex="1">
<mxGeometry height="30" width="220" x="30" as="geometry">
<mxRectangle height="30" width="220" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-25" parent="6W2G5BJYrON_X3-Y-d_I-21" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="250" y="60" as="geometry" />
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-26" parent="6W2G5BJYrON_X3-Y-d_I-25" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-27" parent="6W2G5BJYrON_X3-Y-d_I-25" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;" value="name text" vertex="1">
<mxGeometry height="30" width="220" x="30" as="geometry">
<mxRectangle height="30" width="220" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-28" parent="6W2G5BJYrON_X3-Y-d_I-21" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="250" y="90" as="geometry" />
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-29" parent="6W2G5BJYrON_X3-Y-d_I-28" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-30" parent="6W2G5BJYrON_X3-Y-d_I-28" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;" value="description text" vertex="1">
<mxGeometry height="30" width="220" x="30" as="geometry">
<mxRectangle height="30" width="220" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-59" parent="6W2G5BJYrON_X3-Y-d_I-21" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="250" y="120" as="geometry" />
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-60" parent="6W2G5BJYrON_X3-Y-d_I-59" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-61" parent="6W2G5BJYrON_X3-Y-d_I-59" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;" value="created_at timestamptz" vertex="1">
<mxGeometry height="30" width="220" x="30" as="geometry">
<mxRectangle height="30" width="220" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-62" parent="6W2G5BJYrON_X3-Y-d_I-21" style="shape=partialRectangle;collapsible=0;dropTarget=0;pointerEvents=0;fillColor=none;points=[[0,0.5],[1,0.5]];portConstraint=eastwest;top=0;left=0;right=0;bottom=0;" value="" vertex="1">
<mxGeometry height="30" width="250" y="150" as="geometry" />
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-63" parent="6W2G5BJYrON_X3-Y-d_I-62" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;" value="" vertex="1">
<mxGeometry height="30" width="30" as="geometry">
<mxRectangle height="30" width="30" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-64" parent="6W2G5BJYrON_X3-Y-d_I-62" style="shape=partialRectangle;overflow=hidden;connectable=0;fillColor=none;top=0;left=0;bottom=0;right=0;align=left;spacingLeft=6;" value="created_by uuid" vertex="1">
<mxGeometry height="30" width="220" x="30" as="geometry">
<mxRectangle height="30" width="220" as="alternateBounds" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-110" edge="1" parent="1" source="C-vyLk0tnHw3VtMMgP7b-3" style="edgeStyle=entityRelationEdgeStyle;endArrow=ERzeroToMany;startArrow=ERone;endFill=1;startFill=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;" target="6W2G5BJYrON_X3-Y-d_I-8" value="">
<mxGeometry height="100" relative="1" width="100" as="geometry">
<mxPoint x="310" y="300" as="sourcePoint" />
<mxPoint x="300" y="760" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-111" edge="1" parent="1" source="C-vyLk0tnHw3VtMMgP7b-24" style="edgeStyle=entityRelationEdgeStyle;endArrow=ERzeroToMany;startArrow=ERone;endFill=1;startFill=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" target="6W2G5BJYrON_X3-Y-d_I-5" value="">
<mxGeometry height="100" relative="1" width="100" as="geometry">
<mxPoint x="270" y="390" as="sourcePoint" />
<mxPoint x="260" y="850" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-112" edge="1" parent="1" source="6W2G5BJYrON_X3-Y-d_I-22" style="edgeStyle=entityRelationEdgeStyle;endArrow=ERzeroToMany;startArrow=ERone;endFill=1;startFill=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" target="6W2G5BJYrON_X3-Y-d_I-48" value="">
<mxGeometry height="100" relative="1" width="100" as="geometry">
<mxPoint x="-610" y="480" as="sourcePoint" />
<mxPoint x="-620" y="940" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-113" edge="1" parent="1" source="C-vyLk0tnHw3VtMMgP7b-24" style="edgeStyle=entityRelationEdgeStyle;endArrow=ERzeroToMany;startArrow=ERone;endFill=1;startFill=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;" target="6W2G5BJYrON_X3-Y-d_I-15" value="">
<mxGeometry height="100" relative="1" width="100" as="geometry">
<mxPoint x="-450" y="290" as="sourcePoint" />
<mxPoint x="-460" y="750" as="targetPoint" />
</mxGeometry>
</mxCell>
<mxCell id="6W2G5BJYrON_X3-Y-d_I-120" edge="1" parent="1" source="6W2G5BJYrON_X3-Y-d_I-101" style="edgeStyle=entityRelationEdgeStyle;endArrow=ERzeroToMany;startArrow=ERone;endFill=1;startFill=0;entryX=1;entryY=0.5;entryDx=0;entryDy=0;exitX=0;exitY=0.5;exitDx=0;exitDy=0;" target="C-vyLk0tnHw3VtMMgP7b-14" value="">
<mxGeometry height="100" relative="1" width="100" as="geometry">
<mxPoint x="480" y="360" as="sourcePoint" />
<mxPoint x="330" y="500" as="targetPoint" />
</mxGeometry>
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>
erd.png

132 KB

CREATE TABLE classes (
id uuid DEFAULT gen_random_uuid() NOT NULL,
name text,
description text,
created_at timestamp with time zone DEFAULT now(),
created_by uuid,
updated_at timestamp with time zone,
updated_by uuid,
course_id uuid,
status character varying(50)
);
CREATE TABLE courses (
id uuid DEFAULT gen_random_uuid() NOT NULL,
name text,
description text,
created_at timestamp with time zone DEFAULT now(),
created_by uuid,
status character varying(50)
);
CREATE TABLE enrollments (
id uuid DEFAULT gen_random_uuid() NOT NULL,
user_id uuid,
class_id uuid,
created_at timestamp with time zone DEFAULT now(),
status character varying(50)
);
CREATE TABLE roles (
id uuid DEFAULT gen_random_uuid() NOT NULL,
name text NOT NULL,
description text,
created_at timestamp with time zone DEFAULT now(),
created_by uuid
);
CREATE TABLE user_auth (
id uuid DEFAULT gen_random_uuid() NOT NULL,
user_id uuid,
password_hash text,
created_at timestamp with time zone DEFAULT now()
);
CREATE TABLE users (
id uuid DEFAULT gen_random_uuid() NOT NULL,
name text NOT NULL,
date_of_birth timestamp without time zone,
phone text,
email character varying(255),
address text,
created_at timestamp with time zone DEFAULT now(),
role_id uuid
);
ALTER TABLE classes
ADD CONSTRAINT classes_pkey
PRIMARY KEY (id);
ALTER TABLE courses
ADD CONSTRAINT courses_pkey
PRIMARY KEY (id);
ALTER TABLE roles
ADD CONSTRAINT roles_pkey
PRIMARY KEY (id);
ALTER TABLE user_auth
ADD CONSTRAINT user_auth_pkey
PRIMARY KEY (id);
ALTER TABLE users
ADD CONSTRAINT users_pkey
PRIMARY KEY (id);
ALTER TABLE enrollments
ADD CONSTRAINT enrollment_user
FOREIGN KEY (user_id)
REFERENCES users(id);
ALTER TABLE classes
ADD CONSTRAINT fk_classes_course
FOREIGN KEY (course_id)
REFERENCES courses(id);
ALTER TABLE enrollments
ADD CONSTRAINT fk_enrollment_class
FOREIGN KEY (class_id)
REFERENCES classes(id);
ALTER TABLE user_auth
ADD CONSTRAINT fk_user
FOREIGN KEY (user_id)
REFERENCES users(id);
ALTER TABLE users
ADD CONSTRAINT users_role
FOREIGN KEY (role_id)
REFERENCES roles(id);
\ No newline at end of file
-- 1. Thêm 10 Role mẫu (Cần có Role trước để gán cho User)
INSERT INTO roles (id, name, description, created_at)
SELECT
gen_random_uuid(),
'Role Name ' || i,
'Description for role ' || i,
NOW()
FROM generate_series(1, 10) AS i;
-- 2. Thêm 10 User mẫu (Lấy ngẫu nhiên role_id từ bảng roles)
INSERT INTO users (id, name, date_of_birth, phone, email, address, role_id, created_at)
SELECT
gen_random_uuid(),
'User Name ' || i,
'1990-01-01'::timestamptz + (i || ' months')::interval,
'090123456' || (i-1),
'user' || i || '@example.com',
'Address ' || i,
(SELECT id FROM roles ORDER BY random() LIMIT 1), -- Lấy ngẫu nhiên 1 role
NOW()
FROM generate_series(1, 10) AS i;
-- 3. Thêm 10 Auth mẫu (Liên kết 1-1 hoặc 1-n với Users)
INSERT INTO user_auth (id, user_id, password_hash, created_at)
SELECT
gen_random_uuid(),
u.id,
'hash_password_sample_' || row_number() OVER (),
NOW()
FROM (SELECT id FROM users LIMIT 10) u;
-- 4. Thêm 10 Course mẫu
INSERT INTO courses (id, name, description, status, created_at)
SELECT
gen_random_uuid(),
'Course ' || i,
'Description for course ' || i,
'active',
NOW()
FROM generate_series(1, 10) AS i;
-- 5. Thêm 10 Class mẫu (Liên kết với Courses)
INSERT INTO classes (id, name, description, course_id, status, created_at)
SELECT
gen_random_uuid(),
'Class ' || i,
'Description for class ' || i,
(SELECT id FROM courses ORDER BY random() LIMIT 1),
'opened',
NOW()
FROM generate_series(1, 10) AS i;
-- 6. Thêm 10 Enrollment mẫu (Kết nối User và Class)
INSERT INTO enrollments (id, user_id, class_id, created_at)
SELECT
gen_random_uuid(),
(SELECT id FROM users ORDER BY random() LIMIT 1),
(SELECT id FROM classes ORDER BY random() LIMIT 1),
NOW()
FROM generate_series(1, 10) AS i;
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment