@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/build/addKeys.js
CHANGED
|
@@ -49,6 +49,7 @@ function recAddKeys({ object, key, keyMap, parentKeyMapId }) {
|
|
|
49
49
|
keyMap[keyMapId] = {
|
|
50
50
|
key,
|
|
51
51
|
'~r': object['~r'],
|
|
52
|
+
'~l': object['~l'],
|
|
52
53
|
'~k_parent': parentKeyMapId
|
|
53
54
|
};
|
|
54
55
|
Object.defineProperty(object, '~k', {
|
|
@@ -58,6 +59,7 @@ function recAddKeys({ object, key, keyMap, parentKeyMapId }) {
|
|
|
58
59
|
configurable: true
|
|
59
60
|
});
|
|
60
61
|
delete object['~r'];
|
|
62
|
+
delete object['~l'];
|
|
61
63
|
Object.keys(object).forEach((nextKey)=>{
|
|
62
64
|
if (type.isObject(object[nextKey])) {
|
|
63
65
|
recAddKeys({
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
limitations under the License.
|
|
15
15
|
*/ import buildRoutine from './buildRoutine/buildRoutine.js';
|
|
16
16
|
import validateEndpoint from './validateEndpoint.js';
|
|
17
|
+
import validateStepReferences from './validateStepReferences.js';
|
|
17
18
|
function buildEndpoint({ endpoint, index, context, checkDuplicateEndpointId }) {
|
|
18
19
|
validateEndpoint({
|
|
19
20
|
endpoint,
|
|
@@ -25,6 +26,11 @@ function buildEndpoint({ endpoint, index, context, checkDuplicateEndpointId }) {
|
|
|
25
26
|
endpointId: endpoint.endpointId,
|
|
26
27
|
typeCounters: context.typeCounters
|
|
27
28
|
});
|
|
29
|
+
// Validate that _step references point to defined step IDs
|
|
30
|
+
validateStepReferences({
|
|
31
|
+
endpoint,
|
|
32
|
+
context
|
|
33
|
+
});
|
|
28
34
|
endpoint.id = `endpoint:${endpoint.endpointId}`;
|
|
29
35
|
}
|
|
30
36
|
export default buildEndpoint;
|
|
@@ -13,6 +13,6 @@
|
|
|
13
13
|
See the License for the specific language governing permissions and
|
|
14
14
|
limitations under the License.
|
|
15
15
|
*/ function countStepTypes(step, { typeCounters }) {
|
|
16
|
-
typeCounters.requests.increment(step.type);
|
|
16
|
+
typeCounters.requests.increment(step.type, step['~k']);
|
|
17
17
|
}
|
|
18
18
|
export default countStepTypes;
|
|
@@ -0,0 +1,65 @@
|
|
|
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
|
+
import extractOperatorKey from '../../utils/extractOperatorKey.js';
|
|
17
|
+
import formatConfigWarning from '../../utils/formatConfigWarning.js';
|
|
18
|
+
import traverseConfig from '../../utils/traverseConfig.js';
|
|
19
|
+
// Collect all step IDs from a routine (including nested control structures)
|
|
20
|
+
// Note: After buildRoutine, steps have requestId (original id) and id is modified
|
|
21
|
+
function collectStepIds(routine, stepIds) {
|
|
22
|
+
if (type.isArray(routine)) {
|
|
23
|
+
routine.forEach((item)=>collectStepIds(item, stepIds));
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
if (type.isObject(routine)) {
|
|
27
|
+
// Check if this is a step (has requestId after build, or id before build)
|
|
28
|
+
if (routine.requestId) {
|
|
29
|
+
stepIds.add(routine.requestId);
|
|
30
|
+
}
|
|
31
|
+
// Recurse into all values (handles control structures like :then, :else, :try, :catch)
|
|
32
|
+
Object.values(routine).forEach((value)=>collectStepIds(value, stepIds));
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function validateStepReferences({ endpoint, context }) {
|
|
36
|
+
// Collect all step IDs defined in the routine
|
|
37
|
+
const stepIds = new Set();
|
|
38
|
+
collectStepIds(endpoint.routine, stepIds);
|
|
39
|
+
// Find _step references in the routine
|
|
40
|
+
const stepRefs = new Map(); // topLevelKey -> configKey (first occurrence)
|
|
41
|
+
traverseConfig({
|
|
42
|
+
config: endpoint.routine,
|
|
43
|
+
visitor: (obj)=>{
|
|
44
|
+
if (obj._step !== undefined) {
|
|
45
|
+
const stepId = extractOperatorKey({
|
|
46
|
+
operatorValue: obj._step
|
|
47
|
+
});
|
|
48
|
+
if (stepId && !stepRefs.has(stepId)) {
|
|
49
|
+
stepRefs.set(stepId, obj['~k']);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
// Warn for undefined step references
|
|
55
|
+
stepRefs.forEach((configKey, stepId)=>{
|
|
56
|
+
if (stepIds.has(stepId)) return;
|
|
57
|
+
const message = `_step references "${stepId}" in endpoint "${endpoint.endpointId}", ` + `but no step with id "${stepId}" exists in the routine. ` + `Step IDs are defined by the "id" property of each step. ` + `Check for typos or add a step with this id.`;
|
|
58
|
+
context.logger.warn(formatConfigWarning({
|
|
59
|
+
message,
|
|
60
|
+
configKey,
|
|
61
|
+
context
|
|
62
|
+
}));
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
export default validateStepReferences;
|
|
@@ -13,19 +13,33 @@
|
|
|
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
|
-
|
|
16
|
+
import formatConfigError from '../../utils/formatConfigError.js';
|
|
17
|
+
function buildAuthPlugin({ counter, pluginConfig, typeClass, context }) {
|
|
17
18
|
if (type.isArray(pluginConfig)) {
|
|
18
19
|
pluginConfig.forEach((plugin)=>{
|
|
20
|
+
const configKey = plugin['~k'];
|
|
19
21
|
if (type.isUndefined(plugin.id)) {
|
|
20
|
-
throw new Error(
|
|
22
|
+
throw new Error(formatConfigError({
|
|
23
|
+
message: `Auth ${typeClass} id missing.`,
|
|
24
|
+
configKey,
|
|
25
|
+
context
|
|
26
|
+
}));
|
|
21
27
|
}
|
|
22
28
|
if (!type.isString(plugin.id)) {
|
|
23
|
-
throw new Error(
|
|
29
|
+
throw new Error(formatConfigError({
|
|
30
|
+
message: `Auth ${typeClass} id is not a string. Received ${JSON.stringify(plugin.id)}.`,
|
|
31
|
+
configKey,
|
|
32
|
+
context
|
|
33
|
+
}));
|
|
24
34
|
}
|
|
25
35
|
if (!type.isString(plugin.type)) {
|
|
26
|
-
throw new Error(
|
|
36
|
+
throw new Error(formatConfigError({
|
|
37
|
+
message: `Auth ${typeClass} type is not a string at ${typeClass} "${plugin.id}". Received ${JSON.stringify(plugin.type)}.`,
|
|
38
|
+
configKey,
|
|
39
|
+
context
|
|
40
|
+
}));
|
|
27
41
|
}
|
|
28
|
-
counter.increment(plugin.type);
|
|
42
|
+
counter.increment(plugin.type, plugin['~k']);
|
|
29
43
|
});
|
|
30
44
|
}
|
|
31
45
|
}
|
|
@@ -34,16 +48,29 @@ function buildAdapter({ components, context }) {
|
|
|
34
48
|
if (type.isNone(adapter)) {
|
|
35
49
|
return;
|
|
36
50
|
}
|
|
51
|
+
const configKey = adapter['~k'];
|
|
37
52
|
if (type.isUndefined(adapter.id)) {
|
|
38
|
-
throw new Error(
|
|
53
|
+
throw new Error(formatConfigError({
|
|
54
|
+
message: 'Auth adapter id missing.',
|
|
55
|
+
configKey,
|
|
56
|
+
context
|
|
57
|
+
}));
|
|
39
58
|
}
|
|
40
59
|
if (!type.isString(adapter.id)) {
|
|
41
|
-
throw new Error(
|
|
60
|
+
throw new Error(formatConfigError({
|
|
61
|
+
message: `Auth adapter id is not a string. Received ${JSON.stringify(adapter.id)}.`,
|
|
62
|
+
configKey,
|
|
63
|
+
context
|
|
64
|
+
}));
|
|
42
65
|
}
|
|
43
66
|
if (!type.isString(adapter.type)) {
|
|
44
|
-
throw new Error(
|
|
67
|
+
throw new Error(formatConfigError({
|
|
68
|
+
message: `Auth adapter type is not a string at adapter "${adapter.id}". Received ${JSON.stringify(adapter.type)}.`,
|
|
69
|
+
configKey,
|
|
70
|
+
context
|
|
71
|
+
}));
|
|
45
72
|
}
|
|
46
|
-
context.typeCounters.auth.adapters.increment(adapter.type);
|
|
73
|
+
context.typeCounters.auth.adapters.increment(adapter.type, adapter['~k']);
|
|
47
74
|
}
|
|
48
75
|
function buildAuthPlugins({ components, context }) {
|
|
49
76
|
const counters = context.typeCounters.auth;
|
|
@@ -55,17 +82,20 @@ function buildAuthPlugins({ components, context }) {
|
|
|
55
82
|
buildAuthPlugin({
|
|
56
83
|
counter: counters.callbacks,
|
|
57
84
|
pluginConfig: authConfig.callbacks,
|
|
58
|
-
typeClass: 'callback'
|
|
85
|
+
typeClass: 'callback',
|
|
86
|
+
context
|
|
59
87
|
});
|
|
60
88
|
buildAuthPlugin({
|
|
61
89
|
counter: counters.events,
|
|
62
90
|
pluginConfig: authConfig.events,
|
|
63
|
-
typeClass: 'event'
|
|
91
|
+
typeClass: 'event',
|
|
92
|
+
context
|
|
64
93
|
});
|
|
65
94
|
buildAuthPlugin({
|
|
66
95
|
counter: counters.providers,
|
|
67
96
|
pluginConfig: authConfig.providers,
|
|
68
|
-
typeClass: 'provider'
|
|
97
|
+
typeClass: 'provider',
|
|
98
|
+
context
|
|
69
99
|
});
|
|
70
100
|
}
|
|
71
101
|
export default buildAuthPlugins;
|
|
@@ -15,13 +15,19 @@
|
|
|
15
15
|
*/ import { type } from '@lowdefy/helpers';
|
|
16
16
|
import { validate } from '@lowdefy/ajv';
|
|
17
17
|
import lowdefySchema from '../../lowdefySchema.js';
|
|
18
|
+
import formatConfigError from '../../utils/formatConfigError.js';
|
|
18
19
|
import validateMutualExclusivity from './validateMutualExclusivity.js';
|
|
19
|
-
async function validateAuthConfig({ components }) {
|
|
20
|
+
async function validateAuthConfig({ components, context }) {
|
|
20
21
|
if (type.isNone(components.auth)) {
|
|
21
22
|
components.auth = {};
|
|
22
23
|
}
|
|
23
24
|
if (!type.isObject(components.auth)) {
|
|
24
|
-
|
|
25
|
+
const configKey = components.auth?.['~k'];
|
|
26
|
+
throw new Error(formatConfigError({
|
|
27
|
+
message: 'lowdefy.auth is not an object.',
|
|
28
|
+
configKey,
|
|
29
|
+
context
|
|
30
|
+
}));
|
|
25
31
|
}
|
|
26
32
|
if (type.isNone(components.auth.api)) {
|
|
27
33
|
components.auth.api = {};
|
|
@@ -59,10 +65,12 @@ async function validateAuthConfig({ components }) {
|
|
|
59
65
|
});
|
|
60
66
|
validateMutualExclusivity({
|
|
61
67
|
components,
|
|
68
|
+
context,
|
|
62
69
|
entity: 'api'
|
|
63
70
|
});
|
|
64
71
|
validateMutualExclusivity({
|
|
65
72
|
components,
|
|
73
|
+
context,
|
|
66
74
|
entity: 'pages'
|
|
67
75
|
});
|
|
68
76
|
return components;
|
|
@@ -13,15 +13,29 @@
|
|
|
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
|
-
|
|
16
|
+
import formatConfigError from '../../utils/formatConfigError.js';
|
|
17
|
+
function validateMutualExclusivity({ components, context, entity }) {
|
|
18
|
+
const configKey = components.auth[entity]?.['~k'] || components.auth?.['~k'];
|
|
17
19
|
if (components.auth[entity].protected === true && components.auth[entity].public === true || type.isArray(components.auth[entity].protected) && type.isArray(components.auth[entity].public)) {
|
|
18
|
-
throw new Error(
|
|
20
|
+
throw new Error(formatConfigError({
|
|
21
|
+
message: `Protected and public ${entity} are mutually exclusive. When protected ${entity} are listed, all unlisted ${entity} are public by default and vice versa.`,
|
|
22
|
+
configKey,
|
|
23
|
+
context
|
|
24
|
+
}));
|
|
19
25
|
}
|
|
20
26
|
if (components.auth[entity].protected === false) {
|
|
21
|
-
throw new Error(
|
|
27
|
+
throw new Error(formatConfigError({
|
|
28
|
+
message: `Protected ${entity} can not be set to false.`,
|
|
29
|
+
configKey,
|
|
30
|
+
context
|
|
31
|
+
}));
|
|
22
32
|
}
|
|
23
33
|
if (components.auth[entity].public === false) {
|
|
24
|
-
throw new Error(
|
|
34
|
+
throw new Error(formatConfigError({
|
|
35
|
+
message: `Public ${entity} can not be set to false.`,
|
|
36
|
+
configKey,
|
|
37
|
+
context
|
|
38
|
+
}));
|
|
25
39
|
}
|
|
26
40
|
}
|
|
27
41
|
export default validateMutualExclusivity;
|
|
@@ -13,28 +13,47 @@
|
|
|
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
|
+
import collectConfigError from '../utils/collectConfigError.js';
|
|
16
17
|
import countOperators from '../utils/countOperators.js';
|
|
17
18
|
import createCheckDuplicateId from '../utils/createCheckDuplicateId.js';
|
|
18
19
|
function buildConnections({ components, context }) {
|
|
20
|
+
// Store connection IDs for validation in buildRequests
|
|
21
|
+
context.connectionIds = new Set();
|
|
19
22
|
const checkDuplicateConnectionId = createCheckDuplicateId({
|
|
20
|
-
message: 'Duplicate connectionId "{{ id }}".'
|
|
23
|
+
message: 'Duplicate connectionId "{{ id }}".',
|
|
24
|
+
context
|
|
21
25
|
});
|
|
22
26
|
if (type.isArray(components.connections)) {
|
|
23
27
|
components.connections.forEach((connection)=>{
|
|
28
|
+
const configKey = connection['~k'];
|
|
24
29
|
if (type.isUndefined(connection.id)) {
|
|
25
|
-
|
|
30
|
+
collectConfigError({
|
|
31
|
+
message: 'Connection id missing.',
|
|
32
|
+
configKey,
|
|
33
|
+
context
|
|
34
|
+
});
|
|
26
35
|
}
|
|
27
36
|
if (!type.isString(connection.id)) {
|
|
28
|
-
|
|
37
|
+
collectConfigError({
|
|
38
|
+
message: `Connection id is not a string. Received ${JSON.stringify(connection.id)}.`,
|
|
39
|
+
configKey,
|
|
40
|
+
context
|
|
41
|
+
});
|
|
29
42
|
}
|
|
30
43
|
checkDuplicateConnectionId({
|
|
31
|
-
id: connection.id
|
|
44
|
+
id: connection.id,
|
|
45
|
+
configKey
|
|
32
46
|
});
|
|
33
47
|
if (!type.isString(connection.type)) {
|
|
34
|
-
|
|
48
|
+
collectConfigError({
|
|
49
|
+
message: `Connection type is not a string at connection "${connection.id}". Received ${JSON.stringify(connection.type)}.`,
|
|
50
|
+
configKey,
|
|
51
|
+
context
|
|
52
|
+
});
|
|
35
53
|
}
|
|
36
|
-
context.typeCounters.connections.increment(connection.type);
|
|
54
|
+
context.typeCounters.connections.increment(connection.type, connection['~k']);
|
|
37
55
|
connection.connectionId = connection.id;
|
|
56
|
+
context.connectionIds.add(connection.connectionId);
|
|
38
57
|
connection.id = `connection:${connection.id}`;
|
|
39
58
|
countOperators(connection.properties || {}, {
|
|
40
59
|
counter: context.typeCounters.operators.server
|
|
@@ -12,8 +12,7 @@
|
|
|
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
|
-
*/
|
|
16
|
-
const iconPackages = {
|
|
15
|
+
*/ const iconPackages = {
|
|
17
16
|
'react-icons/ai': /"(Ai[A-Z0-9]\w*)"/gm,
|
|
18
17
|
'react-icons/bi': /"(Bi[A-Z0-9]\w*)"/gm,
|
|
19
18
|
'react-icons/bs': /"(Bs[A-Z0-9]\w*)"/gm,
|
|
@@ -43,40 +42,27 @@ const iconPackages = {
|
|
|
43
42
|
'react-icons/vsc': /"(Vsc[A-Z0-9]\w*)"/gm,
|
|
44
43
|
'react-icons/wi': /"(Wi[A-Z0-9]\w*)"/gm
|
|
45
44
|
};
|
|
46
|
-
function getConfigIcons({ components, icons, regex
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
});
|
|
57
|
-
timeSync('stringify:pages', ()=>{
|
|
58
|
-
[
|
|
59
|
-
...JSON.stringify(components.pages || []).matchAll(regex)
|
|
60
|
-
].map((match)=>icons.add(match[1]));
|
|
61
|
-
});
|
|
45
|
+
function getConfigIcons({ components, icons, regex }) {
|
|
46
|
+
[
|
|
47
|
+
...JSON.stringify(components.global || {}).matchAll(regex)
|
|
48
|
+
].map((match)=>icons.add(match[1]));
|
|
49
|
+
[
|
|
50
|
+
...JSON.stringify(components.menus || []).matchAll(regex)
|
|
51
|
+
].map((match)=>icons.add(match[1]));
|
|
52
|
+
[
|
|
53
|
+
...JSON.stringify(components.pages || []).matchAll(regex)
|
|
54
|
+
].map((match)=>icons.add(match[1]));
|
|
62
55
|
}
|
|
63
|
-
function getBlockDefaultIcons({ blocks, context, icons, regex
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
].map((match)=>icons.add(match[1]));
|
|
70
|
-
});
|
|
56
|
+
function getBlockDefaultIcons({ blocks, context, icons, regex }) {
|
|
57
|
+
blocks.forEach((block)=>{
|
|
58
|
+
(context.typesMap.icons[block.typeName] || []).forEach((icon)=>{
|
|
59
|
+
[
|
|
60
|
+
...JSON.stringify(icon).matchAll(regex)
|
|
61
|
+
].map((match)=>icons.add(match[1]));
|
|
71
62
|
});
|
|
72
63
|
});
|
|
73
64
|
}
|
|
74
65
|
function buildIconImports({ blocks, components, context, defaults = {} }) {
|
|
75
|
-
const profiler = createBuildProfiler({
|
|
76
|
-
logger: context.logger,
|
|
77
|
-
prefix: 'buildIconImports'
|
|
78
|
-
});
|
|
79
|
-
const timeSync = profiler.timeSync;
|
|
80
66
|
const iconImports = [];
|
|
81
67
|
Object.entries(iconPackages).forEach(([iconPackage, regex])=>{
|
|
82
68
|
defaults;
|
|
@@ -84,15 +70,13 @@ function buildIconImports({ blocks, components, context, defaults = {} }) {
|
|
|
84
70
|
getConfigIcons({
|
|
85
71
|
components,
|
|
86
72
|
icons,
|
|
87
|
-
regex
|
|
88
|
-
timeSync
|
|
73
|
+
regex
|
|
89
74
|
});
|
|
90
75
|
getBlockDefaultIcons({
|
|
91
76
|
blocks,
|
|
92
77
|
context,
|
|
93
78
|
icons,
|
|
94
|
-
regex
|
|
95
|
-
timeSync
|
|
79
|
+
regex
|
|
96
80
|
});
|
|
97
81
|
iconImports.push({
|
|
98
82
|
icons: [
|
|
@@ -101,7 +85,6 @@ function buildIconImports({ blocks, components, context, defaults = {} }) {
|
|
|
101
85
|
package: iconPackage
|
|
102
86
|
});
|
|
103
87
|
});
|
|
104
|
-
profiler.printSummary();
|
|
105
88
|
return iconImports;
|
|
106
89
|
}
|
|
107
90
|
export default buildIconImports;
|
|
@@ -0,0 +1,41 @@
|
|
|
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
|
+
const sentryDefaults = {
|
|
17
|
+
client: true,
|
|
18
|
+
server: true,
|
|
19
|
+
tracesSampleRate: 0.1,
|
|
20
|
+
replaysSessionSampleRate: 0,
|
|
21
|
+
replaysOnErrorSampleRate: 0.1,
|
|
22
|
+
feedback: false,
|
|
23
|
+
userFields: [
|
|
24
|
+
'id',
|
|
25
|
+
'_id'
|
|
26
|
+
]
|
|
27
|
+
};
|
|
28
|
+
function buildLogger({ components }) {
|
|
29
|
+
if (type.isNone(components.logger)) {
|
|
30
|
+
components.logger = {};
|
|
31
|
+
}
|
|
32
|
+
// Only apply defaults if sentry is explicitly configured
|
|
33
|
+
if (!type.isNone(components.logger.sentry)) {
|
|
34
|
+
components.logger.sentry = {
|
|
35
|
+
...sentryDefaults,
|
|
36
|
+
...components.logger.sentry
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
return components;
|
|
40
|
+
}
|
|
41
|
+
export default buildLogger;
|
package/dist/build/buildMenu.js
CHANGED
|
@@ -12,8 +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 { type } from '@lowdefy/helpers';
|
|
15
|
+
*/ import { type, resolveConfigLocation } from '@lowdefy/helpers';
|
|
16
16
|
import createCheckDuplicateId from '../utils/createCheckDuplicateId.js';
|
|
17
|
+
import formatConfigError from '../utils/formatConfigError.js';
|
|
17
18
|
function buildDefaultMenu({ components, context }) {
|
|
18
19
|
context.logger.warn('No menus found. Building default menu.');
|
|
19
20
|
const pages = type.isArray(components.pages) ? components.pages : [];
|
|
@@ -30,16 +31,18 @@ function buildDefaultMenu({ components, context }) {
|
|
|
30
31
|
];
|
|
31
32
|
return menus;
|
|
32
33
|
}
|
|
33
|
-
function loopItems({ parent, menuId, pages, missingPageWarnings, checkDuplicateMenuItemId }) {
|
|
34
|
+
function loopItems({ parent, menuId, pages, missingPageWarnings, checkDuplicateMenuItemId, context }) {
|
|
34
35
|
if (type.isArray(parent.links)) {
|
|
35
36
|
parent.links.forEach((menuItem)=>{
|
|
37
|
+
const configKey = menuItem['~k'];
|
|
36
38
|
if (menuItem.type === 'MenuLink') {
|
|
37
39
|
if (type.isString(menuItem.pageId)) {
|
|
38
40
|
const page = pages.find((pg)=>pg.pageId === menuItem.pageId);
|
|
39
41
|
if (!page) {
|
|
40
42
|
missingPageWarnings.push({
|
|
41
43
|
menuItemId: menuItem.id,
|
|
42
|
-
pageId: menuItem.pageId
|
|
44
|
+
pageId: menuItem.pageId,
|
|
45
|
+
configKey
|
|
43
46
|
});
|
|
44
47
|
// remove menuItem from menu
|
|
45
48
|
menuItem.remove = true;
|
|
@@ -60,7 +63,8 @@ function loopItems({ parent, menuId, pages, missingPageWarnings, checkDuplicateM
|
|
|
60
63
|
}
|
|
61
64
|
checkDuplicateMenuItemId({
|
|
62
65
|
id: menuItem.id,
|
|
63
|
-
menuId
|
|
66
|
+
menuId,
|
|
67
|
+
configKey
|
|
64
68
|
});
|
|
65
69
|
menuItem.menuItemId = menuItem.id;
|
|
66
70
|
menuItem.id = `menuitem:${menuId}:${menuItem.id}`;
|
|
@@ -69,7 +73,8 @@ function loopItems({ parent, menuId, pages, missingPageWarnings, checkDuplicateM
|
|
|
69
73
|
menuId,
|
|
70
74
|
pages,
|
|
71
75
|
missingPageWarnings,
|
|
72
|
-
checkDuplicateMenuItemId
|
|
76
|
+
checkDuplicateMenuItemId,
|
|
77
|
+
context
|
|
73
78
|
});
|
|
74
79
|
});
|
|
75
80
|
parent.links = parent.links.filter((item)=>item.remove !== true);
|
|
@@ -85,33 +90,55 @@ function buildMenu({ components, context }) {
|
|
|
85
90
|
}
|
|
86
91
|
const missingPageWarnings = [];
|
|
87
92
|
const checkDuplicateMenuId = createCheckDuplicateId({
|
|
88
|
-
message: 'Duplicate menuId "{{ id }}".'
|
|
93
|
+
message: 'Duplicate menuId "{{ id }}".',
|
|
94
|
+
context
|
|
89
95
|
});
|
|
90
96
|
components.menus.forEach((menu)=>{
|
|
97
|
+
const configKey = menu['~k'];
|
|
91
98
|
if (type.isUndefined(menu.id)) {
|
|
92
|
-
throw new Error(
|
|
99
|
+
throw new Error(formatConfigError({
|
|
100
|
+
message: 'Menu id missing.',
|
|
101
|
+
configKey,
|
|
102
|
+
context
|
|
103
|
+
}));
|
|
93
104
|
}
|
|
94
105
|
if (!type.isString(menu.id)) {
|
|
95
|
-
throw new Error(
|
|
106
|
+
throw new Error(formatConfigError({
|
|
107
|
+
message: `Menu id is not a string. Received ${JSON.stringify(menu.id)}.`,
|
|
108
|
+
configKey,
|
|
109
|
+
context
|
|
110
|
+
}));
|
|
96
111
|
}
|
|
97
112
|
checkDuplicateMenuId({
|
|
98
|
-
id: menu.id
|
|
113
|
+
id: menu.id,
|
|
114
|
+
configKey
|
|
99
115
|
});
|
|
100
116
|
menu.menuId = menu.id;
|
|
101
117
|
menu.id = `menu:${menu.id}`;
|
|
102
118
|
const checkDuplicateMenuItemId = createCheckDuplicateId({
|
|
103
|
-
message: 'Duplicate menuItemId "{{ id }}" on menu "{{ menuId }}".'
|
|
119
|
+
message: 'Duplicate menuItemId "{{ id }}" on menu "{{ menuId }}".',
|
|
120
|
+
context
|
|
104
121
|
});
|
|
105
122
|
loopItems({
|
|
106
123
|
parent: menu,
|
|
107
124
|
menuId: menu.menuId,
|
|
108
125
|
pages,
|
|
109
126
|
missingPageWarnings,
|
|
110
|
-
checkDuplicateMenuItemId
|
|
127
|
+
checkDuplicateMenuItemId,
|
|
128
|
+
context
|
|
111
129
|
});
|
|
112
130
|
});
|
|
113
|
-
missingPageWarnings.
|
|
114
|
-
|
|
131
|
+
missingPageWarnings.forEach((warning)=>{
|
|
132
|
+
const location = resolveConfigLocation({
|
|
133
|
+
configKey: warning.configKey,
|
|
134
|
+
keyMap: context.keyMap,
|
|
135
|
+
refMap: context.refMap,
|
|
136
|
+
configDirectory: context.directories.config
|
|
137
|
+
});
|
|
138
|
+
const source = location?.source ? `${location.source} at ${location.config}` : '';
|
|
139
|
+
const link = location?.link || '';
|
|
140
|
+
const message = `Page "${warning.pageId}" referenced in menu link "${warning.menuItemId}" not found.`;
|
|
141
|
+
context.logger.warn(`[Config Error] ${message}\n ${source}\n ${link}`);
|
|
115
142
|
});
|
|
116
143
|
return components;
|
|
117
144
|
}
|