Skip to content

Commit

Permalink
use lists and maps for ecommerce instead of JSON string
Browse files Browse the repository at this point in the history
  • Loading branch information
vkarpov15 committed Nov 14, 2024
1 parent c4f5f4e commit 31a0907
Show file tree
Hide file tree
Showing 4 changed files with 100 additions and 43 deletions.
64 changes: 35 additions & 29 deletions netlify-functions-ecommerce/models.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,20 @@ module.exports.Product = Product;

const orderSchema = new mongoose.Schema({
items: {
type: String,
get(v) {
return v == null ? v : JSON.parse(v);
},
set(v) {
if (v == null) {
return v;
// `items` is stored as an array of JSON strings for compatibility with Data API tables, which do not
// support lists of objects currently.
type: [{
type: String,
get(v) {
return v == null ? v : JSON.parse(v);
},
set(v) {
if (v == null) {
return v;
}
return typeof v === 'string' ? v : JSON.stringify(v);
}
return typeof v === 'string' ? v : JSON.stringify(v);
}
}]
},
total: {
type: Number,
Expand All @@ -34,16 +38,9 @@ const orderSchema = new mongoose.Schema({
type: String
},
paymentMethod: {
type: String,
get(v) {
return v == null ? v : JSON.parse(v);
},
set(v) {
if (v == null) {
return v;
}
return typeof v === 'string' ? v : JSON.stringify(v);
}
id: String,
brand: String,
last4: String
}
}, { versionKey: false });

Expand All @@ -53,16 +50,20 @@ module.exports.Order = Order;

const cartSchema = new mongoose.Schema({
items: {
type: String,
get(v) {
return v == null ? v : JSON.parse(v);
},
set(v) {
if (v == null) {
return v;
// `items` is stored as an array of JSON strings for compatibility with Data API tables, which do not
// support lists of objects currently.
type: [{
type: String,
get(v) {
return v == null ? v : JSON.parse(v);
},
set(v) {
if (v == null) {
return v;
}
return typeof v === 'string' ? v : JSON.stringify(v);
}
return typeof v === 'string' ? v : JSON.stringify(v);
}
}]
},
orderId: { type: mongoose.ObjectId, ref: 'Order' },
total: Number,
Expand All @@ -73,7 +74,12 @@ cartSchema.virtual('numItems').get(function numItems() {
if (this.items == null) {
return 0;
}
const items = typeof this.items === 'string' ? JSON.parse(this.items) : this.items;
const items = this.items.map(item => {
if (typeof item === 'string') {
return JSON.parse(item);
}
return item;
});
return items.reduce((sum, item) => sum + item.quantity, 0);
});

Expand Down
19 changes: 14 additions & 5 deletions netlify-functions-ecommerce/netlify/functions/addToCart.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,13 +30,22 @@ const handler = async(event) => {
}
for (const product of event.body.items) {
const exists = cart.items?.find(item => item?.productId?.toString() === product?.productId?.toString());
if (!exists) {
if (products.find(p => product?.productId?.toString() === p?._id?.toString())) {
cart.items = [...(cart.items || []), product];
}
if (!exists && products.find(p => product?.productId?.toString() === p?._id?.toString())) {
cart.items = [
...cart.items,
product
];
} else {
const items = [];
for (let i = 0; i < cart.items.length; ++i) {
const item = cart.items[i];
if (item?.productId?.toString() === product?.productId?.toString()) {
continue;
}
items.push(item);
}
cart.items = [
...cart.items.filter(item => item?.productId?.toString() !== product?.productId?.toString()),
...items,
{ productId: product.productId, quantity: exists.quantity + product.quantity }
];
}
Expand Down
24 changes: 18 additions & 6 deletions netlify-functions-ecommerce/seed.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,23 +10,35 @@ async function createProducts() {
await connect();

if (process.env.DATA_API_TABLES) {
// @ts-ignore
await mongoose.connection.runCommand({
dropTable: {
name: 'products'
}
}).catch(err => {
if (err.errors && err.errors.length === 1 && err.errors[0].errorCode === 'CANNOT_DROP_UNKNOWN_TABLE') {
return;
}
throw err;
});
// @ts-ignore
await mongoose.connection.runCommand({
dropTable: {
name: 'orders'
}
}).catch(err => {
if (err.errors && err.errors.length === 1 && err.errors[0].errorCode === 'CANNOT_DROP_UNKNOWN_TABLE') {
return;
}
throw err;
});
// @ts-ignore
await mongoose.connection.runCommand({
dropTable: {
name: 'carts'
}
}).catch(err => {
if (err.errors && err.errors.length === 1 && err.errors[0].errorCode === 'CANNOT_DROP_UNKNOWN_TABLE') {
return;
}
throw err;
});

await mongoose.connection.runCommand({
Expand All @@ -53,8 +65,8 @@ async function createProducts() {
_id: { type: 'text' },
total: { type: 'decimal' },
name: { type: 'text' },
paymentMethod: { type: 'text' },
items: { type: 'text' }
paymentMethod: { type: 'map', keyType: 'text', valueType: 'text' },
items: { type: 'list', valueType: 'text' }
}
}
}
Expand All @@ -66,7 +78,7 @@ async function createProducts() {
primaryKey: '_id',
columns: {
_id: { type: 'text' },
items: { type: 'text' },
items: { type: 'list', valueType: 'text' },
orderId: { type: 'text' },
total: { type: 'decimal' },
stripeSessionId: { type: 'text' }
Expand Down
36 changes: 33 additions & 3 deletions netlify-functions-ecommerce/test/setup.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,36 @@ before(async function() {
await connect();

if (process.env.DATA_API_TABLES) {
await mongoose.connection.runCommand({
dropTable: {
name: 'products'
}
}).catch(err => {
if (err.errors && err.errors.length === 1 && err.errors[0].errorCode === 'CANNOT_DROP_UNKNOWN_TABLE') {
return;
}
throw err;
});
await mongoose.connection.runCommand({
dropTable: {
name: 'orders'
}
}).catch(err => {
if (err.errors && err.errors.length === 1 && err.errors[0].errorCode === 'CANNOT_DROP_UNKNOWN_TABLE') {
return;
}
throw err;
});
await mongoose.connection.runCommand({
dropTable: {
name: 'carts'
}
}).catch(err => {
if (err.errors && err.errors.length === 1 && err.errors[0].errorCode === 'CANNOT_DROP_UNKNOWN_TABLE') {
return;
}
throw err;
});
await mongoose.connection.runCommand({
createTable: {
name: 'products',
Expand All @@ -39,8 +69,8 @@ before(async function() {
_id: { type: 'text' },
total: { type: 'decimal' },
name: { type: 'text' },
paymentMethod: { type: 'text' },
items: { type: 'text' }
paymentMethod: { type: 'map', keyType: 'text', valueType: 'text' },
items: { type: 'list', valueType: 'text' }
}
}
}
Expand All @@ -52,7 +82,7 @@ before(async function() {
primaryKey: '_id',
columns: {
_id: { type: 'text' },
items: { type: 'text' },
items: { type: 'list', valueType: 'text' },
orderId: { type: 'text' },
total: { type: 'decimal' },
stripeSessionId: { type: 'text' }
Expand Down

0 comments on commit 31a0907

Please sign in to comment.