package-registry-manager 0.22.9 → 0.22.11

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 CHANGED
@@ -33,7 +33,25 @@ package-registry-manager setup --org link-foundation --all --execute --browser-i
33
33
  Scans read matched manifests/workflows through gh-manager. Account setup shares
34
34
  one browser, groups npm approvals, and uses CI evidence to preserve healthy tokens
35
35
  or verify replacements before revocation. `--secret-name '{REGISTRY}_TOKEN_{REPO}'`
36
- selects custom credential names. Rust requires Node.js and npm for its pinned
37
- GitHub CLI dependency.
36
+ selects custom credential names.
37
+
38
+ Account scans print progress to stderr (`[37/169] owner/repository`) and stream
39
+ text inspection results as each repository finishes. JSON inspection remains one
40
+ report on stdout. Repository, manifest, registry lookup, and release-log failures are
41
+ included in each repository's `error` and structured `errors` fields; valid
42
+ packages and later repositories are retained. The command exits nonzero after
43
+ printing all results, and `setup --org ORG --all` still plans the usable packages.
44
+ Release health checks only the latest default-branch push or manual run of each
45
+ detected publishing workflow; it downloads logs only when that run failed.
46
+ Expired logs retain the failed run's URL and conclusion alongside the error.
47
+ Account `plan` and `setup` JSON reports also include a `plans` array.
48
+
49
+ Without `--repository`, online commands prefer the current repository's
50
+ organization, then a sole organization membership, then the signed-in GitHub
51
+ user. Multiple memberships fall back to the user; select an organization with
52
+ `--org`. If GitHub account discovery is unavailable, the current directory is
53
+ inspected. Explicit `--repository` (including `--repository .`), `--ref`, and
54
+ local `--offline` commands keep local scope. Both CLIs' GitHub dependency needs
55
+ Node.js 22.12 or newer and npm; JavaScript checks the runtime before loading it.
38
56
 
39
57
  See the [bootstrap, wrapper and credential guide](../docs/registry-setup.md) for branch/PR setup, dual npm names, registry policies and integration limits.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "package-registry-manager",
3
- "version": "0.22.9",
3
+ "version": "0.22.11",
4
4
  "description": "Inspect repositories and guide secure package-registry setup",
5
5
  "type": "module",
6
6
  "bin": {
@@ -28,7 +28,7 @@
28
28
  "provenance": true
29
29
  },
30
30
  "scripts": {
31
- "syntax": "node --check src/cli.mjs && node --check src/direct-execution.mjs && node --check src/index.mjs && node --check src/browser.mjs && node --check src/browser-options.mjs && node --check src/browser-catalogue.mjs && node --check src/automation.mjs && node --check src/webdriver-automation.mjs && node --check src/profile.mjs && node --check src/setup.mjs && node --check src/auth-urls.mjs && node --check src/containers.mjs && node --check src/flows.mjs && node --check src/prerequisites.mjs && node --check src/registry-state.mjs && node --check src/workflows.mjs && node --check src/publishers.mjs && node --check src/skips.mjs && node --check src/tokens.mjs && node --check src/approvals.mjs && node --check src/default-browser.mjs && node --check src/pages.mjs && node --check src/crates-api.mjs && node --check src/sign-in-import.mjs && node --check scripts/publish-to-npm.mjs && node --check scripts/setup-npm.mjs && node --check scripts/sanitize-npm-userconfig.mjs && node --check src/python.mjs && node --check src/setup-batch.mjs && node --check src/workflow-proposal.mjs && node --check src/repository-identity.mjs && node --check src/repository-repair.mjs && node --check src/manifest-proposal.mjs",
31
+ "syntax": "node --check src/cli.mjs && node --check src/cli-main.mjs && node --check src/node-version.mjs && node --check src/default-scope.mjs && node --check src/direct-execution.mjs && node --check src/index.mjs && node --check src/browser.mjs && node --check src/browser-options.mjs && node --check src/browser-catalogue.mjs && node --check src/automation.mjs && node --check src/webdriver-automation.mjs && node --check src/profile.mjs && node --check src/setup.mjs && node --check src/auth-urls.mjs && node --check src/containers.mjs && node --check src/flows.mjs && node --check src/prerequisites.mjs && node --check src/registry-state.mjs && node --check src/workflows.mjs && node --check src/publishers.mjs && node --check src/skips.mjs && node --check src/tokens.mjs && node --check src/approvals.mjs && node --check src/default-browser.mjs && node --check src/pages.mjs && node --check src/crates-api.mjs && node --check src/sign-in-import.mjs && node --check scripts/publish-to-npm.mjs && node --check scripts/setup-npm.mjs && node --check scripts/sanitize-npm-userconfig.mjs && node --check src/python.mjs && node --check src/setup-batch.mjs && node --check src/workflow-proposal.mjs && node --check src/repository-identity.mjs && node --check src/repository-repair.mjs && node --check src/manifest-proposal.mjs",
32
32
  "lint": "eslint src test scripts --max-warnings 0",
33
33
  "lint:fix": "eslint src test scripts --fix --max-warnings 0",
34
34
  "format": "prettier --write .",
@@ -41,8 +41,8 @@
41
41
  },
42
42
  "dependencies": {
43
43
  "@link-foundation/gh-manager": "https://codeload.github.com/link-foundation/gh-manager/tar.gz/29808e088ac8fd8374361920bbebab07a4d63ac6",
44
- "browser-commander": "^0.30.1",
45
- "command-stream": "^2.0.2",
44
+ "browser-commander": "^0.31.2",
45
+ "command-stream": "^2.4.0",
46
46
  "playwright": "^1.63.0",
47
47
  "selenium-webdriver": "^4.50.0"
48
48
  },
package/src/auth-urls.mjs CHANGED
@@ -111,6 +111,7 @@ export function runInteractive(command, options) {
111
111
  shell: false,
112
112
  });
113
113
  let legacyLogin = false;
114
+ let openings = Promise.resolve();
114
115
  const stop = options.stopOnLegacyLogin
115
116
  ? () => {
116
117
  legacyLogin = true;
@@ -119,7 +120,11 @@ export function runInteractive(command, options) {
119
120
  : undefined;
120
121
  const scan =
121
122
  options.onUrl || stop
122
- ? authUrlScanner(options.onUrl ?? (() => {}), stop)
123
+ ? authUrlScanner((url, kind) => {
124
+ openings = openings.then(() => options.onUrl?.(url, kind));
125
+ // Observe rejection until the command closes and propagates it.
126
+ openings.catch(() => {});
127
+ }, stop)
123
128
  : null;
124
129
  let stdout = "";
125
130
  child.stdout.setEncoding("utf8");
@@ -141,9 +146,20 @@ export function runInteractive(command, options) {
141
146
  });
142
147
  }
143
148
  child.on("error", reject);
144
- child.on("close", (code) => {
149
+ child.on("close", async (code) => {
145
150
  scan?.("\n");
146
- resolve({ code: code ?? 1, stdout, legacyLogin, approvalExpired });
151
+ try {
152
+ await openings;
153
+ resolve({
154
+ code: code ?? 1,
155
+ stdout,
156
+ stderr: errors,
157
+ legacyLogin,
158
+ approvalExpired,
159
+ });
160
+ } catch (error) {
161
+ reject(error);
162
+ }
147
163
  });
148
164
  });
149
165
  }
package/src/browser.mjs CHANGED
@@ -74,7 +74,13 @@ export function npmPrefillScript(prefill, submit = false) {
74
74
  const config = ${JSON.stringify(prefill)};
75
75
  const shouldSubmit = ${JSON.stringify(submit)};
76
76
  const normalized = value => (value || '').replace(/\\s+/g, ' ').trim().toLowerCase();
77
- const controls = Array.from(document.querySelectorAll('input, select, textarea'));
77
+ const provider = Array.from(document.querySelectorAll('button, label, [role="radio"]'))
78
+ .find(element => normalized(element.textContent) === 'github');
79
+ if (provider) provider.click();
80
+ const githubForm = document.querySelector('#pending-github-publisher-form, #github-publisher-form');
81
+ const controls = Array.from((githubForm || document).querySelectorAll('input, select, textarea'))
82
+ .filter(control => !control.disabled && control.type !== 'hidden'
83
+ && (githubForm || control.getClientRects().length > 0));
78
84
  const setValue = (control, value) => {
79
85
  const prototype = control instanceof HTMLSelectElement
80
86
  ? HTMLSelectElement.prototype
@@ -88,7 +94,7 @@ export function npmPrefillScript(prefill, submit = false) {
88
94
  };
89
95
  const textFor = control => {
90
96
  const explicit = control.id
91
- ? document.querySelector(\`label[for="\${CSS.escape(control.id)}"]\`)?.textContent
97
+ ? (control.closest('form') || document).querySelector(\`label[for="\${CSS.escape(control.id)}"]\`)?.textContent
92
98
  : '';
93
99
  return normalized([explicit, control.getAttribute('aria-label'), control.name,
94
100
  control.placeholder, control.closest('label')?.textContent].filter(Boolean).join(' '));
@@ -103,19 +109,18 @@ export function npmPrefillScript(prefill, submit = false) {
103
109
  const filled = [];
104
110
  const used = new Set();
105
111
  for (const [labels, value] of values) {
106
- if (!value) continue;
112
+ if (!value && labels[0] !== 'environment') continue;
107
113
  const control = controls.find(candidate => !used.has(candidate)
108
114
  && labels.some(label => textFor(candidate).includes(label)));
109
115
  if (control) { setValue(control, value); used.add(control); filled.push(labels[0]); }
110
116
  }
111
- const provider = Array.from(document.querySelectorAll('button, label, [role="radio"]'))
112
- .find(element => normalized(element.textContent).includes('github'));
113
- if (provider && filled.length === 0) provider.click();
114
117
  let submitted = false;
115
- if (shouldSubmit && filled.length >= 3) {
116
- const button = Array.from(document.querySelectorAll('button, input[type="submit"]'))
118
+ const required = ['organization', 'repository', 'workflow', ...(githubForm?.id.startsWith('pending-') ? ['project'] : [])];
119
+ const form = githubForm || controls.find(control => /repository|repo/.test(textFor(control)))?.closest('form');
120
+ if (shouldSubmit && required.every(field => filled.includes(field))) {
121
+ const button = Array.from((form || document).querySelectorAll('button, input[type="submit"]'))
117
122
  .find(candidate => /add|save|configure|submit/.test(normalized(candidate.textContent || candidate.value))
118
- && !candidate.disabled);
123
+ && !candidate.disabled && !candidate.classList.contains('button--disabled'));
119
124
  if (button) { button.click(); submitted = true; }
120
125
  }
121
126
  return { filled, providerSelected: Boolean(provider), submitted };