@florianpat/lando-core 3.23.27-4florianPat.2 → 3.23.27-5florianPat.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/CHANGELOG.md +1 -1
- package/hooks/plugin-auth-from-npmrc.js +25 -0
- package/index.js +3 -1
- package/lib/art.js +1 -1
- package/lib/daemon.js +3 -3
- package/node_modules/ini/LICENSE +15 -0
- package/node_modules/ini/README.md +180 -0
- package/node_modules/ini/lib/ini.js +280 -0
- package/node_modules/ini/package.json +45 -0
- package/package.json +7 -5
- package/plugins/networking/index.js +1 -1
- package/plugins/proxy/lib/utils.js +1 -1
- package/tasks/setup.js +1 -1
- package/utils/get-config-defaults.js +1 -2
- package/utils/get-docker-bin-path.js +1 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
## {{ UNRELEASED_VERSION }} - [{{ UNRELEASED_DATE }}]({{ UNRELEASED_LINK }})
|
|
2
2
|
|
|
3
|
-
## v3.23.27-
|
|
3
|
+
## v3.23.27-5florianPat.1 - [August 25, 2025](https://github.com/florianPat/lando-core/releases/tag/v3.23.27-5florianPat.1)
|
|
4
4
|
|
|
5
5
|
## v3.23.26 - [January 24, 2025](https://github.com/lando/core/releases/tag/v3.23.26)
|
|
6
6
|
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const write = require('../utils/write-file');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const os = require('os');
|
|
7
|
+
const {parse} = require('ini');
|
|
8
|
+
|
|
9
|
+
module.exports = async lando => {
|
|
10
|
+
if (!lando.config.loadNpmrcForPluginAuth) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const npmrcPath = path.resolve(os.homedir(), '.npmrc');
|
|
15
|
+
if (!fs.existsSync(npmrcPath)) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
lando.log.debug('Reading home .npmrc for plugin-auth.json...');
|
|
19
|
+
const content = fs.readFileSync(npmrcPath, {
|
|
20
|
+
encoding: 'utf-8',
|
|
21
|
+
});
|
|
22
|
+
const data = parse(content);
|
|
23
|
+
write(lando.config.pluginConfigFile, data);
|
|
24
|
+
lando.plugins.updates = data;
|
|
25
|
+
};
|
package/index.js
CHANGED
|
@@ -61,7 +61,7 @@ module.exports = async lando => {
|
|
|
61
61
|
lando.events.on('pre-setup', 0, async () => await require('./hooks/lando-copy-v3-scripts')(lando));
|
|
62
62
|
|
|
63
63
|
// ensure we setup docker if needed
|
|
64
|
-
lando.events.once('pre-setup', async options => await require(`./hooks/lando-setup-build-engine-${platform}`)(lando, options));
|
|
64
|
+
lando.events.once('pre-setup', async options => await require(`./hooks/lando-setup-build-engine-${process.platform}`)(lando, options));
|
|
65
65
|
|
|
66
66
|
// do some sepecial handling on wsl
|
|
67
67
|
lando.events.once('pre-setup', async options => await require('./hooks/lando-setup-create-ca-wsl')(lando, options));
|
|
@@ -102,6 +102,8 @@ module.exports = async lando => {
|
|
|
102
102
|
// move v3 scripts directories as needed
|
|
103
103
|
lando.events.on('pre-engine-start', 0, async () => await require('./hooks/lando-copy-v3-scripts')(lando));
|
|
104
104
|
|
|
105
|
+
lando.events.on('post-bootstrap-config', async () => await require('./hooks/plugin-auth-from-npmrc')(lando));
|
|
106
|
+
|
|
105
107
|
// return some default things
|
|
106
108
|
return _.merge({}, defaults, uc(), {config: {
|
|
107
109
|
appEnv: {
|
package/lib/art.js
CHANGED
|
@@ -300,7 +300,7 @@ exports.newContent = (type = 'guide') => [
|
|
|
300
300
|
'',
|
|
301
301
|
].join(os.EOL);
|
|
302
302
|
|
|
303
|
-
exports.setupHeader = (bengine =
|
|
303
|
+
exports.setupHeader = (bengine = ['linux', 'wsl'].includes(process.landoPlatform) ? 'Engine' : 'Desktop') => `
|
|
304
304
|
${chalk.magenta(niceFont('Lando Setup!', 'Small Slant'))}
|
|
305
305
|
|
|
306
306
|
${chalk.bold('lando setup')} is a hidden convenience command to help you satisify the
|
package/lib/daemon.js
CHANGED
|
@@ -28,9 +28,9 @@ const buildDockerCmd = (cmd, scriptsDir, dockerBin) => {
|
|
|
28
28
|
case 'darwin':
|
|
29
29
|
return ['open', MACOS_BASE];
|
|
30
30
|
case 'linux':
|
|
31
|
+
case 'wsl':
|
|
31
32
|
return [path.join(scriptsDir, `docker-engine-${cmd}.sh`)];
|
|
32
33
|
case 'win32':
|
|
33
|
-
case 'wsl':
|
|
34
34
|
return ['powershell.exe', '-ExecutionPolicy', 'Bypass', '-File', `"${windowsStartScript}"`];
|
|
35
35
|
}
|
|
36
36
|
};
|
|
@@ -107,12 +107,12 @@ module.exports = class LandoDaemon {
|
|
|
107
107
|
await require('../utils/run-command')('open', [MACOS_BASE], {debug: this.debug});
|
|
108
108
|
break;
|
|
109
109
|
case 'linux':
|
|
110
|
+
case 'wsl':
|
|
110
111
|
const lscript = path.join(this.scriptsDir, 'docker-engine-start.sh');
|
|
111
112
|
if (password) await require('../utils/run-elevated')([lscript], {debug, password});
|
|
112
113
|
else await require('../utils/run-command')(lscript, {debug});
|
|
113
114
|
break;
|
|
114
115
|
case 'win32':
|
|
115
|
-
case 'wsl':
|
|
116
116
|
const wscript = path.join(this.scriptsDir, 'docker-desktop-start.ps1');
|
|
117
117
|
await require('../utils/run-powershell-script')(wscript, undefined, {debug: this.debug});
|
|
118
118
|
await require('delay')(2000);
|
|
@@ -226,10 +226,10 @@ module.exports = class LandoDaemon {
|
|
|
226
226
|
case 'darwin':
|
|
227
227
|
return getMacProp('CFBundleShortVersionString').then(version => ({...versions, desktop: version}));
|
|
228
228
|
case 'linux':
|
|
229
|
+
case 'wsl':
|
|
229
230
|
const cmd = [`"${this.docker}"`, 'version', '--format', '{{.Server.Version}}'];
|
|
230
231
|
return shell.sh(cmd).catch(() => '18.0.0').then(version => ({...versions, engine: version}));
|
|
231
232
|
case 'win32':
|
|
232
|
-
case 'wsl':
|
|
233
233
|
const componentsVersionFile = this.platform === 'win32'
|
|
234
234
|
? path.resolve(getDockerBinPath('win32'), '..', 'componentsVersion.json') : '/Docker/host/componentsVersion.json';
|
|
235
235
|
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
The ISC License
|
|
2
|
+
|
|
3
|
+
Copyright (c) Isaac Z. Schlueter and Contributors
|
|
4
|
+
|
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any
|
|
6
|
+
purpose with or without fee is hereby granted, provided that the above
|
|
7
|
+
copyright notice and this permission notice appear in all copies.
|
|
8
|
+
|
|
9
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
|
10
|
+
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
|
11
|
+
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
|
12
|
+
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
|
13
|
+
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
|
14
|
+
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
|
|
15
|
+
IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
|
|
2
|
+
An INI format parser & serializer.
|
|
3
|
+
|
|
4
|
+
## Note
|
|
5
|
+
|
|
6
|
+
- Sections are treated as nested objects.
|
|
7
|
+
|
|
8
|
+
- Section-less items are treated as globals.
|
|
9
|
+
|
|
10
|
+
## Usage
|
|
11
|
+
|
|
12
|
+
Consider an INI file such as the following:
|
|
13
|
+
|
|
14
|
+
```ini
|
|
15
|
+
; This comment is being ignored
|
|
16
|
+
scope = global
|
|
17
|
+
|
|
18
|
+
[database]
|
|
19
|
+
user = dbuser
|
|
20
|
+
password = dbpassword
|
|
21
|
+
database = use_this_database
|
|
22
|
+
|
|
23
|
+
[paths.default]
|
|
24
|
+
datadir = /var/lib/data
|
|
25
|
+
array[] = first value
|
|
26
|
+
array[] = second value
|
|
27
|
+
array[] = third value
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
You can **read**, **modify** and **write** it like so:
|
|
31
|
+
|
|
32
|
+
```js
|
|
33
|
+
import { writeFile , readFile } from 'node:fs/promises'
|
|
34
|
+
import { stringify , parse } from 'ini'
|
|
35
|
+
|
|
36
|
+
// Read INI file as text
|
|
37
|
+
|
|
38
|
+
let text = await readFile(`./Original.ini`,{
|
|
39
|
+
encoding : 'utf-8'
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
// Parse text data to object
|
|
43
|
+
|
|
44
|
+
const config = parse(text)
|
|
45
|
+
|
|
46
|
+
// Modify data object
|
|
47
|
+
|
|
48
|
+
config.scope = 'local'
|
|
49
|
+
config.database.database = 'use_another_database'
|
|
50
|
+
config.paths.default.tmpdir = '/tmp'
|
|
51
|
+
delete config.paths.default.datadir
|
|
52
|
+
config.paths.default.array.push('fourth value')
|
|
53
|
+
|
|
54
|
+
// Stringify data object
|
|
55
|
+
|
|
56
|
+
text = stringify(config,{
|
|
57
|
+
section : 'section'
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
// Write INI file as text
|
|
61
|
+
|
|
62
|
+
await writeFile(`./Modified.ini`,text)
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
The written file will contain the following:
|
|
66
|
+
|
|
67
|
+
```ini
|
|
68
|
+
[section]
|
|
69
|
+
scope=local
|
|
70
|
+
[section.database]
|
|
71
|
+
user=dbuser
|
|
72
|
+
password=dbpassword
|
|
73
|
+
database=use_another_database
|
|
74
|
+
[section.paths.default]
|
|
75
|
+
tmpdir=/tmp
|
|
76
|
+
array[]=first value
|
|
77
|
+
array[]=second value
|
|
78
|
+
array[]=third value
|
|
79
|
+
array[]=fourth value
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## API
|
|
83
|
+
|
|
84
|
+
### Parse
|
|
85
|
+
|
|
86
|
+
Attempts to turn the given INI string into a nested data object.
|
|
87
|
+
|
|
88
|
+
```js
|
|
89
|
+
// You can also use `decode`
|
|
90
|
+
const object = parse(`<INI Text>`)
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Stringify
|
|
94
|
+
|
|
95
|
+
Encodes the given data object as an INI formatted string.
|
|
96
|
+
|
|
97
|
+
```js
|
|
98
|
+
// You can also use `encode`
|
|
99
|
+
stringify(object,{
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Whether to insert spaces before & after `=`
|
|
103
|
+
*
|
|
104
|
+
* Disabled by default to have better
|
|
105
|
+
* compatibility with old picky parsers.
|
|
106
|
+
*/
|
|
107
|
+
|
|
108
|
+
whitespace : false ,
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Whether to align the `=` character for each section.
|
|
112
|
+
* -> Also enables the `whitespace` option
|
|
113
|
+
*/
|
|
114
|
+
|
|
115
|
+
align : false ,
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Identifier to use for global items
|
|
119
|
+
* and to prepend to all other sections.
|
|
120
|
+
*/
|
|
121
|
+
|
|
122
|
+
section ,
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Whether to sort all sections & their keys alphabetically.
|
|
126
|
+
*/
|
|
127
|
+
|
|
128
|
+
sort : false ,
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Whether to insert a newline after each section header.
|
|
132
|
+
*
|
|
133
|
+
* The TOSHIBA & FlashAir parser require this format.
|
|
134
|
+
*/
|
|
135
|
+
|
|
136
|
+
newline : false ,
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Which platforms line-endings should be used.
|
|
140
|
+
*
|
|
141
|
+
* win32 -> CR+LF
|
|
142
|
+
* other -> LF
|
|
143
|
+
*
|
|
144
|
+
* Default is the current platform
|
|
145
|
+
*/
|
|
146
|
+
|
|
147
|
+
platform ,
|
|
148
|
+
|
|
149
|
+
/**
|
|
150
|
+
* Whether to append `[]` to array keys.
|
|
151
|
+
*
|
|
152
|
+
* Some parsers treat duplicate names by themselves as arrays
|
|
153
|
+
*/
|
|
154
|
+
|
|
155
|
+
bracketedArray : true
|
|
156
|
+
|
|
157
|
+
})
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
*For backwards compatibility any string passed as the*
|
|
161
|
+
*options parameter is treated as the `section` option.*
|
|
162
|
+
|
|
163
|
+
```js
|
|
164
|
+
stringify(object,'section')
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Un / Escape
|
|
168
|
+
|
|
169
|
+
Turn the given string into a safe to
|
|
170
|
+
use key or value in your INI file.
|
|
171
|
+
|
|
172
|
+
```js
|
|
173
|
+
safe(`"unsafe string"`) // -> \"unsafe string\"
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
Or reverse the process with:
|
|
177
|
+
|
|
178
|
+
```js
|
|
179
|
+
unsafe(`\\"safe string\\"`) // -> "safe string"
|
|
180
|
+
```
|
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
const { hasOwnProperty } = Object.prototype
|
|
2
|
+
|
|
3
|
+
const encode = (obj, opt = {}) => {
|
|
4
|
+
if (typeof opt === 'string') {
|
|
5
|
+
opt = { section: opt }
|
|
6
|
+
}
|
|
7
|
+
opt.align = opt.align === true
|
|
8
|
+
opt.newline = opt.newline === true
|
|
9
|
+
opt.sort = opt.sort === true
|
|
10
|
+
opt.whitespace = opt.whitespace === true || opt.align === true
|
|
11
|
+
// The `typeof` check is required because accessing the `process` directly fails on browsers.
|
|
12
|
+
/* istanbul ignore next */
|
|
13
|
+
opt.platform = opt.platform || (typeof process !== 'undefined' && process.platform)
|
|
14
|
+
opt.bracketedArray = opt.bracketedArray !== false
|
|
15
|
+
|
|
16
|
+
/* istanbul ignore next */
|
|
17
|
+
const eol = opt.platform === 'win32' ? '\r\n' : '\n'
|
|
18
|
+
const separator = opt.whitespace ? ' = ' : '='
|
|
19
|
+
const children = []
|
|
20
|
+
|
|
21
|
+
const keys = opt.sort ? Object.keys(obj).sort() : Object.keys(obj)
|
|
22
|
+
|
|
23
|
+
let padToChars = 0
|
|
24
|
+
// If aligning on the separator, then padToChars is determined as follows:
|
|
25
|
+
// 1. Get the keys
|
|
26
|
+
// 2. Exclude keys pointing to objects unless the value is null or an array
|
|
27
|
+
// 3. Add `[]` to array keys
|
|
28
|
+
// 4. Ensure non empty set of keys
|
|
29
|
+
// 5. Reduce the set to the longest `safe` key
|
|
30
|
+
// 6. Get the `safe` length
|
|
31
|
+
if (opt.align) {
|
|
32
|
+
padToChars = safe(
|
|
33
|
+
(
|
|
34
|
+
keys
|
|
35
|
+
.filter(k => obj[k] === null || Array.isArray(obj[k]) || typeof obj[k] !== 'object')
|
|
36
|
+
.map(k => Array.isArray(obj[k]) ? `${k}[]` : k)
|
|
37
|
+
)
|
|
38
|
+
.concat([''])
|
|
39
|
+
.reduce((a, b) => safe(a).length >= safe(b).length ? a : b)
|
|
40
|
+
).length
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
let out = ''
|
|
44
|
+
const arraySuffix = opt.bracketedArray ? '[]' : ''
|
|
45
|
+
|
|
46
|
+
for (const k of keys) {
|
|
47
|
+
const val = obj[k]
|
|
48
|
+
if (val && Array.isArray(val)) {
|
|
49
|
+
for (const item of val) {
|
|
50
|
+
out += safe(`${k}${arraySuffix}`).padEnd(padToChars, ' ') + separator + safe(item) + eol
|
|
51
|
+
}
|
|
52
|
+
} else if (val && typeof val === 'object') {
|
|
53
|
+
children.push(k)
|
|
54
|
+
} else {
|
|
55
|
+
out += safe(k).padEnd(padToChars, ' ') + separator + safe(val) + eol
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (opt.section && out.length) {
|
|
60
|
+
out = '[' + safe(opt.section) + ']' + (opt.newline ? eol + eol : eol) + out
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
for (const k of children) {
|
|
64
|
+
const nk = splitSections(k, '.').join('\\.')
|
|
65
|
+
const section = (opt.section ? opt.section + '.' : '') + nk
|
|
66
|
+
const child = encode(obj[k], {
|
|
67
|
+
...opt,
|
|
68
|
+
section,
|
|
69
|
+
})
|
|
70
|
+
if (out.length && child.length) {
|
|
71
|
+
out += eol
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
out += child
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return out
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
function splitSections (str, separator) {
|
|
81
|
+
var lastMatchIndex = 0
|
|
82
|
+
var lastSeparatorIndex = 0
|
|
83
|
+
var nextIndex = 0
|
|
84
|
+
var sections = []
|
|
85
|
+
|
|
86
|
+
do {
|
|
87
|
+
nextIndex = str.indexOf(separator, lastMatchIndex)
|
|
88
|
+
|
|
89
|
+
if (nextIndex !== -1) {
|
|
90
|
+
lastMatchIndex = nextIndex + separator.length
|
|
91
|
+
|
|
92
|
+
if (nextIndex > 0 && str[nextIndex - 1] === '\\') {
|
|
93
|
+
continue
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
sections.push(str.slice(lastSeparatorIndex, nextIndex))
|
|
97
|
+
lastSeparatorIndex = nextIndex + separator.length
|
|
98
|
+
}
|
|
99
|
+
} while (nextIndex !== -1)
|
|
100
|
+
|
|
101
|
+
sections.push(str.slice(lastSeparatorIndex))
|
|
102
|
+
|
|
103
|
+
return sections
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const decode = (str, opt = {}) => {
|
|
107
|
+
opt.bracketedArray = opt.bracketedArray !== false
|
|
108
|
+
const out = Object.create(null)
|
|
109
|
+
let p = out
|
|
110
|
+
let section = null
|
|
111
|
+
// section |key = value
|
|
112
|
+
const re = /^\[([^\]]*)\]\s*$|^([^=]+)(=(.*))?$/i
|
|
113
|
+
const lines = str.split(/[\r\n]+/g)
|
|
114
|
+
const duplicates = {}
|
|
115
|
+
|
|
116
|
+
for (const line of lines) {
|
|
117
|
+
if (!line || line.match(/^\s*[;#]/) || line.match(/^\s*$/)) {
|
|
118
|
+
continue
|
|
119
|
+
}
|
|
120
|
+
const match = line.match(re)
|
|
121
|
+
if (!match) {
|
|
122
|
+
continue
|
|
123
|
+
}
|
|
124
|
+
if (match[1] !== undefined) {
|
|
125
|
+
section = unsafe(match[1])
|
|
126
|
+
if (section === '__proto__') {
|
|
127
|
+
// not allowed
|
|
128
|
+
// keep parsing the section, but don't attach it.
|
|
129
|
+
p = Object.create(null)
|
|
130
|
+
continue
|
|
131
|
+
}
|
|
132
|
+
p = out[section] = out[section] || Object.create(null)
|
|
133
|
+
continue
|
|
134
|
+
}
|
|
135
|
+
const keyRaw = unsafe(match[2])
|
|
136
|
+
let isArray
|
|
137
|
+
if (opt.bracketedArray) {
|
|
138
|
+
isArray = keyRaw.length > 2 && keyRaw.slice(-2) === '[]'
|
|
139
|
+
} else {
|
|
140
|
+
duplicates[keyRaw] = (duplicates?.[keyRaw] || 0) + 1
|
|
141
|
+
isArray = duplicates[keyRaw] > 1
|
|
142
|
+
}
|
|
143
|
+
const key = isArray && keyRaw.endsWith('[]')
|
|
144
|
+
? keyRaw.slice(0, -2) : keyRaw
|
|
145
|
+
|
|
146
|
+
if (key === '__proto__') {
|
|
147
|
+
continue
|
|
148
|
+
}
|
|
149
|
+
const valueRaw = match[3] ? unsafe(match[4]) : true
|
|
150
|
+
const value = valueRaw === 'true' ||
|
|
151
|
+
valueRaw === 'false' ||
|
|
152
|
+
valueRaw === 'null' ? JSON.parse(valueRaw)
|
|
153
|
+
: valueRaw
|
|
154
|
+
|
|
155
|
+
// Convert keys with '[]' suffix to an array
|
|
156
|
+
if (isArray) {
|
|
157
|
+
if (!hasOwnProperty.call(p, key)) {
|
|
158
|
+
p[key] = []
|
|
159
|
+
} else if (!Array.isArray(p[key])) {
|
|
160
|
+
p[key] = [p[key]]
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// safeguard against resetting a previously defined
|
|
165
|
+
// array by accidentally forgetting the brackets
|
|
166
|
+
if (Array.isArray(p[key])) {
|
|
167
|
+
p[key].push(value)
|
|
168
|
+
} else {
|
|
169
|
+
p[key] = value
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// {a:{y:1},"a.b":{x:2}} --> {a:{y:1,b:{x:2}}}
|
|
174
|
+
// use a filter to return the keys that have to be deleted.
|
|
175
|
+
const remove = []
|
|
176
|
+
for (const k of Object.keys(out)) {
|
|
177
|
+
if (!hasOwnProperty.call(out, k) ||
|
|
178
|
+
typeof out[k] !== 'object' ||
|
|
179
|
+
Array.isArray(out[k])) {
|
|
180
|
+
continue
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// see if the parent section is also an object.
|
|
184
|
+
// if so, add it to that, and mark this one for deletion
|
|
185
|
+
const parts = splitSections(k, '.')
|
|
186
|
+
p = out
|
|
187
|
+
const l = parts.pop()
|
|
188
|
+
const nl = l.replace(/\\\./g, '.')
|
|
189
|
+
for (const part of parts) {
|
|
190
|
+
if (part === '__proto__') {
|
|
191
|
+
continue
|
|
192
|
+
}
|
|
193
|
+
if (!hasOwnProperty.call(p, part) || typeof p[part] !== 'object') {
|
|
194
|
+
p[part] = Object.create(null)
|
|
195
|
+
}
|
|
196
|
+
p = p[part]
|
|
197
|
+
}
|
|
198
|
+
if (p === out && nl === l) {
|
|
199
|
+
continue
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
p[nl] = out[k]
|
|
203
|
+
remove.push(k)
|
|
204
|
+
}
|
|
205
|
+
for (const del of remove) {
|
|
206
|
+
delete out[del]
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
return out
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
const isQuoted = val => {
|
|
213
|
+
return (val.startsWith('"') && val.endsWith('"')) ||
|
|
214
|
+
(val.startsWith("'") && val.endsWith("'"))
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
const safe = val => {
|
|
218
|
+
if (
|
|
219
|
+
typeof val !== 'string' ||
|
|
220
|
+
val.match(/[=\r\n]/) ||
|
|
221
|
+
val.match(/^\[/) ||
|
|
222
|
+
(val.length > 1 && isQuoted(val)) ||
|
|
223
|
+
val !== val.trim()
|
|
224
|
+
) {
|
|
225
|
+
return JSON.stringify(val)
|
|
226
|
+
}
|
|
227
|
+
return val.split(';').join('\\;').split('#').join('\\#')
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const unsafe = val => {
|
|
231
|
+
val = (val || '').trim()
|
|
232
|
+
if (isQuoted(val)) {
|
|
233
|
+
// remove the single quotes before calling JSON.parse
|
|
234
|
+
if (val.charAt(0) === "'") {
|
|
235
|
+
val = val.slice(1, -1)
|
|
236
|
+
}
|
|
237
|
+
try {
|
|
238
|
+
val = JSON.parse(val)
|
|
239
|
+
} catch {
|
|
240
|
+
// ignore errors
|
|
241
|
+
}
|
|
242
|
+
} else {
|
|
243
|
+
// walk the val to find the first not-escaped ; character
|
|
244
|
+
let esc = false
|
|
245
|
+
let unesc = ''
|
|
246
|
+
for (let i = 0, l = val.length; i < l; i++) {
|
|
247
|
+
const c = val.charAt(i)
|
|
248
|
+
if (esc) {
|
|
249
|
+
if ('\\;#'.indexOf(c) !== -1) {
|
|
250
|
+
unesc += c
|
|
251
|
+
} else {
|
|
252
|
+
unesc += '\\' + c
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
esc = false
|
|
256
|
+
} else if (';#'.indexOf(c) !== -1) {
|
|
257
|
+
break
|
|
258
|
+
} else if (c === '\\') {
|
|
259
|
+
esc = true
|
|
260
|
+
} else {
|
|
261
|
+
unesc += c
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
if (esc) {
|
|
265
|
+
unesc += '\\'
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
return unesc.trim()
|
|
269
|
+
}
|
|
270
|
+
return val
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
module.exports = {
|
|
274
|
+
parse: decode,
|
|
275
|
+
decode,
|
|
276
|
+
stringify: encode,
|
|
277
|
+
encode,
|
|
278
|
+
safe,
|
|
279
|
+
unsafe,
|
|
280
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"author": "GitHub Inc.",
|
|
3
|
+
"name": "ini",
|
|
4
|
+
"description": "An ini encoder/decoder for node",
|
|
5
|
+
"version": "5.0.0",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/npm/ini.git"
|
|
9
|
+
},
|
|
10
|
+
"main": "lib/ini.js",
|
|
11
|
+
"scripts": {
|
|
12
|
+
"eslint": "eslint \"**/*.{js,cjs,ts,mjs,jsx,tsx}\"",
|
|
13
|
+
"lint": "npm run eslint",
|
|
14
|
+
"lintfix": "npm run eslint -- --fix",
|
|
15
|
+
"test": "tap",
|
|
16
|
+
"snap": "tap",
|
|
17
|
+
"posttest": "npm run lint",
|
|
18
|
+
"postlint": "template-oss-check",
|
|
19
|
+
"template-oss-apply": "template-oss-apply --force"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@npmcli/eslint-config": "^5.0.0",
|
|
23
|
+
"@npmcli/template-oss": "4.23.3",
|
|
24
|
+
"tap": "^16.0.1"
|
|
25
|
+
},
|
|
26
|
+
"license": "ISC",
|
|
27
|
+
"files": [
|
|
28
|
+
"bin/",
|
|
29
|
+
"lib/"
|
|
30
|
+
],
|
|
31
|
+
"engines": {
|
|
32
|
+
"node": "^18.17.0 || >=20.5.0"
|
|
33
|
+
},
|
|
34
|
+
"templateOSS": {
|
|
35
|
+
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
|
|
36
|
+
"version": "4.23.3",
|
|
37
|
+
"publish": "true"
|
|
38
|
+
},
|
|
39
|
+
"tap": {
|
|
40
|
+
"nyc-arg": [
|
|
41
|
+
"--exclude",
|
|
42
|
+
"tap-snapshots/**"
|
|
43
|
+
]
|
|
44
|
+
}
|
|
45
|
+
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@florianpat/lando-core",
|
|
3
3
|
"description": "The libraries that power all of Lando. Fork by flo for compose integration",
|
|
4
|
-
"version": "3.23.27-
|
|
4
|
+
"version": "3.23.27-5florianPat.1",
|
|
5
5
|
"author": "Florian Patruck @florianPat",
|
|
6
6
|
"license": "GPL-3.0",
|
|
7
7
|
"repository": "florianPat/lando-core",
|
|
@@ -127,6 +127,7 @@
|
|
|
127
127
|
"figures": "^3.2.0",
|
|
128
128
|
"fs-extra": "^11.1.1",
|
|
129
129
|
"glob": "^7.1.3",
|
|
130
|
+
"ini": "^5.0.0",
|
|
130
131
|
"inquirer": "^6.5.2",
|
|
131
132
|
"inquirer-autocomplete-prompt": "^1.4.0",
|
|
132
133
|
"is-class": "^0.0.9",
|
|
@@ -208,6 +209,7 @@
|
|
|
208
209
|
"figures",
|
|
209
210
|
"fs-extra",
|
|
210
211
|
"glob",
|
|
212
|
+
"ini",
|
|
211
213
|
"inquirer",
|
|
212
214
|
"inquirer-autocomplete-prompt",
|
|
213
215
|
"is-class",
|
|
@@ -247,9 +249,9 @@
|
|
|
247
249
|
"yargs-parser"
|
|
248
250
|
],
|
|
249
251
|
"dist": {
|
|
250
|
-
"integrity": "sha512-
|
|
251
|
-
"shasum": "
|
|
252
|
-
"filename": "florianpat-lando-core-3.23.27-
|
|
253
|
-
"unpackedSize":
|
|
252
|
+
"integrity": "sha512-fKWOfM4UYDTsbPvvdsPG82hLRiDToxg9tTZeytY7Xr5BGs/HcR0NufBpTJ42Dd/zMNxsYp8undbxnHsHxC3ESw==",
|
|
253
|
+
"shasum": "03cc7ac953797fae05985d31f69a96efdfbcf351",
|
|
254
|
+
"filename": "florianpat-lando-core-3.23.27-5florianPat.1.tgz",
|
|
255
|
+
"unpackedSize": 60980524
|
|
254
256
|
}
|
|
255
257
|
}
|
|
@@ -76,7 +76,7 @@ module.exports = lando => {
|
|
|
76
76
|
if (lando.engine.dockerInstalled === false) return false;
|
|
77
77
|
|
|
78
78
|
// we also want to do an additional check on docker-destkop
|
|
79
|
-
if (lando.config.os.landoPlatform
|
|
79
|
+
if (!['linux', 'wsl'].includes(lando.config.os.landoPlatform) && !fs.existsSync(getDockerDesktopBin())) return false;
|
|
80
80
|
|
|
81
81
|
// otherwise attempt to sus things out
|
|
82
82
|
try {
|
|
@@ -167,7 +167,7 @@ exports.parseRoutes = (service, urls = [], sslReady, labels = {}) => {
|
|
|
167
167
|
rule.middlewares.push({name: 'lando', key: 'headers.customrequestheaders.X-Lando', value: 'on'});
|
|
168
168
|
|
|
169
169
|
// Add in any path stripping middleware we need it
|
|
170
|
-
if (rule.pathname.length > 1) {
|
|
170
|
+
if (rule.pathname.length > 1 && _.get(rule, 'stripPrefix', true)) {
|
|
171
171
|
rule.middlewares.push({name: 'stripprefix', key: 'stripprefix.prefixes', value: rule.pathname});
|
|
172
172
|
};
|
|
173
173
|
|
package/tasks/setup.js
CHANGED
|
@@ -67,7 +67,7 @@ module.exports = lando => {
|
|
|
67
67
|
// get defaults from the lando config
|
|
68
68
|
const defaults = lando.config.setup;
|
|
69
69
|
// determine label for build engine
|
|
70
|
-
const buildEngine =
|
|
70
|
+
const buildEngine = ['linux', 'wsl'].includes(process.landoPlatform) ? 'docker-engine' : 'docker-desktop';
|
|
71
71
|
// default options
|
|
72
72
|
const options = {
|
|
73
73
|
'build-engine': {
|
|
@@ -10,11 +10,10 @@ const getBuildEngineVersion = (platform = process.landoPlatform ?? process.platf
|
|
|
10
10
|
case 'darwin':
|
|
11
11
|
return '4.37.2';
|
|
12
12
|
case 'linux':
|
|
13
|
+
case 'wsl':
|
|
13
14
|
return '27.5.0';
|
|
14
15
|
case 'win32':
|
|
15
16
|
return '4.37.1';
|
|
16
|
-
case 'wsl':
|
|
17
|
-
return '4.37.1';
|
|
18
17
|
}
|
|
19
18
|
};
|
|
20
19
|
|
|
@@ -6,6 +6,7 @@ const path = require('path');
|
|
|
6
6
|
module.exports = (platform = process.landoPlatform ?? process.platform) => {
|
|
7
7
|
switch (platform) {
|
|
8
8
|
case 'linux':
|
|
9
|
+
case 'wsl':
|
|
9
10
|
return '/usr/share/lando/bin';
|
|
10
11
|
case 'win32':
|
|
11
12
|
const programFiles = process.env.ProgramW6432 || process.env.ProgramFiles;
|
|
@@ -17,8 +18,6 @@ module.exports = (platform = process.landoPlatform ?? process.platform) => {
|
|
|
17
18
|
} else {
|
|
18
19
|
return path.win32.join(programFiles + '\\Docker\\Docker\\resources\\bin');
|
|
19
20
|
}
|
|
20
|
-
case 'wsl':
|
|
21
|
-
return '/mnt/wsl/docker-desktop/cli-tools/usr/bin';
|
|
22
21
|
default:
|
|
23
22
|
return '/usr/bin';
|
|
24
23
|
}
|