@lowdefy/server-dev 5.3.0 → 5.4.0
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/build/appMeta.js +19 -0
- package/lib/build/i18n.js +19 -0
- package/lib/server/apiWrapper.js +4 -0
- package/lib/server/jitPageBuilder.js +9 -0
- package/lib/server/readBuildApiArtifacts.mjs +53 -0
- package/lib/server/readBuildApiArtifacts.test.mjs +106 -0
- package/manager/processes/lowdefyBuild.mjs +3 -0
- package/manager/utils/createCustomPluginMessagesMap.mjs +59 -0
- package/next.config.js +2 -0
- package/package.json +31 -30
- package/package.original.json +31 -30
- package/pages/_app.js +31 -4
- package/pages/api/agent/[...path].js +7 -6
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import { serializer } from '@lowdefy/helpers';
|
|
17
|
+
import raw from '../../build/appMeta.json';
|
|
18
|
+
|
|
19
|
+
export default serializer.deserialize(raw);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
import { serializer } from '@lowdefy/helpers';
|
|
17
|
+
import raw from '../../build/i18n.json';
|
|
18
|
+
|
|
19
|
+
export default serializer.deserialize(raw);
|
package/lib/server/apiWrapper.js
CHANGED
|
@@ -21,7 +21,9 @@ import { serializer } from '@lowdefy/helpers';
|
|
|
21
21
|
import { v4 as uuid } from 'uuid';
|
|
22
22
|
|
|
23
23
|
import agents from '../../build/plugins/agents.js';
|
|
24
|
+
import appMeta from '../build/appMeta.js';
|
|
24
25
|
import config from '../build/config.js';
|
|
26
|
+
import i18nConfig from '../build/i18n.js';
|
|
25
27
|
import connections from '../../build/plugins/connections.js';
|
|
26
28
|
import createLogger from './log/createLogger.js';
|
|
27
29
|
import fileCache from './fileCache.js';
|
|
@@ -67,12 +69,14 @@ function apiWrapper(handler) {
|
|
|
67
69
|
// Important to give absolute path so Next can trace build files
|
|
68
70
|
rid: uuid(),
|
|
69
71
|
agents,
|
|
72
|
+
appMeta,
|
|
70
73
|
buildDirectory,
|
|
71
74
|
configDirectory: process.env.LOWDEFY_DIRECTORY_CONFIG || process.cwd(),
|
|
72
75
|
config,
|
|
73
76
|
connections,
|
|
74
77
|
fileCache,
|
|
75
78
|
headers: req?.headers,
|
|
79
|
+
i18n: i18nConfig,
|
|
76
80
|
jsMap,
|
|
77
81
|
handleError: async (err) => {
|
|
78
82
|
console.error(err);
|
|
@@ -22,6 +22,7 @@ import { buildPageJit, createContext, makeId } from '@lowdefy/build/dev';
|
|
|
22
22
|
import compileCss from './compileCss.js';
|
|
23
23
|
import createLogger from './log/createLogger.js';
|
|
24
24
|
import PageCache from './pageCache.mjs';
|
|
25
|
+
import readBuildApiArtifacts from './readBuildApiArtifacts.mjs';
|
|
25
26
|
|
|
26
27
|
const jitLogger = createLogger({ name: 'jit-build' });
|
|
27
28
|
|
|
@@ -93,8 +94,11 @@ function getBuildContext(buildDirectory, configDirectory) {
|
|
|
93
94
|
const connectionIds = readJsonFile(path.join(buildDirectory, 'connectionIds.json')) ?? [];
|
|
94
95
|
|
|
95
96
|
const customTypesMap = readJsonFile(path.join(buildDirectory, 'customTypesMap.json')) ?? {};
|
|
97
|
+
const customMessagesMap =
|
|
98
|
+
readJsonFile(path.join(buildDirectory, 'customMessagesMap.json')) ?? {};
|
|
96
99
|
|
|
97
100
|
cachedBuildContext = createContext({
|
|
101
|
+
customMessagesMap,
|
|
98
102
|
customTypesMap,
|
|
99
103
|
directories: {
|
|
100
104
|
build: buildDirectory,
|
|
@@ -125,6 +129,11 @@ function getBuildContext(buildDirectory, configDirectory) {
|
|
|
125
129
|
Object.assign(cachedBuildContext.modules, modules);
|
|
126
130
|
}
|
|
127
131
|
|
|
132
|
+
// Restore api endpoint configs so JIT CallAPI validation (validateCallApiRefs in
|
|
133
|
+
// buildPageJit) can resolve endpointIds. Without this the dev context has no
|
|
134
|
+
// components.api and every CallAPI action is flagged as a non-existent endpoint.
|
|
135
|
+
cachedBuildContext.components = { api: readBuildApiArtifacts(buildDirectory) };
|
|
136
|
+
|
|
128
137
|
// Use the frozen icon imports from the initial build for JIT detection.
|
|
129
138
|
// This represents what's actually in the Next.js bundle — not what shallowBuild
|
|
130
139
|
// discovers on subsequent rebuilds (those icons aren't bundled yet).
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import fs from 'fs';
|
|
18
|
+
import path from 'path';
|
|
19
|
+
import { serializer } from '@lowdefy/helpers';
|
|
20
|
+
|
|
21
|
+
// Recursively collect every endpoint artifact under the api directory. Module
|
|
22
|
+
// endpoints are written to build/api/<moduleId>/<endpointId>.json because their
|
|
23
|
+
// scoped endpointId contains a "/" (buildModules prefixes ids with the module entry
|
|
24
|
+
// id), so a flat read would miss them and flag every module CallAPI as non-existent.
|
|
25
|
+
function readApiConfigs(directory) {
|
|
26
|
+
const configs = [];
|
|
27
|
+
for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
|
|
28
|
+
const entryPath = path.join(directory, entry.name);
|
|
29
|
+
if (entry.isDirectory()) {
|
|
30
|
+
configs.push(...readApiConfigs(entryPath));
|
|
31
|
+
} else if (entry.name.endsWith('.json')) {
|
|
32
|
+
configs.push(serializer.deserialize(JSON.parse(fs.readFileSync(entryPath, 'utf8'))));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return configs;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Read the endpoint artifacts persisted by writeApi (build/api/<endpointId>.json).
|
|
39
|
+
// The full build keeps endpoints in memory on components.api, but the dev context is
|
|
40
|
+
// rebuilt from disk, so getBuildContext hydrates them here. validateCallApiRefs needs
|
|
41
|
+
// each config's endpointId and type, both of which are present in the artifact.
|
|
42
|
+
function readBuildApiArtifacts(buildDirectory) {
|
|
43
|
+
const apiDirectory = path.join(buildDirectory, 'api');
|
|
44
|
+
try {
|
|
45
|
+
return readApiConfigs(apiDirectory);
|
|
46
|
+
} catch (error) {
|
|
47
|
+
// writeApi only creates the directory when endpoints are defined — absent means none.
|
|
48
|
+
if (error.code === 'ENOENT') return [];
|
|
49
|
+
throw error;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export default readBuildApiArtifacts;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
|
+
|
|
4
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
you may not use this file except in compliance with the License.
|
|
6
|
+
You may obtain a copy of the License at
|
|
7
|
+
|
|
8
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
+
|
|
10
|
+
Unless required by applicable law or agreed to in writing, software
|
|
11
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
|
+
See the License for the specific language governing permissions and
|
|
14
|
+
limitations under the License.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
import fs from 'fs';
|
|
18
|
+
import os from 'os';
|
|
19
|
+
import path from 'path';
|
|
20
|
+
import { serializer } from '@lowdefy/helpers';
|
|
21
|
+
|
|
22
|
+
import readBuildApiArtifacts from './readBuildApiArtifacts.mjs';
|
|
23
|
+
|
|
24
|
+
function makeBuildDir() {
|
|
25
|
+
return fs.mkdtempSync(path.join(os.tmpdir(), 'ldf-read-api-'));
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Mirror writeApi: each endpoint is serialized to build/api/<endpointId>.json.
|
|
29
|
+
// Scoped module endpointIds contain a "/", so the file lands in a nested directory.
|
|
30
|
+
function writeEndpoint(buildDir, endpoint) {
|
|
31
|
+
const filePath = path.join(buildDir, 'api', `${endpoint.endpointId}.json`);
|
|
32
|
+
fs.mkdirSync(path.dirname(filePath), { recursive: true });
|
|
33
|
+
fs.writeFileSync(filePath, serializer.serializeToString(endpoint));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
test('readBuildApiArtifacts returns [] when the api directory does not exist', () => {
|
|
37
|
+
const buildDir = makeBuildDir();
|
|
38
|
+
try {
|
|
39
|
+
expect(readBuildApiArtifacts(buildDir)).toEqual([]);
|
|
40
|
+
} finally {
|
|
41
|
+
fs.rmSync(buildDir, { recursive: true, force: true });
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
test('readBuildApiArtifacts returns [] when the api directory is empty', () => {
|
|
46
|
+
const buildDir = makeBuildDir();
|
|
47
|
+
fs.mkdirSync(path.join(buildDir, 'api'));
|
|
48
|
+
try {
|
|
49
|
+
expect(readBuildApiArtifacts(buildDir)).toEqual([]);
|
|
50
|
+
} finally {
|
|
51
|
+
fs.rmSync(buildDir, { recursive: true, force: true });
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
test('readBuildApiArtifacts reads and deserializes endpoint artifacts with endpointId and type', () => {
|
|
56
|
+
const buildDir = makeBuildDir();
|
|
57
|
+
writeEndpoint(buildDir, { id: 'endpoint:my_api', endpointId: 'my_api', type: 'Api' });
|
|
58
|
+
writeEndpoint(buildDir, {
|
|
59
|
+
id: 'endpoint:internal_api',
|
|
60
|
+
endpointId: 'internal_api',
|
|
61
|
+
type: 'InternalApi',
|
|
62
|
+
});
|
|
63
|
+
try {
|
|
64
|
+
const result = readBuildApiArtifacts(buildDir);
|
|
65
|
+
expect(result).toHaveLength(2);
|
|
66
|
+
expect(result).toEqual(
|
|
67
|
+
expect.arrayContaining([
|
|
68
|
+
expect.objectContaining({ endpointId: 'my_api', type: 'Api' }),
|
|
69
|
+
expect.objectContaining({ endpointId: 'internal_api', type: 'InternalApi' }),
|
|
70
|
+
])
|
|
71
|
+
);
|
|
72
|
+
} finally {
|
|
73
|
+
fs.rmSync(buildDir, { recursive: true, force: true });
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
test('readBuildApiArtifacts reads scoped module endpoints from nested subdirectories', () => {
|
|
78
|
+
const buildDir = makeBuildDir();
|
|
79
|
+
// Top-level endpoint at build/api/top_api.json
|
|
80
|
+
writeEndpoint(buildDir, { id: 'endpoint:top_api', endpointId: 'top_api', type: 'Api' });
|
|
81
|
+
// Module endpoint at build/api/inviter/send-invite.json (scoped id contains "/")
|
|
82
|
+
writeEndpoint(buildDir, {
|
|
83
|
+
id: 'endpoint:inviter/send-invite',
|
|
84
|
+
endpointId: 'inviter/send-invite',
|
|
85
|
+
type: 'Api',
|
|
86
|
+
});
|
|
87
|
+
try {
|
|
88
|
+
const result = readBuildApiArtifacts(buildDir);
|
|
89
|
+
expect(result.map((c) => c.endpointId).sort()).toEqual(['inviter/send-invite', 'top_api']);
|
|
90
|
+
} finally {
|
|
91
|
+
fs.rmSync(buildDir, { recursive: true, force: true });
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
test('readBuildApiArtifacts ignores non-json files in the api directory', () => {
|
|
96
|
+
const buildDir = makeBuildDir();
|
|
97
|
+
writeEndpoint(buildDir, { id: 'endpoint:my_api', endpointId: 'my_api', type: 'Api' });
|
|
98
|
+
fs.writeFileSync(path.join(buildDir, 'api', 'notes.txt'), 'ignore me');
|
|
99
|
+
try {
|
|
100
|
+
const result = readBuildApiArtifacts(buildDir);
|
|
101
|
+
expect(result).toHaveLength(1);
|
|
102
|
+
expect(result[0]).toEqual(expect.objectContaining({ endpointId: 'my_api', type: 'Api' }));
|
|
103
|
+
} finally {
|
|
104
|
+
fs.rmSync(buildDir, { recursive: true, force: true });
|
|
105
|
+
}
|
|
106
|
+
});
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
import { shallowBuild } from '@lowdefy/build/dev';
|
|
18
|
+
import createCustomPluginMessagesMap from '../utils/createCustomPluginMessagesMap.mjs';
|
|
18
19
|
import createCustomPluginTypesMap from '../utils/createCustomPluginTypesMap.mjs';
|
|
19
20
|
|
|
20
21
|
function formatDuration(ms) {
|
|
@@ -27,8 +28,10 @@ function lowdefyBuild({ directories, logger, options }) {
|
|
|
27
28
|
logger.info({ spin: 'start' }, 'Building config...');
|
|
28
29
|
const startTime = Date.now();
|
|
29
30
|
const customTypesMap = await createCustomPluginTypesMap({ directories, logger });
|
|
31
|
+
const customMessagesMap = await createCustomPluginMessagesMap({ directories, logger });
|
|
30
32
|
|
|
31
33
|
const result = await shallowBuild({
|
|
34
|
+
customMessagesMap,
|
|
32
35
|
customTypesMap,
|
|
33
36
|
directories,
|
|
34
37
|
logger,
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/*
|
|
3
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
4
|
+
|
|
5
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
you may not use this file except in compliance with the License.
|
|
7
|
+
You may obtain a copy of the License at
|
|
8
|
+
|
|
9
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
|
|
11
|
+
Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
See the License for the specific language governing permissions and
|
|
15
|
+
limitations under the License.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { createRequire } from 'node:module';
|
|
19
|
+
import path from 'path';
|
|
20
|
+
import { get } from '@lowdefy/helpers';
|
|
21
|
+
import { readFile } from '@lowdefy/node-utils';
|
|
22
|
+
import YAML from 'yaml';
|
|
23
|
+
|
|
24
|
+
const require = createRequire(import.meta.url);
|
|
25
|
+
|
|
26
|
+
async function getPluginDefinitions({ directories }) {
|
|
27
|
+
let lowdefyYaml = await readFile(path.join(directories.config, 'lowdefy.yaml'));
|
|
28
|
+
if (!lowdefyYaml) {
|
|
29
|
+
lowdefyYaml = await readFile(path.join(directories.config, 'lowdefy.yml'));
|
|
30
|
+
}
|
|
31
|
+
if (!lowdefyYaml) {
|
|
32
|
+
return [];
|
|
33
|
+
}
|
|
34
|
+
const lowdefy = YAML.parse(lowdefyYaml);
|
|
35
|
+
return get(lowdefy, 'plugins', { default: [] });
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
async function createCustomPluginMessagesMap({ directories, logger }) {
|
|
39
|
+
const customMessagesMap = {};
|
|
40
|
+
const pluginDefinitions = await getPluginDefinitions({ directories });
|
|
41
|
+
|
|
42
|
+
for (const plugin of pluginDefinitions) {
|
|
43
|
+
let messagesModule;
|
|
44
|
+
try {
|
|
45
|
+
messagesModule = require(`${plugin.name}/messages`);
|
|
46
|
+
} catch (e) {
|
|
47
|
+
// Plugin does not ship a `./messages` export — silently skip.
|
|
48
|
+
logger?.debug?.(`Plugin "${plugin.name}" has no "./messages" export; skipping.`);
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
const messages = messagesModule.default ?? messagesModule;
|
|
52
|
+
if (!messages || typeof messages !== 'object') continue;
|
|
53
|
+
customMessagesMap[plugin.name] = messages;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return customMessagesMap;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export default createCustomPluginMessagesMap;
|
package/next.config.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const lowdefyConfig = require('./build/config.json');
|
|
2
2
|
const blockPackages = require('./build/blockPackages.json');
|
|
3
|
+
const serverExternalPackages = require('./build/serverExternalPackages.json');
|
|
3
4
|
|
|
4
5
|
// Transpile @lowdefy/client plus all block plugin packages that may
|
|
5
6
|
// contain CSS imports (e.g., AG Grid themes, loaders, markdown).
|
|
@@ -16,6 +17,7 @@ const nextConfig = {
|
|
|
16
17
|
// reactStrictMode: true,
|
|
17
18
|
turbopack: {},
|
|
18
19
|
transpilePackages,
|
|
20
|
+
serverExternalPackages,
|
|
19
21
|
compress: false,
|
|
20
22
|
poweredByHeader: false,
|
|
21
23
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lowdefy/server-dev",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.4.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "",
|
|
6
6
|
"homepage": "https://lowdefy.com",
|
|
@@ -36,36 +36,37 @@
|
|
|
36
36
|
".npmrc"
|
|
37
37
|
],
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@lowdefy/actions-core": "5.
|
|
40
|
-
"@lowdefy/api": "5.
|
|
41
|
-
"@lowdefy/block-utils": "5.
|
|
42
|
-
"@lowdefy/blocks-aggrid": "5.
|
|
43
|
-
"@lowdefy/blocks-antd": "5.
|
|
44
|
-
"@lowdefy/blocks-antd-x": "5.
|
|
45
|
-
"@lowdefy/blocks-basic": "5.
|
|
46
|
-
"@lowdefy/blocks-echarts": "5.
|
|
47
|
-
"@lowdefy/blocks-loaders": "5.
|
|
48
|
-
"@lowdefy/blocks-markdown": "5.
|
|
49
|
-
"@lowdefy/blocks-tiptap": "5.
|
|
50
|
-
"@lowdefy/build": "5.
|
|
51
|
-
"@lowdefy/client": "5.
|
|
52
|
-
"@lowdefy/connection-axios-http": "5.
|
|
53
|
-
"@lowdefy/engine": "5.
|
|
54
|
-
"@lowdefy/errors": "5.
|
|
55
|
-
"@lowdefy/helpers": "5.
|
|
56
|
-
"@lowdefy/layout": "5.
|
|
57
|
-
"@lowdefy/logger": "5.
|
|
58
|
-
"@lowdefy/node-utils": "5.
|
|
59
|
-
"@lowdefy/operators-change-case": "5.
|
|
60
|
-
"@lowdefy/operators-dayjs": "5.
|
|
61
|
-
"@lowdefy/operators-diff": "5.
|
|
62
|
-
"@lowdefy/operators-js": "5.
|
|
63
|
-
"@lowdefy/operators-mql": "5.
|
|
64
|
-
"@lowdefy/operators-nunjucks": "5.
|
|
65
|
-
"@lowdefy/operators-uuid": "5.
|
|
66
|
-
"@lowdefy/operators-yaml": "5.
|
|
67
|
-
"@lowdefy/plugin-next-auth": "5.
|
|
39
|
+
"@lowdefy/actions-core": "5.4.0",
|
|
40
|
+
"@lowdefy/api": "5.4.0",
|
|
41
|
+
"@lowdefy/block-utils": "5.4.0",
|
|
42
|
+
"@lowdefy/blocks-aggrid": "5.4.0",
|
|
43
|
+
"@lowdefy/blocks-antd": "5.4.0",
|
|
44
|
+
"@lowdefy/blocks-antd-x": "5.4.0",
|
|
45
|
+
"@lowdefy/blocks-basic": "5.4.0",
|
|
46
|
+
"@lowdefy/blocks-echarts": "5.4.0",
|
|
47
|
+
"@lowdefy/blocks-loaders": "5.4.0",
|
|
48
|
+
"@lowdefy/blocks-markdown": "5.4.0",
|
|
49
|
+
"@lowdefy/blocks-tiptap": "5.4.0",
|
|
50
|
+
"@lowdefy/build": "5.4.0",
|
|
51
|
+
"@lowdefy/client": "5.4.0",
|
|
52
|
+
"@lowdefy/connection-axios-http": "5.4.0",
|
|
53
|
+
"@lowdefy/engine": "5.4.0",
|
|
54
|
+
"@lowdefy/errors": "5.4.0",
|
|
55
|
+
"@lowdefy/helpers": "5.4.0",
|
|
56
|
+
"@lowdefy/layout": "5.4.0",
|
|
57
|
+
"@lowdefy/logger": "5.4.0",
|
|
58
|
+
"@lowdefy/node-utils": "5.4.0",
|
|
59
|
+
"@lowdefy/operators-change-case": "5.4.0",
|
|
60
|
+
"@lowdefy/operators-dayjs": "5.4.0",
|
|
61
|
+
"@lowdefy/operators-diff": "5.4.0",
|
|
62
|
+
"@lowdefy/operators-js": "5.4.0",
|
|
63
|
+
"@lowdefy/operators-mql": "5.4.0",
|
|
64
|
+
"@lowdefy/operators-nunjucks": "5.4.0",
|
|
65
|
+
"@lowdefy/operators-uuid": "5.4.0",
|
|
66
|
+
"@lowdefy/operators-yaml": "5.4.0",
|
|
67
|
+
"@lowdefy/plugin-next-auth": "5.4.0",
|
|
68
68
|
"@ant-design/cssinjs": "2.1.2",
|
|
69
|
+
"@ant-design/x": "2.7.0",
|
|
69
70
|
"antd": "6.3.1",
|
|
70
71
|
"dayjs": "1.11.19",
|
|
71
72
|
"chokidar": "3.5.3",
|
package/package.original.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lowdefy/server-dev",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.4.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"description": "",
|
|
6
6
|
"homepage": "https://lowdefy.com",
|
|
@@ -44,36 +44,37 @@
|
|
|
44
44
|
"prepublishOnly": "pnpm build"
|
|
45
45
|
},
|
|
46
46
|
"dependencies": {
|
|
47
|
-
"@lowdefy/actions-core": "5.
|
|
48
|
-
"@lowdefy/api": "5.
|
|
49
|
-
"@lowdefy/block-utils": "5.
|
|
50
|
-
"@lowdefy/blocks-aggrid": "5.
|
|
51
|
-
"@lowdefy/blocks-antd": "5.
|
|
52
|
-
"@lowdefy/blocks-antd-x": "5.
|
|
53
|
-
"@lowdefy/blocks-basic": "5.
|
|
54
|
-
"@lowdefy/blocks-echarts": "5.
|
|
55
|
-
"@lowdefy/blocks-loaders": "5.
|
|
56
|
-
"@lowdefy/blocks-markdown": "5.
|
|
57
|
-
"@lowdefy/blocks-tiptap": "5.
|
|
58
|
-
"@lowdefy/build": "5.
|
|
59
|
-
"@lowdefy/client": "5.
|
|
60
|
-
"@lowdefy/connection-axios-http": "5.
|
|
61
|
-
"@lowdefy/engine": "5.
|
|
62
|
-
"@lowdefy/errors": "5.
|
|
63
|
-
"@lowdefy/helpers": "5.
|
|
64
|
-
"@lowdefy/layout": "5.
|
|
65
|
-
"@lowdefy/logger": "5.
|
|
66
|
-
"@lowdefy/node-utils": "5.
|
|
67
|
-
"@lowdefy/operators-change-case": "5.
|
|
68
|
-
"@lowdefy/operators-dayjs": "5.
|
|
69
|
-
"@lowdefy/operators-diff": "5.
|
|
70
|
-
"@lowdefy/operators-js": "5.
|
|
71
|
-
"@lowdefy/operators-mql": "5.
|
|
72
|
-
"@lowdefy/operators-nunjucks": "5.
|
|
73
|
-
"@lowdefy/operators-uuid": "5.
|
|
74
|
-
"@lowdefy/operators-yaml": "5.
|
|
75
|
-
"@lowdefy/plugin-next-auth": "5.
|
|
47
|
+
"@lowdefy/actions-core": "5.4.0",
|
|
48
|
+
"@lowdefy/api": "5.4.0",
|
|
49
|
+
"@lowdefy/block-utils": "5.4.0",
|
|
50
|
+
"@lowdefy/blocks-aggrid": "5.4.0",
|
|
51
|
+
"@lowdefy/blocks-antd": "5.4.0",
|
|
52
|
+
"@lowdefy/blocks-antd-x": "5.4.0",
|
|
53
|
+
"@lowdefy/blocks-basic": "5.4.0",
|
|
54
|
+
"@lowdefy/blocks-echarts": "5.4.0",
|
|
55
|
+
"@lowdefy/blocks-loaders": "5.4.0",
|
|
56
|
+
"@lowdefy/blocks-markdown": "5.4.0",
|
|
57
|
+
"@lowdefy/blocks-tiptap": "5.4.0",
|
|
58
|
+
"@lowdefy/build": "5.4.0",
|
|
59
|
+
"@lowdefy/client": "5.4.0",
|
|
60
|
+
"@lowdefy/connection-axios-http": "5.4.0",
|
|
61
|
+
"@lowdefy/engine": "5.4.0",
|
|
62
|
+
"@lowdefy/errors": "5.4.0",
|
|
63
|
+
"@lowdefy/helpers": "5.4.0",
|
|
64
|
+
"@lowdefy/layout": "5.4.0",
|
|
65
|
+
"@lowdefy/logger": "5.4.0",
|
|
66
|
+
"@lowdefy/node-utils": "5.4.0",
|
|
67
|
+
"@lowdefy/operators-change-case": "5.4.0",
|
|
68
|
+
"@lowdefy/operators-dayjs": "5.4.0",
|
|
69
|
+
"@lowdefy/operators-diff": "5.4.0",
|
|
70
|
+
"@lowdefy/operators-js": "5.4.0",
|
|
71
|
+
"@lowdefy/operators-mql": "5.4.0",
|
|
72
|
+
"@lowdefy/operators-nunjucks": "5.4.0",
|
|
73
|
+
"@lowdefy/operators-uuid": "5.4.0",
|
|
74
|
+
"@lowdefy/operators-yaml": "5.4.0",
|
|
75
|
+
"@lowdefy/plugin-next-auth": "5.4.0",
|
|
76
76
|
"@ant-design/cssinjs": "2.1.2",
|
|
77
|
+
"@ant-design/x": "2.7.0",
|
|
77
78
|
"antd": "6.3.1",
|
|
78
79
|
"dayjs": "1.11.19",
|
|
79
80
|
"chokidar": "3.5.3",
|
package/pages/_app.js
CHANGED
|
@@ -25,10 +25,14 @@ import { useRouter } from 'next/router';
|
|
|
25
25
|
import useSWR from 'swr';
|
|
26
26
|
|
|
27
27
|
import { ErrorBoundary } from '@lowdefy/block-utils';
|
|
28
|
-
import { useDarkMode } from '@lowdefy/client';
|
|
28
|
+
import { useDarkMode, useLocale } from '@lowdefy/client';
|
|
29
29
|
import { StyleProvider } from '@ant-design/cssinjs';
|
|
30
|
-
import { App as AntdApp,
|
|
30
|
+
import { App as AntdApp, theme as antdTheme } from 'antd';
|
|
31
|
+
import { XProvider } from '@ant-design/x';
|
|
31
32
|
|
|
33
|
+
import antdLocaleLoaders from '../build/i18n/antdLocales.js';
|
|
34
|
+
import antdXLocaleLoaders from '../build/i18n/antdXLocales.js';
|
|
35
|
+
import dayjsLocaleMap from '../build/i18n/dayjsLocales.js';
|
|
32
36
|
import Auth from '../lib/client/auth/Auth.js';
|
|
33
37
|
import ErrorBar from '../lib/client/ErrorBar.js';
|
|
34
38
|
import request from '../lib/client/utils/request.js';
|
|
@@ -62,6 +66,17 @@ function App({ Component }) {
|
|
|
62
66
|
configDarkMode: lowdefyRef.current.theme?.darkMode,
|
|
63
67
|
});
|
|
64
68
|
|
|
69
|
+
const { active: activeLocale, antdLocale, antdXLocale } = useLocale({
|
|
70
|
+
i18n: rootConfig?.i18n,
|
|
71
|
+
antdLocaleLoaders,
|
|
72
|
+
antdXLocaleLoaders,
|
|
73
|
+
dayjsLocaleMap,
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
if (rootConfig?.i18n?.defaultLocale) {
|
|
77
|
+
lowdefyRef.current.i18n = { ...rootConfig.i18n, active: activeLocale };
|
|
78
|
+
}
|
|
79
|
+
|
|
65
80
|
const {
|
|
66
81
|
lightToken: _lightToken,
|
|
67
82
|
darkToken: _darkToken,
|
|
@@ -99,9 +114,21 @@ function App({ Component }) {
|
|
|
99
114
|
}
|
|
100
115
|
}, []);
|
|
101
116
|
|
|
117
|
+
// XProvider extends antd's ConfigProvider; merging antd + antd-X locale packs
|
|
118
|
+
// gives X components their built-in strings alongside antd's.
|
|
119
|
+
const mergedLocale = antdLocale || antdXLocale
|
|
120
|
+
? { ...(antdLocale ?? {}), ...(antdXLocale ?? {}) }
|
|
121
|
+
: undefined;
|
|
122
|
+
|
|
102
123
|
return (
|
|
103
124
|
<StyleProvider layer>
|
|
104
|
-
<
|
|
125
|
+
<XProvider
|
|
126
|
+
locale={mergedLocale}
|
|
127
|
+
form={
|
|
128
|
+
antdLocale?.Form?.defaultValidateMessages
|
|
129
|
+
? { validateMessages: antdLocale.Form.defaultValidateMessages }
|
|
130
|
+
: undefined
|
|
131
|
+
}
|
|
105
132
|
theme={{
|
|
106
133
|
...antdConfig,
|
|
107
134
|
token,
|
|
@@ -134,7 +161,7 @@ function App({ Component }) {
|
|
|
134
161
|
<ErrorBar errors={runtimeErrors} />
|
|
135
162
|
</ThemeTokenResolver>
|
|
136
163
|
</AntdApp>
|
|
137
|
-
</
|
|
164
|
+
</XProvider>
|
|
138
165
|
</StyleProvider>
|
|
139
166
|
);
|
|
140
167
|
}
|
|
@@ -15,17 +15,18 @@
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
import { callAgent } from '@lowdefy/api';
|
|
18
|
-
import { type } from '@lowdefy/helpers';
|
|
18
|
+
import { translate, type } from '@lowdefy/helpers';
|
|
19
19
|
|
|
20
20
|
import apiWrapper from '../../../lib/server/apiWrapper.js';
|
|
21
21
|
|
|
22
22
|
async function handler({ context, req, res }) {
|
|
23
|
+
const t = (key, values) => translate({ key, values, i18n: context.i18n });
|
|
23
24
|
if (req.method !== 'POST') {
|
|
24
|
-
throw new Error('
|
|
25
|
+
throw new Error(t('agent.runtime.methodNotAllowed'));
|
|
25
26
|
}
|
|
26
27
|
const segments = req.query.path;
|
|
27
28
|
if (!Array.isArray(segments) || segments.length < 2) {
|
|
28
|
-
res.status(400).json({ error: '
|
|
29
|
+
res.status(400).json({ error: t('agent.runtime.invalidPath') });
|
|
29
30
|
return;
|
|
30
31
|
}
|
|
31
32
|
const agentId = segments[segments.length - 1];
|
|
@@ -34,15 +35,15 @@ async function handler({ context, req, res }) {
|
|
|
34
35
|
const { conversationId } = req.query;
|
|
35
36
|
const { messages, urlQuery, sharedState } = req.body;
|
|
36
37
|
if (!Array.isArray(messages)) {
|
|
37
|
-
res.status(400).json({ error: '
|
|
38
|
+
res.status(400).json({ error: t('agent.runtime.messagesMustBeArray') });
|
|
38
39
|
return;
|
|
39
40
|
}
|
|
40
41
|
if (urlQuery != null && (typeof urlQuery !== 'object' || Array.isArray(urlQuery))) {
|
|
41
|
-
res.status(400).json({ error: '
|
|
42
|
+
res.status(400).json({ error: t('agent.runtime.urlQueryMustBeObject') });
|
|
42
43
|
return;
|
|
43
44
|
}
|
|
44
45
|
if (sharedState != null && !type.isObject(sharedState)) {
|
|
45
|
-
res.status(400).json({ error: '
|
|
46
|
+
res.status(400).json({ error: t('agent.runtime.sharedStateMustBeObject') });
|
|
46
47
|
return;
|
|
47
48
|
}
|
|
48
49
|
const { response: webResponse } = await callAgent(context, {
|