mirror of
https://github.com/vercel/commerce.git
synced 2025-05-19 07:56:59 +00:00
153 lines
3.4 KiB
JavaScript
153 lines
3.4 KiB
JavaScript
const fs = require('fs')
|
|
const os = require('os')
|
|
const path = require('path')
|
|
|
|
const { lockSync, unlockSync, checkSync, check } = require("proper-lockfile")
|
|
|
|
require("dotenv").config({
|
|
path: `.env.${process.env.NODE_ENV}`,
|
|
})
|
|
|
|
const sleep = (ms) => {
|
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
}
|
|
|
|
|
|
const getFilePath = ({ options, itemType, languageCode, itemID }) => {
|
|
|
|
const fileName = `${itemID}.json`;
|
|
return path.join(options.rootPath, languageCode, itemType, fileName);
|
|
}
|
|
|
|
const saveItem = async ({ options, item, itemType, languageCode, itemID }) => {
|
|
|
|
let filePath = getFilePath({ options, itemType, languageCode, itemID });
|
|
|
|
let dirPath = path.dirname(filePath);
|
|
|
|
|
|
if (!fs.existsSync(dirPath)) {
|
|
fs.mkdirSync(dirPath, { recursive: true });
|
|
}
|
|
|
|
let json = JSON.stringify(item);
|
|
fs.writeFileSync(filePath, json);
|
|
}
|
|
|
|
const deleteItem = async ({ options, itemType, languageCode, itemID }) => {
|
|
|
|
let filePath = getFilePath({ options, itemType, languageCode, itemID });
|
|
|
|
if (fs.existsSync(filePath)) {
|
|
fs.unlinkSync(filePath);
|
|
}
|
|
|
|
}
|
|
|
|
const mergeItemToList = async ({ options, item, languageCode, itemID, referenceName, definitionName }) => {
|
|
|
|
let contentList = await getItem({ options, itemType: "list", languageCode, itemID: referenceName });
|
|
|
|
if (contentList == null) {
|
|
//initialize the list
|
|
contentList = [item];
|
|
} else {
|
|
//replace the item...
|
|
const cIndex = contentList.findIndex((ci) => {
|
|
return ci.contentID === itemID;
|
|
});
|
|
|
|
if (item.properties.state === 3) {
|
|
//*** deleted item (remove from the list) ***
|
|
if (cIndex >= 0) {
|
|
//remove the item
|
|
contentList.splice(cIndex, 1);
|
|
}
|
|
|
|
} else {
|
|
//*** regular item (merge) ***
|
|
if (cIndex >= 0) {
|
|
//replace the existing item
|
|
contentList[cIndex] = item;
|
|
} else {
|
|
//and it to the end of the
|
|
contentList.push(item);
|
|
}
|
|
}
|
|
}
|
|
|
|
await saveItem({ options, item: contentList, itemType: "list", languageCode, itemID: referenceName });
|
|
}
|
|
|
|
const getItem = async ({ options, itemType, languageCode, itemID }) => {
|
|
let filePath = getFilePath({ options, itemType, languageCode, itemID });
|
|
|
|
if (!fs.existsSync(filePath)) return null;
|
|
|
|
let json = fs.readFileSync(filePath, 'utf8');
|
|
return JSON.parse(json);
|
|
}
|
|
|
|
const clearItems = async ({ options }) => {
|
|
fs.rmdirSync(options.rootPath, { recursive: true })
|
|
}
|
|
|
|
const waitOnLock = async (lockFile) => {
|
|
|
|
while (await check(lockFile)) {
|
|
await sleep(100)
|
|
}
|
|
|
|
}
|
|
|
|
const mutexLock = async () => {
|
|
|
|
|
|
const dir = os.tmpdir();
|
|
const lockFile = `${dir}/${"agility-sync"}.mutex`
|
|
if (! fs.existsSync(lockFile)) {
|
|
fs.writeFileSync(lockFile, "agility-sync");
|
|
}
|
|
|
|
//THE LOCK IS ALREADY HELD - WAIT UP!
|
|
await waitOnLock(lockFile)
|
|
|
|
try {
|
|
return lockSync(lockFile)
|
|
} catch (err) {
|
|
if (`${err}`.indexOf("Lock file is already being held") !== -1) {
|
|
|
|
//this error happens when 2 processes try to get a lock at the EXACT same time (very rare)
|
|
await sleep(100)
|
|
await waitOnLock(lockFile)
|
|
|
|
try {
|
|
return lockSync(lockFile)
|
|
} catch (e2) {
|
|
if (`${err}`.indexOf("Lock file is already being held") !== -1) {
|
|
|
|
//this error happens when 2 processes try to get a lock at the EXACT same time (very rare)
|
|
await sleep(100)
|
|
await waitOnLock(lockFile)
|
|
return lockSync(lockFile)
|
|
}
|
|
}
|
|
}
|
|
|
|
throw Error("The mutex lock could not be obtained.")
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
module.exports = {
|
|
saveItem,
|
|
deleteItem,
|
|
mergeItemToList,
|
|
getItem,
|
|
clearItems,
|
|
mutexLock
|
|
} |