@nocobase/server 2.1.0-beta.2 → 2.1.0-beta.20
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/LICENSE +201 -661
- package/README.md +79 -10
- package/lib/acl/available-action.js +1 -1
- package/lib/aes-encryptor.js +3 -2
- package/lib/ai/create-docs-index.js +2 -1
- package/lib/app-supervisor/app-options-factory.d.ts +1 -0
- package/lib/app-supervisor/index.js +15 -1
- package/lib/app-supervisor/main-only-adapter.d.ts +1 -1
- package/lib/app-supervisor/main-only-adapter.js +17 -12
- package/lib/application.d.ts +1 -2
- package/lib/application.js +3 -24
- package/lib/audit-manager/index.d.ts +2 -0
- package/lib/audit-manager/index.js +5 -2
- package/lib/commands/create-migration.js +1 -1
- package/lib/commands/install.js +3 -1
- package/lib/commands/pm.js +7 -0
- package/lib/commands/start.js +2 -2
- package/lib/commands/upgrade.js +3 -1
- package/lib/event-queue.js +1 -1
- package/lib/gateway/index.d.ts +13 -3
- package/lib/gateway/index.js +137 -15
- package/lib/gateway/utils.d.ts +17 -0
- package/lib/gateway/utils.js +115 -0
- package/lib/helper.js +33 -1
- package/lib/index.d.ts +1 -0
- package/lib/index.js +2 -0
- package/lib/main-data-source.js +1 -1
- package/lib/plugin-manager/deps.js +2 -1
- package/lib/plugin-manager/options/resource.d.ts +11 -1
- package/lib/plugin-manager/options/resource.js +155 -53
- package/lib/plugin-manager/plugin-manager.d.ts +7 -2
- package/lib/plugin-manager/plugin-manager.js +56 -43
- package/lib/plugin-manager/utils.d.ts +7 -1
- package/lib/plugin-manager/utils.js +33 -9
- package/lib/plugin.js +33 -1
- package/lib/pub-sub-manager/handler-manager.d.ts +1 -0
- package/lib/pub-sub-manager/handler-manager.js +11 -0
- package/lib/pub-sub-manager/pub-sub-manager.js +2 -1
- package/lib/swagger/app.d.ts +102 -0
- package/lib/swagger/app.js +124 -0
- package/lib/swagger/base.d.ts +244 -0
- package/lib/swagger/base.js +292 -0
- package/lib/swagger/collections.d.ts +996 -0
- package/lib/swagger/collections.js +1264 -0
- package/lib/swagger/index.d.ts +1774 -0
- package/lib/swagger/index.js +70 -0
- package/lib/swagger/pm.d.ts +462 -0
- package/lib/swagger/pm.js +422 -0
- package/lib/sync-message-manager.js +8 -1
- package/lib/worker-mode.d.ts +19 -0
- package/lib/worker-mode.js +67 -0
- package/package.json +18 -18
- package/lib/swagger/index.json +0 -1569
package/README.md
CHANGED
|
@@ -1,17 +1,24 @@
|
|
|
1
1
|
# NocoBase
|
|
2
2
|
|
|
3
3
|
<video width="100%" controls>
|
|
4
|
-
|
|
4
|
+
<source src="https://github.com/user-attachments/assets/4d11a87b-00e2-48f3-9bf7-389d21072d13" type="video/mp4">
|
|
5
5
|
</video>
|
|
6
6
|
|
|
7
|
+
<p align="center">
|
|
8
|
+
<a href="https://trendshift.io/repositories/4112" target="_blank"><img src="https://trendshift.io/api/badge/repositories/4112" alt="nocobase%2Fnocobase | Trendshift" style="width: 250px; height: 55px;" width="250" height="55"/></a>
|
|
9
|
+
<a href="https://www.producthunt.com/posts/nocobase?embed=true&utm_source=badge-top-post-topic-badge&utm_medium=badge&utm_souce=badge-nocobase" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/top-post-topic-badge.svg?post_id=456520&theme=light&period=weekly&topic_id=267" alt="NocoBase - Scalability-first, open-source no-code platform | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a>
|
|
10
|
+
</p>
|
|
7
11
|
|
|
8
12
|
## What is NocoBase
|
|
9
13
|
|
|
10
|
-
NocoBase is
|
|
11
|
-
|
|
14
|
+
NocoBase is the most extensible AI-powered no-code platform.
|
|
15
|
+
Total control. Infinite extensibility. AI collaboration.
|
|
16
|
+
Enable your team to adapt quickly and cut costs dramatically.
|
|
17
|
+
No years of development. No millions wasted.
|
|
18
|
+
Deploy NocoBase in minutes — and take control of everything.
|
|
12
19
|
|
|
13
20
|
Homepage:
|
|
14
|
-
https://www.nocobase.com/
|
|
21
|
+
https://www.nocobase.com/
|
|
15
22
|
|
|
16
23
|
Online Demo:
|
|
17
24
|
https://demo.nocobase.com/new
|
|
@@ -19,12 +26,74 @@ https://demo.nocobase.com/new
|
|
|
19
26
|
Documents:
|
|
20
27
|
https://docs.nocobase.com/
|
|
21
28
|
|
|
22
|
-
|
|
23
|
-
https://
|
|
29
|
+
Forum:
|
|
30
|
+
https://forum.nocobase.com/
|
|
24
31
|
|
|
25
|
-
|
|
26
|
-
https://www.nocobase.com/en/
|
|
32
|
+
Use Cases:
|
|
33
|
+
https://www.nocobase.com/en/blog/tags/customer-stories
|
|
27
34
|
|
|
35
|
+
## Release Notes
|
|
28
36
|
|
|
29
|
-
|
|
30
|
-
|
|
37
|
+
Our [blog](https://www.nocobase.com/en/blog/timeline) is regularly updated with release notes and provides a weekly summary.
|
|
38
|
+
|
|
39
|
+
## Distinctive features
|
|
40
|
+
|
|
41
|
+
### 1. Data model-driven, not form/table–driven
|
|
42
|
+
|
|
43
|
+
Instead of being constrained by forms or tables, NocoBase adopts a data model–driven approach, separating data structure from user interface to unlock unlimited possibilities.
|
|
44
|
+
|
|
45
|
+
- UI and data structure are fully decoupled
|
|
46
|
+
- Multiple blocks and actions can be created for the same table or record in any quantity or form
|
|
47
|
+
- Supports the main database, external databases, and third-party APIs as data sources
|
|
48
|
+
|
|
49
|
+

|
|
50
|
+
|
|
51
|
+
### 2. AI employees, integrated into your business systems
|
|
52
|
+
Unlike standalone AI demos, NocoBase allows you to embed AI capabilities seamlessly into your interfaces, workflows, and data context, making AI truly useful in real business scenarios.
|
|
53
|
+
|
|
54
|
+
- Define AI employees for roles such as translator, analyst, researcher, or assistant
|
|
55
|
+
- Seamless AI–human collaboration in interfaces and workflows
|
|
56
|
+
- Ensure AI usage is secure, transparent, and customizable for your business needs
|
|
57
|
+
|
|
58
|
+

|
|
59
|
+
|
|
60
|
+
### 3. What you see is what you get, incredibly easy to use
|
|
61
|
+
|
|
62
|
+
While enabling the development of complex business systems, NocoBase keeps the experience simple and intuitive.
|
|
63
|
+
|
|
64
|
+
- One-click switch between usage mode and configuration mode
|
|
65
|
+
- Pages serve as a canvas to arrange blocks and actions, similar to Notion
|
|
66
|
+
- Configuration mode is designed for ordinary users, not just programmers
|
|
67
|
+
|
|
68
|
+

|
|
69
|
+
|
|
70
|
+
### 4. Everything is a plugin, designed for extension
|
|
71
|
+
Adding more no-code features will never cover every business case. NocoBase is built for extension through its plugin-based microkernel architecture.
|
|
72
|
+
|
|
73
|
+
- All functionalities are plugins, similar to WordPress
|
|
74
|
+
- Plugins are ready to use upon installation
|
|
75
|
+
- Pages, blocks, actions, APIs, and data sources can all be extended through custom plugins
|
|
76
|
+
|
|
77
|
+

|
|
78
|
+
|
|
79
|
+
## Installation
|
|
80
|
+
|
|
81
|
+
NocoBase supports three installation methods:
|
|
82
|
+
|
|
83
|
+
- <a target="_blank" href="https://docs.nocobase.com/welcome/getting-started/installation/docker-compose">Installing With Docker (👍Recommended)</a>
|
|
84
|
+
|
|
85
|
+
Suitable for no-code scenarios, no code to write. When upgrading, just download the latest image and reboot.
|
|
86
|
+
|
|
87
|
+
- <a target="_blank" href="https://docs.nocobase.com/welcome/getting-started/installation/create-nocobase-app">Installing from create-nocobase-app CLI</a>
|
|
88
|
+
|
|
89
|
+
The business code of the project is completely independent and supports low-code development.
|
|
90
|
+
|
|
91
|
+
- <a target="_blank" href="https://docs.nocobase.com/welcome/getting-started/installation/git-clone">Installing from Git source code</a>
|
|
92
|
+
|
|
93
|
+
If you want to experience the latest unreleased version, or want to participate in the contribution, you need to make changes and debug on the source code, it is recommended to choose this installation method, which requires a high level of development skills, and if the code has been updated, you can git pull the latest code.
|
|
94
|
+
|
|
95
|
+
## How NocoBase works
|
|
96
|
+
|
|
97
|
+
<video width="100%" controls>
|
|
98
|
+
<source src="https://github.com/user-attachments/assets/8d183b44-9bb5-4792-b08f-bc08fe8dfaaf" type="video/mp4">
|
|
99
|
+
</video>
|
package/lib/aes-encryptor.js
CHANGED
|
@@ -44,6 +44,7 @@ module.exports = __toCommonJS(aes_encryptor_exports);
|
|
|
44
44
|
var import_crypto = __toESM(require("crypto"));
|
|
45
45
|
var import_fs_extra = __toESM(require("fs-extra"));
|
|
46
46
|
var import_path = __toESM(require("path"));
|
|
47
|
+
var import_utils = require("@nocobase/utils");
|
|
47
48
|
const _AesEncryptor = class _AesEncryptor {
|
|
48
49
|
key;
|
|
49
50
|
constructor(key) {
|
|
@@ -99,12 +100,12 @@ const _AesEncryptor = class _AesEncryptor {
|
|
|
99
100
|
}
|
|
100
101
|
}
|
|
101
102
|
static async getKeyPath(appName) {
|
|
102
|
-
const appKeyPath =
|
|
103
|
+
const appKeyPath = (0, import_utils.storagePathJoin)("apps", appName, "aes_key.dat");
|
|
103
104
|
const appKeyExists = await import_fs_extra.default.exists(appKeyPath);
|
|
104
105
|
if (appKeyExists) {
|
|
105
106
|
return appKeyPath;
|
|
106
107
|
}
|
|
107
|
-
const envKeyPath =
|
|
108
|
+
const envKeyPath = (0, import_utils.storagePathJoin)("environment-variables", appName, "aes_key.dat");
|
|
108
109
|
const envKeyExists = await import_fs_extra.default.exists(envKeyPath);
|
|
109
110
|
if (envKeyExists) {
|
|
110
111
|
return envKeyPath;
|
|
@@ -43,10 +43,11 @@ module.exports = __toCommonJS(create_docs_index_exports);
|
|
|
43
43
|
var import_fast_glob = __toESM(require("fast-glob"));
|
|
44
44
|
var import_fs_extra = __toESM(require("fs-extra"));
|
|
45
45
|
var import_path = __toESM(require("path"));
|
|
46
|
+
var import_utils = require("@nocobase/utils");
|
|
46
47
|
var import_ai = require("@nocobase/ai");
|
|
47
48
|
var import_findPackageNames = require("../plugin-manager/findPackageNames");
|
|
48
49
|
var import_plugin_manager = require("../plugin-manager");
|
|
49
|
-
const DOCS_STORAGE_DIR =
|
|
50
|
+
const DOCS_STORAGE_DIR = (0, import_utils.storagePathJoin)("ai", "docs");
|
|
50
51
|
const REFERENCE_START = "<!-- docs:references:start -->";
|
|
51
52
|
const REFERENCE_END = "<!-- docs:references:end -->";
|
|
52
53
|
const SPLIT_REFERENCE_START = "<!-- docs:splits:start -->";
|
|
@@ -16,6 +16,7 @@ export declare const appOptionsFactory: (appName: string, mainApp: Application,
|
|
|
16
16
|
migrator?: any;
|
|
17
17
|
usingBigIntForId?: boolean;
|
|
18
18
|
underscored?: boolean;
|
|
19
|
+
rawTimezone?: string;
|
|
19
20
|
logger?: import("@nocobase/logger/lib/logger").Logger | import("@nocobase/logger/lib/logger").LoggerOptions;
|
|
20
21
|
customHooks?: any;
|
|
21
22
|
instanceId?: string;
|
|
@@ -47,6 +47,7 @@ var import_lodash = __toESM(require("lodash"));
|
|
|
47
47
|
var import_utils = require("@nocobase/utils");
|
|
48
48
|
var import_events = require("events");
|
|
49
49
|
var import_application = __toESM(require("../application"));
|
|
50
|
+
var import_worker_mode = require("../worker-mode");
|
|
50
51
|
var import_main_only_adapter = require("./main-only-adapter");
|
|
51
52
|
var import_handler = require("../errors/handler");
|
|
52
53
|
var import_condition_registry = require("./condition-registry");
|
|
@@ -288,6 +289,10 @@ const _AppSupervisor = class _AppSupervisor extends import_events.EventEmitter {
|
|
|
288
289
|
return this.discoveryAdapter.getAppStatus(appName, defaultStatus);
|
|
289
290
|
}
|
|
290
291
|
async setAppStatus(appName, status, options = {}) {
|
|
292
|
+
if ((0, import_worker_mode.isTransient)()) {
|
|
293
|
+
this.logger.debug("App running as worker, status will not be set", { appName, status });
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
291
296
|
this.logger.debug("Setting app status", { appName, status });
|
|
292
297
|
return this.discoveryAdapter.setAppStatus(appName, status, options);
|
|
293
298
|
}
|
|
@@ -329,7 +334,7 @@ const _AppSupervisor = class _AppSupervisor extends import_events.EventEmitter {
|
|
|
329
334
|
};
|
|
330
335
|
}
|
|
331
336
|
const app = new import_application.default(options);
|
|
332
|
-
if (hook
|
|
337
|
+
if (hook ?? !(0, import_worker_mode.isTransient)()) {
|
|
333
338
|
app.on("afterStart", async () => {
|
|
334
339
|
await this.sendSyncMessage(mainApp, {
|
|
335
340
|
type: "app:started",
|
|
@@ -356,6 +361,9 @@ const _AppSupervisor = class _AppSupervisor extends import_events.EventEmitter {
|
|
|
356
361
|
this.registerCommandHandler(app);
|
|
357
362
|
app.on("afterStart", async (app2) => {
|
|
358
363
|
var _a, _b;
|
|
364
|
+
if ((0, import_worker_mode.isTransient)()) {
|
|
365
|
+
return;
|
|
366
|
+
}
|
|
359
367
|
await app2.syncMessageManager.subscribe(
|
|
360
368
|
"app_supervisor:sync",
|
|
361
369
|
async (message) => {
|
|
@@ -390,6 +398,9 @@ const _AppSupervisor = class _AppSupervisor extends import_events.EventEmitter {
|
|
|
390
398
|
}
|
|
391
399
|
});
|
|
392
400
|
app.on("afterDestroy", async (app2) => {
|
|
401
|
+
if ((0, import_worker_mode.isTransient)()) {
|
|
402
|
+
return;
|
|
403
|
+
}
|
|
393
404
|
await this.unregisterEnvironment();
|
|
394
405
|
});
|
|
395
406
|
return app;
|
|
@@ -586,6 +597,9 @@ const _AppSupervisor = class _AppSupervisor extends import_events.EventEmitter {
|
|
|
586
597
|
return super.on(eventName, listener);
|
|
587
598
|
}
|
|
588
599
|
bindAppEvents(app) {
|
|
600
|
+
if ((0, import_worker_mode.isTransient)()) {
|
|
601
|
+
return;
|
|
602
|
+
}
|
|
589
603
|
app.on("afterDestroy", async () => {
|
|
590
604
|
delete this.apps[app.name];
|
|
591
605
|
delete this.appStatus[app.name];
|
|
@@ -13,7 +13,7 @@ import type { AppSupervisor } from './index';
|
|
|
13
13
|
export declare class MainOnlyAdapter implements AppDiscoveryAdapter, AppProcessAdapter {
|
|
14
14
|
protected readonly supervisor: AppSupervisor;
|
|
15
15
|
readonly name: string;
|
|
16
|
-
|
|
16
|
+
apps: Record<string, Application>;
|
|
17
17
|
status: AppStatus;
|
|
18
18
|
appErrors: Record<string, Error>;
|
|
19
19
|
constructor(supervisor: AppSupervisor);
|
|
@@ -36,7 +36,7 @@ const _MainOnlyAdapter = class _MainOnlyAdapter {
|
|
|
36
36
|
this.name = "main-only";
|
|
37
37
|
}
|
|
38
38
|
name;
|
|
39
|
-
|
|
39
|
+
apps = {};
|
|
40
40
|
status;
|
|
41
41
|
appErrors = {};
|
|
42
42
|
async getApp(appName, options = {}) {
|
|
@@ -47,10 +47,10 @@ const _MainOnlyAdapter = class _MainOnlyAdapter {
|
|
|
47
47
|
if (!options.withOutBootStrap) {
|
|
48
48
|
await this.bootstrapApp(appName);
|
|
49
49
|
}
|
|
50
|
-
return this.
|
|
50
|
+
return this.apps[appName];
|
|
51
51
|
}
|
|
52
52
|
async bootstrapApp(appName) {
|
|
53
|
-
if (appName !== "main" || !this.
|
|
53
|
+
if (appName !== "main" || !this.apps[appName]) {
|
|
54
54
|
this.setAppStatus(appName, "not_found");
|
|
55
55
|
return;
|
|
56
56
|
}
|
|
@@ -66,23 +66,23 @@ const _MainOnlyAdapter = class _MainOnlyAdapter {
|
|
|
66
66
|
this.supervisor.logger.warn(`only main app is supported`, { method: "addApp" });
|
|
67
67
|
return;
|
|
68
68
|
}
|
|
69
|
-
if (this.app) {
|
|
69
|
+
if (this.apps[app.name]) {
|
|
70
70
|
throw new Error(`app ${app.name} already exists`);
|
|
71
71
|
}
|
|
72
|
-
this.app = app;
|
|
72
|
+
this.apps[app.name] = app;
|
|
73
73
|
if (!this.status || this.status === "not_found") {
|
|
74
74
|
this.setAppStatus(app.name, "preparing");
|
|
75
75
|
}
|
|
76
76
|
return app;
|
|
77
77
|
}
|
|
78
78
|
getApps() {
|
|
79
|
-
return
|
|
79
|
+
return Object.values(this.apps);
|
|
80
80
|
}
|
|
81
81
|
hasApp(appName) {
|
|
82
82
|
if (appName !== "main") {
|
|
83
83
|
return false;
|
|
84
84
|
}
|
|
85
|
-
return !!this.
|
|
85
|
+
return !!this.apps[appName];
|
|
86
86
|
}
|
|
87
87
|
async startApp(appName) {
|
|
88
88
|
if (appName !== "main") {
|
|
@@ -93,31 +93,36 @@ const _MainOnlyAdapter = class _MainOnlyAdapter {
|
|
|
93
93
|
await (app == null ? void 0 : app.runCommand("start", "--quickstart"));
|
|
94
94
|
}
|
|
95
95
|
async stopApp(appName) {
|
|
96
|
+
var _a;
|
|
96
97
|
if (appName !== "main") {
|
|
97
98
|
this.supervisor.logger.warn(`only main app is supported`, { method: "stopApp" });
|
|
98
99
|
return;
|
|
99
100
|
}
|
|
100
|
-
|
|
101
|
+
if (!this.apps[appName]) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
await ((_a = this.apps[appName]) == null ? void 0 : _a.runCommand("stop"));
|
|
101
105
|
}
|
|
102
106
|
async removeApp(appName) {
|
|
103
107
|
if (appName !== "main") {
|
|
104
108
|
this.supervisor.logger.warn(`only main app is supported`, { method: "removeApp" });
|
|
105
109
|
return;
|
|
106
110
|
}
|
|
107
|
-
if (!this.
|
|
111
|
+
if (!this.apps[appName]) {
|
|
108
112
|
return;
|
|
109
113
|
}
|
|
110
|
-
await this.
|
|
114
|
+
await this.apps[appName].runCommand("destroy");
|
|
115
|
+
this.apps[appName] = null;
|
|
111
116
|
}
|
|
112
117
|
async upgradeApp(appName) {
|
|
113
118
|
if (appName !== "main") {
|
|
114
119
|
this.supervisor.logger.warn(`only main app is supported`, { method: "upgrade" });
|
|
115
120
|
return;
|
|
116
121
|
}
|
|
117
|
-
if (!this.
|
|
122
|
+
if (!this.apps[appName]) {
|
|
118
123
|
return;
|
|
119
124
|
}
|
|
120
|
-
await this.
|
|
125
|
+
await this.apps[appName].runCommand("upgrade");
|
|
121
126
|
}
|
|
122
127
|
async removeAllApps() {
|
|
123
128
|
return this.removeApp("main");
|
package/lib/application.d.ts
CHANGED
|
@@ -270,8 +270,7 @@ export declare class Application<StateT = DefaultState, ContextT = DefaultContex
|
|
|
270
270
|
protected _aesEncryptor: AesEncryptor;
|
|
271
271
|
get aesEncryptor(): AesEncryptor;
|
|
272
272
|
/**
|
|
273
|
-
*
|
|
274
|
-
* @experimental
|
|
273
|
+
* @deprecated use {@link serving} from './worker-mode' instead.
|
|
275
274
|
*/
|
|
276
275
|
serving(key?: string): boolean;
|
|
277
276
|
/**
|
package/lib/application.js
CHANGED
|
@@ -87,6 +87,7 @@ var import_redis_connection_manager = require("./redis-connection-manager");
|
|
|
87
87
|
var import_service_container = require("./service-container");
|
|
88
88
|
var import_snowflake_id_field = require("./snowflake-id-field");
|
|
89
89
|
var import_worker_id_allocator = require("./worker-id-allocator");
|
|
90
|
+
var import_worker_mode = require("./worker-mode");
|
|
90
91
|
const _Application = class _Application extends import_koa.default {
|
|
91
92
|
constructor(options) {
|
|
92
93
|
super();
|
|
@@ -282,32 +283,10 @@ const _Application = class _Application extends import_koa.default {
|
|
|
282
283
|
return this._aesEncryptor;
|
|
283
284
|
}
|
|
284
285
|
/**
|
|
285
|
-
*
|
|
286
|
-
* @experimental
|
|
286
|
+
* @deprecated use {@link serving} from './worker-mode' instead.
|
|
287
287
|
*/
|
|
288
288
|
serving(key) {
|
|
289
|
-
|
|
290
|
-
if (!WORKER_MODE) {
|
|
291
|
-
return true;
|
|
292
|
-
}
|
|
293
|
-
if (WORKER_MODE === "-") {
|
|
294
|
-
return false;
|
|
295
|
-
}
|
|
296
|
-
const topics = WORKER_MODE.trim().split(",");
|
|
297
|
-
if (key) {
|
|
298
|
-
if (WORKER_MODE === "*") {
|
|
299
|
-
return true;
|
|
300
|
-
}
|
|
301
|
-
if (topics.includes(key)) {
|
|
302
|
-
return true;
|
|
303
|
-
}
|
|
304
|
-
return false;
|
|
305
|
-
} else {
|
|
306
|
-
if (topics.includes("!")) {
|
|
307
|
-
return true;
|
|
308
|
-
}
|
|
309
|
-
return false;
|
|
310
|
-
}
|
|
289
|
+
return (0, import_worker_mode.serving)(key);
|
|
311
290
|
}
|
|
312
291
|
/**
|
|
313
292
|
* @internal
|
|
@@ -12,6 +12,7 @@ export interface AuditLog {
|
|
|
12
12
|
dataSource: string;
|
|
13
13
|
resource: string;
|
|
14
14
|
action: string;
|
|
15
|
+
requestSource?: string;
|
|
15
16
|
sourceCollection?: string;
|
|
16
17
|
sourceRecordUK?: string;
|
|
17
18
|
targetCollection?: string;
|
|
@@ -102,6 +103,7 @@ export declare class AuditManager {
|
|
|
102
103
|
'x-authenticator': any;
|
|
103
104
|
'x-locale': any;
|
|
104
105
|
'x-timezone': any;
|
|
106
|
+
'x-request-source': any;
|
|
105
107
|
};
|
|
106
108
|
};
|
|
107
109
|
response: {
|
|
@@ -41,6 +41,7 @@ __export(audit_manager_exports, {
|
|
|
41
41
|
});
|
|
42
42
|
module.exports = __toCommonJS(audit_manager_exports);
|
|
43
43
|
var import_stream = __toESM(require("stream"));
|
|
44
|
+
const REQUEST_SOURCE_HEADER = "x-request-source";
|
|
44
45
|
function isStream(obj) {
|
|
45
46
|
return obj instanceof import_stream.default.Readable || obj instanceof import_stream.default.Writable || obj instanceof import_stream.default.Duplex || obj instanceof import_stream.default.Transform;
|
|
46
47
|
}
|
|
@@ -201,7 +202,7 @@ const _AuditManager = class _AuditManager {
|
|
|
201
202
|
return null;
|
|
202
203
|
}
|
|
203
204
|
async getDefaultMetaData(ctx) {
|
|
204
|
-
var _a, _b, _c;
|
|
205
|
+
var _a, _b, _c, _d;
|
|
205
206
|
let body = null;
|
|
206
207
|
if (ctx.body) {
|
|
207
208
|
if (!Buffer.isBuffer(ctx.body) && !isStream(ctx.body)) {
|
|
@@ -217,7 +218,8 @@ const _AuditManager = class _AuditManager {
|
|
|
217
218
|
headers: {
|
|
218
219
|
"x-authenticator": (_a = ctx.request) == null ? void 0 : _a.headers["x-authenticator"],
|
|
219
220
|
"x-locale": (_b = ctx.request) == null ? void 0 : _b.headers["x-locale"],
|
|
220
|
-
"x-timezone": (_c = ctx.request) == null ? void 0 : _c.headers["x-timezone"]
|
|
221
|
+
"x-timezone": (_c = ctx.request) == null ? void 0 : _c.headers["x-timezone"],
|
|
222
|
+
"x-request-source": (_d = ctx.request) == null ? void 0 : _d.headers[REQUEST_SOURCE_HEADER]
|
|
221
223
|
}
|
|
222
224
|
},
|
|
223
225
|
response: {
|
|
@@ -241,6 +243,7 @@ const _AuditManager = class _AuditManager {
|
|
|
241
243
|
dataSource: ctx.request.header["x-data-source"] || "main",
|
|
242
244
|
resource: resourceName,
|
|
243
245
|
action: ctx.action.actionName,
|
|
246
|
+
requestSource: ctx.request.header[REQUEST_SOURCE_HEADER],
|
|
244
247
|
userId: (_b = (_a = ctx.state) == null ? void 0 : _a.currentUser) == null ? void 0 : _b.id,
|
|
245
248
|
roleName: (_c = ctx.state) == null ? void 0 : _c.currentRole,
|
|
246
249
|
ip: ips.length > 0 ? ips[0] : ctx.request.ip,
|
|
@@ -76,6 +76,6 @@ export default class extends Migration {
|
|
|
76
76
|
`;
|
|
77
77
|
await import_fs.default.promises.mkdir((0, import_path.dirname)(filename), { recursive: true });
|
|
78
78
|
await import_fs.default.promises.writeFile(filename, data, "utf8");
|
|
79
|
-
|
|
79
|
+
console.log(`migration file in ${filename}`);
|
|
80
80
|
});
|
|
81
81
|
}, "default");
|
package/lib/commands/install.js
CHANGED
|
@@ -37,7 +37,9 @@ var install_default = /* @__PURE__ */ __name((app) => {
|
|
|
37
37
|
if (options.lang) {
|
|
38
38
|
process.env.INIT_APP_LANG = options.lang;
|
|
39
39
|
}
|
|
40
|
-
|
|
40
|
+
if (!process.env.VITEST) {
|
|
41
|
+
await (0, import_create_docs_index.createDocsIndex)(app);
|
|
42
|
+
}
|
|
41
43
|
await app.install(options);
|
|
42
44
|
const reinstall = options.clean || options.force;
|
|
43
45
|
app.log.info(`app ${reinstall ? "reinstalled" : "installed"} successfully [v${app.getVersion()}]`);
|
package/lib/commands/pm.js
CHANGED
|
@@ -32,9 +32,16 @@ __export(pm_exports, {
|
|
|
32
32
|
module.exports = __toCommonJS(pm_exports);
|
|
33
33
|
var import_app_supervisor = require("../app-supervisor");
|
|
34
34
|
var import_plugin_command_error = require("../errors/plugin-command-error");
|
|
35
|
+
var import_utils = require("../plugin-manager/utils");
|
|
35
36
|
/* istanbul ignore file -- @preserve */
|
|
36
37
|
var pm_default = /* @__PURE__ */ __name((app) => {
|
|
37
38
|
const pm = app.command("pm");
|
|
39
|
+
pm.command("list").action(async () => {
|
|
40
|
+
const items = await (0, import_utils.pmListSummary)(app);
|
|
41
|
+
console.log("--- BEGIN_PLUGIN_LIST_JSON ---");
|
|
42
|
+
console.log(JSON.stringify(items));
|
|
43
|
+
console.log("--- END_PLUGIN_LIST_JSON ---");
|
|
44
|
+
});
|
|
38
45
|
pm.command("create").argument("plugin").option("--force-recreate").action(async (plugin, options) => {
|
|
39
46
|
await app.pm.create(plugin, options);
|
|
40
47
|
});
|
package/lib/commands/start.js
CHANGED
|
@@ -41,14 +41,14 @@ __export(start_exports, {
|
|
|
41
41
|
});
|
|
42
42
|
module.exports = __toCommonJS(start_exports);
|
|
43
43
|
var import_fs_extra = __toESM(require("fs-extra"));
|
|
44
|
-
var
|
|
44
|
+
var import_utils = require("@nocobase/utils");
|
|
45
45
|
var import_create_docs_index = require("../ai/create-docs-index");
|
|
46
46
|
var import_application_not_install = require("../errors/application-not-install");
|
|
47
47
|
/* istanbul ignore file -- @preserve */
|
|
48
48
|
var start_default = /* @__PURE__ */ __name((app) => {
|
|
49
49
|
app.command("start").auth().option("--db-sync").option("--quickstart").action(async (...cliArgs) => {
|
|
50
50
|
const [options] = cliArgs;
|
|
51
|
-
const file = (0,
|
|
51
|
+
const file = (0, import_utils.storagePathJoin)(".upgrading");
|
|
52
52
|
const upgrading = await import_fs_extra.default.exists(file);
|
|
53
53
|
if (upgrading) {
|
|
54
54
|
if (!process.env.VITEST) {
|
package/lib/commands/upgrade.js
CHANGED
|
@@ -34,7 +34,9 @@ var import_create_docs_index = require("../ai/create-docs-index");
|
|
|
34
34
|
/* istanbul ignore file -- @preserve */
|
|
35
35
|
var upgrade_default = /* @__PURE__ */ __name((app) => {
|
|
36
36
|
app.command("upgrade").ipc().auth().action(async (options) => {
|
|
37
|
-
|
|
37
|
+
if (!process.env.VITEST) {
|
|
38
|
+
await (0, import_create_docs_index.createDocsIndex)(app);
|
|
39
|
+
}
|
|
38
40
|
await app.upgrade(options);
|
|
39
41
|
app.log.info(`\u2728 NocoBase has been upgraded to v${app.getVersion()}`);
|
|
40
42
|
});
|
package/lib/event-queue.js
CHANGED
|
@@ -71,7 +71,7 @@ const _MemoryEventQueueAdapter = class _MemoryEventQueueAdapter {
|
|
|
71
71
|
return null;
|
|
72
72
|
}
|
|
73
73
|
get storagePath() {
|
|
74
|
-
return
|
|
74
|
+
return (0, import_utils.storagePathJoin)("apps", this.options.appName, "event-queue.json");
|
|
75
75
|
}
|
|
76
76
|
listen = /* @__PURE__ */ __name((channel) => {
|
|
77
77
|
if (!this.connected) {
|
package/lib/gateway/index.d.ts
CHANGED
|
@@ -19,6 +19,7 @@ import { IPCSocketClient } from './ipc-socket-client';
|
|
|
19
19
|
import { IPCSocketServer } from './ipc-socket-server';
|
|
20
20
|
import { WSServer } from './ws-server';
|
|
21
21
|
import { Duplex } from 'node:stream';
|
|
22
|
+
export { getHost, getHostname } from './utils';
|
|
22
23
|
export interface IncomingRequest {
|
|
23
24
|
url: string;
|
|
24
25
|
headers: any;
|
|
@@ -40,7 +41,7 @@ interface RunOptions {
|
|
|
40
41
|
mainAppOptions: ApplicationOptions;
|
|
41
42
|
}
|
|
42
43
|
export interface AppSelectorMiddlewareContext {
|
|
43
|
-
req: IncomingRequest;
|
|
44
|
+
req: IncomingMessage | IncomingRequest;
|
|
44
45
|
resolvedAppName: string | null;
|
|
45
46
|
}
|
|
46
47
|
export declare class Gateway extends EventEmitter {
|
|
@@ -57,6 +58,7 @@ export declare class Gateway extends EventEmitter {
|
|
|
57
58
|
private port;
|
|
58
59
|
private host;
|
|
59
60
|
private socketPath;
|
|
61
|
+
private v2IndexTemplateCache;
|
|
60
62
|
private terminating;
|
|
61
63
|
private onTerminate;
|
|
62
64
|
private constructor();
|
|
@@ -74,9 +76,18 @@ export declare class Gateway extends EventEmitter {
|
|
|
74
76
|
code: string;
|
|
75
77
|
}): void;
|
|
76
78
|
responseErrorWithCode(code: any, res: any, options: any): void;
|
|
79
|
+
private getV2PublicPath;
|
|
80
|
+
private getAppPublicPath;
|
|
81
|
+
private isV2Request;
|
|
82
|
+
private isV2IndexRequest;
|
|
83
|
+
private getV2RuntimeConfig;
|
|
84
|
+
private getV2RuntimeConfigScript;
|
|
85
|
+
private getV2AssetPublicPath;
|
|
86
|
+
private getV2IndexTemplate;
|
|
87
|
+
private renderV2IndexHtml;
|
|
77
88
|
requestHandler(req: IncomingMessage, res: ServerResponse): Promise<void>;
|
|
78
89
|
getAppSelectorMiddlewares(): Toposort<AppSelectorMiddleware>;
|
|
79
|
-
getRequestHandleAppName(req: IncomingRequest): Promise<string>;
|
|
90
|
+
getRequestHandleAppName(req: IncomingMessage | IncomingRequest): Promise<string>;
|
|
80
91
|
getCallback(): any;
|
|
81
92
|
watch(): Promise<void>;
|
|
82
93
|
run(options: RunOptions): Promise<void>;
|
|
@@ -96,4 +107,3 @@ export declare class Gateway extends EventEmitter {
|
|
|
96
107
|
static registerWsHandler(wsServer: (req: IncomingMessage, socket: Duplex, head: Buffer, app: Application) => boolean | void): void;
|
|
97
108
|
static unregisterWsHandler(wsServer: (req: IncomingMessage, socket: Duplex, head: Buffer, app: Application) => boolean | void): void;
|
|
98
109
|
}
|
|
99
|
-
export {};
|