diff --git a/packages/api/src/routes/auth/callbacks/createSessionCallback.js b/packages/api/src/routes/auth/callbacks/createSessionCallback.js index 3edbbdf6d..ece123f2d 100644 --- a/packages/api/src/routes/auth/callbacks/createSessionCallback.js +++ b/packages/api/src/routes/auth/callbacks/createSessionCallback.js @@ -24,7 +24,6 @@ function createSessionCallback({ authConfig, plugins }) { }); async function sessionCallback({ session, token, user }) { - // console.log({ session, token, user }); if (token) { const { sub, @@ -74,6 +73,7 @@ function createSessionCallback({ authConfig, plugins }) { } for (const plugin of sessionCallbackPlugins) { + // eslint-disable-next-line no-param-reassign session = await plugin.fn({ properties: plugin.properties ?? {}, session, diff --git a/packages/build/src/build/buildRefs/buildRefs.js b/packages/build/src/build/buildRefs/buildRefs.js index ad5b8d89e..2a95405f7 100644 --- a/packages/build/src/build/buildRefs/buildRefs.js +++ b/packages/build/src/build/buildRefs/buildRefs.js @@ -16,14 +16,21 @@ import recursiveBuild from './recursiveBuild.js'; import makeRefDefinition from './makeRefDefinition.js'; -// TODO: build operators aren't evaluated in lowdefy.yaml file. Move recursive call up a layer or something. +import evaluateBuildOperators from './evaluateBuildOperators.js'; + async function buildRefs({ context }) { - const components = await recursiveBuild({ + const refDef = makeRefDefinition('lowdefy.yaml'); + let components = await recursiveBuild({ context, - refDef: makeRefDefinition('lowdefy.yaml'), + refDef, count: 0, }); - return components || {}; + components = await evaluateBuildOperators({ + context, + input: components, + refDef, + }); + return components ?? {}; } export default buildRefs; diff --git a/packages/build/src/build/buildRefs/buildRefs.test.js b/packages/build/src/build/buildRefs/buildRefs.test.js index ff66c1ce4..a20881851 100644 --- a/packages/build/src/build/buildRefs/buildRefs.test.js +++ b/packages/build/src/build/buildRefs/buildRefs.test.js @@ -19,6 +19,12 @@ import { jest } from '@jest/globals'; import buildRefs from './buildRefs.js'; import testContext from '../../test/testContext.js'; +const mockLogWarn = jest.fn(); + +const logger = { + warn: mockLogWarn, +}; + const readConfigFileMockImplementation = (files) => { const mockImp = (filePath) => { const file = files.find((file) => file.path === filePath); @@ -33,6 +39,7 @@ const readConfigFileMockImplementation = (files) => { const mockReadConfigFile = jest.fn(); const context = testContext({ + logger, readConfigFile: mockReadConfigFile, }); @@ -1047,3 +1054,91 @@ _ref: target`, }); }); }); + +describe('Evaluate build time operators', () => { + test('Evaluate build time operators in lowdefy.yaml', async () => { + const files = [ + { + path: 'lowdefy.yaml', + content: ` +answer: + _build.sum: + - 1 + - 1`, + }, + ]; + mockReadConfigFile.mockImplementation(readConfigFileMockImplementation(files)); + const res = await buildRefs({ context }); + expect(res).toEqual({ + answer: 2, + }); + }); + + test('Evaluate build time operators in referenced file', async () => { + const files = [ + { + path: 'lowdefy.yaml', + content: ` +answer: + _ref: file.yaml`, + }, + { + path: 'file.yaml', + content: ` +_build.sum: + - 1 + - 1`, + }, + ]; + mockReadConfigFile.mockImplementation(readConfigFileMockImplementation(files)); + const res = await buildRefs({ context }); + expect(res).toEqual({ + answer: 2, + }); + }); + + test('Build time operator error in lowdefy.yaml', async () => { + const files = [ + { + path: 'lowdefy.yaml', + content: ` +answer: + _build.sum: A`, + }, + ]; + mockReadConfigFile.mockImplementation(readConfigFileMockImplementation(files)); + const res = await buildRefs({ context }); + expect(res).toEqual({ + answer: null, + }); + expect(mockLogWarn.mock.calls).toEqual([ + ['Build operator errors.'], + ['Operator Error: _sum takes an array type as input. Received: "A" at lowdefy.yaml.'], + ]); + }); + + test('Build time operator error in referenced file', async () => { + const files = [ + { + path: 'lowdefy.yaml', + content: ` +answer: + _ref: file.yaml`, + }, + { + path: 'file.yaml', + content: ` +_build.sum: A`, + }, + ]; + mockReadConfigFile.mockImplementation(readConfigFileMockImplementation(files)); + const res = await buildRefs({ context }); + expect(res).toEqual({ + answer: null, + }); + expect(mockLogWarn.mock.calls).toEqual([ + ['Build operator errors.'], + ['Operator Error: _sum takes an array type as input. Received: "A" at file.yaml.'], + ]); + }); +}); diff --git a/packages/build/src/build/buildRefs/recursiveBuild.js b/packages/build/src/build/buildRefs/recursiveBuild.js index 012044299..df8aa20b6 100644 --- a/packages/build/src/build/buildRefs/recursiveBuild.js +++ b/packages/build/src/build/buildRefs/recursiveBuild.js @@ -25,12 +25,8 @@ async function recursiveParseFile({ context, refDef, count, referencedFrom }) { throw new Error(`Maximum recursion depth of references exceeded.`); } let fileContent = await getRefContent({ context, refDef, referencedFrom }); - const parsedFileContent = await evaluateBuildOperators({ - context, - input: fileContent, - refDef: { path: 'lowdefy.yaml' }, - }); - const { foundRefs, fileContentBuiltRefs } = getRefsFromFile(parsedFileContent); + + const { foundRefs, fileContentBuiltRefs } = getRefsFromFile(fileContent); const parsedFiles = {}; @@ -39,7 +35,6 @@ async function recursiveParseFile({ context, refDef, count, referencedFrom }) { // To do this, since foundRefs is an array of ref definitions that are in order of the // deepest nodes first we for loop over over foundRefs one by one, awaiting each result. - // eslint-disable-next-line no-restricted-syntax for (const newRefDef of foundRefs.values()) { // Parse vars and path before passing down to parse new file const parsedRefDef = populateRefs({ @@ -55,19 +50,20 @@ async function recursiveParseFile({ context, refDef, count, referencedFrom }) { referencedFrom: refDef.path, }); - const evaluatedOperators = await evaluateBuildOperators({ + const transformedFile = await runTransformer({ context, input: parsedFile, refDef: parsedRefDef, }); - const transformedFile = await runTransformer({ + // Evaluated in recursive loop for better error messages + const evaluatedOperators = await evaluateBuildOperators({ context, - input: evaluatedOperators, + input: transformedFile, refDef: parsedRefDef, }); - parsedFiles[newRefDef.id] = transformedFile; + parsedFiles[newRefDef.id] = evaluatedOperators; } return populateRefs({ toPopulate: fileContentBuiltRefs, diff --git a/packages/operators/src/nodeParser.js b/packages/operators/src/nodeParser.js index 69c973cf9..2c9fded44 100644 --- a/packages/operators/src/nodeParser.js +++ b/packages/operators/src/nodeParser.js @@ -17,15 +17,18 @@ import { serializer, type } from '@lowdefy/helpers'; class NodeParser { - constructor({ env, payload, secrets, user, operators }) { + constructor({ env, payload, secrets, user, operators, verbose }) { this.env = env; this.operators = operators; this.payload = payload; this.secrets = secrets; this.user = user; this.parse = this.parse.bind(this); + this.verbose; } + // TODO: Look at logging here + // TODO: Remove console.error = () => {}; from tests parse({ args, input, location, operatorPrefix = '_' }) { if (type.isUndefined(input)) { return { output: input, errors: [] }; @@ -63,7 +66,9 @@ class NodeParser { return res; } catch (e) { errors.push(e); - console.error(e); + if (this.verbose) { + console.error(e); + } return null; } }; diff --git a/packages/operators/src/nodeParser.test.js b/packages/operators/src/nodeParser.test.js index 5e0ca9aa8..5d96053da 100644 --- a/packages/operators/src/nodeParser.test.js +++ b/packages/operators/src/nodeParser.test.js @@ -17,8 +17,6 @@ /* eslint-disable max-classes-per-file */ import NodeParser from './nodeParser.js'; -console.error = () => {}; - const args = [{ args: true }]; const operators = {