tonnage 0.1.2 → 0.1.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/CHANGELOG.md CHANGED
@@ -1,5 +1,11 @@
1
1
  # tonnage
2
2
 
3
+ ## 0.1.3
4
+
5
+ ### Patch Changes
6
+
7
+ - 9866ade: Upgrade comline, pass full runtime argv, add command and config-path completion with shell installation commands, and report ignored-option warnings on stderr while preserving asynchronous config loading.
8
+
3
9
  ## 0.1.2
4
10
 
5
11
  ### Patch Changes
package/README.md CHANGED
@@ -31,12 +31,43 @@ Run `tonnage write` during development to update the README. Run
31
31
  nonzero when the README is stale. Run `tonnage --help` to see both commands and
32
32
  their optional config-path arguments.
33
33
 
34
+ Pass a config path with `tonnage check path/to/tonnage.config.ts` or
35
+ `tonnage write path/to/tonnage.config.ts`. Otherwise, Tonnage looks in the current
36
+ directory for `tonnage.config.ts`, then `tonnage.config.mjs`, then
37
+ `tonnage.config.js`. Config modules may use top-level `await`. Missing configs
38
+ are errors. Use `--` before a config path that starts with a dash.
39
+
40
+ Unknown options are ignored with warnings on stderr. Warnings do not change the
41
+ exit status; `check` still exits nonzero when the report is stale.
42
+
34
43
  By default the tool reads `package.json`, writes `README.md`, and measures every
35
44
  public export except `./package.json`. Paths are resolved relative to the config
36
45
  file. Use `exports.include` or `exports.exclude` to select subpaths, recipe entry
37
46
  files to describe realistic runtime boundaries, and `external` for non-peer
38
47
  imports that the package intentionally leaves to its consumers.
39
48
 
49
+ ### Shell completion
50
+
51
+ With `tonnage` available on your shell's `PATH`, install completion for your shell:
52
+
53
+ ```sh
54
+ tonnage completion install bash
55
+ tonnage completion install zsh
56
+ tonnage completion install fish
57
+ tonnage completion install nushell
58
+ tonnage completion install carapace
59
+ ```
60
+
61
+ Choose the integration you use. Completion suggests commands, help options, and
62
+ config paths without loading your config or measuring bundles. Installation
63
+ checks the shell's prerequisites and writes to its completion directory without
64
+ editing shell profiles. It reports any setup needed for your shell. If Nushell
65
+ already uses Carapace, install only the Carapace integration.
66
+
67
+ Run `tonnage completion bash` (or another target above) to print the integration
68
+ file without installing it. The `completion` command and comline's internal
69
+ completion protocol commands are reserved for shell integration.
70
+
40
71
  ## Report layout
41
72
 
42
73
  Generated reports adapt to the measurements they contain. An exports-only or
package/dist/cli.mjs CHANGED
@@ -3,7 +3,7 @@ import { t as runTonnage } from "./run-CZ_FO4C7.mjs";
3
3
  import fs from "node:fs/promises";
4
4
  import path from "node:path";
5
5
  import { pathToFileURL } from "node:url";
6
- import { cli, help, helpOption, optional } from "comline";
6
+ import { cli, completionResponse, help, helpOption, logWarnings, optional } from "comline";
7
7
  //#region src/command-line.ts
8
8
  const ROOT_MANUAL = helpOption(`Show help for the tonnage command line.`);
9
9
  const WRITE_MANUAL = helpOption(`Update the configured README report.`);
@@ -22,20 +22,32 @@ const tonnageCli = cli({
22
22
  write: WRITE_MANUAL,
23
23
  "write/$configPath": WRITE_MANUAL
24
24
  },
25
+ positionalCompletions: {
26
+ "check/$configPath": { fileSystem: `files` },
27
+ "write/$configPath": { fileSystem: `files` }
28
+ },
25
29
  discoverConfigPath: () => void 0
26
30
  });
31
+ function completeTonnageCli(args) {
32
+ return completionResponse(tonnageCli.definition, args);
33
+ }
27
34
  function parseTonnageCli(args) {
28
- const { inputs } = tonnageCli(args);
29
- if (inputs.case === `` || inputs.opts.help) return { kind: `help` };
35
+ const { inputs, warnings } = tonnageCli(args);
36
+ if (inputs.case === `` || inputs.opts.help) return {
37
+ kind: `help`,
38
+ warnings
39
+ };
30
40
  const mode = inputs.case === `write` || inputs.case === `write/$configPath` ? `write` : `check`;
31
41
  const configArgument = inputs.path[1];
32
42
  return configArgument === void 0 ? {
33
43
  kind: `run`,
34
- mode
44
+ mode,
45
+ warnings
35
46
  } : {
36
47
  configArgument,
37
48
  kind: `run`,
38
- mode
49
+ mode,
50
+ warnings
39
51
  };
40
52
  }
41
53
  function renderTonnageCliHelp() {
@@ -49,7 +61,13 @@ const DEFAULT_CONFIG_FILES = [
49
61
  `tonnage.config.js`
50
62
  ];
51
63
  async function main() {
52
- const invocation = parseTonnageCli([`tonnage`, ...process.argv.slice(2)]);
64
+ const completion = await completeTonnageCli(process.argv);
65
+ if (completion !== void 0) {
66
+ process.stdout.write(completion);
67
+ return;
68
+ }
69
+ const invocation = parseTonnageCli(process.argv);
70
+ logWarnings(invocation.warnings);
53
71
  if (invocation.kind === `help`) {
54
72
  process.stdout.write(renderTonnageCliHelp());
55
73
  return;
package/dist/cli.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.mjs","names":[],"sources":["../src/command-line.ts","../src/cli.ts"],"sourcesContent":["import { cli, help, helpOption, optional } from \"comline\"\n\nimport type { TonnageMode } from \"./types.ts\"\n\nconst ROOT_MANUAL = helpOption(`Show help for the tonnage command line.`)\nconst WRITE_MANUAL = helpOption(`Update the configured README report.`)\nconst CHECK_MANUAL = helpOption(\n\t`Check that the configured README report is up to date.`,\n)\n\nconst tonnageCli = cli({\n\tcliName: `tonnage`,\n\tcliDescription: `Keep deterministic bundle size reports in README files and CI.`,\n\troutes: optional({\n\t\tcheck: optional({ $configPath: null }),\n\t\twrite: optional({ $configPath: null }),\n\t}),\n\trouteOptions: {\n\t\t\"\": ROOT_MANUAL,\n\t\tcheck: CHECK_MANUAL,\n\t\t\"check/$configPath\": CHECK_MANUAL,\n\t\twrite: WRITE_MANUAL,\n\t\t\"write/$configPath\": WRITE_MANUAL,\n\t},\n\tdiscoverConfigPath: () => undefined,\n})\n\nexport type TonnageCliInvocation =\n\t| { kind: `help` }\n\t| { configArgument?: string; kind: `run`; mode: TonnageMode }\n\nexport function parseTonnageCli(args: string[]): TonnageCliInvocation {\n\tconst { inputs } = tonnageCli(args)\n\n\tif (inputs.case === `` || inputs.opts.help) {\n\t\treturn { kind: `help` }\n\t}\n\n\tconst mode =\n\t\tinputs.case === `write` || inputs.case === `write/$configPath`\n\t\t\t? `write`\n\t\t\t: `check`\n\tconst configArgument = inputs.path[1]\n\n\treturn configArgument === undefined\n\t\t? { kind: `run`, mode }\n\t\t: { configArgument, kind: `run`, mode }\n}\n\nexport function renderTonnageCliHelp(): string {\n\treturn help(tonnageCli.definition)\n}\n","#!/usr/bin/env node\n\nimport fs from \"node:fs/promises\"\nimport path from \"node:path\"\nimport { pathToFileURL } from \"node:url\"\n\nimport { parseTonnageCli, renderTonnageCliHelp } from \"./command-line.ts\"\nimport { runTonnage } from \"./run.ts\"\nimport type { TonnageConfig } from \"./types.ts\"\n\nconst DEFAULT_CONFIG_FILES = [\n\t`tonnage.config.ts`,\n\t`tonnage.config.mjs`,\n\t`tonnage.config.js`,\n]\n\nasync function main(): Promise<void> {\n\tconst invocation = parseTonnageCli([`tonnage`, ...process.argv.slice(2)])\n\tif (invocation.kind === `help`) {\n\t\tprocess.stdout.write(renderTonnageCliHelp())\n\t\treturn\n\t}\n\n\tconst { configArgument, mode } = invocation\n\tconst configPath = await findConfig(configArgument)\n\tconst config = await loadConfig(configPath)\n\tconst result = await runTonnage(config, {\n\t\tconfigDirectory: path.dirname(configPath),\n\t\tmode,\n\t})\n\n\tif (mode === `check` && result.changed) {\n\t\tprocess.stderr.write(\n\t\t\t`${path.relative(process.cwd(), result.readmePath)} is out of date. Run tonnage write.\\n`,\n\t\t)\n\t\tprocess.exitCode = 1\n\t\treturn\n\t}\n\n\tconst readme = path.relative(process.cwd(), result.readmePath)\n\tprocess.stdout.write(\n\t\tresult.changed\n\t\t\t? `Updated ${readme}.\\n`\n\t\t\t: `${readme} is already up to date.\\n`,\n\t)\n}\n\nasync function findConfig(configArgument: string | undefined): Promise<string> {\n\tif (configArgument) {\n\t\treturn path.resolve(configArgument)\n\t}\n\n\tfor (const filename of DEFAULT_CONFIG_FILES) {\n\t\tconst candidate = path.resolve(filename)\n\t\ttry {\n\t\t\tawait fs.access(candidate)\n\t\t\treturn candidate\n\t\t} catch {\n\t\t\t// Keep looking for the next supported config filename.\n\t\t}\n\t}\n\n\tthrow new Error(\n\t\t`Could not find a tonnage config (${DEFAULT_CONFIG_FILES.join(`, `)}).`,\n\t)\n}\n\nasync function loadConfig(configPath: string): Promise<TonnageConfig> {\n\tconst imported = (await import(pathToFileURL(configPath).href)) as {\n\t\tdefault?: unknown\n\t}\n\tif (!imported.default || typeof imported.default !== `object`) {\n\t\tthrow new Error(`${configPath} must default-export a tonnage config.`)\n\t}\n\treturn imported.default\n}\n\nmain().catch((error: unknown) => {\n\tprocess.stderr.write(\n\t\t`${error instanceof Error ? error.message : String(error)}\\n`,\n\t)\n\tprocess.exitCode = 1\n})\n"],"mappings":";;;;;;;AAIA,MAAM,cAAc,WAAW,yCAAyC;AACxE,MAAM,eAAe,WAAW,sCAAsC;AACtE,MAAM,eAAe,WACpB,wDACD;AAEA,MAAM,aAAa,IAAI;CACtB,SAAS;CACT,gBAAgB;CAChB,QAAQ,SAAS;EAChB,OAAO,SAAS,EAAE,aAAa,KAAK,CAAC;EACrC,OAAO,SAAS,EAAE,aAAa,KAAK,CAAC;CACtC,CAAC;CACD,cAAc;EACb,IAAI;EACJ,OAAO;EACP,qBAAqB;EACrB,OAAO;EACP,qBAAqB;CACtB;CACA,0BAA0B,KAAA;AAC3B,CAAC;AAMD,SAAgB,gBAAgB,MAAsC;CACrE,MAAM,EAAE,WAAW,WAAW,IAAI;CAElC,IAAI,OAAO,SAAS,MAAM,OAAO,KAAK,MACrC,OAAO,EAAE,MAAM,OAAO;CAGvB,MAAM,OACL,OAAO,SAAS,WAAW,OAAO,SAAS,sBACxC,UACA;CACJ,MAAM,iBAAiB,OAAO,KAAK;CAEnC,OAAO,mBAAmB,KAAA,IACvB;EAAE,MAAM;EAAO;CAAK,IACpB;EAAE;EAAgB,MAAM;EAAO;CAAK;AACxC;AAEA,SAAgB,uBAA+B;CAC9C,OAAO,KAAK,WAAW,UAAU;AAClC;;;ACzCA,MAAM,uBAAuB;CAC5B;CACA;CACA;AACD;AAEA,eAAe,OAAsB;CACpC,MAAM,aAAa,gBAAgB,CAAC,WAAW,GAAG,QAAQ,KAAK,MAAM,CAAC,CAAC,CAAC;CACxE,IAAI,WAAW,SAAS,QAAQ;EAC/B,QAAQ,OAAO,MAAM,qBAAqB,CAAC;EAC3C;CACD;CAEA,MAAM,EAAE,gBAAgB,SAAS;CACjC,MAAM,aAAa,MAAM,WAAW,cAAc;CAClD,MAAM,SAAS,MAAM,WAAW,UAAU;CAC1C,MAAM,SAAS,MAAM,WAAW,QAAQ;EACvC,iBAAiB,KAAK,QAAQ,UAAU;EACxC;CACD,CAAC;CAED,IAAI,SAAS,WAAW,OAAO,SAAS;EACvC,QAAQ,OAAO,MACd,GAAG,KAAK,SAAS,QAAQ,IAAI,GAAG,OAAO,UAAU,EAAE,sCACpD;EACA,QAAQ,WAAW;EACnB;CACD;CAEA,MAAM,SAAS,KAAK,SAAS,QAAQ,IAAI,GAAG,OAAO,UAAU;CAC7D,QAAQ,OAAO,MACd,OAAO,UACJ,WAAW,OAAO,OAClB,GAAG,OAAO,0BACd;AACD;AAEA,eAAe,WAAW,gBAAqD;CAC9E,IAAI,gBACH,OAAO,KAAK,QAAQ,cAAc;CAGnC,KAAK,MAAM,YAAY,sBAAsB;EAC5C,MAAM,YAAY,KAAK,QAAQ,QAAQ;EACvC,IAAI;GACH,MAAM,GAAG,OAAO,SAAS;GACzB,OAAO;EACR,QAAQ,CAER;CACD;CAEA,MAAM,IAAI,MACT,oCAAoC,qBAAqB,KAAK,IAAI,EAAE,GACrE;AACD;AAEA,eAAe,WAAW,YAA4C;CACrE,MAAM,WAAY,MAAM,OAAO,cAAc,UAAU,CAAC,CAAC;CAGzD,IAAI,CAAC,SAAS,WAAW,OAAO,SAAS,YAAY,UACpD,MAAM,IAAI,MAAM,GAAG,WAAW,uCAAuC;CAEtE,OAAO,SAAS;AACjB;AAEA,KAAK,CAAC,CAAC,OAAO,UAAmB;CAChC,QAAQ,OAAO,MACd,GAAG,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK,EAAE,GAC3D;CACA,QAAQ,WAAW;AACpB,CAAC"}
1
+ {"version":3,"file":"cli.mjs","names":[],"sources":["../src/command-line.ts","../src/cli.ts"],"sourcesContent":["import {\n\ttype CliWarning,\n\tcli,\n\tcompletionResponse,\n\thelp,\n\thelpOption,\n\toptional,\n} from \"comline\"\n\nimport type { TonnageMode } from \"./types.ts\"\n\nconst ROOT_MANUAL = helpOption(`Show help for the tonnage command line.`)\nconst WRITE_MANUAL = helpOption(`Update the configured README report.`)\nconst CHECK_MANUAL = helpOption(\n\t`Check that the configured README report is up to date.`,\n)\n\nconst tonnageCli = cli({\n\tcliName: `tonnage`,\n\tcliDescription: `Keep deterministic bundle size reports in README files and CI.`,\n\troutes: optional({\n\t\tcheck: optional({ $configPath: null }),\n\t\twrite: optional({ $configPath: null }),\n\t}),\n\trouteOptions: {\n\t\t\"\": ROOT_MANUAL,\n\t\tcheck: CHECK_MANUAL,\n\t\t\"check/$configPath\": CHECK_MANUAL,\n\t\twrite: WRITE_MANUAL,\n\t\t\"write/$configPath\": WRITE_MANUAL,\n\t},\n\tpositionalCompletions: {\n\t\t\"check/$configPath\": { fileSystem: `files` },\n\t\t\"write/$configPath\": { fileSystem: `files` },\n\t},\n\tdiscoverConfigPath: () => undefined,\n})\n\nexport type TonnageCliInvocation = { warnings: CliWarning[] } & (\n\t| { kind: `help` }\n\t| { configArgument?: string; kind: `run`; mode: TonnageMode }\n)\n\nexport function completeTonnageCli(\n\targs: string[],\n): Promise<string | undefined> {\n\treturn completionResponse(tonnageCli.definition, args)\n}\n\nexport function parseTonnageCli(args: string[]): TonnageCliInvocation {\n\tconst { inputs, warnings } = tonnageCli(args)\n\n\tif (inputs.case === `` || inputs.opts.help) {\n\t\treturn { kind: `help`, warnings }\n\t}\n\n\tconst mode =\n\t\tinputs.case === `write` || inputs.case === `write/$configPath`\n\t\t\t? `write`\n\t\t\t: `check`\n\tconst configArgument = inputs.path[1]\n\n\treturn configArgument === undefined\n\t\t? { kind: `run`, mode, warnings }\n\t\t: { configArgument, kind: `run`, mode, warnings }\n}\n\nexport function renderTonnageCliHelp(): string {\n\treturn help(tonnageCli.definition)\n}\n","#!/usr/bin/env node\n\nimport fs from \"node:fs/promises\"\nimport path from \"node:path\"\nimport { pathToFileURL } from \"node:url\"\n\nimport { logWarnings } from \"comline\"\n\nimport {\n\tcompleteTonnageCli,\n\tparseTonnageCli,\n\trenderTonnageCliHelp,\n} from \"./command-line.ts\"\nimport { runTonnage } from \"./run.ts\"\nimport type { TonnageConfig } from \"./types.ts\"\n\nconst DEFAULT_CONFIG_FILES = [\n\t`tonnage.config.ts`,\n\t`tonnage.config.mjs`,\n\t`tonnage.config.js`,\n]\n\nasync function main(): Promise<void> {\n\tconst completion = await completeTonnageCli(process.argv)\n\tif (completion !== undefined) {\n\t\tprocess.stdout.write(completion)\n\t\treturn\n\t}\n\n\tconst invocation = parseTonnageCli(process.argv)\n\tlogWarnings(invocation.warnings)\n\tif (invocation.kind === `help`) {\n\t\tprocess.stdout.write(renderTonnageCliHelp())\n\t\treturn\n\t}\n\n\tconst { configArgument, mode } = invocation\n\tconst configPath = await findConfig(configArgument)\n\tconst config = await loadConfig(configPath)\n\tconst result = await runTonnage(config, {\n\t\tconfigDirectory: path.dirname(configPath),\n\t\tmode,\n\t})\n\n\tif (mode === `check` && result.changed) {\n\t\tprocess.stderr.write(\n\t\t\t`${path.relative(process.cwd(), result.readmePath)} is out of date. Run tonnage write.\\n`,\n\t\t)\n\t\tprocess.exitCode = 1\n\t\treturn\n\t}\n\n\tconst readme = path.relative(process.cwd(), result.readmePath)\n\tprocess.stdout.write(\n\t\tresult.changed\n\t\t\t? `Updated ${readme}.\\n`\n\t\t\t: `${readme} is already up to date.\\n`,\n\t)\n}\n\nasync function findConfig(configArgument: string | undefined): Promise<string> {\n\tif (configArgument) {\n\t\treturn path.resolve(configArgument)\n\t}\n\n\tfor (const filename of DEFAULT_CONFIG_FILES) {\n\t\tconst candidate = path.resolve(filename)\n\t\ttry {\n\t\t\tawait fs.access(candidate)\n\t\t\treturn candidate\n\t\t} catch {\n\t\t\t// Keep looking for the next supported config filename.\n\t\t}\n\t}\n\n\tthrow new Error(\n\t\t`Could not find a tonnage config (${DEFAULT_CONFIG_FILES.join(`, `)}).`,\n\t)\n}\n\nasync function loadConfig(configPath: string): Promise<TonnageConfig> {\n\tconst imported = (await import(pathToFileURL(configPath).href)) as {\n\t\tdefault?: unknown\n\t}\n\tif (!imported.default || typeof imported.default !== `object`) {\n\t\tthrow new Error(`${configPath} must default-export a tonnage config.`)\n\t}\n\treturn imported.default\n}\n\nmain().catch((error: unknown) => {\n\tprocess.stderr.write(\n\t\t`${error instanceof Error ? error.message : String(error)}\\n`,\n\t)\n\tprocess.exitCode = 1\n})\n"],"mappings":"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"}
package/dist/index.d.mts CHANGED
@@ -47,7 +47,7 @@ type TonnageRunResult = {
47
47
  };
48
48
  //#endregion
49
49
  //#region src/define-config.d.ts
50
- declare function defineConfig(config: TonnageConfig): TonnageConfig;
50
+ export declare function defineConfig(config: TonnageConfig): TonnageConfig;
51
51
  //#endregion
52
52
  //#region src/measure.d.ts
53
53
  type MeasureImportsOptions = {
@@ -57,25 +57,25 @@ type MeasureImportsOptions = {
57
57
  target?: string | undefined;
58
58
  };
59
59
  type MeasureEntryOptions = MeasureImportsOptions;
60
- declare function measureEntry(entry: string, options: MeasureEntryOptions): Promise<BundleMeasurement>;
61
- declare function measureImports(imports: readonly string[], options: MeasureImportsOptions): Promise<BundleMeasurement>;
60
+ export declare function measureEntry(entry: string, options: MeasureEntryOptions): Promise<BundleMeasurement>;
61
+ export declare function measureImports(imports: readonly string[], options: MeasureImportsOptions): Promise<BundleMeasurement>;
62
62
  //#endregion
63
63
  //#region src/readme.d.ts
64
- declare function tonnageMarkers(marker?: string): {
64
+ export declare function tonnageMarkers(marker?: string): {
65
65
  end: string;
66
66
  start: string;
67
67
  };
68
- declare function updateGeneratedSection(readme: string, markdown: string, marker?: string): string;
68
+ export declare function updateGeneratedSection(readme: string, markdown: string, marker?: string): string;
69
69
  //#endregion
70
70
  //#region src/report.d.ts
71
- declare function createTonnageReport(config: TonnageConfig, configDirectory: string): Promise<TonnageReport>;
72
- declare function renderTonnageMarkdown(report: TonnageReport, config?: TonnageConfig): string;
71
+ export declare function createTonnageReport(config: TonnageConfig, configDirectory: string): Promise<TonnageReport>;
72
+ export declare function renderTonnageMarkdown(report: TonnageReport, config?: TonnageConfig): string;
73
73
  //#endregion
74
74
  //#region src/run.d.ts
75
- declare function runTonnage(config: TonnageConfig, options: {
75
+ export declare function runTonnage(config: TonnageConfig, options: {
76
76
  configDirectory?: string;
77
77
  mode: TonnageMode;
78
78
  }): Promise<TonnageRunResult>;
79
79
  //#endregion
80
- export { type BundleMeasurement, type BundlePlatform, type MeasureEntryOptions, type MeasureImportsOptions, type TonnageConfig, type TonnageExports, type TonnageMode, type TonnageRecipe, type TonnageRecipeRow, type TonnageReport, type TonnageRow, type TonnageRunResult, createTonnageReport, defineConfig, measureEntry, measureImports, renderTonnageMarkdown, runTonnage, tonnageMarkers, updateGeneratedSection };
80
+ export type { BundleMeasurement, BundlePlatform, MeasureEntryOptions, MeasureImportsOptions, TonnageConfig, TonnageExports, TonnageMode, TonnageRecipe, TonnageRecipeRow, TonnageReport, TonnageRow, TonnageRunResult };
81
81
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/define-config.ts","../src/measure.ts","../src/readme.ts","../src/report.ts","../src/run.ts"],"mappings":";;KAAY;KAEA;EACX;EACA;;KAGW;EACX;EACA;EACA;EACA,WAAW;;KAGA;EACX,oBAAoB;EACpB;EACA;EACA;EACA;EACA,WAAW;EACX;EACA,mBAAmB;EACnB;;KAGW;EACX;EACA;;KAGW,aAAa;EACxB;EACA;;KAGW,mBAAmB;EAC9B;EACA;;KAGW;EACX,kBAAkB;EAClB;EACA,kBAAkB;;KAGP;KAEA;EACX;EACA;EACA,QAAQ;;;;iBClDO,aAAa,QAAQ,gBAAgB;;;KCKzC;EACX;EACA,WAAW;EACX;EACA;;KAGW,sBAAsB;iBAMZ,aACrB,eACA,SAAS,sBACP,QAAQ;iBAcW,eACrB,4BACA,SAAS,wBACP,QAAQ;;;iBCxCK,eAAe;EAC9B;EACA;;iBASe,uBACf,gBACA,kBACA;;;iBCOqB,oBACrB,QAAQ,eACR,0BACE,QAAQ;iBA+DK,sBACf,QAAQ,eACR,SAAQ;;;iBClFa,WACrB,QAAQ,eACR;EACC;EACA,MAAM;IAEL,QAAQ"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/define-config.ts","../src/measure.ts","../src/readme.ts","../src/report.ts","../src/run.ts"],"mappings":";;KAAY;KAEA;EACX;EACA;;KAGW;EACX;EACA;EACA;EACA,WAAW;;KAGA;EACX,oBAAoB;EACpB;EACA;EACA;EACA;EACA,WAAW;EACX;EACA,mBAAmB;EACnB;;KAGW;EACX;EACA;;KAGW,aAAa;EACxB;EACA;;KAGW,mBAAmB;EAC9B;EACA;;KAGW;EACX,kBAAkB;EAClB;EACA,kBAAkB;;KAGP;KAEA;EACX;EACA;EACA,QAAQ;;;;wBClDO,aAAa,QAAQ,gBAAgB;;;KCKzC;EACX;EACA,WAAW;EACX;EACA;;KAGW,sBAAsB;wBAMZ,aACrB,eACA,SAAS,sBACP,QAAQ;wBAcW,eACrB,4BACA,SAAS,wBACP,QAAQ;;;wBCxCK,eAAe;EAC9B;EACA;;wBASe,uBACf,gBACA,kBACA;;;wBCOqB,oBACrB,QAAQ,eACR,0BACE,QAAQ;wBA+DK,sBACf,QAAQ,eACR,SAAQ;;;wBClFa,WACrB,QAAQ,eACR;EACC;EACA,MAAM;IAEL,QAAQ"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tonnage",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "description": "Keep deterministic bundle size reports in README files and CI.",
5
5
  "type": "module",
6
6
  "license": "MPL-2.0",
@@ -37,11 +37,11 @@
37
37
  "main": "./dist/index.mjs",
38
38
  "types": "./dist/index.d.mts",
39
39
  "dependencies": {
40
- "comline": "0.5.2",
40
+ "comline": "0.7.0",
41
41
  "esbuild": "0.28.2"
42
42
  },
43
43
  "devDependencies": {
44
- "@types/node": "26.4.0",
44
+ "@types/node": "26.5.1",
45
45
  "vitest": "npm:@voidzero-dev/vite-plus-test@0.1.24"
46
46
  },
47
47
  "scripts": {
package/src/cli.ts CHANGED
@@ -4,7 +4,13 @@ import fs from "node:fs/promises"
4
4
  import path from "node:path"
5
5
  import { pathToFileURL } from "node:url"
6
6
 
7
- import { parseTonnageCli, renderTonnageCliHelp } from "./command-line.ts"
7
+ import { logWarnings } from "comline"
8
+
9
+ import {
10
+ completeTonnageCli,
11
+ parseTonnageCli,
12
+ renderTonnageCliHelp,
13
+ } from "./command-line.ts"
8
14
  import { runTonnage } from "./run.ts"
9
15
  import type { TonnageConfig } from "./types.ts"
10
16
 
@@ -15,7 +21,14 @@ const DEFAULT_CONFIG_FILES = [
15
21
  ]
16
22
 
17
23
  async function main(): Promise<void> {
18
- const invocation = parseTonnageCli([`tonnage`, ...process.argv.slice(2)])
24
+ const completion = await completeTonnageCli(process.argv)
25
+ if (completion !== undefined) {
26
+ process.stdout.write(completion)
27
+ return
28
+ }
29
+
30
+ const invocation = parseTonnageCli(process.argv)
31
+ logWarnings(invocation.warnings)
19
32
  if (invocation.kind === `help`) {
20
33
  process.stdout.write(renderTonnageCliHelp())
21
34
  return
@@ -1,4 +1,11 @@
1
- import { cli, help, helpOption, optional } from "comline"
1
+ import {
2
+ type CliWarning,
3
+ cli,
4
+ completionResponse,
5
+ help,
6
+ helpOption,
7
+ optional,
8
+ } from "comline"
2
9
 
3
10
  import type { TonnageMode } from "./types.ts"
4
11
 
@@ -22,18 +29,29 @@ const tonnageCli = cli({
22
29
  write: WRITE_MANUAL,
23
30
  "write/$configPath": WRITE_MANUAL,
24
31
  },
32
+ positionalCompletions: {
33
+ "check/$configPath": { fileSystem: `files` },
34
+ "write/$configPath": { fileSystem: `files` },
35
+ },
25
36
  discoverConfigPath: () => undefined,
26
37
  })
27
38
 
28
- export type TonnageCliInvocation =
39
+ export type TonnageCliInvocation = { warnings: CliWarning[] } & (
29
40
  | { kind: `help` }
30
41
  | { configArgument?: string; kind: `run`; mode: TonnageMode }
42
+ )
43
+
44
+ export function completeTonnageCli(
45
+ args: string[],
46
+ ): Promise<string | undefined> {
47
+ return completionResponse(tonnageCli.definition, args)
48
+ }
31
49
 
32
50
  export function parseTonnageCli(args: string[]): TonnageCliInvocation {
33
- const { inputs } = tonnageCli(args)
51
+ const { inputs, warnings } = tonnageCli(args)
34
52
 
35
53
  if (inputs.case === `` || inputs.opts.help) {
36
- return { kind: `help` }
54
+ return { kind: `help`, warnings }
37
55
  }
38
56
 
39
57
  const mode =
@@ -43,8 +61,8 @@ export function parseTonnageCli(args: string[]): TonnageCliInvocation {
43
61
  const configArgument = inputs.path[1]
44
62
 
45
63
  return configArgument === undefined
46
- ? { kind: `run`, mode }
47
- : { configArgument, kind: `run`, mode }
64
+ ? { kind: `run`, mode, warnings }
65
+ : { configArgument, kind: `run`, mode, warnings }
48
66
  }
49
67
 
50
68
  export function renderTonnageCliHelp(): string {