I would like to add an asset along with an entry. I'm using a form to enter some data and upload an image all in one API call. I'm using cloudinary to store images, but Contentful-Management is giving me a 409 status code and a 'Version Mismatch' error.
These are the steps I'm taking below (add any if you've seen a step I've overlooked, it's much appreciated)
#1. Get space by space id
#2. Get environment
#3. Create Entry
#4. Create a new asset
#5. Assign uploaded image as an entry field
'data' is all the data I need to make a post for a properting posting, and the uploadHref is the link to a single image from Cloudinary.
const postProperty = (data: Partial<Property>, uploadHref: string) => {
const SPACE_ID = process.env.NEXT_CONTENTFUL_SPACE_ID;
const client = createClient({
accessToken: process.env.NEXT_CONTENTFUL_PERSONAL_ACCESS_TOKEN as string,
});
// # 1 Get space by space id
client.getSpace(SPACE_ID).then((space: Space) => {
// # 2 Get environment
space.getEnvironment("master").then(async (environment: Environment) => {
// # 3 Create Entry
environment
.createEntry("propertyListings", {
fields: {
id: {
"en-US": faker.datatype.number(4) + "-" + data.streetAddress,
},
firstName: {
"en-US": data.firstName,
},
lastName: {
"en-US": data.lastName,
},
email: {
"en-US": data.email,
},
phone: {
"en-US": data.phone,
},
price: {
"en-US": data.price,
},
streetAddress: {
"en-US": data.streetAddress,
},
city: {
"en-US": data.city,
},
state: {
"en-US": data.state,
},
zipcode: {
"en-US": data.zipcode,
},
latitude: {
"en-US": Number(data.latitude as number),
},
longitude: {
"en-US": Number(data.longitude as number),
},
bedrooms: {
"en-US": data.bedrooms,
},
bathrooms: {
"en-US": data.bathrooms,
},
sqft: {
"en-US": Number(data.sqft),
},
carSpaces: {
"en-US": data.carSpaces,
},
type: {
"en-US": data.type,
},
datePosted: {
"en-US": data.datePosted,
},
petFriendly: {
"en-US": data.petFriendly,
},
images: {
"en-US": [],
},
},
})
.then(entry => {
entry.publish();
return environment.getEntry(entry.sys.id)
})
.then(function (entry: Entry) {
// #4 Create a new asset in my Contentful media section
environment
.createAssetWithId(faker.datatype.number(4).toString(), {
fields: {
title: {
"en-US": data.streetAddress,
},
file: {
"en-US": {
contentType: "image/jpeg",
fileName: data.streetAddress + ".jpeg",
upload: uploadHref,
},
},
},
})
.then(async (asset) => await asset.processForAllLocales())
.then(async (asset) => await asset.publish())
.then(function (asset) {
// # 5 Assign uploaded image as an entry field
entry.fields["images"]["en-US"] = {
sys: {
id: asset.sys.id,
linkType: "Asset",
type: "Link"
},
};
return entry.update()
})
.then(entry => entry.publish())
console.log('Entry object value: ', entry)
return entry.update()
})
.catch(err => console.log("Error Message!: ", err))
});
});
};
Contentful DevRel here. 👋
If you're running into VersionMisMatch
most you are not re-assigning resources after creation or update. Contentful's API responds every write operation with a new entry version, this way it's prevented to overwrite newer data.
I rewrote your example (untested) to reassign returned entry
and asset
objects with the results from the API.
async function createEntryWithAsset() {
const space = await client.getSpace(SPACE_ID);
const environment = await space.getEnvironment("master");
/**
* Entry creation and publish
*/
let entry = await environment.createEntry("propertyListings", {
/* ... */
});
// reassign `entry` to have the latest version number
entry = await entry.publish();
/**
* Asset creation and publish
*/
let asset = await environment.createAssetWithId(
faker.datatype.number(4).toString(),
{
/* ... */
}
);
// reassign `asset` to have the latest version number
asset = await asset.processForAllLocales();
asset = await asset.publish();
/**
* Update entry with new asset
*/
entry.fields["images"]["en-US"] = {
sys: {
id: asset.sys.id,
linkType: "Asset",
type: "Link",
},
};
entry = await entry.update();
entry = await entry.publish();
}
createEntryWithAsset();