eslint-sh 0.5.0 → 0.6.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 +366 -28
- package/dist/eslint-sh-syntax-analyze.d.ts +17 -0
- package/dist/eslint-sh-syntax.d.ts +16 -0
- package/dist/eslint-sh.d.ts +3 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +4 -1
- package/dist/syntax/analyze.d.ts +13 -0
- package/dist/syntax/analyze.js +15 -0
- package/dist/syntax/index.d.ts +12 -0
- package/dist/syntax/index.js +14 -0
- package/package.json +27 -12
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
package/README.md
CHANGED
|
@@ -1,17 +1,33 @@
|
|
|
1
1
|
# eslint-sh
|
|
2
2
|
|
|
3
|
-
Shell script
|
|
4
|
-
typed shell AST.
|
|
3
|
+
Shell script linting for ESLint: enforce project conventions and contracts with built-in rules,
|
|
4
|
+
shared presets, and custom rules over a typed shell AST.
|
|
5
5
|
|
|
6
6
|
This is the canonical quickstart for the `eslint-sh` / `@eslint-sh/eslint-plugin` project — start
|
|
7
7
|
here regardless of which of the two packages you install.
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
Built-in rules ship in four presets: `configs.recommended`, `configs['agent-authored']`
|
|
10
|
+
and the deployment-target packs `configs['bash-3.2']` and `configs['posix-portable']` (see
|
|
11
|
+
[Presets](#presets)). Browse the
|
|
12
|
+
[rules index](https://github.com/mike-north/eslint-sh/blob/main/packages/eslint-plugin/docs/rules/README.md)
|
|
13
|
+
for each rule's purpose, preset membership, and autofix availability.
|
|
14
|
+
|
|
15
|
+
**Run both eslint-sh and shellcheck.** shellcheck catches shell correctness problems such as
|
|
16
|
+
quoting and word-splitting mistakes. eslint-sh enforces your project's policy: strict mode,
|
|
17
|
+
command declarations, network wrappers, and other conventions. It complements shellcheck; it
|
|
18
|
+
does not aim to reproduce shellcheck's diagnostic catalog. See
|
|
19
|
+
[running eslint-sh beside shellcheck](https://github.com/mike-north/eslint-sh/blob/main/packages/eslint-plugin/docs/shellcheck.md)
|
|
20
|
+
for who owns what, and the
|
|
21
|
+
[design rationale](https://github.com/mike-north/eslint-sh/blob/main/design/README.md#eslint-sh-and-shellcheck).
|
|
10
22
|
|
|
11
23
|
## Installation
|
|
12
24
|
|
|
13
|
-
Requires
|
|
14
|
-
|
|
25
|
+
Requires Node.js 22.13 or later on the 22 line, or Node.js 24 or later (`engines.node` is
|
|
26
|
+
`^22.13.0 || >=24`, the range ESLint 10 itself supports, without the end-of-life Node 20 line).
|
|
27
|
+
|
|
28
|
+
Also requires `eslint@^10.2.0` (ESLint 10.2 or any later 10.x release) as a peer dependency (already
|
|
29
|
+
listed as a peer in `eslint-sh`'s `package.json`, so a compatible `eslint` install satisfies it
|
|
30
|
+
automatically):
|
|
15
31
|
|
|
16
32
|
```sh
|
|
17
33
|
npm install --save-dev eslint-sh
|
|
@@ -19,8 +35,10 @@ npm install --save-dev eslint-sh
|
|
|
19
35
|
|
|
20
36
|
## Usage
|
|
21
37
|
|
|
22
|
-
|
|
23
|
-
|
|
38
|
+
Start with `sh.configs.recommended`. It supplies the shell language and plugin registration,
|
|
39
|
+
reports syntax errors, and enables the convention-free rules: require a shebang and strict
|
|
40
|
+
mode, disallow `eval` and dynamic sourcing, and warn about literal secrets in flags. You supply
|
|
41
|
+
the paths to your shell scripts.
|
|
24
42
|
|
|
25
43
|
```js
|
|
26
44
|
// eslint.config.mjs
|
|
@@ -29,29 +47,255 @@ import sh from 'eslint-sh'; // equivalent to: import sh from '@eslint-sh/eslint-
|
|
|
29
47
|
|
|
30
48
|
export default defineConfig([
|
|
31
49
|
{
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
languageOptions: { dialect: 'bash', shellVersion: '3.2' },
|
|
50
|
+
// Extensionless scripts need `bin/?*`: ESLint never lints a file matched only by `bin/*` or `bin/**`.
|
|
51
|
+
files: ['**/*.sh', '**/*.bash', 'bin/?*'],
|
|
52
|
+
extends: [sh.configs.recommended],
|
|
36
53
|
},
|
|
37
54
|
]);
|
|
38
55
|
```
|
|
39
56
|
|
|
57
|
+
For example, save this as `bin/deploy` (or `scripts/example.sh`):
|
|
58
|
+
|
|
59
|
+
```sh
|
|
60
|
+
#!/usr/bin/env bash
|
|
61
|
+
set -euo pipefail
|
|
62
|
+
if [[ "$#" -gt 0 ]]; then echo "$1"; fi
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Run `npx eslint .` to lint your scripts, or `npx eslint . --fix` to apply available autofixes.
|
|
66
|
+
This script passes the recommended rules. A script without a shebang or strict mode reports
|
|
67
|
+
errors, and `--fix` can insert both. A clean result means the enabled rules found no problems;
|
|
68
|
+
keep running shellcheck alongside eslint-sh for general shell correctness checks.
|
|
69
|
+
|
|
70
|
+
Shell scripts are often extensionless (`bin/deploy`), so list the directories that hold them
|
|
71
|
+
with a pattern like `bin/?*`. A pattern that ends in `*` or `/**` (`bin/*`, `bin/**`) never makes a
|
|
72
|
+
file lintable on its own, and ESLint skips the file without a warning. See
|
|
73
|
+
[My extensionless scripts aren't being linted](#troubleshooting) below.
|
|
74
|
+
|
|
40
75
|
`languageOptions` is entirely optional — omitting it is equivalent to
|
|
41
76
|
`languageOptions: { dialect: 'bash' }`, since `dialect` defaults to `"bash"` (see the
|
|
42
77
|
`languageOptions` reference table below). This README's own [custom-rule tutorial](https://github.com/mike-north/eslint-sh/blob/main/packages/eslint-plugin/docs/custom-rule-tutorial.md)
|
|
43
78
|
config omits `languageOptions` for exactly that reason — it targets bash, the default, so
|
|
44
|
-
there's nothing to override
|
|
45
|
-
|
|
79
|
+
there's nothing to override. Add `languageOptions: { dialect: 'posix' }` to your config entry
|
|
80
|
+
when targeting POSIX shell, or set a `shellVersion` hint or custom `directivePrefix` as needed.
|
|
81
|
+
|
|
82
|
+
### CommonJS config
|
|
83
|
+
|
|
84
|
+
In a package without `"type": "module"` (the ESLint default), `eslint.config.js` is CommonJS, as
|
|
85
|
+
is `eslint.config.cjs` in any package. `eslint-sh` is ESM-only, so `require('eslint-sh')` returns
|
|
86
|
+
the module namespace and the plugin object is its `.default`. Named exports such as
|
|
87
|
+
`commentPragma` are ordinary properties of the `require` result. Without `.default`, `sh.configs`
|
|
88
|
+
is `undefined` and ESLint fails with `Cannot read properties of undefined (reading 'recommended')`.
|
|
89
|
+
|
|
90
|
+
```js
|
|
91
|
+
// eslint.config.js (CommonJS package) or eslint.config.cjs
|
|
92
|
+
const { defineConfig } = require('eslint/config');
|
|
93
|
+
const sh = require('eslint-sh').default;
|
|
94
|
+
// Named exports need no `.default`.
|
|
95
|
+
const { commentPragma } = require('eslint-sh');
|
|
96
|
+
|
|
97
|
+
module.exports = defineConfig([
|
|
98
|
+
{
|
|
99
|
+
files: ['**/*.sh'],
|
|
100
|
+
extends: [sh.configs.recommended],
|
|
101
|
+
settings: { sh: { declarationConvention: commentPragma } },
|
|
102
|
+
rules: { 'sh/no-undeclared-commands': 'error' },
|
|
103
|
+
},
|
|
104
|
+
]);
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## Presets
|
|
108
|
+
|
|
109
|
+
Each preset is a single config object that supplies `plugins: { sh }` and `language: 'sh/sh'` and
|
|
110
|
+
has no `files` key. Extend it from an entry that lists your shell scripts:
|
|
111
|
+
|
|
112
|
+
```js
|
|
113
|
+
import { defineConfig } from 'eslint/config';
|
|
114
|
+
import sh from 'eslint-sh';
|
|
115
|
+
|
|
116
|
+
export default defineConfig([{ files: ['**/*.sh', 'bin/?*'], extends: [sh.configs.recommended] }]);
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
- **`sh.configs.recommended`** enables the rules that assume no project conventions:
|
|
120
|
+
`sh/require-strict-mode`, `sh/require-shebang`, `sh/no-eval`, `sh/no-unchecked-cd` and
|
|
121
|
+
`sh/shebang-matches-dialect` at `error`, and
|
|
122
|
+
`sh/no-secret-flags` and `sh/quote-expansions` at `warn`.
|
|
123
|
+
- **`sh.configs['agent-authored']`** is for scripts that are machine-written and human-reviewed.
|
|
124
|
+
It enables every `recommended` rule plus the contract rules, all at `error`:
|
|
125
|
+
`sh/no-dynamic-invocation`, `sh/no-secret-env-reads`, `sh/no-undeclared-commands`,
|
|
126
|
+
`sh/no-unused-declarations`, `sh/require-network-wrapper`, `sh/require-tty-guard` and `sh/max-script-complexity`
|
|
127
|
+
(which caps function count, nesting depth and statement count).
|
|
128
|
+
`sh/no-secret-flags` and `sh/quote-expansions` are `error` here too.
|
|
129
|
+
- **`sh.configs['bash-3.2']`** is for scripts that must run on the Bash 3.2 macOS ships as
|
|
130
|
+
`/bin/bash`. It sets `languageOptions: { dialect: 'bash', shellVersion: '3.2' }` and enables every
|
|
131
|
+
version-gated `compat/*` rule at `error`.
|
|
132
|
+
- **`sh.configs['posix-portable']`** reports Bash-only constructs that fail on dash, including
|
|
133
|
+
`[[`, `let` and `source`, but not `local`, `echo -e` or the others it leaves to shellcheck, so a
|
|
134
|
+
clean run does not prove a script runs under every POSIX `sh`. It sets
|
|
135
|
+
`languageOptions: { dialect: 'posix' }` and enables the `compat/*` rules and
|
|
136
|
+
`sh/shebang-matches-dialect` at `error`, and `sh/require-strict-mode` with `set -eu`.
|
|
137
|
+
Compose them after `recommended`:
|
|
138
|
+
`extends: [sh.configs.recommended, sh.configs['posix-portable']]`. See
|
|
139
|
+
[version compatibility](https://github.com/mike-north/eslint-sh/blob/main/packages/eslint-plugin/docs/compat.md).
|
|
140
|
+
|
|
141
|
+
Three `agent-authored` rules report nothing until you configure them. `sh/no-undeclared-commands`
|
|
142
|
+
and `sh/no-unused-declarations` need a declaration convention bound in
|
|
143
|
+
`settings.sh.declarationConvention`, and `sh/require-network-wrapper` needs the wrapper your
|
|
144
|
+
network commands must run through, set once in `settings.sh.networkWrapper`. The declaration rules
|
|
145
|
+
read that setting too, so they count `curl` in `with-retry curl …` as used:
|
|
146
|
+
|
|
147
|
+
```js
|
|
148
|
+
import { defineConfig } from 'eslint/config';
|
|
149
|
+
import sh, { commentPragma } from 'eslint-sh';
|
|
150
|
+
|
|
151
|
+
export default defineConfig([
|
|
152
|
+
{
|
|
153
|
+
files: ['**/*.sh', 'bin/?*'],
|
|
154
|
+
extends: [sh.configs['agent-authored']],
|
|
155
|
+
settings: { sh: { declarationConvention: commentPragma, networkWrapper: 'with-retry' } },
|
|
156
|
+
},
|
|
157
|
+
]);
|
|
158
|
+
```
|
|
46
159
|
|
|
47
160
|
## `languageOptions` reference
|
|
48
161
|
|
|
49
162
|
| Option | Allowed values | Default | Effect |
|
|
50
163
|
| ----------------- | ----------------------------------------------------------------------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
51
164
|
| `dialect` | `"bash"`, `"posix"`, `"mksh"`, `"bats"`, `"zsh"` | `"bash"` | Selects which shell grammar the parser accepts. Enforcement is partial: some non-dialect constructs are rejected (e.g. bash array literals under `posix`), but others (e.g. `[[ ... ]]`, `let`) are accepted as ordinary commands — see the [per-dialect enforcement table](https://github.com/mike-north/sh-ast/blob/main/packages/sh-ast/README.md#dialect-enforcement). |
|
|
52
|
-
| `shellVersion` | A numeric `MAJOR` or `MAJOR.MINOR` string, e.g. `"5"` or `"3.2"` | unset |
|
|
165
|
+
| `shellVersion` | A numeric `MAJOR` or `MAJOR.MINOR` string, e.g. `"5"` or `"3.2"` | unset | The Bash version your scripts must run on. It has no effect on parsing; the `compat/*` rules read it to report features that version lacks. Unset means the newest version. See [version compatibility](https://github.com/mike-north/eslint-sh/blob/main/packages/eslint-plugin/docs/compat.md). |
|
|
53
166
|
| `directivePrefix` | Lowercase, hyphen-separated words, e.g. `"eslint"` or `"shellcheck-sh"` | `"eslint"` | The prefix directive/inline-config comments must start with — e.g. the default recognizes `# eslint-disable-next-line ...`. |
|
|
54
167
|
|
|
168
|
+
## Continuous integration
|
|
169
|
+
|
|
170
|
+
Lint with the same command you run locally, `eslint .`, against the config from
|
|
171
|
+
[Usage](#usage). The config's `files` list decides which scripts are linted, including
|
|
172
|
+
extensionless ones such as `bin/deploy`. Listing paths on the command line does not replace it:
|
|
173
|
+
ESLint only lints a file the config's `files` patterns match. Here is a complete GitHub Actions
|
|
174
|
+
job:
|
|
175
|
+
|
|
176
|
+
```yaml
|
|
177
|
+
name: Lint shell scripts
|
|
178
|
+
on:
|
|
179
|
+
push:
|
|
180
|
+
branches: [main]
|
|
181
|
+
pull_request:
|
|
182
|
+
permissions:
|
|
183
|
+
contents: read
|
|
184
|
+
jobs:
|
|
185
|
+
lint-shell:
|
|
186
|
+
runs-on: ubuntu-latest
|
|
187
|
+
steps:
|
|
188
|
+
- uses: actions/checkout@v4
|
|
189
|
+
- uses: actions/setup-node@v7
|
|
190
|
+
with:
|
|
191
|
+
node-version: 22
|
|
192
|
+
cache: npm
|
|
193
|
+
- run: npm ci
|
|
194
|
+
- name: eslint-sh
|
|
195
|
+
run: npx eslint . --max-warnings 0
|
|
196
|
+
- name: shellcheck
|
|
197
|
+
run: |
|
|
198
|
+
git ls-files -z '*.sh' '*.bash' 'bin/*' |
|
|
199
|
+
xargs -0 sh -c '[ "$#" -eq 0 ] || exec shellcheck -- "$@"' sh
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
It assumes `eslint` and `eslint-sh` are in your `devDependencies` with a committed
|
|
203
|
+
`package-lock.json`; use your package manager's frozen install (`pnpm install --frozen-lockfile`)
|
|
204
|
+
otherwise. `permissions: contents: read` keeps the job's `GITHUB_TOKEN` read-only:
|
|
205
|
+
linting needs nothing more. The `uses:` lines name each action's major version for readability;
|
|
206
|
+
to guard against a moved tag, pin each one to a full commit SHA with the version as a trailing
|
|
207
|
+
comment (`actions/checkout@<40-character SHA> # v4.4.0`), as
|
|
208
|
+
[this repository's workflows](https://github.com/mike-north/eslint-sh/tree/main/.github/workflows)
|
|
209
|
+
do, and let Dependabot's `github-actions` updates bump them. `ubuntu-latest` runners ship with shellcheck. The step is separate because shellcheck
|
|
210
|
+
is a different tool with its own exit code; see
|
|
211
|
+
[running eslint-sh beside shellcheck](https://github.com/mike-north/eslint-sh/blob/main/packages/eslint-plugin/docs/shellcheck.md).
|
|
212
|
+
|
|
213
|
+
The shellcheck step checks every tracked `*.sh` and `*.bash` file plus everything tracked under
|
|
214
|
+
`bin/`, so it also works in a project that has no `bin/` or `scripts/` folder (it then checks
|
|
215
|
+
nothing and exits 0). Adapt the pathspecs to where your scripts live. shellcheck needs a shebang
|
|
216
|
+
or a `# shellcheck shell=bash` directive to know a file's dialect: an extensionless file without
|
|
217
|
+
either fails with SC2148, so keep non-shell files out of `bin/`.
|
|
218
|
+
|
|
219
|
+
Exit codes of `eslint`:
|
|
220
|
+
|
|
221
|
+
| Exit code | Meaning |
|
|
222
|
+
| --------- | ------------------------------------------------------------------------------------------------------------------------------ |
|
|
223
|
+
| `0` | No errors. Warnings alone (`sh/quote-expansions` and `sh/no-secret-flags` under `recommended`) do not fail the job. |
|
|
224
|
+
| `1` | At least one error, or more warnings than `--max-warnings` allows (`ESLint found too many warnings (maximum: 0).`). |
|
|
225
|
+
| `2` | ESLint could not run: for example a CLI pattern that matches no files, or an invalid config. Treat it as a failed job as well. |
|
|
226
|
+
|
|
227
|
+
`--max-warnings 0` in the job above makes warnings fail it. Drop the flag if you want warnings
|
|
228
|
+
reported but not blocking.
|
|
229
|
+
|
|
230
|
+
**Pre-commit hook.** To lint only the shell files in a commit, including extensionless ones,
|
|
231
|
+
select the staged paths with git and pass them to ESLint. Save this as `.git/hooks/pre-commit`
|
|
232
|
+
(or run it from your hook manager) and make it executable:
|
|
233
|
+
|
|
234
|
+
```sh
|
|
235
|
+
#!/bin/sh
|
|
236
|
+
git diff --cached --name-only -z --diff-filter=ACM -- '*.sh' '*.bash' 'bin/*' |
|
|
237
|
+
xargs -0 sh -c '[ "$#" -eq 0 ] || exec npx eslint --max-warnings 0 --no-warn-ignored -- "$@"' sh
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
The pathspec `'bin/*'` selects extensionless scripts that a `*.sh` pattern would miss; match it
|
|
241
|
+
to the `files` patterns in your config. `--no-warn-ignored` keeps a staged file that your config
|
|
242
|
+
does not cover from failing the hook as an "ignored file" warning. File names are passed
|
|
243
|
+
NUL-separated, so names with spaces work, and the hook does nothing when no shell file is staged.
|
|
244
|
+
|
|
245
|
+
## Editor setup
|
|
246
|
+
|
|
247
|
+
Editors that run ESLint through its language server, such as the VS Code ESLint extension, run
|
|
248
|
+
the `eslint` installed in your project. They read the same `eslint.config.mjs` as the command
|
|
249
|
+
line, so the plugin and the `files` patterns from [Usage](#usage) apply with no editor-specific
|
|
250
|
+
configuration of eslint-sh. Install `eslint` and `eslint-sh` in the project, not globally.
|
|
251
|
+
|
|
252
|
+
**VS Code.** What the
|
|
253
|
+
[ESLint extension's documentation](https://github.com/microsoft/vscode-eslint#readme) says, which
|
|
254
|
+
has not been tried against eslint-sh in an editor (see "What was and was not verified" below):
|
|
255
|
+
|
|
256
|
+
- The extension only activates for the language ids in its `eslint.probe` list by default
|
|
257
|
+
(JavaScript, TypeScript, HTML, Markdown, JSON and similar, but not `shellscript`). Enforce
|
|
258
|
+
validation of shell files by listing the language id in `eslint.validate`.
|
|
259
|
+
- Fix on save is the `source.fixAll.eslint` code action.
|
|
260
|
+
|
|
261
|
+
```json
|
|
262
|
+
{
|
|
263
|
+
"eslint.validate": ["shellscript"],
|
|
264
|
+
"editor.codeActionsOnSave": {
|
|
265
|
+
"source.fixAll.eslint": "explicit"
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
Put it in `.vscode/settings.json` to share it with your team. Two things are expected but not
|
|
271
|
+
confirmed, so check them (items 3 and 4 below) rather than assuming: that fix on save applies
|
|
272
|
+
eslint-sh's autofixes, such as inserting a missing shebang and strict mode, and that the
|
|
273
|
+
`shellscript` language id is what VS Code assigns to your scripts, including extensionless ones.
|
|
274
|
+
The extension's documentation says ESLint v9 and later use flat config files, which is what
|
|
275
|
+
`eslint.config.mjs` is, so `eslint.useFlatConfig` should not be needed; that is also unconfirmed.
|
|
276
|
+
|
|
277
|
+
**What was and was not verified.**
|
|
278
|
+
|
|
279
|
+
- Verified: the command-line behavior this section relies on (the `files` patterns, extensionless
|
|
280
|
+
scripts, and the exit codes above), by running it from packed tarballs of both packages in a
|
|
281
|
+
separate project, and by a test in this repository that runs the documented commands.
|
|
282
|
+
- Not verified: everything about VS Code. No editor session was driven, and the ESLint extension
|
|
283
|
+
was not installed. The settings above come from the extension's documentation only, and the
|
|
284
|
+
extension version tested is therefore none.
|
|
285
|
+
|
|
286
|
+
Before relying on this setup, check by hand in VS Code with the ESLint extension:
|
|
287
|
+
|
|
288
|
+
1. Open a `.sh` file and a shebang-less `bin/` script in a project with `eslint-sh` installed.
|
|
289
|
+
Do diagnostics from eslint-sh rules (for example `sh/require-shebang`) appear in the Problems
|
|
290
|
+
panel with and without `eslint.validate`? If they appear without it, the setting is not needed.
|
|
291
|
+
2. Does the extension's output channel ("ESLint") report any error loading the plugin or config?
|
|
292
|
+
3. Remove the shebang from a `.sh` file and save. Is it inserted along with strict mode, once
|
|
293
|
+
`source.fixAll.eslint` is enabled?
|
|
294
|
+
4. Does an extensionless script with a shebang, such as `bin/deploy`, get diagnostics? What does
|
|
295
|
+
VS Code show as its language in the status bar, with and without the shebang? If it is not
|
|
296
|
+
`shellscript` (shown as "Shell Script"), the extension will not validate it under
|
|
297
|
+
`eslint.validate: ["shellscript"]`.
|
|
298
|
+
|
|
55
299
|
## Troubleshooting
|
|
56
300
|
|
|
57
301
|
Every worked example below (config, script, and error output) is extracted straight out of this
|
|
@@ -107,6 +351,36 @@ from what the plugin actually does.
|
|
|
107
351
|
The fix for both is the same one-line addition: set `language: 'sh/sh'` alongside
|
|
108
352
|
`plugins: { sh }` in the config object.
|
|
109
353
|
|
|
354
|
+
- **My extensionless scripts aren't being linted.** ESLint treats a `files` pattern that ends in
|
|
355
|
+
`*` or `/**` as one that only adds settings to files another pattern already matched. Such a
|
|
356
|
+
pattern never makes a file lintable on its own. So with this config:
|
|
357
|
+
|
|
358
|
+
```js
|
|
359
|
+
export default [{ files: ['**/*.sh', 'bin/*'], plugins: { sh }, language: 'sh/sh' }];
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
`eslint .` lints `bin/build.sh` but skips the extensionless `bin/deploy`. It prints no warning
|
|
363
|
+
and still exits 0. Use a pattern that matches the file by itself:
|
|
364
|
+
|
|
365
|
+
```js
|
|
366
|
+
export default [{ files: ['**/*.sh', 'bin/?*'], plugins: { sh }, language: 'sh/sh' }];
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
Each of these patterns lints `bin/deploy`:
|
|
370
|
+
- `bin/?*`: every file directly in `bin/`.
|
|
371
|
+
- `bin/!(*.*)`: only the files in `bin/` whose names have no dot, so `bin/helper.js` stays out.
|
|
372
|
+
- `bin/**/?*`: every file in `bin/` and its subdirectories.
|
|
373
|
+
- `bin/deploy`: just that one file.
|
|
374
|
+
|
|
375
|
+
To check whether ESLint will lint a file, print the config it resolves for that file:
|
|
376
|
+
|
|
377
|
+
```sh
|
|
378
|
+
npx eslint --print-config bin/deploy
|
|
379
|
+
```
|
|
380
|
+
|
|
381
|
+
It prints `undefined` when no `files` pattern makes the file lintable. When one does, it prints
|
|
382
|
+
the resolved config, which includes `"language": "sh/sh"`.
|
|
383
|
+
|
|
110
384
|
- **A script I believe is valid reports a parse error.** The parser is dialect-sensitive: a
|
|
111
385
|
construct that's valid in one shell grammar may be rejected in another. Given this config:
|
|
112
386
|
|
|
@@ -136,17 +410,51 @@ from what the plugin actually does.
|
|
|
136
410
|
Set `languageOptions.dialect` to match the shell the script is actually written for. Note that
|
|
137
411
|
dialect enforcement is partial by design: some bash-isms — notably `[[ ... ]]` and `let` — are
|
|
138
412
|
not parse errors under `dialect: 'posix'`; they silently parse as ordinary commands instead, so
|
|
139
|
-
a clean `posix` run does not by itself prove a script is POSIX-compliant.
|
|
413
|
+
a clean `posix` run does not by itself prove a script is POSIX-compliant. The `posix-portable`
|
|
414
|
+
preset reports `[[`, `let` and `source`, and
|
|
415
|
+
[names what it does not report](https://github.com/mike-north/eslint-sh/blob/main/packages/eslint-plugin/docs/compat.md#what-posix-portable-does-not-report). See the
|
|
140
416
|
[per-dialect construct enforcement audit](https://github.com/mike-north/sh-ast/blob/main/packages/sh-ast/README.md#dialect-enforcement)
|
|
141
417
|
in `sh-ast` for the full accept/reject matrix and rationale.
|
|
142
418
|
|
|
143
|
-
- **
|
|
144
|
-
`
|
|
145
|
-
has no
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
419
|
+
- **Every JavaScript file reports a shell parsing error.** `sh.configs.recommended` has no
|
|
420
|
+
`files` key by design: it lints exactly the paths of the config entry it is used in. Used on its
|
|
421
|
+
own, it has no paths, so it applies to every file ESLint lints, including your JavaScript.
|
|
422
|
+
eslint-sh recognizes common non-shell file types (JavaScript, TypeScript, JSON, Markdown, CSS,
|
|
423
|
+
HTML, Vue, Svelte, YAML) and reports one message per file instead of a misleading shell syntax
|
|
424
|
+
error. Given this config:
|
|
425
|
+
|
|
426
|
+
```js
|
|
427
|
+
export default defineConfig([sh.configs.recommended]);
|
|
428
|
+
```
|
|
429
|
+
|
|
430
|
+
linting `index.js`:
|
|
431
|
+
|
|
432
|
+
```js
|
|
433
|
+
if (a) {
|
|
434
|
+
b();
|
|
435
|
+
}
|
|
436
|
+
```
|
|
437
|
+
|
|
438
|
+
produces:
|
|
439
|
+
|
|
440
|
+
```text
|
|
441
|
+
Parsing error: This JavaScript file (.js) is being linted as shell: a config entry selects language 'sh/sh' (for example sh.configs.recommended) without a files list. Wrap the preset in an entry with files, e.g. { files: ['**/*.sh'], extends: [sh.configs.recommended] }
|
|
442
|
+
```
|
|
443
|
+
|
|
444
|
+
The fix is to wrap the preset in an entry whose `files` lists your shell scripts:
|
|
445
|
+
|
|
446
|
+
```js
|
|
447
|
+
export default defineConfig([{ files: ['**/*.sh'], extends: [sh.configs.recommended] }]);
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
- **Setting `shellVersion` doesn't change anything.** `shellVersion` has no effect on parsing,
|
|
451
|
+
and only the version-gated `compat/*` rules read it (`sh/compat/no-append-all-redirect`, `sh/compat/no-associative-arrays`, `sh/compat/no-case-attributes`, `sh/compat/no-case-fallthrough`, `sh/compat/no-case-modification`, `sh/compat/no-coproc`, `sh/compat/no-declare-g`, `sh/compat/no-epoch-variables`, `sh/compat/no-fd-variable`, `sh/compat/no-globstar`, `sh/compat/no-lastpipe-semantics`, `sh/compat/no-mapfile`, `sh/compat/no-nameref`, `sh/compat/no-negative-array-index`, `sh/compat/no-nounset-empty-array`, `sh/compat/no-parameter-transformation`, `sh/compat/no-pipe-all`, `sh/compat/no-printf-time-format`, `sh/compat/no-test-v`, `sh/compat/no-unicode-escape` and `sh/compat/no-wait-n`). The `bash-3.2` and `posix-portable` presets enable them; to pick rules yourself,
|
|
452
|
+
enable the ones you want, for example `'sh/compat/no-mapfile': 'error'`. See
|
|
453
|
+
[version compatibility](https://github.com/mike-north/eslint-sh/blob/main/packages/eslint-plugin/docs/compat.md).
|
|
454
|
+
- **`# eslint-disable-next-line ...` comments don't seem to do anything.** First check that the
|
|
455
|
+
rule is enabled, through a preset or your `rules` config. For example,
|
|
456
|
+
`# eslint-disable-next-line sh/no-eval -- reviewed dynamic evaluation` suppresses an enabled
|
|
457
|
+
`sh/no-eval` finding on the following line. If the directive still isn't recognized, check
|
|
150
458
|
`languageOptions.directivePrefix` — it must match the prefix your comment uses (the default
|
|
151
459
|
`"eslint"` only recognizes `# eslint-disable-next-line ...`, not a custom prefix).
|
|
152
460
|
- **A disable directive's rule id doesn't match anything I've registered.** An unknown rule id in
|
|
@@ -161,16 +469,46 @@ from what the plugin actually does.
|
|
|
161
469
|
language ids in its message (current ESLint 10.x behavior). This plugin registers exactly one
|
|
162
470
|
language: `sh` (selected as `language: 'sh/sh'`).
|
|
163
471
|
|
|
472
|
+
## Writing custom rules
|
|
473
|
+
|
|
474
|
+
`eslint-sh` re-exports everything a custom rule imports, so a project that installs only
|
|
475
|
+
`eslint-sh` needs no other package, even under pnpm's strict `node_modules` layout:
|
|
476
|
+
|
|
477
|
+
```js
|
|
478
|
+
// The plugin's named exports: the rule helper defineShellRule, view-aware helpers such as
|
|
479
|
+
// resolveWord, and the view and rule types.
|
|
480
|
+
import { defineShellRule, resolveWord } from 'eslint-sh';
|
|
481
|
+
// sh-ast's root entry point: parse, walk, and print faithful records.
|
|
482
|
+
import { parseSync, printSync, walk } from 'eslint-sh/syntax';
|
|
483
|
+
// sh-ast/analyze: command enumeration and wrapper resolution over faithful records.
|
|
484
|
+
import { DEFAULT_TRANSPARENT_WRAPPERS, enumerateCommands } from 'eslint-sh/syntax/analyze';
|
|
485
|
+
```
|
|
486
|
+
|
|
487
|
+
`eslint-sh` re-exports `@eslint-sh/eslint-plugin`'s named exports, and `eslint-sh/syntax` and
|
|
488
|
+
`eslint-sh/syntax/analyze` are `@eslint-sh/eslint-plugin/syntax` and
|
|
489
|
+
`@eslint-sh/eslint-plugin/syntax/analyze`. Those re-export `sh-ast` and `sh-ast/analyze` from the
|
|
490
|
+
plugin's own `sh-ast` dependency, the same module instance its language parses with. Don't import
|
|
491
|
+
`sh-ast` directly.
|
|
492
|
+
|
|
493
|
+
**Versioning.** `eslint-sh/syntax` and `eslint-sh/syntax/analyze` track the plugin's pinned
|
|
494
|
+
`sh-ast` minor (currently `sh-ast@^0.7.0`). Under 0.x, a different `sh-ast` minor is a breaking
|
|
495
|
+
change, so an `sh-ast` 0.x minor bump is a minor bump of this package, and the changelog entry
|
|
496
|
+
names the new `sh-ast` version.
|
|
497
|
+
|
|
498
|
+
See the `@eslint-sh/eslint-plugin` package's README for the full API and the
|
|
499
|
+
[custom-rule tutorial](https://github.com/mike-north/eslint-sh/blob/main/packages/eslint-plugin/docs/custom-rule-tutorial.md).
|
|
500
|
+
|
|
164
501
|
## Status
|
|
165
502
|
|
|
166
503
|
Thin umbrella re-exporting `@eslint-sh/eslint-plugin`'s plugin object unchanged as this
|
|
167
504
|
package's default export — `import sh from "eslint-sh"` and `import sh from "@eslint-sh/eslint-plugin"`
|
|
168
|
-
refer to the same object.
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
505
|
+
refer to the same object. Its named exports and its `syntax` / `syntax/analyze` subpaths are the
|
|
506
|
+
plugin's, re-exported unchanged (see [Writing custom rules](#writing-custom-rules)). `@eslint-sh/eslint-plugin` currently ships `ShellLanguage`/
|
|
507
|
+
`ShellSourceCode`, the built-in rules documented under its `docs/rules/`, and the `recommended`
|
|
508
|
+
and `agent-authored` [presets](#presets). Disable directives / inline config are implemented and
|
|
509
|
+
live. Disable comments suppress enabled built-in rules and custom rules alike; for example,
|
|
510
|
+
`# eslint-disable-next-line sh/no-eval -- justification` suppresses that rule on the following
|
|
511
|
+
line.
|
|
174
512
|
|
|
175
513
|
For the plugin's public API reference (types, exports, selector cookbook, and a custom-rule
|
|
176
514
|
authoring tutorial), see the `@eslint-sh/eslint-plugin` package's README.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The faithful shell analysis surface (`eslint-sh/syntax/analyze`):
|
|
3
|
+
* `@eslint-sh/eslint-plugin/syntax/analyze`, re-exported unchanged. It is the complete public
|
|
4
|
+
* surface of `sh-ast/analyze`, taken from the same `sh-ast` instance the plugin's language parses
|
|
5
|
+
* with. Its `resolveWord` takes a faithful `Node`, unlike the view-aware `resolveWord` exported
|
|
6
|
+
* from `eslint-sh` itself.
|
|
7
|
+
*
|
|
8
|
+
* It tracks the plugin's pinned `sh-ast` minor, so an `sh-ast` 0.x minor bump is a minor release
|
|
9
|
+
* of this package.
|
|
10
|
+
*
|
|
11
|
+
* @packageDocumentation
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
export * from "@eslint-sh/eslint-plugin/syntax/analyze";
|
|
16
|
+
|
|
17
|
+
export { }
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The faithful shell syntax surface (`eslint-sh/syntax`): `@eslint-sh/eslint-plugin/syntax`,
|
|
3
|
+
* re-exported unchanged. It is the complete public surface of `sh-ast`'s root entry point, taken
|
|
4
|
+
* from the same `sh-ast` instance the plugin's language parses with, so a project that installs
|
|
5
|
+
* only `eslint-sh` can edit or analyze faithful syntax without installing `sh-ast` itself.
|
|
6
|
+
*
|
|
7
|
+
* It tracks the plugin's pinned `sh-ast` minor, so an `sh-ast` 0.x minor bump is a minor release
|
|
8
|
+
* of this package.
|
|
9
|
+
*
|
|
10
|
+
* @packageDocumentation
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
export * from "@eslint-sh/eslint-plugin/syntax";
|
|
15
|
+
|
|
16
|
+
export { }
|
package/dist/eslint-sh.d.ts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -9,4 +9,7 @@ import sh from '@eslint-sh/eslint-plugin';
|
|
|
9
9
|
* @public
|
|
10
10
|
*/
|
|
11
11
|
export default sh;
|
|
12
|
-
|
|
12
|
+
// Every named export of the plugin root (`resolveWord`, `ShellSourceCode`, the view types, …)
|
|
13
|
+
// is re-exported unchanged, so a project that installs only `eslint-sh` can write custom rules
|
|
14
|
+
// without depending on `@eslint-sh/eslint-plugin` being hoisted where it can import it.
|
|
15
|
+
export * from '@eslint-sh/eslint-plugin';
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The faithful shell analysis surface (`eslint-sh/syntax/analyze`):
|
|
3
|
+
* `@eslint-sh/eslint-plugin/syntax/analyze`, re-exported unchanged. It is the complete public
|
|
4
|
+
* surface of `sh-ast/analyze`, taken from the same `sh-ast` instance the plugin's language parses
|
|
5
|
+
* with. Its `resolveWord` takes a faithful `Node`, unlike the view-aware `resolveWord` exported
|
|
6
|
+
* from `eslint-sh` itself.
|
|
7
|
+
*
|
|
8
|
+
* It tracks the plugin's pinned `sh-ast` minor, so an `sh-ast` 0.x minor bump is a minor release
|
|
9
|
+
* of this package.
|
|
10
|
+
*
|
|
11
|
+
* @packageDocumentation
|
|
12
|
+
*/
|
|
13
|
+
export * from '@eslint-sh/eslint-plugin/syntax/analyze';
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/* eslint-disable @api-extractor-tools/package-documentation -- this file is the barrel of the
|
|
2
|
+
`./syntax/analyze` entry point (package.json `exports`); the rule only recognizes the root barrel. */
|
|
3
|
+
/**
|
|
4
|
+
* The faithful shell analysis surface (`eslint-sh/syntax/analyze`):
|
|
5
|
+
* `@eslint-sh/eslint-plugin/syntax/analyze`, re-exported unchanged. It is the complete public
|
|
6
|
+
* surface of `sh-ast/analyze`, taken from the same `sh-ast` instance the plugin's language parses
|
|
7
|
+
* with. Its `resolveWord` takes a faithful `Node`, unlike the view-aware `resolveWord` exported
|
|
8
|
+
* from `eslint-sh` itself.
|
|
9
|
+
*
|
|
10
|
+
* It tracks the plugin's pinned `sh-ast` minor, so an `sh-ast` 0.x minor bump is a minor release
|
|
11
|
+
* of this package.
|
|
12
|
+
*
|
|
13
|
+
* @packageDocumentation
|
|
14
|
+
*/
|
|
15
|
+
export * from '@eslint-sh/eslint-plugin/syntax/analyze';
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The faithful shell syntax surface (`eslint-sh/syntax`): `@eslint-sh/eslint-plugin/syntax`,
|
|
3
|
+
* re-exported unchanged. It is the complete public surface of `sh-ast`'s root entry point, taken
|
|
4
|
+
* from the same `sh-ast` instance the plugin's language parses with, so a project that installs
|
|
5
|
+
* only `eslint-sh` can edit or analyze faithful syntax without installing `sh-ast` itself.
|
|
6
|
+
*
|
|
7
|
+
* It tracks the plugin's pinned `sh-ast` minor, so an `sh-ast` 0.x minor bump is a minor release
|
|
8
|
+
* of this package.
|
|
9
|
+
*
|
|
10
|
+
* @packageDocumentation
|
|
11
|
+
*/
|
|
12
|
+
export * from '@eslint-sh/eslint-plugin/syntax';
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/* eslint-disable @api-extractor-tools/package-documentation -- this file is the barrel of the
|
|
2
|
+
`./syntax` entry point (package.json `exports`); the rule only recognizes the root barrel. */
|
|
3
|
+
/**
|
|
4
|
+
* The faithful shell syntax surface (`eslint-sh/syntax`): `@eslint-sh/eslint-plugin/syntax`,
|
|
5
|
+
* re-exported unchanged. It is the complete public surface of `sh-ast`'s root entry point, taken
|
|
6
|
+
* from the same `sh-ast` instance the plugin's language parses with, so a project that installs
|
|
7
|
+
* only `eslint-sh` can edit or analyze faithful syntax without installing `sh-ast` itself.
|
|
8
|
+
*
|
|
9
|
+
* It tracks the plugin's pinned `sh-ast` minor, so an `sh-ast` 0.x minor bump is a minor release
|
|
10
|
+
* of this package.
|
|
11
|
+
*
|
|
12
|
+
* @packageDocumentation
|
|
13
|
+
*/
|
|
14
|
+
export * from '@eslint-sh/eslint-plugin/syntax';
|
package/package.json
CHANGED
|
@@ -1,25 +1,37 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "eslint-sh",
|
|
3
|
-
"description": "Shell script
|
|
4
|
-
"version": "0.
|
|
3
|
+
"description": "Shell script linting for ESLint, with built-in policy rules, shared presets, and custom rules over a typed shell AST",
|
|
4
|
+
"version": "0.6.0",
|
|
5
5
|
"author": "Mike North <michael.l.north@gmail.com>",
|
|
6
6
|
"dependencies": {
|
|
7
|
-
"@eslint-sh/eslint-plugin": "0.
|
|
7
|
+
"@eslint-sh/eslint-plugin": "0.6.0"
|
|
8
8
|
},
|
|
9
9
|
"devDependencies": {
|
|
10
10
|
"eslint": "^10.7.0"
|
|
11
11
|
},
|
|
12
12
|
"peerDependencies": {
|
|
13
|
-
"eslint": "^10.
|
|
13
|
+
"eslint": "^10.2.0"
|
|
14
|
+
},
|
|
15
|
+
"engines": {
|
|
16
|
+
"node": "^22.13.0 || >=24"
|
|
14
17
|
},
|
|
15
18
|
"exports": {
|
|
16
19
|
".": {
|
|
17
20
|
"types": "./dist/eslint-sh.d.ts",
|
|
18
21
|
"default": "./dist/index.js"
|
|
22
|
+
},
|
|
23
|
+
"./syntax": {
|
|
24
|
+
"types": "./dist/eslint-sh-syntax.d.ts",
|
|
25
|
+
"default": "./dist/syntax/index.js"
|
|
26
|
+
},
|
|
27
|
+
"./syntax/analyze": {
|
|
28
|
+
"types": "./dist/eslint-sh-syntax-analyze.d.ts",
|
|
29
|
+
"default": "./dist/syntax/analyze.js"
|
|
19
30
|
}
|
|
20
31
|
},
|
|
21
32
|
"files": [
|
|
22
|
-
"dist"
|
|
33
|
+
"dist",
|
|
34
|
+
"!dist/**/*.map"
|
|
23
35
|
],
|
|
24
36
|
"license": "MIT",
|
|
25
37
|
"main": "./dist/index.js",
|
|
@@ -28,8 +40,7 @@
|
|
|
28
40
|
"check:api-report": {
|
|
29
41
|
"outputs": [
|
|
30
42
|
"{projectRoot}/api-report",
|
|
31
|
-
"{projectRoot}/temp"
|
|
32
|
-
"{projectRoot}/dist/eslint-sh.d.ts"
|
|
43
|
+
"{projectRoot}/temp"
|
|
33
44
|
]
|
|
34
45
|
},
|
|
35
46
|
"uplevel-api-reports": {
|
|
@@ -43,7 +54,11 @@
|
|
|
43
54
|
],
|
|
44
55
|
"outputs": [
|
|
45
56
|
"{workspaceRoot}/api-report-combined/eslint-sh.api.md",
|
|
46
|
-
"{workspaceRoot}/api-docs-temp/eslint-sh.api.json"
|
|
57
|
+
"{workspaceRoot}/api-docs-temp/eslint-sh.api.json",
|
|
58
|
+
"{workspaceRoot}/api-report-combined/eslint-sh-syntax.api.md",
|
|
59
|
+
"{workspaceRoot}/api-docs-temp/eslint-sh-syntax.api.json",
|
|
60
|
+
"{workspaceRoot}/api-report-combined/eslint-sh-syntax-analyze.api.md",
|
|
61
|
+
"{workspaceRoot}/api-docs-temp/eslint-sh-syntax-analyze.api.json"
|
|
47
62
|
]
|
|
48
63
|
}
|
|
49
64
|
}
|
|
@@ -59,15 +74,15 @@
|
|
|
59
74
|
"directory": "packages/eslint-sh"
|
|
60
75
|
},
|
|
61
76
|
"scripts": {
|
|
62
|
-
"build": "tsc -p tsconfig.json",
|
|
77
|
+
"build": "tsc -p tsconfig.json && node ../../scripts/rollup-declarations.mjs api-extractor.json syntax/api-extractor.json syntax/analyze/api-extractor.json",
|
|
63
78
|
"check": "concurrently -n lint,types,api-report \"pnpm run check:lint-ts\" \"pnpm run check:typecheck\" \"pnpm run check:api-report\"",
|
|
64
|
-
"check:api-report": "api-extractor run",
|
|
79
|
+
"check:api-report": "api-extractor run && api-extractor run --config syntax/api-extractor.json && api-extractor run --config syntax/analyze/api-extractor.json",
|
|
65
80
|
"check:lint-ts": "eslint .",
|
|
66
81
|
"check:typecheck": "tsc --noEmit",
|
|
67
82
|
"clean": "rimraf --glob dist \"temp/*\" \"*.tsbuildinfo\"",
|
|
68
|
-
"fix:api-report": "api-extractor run --local",
|
|
83
|
+
"fix:api-report": "api-extractor run --local && api-extractor run --local --config syntax/api-extractor.json && api-extractor run --local --config syntax/analyze/api-extractor.json",
|
|
69
84
|
"fix:lint-ts": "eslint . --fix",
|
|
70
85
|
"test": "vitest run",
|
|
71
|
-
"uplevel-api-reports": "mkdir -p ../../api-report-combined ../../api-docs-temp && cp api-report/eslint-sh.api.md ../../api-report-combined/ && cp temp/eslint-sh.api.json ../../api-docs-temp/"
|
|
86
|
+
"uplevel-api-reports": "mkdir -p ../../api-report-combined ../../api-docs-temp && cp api-report/eslint-sh.api.md api-report/eslint-sh-syntax.api.md api-report/eslint-sh-syntax-analyze.api.md ../../api-report-combined/ && cp temp/eslint-sh.api.json temp/eslint-sh-syntax.api.json temp/eslint-sh-syntax-analyze.api.json ../../api-docs-temp/"
|
|
72
87
|
}
|
|
73
88
|
}
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAE1C;;;;;;;;GAQG;AACH,eAAe,EAAE,CAAC"}
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,0BAA0B,CAAC;AAE1C;;;;;;;;GAQG;AACH,eAAe,EAAE,CAAC"}
|