diff --git a/docs/commands/lm.md b/docs/commands/lm.md deleted file mode 100644 index a8f3f0039dc..00000000000 --- a/docs/commands/lm.md +++ /dev/null @@ -1,94 +0,0 @@ ---- -title: Netlify CLI lm command ---- - -# `lm` - -## About - -> ⚠️ The Large Media feature was deprecated on September 1st, 2023 and will become unavailable in a future update. [Learn more and discover alternative solutions](https://answers.netlify.com/t/large-media-feature-deprecated-but-not-removed/100804) - -Handle Netlify Large Media operations - -The lm command will help you manage large media for a site - -**Usage** - -```bash -netlify lm -``` - -**Flags** - -- `debug` (*boolean*) - Print debugging information - -| Subcommand | description | -|:--------------------------- |:-----| -| [`lm:info`](/docs/commands/lm.md#lminfo) | Show large media requirements information. | -| [`lm:install`](/docs/commands/lm.md#lminstall) | Configures your computer to use Netlify Large Media | -| [`lm:setup`](/docs/commands/lm.md#lmsetup) | Configures your site to use Netlify Large Media | - - -**Examples** - -```bash -netlify lm:info -netlify lm:install -netlify lm:setup -``` - ---- -## `lm:info` - -Show large media requirements information. - -**Usage** - -```bash -netlify lm:info -``` - -**Flags** - -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in -- `debug` (*boolean*) - Print debugging information - ---- -## `lm:install` - -Configures your computer to use Netlify Large Media -It installs the required credentials helper for Git, -and configures your Git environment with the right credentials. - -**Usage** - -```bash -netlify lm:install -``` - -**Flags** - -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in -- `force` (*boolean*) - Force the credentials helper installation -- `debug` (*boolean*) - Print debugging information - ---- -## `lm:setup` - -Configures your site to use Netlify Large Media - -**Usage** - -```bash -netlify lm:setup -``` - -**Flags** - -- `filter` (*string*) - For monorepos, specify the name of the application to run the command in -- `force-install` (*boolean*) - Force the credentials helper installation -- `skip-install` (*boolean*) - Skip the credentials helper installation check -- `debug` (*boolean*) - Print debugging information - ---- - diff --git a/package-lock.json b/package-lock.json index 99994a86290..0143e3fd9aa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -62,7 +62,6 @@ "gh-release-fetch": "4.0.3", "git-repo-info": "2.1.1", "gitconfiglocal": "2.1.0", - "hasbin": "1.2.3", "hasha": "5.2.2", "http-proxy": "1.18.1", "http-proxy-middleware": "2.0.7", @@ -78,7 +77,6 @@ "jsonwebtoken": "9.0.2", "jwt-decode": "4.0.0", "lambda-local": "2.2.0", - "listr2": "8.2.5", "locate-path": "7.2.0", "lodash": "4.17.21", "log-symbols": "6.0.0", @@ -99,7 +97,6 @@ "parallel-transform": "1.2.0", "parse-github-url": "1.0.3", "parse-gitignore": "2.0.0", - "path-key": "4.0.0", "prettyjson": "1.2.5", "pump": "3.0.2", "raw-body": "2.5.2", @@ -154,7 +151,6 @@ "fs-extra": "11.2.0", "graphviz": "0.0.9", "husky": "8.0.3", - "ini": "4.1.3", "is-ci": "3.0.1", "mock-fs": "5.4.1", "nock": "13.5.6", @@ -2248,9 +2244,10 @@ } }, "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.9", @@ -9120,42 +9117,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cli-truncate": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", - "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", - "dependencies": { - "slice-ansi": "^5.0.0", - "string-width": "^7.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cli-truncate/node_modules/emoji-regex": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", - "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==" - }, - "node_modules/cli-truncate/node_modules/string-width": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", - "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/cli-width": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", @@ -9341,7 +9302,8 @@ "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true }, "node_modules/colors": { "version": "1.4.0", @@ -9849,10 +9811,11 @@ } }, "node_modules/cosmiconfig": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", - "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", "dev": true, + "license": "MIT", "dependencies": { "@types/parse-json": "^4.0.0", "import-fresh": "^3.2.1", @@ -14004,22 +13967,6 @@ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" }, - "node_modules/hasbin": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/hasbin/-/hasbin-1.2.3.tgz", - "integrity": "sha512-CCd8e/w2w28G8DyZvKgiHnQJ/5XXDz6qiUHnthvtag/6T5acUeN5lqq+HMoBqcmgWueWDhiCplrw0Kb1zDACRg==", - "dependencies": { - "async": "~1.5" - }, - "engines": { - "node": ">=0.10" - } - }, - "node_modules/hasbin/node_modules/async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==" - }, "node_modules/hasha": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", @@ -14396,15 +14343,6 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, - "node_modules/ini": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.3.tgz", - "integrity": "sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==", - "dev": true, - "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" - } - }, "node_modules/inquirer": { "version": "6.5.2", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", @@ -15019,17 +14957,6 @@ "node": ">=0.10.0" } }, - "node_modules/is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -15989,64 +15916,6 @@ "listhen": "bin/listhen.mjs" } }, - "node_modules/listr2": { - "version": "8.2.5", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.5.tgz", - "integrity": "sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==", - "dependencies": { - "cli-truncate": "^4.0.0", - "colorette": "^2.0.20", - "eventemitter3": "^5.0.1", - "log-update": "^6.1.0", - "rfdc": "^1.4.1", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/listr2/node_modules/emoji-regex": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", - "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==" - }, - "node_modules/listr2/node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" - }, - "node_modules/listr2/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/listr2/node_modules/wrap-ansi": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", - "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/local-pkg": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz", @@ -16528,15 +16397,13 @@ } }, "node_modules/magic-string": { - "version": "0.30.5", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz", - "integrity": "sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==", + "version": "0.30.14", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.14.tgz", + "integrity": "sha512-5c99P1WKTed11ZC0HMJOj6CDIue6F8ySu+bJL+85q1zBEIY8IklrJ1eiKC2NDRh3Ct3FcvmJPyQHb9erXMTJNw==", "dev": true, + "license": "MIT", "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.15" - }, - "engines": { - "node": ">=12" + "@jridgewell/sourcemap-codec": "^1.5.0" } }, "node_modules/magicast": { @@ -18762,9 +18629,10 @@ "dev": true }, "node_modules/picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", @@ -18991,9 +18859,9 @@ } }, "node_modules/postcss": { - "version": "8.4.47", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", - "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", "funding": [ { "type": "opencollective", @@ -19008,9 +18876,10 @@ "url": "https://github.com/sponsors/ai" } ], + "license": "MIT", "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.1.0", + "picocolors": "^1.1.1", "source-map-js": "^1.2.1" }, "engines": { @@ -20587,21 +20456,6 @@ "node": ">=8" } }, - "node_modules/slice-ansi": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", - "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", - "dependencies": { - "ansi-styles": "^6.0.0", - "is-fullwidth-code-point": "^4.0.0" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, "node_modules/sonic-boom": { "version": "3.8.1", "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.1.tgz", @@ -25605,9 +25459,9 @@ "dev": true }, "@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==" }, "@jridgewell/trace-mapping": { "version": "0.3.9", @@ -30179,32 +30033,6 @@ "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==" }, - "cli-truncate": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", - "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", - "requires": { - "slice-ansi": "^5.0.0", - "string-width": "^7.0.0" - }, - "dependencies": { - "emoji-regex": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", - "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==" - }, - "string-width": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", - "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", - "requires": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - } - } - } - }, "cli-width": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", @@ -30332,7 +30160,8 @@ "colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==" + "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "dev": true }, "colors": { "version": "1.4.0", @@ -30708,9 +30537,9 @@ } }, "cosmiconfig": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", - "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", + "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", "dev": true, "requires": { "@types/parse-json": "^4.0.0", @@ -33705,21 +33534,6 @@ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==" }, - "hasbin": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/hasbin/-/hasbin-1.2.3.tgz", - "integrity": "sha512-CCd8e/w2w28G8DyZvKgiHnQJ/5XXDz6qiUHnthvtag/6T5acUeN5lqq+HMoBqcmgWueWDhiCplrw0Kb1zDACRg==", - "requires": { - "async": "~1.5" - }, - "dependencies": { - "async": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/async/-/async-1.5.2.tgz", - "integrity": "sha512-nSVgobk4rv61R9PUSDtYt7mPVB2olxNR5RWJcAsH676/ef11bUZwvu7+RGYrYauVdDPcO519v68wRhXQtxsV9w==" - } - } - }, "hasha": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", @@ -33974,12 +33788,6 @@ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" }, - "ini": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.3.tgz", - "integrity": "sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==", - "dev": true - }, "inquirer": { "version": "6.5.2", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", @@ -34376,11 +34184,6 @@ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=" }, - "is-fullwidth-code-point": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", - "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==" - }, "is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -35067,51 +34870,6 @@ "uqr": "^0.1.2" } }, - "listr2": { - "version": "8.2.5", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.2.5.tgz", - "integrity": "sha512-iyAZCeyD+c1gPyE9qpFu8af0Y+MRtmKOncdGoA2S5EY8iFq99dmmvkNnHiWo+pj0s7yH7l3KPIgee77tKpXPWQ==", - "requires": { - "cli-truncate": "^4.0.0", - "colorette": "^2.0.20", - "eventemitter3": "^5.0.1", - "log-update": "^6.1.0", - "rfdc": "^1.4.1", - "wrap-ansi": "^9.0.0" - }, - "dependencies": { - "emoji-regex": { - "version": "10.4.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz", - "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==" - }, - "eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==" - }, - "string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "requires": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - } - }, - "wrap-ansi": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", - "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", - "requires": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - } - } - } - }, "local-pkg": { "version": "0.5.0", "resolved": "https://registry.npmjs.org/local-pkg/-/local-pkg-0.5.0.tgz", @@ -35460,12 +35218,12 @@ "integrity": "sha512-3l6OrhdDg2H2SigtuN3jBh+5dRJRWxNKuJTPBbGeNJTsmt/pj9PO25wYaNb05NuNmAsl435j4rDP6rgNXz7s7g==" }, "magic-string": { - "version": "0.30.5", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.5.tgz", - "integrity": "sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA==", + "version": "0.30.14", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.14.tgz", + "integrity": "sha512-5c99P1WKTed11ZC0HMJOj6CDIue6F8ySu+bJL+85q1zBEIY8IklrJ1eiKC2NDRh3Ct3FcvmJPyQHb9erXMTJNw==", "dev": true, "requires": { - "@jridgewell/sourcemap-codec": "^1.4.15" + "@jridgewell/sourcemap-codec": "^1.5.0" } }, "magicast": { @@ -37068,9 +36826,9 @@ "dev": true }, "picocolors": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", - "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==" + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" }, "picomatch": { "version": "2.3.1", @@ -37230,12 +36988,12 @@ "dev": true }, "postcss": { - "version": "8.4.47", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", - "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", + "version": "8.4.49", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", + "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", "requires": { "nanoid": "^3.3.7", - "picocolors": "^1.1.0", + "picocolors": "^1.1.1", "source-map-js": "^1.2.1" } }, @@ -38404,15 +38162,6 @@ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==" }, - "slice-ansi": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", - "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", - "requires": { - "ansi-styles": "^6.0.0", - "is-fullwidth-code-point": "^4.0.0" - } - }, "sonic-boom": { "version": "3.8.1", "resolved": "https://registry.npmjs.org/sonic-boom/-/sonic-boom-3.8.1.tgz", diff --git a/package.json b/package.json index bf7c2e229c7..d22abfad023 100644 --- a/package.json +++ b/package.json @@ -123,7 +123,6 @@ "gh-release-fetch": "4.0.3", "git-repo-info": "2.1.1", "gitconfiglocal": "2.1.0", - "hasbin": "1.2.3", "hasha": "5.2.2", "http-proxy": "1.18.1", "http-proxy-middleware": "2.0.7", @@ -139,7 +138,6 @@ "jsonwebtoken": "9.0.2", "jwt-decode": "4.0.0", "lambda-local": "2.2.0", - "listr2": "8.2.5", "locate-path": "7.2.0", "lodash": "4.17.21", "log-symbols": "6.0.0", @@ -160,7 +158,6 @@ "parallel-transform": "1.2.0", "parse-github-url": "1.0.3", "parse-gitignore": "2.0.0", - "path-key": "4.0.0", "prettyjson": "1.2.5", "pump": "3.0.2", "raw-body": "2.5.2", @@ -211,7 +208,6 @@ "fs-extra": "11.2.0", "graphviz": "0.0.9", "husky": "8.0.3", - "ini": "4.1.3", "is-ci": "3.0.1", "mock-fs": "5.4.1", "nock": "13.5.6", diff --git a/site/src/_app.js b/site/src/_app.js index eec02d5a5f6..ea39201c6e8 100644 --- a/site/src/_app.js +++ b/site/src/_app.js @@ -37,7 +37,6 @@ const navOrder = [ 'index', 'getting-started', 'commands', - 'addons', 'api', 'blobs', 'build', @@ -49,7 +48,6 @@ const navOrder = [ 'init', 'integration', 'link', - 'lm', 'login', 'logout', 'logs', @@ -66,8 +64,6 @@ const navOrder = [ const pageNames = { index: 'CLI Reference', 'getting-started': 'Getting Started', - addons: 'addons (deprecated)', - lm: 'lm (deprecated)', } const sortRoutes = (routes) => diff --git a/src/commands/base-command.ts b/src/commands/base-command.ts index 129197271fe..9aafb580a11 100644 --- a/src/commands/base-command.ts +++ b/src/commands/base-command.ts @@ -69,7 +69,7 @@ const HELP_SEPARATOR_WIDTH = 5 * Those commands work with the system or are not writing any config files that need to be * workspace aware. */ -const COMMANDS_WITHOUT_WORKSPACE_OPTIONS = new Set(['api', 'recipes', 'completion', 'status', 'switch', 'login', 'lm']) +const COMMANDS_WITHOUT_WORKSPACE_OPTIONS = new Set(['api', 'recipes', 'completion', 'status', 'switch', 'login']) /** * A list of commands where we need to fetch featureflags for config resolution diff --git a/src/commands/lm/index.ts b/src/commands/lm/index.ts deleted file mode 100644 index 860c68d206d..00000000000 --- a/src/commands/lm/index.ts +++ /dev/null @@ -1 +0,0 @@ -export { createLmCommand } from './lm.js' diff --git a/src/commands/lm/lm-info.ts b/src/commands/lm/lm-info.ts deleted file mode 100644 index b8c37c31531..00000000000 --- a/src/commands/lm/lm-info.ts +++ /dev/null @@ -1,32 +0,0 @@ -import { Listr } from 'listr2' - -import { - checkGitLFSVersionStep, - checkGitVersionStep, - checkHelperVersionStep, - checkLFSFiltersStep, -} from '../../utils/lm/steps.js' - -/** - * The lm:info command - */ -export const lmInfo = async () => { - const steps = [ - checkGitVersionStep, - checkGitLFSVersionStep, - // @ts-expect-error TS(7006) FIXME: Parameter 'ctx' implicitly has an 'any' type. - checkLFSFiltersStep((ctx, task, installed) => { - if (!installed) { - throw new Error('Git LFS filters are not installed, run `git lfs install` to install them') - } - }), - checkHelperVersionStep, - ] - - const tasks = new Listr(steps, { concurrent: true, exitOnError: false }) - try { - await tasks.run() - } catch { - // an error is already reported when a task fails - } -} diff --git a/src/commands/lm/lm-install.ts b/src/commands/lm/lm-install.ts deleted file mode 100644 index 4efa3724028..00000000000 --- a/src/commands/lm/lm-install.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { OptionValues } from 'commander' - -import { installPlatform } from '../../utils/lm/install.js' -import { printBanner } from '../../utils/lm/ui.js' - -export const lmInstall = async ({ force }: OptionValues) => { - const installed = await installPlatform({ force }) - if (installed) { - printBanner(force) - } -} diff --git a/src/commands/lm/lm-setup.ts b/src/commands/lm/lm-setup.ts deleted file mode 100644 index f32940ab4c5..00000000000 --- a/src/commands/lm/lm-setup.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { OptionValues } from 'commander' -import { Listr } from 'listr2' - -import { error } from '../../utils/command-helpers.js' -import execa from '../../utils/execa.js' -import { installPlatform } from '../../utils/lm/install.js' -import { checkHelperVersion } from '../../utils/lm/requirements.js' -import { printBanner } from '../../utils/lm/ui.js' -import BaseCommand from '../base-command.js' - -// @ts-expect-error TS(7031) FIXME: Binding element 'force' implicitly has an 'any' ty... Remove this comment to see the full error message -const installHelperIfMissing = async function ({ force }) { - let installHelper = false - try { - const version = await checkHelperVersion() - if (!version) { - installHelper = true - } - } catch { - installHelper = true - } - - if (installHelper) { - return installPlatform({ force }) - } - - return false -} - -// @ts-expect-error TS(7006) FIXME: Parameter 'siteId' implicitly has an 'any' type. -const provisionService = async function (siteId, api) { - const addonName = 'large-media' - - if (!siteId) { - throw new Error('No site id found, please run inside a site folder or `netlify link`') - } - try { - await api.createServiceInstance({ - siteId, - addon: addonName, - body: {}, - }) - } catch (error_) { - // error is JSONHTTPError - // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. - throw new Error(error_.json.error) - } -} - -// @ts-expect-error TS(7006) FIXME: Parameter 'siteId' implicitly has an 'any' type. -const configureLFSURL = async function (siteId, api) { - const siteInfo = await api.getSite({ siteId }) - const url = `https://${siteInfo.id_domain}/.netlify/large-media` - - return execa('git', ['config', '-f', '.lfsconfig', 'lfs.url', url]) -} - -export const lmSetup = async (options: OptionValues, command: BaseCommand) => { - await command.authenticate() - - const { api, site } = command.netlify - - let helperInstalled = false - if (!options.skipInstall) { - try { - helperInstalled = await installHelperIfMissing({ force: options.forceInstall }) - } catch (error_) { - error(error_) - } - } - - const tasks = new Listr([ - { - title: 'Provisioning Netlify Large Media', - async task() { - await provisionService(site.id, api) - }, - }, - { - title: 'Configuring Git LFS for this site', - async task() { - await configureLFSURL(site.id, api) - }, - }, - ]) - await tasks.run().catch(() => {}) - - if (helperInstalled) { - printBanner(options.forceInstall) - } -} diff --git a/src/commands/lm/lm-uninstall.ts b/src/commands/lm/lm-uninstall.ts deleted file mode 100644 index 5235461e946..00000000000 --- a/src/commands/lm/lm-uninstall.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { uninstall } from '../../utils/lm/install.js' - -/** - * The lm:uninstall command - */ -export const lmUninstall = async () => { - await uninstall() -} diff --git a/src/commands/lm/lm.ts b/src/commands/lm/lm.ts deleted file mode 100644 index a11c08db22e..00000000000 --- a/src/commands/lm/lm.ts +++ /dev/null @@ -1,61 +0,0 @@ -import { OptionValues } from 'commander' - -import BaseCommand from '../base-command.js' - -const lm = (options: OptionValues, command: BaseCommand) => { - command.help() -} - -export const createLmCommand = (program: BaseCommand) => { - program - .command('lm:info', { hidden: true }) - .description('Show large media requirements information.') - .action(async () => { - const { lmInfo } = await import('./lm-info.js') - await lmInfo() - }) - - program - .command('lm:install', { hidden: true }) - .alias('lm:init') - .description( - `Configures your computer to use Netlify Large Media -It installs the required credentials helper for Git, -and configures your Git environment with the right credentials.`, - ) - .option('-f, --force', 'Force the credentials helper installation') - .action(async (options: OptionValues) => { - const { lmInstall } = await import('./lm-install.js') - await lmInstall(options) - }) - - program - .command('lm:setup', { hidden: true }) - .description('Configures your site to use Netlify Large Media') - .option('-s, --skip-install', 'Skip the credentials helper installation check') - .option('-f, --force-install', 'Force the credentials helper installation') - .addHelpText('after', 'It runs the install command if you have not installed the dependencies yet.') - .action(async (options: OptionValues, command: BaseCommand) => { - const { lmSetup } = await import('./lm-setup.js') - await lmSetup(options, command) - }) - - program - .command('lm:uninstall', { hidden: true }) - .alias('lm:remove') - .description( - 'Uninstalls Netlify git credentials helper and cleans up any related configuration changes made by the install command.', - ) - .action(async () => { - const { lmUninstall } = await import('./lm-uninstall.js') - await lmUninstall() - }) - - program - .command('lm', { hidden: true }) - .description( - '[Deprecated and will be removed from future versions] Handle Netlify Large Media operations\nThe lm command will help you manage large media for a site', - ) - .addExamples(['netlify lm:info', 'netlify lm:install', 'netlify lm:setup']) - .action(lm) -} diff --git a/src/commands/main.ts b/src/commands/main.ts index 99a356baf70..a3ebfd70deb 100644 --- a/src/commands/main.ts +++ b/src/commands/main.ts @@ -25,7 +25,6 @@ import { createFunctionsCommand } from './functions/index.js' import { createInitCommand } from './init/index.js' import { createIntegrationCommand } from './integration/index.js' import { createLinkCommand } from './link/index.js' -import { createLmCommand } from './lm/index.js' import { createLoginCommand } from './login/index.js' import { createLogoutCommand } from './logout/index.js' import { createLogsCommand } from './logs/index.js' @@ -35,9 +34,10 @@ import { createServeCommand } from './serve/index.js' import { createSitesCommand } from './sites/index.js' import { createStatusCommand } from './status/index.js' import { createSwitchCommand } from './switch/index.js' +import { AddressInUseError } from './types.js' import { createUnlinkCommand } from './unlink/index.js' import { createWatchCommand } from './watch/index.js' -import { AddressInUseError } from './types.js' + const SUGGESTION_TIMEOUT = 1e4 // These commands run with the --force flag in non-interactive and CI environments @@ -225,7 +225,6 @@ export const createMainCommand = () => { createInitCommand(program) createIntegrationCommand(program) createLinkCommand(program) - createLmCommand(program) createLoginCommand(program) createLogoutCommand(program) createOpenCommand(program) @@ -258,7 +257,7 @@ export const createMainCommand = () => { program.commands.forEach((cmd) => { const cmdName = cmd.name() if (cmdName in CI_FORCED_COMMANDS) { - const { options, description } = CI_FORCED_COMMANDS[cmdName as keyof typeof CI_FORCED_COMMANDS] + const { description, options } = CI_FORCED_COMMANDS[cmdName as keyof typeof CI_FORCED_COMMANDS] cmd.option(options, description) } }) diff --git a/src/utils/lm/install.ts b/src/utils/lm/install.ts deleted file mode 100644 index b8e300a3379..00000000000 --- a/src/utils/lm/install.ts +++ /dev/null @@ -1,296 +0,0 @@ -import { appendFile, copyFile, readFile, rm, writeFile } from 'fs/promises' -import os from 'os' -import path, { join, sep } from 'path' -import process from 'process' -import { fileURLToPath } from 'url' - -import execa from 'execa' -// @ts-expect-error TS(7016) FIXME: Could not find a declaration file for module 'hasb... Remove this comment to see the full error message -import hasbin from 'hasbin' -import { Listr } from 'listr2' -import pathKey from 'path-key' - -import { fetchLatestVersion, shouldFetchLatestVersion } from '../../lib/exec-fetcher.js' -import { fileExistsAsync } from '../../lib/fs.js' -import { normalizeBackslash } from '../../lib/path.js' -import { getLegacyPathInHome, getPathInHome } from '../../lib/settings.js' -import { chalk } from '../command-helpers.js' - -import { checkGitLFSVersionStep, checkGitVersionStep, checkLFSFiltersStep } from './steps.js' - -const PACKAGE_NAME = 'netlify-credential-helper' -const EXEC_NAME = 'git-credential-netlify' - -const GIT_CONFIG = '.gitconfig' - -const SUPPORTED_PLATFORMS = { - linux: 'Linux', - darwin: 'Mac OS X', - win32: 'Windows', -} - -const CONFIG_FILES = { - bash: '.bashrc', - zsh: '.zshrc', - fish: '.config/fish/config.fish', -} - -/** The path to the scritps folder on the package root */ -const scriptsPath = fileURLToPath(new URL('../../../scripts', import.meta.url)) -const getHelperPath = () => getPathInHome(['helper']) -const getBinPath = () => join(getHelperPath(), 'bin') -const getGitConfigPath = () => join(getHelperPath(), 'git-config') -const getLegacyBinPath = () => join(getLegacyPathInHome(['helper', 'bin'])) - -// @ts-expect-error TS(7031) FIXME: Binding element 'skipInstall' implicitly has an 'a... Remove this comment to see the full error message -const getSetupStep = ({ skipInstall }) => { - const platform = os.platform() - // @ts-expect-error TS(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message - const platformName = SUPPORTED_PLATFORMS[platform] - if (platformName === undefined) { - throw new Error(`Platform not supported: ${platform}. -See manual setup instructions in https://github.com/netlify/netlify-credential-helper#install`) - } - - return { - title: `Installing Netlify's Git Credential Helper for ${platformName}`, - skip: () => { - if (skipInstall) { - return `Netlify's Git Credential Helper already installed with a package manager` - } - }, - task: async () => { - await installHelper() - await (platform === 'win32' ? setupWindowsPath() : setupUnixPath()) - }, - } -} - -const setupGitConfigStep = { - title: `Configuring Git to use Netlify's Git Credential Helper`, - task: () => configureGitConfig(), -} - -// @ts-expect-error TS(7031) FIXME: Binding element 'force' implicitly has an 'any' ty... Remove this comment to see the full error message -export const installPlatform = async function ({ force }) { - const skipInstall = !force && (await installedWithPackageManager()) - const steps = [ - checkGitVersionStep, - checkGitLFSVersionStep, - // @ts-expect-error TS(7006) FIXME: Parameter 'ctx' implicitly has an 'any' type. - checkLFSFiltersStep(async (ctx, task, installed) => { - if (!installed) { - await execa('git', ['lfs', 'install']) - task.title += chalk.dim(' [installed]') - } - }), - getSetupStep({ skipInstall }), - setupGitConfigStep, - ] - - const tasks = new Listr(steps) - await tasks.run() - - return !skipInstall -} - -const installedWithPackageManager = async function () { - const installed = hasbin.sync('git-credential-netlify') - if (!installed) { - return false - } - // we check for the older location too via getLegacyBinPath - const binExist = await Promise.all([getBinPath(), getLegacyBinPath()].map(fileExistsAsync)) - const withPackageManager = binExist.every((exists) => !exists) - return withPackageManager -} - -const installHelper = async function () { - // remove any old versions that might still exist in `~/.netlify/helper/bin` - await rm(getLegacyBinPath(), { force: true, recursive: true }) - const binPath = getBinPath() - // @ts-expect-error TS(2345) FIXME: Argument of type '{ binPath: string; packageName: ... Remove this comment to see the full error message - const shouldFetch = await shouldFetchLatestVersion({ - binPath, - packageName: PACKAGE_NAME, - execArgs: ['version'], - pattern: `${EXEC_NAME}\\/v?([^\\s]+)`, - execName: EXEC_NAME, - }) - if (!shouldFetch) { - return - } - - // @ts-expect-error TS(2345) FIXME: Argument of type '{ packageName: string; execName:... Remove this comment to see the full error message - await fetchLatestVersion({ - packageName: PACKAGE_NAME, - execName: EXEC_NAME, - destination: binPath, - extension: process.platform === 'win32' ? 'zip' : 'tar.gz', - }) -} - -export const isBinInPath = () => { - const envPath = process.env[pathKey()] - const binPath = getBinPath() - // @ts-expect-error TS(2532) FIXME: Object is possibly 'undefined'. - return envPath.replace(/"+/g, '').split(path.delimiter).includes(binPath) -} - -const setupWindowsPath = async function () { - if (isBinInPath()) { - return true - } - - const scriptPath = join(scriptsPath, 'path.ps1') - return await execa( - 'powershell', - ['-ExecutionPolicy', 'unrestricted', '-windowstyle', 'hidden', '-File', scriptPath, getBinPath()], - { stdio: 'inherit' }, - ) -} - -const CONTENT_COMMENT = ` -# The next line updates PATH for Netlify's Git Credential Helper. -` - -// @ts-expect-error TS(7006) FIXME: Parameter 'incFilePath' implicitly has an 'any' ty... Remove this comment to see the full error message -const getInitContent = (incFilePath) => `${CONTENT_COMMENT}test -f '${incFilePath}' && source '${incFilePath}'` - -const setupUnixPath = async () => { - if (isBinInPath()) { - return true - } - - const { configFile, incFilePath, shell } = getShellInfo() - - if (configFile === undefined) { - const error = `Unable to set credential helper in PATH. We don't how to set the path for ${shell} shell. -Set the helper path in your environment PATH: ${getBinPath()}` - throw new Error(error) - } - - return await Promise.all([ - await copyFile(join(scriptsPath, `${shell}.sh`), incFilePath), - await writeConfig(configFile, getInitContent(incFilePath)), - ]) -} - -// @ts-expect-error TS(7006) FIXME: Parameter 'name' implicitly has an 'any' type. -const writeConfig = async function (name, initContent) { - const configPath = join(os.homedir(), name) - if (!(await fileExistsAsync(configPath))) { - return - } - - const content = await readFile(configPath, 'utf8') - if (content.includes(initContent)) { - return - } - - return await appendFile(configPath, initContent, 'utf-8') -} - -const getCurrentCredentials = async () => { - try { - const { stdout } = await execa('git', ['config', '--no-includes', '--get-regexp', '^credential']) - const currentCredentials = stdout.split('\\n') - return currentCredentials - } catch (error) { - // ignore error caused by not having any credential configured - // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. - if (error.stdout !== '') { - throw error - } - return [] - } -} - -// Git expects the config path to always use / even on Windows -// @ts-expect-error TS(7006) FIXME: Parameter 'gitConfigPath' implicitly has an 'any' ... Remove this comment to see the full error message -const getGitConfigContent = (gitConfigPath) => ` -# This next lines include Netlify's Git Credential Helper configuration in your Git configuration. -[include] - path = ${normalizeBackslash(gitConfigPath)} -` - -const configureGitConfig = async function () { - const currentCredentials = await getCurrentCredentials() - - let helperConfig = ` -# The first line resets the list of helpers so we can check Netlify's first. -[credential] - helper = "" - -[credential] - helper = netlify -` - - let section = 'credential' - if (currentCredentials.length !== 0) { - currentCredentials.forEach((line) => { - const parts = line.split(' ') - - if (parts.length === 2) { - const keys = parts[0].split('.') - const localSection = keys.slice(0, -1).join('.') - if (section !== localSection) { - helperConfig += keys.length > 2 ? `\n[credential "${keys[1]}"]\n` : '\n[credential]\n' - section = localSection - } - - helperConfig += ` ${keys.pop()} = ${parts[1]}\n` - } - }) - } - - const gitConfigPath = getGitConfigPath() - await writeFile(gitConfigPath, helperConfig, 'utf-8') - - return writeConfig(GIT_CONFIG, getGitConfigContent(gitConfigPath)) -} - -export const getShellInfo = function () { - const shellEnv = process.env.SHELL - if (!shellEnv) { - throw new Error('Unable to detect SHELL type, make sure the variable is defined in your environment') - } - - const shell = shellEnv.split(sep).pop() - return { - shell, - incFilePath: `${getHelperPath()}/path.${shell}.inc`, - // @ts-expect-error TS(2538) FIXME: Type 'undefined' cannot be used as an index type. - configFile: CONFIG_FILES[shell], - } -} - -const cleanupShell = async function () { - try { - const { configFile, incFilePath } = getShellInfo() - if (configFile === undefined) { - return - } - - await removeConfig(configFile, getInitContent(incFilePath)) - } catch {} -} - -export const uninstall = async function () { - await Promise.all([ - rm(getHelperPath(), { force: true, recursive: true }), - removeConfig(GIT_CONFIG, getGitConfigContent(getGitConfigPath())), - cleanupShell(), - ]) -} - -const removeConfig = async function (name: string, toRemove: string) { - const configPath = join(os.homedir(), name) - - if (!(await fileExistsAsync(configPath))) { - return - } - - const content = await readFile(configPath, 'utf8') - return await writeFile(configPath, content.replace(toRemove, '')) -} diff --git a/src/utils/lm/requirements.ts b/src/utils/lm/requirements.ts deleted file mode 100644 index 089d1cd2bd2..00000000000 --- a/src/utils/lm/requirements.ts +++ /dev/null @@ -1,70 +0,0 @@ -import semver from 'semver' - -import execa from '../execa.js' - -export const checkLFSFilters = async function () { - try { - const { stdout } = await execa('git', ['config', '--get-regexp', 'filter.lfs']) - return stdout.length !== 0 - } catch { - return false - } -} - -const getHelperVersion = async function () { - try { - const { stdout } = await execa('git-credential-netlify', ['version']) - return stdout - } catch { - throw new Error(`Check that Netlify's Git Credential helper is installed and updated to the latest version`) - } -} - -export const checkHelperVersion = async function () { - const version = await getHelperVersion() - const expectedVersion = '0.1.10' - return matchVersion( - version, - /git-credential-netlify\/([.\d]+).*/, - expectedVersion, - `Invalid Netlify's Git Credential version MATCH_PLACEHOLDER. Please update to version ${expectedVersion} or above by running 'ntl lm:install'`, - ) -} - -export const checkGitVersion = async function () { - try { - const { stdout } = await execa('git', ['--version']) - return stdout.split(' ').pop() - } catch { - throw new Error('Check that Git is installed in your system') - } -} - -const getLFSVersion = async function () { - try { - const { stdout } = await execa('git-lfs', ['version']) - return stdout - } catch { - throw new Error('Check that Git LFS is installed in your system') - } -} - -export const checkLFSVersion = async function () { - const version = await getLFSVersion() - const expectedVersion = '2.5.1' - return matchVersion( - version, - /git-lfs\/([.\d]+).*/, - expectedVersion, - `Invalid Git LFS version MATCH_PLACEHOLDER. Please update to version ${expectedVersion} or above`, - ) -} - -// @ts-expect-error TS(7006) FIXME: Parameter 'out' implicitly has an 'any' type. -const matchVersion = function (out, regex, version, message) { - const match = out.match(regex) - if (!match || match.length !== 2 || semver.lt(match[1], version)) { - throw new Error(message.replace('MATCH_PLACEHOLDER', match[1])) - } - return match[1] -} diff --git a/src/utils/lm/steps.ts b/src/utils/lm/steps.ts deleted file mode 100644 index fedbf4dee9f..00000000000 --- a/src/utils/lm/steps.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { chalk } from '../command-helpers.js' - -import { checkGitVersion, checkHelperVersion, checkLFSFilters, checkLFSVersion } from './requirements.js' - -export const checkGitVersionStep = { - title: 'Checking Git version', - // @ts-expect-error TS(7006) FIXME: Parameter 'ctx' implicitly has an 'any' type. - task: async (ctx, task) => { - const version = await checkGitVersion() - task.title += chalk.dim(` [${version}]`) - }, -} - -export const checkGitLFSVersionStep = { - title: 'Checking Git LFS version', - // @ts-expect-error TS(7006) FIXME: Parameter 'ctx' implicitly has an 'any' type. - task: async (ctx, task) => { - const version = await checkLFSVersion() - task.title += chalk.dim(` [${version}]`) - }, -} - -// @ts-expect-error TS(7006) FIXME: Parameter 'onCheckDone' implicitly has an 'any' ty... Remove this comment to see the full error message -export const checkLFSFiltersStep = (onCheckDone) => ({ - title: 'Checking Git LFS filters', - // @ts-expect-error TS(7006) FIXME: Parameter 'ctx' implicitly has an 'any' type. - task: async (ctx, task) => { - const installed = await checkLFSFilters() - return onCheckDone(ctx, task, installed) - }, -}) - -export const checkHelperVersionStep = { - title: `Checking Netlify's Git Credentials version`, - // @ts-expect-error TS(7006) FIXME: Parameter 'ctx' implicitly has an 'any' type. - task: async (ctx, task) => { - const version = await checkHelperVersion() - task.title += chalk.dim(` [${version}]`) - }, -} diff --git a/src/utils/lm/ui.ts b/src/utils/lm/ui.ts deleted file mode 100644 index edf20334ebe..00000000000 --- a/src/utils/lm/ui.ts +++ /dev/null @@ -1,25 +0,0 @@ -import os from 'os' - -import boxen from 'boxen' - -import { chalk, log } from '../command-helpers.js' - -import { getShellInfo, isBinInPath } from './install.js' - -/** - * @param {boolean} force - */ -// @ts-expect-error TS(7006) FIXME: Parameter 'force' implicitly has an 'any' type. -export const printBanner = function (force) { - const print = force || !isBinInPath() - const platform = os.platform() - - if (print && platform !== 'win32') { - const { incFilePath } = getShellInfo() - const banner = chalk.bold( - `Run this command to use Netlify Large Media in your current shell\n\nsource ${incFilePath}`, - ) - - log(boxen(banner, { padding: 1, margin: 1, align: 'center', borderColor: '#00c7b7' })) - } -} diff --git a/tests/integration/commands/lm/lm.test.ts b/tests/integration/commands/lm/lm.test.ts deleted file mode 100644 index bc67bc88dff..00000000000 --- a/tests/integration/commands/lm/lm.test.ts +++ /dev/null @@ -1,102 +0,0 @@ -import { readFile } from 'fs/promises' -import os from 'os' -import process from 'process' - -import execa from 'execa' -import ini from 'ini' -import { describe, expect, test } from 'vitest' - -import { getPathInHome } from '../../../../src/lib/settings.js' -import { FixtureOptions, FixtureTestContext, setupFixtureTests } from '../../utils/fixture.js' -import { HTTPMethod, getCLIOptions } from '../../utils/mock-api-vitest.js' - -const siteInfo = { - account_slug: 'test-account', - id: 'site_id', - name: 'site-name', - id_domain: 'localhost', -} - -const routes = [ - { path: 'sites/site_id', response: siteInfo }, - { path: 'sites/site_id/service-instances', response: [] }, - { - path: 'accounts', - response: [{ slug: siteInfo.account_slug }], - }, - { method: HTTPMethod.POST, path: 'sites/site_id/services/large-media/instances', status: 201 }, -] -describe('lm command', () => { - let execOptions - const fixtureOptions: FixtureOptions = { - mockApi: { routes }, - async setup({ fixture, mockApi }) { - const CLIOptions = getCLIOptions({ apiUrl: `http://localhost:${mockApi?.server.address().port}/api/v1` }) - execOptions = { ...CLIOptions, env: { ...CLIOptions.env, SHELL: process.env.SHELL || 'bash' } } - await fixture.callCli(['lm:uninstall'], { execOptions }) - }, - async teardown({ fixture }) { - await fixture.callCli(['lm:uninstall'], { execOptions }) - }, - } - - setupFixtureTests('empty-project', fixtureOptions, () => { - test('netlify lm:info', async ({ fixture }) => { - const cliResponse = await fixture.callCli(['lm:info'], { offline: false, execOptions }) - expect(cliResponse).toContain('Checking Git version') - expect(cliResponse).toContain('Checking Git LFS version') - expect(cliResponse).toContain('Checking Git LFS filters') - expect(cliResponse).toContain("Checking Netlify's Git Credentials version") - }) - - test('netlify lm:install', async ({ fixture }) => { - const cliResponse = await fixture.callCli(['lm:install'], { offline: false, execOptions }) - expect(cliResponse).toContain('Checking Git version') - expect(cliResponse).toContain('Checking Git LFS version') - expect(cliResponse).toContain('Checking Git LFS filters') - expect(cliResponse).toContain("Installing Netlify's Git Credential Helper") - expect(cliResponse).toContain("Configuring Git to use Netlify's Git Credential Helper") - - // verify git-credential-netlify was added to the PATH - if (os.platform() === 'win32') { - expect(cliResponse).toContain(`Adding ${getPathInHome(['helper', 'bin'])} to the`) - expect(cliResponse).toContain('Netlify Credential Helper for Git was installed successfully.') - // no good way to test that it was added to the PATH on windows so we test it was installed - // in the expected location - const { stdout } = await execa('git-credential-netlify', ['version'], { - cwd: `${os.homedir()}\\AppData\\Roaming\\netlify\\config\\helper\\bin`, - }) - - expect(stdout.startsWith('git-credential-netlify')).toBe(true) - } else { - expect(cliResponse).toContain('Run this command to use Netlify Large Media in your current shell') - // The source path is always an absolute path so we can match for starting with `/`. - // The reasoning behind this regular expression is, that on different shells the border of the box inside the command output - // can infer with line breaks and split the source with the path. - // https://regex101.com/r/2d5BUn/1 - // /source[\s\S]+?(\/.+inc)/ - // / [\s\S] / \s matches any whitespace character and \S any non whitespace character - // / +? / matches at least one character but until the next group - // / (\/.+inc)/ matches any character until `inc` (the path starting with a `\`) - const match = cliResponse.match(/source[\s\S]+?(\/.+inc)/) - if (!match) expect.fail('could not match path') - const [, sourcePath] = match - const { stdout } = await execa.command(`source ${sourcePath} && git-credential-netlify version`, { - shell: execOptions.env.SHELL, - }) - - expect(stdout.startsWith('git-credential-netlify')).toBe(true) - } - }) - - test('netlify lm:setup', async ({ fixture }) => { - const cliResponse = await fixture.callCli(['lm:setup'], { offline: false, execOptions }) - - expect(cliResponse).toContain('Provisioning Netlify Large Media') - expect(cliResponse).toContain('Configuring Git LFS for this site') - - const lfsConfig = ini.parse(await readFile(`${fixture.directory}/.lfsconfig`, 'utf8')) - expect(lfsConfig.lfs.url).toBe('https://localhost/.netlify/large-media') - }) - }) -})