@lowdefy/build 0.0.0-experimental-20260122074446 → 0.0.0-experimental-20260122121633

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.
@@ -13,6 +13,40 @@
13
13
  See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
15
  */ import { get, serializer, type } from '@lowdefy/helpers';
16
+ /**
17
+ * Copies a _var value while preserving source location markers.
18
+ *
19
+ * When _var copies a value from vars into a template, we need to preserve
20
+ * the ~r (ref ID) and ~l (line number) from WHERE THE VALUE IS DEFINED
21
+ * (the source file), not where _var is used (the template).
22
+ *
23
+ * The issue is that serializer.copy loses non-enumerable properties, and
24
+ * recursiveBuild.js then sets ~r to the template file for objects without ~r.
25
+ *
26
+ * This function preserves the source location by making ~r enumerable on
27
+ * the copied value, so it survives through subsequent serializer.copy calls.
28
+ *
29
+ * @param {*} value - The value to copy from vars
30
+ * @param {string} sourceRefId - The ref ID of the source file where the var is defined
31
+ * @returns {*} The copied value with preserved source location markers
32
+ */ function copyVarValue(value, sourceRefId) {
33
+ if (!type.isObject(value) && !type.isArray(value)) {
34
+ return value;
35
+ }
36
+ // Copy the value, preserving ~l and setting ~r to the source file
37
+ return serializer.copy(value, {
38
+ reviver: (_, v)=>{
39
+ if (type.isObject(v)) {
40
+ // Preserve the source file's ref ID by setting it explicitly
41
+ // This prevents recursiveBuild from overwriting it with the template's ref ID
42
+ if (sourceRefId && v['~r'] === undefined) {
43
+ v['~r'] = sourceRefId;
44
+ }
45
+ }
46
+ return v;
47
+ }
48
+ });
49
+ }
16
50
  function refReviver(key, value) {
17
51
  if (type.isObject(value)) {
18
52
  if (!type.isUndefined(value._ref)) {
@@ -20,14 +54,16 @@ function refReviver(key, value) {
20
54
  }
21
55
  if (value._var) {
22
56
  if (type.isString(value._var)) {
23
- return serializer.copy(get(this.vars, value._var, {
57
+ const varValue = get(this.vars, value._var, {
24
58
  default: null
25
- }));
59
+ });
60
+ return copyVarValue(varValue, this.sourceRefId);
26
61
  }
27
62
  if (type.isObject(value._var) && type.isString(value._var.key)) {
28
- return serializer.copy(get(this.vars, value._var.key, {
63
+ const varValue = get(this.vars, value._var.key, {
29
64
  default: type.isNone(value._var.default) ? null : value._var.default
30
- }));
65
+ });
66
+ return copyVarValue(varValue, this.sourceRefId);
31
67
  }
32
68
  throw new Error(`"_var" operator takes a string or object with "key" field as arguments. Received "${JSON.stringify(value)}"`);
33
69
  }
@@ -36,10 +72,12 @@ function refReviver(key, value) {
36
72
  }
37
73
  function populateRefs({ parsedFiles, refDef, toPopulate }) {
38
74
  // Use serializer.copy to preserve non-enumerable properties like ~r, ~k, ~l
75
+ // sourceRefId is the PARENT file's ref ID where vars are defined (not the template's ID)
39
76
  return serializer.copy(toPopulate, {
40
77
  reviver: refReviver.bind({
41
78
  parsedFiles,
42
- vars: refDef.vars
79
+ vars: refDef.vars,
80
+ sourceRefId: refDef.parent
43
81
  })
44
82
  });
45
83
  }