0

Question:

How can I take a list of paths to files Array<string>:

// ['apps/morningharwood/src/app/app.component.ts',
//  'apps/morningharwood/src/app/app-shell/app-shell.component.ts']

And for each path, call a static method on them ref.SomeStaticMethod() in node?

Note: I'm using typescript for node (if that matters) AND windows 10.


async function prePublish() {

  const componentPaths = await globby('apps/morningharwood/src/app/**/*.component.ts');
  const dirPaths = componentPaths.map(i => `./${i.split('.ts')[ 0 ]}`);
  console.log(dirPaths);
  /**
   * Logs out this
   * [ './apps/morningharwood/src/app/app.component',
   *   './apps/morningharwood/src/app/app-shell/app-shell.component' ]
   */
  const ref = await import('./apps/morningharwood/src/app/app.component');
  const ref2 = await import('./apps/morningharwood/src/app/app-shell/app-shell.component');
  console.log(ref, ref2); // WORKS AS INTENDED

  for (const dp of dirPaths) {
    console.log(dp); // ./apps/morningharwood/src/app/app.component
    const ref3 = await import(dp); // ERROR?

    console.log(ref); // Never runs.
  }
}
prepublish();

Full error stacktrace:

./apps/morningharwood/src/app/app.component
Unhandled Promise rejection: Cannot find module './apps/morningharwood/src/app/app.component' ; Zone: <root> ; Task: Promise.then ; Value: { Error: Cannot find module './apps/morningharwood/src/app/app.component'
    at webpackEmptyContext (webpack:///._sync?:2:10)
    at eval (webpack:///./prerender.ts?:126:126)
    at ZoneDelegate.invoke (webpack:///./node_modules/zone.js/dist/zone-node.js?:387:26)
    at Zone.run (webpack:///./node_modules/zone.js/dist/zone-node.js?:137:43)
    at eval (webpack:///./node_modules/zone.js/dist/zone-node.js?:871:34)
    at ZoneDelegate.invokeTask (webpack:///./node_modules/zone.js/dist/zone-node.js?:420:31)
    at Zone.runTask (webpack:///./node_modules/zone.js/dist/zone-node.js?:187:47)
    at drainMicroTaskQueue (webpack:///./node_modules/zone.js/dist/zone-node.js?:594:35)
    at ZoneTask.invokeTask (webpack:///./node_modules/zone.js/dist/zone-node.js?:499:21)
    at ZoneTask.invoke (webpack:///./node_modules/zone.js/dist/zone-node.js?:484:48) code: 'MODULE_NOT_FOUND' } Error: Cannot find module './apps/morningharwood/src/app/app.component'
    at webpackEmptyContext (webpack:///._sync?:2:10)
    at eval (webpack:///./prerender.ts?:126:126)
    at ZoneDelegate.invoke (webpack:///./node_modules/zone.js/dist/zone-node.js?:387:26)
    at Zone.run (webpack:///./node_modules/zone.js/dist/zone-node.js?:137:43)
    at eval (webpack:///./node_modules/zone.js/dist/zone-node.js?:871:34)
    at ZoneDelegate.invokeTask (webpack:///./node_modules/zone.js/dist/zone-node.js?:420:31)
    at Zone.runTask (webpack:///./node_modules/zone.js/dist/zone-node.js?:187:47)
    at drainMicroTaskQueue (webpack:///./node_modules/zone.js/dist/zone-node.js?:594:35)
    at ZoneTask.invokeTask (webpack:///./node_modules/zone.js/dist/zone-node.js?:499:21)
    at ZoneTask.invoke (webpack:///./node_modules/zone.js/dist/zone-node.js?:484:48)
Armeen Moon
  • 18,061
  • 35
  • 120
  • 233

1 Answers1

0

Modules paths are resolved relatively to current module, and filesystem paths are resolved relatively to current working directory.

Considering a path was successfully matched by a glob, apps/... is relative to current working directory, likely project root. Relying on current working directory is questionable practice itself. Both glob and module paths could be stated unambiguously for consistency.

It can be either:

  const componentPaths = await globby('../apps/morningharwood/src/app/**/*.component.ts', { cwd: __dirname });
  for (const path of componentPaths) {
    const ref = await import(path.join('./', path));
    ...

Or:

  const componentPaths = await globby(path.join(__dirname, '../apps/morningharwood/src/app/**/*.component.ts'));
  for (const path of componentPaths) {
    const ref = await import(path);
    ...
Estus Flask
  • 206,104
  • 70
  • 425
  • 565
  • Hey estus thanks for the help. I've updated teh bug with more feedback.. I'm still unable to get it to work. Any ideas? – Armeen Moon Aug 11 '18 at 18:30
  • Does `import('./apps/morningharwood/src/app/app.component')` work? The question doesn't mention you use Webpack. This is not a common scenario because usually you don't need it with Node or ts-node in particular. It's expected that dynamic imports won't work with Webpack because bundled modules should be known at build time. – Estus Flask Aug 11 '18 at 19:54
  • Ahh I didn't think webpack was part of the problem. Yeah I'm using webpack. And yes that import does work. I'll refactor and bring this task out of webpack. Is the the best solution? – Armeen Moon Aug 11 '18 at 20:29
  • I'd recommend to ditch Webpack from this setup, unless you're heavily using Webpack-specific features. ES modules will just fall back to Node `require` this way. Otherwise you can use ways that are specific to Webpack, e.g. `require.context` instead of `import`, see https://stackoverflow.com/questions/29421409/how-to-load-all-files-in-a-directory-using-webpack-without-require-statements for example. – Estus Flask Aug 11 '18 at 21:15
  • Yeah, I just ended up ripping out webpack for this part. It doesn't make sense. I have mixed approaches from a previous question https://stackoverflow.com/questions/51797603/get-a-reference-to-all-component-in-an-angular-application-from-a-ssr-bundle?noredirect=1#comment90552556_51797603 I understand now why it doesnt work. I'm marking your answer correct tho. If you wanna update your answer with the above comment context around that would be awesome! Or I can delete this – Armeen Moon Aug 12 '18 at 01:17