@nocobase/plugin-data-source-main 2.0.0-alpha.9 → 2.1.0-alpha.1
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/dist/client/index.js +1 -1
- package/dist/externalVersion.js +8 -6
- package/dist/locale/de-DE.json +46 -2
- package/dist/locale/en-US.json +46 -2
- package/dist/locale/es-ES.json +48 -0
- package/dist/locale/fr-FR.json +48 -0
- package/dist/locale/hu-HU.json +48 -0
- package/dist/locale/id-ID.json +48 -0
- package/dist/locale/it-IT.json +46 -2
- package/dist/locale/ja-JP.json +45 -1
- package/dist/locale/ko-KR.json +48 -0
- package/dist/locale/nl-NL.json +46 -2
- package/dist/locale/pt-BR.json +48 -0
- package/dist/locale/ru-RU.json +48 -0
- package/dist/locale/tr-TR.json +48 -0
- package/dist/locale/uk-UA.json +48 -0
- package/dist/locale/vi-VN.json +48 -0
- package/dist/locale/zh-CN.json +46 -2
- package/dist/locale/zh-TW.json +48 -0
- package/dist/server/{hooks/afterCreateForReverseField.d.ts → constants.d.ts} +1 -4
- package/dist/server/{hooks/afterCreateForReverseField.js → constants.js} +6 -16
- package/dist/server/hooks/afterCreateForForeignKeyField.js +5 -3
- package/dist/server/hooks/index.d.ts +0 -1
- package/dist/server/hooks/index.js +0 -2
- package/dist/server/migrations/20251214100636-id2integer.d.ts +14 -0
- package/dist/server/migrations/20251214100636-id2integer.js +48 -0
- package/dist/server/models/collection.js +16 -10
- package/dist/server/resourcers/main-data-source.d.ts +17 -0
- package/dist/server/resourcers/main-data-source.js +52 -0
- package/dist/server/resourcers/views.js +1 -1
- package/dist/server/server.d.ts +1 -0
- package/dist/server/server.js +138 -52
- package/package.json +5 -2
package/dist/server/server.d.ts
CHANGED
package/dist/server/server.js
CHANGED
|
@@ -55,6 +55,10 @@ var import_beforeDestoryField = require("./hooks/beforeDestoryField");
|
|
|
55
55
|
var import_models = require("./models");
|
|
56
56
|
var import_collections = __toESM(require("./resourcers/collections"));
|
|
57
57
|
var import_views = __toESM(require("./resourcers/views"));
|
|
58
|
+
var import_main_data_source = __toESM(require("./resourcers/main-data-source"));
|
|
59
|
+
var import_constants = require("./constants");
|
|
60
|
+
var import_json_schema = require("@formily/json-schema");
|
|
61
|
+
var import_lodash2 = __toESM(require("lodash"));
|
|
58
62
|
class PluginDataSourceMainServer extends import_server.Plugin {
|
|
59
63
|
loadFilter = {};
|
|
60
64
|
db2cmCollections = [];
|
|
@@ -178,7 +182,24 @@ class PluginDataSourceMainServer extends import_server.Plugin {
|
|
|
178
182
|
}
|
|
179
183
|
});
|
|
180
184
|
this.app.db.on("fields.beforeCreate", (0, import_beforeCreateForValidateField.beforeCreateForValidateField)(this.app.db));
|
|
181
|
-
this.app.db.on("fields.afterCreate", (
|
|
185
|
+
this.app.db.on("fields.afterCreate", async (model, { transaction }) => {
|
|
186
|
+
const Field = this.app.db.getCollection("fields");
|
|
187
|
+
const reverseKey = model.get("reverseKey");
|
|
188
|
+
if (!reverseKey) {
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
const reverse = await Field.model.findByPk(reverseKey, { transaction });
|
|
192
|
+
await reverse.update({ reverseKey: model.get("key") }, { hooks: false, transaction });
|
|
193
|
+
this.sendSyncMessage(
|
|
194
|
+
{
|
|
195
|
+
type: "syncCollection",
|
|
196
|
+
collectionName: model.get("collectionName")
|
|
197
|
+
},
|
|
198
|
+
{
|
|
199
|
+
transaction
|
|
200
|
+
}
|
|
201
|
+
);
|
|
202
|
+
});
|
|
182
203
|
this.app.db.on("fields.beforeCreate", async (model, options) => {
|
|
183
204
|
const { transaction } = options;
|
|
184
205
|
const collectionName = model.get("collectionName");
|
|
@@ -357,7 +378,7 @@ class PluginDataSourceMainServer extends import_server.Plugin {
|
|
|
357
378
|
this.app.acl.allow("collectionCategories", "list", "loggedIn");
|
|
358
379
|
this.app.acl.registerSnippet({
|
|
359
380
|
name: `pm.data-source-manager.data-source-main`,
|
|
360
|
-
actions: ["collections:*", "collections.fields:*", "collectionCategories:*"]
|
|
381
|
+
actions: ["collections:*", "collections.fields:*", "collectionCategories:*", "mainDataSource:*"]
|
|
361
382
|
});
|
|
362
383
|
this.app.acl.registerSnippet({
|
|
363
384
|
name: `pm.data-source-manager.collection-view `,
|
|
@@ -382,52 +403,7 @@ class PluginDataSourceMainServer extends import_server.Plugin {
|
|
|
382
403
|
}
|
|
383
404
|
async load() {
|
|
384
405
|
this.db.getRepository("collections").setApp(this.app);
|
|
385
|
-
|
|
386
|
-
errorHandlerPlugin.errorHandler.register(
|
|
387
|
-
(err) => {
|
|
388
|
-
return err instanceof import_database.UniqueConstraintError;
|
|
389
|
-
},
|
|
390
|
-
(err, ctx) => {
|
|
391
|
-
return ctx.throw(400, ctx.t(`The value of ${Object.keys(err.fields)} field duplicated`));
|
|
392
|
-
}
|
|
393
|
-
);
|
|
394
|
-
errorHandlerPlugin.errorHandler.register(
|
|
395
|
-
(err) => err instanceof import_field_is_depended_on_by_other.FieldIsDependedOnByOtherError,
|
|
396
|
-
(err, ctx) => {
|
|
397
|
-
ctx.status = 400;
|
|
398
|
-
ctx.body = {
|
|
399
|
-
errors: [
|
|
400
|
-
{
|
|
401
|
-
message: ctx.i18n.t("field-is-depended-on-by-other", {
|
|
402
|
-
fieldName: err.options.fieldName,
|
|
403
|
-
fieldCollectionName: err.options.fieldCollectionName,
|
|
404
|
-
dependedFieldName: err.options.dependedFieldName,
|
|
405
|
-
dependedFieldCollectionName: err.options.dependedFieldCollectionName,
|
|
406
|
-
dependedFieldAs: err.options.dependedFieldAs,
|
|
407
|
-
ns: "data-source-main"
|
|
408
|
-
})
|
|
409
|
-
}
|
|
410
|
-
]
|
|
411
|
-
};
|
|
412
|
-
}
|
|
413
|
-
);
|
|
414
|
-
errorHandlerPlugin.errorHandler.register(
|
|
415
|
-
(err) => err instanceof import_field_name_exists_error.FieldNameExistsError,
|
|
416
|
-
(err, ctx) => {
|
|
417
|
-
ctx.status = 400;
|
|
418
|
-
ctx.body = {
|
|
419
|
-
errors: [
|
|
420
|
-
{
|
|
421
|
-
message: ctx.i18n.t("field-name-exists", {
|
|
422
|
-
name: err.value,
|
|
423
|
-
collectionName: err.collectionName,
|
|
424
|
-
ns: "data-source-main"
|
|
425
|
-
})
|
|
426
|
-
}
|
|
427
|
-
]
|
|
428
|
-
};
|
|
429
|
-
}
|
|
430
|
-
);
|
|
406
|
+
this.registerErrorHandler();
|
|
431
407
|
this.app.resourceManager.use(async function mergeReverseFieldWhenSaveCollectionField(ctx, next) {
|
|
432
408
|
if (ctx.action.resourceName === "collections.fields" && ["create", "update"].includes(ctx.action.actionName)) {
|
|
433
409
|
ctx.action.mergeParams({
|
|
@@ -436,9 +412,10 @@ class PluginDataSourceMainServer extends import_server.Plugin {
|
|
|
436
412
|
}
|
|
437
413
|
await next();
|
|
438
414
|
});
|
|
439
|
-
this.app.
|
|
440
|
-
this.app.
|
|
441
|
-
|
|
415
|
+
this.app.resourceManager.define(import_views.default);
|
|
416
|
+
this.app.resourceManager.registerActionHandlers(import_collections.default);
|
|
417
|
+
this.app.resourceManager.define(import_main_data_source.default);
|
|
418
|
+
const handleFieldSource = (fields, rawFields) => {
|
|
442
419
|
var _a;
|
|
443
420
|
for (const field of import_lodash.default.castArray(fields)) {
|
|
444
421
|
if (field.get("source")) {
|
|
@@ -456,6 +433,15 @@ class PluginDataSourceMainServer extends import_server.Plugin {
|
|
|
456
433
|
});
|
|
457
434
|
field.set("options", newOptions);
|
|
458
435
|
}
|
|
436
|
+
const fieldTypes = import_database.fieldTypeMap[this.db.options.dialect];
|
|
437
|
+
if (rawFields && fieldTypes) {
|
|
438
|
+
const rawField = rawFields[field.get("name")];
|
|
439
|
+
if (rawField && !import_constants.PRESET_FIELDS_INTERFACES.includes(field.get("interface"))) {
|
|
440
|
+
const mappedType = (0, import_database.extractTypeFromDefinition)(rawField.type);
|
|
441
|
+
const possibleTypes = fieldTypes[mappedType];
|
|
442
|
+
field.set("possibleTypes", possibleTypes);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
459
445
|
}
|
|
460
446
|
};
|
|
461
447
|
this.app.resourceManager.use(async function handleFieldSourceMiddleware(ctx, next) {
|
|
@@ -470,7 +456,18 @@ class PluginDataSourceMainServer extends import_server.Plugin {
|
|
|
470
456
|
}
|
|
471
457
|
}
|
|
472
458
|
if (ctx.action.resourceName == "collections.fields" && ctx.action.actionName == "list") {
|
|
473
|
-
|
|
459
|
+
const collectionName = ctx.action.sourceId;
|
|
460
|
+
const collection = ctx.db.getCollection(collectionName);
|
|
461
|
+
let rawFields = {};
|
|
462
|
+
if (collection) {
|
|
463
|
+
try {
|
|
464
|
+
rawFields = await ctx.app.db.queryInterface.sequelizeQueryInterface.describeTable(
|
|
465
|
+
collection.getTableNameWithSchema()
|
|
466
|
+
);
|
|
467
|
+
} catch (err) {
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
handleFieldSource(((_b = ctx.action.params) == null ? void 0 : _b.paginate) == "false" ? ctx.body : ctx.body.rows, rawFields);
|
|
474
471
|
}
|
|
475
472
|
if (ctx.action.resourceName == "collections.fields" && ctx.action.actionName == "get") {
|
|
476
473
|
handleFieldSource(ctx.body);
|
|
@@ -482,6 +479,95 @@ class PluginDataSourceMainServer extends import_server.Plugin {
|
|
|
482
479
|
origin: this.options.packageName
|
|
483
480
|
});
|
|
484
481
|
}
|
|
482
|
+
registerErrorHandler() {
|
|
483
|
+
const errorHandlerPlugin = this.app.pm.get("error-handler");
|
|
484
|
+
errorHandlerPlugin.errorHandler.register(
|
|
485
|
+
(err) => {
|
|
486
|
+
return err instanceof import_database.UniqueConstraintError;
|
|
487
|
+
},
|
|
488
|
+
(err, ctx) => {
|
|
489
|
+
return ctx.throw(400, ctx.t(`The value of ${Object.keys(err.fields)} field duplicated`));
|
|
490
|
+
}
|
|
491
|
+
);
|
|
492
|
+
errorHandlerPlugin.errorHandler.register(
|
|
493
|
+
(err) => err instanceof import_field_is_depended_on_by_other.FieldIsDependedOnByOtherError,
|
|
494
|
+
(err, ctx) => {
|
|
495
|
+
ctx.status = 400;
|
|
496
|
+
ctx.body = {
|
|
497
|
+
errors: [
|
|
498
|
+
{
|
|
499
|
+
message: ctx.i18n.t("field-is-depended-on-by-other", {
|
|
500
|
+
fieldName: err.options.fieldName,
|
|
501
|
+
fieldCollectionName: err.options.fieldCollectionName,
|
|
502
|
+
dependedFieldName: err.options.dependedFieldName,
|
|
503
|
+
dependedFieldCollectionName: err.options.dependedFieldCollectionName,
|
|
504
|
+
dependedFieldAs: err.options.dependedFieldAs,
|
|
505
|
+
ns: "data-source-main"
|
|
506
|
+
})
|
|
507
|
+
}
|
|
508
|
+
]
|
|
509
|
+
};
|
|
510
|
+
}
|
|
511
|
+
);
|
|
512
|
+
errorHandlerPlugin.errorHandler.register(
|
|
513
|
+
(err) => err instanceof import_field_name_exists_error.FieldNameExistsError,
|
|
514
|
+
(err, ctx) => {
|
|
515
|
+
ctx.status = 400;
|
|
516
|
+
ctx.body = {
|
|
517
|
+
errors: [
|
|
518
|
+
{
|
|
519
|
+
message: ctx.i18n.t("field-name-exists", {
|
|
520
|
+
name: err.value,
|
|
521
|
+
collectionName: err.collectionName,
|
|
522
|
+
ns: "data-source-main"
|
|
523
|
+
})
|
|
524
|
+
}
|
|
525
|
+
]
|
|
526
|
+
};
|
|
527
|
+
}
|
|
528
|
+
);
|
|
529
|
+
errorHandlerPlugin.errorHandler.register(
|
|
530
|
+
(err) => err instanceof import_database.JoiValidationError,
|
|
531
|
+
(err, ctx) => {
|
|
532
|
+
const t = ctx.i18n.t;
|
|
533
|
+
ctx.status = 400;
|
|
534
|
+
ctx.body = {
|
|
535
|
+
errors: err.details.map((detail) => {
|
|
536
|
+
const context = detail.context;
|
|
537
|
+
const label = context.label;
|
|
538
|
+
if (label) {
|
|
539
|
+
const [collectionName, fieldName] = label.split(".");
|
|
540
|
+
const collection = this.db.getCollection(collectionName);
|
|
541
|
+
if (collection) {
|
|
542
|
+
const collectionTitle = import_json_schema.Schema.compile(collection.options.title, { t });
|
|
543
|
+
const field = collection.getField(fieldName);
|
|
544
|
+
const fieldOptions = import_json_schema.Schema.compile(field == null ? void 0 : field.options, { t });
|
|
545
|
+
const fieldTitle = import_lodash2.default.get(fieldOptions, "uiSchema.title", fieldName);
|
|
546
|
+
context.label = `${t(collectionTitle, {
|
|
547
|
+
ns: ["lm-collections", "client"]
|
|
548
|
+
})}: ${t(fieldTitle, {
|
|
549
|
+
ns: ["lm-collections", "client"]
|
|
550
|
+
})}`;
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
if (context.regex) {
|
|
554
|
+
context.regex = context.regex.source;
|
|
555
|
+
}
|
|
556
|
+
let message = ctx.i18n.t(detail.type, {
|
|
557
|
+
...context,
|
|
558
|
+
ns: "data-source-main"
|
|
559
|
+
});
|
|
560
|
+
if (message === detail.type) {
|
|
561
|
+
message = err.message.replace(`"${label}"`, context.label);
|
|
562
|
+
}
|
|
563
|
+
return {
|
|
564
|
+
message
|
|
565
|
+
};
|
|
566
|
+
})
|
|
567
|
+
};
|
|
568
|
+
}
|
|
569
|
+
);
|
|
570
|
+
}
|
|
485
571
|
async install() {
|
|
486
572
|
const dataSourcesCollection = this.app.db.getCollection("dataSources");
|
|
487
573
|
if (dataSourcesCollection) {
|
package/package.json
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/plugin-data-source-main",
|
|
3
3
|
"displayName": "Data source: Main",
|
|
4
|
+
"displayName.ru-RU": "Основной Источник данных",
|
|
4
5
|
"displayName.zh-CN": "数据源:主数据库",
|
|
5
6
|
"description": "NocoBase main database, supports relational databases such as PostgreSQL, MySQL, MariaDB and so on.",
|
|
7
|
+
"description.ru-RU": "Основная база данных NocoBase: поддерживает реляционные СУБД, включая PostgreSQL, MySQL, MariaDB и другие.",
|
|
6
8
|
"description.zh-CN": "NocoBase 主数据库,支持 PostgreSQL、MySQL、MariaDB 等关系型数据库。",
|
|
7
|
-
"version": "2.
|
|
9
|
+
"version": "2.1.0-alpha.1",
|
|
8
10
|
"main": "./dist/server/index.js",
|
|
9
11
|
"homepage": "https://docs.nocobase.com/handbook/data-source-main",
|
|
12
|
+
"homepage.ru-RU": "https://docs-ru.nocobase.com/handbook/data-source-main",
|
|
10
13
|
"homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/data-source-main",
|
|
11
14
|
"license": "AGPL-3.0",
|
|
12
15
|
"devDependencies": {
|
|
@@ -22,7 +25,7 @@
|
|
|
22
25
|
"@nocobase/test": "2.x",
|
|
23
26
|
"@nocobase/utils": "2.x"
|
|
24
27
|
},
|
|
25
|
-
"gitHead": "
|
|
28
|
+
"gitHead": "d27baf21569643d6fa83f882233f4e90eb5b89f1",
|
|
26
29
|
"keywords": [
|
|
27
30
|
"Data sources"
|
|
28
31
|
]
|