Skip to content

Commit 4ec2da1

Browse files
committed
Fixes #110
1 parent 0f356f7 commit 4ec2da1

6 files changed

Lines changed: 95 additions & 6 deletions

File tree

‎src/collectionExporter.ts‎

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ const DEFAULT_COLLECTION_EXPORTER_OPTIONS: CollectionExporterOptions = {
1717
};
1818

1919
class CollectionExporter implements IExporter {
20+
protected _itemsService?: IItemsService;
2021
protected _getService: () => Promise<IItemsService>;
2122
protected collection: string;
2223

@@ -39,8 +40,7 @@ class CollectionExporter implements IExporter {
3940
...otherOpts,
4041
};
4142

42-
let srv: IItemsService;
43-
this._getService = async () => srv || (srv = await getItemsService(collectionName));
43+
this._getService = async () => this._itemsService || (this._itemsService = await getItemsService(collectionName));
4444

4545
this.collection = collectionName;
4646

@@ -78,6 +78,12 @@ class CollectionExporter implements IExporter {
7878
return this.collection;
7979
}
8080

81+
/** Clear cached schema-dependent state after the DB schema has changed. */
82+
public clearCache() {
83+
this._itemsService = undefined;
84+
this._settings = null;
85+
}
86+
8187
protected _persistQueue = condenseAction(() => this.exportCollectionToFile());
8288
public export = () => this._persistQueue();
8389

‎src/exportManager.test.ts‎

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
import assert from 'node:assert';
2+
import { describe, it } from 'node:test';
3+
import { ExportManager } from './exportManager.js';
4+
import type { IExporter } from './types.js';
5+
6+
describe('ExportManager', () => {
7+
it('refreshes schema cache after the schema exporter loads', async () => {
8+
let schemaCacheCleared = false;
9+
let collectionCacheCleared = false;
10+
11+
const schemaExporter: IExporter = {
12+
name: 'schema',
13+
load: async () => {},
14+
export: async () => {},
15+
};
16+
17+
const collectionExporter: IExporter = {
18+
name: 'custom_collection',
19+
load: async () => {},
20+
export: async () => {},
21+
clearCache: () => {
22+
collectionCacheCleared = true;
23+
},
24+
};
25+
26+
const manager = new ExportManager(console as any, () => {
27+
schemaCacheCleared = true;
28+
});
29+
manager.addExporter({ watch: [], exporter: schemaExporter });
30+
manager.addExporter({ watch: [], exporter: collectionExporter });
31+
32+
await manager.loadAll();
33+
34+
assert.strictEqual(schemaCacheCleared, true);
35+
assert.strictEqual(collectionCacheCleared, true);
36+
});
37+
38+
it('does not refresh schema cache when loading data only', async () => {
39+
let schemaCacheCleared = false;
40+
let collectionCacheCleared = false;
41+
42+
const collectionExporter: IExporter = {
43+
name: 'custom_collection',
44+
load: async () => {},
45+
export: async () => {},
46+
clearCache: () => {
47+
collectionCacheCleared = true;
48+
},
49+
};
50+
51+
const manager = new ExportManager(console as any, () => {
52+
schemaCacheCleared = true;
53+
});
54+
manager.addExporter({ watch: [], exporter: collectionExporter });
55+
56+
await manager.loadAll();
57+
58+
assert.strictEqual(schemaCacheCleared, false);
59+
assert.strictEqual(collectionCacheCleared, false);
60+
});
61+
});

‎src/exportManager.ts‎

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
import type { ApiExtensionContext } from '@directus/extensions';
22
import type { ActionHandler } from '@directus/types';
33
import { CollectionExporter } from './collectionExporter.js';
4-
import { ExportCollectionConfig, IExporterConfig, IGetItemsService } from './types';
4+
import type { ExportCollectionConfig, IExporterConfig, IGetItemsService } from './types';
55

66
export class ExportManager {
77
protected exporters: IExporterConfig[] = [];
88

9-
constructor(protected logger: ApiExtensionContext['logger']) {}
9+
constructor(
10+
protected logger: ApiExtensionContext['logger'],
11+
protected clearSchemaCache?: () => void
12+
) {}
1013

1114
// FIRST: Add exporters
1215
public addExporter(exporterConfig: IExporterConfig) {
@@ -28,11 +31,21 @@ export class ExportManager {
2831
await this._loadNextExporter(0, merge);
2932
}
3033

34+
protected refreshSchemaCache() {
35+
this.clearSchemaCache?.();
36+
for (const { exporter } of this.exporters) {
37+
exporter.clearCache?.();
38+
}
39+
}
40+
3141
protected async _loadNextExporter(i = 0, merge = false) {
3242
if (i >= this.exporters.length) return;
3343

3444
try {
3545
const finishUp = await this.exporters[i]!.exporter.load(merge);
46+
if (this.exporters[i]!.exporter.name === 'schema') {
47+
this.refreshSchemaCache();
48+
}
3649
await this._loadNextExporter(i + 1, merge);
3750
if (typeof finishUp === 'function') await finishUp();
3851
} catch (e) {

‎src/index.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ const registerHook: HookConfig = async ({ action, init }, { env, services, datab
4141
let _exportManager: ExportManager;
4242

4343
const createExportManager = async (dataOnly = false) => {
44-
const exportMng = new ExportManager(logger);
44+
const exportMng = new ExportManager(logger, clearAdminSchema);
4545

4646
if (!dataOnly) {
4747
exportMng.addExporter({

‎src/types.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ export interface IExporter {
1010
name: string;
1111
load: (merge?: boolean) => Promise<(() => Promise<void>) | null | void>;
1212
export: () => Promise<void>;
13+
clearCache?: () => void;
1314
}
1415

1516
export interface IExporterConfig {

‎tsconfig.test.json‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,13 @@
2626
"rootDir": "./src",
2727
"outDir": "./dist-test",
2828
},
29-
"include": ["src/utils.ts", "src/utils.test.ts", "src/dialects/postgres/utils.ts", "src/dialects/postgres/utils.test.ts"]
29+
"include": [
30+
"src/utils.ts",
31+
"src/utils.test.ts",
32+
"src/dialects/postgres/utils.ts",
33+
"src/dialects/postgres/utils.test.ts",
34+
"src/exportManager.ts",
35+
"src/exportManager.test.ts",
36+
"src/types.ts"
37+
]
3038
}

0 commit comments

Comments
 (0)