@codejen/jen 1.0.0 → 1.1.0

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 (2) hide show
  1. package/dist/jen.js +66 -7
  2. package/package.json +1 -1
package/dist/jen.js CHANGED
@@ -9,7 +9,7 @@ import { spawnSync } from "node:child_process";
9
9
  import { existsSync as existsSync4, mkdtempSync, readFileSync as readFileSync2, readdirSync, rmSync } from "node:fs";
10
10
  import { createRequire as createRequire2 } from "node:module";
11
11
  import { tmpdir } from "node:os";
12
- import { delimiter, join as join3, resolve as resolve2 } from "node:path";
12
+ import { delimiter, dirname as dirname4, join as join3, resolve as resolve2, sep } from "node:path";
13
13
  import { pathToFileURL as pathToFileURL2 } from "node:url";
14
14
  import { parseArgs, styleText as styleText2 } from "node:util";
15
15
 
@@ -465,6 +465,7 @@ function dirSource(source, dir) {
465
465
  };
466
466
  });
467
467
  }
468
+ var FIRST_PARTY_SCOPE = "@codejen";
468
469
  var PACK_RE = /^(?:jen-pack-|@[^/]+\/pack-)(.+)$/;
469
470
  var packPrefix = (name) => PACK_RE.exec(name)?.[1] ?? name;
470
471
  function readPackageJson(dir) {
@@ -476,6 +477,28 @@ function readPackageJson(dir) {
476
477
  fail(`${file}: ${e.message}`);
477
478
  }
478
479
  }
480
+ function discoverGlobal(re) {
481
+ const names = [];
482
+ for (let dir = dirname4(import.meta.filename); dirname4(dir) !== dir; dir = dirname4(dir)) {
483
+ if (!dir.endsWith(`${sep}node_modules`) || dir.startsWith(ROOT + sep)) continue;
484
+ let children;
485
+ try {
486
+ children = readdirSync(dir);
487
+ } catch {
488
+ continue;
489
+ }
490
+ for (const child of children) {
491
+ if (child.startsWith("@")) {
492
+ const scoped = readdirSync(join3(dir, child)).map((n) => `${child}/${n}`);
493
+ names.push(...scoped);
494
+ } else {
495
+ names.push(child);
496
+ }
497
+ }
498
+ }
499
+ return names.filter((n) => re.test(n));
500
+ }
501
+ var defaultBases = () => [join3(ROOT, "package.json"), join3(USER_DIR, "package.json"), import.meta.filename];
479
502
  function discoverDeps(dir, re) {
480
503
  const pkg = readPackageJson(dir);
481
504
  const names = [
@@ -485,7 +508,7 @@ function discoverDeps(dir, re) {
485
508
  ];
486
509
  return names.filter((n) => re.test(n));
487
510
  }
488
- async function packSource(name, bases = [join3(ROOT, "package.json"), import.meta.filename]) {
511
+ async function packSource(name, bases = defaultBases()) {
489
512
  for (const base of bases) {
490
513
  let file;
491
514
  try {
@@ -507,7 +530,7 @@ async function packSource(name, bases = [join3(ROOT, "package.json"), import.met
507
530
  }
508
531
  var YEOMAN_RE = /^(?:generator-|@[^/]+\/generator-)(.+)$/;
509
532
  var yeomanShortName = (name) => YEOMAN_RE.exec(name)?.[1] ?? name;
510
- async function yeomanSource(name, bases = [join3(ROOT, "package.json"), import.meta.filename]) {
533
+ async function yeomanSource(name, bases = defaultBases()) {
511
534
  for (const base of bases) {
512
535
  let file;
513
536
  try {
@@ -575,8 +598,9 @@ async function fetchFrom(spec) {
575
598
  }
576
599
  async function collect() {
577
600
  const extra = (process.env.JEN_PATH ?? "").split(delimiter).filter(Boolean);
578
- const packs = [.../* @__PURE__ */ new Set([...discoverDeps(ROOT, PACK_RE), ...discoverDeps(USER_DIR, PACK_RE)])];
579
- const yeomanGenerators = [.../* @__PURE__ */ new Set([...discoverDeps(ROOT, YEOMAN_RE), ...discoverDeps(USER_DIR, YEOMAN_RE)])];
601
+ const discover = (re) => [.../* @__PURE__ */ new Set([...discoverDeps(ROOT, re), ...discoverDeps(USER_DIR, re), ...discoverGlobal(re)])];
602
+ const packs = discover(PACK_RE);
603
+ const yeomanGenerators = discover(YEOMAN_RE);
580
604
  const entries = [
581
605
  ...dirSource("project", PROJECT_JEN),
582
606
  ...dirSource("user", USER_DIR),
@@ -598,6 +622,35 @@ function find(entries, query) {
598
622
  (e) => e.name === name && (prefix === null || e.prefix === prefix || e.source === prefix || e.source.startsWith(`${prefix} `))
599
623
  );
600
624
  }
625
+ function unknownPackPrefix(entries, query) {
626
+ const colon = query.indexOf(":");
627
+ if (colon < 0) return null;
628
+ const prefix = query.slice(0, colon);
629
+ const known = entries.some((e) => e.prefix === prefix || e.source === prefix || e.source.startsWith(`${prefix} `));
630
+ return !known && /^[a-z0-9][a-z0-9-]*$/.test(prefix) ? prefix : null;
631
+ }
632
+ function notFound(entries, query) {
633
+ const prefix = unknownPackPrefix(entries, query);
634
+ const lines = [`Generator "${query}" not found \u2013 jen --list shows all.`];
635
+ if (prefix) lines.push(`If "${prefix}" is a pack you haven't installed, try: jen --from ${FIRST_PARTY_SCOPE}/pack-${prefix} ${query}`);
636
+ return fail(lines.join("\n"));
637
+ }
638
+ async function fetchFallback(entries, query) {
639
+ const prefix = unknownPackPrefix(entries, query);
640
+ if (!prefix || process.env.JEN_NO_FETCH) return void 0;
641
+ let fetched;
642
+ try {
643
+ fetched = await fetchFrom(`${FIRST_PARTY_SCOPE}/pack-${prefix}`);
644
+ } catch {
645
+ return void 0;
646
+ }
647
+ const entry = find(fetched.entries, query);
648
+ if (!entry) {
649
+ fetched.cleanup();
650
+ return void 0;
651
+ }
652
+ return { entry, cleanup: fetched.cleanup };
653
+ }
601
654
  async function list(entries) {
602
655
  const seen = /* @__PURE__ */ new Set();
603
656
  for (const e of entries) {
@@ -658,7 +711,7 @@ async function main() {
658
711
  const { values, positionals } = parseArgs({ allowPositionals: true, strict: false, options: FLAGS });
659
712
  if (values.help) return void console.log(HELP);
660
713
  if (values.where) setRoot(resolve2(process.cwd(), String(values.where)));
661
- const fetched = values.from ? await fetchFrom(String(values.from)) : void 0;
714
+ let fetched = values.from ? await fetchFrom(String(values.from)) : void 0;
662
715
  try {
663
716
  const entries = fetched ? fetched.entries : await collect();
664
717
  if (values.list) return void await list(entries);
@@ -668,7 +721,13 @@ async function main() {
668
721
  process.exitCode = 1;
669
722
  return;
670
723
  }
671
- const entry = find(entries, query) ?? fail(`Generator "${query}" not found \u2013 jen --list shows all.`);
724
+ let entry = find(entries, query);
725
+ if (!entry) {
726
+ const fallback = fetched ? void 0 : await fetchFallback(entries, query);
727
+ if (!fallback) notFound(entries, query);
728
+ entry = fallback.entry;
729
+ fetched = { entries: [], cleanup: fallback.cleanup };
730
+ }
672
731
  const gen = await entry.load();
673
732
  console.log(dim(`${qualified(entry)} (${entry.source})${gen.description ? ` \u2013 ${gen.description}` : ""}`));
674
733
  const given = Object.fromEntries(Object.entries(values).filter(([k]) => !(k in FLAGS)));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codejen/jen",
3
- "version": "1.0.0",
3
+ "version": "1.1.0",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "bin": {