I'm using a webpack to transpile my ts code into js because of some circumstances (for Angular Server Side Rendering) and because webpack transpile all models into single file I can't really define path to it from original file. And I have to define every single model by myself.
// ./api/service/Database.ts
import { Sequelize } from 'sequelize-typescript';
import { join } from 'path';
const sequelize = new Sequelize({
//configs
});
sequelize.addModels([join(__dirname, '../models')]);
...
// ./webpack.server.config.js
const path = require('path');
const webpack = require('webpack');
const nodeExternals = require('webpack-node-externals');
module.exports = {
entry: { server: './server.ts' },
resolve: {
extensions: ['.js', '.ts']
},
target: 'node',
// this makes sure we include node_modules and other 3rd party libraries
externals: [nodeExternals()],
output: {
path: path.join(__dirname, 'dist'),
filename: '[name].js'
},
module: {
rules: [
{ test: /\.ts$/, loader: 'ts-loader' }
]
},
plugins: [
// Temporary Fix for issue: https://github.com/angular/angular/issues/11580
// for "WARNING Critical dependency: the request of a dependency is an expression"
new webpack.ContextReplacementPlugin(
/(.+)?angular(\\|\/)core(.+)?/,
path.join(__dirname, 'src'), // location of your src
{} // a map of your routes
),
new webpack.ContextReplacementPlugin(
/(.+)?express(\\|\/)(.+)?/,
path.join(__dirname, 'src'),
{}
)
],
optimization: {
// keep minimization off
// workaround for https://github.com/angular/angular-cli/issues/10635
minimize: false
}
}
Expected that webpack transpile this line sequelize.addModels([join(__dirname, '../models')]); into something like this sequelize.addModels([Object(path__WEBPACK_IMPORTED_MODULE_1__["join"])(__dirname, './')]); and this transpiled function will add all models which looks like that
let User_User = class User extends external_sequelize_typescript_["Model"] {
};
external_tslib_["__decorate"]([
Object(external_sequelize_typescript_["IsUUID"])(4),
Object(external_sequelize_typescript_["Default"])(external_sequelize_typescript_["DataType"].UUIDV4),
external_sequelize_typescript_["PrimaryKey"],
Object(external_sequelize_typescript_["Column"])({
type: external_sequelize_typescript_["DataType"].UUID
}),
external_tslib_["__metadata"]("design:type", String)
], User_User.prototype, "uuid", void 0);
external_tslib_["__decorate"]([
Object(external_sequelize_typescript_["AllowNull"])(false),
external_sequelize_typescript_["IsEmail"],
external_sequelize_typescript_["Column"],
external_tslib_["__metadata"]("design:type", String)
], User_User.prototype, "email", void 0);
external_tslib_["__decorate"]([
Object(external_sequelize_typescript_["AllowNull"])(false),
external_sequelize_typescript_["Column"],
external_tslib_["__metadata"]("design:type", String)
], User_User.prototype, "name", void 0);
external_tslib_["__decorate"]([
Object(external_sequelize_typescript_["AllowNull"])(false),
Object(external_sequelize_typescript_["Is"])(/^\$(2[ayb]?)\$([0-9]{1,2})\$([A-Za-z0-9.\/]{53,54})$/) // is bcrypt hash
,
Object(external_sequelize_typescript_["Column"])(external_sequelize_typescript_["DataType"].STRING(60)),
external_tslib_["__metadata"]("design:type", String)
], User_User.prototype, "hash", void 0);
User_User = external_tslib_["__decorate"]([
Object(external_sequelize_typescript_["Table"])({ tableName: 'user', modelName: 'user' })
], User_User);
Webpack transpile sequelize.addModels([join(__dirname, '../models')]) into sequelize.addModels([Object(path__WEBPACK_IMPORTED_MODULE_1__["join"])(__dirname, './models')]) and when application tries create a model, it throws the error
ERROR: Cannot read property 'createdAt' of undefined
TypeError: Cannot read property 'createdAt' of undefined
at User._initValues (/node_modules/sequelize/lib/model.js:3123:49)
at new Model (/node_modules/sequelize/lib/model.js:3097:10)
at new Model (/node_modules/sequelize-typescript/lib/models/v4/Model.js:8:9)
at new User (/dist/server.js:2025:17)
at /dist/server.js:2140:16
at Generator.next (<anonymous>)
at /node_modules/tslib/tslib.js:107:75
at new ZoneAwarePromise (/node_modules/zone.js/dist/zone-node.js:891:29)
at Object.__awaiter (/node_modules/tslib/tslib.js:103:16)
at router.get.asyncHandler (/dist/server.js:2138:90)
at /dist/server.js:2083:18
at Layer.handle [as handle_request] (/node_modules/express/lib/router/layer.js:95:5)
at next (/node_modules/express/lib/router/route.js:137:13)
at Route.dispatch (/node_modules/express/lib/router/route.js:112:3)
at Layer.handle [as handle_request] (/node_modules/express/lib/router/layer.js:95:5)
at /node_modules/express/lib/router/index.js:281:22
at param (/node_modules/express/lib/router/index.js:354:14)
at param (/node_modules/express/lib/router/index.js:365:14)
at Function.process_params (/node_modules/express/lib/router/index.js:410:3)
at next (/node_modules/express/lib/router/index.js:275:10)
at Function.handle (/node_modules/express/lib/router/index.js:174:3)
at router (/node_modules/express/lib/router/index.js:47:12)
Even set transpiled part of the path to (__dirname, './') manually doesn't actually do anything.
Can anyone advice how to achieve this feature?
Hey @someApprentice, I'm not much experienced in webpack. But I think, unless there isn't already a plugin, you need to write your own for that. Or instead of using paths for loading the models, use references like so: sequelize.addModels([YourModelA, YourModelB, ...])
@RobinBuschmann Okay, I guess issue can keep open until someone suggest solution or I'm not found it by myself.
I'm running into the same error. I'm solving it by using require.context. The following code is working for my project.
const REG_CATCH_NAME = /([^\/\.]+)\.tsx?$/;
function getModelNameByPath(path: string) {
const groups = REG_CATCH_NAME.exec(path);
if (!groups || groups.length < 2) {
console.error('Sequelize: Error in parsing model path: ', path);
return null;
}
return groups[1];
}
// webpack require context
// @ts-ignore
const req = require.context('./models', true, /\.tsx?$/);
const models = req
.keys()
.map(key => {
const modelName = getModelNameByPath(key);
if (modelName) {
console.log('Sequelize: Load model: ', modelName);
return req(key)[modelName];
}
return null;
})
.filter(each => !!each);
sequelize.addModels(models);
@someApprentice Can you confirm that @gogoout's solution works?
Closing this due to inactivity
@someApprentice Can you confirm that @gogoout's solution works?
Not OP, but this solution worked for me, with a slight change.
Since I'm exporting my modules as default export, I need to change the line
return req(key)[modelName];
to
return req(key).default;
Most helpful comment
I'm running into the same error. I'm solving it by using
require.context. The following code is working for my project.