@lowdefy/build 0.0.0-experimental-20260113102133 → 0.0.0-experimental-20260114142524
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.
|
@@ -16,9 +16,10 @@
|
|
|
16
16
|
import formatConfigWarning from '../../utils/formatConfigWarning.js';
|
|
17
17
|
import traverseConfig from '../../utils/traverseConfig.js';
|
|
18
18
|
function validateStateReferences({ page, context }) {
|
|
19
|
-
// Single traversal collects
|
|
19
|
+
// Single traversal collects blockIds, _state references, and SetState keys
|
|
20
20
|
// More memory-efficient than stringify+regex for massive pages
|
|
21
21
|
const blockIds = new Set();
|
|
22
|
+
const setStateKeys = new Set();
|
|
22
23
|
const stateRefs = new Map(); // topLevelKey -> configKey (first occurrence)
|
|
23
24
|
traverseConfig({
|
|
24
25
|
config: page,
|
|
@@ -27,6 +28,13 @@ function validateStateReferences({ page, context }) {
|
|
|
27
28
|
if (obj.blockId) {
|
|
28
29
|
blockIds.add(obj.blockId);
|
|
29
30
|
}
|
|
31
|
+
// Collect SetState action params to track state keys being initialized
|
|
32
|
+
if (obj.type === 'SetState' && obj.params) {
|
|
33
|
+
Object.keys(obj.params).forEach((key)=>{
|
|
34
|
+
const topLevelKey = key.split(/[.\[]/)[0];
|
|
35
|
+
setStateKeys.add(topLevelKey);
|
|
36
|
+
});
|
|
37
|
+
}
|
|
30
38
|
// Collect _state reference if present
|
|
31
39
|
if (obj._state !== undefined) {
|
|
32
40
|
const topLevelKey = extractOperatorKey({
|
|
@@ -40,7 +48,8 @@ function validateStateReferences({ page, context }) {
|
|
|
40
48
|
});
|
|
41
49
|
// Filter to only undefined references and warn
|
|
42
50
|
stateRefs.forEach((configKey, topLevelKey)=>{
|
|
43
|
-
if
|
|
51
|
+
// Skip if state key is from an input block or SetState action
|
|
52
|
+
if (blockIds.has(topLevelKey) || setStateKeys.has(topLevelKey)) return;
|
|
44
53
|
const message = `_state references "${topLevelKey}" on page "${page.pageId}", ` + `but no input block with id "${topLevelKey}" exists on this page. ` + `State keys are created from input block ids. ` + `Check for typos, add an input block with this id, or initialize the state with SetState.`;
|
|
45
54
|
context.logger.warn(formatConfigWarning({
|
|
46
55
|
message,
|
|
@@ -12,7 +12,8 @@
|
|
|
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
|
|
15
|
+
*/ import path from 'path';
|
|
16
|
+
import { type } from '@lowdefy/helpers';
|
|
16
17
|
async function getConfigFile({ context, refDef, referencedFrom }) {
|
|
17
18
|
if (!type.isString(refDef.path)) {
|
|
18
19
|
throw new Error(`Invalid _ref definition ${JSON.stringify({
|
|
@@ -21,8 +22,23 @@ async function getConfigFile({ context, refDef, referencedFrom }) {
|
|
|
21
22
|
}
|
|
22
23
|
const content = await context.readConfigFile(refDef.path);
|
|
23
24
|
if (content === null) {
|
|
25
|
+
// Build helpful error message with resolved path information
|
|
24
26
|
const lineInfo = refDef.lineNumber ? `:${refDef.lineNumber}` : '';
|
|
25
|
-
|
|
27
|
+
const absolutePath = path.resolve(context.directories.config, refDef.path);
|
|
28
|
+
let message = `[Config Error] Referenced file does not exist: "${refDef.path}"\n`;
|
|
29
|
+
message += ` Referenced from: ${referencedFrom}${lineInfo}\n`;
|
|
30
|
+
message += ` Resolved to: ${absolutePath}\n`;
|
|
31
|
+
// Help with common mistakes
|
|
32
|
+
if (refDef.path.startsWith('../')) {
|
|
33
|
+
const suggestedPath = refDef.path.replace(/^(\.\.\/)+/, '');
|
|
34
|
+
message += `\n Tip: Paths in _ref are resolved from your config directory root.`;
|
|
35
|
+
message += `\n Did you mean: "${suggestedPath}"?`;
|
|
36
|
+
} else if (refDef.path.startsWith('./')) {
|
|
37
|
+
const suggestedPath = refDef.path.substring(2);
|
|
38
|
+
message += `\n Tip: Remove the "./" prefix - paths are resolved from config root.`;
|
|
39
|
+
message += `\n Did you mean: "${suggestedPath}"?`;
|
|
40
|
+
}
|
|
41
|
+
throw new Error(message);
|
|
26
42
|
}
|
|
27
43
|
return content;
|
|
28
44
|
}
|