diff --git a/.changeset/silly-pianos-fry.md b/.changeset/silly-pianos-fry.md new file mode 100644 index 00000000000..4ccee6af8da --- /dev/null +++ b/.changeset/silly-pianos-fry.md @@ -0,0 +1,6 @@ +--- +"@fuel-ts/contract": patch +"fuels": patch +--- + +fix: `fuels dev` hangs after compilation errors diff --git a/.github/workflows/pr-release.yaml b/.github/workflows/pr-release.yaml index 6eeca1f3f04..593d7fce145 100644 --- a/.github/workflows/pr-release.yaml +++ b/.github/workflows/pr-release.yaml @@ -8,7 +8,7 @@ jobs: name: "Release PR to npm" runs-on: ubuntu-latest # comment out if:false to enable release PR to npm - if: false + # if: false permissions: write-all steps: - name: Checkout diff --git a/packages/contract/src/contract-factory.ts b/packages/contract/src/contract-factory.ts index 3427651eb40..a319b7b85c9 100644 --- a/packages/contract/src/contract-factory.ts +++ b/packages/contract/src/contract-factory.ts @@ -147,6 +147,7 @@ export default class ContractFactory { const bytecode = deployOptions?.bytecode || this.bytecode; const stateRoot = options.stateRoot || getContractStorageRoot(options.storageSlots); const contractId = getContractId(bytecode, options.salt, stateRoot); + const transactionRequest = new CreateTransactionRequest({ bytecodeWitnessIndex: 0, witnesses: [bytecode], diff --git a/packages/fuels/src/cli/commands/build/buildSwayProgram.ts b/packages/fuels/src/cli/commands/build/buildSwayProgram.ts index 58f989a8fdd..b60d8e69b16 100644 --- a/packages/fuels/src/cli/commands/build/buildSwayProgram.ts +++ b/packages/fuels/src/cli/commands/build/buildSwayProgram.ts @@ -1,12 +1,12 @@ import { spawn } from 'child_process'; import type { FuelsConfig } from '../../types'; -import { debug, loggingConfig } from '../../utils/logger'; +import { loggingConfig, log } from '../../utils/logger'; import { onForcExit, onForcError } from './forcHandlers'; export const buildSwayProgram = async (config: FuelsConfig, path: string) => { - debug('Building Sway program', path); + log('Building Sway program', path); return new Promise((resolve, reject) => { const args = ['build', '-p', path].concat(config.forcBuildFlags); @@ -14,6 +14,13 @@ export const buildSwayProgram = async (config: FuelsConfig, path: string) => { if (loggingConfig.isLoggingEnabled) { // eslint-disable-next-line no-console forc.stderr?.on('data', (chunk) => console.log(chunk.toString())); + + forc.stderr?.on('data', (chunk) => { + if (chunk.toString().includes('Aborting')) { + // because forc logs out 'Aborting due to 2 compilation errors' etc. + onForcError(reject); + } + }); } if (loggingConfig.isDebugEnabled) { diff --git a/packages/fuels/src/cli/commands/build/generateTypes.ts b/packages/fuels/src/cli/commands/build/generateTypes.ts index dbcb17fe4bf..6ec2344e384 100644 --- a/packages/fuels/src/cli/commands/build/generateTypes.ts +++ b/packages/fuels/src/cli/commands/build/generateTypes.ts @@ -64,7 +64,7 @@ export async function generateTypes(config: FuelsConfig) { .map(({ programs, type }) => generateTypesForProgramType(config, programs, type)) ); - const indexFile = await renderIndexTemplate(pluralizedDirNames); + const indexFile = renderIndexTemplate(pluralizedDirNames); writeFileSync(join(config.output, 'index.ts'), indexFile); } diff --git a/packages/fuels/src/cli/commands/deploy/deployContracts.ts b/packages/fuels/src/cli/commands/deploy/deployContracts.ts index a7c6da13d2b..d207e82151d 100644 --- a/packages/fuels/src/cli/commands/deploy/deployContracts.ts +++ b/packages/fuels/src/cli/commands/deploy/deployContracts.ts @@ -17,7 +17,7 @@ import { type ForcToml, } from '../../config/forcUtils'; import type { FuelsConfig, DeployedContract } from '../../types'; -import { debug, log } from '../../utils/logger'; +import { debug } from '../../utils/logger'; import { createWallet } from './createWallet'; import { getDeployConfig } from './getDeployConfig'; @@ -138,8 +138,6 @@ export async function deployContracts(config: FuelsConfig) { const wallet = await createWallet(config.providerUrl, config.privateKey); - log(`Deploying contracts to: ${wallet.provider.url}`); - const contractsLen = config.contracts.length; for (let i = 0; i < contractsLen; i++) { diff --git a/packages/fuels/src/cli/commands/dev/index.test.ts b/packages/fuels/src/cli/commands/dev/index.test.ts index f950daff5b4..dd3982a5718 100644 --- a/packages/fuels/src/cli/commands/dev/index.test.ts +++ b/packages/fuels/src/cli/commands/dev/index.test.ts @@ -65,7 +65,10 @@ describe('dev', () => { const { log } = mockLogger(); const { build, deploy } = mockAll(); - await workspaceFileChanged({ config: fuelsConfig, watchHandlers: [] })('event', 'some/path'); + await workspaceFileChanged({ config: fuelsConfig, watchHandlers: [], filesBeingProcessed: [] })( + 'event', + 'some/path' + ); expect(log).toHaveBeenCalledTimes(1); expect(build).toHaveBeenCalledTimes(1); @@ -127,7 +130,10 @@ describe('dev', () => { const close = vi.fn(); const watchHandlers = [{ close }, { close }] as unknown as FSWatcher[]; - await configFileChanged({ config, fuelCore, watchHandlers })('event', 'some/path'); + await configFileChanged({ config, fuelCore, watchHandlers, filesBeingProcessed: [] })( + 'event', + 'some/path' + ); // configFileChanged() internals expect(log).toHaveBeenCalledTimes(1); @@ -163,7 +169,10 @@ describe('dev', () => { const close = vi.fn(); const watchHandlers = [{ close }, { close }] as unknown as FSWatcher[]; - await configFileChanged({ config, fuelCore, watchHandlers })('event', 'some/path'); + await configFileChanged({ config, fuelCore, watchHandlers, filesBeingProcessed: [] })( + 'event', + 'some/path' + ); // configFileChanged() internals expect(log).toHaveBeenCalledTimes(1); diff --git a/packages/fuels/src/cli/commands/dev/index.ts b/packages/fuels/src/cli/commands/dev/index.ts index bd62eaecbda..afda9ec5904 100644 --- a/packages/fuels/src/cli/commands/dev/index.ts +++ b/packages/fuels/src/cli/commands/dev/index.ts @@ -4,7 +4,7 @@ import { globSync } from 'glob'; import { loadConfig } from '../../config/loadConfig'; import { type FuelsConfig } from '../../types'; -import { error, log } from '../../utils/logger'; +import { debug, error, log } from '../../utils/logger'; import { build } from '../build'; import { deploy } from '../deploy'; import { withConfigErrorHandler } from '../withConfig'; @@ -36,15 +36,27 @@ export type DevState = { config: FuelsConfig; watchHandlers: FSWatcher[]; fuelCore?: FuelCoreNode; + filesBeingProcessed: string[]; }; export const workspaceFileChanged = (state: DevState) => async (_event: string, path: string) => { - log(`\nFile changed: ${path}`); - await buildAndDeploy(state.config); + if (!state.filesBeingProcessed.includes(path)) { + log(`\nFile changed: ${path}`); + try { + state.filesBeingProcessed.push(path); + await buildAndDeploy(state.config); + } catch (err: unknown) { + debug('Error in buildAndDeploy', err); + } finally { + const newState = { ...state }; + newState.filesBeingProcessed = [...state.filesBeingProcessed].filter((p) => p !== path); + Object.assign(state, newState); + } + } }; export const configFileChanged = (state: DevState) => async (_event: string, path: string) => { - log(`\nFile changed: ${path}`); + log(`\nFile changed config: ${path}`); closeAllFileHandlers(state.watchHandlers); state.fuelCore?.killChildProcess(); @@ -79,7 +91,7 @@ export const dev = async (config: FuelsConfig) => { const watchHandlers: FSWatcher[] = []; const options = { persistent: true, ignoreInitial: true, ignored: '**/out/**' }; - const state = { config, watchHandlers, fuelCore }; + const state: DevState = { config, watchHandlers, fuelCore, filesBeingProcessed: [] }; // watch: fuels.config.ts and snapshotDir watchHandlers.push(watch(configFilePaths, options).on('all', configFileChanged(state)));