diff --git a/CHANGELOG.md b/CHANGELOG.md index 35ac8efc..7bb23e82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,10 @@ This project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.htm ## Unreleased +### Fixed + +- Fixed zkProgramFile to support nested paths. [#690](https://github.com/o1-labs/zkapp-cli/pull/690) + ## [0.21.5](https://github.com/o1-labs/zkapp-cli/compare/0.21.4...0.21.5) - 2024-06-06 ### Changed diff --git a/src/lib/deploy.js b/src/lib/deploy.js index 75e03c19..11fdce9d 100644 --- a/src/lib/deploy.js +++ b/src/lib/deploy.js @@ -792,8 +792,19 @@ async function findZkProgramFile(buildPath, zkProgramNameArg) { // eslint-disable-next-line no-unused-vars const [_, zkProgramVarName, nameArg] = match; + const buildSrcPath = buildPath.replace('**/*.js', 'src'); + const relativePath = path.relative(buildSrcPath, file); + + const isNested = + !relativePath.startsWith('..') && !path.isAbsolute(relativePath); + + const zkProgramFile = isNested ? relativePath : path.basename(file); + if (nameArg === zkProgramNameArg) { - return { zkProgramVarName, zkProgramFile: path.basename(file) }; + return { + zkProgramVarName, + zkProgramFile, + }; } } } diff --git a/src/lib/deploy.test.js b/src/lib/deploy.test.js index 7f81054e..357a737b 100644 --- a/src/lib/deploy.test.js +++ b/src/lib/deploy.test.js @@ -61,6 +61,21 @@ jest.unstable_mockModule('node:path', () => ({ resolve: jest.fn(), dirname: jest.fn(), sep: '/', + relative: jest.fn().mockImplementation((from, to) => { + const fromParts = from.split('/'); + const toParts = to.split('/'); + + let commonLength = 0; + for (let i = 0; i < Math.min(fromParts.length, toParts.length); i++) { + if (fromParts[i] !== toParts[i]) break; + commonLength++; + } + + const up = fromParts.slice(commonLength).map(() => '..'); + const down = toParts.slice(commonLength); + + return [...up, ...down].join('/') || '.'; + }), }, })); @@ -1075,6 +1090,31 @@ describe('deploy.js', () => { ); }); + it('should return the ZkProgram when found in nested folders', async () => { + const projectRoot = '/some/path/'; + const zkProgramNameArg = 'myZkProgram'; + const zkProgramFile = 'proofs/file1.js'; + const zkProgramMock = { name: 'myZkProgram' }; + glob.mockResolvedValue(['/some/path/file1.js']); + fs.readFileSync.mockReturnValue( + ` + const myVar = ZkProgram({ + name: 'myZkProgram' + }); + ` + ); + jest.spyOn(path, 'basename').mockReturnValue('proofs/file1.js'); + dynamicImport.mockResolvedValue({ myVar: zkProgramMock }); + const { getZkProgram } = await import('./deploy.js'); + + const result = await getZkProgram(projectRoot, zkProgramNameArg); + + expect(result).toBe(zkProgramMock); + expect(dynamicImport).toHaveBeenCalledWith( + `${projectRoot}/build/src/${zkProgramFile}` + ); + }); + it('should handle Windows paths correctly', async () => { const originalPlatform = process.platform; try {