local-fake-api
Version:
A simple async local mock API without backend.
143 lines (142 loc) • 5.56 kB
JavaScript
// src/fakeApi/createIndexedDbApi.ts
import { delay, getUuid } from "../utils";
import { db } from "./indexedDb";
export function createIndexedDbApi(tableName, primaryKey) {
// _primaryKey always exists
const _primaryKey = (primaryKey || "id");
// Helper to filter items by key-value pairs
async function filterItems(items, filter) {
if (!filter)
return items;
return items.filter((item) => Object.entries(filter).every(([k, v]) => item[k] === v));
}
// List (ProTable-friendly)
async function list(filter) {
try {
await delay(100);
const table = await db.getTable(tableName, _primaryKey);
const allItems = await table.toArray();
const items = await filterItems(allItems, filter);
return { data: items, total: items.length, success: true };
}
catch (e) {
return { data: [], total: 0, success: false, message: e.message };
}
}
async function get(keyValue, keyName) {
var _a;
try {
const table = await db.getTable(tableName, _primaryKey);
const searchKey = keyName !== null && keyName !== void 0 ? keyName : _primaryKey;
const items = await table.toArray();
const item = (_a = items.find((row) => String(row[searchKey]) === keyValue)) !== null && _a !== void 0 ? _a : null;
return { data: item, success: true };
}
catch (e) {
return { success: false, message: e.message };
}
}
async function create(item, uniqKey) {
try {
await delay(100);
const table = await db.getTable(tableName, _primaryKey);
const actualPk = db.getPrimaryKey(tableName);
// Generate table primary key if missing
const newItem = { ...item };
if (!(actualPk in newItem)) {
newItem[actualPk] = getUuid();
}
const keyToCheck = (uniqKey || actualPk);
// Check uniqueness
const existingRows = await table
.filter((row) => String(row[keyToCheck]) === String(newItem[keyToCheck]))
.toArray();
if (existingRows.length > 0) {
return {
success: false,
message: `Duplicate key '${String(keyToCheck)}': ${newItem[keyToCheck]}`,
};
}
await table.add(newItem);
return { data: newItem, success: true };
}
catch (e) {
return { success: false, message: e.message };
}
}
async function update(keyValue, updates, uniqKey) {
try {
const table = await db.getTable(tableName, _primaryKey);
const keyToUse = uniqKey || _primaryKey;
const allItems = await table.toArray();
let updatedItem = null;
for (const currentItem of allItems) {
if (String(currentItem[keyToUse]) !== keyValue)
continue;
debugger;
// Merge updates
const candidateItem = { ...currentItem, ...updates };
// Check uniqueness against all other items
const duplicateExists = allItems.some((otherItem) => {
return (String(otherItem[keyToUse]) === String(candidateItem[keyToUse]) &&
String(otherItem[_primaryKey]) !== String(currentItem[_primaryKey]));
});
if (duplicateExists) {
throw new Error(`Duplicate key '${String(keyToUse)}': ${candidateItem[keyToUse]}`);
}
await delay(100);
await table.put(candidateItem);
updatedItem = candidateItem;
break; // stop after updating the first matching row
}
return { data: updatedItem, success: true };
}
catch (e) {
return { success: false, message: e.message };
}
}
async function _delete(keyValue, keyName) {
try {
const table = await db.getTable(tableName, _primaryKey);
const searchKey = keyName !== null && keyName !== void 0 ? keyName : _primaryKey;
const items = await table.toArray();
const toDelete = items.find((row) => String(row[searchKey]) === keyValue);
if (toDelete) {
// Use actual table primary key
const actualPk = db.getPrimaryKey(tableName);
await table.delete(toDelete[actualPk]);
}
return { success: true };
}
catch (e) {
return { success: false, message: e.message };
}
}
async function deleteAll(filter) {
try {
const table = await db.getTable(tableName, _primaryKey);
await delay(100);
if (!filter) {
await table.clear();
}
else {
const items = await table.toArray();
const toKeep = items.filter((item) => !Object.entries(filter).every(([k, v]) => item[k] === v));
await table.clear();
await table.bulkPut(toKeep);
}
return { success: true };
}
catch (e) {
return { success: false, message: e.message };
}
}
return {
list,
get,
create,
delete: _delete,
update,
deleteAll,
};
}