dlintr 0.0.0 → 0.1.1

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 CHANGED
@@ -2,8 +2,7 @@
2
2
 
3
3
  [![GitHub Actions](https://github.com/wasmio/dlintr/workflows/CI/badge.svg)](https://github.com/wasmio/dlintr/actions/workflows/ci.yml)
4
4
  [![Codecov](https://img.shields.io/codecov/c/github/wasmio/dlintr.svg)](https://codecov.io/gh/wasmio/dlintr)
5
- [![Language grade: JavaScript](https://img.shields.io/lgtm/grade/javascript/g/wasmio/dlintr.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/wasmio/dlintr/context:javascript)
6
- [![type-coverage](https://img.shields.io/badge/dynamic/json.svg?label=type-coverage&prefix=%E2%89%A5&suffix=%&query=$.typeCoverage.atLeast&uri=https%3A%2F%2Fraw.githubusercontent.com%2Fun-ts%2Flib-boilerplate%2Fmain%2Fpackage.json)](https://github.com/plantain-00/type-coverage)
5
+ [![type-coverage](https://img.shields.io/badge/dynamic/json.svg?label=type-coverage&prefix=%E2%89%A5&suffix=%&query=$.typeCoverage.atLeast&uri=https%3A%2F%2Fraw.githubusercontent.com%2Fwasmio%2Fdlintr%2Fmain%2Fpackage.json)](https://github.com/plantain-00/type-coverage)
7
6
  [![npm](https://img.shields.io/npm/v/dlintr.svg)](https://www.npmjs.com/package/dlintr)
8
7
  [![GitHub Release](https://img.shields.io/github/release/wasmio/dlintr)](https://github.com/wasmio/dlintr/releases)
9
8
 
@@ -13,13 +12,14 @@
13
12
  [![Code Style: Prettier](https://img.shields.io/badge/code_style-prettier-ff69b4.svg)](https://github.com/prettier/prettier)
14
13
  [![changesets](https://img.shields.io/badge/maintained%20with-changesets-176de3.svg)](https://github.com/changesets/changesets)
15
14
 
16
- A simple library boilerplate.
15
+ Dockerfile linter, validate inline bash, powered by [`hadolint`](https://github.com/hadolint/hadolint) with WASM
17
16
 
18
17
  ## TOC <!-- omit in toc -->
19
18
 
20
19
  - [Usage](#usage)
21
20
  - [Install](#install)
22
21
  - [API](#api)
22
+ - [How it works](#how-it-works)
23
23
  - [Sponsors](#sponsors)
24
24
  - [Backers](#backers)
25
25
  - [Changelog](#changelog)
@@ -40,14 +40,50 @@ yarn add dlintr
40
40
  npm i dlintr
41
41
  ```
42
42
 
43
+ Requires Node.js 20.1+ for the built-in [`node:wasi`][node-wasi].
44
+
43
45
  ### API
44
46
 
45
47
  ```js
46
- import echo from 'dlintr'
47
-
48
- echo()
48
+ import { getVersion, lint, run } from 'dlintr'
49
+
50
+ // Lint Dockerfile content and get the findings back.
51
+ const results = await lint('FROM ubuntu:latest\nRUN apt-get update\n')
52
+ // [
53
+ // { code: 'DL3007', line: 1, column: 1, level: 'warning', file: '-', message: '…' },
54
+ // { code: 'DL3009', line: 2, column: 1, level: 'info', file: '-', message: '…' },
55
+ // ]
56
+
57
+ await lint('FROM alpine:3.20\n', {
58
+ ignore: ['DL3009'], // rule codes to suppress
59
+ severityOverrides: { DL3007: 'error' }, // re-level a single rule
60
+ env: { HADOLINT_TRUSTED_REGISTRIES: 'docker.io' }, // anything hadolint reads
61
+ })
62
+
63
+ await getVersion() // 'Haskell Dockerfile Linter 3.0.0'
64
+
65
+ // Or drive the CLI directly, for options `lint` does not model.
66
+ const { exitCode, stdout, stderr } = await run(
67
+ ['--no-color', '--failure-threshold', 'error', '-'],
68
+ {
69
+ stdin: 'FROM ubuntu:latest\n',
70
+ },
71
+ )
49
72
  ```
50
73
 
74
+ 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.
75
+
76
+ `lint` returns findings and drops the exit code. To gate CI, either look at `level`, or use `run` with `--failure-threshold` and check `exitCode`.
77
+
78
+ ### How it works
79
+
80
+ [`hadolint`][hadolint] is compiled to WASI with the GHC backend and executed in-process; there is no native binary and no Docker.
81
+
82
+ - **Node** drives it with the built-in `node:wasi`, so there is nothing to install.
83
+ - **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.
84
+
85
+ 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.
86
+
51
87
  ## Sponsors
52
88
 
53
89
  | 1stG | RxTS | UnTS |
@@ -71,5 +107,8 @@ Detailed changes for each release are documented in [CHANGELOG.md](./CHANGELOG.m
71
107
  [MIT][] © [JounQin][]@[1stG.me][]
72
108
 
73
109
  [1stg.me]: https://www.1stg.me
110
+ [bjorn3]: https://github.com/bjorn3/browser_wasi_shim
111
+ [hadolint]: https://github.com/hadolint/hadolint
74
112
  [jounqin]: https://GitHub.com/JounQin
75
113
  [mit]: http://opensource.org/licenses/MIT
114
+ [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"}
@@ -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 index = () => "Hello World!";
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
- module.exports = index;
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 _default: () => string;
2
- export default _default;
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
- export default () => 'Hello World!';
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":"AAAA,eAAe,GAAG,EAAE,CAAC,cAAc,CAAA"}
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"}
@@ -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,3 @@
1
+ export const HADOLINT = 'hadolint';
2
+ export const DEFAULT_ENV = { HOME: '/' };
3
+ //# sourceMappingURL=runtime.js.map
@@ -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
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,2 @@
1
+ import type { WasiRuntime } from './runtime.js';
2
+ export declare const createBrowserRuntime: () => WasiRuntime;
@@ -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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"}
@@ -0,0 +1,2 @@
1
+ import type { WasiRuntime } from './runtime.js';
2
+ export declare const createNodeRuntime: () => WasiRuntime;
@@ -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.0.0",
3
+ "version": "0.1.1",
4
4
  "type": "module",
5
5
  "description": "Dockerfile linter, validate inline bash, powered by hadolint with WASM",
6
- "repository": "git+https://github.com/wasmio/dlintr.git",
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": "^12.20.0 || ^14.18.0 || >=16.0.0"
14
+ "node": ">=20.1.0"
13
15
  },
14
16
  "exports": {
15
- "types": "./lib/index.d.ts",
16
- "import": "./lib/index.js",
17
- "require": "./lib/index.cjs"
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": "^7.2.1",
28
- "@1stg/lib-config": "^10.2.1",
29
- "@changesets/changelog-github": "^0.4.6",
30
- "@changesets/cli": "^2.24.4",
31
- "@pkgr/webpack": "^3.4.0",
32
- "@pkgr/webpack-mdx": "^2.2.0",
33
- "@size-limit/preset-small-lib": "^8.1.0",
34
- "@types/mdx": "^2.0.2",
35
- "@types/node": "^18.7.16",
36
- "@types/react": "^18.0.19",
37
- "@types/react-dom": "^18.0.6",
38
- "@types/web": "^0.0.72",
39
- "@vitest/coverage-istanbul": "^0.23.2",
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
- "react": "^18.2.0",
43
- "react-dom": "^18.2.0",
44
- "react-router-dom": "^6.3.0",
45
- "sirv-cli": "^2.0.2",
46
- "size-limit": "^8.1.0",
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": "~4.7.4",
49
- "unplugin-auto-import": "^0.11.2",
50
- "vitest": "^0.23.2"
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
- "codesandbox:install": "yarn",
111
+ "build:wasm": "node scripts/hadolint-wasm.mjs",
75
112
  "dev": "vitest",
76
- "docs:build": "w -e docs -p --publicPath /",
77
- "docs:dev": "w -e docs",
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
- "vercel-build": "pnpm docs:build",
89
- "version": "changeset version"
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",