dlintr 0.0.0 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +45 -5
- package/hadolint.wasm +0 -0
- package/lib/api.d.ts +8 -0
- package/lib/api.js +37 -0
- package/lib/api.js.map +1 -0
- package/lib/browser.d.ts +6 -0
- package/lib/browser.js +7 -0
- package/lib/browser.js.map +1 -0
- package/lib/index.cjs +234 -2
- package/lib/index.d.ts +6 -2
- package/lib/index.js +6 -1
- package/lib/index.js.map +1 -1
- package/lib/runtime.d.ts +6 -0
- package/lib/runtime.js +3 -0
- package/lib/runtime.js.map +1 -0
- package/lib/types.d.ts +24 -0
- package/lib/types.js +2 -0
- package/lib/types.js.map +1 -0
- package/lib/wasi-browser.d.ts +2 -0
- package/lib/wasi-browser.js +48 -0
- package/lib/wasi-browser.js.map +1 -0
- package/lib/wasi-node.d.ts +2 -0
- package/lib/wasi-node.js +127 -0
- package/lib/wasi-node.js.map +1 -0
- package/package.json +75 -38
package/README.md
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
[](https://github.com/wasmio/dlintr/actions/workflows/ci.yml)
|
|
4
4
|
[](https://codecov.io/gh/wasmio/dlintr)
|
|
5
5
|
[](https://lgtm.com/projects/g/wasmio/dlintr/context:javascript)
|
|
6
|
-
[](https://github.com/plantain-00/type-coverage)
|
|
7
7
|
[](https://www.npmjs.com/package/dlintr)
|
|
8
8
|
[](https://github.com/wasmio/dlintr/releases)
|
|
9
9
|
|
|
@@ -13,13 +13,14 @@
|
|
|
13
13
|
[](https://github.com/prettier/prettier)
|
|
14
14
|
[](https://github.com/changesets/changesets)
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
Dockerfile linter, validate inline bash, powered by [`hadolint`](https://github.com/hadolint/hadolint) with WASM
|
|
17
17
|
|
|
18
18
|
## TOC <!-- omit in toc -->
|
|
19
19
|
|
|
20
20
|
- [Usage](#usage)
|
|
21
21
|
- [Install](#install)
|
|
22
22
|
- [API](#api)
|
|
23
|
+
- [How it works](#how-it-works)
|
|
23
24
|
- [Sponsors](#sponsors)
|
|
24
25
|
- [Backers](#backers)
|
|
25
26
|
- [Changelog](#changelog)
|
|
@@ -40,14 +41,50 @@ yarn add dlintr
|
|
|
40
41
|
npm i dlintr
|
|
41
42
|
```
|
|
42
43
|
|
|
44
|
+
Requires Node.js 20.1+ for the built-in [`node:wasi`][node-wasi].
|
|
45
|
+
|
|
43
46
|
### API
|
|
44
47
|
|
|
45
48
|
```js
|
|
46
|
-
import
|
|
47
|
-
|
|
48
|
-
|
|
49
|
+
import { getVersion, lint, run } from 'dlintr'
|
|
50
|
+
|
|
51
|
+
// Lint Dockerfile content and get the findings back.
|
|
52
|
+
const results = await lint('FROM ubuntu:latest\nRUN apt-get update\n')
|
|
53
|
+
// [
|
|
54
|
+
// { code: 'DL3007', line: 1, column: 1, level: 'warning', file: '-', message: '…' },
|
|
55
|
+
// { code: 'DL3009', line: 2, column: 1, level: 'info', file: '-', message: '…' },
|
|
56
|
+
// ]
|
|
57
|
+
|
|
58
|
+
await lint('FROM alpine:3.20\n', {
|
|
59
|
+
ignore: ['DL3009'], // rule codes to suppress
|
|
60
|
+
severityOverrides: { DL3007: 'error' }, // re-level a single rule
|
|
61
|
+
env: { HADOLINT_TRUSTED_REGISTRIES: 'docker.io' }, // anything hadolint reads
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
await getVersion() // 'Haskell Dockerfile Linter 3.0.0'
|
|
65
|
+
|
|
66
|
+
// Or drive the CLI directly, for options `lint` does not model.
|
|
67
|
+
const { exitCode, stdout, stderr } = await run(
|
|
68
|
+
['--no-color', '--failure-threshold', 'error', '-'],
|
|
69
|
+
{
|
|
70
|
+
stdin: 'FROM ubuntu:latest\n',
|
|
71
|
+
},
|
|
72
|
+
)
|
|
49
73
|
```
|
|
50
74
|
|
|
75
|
+
An unparseable Dockerfile is reported, not thrown: hadolint returns it as a `DL1000` finding with `level: 'error'`. Anything that stops hadolint before linting — a rejected option, for instance — is thrown, since it would otherwise be indistinguishable from a clean Dockerfile.
|
|
76
|
+
|
|
77
|
+
`lint` returns findings and drops the exit code. To gate CI, either look at `level`, or use `run` with `--failure-threshold` and check `exitCode`.
|
|
78
|
+
|
|
79
|
+
### How it works
|
|
80
|
+
|
|
81
|
+
[`hadolint`][hadolint] is compiled to WASI with the GHC backend and executed in-process; there is no native binary and no Docker.
|
|
82
|
+
|
|
83
|
+
- **Node** drives it with the built-in `node:wasi`, so there is nothing to install.
|
|
84
|
+
- **Browsers** get [`@bjorn3/browser_wasi_shim`][bjorn3] (~29 kB minified) through the `browser` export condition. It is an optional peer dependency — install it if you target the browser, and Node users never pay for it.
|
|
85
|
+
|
|
86
|
+
The Dockerfile is fed over stdin, which is why no filesystem has to be mounted: only what you pass to `lint`/`run` is ever visible to the linter, and it cannot read files from the host.
|
|
87
|
+
|
|
51
88
|
## Sponsors
|
|
52
89
|
|
|
53
90
|
| 1stG | RxTS | UnTS |
|
|
@@ -71,5 +108,8 @@ Detailed changes for each release are documented in [CHANGELOG.md](./CHANGELOG.m
|
|
|
71
108
|
[MIT][] © [JounQin][]@[1stG.me][]
|
|
72
109
|
|
|
73
110
|
[1stg.me]: https://www.1stg.me
|
|
111
|
+
[bjorn3]: https://github.com/bjorn3/browser_wasi_shim
|
|
112
|
+
[hadolint]: https://github.com/hadolint/hadolint
|
|
74
113
|
[jounqin]: https://GitHub.com/JounQin
|
|
75
114
|
[mit]: http://opensource.org/licenses/MIT
|
|
115
|
+
[node-wasi]: https://nodejs.org/api/wasi.html
|
package/hadolint.wasm
ADDED
|
Binary file
|
package/lib/api.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { WasiRuntime } from './runtime.js';
|
|
2
|
+
import type { LintOptions, LintResult, RunOptions, RunResult } from './types.js';
|
|
3
|
+
export interface Dlinter {
|
|
4
|
+
run: (args: string[], options?: RunOptions) => Promise<RunResult>;
|
|
5
|
+
lint: (dockerfile: string, options?: LintOptions) => Promise<LintResult[]>;
|
|
6
|
+
getVersion: () => Promise<string>;
|
|
7
|
+
}
|
|
8
|
+
export declare const createDlinter: (runtime: WasiRuntime) => Dlinter;
|
package/lib/api.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export const createDlinter = (runtime) => {
|
|
2
|
+
let version;
|
|
3
|
+
return {
|
|
4
|
+
run: runtime.run,
|
|
5
|
+
lint: async (dockerfile, options = {}) => {
|
|
6
|
+
const args = ['--format', 'json'];
|
|
7
|
+
for (const code of options.ignore ?? []) {
|
|
8
|
+
args.push('--ignore', code);
|
|
9
|
+
}
|
|
10
|
+
for (const [code, level] of Object.entries(options.severityOverrides ?? {})) {
|
|
11
|
+
if (level) {
|
|
12
|
+
args.push(`--${level}`, code);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
args.push('-');
|
|
16
|
+
const { stdout, stderr } = await runtime.run(args, {
|
|
17
|
+
stdin: dockerfile,
|
|
18
|
+
env: options.env,
|
|
19
|
+
});
|
|
20
|
+
if (!stdout) {
|
|
21
|
+
if (stderr) {
|
|
22
|
+
throw new Error(stderr.trim());
|
|
23
|
+
}
|
|
24
|
+
return [];
|
|
25
|
+
}
|
|
26
|
+
return JSON.parse(stdout);
|
|
27
|
+
},
|
|
28
|
+
getVersion: () => (version ??= runtime
|
|
29
|
+
.run(['--version'])
|
|
30
|
+
.then(({ stdout }) => stdout.trim())
|
|
31
|
+
.catch((error) => {
|
|
32
|
+
version = undefined;
|
|
33
|
+
throw error;
|
|
34
|
+
})),
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=api.js.map
|
package/lib/api.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AAwBA,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,OAAoB,EAAW,EAAE;IAC7D,IAAI,OAAoC,CAAA;IAExC,OAAO;QACL,GAAG,EAAE,OAAO,CAAC,GAAG;QAEhB,IAAI,EAAE,KAAK,EACT,UAAkB,EAClB,OAAO,GAAgB,EAAE,EACF,EAAE;YACzB,MAAM,IAAI,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,CAAA;YACjC,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;gBACxC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAA;YAC7B,CAAC;YACD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CACxC,OAAO,CAAC,iBAAiB,IAAI,EAAE,CAChC,EAAE,CAAC;gBACF,IAAI,KAAK,EAAE,CAAC;oBACV,IAAI,CAAC,IAAI,CAAC,KAAK,KAAK,EAAE,EAAE,IAAI,CAAC,CAAA;gBAC/B,CAAC;YACH,CAAC;YACD,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YAEd,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE;gBACjD,KAAK,EAAE,UAAU;gBACjB,GAAG,EAAE,OAAO,CAAC,GAAG;aACjB,CAAC,CAAA;YAKF,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,IAAI,MAAM,EAAE,CAAC;oBACX,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAA;gBAChC,CAAC;gBACD,OAAO,EAAE,CAAA;YACX,CAAC;YACD,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAiB,CAAA;QAC3C,CAAC;QAED,UAAU,EAAE,GAAG,EAAE,CACf,CAAC,OAAO,KAAK,OAAO;aACjB,GAAG,CAAC,CAAC,WAAW,CAAC,CAAC;aAClB,IAAI,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;aACnC,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;YAExB,OAAO,GAAG,SAAS,CAAA;YACnB,MAAM,KAAK,CAAA;QACb,CAAC,CAAC,CAAC;KACR,CAAA;AACH,CAAC,CAAA"}
|
package/lib/browser.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export declare const run: (args: string[], options?: import("./types.js").RunOptions) => Promise<import("./types.js").RunResult>;
|
|
2
|
+
export declare const lint: (dockerfile: string, options?: import("./types.js").LintOptions) => Promise<import("./types.js").LintResult[]>;
|
|
3
|
+
export declare const getVersion: () => Promise<string>;
|
|
4
|
+
export type { Dlinter } from './api.js';
|
|
5
|
+
export type { WasiRuntime } from './runtime.js';
|
|
6
|
+
export type { LintOptions, LintResult, OutputFormat, RunOptions, RunResult, Severity, } from './types.js';
|
package/lib/browser.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { createDlinter } from './api.js';
|
|
2
|
+
import { createBrowserRuntime } from './wasi-browser.js';
|
|
3
|
+
const dlinter = createDlinter(createBrowserRuntime());
|
|
4
|
+
export const run = dlinter.run;
|
|
5
|
+
export const lint = dlinter.lint;
|
|
6
|
+
export const getVersion = dlinter.getVersion;
|
|
7
|
+
//# sourceMappingURL=browser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"browser.js","sourceRoot":"","sources":["../src/browser.ts"],"names":[],"mappings":"AAWA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AAExD,MAAM,OAAO,GAAG,aAAa,CAAC,oBAAoB,EAAE,CAAC,CAAA;AAErD,MAAM,CAAC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAA;AAC9B,MAAM,CAAC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAA;AAChC,MAAM,CAAC,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAA"}
|
package/lib/index.cjs
CHANGED
|
@@ -1,5 +1,237 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
3
|
+
var node_fs = require('node:fs');
|
|
4
|
+
var promises = require('node:fs/promises');
|
|
5
|
+
var node_os = require('node:os');
|
|
6
|
+
var path = require('node:path');
|
|
7
|
+
var node_url = require('node:url');
|
|
8
|
+
var node_wasi = require('node:wasi');
|
|
4
9
|
|
|
5
|
-
|
|
10
|
+
var __async$1 = (__this, __arguments, generator) => {
|
|
11
|
+
return new Promise((resolve, reject) => {
|
|
12
|
+
var fulfilled = (value) => {
|
|
13
|
+
try {
|
|
14
|
+
step(generator.next(value));
|
|
15
|
+
} catch (e) {
|
|
16
|
+
reject(e);
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
var rejected = (value) => {
|
|
20
|
+
try {
|
|
21
|
+
step(generator.throw(value));
|
|
22
|
+
} catch (e) {
|
|
23
|
+
reject(e);
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
27
|
+
step((generator = generator.apply(__this, __arguments)).next());
|
|
28
|
+
});
|
|
29
|
+
};
|
|
30
|
+
const createDlinter = (runtime) => {
|
|
31
|
+
let version;
|
|
32
|
+
return {
|
|
33
|
+
run: runtime.run,
|
|
34
|
+
lint: (_0, ..._1) => __async$1(null, [_0, ..._1], function* (dockerfile, options = {}) {
|
|
35
|
+
var _a, _b;
|
|
36
|
+
const args = ["--format", "json"];
|
|
37
|
+
for (const code of (_a = options.ignore) != null ? _a : []) {
|
|
38
|
+
args.push("--ignore", code);
|
|
39
|
+
}
|
|
40
|
+
for (const [code, level] of Object.entries(
|
|
41
|
+
(_b = options.severityOverrides) != null ? _b : {}
|
|
42
|
+
)) {
|
|
43
|
+
if (level) {
|
|
44
|
+
args.push(`--${level}`, code);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
args.push("-");
|
|
48
|
+
const { stdout, stderr } = yield runtime.run(args, {
|
|
49
|
+
stdin: dockerfile,
|
|
50
|
+
env: options.env
|
|
51
|
+
});
|
|
52
|
+
if (!stdout) {
|
|
53
|
+
if (stderr) {
|
|
54
|
+
throw new Error(stderr.trim());
|
|
55
|
+
}
|
|
56
|
+
return [];
|
|
57
|
+
}
|
|
58
|
+
return JSON.parse(stdout);
|
|
59
|
+
}),
|
|
60
|
+
getVersion: () => version != null ? version : version = runtime.run(["--version"]).then(({ stdout }) => stdout.trim()).catch((error) => {
|
|
61
|
+
version = void 0;
|
|
62
|
+
throw error;
|
|
63
|
+
})
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
const HADOLINT = "hadolint";
|
|
68
|
+
const DEFAULT_ENV = { HOME: "/" };
|
|
69
|
+
|
|
70
|
+
var __defProp = Object.defineProperty;
|
|
71
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
72
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
73
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
74
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
75
|
+
var __spreadValues = (a, b) => {
|
|
76
|
+
for (var prop in b || (b = {}))
|
|
77
|
+
if (__hasOwnProp.call(b, prop))
|
|
78
|
+
__defNormalProp(a, prop, b[prop]);
|
|
79
|
+
if (__getOwnPropSymbols)
|
|
80
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
81
|
+
if (__propIsEnum.call(b, prop))
|
|
82
|
+
__defNormalProp(a, prop, b[prop]);
|
|
83
|
+
}
|
|
84
|
+
return a;
|
|
85
|
+
};
|
|
86
|
+
var __async = (__this, __arguments, generator) => {
|
|
87
|
+
return new Promise((resolve, reject) => {
|
|
88
|
+
var fulfilled = (value) => {
|
|
89
|
+
try {
|
|
90
|
+
step(generator.next(value));
|
|
91
|
+
} catch (e) {
|
|
92
|
+
reject(e);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
var rejected = (value) => {
|
|
96
|
+
try {
|
|
97
|
+
step(generator.throw(value));
|
|
98
|
+
} catch (e) {
|
|
99
|
+
reject(e);
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
103
|
+
step((generator = generator.apply(__this, __arguments)).next());
|
|
104
|
+
});
|
|
105
|
+
};
|
|
106
|
+
const import_meta = {};
|
|
107
|
+
const packageRoot = () => typeof __dirname === "string" ? path.join(__dirname, "..") : node_url.fileURLToPath(new URL("..", import_meta.url));
|
|
108
|
+
const wasmPath = () => path.join(packageRoot(), "hadolint.wasm");
|
|
109
|
+
const encoder = new TextEncoder();
|
|
110
|
+
const decoder = new TextDecoder();
|
|
111
|
+
let compiled;
|
|
112
|
+
const load = () => {
|
|
113
|
+
compiled != null ? compiled : compiled = promises.readFile(wasmPath()).then((bytes) => WebAssembly.compile(bytes)).catch((error) => {
|
|
114
|
+
compiled = void 0;
|
|
115
|
+
throw error;
|
|
116
|
+
});
|
|
117
|
+
return compiled;
|
|
118
|
+
};
|
|
119
|
+
const IOVEC_SIZE = 8;
|
|
120
|
+
const IOVEC_LENGTH_OFFSET = 4;
|
|
121
|
+
const intercept = (imports, memory, stdin) => {
|
|
122
|
+
const state = { stdout: "", stderr: "" };
|
|
123
|
+
let offset = 0;
|
|
124
|
+
const views = () => {
|
|
125
|
+
const buffer = memory();
|
|
126
|
+
return { view: new DataView(buffer), bytes: new Uint8Array(buffer) };
|
|
127
|
+
};
|
|
128
|
+
const iovecs = (iovs, iovsLen) => {
|
|
129
|
+
const { view } = views();
|
|
130
|
+
const result = [];
|
|
131
|
+
for (let index = 0; index < iovsLen; index++) {
|
|
132
|
+
result.push({
|
|
133
|
+
offset: view.getUint32(iovs + index * IOVEC_SIZE, true),
|
|
134
|
+
length: view.getUint32(
|
|
135
|
+
iovs + index * IOVEC_SIZE + IOVEC_LENGTH_OFFSET,
|
|
136
|
+
true
|
|
137
|
+
)
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
return result;
|
|
141
|
+
};
|
|
142
|
+
imports.fd_read = (_fd, iovs, iovsLen, nreadPtr) => {
|
|
143
|
+
const { view, bytes } = views();
|
|
144
|
+
let read = 0;
|
|
145
|
+
for (const { offset: target, length } of iovecs(iovs, iovsLen)) {
|
|
146
|
+
const size = Math.min(length, stdin.length - offset);
|
|
147
|
+
if (size <= 0) {
|
|
148
|
+
break;
|
|
149
|
+
}
|
|
150
|
+
bytes.set(stdin.subarray(offset, offset + size), target);
|
|
151
|
+
offset += size;
|
|
152
|
+
read += size;
|
|
153
|
+
}
|
|
154
|
+
view.setUint32(nreadPtr, read, true);
|
|
155
|
+
return 0;
|
|
156
|
+
};
|
|
157
|
+
imports.fd_write = (fd, iovs, iovsLen, nwrittenPtr) => {
|
|
158
|
+
const { view, bytes } = views();
|
|
159
|
+
let written = 0;
|
|
160
|
+
for (const { offset: source, length } of iovecs(iovs, iovsLen)) {
|
|
161
|
+
const chunk = decoder.decode(bytes.subarray(source, source + length));
|
|
162
|
+
if (fd === 1) {
|
|
163
|
+
state.stdout += chunk;
|
|
164
|
+
} else if (fd === 2) {
|
|
165
|
+
state.stderr += chunk;
|
|
166
|
+
}
|
|
167
|
+
written += length;
|
|
168
|
+
}
|
|
169
|
+
view.setUint32(nwrittenPtr, written, true);
|
|
170
|
+
return 0;
|
|
171
|
+
};
|
|
172
|
+
return state;
|
|
173
|
+
};
|
|
174
|
+
const memoryOf = (instance) => instance.exports.memory.buffer;
|
|
175
|
+
const openStdio = () => ({
|
|
176
|
+
stdin: node_fs.openSync(node_os.devNull, "r"),
|
|
177
|
+
stdout: node_fs.openSync(node_os.devNull, "w"),
|
|
178
|
+
stderr: node_fs.openSync(node_os.devNull, "w")
|
|
179
|
+
});
|
|
180
|
+
const closeQuietly = (fd) => {
|
|
181
|
+
try {
|
|
182
|
+
node_fs.closeSync(fd);
|
|
183
|
+
} catch (e) {
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
const closeStdio = (stdio) => {
|
|
187
|
+
closeQuietly(stdio.stdin);
|
|
188
|
+
closeQuietly(stdio.stdout);
|
|
189
|
+
closeQuietly(stdio.stderr);
|
|
190
|
+
};
|
|
191
|
+
const createNodeRuntime = () => ({
|
|
192
|
+
run: (_0, ..._1) => __async(null, [_0, ..._1], function* (args, options = {}) {
|
|
193
|
+
var _a;
|
|
194
|
+
const module = yield load();
|
|
195
|
+
const stdio = openStdio();
|
|
196
|
+
let instance;
|
|
197
|
+
try {
|
|
198
|
+
const wasi = new node_wasi.WASI({
|
|
199
|
+
version: "preview1",
|
|
200
|
+
args: [HADOLINT, ...args],
|
|
201
|
+
env: __spreadValues(__spreadValues({}, DEFAULT_ENV), options.env),
|
|
202
|
+
stdin: stdio.stdin,
|
|
203
|
+
stdout: stdio.stdout,
|
|
204
|
+
stderr: stdio.stderr
|
|
205
|
+
});
|
|
206
|
+
const nodeWasi = wasi;
|
|
207
|
+
const intercepted = intercept(
|
|
208
|
+
nodeWasi.wasiImport,
|
|
209
|
+
() => {
|
|
210
|
+
if (!instance) {
|
|
211
|
+
throw new Error(
|
|
212
|
+
"dlintr: hadolint touched stdio before it was instantiated"
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
return memoryOf(instance);
|
|
216
|
+
},
|
|
217
|
+
encoder.encode((_a = options.stdin) != null ? _a : "")
|
|
218
|
+
);
|
|
219
|
+
instance = yield WebAssembly.instantiate(module, {
|
|
220
|
+
wasi_snapshot_preview1: nodeWasi.wasiImport
|
|
221
|
+
});
|
|
222
|
+
const exitCode = nodeWasi.start(instance);
|
|
223
|
+
return __spreadValues({ exitCode: exitCode != null ? exitCode : 0 }, intercepted);
|
|
224
|
+
} finally {
|
|
225
|
+
closeStdio(stdio);
|
|
226
|
+
}
|
|
227
|
+
})
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
const dlinter = createDlinter(createNodeRuntime());
|
|
231
|
+
const run = dlinter.run;
|
|
232
|
+
const lint = dlinter.lint;
|
|
233
|
+
const getVersion = dlinter.getVersion;
|
|
234
|
+
|
|
235
|
+
exports.getVersion = getVersion;
|
|
236
|
+
exports.lint = lint;
|
|
237
|
+
exports.run = run;
|
package/lib/index.d.ts
CHANGED
|
@@ -1,2 +1,6 @@
|
|
|
1
|
-
declare const
|
|
2
|
-
export
|
|
1
|
+
export declare const run: (args: string[], options?: import("./types.js").RunOptions) => Promise<import("./types.js").RunResult>;
|
|
2
|
+
export declare const lint: (dockerfile: string, options?: import("./types.js").LintOptions) => Promise<import("./types.js").LintResult[]>;
|
|
3
|
+
export declare const getVersion: () => Promise<string>;
|
|
4
|
+
export type { Dlinter } from './api.js';
|
|
5
|
+
export type { WasiRuntime } from './runtime.js';
|
|
6
|
+
export type { LintOptions, LintResult, OutputFormat, RunOptions, RunResult, Severity, } from './types.js';
|
package/lib/index.js
CHANGED
|
@@ -1,2 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
import { createDlinter } from './api.js';
|
|
2
|
+
import { createNodeRuntime } from './wasi-node.js';
|
|
3
|
+
const dlinter = createDlinter(createNodeRuntime());
|
|
4
|
+
export const run = dlinter.run;
|
|
5
|
+
export const lint = dlinter.lint;
|
|
6
|
+
export const getVersion = dlinter.getVersion;
|
|
2
7
|
//# sourceMappingURL=index.js.map
|
package/lib/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAA;AACxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAA;AAElD,MAAM,OAAO,GAAG,aAAa,CAAC,iBAAiB,EAAE,CAAC,CAAA;AAElD,MAAM,CAAC,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAA;AAC9B,MAAM,CAAC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAA;AAChC,MAAM,CAAC,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,CAAA"}
|
package/lib/runtime.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { RunOptions, RunResult } from './types.js';
|
|
2
|
+
export interface WasiRuntime {
|
|
3
|
+
run: (args: string[], options?: RunOptions) => Promise<RunResult>;
|
|
4
|
+
}
|
|
5
|
+
export declare const HADOLINT = "hadolint";
|
|
6
|
+
export declare const DEFAULT_ENV: Readonly<Record<string, string>>;
|
package/lib/runtime.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../src/runtime.ts"],"names":[],"mappings":"AAeA,MAAM,CAAC,MAAM,QAAQ,GAAG,UAAU,CAAA;AAQlC,MAAM,CAAC,MAAM,WAAW,GAAqC,EAAE,IAAI,EAAE,GAAG,EAAE,CAAA"}
|
package/lib/types.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export type Severity = 'error' | 'info' | 'style' | 'warning';
|
|
2
|
+
export type OutputFormat = 'checkstyle' | 'codacy' | 'codeclimate' | 'gitlab_codeclimate' | 'gnu' | 'json' | 'sarif' | 'sonarqube' | 'tty';
|
|
3
|
+
export interface LintResult {
|
|
4
|
+
code: string;
|
|
5
|
+
line: number;
|
|
6
|
+
column: number;
|
|
7
|
+
level: Severity;
|
|
8
|
+
message: string;
|
|
9
|
+
file: string;
|
|
10
|
+
}
|
|
11
|
+
export interface RunResult {
|
|
12
|
+
exitCode: number;
|
|
13
|
+
stdout: string;
|
|
14
|
+
stderr: string;
|
|
15
|
+
}
|
|
16
|
+
export interface RunOptions {
|
|
17
|
+
stdin?: string;
|
|
18
|
+
env?: Record<string, string>;
|
|
19
|
+
}
|
|
20
|
+
export interface LintOptions {
|
|
21
|
+
ignore?: string[];
|
|
22
|
+
severityOverrides?: Partial<Record<string, Severity>>;
|
|
23
|
+
env?: Record<string, string>;
|
|
24
|
+
}
|
package/lib/types.js
ADDED
package/lib/types.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { ConsoleStdout, File, OpenFile, WASI } from '@bjorn3/browser_wasi_shim';
|
|
2
|
+
import { DEFAULT_ENV, HADOLINT } from './runtime.js';
|
|
3
|
+
const WASM_URL = new URL('../hadolint.wasm', import.meta.url);
|
|
4
|
+
const encoder = new TextEncoder();
|
|
5
|
+
let compiled;
|
|
6
|
+
const load = () => {
|
|
7
|
+
compiled ??= fetch(WASM_URL)
|
|
8
|
+
.then(response => {
|
|
9
|
+
if (!response.ok) {
|
|
10
|
+
throw new Error(`failed to fetch ${WASM_URL.pathname}: ${response.status} ${response.statusText}`);
|
|
11
|
+
}
|
|
12
|
+
return response.arrayBuffer();
|
|
13
|
+
})
|
|
14
|
+
.then(buffer => WebAssembly.compile(buffer))
|
|
15
|
+
.catch((error) => {
|
|
16
|
+
compiled = undefined;
|
|
17
|
+
throw error;
|
|
18
|
+
});
|
|
19
|
+
return compiled;
|
|
20
|
+
};
|
|
21
|
+
export const createBrowserRuntime = () => ({
|
|
22
|
+
run: async (args, options = {}) => {
|
|
23
|
+
const module = await load();
|
|
24
|
+
let stdout = '';
|
|
25
|
+
let stderr = '';
|
|
26
|
+
const outDecoder = new TextDecoder();
|
|
27
|
+
const errDecoder = new TextDecoder();
|
|
28
|
+
const fds = [
|
|
29
|
+
new OpenFile(new File(encoder.encode(options.stdin ?? ''))),
|
|
30
|
+
new ConsoleStdout(buffer => {
|
|
31
|
+
stdout += outDecoder.decode(buffer, { stream: true });
|
|
32
|
+
}),
|
|
33
|
+
new ConsoleStdout(buffer => {
|
|
34
|
+
stderr += errDecoder.decode(buffer, { stream: true });
|
|
35
|
+
}),
|
|
36
|
+
];
|
|
37
|
+
const env = Object.entries({ ...DEFAULT_ENV, ...options.env }).map(([key, value]) => `${key}=${value}`);
|
|
38
|
+
const wasi = new WASI([HADOLINT, ...args], env, fds, { debug: false });
|
|
39
|
+
const instance = (await WebAssembly.instantiate(module, {
|
|
40
|
+
wasi_snapshot_preview1: wasi.wasiImport,
|
|
41
|
+
}));
|
|
42
|
+
const exitCode = wasi.start(instance);
|
|
43
|
+
stdout += outDecoder.decode();
|
|
44
|
+
stderr += errDecoder.decode();
|
|
45
|
+
return { exitCode, stdout, stderr };
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
//# sourceMappingURL=wasi-browser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wasi-browser.js","sourceRoot":"","sources":["../src/wasi-browser.ts"],"names":[],"mappings":"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"}
|
package/lib/wasi-node.js
ADDED
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import { openSync, closeSync } from 'node:fs';
|
|
2
|
+
import { readFile } from 'node:fs/promises';
|
|
3
|
+
import { devNull } from 'node:os';
|
|
4
|
+
import path from 'node:path';
|
|
5
|
+
import { fileURLToPath } from 'node:url';
|
|
6
|
+
import { WASI } from 'node:wasi';
|
|
7
|
+
import { DEFAULT_ENV, HADOLINT } from './runtime.js';
|
|
8
|
+
const packageRoot = () => typeof __dirname === 'string'
|
|
9
|
+
? path.join(__dirname, '..')
|
|
10
|
+
: fileURLToPath(new URL('..', import.meta.url));
|
|
11
|
+
const wasmPath = () => path.join(packageRoot(), 'hadolint.wasm');
|
|
12
|
+
const encoder = new TextEncoder();
|
|
13
|
+
const decoder = new TextDecoder();
|
|
14
|
+
let compiled;
|
|
15
|
+
const load = () => {
|
|
16
|
+
compiled ??= readFile(wasmPath())
|
|
17
|
+
.then(bytes => WebAssembly.compile(bytes))
|
|
18
|
+
.catch((error) => {
|
|
19
|
+
compiled = undefined;
|
|
20
|
+
throw error;
|
|
21
|
+
});
|
|
22
|
+
return compiled;
|
|
23
|
+
};
|
|
24
|
+
const IOVEC_SIZE = 8;
|
|
25
|
+
const IOVEC_LENGTH_OFFSET = 4;
|
|
26
|
+
const intercept = (imports, memory, stdin) => {
|
|
27
|
+
const state = { stdout: '', stderr: '' };
|
|
28
|
+
let offset = 0;
|
|
29
|
+
const views = () => {
|
|
30
|
+
const buffer = memory();
|
|
31
|
+
return { view: new DataView(buffer), bytes: new Uint8Array(buffer) };
|
|
32
|
+
};
|
|
33
|
+
const iovecs = (iovs, iovsLen) => {
|
|
34
|
+
const { view } = views();
|
|
35
|
+
const result = [];
|
|
36
|
+
for (let index = 0; index < iovsLen; index++) {
|
|
37
|
+
result.push({
|
|
38
|
+
offset: view.getUint32(iovs + index * IOVEC_SIZE, true),
|
|
39
|
+
length: view.getUint32(iovs + index * IOVEC_SIZE + IOVEC_LENGTH_OFFSET, true),
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
return result;
|
|
43
|
+
};
|
|
44
|
+
imports.fd_read = (_fd, iovs, iovsLen, nreadPtr) => {
|
|
45
|
+
const { view, bytes } = views();
|
|
46
|
+
let read = 0;
|
|
47
|
+
for (const { offset: target, length } of iovecs(iovs, iovsLen)) {
|
|
48
|
+
const size = Math.min(length, stdin.length - offset);
|
|
49
|
+
if (size <= 0) {
|
|
50
|
+
break;
|
|
51
|
+
}
|
|
52
|
+
bytes.set(stdin.subarray(offset, offset + size), target);
|
|
53
|
+
offset += size;
|
|
54
|
+
read += size;
|
|
55
|
+
}
|
|
56
|
+
view.setUint32(nreadPtr, read, true);
|
|
57
|
+
return 0;
|
|
58
|
+
};
|
|
59
|
+
imports.fd_write = (fd, iovs, iovsLen, nwrittenPtr) => {
|
|
60
|
+
const { view, bytes } = views();
|
|
61
|
+
let written = 0;
|
|
62
|
+
for (const { offset: source, length } of iovecs(iovs, iovsLen)) {
|
|
63
|
+
const chunk = decoder.decode(bytes.subarray(source, source + length));
|
|
64
|
+
if (fd === 1) {
|
|
65
|
+
state.stdout += chunk;
|
|
66
|
+
}
|
|
67
|
+
else if (fd === 2) {
|
|
68
|
+
state.stderr += chunk;
|
|
69
|
+
}
|
|
70
|
+
written += length;
|
|
71
|
+
}
|
|
72
|
+
view.setUint32(nwrittenPtr, written, true);
|
|
73
|
+
return 0;
|
|
74
|
+
};
|
|
75
|
+
return state;
|
|
76
|
+
};
|
|
77
|
+
const memoryOf = (instance) => instance.exports.memory.buffer;
|
|
78
|
+
const openStdio = () => ({
|
|
79
|
+
stdin: openSync(devNull, 'r'),
|
|
80
|
+
stdout: openSync(devNull, 'w'),
|
|
81
|
+
stderr: openSync(devNull, 'w'),
|
|
82
|
+
});
|
|
83
|
+
const closeQuietly = (fd) => {
|
|
84
|
+
try {
|
|
85
|
+
closeSync(fd);
|
|
86
|
+
}
|
|
87
|
+
catch {
|
|
88
|
+
}
|
|
89
|
+
};
|
|
90
|
+
const closeStdio = (stdio) => {
|
|
91
|
+
closeQuietly(stdio.stdin);
|
|
92
|
+
closeQuietly(stdio.stdout);
|
|
93
|
+
closeQuietly(stdio.stderr);
|
|
94
|
+
};
|
|
95
|
+
export const createNodeRuntime = () => ({
|
|
96
|
+
run: async (args, options = {}) => {
|
|
97
|
+
const module = await load();
|
|
98
|
+
const stdio = openStdio();
|
|
99
|
+
let instance;
|
|
100
|
+
try {
|
|
101
|
+
const wasi = new WASI({
|
|
102
|
+
version: 'preview1',
|
|
103
|
+
args: [HADOLINT, ...args],
|
|
104
|
+
env: { ...DEFAULT_ENV, ...options.env },
|
|
105
|
+
stdin: stdio.stdin,
|
|
106
|
+
stdout: stdio.stdout,
|
|
107
|
+
stderr: stdio.stderr,
|
|
108
|
+
});
|
|
109
|
+
const nodeWasi = wasi;
|
|
110
|
+
const intercepted = intercept(nodeWasi.wasiImport, () => {
|
|
111
|
+
if (!instance) {
|
|
112
|
+
throw new Error('dlintr: hadolint touched stdio before it was instantiated');
|
|
113
|
+
}
|
|
114
|
+
return memoryOf(instance);
|
|
115
|
+
}, encoder.encode(options.stdin ?? ''));
|
|
116
|
+
instance = await WebAssembly.instantiate(module, {
|
|
117
|
+
wasi_snapshot_preview1: nodeWasi.wasiImport,
|
|
118
|
+
});
|
|
119
|
+
const exitCode = nodeWasi.start(instance);
|
|
120
|
+
return { exitCode: exitCode ?? 0, ...intercepted };
|
|
121
|
+
}
|
|
122
|
+
finally {
|
|
123
|
+
closeStdio(stdio);
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
});
|
|
127
|
+
//# sourceMappingURL=wasi-node.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wasi-node.js","sourceRoot":"","sources":["../src/wasi-node.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,56 +1,93 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dlintr",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Dockerfile linter, validate inline bash, powered by hadolint with WASM",
|
|
6
|
-
"repository":
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/wasmio/dlintr.git"
|
|
9
|
+
},
|
|
7
10
|
"author": "JounQin (https://www.1stG.me) <admin@1stg.me>",
|
|
8
11
|
"funding": "https://opencollective.com/unts",
|
|
9
12
|
"license": "MIT",
|
|
10
|
-
"packageManager": "pnpm@7.11.0",
|
|
11
13
|
"engines": {
|
|
12
|
-
"node": "
|
|
14
|
+
"node": ">=20.1.0"
|
|
13
15
|
},
|
|
14
16
|
"exports": {
|
|
15
|
-
"
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
".": {
|
|
18
|
+
"types": "./lib/index.d.ts",
|
|
19
|
+
"browser": "./lib/browser.js",
|
|
20
|
+
"import": "./lib/index.js",
|
|
21
|
+
"require": "./lib/index.cjs"
|
|
22
|
+
},
|
|
23
|
+
"./package.json": "./package.json"
|
|
18
24
|
},
|
|
19
25
|
"files": [
|
|
26
|
+
"hadolint.wasm",
|
|
20
27
|
"lib",
|
|
21
28
|
"!**/*.tsbuildinfo"
|
|
22
29
|
],
|
|
30
|
+
"peerDependencies": {
|
|
31
|
+
"@bjorn3/browser_wasi_shim": "^0.4.2"
|
|
32
|
+
},
|
|
33
|
+
"peerDependenciesMeta": {
|
|
34
|
+
"@bjorn3/browser_wasi_shim": {
|
|
35
|
+
"optional": true
|
|
36
|
+
}
|
|
37
|
+
},
|
|
23
38
|
"dependencies": {
|
|
24
39
|
"tslib": "^2.4.0"
|
|
25
40
|
},
|
|
26
41
|
"devDependencies": {
|
|
27
|
-
"@1stg/app-config": "^
|
|
28
|
-
"@1stg/
|
|
29
|
-
"@
|
|
30
|
-
"@
|
|
31
|
-
"@
|
|
32
|
-
"@
|
|
33
|
-
"@
|
|
34
|
-
"@
|
|
35
|
-
"@
|
|
36
|
-
"@
|
|
37
|
-
"@
|
|
38
|
-
"@
|
|
39
|
-
"@
|
|
42
|
+
"@1stg/app-config": "^15.0.0",
|
|
43
|
+
"@1stg/browserslist-config": "^2.1.4",
|
|
44
|
+
"@1stg/commitlint-config": "^6.0.0",
|
|
45
|
+
"@1stg/eslint-config": "^10.3.0",
|
|
46
|
+
"@1stg/markuplint-config": "^4.0.7",
|
|
47
|
+
"@1stg/nano-staged": "^0.3.1",
|
|
48
|
+
"@1stg/prettier-config": "^5.4.0",
|
|
49
|
+
"@1stg/remark-preset": "^3.2.0",
|
|
50
|
+
"@1stg/simple-git-hooks": "^2.0.0",
|
|
51
|
+
"@1stg/stylelint-config": "^6.2.0",
|
|
52
|
+
"@1stg/tsconfig": "^4.0.0",
|
|
53
|
+
"@bjorn3/browser_wasi_shim": "^0.4.2",
|
|
54
|
+
"@changesets/changelog-github": "^1.0.0",
|
|
55
|
+
"@changesets/cli": "^3.0.0",
|
|
56
|
+
"@commitlint/cli": "^21.2.3",
|
|
57
|
+
"@eslint-react/eslint-plugin": ">=1.0.0",
|
|
58
|
+
"@mdx-js/rollup": "^3.1.1",
|
|
59
|
+
"@pkgr/rollup": "^7.0.0",
|
|
60
|
+
"@types/mdx": "^2.0.3",
|
|
61
|
+
"@types/node": "^24.0.0",
|
|
62
|
+
"@types/react": "^19.0.0",
|
|
63
|
+
"@types/react-dom": "^19.0.0",
|
|
64
|
+
"@typescript/native": "npm:typescript@^7.0.2",
|
|
65
|
+
"@vitejs/plugin-react": "^6.1.2",
|
|
66
|
+
"@vitest/coverage-istanbul": "^5.0.0",
|
|
67
|
+
"@vitest/eslint-plugin": "^1.0.0",
|
|
68
|
+
"browserslist": "^4.28.2",
|
|
40
69
|
"dlintr": "link:.",
|
|
70
|
+
"eslint": "^10.0.0",
|
|
71
|
+
"eslint-formatter-friendly": "^7.0.0",
|
|
72
|
+
"eslint-plugin-react-hooks": ">=5.0.0",
|
|
41
73
|
"github-markdown-css": "^5.1.0",
|
|
42
|
-
"
|
|
43
|
-
"
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
-
"
|
|
74
|
+
"nano-staged": "^1.0.2",
|
|
75
|
+
"npm-run-all": "^4.1.5",
|
|
76
|
+
"prettier": "^3.0.0",
|
|
77
|
+
"react": "^19.0.0",
|
|
78
|
+
"react-dom": "^19.0.0",
|
|
79
|
+
"react-router-dom": "^7.0.0",
|
|
80
|
+
"remark-gfm": "^4.0.1",
|
|
81
|
+
"simple-git-hooks": "^2.14.0",
|
|
82
|
+
"sirv-cli": "^3.0.0",
|
|
83
|
+
"size-limit": "^14.0.0",
|
|
84
|
+
"size-limit-preset-node-lib": "^0.5.1",
|
|
85
|
+
"stylelint": "^17.0.0",
|
|
47
86
|
"type-coverage": "^2.22.0",
|
|
48
|
-
"typescript": "
|
|
49
|
-
"unplugin-auto-import": "^0.
|
|
50
|
-
"
|
|
51
|
-
|
|
52
|
-
"resolutions": {
|
|
53
|
-
"typescript": "~4.7.4"
|
|
87
|
+
"typescript": "npm:@typescript/typescript6@^6.0.2",
|
|
88
|
+
"unplugin-auto-import": "^21.0.0",
|
|
89
|
+
"vite": "^8.3.4",
|
|
90
|
+
"vitest": "^5.0.0"
|
|
54
91
|
},
|
|
55
92
|
"size-limit": [
|
|
56
93
|
{
|
|
@@ -71,22 +108,22 @@
|
|
|
71
108
|
"build": "run-p build:*",
|
|
72
109
|
"build:r": "r -f cjs",
|
|
73
110
|
"build:tsc": "tsc -p src",
|
|
74
|
-
"
|
|
111
|
+
"build:wasm": "node scripts/hadolint-wasm.mjs",
|
|
75
112
|
"dev": "vitest",
|
|
76
|
-
"docs:build": "
|
|
77
|
-
"docs:dev": "
|
|
113
|
+
"docs:build": "vite build docs",
|
|
114
|
+
"docs:dev": "vite docs",
|
|
78
115
|
"lint": "run-p lint:*",
|
|
79
116
|
"lint:es": "eslint . --cache -f friendly --max-warnings 10",
|
|
80
117
|
"lint:style": "stylelint . --cache",
|
|
81
|
-
"lint:tsc": "tsc --noEmit",
|
|
82
|
-
"postversion": "pnpm i --no-frozen-lockfile",
|
|
118
|
+
"lint:tsc": "tsc --noEmit && tsc -p docs --noEmit",
|
|
83
119
|
"prerelease": "pnpm build",
|
|
84
120
|
"release": "changeset publish",
|
|
85
121
|
"serve": "sirv dist -s",
|
|
122
|
+
"pretest": "node scripts/hadolint-wasm.mjs",
|
|
86
123
|
"test": "vitest run --coverage",
|
|
87
124
|
"typecov": "type-coverage",
|
|
88
|
-
"
|
|
89
|
-
"
|
|
125
|
+
"version": "changeset version",
|
|
126
|
+
"postversion": "pnpm i --no-frozen-lockfile"
|
|
90
127
|
},
|
|
91
128
|
"main": "./lib/index.cjs",
|
|
92
129
|
"module": "./lib/index.js",
|