@lowdefy/build 4.5.1 → 4.6.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/dist/build/addDefaultPages/404.js +1 -1
- package/dist/build/addDefaultPages/addDefaultPages.js +10 -4
- package/dist/build/addKeys.js +85 -29
- package/dist/build/buildApi/buildApi.js +27 -8
- package/dist/build/buildApi/buildEndpoint.js +7 -1
- package/dist/build/buildApi/buildRoutine/buildControl.js +1 -1
- package/dist/build/buildApi/buildRoutine/buildRoutine.js +1 -1
- package/dist/build/buildApi/buildRoutine/buildStep.js +1 -1
- package/dist/build/buildApi/buildRoutine/controlTypes.js +34 -11
- package/dist/build/buildApi/buildRoutine/countControl.js +1 -1
- package/dist/build/buildApi/buildRoutine/countStepTypes.js +2 -2
- package/dist/build/buildApi/buildRoutine/setStepId.js +1 -1
- package/dist/build/buildApi/buildRoutine/validateStep.js +30 -9
- package/dist/build/buildApi/validateEndpoint.js +36 -7
- package/dist/build/buildApi/validateStepReferences.js +65 -0
- package/dist/build/buildApp.js +1 -1
- package/dist/build/buildAuth/buildApiAuth.js +7 -3
- package/dist/build/buildAuth/buildAuth.js +7 -4
- package/dist/build/buildAuth/buildAuthPlugins.js +42 -13
- package/dist/build/buildAuth/buildPageAuth.js +14 -3
- package/dist/build/buildAuth/getApiRoles.js +1 -1
- package/dist/build/buildAuth/getPageRoles.js +1 -1
- package/dist/build/buildAuth/getProtectedApi.js +1 -1
- package/dist/build/buildAuth/getProtectedPages.js +1 -1
- package/dist/build/buildAuth/validateAuthConfig.js +39 -5
- package/dist/build/buildAuth/validateMutualExclusivity.js +13 -5
- package/dist/build/buildConnections.js +23 -24
- package/dist/build/buildImports/buildIconImports.js +1 -1
- package/dist/build/buildImports/buildImports.js +1 -1
- package/dist/build/buildImports/buildImportsDev.js +1 -1
- package/dist/build/buildImports/buildImportsProd.js +1 -1
- package/dist/build/buildImports/buildStyleImports.js +1 -1
- package/dist/build/buildImports/defaultIconsDev.js +1 -1
- package/dist/build/buildImports/defaultIconsProd.js +1 -1
- package/dist/build/buildJs/generateJsFile.js +1 -1
- package/dist/build/buildJs/jsMapParser.js +1 -1
- package/dist/build/buildJs/writeJs.js +1 -1
- package/dist/build/buildLogger.js +41 -0
- package/dist/build/buildMenu.js +36 -12
- package/dist/build/buildPages/buildBlock/buildBlock.js +1 -1
- package/dist/build/buildPages/buildBlock/buildEvents.js +79 -9
- package/dist/build/buildPages/buildBlock/buildRequests.js +38 -8
- package/dist/build/buildPages/buildBlock/buildSubBlocks.js +6 -2
- package/dist/build/buildPages/buildBlock/countBlockOperators.js +1 -1
- package/dist/build/buildPages/buildBlock/countBlockTypes.js +2 -2
- package/dist/build/buildPages/buildBlock/moveSkeletonBlocksToArea.js +6 -2
- package/dist/build/buildPages/buildBlock/moveSubBlocksToArea.js +6 -2
- package/dist/build/buildPages/buildBlock/setBlockId.js +1 -1
- package/dist/build/buildPages/buildBlock/validateBlock.js +25 -7
- package/dist/build/buildPages/buildPage.js +35 -6
- package/dist/build/buildPages/validateLinkReferences.js +33 -0
- package/dist/build/buildPages/validatePayloadReferences.js +59 -0
- package/dist/build/buildPages/validateRequestReferences.js +33 -0
- package/dist/build/buildPages/validateServerStateReferences.js +41 -0
- package/dist/build/buildPages/validateStateReferences.js +79 -0
- package/dist/build/buildRefs/buildRefs.js +20 -3
- package/dist/build/buildRefs/createRefReviver.js +28 -0
- package/dist/build/buildRefs/evaluateBuildOperators.js +26 -7
- package/dist/build/buildRefs/evaluateStaticOperators.js +56 -0
- package/dist/build/buildRefs/getConfigFile.js +25 -6
- package/dist/build/buildRefs/getKey.js +1 -1
- package/dist/build/buildRefs/getRefContent.js +1 -1
- package/dist/build/buildRefs/getRefPath.js +1 -1
- package/dist/build/buildRefs/getRefsFromFile.js +9 -4
- package/dist/build/buildRefs/getUserJavascriptFunction.js +18 -4
- package/dist/build/buildRefs/makeRefDefinition.js +10 -5
- package/dist/build/buildRefs/parseNunjucks.js +1 -1
- package/dist/build/buildRefs/parseRefContent.js +100 -6
- package/dist/build/buildRefs/populateRefs.js +75 -13
- package/dist/build/buildRefs/recursiveBuild.js +66 -18
- package/dist/build/buildRefs/runRefResolver.js +11 -3
- package/dist/build/buildRefs/runTransformer.js +7 -3
- package/dist/build/buildTypes.js +22 -7
- package/dist/build/cleanBuildDirectory.js +1 -1
- package/dist/build/collectDynamicIdentifiers.js +35 -0
- package/dist/build/collectTypeNames.js +36 -0
- package/dist/build/copyPublicFolder.js +1 -1
- package/dist/build/{buildJs → full}/buildJs.js +3 -3
- package/dist/build/full/buildPages.js +87 -0
- package/dist/build/{buildPages → full}/buildTestPage.js +15 -3
- package/dist/build/{updateServerPackageJson.js → full/updateServerPackageJson.js} +1 -1
- package/dist/build/{writePages.js → full/writePages.js} +1 -1
- package/dist/build/{writeRequests.js → full/writeRequests.js} +11 -3
- package/dist/build/{writeTypes.js → full/writeTypes.js} +1 -1
- package/dist/build/jit/addInstalledTypes.js +51 -0
- package/dist/build/jit/buildJsShallow.js +41 -0
- package/dist/build/jit/buildPageJit.js +252 -0
- package/dist/build/jit/buildShallowPages.js +90 -0
- package/dist/build/jit/createPageRegistry.js +80 -0
- package/dist/build/jit/detectMissingPluginPackages.js +62 -0
- package/dist/build/jit/getRefPositions.js +38 -0
- package/dist/build/jit/isPageContentPath.js +24 -0
- package/dist/build/jit/pageContentKeys.js +26 -0
- package/dist/build/jit/shallowBuild.js +245 -0
- package/dist/build/jit/stripPageContent.js +23 -0
- package/dist/build/jit/updateServerPackageJsonJit.js +33 -0
- package/dist/build/jit/validatePageTypes.js +73 -0
- package/dist/build/jit/writePageJit.js +44 -0
- package/dist/build/jit/writePageRegistry.js +23 -0
- package/dist/build/jit/writeSourcelessPages.js +23 -0
- package/dist/build/testSchema.js +45 -7
- package/dist/build/validateConfig.js +2 -2
- package/dist/build/validateOperatorsDynamic.js +28 -0
- package/dist/build/writeApi.js +1 -1
- package/dist/build/writeApp.js +1 -1
- package/dist/build/writeAuth.js +1 -1
- package/dist/build/writeConfig.js +1 -1
- package/dist/build/writeConnections.js +1 -1
- package/dist/build/writeGlobal.js +1 -1
- package/dist/build/writeLogger.js +19 -0
- package/dist/build/writeMaps.js +1 -1
- package/dist/build/writeMenus.js +1 -1
- package/dist/build/writePluginImports/generateImportFile.js +1 -1
- package/dist/build/writePluginImports/writeActionImports.js +1 -1
- package/dist/build/writePluginImports/writeActionSchemaMap.js +42 -0
- package/dist/build/writePluginImports/writeAuthImports.js +1 -1
- package/dist/build/writePluginImports/writeBlockImports.js +1 -1
- package/dist/build/writePluginImports/writeBlockSchemaMap.js +42 -0
- package/dist/build/writePluginImports/writeConnectionImports.js +1 -1
- package/dist/build/writePluginImports/writeIconImports.js +1 -1
- package/dist/build/writePluginImports/writeOperatorImports.js +1 -1
- package/dist/build/writePluginImports/writeOperatorSchemaMap.js +49 -0
- package/dist/build/writePluginImports/writePluginImports.js +16 -1
- package/dist/build/writePluginImports/writeStyleImports.js +1 -1
- package/dist/createContext.js +16 -4
- package/dist/defaultTypesMap.js +477 -455
- package/dist/index.js +188 -127
- package/dist/indexDev.js +18 -0
- package/dist/lowdefySchema.js +589 -0
- package/dist/scripts/generateDefaultTypes.js +2 -1
- package/dist/scripts/run.js +1 -1
- package/dist/{test → test-utils}/buildRefs/testBuildRefsAsyncFunction.js +1 -1
- package/dist/{test → test-utils}/buildRefs/testBuildRefsErrorResolver.js +1 -1
- package/dist/{test → test-utils}/buildRefs/testBuildRefsNullResolver.js +1 -1
- package/dist/{test → test-utils}/buildRefs/testBuildRefsParsingResolver.js +1 -1
- package/dist/{test → test-utils}/buildRefs/testBuildRefsResolver.js +1 -1
- package/dist/{test → test-utils}/buildRefs/testBuildRefsTransform.js +1 -1
- package/dist/{test → test-utils}/buildRefs/testBuildRefsTransformIdentity.js +1 -1
- package/dist/test-utils/buildRefs/testJitPageResolver.js +24 -0
- package/dist/test-utils/createTestLogger.js +36 -0
- package/dist/test-utils/parseTestYaml.js +126 -0
- package/dist/test-utils/runBuild.js +228 -0
- package/dist/test-utils/runBuildForSnapshots.js +704 -0
- package/dist/{test → test-utils}/testContext.js +12 -2
- package/dist/utils/collectExceptions.js +34 -0
- package/dist/utils/countOperators.js +31 -12
- package/dist/utils/createBuildHandleError.js +38 -0
- package/dist/utils/createCheckDuplicateId.js +15 -9
- package/dist/utils/createCounter.js +16 -3
- package/dist/utils/createHandleWarning.js +41 -0
- package/dist/utils/createPluginTypesMap.js +1 -1
- package/dist/utils/extractOperatorKey.js +36 -0
- package/dist/utils/findConfigKey.js +37 -0
- package/dist/utils/findSimilarString.js +53 -0
- package/dist/utils/logCollectedErrors.js +30 -0
- package/dist/utils/makeId.js +13 -8
- package/dist/utils/preserveMetaProperties.js +27 -0
- package/dist/utils/readConfigFile.js +1 -1
- package/dist/utils/setNonEnumerableProperty.js +23 -0
- package/dist/utils/traverseConfig.js +43 -0
- package/dist/utils/tryBuildStep.js +46 -0
- package/dist/utils/writeBuildArtifact.js +1 -1
- package/package.json +46 -41
- package/dist/build/buildPages/buildPages.js +0 -31
- package/dist/utils/formatErrorMessage.js +0 -56
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* eslint-disable no-param-reassign */ /*
|
|
2
|
-
Copyright 2020-
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
3
|
|
|
4
4
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
5
|
you may not use this file except in compliance with the License.
|
|
@@ -13,9 +13,10 @@
|
|
|
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 { ConfigError } from '@lowdefy/errors';
|
|
16
17
|
import getApiRoles from './getApiRoles.js';
|
|
17
18
|
import getProtectedApi from './getProtectedApi.js';
|
|
18
|
-
function buildApiAuth({ components }) {
|
|
19
|
+
function buildApiAuth({ components, context }) {
|
|
19
20
|
const protectedApiEndpoints = getProtectedApi({
|
|
20
21
|
components
|
|
21
22
|
});
|
|
@@ -29,7 +30,10 @@ function buildApiAuth({ components }) {
|
|
|
29
30
|
(components.api || []).forEach((endpoint)=>{
|
|
30
31
|
if (apiRoles[endpoint.id]) {
|
|
31
32
|
if (configPublicApi.includes(endpoint.id)) {
|
|
32
|
-
throw new
|
|
33
|
+
throw new ConfigError(`Endpoint "${endpoint.id}" is both protected by roles and public.`, {
|
|
34
|
+
received: apiRoles[endpoint.id],
|
|
35
|
+
configKey: endpoint['~k']
|
|
36
|
+
});
|
|
33
37
|
}
|
|
34
38
|
endpoint.auth = {
|
|
35
39
|
public: false,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* eslint-disable no-param-reassign */ /*
|
|
2
|
-
Copyright 2020-
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
3
|
|
|
4
4
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
5
|
you may not use this file except in compliance with the License.
|
|
@@ -20,14 +20,17 @@ import validateAuthConfig from './validateAuthConfig.js';
|
|
|
20
20
|
function buildAuth({ components, context }) {
|
|
21
21
|
const configured = !type.isNone(components.auth);
|
|
22
22
|
validateAuthConfig({
|
|
23
|
-
components
|
|
23
|
+
components,
|
|
24
|
+
context
|
|
24
25
|
});
|
|
25
26
|
components.auth.configured = configured;
|
|
26
27
|
buildApiAuth({
|
|
27
|
-
components
|
|
28
|
+
components,
|
|
29
|
+
context
|
|
28
30
|
});
|
|
29
31
|
buildPageAuth({
|
|
30
|
-
components
|
|
32
|
+
components,
|
|
33
|
+
context
|
|
31
34
|
});
|
|
32
35
|
buildAuthPlugins({
|
|
33
36
|
components,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*
|
|
2
|
-
Copyright 2020-
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
3
|
|
|
4
4
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
5
|
you may not use this file except in compliance with the License.
|
|
@@ -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 { ConfigError } from '@lowdefy/errors';
|
|
17
|
+
import collectExceptions from '../../utils/collectExceptions.js';
|
|
18
|
+
function buildAuthPlugin({ counter, pluginConfig, typeClass, context }) {
|
|
17
19
|
if (type.isArray(pluginConfig)) {
|
|
18
20
|
pluginConfig.forEach((plugin)=>{
|
|
21
|
+
const configKey = plugin['~k'];
|
|
19
22
|
if (type.isUndefined(plugin.id)) {
|
|
20
|
-
|
|
23
|
+
collectExceptions(context, new ConfigError(`Auth ${typeClass} id missing.`, {
|
|
24
|
+
configKey
|
|
25
|
+
}));
|
|
26
|
+
return;
|
|
21
27
|
}
|
|
22
28
|
if (!type.isString(plugin.id)) {
|
|
23
|
-
|
|
29
|
+
collectExceptions(context, new ConfigError(`Auth ${typeClass} id is not a string.`, {
|
|
30
|
+
received: plugin.id,
|
|
31
|
+
configKey
|
|
32
|
+
}));
|
|
33
|
+
return;
|
|
24
34
|
}
|
|
25
35
|
if (!type.isString(plugin.type)) {
|
|
26
|
-
|
|
36
|
+
collectExceptions(context, new ConfigError(`Auth ${typeClass} type is not a string at ${typeClass} "${plugin.id}".`, {
|
|
37
|
+
received: plugin.type,
|
|
38
|
+
configKey
|
|
39
|
+
}));
|
|
40
|
+
return;
|
|
27
41
|
}
|
|
28
|
-
counter.increment(plugin.type);
|
|
42
|
+
counter.increment(plugin.type, plugin['~k']);
|
|
29
43
|
});
|
|
30
44
|
}
|
|
31
45
|
}
|
|
@@ -34,16 +48,28 @@ 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
|
-
|
|
53
|
+
collectExceptions(context, new ConfigError('Auth adapter id missing.', {
|
|
54
|
+
configKey
|
|
55
|
+
}));
|
|
56
|
+
return;
|
|
39
57
|
}
|
|
40
58
|
if (!type.isString(adapter.id)) {
|
|
41
|
-
|
|
59
|
+
collectExceptions(context, new ConfigError('Auth adapter id is not a string.', {
|
|
60
|
+
received: adapter.id,
|
|
61
|
+
configKey
|
|
62
|
+
}));
|
|
63
|
+
return;
|
|
42
64
|
}
|
|
43
65
|
if (!type.isString(adapter.type)) {
|
|
44
|
-
|
|
66
|
+
collectExceptions(context, new ConfigError(`Auth adapter type is not a string at adapter "${adapter.id}".`, {
|
|
67
|
+
received: adapter.type,
|
|
68
|
+
configKey
|
|
69
|
+
}));
|
|
70
|
+
return;
|
|
45
71
|
}
|
|
46
|
-
context.typeCounters.auth.adapters.increment(adapter.type);
|
|
72
|
+
context.typeCounters.auth.adapters.increment(adapter.type, adapter['~k']);
|
|
47
73
|
}
|
|
48
74
|
function buildAuthPlugins({ components, context }) {
|
|
49
75
|
const counters = context.typeCounters.auth;
|
|
@@ -55,17 +81,20 @@ function buildAuthPlugins({ components, context }) {
|
|
|
55
81
|
buildAuthPlugin({
|
|
56
82
|
counter: counters.callbacks,
|
|
57
83
|
pluginConfig: authConfig.callbacks,
|
|
58
|
-
typeClass: 'callback'
|
|
84
|
+
typeClass: 'callback',
|
|
85
|
+
context
|
|
59
86
|
});
|
|
60
87
|
buildAuthPlugin({
|
|
61
88
|
counter: counters.events,
|
|
62
89
|
pluginConfig: authConfig.events,
|
|
63
|
-
typeClass: 'event'
|
|
90
|
+
typeClass: 'event',
|
|
91
|
+
context
|
|
64
92
|
});
|
|
65
93
|
buildAuthPlugin({
|
|
66
94
|
counter: counters.providers,
|
|
67
95
|
pluginConfig: authConfig.providers,
|
|
68
|
-
typeClass: 'provider'
|
|
96
|
+
typeClass: 'provider',
|
|
97
|
+
context
|
|
69
98
|
});
|
|
70
99
|
}
|
|
71
100
|
export default buildAuthPlugins;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* eslint-disable no-param-reassign */ /*
|
|
2
|
-
Copyright 2020-
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
3
|
|
|
4
4
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
5
|
you may not use this file except in compliance with the License.
|
|
@@ -13,9 +13,10 @@
|
|
|
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 { ConfigError } from '@lowdefy/errors';
|
|
16
17
|
import getPageRoles from './getPageRoles.js';
|
|
17
18
|
import getProtectedPages from './getProtectedPages.js';
|
|
18
|
-
function buildPageAuth({ components }) {
|
|
19
|
+
function buildPageAuth({ components, context }) {
|
|
19
20
|
const protectedPages = getProtectedPages({
|
|
20
21
|
components
|
|
21
22
|
});
|
|
@@ -27,9 +28,19 @@ function buildPageAuth({ components }) {
|
|
|
27
28
|
configPublicPages = components.auth.pages.public;
|
|
28
29
|
}
|
|
29
30
|
(components.pages || []).forEach((page)=>{
|
|
31
|
+
// The 404 page must always be public so unauthenticated users can see it.
|
|
32
|
+
if (page.id === '404') {
|
|
33
|
+
page.auth = {
|
|
34
|
+
public: true
|
|
35
|
+
};
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
30
38
|
if (pageRoles[page.id]) {
|
|
31
39
|
if (configPublicPages.includes(page.id)) {
|
|
32
|
-
throw new
|
|
40
|
+
throw new ConfigError(`Page "${page.id}" is both protected by roles and public.`, {
|
|
41
|
+
received: pageRoles[page.id],
|
|
42
|
+
configKey: page['~k']
|
|
43
|
+
});
|
|
33
44
|
}
|
|
34
45
|
page.auth = {
|
|
35
46
|
public: false,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* eslint-disable no-param-reassign */ /*
|
|
2
|
-
Copyright 2020-
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
3
|
|
|
4
4
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
5
|
you may not use this file except in compliance with the License.
|
|
@@ -14,14 +14,17 @@
|
|
|
14
14
|
limitations under the License.
|
|
15
15
|
*/ import { type } from '@lowdefy/helpers';
|
|
16
16
|
import { validate } from '@lowdefy/ajv';
|
|
17
|
+
import { ConfigError } from '@lowdefy/errors';
|
|
17
18
|
import lowdefySchema from '../../lowdefySchema.js';
|
|
18
19
|
import validateMutualExclusivity from './validateMutualExclusivity.js';
|
|
19
|
-
|
|
20
|
+
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
|
-
throw new
|
|
25
|
+
throw new ConfigError('lowdefy.auth is not an object.', {
|
|
26
|
+
configKey: components['~k']
|
|
27
|
+
});
|
|
25
28
|
}
|
|
26
29
|
if (type.isNone(components.auth.api)) {
|
|
27
30
|
components.auth.api = {};
|
|
@@ -53,18 +56,49 @@ async function validateAuthConfig({ components }) {
|
|
|
53
56
|
if (type.isNone(components.auth.theme)) {
|
|
54
57
|
components.auth.theme = {};
|
|
55
58
|
}
|
|
56
|
-
validate({
|
|
59
|
+
const { valid, errors } = validate({
|
|
57
60
|
schema: lowdefySchema.definitions.authConfig,
|
|
58
|
-
data: components.auth
|
|
61
|
+
data: components.auth,
|
|
62
|
+
returnErrors: true
|
|
59
63
|
});
|
|
64
|
+
if (!valid) {
|
|
65
|
+
errors.forEach((error)=>{
|
|
66
|
+
// Try to get configKey from the item in the error path
|
|
67
|
+
const instancePath = error.instancePath.split('/').filter(Boolean);
|
|
68
|
+
let configKey = components.auth['~k'];
|
|
69
|
+
let currentData = components.auth;
|
|
70
|
+
for (const part of instancePath){
|
|
71
|
+
if (type.isArray(currentData)) {
|
|
72
|
+
const index = parseInt(part, 10);
|
|
73
|
+
currentData = currentData[index];
|
|
74
|
+
} else {
|
|
75
|
+
currentData = currentData?.[part];
|
|
76
|
+
}
|
|
77
|
+
if (currentData?.['~k']) {
|
|
78
|
+
configKey = currentData['~k'];
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
throw new ConfigError(`Auth ${error.message}.`, {
|
|
82
|
+
configKey
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
}
|
|
60
86
|
validateMutualExclusivity({
|
|
61
87
|
components,
|
|
88
|
+
context,
|
|
62
89
|
entity: 'api'
|
|
63
90
|
});
|
|
64
91
|
validateMutualExclusivity({
|
|
65
92
|
components,
|
|
93
|
+
context,
|
|
66
94
|
entity: 'pages'
|
|
67
95
|
});
|
|
96
|
+
// Validate NEXTAUTH_SECRET is set when auth providers are configured
|
|
97
|
+
if (components.auth.providers.length > 0 && type.isNone(process.env.NEXTAUTH_SECRET)) {
|
|
98
|
+
throw new ConfigError('Auth providers are configured but NEXTAUTH_SECRET environment variable is not set. ' + 'Set NEXTAUTH_SECRET to a secure random string (e.g., generate with `openssl rand -base64 32`).', {
|
|
99
|
+
configKey: components.auth.providers['~k'] ?? components.auth['~k']
|
|
100
|
+
});
|
|
101
|
+
}
|
|
68
102
|
return components;
|
|
69
103
|
}
|
|
70
104
|
export default validateAuthConfig;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* eslint-disable no-param-reassign */ /*
|
|
2
|
-
Copyright 2020-
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
3
|
|
|
4
4
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
5
|
you may not use this file except in compliance with the License.
|
|
@@ -13,15 +13,23 @@
|
|
|
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 { ConfigError } from '@lowdefy/errors';
|
|
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
|
|
20
|
+
throw new ConfigError(`Protected and public ${entity} are mutually exclusive. When protected ${entity} are listed, all unlisted ${entity} are public by default and vice versa.`, {
|
|
21
|
+
configKey
|
|
22
|
+
});
|
|
19
23
|
}
|
|
20
24
|
if (components.auth[entity].protected === false) {
|
|
21
|
-
throw new
|
|
25
|
+
throw new ConfigError(`Protected ${entity} can not be set to false.`, {
|
|
26
|
+
configKey
|
|
27
|
+
});
|
|
22
28
|
}
|
|
23
29
|
if (components.auth[entity].public === false) {
|
|
24
|
-
throw new
|
|
30
|
+
throw new ConfigError(`Public ${entity} can not be set to false.`, {
|
|
31
|
+
configKey
|
|
32
|
+
});
|
|
25
33
|
}
|
|
26
34
|
}
|
|
27
35
|
export default validateMutualExclusivity;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* eslint-disable no-param-reassign */ /*
|
|
2
|
-
Copyright 2020-
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
3
|
|
|
4
4
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
5
|
you may not use this file except in compliance with the License.
|
|
@@ -12,35 +12,34 @@
|
|
|
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 countOperators from '../utils/countOperators.js';
|
|
15
|
+
*/ import countOperators from '../utils/countOperators.js';
|
|
17
16
|
import createCheckDuplicateId from '../utils/createCheckDuplicateId.js';
|
|
18
17
|
function buildConnections({ components, context }) {
|
|
18
|
+
// Store connection IDs for validation in buildRequests
|
|
19
|
+
context.connectionIds = new Set();
|
|
20
|
+
// Schema validates: id required, id is string, type is string
|
|
21
|
+
// Only check for duplicates here (schema can't do that)
|
|
19
22
|
const checkDuplicateConnectionId = createCheckDuplicateId({
|
|
20
23
|
message: 'Duplicate connectionId "{{ id }}".'
|
|
21
24
|
});
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
throw new Error(`Connection id is not a string. Received ${JSON.stringify(connection.id)}.`);
|
|
29
|
-
}
|
|
30
|
-
checkDuplicateConnectionId({
|
|
31
|
-
id: connection.id
|
|
32
|
-
});
|
|
33
|
-
if (!type.isString(connection.type)) {
|
|
34
|
-
throw new Error(`Connection type is not a string at connection "${connection.id}". Received ${JSON.stringify(connection.type)}.`);
|
|
35
|
-
}
|
|
36
|
-
context.typeCounters.connections.increment(connection.type);
|
|
37
|
-
connection.connectionId = connection.id;
|
|
38
|
-
connection.id = `connection:${connection.id}`;
|
|
39
|
-
countOperators(connection.properties || {}, {
|
|
40
|
-
counter: context.typeCounters.operators.server
|
|
41
|
-
});
|
|
25
|
+
(components.connections ?? []).forEach((connection)=>{
|
|
26
|
+
const configKey = connection['~k'];
|
|
27
|
+
// Check duplicates (schema can't validate this)
|
|
28
|
+
checkDuplicateConnectionId({
|
|
29
|
+
id: connection.id,
|
|
30
|
+
configKey
|
|
42
31
|
});
|
|
43
|
-
|
|
32
|
+
// Track type usage for buildTypes validation
|
|
33
|
+
context.typeCounters.connections.increment(connection.type, configKey);
|
|
34
|
+
// Store connectionId for request validation and rename id
|
|
35
|
+
connection.connectionId = connection.id;
|
|
36
|
+
context.connectionIds.add(connection.connectionId);
|
|
37
|
+
connection.id = `connection:${connection.id}`;
|
|
38
|
+
// Count operators in connection properties
|
|
39
|
+
countOperators(connection.properties ?? {}, {
|
|
40
|
+
counter: context.typeCounters.operators.server
|
|
41
|
+
});
|
|
42
|
+
});
|
|
44
43
|
return components;
|
|
45
44
|
}
|
|
46
45
|
export default buildConnections;
|
|
@@ -0,0 +1,41 @@
|
|
|
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
|
+
*/ 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
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* eslint-disable no-param-reassign */ /*
|
|
2
|
-
Copyright 2020-
|
|
2
|
+
Copyright 2020-2026 Lowdefy, Inc
|
|
3
3
|
|
|
4
4
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
5
|
you may not use this file except in compliance with the License.
|
|
@@ -13,6 +13,8 @@
|
|
|
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 { ConfigError, ConfigWarning } from '@lowdefy/errors';
|
|
17
|
+
import collectExceptions from '../utils/collectExceptions.js';
|
|
16
18
|
import createCheckDuplicateId from '../utils/createCheckDuplicateId.js';
|
|
17
19
|
function buildDefaultMenu({ components, context }) {
|
|
18
20
|
context.logger.warn('No menus found. Building default menu.');
|
|
@@ -30,16 +32,18 @@ function buildDefaultMenu({ components, context }) {
|
|
|
30
32
|
];
|
|
31
33
|
return menus;
|
|
32
34
|
}
|
|
33
|
-
function loopItems({ parent, menuId, pages, missingPageWarnings, checkDuplicateMenuItemId }) {
|
|
35
|
+
function loopItems({ parent, menuId, pages, missingPageWarnings, checkDuplicateMenuItemId, context }) {
|
|
34
36
|
if (type.isArray(parent.links)) {
|
|
35
37
|
parent.links.forEach((menuItem)=>{
|
|
38
|
+
const configKey = menuItem['~k'];
|
|
36
39
|
if (menuItem.type === 'MenuLink') {
|
|
37
40
|
if (type.isString(menuItem.pageId)) {
|
|
38
41
|
const page = pages.find((pg)=>pg.pageId === menuItem.pageId);
|
|
39
42
|
if (!page) {
|
|
40
43
|
missingPageWarnings.push({
|
|
41
44
|
menuItemId: menuItem.id,
|
|
42
|
-
pageId: menuItem.pageId
|
|
45
|
+
pageId: menuItem.pageId,
|
|
46
|
+
configKey
|
|
43
47
|
});
|
|
44
48
|
// remove menuItem from menu
|
|
45
49
|
menuItem.remove = true;
|
|
@@ -60,7 +64,8 @@ function loopItems({ parent, menuId, pages, missingPageWarnings, checkDuplicateM
|
|
|
60
64
|
}
|
|
61
65
|
checkDuplicateMenuItemId({
|
|
62
66
|
id: menuItem.id,
|
|
63
|
-
menuId
|
|
67
|
+
menuId,
|
|
68
|
+
configKey
|
|
64
69
|
});
|
|
65
70
|
menuItem.menuItemId = menuItem.id;
|
|
66
71
|
menuItem.id = `menuitem:${menuId}:${menuItem.id}`;
|
|
@@ -69,7 +74,8 @@ function loopItems({ parent, menuId, pages, missingPageWarnings, checkDuplicateM
|
|
|
69
74
|
menuId,
|
|
70
75
|
pages,
|
|
71
76
|
missingPageWarnings,
|
|
72
|
-
checkDuplicateMenuItemId
|
|
77
|
+
checkDuplicateMenuItemId,
|
|
78
|
+
context
|
|
73
79
|
});
|
|
74
80
|
});
|
|
75
81
|
parent.links = parent.links.filter((item)=>item.remove !== true);
|
|
@@ -87,15 +93,28 @@ function buildMenu({ components, context }) {
|
|
|
87
93
|
const checkDuplicateMenuId = createCheckDuplicateId({
|
|
88
94
|
message: 'Duplicate menuId "{{ id }}".'
|
|
89
95
|
});
|
|
90
|
-
|
|
96
|
+
// Track which menus failed validation so we skip processing them
|
|
97
|
+
const failedMenuIndices = new Set();
|
|
98
|
+
components.menus.forEach((menu, menuIndex)=>{
|
|
99
|
+
const configKey = menu['~k'];
|
|
91
100
|
if (type.isUndefined(menu.id)) {
|
|
92
|
-
|
|
101
|
+
collectExceptions(context, new ConfigError('Menu id missing.', {
|
|
102
|
+
configKey
|
|
103
|
+
}));
|
|
104
|
+
failedMenuIndices.add(menuIndex);
|
|
105
|
+
return;
|
|
93
106
|
}
|
|
94
107
|
if (!type.isString(menu.id)) {
|
|
95
|
-
|
|
108
|
+
collectExceptions(context, new ConfigError('Menu id is not a string.', {
|
|
109
|
+
received: menu.id,
|
|
110
|
+
configKey
|
|
111
|
+
}));
|
|
112
|
+
failedMenuIndices.add(menuIndex);
|
|
113
|
+
return;
|
|
96
114
|
}
|
|
97
115
|
checkDuplicateMenuId({
|
|
98
|
-
id: menu.id
|
|
116
|
+
id: menu.id,
|
|
117
|
+
configKey
|
|
99
118
|
});
|
|
100
119
|
menu.menuId = menu.id;
|
|
101
120
|
menu.id = `menu:${menu.id}`;
|
|
@@ -107,11 +126,16 @@ function buildMenu({ components, context }) {
|
|
|
107
126
|
menuId: menu.menuId,
|
|
108
127
|
pages,
|
|
109
128
|
missingPageWarnings,
|
|
110
|
-
checkDuplicateMenuItemId
|
|
129
|
+
checkDuplicateMenuItemId,
|
|
130
|
+
context
|
|
111
131
|
});
|
|
112
132
|
});
|
|
113
|
-
missingPageWarnings.
|
|
114
|
-
context.
|
|
133
|
+
missingPageWarnings.forEach((warning)=>{
|
|
134
|
+
context.handleWarning(new ConfigWarning(`Page "${warning.pageId}" referenced in menu link "${warning.menuItemId}" not found.`, {
|
|
135
|
+
configKey: warning.configKey,
|
|
136
|
+
prodError: true,
|
|
137
|
+
checkSlug: 'link-refs'
|
|
138
|
+
}));
|
|
115
139
|
});
|
|
116
140
|
return components;
|
|
117
141
|
}
|