ssh-config 4.1.0 → 4.1.3

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/History.md CHANGED
@@ -1,3 +1,31 @@
1
+ 4.1.3 / 2022-03-11
2
+ ==================
3
+
4
+ ## What's Changed
5
+ * fix: IdentityAgent should be quoted if necessary by @cyjake in https://github.com/cyjake/ssh-config/pull/52
6
+
7
+
8
+ **Full Changelog**: https://github.com/cyjake/ssh-config/compare/v4.1.2...v4.1.3
9
+
10
+ 4.1.2 / 2022-01-20
11
+ ==================
12
+
13
+ ## What's Changed
14
+ * docs: types field in package.json by @cyjake in https://github.com/cyjake/ssh-config/pull/50
15
+
16
+
17
+ **Full Changelog**: https://github.com/cyjake/ssh-config/compare/v4.1.1...v4.1.2
18
+
19
+ 4.1.1 / 2021-10-21
20
+ ==================
21
+
22
+ ## What's Changed
23
+ * docs: `.prepend` and type definitions by @cyjake in https://github.com/cyjake/ssh-config/pull/47
24
+ * fix: improper parsing of ProxyCommand with quotation marks by @tanhakabir in https://github.com/cyjake/ssh-config/pull/48
25
+
26
+
27
+ **Full Changelog**: https://github.com/cyjake/ssh-config/compare/v4.1.0...v4.1.1
28
+
1
29
  4.1.0 / 2021-10-20
2
30
  ==================
3
31
 
package/Readme.md CHANGED
@@ -154,6 +154,62 @@ SSHConfig.stringify(config)
154
154
  // User dinosaur
155
155
  ```
156
156
 
157
+ ### `.prepend` sections
158
+
159
+ But appending options to the end of the config isn't very effective if your config is organizated per the recommendations of ssh_config(5) that the generic options are at at the end of the config, such as:
160
+
161
+ ```
162
+ Host ness
163
+ HostName lochness.com
164
+ User dinosaur
165
+
166
+ IdentityFile ~/.ssh/id_rsa
167
+ ```
168
+
169
+ The config could get messy if you put new options after the line of `IdentityFile`. To work around this issue, it is recommended that `.prepend` should be used instead. For the example above, we can prepend new options at the beginning of the config:
170
+
171
+ ```js
172
+ config.prepend({
173
+ Host: 'tahoe',
174
+ HostName 'tahoe.com',
175
+ })
176
+ ```
177
+
178
+ The result would be:
179
+
180
+ ```
181
+ Host tahoe
182
+ HostName tahoe.com
183
+
184
+ Host ness
185
+ HostName lochness.com
186
+ User dinosaur
187
+
188
+ IdentityFile ~/.ssh/id_rsa
189
+ ```
190
+
191
+ If there are generic options at the beginning of the config, and you'd like the prepended section put before the first existing section, please turn on the second argument of `.prepend`:
192
+
193
+ ```js
194
+ config.prepend({
195
+ Host: 'tahoe',
196
+ HostName 'tahoe.com',
197
+ }, true)
198
+ ```
199
+
200
+ The result would be like:
201
+
202
+ ```
203
+ IdentityFile ~/.ssh/id_rsa
204
+
205
+ Host tahoe
206
+ HostName tahoe.com
207
+
208
+ Host ness
209
+ HostName lochness.com
210
+ User dinosaur
211
+ ```
212
+
157
213
  ## References
158
214
 
159
215
  - [ssh_config(5)][ssh_config]
package/index.js CHANGED
@@ -5,17 +5,13 @@ const glob = require('./src/glob')
5
5
  const RE_SPACE = /\s/
6
6
  const RE_LINE_BREAK = /\r|\n/
7
7
  const RE_SECTION_DIRECTIVE = /^(Host|Match)$/i
8
- const RE_MULTI_VALUE_DIRECTIVE = /^(GlobalKnownHostsFile|Host|IPQoS|SendEnv|UserKnownHostsFile)$/i
9
- const RE_QUOTE_DIRECTIVE = /^(?:CertificateFile|IdentityFile|User)$/i
8
+ const RE_MULTI_VALUE_DIRECTIVE = /^(GlobalKnownHostsFile|Host|IPQoS|SendEnv|UserKnownHostsFile|ProxyCommand)$/i
9
+ const RE_QUOTE_DIRECTIVE = /^(?:CertificateFile|IdentityFile|IdentityAgent|User)$/i
10
10
  const RE_SINGLE_LINE_DIRECTIVE = /^(Include|IdentityFile)$/i
11
11
 
12
12
  const DIRECTIVE = 1
13
13
  const COMMENT = 2
14
14
 
15
- function compare(line, opts) {
16
- return opts.hasOwnProperty(line.param) && opts[line.param] === line.value
17
- }
18
-
19
15
  const MULTIPLE_VALUE_PROPS = [
20
16
  'IdentityFile',
21
17
  'LocalForward',
@@ -24,6 +20,24 @@ const MULTIPLE_VALUE_PROPS = [
24
20
  'CertificateFile'
25
21
  ]
26
22
 
23
+ function compare(line, opts) {
24
+ return opts.hasOwnProperty(line.param) && opts[line.param] === line.value
25
+ }
26
+
27
+ function getIndent(config) {
28
+ for (const line of config) {
29
+ if (RE_SECTION_DIRECTIVE.test(line.param)) {
30
+ for (const subline of line.config) {
31
+ if (subline.before) {
32
+ return subline.before
33
+ }
34
+ }
35
+ }
36
+ }
37
+
38
+ return ' '
39
+ }
40
+
27
41
  class SSHConfig extends Array {
28
42
  /**
29
43
  * Query ssh config by host.
@@ -106,20 +120,7 @@ class SSHConfig extends Array {
106
120
  * @param {Object} opts
107
121
  */
108
122
  append(opts) {
109
- let indent = ' '
110
-
111
- outer:
112
- for (const line of this) {
113
- if (RE_SECTION_DIRECTIVE.test(line.param)) {
114
- for (const subline of line.config) {
115
- if (subline.before) {
116
- indent = subline.before
117
- break outer
118
- }
119
- }
120
- }
121
- }
122
-
123
+ const indent = getIndent(this)
123
124
  const lastEntry = this.length > 0 ? this[this.length - 1] : null
124
125
  let config = lastEntry && lastEntry.config || this
125
126
  let configWas = this
@@ -158,21 +159,8 @@ class SSHConfig extends Array {
158
159
  * Prepend new section to existing ssh config.
159
160
  * @param {Object} opts
160
161
  */
161
- prepend(opts, beforeFirstSection = false) {
162
- let indent = ' '
163
-
164
- outer:
165
- for (const line of this) {
166
- if (RE_SECTION_DIRECTIVE.test(line.param)) {
167
- for (const subline of line.config) {
168
- if (subline.before) {
169
- indent = subline.before
170
- break outer
171
- }
172
- }
173
- }
174
- }
175
-
162
+ prepend(opts, beforeFirstSection = false) {
163
+ const indent = getIndent(this)
176
164
  let config = this
177
165
  let i = 0
178
166
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "ssh-config",
3
3
  "description": "SSH config parser and stringifier",
4
- "version": "4.1.0",
4
+ "version": "4.1.3",
5
5
  "author": "Chen Yangjian (https://www.cyj.me)",
6
6
  "repository": {
7
7
  "type": "git",
@@ -9,7 +9,8 @@
9
9
  },
10
10
  "files": [
11
11
  "index.js",
12
- "src"
12
+ "src",
13
+ "types"
13
14
  ],
14
15
  "devDependencies": {
15
16
  "eslint": "^7.17.0",
@@ -25,5 +26,6 @@
25
26
  "engine": {
26
27
  "node": ">= 10.0.0"
27
28
  },
29
+ "types": "types/index.d.ts",
28
30
  "license": "MIT"
29
31
  }
@@ -0,0 +1,41 @@
1
+ declare enum ELine {
2
+ DIRECTIVE = 1,
3
+ COMMENT = 2,
4
+ }
5
+
6
+ interface Directive {
7
+ type: ELine.DIRECTIVE;
8
+ before: string;
9
+ after: string;
10
+ param: string;
11
+ separator: ' ' | '=';
12
+ value: string;
13
+ }
14
+
15
+ interface Section extends Directive {
16
+ config: SSHConfig;
17
+ }
18
+
19
+ interface Comment {
20
+ type: ELine.COMMENT;
21
+ content: string;
22
+ }
23
+
24
+ type Line = Directive | Comment;
25
+
26
+ export default class SSHConfig extends Array {
27
+ static parse(text: string): SSHConfig;
28
+ static stringify(config: SSHConfig): string;
29
+
30
+ toString(): string;
31
+
32
+ compute(host: string): Record<string, string>;
33
+
34
+ find(predicate: (value: any, index: number, obj: any[]) => any);
35
+ find(options: Record<string, string>): Line | Section;
36
+
37
+ remove(options: Record<string, string>): Line | Section;
38
+
39
+ append(options: Record<string, string>): SSHConfig;
40
+ prepend(options: Record<string, string>): SSHConfig;
41
+ }
@@ -0,0 +1,10 @@
1
+ import SSHConfig from './index';
2
+
3
+ const config = SSHConfig.parse(`
4
+ IdentityFile ~/.ssh/id_rsa
5
+
6
+ Host ness
7
+ HostName lochness.com
8
+ `);
9
+
10
+ console.log(config.toString());