deepkit-framework icon indicating copy to clipboard operation
deepkit-framework copied to clipboard

[Feature] Improve webpack support (ts-loader) breaks type import

Open CristianPi opened this issue 3 years ago • 0 comments

I'm not sure where the problem is, but i have problem with imported types when compiling with webpack.

tsc works

PrivateApiController.__type = ['methods', function () { return {}; }, () => app_1.App, 'moduleRef', () => logger_1.Logger, 'logger', 'constructor', () => __ΩHttpBody, 'data', () => __ΩPrivateApiResponse, 'execute', 'name', 'method', 'args', 'context', 'callController', 'queryOrMutation', 'resolveMethod', () => Object, 'cls', 'controller', 'resolveController', 'P&"LM3!>"PP"7#2$;P7%2&;"0\'P"o("2)n*`0+P&2,&2-"F2."2/8"`00P&2,&2-"21"02P&2,Pi344"45M`065'];

() => logger_1.Logger is set and imported correctly

webpack ts-loader commonjs2 (no cache, no optimization, DisableTreeShakingForChunk(".*") ) breaks

PrivateApiController.__type = ['methods', function () { return {}; }, () => app_1.App, 'moduleRef', 'logger', 'constructor', () => __ΩHttpBody, 'data', () => __ΩPrivateApiResponse, 'execute', 'name', 'method', 'args', 'context', 'callController', 'queryOrMutation', 'resolveMethod', () => Object, 'cls', 'controller', 'resolveController', 'P&"LM3!>"PP"7#2$;!2%;"0&P"o\'"2(n)`0*P&2+&2,"F2-"2.8"`0/P&2+&2,"20"01P&2+Pi243"44M`055'];

With the obvious error as logger is computed as never

DependenciesUnmetError: Undefined dependency "logger: never" of PrivateApiController(✓, ?). Type has no provider in scope http.

This was breaking also deepkit types as

export class BaseEntity {
  // generate the id for the entity server side
  id: MongoId & PrimaryKey = new ObjectID().toString(); // broken PrimaryKey
}

with weird behaviors. #342

Workaround

Build the project with tsc -> TscWebpackPlugin And replace ts-loader with a custom loader.

"./webpack-loader.ts"

import * as path from 'path';
import type * as webpack from 'webpack';
// adapt this line to your tsc out dir/naming
function referToDistJs(name: string) {
  return name.replace('.ts', '.js').replace("/apps/", "/dist/out-tsc/apps/").replace("/libs/", "/dist/out-tsc/libs/")
}

/**
 * The entry point for ts-loader
 */
function loader(this: webpack.LoaderContext<any>, contents: string) {
  this.cacheable && this.cacheable();
  const callback = this.async();
  successLoader(this, contents, callback);
}

function successLoader(
  loaderContext: webpack.LoaderContext<any>,
  contents: string,
  callback: ReturnType<webpack.LoaderContext<any>['async']>
) {
  const rawFilePath = path.normalize(loaderContext.resourcePath);

  const filePath = rawFilePath;
  const realFilePath = referToDistJs(filePath);
  const realMapPath = realFilePath + '.map';

  // load js file and source map from filePath usign syncRead
  loaderContext.fs.readFile(realFilePath,(error,outputText)=>{
    loaderContext.fs.readFile(realMapPath,(error,sourceMapText)=>{

      const {sourceMap, output} = makeSourceMap(
        sourceMapText.toString(),
        outputText.toString(),
        filePath,
        contents,
        loaderContext
      );

      callback(null, output, sourceMap);
    })
  });

}

function makeSourceMap(
  sourceMapText: string | undefined,
  outputText: string,
  filePath: string,
  contents: string,
  loaderContext: webpack.LoaderContext<any>
) {
  if (sourceMapText === undefined) {
    return {output: outputText, sourceMap: undefined};
  }

  return {
    output: outputText.replace(/^\/\/# sourceMappingURL=[^\r\n]*/gm, ''),
    sourceMap: Object.assign(JSON.parse(sourceMapText), {
      sources: [loaderContext.remainingRequest],
      file: filePath,
      sourcesContent: [contents],
    }),
  };
}

export = loader;

CristianPi avatar Aug 11 '22 22:08 CristianPi