Skip to content

Commit e7bf2f4

Browse files
committed
Fixed loading adapters from node_modules
ref https://linear.app/ghost/issue/PRO-1465 The AdapterManager was designed to support loading from node_modules by passing an empty string for the adapter storage path. The idea was that `require` would get called with just the name of the adapter, rather than a path prefix. This however was not working, because we were prefixing the adapter name with a subdirectory. This was so that we would load e.g. storages adapters from e.g. `content/adapters/storage` instead of `content/adapters` this breaks loading from node modules because we would attempt to require `storage/node-module` instead of `node-module` I've added a test here to make sure this doesn't regress, the fix is scoped only to loading from the empty string path.
1 parent 0fa1d85 commit e7bf2f4

File tree

2 files changed

+28
-1
lines changed

2 files changed

+28
-1
lines changed

ghost/core/core/server/services/adapter-manager/AdapterManager.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,11 @@ module.exports = class AdapterManager {
102102
/** @type AdapterConstructor */
103103
let Adapter;
104104
for (const pathToAdapters of this.pathsToAdapters) {
105-
const pathToAdapter = path.join(pathToAdapters, adapterType, adapterClassName);
105+
let pathToAdapter = path.join(pathToAdapters, adapterType, adapterClassName);
106+
if (pathToAdapters === '') {
107+
// We are loading from node_modules, we can remove the `adapterType` prefix
108+
pathToAdapter = path.join(pathToAdapters, adapterClassName);
109+
}
106110
try {
107111
Adapter = this.loadAdapterFromPath(pathToAdapter);
108112
if (Adapter) {

ghost/core/test/unit/server/services/adapter-manager/AdapterManager.test.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,29 @@ describe('AdapterManager', function () {
6565
}
6666
});
6767

68+
it('getAdapter can handle looking up from node_modules', function () {
69+
const pathsToAdapters = [
70+
'', // node_modules
71+
'first/path'
72+
];
73+
74+
const loadAdapterFromPath = sinon.stub();
75+
const adapterManager = new AdapterManager({
76+
loadAdapterFromPath,
77+
pathsToAdapters
78+
});
79+
80+
adapterManager.registerAdapter('mail', BaseMailAdapter);
81+
82+
try {
83+
adapterManager.getAdapter('mail', 'some-node-module-adapter');
84+
} catch (err) {
85+
should.ok(err); // We don't care about the error, we just want to check `loadAdapterFromPath`
86+
}
87+
88+
loadAdapterFromPath.calledWith('some-node-module-adapter').should.equal(true);
89+
});
90+
6891
it('Loads registered adapters in the order defined by the paths', function () {
6992
const pathsToAdapters = [
7093
'first/path',

0 commit comments

Comments
 (0)