Skip to content

Commit 2b9b161

Browse files
authored
fix: add typescript checking to codebase and fix existing compilation errors (#13)
* Install typescript * Remove stray import * Add mocha types * Update schema-utils * Update loader-utils and add types * Add typing to main loader interface * Add type checking to PR workflow * Remove unnecessary second resolve parameter * Fix bad error throwing call in tests * prettier fix * Add webpack@2 to type checks * Enable strict type checks * Handle undefined `_compiler` value * Explicitly return null from path resolver if no valid resolution found * Check for possible undefined async callback object * Fix additional missing types in main file * Fix typing errors in test file * Add types for chai * Remove unnecessary break statements * Update memory-fs and add types * Handle possible undefined version string in test compilation * Fix remaining type errors in tests * Remove stray comment * Test compilation errors on invalid protobuf input Co-authored-by: Kevin Montag <[email protected]>
1 parent fed52a8 commit 2b9b161

File tree

8 files changed

+856
-115
lines changed

8 files changed

+856
-115
lines changed

.github/workflows/pull_request.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,13 @@ jobs:
3030
# unless we force the legacy SSL provider.
3131
- run: ${{ matrix.node-version == '18.x' && 'NODE_OPTIONS=--openssl-legacy-provider ' || '' }}npm test
3232

33-
lint:
33+
validate:
3434
runs-on: ubuntu-latest
3535
steps:
3636
- uses: actions/checkout@v3
3737
- uses: actions/setup-node@v3
3838
with:
3939
node-version: '16.x'
4040
- run: npm ci
41+
- run: npm run check
4142
- run: npm run lint

index.js

+40-12
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
'use strict';
22

33
const fs = require('fs');
4-
const path = require('path');
54
const pbjs = require('protobufjs/cli').pbjs;
65
const protobuf = require('protobufjs');
76
const tmp = require('tmp-promise');
8-
const validateOptions = require('schema-utils');
7+
const validateOptions = require('schema-utils').validate;
98

109
const getOptions = require('loader-utils').getOptions;
1110

11+
/** @type { Parameters<typeof validateOptions>[0] } */
1212
const schema = {
1313
type: 'object',
1414
properties: {
@@ -25,18 +25,43 @@ const schema = {
2525
additionalProperties: false,
2626
};
2727

28+
/**
29+
* We're supporting multiple webpack versions, so there are several
30+
* different possible structures for the `this` context in our loader
31+
* callback.
32+
*
33+
* The `never` generic in the v5 context sets the return type of
34+
* `getOptions`. Since we're using the deprecated `loader-utils`
35+
* method of fetching options, this should be fine; however, if we
36+
* drop support for older webpack versions, we'll want to define a
37+
* stricter type for the options object.
38+
*
39+
* @typedef { import('webpack').LoaderContext<never> | import('webpack4').loader.LoaderContext | import('webpack3').loader.LoaderContext | import('webpack2').loader.LoaderContext } LoaderContext
40+
*/
41+
42+
/** @type { (this: LoaderContext, source: string) => any } */
2843
module.exports = function (source) {
29-
let callback = this.async();
44+
const callback = this.async();
3045
let self = this;
3146

32-
const paths = this.options
33-
? // For webpack@2 and webpack@3. property loaderContext.options
34-
// was deprecated in webpack@3 and removed in webpack@4.
35-
(this.options.resolve || {}).modules
36-
: // For webpack@4 and webpack@5. The `_compiler` property is
47+
// Explicitly check this case, as the typescript compiler thinks
48+
// it's possible.
49+
if (callback === undefined) {
50+
throw new Error('Failed to request async execution from webpack');
51+
}
52+
53+
const paths =
54+
'options' in this
55+
? // For webpack@2 and webpack@3. property loaderContext.options
56+
// was deprecated in webpack@3 and removed in webpack@4.
57+
(this.options.resolve || {}).modules
58+
: // For webpack@4 and webpack@5. The `_compiler` property is
3759
// deprecated, but still works as of webpack@5.
38-
(this._compiler.options.resolve || {}).modules;
60+
this._compiler
61+
? (this._compiler.options.resolve || {}).modules
62+
: undefined;
3963

64+
/** @type {{ json: boolean, paths: string[], pbjsArgs: string[] }} */
4065
const options = Object.assign(
4166
{
4267
json: false,
@@ -48,19 +73,20 @@ module.exports = function (source) {
4873
},
4974
getOptions(this)
5075
);
51-
validateOptions(schema, options, 'protobufjs-loader');
76+
validateOptions(schema, options, { name: 'protobufjs-loader' });
5277

78+
/** @type { string } */
5379
let filename;
5480
tmp
5581
.file()
5682
.then(function (o) {
5783
filename = o.path;
5884
return new Promise(function (resolve, reject) {
59-
fs.write(o.fd, source, function (err, bytesWritten, buffer) {
85+
fs.write(o.fd, source, function (err, bytesWritten, _buffer) {
6086
if (err) {
6187
reject(err);
6288
} else {
63-
resolve(bytesWritten, buffer);
89+
resolve(bytesWritten);
6490
}
6591
});
6692
});
@@ -104,6 +130,8 @@ module.exports = function (source) {
104130
return iresolved;
105131
}
106132
}
133+
134+
return null;
107135
};
108136
protobuf.load(filename, root, function (err, result) {
109137
if (err) {

0 commit comments

Comments
 (0)