@lowdefy/build 0.0.0-experimental-20251203205559 → 0.0.0-experimental-20260113081624
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/build/addKeys.js +2 -0
- package/dist/build/buildApi/buildEndpoint.js +6 -0
- package/dist/build/buildApi/buildRoutine/countStepTypes.js +1 -1
- package/dist/build/buildApi/validateStepReferences.js +65 -0
- package/dist/build/buildAuth/buildAuthPlugins.js +42 -12
- package/dist/build/buildAuth/validateAuthConfig.js +10 -2
- package/dist/build/buildAuth/validateMutualExclusivity.js +18 -4
- package/dist/build/buildConnections.js +25 -6
- package/dist/build/buildImports/buildIconImports.js +19 -36
- package/dist/build/buildLogger.js +41 -0
- package/dist/build/buildMenu.js +40 -13
- package/dist/build/buildPages/buildBlock/buildEvents.js +90 -9
- package/dist/build/buildPages/buildBlock/buildRequests.js +47 -7
- package/dist/build/buildPages/buildBlock/countBlockTypes.js +1 -1
- package/dist/build/buildPages/buildBlock/validateBlock.js +33 -7
- package/dist/build/buildPages/buildPage.js +28 -4
- package/dist/build/buildPages/buildPages.js +26 -1
- package/dist/build/buildPages/buildTestPage.js +9 -1
- package/dist/build/buildPages/validateLinkReferences.js +33 -0
- package/dist/build/buildPages/validatePayloadReferences.js +52 -0
- package/dist/build/buildPages/validateRequestReferences.js +33 -0
- package/dist/build/buildPages/validateStateReferences.js +52 -0
- package/dist/build/buildRefs/buildRefs.js +11 -33
- package/dist/build/buildRefs/evaluateBuildOperators.js +8 -2
- package/dist/build/buildRefs/getConfigFile.js +2 -1
- package/dist/build/buildRefs/getRefContent.js +17 -31
- package/dist/build/buildRefs/getRefsFromFile.js +8 -3
- package/dist/build/buildRefs/makeRefDefinition.js +9 -8
- package/dist/build/buildRefs/parseRefContent.js +61 -2
- package/dist/build/buildRefs/populateRefs.js +14 -11
- package/dist/build/buildRefs/recursiveBuild.js +62 -71
- package/dist/build/buildTypes.js +19 -2
- package/dist/build/formatBuildError.js +34 -0
- package/dist/build/writeLogger.js +19 -0
- package/dist/createContext.js +3 -19
- package/dist/defaultTypesMap.js +541 -534
- package/dist/index.js +138 -125
- package/dist/lowdefySchema.js +75 -0
- package/dist/test/testContext.js +2 -1
- package/dist/utils/collectConfigError.js +40 -0
- package/dist/utils/countOperators.js +24 -11
- package/dist/utils/createCheckDuplicateId.js +30 -9
- package/dist/utils/createCounter.js +15 -2
- package/dist/utils/extractOperatorKey.js +36 -0
- package/dist/utils/findSimilarString.js +53 -0
- package/dist/utils/formatConfigError.js +24 -0
- package/dist/utils/formatConfigMessage.js +33 -0
- package/dist/utils/formatConfigWarning.js +24 -0
- package/dist/utils/traverseConfig.js +43 -0
- package/dist/utils/tryBuildStep.js +38 -0
- package/package.json +39 -39
- package/dist/utils/createBuildProfiler.js +0 -125
- package/dist/utils/invalidateChangedFiles.js +0 -89
- package/dist/utils/makeRefHash.js +0 -15
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
/*
|
|
1
|
+
/* eslint-disable no-console */ /*
|
|
2
2
|
Copyright 2020-2024 Lowdefy, Inc
|
|
3
3
|
|
|
4
4
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
@@ -12,9 +12,9 @@
|
|
|
12
12
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
13
13
|
See the License for the specific language governing permissions and
|
|
14
14
|
limitations under the License.
|
|
15
|
-
*/ import
|
|
16
|
-
import createContext from './createContext.js';
|
|
15
|
+
*/ import createContext from './createContext.js';
|
|
17
16
|
import createPluginTypesMap from './utils/createPluginTypesMap.js';
|
|
17
|
+
import tryBuildStep from './utils/tryBuildStep.js';
|
|
18
18
|
import addDefaultPages from './build/addDefaultPages/addDefaultPages.js';
|
|
19
19
|
import addKeys from './build/addKeys.js';
|
|
20
20
|
import buildApp from './build/buildApp.js';
|
|
@@ -23,6 +23,7 @@ import buildConnections from './build/buildConnections.js';
|
|
|
23
23
|
import buildApi from './build/buildApi/buildApi.js';
|
|
24
24
|
import buildImports from './build/buildImports/buildImports.js';
|
|
25
25
|
import buildJs from './build/buildJs/buildJs.js';
|
|
26
|
+
import buildLogger from './build/buildLogger.js';
|
|
26
27
|
import buildMenu from './build/buildMenu.js';
|
|
27
28
|
import buildPages from './build/buildPages/buildPages.js';
|
|
28
29
|
import buildRefs from './build/buildRefs/buildRefs.js';
|
|
@@ -39,6 +40,7 @@ import writeConnections from './build/writeConnections.js';
|
|
|
39
40
|
import writeApi from './build/writeApi.js';
|
|
40
41
|
import writeGlobal from './build/writeGlobal.js';
|
|
41
42
|
import writeJs from './build/buildJs/writeJs.js';
|
|
43
|
+
import writeLogger from './build/writeLogger.js';
|
|
42
44
|
import writeMaps from './build/writeMaps.js';
|
|
43
45
|
import writeMenus from './build/writeMenus.js';
|
|
44
46
|
import writePages from './build/writePages.js';
|
|
@@ -47,128 +49,139 @@ import writeRequests from './build/writeRequests.js';
|
|
|
47
49
|
import writeTypes from './build/writeTypes.js';
|
|
48
50
|
async function build(options) {
|
|
49
51
|
const context = createContext(options);
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
await
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
await
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
await
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
await
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
await
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
await
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
await
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
await
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
await
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
await
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
await
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
await
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
await
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
52
|
+
const components = await buildRefs({
|
|
53
|
+
context
|
|
54
|
+
});
|
|
55
|
+
// Build steps - collect all errors before stopping
|
|
56
|
+
tryBuildStep(testSchema, 'testSchema', {
|
|
57
|
+
components,
|
|
58
|
+
context
|
|
59
|
+
});
|
|
60
|
+
tryBuildStep(buildApp, 'buildApp', {
|
|
61
|
+
components,
|
|
62
|
+
context
|
|
63
|
+
});
|
|
64
|
+
tryBuildStep(buildLogger, 'buildLogger', {
|
|
65
|
+
components,
|
|
66
|
+
context
|
|
67
|
+
});
|
|
68
|
+
tryBuildStep(validateConfig, 'validateConfig', {
|
|
69
|
+
components,
|
|
70
|
+
context
|
|
71
|
+
});
|
|
72
|
+
tryBuildStep(addDefaultPages, 'addDefaultPages', {
|
|
73
|
+
components,
|
|
74
|
+
context
|
|
75
|
+
});
|
|
76
|
+
tryBuildStep(addKeys, 'addKeys', {
|
|
77
|
+
components,
|
|
78
|
+
context
|
|
79
|
+
});
|
|
80
|
+
tryBuildStep(buildAuth, 'buildAuth', {
|
|
81
|
+
components,
|
|
82
|
+
context
|
|
83
|
+
});
|
|
84
|
+
tryBuildStep(buildConnections, 'buildConnections', {
|
|
85
|
+
components,
|
|
86
|
+
context
|
|
87
|
+
});
|
|
88
|
+
tryBuildStep(buildApi, 'buildApi', {
|
|
89
|
+
components,
|
|
90
|
+
context
|
|
91
|
+
});
|
|
92
|
+
tryBuildStep(buildPages, 'buildPages', {
|
|
93
|
+
components,
|
|
94
|
+
context
|
|
95
|
+
});
|
|
96
|
+
tryBuildStep(buildMenu, 'buildMenu', {
|
|
97
|
+
components,
|
|
98
|
+
context
|
|
99
|
+
});
|
|
100
|
+
tryBuildStep(buildJs, 'buildJs', {
|
|
101
|
+
components,
|
|
102
|
+
context
|
|
103
|
+
});
|
|
104
|
+
tryBuildStep(buildTypes, 'buildTypes', {
|
|
105
|
+
components,
|
|
106
|
+
context
|
|
107
|
+
});
|
|
108
|
+
tryBuildStep(buildImports, 'buildImports', {
|
|
109
|
+
components,
|
|
110
|
+
context
|
|
111
|
+
});
|
|
112
|
+
// Check if there are any collected errors before writing
|
|
113
|
+
if (context.errors.length > 0) {
|
|
114
|
+
context.logger.error(`\nBuild failed with ${context.errors.length} error(s):\n`);
|
|
115
|
+
throw new Error(`Build failed with ${context.errors.length} error(s). See above for details.`);
|
|
116
|
+
}
|
|
117
|
+
// Write steps - only if no errors
|
|
118
|
+
await cleanBuildDirectory({
|
|
119
|
+
context
|
|
120
|
+
});
|
|
121
|
+
await writeApp({
|
|
122
|
+
components,
|
|
123
|
+
context
|
|
124
|
+
});
|
|
125
|
+
await writeAuth({
|
|
126
|
+
components,
|
|
127
|
+
context
|
|
128
|
+
});
|
|
129
|
+
await writeConnections({
|
|
130
|
+
components,
|
|
131
|
+
context
|
|
132
|
+
});
|
|
133
|
+
await writeApi({
|
|
134
|
+
components,
|
|
135
|
+
context
|
|
136
|
+
});
|
|
137
|
+
await writeRequests({
|
|
138
|
+
components,
|
|
139
|
+
context
|
|
140
|
+
});
|
|
141
|
+
await writePages({
|
|
142
|
+
components,
|
|
143
|
+
context
|
|
144
|
+
});
|
|
145
|
+
await writeConfig({
|
|
146
|
+
components,
|
|
147
|
+
context
|
|
148
|
+
});
|
|
149
|
+
await writeGlobal({
|
|
150
|
+
components,
|
|
151
|
+
context
|
|
152
|
+
});
|
|
153
|
+
await writeLogger({
|
|
154
|
+
components,
|
|
155
|
+
context
|
|
156
|
+
});
|
|
157
|
+
await writeMaps({
|
|
158
|
+
components,
|
|
159
|
+
context
|
|
160
|
+
});
|
|
161
|
+
await writeMenus({
|
|
162
|
+
components,
|
|
163
|
+
context
|
|
164
|
+
});
|
|
165
|
+
await writeTypes({
|
|
166
|
+
components,
|
|
167
|
+
context
|
|
168
|
+
});
|
|
169
|
+
await writePluginImports({
|
|
170
|
+
components,
|
|
171
|
+
context
|
|
172
|
+
});
|
|
173
|
+
await writeJs({
|
|
174
|
+
components,
|
|
175
|
+
context
|
|
176
|
+
});
|
|
177
|
+
await updateServerPackageJson({
|
|
178
|
+
components,
|
|
179
|
+
context
|
|
180
|
+
});
|
|
181
|
+
await copyPublicFolder({
|
|
182
|
+
components,
|
|
183
|
+
context
|
|
184
|
+
});
|
|
172
185
|
}
|
|
173
186
|
export { createPluginTypesMap };
|
|
174
187
|
export default build;
|
package/dist/lowdefySchema.js
CHANGED
|
@@ -967,6 +967,81 @@ export default {
|
|
|
967
967
|
errorMessage: {
|
|
968
968
|
type: 'App "pages" should be an array.'
|
|
969
969
|
}
|
|
970
|
+
},
|
|
971
|
+
logger: {
|
|
972
|
+
type: 'object',
|
|
973
|
+
additionalProperties: false,
|
|
974
|
+
errorMessage: {
|
|
975
|
+
type: 'App "logger" should be an object.'
|
|
976
|
+
},
|
|
977
|
+
properties: {
|
|
978
|
+
sentry: {
|
|
979
|
+
type: 'object',
|
|
980
|
+
additionalProperties: false,
|
|
981
|
+
errorMessage: {
|
|
982
|
+
type: 'App "logger.sentry" should be an object.'
|
|
983
|
+
},
|
|
984
|
+
properties: {
|
|
985
|
+
client: {
|
|
986
|
+
type: 'boolean',
|
|
987
|
+
errorMessage: {
|
|
988
|
+
type: 'App "logger.sentry.client" should be a boolean.'
|
|
989
|
+
}
|
|
990
|
+
},
|
|
991
|
+
server: {
|
|
992
|
+
type: 'boolean',
|
|
993
|
+
errorMessage: {
|
|
994
|
+
type: 'App "logger.sentry.server" should be a boolean.'
|
|
995
|
+
}
|
|
996
|
+
},
|
|
997
|
+
tracesSampleRate: {
|
|
998
|
+
type: 'number',
|
|
999
|
+
minimum: 0,
|
|
1000
|
+
maximum: 1,
|
|
1001
|
+
errorMessage: {
|
|
1002
|
+
type: 'App "logger.sentry.tracesSampleRate" should be a number between 0 and 1.'
|
|
1003
|
+
}
|
|
1004
|
+
},
|
|
1005
|
+
replaysSessionSampleRate: {
|
|
1006
|
+
type: 'number',
|
|
1007
|
+
minimum: 0,
|
|
1008
|
+
maximum: 1,
|
|
1009
|
+
errorMessage: {
|
|
1010
|
+
type: 'App "logger.sentry.replaysSessionSampleRate" should be a number between 0 and 1.'
|
|
1011
|
+
}
|
|
1012
|
+
},
|
|
1013
|
+
replaysOnErrorSampleRate: {
|
|
1014
|
+
type: 'number',
|
|
1015
|
+
minimum: 0,
|
|
1016
|
+
maximum: 1,
|
|
1017
|
+
errorMessage: {
|
|
1018
|
+
type: 'App "logger.sentry.replaysOnErrorSampleRate" should be a number between 0 and 1.'
|
|
1019
|
+
}
|
|
1020
|
+
},
|
|
1021
|
+
feedback: {
|
|
1022
|
+
type: 'boolean',
|
|
1023
|
+
errorMessage: {
|
|
1024
|
+
type: 'App "logger.sentry.feedback" should be a boolean.'
|
|
1025
|
+
}
|
|
1026
|
+
},
|
|
1027
|
+
environment: {
|
|
1028
|
+
type: 'string',
|
|
1029
|
+
errorMessage: {
|
|
1030
|
+
type: 'App "logger.sentry.environment" should be a string.'
|
|
1031
|
+
}
|
|
1032
|
+
},
|
|
1033
|
+
userFields: {
|
|
1034
|
+
type: 'array',
|
|
1035
|
+
items: {
|
|
1036
|
+
type: 'string'
|
|
1037
|
+
},
|
|
1038
|
+
errorMessage: {
|
|
1039
|
+
type: 'App "logger.sentry.userFields" should be an array of strings.'
|
|
1040
|
+
}
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
970
1045
|
}
|
|
971
1046
|
},
|
|
972
1047
|
errorMessage: {
|
package/dist/test/testContext.js
CHANGED
|
@@ -47,7 +47,8 @@ function testContext({ writeBuildArtifact, configDirectory, readConfigFile, logg
|
|
|
47
47
|
readConfigFile: readConfigFile || (()=>{}),
|
|
48
48
|
refMap: {},
|
|
49
49
|
keyMap: {},
|
|
50
|
-
jsMap: {}
|
|
50
|
+
jsMap: {},
|
|
51
|
+
connectionIds: new Set()
|
|
51
52
|
};
|
|
52
53
|
context.logger = {
|
|
53
54
|
...defaultLogger,
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2024 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
|
+
*/ import formatConfigError from './formatConfigError.js';
|
|
16
|
+
/**
|
|
17
|
+
* Collects a config error instead of throwing immediately.
|
|
18
|
+
* Allows the build to continue and collect all errors before stopping.
|
|
19
|
+
*
|
|
20
|
+
* @param {Object} params
|
|
21
|
+
* @param {string} params.message - Error message
|
|
22
|
+
* @param {string} params.configKey - Config key (~k) for location tracking
|
|
23
|
+
* @param {Object} params.context - Build context
|
|
24
|
+
*/ function collectConfigError({ message, configKey, context }) {
|
|
25
|
+
const errorMessage = formatConfigError({
|
|
26
|
+
message,
|
|
27
|
+
configKey,
|
|
28
|
+
context
|
|
29
|
+
});
|
|
30
|
+
if (!context.errors) {
|
|
31
|
+
// If no error collection array, throw immediately (fallback for tests)
|
|
32
|
+
throw new Error(errorMessage);
|
|
33
|
+
}
|
|
34
|
+
// Collect error to show all errors at once
|
|
35
|
+
context.errors.push(errorMessage);
|
|
36
|
+
if (context.logger && context.logger.error) {
|
|
37
|
+
context.logger.error(errorMessage);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
export default collectConfigError;
|
|
@@ -13,18 +13,31 @@
|
|
|
13
13
|
See the License for the specific language governing permissions and
|
|
14
14
|
limitations under the License.
|
|
15
15
|
*/ import { type } from '@lowdefy/helpers';
|
|
16
|
-
function
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
16
|
+
function walkAndCount(value, counter, parentConfigKey) {
|
|
17
|
+
if (type.isArray(value)) {
|
|
18
|
+
value.forEach((item)=>walkAndCount(item, counter, parentConfigKey));
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
if (!type.isObject(value)) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const configKey = value['~k'] || parentConfigKey;
|
|
25
|
+
const keys = Object.keys(value);
|
|
26
|
+
// Check if this object is an operator (single key starting with _)
|
|
27
|
+
if (keys.length === 1) {
|
|
28
|
+
const key = keys[0];
|
|
29
|
+
const [op] = key.split('.');
|
|
30
|
+
const operator = op.replace(/^(_+)/gm, '_');
|
|
31
|
+
if (operator.length > 1 && operator[0] === '_') {
|
|
32
|
+
counter.increment(operator, configKey);
|
|
25
33
|
}
|
|
26
|
-
return value;
|
|
27
34
|
}
|
|
28
|
-
|
|
35
|
+
// Recurse into all values
|
|
36
|
+
keys.forEach((key)=>{
|
|
37
|
+
walkAndCount(value[key], counter, configKey);
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
function countOperators(obj, { counter }) {
|
|
41
|
+
walkAndCount(obj, counter, null);
|
|
29
42
|
}
|
|
30
43
|
export default countOperators;
|
|
@@ -13,17 +13,38 @@
|
|
|
13
13
|
See the License for the specific language governing permissions and
|
|
14
14
|
limitations under the License.
|
|
15
15
|
*/ import { nunjucksFunction } from '@lowdefy/nunjucks';
|
|
16
|
-
|
|
16
|
+
import { resolveConfigLocation } from '@lowdefy/helpers';
|
|
17
|
+
function createCheckDuplicateId({ message, context }) {
|
|
17
18
|
const template = nunjucksFunction(message);
|
|
18
19
|
const ids = new Set();
|
|
19
|
-
function checkDuplicateId({ id, blockId, eventId, menuId, pageId }) {
|
|
20
|
-
if (ids.has(id.toLowerCase()))
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
function checkDuplicateId({ id, blockId, configKey, eventId, menuId, pageId }) {
|
|
21
|
+
if (ids.has(id.toLowerCase())) {
|
|
22
|
+
let errorMessage = template({
|
|
23
|
+
id,
|
|
24
|
+
blockId,
|
|
25
|
+
eventId,
|
|
26
|
+
menuId,
|
|
27
|
+
pageId
|
|
28
|
+
});
|
|
29
|
+
if (configKey && context) {
|
|
30
|
+
const location = resolveConfigLocation({
|
|
31
|
+
configKey,
|
|
32
|
+
keyMap: context.keyMap,
|
|
33
|
+
refMap: context.refMap,
|
|
34
|
+
configDirectory: context.directories.config
|
|
35
|
+
});
|
|
36
|
+
if (location) {
|
|
37
|
+
const source = location.source ? `${location.source} at ${location.config}` : '';
|
|
38
|
+
const link = location.link || '';
|
|
39
|
+
errorMessage = `[Config Error] ${errorMessage}\n ${source}\n ${link}`;
|
|
40
|
+
} else {
|
|
41
|
+
errorMessage = `[Config Error] ${errorMessage}`;
|
|
42
|
+
}
|
|
43
|
+
} else {
|
|
44
|
+
errorMessage = `[Config Error] ${errorMessage}`;
|
|
45
|
+
}
|
|
46
|
+
throw new Error(errorMessage);
|
|
47
|
+
}
|
|
27
48
|
ids.add(id.toLowerCase());
|
|
28
49
|
}
|
|
29
50
|
return checkDuplicateId;
|
|
@@ -14,9 +14,14 @@
|
|
|
14
14
|
limitations under the License.
|
|
15
15
|
*/ function createCounter() {
|
|
16
16
|
const counts = new Map();
|
|
17
|
-
|
|
17
|
+
const locations = new Map();
|
|
18
|
+
function increment(key, configKey) {
|
|
18
19
|
const count = counts.get(key) || 0;
|
|
19
20
|
counts.set(key, count + 1);
|
|
21
|
+
// Store first occurrence location for error reporting
|
|
22
|
+
if (configKey && !locations.has(key)) {
|
|
23
|
+
locations.set(key, configKey);
|
|
24
|
+
}
|
|
20
25
|
}
|
|
21
26
|
function getCount(key) {
|
|
22
27
|
return counts.get(key) || 0;
|
|
@@ -24,10 +29,18 @@
|
|
|
24
29
|
function getCounts() {
|
|
25
30
|
return Object.fromEntries(counts);
|
|
26
31
|
}
|
|
32
|
+
function getLocation(key) {
|
|
33
|
+
return locations.get(key) || null;
|
|
34
|
+
}
|
|
35
|
+
function getLocations() {
|
|
36
|
+
return Object.fromEntries(locations);
|
|
37
|
+
}
|
|
27
38
|
return {
|
|
28
39
|
increment,
|
|
29
40
|
getCount,
|
|
30
|
-
getCounts
|
|
41
|
+
getCounts,
|
|
42
|
+
getLocation,
|
|
43
|
+
getLocations
|
|
31
44
|
};
|
|
32
45
|
}
|
|
33
46
|
export default createCounter;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2024 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
|
+
*/ import { type } from '@lowdefy/helpers';
|
|
16
|
+
/**
|
|
17
|
+
* Extracts the top-level key from an operator reference value.
|
|
18
|
+
*
|
|
19
|
+
* Handles both string and object forms of operator references:
|
|
20
|
+
* - String: "_state: 'user.name'" -> 'user'
|
|
21
|
+
* - Object: "_state: { key: 'user.name' }" -> 'user'
|
|
22
|
+
* - Object: "_state: { path: 'user[0].name' }" -> 'user'
|
|
23
|
+
*
|
|
24
|
+
* @param {Object} params
|
|
25
|
+
* @param {string|Object} params.operatorValue - The value of the operator (e.g., obj._state)
|
|
26
|
+
* @returns {string|null} The top-level key, or null if not extractable
|
|
27
|
+
*/ function extractOperatorKey({ operatorValue }) {
|
|
28
|
+
const value = type.isString(operatorValue) ? operatorValue : type.isObject(operatorValue) ? operatorValue.key || operatorValue.path : null;
|
|
29
|
+
if (!value) {
|
|
30
|
+
return null;
|
|
31
|
+
}
|
|
32
|
+
// Extract first segment before any '.' or '['
|
|
33
|
+
const topLevelKey = value.split(/[.[]/)[0];
|
|
34
|
+
return topLevelKey || null;
|
|
35
|
+
}
|
|
36
|
+
export default extractOperatorKey;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Copyright 2020-2024 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
|
+
*/ function levenshteinDistance(a, b) {
|
|
16
|
+
const matrix = [];
|
|
17
|
+
for(let i = 0; i <= b.length; i++){
|
|
18
|
+
matrix[i] = [
|
|
19
|
+
i
|
|
20
|
+
];
|
|
21
|
+
}
|
|
22
|
+
for(let j = 0; j <= a.length; j++){
|
|
23
|
+
matrix[0][j] = j;
|
|
24
|
+
}
|
|
25
|
+
for(let i = 1; i <= b.length; i++){
|
|
26
|
+
for(let j = 1; j <= a.length; j++){
|
|
27
|
+
if (b[i - 1] === a[j - 1]) {
|
|
28
|
+
matrix[i][j] = matrix[i - 1][j - 1];
|
|
29
|
+
} else {
|
|
30
|
+
matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j] + 1);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return matrix[b.length][a.length];
|
|
35
|
+
}
|
|
36
|
+
function findSimilarString({ input, candidates, maxDistance = 3 }) {
|
|
37
|
+
if (!input || !candidates || candidates.length === 0) {
|
|
38
|
+
return null;
|
|
39
|
+
}
|
|
40
|
+
const inputLower = input.toLowerCase();
|
|
41
|
+
let bestMatch = null;
|
|
42
|
+
let bestDistance = Infinity;
|
|
43
|
+
for (const candidate of candidates){
|
|
44
|
+
const candidateLower = candidate.toLowerCase();
|
|
45
|
+
const distance = levenshteinDistance(inputLower, candidateLower);
|
|
46
|
+
if (distance < bestDistance && distance <= maxDistance) {
|
|
47
|
+
bestDistance = distance;
|
|
48
|
+
bestMatch = candidate;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return bestMatch;
|
|
52
|
+
}
|
|
53
|
+
export default findSimilarString;
|