@ahmednawaz/crank 0.2.2 → 0.2.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.
- package/bin/crank.js +5 -1
- package/lib/wire-react.js +136 -25
- package/package.json +1 -1
package/bin/crank.js
CHANGED
|
@@ -635,7 +635,11 @@ async function main() {
|
|
|
635
635
|
console.log(`[Crank] Installed package (${result.installCommand})`);
|
|
636
636
|
} else if (result.installError) {
|
|
637
637
|
console.warn(`[Crank] Package install warning: ${result.installError}`);
|
|
638
|
-
|
|
638
|
+
if (result.installHint) {
|
|
639
|
+
console.warn(`[Crank] Run manually:\n ${result.installHint}`);
|
|
640
|
+
} else {
|
|
641
|
+
console.warn('[Crank] Try: pnpm add -D @ahmednawaz/crank');
|
|
642
|
+
}
|
|
639
643
|
}
|
|
640
644
|
if (result.reactWire?.wired) {
|
|
641
645
|
console.log(`[Crank] Patched ${result.reactWire.file}`);
|
package/lib/wire-react.js
CHANGED
|
@@ -226,44 +226,153 @@ function wireReactEntry(projectRoot) {
|
|
|
226
226
|
return { wired: true, file: entryPath };
|
|
227
227
|
}
|
|
228
228
|
|
|
229
|
-
function
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
229
|
+
function findPnpmWorkspaceRoot(startDir) {
|
|
230
|
+
let dir = path.resolve(startDir);
|
|
231
|
+
for (let i = 0; i < 12; i++) {
|
|
232
|
+
if (
|
|
233
|
+
exists(path.join(dir, 'pnpm-workspace.yaml')) ||
|
|
234
|
+
exists(path.join(dir, 'pnpm-workspace.yml'))
|
|
235
|
+
) {
|
|
236
|
+
return dir;
|
|
237
|
+
}
|
|
238
|
+
// lockfile alone can mean pnpm without workspaces
|
|
239
|
+
if (exists(path.join(dir, 'pnpm-lock.yaml')) && i === 0) {
|
|
240
|
+
return dir;
|
|
241
|
+
}
|
|
242
|
+
const parent = path.dirname(dir);
|
|
243
|
+
if (parent === dir) break;
|
|
244
|
+
dir = parent;
|
|
235
245
|
}
|
|
236
|
-
if
|
|
237
|
-
|
|
246
|
+
// Prefer ancestor with lockfile if no workspace file
|
|
247
|
+
dir = path.resolve(startDir);
|
|
248
|
+
for (let i = 0; i < 12; i++) {
|
|
249
|
+
if (exists(path.join(dir, 'pnpm-lock.yaml'))) {
|
|
250
|
+
return dir;
|
|
251
|
+
}
|
|
252
|
+
const parent = path.dirname(dir);
|
|
253
|
+
if (parent === dir) break;
|
|
254
|
+
dir = parent;
|
|
238
255
|
}
|
|
239
|
-
return
|
|
256
|
+
return null;
|
|
240
257
|
}
|
|
241
258
|
|
|
242
|
-
function
|
|
243
|
-
const { execFileSync } = require('child_process');
|
|
244
|
-
const { cmd, args } = detectInstallCommand(projectRoot);
|
|
245
|
-
const result = { installed: false, installCommand: `${cmd} ${args.join(' ')}` };
|
|
259
|
+
function readPackageName(projectRoot) {
|
|
246
260
|
try {
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
261
|
+
const pkg = JSON.parse(
|
|
262
|
+
fs.readFileSync(path.join(projectRoot, 'package.json'), 'utf8')
|
|
263
|
+
);
|
|
264
|
+
return pkg.name || null;
|
|
265
|
+
} catch {
|
|
266
|
+
return null;
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
/**
|
|
271
|
+
* Build install attempts for this project (pnpm monorepo-aware).
|
|
272
|
+
* Never uses npm as a fallback inside a pnpm workspace.
|
|
273
|
+
*/
|
|
274
|
+
function detectInstallAttempts(projectRoot) {
|
|
275
|
+
const root = path.resolve(projectRoot);
|
|
276
|
+
const pnpmRoot = findPnpmWorkspaceRoot(root);
|
|
277
|
+
const attempts = [];
|
|
278
|
+
|
|
279
|
+
if (pnpmRoot) {
|
|
280
|
+
const isWorkspace = exists(path.join(pnpmRoot, 'pnpm-workspace.yaml')) ||
|
|
281
|
+
exists(path.join(pnpmRoot, 'pnpm-workspace.yml'));
|
|
282
|
+
const pkgName = readPackageName(root);
|
|
283
|
+
const relFilter = path.relative(pnpmRoot, root).replace(/\\/g, '/') || '.';
|
|
284
|
+
|
|
285
|
+
// 1) From the package directory (works when cwd is the workspace package)
|
|
286
|
+
attempts.push({
|
|
287
|
+
cmd: 'pnpm',
|
|
288
|
+
args: ['add', '-D', '@ahmednawaz/crank'],
|
|
289
|
+
cwd: root,
|
|
290
|
+
label: `pnpm add -D @ahmednawaz/crank (in ${relFilter})`
|
|
291
|
+
});
|
|
292
|
+
|
|
293
|
+
if (isWorkspace && pnpmRoot !== root) {
|
|
294
|
+
// 2) From monorepo root with --filter by package name
|
|
295
|
+
if (pkgName) {
|
|
296
|
+
attempts.push({
|
|
297
|
+
cmd: 'pnpm',
|
|
298
|
+
args: ['add', '-D', '@ahmednawaz/crank', '--filter', pkgName],
|
|
299
|
+
cwd: pnpmRoot,
|
|
300
|
+
label: `pnpm add -D @ahmednawaz/crank --filter ${pkgName}`
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
// 3) From monorepo root with --filter by path
|
|
304
|
+
attempts.push({
|
|
305
|
+
cmd: 'pnpm',
|
|
306
|
+
args: ['add', '-D', '@ahmednawaz/crank', '--filter', `./${relFilter}`],
|
|
307
|
+
cwd: pnpmRoot,
|
|
308
|
+
label: `pnpm add -D @ahmednawaz/crank --filter ./${relFilter}`
|
|
309
|
+
});
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
return attempts;
|
|
252
313
|
}
|
|
253
|
-
|
|
314
|
+
|
|
315
|
+
if (exists(path.join(root, 'yarn.lock'))) {
|
|
316
|
+
return [
|
|
317
|
+
{
|
|
318
|
+
cmd: 'yarn',
|
|
319
|
+
args: ['add', '-D', '@ahmednawaz/crank'],
|
|
320
|
+
cwd: root,
|
|
321
|
+
label: 'yarn add -D @ahmednawaz/crank'
|
|
322
|
+
}
|
|
323
|
+
];
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
return [
|
|
327
|
+
{
|
|
328
|
+
cmd: 'npm',
|
|
329
|
+
args: ['install', '-D', '@ahmednawaz/crank'],
|
|
330
|
+
cwd: root,
|
|
331
|
+
label: 'npm install -D @ahmednawaz/crank'
|
|
332
|
+
}
|
|
333
|
+
];
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
function detectInstallCommand(projectRoot) {
|
|
337
|
+
const attempts = detectInstallAttempts(projectRoot);
|
|
338
|
+
const first = attempts[0];
|
|
339
|
+
return { cmd: first.cmd, args: first.args, cwd: first.cwd };
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
function installCrankPackage(projectRoot) {
|
|
343
|
+
const { execFileSync } = require('child_process');
|
|
344
|
+
const attempts = detectInstallAttempts(projectRoot);
|
|
345
|
+
const result = {
|
|
346
|
+
installed: false,
|
|
347
|
+
installCommand: attempts[0]?.label || '',
|
|
348
|
+
installAttempts: []
|
|
349
|
+
};
|
|
350
|
+
|
|
351
|
+
for (const attempt of attempts) {
|
|
352
|
+
result.installAttempts.push(attempt.label);
|
|
254
353
|
try {
|
|
255
|
-
execFileSync(
|
|
256
|
-
cwd:
|
|
354
|
+
execFileSync(attempt.cmd, attempt.args, {
|
|
355
|
+
cwd: attempt.cwd,
|
|
257
356
|
stdio: 'inherit',
|
|
258
357
|
env: process.env
|
|
259
358
|
});
|
|
260
359
|
result.installed = true;
|
|
261
|
-
result.installCommand =
|
|
360
|
+
result.installCommand = attempt.label;
|
|
262
361
|
delete result.installError;
|
|
263
|
-
|
|
264
|
-
|
|
362
|
+
return result;
|
|
363
|
+
} catch (err) {
|
|
364
|
+
result.installError = err.message;
|
|
265
365
|
}
|
|
266
366
|
}
|
|
367
|
+
|
|
368
|
+
// Hint for humans / agents — do not npm-install into a pnpm monorepo
|
|
369
|
+
const pkgName = readPackageName(projectRoot);
|
|
370
|
+
if (findPnpmWorkspaceRoot(projectRoot)) {
|
|
371
|
+
result.installHint = pkgName
|
|
372
|
+
? `pnpm add -D @ahmednawaz/crank --filter ${pkgName}`
|
|
373
|
+
: `pnpm add -D @ahmednawaz/crank --filter ${path.basename(projectRoot)}`;
|
|
374
|
+
}
|
|
375
|
+
|
|
267
376
|
return result;
|
|
268
377
|
}
|
|
269
378
|
|
|
@@ -293,5 +402,7 @@ module.exports = {
|
|
|
293
402
|
installCrankPackage,
|
|
294
403
|
injectCrank,
|
|
295
404
|
findEntry,
|
|
296
|
-
detectInstallCommand
|
|
405
|
+
detectInstallCommand,
|
|
406
|
+
detectInstallAttempts,
|
|
407
|
+
findPnpmWorkspaceRoot
|
|
297
408
|
};
|