modern-cmdk 1.2.3 → 1.4.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.
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import { createRequire } from "node:module";
3
3
  import fsPromises, { readFile, writeFile } from "node:fs/promises";
4
- import path, { resolve } from "node:path";
4
+ import path, { relative } from "node:path";
5
+ import { parseArgs, promisify, styleText } from "node:util";
5
6
  import process$1 from "node:process";
6
7
  import fs from "node:fs";
7
8
  import "node:stream";
8
9
  import "node:events";
9
10
  import "node:stream/promises";
10
- import { promisify } from "node:util";
11
11
  import { execFile } from "node:child_process";
12
12
  import { fileURLToPath } from "node:url";
13
13
  import os from "node:os";
@@ -7427,7 +7427,7 @@ const globby = normalizeArguments(async (patterns, options) => {
7427
7427
  return unionFastGlobResultsAsync(results, filter);
7428
7428
  });
7429
7429
  const { convertPathToPattern } = import_out.default;
7430
- // ../../node_modules/.pnpm/jscodeshift@17.4.0/node_modules/jscodeshift/src/utils/intersection.js
7430
+ // ../../node_modules/.pnpm/jscodeshift@17.4.0_supports-color@7.2.0/node_modules/jscodeshift/src/utils/intersection.js
7431
7431
  var require_intersection = /* @__PURE__ */ __commonJSMin(((exports, module) => {
7432
7432
  /**
7433
7433
  * Copyright (c) Facebook, Inc. and its affiliates.
@@ -21523,7 +21523,7 @@ var require_main = /* @__PURE__ */ __commonJSMin(((exports) => {
21523
21523
  });
21524
21524
  }
21525
21525
  }));
21526
- // ../../node_modules/.pnpm/jscodeshift@17.4.0/node_modules/jscodeshift/src/utils/union.js
21526
+ // ../../node_modules/.pnpm/jscodeshift@17.4.0_supports-color@7.2.0/node_modules/jscodeshift/src/utils/union.js
21527
21527
  var require_union = /* @__PURE__ */ __commonJSMin(((exports, module) => {
21528
21528
  /**
21529
21529
  * Copyright (c) Facebook, Inc. and its affiliates.
@@ -21541,7 +21541,7 @@ var require_union = /* @__PURE__ */ __commonJSMin(((exports, module) => {
21541
21541
  return Array.from(result);
21542
21542
  };
21543
21543
  }));
21544
- // ../../node_modules/.pnpm/jscodeshift@17.4.0/node_modules/jscodeshift/src/Collection.js
21544
+ // ../../node_modules/.pnpm/jscodeshift@17.4.0_supports-color@7.2.0/node_modules/jscodeshift/src/Collection.js
21545
21545
  /**
21546
21546
  * Copyright (c) Facebook, Inc. and its affiliates.
21547
21547
  *
@@ -21874,7 +21874,7 @@ var require_Collection = /* @__PURE__ */ __commonJSMin(((exports) => {
21874
21874
  exports.hasConflictingRegistration = hasConflictingRegistration;
21875
21875
  exports.setDefaultCollectionType = setDefaultCollectionType;
21876
21876
  }));
21877
- // ../../node_modules/.pnpm/jscodeshift@17.4.0/node_modules/jscodeshift/src/matchNode.js
21877
+ // ../../node_modules/.pnpm/jscodeshift@17.4.0_supports-color@7.2.0/node_modules/jscodeshift/src/matchNode.js
21878
21878
  /**
21879
21879
  * Copyright (c) Facebook, Inc. and its affiliates.
21880
21880
  *
@@ -21902,7 +21902,7 @@ var require_matchNode = /* @__PURE__ */ __commonJSMin(((exports, module) => {
21902
21902
  }
21903
21903
  module.exports = matchNode;
21904
21904
  }));
21905
- // ../../node_modules/.pnpm/jscodeshift@17.4.0/node_modules/jscodeshift/src/utils/once.js
21905
+ // ../../node_modules/.pnpm/jscodeshift@17.4.0_supports-color@7.2.0/node_modules/jscodeshift/src/utils/once.js
21906
21906
  var require_once = /* @__PURE__ */ __commonJSMin(((exports, module) => {
21907
21907
  /**
21908
21908
  * Copyright (c) Facebook, Inc. and its affiliates.
@@ -21923,7 +21923,7 @@ var require_once = /* @__PURE__ */ __commonJSMin(((exports, module) => {
21923
21923
  };
21924
21924
  };
21925
21925
  }));
21926
- // ../../node_modules/.pnpm/jscodeshift@17.4.0/node_modules/jscodeshift/src/collections/Node.js
21926
+ // ../../node_modules/.pnpm/jscodeshift@17.4.0_supports-color@7.2.0/node_modules/jscodeshift/src/collections/Node.js
21927
21927
  /**
21928
21928
  * Copyright (c) Facebook, Inc. and its affiliates.
21929
21929
  *
@@ -22071,7 +22071,7 @@ var require_Node = /* @__PURE__ */ __commonJSMin(((exports) => {
22071
22071
  }
22072
22072
  exports.register = once(register);
22073
22073
  }));
22074
- // ../../node_modules/.pnpm/jscodeshift@17.4.0/node_modules/jscodeshift/src/collections/VariableDeclarator.js
22074
+ // ../../node_modules/.pnpm/jscodeshift@17.4.0_supports-color@7.2.0/node_modules/jscodeshift/src/collections/VariableDeclarator.js
22075
22075
  /**
22076
22076
  * Copyright (c) Facebook, Inc. and its affiliates.
22077
22077
  *
@@ -22167,7 +22167,7 @@ renameTo: function(newName) {
22167
22167
  exports.register = once(register);
22168
22168
  exports.filters = filterMethods;
22169
22169
  }));
22170
- // ../../node_modules/.pnpm/jscodeshift@17.4.0/node_modules/jscodeshift/src/collections/JSXElement.js
22170
+ // ../../node_modules/.pnpm/jscodeshift@17.4.0_supports-color@7.2.0/node_modules/jscodeshift/src/collections/JSXElement.js
22171
22171
  /**
22172
22172
  * Copyright (c) Facebook, Inc. and its affiliates.
22173
22173
  *
@@ -22324,7 +22324,7 @@ getRootName: function(path) {
22324
22324
  exports.filters = filterMethods;
22325
22325
  exports.mappings = mappingMethods;
22326
22326
  }));
22327
- // ../../node_modules/.pnpm/jscodeshift@17.4.0/node_modules/jscodeshift/src/collections/ImportDeclaration.js
22327
+ // ../../node_modules/.pnpm/jscodeshift@17.4.0_supports-color@7.2.0/node_modules/jscodeshift/src/collections/ImportDeclaration.js
22328
22328
  /**
22329
22329
  * Copyright (c) Facebook, Inc. and its affiliates.
22330
22330
  *
@@ -22395,7 +22395,7 @@ var require_ImportDeclaration = /* @__PURE__ */ __commonJSMin(((exports) => {
22395
22395
  }
22396
22396
  exports.register = once(register);
22397
22397
  }));
22398
- // ../../node_modules/.pnpm/jscodeshift@17.4.0/node_modules/jscodeshift/src/collections/index.js
22398
+ // ../../node_modules/.pnpm/jscodeshift@17.4.0_supports-color@7.2.0/node_modules/jscodeshift/src/collections/index.js
22399
22399
  var require_collections = /* @__PURE__ */ __commonJSMin(((exports, module) => {
22400
22400
  /**
22401
22401
  * Copyright (c) Facebook, Inc. and its affiliates.
@@ -35145,7 +35145,7 @@ var require_lib = /* @__PURE__ */ __commonJSMin(((exports) => {
35145
35145
  exports.parseExpression = parseExpression;
35146
35146
  exports.tokTypes = tokTypes;
35147
35147
  }));
35148
- // ../../node_modules/.pnpm/jscodeshift@17.4.0/node_modules/jscodeshift/parser/babylon.js
35148
+ // ../../node_modules/.pnpm/jscodeshift@17.4.0_supports-color@7.2.0/node_modules/jscodeshift/parser/babylon.js
35149
35149
  /**
35150
35150
  * Copyright (c) Facebook, Inc. and its affiliates.
35151
35151
  *
@@ -43182,7 +43182,7 @@ var require_dist = /* @__PURE__ */ __commonJSMin(((exports) => {
43182
43182
  stripFlowTypes: StripFlowTypes.transformProgram
43183
43183
  };
43184
43184
  }));
43185
- // ../../node_modules/.pnpm/jscodeshift@17.4.0/node_modules/jscodeshift/parser/flow.js
43185
+ // ../../node_modules/.pnpm/jscodeshift@17.4.0_supports-color@7.2.0/node_modules/jscodeshift/parser/flow.js
43186
43186
  /**
43187
43187
  * Copyright (c) Facebook, Inc. and its affiliates.
43188
43188
  *
@@ -43211,7 +43211,7 @@ var require_flow = /* @__PURE__ */ __commonJSMin(((exports, module) => {
43211
43211
  } };
43212
43212
  };
43213
43213
  }));
43214
- // ../../node_modules/.pnpm/jscodeshift@17.4.0/node_modules/jscodeshift/parser/tsOptions.js
43214
+ // ../../node_modules/.pnpm/jscodeshift@17.4.0_supports-color@7.2.0/node_modules/jscodeshift/parser/tsOptions.js
43215
43215
  /**
43216
43216
  * Copyright (c) Facebook, Inc. and its affiliates.
43217
43217
  *
@@ -43256,7 +43256,7 @@ var require_tsOptions = /* @__PURE__ */ __commonJSMin(((exports, module) => {
43256
43256
  ]
43257
43257
  };
43258
43258
  }));
43259
- // ../../node_modules/.pnpm/jscodeshift@17.4.0/node_modules/jscodeshift/parser/ts.js
43259
+ // ../../node_modules/.pnpm/jscodeshift@17.4.0_supports-color@7.2.0/node_modules/jscodeshift/parser/ts.js
43260
43260
  /**
43261
43261
  * Copyright (c) Facebook, Inc. and its affiliates.
43262
43262
  *
@@ -43276,7 +43276,7 @@ var require_ts = /* @__PURE__ */ __commonJSMin(((exports, module) => {
43276
43276
  } };
43277
43277
  };
43278
43278
  }));
43279
- // ../../node_modules/.pnpm/jscodeshift@17.4.0/node_modules/jscodeshift/parser/tsx.js
43279
+ // ../../node_modules/.pnpm/jscodeshift@17.4.0_supports-color@7.2.0/node_modules/jscodeshift/parser/tsx.js
43280
43280
  /**
43281
43281
  * Copyright (c) Facebook, Inc. and its affiliates.
43282
43282
  *
@@ -43298,7 +43298,7 @@ var require_tsx = /* @__PURE__ */ __commonJSMin(((exports, module) => {
43298
43298
  } };
43299
43299
  };
43300
43300
  }));
43301
- // ../../node_modules/.pnpm/jscodeshift@17.4.0/node_modules/jscodeshift/parser/babel5Compat.js
43301
+ // ../../node_modules/.pnpm/jscodeshift@17.4.0_supports-color@7.2.0/node_modules/jscodeshift/parser/babel5Compat.js
43302
43302
  /**
43303
43303
  * Copyright (c) Facebook, Inc. and its affiliates.
43304
43304
  *
@@ -43341,7 +43341,7 @@ var require_babel5Compat = /* @__PURE__ */ __commonJSMin(((exports, module) => {
43341
43341
  } };
43342
43342
  };
43343
43343
  }));
43344
- // ../../node_modules/.pnpm/jscodeshift@17.4.0/node_modules/jscodeshift/src/getParser.js
43344
+ // ../../node_modules/.pnpm/jscodeshift@17.4.0_supports-color@7.2.0/node_modules/jscodeshift/src/getParser.js
43345
43345
  /**
43346
43346
  * Copyright (c) Facebook, Inc. and its affiliates.
43347
43347
  *
@@ -43359,7 +43359,7 @@ var require_getParser = /* @__PURE__ */ __commonJSMin(((exports, module) => {
43359
43359
  }
43360
43360
  };
43361
43361
  }));
43362
- // ../../node_modules/.pnpm/jscodeshift@17.4.0/node_modules/jscodeshift/src/template.js
43362
+ // ../../node_modules/.pnpm/jscodeshift@17.4.0_supports-color@7.2.0/node_modules/jscodeshift/src/template.js
43363
43363
  /**
43364
43364
  * Copyright (c) Facebook, Inc. and its affiliates.
43365
43365
  *
@@ -43450,7 +43450,7 @@ var require_template = /* @__PURE__ */ __commonJSMin(((exports, module) => {
43450
43450
  };
43451
43451
  };
43452
43452
  }));
43453
- // ../../node_modules/.pnpm/jscodeshift@17.4.0/node_modules/jscodeshift/src/core.js
43453
+ // ../../node_modules/.pnpm/jscodeshift@17.4.0_supports-color@7.2.0/node_modules/jscodeshift/src/core.js
43454
43454
  /**
43455
43455
  * Copyright (c) Facebook, Inc. and its affiliates.
43456
43456
  *
@@ -43584,7 +43584,7 @@ var require_core = /* @__PURE__ */ __commonJSMin(((exports, module) => {
43584
43584
  }
43585
43585
  module.exports = enrichCore(core, getParser());
43586
43586
  }));
43587
- // src/core/utils/group-by.ts
43587
+ // src/codemod/cli.ts
43588
43588
  var import_jscodeshift = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
43589
43589
  /**
43590
43590
  * Copyright (c) Facebook, Inc. and its affiliates.
@@ -43594,21 +43594,6 @@ var import_jscodeshift = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(
43594
43594
  */
43595
43595
  module.exports = require_core();
43596
43596
  })))(), 1);
43597
- /**
43598
- * Groups items from an iterable into a plain object keyed by the string result of `keyFn`.
43599
- * Cross-browser replacement for `Object.groupBy()`.
43600
- */
43601
- function objectGroupBy(items, keyFn) {
43602
- const result = Object.create(null);
43603
- for (const item of items) {
43604
- const key = keyFn(item);
43605
- const existing = result[key];
43606
- if (existing) existing.push(item);
43607
- else result[key] = [item];
43608
- }
43609
- return result;
43610
- }
43611
- // src/codemod/cli.ts
43612
43597
  const AVAILABLE_TRANSFORMS = /* @__PURE__ */ new Map([
43613
43598
  ["import-rewrite", "Rewrites cmdk imports to modern-cmdk/react"],
43614
43599
  ["data-attrs", "Converts [cmdk-*] selectors to [data-command-*]"],
@@ -43619,102 +43604,202 @@ const AVAILABLE_TRANSFORMS = /* @__PURE__ */ new Map([
43619
43604
  * Dynamically import a transform module by name and return its default export.
43620
43605
  */
43621
43606
  async function loadTransform(name) {
43622
- return (await import(`./transforms/${name}.mjs`)).default;
43607
+ return (await import(
43608
+ /* @vite-ignore */
43609
+ `./transforms/${name}.mjs`
43610
+ )).default;
43623
43611
  }
43624
- function printUsage() {
43625
- AVAILABLE_TRANSFORMS.entries().forEach(([_name, _description]) => {});
43612
+ function usageText(stream) {
43613
+ const bold = (s) => styleText("bold", s, { stream });
43614
+ const opt = (s) => styleText("cyan", s.padEnd(17), { stream });
43615
+ return [
43616
+ `${bold("Usage:")} modern-cmdk <transform> <glob> [options]`,
43617
+ "",
43618
+ bold("Transforms:"),
43619
+ ...AVAILABLE_TRANSFORMS.entries().map(([name, description]) => ` ${opt(name)}${description}`).toArray(),
43620
+ "",
43621
+ bold("Options:"),
43622
+ ` ${opt("--dry-run")}List the files that would change; write nothing`,
43623
+ ` ${opt("--strict")}Exit 2 on usage errors (incl. unknown options), 1 on file errors`,
43624
+ ` ${opt("--concurrency=N")}Files processed at once (default 8)`,
43625
+ ` ${opt("-h, --help")}Show this help`,
43626
+ "",
43627
+ "Node >= 26.4.0 (the floor modern-cmdk's toolchain and create-modern-cmdk declare; modern-cmdk itself declares no engines)",
43628
+ ""
43629
+ ].join("\n");
43626
43630
  }
43627
- function parseArgs(argv) {
43628
- const args = argv.slice(2);
43629
- const flags = args.values().filter((a) => a.startsWith("--")).toArray();
43630
- const positional = args.values().filter((a) => !a.startsWith("--")).toArray();
43631
- if (positional.length < 2) return null;
43632
- const transformName = positional[0];
43633
- const fileGlob = positional[1];
43634
- const dryRun = flags.some((f) => f === "--dry-run");
43635
- const concurrencyFlag = flags.values().find((f) => f.startsWith("--concurrency="));
43631
+ const OPTIONS = {
43632
+ help: {
43633
+ type: "boolean",
43634
+ short: "h"
43635
+ },
43636
+ strict: { type: "boolean" },
43637
+ "dry-run": { type: "boolean" },
43638
+ concurrency: { type: "string" }
43639
+ };
43640
+ function parse(argv) {
43641
+ let values;
43642
+ let positionals;
43643
+ let ignored = [];
43644
+ try {
43645
+ ({values, positionals} = parseCli(argv));
43646
+ } catch (err) {
43647
+ const strictArg = argv.includes("--strict");
43648
+ if (err.code !== "ERR_PARSE_ARGS_UNKNOWN_OPTION") return {
43649
+ kind: "usage-error",
43650
+ message: err instanceof Error ? err.message : String(err),
43651
+ strict: strictArg
43652
+ };
43653
+ const loose = parseArgs({
43654
+ args: [...argv],
43655
+ options: OPTIONS,
43656
+ allowPositionals: true,
43657
+ strict: false,
43658
+ tokens: true
43659
+ });
43660
+ ignored = loose.tokens.filter((t) => t.kind === "option" && !Object.hasOwn(OPTIONS, t.name)).map((t) => t.rawName);
43661
+ const badValue = loose.tokens.find((t) => t.kind === "option" && Object.hasOwn(OPTIONS, t.name) && (OPTIONS[t.name].type === "boolean" ? t.value !== void 0 : t.value === void 0 || !t.inlineValue && t.value.length > 1 && t.value.startsWith("-")));
43662
+ const badMessage = badValue?.kind === "option" ? badValue.value === void 0 ? `Option '${badValue.rawName} <value>' argument missing` : OPTIONS[badValue.name].type === "boolean" ? `Option '${badValue.rawName}' does not take an argument` : `Option '${badValue.rawName}' argument is ambiguous.\nDid you forget to specify the option argument for '${badValue.rawName}'?\nTo specify an option argument starting with a dash use '${badValue.rawName}=-XYZ'.` : void 0;
43663
+ if (badMessage !== void 0) return {
43664
+ kind: "usage-error",
43665
+ message: badMessage,
43666
+ strict: strictArg
43667
+ };
43668
+ if (strictArg || loose.values.help === true || loose.positionals.length < 2) return {
43669
+ kind: "usage-error",
43670
+ message: `unknown option ${ignored[0]}`,
43671
+ strict: strictArg
43672
+ };
43673
+ values = loose.values;
43674
+ positionals = loose.positionals;
43675
+ }
43676
+ const strict = values.strict === true;
43677
+ if (values.help) return { kind: "help" };
43678
+ if (positionals.length < 2) return {
43679
+ kind: "usage-error",
43680
+ message: void 0,
43681
+ strict
43682
+ };
43683
+ let concurrency = 8;
43684
+ if (values.concurrency !== void 0) {
43685
+ if (typeof values.concurrency !== "string" || !/^[1-9]\d*$/.test(values.concurrency)) return {
43686
+ kind: "usage-error",
43687
+ message: `--concurrency must be a positive integer, got "${String(values.concurrency)}"`,
43688
+ strict
43689
+ };
43690
+ concurrency = Number.parseInt(values.concurrency, 10);
43691
+ }
43636
43692
  return {
43637
- transformName,
43638
- fileGlob,
43639
- dryRun,
43640
- concurrency: concurrencyFlag ? Number.parseInt(concurrencyFlag.split("=")[1], 10) : 8
43693
+ kind: "run",
43694
+ transformName: positionals[0],
43695
+ fileGlob: positionals[1],
43696
+ dryRun: values["dry-run"] === true,
43697
+ strict,
43698
+ concurrency,
43699
+ ignored
43641
43700
  };
43642
43701
  }
43702
+ function parseCli(argv) {
43703
+ return parseArgs({
43704
+ args: [...argv],
43705
+ options: OPTIONS,
43706
+ allowPositionals: true,
43707
+ strict: true
43708
+ });
43709
+ }
43643
43710
  async function* chunked(items, size) {
43644
43711
  for (let i = 0; i < items.length; i += size) yield items.slice(i, i + size);
43645
43712
  }
43646
43713
  async function processFile(filePath, transformFn, apiForParser, dryRun) {
43647
- const source = await readFile(filePath, "utf-8");
43648
- const parser = filePath.endsWith(".tsx") || filePath.endsWith(".jsx") ? "tsx" : "ts";
43649
- const result = transformFn({
43650
- path: filePath,
43651
- source
43652
- }, apiForParser(parser));
43653
- if (result !== source) {
43654
- if (!dryRun) await writeFile(filePath, result, "utf-8");
43714
+ try {
43715
+ const source = await readFile(filePath, "utf-8");
43716
+ const parser = filePath.endsWith(".tsx") || filePath.endsWith(".jsx") ? "tsx" : "ts";
43717
+ const result = transformFn({
43718
+ path: filePath,
43719
+ source
43720
+ }, apiForParser(parser));
43721
+ if (result !== source) {
43722
+ if (!dryRun) await writeFile(filePath, result, "utf-8");
43723
+ return {
43724
+ filePath,
43725
+ changed: true
43726
+ };
43727
+ }
43728
+ return {
43729
+ filePath,
43730
+ changed: false
43731
+ };
43732
+ } catch (err) {
43655
43733
  return {
43656
43734
  filePath,
43657
- changed: true
43735
+ changed: false,
43736
+ error: err instanceof Error ? err : new Error(String(err))
43658
43737
  };
43659
43738
  }
43660
- return {
43661
- filePath,
43662
- changed: false
43663
- };
43664
43739
  }
43665
- async function main() {
43666
- const cliArgs = parseArgs(process.argv);
43667
- if (!cliArgs) {
43668
- printUsage();
43669
- process.exit(0);
43670
- }
43671
- const { transformName, fileGlob, dryRun, concurrency } = cliArgs;
43672
- if (!AVAILABLE_TRANSFORMS.has(transformName)) process.exit(1);
43673
- const files = await globby([fileGlob], {
43674
- absolute: true,
43675
- ignore: [
43676
- "**/node_modules/**",
43677
- "**/dist/**",
43678
- "**/build/**",
43679
- "**/.next/**"
43680
- ]
43681
- });
43682
- if (files.length === 0) process.exit(1);
43683
- const transformFn = await loadTransform(transformName);
43684
- const apiForParser = (parser) => ({
43685
- jscodeshift: import_jscodeshift.default.withParser(parser),
43686
- j: import_jscodeshift.default.withParser(parser),
43687
- stats: () => {},
43688
- report: () => {}
43689
- });
43690
- let resolveDone;
43691
- const done = new Promise((r) => {
43692
- resolveDone = r;
43693
- });
43694
- const allResults = [];
43695
- for await (const batch of chunked(files, concurrency)) (await Promise.allSettled(batch.map((filePath) => processFile(filePath, transformFn, apiForParser, dryRun)))).values().forEach((result) => {
43696
- if (result.status === "fulfilled") allResults.push(result.value);
43697
- else allResults.push({
43698
- filePath: "(unknown)",
43699
- changed: false,
43700
- error: result.reason
43740
+ /**
43741
+ * Run the codemod CLI. Resolves to the process exit code; writes only to `io`.
43742
+ */
43743
+ async function run(argv, io, deps = {}) {
43744
+ const out = (s) => void io.stdout.write(`${s}\n`);
43745
+ const err = (s) => void io.stderr.write(`${s}\n`);
43746
+ const fail = (s) => err(`${styleText("red", "error:", { stream: io.stderr })} ${s}`);
43747
+ try {
43748
+ const parsed = parse(argv);
43749
+ if (parsed.kind === "help") {
43750
+ out(usageText(io.stdout));
43751
+ return 0;
43752
+ }
43753
+ if (parsed.kind === "usage-error") {
43754
+ if (parsed.message !== void 0) fail(parsed.message);
43755
+ err(usageText(io.stderr));
43756
+ return parsed.strict ? 2 : 0;
43757
+ }
43758
+ const { transformName, fileGlob, dryRun, strict, concurrency, ignored } = parsed;
43759
+ for (const name of ignored) err(`warning: unknown option ${name} ignored (--strict makes this exit 2)`);
43760
+ if (!AVAILABLE_TRANSFORMS.has(transformName)) {
43761
+ fail(`unknown transform "${transformName}". Valid transforms: ${[...AVAILABLE_TRANSFORMS.keys()].join(", ")}`);
43762
+ return strict ? 2 : 1;
43763
+ }
43764
+ const files = await globby([fileGlob], {
43765
+ absolute: true,
43766
+ ignore: [
43767
+ "**/node_modules/**",
43768
+ "**/dist/**",
43769
+ "**/build/**",
43770
+ "**/.next/**"
43771
+ ]
43701
43772
  });
43702
- });
43703
- resolveDone(allResults);
43704
- const grouped = objectGroupBy(await done, (r) => {
43705
- if (r.error) return "errors";
43706
- if (r.changed) return "changed";
43707
- return "unchanged";
43708
- });
43709
- const changedFiles = grouped.changed ?? [];
43710
- const errorFiles = grouped.errors ?? [];
43711
- changedFiles.values().forEach((r) => {
43712
- r.filePath.replace(`${resolve(".")}/`, "");
43713
- });
43714
- if (errorFiles.length > 0) errorFiles.values().forEach((_r) => {});
43715
- if (dryRun && changedFiles.length > 0) {}
43773
+ if (files.length === 0) {
43774
+ fail(`no files matched "${fileGlob}"`);
43775
+ return 1;
43776
+ }
43777
+ const transformFn = await (deps.loadTransform ?? loadTransform)(transformName);
43778
+ const apiForParser = (parser) => ({
43779
+ jscodeshift: import_jscodeshift.default.withParser(parser),
43780
+ j: import_jscodeshift.default.withParser(parser),
43781
+ stats: () => {},
43782
+ report: () => {}
43783
+ });
43784
+ const results = [];
43785
+ for await (const batch of chunked(files, concurrency)) results.push(...await Promise.all(batch.map((filePath) => processFile(filePath, transformFn, apiForParser, dryRun))));
43786
+ const rel = (p) => relative(process.cwd(), p).replaceAll("\\", "/");
43787
+ let changed = 0;
43788
+ let errors = 0;
43789
+ for (const r of results) if (r.error) {
43790
+ errors++;
43791
+ err(`${rel(r.filePath)}: ${r.error.message}`);
43792
+ } else if (r.changed) {
43793
+ changed++;
43794
+ out(`${styleText("green", dryRun ? "would change" : "changed", { stream: io.stdout })} ${rel(r.filePath)}`);
43795
+ }
43796
+ const unchanged = results.length - changed - errors;
43797
+ out(`${changed} changed, ${unchanged} unchanged, ${errors} errors${dryRun ? " (dry run, nothing written)" : ""}`);
43798
+ return strict && errors > 0 ? 1 : 0;
43799
+ } catch (e) {
43800
+ fail(e instanceof Error ? e.message : String(e));
43801
+ return 1;
43802
+ }
43716
43803
  }
43717
- main().catch((_err) => {
43718
- process.exit(1);
43719
- });
43720
- export {};
43804
+ if (import.meta.main) process.exitCode = await run(process.argv.slice(2), process);
43805
+ export { run };
@@ -14,7 +14,7 @@ const ATTR_MAP = /* @__PURE__ */ new Map([
14
14
  const CSS_VAR_MAP = /* @__PURE__ */ new Map([["--cmdk-list-height", "--command-list-height"]]);
15
15
  /**
16
16
  * Replace all cmdk attribute selectors (bracketed) and CSS vars in a string.
17
- * Uses ES2026 Set.union to combine both maps into a single pass.
17
+ * Runs replaceAll for each ATTR_MAP entry (bracketed selectors), then for each CSS_VAR_MAP entry.
18
18
  */
19
19
  function replaceInString(input) {
20
20
  let result = input;
@@ -2,7 +2,7 @@
2
2
  interface SearchResult {
3
3
  readonly id: ItemId;
4
4
  readonly score: number;
5
- /** Character ranges that matched (for highlighting) — [start, end] tuples */
5
+ /** Character ranges that matched (for highlighting) — half-open [start, end) tuples, end exclusive */
6
6
  readonly matches: ReadonlyArray<readonly [start: number, end: number]>;
7
7
  }
8
8
  /** A scoring function that evaluates a single item against a query */
@@ -13,7 +13,7 @@ interface SearchEngine extends Disposable {
13
13
  index(items: readonly CommandItem[]): void;
14
14
  /** Search items by query, return ordered results — uses Iterator pipeline */
15
15
  search(query: string, items: readonly CommandItem[]): IteratorObject<SearchResult>;
16
- /** Remove items from index — uses Set.difference for efficient bulk removal */
16
+ /** Remove items from index by id */
17
17
  remove(ids: ReadonlySet<ItemId>): void;
18
18
  /** Clear the entire index */
19
19
  clear(): void;
@@ -162,7 +162,7 @@ interface FrecencyStorage extends Disposable {
162
162
  load(namespace: string): FrecencyData | Promise<FrecencyData>;
163
163
  save(namespace: string, data: FrecencyData): void | Promise<void>;
164
164
  }
165
- /** Frecency exponential decay bucket configuration */
165
+ /** Frecency step-weight configuration per recency bucket (hour/day/week/month/older) */
166
166
  interface FrecencyDecayConfig {
167
167
  readonly hourWeight?: number | undefined;
168
168
  readonly dayWeight?: number | undefined;
@@ -179,7 +179,7 @@ interface FrecencyOptions {
179
179
  }
180
180
  /** Default frecency decay configuration */
181
181
  export declare const DEFAULT_FRECENCY_DECAY: Required<FrecencyDecayConfig>;
182
- /** Options for creating a command machine — const type param for narrowed option inference */
182
+ /** Options for creating a command machine */
183
183
  interface CommandMachineOptions {
184
184
  /** Pre-registered items to populate on creation */
185
185
  readonly items?: readonly CommandItem[] | undefined;
@@ -205,7 +205,7 @@ interface CommandMachineOptions {
205
205
  readonly onSearchChange?: ((query: string) => void) | undefined;
206
206
  /** Whether keyboard navigation loops from last to first item (default: true) */
207
207
  readonly loop?: boolean | undefined;
208
- /** Item count threshold for automatic virtualization (default: 100) */
208
+ /** Accepted but not read yet: Command.List uses fixed thresholds (on above 100 matches, off at 50 or fewer) (default: 100) */
209
209
  readonly virtualizeThreshold?: number | undefined;
210
210
  }
211
211
  /** Default machine options */
@@ -213,7 +213,7 @@ export declare const DEFAULT_MACHINE_OPTIONS: Partial<CommandMachineOptions>;
213
213
  /** Initial state factory */
214
214
  export declare function createInitialState(options?: CommandMachineOptions): CommandState;
215
215
  /**
216
- * IndexedDB-backed frecency storage using idb-keyval 6.2.2.
216
+ * IndexedDB-backed frecency storage using idb-keyval.
217
217
  *
218
218
  * Persists frecency data across browser sessions. Implements both
219
219
  * `Disposable` and `AsyncDisposable` for use with `using` and `await using`.
@@ -250,7 +250,7 @@ export declare class IdbFrecencyStorage implements FrecencyStorage, AsyncDisposa
250
250
  /**
251
251
  * Computes a frecency bonus for an item based on usage frequency and recency.
252
252
  * Uses hour/day/week/month bucket boundaries with
253
- * configurable exponential decay weights per time bucket.
253
+ * configurable step weights per recency bucket (hour/day/week/month/older).
254
254
  */
255
255
  export declare function computeFrecencyBonus(history: FrecencyRecord, now?: number, config?: FrecencyDecayConfig): number;
256
256
  /**
@@ -290,7 +290,7 @@ export declare class MemoryFrecencyStorage implements FrecencyStorage {
290
290
  #private;
291
291
  load(namespace: string): FrecencyData;
292
292
  save(namespace: string, data: FrecencyData): void;
293
- /** Serialize all stored data — Iterator Helpers pipeline (ES2026) */
293
+ /** Serialize all stored data — Iterator Helpers pipeline (ES2025) */
294
294
  toJSON(): Record<string, {
295
295
  records: Array<[string, FrecencyRecord]>;
296
296
  }>;
@@ -340,7 +340,7 @@ interface ShortcutBinding {
340
340
  /**
341
341
  * Manages keyboard shortcut bindings with global keydown listening.
342
342
  * Supports `using` for automatic cleanup of both individual bindings and the
343
- * global document listener. Detects conflicts via Map.groupBy (ES2026).
343
+ * global document listener. Detects conflicts with the local mapGroupBy helper (core/utils/group-by.ts).
344
344
  */
345
345
  export declare class KeyboardShortcutRegistry implements Disposable {
346
346
  #private;
@@ -466,7 +466,7 @@ interface SearchEngineOptions {
466
466
  * Creates a search engine with pluggable scorer and incremental filtering.
467
467
  * When the query extends the previous one, only prior matches are re-scored.
468
468
  * Pre-caches lowercase at index time — zero toLowerCase() calls during search.
469
- * Uses Iterator Helpers (ES2026) for result pipelines and Set.difference for pruning.
469
+ * Uses Iterator Helpers (ES2025) for result pipelines.
470
470
  */
471
471
  export declare function createSearchEngine(options?: SearchEngineOptions): SearchEngine;
472
472
  interface CommandTelemetryHooks {