Breeze-Sequelize with autoGeneratedKeyType Identity - javascript

I am trying to create an MS SQL db with breeze-breeze sequelize and i like to generate the ids on the db server. My solution is oriented on the tempHire example from the breeze samples repo
My Metadata.json looks like this:
{
"metadataVersion": "1.0.5",
"namingConvetion": "camelCase",
"localQueryComparisonOptions": "caseInsensitiveSQL",
"dataServices": [{
"serviceName": "breeze/",
"hasServerMetadata": true,
"useJsonp": false
}],
"structuralTypes": [{
"shortName": "User",
"namespace": "Model",
"autoGeneratedKeyType": "Identity",
"defaultResourceName": "Users",
"dataProperties": [{
"nameOnServer": "id",
"dataType": "Int32",
"isPartOfKey": true,
"isNullable": false
}, {
"name": "firstName",
"dataType": "String"
}, {
"name": "lastName",
"dataType": "String"
}, {
"name": "userName",
"dataType": "String",
"isNullable": false,
"maxLength": 64,
"validators": [{
"name": "required"
}, {
"maxLength": 64,
"name": "maxLength"
}]
}, {
"name": "email",
"dataType": "String"
}]
}],
"resourceEntityTypeMap": {
"Users": "User:#Model"
}
}
though this will not create an identity id column.
the created table looks like the following create script:
CREATE TABLE [User] (
[id] INTEGER NOT NULL ,
[firstName] NVARCHAR(255) DEFAULT NULL,
[lastName] NVARCHAR(255) DEFAULT NULL,
[userName] NVARCHAR(64) NOT NULL DEFAULT '',
[email] NVARCHAR(255) DEFAULT NULL,
PRIMARY KEY ([id])
)
In addition here are some breeze server side implementations:
var dbConfig = {
user: 'user',
password: 'secret',
dbName: 'dbname'
};
var sequelizeOptions = {
host: 'hostname',
dialect: 'mssql',
port: 1433
};
function createSequelizeManager() {
var metadata = readMetadata();
var sm = new SequelizeManager(dbConfig, sequelizeOptions);
sm.importMetadata(metadata);
return sm;
}
var _sequelizeManager = createSequelizeManager();
_sequelizeManager.authenticate();
_sequelizeManager.sync(false /* createDb */)
.then(seed)
.then(function () {
console.log('db init successful');
});
Do i have a wrong configuration? Is the Identity not available with the mssql dialect? Am i doing something wrong?

With the configuration is nothing wrong i guess.
I just found out that there is a bug in the MetadataMapper from breeze-sequelize. I tested it with the sequelize version 2.1.3 and 3.x.
The autoIncrement attribute for sequelize will never get set. The if statement will never be true. I'll report this on github. ;)
The fix would be the following code in the MetadataMapper.js at line 134:
if (attributes.type.key == "INTEGER" || attributes.type.key =="BIGINT") {
attributes.autoIncrement = true;
}
In the original code the if statement is attributes.type== "INTEGER" || attributes.type=="BIGINT" where the type actually never is a string.

Related

Statsig - How to get true value from feature gate?

I am trying to implement StatSig(Refer: https://docs.statsig.com/) feature into my react(Nextjs) application. I have created new feature gate changeComponentUI and Rule has been added as Environment Tier -> Any of - staging, development. From client side I am trying retrieve the data as const statsigFeatureOn = useGate('changecomponentui').value, here I am always getting false value even if it is ON.
In app.js I have initialized like,
<StatsigProvider
sdkKey={"client-PsdasdASQW6556aIOPASASsqwewqeGSsad"}
user={{ userId, }}
options={{ environment: { tier: 'staging' } }}
waitForInitialization={true}
>
<Component {...args} />
</StatsigProvider>
In browser's Network tab I am getting -
Request Payload as,
{"user":{"userID":"","statsigEnvironment":{"tier":"staging"}},"statsigMetadata":{"sessionID":"433h67a3-416c-4914-82fd-e3c2b12f7n05","sdkType":"react-client","sdkVersion":"0.5.1","stableID":"8d122318-6d18-2322-889a-83c10e44e46"}}
Output is (Preview),
{
"gates": {
"+ZpxDXVQ/Rbhf02jl1Yv91VU+X+c0Gq/DZM+CmjPJgc=": false,
"uwglh6w2Nas8RufxC82qrsVAohod9gsGpvaT6/1l7ts=": false,
"sKSndsyjj+9MYUFlHPcdavbtA38g1+PjhofnyTDSxU8=": false,
"w9AtEJ/+vqrqb1kh8KPvhN2Rd32mkwfR+gxvlesY4ac=": true,
"gUZn3VlwEVdqBs7NcXGWHpBueNz0rlZGTufpLeB8Fug=": false
},
"feature_gates": {
"+ZpxDXVQ/Rbhf02jl1Yv91VU+X+c0Gq/DZM+CmjPJgc=": {
"name": "+ZpxDXVQ/Rbhf02jl1Yv91VU+X+c0Gq/DZM+CmjPJgc=",
"value": false,
"rule_id": "",
"secondary_exposures": []
},
"uwglh6w2Nas8RufxC82qrsVAohod9gsGpvaT6/1l7ts=": {
"name": "uwglh6w2Nas8RufxC82qrsVAohod9gsGpvaT6/1l7ts=",
"value": false,
"rule_id": "",
"secondary_exposures": []
},
"sKSndsyjj+9MYUFlHPcdavbtA38g1+PjhofnyTDSxU8=": {
"name": "sKSndsyjj+9MYUFlHPcdavbtA38g1+PjhofnyTDSxU8=",
"value": false,
"rule_id": "default",
"secondary_exposures": []
},
"w9AtEJ/+vqrqb1kh8KPvhN2Rd32mkwfR+gxvlesY4ac=": {
"name": "w9AtEJ/+vqrqb1kh8KPvhN2Rd32mkwfR+gxvlesY4ac=",
"value": true,
"rule_id": "6ZcQ0LOgAi2kSd5QgbtJzJ",
"secondary_exposures": []
},
"gUZn3VlwEVdqBs7NcXGWHpBueNz0rlZGTufpLeB8Fug=": {
"name": "gUZn3VlwEVdqBs7NcXGWHpBueNz0rlZGTufpLeB8Fug=",
"value": false,
"rule_id": "default",
"secondary_exposures": []
}
},
"configs": {},
"dynamic_configs": {},
"sdkParams": {},
"has_updates": true,
"time": 1631164754145
}
How can I get true value here? Also in output there is one object with true value but I am not getting it is for which feature gate's data.
Please help me to solve this issue.
Make sure you are using the exact ID from the console. In this case, you might need to do const statsigFeatureOn = useGate('changecomponentui').value if the feature name is "ChangeComponentUI" but the id is "changecomponentui". I believe all ID's are currently lowercase, but maybe camel case is a good reason not to do that (or to be case-insensitive)
(Edit) The following code snippet works for me in next.js after creating a gate by the same steps:
import React from "react";
import { StatsigProvider, useGate } from "statsig-react";
export default function App(): JSX.Element {
return (
<StatsigProvider
sdkKey={"client-(redacted)"}
user={{ userID: "" }} // Fixed from userId, but since userID didn't matter both worked in this case
options={{ environment: { tier: "staging" } }}
waitForInitialization={true}
>
<TestComponent />
</StatsigProvider>
);
}
function TestComponent() {
const statsigFeatureOn = useGate("changecomponentui").value;
return <div>{String(statsigFeatureOn)}</div>;
}

How to use sequalize.literal IF statement in node js

I need to use sequalize.literal in my node js code.
What I need to do is use an If else statement inside that sequalize literal,
Are there any references for this?
I tried in the below way, but node js returning that syntax is wrong. Can someone helop me to correct the syntax?
sequelize.literal('if(userId is not null, yes,no) as status')
I think what you really want is to use a MySQL case statement inside of a sequelize subquery.
The relevant MySQL docs are for cases statements can be found here, and the sequelize docs for sub queries can are here.
Here's an example similar to the query in the original question.
let {
Sequelize,
DataTypes,
} = require('sequelize')
async function run () {
let sequelize = new Sequelize(process.env.DB_NAME, process.env.DB_USER, process.env.DB_PASSWORD, {
host: 'localhost',
dialect: 'mysql',
logging: console.log
})
let Comment = sequelize.define('comment', {
userId: DataTypes.INTEGER,
comment: DataTypes.STRING
})
await sequelize.sync({ force: true })
await Comment.bulkCreate([{
comment: 'Hello'
}, {
userId: 42,
comment: 'This is it.'
}, {
userId: 128,
comment: 'Breakfast of the day.'
}])
let comments = await Comment.findAll({
attributes: [
'id',
'comment',
[ sequelize.literal('(case when userId is not null then "yes" else "no" end)'), 'status' ]
]
})
console.log(JSON.stringify(comments, null, 2))
await sequelize.close()
}
run()
This outputs
[
{
"id": 1,
"comment": "Hello",
"status": "no"
},
{
"id": 2,
"comment": "This is it.",
"status": "yes"
},
{
"id": 3,
"comment": "Breakfast of the day.",
"status": "yes"
}
]

Mongoose: Array attribute inside a collection is returned empty by Model.find() even though it has data in the database

I'm trying to create a test query for one of my databases using Mongoose. For this, I have created some data in a JSON file and have imported it into MongoDB. Here's the data:
{
"name": "SSS",
"discordid": "61231237",
"prefix": "!",
"servers": [
{
"name": "DMG TTT",
"type": "garrysmod",
"host": "66.151.244.2",
"vchannelid": "616413849679036530",
"tchannelid": "616414488916393984"
},
{
"name": "DMG Potpourri",
"type": "garrysmod",
"host": "192.223.27.68",
"vchannelid": "616415352271667232",
"tchannelid": "616415277713981441"
}
]
}
As you can see, the servers attribute is an array that has 2 objects inside it. However, when I query the database using Mongoose using this code:
Guild.find({ name: "SSS" }).exec((err, data) => { console.log(JSON.stringify(data)) })
The following is returned in console:
[{"servers":[],"_id":"5d675d80dd57df7e7d88e491","name":"SSS","discordid":"61231237","prefix":"!"}]
Notice that the servers array is returned as empty, even though it has data inside of it. Looking through some solutions, it was suggested that I try JSON.stringify, but it made no difference with or without it. Why does this happen?
EDIT: Here is the model file:
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
//Discord Guild schema
const guildSchema = Schema({
name: String,
discordid: String,
prefix: String,
servers: [{
name: String,
type: String,
host: String,
vchannelid: String,
tchannelid: String
}]
})
module.exports = mongoose.model("Guild", guildSchema)
and here is the same query done thought the MongoDB CLI:
> db.guilds.find()
{ "_id" : ObjectId("5d675d80dd57df7e7d88e491"), "name" : "SSS", "discordid" : "61231237", "prefix" : "!", "servers" : [ { "name" : "DMG TTT", "type" : "garrysmod", "host" : "66.151.244.2", "vchannelid" : "616413849679036530", "tchannelid" : "616414488916393984" }, { "name" : "DMG Potpourri", "type" : "garrysmod", "host" : "192.223.27.68", "vchannelid" : "616415352271667232", "tchannelid" : "616415277713981441" } ] }
Try the following approach ,
Your guildModel ,
const guildSchema = Schema({
name: {type: String},
discordid: {type: String},
prefix: {type: String},
servers: [{
name: {type: String},
type: {type: String},
host: {type: String},
vchannelid: {type: String},
tchannelid: {type: String}
}]
})
First save the JSON object in your database as below-
Your Controller File , Make sure the format is as same as below .
var guildModel = require('../models/guild.model');
req.body = [{
"name": "SSS",
"discordid": "61231237",
"prefix": "!",
"servers": [
{
"name": "DMG TTT",
"type": "garrysmod",
"host": "66.151.244.2",
"vchannelid": "616413849679036530",
"tchannelid": "616414488916393984"
},
{
"name": "DMG Potpourri",
"type": "garrysmod",
"host": "192.223.27.68",
"vchannelid": "616415352271667232",
"tchannelid": "616415277713981441"
}
],
}];
var guild = new guildModel(req.body[0]);
guild.save((err , userSaved)=>{
if(err){
res.status(400).send(err);
}
else{
console.log("userSaved =========> " , userSaved);
res.json({user: userSaved});
}
});
then apply the below code to retrieve the data from the database .
guildModel.find({name : "SSS"})
.exec((err , found )=>{
if (err){
res.send(err)
}else{
res.send(found);
}
});

Is there any way in nodejs to print log4js output in JSON format?

I am trying to get output of log4js in JSON format so I can easily trace it.
Is there any way that we have to set in configuration.json so output produced by log4js will be in JSON format?
Currently I am using following config.
{
"appenders": [
{
"category": "XXXXX",
"type": "dateFile",
"filename": "XXXXXXXX",
"pattern": "-from-MM-dd",
"layout": {
"type": "messagePassThrough"
}
},
{
"category": "XXXXXXXXX",
"type": "dateFile",
"filename": "XXXXXXXX",
"pattern": "-from-MM-dd",
"layout": {
"type": "messagePassThrough"
}
}
],
"levels": {
"XXXXConfig": "INFO",
"XXXXXjectConfig" : "INFO"
}
}
and I got output is in following format :
DEBUG: 1458562784032 : 2016-03-21T12:19:44.4444+00:00 : Data in request: : {
"action": "XXXXXXX",
"user": {
"username": "XXXX",
"id" : XXXX,
"pos" : XXXX
},
"version": 111
}
instead I want it in (Something like following structure) :
{"id" : "1458562784032", "time" : "2016-03-21T12:19:44.4444+00:00", "message" : "Data in request:", "data" : "{
"action": "XXXXXXX",
"user": {
"username": "XXXX",
"id" : XXXX,
"pos: : XXXX
},
"version": 111
}" }
May be there is something I missing in config.
Thanks for helping.
There are two ways to implement this issue now, you can add your own layouts or pattern format.
Below is the sample code of adding your own layouts with JSON format
const log4js = require('log4js');
log4js.addLayout('json', function(config) {
return function(logEvent) { return JSON.stringify(logEvent) + config.separator; }
});
log4js.configure({
appenders: {
out: { type: 'stdout', layout: { type: 'json', separator: ',' } }
},
categories: {
default: { appenders: ['out'], level: 'info' }
}
});
const logger = log4js.getLogger('json-test');
logger.info('this is just a test');
We can use bunyan for same purpose which logs your console log in JSON format.
Here is the npm link for node : https://www.npmjs.com/package/bunyan.
Also even if you want to use log4js then create your own pattern and write log file into JSON format.
Thanks.

Mongoose - use a post method to create a new empty collection

Libraries in use: Express, Mongoose, Express-Restify-Mongoose
Problem: I am trying to figure out how to create a POST request that will provide the schema in the req.body. I want to simply create a new collection if it does not already exist and enforce that new schema.
when I use the following code:
app.use('/api/v1', function(req, res, next) {
if(req.path[0] === '/' && -1 === req.path.indexOf('/', 1) && req.method === 'POST') {
var collection_name = req.path.substr(1, req.path.length - 1).toLowerCase();
if(mongoose.modelNames().indexOf(collection_name) === -1) {
// only create if model does not exist
console.log(req.body);
var schema = new mongoose.Schema({}, { strict: false, collection: collection_name });
var model = mongoose.model(collection_name, schema);
restify.serve(app, model, { plural: false, name: collection_name });
}
}
next();
});
It also posts an empty document to that collection. If I change the code ever so slightly so that var schema uses the post's req.body to determine the schema the POST request does not go through:
var schema = new mongoose.Schema(req.body, { strict: false, collection: collection_name });
Where the req.body from the POST is:
{
"update_count": { "type": "String", "required": "false" },
"created_date": { "type": "String", "required": "false" },
"created_by": { "type": "String", "required": "false" },
"updated_date": { "type": "String", "required": "false" },
"updated_by": { "type": "String", "required": "false" }
}
Which returns an error and does not complete the POST request because it is also trying to use that same req.body to follow the schema I've just set AND it wants to use the req.body to enter into the document.
{
"message": "testcollection3 validation failed",
"name": "ValidationError",
"errors": {
"updated_by": {
"message": "Cast to String failed for value \"[object Object]\" at path \"updated_by\"",
"name": "CastError",
"kind": "String",
"value": {
"type": "String",
"required": "false"
},
"path": "updated_by"
},
..................................
How can I set the schema with my post and also prevent a document from being created?
As you've seen, Mongoose won't create a model's collection until it needs to save a document to it. However, you can create the collection explicitly using the Db#createCollection method from the native MongoDB driver that's accessible via mongoose.connection.db:
mongoose.connection.db.createCollection(collection_name, (err) => {...});
Mongoose seems to create a still missing collection any time it is needed for some data access operation. So for me, (using v4.5.9) this works:
mongoose.connection.db.findOne({}).then(...).catch(...);

Categories

Resources