directus

Форк
0
/
get-extensions-settings.ts 
160 строк · 4.8 Кб
1
import type { BundleExtension, Extension, ExtensionSettings } from '@directus/extensions';
2
import { randomUUID } from 'node:crypto';
3
import getDatabase from '../../database/index.js';
4
import { ExtensionsService } from '../../services/extensions.js';
5
import { getSchema } from '../../utils/get-schema.js';
6

7
/**
8
 * Loads stored settings for all extensions. Creates empty new rows in extensions tables for
9
 * extensions that don't have settings yet, and remove any settings for extensions that are no
10
 * longer installed.
11
 */
12
export const getExtensionsSettings = async ({
13
	local,
14
	module,
15
	registry,
16
}: {
17
	local: Map<string, Extension>;
18
	module: Map<string, Extension>;
19
	registry: Map<string, Extension>;
20
}) => {
21
	const database = getDatabase();
22

23
	const service = new ExtensionsService({
24
		knex: database,
25
		schema: await getSchema(),
26
	});
27

28
	const existingSettings = await service.extensionsItemService.readByQuery({ limit: -1 });
29

30
	const newSettings: ExtensionSettings[] = [];
31
	const removedSettingIds: string[] = [];
32

33
	const localSettings = existingSettings.filter(({ source }) => source === 'local');
34
	const registrySettings = existingSettings.filter(({ source }) => source === 'registry');
35
	const moduleSettings = existingSettings.filter(({ source }) => source === 'module');
36

37
	const updateBundleEntriesSettings = (
38
		bundle: BundleExtension,
39
		bundleSettings: ExtensionSettings,
40
		allSettings: ExtensionSettings[],
41
	) => {
42
		const bundleEntriesSettings = allSettings.filter(({ bundle }) => bundle === bundleSettings.id);
43

44
		// Remove settings of removed bundle entries from the DB
45
		for (const entry of bundleEntriesSettings) {
46
			const entryInBundle = bundle.entries.some(({ name }) => name === entry.folder);
47

48
			if (entryInBundle) continue;
49

50
			removedSettingIds.push(entry.id);
51
		}
52

53
		// Add new bundle entries to the settings
54
		for (const entry of bundle.entries) {
55
			const settingsExist = bundleEntriesSettings.some(({ folder }) => folder === entry.name);
56

57
			if (settingsExist) continue;
58

59
			newSettings.push({
60
				id: randomUUID(),
61
				enabled: bundleSettings.enabled,
62
				source: bundleSettings.source,
63
				bundle: bundleSettings.id,
64
				folder: entry.name,
65
			});
66
		}
67
	};
68

69
	const generateSettingsEntry = (folder: string, extension: Extension, source: 'local' | 'registry' | 'module') => {
70
		if (extension.type === 'bundle') {
71
			const bundleId = randomUUID();
72

73
			newSettings.push({
74
				id: bundleId,
75
				enabled: true,
76
				source: source,
77
				bundle: null,
78
				folder: folder,
79
			});
80

81
			for (const entry of extension.entries) {
82
				newSettings.push({
83
					id: randomUUID(),
84
					enabled: true,
85
					source: source,
86
					bundle: bundleId,
87
					folder: entry.name,
88
				});
89
			}
90
		} else {
91
			newSettings.push({
92
				id: randomUUID(),
93
				enabled: true,
94
				source: source,
95
				bundle: null,
96
				folder: folder,
97
			});
98
		}
99
	};
100

101
	for (const [folder, extension] of local.entries()) {
102
		const existingSettings = localSettings.find((settings) => settings.folder === folder);
103

104
		if (existingSettings) {
105
			if (extension.type === 'bundle') {
106
				updateBundleEntriesSettings(extension, existingSettings, localSettings);
107
			}
108

109
			continue;
110
		}
111

112
		const settingsForName = localSettings.find((settings) => settings.folder === extension.name);
113

114
		/*
115
		 * TODO: Consider removing this in follow-up versions after v10.10.0
116
		 *
117
		 * Previously, the package name (from package.json) was used to identify
118
		 * local extensions - now it's the folder name.
119
		 * If those two are different, we need to check for existing settings
120
		 * with the package name, too. On a match and if there's no other local extension
121
		 * with such a folder name, these settings can be taken over with the folder updated.
122
		 */
123
		if (settingsForName && !local.has(extension.name)) {
124
			await service.extensionsItemService.updateOne(settingsForName.id, { folder });
125
			continue;
126
		}
127

128
		generateSettingsEntry(folder, extension, 'local');
129
	}
130

131
	for (const [folder, extension] of module.entries()) {
132
		const existingSettings = moduleSettings.find((settings) => settings.folder === folder);
133

134
		if (!existingSettings) {
135
			generateSettingsEntry(folder, extension, 'module');
136
		} else if (extension.type === 'bundle') {
137
			updateBundleEntriesSettings(extension, existingSettings, moduleSettings);
138
		}
139
	}
140

141
	for (const [folder, extension] of registry.entries()) {
142
		const existingSettings = registrySettings.find((settings) => settings.folder === folder);
143

144
		if (!existingSettings) {
145
			generateSettingsEntry(folder, extension, 'registry');
146
		} else if (extension.type === 'bundle') {
147
			updateBundleEntriesSettings(extension, existingSettings, registrySettings);
148
		}
149
	}
150

151
	if (removedSettingIds.length > 0) {
152
		await service.extensionsItemService.deleteMany(removedSettingIds);
153
	}
154

155
	if (newSettings.length > 0) {
156
		await service.extensionsItemService.createMany(newSettings);
157
	}
158

159
	return [...existingSettings.filter(({ id }) => !removedSettingIds.includes(id)), ...newSettings];
160
};
161

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.