@nocobase/utils 2.1.0-alpha.33 → 2.1.0-alpha.35
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +2 -2
- package/plugin-symlink.d.ts +1 -0
- package/plugin-symlink.js +109 -14
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/utils",
|
|
3
|
-
"version": "2.1.0-alpha.
|
|
3
|
+
"version": "2.1.0-alpha.35",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"types": "./lib/index.d.ts",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -21,5 +21,5 @@
|
|
|
21
21
|
"object-path": "^0.11.8",
|
|
22
22
|
"ses": "^1.14.0"
|
|
23
23
|
},
|
|
24
|
-
"gitHead": "
|
|
24
|
+
"gitHead": "313a9e19e84a99924c86f9855c2ae48943f450b0"
|
|
25
25
|
}
|
package/plugin-symlink.d.ts
CHANGED
|
@@ -4,3 +4,4 @@ export declare function createStoragePluginSymLink(pluginName: any): Promise<voi
|
|
|
4
4
|
export declare function createStoragePluginsSymlink(): Promise<void>;
|
|
5
5
|
export declare function createDevPluginSymLink(pluginName: any): Promise<void>;
|
|
6
6
|
export declare function createDevPluginsSymlink(): Promise<void>;
|
|
7
|
+
export declare function syncPluginSymlinks(): Promise<void>;
|
package/plugin-symlink.js
CHANGED
|
@@ -37,6 +37,36 @@ async function getStoragePluginNames(target) {
|
|
|
37
37
|
return plugins;
|
|
38
38
|
}
|
|
39
39
|
|
|
40
|
+
async function getPluginNamesFromSourceRoot(rootPath) {
|
|
41
|
+
if (!(await fs.pathExists(rootPath))) {
|
|
42
|
+
return [];
|
|
43
|
+
}
|
|
44
|
+
return await getStoragePluginNames(rootPath);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function isValidPluginSourcePath(candidate) {
|
|
48
|
+
return await fs.pathExists(resolve(candidate, 'package.json'));
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function getPluginSourceRoots(storagePluginsPath) {
|
|
52
|
+
return [
|
|
53
|
+
resolve(process.cwd(), 'packages/plugins'),
|
|
54
|
+
resolve(process.cwd(), 'packages/pro-plugins'),
|
|
55
|
+
storagePluginsPath,
|
|
56
|
+
];
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
async function resolvePluginSourcePath(pluginName, storagePluginsPath) {
|
|
60
|
+
const sourceRoots = getPluginSourceRoots(storagePluginsPath);
|
|
61
|
+
for (const rootPath of sourceRoots) {
|
|
62
|
+
const candidate = resolve(rootPath, pluginName);
|
|
63
|
+
if (await isValidPluginSourcePath(candidate)) {
|
|
64
|
+
return candidate;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return '';
|
|
68
|
+
}
|
|
69
|
+
|
|
40
70
|
/**
|
|
41
71
|
* Ensure the organization directory exists for scoped packages
|
|
42
72
|
* @param {string} nodeModulesPath - Path to node_modules
|
|
@@ -52,22 +82,35 @@ async function ensureOrgDirectory(nodeModulesPath, pluginName) {
|
|
|
52
82
|
}
|
|
53
83
|
|
|
54
84
|
/**
|
|
55
|
-
* Check
|
|
56
|
-
* @param {string} linkPath - Path
|
|
57
|
-
* @
|
|
58
|
-
* @returns {Promise<boolean>} True if symlink exists and points to target
|
|
85
|
+
* Check whether node_modules entry is a real directory, symlink, or missing
|
|
86
|
+
* @param {string} linkPath - Path inside node_modules
|
|
87
|
+
* @returns {Promise<'missing'|'dir'|'symlink'|'other'>}
|
|
59
88
|
*/
|
|
60
|
-
async function
|
|
89
|
+
async function getNodeModulesEntryType(linkPath) {
|
|
61
90
|
try {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
return
|
|
91
|
+
const statResult = await fs.lstat(linkPath);
|
|
92
|
+
if (statResult.isSymbolicLink()) {
|
|
93
|
+
return 'symlink';
|
|
65
94
|
}
|
|
95
|
+
if (statResult.isDirectory()) {
|
|
96
|
+
return 'dir';
|
|
97
|
+
}
|
|
98
|
+
return 'other';
|
|
66
99
|
} catch (error) {
|
|
67
|
-
|
|
100
|
+
if (error.code === 'ENOENT') {
|
|
101
|
+
return 'missing';
|
|
102
|
+
}
|
|
103
|
+
return 'other';
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async function isSymlinkValid(linkPath, targetPath) {
|
|
108
|
+
try {
|
|
109
|
+
const realPath = await fs.realpath(linkPath);
|
|
110
|
+
return realPath === targetPath;
|
|
111
|
+
} catch {
|
|
68
112
|
return false;
|
|
69
113
|
}
|
|
70
|
-
return false;
|
|
71
114
|
}
|
|
72
115
|
|
|
73
116
|
/**
|
|
@@ -119,13 +162,18 @@ async function createPluginSymLink(pluginName, sourcePath, nodeModulesPath, plug
|
|
|
119
162
|
return;
|
|
120
163
|
}
|
|
121
164
|
|
|
165
|
+
const linkPath = resolve(nodeModulesPath, pluginName);
|
|
166
|
+
const entryType = await getNodeModulesEntryType(linkPath);
|
|
167
|
+
|
|
168
|
+
if (entryType === 'dir') {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
|
|
122
172
|
// Ensure organization directory exists for scoped packages
|
|
123
173
|
await ensureOrgDirectory(nodeModulesPath, pluginName);
|
|
124
174
|
|
|
125
|
-
const linkPath = resolve(nodeModulesPath, pluginName);
|
|
126
|
-
|
|
127
175
|
// Check if symlink already points to the correct target
|
|
128
|
-
if (await isSymlinkValid(linkPath, targetPath)) {
|
|
176
|
+
if (entryType === 'symlink' && (await isSymlinkValid(linkPath, targetPath))) {
|
|
129
177
|
return; // Symlink is already correct, no need to recreate
|
|
130
178
|
}
|
|
131
179
|
|
|
@@ -142,7 +190,6 @@ async function createPluginSymLink(pluginName, sourcePath, nodeModulesPath, plug
|
|
|
142
190
|
/**
|
|
143
191
|
* Create a symlink for a storage plugin
|
|
144
192
|
* @param {string} pluginName - Name of the plugin
|
|
145
|
-
* @returns {Promise<void>}
|
|
146
193
|
*/
|
|
147
194
|
async function createStoragePluginSymLink(pluginName) {
|
|
148
195
|
const storagePluginsPath = resolvePluginStoragePath();
|
|
@@ -187,8 +234,56 @@ async function createDevPluginsSymlink() {
|
|
|
187
234
|
await Promise.all(pluginNames.map((pluginName) => createDevPluginSymLink(pluginName)));
|
|
188
235
|
}
|
|
189
236
|
|
|
237
|
+
/**
|
|
238
|
+
* Create symlinks for all plugins from all sources
|
|
239
|
+
* @returns {Promise<void>}
|
|
240
|
+
*/
|
|
241
|
+
async function syncPluginSymlinks() {
|
|
242
|
+
const nodeModulesPath = process.env.NODE_MODULES_PATH;
|
|
243
|
+
if (!nodeModulesPath) {
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
const storagePluginsPath = resolvePluginStoragePath();
|
|
248
|
+
const sourceRoots = getPluginSourceRoots(storagePluginsPath);
|
|
249
|
+
const pluginNames = new Set();
|
|
250
|
+
|
|
251
|
+
for (const rootPath of sourceRoots) {
|
|
252
|
+
const names = await getPluginNamesFromSourceRoot(rootPath);
|
|
253
|
+
names.forEach((name) => pluginNames.add(name));
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
await Promise.all(
|
|
257
|
+
[...pluginNames].map(async (pluginName) => {
|
|
258
|
+
const linkPath = resolve(nodeModulesPath, pluginName);
|
|
259
|
+
const entryType = await getNodeModulesEntryType(linkPath);
|
|
260
|
+
|
|
261
|
+
if (entryType === 'dir') {
|
|
262
|
+
return;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
const sourcePath = await resolvePluginSourcePath(pluginName, storagePluginsPath);
|
|
266
|
+
if (!sourcePath) {
|
|
267
|
+
if (entryType === 'symlink' || entryType === 'other') {
|
|
268
|
+
await removeExistingLink(linkPath, pluginName, 'plugin');
|
|
269
|
+
}
|
|
270
|
+
return;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
if (entryType === 'symlink' && (await isSymlinkValid(linkPath, sourcePath))) {
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
await ensureOrgDirectory(nodeModulesPath, pluginName);
|
|
278
|
+
await removeExistingLink(linkPath, pluginName, 'plugin');
|
|
279
|
+
await fs.symlink(sourcePath, linkPath, 'dir');
|
|
280
|
+
}),
|
|
281
|
+
);
|
|
282
|
+
}
|
|
283
|
+
|
|
190
284
|
exports.resolvePluginStoragePath = resolvePluginStoragePath;
|
|
191
285
|
exports.createStoragePluginSymLink = createStoragePluginSymLink;
|
|
192
286
|
exports.createStoragePluginsSymlink = createStoragePluginsSymlink;
|
|
193
287
|
exports.createDevPluginSymLink = createDevPluginSymLink;
|
|
194
288
|
exports.createDevPluginsSymlink = createDevPluginsSymlink;
|
|
289
|
+
exports.syncPluginSymlinks = syncPluginSymlinks;
|