#javascript #indexeddb #dexie
Вопрос:
У меня есть Dexie.js база данных с таблицей «Бизнес-слои» в моем приложении React. Я хотел бы убедиться, что типы данных de для кортежей, вставленных в эту таблицу. Я подумал о методической таблице.defineClass() сделал бы это, но это не так. Моя база данных выглядит следующим образом:
import Dexie from 'dexie';
const db = new Dexie('MyDB');
db.version(1).stores({
businessLayers: ' id, layer'
});
const BusinessLayer = db.businessLayers.defineClass({
id: Number,
layer: String,
values: Object
});
export default db;
Я хотел бы сделать невозможным вставку недопустимого типа данных в каждое поле. Я не нашел никакого встроенного метода для этого. Вы знаете кого-нибудь из них? Спасибо!
Ответ №1:
Стол.defineClass() была старой функцией в Dexie 1.x только для завершения кода — никаких принудительных мер. Этот метод должен был устареть. Но необходимая вам функциональность может быть реализована с помощью промежуточного программного обеспечения DBCore или создания/обновления крючков. Промежуточное программное обеспечение DBCore было бы наиболее эффективным решением, поскольку ему не нужно проверять существующие данные.
Ниже приведен полный пример с сухим кодом. Пожалуйста, проверьте и ответьте, работает ли это. Он должен поддерживать строку, число, логическое значение, Массив, объект, набор, карту, ArrayBuffer, Uint8Array и т. Д…. И даже пользовательские классы. Если кто-то хочет сделать пакет из этого кода, пожалуйста, продолжайте! Я думаю, что это может быть хорошим дополнением к декси:
import Dexie from 'dexie';
const db = new Dexie('MyDB');
db.version(1).stores({
businessLayers: ' id, layer'
});
// Use a DBCore middleware "enforceSchema" defined further down...
db.use(
enforceSchema({
businessLayers: {
id: Number,
layer: String,
values: Object
}
}
);
// This is the function that returns the middlware:
function enforceSchema(dbSchema) {
return {
stack: "dbcore",
name: "SchemaEnforcement",
create (downlevelDatabase) {
return {
...downlevelDatabase,
table (tableName) {
const downlevelTable = downlevelDatabase.table(tableName);
const tableSchema = dbSchema[tableName];
if (!tableSchema) return downlevelTable; // No schema for this table.
return {
...downlevelTable,
mutate: req => {
if (req.type === "add" || req.type === "put") {
for (obj of req.values) {
validateSchema(tableName, tableSchema, obj);
}
}
return downlevelTable.mutate(req);
}
}
}
};
}
};
}
function validateSchema(tableName, schema, obj) {
const invalidProp = Object.keys(schema).find(key =>
{
const value = obj[key];
const type = schema[key];
switch (type) {
// Handle numbers, strings and booleans specifically:
case Number: return typeof value !== "number";
case String: return typeof value !== "string";
case Boolean: return typeof value !== "boolean";
// All other types will be supported in the following
// single line:
default: return !(value instanceof type);
}
});
if (invalidProp) {
// Throw exception to abort the transaction and make the
// user get a rejected promise:
throw new TypeError(`Invalid type given for property ${invalidProp} in table ${tableName}. ${schema[invalidProp].name} expected.`);
}
}
Комментарии:
1. Это работает идеально!! Мне просто нужно было внести некоторые минимальные изменения в синтаксис. Большое вам спасибо, это то, что я искал. Я догадывался, что мне нужно было реализовать что-то подобное «вручную», но я не уверен, что смог бы заставить это работать так хорошо. Было бы здорово, если бы Декси поддерживал какой-то тип принуждения, подобный этому.