ra-core
Version:
Core components of react-admin, a frontend Framework for building admin applications on top of REST services, using ES6, React
606 lines • 31.2 kB
JavaScript
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (g && (g = 0, op[0] && (_ = 0)), _) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};
/**
* Extend a dataProvider to execute callbacks before and after read and write calls.
*
* @param {DataProvider} dataProvider The dataProvider to wrap
* @param {ResourceCallbacks[]} handlers An array of ResourceCallbacks
*
* @typedef {Object} ResourceCallbacks
* @property {string} resource The resource name
* @property {AfterCreate} [afterCreate] A callback (or array of callbacks) executed after create
* @property {AfterDelete} [afterDelete] A callback (or array of callbacks) executed after delete
* @property {AfterDeleteMany} [afterDeleteMany] A callback (or array of callbacks) executed after deleteMany
* @property {AfterGetList} [afterGetList] A callback (or array of callbacks) executed after getList
* @property {AfterGetMany} [afterGetMany] A callback (or array of callbacks) executed after getMany
* @property {AfterGetManyReference} [afterGetManyReference] A callback (or array of callbacks) executed after getManyReference
* @property {AfterGetOne} [afterGetOne] A callback (or array of callbacks) executed after getOne
* @property {AfterRead} [afterRead] A callback (or array of callbacks) executed after read (getList, getMany, getManyReference, getOne)
* @property {AfterSave} [afterSave] A callback (or array of callbacks) executed after save (create, update, updateMany)
* @property {AfterUpdate} [afterUpdate] A callback (or array of callbacks) executed after update
* @property {AfterUpdateMany} [afterUpdateMany] A callback (or array of callbacks) executed after updateMany
* @property {BeforeCreate} [beforeCreate] A callback (or array of callbacks) executed before create
* @property {BeforeDelete} [beforeDelete] A callback (or array of callbacks) executed before delete
* @property {BeforeDeleteMany} [beforeDeleteMany] A callback (or array of callbacks) executed before deleteMany
* @property {BeforeGetList} [beforeGetList] A callback (or array of callbacks) executed before getList
* @property {BeforeGetMany} [beforeGetMany] A callback (or array of callbacks) executed before getMany
* @property {BeforeGetManyReference} [beforeGetManyReference] A callback (or array of callbacks) executed before getManyReference
* @property {BeforeGetOne} [beforeGetOne] A callback (or array of callbacks) executed before getOne
* @property {BeforeSave} [beforeSave] A callback (or array of callbacks) executed before save (create, update, updateMany)
* @property {BeforeUpdate} [beforeUpdate] A callback (or array of callbacks) executed before update
* @property {BeforeUpdateMany} [beforeUpdateMany] A callback (or array of callbacks) executed before updateMany
*
* Warnings:
* - As queries issued in the callbacks are not done through react-query,
* any change in the data will not be automatically reflected in the UI.
* - The callbacks are not executed in a transaction. In case of error,
* the backend may be left in an inconsistent state.
* - When calling the API directly using fetch or another client,
* the callbacks will not be executed, leaving the backend in a possibly inconsistent state.
* - If a callback triggers the query it's listening to, this will lead to a infinite loop.
*
* @example
*
* const dataProvider = withLifecycleCallbacks(
* jsonServerProvider("http://localhost:3000"),
* [
* {
* resource: "posts",
* afterRead: async (data, dataProvider, resource) => {
* // rename field to the record
* data.user_id = data.userId;
* return data;
* },
* // executed after create, update and updateMany
* afterSave: async (record, dataProvider, resource) => {
* // update the author's nb_posts
* const { total } = await dataProvider.getList("users", {
* filter: { id: record.user_id },
* pagination: { page: 1, perPage: 1 },
* });
* await dataProvider.update("users", {
* id: user.id,
* data: { nb_posts: total },
* previousData: user,
* });
* return record;
* },
* beforeDelete: async (params, dataProvider, resource) => {
* // delete all comments linked to the post
* const { data: comments } = await dataProvider.getManyReference(
* "comments",
* {
* target: "post_id",
* id: params.id,
* }
* );
* if (comments.length > 0) {
* await dataProvider.deleteMany("comments", {
* ids: comments.map((comment) => comment.id),
* });
* }
* // update the author's nb_posts
* const { data: post } = await dataProvider.getOne("posts", {
* id: params.id,
* });
* const { total } = await dataProvider.getList("users", {
* filter: { id: post.user_id },
* pagination: { page: 1, perPage: 1 },
* });
* await dataProvider.update("users", {
* id: user.id,
* data: { nb_posts: total - 1 },
* previousData: user,
* });
* return params;
* },
* },
* ]
* );
*/
export var withLifecycleCallbacks = function (dataProvider, handlers) {
return __assign(__assign({}, dataProvider), { getList: function (resource, params) {
return __awaiter(this, void 0, void 0, function () {
var newParams, result, _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
newParams = params;
return [4 /*yield*/, applyCallbacks({
name: 'beforeGetList',
params: newParams,
dataProvider: dataProvider,
handlers: handlers,
resource: resource,
})];
case 1:
newParams = _b.sent();
return [4 /*yield*/, dataProvider.getList(resource, newParams)];
case 2:
result = _b.sent();
return [4 /*yield*/, applyCallbacks({
name: 'afterGetList',
params: result,
dataProvider: dataProvider,
handlers: handlers,
resource: resource,
})];
case 3:
result = _b.sent();
_a = result;
return [4 /*yield*/, Promise.all(result.data.map(function (record) {
return applyCallbacks({
name: 'afterRead',
params: record,
dataProvider: dataProvider,
handlers: handlers,
resource: resource,
});
}))];
case 4:
_a.data = _b.sent();
return [2 /*return*/, result];
}
});
});
}, getOne: function (resource, params) {
return __awaiter(this, void 0, void 0, function () {
var newParams, result, _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
newParams = params;
return [4 /*yield*/, applyCallbacks({
name: 'beforeGetOne',
params: newParams,
dataProvider: dataProvider,
handlers: handlers,
resource: resource,
})];
case 1:
newParams = _b.sent();
return [4 /*yield*/, dataProvider.getOne(resource, newParams)];
case 2:
result = _b.sent();
return [4 /*yield*/, applyCallbacks({
name: 'afterGetOne',
params: result,
dataProvider: dataProvider,
handlers: handlers,
resource: resource,
})];
case 3:
result = _b.sent();
_a = result;
return [4 /*yield*/, applyCallbacks({
name: 'afterRead',
params: result.data,
dataProvider: dataProvider,
handlers: handlers,
resource: resource,
})];
case 4:
_a.data = _b.sent();
return [2 /*return*/, result];
}
});
});
}, getMany: function (resource, params) {
return __awaiter(this, void 0, void 0, function () {
var newParams, result, _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
newParams = params;
return [4 /*yield*/, applyCallbacks({
name: 'beforeGetMany',
params: newParams,
dataProvider: dataProvider,
handlers: handlers,
resource: resource,
})];
case 1:
newParams = _b.sent();
return [4 /*yield*/, dataProvider.getMany(resource, newParams)];
case 2:
result = _b.sent();
return [4 /*yield*/, applyCallbacks({
name: 'afterGetMany',
params: result,
dataProvider: dataProvider,
handlers: handlers,
resource: resource,
})];
case 3:
result = _b.sent();
_a = result;
return [4 /*yield*/, Promise.all(result.data.map(function (record) {
return applyCallbacks({
name: 'afterRead',
params: record,
dataProvider: dataProvider,
handlers: handlers,
resource: resource,
});
}))];
case 4:
_a.data = _b.sent();
return [2 /*return*/, result];
}
});
});
}, getManyReference: function (resource, params) {
return __awaiter(this, void 0, void 0, function () {
var newParams, result, _a;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
newParams = params;
return [4 /*yield*/, applyCallbacks({
name: 'beforeGetManyReference',
params: newParams,
dataProvider: dataProvider,
handlers: handlers,
resource: resource,
})];
case 1:
newParams = _b.sent();
return [4 /*yield*/, dataProvider.getManyReference(resource, newParams)];
case 2:
result = _b.sent();
return [4 /*yield*/, applyCallbacks({
name: 'afterGetManyReference',
params: result,
dataProvider: dataProvider,
handlers: handlers,
resource: resource,
})];
case 3:
result = _b.sent();
_a = result;
return [4 /*yield*/, Promise.all(result.data.map(function (record) {
return applyCallbacks({
name: 'afterRead',
params: record,
dataProvider: dataProvider,
handlers: handlers,
resource: resource,
});
}))];
case 4:
_a.data = _b.sent();
return [2 /*return*/, result];
}
});
});
}, update: function (resource, params) {
return __awaiter(this, void 0, void 0, function () {
var newParams, _a, result, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
newParams = params;
return [4 /*yield*/, applyCallbacks({
name: 'beforeUpdate',
params: newParams,
dataProvider: dataProvider,
handlers: handlers,
resource: resource,
})];
case 1:
newParams = _c.sent();
_a = newParams;
return [4 /*yield*/, applyCallbacks({
name: 'beforeSave',
params: newParams.data,
dataProvider: dataProvider,
handlers: handlers,
resource: resource,
})];
case 2:
_a.data = _c.sent();
return [4 /*yield*/, dataProvider.update(resource, newParams)];
case 3:
result = _c.sent();
return [4 /*yield*/, applyCallbacks({
name: 'afterUpdate',
params: result,
dataProvider: dataProvider,
handlers: handlers,
resource: resource,
})];
case 4:
result = _c.sent();
_b = result;
return [4 /*yield*/, applyCallbacks({
name: 'afterSave',
params: result.data,
dataProvider: dataProvider,
handlers: handlers,
resource: resource,
})];
case 5:
_b.data = _c.sent();
return [2 /*return*/, result];
}
});
});
}, create: function (resource, params) {
return __awaiter(this, void 0, void 0, function () {
var newParams, _a, result, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
newParams = params;
return [4 /*yield*/, applyCallbacks({
name: 'beforeCreate',
params: newParams,
dataProvider: dataProvider,
handlers: handlers,
resource: resource,
})];
case 1:
newParams = _c.sent();
_a = newParams;
return [4 /*yield*/, applyCallbacks({
name: 'beforeSave',
params: newParams.data,
dataProvider: dataProvider,
handlers: handlers,
resource: resource,
})];
case 2:
_a.data = _c.sent();
return [4 /*yield*/, dataProvider.create(resource, newParams)];
case 3:
result = _c.sent();
return [4 /*yield*/, applyCallbacks({
name: 'afterCreate',
params: result,
dataProvider: dataProvider,
handlers: handlers,
resource: resource,
})];
case 4:
result = _c.sent();
_b = result;
return [4 /*yield*/, applyCallbacks({
name: 'afterSave',
params: result.data,
dataProvider: dataProvider,
handlers: handlers,
resource: resource,
})];
case 5:
_b.data = _c.sent();
return [2 /*return*/, result];
}
});
});
}, delete: function (resource, params) {
return __awaiter(this, void 0, void 0, function () {
var newParams, result;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
newParams = params;
return [4 /*yield*/, applyCallbacks({
name: 'beforeDelete',
params: newParams,
dataProvider: dataProvider,
handlers: handlers,
resource: resource,
})];
case 1:
newParams = _a.sent();
return [4 /*yield*/, dataProvider.delete(resource, newParams)];
case 2:
result = _a.sent();
return [4 /*yield*/, applyCallbacks({
name: 'afterDelete',
params: result,
dataProvider: dataProvider,
handlers: handlers,
resource: resource,
})];
case 3:
result = _a.sent();
return [2 /*return*/, result];
}
});
});
}, updateMany: function (resource, params) {
return __awaiter(this, void 0, void 0, function () {
var newParams, _a, result, afterSaveHandlers, records;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
newParams = params;
return [4 /*yield*/, applyCallbacks({
name: 'beforeUpdateMany',
params: newParams,
dataProvider: dataProvider,
handlers: handlers,
resource: resource,
})];
case 1:
newParams = _b.sent();
_a = newParams;
return [4 /*yield*/, applyCallbacks({
name: 'beforeSave',
params: newParams.data,
dataProvider: dataProvider,
handlers: handlers,
resource: resource,
})];
case 2:
_a.data = _b.sent();
return [4 /*yield*/, dataProvider.updateMany(resource, newParams)];
case 3:
result = _b.sent();
return [4 /*yield*/, applyCallbacks({
name: 'afterUpdateMany',
params: result,
dataProvider: dataProvider,
handlers: handlers,
resource: resource,
})];
case 4:
result = _b.sent();
afterSaveHandlers = handlers.filter(function (h) {
return (h.resource === resource || h.resource === '*') &&
h.afterSave;
});
if (!(afterSaveHandlers.length > 0)) return [3 /*break*/, 7];
return [4 /*yield*/, dataProvider.getMany(resource, {
//@ts-ignore
ids: result.data,
})];
case 5:
records = (_b.sent()).data;
return [4 /*yield*/, Promise.all(records.map(function (record) {
return applyCallbacks({
name: 'afterSave',
params: record,
dataProvider: dataProvider,
handlers: handlers,
resource: resource,
});
}))];
case 6:
_b.sent();
_b.label = 7;
case 7: return [2 /*return*/, result];
}
});
});
}, deleteMany: function (resource, params) {
return __awaiter(this, void 0, void 0, function () {
var newParams, result;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
newParams = params;
return [4 /*yield*/, applyCallbacks({
name: 'beforeDeleteMany',
params: newParams,
dataProvider: dataProvider,
handlers: handlers,
resource: resource,
})];
case 1:
newParams = _a.sent();
return [4 /*yield*/, dataProvider.deleteMany(resource, newParams)];
case 2:
result = _a.sent();
return [4 /*yield*/, applyCallbacks({
name: 'afterDeleteMany',
params: result,
dataProvider: dataProvider,
handlers: handlers,
resource: resource,
})];
case 3:
result = _a.sent();
return [2 /*return*/, result];
}
});
});
} });
};
/**
* Apply callbacks to the params for the given resource and hook
* @param {DataProvider} dataProvider The dataProvider
* @param {ResourceCallbacks[]} handlers An array of ResourceCallbacks
* @param {string} resource The resource name
* @param {string} hook The hook name (beforeGetList, afterGetOne, etc.)
* @param {U} params The params / result to pass to the callbacks
* @returns {Promise<U>} The params / result after the callbacks have been applied
*/
export var applyCallbacks = function (_a) {
var name = _a.name, params = _a.params, dataProvider = _a.dataProvider, handlers = _a.handlers, resource = _a.resource;
return __awaiter(this, void 0, void 0, function () {
var newParams, handlersToApply, _i, handlersToApply_1, handler, callbacksValue, _b, _c, callback;
return __generator(this, function (_d) {
switch (_d.label) {
case 0:
newParams = params;
handlersToApply = handlers.filter(function (h) { return (h.resource === resource || h.resource === '*') && h[name]; });
_i = 0, handlersToApply_1 = handlersToApply;
_d.label = 1;
case 1:
if (!(_i < handlersToApply_1.length)) return [3 /*break*/, 9];
handler = handlersToApply_1[_i];
callbacksValue = handler[name];
if (!Array.isArray(callbacksValue)) return [3 /*break*/, 6];
_b = 0, _c = callbacksValue !== null && callbacksValue !== void 0 ? callbacksValue : [];
_d.label = 2;
case 2:
if (!(_b < _c.length)) return [3 /*break*/, 5];
callback = _c[_b];
return [4 /*yield*/, callback(newParams, dataProvider, resource)];
case 3:
newParams = _d.sent();
_d.label = 4;
case 4:
_b++;
return [3 /*break*/, 2];
case 5: return [3 /*break*/, 8];
case 6: return [4 /*yield*/, callbacksValue(newParams, dataProvider, resource)];
case 7:
newParams = _d.sent();
_d.label = 8;
case 8:
_i++;
return [3 /*break*/, 1];
case 9: return [2 /*return*/, newParams];
}
});
});
};
//# sourceMappingURL=withLifecycleCallbacks.js.map