@nocobase/server 2.0.0-alpha.20 → 2.0.0-alpha.22

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.
@@ -33,11 +33,11 @@ import { PubSubManager, PubSubManagerOptions } from './pub-sub-manager';
33
33
  import { SyncMessageManager } from './sync-message-manager';
34
34
  import AesEncryptor from './aes-encryptor';
35
35
  import { AuditManager } from './audit-manager';
36
+ import { BackgroundJobManager, BackgroundJobManagerOptions } from './background-job-manager';
36
37
  import { Environment } from './environment';
37
- import { ServiceContainer } from './service-container';
38
38
  import { EventQueue, EventQueueOptions } from './event-queue';
39
- import { BackgroundJobManager, BackgroundJobManagerOptions } from './background-job-manager';
40
39
  import { RedisConfig, RedisConnectionManager } from './redis-connection-manager';
40
+ import { ServiceContainer } from './service-container';
41
41
  import { WorkerIdAllocator } from './worker-id-allocator';
42
42
  export type PluginType = string | typeof Plugin;
43
43
  export type PluginConfiguration = PluginType | [PluginType, any];
@@ -219,7 +219,7 @@ export declare class Application<StateT = DefaultState, ContextT = DefaultContex
219
219
  get environment(): Environment;
220
220
  protected _cronJobManager: CronJobManager;
221
221
  get cronJobManager(): CronJobManager;
222
- get mainDataSource(): SequelizeDataSource;
222
+ get mainDataSource(): SequelizeDataSource<import("@nocobase/data-source-manager").DatabaseIntrospector>;
223
223
  get db(): Database;
224
224
  get resourceManager(): import("@nocobase/resourcer").ResourceManager;
225
225
  /**
@@ -50,8 +50,8 @@ var import_database = __toESM(require("@nocobase/database"));
50
50
  var import_logger = require("@nocobase/logger");
51
51
  var import_telemetry = require("@nocobase/telemetry");
52
52
  var import_lock_manager = require("@nocobase/lock-manager");
53
- var import_utils = require("@nocobase/utils");
54
53
  var import_snowflake_id = require("@nocobase/snowflake-id");
54
+ var import_utils = require("@nocobase/utils");
55
55
  var import_crypto = require("crypto");
56
56
  var import_glob = __toESM(require("glob"));
57
57
  var import_koa = __toESM(require("koa"));
@@ -80,13 +80,13 @@ var import_package = __toESM(require("../package.json"));
80
80
  var import_available_action = require("./acl/available-action");
81
81
  var import_aes_encryptor = __toESM(require("./aes-encryptor"));
82
82
  var import_audit_manager = require("./audit-manager");
83
+ var import_background_job_manager = require("./background-job-manager");
83
84
  var import_environment = require("./environment");
84
- var import_service_container = require("./service-container");
85
85
  var import_event_queue = require("./event-queue");
86
- var import_background_job_manager = require("./background-job-manager");
87
86
  var import_redis_connection_manager = require("./redis-connection-manager");
88
- var import_worker_id_allocator = require("./worker-id-allocator");
87
+ var import_service_container = require("./service-container");
89
88
  var import_snowflake_id_field = require("./snowflake-id-field");
89
+ var import_worker_id_allocator = require("./worker-id-allocator");
90
90
  const _Application = class _Application extends import_koa.default {
91
91
  constructor(options) {
92
92
  super();
@@ -777,6 +777,12 @@ const _Application = class _Application extends import_koa.default {
777
777
  }
778
778
  async upgrade(options = {}) {
779
779
  this.log.info("upgrading...");
780
+ const pkgVersion = this.getPackageVersion();
781
+ const appVersion = await this.version.get();
782
+ if (process.env.SKIP_SAME_VERSION_UPGRADE === "true" && pkgVersion === appVersion) {
783
+ this.log.info(`app is already the latest version (${appVersion})`);
784
+ return;
785
+ }
780
786
  await this.reInit();
781
787
  const migrator1 = await this.loadCoreMigrations();
782
788
  await migrator1.beforeLoad.up();
package/lib/index.d.ts CHANGED
@@ -22,6 +22,7 @@ export * from './event-queue';
22
22
  export * from './background-job-manager';
23
23
  export * from './worker-id-allocator';
24
24
  export * from './redis-connection-manager';
25
+ export * from './main-data-source';
25
26
  export declare const OFFICIAL_PLUGIN_PREFIX = "@nocobase/plugin-";
26
27
  export { appendToBuiltInPlugins, findAllPlugins, findBuiltInPlugins, findLocalPlugins, packageNameTrim, } from './plugin-manager/findPackageNames';
27
28
  export { runPluginStaticImports } from './run-plugin-static-imports';
package/lib/index.js CHANGED
@@ -64,6 +64,7 @@ __reExport(src_exports, require("./event-queue"), module.exports);
64
64
  __reExport(src_exports, require("./background-job-manager"), module.exports);
65
65
  __reExport(src_exports, require("./worker-id-allocator"), module.exports);
66
66
  __reExport(src_exports, require("./redis-connection-manager"), module.exports);
67
+ __reExport(src_exports, require("./main-data-source"), module.exports);
67
68
  var import_findPackageNames = require("./plugin-manager/findPackageNames");
68
69
  var import_run_plugin_static_imports = require("./run-plugin-static-imports");
69
70
  const OFFICIAL_PLUGIN_PREFIX = "@nocobase/plugin-";
@@ -90,5 +91,6 @@ const OFFICIAL_PLUGIN_PREFIX = "@nocobase/plugin-";
90
91
  ...require("./event-queue"),
91
92
  ...require("./background-job-manager"),
92
93
  ...require("./worker-id-allocator"),
93
- ...require("./redis-connection-manager")
94
+ ...require("./redis-connection-manager"),
95
+ ...require("./main-data-source")
94
96
  });
@@ -138,7 +138,7 @@ const _Locale = class _Locale {
138
138
  if (!packageName) {
139
139
  continue;
140
140
  }
141
- const res = (0, import_resource.getResource)(packageName, lang);
141
+ const res = await (0, import_resource.getResource)(packageName, lang);
142
142
  if (res) {
143
143
  resources[packageName] = { ...res };
144
144
  if (packageName.includes(import__.OFFICIAL_PLUGIN_PREFIX)) {
@@ -40,7 +40,7 @@ __export(resource_exports, {
40
40
  getResource: () => getResource
41
41
  });
42
42
  module.exports = __toCommonJS(resource_exports);
43
- var import_utils = require("@nocobase/utils");
43
+ var import_promises = __toESM(require("fs/promises"));
44
44
  const arr2obj = /* @__PURE__ */ __name((items) => {
45
45
  const obj = {};
46
46
  for (const item of items) {
@@ -48,7 +48,7 @@ const arr2obj = /* @__PURE__ */ __name((items) => {
48
48
  }
49
49
  return obj;
50
50
  }, "arr2obj");
51
- const getResource = /* @__PURE__ */ __name((packageName, lang, isPlugin = true) => {
51
+ const getResource = /* @__PURE__ */ __name(async (packageName, lang, isPlugin = true) => {
52
52
  const resources = [];
53
53
  const prefixes = [isPlugin ? "dist" : "lib"];
54
54
  if (process.env.APP_ENV !== "production") {
@@ -70,13 +70,10 @@ const getResource = /* @__PURE__ */ __name((packageName, lang, isPlugin = true)
70
70
  }
71
71
  for (const prefix of prefixes) {
72
72
  try {
73
- const file = `${packageName}/${prefix}/locale/${lang}`;
73
+ const file = `${packageName}/${prefix}/locale/${lang}.json`;
74
74
  const f = require.resolve(file);
75
- if (process.env.APP_ENV !== "production") {
76
- delete require.cache[f];
77
- }
78
- const resource = (0, import_utils.requireModule)(file);
79
- resources.push(resource);
75
+ const resource = await import_promises.default.readFile(f, "utf8");
76
+ resources.push(JSON.parse(resource));
80
77
  } catch (error) {
81
78
  }
82
79
  if (resources.length) {
@@ -84,7 +81,7 @@ const getResource = /* @__PURE__ */ __name((packageName, lang, isPlugin = true)
84
81
  }
85
82
  }
86
83
  if (resources.length === 0 && lang.replace("-", "_") !== lang) {
87
- return getResource(packageName, lang.replace("-", "_"));
84
+ return await getResource(packageName, lang.replace("-", "_"));
88
85
  }
89
86
  return arr2obj(resources);
90
87
  }, "getResource");
@@ -6,7 +6,18 @@
6
6
  * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
7
  * For more information, please refer to: https://www.nocobase.com/agreement.
8
8
  */
9
+ import { Context } from '@nocobase/actions';
9
10
  import { DataSourceOptions, SequelizeDataSource } from '@nocobase/data-source-manager';
11
+ type MainDataSourceStatus = 'loaded' | 'loading';
10
12
  export declare class MainDataSource extends SequelizeDataSource {
13
+ status: MainDataSourceStatus;
11
14
  init(options?: DataSourceOptions): void;
15
+ readTables(): Promise<{
16
+ name: string;
17
+ }[]>;
18
+ private tables2Collections;
19
+ loadTables(ctx: Context, tables: string[]): Promise<void>;
20
+ private getLoadedCollections;
21
+ syncFieldsFromDatabase(ctx: any, collectionNames?: string[]): Promise<void>;
12
22
  }
23
+ export {};
@@ -32,6 +32,7 @@ __export(main_data_source_exports, {
32
32
  module.exports = __toCommonJS(main_data_source_exports);
33
33
  var import_data_source_manager = require("@nocobase/data-source-manager");
34
34
  const _MainDataSource = class _MainDataSource extends import_data_source_manager.SequelizeDataSource {
35
+ status = "loaded";
35
36
  init(options = {}) {
36
37
  const { acl, resourceManager, database } = options;
37
38
  this.acl = acl;
@@ -48,6 +49,133 @@ const _MainDataSource = class _MainDataSource extends import_data_source_manager
48
49
  this.resourceManager.use(this.acl.middleware(), { group: "acl", after: "auth" });
49
50
  }
50
51
  }
52
+ async readTables() {
53
+ const allTables = await this.introspector.getTableList();
54
+ const existsCollections = this.collectionManager.db.collections;
55
+ const existsTables = Array.from(existsCollections.values()).map(
56
+ (collection) => collection.model.tableName
57
+ );
58
+ const diffTables = allTables.filter((table) => !existsTables.includes(table));
59
+ return diffTables.map((name) => ({ name }));
60
+ }
61
+ async tables2Collections(tableNames) {
62
+ const db = this.collectionManager.db;
63
+ const results = await Promise.all(
64
+ tableNames.map(async (tableName) => {
65
+ let tableInfo;
66
+ if (typeof tableName === "string") {
67
+ tableInfo = { tableName };
68
+ if (db.options.schema) {
69
+ tableInfo.schema = db.options.schema;
70
+ }
71
+ } else {
72
+ tableInfo = tableName;
73
+ }
74
+ try {
75
+ return await this.introspector.getCollection({ tableInfo });
76
+ } catch (e) {
77
+ if (e.message.includes("No description found for")) {
78
+ return null;
79
+ }
80
+ throw e;
81
+ }
82
+ })
83
+ );
84
+ return results.filter(Boolean);
85
+ }
86
+ async loadTables(ctx, tables) {
87
+ const repo = this.collectionManager.db.getRepository("collections");
88
+ const existsCollections = this.collectionManager.db.collections;
89
+ const existsTables = Array.from(existsCollections.values()).map(
90
+ (collection) => collection.model.tableName
91
+ );
92
+ const toAddTables = tables.filter((table) => !existsTables.includes(table));
93
+ if (toAddTables.length) {
94
+ try {
95
+ this.status = "loading";
96
+ const results = await this.tables2Collections(toAddTables);
97
+ const values = results.map((result) => ({
98
+ ...result,
99
+ underscored: false
100
+ }));
101
+ await repo.create({ values, context: ctx });
102
+ } catch (e) {
103
+ throw e;
104
+ } finally {
105
+ this.status = "loaded";
106
+ }
107
+ }
108
+ }
109
+ async getLoadedCollections(filter) {
110
+ const db = this.collectionManager.db;
111
+ const loadedCollections = await db.getRepository("collections").find({
112
+ appends: ["fields"],
113
+ filter: {
114
+ hidden: false,
115
+ ...filter
116
+ }
117
+ });
118
+ const collections = loadedCollections.filter((collection) => {
119
+ var _a;
120
+ return ((_a = collection.options) == null ? void 0 : _a.from) !== "db2cm";
121
+ });
122
+ const loadedData = {};
123
+ for (const collection of collections) {
124
+ const c = db.getCollection(collection.name);
125
+ loadedData[c.tableName()] = {
126
+ ...collection.toJSON(),
127
+ fields: collection.fields.map((field) => {
128
+ const f = c.getField(field.name);
129
+ return {
130
+ columnName: f == null ? void 0 : f.columnName(),
131
+ ...field.toJSON()
132
+ };
133
+ })
134
+ };
135
+ }
136
+ return loadedData;
137
+ }
138
+ async syncFieldsFromDatabase(ctx, collectionNames) {
139
+ let filter = {};
140
+ if (collectionNames == null ? void 0 : collectionNames.length) {
141
+ filter = {
142
+ name: collectionNames
143
+ };
144
+ }
145
+ const db = this.collectionManager.db;
146
+ const loadedCollections = await this.getLoadedCollections(filter);
147
+ const tableNames = Object.values(loadedCollections).map(({ name }) => {
148
+ const collection = db.getCollection(name);
149
+ return collection.getTableNameWithSchema();
150
+ });
151
+ let collections = [];
152
+ try {
153
+ collections = await this.tables2Collections(tableNames);
154
+ } catch (err) {
155
+ ctx.log.error(err);
156
+ }
157
+ const toLoadCollections = this.mergeWithLoadedCollections(collections, loadedCollections);
158
+ for (const values of toLoadCollections) {
159
+ const existsFields = loadedCollections[values.tableName].fields;
160
+ const deletedFields = existsFields.filter((field) => !values.fields.find((f) => f.name === field.name));
161
+ await db.sequelize.transaction(async (transaction) => {
162
+ for (const field of deletedFields) {
163
+ await db.getRepository("fields").destroy({
164
+ filterByTk: field.key,
165
+ context: ctx,
166
+ transaction
167
+ });
168
+ }
169
+ await db.getRepository("collections").update({
170
+ filterByTk: values.name,
171
+ values,
172
+ updateAssociationValues: ["fields"],
173
+ context: ctx,
174
+ transaction
175
+ });
176
+ });
177
+ }
178
+ }
51
179
  };
52
180
  __name(_MainDataSource, "MainDataSource");
53
181
  let MainDataSource = _MainDataSource;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nocobase/server",
3
- "version": "2.0.0-alpha.20",
3
+ "version": "2.0.0-alpha.22",
4
4
  "main": "lib/index.js",
5
5
  "types": "./lib/index.d.ts",
6
6
  "license": "AGPL-3.0",
@@ -10,20 +10,20 @@
10
10
  "@koa/cors": "^5.0.0",
11
11
  "@koa/multer": "^3.1.0",
12
12
  "@koa/router": "^13.1.0",
13
- "@nocobase/acl": "2.0.0-alpha.20",
14
- "@nocobase/actions": "2.0.0-alpha.20",
15
- "@nocobase/auth": "2.0.0-alpha.20",
16
- "@nocobase/cache": "2.0.0-alpha.20",
17
- "@nocobase/data-source-manager": "2.0.0-alpha.20",
18
- "@nocobase/database": "2.0.0-alpha.20",
19
- "@nocobase/evaluators": "2.0.0-alpha.20",
20
- "@nocobase/lock-manager": "2.0.0-alpha.20",
21
- "@nocobase/logger": "2.0.0-alpha.20",
22
- "@nocobase/resourcer": "2.0.0-alpha.20",
23
- "@nocobase/sdk": "2.0.0-alpha.20",
24
- "@nocobase/snowflake-id": "2.0.0-alpha.20",
25
- "@nocobase/telemetry": "2.0.0-alpha.20",
26
- "@nocobase/utils": "2.0.0-alpha.20",
13
+ "@nocobase/acl": "2.0.0-alpha.22",
14
+ "@nocobase/actions": "2.0.0-alpha.22",
15
+ "@nocobase/auth": "2.0.0-alpha.22",
16
+ "@nocobase/cache": "2.0.0-alpha.22",
17
+ "@nocobase/data-source-manager": "2.0.0-alpha.22",
18
+ "@nocobase/database": "2.0.0-alpha.22",
19
+ "@nocobase/evaluators": "2.0.0-alpha.22",
20
+ "@nocobase/lock-manager": "2.0.0-alpha.22",
21
+ "@nocobase/logger": "2.0.0-alpha.22",
22
+ "@nocobase/resourcer": "2.0.0-alpha.22",
23
+ "@nocobase/sdk": "2.0.0-alpha.22",
24
+ "@nocobase/snowflake-id": "2.0.0-alpha.22",
25
+ "@nocobase/telemetry": "2.0.0-alpha.22",
26
+ "@nocobase/utils": "2.0.0-alpha.22",
27
27
  "@types/decompress": "4.2.7",
28
28
  "@types/ini": "^1.3.31",
29
29
  "@types/koa-send": "^4.1.3",
@@ -59,5 +59,5 @@
59
59
  "@types/serve-handler": "^6.1.1",
60
60
  "@types/ws": "^8.5.5"
61
61
  },
62
- "gitHead": "af5ff4eaa490349420135405128da466d72ac74c"
62
+ "gitHead": "717bcfaa0bdeaa8026717b4309a65abdc19478f1"
63
63
  }