@lowdefy/build 0.0.0-experimental-20251203202233 → 0.0.0-experimental-20260112140412

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.
Files changed (52) hide show
  1. package/dist/build/addKeys.js +2 -0
  2. package/dist/build/buildApi/buildEndpoint.js +6 -0
  3. package/dist/build/buildApi/buildRoutine/countStepTypes.js +1 -1
  4. package/dist/build/buildApi/validateStepReferences.js +65 -0
  5. package/dist/build/buildAuth/buildAuthPlugins.js +42 -12
  6. package/dist/build/buildAuth/validateAuthConfig.js +10 -2
  7. package/dist/build/buildAuth/validateMutualExclusivity.js +18 -4
  8. package/dist/build/buildConnections.js +25 -6
  9. package/dist/build/buildImports/buildIconImports.js +19 -36
  10. package/dist/build/buildLogger.js +41 -0
  11. package/dist/build/buildMenu.js +40 -13
  12. package/dist/build/buildPages/buildBlock/buildEvents.js +90 -9
  13. package/dist/build/buildPages/buildBlock/buildRequests.js +47 -7
  14. package/dist/build/buildPages/buildBlock/countBlockTypes.js +1 -1
  15. package/dist/build/buildPages/buildBlock/validateBlock.js +33 -7
  16. package/dist/build/buildPages/buildPage.js +28 -4
  17. package/dist/build/buildPages/buildPages.js +26 -1
  18. package/dist/build/buildPages/buildTestPage.js +9 -1
  19. package/dist/build/buildPages/validateLinkReferences.js +33 -0
  20. package/dist/build/buildPages/validatePayloadReferences.js +52 -0
  21. package/dist/build/buildPages/validateRequestReferences.js +33 -0
  22. package/dist/build/buildPages/validateStateReferences.js +52 -0
  23. package/dist/build/buildRefs/buildRefs.js +11 -30
  24. package/dist/build/buildRefs/evaluateBuildOperators.js +8 -2
  25. package/dist/build/buildRefs/getConfigFile.js +2 -1
  26. package/dist/build/buildRefs/getRefContent.js +17 -31
  27. package/dist/build/buildRefs/getRefsFromFile.js +8 -3
  28. package/dist/build/buildRefs/makeRefDefinition.js +9 -8
  29. package/dist/build/buildRefs/parseRefContent.js +61 -2
  30. package/dist/build/buildRefs/populateRefs.js +14 -11
  31. package/dist/build/buildRefs/recursiveBuild.js +64 -63
  32. package/dist/build/buildTypes.js +19 -2
  33. package/dist/build/formatBuildError.js +34 -0
  34. package/dist/build/writeLogger.js +19 -0
  35. package/dist/createContext.js +2 -15
  36. package/dist/defaultTypesMap.js +494 -487
  37. package/dist/index.js +130 -125
  38. package/dist/lowdefySchema.js +75 -0
  39. package/dist/test/testContext.js +2 -1
  40. package/dist/utils/countOperators.js +24 -11
  41. package/dist/utils/createCheckDuplicateId.js +30 -9
  42. package/dist/utils/createCounter.js +15 -2
  43. package/dist/utils/extractOperatorKey.js +36 -0
  44. package/dist/utils/findSimilarString.js +53 -0
  45. package/dist/utils/formatConfigError.js +24 -0
  46. package/dist/utils/formatConfigMessage.js +33 -0
  47. package/dist/utils/formatConfigWarning.js +24 -0
  48. package/dist/utils/traverseConfig.js +43 -0
  49. package/package.json +39 -39
  50. package/dist/utils/createBuildProfiler.js +0 -125
  51. package/dist/utils/invalidateChangedFiles.js +0 -74
  52. package/dist/utils/makeRefHash.js +0 -15
@@ -12,8 +12,14 @@
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
- */ async function evaluateBuildOperators({ context, input, refDef }) {
16
- const { output, errors } = context.operatorsParser.parse({
15
+ */ import { BuildParser } from '@lowdefy/operators';
16
+ import operators from '@lowdefy/operators-js/operators/build';
17
+ async function evaluateBuildOperators({ context, input, refDef }) {
18
+ const operatorsParser = new BuildParser({
19
+ env: process.env,
20
+ operators
21
+ });
22
+ const { output, errors } = operatorsParser.parse({
17
23
  input,
18
24
  location: refDef.path ?? refDef.resolver,
19
25
  operatorPrefix: '_build.'
@@ -21,7 +21,8 @@ async function getConfigFile({ context, refDef, referencedFrom }) {
21
21
  }
22
22
  const content = await context.readConfigFile(refDef.path);
23
23
  if (content === null) {
24
- throw new Error(`Tried to reference file "${refDef.path}" from "${referencedFrom}", but file does not exist.`);
24
+ const lineInfo = refDef.lineNumber ? `:${refDef.lineNumber}` : '';
25
+ throw new Error(`Tried to reference file "${refDef.path}" from "${referencedFrom}${lineInfo}", but file does not exist.`);
25
26
  }
26
27
  return content;
27
28
  }
@@ -12,47 +12,33 @@
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 { getFileExtension } from '@lowdefy/node-utils';
16
- import getConfigFile from './getConfigFile.js';
15
+ */ import getConfigFile from './getConfigFile.js';
17
16
  import parseRefContent from './parseRefContent.js';
18
17
  import runRefResolver from './runRefResolver.js';
19
- function getCacheKey(refDef) {
20
- const { path, vars } = refDef;
21
- // For nunjucks files, vars affect the output, so include them in the cache key
22
- const ext = getFileExtension(path);
23
- if (ext === 'njk' && vars) {
24
- return `${path}::${JSON.stringify(vars)}`;
25
- }
26
- return path;
27
- }
28
18
  async function getRefContent({ context, refDef, referencedFrom }) {
29
- // Skip caching for resolver-based refs (dynamic content)
30
- if (refDef.resolver || context.refResolver) {
31
- const content = await runRefResolver({
19
+ let content;
20
+ if (refDef.path === 'lowdefy.yaml' || refDef.path === 'lowdefy.yml') {
21
+ content = await getConfigFile({
32
22
  context,
33
23
  refDef,
34
24
  referencedFrom
35
25
  });
36
- return parseRefContent({
37
- content,
38
- refDef
26
+ } else if (refDef.resolver || context.refResolver) {
27
+ content = await runRefResolver({
28
+ context,
29
+ refDef,
30
+ referencedFrom
31
+ });
32
+ } else {
33
+ content = await getConfigFile({
34
+ context,
35
+ refDef,
36
+ referencedFrom
39
37
  });
40
38
  }
41
- const cacheKey = getCacheKey(refDef);
42
- const cached = context.parsedContentCache.get(cacheKey);
43
- if (cached !== undefined) {
44
- return cached;
45
- }
46
- const rawContent = await getConfigFile({
47
- context,
48
- refDef,
49
- referencedFrom
50
- });
51
- const parsed = parseRefContent({
52
- content: rawContent,
39
+ return parseRefContent({
40
+ content,
53
41
  refDef
54
42
  });
55
- context.parsedContentCache.set(cacheKey, parsed);
56
- return parsed;
57
43
  }
58
44
  export default getRefContent;
@@ -12,14 +12,16 @@
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 { serializer, type } from '@lowdefy/helpers';
16
16
  import makeRefDefinition from './makeRefDefinition.js';
17
17
  function getRefsFromFile(fileContent, parentRefDefId, refMap) {
18
18
  const foundRefs = [];
19
19
  const reviver = (key, value)=>{
20
20
  if (type.isObject(value)) {
21
21
  if (!type.isUndefined(value._ref)) {
22
- const def = makeRefDefinition(value._ref, parentRefDefId, refMap);
22
+ // Capture line number from the object containing the _ref
23
+ const lineNumber = value['~l'];
24
+ const def = makeRefDefinition(value._ref, parentRefDefId, refMap, lineNumber);
23
25
  foundRefs.push(def);
24
26
  return {
25
27
  _ref: def
@@ -28,7 +30,10 @@ function getRefsFromFile(fileContent, parentRefDefId, refMap) {
28
30
  }
29
31
  return value;
30
32
  };
31
- const fileContentBuiltRefs = JSON.parse(JSON.stringify(fileContent), reviver);
33
+ // Use serializer.copy to preserve non-enumerable properties like ~l
34
+ const fileContentBuiltRefs = serializer.copy(fileContent, {
35
+ reviver
36
+ });
32
37
  return {
33
38
  foundRefs,
34
39
  fileContentBuiltRefs
@@ -14,10 +14,17 @@
14
14
  limitations under the License.
15
15
  */ import { get } from '@lowdefy/helpers';
16
16
  import getRefPath from './getRefPath.js';
17
- import makeRefHash from '../../utils/makeRefHash.js';
18
- function makeRefDefinition(refDefinition, parent, refMap) {
17
+ import makeId from '../../utils/makeId.js';
18
+ function makeRefDefinition(refDefinition, parent, refMap, lineNumber) {
19
+ const id = makeId();
19
20
  const refDef = {
20
21
  parent,
22
+ lineNumber
23
+ };
24
+ refMap[id] = refDef;
25
+ return {
26
+ ...refDef,
27
+ id,
21
28
  key: get(refDefinition, 'key'),
22
29
  original: refDefinition,
23
30
  path: getRefPath(refDefinition),
@@ -27,11 +34,5 @@ function makeRefDefinition(refDefinition, parent, refMap) {
27
34
  default: {}
28
35
  })
29
36
  };
30
- const refHash = makeRefHash(refDef);
31
- refMap[refHash] = {
32
- parent
33
- };
34
- refDef.hash = refHash;
35
- return refDef;
36
37
  }
37
38
  export default makeRefDefinition;
@@ -15,8 +15,67 @@
15
15
  */ /* eslint-disable no-param-reassign */ import { type } from '@lowdefy/helpers';
16
16
  import { getFileExtension, getFileSubExtension } from '@lowdefy/node-utils';
17
17
  import JSON5 from 'json5';
18
- import YAML from 'yaml';
18
+ import YAML, { isMap, isSeq, isPair, isScalar } from 'yaml';
19
19
  import parseNunjucks from './parseNunjucks.js';
20
+ function getLineNumber(content, offset) {
21
+ if (offset == null || offset < 0) return null;
22
+ return content.substring(0, offset).split('\n').length;
23
+ }
24
+ function addLineNumbers(node, content, result) {
25
+ if (isMap(node)) {
26
+ const obj = result || {};
27
+ if (node.range) {
28
+ Object.defineProperty(obj, '~l', {
29
+ value: getLineNumber(content, node.range[0]),
30
+ enumerable: false,
31
+ writable: true,
32
+ configurable: true
33
+ });
34
+ }
35
+ for (const pair of node.items){
36
+ if (isPair(pair) && isScalar(pair.key)) {
37
+ const key = pair.key.value;
38
+ const value = pair.value;
39
+ if (isMap(value)) {
40
+ obj[key] = addLineNumbers(value, content, {});
41
+ } else if (isSeq(value)) {
42
+ obj[key] = addLineNumbers(value, content, []);
43
+ } else if (isScalar(value)) {
44
+ obj[key] = value.value;
45
+ } else {
46
+ obj[key] = value?.toJSON?.() ?? value;
47
+ }
48
+ }
49
+ }
50
+ return obj;
51
+ }
52
+ if (isSeq(node)) {
53
+ const arr = result || [];
54
+ for (const item of node.items){
55
+ if (isMap(item)) {
56
+ arr.push(addLineNumbers(item, content, {}));
57
+ } else if (isSeq(item)) {
58
+ arr.push(addLineNumbers(item, content, []));
59
+ } else if (isScalar(item)) {
60
+ arr.push(item.value);
61
+ } else {
62
+ arr.push(item?.toJSON?.() ?? item);
63
+ }
64
+ }
65
+ return arr;
66
+ }
67
+ if (isScalar(node)) {
68
+ return node.value;
69
+ }
70
+ return node?.toJSON?.() ?? node;
71
+ }
72
+ function parseYamlWithLineNumbers(content) {
73
+ const doc = YAML.parseDocument(content);
74
+ if (doc.errors && doc.errors.length > 0) {
75
+ throw new Error(doc.errors[0].message);
76
+ }
77
+ return addLineNumbers(doc.contents, content);
78
+ }
20
79
  function parseRefContent({ content, refDef }) {
21
80
  const { path, vars } = refDef;
22
81
  if (type.isString(path)) {
@@ -26,7 +85,7 @@ function parseRefContent({ content, refDef }) {
26
85
  ext = getFileSubExtension(path);
27
86
  }
28
87
  if (ext === 'yaml' || ext === 'yml') {
29
- content = YAML.parse(content);
88
+ content = parseYamlWithLineNumbers(content);
30
89
  }
31
90
  if (ext === 'json') {
32
91
  content = JSON5.parse(content);
@@ -12,32 +12,35 @@
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 { get, type } from '@lowdefy/helpers';
15
+ */ import { get, serializer, type } from '@lowdefy/helpers';
16
16
  function refReviver(key, value) {
17
17
  if (type.isObject(value)) {
18
18
  if (!type.isUndefined(value._ref)) {
19
- return this.refCache.get(value._ref.hash);
19
+ return this.parsedFiles[value._ref.id];
20
20
  }
21
21
  if (value._var) {
22
22
  if (type.isString(value._var)) {
23
- return JSON.parse(JSON.stringify(get(this.vars, value._var, {
23
+ return serializer.copy(get(this.vars, value._var, {
24
24
  default: null
25
- })));
25
+ }));
26
26
  }
27
27
  if (type.isObject(value._var) && type.isString(value._var.key)) {
28
- return JSON.parse(JSON.stringify(get(this.vars, value._var.key, {
28
+ return serializer.copy(get(this.vars, value._var.key, {
29
29
  default: type.isNone(value._var.default) ? null : value._var.default
30
- })));
30
+ }));
31
31
  }
32
32
  throw new Error(`"_var" operator takes a string or object with "key" field as arguments. Received "${JSON.stringify(value)}"`);
33
33
  }
34
34
  }
35
35
  return value;
36
36
  }
37
- function populateRefs({ refCache, refDef, toPopulate }) {
38
- return JSON.parse(JSON.stringify(toPopulate), refReviver.bind({
39
- refCache,
40
- vars: refDef.vars
41
- }));
37
+ function populateRefs({ parsedFiles, refDef, toPopulate }) {
38
+ // Use serializer.copy to preserve non-enumerable properties like ~r, ~k, ~l
39
+ return serializer.copy(toPopulate, {
40
+ reviver: refReviver.bind({
41
+ parsedFiles,
42
+ vars: refDef.vars
43
+ })
44
+ });
42
45
  }
43
46
  export default populateRefs;
@@ -12,92 +12,93 @@
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 { serializer, type } from '@lowdefy/helpers';
16
16
  import evaluateBuildOperators from './evaluateBuildOperators.js';
17
17
  import getKey from './getKey.js';
18
18
  import getRefContent from './getRefContent.js';
19
19
  import getRefsFromFile from './getRefsFromFile.js';
20
20
  import populateRefs from './populateRefs.js';
21
21
  import runTransformer from './runTransformer.js';
22
- async function recursiveBuild({ context, refDef, count, referencedFrom, refCache, profiler }) {
23
- const time = profiler?.time ?? ((_, fn)=>fn());
24
- const timeSync = profiler?.timeSync ?? ((_, fn)=>fn());
25
- // TODO: Maybe it would be better to detect a cycle, since this is the real issue here?
22
+ async function recursiveBuild({ context, refDef, count, referencedFrom, refChainSet = new Set(), refChainList = [] }) {
23
+ // Detect circular references by tracking the chain of files being resolved
24
+ const currentPath = refDef.path;
25
+ if (refChainSet.has(currentPath)) {
26
+ const chainDisplay = [
27
+ ...refChainList,
28
+ currentPath
29
+ ].join(' -> ');
30
+ throw new Error(`Circular reference detected: ${chainDisplay}`);
31
+ }
32
+ refChainSet.add(currentPath);
33
+ refChainList.push(currentPath);
34
+ // Keep count as a fallback safety limit
26
35
  if (count > 10000) {
27
36
  throw new Error(`Maximum recursion depth of references exceeded.`);
28
37
  }
29
- if (refCache.has(refDef.hash)) {
30
- return refCache.get(refDef.hash);
31
- }
32
- let fileContent = await time('getRefContent', ()=>getRefContent({
33
- context,
34
- refDef,
35
- referencedFrom
36
- }));
37
- const { foundRefs, fileContentBuiltRefs } = timeSync('getRefsFromFile', ()=>getRefsFromFile(fileContent, refDef.hash, context.refMap));
38
+ let fileContent = await getRefContent({
39
+ context,
40
+ refDef,
41
+ referencedFrom
42
+ });
43
+ const { foundRefs, fileContentBuiltRefs } = getRefsFromFile(fileContent, refDef.id, context.refMap);
44
+ const parsedFiles = {};
38
45
  // Since we can have references in the variables of a reference, we need to first parse
39
46
  // the deeper nodes, so we can use those parsed files in references higher in the tree.
40
47
  // To do this, since foundRefs is an array of ref definitions that are in order of the
41
48
  // deepest nodes first we for loop over over foundRefs one by one, awaiting each result.
42
49
  for (const newRefDef of foundRefs.values()){
43
50
  // Parse vars and path before passing down to parse new file
44
- const parsedRefDef = timeSync('populateRefs:vars', ()=>populateRefs({
45
- toPopulate: newRefDef,
46
- refCache,
47
- refDef
48
- }));
49
- context.refMap[parsedRefDef.hash].path = parsedRefDef.path;
50
- // Build dependency graph: when refDef.path references parsedRefDef.path,
51
- // add refDef.path as a dependent of parsedRefDef.path
52
- if (parsedRefDef.path && refDef.path) {
53
- if (!context.dependencyGraph.has(parsedRefDef.path)) {
54
- context.dependencyGraph.set(parsedRefDef.path, new Set());
55
- }
56
- context.dependencyGraph.get(parsedRefDef.path).add(refDef.path);
57
- }
51
+ const parsedRefDef = populateRefs({
52
+ toPopulate: newRefDef,
53
+ parsedFiles,
54
+ refDef
55
+ });
56
+ context.refMap[parsedRefDef.id].path = parsedRefDef.path;
58
57
  const parsedFile = await recursiveBuild({
59
58
  context,
60
59
  refDef: parsedRefDef,
61
60
  count: count + 1,
62
61
  referencedFrom: refDef.path,
63
- refCache,
64
- profiler
62
+ refChainSet,
63
+ refChainList
64
+ });
65
+ const transformedFile = await runTransformer({
66
+ context,
67
+ input: parsedFile,
68
+ refDef: parsedRefDef
65
69
  });
66
- const transformedFile = await time('runTransformer', ()=>runTransformer({
67
- context,
68
- input: parsedFile,
69
- refDef: parsedRefDef
70
- }));
71
70
  // Evaluated in recursive loop for better error messages
72
- const evaluatedOperators = await time('evaluateBuildOperators', ()=>evaluateBuildOperators({
73
- context,
74
- input: transformedFile,
75
- refDef: parsedRefDef
76
- }));
77
- const withRefKey = timeSync('getKey', ()=>getKey({
78
- input: evaluatedOperators,
79
- refDef: parsedRefDef
80
- }));
81
- timeSync('cacheWithReviver', ()=>{
82
- const reviver = (_, value)=>{
83
- if (!type.isObject(value)) return value;
84
- Object.defineProperty(value, '~r', {
85
- value: refDef.hash,
86
- enumerable: false,
87
- writable: true,
88
- configurable: true
89
- });
90
- return value;
91
- };
92
- refCache.set(newRefDef.hash, JSON.parse(JSON.stringify(withRefKey), reviver));
71
+ const evaluatedOperators = await evaluateBuildOperators({
72
+ context,
73
+ input: transformedFile,
74
+ refDef: parsedRefDef
75
+ });
76
+ const withRefKey = getKey({
77
+ input: evaluatedOperators,
78
+ refDef: parsedRefDef
79
+ });
80
+ const reviver = (_, value)=>{
81
+ if (!type.isObject(value)) return value;
82
+ Object.defineProperty(value, '~r', {
83
+ value: refDef.id,
84
+ enumerable: false,
85
+ writable: true,
86
+ configurable: true
87
+ });
88
+ return value;
89
+ };
90
+ // Use serializer.copy to preserve non-enumerable properties like ~l
91
+ parsedFiles[newRefDef.id] = serializer.copy(withRefKey, {
92
+ reviver
93
93
  });
94
94
  }
95
- const result = timeSync('populateRefs:final', ()=>populateRefs({
96
- toPopulate: fileContentBuiltRefs,
97
- refCache,
98
- refDef
99
- }));
100
- refCache.set(refDef.hash, result);
101
- return result;
95
+ // Backtrack: remove current file from chain so sibling refs can use it
96
+ refChainSet.delete(currentPath);
97
+ refChainList.pop();
98
+ return populateRefs({
99
+ toPopulate: fileContentBuiltRefs,
100
+ parsedFiles,
101
+ refDef
102
+ });
102
103
  }
103
104
  export default recursiveBuild;
@@ -14,18 +14,35 @@
14
14
  limitations under the License.
15
15
  */ import basicTypes from '@lowdefy/blocks-basic/types';
16
16
  import loaderTypes from '@lowdefy/blocks-loaders/types';
17
+ import findSimilarString from '../utils/findSimilarString.js';
18
+ import formatBuildError from './formatBuildError.js';
17
19
  function buildTypeClass(context, { counter, definitions, store, typeClass, warnIfMissing = false }) {
18
20
  const counts = counter.getCounts();
21
+ const definedTypes = Object.keys(definitions);
19
22
  Object.keys(counts).forEach((typeName)=>{
20
23
  if (!definitions[typeName]) {
24
+ let message = `${typeClass} type "${typeName}" was used but is not defined.`;
25
+ const suggestion = findSimilarString({
26
+ input: typeName,
27
+ candidates: definedTypes
28
+ });
29
+ if (suggestion) {
30
+ message += ` Did you mean "${suggestion}"?`;
31
+ }
32
+ const formattedError = formatBuildError({
33
+ context,
34
+ counter,
35
+ typeName,
36
+ message
37
+ });
21
38
  if (warnIfMissing) {
22
39
  if (typeName === '_id') {
23
40
  return;
24
41
  }
25
- context.logger.warn(`${typeClass} type "${typeName}" was used but is not defined.`);
42
+ context.logger.warn(formattedError);
26
43
  return;
27
44
  }
28
- throw new Error(`${typeClass} type "${typeName}" was used but is not defined.`);
45
+ throw new Error(formattedError);
29
46
  }
30
47
  store[typeName] = {
31
48
  originalTypeName: definitions[typeName].originalTypeName,
@@ -0,0 +1,34 @@
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 { resolveConfigLocation } from '@lowdefy/helpers';
16
+ function formatBuildError({ context, counter, typeName, message }) {
17
+ const configKey = counter.getLocation(typeName);
18
+ if (!configKey) {
19
+ return `[Config Error] ${message}`;
20
+ }
21
+ const location = resolveConfigLocation({
22
+ configKey,
23
+ keyMap: context.keyMap,
24
+ refMap: context.refMap,
25
+ configDirectory: context.directories.config
26
+ });
27
+ if (!location) {
28
+ return `[Config Error] ${message}`;
29
+ }
30
+ const source = location.source ? `${location.source} at ${location.config}` : '';
31
+ const link = location.link || '';
32
+ return `[Config Error] ${message}\n ${source}\n ${link}`;
33
+ }
34
+ export default formatBuildError;
@@ -0,0 +1,19 @@
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 { serializer } from '@lowdefy/helpers';
16
+ async function writeLogger({ components, context }) {
17
+ await context.writeBuildArtifact('logger.json', serializer.serializeToString(components.logger ?? {}));
18
+ }
19
+ export default writeLogger;
@@ -13,30 +13,17 @@
13
13
  See the License for the specific language governing permissions and
14
14
  limitations under the License.
15
15
  */ import { mergeObjects } from '@lowdefy/helpers';
16
- import { BuildParser } from '@lowdefy/operators';
17
- import operators from '@lowdefy/operators-js/operators/build';
18
16
  import createCounter from './utils/createCounter.js';
19
17
  import createReadConfigFile from './utils/readConfigFile.js';
20
18
  import createWriteBuildArtifact from './utils/writeBuildArtifact.js';
21
19
  import defaultTypesMap from './defaultTypesMap.js';
22
- function createContext({ customTypesMap, directories, logger, refResolver, stage = 'prod', changedFiles = [], buildState = null }) {
23
- const operatorsParser = new BuildParser({
24
- env: process.env,
25
- operators
26
- });
27
- // Use persistent buildState if provided (for incremental builds in dev mode)
28
- // Otherwise create fresh Maps
29
- const dependencyGraph = buildState?.dependencyGraph ?? new Map();
30
- const parsedContentCache = buildState?.parsedContentCache ?? new Map();
20
+ function createContext({ customTypesMap, directories, logger, refResolver, stage = 'prod' }) {
31
21
  const context = {
32
- changedFiles,
33
- dependencyGraph,
22
+ connectionIds: new Set(),
34
23
  directories,
35
24
  jsMap: {},
36
25
  keyMap: {},
37
26
  logger,
38
- operatorsParser,
39
- parsedContentCache,
40
27
  readConfigFile: createReadConfigFile({
41
28
  directories
42
29
  }),