gajus / turbowatch

Extremely fast file change detector and task orchestrator for Node.js.
Other
938 stars 23 forks source link

Watchman and symlinks #19

Closed vjpr closed 1 year ago

vjpr commented 1 year ago

I saw your post on watchman and symlinks here: https://github.com/facebook/watchman/issues/105#issuecomment-1469496330

when the goal is to detected when symlinked dependencies change. The lack of symlink support makes Watchman unusable for our use case (monorepo with linked dependencies).

What exactly was the issue you ran into? I am using watchman for a pnpm monorepo just fine.

The symlinks issue is only an issue if you are symlinking outside the monorepo root. And this can be resolved by just manually resolving the symlinks.

If you want to only watch a few packages, and they are "workspace packages" (not third party and source code is in the monorepo, e.g. root/packages/a/node_modules/b -> root/packages/b), you can:

a. traverse the dependency graph to include all workspace packages abs paths b. ...or read the node_modules dir for symlinks and resolve them

I can't remember if watchman will detect the creation of new symlinks if that is what you are looking for.

gajus commented 1 year ago

The symlinks issue is only an issue if you are symlinking outside the monorepo root. And this can be resolved by just manually resolving the symlinks.

That does not align with my experience.

Project structure:

/node_modules/.pnpm/got@11.8.6/node_modules/got
/apps
  contra-api
    node_modules/got@ -> ../../../node_modules/.pnpm/got@11.8.6/node_modules/got
    src/bin/watch.ts

src/bin/watch.ts code:

import path from 'node:path';
import { watch } from 'turbowatch';

void watch({
  project: path.resolve(__dirname, '../..'),
  triggers: [
    {
      expression: [
        'anyof',
        ['allof', ['dirname', 'node_modules'], ['match', '*', 'basename']],
        ['match', '*.ts', 'basename'],
        ['match', '*.graphql', 'basename'],
      ],
      interruptible: true,
      name: 'start-server',
      onChange: async ({ spawn }) => {
        await spawn`tsx ./src/bin/wait.ts`;
        await spawn`tsx ./src/bin/server.ts`;
      },
    },
  ],
});

I am doing:

touch apps/contra-api/node_modules/got/readme.md

and expect that watchman detects the change, but it does not.

The root of the project is /, i.e. all affected paths are within watchman's root.

vjpr commented 1 year ago

https://github.com/facebook/watchman/issues/647

Dot dirs need a special flag.

gajus commented 1 year ago

Wish this would have been documented. Would have saved many hours of debugging.

As far as I can tell, there is no way to pass this as configuration using Node.js interface though?

vjpr commented 1 year ago

They say make it a sibling to glob. Should just be part of the query. I'd have to check my code.

gajus commented 1 year ago

Unfortunately, no luck.

{
  expression: [
    'anyof',
    [
      'allof',
      [ 'dirname', 'node_modules' ],
      [ 'match', '*', 'basename' ]
    ],
    [ 'match', '*.ts', 'basename' ]
  ],
  fields: [ 'name', 'size', 'mtime_ms', 'exists', 'type' ],
  glob: [ '**/*' ],
  glob_includedotfiles: true,
  relative_root: 'apps/contra-api'
}

Fails in the same setup as described above.

gajus commented 1 year ago

Closing this as Watchman team confirmed that it isn't a feature that is currently supported.

vjpr commented 1 year ago

I found this in my code if it helps:

Screenshot 2023-03-20 at 3 38 09 pm

That nested includedotfiles might do the trick.

gajus commented 1 year ago

Will give this a shot.

Now that https://github.com/gajus/turbowatch/pull/22 merged, this could be additional as a fallback backend.