pier-setup 0.4.2 → 0.4.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +4 -0
  2. package/install.mjs +67 -13
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -77,6 +77,10 @@ node install.mjs update --dev # re-check env + versions; pull the repo yourse
77
77
  ```
78
78
 
79
79
  The script verifies the environment (node / pi / herdr versions) and registers both halves.
80
+ pier must be registered in pi from exactly one source: `install`/`update` drops the legacy
81
+ `git:github.com/July24/pier` registration automatically, and stops (exit 1, nothing changed)
82
+ when pier is already registered from another source - e.g. a `--dev` checkout before a user-mode
83
+ install - printing the `pi remove …` to run. `version` reports the source pi actually loads.
80
84
 
81
85
  `update` re-runs `pi update npm:pi-pier` (falls back to `pi install`) and
82
86
  `herdr plugin install … --yes`. Override sources with
package/install.mjs CHANGED
@@ -127,14 +127,17 @@ function cmpSemver(a, b) {
127
127
  return 0;
128
128
  }
129
129
 
130
- function readPkgVersion(dir) {
130
+ function readPkgJson(dir) {
131
131
  try {
132
- return JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8')).version ?? null;
132
+ return JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8'));
133
133
  } catch {
134
134
  return null;
135
135
  }
136
136
  }
137
137
 
138
+ const readPkgVersion = (dir) => readPkgJson(dir)?.version ?? null;
139
+ const readPkgName = (dir) => readPkgJson(dir)?.name ?? null;
140
+
138
141
  function npmLatest(name) {
139
142
  try {
140
143
  return run('npm', ['view', name, 'version'], { timeout: 15000 });
@@ -181,12 +184,56 @@ function registeredPiPackages() {
181
184
  } catch { return []; }
182
185
  }
183
186
 
184
- /** Clean up legacy git-mode registration before install/update; if --pi-spec explicitly specifies that git source, treat it as target and keep it. */
185
- function removeLegacyGitRegistration() {
186
- if (piSource() === LEGACY_GIT_SPEC) return;
187
- if (!registeredPiPackages().includes(LEGACY_GIT_SPEC)) return;
188
- if (tryRun('pi', ['remove', LEGACY_GIT_SPEC])) log(`✓ removed legacy git-mode registration (${LEGACY_GIT_SPEC}); using ${piSource()}`);
189
- else { console.error('✗ failed to remove legacy git-mode registration'); log(` manual: pi remove ${LEGACY_GIT_SPEC}`); process.exitCode = 1; }
187
+ /** A `packages` entry is a string spec or `{ source }`; local paths are relative to the agent dir. */
188
+ function packageSource(entry) {
189
+ return typeof entry === 'string' ? entry : (typeof entry?.source === 'string' ? entry.source : null);
190
+ }
191
+
192
+ function localPackageDir(src) {
193
+ if (/^(npm|git|https?|ssh):/.test(src)) return null;
194
+ return resolve(piAgentDir(), src.startsWith('~/') ? join(homedir(), src.slice(2)) : src);
195
+ }
196
+
197
+ /** Registered sources that load pier's extension (npm, git, or a local checkout of pi-pier). */
198
+ function registeredPierSources() {
199
+ return registeredPiPackages().map(packageSource).filter((src) => {
200
+ if (!src) return false;
201
+ if (npmNameFromSpec(src) === 'pi-pier' || /^git:.*july24\/pier/i.test(src)) return true;
202
+ const dir = localPackageDir(src);
203
+ return dir !== null && readPkgName(dir) === 'pi-pier';
204
+ });
205
+ }
206
+
207
+ function sameSource(registered, target) {
208
+ const dir = localPackageDir(registered);
209
+ if (dir !== null) return localPackageDir(target) === dir;
210
+ const name = npmNameFromSpec(registered);
211
+ return name !== null ? npmNameFromSpec(target) === name : registered === target;
212
+ }
213
+
214
+ /** Human/CLI form of a registered source: local entries become absolute (`pi remove` takes them). */
215
+ function displaySource(src) {
216
+ const dir = localPackageDir(src);
217
+ return dir !== null ? dir : src;
218
+ }
219
+
220
+ /**
221
+ * Before install/update: drop the legacy git-mode registration (unless it is the explicit target),
222
+ * and refuse when pier is registered from any other source — two registrations load every pier
223
+ * tool twice and pi rejects the duplicate at launch.
224
+ */
225
+ function reconcilePierRegistrations() {
226
+ for (const src of registeredPierSources()) {
227
+ if (sameSource(src, piSource())) continue;
228
+ if (src === LEGACY_GIT_SPEC) {
229
+ if (tryRun('pi', ['remove', LEGACY_GIT_SPEC])) log(`✓ removed legacy git-mode registration (${LEGACY_GIT_SPEC}); using ${piSource()}`);
230
+ else { console.error('✗ failed to remove legacy git-mode registration'); log(` manual: pi remove ${LEGACY_GIT_SPEC}`); process.exitCode = 1; }
231
+ continue;
232
+ }
233
+ const switchHint = localPackageDir(src) !== null && !dev ? ', or keep it and rerun with --dev'
234
+ : dev && localPackageDir(src) === null ? ', or keep it and rerun without --dev' : '';
235
+ die(`pier is already registered in pi from ${displaySource(src)}; adding ${piSource()} would load every pier tool twice.\n Remove it first: pi remove ${displaySource(src)}${switchHint}`);
236
+ }
190
237
  }
191
238
 
192
239
  function npmNameFromSpec(spec) {
@@ -305,13 +352,20 @@ function herdrPluginInfo() {
305
352
 
306
353
  function collectStatus() {
307
354
  const installer = readPkgVersion(ROOT);
308
- const extPath = dev ? (existsSync(EXT_PATH) ? EXT_PATH : null) : resolveUserExtPath();
309
- const extDir = extPath ? pkgDirFromExtPath(extPath) : null;
355
+ // Report what pi actually loads, not the spec this run would install.
356
+ const registered = registeredPierSources();
357
+ const registeredDir = registered.map(localPackageDir).find((d) => d !== null);
358
+ const extDir = dev
359
+ ? (existsSync(EXT_PATH) ? EXT_DIR : null)
360
+ : registeredDir ?? (() => { const p = resolveUserExtPath(); return p ? pkgDirFromExtPath(p) : null; })();
361
+ const spec = registered.length > 0
362
+ ? registered.map((src) => (localPackageDir(src) !== null ? `local:${localPackageDir(src)}` : src)).join(', ')
363
+ : piSource();
310
364
  return {
311
365
  product: (extDir ? readPkgVersion(extDir) : null) || installer,
312
366
  mode: dev ? 'dev' : 'user',
313
367
  installer: { name: 'pier-setup', version: installer },
314
- piExt: { spec: piSource(), version: extDir ? readPkgVersion(extDir) : null, path: extDir },
368
+ piExt: { spec, version: extDir ? readPkgVersion(extDir) : null, path: extDir },
315
369
  herdr: herdrPluginInfo(),
316
370
  latest: { 'pier-setup': npmLatest('pier-setup'), 'pi-pier': npmLatest('pi-pier') },
317
371
  };
@@ -362,7 +416,7 @@ function version() {
362
416
 
363
417
  function update() {
364
418
  checkEnv();
365
- removeLegacyGitRegistration();
419
+ reconcilePierRegistrations();
366
420
  const me = readPkgVersion(ROOT);
367
421
  const latestSetup = npmLatest('pier-setup');
368
422
  if (latestSetup && me && cmpSemver(me, latestSetup) < 0) {
@@ -389,7 +443,7 @@ function update() {
389
443
 
390
444
  function install() {
391
445
  checkEnv();
392
- removeLegacyGitRegistration();
446
+ reconcilePierRegistrations();
393
447
 
394
448
  if (dev) {
395
449
  if (tryRun('pi', ['install', piSource()])) log('✓ pi extension installed (packages/pier-ext, local)');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pier-setup",
3
- "version": "0.4.2",
3
+ "version": "0.4.3",
4
4
  "description": "One-shot installer for pier: install / update / version / uninstall for pi-pier + pier.workbench",
5
5
  "license": "MIT",
6
6
  "type": "module",