@nocobase/database 0.14.0-alpha.2 → 0.14.0-alpha.4
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/collection-importer.js +4 -0
- package/lib/database.d.ts +1 -1
- package/lib/database.js +18 -13
- package/lib/helpers.d.ts +2 -0
- package/lib/helpers.js +120 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +3 -1
- package/lib/update-associations.js +0 -3
- package/lib/update-guard.d.ts +1 -0
- package/lib/update-guard.js +30 -0
- package/package.json +5 -4
|
@@ -32,6 +32,7 @@ __export(collection_importer_exports, {
|
|
|
32
32
|
});
|
|
33
33
|
module.exports = __toCommonJS(collection_importer_exports);
|
|
34
34
|
var import_path = __toESM(require("path"));
|
|
35
|
+
var import_fs = require("fs");
|
|
35
36
|
var import_promises = require("fs/promises");
|
|
36
37
|
var import_lodash = require("lodash");
|
|
37
38
|
var import_utils = require("@nocobase/utils");
|
|
@@ -46,6 +47,9 @@ const _ImporterReader = class _ImporterReader {
|
|
|
46
47
|
this.extensions = new Set(extensions);
|
|
47
48
|
}
|
|
48
49
|
async read() {
|
|
50
|
+
if (!(0, import_fs.existsSync)(this.directory)) {
|
|
51
|
+
return [];
|
|
52
|
+
}
|
|
49
53
|
const files = await (0, import_promises.readdir)(this.directory, {
|
|
50
54
|
encoding: "utf-8"
|
|
51
55
|
});
|
package/lib/database.d.ts
CHANGED
|
@@ -142,7 +142,7 @@ export declare class Database extends EventEmitter implements AsyncEmitter {
|
|
|
142
142
|
isSqliteMemory(): boolean;
|
|
143
143
|
auth(options?: Omit<QueryOptions, 'retry'> & {
|
|
144
144
|
retry?: number | Pick<QueryOptions, 'retry'>;
|
|
145
|
-
}): Promise<
|
|
145
|
+
}): Promise<void>;
|
|
146
146
|
prepare(): Promise<void>;
|
|
147
147
|
reconnect(): Promise<void>;
|
|
148
148
|
closed(): any;
|
package/lib/database.js
CHANGED
|
@@ -61,6 +61,7 @@ var import_query_interface_builder = __toESM(require("./query-interface/query-in
|
|
|
61
61
|
var import_utils2 = require("./utils");
|
|
62
62
|
var import_value_parsers = require("./value-parsers");
|
|
63
63
|
var import_view_collection = require("./view-collection");
|
|
64
|
+
var import_exponential_backoff = require("exponential-backoff");
|
|
64
65
|
const DialectVersionAccessors = {
|
|
65
66
|
sqlite: {
|
|
66
67
|
sql: "select sqlite_version() as version",
|
|
@@ -205,7 +206,6 @@ const _Database = class _Database extends import_events.EventEmitter {
|
|
|
205
206
|
migrations: this.migrations.callback(),
|
|
206
207
|
context,
|
|
207
208
|
storage: new import_umzug.SequelizeStorage({
|
|
208
|
-
modelName: `${this.options.tablePrefix || ""}migrations`,
|
|
209
209
|
...migratorOptions.storage,
|
|
210
210
|
sequelize: this.sequelize
|
|
211
211
|
})
|
|
@@ -525,25 +525,30 @@ const _Database = class _Database extends import_events.EventEmitter {
|
|
|
525
525
|
}
|
|
526
526
|
async auth(options = {}) {
|
|
527
527
|
const { retry = 10, ...others } = options;
|
|
528
|
-
const
|
|
529
|
-
|
|
528
|
+
const startingDelay = 50;
|
|
529
|
+
const timeMultiple = 2;
|
|
530
|
+
let attemptNumber = 1;
|
|
530
531
|
const authenticate = /* @__PURE__ */ __name(async () => {
|
|
531
532
|
try {
|
|
532
533
|
await this.sequelize.authenticate(others);
|
|
533
534
|
console.log("Connection has been established successfully.");
|
|
534
|
-
return true;
|
|
535
535
|
} catch (error) {
|
|
536
|
-
console.log(`Unable to connect to the database: ${error.message}`);
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
++count;
|
|
542
|
-
await delay(500);
|
|
543
|
-
return await authenticate();
|
|
536
|
+
console.log(`Attempt ${attemptNumber}/${retry}: Unable to connect to the database: ${error.message}`);
|
|
537
|
+
const nextDelay = startingDelay * Math.pow(timeMultiple, attemptNumber - 1);
|
|
538
|
+
console.log(`Will retry in ${nextDelay}ms...`);
|
|
539
|
+
attemptNumber++;
|
|
540
|
+
throw error;
|
|
544
541
|
}
|
|
545
542
|
}, "authenticate");
|
|
546
|
-
|
|
543
|
+
try {
|
|
544
|
+
await (0, import_exponential_backoff.backOff)(authenticate, {
|
|
545
|
+
numOfAttempts: retry,
|
|
546
|
+
startingDelay,
|
|
547
|
+
timeMultiple
|
|
548
|
+
});
|
|
549
|
+
} catch (error) {
|
|
550
|
+
throw new Error("Connection failed, please check your database connection credentials and try again.");
|
|
551
|
+
}
|
|
547
552
|
}
|
|
548
553
|
async prepare() {
|
|
549
554
|
if (this.inDialect("postgres") && this.options.schema && this.options.schema != "public") {
|
package/lib/helpers.d.ts
ADDED
package/lib/helpers.js
ADDED
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
|
|
8
|
+
var __export = (target, all) => {
|
|
9
|
+
for (var name in all)
|
|
10
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
11
|
+
};
|
|
12
|
+
var __copyProps = (to, from, except, desc) => {
|
|
13
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
14
|
+
for (let key of __getOwnPropNames(from))
|
|
15
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
16
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
17
|
+
}
|
|
18
|
+
return to;
|
|
19
|
+
};
|
|
20
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
21
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
22
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
23
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
24
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
25
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
26
|
+
mod
|
|
27
|
+
));
|
|
28
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
29
|
+
var helpers_exports = {};
|
|
30
|
+
__export(helpers_exports, {
|
|
31
|
+
parseDatabaseOptionsFromEnv: () => parseDatabaseOptionsFromEnv
|
|
32
|
+
});
|
|
33
|
+
module.exports = __toCommonJS(helpers_exports);
|
|
34
|
+
var import_fs = __toESM(require("fs"));
|
|
35
|
+
function getEnvValue(key, defaultValue) {
|
|
36
|
+
return process.env[key] || defaultValue;
|
|
37
|
+
}
|
|
38
|
+
__name(getEnvValue, "getEnvValue");
|
|
39
|
+
function isFilePath(value) {
|
|
40
|
+
return import_fs.default.promises.stat(value).then((stats) => stats.isFile()).catch((err) => {
|
|
41
|
+
if (err.code === "ENOENT") {
|
|
42
|
+
return false;
|
|
43
|
+
}
|
|
44
|
+
throw err;
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
__name(isFilePath, "isFilePath");
|
|
48
|
+
function getValueOrFileContent(envVarName) {
|
|
49
|
+
const value = getEnvValue(envVarName);
|
|
50
|
+
if (!value) {
|
|
51
|
+
return Promise.resolve(null);
|
|
52
|
+
}
|
|
53
|
+
return isFilePath(value).then((isFile) => {
|
|
54
|
+
if (isFile) {
|
|
55
|
+
return import_fs.default.promises.readFile(value, "utf8");
|
|
56
|
+
}
|
|
57
|
+
return value;
|
|
58
|
+
}).catch((error) => {
|
|
59
|
+
console.error(`Failed to read file content for environment variable ${envVarName}.`);
|
|
60
|
+
throw error;
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
__name(getValueOrFileContent, "getValueOrFileContent");
|
|
64
|
+
function extractSSLOptionsFromEnv() {
|
|
65
|
+
return Promise.all([
|
|
66
|
+
getValueOrFileContent("DB_DIALECT_OPTIONS_SSL_MODE"),
|
|
67
|
+
getValueOrFileContent("DB_DIALECT_OPTIONS_SSL_CA"),
|
|
68
|
+
getValueOrFileContent("DB_DIALECT_OPTIONS_SSL_KEY"),
|
|
69
|
+
getValueOrFileContent("DB_DIALECT_OPTIONS_SSL_CERT"),
|
|
70
|
+
getValueOrFileContent("DB_DIALECT_OPTIONS_SSL_REJECT_UNAUTHORIZED")
|
|
71
|
+
]).then(([mode, ca, key, cert, rejectUnauthorized]) => {
|
|
72
|
+
const sslOptions = {};
|
|
73
|
+
if (mode)
|
|
74
|
+
sslOptions["mode"] = mode;
|
|
75
|
+
if (ca)
|
|
76
|
+
sslOptions["ca"] = ca;
|
|
77
|
+
if (key)
|
|
78
|
+
sslOptions["key"] = key;
|
|
79
|
+
if (cert)
|
|
80
|
+
sslOptions["cert"] = cert;
|
|
81
|
+
if (rejectUnauthorized)
|
|
82
|
+
sslOptions["rejectUnauthorized"] = rejectUnauthorized === "true";
|
|
83
|
+
return sslOptions;
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
__name(extractSSLOptionsFromEnv, "extractSSLOptionsFromEnv");
|
|
87
|
+
async function parseDatabaseOptionsFromEnv() {
|
|
88
|
+
const databaseOptions = {
|
|
89
|
+
logging: process.env.DB_LOGGING == "on" ? customLogger : false,
|
|
90
|
+
dialect: process.env.DB_DIALECT,
|
|
91
|
+
storage: process.env.DB_STORAGE,
|
|
92
|
+
username: process.env.DB_USER,
|
|
93
|
+
password: process.env.DB_PASSWORD,
|
|
94
|
+
database: process.env.DB_DATABASE,
|
|
95
|
+
host: process.env.DB_HOST,
|
|
96
|
+
port: process.env.DB_PORT,
|
|
97
|
+
timezone: process.env.DB_TIMEZONE,
|
|
98
|
+
tablePrefix: process.env.DB_TABLE_PREFIX,
|
|
99
|
+
schema: process.env.DB_SCHEMA,
|
|
100
|
+
underscored: process.env.DB_UNDERSCORED === "true"
|
|
101
|
+
};
|
|
102
|
+
const sslOptions = await extractSSLOptionsFromEnv();
|
|
103
|
+
if (Object.keys(sslOptions).length) {
|
|
104
|
+
databaseOptions.dialectOptions = databaseOptions.dialectOptions || {};
|
|
105
|
+
databaseOptions.dialectOptions["ssl"] = sslOptions;
|
|
106
|
+
}
|
|
107
|
+
return databaseOptions;
|
|
108
|
+
}
|
|
109
|
+
__name(parseDatabaseOptionsFromEnv, "parseDatabaseOptionsFromEnv");
|
|
110
|
+
function customLogger(queryString, queryObject) {
|
|
111
|
+
console.log(queryString);
|
|
112
|
+
if (queryObject == null ? void 0 : queryObject.bind) {
|
|
113
|
+
console.log(queryObject.bind);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
__name(customLogger, "customLogger");
|
|
117
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
118
|
+
0 && (module.exports = {
|
|
119
|
+
parseDatabaseOptionsFromEnv
|
|
120
|
+
});
|
package/lib/index.d.ts
CHANGED
package/lib/index.js
CHANGED
|
@@ -75,6 +75,7 @@ var import_utils = require("./utils");
|
|
|
75
75
|
__reExport(src_exports, require("./value-parsers"), module.exports);
|
|
76
76
|
__reExport(src_exports, require("./view-collection"), module.exports);
|
|
77
77
|
__reExport(src_exports, require("./view/view-inference"), module.exports);
|
|
78
|
+
__reExport(src_exports, require("./helpers"), module.exports);
|
|
78
79
|
// Annotate the CommonJS export names for ESM import in node:
|
|
79
80
|
0 && (module.exports = {
|
|
80
81
|
BaseError,
|
|
@@ -116,5 +117,6 @@ __reExport(src_exports, require("./view/view-inference"), module.exports);
|
|
|
116
117
|
...require("./update-associations"),
|
|
117
118
|
...require("./value-parsers"),
|
|
118
119
|
...require("./view-collection"),
|
|
119
|
-
...require("./view/view-inference")
|
|
120
|
+
...require("./view/view-inference"),
|
|
121
|
+
...require("./helpers")
|
|
120
122
|
});
|
|
@@ -268,9 +268,6 @@ async function updateMultipleAssociation(model, key, value, options = {}) {
|
|
|
268
268
|
if (!association) {
|
|
269
269
|
return false;
|
|
270
270
|
}
|
|
271
|
-
if (association.through && association.through.model.options.view) {
|
|
272
|
-
return false;
|
|
273
|
-
}
|
|
274
271
|
if (!["undefined", "string", "number", "object"].includes(typeof value)) {
|
|
275
272
|
return false;
|
|
276
273
|
}
|
package/lib/update-guard.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ export declare class UpdateGuard {
|
|
|
18
18
|
setAssociationKeysToBeUpdate(associationKeysToBeUpdate: AssociationKeysToBeUpdate): void;
|
|
19
19
|
setWhiteList(whiteList: WhiteList): void;
|
|
20
20
|
setBlackList(blackList: BlackList): void;
|
|
21
|
+
checkValues(values: any): void;
|
|
21
22
|
/**
|
|
22
23
|
* Sanitize values by whitelist blacklist
|
|
23
24
|
* @param values
|
package/lib/update-guard.js
CHANGED
|
@@ -71,6 +71,35 @@ const _UpdateGuard = class _UpdateGuard {
|
|
|
71
71
|
setBlackList(blackList) {
|
|
72
72
|
this.blackList = blackList;
|
|
73
73
|
}
|
|
74
|
+
checkValues(values) {
|
|
75
|
+
const dfs = /* @__PURE__ */ __name((values2, model) => {
|
|
76
|
+
const associations = model.associations;
|
|
77
|
+
const belongsToManyThroughNames = [];
|
|
78
|
+
const associationValueKeys = Object.keys(associations).filter((key) => {
|
|
79
|
+
return Object.keys(values2).includes(key);
|
|
80
|
+
});
|
|
81
|
+
const belongsToManyValueKeys = associationValueKeys.filter((key) => {
|
|
82
|
+
return associations[key].associationType === "BelongsToMany";
|
|
83
|
+
});
|
|
84
|
+
const hasManyValueKeys = associationValueKeys.filter((key) => {
|
|
85
|
+
return associations[key].associationType === "HasMany";
|
|
86
|
+
});
|
|
87
|
+
for (const belongsToManyKey of belongsToManyValueKeys) {
|
|
88
|
+
const association = associations[belongsToManyKey];
|
|
89
|
+
const through = association.through.model;
|
|
90
|
+
belongsToManyThroughNames.push(through.name);
|
|
91
|
+
}
|
|
92
|
+
for (const hasManyKey of hasManyValueKeys) {
|
|
93
|
+
const association = associations[hasManyKey];
|
|
94
|
+
if (belongsToManyThroughNames.includes(association.target.name)) {
|
|
95
|
+
throw new Error(
|
|
96
|
+
`HasMany association ${hasManyKey} cannot be used with BelongsToMany association ${association.target.name} with same through model`
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}, "dfs");
|
|
101
|
+
dfs(values, this.model);
|
|
102
|
+
}
|
|
74
103
|
/**
|
|
75
104
|
* Sanitize values by whitelist blacklist
|
|
76
105
|
* @param values
|
|
@@ -80,6 +109,7 @@ const _UpdateGuard = class _UpdateGuard {
|
|
|
80
109
|
if (!this.model) {
|
|
81
110
|
throw new Error("please set model first");
|
|
82
111
|
}
|
|
112
|
+
this.checkValues(values);
|
|
83
113
|
const associations = this.model.associations;
|
|
84
114
|
const associationsValues = import_lodash.default.pick(values, Object.keys(associations));
|
|
85
115
|
const listOfAssociation = /* @__PURE__ */ __name((list, association) => {
|
package/package.json
CHANGED
|
@@ -1,18 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/database",
|
|
3
|
-
"version": "0.14.0-alpha.
|
|
3
|
+
"version": "0.14.0-alpha.4",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"types": "./lib/index.d.ts",
|
|
7
7
|
"license": "Apache-2.0",
|
|
8
8
|
"dependencies": {
|
|
9
|
-
"@nocobase/logger": "0.14.0-alpha.
|
|
10
|
-
"@nocobase/utils": "0.14.0-alpha.
|
|
9
|
+
"@nocobase/logger": "0.14.0-alpha.4",
|
|
10
|
+
"@nocobase/utils": "0.14.0-alpha.4",
|
|
11
11
|
"async-mutex": "^0.3.2",
|
|
12
12
|
"cron-parser": "4.4.0",
|
|
13
13
|
"dayjs": "^1.11.8",
|
|
14
14
|
"deepmerge": "^4.2.2",
|
|
15
15
|
"excel-date-to-js": "^1.1.5",
|
|
16
|
+
"exponential-backoff": "^3.1.1",
|
|
16
17
|
"flat": "^5.0.2",
|
|
17
18
|
"glob": "^7.1.6",
|
|
18
19
|
"graphlib": "^2.1.8",
|
|
@@ -29,5 +30,5 @@
|
|
|
29
30
|
"url": "git+https://github.com/nocobase/nocobase.git",
|
|
30
31
|
"directory": "packages/database"
|
|
31
32
|
},
|
|
32
|
-
"gitHead": "
|
|
33
|
+
"gitHead": "e2aab7863bbdfd76afc7164272b275e868ac59c0"
|
|
33
34
|
}
|