Is there any way to create circural reference with Nim? - circular-reference

I'm trying to do something like this:
type
User = ref object
email: string
session: Session # ERROR! undeclared identifier 'Session'
type
Session = ref object
key: string
user: User
Is there any way to do it with Nim?

Ok, the answer is to do it with single "type" statment like this:
type
User = ref object
email: string
session: Session # NO ERROR :)
Session = ref object
key: string
user: User

Related

Mongoose Schema type as a custom interface from TypeScript?

I´d like to store a custom object that has the StationRating interface attributes, can somebody help me ?
It's possible, but it requires some boilerplate. Issues are:
Interfaces and types in TS do not exist in emitted code
While you could go in the other direction - create a schema object and make an interface/type out of it - schema object values must be constructors, eg Number, which is not the same thing as something with a number type.
But you can create a type that maps the constructor types to their primitive types (eg Number to number), then use that to turn the schema object into the type you want:
type ConstructorMapping<T> =
T extends NumberConstructor ? number :
T extends StringConstructor ? string : never; // etc: continue as needed
const schemaObj = {
score: Number,
user_id: String,
station_id: String,
description: String,
};
type SchemaObj = typeof schemaObj;
type StationRating = {
[prop in keyof SchemaObj]: ConstructorMapping<SchemaObj[prop]>
};
Then use schemaObj when calling new Schema, and you'll also have the following usable type:
type StationRating = {
score: number;
user_id: string;
station_id: string;
description: string;
}
Is it worth it? I'm not sure. For smaller objects, maybe not. For larger objects, maybe so. You might prefer just to write out the type and the schema object.
Is there a specific reason you want to store it in an object? You could use a virtual method to create the "Rating". I'm not exactly sure without seeing more, but if all you want to do is reference the score or create some calculations off it, then it seems like an easy enough solution.
https://mongoosejs.com/docs/tutorials/virtuals.html
const userSchema = mongoose.Schema({
firstName: String,
lastName: String
});
// Create a virtual property `fullName` with a getter and setter.
userSchema.virtual('fullName').
get(function() { return `${this.firstName} ${this.lastName}`; }).
set(function(v) {
// `v` is the value being set, so use the value to set
// `firstName` and `lastName`.
const firstName = v.substring(0, v.indexOf(' '));
const lastName = v.substring(v.indexOf(' ') + 1);
this.set({ firstName, lastName });
});
const User = mongoose.model('User', userSchema);
const doc = new User();
// Vanilla JavaScript assignment triggers the setter
doc.fullName = 'Jean-Luc Picard';
doc.fullName; // 'Jean-Luc Picard'
doc.firstName; // 'Jean-Luc'
doc.lastName; // 'Picard'

Can we return a string or object in grapqhl while resolving?

I wanted to check whether the user exists in database ... if user exists in the database then send
type user{
name
email
password
username
}
or if user doesn't exist in database then send a string which tells "user doesn't exists in database"
like.... if I am writing tyepDefs
type Query{
show_data(username: String!): #if user exists then# ***user!*** or #if user doesnot exists then# ***String!***
How to make such type of resolvers and typeDefs ?
You can create a new type to use in your query:
type UserPayload {
state: String! # success or other value
user: User # if state was not success this must be null
}
Then use that type directly by your query like this:
type Query{
show_data(username: String!):UserPayload
}

Remove generated string from Mongoose schema with custom validation

I have a schema with a custom validation.
const schema = new mongoose.Schema({
username: {
type: String,
required: true,
validate: {
validator: /^[a-zA-Z0-9_]{3,16}$/,
message: "Usernames must be 3 to 16 characters long and contain only alphanumeric characters and underscores (_)."
},
},
// ...other things
});
However, the validation message comes out like this when I type an invalid username:
User validation failed: username: Usernames must be 3 to 16 characters long and contain only alphanumeric characters and underscores (_).
How do I get rid of the part of the string at the start that says User validation failed: username: ?
The format is embedded into the ValidationError class. Short of monkey patching that class, I can't see a way to easily change the format.
One option could be to run validation before being thrown by the model:
const user = new User({ username: 'ab' })
const error = user.validateSync()
console.log(error.errors['username'].message)
Or handle ValidationError when caught:
try {
const user = new User({ username: 'ab' })
await user.save()
} catch (error) {
if (error instanceOf mongoose.Document.ValidationError ) {
console.log(error.errors['username'].message)
}
}
To get rid of the initial string , you could simply use a split method on the string returned before displaying it. Here is a sample code:
let stringa = "User validation failed: username: Usernames must be 3 to 16 characters long and contain only alphanumeric characters and underscores (_)."; //replace this with error message
let stringb = (stringa.split(":")[2]);
console.log(stringb);//This displays the needed output string with Usernames
Your error object has another nested object called properties that has a field called message.
(example: properties.message) This gives you the exact string you wrote in the mongoose schema

How to use ramda mergeRight in Typescript and respect interface definitions

I'm trying to make a copy of an object and change properties using Rambda's mergeRight function. The problem is it allows me to merge in properties that do not exist in the interface definition.
import {mergeRight} from "ramda";
export interface User {
readonly userId: string
readonly username: string
}
const user: User = {
userId: "12345",
username: "SomeUser"
}
//I want this to be a compile time error, because "something" is not a property of User interface
const updatedUser: User = mergeRight(user, {something: "3"})
Is there any way I can ensure that the properties I am merging are part of the User type, without having to specify an entire new User object (thus defeating the advantage of mergeRight)? This would prevent a simple typo from causing a runtime error that is difficult to debug.
Ideally I would like Typescript to detect this at compile time
To filter out keys that are not part of user, use R.pick to take just keys that exist in User from the new object.
This will only effect the root level of the object, and not deeper mismatches.
const { pick, keys, mergeDeepRight } = R
const user = {
userId: "12345",
username: "SomeUser"
}
const getUserKeys = pick(keys(user))
//I want this to be an error, because "something" is not a property of User interface
const updatedUser = mergeDeepRight(user, getUserKeys({
something: "3"
}))
console.log(updatedUser)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.27.0/ramda.js"></script>
It seems that simply casting the anonymous object as User will give the error I want. That's good enough for my use case.
//This causes a compile time error
const updatedUser: User = mergeRight(user, {something: "3"} as User)
//This does not
const updatedUser2: User = mergeRight(user, {userId: "3"} as User)

NodeJs GraphQL enum type value as dynamic

https://launchpad.graphql.com/9qvqz3v5r
Here is my example graphQL Schema. i am trying to use enum type. How do i get enum values from backend and give it into schema?
// Construct a schema, using GraphQL schema language
const typeDefs = `
type User {
userId: Int
firstName: String
lastName: String
pincode:String
state:String
country:String
}
type Query {
hello: String
user: User
}
type CreateUserLoad {
user: User
}
enum Role {
writer
reader
author
admin
superAdmin
}
type Mutation{
createUser(firstName: String, lastName: String, role: Role): User
}
`;
I want to populate enum Role value from dynamic variable as
const roleData = ['writer','reader','author','admin','superAdmin'];
Can anyone help me?
You can simply use string interpolation:
// Construct a schema, using GraphQL schema language
const typeDefs = `
type User {
userId: Int
firstName: String
lastName: String
pincode:String
state:String
country:String
}
type Query {
hello: String
user: User
}
type CreateUserLoad {
user: User
}
enum Role { ${roles.join(' ')} }
type Mutation{
createUser(firstName: String, lastName: String, role: Role): User
}
`;
In fact, on every incoming grahpql query you have to pass the parsed schema to the graphql server, so you can even change it for every request. In that case, it would be better to change the object representation that the schema parsing returned.
For creating enum types directly, say you have an array of values userRoles and want a RolesEnum type, then you can create it like so:
const roleValues = {}
for (const value of userRoles) {
roleValues[value] = {value}
}
const RolesEnum = new GraphQLEnumType({
name: 'UserRoles',
values: roleValues,
})
you can then assign that directly as a type in your schema.
If your enum values are loaded from a database or any other back-end source, or if the enum list is dynamic, then you can't have a static enum definition in your schema.
The biggest problem with setting enums dynamically is that your schema is meant to be a contract between back-end and front-end and is not suppose to be altered.
If you are going to use your role as an arbitrary string then define it as such!
type Mutation {
createUser(firstName: String, lastName: String, role: String): User
}
The only difference here would be that your resolver will have to check if the role exists, which is what graphql previously did for you when you were using an enum.
Alternatively
If the role is used on a lot of queries / mutations, you can define a scalar Role and in the resolved for the scalar you can check if the role exists and simply throw an error if it doesn't.
In this case your mutation would look the same as if you had a dynamic enum Role, but you will not need to alter the schema at all.
type Mutation {
createUser(firstName: String, lastName: String, role: Role): User
}
To add dynamic enums along with documentation string using string interpolation.
Example: I have a list of countries and their ISO2 Codes
const countryData = [
{name:'India', code: 'IN'},
{name:'Afghanistan', code: 'AF'},
{name:'Algeria', code: 'DZ'},
{name: 'Ireland', code: 'IE'
];
const countryCodes = countryData.flatMap(country => [
`"${country.name}"`,
country.code
]);
Without using Array.join()
enum CountryCode { ${countryCodes} }

Resources