Convert client-reachable CJS helpers from CommonJS to ES modules (2/2).

A transitive walk from client/main.js found the remaining CommonJS
(module.exports) helpers that the rspack client build pulls into the ES
module graph and rejects: 3 client/lib helpers (cardDragGeometry,
inlinedFormManager, popupOffset), 4 imports/lib helpers (boardAutoScroll,
datePickerTime, fileNameDisplay, staleWhileRevalidate), imports/simpleSchema
(its meteor/aldeed:simple-schema require becomes a namespace import),
imports/i18n/loadHelpers, and 4 more models/lib helpers (cardLinkRedirect,
sandstormAutoOpen, securityCategories, securityLogFormat). All become
`export { ... }`; their .cjs unit tests use `await import(...js)`.

The only CJS files still reachable in the walk are server-only: the
server/lib/* files (Meteor never bundles server/ to the client) and the
fs-using models/lib file-storage helpers (reached only via the server-side
fileStoreStrategy; they would fail on require("fs") if they were actually in
the client bundle). Those correctly stay CommonJS.

Full tests/*.test.cjs suite: same 7 pre-existing failures, no new ones.
This commit is contained in:
Lauri Ojansivu committed 2026-07-23 18:59:30 +03:00
1 parent 8d1fae4f7d
commit d6908cf418
20 files changed
+42 -21

No files matched your search

+1 -1
View File
@@ -96,7 +96,7 @@ function findActiveCardDrag(instances) {
return null;
}
module.exports = {
export {
nodeChangesDragGeometry,
mutationsChangeDragGeometry,
findActiveCardDrag,
+1 -1
View File
@@ -74,4 +74,4 @@ function forgetForm(tracker, form) {
}
}
module.exports = { openForm, closeForm, forgetForm };
export { openForm, closeForm, forgetForm };
+1 -1
View File
@@ -115,4 +115,4 @@ function computePopupOffset(params) {
return { left: clampedLeft, top: topVp + scrollTop, maxHeight };
}
module.exports = { computePopupOffset };
export { computePopupOffset };
+1 -1
View File
@@ -47,4 +47,4 @@ function promiseWithTimeout(promise, ms, timeoutMessage) {
});
}
module.exports = { unwrapI18nModule, promiseWithTimeout };
export { unwrapI18nModule, promiseWithTimeout };
+1 -1
View File
@@ -130,7 +130,7 @@ function findLaneUnderPointer(laneRects, pointerX, pointerY) {
return -1;
}
module.exports = {
export {
EDGE_SIZE,
SCROLL_STEP,
computeEdgeScroll,
+1 -1
View File
@@ -56,7 +56,7 @@ function fallbackSubmitTime(defaultTime) {
return defaultTimeValue(defaultTime) || '12:00';
}
module.exports = {
export {
isValidDate,
formatTime,
initialTimeValue,
+1 -1
View File
@@ -166,7 +166,7 @@ function sanitizeDownloadFileName(name) {
return cleanFileName(name) || 'download';
}
module.exports = {
export {
INVISIBLE_CHARS_SOURCE,
INVISIBLE_CHARS_REGEX,
INVISIBLE_CHARS_GLOBAL,
+1 -1
View File
@@ -25,4 +25,4 @@ function shouldDeferCacheMiss(options, newData, cachedValue) {
);
}
module.exports = { shouldDeferCacheMiss };
export { shouldDeferCacheMiss };
+2 -2
View File
@@ -1,4 +1,4 @@
const schemaPackage = require('meteor/aldeed:simple-schema');
import * as schemaPackage from 'meteor/aldeed:simple-schema';
const SimpleSchema =
schemaPackage.default || schemaPackage.SimpleSchema || schemaPackage;
@@ -8,4 +8,4 @@ if (!SimpleSchema._wekanExtendedOptions) {
SimpleSchema._wekanExtendedOptions = true;
}
module.exports = { SimpleSchema };
export { SimpleSchema };
+1 -1
View File
@@ -24,4 +24,4 @@ function cardBoardRedirectTarget(urlBoardId, card) {
return card.boardId;
}
module.exports = { cardBoardRedirectTarget };
export { cardBoardRedirectTarget };
+1 -1
View File
@@ -53,4 +53,4 @@ function decideSandstormAutoOpen(input) {
return { action: 'stay' };
}
module.exports = { decideSandstormAutoOpen };
export { decideSandstormAutoOpen };
+1 -1
View File
@@ -43,4 +43,4 @@ function categoryFor(key) {
return Object.assign({}, DEFAULT, CATALOG[key] || {});
}
module.exports = { CATALOG, categoryFor };
export { CATALOG, categoryFor };
+1 -1
View File
@@ -18,4 +18,4 @@ function sanitizeDetail(s) {
return out;
}
module.exports = { MAX_DETAIL, sanitizeDetail };
export { MAX_DETAIL, sanitizeDetail };
+4 -1
View File
@@ -1,4 +1,5 @@
'use strict';
(async () => {
// Plain-Node unit test (no Meteor) for the #2769 drag-geometry helpers.
// Run: ELECTRON_RUN_AS_NODE=1 <node> tests/cardDragGeometry.test.cjs
@@ -26,7 +27,7 @@ const {
nodeChangesDragGeometry,
mutationsChangeDragGeometry,
findActiveCardDrag,
} = require('../client/lib/cardDragGeometry');
} = await import('../client/lib/cardDragGeometry.js');
let passed = 0;
function test(name, fn) {
@@ -171,3 +172,5 @@ test('listBody.js wires the observer to the helpers and refreshes the active dra
});
console.log(`\n${passed} passing`);
})().catch(e => { console.error(e); process.exit(1); });
+4 -1
View File
@@ -1,4 +1,5 @@
'use strict';
(async () => {
// Unit tests for the #4758 card-link redirect decision
// (models/lib/cardLinkRedirect.js): a card link keeps working after the card is
@@ -7,7 +8,7 @@
const assert = require('assert');
const fs = require('fs');
const path = require('path');
const { cardBoardRedirectTarget } = require('../models/lib/cardLinkRedirect');
const { cardBoardRedirectTarget } = await import('../models/lib/cardLinkRedirect.js');
let passed = 0;
function check(name, fn) { fn(); passed += 1; console.log(' ok -', name); }
@@ -60,3 +61,5 @@ check('router wires the redirect via the card publication (permission-checked)',
});
console.log(`\ncardLinkRedirect: ${passed} checks passed`);
})().catch(e => { console.error(e); process.exit(1); });
+4 -1
View File
@@ -1,4 +1,5 @@
'use strict';
(async () => {
// Plain-Node unit test (no Meteor) for the date-picker default-time logic.
// Run: ELECTRON_RUN_AS_NODE=1 <node> tests/datePickerDefaultTime.test.cjs
@@ -16,7 +17,7 @@ const {
formatTime,
initialTimeValue,
fallbackSubmitTime,
} = require('../imports/lib/datePickerTime');
} = await import('../imports/lib/datePickerTime.js');
let passed = 0;
function test(name, fn) {
@@ -84,3 +85,5 @@ test('NEGATIVE: without (or with a broken) default the legacy 12:00 remains', ()
});
console.log(`\n${passed} tests passed`);
})().catch(e => { console.error(e); process.exit(1); });
+4 -1
View File
@@ -1,4 +1,5 @@
'use strict';
(async () => {
// Unit + negative tests for the i18n loader helpers (imports/i18n/loadHelpers.js),
// the robustness guards behind #6503 (a hung/failed dynamic language import must
@@ -9,7 +10,7 @@ const assert = require('assert');
const {
unwrapI18nModule,
promiseWithTimeout,
} = require('../imports/i18n/loadHelpers');
} = await import('../imports/i18n/loadHelpers.js');
let passed = 0;
const pending = [];
@@ -92,3 +93,5 @@ Promise.all(pending).then(() => {
console.error('FAILED:', err && err.message);
process.exit(1);
});
})().catch(e => { console.error(e); process.exit(1); });
+4 -1
View File
@@ -1,4 +1,5 @@
'use strict';
(async () => {
// Plain-Node unit test (no DOM/Meteor) for the inlined-form open/close state
// transitions used by client/lib/inlinedform.js.
@@ -21,7 +22,7 @@ const {
openForm,
closeForm,
forgetForm,
} = require('../client/lib/inlinedFormManager');
} = await import('../client/lib/inlinedFormManager.js');
let passed = 0;
function test(name, fn) {
@@ -162,3 +163,5 @@ test('NEGATIVE: closeForm tolerates null/malformed forms without throwing', () =
});
console.log(`\n${passed} tests passed`);
})().catch(e => { console.error(e); process.exit(1); });
+4 -1
View File
@@ -1,4 +1,5 @@
'use strict';
(async () => {
// Plain-Node unit test (no DOM/Meteor) for the popup positioning geometry.
// Run: node tests/popupOffset.test.cjs
@@ -12,7 +13,7 @@
// staying byte-identical to the old behaviour when the page is not scrolled.
const assert = require('assert');
const { computePopupOffset } = require('../client/lib/popupOffset');
const { computePopupOffset } = await import('../client/lib/popupOffset.js');
let passed = 0;
function test(name, fn) {
@@ -160,3 +161,5 @@ test('maxHeight is never negative for an opener above the viewport', () => {
});
console.log(`\n${passed} tests passed`);
})().catch(e => { console.error(e); process.exit(1); });
+4 -1
View File
@@ -1,4 +1,5 @@
'use strict';
(async () => {
// Plain-Node unit test (no Meteor) for the DataCache stale-while-revalidate
// decision — the board-not-found flicker fix.
@@ -13,7 +14,7 @@
// only apply when the owning cache opted in.
const assert = require('assert');
const { shouldDeferCacheMiss } = require('../imports/lib/staleWhileRevalidate');
const { shouldDeferCacheMiss } = await import('../imports/lib/staleWhileRevalidate.js');
let passed = 0;
function test(name, fn) {
@@ -60,3 +61,5 @@ test('NEGATIVE: a falsy-but-present cached value (0 / "") is still preserved', (
});
console.log(`\n${passed} passing`);
})().catch(e => { console.error(e); process.exit(1); });