piral-cli 1.8.0-beta.7544 → 1.8.0-beta.7653

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 (74) hide show
  1. package/lib/apps/add-piral-instance-pilet.d.ts +8 -0
  2. package/lib/apps/add-piral-instance-pilet.js +6 -2
  3. package/lib/apps/add-piral-instance-pilet.js.map +1 -1
  4. package/lib/apps/new-pilet.d.ts +8 -0
  5. package/lib/apps/new-pilet.js +6 -2
  6. package/lib/apps/new-pilet.js.map +1 -1
  7. package/lib/apps/publish-pilet.d.ts +4 -0
  8. package/lib/apps/publish-pilet.js +9 -7
  9. package/lib/apps/publish-pilet.js.map +1 -1
  10. package/lib/apps/publish-piral.d.ts +4 -0
  11. package/lib/apps/publish-piral.js +6 -4
  12. package/lib/apps/publish-piral.js.map +1 -1
  13. package/lib/apps/run-emulator-piral.d.ts +8 -0
  14. package/lib/apps/run-emulator-piral.js +7 -5
  15. package/lib/apps/run-emulator-piral.js.map +1 -1
  16. package/lib/apps/upgrade-pilet.d.ts +8 -0
  17. package/lib/apps/upgrade-pilet.js +7 -3
  18. package/lib/apps/upgrade-pilet.js.map +1 -1
  19. package/lib/commands.js +40 -0
  20. package/lib/commands.js.map +1 -1
  21. package/lib/common/config.d.ts +4 -0
  22. package/lib/common/config.js +1 -0
  23. package/lib/common/config.js.map +1 -1
  24. package/lib/common/constants.d.ts +1 -1
  25. package/lib/common/constants.js +1 -0
  26. package/lib/common/constants.js.map +1 -1
  27. package/lib/common/emulator.js +3 -3
  28. package/lib/common/emulator.js.map +1 -1
  29. package/lib/common/http.d.ts +9 -3
  30. package/lib/common/http.js +24 -8
  31. package/lib/common/http.js.map +1 -1
  32. package/lib/common/npm.d.ts +6 -6
  33. package/lib/common/npm.js +63 -34
  34. package/lib/common/npm.js.map +1 -1
  35. package/lib/common/package.d.ts +5 -3
  36. package/lib/common/package.js +7 -7
  37. package/lib/common/package.js.map +1 -1
  38. package/lib/common/release.d.ts +2 -1
  39. package/lib/common/release.js +2 -2
  40. package/lib/common/release.js.map +1 -1
  41. package/lib/common/shell.d.ts +4 -2
  42. package/lib/common/shell.js +2 -2
  43. package/lib/common/shell.js.map +1 -1
  44. package/lib/common/website.d.ts +4 -2
  45. package/lib/common/website.js +7 -11
  46. package/lib/common/website.js.map +1 -1
  47. package/lib/external/index.js +10 -10
  48. package/lib/npm-clients/index.d.ts +9 -5
  49. package/lib/npm-clients/index.js +17 -5
  50. package/lib/npm-clients/index.js.map +1 -1
  51. package/lib/types/internal.d.ts +18 -1
  52. package/lib/types/public.d.ts +3 -1
  53. package/package.json +2 -2
  54. package/src/apps/add-piral-instance-pilet.ts +20 -1
  55. package/src/apps/new-pilet.ts +19 -1
  56. package/src/apps/publish-pilet.ts +17 -7
  57. package/src/apps/publish-piral.ts +13 -4
  58. package/src/apps/run-emulator-piral.ts +22 -6
  59. package/src/apps/upgrade-pilet.ts +21 -2
  60. package/src/commands.ts +41 -1
  61. package/src/common/config.ts +5 -0
  62. package/src/common/constants.ts +1 -0
  63. package/src/common/emulator.ts +4 -4
  64. package/src/common/http.test.ts +5 -4
  65. package/src/common/http.ts +26 -7
  66. package/src/common/npm.test.ts +16 -16
  67. package/src/common/npm.ts +84 -50
  68. package/src/common/package.ts +10 -11
  69. package/src/common/release.ts +3 -2
  70. package/src/common/shell.ts +6 -4
  71. package/src/common/website.ts +8 -11
  72. package/src/npm-clients/index.ts +21 -6
  73. package/src/types/internal.ts +25 -1
  74. package/src/types/public.ts +5 -1
package/src/common/npm.ts CHANGED
@@ -5,10 +5,10 @@ import { config } from './config';
5
5
  import { legacyCoreExternals, frameworkLibs, defaultRegistry, packageJson } from './constants';
6
6
  import { inspectPackage } from './inspect';
7
7
  import { readJson, checkExists } from './io';
8
- import { clients, detectClients, isWrapperClient } from '../npm-clients';
8
+ import { clients, detectDirectClients, detectWrapperClients, isDirectClient, isWrapperClient } from '../npm-clients';
9
9
  import { clientTypeKeys } from '../helpers';
10
10
  import { getModulePath } from '../external';
11
- import { PackageType, NpmClientType } from '../types';
11
+ import { PackageType, NpmClientType, NpmClient, NpmDirectClientType, NpmWapperClientType } from '../types';
12
12
 
13
13
  const gitPrefix = 'git+';
14
14
  const filePrefix = 'file:';
@@ -63,56 +63,88 @@ async function detectMonorepoRoot(root: string): Promise<[] | [string, NpmClient
63
63
  return [];
64
64
  }
65
65
 
66
- /**
67
- * For details about how this works consult issue
68
- * https://github.com/smapiot/piral/issues/203
69
- * @param root The project's root directory.
70
- */
71
- export async function determineNpmClient(root: string, selected?: NpmClientType): Promise<NpmClientType> {
72
- if (!selected || !clientTypeKeys.includes(selected)) {
73
- log('generalDebug_0003', 'No npm client selected. Checking for lock or config files ...');
66
+ async function determineWrapperClient(root: string): Promise<NpmWapperClientType | undefined> {
67
+ const searchedClients = await detectWrapperClients(root);
68
+ const foundClients = searchedClients.filter((m) => m.result).map((m) => m.client);
74
69
 
75
- const searchedClients = await detectClients(root);
76
- const foundClients = searchedClients.filter((m) => m.result);
77
-
78
- log(
79
- 'generalDebug_0003',
80
- `Results of the lock file check: ${searchedClients.map((m) => `${m.client}=${m.result}`).join(', ')}`,
81
- );
70
+ if (foundClients.length > 0) {
71
+ const [client] = foundClients;
82
72
 
83
73
  if (foundClients.length > 1) {
84
- const wrapperClient = foundClients.find((m) => isWrapperClient(m.client));
85
-
86
- if (wrapperClient) {
87
- const { client } = wrapperClient;
88
- log('generalDebug_0003', `Found valid wrapper client via lock or config file: "${client}".`);
89
- }
74
+ log(
75
+ 'generalWarning_0001',
76
+ `Found multiple clients via their lock or config files: "${foundClients.join('", "')}".`,
77
+ );
90
78
  }
91
79
 
92
- if (foundClients.length > 0) {
93
- const { client } = foundClients[0];
80
+ log('generalDebug_0003', `Found valid direct client via lock or config file: "${client}".`);
81
+ return client;
82
+ }
94
83
 
95
- if (foundClients.length > 1) {
96
- const clientStr = `"${foundClients.map((m) => m.client).join('", "')}"`;
97
- log('generalWarning_0001', `Found multiple clients via their lock or config files: ${clientStr}.`);
98
- }
84
+ const defaultClient = config.npmClient;
99
85
 
100
- log('generalDebug_0003', `Found valid direct client via lock or config file: "${client}".`);
101
- return client;
102
- }
86
+ if (isWrapperClient(defaultClient)) {
87
+ log('generalDebug_0003', `Using the default client: "${defaultClient}".`);
88
+ return defaultClient;
89
+ }
90
+
91
+ return undefined;
92
+ }
103
93
 
104
- const defaultClient = config.npmClient;
94
+ async function determineDirectClient(root: string): Promise<NpmDirectClientType> {
95
+ const searchedClients = await detectDirectClients(root);
96
+ const foundClients = searchedClients.filter((m) => m.result).map((m) => m.client);
105
97
 
106
- if (clientTypeKeys.includes(defaultClient)) {
107
- log('generalDebug_0003', `Using the default client: "${defaultClient}".`);
108
- return defaultClient;
98
+ if (foundClients.length > 0) {
99
+ const [client] = foundClients;
100
+
101
+ if (foundClients.length > 1) {
102
+ log(
103
+ 'generalWarning_0001',
104
+ `Found multiple clients via their lock or config files: "${foundClients.join('", "')}".`,
105
+ );
109
106
  }
110
107
 
111
- log('generalDebug_0003', 'Using the fallback "npm" client.');
112
- return 'npm';
108
+ log('generalDebug_0003', `Found valid direct client via lock or config file: "${client}".`);
109
+ return client;
110
+ }
111
+
112
+ const defaultClient = config.npmClient;
113
+
114
+ if (isDirectClient(defaultClient)) {
115
+ log('generalDebug_0003', `Using the default client: "${defaultClient}".`);
116
+ return defaultClient;
113
117
  }
114
118
 
115
- return selected;
119
+ log('generalDebug_0003', 'Using the fallback "npm" client.');
120
+ return 'npm';
121
+ }
122
+
123
+ /**
124
+ * For details about how this works consult issue
125
+ * https://github.com/smapiot/piral/issues/203
126
+ * @param root The project's root directory.
127
+ */
128
+ export async function determineNpmClient(root: string, selected?: NpmClientType): Promise<NpmClient> {
129
+ if (!selected || !clientTypeKeys.includes(selected)) {
130
+ log('generalDebug_0003', 'No npm client selected. Checking for lock or config files ...');
131
+ const [direct, wrapper] = await Promise.all([determineDirectClient(root), determineWrapperClient(root)]);
132
+ return {
133
+ direct,
134
+ wrapper,
135
+ };
136
+ } else if (isDirectClient(selected)) {
137
+ return {
138
+ proposed: selected,
139
+ direct: selected,
140
+ };
141
+ } else {
142
+ return {
143
+ proposed: selected,
144
+ direct: await determineDirectClient(root),
145
+ wrapper: selected,
146
+ };
147
+ }
116
148
  }
117
149
 
118
150
  export async function isMonorepoPackageRef(refName: string, root: string): Promise<boolean> {
@@ -126,35 +158,37 @@ export async function isMonorepoPackageRef(refName: string, root: string): Promi
126
158
  return false;
127
159
  }
128
160
 
129
- export function installNpmDependencies(client: NpmClientType, target = '.'): Promise<string> {
130
- const { installDependencies } = clients[client];
161
+ export function installNpmDependencies(client: NpmClient, target = '.'): Promise<string> {
162
+ const { installDependencies } = clients[client.direct];
131
163
  return installDependencies(target);
132
164
  }
133
165
 
134
166
  export async function installNpmPackageFromOptionalRegistry(
135
167
  packageRef: string,
136
- target = '.',
168
+ target: string,
137
169
  registry: string,
138
170
  ): Promise<void> {
171
+ const client = await determineNpmClient(target, 'npm');
172
+
139
173
  try {
140
- await installNpmPackage('npm', packageRef, target, '--registry', registry);
174
+ await installNpmPackage(client, packageRef, target, '--registry', registry);
141
175
  } catch (e) {
142
176
  if (registry === defaultRegistry) {
143
177
  throw e;
144
178
  }
145
179
 
146
- await installNpmPackage('npm', packageRef, target, '--registry', defaultRegistry);
180
+ await installNpmPackage(client, packageRef, target, '--registry', defaultRegistry);
147
181
  }
148
182
  }
149
183
 
150
184
  export async function uninstallNpmPackage(
151
- client: NpmClientType,
185
+ client: NpmClient,
152
186
  packageRef: string,
153
187
  target = '.',
154
188
  ...flags: Array<string>
155
189
  ): Promise<string> {
156
190
  try {
157
- const { uninstallPackage } = clients[client];
191
+ const { uninstallPackage } = clients[client.direct];
158
192
  return await uninstallPackage(packageRef, target, ...flags);
159
193
  } catch (ex) {
160
194
  log(
@@ -166,13 +200,13 @@ export async function uninstallNpmPackage(
166
200
  }
167
201
 
168
202
  export async function installNpmPackage(
169
- client: NpmClientType,
203
+ client: NpmClient,
170
204
  packageRef: string,
171
205
  target = '.',
172
206
  ...flags: Array<string>
173
207
  ): Promise<string> {
174
208
  try {
175
- const { installPackage } = clients[client];
209
+ const { installPackage } = clients[client.direct];
176
210
  return await installPackage(packageRef, target, ...flags);
177
211
  } catch (ex) {
178
212
  log(
@@ -183,8 +217,8 @@ export async function installNpmPackage(
183
217
  }
184
218
  }
185
219
 
186
- export function initNpmProject(client: NpmClientType, projectName: string, target: string) {
187
- const { initProject } = clients[client];
220
+ export function initNpmProject(client: NpmClient, projectName: string, target: string) {
221
+ const { initProject } = clients[client.wrapper || client.direct];
188
222
  return initProject(projectName, target);
189
223
  }
190
224
 
@@ -1,3 +1,4 @@
1
+ import { Agent } from 'https';
1
2
  import { resolve, join, extname, basename, dirname, relative } from 'path';
2
3
  import { log, fail } from './log';
3
4
  import { cliVersion } from './info';
@@ -161,7 +162,8 @@ async function loadPiralInstance(root: string, details?: PiralInstanceDetails):
161
162
  export async function findPiralInstance(
162
163
  proposedApp: string,
163
164
  rootDir: string,
164
- details?: PiralInstanceDetails,
165
+ details: PiralInstanceDetails,
166
+ agent: Agent,
165
167
  interactive = false,
166
168
  ) {
167
169
  const path = findPackageRoot(proposedApp, rootDir);
@@ -172,13 +174,13 @@ export async function findPiralInstance(
172
174
 
173
175
  if (url) {
174
176
  log('generalDebug_0003', `Updating the emulator from remote "${url}" ...`);
175
- await updateFromEmulatorWebsite(root, url, interactive);
177
+ await updateFromEmulatorWebsite(root, url, agent, interactive);
176
178
  }
177
179
 
178
180
  return await loadPiralInstance(root, details);
179
181
  } else if (url) {
180
182
  log('generalDebug_0003', `Piral instance not installed yet - trying from remote "${url}" ...`);
181
- const emulator = await scaffoldFromEmulatorWebsite(rootDir, url);
183
+ const emulator = await scaffoldFromEmulatorWebsite(rootDir, url, agent);
182
184
  return await loadPiralInstance(emulator.path, details);
183
185
  }
184
186
 
@@ -190,6 +192,7 @@ export async function findPiralInstances(
190
192
  piletPackage: PiletPackageData,
191
193
  piletDefinition: undefined | PiletDefinition,
192
194
  rootDir: string,
195
+ agent: Agent,
193
196
  interactive?: boolean,
194
197
  ) {
195
198
  if (proposedApps) {
@@ -208,7 +211,7 @@ export async function findPiralInstances(
208
211
  if (proposedApps.length > 0) {
209
212
  return Promise.all(
210
213
  proposedApps.map((proposedApp) =>
211
- findPiralInstance(proposedApp, rootDir, piletDefinition?.piralInstances?.[proposedApp], interactive),
214
+ findPiralInstance(proposedApp, rootDir, piletDefinition?.piralInstances?.[proposedApp], agent, interactive),
212
215
  ),
213
216
  );
214
217
  }
@@ -280,11 +283,7 @@ export async function getPiralPackage(app: string, data: PiralInstanceData, vers
280
283
  };
281
284
  }
282
285
 
283
- async function getAvailableFiles(
284
- root: string,
285
- name: string,
286
- dirName: string,
287
- ): Promise<Array<FileDescriptor>> {
286
+ async function getAvailableFiles(root: string, name: string, dirName: string): Promise<Array<FileDescriptor>> {
288
287
  const source = getPiralPath(root, name);
289
288
  const tgz = `${dirName}.tar`;
290
289
  log('generalDebug_0003', `Checking if "${tgz}" exists in "${source}" ...`);
@@ -780,13 +779,13 @@ export async function findPiletRoot(proposedRoot: string) {
780
779
  return dirname(packageJsonPath);
781
780
  }
782
781
 
783
- export async function retrievePiletData(target: string, app?: string, interactive?: boolean) {
782
+ export async function retrievePiletData(target: string, app?: string, agent?: Agent, interactive?: boolean) {
784
783
  const piletJsonPath = await findFile(target, piletJson);
785
784
  const proposedRoot = piletJsonPath ? dirname(piletJsonPath) : target;
786
785
  const root = await findPiletRoot(proposedRoot);
787
786
  const piletPackage = await readJson(root, packageJson);
788
787
  const piletDefinition: PiletDefinition = piletJsonPath && (await readJson(proposedRoot, piletJson));
789
- const appPackages = await findPiralInstances(app && [app], piletPackage, piletDefinition, root, interactive);
788
+ const appPackages = await findPiralInstances(app && [app], piletPackage, piletDefinition, root, agent, interactive);
790
789
  const apps: Array<AppDefinition> = [];
791
790
 
792
791
  for (const appPackage of appPackages) {
@@ -1,3 +1,4 @@
1
+ import { Agent } from 'https';
1
2
  import { basename, dirname, relative } from 'path';
2
3
  import { readBinary } from './io';
3
4
  import { publishNpmPackage } from './npm';
@@ -39,7 +40,7 @@ export async function publishWebsiteEmulator(
39
40
  files: Array<string>,
40
41
  interactive: boolean,
41
42
  headers?: Record<string, string>,
42
- ca?: Buffer,
43
+ agent?: Agent,
43
44
  ) {
44
45
  const data: FormDataObj = {
45
46
  version,
@@ -53,5 +54,5 @@ export async function publishWebsiteEmulator(
53
54
  data[relPath] = [content, fileName];
54
55
  }
55
56
 
56
- return await postForm(url, mode, apiKey, data, headers, ca, interactive);
57
+ return await postForm(url, mode, apiKey, data, headers, agent, interactive);
57
58
  }
@@ -1,10 +1,11 @@
1
+ import { Agent } from 'https';
1
2
  import { progress } from './log';
2
3
  import { packageJson, piletJson } from './constants';
3
4
  import { readJson, updateExistingJson, writeJson } from './io';
4
5
  import { scaffoldFromEmulatorWebsite } from './website';
5
6
  import { combinePackageRef, getPackageName, getPackageVersion } from './npm';
6
7
  import { dissectPackageName, installNpmPackage, isLinkedPackage } from './npm';
7
- import { NpmClientType, PackageType, PiralInstanceDetails } from '../types';
8
+ import { NpmClient, PackageType, PiralInstanceDetails } from '../types';
8
9
 
9
10
  async function updatePiletJson(target: string, appName: string, appDetails: PiralInstanceDetails) {
10
11
  const oldContent = await readJson(target, piletJson);
@@ -29,7 +30,7 @@ async function setupPiralInstance(
29
30
  hadVersion: boolean,
30
31
  rootDir: string,
31
32
  sourceVersion: string,
32
- npmClient: NpmClientType,
33
+ npmClient: NpmClient,
33
34
  ) {
34
35
  if (!isLinkedPackage(sourceName, type, hadVersion, rootDir)) {
35
36
  const packageRef = combinePackageRef(sourceName, sourceVersion, type);
@@ -54,13 +55,14 @@ export async function installPiralInstance(
54
55
  usedSource: string,
55
56
  baseDir: string,
56
57
  rootDir: string,
57
- npmClient: NpmClientType,
58
+ npmClient: NpmClient,
59
+ agent: Agent,
58
60
  selected?: boolean,
59
61
  ): Promise<string> {
60
62
  const [sourceName, sourceVersion, hadVersion, type] = await dissectPackageName(baseDir, usedSource);
61
63
 
62
64
  if (type === 'remote') {
63
- const emulator = await scaffoldFromEmulatorWebsite(rootDir, sourceName);
65
+ const emulator = await scaffoldFromEmulatorWebsite(rootDir, sourceName, agent);
64
66
  const packageName = emulator.name;
65
67
  await updatePiletJson(rootDir, packageName, {
66
68
  selected,
@@ -1,7 +1,7 @@
1
1
  import { Agent } from 'https';
2
2
  import { posix, relative, resolve } from 'path';
3
3
  import { createPiralStubIndexIfNotExists } from './template';
4
- import { getAuthorizationHeaders, getAxiosOptions, getCertificate, handleAxiosError } from './http';
4
+ import { getAuthorizationHeaders, getAxiosOptions, handleAxiosError } from './http';
5
5
  import { packageJson } from './constants';
6
6
  import { updateConfig } from './config';
7
7
  import { ForceOverwrite } from './enums';
@@ -11,7 +11,7 @@ import { progress, log } from './log';
11
11
  import { axios, isInteractive } from '../external';
12
12
  import { EmulatorWebsiteManifestFiles, EmulatorWebsiteManifest } from '../types';
13
13
 
14
- async function requestManifest(url: string, interactive: boolean, httpsAgent?: Agent) {
14
+ async function requestManifest(url: string, httpsAgent: Agent, interactive: boolean) {
15
15
  const opts = getAxiosOptions(url);
16
16
 
17
17
  try {
@@ -26,7 +26,7 @@ async function requestManifest(url: string, interactive: boolean, httpsAgent?: A
26
26
  value: headers.authorization,
27
27
  },
28
28
  });
29
- return await requestManifest(url, false, httpsAgent);
29
+ return await requestManifest(url, httpsAgent, false);
30
30
  });
31
31
  }
32
32
  }
@@ -92,6 +92,7 @@ async function createEmulatorFiles(
92
92
  peerDependencies: {},
93
93
  optionalDependencies: emulatorJson.dependencies.optional,
94
94
  devDependencies: emulatorJson.dependencies.included,
95
+ sharedDependencies: [Object.keys(emulatorJson.importmap.imports)],
95
96
  },
96
97
  true,
97
98
  );
@@ -105,13 +106,11 @@ async function createEmulatorFiles(
105
106
  await downloadEmulatorFiles(manifestUrl, targetDir, appDir, emulatorJson.files, httpsAgent);
106
107
  }
107
108
 
108
- export async function updateFromEmulatorWebsite(targetDir: string, manifestUrl: string, interactive: boolean) {
109
+ export async function updateFromEmulatorWebsite(targetDir: string, manifestUrl: string, httpsAgent: Agent, interactive: boolean) {
109
110
  progress(`Updating emulator from %s ...`, manifestUrl);
110
- const ca = await getCertificate();
111
- const httpsAgent = ca ? new Agent({ ca }) : undefined;
112
111
 
113
112
  try {
114
- const response = await requestManifest(manifestUrl, interactive, httpsAgent);
113
+ const response = await requestManifest(manifestUrl, httpsAgent, interactive);
115
114
  const nextEmulator: EmulatorWebsiteManifest = response.data;
116
115
  const currentEmulator = await readJson(targetDir, packageJson);
117
116
 
@@ -130,12 +129,10 @@ export async function updateFromEmulatorWebsite(targetDir: string, manifestUrl:
130
129
  }
131
130
  }
132
131
 
133
- export async function scaffoldFromEmulatorWebsite(rootDir: string, manifestUrl: string) {
132
+ export async function scaffoldFromEmulatorWebsite(rootDir: string, manifestUrl: string, httpsAgent: Agent) {
134
133
  progress(`Downloading emulator from %s ...`, manifestUrl);
135
- const ca = await getCertificate();
136
- const httpsAgent = ca ? new Agent({ ca }) : undefined;
137
134
  const interactive = isInteractive();
138
- const response = await requestManifest(manifestUrl, interactive, httpsAgent);
135
+ const response = await requestManifest(manifestUrl, httpsAgent, interactive);
139
136
  const emulatorJson: EmulatorWebsiteManifest = response.data;
140
137
  const targetDir = resolve(rootDir, 'node_modules', emulatorJson.name);
141
138
  const appDir = resolve(targetDir, 'app');
@@ -1,5 +1,6 @@
1
1
  import { dirname, resolve } from 'path';
2
2
  import { findFile } from '../common/io';
3
+ import type { NpmClientType, NpmDirectClientType, NpmWapperClientType } from '../types';
3
4
 
4
5
  import * as lerna from './lerna';
5
6
  import * as npm from './npm';
@@ -19,20 +20,26 @@ export const clients = {
19
20
  bun,
20
21
  };
21
22
 
22
- type ClientName = keyof typeof clients;
23
+ const directClients: Array<NpmDirectClientType> = ['npm', 'pnp', 'yarn', 'pnpm', 'bun'];
24
+ const wrapperClients: Array<NpmWapperClientType> = ['lerna', 'rush'];
23
25
 
24
- const directClients = ['npm', 'pnp', 'yarn', 'pnpm', 'bun'];
26
+ export function isWrapperClient(client: NpmClientType): client is NpmWapperClientType {
27
+ return wrapperClients.includes(client as any);
28
+ }
25
29
 
26
- export function isWrapperClient(client: ClientName) {
27
- return !directClients.includes(client);
30
+ export function isDirectClient(client: NpmClientType): client is NpmDirectClientType {
31
+ return directClients.includes(client as any);
28
32
  }
29
33
 
30
- export async function detectClients(root: string) {
34
+ async function detectClients<T extends NpmClientType>(
35
+ root: string,
36
+ clientNames: Array<T>,
37
+ ): Promise<Array<{ client: T; result: boolean }>> {
31
38
  const packageJson = await findFile(resolve(root, '..'), 'package.json');
32
39
  const stopDir = packageJson ? dirname(packageJson) : undefined;
33
40
 
34
41
  return await Promise.all(
35
- Object.keys(clients).map(async (client: ClientName) => {
42
+ clientNames.map(async (client) => {
36
43
  const result = await clients[client].detectClient(root, stopDir);
37
44
  return {
38
45
  client,
@@ -41,3 +48,11 @@ export async function detectClients(root: string) {
41
48
  }),
42
49
  );
43
50
  }
51
+
52
+ export function detectDirectClients(root: string) {
53
+ return detectClients<NpmDirectClientType>(root, directClients);
54
+ }
55
+
56
+ export function detectWrapperClients(root: string) {
57
+ return detectClients<NpmWapperClientType>(root, wrapperClients);
58
+ }
@@ -1,5 +1,11 @@
1
1
  import type { LogLevels } from './common';
2
- import type { ImportmapVersions, PiletSchemaVersion } from './public';
2
+ import type {
3
+ ImportmapVersions,
4
+ NpmClientType,
5
+ NpmDirectClientType,
6
+ NpmWapperClientType,
7
+ PiletSchemaVersion,
8
+ } from './public';
3
9
 
4
10
  export interface PiralInstanceDetails {
5
11
  selected?: boolean;
@@ -34,3 +40,21 @@ export interface FileInfo {
34
40
  * 2. The (short) error message
35
41
  */
36
42
  export type QuickMessage = [LogLevels, string, string];
43
+
44
+ /**
45
+ * Result of identifying an npm client in a project.
46
+ */
47
+ export interface NpmClient {
48
+ /**
49
+ * The proposed client - can be anything.
50
+ */
51
+ proposed?: NpmClientType;
52
+ /**
53
+ * The direct npm client.
54
+ */
55
+ direct: NpmDirectClientType;
56
+ /**
57
+ * The wrapper npm client, if any.
58
+ */
59
+ wrapper?: NpmWapperClientType;
60
+ }
@@ -261,7 +261,11 @@ export type PiletBuildType = 'default' | 'standalone' | 'manifest';
261
261
 
262
262
  export type PackageType = 'registry' | 'file' | 'git' | 'remote';
263
263
 
264
- export type NpmClientType = 'npm' | 'yarn' | 'pnp' | 'pnpm' | 'lerna' | 'rush' | 'bun';
264
+ export type NpmDirectClientType = 'npm' | 'yarn' | 'pnp' | 'pnpm' | 'bun';
265
+
266
+ export type NpmWapperClientType = 'lerna' | 'rush';
267
+
268
+ export type NpmClientType = NpmDirectClientType | NpmWapperClientType;
265
269
 
266
270
  export type Framework = 'piral' | 'piral-core' | 'piral-base';
267
271