• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

nightlycommit / rollup-plugin-typescript / 30

27 Dec 2023 09:56AM UTC coverage: 100.0%. Remained the same
30

push

gitlab-ci

Eric MORAND
Merge branch 'bootstrapping' into 'main'

Use the plugin to build itself

See merge request nightlycommit/rollup-plugin-typescript!2

53 of 53 branches covered (100.0%)

Branch coverage included in aggregate %.

96 of 96 relevant lines covered (100.0%)

479.83 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

100.0
/src/lib/plugin.ts
1
import type {Plugin} from "rollup";
2
import {TransformResult} from "rollup";
3
import typeScript from "typescript";
4
import {createFilter} from "@rollup/pluginutils";
5
import {normalize, resolve} from "path";
6
import {CompilationResult, createCompiler} from "./compiler";
7
import {Volume} from "memfs";
8
import {isADeclarationOutputFile} from "./helpers";
9

10
export type FactoryOptions = {
11
    /**
12
     * An instance of TypeScript `CompilerOptions`, minus the properties `inlineSourceMap` and `sourceMap`. Used by the factory to either override the compiler options resolved from the first available `tsconfig.json` file (starting from the current working directory) if any, or as the entire set of compiler options otherwise.
13
     *
14
     * Note that the `inlineSourceMap` and `sourceMap` properties will always be passed as `false` and `true`, respectively, to the underlying TypeScript compiler, in order to guarantee that the plugin is always capable of returning a source map to the Rollup engine.
15
     */
16
    compilerOptions?: Omit<typeScript.CompilerOptions, "inlineSourceMap" | "sourceMap">;
17

18
    /**
19
     * A pattern, or an array of patterns, which specifies the files in the build the plugin should ignore. By default, no files are ignored.
20
     */
21
    exclude?: ReadonlyArray<string | RegExp> | string | RegExp;
22

23
    /**
24
     * A pattern, or an array of patterns, which specifies the files in the build the plugin should operate on. By default, `.ts`, `.cts`, `.mts` and `.tsx` files are targeted.
25
     */
26
    include?: ReadonlyArray<string | RegExp> | string | RegExp;
27
};
28

29
/**
30
 * Returns a newly created instance of [Plugin](https://rollupjs.org/plugin-development/) from the passed options.
31
 *
32
 * @param options
33
 */
34
export const createTypeScriptPlugin = (options: FactoryOptions = {}) => {
1✔
35
    let passedCompilerOptions = options.compilerOptions || {};
45✔
36
    
37
    const configFilePath = typeScript.findConfigFile(process.cwd(), typeScript.sys.fileExists);
45✔
38

39
    const tsConfigFile: {
40
        compilerOptions: typeScript.CompilerOptions
41
    } = configFilePath ? typeScript.readConfigFile(configFilePath, typeScript.sys.readFile).config : {};
45✔
42
    
43
    const parsedCommandLine = typeScript.parseJsonConfigFileContent(
45✔
44
        {
45
            ...tsConfigFile,
46
            compilerOptions: {
47
                ...tsConfigFile.compilerOptions,
48
                ...passedCompilerOptions
49
            }
50
        },
51
        typeScript.sys,
52
        process.cwd()
53
    );
54
    
55
    const compilerOptions: typeScript.CompilerOptions = {
45✔
56
        ...parsedCommandLine.options,
57
        inlineSourceMap: false,
58
        sourceMap: true
59
    };
60
    
61
    const fileSystem = new Volume();
45✔
62
    const compiler = createCompiler(compilerOptions, fileSystem);
45✔
63

64
    const createModuleResolver = () => {
45✔
65
        const cache = typeScript.createModuleResolutionCache(
45✔
66
            process.cwd(),
67
            host.getCanonicalFileName,
68
            compilerOptions
69
        );
70

71
        return (moduleName: string, containingFile: string, redirectedReference?: typeScript.ResolvedProjectReference, mode?: typeScript.ResolutionMode) => {
45✔
72
            const {resolvedModule} = typeScript.resolveModuleName(
124✔
73
                moduleName,
74
                containingFile,
75
                compilerOptions,
76
                typeScript.sys,
77
                cache,
78
                redirectedReference,
79
                mode
80
            );
81

82
            return resolvedModule;
124✔
83
        };
84
    };
85

86
    const host = typeScript.createCompilerHost(compilerOptions);
45✔
87

88
    // options
89
    // @see https://github.com/rollup/plugins/issues/1651#issuecomment-1868495405
90
    options.include = options.include || /\.(cts|mts|ts|tsx)$/;
45✔
91

92
    if (typeof options.include === "string") {
45✔
93
        options.include = [options.include];
1✔
94
    }
95

96
    if (Array.isArray(options.include)) {
45✔
97
        options.include = options.include.map((include) => {
2✔
98
            if (typeof include === "string") {
3✔
99
                return new RegExp(include);
2✔
100
            }
101

102
            return include;
1✔
103
        });
104
    }
105

106
    const filter = createFilter(options.include, options.exclude);
45✔
107
    const resolveModule = createModuleResolver();
45✔
108

109
    let compilationResult: CompilationResult | null;
110

111
    const plugin: Plugin<null> = {
45✔
112
        name: 'typescript',
113

114
        buildStart() {
115
            compilationResult = null;
45✔
116
        },
117

118
        transform(_code, id): TransformResult {
119
            if (!filter(id)) {
164✔
120
                return null;
11✔
121
            }
122

123
            const resolvedId = resolve(id);
153✔
124

125
            if (compilationResult === null) {
153✔
126
                compilationResult = compiler.compile(resolvedId);
41✔
127
            }
128

129
            const errorsToEmit = compilationResult.filter((error) => {
153✔
130
                // if error is a string, this is a global error
131
                return typeof error === "string" || error.file === resolvedId;
12✔
132
            });
133

134
            if (errorsToEmit.length > 0) {
153✔
135
                for (const error of errorsToEmit) {
7✔
136
                    if (typeof error === "string") {
7✔
137
                        this.error(error);
2✔
138
                    }
139
                    else {
140
                        const {column, line, message} = error;
5✔
141

142
                        this.error(message, {
5✔
143
                            column,
144
                            line
145
                        });
146
                    }
147
                }
148
            }
149

150
            const outputFileNames = compiler.getOutputFileNames(resolvedId);
146✔
151

152
            const code = fileSystem.existsSync(outputFileNames.code) && fileSystem.readFileSync(outputFileNames.code);
146✔
153

154
            if (code) {
146✔
155
                const map = fileSystem.existsSync(outputFileNames.code) && fileSystem.readFileSync(outputFileNames.map)!;
143✔
156

157
                return {
143✔
158
                    code: code.toString(),
159
                    map: map.toString()
160
                };
161
            }
162

163
            return null;
3✔
164
        },
165
        resolveId(importee, importer) {
166
            if (importer !== undefined) {
127✔
167
                const containingFile = normalize(importer);
124✔
168

169
                const mode = typeScript.getImpliedNodeFormatForFile(
124✔
170
                    containingFile as any, // todo: https://github.com/microsoft/TypeScript/issues/56852
171
                    undefined,
172
                    typeScript.sys,
173
                    compilerOptions
174
                );
175

176
                const resolved = resolveModule(
124✔
177
                    importee,
178
                    containingFile,
179
                    undefined,
180
                    mode
181
                );
182
                
183
                if (!resolved || isADeclarationOutputFile(resolved.resolvedFileName)) {
124✔
184
                    return null;
2✔
185
                }
186

187
                return normalize(resolve(resolved.resolvedFileName));
122✔
188
            }
189

190
            return null;
3✔
191
        }
192
    };
193

194
    return plugin;
45✔
195
};
196

197
export default createTypeScriptPlugin;
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc