fromNpm static method

Future<InteropProject> fromNpm({
  1. required String package,
  2. required String version,
  3. required String targetPath,
  4. required String dirName,
  5. Iterable<String> files = const [],
  6. ({bool import, bool typings}) packageJson = (typings: true, import: true),
  7. String? contextCheck,
  8. Iterable<String> distFiles = const [],
  9. Iterable<String> uses = const {},
  10. String? targetMainFile,
  11. bool force = false,
  12. bool fetchExternals = true,
})

Implementation

static Future<InteropProject> fromNpm({required String package, required String version, required String targetPath, required String dirName, Iterable<String> files = const [], ({bool typings, bool import}) packageJson = (typings: true, import: true), String? contextCheck, Iterable<String> distFiles = const [], Iterable<String> uses = const {}, String? targetMainFile, bool force = false, bool fetchExternals = true}) async {
  final mainFiles = files.toList();
  final transpiller = Transpiler(package: package, targetPath: targetPath, dirName: dirName, contextCheck: contextCheck, uses: uses, targetMainFile: targetMainFile, distFiles: distFiles.toList());
  final outDir = Directory(transpiller.dir('out/package'));
  final dir = transpiller.dir;
  var crawlTsFiles = false;

  assert(!packageJson.typings || mainFiles.isEmpty, 'Either use packageJson.typings=true or files($mainFiles)');

  assert(!packageJson.import || distFiles.isEmpty, 'Either use packageJson.typings=true or distFiles($distFiles)');

  if (!outDir.existsSync() || force) {
    await Directory(dir()).create(recursive: true);

    // http://registry.npmjs.org/typescript/latest
    final buf = await http.read(Uri(scheme: 'http', host: 'registry.npmjs.org', path: '$package/$version'));
    final map = (conv.json.decode(buf) as Map).cast<String, dynamic>();
    final {'tarball': String tarballUrl} = map.prop<Map>('dist');
    final tarballUri = Uri.parse(tarballUrl);
    final tarballName = basename(tarballUri.path);
    final tarballPath = dir(tarballName);

    final request = await HttpClient().getUrl(tarballUri);
    final response = await request.close();

    await response.pipe(File(tarballPath).openWrite());

    await extractFileToDisk(tarballPath, dir('out'));

    assert(outDir.existsSync());
  }

  if (packageJson.import || packageJson.typings) {
    final pkg = conv.json.decode(File(dir('out/package/package.json')).readAsStringSync()) as Map<String, dynamic>;

    if (packageJson.typings) {
      final typings = pkg.prop<String?>('typings');
      final types = pkg.prop<String?>('types');

      if (typings != null) {
        mainFiles.add(typings);
      } else if (types != null) {
        crawlTsFiles = true;
        mainFiles.add(types);
      } else {
        final useTypesVersions = 1 > 0;

        if (useTypesVersions) {
          final tv = pkg['typesVersions'];

          if (tv case Map rawMap) {
            Iterable<String> digFiles(Map rawMap) sync* {
              final map = rawMap.cast<String, dynamic>();

              for (final value in map.values) {
                if (value is Map) {
                  yield* digFiles(value);
                } else if (value is Iterable) {
                  for (final item in value) {
                    if (item is String) {
                      final paths = {'$item.d.ts', '$item/index.d.ts', '$item/types.d.ts'};

                      for (final path in paths) {
                        if (File(dir('out/package/$path')).existsSync()) {
                          yield path;
                        }
                      }
                    }
                  }
                }
              }
            }

            mainFiles.addAll(digFiles(rawMap).toSet());
          }
        } else {
          final tsFiles = Glob(dir('out/package/**.d.ts'));

          for (final entity in tsFiles.listSync()) {
            mainFiles.add(entity.path.substring(entity.path.indexOf('out/package/') + 'out/package/'.length));
          }
        }
      }
    }

    if (packageJson.import) {
      transpiller.distFiles.add(pkg.prop('main'));
    }
  }

  final fileArgs = <String>[];

  for (final path in mainFiles) {
    if (path.startsWith('https://')) {
      final segs = File(path).uri.normalizePath().pathSegments.toList();
      final fileName = segs.removeLast();
      final dirPath = dir('out/temp/${segs.join('/')}');
      final handle = Directory(dirPath);

      if (!handle.existsSync()) {
        handle.createSync(recursive: true);
      }

      final filePath = '$dirPath/$fileName';
      final fileHandle = File(filePath);

      if (!fileHandle.existsSync()) {
        final request = await HttpClient().getUrl(Uri.parse(path));
        final response = await request.close();

        await response.pipe(fileHandle.openWrite());
      }

      fileArgs.add(filePath);
    } else {
      fileArgs.add('out/package/$path');
    }
  }

  return transpiller._createProject(fileArgs: fileArgs, crawlTsFiles: crawlTsFiles, fetchExternals: fetchExternals);
}