1# -*- bazel-starlark -*- 2load("@builtin//encoding.star", "json") 3load("@builtin//path.star", "path") 4load("@builtin//struct.star", "module") 5 6def _load(ctx, tsconfig_path, loaded): 7 if tsconfig_path in loaded: 8 return loaded[tsconfig_path] 9 tsconfig = json.decode(str(ctx.fs.read(tsconfig_path))) 10 loaded[tsconfig_path] = tsconfig 11 return tsconfig 12 13def _paths(ctx, tsconfig_path, tsconfig, loaded): 14 paths = [tsconfig_path] 15 tsconfig_dir = path.dir(tsconfig_path) 16 if "files" in tsconfig: 17 for file in tsconfig["files"]: 18 paths.append(path.join(tsconfig_dir, file)) 19 if file.endswith(".js"): 20 # Add if d.ts version of the file exists. 21 file_dts = path.join(tsconfig_dir, file[:-2] + "d.ts") 22 if ctx.fs.exists(file_dts): 23 paths.append(file_dts) 24 return paths 25 26def _scan_inputs(ctx, tsconfig_path, tsconfig, loaded, scanned): 27 if tsconfig_path in scanned: 28 return scanned[tsconfig_path] 29 inputs = {} 30 for fname in _paths(ctx, tsconfig_path, tsconfig, loaded): 31 if fname not in inputs: 32 inputs[fname] = True 33 tsconfig_dir = path.dir(tsconfig_path) 34 tsconfig_deps = [ref["path"] for ref in tsconfig.get("references", [])] 35 if "extends" in tsconfig: 36 tsconfig_deps.append(tsconfig["extends"]) 37 for tsconfig_dep in tsconfig_deps: 38 ref_path = path.join(tsconfig_dir, tsconfig_dep) 39 if ref_path not in inputs: 40 inputs[ref_path] = True 41 ref_tsconfig = _load(ctx, ref_path, loaded) 42 for fname in _scan_inputs(ctx, ref_path, ref_tsconfig, loaded, scanned): 43 if fname not in inputs: 44 inputs[fname] = True 45 scanned[tsconfig_path] = inputs.keys() 46 return scanned[tsconfig_path] 47 48def _scandeps(ctx, tsconfig_path, tsconfig): 49 loaded = {tsconfig_path: tsconfig} 50 scanned = {} 51 inputs = _scan_inputs(ctx, tsconfig_path, tsconfig, loaded, scanned) 52 return inputs 53 54tsc = module( 55 "tsc", 56 scandeps = _scandeps, 57) 58