How to add a date to a prisma typescript form? - prisma

I am trying to figure out how to post a date to a prisma database.
I have a prisma.schema which has a createdAt field as follows:
createdAt DateTime #default(now()) #db.Timestamptz(6)
I made a model with a date field in it as follows:
#Field()
createdAt: Date;
And a create.input.ts with a similar field:
#IsNotEmpty()
#Field()
createdAt: Date;
then, in the form, I'm trying to add the createdAt date as the date the form is submitted, as follows:
return form.handler(() => createIssueGroup({ variables: { data: { ...data, createdAt: Date.now() } } })),
However, I get an error that says type number is not assignable to type string. I don't think I'm using a string in any of the date fields.
How can I post a date to prisma?

From your schema definition,
createdAt DateTime #default(now()) #db.Timestamptz(6)
The date will be automatically generated due to the now() method you specified in #default(). You don't need to pass a date to the database as that will be handled for you by Prisma. See the docs for more information on using now() and defining a default value.

Related

How to update document with specific version

I have a use case where my function first gets a user record, does some work on it and then updates it. To guarantee correct operation, I need to ensure that user record was not updated while such work is being done. Typically, I would do this by adding version to my user model, thus I get current version and update based on this exact version (auto incrementing it with each update), however I am getting a strange uniqueness error that I am not able to figure out:
User model
model User {
uid String #id #default(uuid())
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
version Int #default(0)
email String #unique
}
Update opperation
prisma.user.update({
where: { uid, version },
data: { ...newData, version: { increment: 1 } }
})
Version is highlighted with following error
Type '{ uid: string; version: number; }' is not assignable to type
'UserWhereUniqueInput'. Object literal may only specify known
properties, and 'version' does not exist in type
'UserWhereUniqueInput'.ts(2322)
It's because you need a unique clause to use a where clause on a simple update.
Prisma ask you to give it a unique contraint for this type of update, like for the where clause in a findUnique. Currently you unique constraint is on the email field
Here you have 2 solutions
The good practice?
Add a unique constraint between uid and version
model User {
uid String #id #default(uuid())
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
version Int #default(0)
email String #unique
// new unique constraint
##unique([uid, version])
}
and then you can do your update with the new unique constraint
prisma.user.update({
where: { uid_version: { uid, version } },
data: { ...newData, version: { increment: 1 } }
})
Easy win
If you want, you can also do an updateMany that will not need a unique constraint to filter
prisma.user.updateMany({
where: { uid, version },
data: { ...newData, version: { increment: 1 } }
})

Save Date.now() to timestamp column but get date/time field value out of range

My project (NestJS with TypeScript) is using TypeOrm on PostgreSQL database.
My table has a column (in migration file):
new TableColumn({
name: 'managed_at',
type: 'timestamp',
isNullable: true,
}),
Associated field in entity class:
#Column({ type: 'timestamp', nullable: true })
managedAt: Date | null;
I would like the column managed_at holds value of date and time.
If I save a data to the table with:
import { Repository } from 'typeorm';
...
// repo is the Repository of typeorm
repo.update(
{ managedAt: Date.now() }
);
I get error:
QueryFailedError: date/time field value out of range: "1651495656811"
How to solve this problem that using Date.now() and hold value of data and time?
import { Repository } from 'typeorm';
...
// repo is the Repository of typeorm
repo.update(
{ managedAt: new Date() }
);
Change Date.now() -> new Date().
You need to save Date type data to column in timestamp type.
Btw, you can add this in your entity class.
It will update column before update data.
#BeforeUpdate()
updateManagedAt(): void {
this.managedAt = new Date();
}
The static Date.now() method returns the number of milliseconds elapsed since January 1, 1970 00:00:00 UTC, as per documentation here Date.now().
Whereas valid input for the time stamp types consists of the concatenation of a date and a time, followed by an optional time zone (if you are using timestamptz type instead of timestamp type), followed by an optional AD or BC. (Alternatively, AD/BC can appear before the time zone, but this is not the preferred ordering.
You can read more about Date/Time types in pgSQL here.
In your case, you can do it like this
repo.update({ managedAt: (new Date()).toISOString() });
You'd use toISOString for sharing a date with another machine or process.

Increment a field to a unique integer when a field updates in Prisma

In my Prisma schema, I have a model that looks like this:
model Document {
id String #id #default(uuid())
createdAt DateTime #default(now())
updatedAt DateTime #updatedAt
draft Boolean #default(true)
publishedDocumentNumber Int? #unique()
text String?
}
When each document is created, it is in draft mode with the value set to true. It does not have a publishedDocumentNumber until it is officially published. When I publish a document, I will update the draft value like this:
prisma.draft.update({
where: {
id: req.body.id,
},
data: {
draft: false,
}
});
Since this document is no longer a draft, I want to safely auto-increment the publishedDocumentNumber value to the previous published document's publishedDocumentNumber value + 1. I don't want to do a prisma.document.count since I could accidentally run into a collision if two documents are publish simultaneously (race condition), and they have to be unique.
Is there a better way to safely do this?
Try using serial or smallserial as described in the documentation

Persisting time with timezone offset in mongodb with nestjs

I have a nestjs application which has a very date heavy schema.
According to my understanding date is stored in mongo without timezone. My API accepts time in ISO format with timezone offset.
Inserting following object {"date": "2009-06-30T18:30:00+11:00"}
will result in following document in the mongo database {date: ISODate('2009-06-30T07:30:00.000Z'), _id: "..."}
So the timezone offset is lost.
Is there an elegant way to keep the timezone offset and deliver the ISO string with the same offset on an GET request? Maybe make use of the class-transformer and store the offset in a separate property? If yes, how?
Here are the involved classes. (There is a dedicated ItemDto for GET requests which is not shown here.)
Dto:
export class CreateItemDto {
// Some other props are here
/**
* Date of this Information.
* #example "1900-01-01T05:00:00.000+05:00"
*/
#IsNotEmpty()
#IsDate()
#Type(() => Date)
date: Date;
}
Schema:
export class ItemSchema {
// Some other props are here
#Prop({ type: Date, required: true })
date!: Date;
}
In many cases the client application will convert and display the time in current local time zone, no matter in which time zone the timestamp was inserted.
If this is not sufficient for you then you have to store the time zone information in a separate field along with the actual timestamp.

Apollo/GraphQL: Field Type to Use for Timestamp?

I'm storing a value to a postgres field that is of type timestamp with time zone. I was defining the field as an int in my Apollo schema, but I'm getting this error message in the resolver:
column "apptDateTime" is of type timestamp with time zone but expression is of type integer
Looking up GraphQL data types, I don't yet see any type that is cited as corresponding to a field of type timestamp.
What's the correct field type to use in the Apollo schema for a field that is of type timestamp in the database?
I find this way to work with input in forms, needed convert from client (input form) to the server, and from the server to client (input form)
Graphql:
updatedAt: String
Sequelize:
updatedAt: { type: Sequelize.DATE },
Postgresql:
"createdAt" timestamp(6) with time zone DEFAULT now(),
Value transform to the Server:
value = dateToISO(value);
Value transform to the Client:
if ( isNil(value) ) {
value = '';
} else {
value = value.toLocaleDateString() +' '+ value.toLocaleTimeString();
}
the helpers:
let dateToISO = function (dateString) {
if (!dateString) {
return null;
}
let p = dateString.split(/\D/g);
/* It's up your date on input in this case come from DD-MM-YYYY
for MM-DD-YYY use: return [p[1], p[2], p[0]].join('-'); */
return [p[2], p[1], p[0]].join('-');
};
I got my mutation working that includes a field of type Timestamp with Time Zone. I did it by changing the schema for my apptDateTime field from Int to String, and passing in an ISO string. Sequelize and Postgres took care of changing it into a field of type Timestamp with Time Zone.
Update 2021:
Here's what I'm using these days.
Sequelize:
timeOfNonce: {type: Sequelize.DATE}
Schema:
scalar DATETIME
.....
timeOfNonce: DATETIME
These days I let Sequelize define my SQL tables via:
const deleteAllData_fromThisModel = false;
const alterThisTableToMatchDBConnectorsModel = true;
myDataModel.sync({force: deleteAllData_fromThisModel,
alter: alterThisTableToMatchDBConnectorsModel}).then(err => {
console.log('myDataModel has been synced')
}).catch(err => {
throw err
});