@sparkelf/dsh-plus 0.1.0-rc.26 → 0.1.0-rc.27

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/lib/bin.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import { r as runApply } from "./apply-e0aMC4B4.js";
3
3
  import { createRequire } from "node:module";
4
4
  import { execFileSync, spawn, spawnSync } from "node:child_process";
5
- import { createWriteStream, existsSync, mkdirSync, readFileSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
5
+ import { createWriteStream, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, symlinkSync, writeFileSync } from "node:fs";
6
6
  import { dirname, join, resolve } from "node:path";
7
7
  import { homedir } from "node:os";
8
8
  import semver from "semver";
@@ -282,6 +282,11 @@ function readDistributionProfile(distributionDirectory) {
282
282
  * `node_modules` cannot see packages the consumer installed beside it. One link to
283
283
  * the consumer's directory keeps a single installed copy as the only authority.
284
284
  *
285
+ * npm hoists what it can and nests the rest, so a bundle can sit at the consumer's
286
+ * top level or inside the package that depends on it. The profile reaches the first
287
+ * through one link and the second through the distribution's own `node_modules`, and
288
+ * a bundle found in neither is one the installation does not carry at all.
289
+ *
285
290
  * @param paths - resolved standalone paths.
286
291
  * @param consumerDirectory - directory whose `node_modules` holds the packages.
287
292
  */
@@ -290,8 +295,37 @@ function linkConsumerPackages(paths, consumerDirectory) {
290
295
  if (!existsSync(target)) throw new Error("no node_modules in " + consumerDirectory + "; run npm install there first");
291
296
  mkdirSync(paths.profileDirectory, { recursive: true });
292
297
  const link = join(paths.profileDirectory, "node_modules");
293
- if (existsSync(link)) return;
294
- symlinkSync(target, link, "junction");
298
+ if (!existsSync(link)) symlinkSync(target, link, "junction");
299
+ linkNestedBundles(paths, target);
300
+ }
301
+ /**
302
+ * Expose the distribution's nested packages at the top level the profile searches.
303
+ *
304
+ * The profile resolves a bundle from one directory, so a package npm nested under the
305
+ * distribution is invisible there even though the installation carries it. Linking each
306
+ * one beside the hoisted packages keeps a single installed copy and needs no reinstall.
307
+ *
308
+ * @param paths - resolved standalone paths.
309
+ * @param consumerModules - the consumer's `node_modules` directory.
310
+ */
311
+ function linkNestedBundles(paths, consumerModules) {
312
+ const nested = join(paths.distributionDirectory, "node_modules");
313
+ if (!existsSync(nested)) return;
314
+ for (const entry of readdirSync(nested)) {
315
+ if (entry.startsWith("@")) {
316
+ for (const scoped of readdirSync(join(nested, entry))) linkBundle(consumerModules, join(entry, scoped), join(nested, entry, scoped));
317
+ continue;
318
+ }
319
+ linkBundle(consumerModules, entry, join(nested, entry));
320
+ }
321
+ }
322
+ /** Link one nested bundle into the consumer's top level when it is not already there. */
323
+ function linkBundle(consumerModules, name, source) {
324
+ const destination = join(consumerModules, name);
325
+ if (existsSync(destination)) return;
326
+ try {
327
+ symlinkSync(source, destination, "junction");
328
+ } catch {}
295
329
  }
296
330
  /** Resolve every path a command needs, without creating anything. */
297
331
  function resolvePaths(anchor, env = process.env) {
@@ -47,6 +47,11 @@ export declare function readDistributionProfile(distributionDirectory: string):
47
47
  * `node_modules` cannot see packages the consumer installed beside it. One link to
48
48
  * the consumer's directory keeps a single installed copy as the only authority.
49
49
  *
50
+ * npm hoists what it can and nests the rest, so a bundle can sit at the consumer's
51
+ * top level or inside the package that depends on it. The profile reaches the first
52
+ * through one link and the second through the distribution's own `node_modules`, and
53
+ * a bundle found in neither is one the installation does not carry at all.
54
+ *
50
55
  * @param paths - resolved standalone paths.
51
56
  * @param consumerDirectory - directory whose `node_modules` holds the packages.
52
57
  */
@@ -8,7 +8,7 @@
8
8
  * the launcher mounts exactly the bundles the profile names and nothing expands a
9
9
  * bundle's own list.
10
10
  */
11
- import { existsSync, mkdirSync, readFileSync, symlinkSync, writeFileSync } from 'node:fs';
11
+ import { existsSync, mkdirSync, readdirSync, readFileSync, symlinkSync, writeFileSync } from 'node:fs';
12
12
  import { createRequire } from 'node:module';
13
13
  import { homedir } from 'node:os';
14
14
  import { dirname, join, resolve } from 'node:path';
@@ -89,6 +89,11 @@ export function readDistributionProfile(distributionDirectory) {
89
89
  * `node_modules` cannot see packages the consumer installed beside it. One link to
90
90
  * the consumer's directory keeps a single installed copy as the only authority.
91
91
  *
92
+ * npm hoists what it can and nests the rest, so a bundle can sit at the consumer's
93
+ * top level or inside the package that depends on it. The profile reaches the first
94
+ * through one link and the second through the distribution's own `node_modules`, and
95
+ * a bundle found in neither is one the installation does not carry at all.
96
+ *
92
97
  * @param paths - resolved standalone paths.
93
98
  * @param consumerDirectory - directory whose `node_modules` holds the packages.
94
99
  */
@@ -99,9 +104,47 @@ export function linkConsumerPackages(paths, consumerDirectory) {
99
104
  }
100
105
  mkdirSync(paths.profileDirectory, { recursive: true });
101
106
  const link = join(paths.profileDirectory, 'node_modules');
102
- if (existsSync(link))
107
+ if (!existsSync(link))
108
+ symlinkSync(target, link, 'junction');
109
+ // A profile created before the installation changed must still reach what npm nested
110
+ // afterwards, so this runs on every start rather than only when the profile is new.
111
+ linkNestedBundles(paths, target);
112
+ }
113
+ /**
114
+ * Expose the distribution's nested packages at the top level the profile searches.
115
+ *
116
+ * The profile resolves a bundle from one directory, so a package npm nested under the
117
+ * distribution is invisible there even though the installation carries it. Linking each
118
+ * one beside the hoisted packages keeps a single installed copy and needs no reinstall.
119
+ *
120
+ * @param paths - resolved standalone paths.
121
+ * @param consumerModules - the consumer's `node_modules` directory.
122
+ */
123
+ function linkNestedBundles(paths, consumerModules) {
124
+ const nested = join(paths.distributionDirectory, 'node_modules');
125
+ if (!existsSync(nested))
103
126
  return;
104
- symlinkSync(target, link, 'junction');
127
+ for (const entry of readdirSync(nested)) {
128
+ if (entry.startsWith('@')) {
129
+ for (const scoped of readdirSync(join(nested, entry))) {
130
+ linkBundle(consumerModules, join(entry, scoped), join(nested, entry, scoped));
131
+ }
132
+ continue;
133
+ }
134
+ linkBundle(consumerModules, entry, join(nested, entry));
135
+ }
136
+ }
137
+ /** Link one nested bundle into the consumer's top level when it is not already there. */
138
+ function linkBundle(consumerModules, name, source) {
139
+ const destination = join(consumerModules, name);
140
+ if (existsSync(destination))
141
+ return;
142
+ try {
143
+ symlinkSync(source, destination, 'junction');
144
+ }
145
+ catch {
146
+ // A concurrent start may have created the same link; the existing one is equivalent.
147
+ }
105
148
  }
106
149
  /** Resolve every path a command needs, without creating anything. */
107
150
  export function resolvePaths(anchor, env = process.env) {
package/package.json CHANGED
@@ -136,5 +136,5 @@
136
136
  },
137
137
  "type": "module",
138
138
  "types": "lib/types/index.d.ts",
139
- "version": "0.1.0-rc.26"
139
+ "version": "0.1.0-rc.27"
140
140
  }