@nocobase/utils 2.0.0-alpha.7 → 2.0.0-alpha.71
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/lib/assign.js +13 -1
- package/lib/client.d.ts +2 -0
- package/lib/client.js +5 -1
- package/lib/common.js +6 -1
- package/lib/i18n.d.ts +3 -0
- package/lib/index.d.ts +2 -0
- package/lib/index.js +5 -1
- package/lib/liquidjs.d.ts +11 -0
- package/lib/liquidjs.js +71 -0
- package/lib/run-sql.d.ts +17 -0
- package/lib/run-sql.js +57 -0
- package/lib/transformFilter.d.ts +1 -0
- package/lib/transformFilter.js +26 -2
- package/package.json +4 -2
- package/plugin-symlink.js +137 -60
package/lib/assign.js
CHANGED
|
@@ -45,7 +45,10 @@ var import_deepmerge = __toESM(require("deepmerge"));
|
|
|
45
45
|
var import_lodash = __toESM(require("lodash"));
|
|
46
46
|
var import_common = require("./common");
|
|
47
47
|
function getEnumerableOwnPropertySymbols(target) {
|
|
48
|
-
return Object.getOwnPropertySymbols ?
|
|
48
|
+
return Object.getOwnPropertySymbols ? (
|
|
49
|
+
// eslint-disable-next-line no-prototype-builtins
|
|
50
|
+
Object.getOwnPropertySymbols(target).filter((symbol) => target.propertyIsEnumerable(symbol))
|
|
51
|
+
) : [];
|
|
49
52
|
}
|
|
50
53
|
__name(getEnumerableOwnPropertySymbols, "getEnumerableOwnPropertySymbols");
|
|
51
54
|
function getKeys(target) {
|
|
@@ -119,6 +122,15 @@ mergeStrategies.set(
|
|
|
119
122
|
if (typeof y === "string") {
|
|
120
123
|
y = y.split(",");
|
|
121
124
|
}
|
|
125
|
+
if (typeof x === "object" && !Array.isArray(x)) {
|
|
126
|
+
x = Object.values(x || {});
|
|
127
|
+
}
|
|
128
|
+
if (typeof y === "object" && !Array.isArray(y)) {
|
|
129
|
+
y = Object.values(y || {});
|
|
130
|
+
}
|
|
131
|
+
if (!Array.isArray(x) || x.length === 0) {
|
|
132
|
+
return y || [];
|
|
133
|
+
}
|
|
122
134
|
if (!Array.isArray(x) || x.length === 0) {
|
|
123
135
|
return y || [];
|
|
124
136
|
}
|
package/lib/client.d.ts
CHANGED
|
@@ -31,4 +31,6 @@ export * from './url';
|
|
|
31
31
|
export * from './transformMultiColumnToSingleColumn';
|
|
32
32
|
export * from './transformFilter';
|
|
33
33
|
export * from './variable-usage';
|
|
34
|
+
export * from './run-sql';
|
|
35
|
+
export * from './liquidjs';
|
|
34
36
|
export { dayjs, lodash, getDayRangeByParams, getOffsetRangeByParams };
|
package/lib/client.js
CHANGED
|
@@ -68,6 +68,8 @@ __reExport(client_exports, require("./url"), module.exports);
|
|
|
68
68
|
__reExport(client_exports, require("./transformMultiColumnToSingleColumn"), module.exports);
|
|
69
69
|
__reExport(client_exports, require("./transformFilter"), module.exports);
|
|
70
70
|
__reExport(client_exports, require("./variable-usage"), module.exports);
|
|
71
|
+
__reExport(client_exports, require("./run-sql"), module.exports);
|
|
72
|
+
__reExport(client_exports, require("./liquidjs"), module.exports);
|
|
71
73
|
// Annotate the CommonJS export names for ESM import in node:
|
|
72
74
|
0 && (module.exports = {
|
|
73
75
|
dayjs,
|
|
@@ -95,5 +97,7 @@ __reExport(client_exports, require("./variable-usage"), module.exports);
|
|
|
95
97
|
...require("./url"),
|
|
96
98
|
...require("./transformMultiColumnToSingleColumn"),
|
|
97
99
|
...require("./transformFilter"),
|
|
98
|
-
...require("./variable-usage")
|
|
100
|
+
...require("./variable-usage"),
|
|
101
|
+
...require("./run-sql"),
|
|
102
|
+
...require("./liquidjs")
|
|
99
103
|
});
|
package/lib/common.js
CHANGED
|
@@ -67,7 +67,7 @@ const isEmpty = /* @__PURE__ */ __name((value) => {
|
|
|
67
67
|
if (Array.isArray(value)) {
|
|
68
68
|
return value.length === 0;
|
|
69
69
|
}
|
|
70
|
-
return
|
|
70
|
+
return false;
|
|
71
71
|
}, "isEmpty");
|
|
72
72
|
const isPlainObject = /* @__PURE__ */ __name((value) => {
|
|
73
73
|
if (Object.prototype.toString.call(value) !== "[object Object]") {
|
|
@@ -154,6 +154,11 @@ const removeNullCondition = /* @__PURE__ */ __name((filter, customFlat = import_
|
|
|
154
154
|
}
|
|
155
155
|
}
|
|
156
156
|
const result = customFlat.unflatten(values);
|
|
157
|
+
for (const key in result) {
|
|
158
|
+
if (Array.isArray(result[key])) {
|
|
159
|
+
result[key] = result[key].filter((item) => item != null);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
157
162
|
return import_lodash.default.isEmpty(result) ? void 0 : result;
|
|
158
163
|
}, "removeNullCondition");
|
|
159
164
|
// Annotate the CommonJS export names for ESM import in node:
|
package/lib/i18n.d.ts
CHANGED
|
@@ -7,4 +7,7 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
import { TFuncKey, TOptions } from 'i18next';
|
|
10
|
+
/**
|
|
11
|
+
* @deprecated use tExpr from @nocobase/flow-engine instead
|
|
12
|
+
*/
|
|
10
13
|
export declare function tval(text: TFuncKey | TFuncKey[], options?: TOptions): string;
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -77,6 +77,8 @@ __reExport(src_exports, require("./uid"), module.exports);
|
|
|
77
77
|
__reExport(src_exports, require("./url"), module.exports);
|
|
78
78
|
__reExport(src_exports, require("./variable-usage"), module.exports);
|
|
79
79
|
__reExport(src_exports, require("./wrap-middleware"), module.exports);
|
|
80
|
+
__reExport(src_exports, require("./run-sql"), module.exports);
|
|
81
|
+
__reExport(src_exports, require("./liquidjs"), module.exports);
|
|
80
82
|
// Annotate the CommonJS export names for ESM import in node:
|
|
81
83
|
0 && (module.exports = {
|
|
82
84
|
Schema,
|
|
@@ -113,5 +115,7 @@ __reExport(src_exports, require("./wrap-middleware"), module.exports);
|
|
|
113
115
|
...require("./uid"),
|
|
114
116
|
...require("./url"),
|
|
115
117
|
...require("./variable-usage"),
|
|
116
|
-
...require("./wrap-middleware")
|
|
118
|
+
...require("./wrap-middleware"),
|
|
119
|
+
...require("./run-sql"),
|
|
120
|
+
...require("./liquidjs")
|
|
117
121
|
});
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
export declare function transformLiquidContext(paths?: any[]): {};
|
|
10
|
+
export declare function getLiquidContext(template: string): Promise<{}>;
|
|
11
|
+
export declare function parseLiquidContext(template: string, liquidContext: any): Promise<any>;
|
package/lib/liquidjs.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var __defProp = Object.defineProperty;
|
|
11
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
12
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
13
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
15
|
+
var __export = (target, all) => {
|
|
16
|
+
for (var name in all)
|
|
17
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
18
|
+
};
|
|
19
|
+
var __copyProps = (to, from, except, desc) => {
|
|
20
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
21
|
+
for (let key of __getOwnPropNames(from))
|
|
22
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
23
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
24
|
+
}
|
|
25
|
+
return to;
|
|
26
|
+
};
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
+
var liquidjs_exports = {};
|
|
29
|
+
__export(liquidjs_exports, {
|
|
30
|
+
getLiquidContext: () => getLiquidContext,
|
|
31
|
+
parseLiquidContext: () => parseLiquidContext,
|
|
32
|
+
transformLiquidContext: () => transformLiquidContext
|
|
33
|
+
});
|
|
34
|
+
module.exports = __toCommonJS(liquidjs_exports);
|
|
35
|
+
var import_liquidjs = require("liquidjs");
|
|
36
|
+
const liquid = new import_liquidjs.Liquid();
|
|
37
|
+
function transformLiquidContext(paths = []) {
|
|
38
|
+
const result = {};
|
|
39
|
+
for (const fullPath of paths) {
|
|
40
|
+
const path = fullPath.replace(/^ctx\./, "");
|
|
41
|
+
const keys = path.split(".");
|
|
42
|
+
let current = result;
|
|
43
|
+
for (let i = 0; i < keys.length; i++) {
|
|
44
|
+
const key = keys[i];
|
|
45
|
+
const isLast = i === keys.length - 1;
|
|
46
|
+
if (isLast) {
|
|
47
|
+
current[key] = `{{${fullPath}}}`;
|
|
48
|
+
} else {
|
|
49
|
+
current[key] = current[key] || {};
|
|
50
|
+
current = current[key];
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return result;
|
|
55
|
+
}
|
|
56
|
+
__name(transformLiquidContext, "transformLiquidContext");
|
|
57
|
+
async function getLiquidContext(template) {
|
|
58
|
+
const vars = await liquid.fullVariables(template);
|
|
59
|
+
return transformLiquidContext(vars);
|
|
60
|
+
}
|
|
61
|
+
__name(getLiquidContext, "getLiquidContext");
|
|
62
|
+
async function parseLiquidContext(template, liquidContext) {
|
|
63
|
+
return await liquid.parseAndRender(template, { ctx: liquidContext });
|
|
64
|
+
}
|
|
65
|
+
__name(parseLiquidContext, "parseLiquidContext");
|
|
66
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
67
|
+
0 && (module.exports = {
|
|
68
|
+
getLiquidContext,
|
|
69
|
+
parseLiquidContext,
|
|
70
|
+
transformLiquidContext
|
|
71
|
+
});
|
package/lib/run-sql.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
export declare function parseSQLBindParams(template: string): {
|
|
10
|
+
sql: string;
|
|
11
|
+
bind: {};
|
|
12
|
+
};
|
|
13
|
+
export declare function transformSQL(template: string): Promise<{
|
|
14
|
+
sql: string;
|
|
15
|
+
bind: {};
|
|
16
|
+
liquidContext: {};
|
|
17
|
+
}>;
|
package/lib/run-sql.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* This file is part of the NocoBase (R) project.
|
|
3
|
+
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
|
|
4
|
+
* Authors: NocoBase Team.
|
|
5
|
+
*
|
|
6
|
+
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
|
+
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
var __defProp = Object.defineProperty;
|
|
11
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
12
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
13
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
14
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
15
|
+
var __export = (target, all) => {
|
|
16
|
+
for (var name in all)
|
|
17
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
18
|
+
};
|
|
19
|
+
var __copyProps = (to, from, except, desc) => {
|
|
20
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
21
|
+
for (let key of __getOwnPropNames(from))
|
|
22
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
23
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
24
|
+
}
|
|
25
|
+
return to;
|
|
26
|
+
};
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
+
var run_sql_exports = {};
|
|
29
|
+
__export(run_sql_exports, {
|
|
30
|
+
parseSQLBindParams: () => parseSQLBindParams,
|
|
31
|
+
transformSQL: () => transformSQL
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(run_sql_exports);
|
|
34
|
+
var import_liquidjs = require("./liquidjs");
|
|
35
|
+
function parseSQLBindParams(template) {
|
|
36
|
+
let index = 1;
|
|
37
|
+
const bind = {};
|
|
38
|
+
const sql = template.replace(/{{\s*([^}]+)\s*}}/g, (_, expr) => {
|
|
39
|
+
const key = `__var${index}`;
|
|
40
|
+
bind[key] = `{{${expr.trim()}}}`;
|
|
41
|
+
index++;
|
|
42
|
+
return `$${key}`;
|
|
43
|
+
});
|
|
44
|
+
return { sql, bind };
|
|
45
|
+
}
|
|
46
|
+
__name(parseSQLBindParams, "parseSQLBindParams");
|
|
47
|
+
async function transformSQL(template) {
|
|
48
|
+
const { sql, bind } = parseSQLBindParams(template);
|
|
49
|
+
const liquidContext = await (0, import_liquidjs.getLiquidContext)(sql);
|
|
50
|
+
return { sql, bind, liquidContext };
|
|
51
|
+
}
|
|
52
|
+
__name(transformSQL, "transformSQL");
|
|
53
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
54
|
+
0 && (module.exports = {
|
|
55
|
+
parseSQLBindParams,
|
|
56
|
+
transformSQL
|
|
57
|
+
});
|
package/lib/transformFilter.d.ts
CHANGED
package/lib/transformFilter.js
CHANGED
|
@@ -28,11 +28,13 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
28
28
|
var transformFilter_exports = {};
|
|
29
29
|
__export(transformFilter_exports, {
|
|
30
30
|
evaluateConditions: () => evaluateConditions,
|
|
31
|
+
removeInvalidFilterItems: () => removeInvalidFilterItems,
|
|
31
32
|
transformFilter: () => transformFilter
|
|
32
33
|
});
|
|
33
34
|
module.exports = __toCommonJS(transformFilter_exports);
|
|
35
|
+
var import_common = require("./common");
|
|
34
36
|
function isFilterCondition(item) {
|
|
35
|
-
return "path" in item && "operator" in item
|
|
37
|
+
return "path" in item && "operator" in item;
|
|
36
38
|
}
|
|
37
39
|
__name(isFilterCondition, "isFilterCondition");
|
|
38
40
|
function isFilterGroup(item) {
|
|
@@ -74,9 +76,30 @@ function transformFilter(filter) {
|
|
|
74
76
|
if (!Array.isArray(filter.items)) {
|
|
75
77
|
throw new Error("Invalid filter: items must be an array");
|
|
76
78
|
}
|
|
77
|
-
return transformGroup(filter);
|
|
79
|
+
return (0, import_common.removeNullCondition)(transformGroup(filter));
|
|
78
80
|
}
|
|
79
81
|
__name(transformFilter, "transformFilter");
|
|
82
|
+
function removeInvalidFilterItems(filter) {
|
|
83
|
+
if (!filter || typeof filter !== "object") {
|
|
84
|
+
throw new Error("Invalid filter: filter must be an object");
|
|
85
|
+
}
|
|
86
|
+
if (!isFilterGroup(filter)) {
|
|
87
|
+
throw new Error("Invalid filter: filter must have logic and items properties");
|
|
88
|
+
}
|
|
89
|
+
if (!Array.isArray(filter.items)) {
|
|
90
|
+
throw new Error("Invalid filter: items must be an array");
|
|
91
|
+
}
|
|
92
|
+
filter.items = filter.items.filter((item) => {
|
|
93
|
+
if (isFilterCondition(item)) {
|
|
94
|
+
return !!item.operator;
|
|
95
|
+
} else if (isFilterGroup(item)) {
|
|
96
|
+
return removeInvalidFilterItems(item);
|
|
97
|
+
}
|
|
98
|
+
return false;
|
|
99
|
+
});
|
|
100
|
+
return { ...filter };
|
|
101
|
+
}
|
|
102
|
+
__name(removeInvalidFilterItems, "removeInvalidFilterItems");
|
|
80
103
|
function evaluateCondition(condition, evaluator) {
|
|
81
104
|
const { path, operator, value } = condition;
|
|
82
105
|
return evaluator(path, operator, value);
|
|
@@ -124,5 +147,6 @@ __name(evaluateConditions, "evaluateConditions");
|
|
|
124
147
|
// Annotate the CommonJS export names for ESM import in node:
|
|
125
148
|
0 && (module.exports = {
|
|
126
149
|
evaluateConditions,
|
|
150
|
+
removeInvalidFilterItems,
|
|
127
151
|
transformFilter
|
|
128
152
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/utils",
|
|
3
|
-
"version": "2.0.0-alpha.
|
|
3
|
+
"version": "2.0.0-alpha.71",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"types": "./lib/index.d.ts",
|
|
6
6
|
"license": "AGPL-3.0",
|
|
@@ -11,10 +11,12 @@
|
|
|
11
11
|
"dayjs": "^1.11.9",
|
|
12
12
|
"deepmerge": "^4.2.2",
|
|
13
13
|
"flat-to-nested": "^1.1.1",
|
|
14
|
+
"fs-extra": "^11.1.1",
|
|
14
15
|
"graphlib": "^2.1.8",
|
|
15
16
|
"handlebars": "^4.7.8",
|
|
17
|
+
"liquidjs": "^10.23.0",
|
|
16
18
|
"multer": "^1.4.5-lts.2",
|
|
17
19
|
"object-path": "^0.11.8"
|
|
18
20
|
},
|
|
19
|
-
"gitHead": "
|
|
21
|
+
"gitHead": "b6fc484eb698fa12fba02dd468a04e39079b1e79"
|
|
20
22
|
}
|
package/plugin-symlink.js
CHANGED
|
@@ -1,107 +1,184 @@
|
|
|
1
|
-
const {
|
|
2
|
-
const
|
|
1
|
+
const { resolve } = require('path');
|
|
2
|
+
const fs = require('fs-extra');
|
|
3
3
|
|
|
4
|
+
/**
|
|
5
|
+
* Recursively get plugin names from a directory
|
|
6
|
+
* @param {string} target - Target directory to scan
|
|
7
|
+
* @returns {Promise<string[]>} Array of plugin names
|
|
8
|
+
*/
|
|
4
9
|
async function getStoragePluginNames(target) {
|
|
5
10
|
const plugins = [];
|
|
6
|
-
const items = await readdir(target);
|
|
11
|
+
const items = await fs.readdir(target);
|
|
12
|
+
|
|
7
13
|
for (const item of items) {
|
|
14
|
+
const itemPath = resolve(target, item);
|
|
15
|
+
|
|
8
16
|
if (item.startsWith('@')) {
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
if (!s.isDirectory()) {
|
|
17
|
+
const statResult = await fs.stat(itemPath);
|
|
18
|
+
if (!statResult.isDirectory()) {
|
|
12
19
|
continue;
|
|
13
20
|
}
|
|
14
|
-
const children = await getStoragePluginNames(
|
|
15
|
-
plugins.push(
|
|
16
|
-
|
|
17
|
-
return `${item}/${child}`;
|
|
18
|
-
}),
|
|
19
|
-
);
|
|
20
|
-
} else if (await fsExists(resolve(target, item, 'package.json'))) {
|
|
21
|
+
const children = await getStoragePluginNames(itemPath);
|
|
22
|
+
plugins.push(...children.map((child) => `${item}/${child}`));
|
|
23
|
+
} else if (await fs.pathExists(resolve(itemPath, 'package.json'))) {
|
|
21
24
|
plugins.push(item);
|
|
22
25
|
}
|
|
23
26
|
}
|
|
27
|
+
|
|
24
28
|
return plugins;
|
|
25
29
|
}
|
|
26
30
|
|
|
27
|
-
|
|
31
|
+
/**
|
|
32
|
+
* Ensure the organization directory exists for scoped packages
|
|
33
|
+
* @param {string} nodeModulesPath - Path to node_modules
|
|
34
|
+
* @param {string} pluginName - Plugin name (may be scoped)
|
|
35
|
+
* @returns {Promise<void>}
|
|
36
|
+
*/
|
|
37
|
+
async function ensureOrgDirectory(nodeModulesPath, pluginName) {
|
|
38
|
+
if (pluginName.startsWith('@')) {
|
|
39
|
+
const [orgName] = pluginName.split('/');
|
|
40
|
+
const orgPath = resolve(nodeModulesPath, orgName);
|
|
41
|
+
await fs.ensureDir(orgPath);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Check if a symlink already points to the correct target
|
|
47
|
+
* @param {string} linkPath - Path to the symlink
|
|
48
|
+
* @param {string} targetPath - Expected target path
|
|
49
|
+
* @returns {Promise<boolean>} True if symlink exists and points to target
|
|
50
|
+
*/
|
|
51
|
+
async function isSymlinkValid(linkPath, targetPath) {
|
|
28
52
|
try {
|
|
29
|
-
await
|
|
30
|
-
|
|
53
|
+
if (await fs.pathExists(linkPath)) {
|
|
54
|
+
const realPath = await fs.realpath(linkPath);
|
|
55
|
+
return realPath === targetPath;
|
|
56
|
+
}
|
|
31
57
|
} catch (error) {
|
|
58
|
+
// If realpath fails, the symlink is invalid
|
|
32
59
|
return false;
|
|
33
60
|
}
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Remove an existing symlink or file at the given path
|
|
66
|
+
* @param {string} linkPath - Path to remove
|
|
67
|
+
* @param {string} pluginName - Plugin name for error messages
|
|
68
|
+
* @param {string} pluginType - Type of plugin ('storage' or 'dev') for error messages
|
|
69
|
+
* @returns {Promise<void>}
|
|
70
|
+
*/
|
|
71
|
+
async function removeExistingLink(linkPath, pluginName, pluginType) {
|
|
72
|
+
try {
|
|
73
|
+
await fs.remove(linkPath);
|
|
74
|
+
} catch (error) {
|
|
75
|
+
// Ignore ENOENT errors (file doesn't exist)
|
|
76
|
+
if (error.code !== 'ENOENT') {
|
|
77
|
+
console.error(`Failed to remove existing symlink for ${pluginType} plugin: ${pluginName}`, error.message);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
34
80
|
}
|
|
35
81
|
|
|
36
|
-
|
|
82
|
+
/**
|
|
83
|
+
* Create a symlink for a plugin
|
|
84
|
+
* @param {string} pluginName - Name of the plugin
|
|
85
|
+
* @param {string} sourcePath - Source directory path
|
|
86
|
+
* @param {string} nodeModulesPath - Target node_modules path
|
|
87
|
+
* @param {string} pluginType - Type of plugin ('storage' or 'dev')
|
|
88
|
+
* @returns {Promise<void>}
|
|
89
|
+
*/
|
|
90
|
+
async function createPluginSymLink(pluginName, sourcePath, nodeModulesPath, pluginType) {
|
|
91
|
+
if (!nodeModulesPath) {
|
|
92
|
+
console.error(`NODE_MODULES_PATH is not set, cannot create symlink for ${pluginType} plugin: ${pluginName}`);
|
|
93
|
+
return;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
const distClientIndexPath = resolve(sourcePath, pluginName, 'dist', 'client', 'index.js');
|
|
97
|
+
|
|
98
|
+
if (await fs.pathExists(distClientIndexPath)) {
|
|
99
|
+
// Update the mtime of distClientIndexPath
|
|
100
|
+
const now = new Date();
|
|
101
|
+
await fs.utimes(distClientIndexPath, now, now);
|
|
102
|
+
}
|
|
37
103
|
|
|
38
|
-
async function createStoragePluginSymLink(pluginName) {
|
|
39
|
-
const storagePluginsPath = resolve(process.cwd(), 'storage/plugins');
|
|
40
|
-
const nodeModulesPath = process.env.NODE_MODULES_PATH; // resolve(dirname(require.resolve('@nocobase/server/package.json')), 'node_modules');
|
|
41
|
-
// const nodeModulesPath = resolve(process.cwd(), 'node_modules');
|
|
42
104
|
try {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
}
|
|
105
|
+
const targetPath = resolve(sourcePath, pluginName);
|
|
106
|
+
|
|
107
|
+
// Check if source exists
|
|
108
|
+
if (!(await fs.pathExists(targetPath))) {
|
|
109
|
+
console.warn(`Source path does not exist for ${pluginType} plugin: ${pluginName} at ${targetPath}`);
|
|
110
|
+
return;
|
|
48
111
|
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
112
|
+
|
|
113
|
+
// Ensure organization directory exists for scoped packages
|
|
114
|
+
await ensureOrgDirectory(nodeModulesPath, pluginName);
|
|
115
|
+
|
|
116
|
+
const linkPath = resolve(nodeModulesPath, pluginName);
|
|
117
|
+
|
|
118
|
+
// Check if symlink already points to the correct target
|
|
119
|
+
if (await isSymlinkValid(linkPath, targetPath)) {
|
|
120
|
+
return; // Symlink is already correct, no need to recreate
|
|
52
121
|
}
|
|
53
|
-
|
|
122
|
+
|
|
123
|
+
// Remove existing link if it exists
|
|
124
|
+
await removeExistingLink(linkPath, pluginName, pluginType);
|
|
125
|
+
|
|
126
|
+
// Create new symlink
|
|
127
|
+
await fs.symlink(targetPath, linkPath, 'dir');
|
|
54
128
|
} catch (error) {
|
|
55
|
-
console.error(error);
|
|
129
|
+
console.error(`Failed to create symlink for ${pluginType} plugin: ${pluginName}`, error.message);
|
|
56
130
|
}
|
|
57
131
|
}
|
|
58
132
|
|
|
59
|
-
|
|
133
|
+
/**
|
|
134
|
+
* Create a symlink for a storage plugin
|
|
135
|
+
* @param {string} pluginName - Name of the plugin
|
|
136
|
+
* @returns {Promise<void>}
|
|
137
|
+
*/
|
|
138
|
+
async function createStoragePluginSymLink(pluginName) {
|
|
139
|
+
const storagePluginsPath = resolve(process.cwd(), 'storage/plugins');
|
|
140
|
+
const nodeModulesPath = process.env.NODE_MODULES_PATH;
|
|
141
|
+
await createPluginSymLink(pluginName, storagePluginsPath, nodeModulesPath, 'storage');
|
|
142
|
+
}
|
|
60
143
|
|
|
144
|
+
/**
|
|
145
|
+
* Create symlinks for all storage plugins
|
|
146
|
+
* @returns {Promise<void>}
|
|
147
|
+
*/
|
|
61
148
|
async function createStoragePluginsSymlink() {
|
|
62
149
|
const storagePluginsPath = resolve(process.cwd(), 'storage/plugins');
|
|
63
|
-
if (!(await
|
|
150
|
+
if (!(await fs.pathExists(storagePluginsPath))) {
|
|
64
151
|
return;
|
|
65
152
|
}
|
|
66
153
|
const pluginNames = await getStoragePluginNames(storagePluginsPath);
|
|
67
154
|
await Promise.all(pluginNames.map((pluginName) => createStoragePluginSymLink(pluginName)));
|
|
68
155
|
}
|
|
69
156
|
|
|
70
|
-
|
|
71
|
-
|
|
157
|
+
/**
|
|
158
|
+
* Create a symlink for a dev plugin
|
|
159
|
+
* @param {string} pluginName - Name of the plugin
|
|
160
|
+
* @returns {Promise<void>}
|
|
161
|
+
*/
|
|
72
162
|
async function createDevPluginSymLink(pluginName) {
|
|
73
163
|
const packagePluginsPath = resolve(process.cwd(), 'packages/plugins');
|
|
74
|
-
const nodeModulesPath = process.env.NODE_MODULES_PATH;
|
|
75
|
-
|
|
76
|
-
if (pluginName.startsWith('@')) {
|
|
77
|
-
const [orgName] = pluginName.split('/');
|
|
78
|
-
if (!(await fsExists(resolve(nodeModulesPath, orgName)))) {
|
|
79
|
-
await mkdir(resolve(nodeModulesPath, orgName), { recursive: true });
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
const link = resolve(nodeModulesPath, pluginName);
|
|
83
|
-
if (await fsExists(link)) {
|
|
84
|
-
const real = await realpath(link);
|
|
85
|
-
if (real === resolve(packagePluginsPath, pluginName)) {
|
|
86
|
-
return;
|
|
87
|
-
}
|
|
88
|
-
await unlink(link);
|
|
89
|
-
}
|
|
90
|
-
await symlink(resolve(packagePluginsPath, pluginName), link, 'dir');
|
|
91
|
-
} catch (error) {
|
|
92
|
-
console.error(error);
|
|
93
|
-
}
|
|
164
|
+
const nodeModulesPath = process.env.NODE_MODULES_PATH;
|
|
165
|
+
await createPluginSymLink(pluginName, packagePluginsPath, nodeModulesPath, 'dev');
|
|
94
166
|
}
|
|
95
167
|
|
|
96
|
-
|
|
97
|
-
|
|
168
|
+
/**
|
|
169
|
+
* Create symlinks for all dev plugins
|
|
170
|
+
* @returns {Promise<void>}
|
|
171
|
+
*/
|
|
98
172
|
async function createDevPluginsSymlink() {
|
|
99
|
-
const
|
|
100
|
-
if (!(await
|
|
173
|
+
const packagePluginsPath = resolve(process.cwd(), 'packages/plugins');
|
|
174
|
+
if (!(await fs.pathExists(packagePluginsPath))) {
|
|
101
175
|
return;
|
|
102
176
|
}
|
|
103
|
-
const pluginNames = await getStoragePluginNames(
|
|
177
|
+
const pluginNames = await getStoragePluginNames(packagePluginsPath);
|
|
104
178
|
await Promise.all(pluginNames.map((pluginName) => createDevPluginSymLink(pluginName)));
|
|
105
179
|
}
|
|
106
180
|
|
|
181
|
+
exports.createStoragePluginSymLink = createStoragePluginSymLink;
|
|
182
|
+
exports.createStoragePluginsSymlink = createStoragePluginsSymlink;
|
|
183
|
+
exports.createDevPluginSymLink = createDevPluginSymLink;
|
|
107
184
|
exports.createDevPluginsSymlink = createDevPluginsSymlink;
|