ado-npm-auth 0.0.3 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -1
- package/dist/ado-npm-auth.cjs +117 -30
- package/lib/.tsbuildinfo +1 -1
- package/lib/azureauth/ado.d.ts.map +1 -1
- package/lib/azureauth/ado.js +10 -2
- package/lib/azureauth/ado.js.map +1 -1
- package/lib/azureauth/ado.test.d.ts +2 -0
- package/lib/azureauth/ado.test.d.ts.map +1 -0
- package/lib/azureauth/ado.test.js +119 -0
- package/lib/azureauth/ado.test.js.map +1 -0
- package/lib/azureauth/azureauth-command.d.ts +1 -0
- package/lib/azureauth/azureauth-command.d.ts.map +1 -1
- package/lib/azureauth/azureauth-command.js +4 -0
- package/lib/azureauth/azureauth-command.js.map +1 -1
- package/lib/azureauth/is-azureauth-installed.d.ts +1 -0
- package/lib/azureauth/is-azureauth-installed.d.ts.map +1 -1
- package/lib/azureauth/is-azureauth-installed.js +4 -1
- package/lib/azureauth/is-azureauth-installed.js.map +1 -1
- package/lib/azureauth/is-azureauth-installed.test.d.ts +2 -0
- package/lib/azureauth/is-azureauth-installed.test.d.ts.map +1 -0
- package/lib/azureauth/is-azureauth-installed.test.js +51 -0
- package/lib/azureauth/is-azureauth-installed.test.js.map +1 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -1
- package/lib/npmrc/get-repo-npmrc-ado-orgs.d.ts.map +1 -1
- package/lib/npmrc/get-repo-npmrc-ado-orgs.js +13 -3
- package/lib/npmrc/get-repo-npmrc-ado-orgs.js.map +1 -1
- package/lib/npmrc/index.d.ts +1 -0
- package/lib/npmrc/index.js +1 -1
- package/lib/utils/exec.d.ts +1 -1
- package/lib/utils/get-feed-without-protocol.d.ts.map +1 -1
- package/lib/utils/get-feed-without-protocol.js +3 -1
- package/lib/utils/get-feed-without-protocol.js.map +1 -1
- package/lib/utils/get-feed-without-protocol.test.d.ts +2 -0
- package/lib/utils/get-feed-without-protocol.test.d.ts.map +1 -0
- package/lib/utils/get-feed-without-protocol.test.js +31 -0
- package/lib/utils/get-feed-without-protocol.test.js.map +1 -0
- package/lib/utils/get-organization-from-feed-url.d.ts.map +1 -1
- package/lib/utils/get-organization-from-feed-url.js +64 -13
- package/lib/utils/get-organization-from-feed-url.js.map +1 -1
- package/lib/utils/get-organization-from-feed-url.test.d.ts +2 -0
- package/lib/utils/get-organization-from-feed-url.test.d.ts.map +1 -0
- package/lib/utils/get-organization-from-feed-url.test.js +19 -0
- package/lib/utils/get-organization-from-feed-url.test.js.map +1 -0
- package/lib/utils/request.d.ts +1 -1
- package/package.json +6 -3
package/README.md
CHANGED
|
@@ -12,6 +12,14 @@ You can run the binary `"ado-npm-auth"` via `yarn ado-npm-auth` or `npm exec ado
|
|
|
12
12
|
|
|
13
13
|
It will then shell out to the `azureauth` package on [npm](https://www.npmjs.com/package/azureauth), retrieve a token, and update your `~/.npmrc`.
|
|
14
14
|
|
|
15
|
+
## Beware the chicken and egg problem
|
|
16
|
+
|
|
17
|
+
You may need to set the registry to the public NPM feed when running `npm exec` or `npx`.
|
|
18
|
+
|
|
19
|
+
If that's the case, set the environment variable `npm_config_registry=https://registry.npmjs.org`.
|
|
20
|
+
|
|
21
|
+
That will ensure that `npx` or `npm exec` grabs from the public NPM feed, bypassing the soon-to-be authenticated ADO feed.
|
|
22
|
+
|
|
15
23
|
## ado-npm-auth vs vsts-npm-auth
|
|
16
24
|
|
|
17
25
|
The main difference between the two is how they function, and where they can run. The `vsts-npm-auth` tool is Windows only, and uses MSAL authentication.
|
|
@@ -32,4 +40,4 @@ One of the easiest ways to use the tool is to add it to your `"preinstall"` scri
|
|
|
32
40
|
|
|
33
41
|
It will then perform a quick "pre-flight" check to assess if the token is valid, and generate a new one if it has expired.
|
|
34
42
|
|
|
35
|
-

|
|
43
|
+

|
package/dist/ado-npm-auth.cjs
CHANGED
|
@@ -38004,6 +38004,14 @@ module.exports = require("fs");
|
|
|
38004
38004
|
|
|
38005
38005
|
/***/ }),
|
|
38006
38006
|
|
|
38007
|
+
/***/ 1455:
|
|
38008
|
+
/***/ ((module) => {
|
|
38009
|
+
|
|
38010
|
+
"use strict";
|
|
38011
|
+
module.exports = require("node:fs/promises");
|
|
38012
|
+
|
|
38013
|
+
/***/ }),
|
|
38014
|
+
|
|
38007
38015
|
/***/ 6760:
|
|
38008
38016
|
/***/ ((module) => {
|
|
38009
38017
|
|
|
@@ -38098,7 +38106,7 @@ __webpack_require__.a(__webpack_module__, async (__webpack_handle_async_dependen
|
|
|
38098
38106
|
/* harmony import */ var _utils_is_codespaces_js__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(3827);
|
|
38099
38107
|
/* harmony import */ var _telemetry_index_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6000);
|
|
38100
38108
|
/* harmony import */ var os__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(857);
|
|
38101
|
-
/* harmony import */ var _npmrc_is_valid_pat_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(
|
|
38109
|
+
/* harmony import */ var _npmrc_is_valid_pat_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(7467);
|
|
38102
38110
|
/* harmony import */ var _npmrc_set_npmrc_pat_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(4460);
|
|
38103
38111
|
|
|
38104
38112
|
|
|
@@ -38176,7 +38184,9 @@ __webpack_async_result__();
|
|
|
38176
38184
|
/* harmony import */ var _npmcli_config__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(7954);
|
|
38177
38185
|
/* harmony import */ var workspace_tools__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(6892);
|
|
38178
38186
|
/* harmony import */ var node_path__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(6760);
|
|
38179
|
-
/* harmony import */ var
|
|
38187
|
+
/* harmony import */ var node_fs_promises__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(1455);
|
|
38188
|
+
/* harmony import */ var _utils_get_organization_from_feed_url_js__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(962);
|
|
38189
|
+
|
|
38180
38190
|
|
|
38181
38191
|
|
|
38182
38192
|
|
|
@@ -38190,17 +38200,26 @@ const getRepoNpmrcAdoOrganizations = async () => {
|
|
|
38190
38200
|
var _a;
|
|
38191
38201
|
const workspaceRoot = (0,workspace_tools__WEBPACK_IMPORTED_MODULE_1__.getWorkspaceRoot)(process.cwd()) || "";
|
|
38192
38202
|
let config;
|
|
38193
|
-
|
|
38203
|
+
const npmrcPath = (0,node_path__WEBPACK_IMPORTED_MODULE_2__.join)(workspaceRoot, ".npmrc");
|
|
38204
|
+
try {
|
|
38205
|
+
await node_fs_promises__WEBPACK_IMPORTED_MODULE_3__.access(npmrcPath);
|
|
38206
|
+
}
|
|
38207
|
+
catch (error) {
|
|
38208
|
+
throw new Error("No project .npmrc file found");
|
|
38209
|
+
}
|
|
38194
38210
|
try {
|
|
38195
38211
|
config = new _npmcli_config__WEBPACK_IMPORTED_MODULE_0__({
|
|
38196
|
-
npmPath:
|
|
38212
|
+
npmPath: npmrcPath,
|
|
38197
38213
|
shorthands: {},
|
|
38198
38214
|
definitions: {}, // needed so we can access random feed names
|
|
38199
38215
|
});
|
|
38200
38216
|
await config.load();
|
|
38201
38217
|
}
|
|
38202
38218
|
catch (error) {
|
|
38203
|
-
|
|
38219
|
+
if (error instanceof TypeError && error.message.includes("Invalid URL")) {
|
|
38220
|
+
throw new Error("Registry URL missing or invalid");
|
|
38221
|
+
}
|
|
38222
|
+
throw new Error("Error loading .npmrc");
|
|
38204
38223
|
}
|
|
38205
38224
|
// @npmcli/config does not have a normal way to display all keys
|
|
38206
38225
|
// so we use this ugly access instead
|
|
@@ -38211,7 +38230,7 @@ const getRepoNpmrcAdoOrganizations = async () => {
|
|
|
38211
38230
|
const feed = config.get(registry, "project");
|
|
38212
38231
|
return {
|
|
38213
38232
|
feed,
|
|
38214
|
-
organization: (0,
|
|
38233
|
+
organization: (0,_utils_get_organization_from_feed_url_js__WEBPACK_IMPORTED_MODULE_4__/* .getOrganizationFromFeedUrl */ .N)(feed),
|
|
38215
38234
|
};
|
|
38216
38235
|
});
|
|
38217
38236
|
};
|
|
@@ -38219,7 +38238,7 @@ const getRepoNpmrcAdoOrganizations = async () => {
|
|
|
38219
38238
|
|
|
38220
38239
|
/***/ }),
|
|
38221
38240
|
|
|
38222
|
-
/***/
|
|
38241
|
+
/***/ 7467:
|
|
38223
38242
|
/***/ ((__unused_webpack___webpack_module__, __webpack_exports__, __webpack_require__) => {
|
|
38224
38243
|
|
|
38225
38244
|
"use strict";
|
|
@@ -38391,8 +38410,8 @@ var get_organization_from_feed_url = __webpack_require__(962);
|
|
|
38391
38410
|
const external_node_os_namespaceObject = require("node:os");
|
|
38392
38411
|
// EXTERNAL MODULE: external "node:path"
|
|
38393
38412
|
var external_node_path_ = __webpack_require__(6760);
|
|
38394
|
-
|
|
38395
|
-
|
|
38413
|
+
// EXTERNAL MODULE: external "node:fs/promises"
|
|
38414
|
+
var promises_ = __webpack_require__(1455);
|
|
38396
38415
|
// EXTERNAL MODULE: ./lib/npmrc/get-repo-npmrc-ado-orgs.js
|
|
38397
38416
|
var get_repo_npmrc_ado_orgs = __webpack_require__(2236);
|
|
38398
38417
|
;// CONCATENATED MODULE: ./lib/npmrc/is-valid-pat.js
|
|
@@ -38410,17 +38429,17 @@ const isValidPat = async () => {
|
|
|
38410
38429
|
const removeUserNpmrcRegistries = async () => {
|
|
38411
38430
|
const userNpmrc = (0,external_node_path_.join)((0,external_node_os_namespaceObject.homedir)(), ".npmrc");
|
|
38412
38431
|
try {
|
|
38413
|
-
const npmrcContent = await (0,
|
|
38432
|
+
const npmrcContent = await (0,promises_.readFile)(userNpmrc, "utf-8");
|
|
38414
38433
|
// remove the entry for registries in the user-level .npmrc
|
|
38415
38434
|
const updatedNpmrcContent = npmrcContent
|
|
38416
38435
|
.split(external_node_os_namespaceObject.EOL)
|
|
38417
38436
|
.filter((line) => !line.includes("registry="))
|
|
38418
38437
|
.join(external_node_os_namespaceObject.EOL);
|
|
38419
|
-
await (0,
|
|
38438
|
+
await (0,promises_.writeFile)(userNpmrc, updatedNpmrcContent);
|
|
38420
38439
|
}
|
|
38421
38440
|
catch (error) {
|
|
38422
38441
|
// user npmrc does not exist so make an empty one
|
|
38423
|
-
await (0,
|
|
38442
|
+
await (0,promises_.writeFile)(userNpmrc, "");
|
|
38424
38443
|
}
|
|
38425
38444
|
};
|
|
38426
38445
|
const getNpmrcFeeds = async () => {
|
|
@@ -38439,7 +38458,7 @@ const getNpmrcFeeds = async () => {
|
|
|
38439
38458
|
};
|
|
38440
38459
|
const getUserNpmrcFeeds = async () => {
|
|
38441
38460
|
const userNpmrcFilepath = (0,external_node_path_.join)((0,external_node_os_namespaceObject.homedir)(), ".npmrc");
|
|
38442
|
-
const userNpmrcContent = await (0,
|
|
38461
|
+
const userNpmrcContent = await (0,promises_.readFile)(userNpmrcFilepath, "utf-8");
|
|
38443
38462
|
return userNpmrcContent
|
|
38444
38463
|
.split(external_node_os_namespaceObject.EOL)
|
|
38445
38464
|
.filter((line) => line.includes(":_password="))
|
|
@@ -38525,6 +38544,9 @@ var is_wsl = __webpack_require__(1891);
|
|
|
38525
38544
|
;// CONCATENATED MODULE: ./lib/azureauth/azureauth-command.js
|
|
38526
38545
|
|
|
38527
38546
|
let memo = undefined;
|
|
38547
|
+
const clearMemo = () => {
|
|
38548
|
+
memo = void 0;
|
|
38549
|
+
};
|
|
38528
38550
|
/**
|
|
38529
38551
|
* Get the executable path of azureauth command
|
|
38530
38552
|
* @returns { string } the string of the executable command to run azureauth
|
|
@@ -38532,6 +38554,7 @@ let memo = undefined;
|
|
|
38532
38554
|
const npxAzureAuthCommand = [
|
|
38533
38555
|
"npm",
|
|
38534
38556
|
"exec",
|
|
38557
|
+
"--silent",
|
|
38535
38558
|
"--yes",
|
|
38536
38559
|
"azureauth",
|
|
38537
38560
|
"--",
|
|
@@ -38549,13 +38572,16 @@ var external_child_process_ = __webpack_require__(5317);
|
|
|
38549
38572
|
|
|
38550
38573
|
|
|
38551
38574
|
let is_azureauth_installed_memo = undefined;
|
|
38575
|
+
const is_azureauth_installed_clearMemo = () => {
|
|
38576
|
+
is_azureauth_installed_memo = void 0;
|
|
38577
|
+
};
|
|
38552
38578
|
/**
|
|
38553
38579
|
* Determine if a valid version (>=0.8.0.0) is installed
|
|
38554
38580
|
* @returns { boolean } Whether a valid version of azureauth is installed
|
|
38555
38581
|
*/
|
|
38556
38582
|
const isAzureAuthInstalled = async () => {
|
|
38557
38583
|
if (is_azureauth_installed_memo === undefined) {
|
|
38558
|
-
const command = `${azureAuthCommand()} --version`;
|
|
38584
|
+
const command = `${azureAuthCommand().join(" ")} --version`;
|
|
38559
38585
|
try {
|
|
38560
38586
|
const result = await exec(command);
|
|
38561
38587
|
// version must be >=0.8.0.0
|
|
@@ -38629,13 +38655,21 @@ const adoPat = async (options) => {
|
|
|
38629
38655
|
npm_config_registry: "https://registry.npmjs.org",
|
|
38630
38656
|
},
|
|
38631
38657
|
});
|
|
38658
|
+
if (result.stderr) {
|
|
38659
|
+
throw new Error(result.stderr);
|
|
38660
|
+
}
|
|
38632
38661
|
}
|
|
38633
38662
|
catch (error) {
|
|
38634
|
-
throw new Error(`Failed to get Ado Pat from npx AzureAuth: ${error.message}
|
|
38663
|
+
throw new Error(`Failed to get Ado Pat from npx AzureAuth: ${error.message}`);
|
|
38635
38664
|
}
|
|
38636
38665
|
}
|
|
38637
38666
|
if (options.output === "json") {
|
|
38638
|
-
|
|
38667
|
+
try {
|
|
38668
|
+
return JSON.parse(result.stdout);
|
|
38669
|
+
}
|
|
38670
|
+
catch (error) {
|
|
38671
|
+
throw new Error(`Failed to parse JSON output: ${result.stdout}`);
|
|
38672
|
+
}
|
|
38639
38673
|
}
|
|
38640
38674
|
return result.stdout;
|
|
38641
38675
|
}
|
|
@@ -38838,7 +38872,9 @@ const logTelemetry = (inputProperties, flush, client) => {
|
|
|
38838
38872
|
*/
|
|
38839
38873
|
const getFeedWithoutProtocol = (feed) => {
|
|
38840
38874
|
const feedUrl = new URL(feed);
|
|
38841
|
-
const
|
|
38875
|
+
const protocol = feedUrl.protocol; // will be something like "http:"
|
|
38876
|
+
const protocolLength = protocol.length + 2; // we want to strip out the protocol, colon, and double slash
|
|
38877
|
+
const feedWithoutProtocol = feedUrl.toString().slice(protocolLength);
|
|
38842
38878
|
return feedWithoutProtocol;
|
|
38843
38879
|
};
|
|
38844
38880
|
//# sourceMappingURL=get-feed-without-protocol.js.map
|
|
@@ -38852,6 +38888,68 @@ const getFeedWithoutProtocol = (feed) => {
|
|
|
38852
38888
|
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
|
|
38853
38889
|
/* harmony export */ N: () => (/* binding */ getOrganizationFromFeedUrl)
|
|
38854
38890
|
/* harmony export */ });
|
|
38891
|
+
/**
|
|
38892
|
+
* Extracts the organization and project details from a given Azure DevOps URL.
|
|
38893
|
+
* The function differentiates between the "new style" URLs that use 'dev.azure.com'
|
|
38894
|
+
* and "old style" URLs that use a subdomain of 'visualstudio.com'.
|
|
38895
|
+
*
|
|
38896
|
+
* @param {string} url - The Azure DevOps URL from which to extract details.
|
|
38897
|
+
* @returns {Object} An object containing the `organization` and `project` extracted from the URL.
|
|
38898
|
+
* @throws {Error} Throws an error if the URL is invalid, not in the expected format,
|
|
38899
|
+
* or does not contain the necessary information for extraction.
|
|
38900
|
+
*
|
|
38901
|
+
* @example
|
|
38902
|
+
* // New style URL
|
|
38903
|
+
* extractAdoDetails("https://dev.azure.com/contoso/WebsiteRedesign");
|
|
38904
|
+
* // returns { organization: "contoso", project: "WebsiteRedesign" }
|
|
38905
|
+
*
|
|
38906
|
+
* // Old style URL
|
|
38907
|
+
* extractAdoDetails("https://contoso.visualstudio.com/WebsiteRedesign");
|
|
38908
|
+
* // returns { organization: "contoso", project: "WebsiteRedesign" }
|
|
38909
|
+
*
|
|
38910
|
+
* // Invalid URL
|
|
38911
|
+
* extractAdoDetails("https://invalid.url.com");
|
|
38912
|
+
* // throws Error
|
|
38913
|
+
*/
|
|
38914
|
+
const extractAdoDetails = (url) => {
|
|
38915
|
+
try {
|
|
38916
|
+
const parsedUrl = new URL(url);
|
|
38917
|
+
const hostname = parsedUrl.hostname;
|
|
38918
|
+
const pathname = parsedUrl.pathname;
|
|
38919
|
+
// Check for new style URLs (dev.azure.com)
|
|
38920
|
+
if (hostname.endsWith("dev.azure.com")) {
|
|
38921
|
+
const pathSegments = pathname.split('/').filter(Boolean); // Remove empty strings from the split result
|
|
38922
|
+
if (pathSegments.length >= 2) {
|
|
38923
|
+
return {
|
|
38924
|
+
organization: pathSegments[0],
|
|
38925
|
+
project: pathSegments[1]
|
|
38926
|
+
};
|
|
38927
|
+
}
|
|
38928
|
+
else {
|
|
38929
|
+
throw new Error("Not enough segments in path for a valid organization and project extraction.");
|
|
38930
|
+
}
|
|
38931
|
+
}
|
|
38932
|
+
// Check for old style URLs (visualstudio.com)
|
|
38933
|
+
if (hostname.endsWith("visualstudio.com")) {
|
|
38934
|
+
const subdomain = hostname.split('.')[0];
|
|
38935
|
+
const pathSegments = pathname.split('/').filter(Boolean);
|
|
38936
|
+
if (subdomain && pathSegments.length >= 1) {
|
|
38937
|
+
return {
|
|
38938
|
+
organization: subdomain,
|
|
38939
|
+
project: pathSegments[0]
|
|
38940
|
+
};
|
|
38941
|
+
}
|
|
38942
|
+
else {
|
|
38943
|
+
throw new Error("Not enough segments in path or missing subdomain for a valid organization and project extraction.");
|
|
38944
|
+
}
|
|
38945
|
+
}
|
|
38946
|
+
// If the URL does not match expected formats
|
|
38947
|
+
throw new Error("URL format not recognized or does not contain enough information.");
|
|
38948
|
+
}
|
|
38949
|
+
catch (error) {
|
|
38950
|
+
throw new Error("Invalid URL or unsupported format");
|
|
38951
|
+
}
|
|
38952
|
+
};
|
|
38855
38953
|
/**
|
|
38856
38954
|
* Get the ADO Org for a npm feed
|
|
38857
38955
|
* @param {string} feedUrl URL of the feed to get the ADO organization from
|
|
@@ -38860,19 +38958,8 @@ const getFeedWithoutProtocol = (feed) => {
|
|
|
38860
38958
|
*/
|
|
38861
38959
|
const getOrganizationFromFeedUrl = (feedUrl, defaultOrg = "") => {
|
|
38862
38960
|
try {
|
|
38863
|
-
const
|
|
38864
|
-
|
|
38865
|
-
if (packagingIndex > 0) {
|
|
38866
|
-
// sometimes org is included in the path as the first item in the path
|
|
38867
|
-
// after the initial "/"
|
|
38868
|
-
// ex. "https://pkgs.dev.azure.com/foo/bar/_packaging/baz/npm/registry/" -> "foo"
|
|
38869
|
-
// these are project-scoped feeds
|
|
38870
|
-
return url.pathname.split("/")[1];
|
|
38871
|
-
}
|
|
38872
|
-
// otherwise feed is the first item in the host
|
|
38873
|
-
// ex. "https://foo.pkgs.visualstudio.com/_packaging/npm-mirror/npm/registry" -> "foo"
|
|
38874
|
-
// these are org-wide feeds
|
|
38875
|
-
return url.host.split(".")[0];
|
|
38961
|
+
const { organization } = extractAdoDetails(feedUrl);
|
|
38962
|
+
return organization;
|
|
38876
38963
|
}
|
|
38877
38964
|
catch (error) {
|
|
38878
38965
|
return defaultOrg;
|