wyvrnpm 2.10.2 → 2.12.2

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 (49) hide show
  1. package/README.md +1914 -1860
  2. package/bin/{wyvrn.js → wyvrnpm.js} +66 -0
  3. package/cmake/cpp.cmake +9 -9
  4. package/cmake/functions.cmake +224 -224
  5. package/cmake/macros.cmake +284 -284
  6. package/package.json +3 -2
  7. package/src/auth.js +66 -66
  8. package/src/binary-dir.js +95 -0
  9. package/src/bootstrap/cookbook.js +196 -196
  10. package/src/bootstrap/detect.js +150 -150
  11. package/src/bootstrap/index.js +220 -220
  12. package/src/bootstrap/version.js +72 -72
  13. package/src/build/cache.js +344 -344
  14. package/src/build/clone.js +170 -170
  15. package/src/build/cmake.js +342 -342
  16. package/src/build/index.js +299 -297
  17. package/src/build/msvc-env.js +260 -260
  18. package/src/build/recipe.js +188 -188
  19. package/src/commands/add.js +141 -141
  20. package/src/commands/bootstrap.js +96 -96
  21. package/src/commands/build.js +482 -452
  22. package/src/commands/cache.js +189 -189
  23. package/src/commands/clean.js +80 -80
  24. package/src/commands/configure.js +92 -92
  25. package/src/commands/init.js +70 -70
  26. package/src/commands/install-skill.js +115 -115
  27. package/src/commands/install.js +730 -674
  28. package/src/commands/link.js +320 -320
  29. package/src/commands/profile.js +237 -237
  30. package/src/commands/publish.js +584 -555
  31. package/src/commands/show.js +252 -252
  32. package/src/commands/version.js +187 -0
  33. package/src/compat.js +273 -273
  34. package/src/conf/index.js +415 -391
  35. package/src/conf/namespaces.js +94 -94
  36. package/src/context.js +230 -230
  37. package/src/http-fetch.js +53 -53
  38. package/src/ignore.js +118 -118
  39. package/src/logger.js +122 -122
  40. package/src/options.js +303 -303
  41. package/src/settings-overrides.js +152 -152
  42. package/src/toolchain/deps.js +164 -164
  43. package/src/toolchain/index.js +212 -212
  44. package/src/toolchain/presets.js +356 -340
  45. package/src/toolchain/template.cmake +77 -77
  46. package/src/upload-built.js +265 -265
  47. package/src/version-range.js +301 -301
  48. package/src/zip-safe.js +52 -52
  49. package/src/zip-stream.js +126 -0
@@ -1,320 +1,320 @@
1
- 'use strict';
2
-
3
- const fs = require('fs');
4
- const path = require('path');
5
- const { readConfig, writeConfig } = require('../config');
6
- const { readManifest } = require('../manifest');
7
- const { createLink, isLink, removeLink, getLinkTarget } = require('../link-utils');
8
- const { downloadDependencies } = require('../download');
9
- const { resolveDependencies } = require('../resolve');
10
- const { wyvrnFetch } = require('../http-fetch');
11
- const log = require('../logger');
12
-
13
- /**
14
- * Normalizes a linked package entry to object form.
15
- * Supports both legacy string format and new object format.
16
- *
17
- * @param {string|object} entry - Either a path string or {path, subdir} object.
18
- * @returns {{path: string, subdir?: string}}
19
- */
20
- function normalizeLinkedEntry(entry) {
21
- if (typeof entry === 'string') {
22
- return { path: entry };
23
- }
24
- return entry;
25
- }
26
-
27
- /**
28
- * Gets the effective link target path (combining path + subdir).
29
- *
30
- * @param {{path: string, subdir?: string}} entry - Linked package entry.
31
- * @returns {string} The full path to link to.
32
- */
33
- function getEffectivePath(entry) {
34
- if (entry.subdir) {
35
- return path.join(entry.path, entry.subdir);
36
- }
37
- return entry.path;
38
- }
39
-
40
- /**
41
- * Register the current directory's package globally for linking.
42
- * Reads wyvrn.json to get the package name, stores {name: {path, subdir}} in config.
43
- *
44
- * @param {string} manifestPath - Path to wyvrn.json
45
- * @param {string} [subdir] - Optional subdirectory within the package to link.
46
- */
47
- function registerGlobal(manifestPath, subdir) {
48
- const manifest = readManifest(manifestPath);
49
- const packageName = manifest.name || manifest.Name;
50
-
51
- if (!packageName) {
52
- log.error('wyvrn.json must have a "name" field');
53
- process.exit(1);
54
- }
55
-
56
- const packagePath = path.dirname(path.resolve(manifestPath));
57
- const config = readConfig();
58
- config.linkedPackages = config.linkedPackages || {};
59
-
60
- const entry = { path: packagePath };
61
- if (subdir) {
62
- entry.subdir = subdir;
63
- }
64
- config.linkedPackages[packageName] = entry;
65
- writeConfig(config);
66
-
67
- const effectivePath = getEffectivePath(entry);
68
- log.info(`Registered "${packageName}" → ${effectivePath}`);
69
- }
70
-
71
- /**
72
- * Link a package into the current project's wyvrn_internal directory.
73
- *
74
- * @param {string} name - Package name to link.
75
- * @param {string} sourcePath - Source directory path (absolute or relative).
76
- * @param {string} rootDir - Project root directory.
77
- */
78
- function linkToProject(name, sourcePath, rootDir) {
79
- const absoluteSource = path.resolve(sourcePath);
80
-
81
- if (!fs.existsSync(absoluteSource)) {
82
- log.error(`source path does not exist: ${absoluteSource}`);
83
- process.exit(1);
84
- }
85
-
86
- const razerDir = path.join(rootDir, 'wyvrn_internal');
87
- const linkPath = path.join(razerDir, name);
88
-
89
- // Create the link
90
- createLink(absoluteSource, linkPath);
91
-
92
- // Write a .wyvrn-version file to indicate it's linked
93
- const versionFile = path.join(linkPath, '.wyvrn-version');
94
- fs.writeFileSync(versionFile, 'linked', 'utf8');
95
-
96
- // Update the lock file to record the link
97
- const lockPath = path.join(rootDir, 'wyvrn.lock');
98
- let lockData = { packages: {} };
99
- if (fs.existsSync(lockPath)) {
100
- try {
101
- lockData = JSON.parse(fs.readFileSync(lockPath, 'utf8'));
102
- } catch {
103
- // Use default if parsing fails
104
- }
105
- }
106
- lockData.packages = lockData.packages || {};
107
- lockData.packages[name] = `linked:${absoluteSource}`;
108
- lockData.generatedAt = new Date().toISOString();
109
- fs.writeFileSync(lockPath, JSON.stringify(lockData, null, 2) + '\n', 'utf8');
110
-
111
- log.info(`Linked: ${name} → ${absoluteSource}`);
112
- }
113
-
114
- /**
115
- * Unlink a package from the current project.
116
- *
117
- * @param {string} name - Package name to unlink.
118
- * @param {string} rootDir - Project root directory.
119
- * @param {boolean} restore - Whether to re-download from registry.
120
- * @param {object} argv - Original argv for re-download options.
121
- */
122
- async function unlinkFromProject(name, rootDir, restore, argv) {
123
- const razerDir = path.join(rootDir, 'wyvrn_internal');
124
- const linkPath = path.join(razerDir, name);
125
-
126
- if (!fs.existsSync(linkPath)) {
127
- log.error(`package "${name}" is not installed`);
128
- process.exit(1);
129
- }
130
-
131
- if (!isLink(linkPath)) {
132
- log.error(`package "${name}" is not a linked package`);
133
- process.exit(1);
134
- }
135
-
136
- // Remove the symlink
137
- removeLink(linkPath);
138
- log.info(`Unlinked: ${name}`);
139
-
140
- // Update the lock file
141
- const lockPath = path.join(rootDir, 'wyvrn.lock');
142
- if (fs.existsSync(lockPath)) {
143
- try {
144
- const lockData = JSON.parse(fs.readFileSync(lockPath, 'utf8'));
145
- if (lockData.packages && lockData.packages[name]) {
146
- delete lockData.packages[name];
147
- lockData.generatedAt = new Date().toISOString();
148
- fs.writeFileSync(lockPath, JSON.stringify(lockData, null, 2) + '\n', 'utf8');
149
- }
150
- } catch {
151
- // Ignore lock file errors
152
- }
153
- }
154
-
155
- // Re-download from registry if requested
156
- if (restore) {
157
- const manifestPath = path.resolve(argv.manifest);
158
- const manifest = readManifest(manifestPath);
159
-
160
- const rawDeps = manifest.dependencies || manifest.Dependencies || {};
161
- const deps = Array.isArray(rawDeps)
162
- ? Object.fromEntries(rawDeps.map((d) => [d.Name ?? d.name, d.Version ?? d.version]))
163
- : rawDeps;
164
-
165
- if (!deps[name]) {
166
- log.warn(`"${name}" is not in manifest dependencies, cannot restore`);
167
- return;
168
- }
169
-
170
- // Get package sources
171
- let packageSources;
172
- if (argv.source && argv.source.length > 0) {
173
- packageSources = argv.source;
174
- } else {
175
- const config = readConfig();
176
- packageSources = config.installSources.map((s) => s.url);
177
- }
178
-
179
- if (packageSources.length === 0) {
180
- log.warn('no sources configured, cannot restore package');
181
- return;
182
- }
183
-
184
- // Resolve just this one dependency
185
- const resolvedDeps = await resolveDependencies(
186
- { [name]: deps[name] },
187
- packageSources,
188
- argv.platform || 'win_x64',
189
- wyvrnFetch,
190
- new Map(),
191
- );
192
-
193
- // Download it
194
- await downloadDependencies(
195
- resolvedDeps,
196
- packageSources,
197
- argv.platform || 'win_x64',
198
- razerDir,
199
- wyvrnFetch,
200
- argv.timeout || 300,
201
- );
202
-
203
- // Update lock file with restored version
204
- if (fs.existsSync(lockPath)) {
205
- try {
206
- const lockData = JSON.parse(fs.readFileSync(lockPath, 'utf8'));
207
- for (const [depName, version] of resolvedDeps) {
208
- lockData.packages[depName] = version;
209
- }
210
- lockData.generatedAt = new Date().toISOString();
211
- fs.writeFileSync(lockPath, JSON.stringify(lockData, null, 2) + '\n', 'utf8');
212
- } catch {
213
- // Ignore lock file errors
214
- }
215
- }
216
- }
217
- }
218
-
219
- /**
220
- * List all globally registered packages.
221
- */
222
- function listLinked() {
223
- const config = readConfig();
224
- const linked = config.linkedPackages || {};
225
- const entries = Object.entries(linked);
226
-
227
- if (entries.length === 0) {
228
- log.info('No globally registered packages');
229
- return;
230
- }
231
-
232
- log.info('Globally registered packages:');
233
- for (const [name, rawEntry] of entries) {
234
- const entry = normalizeLinkedEntry(rawEntry);
235
- const effectivePath = getEffectivePath(entry);
236
- const exists = fs.existsSync(effectivePath);
237
- const status = exists ? '' : ' (path not found)';
238
- const subdirInfo = entry.subdir ? ` [subdir: ${entry.subdir}]` : '';
239
- console.log(` ${name} → ${effectivePath}${subdirInfo}${status}`);
240
- }
241
- }
242
-
243
- /**
244
- * Main link command handler.
245
- *
246
- * @param {object} argv - Parsed yargs arguments.
247
- */
248
- async function link(argv) {
249
- const rootDir = path.resolve(argv.root);
250
- const manifestPath = path.resolve(argv.manifest);
251
-
252
- // wyvrnpm link --list
253
- if (argv.list) {
254
- listLinked();
255
- return;
256
- }
257
-
258
- // wyvrnpm link (no args) - register current package globally
259
- if (!argv.name) {
260
- if (!fs.existsSync(manifestPath)) {
261
- log.error(`no wyvrn.json found at ${manifestPath}`);
262
- process.exit(1);
263
- }
264
- registerGlobal(manifestPath, argv.subdir);
265
- return;
266
- }
267
-
268
- // wyvrnpm link <name> <path> - direct path link
269
- if (argv.name && argv.path) {
270
- let targetPath = argv.path;
271
- if (argv.subdir) {
272
- targetPath = path.join(argv.path, argv.subdir);
273
- }
274
- linkToProject(argv.name, targetPath, rootDir);
275
- return;
276
- }
277
-
278
- // wyvrnpm link <name> - link from global registry
279
- const config = readConfig();
280
- const linked = config.linkedPackages || {};
281
-
282
- if (!linked[argv.name]) {
283
- log.error(
284
- `"${argv.name}" is not registered globally\n` +
285
- `Run "wyvrnpm link" in the package directory first, or use:\n` +
286
- ` wyvrnpm link ${argv.name} <path>`,
287
- );
288
- process.exit(1);
289
- }
290
-
291
- const entry = normalizeLinkedEntry(linked[argv.name]);
292
- // Command-line --subdir overrides the registered subdir
293
- let effectivePath;
294
- if (argv.subdir) {
295
- effectivePath = path.join(entry.path, argv.subdir);
296
- } else {
297
- effectivePath = getEffectivePath(entry);
298
- }
299
-
300
- linkToProject(argv.name, effectivePath, rootDir);
301
- }
302
-
303
- /**
304
- * Unlink command handler.
305
- *
306
- * @param {object} argv - Parsed yargs arguments.
307
- */
308
- async function unlink(argv) {
309
- const rootDir = path.resolve(argv.root);
310
- await unlinkFromProject(argv.name, rootDir, argv.restore, argv);
311
- }
312
-
313
- module.exports = {
314
- link,
315
- unlink,
316
- listLinked,
317
- registerGlobal,
318
- linkToProject,
319
- unlinkFromProject,
320
- };
1
+ 'use strict';
2
+
3
+ const fs = require('fs');
4
+ const path = require('path');
5
+ const { readConfig, writeConfig } = require('../config');
6
+ const { readManifest } = require('../manifest');
7
+ const { createLink, isLink, removeLink, getLinkTarget } = require('../link-utils');
8
+ const { downloadDependencies } = require('../download');
9
+ const { resolveDependencies } = require('../resolve');
10
+ const { wyvrnFetch } = require('../http-fetch');
11
+ const log = require('../logger');
12
+
13
+ /**
14
+ * Normalizes a linked package entry to object form.
15
+ * Supports both legacy string format and new object format.
16
+ *
17
+ * @param {string|object} entry - Either a path string or {path, subdir} object.
18
+ * @returns {{path: string, subdir?: string}}
19
+ */
20
+ function normalizeLinkedEntry(entry) {
21
+ if (typeof entry === 'string') {
22
+ return { path: entry };
23
+ }
24
+ return entry;
25
+ }
26
+
27
+ /**
28
+ * Gets the effective link target path (combining path + subdir).
29
+ *
30
+ * @param {{path: string, subdir?: string}} entry - Linked package entry.
31
+ * @returns {string} The full path to link to.
32
+ */
33
+ function getEffectivePath(entry) {
34
+ if (entry.subdir) {
35
+ return path.join(entry.path, entry.subdir);
36
+ }
37
+ return entry.path;
38
+ }
39
+
40
+ /**
41
+ * Register the current directory's package globally for linking.
42
+ * Reads wyvrn.json to get the package name, stores {name: {path, subdir}} in config.
43
+ *
44
+ * @param {string} manifestPath - Path to wyvrn.json
45
+ * @param {string} [subdir] - Optional subdirectory within the package to link.
46
+ */
47
+ function registerGlobal(manifestPath, subdir) {
48
+ const manifest = readManifest(manifestPath);
49
+ const packageName = manifest.name || manifest.Name;
50
+
51
+ if (!packageName) {
52
+ log.error('wyvrn.json must have a "name" field');
53
+ process.exit(1);
54
+ }
55
+
56
+ const packagePath = path.dirname(path.resolve(manifestPath));
57
+ const config = readConfig();
58
+ config.linkedPackages = config.linkedPackages || {};
59
+
60
+ const entry = { path: packagePath };
61
+ if (subdir) {
62
+ entry.subdir = subdir;
63
+ }
64
+ config.linkedPackages[packageName] = entry;
65
+ writeConfig(config);
66
+
67
+ const effectivePath = getEffectivePath(entry);
68
+ log.info(`Registered "${packageName}" → ${effectivePath}`);
69
+ }
70
+
71
+ /**
72
+ * Link a package into the current project's wyvrn_internal directory.
73
+ *
74
+ * @param {string} name - Package name to link.
75
+ * @param {string} sourcePath - Source directory path (absolute or relative).
76
+ * @param {string} rootDir - Project root directory.
77
+ */
78
+ function linkToProject(name, sourcePath, rootDir) {
79
+ const absoluteSource = path.resolve(sourcePath);
80
+
81
+ if (!fs.existsSync(absoluteSource)) {
82
+ log.error(`source path does not exist: ${absoluteSource}`);
83
+ process.exit(1);
84
+ }
85
+
86
+ const razerDir = path.join(rootDir, 'wyvrn_internal');
87
+ const linkPath = path.join(razerDir, name);
88
+
89
+ // Create the link
90
+ createLink(absoluteSource, linkPath);
91
+
92
+ // Write a .wyvrn-version file to indicate it's linked
93
+ const versionFile = path.join(linkPath, '.wyvrn-version');
94
+ fs.writeFileSync(versionFile, 'linked', 'utf8');
95
+
96
+ // Update the lock file to record the link
97
+ const lockPath = path.join(rootDir, 'wyvrn.lock');
98
+ let lockData = { packages: {} };
99
+ if (fs.existsSync(lockPath)) {
100
+ try {
101
+ lockData = JSON.parse(fs.readFileSync(lockPath, 'utf8'));
102
+ } catch {
103
+ // Use default if parsing fails
104
+ }
105
+ }
106
+ lockData.packages = lockData.packages || {};
107
+ lockData.packages[name] = `linked:${absoluteSource}`;
108
+ lockData.generatedAt = new Date().toISOString();
109
+ fs.writeFileSync(lockPath, JSON.stringify(lockData, null, 2) + '\n', 'utf8');
110
+
111
+ log.info(`Linked: ${name} → ${absoluteSource}`);
112
+ }
113
+
114
+ /**
115
+ * Unlink a package from the current project.
116
+ *
117
+ * @param {string} name - Package name to unlink.
118
+ * @param {string} rootDir - Project root directory.
119
+ * @param {boolean} restore - Whether to re-download from registry.
120
+ * @param {object} argv - Original argv for re-download options.
121
+ */
122
+ async function unlinkFromProject(name, rootDir, restore, argv) {
123
+ const razerDir = path.join(rootDir, 'wyvrn_internal');
124
+ const linkPath = path.join(razerDir, name);
125
+
126
+ if (!fs.existsSync(linkPath)) {
127
+ log.error(`package "${name}" is not installed`);
128
+ process.exit(1);
129
+ }
130
+
131
+ if (!isLink(linkPath)) {
132
+ log.error(`package "${name}" is not a linked package`);
133
+ process.exit(1);
134
+ }
135
+
136
+ // Remove the symlink
137
+ removeLink(linkPath);
138
+ log.info(`Unlinked: ${name}`);
139
+
140
+ // Update the lock file
141
+ const lockPath = path.join(rootDir, 'wyvrn.lock');
142
+ if (fs.existsSync(lockPath)) {
143
+ try {
144
+ const lockData = JSON.parse(fs.readFileSync(lockPath, 'utf8'));
145
+ if (lockData.packages && lockData.packages[name]) {
146
+ delete lockData.packages[name];
147
+ lockData.generatedAt = new Date().toISOString();
148
+ fs.writeFileSync(lockPath, JSON.stringify(lockData, null, 2) + '\n', 'utf8');
149
+ }
150
+ } catch {
151
+ // Ignore lock file errors
152
+ }
153
+ }
154
+
155
+ // Re-download from registry if requested
156
+ if (restore) {
157
+ const manifestPath = path.resolve(argv.manifest);
158
+ const manifest = readManifest(manifestPath);
159
+
160
+ const rawDeps = manifest.dependencies || manifest.Dependencies || {};
161
+ const deps = Array.isArray(rawDeps)
162
+ ? Object.fromEntries(rawDeps.map((d) => [d.Name ?? d.name, d.Version ?? d.version]))
163
+ : rawDeps;
164
+
165
+ if (!deps[name]) {
166
+ log.warn(`"${name}" is not in manifest dependencies, cannot restore`);
167
+ return;
168
+ }
169
+
170
+ // Get package sources
171
+ let packageSources;
172
+ if (argv.source && argv.source.length > 0) {
173
+ packageSources = argv.source;
174
+ } else {
175
+ const config = readConfig();
176
+ packageSources = config.installSources.map((s) => s.url);
177
+ }
178
+
179
+ if (packageSources.length === 0) {
180
+ log.warn('no sources configured, cannot restore package');
181
+ return;
182
+ }
183
+
184
+ // Resolve just this one dependency
185
+ const resolvedDeps = await resolveDependencies(
186
+ { [name]: deps[name] },
187
+ packageSources,
188
+ argv.platform || 'win_x64',
189
+ wyvrnFetch,
190
+ new Map(),
191
+ );
192
+
193
+ // Download it
194
+ await downloadDependencies(
195
+ resolvedDeps,
196
+ packageSources,
197
+ argv.platform || 'win_x64',
198
+ razerDir,
199
+ wyvrnFetch,
200
+ argv.timeout || 300,
201
+ );
202
+
203
+ // Update lock file with restored version
204
+ if (fs.existsSync(lockPath)) {
205
+ try {
206
+ const lockData = JSON.parse(fs.readFileSync(lockPath, 'utf8'));
207
+ for (const [depName, version] of resolvedDeps) {
208
+ lockData.packages[depName] = version;
209
+ }
210
+ lockData.generatedAt = new Date().toISOString();
211
+ fs.writeFileSync(lockPath, JSON.stringify(lockData, null, 2) + '\n', 'utf8');
212
+ } catch {
213
+ // Ignore lock file errors
214
+ }
215
+ }
216
+ }
217
+ }
218
+
219
+ /**
220
+ * List all globally registered packages.
221
+ */
222
+ function listLinked() {
223
+ const config = readConfig();
224
+ const linked = config.linkedPackages || {};
225
+ const entries = Object.entries(linked);
226
+
227
+ if (entries.length === 0) {
228
+ log.info('No globally registered packages');
229
+ return;
230
+ }
231
+
232
+ log.info('Globally registered packages:');
233
+ for (const [name, rawEntry] of entries) {
234
+ const entry = normalizeLinkedEntry(rawEntry);
235
+ const effectivePath = getEffectivePath(entry);
236
+ const exists = fs.existsSync(effectivePath);
237
+ const status = exists ? '' : ' (path not found)';
238
+ const subdirInfo = entry.subdir ? ` [subdir: ${entry.subdir}]` : '';
239
+ console.log(` ${name} → ${effectivePath}${subdirInfo}${status}`);
240
+ }
241
+ }
242
+
243
+ /**
244
+ * Main link command handler.
245
+ *
246
+ * @param {object} argv - Parsed yargs arguments.
247
+ */
248
+ async function link(argv) {
249
+ const rootDir = path.resolve(argv.root);
250
+ const manifestPath = path.resolve(argv.manifest);
251
+
252
+ // wyvrnpm link --list
253
+ if (argv.list) {
254
+ listLinked();
255
+ return;
256
+ }
257
+
258
+ // wyvrnpm link (no args) - register current package globally
259
+ if (!argv.name) {
260
+ if (!fs.existsSync(manifestPath)) {
261
+ log.error(`no wyvrn.json found at ${manifestPath}`);
262
+ process.exit(1);
263
+ }
264
+ registerGlobal(manifestPath, argv.subdir);
265
+ return;
266
+ }
267
+
268
+ // wyvrnpm link <name> <path> - direct path link
269
+ if (argv.name && argv.path) {
270
+ let targetPath = argv.path;
271
+ if (argv.subdir) {
272
+ targetPath = path.join(argv.path, argv.subdir);
273
+ }
274
+ linkToProject(argv.name, targetPath, rootDir);
275
+ return;
276
+ }
277
+
278
+ // wyvrnpm link <name> - link from global registry
279
+ const config = readConfig();
280
+ const linked = config.linkedPackages || {};
281
+
282
+ if (!linked[argv.name]) {
283
+ log.error(
284
+ `"${argv.name}" is not registered globally\n` +
285
+ `Run "wyvrnpm link" in the package directory first, or use:\n` +
286
+ ` wyvrnpm link ${argv.name} <path>`,
287
+ );
288
+ process.exit(1);
289
+ }
290
+
291
+ const entry = normalizeLinkedEntry(linked[argv.name]);
292
+ // Command-line --subdir overrides the registered subdir
293
+ let effectivePath;
294
+ if (argv.subdir) {
295
+ effectivePath = path.join(entry.path, argv.subdir);
296
+ } else {
297
+ effectivePath = getEffectivePath(entry);
298
+ }
299
+
300
+ linkToProject(argv.name, effectivePath, rootDir);
301
+ }
302
+
303
+ /**
304
+ * Unlink command handler.
305
+ *
306
+ * @param {object} argv - Parsed yargs arguments.
307
+ */
308
+ async function unlink(argv) {
309
+ const rootDir = path.resolve(argv.root);
310
+ await unlinkFromProject(argv.name, rootDir, argv.restore, argv);
311
+ }
312
+
313
+ module.exports = {
314
+ link,
315
+ unlink,
316
+ listLinked,
317
+ registerGlobal,
318
+ linkToProject,
319
+ unlinkFromProject,
320
+ };