Update ReactiveCache call sites to use async/await for Meteor 3.0

Part 3 of ReactiveCache async migration:
- Add await before all ReactiveCache.getX() calls
- Make functions containing ReactiveCache calls async
- Convert forEach/map/filter loops with async callbacks to for...of
- Update model helpers, Meteor methods, JsonRoutes handlers
- Update collection hooks (.before/.after insert/update/remove)
- Update .allow() callbacks to async

Files updated across models/ and server/ directories:
- Model files: cards, boards, lists, swimlanes, activities, users,
  checklists, checklistItems, customFields, attachments, integrations,
  cardComments, settings files, creators, exporters, and more
- Server files: publications, methods, notifications, routes, migrations
This commit is contained in:
Harry Adel 2026-02-01 00:54:38 +02:00
parent 2f6e34c5f5
commit 71eb01e233
81 changed files with 2218 additions and 2148 deletions

View file

@ -174,17 +174,17 @@ UserPositionHistory.helpers({
/**
* Can this change be undone?
*/
canUndo() {
async canUndo() {
// Can undo if the entity still exists
switch (this.entityType) {
case 'card':
return !!ReactiveCache.getCard(this.entityId);
return !!(await ReactiveCache.getCard(this.entityId));
case 'list':
return !!ReactiveCache.getList(this.entityId);
return !!(await ReactiveCache.getList(this.entityId));
case 'swimlane':
return !!ReactiveCache.getSwimlane(this.entityId);
return !!(await ReactiveCache.getSwimlane(this.entityId));
case 'checklist':
return !!ReactiveCache.getChecklist(this.entityId);
return !!(await ReactiveCache.getChecklist(this.entityId));
case 'checklistItem':
return !!ChecklistItems.findOne(this.entityId);
default:
@ -195,23 +195,23 @@ UserPositionHistory.helpers({
/**
* Undo this change
*/
undo() {
if (!this.canUndo()) {
async undo() {
if (!(await this.canUndo())) {
throw new Meteor.Error('cannot-undo', 'Entity no longer exists');
}
const userId = this.userId;
switch (this.entityType) {
case 'card': {
const card = ReactiveCache.getCard(this.entityId);
const card = await ReactiveCache.getCard(this.entityId);
if (card) {
// Restore previous position
const boardId = this.previousBoardId || card.boardId;
const swimlaneId = this.previousSwimlaneId || card.swimlaneId;
const listId = this.previousListId || card.listId;
const sort = this.previousSort !== undefined ? this.previousSort : card.sort;
Cards.update(card._id, {
$set: {
boardId,
@ -224,11 +224,11 @@ UserPositionHistory.helpers({
break;
}
case 'list': {
const list = ReactiveCache.getList(this.entityId);
const list = await ReactiveCache.getList(this.entityId);
if (list) {
const sort = this.previousSort !== undefined ? this.previousSort : list.sort;
const swimlaneId = this.previousSwimlaneId || list.swimlaneId;
Lists.update(list._id, {
$set: {
sort,
@ -239,10 +239,10 @@ UserPositionHistory.helpers({
break;
}
case 'swimlane': {
const swimlane = ReactiveCache.getSwimlane(this.entityId);
const swimlane = await ReactiveCache.getSwimlane(this.entityId);
if (swimlane) {
const sort = this.previousSort !== undefined ? this.previousSort : swimlane.sort;
Swimlanes.update(swimlane._id, {
$set: {
sort,
@ -252,10 +252,10 @@ UserPositionHistory.helpers({
break;
}
case 'checklist': {
const checklist = ReactiveCache.getChecklist(this.entityId);
const checklist = await ReactiveCache.getChecklist(this.entityId);
if (checklist) {
const sort = this.previousSort !== undefined ? this.previousSort : checklist.sort;
Checklists.update(checklist._id, {
$set: {
sort,
@ -270,7 +270,7 @@ UserPositionHistory.helpers({
if (item) {
const sort = this.previousSort !== undefined ? this.previousSort : item.sort;
const checklistId = this.previousState?.checklistId || item.checklistId;
ChecklistItems.update(item._id, {
$set: {
sort,
@ -411,19 +411,19 @@ Meteor.methods({
});
},
'userPositionHistory.undo'(historyId) {
async 'userPositionHistory.undo'(historyId) {
check(historyId, String);
if (!this.userId) {
throw new Meteor.Error('not-authorized', 'Must be logged in');
}
const history = UserPositionHistory.findOne({ _id: historyId, userId: this.userId });
if (!history) {
throw new Meteor.Error('not-found', 'History entry not found');
}
return history.undo();
return await history.undo();
},
'userPositionHistory.getRecent'(boardId, limit = 50) {
@ -453,23 +453,23 @@ Meteor.methods({
).fetch();
},
'userPositionHistory.restoreToCheckpoint'(checkpointId) {
async 'userPositionHistory.restoreToCheckpoint'(checkpointId) {
check(checkpointId, String);
if (!this.userId) {
throw new Meteor.Error('not-authorized', 'Must be logged in');
}
const checkpoint = UserPositionHistory.findOne({
_id: checkpointId,
const checkpoint = UserPositionHistory.findOne({
_id: checkpointId,
userId: this.userId,
isCheckpoint: true,
});
if (!checkpoint) {
throw new Meteor.Error('not-found', 'Checkpoint not found');
}
// Find all changes after this checkpoint and undo them in reverse order
const changesToUndo = UserPositionHistory.find(
{
@ -480,19 +480,19 @@ Meteor.methods({
},
{ sort: { createdAt: -1 } }
).fetch();
let undoneCount = 0;
changesToUndo.forEach(change => {
for (const change of changesToUndo) {
try {
if (change.canUndo()) {
change.undo();
if (await change.canUndo()) {
await change.undo();
undoneCount++;
}
} catch (e) {
console.warn('Failed to undo change:', change._id, e);
}
});
}
return { undoneCount, totalChanges: changesToUndo.length };
},
});